Adds Cinder client

This change adds Cinder client in services/volume

* Keeps existing tests for Compute Extensions in tempest/tests/compute
* Copies existing volumes test to tests/volume and refactors them to test the
Cinder API, and adds a BaseVolumesTest class
* Renames the Nova Extensions' volumes_client to volumes_extensions_client
* Adds build_interval and build_timeout parameters in config for Cinder
specific tests
* Renames build_interval and build_timeout environment variables in the
Devstack template file to COMPUTE_BUILD_INTERVAL and COMPUTE_BUILD_TIMEOUT
* Adds volume specific environment variables VOLUME_BUILD_INTERVAL AND
VOLUME_BUILD_TIMEOUT to the Devstack template file.

Fixes LP Bug #1026190

Change-Id: I14d980ada1ddb29e8147f990aaf239fdcaae5eb6
diff --git a/tempest/tests/volume/test_volumes_negative.py b/tempest/tests/volume/test_volumes_negative.py
new file mode 100644
index 0000000..63b209e
--- /dev/null
+++ b/tempest/tests/volume/test_volumes_negative.py
@@ -0,0 +1,133 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 OpenStack, LLC
+# 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 nose.plugins.attrib import attr
+from nose.tools import raises
+
+from tempest import exceptions
+from tempest.common.utils.data_utils import rand_name
+from tempest.tests.volume.base import BaseVolumeTest
+
+
+class VolumesNegativeTest(BaseVolumeTest):
+
+    @classmethod
+    def setUpClass(cls):
+        super(VolumesNegativeTest, cls).setUpClass()
+        cls.client = cls.volumes_client
+
+    @raises(exceptions.NotFound)
+    @attr(type='negative')
+    def test_volume_get_nonexistant_volume_id(self):
+        """Should not be able to get a nonexistant volume"""
+        #Creating a nonexistant volume id
+        volume_id_list = []
+        resp, volumes = self.client.list_volumes()
+        for i in range(len(volumes)):
+            volume_id_list.append(volumes[i]['id'])
+        while True:
+            non_exist_id = rand_name('999')
+            if non_exist_id not in volume_id_list:
+                break
+        #Trying to Get a non existant volume
+        resp, volume = self.client.get_volume(non_exist_id)
+
+    @raises(exceptions.NotFound)
+    @attr(type='negative')
+    def test_volume_delete_nonexistant_volume_id(self):
+        """Should not be able to delete a nonexistant Volume"""
+        # Creating nonexistant volume id
+        volume_id_list = []
+        resp, volumes = self.client.list_volumes()
+        for i in range(len(volumes)):
+            volume_id_list.append(volumes[i]['id'])
+        while True:
+            non_exist_id = '12345678-abcd-4321-abcd-123456789098'
+            if non_exist_id not in volume_id_list:
+                break
+        # Try to Delete a non existant volume
+        resp, body = self.client.delete_volume(non_exist_id)
+
+    @raises(exceptions.BadRequest)
+    @attr(type='negative')
+    def test_create_volume_with_invalid_size(self):
+        """
+        Should not be able to create volume with invalid size
+        in request
+        """
+        v_name = rand_name('Volume-')
+        metadata = {'Type': 'work'}
+        resp, volume = self.client.create_volume(size='#$%',
+                                                 display_name=v_name,
+                                                 metadata=metadata)
+
+    @raises(exceptions.BadRequest)
+    @attr(type='negative')
+    def test_create_volume_with_out_passing_size(self):
+        """
+        Should not be able to create volume without passing size
+        in request
+        """
+        v_name = rand_name('Volume-')
+        metadata = {'Type': 'work'}
+        resp, volume = self.client.create_volume(size='',
+                                                 display_name=v_name,
+                                                 metadata=metadata)
+
+    @raises(exceptions.BadRequest)
+    @attr(type='negative')
+    def test_create_volume_with_size_zero(self):
+        """
+        Should not be able to create volume with size zero
+        """
+        v_name = rand_name('Volume-')
+        metadata = {'Type': 'work'}
+        resp, volume = self.client.create_volume(size='0',
+                                                 display_name=v_name,
+                                                 metadata=metadata)
+
+    @raises(exceptions.NotFound)
+    @attr(type='negative')
+    def test_get_invalid_volume_id(self):
+        """
+        Should not be able to get volume with invalid id
+        """
+        resp, volume = self.client.get_volume('#$%%&^&^')
+
+    @raises(exceptions.NotFound)
+    @attr(type='negative')
+    def test_get_volume_without_passing_volume_id(self):
+        """
+        Should not be able to get volume when empty ID is passed
+        """
+        resp, volume = self.client.get_volume('')
+
+    @raises(exceptions.NotFound)
+    @attr(type='negative')
+    def test_delete_invalid_volume_id(self):
+        """
+        Should not be able to delete volume when invalid ID is passed
+        """
+        resp, volume = self.client.delete_volume('!@#$%^&*()')
+
+    @raises(exceptions.NotFound)
+    @attr(type='negative')
+    def test_delete_volume_without_passing_volume_id(self):
+        """
+        Should not be able to delete volume when empty ID is passed
+        """
+        resp, volume = self.client.delete_volume('')