dragonflow/dragonflow/tests/fullstack/test_dhcp_flows.py

179 lines
7.5 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 time
from dragonflow.controller.common import constants
from dragonflow.db.models import l2
from dragonflow.tests.common import constants as const
from dragonflow.tests.common import utils
from dragonflow.tests.fullstack import test_base
from dragonflow.tests.fullstack import test_objects as objects
class TestOVSFlowsForDHCP(test_base.DFTestBase):
def get_dhcp_ip(self, network_id, subnet_id):
ports = self.neutron.list_ports(network_id=network_id)
ports = ports['ports']
for port in ports:
if port['device_owner'] == 'network:dhcp':
ips = port['fixed_ips']
for ip in ips:
if ip['subnet_id'] == subnet_id:
return ip['ip_address']
return None
def test_dhcp_packet_rule(self):
found_dhcp_cast_flow = False
ovs = utils.OvsFlowsParser()
flows = ovs.dump(self.integration_bridge)
goto_dhcp = 'goto_table:' + str(constants.DHCP_TABLE)
dhcp_ports = ',tp_src=' + str(constants.DHCP_CLIENT_PORT) + \
',tp_dst=' + str(constants.DHCP_SERVER_PORT)
for flow in flows:
if (flow['table'] == str(constants.SERVICES_CLASSIFICATION_TABLE)
and flow['actions'] == goto_dhcp):
if ('udp' + dhcp_ports
in flow['match']):
found_dhcp_cast_flow = True
break
self.assertTrue(found_dhcp_cast_flow)
def _create_network(self):
network = objects.NetworkTestObj(self.neutron, self.nb_api)
self.addCleanup(network.close)
network_id = network.create()
self.assertTrue(network.exists())
lean_lswitch = l2.LogicalSwitch(id=network_id)
df_network = self.nb_api.get(lean_lswitch)
network_key = df_network.unique_key
return network, network_id, network_key
def test_create_update_subnet_with_dhcp(self):
ovs = utils.OvsFlowsParser()
flows_before_change = ovs.dump(self.integration_bridge)
network, network_id, network_key = self._create_network()
subnet = {'network_id': network_id,
'cidr': '10.10.254.0/24',
'gateway_ip': '10.10.254.1',
'ip_version': 4,
'name': 'subnet-test',
'enable_dhcp': True}
subnet = self.neutron.create_subnet({'subnet': subnet})
subnet_id = subnet['subnet']['id']
dhcp_ip = utils.wait_until_is_and_return(
lambda: self.get_dhcp_ip(network_id, subnet_id),
exception=Exception('DHCP IP was not generated')
)
self.assertIsNotNone(dhcp_ip)
self.assertFalse(utils.check_dhcp_network_rule(
flows_before_change, network_key))
utils.wait_until_true(
lambda: utils.check_dhcp_network_rule(
ovs.dump(self.integration_bridge),
network_key),
exception=Exception('DHCP ip was not found in OpenFlow rules'),
timeout=5
)
# change dhcp
updated_subnet = {'enable_dhcp': False}
self.neutron.update_subnet(subnet_id, {'subnet': updated_subnet})
time.sleep(const.DEFAULT_RESOURCE_READY_TIMEOUT)
flows_after_update = ovs.dump(self.integration_bridge)
self.assertFalse(utils.check_dhcp_network_rule(
flows_after_update, network_key))
network.close()
def test_create_update_subnet_without_dhcp(self):
ovs = utils.OvsFlowsParser()
flows_before_change = ovs.dump(self.integration_bridge)
network, network_id, network_key = self._create_network()
subnet = {'network_id': network_id,
'cidr': '10.20.0.0/24',
'gateway_ip': '10.20.0.1',
'ip_version': 4,
'name': 'subnet-test',
'enable_dhcp': False}
subnet = self.neutron.create_subnet({'subnet': subnet})
subnet_id = subnet['subnet']['id']
time.sleep(const.DEFAULT_CMD_TIMEOUT)
flows_after_change = ovs.dump(self.integration_bridge)
# change dhcp
updated_subnet = {'enable_dhcp': True}
self.neutron.update_subnet(subnet_id, {'subnet': updated_subnet})
dhcp_ip = utils.wait_until_is_and_return(
lambda: self.get_dhcp_ip(network_id, subnet_id),
exception=Exception('DHCP IP was not generated')
)
self.assertIsNotNone(dhcp_ip)
self.assertFalse(utils.check_dhcp_network_rule(
flows_before_change, network_key))
self.assertFalse(utils.check_dhcp_network_rule(
flows_after_change, network_key))
utils.wait_until_true(
lambda: utils.check_dhcp_network_rule(
ovs.dump(self.integration_bridge),
network_key),
exception=Exception('DHCP ip was not found in OpenFlow rules'),
timeout=5
)
network.close()
utils.wait_until_none(
lambda: utils.check_dhcp_network_rule(
ovs.dump(self.integration_bridge),
network_key),
exception=Exception('DHCP IP was not removed from OpenFlow rules'),
timeout=30
)
def test_create_router_interface(self):
ovs = utils.OvsFlowsParser()
flows_before_change = ovs.dump(self.integration_bridge)
router = objects.RouterTestObj(self.neutron, self.nb_api)
self.addCleanup(router.close)
network, network_id, network_key = self._create_network()
subnet = {'network_id': network_id,
'cidr': '10.30.0.0/24',
'gateway_ip': '10.30.0.1',
'ip_version': 4,
'name': 'subnet-test',
'enable_dhcp': True}
subnet = self.neutron.create_subnet({'subnet': subnet})
subnet_id = subnet['subnet']['id']
router_id = router.create()
self.assertTrue(router.exists())
subnet_msg = {'subnet_id': subnet_id}
time.sleep(const.DEFAULT_RESOURCE_READY_TIMEOUT)
self.neutron.add_interface_router(router_id, body=subnet_msg)
dhcp_ip = utils.wait_until_is_and_return(
lambda: self.get_dhcp_ip(network_id, subnet_id),
exception=Exception('DHCP IP was not generated')
)
self.assertIsNotNone(dhcp_ip)
flows_after_change = ovs.dump(self.integration_bridge)
self.assertFalse(utils.check_dhcp_network_rule(
flows_before_change, network_key))
self.assertTrue(utils.check_dhcp_network_rule(
flows_after_change, network_key))
self.neutron.remove_interface_router(router_id, body=subnet_msg)
router.close()
network.close()
utils.wait_until_none(
lambda: utils.check_dhcp_network_rule(
ovs.dump(self.integration_bridge),
network_key),
exception=Exception('DHCP IP was not removed from OpenFlow rules'),
timeout=30
)