#!/usr/bin/python3 # This file is part of Cockpit. # # Copyright (C) 2013 Red Hat, Inc. # # Cockpit is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # Cockpit is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with Cockpit; If not, see . import argparse import errno import os import subprocess import sys import re from machine import testvm BOTS = os.path.abspath(os.path.dirname(__file__)) NETWORK_SCRIPT=b""" set -ex virsh net-destroy cockpit1 || true virsh net-undefine cockpit1 || true virsh net-define /dev/stdin < cockpit1 f3605fa4-0763-41ea-8143-49da3bf73263 EOF if [ ! -u /usr/libexec/qemu-bridge-helper ]; then chmod -v u+s /usr/libexec/qemu-bridge-helper fi for qemu_config in /etc/qemu-kvm/bridge.conf /etc/qemu/bridge.conf; do if [ -e "$qemu_config" ] && ! grep -qF cockpit1 "$qemu_config"; then echo "allow cockpit1" >> "$qemu_config" fi done virsh net-autostart cockpit1 virsh net-start cockpit1 """ parser = argparse.ArgumentParser(description='Run a test machine') parser.add_argument('-v', '--verbose', action='store_true', help='Display verbose details') parser.add_argument('-m', '--maintain', action='store_true', help='Changes are permanent') parser.add_argument('-M', '--memory', default=None, type=int, help='Memory (in MiB) of the target machine') parser.add_argument('-G', '--graphics', action='store_true', help='Display a graphics console') parser.add_argument('-C', '--cpus', default=None, type=int, help='Number of cpus in the target machine') parser.add_argument('-S', '--storage', default=None, type=str, help='Add a second qcow2 disk at this path') parser.add_argument('--network', action='store_true', help='Setup a bridged network for running machines') parser.add_argument('--no-network', action='store_true', help='Do not connect the machine to the Internet') parser.add_argument('image', help='The image to run') args = parser.parse_args() try: if args.network: proc = subprocess.Popen(["sudo", "/bin/sh"], stdin=subprocess.PIPE) proc.communicate(NETWORK_SCRIPT) if proc.returncode != 0: sys.stderr.write("vm-run: failed to create cockpit1 network\n") sys.exit(1) bridge=None with open(os.devnull, 'w') as fp: if subprocess.call(["ip", "address", "show", "dev", "cockpit1"], stdout=fp, stderr=fp) == 0: bridge = "cockpit1" # Lets make sure Windows has enough memory to be productive memory = args.memory if "windows" in args.image and memory is None: memory = 4096 graphics = args.graphics or 'windows' in args.image network = testvm.VirtNetwork(0, bridge=bridge, image=args.image) machine = testvm.VirtMachine(verbose=args.verbose, image=args.image, maintain=args.maintain, networking=network.host(restrict=args.no_network), memory_mb=memory, cpus=args.cpus, graphics=graphics) # Hack to make things easier for users who don't know about kubeconfig if 'openshift' in args.image: kubeconfig = os.path.join(os.path.expanduser("~"), ".kube", "config") if not os.path.lexists(kubeconfig): d = os.path.dirname(kubeconfig) src = os.path.abspath(os.path.join(BOTS, "images", "files", "openshift.kubeconfig")) os.makedirs(d, exist_ok=True) sys.stderr.write("image-run: linking kubeconfig into ~/.kube/config\n") os.symlink(src, kubeconfig) # Check that image is downloaded if not os.path.exists(machine.image_file): try: ret = subprocess.call([ os.path.join(BOTS, "image-download"), args.image]) except OSError as ex: if ex.errno != errno.ENOENT: raise else: if ret != 0: sys.exit(ret) machine.start() if args.storage: machine.add_disk(path=args.storage, type='qcow2') # for a bridged network, up its interface with DHCP and show it in the console message message = "" if args.network and bridge and 'windows' not in args.image: machine.execute("nmcli connection modify 'System eth1' ipv4.method auto && nmcli connection up 'System eth1'") output = machine.execute("ip -4 a show dev eth1") ip = re.search("inet ([^/]+)", output).group(1) message = "\nBRIDGE IP FROM HOST\n %s\n" % ip # Graphics console necessary if graphics: machine.graphics_console() # No graphics console necessary else: machine.qemu_console(message) except testvm.Failure as ex: sys.stderr.write("vm-run: %s\n" % ex) sys.exit(1)