Пример #1
0
    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)])
Пример #2
0
 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)])
Пример #8
0
 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)
Пример #9
0
 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
Пример #10
0
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)
Пример #11
0
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)
Пример #12
0
 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)
Пример #13
0
 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)
Пример #14
0
    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)
Пример #15
0
 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)
Пример #16
0
 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"
Пример #17
0
 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)
Пример #18
0
    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()
Пример #19
0
 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
Пример #20
0
    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)
Пример #21
0
    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
Пример #22
0
    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
Пример #23
0
    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)
Пример #24
0
    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)
Пример #25
0
 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
Пример #26
0
 def set_parent(dbg, vol_path, parent_path):
     cmd = [VHD_UTIL_BIN, 'modify', '-n', vol_path, '-p', parent_path]
     return call(dbg, cmd)
Пример #27
0
 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
Пример #28
0
 def get_parent(dbg, vol_path):
     cmd = [VHD_UTIL_BIN, 'query', '-n', vol_path, '-p']
     return call(dbg, cmd).rstrip()
Пример #29
0
 def resize(dbg, vol_path, size_mib):
     cmd = [QEMU_IMG, 'resize', vol_path, str(size_mib) + 'M']
     return call(dbg, cmd)
Пример #30
0
 def coalesce(dbg, vol_path):
     cmd = [VHD_UTIL_BIN, 'coalesce', '-n', vol_path]
     return call(dbg, cmd)
Пример #31
0
 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)
Пример #32
0
 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
Пример #33
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)
Пример #34
0
 def coalesce(dbg, vol_path, parent_path):
     cmd = [VHD_UTIL_BIN, 'coalesce', '-n', vol_path]
     return call(dbg, cmd)
Пример #35
0
 def coalesce(dbg, vol_path, parent_path):
     cmd = [
         QEMU_IMG, 'commit', '-q', '-t', 'none', vol_path, '-b',
         parent_path, '-d'
     ]
     return call(dbg, cmd)
Пример #36
0
 def set_parent(dbg, vol_path, parent_path):
     cmd = [VHD_UTIL_BIN, 'modify', '-n', vol_path, '-p', parent_path]
     return call(dbg, cmd)
Пример #37
0
 def get_psize(dbg, vol_path):
     cmd = [VHD_UTIL_BIN, 'query', '-n', vol_path, '-s']
     return call(dbg, cmd).rstrip()
Пример #38
0
 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
Пример #39
0
    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
Пример #40
0
 def resize(dbg, vol_path, size_mib):
     cmd = [
         VHD_UTIL_BIN, 'resize', '-n', vol_path, '-s',
         str(size_mib), '-f'
     ]
     return call(dbg, cmd)
Пример #41
0
 def close(self, dbg):
     call(dbg,
          ["tap-ctl", "close", "-m",
           str(self.minor), "-p",
           str(self.pid)])
     self.f = None
Пример #42
0
 def resize(dbg, vol_path, size_mib):
     cmd = [VHD_UTIL_BIN, 'resize', '-n', vol_path,
            '-s', str(size_mib), '-f']
     return call(dbg, cmd)
Пример #43
0
 def pause(self, dbg):
     call(dbg,
          ["tap-ctl", "pause", "-m",
           str(self.minor), "-p",
           str(self.pid)])
Пример #44
0
 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)
Пример #45
0
    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)