def test_cg_create_source_cgsnapshot_not_in_available(self): fake_snap_id = six.text_type(uuid.uuid4()) body = {"consistency_group": {"source_cgsnapshot_id": fake_snap_id}} self.mock_object( self.controller.cg_api, 'create', mock.Mock(side_effect=exception.InvalidCGSnapshot(reason='blah'))) self.assertRaises(webob.exc.HTTPConflict, self.controller.create, self.request, body)
def test_delete_in_conflicting_status(self): fake_snap, expected_snap = self._get_fake_cgsnapshot() self.mock_object(self.controller.cg_api, 'get_cgsnapshot', mock.Mock(return_value=fake_snap)) self.mock_object( self.controller.cg_api, 'delete_cgsnapshot', mock.Mock(side_effect=exception.InvalidCGSnapshot(reason='blah'))) self.assertRaises(webob.exc.HTTPConflict, self.controller.delete, self.request, fake_snap['id'])
def test_cg_create_invalid_cgsnapshot_state(self): fake_snap_id = six.text_type(uuid.uuid4()) self.mock_object(self.controller.cg_api, 'create', mock.Mock(side_effect=exception.InvalidCGSnapshot( reason='bad status' ))) body = {"consistency_group": {"source_cgsnapshot_id": fake_snap_id}} self.assertRaises(webob.exc.HTTPConflict, self.controller.create, self.request, body) self.mock_policy_check.assert_called_once_with( self.context, self.resource_name, 'create')
def delete_cgsnapshot(self, context, snap): """Delete consistency group snapshot.""" snap_id = snap['id'] cg = self.db.consistency_group_get(context, snap['consistency_group_id']) statuses = (constants.STATUS_AVAILABLE, constants.STATUS_ERROR) if not snap['status'] in statuses: msg = (_("Consistency group snapshot status must be one of" " %(statuses)s") % { "statuses": statuses }) raise exception.InvalidCGSnapshot(reason=msg) self.db.cgsnapshot_update(context, snap_id, {'status': constants.STATUS_DELETING}) # Cast to share manager self.share_rpcapi.delete_cgsnapshot(context, snap, cg['host'])
def create(self, context, name=None, description=None, share_type_ids=None, source_cgsnapshot_id=None, share_network_id=None): """Create new consistency group.""" cgsnapshot = None original_cg = None # NOTE(gouthamr): share_server_id is inherited from the parent CG if a # CG snapshot is specified, else, it will be set in the share manager. share_server_id = None if source_cgsnapshot_id: cgsnapshot = self.db.cgsnapshot_get(context, source_cgsnapshot_id) if cgsnapshot['status'] != constants.STATUS_AVAILABLE: msg = (_("Consistency group snapshot status must be %s") % constants.STATUS_AVAILABLE) raise exception.InvalidCGSnapshot(reason=msg) original_cg = self.db.consistency_group_get( context, cgsnapshot['consistency_group_id']) share_type_ids = [ s['share_type_id'] for s in original_cg['share_types'] ] share_network_id = original_cg['share_network_id'] share_server_id = original_cg['share_server_id'] # Get share_type_objects share_type_objects = [] driver_handles_share_servers = None for share_type_id in (share_type_ids or []): try: share_type_object = share_types.get_share_type( context, share_type_id) except exception.ShareTypeNotFound: msg = _("Share type with id %s could not be found") raise exception.InvalidInput(msg % share_type_id) share_type_objects.append(share_type_object) extra_specs = share_type_object.get('extra_specs') if extra_specs: share_type_handle_ss = strutils.bool_from_string( extra_specs.get( constants.ExtraSpecs.DRIVER_HANDLES_SHARE_SERVERS)) if driver_handles_share_servers is None: driver_handles_share_servers = share_type_handle_ss elif not driver_handles_share_servers == share_type_handle_ss: # NOTE(ameade): if the share types have conflicting values # for driver_handles_share_servers then raise bad request msg = _("The specified share_types cannot have " "conflicting values for the " "driver_handles_share_servers extra spec.") raise exception.InvalidInput(reason=msg) if (not share_type_handle_ss) and share_network_id: msg = _("When using a share types with the " "driver_handles_share_servers extra spec as " "False, a share_network_id must not be provided.") raise exception.InvalidInput(reason=msg) try: if share_network_id: self.db.share_network_get(context, share_network_id) except exception.ShareNetworkNotFound: msg = _("The specified share network does not exist.") raise exception.InvalidInput(reason=msg) if (driver_handles_share_servers and not (source_cgsnapshot_id or share_network_id)): msg = _("When using a share type with the " "driver_handles_share_servers extra spec as " "True, a share_network_id must be provided.") raise exception.InvalidInput(reason=msg) options = { 'source_cgsnapshot_id': source_cgsnapshot_id, 'share_network_id': share_network_id, 'share_server_id': share_server_id, 'name': name, 'description': description, 'user_id': context.user_id, 'project_id': context.project_id, 'status': constants.STATUS_CREATING, 'share_types': share_type_ids } if original_cg: options['host'] = original_cg['host'] cg = self.db.consistency_group_create(context, options) try: if cgsnapshot: members = self.db.cgsnapshot_members_get_all( context, source_cgsnapshot_id) for member in members: share_type = share_types.get_share_type( context, member['share_type_id']) member['share_instance'] = self.db.share_instance_get( context, member['share_instance_id'], with_share_data=True) self.share_api.create(context, member['share_proto'], member['size'], None, None, consistency_group_id=cg['id'], cgsnapshot_member=member, share_type=share_type, share_network_id=share_network_id) except Exception: with excutils.save_and_reraise_exception(): self.db.consistency_group_destroy(context.elevated(), cg['id']) request_spec = {'consistency_group_id': cg['id']} request_spec.update(options) request_spec['share_types'] = share_type_objects if cgsnapshot and original_cg: self.share_rpcapi.create_consistency_group(context, cg, original_cg['host']) else: self.scheduler_rpcapi.create_consistency_group( context, cg_id=cg['id'], request_spec=request_spec, filter_properties={}) return cg