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


Reply via email to