diff --git a/azureguestagent/agent.py b/azureguestagent/agent.py index 4d7da14..cb8d23f 100644 --- a/azureguestagent/agent.py +++ b/azureguestagent/agent.py @@ -26,6 +26,7 @@ import traceback import threading import azureguestagent.logger as logger import azureguestagent.conf as conf +import azureguestagent.prot as prot from azureguestagent.osinfo import CurrOSInfo from azureguestagent.handler import CurrOSHandlerFactory from azureguestagent.utils.osutil import CurrOSUtil @@ -39,71 +40,64 @@ GuestAgentLongVersion = "{0}-{1}".format(GuestAgentName, GuestAgentVersion) GuestAgentAuthor='MS OSTC' GuestAgentUri='https://github.com/Azure/WALinuxAgent' -class Agent(object): - - def __init__(self, config): - self.config = config - - def run(self): - self.initialize() - self.start() - - def initialize(self): - os.chdir(CurrOSUtil.GetLibDir()) - self.savePid() - - scvmmHandler = CurrOSHandlerFactory.GetScvmmHandler() - if scvmmHandler.detectScvmmEnv(): - scvmmHandler.startScvmmAgent() - return - - dhcpHandler = CurrOSHandlerFactory.GetDhcpHandler() - dhcpHandler.waitForNetwork() - dhcpHandler.probe() - CurrOSUtil.SetWireServerEndpoint(dhcpHandler.getEndpoint()) - - self.protocol = proto.DetectDefaultProtocol() - - provisoned = os.path.join(CurrOSUtil.GetLibDir(), "provisioned") - if(not os.path.isfile(provisoned)): - provisionHandler = provision.ProvisionHandler(self.config, - self.protocol) - try: - provisionHandler.provision() - fileutil.SetFileContents(provisoned, "") - except Exception, e: - self.protocol.reportAgentStatus(GuestAgentVersion, - "NotReady", - "ProvisioningFailed") - raise e - - if self.config.getSwitch("ResourceDisk.Format", False): - rdHandler = CurrOSHandlerFactory.GetResourceDiskHandler() - rdHandler.startActivateResourceDisk(self.config) - - self.envmonitor = envmon.EnvMonitor(self.config, self.dhcpHandler) - #TODO Start load balancer - #Need to check whether this should be kept - - def start(self): - #Handle state change - while True: - #Handle extensions - extHandler = CurrOSHandlerFactory.GetExtensionHandler() - extHandler.process(self.protocol) - - #Report status - agentStatus = "Ready" - agentStatusDetail = "Guest Agent is running" - self.protocol.reportAgentStatus(GuestAgentVersion, - agentStatus, - agentStatusDetail) - time.sleep(25) +def Init(): + #Init config + configPath = CurrOSUtil.GetConfigurationPath() + conf.LoadConfiguration(configPath) - def savePid(self): - fileutil.SetFileContents(CurrOSUtil.GetAgentPidPath(), - str(os.getpid())) + #Init log + verbose = conf.GetSwitch("Logs.Verbose", False) + logger.LoggerInit('/var/log/waagent.log', '/dev/console', verbose=verbose) + + #Create lib dir + fileutil.CreateDir(CurrOSUtil.GetLibDir(), mode='0700') + os.chdir(CurrOSUtil.GetLibDir()) +def Run(): + fileutil.SetFileContents(CurrOSUtil.GetAgentPidPath(), + str(os.getpid())) + + scvmmHandler = CurrOSHandlerFactory.GetScvmmHandler() + if scvmmHandler.detectScvmmEnv(): + scvmmHandler.startScvmmAgent() + return + + dhcpHandler = CurrOSHandlerFactory.GetDhcpHandler() + dhcpHandler.probe() + + prot.DetectDefaultProtocol() + + provisionHandler = CurrOSHandlerFactory.getProvisionHandler() + provisionHandler.process() + + if conf.getSwitch("ResourceDisk.Format", False): + rdHandler = CurrOSHandlerFactory.GetResourceDiskHandler() + rdHandler.startActivateResourceDisk() + + envHandler = CurrOSHandlerFactory.GetEnvHandler() + envHandler.startMonitor() + + #TODO Start load balancer + #Need to check whether this should be kept + + protocol = prot.GetDefaultProtocol() + while True: + #Handle extensions + extHandler = CurrOSHandlerFactory.GetExtensionHandler() + extHandler.process() + + #Report status + agentStatus = "Ready" + agentStatusDetail = "Guest Agent is running" + protocol.reportAgentStatus(GuestAgentVersion, + agentStatus, + agentStatusDetail) + time.sleep(25) + +def Deprovision(force=False, deluser=False): + deprovisionHandler = CurrOSHandlerFactory.GetDeprovisionHandler() + deprovisionHandler.deprovision(force=force, deluser=deluser) + def ParseArgs(sysArgv): cmd = None force = False @@ -115,6 +109,8 @@ def ParseArgs(sysArgv): cmd = "deprovision" elif re.match("^([-/]*)daemon", a): cmd = "daemon" + elif re.match("^([-/]*)run", a): + cmd = "run" elif re.match("^([-/]*)version", a): cmd = "version" elif re.match("^([-/]*)serialconsole", a): @@ -134,31 +130,30 @@ def Version(): CurrOSInfo[0], CurrOSInfo[1]) def Usage(): - print ("usage: {0} [-verbose] [-force] " - "[-help|-deprovision[+user]|-version|-serialconsole|-daemon]") + print (("usage: {0} [-verbose] [-force] " + "[-help|-deprovision[+user]|-version|-serialconsole|-daemon|-run]" + "").format(sys.argv[0])) + +def Daemon(): + print "Start daemon in backgroud" + subprocess.Popen([sys.argv[0], "run"], stdout=devnull, stderr=devnull) def Main(): command, force, verbose = ParseArgs(sys.argv[1:]) - if command == "deprovision+user": - deprovisionHandler = CurrOSHandlerFactory.GetDeprovisionHandler() - deprovisionHandler.deprovision(force=force, deluser=True) - elif command == "deprovision": - deprovisionHandler = CurrOSHandlerFactory.GetDeprovisionHandler() - deprovisionHandler.deprovision(force=force, deluser=True) - elif command == "daemon": - configPath = CurrOSUtil.GetConfigurationPath() - config = conf.LoadConfiguration(configPath) - verbose = config.getSwitch("Logs.Verbose", False) - logger.LoggerInit('/var/log/waagent.log', - '/dev/console', - verbose=verbose) - fileutil.CreateDir(CurrOSUtil.GetLibDir(), mode='0700') - os.chdir(CurrOSUtil.GetLibDir()) - Agent(config).run() - elif command == "serialconsole": - #TODO - pass - elif command == "version": + if command == "version": Version() - else: + elif command == "help": Usage() + elif command == "daemon": + Daemon() + else: + Init() + if command == "serialconsole": + #TODO + pass + if command == "deprovision+user": + Deprovision(force, deluser=True) + elif command == "deprovision": + Deprovision(force, deluser=False) + elif command == "run": + Run() diff --git a/azureguestagent/exception.py b/azureguestagent/exception.py index b3e95d9..9d6d7cb 100644 --- a/azureguestagent/exception.py +++ b/azureguestagent/exception.py @@ -46,3 +46,10 @@ class ExtensionError(AgentError): def __init__(self, msg): super(ExtensionError, self).__init__('000003', msg) +""" +When provision failed +""" +class ProvisionError(AgentError): + def __init__(self, msg): + super(ExtensionError, self).__init__('000004', msg) + diff --git a/azureguestagent/handler/default/dhcpHandler.py b/azureguestagent/handler/default/dhcpHandler.py index 97b7711..9967597 100644 --- a/azureguestagent/handler/default/dhcpHandler.py +++ b/azureguestagent/handler/default/dhcpHandler.py @@ -44,11 +44,14 @@ class DhcpHandler(object): ipv4 = CurrOSUtil.GetIpv4Address() def probe(self): + self.waitForNetwork() macAddress = CurrOSUtil.GetMacAddress() req = BuildDhcpRequest(macAddress) resp = SendDhcpRequest(req) endpoint, gateway, routes = ParseDhcpResponse(resp) self.endpoint = endpoint + if endpoint is not None: + CurrOSUtil.SetWireServerEndpoint(endpoint) self.gateway = gateway self.routes = routes self.configRoutes() diff --git a/azureguestagent/handler/default/extensionHandler.py b/azureguestagent/handler/default/extensionHandler.py index a1d3164..86c8cd0 100644 --- a/azureguestagent/handler/default/extensionHandler.py +++ b/azureguestagent/handler/default/extensionHandler.py @@ -22,6 +22,7 @@ import zipfile import json import subprocess import azureguestagent.logger as logger +import azureguestagent.prot as prot from azureguestagent.exception import ExtensionError import azureguestagent.utils.fileutil as fileutil import azureguestagent.utils.restutil as restutil @@ -40,7 +41,9 @@ HandlerStatusToAggStatus = { class ExtensionHandler(object): - def process(self, protocol): + def process(self): + protocol = prot.GetDefaultProtocol() + extSettings = protocol.getExtensions() for setting in extSettings: #TODO handle extension in parallel @@ -55,7 +58,7 @@ class ExtensionHandler(object): ext.handle() aggStatus = ext.getAggStatus() except ExtensionError as e: - logger.Error("Failed to handle extension: {0}-{1}, {2}", + logger.Error("Failed to handle extension: {0}-{1}\n {2}", setting.getName(), setting.getVersion(), e) @@ -396,7 +399,8 @@ class ExtensionInstance(object): self.updateSetting() try: devnull = open(os.devnull, 'w') - child = subprocess.Popen(cmd, shell=True, cwd=baseDir, stdout=devnull) + child = subprocess.Popen([cmd], shell=True, + cwd=baseDir, stdout=devnull) except Exception as e: #TODO do not catch all exception raise ExtensionError("Failed to launch: {0}, {1}".format(cmd, e)) diff --git a/azureguestagent/handler/default/installHandler.py b/azureguestagent/handler/default/installHandler.py index 66e74fc..d2f82b6 100644 --- a/azureguestagent/handler/default/installHandler.py +++ b/azureguestagent/handler/default/installHandler.py @@ -17,16 +17,17 @@ # Requires Python 2.4+ and Openssl 1.0+ # -from azureguestagent.utils.osutil import CurrOS, CurrOSInfo +#TODO move install/uninstall handler to setup.py +from azureguestagent.utils.osutil import CurrOSUtil def Install(): - CurrOS.CheckDependencies() - CurrOS.RemoveRuleFiles() - CurrOS.SetSshClientAliveInterval() - CurrOS.RegisterAgentService() + CurrOSUtil.CheckDependencies() + CurrOSUtil.RemoveRuleFiles() + CurrOSUtil.SetSshClientAliveInterval() + CurrOSUtil.RegisterAgentService() def Uninstall(): - CurrOS.SwitchCwd() - CurrOS.UnregisterAgentService() - CurrOS.RestoreRuleFiles() + CurrOSUtil.SwitchCwd() + CurrOSUtil.UnregisterAgentService() + CurrOSUtil.RestoreRuleFiles() diff --git a/azureguestagent/handler/default/provisionHandler.py b/azureguestagent/handler/default/provisionHandler.py index 5c5b152..b5554cf 100644 --- a/azureguestagent/handler/default/provisionHandler.py +++ b/azureguestagent/handler/default/provisionHandler.py @@ -1,5 +1,3 @@ -# Windows Azure Linux Agent -# # Copyright 2014 Microsoft Corporation # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,102 +18,122 @@ import os import traceback import azureguestagent.logger as logger -from azureguestagent.utils.osutil import CurrOS, CurrOSInfo +import azureguestagent.conf as conf +from azureguestagent.utils.osutil import CurrOSUtil import azureguestagent.utils.shellutil as shellutil import azureguestagent.utils.fileutil as fileutil CustomDataFile="CustomData" class ProvisionHandler(object): - def __init__(self, config, protocol): - self.config = config - self.protocol = protocol + def process(self): + #If provision is not enabled, return + if not conf.GetSwitch("Provisioning.Enabled", True): + logger.Info("Provisioning is disabled. Skip.") + return + + provisoned = os.path.join(CurrOSUtil.GetLibDir(), "provisioned") + if os.path.isfile(provisioned): + return + + logger.Info("Start provisioning.") + protocol = prot.GetDefaultProtocol() + try: + logger.Info("Provisioning image started") + protocol.reportProvisionStatus("NotReady", + "Provisioning", + "Starting") + self.provision() + fileutil.SetFileContents(provisoned, "") + thumbprint = self.regenerateSshHostKey(keyPairType) + protocol.reportProvisionStatus(status="Ready", + thumbprint = thumbprint) + except ProvisionError as e: + logger.Error("Provision failed: {0}", e) + protocol.reportProvisionStatus(status="NotReady", subStatus=str(e)) + + + def regenerateSshHostKey(self): + keyPairType = conf.Get("Provisioning.SshHostKeyPairType", "rsa") + if self.config.getSwitch("Provisioning.RegenerateSshHostKeyPair"): + shellutil.Run("rm -f /etc/ssh/ssh_host_*key*") + shellutil.Run(("ssh-keygen -N '' -t {0} -f /etc/ssh/ssh_host_{1}_key" + "").format(keyPairType, keyPairType)) + thumbprint = self.getSshHostKeyThumbprint(keyPairType) + return thumbprint + + def getSshHostKeyThumbprint(self, keyPairType): + cmd = "ssh-keygen -lf /etc/ssh/ssh_host_{0}_key.pub".format(keyPairType) + ret = shellutil.RunGetOutput(cmd) + if ret[0] == 0: + return ret[1].rstrip().split()[1].replace(':', '') + else: + raise ProvisionError(("Failed to generate ssh host key: " + "ret={0}, out= {1}").format(ret[0], ret[1])) + def provision(self): - try: - if self.config.getSwitch("Provisioning.Enabled"): - self._provision() - else: - #In some distro like Ubuntu, cloud init does the provision - #In this case, we need to wait the cloud init to complete - #provision work and generate ssh host key - keyPairType = self.config.get("Provisioning.SshHostKeyPairType", "rsa") - CurrOS.WaitForSshHostKey(keyPairType) + ovfenv = self.copyOvf() + password = ovfenv.getUserPassword() + ovfenv.clearUserPassword() - keyPairType = self.config.get("Provisioning.SshHostKeyPairType", "rsa") - thumbprint = CurrOS.GetSshHostKeyThumbprint(keyPairType) - self.protocol.reportProvisionStatus(status="Ready", - thumbprint = thumbprint) - except Exception, e: - logger.Error("Provision failed: {0} {1}", e, traceback.format_exc()) - self.protocol.reportProvisionStatus(status="NotReady", - subStatus="Provisioning Failed") - raise e + CurrOSUtil.SetHostname(ovfenv.getComputerName()) + CurrOSUtil.PublishHostname(ovfenv.getComputerName()) + CurrOSUtil.UpdateUserAccount(ovfenv.getUserName(), password) - def _provision(self): - logger.Info("Provisioning image started") - self.protocol.reportProvisionStatus("NotReady", "Provisioning", "Starting") + CurrOSUtil.ConfigSshd(ovfenv.getDisableSshPasswordAuthentication()) - self.ovfenv = self.copyOvf() - password = self.ovfenv.getUserPassword() - self.ovfenv.clearUserPassword() - - CurrOS.SetHostname(self.ovfenv.getComputerName()) - CurrOS.PublishHostname(self.ovfenv.getComputerName()) - CurrOS.UpdateUserAccount(self.ovfenv.getUserName(), password) - - CurrOS.ConfigSshd(self.ovfenv.getDisableSshPasswordAuthentication()) #Disable selinux temporary - sel = CurrOS.IsSelinuxRunning() + sel = CurrOSUtil.IsSelinuxRunning() if sel: - CurrOS.SetSelinuxEnforce(0) - self.deploySshPublicKeys() - self.deploySshKeyPairs() - self.saveCustomData() + CurrOSUtil.SetSelinuxEnforce(0) + + self.deploySshPublicKeys(ovfenv) + self.deploySshKeyPairs(ovfenv) + self.saveCustomData(ovfenv) + if sel: - CurrOS.SetSelinuxEnforce(1) + CurrOSUtil.SetSelinuxEnforce(1) - keyPairType = self.config.get("Provisioning.SshHostKeyPairType", "rsa") - if self.config.getSwitch("Provisioning.RegenerateSshHostKeyPair"): - CurrOS.RegenerateSshHostkey(keyPairType) - - CurrOS.RestartSshService() + CurrOSUtil.RestartSshService() if self.config.getSwitch("Provisioning.DeleteRootPassword"): - CurrOS.DeleteRootPassword() + CurrOSUtil.DeleteRootPassword() def copyOvf(self): """ Copy ovf env file from dvd to hard disk. Remove password before save it to the disk """ - ovfFile = CurrOS.GetOvfEnvPathOnDvd() - CurrOS.MountDvd() + CurrOSUtil.MountDvd() + ovfFile = CurrOSUtil.GetOvfEnvPathOnDvd() if not os.path.isfile(ovfFile): - raise Exception("Unable to provision: Missing ovf-env.xml on DVD") + raise ProvisionError("Missing ovf-env.xml") + ovfxml = fileutil.GetFileContents(ovfFile, removeBom=True) ovfenv = OvfEnv(ovfxml) ovfxml = re.sub(".*?<", "*<", ovfxml) - ovfFilePath = os.path.join(CurrOS.GetLibDir(), OvfFileName) + ovfFilePath = os.path.join(CurrOSUtil.GetLibDir(), OvfFileName) fileutil.SetFileContents(ovfFilePath, ovfxml) - CurrOS.UmountDvd() + CurrOSUtil.UmountDvd() return ovfenv - def saveCustomData(self): - customData = self.ovfenv.getCustomData() + def saveCustomData(self, ovfenv): + customData = ovfenv.getCustomData() if customData is None: return - libDir = CurrOS.GetLibDir() + #TODO port Abel's fix to decoding custom data + libDir = CurrOSUtil.GetLibDir() fileutil.SetFileContents(os.path.join(libDir, CustomDataFile), - CurrOS.TranslateCustomData(customData)) + CurrOSUtil.TranslateCustomData(customData)) - def deploySshPublicKeys(self): - for thumbprint, path in self.ovfenv.getSshPublicKeys(): - CurrOS.DeploySshPublicKey(self.ovfenv.getUserName(), thumbprint, path) + def deploySshPublicKeys(self, ovfenv): + for thumbprint, path in ovfenv.getSshPublicKeys(): + CurrOSUtil.DeploySshPublicKey(ovfenv.getUserName(), thumbprint, path) - def deploySshKeyPairs(self): - for thumbprint, path in self.ovfenv.getSshKeyPairs(): - CurrOS.DeploySshKeyPair(self.ovfenv.getUserName(), thumbprint, path) + def deploySshKeyPairs(self, ovfenv): + for thumbprint, path in ovfenv.getSshKeyPairs(): + CurrOSUtil.DeploySshKeyPair(ovfenv.getUserName(), thumbprint, path) diff --git a/azureguestagent/handler/default/resourceDiskHandler.py b/azureguestagent/handler/default/resourceDiskHandler.py index 9e68365..e5b2b3c 100644 --- a/azureguestagent/handler/default/resourceDiskHandler.py +++ b/azureguestagent/handler/default/resourceDiskHandler.py @@ -18,6 +18,8 @@ # import os +import azureguestagent.logger as logger +import azureguestagent.conf as conf from azureguestagent.utils.osutil import CurrOSUtil import azureguestagent.utils.fileutil as fileutil @@ -34,19 +36,17 @@ For additional details to please refer to the MSDN documentation at : http://msd class ResourceDiskHandler(object): - def startActivateResourceDisk(self, config): - #TODO FreeBSD use Popen to open another process to do this - diskThread = threading.Thread(target = self.activateResourceDisk, - args = (config)) + def startActivateResourceDisk(self): + diskThread = threading.Thread(target = self.activateResourceDisk) diskThread.start() - def activateResourceDisk(self, config): - mountpoint = config.get("ResourceDisk.MountPoint", "/mnt/resource") - fs = config.get("ResourceDisk.Filesystem", "ext3") + def activateResourceDisk(self): + mountpoint = conf.Get("ResourceDisk.MountPoint", "/mnt/resource") + fs = conf.Get("ResourceDisk.Filesystem", "ext3") mountpoint = CurrOSUtil.MountResourceDisk(mountpoint, fs) warningFile = os.path.join(mountpoint, DataLossWarningFile) fileutil.SetFileContents(warningFile, DataLossWarning) - if config.getSwitch("ResourceDisk.EnabledSwap", False): + if conf.GetSwitch("ResourceDisk.EnabledSwap", False): sizeMB = config.getInt("ResourceDisk.SwapSizeMB", 0) CurrOSUtil.CreateSwapSpace(mountpoint, sizeMB) diff --git a/azureguestagent/handler/freebsd/__init__.py b/azureguestagent/handler/ubuntu/__init__.py similarity index 88% rename from azureguestagent/handler/freebsd/__init__.py rename to azureguestagent/handler/ubuntu/__init__.py index 7a4980e..1c87348 100644 --- a/azureguestagent/handler/freebsd/__init__.py +++ b/azureguestagent/handler/ubuntu/__init__.py @@ -16,3 +16,5 @@ # # Requires Python 2.4+ and Openssl 1.0+ # + +#from azureguestagent.handler.default.handlerFactory import DefaultHandlerFactory diff --git a/azureguestagent/handler/ubuntu/handlerFactory.py b/azureguestagent/handler/ubuntu/handlerFactory.py new file mode 100644 index 0000000..9a1d089 --- /dev/null +++ b/azureguestagent/handler/ubuntu/handlerFactory.py @@ -0,0 +1,29 @@ +# Windows Azure Linux Agent +# +# 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. +# +# Requires Python 2.4+ and Openssl 1.0+ +# + +from azureguestagent.handler.default.handlerFactory import DefaultHandlerFactory +from azureguestagent.handler.ubuntu.provisionHandler import UbuntuProvisionHandler + +class UbuntuHandlerFactory(DefaultHandlerFactory): + def __init__(self): + super(UbuntuHandlerFactory, self).__init__() + self.provisionHandler = UbuntuProvisionHandler() + + def getProvisionHandler(self): + return self.provisionHandler diff --git a/azureguestagent/handler/ubuntu/provisionHandler.py b/azureguestagent/handler/ubuntu/provisionHandler.py new file mode 100644 index 0000000..43ecd85 --- /dev/null +++ b/azureguestagent/handler/ubuntu/provisionHandler.py @@ -0,0 +1,62 @@ +# Windows Azure Linux Agent +# +# 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. +# +# Requires Python 2.4+ and Openssl 1.0+ +# + +import os +import traceback +import azureguestagent.logger as logger +import azureguestagent.conf as conf +from azureguestagent.utils.osutil import CurrOSUtil +import azureguestagent.utils.shellutil as shellutil +import azureguestagent.utils.fileutil as fileutil + +""" +On ubuntu image, provision could be disabled. +""" +class UbuntuProvisionHandler(ProvisionHandler): + def process(self): + + #If provision is enabled, run default provision handler + if conf.GetSwitch("Provisioning.Enabled", True): + super(UbuntuProvisionHandler, self).process() + return + + provisoned = os.path.join(CurrOSUtil.GetLibDir(), "provisioned") + if os.path.isfile(provisioned): + return + + logger.Info("Waiting cloud-init to finish provisioning.") + protocol = prot.GetDefaultProtocol() + try: + thumbprint = self.waitForSshHostKey() + protocol.reportProvisionStatus(status="Ready", + thumbprint = thumbprint) + fileutil.SetFileContents(provisoned, "") + except Provisioning as e: + logger.Error("Provision failed: {0}", e) + protocol.reportProvisionStatus(status="NotReady", subStatus=str(e)) + + def waitForSshHostKey(self, maxRetry=60): + keyPairType = self.config.get("Provisioning.SshHostKeyPairType", "rsa") + path = '/etc/ssh/ssh_host_{0}_key'.format(keyPairType) + for retry in range(0, maxRetry): + if os.path.isfile(path): + return self.getSshHostKeyThumbprint(keyPairType) + logger.Info("Wait for ssh host key be generated: {0}", path) + time.sleep(5) + raise ProvisionError("Ssh hsot key is not generated.") diff --git a/azureguestagent/utils/osutil/default.py b/azureguestagent/utils/osutil/default.py index fba6663..e6ceeb0 100644 --- a/azureguestagent/utils/osutil/default.py +++ b/azureguestagent/utils/osutil/default.py @@ -302,27 +302,6 @@ class DefaultOSUtil(object): fileutil.ReplaceFileContentsAtomic(configPath, "\n".join(config)) logger.Info("Disabled SSH password-based authentication methods.") - def RegenerateSshHostkey(self, keyPairType): - shellutil.Run("rm -f /etc/ssh/ssh_host_*key*") - shellutil.Run("ssh-keygen -N '' -t {0} -f /etc/ssh/ssh_host_{1}_key" - .format(keyPairType, keyPairType)) - - def GetSshHostKeyThumbprint(self, keyPairType): - cmd = "ssh-keygen -lf /etc/ssh/ssh_host_{0}_key.pub".format(keyPairType) - ret = shellutil.RunGetOutput(cmd) - if ret[0] == 0: - return ret[1].rstrip().split()[1].replace(':', '') - else: - return None - - def WaitForSshHostKey(self, keyPairType, maxRetry=6): - path = '/etc/ssh/ssh_host_{0}_key'.format(keyPairType) - for retry in range(0, maxRetry): - if os.path.isfile(path): - return - logger.Info("Wait for ssh host key be generated: {0}", path) - time.sleep(1) - raise Exception("Can't find ssh host key.") def GetDvdDevice(self, devDir='/dev'): patten=r'(sr[0-9]|hd[c-z]|cdrom[0-9])' diff --git a/tests/test_ext.py b/tests/test_ext.py index 29b880c..2c129ef 100644 --- a/tests/test_ext.py +++ b/tests/test_ext.py @@ -136,7 +136,7 @@ class TestExtensions(unittest.TestCase): @Mockup(ext.ExtensionInstance, 'getHandlerStatus', MockFunc(retval="enabled")) @Mockup(ext.ExtensionInstance, 'setHandlerStatus', MockSetHandlerStatus) def test_handle(self): - #Test handle + #Test enable testExt = ext.ExtensionInstance(setting, setting.getVersion(), False) testExt.initLog() self.assertEqual(1, len(testExt.logger.appenders) - len(logger.DefaultLogger.appenders)) @@ -148,8 +148,5 @@ class TestExtensions(unittest.TestCase): self.assertEqual(1, len(testExt.logger.appenders) - len(logger.DefaultLogger.appenders)) testExt.handle() - def test_status(self): - pass - if __name__ == '__main__': unittest.main() diff --git a/tests/test_provision.py b/tests/test_provision.py new file mode 100644 index 0000000..6fe81a9 --- /dev/null +++ b/tests/test_provision.py @@ -0,0 +1,33 @@ +# 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. +# +# Requires Python 2.4+ and Openssl 1.0+ +# + +import env +import tests.tools as tools +import uuid +import unittest +import os +import json +import azureguestagent.utils.fileutil as fileutil +from azureguestagent.handler.default.provisionHandler import ProvisionHandler + +class TestProvision(unittest.TestCase): + + def test_process(self): + pass + +if __name__ == '__main__': + unittest.main()