Remove main() and __main__ from tests.
[yardstick.git] / yardstick / tests / unit / benchmark / contexts / test_heat.py
1 ##############################################################################
2 # Copyright (c) 2015 Ericsson AB and others.
3 #
4 # All rights reserved. This program and the accompanying materials
5 # are made available under the terms of the Apache License, Version 2.0
6 # which accompanies this distribution, and is available at
7 # http://www.apache.org/licenses/LICENSE-2.0
8 ##############################################################################
9
10 from collections import OrderedDict
11 from itertools import count
12 import logging
13
14 import mock
15 import unittest
16
17 import shade
18
19 from yardstick.benchmark.contexts import base
20 from yardstick.benchmark.contexts import heat
21 from yardstick.benchmark.contexts import model
22 from yardstick.common import exceptions as y_exc
23 from yardstick.orchestrator import heat as orch_heat
24 from yardstick import ssh
25
26
27 LOG = logging.getLogger(__name__)
28
29
30 class HeatContextTestCase(unittest.TestCase):
31
32     def __init__(self, *args, **kwargs):
33         super(HeatContextTestCase, self).__init__(*args, **kwargs)
34         self.name_iter = ('vnf{:03}'.format(x) for x in count(0, step=3))
35
36     def setUp(self):
37         self.test_context = heat.HeatContext()
38         self.addCleanup(self._remove_contexts)
39         self.mock_context = mock.Mock(spec=heat.HeatContext())
40
41     def _remove_contexts(self):
42         if self.test_context in self.test_context.list:
43             self.test_context._delete_context()
44
45     def test___init__(self):
46         self.assertIsNone(self.test_context._name)
47         self.assertIsNone(self.test_context._task_id)
48         self.assertFalse(self.test_context._flags.no_setup)
49         self.assertFalse(self.test_context._flags.no_teardown)
50         self.assertIsNone(self.test_context.stack)
51         self.assertEqual(self.test_context.networks, OrderedDict())
52         self.assertEqual(self.test_context.servers, [])
53         self.assertEqual(self.test_context.placement_groups, [])
54         self.assertEqual(self.test_context.server_groups, [])
55         self.assertIsNone(self.test_context.keypair_name)
56         self.assertIsNone(self.test_context.secgroup_name)
57         self.assertEqual(self.test_context._server_map, {})
58         self.assertIsNone(self.test_context._image)
59         self.assertIsNone(self.test_context._flavor)
60         self.assertIsNone(self.test_context._user)
61         self.assertIsNone(self.test_context.template_file)
62         self.assertIsNone(self.test_context.heat_parameters)
63         self.assertIsNone(self.test_context.key_filename)
64
65     @mock.patch.object(ssh.SSH, 'gen_keys')
66     @mock.patch('yardstick.benchmark.contexts.heat.PlacementGroup')
67     @mock.patch('yardstick.benchmark.contexts.heat.ServerGroup')
68     @mock.patch('yardstick.benchmark.contexts.heat.Network')
69     @mock.patch('yardstick.benchmark.contexts.heat.Server')
70     def test_init(self, mock_server, mock_network, mock_sg, mock_pg, mock_ssh_gen_keys):
71
72         pgs = {'pgrp1': {'policy': 'availability'}}
73         sgs = {'servergroup1': {'policy': 'affinity'}}
74         networks = {'bar': {'cidr': '10.0.1.0/24'}}
75         servers = {'baz': {'floating_ip': True, 'placement': 'pgrp1'}}
76         attrs = {'name': 'foo',
77                  'task_id': '1234567890',
78                  'placement_groups': pgs,
79                  'server_groups': sgs,
80                  'networks': networks,
81                  'servers': servers}
82
83         self.test_context.init(attrs)
84
85         self.assertFalse(self.test_context._flags.no_setup)
86         self.assertFalse(self.test_context._flags.no_teardown)
87         self.assertEqual(self.test_context._name, "foo")
88         self.assertEqual(self.test_context._task_id, '1234567890')
89         self.assertEqual(self.test_context.name, "foo-12345678")
90         self.assertEqual(self.test_context.keypair_name, "foo-12345678-key")
91         self.assertEqual(self.test_context.secgroup_name, "foo-12345678-secgroup")
92
93         mock_pg.assert_called_with('pgrp1', self.test_context,
94                                    pgs['pgrp1']['policy'])
95         mock_sg.assert_called_with('servergroup1', self.test_context,
96                                    sgs['servergroup1']['policy'])
97         self.assertEqual(len(self.test_context.placement_groups), 1)
98         self.assertEqual(len(self.test_context.server_groups), 1)
99
100         mock_network.assert_called_with(
101             'bar', self.test_context, networks['bar'])
102         self.assertEqual(len(self.test_context.networks), 1)
103
104         mock_server.assert_called_with('baz', self.test_context,
105                                        servers['baz'])
106         self.assertEqual(len(self.test_context.servers), 1)
107
108         mock_ssh_gen_keys.assert_called()
109
110     def test_init_no_name_or_task_id(self):
111         attrs = {}
112         self.assertRaises(KeyError, self.test_context.init, attrs)
113
114     def test_name(self):
115         self.test_context._name = 'foo'
116         self.test_context._task_id = '1234567890'
117         self.test_context._name_task_id = '{}-{}'.format(
118             self.test_context._name, self.test_context._task_id[:8])
119         self.assertEqual(self.test_context.name, 'foo-12345678')
120         self.assertEqual(self.test_context.assigned_name, 'foo')
121
122     def test_name_flags(self):
123         self.test_context._flags = base.Flags(
124             **{"no_setup": True, "no_teardown": True})
125         self.test_context._name = 'foo'
126         self.test_context._task_id = '1234567890'
127
128         self.assertEqual(self.test_context.name, 'foo')
129         self.assertEqual(self.test_context.assigned_name, 'foo')
130
131     @mock.patch('yardstick.ssh.SSH.gen_keys')
132     def test_init_no_setup_no_teardown(self, *args):
133
134         attrs = {'name': 'foo',
135                  'task_id': '1234567890',
136                  'placement_groups': {},
137                  'server_groups': {},
138                  'networks': {},
139                  'servers': {},
140                  'flags': {
141                      'no_setup': True,
142                      'no_teardown': True,
143                      },
144                 }
145
146         self.test_context.init(attrs)
147         self.assertTrue(self.test_context._flags.no_setup)
148         self.assertTrue(self.test_context._flags.no_teardown)
149
150     @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
151     def test__add_resources_to_template_no_servers(self, mock_template):
152         self.test_context._name = 'ctx'
153         self.test_context._task_id = '1234567890'
154         self.test_context._name_task_id = '{}-{}'.format(
155             self.test_context._name, self.test_context._task_id[:8])
156         self.test_context.keypair_name = "ctx-key"
157         self.test_context.secgroup_name = "ctx-secgroup"
158         self.test_context.key_uuid = "2f2e4997-0a8e-4eb7-9fa4-f3f8fbbc393b"
159         netattrs = {'cidr': '10.0.0.0/24', 'provider': None,
160                     'external_network': 'ext_net'}
161
162         self.test_context.networks = OrderedDict(
163             {"mynet": model.Network("mynet", self.test_context,
164                                            netattrs)})
165
166         self.test_context._add_resources_to_template(mock_template)
167         mock_template.add_keypair.assert_called_with(
168             "ctx-key",
169             "ctx-12345678")
170         mock_template.add_security_group.assert_called_with("ctx-secgroup")
171         mock_template.add_network.assert_called_with(
172             "ctx-12345678-mynet", 'physnet1', None, None, None, None)
173         mock_template.add_router.assert_called_with(
174             "ctx-12345678-mynet-router",
175             netattrs["external_network"],
176             "ctx-12345678-mynet-subnet")
177         mock_template.add_router_interface.assert_called_with(
178             "ctx-12345678-mynet-router-if0",
179             "ctx-12345678-mynet-router",
180             "ctx-12345678-mynet-subnet")
181
182     @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
183     def test_attrs_get(self, *args):
184         image, flavor, user = expected_tuple = 'foo1', 'foo2', 'foo3'
185         self.assertNotEqual(self.test_context.image, image)
186         self.assertNotEqual(self.test_context.flavor, flavor)
187         self.assertNotEqual(self.test_context.user, user)
188         self.test_context._image = image
189         self.test_context._flavor = flavor
190         self.test_context._user = user
191         attr_tuple = self.test_context.image, self.test_context.flavor, self.test_context.user
192         self.assertEqual(attr_tuple, expected_tuple)
193
194     @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
195     def test_attrs_set_negative(self, *args):
196         with self.assertRaises(AttributeError):
197             self.test_context.image = 'foo'
198
199         with self.assertRaises(AttributeError):
200             self.test_context.flavor = 'foo'
201
202         with self.assertRaises(AttributeError):
203             self.test_context.user = 'foo'
204
205     def test__create_new_stack(self):
206         template = mock.Mock()
207         self.test_context._create_new_stack(template)
208         template.create.assert_called_once()
209
210     def test__create_new_stack_stack_create_failed(self):
211         template = mock.Mock()
212         template.create.side_effect = y_exc.HeatTemplateError
213
214         self.assertRaises(y_exc.HeatTemplateError,
215                           self.test_context._create_new_stack,
216                           template)
217
218     def test__create_new_stack_keyboard_interrupt(self):
219         template = mock.Mock()
220         template.create.side_effect = KeyboardInterrupt
221         self.assertRaises(y_exc.StackCreationInterrupt,
222                           self.test_context._create_new_stack,
223                           template)
224
225     @mock.patch.object(orch_heat.HeatTemplate, 'add_keypair')
226     @mock.patch.object(heat.HeatContext, '_create_new_stack')
227     def test_deploy_stack_creation_failed(self, mock_create, *args):
228         self.test_context._name = 'foo'
229         self.test_context._task_id = '1234567890'
230         self.test_context._name_task_id = 'foo-12345678'
231         mock_create.side_effect = y_exc.HeatTemplateError
232         self.assertRaises(y_exc.HeatTemplateError,
233                           self.test_context.deploy)
234
235     @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
236     def test_deploy(self, mock_template):
237         self.test_context._name = 'foo'
238         self.test_context._task_id = '1234567890'
239         self.test_context._name_task_id = '{}-{}'.format(
240             self.test_context._name, self.test_context._task_id[:8])
241         self.test_context.template_file = '/bar/baz/some-heat-file'
242         self.test_context.heat_parameters = {'image': 'cirros'}
243         self.test_context.get_neutron_info = mock.MagicMock()
244         self.test_context.deploy()
245
246         mock_template.assert_called_with('foo-12345678',
247                                          '/bar/baz/some-heat-file',
248                                          {'image': 'cirros'})
249         self.assertIsNotNone(self.test_context.stack)
250
251     # TODO: patch objects
252     @mock.patch.object(heat, 'HeatTemplate')
253     @mock.patch.object(heat.HeatContext, '_retrieve_existing_stack')
254     @mock.patch.object(heat.HeatContext, '_create_new_stack')
255     def test_deploy_no_setup(self, mock_create_new_stack, mock_retrieve_existing_stack, *args):
256         self.test_context._name = 'foo'
257         self.test_context._task_id = '1234567890'
258         # Might be able to get rid of these
259         self.test_context.template_file = '/bar/baz/some-heat-file'
260         self.test_context.heat_parameters = {'image': 'cirros'}
261         self.test_context.get_neutron_info = mock.MagicMock()
262         self.test_context._flags.no_setup = True
263         self.test_context.deploy()
264
265         # check that heat client is called...
266         mock_create_new_stack.assert_not_called()
267         mock_retrieve_existing_stack.assert_called_with(self.test_context.name)
268         self.assertIsNotNone(self.test_context.stack)
269
270     @mock.patch.object(shade, 'openstack_cloud')
271     @mock.patch.object(heat.HeatTemplate, 'add_keypair')
272     @mock.patch.object(heat.HeatContext, '_create_new_stack')
273     @mock.patch.object(heat.HeatStack, 'get')
274     def test_deploy_try_retrieve_context_does_not_exist(self,
275                                                         mock_get_stack,
276                                                         mock_create_new_stack,
277                                                         *args):
278         self.test_context._name = 'demo'
279         self.test_context._task_id = '1234567890'
280         self.test_context._flags.no_setup = True
281         self.test_context.get_neutron_info = mock.MagicMock()
282
283         # TODo: Check is this the right value to return, should it be None instead?
284         mock_get_stack.return_value = []
285
286         self.test_context.deploy()
287
288         mock_get_stack.assert_called()
289         mock_create_new_stack.assert_called()
290
291     def test_check_for_context(self):
292         pass
293         # check that the context exists
294
295     def test_add_server_port(self):
296         network1 = mock.MagicMock()
297         network2 = mock.MagicMock()
298         self.test_context._name = 'foo'
299         self.test_context._task_id = '1234567890'
300         self.test_context._name_task_id = '{}-{}'.format(
301             self.test_context._name, self.test_context._task_id[:8])
302         self.test_context.stack = mock.MagicMock()
303         self.test_context.networks = {
304             'a': network1,
305             'c': network2,
306         }
307         self.test_context.stack.outputs = {
308             u'b': u'10.20.30.45',
309             u'b-subnet_id': 1,
310             u'foo-12345678-a-subnet-cidr': u'10.20.0.0/15',
311             u'foo-12345678-a-subnet-gateway_ip': u'10.20.30.1',
312             u'b-mac_address': u'00:01',
313             u'b-device_id': u'dev21',
314             u'b-network_id': u'net789',
315             u'd': u'40.30.20.15',
316             u'd-subnet_id': 2,
317             u'foo-12345678-c-subnet-cidr': u'40.30.0.0/18',
318             u'foo-12345678-c-subnet-gateway_ip': u'40.30.20.254',
319             u'd-mac_address': u'00:10',
320             u'd-device_id': u'dev43',
321             u'd-network_id': u'net987',
322             u'e': u'40.30.20.15',
323             u'e-subnet_id': 2,
324             u'e-mac_address': u'00:10',
325             u'e-device_id': u'dev43',
326             u'e-network_id': u'net987',
327         }
328         server = mock.MagicMock()
329         server.ports = OrderedDict([
330             ('a', [{'stack_name': 'b', 'port': 'port_a'}]),
331             ('c', [{'stack_name': 'd', 'port': 'port_c'},
332                    {'stack_name': 'e', 'port': 'port_f'}]),
333         ])
334
335         expected = {
336             "private_ip": '10.20.30.45',
337             "subnet_id": 1,
338             "subnet_cidr": '10.20.0.0/15',
339             "network": '10.20.0.0',
340             "netmask": '255.254.0.0',
341             "name": "port_a",
342             "gateway_ip": '10.20.30.1',
343             "mac_address": '00:01',
344             "device_id": 'dev21',
345             "network_id": 'net789',
346             "network_name": 'a',
347             "local_mac": '00:01',
348             "local_ip": '10.20.30.45',
349         }
350         self.test_context.add_server_port(server)
351         self.assertEqual(server.private_ip, '10.20.30.45')
352         self.assertEqual(len(server.interfaces), 3)
353         self.assertDictEqual(server.interfaces['port_a'], expected)
354
355     @mock.patch('yardstick.benchmark.contexts.heat.os')
356     @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
357     def test_undeploy(self, mock_template, *args):
358         self.test_context.stack = mock_template
359         self.test_context._name = 'foo'
360         self.test_context._task_id = '1234567890'
361         self.test_context._name_task_id = '{}-{}'.format(
362             self.test_context._name, self.test_context._task_id[:8])
363         # mock_os.path.exists.return_value = True
364         self.test_context.key_filename = 'foo/bar/foobar'
365         self.test_context.undeploy()
366         self.assertTrue(mock_template.delete.called)
367
368     @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
369     def test_undeploy_no_teardown(self, mock_template):
370         self.test_context.stack = mock_template
371         self.test_context._name = 'foo'
372         self.test_context._task_id = '1234567890'
373         self.test_context._flags.no_teardown = True
374         self.test_context.undeploy()
375
376         mock_template.delete.assert_not_called()
377
378     @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
379     @mock.patch('yardstick.benchmark.contexts.heat.os')
380     def test_undeploy_key_filename(self, mock_os, mock_template):
381         self.test_context.stack = mock_template
382         self.test_context._name = 'foo'
383         self.test_context._task_id = '1234567890'
384         self.test_context._name_task_id = '{}-{}'.format(
385             self.test_context._name, self.test_context._task_id)
386         mock_os.path.exists.return_value = True
387         self.test_context.key_filename = 'foo/bar/foobar'
388         self.assertIsNone(self.test_context.undeploy())
389
390     @mock.patch("yardstick.benchmark.contexts.heat.pkg_resources")
391     def test__get_server_found_dict(self, *args):
392         """
393         Use HeatContext._get_server to get a server that matches
394         based on a dictionary input.
395         """
396         foo2_server = mock.Mock()
397         foo2_server.key_filename = None
398         foo2_server.private_ip = '10.0.0.2'
399         foo2_server.public_ip = '127.0.0.2'
400         foo2_server.context.user = 'oof'
401
402         baz3_server = mock.Mock()
403         baz3_server.key_filename = None
404         baz3_server.private_ip = '10.0.0.3'
405         baz3_server.public_ip = '127.0.0.3'
406         baz3_server.context.user = 'zab'
407
408         self.test_context._name = 'bar'
409         self.test_context._task_id = '1234567890'
410         self.test_context._name_task_id = '{}-{}'.format(
411             self.test_context._name, self.test_context._task_id[:8])
412         self.test_context._user = 'bot'
413         self.test_context.stack = mock.Mock()
414         self.test_context.stack.outputs = {
415             'private_ip': '10.0.0.1',
416             'public_ip': '127.0.0.1',
417         }
418         self.test_context._server_map = {
419             'baz3': baz3_server,
420             'foo2': foo2_server,
421         }
422
423         attr_name = {
424             'name': 'foo.bar-12345678',
425             'private_ip_attr': 'private_ip',
426             'public_ip_attr': 'public_ip',
427         }
428         self.test_context.key_uuid = 'foo-42'
429         result = self.test_context._get_server(attr_name)
430         self.assertEqual(result['user'], 'bot')
431         self.assertEqual(result['ip'], '127.0.0.1')
432         self.assertEqual(result['private_ip'], '10.0.0.1')
433
434     @mock.patch("yardstick.benchmark.contexts.heat.pkg_resources")
435     def test__get_server_found_dict_no_attrs(self, *args):
436         """
437         Use HeatContext._get_server to get a server that matches
438         based on a dictionary input.
439         """
440         foo2_server = mock.Mock()
441         foo2_server.private_ip = '10.0.0.2'
442         foo2_server.public_ip = '127.0.0.2'
443         foo2_server.context.user = 'oof'
444
445         baz3_server = mock.Mock()
446         baz3_server.private_ip = '10.0.0.3'
447         baz3_server.public_ip = '127.0.0.3'
448         baz3_server.context.user = 'zab'
449
450         self.test_context._name = 'bar'
451         self.test_context._task_id = '1234567890'
452         self.test_context._name_task_id = '{}-{}'.format(
453             self.test_context._name, self.test_context._task_id[:8])
454         self.test_context._user = 'bot'
455         self.test_context.stack = mock.Mock()
456         self.test_context.stack.outputs = {
457             'private_ip': '10.0.0.1',
458             'public_ip': '127.0.0.1',
459         }
460         self.test_context._server_map = {
461             'baz3': baz3_server,
462             'foo2': foo2_server,
463         }
464
465         attr_name = {
466             'name': 'foo.bar-12345678',
467         }
468
469         self.test_context.key_uuid = 'foo-42'
470         result = self.test_context._get_server(attr_name)
471         self.assertEqual(result['user'], 'bot')
472         # no private ip attr mapping in the map results in None value in the result
473         self.assertIsNone(result['private_ip'])
474         # no public ip attr mapping in the map results in no value in the result
475         self.assertNotIn('ip', result)
476
477     @mock.patch("yardstick.benchmark.contexts.heat.pkg_resources")
478     def test__get_server_found_not_dict(self, *args):
479         """
480         Use HeatContext._get_server to get a server that matches
481         based on a non-dictionary input
482         """
483         foo2_server = mock.Mock()
484         foo2_server.private_ip = '10.0.0.2'
485         foo2_server.public_ip = '127.0.0.2'
486         foo2_server.context.user = 'oof'
487
488         baz3_server = mock.Mock()
489         baz3_server.private_ip = '10.0.0.3'
490         baz3_server.public_ip = None
491         baz3_server.context.user = 'zab'
492
493         self.test_context._name = 'bar1'
494         self.test_context._task_id = '1234567890'
495         self.test_context._name_task_id = 'bar1-12345678'
496         self.test_context.stack = mock.Mock()
497         self.test_context.stack.outputs = {
498             'private_ip': '10.0.0.1',
499             'public_ip': '127.0.0.1',
500         }
501         self.test_context.generate_routing_table = mock.MagicMock(return_value=[])
502
503         self.test_context._server_map = {
504             'baz3': baz3_server,
505             'foo2': foo2_server,
506         }
507
508         attr_name = 'baz3'
509         result = self.test_context._get_server(attr_name)
510         self.assertEqual(result['user'], 'zab')
511         self.assertEqual(result['private_ip'], '10.0.0.3')
512         # no public_ip on the server results in no value in the result
513         self.assertNotIn('public_ip', result)
514
515     @mock.patch("yardstick.benchmark.contexts.heat.pkg_resources")
516     def test__get_server_none_found_not_dict(self, *args):
517         """
518         Use HeatContext._get_server to not get a server due to
519         None value associated with the match to a non-dictionary
520         input
521         """
522         foo2_server = mock.Mock()
523         foo2_server.private_ip = '10.0.0.2'
524         foo2_server.public_ip = '127.0.0.2'
525         foo2_server.context.user = 'oof'
526
527         baz3_server = mock.Mock()
528         baz3_server.private_ip = '10.0.0.3'
529         baz3_server.public_ip = None
530         baz3_server.context.user = 'zab'
531
532         self.test_context._name = 'bar1'
533         self.test_context.stack = mock.Mock()
534         self.test_context.stack.outputs = {
535             'private_ip': '10.0.0.1',
536             'public_ip': '127.0.0.1',
537         }
538         self.test_context._server_map = {
539             'baz3': baz3_server,
540             'foo2': foo2_server,
541             'wow4': None,
542         }
543
544         self.test_context.key_uuid = 'foo-42'
545         attr_name = 'wow4'
546         result = self.test_context._get_server(attr_name)
547         self.assertIsNone(result)
548
549     @mock.patch("yardstick.benchmark.contexts.heat.pkg_resources")
550     def test__get_server_not_found_dict(self, *args):
551         """
552         Use HeatContext._get_server to not get a server for lack
553         of a match to a dictionary input
554         """
555         foo2_server = mock.Mock()
556         foo2_server.private_ip = '10.0.0.2'
557         foo2_server.public_ip = '127.0.0.2'
558         foo2_server.context.user = 'oof'
559
560         baz3_server = mock.Mock()
561         baz3_server.private_ip = '10.0.0.3'
562         baz3_server.public_ip = None
563         baz3_server.context.user = 'zab'
564
565         self.test_context._name = 'bar1'
566         self.test_context._task_id = '1235467890'
567         self.test_context._name_task_id = '{}-{}'.format(
568             self.test_context._name, self.test_context._task_id[:8])
569         self.test_context.stack = mock.Mock()
570         self.test_context.stack.outputs = {
571             'private_ip': '10.0.0.1',
572             'public_ip': '127.0.0.1',
573         }
574         self.test_context._server_map = {
575             'baz3': baz3_server,
576             'foo2': foo2_server,
577         }
578
579         self.test_context.key_uuid = 'foo-42'
580         attr_name = {
581             'name': 'foo.wow4',
582             'private_ip_attr': 'private_ip',
583             'public_ip_attr': 'public_ip',
584         }
585         result = self.test_context._get_server(attr_name)
586         self.assertIsNone(result)
587
588     @mock.patch("yardstick.benchmark.contexts.heat.pkg_resources")
589     def test__get_server_not_found_not_dict(self, *args):
590         """
591         Use HeatContext._get_server to not get a server for lack
592         of a match to a non-dictionary input
593         """
594         foo2_server = mock.Mock()
595         foo2_server.private_ip = '10.0.0.2'
596         foo2_server.public_ip = '127.0.0.2'
597         foo2_server.context.user = 'oof'
598
599         baz3_server = mock.Mock()
600         baz3_server.private_ip = '10.0.0.3'
601         baz3_server.public_ip = None
602         baz3_server.context.user = 'zab'
603
604         self.mock_context._name = 'bar1'
605         self.test_context.stack = mock.Mock()
606         self.mock_context.stack.outputs = {
607             'private_ip': '10.0.0.1',
608             'public_ip': '127.0.0.1',
609         }
610         self.mock_context._server_map = {
611             'baz3': baz3_server,
612             'foo2': foo2_server,
613         }
614
615         self.test_context.key_uuid = 'foo-42'
616         attr_name = 'foo.wow4'
617         result = self.test_context._get_server(attr_name)
618         self.assertIsNone(result)
619
620     # TODO: Split this into more granular tests
621     def test__get_network(self):
622         network1 = mock.MagicMock()
623         network1.name = 'net_1'
624         network1.vld_id = 'vld111'
625         network1.segmentation_id = 'seg54'
626         network1.network_type = 'type_a'
627         network1.physical_network = 'phys'
628
629         network2 = mock.MagicMock()
630         network2.name = 'net_2'
631         network2.segmentation_id = 'seg45'
632         network2.network_type = 'type_b'
633         network2.physical_network = 'virt'
634
635         self.test_context.networks = {
636             'a': network1,
637             'b': network2,
638         }
639
640         attr_name = None
641         self.assertIsNone(self.test_context._get_network(attr_name))
642
643         attr_name = {}
644         self.assertIsNone(self.test_context._get_network(attr_name))
645
646         attr_name = {'network_type': 'nosuch'}
647         self.assertIsNone(self.test_context._get_network(attr_name))
648
649         attr_name = 'vld777'
650         self.assertIsNone(self.test_context._get_network(attr_name))
651
652         attr_name = {'segmentation_id': 'seg45'}
653         expected = {
654             "name": 'net_2',
655             "segmentation_id": 'seg45',
656             "network_type": 'type_b',
657             "physical_network": 'virt',
658         }
659         result = self.test_context._get_network(attr_name)
660         self.assertDictEqual(result, expected)
661
662         attr_name = 'a'
663         expected = {
664             "name": 'net_1',
665             "segmentation_id": 'seg54',
666             "network_type": 'type_a',
667             "physical_network": 'phys',
668         }
669         result = self.test_context._get_network(attr_name)
670         self.assertDictEqual(result, expected)