def _cliq_run_xml(self, verb, cliq_args, check_cliq_result=True): """Runs a CLIQ command over SSH, parsing and checking the output""" cliq_args['output'] = 'XML' (out, _err) = self._cliq_run(verb, cliq_args) LOG.debug(_("CLIQ command returned %s"), out) result_xml = etree.fromstring(out) if check_cliq_result: response_node = result_xml.find("response") if response_node is None: msg = (_("Malformed response to CLIQ command " "%(verb)s %(cliq_args)s. Result=%(out)s") % locals()) raise exception.VolumeBackendAPIException(data=msg) result_code = response_node.attrib.get("result") if result_code != "0": msg = (_("Error running CLIQ command %(verb)s %(cliq_args)s. " " Result=%(out)s") % locals()) raise exception.VolumeBackendAPIException(data=msg) return result_xml
def initialize_connection(self, volume, connector): try: xensm_properties = dict( self.db.sm_volume_get(self.ctxt, volume['id'])) except Exception as ex: LOG.exception(ex) msg = _("Failed to find volume in db") raise exception.VolumeBackendAPIException(data=msg) # Keep the volume id key consistent with what ISCSI driver calls it xensm_properties['volume_id'] = xensm_properties['id'] del xensm_properties['id'] try: backend_conf = self.db.sm_backend_conf_get( self.ctxt, xensm_properties['backend_id']) except Exception as ex: LOG.exception(ex) msg = _("Failed to find backend in db") raise exception.VolumeBackendAPIException(data=msg) params = self._convert_config_params(backend_conf['config_params']) xensm_properties['flavor_id'] = backend_conf['flavor_id'] xensm_properties['sr_uuid'] = backend_conf['sr_uuid'] xensm_properties['sr_type'] = backend_conf['sr_type'] xensm_properties.update(params) _introduce_sr_keys = self._get_introduce_sr_keys(params) xensm_properties['introduce_sr_keys'] = _introduce_sr_keys return {'driver_volume_type': 'xensm', 'data': xensm_properties}
def check_for_setup_error(self): """Returns an error if prerequisites aren't met""" (stdout, stderr) = self._execute('rados', 'lspools') pools = stdout.split("\n") if not FLAGS.rbd_pool in pools: exception_message = (_("rbd has no pool %s") % FLAGS.rbd_pool) raise exception.VolumeBackendAPIException(data=exception_message)
def _get_luid(self, volume): zfs_poolname = self._build_zfs_poolname(volume) zvol_name = '/dev/zvol/rdsk/%s' % zfs_poolname (out, _err) = self._execute('/usr/sbin/sbdadm', 'list-lu') lines = _collect_lines(out) # Strip headers if len(lines) >= 1: if lines[0] == '': lines = lines[1:] if len(lines) >= 4: assert 'Found' in lines[0] assert '' == lines[1] assert 'GUID' in lines[2] assert '------------------' in lines[3] lines = lines[4:] for line in lines: items = line.split() assert len(items) == 3 if items[2] == zvol_name: luid = items[0].strip() return luid msg = _('LUID not found for %(zfs_poolname)s. ' 'Output=%(out)s') % locals() raise exception.VolumeBackendAPIException(data=msg)
def _create_storage_repo(self, context, backend_ref): """Either creates or introduces SR on host depending on whether it exists in xapi db.""" params = self._convert_config_params(backend_ref['config_params']) if 'name_label' in params: label = params['name_label'] del params['name_label'] else: label = 'SR-' + str(backend_ref['id']) params['sr_type'] = backend_ref['sr_type'] if backend_ref['sr_uuid'] is None: # run the sr create command try: LOG.debug(_('SR name = %s') % label) LOG.debug(_('Params: %s') % str(params)) sr_uuid = self._volumeops.create_sr(label, params) # update sr_uuid and created in db except Exception as ex: LOG.debug( _("Failed to create sr %s...continuing") % str(backend_ref['id'])) msg = _('Create failed') raise exception.VolumeBackendAPIException(data=msg) LOG.debug(_('SR UUID of new SR is: %s') % sr_uuid) try: self.db.sm_backend_conf_update(context, backend_ref['id'], dict(sr_uuid=sr_uuid)) except Exception as ex: LOG.exception(ex) msg = _("Failed to update db") raise exception.VolumeBackendAPIException(data=msg) else: # sr introduce, if not already done try: self._volumeops.introduce_sr(backend_ref['sr_uuid'], label, params) except Exception as ex: LOG.exception(ex) LOG.debug( _("Failed to introduce sr %s...continuing") % str(backend_ref['id']))
def _create_storage_repos(self, context): """Create/Introduce storage repositories at start.""" backends = self.db.sm_backend_conf_get_all(context) for backend in backends: try: self._create_storage_repo(context, backend) except Exception as ex: LOG.exception(ex) msg = _('Failed to reach backend %d') % backend['id'] raise exception.VolumeBackendAPIException(data=msg)
def check_for_setup_error(self): """Returns an error if prerequisites aren't met""" out, err = self._execute('vgs', '--noheadings', '-o', 'name', run_as_root=True) volume_groups = out.split() if not FLAGS.volume_group in volume_groups: exception_message = (_("volume group %s doesn't exist") % FLAGS.volume_group) raise exception.VolumeBackendAPIException(data=exception_message)
def _view_exists(self, luid): (out, _err) = self._execute('/usr/sbin/stmfadm', 'list-view', '-l', luid, check_exit_code=False) if "no views found" in out: return False if "View Entry:" in out: return True msg = _("Cannot parse list-view output: %s") % out raise exception.VolumeBackendAPIException(data=msg)
def delete_volume(self, volume): vol_rec = self.db.sm_volume_get(self.ctxt, volume['id']) if not vol_rec: raise exception.NotFound(_("Volume %s does not exist"), volume['id']) try: # If compute runs on this node, detach could have disconnected SR backend_ref = self.db.sm_backend_conf_get(self.ctxt, vol_rec['backend_id']) self._create_storage_repo(self.ctxt, backend_ref) self._volumeops.delete_volume_for_sm(vol_rec['vdi_uuid']) except Exception as ex: LOG.exception(ex) msg = _("Failed to delete vdi") raise exception.VolumeBackendAPIException(data=msg) try: self.db.sm_volume_delete(self.ctxt, volume['id']) except Exception as ex: LOG.exception(ex) msg = _("Failed to delete volume in db") raise exception.VolumeBackendAPIException(data=msg)
def create_volume(self, volume): """Creates a logical volume. Can optionally return a Dictionary of changes to the volume object to be persisted.""" # For now the scheduling logic will be to try to fit the volume in # the first available backend. # TODO(renukaapte) better scheduling once APIs are in place sm_vol_rec = None backends = self.db.sm_backend_conf_get_all(self.ctxt) for backend in backends: # Ensure that storage repo exists, if not create. # This needs to be done because if nova compute and # volume are both running on this host, then, as a # part of detach_volume, compute could potentially forget SR self._create_storage_repo(self.ctxt, backend) sm_vol_rec = self._volumeops.create_volume_for_sm( volume, backend['sr_uuid']) if sm_vol_rec: LOG.debug( _('Volume will be created in backend - %d') % backend['id']) break if sm_vol_rec: # Update db sm_vol_rec['id'] = volume['id'] sm_vol_rec['backend_id'] = backend['id'] try: self.db.sm_volume_create(self.ctxt, sm_vol_rec) except Exception as ex: LOG.exception(ex) msg = _("Failed to update volume in db") raise exception.VolumeBackendAPIException(data=msg) else: msg = _('Unable to create volume') raise exception.VolumeBackendAPIException(data=msg)
def __init__(self, *args, **kwargs): """Connect to the hypervisor.""" # This driver leverages Xen storage manager, and hence requires # hypervisor to be Xen if FLAGS.connection_type != 'xenapi': msg = _('XenSMDriver requires xenapi connection') raise exception.VolumeBackendAPIException(data=msg) url = FLAGS.xenapi_connection_url username = FLAGS.xenapi_connection_username password = FLAGS.xenapi_connection_password try: session = xenapi_conn.XenAPISession(url, username, password) self._volumeops = volumeops.VolumeOps(session) except Exception as ex: LOG.exception(ex) msg = _("Failed to initiate session") raise exception.VolumeBackendAPIException(data=msg) super(XenSMDriver, self).__init__(execute=utils.execute, sync_exec=utils.execute, *args, **kwargs)
def check_for_setup_error(self): """Returns an error if prerequisites aren't met""" try: #NOTE(francois-charlier) Since 0.24 'collie cluster info -r' # gives short output, but for compatibility reason we won't # use it and just check if 'running' is in the output. (out, err) = self._execute('collie', 'cluster', 'info') if not 'running' in out.split(): exception_message = _("Sheepdog is not working: %s") % out raise exception.VolumeBackendAPIException( data=exception_message) except exception.ProcessExecutionError: exception_message = _("Sheepdog is not working") raise exception.NovaException(data=exception_message)
def _cliq_get_cluster_vip(self, cluster_name): """Gets the IP on which a cluster shares iSCSI volumes""" cluster_xml = self._cliq_get_cluster_info(cluster_name) vips = [] for vip in cluster_xml.findall("response/cluster/vip"): vips.append(vip.attrib.get('ipAddress')) if len(vips) == 1: return vips[0] _xml = etree.tostring(cluster_xml) msg = (_("Unexpected number of virtual ips for cluster " " %(cluster_name)s. Result=%(_xml)s") % locals()) raise exception.VolumeBackendAPIException(data=msg)
def local_path(self, volume): # TODO(justinsb): Is this needed here? msg = _("local_path not supported") raise exception.VolumeBackendAPIException(data=msg)