
The current patch proposes the addition of a new data source strategy for filtering the strategies by a given list of versions. Each data source exports a new API, called ``version()``, which should return the underlying version of the said data source. This implies that each data source module can export multiple versioned data sources and it's the duty of an external strategy to select the appropiate data source with regard to a particular set of versions. Change-Id: I6ef2fdd6520a53fc600232247f23bd22b848461e
117 lines
3.4 KiB
Python
117 lines
3.4 KiB
Python
# Copyright 2015 Canonical Ltd.
|
|
# This file is part of cloud-init. See LICENCE file for license information.
|
|
#
|
|
# vi: ts=4 expandtab
|
|
|
|
"""Base classes for interacting with OpenStack data sources."""
|
|
|
|
import abc
|
|
import json
|
|
import logging
|
|
import os
|
|
|
|
import six
|
|
|
|
from cloudinit.sources import base
|
|
|
|
__all__ = ('BaseOpenStackSource', )
|
|
|
|
_PAYLOAD_KEY = "content_path"
|
|
_ADMIN_PASSWORD = "admin_pass"
|
|
LOG = logging.getLogger(__name__)
|
|
_OS_LATEST = 'latest'
|
|
_OS_FOLSOM = '2012-08-10'
|
|
_OS_GRIZZLY = '2013-04-04'
|
|
_OS_HAVANA = '2013-10-17'
|
|
# Keep this in chronological order. New supported versions go at the end.
|
|
_OS_VERSIONS = (
|
|
_OS_FOLSOM,
|
|
_OS_GRIZZLY,
|
|
_OS_HAVANA,
|
|
)
|
|
|
|
|
|
@six.add_metaclass(abc.ABCMeta)
|
|
class BaseOpenStackSource(base.BaseDataSource):
|
|
"""Base classes for interacting with an OpenStack data source.
|
|
|
|
This is useful for both the HTTP data source, as well for
|
|
ConfigDrive.
|
|
"""
|
|
def __init__(self):
|
|
super(BaseOpenStackSource, self).__init__()
|
|
self._version = None
|
|
|
|
@abc.abstractmethod
|
|
def _available_versions(self):
|
|
"""Get the available metadata versions."""
|
|
|
|
@abc.abstractmethod
|
|
def _path_join(self, path, *addons):
|
|
"""Join one or more components together."""
|
|
|
|
def version(self):
|
|
"""Get the underlying data source version."""
|
|
return self._version
|
|
|
|
def _working_version(self):
|
|
versions = self._available_versions()
|
|
# OS_VERSIONS is stored in chronological order, so
|
|
# reverse it to check newest first.
|
|
supported = reversed(_OS_VERSIONS)
|
|
selected_version = next((version for version in supported
|
|
if version in versions), _OS_LATEST)
|
|
|
|
LOG.debug("Selected version %r from %s", selected_version, versions)
|
|
return selected_version
|
|
|
|
def _get_content(self, name):
|
|
path = self._path_join('openstack', 'content', name)
|
|
return self._get_cache_data(path)
|
|
|
|
def _get_meta_data(self):
|
|
path = self._path_join('openstack', self._version, 'meta_data.json')
|
|
data = self._get_cache_data(path)
|
|
if data:
|
|
return json.loads(str(data))
|
|
|
|
def load(self):
|
|
self._version = self._working_version()
|
|
super(BaseOpenStackSource, self).load()
|
|
|
|
def user_data(self):
|
|
path = self._path_join('openstack', self._version, 'user_data')
|
|
return self._get_cache_data(path).buffer
|
|
|
|
def vendor_data(self):
|
|
path = self._path_join('openstack', self._version, 'vendor_data.json')
|
|
return self._get_cache_data(path).buffer
|
|
|
|
def instance_id(self):
|
|
return self._get_meta_data().get('uuid')
|
|
|
|
def host_name(self):
|
|
return self._get_meta_data().get('hostname')
|
|
|
|
def public_keys(self):
|
|
public_keys = self._get_meta_data().get('public_keys')
|
|
if public_keys:
|
|
return list(public_keys.values())
|
|
return []
|
|
|
|
def network_config(self):
|
|
network_config = self._get_meta_data().get('network_config')
|
|
if not network_config:
|
|
return None
|
|
if _PAYLOAD_KEY not in network_config:
|
|
return None
|
|
|
|
content_path = network_config[_PAYLOAD_KEY]
|
|
content_name = os.path.basename(content_path)
|
|
return str(self._get_content(content_name))
|
|
|
|
def admin_password(self):
|
|
meta_data = self._get_meta_data()
|
|
meta = meta_data.get('meta', {})
|
|
return meta.get(_ADMIN_PASSWORD) or meta_data.get(_ADMIN_PASSWORD)
|