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 'multihomelist' in self.dconf and 'multiSession' not in self.dconf: 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 as 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 as inst: raise xs_errors.XenError('ISCSILogin', \ opterr='code is %d' % inst.code) self.attached = True self._initPaths() util._incr_iscsiSR_refcount(self.targetIQN, sr_uuid) IQNs = [] if "multiSession" in self.dconf: IQNs = "" for iqn in self.dconf['multiSession'].split("|"): if len(iqn): IQNs += iqn.split(',')[2] else: IQNs.append(self.targetIQN) sessions = 0 paths = iscsilib.get_IQN_paths() for path in paths: try: if util.get_single_entry(os.path.join(path, 'targetname')) in IQNs: sessions += 1 util.SMlog("IQN match. Incrementing sessions to %d" % sessions) except: util.SMlog("Failed to read targetname path," \ + "iscsi_sessions value may be incorrect") if pbdref: # Just to be safe in case of garbage left during crashes # we remove the key and add it self.session.xenapi.PBD.remove_from_other_config( pbdref, "iscsi_sessions") self.session.xenapi.PBD.add_to_other_config( pbdref, "iscsi_sessions", str(sessions)) if 'SCSIid' in self.dconf: if self.mpath == 'true': self.mpathmodule.refresh(self.dconf['SCSIid'], 0) devs = os.listdir("/dev/disk/by-scsid/%s" % self.dconf['SCSIid']) for dev in devs: realdev = os.path.realpath("/dev/disk/by-scsid/%s/%s" % (self.dconf['SCSIid'], dev)) util.set_scheduler(realdev.split("/")[-1], "noop")
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) self.attached = True self._initPaths() util._incr_iscsiSR_refcount(self.targetIQN, sr_uuid) IQNs = [] if self.dconf.has_key("multiSession"): IQNs = "" for iqn in self.dconf['multiSession'].split("|"): if len(iqn): IQNs += iqn.split(',')[2] else: IQNs.append(self.targetIQN) sessions = 0 paths = iscsilib.get_IQN_paths() for path in paths: try: if util.get_single_entry(os.path.join(path, 'targetname')) in IQNs: sessions += 1 util.SMlog("IQN match. Incrementing sessions to %d" %
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) self.attached = True self._initPaths() util._incr_iscsiSR_refcount(self.targetIQN, sr_uuid) IQNs = [] if self.dconf.has_key("multiSession"): IQNs = "" for iqn in self.dconf['multiSession'].split("|"): if len(iqn): IQNs += iqn.split(',')[2] else: IQNs.append(self.targetIQN) sessions = 0 paths = iscsilib.get_IQN_paths() for path in paths: try: if util.get_single_entry(os.path.join(path, 'targetname')) in IQNs: sessions += 1 util.SMlog("IQN match. Incrementing sessions to %d" % sessions) except:
class ISCSISR(SR.SR): """ISCSI storage repository""" def handles(type): if type == "iscsi": return True return False handles = staticmethod(handles) def _synchroniseAddrList(self, addrlist): if not self.multihomed: return change = False if not self.dconf.has_key('multihomelist'): change = True self.mlist = [] mstr = "" else: self.mlist = self.dconf['multihomelist'].split(',') mstr = self.dconf['multihomelist'] for val in addrlist: if not val in self.mlist: self.mlist.append(val) if len(mstr): mstr += "," mstr += val change = True if change: pbd = None try: pbd = util.find_my_pbd(self.session, self.host_ref, self.sr_ref) if pbd <> None: device_config = self.session.xenapi.PBD.get_device_config( pbd) device_config['multihomelist'] = mstr self.session.xenapi.PBD.set_device_config( pbd, device_config) except: pass def load(self, sr_uuid): 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'] 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.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'] 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.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 = self.dconf['targetIQN'] self.attached = False try: self.attached = iscsilib._checkTGT(self.targetIQN) except: pass self._initPaths() def _initPaths(self): self._init_adapters() # Generate a list of all possible paths self.pathdict = {} addrlist = [] rec = {} key = "%s:%d" % (self.target, self.port) rec['ipaddr'] = self.target rec['port'] = self.port rec['path'] = os.path.join("/dev/iscsi",self.targetIQN,\ key) self.pathdict[key] = rec util.SMlog("PATHDICT: key %s: %s" % (key, rec)) self.tgtidx = key addrlist.append(key) self.path = rec['path'] self.address = self.tgtidx if not self.attached: return if self.multihomed: map = iscsilib.get_node_records(targetIQN=self.targetIQN) for i in range(0, len(map)): (portal, tpgt, iqn) = map[i] (ipaddr, port) = portal.split(',')[0].split(':') if self.target != ipaddr: key = "%s:%s" % (ipaddr, port) rec = {} rec['ipaddr'] = ipaddr rec['port'] = long(port) rec['path'] = os.path.join("/dev/iscsi",self.targetIQN,\ key) self.pathdict[key] = rec util.SMlog("PATHDICT: key %s: %s" % (key, rec)) addrlist.append(key) # Try to detect an active path in order of priority for key in self.pathdict: if self.adapter.has_key(key): self.tgtidx = key self.path = self.pathdict[self.tgtidx]['path'] if os.path.exists(self.path): util.SMlog("Path found: %s" % self.path) break self.address = self.tgtidx self._synchroniseAddrList(addrlist) def _init_adapters(self): # Generate a list of active adapters ids = scsiutil._genHostList(ISCSI_PROCNAME) util.SMlog(ids) self.adapter = {} for host in ids: try: targetIQN = util.get_single_entry(glob.glob(\ '/sys/class/iscsi_host/host%s/device/session*/iscsi_session*/targetname' % host)[0]) if targetIQN != self.targetIQN: continue addr = util.get_single_entry(glob.glob(\ '/sys/class/iscsi_host/host%s/device/session*/connection*/iscsi_connection*/persistent_address' % host)[0]) port = util.get_single_entry(glob.glob(\ '/sys/class/iscsi_host/host%s/device/session*/connection*/iscsi_connection*/persistent_port' % host)[0]) entry = "%s:%s" % (addr, port) self.adapter[entry] = host except: pass self.devs = scsiutil.cacheSCSIidentifiers() 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 self._initPaths() util._incr_iscsiSR_refcount(self.targetIQN, sr_uuid) IQNs = [] if self.dconf.has_key("multiSession"): IQNs = "" for iqn in self.dconf['multiSession'].split("|"): if len(iqn): IQNs += iqn.split(',')[2] else: IQNs.append(self.targetIQN) sessions = 0 paths = glob.glob(\ '/sys/class/iscsi_host/host*/device/session*/iscsi_session*/targetname') for path in paths: try: if util.get_single_entry(path) in IQNs: sessions += 1 util.SMlog("IQN match. Incrementing sessions to %d" % sessions) except: util.SMlog("Failed to read targetname path," \ + "iscsi_sessions value may be incorrect") try: pbdref = util.find_my_pbd(self.session, self.host_ref, self.sr_ref) if pbdref <> None: other_conf = self.session.xenapi.PBD.get_other_config(pbdref) other_conf['iscsi_sessions'] = str(sessions) self.session.xenapi.PBD.set_other_config(pbdref, other_conf) except: pass if self.mpath == 'true' and self.dconf.has_key('SCSIid'): self.mpathmodule.refresh(self.dconf['SCSIid'], npaths)