~ubuntu-branches/ubuntu/saucy/heat/saucy-updates

« back to all changes in this revision

Viewing changes to heat/engine/resources/nova_utils.py

  • Committer: Package Import Robot
  • Author(s): James Page, Chuck Short, James Page
  • Date: 2013-08-08 15:23:59 UTC
  • mfrom: (1.1.3)
  • Revision ID: package-import@ubuntu.com-20130808152359-9jgqjp23kssvc3x9
Tags: 2013.2~b2.a186.g2b4b248-0ubuntu1
[ Chuck Short ]
* debian/patches/rename-quantumclient.patch: Dropped no longer needed. 
* debian/control: Add python-oslo.sphinx

[ James Page ]
* New upstream snapshot.
* d/watch: Updated to track releases on launchpad.
* d/control: Drop BD in pep8, no longer required.
* d/control,rules: Drop use of openstack-pkg-tools, revert use of xz
  compression for debs.
* d/control,*.config,*.templates,po: Drop use of debconf/dbconfig-common
  to configure heat.
* d/*.upstart: Add upstart configurations for Ubuntu.
* d/p/default-kombu.patch: Switch default messaging from qpid to
  kombu.
* d/p/default-sqlite.patch: Use sqlite as default database option.
* d/control: Add python-ceilometerclient to BD's.
* d/rules: Fail package build for unit test failures.
* d/*.install: Directly install configuration files to /etc/heat.
* d/control: Update VCS locations to ubuntu-server-dev branches.
* d/heat-common.{install,manpages}: Include new binaries and associated
  manpages.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# vim: tabstop=4 shiftwidth=4 softtabstop=4
 
2
 
 
3
#
 
4
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
 
5
#    not use this file except in compliance with the License. You may obtain
 
6
#    a copy of the License at
 
7
#
 
8
#         http://www.apache.org/licenses/LICENSE-2.0
 
9
#
 
10
#    Unless required by applicable law or agreed to in writing, software
 
11
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 
12
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 
13
#    License for the specific language governing permissions and limitations
 
14
#    under the License.
 
15
"""Utilities for Resources that use the Openstack Nova API."""
 
16
 
 
17
from email.mime.multipart import MIMEMultipart
 
18
from email.mime.text import MIMEText
 
19
 
 
20
import json
 
21
import os
 
22
import pkgutil
 
23
 
 
24
from urlparse import urlparse
 
25
 
 
26
from oslo.config import cfg
 
27
 
 
28
from heat.common import exception
 
29
from heat.engine import clients
 
30
from heat.openstack.common import log as logging
 
31
from heat.openstack.common import uuidutils
 
32
 
 
33
logger = logging.getLogger(__name__)
 
34
 
 
35
 
 
36
def get_image_id(nova_client, image_identifier):
 
37
    '''
 
38
    Return an id for the specified image name or identifier.
 
39
 
 
40
    :param nova_client: the nova client to use
 
41
    :param image_identifier: image name or a UUID-like identifier
 
42
    :returns: the id of the requested :image_identifier:
 
43
    :raises: exception.ImageNotFound, exception.NoUniqueImageFound
 
44
    '''
 
45
    image_id = None
 
46
    if uuidutils.is_uuid_like(image_identifier):
 
47
        try:
 
48
            image_id = nova_client.images.get(image_identifier).id
 
49
        except clients.novaclient.exceptions.NotFound:
 
50
            logger.info("Image %s was not found in glance"
 
51
                        % image_identifier)
 
52
            raise exception.ImageNotFound(image_name=image_identifier)
 
53
    else:
 
54
        try:
 
55
            image_list = nova_client.images.list()
 
56
        except clients.novaclient.exceptions.ClientException as ex:
 
57
            raise exception.ServerError(message=str(ex))
 
58
        image_names = dict(
 
59
            (o.id, o.name)
 
60
            for o in image_list if o.name == image_identifier)
 
61
        if len(image_names) == 0:
 
62
            logger.info("Image %s was not found in glance" %
 
63
                        image_identifier)
 
64
            raise exception.ImageNotFound(image_name=image_identifier)
 
65
        elif len(image_names) > 1:
 
66
            logger.info("Mulitple images %s were found in glance with name"
 
67
                        % image_identifier)
 
68
            raise exception.NoUniqueImageFound(image_name=image_identifier)
 
69
        image_id = image_names.popitem()[0]
 
70
    return image_id
 
71
 
 
72
 
 
73
def get_flavor_id(nova_client, flavor):
 
74
    '''
 
75
    Get the id for the specified flavor name.
 
76
 
 
77
    :param nova_client: the nova client to use
 
78
    :param flavor: the name of the flavor to find
 
79
    :returns: the id of :flavor:
 
80
    :raises: exception.FlavorMissing
 
81
    '''
 
82
    flavor_id = None
 
83
    flavor_list = nova_client.flavors.list()
 
84
    for o in flavor_list:
 
85
        if o.name == flavor:
 
86
            flavor_id = o.id
 
87
            break
 
88
    if flavor_id is None:
 
89
        raise exception.FlavorMissing(flavor_id=flavor)
 
90
    return flavor_id
 
91
 
 
92
 
 
93
def get_keypair(nova_client, key_name):
 
94
    '''
 
95
    Get the public key specified by :key_name:
 
96
 
 
97
    :param nova_client: the nova client to use
 
98
    :param key_name: the name of the key to look for
 
99
    :returns: the keypair (name, public_key) for :key_name:
 
100
    :raises: exception.UserKeyPairMissing
 
101
    '''
 
102
    for keypair in nova_client.keypairs.list():
 
103
        if keypair.name == key_name:
 
104
            return keypair
 
105
    raise exception.UserKeyPairMissing(key_name=key_name)
 
106
 
 
107
 
 
108
def build_userdata(resource, userdata=None):
 
109
    '''
 
110
    Build multipart data blob for CloudInit which includes user-supplied
 
111
    Metadata, user data, and the required Heat in-instance configuration.
 
112
 
 
113
    :param resource: the resource implementation
 
114
    :type resource: heat.engine.Resource
 
115
    :param userdata: user data string
 
116
    :type userdata: str or None
 
117
    :returns: multipart mime as a string
 
118
    '''
 
119
 
 
120
    def make_subpart(content, filename, subtype=None):
 
121
        if subtype is None:
 
122
            subtype = os.path.splitext(filename)[0]
 
123
        msg = MIMEText(content, _subtype=subtype)
 
124
        msg.add_header('Content-Disposition', 'attachment',
 
125
                       filename=filename)
 
126
        return msg
 
127
 
 
128
    def read_cloudinit_file(fn):
 
129
        data = pkgutil.get_data('heat', 'cloudinit/%s' % fn)
 
130
        data = data.replace('@INSTANCE_USER@',
 
131
                            cfg.CONF.instance_user)
 
132
        return data
 
133
 
 
134
    attachments = [(read_cloudinit_file('config'), 'cloud-config'),
 
135
                   (read_cloudinit_file('boothook.sh'), 'boothook.sh',
 
136
                    'cloud-boothook'),
 
137
                   (read_cloudinit_file('part_handler.py'),
 
138
                    'part-handler.py'),
 
139
                   (userdata, 'cfn-userdata', 'x-cfninitdata'),
 
140
                   (read_cloudinit_file('loguserdata.py'),
 
141
                    'loguserdata.py', 'x-shellscript')]
 
142
 
 
143
    if 'Metadata' in resource.t:
 
144
        attachments.append((json.dumps(resource.metadata),
 
145
                            'cfn-init-data', 'x-cfninitdata'))
 
146
 
 
147
    attachments.append((cfg.CONF.heat_watch_server_url,
 
148
                        'cfn-watch-server', 'x-cfninitdata'))
 
149
 
 
150
    attachments.append((cfg.CONF.heat_metadata_server_url,
 
151
                        'cfn-metadata-server', 'x-cfninitdata'))
 
152
 
 
153
    # Create a boto config which the cfntools on the host use to know
 
154
    # where the cfn and cw API's are to be accessed
 
155
    cfn_url = urlparse(cfg.CONF.heat_metadata_server_url)
 
156
    cw_url = urlparse(cfg.CONF.heat_watch_server_url)
 
157
    is_secure = cfg.CONF.instance_connection_is_secure
 
158
    vcerts = cfg.CONF.instance_connection_https_validate_certificates
 
159
    boto_cfg = "\n".join(["[Boto]",
 
160
                          "debug = 0",
 
161
                          "is_secure = %s" % is_secure,
 
162
                          "https_validate_certificates = %s" % vcerts,
 
163
                          "cfn_region_name = heat",
 
164
                          "cfn_region_endpoint = %s" %
 
165
                          cfn_url.hostname,
 
166
                          "cloudwatch_region_name = heat",
 
167
                          "cloudwatch_region_endpoint = %s" %
 
168
                          cw_url.hostname])
 
169
    attachments.append((boto_cfg,
 
170
                        'cfn-boto-cfg', 'x-cfninitdata'))
 
171
 
 
172
    subparts = [make_subpart(*args) for args in attachments]
 
173
    mime_blob = MIMEMultipart(_subparts=subparts)
 
174
 
 
175
    return mime_blob.as_string()