@@ -45,7 +45,9 @@ def stop_container():
4545 )
4646
4747
48- def get_apps_to_be_migrated (registered_workers , in_flight_apps , worker_occupation ):
48+ def get_apps_to_be_migrated (
49+ planner_policy , registered_workers , in_flight_apps , worker_occupation
50+ ):
4951 """
5052 Helper method that, given the current worker occupation, works out all the
5153 apps that could be migrated if they checked for a migration opportunity
@@ -56,12 +58,17 @@ def get_apps_to_be_migrated(registered_workers, in_flight_apps, worker_occupatio
5658 worker_occupation_file_path = "/tmp/worker_occupation{}.csv" .format (file_suffix )
5759 with open (worker_occupation_file_path , "w" ) as fh :
5860 fh .write ("WorkerIp,Slots\n " )
59- for ip in worker_occupation :
60- total_slots = [w for w in registered_workers .hosts if w .ip == ip ][0 ].slots
61- for i in range (len (worker_occupation [ip ]), total_slots ):
62- worker_occupation [ip ].append ("-1" )
63-
64- fh .write ("{},{}\n " .format (ip , "," .join (worker_occupation [ip ])))
61+ try :
62+ for ip in worker_occupation :
63+ total_slots = [w for w in registered_workers .hosts if w .ip == ip ][
64+ 0
65+ ].slots
66+ for i in range (len (worker_occupation [ip ]), total_slots ):
67+ worker_occupation [ip ].append ("-1" )
68+
69+ fh .write ("{},{}\n " .format (ip , "," .join (worker_occupation [ip ])))
70+ except IndexError :
71+ return []
6572
6673 # Start container in the background
6774 docker_cmd = [
@@ -81,8 +88,8 @@ def get_apps_to_be_migrated(registered_workers, in_flight_apps, worker_occupatio
8188 docker_cmd = [
8289 "docker exec" ,
8390 get_ctr_name (),
84- "bash -c '/build/faasm/bin/is_app_migratable {} {}'" .format (
85- app .appId , worker_occupation_file_path
91+ "bash -c '/build/faasm/bin/is_app_migratable {} {} {} '" .format (
92+ planner_policy , app .appId , worker_occupation_file_path
8693 ),
8794 ]
8895 docker_cmd = " " .join (docker_cmd )
@@ -91,7 +98,7 @@ def get_apps_to_be_migrated(registered_workers, in_flight_apps, worker_occupatio
9198 # App can not be migrated
9299 continue
93100 elif out .returncode == 0 :
94- to_be_migrated_apps .append (app . appId )
101+ to_be_migrated_apps .append (app )
95102 else :
96103 # stop_container()
97104 # Survive downstream binary errors, but report a warning
@@ -111,7 +118,7 @@ def get_apps_to_be_migrated(registered_workers, in_flight_apps, worker_occupatio
111118orig_num_migrations = - 1
112119
113120
114- def print_planner_resources ():
121+ def print_planner_resources (policy ):
115122 """
116123 Helper method to visualise the state of the planner
117124 """
@@ -121,13 +128,19 @@ def color_text(color, text="X"):
121128 num1 = str (color )
122129 return f"\033 [38;5;{ num1 } m{ text } \033 [0;0m"
123130
124- def print_line (host_msg , worker_occupation ):
131+ def print_line (host_msg , worker_occupation , next_evicted_vm_ips = []):
132+ is_evicted = host_msg .ip in next_evicted_vm_ips
133+
125134 line = "{}\t " .format (host_msg .ip )
135+ if is_evicted :
136+ line = "{}\t " .format (color_text (1 , text = host_msg .ip ))
137+
126138 used_slots = host_msg .usedSlots
127139 occupation = (
128140 worker_occupation [host_msg .ip ] if host_msg .ip in worker_occupation else []
129141 )
130142 if used_slots != len (occupation ):
143+ # TODO: FIXME: this is a symptom of a problem!!
131144 print (
132145 "Expected {} used slots for host {} but got {}!" .format (
133146 used_slots ,
@@ -145,11 +158,25 @@ def print_line(host_msg, worker_occupation):
145158 line += " [ ]"
146159 print (line )
147160
161+ def get_app_color (app , policy ):
162+ user_id = 0
163+ try :
164+ user_id = app .subType
165+ except AttributeError :
166+ pass
167+
168+ # We only care about user ids if we are using the COMPACT (multi-tenant)
169+ # policy
170+ if policy != "compact" :
171+ return app .appId % 256
172+
173+ return (user_id * 10 ) % 256
174+
148175 def print_apps_legend (in_flight_apps ):
149176 num_apps_per_line = NUM_APPS_PER_LINE
150177 line = ""
151178 for i , app in enumerate (in_flight_apps .apps ):
152- app_color = app . appId % 256
179+ app_color = get_app_color ( app , policy )
153180 app_text = color_text (app_color , "App ID: {}" .format (app .appId ))
154181 if i == 0 :
155182 line = app_text
@@ -163,9 +190,24 @@ def print_apps_legend(in_flight_apps):
163190 def print_migration_opportunities (apps_to_be_migrated ):
164191 num_apps_per_line = NUM_APPS_PER_LINE
165192 line = ""
166- for i , app_id in enumerate (apps_to_be_migrated ):
167- app_color = app_id % 256
168- app_text = color_text (app_color , "App ID: {}" .format (app_id ))
193+ for i , app in enumerate (apps_to_be_migrated ):
194+ app_color = get_app_color (app , policy )
195+ app_text = color_text (app_color , "App ID: {}" .format (app .appId ))
196+ if i == 0 :
197+ line = app_text
198+ elif i % num_apps_per_line == 0 :
199+ print (line )
200+ line = app_text
201+ else :
202+ line += "\t {}" .format (app_text )
203+ print (line )
204+
205+ def print_frozen_apps (frozen_apps ):
206+ num_apps_per_line = NUM_APPS_PER_LINE
207+ line = ""
208+ for i , app in enumerate (frozen_apps ):
209+ app_color = get_app_color (app , policy )
210+ app_text = color_text (app_color , "App ID: {}" .format (app .appId ))
169211 if i == 0 :
170212 line = app_text
171213 elif i % num_apps_per_line == 0 :
@@ -178,6 +220,7 @@ def print_migration_opportunities(apps_to_be_migrated):
178220 header = "============== PLANNER RESOURCES ==============="
179221 divide = "------------------------------------------------"
180222 div_mg = "*********** MIGRATION OPPORTUNITIES ************"
223+ div_fa = "***************** FROZEN APPS ******************"
181224 div_al = "************* APP ID COLOR LEGEND **************"
182225 footer = "================================================"
183226
@@ -192,7 +235,7 @@ def print_migration_opportunities(apps_to_be_migrated):
192235 worker_occupation = {}
193236 worker_occupation_ids = {}
194237 for app in in_flight_apps .apps :
195- app_color = app . appId % 256
238+ app_color = get_app_color ( app , policy )
196239 for ip in app .hostIps :
197240 if ip not in worker_occupation :
198241 worker_occupation [ip ] = []
@@ -204,10 +247,14 @@ def print_migration_opportunities(apps_to_be_migrated):
204247 if orig_num_migrations < 0 :
205248 orig_num_migrations = in_flight_apps .numMigrations
206249
250+ # Work-out the forzen apps
251+ next_evicted_vm_ips = in_flight_apps .nextEvictedVmIps
252+ frozen_apps = [app for app in in_flight_apps .frozenApps ]
253+
207254 # Work out the existing migration opportunities
208255 registered_workers = get_available_hosts ()
209256 apps_to_be_migrated = get_apps_to_be_migrated (
210- registered_workers , in_flight_apps , worker_occupation_ids
257+ policy , registered_workers , in_flight_apps , worker_occupation_ids
211258 )
212259
213260 # -------------
@@ -217,7 +264,7 @@ def print_migration_opportunities(apps_to_be_migrated):
217264 print (header )
218265 # Print registered worker occupation
219266 for worker in registered_workers .hosts :
220- print_line (worker , worker_occupation )
267+ print_line (worker , worker_occupation , next_evicted_vm_ips )
221268
222269 # Print migration opportunities (if any)
223270 if len (apps_to_be_migrated ) > 0 :
@@ -226,6 +273,13 @@ def print_migration_opportunities(apps_to_be_migrated):
226273 print (divide )
227274 print_migration_opportunities (apps_to_be_migrated )
228275
276+ # Print frozen apps (if any)
277+ if len (frozen_apps ) > 0 :
278+ print (divide )
279+ print (div_fa )
280+ print (divide )
281+ print_frozen_apps (frozen_apps )
282+
229283 # Print app-to-color legend (if any)
230284 if len (in_flight_apps .apps ) > 0 :
231285 print (divide )
@@ -253,11 +307,11 @@ def signal_handler(sig, frame):
253307
254308
255309@task
256- def planner (ctx , poll_period_sec = 2 ):
310+ def planner (ctx , policy = "bin-pack" , poll_period_sec = 2 ):
257311 """
258312 Monitor the in-flight apps and host occupation in the planner
259313 """
260314 signal (SIGINT , signal_handler )
261315 while True :
262- print_planner_resources ()
316+ print_planner_resources (policy )
263317 sleep (poll_period_sec )
0 commit comments