From 654334975c0efeb835ccff88ef949461296b211c Mon Sep 17 00:00:00 2001 From: Alessandro Pilotti Date: Mon, 24 Feb 2014 02:21:36 +0200 Subject: [PATCH] Reintroduces EC2 metadata service Adds a refactored version of the EC2 metadata service removed in a previous commit. --- cloudbaseinit/metadata/factory.py | 1 + cloudbaseinit/metadata/services/ec2service.py | 102 ++++++++++++++++++ .../metadata/services/httpservice.py | 32 +----- cloudbaseinit/utils/network.py | 50 +++++++++ 4 files changed, 155 insertions(+), 30 deletions(-) create mode 100644 cloudbaseinit/metadata/services/ec2service.py create mode 100644 cloudbaseinit/utils/network.py diff --git a/cloudbaseinit/metadata/factory.py b/cloudbaseinit/metadata/factory.py index a6422d1d..6cfdcb19 100644 --- a/cloudbaseinit/metadata/factory.py +++ b/cloudbaseinit/metadata/factory.py @@ -25,6 +25,7 @@ opts = [ default=[ 'cloudbaseinit.metadata.services.httpservice.HttpService', 'cloudbaseinit.metadata.services.configdrive.ConfigDriveService', + 'cloudbaseinit.metadata.services.ec2service.EC2Service', 'cloudbaseinit.metadata.services.maasservice.MaaSHttpService' ], help='List of enabled metadata service classes, ' diff --git a/cloudbaseinit/metadata/services/ec2service.py b/cloudbaseinit/metadata/services/ec2service.py new file mode 100644 index 00000000..38fb792b --- /dev/null +++ b/cloudbaseinit/metadata/services/ec2service.py @@ -0,0 +1,102 @@ +# Copyright 2014 Cloudbase Solutions Srl +# Copyright 2012 Mirantis Inc. +# +# 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. + +import posixpath +import urllib2 + +from oslo.config import cfg + +from cloudbaseinit.metadata.services import base +from cloudbaseinit.openstack.common import log as logging +from cloudbaseinit.utils import network + +opts = [ + cfg.StrOpt('ec2_metadata_base_url', + default='http://169.254.169.254/', + help='The base URL where the service looks for metadata'), +] + +CONF = cfg.CONF +CONF.register_opts(opts) + +LOG = logging.getLogger(__name__) + + +class EC2Service(base.BaseMetadataService): + _metadata_version = '2009-04-04' + + def __init__(self): + super(EC2Service, self).__init__() + self._enable_retry = True + + def load(self): + super(EC2Service, self).load() + network.check_metadata_ip_route(CONF.ec2_metadata_base_url) + + try: + self._get_data('latest/meta-data/') + return True + except Exception, ex: + LOG.exception(ex) + LOG.debug('Metadata not found at URL \'%s\'' % + CONF.ec2_metadata_base_url) + return False + + def _get_response(self, req): + try: + return urllib2.urlopen(req) + except urllib2.HTTPError as ex: + if ex.code == 404: + raise base.NotExistingMetadataException() + else: + raise + + def _get_data(self, path): + norm_path = posixpath.join(CONF.ec2_metadata_base_url, path) + + LOG.debug('Getting metadata from: %(norm_path)s', + {'norm_path': norm_path}) + req = urllib2.Request(norm_path) + response = self._get_response(req) + return response.read() + + def get_host_name(self): + return self._get_cache_data('%s/meta-data/local-hostname' % + self._metadata_version) + + def get_instance_id(self): + return self._get_cache_data('%s/meta-data/instance-id' % + self._metadata_version) + + def get_public_keys(self): + ssh_keys = [] + + keys_info = self._get_cache_data( + '%s/meta-data/public-keys' % + self._metadata_version).split("\n") + + for key_info in keys_info: + (idx, key_name) = key_info.split('=') + + ssh_key = self._get_cache_data( + '%(version)s/meta-data/public-keys/%(idx)s/openssh-key' % + {'version': self._metadata_version, 'idx': idx}) + ssh_keys.append(ssh_key) + + return ssh_keys + + def get_network_config(self): + # TODO(alexpilotti): add static network support + pass diff --git a/cloudbaseinit/metadata/services/httpservice.py b/cloudbaseinit/metadata/services/httpservice.py index 76d27423..4adfa686 100644 --- a/cloudbaseinit/metadata/services/httpservice.py +++ b/cloudbaseinit/metadata/services/httpservice.py @@ -16,14 +16,13 @@ import posixpath import urllib2 -import urlparse from oslo.config import cfg from cloudbaseinit.metadata.services import base from cloudbaseinit.metadata.services import baseopenstackservice from cloudbaseinit.openstack.common import log as logging -from cloudbaseinit.osutils import factory as osutils_factory +from cloudbaseinit.utils import network opts = [ cfg.StrOpt('metadata_base_url', default='http://169.254.169.254/', @@ -43,36 +42,9 @@ class HttpService(baseopenstackservice.BaseOpenStackService): super(HttpService, self).__init__() self._enable_retry = True - def _check_metadata_ip_route(self): - ''' - Workaround for: https://bugs.launchpad.net/quantum/+bug/1174657 - ''' - osutils = osutils_factory.get_os_utils() - - if osutils.check_os_version(6, 0): - # 169.254.x.x addresses are not getting routed starting from - # Windows Vista / 2008 - metadata_netloc = urlparse.urlparse(CONF.metadata_base_url).netloc - metadata_host = metadata_netloc.split(':')[0] - - if metadata_host.startswith("169.254."): - if not osutils.check_static_route_exists(metadata_host): - (interface_index, gateway) = osutils.get_default_gateway() - if gateway: - try: - osutils.add_static_route(metadata_host, - "255.255.255.255", - gateway, - interface_index, - 10) - except Exception, ex: - # Ignore it - LOG.exception(ex) - def load(self): super(HttpService, self).load() - - self._check_metadata_ip_route() + network.check_metadata_ip_route(CONF.metadata_base_url) try: self._get_meta_data() diff --git a/cloudbaseinit/utils/network.py b/cloudbaseinit/utils/network.py new file mode 100644 index 00000000..533b986a --- /dev/null +++ b/cloudbaseinit/utils/network.py @@ -0,0 +1,50 @@ +# Copyright 2012 Cloudbase Solutions Srl +# +# 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. + +import sys +import urlparse + +from cloudbaseinit.openstack.common import log as logging +from cloudbaseinit.osutils import factory as osutils_factory + +LOG = logging.getLogger(__name__) + + +def check_metadata_ip_route(metadata_url): + ''' + Workaround for: https://bugs.launchpad.net/quantum/+bug/1174657 + ''' + osutils = osutils_factory.get_os_utils() + + if sys.platform == 'win32' and osutils.check_os_version(6, 0): + # 169.254.x.x addresses are not getting routed starting from + # Windows Vista / 2008 + metadata_netloc = urlparse.urlparse(metadata_url).netloc + metadata_host = metadata_netloc.split(':')[0] + + if metadata_host.startswith("169.254."): + if not osutils.check_static_route_exists(metadata_host): + (interface_index, gateway) = osutils.get_default_gateway() + if gateway: + try: + LOG.debug('Setting gateway for host: %s', + metadata_host) + osutils.add_static_route(metadata_host, + "255.255.255.255", + gateway, + interface_index, + 10) + except Exception, ex: + # Ignore it + LOG.exception(ex)