def load(self, vdi_uuid): self.lock = self.sr.lock self.sr.srcmd.params['o_direct'] = self.sr.o_direct if self.sr.srcmd.cmd == "vdi_create": self.vdi_type = vhdutil.VDI_TYPE_VHD self.key_hash = None if "vdi_sm_config" in self.sr.srcmd.params: if "key_hash" in self.sr.srcmd.params["vdi_sm_config"]: self.key_hash = self.sr.srcmd.params["vdi_sm_config"][ "key_hash"] if "type" in self.sr.srcmd.params["vdi_sm_config"]: vdi_type = self.sr.srcmd.params["vdi_sm_config"]["type"] if not self.VDI_TYPE.get(vdi_type): raise xs_errors.XenError('VDIType', opterr='Invalid VDI type %s' % vdi_type) self.vdi_type = self.VDI_TYPE[vdi_type] self.path = os.path.join(self.sr.path, "%s%s" % \ (vdi_uuid, vhdutil.FILE_EXTN[self.vdi_type])) else: found = self._find_path_with_retries(vdi_uuid) if not found: if self.sr.srcmd.cmd == "vdi_delete": # Could be delete for CBT log file self.path = os.path.join( self.sr.path, "%s.%s" % (vdi_uuid, self.PARAM_VHD)) return if self.sr.srcmd.cmd == "vdi_attach_from_config": return raise xs_errors.XenError('VDIUnavailable', opterr="VDI %s not found" % vdi_uuid) if self.vdi_type == vhdutil.VDI_TYPE_VHD and \ self.sr.__dict__.get("vhds") and self.sr.vhds.get(vdi_uuid): # VHD info already preloaded: use it instead of querying directly vhdInfo = self.sr.vhds[vdi_uuid] self.utilisation = vhdInfo.sizePhys self.size = vhdInfo.sizeVirt self.hidden = vhdInfo.hidden if self.hidden: self.managed = False self.parent = vhdInfo.parentUuid if self.parent: self.sm_config_override = {'vhd-parent': self.parent} else: self.sm_config_override = {'vhd-parent': None} return try: # Change to the SR directory in case parent # locator field path has changed os.chdir(self.sr.path) except Exception as chdir_exception: util.SMlog("Unable to change to SR directory, SR unavailable, %s" % str(chdir_exception)) raise xs_errors.XenError('SRUnavailable', opterr=str(chdir_exception)) if util.ioretry(lambda: util.pathexists(self.path), errlist=[errno.EIO, errno.ENOENT]): try: st = util.ioretry(lambda: os.stat(self.path), errlist=[errno.EIO, errno.ENOENT]) self.utilisation = long(st.st_size) except util.CommandException as inst: if inst.code == errno.EIO: raise xs_errors.XenError('VDILoad', \ opterr='Failed load VDI information %s' % self.path) else: util.SMlog("Stat failed for %s, %s" % (self.path, str(inst))) raise xs_errors.XenError('VDIType', \ opterr='Invalid VDI type %s' % self.vdi_type) if self.vdi_type == vhdutil.VDI_TYPE_RAW: self.exists = True self.size = self.utilisation self.sm_config_override = {'type': self.PARAM_RAW} return if self.vdi_type == CBTLOG_TAG: self.exists = True self.size = self.utilisation return try: # The VDI might be activated in R/W mode so the VHD footer # won't be valid, use the back-up one instead. diskinfo = util.ioretry( lambda: self._query_info(self.path, True), errlist=[errno.EIO, errno.ENOENT]) if 'parent' in diskinfo: self.parent = diskinfo['parent'] self.sm_config_override = {'vhd-parent': self.parent} else: self.sm_config_override = {'vhd-parent': None} self.parent = '' self.size = long(diskinfo['size']) * 1024 * 1024 self.hidden = long(diskinfo['hidden']) if self.hidden: self.managed = False self.exists = True except util.CommandException as inst: raise xs_errors.XenError('VDILoad', \ opterr='Failed load VDI information %s' % self.path)
def _snapshot(self, snap_type, cbtlog=None, cbt_consistency=None): util.SMlog("FileVDI._snapshot for %s (type %s)" % (self.uuid, snap_type)) args = [] args.append("vdi_clone") args.append(self.sr.uuid) args.append(self.uuid) dest = None dst = None if snap_type == VDI.SNAPSHOT_DOUBLE: dest = util.gen_uuid() dst = os.path.join(self.sr.path, "%s.%s" % (dest, self.vdi_type)) args.append(dest) if self.hidden: raise xs_errors.XenError('VDIClone', opterr='hidden VDI') depth = vhdutil.getDepth(self.path) if depth == -1: raise xs_errors.XenError('VDIUnavailable', \ opterr='failed to get VHD depth') elif depth >= vhdutil.MAX_CHAIN_SIZE: raise xs_errors.XenError('SnapshotChainTooLong') # Test the amount of actual disk space if ENFORCE_VIRT_ALLOC: self.sr._loadvdis() reserved = self.sr.virtual_allocation sr_size = self.sr._getsize() num_vdis = 2 if (snap_type == VDI.SNAPSHOT_SINGLE or snap_type == VDI.SNAPSHOT_INTERNAL): num_vdis = 1 if (sr_size - reserved) < ((self.size + VDI.VDIMetadataSize( \ vhdutil.VDI_TYPE_VHD, self.size)) * num_vdis): raise xs_errors.XenError('SRNoSpace') newuuid = util.gen_uuid() src = self.path newsrc = os.path.join(self.sr.path, "%s.%s" % (newuuid, self.vdi_type)) newsrcname = "%s.%s" % (newuuid, self.vdi_type) if not self._checkpath(src): raise xs_errors.XenError('VDIUnavailable', \ opterr='VDI %s unavailable %s' % (self.uuid, src)) # wkcfix: multiphase util.start_log_entry(self.sr.path, self.path, args) # We assume the filehandle has been released try: util.ioretry(lambda: os.rename(src, newsrc)) # Create the snapshot under a temporary name, then rename # it afterwards. This avoids a small window where it exists # but is invalid. We do not need to do this for # snap_type == VDI.SNAPSHOT_DOUBLE because dst never existed # before so nobody will try to query it. tmpsrc = "%s.%s" % (src, "new") util.ioretry(lambda: self._snap(tmpsrc, newsrcname)) util.ioretry(lambda: os.rename(tmpsrc, src)) if snap_type == VDI.SNAPSHOT_DOUBLE: util.ioretry(lambda: self._snap(dst, newsrcname)) # mark the original file (in this case, its newsrc) # as hidden so that it does not show up in subsequent scans util.ioretry(lambda: self._mark_hidden(newsrc)) #Verify parent locator field of both children and delete newsrc if unused introduce_parent = True try: srcparent = util.ioretry(lambda: self._query_p_uuid(src)) dstparent = None if snap_type == VDI.SNAPSHOT_DOUBLE: dstparent = util.ioretry(lambda: self._query_p_uuid(dst)) if srcparent != newuuid and \ (snap_type == VDI.SNAPSHOT_SINGLE or \ snap_type == VDI.SNAPSHOT_INTERNAL or \ dstparent != newuuid): util.ioretry(lambda: os.unlink(newsrc)) introduce_parent = False except: pass # Introduce the new VDI records leaf_vdi = None if snap_type == VDI.SNAPSHOT_DOUBLE: leaf_vdi = VDI.VDI(self.sr, dest) # user-visible leaf VDI leaf_vdi.read_only = False leaf_vdi.location = dest leaf_vdi.size = self.size leaf_vdi.utilisation = self.utilisation leaf_vdi.sm_config = {} leaf_vdi.sm_config['vhd-parent'] = dstparent # If the parent is encrypted set the key_hash # for the new snapshot disk vdi_ref = self.sr.srcmd.params['vdi_ref'] sm_config = self.session.xenapi.VDI.get_sm_config(vdi_ref) if "key_hash" in sm_config: leaf_vdi.sm_config['key_hash'] = sm_config['key_hash'] # If we have CBT enabled on the VDI, # set CBT status for the new snapshot disk if cbtlog: leaf_vdi.cbt_enabled = True base_vdi = None if introduce_parent: base_vdi = VDI.VDI(self.sr, newuuid) # readonly parent base_vdi.label = "base copy" base_vdi.read_only = True base_vdi.location = newuuid base_vdi.size = self.size base_vdi.utilisation = self.utilisation base_vdi.sm_config = {} grandparent = util.ioretry(lambda: self._query_p_uuid(newsrc)) if grandparent.find("no parent") == -1: base_vdi.sm_config['vhd-parent'] = grandparent try: if snap_type == VDI.SNAPSHOT_DOUBLE: leaf_vdi_ref = leaf_vdi._db_introduce() util.SMlog("vdi_clone: introduced VDI: %s (%s)" % \ (leaf_vdi_ref,dest)) if introduce_parent: base_vdi_ref = base_vdi._db_introduce() self.session.xenapi.VDI.set_managed(base_vdi_ref, False) util.SMlog("vdi_clone: introduced VDI: %s (%s)" % (base_vdi_ref, newuuid)) vdi_ref = self.sr.srcmd.params['vdi_ref'] sm_config = self.session.xenapi.VDI.get_sm_config(vdi_ref) sm_config['vhd-parent'] = srcparent self.session.xenapi.VDI.set_sm_config(vdi_ref, sm_config) except Exception as e: util.SMlog( "vdi_clone: caught error during VDI.db_introduce: %s" % (str(e))) # Note it's too late to actually clean stuff up here: the base disk has # been marked as deleted already. util.end_log_entry(self.sr.path, self.path, ["error"]) raise except util.CommandException as inst: # XXX: it might be too late if the base disk has been marked as deleted! self._clonecleanup(src, dst, newsrc) util.end_log_entry(self.sr.path, self.path, ["error"]) raise xs_errors.XenError('VDIClone', opterr='VDI clone failed error %d' % inst.code) # Update cbt files if user created snapshot (SNAPSHOT_DOUBLE) if snap_type == VDI.SNAPSHOT_DOUBLE and cbtlog: try: self._cbt_snapshot(dest, cbt_consistency) except: # CBT operation failed. util.end_log_entry(self.sr.path, self.path, ["error"]) raise util.end_log_entry(self.sr.path, self.path, ["done"]) if snap_type != VDI.SNAPSHOT_INTERNAL: self.sr._update(self.sr.uuid, self.size) # Return info on the new user-visible leaf VDI ret_vdi = leaf_vdi if not ret_vdi: ret_vdi = base_vdi if not ret_vdi: ret_vdi = self return ret_vdi.get_params()
def update(self, sr_uuid): if not self._checkmount(): raise xs_errors.XenError('SRUnavailable', \ opterr='no such directory %s' % self.path) self._update(sr_uuid, 0)
def _loadvdis(self): if self.vdis: return pattern = os.path.join(self.path, "*%s" % vhdutil.FILE_EXTN_VHD) try: self.vhds = vhdutil.getAllVHDs(pattern, FileVDI.extractUuid) except util.CommandException as inst: raise xs_errors.XenError('SRScan', opterr="error VHD-scanning " \ "path %s (%s)" % (self.path, inst)) try: list_vhds = [ FileVDI.extractUuid(v) for v in util.ioretry(lambda: glob.glob(pattern)) ] if len(self.vhds) != len(list_vhds): util.SMlog("VHD scan returns %d VHDs: %s" % (len(self.vhds), sorted(list(self.vhds)))) util.SMlog("VHD list returns %d VHDs: %s" % (len(list_vhds), sorted(list_vhds))) except: pass for uuid in self.vhds.iterkeys(): if self.vhds[uuid].error: raise xs_errors.XenError('SRScan', opterr='uuid=%s' % uuid) self.vdis[uuid] = self.vdi(uuid, True) # Get the key hash of any encrypted VDIs: vhd_path = os.path.join(self.path, self.vhds[uuid].path) key_hash = vhdutil.getKeyHash(vhd_path) self.vdis[uuid].sm_config_override['key_hash'] = key_hash # raw VDIs and CBT log files files = util.ioretry(lambda: util.listdir(self.path)) for fn in files: if fn.endswith(vhdutil.FILE_EXTN_RAW): uuid = fn[:-(len(vhdutil.FILE_EXTN_RAW))] self.vdis[uuid] = self.vdi(uuid, True) elif fn.endswith(CBTLOG_TAG): cbt_uuid = fn.split(".")[0] # If an associated disk exists, update CBT status # else create new VDI of type cbt_metadata if cbt_uuid in self.vdis: self.vdis[cbt_uuid].cbt_enabled = True else: new_vdi = self.vdi(cbt_uuid) new_vdi.ty = "cbt_metadata" new_vdi.cbt_enabled = True self.vdis[cbt_uuid] = new_vdi # Mark parent VDIs as Read-only and generate virtual allocation self.virtual_allocation = 0 for uuid, vdi in self.vdis.iteritems(): if vdi.parent: if vdi.parent in self.vdis: self.vdis[vdi.parent].read_only = True if vdi.parent in geneology: geneology[vdi.parent].append(uuid) else: geneology[vdi.parent] = [uuid] if not vdi.hidden: self.virtual_allocation += (vdi.size) # now remove all hidden leaf nodes from self.vdis so that they are not # introduced into the Agent DB when SR is synchronized. With the # asynchronous GC, a deleted VDI might stay around until the next # SR.scan, so if we don't ignore hidden leaves we would pick up # freshly-deleted VDIs as newly-added VDIs for uuid in self.vdis.keys(): if uuid not in geneology and self.vdis[uuid].hidden: util.SMlog("Scan found hidden leaf (%s), ignoring" % uuid) del self.vdis[uuid]
def _run(self, sr, target): dconf_type = sr.dconf.get("type") if not dconf_type or not NO_LOGGING.get(dconf_type) or \ not self.cmd in NO_LOGGING[dconf_type]: util.SMlog("%s %s" % (self.cmd, repr(self.params))) caching_params = dict((k, self.params.get(k)) for k in \ [blktap2.VDI.CONF_KEY_ALLOW_CACHING, blktap2.VDI.CONF_KEY_MODE_ON_BOOT, blktap2.VDI.CONF_KEY_CACHE_SR]) if self.cmd == 'vdi_create': # These are the fields owned by the backend, passed on the # commandline: target.label = self.params['args'][1] target.description = self.params['args'][2] target.ty = self.params['vdi_type'] target.metadata_of_pool = self.params['args'][3] target.is_a_snapshot = self.params['args'][4] == "true" target.snapshot_time = self.params['args'][5] target.snapshot_of = self.params['args'][6] target.read_only = self.params['args'][7] == "true" return target.create(self.params['sr_uuid'], self.vdi_uuid, long(self.params['args'][0])) elif self.cmd == 'vdi_update': return target.update(self.params['sr_uuid'], self.vdi_uuid) elif self.cmd == 'vdi_introduce': target = sr.vdi(self.params['new_uuid']) return target.introduce(self.params['sr_uuid'], self.params['new_uuid']) elif self.cmd == 'vdi_delete': return target.delete(self.params['sr_uuid'], self.vdi_uuid) elif self.cmd == 'vdi_attach': target = blktap2.VDI(self.vdi_uuid, target, self.driver_info) writable = self.params['args'][0] == 'true' return target.attach(self.params['sr_uuid'], self.vdi_uuid, writable) elif self.cmd == 'vdi_detach': target = blktap2.VDI(self.vdi_uuid, target, self.driver_info) return target.detach(self.params['sr_uuid'], self.vdi_uuid) elif self.cmd == 'vdi_snapshot': return target.snapshot(self.params['sr_uuid'], self.vdi_uuid) elif self.cmd == 'vdi_clone': return target.clone(self.params['sr_uuid'], self.vdi_uuid) elif self.cmd == 'vdi_resize': return target.resize(self.params['sr_uuid'], self.vdi_uuid, long(self.params['args'][0])) elif self.cmd == 'vdi_resize_online': return target.resize_online(self.params['sr_uuid'], self.vdi_uuid, long(self.params['args'][0])) elif self.cmd == 'vdi_activate': target = blktap2.VDI(self.vdi_uuid, target, self.driver_info) writable = self.params['args'][0] == 'true' return target.activate(self.params['sr_uuid'], self.vdi_uuid, writable, caching_params) elif self.cmd == 'vdi_deactivate': target = blktap2.VDI(self.vdi_uuid, target, self.driver_info) return target.deactivate(self.params['sr_uuid'], self.vdi_uuid, caching_params) elif self.cmd == 'vdi_generate_config': return target.generate_config(self.params['sr_uuid'], self.vdi_uuid) elif self.cmd == 'vdi_attach_from_config': ret = target.attach_from_config(self.params['sr_uuid'], self.vdi_uuid) if not target.sr.driver_config.get( "ATTACH_FROM_CONFIG_WITH_TAPDISK"): return ret target = blktap2.VDI(self.vdi_uuid, target, self.driver_info) return target.attach(self.params['sr_uuid'], self.vdi_uuid, True, True) elif self.cmd == 'sr_create': return sr.create(self.params['sr_uuid'], long(self.params['args'][0])) elif self.cmd == 'sr_delete': return sr.delete(self.params['sr_uuid']) elif self.cmd == 'sr_update': return sr.update(self.params['sr_uuid']) elif self.cmd == 'sr_probe': txt = sr.probe() util.SMlog("sr_probe result: %s" % txt) # return the XML document as a string return xmlrpclib.dumps((txt, ), "", True) elif self.cmd == 'sr_attach': is_master = False if sr.dconf.get("SRmaster") == "true": is_master = True resetvdis.reset(sr.session, util.get_this_host(), self.params['sr_uuid'], is_master) if is_master: # Schedule a scan only when attaching on the SRmaster util.set_dirty(sr.session, self.params["sr_ref"]) return sr.attach(self.params['sr_uuid']) elif self.cmd == 'sr_detach': return sr.detach(self.params['sr_uuid']) elif self.cmd == 'sr_content_type': return sr.content_type(self.params['sr_uuid']) elif self.cmd == 'sr_scan': return sr.scan(self.params['sr_uuid']) else: util.SMlog("Unknown command: %s" % self.cmd) raise xs_errors.XenError('BadRequest')
def mount(self, mountpoint, remotepath): try: nfs.soft_mount(mountpoint, self.remoteserver, remotepath, self.transport) except nfs.NfsException, exc: raise xs_errors.XenError('NFSMount', opterr=exc.errstr)
def load(self, sr_uuid): if self.force_tapdisk: self.sr_vditype = 'aio' else: self.sr_vditype = 'phy' self.discoverentry = 0 self.default_vdi_visibility = False # Required parameters if not self.dconf.has_key('target') or not self.dconf['target']: raise xs_errors.XenError('ConfigTargetMissing') # we are no longer putting hconf in the xml. # Instead we pass a session and host ref and let the SM backend query XAPI itself try: if not self.dconf.has_key('localIQN'): self.localIQN = self.session.xenapi.host.get_other_config( self.host_ref)['iscsi_iqn'] else: self.localIQN = self.dconf['localIQN'] except: raise xs_errors.XenError('ConfigISCSIIQNMissing') # Check for empty string if not self.localIQN: raise xs_errors.XenError('ConfigISCSIIQNMissing') try: self.target = util._convertDNS(self.dconf['target'].split(',')[0]) except: raise xs_errors.XenError('DNSError') self.targetlist = self.target if self.dconf.has_key('targetlist'): self.targetlist = self.dconf['targetlist'] # Optional parameters self.chapuser = "" self.chappassword = "" if self.dconf.has_key('chapuser') \ and (self.dconf.has_key('chappassword') or self.dconf.has_key('chappassword_secret')): self.chapuser = self.dconf['chapuser'].encode('utf-8') if self.dconf.has_key('chappassword_secret'): self.chappassword = util.get_secret( self.session, self.dconf['chappassword_secret']) else: self.chappassword = self.dconf['chappassword'] self.chappassword = self.chappassword.encode('utf-8') self.incoming_chapuser = "" self.incoming_chappassword = "" if self.dconf.has_key('incoming_chapuser') \ and (self.dconf.has_key('incoming_chappassword') or self.dconf.has_key('incoming_chappassword_secret')): self.incoming_chapuser = self.dconf['incoming_chapuser'].encode( 'utf-8') if self.dconf.has_key('incoming_chappassword_secret'): self.incoming_chappassword = util.get_secret( self.session, self.dconf['incoming_chappassword_secret']) else: self.incoming_chappassword = self.dconf[ 'incoming_chappassword'] self.incoming_chappassword = self.incoming_chappassword.encode( 'utf-8') self.port = DEFAULT_PORT if self.dconf.has_key('port') and self.dconf['port']: try: self.port = long(self.dconf['port']) except: raise xs_errors.XenError('ISCSIPort') if self.port > MAXPORT or self.port < 1: raise xs_errors.XenError('ISCSIPort') # For backwards compatibility if self.dconf.has_key('usediscoverynumber'): self.discoverentry = self.dconf['usediscoverynumber'] self.multihomed = False if self.dconf.has_key('multihomed'): if self.dconf['multihomed'] == "true": self.multihomed = True elif self.mpath == 'true': self.multihomed = True if not self.dconf.has_key('targetIQN') or not self.dconf['targetIQN']: self._scan_IQNs() raise xs_errors.XenError('ConfigTargetIQNMissing') self.targetIQN = unicode(self.dconf['targetIQN']).encode('utf-8') self._attached = None self._pathdict = None self._adapter = None self._devs = None self._tgtidx = None self._path = None self._address = None
try: self.mount() except CephFSException, exc: # noinspection PyBroadException try: os.rmdir(self.mountpoint) except: # we have no recovery strategy pass raise SR.SROSError(111, "CephFS mount error [opterr=%s]" % exc.errstr) if util.ioretry(lambda: util.pathexists(self.linkpath)): if len(util.ioretry(lambda: util.listdir(self.linkpath))) != 0: self.detach(sr_uuid) raise xs_errors.XenError('SRExists') else: try: util.ioretry(lambda: util.makedirs(self.linkpath)) os.symlink(self.linkpath, self.path) except util.CommandException, inst: if inst.code != errno.EEXIST: try: self.unmount(self.mountpoint, True) except CephFSException: util.logException('CephFSSR.unmount()') raise SR.SROSError( 116, "Failed to create CephFS SR. remote directory creation error: {}" .format(os.strerror(inst.code))) self.detach(sr_uuid)
opterr='Unable to activate LV. Errno is %d' % inst.code) try: util.pread(["fsck", "-a", self.remotepath]) except util.CommandException, inst: if inst.code == 1: util.SMlog( "FSCK detected and corrected FS errors. Not fatal.") else: raise xs_errors.XenError('LVMMount', \ opterr='FSCK failed on %s. Errno is %d' % (self.remotepath,inst.code)) try: util.pread(["mount", self.remotepath, self.path]) except util.CommandException, inst: raise xs_errors.XenError('LVMMount', \ opterr='Failed to mount FS. Errno is %d' % inst.code) self.attached = True #Update SCSIid string scsiutil.add_serial_record(self.session, self.sr_ref, \ scsiutil.devlist_to_serialstring(self.root.split(','))) # Set the block scheduler for dev in self.root.split(','): self.block_setscheduler(dev) def detach(self, sr_uuid): super(EXTSR, self).detach(sr_uuid) try: # deactivate SR
if self.checkmount(): raise xs_errors.XenError('SMBAttached') try: self.mount() except SMBException, exc: try: os.rmdir(self.mountpoint) except: pass raise xs_errors.XenError('SMBMount', opterr=exc.errstr) if util.ioretry(lambda: util.pathexists(self.linkpath)): if len(util.ioretry(lambda: util.listdir(self.linkpath))) != 0: self.detach(sr_uuid) raise xs_errors.XenError('SRExists') else: try: util.ioretry(lambda: util.makedirs(self.linkpath)) os.symlink(self.linkpath, self.path) except util.CommandException, inst: if inst.code != errno.EEXIST: try: self.unmount(self.mountpoint, True) except SMBException: util.logException('SMBSR.unmount()') raise xs_errors.XenError( 'SMBCreate', opterr="remote directory creation error: {}".format( os.strerror(inst.code))) self.detach(sr_uuid)
def attach(self, sr_uuid, vdi_uuid): util.SMlog("RBDVDI.attach for %s" % self.uuid) vdi_ref = self.session.xenapi.VDI.get_by_uuid(vdi_uuid) sm_config = self.session.xenapi.VDI.get_sm_config(vdi_ref) if sm_config.has_key("snapshot-of"): base_uuid = sm_config["snapshot-of"] # it's a snapshot VDI self.path = self.sr._get_snap_path(base_uuid, vdi_uuid) else: self.path = self.sr._get_path(vdi_uuid) if not hasattr(self, 'xenstore_data'): self.xenstore_data = {} self.xenstore_data.update( scsiutil.update_XS_SCSIdata( self.uuid, scsiutil.gen_synthetic_page_data(self.uuid))) self.xenstore_data['storage-type'] = 'rbd' self.xenstore_data['vdi-type'] = self.vdi_type self.attached = True self.session.xenapi.VDI.remove_from_sm_config(vdi_ref, 'attached') self.session.xenapi.VDI.add_to_sm_config(vdi_ref, 'attached', 'true') self.size = int(self.session.xenapi.VDI.get_virtual_size(vdi_ref)) ########## vdis = self.session.xenapi.SR.get_VDIs(self.sr.sr_ref) has_a_snapshot = False for tmp_vdi in vdis: tmp_vdi_uuid = self.session.xenapi.VDI.get_uuid(tmp_vdi) tmp_sm_config = self.session.xenapi.VDI.get_sm_config(tmp_vdi) if tmp_sm_config.has_key("snapshot-of"): if tmp_sm_config["snapshot-of"] == vdi_uuid: has_a_snapshot = True if tmp_sm_config.has_key("sxm_mirror"): sxm_mirror_vdi = vdi_uuid ########## SXM VDIs if sm_config.has_key("base_mirror"): if has_a_snapshot: # it's a mirror vdi of storage migrating VM # it's attached first self.session.xenapi.VDI.add_to_sm_config( vdi_ref, 'sxm_mirror', 'true') # creating dm snapshot dev self._setup_mirror(vdi_uuid, self.size) else: # it's a base vdi of storage migrating VM # it's attached after mirror VDI and mirror snapshot VDI has been created self._map_VHD(vdi_uuid) ########## not SXM VDIs elif sm_config.has_key("snapshot-of"): base_uuid = sm_config["snapshot-of"] # it's a snapshot VDI, attach it as snapshot self._map_SNAP(base_uuid, vdi_uuid) else: # it's not SXM VDI, just attach it self._map_VHD(vdi_uuid) if not util.pathexists(self.path): raise xs_errors.XenError('VDIUnavailable', opterr='Could not find: %s' % self.path) return VDI.VDI.attach(self, self.sr.uuid, self.uuid)
def attach(self, sr_uuid): self._mpathHandle() npaths = 0 if not self.attached: # Verify iSCSI target and port if self.dconf.has_key('multihomelist' ) and not self.dconf.has_key('multiSession'): targetlist = self.dconf['multihomelist'].split(',') else: targetlist = ['%s:%d' % (self.target, self.port)] conn = False for val in targetlist: (target, port) = val.split(':') try: util._testHost(target, long(port), 'ISCSITarget') self.target = target self.port = long(port) conn = True break except: pass if not conn: raise xs_errors.XenError('ISCSITarget') # Test and set the initiatorname file iscsilib.ensure_daemon_running_ok(self.localIQN) # Check to see if auto attach was set if not iscsilib._checkTGT(self.targetIQN): try: map = iscsilib.discovery(self.target, self.port, self.chapuser, \ self.chappassword, targetIQN=self.targetIQN) iqn = '' if len(map) == 0: self._scan_IQNs() raise xs_errors.XenError( 'ISCSIDiscovery', opterr='check target settings') for i in range(0, len(map)): (portal, tpgt, iqn) = map[i] try: (ipaddr, port) = portal.split(',')[0].split(':') if not self.multihomed and ipaddr != self.target: continue util._testHost(ipaddr, long(port), 'ISCSITarget') util.SMlog("Logging in to [%s:%s]" % (ipaddr, port)) iscsilib.login(portal, iqn, self.chapuser, self.chappassword, self.incoming_chapuser, self.incoming_chappassword) npaths = npaths + 1 except: pass if not iscsilib._checkTGT(self.targetIQN): raise xs_errors.XenError('ISCSIDevice', \ opterr='during login') # Allow the devices to settle time.sleep(5) except util.CommandException, inst: raise xs_errors.XenError('ISCSILogin', \ opterr='code is %d' % inst.code) self.attached = True
def scan(srobj): systemrootID = util.getrootdevID() hbadict = srobj.hbadict hbas = srobj.hbas dom = xml.dom.minidom.Document() e = dom.createElement("Devlist") dom.appendChild(e) if not os.path.exists(DEVPATH): return dom.toprettyxml() devs = srobj.devs vdis = {} for key in hbadict: hba = hbadict[key] path = os.path.join("/dev", key) realpath = path obj = srobj.vdi("") try: obj._query(realpath, devs[realpath][4]) except: continue # Test for root dev or existing PBD if len(obj.SCSIid) and len(systemrootID) and util.match_scsiID( obj.SCSIid, systemrootID): util.SMlog("Ignoring root device %s" % realpath) continue elif util.test_SCSIid(srobj.session, None, obj.SCSIid): util.SMlog("SCSIid in use, ignoring (%s)" % obj.SCSIid) continue elif not devs.has_key(realpath): continue ids = devs[realpath] obj.adapter = ids[1] obj.channel = ids[2] obj.id = ids[3] obj.lun = ids[4] obj.hba = hba['procname'] if hba['eth']: obj.eth = hba['eth'] obj.numpaths = 1 if vdis.has_key(obj.SCSIid): vdis[obj.SCSIid].numpaths += 1 vdis[obj.SCSIid].path += " [%s]" % key elif obj.hba == 'mpp': mppdict = _genMPPHBA(obj.adapter) if mppdict.has_key(key): item = mppdict[key] adapters = '' for i in item: if len(adapters): adapters += ', ' obj.numpaths += 1 adapters += i if len(adapters): obj.mpp = adapters vdis[obj.SCSIid] = obj else: vdis[obj.SCSIid] = obj for key in vdis: obj = vdis[key] d = dom.createElement("BlockDevice") e.appendChild(d) for attr in [ 'path', 'numpaths', 'SCSIid', 'vendor', 'serial', 'size', 'adapter', 'channel', 'id', 'lun', 'hba', 'mpp', 'eth' ]: try: aval = getattr(obj, attr) except AttributeError: if attr in ['mpp'] or attr in ['eth']: continue raise xs_errors.XenError('InvalidArg', \ opterr='Missing required field [%s]' % attr) entry = dom.createElement(attr) d.appendChild(entry) textnode = dom.createTextNode(str(aval)) entry.appendChild(textnode) for key in hbas.iterkeys(): a = dom.createElement("Adapter") e.appendChild(a) entry = dom.createElement('host') a.appendChild(entry) textnode = dom.createTextNode(key) entry.appendChild(textnode) entry = dom.createElement('name') a.appendChild(entry) textnode = dom.createTextNode(hbas[key]) entry.appendChild(textnode) entry = dom.createElement('manufacturer') a.appendChild(entry) textnode = dom.createTextNode(getManufacturer(hbas[key])) entry.appendChild(textnode) id = key.replace("host", "") entry = dom.createElement('id') a.appendChild(entry) textnode = dom.createTextNode(id) entry.appendChild(textnode) _add_host_parameters_to_adapter(dom, a, 'fc_host', id, [ 'node_name', 'port_name', 'port_state', 'speed', 'supported_speeds' ]) _add_host_parameters_to_adapter(dom, a, 'iscsi_host', id, [ 'hwaddress', 'initiatorname', 'ipaddress', 'port_speed', 'port_state' ]) return dom.toprettyxml()
def get_params(self): if not self._checkpath(self.path): raise xs_errors.XenError('VDIUnavailable', \ opterr='VDI %s unavailable %s' % (self.uuid, self.path)) return super(FileVDI, self).get_params()
def attach(self, sr_uuid): self._mpathHandle() multiTargets = False npaths = 0 try: pbdref = util.find_my_pbd(self.session, self.host_ref, self.sr_ref) if pbdref: other_config = self.session.xenapi.PBD.get_other_config(pbdref) multiTargets = util.sessions_less_than_targets( other_config, self.dconf) except: pass if not self.attached or multiTargets: # Verify iSCSI target and port if self.dconf.has_key('multihomelist' ) and not self.dconf.has_key('multiSession'): targetlist = self.dconf['multihomelist'].split(',') else: targetlist = ['%s:%d' % (self.target, self.port)] conn = False for val in targetlist: (target, port) = iscsilib.parse_IP_port(val) try: util._testHost(target, long(port), 'ISCSITarget') self.target = target self.port = long(port) conn = True break except: pass if not conn: raise xs_errors.XenError('ISCSITarget') # Test and set the initiatorname file iscsilib.ensure_daemon_running_ok(self.localIQN) # Check to see if auto attach was set if not iscsilib._checkTGT(self.targetIQN) or multiTargets: try: map = [] if 'any' != self.targetIQN: try: map = iscsilib.get_node_records(self.targetIQN) except: # Pass the exception that is thrown, when there # are no nodes pass if len(map) == 0: map = iscsilib.discovery( self.target, self.port, self.chapuser, self.chappassword, self.targetIQN, iscsilib.get_iscsi_interfaces()) if len(map) == 0: self._scan_IQNs() raise xs_errors.XenError( 'ISCSIDiscovery', opterr='check target settings') for i in range(0, len(map)): (portal, tpgt, iqn) = map[i] try: (ipaddr, port) = iscsilib.parse_IP_port(portal) if not self.multihomed and ipaddr != self.target: continue util._testHost(ipaddr, long(port), 'ISCSITarget') util.SMlog("Logging in to [%s:%s]" % (ipaddr, port)) iscsilib.login(portal, iqn, self.chapuser, self.chappassword, self.incoming_chapuser, self.incoming_chappassword, self.mpath == "true") npaths = npaths + 1 except Exception, e: # Exceptions thrown in login are acknowledged, # the rest of exceptions are ignored since some of the # paths in multipath may not be reachable if str(e).startswith('ISCSI login'): raise else: pass if not iscsilib._checkTGT(self.targetIQN): raise xs_errors.XenError('ISCSIDevice', \ opterr='during login') # Allow the devices to settle time.sleep(5) except util.CommandException, inst: raise xs_errors.XenError('ISCSILogin', \ opterr='code is %d' % inst.code)
def attach(self, sr_uuid, vdi_uuid): if self.deleted: raise xs_errors.XenError('VDIUnavailable') return super(udevVDI, self).attach(sr_uuid, vdi_uuid)
def check_server(self): try: nfs.check_server_tcp(self.remoteserver) except nfs.NfsException, exc: raise xs_errors.XenError('NFSVersion', opterr=exc.errstr)
self.remotepath = self.dconf['serverpath'] try: self.mount_remotepath(sr_uuid) except Exception, exn: try: os.rmdir(self.path) except: pass raise exn if not self.nosubdir: newpath = os.path.join(self.path, sr_uuid) if util.ioretry(lambda: util.pathexists(newpath)): if len(util.ioretry(lambda: util.listdir(newpath))) != 0: self.detach(sr_uuid) raise xs_errors.XenError('SRExists') else: try: util.ioretry(lambda: util.makedirs(newpath)) except util.CommandException, inst: if inst.code != errno.EEXIST: self.detach(sr_uuid) raise xs_errors.XenError( 'NFSCreate', opterr='remote directory creation error is %d' % inst.code) self.detach(sr_uuid) def delete(self, sr_uuid): # try to remove/delete non VDI contents first super(NFSSR, self).delete(sr_uuid)
def attach_from_config(self, sr_uuid, vdi_uuid): self.sr.iscsi.attach(sr_uuid) if not self.sr.iscsi._attach_LUN_bySCSIid(self.sr.SCSIid): raise xs_errors.XenError('InvalidDev') return super(LVMoISCSIVDI, self).attach(sr_uuid, vdi_uuid)