def create_volume(self, context, volume_id, request_spec=None, filter_properties=None, allow_reschedule=True, snapshot_id=None, image_id=None, source_volid=None): """Creates and exports the volume.""" flow = create_volume.get_manager_flow( self.db, self.driver, self.scheduler_rpcapi, self.host, volume_id, request_spec=request_spec, filter_properties=filter_properties, allow_reschedule=allow_reschedule, snapshot_id=snapshot_id, image_id=image_id, source_volid=source_volid, reschedule_context=context.deepcopy()) assert flow, _('Manager volume flow not retrieved') flow.run(context.elevated()) if flow.state != states.SUCCESS: raise exception.CinderException( _("Failed to successfully complete" " manager volume workflow")) self._reset_stats() return volume_id
def create_volume(self, context, volume_id, request_spec=None, filter_properties=None, allow_reschedule=True, snapshot_id=None, image_id=None, source_volid=None): """Creates and exports the volume.""" flow = create_volume.get_manager_flow( self.db, self.driver, self.scheduler_rpcapi, self.host, volume_id, request_spec=request_spec, filter_properties=filter_properties, allow_reschedule=allow_reschedule, snapshot_id=snapshot_id, image_id=image_id, source_volid=source_volid, reschedule_context=context.deepcopy()) assert flow, _('Manager volume flow not retrieved') flow.run(context.elevated()) if flow.state != states.SUCCESS: raise exception.CinderException(_("Failed to successfully complete" " manager volume workflow")) self._reset_stats() return volume_id
def create_volume(self, context, volume_id, request_spec=None, filter_properties=None, allow_reschedule=True, snapshot_id=None, image_id=None, source_volid=None): """Creates and exports the volume.""" context_saved = context.deepcopy() context = context.elevated() if filter_properties is None: filter_properties = {} try: flow_engine = create_volume.get_manager_flow( context, self.db, self.driver, self.scheduler_rpcapi, self.host, volume_id, snapshot_id=snapshot_id, image_id=image_id, source_volid=source_volid, allow_reschedule=allow_reschedule, reschedule_context=context_saved, request_spec=request_spec, filter_properties=filter_properties) except Exception: LOG.exception(_("Failed to create manager volume flow")) raise exception.CinderException( _("Failed to create manager volume flow")) if snapshot_id is not None: # Make sure the snapshot is not deleted until we are done with it. locked_action = "%s-%s" % (snapshot_id, 'delete_snapshot') elif source_volid is not None: # Make sure the volume is not deleted until we are done with it. locked_action = "%s-%s" % (source_volid, 'delete_volume') else: locked_action = None def _run_flow(): # This code executes create volume flow. If something goes wrong, # flow reverts all job that was done and reraises an exception. # Otherwise, all data that was generated by flow becomes available # in flow engine's storage. flow_engine.run() @utils.synchronized(locked_action, external=True) def _run_flow_locked(): _run_flow() if locked_action is None: _run_flow() else: _run_flow_locked() # Fetch created volume from storage volume_ref = flow_engine.storage.fetch('volume') # Update volume stats self.stats['allocated_capacity_gb'] += volume_ref['size'] return volume_ref['id']
def get(self, context, volume_id, viewable_admin_meta=False): old_ctxt = context.deepcopy() if viewable_admin_meta: ctxt = context.elevated() else: ctxt = context rv = self.db.volume_get(ctxt, volume_id) volume = dict(rv.iteritems()) try: check_policy(old_ctxt, 'get', volume) except exception.PolicyNotAuthorized: # raise VolumeNotFound instead to make sure Cinder behaves # as it used to raise exception.VolumeNotFound(volume_id=volume_id) return volume
def create_volume(self, context, volume_id, request_spec=None, filter_properties=None, allow_reschedule=True, snapshot_id=None, image_id=None, source_volid=None): """Creates and exports the volume.""" context_saved = context.deepcopy() context = context.elevated() if filter_properties is None: filter_properties = {} volume_ref = self.db.volume_get(context, volume_id) self._notify_about_volume_usage(context, volume_ref, "create.start") # NOTE(vish): so we don't have to get volume from db again # before passing it to the driver. volume_ref['host'] = self.host if volume_ref['status'] == 'migration_target_creating': status = 'migration_target' else: status = 'available' model_update = False image_meta = None cloned = False try: LOG.debug( _("volume %(vol_name)s: creating lv of" " size %(vol_size)sG"), { 'vol_name': volume_ref['name'], 'vol_size': volume_ref['size'] }) snapshot_ref = None sourcevol_ref = None image_service = None image_location = None image_meta = None if snapshot_id is not None: LOG.info(_("volume %s: creating from snapshot"), volume_ref['name']) snapshot_ref = self.db.snapshot_get(context, snapshot_id) elif source_volid is not None: LOG.info(_("volume %s: creating from existing volume"), volume_ref['name']) sourcevol_ref = self.db.volume_get(context, source_volid) elif image_id is not None: LOG.info(_("volume %s: creating from image"), volume_ref['name']) # create the volume from an image image_service, image_id = \ glance.get_remote_image_service(context, image_id) image_location = image_service.get_location(context, image_id) image_meta = image_service.show(context, image_id) else: LOG.info(_("volume %s: creating"), volume_ref['name']) try: model_update, cloned = self._create_volume( context, volume_ref, snapshot_ref, sourcevol_ref, image_service, image_id, image_location) except exception.ImageCopyFailure as ex: LOG.error( _('Setting volume: %s status to error ' 'after failed image copy.'), volume_ref['id']) self.db.volume_update(context, volume_ref['id'], {'status': 'error'}) return except Exception: exc_info = sys.exc_info() # restore source volume status before reschedule # FIXME(zhiteng) do all the clean-up before reschedule if sourcevol_ref is not None: self.db.volume_update(context, sourcevol_ref['id'], {'status': sourcevol_ref['status']}) rescheduled = False # try to re-schedule volume: if allow_reschedule: rescheduled = self._reschedule_or_error( context_saved, volume_id, exc_info, snapshot_id, image_id, request_spec, filter_properties) if rescheduled: LOG.error(_('Unexpected Error: '), exc_info=exc_info) msg = (_('Creating %(volume_id)s %(snapshot_id)s ' '%(image_id)s was rescheduled due to ' '%(reason)s') % { 'volume_id': volume_id, 'snapshot_id': snapshot_id, 'image_id': image_id, 'reason': unicode(exc_info[1]) }) raise exception.CinderException(msg) else: # not re-scheduling raise exc_info[0], exc_info[1], exc_info[2] if model_update: volume_ref = self.db.volume_update(context, volume_ref['id'], model_update) if sourcevol_ref is not None: self.db.volume_glance_metadata_copy_from_volume_to_volume( context, source_volid, volume_id) LOG.debug(_("volume %s: creating export"), volume_ref['name']) model_update = self.driver.create_export(context, volume_ref) if model_update: self.db.volume_update(context, volume_ref['id'], model_update) except Exception: with excutils.save_and_reraise_exception(): volume_ref['status'] = 'error' self.db.volume_update(context, volume_ref['id'], {'status': volume_ref['status']}) LOG.error(_("volume %s: create failed"), volume_ref['name']) self._notify_about_volume_usage(context, volume_ref, "create.end") if snapshot_id: # Copy any Glance metadata from the original volume self.db.volume_glance_metadata_copy_to_volume( context, volume_ref['id'], snapshot_id) if image_id and image_meta: # Copy all of the Glance image properties to the # volume_glance_metadata table for future reference. self.db.volume_glance_metadata_create(context, volume_ref['id'], 'image_id', image_id) name = image_meta.get('name', None) if name: self.db.volume_glance_metadata_create(context, volume_ref['id'], 'image_name', name) # Save some more attributes into the volume metadata IMAGE_ATTRIBUTES = [ 'size', 'disk_format', 'container_format', 'checksum', 'min_disk', 'min_ram' ] for key in IMAGE_ATTRIBUTES: value = image_meta.get(key, None) if value is not None: self.db.volume_glance_metadata_create( context, volume_ref['id'], key, value) image_properties = image_meta.get('properties', {}) for key, value in image_properties.items(): self.db.volume_glance_metadata_create(context, volume_ref['id'], key, value) now = timeutils.utcnow() volume_ref['status'] = status self.db.volume_update(context, volume_ref['id'], { 'status': volume_ref['status'], 'launched_at': now }) LOG.info(_("volume %s: created successfully"), volume_ref['name']) self._reset_stats() self._notify_about_volume_usage(context, volume_ref, "create.end") return volume_ref['id']
def create_volume(self, context, volume_id, request_spec=None, filter_properties=None, allow_reschedule=True, snapshot_id=None, image_id=None, source_volid=None): """Creates and exports the volume.""" context_saved = context.deepcopy() context = context.elevated() if filter_properties is None: filter_properties = {} volume_ref = self.db.volume_get(context, volume_id) self._notify_about_volume_usage(context, volume_ref, "create.start") # NOTE(vish): so we don't have to get volume from db again # before passing it to the driver. volume_ref['host'] = self.host if volume_ref['status'] == 'migration_target_creating': status = 'migration_target' else: status = 'available' model_update = False image_meta = None cloned = False try: LOG.debug(_("volume %(vol_name)s: creating lv of" " size %(vol_size)sG"), {'vol_name': volume_ref['name'], 'vol_size': volume_ref['size']}) snapshot_ref = None sourcevol_ref = None image_service = None image_location = None image_meta = None if snapshot_id is not None: LOG.info(_("volume %s: creating from snapshot"), volume_ref['name']) snapshot_ref = self.db.snapshot_get(context, snapshot_id) elif source_volid is not None: LOG.info(_("volume %s: creating from existing volume"), volume_ref['name']) sourcevol_ref = self.db.volume_get(context, source_volid) elif image_id is not None: LOG.info(_("volume %s: creating from image"), volume_ref['name']) # create the volume from an image image_service, image_id = \ glance.get_remote_image_service(context, image_id) image_location = image_service.get_location(context, image_id) image_meta = image_service.show(context, image_id) else: LOG.info(_("volume %s: creating"), volume_ref['name']) try: model_update, cloned = self._create_volume(context, volume_ref, snapshot_ref, sourcevol_ref, image_service, image_id, image_location) except exception.ImageCopyFailure as ex: LOG.error(_('Setting volume: %s status to error ' 'after failed image copy.'), volume_ref['id']) self.db.volume_update(context, volume_ref['id'], {'status': 'error'}) return except Exception: exc_info = sys.exc_info() # restore source volume status before reschedule # FIXME(zhiteng) do all the clean-up before reschedule if sourcevol_ref is not None: self.db.volume_update(context, sourcevol_ref['id'], {'status': sourcevol_ref['status']}) rescheduled = False # try to re-schedule volume: if allow_reschedule: rescheduled = self._reschedule_or_error(context_saved, volume_id, exc_info, snapshot_id, image_id, request_spec, filter_properties) if rescheduled: # log the original build error self._log_original_error(exc_info) msg = (_('Creating %(volume_id)s %(snapshot_id)s ' '%(image_id)s was rescheduled due to ' '%(reason)s') % {'volume_id': volume_id, 'snapshot_id': snapshot_id, 'image_id': image_id, 'reason': unicode(exc_info[1])}) raise exception.CinderException(msg) else: # not re-scheduling raise exc_info[0], exc_info[1], exc_info[2] if model_update: volume_ref = self.db.volume_update( context, volume_ref['id'], model_update) if sourcevol_ref is not None: self.db.volume_glance_metadata_copy_from_volume_to_volume( context, source_volid, volume_id) LOG.debug(_("volume %s: creating export"), volume_ref['name']) model_update = self.driver.create_export(context, volume_ref) if model_update: self.db.volume_update(context, volume_ref['id'], model_update) except Exception: with excutils.save_and_reraise_exception(): volume_ref['status'] = 'error' self.db.volume_update(context, volume_ref['id'], {'status': volume_ref['status']}) LOG.error(_("volume %s: create failed"), volume_ref['name']) self._notify_about_volume_usage(context, volume_ref, "create.end") if snapshot_id: # Copy any Glance metadata from the original volume self.db.volume_glance_metadata_copy_to_volume(context, volume_ref['id'], snapshot_id) if image_id and image_meta: # Copy all of the Glance image properties to the # volume_glance_metadata table for future reference. self.db.volume_glance_metadata_create(context, volume_ref['id'], 'image_id', image_id) name = image_meta.get('name', None) if name: self.db.volume_glance_metadata_create(context, volume_ref['id'], 'image_name', name) # Save some more attributes into the volume metadata IMAGE_ATTRIBUTES = ['size', 'disk_format', 'container_format', 'checksum', 'min_disk', 'min_ram'] for key in IMAGE_ATTRIBUTES: value = image_meta.get(key, None) if value is not None: self.db.volume_glance_metadata_create(context, volume_ref['id'], key, value) image_properties = image_meta.get('properties', {}) for key, value in image_properties.items(): self.db.volume_glance_metadata_create(context, volume_ref['id'], key, value) now = timeutils.utcnow() volume_ref['status'] = status self.db.volume_update(context, volume_ref['id'], {'status': volume_ref['status'], 'launched_at': now}) LOG.info(_("volume %s: created successfully"), volume_ref['name']) self._reset_stats() self._notify_about_volume_usage(context, volume_ref, "create.end") return volume_ref['id']
def create_volume(self, context, volume_id, request_spec=None, filter_properties=None, allow_reschedule=True, snapshot_id=None, image_id=None, source_volid=None): """Creates and exports the volume.""" context_saved = context.deepcopy() context = context.elevated() if filter_properties is None: filter_properties = {} try: flow_engine = create_volume.get_manager_flow( context, self.db, self.driver, self.scheduler_rpcapi, self.host, volume_id, snapshot_id=snapshot_id, image_id=image_id, source_volid=source_volid, allow_reschedule=allow_reschedule, reschedule_context=context_saved, request_spec=request_spec, filter_properties=filter_properties) except Exception: LOG.exception(_("Failed to create manager volume flow")) raise exception.CinderException( _("Failed to create manager volume flow")) if snapshot_id is not None: # Make sure the snapshot is not deleted until we are done with it. locked_action = "%s-%s" % (snapshot_id, 'delete_snapshot') elif source_volid is not None: # Make sure the volume is not deleted until we are done with it. locked_action = "%s-%s" % (source_volid, 'delete_volume') else: locked_action = None def _run_flow(): # This code executes create volume flow. If something goes wrong, # flow reverts all job that was done and reraises an exception. # Otherwise, all data that was generated by flow becomes available # in flow engine's storage. flow_engine.run() @utils.synchronized(locked_action, external=True) def _run_flow_locked(): _run_flow() if locked_action is None: _run_flow() else: _run_flow_locked() # Fetch created volume from storage volume_ref = flow_engine.storage.fetch('volume') return volume_ref['id']