Merge "Neutron resources observe reality implementation"
This commit is contained in:
commit
13f1f0d9fa
|
@ -181,6 +181,13 @@ class Firewall(neutron.NeutronResource):
|
|||
'firewall resource.')
|
||||
return super(Firewall, self)._resolve_attribute(name)
|
||||
|
||||
def parse_live_resource_data(self, resource_properties, resource_data):
|
||||
result = super(Firewall, self).parse_live_resource_data(
|
||||
resource_properties, resource_data)
|
||||
if self.SHARED in result:
|
||||
result.pop(self.SHARED)
|
||||
return result
|
||||
|
||||
|
||||
class FirewallPolicy(neutron.NeutronResource):
|
||||
"""A resource for the FirewallPolicy resource in Neutron FWaaS.
|
||||
|
|
|
@ -17,6 +17,7 @@ from heat.engine import constraints
|
|||
from heat.engine import properties
|
||||
from heat.engine.resources.openstack.neutron import neutron
|
||||
from heat.engine import support
|
||||
from heat.engine import translation
|
||||
|
||||
|
||||
class Net(neutron.NeutronResource):
|
||||
|
@ -168,6 +169,14 @@ class Net(neutron.NeutronResource):
|
|||
),
|
||||
}
|
||||
|
||||
def translation_rules(self, properties):
|
||||
return [translation.TranslationRule(
|
||||
properties,
|
||||
translation.TranslationRule.RESOLVE,
|
||||
[self.QOS_POLICY],
|
||||
client_plugin=self.client_plugin(),
|
||||
finder='get_qos_policy_id')]
|
||||
|
||||
def handle_create(self):
|
||||
props = self.prepare_properties(
|
||||
self.properties,
|
||||
|
@ -177,8 +186,7 @@ class Net(neutron.NeutronResource):
|
|||
qos_policy = props.pop(self.QOS_POLICY, None)
|
||||
tags = props.pop(self.TAGS, [])
|
||||
if qos_policy:
|
||||
props['qos_policy_id'] = self.client_plugin().get_qos_policy_id(
|
||||
qos_policy)
|
||||
props['qos_policy_id'] = qos_policy
|
||||
|
||||
net = self.client().create_network({'network': props})['network']
|
||||
self.resource_id_set(net['id'])
|
||||
|
@ -191,6 +199,7 @@ class Net(neutron.NeutronResource):
|
|||
|
||||
def check_create_complete(self, *args):
|
||||
attributes = self._show_resource()
|
||||
self._store_config_default_properties(attributes)
|
||||
return self.is_built(attributes)
|
||||
|
||||
def handle_delete(self):
|
||||
|
@ -205,7 +214,7 @@ class Net(neutron.NeutronResource):
|
|||
if prop_diff:
|
||||
self.prepare_update_properties(prop_diff)
|
||||
if self.DHCP_AGENT_IDS in prop_diff:
|
||||
dhcp_agent_ids = prop_diff.pop(self.DHCP_AGENT_IDS, [])
|
||||
dhcp_agent_ids = prop_diff.pop(self.DHCP_AGENT_IDS) or []
|
||||
self._replace_dhcp_agents(dhcp_agent_ids)
|
||||
if self.QOS_POLICY in prop_diff:
|
||||
qos_policy = prop_diff.pop(self.QOS_POLICY)
|
||||
|
@ -249,6 +258,21 @@ class Net(neutron.NeutronResource):
|
|||
self.client_plugin().is_not_found(ex)):
|
||||
raise
|
||||
|
||||
def parse_live_resource_data(self, resource_properties, resource_data):
|
||||
result = super(Net, self).parse_live_resource_data(
|
||||
resource_properties, resource_data)
|
||||
result.pop(self.SHARED)
|
||||
result[self.QOS_POLICY] = resource_data.get('qos_policy_id')
|
||||
try:
|
||||
dhcp = self.client().list_dhcp_agent_hosting_networks(
|
||||
self.resource_id)
|
||||
dhcp_agents = set([agent['id'] for agent in dhcp['agents']])
|
||||
result.update({self.DHCP_AGENT_IDS: list(dhcp_agents)})
|
||||
except self.client_plugin().exceptions.Forbidden:
|
||||
# Just don't add dhcp_clients if we can't get values.
|
||||
pass
|
||||
return result
|
||||
|
||||
|
||||
def resource_mapping():
|
||||
return {
|
||||
|
|
|
@ -81,6 +81,16 @@ class NeutronResource(resource.Resource):
|
|||
NeutronResource.merge_value_specs(props)
|
||||
return props
|
||||
|
||||
def _store_config_default_properties(self, attrs):
|
||||
"""A method for storing properties, which defaults stored in config.
|
||||
|
||||
A method allows to store properties default values, which cannot be
|
||||
defined in schema in case of specifying in config file.
|
||||
"""
|
||||
if 'port_security_enabled' in attrs:
|
||||
self.data_set('port_security_enabled',
|
||||
attrs['port_security_enabled'])
|
||||
|
||||
@staticmethod
|
||||
def merge_value_specs(props):
|
||||
value_spec_props = props.pop('value_specs')
|
||||
|
@ -175,3 +185,24 @@ class NeutronResource(resource.Resource):
|
|||
self.client().replace_tag(resource_plural,
|
||||
self.resource_id,
|
||||
body)
|
||||
|
||||
def parse_live_resource_data(self, resource_properties, resource_data):
|
||||
result = super(NeutronResource, self).parse_live_resource_data(
|
||||
resource_properties, resource_data)
|
||||
|
||||
if 'value_specs' in self.properties.keys():
|
||||
result.update({self.VALUE_SPECS: {}})
|
||||
for key in self.properties.get(self.VALUE_SPECS):
|
||||
if key in resource_data:
|
||||
result[self.VALUE_SPECS][key] = resource_data.get(key)
|
||||
|
||||
# We already get real `port_security_enabled` from
|
||||
# super().parse_live_resource_data above, so just check and remove
|
||||
# if that's same value as old port value.
|
||||
if 'port_security_enabled' in self.properties.keys():
|
||||
old_port = bool(self.data().get(self.PORT_SECURITY_ENABLED))
|
||||
new_port = resource_data.get(self.PORT_SECURITY_ENABLED)
|
||||
if old_port == new_port:
|
||||
del result[self.PORT_SECURITY_ENABLED]
|
||||
|
||||
return result
|
||||
|
|
|
@ -490,8 +490,19 @@ class Port(neutron.NeutronResource):
|
|||
if self.REPLACEMENT_POLICY in props:
|
||||
del(props[self.REPLACEMENT_POLICY])
|
||||
|
||||
def _store_config_default_properties(self, attrs):
|
||||
"""A method for storing properties default values.
|
||||
|
||||
A method allows to store properties default values, which cannot be
|
||||
defined in schema in case of specifying in config file.
|
||||
"""
|
||||
super(Port, self)._store_config_default_properties(attrs)
|
||||
if self.VNIC_TYPE in attrs:
|
||||
self.data_set(self.VNIC_TYPE, attrs[self.VNIC_TYPE])
|
||||
|
||||
def check_create_complete(self, *args):
|
||||
attributes = self._show_resource()
|
||||
self._store_config_default_properties(attributes)
|
||||
return self.is_built(attributes)
|
||||
|
||||
def handle_delete(self):
|
||||
|
@ -502,6 +513,20 @@ class Port(neutron.NeutronResource):
|
|||
else:
|
||||
return True
|
||||
|
||||
def parse_live_resource_data(self, resource_properties, resource_data):
|
||||
result = super(Port, self).parse_live_resource_data(
|
||||
resource_properties, resource_data)
|
||||
result[self.QOS_POLICY] = resource_data.get('qos_policy_id')
|
||||
result.pop(self.MAC_ADDRESS)
|
||||
fixed_ips = resource_data.get(self.FIXED_IPS) or []
|
||||
if fixed_ips:
|
||||
result.update({self.FIXED_IPS: []})
|
||||
for fixed_ip in fixed_ips:
|
||||
result[self.FIXED_IPS].append(
|
||||
{self.FIXED_IP_SUBNET: fixed_ip.get('subnet_id'),
|
||||
self.FIXED_IP_IP_ADDRESS: fixed_ip.get('ip_address')})
|
||||
return result
|
||||
|
||||
def _resolve_attribute(self, name):
|
||||
if self.resource_id is None:
|
||||
return
|
||||
|
|
|
@ -170,6 +170,24 @@ class ProviderNet(net.Net):
|
|||
self.client().update_network(self.resource_id,
|
||||
{'network': prop_diff})
|
||||
|
||||
def parse_live_resource_data(self, resource_properties, resource_data):
|
||||
# this resource should not have super in case of we don't need to
|
||||
# parse Net resource properties.
|
||||
result = {}
|
||||
provider_keys = [self.PROVIDER_NETWORK_TYPE,
|
||||
self.PROVIDER_PHYSICAL_NETWORK,
|
||||
self.PROVIDER_SEGMENTATION_ID]
|
||||
for key in provider_keys:
|
||||
result[key] = resource_data.get('provider:%s' % key)
|
||||
result[self.ROUTER_EXTERNAL] = resource_data.get('router:external')
|
||||
provider_keys.append(self.ROUTER_EXTERNAL)
|
||||
|
||||
provider_keys.append(self.SHARED)
|
||||
for key in set(self.PROPERTIES) - set(provider_keys):
|
||||
if key in resource_data:
|
||||
result[key] = resource_data.get(key)
|
||||
return result
|
||||
|
||||
|
||||
def resource_mapping():
|
||||
return {
|
||||
|
|
|
@ -354,6 +354,27 @@ class Router(neutron.NeutronResource):
|
|||
self.client().add_router_to_l3_agent(
|
||||
l3_agent_id, {'router_id': self.resource_id})
|
||||
|
||||
def parse_live_resource_data(self, resource_properties, resource_data):
|
||||
result = super(Router, self).parse_live_resource_data(
|
||||
resource_properties, resource_data)
|
||||
|
||||
try:
|
||||
ret = self.client().list_l3_agent_hosting_routers(self.resource_id)
|
||||
if ret:
|
||||
result[self.L3_AGENT_IDS] = list(
|
||||
agent['id'] for agent in ret['agents'])
|
||||
except self.client_plugin().exceptions.Forbidden:
|
||||
# Just pass if forbidden
|
||||
pass
|
||||
|
||||
gateway = resource_data.get(self.EXTERNAL_GATEWAY)
|
||||
if gateway is not None:
|
||||
result[self.EXTERNAL_GATEWAY] = {
|
||||
self.EXTERNAL_GATEWAY_NETWORK: gateway.get('network_id'),
|
||||
self.EXTERNAL_GATEWAY_ENABLE_SNAT: gateway.get('enable_snat')
|
||||
}
|
||||
return result
|
||||
|
||||
|
||||
class RouterInterface(neutron.NeutronResource):
|
||||
"""A resource for managing Neutron router interfaces.
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import mock
|
||||
from neutronclient.common import exceptions
|
||||
from neutronclient.v2_0 import client as neutronclient
|
||||
from oslo_config import cfg
|
||||
|
@ -271,6 +272,37 @@ class FirewallTest(common.HeatTestCase):
|
|||
rsrc.handle_update(update_snippet, {}, prop_diff)
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_get_live_state(self):
|
||||
rsrc = self.create_firewall(value_specs=True)
|
||||
rsrc.client().show_firewall = mock.Mock(return_value={
|
||||
'firewall': {
|
||||
'status': 'ACTIVE',
|
||||
'router_ids': ['router_1', 'router_2'],
|
||||
'name': 'firewall-firewall-pwakkqdrcl7z',
|
||||
'admin_state_up': True,
|
||||
'tenant_id': 'df49ea64e87c43a792a510698364f03e',
|
||||
'firewall_policy_id': '680eb26d-3eea-40be-b484-1476e4c7c1b3',
|
||||
'id': '11425cd4-41b6-4fd4-97aa-17629c63de61',
|
||||
'description': ''
|
||||
}
|
||||
})
|
||||
self.m.ReplayAll()
|
||||
scheduler.TaskRunner(rsrc.create)()
|
||||
|
||||
reality = rsrc.get_live_state(rsrc.properties)
|
||||
expected = {
|
||||
'value_specs': {
|
||||
'router_ids': ['router_1', 'router_2']
|
||||
},
|
||||
'name': 'firewall-firewall-pwakkqdrcl7z',
|
||||
'admin_state_up': True,
|
||||
'firewall_policy_id': '680eb26d-3eea-40be-b484-1476e4c7c1b3',
|
||||
'description': ''
|
||||
}
|
||||
|
||||
self.assertEqual(expected, reality)
|
||||
self.m.VerifyAll()
|
||||
|
||||
|
||||
class FirewallPolicyTest(common.HeatTestCase):
|
||||
|
||||
|
|
|
@ -285,3 +285,67 @@ class NeutronNetTest(common.HeatTestCase):
|
|||
rsrc.state_set(rsrc.CREATE, rsrc.COMPLETE, 'to delete again')
|
||||
scheduler.TaskRunner(rsrc.delete)()
|
||||
self.assertEqual((rsrc.DELETE, rsrc.COMPLETE), rsrc.state)
|
||||
|
||||
def test_net_get_live_state(self):
|
||||
tmpl = """
|
||||
heat_template_version: 2015-10-15
|
||||
resources:
|
||||
net:
|
||||
type: OS::Neutron::Net
|
||||
properties:
|
||||
value_specs:
|
||||
'test:property': test_value
|
||||
"""
|
||||
t = template_format.parse(tmpl)
|
||||
stack = utils.parse_stack(t)
|
||||
show_net = self.patchobject(neutronclient.Client, 'show_network')
|
||||
show_net.return_value = {'network': {'status': 'ACTIVE'}}
|
||||
self.patchobject(neutronclient.Client,
|
||||
'list_dhcp_agent_hosting_networks',
|
||||
return_value={'agents': [{'id': '1111'}]})
|
||||
|
||||
self.patchobject(neutronclient.Client, 'create_network',
|
||||
return_value={"network": {
|
||||
"status": "BUILD",
|
||||
"subnets": [],
|
||||
"qos_policy_id": "some",
|
||||
"name": "name",
|
||||
"admin_state_up": True,
|
||||
"shared": True,
|
||||
"tenant_id": "c1210485b2424d48804aad5d39c61b8f",
|
||||
"id": "fc68ea2c-b60b-4b4f-bd82-94ec81110766",
|
||||
"mtu": 0
|
||||
}})
|
||||
rsrc = self.create_net(t, stack, 'net')
|
||||
|
||||
network_resp = {
|
||||
'name': 'net1-net-wkkl2vwupdee',
|
||||
'admin_state_up': True,
|
||||
'tenant_id': '30f466e3d14b4251853899f9c26e2b66',
|
||||
'mtu': 0,
|
||||
'router:external': False,
|
||||
'port_security_enabled': True,
|
||||
'shared': False,
|
||||
'qos_policy_id': 'some',
|
||||
'id': u'5a4bb8a0-5077-4f8a-8140-5430370020e6',
|
||||
'test:property': 'test_value_resp'
|
||||
}
|
||||
show_net.return_value = {'network': network_resp}
|
||||
|
||||
reality = rsrc.get_live_state(rsrc.properties)
|
||||
expected = {
|
||||
'name': 'net1-net-wkkl2vwupdee',
|
||||
'admin_state_up': True,
|
||||
'qos_policy': "some",
|
||||
'value_specs': {
|
||||
'test:property': 'test_value_resp'
|
||||
},
|
||||
'port_security_enabled': True,
|
||||
'dhcp_agent_ids': ['1111']
|
||||
}
|
||||
self.assertEqual(set(expected.keys()), set(reality.keys()))
|
||||
for key in expected:
|
||||
if key == 'dhcp_agent_ids':
|
||||
self.assertEqual(set(expected[key]), set(reality[key]))
|
||||
continue
|
||||
self.assertEqual(expected[key], reality[key])
|
||||
|
|
|
@ -732,6 +732,68 @@ class NeutronPortTest(common.HeatTestCase):
|
|||
mock.call(existing_rsrc.resource_id, expected_existing_props),
|
||||
mock.call(prev_rsrc.resource_id, expected_prev_props)])
|
||||
|
||||
def test_port_get_live_state(self):
|
||||
t = template_format.parse(neutron_port_template)
|
||||
t['resources']['port']['properties']['value_specs'] = {
|
||||
'binding:vif_type': 'test'}
|
||||
|
||||
stack = utils.parse_stack(t)
|
||||
|
||||
port = stack['port']
|
||||
|
||||
resp = {'port': {
|
||||
'status': 'DOWN',
|
||||
'binding:host_id': '',
|
||||
'name': 'flip-port-xjbal77qope3',
|
||||
'allowed_address_pairs': [],
|
||||
'admin_state_up': True,
|
||||
'network_id': 'd6859535-efef-4184-b236-e5fcae856e0f',
|
||||
'dns_name': '',
|
||||
'extra_dhcp_opts': [],
|
||||
'mac_address': 'fa:16:3e:fe:64:79',
|
||||
'qos_policy_id': 'some',
|
||||
'dns_assignment': [],
|
||||
'binding:vif_details': {},
|
||||
'binding:vif_type': 'unbound',
|
||||
'device_owner': '',
|
||||
'tenant_id': '30f466e3d14b4251853899f9c26e2b66',
|
||||
'binding:profile': {},
|
||||
'port_security_enabled': True,
|
||||
'binding:vnic_type': 'normal',
|
||||
'fixed_ips': [
|
||||
{'subnet_id': '02d9608f-8f30-4611-ad02-69855c82457f',
|
||||
'ip_address': '10.0.3.4'}],
|
||||
'id': '829bf5c1-b59c-40ad-80e3-ea15a93879f3',
|
||||
'security_groups': ['c276247f-50fd-4289-862a-80fb81a55de1'],
|
||||
'device_id': ''}
|
||||
}
|
||||
port.client().show_port = mock.MagicMock(return_value=resp)
|
||||
port.resource_id = '1234'
|
||||
port._data = {}
|
||||
port.data_set = mock.Mock()
|
||||
|
||||
reality = port.get_live_state(port.properties)
|
||||
expected = {
|
||||
'name': 'flip-port-xjbal77qope3',
|
||||
'allowed_address_pairs': [],
|
||||
'admin_state_up': True,
|
||||
'device_owner': '',
|
||||
'port_security_enabled': True,
|
||||
'binding:vnic_type': 'normal',
|
||||
'fixed_ips': [
|
||||
{'subnet': '02d9608f-8f30-4611-ad02-69855c82457f',
|
||||
'ip_address': '10.0.3.4'}],
|
||||
'security_groups': ['c276247f-50fd-4289-862a-80fb81a55de1'],
|
||||
'device_id': '',
|
||||
'dns_name': '',
|
||||
'qos_policy': 'some',
|
||||
'value_specs': {'binding:vif_type': 'unbound'}
|
||||
}
|
||||
|
||||
self.assertEqual(set(expected.keys()), set(reality.keys()))
|
||||
for key in expected:
|
||||
self.assertEqual(expected[key], reality[key])
|
||||
|
||||
|
||||
class UpdatePortTest(common.HeatTestCase):
|
||||
scenarios = [
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
import copy
|
||||
|
||||
import mock
|
||||
from neutronclient.common import exceptions as qe
|
||||
from neutronclient.v2_0 import client as neutronclient
|
||||
|
||||
|
@ -190,3 +191,36 @@ class NeutronProviderNetTest(common.HeatTestCase):
|
|||
# no prop_diff
|
||||
self.assertIsNone(rsrc.handle_update(update_snippet, {}, {}))
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_get_live_state(self):
|
||||
rsrc = self.create_provider_net()
|
||||
rsrc.client().show_network = mock.Mock(return_value={
|
||||
'network': {
|
||||
'status': 'ACTIVE',
|
||||
'subnets': [],
|
||||
'availability_zone_hints': [],
|
||||
'availability_zones': [],
|
||||
'name': 'prov-provider-nhalkd5xftp3',
|
||||
'provider:physical_network': 'public',
|
||||
'admin_state_up': True,
|
||||
'tenant_id': 'df49ea64e87c43a792a510698364f03e',
|
||||
'mtu': 0,
|
||||
'router:external': False,
|
||||
'port_security_enabled': True,
|
||||
'shared': True,
|
||||
'provider:network_type': 'flat',
|
||||
'id': 'af216806-4462-4c68-bfa4-9580857e71c3',
|
||||
'provider:segmentation_id': None}})
|
||||
|
||||
reality = rsrc.get_live_state(rsrc.properties)
|
||||
expected = {
|
||||
'name': 'prov-provider-nhalkd5xftp3',
|
||||
'physical_network': 'public',
|
||||
'admin_state_up': True,
|
||||
'network_type': 'flat',
|
||||
'port_security_enabled': True,
|
||||
'segmentation_id': None,
|
||||
'router_external': False
|
||||
}
|
||||
|
||||
self.assertEqual(expected, reality)
|
||||
|
|
|
@ -807,3 +807,65 @@ class NeutronRouterTest(common.HeatTestCase):
|
|||
rsrc = self.create_router(t, stack, 'router')
|
||||
self._assert_mock_call_create_with_router_gw()
|
||||
self.assertIsNone(scheduler.TaskRunner(rsrc.delete)())
|
||||
|
||||
def test_router_get_live_state(self):
|
||||
tmpl = """
|
||||
heat_template_version: 2015-10-15
|
||||
resources:
|
||||
router:
|
||||
type: OS::Neutron::Router
|
||||
properties:
|
||||
external_gateway_info:
|
||||
network: public
|
||||
enable_snat: true
|
||||
value_specs:
|
||||
test_value_spec: spec_value
|
||||
"""
|
||||
t = template_format.parse(tmpl)
|
||||
stack = utils.parse_stack(t)
|
||||
|
||||
rsrc = stack['router']
|
||||
|
||||
router_resp = {
|
||||
'status': 'ACTIVE',
|
||||
'external_gateway_info': {
|
||||
'network_id': '1ede231a-0b46-40fc-ab3b-8029446d0d1b',
|
||||
'enable_snat': True,
|
||||
'external_fixed_ips': [
|
||||
{'subnet_id': '8eea1723-6de7-4255-9f8a-a0ce0db8b995',
|
||||
'ip_address': '10.0.3.3'}]
|
||||
},
|
||||
'name': 'er-router-naqzmqnzk4ej',
|
||||
'admin_state_up': True,
|
||||
'tenant_id': '30f466e3d14b4251853899f9c26e2b66',
|
||||
'distributed': False,
|
||||
'routes': [],
|
||||
'ha': False,
|
||||
'id': 'b047ff06-487d-48d7-a735-a54e2fd836c2',
|
||||
'test_value_spec': 'spec_value'
|
||||
}
|
||||
rsrc.client().show_router = mock.MagicMock(
|
||||
return_value={'router': router_resp})
|
||||
rsrc.client().list_l3_agent_hosting_routers = mock.MagicMock(
|
||||
return_value={'agents': [{'id': '1234'}, {'id': '5678'}]})
|
||||
|
||||
reality = rsrc.get_live_state(rsrc.properties)
|
||||
expected = {
|
||||
'external_gateway_info': {
|
||||
'network': '1ede231a-0b46-40fc-ab3b-8029446d0d1b',
|
||||
'enable_snat': True
|
||||
},
|
||||
'name': 'er-router-naqzmqnzk4ej',
|
||||
'admin_state_up': True,
|
||||
'value_specs': {
|
||||
'test_value_spec': 'spec_value'
|
||||
},
|
||||
'l3_agent_ids': ['1234', '5678']
|
||||
}
|
||||
|
||||
self.assertEqual(set(expected.keys()), set(reality.keys()))
|
||||
for key in expected:
|
||||
if key == 'external_gateway_info':
|
||||
for info in expected[key]:
|
||||
self.assertEqual(expected[key][info], reality[key][info])
|
||||
self.assertEqual(expected[key], reality[key])
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
# under the License.
|
||||
|
||||
import copy
|
||||
import mock
|
||||
from neutronclient.common import exceptions as qe
|
||||
from neutronclient.neutron import v2_0 as neutronV20
|
||||
from neutronclient.v2_0 import client as neutronclient
|
||||
|
@ -699,3 +700,60 @@ class NeutronSubnetTest(common.HeatTestCase):
|
|||
self.assertEqual(hot_funcs.GetResource(stack, 'get_resource', 'net'),
|
||||
rsrc.properties.get('network'))
|
||||
self.assertIsNone(rsrc.properties.get('network_id'))
|
||||
|
||||
def test_subnet_get_live_state(self):
|
||||
template = """
|
||||
heat_template_version: 2015-04-30
|
||||
resources:
|
||||
net:
|
||||
type: OS::Neutron::Net
|
||||
properties:
|
||||
name: test
|
||||
subnet:
|
||||
type: OS::Neutron::Subnet
|
||||
properties:
|
||||
network_id: { get_resource: net }
|
||||
cidr: 10.0.0.0/25
|
||||
value_specs:
|
||||
test_value_spec: value_spec_value
|
||||
"""
|
||||
t = template_format.parse(template)
|
||||
stack = utils.parse_stack(t)
|
||||
rsrc = stack['subnet']
|
||||
stack.create()
|
||||
|
||||
subnet_resp = {'subnet': {
|
||||
'name': 'subnet-subnet-la5usdgifhrd',
|
||||
'enable_dhcp': True,
|
||||
'network_id': 'dffd43b3-6206-4402-87e6-8a16ddf3bd68',
|
||||
'tenant_id': '30f466e3d14b4251853899f9c26e2b66',
|
||||
'dns_nameservers': [],
|
||||
'ipv6_ra_mode': None,
|
||||
'allocation_pools': [{'start': '10.0.0.2', 'end': '10.0.0.126'}],
|
||||
'gateway_ip': '10.0.0.1',
|
||||
'ipv6_address_mode': None,
|
||||
'ip_version': 4,
|
||||
'host_routes': [],
|
||||
'prefixlen': None,
|
||||
'cidr': '10.0.0.0/25',
|
||||
'id': 'b255342b-31b7-4674-8ea4-a144bca658b0',
|
||||
'subnetpool_id': None,
|
||||
'test_value_spec': 'value_spec_value'}
|
||||
}
|
||||
rsrc.client().show_subnet = mock.MagicMock(return_value=subnet_resp)
|
||||
rsrc.resource_id = '1234'
|
||||
|
||||
reality = rsrc.get_live_state(rsrc.properties)
|
||||
expected = {
|
||||
'name': 'subnet-subnet-la5usdgifhrd',
|
||||
'enable_dhcp': True,
|
||||
'dns_nameservers': [],
|
||||
'allocation_pools': [{'start': '10.0.0.2', 'end': '10.0.0.126'}],
|
||||
'gateway_ip': '10.0.0.1',
|
||||
'host_routes': [],
|
||||
'value_specs': {'test_value_spec': 'value_spec_value'}
|
||||
}
|
||||
|
||||
self.assertEqual(set(expected.keys()), set(reality.keys()))
|
||||
for key in expected:
|
||||
self.assertEqual(expected[key], reality[key])
|
||||
|
|
Loading…
Reference in New Issue