~bloodearnest/charms/trusty/rabbitmq-server/add-nagios-service-groups

« back to all changes in this revision

Viewing changes to hooks/charmhelpers/contrib/openstack/amulet/utils.py

  • Committer: james.page at ubuntu
  • Date: 2015-01-23 08:23:05 UTC
  • mfrom: (79 rabbitmq-server)
  • mto: This revision was merged to the branch mainline in revision 80.
  • Revision ID: james.page@ubuntu.com-20150123082305-5uf1uk14iov78hl2
Rebase on next branch

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
import logging
 
2
import os
 
3
import time
 
4
import urllib
 
5
 
 
6
import glanceclient.v1.client as glance_client
 
7
import keystoneclient.v2_0 as keystone_client
 
8
import novaclient.v1_1.client as nova_client
 
9
 
 
10
import six
 
11
 
 
12
from charmhelpers.contrib.amulet.utils import (
 
13
    AmuletUtils
 
14
)
 
15
 
 
16
DEBUG = logging.DEBUG
 
17
ERROR = logging.ERROR
 
18
 
 
19
 
 
20
class OpenStackAmuletUtils(AmuletUtils):
 
21
    """OpenStack amulet utilities.
 
22
 
 
23
       This class inherits from AmuletUtils and has additional support
 
24
       that is specifically for use by OpenStack charms.
 
25
       """
 
26
 
 
27
    def __init__(self, log_level=ERROR):
 
28
        """Initialize the deployment environment."""
 
29
        super(OpenStackAmuletUtils, self).__init__(log_level)
 
30
 
 
31
    def validate_endpoint_data(self, endpoints, admin_port, internal_port,
 
32
                               public_port, expected):
 
33
        """Validate endpoint data.
 
34
 
 
35
           Validate actual endpoint data vs expected endpoint data. The ports
 
36
           are used to find the matching endpoint.
 
37
           """
 
38
        found = False
 
39
        for ep in endpoints:
 
40
            self.log.debug('endpoint: {}'.format(repr(ep)))
 
41
            if (admin_port in ep.adminurl and
 
42
                    internal_port in ep.internalurl and
 
43
                    public_port in ep.publicurl):
 
44
                found = True
 
45
                actual = {'id': ep.id,
 
46
                          'region': ep.region,
 
47
                          'adminurl': ep.adminurl,
 
48
                          'internalurl': ep.internalurl,
 
49
                          'publicurl': ep.publicurl,
 
50
                          'service_id': ep.service_id}
 
51
                ret = self._validate_dict_data(expected, actual)
 
52
                if ret:
 
53
                    return 'unexpected endpoint data - {}'.format(ret)
 
54
 
 
55
        if not found:
 
56
            return 'endpoint not found'
 
57
 
 
58
    def validate_svc_catalog_endpoint_data(self, expected, actual):
 
59
        """Validate service catalog endpoint data.
 
60
 
 
61
           Validate a list of actual service catalog endpoints vs a list of
 
62
           expected service catalog endpoints.
 
63
           """
 
64
        self.log.debug('actual: {}'.format(repr(actual)))
 
65
        for k, v in six.iteritems(expected):
 
66
            if k in actual:
 
67
                ret = self._validate_dict_data(expected[k][0], actual[k][0])
 
68
                if ret:
 
69
                    return self.endpoint_error(k, ret)
 
70
            else:
 
71
                return "endpoint {} does not exist".format(k)
 
72
        return ret
 
73
 
 
74
    def validate_tenant_data(self, expected, actual):
 
75
        """Validate tenant data.
 
76
 
 
77
           Validate a list of actual tenant data vs list of expected tenant
 
78
           data.
 
79
           """
 
80
        self.log.debug('actual: {}'.format(repr(actual)))
 
81
        for e in expected:
 
82
            found = False
 
83
            for act in actual:
 
84
                a = {'enabled': act.enabled, 'description': act.description,
 
85
                     'name': act.name, 'id': act.id}
 
86
                if e['name'] == a['name']:
 
87
                    found = True
 
88
                    ret = self._validate_dict_data(e, a)
 
89
                    if ret:
 
90
                        return "unexpected tenant data - {}".format(ret)
 
91
            if not found:
 
92
                return "tenant {} does not exist".format(e['name'])
 
93
        return ret
 
94
 
 
95
    def validate_role_data(self, expected, actual):
 
96
        """Validate role data.
 
97
 
 
98
           Validate a list of actual role data vs a list of expected role
 
99
           data.
 
100
           """
 
101
        self.log.debug('actual: {}'.format(repr(actual)))
 
102
        for e in expected:
 
103
            found = False
 
104
            for act in actual:
 
105
                a = {'name': act.name, 'id': act.id}
 
106
                if e['name'] == a['name']:
 
107
                    found = True
 
108
                    ret = self._validate_dict_data(e, a)
 
109
                    if ret:
 
110
                        return "unexpected role data - {}".format(ret)
 
111
            if not found:
 
112
                return "role {} does not exist".format(e['name'])
 
113
        return ret
 
114
 
 
115
    def validate_user_data(self, expected, actual):
 
116
        """Validate user data.
 
117
 
 
118
           Validate a list of actual user data vs a list of expected user
 
119
           data.
 
120
           """
 
121
        self.log.debug('actual: {}'.format(repr(actual)))
 
122
        for e in expected:
 
123
            found = False
 
124
            for act in actual:
 
125
                a = {'enabled': act.enabled, 'name': act.name,
 
126
                     'email': act.email, 'tenantId': act.tenantId,
 
127
                     'id': act.id}
 
128
                if e['name'] == a['name']:
 
129
                    found = True
 
130
                    ret = self._validate_dict_data(e, a)
 
131
                    if ret:
 
132
                        return "unexpected user data - {}".format(ret)
 
133
            if not found:
 
134
                return "user {} does not exist".format(e['name'])
 
135
        return ret
 
136
 
 
137
    def validate_flavor_data(self, expected, actual):
 
138
        """Validate flavor data.
 
139
 
 
140
           Validate a list of actual flavors vs a list of expected flavors.
 
141
           """
 
142
        self.log.debug('actual: {}'.format(repr(actual)))
 
143
        act = [a.name for a in actual]
 
144
        return self._validate_list_data(expected, act)
 
145
 
 
146
    def tenant_exists(self, keystone, tenant):
 
147
        """Return True if tenant exists."""
 
148
        return tenant in [t.name for t in keystone.tenants.list()]
 
149
 
 
150
    def authenticate_keystone_admin(self, keystone_sentry, user, password,
 
151
                                    tenant):
 
152
        """Authenticates admin user with the keystone admin endpoint."""
 
153
        unit = keystone_sentry
 
154
        service_ip = unit.relation('shared-db',
 
155
                                   'mysql:shared-db')['private-address']
 
156
        ep = "http://{}:35357/v2.0".format(service_ip.strip().decode('utf-8'))
 
157
        return keystone_client.Client(username=user, password=password,
 
158
                                      tenant_name=tenant, auth_url=ep)
 
159
 
 
160
    def authenticate_keystone_user(self, keystone, user, password, tenant):
 
161
        """Authenticates a regular user with the keystone public endpoint."""
 
162
        ep = keystone.service_catalog.url_for(service_type='identity',
 
163
                                              endpoint_type='publicURL')
 
164
        return keystone_client.Client(username=user, password=password,
 
165
                                      tenant_name=tenant, auth_url=ep)
 
166
 
 
167
    def authenticate_glance_admin(self, keystone):
 
168
        """Authenticates admin user with glance."""
 
169
        ep = keystone.service_catalog.url_for(service_type='image',
 
170
                                              endpoint_type='adminURL')
 
171
        return glance_client.Client(ep, token=keystone.auth_token)
 
172
 
 
173
    def authenticate_nova_user(self, keystone, user, password, tenant):
 
174
        """Authenticates a regular user with nova-api."""
 
175
        ep = keystone.service_catalog.url_for(service_type='identity',
 
176
                                              endpoint_type='publicURL')
 
177
        return nova_client.Client(username=user, api_key=password,
 
178
                                  project_id=tenant, auth_url=ep)
 
179
 
 
180
    def create_cirros_image(self, glance, image_name):
 
181
        """Download the latest cirros image and upload it to glance."""
 
182
        http_proxy = os.getenv('AMULET_HTTP_PROXY')
 
183
        self.log.debug('AMULET_HTTP_PROXY: {}'.format(http_proxy))
 
184
        if http_proxy:
 
185
            proxies = {'http': http_proxy}
 
186
            opener = urllib.FancyURLopener(proxies)
 
187
        else:
 
188
            opener = urllib.FancyURLopener()
 
189
 
 
190
        f = opener.open("http://download.cirros-cloud.net/version/released")
 
191
        version = f.read().strip()
 
192
        cirros_img = "cirros-{}-x86_64-disk.img".format(version)
 
193
        local_path = os.path.join('tests', cirros_img)
 
194
 
 
195
        if not os.path.exists(local_path):
 
196
            cirros_url = "http://{}/{}/{}".format("download.cirros-cloud.net",
 
197
                                                  version, cirros_img)
 
198
            opener.retrieve(cirros_url, local_path)
 
199
        f.close()
 
200
 
 
201
        with open(local_path) as f:
 
202
            image = glance.images.create(name=image_name, is_public=True,
 
203
                                         disk_format='qcow2',
 
204
                                         container_format='bare', data=f)
 
205
        count = 1
 
206
        status = image.status
 
207
        while status != 'active' and count < 10:
 
208
            time.sleep(3)
 
209
            image = glance.images.get(image.id)
 
210
            status = image.status
 
211
            self.log.debug('image status: {}'.format(status))
 
212
            count += 1
 
213
 
 
214
        if status != 'active':
 
215
            self.log.error('image creation timed out')
 
216
            return None
 
217
 
 
218
        return image
 
219
 
 
220
    def delete_image(self, glance, image):
 
221
        """Delete the specified image."""
 
222
        num_before = len(list(glance.images.list()))
 
223
        glance.images.delete(image)
 
224
 
 
225
        count = 1
 
226
        num_after = len(list(glance.images.list()))
 
227
        while num_after != (num_before - 1) and count < 10:
 
228
            time.sleep(3)
 
229
            num_after = len(list(glance.images.list()))
 
230
            self.log.debug('number of images: {}'.format(num_after))
 
231
            count += 1
 
232
 
 
233
        if num_after != (num_before - 1):
 
234
            self.log.error('image deletion timed out')
 
235
            return False
 
236
 
 
237
        return True
 
238
 
 
239
    def create_instance(self, nova, image_name, instance_name, flavor):
 
240
        """Create the specified instance."""
 
241
        image = nova.images.find(name=image_name)
 
242
        flavor = nova.flavors.find(name=flavor)
 
243
        instance = nova.servers.create(name=instance_name, image=image,
 
244
                                       flavor=flavor)
 
245
 
 
246
        count = 1
 
247
        status = instance.status
 
248
        while status != 'ACTIVE' and count < 60:
 
249
            time.sleep(3)
 
250
            instance = nova.servers.get(instance.id)
 
251
            status = instance.status
 
252
            self.log.debug('instance status: {}'.format(status))
 
253
            count += 1
 
254
 
 
255
        if status != 'ACTIVE':
 
256
            self.log.error('instance creation timed out')
 
257
            return None
 
258
 
 
259
        return instance
 
260
 
 
261
    def delete_instance(self, nova, instance):
 
262
        """Delete the specified instance."""
 
263
        num_before = len(list(nova.servers.list()))
 
264
        nova.servers.delete(instance)
 
265
 
 
266
        count = 1
 
267
        num_after = len(list(nova.servers.list()))
 
268
        while num_after != (num_before - 1) and count < 10:
 
269
            time.sleep(3)
 
270
            num_after = len(list(nova.servers.list()))
 
271
            self.log.debug('number of instances: {}'.format(num_after))
 
272
            count += 1
 
273
 
 
274
        if num_after != (num_before - 1):
 
275
            self.log.error('instance deletion timed out')
 
276
            return False
 
277
 
 
278
        return True