11
11
# License for the specific language governing permissions and limitations
12
12
# under the License.
15
16
from neutronclient.v2_0 import client as neutronclient
16
17
from novaclient import exceptions as nova_exceptions
18
20
from heat.common import exception
19
21
from heat.common import template_format
20
22
from heat.engine.clients.os import nova
21
23
from heat.engine import parser
22
24
from heat.engine.resources import eip
25
from heat.engine import rsrc_defn
23
26
from heat.engine import scheduler
24
27
from heat.tests.common import HeatTestCase
25
28
from heat.tests import utils
191
211
self.m.VerifyAll()
213
def test_eip_update(self):
214
nova.NovaClientPlugin._create().AndReturn(self.fc)
215
server_old = self.fc.servers.list()[0]
216
self.fc.servers.get('WebServer').AndReturn(server_old)
218
server_update = self.fc.servers.list()[1]
219
self.fc.servers.get('5678').MultipleTimes().AndReturn(server_update)
222
t = template_format.parse(eip_template)
223
stack = utils.parse_stack(t)
225
rsrc = self.create_eip(t, stack, 'IPAddress')
226
self.assertEqual('11.0.0.1', rsrc.FnGetRefId())
227
# update with the new InstanceId
228
props = copy.deepcopy(rsrc.properties.data)
229
update_server_id = '5678'
230
props['InstanceId'] = update_server_id
231
update_snippet = rsrc_defn.ResourceDefinition(rsrc.name, rsrc.type(),
233
scheduler.TaskRunner(rsrc.update, update_snippet)()
234
self.assertEqual((rsrc.UPDATE, rsrc.COMPLETE), rsrc.state)
235
self.assertEqual('11.0.0.1', rsrc.FnGetRefId())
236
# update without InstanceId
237
props = copy.deepcopy(rsrc.properties.data)
238
props.pop('InstanceId')
239
update_snippet = rsrc_defn.ResourceDefinition(rsrc.name, rsrc.type(),
241
scheduler.TaskRunner(rsrc.update, update_snippet)()
242
self.assertEqual((rsrc.UPDATE, rsrc.COMPLETE), rsrc.state)
193
245
def test_association_eip(self):
194
246
nova.NovaClientPlugin._create().AndReturn(self.fc)
195
247
self.fc.servers.get('WebServer').MultipleTimes() \
258
310
rsrc.handle_delete()
259
311
self.m.VerifyAll()
313
def test_delete_eip_successful_if_eip_associate_failed(self):
314
floating_ip = mox.IsA(object)
315
floating_ip.ip = '172.24.4.13'
316
floating_ip.id = '9037272b-6875-42e6-82e9-4342d5925da4'
318
self.m.StubOutWithMock(self.fc.floating_ips, 'create')
319
self.fc.floating_ips.create().AndReturn(floating_ip)
321
server = self.fc.servers.list()[0]
322
nova.NovaClientPlugin._create().AndReturn(self.fc)
323
self.fc.servers.get('WebServer').MultipleTimes().AndReturn(server)
325
self.m.StubOutWithMock(self.fc.servers, 'add_floating_ip')
326
self.fc.servers.add_floating_ip(server, floating_ip.ip, None).\
327
AndRaise(nova_exceptions.BadRequest(400))
329
self.m.StubOutWithMock(self.fc.servers, 'remove_floating_ip')
330
msg = ("ClientException: Floating ip 172.24.4.13 is not associated "
331
"with instance 1234.")
332
self.fc.servers.remove_floating_ip(server, floating_ip.ip).\
333
AndRaise(nova_exceptions.ClientException(422, msg))
334
self.m.StubOutWithMock(self.fc.floating_ips, 'delete')
335
self.fc.floating_ips.delete(mox.IsA(object))
339
t = template_format.parse(eip_template)
340
stack = utils.parse_stack(t)
341
resource_name = 'IPAddress'
342
resource_defns = stack.t.resource_definitions(stack)
343
rsrc = eip.ElasticIp(resource_name,
344
resource_defns[resource_name],
347
self.assertIsNone(rsrc.validate())
348
self.assertRaises(exception.ResourceFailure,
349
scheduler.TaskRunner(rsrc.create))
350
self.assertEqual((rsrc.CREATE, rsrc.FAILED), rsrc.state)
353
scheduler.TaskRunner(rsrc.delete)()
354
self.assertEqual((rsrc.DELETE, rsrc.COMPLETE), rsrc.state)
262
358
class AllocTest(HeatTestCase):
280
376
'add_gateway_router')
281
377
self.m.StubOutWithMock(neutronclient.Client, 'list_networks')
282
378
self.m.StubOutWithMock(neutronclient.Client, 'list_ports')
283
self.m.StubOutWithMock(neutronclient.Client, 'list_subnets')
284
379
self.m.StubOutWithMock(neutronclient.Client, 'show_network')
285
380
self.m.StubOutWithMock(neutronclient.Client, 'list_routers')
286
381
self.m.StubOutWithMock(neutronclient.Client,
287
382
'remove_gateway_router')
288
383
self.stub_keystoneclient()
385
def _setup_test_stack(self, stack_name):
386
t = template_format.parse(ipassoc_template_validate)
387
template = parser.Template(t)
388
stack = parser.Stack(utils.dummy_context(), stack_name,
389
template, stack_id='12233',
390
stack_user_project_id='8888')
392
return template, stack
394
def _validate_properties(self, stack, template, expected):
395
resource_defns = template.resource_definitions(stack)
396
rsrc = eip.ElasticIpAssociation('validate_eip_ass',
397
resource_defns['IPAssoc'],
400
exc = self.assertRaises(exception.StackValidationFailed,
402
self.assertIn(expected, six.text_type(exc))
290
404
def mock_show_network(self):
291
405
vpc_name = utils.PhysName('test_stack', 'the_vpc')
292
406
neutronclient.Client.show_network(
407
'22c26451-cf27-4d48-9031-51f5e397b84e'
294
408
).AndReturn({"network": {
295
409
"status": "BUILD",
408
522
"device_id": refid
411
def mock_list_subnets(self):
412
neutronclient.Client.list_subnets(
413
id='mysubnetid-70ec').AndReturn(
415
u'name': u'wp-Subnet-pyjm7bvoi4xw',
416
u'enable_dhcp': True,
417
u'network_id': u'aaaa-netid',
418
u'tenant_id': u'ecf538ec1729478fa1f97f1bf4fdcf7b',
419
u'dns_nameservers': [],
420
u'allocation_pools': [{u'start': u'192.168.9.2',
421
u'end': u'192.168.9.254'}],
424
u'gateway_ip': u'192.168.9.1',
425
u'cidr': u'192.168.9.0/24',
426
u'id': u'2c339ccd-734a-4acc-9f64-6f0dfe427e2d'
429
525
def mock_router_for_vpc(self):
430
526
vpc_name = utils.PhysName('test_stack', 'the_vpc')
431
527
neutronclient.Client.list_routers(name=vpc_name).AndReturn({
529
623
scheduler.TaskRunner(rsrc.delete)()
531
625
self.m.VerifyAll()
627
def test_validate_properties_EIP_and_AllocationId(self):
628
template, stack = self._setup_test_stack(
629
stack_name='validate_EIP_AllocationId')
631
properties = template.t['Resources']['IPAssoc']['Properties']
632
# test with EIP and AllocationId
633
properties['AllocationId'] = 'fc68ea2c-b60b-4b4f-bd82-94ec81110766'
634
expected = ("Either 'EIP' or 'AllocationId' must be provided.")
635
self._validate_properties(stack, template, expected)
637
# test without EIP and AllocationId
638
properties.pop('AllocationId')
639
properties.pop('EIP')
640
self._validate_properties(stack, template, expected)
642
def test_validate_EIP_and_InstanceId(self):
643
template, stack = self._setup_test_stack(
644
stack_name='validate_EIP_InstanceId')
645
properties = template.t['Resources']['IPAssoc']['Properties']
646
# test with EIP and no InstanceId
647
properties.pop('InstanceId')
648
expected = ("Must specify 'InstanceId' if you specify 'EIP'.")
649
self._validate_properties(stack, template, expected)
651
def test_validate_without_NetworkInterfaceId_and_InstanceId(self):
652
template, stack = self._setup_test_stack(
653
stack_name='validate_EIP_InstanceId')
655
properties = template.t['Resources']['IPAssoc']['Properties']
656
# test without NetworkInterfaceId and InstanceId
657
properties.pop('InstanceId')
658
properties.pop('EIP')
659
allocation_id = '1fafbe59-2332-4f5f-bfa4-517b4d6c1b65'
660
properties['AllocationId'] = allocation_id
661
expected = ("Must specify at least one of 'InstanceId' "
662
"or 'NetworkInterfaceId'.")
663
self._validate_properties(stack, template, expected)
665
def test_delete_association_successful_if_create_failed(self):
666
nova.NovaClientPlugin._create().AndReturn(self.fc)
667
server = self.fc.servers.list()[0]
668
self.fc.servers.get('WebServer').MultipleTimes() \
670
self.m.StubOutWithMock(self.fc.servers, 'add_floating_ip')
671
self.fc.servers.add_floating_ip(server, '11.0.0.1').AndRaise(
672
fakes.fake_exception(400))
675
t = template_format.parse(eip_template_ipassoc)
676
stack = utils.parse_stack(t)
678
self.create_eip(t, stack, 'IPAddress')
679
resource_defns = stack.t.resource_definitions(stack)
680
rsrc = eip.ElasticIpAssociation('IPAssoc',
681
resource_defns['IPAssoc'],
683
self.assertIsNone(rsrc.validate())
684
self.assertRaises(exception.ResourceFailure,
685
scheduler.TaskRunner(rsrc.create))
686
self.assertEqual((rsrc.CREATE, rsrc.FAILED), rsrc.state)
688
scheduler.TaskRunner(rsrc.delete)()
689
self.assertEqual((rsrc.DELETE, rsrc.COMPLETE), rsrc.state)