Enable HostsAdminTestXML

Although there is hosts_client class for XML, HostsAdminTestXML is
disabled. This patch enables HostsAdminTestXML.

Change-Id: Ib136661107a94f3e2c1607dad644dce0a3b42502
Closes-Bug: #1261968
diff --git a/tempest/api/compute/admin/test_hosts_negative.py b/tempest/api/compute/admin/test_hosts_negative.py
index 6b24e72..dbf7967 100644
--- a/tempest/api/compute/admin/test_hosts_negative.py
+++ b/tempest/api/compute/admin/test_hosts_negative.py
@@ -17,7 +17,7 @@
 from tempest.api.compute import base
 from tempest.common.utils import data_utils
 from tempest import exceptions
-from tempest.test import attr
+from tempest import test
 
 
 class HostsAdminNegativeTestJSON(base.BaseV2ComputeAdminTest):
@@ -41,18 +41,18 @@
         hostname = hosts[0]['host_name']
         return hostname
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_list_hosts_with_non_admin_user(self):
         self.assertRaises(exceptions.Unauthorized,
                           self.non_admin_client.list_hosts)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_show_host_detail_with_nonexistent_hostname(self):
         nonexitent_hostname = data_utils.rand_name('rand_hostname')
         self.assertRaises(exceptions.NotFound,
                           self.client.show_host_detail, nonexitent_hostname)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_show_host_detail_with_non_admin_user(self):
         hostname = self._get_host_name()
 
@@ -60,7 +60,7 @@
                           self.non_admin_client.show_host_detail,
                           hostname)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_update_host_with_non_admin_user(self):
         hostname = self._get_host_name()
 
@@ -68,7 +68,8 @@
                           self.non_admin_client.update_host,
                           hostname)
 
-    @attr(type=['negative', 'gate'])
+    @test.skip_because(bug="1261964", interface="xml")
+    @test.attr(type=['negative', 'gate'])
     def test_update_host_with_extra_param(self):
         # only 'status' and 'maintenance_mode' are the valid params.
         hostname = self._get_host_name()
@@ -80,7 +81,7 @@
                           maintenance_mode='enable',
                           param='XXX')
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_update_host_with_invalid_status(self):
         # 'status' can only be 'enable' or 'disable'
         hostname = self._get_host_name()
@@ -91,7 +92,7 @@
                           status='invalid',
                           maintenance_mode='enable')
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_update_host_with_invalid_maintenance_mode(self):
         # 'maintenance_mode' can only be 'enable' or 'disable'
         hostname = self._get_host_name()
@@ -102,7 +103,7 @@
                           status='enable',
                           maintenance_mode='invalid')
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_update_host_without_param(self):
         # 'status' or 'maintenance_mode' needed for host update
         hostname = self._get_host_name()
@@ -111,7 +112,7 @@
                           self.client.update_host,
                           hostname)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_update_nonexistent_host(self):
         nonexitent_hostname = data_utils.rand_name('rand_hostname')
 
@@ -121,7 +122,7 @@
                           status='enable',
                           maintenance_mode='enable')
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_startup_nonexistent_host(self):
         nonexitent_hostname = data_utils.rand_name('rand_hostname')
 
@@ -129,7 +130,7 @@
                           self.client.startup_host,
                           nonexitent_hostname)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_startup_host_with_non_admin_user(self):
         hostname = self._get_host_name()
 
@@ -137,7 +138,7 @@
                           self.non_admin_client.startup_host,
                           hostname)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_shutdown_nonexistent_host(self):
         nonexitent_hostname = data_utils.rand_name('rand_hostname')
 
@@ -145,7 +146,7 @@
                           self.client.shutdown_host,
                           nonexitent_hostname)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_shutdown_host_with_non_admin_user(self):
         hostname = self._get_host_name()
 
@@ -153,7 +154,7 @@
                           self.non_admin_client.shutdown_host,
                           hostname)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_reboot_nonexistent_host(self):
         nonexitent_hostname = data_utils.rand_name('rand_hostname')
 
@@ -161,7 +162,7 @@
                           self.client.reboot_host,
                           nonexitent_hostname)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_reboot_host_with_non_admin_user(self):
         hostname = self._get_host_name()
 
diff --git a/tempest/clients.py b/tempest/clients.py
index ac79ce0..fe5ed74 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -87,6 +87,7 @@
 from tempest.services.compute.xml.flavors_client import FlavorsClientXML
 from tempest.services.compute.xml.floating_ips_client import \
     FloatingIPsClientXML
+from tempest.services.compute.xml.hosts_client import HostsClientXML
 from tempest.services.compute.xml.hypervisor_client import HypervisorClientXML
 from tempest.services.compute.xml.images_client import ImagesClientXML
 from tempest.services.compute.xml.instance_usage_audit_log_client import \
@@ -242,6 +243,7 @@
                 *client_args)
             self.tenant_usages_client = TenantUsagesClientXML(*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)
@@ -293,6 +295,7 @@
                 *client_args)
             self.tenant_usages_client = TenantUsagesClientJSON(*client_args)
             self.policy_client = PolicyClientJSON(*client_args)
+            self.hosts_client = HostsClientJSON(*client_args)
             self.hypervisor_v3_client = HypervisorV3ClientJSON(*client_args)
             self.hypervisor_client = HypervisorClientJSON(*client_args)
             self.token_v3_client = V3TokenClientJSON(*client_args)
@@ -310,7 +313,6 @@
             raise exceptions.InvalidConfiguration(msg)
 
         # common clients
-        self.hosts_client = HostsClientJSON(*client_args)
         self.account_client = AccountClient(*client_args)
         if self.config.service_available.glance:
             self.image_client = ImageClientJSON(*client_args)
diff --git a/tempest/services/compute/xml/hosts_client.py b/tempest/services/compute/xml/hosts_client.py
index f7d7b0a..519798e 100644
--- a/tempest/services/compute/xml/hosts_client.py
+++ b/tempest/services/compute/xml/hosts_client.py
@@ -47,18 +47,16 @@
 
         resp, body = self.get("os-hosts/%s" % str(hostname), self.headers)
         node = etree.fromstring(body)
-        body = [xml_to_json(x) for x in node.getchildren()]
+        body = [xml_to_json(node)]
         return resp, body
 
-    def update_host(self, hostname, status=None, maintenance_mode=None,
-                    **kwargs):
+    def update_host(self, hostname, **kwargs):
         """Update a host."""
 
-        request_body = Element(status=status,
-                               maintenance_mode=maintenance_mode)
+        request_body = Element("updates")
         if kwargs:
-            for k, v in kwargs.iteritem():
-                request_body.add_attr(k, v)
+            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)
diff --git a/tempest/test.py b/tempest/test.py
index ceb2c80..b48832f 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -110,15 +110,24 @@
 
     @param bug: bug number causing the test to skip
     @param condition: optional condition to be True for the skip to have place
+    @param interface: skip the test if it is the same as self._interface
     """
     def decorator(f):
         @functools.wraps(f)
-        def wrapper(*func_args, **func_kwargs):
-            if "bug" in kwargs:
-                if "condition" not in kwargs or kwargs["condition"] is True:
-                    msg = "Skipped until Bug: %s is resolved." % kwargs["bug"]
-                    raise testtools.TestCase.skipException(msg)
-            return f(*func_args, **func_kwargs)
+        def wrapper(self, *func_args, **func_kwargs):
+            skip = False
+            if "condition" in kwargs:
+                if kwargs["condition"] is True:
+                    skip = True
+            elif "interface" in kwargs:
+                if kwargs["interface"] == self._interface:
+                    skip = True
+            else:
+                skip = True
+            if "bug" in kwargs and skip is True:
+                msg = "Skipped until Bug: %s is resolved." % kwargs["bug"]
+                raise testtools.TestCase.skipException(msg)
+            return f(self, *func_args, **func_kwargs)
         return wrapper
     return decorator