Merge "Remove unnecessary setUp()"
diff --git a/releasenotes/notes/image-clients-as-library-86d17caa26ce3961.yaml b/releasenotes/notes/image-clients-as-library-86d17caa26ce3961.yaml
index b50ed38..faae7d0 100644
--- a/releasenotes/notes/image-clients-as-library-86d17caa26ce3961.yaml
+++ b/releasenotes/notes/image-clients-as-library-86d17caa26ce3961.yaml
@@ -6,7 +6,8 @@
     so the other projects can use these modules as stable libraries
     without any maintenance changes.
 
-      * image_members_client
-      * namespaces_client
-      * resource_types_client
-      * schemas_client
+      * image_members_client(v2)
+      * images_client(v2)
+      * namespaces_client(v2)
+      * resource_types_client(v2)
+      * schemas_client(v2)
diff --git a/tempest/api/compute/admin/test_aggregates.py b/tempest/api/compute/admin/test_aggregates.py
index dabc45e..84b00a7 100644
--- a/tempest/api/compute/admin/test_aggregates.py
+++ b/tempest/api/compute/admin/test_aggregates.py
@@ -39,12 +39,13 @@
         cls.az_name_prefix = 'test_az'
 
         cls.host = None
-        hypers = cls.os_adm.hypervisor_client.list_hypervisors()['hypervisors']
-        hypers_available = [hyper['hypervisor_hostname'] for hyper in hypers
-                            if (hyper['state'] == 'up' and
-                                hyper['status'] == 'enabled')]
-        if hypers_available:
-            cls.host = hypers_available[0]
+        hypers = cls.os_adm.hypervisor_client.list_hypervisors(
+            detail=True)['hypervisors']
+        hosts_available = [hyper['service']['host'] for hyper in hypers
+                           if (hyper['state'] == 'up' and
+                               hyper['status'] == 'enabled')]
+        if hosts_available:
+            cls.host = hosts_available[0]
         else:
             raise testtools.TestCase.failureException(
                 "no available compute node found")
diff --git a/tempest/clients.py b/tempest/clients.py
index 7ec5c7e..31883fd 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -77,6 +77,8 @@
 from tempest.lib.services.identity.v3.token_client import V3TokenClient
 from tempest.lib.services.image.v2.image_members_client import \
     ImageMembersClient as ImageMembersClientV2
+from tempest.lib.services.image.v2.images_client import \
+    ImagesClient as ImagesV2Client
 from tempest.lib.services.image.v2.namespaces_client import NamespacesClient
 from tempest.lib.services.image.v2.resource_types_client import \
     ResourceTypesClient
@@ -140,8 +142,6 @@
 from tempest.services.image.v1.json.image_members_client import \
     ImageMembersClient
 from tempest.services.image.v1.json.images_client import ImagesClient
-from tempest.services.image.v2.json.images_client import \
-    ImagesClient as ImagesV2Client
 from tempest.services.object_storage.account_client import AccountClient
 from tempest.services.object_storage.container_client import ContainerClient
 from tempest.services.object_storage.object_client import ObjectClient
diff --git a/tempest/cmd/account_generator.py b/tempest/cmd/account_generator.py
index 0a5a41b..db323de 100755
--- a/tempest/cmd/account_generator.py
+++ b/tempest/cmd/account_generator.py
@@ -234,7 +234,7 @@
     parser.add_argument('-r', '--concurrency',
                         default=1,
                         type=int,
-                        required=True,
+                        required=False,
                         dest='concurrency',
                         help='Concurrency count')
     parser.add_argument('--with-admin',
diff --git a/tempest/cmd/javelin.py b/tempest/cmd/javelin.py
index 6a65fcb..1f433eb 100755
--- a/tempest/cmd/javelin.py
+++ b/tempest/cmd/javelin.py
@@ -126,6 +126,7 @@
 from tempest.lib.services.compute import security_group_rules_client
 from tempest.lib.services.compute import security_groups_client
 from tempest.lib.services.compute import servers_client
+from tempest.lib.services.image.v2 import images_client
 from tempest.lib.services.network import networks_client
 from tempest.lib.services.network import ports_client
 from tempest.lib.services.network import routers_client
@@ -134,7 +135,6 @@
 from tempest.services.identity.v2.json import roles_client
 from tempest.services.identity.v2.json import tenants_client
 from tempest.services.identity.v2.json import users_client
-from tempest.services.image.v2.json import images_client
 from tempest.services.object_storage import container_client
 from tempest.services.object_storage import object_client
 from tempest.services.volume.v1.json import volumes_client
diff --git a/tempest/lib/services/compute/servers_client.py b/tempest/lib/services/compute/servers_client.py
index 8e4eca1..0d31ac7 100644
--- a/tempest/lib/services/compute/servers_client.py
+++ b/tempest/lib/services/compute/servers_client.py
@@ -315,7 +315,11 @@
         return self.action(server_id, 'os-start', **kwargs)
 
     def attach_volume(self, server_id, **kwargs):
-        """Attaches a volume to a server instance."""
+        """Attaches a volume to a server instance.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-compute-v2.1.html#attachVolume
+        """
         post_body = json.dumps({'volumeAttachment': kwargs})
         resp, body = self.post('servers/%s/os-volume_attachments' % server_id,
                                post_body)
diff --git a/tempest/services/image/v2/json/images_client.py b/tempest/lib/services/image/v2/images_client.py
similarity index 100%
rename from tempest/services/image/v2/json/images_client.py
rename to tempest/lib/services/image/v2/images_client.py
diff --git a/tempest/services/image/v2/__init__.py b/tempest/services/image/v2/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tempest/services/image/v2/__init__.py
+++ /dev/null
diff --git a/tempest/services/image/v2/json/__init__.py b/tempest/services/image/v2/json/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tempest/services/image/v2/json/__init__.py
+++ /dev/null
diff --git a/tempest/tests/lib/services/image/v2/test_images_client.py b/tempest/tests/lib/services/image/v2/test_images_client.py
new file mode 100644
index 0000000..9648985
--- /dev/null
+++ b/tempest/tests/lib/services/image/v2/test_images_client.py
@@ -0,0 +1,111 @@
+# Copyright 2016 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 tempest.lib.services.image.v2 import images_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestImagesClient(base.BaseServiceTest):
+    FAKE_CREATE_UPDATE_SHOW_IMAGE = {
+        "id": "e485aab9-0907-4973-921c-bb6da8a8fcf8",
+        "name": u"\u2740(*\xb4\u25e2`*)\u2740",
+        "status": "active",
+        "visibility": "public",
+        "size": 2254249,
+        "checksum": "2cec138d7dae2aa59038ef8c9aec2390",
+        "tags": [
+            "fedora",
+            "beefy"
+        ],
+        "created_at": "2012-08-10T19:23:50Z",
+        "updated_at": "2012-08-12T11:11:33Z",
+        "self": "/v2/images/da3b75d9-3f4a-40e7-8a2c-bfab23927dea",
+        "file": "/v2/images/da3b75d9-3f4a-40e7-8a2c-bfab23927dea/file",
+        "schema": "/v2/schemas/image",
+        "owner": None,
+        "min_ram": None,
+        "min_disk": None,
+        "disk_format": None,
+        "virtual_size": None,
+        "container_format": None
+    }
+
+    def setUp(self):
+        super(TestImagesClient, self).setUp()
+        fake_auth = fake_auth_provider.FakeAuthProvider()
+        self.client = images_client.ImagesClient(fake_auth,
+                                                 'image', 'regionOne')
+
+    def _test_update_image(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.update_image,
+            'tempest.lib.common.rest_client.RestClient.patch',
+            self.FAKE_CREATE_UPDATE_SHOW_IMAGE,
+            bytes_body,
+            image_id="e485aab9-0907-4973-921c-bb6da8a8fcf8",
+            patch=[{"op": "add", "path": "/a/b/c", "value": ["foo", "bar"]}])
+
+    def _test_create_image(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.create_image,
+            'tempest.lib.common.rest_client.RestClient.post',
+            self.FAKE_CREATE_UPDATE_SHOW_IMAGE,
+            bytes_body,
+            name="virtual machine image",
+            status=201)
+
+    def _test_show_image(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.show_image,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_CREATE_UPDATE_SHOW_IMAGE,
+            bytes_body,
+            image_id="e485aab9-0907-4973-921c-bb6da8a8fcf8")
+
+    def test_create_image_with_str_body(self):
+        self._test_create_image()
+
+    def test_create_image_with_bytes_body(self):
+        self._test_create_image(bytes_body=True)
+
+    def test_update_image_with_str_body(self):
+        self._test_update_image()
+
+    def test_update_image_with_bytes_body(self):
+        self._test_update_image(bytes_body=True)
+
+    def test_deactivate_image(self):
+        self.check_service_client_function(
+            self.client.deactivate_image,
+            'tempest.lib.common.rest_client.RestClient.post',
+            {}, image_id="e485aab9-0907-4973-921c-bb6da8a8fcf8", status=204)
+
+    def test_reactivate_image(self):
+        self.check_service_client_function(
+            self.client.reactivate_image,
+            'tempest.lib.common.rest_client.RestClient.post',
+            {}, image_id="e485aab9-0907-4973-921c-bb6da8a8fcf8", status=204)
+
+    def test_delete_image(self):
+        self.check_service_client_function(
+            self.client.delete_image,
+            'tempest.lib.common.rest_client.RestClient.delete',
+            {}, image_id="e485aab9-0907-4973-921c-bb6da8a8fcf8", status=204)
+
+    def test_show_image_with_str_body(self):
+        self._test_show_image()
+
+    def test_show_image_with_bytes_body(self):
+        self._test_show_image(bytes_body=True)