cloud-init/cloudinit/sources/openstack/base.py

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)