mirror of
https://github.com/clearlinux/WALinuxAgent.git
synced 2026-09-06 22:01:34 +00:00
Refactor extension and provision handler
This commit is contained in:
+81
-86
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
+2
@@ -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.")
|
||||
@@ -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
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
Reference in New Issue
Block a user