def create(dbg, path): """Creates a new loop device backed by the given file""" # losetup will resolve paths and 'find' needs to use string equality path = os.path.realpath(path) call(dbg, ["losetup", "-f", path]) return find(dbg, path)
def create(dbg, base_device): try: return DeviceMapper(dbg, base_device) except: call(dbg, ["dmsetup", "create", name_of_device( base_device), "--table", table(base_device)]) return DeviceMapper(dbg, base_device)
def mount(dbg, dev_path): # Ensure corosync+dlm are configured and running inventory = xcp.environ.readInventory() session = XenAPI.xapi_local() session.xenapi.login_with_password("root", "") this_host = session.xenapi.host.get_by_uuid( inventory.get("INSTALLATION_UUID")) log.debug("%s: setting up corosync and dlm on this host" % (dbg)) session.xenapi.host.call_plugin( this_host, "gfs2setup", "gfs2Setup", {}) mnt_path = os.path.abspath(mountpoint_root + dev_path) try: os.makedirs(mnt_path) except OSError as exc: if exc.errno == errno.EEXIST and os.path.isdir(mnt_path): pass else: raise if not os.path.ismount(mnt_path): cmd = ["/usr/sbin/modprobe", "gfs2"] call(dbg, cmd) cmd = ["/usr/bin/mount", "-t", "gfs2", "-o", "noatime,nodiratime", dev_path, mnt_path] call(dbg, cmd) return mnt_path
def sync_leaf_coalesce(key, parent_key, conn, cb, opq): print("leaf_coalesce_snapshot key=%s" % key) key_path = cb.volumeGetPath(opq, key) parent_path = cb.volumeGetPath(opq, parent_key) res = conn.execute("select parent from VDI where rowid = (?)", (int(parent_key), )).fetchall() p_parent = res[0][0] print p_parent if p_parent: p_parent = int(p_parent) else: p_parent = "?" tap_ctl_pause(key, conn, cb, opq) cmd = ["/usr/bin/vhd-util", "coalesce", "-n", key_path] call("GC", cmd) cb.volumeDestroy(opq, key) base_path = cb.volumeRename(opq, parent_key, key) res = conn.execute("delete from VDI where rowid = (?)", (int(parent_key), )) res = conn.execute("update VDI set parent = (?) where rowid = (?)", ( p_parent, int(key), )) conn.commit() tap_ctl_unpause(key, conn, cb, opq)
def destroy(self, dbg): self.pause(dbg) call( dbg, ["tap-ctl", "destroy", "-m", str(self.minor), "-p", str(self.pid)])
def find_if_gfs2(impl, dbg, uri): srs = [] dev_path = blkinfo.get_device_path(dbg, uri) unique_id = get_unique_id_from_dev_path(dev_path) if blkinfo.get_format(dbg, dev_path) == "LVM2_member": gfs2_dev_path = "/dev/" + unique_id + "/gfs2" # activate gfs2 LV cmd = ["/usr/sbin/lvchange", "-ay", unique_id + "/gfs2"] call(dbg, cmd) if blkinfo.get_format(dbg, gfs2_dev_path) == "gfs2": mount = False try: mnt_path = getSRMountPath(dbg, gfs2_dev_path) except: #mount path doesn't exist mount = True mnt_path = mount_local(dbg, gfs2_dev_path) # stat takes sr_path which is # file://<mnt_path> sr_path = "file://%s" % mnt_path srs.append(impl.stat(dbg, sr_path)) if mount == True: umount(dbg, mnt_path) # deactivate gfs2 LV cmd = ["/usr/sbin/lvchange", "-an", unique_id + "/gfs2"] call(dbg, cmd) return srs
def sync_leaf_coalesce(key, parent_key, conn, cb, opq): print ("leaf_coalesce_snapshot key=%s" % key) key_path = cb.volumeGetPath(opq, key) parent_path = cb.volumeGetPath(opq, parent_key) res = conn.execute("select parent from VDI where rowid = (?)", (int(parent_key),)).fetchall() p_parent = res[0][0] print p_parent if p_parent: p_parent = int(p_parent) else: p_parent = "?" tap_ctl_pause(key, conn, cb, opq) cmd = ["/usr/bin/vhd-util", "coalesce", "-n", key_path] call("GC", cmd) cb.volumeDestroy(opq, key) base_path = cb.volumeRename(opq, parent_key, key) res = conn.execute("delete from VDI where rowid = (?)", (int(parent_key),)) res = conn.execute("update VDI set parent = (?) where rowid = (?)", (p_parent, int(key),) ) conn.commit() tap_ctl_unpause(key, conn, cb, opq)
def attach(self, dbg, uri, domain): parsed_url = urlparse.urlparse(uri) query = urlparse.parse_qs(parsed_url.query) file_path = os.path.realpath(parsed_url.path) cmd = ['losetup', '-f', file_path] if 'size' in query: cmd.extend(['--sizelimit', query['size'][0]]) call(dbg, cmd) loop = Loop.from_path(dbg, file_path) return {"implementations": [ [ 'XenDisk', { 'backend_type': 'vbd', 'params': loop.block_device(), 'extra': {} } ], [ 'BlockDevice', { 'path': loop.block_device() } ] ]}
def create(dbg, host, name): """Return an active nbd device associated with the given name, creating a fresh one if one doesn't already exist.""" existing = find(dbg, host, name) if existing: return existing used = set() try: used = set(os.listdir(persist_root)) except OSError as exc: if exc.errno == errno.ENOENT: pass else: raise all = set(filter(lambda x: x.startswith("nbd"), os.listdir("/dev"))) for nbd in all.difference(used): # try: call(dbg, ["nbd-client", host, "/dev/" + nbd, "-name", name, "-b", "4096"]) with open("/sys/block/" + nbd + "/queue/scheduler", "w") as fd: fd.write("none") return Nbd(host, name, nbd) # except: # pass # try another one raise NoAvailableNbd()
def open(self, dbg, f, o_direct=True): assert (isinstance(f, image.Vhd) or isinstance(f, image.Raw)) args = ["tap-ctl", "open", "-m", str(self.minor), "-p", str(self.pid), "-a", str(f)] if not o_direct: args.append("-D") call(dbg, args) self.f = f
def pause(self, dbg): call(dbg, ["tap-ctl", "pause", "-m", str(self.minor), "-p", str(self.pid)])
def waitForDevice(dbg): # Wait for new device(s) to appear cmd = ["/usr/sbin/udevadm", "settle"] call(dbg, cmd) # FIXME: For some reason, udevadm settle isn't sufficient # to ensure the device is present. Why not? time.sleep(10)
def close(self, dbg): call(dbg, ["tap-ctl", "close", "-m", str(self.minor), "-p", str(self.pid)]) self.f = None
def open(self, dbg, f): assert (isinstance(f, image.Vhd) or isinstance(f, image.Raw)) call(dbg, [ "tap-ctl", "open", "-m", str(self.minor), "-p", str(self.pid), "-a", str(f) ]) self.f = f
def destroy(self, dbg): self.pause(dbg) call(dbg, ["tap-ctl", "destroy", "-m", str(self.minor), "-p", str(self.pid)])
def unpause(self, dbg): cmd = [ "tap-ctl", "unpause", "-m", str(self.minor), "-p", str(self.pid) ] if self.secondary is not None: cmd = cmd + ["-2 ", self.secondary] call(dbg, cmd)
def create(dbg, base_device): try: return DeviceMapper(dbg, base_device) except: call(dbg, [ "dmsetup", "create", name_of_device(base_device), "--table", table(base_device) ]) return DeviceMapper(dbg, base_device)
def create(dbg, sr, name, description, size, cb): vol_name = str(uuid.uuid4()) + ".vhd" opq = cb.volumeStartOperations(sr, 'w') vol_path = cb.volumeCreate(opq, vol_name, size) cb.volumeActivateLocal(opq, vol_name) # Calculate virtual size (round up size to nearest MiB) size = int(size) size_mib = size / 1048576 if size % 1048576 != 0: size_mib = size_mib + 1 vsize = size_mib * 1048576 # Create the VHD cmd = ["/usr/bin/vhd-util", "create", "-n", vol_path, "-s", str(size_mib)] call(dbg, cmd) cb.volumeDeactivateLocal(opq, vol_name) # Fetch physical utilisation psize = cb.volumeGetPhysSize(opq, vol_name) # Save metadata meta_path = cb.volumeMetadataGetPath(opq) cb.volumeStopOperations(opq) d = shelve.open(meta_path) meta = { "name": name, "description": description, "vsize": vsize, "keys": {}, "childrens": [], "parent": "None" } d[vol_name] = meta d.close() return { "key": vol_name, "uuid": vol_name, "name": name, "description": description, "read_write": True, "virtual_size": vsize, "physical_utilisation": psize, "uri": ["vhd+file://" + vol_path], "keys": {}, }
def zoneOutLUN(dbg, uri): log.debug("%s: zoneOutLUN uri=%s" % (dbg, uri)) u = urlparse.urlparse(uri) log.debug("%s: u = %s" % (dbg, u)) if u.scheme == 'iscsi': (target, iqn, lunid) = decomposeISCSIuri(dbg, u) log.debug("%s: iqn = %s" % (dbg, iqn)) cmd = ["/usr/sbin/iscsiadm", "-m", "node", "-T", iqn, "-u"] call(dbg, cmd)
def open(self, dbg, f, o_direct=True): assert (isinstance(f, image.Vhd) or isinstance(f, image.Raw)) args = [ "tap-ctl", "open", "-m", str(self.minor), "-p", str(self.pid), "-a", str(f) ] if not o_direct: args.append("-D") call(dbg, args) self.f = f
def create(dbg): output = call(dbg, ["tap-ctl", "spawn"]).strip() pid = int(output) output = call(dbg, ["tap-ctl", "allocate"]).strip() prefix = blktap2_prefix minor = None if output.startswith(prefix): minor = int(output[len(prefix):]) if minor is None: os.kill(pid, signal.SIGQUIT) raise xapi.InternalError("tap-ctl allocate returned unexpected " + "output: %s" % (output)) call(dbg, ["tap-ctl", "attach", "-m", str(minor), "-p", str(pid)]) return Tapdisk(minor, pid, None)
def mount_local(dbg, dev_path): mnt_path = os.path.abspath(mountpoint_root + dev_path) try: os.makedirs(mnt_path) except OSError as exc: if exc.errno == errno.EEXIST and os.path.isdir(mnt_path): pass else: raise if not os.path.ismount(mnt_path): cmd = ["/usr/bin/mount", "-t", "gfs2", "-o", "noatime,nodiratime,lockproto=lock_nolock", dev_path, mnt_path] call(dbg, cmd) return mnt_path
def waitForDevice(dbg, keys): # Wait for new device(s) to appear cmd = ["/usr/sbin/udevadm", "settle"] call(dbg, cmd) # FIXME: For some reason, udevadm settle isn't sufficient # to ensure the device is present. Why not? for i in range(1,10): time.sleep(1) if keys['scsiid'] != None: try: os.stat(DEV_PATH_ROOT + keys['scsiid']) return except: log.debug("%s: Waiting for device to appear" % dbg)
def create(dbg, sr, name, description, size, cb): # Calculate virtual size (round up size to nearest MiB) size = int(size) size_mib = size / 1048576 if size % 1048576 != 0: size_mib = size_mib + 1 vsize = size_mib * 1048576 opq = cb.volumeStartOperations(sr, 'w') meta_path = cb.volumeMetadataGetPath(opq) vol_uuid = str(uuid.uuid4()) conn = connectSQLite3(meta_path) with write_context(conn): res = conn.execute("insert into VDI(snap, name, description, uuid, vsize) values (?, ?, ?, ?, ?)", (0, name, description, vol_uuid, str(vsize))) vol_name = str(res.lastrowid) vol_path = cb.volumeCreate(opq, vol_name, size) cb.volumeActivateLocal(opq, vol_name) # Create the VHD cmd = ["/usr/bin/vhd-util", "create", "-n", vol_path, "-s", str(size_mib)] call(dbg, cmd) cb.volumeDeactivateLocal(opq, vol_name) # Fetch physical utilisation psize = cb.volumeGetPhysSize(opq, vol_name) vol_uri = cb.getVolumeURI(opq, vol_name) cb.volumeStopOperations(opq) conn.close() return { "key": vol_name, "uuid": vol_uuid, "name": name, "description": description, "read_write": True, "virtual_size": vsize, "physical_utilisation": psize, "uri": [DP_URI_PREFIX + vol_uri], "keys": {}, }
def rescanSession(dbg, sessionid): cmd = [ "/usr/sbin/iscsiadm", "-m", "session", "-r", str(sessionid), "--rescan" ] output = call(dbg, cmd) log.debug("%s: output = '%s'" % (dbg, output))
def set_chap_settings(dbg, portal, target, username, password): cmd = ["/usr/sbin/iscsiadm", "-m", "node", "-T", iqn, "--portal", portal, "--op", "update", "-n", "node.session.auth.authmethod", "-v", "CHAP"] output = call(dbg, cmd) log.debug("%s: output = %s" % (dbg, output)) cmd = ["/usr/sbin/iscsiadm", "-m", "node", "-T", iqn, "--portal", portal, "--op", "update", "-n", "node.session.auth.username", "-v", username] output = call(dbg, cmd) log.debug("%s: output = %s" % (dbg, output)) cmd = ["/usr/sbin/iscsiadm", "-m", "node", "-T", iqn, "--portal", portal, "--op", "update", "-n", "node.session.auth.password", "-v", password] output = call(dbg, cmd) log.debug("%s: output = %s" % (dbg, output))
def getmanufacturer(dbg, path): cmd = ["sginfo", "-M", path] try: for line in filter(match_vendor, call(dbg, cmd).split('\n')): return line.replace(' ','').split(':')[-1] except: return ''
def list(dbg): results = [] for line in call(dbg, ["tap-ctl", "list"]).split("\n"): bits = line.split() if bits == []: continue prefix = "pid=" pid = None if bits[0].startswith(prefix): pid = int(bits[0][len(prefix):]) minor = None prefix = "minor=" if len(bits) <= 1: results.append(Tapdisk(None, pid, None)) continue if bits[1].startswith(prefix): minor = int(bits[1][len(prefix):]) if len(bits) <= 3: results.append(Tapdisk(minor, pid, None)) else: before, args = line.split("args=") prefix = "aio:" if args.startswith(prefix): this = image.Raw(os.path.realpath(args[len(prefix):])) results.append(Tapdisk(minor, pid, this)) prefix = "vhd:" if args.startswith(prefix): this = image.Vhd(os.path.realpath(args[len(prefix):])) results.append(Tapdisk(minor, pid, this)) return results
def leaf_coalesce_snapshot(key, conn, cb, opq): print("leaf_coalesce_snapshot key=%s" % key) key_path = cb.volumeGetPath(opq, key) res = conn.execute( "select name,parent,description,uuid,vsize from VDI where rowid = (?)", (int(key), )).fetchall() (p_name, p_parent, p_desc, p_uuid, p_vsize) = res[0] tap_ctl_pause(key, conn, cb, opq) res = conn.execute("insert into VDI(snap, parent) values (?, ?)", (0, p_parent)) base_name = str(res.lastrowid) base_path = cb.volumeRename(opq, key, base_name) cb.volumeCreate(opq, key, int(p_vsize)) cmd = ["/usr/bin/vhd-util", "snapshot", "-n", key_path, "-p", base_path] output = call("GC", cmd) res = conn.execute("update VDI set parent = (?) where rowid = (?)", ( int(base_name), int(key), )) conn.commit() tap_ctl_unpause(key, conn, cb, opq)
def attach(self, dbg, uri, domain): # FIXME: add lvm activation code u = urlparse.urlparse(uri) (vgname, lvname, scsid) = self._getVgLvScsid(dbg, u.path) log.debug("%s Vg=%s Lv=%s Scsid%s" % (dbg, vgname, lvname, scsid)) vg = self._vgOpen(dbg, vgname, "r", scsid) lv = vg.lvFromName(lvname) lv.activate() vg.close() cmd = ["/usr/bin/vhd-util", "query", "-n", u.path, "-P"] output = call(dbg, cmd) log.debug("%s output=%s" % (dbg, output)) output = output[:-1] if output[-6:] == "parent": log.debug("No Parent") else: output = output.replace("--", "-") log.debug("%s" % output[-36:]) activation_file = "/var/run/nonpersistent/" + vgname + "/" + output[-36:] if (not os.path.exists(activation_file)): vg = self._vgOpen(dbg, vgname, "r", scsid) lv = vg.lvFromName(output[-36:]) log.debug("Activating %s" % lv.getName()) lv.activate() vg.close() open(activation_file, 'a').close() tap = tapdisk.create(dbg) tapdisk.save_tapdisk_metadata(dbg, u.path, tap) return { 'domain_uuid': '0', 'implementation': ['Tapdisk3', tap.block_device()], }
def list(dbg): results = [] for line in call(dbg, ["tap-ctl", "list"]).split("\n"): bits = line.split() if bits == []: continue prefix = "pid=" pid = None if bits[0].startswith(prefix): pid = int(bits[0][len(prefix):]) minor = None prefix = "minor=" if bits[1].startswith(prefix): minor = int(bits[1][len(prefix):]) if len(bits) <= 3: results.append(Tapdisk(minor, pid, None)) else: before, args = line.split("args=") prefix = "aio:" if args.startswith(prefix): this = image.Raw(os.path.realpath(args[len(prefix):])) results.append(Tapdisk(minor, pid, this)) prefix = "vhd:" if args.startswith(prefix): this = image.Vhd(os.path.realpath(args[len(prefix):])) results.append(Tapdisk(minor, pid, this)) return results
def getmanufacturer(dbg, path): cmd = ["sginfo", "-M", path] try: for line in filter(match_vendor, call(dbg, cmd).split('\n')): return line.replace(' ', '').split(':')[-1] except: return ''
def _mount(self, dbg, nfs_path, sr_uuid): """Mount the NFS share to a temporary local folder""" mnt_path = self._mount_path(sr_uuid) try: os.makedirs(mnt_path) except OSError as exc: if exc.errno == errno.EEXIST and os.path.isdir(mnt_path): pass else: raise if not os.path.ismount(mnt_path): cmd = [ '/usr/bin/mount', '-t', 'nfs', '-o', 'noatime,nodiratime', nfs_path, mnt_path ] call(dbg, cmd) return mnt_path
def __init__(self, dbg, base_device): self.name = name_of_device(base_device) t = table(base_device) existing = call(dbg, ["dmsetup", "table", self.name]).strip() if existing != t: message = "Device mapper device %s has table %s, expected %s" % (self.name, existing, t) log.error("%s: %s" % (dbg, message)) raise xapi.InternalError(message)
def non_leaf_coalesce(key, parent_key, conn, cb, opq): print("non_leaf_coalesce key=%s, parent=%s" % (key, parent_key)) #conn.execute("key is coalescing") key_path = cb.volumeGetPath(opq, key) parent_path = cb.volumeGetPath(opq, parent_key) cmd = ["/usr/bin/vhd-util", "coalesce", "-n", key_path] call("GC", cmd) #conn.execute("key coalesced") # reparent all of the children to this node's parent children = conn.execute("select key from VDI where parent = (?)", (int(key), )).fetchall() for child in children: child_key = str(child[0]) child_path = cb.volumeGetPath(opq, child_key) res = conn.execute("update VDI set parent = (?) where rowid = (?)", ( parent_key, child_key, )) #conn.execute("child is being reparented to parent") # pause all leafs having child as an ancestor leaves = [] find_leaves(child_key, conn, leaves) for leaf in leaves: tap_ctl_pause(leaf, conn, cb, opq) # reparent child to grandparent cmd = [ "/usr/bin/vhd-util", "modify", "-n", child_path, "-p", parent_path ] call("GC", cmd) # unpause all leafs having child as an ancestor for leaf in leaves: tap_ctl_unpause(leaf, conn, cb, opq) # remove key cb.volumeDestroy(opq, key) res = conn.execute("delete from VDI where rowid = (?)", (int(key), )) conn.commit()
def getPVName(dbg, sr): try: uri = getFromSRMetadata(dbg, sr, 'uri') dev_path = blkinfo.get_device_path(dbg, uri) cmd = ["readlink", "-f", dev_path] output = call(dbg, cmd) return output.rstrip() except Exception,e: log.debug("Exception raised in getting PV name: %s" %str(e))
def __init__(self, dbg, base_device): self.name = name_of_device(base_device) t = table(base_device) existing = call(dbg, ["dmsetup", "table", self.name]).strip() if existing != t: message = ("Device mapper device %s has table %s, expected %s" % (self.name, existing, t)) log.error("%s: %s" % (dbg, message)) raise xapi.InternalError(message)
def listSessions(dbg): '''Return a list of (sessionid, portal, targetIQN) pairs representing logged-in iSCSI sessions.''' cmd = ["/usr/sbin/iscsiadm", "-m", "session"] output = call(dbg, cmd, error=False) # if there are none, this command exits with rc 21 # e.g. "tcp: [1] 10.71.153.28:3260,1 iqn.2009-01.xenrt.test:iscsi6da966ca # (non-flash)" return [tuple([int(x.split(' ')[1].strip('[]')), x.split(' ')[2], x.split(' ')[3]]) for x in output.split('\n') if x <> '']
def get_format(dbg, dev_path): # FIXME:Check path exists cmd = ["/usr/sbin/blkid", "-s", "TYPE", dev_path] output = call(dbg, cmd) # output should look like # <dev_path>: TYPE="<type>" format_type = output.split(":")[1].split("=")[1].strip(' \t\n\r') format_type = format_type[1:-1] return format_type
def getSCSIid(dbg, path): """Get the SCSI id of a block device Input: path -- (str) path to block device; can be symlink Return: scsi_id -- (str) the device's SCSI id Raise: util.CommandException """ try: stdout = call(dbg, [SCSI_ID_BIN, '-g', '--device', path]) except: # fallback call dev = rawdev(path) stdout = call(dbg, [SCSI_ID_BIN, '-g', '-s', '/block/%s' % dev]) return SCSIid_sanitise(stdout[:-1])
def discover(self, dbg, address): return map(lambda x: Target(x), call(dbg, ["iscsiadm", "--mode", "discoverydb", "--type", "sendtargets", "--portal", address, "--discover"]).split("\n"))
def login(dbg, uri, keys): iqn_map = discoverIQN(dbg, keys) output = iqn_map[0] # FIXME: only take the first one returned. # This might not always be the one we want. log.debug("%s: output = %s" % (dbg, output)) portal = output[0] # FIXME: error handling # Provide authentication details if necessary if keys['username'] != None: set_chap_settings(dbg, portal, keys['target'], keys['username'], keys['password']) # Lock refcount file before login if not os.path.exists(ISCSI_REFDIR): os.mkdir(ISCSI_REFDIR) filename = os.path.join(ISCSI_REFDIR, keys['iqn']) f = lock_file(dbg, filename, "a+") current_sessions = listSessions(dbg) log.debug("%s: current iSCSI sessions are %s" % (dbg, current_sessions)) sessionid = findMatchingSession(dbg, portal, keys['iqn'], current_sessions) if sessionid: # If there's an existing session, rescan it # in case new LUNs have appeared in it log.debug("%s: rescanning session %d for %s on %s" % (dbg, sessionid, keys['iqn'], keys['target'])) rescanSession(dbg, sessionid) else: # Otherwise, perform a fresh login cmd = ["/usr/sbin/iscsiadm", "-m", "node", "-T", keys['iqn'], "--portal", portal, "-l"] output = call(dbg, cmd) log.debug("%s: output = %s" % (dbg, output)) # FIXME: check for success # Increment refcount found = False for line in f.readlines(): if line.find(uri) != -1: found = True if not found: f.write("%s\n" % uri) unlock_file(dbg, f) waitForDevice(dbg) # Return path to logged in target target_path = "/dev/iscsi/%s/%s" % (keys['iqn'], portal) return target_path
def getserial(dbg, path): dev = os.path.join('/dev',getdev(path)) try: cmd = ["sginfo", "-s", dev] text = re.sub("\s+","",call(dbg, cmd)) except: raise xapi.storage.api.volume.Unimplemented( "An error occured querying device serial number [%s]" % dev) try: return text.split("'")[1] except: return ''
def getserial(dbg, path): dev = os.path.join('/dev', getdev(path)) try: cmd = ["sginfo", "-s", dev] text = re.sub("\s+", "", call(dbg, cmd)) except: raise xapi.storage.api.volume.Unimplemented( "An error occured querying device serial number [%s]" % dev) try: return text.split("'")[1] except: return ''
def non_leaf_coalesce(key, parent_key, conn, cb, opq): print ("non_leaf_coalesce key=%s, parent=%s" % (key, parent_key)) #conn.execute("key is coalescing") key_path = cb.volumeGetPath(opq, key) parent_path = cb.volumeGetPath(opq, parent_key) cmd = ["/usr/bin/vhd-util", "coalesce", "-n", key_path] call("GC", cmd) #conn.execute("key coalesced") # reparent all of the children to this node's parent children = conn.execute("select key from VDI where parent = (?)",(int(key),)).fetchall() for child in children: child_key = str(child[0]) child_path = cb.volumeGetPath(opq, child_key) res = conn.execute("update VDI set parent = (?) where rowid = (?)", (parent_key, child_key,) ) #conn.execute("child is being reparented to parent") # pause all leafs having child as an ancestor leaves = [] find_leaves(child_key, conn, leaves) for leaf in leaves: tap_ctl_pause(leaf, conn, cb, opq) # reparent child to grandparent cmd = ["/usr/bin/vhd-util", "modify", "-n", child_path, "-p", parent_path] call("GC", cmd) # unpause all leafs having child as an ancestor for leaf in leaves: tap_ctl_unpause(leaf, conn, cb, opq) # remove key cb.volumeDestroy(opq, key) res = conn.execute("delete from VDI where rowid = (?)", (int(key),)) conn.commit()
def create(self, dbg, sr_uuid, configuration, name, description): log.debug('{}: SR.create: config={}, sr_uuid={}'.format( dbg, configuration, sr_uuid)) uri = configuration['device'] dev_path = urlparse.urlparse(uri).path log.debug('{}: SR.create: dev_path={}'.format(dbg, dev_path)) # Make the filesystem cmd = ['/usr/sbin/mkfs.ext4', dev_path] call(dbg, cmd) # Temporarily mount the filesystem so we can write the SR metadata sr = self._mount_path(sr_uuid) util.mkdir_p(sr) ext4_mount(dbg, dev_path, sr) # Create the metadata database importlib.import_module('ext4-ng').Callbacks().create_database(sr) read_caching = True if 'read_caching' in configuration: if configuration['read_caching'] not in [ 'true', 't', 'on', '1', 'yes']: read_caching = False meta = { 'name': name, 'description': description, 'uri': uri, 'unique_id': sr_uuid, 'read_caching': read_caching, 'keys': {} } util.update_sr_metadata(dbg, 'file://' + sr, meta) ext4_unmount(dbg, sr) configuration['sr_uuid'] = sr_uuid return configuration
def create(dbg, host, name): """Return an active nbd device associated with the given name, creating a fresh one if one doesn't already exist.""" existing = find(dbg, host, name) if existing: return existing used = set() try: used = set(os.listdir(persist_root)) except OSError as exc: if exc.errno == errno.ENOENT: pass else: raise all = set(filter(lambda x: x.startswith("nbd"), os.listdir("/dev"))) for nbd in all.difference(used): # try: call(dbg, ["nbd-client", host, "/dev/" + nbd, "-name", name]) return Nbd(host, name, nbd) # except: # pass # try another one raise NoAvailableNbd()
def mount(dbg, dev_path): # FIXME: Ensure corosync+dlm are configured and running mnt_path = os.path.abspath(mountpoint_root + dev_path) try: os.makedirs(mnt_path) except OSError as exc: if exc.errno == errno.EEXIST and os.path.isdir(mnt_path): pass else: raise if not os.path.ismount(mnt_path): cmd = ["/usr/sbin/modprobe", "gfs2"] call(dbg, cmd) cmd = ["/usr/bin/mount", "-t", "gfs2", "-o", "noatime,nodiratime", dev_path, mnt_path] try: call(dbg, cmd) except: raise return mnt_path
def from_path(dbg, path): path = os.path.realpath(path) for line in call(dbg, ["losetup", "-a"]).split("\n"): line = line.strip() if line != "": bits = line.split() loop = bits[0][0:-1] open_bracket = line.find('(') close_bracket = line.find(')') this_path = line[open_bracket + 1:close_bracket] if this_path == path: return Loop(path, loop) return None
def login(dbg, target, iqn, usechap=False, username=None, password=None): cmd = ["/usr/sbin/iscsiadm", "-m", "discovery", "-t", "st", "-p", target] output = call(dbg, cmd).split('\n')[0] # FIXME: only take the first one returned. # This might not always be the one we want. log.debug("%s: output = %s" % (dbg, output)) portal = output.split(' ')[0] # FIXME: error handling # Provide authentication details if necessary if usechap: cmd = [ "/usr/sbin/iscsiadm", "-m", "node", "-T", iqn, "--portal", portal, "--op", "update", "-n", "node.session.auth.authmethod", "-v", "CHAP" ] output = call(dbg, cmd) log.debug("%s: output = %s" % (dbg, output)) cmd = [ "/usr/sbin/iscsiadm", "-m", "node", "-T", iqn, "--portal", portal, "--op", "update", "-n", "node.session.auth.username", "-v", username ] output = call(dbg, cmd) log.debug("%s: output = %s" % (dbg, output)) cmd = [ "/usr/sbin/iscsiadm", "-m", "node", "-T", iqn, "--portal", portal, "--op", "update", "-n", "node.session.auth.password", "-v", password ] output = call(dbg, cmd) log.debug("%s: output = %s" % (dbg, output)) # Log in cmd = [ "/usr/sbin/iscsiadm", "-m", "node", "-T", iqn, "--portal", portal, "-l" ] output = call(dbg, cmd) log.debug("%s: output = %s" % (dbg, output))
def listSessions(dbg): '''Return a list of (sessionid, portal, targetIQN) pairs representing logged-in iSCSI sessions.''' cmd = ["/usr/sbin/iscsiadm", "-m", "session"] output = call(dbg, cmd, error=False) # if there are none, this command exits with rc 21 # e.g. "tcp: [1] 10.71.153.28:3260,1 iqn.2009-01.xenrt.test:iscsi6da966ca # (non-flash)" return [ tuple([ int(x.split(' ')[1].strip('[]')), x.split(' ')[2], x.split(' ')[3] ]) for x in output.split('\n') if x <> '' ]