Merge "Enable heat context to support existing network"
[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.private_ip = None
330         server.ports = OrderedDict([
331             ('a', [{'stack_name': 'b', 'port': 'port_a'}]),
332             ('c', [{'stack_name': 'd', 'port': 'port_c'},
333                    {'stack_name': 'e', 'port': 'port_f'}]),
334         ])
335
336         expected = {
337             "private_ip": '10.20.30.45',
338             "subnet_id": 1,
339             "subnet_cidr": '10.20.0.0/15',
340             "network": '10.20.0.0',
341             "netmask": '255.254.0.0',
342             "name": "port_a",
343             "gateway_ip": '10.20.30.1',
344             "mac_address": '00:01',
345             "device_id": 'dev21',
346             "network_id": 'net789',
347             "network_name": 'a',
348             "local_mac": '00:01',
349             "local_ip": '10.20.30.45',
350         }
351         self.test_context.add_server_port(server)
352         self.assertEqual(server.private_ip, '10.20.30.45')
353         self.assertEqual(len(server.interfaces), 3)
354         self.assertDictEqual(server.interfaces['port_a'], expected)
355
356     @mock.patch('yardstick.benchmark.contexts.heat.os')
357     @mock.patch.object(heat.HeatContext, '_delete_key_file')
358     @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
359     def test_undeploy(self, mock_template, mock_delete_key, *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         mock_delete_key.assert_called()
369         self.assertTrue(mock_template.delete.called)
370
371     @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
372     def test_undeploy_no_teardown(self, mock_template):
373         self.test_context.stack = mock_template
374         self.test_context._name = 'foo'
375         self.test_context._task_id = '1234567890'
376         self.test_context._flags.no_teardown = True
377         self.test_context.undeploy()
378
379         mock_template.delete.assert_not_called()
380
381     @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
382     @mock.patch('yardstick.benchmark.contexts.heat.os')
383     def test_undeploy_key_filename(self, mock_os, mock_template):
384         self.test_context.stack = mock_template
385         self.test_context._name = 'foo'
386         self.test_context._task_id = '1234567890'
387         self.test_context._name_task_id = '{}-{}'.format(
388             self.test_context._name, self.test_context._task_id)
389         mock_os.path.exists.return_value = True
390         self.test_context.key_filename = 'foo/bar/foobar'
391         self.assertIsNone(self.test_context.undeploy())
392
393     @mock.patch("yardstick.benchmark.contexts.heat.pkg_resources")
394     def test__get_server_found_dict(self, *args):
395         """
396         Use HeatContext._get_server to get a server that matches
397         based on a dictionary input.
398         """
399         foo2_server = mock.Mock()
400         foo2_server.key_filename = None
401         foo2_server.private_ip = '10.0.0.2'
402         foo2_server.public_ip = '127.0.0.2'
403         foo2_server.context.user = 'oof'
404
405         baz3_server = mock.Mock()
406         baz3_server.key_filename = None
407         baz3_server.private_ip = '10.0.0.3'
408         baz3_server.public_ip = '127.0.0.3'
409         baz3_server.context.user = 'zab'
410
411         self.test_context._name = 'bar'
412         self.test_context._task_id = '1234567890'
413         self.test_context._name_task_id = '{}-{}'.format(
414             self.test_context._name, self.test_context._task_id[:8])
415         self.test_context._user = 'bot'
416         self.test_context.stack = mock.Mock()
417         self.test_context.stack.outputs = {
418             'private_ip': '10.0.0.1',
419             'public_ip': '127.0.0.1',
420         }
421         self.test_context._server_map = {
422             'baz3': baz3_server,
423             'foo2': foo2_server,
424         }
425
426         attr_name = {
427             'name': 'foo.bar-12345678',
428             'private_ip_attr': 'private_ip',
429             'public_ip_attr': 'public_ip',
430         }
431         self.test_context.key_uuid = 'foo-42'
432         result = self.test_context._get_server(attr_name)
433         self.assertEqual(result['user'], 'bot')
434         self.assertEqual(result['ip'], '127.0.0.1')
435         self.assertEqual(result['private_ip'], '10.0.0.1')
436
437     @mock.patch("yardstick.benchmark.contexts.heat.pkg_resources")
438     def test__get_server_found_dict_no_attrs(self, *args):
439         """
440         Use HeatContext._get_server to get a server that matches
441         based on a dictionary input.
442         """
443         foo2_server = mock.Mock()
444         foo2_server.private_ip = '10.0.0.2'
445         foo2_server.public_ip = '127.0.0.2'
446         foo2_server.context.user = 'oof'
447
448         baz3_server = mock.Mock()
449         baz3_server.private_ip = '10.0.0.3'
450         baz3_server.public_ip = '127.0.0.3'
451         baz3_server.context.user = 'zab'
452
453         self.test_context._name = 'bar'
454         self.test_context._task_id = '1234567890'
455         self.test_context._name_task_id = '{}-{}'.format(
456             self.test_context._name, self.test_context._task_id[:8])
457         self.test_context._user = 'bot'
458         self.test_context.stack = mock.Mock()
459         self.test_context.stack.outputs = {
460             'private_ip': '10.0.0.1',
461             'public_ip': '127.0.0.1',
462         }
463         self.test_context._server_map = {
464             'baz3': baz3_server,
465             'foo2': foo2_server,
466         }
467
468         attr_name = {
469             'name': 'foo.bar-12345678',
470         }
471
472         self.test_context.key_uuid = 'foo-42'
473         result = self.test_context._get_server(attr_name)
474         self.assertEqual(result['user'], 'bot')
475         # no private ip attr mapping in the map results in None value in the result
476         self.assertIsNone(result['private_ip'])
477         # no public ip attr mapping in the map results in no value in the result
478         self.assertNotIn('ip', result)
479
480     @mock.patch("yardstick.benchmark.contexts.heat.pkg_resources")
481     def test__get_server_found_not_dict(self, *args):
482         """
483         Use HeatContext._get_server to get a server that matches
484         based on a non-dictionary input
485         """
486         foo2_server = mock.Mock()
487         foo2_server.private_ip = '10.0.0.2'
488         foo2_server.public_ip = '127.0.0.2'
489         foo2_server.context.user = 'oof'
490
491         baz3_server = mock.Mock()
492         baz3_server.private_ip = '10.0.0.3'
493         baz3_server.public_ip = None
494         baz3_server.context.user = 'zab'
495
496         self.test_context._name = 'bar1'
497         self.test_context._task_id = '1234567890'
498         self.test_context._name_task_id = 'bar1-12345678'
499         self.test_context.stack = mock.Mock()
500         self.test_context.stack.outputs = {
501             'private_ip': '10.0.0.1',
502             'public_ip': '127.0.0.1',
503         }
504         self.test_context.generate_routing_table = mock.MagicMock(return_value=[])
505
506         self.test_context._server_map = {
507             'baz3': baz3_server,
508             'foo2': foo2_server,
509         }
510
511         attr_name = 'baz3'
512         result = self.test_context._get_server(attr_name)
513         self.assertEqual(result['user'], 'zab')
514         self.assertEqual(result['private_ip'], '10.0.0.3')
515         # no public_ip on the server results in no value in the result
516         self.assertNotIn('public_ip', result)
517
518     @mock.patch("yardstick.benchmark.contexts.heat.pkg_resources")
519     def test__get_server_none_found_not_dict(self, *args):
520         """
521         Use HeatContext._get_server to not get a server due to
522         None value associated with the match to a non-dictionary
523         input
524         """
525         foo2_server = mock.Mock()
526         foo2_server.private_ip = '10.0.0.2'
527         foo2_server.public_ip = '127.0.0.2'
528         foo2_server.context.user = 'oof'
529
530         baz3_server = mock.Mock()
531         baz3_server.private_ip = '10.0.0.3'
532         baz3_server.public_ip = None
533         baz3_server.context.user = 'zab'
534
535         self.test_context._name = 'bar1'
536         self.test_context.stack = mock.Mock()
537         self.test_context.stack.outputs = {
538             'private_ip': '10.0.0.1',
539             'public_ip': '127.0.0.1',
540         }
541         self.test_context._server_map = {
542             'baz3': baz3_server,
543             'foo2': foo2_server,
544             'wow4': None,
545         }
546
547         self.test_context.key_uuid = 'foo-42'
548         attr_name = 'wow4'
549         result = self.test_context._get_server(attr_name)
550         self.assertIsNone(result)
551
552     @mock.patch("yardstick.benchmark.contexts.heat.pkg_resources")
553     def test__get_server_not_found_dict(self, *args):
554         """
555         Use HeatContext._get_server to not get a server for lack
556         of a match to a dictionary input
557         """
558         foo2_server = mock.Mock()
559         foo2_server.private_ip = '10.0.0.2'
560         foo2_server.public_ip = '127.0.0.2'
561         foo2_server.context.user = 'oof'
562
563         baz3_server = mock.Mock()
564         baz3_server.private_ip = '10.0.0.3'
565         baz3_server.public_ip = None
566         baz3_server.context.user = 'zab'
567
568         self.test_context._name = 'bar1'
569         self.test_context._task_id = '1235467890'
570         self.test_context._name_task_id = '{}-{}'.format(
571             self.test_context._name, self.test_context._task_id[:8])
572         self.test_context.stack = mock.Mock()
573         self.test_context.stack.outputs = {
574             'private_ip': '10.0.0.1',
575             'public_ip': '127.0.0.1',
576         }
577         self.test_context._server_map = {
578             'baz3': baz3_server,
579             'foo2': foo2_server,
580         }
581
582         self.test_context.key_uuid = 'foo-42'
583         attr_name = {
584             'name': 'foo.wow4',
585             'private_ip_attr': 'private_ip',
586             'public_ip_attr': 'public_ip',
587         }
588         result = self.test_context._get_server(attr_name)
589         self.assertIsNone(result)
590
591     @mock.patch("yardstick.benchmark.contexts.heat.pkg_resources")
592     def test__get_server_not_found_not_dict(self, *args):
593         """
594         Use HeatContext._get_server to not get a server for lack
595         of a match to a non-dictionary input
596         """
597         foo2_server = mock.Mock()
598         foo2_server.private_ip = '10.0.0.2'
599         foo2_server.public_ip = '127.0.0.2'
600         foo2_server.context.user = 'oof'
601
602         baz3_server = mock.Mock()
603         baz3_server.private_ip = '10.0.0.3'
604         baz3_server.public_ip = None
605         baz3_server.context.user = 'zab'
606
607         self.mock_context._name = 'bar1'
608         self.test_context.stack = mock.Mock()
609         self.mock_context.stack.outputs = {
610             'private_ip': '10.0.0.1',
611             'public_ip': '127.0.0.1',
612         }
613         self.mock_context._server_map = {
614             'baz3': baz3_server,
615             'foo2': foo2_server,
616         }
617
618         self.test_context.key_uuid = 'foo-42'
619         attr_name = 'foo.wow4'
620         result = self.test_context._get_server(attr_name)
621         self.assertIsNone(result)
622
623     # TODO: Split this into more granular tests
624     def test__get_network(self):
625         network1 = mock.MagicMock()
626         network1.name = 'net_1'
627         network1.vld_id = 'vld111'
628         network1.segmentation_id = 'seg54'
629         network1.network_type = 'type_a'
630         network1.physical_network = 'phys'
631
632         network2 = mock.MagicMock()
633         network2.name = 'net_2'
634         network2.segmentation_id = 'seg45'
635         network2.network_type = 'type_b'
636         network2.physical_network = 'virt'
637
638         self.test_context.networks = {
639             'a': network1,
640             'b': network2,
641         }
642
643         attr_name = None
644         self.assertIsNone(self.test_context._get_network(attr_name))
645
646         attr_name = {}
647         self.assertIsNone(self.test_context._get_network(attr_name))
648
649         attr_name = {'network_type': 'nosuch'}
650         self.assertIsNone(self.test_context._get_network(attr_name))
651
652         attr_name = 'vld777'
653         self.assertIsNone(self.test_context._get_network(attr_name))
654
655         attr_name = {'segmentation_id': 'seg45'}
656         expected = {
657             "name": 'net_2',
658             "segmentation_id": 'seg45',
659             "network_type": 'type_b',
660             "physical_network": 'virt',
661         }
662         result = self.test_context._get_network(attr_name)
663         self.assertDictEqual(result, expected)
664
665         attr_name = 'a'
666         expected = {
667             "name": 'net_1',
668             "segmentation_id": 'seg54',
669             "network_type": 'type_a',
670             "physical_network": 'phys',
671         }
672         result = self.test_context._get_network(attr_name)
673         self.assertDictEqual(result, expected)