Merge "Removed RestClientXML class"
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index 1d368af..a2d3877 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -553,6 +553,9 @@
# The mask bits for tenant ipv4 subnets (integer value)
#tenant_network_mask_bits=28
+# Allow the execution of IPv6 tests (boolean value)
+#ipv6_enabled=true
+
# The cidr block to allocate tenant ipv6 subnets from (string
# value)
#tenant_network_v6_cidr=2003::/64
diff --git a/tempest/api/network/test_extra_dhcp_options.py b/tempest/api/network/test_extra_dhcp_options.py
new file mode 100644
index 0000000..ed86d75
--- /dev/null
+++ b/tempest/api/network/test_extra_dhcp_options.py
@@ -0,0 +1,99 @@
+# Copyright 2013 OpenStack Foundation
+# 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.
+
+from tempest.api.network import base
+from tempest.common.utils import data_utils
+from tempest import test
+
+
+class ExtraDHCPOptionsTestJSON(base.BaseNetworkTest):
+ _interface = 'json'
+
+ """
+ Tests the following operations with the Extra DHCP Options Neutron API
+ extension:
+
+ port create
+ port list
+ port show
+ port update
+
+ v2.0 of the Neutron API is assumed. It is also assumed that the Extra
+ DHCP Options extension is enabled in the [network-feature-enabled]
+ section of etc/tempest.conf
+ """
+
+ @classmethod
+ def setUpClass(cls):
+ super(ExtraDHCPOptionsTestJSON, cls).setUpClass()
+ if not test.is_extension_enabled('extra_dhcp_opt', 'network'):
+ msg = "Extra DHCP Options extension not enabled."
+ raise cls.skipException(msg)
+ cls.network = cls.create_network()
+ cls.subnet = cls.create_subnet(cls.network)
+ cls.port = cls.create_port(cls.network)
+
+ @test.attr(type='smoke')
+ def test_create_list_port_with_extra_dhcp_options(self):
+ # Create a port with Extra DHCP Options
+ extra_dhcp_opts = [
+ {'opt_value': 'pxelinux.0', 'opt_name': 'bootfile-name'},
+ {'opt_value': '123.123.123.123', 'opt_name': 'tftp-server'},
+ {'opt_value': '123.123.123.45', 'opt_name': 'server-ip-address'}
+ ]
+ resp, body = self.client.create_port(
+ network_id=self.network['id'],
+ extra_dhcp_opts=extra_dhcp_opts)
+ self.assertEqual('201', resp['status'])
+ port_id = body['port']['id']
+ self.addCleanup(self.client.delete_port, port_id)
+
+ # Confirm port created has Extra DHCP Options
+ resp, body = self.client.list_ports()
+ self.assertEqual('200', resp['status'])
+ ports = body['ports']
+ port = [p for p in ports if p['id'] == port_id]
+ self.assertTrue(port)
+ self._confirm_extra_dhcp_options(port[0], extra_dhcp_opts)
+
+ @test.attr(type='smoke')
+ def test_update_show_port_with_extra_dhcp_options(self):
+ # Update port with extra dhcp options
+ extra_dhcp_opts = [
+ {'opt_value': 'pxelinux.0', 'opt_name': 'bootfile-name'},
+ {'opt_value': '123.123.123.123', 'opt_name': 'tftp-server'},
+ {'opt_value': '123.123.123.45', 'opt_name': 'server-ip-address'}
+ ]
+ name = data_utils.rand_name('new-port-name')
+ resp, body = self.client.update_port(
+ self.port['id'], name=name, extra_dhcp_opts=extra_dhcp_opts)
+ self.assertEqual('200', resp['status'])
+
+ # Confirm extra dhcp options were added to the port
+ resp, body = self.client.show_port(self.port['id'])
+ self.assertEqual('200', resp['status'])
+ self._confirm_extra_dhcp_options(body['port'], extra_dhcp_opts)
+
+ def _confirm_extra_dhcp_options(self, port, extra_dhcp_opts):
+ retrieved = port['extra_dhcp_opts']
+ self.assertEqual(len(retrieved), len(extra_dhcp_opts))
+ for retrieved_option in retrieved:
+ for option in extra_dhcp_opts:
+ if (retrieved_option['opt_value'] == option['opt_value'] and
+ retrieved_option['opt_name'] == option['opt_name']):
+ break
+ else:
+ self.fail('Extra DHCP option not found in port %s' %
+ str(retrieved_option))
diff --git a/tempest/api/network/test_networks.py b/tempest/api/network/test_networks.py
index 9029b1f..aba2c8e 100644
--- a/tempest/api/network/test_networks.py
+++ b/tempest/api/network/test_networks.py
@@ -467,6 +467,14 @@
_tenant_network_cidr = CONF.network.tenant_network_v6_cidr
_tenant_network_mask_bits = CONF.network.tenant_network_v6_mask_bits
+ @classmethod
+ def setUpClass(cls):
+ super(NetworksIpV6TestJSON, cls).setUpClass()
+ if not CONF.network.ipv6_enabled:
+ cls.tearDownClass()
+ skip_msg = "IPv6 Tests are disabled."
+ raise cls.skipException(skip_msg)
+
class NetworksIpV6TestXML(NetworksIpV6TestJSON):
_interface = 'xml'
diff --git a/tempest/config.py b/tempest/config.py
index a2d35a9..c92a04d 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -343,6 +343,9 @@
cfg.IntOpt('tenant_network_mask_bits',
default=28,
help="The mask bits for tenant ipv4 subnets"),
+ cfg.BoolOpt('ipv6_enabled',
+ default=True,
+ help="Allow the execution of IPv6 tests"),
cfg.StrOpt('tenant_network_v6_cidr',
default="2003::/64",
help="The cidr block to allocate tenant ipv6 subnets from"),
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 02a3c9d..4dd51fb 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -681,18 +681,32 @@
Create a subnet for the given network within the cidr block
configured for tenant networks.
"""
+
+ def cidr_in_use(cidr, tenant_id):
+ """
+ :return True if subnet with cidr already exist in tenant
+ False else
+ """
+ cidr_in_use = self._list_subnets(tenant_id=tenant_id, cidr=cidr)
+ return len(cidr_in_use) != 0
+
tenant_cidr = netaddr.IPNetwork(CONF.network.tenant_network_cidr)
result = None
# Repeatedly attempt subnet creation with sequential cidr
# blocks until an unallocated block is found.
for subnet_cidr in tenant_cidr.subnet(
CONF.network.tenant_network_mask_bits):
+ str_cidr = str(subnet_cidr)
+ if cidr_in_use(str_cidr, tenant_id=network.tenant_id):
+ continue
+
body = dict(
subnet=dict(
+ name=data_utils.rand_name(namestart),
ip_version=4,
network_id=network.id,
tenant_id=network.tenant_id,
- cidr=str(subnet_cidr),
+ cidr=str_cidr,
),
)
try:
@@ -705,7 +719,7 @@
self.assertIsNotNone(result, 'Unable to allocate tenant network')
subnet = net_common.DeletableSubnet(client=self.network_client,
**result['subnet'])
- self.assertEqual(subnet.cidr, str(subnet_cidr))
+ self.assertEqual(subnet.cidr, str_cidr)
self.set_resource(data_utils.rand_name(namestart), subnet)
return subnet
diff --git a/tempest/services/network/xml/network_client.py b/tempest/services/network/xml/network_client.py
index a669efc..f6ae718 100644
--- a/tempest/services/network/xml/network_client.py
+++ b/tempest/services/network/xml/network_client.py
@@ -27,7 +27,7 @@
# list of plurals used for xml serialization
PLURALS = ['dns_nameservers', 'host_routes', 'allocation_pools',
- 'fixed_ips', 'extensions']
+ 'fixed_ips', 'extensions', 'extra_dhcp_opts']
def get_rest_client(self, auth_provider):
rc = rest_client.RestClient(auth_provider)
@@ -77,6 +77,18 @@
xml_elem = Element(name)
xml_elem.add_attr("xsi:nil", "true")
return xml_elem
+ elif isinstance(value, dict):
+ dict_element = Element(name)
+ for key, value in value.iteritems():
+ elem = self._get_element(key, value)
+ dict_element.append(elem)
+ return dict_element
+ elif isinstance(value, list):
+ list_element = Element(name)
+ for element in value:
+ elem = self._get_element(name[:-1], element)
+ list_element.append(elem)
+ return list_element
else:
return Element(name, value)
diff --git a/tempest/stress/run_stress.py b/tempest/stress/run_stress.py
index 76320d0..a6c2b77 100755
--- a/tempest/stress/run_stress.py
+++ b/tempest/stress/run_stress.py
@@ -87,8 +87,13 @@
# NOTE(mkoderer): we just save the last result code
if (step_result != 0):
result = step_result
+ if ns.stop:
+ return result
else:
- driver.stress_openstack(tests, ns.duration, ns.number, ns.stop)
+ result = driver.stress_openstack(tests,
+ ns.duration,
+ ns.number,
+ ns.stop)
return result
diff --git a/tools/verify_tempest_config.py b/tools/verify_tempest_config.py
index 29eed9d..4be812c 100755
--- a/tools/verify_tempest_config.py
+++ b/tools/verify_tempest_config.py
@@ -42,7 +42,12 @@
def verify_nova_api_versions(os):
# Check nova api versions - only get base URL without PATH
os.servers_client.skip_path = True
- __, body = RAW_HTTP.request(os.servers_client.base_url, 'GET')
+ # The nova base endpoint url includes the version but to get the versions
+ # list the unversioned endpoint is needed
+ v2_endpoint = os.servers_client.base_url
+ v2_endpoint_parts = v2_endpoint.split('/')
+ endpoint = v2_endpoint_parts[0] + '//' + v2_endpoint_parts[2]
+ __, body = RAW_HTTP.request(endpoint, 'GET')
body = json.loads(body)
# Restore full base_url
os.servers_client.skip_path = False