Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CloudStack ConfigDrive support #68

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion cloudbaseinit/conf/cloudstack.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def __init__(self, config):
super(CloudStackOptions, self).__init__(config, group="cloudstack")
self._options = [
cfg.StrOpt(
"metadata_base_url", default="http://10.1.1.1/",
"metadata_base_url", default="http://data-server/",
help="The base URL where the service looks for metadata",
deprecated_name="cloudstack_metadata_ip",
deprecated_group="DEFAULT"),
Expand All @@ -46,6 +46,10 @@ def __init__(self, config):
cfg.BoolOpt(
"add_metadata_private_ip_route", default=False,
help="Add a route for the metadata ip address to the gateway"),
cfg.StrOpt(
"disk_label", default="config-2",
help="Disk label of ConfigDrive"
)
]

def register(self):
Expand Down
73 changes: 69 additions & 4 deletions cloudbaseinit/metadata/services/cloudstack.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,16 @@

import contextlib
import posixpath
import hashlib

from oslo_log import log as oslo_logging
from six.moves import http_client
from six.moves import urllib

from cloudbaseinit import conf as cloudbaseinit_conf
from cloudbaseinit.metadata.services import base
from cloudbaseinit.metadata.services import baseconfigdrive
from cloudbaseinit.metadata.services import baseopenstackservice
from cloudbaseinit.osutils import factory as osutils_factory
from cloudbaseinit.utils import encoding
from cloudbaseinit.utils import network
Expand All @@ -33,9 +36,9 @@
TIMEOUT = 10


class CloudStack(base.BaseHTTPMetadataService):
class DataServer(base.BaseHTTPMetadataService):

"""Metadata service for Apache CloudStack.
"""Metadata service based on DataServer for Apache CloudStack.

Apache CloudStack is an open source software designed to deploy and
manage large networks of virtual machines, as a highly available,
Expand All @@ -44,7 +47,7 @@ class CloudStack(base.BaseHTTPMetadataService):
"""

def __init__(self):
super(CloudStack, self).__init__(
super(DataServer, self).__init__(
# Note(alexcoman): The base url used by the current metadata
# service will be updated later by the `_test_api` method.
base_url=None,
Expand Down Expand Up @@ -83,7 +86,7 @@ def _test_api(self, metadata_url):

def load(self):
"""Obtain all the required information."""
super(CloudStack, self).load()
super(DataServer, self).load()

if CONF.cloudstack.add_metadata_private_ip_route:
network.check_metadata_ip_route(CONF.cloudstack.metadata_base_url)
Expand Down Expand Up @@ -259,3 +262,65 @@ def can_update_password(self):
def is_password_changed(self):
"""Check if a new password exists in the Password Server."""
return bool(self._get_password())


# For backward compatibiliy, CloudStack Class is an alias to DataServer Class
CloudStack = DataServer


class ConfigDrive(baseconfigdrive.BaseConfigDriveService,
baseopenstackservice.BaseOpenStackService):

"""Metadata service based on ConfigDrive for Apache CloudStack.

Apache CloudStack is an open source software designed to deploy and
manage large networks of virtual machines, as a highly available,
highly scalable Infrastructure as a Service (IaaS) cloud computing
platform.
"""

def __init__(self):
super(ConfigDrive, self).__init__(
CONF.cloudstack.disk_label, 'openstack\\latest\\meta_data.json')

def _preprocess_options(self):
"""CloudStack ConfigDrive only supports CD-ROM"""
self._searched_types = set(['iso'])
self._searched_locations = set(['cdrom'])

def _get_password(self):
"""Read password from cloudstack/password/vm_password.txt file if exist
"""
password = None
path = posixpath.normpath(
posixpath.join('cloudstack', 'password', 'vm_password.txt'))
try:
password = self._get_cache_data(path, True)
LOG.info('Password file was found in ConfigDrive')
except base.NotExistingMetadataException:
LOG.info('No password file was found in ConfigDrive')
return password

def get_admin_password(self):
return self._get_password()

@property
def can_update_password(self):
"""The CloudStack Password Server supports password update."""
return True

def is_password_changed(self):
"""Check if a new password exists in the ConfigDrive."""
password = self._get_password()
if password:
osutils = osutils_factory.get_os_utils()
old_password_hash = osutils.get_config_value(
'PasswordHash', self.get_instance_id())
new_password_hash = hashlib.sha256(
password.encode('utf-8')).hexdigest()
if old_password_hash != new_password_hash:
LOG.debug('New password is detected')
osutils.set_config_value('PasswordHash', new_password_hash,
self.get_instance_id())
return True
return False
39 changes: 35 additions & 4 deletions doc/source/services.rst
Original file line number Diff line number Diff line change
Expand Up @@ -265,12 +265,12 @@ Config options for `default` section:
.. note:: http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html


Apache CloudStack
Apache CloudStack (DataServer)
-----------------

.. class:: cloudbaseinit.metadata.services.cloudstack.CloudStack
.. class:: cloudbaseinit.metadata.services.cloudstack.DataServer

Another web-based service which usually uses "10.1.1.1" or DHCP addresses for
Another web-based service which usually uses "data-server" DNS record or DHCP addresses for
retrieving content. If no metadata can be found at the `metadata_base_url`,
the service will look for the metadata at the DHCP server URL.

Expand All @@ -285,7 +285,7 @@ Capabilities:

Config options for `cloudstack` section:

* metadata_base_url (string: "http://10.1.1.1/")
* metadata_base_url (string: "http://data-server/")
* password_server_port (int: 8080)
* add_metadata_private_ip_route (bool: True)
* https_allow_insecure (bool: False)
Expand All @@ -302,6 +302,37 @@ Config options for `default` section:
and no updating will occur until a new password is available on the
server.

.. _configdrive:

Apache CloudStack (ConfigDrive)
-------------------------------

.. class:: cloudbaseinit.metadata.services.cloudstack.ConfigDrive

CloudStack also provides meta-data and user-data with help of CD-ROM without
requiring network access.

This service is usually faster than the HTTP twin, as there is no timeout
waiting for the network to be up.

Metadata version used: `latest`.

Capabilities:

* instance id
* hostname
* public keys
* admin user password
* user data

Config options for `cloudstack` section:

* disk_label (string: "config-2")

.. note:: By design, this service can update the password anytime, so it will
cause the `setuserpassword` plugin to run at every boot and the password hash
is stored right after retrieval and no updating will occur until a new password
is available on the server.

OpenNebula Service
------------------
Expand Down