6e4831cc49
Adds a attribute to the neutron Net resource to get the segments of a network. Story: 2001988 Task: 19610 Change-Id: I7acb3d29a01fa92bebdb2c85094655e27cb16a29
351 lines
12 KiB
Python
351 lines
12 KiB
Python
#
|
|
# 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
|
|
|
|
from neutronclient.common import exceptions as qe
|
|
from neutronclient.v2_0 import client as neutronclient
|
|
|
|
from heat.common import exception
|
|
from heat.common import template_format
|
|
from heat.engine.clients.os import neutron
|
|
from heat.engine.resources.openstack.neutron import net
|
|
from heat.engine import rsrc_defn
|
|
from heat.engine import scheduler
|
|
from heat.tests import common
|
|
from heat.tests import utils
|
|
|
|
|
|
neutron_template = '''
|
|
heat_template_version: rocky
|
|
description: Template to test network Neutron resource
|
|
resources:
|
|
network:
|
|
type: OS::Neutron::Net
|
|
properties:
|
|
name: the_network
|
|
tenant_id: c1210485b2424d48804aad5d39c61b8f
|
|
shared: true
|
|
dhcp_agent_ids:
|
|
- 28c25a04-3f73-45a7-a2b4-59e183943ddc
|
|
port_security_enabled: False
|
|
dns_domain: openstack.org.
|
|
tags:
|
|
- tag1
|
|
- tag2
|
|
|
|
subnet:
|
|
type: OS::Neutron::Subnet
|
|
properties:
|
|
network: { get_resource: network }
|
|
tenant_id: c1210485b2424d48804aad5d39c61b8f
|
|
ip_version: 4
|
|
cidr: 10.0.3.0/24
|
|
allocation_pools:
|
|
- start: 10.0.3.20
|
|
end: 10.0.3.150
|
|
host_routes:
|
|
- destination: 10.0.4.0/24
|
|
nexthop: 10.0.3.20
|
|
dns_nameservers:
|
|
- 8.8.8.8
|
|
|
|
router:
|
|
type: OS::Neutron::Router
|
|
properties:
|
|
l3_agent_ids:
|
|
- 792ff887-6c85-4a56-b518-23f24fa65581
|
|
|
|
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: {get_resource : network}
|
|
'''
|
|
|
|
|
|
class NeutronNetTest(common.HeatTestCase):
|
|
|
|
def setUp(self):
|
|
super(NeutronNetTest, self).setUp()
|
|
self.patchobject(neutron.NeutronClientPlugin, 'has_extension',
|
|
return_value=True)
|
|
|
|
def create_net(self, t, stack, resource_name):
|
|
resource_defns = stack.t.resource_definitions(stack)
|
|
rsrc = net.Net('test_net', resource_defns[resource_name], stack)
|
|
scheduler.TaskRunner(rsrc.create)()
|
|
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
|
|
return rsrc
|
|
|
|
def test_net(self):
|
|
t = template_format.parse(neutron_template)
|
|
stack = utils.parse_stack(t)
|
|
resource_type = 'networks'
|
|
net_info_build = {"network": {
|
|
"status": "BUILD",
|
|
"subnets": [],
|
|
"name": "name",
|
|
"admin_state_up": True,
|
|
"shared": True,
|
|
"tenant_id": "c1210485b2424d48804aad5d39c61b8f",
|
|
"id": "fc68ea2c-b60b-4b4f-bd82-94ec81110766",
|
|
"mtu": 0
|
|
}}
|
|
net_info_active = copy.deepcopy(net_info_build)
|
|
net_info_active['network'].update({'status': 'ACTIVE'})
|
|
agent_info = {
|
|
"agents": [{
|
|
"admin_state_up": True,
|
|
"agent_type": "DHCP agent",
|
|
"alive": True,
|
|
"binary": "neutron-dhcp-agent",
|
|
"configurations": {
|
|
"dhcp_driver": "DummyDriver",
|
|
"dhcp_lease_duration": 86400,
|
|
"networks": 0,
|
|
"ports": 0,
|
|
"subnets": 0,
|
|
"use_namespaces": True},
|
|
"created_at": "2014-03-20 05:12:34",
|
|
"description": None,
|
|
"heartbeat_timestamp": "2014-03-20 05:12:34",
|
|
"host": "hostname",
|
|
"id": "28c25a04-3f73-45a7-a2b4-59e183943ddc",
|
|
"started_at": "2014-03-20 05:12:34",
|
|
"topic": "dhcp_agent"
|
|
}]
|
|
}
|
|
create_mock = self.patchobject(neutronclient.Client, 'create_network')
|
|
create_mock.return_value = net_info_build
|
|
list_dhcp_agent_mock = self.patchobject(
|
|
neutronclient.Client,
|
|
'list_dhcp_agent_hosting_networks')
|
|
list_dhcp_agent_mock.side_effect = [{"agents": []},
|
|
agent_info]
|
|
add_dhcp_agent_mock = self.patchobject(
|
|
neutronclient.Client,
|
|
'add_network_to_dhcp_agent')
|
|
|
|
remove_dhcp_agent_mock = self.patchobject(
|
|
neutronclient.Client,
|
|
'remove_network_from_dhcp_agent')
|
|
replace_tag_mock = self.patchobject(
|
|
neutronclient.Client,
|
|
'replace_tag')
|
|
show_network_mock = self.patchobject(
|
|
neutronclient.Client,
|
|
'show_network')
|
|
show_network_mock.side_effect = [
|
|
net_info_build,
|
|
net_info_active,
|
|
qe.NetworkNotFoundClient(status_code=404),
|
|
net_info_active,
|
|
net_info_active,
|
|
qe.NetworkNotFoundClient(status_code=404)]
|
|
update_net_mock = self.patchobject(
|
|
neutronclient.Client,
|
|
'update_network')
|
|
|
|
del_net_mock = self.patchobject(
|
|
neutronclient.Client,
|
|
'delete_network')
|
|
del_net_mock.side_effect = [None,
|
|
qe.NetworkNotFoundClient(status_code=404)]
|
|
|
|
self.patchobject(neutron.NeutronClientPlugin, 'get_qos_policy_id',
|
|
return_value='0389f747-7785-4757-b7bb-2ab07e4b09c3')
|
|
|
|
self.patchobject(stack['router'], 'FnGetRefId',
|
|
return_value='792ff887-6c85-4a56-b518-23f24fa65581')
|
|
|
|
# network create
|
|
rsrc = self.create_net(t, stack, 'network')
|
|
create_mock.assert_called_with(
|
|
{'network':
|
|
{'name': u'the_network',
|
|
'admin_state_up': True,
|
|
'tenant_id': u'c1210485b2424d48804aad5d39c61b8f',
|
|
'dns_domain': u'openstack.org.',
|
|
'shared': True,
|
|
'port_security_enabled': False}
|
|
}
|
|
)
|
|
add_dhcp_agent_mock.assert_called_with(
|
|
'28c25a04-3f73-45a7-a2b4-59e183943ddc',
|
|
{'network_id': u'fc68ea2c-b60b-4b4f-bd82-94ec81110766'})
|
|
replace_tag_mock.assert_called_with(
|
|
resource_type,
|
|
'fc68ea2c-b60b-4b4f-bd82-94ec81110766',
|
|
{'tags': ['tag1', 'tag2']}
|
|
)
|
|
|
|
# assert the implicit dependency between the gateway and the interface
|
|
deps = stack.dependencies[stack['router_interface']]
|
|
self.assertIn(stack['gateway'], deps)
|
|
|
|
# assert the implicit dependency between the gateway and the subnet
|
|
deps = stack.dependencies[stack['subnet']]
|
|
self.assertIn(stack['gateway'], deps)
|
|
|
|
rsrc.validate()
|
|
|
|
ref_id = rsrc.FnGetRefId()
|
|
self.assertEqual('fc68ea2c-b60b-4b4f-bd82-94ec81110766', ref_id)
|
|
|
|
self.assertIsNone(rsrc.FnGetAtt('status'))
|
|
self.assertEqual('ACTIVE', rsrc.FnGetAtt('status'))
|
|
self.assertEqual(0, rsrc.FnGetAtt('mtu'))
|
|
self.assertRaises(
|
|
exception.InvalidTemplateAttribute, rsrc.FnGetAtt, 'Foo')
|
|
|
|
# update tests
|
|
prop_diff = {
|
|
"name": "mynet",
|
|
"dhcp_agent_ids": [
|
|
"bb09cfcd-5277-473d-8336-d4ed8628ae68"
|
|
],
|
|
'qos_policy': '0389f747-7785-4757-b7bb-2ab07e4b09c3'
|
|
}
|
|
update_snippet = rsrc_defn.ResourceDefinition(rsrc.name, rsrc.type(),
|
|
prop_diff)
|
|
rsrc.handle_update(update_snippet, {}, prop_diff)
|
|
update_net_mock.assert_called_with(
|
|
'fc68ea2c-b60b-4b4f-bd82-94ec81110766',
|
|
{'network': {
|
|
'name': 'mynet',
|
|
'qos_policy_id': '0389f747-7785-4757-b7bb-2ab07e4b09c3'
|
|
}})
|
|
add_dhcp_agent_mock.assert_called_with(
|
|
'bb09cfcd-5277-473d-8336-d4ed8628ae68',
|
|
{'network_id': 'fc68ea2c-b60b-4b4f-bd82-94ec81110766'})
|
|
remove_dhcp_agent_mock.assert_called_with(
|
|
'28c25a04-3f73-45a7-a2b4-59e183943ddc',
|
|
'fc68ea2c-b60b-4b4f-bd82-94ec81110766'
|
|
)
|
|
# Update with None qos_policy
|
|
prop_diff['qos_policy'] = None
|
|
rsrc.handle_update(update_snippet, {}, prop_diff)
|
|
update_net_mock.assert_called_with(
|
|
'fc68ea2c-b60b-4b4f-bd82-94ec81110766',
|
|
{'network': {
|
|
'name': 'mynet',
|
|
'qos_policy_id': None
|
|
}}
|
|
)
|
|
# Update with value_specs
|
|
prop_diff['value_specs'] = {"port_security_enabled": True}
|
|
rsrc.handle_update(update_snippet, {}, prop_diff)
|
|
update_net_mock.assert_called_with(
|
|
'fc68ea2c-b60b-4b4f-bd82-94ec81110766',
|
|
{'network': {
|
|
'name': 'mynet',
|
|
'port_security_enabled': True,
|
|
'qos_policy_id': None
|
|
}}
|
|
)
|
|
# Update with name = None
|
|
rsrc.handle_update(update_snippet, {}, {'name': None})
|
|
update_net_mock.assert_called_with(
|
|
'fc68ea2c-b60b-4b4f-bd82-94ec81110766',
|
|
{'network': {
|
|
'name': utils.PhysName(stack.name, 'test_net'),
|
|
}}
|
|
)
|
|
# Update with tags=[]
|
|
rsrc.handle_update(update_snippet, {}, {'tags': []})
|
|
replace_tag_mock.assert_called_with(
|
|
resource_type,
|
|
'fc68ea2c-b60b-4b4f-bd82-94ec81110766',
|
|
{'tags': []}
|
|
)
|
|
# Update with empty prop_diff
|
|
rsrc.handle_update(update_snippet, {}, {})
|
|
|
|
# update delete
|
|
scheduler.TaskRunner(rsrc.delete)()
|
|
del_net_mock.assert_called_with('fc68ea2c-b60b-4b4f-bd82-94ec81110766')
|
|
# delete raise not found
|
|
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: rocky
|
|
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 = {
|
|
'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])
|