summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Harlow <harlowja@yahoo-inc.com>2014-08-27 12:30:23 -0700
committerJoshua Harlow <harlowja@yahoo-inc.com>2014-08-27 12:30:23 -0700
commitd701035265c765bc42cb3bc358f2bfd0b41f484b (patch)
tree5c2b597dea6f27ad88bc2bc3ee1d8f9d6a9e422c
parentfb482ce4a36d9b4be75a8bf5b428189548a205d9 (diff)
downloadvyos-cloud-init-d701035265c765bc42cb3bc358f2bfd0b41f484b.tar.gz
vyos-cloud-init-d701035265c765bc42cb3bc358f2bfd0b41f484b.zip
Fixed more of the slowness around fetching and retrying
-rw-r--r--cloudinit/sources/helpers/openstack.py112
-rw-r--r--tests/unittests/test_datasource/test_openstack.py23
2 files changed, 84 insertions, 51 deletions
diff --git a/cloudinit/sources/helpers/openstack.py b/cloudinit/sources/helpers/openstack.py
index 3ceec837..2d0fc70e 100644
--- a/cloudinit/sources/helpers/openstack.py
+++ b/cloudinit/sources/helpers/openstack.py
@@ -21,6 +21,7 @@
import abc
import base64
import copy
+import httplib
import os
from cloudinit import ec2_utils
@@ -154,9 +155,30 @@ class BaseReader(object):
pass
@abc.abstractmethod
+ def _fetch_available_versions(self):
+ pass
+
+ @abc.abstractmethod
def _read_ec2_metadata(self):
pass
+ def _find_working_version(self, version):
+ search_versions = [version] + list(OS_VERSIONS)
+ available_versions = self._fetch_available_versions()
+ for potential_version in search_versions:
+ if not potential_version:
+ continue
+ if potential_version not in available_versions:
+ continue
+ if potential_version != version:
+ LOG.debug("Version '%s' not available, attempting to use"
+ " version '%s' instead", version,
+ potential_version)
+ return potential_version
+ LOG.debug("Version '%s' not available, attempting to use '%s'"
+ " instead", version, OS_LATEST)
+ return OS_LATEST
+
def _read_content_path(self, item):
path = item.get('content_path', '').lstrip("/")
path_pieces = path.split("/")
@@ -166,10 +188,6 @@ class BaseReader(object):
path = self._path_join(self.base_path, "openstack", *path_pieces)
return self._path_read(path)
- @abc.abstractmethod
- def _find_working_version(self, version):
- pass
-
def read_v2(self, version=None):
"""Reads a version 2 formatted location.
@@ -290,6 +308,7 @@ class BaseReader(object):
class ConfigDriveReader(BaseReader):
def __init__(self, base_path):
super(ConfigDriveReader, self).__init__(base_path)
+ self._versions = None
def _path_join(self, base, *add_ons):
components = [base] + list(add_ons)
@@ -298,22 +317,21 @@ class ConfigDriveReader(BaseReader):
def _path_read(self, path):
return util.load_file(path)
- def _find_working_version(self, version):
- search_versions = [version] + list(OS_VERSIONS)
- for potential_version in search_versions:
- if not potential_version:
- continue
- path = self._path_join(self.base_path, "openstack",
- potential_version)
- if os.path.exists(path):
- if potential_version != version:
- LOG.debug("Version '%s' not available, attempting to use"
- " version '%s' instead", version,
- potential_version)
- return potential_version
- LOG.debug("Version '%s' not available, attempting to use '%s'"
- " instead", version, OS_LATEST)
- return OS_LATEST
+ def _fetch_available_versions(self):
+ if self._versions is not None:
+ return self._versions
+ else:
+ versions_available = []
+ path = self._path_join(self.base_path, 'openstack')
+ try:
+ for child in os.listdir(path):
+ child_path = os.path.join(path, child)
+ if os.path.isdir(child_path):
+ versions_available.append(child)
+ except (OSError, IOError):
+ pass
+ self._versions = tuple(versions_available)
+ return self._versions
def _read_ec2_metadata(self):
path = self._path_join(self.base_path,
@@ -400,40 +418,40 @@ class MetadataReader(BaseReader):
self.ssl_details = ssl_details
self.timeout = float(timeout)
self.retries = int(retries)
+ self._versions = None
- def _find_working_version(self, version):
- search_versions = [version] + list(OS_VERSIONS)
- version_path = self._path_join(self.base_path, "openstack")
- versions_available = []
- try:
- versions = self._path_read(version_path)
- except IOError as e:
- LOG.warn("Unable to read openstack versions from %s due"
- " to: %s", version_path, e)
+ def _fetch_available_versions(self):
+ if self._versions is not None:
+ return self._versions
else:
- for line in versions.splitlines():
- line = line.strip()
- if not line:
- continue
- versions_available.append(line)
- for potential_version in search_versions:
- if potential_version not in versions_available:
- continue
- if potential_version != version:
- LOG.debug("Version '%s' not available, attempting to use"
- " version '%s' instead", version,
- potential_version)
- return potential_version
- LOG.debug("Version '%s' not available, searched for %s (with available"
- " versions being %s), attempting to use '%s' instead",
- version, search_versions, versions_available, OS_LATEST)
- return OS_LATEST
+ path = self._path_join(self.base_path, "openstack")
+ versions_available = []
+ try:
+ versions = self._path_read(path)
+ except IOError as e:
+ LOG.warn("Unable to read openstack versions from %s due"
+ " to: %s", path, e)
+ else:
+ for line in versions.splitlines():
+ line = line.strip()
+ if not line:
+ continue
+ versions_available.append(line)
+ self._versions = tuple(versions_available)
+ return self._versions
def _path_read(self, path):
+
+ def should_retry(_request_args, cause):
+ if cause.code == httplib.NOT_FOUND:
+ return False
+ return True
+
response = url_helper.readurl(path,
retries=self.retries,
ssl_details=self.ssl_details,
- timeout=self.timeout)
+ timeout=self.timeout,
+ exception_cb=should_retry)
return response.contents
def _path_join(self, base, *add_ons):
diff --git a/tests/unittests/test_datasource/test_openstack.py b/tests/unittests/test_datasource/test_openstack.py
index f43cbec8..412ae5a4 100644
--- a/tests/unittests/test_datasource/test_openstack.py
+++ b/tests/unittests/test_datasource/test_openstack.py
@@ -67,8 +67,8 @@ OSTACK_META = {
CONTENT_0 = 'This is contents of /etc/foo.cfg\n'
CONTENT_1 = '# this is /etc/bar/bar.cfg\n'
OS_FILES = {
- 'openstack/2012-08-10/meta_data.json': json.dumps(OSTACK_META),
- 'openstack/2012-08-10/user_data': USER_DATA,
+ 'openstack/latest/meta_data.json': json.dumps(OSTACK_META),
+ 'openstack/latest/user_data': USER_DATA,
'openstack/content/0000': CONTENT_0,
'openstack/content/0001': CONTENT_1,
'openstack/latest/meta_data.json': json.dumps(OSTACK_META),
@@ -78,6 +78,9 @@ OS_FILES = {
EC2_FILES = {
'latest/user-data': USER_DATA,
}
+EC2_VERSIONS = [
+ 'lastest',
+]
def _register_uris(version, ec2_files, ec2_meta, os_files):
@@ -85,6 +88,9 @@ def _register_uris(version, ec2_files, ec2_meta, os_files):
same data returned by the openstack metadata service (and ec2 service)."""
def match_ec2_url(uri, headers):
+ path = uri.path.strip("/")
+ if len(path) == 0:
+ return (200, headers, "\n".join(EC2_VERSIONS))
path = uri.path.lstrip("/")
if path in ec2_files:
return (200, headers, ec2_files.get(path))
@@ -110,11 +116,20 @@ def _register_uris(version, ec2_files, ec2_meta, os_files):
return (200, headers, str(value))
return (404, headers, '')
- def get_request_callback(method, uri, headers):
- uri = urlparse(uri)
+ def match_os_uri(uri, headers):
+ path = uri.path.strip("/")
+ if path == 'openstack':
+ return (200, headers, "\n".join([openstack.OS_LATEST]))
path = uri.path.lstrip("/")
if path in os_files:
return (200, headers, os_files.get(path))
+ return (404, headers, '')
+
+ def get_request_callback(method, uri, headers):
+ uri = urlparse(uri)
+ path = uri.path.lstrip("/").split("/")
+ if path[0] == 'openstack':
+ return match_os_uri(uri, headers)
return match_ec2_url(uri, headers)
hp.register_uri(hp.GET, re.compile(r'http://169.254.169.254/.*'),