Skip to content

Commit

Permalink
Adds client API and tests for volume attachments
Browse files Browse the repository at this point in the history
Change-Id: Id903069ec49b38806fa37845d1aea589a835206b
  • Loading branch information
Rohit Karajgi committed Sep 24, 2012
1 parent c25ef68 commit a42fe44
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 1 deletion.
8 changes: 7 additions & 1 deletion tempest/common/rest_client.py
Expand Up @@ -132,7 +132,13 @@ def keystone_auth(self, user, password, auth_url, service, tenant_name):

mgmt_url = None
for ep in auth_data['serviceCatalog']:
if ep["type"] == service:
if ep["type"] == service and service != 'volume':
mgmt_url = ep['endpoints'][self.region][self.endpoint_url]
tenant_id = auth_data['token']['tenant']['id']
break

elif ep["type"] == service and ep['name'] == 'cinder' \
and service == 'volume':
mgmt_url = ep['endpoints'][self.region][self.endpoint_url]
tenant_id = auth_data['token']['tenant']['id']
break
Expand Down
19 changes: 19 additions & 0 deletions tempest/services/volume/json/volumes_client.py
Expand Up @@ -92,6 +92,25 @@ def delete_volume(self, volume_id):
"""Deletes the Specified Volume"""
return self.delete("volumes/%s" % str(volume_id))

def attach_volume(self, volume_id, instance_uuid, mountpoint):
"""Attaches a volume to a given instance on a given mountpoint"""
post_body = {
'instance_uuid': instance_uuid,
'mountpoint': mountpoint
}
post_body = json.dumps({'os-attach': post_body})
url = 'volumes/%s/action' % (volume_id)
resp, body = self.post(url, post_body, self.headers)
return resp, body

def detach_volume(self, volume_id):
"""Detaches a volume from an instance"""
post_body = {}
post_body = json.dumps({'os-detach': post_body})
url = 'volumes/%s/action' % (volume_id)
resp, body = self.post(url, post_body, self.headers)
return resp, body

def wait_for_volume_status(self, volume_id, status):
"""Waits for a Volume to reach a given status"""
resp, body = self.get_volume(volume_id)
Expand Down
4 changes: 4 additions & 0 deletions tempest/tests/volume/base.py
Expand Up @@ -50,6 +50,9 @@ def setUpClass(cls):

cls.os = os
cls.volumes_client = os.volumes_client
cls.servers_client = os.servers_client
cls.image_ref = cls.config.compute.image_ref
cls.flavor_ref = cls.config.compute.flavor_ref
cls.build_interval = cls.config.volume.build_interval
cls.build_timeout = cls.config.volume.build_timeout
cls.volumes = {}
Expand All @@ -63,6 +66,7 @@ def setUpClass(cls):
cls.volumes_client.service,
cls.os.tenant_name)
except exceptions.EndpointNotFound:
cls.clear_isolated_creds()
raise nose.SkipTest(skip_msg)

@classmethod
Expand Down
90 changes: 90 additions & 0 deletions tempest/tests/volume/test_volumes_actions.py
@@ -0,0 +1,90 @@
# 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 tempest.common.utils.data_utils import rand_name
from tempest.tests.volume.base import BaseVolumeTest


class VolumesActionsTest(BaseVolumeTest):

@classmethod
def setUpClass(cls):
super(VolumesActionsTest, cls).setUpClass()
cls.client = cls.volumes_client
cls.servers_client = cls.servers_client

# Create a test shared instance and volume for attach/detach tests
srv_name = rand_name('Instance-')
vol_name = rand_name('Volume-')
resp, cls.server = cls.servers_client.create_server(srv_name,
cls.image_ref,
cls.flavor_ref)
cls.servers_client.wait_for_server_status(cls.server['id'], 'ACTIVE')

resp, cls.volume = cls.client.create_volume(size=1,
display_name=vol_name)
cls.client.wait_for_volume_status(cls.volume['id'], 'available')

@classmethod
def tearDownClass(cls):
super(VolumesActionsTest, cls).tearDownClass()
# Delete the test instance and volume
cls.client.delete_volume(cls.volume['id'])
cls.servers_client.delete_server(cls.server['id'])

@attr(type='smoke')
def test_attach_detach_volume_to_instance(self):
"""Volume is attached and detached successfully from an instance"""
try:
mountpoint = '/dev/vdc'
resp, body = self.client.attach_volume(self.volume['id'],
self.server['id'],
mountpoint)
self.assertEqual(202, resp.status)
self.client.wait_for_volume_status(self.volume['id'], 'in-use')
except:
self.fail("Could not attach volume to instance")
finally:
# Detach the volume from the instance
resp, body = self.client.detach_volume(self.volume['id'])
self.assertEqual(202, resp.status)
self.client.wait_for_volume_status(self.volume['id'], 'available')

def test_get_volume_attachment(self):
"""Verify that a volume's attachment information is retrieved"""
mountpoint = '/dev/vdc'
resp, body = self.client.attach_volume(self.volume['id'],
self.server['id'],
mountpoint)
self.client.wait_for_volume_status(self.volume['id'], 'in-use')
self.assertEqual(202, resp.status)
try:
resp, volume = self.client.get_volume(self.volume['id'])
self.assertEqual(200, resp.status)
self.assertTrue('attachments' in volume)
attachment = volume['attachments'][0]
self.assertEqual(mountpoint, attachment['device'])
self.assertEqual(self.server['id'], attachment['server_id'])
self.assertEqual(self.volume['id'], attachment['id'])
self.assertEqual(self.volume['id'], attachment['volume_id'])
except:
self.fail("Could not get attachment details from volume")
finally:
self.client.detach_volume(self.volume['id'])
self.client.wait_for_volume_status(self.volume['id'], 'available')

0 comments on commit a42fe44

Please sign in to comment.