class SnapshotsController(wsgi.Controller): """The Snapshots API controller for the SG-Service.""" _view_builder_class = SnapshotViewBuilder def __init__(self): self.service_api = ServiceAPI() super(SnapshotsController, self).__init__() def _get_snapshot_filter_options(self): return CONF.query_snapshot_filters def show(self, req, id): """Return data about the given snapshots.""" LOG.info(_LI("Show snapshot with id: %s"), id) context = req.environ['sgservice.context'] snapshot = self.service_api.get_snapshot(context, id) return self._view_builder.detail(req, snapshot) def delete(self, req, id): """Delete a snapshot.""" LOG.info(_LI("Delete snapshot with id: %s"), id) context = req.environ['sgservice.context'] snapshot = self.service_api.get_snapshot(context, id) self.service_api.delete_snapshot(context, snapshot) return webob.Response(status_int=202) def index(self, req): """Returns a list of snapshots, transformed through view builder.""" LOG.info(_LI("Show snapshot list")) context = req.environ['sgservice.context'] params = req.params.copy() marker, limit, offset = common.get_pagination_params(params) sort_keys, sort_dirs = common.get_sort_params(params) filters = params utils.remove_invaild_filter_options( context, filters, self._get_snapshot_filter_options()) utils.check_filters(filters) if 'name' in sort_keys: sort_keys[sort_keys.index('name')] = 'display_name' if 'name' in filters: filters['display_name'] = filters.pop('name') snapshots = self.service_api.get_all_snapshots(context, marker=marker, limit=limit, sort_keys=sort_keys, sort_dirs=sort_dirs, filters=filters, offset=offset) retval_snapshots = self._view_builder.detail_list(req, snapshots) LOG.info(_LI("Show snapshot list request issued successfully.")) return retval_snapshots def create(self, req, body): """Creates a new snapshot.""" LOG.debug('Create snapshot request body: %s', body) context = req.environ['sgservice.context'] snapshot = body['snapshot'] volume_id = snapshot.get('volume_id', None) if volume_id is None: msg = _('Incorrect request body format') raise webob.exc.HTTPBadRequest(explanation=msg) name = snapshot.get('name', None) description = snapshot.get('description', None) if description is None: description = 'snapshot-%s' % volume_id checkpoint_id = snapshot.get('checkpoint_id', None) volume = self.service_api.get(context, volume_id) snapshot = self.service_api.create_snapshot(context, name, description, volume, checkpoint_id) return self._view_builder.detail(req, snapshot) def update(self, req, id, body): """Update a snapshot.""" LOG.info(_LI("Update snapshot with id: %s"), id) context = req.environ['sgservice.context'] if not body: msg = _("Missing request body") raise webob.exc.HTTPBadRequest(explanation=msg) if 'snapshot' not in body: msg = (_("Missing required element '%s' in request body"), 'snapshot') raise webob.exc.HTTPBadRequest(explanation=msg) snapshot = body['snapshot'] update_dict = {} valid_update_keys = ( 'name', 'description', 'display_name', 'display_description', ) for key in valid_update_keys: if key in snapshot: update_dict[key] = snapshot[key] self.validate_name_and_description(update_dict) if 'name' in update_dict: update_dict['display_name'] = update_dict.pop('name') if 'description' in update_dict: update_dict['display_description'] = update_dict.pop('description') snapshot = self.service_api.get_snapshot(context, id) snapshot.update(update_dict) snapshot.save() return self._view_builder.detail(req, snapshot) @wsgi.action('rollback') def rollback(self, req, id, body): """Rollback a snapshot to volume""" LOG.info(_LI("Rollback snapshot with id: %s"), id) context = req.environ['sgservice.context'] snapshot = self.service_api.get_snapshot(context, id) rollback = self.service_api.rollback_snapshot(context, snapshot) return self._view_builder.rollback_summary(req, rollback) @wsgi.action('reset_status') def reset_status(self, req, id, body): """reset snapshot status""" LOG.info(_LI("Reset snapshot status, id: %s"), id) status = body['reset_status'].get('status', fields.SnapshotStatus.AVAILABLE) if status not in fields.SnapshotStatus.ALL: msg = _("Invalid status provided.") LOG.error(msg) raise exception.InvalidStatus(status=status) context = req.environ['sgservice.context'] snapshot = self.service_api.get_snapshot(context, id) snapshot.status = status snapshot.save() return webob.Response(status_int=202)
def __init__(self): self.service_api = ServiceAPI() super(SnapshotsController, self).__init__()
class VolumesController(wsgi.Controller): """The Volumes API controller for the SG-Service.""" _view_builder_class = VolumeViewBuilder def __init__(self): self.service_api = ServiceAPI() super(VolumesController, self).__init__() def _get_volume_filter_options(self): return CONF.query_volume_filters def show(self, req, id): """Return data about the given volumes.""" LOG.info(_LI("Show volume with id: %s"), id) context = req.environ['sgservice.context'] volume = self.service_api.get(context, id) return self._view_builder.detail(req, volume) def delete(self, req, id): """Delete a sg volume.""" LOG.info(_LI("Delete sg volume, volume_id: %s"), id) context = req.environ['sgservice.context'] volume = self.service_api.get(context, id) self.service_api.delete(context, volume) return webob.Response(status_int=202) def index(self, req): """Returns a list of volumes, transformed through view builder.""" LOG.info(_LI("Show volume list")) context = req.environ['sgservice.context'] params = req.params.copy() marker, limit, offset = common.get_pagination_params(params) sort_keys, sort_dirs = common.get_sort_params(params) filters = params utils.remove_invaild_filter_options(context, filters, self._get_volume_filter_options()) utils.check_filters(filters) if 'name' in sort_keys: sort_keys[sort_keys.index('name')] = 'display_name' if 'name' in filters: filters['display_name'] = filters.pop('name') volumes = self.service_api.get_all(context, marker=marker, limit=limit, sort_keys=sort_keys, sort_dirs=sort_dirs, filters=filters, offset=offset) retval_volumes = self._view_builder.detail_list(req, volumes) LOG.info(_LI("Show volume list request issued successfully.")) return retval_volumes def create(self, req, body): """Creates a new volume from snapshot or checkpoint.""" LOG.debug('Create volume from snapshot, request body: %s', body) context = req.environ['sgservice.context'] volume = body['volume'] volume_type = volume.get('volume_type', None) availability_zone = volume.get('availability_zone', None) volume_id = volume.get('volume_id', None) size = volume.get('size', None) # create from snapshot snapshot_id = volume.get('snapshot_id') if snapshot_id is not None: name = volume.get('name', 'volume-%s' % snapshot_id) description = volume.get('description', name) snapshot = self.service_api.get_snapshot(context, snapshot_id) volume = self.service_api.create_volume( context, snapshot=snapshot, volume_type=volume_type, availability_zone=availability_zone, description=description, name=name, volume_id=volume_id, size=size) return self._view_builder.detail(req, volume) # create from checkpoint checkpoint_id = volume.get('checkpoint_id') if checkpoint_id is not None: name = volume.get('name', 'volume-%s' % checkpoint_id) description = volume.get('description', name) checkpoint = self.service_api.get_checkpoint( context, checkpoint_id) volume = self.service_api.create_volume( context, checkpoint=checkpoint, volume_type=volume_type, availability_zone=availability_zone, description=description, name=name, volume_id=volume_id) return self._view_builder.detail(req, volume) msg = _('Incorrect request body format, create volume must specified ' 'a snapshot or checkpoint') raise webob.exc.HTTPBadRequest(explanation=msg) def update(self, req, id, body): """Update a volume.""" LOG.info(_LI("Update snapshot with id: %s"), id) context = req.environ['sgservice.context'] if not body: msg = _("Missing request body") raise webob.exc.HTTPBadRequest(explanation=msg) if 'volume' not in body: msg = (_("Missing required element '%s' in request body"), 'volume') raise webob.exc.HTTPBadRequest(explanation=msg) volume = body['volume'] update_dict = {} valid_update_keys = ( 'name', 'description', 'display_name', 'display_description', ) for key in valid_update_keys: if key in volume: update_dict[key] = volume[key] self.validate_name_and_description(update_dict) if 'name' in update_dict: update_dict['display_name'] = update_dict.pop('name') if 'description' in update_dict: update_dict['display_description'] = update_dict.pop('description') volume = self.service_api.get(context, id) volume.update(update_dict) volume.save() return self._view_builder.detail(req, volume) @wsgi.action('enable') def enable(self, req, id, body): """Enable-SG a available volume.""" LOG.debug('Enable volume SG, volume_id: %s', id) context = req.environ['sgservice.context'] params = body['enable'] params = {} if params is None else params name = params.get('name', None) description = params.get('description', None) metadata = params.get('metadata', None) volume = self.service_api.enable_sg(context, id, name=name, description=description, metadata=metadata) return self._view_builder.detail(req, volume) @wsgi.action('disable') def disable(self, req, id, body): """Disable a enabled-volume.""" LOG.info(_LI("Disable volume SG, volume_id: %s"), id) context = req.environ['sgservice.context'] volume = self.service_api.get(context, id) volume = self.service_api.disable_sg(context, volume) return self._view_builder.detail(req, volume) @wsgi.action('attach') def attach(self, req, id, body): """Add sg-volume attachment metadata.""" LOG.info(_LI("Add SG-volume attachment, volume_id: %s"), id) context = req.environ['sgservice.context'] volume = self.service_api.get(context, id) params = body['attach'] params = {} if params is None else params instance_uuid = params.get('instance_uuid', None) mode = params.get('mode', None) if mode is None: mode = 'rw' if instance_uuid is None: msg = _("Invalid request to attach volume to an invalid target") raise webob.exc.HTTPBadRequest(explanation=msg) if mode not in ('rw', 'ro'): msg = _("Invalid request to attach volume to an invalid mode. " "Attaching mode should be 'rw' or 'ro'.") raise webob.exc.HTTPBadRequest(explanation=msg) attach_result = self.service_api.attach(context, volume, instance_uuid, mode) return self._view_builder.attach_summary(req, attach_result) @wsgi.action('detach') def detach(self, req, id, body): """Clear attachment metadata.""" LOG.info(_LI("Clear SG-volume attachment with volume_id: %s"), id) context = req.environ['sgservice.context'] volume = self.service_api.get(context, id) params = body['detach'] params = {} if params is None else params instance_uuid = params.get('instance_uuid', None) self.service_api.detach(context, volume, instance_uuid) return webob.Response(status_int=202) @wsgi.action('reset_status') def reset_status(self, req, id, body): """reset volume status""" LOG.info(_LI("Reset volume status, id: %s"), id) status = body['reset_status'].get('status', fields.VolumeStatus.ENABLED) if status not in fields.VolumeStatus.ALL: msg = _("Invalid status provided.") LOG.error(msg) raise exception.InvalidStatus(status=status) context = req.environ['sgservice.context'] volume = self.service_api.get(context, id) volume.status = status volume.save() return webob.Response(status_int=202)
def __init__(self): self.service_api = ServiceAPI() super(VolumesController, self).__init__()
class ReplicationsController(wsgi.Controller): """The Replications API controller for the SG-Service.""" _view_builder_class = ReplicationViewBuilder def __init__(self): self.service_api = ServiceAPI() super(ReplicationsController, self).__init__() def _get_replication_filter_options(self): return CONF.query_replication_filters def show(self, req, id): """Return data about the given replications.""" LOG.info(_LI("Show replication with id: %s"), id) context = req.environ['sgservice.context'] replication = self.service_api.get_replication(context, id) return self._view_builder.detail(req, replication) def delete(self, req, id): """Delete a replication.""" LOG.info(_LI("Delete replication with id: %s"), id) context = req.environ['sgservice.context'] replication = self.service_api.get_replication(context, id) self.service_api.delete_replication(context, replication) return webob.Response(status_int=202) def index(self, req): """Returns a list of replications, transformed through view builder.""" LOG.info(_LI("Show replication list")) context = req.environ['sgservice.context'] params = req.params.copy() marker, limit, offset = common.get_pagination_params(params) sort_keys, sort_dirs = common.get_sort_params(params) filters = params utils.remove_invaild_filter_options( context, filters, self._get_replication_filter_options()) utils.check_filters(filters) if 'name' in sort_keys: sort_keys[sort_keys.index('name')] = 'display_name' if 'name' in filters: filters['display_name'] = filters.pop('name') replications = self.service_api.get_all_replications( context, marker=marker, limit=limit, sort_keys=sort_keys, sort_dirs=sort_dirs, filters=filters, offset=offset) retval_replications = self._view_builder.detail_list(req, replications) LOG.info(_LI("Show replication list request issued successfully.")) return retval_replications def create(self, req, body): """Creates a new replication.""" if not self.is_valid_body(body, 'replication'): raise exc.HTTPUnprocessableEntity() LOG.debug('Create replication request body: %s', body) context = req.environ['sgservice.context'] replication = body['replication'] master_volume_id = replication.get('master_volume', None) if master_volume_id is None: msg = _('Incorrect request body format') raise webob.exc.HTTPBadRequest(explanation=msg) slave_volume_id = replication.get('slave_volume', None) if slave_volume_id is None: msg = _('Incorrect request body format') raise webob.exc.HTTPBadRequest(explanation=msg) name = replication.get('name', None) description = replication.get('description', None) if description is None: description = 'replication:%s-%s' % (master_volume_id, slave_volume_id) master_volume = self.service_api.get(context, master_volume_id) slave_volume = self.service_api.get(context, slave_volume_id) replication = self.service_api.create_replication( context, name, description, master_volume, slave_volume) return self._view_builder.detail(req, replication) def update(self, req, id, body): """Update a replication.""" LOG.info(_LI("Update replication with id: %s"), id) context = req.environ['sgservice.context'] if not body: msg = _("Missing request body") raise webob.exc.HTTPBadRequest(explanation=msg) if 'replication' not in body: msg = (_("Missing required element '%s' in request body"), 'replication') raise webob.exc.HTTPBadRequest(explanation=msg) replication = body['replication'] update_dict = {} valid_update_keys = ( 'name', 'description', 'display_name', 'display_description', ) for key in valid_update_keys: if key in replication: update_dict[key] = replication[key] self.validate_name_and_description(update_dict) if 'name' in update_dict: update_dict['display_name'] = update_dict.pop('name') if 'description' in update_dict: update_dict['display_description'] = update_dict.pop('description') replication = self.service_api.get_replication(context, id) replication.update(update_dict) replication.save() return self._view_builder.detail(req, replication) @wsgi.action('enable') def enable(self, req, id, body): """Enable a disabled-replication""" LOG.info(_LI("Enable replication with id: %s"), id) context = req.environ['sgservice.context'] replication = self.service_api.get_replication(context, id) replication = self.service_api.enable_replication(context, replication) return self._view_builder.detail(req, replication) @wsgi.action('disable') def disable(self, req, id, body): """Disable a failed-over replication""" LOG.info(_LI("Disable replication with id: %s"), id) context = req.environ['sgservice.context'] replication = self.service_api.get_replication(context, id) replication = self.service_api.disable_replication( context, replication) return self._view_builder.detail(req, replication) @wsgi.action('failover') def failover(self, req, id, body): """Failover a enabled replication""" LOG.info(_LI("Failover replication with id: %s"), id) context = req.environ['sgservice.context'] params = body['failover'] force = params.get('force', False) replication = self.service_api.get_replication(context, id) replication = self.service_api.failover_replication( context, replication, force) return self._view_builder.detail(req, replication) @wsgi.action('reverse') def reverse(self, req, id, body): """reverse a enabled replication""" LOG.info(_LI("Reverse replication with id: %s"), id) context = req.environ['sgservice.context'] replication = self.service_api.get_replication(context, id) replication = self.service_api.reverse_replication( context, replication) return self._view_builder.detail(req, replication) @wsgi.action('reset_status') def reset_status(self, req, id, body): """reset replication status""" LOG.info(_LI("Reset replication status, id: %s"), id) status = body['reset_status'].get('status', fields.ReplicationStatus.ENABLED) if status not in fields.ReplicationStatus.ALL: msg = _("Invalid status provided.") LOG.error(msg) raise exception.InvalidStatus(status=status) context = req.environ['sgservice.context'] replication = self.service_api.get_replication(context, id) replication.status = status replication.save() # reset master volume replicate status master_volume = self.service_api.get(context, replication.master_volume) if master_volume.replicate_status not in [ None, fields.ReplicateStatus.DELETED ]: master_volume.replicate_status = status master_volume.save() # reset slave volume replicate status slave_volume = self.service_api.get(context, replication.slave_volume) if slave_volume.replicate_status not in [ None, fields.ReplicateStatus.DELETED ]: slave_volume.replicate_status = status slave_volume.save() return webob.Response(status_int=202)
def __init__(self): self.service_api = ServiceAPI() super(ReplicationsController, self).__init__()
def __init__(self): self.service_api = ServiceAPI() super(CheckpointsController, self).__init__()
def __init__(self): self.service_api = ServiceAPI() super(BackupsController, self).__init__()
class BackupsController(wsgi.Controller): """The Backups API controller for the SG-Service.""" _view_builder_class = BackupViewBuilder def __init__(self): self.service_api = ServiceAPI() super(BackupsController, self).__init__() def _get_backup_filter_options(self): return CONF.query_backup_filters def show(self, req, id): """Return data about the given backups.""" LOG.info(_LI("Show backup, backup_id: %s"), id) context = req.environ['sgservice.context'] backup = self.service_api.get_backup(context, id) return self._view_builder.detail(req, backup) def delete(self, req, id): """Delete a backup.""" LOG.info(_LI("Delete backup, backup_id: %s"), id) context = req.environ['sgservice.context'] backup = self.service_api.get_backup(context, id) self.service_api.delete_backup(context, backup) return webob.Response(status_int=202) def index(self, req): """Returns a list of backups, transformed through view builder.""" LOG.info(_LI("Show backup list")) context = req.environ['sgservice.context'] params = req.params.copy() marker, limit, offset = common.get_pagination_params(params) sort_keys, sort_dirs = common.get_sort_params(params) filters = params utils.remove_invaild_filter_options(context, filters, self._get_backup_filter_options()) utils.check_filters(filters) if 'name' in sort_keys: sort_keys[sort_keys.index('name')] = 'display_name' if 'name' in filters: filters['display_name'] = filters.pop('name') backups = self.service_api.get_all_backups(context, marker=marker, limit=limit, sort_keys=sort_keys, sort_dirs=sort_dirs, filters=filters, offset=offset) retval_backups = self._view_builder.detail_list(req, backups) LOG.info(_LI("Show backup list request issued successfully.")) return retval_backups def create(self, req, body): """Creates a new backup.""" LOG.debug('Create backup request body: %s', body) context = req.environ['sgservice.context'] backup = body['backup'] volume_id = backup.get('volume_id', None) if volume_id is None: msg = _('Incorrect request body format') raise webob.exc.HTTPBadRequest(explanation=msg) name = backup.get('name', None) description = backup.get('description', None) if description is None: description = 'backup-%s' % volume_id backup_type = backup.get('type') if backup_type is None: backup_type = constants.FULL_BACKUP if backup_type not in constants.SUPPORT_BACKUP_TYPES: msg = _('backup type should be full or incremental') raise webob.exc.HTTPBadRequest(explanation=msg) backup_destination = backup.get('destination') if backup_destination is None: backup_destination = constants.LOCAL_BACKUP if backup_destination not in constants.SUPPORT_BACKUP_DESTINATIONS: msg = _('backup destination should be local or remote') raise webob.exc.HTTPBadRequest(explanation=msg) volume = self.service_api.get(context, volume_id) backup = self.service_api.create_backup(context, name, description, volume, backup_type, backup_destination) return self._view_builder.detail(req, backup) def update(self, req, id, body): """Update a backup.""" LOG.info(_LI("Update backup, backup_id: %s"), id) context = req.environ['sgservice.context'] if not body: msg = _("Missing request body") raise webob.exc.HTTPBadRequest(explanation=msg) if 'backup' not in body: msg = (_("Missing required element '%s' in request body"), 'backup') raise webob.exc.HTTPBadRequest(explanation=msg) backup = body['backup'] update_dict = {} valid_update_keys = ( 'name', 'description', 'display_name', 'display_description', ) for key in valid_update_keys: if key in backup: update_dict[key] = backup[key] self.validate_name_and_description(update_dict) if 'name' in update_dict: update_dict['display_name'] = update_dict.pop('name') if 'description' in update_dict: update_dict['display_description'] = update_dict.pop('description') backup = self.service_api.get_backup(context, id) backup.update(update_dict) backup.save() return self._view_builder.detail(req, backup) @wsgi.action('restore') def restore(self, req, id, body): """Restore backup to an SG-enabled volume""" LOG.info(_LI("Restore backup to sg-enabled volume, backup_id: %s"), id) context = req.environ['sgservice.context'] backup = self.service_api.get_backup(context, id) restore = body['restore'] volume_id = restore.get('volume_id', None) if volume_id is None: msg = _('restored volume should be specified.') raise webob.exc.HTTPBadRequest(explanation=msg) restore = self.service_api.restore_backup(context, backup, volume_id) return self._view_builder.restore_summary(req, restore) @wsgi.action('export_record') def export_record(self, req, id, body): """Export backup record""" LOG.info(_LI("Export backup record, backup_id: %s"), id) context = req.environ['sgservice.context'] backup = self.service_api.get_backup(context, id) record = self.service_api.export_record(context, backup) return self._view_builder.export_summary(req, record) def import_record(self, req, body): """Import a backup""" LOG.info(_LI("Importing record from body: %s"), body) self.assert_valid_body(body, 'backup_record') context = req.environ['sgservice.context'] backup_record = body['backup_record'] # Verify that body elements are provided try: driver_data = backup_record['driver_data'] except KeyError: msg = _("Incorrect request body format.") raise webob.exc.HTTPBadRequest(explanation=msg) LOG.debug('Importing backup using driver_data %s.', driver_data) try: new_backup = self.service_api.import_record(context, backup_record) except exception.InvalidBackup as error: raise webob.exc.HTTPBadRequest(explanation=error.msg) # Other Not found exceptions will be handled at the wsgi level except exception.ServiceNotFound as error: raise webob.exc.HTTPInternalServerError(explanation=error.msg) retval = self._view_builder.detail(req, new_backup) return retval @wsgi.action('reset_status') def reset_status(self, req, id, body): """reset backup status""" LOG.info(_LI("Reset backup status, id: %s"), id) status = body['reset_status'].get('status', fields.BackupStatus.AVAILABLE) if status not in fields.BackupStatus.ALL: msg = _("Invalid status provided.") LOG.error(msg) raise exception.InvalidStatus(status=status) context = req.environ['sgservice.context'] backup = self.service_api.get_backup(context, id) backup.status = status backup.save() return webob.Response(status_int=202)