1+ 'use strict' ;
2+ require ( 'loadenv' ) ( ) ;
3+
4+ var async = require ( 'async' ) ;
5+ var request = require ( 'request' ) ;
6+ var fullUrl = 'http://' + process . env . TARGET_DOCK + ':4242' ;
7+ var redis = require ( 'models/redis' ) ;
8+ var Runnable = require ( 'runnable' ) ;
9+ var user = new Runnable ( 'localhost:80' ) ;
10+ var saveKey = 'migrateDock:' + process . env . TARGET_DOCK ;
11+ var MongoUser = require ( 'models/mongo/user' ) ;
12+ var Instance = require ( 'models/mongo/instance' ) ;
13+ var debug = require ( 'debug' ) ( 'script' ) ;
14+
15+ var mongoose = require ( 'mongoose' ) ;
16+ mongoose . connect ( process . env . MONGO ) ;
17+
18+ var ERRORS = [ ] ;
19+ // ensure env's
20+ [ 'MONGO' , 'MAVIS_HOST' , 'TARGET_DOCK' ] . forEach ( function ( item ) {
21+ if ( ! process . env [ item ] ) {
22+ console . error ( 'missing' , item ) ;
23+ process . exit ( 1 ) ;
24+ }
25+ } ) ;
26+
27+ function login ( cb ) {
28+ debug ( 'login' ) ;
29+ var thisUser = user . githubLogin ( 'f914c65e30f6519cfb4d10d0aa81e235dd9b3652' , function ( err ) {
30+ if ( err ) { return cb ( err ) ; }
31+ MongoUser . updateById ( thisUser . id ( ) , { $set : { permissionLevel : 5 } } , cb ) ;
32+ } ) ;
33+ }
34+
35+ // remove dock from mavis
36+ function removeFromMavis ( cb ) {
37+ debug ( 'removeFromMavis' ) ;
38+ request ( {
39+ method : 'DELETE' ,
40+ url : process . env . MAVIS_HOST + '/docks' ,
41+ qs : {
42+ host : fullUrl
43+ }
44+ } , function ( err , res ) {
45+ if ( err ) { return cb ( err ) ; }
46+ if ( res . statusCode !== 200 ) { return cb ( new Error ( 'mavis delete failed' ) ) ; }
47+ cb ( ) ;
48+ } ) ;
49+ }
50+
51+ // save list of running containers
52+ // docker ps
53+ // get context-version of containers and save in redis
54+ var thisList = { } ;
55+
56+ function saveList ( cb ) {
57+ debug ( 'saveList' ) ;
58+ Instance . find ( {
59+ 'container.dockerHost' : fullUrl ,
60+ 'container.inspect.State.Running' : true ,
61+ } , function ( err , instances ) {
62+ if ( err ) { return cb ( err ) ; }
63+ thisList = instances ;
64+ var multi = redis . multi ( ) ;
65+ multi . del ( saveKey ) ;
66+ instances . forEach ( function ( item ) {
67+ multi . lpush ( saveKey , item . shortHash ) ;
68+ } ) ;
69+ multi . exec ( cb ) ;
70+ } ) ;
71+ }
72+
73+ // stop all containers
74+ function stopAllContainers ( cb ) {
75+ debug ( 'stopAllContainers' ) ;
76+ async . eachLimit ( thisList , 10 , function ( instance , next ) {
77+ stopInstance ( instance . shortHash , next ) ;
78+ } , cb ) ;
79+ }
80+
81+ function stopInstance ( shortHash , cb ) {
82+ var Instance = user . fetchInstance ( shortHash , function ( err ) {
83+ if ( err ) {
84+ ERRORS . push ( {
85+ func : 'stopInstance:fetchInstance' ,
86+ err : err . message ,
87+ shortHash : shortHash
88+ } ) ;
89+ return cb ( ) ;
90+ }
91+ Instance . stop ( function ( err ) {
92+ if ( err ) {
93+ ERRORS . push ( {
94+ func : 'stopInstance:stop' ,
95+ err : err . message ,
96+ shortHash : shortHash
97+ } ) ;
98+ }
99+ cb ( ) ;
100+ } ) ;
101+ } ) ;
102+ }
103+
104+ function logErrs ( cb ) {
105+ console . log ( 'save errors' , ERRORS ) ;
106+ cb ( ) ;
107+ }
108+
109+ function saveAndKill ( cb ) {
110+ async . series ( [
111+ login ,
112+ removeFromMavis ,
113+ saveList ,
114+ stopAllContainers ,
115+ logErrs
116+ ] , cb ) ;
117+ }
118+
119+ ////////////////////////////////////////////////////
120+ // part 2 (seemless restart)
121+ ////////////////////////////////////////////////////
122+ var ctx = { numStarted : 0 } ;
123+ function getAllContainers ( cb ) {
124+ debug ( 'getAllContainers' ) ;
125+ redis . lrange ( saveKey , 0 , - 1 , cb ) ;
126+ }
127+
128+ function startAllContainers ( instances , cb ) {
129+ debug ( 'instances' ) ;
130+ ctx . retry = [ ] ;
131+ async . eachLimit ( instances , 10 , function ( shortHash , next ) {
132+ startInstance ( shortHash , next ) ;
133+ } , cb ) ;
134+ }
135+
136+ function startInstance ( shortHash , cb ) {
137+ var Instance = user . fetchInstance ( shortHash , function ( err ) {
138+ if ( err ) {
139+ ctx . retry . push ( shortHash ) ;
140+ ERRORS . push ( {
141+ func : 'startInstance:fetchInstance' ,
142+ err : err . message ,
143+ shortHash : shortHash
144+ } ) ;
145+ return cb ( ) ;
146+ }
147+ Instance . start ( function ( err ) {
148+ if ( err ) {
149+ ctx . retry . push ( shortHash ) ;
150+ ERRORS . push ( {
151+ func : 'startInstance:start' ,
152+ err : err . message ,
153+ shortHash : shortHash
154+ } ) ;
155+ } else {
156+ ctx . numStarted ++ ;
157+ }
158+ cb ( ) ;
159+ } ) ;
160+ } ) ;
161+ }
162+
163+ function retryStart ( cb ) {
164+ console . error ( 'old errors' , ERRORS ) ;
165+ ERRORS = [ ] ;
166+ startAllContainers ( ctx . retry , cb ) ;
167+ }
168+
169+ // put back into mavis
170+ function addToMavis ( cb ) {
171+ debug ( 'addToMavis' ) ;
172+ mavisRequst ( 'PUT' , { host : fullUrl } , function ( ) {
173+ mavisRequst ( 'POST' , { host : fullUrl , numContainer : ctx . numStarted } , cb ) ;
174+ } ) ;
175+ }
176+
177+ function mavisRequst ( type , data , cb ) {
178+ debug ( 'mavisRequst' , type , data ) ;
179+ request ( {
180+ method : type ,
181+ url : process . env . MAVIS_HOST + '/docks' ,
182+ qs : data
183+ } , function ( err , res ) {
184+ if ( err || res . statusCode !== 200 ) {
185+ ERRORS . push ( {
186+ func : 'addToMavis:PUT' ,
187+ err : err && err . message || res . statusCode
188+ } ) ;
189+ }
190+ cb ( ) ;
191+ } ) ;
192+ }
193+
194+ function restore ( cb ) {
195+ async . waterfall ( [
196+ getAllContainers ,
197+ startAllContainers ,
198+ retryStart ,
199+ addToMavis
200+ ] , cb ) ;
201+ }
202+
203+ ///////////////////////
204+ /// helpers
205+
206+ function waitForYes ( cb ) {
207+ console . log ( 'curl -sSL https://get.docker.com/ubuntu/ | sudo sh' ) ;
208+ console . log ( 'update docker now, type yes to contine' ) ;
209+ process . stdin . on ( 'data' , function read ( chunk ) {
210+ if ( ~ chunk . toString ( ) . indexOf ( 'yes' ) ) {
211+ process . stdin . removeListener ( 'data' , read ) ;
212+ cb ( ) ;
213+ } else {
214+ console . log ( 'must type yes to continue' ) ;
215+ }
216+ } ) ;
217+ }
218+
219+ function finish ( err ) {
220+ console . log ( 'DONE: err?' , err ) ;
221+ console . log ( 'all erros encounted' , ERRORS ) ;
222+ process . exit ( ) ;
223+ }
224+
225+ // program
226+ async . series ( [
227+ saveAndKill ,
228+ waitForYes ,
229+ restore
230+ ] , finish ) ;
0 commit comments