Exemple #1
0
    def _migrate_image(self, image_uuid, image_size, src_install_path,
                       dst_install_path, dst_mon_addr, dst_mon_user,
                       dst_mon_passwd, dst_mon_port):
        src_install_path = self._normalize_install_path(src_install_path)
        dst_install_path = self._normalize_install_path(dst_install_path)

        ssh_cmd, tmp_file = linux.build_sshpass_cmd(
            dst_mon_addr, dst_mon_passwd,
            'tee >(md5sum >/tmp/%s_dst_md5) | rbd import - %s' %
            (image_uuid, dst_install_path), dst_mon_user, dst_mon_port)
        rst = shell.run(
            "rbd export %s - | tee >(md5sum >/tmp/%s_src_md5) | %s" %
            (src_install_path, image_uuid, ssh_cmd))
        linux.rm_file_force(tmp_file)
        if rst != 0:
            return rst

        src_md5 = self._read_file_content('/tmp/%s_src_md5' % image_uuid)
        dst_md5 = linux.sshpass_call(dst_mon_addr, dst_mon_passwd,
                                     'cat /tmp/%s_dst_md5' % image_uuid,
                                     dst_mon_user, dst_mon_port)
        if src_md5 != dst_md5:
            return -1
        else:
            return 0
Exemple #2
0
    def ping(self, req):
        cmd = jsonobject.loads(req[http.REQUEST_BODY])
        if cmd.uuid not in self.mount_path.keys():
            self.mount_path[cmd.uuid] = cmd.mountPath

        mount_path = self.mount_path[cmd.uuid]
        # if nfs service stop, os.path.isdir will hung
        if not linux.timeout_isdir(mount_path) or not linux.is_mounted(
                path=mount_path):
            raise Exception(
                'the mount path[%s] of the nfs primary storage[uuid:%s] is not existing'
                % (mount_path, cmd.uuid))

        test_file = os.path.join(mount_path,
                                 '%s-ping-test-file' % uuidhelper.uuid())
        touch = shell.ShellCmd('timeout 60 touch %s' % test_file)
        touch(False)
        if touch.return_code == 124:
            raise Exception(
                'unable to access the mount path[%s] of the nfs primary storage[uuid:%s] in 60s, timeout'
                % (mount_path, cmd.uuid))
        elif touch.return_code != 0:
            touch.raise_error()

        linux.rm_file_force(test_file)
        return jsonobject.dumps(NfsResponse())
Exemple #3
0
    def upload(self, req):
        imageUuid = req.headers['X-IMAGE-UUID']
        imageSize = req.headers['X-IMAGE-SIZE']

        task = self.upload_tasks.get_task(imageUuid)
        if task is None:
            raise Exception('image not found %s' % imageUuid)

        task.expectedSize = long(imageSize)
        total, avail, poolCapacities, xsky = self._get_capacity()
        if avail <= task.expectedSize:
            self._fail_task(task, 'capacity not enough for size: ' + imageSize)

        entity = req.body
        boundary = get_boundary(entity)
        if not boundary:
            self._fail_task(task, 'unexpected post form')

        try:
            # prepare the fifo to save image upload
            fpath = self._get_fifopath(imageUuid)
            linux.rm_file_force(fpath)
            os.mkfifo(fpath)
            stream_body(task, fpath, entity, boundary)
        except Exception as e:
            self._fail_task(task, str(e))
        finally:
            linux.rm_file_force(fpath)
        def check_other_smp_and_set_id_file(uuid, existUuids):
            o = shell.ShellCmd('''\
            ls %s | grep -v %s | grep -o "[0-9a-f]\{8\}[0-9a-f]\{4\}[1-5][0-9a-f]\{3\}[89ab][0-9a-f]\{3\}[0-9a-f]\{12\}"\
            ''' % (id_dir, uuid))
            o(False)
            if o.return_code != 0:
                file_uuids = []
            else:
                file_uuids = o.stdout.splitlines()

            for file_uuid in file_uuids:
                if file_uuid in existUuids:
                    raise Exception(
                        "the mount point [%s] has been occupied by other SMP[uuid:%s], Please attach this directly"
                        % (cmd.mountPoint, file_uuid))

            logger.debug("existing id files: %s" % file_uuids)
            self.id_files[uuid] = os.path.join(id_dir, uuid)

            if not os.path.exists(self.id_files[uuid]):
                # check if hosts in the same cluster mount the same path but different storages.
                rsp.isFirst = True
                for file_uuid in file_uuids:
                    linux.rm_file_force(os.path.join(id_dir, file_uuid))
                linux.touch_file(self.id_files[uuid])
                linux.sync()
Exemple #5
0
        def check_other_smp_and_set_id_file(uuid, existUuids):
            o = shell.ShellCmd('''\
            ls %s | grep -v %s | grep -o "[0-9a-f]\{8\}[0-9a-f]\{4\}[1-5][0-9a-f]\{3\}[89ab][0-9a-f]\{3\}[0-9a-f]\{12\}"\
            ''' % (id_dir, uuid))
            o(False)
            if o.return_code != 0:
                file_uuids = []
            else:
                file_uuids = o.stdout.splitlines()

            for file_uuid in file_uuids:
                if file_uuid in existUuids:
                    raise Exception(
                        "the mount point [%s] has been occupied by other SMP[uuid:%s], Please attach this directly"
                        % (cmd.mountPoint, file_uuid))

            logger.debug("existing id files: %s" % file_uuids)
            self.id_files[uuid] = os.path.join(id_dir, uuid)

            if not os.path.exists(self.id_files[uuid]):
                # check if hosts in the same cluster mount the same path but different storages.
                rsp.isFirst = True
                for file_uuid in file_uuids:
                    linux.rm_file_force(os.path.join(id_dir, file_uuid))
                linux.touch_file(self.id_files[uuid])
                linux.sync_file(self.id_files[uuid])
    def upload(self, req):
        imageUuid = req.headers['X-IMAGE-UUID']
        imageSize = req.headers['X-IMAGE-SIZE']

        task = self.upload_tasks.get_task(imageUuid)
        if task is None:
            raise Exception('image not found %s' % imageUuid)

        task.expectedSize = long(imageSize)
        total, avail, poolCapacities, xsky = self._get_capacity()
        if avail <= task.expectedSize:
            self._fail_task(task, 'capacity not enough for size: ' + imageSize)

        entity = req.body
        boundary = get_boundary(entity)
        if not boundary:
            self._fail_task(task, 'unexpected post form')

        try:
            # prepare the fifo to save image upload
            fpath = self._get_fifopath(imageUuid)
            linux.rm_file_force(fpath)
            os.mkfifo(fpath)
            stream_body(task, fpath, entity, boundary)
        except Exception as e:
            self._fail_task(task, str(e))
        finally:
            linux.rm_file_force(fpath)
Exemple #7
0
        def heartbeat_on_aliyunnas():
            failure = 0

            while self.run_fencer(cmd.uuid, created_time):
                try:
                    time.sleep(cmd.interval)

                    mount_path = cmd.mountPath

                    test_file = os.path.join(
                        mount_path, cmd.heartbeat, '%s-ping-test-file-%s' %
                        (cmd.uuid, kvmagent.HOST_UUID))
                    touch = shell.ShellCmd('timeout 5 touch %s' % test_file)
                    touch(False)
                    if touch.return_code != 0:
                        logger.debug('touch file failed, cause: %s' %
                                     touch.stderr)
                        failure += 1
                    else:
                        failure = 0
                        linux.rm_file_force(test_file)
                        continue

                    if failure < cmd.maxAttempts:
                        continue

                    try:
                        logger.warn("aliyun nas storage %s fencer fired!" %
                                    cmd.uuid)

                        if cmd.strategy == 'Permissive':
                            continue

                        vm_uuids = kill_vm(cmd.maxAttempts).keys()

                        if vm_uuids:
                            self.report_self_fencer_triggered(
                                [cmd.uuid], ','.join(vm_uuids))
                            clean_network_config(vm_uuids)

                        # reset the failure count
                        failure = 0
                    except Exception as e:
                        logger.warn("kill vm failed, %s" % e.message)
                        content = traceback.format_exc()
                        logger.warn("traceback: %s" % content)
                    finally:
                        self.report_storage_status([cmd.uuid], 'Disconnected')

                except Exception as e:
                    logger.debug(
                        'self-fencer on aliyun nas primary storage %s stopped abnormally'
                        % cmd.uuid)
                    content = traceback.format_exc()
                    logger.warn(content)

            logger.debug('stop self-fencer on aliyun nas primary storage %s' %
                         cmd.uuid)
Exemple #8
0
    def cancel_download_from_kvmhost(self, req):
        cmd = jsonobject.loads(req[http.REQUEST_BODY])
        rsp = kvmagent.AgentResponse()

        install_abs_path = cmd.primaryStorageInstallPath
        shell.run("pkill -9 -f '%s'" % install_abs_path)

        linux.rm_file_force(cmd.primaryStorageInstallPath)
        return jsonobject.dumps(rsp)
Exemple #9
0
    def _delete_target(self, target_name, conf_uuid):
        conf_file = os.path.join('/etc/tgt/conf.d/%s.conf' % conf_uuid)
        linux.rm_file_force(conf_file)

        output = shell.call('tgt-admin --show')
        if target_name not in output:
            return

        update_target(target_name)
Exemple #10
0
    def _delete_target(self, target_name, conf_uuid):
        conf_file = os.path.join('/etc/tgt/conf.d/%s.conf' % conf_uuid)
        linux.rm_file_force(conf_file)

        output = shell.call('tgt-admin --show')
        if target_name not in output:
            return

        update_target(target_name)
Exemple #11
0
def deleteImage(path):
     linux.rm_file_checked(path)
     logger.debug('successfully delete %s' % path)
     if (path.endswith('.qcow2')):
        imfFiles = [".imf",".imf2"]
        for f in imfFiles:
            filePath = path.replace(".qcow2", f)
            linux.rm_file_force(filePath)
     pdir = os.path.dirname(path)
     linux.rmdir_if_empty(pdir)
Exemple #12
0
def deleteImage(path):
    linux.rm_file_checked(path)
    logger.debug('successfully delete %s' % path)
    if (path.endswith('.qcow2')):
        imfFiles = [".imf", ".imf2"]
        for f in imfFiles:
            filePath = path.replace(".qcow2", f)
            linux.rm_file_force(filePath)
    pdir = os.path.dirname(path)
    linux.rmdir_if_empty(pdir)
Exemple #13
0
    def _kill_lb(self, to):
        pid_file_path = self._make_pid_file_path(to.lbUuid, to.listenerUuid)

        pid = linux.find_process_by_cmdline([pid_file_path])
        if pid:
            shell.call('kill %s' % pid)

        linux.rm_file_force(pid_file_path)
        linux.rm_file_force(self._make_conf_file_path(to.lbUuid, to.listenerUuid))

        ipt = iptables.from_iptables_save()
        ipt.delete_chain(self._make_chain_name(to))
        ipt.iptable_restore()
Exemple #14
0
    def _kill_lb(self, to):
        pid_file_path = self._make_pid_file_path(to.lbUuid, to.listenerUuid)

        pid = linux.find_process_by_cmdline([pid_file_path])
        if pid:
            shell.call('kill %s' % pid)

        linux.rm_file_force(pid_file_path)
        linux.rm_file_force(
            self._make_conf_file_path(to.lbUuid, to.listenerUuid))

        ipt = iptables.from_iptables_save()
        ipt.delete_chain(self._make_chain_name(to))
        ipt.iptable_restore()
Exemple #15
0
        def heartbeat_on_aliyunnas():
            failure = 0

            while self.run_fencer(cmd.uuid, created_time):
                try:
                    time.sleep(cmd.interval)

                    mount_path = cmd.mountPath

                    test_file = os.path.join(mount_path, cmd.heartbeat, '%s-ping-test-file-%s' % (cmd.uuid, kvmagent.HOST_UUID))
                    touch = shell.ShellCmd('timeout 5 touch %s' % test_file)
                    touch(False)
                    if touch.return_code != 0:
                        logger.debug('touch file failed, cause: %s' % touch.stderr)
                        failure += 1
                    else:
                        failure = 0
                        linux.rm_file_force(test_file)
                        continue

                    if failure < cmd.maxAttempts:
                        continue

                    try:
                        logger.warn("aliyun nas storage %s fencer fired!" % cmd.uuid)
                        vm_uuids = kill_vm(cmd.maxAttempts).keys()

                        if vm_uuids:
                            self.report_self_fencer_triggered([cmd.uuid], ','.join(vm_uuids))

                        # reset the failure count
                        failure = 0
                    except Exception as e:
                        logger.warn("kill vm failed, %s" % e.message)
                        content = traceback.format_exc()
                        logger.warn("traceback: %s" % content)
                    finally:
                        self.report_storage_status([cmd.uuid], 'Disconnected')

                except Exception as e:
                    logger.debug('self-fencer on aliyun nas primary storage %s stopped abnormally' % cmd.uuid)
                    content = traceback.format_exc()
                    logger.warn(content)

            logger.debug('stop self-fencer on aliyun nas primary storage %s' % cmd.uuid)
    def ping(self, req):
        cmd = jsonobject.loads(req[http.REQUEST_BODY])
        mount_path = self.mount_path[cmd.uuid]
        # if nfs service stop, os.path.isdir will hung
        if not linux.timeout_isdir(mount_path) or not linux.is_mounted(path=mount_path):
            raise Exception('the mount path[%s] of the nfs primary storage[uuid:%s] is not existing' % (mount_path, cmd.uuid))

        test_file = os.path.join(mount_path, '%s-ping-test-file' % uuidhelper.uuid())
        touch = shell.ShellCmd('timeout 60 touch %s' % test_file)
        touch(False)
        if touch.return_code == 124:
            raise Exception('unable to access the mount path[%s] of the nfs primary storage[uuid:%s] in 60s, timeout' %
                            (mount_path, cmd.uuid))
        elif touch.return_code != 0:
            touch.raise_error()

        linux.rm_file_force(test_file)
        return jsonobject.dumps(NfsResponse())
Exemple #17
0
 def clean_iscsi_cache_configuration(path, iscsiServerIp, iscsiServerPort):
     # clean cache configuration file:/var/lib/iscsi/nodes/iqnxxx/ip,port
     results = bash.bash_o(
         ("ls %s/*/ | grep %s | grep %s" %
          (path, iscsiServerIp, iscsiServerPort))).strip().splitlines()
     if results is None or len(results) == 0:
         return
     for result in results:
         dpaths = bash.bash_o("dirname %s/*/%s" %
                              (path, result)).strip().splitlines()
         if dpaths is None or len(dpaths) == 0:
             continue
         for dpath in dpaths:
             ipath = "%s/%s" % (dpath, result)
             if os.path.isdir(ipath):
                 linux.rm_dir_force(ipath)
             else:
                 linux.rm_file_force(ipath)
    def listvm(self, req):
        cmd = jsonobject.loads(req[http.REQUEST_BODY])
        rsp = ListVmRsp()

        if cmd.sshPassword and not cmd.sshPrivKey:
            target, port = getSshTargetAndPort(cmd.libvirtURI)
            ssh_pswd_file = linux.write_to_temp_file(cmd.sshPassword)
            if not os.path.exists(V2V_PRIV_KEY) or not os.path.exists(V2V_PUB_KEY):
                shell.check_run("yes | ssh-keygen -t rsa -N '' -f {}".format(V2V_PRIV_KEY))
            cmdstr = "HOME={4} timeout 30 sshpass -f {0} ssh-copy-id -i {5} -p {1} {2} {3}".format(
                    ssh_pswd_file,
                    port,
                    DEF_SSH_OPTS,
                    target,
                    os.path.expanduser("~"),
                    V2V_PUB_KEY)
            shell.check_run(cmdstr)
            linux.rm_file_force(ssh_pswd_file)

        rsp.qemuVersion, rsp.libvirtVersion, rsp.vms, rsp.v2vCaps = listVirtualMachines(cmd.libvirtURI,
                cmd.saslUser,
                cmd.saslPass,
                cmd.sshPrivKey)
        return jsonobject.dumps(rsp)
Exemple #19
0
    def _migrate_volume_segment(self, parent_uuid, resource_uuid,
                                src_install_path, dst_install_path,
                                dst_mon_addr, dst_mon_user, dst_mon_passwd,
                                dst_mon_port, cmd):
        src_install_path = self._normalize_install_path(src_install_path)
        dst_install_path = self._normalize_install_path(dst_install_path)

        traceable_bash = traceable_shell.get_shell(cmd)
        ssh_cmd, tmp_file = linux.build_sshpass_cmd(
            dst_mon_addr, dst_mon_passwd,
            "tee >(md5sum >/tmp/%s_dst_md5) | rbd import-diff - %s" %
            (resource_uuid, dst_install_path), dst_mon_user, dst_mon_port)
        r, _, e = traceable_bash.bash_roe(
            'set -o pipefail; rbd export-diff {FROM_SNAP} {SRC_INSTALL_PATH} - | tee >(md5sum >/tmp/{RESOURCE_UUID}_src_md5) | {SSH_CMD}'
            .format(RESOURCE_UUID=resource_uuid,
                    SSH_CMD=ssh_cmd,
                    SRC_INSTALL_PATH=src_install_path,
                    FROM_SNAP='--from-snap ' +
                    parent_uuid if parent_uuid != '' else ''))
        linux.rm_file_force(tmp_file)
        if r != 0:
            logger.error('failed to migrate volume %s: %s' %
                         (src_install_path, e))
            return r

        # compare md5sum of src/dst segments
        src_segment_md5 = self._read_file_content('/tmp/%s_src_md5' %
                                                  resource_uuid)
        dst_segment_md5 = linux.sshpass_call(
            dst_mon_addr, dst_mon_passwd,
            'cat /tmp/%s_dst_md5' % resource_uuid, dst_mon_user, dst_mon_port)
        if src_segment_md5 != dst_segment_md5:
            logger.error('check sum mismatch after migration: %s' %
                         src_install_path)
            return -1
        return 0
Exemple #20
0
    def create_template_from_root_volume(self, req):
        cmd = jsonobject.loads(req[http.REQUEST_BODY])
        rsp = CreateTemplateFromRootVolumeRsp()
        try:
            dirname = os.path.dirname(cmd.installPath)
            if not os.path.exists(dirname):
                os.makedirs(dirname, 0755)

            t_shell = traceable_shell.get_shell(cmd)
            linux.create_template(cmd.rootVolumePath,
                                  cmd.installPath,
                                  shell=t_shell)
        except linux.LinuxError as e:
            linux.rm_file_force(cmd.installPath)
            logger.warn(linux.get_exception_stacktrace())
            rsp.error = 'unable to create image to root@%s:%s from root volume[%s], %s' % (
                cmd.sftpBackupStorageHostName, cmd.installPath,
                cmd.rootVolumePath, str(e))
            rsp.success = False

        self._set_capacity_to_response(cmd.uuid, rsp)
        logger.debug('successfully created template[%s] from root volume[%s]' %
                     (cmd.installPath, cmd.rootVolumePath))
        return jsonobject.dumps(rsp)
 def delete_bootstrap_iso(self, req):
     cmd = jsonobject.loads(req[http.REQUEST_BODY])
     linux.rm_file_force(cmd.isoPath)
     return jsonobject.dumps(DeleteVirtualRouterBootstrapIsoRsp())
Exemple #22
0
    def copy_bits_to_remote(self, req):
        cmd = jsonobject.loads(req[http.REQUEST_BODY])
        if cmd.dstUsername != 'root':
            raise Exception("cannot support migrate to non-root user host")

        chain = sum([linux.qcow2_get_file_chain(p) for p in cmd.paths], [])
        if cmd.sendCommandUrl:
            Report.url = cmd.sendCommandUrl

        report = Report(cmd.threadContext, cmd.threadContextStack)
        report.processType = "LocalStorageMigrateVolume"
        report.resourceUuid = cmd.volumeUuid

        PFILE = shell.call('mktemp /tmp/tmp-XXXXXX').strip()
        PASSWORD_FILE = linux.write_to_temp_file(cmd.dstPassword)

        start = 10
        end = 90
        if cmd.stage:
            start, end = get_scale(cmd.stage)

        total = 0
        for path in set(chain):
            total = total + os.path.getsize(path)

        written = 0

        def _get_progress(synced):
            logger.debug(
                "getProgress in localstorage-agent, synced: %s, total: %s" %
                (synced, total))
            if not os.path.exists(PFILE):
                return synced
            fpread = open(PFILE, 'r')
            lines = fpread.readlines()
            if not lines:
                fpread.close()
                return synced
            last = str(lines[-1]).strip().split('\r')[-1]
            if not last or len(last.split()) < 1:
                fpread.close()
                return synced
            line = last.split()[0]
            if not line.isdigit():
                return synced
            if total > 0:
                synced = long(line)
                if synced < total:
                    percent = int(
                        round(
                            float(written + synced) / float(total) *
                            (end - start) + start))
                    report.progress_report(percent, "report")
                    synced = written
            fpread.close()
            return synced

        for path in set(chain):
            PATH = path
            USER = cmd.dstUsername
            IP = cmd.dstIp
            PORT = (cmd.dstPort and cmd.dstPort or "22")
            DIR = os.path.dirname(path)
            _, _, err = bash_progress_1(
                # Fixes ZSTAC-13430: handle extremely complex password like ~ ` !@#$%^&*()_+-=[]{}|?<>;:'"/ .
                'rsync -av --progress --relative {{PATH}} --rsh="/usr/bin/sshpass -f{{PASSWORD_FILE}} ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p {{PORT}} -l {{USER}}" {{IP}}:/ 1>{{PFILE}}',
                _get_progress,
                False)
            if err:
                linux.rm_file_force(PASSWORD_FILE)
                linux.rm_file_force(PFILE)
                raise Exception('fail to migrate vm to host, because %s' %
                                str(err))

            written += os.path.getsize(path)
            bash_errorout(
                '/usr/bin/sshpass -f{{PASSWORD_FILE}} ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p {{PORT}} {{USER}}@{{IP}} "/bin/sync {{PATH}}"'
            )
            percent = int(
                round(float(written) / float(total) * (end - start) + start))
            report.progress_report(percent, "report")

        linux.rm_file_force(PASSWORD_FILE)
        linux.rm_file_force(PFILE)
        rsp = AgentResponse()
        rsp.totalCapacity, rsp.availableCapacity = self._get_disk_capacity(
            cmd.storagePath)
        return jsonobject.dumps(rsp)
Exemple #23
0
    def download(self, req):
        rsp = DownloadRsp()

        def _get_origin_format(path):
            qcow2_length = 0x9007
            if path.startswith('http://') or path.startswith(
                    'https://') or path.startswith('ftp://'):
                resp = urllib2.urlopen(path)
                qhdr = resp.read(qcow2_length)
                resp.close()
            elif path.startswith('sftp://'):
                fd, tmp_file = tempfile.mkstemp()
                get_header_from_pipe_cmd = "timeout 60 head --bytes=%d %s > %s" % (
                    qcow2_length, pipe_path, tmp_file)
                clean_cmd = "pkill -f %s" % pipe_path
                shell.run(
                    '%s & %s && %s' %
                    (scp_to_pipe_cmd, get_header_from_pipe_cmd, clean_cmd))
                qhdr = os.read(fd, qcow2_length)
                if os.path.exists(tmp_file):
                    os.remove(tmp_file)
            else:
                resp = open(path)
                qhdr = resp.read(qcow2_length)
                resp.close()
            if len(qhdr) < qcow2_length:
                return "raw"

            return get_image_format_from_buf(qhdr)

        def get_origin_format(fpath, fail_if_has_backing_file=True):
            image_format = _get_origin_format(fpath)
            if image_format == "derivedQcow2" and fail_if_has_backing_file:
                raise Exception('image has backing file or %s is not exist!' %
                                fpath)
            return image_format

        cmd = jsonobject.loads(req[http.REQUEST_BODY])
        shell = traceable_shell.get_shell(cmd)
        pool, image_name = self._parse_install_path(cmd.installPath)
        tmp_image_name = 'tmp-%s' % image_name

        @rollbackable
        def _1():
            shell.check_run('rbd rm %s/%s' % (pool, tmp_image_name))

        def _getRealSize(length):
            '''length looks like: 10245K'''
            logger.debug(length)
            if not length[-1].isalpha():
                return length
            units = {
                "g": lambda x: x * 1024 * 1024 * 1024,
                "m": lambda x: x * 1024 * 1024,
                "k": lambda x: x * 1024,
            }
            try:
                if not length[-1].isalpha():
                    return length
                return units[length[-1].lower()](int(length[:-1]))
            except:
                logger.warn(linux.get_exception_stacktrace())
                return length

        # whether we have an upload request
        if cmd.url.startswith(self.UPLOAD_PROTO):
            self._prepare_upload(cmd)
            rsp.size = 0
            rsp.uploadPath = self._get_upload_path(req)
            self._set_capacity_to_response(rsp)
            return jsonobject.dumps(rsp)

        if cmd.sendCommandUrl:
            Report.url = cmd.sendCommandUrl

        report = Report(cmd.threadContext, cmd.threadContextStack)
        report.processType = "AddImage"
        report.resourceUuid = cmd.imageUuid
        report.progress_report("0", "start")

        url = urlparse.urlparse(cmd.url)
        if url.scheme in ('http', 'https', 'ftp'):
            image_format = get_origin_format(cmd.url, True)
            cmd.url = linux.shellquote(cmd.url)
            # roll back tmp ceph file after import it
            _1()

            _, PFILE = tempfile.mkstemp()
            content_length = shell.call(
                """curl -sLI %s|awk '/[cC]ontent-[lL]ength/{print $NF}'""" %
                cmd.url).splitlines()[-1]
            total = _getRealSize(content_length)

            def _getProgress(synced):
                last = linux.tail_1(PFILE).strip()
                if not last or len(last.split(
                )) < 1 or 'HTTP request sent, awaiting response' in last:
                    return synced
                logger.debug("last synced: %s" % last)
                written = _getRealSize(last.split()[0])
                if total > 0 and synced < written:
                    synced = written
                    if synced < total:
                        percent = int(round(float(synced) / float(total) * 90))
                        report.progress_report(percent, "report")
                return synced

            logger.debug("content-length is: %s" % total)

            _, _, err = shell.bash_progress_1(
                'set -o pipefail;wget --no-check-certificate -O - %s 2>%s| rbd import --image-format 2 - %s/%s'
                % (cmd.url, PFILE, pool, tmp_image_name), _getProgress)
            if err:
                raise err
            actual_size = linux.get_file_size_by_http_head(cmd.url)

            if os.path.exists(PFILE):
                os.remove(PFILE)

        elif url.scheme == 'sftp':
            port = (url.port, 22)[url.port is None]
            _, PFILE = tempfile.mkstemp()
            ssh_pswd_file = None
            pipe_path = PFILE + "fifo"
            scp_to_pipe_cmd = "scp -P %d -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null %s@%s:%s %s" % (
                port, url.username, url.hostname, url.path, pipe_path)
            sftp_command = "sftp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o BatchMode=no -P %s -b /dev/stdin %s@%s" % (
                port, url.username, url.hostname) + " <<EOF\n%s\nEOF\n"
            if url.password is not None:
                ssh_pswd_file = linux.write_to_temp_file(url.password)
                scp_to_pipe_cmd = 'sshpass -f %s %s' % (ssh_pswd_file,
                                                        scp_to_pipe_cmd)
                sftp_command = 'sshpass -f %s %s' % (ssh_pswd_file,
                                                     sftp_command)

            actual_size = shell.call(
                sftp_command %
                ("ls -l " + url.path)).splitlines()[1].strip().split()[4]
            os.mkfifo(pipe_path)
            image_format = get_origin_format(cmd.url, True)
            cmd.url = linux.shellquote(cmd.url)
            # roll back tmp ceph file after import it
            _1()

            def _get_progress(synced):
                if not os.path.exists(PFILE):
                    return synced
                last = linux.tail_1(PFILE).strip()
                if not last or not last.isdigit():
                    return synced
                report.progress_report(int(last) * 90 / 100, "report")
                return synced

            get_content_from_pipe_cmd = "pv -s %s -n %s 2>%s" % (
                actual_size, pipe_path, PFILE)
            import_from_pipe_cmd = "rbd import --image-format 2 - %s/%s" % (
                pool, tmp_image_name)
            _, _, err = shell.bash_progress_1(
                'set -o pipefail; %s & %s | %s' %
                (scp_to_pipe_cmd, get_content_from_pipe_cmd,
                 import_from_pipe_cmd), _get_progress)

            if ssh_pswd_file:
                linux.rm_file_force(ssh_pswd_file)

            linux.rm_file_force(PFILE)
            linux.rm_file_force(pipe_path)

            if err:
                raise err

        elif url.scheme == 'file':
            src_path = cmd.url.lstrip('file:')
            src_path = os.path.normpath(src_path)
            if not os.path.isfile(src_path):
                raise Exception('cannot find the file[%s]' % src_path)
            image_format = get_origin_format(src_path, True)
            # roll back tmp ceph file after import it
            _1()

            shell.check_run("rbd import --image-format 2 %s %s/%s" %
                            (src_path, pool, tmp_image_name))
            actual_size = os.path.getsize(src_path)
        else:
            raise Exception('unknown url[%s]' % cmd.url)

        file_format = shell.call(
            "set -o pipefail; %s rbd:%s/%s | grep 'file format' | cut -d ':' -f 2"
            % (qemu_img.subcmd('info'), pool, tmp_image_name))
        file_format = file_format.strip()
        if file_format not in ['qcow2', 'raw']:
            raise Exception('unknown image format: %s' % file_format)

        if file_format == 'qcow2':
            conf_path = None
            try:
                with open('/etc/ceph/ceph.conf', 'r') as fd:
                    conf = fd.read()
                    conf = '%s\n%s\n' % (conf, 'rbd default format = 2')
                    conf_path = linux.write_to_temp_file(conf)

                shell.check_run(
                    '%s -f qcow2 -O rbd rbd:%s/%s rbd:%s/%s:conf=%s' %
                    (qemu_img.subcmd('convert'), pool, tmp_image_name, pool,
                     image_name, conf_path))
                shell.check_run('rbd rm %s/%s' % (pool, tmp_image_name))
            finally:
                if conf_path:
                    os.remove(conf_path)
        else:
            shell.check_run('rbd mv %s/%s %s/%s' %
                            (pool, tmp_image_name, pool, image_name))
        report.progress_report("100", "finish")

        @rollbackable
        def _2():
            shell.check_run('rbd rm %s/%s' % (pool, image_name))

        _2()

        o = shell.call('rbd --format json info %s/%s' % (pool, image_name))
        image_stats = jsonobject.loads(o)

        rsp.size = long(image_stats.size_)
        rsp.actualSize = actual_size
        if image_format == "qcow2":
            rsp.format = "raw"
        else:
            rsp.format = image_format

        self._set_capacity_to_response(rsp)
        return jsonobject.dumps(rsp)
Exemple #24
0
    def migrate_bits(self, req):
        cmd = jsonobject.loads(req[http.REQUEST_BODY])
        rsp = NfsToNfsMigrateBitsRsp()

        mount_path = cmd.mountPath
        dst_folder_path = cmd.dstFolderPath
        temp_dir = None
        fd, PFILE = tempfile.mkstemp()
        os.close(fd)
        f = open(PFILE, 'r')

        try:
            if not cmd.isMounted:
                linux.is_valid_nfs_url(cmd.url)

                temp_dir = tempfile.mkdtemp()

                # dst folder is absolute path
                mount_path = temp_dir + mount_path
                dst_folder_path = temp_dir + dst_folder_path

                if not linux.is_mounted(mount_path, cmd.url):
                    linux.mount(cmd.url, mount_path, cmd.options, "nfs4")

            # begin migration, then check md5 sums
            linux.mkdir(dst_folder_path)

            t_shell = traceable_shell.get_shell(cmd)
            rsync_excludes = ""
            md5_excludes = ""
            if cmd.filtPaths:
                for filtPath in cmd.filtPaths:
                    # filtPath cannot start with '/', because it must be a relative path
                    if filtPath.startswith('/'):
                        filtPath = filtPath[1:]
                    if filtPath != '':
                        rsync_excludes = rsync_excludes + " --exclude=%s" % filtPath
                        md5_excludes = md5_excludes + " ! -path %s/%s" % (
                            cmd.srcFolderPath, filtPath)

            total_size = int(
                shell.call(
                    "rsync -aznv %s/ %s %s | grep -o -P 'total size is \K\d*'"
                    % (cmd.srcFolderPath, dst_folder_path, rsync_excludes)))

            stage = get_task_stage(cmd)
            reporter = Report.from_spec(cmd, "MigrateVolume")

            def _get_progress(synced):
                def get_written(regex):
                    matcher = re.match(regex, line)
                    return int(matcher.group(1)) if matcher else 0

                lines = f.readlines()
                writing = 0
                for line in lines:
                    if line[1] == ' ' and line[-1] == '\n':
                        synced += get_written(r'\s.*?(\d+)\s+100%')
                    elif line[-1] == '\r' and line[1] == ' ':
                        writing = get_written(r'.*?(\d+)\s+\d+%[^\r]*\r$')
                reporter.progress_report(
                    get_exact_percent(
                        float(synced + writing) / total_size * 100, stage))
                return synced

            t_shell.bash_progress_1(
                "rsync -az --progress %s/ %s %s > %s" %
                (cmd.srcFolderPath, dst_folder_path, rsync_excludes, PFILE),
                _get_progress)

            src_md5 = t_shell.call(
                "find %s -type f %s -exec md5sum {} \; | awk '{ print $1 }' | sort | md5sum"
                % (cmd.srcFolderPath, md5_excludes))
            dst_md5 = t_shell.call(
                "find %s -type f -exec md5sum {} \; | awk '{ print $1 }' | sort | md5sum"
                % dst_folder_path)
            if src_md5 != dst_md5:
                rsp.error = "failed to copy files from %s to %s, md5sum not match" % (
                    cmd.srcFolderPath, dst_folder_path)
                rsp.success = False

            if not cmd.isMounted:
                linux.umount(mount_path)
        finally:
            if temp_dir is not None:
                return_code = shell.run("mount | grep '%s'" % temp_dir)

                if return_code != 0:
                    # in case dir is not empty
                    try:
                        os.rmdir(temp_dir)
                    except OSError as e:
                        logger.warn("delete temp_dir %s failed: %s",
                                    (temp_dir, str(e)))
                else:
                    logger.warn(
                        "temp_dir %s still had mounted destination primary storage, skip cleanup operation"
                        % temp_dir)

            f.close()
            linux.rm_file_force(PFILE)
        return jsonobject.dumps(rsp)
Exemple #25
0
 def get_metadata_file(self, bs_uuid, file_name):
     local_file_name = "/tmp/%s" % file_name
     linux.rm_file_force(local_file_name)
     bash_ro("rados -p bak-t-%s get %s %s" % (bs_uuid, file_name, local_file_name))
Exemple #26
0
 def _0():
     linux.rm_file_force(cmd.installPath)
Exemple #27
0
 def _0():
     linux.rm_file_force(pid_file)
Exemple #28
0
 def delpid(self):
     linux.rm_file_force(self.pidfile)
Exemple #29
0
 def _0():
     linux.rm_file_force(pid_file)
Exemple #30
0
 def delete_bootstrap_iso(self, req):
     cmd = jsonobject.loads(req[http.REQUEST_BODY])
     linux.rm_file_force(cmd.isoPath)
     return jsonobject.dumps(DeleteVirtualRouterBootstrapIsoRsp())
    def copy_bits_to_remote(self, req):
        cmd = jsonobject.loads(req[http.REQUEST_BODY])
        if cmd.dstUsername != 'root':
            raise Exception("cannot support migrate to non-root user host")

        chain = sum([linux.qcow2_get_file_chain(p) for p in cmd.paths], [])
        if cmd.sendCommandUrl:
            Report.url = cmd.sendCommandUrl

        report = Report(cmd.threadContext, cmd.threadContextStack)
        report.processType = "LocalStorageMigrateVolume"
        report.resourceUuid = cmd.volumeUuid

        PFILE = shell.call('mktemp /tmp/tmp-XXXXXX').strip()
        PASSWORD_FILE = linux.write_to_temp_file(cmd.dstPassword)

        start = 10
        end = 90
        if cmd.stage:
            start, end = get_scale(cmd.stage)

        total = 0
        for path in set(chain):
            total = total + os.path.getsize(path)

        written = 0

        def _get_progress(synced):
            logger.debug("getProgress in localstorage-agent, synced: %s, total: %s" % (synced, total))
            if not os.path.exists(PFILE):
                return synced
            fpread = open(PFILE, 'r')
            lines = fpread.readlines()
            if not lines:
                fpread.close()
                return synced
            last = str(lines[-1]).strip().split('\r')[-1]
            if not last or len(last.split()) < 1:
                fpread.close()
                return synced
            line = last.split()[0]
            if not line.isdigit():
                return synced
            if total > 0:
                synced = long(line)
                if synced < total:
                    percent = int(round(float(written + synced) / float(total) * (end - start) + start))
                    report.progress_report(percent, "report")
                    synced = written
            fpread.close()
            return synced

        for path in set(chain):
            PATH = path
            USER = cmd.dstUsername
            IP = cmd.dstIp
            PORT = (cmd.dstPort and cmd.dstPort or "22")
            DIR = os.path.dirname(path)
            _, _, err = bash_progress_1(
                # Fixes ZSTAC-13430: handle extremely complex password like ~ ` !@#$%^&*()_+-=[]{}|?<>;:'"/ .
                'rsync -av --progress --relative {{PATH}} --rsh="/usr/bin/sshpass -f{{PASSWORD_FILE}} ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p {{PORT}} -l {{USER}}" {{IP}}:/ 1>{{PFILE}}', _get_progress, False)
            if err:
                linux.rm_file_force(PASSWORD_FILE)
                linux.rm_file_force(PFILE)
                raise Exception('fail to migrate vm to host, because %s' % str(err))

            written += os.path.getsize(path)
            bash_errorout('/usr/bin/sshpass -f{{PASSWORD_FILE}} ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p {{PORT}} {{USER}}@{{IP}} "/bin/sync {{PATH}}"')
            percent = int(round(float(written) / float(total) * (end - start) + start))
            report.progress_report(percent, "report")

        linux.rm_file_force(PASSWORD_FILE)
        linux.rm_file_force(PFILE)
        rsp = AgentResponse()
        rsp.totalCapacity, rsp.availableCapacity = self._get_disk_capacity(cmd.storagePath)
        return jsonobject.dumps(rsp)
Exemple #32
0
 def get_metadata_file(self, bs_uuid, file_name):
     local_file_name = "/tmp/%s" % file_name
     linux.rm_file_force(local_file_name)
     bash_ro("rados -p bak-t-%s get %s %s" %
             (bs_uuid, file_name, local_file_name))
Exemple #33
0
 def put_metadata_file(self, bs_uuid, file_name):
     local_file_name = "/tmp/%s" % file_name
     ret, output = bash_ro("rados -p bak-t-%s put %s %s" %
                           (bs_uuid, file_name, local_file_name))
     if ret == 0:
         linux.rm_file_force(local_file_name)
Exemple #34
0
 def put_metadata_file(self, bs_uuid, file_name):
     local_file_name = "/tmp/%s" % file_name
     ret, output = bash_ro("rados -p bak-t-%s put %s %s" % (bs_uuid, file_name, local_file_name))
     if ret == 0:
         linux.rm_file_force(local_file_name)