def convert_image(source, dest, out_format, run_as_root=True): """Convert image to other format.""" cmd = ('qemu-img', 'convert', '-O', out_format, source, dest) start_time = timeutils.utcnow() execute(*cmd, run_as_root=True) duration = timeutils.delta_seconds(start_time, timeutils.utcnow()) if duration < 1: duration = 1 try: image_size = qemu_img_info(source, run_as_root=True).virtual_size except ValueError as e: msg = _LI("The image was successfully converted, but image size " "is unavailable. src %(src)s, dest %(dest)s. %(error)s") LOG.info(msg, {"src": source, "dest": dest, "error": e}) return fsz_mb = image_size / units.Mi mbps = (fsz_mb / duration) msg = ("Image conversion details: src %(src)s, size %(sz).2f MB, " "duration %(duration).2f sec, destination %(dest)s") LOG.debug(msg, { "src": source, "sz": fsz_mb, "duration": duration, "dest": dest }) msg = _LI("Converted %(sz).2f MB image at %(mbps).2f MB/s") LOG.info(msg, {"sz": fsz_mb, "mbps": mbps})
def convert_image(source, dest, out_format, run_as_root=True): """Convert image to other format.""" cmd = ('qemu-img', 'convert', '-O', out_format, source, dest) start_time = timeutils.utcnow() execute(*cmd, run_as_root=True) duration = timeutils.delta_seconds(start_time, timeutils.utcnow()) if duration < 1: duration = 1 try: image_size = qemu_img_info(source, run_as_root=True).virtual_size except ValueError as e: msg = _LI("The image was successfully converted, but image size " "is unavailable. src %(src)s, dest %(dest)s. %(error)s") LOG.info(msg, {"src": source, "dest": dest, "error": e}) return fsz_mb = image_size / units.Mi mbps = (fsz_mb / duration) msg = ("Image conversion details: src %(src)s, size %(sz).2f MB, " "duration %(duration).2f sec, destination %(dest)s") LOG.debug(msg, {"src": source, "sz": fsz_mb, "duration": duration, "dest": dest}) msg = _LI("Converted %(sz).2f MB image at %(mbps).2f MB/s") LOG.info(msg, {"sz": fsz_mb, "mbps": mbps})
def get_filtered_objects(self, filter_classes, objs, filter_properties, index=0): """Get objects after filter :param filter_classes: filters that will be used to filter the objects :param objs: objects that will be filtered :param filter_properties: client filter properties :param index: This value needs to be increased in the caller function of get_filtered_objects when handling each resource. """ list_objs = list(objs) LOG.debug("Starting with %d host(s)", len(list_objs)) for filter_cls in filter_classes: cls_name = filter_cls.__name__ filter_class = filter_cls() if filter_class.run_filter_for_index(index): objs = filter_class.filter_all(list_objs, filter_properties) if objs is None: LOG.debug("Filter %(cls_name)s says to stop filtering", {'cls_name': cls_name}) return list_objs = list(objs) msg = (_LI("Filter %(cls_name)s returned %(obj_len)d host(s)") % {'cls_name': cls_name, 'obj_len': len(list_objs)}) if not list_objs: LOG.info(msg) break LOG.debug(msg) return list_objs
def __init__(self, destination_driver=None, service_name=None, *args, **kwargs): """Load the destination driver.""" # updated_service_capabilities needs service_name to be "source". super(DestinationManager, self).__init__(service_name='destination', *args, **kwargs) self.configuration = config.Configuration(destination_manager_opts, config_group=service_name) self.stats = {} if not destination_driver: # Get from configuration, which will get the default # if its not using the multi backend. destination_driver = self.configuration.destination_driver svc_host = utils.extract_host(self.host) try: objects.Service.get_by_args(context.get_admin_context(), svc_host, 'guts-destination') except exception.ServiceNotFound: LOG.info(_LI("Service not found for updating.")) self.driver = importutils.import_object( destination_driver, configuration=self.configuration, host=self.host)
def resource_fetch(self, ctxt, cloud): """Fetches list of resources from given Clouds.""" if cloud.type != "source": LOG.warning(_LW('Cloud %(cloud_name)s is not a Source Cloud.'), {'cloud_name': cloud.name}) LOG.info(_LI("Fetching resources from the Cloud %(cloud_name)s."), {'cloud_name': cloud.name}) self._resource_fetch(ctxt, cloud)
def __init__(self, service_name=None, *args, **kwargs): super(MigrationManager, self).__init__(service_name='migration', *args, **kwargs) try: svc_host = utils.extract_host(self.host) objects.Service.get_by_args(context.get_admin_context(), svc_host, 'guts-migration') except exception.ServiceNotFound: LOG.info(_LI("Service not found for updating."))
def prop_update(self, ctxt, cloud): """Updates properties of the Cloud.""" if cloud.type != "destination": LOG.warning(_LW('Cloud %(cloud)s is not a destination Cloud.'), {'cloud': cloud.name}) return LOG.info(_LI("Fetching resources from the Cloud %(cloud)s."), {'cloud': cloud.name}) self._prop_update(ctxt, cloud)
def _get_network(self, context, migration_ref, resource_ref, dest_host): network_info = ast.literal_eval(resource_ref.properties) LOG.info(_LI('Getting network information from source hypervisor, ' 'network_info: %s'), network_info) migration_ref.migration_status = "Inprogress" migration_ref.migration_event = "Fetching from source" migration_ref.save() _cast_to_destination(context, dest_host, 'create_network', migration_ref, resource_ref, **network_info)
def register(self, ext): # Do nothing if the extension doesn't check out if not self._check_extension(ext): return alias = ext.alias LOG.info(_LI('Loaded extension: %s'), alias) if alias in self.extensions: raise exception.Error("Found duplicate extension: %s" % alias) self.extensions[alias] = ext
def _convert_disks(self, disks): LOG.info(_LI('Disk conversion started: %s'), disks) converted_disks = [] for disk in disks: index = disk.keys()[0] path = disk[index] disk[index] = path.replace('.vmdk', '.qcow2') utils.convert_image(path, disk[index], 'qcow2', run_as_root=False) converted_disks.append(disk) return converted_disks
def delete(self, req, id): """Deletes a Migration""" context = req.environ['guts.context'] LOG.info(_LI("Deleting migration with ID: %s"), id, context=context) try: migration = objects.Migration.get_by_id(context, id) migration.destroy() except exception.MigrationNotFound as error: raise exc.HTTPNotFound(explanation=error.msg) return webob.Response(status_int=202)
def __exit__(self, ex_type, ex_value, ex_traceback): if not ex_value: return True if isinstance(ex_value, exception.NotAuthorized): raise Fault(webob.exc.HTTPForbidden(explanation=ex_value.msg)) elif isinstance(ex_value, exception.Invalid): raise Fault(exception.ConvertedException(code=ex_value.code, explanation=ex_value.msg)) elif isinstance(ex_value, TypeError): exc_info = (ex_type, ex_value, ex_traceback) LOG.error(_LE("Exception handling resource: %s"), ex_value, exc_info=exc_info) raise Fault(webob.exc.HTTPBadRequest()) elif isinstance(ex_value, Fault): LOG.info(_LI("Fault thrown: %s"), ex_value) raise ex_value elif isinstance(ex_value, webob.exc.HTTPException): LOG.info(_LI("HTTP exception thrown: %s"), ex_value) raise Fault(ex_value) # We didn't handle the exception return False
def __call__(self, request): """WSGI method that controls (de)serialization and method dispatch.""" LOG.info(_LI("%(method)s %(url)s"), {"method": request.method, "url": request.url}) # Identify the action, its arguments, and the requested # content type action_args = self.get_action_args(request.environ) action = action_args.pop("action", None) content_type, body = self.get_body(request) accept = request.best_match_content_type() return self._process_stack(request, action, action_args, content_type, body, accept)
def _get_instance(self, context, migration_ref, resource_ref, dest_host): instance_id = resource_ref.id_at_source LOG.info(_LI('Getting instance from source hypervisor, ' 'instance_id: %s'), instance_id) migration_ref.save() instance_disks = self.driver.get_instance(context, instance_id) instance_disks = self._convert_disks(instance_disks) instance_info = ast.literal_eval(resource_ref.properties) instance_info['disks'] = instance_disks _cast_to_destination(context, dest_host, 'create_instance', migration_ref, resource_ref, **instance_info)
def stop(self): """Stop this server. This is not a very nice action, as currently the method by which a server is stopped is by killing its eventlet. :returns: None """ LOG.info(_LI("Stopping WSGI server.")) if self._server is not None: # Resize pool to stop new requests from being processed self._pool.resize(0) self._server.kill()
def _get_volume(self, context, migration_ref, resource_ref, dest_host): volume_id = resource_ref.id_at_source LOG.info(_LI('Getting volume from source hypervisor, ' 'volume_id: %s'), volume_id) migration_ref.migration_status = "Inprogress" migration_ref.migration_event = "Fetching from source" migration_ref.save() volume_path = self.driver.get_volume(context, volume_id, migration_ref.id) volume_info = ast.literal_eval(resource_ref.properties) volume_info['path'] = volume_path _cast_to_destination(context, dest_host, 'create_volume', migration_ref, resource_ref, **volume_info)
def wait(self): """Block, until the server has stopped. Waits on the server's eventlet to finish, then returns. :returns: None """ try: if self._server is not None: self._pool.waitall() self._server.wait() except greenlet.GreenletExit: LOG.info(_LI("WSGI server has stopped."))
def init_host(self): """Perform any required initialization.""" ctxt = context.get_admin_context() LOG.info(_LI("Starting destination driver %(driver_name)s."), {'driver_name': self.driver.__class__.__name__}) try: self.driver.do_setup(ctxt) except Exception: LOG.exception(_LE("Failed to initialize driver."), resource={'type': 'driver', 'id': self.__class__.__name__}) # we don't want to continue since we failed # to initialize the driver correctly. return self.publish_service_capabilities(ctxt)
def start(self): version_string = version.version_string() LOG.info(_LI('Starting %(topic)s node (version %(version_string)s)'), { 'topic': self.topic, 'version_string': version_string }) self.model_disconnected = False self.manager.init_host() ctxt = context.get_admin_context() try: service_ref = objects.Service.get_by_args(ctxt, self.host, self.binary) self.service_id = service_ref.id except exception.NotFound: self._create_service_ref(ctxt) LOG.debug("Creating RPC server for service %s", self.topic) target = messaging.Target(topic=self.topic, server=self.host) endpoints = [self.manager] endpoints.extend(self.manager.additional_endpoints) serializer = objects_base.GutsObjectSerializer() self.rpcserver = rpc.get_server(target, endpoints, serializer) self.rpcserver.start() self.manager.init_host_with_rpc() if self.report_interval: pulse = loopingcall.FixedIntervalLoopingCall(self.report_state) pulse.start(interval=self.report_interval, initial_delay=self.report_interval) self.timers.append(pulse) if self.periodic_interval: if self.periodic_fuzzy_delay: initial_delay = random.randint(0, self.periodic_fuzzy_delay) else: initial_delay = None periodic = loopingcall.FixedIntervalLoopingCall( self.periodic_tasks) periodic.start(interval=self.periodic_interval, initial_delay=initial_delay) self.timers.append(periodic)
def _error(self, inner, req): safe = getattr(inner, 'safe', False) headers = getattr(inner, 'headers', None) status = getattr(inner, 'code', 500) if status is None: status = 500 msg_dict = dict(url=req.url, status=status) LOG.info(_LI("%(url)s returned with HTTP %(status)d"), msg_dict) outer = self.status_to_type(status) if headers: outer.headers = headers if safe: msg = (inner.msg if isinstance(inner, exception.GutsException) else six.text_type(inner)) params = {'exception': inner.__class__.__name__, 'explanation': msg} outer.explanation = _('%(exception)s: %(explanation)s') % params return wsgi.Fault(outer)
def start(self): version_string = version.version_string() LOG.info(_LI('Starting %(topic)s node (version %(version_string)s)'), {'topic': self.topic, 'version_string': version_string}) self.model_disconnected = False self.manager.init_host() ctxt = context.get_admin_context() try: service_ref = objects.Service.get_by_args( ctxt, self.host, self.binary) self.service_id = service_ref.id except exception.NotFound: self._create_service_ref(ctxt) LOG.debug("Creating RPC server for service %s", self.topic) target = messaging.Target(topic=self.topic, server=self.host) endpoints = [self.manager] endpoints.extend(self.manager.additional_endpoints) serializer = objects_base.GutsObjectSerializer() self.rpcserver = rpc.get_server(target, endpoints, serializer) self.rpcserver.start() self.manager.init_host_with_rpc() if self.report_interval: pulse = loopingcall.FixedIntervalLoopingCall( self.report_state) pulse.start(interval=self.report_interval, initial_delay=self.report_interval) self.timers.append(pulse) if self.periodic_interval: if self.periodic_fuzzy_delay: initial_delay = random.randint(0, self.periodic_fuzzy_delay) else: initial_delay = None periodic = loopingcall.FixedIntervalLoopingCall( self.periodic_tasks) periodic.start(interval=self.periodic_interval, initial_delay=initial_delay) self.timers.append(periodic)
def create_instance(self, context, **kwargs): """Create a new instance.""" LOG.info(_LI('Create instance started.')) migration_ref = kwargs.pop('migration_ref') resource_ref = kwargs.pop('resource_ref') migration_ref.migration_event = 'Creating at destination' migration_ref.save() kwargs['mig_ref_id'] = migration_ref.id try: self.driver.create_instance(context, **kwargs) except exception.NetworkCreationFailed: migration_ref.migration_status = 'ERROR' migration_ref.migration_event = None migration_ref.save() raise migration_ref.migration_status = 'COMPLETE' migration_ref.migration_event = None migration_ref.save() resource_ref.migrated = True resource_ref.save()
def create_network(self, context, **kwargs): """Creates new network on destination OpenStack hypervisor.""" LOG.info(_LI('Create network started, network: %s.'), kwargs['id']) del kwargs['id'] del kwargs['name'] migration_ref = kwargs.pop('migration_ref') resource_ref = kwargs.pop('resource_ref') migration_ref.migration_event = 'Creating at destination' migration_ref.save() try: self.driver.create_network(context, **kwargs) except exception.NetworkCreationFailed: migration_ref.migration_status = 'ERROR' migration_ref.migration_event = None migration_ref.save() raise migration_ref.migration_status = 'COMPLETE' migration_ref.migration_event = None migration_ref.save() resource_ref.migrated = True resource_ref.save()
def create_volume(self, context, **kwargs): """Creats volume on destination OpenStack hypervisor.""" LOG.info(_LI('Create volume started, volume: %s.'), kwargs['id']) del kwargs['id'] migration_ref = kwargs.pop('migration_ref') resource_ref = kwargs.pop('resource_ref') migration_ref.migration_event = 'Creating at destination' migration_ref.save() kwargs['mig_ref_id'] = migration_ref.id try: self.driver.create_volume(context, **kwargs) except exception.NetworkCreationFailed: migration_ref.migration_status = 'ERROR' migration_ref.migration_event = None migration_ref.save() raise migration_ref.migration_status = 'COMPLETE' migration_ref.migration_event = None migration_ref.save() resource_ref.migrated = True resource_ref.save()
def _update_host_state_map(self, context): # Get resource usage across the available nodes: sources = objects.ServiceList.get_all_by_topic(context, CONF.source_topic, disabled=False) dests = objects.ServiceList.get_all_by_topic(context, CONF.destination_topic, disabled=False) active_hosts = set() no_capabilities_hosts = set() for service in sources.objects + dests.objects: host = service.host if not utils.service_is_up(service): LOG.warning(_LW("Service is down. (host: %s)"), host) continue capabilities = self.service_states.get(host, None) if capabilities is None: no_capabilities_hosts.add(host) continue host_state = self.host_state_map.get(host) if not host_state: host_state = self.host_state_cls(host, capabilities=capabilities, service=dict(service)) self.host_state_map[host] = host_state # update capabilities and attributes in host_state host_state.update_from_migration_capability(capabilities, service=dict(service)) active_hosts.add(host) self._no_capabilities_hosts = no_capabilities_hosts # remove non-active hosts from host_state_map nonactive_hosts = set(self.host_state_map.keys()) - active_hosts for host in nonactive_hosts: LOG.info(_LI("Removing non-active host: %(host)s from " "scheduler cache."), {'host': host}) del self.host_state_map[host]
def get_filtered_objects(self, filter_classes, objs, filter_properties, index=0): """Get objects after filter :param filter_classes: filters that will be used to filter the objects :param objs: objects that will be filtered :param filter_properties: client filter properties :param index: This value needs to be increased in the caller function of get_filtered_objects when handling each resource. """ list_objs = list(objs) LOG.debug("Starting with %d host(s)", len(list_objs)) for filter_cls in filter_classes: cls_name = filter_cls.__name__ filter_class = filter_cls() if filter_class.run_filter_for_index(index): objs = filter_class.filter_all(list_objs, filter_properties) if objs is None: LOG.debug("Filter %(cls_name)s says to stop filtering", {'cls_name': cls_name}) return list_objs = list(objs) msg = ( _LI("Filter %(cls_name)s returned %(obj_len)d host(s)") % { 'cls_name': cls_name, 'obj_len': len(list_objs) }) if not list_objs: LOG.info(msg) break LOG.debug(msg) return list_objs
def _process_stack(self, request, action, action_args, content_type, body, accept): """Implement the processing stack.""" # Get the implementing method try: meth, extensions = self.get_method(request, action, content_type, body) except (AttributeError, TypeError): return Fault(webob.exc.HTTPNotFound()) except KeyError as ex: msg = _("There is no such action: %s") % ex.args[0] return Fault(webob.exc.HTTPBadRequest(explanation=msg)) except exception.MalformedRequestBody: msg = _("Malformed request body") return Fault(webob.exc.HTTPBadRequest(explanation=msg)) # Now, deserialize the request body... try: if content_type: contents = self.deserialize(meth, content_type, body) else: contents = {} except exception.InvalidContentType: msg = _("Unsupported Content-Type") return Fault(webob.exc.HTTPBadRequest(explanation=msg)) except exception.MalformedRequestBody: msg = _("Malformed request body") return Fault(webob.exc.HTTPBadRequest(explanation=msg)) # Update the action args action_args.update(contents) project_id = action_args.pop("project_id", None) context = request.environ.get('guts.context') if (context and project_id and (project_id != context.project_id)): msg = _("Malformed request url") return Fault(webob.exc.HTTPBadRequest(explanation=msg)) # Run pre-processing extensions response, post = self.pre_process_extensions(extensions, request, action_args) if not response: try: with ResourceExceptionHandler(): action_result = self.dispatch(meth, request, action_args) except Fault as ex: response = ex if not response: # No exceptions; convert action_result into a # ResponseObject resp_obj = None if type(action_result) is dict or action_result is None: resp_obj = ResponseObject(action_result) elif isinstance(action_result, ResponseObject): resp_obj = action_result else: response = action_result # Run post-processing extensions if resp_obj: _set_request_id_header(request, resp_obj) # Do a preserialize to set up the response object serializers = getattr(meth, 'wsgi_serializers', {}) resp_obj._bind_method_serializers(serializers) if hasattr(meth, 'wsgi_code'): resp_obj._default_code = meth.wsgi_code resp_obj.preserialize(accept, self.default_serializers) # Process post-processing extensions response = self.post_process_extensions(post, resp_obj, request, action_args) if resp_obj and not response: response = resp_obj.serialize(request, accept, self.default_serializers) try: msg_dict = dict(url=request.url, status=response.status_int) msg = _LI("%(url)s returned with HTTP %(status)d") except AttributeError as e: msg_dict = dict(url=request.url, e=e) msg = _LI("%(url)s returned a fault: %(e)s") LOG.info(msg, msg_dict) return response
def __init__(self): LOG.info(_LI('Initializing extension manager.')) self.cls_list = CONF.osapi_migration_extension self.extensions = {} self._load_extensions()
def __init__( self, name, app, host=None, port=None, pool_size=None, protocol=eventlet.wsgi.HttpProtocol, backlog=128 ): """Initialize, but do not start, a WSGI server. :param name: Pretty name for logging. :param app: The WSGI application to serve. :param host: IP address to serve the application. :param port: Port number to server the application. :param pool_size: Maximum number of eventlets to spawn concurrently. :returns: None """ # Allow operators to customize http requests max header line size. eventlet.wsgi.MAX_HEADER_LINE = CONF.max_header_line self.client_socket_timeout = CONF.client_socket_timeout or None self.name = name self.app = app self._host = host or "0.0.0.0" self._port = port or 0 self._server = None self._socket = None self._protocol = protocol self.pool_size = pool_size or self.default_pool_size self._pool = eventlet.GreenPool(self.pool_size) self._logger = logging.getLogger("eventlet.wsgi.server") if backlog < 1: raise exception.InvalidInput(reason="The backlog must be more than 1") bind_addr = (host, port) try: info = socket.getaddrinfo(bind_addr[0], bind_addr[1], socket.AF_UNSPEC, socket.SOCK_STREAM)[0] family = info[0] bind_addr = info[-1] except Exception: family = socket.AF_INET cert_file = CONF.ssl_cert_file key_file = CONF.ssl_key_file ca_file = CONF.ssl_ca_file self._use_ssl = cert_file or key_file if cert_file and not os.path.exists(cert_file): raise RuntimeError(_("Unable to find cert_file : %s") % cert_file) if ca_file and not os.path.exists(ca_file): raise RuntimeError(_("Unable to find ca_file : %s") % ca_file) if key_file and not os.path.exists(key_file): raise RuntimeError(_("Unable to find key_file : %s") % key_file) if self._use_ssl and (not cert_file or not key_file): raise RuntimeError( _( "When running server in SSL mode, you " "must specify both a cert_file and " "key_file option value in your " "configuration file." ) ) retry_until = time.time() + 30 while not self._socket and time.time() < retry_until: try: self._socket = eventlet.listen(bind_addr, backlog=backlog, family=family) except socket.error as err: if err.args[0] != errno.EADDRINUSE: raise eventlet.sleep(0.1) if not self._socket: raise RuntimeError( _("Could not bind to %(host)s:%(port)s " "after trying for 30 seconds") % {"host": host, "port": port} ) (self._host, self._port) = self._socket.getsockname()[0:2] LOG.info( _LI("%(name)s listening on %(_host)s:%(_port)s"), {"name": self.name, "_host": self._host, "_port": self._port}, )
def _create_migration(self, ctxt, migration_ref): """ Migration setps: Step - 1: Get resource object, R Step - 2: Get the source cloud, S Step - 3: Get the destination cloud, D Step - 4: Check if D is destination Step - 5: Check if S support R migration Step - 6: Check if D support R migration Step - 7: Load source driver, source_driver Step - 8: Load destination driver, dest_driver Step - 9: Call R's migration method """ utils.migration_status_update(migration_ref, 'INITIATING', 'validating') try: # NOTE(Step - 1): Get resource object, R resource = objects.Resource.get_by_id(ctxt, migration_ref.resource_id) # NOTE(Step - 2): Get the source cloud, S source = objects.Cloud.get_by_id(ctxt, resource.cloud_id) # NOTE(Step - 3): Get the destination cloud, D dest = objects.Cloud.get_by_id(ctxt, migration_ref.destination_cloud_id) except exception.GutsException as error: LOG.exception(error.message) utils.migration_status_update(migration_ref, 'FAILED', '-', error.message) raise exception.MigrationFailed(messaage=error.message) except Exception as error: LOG.exception(error.message) utils.migration_status_update(migration_ref, 'FAILED', '-', error.message) raise exception.MigrationFailed(message=error.message) LOG.info(_LI('Starting %(r_name)s migration from %(s_name)s cloud ' 'to %(d_name)s cloud.') % {'r_name': resource.name, 's_name': source.name, 'd_name': dest.name}) # NOTE(Step - 4): Verify D supports R migration if dest.type != "destination": msg = (_('Cloud %(cloud_name)s is not a destination Cloud.'), {'cloud_name': dest.name}) LOG.exception(msg) utils.migration_status_update(migration_ref, 'FAILED', '-', msg) raise exception.MigrationFailed(message=msg) # NOTE(Step - 5): Check if S support R migration if resource.type not in ast.literal_eval(source.capabilities): msg = (_('%(resource_type)s resource migration not supported by ' 'the source cloud %(cloud_name)s.'), {'resource_type': resource.type, 'cloud_name': source.name}) LOG.exception(msg) utils.migration_status_update(migration_ref, 'FAILED', '-', msg) raise exception.MigrationFailed(message=msg) # NOTE(Step - 6): Check if D support R migration if resource.type not in ast.literal_eval(dest.capabilities): msg = (_('%(resource_type)s resource migration not supported by ' 'the destination cloud %(cloud_name)s.'), {'resource_type': resource.type, 'cloud_name': dest.name}) LOG.exception(msg) utils.migration_status_update(migration_ref, 'FAILED', '-', msg) raise exception.MigrationFailed(message=msg) # NOTE(Step - 7): Load source driver, source_driver try: source_driver = importutils.import_object(source.driver, cloud=source) except Exception: msg = (_('Failed to load source driver: %s') % source.driver) LOG.exception(msg) utils.migration_status_update(migration_ref, 'FAILED', '-', msg) raise exception.MigrationFailed(message=msg) # NOTE(Step - 8): Load destination driver, dest_driver try: dest_driver = importutils.import_object(dest.driver, cloud=dest) except Exception: msg = (_('Failed to load destination driver: %s') % dest.driver) LOG.exception(msg) utils.migration_status_update(migration_ref, 'FAILED', '-', msg) raise exception.MigrationFailed(message=msg) # NOTE(Step - 9): Call migration method try: self._migrate_resource(migration_ref, resource, source_driver, dest_driver) except AttributeError: msg = (_('Method %(name)s not implemented in the manager:') % {'name': method_name}) LOG.exception(msg) utils.migration_status_update(migration_ref, 'FAILED', '-', msg) raise exception.MigrationFailed(message=msg) except exception.OpenStackException as error: msg = (_('Failed fetch resource %(r_name)s properties from ' '%(s_name)s cloud: %(err)s') % {'r_name': resource.name, 's_name': source.name, 'err': error}) LOG.exception(msg) utils.migration_status_update(migration_ref, 'FAILED', '-', msg) raise exception.MigrationFailed(message=msg)
def update_cloud(self, context, id, name=None, driver=None, type=None, capabilities=None, enabled=None, params=None): """Updates a cloud""" check_policy(context, 'update_cloud') cloud_obj = objects.Cloud.get_by_id(context, id) old_capabs = ast.literal_eval(cloud_obj.capabilities) updates = {} if name: updates['name'] = name # Driver path if driver: try: driver_cls = importutils.import_class(driver) except ImportError: msg = _('Unable to import driver class %s') % driver raise exception.InvalidInput(reason=msg) # Driver type validation if issubclass(driver_cls, m_driver.SourceDriver): if type and type != 'source': msg = _("Invalid driver type %s") % type raise exception.InvalidInput(reason=msg) else: type = 'source' elif issubclass(driver_cls, m_driver.DestinationDriver): if type and type != 'destination': msg = _("Invalid driver type %s") % type raise exception.InvalidInput(reason=msg) else: type = 'destination' else: msg = _("Invalid driver class path %s") % driver raise exception.InvalidInput(reason=msg) updates['driver'] = driver if not capabilities: capabilities = cloud_obj.capabilities if not params: params = cloud_obj.params else: driver_cls = importutils.import_class(cloud_obj.driver) if 'driver' in updates: # Existing capabilities validation against new driver for capab in capabilities: if capab not in driver_cls.DRIVER_CAPABILITIES: msg = (_("Specified capability %s not supported by the " "driver") % (capab, driver)) raise exception.InvalidInput(reason=msg) updates['capabilities'] = str(capabilities) # Existing params validation against new driver try: con_params = driver_cls.validate_params(params, capabilities) except exception.MigrationDriverException as error: raise exception.InvalidInput(reason=error.msg) updates['params'] = con_params else: if capabilities: for capab in capabilities: if capab not in driver_cls.DRIVER_CAPABILITIES: msg = (_("Specified capability %(capab)s not supported" " by the driver %(dri)s") % {'capab': capab, 'dri': driver}) raise exception.InvalidInput(reason=msg) updates['capabilities'] = str(capabilities) if params: # Connection params validation old_params = cloud_obj.params.copy() old_params.update(params) try: con_params = driver_cls.validate_params( old_params, capabilities or cloud_obj.capabilities) except exception.MigrationDriverException as error: raise exception.InvalidInput(reason=error.msg) updates['params'] = con_params if enabled is not None: updates['enabled'] = enabled cloud_obj.update(updates) cloud_obj.save() if cloud_obj.enabled: if cloud_obj.type == "source": self.scheduler_rpcapi.resource_fetch(context, clouds=[cloud_obj]) self._delete_existing_capab_resources(context, cloud_obj, old_capabs) elif cloud_obj.type == "destination": self.scheduler_rpcapi.cloud_prop_update(context, clouds=[cloud_obj]) else: # Delete all existing resources from cloud, when its disabled. self._delete_resources(context, cloud_obj.id) LOG.info(_LI("Cloud updated successfully.")) return cloud_obj
def __init__(self, name, app, host=None, port=None, pool_size=None, protocol=eventlet.wsgi.HttpProtocol, backlog=128): """Initialize, but do not start, a WSGI server. :param name: Pretty name for logging. :param app: The WSGI application to serve. :param host: IP address to serve the application. :param port: Port number to server the application. :param pool_size: Maximum number of eventlets to spawn concurrently. :returns: None """ # Allow operators to customize http requests max header line size. eventlet.wsgi.MAX_HEADER_LINE = CONF.max_header_line self.client_socket_timeout = CONF.client_socket_timeout or None self.name = name self.app = app self._host = host or "0.0.0.0" self._port = port or 0 self._server = None self._socket = None self._protocol = protocol self.pool_size = pool_size or self.default_pool_size self._pool = eventlet.GreenPool(self.pool_size) self._logger = logging.getLogger("eventlet.wsgi.server") if backlog < 1: raise exception.InvalidInput( reason='The backlog must be more than 1') bind_addr = (host, port) try: info = socket.getaddrinfo(bind_addr[0], bind_addr[1], socket.AF_UNSPEC, socket.SOCK_STREAM)[0] family = info[0] bind_addr = info[-1] except Exception: family = socket.AF_INET cert_file = CONF.ssl_cert_file key_file = CONF.ssl_key_file ca_file = CONF.ssl_ca_file self._use_ssl = cert_file or key_file if cert_file and not os.path.exists(cert_file): raise RuntimeError(_("Unable to find cert_file : %s") % cert_file) if ca_file and not os.path.exists(ca_file): raise RuntimeError(_("Unable to find ca_file : %s") % ca_file) if key_file and not os.path.exists(key_file): raise RuntimeError(_("Unable to find key_file : %s") % key_file) if self._use_ssl and (not cert_file or not key_file): raise RuntimeError( _("When running server in SSL mode, you " "must specify both a cert_file and " "key_file option value in your " "configuration file.")) retry_until = time.time() + 30 while not self._socket and time.time() < retry_until: try: self._socket = eventlet.listen(bind_addr, backlog=backlog, family=family) except socket.error as err: if err.args[0] != errno.EADDRINUSE: raise eventlet.sleep(0.1) if not self._socket: raise RuntimeError( _("Could not bind to %(host)s:%(port)s " "after trying for 30 seconds") % { 'host': host, 'port': port }) (self._host, self._port) = self._socket.getsockname()[0:2] LOG.info(_LI("%(name)s listening on %(_host)s:%(_port)s"), { 'name': self.name, '_host': self._host, '_port': self._port })