~gz/pyjuju/0.5_unicode_token_backport

« back to all changes in this revision

Viewing changes to juju/providers/openstack/tests/test_ports.py

  • Committer: Clint Byrum
  • Author(s): Martin Packman
  • Date: 2012-09-10 08:32:41 UTC
  • Revision ID: clint@ubuntu.com-20120910083241-xueuh0bt5jl44w2b
OpenStack Provider

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
"""Tests for emulating port management with security groups"""
 
2
 
 
3
import logging
 
4
 
 
5
from juju import errors
 
6
from juju.lib.testing import TestCase
 
7
from juju.providers.openstack.machine import NovaProviderMachine
 
8
from juju.providers.openstack.ports import NovaPortManager
 
9
from juju.providers.openstack.tests import OpenStackTestMixin
 
10
 
 
11
 
 
12
class ProviderPortMgmtTests(OpenStackTestMixin, TestCase):
 
13
    """Tests for provider exposed port management methods"""
 
14
 
 
15
    def expect_create_rule(self, group_id, proto, port):
 
16
        self.expect_nova_post("os-security-group-rules",
 
17
            {'security_group_rule': {
 
18
                'parent_group_id': group_id,
 
19
                'ip_protocol': proto,
 
20
                'from_port': port,
 
21
                'to_port': port,
 
22
            }},
 
23
            response={'security_group_rule': {
 
24
                'id': 144, 'parent_group_id': group_id,
 
25
            }})
 
26
 
 
27
    def expect_existing_rule(self, rule_id, proto, port):
 
28
        self.expect_nova_get("servers/1000/os-security-groups",
 
29
            response={'security_groups': [
 
30
                    {'name': "juju-testing-1", 'id': 1, 'rules': [{
 
31
                        'id': rule_id,
 
32
                        'parent_group_id': 1,
 
33
                        'ip_protocol': proto,
 
34
                        'from_port': port,
 
35
                        'to_port': port,
 
36
                        }]
 
37
                    },
 
38
                ]})
 
39
 
 
40
    def test_open_port(self):
 
41
        """Opening a port adds the rule to the appropriate security group"""
 
42
        self.expect_nova_get("servers/1000/os-security-groups",
 
43
            response={'security_groups': [
 
44
                    {'name': "juju-testing-1", 'id': 1},
 
45
                ]})
 
46
        self.expect_create_rule(1, "tcp", 80)
 
47
        self.mocker.replay()
 
48
 
 
49
        log = self.capture_logging("juju.openstack", level=logging.DEBUG)
 
50
        machine = NovaProviderMachine('1000', "server1000.testing.invalid")
 
51
        deferred = self.get_provider().open_port(machine, "1", 80)
 
52
        def _check_log(_):
 
53
            self.assertIn("Opened 80/tcp on machine '1000'",
 
54
                log.getvalue())
 
55
        return deferred.addCallback(_check_log)
 
56
 
 
57
    def test_open_port_missing_group(self):
 
58
        """Missing security group raises an error on deleting port"""
 
59
        self.expect_nova_get("servers/1000/os-security-groups",
 
60
            response={'security_groups': []})
 
61
        self.mocker.replay()
 
62
 
 
63
        machine = NovaProviderMachine('1000', "server1000.testing.invalid")
 
64
        deferred = self.get_provider().open_port(machine, "1", 80)
 
65
        return self.assertFailure(deferred, errors.ProviderInteractionError)
 
66
 
 
67
    def test_close_port(self):
 
68
        """Closing a port removes the matching rule from the security group"""
 
69
        self.expect_existing_rule(12, "tcp", 80)
 
70
        self.expect_nova_delete("os-security-group-rules/12")
 
71
        self.mocker.replay()
 
72
 
 
73
        log = self.capture_logging("juju.openstack", level=logging.DEBUG)
 
74
        machine = NovaProviderMachine('1000', "server1000.testing.invalid")
 
75
        deferred = self.get_provider().close_port(machine, "1", 80)
 
76
        def _check_log(_):
 
77
            self.assertIn("Closed 80/tcp on machine '1000'",
 
78
                log.getvalue())
 
79
        return deferred.addCallback(_check_log)
 
80
 
 
81
    def test_close_port_missing_group(self):
 
82
        """Missing security group raises an error on closing port"""
 
83
        self.expect_nova_get("servers/1000/os-security-groups",
 
84
            response={'security_groups': []})
 
85
        self.mocker.replay()
 
86
 
 
87
        machine = NovaProviderMachine('1000', "server1000.testing.invalid")
 
88
        deferred = self.get_provider().close_port(machine, "1", 80)
 
89
        return self.assertFailure(deferred, errors.ProviderInteractionError)
 
90
 
 
91
    def test_close_port_missing_rule(self):
 
92
        """Missing security group rule raises an error on closing port"""
 
93
        self.expect_nova_get("servers/1000/os-security-groups",
 
94
            response={'security_groups': [{
 
95
                'name': "juju-testing-1", 'id': 1, "rules": [],
 
96
            }]})
 
97
        self.mocker.replay()
 
98
 
 
99
        machine = NovaProviderMachine('1000', "server1000.testing.invalid")
 
100
        deferred = self.get_provider().close_port(machine, "1", 80)
 
101
        return self.assertFailure(deferred, errors.ProviderInteractionError)
 
102
 
 
103
    def test_close_port_mismatching_rule(self):
 
104
        """Rule with different port raises an error on closing port"""
 
105
        self.expect_existing_rule(12, "tcp", 8080)
 
106
        self.mocker.replay()
 
107
 
 
108
        machine = NovaProviderMachine('1000', "server1000.testing.invalid")
 
109
        deferred = self.get_provider().close_port(machine, "1", 80)
 
110
        return self.assertFailure(deferred, errors.ProviderInteractionError)
 
111
 
 
112
    def test_get_opened_ports_none(self):
 
113
        """No opened ports are listed when there are no rules"""
 
114
        self.expect_nova_get("servers/1000/os-security-groups",
 
115
            response={'security_groups': [{
 
116
                'name': "juju-testing-1", 'id': 1, "rules": [],
 
117
            }]})
 
118
        self.mocker.replay()
 
119
 
 
120
        machine = NovaProviderMachine('1000', "server1000.testing.invalid")
 
121
        deferred = self.get_provider().get_opened_ports(machine, "1")
 
122
        return deferred.addCallback(self.assertEqual, set())
 
123
 
 
124
    def test_get_opened_ports_one(self):
 
125
        """Opened port is listed when there is a matching rule"""
 
126
        self.expect_existing_rule(12, "tcp", 80)
 
127
        self.mocker.replay()
 
128
 
 
129
        machine = NovaProviderMachine('1000', "server1000.testing.invalid")
 
130
        deferred = self.get_provider().get_opened_ports(machine, "1")
 
131
        return deferred.addCallback(self.assertEqual, set([(80, "tcp")]))
 
132
 
 
133
    def test_get_opened_ports_group_ignored(self):
 
134
        """Opened ports exclude rules delegating to other security groups"""
 
135
        self.expect_nova_get("servers/1000/os-security-groups",
 
136
            response={'security_groups': [{
 
137
                'name': "juju-testing-1", 'id': 1, "rules": [{
 
138
                        'id': 12,
 
139
                        'parent_group_id': 1,
 
140
                        'ip_protocol': None,
 
141
                        'from_port': None,
 
142
                        'to_port': None,
 
143
                        'group': {'name': "juju-testing"},
 
144
                        }],
 
145
            }]})
 
146
        self.mocker.replay()
 
147
 
 
148
        machine = NovaProviderMachine('1000', "server1000.testing.invalid")
 
149
        deferred = self.get_provider().get_opened_ports(machine, "1")
 
150
        return deferred.addCallback(self.assertEqual, set())
 
151
 
 
152
    def test_get_opened_ports_multiport_ignored(self):
 
153
        """Opened ports exclude rules spanning multiple ports"""
 
154
        self.expect_nova_get("servers/1000/os-security-groups",
 
155
            response={'security_groups': [{
 
156
                'name': "juju-testing-1", 'id': 1, "rules": [{
 
157
                        'id': 12,
 
158
                        'parent_group_id': 1,
 
159
                        'ip_protocol': "tcp",
 
160
                        'from_port': 8080,
 
161
                        'to_port': 8081,
 
162
                        }],
 
163
            }]})
 
164
        self.mocker.replay()
 
165
 
 
166
        machine = NovaProviderMachine('1000', "server1000.testing.invalid")
 
167
        deferred = self.get_provider().get_opened_ports(machine, "1")
 
168
        return deferred.addCallback(self.assertEqual, set())
 
169
 
 
170
 
 
171
class PortManagerTestMixin(OpenStackTestMixin):
 
172
 
 
173
    def get_port_manager(self):
 
174
        provider = self.get_provider()
 
175
        return NovaPortManager(provider.nova, provider.environment_name)
 
176
 
 
177
 
 
178
class EnsureGroupsTests(PortManagerTestMixin, TestCase):
 
179
    """Tests for ensure_groups method used when launching machines"""
 
180
 
 
181
    def expect_create_juju_group(self):
 
182
        self.expect_nova_post("os-security-groups",
 
183
            {'security_group': {
 
184
                'name': 'juju-testing',
 
185
                'description': 'juju group for testing',
 
186
            }},
 
187
            response={'security_group': {
 
188
                'id': 1,
 
189
            }})
 
190
        self.expect_nova_post("os-security-group-rules",
 
191
            {'security_group_rule': {
 
192
                'parent_group_id': 1,
 
193
                'ip_protocol': "tcp",
 
194
                'from_port': 22,
 
195
                'to_port': 22,
 
196
            }},
 
197
            response={'security_group_rule': {
 
198
                'id': 144, 'parent_group_id': 1,
 
199
            }})
 
200
        self.expect_nova_post("os-security-group-rules",
 
201
            {'security_group_rule': {
 
202
                'parent_group_id': 1,
 
203
                'group_id': 1,
 
204
                'ip_protocol': "tcp",
 
205
                'from_port': 1,
 
206
                'to_port': 65535,
 
207
            }},
 
208
            response={'security_group_rule': {
 
209
                'id': 145, 'parent_group_id': 1,
 
210
            }})
 
211
 
 
212
    def expect_create_machine_group(self, machine_id):
 
213
        machine = str(machine_id)
 
214
        self.expect_nova_post("os-security-groups",
 
215
            {'security_group': {
 
216
                'name': 'juju-testing-' + machine,
 
217
                'description': 'juju group for testing machine ' + machine,
 
218
            }},
 
219
            response={'security_group': {
 
220
                'id': 2,
 
221
            }})
 
222
 
 
223
    def check_group_names(self, result, machine_id):
 
224
        self.assertEqual(["juju-testing", "juju-testing-" + str(machine_id)],
 
225
            result)
 
226
 
 
227
    def test_none_existing(self):
 
228
        """When no groups exist juju and machine security groups are created"""
 
229
        self.expect_nova_get("os-security-groups",
 
230
            response={'security_groups': []})
 
231
        self.expect_create_juju_group()
 
232
        self.expect_create_machine_group(0)
 
233
        self.mocker.replay()
 
234
        deferred = self.get_port_manager().ensure_groups(0)
 
235
        return deferred.addCallback(self.check_group_names, 0)
 
236
 
 
237
    def test_other_existing(self):
 
238
        """Existing groups in a different environment are not affected"""
 
239
        self.expect_nova_get("os-security-groups",
 
240
            response={'security_groups': [
 
241
                    {'name': "juju-testingish", 'id': 7},
 
242
                    {'name': "juju-testingish-0", 'id': 8},
 
243
                ]})
 
244
        self.expect_create_juju_group()
 
245
        self.expect_create_machine_group(0)
 
246
        self.mocker.replay()
 
247
        deferred = self.get_port_manager().ensure_groups(0)
 
248
        return deferred.addCallback(self.check_group_names, 0)
 
249
 
 
250
    def test_existing_juju_group(self):
 
251
        """An exisiting juju security group is reused"""
 
252
        self.expect_nova_get("os-security-groups",
 
253
            response={'security_groups': [
 
254
                    {'name': "juju-testing", 'id': 1},
 
255
                ]})
 
256
        self.expect_create_machine_group(0)
 
257
        self.mocker.replay()
 
258
        deferred = self.get_port_manager().ensure_groups(0)
 
259
        return deferred.addCallback(self.check_group_names, 0)
 
260
 
 
261
    def test_existing_machine_group(self):
 
262
        """An existing machine security group is deleted and remade"""
 
263
        self.expect_nova_get("os-security-groups",
 
264
            response={'security_groups': [
 
265
                    {'name': "juju-testing-6", 'id': 3},
 
266
                ]})
 
267
        self.expect_create_juju_group()
 
268
        self.expect_nova_delete("os-security-groups/3")
 
269
        self.expect_create_machine_group(6)
 
270
        self.mocker.replay()
 
271
        deferred = self.get_port_manager().ensure_groups(6)
 
272
        return deferred.addCallback(self.check_group_names, 6)
 
273
 
 
274
 
 
275
class GetMachineGroupsTests(PortManagerTestMixin, TestCase):
 
276
    """Tests for get_machine_groups method needed for machine shutdown"""
 
277
 
 
278
    def test_normal(self):
 
279
        """A standard juju machine returns the machine group name and id"""
 
280
        self.expect_nova_get("servers/1000/os-security-groups",
 
281
            response={'security_groups': [
 
282
                    {'id': 7, 'name': "juju-testing"},
 
283
                    {'id': 8, 'name': "juju-testing-0"},
 
284
                ]})
 
285
        self.mocker.replay()
 
286
        machine = NovaProviderMachine(1000)
 
287
        deferred = self.get_port_manager().get_machine_groups(machine)
 
288
        return deferred.addCallback(self.assertEqual, {"juju-testing-0": 8})
 
289
 
 
290
    def test_normal_include_juju(self):
 
291
        """If param with_juju_group=True the juju group is also returned"""
 
292
        self.expect_nova_get("servers/1000/os-security-groups",
 
293
            response={'security_groups': [
 
294
                    {'id': 7, 'name': "juju-testing"},
 
295
                    {'id': 8, 'name': "juju-testing-0"},
 
296
                ]})
 
297
        self.mocker.replay()
 
298
        machine = NovaProviderMachine(1000)
 
299
        deferred = self.get_port_manager().get_machine_groups(machine, True)
 
300
        return deferred.addCallback(self.assertEqual,
 
301
            {"juju-testing": 7, "juju-testing-0": 8})
 
302
 
 
303
    def test_extra_group(self):
 
304
        """Additional groups not in the juju namespace are ignored"""
 
305
        self.expect_nova_get("servers/1000/os-security-groups",
 
306
            response={'security_groups': [
 
307
                    {'id': 1, 'name': "default"},
 
308
                    {'id': 7, 'name': "juju-testing"},
 
309
                    {'id': 8, 'name': "juju-testing-0"},
 
310
                ]})
 
311
        self.mocker.replay()
 
312
        machine = NovaProviderMachine(1000)
 
313
        deferred = self.get_port_manager().get_machine_groups(machine)
 
314
        return deferred.addCallback(self.assertEqual, {"juju-testing-0": 8})
 
315
 
 
316
    def test_other_group(self):
 
317
        """A server not managed by juju returns nothing"""
 
318
        self.expect_nova_get("servers/1000/os-security-groups",
 
319
            response={'security_groups': [
 
320
                    {'id': 1, 'name': "default"},
 
321
                ]})
 
322
        self.mocker.replay()
 
323
        machine = NovaProviderMachine(1000)
 
324
        deferred = self.get_port_manager().get_machine_groups(machine)
 
325
        return deferred.addCallback(self.assertEqual, None)
 
326
 
 
327
    def test_missing_groups(self):
 
328
        """A server with no groups returns nothing"""
 
329
        self.expect_nova_get("servers/1000/os-security-groups",
 
330
            response={'security_groups': []})
 
331
        self.mocker.replay()
 
332
        machine = NovaProviderMachine(1000)
 
333
        deferred = self.get_port_manager().get_machine_groups(machine)
 
334
        return deferred.addCallback(self.assertEqual, None)
 
335
 
 
336
    def test_error_missing_server(self):
 
337
        """A server that doesn't exist or has been deleted returns nothing"""
 
338
        self.expect_nova_get("servers/1000/os-security-groups",
 
339
            code=404, response={"itemNotFound": {
 
340
                "message": "Instance 1000 could not be found.",
 
341
                "code": 404,
 
342
            }})
 
343
        self.mocker.replay()
 
344
        machine = NovaProviderMachine(1000)
 
345
        deferred = self.get_port_manager().get_machine_groups(machine)
 
346
        return deferred.addCallback(self.assertEqual, None)
 
347
    # XXX: Broken by workaround for HP not supporting this api
 
348
    test_error_missing_server.skip = True
 
349
 
 
350
    def test_error_missing_page(self):
 
351
        """Unexpected errors from the client are propogated"""
 
352
        self.expect_nova_get("servers/1000/os-security-groups",
 
353
            code=404, response="404 Not Found\n\n"
 
354
                "The resource could not be found.\n\n   ")
 
355
        self.mocker.replay()
 
356
        machine = NovaProviderMachine(1000)
 
357
        deferred = self.get_port_manager().get_machine_groups(machine)
 
358
        return self.assertFailure(deferred, errors.ProviderInteractionError)
 
359
    # XXX: Need implemention of fancy error to exception mapping
 
360
    test_error_missing_page.skip = True
 
361
 
 
362
    def test_error_missing_server_fault(self):
 
363
        "A bogus compute fault due to lp:1010486 returns nothing"""
 
364
        self.expect_nova_get("servers/1000/os-security-groups",
 
365
            code=500, response={"computeFault": {
 
366
                "message": "The server has either erred or is incapable of"
 
367
                    " performing the requested operation.",
 
368
                "code": 500,
 
369
            }})
 
370
        self.expect_nova_get("servers/1000",
 
371
            code=404, response={"itemNotFound": {
 
372
                "message": "The resource could not be found.",
 
373
                "code": 404,
 
374
            }})
 
375
        self.mocker.replay()
 
376
        machine = NovaProviderMachine(1000)
 
377
        deferred = self.get_port_manager().get_machine_groups(machine)
 
378
        return deferred.addCallback(self.assertEqual, None)
 
379
    # XXX: Need implemention of fancy error to exception mapping
 
380
    test_error_missing_server_fault.skip = True
 
381
 
 
382
    def test_error_really_fault(self):
 
383
        """A real compute fault is propogated"""
 
384
        self.expect_nova_get("servers/1000/os-security-groups",
 
385
            code=500, response={"computeFault": {
 
386
                "message": "The server has either erred or is incapable of"
 
387
                    " performing the requested operation.",
 
388
                "code": 500,
 
389
            }})
 
390
        self.expect_nova_get("servers/1000", response={"server": {"id": 1000}})
 
391
        self.mocker.replay()
 
392
        machine = NovaProviderMachine(1000)
 
393
        deferred = self.get_port_manager().get_machine_groups(machine)
 
394
        return self.assertFailure(deferred, errors.ProviderInteractionError)
 
395
    # XXX: Need implemention of fancy error to exception mapping
 
396
    test_error_really_fault.skip = True