def delete_volume(self, volume): volume_id = volume.volume_id cinder_api = cinder.CinderAPI(self.context) try: cinder_api.delete_volume(volume_id) except cinder_exception as e: raise exception.Invalid(_("Delete Volume failed: %s") % str(e))
def _build_requested_volumes(self, context, mounts): # NOTE(hongbin): We assume cinder is the only volume provider here. # The logic needs to be re-visited if a second volume provider # (i.e. Manila) is introduced. cinder_api = cinder.CinderAPI(context) requested_volumes = [] for mount in mounts: if mount.get('source'): volume = cinder_api.search_volume(mount['source']) auto_remove = False else: volume = cinder_api.create_volume(mount['size']) auto_remove = True cinder_api.ensure_volume_usable(volume) volmapp = objects.VolumeMapping( context, volume_id=volume.id, volume_provider='cinder', container_path=mount['destination'], user_id=context.user_id, project_id=context.project_id, auto_remove=auto_remove) requested_volumes.append(volmapp) return requested_volumes
def test_unreserve_volume(self, mock_cinderclient): mock_volumes = mock.MagicMock() mock_cinderclient.return_value = mock.MagicMock(volumes=mock_volumes) self.api = cinder_api.CinderAPI(self.context) self.api.unreserve_volume('id1') mock_cinderclient.assert_called_once_with() mock_volumes.unreserve.assert_called_once_with('id1')
def test_roll_detaching(self, mock_cinderclient): mock_volumes = mock.MagicMock() mock_cinderclient.return_value = mock.MagicMock(volumes=mock_volumes) self.api = cinder_api.CinderAPI(self.context) self.api.roll_detaching('id1') mock_cinderclient.assert_called_once_with() mock_volumes.roll_detaching.assert_called_once_with('id1')
def attach_volume(self, volume): cinder_api = cinder.CinderAPI(self.context) try: return self._do_attach_volume(cinder_api, volume) except Exception: with excutils.save_and_reraise_exception(): LOG.exception("Failed to attach volume %(volume_id)s", {'volume_id': volume.volume_id}) cinder_api.unreserve_volume(volume.volume_id)
def test_create_volume(self, mock_cinderclient): mock_volumes = mock.MagicMock() mock_cinderclient.return_value = mock.MagicMock(volumes=mock_volumes) volume_size = '5' self.api = cinder_api.CinderAPI(self.context) self.api.create_volume(volume_size) mock_cinderclient.assert_called_once_with() mock_volumes.create.assert_called_once_with(volume_size)
def test_terminate_connection(self, mock_cinderclient): mock_volumes = mock.MagicMock() mock_cinderclient.return_value = mock.MagicMock(volumes=mock_volumes) self.api = cinder_api.CinderAPI(self.context) self.api.terminate_connection('id1', 'connector') mock_cinderclient.assert_called_once_with() mock_volumes.terminate_connection.assert_called_once_with( 'id1', 'connector')
def test_initialize_connection_no_rollback(self, mock_cinderclient): mock_cinderclient.return_value.volumes.\ initialize_connection.side_effect = TestingException connector = {'host': 'host1'} self.api = cinder_api.CinderAPI(self.context) self.assertRaises(TestingException, self.api.initialize_connection, 'id1', connector) self.assertFalse( mock_cinderclient.return_value.volumes.terminate_connection.called)
def test_delete_volume(self, mock_cinderclient): mock_volumes = mock.MagicMock() mock_cinderclient.return_value = mock.MagicMock(volumes=mock_volumes) volume_id = self.id self.api = cinder_api.CinderAPI(self.context) self.api.delete_volume(volume_id) mock_cinderclient.assert_called_once_with() mock_volumes.delete.assert_called_once_with(volume_id)
def test_get(self, mock_cinderclient): volume_id = 'volume_id1' mock_volumes = mock.MagicMock() mock_cinderclient.return_value = mock.MagicMock(volumes=mock_volumes) self.api = cinder_api.CinderAPI(self.context) self.api.get(volume_id) mock_cinderclient.assert_called_once_with() mock_volumes.get.assert_called_once_with(volume_id)
def test_attach(self, mock_cinderclient): mock_volumes = mock.MagicMock() mock_cinderclient.return_value = mock.MagicMock(volumes=mock_volumes) self.api = cinder_api.CinderAPI(self.context) self.api.attach('id1', 'point', 'host') mock_cinderclient.assert_called_once_with() mock_volumes.attach.assert_called_once_with( volume='id1', mountpoint='point', host_name='host', instance_uuid=None)
def test_detach_multiattach(self, mock_cinderclient): attachment = {'host_name': CONF.host, 'attachment_id': 'fakeid'} mock_volumes = mock.MagicMock() mock_cinderclient.return_value = mock.MagicMock(volumes=mock_volumes) mock_cinderclient.return_value.volumes.get.return_value = \ FakeVolume('id1', attachments=[attachment], multiattach=True) self.api = cinder_api.CinderAPI(self.context) self.api.detach('id1') mock_cinderclient.assert_called_with() mock_volumes.detach.assert_called_once_with('id1', 'fakeid')
def test_initialize_connection_exception_no_code(self, mock_cinderclient, mock_log): mock_cinderclient.return_value.volumes. \ initialize_connection.side_effect = ( cinder_exception.ClientException(500, "500")) mock_cinderclient.return_value.volumes. \ terminate_connection.side_effect = (TestingException) connector = {'host': 'fakehost1'} self.api = cinder_api.CinderAPI(self.context) self.assertRaises(cinder_exception.ClientException, self.api.initialize_connection, 'id1', connector) self.assertIsNone(mock_log.error.call_args_list[1][0][1]['code'])
def test_initialize_connection_rollback(self, mock_cinderclient): mock_cinderclient.return_value.volumes.\ initialize_connection.side_effect = ( cinder_exception.ClientException(500, "500")) connector = {'host': 'host1'} self.api = cinder_api.CinderAPI(self.context) ex = self.assertRaises(cinder_exception.ClientException, self.api.initialize_connection, 'id1', connector) self.assertEqual(500, ex.code) mock_cinderclient.return_value.volumes.\ terminate_connection.assert_called_once_with('id1', connector)
def is_volume_deleted(self, context, volmap): try: volume = cinder_api.CinderAPI(context).search_volume( volmap.cinder_volume_id) is_deleted = False # Cinder volume error states: 'error', 'error_deleting', # 'error_backing-up', 'error_restoring', 'error_extending', # all of which start with 'error' is_error = True if 'error' in volume.status else False except exception.VolumeNotFound: is_deleted = True is_error = False return is_deleted, is_error
def test_initialize_connection(self, mock_cinderclient): connection_info = {'foo': 'bar'} mock_cinderclient.return_value.volumes. \ initialize_connection.return_value = connection_info volume_id = 'fake_vid' connector = {'host': 'fakehost1'} self.api = cinder_api.CinderAPI(self.context) actual = self.api.initialize_connection(volume_id, connector) expected = connection_info self.assertEqual(expected, actual) mock_cinderclient.return_value.volumes. \ initialize_connection.assert_called_once_with(volume_id, connector)
def test_detach(self, mock_cinderclient): attachment = {'server_id': 'fake_server', 'attachment_id': 'fakeid'} mock_volumes = mock.MagicMock() mock_cinderclient.return_value = mock.MagicMock(volumes=mock_volumes) mock_cinderclient.return_value.volumes.get.return_value = \ FakeVolume('id1', attachments=[attachment]) volume = mock.MagicMock() volume.volume_id = 'id1' self.api = cinder_api.CinderAPI(self.context) self.api.detach(volume) mock_cinderclient.assert_called_with() mock_volumes.detach.assert_called_once_with('id1', None)
def detach_volume(self, volume): volume_id = volume.volume_id cinder_api = cinder.CinderAPI(self.context) try: cinder_api.begin_detaching(volume_id) except cinder_exception.BadRequest as e: raise exception.Invalid(_("Invalid volume: %s") % str(e)) conn_info = jsonutils.loads(volume.connection_info) try: self._disconnect_volume(conn_info) except Exception: with excutils.save_and_reraise_exception(): LOG.exception('Failed to disconnect volume %(volume_id)s', {'volume_id': volume_id}) cinder_api.roll_detaching(volume_id) cinder_api.terminate_connection( volume_id, get_volume_connector_properties()) cinder_api.detach(volume_id)
def check_multiattach(self, context, volmap): ca = cinder_api.CinderAPI(context) return ca.get(volmap.cinder_volume_id).multiattach
def get_volume_status(self, context, volmap): ca = cinder_api.CinderAPI(context) return ca.get(volmap.cinder_volume_id).status
def is_volume_available(self, context, volume): ca = cinder_api.CinderAPI(context) if 'available' == ca.get(volume.volume_id).status: return True else: return False
def __init__(self, context): self.context = context self.cinder_api = cinder.CinderAPI(self.context)
def _build_requested_volumes(self, context, volume_spec, volume_mounts, capsule): # NOTE(hongbin): We assume cinder is the only volume provider here. # The logic needs to be re-visited if a second volume provider # (i.e. Manila) is introduced. # NOTE(kevinz): We assume the volume_mounts has been pretreated, # there won't occur that volume multiple attach and no untapped # volume. cinder_api = cinder.CinderAPI(context) volume_driver = "cinder" requested_volumes = [] volume_created = [] try: for mount in volume_spec: mount_driver = mount[volume_driver] auto_remove = False if mount_driver.get("volumeID"): uuid = mount_driver.get("volumeID") volume = cinder_api.search_volume(uuid) cinder_api.ensure_volume_usable(volume) else: size = mount_driver.get("size") volume = cinder_api.create_volume(size) volume_created.append(volume) if "autoRemove" in mount_driver.keys() \ and mount_driver.get("autoRemove", False): auto_remove = True mount_destination = None container_name = None volume_object = objects.Volume(context, cinder_volume_id=volume.id, volume_provider=volume_driver, user_id=context.user_id, project_id=context.project_id, auto_remove=auto_remove) volume_object.create(context) for item in volume_mounts: if item['name'] == mount['name']: mount_destination = item['mountPath'] container_name = item['container_name'] volmapp = objects.VolumeMapping( context, container_path=mount_destination, user_id=context.user_id, project_id=context.project_id, volume_id=volume_object.id) requested_volumes.append({container_name: volmapp}) if not mount_destination or not container_name: msg = _("volume mount parameters is invalid.") raise exception.Invalid(msg) except Exception as e: # if volume search or created failed, will remove all # the created volume. The existed volume will remain. for volume in volume_created: try: cinder_api.delete_volume(volume.id) except Exception as exc: LOG.error('Error on deleting volume "%s": %s.', volume.id, six.text_type(exc)) # Since the container and capsule database model has been created, # we need to delete them here due to the volume create failed. for container in capsule.containers: try: container.destroy(context) except Exception as exc: LOG.warning('fail to delete the container %s: %s', container.uuid, exc) capsule.destroy(context) raise e return requested_volumes