def _start_dnsmasq() -> None: """ Start dhcp and dns server for vms """ host = "" bridge_routes = f"0.0.0.0/0,{config.BRIDGE_IP}" cmd = f"{config.DNSMASQ_TOOL} " \ f"--interface={config.BRIDGE_NAME} " \ "--bind-interfaces " \ "--except-interface=lo " \ f"--pid-file={config.DNSMASQ_PID_FILE} " \ f"--dhcp-range={config.DNSMASQ_DHCP_IP_RANGE} " \ f"--dhcp-option=option:classless-static-route,{bridge_routes}" if config.NUM_VMS > 8: print("too many VMs") return for i in range(config.NUM_VMS): mac_to_ip = f"{config.vm_get_mac(i)},{config.vm_get_ip(i)}" cmd += f" --dhcp-host={mac_to_ip}" print(cmd) run.run_cmd(host, cmd)
def mount_image(file_name: str) -> None: """ Mount a vm image """ mnt_host = "" # make sure nbd module is loaded mod_cmd = f"{config.MODPROBE_TOOL} nbd" run.run_ok(mnt_host, mod_cmd) # setup network block device nbd_cmd = f"{config.QEMU_NBD_TOOL} --connect={config.QEMU_IMG_NBD_DEV} " \ f"{file_name}" print(f"Creating nbd {config.QEMU_IMG_NBD_DEV}") run.run_background(mnt_host, nbd_cmd) # make sure nbd partition is ready run.run_try(mnt_host, f"{config.LS_TOOL} {config.QEMU_IMG_NBD_PART}", 10) # make sure mount directory exists mnt_dir = config.QEMU_IMG_MOUNT_DIR mkdir_cmd = f"{config.MKDIR_TOOL} {mnt_dir}" run.run_ok(mnt_host, mkdir_cmd) # mount nbd partition mnt_cmd = f"{config.MOUNT_TOOL} {config.QEMU_IMG_NBD_PART} {mnt_dir}" print(f"Mounting partition {config.QEMU_IMG_NBD_PART}") run.run_cmd(mnt_host, mnt_cmd)
def _create_if_down_script() -> None: """ Create if down script for vm """ host = "" # create script script = f"""#!/bin/bash IP={config.IP_TOOL} TAP=\\$1 # remove tap interface from bridge \\$IP link set \\"\\$TAP\\" nomaster \\$IP link set \\"\\$TAP\\" promisc off \\$IP link set \\"\\$TAP\\" down """ cat_cmd = f"{config.CAT_TOOL} <<-\\\"EOF\\\" > " \ f"{config.VM_IF_DOWN_SCRIPT}\n{script}EOF" run.run_cmd(host, cat_cmd) # make script executable chmod_cmd = f"{config.CHMOD_TOOL} +x {config.VM_IF_DOWN_SCRIPT}" run.run_cmd(host, chmod_cmd)
def _create_if_up_script() -> None: """ Create if up script for vm """ host = "" # create script script = f"""#!/bin/bash IP={config.IP_TOOL} BRIDGE={config.BRIDGE_NAME} TAP=\\$1 # add tap interface to bridge \\$IP link set \\"\\$TAP\\" up \\$IP link set \\"\\$TAP\\" promisc on \\$IP link set \\"\\$TAP\\" master \\$BRIDGE """ cat_cmd = f"{config.CAT_TOOL} <<-\\\"EOF\\\" > " \ f"{config.VM_IF_UP_SCRIPT}\n{script}EOF" run.run_cmd(host, cat_cmd) # make script executable chmod_cmd = f"{config.CHMOD_TOOL} +x {config.VM_IF_UP_SCRIPT}" run.run_cmd(host, chmod_cmd)
def _stop_dnsmasq() -> None: """ Stop dhcp and dns server for vms """ host = "" cmd = f"{config.KILL_TOOL} $({config.CAT_TOOL} {config.DNSMASQ_PID_FILE})" run.run_cmd(host, cmd)
def _remove_vm_sockfile(vm_id: int) -> None: """ Delete sockfile of vm """ host = "" vm_sock = config.vm_get_sockfile(vm_id) cmd = f"{config.RM_TOOL} {vm_sock}" run.run_cmd(host, cmd)
def quit_vm(vm_id: int) -> None: """ Quit a VM (force stop) """ host = "" vm_sock = config.vm_get_sockfile(vm_id) if run.run_ok(host, f"{config.LS_TOOL} {vm_sock}"): cmd = f"{config.ECHO_TOOL} \"quit\" | nc -U \"{vm_sock}\"" run.run_cmd(host, cmd) _remove_vm_sockfile(vm_id)
def stop_vm(vm_id: int) -> None: """ Stop a VM """ host = "" vm_sock = config.vm_get_sockfile(vm_id) if run.run_ok(host, f"{config.LS_TOOL} {vm_sock}"): cmd = f"{config.ECHO_TOOL} \"system_powerdown\" | nc -U \"{vm_sock}\"" run.run_cmd(host, cmd) _remove_vm_sockfile(vm_id)
def create_vm_image(vm_id: int) -> None: """ Create a vm image that is based on a base image """ image_host = "" file_format = "qcow2" base_image = config.qemu_get_base_image() file_name = config.qemu_get_vm_image(vm_id) image_cmd = f"{config.QEMU_IMG_TOOL} create -f {file_format} " \ f"-b {base_image} {file_name}" run.run_cmd(image_host, image_cmd)
def _start_nat() -> None: """ Start nat for vms """ host = "" # enable ip forwarding fwd_cmd = f"{config.SYSCTL_TOOL} " \ f"net.ipv4.conf.{config.BRIDGE_NAME}.forwarding=1" run.run_cmd(host, fwd_cmd) # enable nat prefix = f"{config.BRIDGE_IP_NET}/{config.BRIDGE_IP_PREFIX_LEN}" masq_cmd = f"{config.IPTABLES_TOOL} -t nat -A POSTROUTING -s {prefix} " \ "-j MASQUERADE" run.run_cmd(host, masq_cmd) out_cmd = f"{config.IPTABLES_TOOL} -A FORWARD -m conntrack " \ f"--ctstate RELATED,ESTABLISHED -o {config.BRIDGE_NAME} -d {prefix} " \ "-j ACCEPT" run.run_cmd(host, out_cmd) in_cmd = f"{config.IPTABLES_TOOL} -A FORWARD -i {config.BRIDGE_NAME} " \ f"-s {prefix} -j ACCEPT" run.run_cmd(host, in_cmd)
def umount_image() -> None: """ Unmount a vm image """ mnt_host = "" # umount nbd partition mnt_dir = config.QEMU_IMG_MOUNT_DIR mnt_cmd = f"{config.UMOUNT_TOOL} {mnt_dir}" print(f"Umounting dir {mnt_dir}") run.run_cmd(mnt_host, mnt_cmd) # close network block device nbd_cmd = f"{config.QEMU_NBD_TOOL} --disconnect {config.QEMU_IMG_NBD_DEV}" print(f"Disconnecting nbd {config.QEMU_IMG_NBD_DEV}") run.run_cmd(mnt_host, nbd_cmd)
def create_base_image() -> None: """ Create a base vm image """ image_host = "" file_name = config.qemu_get_base_image() # stop if file already exists if run.run_ok(image_host, f"{config.LS_TOOL} {file_name}"): print("File already exists") return file_format = "qcow2" file_size = config.QEMU_IMG_SIZE image_cmd = f"{config.QEMU_IMG_TOOL} create -f {file_format} " \ f"{file_name} {file_size}" run.run_cmd(image_host, image_cmd)
def build() -> None: """ Build kernel """ build_host = "" build_cmd = f"make -j{config.BUILDJOBS} tarxz-pkg" output = run.run_cmd(build_host, build_cmd) # get name of file from output parts = output.split() if parts: # get file name and extract kernel version from filename file_name = parts[-1] version = "-".join(file_name.split("-")[1:-1]) print("Built kernel version:", version) print("Saved kernel in file:", file_name)
def _start_bridge() -> None: """ Start vm network bridge """ host = "" # add bridge device add_cmd = f"{config.IP_TOOL} link add name {config.BRIDGE_NAME} " \ "type bridge" run.run_cmd(host, add_cmd) # make sure bridge device is up up_cmd = f"{config.IP_TOOL} link set {config.BRIDGE_NAME} up" run.run_cmd(host, up_cmd) # set promiscuous mode on bridge device promisc_cmd = f"{config.IP_TOOL} link set {config.BRIDGE_NAME} promisc on" run.run_cmd(host, promisc_cmd) # set ip address on bridge device ip_cmd = f"{config.IP_TOOL} address add {config.BRIDGE_IP}/" \ f"{config.BRIDGE_IP_PREFIX_LEN} dev {config.BRIDGE_NAME}" run.run_cmd(host, ip_cmd)
def _stop_bridge() -> None: """ Stop vm network bridge """ host = "" # remove ip from bridge device ip_cmd = f"{config.IP_TOOL} address del {config.BRIDGE_IP}/" \ f"{config.BRIDGE_IP_PREFIX_LEN} dev {config.BRIDGE_NAME}" run.run_cmd(host, ip_cmd) # turn promiscuous mode of on bridge device promisc_cmd = f"{config.IP_TOOL} link set {config.BRIDGE_NAME} promisc off" run.run_cmd(host, promisc_cmd) # set bridge down down_cmd = f"{config.IP_TOOL} link set {config.BRIDGE_NAME} down" run.run_cmd(host, down_cmd) # remove bridge device del_cmd = f"{config.IP_TOOL} link del name {config.BRIDGE_NAME} " \ "type bridge" run.run_cmd(host, del_cmd)
def _install_sub_image_kernel(kernel_version: str) -> None: """ Install kernel in sub image """ mount_dir = config.QEMU_IMG_MOUNT_DIR install_host = "" # extract kernel archive to mounted vm image kernel_archive = f"linux-{kernel_version}-x86.tar.xz" cmd = f"{config.TAR_TOOL} xvfJ {kernel_archive} -C {mount_dir}" run.run_cmd(install_host, cmd) # rename/copy installed kernel cmd = f"{config.CP_TOOL} {mount_dir}/boot/vmlinuz-{kernel_version} " \ f"{mount_dir}{config.INSTALL_DEST_KERNEL}" run.run_cmd(install_host, cmd) # create initramfs for kernel cmd = f"{config.MKINITCPIO_TOOL} " \ f"-g {mount_dir}{config.INSTALL_DEST_INITRD} " \ f"-k {kernel_version} -r {mount_dir} -S autodetect" run.run_cmd(install_host, cmd)