15
15
from .exception import SonicRuntimeException
16
16
17
17
SYSLOG_IDENTIFIER = "sonic-installer"
18
+ LOG_ERR = logger .Logger .LOG_PRIORITY_ERROR
19
+ LOG_NOTICE = logger .Logger .LOG_PRIORITY_NOTICE
18
20
19
21
# Global Config object
20
22
_config = None
@@ -123,6 +125,15 @@ def get_docker_tag_name(image):
123
125
return tag
124
126
125
127
128
+ def echo_and_log (msg , priority = LOG_NOTICE , fg = None ):
129
+ if priority >= LOG_ERR :
130
+ # Print to stderr if priority is error
131
+ click .secho (msg , fg = fg , err = True )
132
+ else :
133
+ click .secho (msg , fg = fg )
134
+ log .log (priority , msg , False )
135
+
136
+
126
137
# Function which validates whether a given URL specifies an existent file
127
138
# on a reachable remote machine. Will abort the current operation if not
128
139
def validate_url_or_abort (url ):
@@ -135,12 +146,12 @@ def validate_url_or_abort(url):
135
146
response_code = None
136
147
137
148
if not response_code :
138
- click . echo ("Did not receive a response from remote machine. Aborting..." )
149
+ echo_and_log ("Did not receive a response from remote machine. Aborting..." , LOG_ERR )
139
150
raise click .Abort ()
140
151
else :
141
152
# Check for a 4xx response code which indicates a nonexistent URL
142
153
if response_code / 100 == 4 :
143
- click . echo ("Image file not found on remote machine. Aborting..." )
154
+ echo_and_log ("Image file not found on remote machine. Aborting..." , LOG_ERR )
144
155
raise click .Abort ()
145
156
146
157
@@ -207,6 +218,7 @@ def print_deprecation_warning(deprecated_cmd_or_subcmd, new_cmd_or_subcmd):
207
218
fg = "red" , err = True )
208
219
click .secho ("Please use '{}' instead" .format (new_cmd_or_subcmd ), fg = "red" , err = True )
209
220
221
+
210
222
def update_sonic_environment (click , binary_image_version ):
211
223
"""Prepare sonic environment variable using incoming image template file. If incoming image template does not exist
212
224
use current image template file.
@@ -248,8 +260,7 @@ def umount_next_image_fs(mount_point):
248
260
print (sonic_env , file = ef )
249
261
os .chmod (env_file , 0o644 )
250
262
except SonicRuntimeException as ex :
251
- click .secho ("Warning: SONiC environment variables are not supported for this image: {0}" .format (str (ex )),
252
- fg = "red" , err = True )
263
+ echo_and_log ("Warning: SONiC environment variables are not supported for this image: {0}" .format (str (ex )), LOG_ERR , fg = "red" )
253
264
if os .path .exists (env_file ):
254
265
os .remove (env_file )
255
266
os .rmdir (env_dir )
@@ -282,42 +293,42 @@ def install(url, force, skip_migration=False):
282
293
bootloader = get_bootloader ()
283
294
284
295
if url .startswith ('http://' ) or url .startswith ('https://' ):
285
- click . echo ('Downloading image...' )
296
+ echo_and_log ('Downloading image...' )
286
297
validate_url_or_abort (url )
287
298
try :
288
299
urlretrieve (url , bootloader .DEFAULT_IMAGE_PATH , reporthook )
289
300
click .echo ('' )
290
301
except Exception as e :
291
- click . echo ("Download error" , e )
302
+ echo_and_log ("Download error" , e )
292
303
raise click .Abort ()
293
304
image_path = bootloader .DEFAULT_IMAGE_PATH
294
305
else :
295
306
image_path = os .path .join ("./" , url )
296
307
297
308
binary_image_version = bootloader .get_binary_image_version (image_path )
298
309
if not binary_image_version :
299
- click . echo ("Image file does not exist or is not a valid SONiC image file" )
310
+ echo_and_log ("Image file does not exist or is not a valid SONiC image file" , LOG_ERR )
300
311
raise click .Abort ()
301
312
302
313
# Is this version already installed?
303
314
if binary_image_version in bootloader .get_installed_images ():
304
- click . echo ("Image {} is already installed. Setting it as default..." .format (binary_image_version ))
315
+ echo_and_log ("Image {} is already installed. Setting it as default..." .format (binary_image_version ))
305
316
if not bootloader .set_default_image (binary_image_version ):
306
- click . echo ('Error: Failed to set image as default' )
317
+ echo_and_log ('Error: Failed to set image as default' , LOG_ERR )
307
318
raise click .Abort ()
308
319
else :
309
320
# Verify that the binary image is of the same type as the running image
310
321
if not bootloader .verify_binary_image (image_path ) and not force :
311
- click . echo ("Image file '{}' is of a different type than running image.\n " .format (url ) +
322
+ echo_and_log ("Image file '{}' is of a different type than running image.\n " .format (url ) +
312
323
"If you are sure you want to install this image, use -f|--force.\n " +
313
- "Aborting..." )
324
+ "Aborting..." , LOG_ERR )
314
325
raise click .Abort ()
315
326
316
- click . echo ("Installing image {} and setting it as default..." .format (binary_image_version ))
327
+ echo_and_log ("Installing image {} and setting it as default..." .format (binary_image_version ))
317
328
bootloader .install_image (image_path )
318
329
# Take a backup of current configuration
319
330
if skip_migration :
320
- click . echo ("Skipping configuration migration as requested in the command option." )
331
+ echo_and_log ("Skipping configuration migration as requested in the command option." )
321
332
else :
322
333
run_command ('config-setup backup' )
323
334
@@ -326,7 +337,7 @@ def install(url, force, skip_migration=False):
326
337
# Finally, sync filesystem
327
338
run_command ("sync;sync;sync" )
328
339
run_command ("sleep 3" ) # wait 3 seconds after sync
329
- click . echo ('Done' )
340
+ echo_and_log ('Done' )
330
341
331
342
332
343
# List installed images
@@ -355,7 +366,7 @@ def set_default(image):
355
366
356
367
bootloader = get_bootloader ()
357
368
if image not in bootloader .get_installed_images ():
358
- click . echo ('Error: Image does not exist' )
369
+ echo_and_log ('Error: Image does not exist' , LOG_ERR )
359
370
raise click .Abort ()
360
371
bootloader .set_default_image (image )
361
372
@@ -371,7 +382,7 @@ def set_next_boot(image):
371
382
372
383
bootloader = get_bootloader ()
373
384
if image not in bootloader .get_installed_images ():
374
- click . echo ('Error: Image does not exist' )
385
+ echo_and_log ('Error: Image does not exist' , LOG_ERR )
375
386
sys .exit (1 )
376
387
bootloader .set_next_image (image )
377
388
@@ -387,10 +398,10 @@ def remove(image):
387
398
images = bootloader .get_installed_images ()
388
399
current = bootloader .get_current_image ()
389
400
if image not in images :
390
- click . echo ('Image does not exist' )
401
+ echo_and_log ('Image does not exist' , LOG_ERR )
391
402
sys .exit (1 )
392
403
if image == current :
393
- click . echo ('Cannot remove current image' )
404
+ echo_and_log ('Cannot remove current image' , LOG_ERR )
394
405
sys .exit (1 )
395
406
# TODO: check if image is next boot or default boot and fix these
396
407
bootloader .remove_image (image )
@@ -427,12 +438,12 @@ def cleanup():
427
438
image_removed = 0
428
439
for image in images :
429
440
if image != curimage and image != nextimage :
430
- click . echo ("Removing image %s" % image )
441
+ echo_and_log ("Removing image %s" % image )
431
442
bootloader .remove_image (image )
432
443
image_removed += 1
433
444
434
445
if image_removed == 0 :
435
- click . echo ("No image(s) to remove" )
446
+ echo_and_log ("No image(s) to remove" )
436
447
437
448
438
449
DOCKER_CONTAINER_LIST = [
@@ -474,12 +485,12 @@ def upgrade_docker(container_name, url, cleanup_image, skip_check, tag, warm):
474
485
475
486
DEFAULT_IMAGE_PATH = os .path .join ("/tmp/" , image_name )
476
487
if url .startswith ('http://' ) or url .startswith ('https://' ):
477
- click . echo ('Downloading image...' )
488
+ echo_and_log ('Downloading image...' )
478
489
validate_url_or_abort (url )
479
490
try :
480
491
urlretrieve (url , DEFAULT_IMAGE_PATH , reporthook )
481
492
except Exception as e :
482
- click . echo ("Download error" , e )
493
+ echo_and_log ("Download error: {}" . format ( e ), LOG_ERR )
483
494
raise click .Abort ()
484
495
image_path = DEFAULT_IMAGE_PATH
485
496
else :
@@ -488,7 +499,7 @@ def upgrade_docker(container_name, url, cleanup_image, skip_check, tag, warm):
488
499
# Verify that the local file exists and is a regular file
489
500
# TODO: Verify the file is a *proper Docker image file*
490
501
if not os .path .isfile (image_path ):
491
- click . echo ("Image file '{}' does not exist or is not a regular file. Aborting..." .format (image_path ))
502
+ echo_and_log ("Image file '{}' does not exist or is not a regular file. Aborting..." .format (image_path ), LOG_ERR )
492
503
raise click .Abort ()
493
504
494
505
warm_configured = False
@@ -525,7 +536,7 @@ def upgrade_docker(container_name, url, cleanup_image, skip_check, tag, warm):
525
536
(out , err ) = proc .communicate ()
526
537
if proc .returncode != 0 :
527
538
if not skip_check :
528
- click . echo ("Orchagent is not in clean state, RESTARTCHECK failed" )
539
+ echo_and_log ("Orchagent is not in clean state, RESTARTCHECK failed" , LOG_ERR )
529
540
# Restore orignal config before exit
530
541
if warm_configured is False and warm :
531
542
run_command ("config warm_restart disable %s" % container_name )
@@ -537,27 +548,27 @@ def upgrade_docker(container_name, url, cleanup_image, skip_check, tag, warm):
537
548
538
549
sys .exit (proc .returncode )
539
550
else :
540
- click . echo ("Orchagent is not in clean state, upgrading it anyway" )
551
+ echo_and_log ("Orchagent is not in clean state, upgrading it anyway" )
541
552
else :
542
- click . echo ("Orchagent is in clean state and frozen for warm upgrade" )
553
+ echo_and_log ("Orchagent is in clean state and frozen for warm upgrade" )
543
554
544
555
warm_app_names = ["orchagent" , "neighsyncd" ]
545
556
546
557
elif container_name == "bgp" :
547
558
# Kill bgpd to restart the bgp graceful restart procedure
548
- click . echo ("Stopping bgp ..." )
559
+ echo_and_log ("Stopping bgp ..." )
549
560
run_command ("docker exec -i bgp pkill -9 zebra" )
550
561
run_command ("docker exec -i bgp pkill -9 bgpd" )
551
562
warm_app_names = ["bgp" ]
552
- click . echo ("Stopped bgp ..." )
563
+ echo_and_log ("Stopped bgp ..." )
553
564
554
565
elif container_name == "teamd" :
555
- click . echo ("Stopping teamd ..." )
566
+ echo_and_log ("Stopping teamd ..." )
556
567
# Send USR1 signal to all teamd instances to stop them
557
568
# It will prepare teamd for warm-reboot
558
569
run_command ("docker exec -i teamd pkill -USR1 teamd > /dev/null" )
559
570
warm_app_names = ["teamsyncd" ]
560
- click . echo ("Stopped teamd ..." )
571
+ echo_and_log ("Stopped teamd ..." )
561
572
562
573
# clean app reconcilation state from last warm start if exists
563
574
for warm_app_name in warm_app_names :
@@ -602,8 +613,7 @@ def upgrade_docker(container_name, url, cleanup_image, skip_check, tag, warm):
602
613
log .log_notice ("%s reached %s state" % (warm_app_name , state ))
603
614
sys .stdout .write ("]\n \r " )
604
615
if state != exp_state :
605
- click .echo ("%s failed to reach %s state" % (warm_app_name , exp_state ))
606
- log .log_error ("%s failed to reach %s state" % (warm_app_name , exp_state ))
616
+ echo_and_log ("%s failed to reach %s state" % (warm_app_name , exp_state ), LOG_ERR )
607
617
else :
608
618
exp_state = "" # this is cold upgrade
609
619
@@ -613,9 +623,9 @@ def upgrade_docker(container_name, url, cleanup_image, skip_check, tag, warm):
613
623
run_command ("config warm_restart disable %s" % container_name )
614
624
615
625
if state == exp_state :
616
- click . echo ('Done' )
626
+ echo_and_log ('Done' )
617
627
else :
618
- click . echo ('Failed' )
628
+ echo_and_log ('Failed' , LOG_ERR )
619
629
sys .exit (1 )
620
630
621
631
@@ -635,7 +645,7 @@ def rollback_docker(container_name):
635
645
# All images id under the image name
636
646
image_id_all = get_container_image_id_all (image_name )
637
647
if len (image_id_all ) != 2 :
638
- click . echo ("Two images required, but there are '{}' images for '{}'. Aborting..." .format (len (image_id_all ), image_name ))
648
+ echo_and_log ("Two images required, but there are '{}' images for '{}'. Aborting..." .format (len (image_id_all ), image_name ), LOG_ERR )
639
649
raise click .Abort ()
640
650
641
651
image_latest = image_name + ":latest"
@@ -649,19 +659,19 @@ def rollback_docker(container_name):
649
659
# make previous image as latest
650
660
run_command ("docker tag %s:%s %s:latest" % (image_name , version_tag , image_name ))
651
661
if container_name == "swss" or container_name == "bgp" or container_name == "teamd" :
652
- click . echo ("Cold reboot is required to restore system state after '{}' rollback !!" .format (container_name ))
662
+ echo_and_log ("Cold reboot is required to restore system state after '{}' rollback !!" .format (container_name ), LOG_ERR )
653
663
else :
654
664
run_command ("systemctl restart %s" % container_name )
655
665
656
- click . echo ('Done' )
666
+ echo_and_log ('Done' )
657
667
658
668
# verify the next image
659
669
@sonic_installer .command ('verify-next-image' )
660
670
def verify_next_image ():
661
671
""" Verify the next image for reboot"""
662
672
bootloader = get_bootloader ()
663
673
if not bootloader .verify_next_image ():
664
- click . echo ('Image verification failed' )
674
+ echo_and_log ('Image verification failed' , LOG_ERR )
665
675
sys .exit (1 )
666
676
click .echo ('Image successfully verified' )
667
677
0 commit comments