Example #1
0
File: all.py Project: kjylmr/guts
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()
Example #2
0
    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)
Example #3
0
    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})
Example #4
0
    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: '))
Example #5
0
 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})
Example #6
0
 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 {}
Example #7
0
    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
Example #9
0
 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 {}
Example #10
0
    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: '))
Example #11
0
 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
Example #12
0
 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)
Example #13
0
 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
Example #14
0
 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))
Example #15
0
File: sources.py Project: curx/guts
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
Example #16
0
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
Example #17
0
File: types.py Project: curx/guts
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
Example #18
0
    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)
Example #19
0
    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)
Example #20
0
    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)
Example #21
0
    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)
Example #22
0
    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
Example #23
0
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
Example #25
0
    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
Example #26
0
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
Example #27
0
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
Example #28
0
    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
Example #30
0
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
Example #31
0
 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}]
Example #32
0
 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)
Example #33
0
File: wsgi.py Project: curx/guts
    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
Example #34
0
 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
Example #35
0
    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()