summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Watkins <daniel.watkins@canonical.com>2015-02-20 10:57:18 +0000
committerDaniel Watkins <daniel.watkins@canonical.com>2015-02-20 10:57:18 +0000
commitf8d9ebbe3743bcada75bc1a980b49f493e2da2f1 (patch)
tree565a4c965b96d5fc3733fa87ed2c1929683580e8
parentb57c6a109491f344fa6e6fc2593ab2e60ca65249 (diff)
downloadvyos-cloud-init-f8d9ebbe3743bcada75bc1a980b49f493e2da2f1.tar.gz
vyos-cloud-init-f8d9ebbe3743bcada75bc1a980b49f493e2da2f1.zip
Split CloudStack password handling out to separate class.
-rw-r--r--cloudinit/sources/DataSourceCloudStack.py65
1 files changed, 45 insertions, 20 deletions
diff --git a/cloudinit/sources/DataSourceCloudStack.py b/cloudinit/sources/DataSourceCloudStack.py
index 85f20c23..0c3c51c0 100644
--- a/cloudinit/sources/DataSourceCloudStack.py
+++ b/cloudinit/sources/DataSourceCloudStack.py
@@ -39,6 +39,49 @@ 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
+
+ The CloudStack password server is, essentially, a broken HTTP
+ server. It requires us to provide a valid HTTP request (including a
+ DomU_Request header, which is the meat of the request), but just
+ writes the text of its response on to the socket, without a status
+ line or any HTTP headers. This makes HTTP libraries sad, which
+ explains the screwiness of the implementation of this class.
+ """
+
+ def __init__(self, virtual_router_address):
+ self.virtual_router_address = virtual_router_address
+
+ def _do_request(self, domu_request):
+ # We have to provide a valid HTTP request, but a valid HTTP
+ # response is not returned. This means that getresponse() chokes,
+ # so we use the socket directly to read off the response.
+ # Because we're reading off the socket directly, we can't re-use the
+ # connection.
+ conn = http_client.HTTPConnection(self.virtual_router_address, 8080)
+ conn.request('GET', '', headers={'DomU_Request': domu_request})
+ conn.sock.settimeout(30)
+ output = conn.sock.recv(1024).decode('utf-8').strip()
+ conn.close()
+ return output
+
+ 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)
@@ -115,8 +158,9 @@ class DataSourceCloudStack(sources.DataSource):
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 = self.get_password()
+ set_password = password_client.get_password()
except Exception:
util.logexc(LOG,
'Failed to fetch password from virtual router %s',
@@ -136,25 +180,6 @@ class DataSourceCloudStack(sources.DataSource):
self.metadata_address)
return False
- def get_password(self):
- def _do_request(req_string):
- # We have to provide a valid HTTP request, but a valid HTTP
- # response is not returned. This means that getresponse() chokes,
- # so we use the socket directly to read off the password.
- conn = http_client.HTTPConnection(self.vr_addr, 8080)
- conn.request('GET', '', headers={'DomU_Request': req_string})
- conn.sock.settimeout(30)
- output = conn.sock.recv(1024).decode('utf-8').strip()
- conn.close()
- return output
- password = _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.')
- _do_request('saved_password')
- return password
-
def get_instance_id(self):
return self.metadata['instance-id']