remove Nova v3 XML testing
this removes the XML base clients, as well as skips any Nova v3
XML tests so that we can actually propose the patch to remove
v3 XML from Nova.
Part of bp:remove-v3-xml-api
Change-Id: I68ff62846346bac94a3b91366aa03f022f3f32b7
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index 872a841..9b9eb9f 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -261,6 +261,11 @@
@classmethod
def setUpClass(cls):
# By default compute tests do not create network resources
+ if cls._interface == "xml":
+ skip_msg = ("XML interface is being removed from Nova v3. "
+ "%s will be removed shortly" % cls.__name__)
+ raise cls.skipException(skip_msg)
+
cls.set_network_resources()
super(BaseV3ComputeTest, cls).setUpClass()
if not cls.config.compute_feature_enabled.api_v3:
diff --git a/tempest/clients.py b/tempest/clients.py
index e44da84..65b603b 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -78,31 +78,6 @@
TenantUsagesV3ClientJSON
from tempest.services.compute.v3.json.version_client import \
VersionV3ClientJSON
-from tempest.services.compute.v3.xml.aggregates_client import \
- AggregatesV3ClientXML
-from tempest.services.compute.v3.xml.availability_zone_client import \
- AvailabilityZoneV3ClientXML
-from tempest.services.compute.v3.xml.certificates_client import \
- CertificatesV3ClientXML
-from tempest.services.compute.v3.xml.extensions_client import \
- ExtensionsV3ClientXML
-from tempest.services.compute.v3.xml.flavors_client import FlavorsV3ClientXML
-from tempest.services.compute.v3.xml.hosts_client import HostsV3ClientXML
-from tempest.services.compute.v3.xml.hypervisor_client import \
- HypervisorV3ClientXML
-from tempest.services.compute.v3.xml.instance_usage_audit_log_client import \
- InstanceUsagesAuditLogV3ClientXML
-from tempest.services.compute.v3.xml.interfaces_client import \
- InterfacesV3ClientXML
-from tempest.services.compute.v3.xml.keypairs_client import KeyPairsV3ClientXML
-from tempest.services.compute.v3.xml.quotas_client import \
- QuotasV3ClientXML
-from tempest.services.compute.v3.xml.servers_client import ServersV3ClientXML
-from tempest.services.compute.v3.xml.services_client import \
- ServicesV3ClientXML
-from tempest.services.compute.v3.xml.tenant_usages_client import \
- TenantUsagesV3ClientXML
-from tempest.services.compute.v3.xml.version_client import VersionV3ClientXML
from tempest.services.compute.xml.aggregates_client import AggregatesClientXML
from tempest.services.compute.xml.availability_zone_client import \
AvailabilityZoneClientXML
@@ -238,20 +213,13 @@
if interface == 'xml':
self.certificates_client = CertificatesClientXML(*client_args)
- self.certificates_v3_client = CertificatesV3ClientXML(*client_args)
self.baremetal_client = BaremetalClientXML(*client_args)
self.servers_client = ServersClientXML(*client_args)
- self.servers_v3_client = ServersV3ClientXML(*client_args)
self.limits_client = LimitsClientXML(*client_args)
self.images_client = ImagesClientXML(*client_args)
- self.keypairs_v3_client = KeyPairsV3ClientXML(*client_args)
self.keypairs_client = KeyPairsClientXML(*client_args)
- self.keypairs_v3_client = KeyPairsV3ClientXML(*client_args)
self.quotas_client = QuotasClientXML(*client_args)
- self.quotas_v3_client = QuotasV3ClientXML(*client_args)
self.flavors_client = FlavorsClientXML(*client_args)
- self.flavors_v3_client = FlavorsV3ClientXML(*client_args)
- self.extensions_v3_client = ExtensionsV3ClientXML(*client_args)
self.extensions_client = ExtensionsClientXML(*client_args)
self.volumes_extensions_client = VolumesExtensionsClientXML(
*client_args)
@@ -264,38 +232,26 @@
self.token_client = TokenClientXML(CONF)
self.security_groups_client = SecurityGroupsClientXML(
*client_args)
- self.interfaces_v3_client = InterfacesV3ClientXML(*client_args)
self.interfaces_client = InterfacesClientXML(*client_args)
self.endpoints_client = EndPointClientXML(*client_args)
self.fixed_ips_client = FixedIPsClientXML(*client_args)
- self.availability_zone_v3_client = AvailabilityZoneV3ClientXML(
- *client_args)
self.availability_zone_client = AvailabilityZoneClientXML(
*client_args)
- self.services_v3_client = ServicesV3ClientXML(*client_args)
self.service_client = ServiceClientXML(*client_args)
- self.aggregates_v3_client = AggregatesV3ClientXML(*client_args)
self.aggregates_client = AggregatesClientXML(*client_args)
self.services_client = ServicesClientXML(*client_args)
- self.tenant_usages_v3_client = TenantUsagesV3ClientXML(
- *client_args)
self.tenant_usages_client = TenantUsagesClientXML(*client_args)
- self.version_v3_client = VersionV3ClientXML(*client_args)
self.policy_client = PolicyClientXML(*client_args)
self.hosts_client = HostsClientXML(*client_args)
- self.hypervisor_v3_client = HypervisorV3ClientXML(*client_args)
self.hypervisor_client = HypervisorClientXML(*client_args)
self.token_v3_client = V3TokenClientXML(*client_args)
self.network_client = NetworkClientXML(*client_args)
self.credentials_client = CredentialsClientXML(*client_args)
self.instance_usages_audit_log_client = \
InstanceUsagesAuditLogClientXML(*client_args)
- self.instance_usages_audit_log_v3_client = \
- InstanceUsagesAuditLogV3ClientXML(*client_args)
self.volume_hosts_client = VolumeHostsClientXML(*client_args)
self.volumes_extension_client = VolumeExtensionClientXML(
*client_args)
- self.hosts_v3_client = HostsV3ClientXML(*client_args)
if client_args_v3_auth:
self.servers_client_v3_auth = ServersClientXML(
diff --git a/tempest/services/compute/v3/xml/__init__.py b/tempest/services/compute/v3/xml/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tempest/services/compute/v3/xml/__init__.py
+++ /dev/null
diff --git a/tempest/services/compute/v3/xml/aggregates_client.py b/tempest/services/compute/v3/xml/aggregates_client.py
deleted file mode 100644
index d619aa7..0000000
--- a/tempest/services/compute/v3/xml/aggregates_client.py
+++ /dev/null
@@ -1,128 +0,0 @@
-# Copyright 2013 NEC Corporation.
-# 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 lxml import etree
-
-from tempest.common.rest_client import RestClientXML
-from tempest import exceptions
-from tempest.services.compute.xml.common import Document
-from tempest.services.compute.xml.common import Element
-from tempest.services.compute.xml.common import Text
-from tempest.services.compute.xml.common import xml_to_json
-
-
-class AggregatesV3ClientXML(RestClientXML):
-
- def __init__(self, config, username, password, auth_url, tenant_name=None):
- super(AggregatesV3ClientXML, self).__init__(config, username, password,
- auth_url, tenant_name)
- self.service = self.config.compute.catalog_v3_type
-
- def _format_aggregate(self, g):
- agg = xml_to_json(g)
- aggregate = {}
- for key, value in agg.items():
- if key == 'hosts':
- aggregate['hosts'] = []
- for k, v in value.items():
- aggregate['hosts'].append(v)
- elif key == 'availability_zone':
- aggregate[key] = None if value == 'None' else value
- else:
- aggregate[key] = value
- return aggregate
-
- def _parse_array(self, node):
- return [self._format_aggregate(x) for x in node]
-
- def list_aggregates(self):
- """Get aggregate list."""
- resp, body = self.get("os-aggregates", self.headers)
- aggregates = self._parse_array(etree.fromstring(body))
- return resp, aggregates
-
- def get_aggregate(self, aggregate_id):
- """Get details of the given aggregate."""
- resp, body = self.get("os-aggregates/%s" % str(aggregate_id),
- self.headers)
- aggregate = self._format_aggregate(etree.fromstring(body))
- return resp, aggregate
-
- def create_aggregate(self, name, availability_zone=None):
- """Creates a new aggregate."""
- post_body = Element("aggregate",
- name=name,
- availability_zone=availability_zone)
- resp, body = self.post('os-aggregates',
- str(Document(post_body)),
- self.headers)
- aggregate = self._format_aggregate(etree.fromstring(body))
- return resp, aggregate
-
- def update_aggregate(self, aggregate_id, name, availability_zone=None):
- """Update a aggregate."""
- put_body = Element("aggregate",
- name=name,
- availability_zone=availability_zone)
- resp, body = self.put('os-aggregates/%s' % str(aggregate_id),
- str(Document(put_body)),
- self.headers)
- aggregate = self._format_aggregate(etree.fromstring(body))
- return resp, aggregate
-
- def delete_aggregate(self, aggregate_id):
- """Deletes the given aggregate."""
- return self.delete("os-aggregates/%s" % str(aggregate_id),
- self.headers)
-
- def is_resource_deleted(self, id):
- try:
- self.get_aggregate(id)
- except exceptions.NotFound:
- return True
- return False
-
- def add_host(self, aggregate_id, host):
- """Adds a host to the given aggregate."""
- post_body = Element("add_host", host=host)
- resp, body = self.post('os-aggregates/%s/action' % aggregate_id,
- str(Document(post_body)),
- self.headers)
- aggregate = self._format_aggregate(etree.fromstring(body))
- return resp, aggregate
-
- def remove_host(self, aggregate_id, host):
- """Removes a host from the given aggregate."""
- post_body = Element("remove_host", host=host)
- resp, body = self.post('os-aggregates/%s/action' % aggregate_id,
- str(Document(post_body)),
- self.headers)
- aggregate = self._format_aggregate(etree.fromstring(body))
- return resp, aggregate
-
- def set_metadata(self, aggregate_id, meta):
- """Replaces the aggregate's existing metadata with new metadata."""
- post_body = Element("set_metadata")
- metadata = Element("metadata")
- post_body.append(metadata)
- for k, v in meta.items():
- meta = Element(k)
- meta.append(Text(v))
- metadata.append(meta)
- resp, body = self.post('os-aggregates/%s/action' % aggregate_id,
- str(Document(post_body)),
- self.headers)
- aggregate = self._format_aggregate(etree.fromstring(body))
- return resp, aggregate
diff --git a/tempest/services/compute/v3/xml/availability_zone_client.py b/tempest/services/compute/v3/xml/availability_zone_client.py
deleted file mode 100644
index 5278eab..0000000
--- a/tempest/services/compute/v3/xml/availability_zone_client.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright 2013 NEC Corporation
-# 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 lxml import etree
-
-from tempest.common.rest_client import RestClientXML
-from tempest.services.compute.xml.common import xml_to_json
-
-
-class AvailabilityZoneV3ClientXML(RestClientXML):
-
- def __init__(self, config, username, password, auth_url, tenant_name=None):
- super(AvailabilityZoneV3ClientXML, self).__init__(config, username,
- password, auth_url,
- tenant_name)
- self.service = self.config.compute.catalog_v3_type
-
- def _parse_array(self, node):
- return [xml_to_json(x) for x in node]
-
- def get_availability_zone_list(self):
- resp, body = self.get('os-availability-zone', self.headers)
- availability_zone = self._parse_array(etree.fromstring(body))
- return resp, availability_zone
-
- def get_availability_zone_list_detail(self):
- resp, body = self.get('os-availability-zone/detail', self.headers)
- availability_zone = self._parse_array(etree.fromstring(body))
- return resp, availability_zone
diff --git a/tempest/services/compute/v3/xml/certificates_client.py b/tempest/services/compute/v3/xml/certificates_client.py
deleted file mode 100644
index 0ff4de4..0000000
--- a/tempest/services/compute/v3/xml/certificates_client.py
+++ /dev/null
@@ -1,39 +0,0 @@
-# Copyright 2013 IBM Corp
-# 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.common.rest_client import RestClientXML
-
-
-class CertificatesV3ClientXML(RestClientXML):
-
- def __init__(self, config, username, password, auth_url, tenant_name=None):
- super(CertificatesV3ClientXML, self).__init__(config, username,
- password,
- auth_url, tenant_name)
- self.service = self.config.compute.catalog_v3_type
-
- def get_certificate(self, id):
- url = "os-certificates/%s" % (id)
- resp, body = self.get(url, self.headers)
- body = self._parse_resp(body)
- return resp, body
-
- def create_certificate(self):
- """create certificates."""
- url = "os-certificates"
- resp, body = self.post(url, None, self.headers)
- body = self._parse_resp(body)
- return resp, body
diff --git a/tempest/services/compute/v3/xml/extensions_client.py b/tempest/services/compute/v3/xml/extensions_client.py
deleted file mode 100644
index 8145e20..0000000
--- a/tempest/services/compute/v3/xml/extensions_client.py
+++ /dev/null
@@ -1,48 +0,0 @@
-# Copyright 2012 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 lxml import etree
-from tempest.common.rest_client import RestClientXML
-from tempest.services.compute.xml.common import xml_to_json
-
-
-class ExtensionsV3ClientXML(RestClientXML):
-
- def __init__(self, config, username, password, auth_url, tenant_name=None):
- super(ExtensionsV3ClientXML, self).__init__(config, username, password,
- auth_url, tenant_name)
- self.service = self.config.compute.catalog_v3_type
-
- def _parse_array(self, node):
- array = []
- for child in node:
- array.append(xml_to_json(child))
- return array
-
- def list_extensions(self):
- url = 'extensions'
- resp, body = self.get(url, self.headers)
- body = self._parse_array(etree.fromstring(body))
- return resp, body
-
- def is_enabled(self, extension):
- _, extensions = self.list_extensions()
- exts = extensions['extensions']
- return any([e for e in exts if e['name'] == extension])
-
- def get_extension(self, extension_alias):
- resp, body = self.get('extensions/%s' % extension_alias, self.headers)
- body = xml_to_json(etree.fromstring(body))
- return resp, body
diff --git a/tempest/services/compute/v3/xml/flavors_client.py b/tempest/services/compute/v3/xml/flavors_client.py
deleted file mode 100644
index f568488..0000000
--- a/tempest/services/compute/v3/xml/flavors_client.py
+++ /dev/null
@@ -1,210 +0,0 @@
-# Copyright 2012 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.
-
-import urllib
-
-from lxml import etree
-
-from tempest.common.rest_client import RestClientXML
-from tempest.services.compute.xml.common import Document
-from tempest.services.compute.xml.common import Element
-from tempest.services.compute.xml.common import Text
-from tempest.services.compute.xml.common import xml_to_json
-from tempest.services.compute.xml.common import XMLNS_V3
-
-XMLNS_OS_FLV_ACCESS = \
- "http://docs.openstack.org/compute/core/flavor-access/api/v3"
-
-
-class FlavorsV3ClientXML(RestClientXML):
-
- def __init__(self, config, username, password, auth_url, tenant_name=None):
- super(FlavorsV3ClientXML, self).__init__(config, username, password,
- auth_url, tenant_name)
- self.service = self.config.compute.catalog_v3_type
-
- def _format_flavor(self, f):
- flavor = {'links': []}
- for k, v in f.items():
- if k == 'id':
- flavor['id'] = v
- continue
-
- if k == 'link':
- flavor['links'].append(v)
- continue
-
- if k == '{%s}is_public' % XMLNS_OS_FLV_ACCESS:
- k = 'flavor-access:is_public'
- v = True if v == 'True' else False
-
- if k == 'extra_specs':
- k = 'flavor-extra-specs:extra_specs'
- flavor[k] = dict(v)
- continue
-
- try:
- v = int(v)
- except ValueError:
- try:
- v = float(v)
- except ValueError:
- pass
-
- flavor[k] = v
-
- return flavor
-
- def _parse_array(self, node):
- return [self._format_flavor(xml_to_json(x)) for x in node]
-
- def _list_flavors(self, url, params):
- if params:
- url += "?%s" % urllib.urlencode(params)
-
- resp, body = self.get(url, self.headers)
- flavors = self._parse_array(etree.fromstring(body))
- return resp, flavors
-
- def list_flavors(self, params=None):
- url = 'flavors'
- return self._list_flavors(url, params)
-
- def list_flavors_with_detail(self, params=None):
- url = 'flavors/detail'
- return self._list_flavors(url, params)
-
- def get_flavor_details(self, flavor_id):
- resp, body = self.get("flavors/%s" % str(flavor_id), self.headers)
- body = xml_to_json(etree.fromstring(body))
- flavor = self._format_flavor(body)
- return resp, flavor
-
- def create_flavor(self, name, ram, vcpus, disk, flavor_id, **kwargs):
- """Creates a new flavor or instance type."""
- flavor = Element("flavor",
- xmlns=XMLNS_V3,
- ram=ram,
- vcpus=vcpus,
- disk=disk,
- id=flavor_id,
- name=name)
- if kwargs.get('rxtx'):
- flavor.add_attr('rxtx_factor', kwargs.get('rxtx'))
- if kwargs.get('swap'):
- flavor.add_attr('swap', kwargs.get('swap'))
- if kwargs.get('ephemeral'):
- flavor.add_attr('ephemeral', kwargs.get('ephemeral'))
- if kwargs.get('is_public'):
- flavor.add_attr('flavor-access:is_public',
- kwargs.get('is_public'))
- flavor.add_attr('xmlns:flavor-access', XMLNS_OS_FLV_ACCESS)
- resp, body = self.post('flavors', str(Document(flavor)), self.headers)
- body = xml_to_json(etree.fromstring(body))
- flavor = self._format_flavor(body)
- return resp, flavor
-
- def delete_flavor(self, flavor_id):
- """Deletes the given flavor."""
- return self.delete("flavors/%s" % str(flavor_id), self.headers)
-
- def is_resource_deleted(self, id):
- # Did not use get_flavor_details(id) for verification as it gives
- # 200 ok even for deleted id. LP #981263
- # we can remove the loop here and use get by ID when bug gets sortedout
- resp, flavors = self.list_flavors_with_detail()
- for flavor in flavors:
- if flavor['id'] == id:
- return False
- return True
-
- def set_flavor_extra_spec(self, flavor_id, specs):
- """Sets extra Specs to the mentioned flavor."""
- extra_specs = Element("extra_specs")
- for key in specs.keys():
- extra_specs.add_attr(key, specs[key])
- resp, body = self.post('flavors/%s/flavor-extra-specs' % flavor_id,
- str(Document(extra_specs)), self.headers)
- body = xml_to_json(etree.fromstring(body))
- return resp, body
-
- def get_flavor_extra_spec(self, flavor_id):
- """Gets extra Specs of the mentioned flavor."""
- resp, body = self.get('flavors/%s/flavor-extra-specs' % flavor_id,
- self.headers)
- body = xml_to_json(etree.fromstring(body))
- return resp, body
-
- def get_flavor_extra_spec_with_key(self, flavor_id, key):
- """Gets extra Specs key-value of the mentioned flavor and key."""
- resp, xml_body = self.get('flavors/%s/flavor-extra-specs/%s' %
- (str(flavor_id), key), self.headers)
- body = {}
- element = etree.fromstring(xml_body)
- key = element.get('key')
- body[key] = xml_to_json(element)
- return resp, body
-
- def update_flavor_extra_spec(self, flavor_id, key, **kwargs):
- """Update extra Specs details of the mentioned flavor and key."""
- doc = Document()
- for (k, v) in kwargs.items():
- element = Element(k)
- doc.append(element)
- value = Text(v)
- element.append(value)
-
- resp, body = self.put('flavors/%s/flavor-extra-specs/%s' %
- (flavor_id, key),
- str(doc), self.headers)
- body = xml_to_json(etree.fromstring(body))
- return resp, {key: body}
-
- def unset_flavor_extra_spec(self, flavor_id, key):
- """Unsets an extra spec based on the mentioned flavor and key."""
- return self.delete('flavors/%s/flavor-extra-specs/%s' %
- (str(flavor_id), key))
-
- def _parse_array_access(self, node):
- return [xml_to_json(x) for x in node]
-
- def list_flavor_access(self, flavor_id):
- """Gets flavor access information given the flavor id."""
- resp, body = self.get('flavors/%s/flavor-access' % str(flavor_id),
- self.headers)
- body = self._parse_array(etree.fromstring(body))
- return resp, body
-
- def add_flavor_access(self, flavor_id, tenant_id):
- """Add flavor access for the specified tenant."""
- doc = Document()
- server = Element("add_tenant_access")
- doc.append(server)
- server.add_attr("tenant_id", tenant_id)
- resp, body = self.post('flavors/%s/action' % str(flavor_id),
- str(doc), self.headers)
- body = self._parse_array_access(etree.fromstring(body))
- return resp, body
-
- def remove_flavor_access(self, flavor_id, tenant_id):
- """Remove flavor access from the specified tenant."""
- doc = Document()
- server = Element("remove_tenant_access")
- doc.append(server)
- server.add_attr("tenant_id", tenant_id)
- resp, body = self.post('flavors/%s/action' % str(flavor_id),
- str(doc), self.headers)
- body = self._parse_array_access(etree.fromstring(body))
- return resp, body
diff --git a/tempest/services/compute/v3/xml/hosts_client.py b/tempest/services/compute/v3/xml/hosts_client.py
deleted file mode 100644
index 2951928..0000000
--- a/tempest/services/compute/v3/xml/hosts_client.py
+++ /dev/null
@@ -1,90 +0,0 @@
-# Copyright 2013 IBM Corp.
-#
-# 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 urllib
-
-from lxml import etree
-from tempest.common.rest_client import RestClientXML
-from tempest.services.compute.xml.common import Document
-from tempest.services.compute.xml.common import Element
-from tempest.services.compute.xml.common import xml_to_json
-
-
-class HostsV3ClientXML(RestClientXML):
-
- def __init__(self, config, username, password, auth_url, tenant_name=None):
- super(HostsV3ClientXML, self).__init__(config, username, password,
- auth_url, tenant_name)
- self.service = self.config.compute.catalog_v3_type
-
- def list_hosts(self, params=None):
- """Lists all hosts."""
-
- url = 'os-hosts'
- if params:
- url += '?%s' % urllib.urlencode(params)
-
- resp, body = self.get(url, self.headers)
- node = etree.fromstring(body)
- body = [xml_to_json(x) for x in node.getchildren()]
- return resp, body
-
- def show_host_detail(self, hostname):
- """Show detail information for the host."""
-
- resp, body = self.get("os-hosts/%s" % str(hostname), self.headers)
- node = etree.fromstring(body)
- body = [xml_to_json(node)]
- return resp, body
-
- def update_host(self, hostname, **kwargs):
- """Update a host."""
-
- request_body = Element("host")
- if kwargs:
- for k, v in kwargs.iteritems():
- request_body.append(Element(k, v))
- resp, body = self.put("os-hosts/%s" % str(hostname),
- str(Document(request_body)),
- self.headers)
- node = etree.fromstring(body)
- body = [xml_to_json(x) for x in node.getchildren()]
- return resp, body
-
- def startup_host(self, hostname):
- """Startup a host."""
-
- resp, body = self.get("os-hosts/%s/startup" % str(hostname),
- self.headers)
- node = etree.fromstring(body)
- body = [xml_to_json(x) for x in node.getchildren()]
- return resp, body
-
- def shutdown_host(self, hostname):
- """Shutdown a host."""
-
- resp, body = self.get("os-hosts/%s/shutdown" % str(hostname),
- self.headers)
- node = etree.fromstring(body)
- body = [xml_to_json(x) for x in node.getchildren()]
- return resp, body
-
- def reboot_host(self, hostname):
- """Reboot a host."""
-
- resp, body = self.get("os-hosts/%s/reboot" % str(hostname),
- self.headers)
- node = etree.fromstring(body)
- body = [xml_to_json(x) for x in node.getchildren()]
- return resp, body
diff --git a/tempest/services/compute/v3/xml/hypervisor_client.py b/tempest/services/compute/v3/xml/hypervisor_client.py
deleted file mode 100644
index 2f232ab..0000000
--- a/tempest/services/compute/v3/xml/hypervisor_client.py
+++ /dev/null
@@ -1,77 +0,0 @@
-# Copyright 2013 IBM Corporation
-# 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 lxml import etree
-
-from tempest.common.rest_client import RestClientXML
-from tempest.services.compute.xml.common import xml_to_json
-
-
-class HypervisorV3ClientXML(RestClientXML):
-
- def __init__(self, config, username, password, auth_url, tenant_name=None):
- super(HypervisorV3ClientXML, self).__init__(config, username,
- password, auth_url,
- tenant_name)
- self.service = self.config.compute.catalog_v3_type
-
- def _parse_array(self, node):
- return [xml_to_json(x) for x in node]
-
- def get_hypervisor_list(self):
- """List hypervisors information."""
- resp, body = self.get('os-hypervisors', self.headers)
- hypervisors = self._parse_array(etree.fromstring(body))
- return resp, hypervisors
-
- def get_hypervisor_list_details(self):
- """Show detailed hypervisors information."""
- resp, body = self.get('os-hypervisors/detail', self.headers)
- hypervisors = self._parse_array(etree.fromstring(body))
- return resp, hypervisors
-
- def get_hypervisor_show_details(self, hyper_id):
- """Display the details of the specified hypervisor."""
- resp, body = self.get('os-hypervisors/%s' % hyper_id,
- self.headers)
- hypervisor = xml_to_json(etree.fromstring(body))
- return resp, hypervisor
-
- def get_hypervisor_servers(self, hyper_name):
- """List instances belonging to the specified hypervisor."""
- resp, body = self.get('os-hypervisors/%s/servers' % hyper_name,
- self.headers)
- hypervisors = self._parse_array(etree.fromstring(body))
- return resp, hypervisors
-
- def get_hypervisor_stats(self):
- """Get hypervisor statistics over all compute nodes."""
- resp, body = self.get('os-hypervisors/statistics', self.headers)
- stats = xml_to_json(etree.fromstring(body))
- return resp, stats
-
- def get_hypervisor_uptime(self, hyper_id):
- """Display the uptime of the specified hypervisor."""
- resp, body = self.get('os-hypervisors/%s/uptime' % hyper_id,
- self.headers)
- uptime = xml_to_json(etree.fromstring(body))
- return resp, uptime
-
- def search_hypervisor(self, hyper_name):
- """Search specified hypervisor."""
- resp, body = self.get('os-hypervisors/search?query=%s' % hyper_name,
- self.headers)
- hypervisors = self._parse_array(etree.fromstring(body))
- return resp, hypervisors
diff --git a/tempest/services/compute/v3/xml/instance_usage_audit_log_client.py b/tempest/services/compute/v3/xml/instance_usage_audit_log_client.py
deleted file mode 100644
index ed6f36e..0000000
--- a/tempest/services/compute/v3/xml/instance_usage_audit_log_client.py
+++ /dev/null
@@ -1,36 +0,0 @@
-# Copyright 2013 IBM Corporation
-# 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 lxml import etree
-
-from tempest.common.rest_client import RestClientXML
-from tempest.services.compute.xml.common import xml_to_json
-
-
-class InstanceUsagesAuditLogV3ClientXML(RestClientXML):
-
- def __init__(self, config, username, password, auth_url, tenant_name=None):
- super(InstanceUsagesAuditLogV3ClientXML, self).__init__(
- config, username, password, auth_url, tenant_name)
- self.service = self.config.compute.catalog_v3_type
-
- def list_instance_usage_audit_logs(self, time_before=None):
- if time_before:
- url = 'os-instance-usage-audit-log?before=%s' % time_before
- else:
- url = 'os-instance-usage-audit-log'
- resp, body = self.get(url, self.headers)
- instance_usage_audit_logs = xml_to_json(etree.fromstring(body))
- return resp, instance_usage_audit_logs
diff --git a/tempest/services/compute/v3/xml/interfaces_client.py b/tempest/services/compute/v3/xml/interfaces_client.py
deleted file mode 100644
index 870c130..0000000
--- a/tempest/services/compute/v3/xml/interfaces_client.py
+++ /dev/null
@@ -1,108 +0,0 @@
-# Copyright 2013 IBM Corp.
-# 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 time
-
-from lxml import etree
-
-from tempest.common.rest_client import RestClientXML
-from tempest import exceptions
-from tempest.services.compute.xml.common import Document
-from tempest.services.compute.xml.common import Element
-from tempest.services.compute.xml.common import Text
-from tempest.services.compute.xml.common import xml_to_json
-
-
-class InterfacesV3ClientXML(RestClientXML):
-
- def __init__(self, config, username, password, auth_url, tenant_name=None):
- super(InterfacesV3ClientXML, self).__init__(config, username, password,
- auth_url, tenant_name)
- self.service = self.config.compute.catalog_v3_type
-
- def _process_xml_interface(self, node):
- iface = xml_to_json(node)
- # NOTE(danms): if multiple addresses per interface is ever required,
- # xml_to_json will need to be fixed or replaced in this case
- iface['fixed_ips'] = [dict(iface['fixed_ips']['fixed_ip'].items())]
- return iface
-
- def list_interfaces(self, server):
- resp, body = self.get('servers/%s/os-attach-interfaces' % server,
- self.headers)
- node = etree.fromstring(body)
- interfaces = [self._process_xml_interface(x)
- for x in node.getchildren()]
- return resp, interfaces
-
- def create_interface(self, server, port_id=None, network_id=None,
- fixed_ip=None):
- doc = Document()
- iface = Element('interface_attachment')
- if port_id:
- _port_id = Element('port_id')
- _port_id.append(Text(port_id))
- iface.append(_port_id)
- if network_id:
- _network_id = Element('net_id')
- _network_id.append(Text(network_id))
- iface.append(_network_id)
- if fixed_ip:
- _fixed_ips = Element('fixed_ips')
- _fixed_ip = Element('fixed_ip')
- _ip_address = Element('ip_address')
- _ip_address.append(Text(fixed_ip))
- _fixed_ip.append(_ip_address)
- _fixed_ips.append(_fixed_ip)
- iface.append(_fixed_ips)
- doc.append(iface)
- resp, body = self.post('servers/%s/os-attach-interfaces' % server,
- headers=self.headers,
- body=str(doc))
- body = self._process_xml_interface(etree.fromstring(body))
- return resp, body
-
- def show_interface(self, server, port_id):
- resp, body =\
- self.get('servers/%s/os-attach-interfaces/%s' % (server, port_id),
- self.headers)
- body = self._process_xml_interface(etree.fromstring(body))
- return resp, body
-
- def delete_interface(self, server, port_id):
- resp, body =\
- self.delete('servers/%s/os-attach-interfaces/%s' % (server,
- port_id))
- return resp, body
-
- def wait_for_interface_status(self, server, port_id, status):
- """Waits for a interface to reach a given status."""
- resp, body = self.show_interface(server, port_id)
- interface_status = body['port_state']
- start = int(time.time())
-
- while(interface_status != status):
- time.sleep(self.build_interval)
- resp, body = self.show_interface(server, port_id)
- interface_status = body['port_state']
-
- timed_out = int(time.time()) - start >= self.build_timeout
-
- if interface_status != status and timed_out:
- message = ('Interface %s failed to reach %s status within '
- 'the required time (%s s).' %
- (port_id, status, self.build_timeout))
- raise exceptions.TimeoutException(message)
- return resp, body
diff --git a/tempest/services/compute/v3/xml/keypairs_client.py b/tempest/services/compute/v3/xml/keypairs_client.py
deleted file mode 100644
index 6efb7fe..0000000
--- a/tempest/services/compute/v3/xml/keypairs_client.py
+++ /dev/null
@@ -1,67 +0,0 @@
-# Copyright 2012 IBM Corp.
-# 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 lxml import etree
-from tempest.common.rest_client import RestClientXML
-from tempest.services.compute.xml.common import Document
-from tempest.services.compute.xml.common import Element
-from tempest.services.compute.xml.common import Text
-from tempest.services.compute.xml.common import xml_to_json
-
-
-class KeyPairsV3ClientXML(RestClientXML):
-
- def __init__(self, config, username, password, auth_url, tenant_name=None):
- super(KeyPairsV3ClientXML, self).__init__(config, username, password,
- auth_url, tenant_name)
- self.service = self.config.compute.catalog_v3_type
-
- def list_keypairs(self):
- resp, body = self.get("keypairs", self.headers)
- node = etree.fromstring(body)
- body = [{'keypair': xml_to_json(x)} for x in node.getchildren()]
- return resp, body
-
- def get_keypair(self, key_name):
- resp, body = self.get("keypairs/%s" % str(key_name), self.headers)
- body = xml_to_json(etree.fromstring(body))
- return resp, body
-
- def create_keypair(self, name, pub_key=None):
- doc = Document()
-
- keypair_element = Element("keypair")
-
- if pub_key:
- public_key_element = Element("public_key")
- public_key_text = Text(pub_key)
- public_key_element.append(public_key_text)
- keypair_element.append(public_key_element)
-
- name_element = Element("name")
- name_text = Text(name)
- name_element.append(name_text)
- keypair_element.append(name_element)
-
- doc.append(keypair_element)
-
- resp, body = self.post("keypairs",
- headers=self.headers, body=str(doc))
- body = xml_to_json(etree.fromstring(body))
- return resp, body
-
- def delete_keypair(self, key_name):
- return self.delete("keypairs/%s" % str(key_name))
diff --git a/tempest/services/compute/v3/xml/quotas_client.py b/tempest/services/compute/v3/xml/quotas_client.py
deleted file mode 100644
index 145c6e8..0000000
--- a/tempest/services/compute/v3/xml/quotas_client.py
+++ /dev/null
@@ -1,111 +0,0 @@
-# Copyright 2012 NTT Data
-# 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 lxml import etree
-
-from tempest.common.rest_client import RestClientXML
-from tempest.services.compute.xml.common import Document
-from tempest.services.compute.xml.common import Element
-from tempest.services.compute.xml.common import xml_to_json
-from tempest.services.compute.xml.common import XMLNS_V3
-
-
-class QuotasV3ClientXML(RestClientXML):
-
- def __init__(self, config, username, password, auth_url, tenant_name=None):
- super(QuotasV3ClientXML, self).__init__(config, username, password,
- auth_url, tenant_name)
- self.service = self.config.compute.catalog_v3_type
-
- def _format_quota(self, q):
- quota = {}
- for k, v in q.items():
- try:
- v = int(v)
- except ValueError:
- pass
-
- quota[k] = v
-
- return quota
-
- def _parse_array(self, node):
- return [self._format_quota(xml_to_json(x)) for x in node]
-
- def get_quota_set(self, tenant_id):
- """List the quota set for a tenant."""
-
- url = 'os-quota-sets/%s' % str(tenant_id)
- resp, body = self.get(url, self.headers)
- body = xml_to_json(etree.fromstring(body))
- body = self._format_quota(body)
- return resp, body
-
- def get_default_quota_set(self, tenant_id):
- """List the default quota set for a tenant."""
-
- url = 'os-quota-sets/%s/defaults' % str(tenant_id)
- resp, body = self.get(url, self.headers)
- body = xml_to_json(etree.fromstring(body))
- body = self._format_quota(body)
- return resp, body
-
- def update_quota_set(self, tenant_id, force=None,
- metadata_items=None, ram=None, floating_ips=None,
- fixed_ips=None, key_pairs=None, instances=None,
- security_group_rules=None, cores=None,
- security_groups=None):
- """
- Updates the tenant's quota limits for one or more resources
- """
- post_body = Element("quota_set",
- xmlns=XMLNS_V3)
-
- if force is not None:
- post_body.add_attr('force', force)
-
- if metadata_items is not None:
- post_body.add_attr('metadata_items', metadata_items)
-
- if ram is not None:
- post_body.add_attr('ram', ram)
-
- if floating_ips is not None:
- post_body.add_attr('floating_ips', floating_ips)
-
- if fixed_ips is not None:
- post_body.add_attr('fixed_ips', fixed_ips)
-
- if key_pairs is not None:
- post_body.add_attr('key_pairs', key_pairs)
-
- if instances is not None:
- post_body.add_attr('instances', instances)
-
- if security_group_rules is not None:
- post_body.add_attr('security_group_rules', security_group_rules)
-
- if cores is not None:
- post_body.add_attr('cores', cores)
-
- if security_groups is not None:
- post_body.add_attr('security_groups', security_groups)
-
- resp, body = self.put('os-quota-sets/%s' % str(tenant_id),
- str(Document(post_body)),
- self.headers)
- body = xml_to_json(etree.fromstring(body))
- body = self._format_quota(body)
- return resp, body
diff --git a/tempest/services/compute/v3/xml/servers_client.py b/tempest/services/compute/v3/xml/servers_client.py
deleted file mode 100644
index 240c962..0000000
--- a/tempest/services/compute/v3/xml/servers_client.py
+++ /dev/null
@@ -1,663 +0,0 @@
-# Copyright 2012 IBM Corp.
-# Copyright 2013 Hewlett-Packard Development Company, L.P.
-# 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 time
-import urllib
-
-from lxml import etree
-
-from tempest.common.rest_client import RestClientXML
-from tempest.common import waiters
-from tempest import exceptions
-from tempest.openstack.common import log as logging
-from tempest.services.compute.xml.common import Document
-from tempest.services.compute.xml.common import Element
-from tempest.services.compute.xml.common import Text
-from tempest.services.compute.xml.common import xml_to_json
-from tempest.services.compute.xml.common import XMLNS_V3
-
-
-LOG = logging.getLogger(__name__)
-
-
-def _translate_ip_xml_json(ip):
- """
- Convert the address version to int.
- """
- ip = dict(ip)
- version = ip.get('version')
- if version:
- ip['version'] = int(version)
- if ip.get('type'):
- ip['type'] = ip.get('type')
- if ip.get('mac_addr'):
- ip['mac_addr'] = ip.get('mac_addr')
- return ip
-
-
-def _translate_network_xml_to_json(network):
- return [_translate_ip_xml_json(ip.attrib)
- for ip in network.findall('{%s}ip' % XMLNS_V3)]
-
-
-def _translate_addresses_xml_to_json(xml_addresses):
- return dict((network.attrib['id'], _translate_network_xml_to_json(network))
- for network in xml_addresses.findall('{%s}network' % XMLNS_V3))
-
-
-def _translate_server_xml_to_json(xml_dom):
- """Convert server XML to server JSON.
-
- The addresses collection does not convert well by the dumb xml_to_json.
- This method does some pre and post-processing to deal with that.
-
- Translate XML addresses subtree to JSON.
-
- Having xml_doc similar to
- <api:server xmlns:api="http://docs.openstack.org/compute/api/v3">
- <api:addresses>
- <api:network id="foo_novanetwork">
- <api:ip version="4" addr="192.168.0.4"/>
- </api:network>
- <api:network id="bar_novanetwork">
- <api:ip version="4" addr="10.1.0.4"/>
- <api:ip version="6" addr="2001:0:0:1:2:3:4:5"/>
- </api:network>
- </api:addresses>
- </api:server>
-
- the _translate_server_xml_to_json(etree.fromstring(xml_doc)) should produce
- something like
-
- {'addresses': {'bar_novanetwork': [{'addr': '10.1.0.4', 'version': 4},
- {'addr': '2001:0:0:1:2:3:4:5',
- 'version': 6}],
- 'foo_novanetwork': [{'addr': '192.168.0.4', 'version': 4}]}}
- """
- nsmap = {'api': XMLNS_V3}
- addresses = xml_dom.xpath('/api:server/api:addresses', namespaces=nsmap)
- if addresses:
- if len(addresses) > 1:
- raise ValueError('Expected only single `addresses` element.')
- json_addresses = _translate_addresses_xml_to_json(addresses[0])
- json = xml_to_json(xml_dom)
- json['addresses'] = json_addresses
- else:
- json = xml_to_json(xml_dom)
- disk_config = ('{http://docs.openstack.org'
- '/compute/ext/disk_config/api/v3}disk_config')
- terminated_at = ('{http://docs.openstack.org/'
- 'compute/ext/os-server-usage/api/v3}terminated_at')
- launched_at = ('{http://docs.openstack.org'
- '/compute/ext/os-server-usage/api/v3}launched_at')
- power_state = ('{http://docs.openstack.org'
- '/compute/ext/extended_status/api/v3}power_state')
- availability_zone = ('{http://docs.openstack.org'
- '/compute/ext/extended_availability_zone/api/v3}'
- 'availability_zone')
- vm_state = ('{http://docs.openstack.org'
- '/compute/ext/extended_status/api/v3}vm_state')
- task_state = ('{http://docs.openstack.org'
- '/compute/ext/extended_status/api/v3}task_state')
- access_ip_v4 = ('{http://docs.openstack.org/compute/ext/'
- 'os-access-ips/api/v3}access_ip_v4')
- access_ip_v6 = ('{http://docs.openstack.org/compute/ext/'
- 'os-access-ips/api/v3}access_ip_v6')
- if disk_config in json:
- json['os-disk-config:disk_config'] = json.pop(disk_config)
- if terminated_at in json:
- json['os-server-usage:terminated_at'] = json.pop(terminated_at)
- if launched_at in json:
- json['os-server-usage:launched_at'] = json.pop(launched_at)
- if power_state in json:
- json['os-extended-status:power_state'] = json.pop(power_state)
- if availability_zone in json:
- json['os-extended-availability-zone:availability_zone'] = json.pop(
- availability_zone)
- if vm_state in json:
- json['os-extended-status:vm_state'] = json.pop(vm_state)
- if task_state in json:
- json['os-extended-status:task_state'] = json.pop(task_state)
- if access_ip_v4 in json:
- json['os-access-ips:access_ip_v4'] = json.pop(access_ip_v4)
- if access_ip_v6 in json:
- json['os-access-ips:access_ip_v6'] = json.pop(access_ip_v6)
- return json
-
-
-class ServersV3ClientXML(RestClientXML):
-
- def __init__(self, config, username, password, auth_url,
- tenant_name=None, auth_version='v2'):
- super(ServersV3ClientXML, self).__init__(config, username, password,
- auth_url, tenant_name,
- auth_version=auth_version)
- self.service = self.config.compute.catalog_v3_type
-
- def _parse_key_value(self, node):
- """Parse <foo key='key'>value</foo> data into {'key': 'value'}."""
- data = {}
- for node in node.getchildren():
- data[node.get('key')] = node.text
- return data
-
- def _parse_links(self, node, json):
- del json['link']
- json['links'] = []
- for linknode in node.findall('{http://www.w3.org/2005/Atom}link'):
- json['links'].append(xml_to_json(linknode))
-
- def _parse_server(self, body):
- json = _translate_server_xml_to_json(body)
-
- if 'metadata' in json and json['metadata']:
- # NOTE(danms): if there was metadata, we need to re-parse
- # that as a special type
- metadata_tag = body.find('{%s}metadata' % XMLNS_V3)
- json["metadata"] = self._parse_key_value(metadata_tag)
- if 'link' in json:
- self._parse_links(body, json)
- for sub in ['image', 'flavor']:
- if sub in json and 'link' in json[sub]:
- self._parse_links(body, json[sub])
- return json
-
- def _parse_xml_virtual_interfaces(self, xml_dom):
- """
- Return server's virtual interfaces XML as JSON.
- """
- data = {"virtual_interfaces": []}
- for iface in xml_dom.getchildren():
- data["virtual_interfaces"].append(
- {"id": iface.get("id"),
- "mac_address": iface.get("mac_address")})
- return data
-
- def get_server(self, server_id):
- """Returns the details of an existing server."""
- resp, body = self.get("servers/%s" % str(server_id), self.headers)
- server = self._parse_server(etree.fromstring(body))
- return resp, server
-
- def migrate_server(self, server_id, **kwargs):
- """Migrates the given server ."""
- return self.action(server_id, 'migrate', None, **kwargs)
-
- def lock_server(self, server_id, **kwargs):
- """Locks the given server."""
- return self.action(server_id, 'lock', None, **kwargs)
-
- def unlock_server(self, server_id, **kwargs):
- """Unlocks the given server."""
- return self.action(server_id, 'unlock', None, **kwargs)
-
- def suspend_server(self, server_id, **kwargs):
- """Suspends the provided server."""
- return self.action(server_id, 'suspend', None, **kwargs)
-
- def resume_server(self, server_id, **kwargs):
- """Un-suspends the provided server."""
- return self.action(server_id, 'resume', None, **kwargs)
-
- def pause_server(self, server_id, **kwargs):
- """Pauses the provided server."""
- return self.action(server_id, 'pause', None, **kwargs)
-
- def unpause_server(self, server_id, **kwargs):
- """Un-pauses the provided server."""
- return self.action(server_id, 'unpause', None, **kwargs)
-
- def reset_state(self, server_id, state='error'):
- """Resets the state of a server to active/error."""
- return self.action(server_id, 'reset_state', None, state=state)
-
- def shelve_server(self, server_id, **kwargs):
- """Shelves the provided server."""
- return self.action(server_id, 'shelve', None, **kwargs)
-
- def unshelve_server(self, server_id, **kwargs):
- """Un-shelves the provided server."""
- return self.action(server_id, 'unshelve', None, **kwargs)
-
- def delete_server(self, server_id):
- """Deletes the given server."""
- return self.delete("servers/%s" % str(server_id))
-
- def _parse_array(self, node):
- array = []
- for child in node.getchildren():
- array.append(xml_to_json(child))
- return array
-
- def list_servers(self, params=None):
- url = 'servers'
- if params:
- url += '?%s' % urllib.urlencode(params)
-
- resp, body = self.get(url, self.headers)
- servers = self._parse_array(etree.fromstring(body))
- return resp, {"servers": servers}
-
- def list_servers_with_detail(self, params=None):
- url = 'servers/detail'
- if params:
- url += '?%s' % urllib.urlencode(params)
-
- resp, body = self.get(url, self.headers)
- servers = self._parse_array(etree.fromstring(body))
- return resp, {"servers": servers}
-
- def update_server(self, server_id, name=None, meta=None, access_ip_v4=None,
- access_ip_v6=None, disk_config=None):
- doc = Document()
- server = Element("server")
- doc.append(server)
-
- if name is not None:
- server.add_attr("name", name)
- if access_ip_v4 or access_ip_v6:
- server.add_attr('xmlns:os-access-ips',
- "http://docs.openstack.org/compute/ext/"
- "os-access-ips/api/v3")
- if access_ip_v4 is not None:
- server.add_attr("os-access-ips:access_ip_v4", access_ip_v4)
- if access_ip_v6 is not None:
- server.add_attr("os-access-ips:access_ip_v6", access_ip_v6)
- if disk_config is not None:
- server.add_attr('xmlns:os-disk-config', "http://docs.openstack.org"
- "/compute/ext/disk_config/api/v3")
- server.add_attr("os-disk-config:disk_config", disk_config)
- if meta is not None:
- metadata = Element("metadata")
- server.append(metadata)
- for k, v in meta:
- meta = Element("meta", key=k)
- meta.append(Text(v))
- metadata.append(meta)
-
- resp, body = self.put('servers/%s' % str(server_id),
- str(doc), self.headers)
- return resp, xml_to_json(etree.fromstring(body))
-
- def create_server(self, name, image_ref, flavor_ref, **kwargs):
- """
- Creates an instance of a server.
- name (Required): The name of the server.
- image_ref (Required): Reference to the image used to build the server.
- flavor_ref (Required): The flavor used to build the server.
- Following optional keyword arguments are accepted:
- admin_password: Sets the initial root password.
- key_name: Key name of keypair that was created earlier.
- meta: A dictionary of values to be used as metadata.
- security_groups: A list of security group dicts.
- networks: A list of network dicts with UUID and fixed_ip.
- user_data: User data for instance.
- availability_zone: Availability zone in which to launch instance.
- access_ip_v4: The IPv4 access address for the server.
- access_ip_v6: The IPv6 access address for the server.
- min_count: Count of minimum number of instances to launch.
- max_count: Count of maximum number of instances to launch.
- disk_config: Determines if user or admin controls disk configuration.
- return_reservation_id: Enable/Disable the return of reservation id.
- """
- server = Element("server",
- xmlns=XMLNS_V3,
- flavor_ref=flavor_ref,
- image_ref=image_ref,
- name=name)
- attrs = ["admin_password", "key_name",
- ('os-access-ips:access_ip_v4',
- 'access_ip_v4',
- 'xmlns:os-access-ips',
- "http://docs.openstack.org/compute/ext/"
- "os-access-ips/api/v3"),
- ('os-access-ips:access_ip_v6',
- 'access_ip_v6',
- 'xmlns:os-access-ips',
- "http://docs.openstack.org/compute/ext/"
- "os-access-ips/api/v3"),
- ("os-user-data:user_data",
- 'user_data',
- 'xmlns:os-user-data',
- "http://docs.openstack.org/compute/ext/userdata/api/v3"),
- ("os-availability-zone:availability_zone",
- 'availability_zone',
- 'xmlns:os-availability-zone',
- "http://docs.openstack.org/compute/ext/"
- "availabilityzone/api/v3"),
- ("os-multiple-create:min_count",
- 'min_count',
- 'xmlns:os-multiple-create',
- "http://docs.openstack.org/compute/ext/"
- "multiplecreate/api/v3"),
- ("os-multiple-create:max_count",
- 'max_count',
- 'xmlns:os-multiple-create',
- "http://docs.openstack.org/compute/ext/"
- "multiplecreate/api/v3"),
- ("os-multiple-create:return_reservation_id",
- "return_reservation_id",
- 'xmlns:os-multiple-create',
- "http://docs.openstack.org/compute/ext/"
- "multiplecreate/api/v3"),
- ("os-disk-config:disk_config",
- "disk_config",
- "xmlns:os-disk-config",
- "http://docs.openstack.org/"
- "compute/ext/disk_config/api/v3")]
-
- for attr in attrs:
- if isinstance(attr, tuple):
- post_param = attr[0]
- key = attr[1]
- value = kwargs.get(key)
- if value is not None:
- server.add_attr(attr[2], attr[3])
- server.add_attr(post_param, value)
- else:
- post_param = attr
- key = attr
- value = kwargs.get(key)
- if value is not None:
- server.add_attr(post_param, value)
-
- if 'security_groups' in kwargs:
- server.add_attr("xmlns:os-security-groups",
- "http://docs.openstack.org/compute/ext/"
- "securitygroups/api/v3")
- secgroups = Element("os-security-groups:security_groups")
- server.append(secgroups)
- for secgroup in kwargs['security_groups']:
- s = Element("security_group", name=secgroup['name'])
- secgroups.append(s)
-
- if 'networks' in kwargs:
- networks = Element("networks")
- server.append(networks)
- for network in kwargs['networks']:
- s = Element("network", uuid=network['uuid'],
- fixed_ip=network['fixed_ip'])
- networks.append(s)
-
- if 'meta' in kwargs:
- metadata = Element("metadata")
- server.append(metadata)
- for k, v in kwargs['meta'].items():
- meta = Element("meta", key=k)
- meta.append(Text(v))
- metadata.append(meta)
-
- resp, body = self.post('servers', str(Document(server)), self.headers)
- server = self._parse_server(etree.fromstring(body))
- return resp, server
-
- def wait_for_server_status(self, server_id, status, extra_timeout=0,
- raise_on_error=True):
- """Waits for a server to reach a given status."""
- return waiters.wait_for_server_status(self, server_id, status,
- extra_timeout=extra_timeout,
- raise_on_error=raise_on_error)
-
- def wait_for_server_termination(self, server_id, ignore_error=False):
- """Waits for server to reach termination."""
- start_time = int(time.time())
- while True:
- try:
- resp, body = self.get_server(server_id)
- except exceptions.NotFound:
- return
-
- server_status = body['status']
- if server_status == 'ERROR' and not ignore_error:
- raise exceptions.BuildErrorException
-
- if int(time.time()) - start_time >= self.build_timeout:
- raise exceptions.TimeoutException
-
- time.sleep(self.build_interval)
-
- def _parse_network(self, node):
- addrs = []
- for child in node.getchildren():
- addrs.append({'version': int(child.get('version')),
- 'addr': child.get('addr')})
- return {node.get('id'): addrs}
-
- def list_addresses(self, server_id):
- """Lists all addresses for a server."""
- resp, body = self.get("servers/%s/ips" % str(server_id), self.headers)
-
- networks = {}
- xml_list = etree.fromstring(body)
- for child in xml_list.getchildren():
- network = self._parse_network(child)
- networks.update(**network)
-
- return resp, networks
-
- def list_addresses_by_network(self, server_id, network_id):
- """Lists all addresses of a specific network type for a server."""
- resp, body = self.get("servers/%s/ips/%s" % (str(server_id),
- network_id),
- self.headers)
- network = self._parse_network(etree.fromstring(body))
-
- return resp, network
-
- def action(self, server_id, action_name, response_key, **kwargs):
- if 'xmlns' not in kwargs:
- kwargs['xmlns'] = XMLNS_V3
- doc = Document((Element(action_name, **kwargs)))
- resp, body = self.post("servers/%s/action" % server_id,
- str(doc), self.headers)
- if response_key is not None:
- body = xml_to_json(etree.fromstring(body))
- return resp, body
-
- def create_backup(self, server_id, backup_type, rotation, name):
- """Backup a server instance."""
- return self.action(server_id, "create_backup", None,
- backup_type=backup_type,
- rotation=rotation,
- name=name)
-
- def change_password(self, server_id, password):
- return self.action(server_id, "change_password", None,
- admin_password=password)
-
- def reboot(self, server_id, reboot_type):
- return self.action(server_id, "reboot", None, type=reboot_type)
-
- def rebuild(self, server_id, image_ref, **kwargs):
- kwargs['image_ref'] = image_ref
- if 'disk_config' in kwargs:
- kwargs['os-disk-config:disk_config'] = kwargs['disk_config']
- del kwargs['disk_config']
- kwargs['xmlns:os-disk-config'] = "http://docs.openstack.org/"\
- "compute/ext/disk_config/api/v3"
- kwargs['xmlns:atom'] = "http://www.w3.org/2005/Atom"
- if 'xmlns' not in kwargs:
- kwargs['xmlns'] = XMLNS_V3
-
- attrs = kwargs.copy()
- if 'metadata' in attrs:
- del attrs['metadata']
- rebuild = Element("rebuild",
- **attrs)
-
- if 'metadata' in kwargs:
- metadata = Element("metadata")
- rebuild.append(metadata)
- for k, v in kwargs['metadata'].items():
- meta = Element("meta", key=k)
- meta.append(Text(v))
- metadata.append(meta)
-
- resp, body = self.post('servers/%s/action' % server_id,
- str(Document(rebuild)), self.headers)
- server = self._parse_server(etree.fromstring(body))
- return resp, server
-
- def resize(self, server_id, flavor_ref, **kwargs):
- if 'disk_config' in kwargs:
- kwargs['os-disk-config:disk_config'] = kwargs['disk_config']
- del kwargs['disk_config']
- kwargs['xmlns:os-disk-config'] = "http://docs.openstack.org/"\
- "compute/ext/disk_config/api/v3"
- kwargs['xmlns:atom'] = "http://www.w3.org/2005/Atom"
- kwargs['flavor_ref'] = flavor_ref
- return self.action(server_id, 'resize', None, **kwargs)
-
- def confirm_resize(self, server_id, **kwargs):
- return self.action(server_id, 'confirm_resize', None, **kwargs)
-
- def revert_resize(self, server_id, **kwargs):
- return self.action(server_id, 'revert_resize', None, **kwargs)
-
- def stop(self, server_id, **kwargs):
- return self.action(server_id, 'stop', None, **kwargs)
-
- def start(self, server_id, **kwargs):
- return self.action(server_id, 'start', None, **kwargs)
-
- def create_image(self, server_id, name, meta=None):
- """Creates an image of the original server."""
- post_body = Element('create_image', name=name)
-
- if meta:
- metadata = Element('metadata')
- post_body.append(metadata)
- for k, v in meta.items():
- data = Element('meta', key=k)
- data.append(Text(v))
- metadata.append(data)
- resp, body = self.post('servers/%s/action' % str(server_id),
- str(Document(post_body)), self.headers)
- return resp, body
-
- def live_migrate_server(self, server_id, dest_host, use_block_migration):
- """This should be called with administrator privileges ."""
-
- req_body = Element("migrate_live",
- xmlns=XMLNS_V3,
- disk_over_commit=False,
- block_migration=use_block_migration,
- host=dest_host)
-
- resp, body = self.post("servers/%s/action" % str(server_id),
- str(Document(req_body)), self.headers)
- return resp, body
-
- def list_server_metadata(self, server_id):
- resp, body = self.get("servers/%s/metadata" % str(server_id),
- self.headers)
- body = self._parse_key_value(etree.fromstring(body))
- return resp, body
-
- def set_server_metadata(self, server_id, meta, no_metadata_field=False):
- doc = Document()
- if not no_metadata_field:
- metadata = Element("metadata")
- doc.append(metadata)
- for k, v in meta.items():
- meta_element = Element("meta", key=k)
- meta_element.append(Text(v))
- metadata.append(meta_element)
- resp, body = self.put('servers/%s/metadata' % str(server_id),
- str(doc), self.headers)
- return resp, xml_to_json(etree.fromstring(body))
-
- def update_server_metadata(self, server_id, meta):
- doc = Document()
- metadata = Element("metadata")
- doc.append(metadata)
- for k, v in meta.items():
- meta_element = Element("meta", key=k)
- meta_element.append(Text(v))
- metadata.append(meta_element)
- resp, body = self.post("/servers/%s/metadata" % str(server_id),
- str(doc), headers=self.headers)
- body = xml_to_json(etree.fromstring(body))
- return resp, body
-
- def get_server_metadata_item(self, server_id, key):
- resp, body = self.get("servers/%s/metadata/%s" % (str(server_id), key),
- headers=self.headers)
- return resp, dict([(etree.fromstring(body).attrib['key'],
- xml_to_json(etree.fromstring(body)))])
-
- def set_server_metadata_item(self, server_id, key, meta):
- doc = Document()
- for k, v in meta.items():
- meta_element = Element("metadata", key=k)
- meta_element.append(Text(v))
- doc.append(meta_element)
- resp, body = self.put('servers/%s/metadata/%s' % (str(server_id), key),
- str(doc), self.headers)
- return resp, xml_to_json(etree.fromstring(body))
-
- def delete_server_metadata_item(self, server_id, key):
- resp, body = self.delete("servers/%s/metadata/%s" %
- (str(server_id), key))
- return resp, body
-
- def get_console_output(self, server_id, length):
- return self.action(server_id, 'get_console_output', 'output',
- length=length)
-
- def rescue_server(self, server_id, **kwargs):
- """Rescue the provided server."""
- return self.action(server_id, 'rescue', None, **kwargs)
-
- def unrescue_server(self, server_id):
- """Unrescue the provided server."""
- return self.action(server_id, 'unrescue', None)
-
- def attach_volume(self, server_id, volume_id, device='/dev/vdz'):
- return self.action(server_id, "attach", None, volume_id=volume_id,
- device=device)
-
- def detach_volume(self, server_id, volume_id):
- return self.action(server_id, "detach", None, volume_id=volume_id)
-
- def get_server_diagnostics(self, server_id):
- """Get the usage data for a server."""
- resp, body = self.get("servers/%s/os-server-diagnostics" % server_id,
- self.headers)
- body = xml_to_json(etree.fromstring(body))
- return resp, body
-
- def list_instance_actions(self, server_id):
- """List the provided server action."""
- resp, body = self.get("servers/%s/os-instance-actions" % server_id,
- self.headers)
- body = self._parse_array(etree.fromstring(body))
- return resp, body
-
- def get_instance_action(self, server_id, request_id):
- """Returns the action details of the provided server."""
- resp, body = self.get("servers/%s/os-instance-actions/%s" %
- (server_id, request_id), self.headers)
- body = xml_to_json(etree.fromstring(body))
- return resp, body
-
- def force_delete_server(self, server_id, **kwargs):
- """Force delete a server."""
- return self.action(server_id, 'force_delete', None, **kwargs)
-
- def restore_soft_deleted_server(self, server_id, **kwargs):
- """Restore a soft-deleted server."""
- return self.action(server_id, 'restore', None, **kwargs)
diff --git a/tempest/services/compute/v3/xml/services_client.py b/tempest/services/compute/v3/xml/services_client.py
deleted file mode 100644
index 749a812..0000000
--- a/tempest/services/compute/v3/xml/services_client.py
+++ /dev/null
@@ -1,71 +0,0 @@
-# Copyright 2013 NEC Corporation
-# Copyright 2013 IBM Corp.
-# 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 urllib
-
-from lxml import etree
-from tempest.common.rest_client import RestClientXML
-from tempest.services.compute.xml.common import Document
-from tempest.services.compute.xml.common import Element
-from tempest.services.compute.xml.common import xml_to_json
-
-
-class ServicesV3ClientXML(RestClientXML):
-
- def __init__(self, config, username, password, auth_url, tenant_name=None):
- super(ServicesV3ClientXML, self).__init__(config, username, password,
- auth_url, tenant_name)
- self.service = self.config.compute.catalog_v3_type
-
- def list_services(self, params=None):
- url = 'os-services'
- if params:
- url += '?%s' % urllib.urlencode(params)
-
- resp, body = self.get(url, self.headers)
- node = etree.fromstring(body)
- body = [xml_to_json(x) for x in node.getchildren()]
- return resp, body
-
- def enable_service(self, host_name, binary):
- """
- Enable service on a host
- host_name: Name of host
- binary: Service binary
- """
- post_body = Element("service")
- post_body.add_attr('binary', binary)
- post_body.add_attr('host', host_name)
-
- resp, body = self.put('os-services/enable', str(Document(post_body)),
- self.headers)
- body = xml_to_json(etree.fromstring(body))
- return resp, body
-
- def disable_service(self, host_name, binary):
- """
- Disable service on a host
- host_name: Name of host
- binary: Service binary
- """
- post_body = Element("service")
- post_body.add_attr('binary', binary)
- post_body.add_attr('host', host_name)
-
- resp, body = self.put('os-services/disable', str(Document(post_body)),
- self.headers)
- body = xml_to_json(etree.fromstring(body))
- return resp, body
diff --git a/tempest/services/compute/v3/xml/tenant_usages_client.py b/tempest/services/compute/v3/xml/tenant_usages_client.py
deleted file mode 100644
index 12b7655..0000000
--- a/tempest/services/compute/v3/xml/tenant_usages_client.py
+++ /dev/null
@@ -1,52 +0,0 @@
-# Copyright 2013 NEC Corporation
-# 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 urllib
-
-from lxml import etree
-
-from tempest.common.rest_client import RestClientXML
-from tempest.services.compute.xml.common import xml_to_json
-
-
-class TenantUsagesV3ClientXML(RestClientXML):
-
- def __init__(self, config, username, password, auth_url, tenant_name=None):
- super(TenantUsagesV3ClientXML, self).__init__(config, username,
- password, auth_url,
- tenant_name)
- self.service = self.config.compute.catalog_v3_type
-
- def _parse_array(self, node):
- json = xml_to_json(node)
- return json
-
- def list_tenant_usages(self, params=None):
- url = 'os-simple-tenant-usage'
- if params:
- url += '?%s' % urllib.urlencode(params)
-
- resp, body = self.get(url, self.headers)
- tenant_usage = self._parse_array(etree.fromstring(body))
- return resp, tenant_usage['tenant_usage']
-
- def get_tenant_usage(self, tenant_id, params=None):
- url = 'os-simple-tenant-usage/%s' % tenant_id
- if params:
- url += '?%s' % urllib.urlencode(params)
-
- resp, body = self.get(url, self.headers)
- tenant_usage = self._parse_array(etree.fromstring(body))
- return resp, tenant_usage
diff --git a/tempest/services/compute/v3/xml/version_client.py b/tempest/services/compute/v3/xml/version_client.py
deleted file mode 100644
index 7ecb31f..0000000
--- a/tempest/services/compute/v3/xml/version_client.py
+++ /dev/null
@@ -1,37 +0,0 @@
-# Copyright 2014 NEC Corporation
-# 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 lxml import etree
-
-from tempest.common import rest_client
-from tempest.services.compute.xml import common
-
-
-class VersionV3ClientXML(rest_client.RestClientXML):
-
- def __init__(self, config, username, password, auth_url, tenant_name=None):
- super(VersionV3ClientXML, self).__init__(config, username,
- password, auth_url,
- tenant_name)
- self.service = self.config.compute.catalog_v3_type
-
- def _parse_array(self, node):
- json = common.xml_to_json(node)
- return json
-
- def get_version(self):
- resp, body = self.get('', self.headers)
- body = self._parse_array(etree.fromstring(body))
- return resp, body