def restore_backup(self, sg_client, backup, restore_volume, device): driver_data = jsonutils.loads(backup.driver_data) vol_id = driver_data['volume_id'] vol_size = backup['size'] backup_id = driver_data['backup_id'] # backup_type: local, remote backup_type = backup['destination'] # new volume id new_vol_id = restore_volume.id new_vol_size = restore_volume.size * GB_SIZE new_device = device try: res = self.backup_ctrl(sg_client).RestoreBackup( backup_id, backup_type, vol_id, vol_size, new_vol_id, new_vol_size, new_device) except Exception as exc: msg = (_LE('restore backup failed, err: %s'), exc) LOG.error(msg) raise exception.SGDriverError(reason=msg) if res.status != 0: msg = (_LE('restore backup failed, err_no: %s'), res.status) LOG.error(msg) raise exception.SGDriverError(reason=msg)
def get_admin_client(): if CONF.sgs_client.sgs_ca_cert_file: verify = CONF.sgs_client.sgs_ca_cert_file else: verify = False try: session = utils.get_admin_session( auth_url=CONF.sgs_client.keystone_auth_url, username=CONF.sgs_client.sgs_admin_username, password=CONF.sgs_client.sgs_admin_password, project_name=CONF.sgs_client.sgs_admin_tenant_name, project_domain_name=CONF.sgs_client.sgs_admin_tenant_domain, user_domain_name=CONF.sgs_client.sgs_admin_tenant_domain, verify=verify, timeout=CONF.sgs_client.timeout) client = sc.Client(session=session, version=CONF.sgs_client.sgs_version, connect_retries=3, region_name=CONF.sgs_client.region_name) return client except keystone_exception.Unauthorized: with excutils.save_and_reraise_exception(): LOG.error(_LE('Token unauthorized failed for keystoneclient ' 'constructed when get admin client')) except sgs_exception.Unauthorized: with excutils.save_and_reraise_exception(): LOG.error(_LE('Token unauthorized failed for sgsClient ' 'constructed')) except Exception: with excutils.save_and_reraise_exception(): LOG.error(_LE('Failed to get sgs python client.'))
def disable_sg(self, sg_client, volume): try: res = self.volume_ctrl(sg_client).DisableSG(volume.id) except Exception as exc: msg = (_LE('disable sg failed, err: %s'), exc) LOG.error(msg) raise exception.SGDriverError(reason=msg) if res.status != 0: msg = (_LE('disable sg failed, err_no: %s'), res.status) LOG.error(msg) raise exception.SGDriverError(reason=msg)
def detach_volume(self, sg_client, volume): try: res = self.volume_ctrl(sg_client).DetachVolume(volume.id) except Exception as exc: msg = (_LE('detach volume failed, err:%s'), exc) LOG.error(msg) raise exception.SGDriverError(reason=msg) if res.status != 0: msg = (_LE('detach volume failed, err_no:%s'), res.status) LOG.error(msg) raise exception.SGDriverError(reason=msg)
def list_devices(self, sg_client): try: res = self.volume_ctrl(sg_client).ListDevices() except Exception as exc: msg = (_LE('list devices failed, err: %s'), exc) LOG.error(msg) raise exception.SGDriverError(reason=msg) if res.status != 0: msg = (_LE('list devices failed, err_no: %s'), res.status) LOG.error(msg) raise exception.SGDriverError(reason=msg) return res.devices
def create_volume_from_snapshot(self, sg_client, snapshot, new_volume_id, device): try: res = self.snap_ctrl(sg_client).CreateVolumeFromSnap( snapshot.volume_id, snapshot.id, new_volume_id, device) except Exception as exc: msg = (_LE('create volume from snapshot failed, err: %s'), exc) LOG.error(msg) raise exception.SGDriverError(reason=msg) if res.header.status != 0: msg = (_LE('create volume from snapshot failed, ' 'err_noe: %s'), res.header.status) raise exception.SGDriverError(reason=msg)
def terminate_connection(self, sg_client, volume, mode, device=None): mode = CLIENT_MODE_MAPPING.get(mode, common_pb2.ISCSI_MODE) try: res = self.volume_ctrl(sg_client).TerminateConnection( volume.id, mode, device) except Exception as exc: msg = (_LE('terminate connection failed, err:%s'), exc) LOG.error(msg) raise exception.SGDriverError(reason=msg) if res.status != 0: msg = (_LE('terminate connection failed, err_no:%s'), res.status) LOG.error(msg) raise exception.SGDriverError(reason=msg)
def query_volume_from_snapshot(self, sg_client, new_volume_id): try: res = self.snap_ctrl(sg_client).QueryVolumeFromSnap(new_volume_id) except Exception as exc: msg = (_LE('query volume from snapshot failed, err: %s'), exc) LOG.error(msg) raise exception.SGDriverError(reason=msg) if res.header.status != 0: msg = (_LE('query volume from snapshot failed, ' 'err_noe: %s'), res.header.status) raise exception.SGDriverError(reason=msg) return {'id': new_volume_id, 'status': VOLUME_STATUS_MAPPING[res.vol_status]}
def enable_sg(self, sg_client, volume, device): vol_size = volume.size * GB_SIZE try: res = self.volume_ctrl(sg_client).EnableSG( volume.id, vol_size, device) except Exception as exc: msg = (_LE('enable sg failed, err: %s'), exc) LOG.error(msg) raise exception.SGDriverError(reason=msg) if res.status != 0: msg = (_LE('enable sg failed, err_no: %s'), res.status) LOG.error(msg) raise exception.SGDriverError(reason=msg)
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() state_catalog = {} try: try: service_ref = db.service_get(ctxt, self.service_id) except exception.NotFound: LOG.debug('The service database object disappeared, ' 'recreating it.') self._create_service_ref(ctxt) service_ref = db.service_get(ctxt, self.service_id) state_catalog['report_count'] = service_ref['report_count'] + 1 db.service_update(ctxt, self.service_id, state_catalog) # 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 delete_backup(self, sg_client, backup): vol_id = backup.volume_id backup_id = backup.id try: res = self.backup_ctrl(sg_client).DeleteBackup(backup_id, vol_id) except Exception as exc: msg = (_LE('delete backup failed, err: %s'), exc) LOG.error(msg) raise exception.SGDriverError(reason=msg) if res.status != 0: msg = (_LE('delete backup failed, err_no: %s'), res.status) LOG.error(msg) raise exception.SGDriverError(reason=msg)
def reverse_replicate(self, sg_client, volume): vol_id = volume.id role = REPLICATE_ROLE_MAPPING[volume.replicate_mode] try: res = self.replicate_ctrl(sg_client).ReverseReplication( vol_id, role) except Exception as exc: msg = (_LE('reverse replicate failed, err: %s'), exc) LOG.error(msg) raise exception.SGDriverError(reason=msg) if res.status != 0: msg = (_LE('reverse replicate failed, err_no: %s'), res.status) LOG.error(msg) raise exception.SGDriverError(reason=msg)
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_method(self, request, action, content_type, body): """Look up the action-specific method and its extensions.""" # Look up the method 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 _error(self, inner, req): LOG.exception(_LE("Caught error: %(type)s %(error)s"), { 'type': type(inner), 'error': inner }) 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 # NOTE(johannes): We leave the explanation empty here on # purpose. It could possibly have sensitive information # that should not be returned back to the user. See # bugs 868360 and 874472 # NOTE(eglynn): However, it would be over-conservative and # inconsistent with the EC2 API to hide every exception, # including those that are safe to expose, see bug 1021373 if safe: msg = (inner.msg if isinstance(inner, exception.SGServiceException) else six.text_type(inner)) params = { 'exception': inner.__class__.__name__, 'explanation': msg } outer.explanation = _('%(exception)s: %(explanation)s') % params return wsgi.Fault(outer)
def __init__(self, message=None, **kwargs): """Initiate the instance of SGServiceException There are two ways to initiate the instance. 1. Specify the value of 'message' and leave the 'kwargs' None. 2. Leave 'message' None, and specify the keyword arguments matched with the format of SGServiceException.message. Especially, can't use the 'message' as the key in the 'kwargs', otherwise, the first argument('message') will be set. Note: This class doesn't support to create instance of SGServiceException with another instance. """ self.kwargs = kwargs if 'code' not in self.kwargs: try: self.kwargs['code'] = self.code except AttributeError: pass if not message: 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(SGServiceException, self).__init__(message)
def failover_replicate(self, sg_client, volume, checkpoint_id, snapshot_id): vol_id = volume.id role = REPLICATE_ROLE_MAPPING[volume.replicate_mode] try: res = self.replicate_ctrl(sg_client).FailoverReplication( vol_id, role, checkpoint_id=checkpoint_id, snapshot_id=snapshot_id) except Exception as exc: msg = (_LE('failover replicate failed, err: %s'), exc) LOG.error(msg) raise exception.SGDriverError(reason=msg) if res.status != 0: msg = (_LE('failover replicate failed, err_no: %s'), res.status) LOG.error(msg) raise exception.SGDriverError(reason=msg)
def create_replicate(self, sg_client, volume): rep_uuid = volume.replication_id role = REPLICATE_ROLE_MAPPING[volume.replicate_mode] local_volume = volume.id peer_volumes = [volume.peer_volume] try: res = self.replicate_ctrl(sg_client).CreateReplication( rep_uuid, local_volume, role, peer_volumes) except Exception as exc: msg = (_LE('create replicate failed, err: %s'), exc) LOG.error(msg) raise exception.SGDriverError(reason=msg) if res.status != 0: msg = (_LE('create replicate failed, err_no: %s'), res.status) LOG.error(msg) raise exception.SGDriverError(reason=msg)
def start(self): """Start serving a WSGI application. :returns: None :raises: sgservice.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) # NOTE(praneshp): Call set_tcp_keepalive in oslo to set # tcp keepalive parameters. Sockets can hang around forever # without keepalive 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 create_backup(self, sg_client, backup): # backup_mode: full, incremental backup_mode = backup.type # backup_type: local, remote backup_type = backup.destination vol_id = backup.volume_id vol_size = backup.size * GB_SIZE backup_id = backup.id try: res = self.backup_ctrl(sg_client).CreateBackup( backup_mode, backup_type, vol_id, vol_size, backup_id) except Exception as exc: msg = (_LE('create backup failed, err: %s'), exc) LOG.error(msg) raise exception.SGDriverError(reason=msg) if res.status != 0: msg = (_LE('create backup failed, err_no: %s'), res.status) LOG.error(msg) raise exception.SGDriverError(reason=msg)
def rollback_snapshot(self, sg_client, snapshot): vol_id = snapshot.volume_id snap_id = snapshot.id snap_type = snapshot.destination if snapshot.checkpoint_id: checkpoint_uuid = snapshot.checkpoint_id else: checkpoint_uuid = None try: res = self.snap_ctrl(sg_client).RollbackSnapshot( snap_type, vol_id, snap_id, checkpoint_uuid) except Exception as exc: msg = (_LE('rollback snapshot failed, err: %s'), exc) LOG.error(msg) raise exception.SGDriverError(reason=msg) if res.header.status != 0: msg = (_LE('rollback snapshot failed, err_no: %s'), res.header.status) LOG.error(msg) raise exception.SGDriverError(reason=msg)
def get_backup(self, sg_client, backup): vol_id = backup.volume_id backup_id = backup.id try: res = self.backup_ctrl(sg_client).GetBackup(backup_id, vol_id) except Exception as exc: msg = (_LE('get backup failed, err: %s'), exc) LOG.error(msg) raise exception.SGDriverError(reason=msg) if res.status != 0: if res.status == common_pb2.sBackupNotExist: backup = {'id': backup.id, 'status': fields.BackupStatus.DELETED} else: msg = (_LE('get backup failed, err_no: %s'), res.status) LOG.error(msg) raise exception.SGDriverError(reason=msg) else: backup = {'id': backup.id, 'status': BACKUP_STATUS_MAPPING[res.backup_status]} return backup
def get_project_context_client(context): try: url = utils.get_management_url( auth_url=CONF.nova_client.keystone_auth_url, tenant_name=CONF.nova_client.nova_admin_tenant_name, username=CONF.nova_client.nova_admin_username, password=CONF.nova_client.nova_admin_password, region_name=CONF.nova_client.region_name, service_type=CONF.nova_client.service_type, insecure=CONF.nova_client.nova_auth_insecure, cacert=CONF.nova_client.nova_ca_cert_file) management_url = url + '/' + context.project_id args = { 'project_id': context.project_id, 'auth_url': CONF.nova_client.keystone_auth_url, 'service_type': CONF.nova_client.service_type, 'region_name': CONF.nova_client.region_name, 'username': context.user_id, 'insecure': CONF.nova_client.nova_auth_insecure, 'cacert': CONF.nova_client.nova_ca_cert_file, 'timeout': CONF.nova_client.timeout, 'auth_token': context.auth_token } client = nc.Client(CONF.nova_client.nova_version, **args) client.client.management_url = management_url return client except keystone_exception.Unauthorized: with excutils.save_and_reraise_exception(): LOG.error(_LE('Token unauthorized failed for keystoneclient ' 'constructed when get admin novaClient')) except nova_exception.Unauthorized: with excutils.save_and_reraise_exception(): LOG.error(_LE('Token unauthorized failed for novaClient ' 'constructed')) except Exception: with excutils.save_and_reraise_exception(): LOG.error(_LE('Failed to get nova python client.'))
def get_snapshot(self, sg_client, snapshot): vol_id = snapshot.volume_id snap_id = snapshot.id try: res = self.snap_ctrl(sg_client).GetSnapshot(vol_id, snap_id) except Exception as exc: msg = (_LE('get snapshot failed, err: %s'), exc) LOG.error(msg) raise exception.SGDriverError(reason=msg) if res.header.status != 0: if res.header.status == common_pb2.sSnapNotExist: snapshot = {'id': snapshot.id, 'status': fields.SnapshotStatus.DELETED} else: msg = (_LE('get snapshot failed, err_no: %s'), res.header.status) LOG.error(msg) raise exception.SGDriverError(reason=msg) else: snapshot = {'id': snapshot.id, 'status': SNAPSHOT_STATUS_MAPPING[res.snap_status]} return snapshot
def initialize_connection(self, sg_client, volume, mode): mode = CLIENT_MODE_MAPPING.get(mode, common_pb2.ISCSI_MODE) try: res = self.volume_ctrl(sg_client).InitializeConnection( volume.id, mode) except Exception as exc: msg = (_LE('initialize connection failed, err:%s'), exc) LOG.error(msg) raise exception.SGDriverError(reason=msg) if res.status != 0: msg = (_LE('initialize connection failed, err_no:%s'), res.status) LOG.error(msg) raise exception.SGDriverError(reason=msg) if mode == common_pb2.ISCSI_MODE: target_portal = "%s:3260" % sg_client.host target_iqn = res.connection_info['target_iqn'] target_lun = int(res.connection_info['target_lun']) connection_info = { 'target_portal': target_portal, 'target_iqn': target_iqn, 'target_lun': target_lun, } return connection_info
def get_volume(self, sg_client, volume): try: res = self.volume_ctrl(sg_client).GetVolume(volume.id) except Exception as exc: msg = (_LE('get volume failed, err: %s'), exc) LOG.error(msg) raise exception.SGDriverError(reason=msg) if res.status != 0: volume = {'id': volume.id, 'status': fields.VolumeStatus.DELETED, 'replicate_status': fields.ReplicateStatus.DELETED} return volume status = VOLUME_STATUS_MAPPING[res.volume.vol_status] replicate_status = REPLICATE_STATUS_MAPPING[res.volume.rep_status] volume = { 'id': volume.id, 'status': status, 'replicate_status': replicate_status, 'replicate_mode': ROLE_REPLICATE_MAPPING.get(res.volume.role, None)} return volume