2014-08-01 12:52:46 +04:00
#!/usr/bin/python
2014-07-21 22:05:42 +04:00
#
# AbstractPatching is the base patching class of all the linux distros
#
# Copyright 2014 Microsoft Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import sys
import re
import json
2015-10-12 06:43:51 +03:00
import random
2014-07-21 22:05:42 +04:00
import shutil
import time
import datetime
2015-04-29 05:34:15 +03:00
import logging
2015-10-12 06:40:37 +03:00
import logging . handlers
2014-07-21 22:05:42 +04:00
from Utils . WAAgentUtil import waagent
2015-05-14 10:30:39 +03:00
from ConfigOptions import ConfigOptions
2014-07-21 22:05:42 +04:00
2015-05-29 11:51:52 +03:00
mfile = os . path . join ( os . getcwd ( ) , ' HandlerManifest.json ' )
with open ( mfile , ' r ' ) as f :
manifest = json . loads ( f . read ( ) ) [ 0 ]
Version = manifest [ ' version ' ]
2015-05-08 10:12:49 +03:00
StatusTest = {
" Scheduled " : {
" Idle " : None ,
" Healthy " : None
} ,
" Oneoff " : {
" Idle " : None ,
" Healthy " : None
}
}
try :
from scheduled . idleTest import is_vm_idle
StatusTest [ " Scheduled " ] [ " Idle " ] = is_vm_idle
except :
pass
try :
from oneoff . idleTest import is_vm_idle
StatusTest [ " Oneoff " ] [ " Idle " ] = is_vm_idle
except :
pass
2015-04-23 10:59:00 +03:00
try :
2015-05-08 10:12:49 +03:00
from scheduled . healthyTest import is_vm_healthy
StatusTest [ " Scheduled " ] [ " Healthy " ] = is_vm_healthy
2015-04-23 10:59:00 +03:00
except :
2015-05-08 10:12:49 +03:00
pass
try :
from oneoff . healthyTest import is_vm_healthy
StatusTest [ " Oneoff " ] [ " Healthy " ] = is_vm_healthy
except :
pass
2015-05-05 11:44:46 +03:00
2014-07-21 22:05:42 +04:00
class AbstractPatching ( object ) :
"""
AbstractPatching defines a skeleton neccesary for a concrete Patching class .
"""
def __init__ ( self , hutil ) :
2014-07-30 20:21:23 +04:00
self . hutil = hutil
2015-10-12 06:40:37 +03:00
self . syslogger = None
2014-07-30 20:21:23 +04:00
2014-07-21 22:05:42 +04:00
self . patched = [ ]
self . to_patch = [ ]
self . downloaded = [ ]
2015-10-12 06:43:51 +03:00
self . download_retry_queue = [ ]
2014-07-21 22:05:42 +04:00
2015-05-14 10:30:39 +03:00
# Patching Configuration
2014-07-30 20:21:23 +04:00
self . disabled = None
self . stop = None
self . reboot_after_patch = None
2015-05-14 10:30:39 +03:00
self . category = None
self . install_duration = None
self . oneoff = None
2014-09-10 16:52:22 +04:00
self . interval_of_weeks = None
2014-07-30 20:21:23 +04:00
self . day_of_week = None
self . start_time = None
self . download_time = None
2014-08-06 18:39:29 +04:00
self . download_duration = 3600
self . gap_between_stage = 60
2015-05-14 10:30:39 +03:00
self . current_configs = dict ( )
2014-07-30 20:21:23 +04:00
2015-05-14 10:30:39 +03:00
self . category_required = ConfigOptions . category [ " required " ]
self . category_all = ConfigOptions . category [ " all " ]
# Crontab Variables
2014-07-21 22:05:42 +04:00
self . crontab = ' /etc/crontab '
self . cron_restart_cmd = ' service cron restart '
self . cron_chkconfig_cmd = ' chkconfig cron on '
2015-05-14 10:30:39 +03:00
# Path Variables
2015-05-18 12:32:45 +03:00
self . cwd = os . getcwd ( )
2015-05-14 10:30:39 +03:00
self . package_downloaded_path = os . path . join ( self . cwd , ' package.downloaded ' )
self . package_patched_path = os . path . join ( self . cwd , ' package.patched ' )
self . stop_flag_path = os . path . join ( self . cwd , ' StopOSPatching ' )
self . history_scheduled = os . path . join ( self . cwd , ' scheduled/history ' )
self . scheduled_configs_file = os . path . join ( self . cwd , ' scheduled/configs ' )
2015-12-11 02:06:01 +03:00
self . dist_upgrade_list = None
self . dist_upgrade_list_key = ' distUpgradeList '
2016-01-21 23:00:02 +03:00
self . dist_upgrade_all = False
self . dist_upgrade_all_key = ' distUpgradeAll '
2014-09-11 14:42:36 +04:00
2015-04-13 10:13:20 +03:00
# Reboot Requirements
self . reboot_required = False
self . open_deleted_files_before = list ( )
self . open_deleted_files_after = list ( )
self . needs_restart = list ( )
2015-12-11 02:06:01 +03:00
def is_string_none_or_empty ( self , str ) :
if str is None or len ( str ) < 1 :
return True
return False
2014-07-21 22:05:42 +04:00
def parse_settings ( self , settings ) :
2015-05-14 10:30:39 +03:00
disabled = settings . get ( " disabled " )
2015-05-18 12:32:45 +03:00
if disabled is None or str ( disabled ) . lower ( ) not in ConfigOptions . disabled :
msg = " The value of parameter \" disabled \" is empty or invalid. Set it False by default. "
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . WARNING , msg )
2015-05-14 10:30:39 +03:00
self . disabled = False
else :
2015-05-18 12:32:45 +03:00
if str ( disabled ) . lower ( ) == " true " :
2015-05-14 10:30:39 +03:00
self . disabled = True
else :
self . disabled = False
self . current_configs [ " disabled " ] = str ( self . disabled )
2014-07-30 20:21:23 +04:00
if self . disabled :
2015-05-29 11:51:52 +03:00
msg = " The extension is disabled. "
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . WARNING , msg )
2014-07-30 20:21:23 +04:00
return
2014-07-30 12:25:32 +04:00
2015-05-14 10:30:39 +03:00
stop = settings . get ( " stop " )
2015-05-18 12:32:45 +03:00
if stop is None or str ( stop ) . lower ( ) not in ConfigOptions . stop :
msg = " The value of parameter \" stop \" is empty or invalid. Set it False by default. "
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . WARNING , msg )
2015-05-14 10:30:39 +03:00
self . stop = False
else :
2015-05-18 12:32:45 +03:00
if str ( stop ) . lower ( ) == ' true ' :
2015-05-14 10:30:39 +03:00
self . stop = True
else :
self . stop = False
self . current_configs [ " stop " ] = str ( self . stop )
2014-07-30 20:21:23 +04:00
2015-05-14 10:30:39 +03:00
reboot_after_patch = settings . get ( " rebootAfterPatch " )
if reboot_after_patch is None or reboot_after_patch . lower ( ) not in ConfigOptions . reboot_after_patch :
2015-05-18 12:32:45 +03:00
msg = " The value of parameter \" rebootAfterPatch \" is empty or invalid. Set it \" rebootifneed \" by default. "
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . WARNING , msg )
2015-05-14 10:30:39 +03:00
self . reboot_after_patch = ConfigOptions . reboot_after_patch [ 0 ]
2014-07-30 20:21:23 +04:00
else :
2015-05-14 10:30:39 +03:00
self . reboot_after_patch = reboot_after_patch . lower ( )
2015-05-05 11:44:46 +03:00
waagent . AddExtensionEvent ( name = self . hutil . get_name ( ) ,
2015-04-29 05:34:15 +03:00
op = waagent . WALAEventOperation . Enable ,
isSuccess = True ,
2015-05-29 11:51:52 +03:00
version = Version ,
message = " rebootAfterPatch= " + self . reboot_after_patch )
2015-05-14 10:30:39 +03:00
self . current_configs [ " rebootAfterPatch " ] = self . reboot_after_patch
category = settings . get ( ' category ' )
if category is None or category . lower ( ) not in ConfigOptions . category . values ( ) :
2015-05-18 12:32:45 +03:00
msg = " The value of parameter \" category \" is empty or invalid. Set it " + self . category_required + " by default. "
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . WARNING , msg )
2015-05-14 10:30:39 +03:00
self . category = self . category_required
else :
self . category = category . lower ( )
waagent . AddExtensionEvent ( name = self . hutil . get_name ( ) ,
op = waagent . WALAEventOperation . Enable ,
isSuccess = True ,
2015-05-29 11:51:52 +03:00
version = Version ,
message = " category= " + self . category )
2015-05-14 10:30:39 +03:00
self . current_configs [ " category " ] = self . category
2015-12-11 02:06:01 +03:00
self . dist_upgrade_list = settings . get ( self . dist_upgrade_list_key )
if not self . is_string_none_or_empty ( self . dist_upgrade_list ) :
self . current_configs [ self . dist_upgrade_list_key ] = self . dist_upgrade_list
2016-01-21 23:00:02 +03:00
dist_upgrade_all = settings . get ( self . dist_upgrade_all_key )
if dist_upgrade_all is None :
msg = " The value of parameter \" {0} \" is empty or invalid. Set it false by default. " . format ( self . dist_upgrade_all_key )
self . log_and_syslog ( logging . INFO , msg )
self . dist_upgrade_all = False
elif str ( dist_upgrade_all ) . lower ( ) == ' true ' :
self . dist_upgrade_all = True
else :
self . dist_upgrade_all = False
self . current_configs [ self . dist_upgrade_all_key ] = str ( self . dist_upgrade_all )
2015-12-11 02:06:01 +03:00
2015-05-14 10:30:39 +03:00
check_hrmin = re . compile ( r ' ^[0-9] { 1,2}:[0-9] { 1,2}$ ' )
install_duration = settings . get ( ' installDuration ' )
if install_duration is None or not re . match ( check_hrmin , install_duration ) :
2015-05-18 12:32:45 +03:00
msg = " The value of parameter \" installDuration \" is empty or invalid. Set it 1 hour by default. "
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . WARNING , msg )
2015-05-14 10:30:39 +03:00
self . install_duration = 3600
2015-05-18 12:32:45 +03:00
self . current_configs [ " installDuration " ] = " 01:00 "
2015-05-14 10:30:39 +03:00
else :
hr_min = install_duration . split ( ' : ' )
self . install_duration = int ( hr_min [ 0 ] ) * 3600 + int ( hr_min [ 1 ] ) * 60
2015-05-18 12:32:45 +03:00
self . current_configs [ " installDuration " ] = install_duration
2015-05-14 10:30:39 +03:00
if self . install_duration < = 300 :
2015-05-18 12:32:45 +03:00
msg = " The value of parameter \" installDuration \" is smaller than 5 minutes. The extension will not reserve 5 minutes for reboot. It is recommended to set \" installDuration \" more than 30 minutes. "
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . WARNING , msg )
2014-07-30 20:21:23 +04:00
else :
2015-05-14 10:30:39 +03:00
msg = " The extension will reserve 5 minutes for reboot. "
# 5 min for reboot
self . install_duration - = 300
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . INFO , msg )
2015-05-18 12:32:45 +03:00
# The parameter "downloadDuration" is not exposed to users. So there's no log.
download_duration = settings . get ( ' downloadDuration ' )
if download_duration is not None and re . match ( check_hrmin , download_duration ) :
hr_min = download_duration . split ( ' : ' )
self . download_duration = int ( hr_min [ 0 ] ) * 3600 + int ( hr_min [ 1 ] ) * 60
2015-05-14 10:30:39 +03:00
oneoff = settings . get ( ' oneoff ' )
2015-05-18 12:32:45 +03:00
if oneoff is None or str ( oneoff ) . lower ( ) not in ConfigOptions . oneoff :
msg = " The value of parameter \" oneoff \" is empty or invalid. Set it False by default. "
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . WARNING , msg )
2015-05-14 10:30:39 +03:00
self . oneoff = False
else :
2015-05-18 12:32:45 +03:00
if str ( oneoff ) . lower ( ) == " true " :
2015-05-14 10:30:39 +03:00
self . oneoff = True
msg = " The extension will run in one-off mode. "
else :
self . oneoff = False
msg = " The extension will run in scheduled task mode. "
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . INFO , msg )
2015-05-14 10:30:39 +03:00
self . current_configs [ " oneoff " ] = str ( self . oneoff )
if not self . oneoff :
start_time = settings . get ( ' startTime ' )
if start_time is None or not re . match ( check_hrmin , start_time ) :
2015-05-18 12:32:45 +03:00
msg = " The parameter \" startTime \" is empty or invalid. It defaults to 03:00. "
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . WARNING , msg )
2015-05-14 10:30:39 +03:00
start_time = " 03:00 "
2017-06-16 21:04:05 +03:00
try :
start_time_dt = datetime . datetime . strptime ( start_time , ' % H: % M ' )
self . start_time = datetime . time ( start_time_dt . hour , start_time_dt . minute )
except ValueError :
msg = " The parameter \" startTime \" is invalid. It defaults to 03:00. "
self . log_and_syslog ( logging . WARNING , msg )
self . start_time = datetime . time ( 3 )
download_time_dt = start_time_dt - datetime . timedelta ( seconds = self . download_duration )
self . download_time = datetime . time ( download_time_dt . hour , download_time_dt . minute )
2015-05-14 10:30:39 +03:00
self . current_configs [ " startTime " ] = start_time
2014-07-22 06:15:05 +04:00
2015-05-14 10:30:39 +03:00
day_of_week = settings . get ( " dayOfWeek " )
if day_of_week is None or day_of_week == " " :
2015-05-18 12:32:45 +03:00
msg = " The parameter \" dayOfWeek \" is empty. dayOfWeek defaults to Everyday. "
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . WARNING , msg )
2015-05-14 10:30:39 +03:00
day_of_week = " everyday "
self . day_of_week = ConfigOptions . day_of_week [ " everyday " ]
else :
for day in day_of_week . split ( ' | ' ) :
day = day . strip ( ) . lower ( )
if day not in ConfigOptions . day_of_week :
2015-05-18 12:32:45 +03:00
msg = " The parameter \" dayOfWeek \" is invalid. dayOfWeek defaults to Everyday. "
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . WARNING , msg )
2015-05-14 10:30:39 +03:00
day_of_week = " everyday "
break
if " everyday " in day_of_week :
self . day_of_week = ConfigOptions . day_of_week [ " everyday " ]
else :
self . day_of_week = [ ConfigOptions . day_of_week [ day . strip ( ) . lower ( ) ] for day in day_of_week . split ( ' | ' ) ]
2015-05-05 11:44:46 +03:00
waagent . AddExtensionEvent ( name = self . hutil . get_name ( ) ,
2015-04-29 05:34:15 +03:00
op = waagent . WALAEventOperation . Enable ,
isSuccess = True ,
2015-05-29 11:51:52 +03:00
version = Version ,
2015-05-05 11:44:46 +03:00
message = " dayOfWeek= " + day_of_week )
2015-05-14 10:30:39 +03:00
self . current_configs [ " dayOfWeek " ] = day_of_week
2014-07-30 20:21:23 +04:00
2014-09-10 16:52:22 +04:00
interval_of_weeks = settings . get ( ' intervalOfWeeks ' )
2015-05-14 10:30:39 +03:00
if interval_of_weeks is None or interval_of_weeks not in ConfigOptions . interval_of_weeks :
2015-05-18 12:32:45 +03:00
msg = " The parameter \" intervalOfWeeks \" is empty or invalid. intervalOfWeeks defaults to 1. "
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . WARNING , msg )
2014-09-10 16:52:22 +04:00
self . interval_of_weeks = ' 1 '
else :
self . interval_of_weeks = interval_of_weeks
2015-05-05 11:44:46 +03:00
waagent . AddExtensionEvent ( name = self . hutil . get_name ( ) ,
2015-04-29 05:34:15 +03:00
op = waagent . WALAEventOperation . Enable ,
isSuccess = True ,
2015-05-29 11:51:52 +03:00
version = Version ,
message = " intervalOfWeeks= " + self . interval_of_weeks )
2015-05-14 10:30:39 +03:00
self . current_configs [ " intervalOfWeeks " ] = self . interval_of_weeks
2014-09-10 16:52:22 +04:00
2015-05-18 12:32:45 +03:00
# Save the latest configuration for scheduled task to avoid one-off mode's affection
2015-05-14 10:30:39 +03:00
waagent . SetFileContents ( self . scheduled_configs_file , json . dumps ( self . current_configs ) )
2015-04-23 10:59:00 +03:00
2015-05-14 10:30:39 +03:00
msg = " Current Configuration: " + self . get_current_config ( )
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . INFO , msg )
2014-07-21 22:05:42 +04:00
2014-08-01 12:52:46 +04:00
def install ( self ) :
pass
def enable ( self ) :
if self . stop :
self . stop_download ( )
self . create_stop_flag ( )
return
self . delete_stop_flag ( )
2015-05-14 10:30:39 +03:00
if not self . disabled and self . oneoff :
2014-08-20 18:02:02 +04:00
script_file_path = os . path . realpath ( sys . argv [ 0 ] )
2014-08-25 06:37:45 +04:00
os . system ( ' ' . join ( [ ' python ' , script_file_path , ' -oneoff ' , ' >/dev/null 2>&1 & ' ] ) )
2014-08-01 12:52:46 +04:00
else :
2014-09-10 16:52:22 +04:00
waagent . SetFileContents ( self . history_scheduled , ' ' )
2014-08-01 12:52:46 +04:00
self . set_download_cron ( )
self . set_patch_cron ( )
self . restart_cron ( )
def disable ( self ) :
self . disabled = True
self . enable ( )
2014-07-30 22:12:29 +04:00
def stop_download ( self ) :
2014-07-24 20:30:53 +04:00
'''
2014-07-30 22:12:29 +04:00
kill the process of downloading and its subprocess .
return code :
2014-08-01 13:53:01 +04:00
100 - There are no downloading process to stop
0 - The downloading process is stopped
2014-07-24 20:30:53 +04:00
'''
2014-07-24 11:56:38 +04:00
script_file_path = os . path . realpath ( sys . argv [ 0 ] )
script_file = os . path . basename ( script_file_path )
retcode , output = waagent . RunGetOutput ( ' ps -ef | grep " ' + script_file + ' -download " | grep -v grep | grep -v sh | awk \' { print $2} \' ' )
if retcode > 0 :
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . ERROR , output )
2014-07-24 11:56:38 +04:00
if output != ' ' :
2014-07-24 20:30:53 +04:00
retcode , output2 = waagent . RunGetOutput ( " ps -ef | awk ' { if($3== " + output . strip ( ) + " ) { print $2}} ' " )
if retcode > 0 :
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . ERROR , output2 )
2014-07-24 20:30:53 +04:00
if output2 != ' ' :
2014-08-04 09:52:24 +04:00
waagent . Run ( ' kill -9 ' + output2 . strip ( ) )
waagent . Run ( ' kill -9 ' + output . strip ( ) )
2014-08-01 13:53:01 +04:00
return 0
return 100
2014-07-24 11:56:38 +04:00
2014-07-21 22:05:42 +04:00
def set_download_cron ( self ) :
script_file_path = os . path . realpath ( sys . argv [ 0 ] )
script_dir = os . path . dirname ( script_file_path )
script_file = os . path . basename ( script_file_path )
old_line_end = ' ' . join ( [ script_file , ' -download ' ] )
if self . disabled :
new_line = ' \n '
else :
2017-06-16 21:04:05 +03:00
if self . download_time > self . start_time :
dow = ' , ' . join ( [ str ( ( day - 1 ) % 7 ) for day in self . day_of_week ] )
else :
dow = ' , ' . join ( [ str ( day % 7 ) for day in self . day_of_week ] )
2014-07-21 22:05:42 +04:00
hr = str ( self . download_time . hour )
2014-07-30 12:25:32 +04:00
minute = str ( self . download_time . minute )
2014-09-10 16:52:22 +04:00
new_line = ' ' . join ( [ ' \n ' + minute , hr , ' * * ' , dow , ' root cd ' , script_dir , ' && python check.py ' , self . interval_of_weeks , ' && python ' , script_file , ' -download > /dev/null 2>&1 \n ' ] )
2014-07-21 22:05:42 +04:00
waagent . ReplaceFileContentsAtomic ( self . crontab , ' \n ' . join ( filter ( lambda a : a and ( old_line_end not in a ) , waagent . GetFileContents ( self . crontab ) . split ( ' \n ' ) ) ) + new_line )
def set_patch_cron ( self ) :
script_file_path = os . path . realpath ( sys . argv [ 0 ] )
script_dir = os . path . dirname ( script_file_path )
script_file = os . path . basename ( script_file_path )
old_line_end = ' ' . join ( [ script_file , ' -patch ' ] )
if self . disabled :
new_line = ' \n '
else :
2017-06-16 21:04:05 +03:00
start_time_dt = datetime . datetime ( 100 , 1 , 1 , self . start_time . hour , self . start_time . minute )
start_hr = str ( self . start_time . hour )
start_minute = str ( self . start_time . minute )
start_dow = ' , ' . join ( [ str ( day % 7 ) for day in self . day_of_week ] )
cleanup_time_dt = start_time_dt + datetime . timedelta ( minutes = 1 )
cleanup_hr = str ( cleanup_time_dt . hour )
cleanup_minute = str ( cleanup_time_dt . minute )
if start_time_dt . day < cleanup_time_dt . day :
cleanup_dow = ' , ' . join ( [ str ( ( day + 1 ) % 7 ) for day in self . day_of_week ] )
else :
cleanup_dow = ' , ' . join ( [ str ( day % 7 ) for day in self . day_of_week ] )
new_line = ' ' . join ( [ ' \n ' + start_minute , start_hr , ' * * ' , start_dow , ' root cd ' , script_dir , ' && python check.py ' , self . interval_of_weeks , ' && python ' , script_file , ' -patch >/dev/null 2>&1 \n ' ] )
new_line + = ' ' . join ( [ cleanup_minute , cleanup_hr , ' * * ' , cleanup_dow , ' root rm -f ' , self . stop_flag_path , ' \n ' ] )
2014-09-10 21:39:20 +04:00
waagent . ReplaceFileContentsAtomic ( self . crontab , " \n " . join ( filter ( lambda a : a and ( old_line_end not in a ) and ( self . stop_flag_path not in a ) , waagent . GetFileContents ( self . crontab ) . split ( ' \n ' ) ) ) + new_line )
2014-07-21 22:05:42 +04:00
def restart_cron ( self ) :
retcode , output = waagent . RunGetOutput ( self . cron_restart_cmd )
if retcode > 0 :
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . ERROR , output )
2014-07-21 22:05:42 +04:00
2014-08-01 12:52:46 +04:00
def download ( self ) :
2015-05-18 12:32:45 +03:00
# Read the latest configuration for scheduled task
2015-05-14 10:30:39 +03:00
settings = json . loads ( waagent . GetFileContents ( self . scheduled_configs_file ) )
self . parse_settings ( settings )
self . provide_vm_status_test ( StatusTest [ " Scheduled " ] )
if not self . check_vm_idle ( StatusTest [ " Scheduled " ] ) :
2015-05-08 10:12:49 +03:00
return
2015-04-23 10:59:00 +03:00
2014-08-01 12:52:46 +04:00
if self . exists_stop_flag ( ) :
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . INFO , " Downloading patches is stopped/canceled " )
2014-08-01 12:52:46 +04:00
return
2014-07-21 22:05:42 +04:00
2014-08-01 12:52:46 +04:00
waagent . SetFileContents ( self . package_downloaded_path , ' ' )
waagent . SetFileContents ( self . package_patched_path , ' ' )
2015-04-29 05:34:15 +03:00
start_download_time = time . time ( )
2014-08-01 12:52:46 +04:00
# Installing security patches is mandatory
self . _download ( self . category_required )
if self . category == self . category_all :
self . _download ( self . category_all )
2015-10-12 06:43:51 +03:00
self . retry_download ( )
2015-04-29 05:34:15 +03:00
end_download_time = time . time ( )
2015-05-05 11:44:46 +03:00
waagent . AddExtensionEvent ( name = self . hutil . get_name ( ) ,
2015-05-29 11:51:52 +03:00
op = waagent . WALAEventOperation . Download ,
2015-04-29 05:34:15 +03:00
isSuccess = True ,
2015-05-29 11:51:52 +03:00
version = Version ,
2015-05-05 11:44:46 +03:00
message = " " . join ( [ " Real downloading time is " , str ( round ( end_download_time - start_download_time , 3 ) ) , " s " ] ) )
2014-08-01 12:52:46 +04:00
def _download ( self , category ) :
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . INFO , " Start to check&download patches (Category: " + category + " ) " )
2014-08-01 13:53:01 +04:00
retcode , downloadlist = self . check ( category )
if retcode > 0 :
2015-05-14 10:30:39 +03:00
msg = " Failed to check valid upgrades "
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . ERROR , msg )
2015-05-14 10:30:39 +03:00
self . hutil . do_exit ( 1 , ' Enable ' , ' error ' , ' 0 ' , msg )
2015-04-13 10:13:20 +03:00
if ' walinuxagent ' in downloadlist :
downloadlist . remove ( ' walinuxagent ' )
2014-08-01 13:53:01 +04:00
if not downloadlist :
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . INFO , " No packages are available for update. " )
2014-08-01 13:53:01 +04:00
return
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . INFO , " There are " + str ( len ( downloadlist ) ) + " packages to upgrade. " )
self . log_and_syslog ( logging . INFO , " Download list: " + ' ' . join ( downloadlist ) )
2014-08-01 12:52:46 +04:00
for pkg_name in downloadlist :
if pkg_name in self . downloaded :
continue
retcode = self . download_package ( pkg_name )
if retcode != 0 :
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . ERROR , " Failed to download the package: " + pkg_name )
2015-10-12 06:43:51 +03:00
self . log_and_syslog ( logging . INFO , " Put {0} into a retry queue " . format ( pkg_name ) )
self . download_retry_queue . append ( ( pkg_name , category ) )
2014-08-01 12:52:46 +04:00
continue
self . downloaded . append ( pkg_name )
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . INFO , " Package " + pkg_name + " is downloaded. " )
2014-08-01 12:52:46 +04:00
waagent . AppendFileContents ( self . package_downloaded_path , pkg_name + ' ' + category + ' \n ' )
2015-10-12 06:43:51 +03:00
def retry_download ( self ) :
retry_count = 0
max_retry_count = 12
self . log_and_syslog ( logging . INFO , " Retry queue: {0} " . format (
" " . join ( [ pkg_name for pkg_name , category in self . download_retry_queue ] ) ) )
while self . download_retry_queue :
pkg_name , category = self . download_retry_queue [ 0 ]
self . download_retry_queue = self . download_retry_queue [ 1 : ]
retcode = self . download_package ( pkg_name )
if retcode == 0 :
self . downloaded . append ( pkg_name )
self . log_and_syslog ( logging . INFO , " Package " + pkg_name + " is downloaded. " )
waagent . AppendFileContents ( self . package_downloaded_path , pkg_name + ' ' + category + ' \n ' )
else :
self . log_and_syslog ( logging . ERROR , " Failed to download the package: " + pkg_name )
self . log_and_syslog ( logging . INFO , " Put {0} back into a retry queue " . format ( pkg_name ) )
self . download_retry_queue . append ( ( pkg_name , category ) )
retry_count = retry_count + 1
if retry_count > max_retry_count :
err_msg = ( " Failed to download after {0} retries, "
" retry queue: {1} " ) . format ( max_retry_count ,
" " . join ( [ pkg_name for pkg_name , category in self . download_retry_queue ] ) )
self . log_and_syslog ( logging . ERROR , err_msg )
waagent . AddExtensionEvent ( name = self . hutil . get_name ( ) ,
op = waagent . WALAEventOperation . Download ,
isSuccess = False ,
version = Version ,
message = err_msg )
break
k = retry_count if ( retry_count < 10 ) else 10
interval = int ( random . uniform ( 0 , 2 * * k ) )
self . log_and_syslog ( logging . INFO , ( " Sleep {0} s before "
" the next retry, current retry_count = {1} " ) . format ( interval , retry_count ) )
time . sleep ( interval )
2014-08-01 12:52:46 +04:00
def patch ( self ) :
2015-05-18 12:32:45 +03:00
# Read the latest configuration for scheduled task
2015-05-14 10:30:39 +03:00
settings = json . loads ( waagent . GetFileContents ( self . scheduled_configs_file ) )
self . parse_settings ( settings )
if not self . check_vm_idle ( StatusTest [ " Scheduled " ] ) :
2015-05-08 10:12:49 +03:00
return
2015-04-23 10:59:00 +03:00
2014-08-01 12:52:46 +04:00
if self . exists_stop_flag ( ) :
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . INFO , " Installing patches is stopped/canceled " )
2014-08-01 12:52:46 +04:00
self . delete_stop_flag ( )
2014-07-30 20:21:23 +04:00
return
2014-08-01 12:52:46 +04:00
2015-04-13 10:13:20 +03:00
# Record the scheduled time
2014-09-10 16:52:22 +04:00
waagent . AppendFileContents ( self . history_scheduled , time . strftime ( " % Y- % m- %d %a " , time . localtime ( ) ) + ' \n ' )
2015-04-13 10:13:20 +03:00
# Record the open deleted files before patching
self . open_deleted_files_before = self . check_open_deleted_files ( )
2014-09-10 16:52:22 +04:00
2014-08-01 12:52:46 +04:00
retcode = self . stop_download ( )
2014-08-01 13:53:01 +04:00
if retcode == 0 :
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . WARNING , " Download time exceeded. The pending package will be downloaded in the next cycle " )
2015-05-05 11:44:46 +03:00
waagent . AddExtensionEvent ( name = self . hutil . get_name ( ) ,
2015-05-29 11:51:52 +03:00
op = waagent . WALAEventOperation . Download ,
isSuccess = False ,
version = Version ,
2015-05-05 11:44:46 +03:00
message = " Downloading time out " )
2014-08-01 12:52:46 +04:00
global start_patch_time
start_patch_time = time . time ( )
2015-04-29 05:34:15 +03:00
pkg_failed = [ ]
is_time_out = [ False , False ]
2014-08-01 12:52:46 +04:00
patchlist = self . get_pkg_to_patch ( self . category_required )
2015-04-29 05:34:15 +03:00
is_time_out [ 0 ] , failed = self . _patch ( self . category_required , patchlist )
pkg_failed . extend ( failed )
2014-08-01 12:52:46 +04:00
if not self . exists_stop_flag ( ) :
2015-04-29 05:34:15 +03:00
if not is_time_out [ 0 ] :
patchlist = self . get_pkg_to_patch ( self . category_all )
if len ( patchlist ) == 0 :
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . INFO , " No packages are available for update. (Category: " + self . category_all + " ) " )
2015-04-29 05:34:15 +03:00
else :
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . INFO , " Going to sleep for " + str ( self . gap_between_stage ) + " s " )
2015-04-29 05:34:15 +03:00
time . sleep ( self . gap_between_stage )
is_time_out [ 1 ] , failed = self . _patch ( self . category_all , patchlist )
pkg_failed . extend ( failed )
2014-08-01 12:52:46 +04:00
else :
2015-05-18 12:32:45 +03:00
msg = " Installing patches (Category: " + self . category_all + " ) is stopped/canceled "
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . INFO , msg )
2015-04-29 05:34:15 +03:00
if is_time_out [ 0 ] or is_time_out [ 1 ] :
2015-05-18 12:32:45 +03:00
msg = " Patching time out "
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . WARNING , msg )
2015-05-05 11:44:46 +03:00
waagent . AddExtensionEvent ( name = self . hutil . get_name ( ) ,
2015-05-29 11:51:52 +03:00
op = " Patch " ,
isSuccess = False ,
version = Version ,
2015-05-18 12:32:45 +03:00
message = msg )
2014-08-01 12:52:46 +04:00
2015-04-13 10:13:20 +03:00
self . open_deleted_files_after = self . check_open_deleted_files ( )
2014-07-30 20:21:23 +04:00
self . delete_stop_flag ( )
2014-08-01 12:52:46 +04:00
#self.report()
2015-05-14 10:30:39 +03:00
if StatusTest [ " Scheduled " ] [ " Healthy " ] :
2015-05-29 11:51:52 +03:00
is_healthy = StatusTest [ " Scheduled " ] [ " Healthy " ] ( )
msg = " Checking the VM is healthy after patching: " + str ( is_healthy )
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . INFO , msg )
2015-05-29 11:51:52 +03:00
waagent . AddExtensionEvent ( name = self . hutil . get_name ( ) ,
op = " Check healthy " ,
isSuccess = is_healthy ,
version = Version ,
message = msg )
2015-02-27 08:16:41 +03:00
if self . patched is not None and len ( self . patched ) > 0 :
self . reboot_if_required ( )
2014-08-01 12:52:46 +04:00
def _patch ( self , category , patchlist ) :
if self . exists_stop_flag ( ) :
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . INFO , " Installing patches (Category: " + category + " ) is stopped/canceled " )
2015-05-18 12:32:45 +03:00
return False , list ( )
2014-08-01 13:53:01 +04:00
if not patchlist :
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . INFO , " No packages are available for update. " )
2015-05-18 12:32:45 +03:00
return False , list ( )
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . INFO , " Start to install " + str ( len ( patchlist ) ) + " patches (Category: " + category + " ) " )
self . log_and_syslog ( logging . INFO , " Patch list: " + ' ' . join ( patchlist ) )
2014-08-20 18:02:02 +04:00
pkg_failed = [ ]
2014-08-01 12:52:46 +04:00
for pkg_name in patchlist :
2015-04-13 10:13:20 +03:00
if pkg_name == ' walinuxagent ' :
continue
2014-08-01 12:52:46 +04:00
current_patch_time = time . time ( )
if current_patch_time - start_patch_time > self . install_duration :
2015-05-18 12:32:45 +03:00
msg = " Patching time exceeded. The pending package will be patched in the next cycle "
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . WARNING , msg )
2015-04-29 05:34:15 +03:00
return True , pkg_failed
2014-08-01 12:52:46 +04:00
retcode = self . patch_package ( pkg_name )
if retcode != 0 :
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . ERROR , " Failed to patch the package: " + pkg_name )
2014-08-20 18:02:02 +04:00
pkg_failed . append ( ' ' . join ( [ pkg_name , category ] ) )
2014-08-01 12:52:46 +04:00
continue
self . patched . append ( pkg_name )
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . INFO , " Package " + pkg_name + " is patched. " )
2014-08-01 12:52:46 +04:00
waagent . AppendFileContents ( self . package_patched_path , pkg_name + ' ' + category + ' \n ' )
2015-04-29 05:34:15 +03:00
return False , pkg_failed
2014-08-20 13:28:50 +04:00
2014-08-01 12:52:46 +04:00
def patch_one_off ( self ) :
"""
Called when startTime is empty string , which means a on - demand patch .
"""
2015-05-14 10:30:39 +03:00
self . provide_vm_status_test ( StatusTest [ " Oneoff " ] )
if not self . check_vm_idle ( StatusTest [ " Oneoff " ] ) :
2015-05-08 10:12:49 +03:00
return
2015-04-23 10:59:00 +03:00
2014-08-01 12:52:46 +04:00
global start_patch_time
start_patch_time = time . time ( )
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . INFO , " Going to patch one-off " )
2014-08-01 12:52:46 +04:00
waagent . SetFileContents ( self . package_downloaded_path , ' ' )
waagent . SetFileContents ( self . package_patched_path , ' ' )
2015-04-13 10:13:20 +03:00
# Record the open deleted files before patching
self . open_deleted_files_before = self . check_open_deleted_files ( )
2014-08-20 18:02:02 +04:00
pkg_failed = [ ]
2015-04-29 05:34:15 +03:00
is_time_out = [ False , False ]
2014-08-06 18:39:29 +04:00
retcode , patchlist_required = self . check ( self . category_required )
if retcode > 0 :
2015-05-14 10:30:39 +03:00
msg = " Failed to check valid upgrades "
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . ERROR , msg )
2015-05-14 10:30:39 +03:00
self . hutil . do_exit ( 1 , ' Enable ' , ' error ' , ' 0 ' , msg )
2014-08-06 18:39:29 +04:00
if not patchlist_required :
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . INFO , " No packages are available for update. (Category: " + self . category_required + " ) " )
2014-07-22 06:15:05 +04:00
else :
2015-04-29 05:34:15 +03:00
is_time_out [ 0 ] , failed = self . _patch ( self . category_required , patchlist_required )
pkg_failed . extend ( failed )
2014-08-06 18:39:29 +04:00
if self . category == self . category_all :
if not self . exists_stop_flag ( ) :
2015-04-29 05:34:15 +03:00
if not is_time_out [ 0 ] :
retcode , patchlist_other = self . check ( self . category_all )
if retcode > 0 :
2015-05-14 10:30:39 +03:00
msg = " Failed to check valid upgrades "
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . ERROR , msg )
2015-05-14 10:30:39 +03:00
self . hutil . do_exit ( 1 , ' Enable ' , ' error ' , ' 0 ' , msg )
2015-04-29 05:34:15 +03:00
patchlist_other = [ pkg for pkg in patchlist_other if pkg not in patchlist_required ]
if len ( patchlist_other ) == 0 :
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . INFO , " No packages are available for update. (Category: " + self . category_all + " ) " )
2015-04-29 05:34:15 +03:00
else :
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . INFO , " Going to sleep for " + str ( self . gap_between_stage ) + " s " )
2015-04-29 05:34:15 +03:00
time . sleep ( self . gap_between_stage )
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . INFO , " Going to patch one-off (Category: " + self . category_all + " ) " )
2015-04-29 05:34:15 +03:00
is_time_out [ 1 ] , failed = self . _patch ( self . category_all , patchlist_other )
pkg_failed . extend ( failed )
2014-08-06 18:39:29 +04:00
else :
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . INFO , " Installing patches (Category: " + self . category_all + " ) is stopped/canceled " )
2015-04-29 05:34:15 +03:00
if is_time_out [ 0 ] or is_time_out [ 1 ] :
2015-05-05 11:44:46 +03:00
waagent . AddExtensionEvent ( name = self . hutil . get_name ( ) ,
2015-05-29 11:51:52 +03:00
op = " Oneoff Patch " ,
isSuccess = False ,
version = Version ,
2015-05-05 11:44:46 +03:00
message = " Patching time out " )
2015-04-29 05:34:15 +03:00
2014-08-01 12:52:46 +04:00
shutil . copy2 ( self . package_patched_path , self . package_downloaded_path )
2014-08-20 18:02:02 +04:00
for pkg in pkg_failed :
waagent . AppendFileContents ( self . package_downloaded_path , pkg + ' \n ' )
2014-07-21 22:05:42 +04:00
2015-04-13 10:13:20 +03:00
self . open_deleted_files_after = self . check_open_deleted_files ( )
2014-08-01 12:52:46 +04:00
self . delete_stop_flag ( )
#self.report()
2015-05-14 10:30:39 +03:00
if StatusTest [ " Oneoff " ] [ " Healthy " ] :
2015-05-29 11:51:52 +03:00
is_healthy = StatusTest [ " Oneoff " ] [ " Healthy " ] ( )
msg = " Checking the VM is healthy after patching: " + str ( is_healthy )
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . INFO , msg )
2015-05-29 11:51:52 +03:00
waagent . AddExtensionEvent ( name = self . hutil . get_name ( ) ,
op = " Check healthy " ,
isSuccess = is_healthy ,
version = Version ,
message = msg )
2015-02-27 08:16:41 +03:00
if self . patched is not None and len ( self . patched ) > 0 :
self . reboot_if_required ( )
2014-08-01 12:52:46 +04:00
def reboot_if_required ( self ) :
2015-04-13 10:13:20 +03:00
self . check_reboot ( )
self . check_needs_restart ( )
msg = ' '
2015-05-18 12:32:45 +03:00
if self . reboot_after_patch == ' notrequired ' and self . reboot_required :
2015-04-13 10:13:20 +03:00
msg + = ' Pending Reboot '
if self . needs_restart :
msg + = ' : ' + ' ' . join ( self . needs_restart )
2015-05-05 11:44:46 +03:00
waagent . AddExtensionEvent ( name = self . hutil . get_name ( ) ,
2015-05-29 11:51:52 +03:00
op = " Reboot " ,
isSuccess = False ,
version = Version ,
2015-04-29 05:34:15 +03:00
message = " " . join ( [ self . reboot_after_patch , msg ,
2015-11-04 09:45:39 +03:00
str ( len ( self . needs_restart ) ) ,
2015-04-29 05:34:15 +03:00
" packages need to restart " ] ) )
2015-04-13 10:13:20 +03:00
self . hutil . do_exit ( 0 , ' Enable ' , ' success ' , ' 0 ' , msg )
2015-05-18 12:32:45 +03:00
if self . reboot_after_patch == ' required ' :
2015-04-13 10:13:20 +03:00
msg + = " System going to reboot(Required) "
2015-05-18 12:32:45 +03:00
elif self . reboot_after_patch == ' auto ' and self . reboot_required :
2015-04-13 10:13:20 +03:00
msg + = " System going to reboot(Auto) "
2015-05-18 12:32:45 +03:00
elif self . reboot_after_patch == ' rebootifneed ' :
2015-04-13 10:13:20 +03:00
if ( self . reboot_required or self . needs_restart ) :
msg + = " System going to reboot(RebootIfNeed) "
if msg :
if self . needs_restart :
msg + = ' : ' + ' ' . join ( self . needs_restart )
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . INFO , msg )
2015-05-05 11:44:46 +03:00
waagent . AddExtensionEvent ( name = self . hutil . get_name ( ) ,
2015-05-29 11:51:52 +03:00
op = " Reboot " ,
2015-04-29 05:34:15 +03:00
isSuccess = True ,
2015-05-29 11:51:52 +03:00
version = Version ,
2015-05-05 11:44:46 +03:00
message = " Reboot " )
2014-08-01 12:52:46 +04:00
retcode = waagent . Run ( ' reboot ' )
2014-08-05 11:13:56 +04:00
if retcode != 0 :
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . ERROR , " Failed to reboot " )
2015-05-05 11:44:46 +03:00
waagent . AddExtensionEvent ( name = self . hutil . get_name ( ) ,
2015-05-29 11:51:52 +03:00
op = " Reboot " ,
2015-04-29 05:34:15 +03:00
isSuccess = False ,
2015-05-29 11:51:52 +03:00
version = Version ,
2015-05-05 11:44:46 +03:00
message = " Failed to reboot " )
2015-04-29 05:34:15 +03:00
else :
2015-05-05 11:44:46 +03:00
waagent . AddExtensionEvent ( name = self . hutil . get_name ( ) ,
2015-05-29 11:51:52 +03:00
op = " Reboot " ,
isSuccess = False ,
version = Version ,
2015-05-05 11:44:46 +03:00
message = " Not reboot " )
2014-07-30 20:21:23 +04:00
2015-04-13 10:13:20 +03:00
def check_needs_restart ( self ) :
self . needs_restart . extend ( self . get_pkg_needs_restart ( ) )
patched_files = dict ( )
for pkg in self . get_pkg_patched ( ) :
cmd = ' ' . join ( [ self . pkg_query_cmd , pkg ] )
try :
retcode , output = waagent . RunGetOutput ( cmd )
patched_files [ os . path . basename ( pkg ) ] = [ filename for filename in output . split ( " \n " ) if os . path . isfile ( filename ) ]
except Exception :
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . ERROR , " Failed to " + cmd )
2015-04-13 10:13:20 +03:00
# for k,v in patched_files.items():
2015-10-12 06:40:37 +03:00
# self.log_and_syslog(logging.INFO, k + ": " + " ".join(v))
2015-04-13 10:13:20 +03:00
open_deleted_files = list ( )
for filename in self . open_deleted_files_after :
if filename not in self . open_deleted_files_before :
open_deleted_files . append ( filename )
2015-10-12 06:40:37 +03:00
# self.log_and_syslog(logging.INFO, "Open deleted files: " + " ".join(open_deleted_files))
2015-04-13 10:13:20 +03:00
for pkg , files in patched_files . items ( ) :
for filename in files :
realpath = os . path . realpath ( filename )
if realpath in open_deleted_files and pkg not in self . needs_restart :
self . needs_restart . append ( pkg )
2015-05-05 11:44:46 +03:00
msg = " Packages needs to restart: "
pkgs = " " . join ( self . needs_restart )
if pkgs :
msg + = pkgs
else :
msg = " There is no package which needs to restart "
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . INFO , msg )
2015-04-13 10:13:20 +03:00
def get_pkg_needs_restart ( self ) :
return [ ]
def check_open_deleted_files ( self ) :
ret = list ( )
retcode , output = waagent . RunGetOutput ( ' lsof | grep " DEL " ' )
if retcode == 0 :
for line in output . split ( ' \n ' ) :
if line :
filename = line . split ( ) [ - 1 ]
if filename not in ret :
ret . append ( filename )
return ret
2014-07-30 20:21:23 +04:00
def create_stop_flag ( self ) :
waagent . SetFileContents ( self . stop_flag_path , ' ' )
def delete_stop_flag ( self ) :
if self . exists_stop_flag ( ) :
os . remove ( self . stop_flag_path )
def exists_stop_flag ( self ) :
if os . path . isfile ( self . stop_flag_path ) :
return True
else :
return False
2014-08-01 12:52:46 +04:00
def get_pkg_to_patch ( self , category ) :
2014-08-25 06:37:45 +04:00
if not os . path . isfile ( self . package_downloaded_path ) :
2014-08-20 18:02:02 +04:00
return [ ]
2014-08-20 13:28:50 +04:00
pkg_to_patch = waagent . GetFileContents ( self . package_downloaded_path )
if not pkg_to_patch :
return [ ]
patchlist = [ line . split ( ) [ 0 ] for line in pkg_to_patch . split ( ' \n ' ) if line . endswith ( category ) ]
2015-05-18 12:32:45 +03:00
if patchlist is None :
return [ ]
2014-08-01 12:52:46 +04:00
return patchlist
2014-09-11 14:42:36 +04:00
2015-04-13 10:13:20 +03:00
def get_pkg_patched ( self ) :
if not os . path . isfile ( self . package_patched_path ) :
return [ ]
pkg_patched = waagent . GetFileContents ( self . package_patched_path )
if not pkg_patched :
return [ ]
patchedlist = [ line . split ( ) [ 0 ] for line in pkg_patched . split ( ' \n ' ) if line ]
return patchedlist
2014-09-11 14:42:36 +04:00
def get_current_config ( self ) :
2015-05-14 10:30:39 +03:00
current_configs = [ ]
for k , v in self . current_configs . items ( ) :
current_configs . append ( k + " = " + v )
return " , " . join ( current_configs )
2015-04-29 05:34:15 +03:00
2015-05-14 10:30:39 +03:00
def provide_vm_status_test ( self , status_test ) :
for status , provided in status_test . items ( ) :
2015-05-08 10:12:49 +03:00
if provided is None :
provided = " False "
level = logging . WARNING
else :
provided = " True "
level = logging . INFO
msg = " The VM %s test script is provided: %s " % ( status , provided )
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( level , msg )
2015-05-08 10:12:49 +03:00
waagent . AddExtensionEvent ( name = self . hutil . get_name ( ) ,
2015-05-29 11:51:52 +03:00
op = " provides %s test script " % ( status , ) ,
isSuccess = provided ,
version = Version ,
2015-05-08 10:12:49 +03:00
message = msg )
2015-05-05 11:44:46 +03:00
2015-05-14 10:30:39 +03:00
def check_vm_idle ( self , status_test ) :
2015-05-08 10:12:49 +03:00
is_idle = True
2015-05-14 10:30:39 +03:00
if status_test [ " Idle " ] :
is_idle = status_test [ " Idle " ] ( )
2015-05-08 10:12:49 +03:00
msg = " Checking the VM is idle: " + str ( is_idle )
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . INFO , msg )
2015-05-29 11:51:52 +03:00
waagent . AddExtensionEvent ( name = self . hutil . get_name ( ) ,
op = " Check idle " ,
isSuccess = is_idle ,
version = Version ,
message = msg )
2015-05-08 10:12:49 +03:00
if not is_idle :
2015-10-12 06:40:37 +03:00
self . log_and_syslog ( logging . WARNING , " Current Operation is skipped. " )
2015-05-08 10:12:49 +03:00
return is_idle
2015-10-12 06:40:37 +03:00
def log_and_syslog ( self , level , message ) :
if level == logging . INFO :
self . hutil . log ( message )
elif level == logging . WARNING :
self . hutil . log ( " " . join ( [ " Warning: " , message ] ) )
elif level == logging . ERROR :
self . hutil . error ( message )
if self . syslogger is None :
self . init_syslog ( )
self . syslog ( level , message )
def init_syslog ( self ) :
self . syslogger = logging . getLogger ( self . hutil . get_name ( ) )
self . syslogger . setLevel ( logging . INFO )
formatter = logging . Formatter ( ' %(name)s : %(levelname)s %(message)s ' )
try :
handler = logging . handlers . SysLogHandler ( address = ' /dev/log ' )
handler . setFormatter ( formatter )
self . syslogger . addHandler ( handler )
except :
self . syslogger = None
self . hutil . error ( " Syslog is not ready. " )
def syslog ( self , level , message ) :
if self . syslogger is None :
return
if level == logging . INFO :
self . syslogger . info ( message )
elif level == logging . WARNING :
self . syslogger . warning ( message )
elif level == logging . ERROR :
self . syslogger . error ( message )
2015-12-11 02:06:01 +03:00