diff options
author | Ćukasz 'sil2100' Zemczak <lukasz.zemczak@ubuntu.com> | 2017-04-18 12:27:57 +0200 |
---|---|---|
committer | usd-importer <ubuntu-server@lists.ubuntu.com> | 2017-04-24 08:23:24 +0000 |
commit | 473ad6fbfe0b9c3b362b530492928303f2b4c7f3 (patch) | |
tree | 8a90733041edb1bdb2c4523a1bb85a8a60b86018 /tests | |
parent | 83be006e288c58a46f5b76c29b6886c1f417d88c (diff) | |
download | vyos-walinuxagent-473ad6fbfe0b9c3b362b530492928303f2b4c7f3.tar.gz vyos-walinuxagent-473ad6fbfe0b9c3b362b530492928303f2b4c7f3.zip |
Import patches-unapplied version 2.2.9-0ubuntu1 to ubuntu/zesty-proposed
Imported using git-ubuntu import.
Changelog parent: 83be006e288c58a46f5b76c29b6886c1f417d88c
New changelog entries:
* New upstream release (LP: #1683521).
Diffstat (limited to 'tests')
-rw-r--r-- | tests/common/test_event.py | 91 | ||||
-rw-r--r-- | tests/common/test_version.py | 16 | ||||
-rw-r--r-- | tests/daemon/test_daemon.py | 3 | ||||
-rw-r--r-- | tests/data/ga/WALinuxAgent-2.2.4.zip | bin | 403507 -> 0 bytes | |||
-rw-r--r-- | tests/data/ga/WALinuxAgent-2.2.8.zip | bin | 0 -> 415285 bytes | |||
-rw-r--r-- | tests/ga/test_update.py | 32 | ||||
-rw-r--r-- | tests/protocol/test_hostplugin.py | 326 | ||||
-rw-r--r-- | tests/protocol/test_wire.py | 65 |
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 Binary files differdeleted file mode 100644 index fd48991..0000000 --- a/tests/data/ga/WALinuxAgent-2.2.4.zip +++ /dev/null diff --git a/tests/data/ga/WALinuxAgent-2.2.8.zip b/tests/data/ga/WALinuxAgent-2.2.8.zip Binary files differnew file mode 100644 index 0000000..04c60a8 --- /dev/null +++ b/tests/data/ga/WALinuxAgent-2.2.8.zip 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) |