summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/common/test_event.py91
-rw-r--r--tests/common/test_version.py16
-rw-r--r--tests/daemon/test_daemon.py3
-rw-r--r--tests/data/ga/WALinuxAgent-2.2.4.zipbin403507 -> 0 bytes
-rw-r--r--tests/data/ga/WALinuxAgent-2.2.8.zipbin0 -> 415285 bytes
-rw-r--r--tests/ga/test_update.py32
-rw-r--r--tests/protocol/test_hostplugin.py326
-rw-r--r--tests/protocol/test_wire.py65
8 files changed, 442 insertions, 91 deletions
diff --git a/tests/common/test_event.py b/tests/common/test_event.py
new file mode 100644
index 0000000..f535411
--- /dev/null
+++ b/tests/common/test_event.py
@@ -0,0 +1,91 @@
+# Copyright 2017 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 __future__ import print_function
+
+from azurelinuxagent.common.event import init_event_logger, add_event
+from azurelinuxagent.common.future import ustr
+from tests.tools import *
+
+
+class TestEvent(AgentTestCase):
+ def test_save_event(self):
+ tmp_evt = tempfile.mkdtemp()
+ init_event_logger(tmp_evt)
+ add_event('test', message='test event')
+ self.assertTrue(len(os.listdir(tmp_evt)) == 1)
+ shutil.rmtree(tmp_evt)
+
+ def test_save_event_rollover(self):
+ tmp_evt = tempfile.mkdtemp()
+ init_event_logger(tmp_evt)
+ add_event('test', message='first event')
+ for i in range(0, 999):
+ add_event('test', message='test event {0}'.format(i))
+
+ events = os.listdir(tmp_evt)
+ events.sort()
+ self.assertTrue(len(events) == 1000)
+
+ first_event = os.path.join(tmp_evt, events[0])
+ with open(first_event) as first_fh:
+ first_event_text = first_fh.read()
+ self.assertTrue('first event' in first_event_text)
+
+ add_event('test', message='last event')
+ events = os.listdir(tmp_evt)
+ events.sort()
+ self.assertTrue(len(events) == 1000, "{0} events found, 1000 expected".format(len(events)))
+
+ first_event = os.path.join(tmp_evt, events[0])
+ with open(first_event) as first_fh:
+ first_event_text = first_fh.read()
+ self.assertFalse('first event' in first_event_text)
+ self.assertTrue('test event 0' in first_event_text)
+
+ last_event = os.path.join(tmp_evt, events[-1])
+ with open(last_event) as last_fh:
+ last_event_text = last_fh.read()
+ self.assertTrue('last event' in last_event_text)
+
+ shutil.rmtree(tmp_evt)
+
+ def test_save_event_cleanup(self):
+ tmp_evt = tempfile.mkdtemp()
+ init_event_logger(tmp_evt)
+
+ for i in range(0, 2000):
+ evt = os.path.join(tmp_evt, '{0}.tld'.format(ustr(1491004920536531 + i)))
+ with open(evt, 'w') as fh:
+ fh.write('test event {0}'.format(i))
+
+ events = os.listdir(tmp_evt)
+ self.assertTrue(len(events) == 2000, "{0} events found, 2000 expected".format(len(events)))
+ add_event('test', message='last event')
+
+ events = os.listdir(tmp_evt)
+ events.sort()
+ self.assertTrue(len(events) == 1000, "{0} events found, 1000 expected".format(len(events)))
+ first_event = os.path.join(tmp_evt, events[0])
+ with open(first_event) as first_fh:
+ first_event_text = first_fh.read()
+ self.assertTrue('test event 1001' in first_event_text)
+
+ last_event = os.path.join(tmp_evt, events[-1])
+ with open(last_event) as last_fh:
+ last_event_text = last_fh.read()
+ self.assertTrue('last event' in last_event_text)
diff --git a/tests/common/test_version.py b/tests/common/test_version.py
index df4f0e3..c01430b 100644
--- a/tests/common/test_version.py
+++ b/tests/common/test_version.py
@@ -21,8 +21,9 @@ import textwrap
import mock
-import azurelinuxagent.common.version as version
-from azurelinuxagent.common.version import *
+from azurelinuxagent.common.version import set_current_agent, \
+ AGENT_LONG_VERSION, AGENT_VERSION, AGENT_NAME, AGENT_NAME_PATTERN, \
+ get_f5_platform
from tests.tools import *
@@ -67,6 +68,7 @@ class TestCurrentAgentName(AgentTestCase):
self.assertEqual(version, str(current_version))
return
+
class TestGetF5Platforms(AgentTestCase):
def test_get_f5_platform_bigip_12_1_1(self):
version_file = textwrap.dedent("""
@@ -83,7 +85,7 @@ class TestGetF5Platforms(AgentTestCase):
mo = mock.mock_open(read_data=version_file)
with patch(open_patch(), mo):
- platform = version.get_f5_platform()
+ platform = get_f5_platform()
self.assertTrue(platform[0] == 'bigip')
self.assertTrue(platform[1] == '12.1.1')
self.assertTrue(platform[2] == 'bigip')
@@ -104,7 +106,7 @@ class TestGetF5Platforms(AgentTestCase):
mo = mock.mock_open(read_data=version_file)
with patch(open_patch(), mo):
- platform = version.get_f5_platform()
+ platform = get_f5_platform()
self.assertTrue(platform[0] == 'bigip')
self.assertTrue(platform[1] == '12.1.0')
self.assertTrue(platform[2] == 'bigip')
@@ -125,7 +127,7 @@ class TestGetF5Platforms(AgentTestCase):
mo = mock.mock_open(read_data=version_file)
with patch(open_patch(), mo):
- platform = version.get_f5_platform()
+ platform = get_f5_platform()
self.assertTrue(platform[0] == 'bigip')
self.assertTrue(platform[1] == '12.0.0')
self.assertTrue(platform[2] == 'bigip')
@@ -146,7 +148,7 @@ class TestGetF5Platforms(AgentTestCase):
mo = mock.mock_open(read_data=version_file)
with patch(open_patch(), mo):
- platform = version.get_f5_platform()
+ platform = get_f5_platform()
self.assertTrue(platform[0] == 'iworkflow')
self.assertTrue(platform[1] == '2.0.1')
self.assertTrue(platform[2] == 'iworkflow')
@@ -167,7 +169,7 @@ class TestGetF5Platforms(AgentTestCase):
mo = mock.mock_open(read_data=version_file)
with patch(open_patch(), mo):
- platform = version.get_f5_platform()
+ platform = get_f5_platform()
self.assertTrue(platform[0] == 'bigiq')
self.assertTrue(platform[1] == '5.1.0')
self.assertTrue(platform[2] == 'bigiq')
diff --git a/tests/daemon/test_daemon.py b/tests/daemon/test_daemon.py
index 77b4e3e..dd31fd7 100644
--- a/tests/daemon/test_daemon.py
+++ b/tests/daemon/test_daemon.py
@@ -14,8 +14,7 @@
#
# Requires Python 2.4+ and Openssl 1.0+
#
-
-from azurelinuxagent.daemon import *
+from azurelinuxagent.daemon import get_daemon_handler
from tests.tools import *
diff --git a/tests/data/ga/WALinuxAgent-2.2.4.zip b/tests/data/ga/WALinuxAgent-2.2.4.zip
deleted file mode 100644
index fd48991..0000000
--- a/tests/data/ga/WALinuxAgent-2.2.4.zip
+++ /dev/null
Binary files differ
diff --git a/tests/data/ga/WALinuxAgent-2.2.8.zip b/tests/data/ga/WALinuxAgent-2.2.8.zip
new file mode 100644
index 0000000..04c60a8
--- /dev/null
+++ b/tests/data/ga/WALinuxAgent-2.2.8.zip
Binary files differ
diff --git a/tests/ga/test_update.py b/tests/ga/test_update.py
index 5277e59..e7a7af4 100644
--- a/tests/ga/test_update.py
+++ b/tests/ga/test_update.py
@@ -522,7 +522,8 @@ class TestGuestAgent(UpdateTestCase):
self.assertFalse(os.path.isdir(self.agent_path))
mock_http_get.return_value = ResponseMock(
- status=restutil.httpclient.SERVICE_UNAVAILABLE)
+ status=restutil.httpclient.SERVICE_UNAVAILABLE,
+ response="")
ext_uri = 'ext_uri'
host_uri = 'host_uri'
@@ -1039,7 +1040,7 @@ class TestUpdate(UpdateTestCase):
with patch('subprocess.Popen', return_value=mock_child) as mock_popen:
with patch('time.time', side_effect=mock_time.time):
- with patch('time.sleep', return_value=mock_time.sleep):
+ with patch('time.sleep', side_effect=mock_time.sleep):
self.update_handler.run_latest()
self.assertEqual(1, mock_popen.call_count)
@@ -1082,7 +1083,22 @@ class TestUpdate(UpdateTestCase):
self._test_run_latest(mock_child=mock_child, mock_time=mock_time)
self.assertEqual(1, mock_child.poll.call_count)
self.assertEqual(0, mock_child.wait.call_count)
- self.assertEqual(2, mock_time.time_call_count)
+ return
+
+ def test_run_latest_polls_frequently_if_installed_is_latest(self):
+ mock_child = ChildMock(return_value=0)
+ mock_time = TimeMock(time_increment=CHILD_HEALTH_INTERVAL/2)
+ self._test_run_latest(mock_time=mock_time)
+ self.assertEqual(1, mock_time.sleep_interval)
+ return
+
+ def test_run_latest_polls_moderately_if_installed_not_latest(self):
+ self.prepare_agents()
+
+ mock_child = ChildMock(return_value=0)
+ mock_time = TimeMock(time_increment=CHILD_HEALTH_INTERVAL/2)
+ self._test_run_latest(mock_time=mock_time)
+ self.assertNotEqual(1, mock_time.sleep_interval)
return
def test_run_latest_defaults_to_current(self):
@@ -1137,7 +1153,6 @@ class TestUpdate(UpdateTestCase):
return
def test_run_latest_exception_blacklists(self):
- # logger.add_logger_appender(logger.AppenderType.STDOUT)
self.prepare_agents()
latest_agent = self.update_handler.get_latest_agent()
@@ -1371,9 +1386,10 @@ class ProtocolMock(object):
class ResponseMock(Mock):
- def __init__(self, status=restutil.httpclient.OK, response=None):
+ def __init__(self, status=restutil.httpclient.OK, response=None, reason=None):
Mock.__init__(self)
self.status = status
+ self.reason = reason
self.response = response
return
@@ -1388,7 +1404,11 @@ class TimeMock(Mock):
self.time_call_count = 0
self.time_increment = time_increment
- self.sleep = Mock(return_value=0)
+ self.sleep_interval = None
+ return
+
+ def sleep(self, n):
+ self.sleep_interval = n
return
def time(self):
diff --git a/tests/protocol/test_hostplugin.py b/tests/protocol/test_hostplugin.py
index 1298fdc..ef91998 100644
--- a/tests/protocol/test_hostplugin.py
+++ b/tests/protocol/test_hostplugin.py
@@ -15,123 +15,314 @@
# Requires Python 2.4+ and Openssl 1.0+
#
-import unittest
+import base64
+import json
+import sys
+
+
+
+if sys.version_info[0] == 3:
+ import http.client as httpclient
+ bytebuffer = memoryview
+elif sys.version_info[0] == 2:
+ import httplib as httpclient
+ bytebuffer = buffer
import azurelinuxagent.common.protocol.restapi as restapi
import azurelinuxagent.common.protocol.wire as wire
import azurelinuxagent.common.protocol.hostplugin as hostplugin
+
+from azurelinuxagent.common import event
+from azurelinuxagent.common.protocol.hostplugin import API_VERSION
+from azurelinuxagent.common.utils import restutil
+
from tests.protocol.mockwiredata import WireProtocolData, DATA_FILE
from tests.tools import *
-wireserver_url = "168.63.129.16"
+hostplugin_status_url = "http://168.63.129.16:32526/status"
sas_url = "http://sas_url"
-testtype = 'BlockBlob'
+wireserver_url = "168.63.129.16"
+
+block_blob_type = 'BlockBlob'
+page_blob_type = 'PageBlob'
+
api_versions = '["2015-09-01"]'
+storage_version = "2014-02-14"
+faux_status = "{ 'dummy' : 'data' }"
+faux_status_b64 = base64.b64encode(bytes(bytearray(faux_status, encoding='utf-8')))
+if PY_VERSION_MAJOR > 2:
+ faux_status_b64 = faux_status_b64.decode('utf-8')
class TestHostPlugin(AgentTestCase):
+
+ def _compare_data(self, actual, expected):
+ for k in iter(expected.keys()):
+ if k == 'content' or k == 'requestUri':
+ if actual[k] != expected[k]:
+ print("Mismatch: Actual '{0}'='{1}', " \
+ "Expected '{0}'='{3}'".format(
+ k, actual[k], expected[k]))
+ return False
+ elif k == 'headers':
+ for h in expected['headers']:
+ if not (h in actual['headers']):
+ print("Missing Header: '{0}'".format(h))
+ return False
+ else:
+ print("Unexpected Key: '{0}'".format(k))
+ return False
+ return True
+
+ def _hostplugin_data(self, blob_headers, content=None):
+ headers = []
+ for name in iter(blob_headers.keys()):
+ headers.append({
+ 'headerName': name,
+ 'headerValue': blob_headers[name]
+ })
+
+ data = {
+ 'requestUri': sas_url,
+ 'headers': headers
+ }
+ if not content is None:
+ s = base64.b64encode(bytes(content))
+ if PY_VERSION_MAJOR > 2:
+ s = s.decode('utf-8')
+ data['content'] = s
+ return data
+
+ def _hostplugin_headers(self, goal_state):
+ return {
+ 'x-ms-version': '2015-09-01',
+ 'Content-type': 'application/json',
+ 'x-ms-containerid': goal_state.container_id,
+ 'x-ms-host-config-name': goal_state.role_config_name
+ }
+
+ def _validate_hostplugin_args(self, args, goal_state, exp_method, exp_url, exp_data):
+ args, kwargs = args
+ self.assertEqual(exp_method, args[0])
+ self.assertEqual(exp_url, args[1])
+ self.assertTrue(self._compare_data(json.loads(args[2]), exp_data))
+
+ headers = kwargs['headers']
+ self.assertEqual(headers['x-ms-containerid'], goal_state.container_id)
+ self.assertEqual(headers['x-ms-host-config-name'], goal_state.role_config_name)
+
def test_fallback(self):
"""
- Validate fallback to upload status using HostGAPlugin is happening when status reporting via
- default method is unsuccessful
+ Validate fallback to upload status using HostGAPlugin is happening when
+ status reporting via default method is unsuccessful
"""
test_goal_state = wire.GoalState(WireProtocolData(DATA_FILE).goal_state)
-
- with patch.object(wire.HostPluginProtocol, "put_vm_status") as patch_put:
+ status = restapi.VMStatus(status="Ready", message="Guest Agent is running")
+ with patch.object(wire.HostPluginProtocol,
+ "ensure_initialized",
+ return_value=True):
with patch.object(wire.StatusBlob, "upload", return_value=False) as patch_upload:
- wire_protocol_client = wire.WireProtocol(wireserver_url).client
- wire_protocol_client.get_goal_state = Mock(return_value=test_goal_state)
- wire_protocol_client.ext_conf = wire.ExtensionsConfig(None)
- wire_protocol_client.ext_conf.status_upload_blob = sas_url
- wire_protocol_client.upload_status_blob()
- self.assertTrue(patch_put.call_count == 1,
- "Fallback was not engaged")
- self.assertTrue(patch_put.call_args[0][1] == sas_url)
+ with patch.object(wire.HostPluginProtocol,
+ "_put_page_blob_status") as patch_put:
+ wire_protocol_client = wire.WireProtocol(wireserver_url).client
+ wire_protocol_client.get_goal_state = Mock(return_value=test_goal_state)
+ wire_protocol_client.ext_conf = wire.ExtensionsConfig(None)
+ wire_protocol_client.ext_conf.status_upload_blob = sas_url
+ wire_protocol_client.status_blob.set_vm_status(status)
+ wire_protocol_client.upload_status_blob()
+ self.assertTrue(patch_put.call_count == 1,
+ "Fallback was not engaged")
+ self.assertTrue(patch_put.call_args[0][0] == sas_url)
+ self.assertTrue(wire.HostPluginProtocol.is_default_channel())
+ wire.HostPluginProtocol.set_default_channel(False)
+
+ def test_fallback_failure(self):
+ """
+ Validate that when host plugin fails, the default channel is reset
+ """
+ test_goal_state = wire.GoalState(WireProtocolData(DATA_FILE).goal_state)
+ status = restapi.VMStatus(status="Ready",
+ message="Guest Agent is running")
+ with patch.object(wire.HostPluginProtocol,
+ "ensure_initialized",
+ return_value=True):
+ with patch.object(wire.StatusBlob,
+ "upload",
+ return_value=False):
+ with patch.object(wire.HostPluginProtocol,
+ "_put_page_blob_status",
+ side_effect=wire.HttpError("put failure")) as patch_put:
+ client = wire.WireProtocol(wireserver_url).client
+ client.get_goal_state = Mock(return_value=test_goal_state)
+ client.ext_conf = wire.ExtensionsConfig(None)
+ client.ext_conf.status_upload_blob = sas_url
+ client.status_blob.set_vm_status(status)
+ client.upload_status_blob()
+ self.assertTrue(patch_put.call_count == 1,
+ "Fallback was not engaged")
+ self.assertFalse(wire.HostPluginProtocol.is_default_channel())
+
+ def test_put_status_error_reporting(self):
+ """
+ Validate the telemetry when uploading status fails
+ """
+ test_goal_state = wire.GoalState(WireProtocolData(DATA_FILE).goal_state)
+ status = restapi.VMStatus(status="Ready",
+ message="Guest Agent is running")
+ with patch.object(wire.StatusBlob,
+ "upload",
+ return_value=False):
+ wire_protocol_client = wire.WireProtocol(wireserver_url).client
+ wire_protocol_client.get_goal_state = Mock(return_value=test_goal_state)
+ wire_protocol_client.ext_conf = wire.ExtensionsConfig(None)
+ wire_protocol_client.ext_conf.status_upload_blob = sas_url
+ wire_protocol_client.status_blob.set_vm_status(status)
+ put_error = wire.HttpError("put status http error")
+ with patch.object(event,
+ "add_event") as patch_add_event:
+ with patch.object(restutil,
+ "http_put",
+ side_effect=put_error) as patch_http_put:
+ with patch.object(wire.HostPluginProtocol,
+ "ensure_initialized", return_value=True):
+ wire_protocol_client.upload_status_blob()
+ self.assertFalse(wire.HostPluginProtocol.is_default_channel())
+ self.assertTrue(patch_add_event.call_count == 1)
+
def test_validate_http_request(self):
"""Validate correct set of data is sent to HostGAPlugin when reporting VM status"""
- 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": "eyJkdW1teSI6ICJkYXRhIn0=", "headers": [{"headerName": ' \
- '"x-ms-version", "headerValue": "2014-02-14"}, ' \
- '{"headerName": "x-ms-blob-type", "headerValue": "BlockBlob"}], ' \
- '"requestUri": "http://sas_url"}'
+
+ wire_protocol_client = wire.WireProtocol(wireserver_url).client
test_goal_state = wire.GoalState(WireProtocolData(DATA_FILE).goal_state)
+ status_blob = wire_protocol_client.status_blob
+ status_blob.data = faux_status
+ status_blob.vm_status = restapi.VMStatus(message="Ready", status="Ready")
+
+ exp_method = 'PUT'
+ exp_url = hostplugin_status_url
+ exp_data = self._hostplugin_data(
+ status_blob.get_block_blob_headers(len(faux_status)),
+ bytearray(faux_status, encoding='utf-8'))
+
with patch.object(restutil, "http_request") as patch_http:
- wire_protocol_client = wire.WireProtocol(wireserver_url).client
wire_protocol_client.get_goal_state = Mock(return_value=test_goal_state)
plugin = wire_protocol_client.get_host_plugin()
- blob = wire_protocol_client.status_blob
- blob.vm_status = restapi.VMStatus(message="Ready", status="Ready")
- blob.data = '{"dummy": "data"}'
+
with patch.object(plugin, 'get_api_versions') as patch_api:
patch_api.return_value = API_VERSION
- plugin.put_vm_status(blob, sas_url, testtype)
- 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)
+ plugin.put_vm_status(status_blob, sas_url, block_blob_type)
- # Assert headers
- headers = patch_http.call_args[1]['headers']
- self.assertEqual(headers['x-ms-containerid'], test_goal_state.container_id)
- self.assertEqual(headers['x-ms-host-config-name'], test_goal_state.role_config_name)
+ self.assertTrue(patch_http.call_count == 1)
+ self._validate_hostplugin_args(
+ patch_http.call_args_list[0],
+ test_goal_state,
+ exp_method, exp_url, exp_data)
def test_no_fallback(self):
"""
- Validate fallback to upload status using HostGAPlugin is not happening when status reporting via
- default method is successful
+ Validate fallback to upload status using HostGAPlugin is not happening
+ when status reporting via default method is successful
"""
- with patch.object(wire.HostPluginProtocol,
- "put_vm_status") as patch_put:
+ vmstatus = restapi.VMStatus(message="Ready", status="Ready")
+ with patch.object(wire.HostPluginProtocol, "put_vm_status") as patch_put:
with patch.object(wire.StatusBlob, "upload") as patch_upload:
patch_upload.return_value = True
wire_protocol_client = wire.WireProtocol(wireserver_url).client
wire_protocol_client.ext_conf = wire.ExtensionsConfig(None)
wire_protocol_client.ext_conf.status_upload_blob = sas_url
+ wire_protocol_client.status_blob.vm_status = vmstatus
wire_protocol_client.upload_status_blob()
- self.assertTrue(patch_put.call_count == 0,
- "Fallback was engaged")
+ self.assertTrue(patch_put.call_count == 0, "Fallback was engaged")
- def test_validate_http_put(self):
+ def test_validate_block_blob(self):
"""Validate correct set of data is sent to HostGAPlugin when reporting VM status"""
+ wire_protocol_client = wire.WireProtocol(wireserver_url).client
test_goal_state = wire.GoalState(WireProtocolData(DATA_FILE).goal_state)
- expected_url = "http://168.63.129.16:32526/status"
- expected_headers = {'x-ms-version': '2015-09-01',
- "Content-type": "application/json",
- "x-ms-containerid": test_goal_state.container_id,
- "x-ms-host-config-name": test_goal_state.role_config_name}
- expected_content = '{"content": "eyJkdW1teSI6ICJkYXRhIn0=", ' \
- '"headers": [{"headerName": "x-ms-version", ' \
- '"headerValue": "2014-02-14"}, ' \
- '{"headerName": "x-ms-blob-type", "headerValue": ' \
- '"BlockBlob"}], ' \
- '"requestUri": "http://sas_url"}'
host_client = wire.HostPluginProtocol(wireserver_url,
test_goal_state.container_id,
test_goal_state.role_config_name)
self.assertFalse(host_client.is_initialized)
self.assertTrue(host_client.api_versions is None)
- status_blob = wire.StatusBlob(None)
+
+ status_blob = wire_protocol_client.status_blob
+ status_blob.data = faux_status
+ status_blob.type = block_blob_type
status_blob.vm_status = restapi.VMStatus(message="Ready", status="Ready")
- status_blob.data = '{"dummy": "data"}'
- status_blob.type = "BlockBlob"
- with patch.object(wire.HostPluginProtocol,
+
+ exp_method = 'PUT'
+ exp_url = hostplugin_status_url
+ exp_data = self._hostplugin_data(
+ status_blob.get_block_blob_headers(len(faux_status)),
+ bytearray(faux_status, encoding='utf-8'))
+
+ with patch.object(restutil, "http_request") as patch_http:
+ with patch.object(wire.HostPluginProtocol,
"get_api_versions") as patch_get:
- patch_get.return_value = api_versions
- with patch.object(restapi.restutil, "http_put") as patch_put:
- patch_put.return_value = MagicMock()
+ patch_get.return_value = api_versions
+ host_client.put_vm_status(status_blob, sas_url)
+
+ self.assertTrue(patch_http.call_count == 1)
+ self._validate_hostplugin_args(
+ patch_http.call_args_list[0],
+ test_goal_state,
+ exp_method, exp_url, exp_data)
+
+ def test_validate_page_blobs(self):
+ """Validate correct set of data is sent for page blobs"""
+ wire_protocol_client = wire.WireProtocol(wireserver_url).client
+ test_goal_state = wire.GoalState(WireProtocolData(DATA_FILE).goal_state)
+
+ host_client = wire.HostPluginProtocol(wireserver_url,
+ test_goal_state.container_id,
+ test_goal_state.role_config_name)
+
+ self.assertFalse(host_client.is_initialized)
+ self.assertTrue(host_client.api_versions is None)
+
+ status_blob = wire_protocol_client.status_blob
+ status_blob.data = faux_status
+ status_blob.type = page_blob_type
+ status_blob.vm_status = restapi.VMStatus(message="Ready", status="Ready")
+
+ exp_method = 'PUT'
+ exp_url = hostplugin_status_url
+
+ page_status = bytearray(status_blob.data, encoding='utf-8')
+ page_size = int((len(page_status) + 511) / 512) * 512
+ page_status = bytearray(status_blob.data.ljust(page_size), encoding='utf-8')
+ page = bytearray(page_size)
+ page[0: page_size] = page_status[0: len(page_status)]
+ mock_response = MockResponse('', httpclient.OK)
+
+ with patch.object(restutil, "http_request",
+ return_value=mock_response) as patch_http:
+ with patch.object(wire.HostPluginProtocol,
+ "get_api_versions") as patch_get:
+ patch_get.return_value = api_versions
host_client.put_vm_status(status_blob, sas_url)
- self.assertTrue(host_client.is_initialized)
- self.assertFalse(host_client.api_versions is None)
- self.assertTrue(patch_put.call_count == 1)
- self.assertTrue(patch_put.call_args[0][0] == expected_url)
- self.assertTrue(patch_put.call_args[1]['data'] == expected_content)
- self.assertTrue(patch_put.call_args[1]['headers'] == expected_headers)
+
+ self.assertTrue(patch_http.call_count == 2)
+
+ exp_data = self._hostplugin_data(
+ status_blob.get_page_blob_create_headers(
+ page_size))
+ self._validate_hostplugin_args(
+ patch_http.call_args_list[0],
+ test_goal_state,
+ exp_method, exp_url, exp_data)
+
+ exp_data = self._hostplugin_data(
+ status_blob.get_page_blob_page_headers(
+ 0, page_size),
+ page)
+ exp_data['requestUri'] += "?comp=page"
+ self._validate_hostplugin_args(
+ patch_http.call_args_list[1],
+ test_goal_state,
+ exp_method, exp_url, exp_data)
def test_validate_get_extension_artifacts(self):
test_goal_state = wire.GoalState(WireProtocolData(DATA_FILE).goal_state)
@@ -155,6 +346,7 @@ class TestHostPlugin(AgentTestCase):
for k in expected_headers:
self.assertTrue(k in actual_headers)
self.assertEqual(expected_headers[k], actual_headers[k])
+
class MockResponse:
def __init__(self, body, status_code):
diff --git a/tests/protocol/test_wire.py b/tests/protocol/test_wire.py
index e083678..dda7a2b 100644
--- a/tests/protocol/test_wire.py
+++ b/tests/protocol/test_wire.py
@@ -14,7 +14,7 @@
#
# Requires Python 2.4+ and Openssl 1.0+
#
-
+from azurelinuxagent.common import event
from azurelinuxagent.common.protocol.wire import *
from tests.protocol.mockwiredata import *
@@ -148,13 +148,16 @@ class TestWireProtocolGetters(AgentTestCase):
host_uri)
def test_upload_status_blob_default(self, *args):
+ vmstatus = VMStatus(message="Ready", status="Ready")
wire_protocol_client = WireProtocol(wireserver_url).client
wire_protocol_client.ext_conf = ExtensionsConfig(None)
wire_protocol_client.ext_conf.status_upload_blob = testurl
+ wire_protocol_client.status_blob.vm_status = vmstatus
with patch.object(WireClient, "get_goal_state") as patch_get_goal_state:
with patch.object(HostPluginProtocol, "put_vm_status") as patch_host_ga_plugin_upload:
- with patch.object(StatusBlob, "upload", return_value = True) as patch_default_upload:
+ with patch.object(StatusBlob, "upload", return_value=True) as patch_default_upload:
+ HostPluginProtocol.set_default_channel(False)
wire_protocol_client.upload_status_blob()
patch_default_upload.assert_called_once_with(testurl)
@@ -162,20 +165,63 @@ class TestWireProtocolGetters(AgentTestCase):
patch_host_ga_plugin_upload.assert_not_called()
def test_upload_status_blob_host_ga_plugin(self, *args):
+ vmstatus = VMStatus(message="Ready", status="Ready")
wire_protocol_client = WireProtocol(wireserver_url).client
wire_protocol_client.ext_conf = ExtensionsConfig(None)
wire_protocol_client.ext_conf.status_upload_blob = testurl
wire_protocol_client.ext_conf.status_upload_blob_type = testtype
+ wire_protocol_client.status_blob.vm_status = vmstatus
goal_state = GoalState(WireProtocolData(DATA_FILE).goal_state)
- with patch.object(HostPluginProtocol, "put_vm_status") as patch_host_ga_plugin_upload:
- with patch.object(StatusBlob, "upload", return_value=False) as patch_default_upload:
- wire_protocol_client.get_goal_state = Mock(return_value = goal_state)
- wire_protocol_client.upload_status_blob()
+ with patch.object(HostPluginProtocol,
+ "ensure_initialized",
+ return_value=True):
+ with patch.object(StatusBlob,
+ "upload",
+ return_value=False) as patch_default_upload:
+ with patch.object(HostPluginProtocol,
+ "_put_block_blob_status") as patch_http:
+ HostPluginProtocol.set_default_channel(False)
+ wire_protocol_client.get_goal_state = Mock(return_value=goal_state)
+ wire_protocol_client.upload_status_blob()
+ patch_default_upload.assert_called_once_with(testurl)
+ wire_protocol_client.get_goal_state.assert_called_once()
+ patch_http.assert_called_once_with(testurl, wire_protocol_client.status_blob)
+ self.assertTrue(HostPluginProtocol.is_default_channel())
+ HostPluginProtocol.set_default_channel(False)
+
+ def test_upload_status_blob_error_reporting(self, *args):
+ vmstatus = VMStatus(message="Ready", status="Ready")
+ wire_protocol_client = WireProtocol(wireserver_url).client
+ wire_protocol_client.ext_conf = ExtensionsConfig(None)
+ wire_protocol_client.ext_conf.status_upload_blob = testurl
+ wire_protocol_client.ext_conf.status_upload_blob_type = testtype
+ wire_protocol_client.status_blob.vm_status = vmstatus
+ goal_state = GoalState(WireProtocolData(DATA_FILE).goal_state)
- patch_default_upload.assert_called_once_with(testurl)
- wire_protocol_client.get_goal_state.assert_called_once()
- patch_host_ga_plugin_upload.assert_called_once_with(wire_protocol_client.status_blob, testurl, testtype)
+ with patch.object(HostPluginProtocol,
+ "ensure_initialized",
+ return_value=True):
+ with patch.object(StatusBlob,
+ "put_block_blob",
+ side_effect=HttpError("error")):
+ with patch.object(StatusBlob,
+ "get_blob_type",
+ return_value='BlockBlob'):
+ with patch.object(HostPluginProtocol,
+ "put_vm_status"):
+ with patch.object(WireClient,
+ "report_blob_type",
+ side_effect=MagicMock()):
+ with patch.object(event,
+ "add_event") as patch_add_event:
+ HostPluginProtocol.set_default_channel(False)
+ wire_protocol_client.get_goal_state = Mock(return_value=goal_state)
+ wire_protocol_client.upload_status_blob()
+ wire_protocol_client.get_goal_state.assert_called_once()
+ self.assertTrue(patch_add_event.call_count == 1)
+ self.assertTrue(patch_add_event.call_args_list[0][1]['op'] == 'ReportStatus')
+ self.assertFalse(HostPluginProtocol.is_default_channel())
def test_get_in_vm_artifacts_profile_blob_not_available(self, *args):
wire_protocol_client = WireProtocol(wireserver_url).client
@@ -249,6 +295,7 @@ class TestWireProtocolGetters(AgentTestCase):
with patch.object(HostPluginProtocol,
"get_artifact_request",
return_value=[host_uri, {}]):
+ HostPluginProtocol.set_default_channel(False)
self.assertRaises(ProtocolError, client.fetch_manifest, uris)
self.assertEqual(patch_fetch.call_count, 2)
self.assertEqual(patch_fetch.call_args_list[0][0][0], uri1.uri)