Hello community, here is the log from the commit of package WALinuxAgent for openSUSE:Factory checked in at 2015-07-14 17:43:14 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/WALinuxAgent (Old) and /work/SRC/openSUSE:Factory/.WALinuxAgent.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "WALinuxAgent" Changes: -------- --- /work/SRC/openSUSE:Factory/WALinuxAgent/WALinuxAgent.changes 2015-06-23 11:57:40.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.WALinuxAgent.new/WALinuxAgent.changes 2015-07-14 17:44:20.000000000 +0200 @@ -1,0 +2,8 @@ +Thu Jul 2 15:33:05 UTC 2015 - [email protected] + +- Update to version 2.0.14 (bnc#936908) + + Fix rdma config + + Fix page blob uploading for python 2.6 + + Fix http request error handling + +------------------------------------------------------------------- Old: ---- WALinuxAgent-2.0.13.tar.gz New: ---- WALinuxAgent-2.0.14.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ WALinuxAgent.spec ++++++ --- /var/tmp/diff_new_pack.Cl5xyP/_old 2015-07-14 17:44:21.000000000 +0200 +++ /var/tmp/diff_new_pack.Cl5xyP/_new 2015-07-14 17:44:21.000000000 +0200 @@ -20,7 +20,7 @@ Summary: The Windows Azure Linux Agent License: Apache-2.0 Group: System/Daemons -Version: 2.0.13 +Version: 2.0.14 Release: 0 Url: https://github.com/Azure/WALinuxAgent Source0: https://github.com/Azure/%{name}/archive/%{name}-%{version}.tar.gz ++++++ WALinuxAgent-2.0.13.tar.gz -> WALinuxAgent-2.0.14.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/WALinuxAgent-WALinuxAgent-2.0.13/Changelog new/WALinuxAgent-WALinuxAgent-2.0.14/Changelog --- old/WALinuxAgent-WALinuxAgent-2.0.13/Changelog 2015-06-01 03:55:11.000000000 +0200 +++ new/WALinuxAgent-WALinuxAgent-2.0.14/Changelog 2015-07-02 11:26:10.000000000 +0200 @@ -1,5 +1,10 @@ WALinuxAgent Changelog ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| +1 Jul 2015, WALinuxAgent 2.0.14 + . Fix rdma config + . Fix page blob uploading for python 2.6 + . Fix http request error handling + 1 Jun 2015, WALinuxAgent 2.0.13 . Handle http 410 returned by host . Add support for http proxy diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/WALinuxAgent-WALinuxAgent-2.0.13/Dockerfile new/WALinuxAgent-WALinuxAgent-2.0.14/Dockerfile --- old/WALinuxAgent-WALinuxAgent-2.0.13/Dockerfile 1970-01-01 01:00:00.000000000 +0100 +++ new/WALinuxAgent-WALinuxAgent-2.0.14/Dockerfile 2015-07-02 11:26:10.000000000 +0200 @@ -0,0 +1,10 @@ +FROM debian:jessie +RUN apt-get update && apt-get upgrade --no-install-recommends -y +RUN apt-get install -y --no-install-recommends \ + openssl ca-certificates ssh parted sudo net-tools ifupdown python python-pyasn1 python-rpm +COPY waagent /usr/sbin/ +COPY config/docker-waagent.conf /etc/waagent.conf +RUN chmod +x /usr/sbin/waagent && \ + rm -rf /etc/skel && \ + ln -sf /dev/stdout /var/log/waagent.log +ENTRYPOINT ["/usr/sbin/waagent"] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/WALinuxAgent-WALinuxAgent-2.0.13/README new/WALinuxAgent-WALinuxAgent-2.0.14/README --- old/WALinuxAgent-WALinuxAgent-2.0.13/README 2015-06-01 03:55:11.000000000 +0200 +++ new/WALinuxAgent-WALinuxAgent-2.0.14/README 2015-07-02 11:26:10.000000000 +0200 @@ -128,6 +128,10 @@ -force: Skip interactive confirmation for some commands +Options: + + -conf=/path/to/file.conf: Specify configuration file to use instead of default one. + Commands: -help: Lists the supported commands and flags. @@ -203,6 +207,8 @@ ResourceDisk.EnableSwap=n ResourceDisk.SwapSizeMB=0 LBProbeResponder=y +Logs.File=/var/log/waagent.log +Logs.Console=y Logs.Verbose=n OS.RootDeviceScsiTimeout=300 OS.OpensslPath=None @@ -337,11 +343,23 @@ If set, waagent will respond to load balancer probes from the platform (if present). +Logs.File: +Type: String Default: /dev/stdout + +If set, logs are appended to this file (instead of stdout). Bundled +config (config/waagent.conf) sets this to '/var/log/waagent.log'. + +Logs.Console: +Type: Boolean Default: n + +If set, waagent also logs to serial console. Bundled config (config/waagent.conf) +sets this to 'y'. + Logs.Verbose: Type: Boolean Default: n -If set, log verbosity is boosted. Waagent logs to /var/log/waagent.log and -leverages the system logrotate functionality to rotate logs. +If set, log verbosity is boosted. When waagent logs to file it can +leverage the system logrotate functionality to rotate logs. OS.RootDeviceScsiTimeout: Type: Integer Default: 300 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/WALinuxAgent-WALinuxAgent-2.0.13/config/docker-waagent.conf new/WALinuxAgent-WALinuxAgent-2.0.14/config/docker-waagent.conf --- old/WALinuxAgent-WALinuxAgent-2.0.13/config/docker-waagent.conf 1970-01-01 01:00:00.000000000 +0100 +++ new/WALinuxAgent-WALinuxAgent-2.0.14/config/docker-waagent.conf 2015-07-02 11:26:10.000000000 +0200 @@ -0,0 +1,75 @@ +# +# Windows Azure Linux Agent Configuration +# + +# Specified program is invoked with the argument "Ready" when we report ready status +# to the endpoint server. +Role.StateConsumer=None + +# Specified program is invoked with XML file argument specifying role +# configuration. +Role.ConfigurationConsumer=None + +# Specified program is invoked with XML file argument specifying role topology. +Role.TopologyConsumer=None + +# Enable instance creation +Provisioning.Enabled=y + +# Password authentication for root account will be unavailable. +Provisioning.DeleteRootPassword=y + +# Generate fresh host key pair. +Provisioning.RegenerateSshHostKeyPair=n + +# Supported values are "rsa", "dsa" and "ecdsa". +Provisioning.SshHostKeyPairType=rsa + +# Monitor host name changes and publish changes via DHCP requests. +Provisioning.MonitorHostName=y + +# Decode CustomData from Base64. +Provisioning.DecodeCustomData=n + +# Execute CustomData after provisioning. +Provisioning.ExecuteCustomData=n + +# Format if unformatted. If 'n', resource disk will not be mounted. +ResourceDisk.Format=y + +# File system on the resource disk +# Typically ext3 or ext4. FreeBSD images should use 'ufs2' here. +ResourceDisk.Filesystem=ext4 + +# Mount point for the resource disk +ResourceDisk.MountPoint=/mnt/resource + +# Create and use swapfile on resource disk. +ResourceDisk.EnableSwap=n + +# Size of the swapfile. +ResourceDisk.SwapSizeMB=0 + +# Respond to load balancer probes if requested by Windows Azure. +LBProbeResponder=y + +# File to write log to. +# '/var/log/waagent.log' if not set +Logs.File=/dev/stdout + +# Enable logging to serial console (y|n) +# When stdout is not enough... +# 'y' if not set +Logs.Console=n + +# Enable verbose logging (y|n) +Logs.Verbose=n + +# Preferred network interface to communicate with Azure platform +Network.Interface=eth0 + +# Root device timeout in seconds. +OS.RootDeviceScsiTimeout=300 + +# If "None", the system default version is used. +OS.OpensslPath=None diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/WALinuxAgent-WALinuxAgent-2.0.13/config/waagent.conf new/WALinuxAgent-WALinuxAgent-2.0.14/config/waagent.conf --- old/WALinuxAgent-WALinuxAgent-2.0.13/config/waagent.conf 2015-06-01 03:55:11.000000000 +0200 +++ new/WALinuxAgent-WALinuxAgent-2.0.14/config/waagent.conf 2015-07-02 11:26:10.000000000 +0200 @@ -53,9 +53,21 @@ # Respond to load balancer probes if requested by Windows Azure. LBProbeResponder=y +# File to write log to. +# '/var/log/waagent.log' if not set +Logs.File=/var/log/waagent.log + +# Enable logging to serial console (y|n) +# When stdout is not enough... +# 'y' if not set +Logs.Console=y + # Enable verbose logging (y|n) Logs.Verbose=n +# Preferred network interface to communicate with Azure platform +#Network.Interface=eth0 + # Root device timeout in seconds. OS.RootDeviceScsiTimeout=300 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/WALinuxAgent-WALinuxAgent-2.0.13/tests/test_shared_config.py new/WALinuxAgent-WALinuxAgent-2.0.14/tests/test_shared_config.py --- old/WALinuxAgent-WALinuxAgent-2.0.13/tests/test_shared_config.py 2015-06-01 03:55:11.000000000 +0200 +++ new/WALinuxAgent-WALinuxAgent-2.0.14/tests/test_shared_config.py 2015-07-02 11:26:10.000000000 +0200 @@ -13,6 +13,8 @@ # limitations under the License. # +import os +import re import unittest from env import waagent @@ -24,6 +26,16 @@ pass class TestSharedConfig(unittest.TestCase): + + def test_reg(self): + mac = "00:15:5D:34:00:08" + output = Ifconfig_Out + output = output.replace('\n', '') + reg = r"(eth\d).*(HWaddr|ether) {0}".format(mac) + match = re.search(reg, output, re.IGNORECASE) + output = match.group(0) + eths = re.findall(r"eth\d", output) + self.assertNotEquals(0, len(eths)) def test_parse_shared_config(self): conf = waagent.SharedConfig().Parse(SharedConfigText) @@ -34,15 +46,32 @@ return conf def test_config_rdma(self): - #waagent.LoggerInit("/dev/stdout", "/dev/null", verbose=True) waagent.MyDistro= MockDistro() - testDev = "/tmp/hvnd_rdma" - waagent.SetFileContents(testDev, "") + waagent.LibDir="/tmp" + + test_dev = "/tmp/hvnd_rdma" + test_dat_conf_files = ["/tmp/dat.conf"] + if os.path.isfile("/tmp/rdmaconfiged"): + os.remove("/tmp/rdmaconfiged") + waagent.SetFileContents(test_dev, "") + old = ("ofa-v2-ib0 u2.0 nonthreadsafe default libdaplofa.so.2 " + "dapl.2.0 \"oldip 0\"") + waagent.SetFileContents(test_dat_conf_files[0], old) conf = self.test_parse_shared_config() - conf.ConfigRdma(dev=testDev) - rdmaConf = waagent.GetFileContents(testDev) - self.assertNotEquals(None, rdmaConf) - self.assertNotEquals("", rdmaConf) + handler = waagent.RdmaHandler(conf.RdmaMacAddress, conf.RdmaIPv4Address, + test_dev, test_dat_conf_files) + handler.set_dat_conf() + handler.set_rdma_dev() + + rdma_conf = waagent.GetFileContents(test_dev) + self.assertNotEquals(None, rdma_conf) + self.assertNotEquals(0, rdma_conf.count(conf.RdmaIPv4Address)) + self.assertNotEquals(0, rdma_conf.count(conf.RdmaMacAddress)) + + dat_conf = waagent.GetFileContents(test_dat_conf_files[0]) + self.assertNotEquals(None, dat_conf) + self.assertNotEquals(0, dat_conf.count(conf.RdmaIPv4Address)) + self.assertEquals(0, dat_conf.count("oldip")) SharedConfigText="""\ <?xml version="1.0" encoding="utf-8"?> @@ -88,6 +117,32 @@ </Instances> </SharedConfig> """ +Ifconfig_Out="""\ +eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 +inet 100.74.52.8 netmask 255.255.255.0 broadcast 100.74.52.255 +inet6 fe80::20d:3aff:fe10:672f prefixlen 64 scopeid 0x20<link> +ether 00:0d:3a:10:67:2f txqueuelen 1000 (Ethernet) +RX packets 9911 bytes 4451278 (4.2 MiB) +RX errors 0 dropped 0 overruns 0 frame 0 +TX packets 10505 bytes 1643251 (1.5 MiB) +TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 + +eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 +inet6 fe80::215:5dff:fe34:8 prefixlen 64 scopeid 0x20<link> +ether 00:15:5d:34:00:08 txqueuelen 1000 (Ethernet) +RX packets 16 bytes 672 (672.0 B) +RX errors 0 dropped 0 overruns 0 frame 0 +TX packets 16 bytes 2544 (2.4 KiB) +TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 + +lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 +inet 127.0.0.1 netmask 255.0.0.0 +inet6 ::1 prefixlen 128 scopeid 0x10<host> +loop txqueuelen 0 (Local Loopback) +RX packets 0 bytes 0 (0.0 B) +RX errors 0 dropped 0 overruns 0 frame 0 +TX packets 0 bytes 0 (0.0 B) +""" if __name__ == '__main__': unittest.main() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/WALinuxAgent-WALinuxAgent-2.0.13/tests/upload_status_blob.py new/WALinuxAgent-WALinuxAgent-2.0.14/tests/upload_status_blob.py --- old/WALinuxAgent-WALinuxAgent-2.0.13/tests/upload_status_blob.py 2015-06-01 03:55:11.000000000 +0200 +++ new/WALinuxAgent-WALinuxAgent-2.0.14/tests/upload_status_blob.py 2015-07-02 11:26:10.000000000 +0200 @@ -30,8 +30,14 @@ """ from status_blob_url import blockBlobUrl, pageBlobUrl +class MockConfig(object): + def get(self, keyName): + return None + +waagent.Config = MockConfig() + if __name__ == '__main__': waagent.LoggerInit('/dev/stdout', '/dev/null', verbose=True) status = "a" * 512 waagent.UploadStatusBlob(blockBlobUrl, status.encode("utf-8")) - waagent.UploadStatusBlob(pageBlobUrl, status.encode("utf-8")) + #waagent.UploadStatusBlob(pageBlobUrl, status.encode("utf-8")) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/WALinuxAgent-WALinuxAgent-2.0.13/waagent new/WALinuxAgent-WALinuxAgent-2.0.14/waagent --- old/WALinuxAgent-WALinuxAgent-2.0.13/waagent 2015-06-01 03:55:11.000000000 +0200 +++ new/WALinuxAgent-WALinuxAgent-2.0.14/waagent 2015-07-02 11:26:10.000000000 +0200 @@ -80,7 +80,7 @@ GuestAgentName = "WALinuxAgent" GuestAgentLongName = "Windows Azure Linux Agent" -GuestAgentVersion = "WALinuxAgent-2.0.13" +GuestAgentVersion = "WALinuxAgent-2.0.14" ProtocolVersion = "2012-11-30" #WARNING this value is used to confirm the correct fabric protocol. Config = None @@ -624,17 +624,24 @@ 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) + output = output.replace('\n', '') + match = re.search(r"(eth\d).*(HWaddr|ether) {0}".format(mac), + output, re.IGNORECASE) if match is None: raise Exception("Failed to get ifname with mac: {0}".format(mac)) - return match.group(1) + output = match.group(0) + eths = re.findall(r"eth\d", output) + if eths is None or len(eths) == 0: + raise Exception("Failed to get ifname with mac: {0}".format(mac)) + return eths[-1] - def configIpV4(self, ifName, addr): + def configIpV4(self, ifName, addr, netmask=24): 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)) + ret, output = RunGetOutput("ifconfig {0} {1}/{2}".format(ifName, addr, + netmask)) if ret != 0: raise Exception("Failed to config ipv4 for {0}: {1}".format(ifName, output)) @@ -1315,6 +1322,18 @@ return 0 ############################################################ +# KaliDistro - WIP +# Functioning on Kali 1.1.0a so far +############################################################ +class KaliDistro(debianDistro): + """ + Kali Distro concrete class + Put Kali specific behavior here... + """ + def __init__(self): + super(KaliDistro,self).__init__() + +############################################################ # UbuntuDistro ############################################################ ubuntu_upstart_file = """\ @@ -2526,18 +2545,22 @@ """ iface='' expected=16 # how many devices should I expect... - struct_size=40 # for 64bit the size is 40 bytes + is_64bits = sys.maxsize > 2**32 + struct_size=40 if is_64bits else 32 # for 64bit the size is 40 bytes, for 32bits it is 32 bytes. s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) buff=array.array('B', b'\0' * (expected*struct_size)) retsize=(struct.unpack('iL', fcntl.ioctl(s.fileno(), 0x8912, struct.pack('iL',expected*struct_size,buff.buffer_info()[0]))))[0] if retsize == (expected*struct_size) : Warn('SIOCGIFCONF returned more than ' + str(expected) + ' up network interfaces.') s=buff.tostring() + preferred_nic = Config.get("Network.Interface") for i in range(0,struct_size*expected,struct_size): iface=s[i:i+16].split(b'\0', 1)[0] if iface == b'lo': continue - else : + elif preferred_nic is None: + break + elif iface == preferred_nic: break return iface.decode('latin-1'), socket.inet_ntoa(s[i+20:i+24]) @@ -2722,8 +2745,9 @@ secure = False proxyHost, proxyPort = self.GetHttpProxy(secure) - resp = self._HttpRequest(method, host, path, port, data, - secure, headers, proxyHost, proxyPort) + resp = self._HttpRequest(method, host, path, port=port, data=data, + secure=secure, headers=headers, + proxyHost=proxyHost, proxyPort=proxyPort) for retry in range(0, maxRetry): if resp is not None and \ (resp.status == httplib.OK or \ @@ -2747,31 +2771,38 @@ Error("HTTP Err: Body={0}".format(resp.read())) time.sleep(self.__class__.RetryWaitingInterval) - resp = self._HttpRequest(method, host, path, data, secure, - headers, proxyHost, proxyPort) + resp = self._HttpRequest(method, host, path, port=port, data=data, + secure=secure, headers=headers, + proxyHost=proxyHost, proxyPort=proxyPort) return None def HttpGet(self, url, headers=None, maxRetry=3, chkProxy=False): - return self.HttpRequest("GET", url, None, headers, maxRetry, chkProxy) + return self.HttpRequest("GET", url, headers=headers, + maxRetry=maxRetry, chkProxy=chkProxy) def HttpHead(self, url, headers=None, maxRetry=3, chkProxy=False): - return self.HttpRequest("HEAD", url, None, headers, maxRetry, chkProxy) + return self.HttpRequest("HEAD", url, headers=headers, + maxRetry=maxRetry, chkProxy=chkProxy) def HttpPost(self, url, data, headers=None, maxRetry=3, chkProxy=False): - return self.HttpRequest("POST", url, data, headers, maxRetry, chkProxy) + return self.HttpRequest("POST", url, data=data, headers=headers, + maxRetry=maxRetry, chkProxy=chkProxy) def HttpPut(self, url, data, headers=None, maxRetry=3, chkProxy=False): - return self.HttpRequest("PUT", url, data, headers, maxRetry, chkProxy) + return self.HttpRequest("PUT", url, data=data, headers=headers, + maxRetry=maxRetry, chkProxy=chkProxy) def HttpDelete(self, url, headers=None, maxRetry=3, chkProxy=False): - return self.HttpRequest("DELETE", url, None, headers, maxRetry, chkProxy) + return self.HttpRequest("DELETE", url, headers=headers, + maxRetry=maxRetry, chkProxy=chkProxy) def HttpGetWithoutHeaders(self, url, maxRetry=3, chkProxy=False): """ Return data from an HTTP get on 'url'. """ - resp = self.HttpGet(url, None, maxRetry, chkProxy) + resp = self.HttpGet(url, headers=None, maxRetry=maxRetry, + chkProxy=chkProxy) return resp.read() if resp is not None else None def HttpGetWithHeaders(self, url, maxRetry=3, chkProxy=False): @@ -2780,10 +2811,10 @@ x-ms-agent-name and x-ms-version headers. """ - resp = self.HttpGet(url, { + resp = self.HttpGet(url, headers={ "x-ms-agent-name": GuestAgentName, "x-ms-version": ProtocolVersion - }, maxRetry, chkProxy) + }, maxRetry=maxRetry, chkProxy=chkProxy) return resp.read() if resp is not None else None def HttpSecureGetWithHeaders(self, url, transportCert, maxRetry=3, @@ -2791,21 +2822,22 @@ """ Return output of get using ssl cert. """ - resp = self.HttpGet(url, { + resp = self.HttpGet(url, headers={ "x-ms-agent-name": GuestAgentName, "x-ms-version": ProtocolVersion, "x-ms-cipher-name": "DES_EDE3_CBC", "x-ms-guest-agent-public-x509-cert": transportCert - }, maxRetry, chkProxy) + }, maxRetry=maxRetry, chkProxy=chkProxy) return resp.read() if resp is not None else None def HttpPostWithHeaders(self, url, data, maxRetry=3, chkProxy=False): - header = { + headers = { "x-ms-agent-name": GuestAgentName, "Content-Type": "text/xml; charset=utf-8", "x-ms-version": ProtocolVersion } - return self.HttpPost(url, data, header, maxRetry, chkProxy) + return self.HttpPost(url, data=data, headers=headers, + maxRetry=maxRetry, chkProxy=chkProxy) __StorageVersion="2014-02-14" @@ -2873,7 +2905,7 @@ bufSize = pageEnd - start buf = bytearray(bufSize) buf[0 : contentSize] = data[start : end] - ret = restutil.HttpPut(url, buf, { + ret = restutil.HttpPut(url, buffer(buf), { "x-ms-date" : timestamp, "x-ms-range" : "bytes={0}-{1}".format(start, pageEnd - 1), "x-ms-page-write" : "update", @@ -2956,12 +2988,13 @@ """ Parse amd store key:values in waagent.conf """ - def __init__(self): + def __init__(self, walaConfigFile): self.values = dict() if 'MyDistro' not in globals(): global MyDistro MyDistro = GetMyDistro() - walaConfigFile = MyDistro.getConfigurationPath() + if walaConfigFile is None: + walaConfigFile = MyDistro.getConfigurationPath() if os.path.isfile(walaConfigFile) == False: raise Exception("Missing configuration in {0}".format(walaConfigFile)) try: @@ -3239,35 +3272,6 @@ LogIfVerbose("Save SharedConfig.xml") SetFileContents("SharedConfig.xml", self.xmlText) - 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") if program != None: @@ -3277,9 +3281,105 @@ ErrorWithPrefix('Agent.Run','Exception: '+ str(e) +' occured launching ' + program ) def Process(self): - self.ConfigRdma() + global rdma_configured + if not rdma_configured and self.RdmaMacAddress is not None and self.RdmaIPv4Address is not None: + handler = RdmaHandler(self.RdmaMacAddress, self.RdmaIPv4Address) + handler.start() + rdma_configured = True self.InvokeTopologyConsumer() +rdma_configured = False + +class RdmaError(Exception): + pass + +class RdmaHandler(object): + """ + Handle rdma configuration. + """ + + def __init__(self, mac, ip_addr, dev="/dev/hvnd_rdma", + dat_conf_files=['/etc/dat.conf', '/etc/rdma/dat.conf', + '/usr/local/etc/dat.conf']): + self.mac = mac + self.ip_addr = ip_addr + self.dev = dev + self.dat_conf_files = dat_conf_files + self.data = ('rdmaMacAddress="{0}" rdmaIPv4Address="{1}"' + '').format(self.mac, self.ip_addr) + + def start(self): + """ + Start a new thread to process rdma + """ + threading.Thread(target=self.process).start() + + def process(self): + try: + self.set_dat_conf() + self.set_rdma_dev() + self.set_rdma_ip() + except RdmaError as e: + Error("Failed to config rdma device: {0}".format(e)) + + def set_dat_conf(self): + """ + Agent needs to search all possible locations for dat.conf + """ + Log("Set dat.conf") + for dat_conf_file in self.dat_conf_files: + if not os.path.isfile(dat_conf_file): + continue + try: + self.write_dat_conf(dat_conf_file) + except IOError as e: + raise RdmaError("Failed to write to dat.conf: {0}".format(e)) + + def write_dat_conf(self, dat_conf_file): + Log("Write config to {0}".format(dat_conf_file)) + 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.ip_addr) + lines = GetFileContents(dat_conf_file) + lines = re.sub(old, new, lines) + SetFileContents(dat_conf_file, lines) + + def set_rdma_dev(self): + """ + Write config string to /dev/hvnd_rdma + """ + Log("Set /dev/hvnd_rdma") + self.wait_rdma_dev() + self.write_rdma_dev_conf() + + def write_rdma_dev_conf(self): + Log("Write rdma config to {0}: {1}".format(self.dev, self.data)) + try: + with open(self.dev, "w") as c: + c.write(self.data) + except IOError, e: + raise RdmaError("Error writing {0}, {1}".format(self.dev, e)) + + def wait_rdma_dev(self): + Log("Wait for /dev/hvnd_rdma") + retry = 0 + while retry < 120: + if os.path.exists(self.dev): + return + time.sleep(1) + retry += 1 + raise RdmaError("The device doesn't show up in 120 seconds") + + def set_rdma_ip(self): + Log("Set ip addr for rdma") + try: + if_name = MyDistro.getInterfaceNameByMac(self.mac) + #Azure is using 12 bits network mask for infiniband. + MyDistro.configIpV4(if_name, self.ip_addr, 12) + except Exception as e: + raise RdmaError("Failed to config rdma device: {0}".format(e)) + class ExtensionsConfig(object): """ Parse ExtensionsConfig, downloading and unpacking them to /var/lib/waagent. @@ -5884,6 +5984,7 @@ if MyDistro == None : sys.exit(1) args = [] + conf_file = None global force force = False for a in sys.argv[1:]: @@ -5896,6 +5997,8 @@ myLogger.verbose = True elif re.match("^([-/]*)force", a): force = True + elif re.match("^(?:[-/]*)conf=.+", a): + conf_file = re.match("^(?:[-/]*)conf=(.+)", a).groups()[0] elif re.match("^([-/]*)(setup|install)", a): sys.exit(MyDistro.Install()) elif re.match("^([-/]*)(uninstall)", a): @@ -5903,8 +6006,14 @@ else: args.append(a) global Config - Config = ConfigurationProvider() + Config = ConfigurationProvider(conf_file) + logfile = Config.get("Logs.File") + if logfile is not None: + myLogger.file_path = logfile + logconsole = Config.get("Logs.Console") + if logconsole is not None and logconsole.lower().startswith("n"): + myLogger.con_path = None verbose = Config.get("Logs.Verbose") if verbose != None and verbose.lower().startswith("y"): myLogger.verbose=True
