def _resize(cls, dbg, sr, key, new_size, image_meta): log.debug("%s: librbd.QCOW2Volume._resize: SR: %s Key: %s New_size: %s" % (dbg, sr, key, new_size)) # TODO: Implement overhead calculation for QCOW2 format new_size = utils.validate_and_round_vhd_size(new_size) new_rbd_size = utils.fullSizeVHD(new_size) ceph_cluster = ceph_utils.connect(dbg, sr) uri = "%s/%s" % (sr, key) image_name = "%s%s/%s%s" % (utils.RBDPOOL_PREFIX, utils.get_sr_uuid_by_uri(dbg, sr), utils.VDI_PREFIXES[utils.get_vdi_type_by_uri(dbg, uri)], key) try: rbd_utils.resize(dbg, ceph_cluster, image_name, new_rbd_size) except Exception: raise Volume_does_not_exist(key) finally: ceph_utils.disconnect(dbg, ceph_cluster) #nbd_device = call(dbg, ["/usr/bin/rbd-nbd", # "map", # image_name]).rstrip('\n') call(dbg, ["/usr/lib64/qemu-dp/bin/qemu-img", "resize", "rbd:%s" % image_name, str(new_size)])
def destroy(self, dbg): self.pause(dbg) call( dbg, ["tap-ctl", "destroy", "-m", str(self.minor), "-p", str(self.pid)])
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 unpause(self, dbg, f=None): cmd = ["tap-ctl", "unpause", "-m", str(self.minor), "-p", str(self.pid)] if f: cmd = cmd + ["-a", str(f)] if self.secondary is not None: cmd = cmd + ["-2 ", self.secondary] call(dbg, cmd)
def pause(self, dbg): call(dbg, ["tap-ctl", "pause", "-m", str(self.minor), "-p", str(self.pid)])
def close(self, dbg): call(dbg, ["tap-ctl", "close", "-m", str(self.minor), "-p", str(self.pid)]) self.f = None
def destroy(self, dbg): self.pause(dbg) call(dbg, ["tap-ctl", "destroy", "-m", str(self.minor), "-p", str(self.pid)])
def unpause(self, dbg, f=None): cmd = [ "tap-ctl", "unpause", "-m", str(self.minor), "-p", str(self.pid) ] if f: cmd = cmd + ["-a", str(f)] if self.secondary is not None: cmd = cmd + ["-2 ", self.secondary] call(dbg, cmd)
def open(self, dbg, f, o_direct=True): assert (isinstance(f, image.Cow) 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) # TODO: FIXME: break link to XAPI # 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 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) # TODO: FIXME: break link to XAPI #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 create(dbg, vol_path, size_mib): cmd = [ QEMU_IMG, 'create', '-f', 'qcow2', '-o', 'size={}M,cluster_size={}'.format(size_mib, QCOW2_CLUSTER_SIZE), vol_path ] return call(dbg, cmd)
def create(dbg, vol_path, size_mib): cmd = [ VHD_UTIL_BIN, 'create', '-n', vol_path, '-s', str(size_mib), '-S', str(MSIZE_MIB) ] return call(dbg, cmd)
def open_2(self, dbg, type_, file_path, options): #pid, minor, _type, _file, options assert type_ in IMAGE_TYPES self.type_file = ':'.join([type_, os.path.realpath(file_path)]) cmd = [ 'tap-ctl', 'open', '-m', str(self.minor), '-p', str(self.pid), '-a', self.type_file ] if 'readonly' in options and options['readonly']: cmd.append('-R') if 'leaf_cache' in options and options['leaf_cache']: cmd.append('-r') if ('existing_parent' in options and options['existing_parent'] is not None): cmd.append('-e') cmd.append(str(options['existing_parent'])) if ('secondary' in options and 'type' in options['secondary'] and 'file_path' in options['secondary']): assert options['secondary']['type'] in IMAGE_TYPES cmd.append('-2') cmd.append( ':'.join([ options['secondary']['type'], os.path.realpath(options['secondary']['file_path']) ]) ) if 'standby' in options and options['standby']: cmd.append('-s') if 'timeout' in options and options['timeout'] is not None: cmd.append('-t') cmd.append(str(options['timeout'])) if 'o_direct' in options and options['o_direct'] == False: cmd.append('-D') call(dbg, cmd)
def create_snapshot(dbg, backing_file, vol_path): cmd = [ QEMU_IMG, 'create', '-f', 'qcow2', '-o', 'backing_file={},cluster_size={}'.format(backing_file, QCOW2_CLUSTER_SIZE), vol_path ] return call(dbg, cmd)
def get_parent(dbg, vol_path): cmd = [QEMU_IMG, 'info', '--output=json', vol_path] ret = call(dbg, cmd) d = json.loads(ret) if "backing-filename" in d.keys(): return d["backing-filename"] else: return "None"
def close(self, dbg): log.debug( "%s: qemudisk.Qemudisk.close: vdi_uuid %s pid %d qmp_sock %s" % (dbg, self.vdi_uuid, self.pid, self.qmp_sock)) _qmp_ = qmp.QEMUMonitorProtocol(self.qmp_sock) _qmp_.connect() if platform.linux_distribution()[1] == '7.5.0': try: path = "{}/{}".format(utils.VAR_RUN_PREFIX, self.vdi_uuid) with open(path, 'r') as f: line = f.readline().strip() call(dbg, ["/usr/bin/xenstore-write", line, "5"]) os.unlink(path) except: log.debug( "%s: qemudisk.Qemudisk.close: There was no xenstore setup" % dbg) elif platform.linux_distribution()[1] == '7.6.0': path = "{}/{}".format(utils.VAR_RUN_PREFIX, self.vdi_uuid) try: with open(path, 'r') as f: line = f.readline().strip() os.unlink(path) args = { 'type': 'qdisk', 'domid': int(re.search('domain/(\d+)/', line).group(1)), 'devid': int(re.search('vbd/(\d+)/', line).group(1)) } _qmp_.command(dbg, "xen-unwatch-device", **args) except: log.debug( "%s: qemudisk.Qemudisk.close: There was no xenstore setup" % dbg) try: # Stop the NBD server _qmp_.command("nbd-server-stop") # Remove the block device args = {"node-name": ROOT_NODE_NAME} _qmp_.command("blockdev-del", **args) except Exception: raise Volume_does_not_exist(self.vdi_uuid) finally: _qmp_.close()
def is_empty(dbg, vol_path): cmd = [QEMU_IO, '--cmd', 'open ' + vol_path, '--cmd', 'map'] ret = call(dbg, cmd) lines = ret.splitlines() if len(lines) == 1: log.debug("Empty, {}".format(lines[0])) return "not allocated" in lines[0] else: log.debug("Not empty {}".format(lines)) return False
def open_2(self, dbg, type_, file_path, options): # pid, minor, _type, _file, options assert type_ in IMAGE_TYPES self.type_file = ':'.join([type_, os.path.realpath(file_path)]) cmd = [ 'tap-ctl', 'open', '-m', str(self.minor), '-p', str(self.pid), '-a', self.type_file ] if 'readonly' in options and options['readonly']: cmd.append('-R') if 'leaf_cache' in options and options['leaf_cache']: cmd.append('-r') if ('existing_parent' in options and options['existing_parent'] is not None): cmd.append('-e') cmd.append(str(options['existing_parent'])) if ('secondary' in options and 'type' in options['secondary'] and 'file_path' in options['secondary']): assert options['secondary']['type'] in IMAGE_TYPES cmd.append('-2') cmd.append(':'.join([ options['secondary']['type'], os.path.realpath(options['secondary']['file_path']) ])) if 'standby' in options and options['standby']: cmd.append('-s') if 'timeout' in options and options['timeout'] is not None: cmd.append('-t') cmd.append(str(options['timeout'])) if 'o_direct' in options and not options['o_direct']: cmd.append('-D') call(dbg, cmd)
def list(minor=None, pid=None, type_=None, file_path=None): result_list = [] search_attributes = set() cmd = ['tap-ctl', 'list'] if minor is not None: cmd += ['-m', str(minor)] search_attributes.add('minor') if pid is not None: cmd += ['-p', str(pid)] search_attributes.add('pid') if type_ is not None: cmd += ['-t', str(type_)] search_attributes.add('type') if file_path is not None: cmd += ['-f', str(file_path)] search_attributes.add('file_path') stdout = call('', cmd).rstrip().split('\n') # Example return: # 'pid=6068 minor=0 state=0 # args=vhd:/run/sr-mount/<mount_point>\n' for line in stdout: # pid minor state args tap_dict = {} for field in line.split(): name, value = field.split('=') if name in ('pid', 'minor'): tap_dict[name] = int(value) elif name == 'state': tap_dict[name] = int(value, 0x10) elif name == 'args': args = value.split(':') tap_dict['type'] = args[0] tap_dict['file_path'] = args[1] for attr in search_attributes: if attr not in tap_dict: break else: result_list.append(tap_dict) return result_list
def snapshot(dbg, new_cow_path, parent_cow_path, force_parent_link): """Perform COW snapshot. Args: new_cow_path: (str) Absolute path to the COW that will be created parent_cow_path: (str) Absolute path to the existing COW we wish to snapshot force_parent_link: (bool) If 'True', link new COW to the parent COW, even if the parent is empty """ cmd = [ VHD_UTIL_BIN, 'snapshot', '-n', new_cow_path, '-p', parent_cow_path ] if force_parent_link: cmd.append('-e') return call(dbg, cmd)
def snapshot(dbg, new_vhd_path, parent_vhd_path, force_parent_link): """Perform VHD snapshot. Args: new_vhd_path: (str) Absolute path to the VHD that will be created parent_vhd_path: (str) Absolute path to the existing VHD we wish to snapshot force_parent_link: (bool) If 'True', link new VHD to the parent VHD, even if the parent is empty """ cmd = [ VHD_UTIL_BIN, 'snapshot', '-n', new_vhd_path, '-p', parent_vhd_path, '-S', str(MSIZE_MIB) ] if force_parent_link: cmd.append('-e') return call(dbg, cmd)
def is_empty(dbg, vol_path): cmd = [VHD_UTIL_BIN, 'read', OPT_LOG_ERR, '-B', '-n', vol_path] ret = call(dbg, cmd) return VHDUtil.__count_bits(ret) == 0
def set_parent(dbg, vol_path, parent_path): cmd = [VHD_UTIL_BIN, 'modify', '-n', vol_path, '-p', parent_path] return call(dbg, cmd)
def get_vsize(dbg, vol_path): # vsize is returned in MB but we want to return bytes cmd = [VHD_UTIL_BIN, 'query', '-n', vol_path, '-v'] out = call(dbg, cmd).rstrip() return int(out) * MEBIBYTE
def get_parent(dbg, vol_path): cmd = [VHD_UTIL_BIN, 'query', '-n', vol_path, '-p'] return call(dbg, cmd).rstrip()
def resize(dbg, vol_path, size_mib): cmd = [QEMU_IMG, 'resize', vol_path, str(size_mib) + 'M'] return call(dbg, cmd)
def coalesce(dbg, vol_path): cmd = [VHD_UTIL_BIN, 'coalesce', '-n', vol_path] return call(dbg, cmd)
def reset(dbg, vol_path): """Zeroes out the disk.""" cmd = [VHD_UTIL_BIN, 'modify', OPT_LOG_ERR, '-z', '-n', vol_path] return call(dbg, cmd)
def is_empty(dbg, vol_path): cmd = [VHD_UTIL_BIN, 'read', OPT_LOG_ERR, '-B', '-n', vol_path] ret = call(dbg, cmd) return __count_bits(ret) == 0
def set_parent(dbg, vol_path, parent_path): cmd = [ QEMU_IMG, 'rebase', '-t', 'none', '-T', 'none', vol_path, '-b', parent_path, '-u' ] return call(dbg, cmd)
def coalesce(dbg, vol_path, parent_path): cmd = [VHD_UTIL_BIN, 'coalesce', '-n', vol_path] return call(dbg, cmd)
def coalesce(dbg, vol_path, parent_path): cmd = [ QEMU_IMG, 'commit', '-q', '-t', 'none', vol_path, '-b', parent_path, '-d' ] return call(dbg, cmd)
def get_psize(dbg, vol_path): cmd = [VHD_UTIL_BIN, 'query', '-n', vol_path, '-s'] return call(dbg, cmd).rstrip()
def _create(cls, dbg, sr, name, description, size, sharable, image_meta): log.debug("%s: librbd.QCOW2Volume._create: SR: %s Name: %s Description: %s Size: %s" % (dbg, sr, name, description, size)) image_meta[meta.TYPE_TAG] = utils.get_vdi_type_by_uri(dbg, image_meta[meta.URI_TAG][0]) ceph_cluster = ceph_utils.connect(dbg, sr) image_name = "%s%s/%s%s" % (utils.RBDPOOL_PREFIX, utils.get_sr_uuid_by_uri(dbg, sr), utils.VDI_PREFIXES[image_meta[meta.TYPE_TAG]], image_meta[meta.UUID_TAG]) # TODO: Implement overhead calculation for QCOW2 format size = utils.validate_and_round_vhd_size(size) rbd_size = utils.fullSizeVHD(size) try: rbd_utils.create(dbg, ceph_cluster, image_name, rbd_size) meta.RBDMetadataHandler.update(dbg, image_meta[meta.URI_TAG][0], image_meta) except Exception: try: rbd_utils.remove(dbg, ceph_cluster, image_name) except Exception: pass finally: raise Volume_does_not_exist(image_meta[meta.UUID_TAG]) finally: ceph_utils.disconnect(dbg, ceph_cluster) #Datapath.attach(dbg, image_meta[meta.URI_TAG][0], 0) #Datapath.activate(dbg, image_meta[meta.URI_TAG][0], 0, 'raw') #nbd_device=call(dbg, ["/opt/xensource/libexec/nbd_client_manager.py", # "connect", # "--path", # utils.VAR_RUN_PREFIX + "/qemu-nbd.{}".format(image_meta[meta.UUID_TAG]), # "--exportname", # "qemu_node"]) nbd_device = call(dbg, ["/usr/bin/rbd-nbd", "map", image_name]).rstrip('\n') call(dbg, ["/usr/lib64/qemu-dp/bin/qemu-img", "create", "-f", image_meta[meta.TYPE_TAG], nbd_device, str(size)]) call(dbg, ["/usr/bin/rbd-nbd", "unmap", nbd_device]) #call(dbg, ["/opt/xensource/libexec/nbd_client_manager.py", # "disconnect", # "--device", # nbd_device]) #Datapath.deactivate(dbg, image_meta[meta.URI_TAG][0], 0) #Datapath.detach(dbg, image_meta[meta.URI_TAG][0], 0) return image_meta
def resize(dbg, vol_path, size_mib): cmd = [ VHD_UTIL_BIN, 'resize', '-n', vol_path, '-s', str(size_mib), '-f' ] return call(dbg, cmd)
def resize(dbg, vol_path, size_mib): cmd = [VHD_UTIL_BIN, 'resize', '-n', vol_path, '-s', str(size_mib), '-f'] return call(dbg, cmd)
def _clone(cls, dbg, sr, key, mode, base_meta): log.debug("%s: librbd.QCOW2Volume.clone: SR: %s Key: %s Mode: %s" % (dbg, sr, key, mode)) # TODO: Implement overhead calculation for QCOW2 format size = utils.validate_and_round_vhd_size(base_meta[meta.VIRTUAL_SIZE_TAG]) rbd_size = utils.fullSizeVHD(size) ceph_cluster = ceph_utils.connect(dbg, sr) clone_uuid = str(uuid.uuid4()) clone_name = "%s%s/%s%s" % (utils.RBDPOOL_PREFIX, utils.get_sr_uuid_by_uri(dbg, sr), utils.VDI_PREFIXES[utils.get_vdi_type_by_uri(dbg, sr)], clone_uuid) try: if base_meta[meta.KEY_TAG] == key: base_name = "%s%s/%s%s" % (utils.RBDPOOL_PREFIX, utils.get_sr_uuid_by_uri(dbg, sr), utils.VDI_PREFIXES[utils.get_vdi_type_by_uri(dbg, sr)], key) new_base_uuid = str(uuid.uuid4()) new_base_name = "%s%s/%s%s" % (utils.RBDPOOL_PREFIX, utils.get_sr_uuid_by_uri(dbg, sr), utils.VDI_PREFIXES[utils.get_vdi_type_by_uri(dbg, sr)], new_base_uuid) rbd_utils.rename(dbg, ceph_cluster, base_name, new_base_name) rbd_utils.create(dbg, ceph_cluster, base_name, rbd_size) rbd_utils.create(dbg, ceph_cluster, clone_name, rbd_size) base_nbd_device = call(dbg, ["/usr/bin/rbd-nbd", "map", base_name]).rstrip('\n') clone_nbd_device = call(dbg, ["/usr/bin/rbd-nbd", "map", clone_name]).rstrip('\n') call(dbg, ["/usr/lib64/qemu-dp/bin/qemu-img", "create", "-f", base_meta[meta.TYPE_TAG], "-b", "rbd:%s" % new_base_name, base_nbd_device]) call(dbg, ["/usr/lib64/qemu-dp/bin/qemu-img", "create", "-f", base_meta[meta.TYPE_TAG], "-b", "rbd:%s" % new_base_name, clone_nbd_device]) call(dbg, ["/usr/bin/rbd-nbd", "unmap", clone_nbd_device]) call(dbg, ["/usr/bin/rbd-nbd", "unmap", base_nbd_device]) new_base_meta = copy.deepcopy(base_meta) new_base_meta[meta.NAME_TAG] = "(base) %s" % new_base_meta[meta.NAME_TAG] new_base_meta[meta.KEY_TAG] = new_base_uuid new_base_meta[meta.UUID_TAG] = new_base_uuid new_base_meta[meta.URI_TAG] = ["%s/%s" % (sr, new_base_uuid)] new_base_meta[meta.READ_WRITE_TAG] = False if meta.ACTIVE_ON_TAG in new_base_meta: Datapath.snapshot(dbg,new_base_meta[meta.URI_TAG][0], base_meta[meta.URI_TAG][0], 0) if meta.ACTIVE_ON_TAG in new_base_meta: new_base_meta[meta.ACTIVE_ON_TAG] = None new_base_meta[meta.QEMU_PID_TAG] = None new_base_meta[meta.QEMU_NBD_SOCK_TAG] = None new_base_meta[meta.QEMU_QMP_SOCK_TAG] = None new_base_meta[meta.QEMU_QMP_LOG_TAG] = None meta.RBDMetadataHandler.update(dbg, new_base_meta[meta.URI_TAG][0], new_base_meta) meta.RBDMetadataHandler.update(dbg, base_meta[meta.URI_TAG][0], base_meta) else: base_name = "%s%s/%s%s" % (utils.RBDPOOL_PREFIX, utils.get_sr_uuid_by_uri(dbg, sr), utils.VDI_PREFIXES[utils.get_vdi_type_by_uri(dbg, sr)], base_meta[meta.UUID_TAG]) rbd_utils.create(dbg, ceph_cluster, clone_name, rbd_size) clone_nbd_device = call(dbg, ["/usr/bin/rbd-nbd", "map", clone_name]).rstrip('\n') call(dbg, ["/usr/lib64/qemu-dp/bin/qemu-img", "create", "-f", base_meta[meta.TYPE_TAG], "-b", "rbd:%s" % base_name, clone_nbd_device]) call(dbg, ["/usr/bin/rbd-nbd", "unmap", clone_nbd_device]) clone_meta = copy.deepcopy(base_meta) clone_meta[meta.KEY_TAG] = clone_uuid clone_meta[meta.UUID_TAG] = clone_uuid clone_meta[meta.URI_TAG] = ["%s/%s" % (sr, clone_uuid)] if meta.ACTIVE_ON_TAG in clone_meta: clone_meta.pop(meta.ACTIVE_ON_TAG, None) clone_meta.pop(meta.QEMU_PID_TAG, None) clone_meta.pop(meta.QEMU_NBD_SOCK_TAG, None) clone_meta.pop(meta.QEMU_QMP_SOCK_TAG, None) clone_meta.pop(meta.QEMU_QMP_LOG_TAG, None) if mode is 'snapshot': clone_meta[meta.READ_WRITE_TAG] = False clone_meta[meta.SNAPSHOT_OF_TAG] = new_base_meta[meta.UUID_TAG] elif mode is 'clone': clone_meta[meta.READ_WRITE_TAG] = True meta.RBDMetadataHandler.update(dbg, clone_meta[meta.URI_TAG][0], clone_meta) return clone_meta except Exception: raise Volume_does_not_exist(key) finally: ceph_utils.disconnect(dbg, ceph_cluster)