diff options
author | Ćukasz 'sil2100' Zemczak <lukasz.zemczak@ubuntu.com> | 2017-05-18 19:58:02 +0200 |
---|---|---|
committer | usd-importer <ubuntu-server@lists.ubuntu.com> | 2017-05-31 09:53:12 +0000 |
commit | 4fb0b5a09b26135ade285844da5d7dfe582a8d4c (patch) | |
tree | 09b1e5867d6e7501118cdd0af0012b51fc216530 /azurelinuxagent/common/protocol | |
parent | 473ad6fbfe0b9c3b362b530492928303f2b4c7f3 (diff) | |
download | vyos-walinuxagent-4fb0b5a09b26135ade285844da5d7dfe582a8d4c.tar.gz vyos-walinuxagent-4fb0b5a09b26135ade285844da5d7dfe582a8d4c.zip |
Import patches-unapplied version 2.2.12-0ubuntu1 to ubuntu/artful-proposed
Imported using git-ubuntu import.
Changelog parent: 473ad6fbfe0b9c3b362b530492928303f2b4c7f3
New changelog entries:
* New upstream release (LP: #1690854).
- Refreshed debian/patches/disable_import_test.patch.
Diffstat (limited to 'azurelinuxagent/common/protocol')
-rw-r--r-- | azurelinuxagent/common/protocol/hostplugin.py | 4 | ||||
-rw-r--r-- | azurelinuxagent/common/protocol/metadata.py | 78 | ||||
-rw-r--r-- | azurelinuxagent/common/protocol/ovfenv.py | 2 | ||||
-rw-r--r-- | azurelinuxagent/common/protocol/util.py | 57 | ||||
-rw-r--r-- | azurelinuxagent/common/protocol/wire.py | 127 |
5 files changed, 142 insertions, 126 deletions
diff --git a/azurelinuxagent/common/protocol/hostplugin.py b/azurelinuxagent/common/protocol/hostplugin.py index 70bf8b4..464fd35 100644 --- a/azurelinuxagent/common/protocol/hostplugin.py +++ b/azurelinuxagent/common/protocol/hostplugin.py @@ -19,6 +19,7 @@ import base64 import json +import traceback from azurelinuxagent.common import logger from azurelinuxagent.common.exception import ProtocolError, HttpError @@ -177,8 +178,7 @@ class HostPluginProtocol(object): logger.info("HostGAPlugin: Setting host plugin as default channel") HostPluginProtocol.set_default_channel(True) except Exception as e: - message = "HostGAPlugin: Exception Put VM status: {0}".format(e) - logger.error(message) + message = "HostGAPlugin: Exception Put VM status: {0}, {1}".format(e, traceback.format_exc()) from azurelinuxagent.common.event import WALAEventOperation, report_event report_event(op=WALAEventOperation.ReportStatus, is_success=False, diff --git a/azurelinuxagent/common/protocol/metadata.py b/azurelinuxagent/common/protocol/metadata.py index c61e373..c50b3dd 100644 --- a/azurelinuxagent/common/protocol/metadata.py +++ b/azurelinuxagent/common/protocol/metadata.py @@ -21,17 +21,19 @@ import json import os import shutil import re + import azurelinuxagent.common.conf as conf import azurelinuxagent.common.utils.fileutil as fileutil import azurelinuxagent.common.utils.shellutil as shellutil import azurelinuxagent.common.utils.textutil as textutil + from azurelinuxagent.common.future import httpclient from azurelinuxagent.common.protocol.restapi import * from azurelinuxagent.common.utils.cryptutil import CryptUtil METADATA_ENDPOINT = '169.254.169.254' APIVERSION = '2015-05-01-preview' -BASE_URI = "http://{0}/Microsoft.Compute/{1}?api-version={2}{3}" +BASE_URI = "http://{0}/Microsoft.Compute/{1}?api-version={2}" TRANSPORT_PRV_FILE_NAME = "V2TransportPrivate.pem" TRANSPORT_CERT_FILE_NAME = "V2TransportCert.pem" @@ -39,6 +41,9 @@ P7M_FILE_NAME = "Certificates.p7m" P7B_FILE_NAME = "Certificates.p7b" PEM_FILE_NAME = "Certificates.pem" +KEY_AGENT_VERSION_URIS = "versionsManifestUris" +KEY_URI = "uri" + # TODO remote workaround for azure stack MAX_PING = 30 RETRY_PING_INTERVAL = 10 @@ -56,13 +61,13 @@ class MetadataProtocol(Protocol): self.apiversion = apiversion self.endpoint = endpoint self.identity_uri = BASE_URI.format(self.endpoint, "identity", - self.apiversion, "&$expand=*") + self.apiversion) self.cert_uri = BASE_URI.format(self.endpoint, "certificates", - self.apiversion, "&$expand=*") + self.apiversion) self.ext_uri = BASE_URI.format(self.endpoint, "extensionHandlers", - self.apiversion, "&$expand=*") + self.apiversion) self.vmagent_uri = BASE_URI.format(self.endpoint, "vmAgentVersions", - self.apiversion, "&$expand=*") + self.apiversion) self.provision_status_uri = BASE_URI.format(self.endpoint, "provisioningStatus", self.apiversion, "") @@ -74,6 +79,8 @@ class MetadataProtocol(Protocol): self.event_uri = BASE_URI.format(self.endpoint, "status/telemetry", self.apiversion, "") self.certs = None + self.agent_manifests = None + self.agent_etag = None def _get_data(self, url, headers=None): try: @@ -166,32 +173,55 @@ class MetadataProtocol(Protocol): return None return self.certs - def get_vmagent_manifests(self, last_etag=None): - manifests = VMAgentManifestList() + def get_vmagent_manifests(self): self.update_goal_state() + data, etag = self._get_data(self.vmagent_uri) - if last_etag is None or last_etag < etag: - set_properties("vmAgentManifests", - manifests.vmAgentManifests, - data) - return manifests, etag + if self.agent_etag is None or self.agent_etag < etag: + self.agent_etag = etag + + # Create a list with a single manifest + # -- The protocol lacks "family," use the configured family + self.agent_manifests = VMAgentManifestList() + + manifest = VMAgentManifest() + manifest.family = family=conf.get_autoupdate_gafamily() + + if not KEY_AGENT_VERSION_URIS in data: + raise ProtocolError( + "Agent versions missing '{0}': {1}".format( + KEY_AGENT_VERSION_URIS, data)) + + for version in data[KEY_AGENT_VERSION_URIS]: + if not KEY_URI in version: + raise ProtocolError( + "Agent versions missing '{0': {1}".format( + KEY_URI, data)) + manifest_uri = VMAgentManifestUri(uri=version[KEY_URI]) + manifest.versionsManifestUris.append(manifest_uri) + + self.agent_manifests.vmAgentManifests.append(manifest) + + return self.agent_manifests, self.agent_etag def get_vmagent_pkgs(self, vmagent_manifest): - # Agent package is the same with extension handler - vmagent_pkgs = ExtHandlerPackageList() data = None + etag = None for manifest_uri in vmagent_manifest.versionsManifestUris: try: - data = self._get_data(manifest_uri.uri) + data, etag = self._get_data(manifest_uri.uri) break except ProtocolError as e: - logger.warn("Failed to get vmagent versions: {0}", e) - logger.info("Retry getting vmagent versions") + logger.verbose( + "Error retrieving agent package from {0}: {1}".format( + manifest_uri, e)) + if data is None: - raise ProtocolError(("Failed to get versions for vm agent: {0}" - "").format(vmagent_manifest.family)) + raise ProtocolError( + "Failed retrieving agent package from all URIs") + + vmagent_pkgs = ExtHandlerPackageList() set_properties("vmAgentVersions", vmagent_pkgs, data) - # TODO: What etag should this return? return vmagent_pkgs def get_ext_handlers(self, last_etag=None): @@ -251,11 +281,9 @@ class MetadataProtocol(Protocol): self._put_data(uri, data) def report_event(self, events): - # TODO disable telemetry for azure stack test - # validate_param('events', events, TelemetryEventList) - # data = get_properties(events) - # self._post_data(self.event_uri, data) - pass + validate_param('events', events, TelemetryEventList) + data = get_properties(events) + self._post_data(self.event_uri, data) def update_certs(self): certificates = self.get_certs() diff --git a/azurelinuxagent/common/protocol/ovfenv.py b/azurelinuxagent/common/protocol/ovfenv.py index 4901871..3122e3b 100644 --- a/azurelinuxagent/common/protocol/ovfenv.py +++ b/azurelinuxagent/common/protocol/ovfenv.py @@ -35,7 +35,7 @@ WA_NAME_SPACE = "http://schemas.microsoft.com/windowsazure" def _validate_ovf(val, msg): if val is None: - raise ProtocolError("Failed to parse OVF XML: {0}".format(msg)) + raise ProtocolError("Failed to validate OVF: {0}".format(msg)) class OvfEnv(object): """ diff --git a/azurelinuxagent/common/protocol/util.py b/azurelinuxagent/common/protocol/util.py index 7e7a74f..0ba03ec 100644 --- a/azurelinuxagent/common/protocol/util.py +++ b/azurelinuxagent/common/protocol/util.py @@ -33,25 +33,21 @@ from azurelinuxagent.common.protocol.ovfenv import OvfEnv from azurelinuxagent.common.protocol.wire import WireProtocol from azurelinuxagent.common.protocol.metadata import MetadataProtocol, \ METADATA_ENDPOINT -import azurelinuxagent.common.utils.shellutil as shellutil OVF_FILE_NAME = "ovf-env.xml" - -#Tag file to indicate usage of metadata protocol -TAG_FILE_NAME = "useMetadataEndpoint.tag" - +TAG_FILE_NAME = "useMetadataEndpoint.tag" PROTOCOL_FILE_NAME = "Protocol" - -#MAX retry times for protocol probing MAX_RETRY = 360 - PROBE_INTERVAL = 10 - ENDPOINT_FILE_NAME = "WireServerEndpoint" +PASSWORD_PATTERN = "<UserPassword>.*?<" +PASSWORD_REPLACEMENT = "<UserPassword>*<" + def get_protocol_util(): return ProtocolUtil() + class ProtocolUtil(object): """ ProtocolUtil handles initialization for protocol instance. 2 protocol types @@ -71,21 +67,42 @@ class ProtocolUtil(object): dvd_mount_point = conf.get_dvd_mount_point() ovf_file_path_on_dvd = os.path.join(dvd_mount_point, OVF_FILE_NAME) tag_file_path_on_dvd = os.path.join(dvd_mount_point, TAG_FILE_NAME) + ovf_file_path = os.path.join(conf.get_lib_dir(), OVF_FILE_NAME) + tag_file_path = os.path.join(conf.get_lib_dir(), TAG_FILE_NAME) + try: self.osutil.mount_dvd() + except OSUtilError as e: + raise ProtocolError("[CopyOvfEnv] Error mounting dvd: " + "{0}".format(ustr(e))) + + try: ovfxml = fileutil.read_file(ovf_file_path_on_dvd, remove_bom=True) ovfenv = OvfEnv(ovfxml) - ovfxml = re.sub("<UserPassword>.*?<", "<UserPassword>*<", ovfxml) - ovf_file_path = os.path.join(conf.get_lib_dir(), OVF_FILE_NAME) + except IOError as e: + raise ProtocolError("[CopyOvfEnv] Error reading file " + "{0}: {1}".format(ovf_file_path_on_dvd, + ustr(e))) + + try: + ovfxml = re.sub(PASSWORD_PATTERN, + PASSWORD_REPLACEMENT, + ovfxml) fileutil.write_file(ovf_file_path, ovfxml) - + except IOError as e: + raise ProtocolError("[CopyOvfEnv] Error writing file " + "{0}: {1}".format(ovf_file_path, + ustr(e))) + + try: if os.path.isfile(tag_file_path_on_dvd): logger.info("Found {0} in provisioning ISO", TAG_FILE_NAME) - tag_file_path = os.path.join(conf.get_lib_dir(), TAG_FILE_NAME) - shutil.copyfile(tag_file_path_on_dvd, tag_file_path) - - except (OSUtilError, IOError) as e: - raise ProtocolError(ustr(e)) + shutil.copyfile(tag_file_path_on_dvd, tag_file_path) + except IOError as e: + raise ProtocolError("[CopyOvfEnv] Error copying file " + "{0} to {1}: {2}".format(tag_file_path, + tag_file_path, + ustr(e))) try: self.osutil.umount_dvd() @@ -104,7 +121,7 @@ class ProtocolUtil(object): xml_text = fileutil.read_file(ovf_file_path) return OvfEnv(xml_text) else: - raise ProtocolError("ovf-env.xml is missing.") + raise ProtocolError("ovf-env.xml is missing from {0}".format(ovf_file_path)) def _get_wireserver_endpoint(self): try: @@ -146,7 +163,7 @@ class ProtocolUtil(object): protocol = MetadataProtocol() protocol.detect() - #Only allow root access METADATA_ENDPOINT + # only allow root access METADATA_ENDPOINT self.osutil.set_admin_access_to_ip(METADATA_ENDPOINT) self.save_protocol("MetadataProtocol") @@ -206,7 +223,6 @@ class ProtocolUtil(object): except IOError as e: logger.error("Failed to save protocol endpoint: {0}", e) - def clear_protocol(self): """ Cleanup previous saved endpoint. @@ -249,7 +265,6 @@ class ProtocolUtil(object): finally: self.lock.release() - def get_protocol_by_file(self): """ Detect protocol by tag file. diff --git a/azurelinuxagent/common/protocol/wire.py b/azurelinuxagent/common/protocol/wire.py index 265e2dd..936be8c 100644 --- a/azurelinuxagent/common/protocol/wire.py +++ b/azurelinuxagent/common/protocol/wire.py @@ -21,16 +21,18 @@ import os import re import time import xml.sax.saxutils as saxutils + import azurelinuxagent.common.conf as conf +import azurelinuxagent.common.utils.fileutil as fileutil +import azurelinuxagent.common.utils.textutil as textutil + from azurelinuxagent.common.exception import ProtocolNotFoundError from azurelinuxagent.common.future import httpclient, bytebuffer +from azurelinuxagent.common.protocol.hostplugin import HostPluginProtocol +from azurelinuxagent.common.protocol.restapi import * +from azurelinuxagent.common.utils.cryptutil import CryptUtil from azurelinuxagent.common.utils.textutil import parse_doc, findall, find, \ findtext, getattrib, gettext, remove_bom, get_bytes_from_pem, parse_json -import azurelinuxagent.common.utils.fileutil as fileutil -import azurelinuxagent.common.utils.textutil as textutil -from azurelinuxagent.common.utils.cryptutil import CryptUtil -from azurelinuxagent.common.protocol.restapi import * -from azurelinuxagent.common.protocol.hostplugin import HostPluginProtocol VERSION_INFO_URI = "http://{0}/?comp=versions" GOAL_STATE_URI = "http://{0}/machine/?comp=goalstate" @@ -376,48 +378,20 @@ class StatusBlob(object): self.type = blob_type def upload(self, url): - # TODO upload extension only if content has changed - upload_successful = False - self.type = self.get_blob_type(url) try: + if not self.type in ["BlockBlob", "PageBlob"]: + raise ProtocolError("Illegal blob type: {0}".format(self.type)) + if self.type == "BlockBlob": self.put_block_blob(url, self.data) - elif self.type == "PageBlob": - self.put_page_blob(url, self.data) else: - raise ProtocolError("Unknown blob type: {0}".format(self.type)) - except HttpError as e: - message = "Initial upload failed [{0}]".format(e) - logger.warn(message) - from azurelinuxagent.common.event import WALAEventOperation, report_event - report_event(op=WALAEventOperation.ReportStatus, - is_success=False, - message=message) - else: - logger.verbose("Uploading status blob succeeded") - upload_successful = True - return upload_successful - - def get_blob_type(self, url): - logger.verbose("Get blob type") - timestamp = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()) - try: - resp = self.client.call_storage_service( - restutil.http_head, - url, - { - "x-ms-date": timestamp, - "x-ms-version": self.__class__.__storage_version__ - }) - except HttpError as e: - raise ProtocolError("Failed to get status blob type: {0}", e) + self.put_page_blob(url, self.data) + return True - if resp is None or resp.status != httpclient.OK: - raise ProtocolError("Failed to get status blob type") + except Exception as e: + logger.verbose("Initial status upload failed: {0}", e) - blob_type = resp.getheader("x-ms-blob-type") - logger.verbose("Blob type: [{0}]", blob_type) - return blob_type + return False def get_block_blob_headers(self, blob_size): return { @@ -538,7 +512,6 @@ class WireClient(object): self.req_count = 0 self.host_plugin = None self.status_blob = StatusBlob(self) - self.status_blob_type_reported = False def prevent_throttling(self): """ @@ -725,7 +698,6 @@ class WireClient(object): xml_text = self.fetch_config(goal_state.ext_uri, self.get_header()) self.save_cache(local_file, xml_text) self.ext_conf = ExtensionsConfig(xml_text) - self.status_blob_type_reported = False def update_goal_state(self, forced=False, max_retry=3): uri = GOAL_STATE_URI.format(self.endpoint) @@ -815,7 +787,6 @@ class WireClient(object): local_file = os.path.join(conf.get_lib_dir(), local_file) xml_text = self.fetch_cache(local_file) self.ext_conf = ExtensionsConfig(xml_text) - self.status_blob_type_reported = False return self.ext_conf def get_ext_manifest(self, ext_handler, goal_state): @@ -852,46 +823,38 @@ class WireClient(object): def upload_status_blob(self): ext_conf = self.get_ext_conf() - if ext_conf.status_upload_blob is not None: - uploaded = False + + blob_uri = ext_conf.status_upload_blob + blob_type = ext_conf.status_upload_blob_type + + if blob_uri is not None: + + if not blob_type in ["BlockBlob", "PageBlob"]: + blob_type = "BlockBlob" + logger.info("Status Blob type is unspecified " + "-- assuming it is a BlockBlob") + try: - self.status_blob.prepare(ext_conf.status_upload_blob_type) - if not HostPluginProtocol.is_default_channel(): - uploaded = self.status_blob.upload(ext_conf.status_upload_blob) - self.report_blob_type(self.status_blob.type, - ext_conf.status_upload_blob_type) - except (HttpError, ProtocolError): - # errors have already been logged - pass + self.status_blob.prepare(blob_type) + except Exception as e: + self.report_status_event( + "Exception creating status blob: {0}", + e) + return + + uploaded = False + if not HostPluginProtocol.is_default_channel(): + try: + uploaded = self.status_blob.upload(blob_uri) + except HttpError as e: + pass + if not uploaded: host = self.get_host_plugin() host.put_vm_status(self.status_blob, ext_conf.status_upload_blob, ext_conf.status_upload_blob_type) - """ - Emit an event to determine if the type in the extension config - matches the actual type from the HTTP HEAD request. - """ - def report_blob_type(self, head_type, config_type): - if head_type and config_type: - is_match = head_type == config_type - if self.status_blob_type_reported is False: - message = \ - 'Blob type match [{0}]'.format(head_type) if is_match else \ - 'Blob type mismatch [HEAD {0}], [CONFIG {1}]'.format( - head_type, - config_type) - - from azurelinuxagent.common.event import add_event, WALAEventOperation - from azurelinuxagent.common.version import AGENT_NAME, CURRENT_VERSION - add_event(AGENT_NAME, - version=CURRENT_VERSION, - is_success=is_match, - message=message, - op=WALAEventOperation.HealthCheck) - self.status_blob_type_reported = True - def report_role_prop(self, thumbprint): goal_state = self.get_goal_state() role_prop = _build_role_properties(goal_state.container_id, @@ -980,6 +943,16 @@ class WireClient(object): if len(buf[provider_id]) > 0: self.send_event(provider_id, buf[provider_id]) + def report_status_event(self, message, *args): + from azurelinuxagent.common.event import report_event, \ + WALAEventOperation + + message = message.format(*args) + logger.warn(message) + report_event(op=WALAEventOperation.ReportStatus, + is_success=False, + message=message) + def get_header(self): return { "x-ms-agent-name": "WALinuxAgent", |