summaryrefslogtreecommitdiff
path: root/waagent
diff options
context:
space:
mode:
Diffstat (limited to 'waagent')
-rw-r--r--waagent344
1 files changed, 238 insertions, 106 deletions
diff --git a/waagent b/waagent
index cbd005b..dd67353 100644
--- a/waagent
+++ b/waagent
@@ -80,7 +80,7 @@ if not hasattr(subprocess,'check_output'):
GuestAgentName = "WALinuxAgent"
GuestAgentLongName = "Windows Azure Linux Agent"
-GuestAgentVersion = "WALinuxAgent-2.0.12"
+GuestAgentVersion = "WALinuxAgent-2.0.13"
ProtocolVersion = "2012-11-30" #WARNING this value is used to confirm the correct fabric protocol.
Config = None
@@ -499,8 +499,9 @@ class AbstractDistro(object):
if existingFS == "7" and fs != "ntfs":
Run("sfdisk -c " + device + " 1 83")
Run("mkfs." + fs + " " + partition)
- if Run("mount " + partition + " " + mountpoint):
+ if Run("mount " + partition + " " + mountpoint, chk_err=False):
#If mount failed, try to format the partition and mount again
+ Warn("Failed to mount resource disk. Retry mounting.")
Run("mkfs." + fs + " " + partition + " -F")
if Run("mount " + partition + " " + mountpoint):
Error("ActivateResourceDisk: Failed to mount resource disk (" + partition + ").")
@@ -588,7 +589,7 @@ class AbstractDistro(object):
def stopDHCP(self):
"""
- Stop the system DHCP client so that tha agent can bind on its port. If
+ Stop the system DHCP client so that the agent can bind on its port. If
the distro has set dhcp_enabled to True, it will need to provide an
implementation of this method.
"""
@@ -605,6 +606,9 @@ class AbstractDistro(object):
"""
Translate the custom data from a Base64 encoding. Default to no-op.
"""
+ decodeCustomData = Config.get("Provisioning.DecodeCustomData")
+ if decodeCustomData != None and decodeCustomData.lower().startswith("y"):
+ return base64.b64decode(data)
return data
def getConfigurationPath(self):
@@ -615,7 +619,26 @@ class AbstractDistro(object):
def getTotalMemory(self):
return int(RunGetOutput("grep MemTotal /proc/meminfo |awk '{print $2}'")[1])/1024
-
+
+ def getInterfaceNameByMac(self, mac):
+ ret, output = RunGetOutput("ifconfig -a")
+ if ret != 0:
+ raise Exception("Failed to get network interface info")
+ match = re.search(r"(eth\d)[^\n]+HWaddr {0}".format(mac), output)
+ if match is None:
+ raise Exception("Failed to get ifname with mac: {0}".format(mac))
+ return match.group(1)
+
+ def configIpV4(self, ifName, addr):
+ ret, output = RunGetOutput("ifconfig {0} up".format(ifName))
+ if ret != 0:
+ raise Exception("Failed to bring up {0}: {1}".format(ifName,
+ output))
+ ret, output = RunGetOutput("ifconfig {0} {1}/24".format(ifName, addr))
+ if ret != 0:
+ raise Exception("Failed to config ipv4 for {0}: {1}".format(ifName,
+ output))
+
############################################################
# GentooDistro
############################################################
@@ -1019,7 +1042,7 @@ class CoreOSDistro(AbstractDistro):
self.dhcp_client_name='systemd-networkd'
self.getpidcmd='pidof '
self.shadow_file_mode=0640
- self.waagent_path='/usr/share/oem/waagent/bin'
+ self.waagent_path='/usr/share/oem/bin'
self.python_path='/usr/share/oem/python/bin'
self.dhcp_enabled=True
if 'PATH' in os.environ:
@@ -1337,18 +1360,6 @@ class UbuntuDistro(debianDistro):
def registerAgentService(self):
return self.installAgentServiceScriptFiles()
-
- def startAgentService(self):
- """
- Use upstart syntax.
- """
- return Run('start ' + self.agent_service_name)
-
- def stopAgentService(self):
- """
- Use upstart syntax.
- """
- return Run('stop ' + self.agent_service_name)
def uninstallAgentService(self):
"""
@@ -2585,12 +2596,15 @@ def DeviceForIdePort(n):
break
return device
+class HttpResourceGoneError(Exception):
+ pass
+
class Util(object):
"""
Http communication class.
Base of GoalState, and Agent classes.
"""
- __RetryWaitingInterval=10
+ RetryWaitingInterval=10
def __init__(self):
self.Endpoint = None
@@ -2598,47 +2612,82 @@ class Util(object):
def _ParseUrl(self, url):
secure = False
host = self.Endpoint
- action = url
-
- #Strip "http[s]://hostname/" from url
+ path = url
+ port = None
+
+ #"http[s]://hostname[:port][/]"
if url.startswith("http://"):
url = url[7:]
- pos = url.index("/")
- if pos > 0:
- host = url[0: pos]
- action = url[pos:]
+ if "/" in url:
+ host = url[0: url.index("/")]
+ path = url[url.index("/"):]
+ else:
+ host = url
+ path = "/"
elif url.startswith("https://"):
secure = True
url = url[8:]
- pos = url.index("/")
- if pos > 0:
- host = url[0:pos]
- action = url[pos:]
- return host, action, secure
-
- def _HttpRequest(self, method, host, action, data=None,
- secure=False, headers=None):
- resp = None;
- try:
- httpConnection = None
+ if "/" in url:
+ host = url[0: url.index("/")]
+ path = url[url.index("/"):]
+ else:
+ host = url
+ path = "/"
+
+ if host is None:
+ raise ValueError("Host is invalid:{0}".format(url))
+
+ if(":" in host):
+ pos = host.rfind(":")
+ port = int(host[pos + 1:])
+ host = host[0:pos]
+
+ return host, port, secure, path
- #If httplib module is not built with ssl support. Failback to http
- if secure and hasattr(httplib, "HTTPSConnection"):
- httpConnection = httplib.HTTPSConnection(host)
+ def GetHttpProxy(self, secure):
+ """
+ Get http_proxy and https_proxy from environment variables.
+ Username and password is not supported now.
+ """
+ host = Config.get("HttpProxy.Host")
+ port = Config.get("HttpProxy.Port")
+ return (host, port)
+
+ def _HttpRequest(self, method, host, path, port=None, data=None, secure=False,
+ headers=None, proxyHost=None, proxyPort=None):
+ resp = None
+ conn = None
+ try:
+ if secure:
+ port = 443 if port is None else port
+ if proxyHost is not None and proxyPort is not None:
+ conn = httplib.HTTPSConnection(proxyHost, proxyPort)
+ conn.set_tunnel(host, port)
+ #If proxy is used, full url is needed.
+ path = "https://{0}:{1}{2}".format(host, port, path)
+ else:
+ conn = httplib.HTTPSConnection(host, port)
else:
- httpConnection = httplib.HTTPConnection(host)
+ port = 80 if port is None else port
+ if proxyHost is not None and proxyPort is not None:
+ conn = httplib.HTTPConnection(proxyHost, proxyPort)
+ #If proxy is used, full url is needed.
+ path = "http://{0}:{1}{2}".format(host, port, path)
+ else:
+ conn = httplib.HTTPConnection(host, port)
if headers == None:
- httpConnection.request(method, action, data)
+ conn.request(method, path, data)
else:
- httpConnection.request(method, action, data, headers)
- resp = httpConnection.getresponse()
+ conn.request(method, path, data, headers)
+ resp = conn.getresponse()
except httplib.HTTPException, e:
Error('HTTPException {0}, args:{1}'.format(e, repr(e.args)))
except IOError, e:
Error('Socket IOError {0}, args:{1}'.format(e, repr(e.args)))
return resp
- def HttpRequest(self, method, url, data, headers=None, maxRetry=3):
+ def HttpRequest(self, method, url, data=None,
+ headers=None, maxRetry=3, chkProxy=False):
"""
Sending http request to server
On error, sleep 10 and maxRetry times.
@@ -2647,8 +2696,34 @@ class Util(object):
LogIfVerbose("HTTP Req: {0} {1}".format(method, url))
LogIfVerbose("HTTP Req: Data={0}".format(data))
LogIfVerbose("HTTP Req: Header={0}".format(headers))
- host, action, secure = self._ParseUrl(url)
- resp = self._HttpRequest(method, host, action, data, secure, headers)
+ try:
+ host, port, secure, path = self._ParseUrl(url)
+ except ValueError, e:
+ Error("Failed to parse url:{0}".format(url))
+ return None
+
+ #Check proxy
+ proxyHost, proxyPort = (None, None)
+ if chkProxy:
+ proxyHost, proxyPort = self.GetHttpProxy(secure)
+
+ #If httplib module is not built with ssl support. Fallback to http
+ if secure and not hasattr(httplib, "HTTPSConnection"):
+ Warn("httplib is not built with ssl support")
+ secure = False
+ proxyHost, proxyPort = self.GetHttpProxy(secure)
+
+ #If httplib module doesn't support https tunnelling. Fallback to http
+ if secure and \
+ proxyHost is not None and \
+ proxyPort is not None and \
+ not hasattr(httplib.HTTPSConnection, "set_tunnel"):
+ Warn("httplib doesn't support https tunnelling(new in python 2.7)")
+ secure = False
+ proxyHost, proxyPort = self.GetHttpProxy(secure)
+
+ resp = self._HttpRequest(method, host, path, port, data,
+ secure, headers, proxyHost, proxyPort)
for retry in range(0, maxRetry):
if resp is not None and \
(resp.status == httplib.OK or \
@@ -2656,6 +2731,9 @@ class Util(object):
resp.status == httplib.ACCEPTED):
return resp;
+ if resp is not None and resp.status == httplib.GONE:
+ raise HttpResourceGoneError("Http resource gone.")
+
Error("Retry={0}".format(retry))
Error("HTTP Req: {0} {1}".format(method, url))
Error("HTTP Req: Data={0}".format(data))
@@ -2667,35 +2745,36 @@ class Util(object):
Error("HTTP Err: Reason={0}".format(resp.reason))
Error("HTTP Err: Header={0}".format(resp.getheaders()))
Error("HTTP Err: Body={0}".format(resp.read()))
- time.sleep(self.__class__.__RetryWaitingInterval)
- resp = self._HttpRequest(method, host, action, data, secure,
- headers)
+
+ time.sleep(self.__class__.RetryWaitingInterval)
+ resp = self._HttpRequest(method, host, path, data, secure,
+ headers, proxyHost, proxyPort)
return None
- def HttpGet(self, url, headers=None, maxRetry=3):
- return self.HttpRequest("GET", url, None, headers, maxRetry)
+ def HttpGet(self, url, headers=None, maxRetry=3, chkProxy=False):
+ return self.HttpRequest("GET", url, None, headers, maxRetry, chkProxy)
- def HttpHead(self, url, headers=None, maxRetry=3):
- return self.HttpRequest("HEAD", url, None, headers, maxRetry)
+ def HttpHead(self, url, headers=None, maxRetry=3, chkProxy=False):
+ return self.HttpRequest("HEAD", url, None, headers, maxRetry, chkProxy)
- def HttpPost(self, url, data, headers=None, maxRetry=3):
- return self.HttpRequest("POST", url, data, headers, maxRetry)
+ def HttpPost(self, url, data, headers=None, maxRetry=3, chkProxy=False):
+ return self.HttpRequest("POST", url, data, headers, maxRetry, chkProxy)
- def HttpPut(self, url, data, headers=None, maxRetry=3):
- return self.HttpRequest("PUT", url, data, headers, maxRetry)
+ def HttpPut(self, url, data, headers=None, maxRetry=3, chkProxy=False):
+ return self.HttpRequest("PUT", url, data, headers, maxRetry, chkProxy)
- def HttpDelete(url, data, headers=None, maxRetry=3):
- return self.HttpRequest("DELETE", url, data, headers, maxRetry)
+ def HttpDelete(self, url, headers=None, maxRetry=3, chkProxy=False):
+ return self.HttpRequest("DELETE", url, None, headers, maxRetry, chkProxy)
- def HttpGetWithoutHeaders(self, url, maxRetry=3):
+ def HttpGetWithoutHeaders(self, url, maxRetry=3, chkProxy=False):
"""
Return data from an HTTP get on 'url'.
"""
- resp = self.HttpGet(url, None, maxRetry)
+ resp = self.HttpGet(url, None, maxRetry, chkProxy)
return resp.read() if resp is not None else None
- def HttpGetWithHeaders(self, url, maxRetry=3):
+ def HttpGetWithHeaders(self, url, maxRetry=3, chkProxy=False):
"""
Return data from an HTTP get on 'url' with
x-ms-agent-name and x-ms-version
@@ -2704,10 +2783,11 @@ class Util(object):
resp = self.HttpGet(url, {
"x-ms-agent-name": GuestAgentName,
"x-ms-version": ProtocolVersion
- }, maxRetry)
+ }, maxRetry, chkProxy)
return resp.read() if resp is not None else None
- def HttpSecureGetWithHeaders(self, url, transportCert, maxRetry=3):
+ def HttpSecureGetWithHeaders(self, url, transportCert, maxRetry=3,
+ chkProxy=False):
"""
Return output of get using ssl cert.
"""
@@ -2716,16 +2796,16 @@ class Util(object):
"x-ms-version": ProtocolVersion,
"x-ms-cipher-name": "DES_EDE3_CBC",
"x-ms-guest-agent-public-x509-cert": transportCert
- }, maxRetry)
+ }, maxRetry, chkProxy)
return resp.read() if resp is not None else None
- def HttpPostWithHeaders(self, url, data, maxRetry=3):
+ def HttpPostWithHeaders(self, url, data, maxRetry=3, chkProxy=False):
header = {
"x-ms-agent-name": GuestAgentName,
"Content-Type": "text/xml; charset=utf-8",
"x-ms-version": ProtocolVersion
}
- return self.HttpPost(url, data, header, maxRetry)
+ return self.HttpPost(url, data, header, maxRetry, chkProxy)
__StorageVersion="2014-02-14"
@@ -2737,7 +2817,7 @@ def GetBlobType(url):
blobPropResp = restutil.HttpHead(url, {
"x-ms-date" : timestamp,
'x-ms-version' : __StorageVersion
- });
+ }, chkProxy=True);
blobType = None
if blobPropResp is None:
Error("Can't get status blob type.")
@@ -2755,7 +2835,7 @@ def PutBlockBlob(url, data):
"x-ms-blob-type" : "BlockBlob",
"Content-Length": str(len(data)),
"x-ms-version" : __StorageVersion
- })
+ }, chkProxy=True)
if ret is None:
Error("Failed to upload block blob for status.")
@@ -2771,7 +2851,7 @@ def PutPageBlob(url, data):
"Content-Length": "0",
"x-ms-blob-content-length" : str(pageBlobSize),
"x-ms-version" : __StorageVersion
- })
+ }, chkProxy=True)
if ret is None:
Error("Failed to clean up page blob for status")
return
@@ -2799,7 +2879,7 @@ def PutPageBlob(url, data):
"x-ms-page-write" : "update",
"x-ms-version" : __StorageVersion,
"Content-Length": str(pageEnd - start)
- })
+ }, chkProxy=True)
if ret is None:
Error("Failed to upload page blob for status")
return
@@ -2919,7 +2999,7 @@ class EnvMonitor(object):
Monitor dhcp client pid and hostname.
If dhcp clinet process re-start has occurred, reset routes, dhcp with fabric.
"""
- publish = ConfigurationProvider().get("Provisioning.MonitorHostName")
+ publish = Config.get("Provisioning.MonitorHostName")
dhcpcmd = MyDistro.getpidcmd+ ' ' + MyDistro.getDhcpClientName()
dhcppid = RunGetOutput(dhcpcmd)[1]
while not self.shutdown:
@@ -3130,6 +3210,7 @@ class SharedConfig(object):
"""
Parse and write configuration to file SharedConfig.xml.
"""
+ LogIfVerbose(xmlText)
self.reinitialize()
self.xmlText = xmlText
dom = xml.dom.minidom.parseString(xmlText)
@@ -3146,25 +3227,46 @@ class SharedConfig(object):
if nodes is not None and len(nodes) != 0:
node = nodes[0]
if node.hasAttribute("rdmaMacAddress"):
- self.RdmaMacAddress = node.getAttribute("rdmaMacAddress")
+ addr = node.getAttribute("rdmaMacAddress")
+ self.RdmaMacAddress = addr[0:2]
+ for i in range(1, 6):
+ self.RdmaMacAddress += ":" + addr[2 * i : 2 *i + 2]
if node.hasAttribute("rdmaIPv4Address"):
self.RdmaIPv4Address = node.getAttribute("rdmaIPv4Address")
return self
def Save(self):
+ LogIfVerbose("Save SharedConfig.xml")
SetFileContents("SharedConfig.xml", self.xmlText)
- def ConfigRdma(self, dev="/dev/hvnd_rdma"):
- if self.RdmaIPv4Address is not None and self.RdmaMacAddress is not None:
- if os.path.isfile(dev):
- data = ('rdmaMacAddress="{0}" rdmaIPv4Address="{1}"'
- '').format(self.RdmaMacAddress, self.RdmaIPv4Address)
- Log("Write rdma config to {0}: {1}".format(dev, data))
- try:
- with open(dev, "w") as c:
- c.write(data)
- except IOError, e:
- Error("Error writing {0}, {1}".format(dev, e))
+ def ConfigRdma(self, dev="/dev/hvnd_rdma", datConf="/etc/dat.conf"):
+ if self.RdmaIPv4Address is None or self.RdmaMacAddress is None:
+ return
+
+ if os.path.isfile(datConf):
+ old = ("ofa-v2-ib0 u2.0 nonthreadsafe default libdaplofa.so.2 "
+ "dapl.2.0 \"\S+ 0\"")
+ new = ("ofa-v2-ib0 u2.0 nonthreadsafe default libdaplofa.so.2 "
+ "dapl.2.0 \"{0} 0\"").format(self.RdmaIPv4Address)
+ lines = GetFileContents(datConf)
+ lines = re.sub(old, new, lines)
+ SetFileContents(lines)
+
+ if os.path.isfile(dev):
+ data = ('rdmaMacAddress="{0}" rdmaIPv4Address="{1}"'
+ '').format(self.RdmaMacAddress, self.RdmaIPv4Address)
+ Log("Write rdma config to {0}: {1}".format(dev, data))
+ try:
+ with open(dev, "w") as c:
+ c.write(data)
+ except IOError, e:
+ Error("Error writing {0}, {1}".format(dev, e))
+
+ try:
+ ifName = MyDistro.getInterfaceNameByMac(self.RdmaMacAddress)
+ MyDistro.configIpV4(ifName, self.RdmaIPv4Address)
+ except Exception as e:
+ Error("Failed to config rdma device: {0}".format(e))
def InvokeTopologyConsumer(self):
program = Config.get("Role.TopologyConsumer")
@@ -3331,7 +3433,7 @@ class ExtensionsConfig(object):
Log("Plugin server is: " + self.Util.Endpoint)
SimpleLog(p.plugin_log,"Plugin server is: " + self.Util.Endpoint)
- manifest=self.Util.HttpGetWithoutHeaders(location)
+ manifest=self.Util.HttpGetWithoutHeaders(location, chkProxy=True)
if manifest == None:
Error("Unable to download plugin manifest" + name + " from primary location. Attempting with failover location.")
SimpleLog(p.plugin_log,"Unable to download plugin manifest" + name + " from primary location. Attempting with failover location.")
@@ -3340,12 +3442,12 @@ class ExtensionsConfig(object):
Log("Plugin failover server is: " + self.Util.Endpoint)
SimpleLog(p.plugin_log,"Plugin failover server is: " + self.Util.Endpoint)
- manifest=self.Util.HttpGetWithoutHeaders(failoverlocation)
+ manifest=self.Util.HttpGetWithoutHeaders(failoverlocation, chkProxy=True)
#if failoverlocation also fail what to do then?
if manifest == None:
AddExtensionEvent(name,WALAEventOperation.Download,False,0,version,"Download mainfest fail "+failoverlocation)
- Log("Plugin manifest" + name + "downloaded successfully length = " + str(len(manifest)))
- SimpleLog(p.plugin_log,"Plugin manifest" + name + "downloaded successfully length = " + str(len(manifest)))
+ Log("Plugin manifest " + name + " downloading failed from failover location.")
+ SimpleLog(p.plugin_log,"Plugin manifest " + name + " downloading failed from failover location.")
filepath=LibDir+"/" + name + '.' + incarnation + '.manifest'
if os.path.splitext(location)[-1] == '.xml' : #if this is an xml file we may have a BOM
@@ -3374,7 +3476,7 @@ class ExtensionsConfig(object):
SimpleLog(p.plugin_log,"Bundle URI = " + bundle_uri)
# Download the zipfile archive and save as '.zip'
- bundle=self.Util.HttpGetWithoutHeaders(bundle_uri)
+ bundle=self.Util.HttpGetWithoutHeaders(bundle_uri, chkProxy=True)
if bundle == None:
AddExtensionEvent(name,WALAEventOperation.Download,True,0,version,"Download zip fail "+bundle_uri)
Error("Unable to download plugin bundle" + bundle_uri )
@@ -4085,6 +4187,7 @@ class GoalState(Util):
LogIfVerbose("SharedConfigUrl:" + self.SharedConfigUrl)
self.SharedConfigXml = self.HttpGetWithHeaders(self.SharedConfigUrl)
self.SharedConfig = SharedConfig().Parse(self.SharedConfigXml)
+ self.SharedConfig.Save()
elif e.localName == "ExtensionsConfig":
self.ExtensionsConfigUrl = GetNodeTextData(e)
LogIfVerbose("ExtensionsConfigUrl:" + self.ExtensionsConfigUrl)
@@ -4113,9 +4216,9 @@ class GoalState(Util):
"""
Calls HostingEnvironmentConfig.Process()
"""
+ LogIfVerbose("Process goalstate")
self.HostingEnvironmentConfig.Process()
self.SharedConfig.Process()
- self.SharedConfig.Save()
class OvfEnv(object):
"""
@@ -4170,7 +4273,7 @@ class OvfEnv(object):
self.SshPublicKeys = []
self.SshKeyPairs = []
- def Parse(self, xmlText):
+ def Parse(self, xmlText, isDeprovision = False):
"""
Parse xml tree, retreiving user and ssh key information.
Return self.
@@ -4202,6 +4305,8 @@ class OvfEnv(object):
return None
self.ComputerName = GetNodeTextData(section.getElementsByTagNameNS(self.WaNs, "HostName")[0])
self.UserName = GetNodeTextData(section.getElementsByTagNameNS(self.WaNs, "UserName")[0])
+ if isDeprovision == True:
+ return self
try:
self.UserPassword = GetNodeTextData(section.getElementsByTagNameNS(self.WaNs, "UserPassword")[0])
except:
@@ -4450,7 +4555,7 @@ class WALAEvent(object):
os.mkdir(eventfolder)
os.chmod(eventfolder,0700)
if len(os.listdir(eventfolder)) > 1000:
- raise Exception("WriteToFolder:Too many file under "+datafolder+" exit")
+ raise Exception("WriteToFolder:Too many file under "+eventfolder+" exit")
filename = os.path.join(eventfolder,str(int(time.time()*1000000)))
with open(filename+".tmp",'wb+') as hfile:
@@ -4594,7 +4699,7 @@ class WALAEventMonitor(WALAEvent):
if not self.issysteminfoinitilized:
self.issysteminfoinitilized=True
try:
- self.sysInfo["OSVersion"]=platform.system()+":"+"-".join(DistInfo())+":"+platform.release()
+ self.sysInfo["OSVersion"]=platform.system()+":"+"-".join(DistInfo(1))+":"+platform.release()
self.sysInfo["GAVersion"]=GuestAgentVersion
self.sysInfo["RAM"]=MyDistro.getTotalMemory()
self.sysInfo["Processors"]=MyDistro.getProcessorCores()
@@ -5346,9 +5451,17 @@ class Agent(Util):
lbProbeResponder = False
while True:
if (goalState == None) or (incarnation == None) or (goalState.Incarnation != incarnation):
- goalState = self.UpdateGoalState()
+ try:
+ goalState = self.UpdateGoalState()
+ except HttpResourceGoneError as e:
+ Warn("Incarnation is out of date:{0}".format(e))
+ incarnation = None
+ continue
+
if goalState == None :
+ Warn("Failed to fetch goalstate")
continue
+
if provisioned == False:
self.ReportNotReady("Provisioning", "Starting")
@@ -5368,7 +5481,15 @@ class Agent(Util):
#Get Ctime of wala config, can help identify the base image of this VM
AddExtensionEvent(name="WALA",op=WALAEventOperation.Provision,isSuccess=True,
message="WALA Config Ctime:"+lastCtime)
-
+
+ executeCustomData = Config.get("Provisioning.ExecuteCustomData")
+ if executeCustomData != None and executeCustomData.lower().startswith("y"):
+ if os.path.exists(LibDir + '/CustomData'):
+ Run('chmod +x ' + LibDir + '/CustomData')
+ Run(LibDir + '/CustomData')
+ else:
+ Error(LibDir + '/CustomData does not exist.')
+
#
# only one port supported
# restart server if new port is different than old port
@@ -5376,13 +5497,17 @@ class Agent(Util):
#
goalPort = goalState.LoadBalancerProbePort
if currentPort != goalPort:
- self.LoadBalancerProbeServer_Shutdown()
- currentPort = goalPort
- if currentPort != None and lbProbeResponder == True:
- self.LoadBalancerProbeServer = LoadBalancerProbeServer(currentPort)
- if self.LoadBalancerProbeServer == None :
- lbProbeResponder = False
- Log("Unable to create LBProbeResponder.")
+ try:
+ self.LoadBalancerProbeServer_Shutdown()
+ currentPort = goalPort
+ if currentPort != None and lbProbeResponder == True:
+ self.LoadBalancerProbeServer = LoadBalancerProbeServer(currentPort)
+ if self.LoadBalancerProbeServer == None :
+ lbProbeResponder = False
+ Log("Unable to create LBProbeResponder.")
+ except Exception, e:
+ Error("Failed to launch LBProbeResponder: {0}".format(e))
+ currentPort = None
# Report SSH key fingerprint
type = Config.get("Provisioning.SshHostKeyPairType")
@@ -5419,7 +5544,7 @@ class Agent(Util):
eventMonitor = WALAEventMonitor(self.HttpPostWithHeaders)
eventMonitor.StartEventsLoop()
- time.sleep(25 - sleepToReduceAccessDenied)
+ time.sleep(25 - sleepToReduceAccessDenied)
WaagentLogrotate = """\
@@ -5513,14 +5638,14 @@ def ReplaceStringInFile(fname,src,repl):
"""
Replace 'src' with 'repl' in file.
"""
- updated=''
try:
sr=re.compile(src)
if FindStringInFile(fname,src):
+ updated=''
for l in (open(fname,'r')).readlines():
n=re.sub(sr,repl,l)
updated+=n
- ReplaceFileContentsAtomic(fname,updated)
+ ReplaceFileContentsAtomic(fname,updated)
except :
raise
return
@@ -5619,6 +5744,7 @@ def DistInfo(fullname=0):
release = re.sub('\-.*\Z', '', str(platform.release()))
distinfo = ['FreeBSD', release]
return distinfo
+
if 'linux_distribution' in dir(platform):
distinfo = list(platform.linux_distribution(full_distribution_name=fullname))
distinfo[0] = distinfo[0].strip() # remove trailing whitespace in distro name
@@ -5679,7 +5805,7 @@ def Deprovision(force, deluser):
ovfxml = GetFileContents(LibDir+"/ovf-env.xml")
ovfobj = None
if ovfxml != None:
- ovfobj = OvfEnv().Parse(ovfxml)
+ ovfobj = OvfEnv().Parse(ovfxml, True)
print("WARNING! The waagent service will be stopped.")
print("WARNING! All SSH host key pairs will be deleted.")
@@ -5747,6 +5873,12 @@ def main():
LoggerInit('/var/log/waagent.log','/dev/console')
global LinuxDistro
LinuxDistro=DistInfo()[0]
+
+ #The platform.py lib has issue with detecting oracle linux distribution.
+ #Merge the following patch provided by oracle as a temparory fix.
+ if os.path.exists("/etc/oracle-release"):
+ LinuxDistro="Oracle Linux"
+
global MyDistro
MyDistro=GetMyDistro()
if MyDistro == None :