Merge "port test_hypervisor into nova v3 part1"
diff --git a/tempest/api/compute/v3/admin/test_hypervisor.py b/tempest/api/compute/v3/admin/test_hypervisor.py
new file mode 100644
index 0000000..ef4f51f
--- /dev/null
+++ b/tempest/api/compute/v3/admin/test_hypervisor.py
@@ -0,0 +1,105 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# 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 tempest.api.compute import base
+from tempest.test import attr
+
+
+class HypervisorAdminTestJSON(base.BaseV2ComputeAdminTest):
+
+    """
+    Tests Hypervisors API that require admin privileges
+    """
+
+    _interface = 'json'
+
+    @classmethod
+    def setUpClass(cls):
+        super(HypervisorAdminTestJSON, cls).setUpClass()
+        cls.client = cls.os_adm.hypervisor_client
+
+    def _list_hypervisors(self):
+        # List of hypervisors
+        resp, hypers = self.client.get_hypervisor_list()
+        self.assertEqual(200, resp.status)
+        return hypers
+
+    @attr(type='gate')
+    def test_get_hypervisor_list(self):
+        # List of hypervisor and available hypervisors hostname
+        hypers = self._list_hypervisors()
+        self.assertTrue(len(hypers) > 0)
+
+    @attr(type='gate')
+    def test_get_hypervisor_list_details(self):
+        # Display the details of the all hypervisor
+        resp, hypers = self.client.get_hypervisor_list_details()
+        self.assertEqual(200, resp.status)
+        self.assertTrue(len(hypers) > 0)
+
+    @attr(type='gate')
+    def test_get_hypervisor_show_details(self):
+        # Display the details of the specified hypervisor
+        hypers = self._list_hypervisors()
+        self.assertTrue(len(hypers) > 0)
+
+        resp, details = (self.client.
+                         get_hypervisor_show_details(hypers[0]['id']))
+        self.assertEqual(200, resp.status)
+        self.assertTrue(len(details) > 0)
+        self.assertEqual(details['hypervisor_hostname'],
+                         hypers[0]['hypervisor_hostname'])
+
+    @attr(type='gate')
+    def test_get_hypervisor_show_servers(self):
+        # Show instances about the specific hypervisors
+        hypers = self._list_hypervisors()
+        self.assertTrue(len(hypers) > 0)
+
+        hostname = hypers[0]['hypervisor_hostname']
+        resp, hypervisors = self.client.get_hypervisor_servers(hostname)
+        self.assertEqual(200, resp.status)
+        self.assertTrue(len(hypervisors) > 0)
+
+    @attr(type='gate')
+    def test_get_hypervisor_stats(self):
+        # Verify the stats of the all hypervisor
+        resp, stats = self.client.get_hypervisor_stats()
+        self.assertEqual(200, resp.status)
+        self.assertTrue(len(stats) > 0)
+
+    @attr(type='gate')
+    def test_get_hypervisor_uptime(self):
+        # Verify that GET shows the specified hypervisor uptime
+        hypers = self._list_hypervisors()
+
+        resp, uptime = self.client.get_hypervisor_uptime(hypers[0]['id'])
+        self.assertEqual(200, resp.status)
+        self.assertTrue(len(uptime) > 0)
+
+    @attr(type='gate')
+    def test_search_hypervisor(self):
+        hypers = self._list_hypervisors()
+        self.assertTrue(len(hypers) > 0)
+        resp, hypers = self.client.search_hypervisor(
+            hypers[0]['hypervisor_hostname'])
+        self.assertEqual(200, resp.status)
+        self.assertTrue(len(hypers) > 0)
+
+
+class HypervisorAdminTestXML(HypervisorAdminTestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/compute/v3/admin/test_hypervisor_negative.py b/tempest/api/compute/v3/admin/test_hypervisor_negative.py
new file mode 100644
index 0000000..c6455b5
--- /dev/null
+++ b/tempest/api/compute/v3/admin/test_hypervisor_negative.py
@@ -0,0 +1,144 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 Huawei Technologies Co.,LTD.
+# 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 uuid
+
+from tempest.api.compute import base
+from tempest.common.utils import data_utils
+from tempest import exceptions
+from tempest.test import attr
+
+
+class HypervisorAdminNegativeTestJSON(base.BaseV2ComputeAdminTest):
+
+    """
+    Tests Hypervisors API that require admin privileges
+    """
+
+    _interface = 'json'
+
+    @classmethod
+    def setUpClass(cls):
+        super(HypervisorAdminNegativeTestJSON, cls).setUpClass()
+        cls.client = cls.os_adm.hypervisor_client
+        cls.non_adm_client = cls.hypervisor_client
+
+    def _list_hypervisors(self):
+        # List of hypervisors
+        resp, hypers = self.client.get_hypervisor_list()
+        self.assertEqual(200, resp.status)
+        return hypers
+
+    @attr(type=['negative', 'gate'])
+    def test_show_nonexistent_hypervisor(self):
+        nonexistent_hypervisor_id = str(uuid.uuid4())
+
+        self.assertRaises(
+            exceptions.NotFound,
+            self.client.get_hypervisor_show_details,
+            nonexistent_hypervisor_id)
+
+    @attr(type=['negative', 'gate'])
+    def test_show_hypervisor_with_non_admin_user(self):
+        hypers = self._list_hypervisors()
+        self.assertTrue(len(hypers) > 0)
+
+        self.assertRaises(
+            exceptions.Unauthorized,
+            self.non_adm_client.get_hypervisor_show_details,
+            hypers[0]['id'])
+
+    @attr(type=['negative', 'gate'])
+    def test_show_servers_with_non_admin_user(self):
+        hypers = self._list_hypervisors()
+        self.assertTrue(len(hypers) > 0)
+
+        self.assertRaises(
+            exceptions.Unauthorized,
+            self.non_adm_client.get_hypervisor_servers,
+            hypers[0]['id'])
+
+    @attr(type=['negative', 'gate'])
+    def test_show_servers_with_nonexistent_hypervisor(self):
+        nonexistent_hypervisor_id = str(uuid.uuid4())
+
+        self.assertRaises(
+            exceptions.NotFound,
+            self.client.get_hypervisor_servers,
+            nonexistent_hypervisor_id)
+
+    @attr(type=['negative', 'gate'])
+    def test_get_hypervisor_stats_with_non_admin_user(self):
+        self.assertRaises(
+            exceptions.Unauthorized,
+            self.non_adm_client.get_hypervisor_stats)
+
+    @attr(type=['negative', 'gate'])
+    def test_get_nonexistent_hypervisor_uptime(self):
+        nonexistent_hypervisor_id = str(uuid.uuid4())
+
+        self.assertRaises(
+            exceptions.NotFound,
+            self.client.get_hypervisor_uptime,
+            nonexistent_hypervisor_id)
+
+    @attr(type=['negative', 'gate'])
+    def test_get_hypervisor_uptime_with_non_admin_user(self):
+        hypers = self._list_hypervisors()
+        self.assertTrue(len(hypers) > 0)
+
+        self.assertRaises(
+            exceptions.Unauthorized,
+            self.non_adm_client.get_hypervisor_uptime,
+            hypers[0]['id'])
+
+    @attr(type=['negative', 'gate'])
+    def test_get_hypervisor_list_with_non_admin_user(self):
+        # List of hypervisor and available services with non admin user
+        self.assertRaises(
+            exceptions.Unauthorized,
+            self.non_adm_client.get_hypervisor_list)
+
+    @attr(type=['negative', 'gate'])
+    def test_get_hypervisor_list_details_with_non_admin_user(self):
+        # List of hypervisor details and available services with non admin user
+        self.assertRaises(
+            exceptions.Unauthorized,
+            self.non_adm_client.get_hypervisor_list_details)
+
+    @attr(type=['negative', 'gate'])
+    def test_search_nonexistent_hypervisor(self):
+        nonexistent_hypervisor_name = data_utils.rand_name('test_hypervisor')
+
+        self.assertRaises(
+            exceptions.NotFound,
+            self.client.search_hypervisor,
+            nonexistent_hypervisor_name)
+
+    @attr(type=['negative', 'gate'])
+    def test_search_hypervisor_with_non_admin_user(self):
+        hypers = self._list_hypervisors()
+        self.assertTrue(len(hypers) > 0)
+
+        self.assertRaises(
+            exceptions.Unauthorized,
+            self.non_adm_client.search_hypervisor,
+            hypers[0]['hypervisor_hostname'])
+
+
+class HypervisorAdminNegativeTestXML(HypervisorAdminNegativeTestJSON):
+    _interface = 'xml'
diff --git a/tempest/services/compute/v3/json/hypervisor_client.py b/tempest/services/compute/v3/json/hypervisor_client.py
new file mode 100644
index 0000000..fba5acb
--- /dev/null
+++ b/tempest/services/compute/v3/json/hypervisor_client.py
@@ -0,0 +1,71 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# 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.
+
+import json
+
+from tempest.common.rest_client import RestClient
+
+
+class HypervisorClientJSON(RestClient):
+
+    def __init__(self, config, username, password, auth_url, tenant_name=None):
+        super(HypervisorClientJSON, self).__init__(config, username,
+                                                   password, auth_url,
+                                                   tenant_name)
+        self.service = self.config.compute.catalog_type
+
+    def get_hypervisor_list(self):
+        """List hypervisors information."""
+        resp, body = self.get('os-hypervisors')
+        body = json.loads(body)
+        return resp, body['hypervisors']
+
+    def get_hypervisor_list_details(self):
+        """Show detailed hypervisors information."""
+        resp, body = self.get('os-hypervisors/detail')
+        body = json.loads(body)
+        return resp, body['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)
+        body = json.loads(body)
+        return resp, body['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)
+        body = json.loads(body)
+        return resp, body['hypervisors']
+
+    def get_hypervisor_stats(self):
+        """Get hypervisor statistics over all compute nodes."""
+        resp, body = self.get('os-hypervisors/statistics')
+        body = json.loads(body)
+        return resp, body['hypervisor_statistics']
+
+    def get_hypervisor_uptime(self, hyper_id):
+        """Display the uptime of the specified hypervisor."""
+        resp, body = self.get('os-hypervisors/%s/uptime' % hyper_id)
+        body = json.loads(body)
+        return resp, body['hypervisor']
+
+    def search_hypervisor(self, hyper_name):
+        """Search specified hypervisor."""
+        resp, body = self.get('os-hypervisors/%s/search' % hyper_name)
+        body = json.loads(body)
+        return resp, body['hypervisors']
diff --git a/tempest/services/compute/v3/xml/hypervisor_client.py b/tempest/services/compute/v3/xml/hypervisor_client.py
new file mode 100644
index 0000000..c10fed9
--- /dev/null
+++ b/tempest/services/compute/v3/xml/hypervisor_client.py
@@ -0,0 +1,79 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# 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 HypervisorClientXML(RestClientXML):
+
+    def __init__(self, config, username, password, auth_url, tenant_name=None):
+        super(HypervisorClientXML, self).__init__(config, username,
+                                                  password, auth_url,
+                                                  tenant_name)
+        self.service = self.config.compute.catalog_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/%s/search' % hyper_name,
+                              self.headers)
+        hypervisors = self._parse_array(etree.fromstring(body))
+        return resp, hypervisors