def test_put_vm_log_should_raise_an_exception_when_request_fails(self): def http_put_handler(url, *args, **kwargs): # pylint: disable=inconsistent-return-statements if self.is_host_plugin_put_logs_request(url): http_put_handler.args, http_put_handler.kwargs = args, kwargs return MockResponse(body=ustr('Gone'), status_code=410) http_put_handler.args, http_put_handler.kwargs = [], {} with mock_wire_protocol(DATA_FILE, http_put_handler=http_put_handler) as protocol: test_goal_state = protocol.client.get_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, "Host plugin should not be initialized!") with self.assertRaises(HttpError) as context_manager: content = b"test" host_client.put_vm_log(content) self.assertIsInstance(context_manager.exception, HttpError) self.assertIn("410", ustr(context_manager.exception)) self.assertIn("Gone", ustr(context_manager.exception))
def test_validate_get_extension_artifacts(self): with mock_wire_protocol(DATA_FILE) as protocol: test_goal_state = protocol.client._goal_state # pylint: disable=protected-access expected_url = hostplugin.URI_FORMAT_GET_EXTENSION_ARTIFACT.format( wireserver_url, hostplugin.HOST_PLUGIN_PORT) expected_headers = { 'x-ms-version': '2015-09-01', "x-ms-containerid": test_goal_state.container_id, "x-ms-host-config-name": test_goal_state.role_config_name, "x-ms-artifact-location": 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) self.assertTrue(host_client.health_service is not None) with patch.object(wire.HostPluginProtocol, "get_api_versions", return_value=api_versions) as patch_get: # pylint: disable=unused-variable actual_url, actual_headers = host_client.get_artifact_request( sas_url) self.assertTrue(host_client.is_initialized) self.assertFalse(host_client.api_versions is None) self.assertEqual(expected_url, actual_url) for k in expected_headers: self.assertTrue(k in actual_headers) self.assertEqual(expected_headers[k], actual_headers[k])
def test_validate_get_extension_artifacts(self): test_goal_state = wire.GoalState( WireProtocolData(DATA_FILE).goal_state) expected_url = hostplugin.URI_FORMAT_GET_EXTENSION_ARTIFACT.format( wireserver_url, hostplugin.HOST_PLUGIN_PORT) expected_headers = { 'x-ms-version': '2015-09-01', "x-ms-containerid": test_goal_state.container_id, "x-ms-host-config-name": test_goal_state.role_instance_config_name, "x-ms-artifact-location": sas_url } host_client = wire.HostPluginProtocol( wireserver_url, test_goal_state.container_id, test_goal_state.role_instance_config_name) self.assertFalse(host_client.is_initialized) self.assertTrue(host_client.api_versions is None) with patch.object(wire.HostPluginProtocol, "get_api_versions", return_value=api_versions) as patch_get: actual_url, actual_headers = host_client.get_extension_artifact_url_and_headers( sas_url) self.assertTrue(host_client.is_initialized) self.assertFalse(host_client.api_versions is None) self.assertEqual(expected_url, actual_url) for k in expected_headers: self.assertTrue(k in actual_headers) self.assertEqual(expected_headers[k], actual_headers[k])
def test_validate_page_blobs(self): """Validate correct set of data is sent for page blobs""" with mock_wire_protocol(DATA_FILE) as protocol: test_goal_state = protocol.client._goal_state # pylint: disable=protected-access 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 = 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(patch_http.call_count == 3) # first call is to host plugin 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) # second call is to health service self.assertEqual('POST', patch_http.call_args_list[1][0][0]) self.assertEqual(health_service_url, patch_http.call_args_list[1][0][1]) # last call is to host plugin 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[2], test_goal_state, exp_method, exp_url, exp_data)
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) 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 = block_blob_type 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: patch_http.return_value = Mock(status=httpclient.OK) 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(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_init_put(self): expected_url = "http://168.63.129.16:32526/status" expected_headers = {'x-ms-version': '2015-09-01'} expected_content = '{"content": "b2s=", ' \ '"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) self.assertFalse(host_client.is_initialized) self.assertTrue(host_client.api_versions is None) status_blob = wire.StatusBlob(None) 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: patch_get.return_value = api_versions with patch.object(restapi.restutil, "http_put") as patch_put: patch_put.return_value = MagicMock() 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[0][1] == expected_content) self.assertTrue(patch_put.call_args[0][2] == expected_headers)
def _init_host(self): with mock_wire_protocol(DATA_FILE) as protocol: test_goal_state = protocol.client.get_goal_state() host_plugin = wire.HostPluginProtocol( wireserver_url, test_goal_state.container_id, test_goal_state.role_config_name) self.assertTrue(host_plugin.health_service is not None) return host_plugin
def _init_host(self): test_goal_state = wire.GoalState( WireProtocolData(DATA_FILE).goal_state) host_plugin = wire.HostPluginProtocol(wireserver_url, test_goal_state.container_id, test_goal_state.role_config_name) self.assertTrue(host_plugin.health_service is not None) return host_plugin
def test_validate_http_request_for_put_vm_log(self): def http_put_handler(url, *args, **kwargs): # pylint: disable=inconsistent-return-statements if self.is_host_plugin_put_logs_request(url): http_put_handler.args, http_put_handler.kwargs = args, kwargs return MockResponse(body=b'', status_code=200) http_put_handler.args, http_put_handler.kwargs = [], {} with mock_wire_protocol(DATA_FILE, http_put_handler=http_put_handler) as protocol: test_goal_state = protocol.client.get_goal_state() expected_url = hostplugin.URI_FORMAT_PUT_LOG.format( wireserver_url, hostplugin.HOST_PLUGIN_PORT) expected_headers = { 'x-ms-version': '2015-09-01', "x-ms-containerid": test_goal_state.container_id, "x-ms-vmagentlog-deploymentid": test_goal_state.role_config_name.split(".")[0], "x-ms-client-name": AGENT_NAME, "x-ms-client-version": AGENT_VERSION } host_client = wire.HostPluginProtocol( wireserver_url, test_goal_state.container_id, test_goal_state.role_config_name) self.assertFalse(host_client.is_initialized, "Host plugin should not be initialized!") content = b"test" host_client.put_vm_log(content) self.assertTrue(host_client.is_initialized, "Host plugin is not initialized!") urls = protocol.get_tracked_urls() self.assertEqual(expected_url, urls[0], "Unexpected request URL!") self.assertEqual(content, http_put_handler.args[0], "Unexpected content for HTTP PUT request!") headers = http_put_handler.kwargs['headers'] for k in expected_headers: self.assertTrue(k in headers, "Header {0} not found in headers!".format(k)) self.assertEqual(expected_headers[k], headers[k], "Request headers don't match!") # Special check for correlation id header value, check for pattern, not exact value self.assertTrue("x-ms-client-correlationid" in headers.keys(), "Correlation id not found in headers!") self.assertTrue( UUID_PATTERN.match(headers["x-ms-client-correlationid"]), "Correlation id is not in GUID form!")
def test_validate_block_blob(self): with mock_wire_protocol(DATA_FILE) as protocol: test_goal_state = protocol.client._goal_state # pylint: disable=protected-access 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) self.assertTrue(host_client.health_service is not None) status_blob = 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") 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: patch_http.return_value = Mock(status=httpclient.OK) 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(patch_http.call_count == 2) # first call is to host plugin self._validate_hostplugin_args( patch_http.call_args_list[0], test_goal_state, exp_method, exp_url, exp_data) # second call is to health service self.assertEqual('POST', patch_http.call_args_list[1][0][0]) self.assertEqual(health_service_url, patch_http.call_args_list[1][0][1])
def test_validate_http_put(self): """Validate correct set of data is sent to HostGAPlugin when reporting VM status""" 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.vm_status = restapi.VMStatus(message="Ready", status="Ready") status_blob.data = '{"dummy": "data"}' status_blob.type = "BlockBlob" 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() 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)