Tempest: Providing support for dhcp-121 feature

Added scenario testcases for dhcp-121 feature.

Change-Id: I0a37500bd947c87fbbb6c21daf9de44d286a1792
This commit is contained in:
Puneet Arora 2016-06-01 10:35:28 +00:00
parent af8ee940a7
commit 866c222a18
2 changed files with 461 additions and 0 deletions

View File

@ -14,6 +14,7 @@ import base64
from oslo_log import log as logging
from oslo_serialization import jsonutils
import re
import requests
from tempest import config
@ -249,6 +250,45 @@ class VSMClient(object):
LOG.debug('Found edge: %s' % edge)
return edge
def get_dhcp_edge_config(self, edge_id):
"""Get dhcp edge config.
Return edge information.
"""
self.__set_api_version('4.0')
self.__set_endpoint('/edges/%s/dhcp/config' % edge_id)
response = self.get()
return response
def get_dhcp_edge_info(self):
"""Get dhcp edge info.
Return edge if found, else return None.
"""
edges = self.get_all_edges()
edge_list = []
for e in edges:
if (not e['edgeStatus'] == 'GREY'
and not e['state'] == 'undeployed'):
p = re.compile(r'dhcp*')
if (p.match(e['name'])):
edge_list.append(e['recentJobInfo']['edgeId'])
count = 0
result_edge = {}
for edge_id in edge_list:
response = self.get_dhcp_edge_config(edge_id)
paging_info = response.json()
if (paging_info['staticBindings']['staticBindings']):
result_edge[count] = paging_info
count += 1
else:
LOG.debug('Host Routes are not avilable for %s ' % edge_id)
if (count > 0):
edge = result_edge[0]
else:
edge = None
return edge
def get_vsm_version(self):
"""Get the VSM client version including major, minor, patch, & build#.

View File

@ -0,0 +1,421 @@
# Copyright 2016 OpenStack Foundation
# Copyright 2016 VMware Inc
# All Rights Reserved.
#
# 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 re
import sys
import time
from tempest import config
from tempest.lib.common import ssh
from tempest.lib.common.utils import data_utils
from tempest.lib import exceptions
from tempest import test
from vmware_nsx_tempest._i18n import _LI
from vmware_nsx_tempest.services import nsxv_client
from vmware_nsx_tempest.tests.nsxv.scenario import (
manager_topo_deployment as dmgr)
CONF = config.CONF
LOG = dmgr.manager.log.getLogger(__name__)
DHCP_121_DEPLOY_TOPO = "Testcase DHCP-121 option [%s] deploying"
DHCP_121_DEPLOY_COMPLETED = "Testcase [%s] deploy test-completed."
Metadataserver_ip = '169.254.169.254'
class TestDHCP121BasicOps(dmgr.TopoDeployScenarioManager):
"""Base class provides DHCP 121 options operations.
1) Creates an instance
2) Ssh to instance and then check below information:
a) check metadata routes avialable or not
b) check host routes avialble or not
c) clear host-routes from subnet and check routes present on vm or not
d) update subnet to disbale dhcp and check metadata routes not visible
on instance
3) Check at beckend(nsx-v) for host-routes and metadata route information
4) Delete of host routes from subnet will make it deleted from beckend
5) Negative test where try to make subnet dhcp disable but host-routes
present and vice-versa
6) Create large no of host-routes for subnet and check validation at
beckend
"""
@classmethod
def skip_checks(cls):
super(TestDHCP121BasicOps, cls).skip_checks()
if not (CONF.network.project_networks_reachable
or CONF.network.public_network_id):
msg = ('Either project_networks_reachable must be "true", or '
'public_network_id must be defined.')
raise cls.skipException(msg)
manager_ip = re.search(r"(\d{1,3}\.){3}\d{1,3}",
CONF.nsxv.manager_uri).group(0)
cls.vsm = nsxv_client.VSMClient(
manager_ip, CONF.nsxv.user, CONF.nsxv.password)
nsxv_version = cls.vsm.get_vsm_version()
# Raise skip testcase exception if nsx-v version is less than 6.2.3
if (nsxv_version and nsxv_version < '6.2.3'):
msg = ('NSX-v version should be greater than or equal to 6.2.3')
raise cls.skipException(msg)
@classmethod
def resource_setup(cls):
super(TestDHCP121BasicOps, cls).resource_setup()
@classmethod
def resource_cleanup(cls):
super(TestDHCP121BasicOps, cls).resource_cleanup()
def setUp(self):
super(TestDHCP121BasicOps, self).setUp()
def tearDown(self):
try:
self.remove_project_network(False)
except Exception:
pass
super(TestDHCP121BasicOps, self).tearDown()
@test.attr(type='nsxv')
@test.idempotent_id('95d06aba-895f-47f8-b47d-ae48c6853a85')
def test_dhcp_121_metadata_check_on_vm_nsxv(self):
LOG.info(_LI("Testcase DHCP-121 option metadata check on vm and \
on nsx deploying"))
self.vm_env = self.setup_vm_enviornment(self.manager, 'green', True)
self.green = self.dhcp_121_metadata_hostroutes_check_on_vm_nsxv(
self.vm_env)
self.remove_project_network()
self.green['router'].unset_gateway()
self.green['router'].delete()
LOG.info(_LI("Testcase DHCP-121 option metadata check on vm and on \
nsx completed"))
@test.attr(type='nsxv')
@test.idempotent_id('6bec6eb4-8632-493d-a895-a3ee87cb3002')
def test_dhcp_121_hostroutes_clear(self):
LOG.info(_LI("Testcase DHCP-121 option host routes clear deploying"))
self.vm_env = self.setup_vm_enviornment(self.manager, 'green', True)
self.green = self.dhcp_121_hostroutes_clear(self.vm_env)
self.remove_project_network()
self.green['router'].unset_gateway()
self.green['router'].delete()
LOG.info(_LI("Testcase DHCP-121 option host routes clear completed"))
@test.attr(type='nsxv')
@test.idempotent_id('a58dc6c5-9f28-4184-baf7-37ded52593c4')
def test_dhcp121_negative_test(self):
LOG.info(_LI("Testcase DHCP-121 option negative test deploying"))
t_net_id, t_network, t_subnet =\
self.create_project_network_subnet('admin')
subnet_id = t_subnet['id']
kwargs = {'enable_dhcp': 'false'}
new_name = "New_subnet"
# Update subnet with disable dhcp subnet
self.subnets_client.update_subnet(
subnet_id, name=new_name, **kwargs)
# Fetch next hop information from tempest.conf
next_hop = CONF.network.project_network_cidr
self.nexthop_host_route = next_hop.rsplit('.', 1)[0]
self.nexthop1 = self.nexthop_host_route + ".2"
username, password = self.get_image_userpass()
# Update subnet with host routes
_subnet_data = {'host_routes': [{'destination': '10.20.0.0/32',
'nexthop': '10.100.1.1'}],
'new_host_routes': [{'destination': '10.20.0.0/32',
'nexthop': self.nexthop1}]}
new_host_routes = _subnet_data['new_host_routes']
kwargs = {'host_routes': new_host_routes}
new_name = "New_subnet"
# Update subnet with host-route info
try:
self.subnets_client.update_subnet(
subnet_id, name=new_name, **kwargs)
except exceptions.BadRequest:
e = sys.exc_info()[0].__dict__['message']
if (e == "Bad request"):
LOG.info(_LI("Invalid input for operation:\
Host routes can only be supported when\
DHCP is enabled"))
pass
subnet_id = t_subnet['id']
kwargs = {'enable_dhcp': 'true'}
new_name = "New_subnet"
# Update subnet with disable dhcp subnet
self.subnets_client.update_subnet(
subnet_id, name=new_name, **kwargs)
# Update subnet with host routes
_subnet_data = {'host_routes': [{'destination': '10.20.0.0/32',
'nexthop': '10.100.1.1'}],
'new_host_routes': [{'destination': '10.20.0.0/32',
'nexthop': self.nexthop1}]}
new_host_routes = _subnet_data['new_host_routes']
kwargs = {'host_routes': new_host_routes}
new_name = "Subnet_host_routes"
# Update subnet with host-route info
self.subnets_client.update_subnet(
subnet_id, name=new_name, **kwargs)
# Disable dhcp subnet
kwargs = {'enable_dhcp': 'false'}
# Update subnet with disable dhcp subnet
try:
self.subnets_client.update_subnet(
subnet_id, name=new_name, **kwargs)
except exceptions.BadRequest:
e = sys.exc_info()[0].__dict__['message']
if (e == "Bad request"):
LOG.info(_LI("Can't disable DHCP while using host routes"))
pass
LOG.info(_LI("Testcase DHCP-121 option negative test completed"))
@test.attr(type='nsxv')
@test.idempotent_id('c3ca96d7-b704-4d94-b42d-e7bae94b82cd')
def test_dhcp121_multi_host_route(self):
LOG.info(_LI("Testcase DHCP-121 option multi host routes deploying"))
t_net_id, t_network, t_subnet =\
self.create_project_network_subnet('admin')
# Fetch next hop information from tempest.conf
next_hop = CONF.network.project_network_cidr
self.nexthop_host_route = next_hop.rsplit('.', 1)[0]
self.nexthop1 = self.nexthop_host_route + ".2"
# Update subnet with host routes
_subnet_data = {'host_routes': [{'destination': '10.20.0.0/32',
'nexthop': '10.100.1.1'}],
'new_host_routes': [{'destination': '10.20.0.0/32',
'nexthop': self.nexthop1},
{'destination': '10.21.0.0/32',
'nexthop': self.nexthop1},
{'destination': '10.22.0.0/32',
'nexthop': self.nexthop1},
{'destination': '10.23.0.0/32',
'nexthop': self.nexthop1},
{'destination': '10.24.0.0/32',
'nexthop': self.nexthop1},
{'destination': '10.25.0.0/32',
'nexthop': self.nexthop1},
{'destination': '10.26.0.0/32',
'nexthop': self.nexthop1},
{'destination': '10.27.0.0/32',
'nexthop': self.nexthop1},
{'destination': '10.28.0.0/32',
'nexthop': self.nexthop1},
{'destination': '10.29.0.0/32',
'nexthop': self.nexthop1},
{'destination': '10.30.0.0/32',
'nexthop': self.nexthop1},
{'destination': '10.31.0.0/32',
'nexthop': self.nexthop1},
{'destination': '10.32.0.0/32',
'nexthop': self.nexthop1},
{'destination': '10.33.0.0/32',
'nexthop': self.nexthop1},
{'destination': '10.34.0.0/32',
'nexthop': self.nexthop1},
{'destination': '10.35.0.0/32',
'nexthop': self.nexthop1},
{'destination': '10.36.0.0/32',
'nexthop': self.nexthop1},
{'destination': '10.37.0.0/32',
'nexthop': self.nexthop1},
{'destination': '10.38.0.0/32',
'nexthop': self.nexthop1}]}
new_host_routes = _subnet_data['new_host_routes']
kwargs = {'host_routes': new_host_routes}
new_name = "New_subnet"
subnet_id = t_subnet['id']
# Update subnet with host-route info
subnet = self.subnets_client.update_subnet(
subnet_id, name=new_name, **kwargs)
'''
Above No of host-routes added are 19 so checking len of
subnet host_routes equal to 19 or not
'''
if (len(subnet['subnet']['host_routes']) == 19):
LOG.info(_LI("Multiple entries for host routes available"))
LOG.info(_LI("Testcase DHCP-121 option multi host routes completed"))
def remove_project_network(self, from_test=True):
project_name = 'green'
tenant = getattr(self, project_name, None)
servers_client = tenant['client_mgr'].servers_client
dmgr.delete_all_servers(servers_client)
self.disassociate_floatingip(tenant['fip1'])
if from_test:
time.sleep(dmgr.WAITTIME_AFTER_DISASSOC_FLOATINGIP)
fip_client = tenant['client_mgr'].floating_ips_client
fip_client.delete_floatingip(tenant['fip1'].id)
tenant.pop('fip1')
tenant['router'].delete_subnet(tenant['subnet'])
tenant['subnet'].delete()
tenant['network'].delete()
def check_server_connected(self, serv):
# Fetch tenant-network from where vm deployed
serv_net = list(serv['addresses'].keys())[0]
serv_addr = serv['addresses'][serv_net][0]
host_ip = serv_addr['addr']
self.waitfor_host_connected(host_ip)
def create_project_network_subnet(self,
name_prefix='dhcp-project'):
network_name = data_utils.rand_name(name_prefix)
network, subnet = self.create_network_subnet(
name=network_name)
return (network.id, network, subnet)
def dhcp_121_metadata_hostroutes_check_on_vm_nsxv(self, vm_env):
self.serv_fip = vm_env['fip1'].floating_ip_address
username, password = self.get_image_userpass()
# Connect to instance launched using ssh lib
client = ssh.Client(self.serv_fip, username=username,
password=password)
# Executes route over launched instance
cmd = ('route -n')
out_data = client.exec_command(cmd)
self.assertIn(Metadataserver_ip, out_data)
LOG.info(_LI("Metadata routes available on vm"))
cmd = ('wget http://169.254.169.254 -O sample.txt')
client.exec_command(cmd)
cmd = ('cat sample.txt')
out_data = client.exec_command(cmd)
# Check metadata server inforamtion available or not
self.assertIn('latest', out_data)
LOG.info(_LI("metadata server is acessible"))
# Fetch dhcp edge infor from nsx-v
exc_edge = self.vsm.get_dhcp_edge_info()
self.assertIsNotNone(exc_edge)
# Fetch host-route and metadata info from nsx-v
dhcp_options_info = {}
dhcp_options_info = \
exc_edge['staticBindings']['staticBindings'][0]['dhcpOptions']
# Check Host Route information avaialable at beckend
self.assertIn(
Metadataserver_ip,
dhcp_options_info['option121'][
'staticRoutes'][0]['destinationSubnet'])
# Storing sec-group, network, subnet, router, server info in dict
project_dict = dict(security_group=vm_env['security_group'],
network=vm_env['network'], subnet=vm_env['subnet'],
router=vm_env['router'],
client_mgr=vm_env['client_mgr'],
serv1=vm_env['serv1'], fip1=vm_env['fip1'])
return project_dict
def dhcp_121_hostroutes_clear(self, vm_env):
# Fetch next hop information from tempest.conf
next_hop = CONF.network.project_network_cidr
self.nexthop_host_route = next_hop.rsplit('.', 1)[0]
self.nexthop1 = self.nexthop_host_route + ".2"
# Floating-ip of VM
self.serv_fip = vm_env['fip1'].floating_ip_address
username, password = self.get_image_userpass()
# Update subnet with host routes
_subnet_data = {'host_routes': [{'destination': '10.20.0.0/32',
'nexthop': '10.100.1.1'}],
'new_host_routes': [{'destination': '10.20.0.0/32',
'nexthop': self.nexthop1}]}
new_host_routes = _subnet_data['new_host_routes']
kwargs = {'host_routes': new_host_routes}
new_name = "New_subnet"
subnet_id = vm_env['subnet']['id']
# Update subnet with host-route info
self.subnets_client.update_subnet(
subnet_id, name=new_name, **kwargs)
# Connect to instance launched using ssh lib
client = ssh.Client(self.serv_fip, username=username,
password=password)
# Executes route over instance launched
cmd = ('route -n')
out_data = client.exec_command(cmd)
self.assertIn(
_subnet_data['new_host_routes'][0]['nexthop'], out_data)
self.assertIn(self.nexthop_host_route, out_data)
LOG.info(_LI("Host routes available on vm"))
# Check Host route info at beckend
exc_edge = self.vsm.get_dhcp_edge_info()
self.assertIsNotNone(exc_edge)
# Fetch host-route and metadata info from nsx-v
dhcp_options_info = {}
dhcp_options_info = exc_edge['staticBindings']['staticBindings'][0][
'dhcpOptions']['option121']['staticRoutes']
# Check Host Route information avaialable at beckend
for destination_net in dhcp_options_info:
if _subnet_data['new_host_routes'][0]['destination']\
in destination_net['destinationSubnet'] and\
self.nexthop1 in destination_net['router']:
LOG.info(_LI("Host routes available on nsxv"))
# Update subnet with no host-routes
_subnet_data1 = {'new_host_routes': []}
new_host_routes = _subnet_data1['new_host_routes']
kwargs = {'host_routes': new_host_routes}
new_name = "New_subnet"
self.subnets_client.update_subnet(
subnet_id, name=new_name, **kwargs)
# Executes route over instance launched
cmd = ('dhclient eth0')
client.exec_command(cmd)
cmd = ('route -n')
out_data = client.exec_command(cmd)
self.assertIsNotNone(out_data)
# Check Host routes on VM shouldn't be avialable
self.assertNotIn(
_subnet_data['new_host_routes'][0]['destination'], out_data)
# Check Host-routes at beckend after deletion
exc_edge = self.vsm.get_dhcp_edge_info()
self.assertIsNotNone(exc_edge)
dhcp_options_info = []
dhcp_options_info = exc_edge['staticBindings']['staticBindings'][0][
'dhcpOptions']['option121']['staticRoutes']
# Check Host Route information avaialable at beckend
for destination_net in dhcp_options_info:
if (_subnet_data['new_host_routes'][0]['destination']
not in destination_net['destinationSubnet']):
LOG.info(_LI("Host routes not available on nsxv"))
project_dict = dict(security_group=vm_env['security_group'],
network=vm_env['network'], subnet=vm_env['subnet'],
router=vm_env['router'],
client_mgr=vm_env['client_mgr'],
serv1=vm_env['serv1'], fip1=vm_env['fip1'])
return project_dict
def setup_vm_enviornment(self, client_mgr, t_id,
check_outside_world=True,
cidr_offset=0):
t_network, t_subnet, t_router = self.setup_project_network(
self.public_network_id, namestart=("deploy-%s-tenant" % t_id))
t_security_group = self._create_security_group(
security_groups_client=self.security_groups_client,
security_group_rules_client=self.security_group_rules_client,
namestart='adm')
username, password = self.get_image_userpass()
security_groups = [{'name': t_security_group['name']}]
t_serv1 = self.create_server_on_network(
t_network, security_groups,
image=self.get_server_image(),
flavor=self.get_server_flavor(),
name=t_network['name'])
self.check_server_connected(t_serv1)
t_floatingip = self.create_floatingip_for_server(
t_serv1, client_mgr=self.admin_manager)
msg = ("Associate t_floatingip[%s] to server[%s]"
% (t_floatingip, t_serv1['name']))
self._check_floatingip_connectivity(
t_floatingip, t_serv1, should_connect=True, msg=msg)
vm_enviornment = dict(security_group=t_security_group,
network=t_network, subnet=t_subnet,
router=t_router, client_mgr=client_mgr,
serv1=t_serv1, fip1=t_floatingip)
return vm_enviornment