Refactor extension and provision handler

This commit is contained in:
Yue Zhang
2015-05-18 11:06:21 +08:00
parent 4d91860b9b
commit 237c68f4fe
13 changed files with 323 additions and 193 deletions
+81 -86
View File
@@ -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()
+7
View File
@@ -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)
@@ -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()
@@ -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))
@@ -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()
@@ -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("<UserPassword>.*?<", "<UserPassword>*<", 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)
@@ -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)
@@ -16,3 +16,5 @@
#
# Requires Python 2.4+ and Openssl 1.0+
#
#from azureguestagent.handler.default.handlerFactory import DefaultHandlerFactory
@@ -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
@@ -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.")
-21
View File
@@ -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])'
+1 -4
View File
@@ -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()
+33
View File
@@ -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()