From 59d13f79d5cdb44b2e182292fa28cf1eccd01cac Mon Sep 17 00:00:00 2001 From: Stephen Zarkos Date: Mon, 28 Apr 2014 14:12:26 -0700 Subject: [PATCH 1/3] Add state handling to handler processing - Use /config/HandlerState to manage plugin state --- waagent | 76 ++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 62 insertions(+), 14 deletions(-) mode change 100755 => 100644 waagent diff --git a/waagent b/waagent old mode 100755 new mode 100644 index 8130287..8356144 --- a/waagent +++ b/waagent @@ -2639,6 +2639,7 @@ class ExtensionsConfig(object): previous_version = None version=p.getAttribute("version") name=p.getAttribute("name") + handler=name + '-' + version if p.getAttribute("isJson") != 'true': Error("Plugin " + name+" version: " +version+" is not a JSON Extension. Skipping.") continue @@ -2659,14 +2660,18 @@ class ExtensionsConfig(object): manifest = GetFileContents(mfile) p.setAttribute('manifestdata',manifest) if self.launchCommand(name,version,'disableCommand') == None : + self.SetHandlerState(handler, 'Enabled') Error('Unable to disable '+name) else : + self.SetHandlerState(handler, 'Installed') Log(name+' is disabled') # uninstall if needed if p.getAttribute("state") == 'uninstall': if self.launchCommand(name,version,'uninstallCommand') == None : + self.SetHandlerState(handler, 'Installed') Error('Unable to uninstall '+name) else : + self.SetHandlerState(handler, 'NotInstalled') Log(name+' uninstallCommand completed .') # remove the plugin Run('rm -rf ' + LibDir + '/' + name +'-'+ version + '*') @@ -2766,17 +2771,22 @@ class ExtensionsConfig(object): #create HandlerEnvironment.json handler_env='[{ "name": "'+name+'", "seqNo": "'+seqNo+'", "version": 1.0, "handlerEnvironment": { "logFolder": "/var/log", "configFolder": "' + root + '/config", "statusFolder": "' + root + '/status", "heartbeatFile": "'+ root + '/heartbeat.log"}}]' SetFileContents(root+'/HandlerEnvironment.json',handler_env) + self.SetHandlerState(handler, 'NotInstalled') + cmd = '' getcmd='installCommand' if plg_dir != None and version > plg_dir.rsplit('-')[-1]: - getcmd='updateCommand' - # disable the old plugin if it exists - if previous_version != None: - if self.launchCommand(name,previous_version,'disableCommand') == None : - Error('Unable to disable old plugin '+name+' version ' + previous_version) - else : - Log(name+' version ' + previous_version + ' is disabled') - + if (self.GetHandlerState(handler) != 'NotInstalled'): + getcmd='updateCommand' + # disable the old plugin if it exists + if previous_version != None: + if self.launchCommand(name,previous_version,'disableCommand') == None : + self.SetHandlerState(handler, 'Enabled') + Error('Unable to disable old plugin '+name+' version ' + previous_version) + else : + self.SetHandlerState(handler, 'Installed') + Log(name+' version ' + previous_version + ' is disabled') + if getcmd=='updateCommand': if self.launchCommand(name,version,getcmd,previous_version) == None : Error('Update failed for '+name+'-'+version) @@ -2784,13 +2794,17 @@ class ExtensionsConfig(object): Log('Update complete'+name+'-'+version) # if we updated - call unistall for the old plugin if self.launchCommand(name,previous_version,'uninstallCommand') == None : + self.SetHandlerState(handler, 'Installed') Error('Uninstall failed for '+name+'-'+previous_version) else : + self.SetHandlerState(handler, 'NotInstalled') Log('Uninstall complete'+ name +'-' + previous_version) - else : # run install + else : # run install if self.launchCommand(name,version,getcmd) == None : + self.SetHandlerState(handler, 'NotInstalled') Error('Installation failed for '+name+'-'+version) else : + self.SetHandlerState(handler, 'Installed') Log('Installation completed for '+name+'-'+version) #end if plg_dir == none or version > = prev # change incarnation of settings file so it knows how to name status... @@ -2826,10 +2840,21 @@ class ExtensionsConfig(object): SetFileContents(root +"/config/" + incarnation +".settings", config ) # state is still enable - if self.launchCommand(name,version,'enableCommand') == None : - Error('Enable failed for '+name+'-'+version) - else : - Log('Enable completed for '+name+'-'+version) + if (self.GetHandlerState(handler) == 'NotInstalled'): # run install first if true + if self.launchCommand(name,version,'installCommand') == None : + self.SetHandlerState(handler, 'NotInstalled') + Error('Installation failed for '+name+'-'+version) + else : + self.SetHandlerState(handler, 'Installed') + Log('Installation completed for '+name+'-'+version) + + if (self.GetHandlerState(handler) != 'NotInstalled'): + if self.launchCommand(name,version,'enableCommand') == None : + self.SetHandlerState(handler, 'Installed') + Error('Enable failed for '+name+'-'+version) + else : + self.SetHandlerState(handler, 'Enabled') + Log('Enable completed for '+name+'-'+version) # this plugin processing is complete Log('Processing completed for '+name+'-'+version) #end plugin processing loop @@ -3041,7 +3066,30 @@ class ExtensionsConfig(object): except: Error("Unable to create " + status_file) continue - + + def SetHandlerState(self, handler, state=''): + zip_dir=LibDir+"/" + handler + mfile=None + for root, dirs, files in os.walk(zip_dir): + for f in files: + if f in ('HandlerManifest.json'): + mfile=os.path.join(root,f) + if mfile != None: + break + if mfile == None : + Error('SetHandlerState(): HandlerManifest.json not found, cannot set HandlerState.') + return None + Log("SetHandlerState: "+handler+", "+state) + return SetFileContents(os.path.dirname(mfile)+'/config/HandlerState', state) + + def GetHandlerState(self, handler): + handlerState = GetFileContents(handler+'/config/HandlerState') + if (handlerState): + return handlerState.rstrip('\r\n') + else: + return None + + class HostingEnvironmentConfig(object): """ Parse Hosting enviromnet config and store in From 10d4d9c50a498c2b304fa407b4be3c1340207879 Mon Sep 17 00:00:00 2001 From: Stephen Zarkos Date: Mon, 28 Apr 2014 14:20:16 -0700 Subject: [PATCH 2/3] GetHandlerState: default to 'NotInstalled' - Return 'NotInstalled' rather than None if GetFileContents() returns None --- waagent | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waagent b/waagent index 8356144..5ceef51 100644 --- a/waagent +++ b/waagent @@ -3087,7 +3087,7 @@ class ExtensionsConfig(object): if (handlerState): return handlerState.rstrip('\r\n') else: - return None + return 'NotInstalled' class HostingEnvironmentConfig(object): From f1f78c896f252832aae3c23007a9c2e1c7ee1bce Mon Sep 17 00:00:00 2001 From: Stephen Zarkos Date: Mon, 28 Apr 2014 15:29:22 -0700 Subject: [PATCH 3/3] SLES12 fix for wickedd-dhcp4 - set dhcp_client_name correctly for SLES12 - temporarily turn off the wickedd-dhcp4 service to enable our DHCP client to obtain wire server endpoint address --- waagent | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/waagent b/waagent index 8130287..a6ce5ff 100755 --- a/waagent +++ b/waagent @@ -655,6 +655,8 @@ class SuSEDistro(AbstractDistro): self.requiredDeps += [ "/sbin/insserv" ] self.init_file=suse_init_file self.dhcp_client_name='dhcpcd' + if (DistInfo(fullname=1)[0] == 'SUSE Linux Enterprise Server') and (DistInfo()[1] >= '12'): + self.dhcp_client_name='wickedd-dhcp4' self.grubKernelBootOptionsFile = '/boot/grub/menu.lst' self.grubKernelBootOptionsLine = 'kernel' self.getpidcmd='pidof ' @@ -3886,6 +3888,8 @@ class Agent(Util): ifname=MyDistro.GetInterfaceName() Log("DoDhcpWork: Missing default route - adding broadcast route for DHCP.") Run("route add 255.255.255.255 dev " + ifname,chk_err=False) # We supress error logging on error. + if MyDistro.dhcp_client_name == 'wickedd-dhcp4': + Run("service " + MyDistro.dhcp_client_name + " stop",chk_err=False) sock.bind(("0.0.0.0", 68)) sock.sendto(sendData, ("", 67)) sock.settimeout(10) @@ -3913,6 +3917,8 @@ class Agent(Util): #We added this route - delete it Run("route del 255.255.255.255 dev " + ifname,chk_err=False) # We supress error logging on error. Log("DoDhcpWork: Removing broadcast route for DHCP.") + if MyDistro.dhcp_client_name == 'wickedd-dhcp4': + Run("service " + MyDistro.dhcp_client_name + " start",chk_err=False) return None def UpdateAndPublishHostName(self, name):