# # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import copy import mock import mox from neutronclient.common import exceptions as qe from neutronclient.neutron import v2_0 as neutronV20 from neutronclient.v2_0 import client as neutronclient from heat.common import exception from heat.common import template_format from heat.common import timeutils from heat.engine.clients.os import neutron from heat.engine.hot import functions as hot_funcs from heat.engine import node_data from heat.engine import rsrc_defn from heat.engine import scheduler from heat.engine import stack as parser from heat.engine import stk_defn from heat.engine import template as tmpl from heat.tests import common from heat.tests import utils neutron_floating_template = ''' heat_template_version: 2015-04-30 description: Template to test floatingip Neutron resource resources: port_floating: type: OS::Neutron::Port properties: network: abcd1234 fixed_ips: - subnet: sub1234 ip_address: 10.0.0.10 floating_ip: type: OS::Neutron::FloatingIP properties: floating_network: abcd1234 floating_ip_assoc: type: OS::Neutron::FloatingIPAssociation properties: floatingip_id: { get_resource: floating_ip } port_id: { get_resource: port_floating } router: type: OS::Neutron::Router router_interface: type: OS::Neutron::RouterInterface properties: router_id: { get_resource: router } subnet: sub1234 gateway: type: OS::Neutron::RouterGateway properties: router_id: { get_resource: router } network: abcd1234 ''' neutron_floating_no_assoc_template = ''' heat_template_version: 2015-04-30 description: Template to test floatingip Neutron resource resources: network: type: OS::Neutron::Net subnet: type: OS::Neutron::Subnet properties: network: { get_resource: network } cidr: 10.0.3.0/24, port_floating: type: OS::Neutron::Port properties: network: { get_resource: network } fixed_ips: - subnet: { get_resource: subnet } ip_address: 10.0.0.10 floating_ip: type: OS::Neutron::FloatingIP properties: floating_network: abcd1234 port_id: { get_resource: port_floating } router: type: OS::Neutron::Router router_interface: type: OS::Neutron::RouterInterface properties: router_id: { get_resource: router } subnet: { get_resource: subnet } gateway: type: OS::Neutron::RouterGateway properties: router_id: { get_resource: router } network: abcd1234 ''' neutron_floating_template_deprecated = neutron_floating_template.replace( 'network', 'network_id').replace('subnet', 'subnet_id') class NeutronFloatingIPTest(common.HeatTestCase): def setUp(self): super(NeutronFloatingIPTest, self).setUp() self.m.StubOutWithMock(neutronclient.Client, 'create_floatingip') self.m.StubOutWithMock(neutronclient.Client, 'delete_floatingip') self.m.StubOutWithMock(neutronclient.Client, 'show_floatingip') self.m.StubOutWithMock(neutronclient.Client, 'update_floatingip') self.m.StubOutWithMock(neutronclient.Client, 'create_port') self.m.StubOutWithMock(neutronclient.Client, 'delete_port') self.m.StubOutWithMock(neutronclient.Client, 'update_port') self.m.StubOutWithMock(neutronclient.Client, 'show_port') self.m.StubOutWithMock(neutronV20, 'find_resourceid_by_name_or_id') self.m.StubOutWithMock(timeutils, 'retry_backoff_delay') self.patchobject(neutron.NeutronClientPlugin, 'has_extension', return_value=True) def test_floating_ip_validate(self): neutronV20.find_resourceid_by_name_or_id( mox.IsA(neutronclient.Client), 'network', 'abcd1234', cmd_resource=None, ).MultipleTimes().AndReturn('abcd1234') self.m.ReplayAll() t = template_format.parse(neutron_floating_no_assoc_template) stack = utils.parse_stack(t) fip = stack['floating_ip'] self.assertIsNone(fip.validate()) del t['resources']['floating_ip']['properties']['port_id'] t['resources']['floating_ip']['properties'][ 'fixed_ip_address'] = '10.0.0.12' stack = utils.parse_stack(t) fip = stack['floating_ip'] self.assertRaises(exception.ResourcePropertyDependency, fip.validate) self.m.VerifyAll() def test_floating_ip_router_interface(self): t = template_format.parse(neutron_floating_template) del t['resources']['gateway'] self._test_floating_ip(t) def test_floating_ip_router_gateway(self): t = template_format.parse(neutron_floating_template) del t['resources']['router_interface'] self._test_floating_ip(t, r_iface=False) def test_floating_ip_deprecated_router_interface(self): t = template_format.parse(neutron_floating_template_deprecated) del t['resources']['gateway'] self._test_floating_ip(t) def test_floating_ip_deprecated_router_gateway(self): t = template_format.parse(neutron_floating_template_deprecated) del t['resources']['router_interface'] self._test_floating_ip(t, r_iface=False) def _test_floating_ip(self, tmpl, r_iface=True): neutronV20.find_resourceid_by_name_or_id( mox.IsA(neutronclient.Client), 'network', 'abcd1234', cmd_resource=None, ).MultipleTimes().AndReturn('abcd1234') neutronclient.Client.create_floatingip({ 'floatingip': {'floating_network_id': u'abcd1234'} }).AndReturn({'floatingip': { 'id': 'fc68ea2c-b60b-4b4f-bd82-94ec81110766', 'floating_network_id': u'abcd1234' }}) neutronclient.Client.show_floatingip( 'fc68ea2c-b60b-4b4f-bd82-94ec81110766' ).AndRaise(qe.NeutronClientException(status_code=404)) neutronclient.Client.show_floatingip( 'fc68ea2c-b60b-4b4f-bd82-94ec81110766' ).AndReturn({'floatingip': { 'id': 'fc68ea2c-b60b-4b4f-bd82-94ec81110766', 'floating_network_id': u'abcd1234' }}) neutronclient.Client.show_floatingip( 'fc68ea2c-b60b-4b4f-bd82-94ec81110766' ).AndReturn({'floatingip': { 'id': 'fc68ea2c-b60b-4b4f-bd82-94ec81110766', 'floating_network_id': u'abcd1234' }}) timeutils.retry_backoff_delay(1, jitter_max=2.0).AndReturn(0.01) neutronclient.Client.delete_floatingip( 'fc68ea2c-b60b-4b4f-bd82-94ec81110766').AndReturn(None) neutronclient.Client.show_floatingip( 'fc68ea2c-b60b-4b4f-bd82-94ec81110766' ).AndReturn({'floatingip': { 'id': 'fc68ea2c-b60b-4b4f-bd82-94ec81110766', 'floating_network_id': u'abcd1234' }}) neutronclient.Client.delete_floatingip( 'fc68ea2c-b60b-4b4f-bd82-94ec81110766').AndReturn(None) neutronclient.Client.show_floatingip( 'fc68ea2c-b60b-4b4f-bd82-94ec81110766').AndRaise( qe.NeutronClientException(status_code=404)) neutronclient.Client.delete_floatingip( 'fc68ea2c-b60b-4b4f-bd82-94ec81110766').AndRaise( qe.NeutronClientException(status_code=404)) self.stub_NetworkConstraint_validate() stack = utils.parse_stack(tmpl) # assert the implicit dependency between the floating_ip # and the gateway self.m.ReplayAll() if r_iface: required_by = set(stack.dependencies.required_by( stack['router_interface'])) self.assertIn(stack['floating_ip_assoc'], required_by) else: deps = stack.dependencies[stack['gateway']] self.assertIn(stack['floating_ip'], deps) fip = stack['floating_ip'] scheduler.TaskRunner(fip.create)() self.assertEqual((fip.CREATE, fip.COMPLETE), fip.state) fip.validate() fip_id = fip.FnGetRefId() self.assertEqual('fc68ea2c-b60b-4b4f-bd82-94ec81110766', fip_id) self.assertIsNone(fip.FnGetAtt('show')) self.assertEqual('fc68ea2c-b60b-4b4f-bd82-94ec81110766', fip.FnGetAtt('show')['id']) self.assertRaises(exception.InvalidTemplateAttribute, fip.FnGetAtt, 'Foo') self.assertEqual(u'abcd1234', fip.FnGetAtt('floating_network_id')) scheduler.TaskRunner(fip.delete)() fip.state_set(fip.CREATE, fip.COMPLETE, 'to delete again') scheduler.TaskRunner(fip.delete)() self.m.VerifyAll() def test_FnGetRefId(self): self.m.ReplayAll() t = template_format.parse(neutron_floating_template) stack = utils.parse_stack(t) rsrc = stack['floating_ip'] rsrc.resource_id = 'xyz' self.assertEqual('xyz', rsrc.FnGetRefId()) self.m.VerifyAll() def test_FnGetRefId_convergence_cache_data(self): neutronV20.find_resourceid_by_name_or_id( mox.IsA(neutronclient.Client), 'network', 'abcd1234', cmd_resource=None, ).MultipleTimes().AndReturn('abcd1234') neutronV20.find_resourceid_by_name_or_id( mox.IsA(neutronclient.Client), 'subnet', 'sub1234', cmd_resource=None, ).MultipleTimes().AndReturn('sub1234') self.m.ReplayAll() t = template_format.parse(neutron_floating_template) template = tmpl.Template(t) stack = parser.Stack(utils.dummy_context(), 'test', template, cache_data={ 'floating_ip': node_data.NodeData.from_dict({ 'uuid': mock.ANY, 'id': mock.ANY, 'action': 'CREATE', 'status': 'COMPLETE', 'reference_id': 'abc'})}) rsrc = stack.defn['floating_ip'] self.assertEqual('abc', rsrc.FnGetRefId()) def test_floatip_association_port(self): t = template_format.parse(neutron_floating_template) stack = utils.parse_stack(t) neutronV20.find_resourceid_by_name_or_id( mox.IsA(neutronclient.Client), 'network', 'abcd1234', cmd_resource=None, ).MultipleTimes().AndReturn('abcd1234') neutronV20.find_resourceid_by_name_or_id( mox.IsA(neutronclient.Client), 'subnet', 'sub1234', cmd_resource=None, ).MultipleTimes().AndReturn('sub1234') neutronclient.Client.create_floatingip({ 'floatingip': {'floating_network_id': u'abcd1234'} }).AndReturn({'floatingip': { "status": "ACTIVE", "id": "fc68ea2c-b60b-4b4f-bd82-94ec81110766" }}) neutronclient.Client.create_port({'port': { 'network_id': u'abcd1234', 'fixed_ips': [ {'subnet_id': u'sub1234', 'ip_address': u'10.0.0.10'} ], 'name': utils.PhysName(stack.name, 'port_floating'), 'admin_state_up': True}} ).AndReturn({'port': { "status": "BUILD", "id": "fc68ea2c-b60b-4b4f-bd82-94ec81110766" }}) neutronclient.Client.show_port( 'fc68ea2c-b60b-4b4f-bd82-94ec81110766' ).AndReturn({'port': { "status": "ACTIVE", "id": "fc68ea2c-b60b-4b4f-bd82-94ec81110766" }}) # create as neutronclient.Client.update_floatingip( 'fc68ea2c-b60b-4b4f-bd82-94ec81110766', { 'floatingip': { 'port_id': u'fc68ea2c-b60b-4b4f-bd82-94ec81110766'}} ).AndReturn({'floatingip': { "status": "ACTIVE", "id": "fc68ea2c-b60b-4b4f-bd82-94ec81110766" }}) # update as with port_id neutronclient.Client.update_floatingip( 'fc68ea2c-b60b-4b4f-bd82-94ec81110766', { 'floatingip': { 'port_id': u'2146dfbf-ba77-4083-8e86-d052f671ece5', 'fixed_ip_address': None}} ).AndReturn({'floatingip': { "status": "ACTIVE", "id": "fc68ea2c-b60b-4b4f-bd82-94ec81110766" }}) # update as with floatingip_id neutronclient.Client.update_floatingip( 'fc68ea2c-b60b-4b4f-bd82-94ec81110766', {'floatingip': { 'port_id': None }}).AndReturn(None) neutronclient.Client.update_floatingip( '2146dfbf-ba77-4083-8e86-d052f671ece5', { 'floatingip': { 'port_id': u'2146dfbf-ba77-4083-8e86-d052f671ece5', 'fixed_ip_address': None}} ).AndReturn({'floatingip': { "status": "ACTIVE", "id": "2146dfbf-ba77-4083-8e86-d052f671ece5" }}) # update as with both neutronclient.Client.update_floatingip( '2146dfbf-ba77-4083-8e86-d052f671ece5', {'floatingip': { 'port_id': None }}).AndReturn(None) neutronclient.Client.update_floatingip( 'fc68ea2c-b60b-4b4f-bd82-94ec81110766', { 'floatingip': { 'port_id': u'ade6fcac-7d47-416e-a3d7-ad12efe445c1', 'fixed_ip_address': None}} ).AndReturn({'floatingip': { "status": "ACTIVE", "id": "fc68ea2c-b60b-4b4f-bd82-94ec81110766" }}) # delete as neutronclient.Client.update_floatingip( 'fc68ea2c-b60b-4b4f-bd82-94ec81110766', {'floatingip': { 'port_id': None }}).AndReturn(None) neutronclient.Client.delete_port( 'fc68ea2c-b60b-4b4f-bd82-94ec81110766' ).AndReturn(None) neutronclient.Client.show_port( 'fc68ea2c-b60b-4b4f-bd82-94ec81110766' ).AndRaise(qe.PortNotFoundClient(status_code=404)) neutronclient.Client.delete_floatingip( 'fc68ea2c-b60b-4b4f-bd82-94ec81110766' ).AndReturn(None) neutronclient.Client.show_floatingip( 'fc68ea2c-b60b-4b4f-bd82-94ec81110766').AndRaise( qe.NeutronClientException(status_code=404)) neutronclient.Client.delete_port( 'fc68ea2c-b60b-4b4f-bd82-94ec81110766' ).AndRaise(qe.PortNotFoundClient(status_code=404)) neutronclient.Client.delete_floatingip( 'fc68ea2c-b60b-4b4f-bd82-94ec81110766' ).AndRaise(qe.NeutronClientException(status_code=404)) self.stub_PortConstraint_validate() self.m.ReplayAll() fip = stack['floating_ip'] scheduler.TaskRunner(fip.create)() self.assertEqual((fip.CREATE, fip.COMPLETE), fip.state) stk_defn.update_resource_data(stack.defn, fip.name, fip.node_data()) p = stack['port_floating'] scheduler.TaskRunner(p.create)() self.assertEqual((p.CREATE, p.COMPLETE), p.state) stk_defn.update_resource_data(stack.defn, p.name, p.node_data()) fipa = stack['floating_ip_assoc'] scheduler.TaskRunner(fipa.create)() self.assertEqual((fipa.CREATE, fipa.COMPLETE), fipa.state) stk_defn.update_resource_data(stack.defn, fipa.name, fipa.node_data()) self.assertIsNotNone(fipa.id) self.assertEqual(fipa.id, fipa.resource_id) fipa.validate() # test update FloatingIpAssociation with port_id props = copy.deepcopy(fipa.properties.data) update_port_id = '2146dfbf-ba77-4083-8e86-d052f671ece5' props['port_id'] = update_port_id update_snippet = rsrc_defn.ResourceDefinition(fipa.name, fipa.type(), stack.t.parse(stack.defn, props)) scheduler.TaskRunner(fipa.update, update_snippet)() self.assertEqual((fipa.UPDATE, fipa.COMPLETE), fipa.state) # test update FloatingIpAssociation with floatingip_id props = copy.deepcopy(fipa.properties.data) update_flip_id = '2146dfbf-ba77-4083-8e86-d052f671ece5' props['floatingip_id'] = update_flip_id update_snippet = rsrc_defn.ResourceDefinition(fipa.name, fipa.type(), props) scheduler.TaskRunner(fipa.update, update_snippet)() self.assertEqual((fipa.UPDATE, fipa.COMPLETE), fipa.state) # test update FloatingIpAssociation with port_id and floatingip_id props = copy.deepcopy(fipa.properties.data) update_flip_id = 'fc68ea2c-b60b-4b4f-bd82-94ec81110766' update_port_id = 'ade6fcac-7d47-416e-a3d7-ad12efe445c1' props['floatingip_id'] = update_flip_id props['port_id'] = update_port_id update_snippet = rsrc_defn.ResourceDefinition(fipa.name, fipa.type(), props) scheduler.TaskRunner(fipa.update, update_snippet)() self.assertEqual((fipa.UPDATE, fipa.COMPLETE), fipa.state) scheduler.TaskRunner(fipa.delete)() scheduler.TaskRunner(p.delete)() scheduler.TaskRunner(fip.delete)() fip.state_set(fip.CREATE, fip.COMPLETE, 'to delete again') p.state_set(p.CREATE, p.COMPLETE, 'to delete again') self.assertIsNone(scheduler.TaskRunner(p.delete)()) scheduler.TaskRunner(fip.delete)() self.m.VerifyAll() def test_floatip_port_dependency_subnet(self): t = template_format.parse(neutron_floating_no_assoc_template) stack = utils.parse_stack(t) p_result = self.patchobject(hot_funcs.GetResource, 'result') p_result.return_value = 'subnet_uuid' # check dependencies for fip resource required_by = set(stack.dependencies.required_by( stack['router_interface'])) self.assertIn(stack['floating_ip'], required_by) self.m.VerifyAll() def test_floatip_port_dependency_network(self): t = template_format.parse(neutron_floating_no_assoc_template) del t['resources']['port_floating']['properties']['fixed_ips'] stack = utils.parse_stack(t) p_show = self.patchobject(neutronclient.Client, 'show_network') p_show.return_value = {'network': {'subnets': ['subnet_uuid']}} p_result = self.patchobject(hot_funcs.GetResource, 'result', autospec=True) def return_uuid(self): if self.args == 'network': return 'net_uuid' return 'subnet_uuid' p_result.side_effect = return_uuid # check dependencies for fip resource required_by = set(stack.dependencies.required_by( stack['router_interface'])) self.assertIn(stack['floating_ip'], required_by) p_show.assert_called_once_with('net_uuid') self.m.VerifyAll() def test_floatingip_create_specify_ip_address(self): neutronV20.find_resourceid_by_name_or_id( mox.IsA(neutronclient.Client), 'network', 'abcd1234', cmd_resource=None, ).MultipleTimes().AndReturn('abcd1234') self.stub_NetworkConstraint_validate() neutronclient.Client.create_floatingip({ 'floatingip': {'floating_network_id': u'abcd1234', 'floating_ip_address': '172.24.4.98'} }).AndReturn({'floatingip': { 'status': 'ACTIVE', 'id': 'fc68ea2c-b60b-4b4f-bd82-94ec81110766', 'floating_ip_address': '172.24.4.98' }}) neutronclient.Client.show_floatingip( 'fc68ea2c-b60b-4b4f-bd82-94ec81110766' ).AndReturn({'floatingip': { 'status': 'ACTIVE', 'id': 'fc68ea2c-b60b-4b4f-bd82-94ec81110766', 'floating_ip_address': '172.24.4.98' }}) self.m.ReplayAll() t = template_format.parse(neutron_floating_template) props = t['resources']['floating_ip']['properties'] props['floating_ip_address'] = '172.24.4.98' stack = utils.parse_stack(t) fip = stack['floating_ip'] scheduler.TaskRunner(fip.create)() self.assertEqual((fip.CREATE, fip.COMPLETE), fip.state) self.assertEqual('172.24.4.98', fip.FnGetAtt('floating_ip_address')) self.m.VerifyAll() def test_floatingip_create_specify_dns(self): neutronV20.find_resourceid_by_name_or_id( mox.IsA(neutronclient.Client), 'network', 'abcd1234', cmd_resource=None, ).MultipleTimes().AndReturn('abcd1234') self.stub_NetworkConstraint_validate() neutronclient.Client.create_floatingip({ 'floatingip': {'floating_network_id': u'abcd1234', 'dns_name': 'myvm', 'dns_domain': 'openstack.org.'} }).AndReturn({'floatingip': { 'status': 'ACTIVE', 'id': 'fc68ea2c-b60b-4b4f-bd82-94ec81110766', 'floating_ip_address': '172.24.4.98' }}) self.m.ReplayAll() t = template_format.parse(neutron_floating_template) props = t['resources']['floating_ip']['properties'] props['dns_name'] = 'myvm' props['dns_domain'] = 'openstack.org.' stack = utils.parse_stack(t) fip = stack['floating_ip'] scheduler.TaskRunner(fip.create)() self.assertEqual((fip.CREATE, fip.COMPLETE), fip.state) self.m.VerifyAll() def test_floatip_port(self): t = template_format.parse(neutron_floating_no_assoc_template) t['resources']['port_floating']['properties']['network'] = "xyz1234" t['resources']['port_floating']['properties'][ 'fixed_ips'][0]['subnet'] = "sub1234" t['resources']['router_interface']['properties']['subnet'] = "sub1234" stack = utils.parse_stack(t) neutronV20.find_resourceid_by_name_or_id( mox.IsA(neutronclient.Client), 'network', 'xyz1234', cmd_resource=None, ).MultipleTimes().AndReturn('xyz1234') neutronV20.find_resourceid_by_name_or_id( mox.IsA(neutronclient.Client), 'subnet', 'sub1234', cmd_resource=None, ).MultipleTimes().AndReturn('sub1234') neutronclient.Client.create_port({'port': { 'network_id': u'xyz1234', 'fixed_ips': [ {'subnet_id': u'sub1234', 'ip_address': u'10.0.0.10'} ], 'name': utils.PhysName(stack.name, 'port_floating'), 'admin_state_up': True}} ).AndReturn({'port': { "status": "BUILD", "id": "fc68ea2c-b60b-4b4f-bd82-94ec81110766" }}) neutronclient.Client.show_port( 'fc68ea2c-b60b-4b4f-bd82-94ec81110766' ).AndReturn({'port': { "status": "ACTIVE", "id": "fc68ea2c-b60b-4b4f-bd82-94ec81110766" }}) neutronV20.find_resourceid_by_name_or_id( mox.IsA(neutronclient.Client), 'network', 'abcd1234', cmd_resource=None, ).MultipleTimes().AndReturn('abcd1234') neutronclient.Client.create_floatingip({ 'floatingip': { 'floating_network_id': u'abcd1234', 'port_id': u'fc68ea2c-b60b-4b4f-bd82-94ec81110766' } }).AndReturn({'floatingip': { "status": "ACTIVE", "id": "fc68ea2c-b60b-4b4f-bd82-94ec81110766" }}) # update with new port_id neutronclient.Client.update_floatingip( 'fc68ea2c-b60b-4b4f-bd82-94ec81110766', { 'floatingip': { 'port_id': u'2146dfbf-ba77-4083-8e86-d052f671ece5', 'fixed_ip_address': None}} ).AndReturn({'floatingip': { "status": "ACTIVE", "id": "fc68ea2c-b60b-4b4f-bd82-94ec81110766" }}) # update with None port_id neutronclient.Client.update_floatingip( 'fc68ea2c-b60b-4b4f-bd82-94ec81110766', { 'floatingip': { 'port_id': None, 'fixed_ip_address': None}} ).AndReturn({'floatingip': { "status": "ACTIVE", "id": "fc68ea2c-b60b-4b4f-bd82-94ec81110766" }}) neutronclient.Client.delete_floatingip( 'fc68ea2c-b60b-4b4f-bd82-94ec81110766' ).AndReturn(None) neutronclient.Client.show_floatingip( 'fc68ea2c-b60b-4b4f-bd82-94ec81110766').AndRaise( qe.NeutronClientException(status_code=404)) neutronclient.Client.delete_port( 'fc68ea2c-b60b-4b4f-bd82-94ec81110766' ).AndReturn(None) neutronclient.Client.show_port( 'fc68ea2c-b60b-4b4f-bd82-94ec81110766' ).AndRaise(qe.PortNotFoundClient(status_code=404)) self.stub_PortConstraint_validate() self.m.ReplayAll() # check dependencies for fip resource required_by = set(stack.dependencies.required_by( stack['router_interface'])) self.assertIn(stack['floating_ip'], required_by) p = stack['port_floating'] scheduler.TaskRunner(p.create)() self.assertEqual((p.CREATE, p.COMPLETE), p.state) stk_defn.update_resource_data(stack.defn, p.name, p.node_data()) fip = stack['floating_ip'] scheduler.TaskRunner(fip.create)() self.assertEqual((fip.CREATE, fip.COMPLETE), fip.state) stk_defn.update_resource_data(stack.defn, fip.name, fip.node_data()) # test update FloatingIp with port_id props = copy.deepcopy(fip.properties.data) update_port_id = '2146dfbf-ba77-4083-8e86-d052f671ece5' props['port_id'] = update_port_id update_snippet = rsrc_defn.ResourceDefinition(fip.name, fip.type(), stack.t.parse(stack.defn, props)) scheduler.TaskRunner(fip.update, update_snippet)() self.assertEqual((fip.UPDATE, fip.COMPLETE), fip.state) stk_defn.update_resource_data(stack.defn, fip.name, fip.node_data()) # test update FloatingIp with None port_id props = copy.deepcopy(fip.properties.data) del(props['port_id']) update_snippet = rsrc_defn.ResourceDefinition(fip.name, fip.type(), stack.t.parse(stack.defn, props)) scheduler.TaskRunner(fip.update, update_snippet)() self.assertEqual((fip.UPDATE, fip.COMPLETE), fip.state) scheduler.TaskRunner(fip.delete)() scheduler.TaskRunner(p.delete)() self.m.VerifyAll() def test_add_dependencies(self): t = template_format.parse(neutron_floating_template) stack = utils.parse_stack(t) fipa = stack['floating_ip_assoc'] port = stack['port_floating'] r_int = stack['router_interface'] deps = mock.MagicMock() dep_list = [] def iadd(obj): dep_list.append(obj[1]) deps.__iadd__.side_effect = iadd deps.graph.return_value = {fipa: [port]} fipa.add_dependencies(deps) self.assertEqual([r_int], dep_list) def test_add_dependencies_without_fixed_ips_in_port(self): t = template_format.parse(neutron_floating_template) del t['resources']['port_floating']['properties']['fixed_ips'] stack = utils.parse_stack(t) fipa = stack['floating_ip_assoc'] port = stack['port_floating'] deps = mock.MagicMock() dep_list = [] def iadd(obj): dep_list.append(obj[1]) deps.__iadd__.side_effect = iadd deps.graph.return_value = {fipa: [port]} fipa.add_dependencies(deps) self.assertEqual([], dep_list)