def _prepare_args(self):
        # add --graphics none later
        # add whatever serial cmds are needed later
        args = [
            "-n", self._virt_name, "-r",
            str(self._memory), "--noautoconsole", "--vcpus",
            str(self._vcpu_count), "--rng", "/dev/random"
        ]

        # CHECKME This seems to be necessary because of ipxe ibft chain booting,
        # otherwise the vm is created but it does not boot into installation
        if not self._boot:
            args.append("--noreboot")

        args.append("--graphics")
        if self._vnc:
            args.append(self._vnc)
        else:
            args.append("none")

        for ks in self._ks_paths:
            args.append("--initrd-inject")
            args.append(ks)

        for disk in self._disk_paths:
            args.append("--disk")
            args.append("path={0},bus=sata".format(disk))

        for nic in self._nics or []:
            args.append("--network")
            args.append(nic)

        if self._iso.stage2:
            disk_opts = "path={0},device=cdrom,readonly=on,shareable=on".format(
                self._iso.iso_path)
            args.append("--disk")
            args.append(disk_opts)

        if self._ks_paths:
            extra_args = "ks=file:/{0}".format(
                os.path.basename(self._ks_paths[0]))
        else:
            extra_args = ""
        if not self._vnc:
            extra_args += " inst.cmdline"
        if self._kernel_args:
            extra_args += " " + self._kernel_args
        if self._iso.stage2:
            extra_args += " stage2=hd:CDLABEL={0}".format(
                udev_escape(self._iso.label))

        if self._boot:
            # eg booting from ipxe to emulate ibft firmware
            args.append("--boot")
            args.append(self._boot)
        else:
            args.append("--extra-args")
            args.append(extra_args)

            args.append("--location")
            args.append(self._iso.iso_path +
                        ",kernel=isolinux/vmlinuz,initrd=isolinux/initrd.img")

        channel_args = "tcp,host={0}:{1},mode=connect,target_type=virtio" \
                       ",name=org.fedoraproject.anaconda.log.0".format(
                           self._virtio_host, self._virtio_port)
        args.append("--channel")
        args.append(channel_args)
        return args
Example #2
0
    def __init__(self,
                 opts,
                 iso,
                 ks_paths,
                 disk_img,
                 img_size=2048,
                 kernel_args=None,
                 memory=1024,
                 vcpus=None,
                 vnc=None,
                 arch=None,
                 cancel_func=None,
                 virtio_host="127.0.0.1",
                 virtio_port=6080,
                 image_type=None,
                 boot_uefi=False,
                 ovmf_path=None):
        """
        Start the installation

        :param iso: Information about the iso to use for the installation
        :type iso: IsoMountpoint
        :param list ks_paths: Paths to kickstart files. All are injected, the
           first one is the one executed.
        :param str disk_img: Path to a disk image, created it it doesn't exist
        :param int img_size: The image size, in MiB, to create if it doesn't exist
        :param str kernel_args: Extra kernel arguments to pass on the kernel cmdline
        :param int memory: Amount of RAM to assign to the virt, in MiB
        :param int vcpus: Number of virtual cpus
        :param str vnc: Arguments to pass to qemu -display
        :param str arch: Optional architecture to use in the virt
        :param cancel_func: Function that returns True if the installation fails
        :type cancel_func: function
        :param str virtio_host: Hostname to connect virtio log to
        :param int virtio_port: Port to connect virtio log to
        :param str image_type: Type of qemu-img disk to create, or None.
        :param bool boot_uefi: Use OVMF to boot the VM in UEFI mode
        :param str ovmf_path: Path to the OVMF firmware
        """
        # Lookup qemu-system- for arch if passed, or try to guess using host arch
        qemu_cmd = [
            self.QEMU_CMDS.get(arch or os.uname().machine,
                               "qemu-system-" + os.uname().machine)
        ]
        if not os.path.exists("/usr/bin/" + qemu_cmd[0]):
            raise InstallError("%s does not exist, cannot run qemu" %
                               qemu_cmd[0])

        qemu_cmd += ["-no-user-config"]
        qemu_cmd += ["-m", str(memory)]
        if vcpus:
            qemu_cmd += ["-smp", str(vcpus)]

        if not opts.no_kvm and os.path.exists("/dev/kvm"):
            qemu_cmd += ["--machine", "accel=kvm"]

        # Copy the initrd from the iso, create a cpio archive of the kickstart files
        # and append it to the temporary initrd.
        qemu_initrd = append_initrd(iso.initrd, ks_paths)
        qemu_cmd += ["-kernel", iso.kernel]
        qemu_cmd += ["-initrd", qemu_initrd]

        # Add the disk and cdrom
        if not os.path.isfile(disk_img):
            mksparse(disk_img, img_size * 1024**2)
        drive_args = "file=%s" % disk_img
        drive_args += ",cache=unsafe,discard=unmap"
        if image_type:
            drive_args += ",format=%s" % image_type
        else:
            drive_args += ",format=raw"
        qemu_cmd += ["-drive", drive_args]

        drive_args = "file=%s,media=cdrom,readonly=on" % iso.iso_path
        qemu_cmd += ["-drive", drive_args]

        # Setup the cmdline args
        # ======================
        cmdline_args = "ks=file:/%s" % os.path.basename(ks_paths[0])
        cmdline_args += " inst.stage2=hd:LABEL=%s" % udev_escape(iso.label)
        if opts.proxy:
            cmdline_args += " inst.proxy=%s" % opts.proxy
        if kernel_args:
            cmdline_args += " " + kernel_args
        cmdline_args += " inst.text inst.cmdline"

        qemu_cmd += ["-append", cmdline_args]

        if not opts.vnc:
            vnc_port = find_free_port()
            if vnc_port == -1:
                raise InstallError("No free VNC ports")
            display_args = "vnc=127.0.0.1:%d" % (vnc_port - 5900)
        else:
            display_args = opts.vnc
        log.info("qemu %s", display_args)
        qemu_cmd += ["-nographic", "-display", display_args]

        # Setup the virtio log port
        qemu_cmd += ["-device", "virtio-serial-pci,id=virtio-serial0"]
        qemu_cmd += [
            "-device",
            "virtserialport,bus=virtio-serial0.0,nr=1,chardev=charchannel0"
            ",id=channel0,name=org.fedoraproject.anaconda.log.0"
        ]
        qemu_cmd += [
            "-chardev",
            "socket,id=charchannel0,host=%s,port=%s" %
            (virtio_host, virtio_port)
        ]

        # PAss through rng from host
        if opts.with_rng != "none":
            qemu_cmd += [
                "-object",
                "rng-random,id=virtio-rng0,filename=%s" % opts.with_rng
            ]
            qemu_cmd += [
                "-device",
                "virtio-rng-pci,rng=virtio-rng0,id=rng0,bus=pci.0,addr=0x9"
            ]

        if boot_uefi and ovmf_path:
            qemu_cmd += [
                "-drive",
                "file=%s/OVMF_CODE.fd,if=pflash,format=raw,unit=0,readonly=on"
                % ovmf_path
            ]

            # Make a copy of the OVMF_VARS.fd for this run
            ovmf_vars = tempfile.mktemp(prefix="lmc-OVMF_VARS-", suffix=".fd")
            shutil.copy2(joinpaths(ovmf_path, "/OVMF_VARS.fd"), ovmf_vars)

            qemu_cmd += [
                "-drive",
                "file=%s,if=pflash,format=raw,unit=1" % ovmf_vars
            ]

        log.info("Running qemu")
        log.debug(qemu_cmd)
        try:
            execWithRedirect(qemu_cmd[0],
                             qemu_cmd[1:],
                             reset_lang=False,
                             raise_err=True,
                             callback=lambda p: not cancel_func())
        except subprocess.CalledProcessError as e:
            log.error("Running qemu failed:")
            log.error("cmd: %s", " ".join(e.cmd))
            log.error("output: %s", e.output or "")
            raise InstallError("QEMUInstall failed")
        except (OSError, KeyboardInterrupt) as e:
            log.error("Running qemu failed: %s", str(e))
            raise InstallError("QEMUInstall failed")
        finally:
            os.unlink(qemu_initrd)
            if boot_uefi and ovmf_path:
                os.unlink(ovmf_vars)

        if cancel_func():
            log.error("Installation error detected. See logfile for details.")
            raise InstallError("QEMUInstall failed")
        else:
            log.info("Installation finished without errors.")
#!/usr/bin/python3

import sys
from pylorax.treebuilder import udev_escape

if len(sys.argv) != 2:
    print("Usage: %s <string>" % sys.argv[0], file=sys.stderr)
    sys.exit(1)

print(udev_escape(sys.argv[1]))