~cloud-init-dev/cloud-init/trunk

« back to all changes in this revision

Viewing changes to cloudinit/sources/DataSourceCloudStack.py

  • Committer: Daniel Watkins
  • Date: 2015-06-16 16:35:03 UTC
  • mto: This revision was merged to the branch mainline in revision 1118.
  • Revision ID: daniel.watkins@canonical.com-20150616163503-a6pfzanz9v4c1hyf
Use wget to fetch CloudStack passwords.

Different versions of the CloudStack password server respond
differently; wget handles these nicely for us, so it's easier to just
use wget.

Show diffs side-by-side

added added

removed removed

Lines of Context:
29
29
from socket import inet_ntoa
30
30
from struct import pack
31
31
 
32
 
from six.moves import http_client
33
 
 
34
32
from cloudinit import ec2_utils as ec2
35
33
from cloudinit import log as logging
36
34
from cloudinit import url_helper as uhelp
47
45
    has documentation about the system.  This implementation is following that
48
46
    found at
49
47
    https://github.com/shankerbalan/cloudstack-scripts/blob/master/cloud-set-guest-password-debian
50
 
 
51
 
    The CloudStack password server is, essentially, a broken HTTP
52
 
    server. It requires us to provide a valid HTTP request (including a
53
 
    DomU_Request header, which is the meat of the request), but just
54
 
    writes the text of its response on to the socket, without a status
55
 
    line or any HTTP headers.  This makes HTTP libraries sad, which
56
 
    explains the screwiness of the implementation of this class.
57
 
 
58
 
    This should be fixed in CloudStack by commit
59
 
    a72f14ea9cb832faaac946b3cf9f56856b50142a in December 2014.
60
48
    """
61
49
 
62
50
    def __init__(self, virtual_router_address):
63
51
        self.virtual_router_address = virtual_router_address
64
52
 
65
53
    def _do_request(self, domu_request):
66
 
        # We have to provide a valid HTTP request, but a valid HTTP
67
 
        # response is not returned. This means that getresponse() chokes,
68
 
        # so we use the socket directly to read off the response.
69
 
        # Because we're reading off the socket directly, we can't re-use the
70
 
        # connection.
71
 
        conn = http_client.HTTPConnection(self.virtual_router_address, 8080)
72
 
        try:
73
 
            conn.request('GET', '', headers={'DomU_Request': domu_request})
74
 
            conn.sock.settimeout(30)
75
 
            output = conn.sock.recv(1024).decode('utf-8').strip()
76
 
        finally:
77
 
            conn.close()
78
 
        return output
 
54
        # The password server was in the past, a broken HTTP server, but is now
 
55
        # fixed.  wget handles this seamlessly, so it's easier to shell out to
 
56
        # that rather than write our own handling code.
 
57
        output, _ = util.subp([
 
58
            'wget', '--quiet', '--tries', '3', '--timeout', '20',
 
59
            '--output-document', '-', '--header',
 
60
            'DomU_Request: {0}'.format(domu_request),
 
61
            '{0}:8080'.format(self.virtual_router_address)
 
62
        ])
 
63
        return output.strip()
79
64
 
80
65
    def get_password(self):
81
66
        password = self._do_request('send_my_password')