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