Repository: Azure/WALinuxAgent
Pull request #375 (2016-08-18 20:40:27)

Host channel fix
VM status is not being passed to the host channel plugin correctly, resulting in the following message:

`WARNING Agent WALinuxAgent-2.1.6 failed with exception: must be convertible to a buffer, not VMStatus`

- fix the issue (#360)
- minor logging tweak
- add unit test
- update the agent version to 2.1.6.1

/cc @ahmetalpbalkan 

msftclas: Hi __@hglkrijger__, I'm your friendly neighborhood Microsoft Pull Request Bot (You can call me MSBOT). Thanks for your contribution!
    <p>
        It looks like you're a Microsoft contributor (Hans Krijger). If you're full-time, we DON'T require a Contribution License Agreement. If you are a vendor, please DO sign the electronic Contribution License Agreement. It will take 2 minutes and there's no faxing! https://cla.microsoft.com.
    </p>

TTYL, MSBOT;

ahmetalpbalkan: LGTM 

Patch:
diff --git a/azurelinuxagent/common/protocol/hostplugin.py b/azurelinuxagent/common/protocol/hostplugin.py
index 65696046..66d58898 100644
--- a/azurelinuxagent/common/protocol/hostplugin.py
+++ b/azurelinuxagent/common/protocol/hostplugin.py
@@ -72,7 +72,8 @@ class HostPluginProtocol(object):
             logger.error("no status data was provided")
             return
         url = URI_FORMAT_PUT_VM_STATUS.format(self.endpoint, HOST_PLUGIN_PORT)
-        status = textutil.b64encode(status_blob.vm_status)
+        logger.verbose("Posting VM status to host channel [{0}]".format(url))
+        status = textutil.b64encode(status_blob.vm_status.vmAgent.status)
         headers = {"x-ms-version": API_VERSION}
         blob_headers = [{'headerName': 'x-ms-version',
                          'headerValue': status_blob.__storage_version__},
@@ -80,7 +81,6 @@ class HostPluginProtocol(object):
                          'headerValue': status_blob.type}]
         data = json.dumps({'requestUri': sas_url, 'headers': blob_headers,
                            'content': status}, sort_keys=True)
-        logger.info("put VM status at [{0}]".format(url))
         try:
             response = restutil.http_put(url, data, headers)
             if response.status != httpclient.OK:
diff --git a/azurelinuxagent/common/version.py b/azurelinuxagent/common/version.py
index 9d60b210..0ba078eb 100644
--- a/azurelinuxagent/common/version.py
+++ b/azurelinuxagent/common/version.py
@@ -51,7 +51,7 @@ def get_distro():
 
 AGENT_NAME = "WALinuxAgent"
 AGENT_LONG_NAME = "Azure Linux Agent"
-AGENT_VERSION = '2.1.6'
+AGENT_VERSION = '2.1.6.1'
 AGENT_LONG_VERSION = "{0}-{1}".format(AGENT_NAME, AGENT_VERSION)
 AGENT_DESCRIPTION = """\
 The Azure Linux Agent supports the provisioning and running of Linux


Test patch:
diff --git a/tests/protocol/test_hostplugin.py b/tests/protocol/test_hostplugin.py
index 65c84659..296a1f58 100644
--- a/tests/protocol/test_hostplugin.py
+++ b/tests/protocol/test_hostplugin.py
@@ -15,10 +15,11 @@
 # Requires Python 2.4+ and Openssl 1.0+
 #
 
-from tests.tools import *
 import unittest
-import azurelinuxagent.common.protocol.wire as wire
+
 import azurelinuxagent.common.protocol.restapi as restapi
+import azurelinuxagent.common.protocol.wire as wire
+from tests.tools import *
 
 wireserver_url = "168.63.129.16"
 sas_url = "http://sas_url"
@@ -39,6 +40,29 @@ class TestHostPlugin(AgentTestCase):
                                 "Fallback was not engaged")
                 self.assertTrue(patch_put.call_args[0][1] == sas_url)
 
+    def test_fallback_data(self):
+        from azurelinuxagent.common.protocol.hostplugin import API_VERSION
+        from azurelinuxagent.common.utils import restutil
+        exp_method = 'PUT'
+        exp_url = 'http://{0}:32526/status'.format(wireserver_url)
+        exp_data = '{"content": "UmVhZHk=", "headers": [{"headerName": ' \
+                   '"x-ms-version", "headerValue": "2014-02-14"}, ' \
+                   '{"headerName": "x-ms-blob-type", "headerValue": null}], ' \
+                   '"requestUri": "http://sas_url"}'
+        with patch.object(restutil, "http_request") as patch_http:
+            wire_protocol_client = wire.WireProtocol(wireserver_url).client
+            plugin = wire_protocol_client.host_plugin
+            blob = wire_protocol_client.status_blob
+            blob.vm_status = restapi.VMStatus()
+            blob.vm_status.vmAgent.status = 'Ready'
+            with patch.object(plugin, "get_api_versions") as patch_api:
+                patch_api.return_value = API_VERSION
+                plugin.put_vm_status(blob, sas_url)
+                self.assertTrue(patch_http.call_count == 1)
+                self.assertTrue(patch_http.call_args[0][0] == exp_method)
+                self.assertTrue(patch_http.call_args[0][1] == exp_url)
+                self.assertTrue(patch_http.call_args[0][2] == exp_data)
+
     def test_no_fallback(self):
         with patch.object(wire.HostPluginProtocol,
                           "put_vm_status") as patch_put:
@@ -65,7 +89,8 @@ class TestHostPlugin(AgentTestCase):
         self.assertFalse(host_client.is_initialized)
         self.assertTrue(host_client.api_versions is None)
         status_blob = wire.StatusBlob(None)
-        status_blob.vm_status = "ok"
+        status_blob.vm_status = restapi.VMStatus()
+        status_blob.vm_status.vmAgent.status = 'ok'
         status_blob.type = "BlockBlob"
         with patch.object(wire.HostPluginProtocol,
                           "get_api_versions") as patch_get: