def main(): objects.register_all() CONF(sys.argv[1:], project='guts', version=version.version_string()) logging.setup(CONF, "guts") LOG = logging.getLogger('guts.all') utils.monkey_patch() gmr.TextGuruMeditation.setup_autorun(version) rpc.init(CONF) launcher = service.process_launcher() # guts-api try: server = service.WSGIService('osapi_migration') launcher.launch_service(server, workers=server.workers or 1) except (Exception, SystemExit): LOG.exception(_LE('Failed to load osapi_migration')) # guts-migration try: launcher.launch_service( service.Service.create(binary='guts-migration')) except (Exception, SystemExit): LOG.exception(_LE('Failed to load guts-migration')) launcher.wait()
def __init__(self, message=None, **kwargs): self.kwargs = kwargs self.kwargs['message'] = message if 'code' not in self.kwargs: try: self.kwargs['code'] = self.code except AttributeError: pass for k, v in self.kwargs.items(): if isinstance(v, Exception): self.kwargs[k] = six.text_type(v) if self._should_format(): try: message = self.message % kwargs except Exception: exc_info = sys.exc_info() # kwargs doesn't match a variable in the message # log the issue and the kwargs LOG.exception(_LE('Exception in string format operation')) for name, value in kwargs.items(): LOG.error(_LE("%(name)s: %(value)s"), {'name': name, 'value': value}) if CONF.fatal_exception_format_errors: six.reraise(*exc_info) # at least get the core message out if something happened message = self.message elif isinstance(message, Exception): message = six.text_type(message) self.msg = message super(GutsException, self).__init__(message)
def create_migration(self, context, migration_ref, request_spec=None, filter_properties=None): self._wait_for_scheduler() try: self.driver.schedule_create_migration(context, migration_ref, request_spec, filter_properties) except exception.NoValidHost: LOG.error(_LE("Could not found a host to create migration.")) except Exception: LOG.exception(_LE("Migration %(mig_id)s failed for the resource: " "%(id)s.") % {'mig_id': migration_ref.id, 'id': migration_ref.resource_id})
def report_state(self): """Update the state of this service in the datastore.""" if not self.manager.is_working(): # NOTE(dulek): If manager reports a problem we're not sending # heartbeats - to indicate that service is actually down. LOG.error( _LE('Manager for service %(binary)s %(host)s is ' 'reporting problems, not sending heartbeat. ' 'Service will appear "down".'), { 'binary': self.binary, 'host': self.host }) return ctxt = context.get_admin_context() try: try: service_ref = objects.Service.get_by_id(ctxt, self.service_id) except exception.NotFound: LOG.debug('The service database object disappeared, ' 'recreating it.') self._create_service_ref(ctxt) service_ref = objects.Service.get_by_id(ctxt, self.service_id) service_ref.report_count += 1 service_ref.save() # TODO(termie): make this pattern be more elegant. if getattr(self, 'model_disconnected', False): self.model_disconnected = False LOG.error(_LE('Recovered model server connection!')) except db_exc.DBConnectionError: if not getattr(self, 'model_disconnected', False): self.model_disconnected = True LOG.exception(_LE('model server went away')) # NOTE(jsbryant) Other DB errors can happen in HA configurations. # such errors shouldn't kill this thread, so we handle them here. except db_exc.DBError: if not getattr(self, 'model_disconnected', False): self.model_disconnected = True LOG.exception(_LE('DBError encountered: ')) except Exception: if not getattr(self, 'model_disconnected', False): self.model_disconnected = True LOG.exception(_LE('Exception encountered: '))
def resource_fetch(self, context, clouds, request_spec=None, filter_properties=None): self._wait_for_scheduler() if not clouds: clouds = objects.CloudList.get_all(context, filters={'type': 'source'}) try: for cloud in clouds: self.driver.schedule_resource_fetch(context, cloud, request_spec, filter_properties) except exception.NoValidHost: LOG.error(_LE("Could not found a host for resource fetch.")) except Exception: LOG.exception(_LE("Failed to fetch resources from the Cloud " "%(cloud)s."), {'cloud': cloud.id})
def _load_file(self, handle): """Decode the JSON file. Broken out for testing.""" try: return json.load(handle) except ValueError: LOG.exception(_LE("Could not decode scheduler options.")) return {}
def get_method(self, request, action, content_type, body): """Look up the action-specific method and its extensions.""" try: if not self.controller: meth = getattr(self, action) else: meth = getattr(self.controller, action) except AttributeError as e: with excutils.save_and_reraise_exception(e) as ctxt: if (not self.wsgi_actions or action not in ['action', 'create', 'delete', 'update']): LOG.exception(_LE('Get method error.')) else: ctxt.reraise = False else: return meth, self.wsgi_extensions.get(action, []) if action == 'action': # OK, it's an action; figure out which action... mtype = _MEDIA_TYPE_MAP.get(content_type) action_name = self.action_peek[mtype](body) LOG.debug("Action body: %s", body) else: action_name = action # Look up the action method return (self.wsgi_actions[action_name], self.wsgi_action_extensions.get(action_name, []))
def create(ctxt, name, source_instance_id, description=None): """Creates migration. Raises: MigrationCreateFailed: If there is error during migration creation. InstanceNotReadyForMigration: Migrating instance failed pre-migration validations """ try: migration_ref = db.migration_create( ctxt, dict(name=name, source_instance_id=source_instance_id, description=description)) except db_exc.DBError: LOG.exception(_LE('DB error:')) raise exception.MigrationCreateFailed(name=name) migration_api = migration_rpcapi.MigrationAPI() try: migration_api.validate_for_migration(ctxt, migration_ref) except messaging.RemoteError as ex: raise exception.InstanceNotReadyForMigration(name=name, reason=six.text_type( ex.value)) migration_api.create_migration(ctxt, migration_ref) return migration_ref
def report_state(self): """Update the state of this service in the datastore.""" if not self.manager.is_working(): # NOTE(dulek): If manager reports a problem we're not sending # heartbeats - to indicate that service is actually down. LOG.error(_LE('Manager for service %(binary)s %(host)s is ' 'reporting problems, not sending heartbeat. ' 'Service will appear "down".'), {'binary': self.binary, 'host': self.host}) return ctxt = context.get_admin_context() try: try: service_ref = objects.Service.get_by_id(ctxt, self.service_id) except exception.NotFound: LOG.debug('The service database object disappeared, ' 'recreating it.') self._create_service_ref(ctxt) service_ref = objects.Service.get_by_id(ctxt, self.service_id) service_ref.report_count += 1 service_ref.save() # TODO(termie): make this pattern be more elegant. if getattr(self, 'model_disconnected', False): self.model_disconnected = False LOG.error(_LE('Recovered model server connection!')) except db_exc.DBConnectionError: if not getattr(self, 'model_disconnected', False): self.model_disconnected = True LOG.exception(_LE('model server went away')) # NOTE(jsbryant) Other DB errors can happen in HA configurations. # such errors shouldn't kill this thread, so we handle them here. except db_exc.DBError: if not getattr(self, 'model_disconnected', False): self.model_disconnected = True LOG.exception(_LE('DBError encountered: ')) except Exception: if not getattr(self, 'model_disconnected', False): self.model_disconnected = True LOG.exception(_LE('Exception encountered: '))
def _get_file_timestamp(self, filename): """Get the last modified datetime. Broken out for testing.""" try: return os.path.getmtime(filename) except os.error: LOG.exception( _LE("Could not stat scheduler options file " "%(filename)s."), {'filename': filename}) raise
def create_network(self, context, **kwargs): if not self._initialized: self.do_setup(context) try: self.nova.networks.create(**kwargs) except Exception as e: LOG.error(_LE("Failed to create network '%s' on " "destination: %s"), kwargs['label'], e) raise exception.NetworkCreationFailed(reason=e.message)
def _get_file_timestamp(self, filename): """Get the last modified datetime. Broken out for testing.""" try: return os.path.getmtime(filename) except os.error: LOG.exception(_LE("Could not stat scheduler options file " "%(filename)s."), {'filename': filename}) raise
def _resource_fetch_by_capab(self, ctxt, cloud, capab): driver = importutils.import_object(cloud.driver, cloud=cloud) try: resources = driver.resource_fetch(resource_type=capab) self.update_resources(ctxt, cloud.id, capab, resources) except Exception as error: msg = (_("Failed to fetch %(capab)ss from the cloud: %(cloud)s. " "Reason: %(reason)s.") % {'capab': capab, 'cloud': cloud.id, 'reason': error}) LOG.exception(_LE('%s') % (msg))
def create(ctxt, name, stype, connection_params, description=None): """Creates source.""" try: source_ref = db.source_create( ctxt, dict(name=name, source_type_id=stype, connection_params=connection_params, description=description) ) except db_exc.DBError: LOG.exception(_LE("DB error:")) raise exception.SourceCreateFailed(name=name) return source_ref
def create(ctxt, name, driver, description=None): """Creates source types.""" try: type_ref = db.source_type_create( ctxt, dict(name=name, driver_class_path=driver, description=description)) except db_exc.DBError: LOG.exception(_LE('DB error:')) raise exception.SourceTypeCreateFailed(name=name) return type_ref
def create(ctxt, name, driver, description=None): """Creates source types.""" try: type_ref = db.source_type_create(ctxt, dict(name=name, driver_class_path=driver, description=description)) except db_exc.DBError: LOG.exception(_LE('DB error:')) raise exception.SourceTypeCreateFailed(name=name) return type_ref
def __init__(self, message=None, **kwargs): self.kwargs = kwargs self.kwargs['message'] = message if 'code' not in self.kwargs: try: self.kwargs['code'] = self.code except AttributeError: pass for k, v in self.kwargs.items(): if isinstance(v, Exception): self.kwargs[k] = six.text_type(v) if self._should_format(): try: message = self.message % kwargs except Exception: exc_info = sys.exc_info() # kwargs doesn't match a variable in the message # log the issue and the kwargs LOG.exception(_LE('Exception in string format operation')) for name, value in kwargs.items(): LOG.error(_LE("%(name)s: %(value)s"), { 'name': name, 'value': value }) if CONF.fatal_exception_format_errors: six.reraise(*exc_info) # at least get the core message out if something happened message = self.message elif isinstance(message, Exception): message = six.text_type(message) # NOTE(luisg): We put the actual message in 'msg' so that we can access # it, because if we try to access the message via 'message' it will be # overshadowed by the class' message attribute self.msg = message super(GutsException, self).__init__(message)
def start(self): """Start serving a WSGI application. :returns: None :raises: guts.exception.InvalidInput """ # The server socket object will be closed after server exits, # but the underlying file descriptor will remain open, and will # give bad file descriptor error. So duplicating the socket object, # to keep file descriptor usable. dup_socket = self._socket.dup() dup_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) netutils.set_tcp_keepalive(dup_socket, CONF.tcp_keepalive, CONF.tcp_keepidle, CONF.tcp_keepalive_count, CONF.tcp_keepalive_interval) if self._use_ssl: try: ssl_kwargs = { 'server_side': True, 'certfile': CONF.ssl_cert_file, 'keyfile': CONF.ssl_key_file, 'cert_reqs': ssl.CERT_NONE, } if CONF.ssl_ca_file: ssl_kwargs['ca_certs'] = CONF.ssl_ca_file ssl_kwargs['cert_reqs'] = ssl.CERT_REQUIRED dup_socket = ssl.wrap_socket(dup_socket, **ssl_kwargs) except Exception: with excutils.save_and_reraise_exception(): LOG.error( _LE("Failed to start %(name)s on %(_host)s: " "%(_port)s with SSL " "support."), self.__dict__) wsgi_kwargs = { 'func': eventlet.wsgi.server, 'sock': dup_socket, 'site': self.app, 'protocol': self._protocol, 'custom_pool': self._pool, 'log': self._logger, 'socket_timeout': self.client_socket_timeout, 'keepalive': CONF.wsgi_keep_alive } self._server = eventlet.spawn(**wsgi_kwargs)
def load_app(self, name): """Return the paste URLMap wrapped WSGI application. :param name: Name of the application to load. :returns: Paste URLMap object wrapping the requested application. :raises: `guts.exception.PasteAppNotFound` """ try: return deploy.loadapp("config:%s" % self.config_path, name=name) except LookupError: LOG.exception(_LE("Error loading app %s"), name) raise exception.PasteAppNotFound(name=name, path=self.config_path)
def start(self): """Start serving a WSGI application. :returns: None :raises: guts.exception.InvalidInput """ # The server socket object will be closed after server exits, # but the underlying file descriptor will remain open, and will # give bad file descriptor error. So duplicating the socket object, # to keep file descriptor usable. dup_socket = self._socket.dup() dup_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) netutils.set_tcp_keepalive( dup_socket, CONF.tcp_keepalive, CONF.tcp_keepidle, CONF.tcp_keepalive_count, CONF.tcp_keepalive_interval ) if self._use_ssl: try: ssl_kwargs = { "server_side": True, "certfile": CONF.ssl_cert_file, "keyfile": CONF.ssl_key_file, "cert_reqs": ssl.CERT_NONE, } if CONF.ssl_ca_file: ssl_kwargs["ca_certs"] = CONF.ssl_ca_file ssl_kwargs["cert_reqs"] = ssl.CERT_REQUIRED dup_socket = ssl.wrap_socket(dup_socket, **ssl_kwargs) except Exception: with excutils.save_and_reraise_exception(): LOG.error( _LE("Failed to start %(name)s on %(_host)s: " "%(_port)s with SSL " "support."), self.__dict__ ) wsgi_kwargs = { "func": eventlet.wsgi.server, "sock": dup_socket, "site": self.app, "protocol": self._protocol, "custom_pool": self._pool, "log": self._logger, "socket_timeout": self.client_socket_timeout, "keepalive": CONF.wsgi_keep_alive, } self._server = eventlet.spawn(**wsgi_kwargs)
def _check_extension(self, extension): """Checks for required methods in extension objects.""" try: LOG.debug('Ext name: %s', extension.name) LOG.debug('Ext alias: %s', extension.alias) LOG.debug('Ext description: %s', ' '.join(extension.__doc__.strip().split())) LOG.debug('Ext namespace: %s', extension.namespace) LOG.debug('Ext updated: %s', extension.updated) except AttributeError: LOG.exception(_LE("Exception loading extension.")) return False return True
def update(context, id, name=None, driver=None, description=None): """Update source type by id.""" if id is None: msg = _("ID cannot be None") raise exception.InvalidSourceType(reason=msg) try: type_updated = db.source_type_update( context, id, dict(name=name, description=description, driver=driver)) except db_exc.DBError: LOG.exception(_LE('DB error:')) raise exception.SourceTypeUpdateFailed(id=id) return type_updated
def create(ctxt, name, stype, connection_params, description=None): """Creates source.""" try: source_ref = db.source_create( ctxt, dict(name=name, source_type_id=stype, connection_params=connection_params, description=description)) except db_exc.DBError: LOG.exception(_LE('DB error:')) raise exception.SourceCreateFailed(name=name) return source_ref
def update(context, id, name=None, driver=None, description=None): """Update source type by id.""" if id is None: msg = _("ID cannot be None") raise exception.InvalidSourceType(reason=msg) try: type_updated = db.source_type_update(context, id, dict(name=name, description=description, driver=driver)) except db_exc.DBError: LOG.exception(_LE('DB error:')) raise exception.SourceTypeUpdateFailed(id=id) return type_updated
def create(ctxt, name, source_instance_id, description=None): """Creates migration.""" try: migration_ref = db.migration_create( ctxt, dict(name=name, source_instance_id=source_instance_id, description=description)) except db_exc.DBError: LOG.exception(_LE('DB error:')) raise exception.MigrationCreateFailed(name=name) migration_api = migration_rpcapi.MigrationAPI() migration_api.create_migration(ctxt, migration_ref) return migration_ref
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 update(context, id, name=None, stype=None, con_params=None, desc=None): """Update source by id.""" if id is None: msg = _("ID cannot be None") raise exception.InvalidSourceType(reason=msg) try: source_updated = db.source_update( context, id, dict(name=name, description=desc, connection_params=con_params, source_type_id=stype)) except db_exc.DBError: LOG.exception(_LE('DB error:')) raise exception.SourceUpdateFailed(id=id) return source_updated
def update(context, id, name=None, stype=None, con_params=None, desc=None): """Update source by id.""" if id is None: msg = _("ID cannot be None") raise exception.InvalidSourceType(reason=msg) try: source_updated = db.source_update(context, id, dict(name=name, description=desc, connection_params=con_params, source_type_id=stype)) except db_exc.DBError: LOG.exception(_LE('DB error:')) raise exception.SourceUpdateFailed(id=id) return source_updated
def get_instance(self, context, instance_id): """Downloads given instance to local conversion directory.""" if not self._initialized: self.do_setup() try: instance = self.nova.servers.get(instance_id) image_id = instance.create_image(instance_id) img = self.glance.images.get(image_id) while img.status != 'active': img = self.glance.images.get(image_id) image_path = os.path.join(self.configuration.conversion_dir, image_id) self._download_image_from_glance(image_id, image_path) self.glance.images.delete(image_id) except Exception as e: LOG.error(_LE('Failed to download instance image from source, ' 'image_id: %s, %s'), image_id, e) raise exception.InstanceImageDownloadFailed(reason=e.message) return [{'0': image_path}]
def create_volume(self, context, **kwargs): if not self._initialized: self.do_setup(context) image_name = kwargs['mig_ref_id'] try: self._upload_image_to_glance(image_name, kwargs['path']) utils.execute('rm', kwargs['path'], run_as_root=True) img = self.glance.images.find(name=image_name) if img.status != 'active': raise Exception vol = self.cinder.volumes.create(display_name=kwargs['name'], size=int(kwargs['size']), imageRef=img.id) while vol.status != 'available': vol = self.cinder.volumes.get(vol.id) self.glance.images.delete(img.id) except Exception as e: LOG.error(_LE('Failed to create volume from image at destination ' 'image_name: %s %s'), image_name, e) raise exception.VolumeCreationFailed(reason=e.message)
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 get_volume(self, context, volume_id, migration_ref_id): """Downloads given volume to local conversion directory.""" if not self._initialized: self.do_setup() try: vol = self.cinder.volumes.get(volume_id) status = self.cinder.volumes.upload_to_image(vol, True, migration_ref_id, 'bare', 'raw') img_id = status[1]['os-volume_upload_image']['image_id'] vol_img = self.glance.images.get(img_id) while vol_img.status != 'active': vol_img = self.glance.images.get(img_id) image_path = os.path.join(self.configuration.conversion_dir, migration_ref_id) self._download_image_from_glance(vol_img.id, image_path) self.glance.images.delete(vol_img.id) except Exception as e: LOG.error(_LE('Failed to download volume from source, id: %s, ' '%s'), volume_id, e) raise exception.VolumeDownloadFailed(reason=e.message) return image_path
def _prop_update_by_capab(self, ctxt, cloud, capab): driver = importutils.import_object(cloud.driver, cloud=cloud) if capab in driver.SKIP_PROPS_UPDATE: return all_props = {} try: props = driver.get_available_resources(resource_type=capab) if props: all_props.update(props) except Exception as error: msg = (_("Failed to get %(capab)ss properties from the cloud: " "%(cloud)s. Reason: %(reason)s.") % {'capab': capab, 'cloud': cloud.id, 'reason': error}) LOG.exception(_LE('%s') % (msg)) # Convert all values to string from list for prop, value in all_props.items(): all_props[prop] = str(value) cloud.update({"properties": all_props}) cloud.save()