Add subnets attribute to OS::Neutron::Port resource
Added subnets attribute to the port resource to fetch the subnet attributes such as gateway_ip which are associated with the port. Change-Id: Ia809c343d5b7d1488b505f9e9e20da02b36de07d Closes-Bug: #1336656
This commit is contained in:
parent
48f402e4c2
commit
5868fd6dd7
|
@ -50,11 +50,11 @@ class Port(neutron.NeutronResource):
|
|||
ATTRIBUTES = (
|
||||
ADMIN_STATE_UP_ATTR, DEVICE_ID_ATTR, DEVICE_OWNER_ATTR, FIXED_IPS_ATTR,
|
||||
MAC_ADDRESS_ATTR, NAME_ATTR, NETWORK_ID_ATTR, SECURITY_GROUPS_ATTR,
|
||||
STATUS, TENANT_ID, ALLOWED_ADDRESS_PAIRS_ATTR, SHOW,
|
||||
STATUS, TENANT_ID, ALLOWED_ADDRESS_PAIRS_ATTR, SHOW, SUBNETS_ATTR,
|
||||
) = (
|
||||
'admin_state_up', 'device_id', 'device_owner', 'fixed_ips',
|
||||
'mac_address', 'name', 'network_id', 'security_groups',
|
||||
'status', 'tenant_id', 'allowed_address_pairs', 'show',
|
||||
'status', 'tenant_id', 'allowed_address_pairs', 'show', 'subnets',
|
||||
)
|
||||
|
||||
properties_schema = {
|
||||
|
@ -194,6 +194,9 @@ class Port(neutron.NeutronResource):
|
|||
SHOW: attributes.Schema(
|
||||
_("All attributes.")
|
||||
),
|
||||
SUBNETS_ATTR: attributes.Schema(
|
||||
_("A list of all subnet attributes for the port.")
|
||||
),
|
||||
}
|
||||
|
||||
def validate(self):
|
||||
|
@ -269,6 +272,22 @@ class Port(neutron.NeutronResource):
|
|||
else:
|
||||
return self._delete_task()
|
||||
|
||||
def _resolve_attribute(self, name):
|
||||
if name == self.SUBNETS_ATTR:
|
||||
subnets = []
|
||||
try:
|
||||
fixed_ips = self._show_resource().get('fixed_ips', [])
|
||||
for fixed_ip in fixed_ips:
|
||||
subnet_id = fixed_ip.get('subnet_id')
|
||||
if subnet_id:
|
||||
subnets.append(self.neutron().show_subnet(
|
||||
subnet_id)['subnet'])
|
||||
except Exception as ex:
|
||||
LOG.warn(_("Failed to fetch resource attributes: %s") % ex)
|
||||
return
|
||||
return subnets
|
||||
return super(Port, self)._resolve_attribute(name)
|
||||
|
||||
def handle_update(self, json_snippet, tmpl_diff, prop_diff):
|
||||
props = self.prepare_update_properties(json_snippet)
|
||||
|
||||
|
|
|
@ -2158,6 +2158,7 @@ class NeutronPortTest(HeatTestCase):
|
|||
self.m.StubOutWithMock(neutronclient.Client, 'create_port')
|
||||
self.m.StubOutWithMock(neutronclient.Client, 'show_port')
|
||||
self.m.StubOutWithMock(neutronclient.Client, 'update_port')
|
||||
self.m.StubOutWithMock(neutronclient.Client, 'show_subnet')
|
||||
self.m.StubOutWithMock(neutronV20, 'find_resourceid_by_name_or_id')
|
||||
self.stub_keystoneclient()
|
||||
|
||||
|
@ -2442,6 +2443,125 @@ class NeutronPortTest(HeatTestCase):
|
|||
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_get_port_attributes(self):
|
||||
subnet_dict = {'name': 'test-subnet', 'enable_dhcp': True,
|
||||
'network_id': 'net1234', 'dns_nameservers': [],
|
||||
'tenant_id': '58a61fc3992944ce971404a2ece6ff98',
|
||||
'ipv6_ra_mode': None, 'cidr': '10.0.0.0/24',
|
||||
'allocation_pools': [{'start': '10.0.0.2',
|
||||
'end': u'10.0.0.254'}],
|
||||
'gateway_ip': '10.0.0.1', 'ipv6_address_mode': None,
|
||||
'ip_version': 4, 'host_routes': [],
|
||||
'id': '6dd609ad-d52a-4587-b1a0-b335f76062a5'}
|
||||
neutronV20.find_resourceid_by_name_or_id(
|
||||
mox.IsA(neutronclient.Client),
|
||||
'network',
|
||||
'net1234'
|
||||
).AndReturn('net1234')
|
||||
neutronclient.Client.create_port({'port': {
|
||||
'network_id': u'net1234',
|
||||
'name': utils.PhysName('test_stack', 'port'),
|
||||
'admin_state_up': True,
|
||||
'device_owner': u'network:dhcp'}}
|
||||
).AndReturn({'port': {
|
||||
'status': 'BUILD',
|
||||
'id': 'fc68ea2c-b60b-4b4f-bd82-94ec81110766'
|
||||
}})
|
||||
neutronclient.Client.show_subnet(
|
||||
'd0e971a6-a6b4-4f4c-8c88-b75e9c120b7e'
|
||||
).AndReturn({'subnet': subnet_dict})
|
||||
neutronclient.Client.show_port(
|
||||
'fc68ea2c-b60b-4b4f-bd82-94ec81110766'
|
||||
).MultipleTimes().AndReturn({'port': {
|
||||
'status': 'DOWN',
|
||||
'name': utils.PhysName('test_stack', 'port'),
|
||||
'allowed_address_pairs': [],
|
||||
'admin_state_up': True,
|
||||
'network_id': 'net1234',
|
||||
'device_id': 'dc68eg2c-b60g-4b3f-bd82-67ec87650532',
|
||||
'mac_address': 'fa:16:3e:75:67:60',
|
||||
'tenant_id': '58a61fc3992944ce971404a2ece6ff98',
|
||||
'security_groups': ['5b15d80c-6b70-4a1c-89c9-253538c5ade6'],
|
||||
'fixed_ips': [{'subnet_id': 'd0e971a6-a6b4-4f4c-8c88-b75e9c120b7e',
|
||||
'ip_address': '10.0.0.2'}]
|
||||
}})
|
||||
self.m.ReplayAll()
|
||||
|
||||
t = template_format.parse(neutron_port_template)
|
||||
t['Resources']['port']['Properties'].pop('fixed_ips')
|
||||
stack = utils.parse_stack(t)
|
||||
|
||||
port = stack['port']
|
||||
scheduler.TaskRunner(port.create)()
|
||||
self.assertEqual('DOWN', port.FnGetAtt('status'))
|
||||
self.assertEqual([], port.FnGetAtt('allowed_address_pairs'))
|
||||
self.assertEqual(True, port.FnGetAtt('admin_state_up'))
|
||||
self.assertEqual('net1234', port.FnGetAtt('network_id'))
|
||||
self.assertEqual('fa:16:3e:75:67:60', port.FnGetAtt('mac_address'))
|
||||
self.assertEqual(utils.PhysName('test_stack', 'port'),
|
||||
port.FnGetAtt('name'))
|
||||
self.assertEqual('dc68eg2c-b60g-4b3f-bd82-67ec87650532',
|
||||
port.FnGetAtt('device_id'))
|
||||
self.assertEqual('58a61fc3992944ce971404a2ece6ff98',
|
||||
port.FnGetAtt('tenant_id'))
|
||||
self.assertEqual(['5b15d80c-6b70-4a1c-89c9-253538c5ade6'],
|
||||
port.FnGetAtt('security_groups'))
|
||||
self.assertEqual([{'subnet_id': 'd0e971a6-a6b4-4f4c-8c88-b75e9c120b7e',
|
||||
'ip_address': '10.0.0.2'}],
|
||||
port.FnGetAtt('fixed_ips'))
|
||||
self.assertEqual([subnet_dict], port.FnGetAtt('subnets'))
|
||||
self.assertRaises(exception.InvalidTemplateAttribute,
|
||||
port.FnGetAtt, 'Foo')
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_subnet_attribute_exception(self):
|
||||
neutronV20.find_resourceid_by_name_or_id(
|
||||
mox.IsA(neutronclient.Client),
|
||||
'network',
|
||||
'net1234'
|
||||
).AndReturn('net1234')
|
||||
neutronclient.Client.create_port({'port': {
|
||||
'network_id': u'net1234',
|
||||
'name': utils.PhysName('test_stack', 'port'),
|
||||
'admin_state_up': True,
|
||||
'device_owner': u'network:dhcp'}}
|
||||
).AndReturn({'port': {
|
||||
'status': 'BUILD',
|
||||
'id': 'fc68ea2c-b60b-4b4f-bd82-94ec81110766'
|
||||
}})
|
||||
neutronclient.Client.show_port(
|
||||
'fc68ea2c-b60b-4b4f-bd82-94ec81110766'
|
||||
).MultipleTimes().AndReturn({'port': {
|
||||
'status': 'DOWN',
|
||||
'name': utils.PhysName('test_stack', 'port'),
|
||||
'allowed_address_pairs': [],
|
||||
'admin_state_up': True,
|
||||
'network_id': 'net1234',
|
||||
'device_id': 'dc68eg2c-b60g-4b3f-bd82-67ec87650532',
|
||||
'mac_address': 'fa:16:3e:75:67:60',
|
||||
'tenant_id': '58a61fc3992944ce971404a2ece6ff98',
|
||||
'security_groups': ['5b15d80c-6b70-4a1c-89c9-253538c5ade6'],
|
||||
'fixed_ips': [{'subnet_id': 'd0e971a6-a6b4-4f4c-8c88-b75e9c120b7e',
|
||||
'ip_address': '10.0.0.2'}]
|
||||
}})
|
||||
neutronclient.Client.show_subnet(
|
||||
'd0e971a6-a6b4-4f4c-8c88-b75e9c120b7e'
|
||||
).AndRaise(qe.NeutronClientException('ConnectionFailed: Connection '
|
||||
'to neutron failed: Maximum '
|
||||
'attempts reached'))
|
||||
self.m.ReplayAll()
|
||||
|
||||
t = template_format.parse(neutron_port_template)
|
||||
t['Resources']['port']['Properties'].pop('fixed_ips')
|
||||
stack = utils.parse_stack(t)
|
||||
port = stack['port']
|
||||
scheduler.TaskRunner(port.create)()
|
||||
self.assertIsNone(port.FnGetAtt('subnets'))
|
||||
log_msg = ('Failed to fetch resource attributes: ConnectionFailed: '
|
||||
'Connection to neutron failed: Maximum attempts reached')
|
||||
self.assertIn(log_msg, self.LOG.output)
|
||||
self.m.VerifyAll()
|
||||
|
||||
|
||||
class NetworkConstraintTest(HeatTestCase):
|
||||
|
||||
|
|
Loading…
Reference in New Issue