summaryrefslogtreecommitdiff
path: root/cloudinit/sources/DataSourceCloudStack.py
diff options
context:
space:
mode:
Diffstat (limited to 'cloudinit/sources/DataSourceCloudStack.py')
-rw-r--r--cloudinit/sources/DataSourceCloudStack.py80
1 files changed, 68 insertions, 12 deletions
diff --git a/cloudinit/sources/DataSourceCloudStack.py b/cloudinit/sources/DataSourceCloudStack.py
index 1bbeca59..64595020 100644
--- a/cloudinit/sources/DataSourceCloudStack.py
+++ b/cloudinit/sources/DataSourceCloudStack.py
@@ -26,18 +26,54 @@
import os
import time
+from socket import inet_ntoa
+from struct import pack
from cloudinit import ec2_utils as ec2
from cloudinit import log as logging
-from cloudinit import sources
from cloudinit import url_helper as uhelp
-from cloudinit import util
-from socket import inet_ntoa
-from struct import pack
+from cloudinit import sources, util
LOG = logging.getLogger(__name__)
+class CloudStackPasswordServerClient(object):
+ """
+ Implements password fetching from the CloudStack password server.
+
+ http://cloudstack-administration.readthedocs.org/
+ en/latest/templates.html#adding-password-management-to-your-templates
+ has documentation about the system. This implementation is following that
+ found at
+ https://github.com/shankerbalan/cloudstack-scripts/
+ blob/master/cloud-set-guest-password-debian
+ """
+
+ def __init__(self, virtual_router_address):
+ self.virtual_router_address = virtual_router_address
+
+ def _do_request(self, domu_request):
+ # The password server was in the past, a broken HTTP server, but is now
+ # fixed. wget handles this seamlessly, so it's easier to shell out to
+ # that rather than write our own handling code.
+ output, _ = util.subp([
+ 'wget', '--quiet', '--tries', '3', '--timeout', '20',
+ '--output-document', '-', '--header',
+ 'DomU_Request: {0}'.format(domu_request),
+ '{0}:8080'.format(self.virtual_router_address)
+ ])
+ return output.strip()
+
+ def get_password(self):
+ password = self._do_request('send_my_password')
+ if password in ['', 'saved_password']:
+ return None
+ if password == 'bad_request':
+ raise RuntimeError('Error when attempting to fetch root password.')
+ self._do_request('saved_password')
+ return password
+
+
class DataSourceCloudStack(sources.DataSource):
def __init__(self, sys_cfg, distro, paths):
sources.DataSource.__init__(self, sys_cfg, distro, paths)
@@ -45,10 +81,11 @@ class DataSourceCloudStack(sources.DataSource):
# Cloudstack has its metadata/userdata URLs located at
# http://<virtual-router-ip>/latest/
self.api_ver = 'latest'
- vr_addr = get_vr_address()
- if not vr_addr:
+ self.vr_addr = get_vr_address()
+ if not self.vr_addr:
raise RuntimeError("No virtual router found!")
- self.metadata_address = "http://%s/" % (vr_addr)
+ self.metadata_address = "http://%s/" % (self.vr_addr,)
+ self.cfg = {}
def _get_url_settings(self):
mcfg = self.ds_cfg
@@ -82,17 +119,20 @@ class DataSourceCloudStack(sources.DataSource):
'latest/meta-data/instance-id')]
start_time = time.time()
url = uhelp.wait_for_url(urls=urls, max_wait=max_wait,
- timeout=timeout, status_cb=LOG.warn)
+ timeout=timeout, status_cb=LOG.warn)
if url:
LOG.debug("Using metadata source: '%s'", url)
else:
LOG.critical(("Giving up on waiting for the metadata from %s"
" after %s seconds"),
- urls, int(time.time() - start_time))
+ urls, int(time.time() - start_time))
return bool(url)
+ def get_config_obj(self):
+ return self.cfg
+
def get_data(self):
seed_ret = {}
if util.read_optional_seed(seed_ret, base=(self.seed_dir + "/")):
@@ -104,12 +144,28 @@ class DataSourceCloudStack(sources.DataSource):
if not self.wait_for_metadata_service():
return False
start_time = time.time()
- self.userdata_raw = ec2.get_instance_userdata(self.api_ver,
- self.metadata_address)
+ self.userdata_raw = ec2.get_instance_userdata(
+ self.api_ver, self.metadata_address)
self.metadata = ec2.get_instance_metadata(self.api_ver,
self.metadata_address)
LOG.debug("Crawl of metadata service took %s seconds",
int(time.time() - start_time))
+ password_client = CloudStackPasswordServerClient(self.vr_addr)
+ try:
+ set_password = password_client.get_password()
+ except Exception:
+ util.logexc(LOG,
+ 'Failed to fetch password from virtual router %s',
+ self.vr_addr)
+ else:
+ if set_password:
+ self.cfg = {
+ 'ssh_pwauth': True,
+ 'password': set_password,
+ 'chpasswd': {
+ 'expire': False,
+ },
+ }
return True
except Exception:
util.logexc(LOG, 'Failed fetching from metadata service %s',
@@ -192,7 +248,7 @@ def get_vr_address():
# Used to match classes to dependencies
datasources = [
- (DataSourceCloudStack, (sources.DEP_FILESYSTEM, sources.DEP_NETWORK)),
+ (DataSourceCloudStack, (sources.DEP_FILESYSTEM, sources.DEP_NETWORK)),
]