From 93b2ab6875583c230e57f9e3210d078bd7ec67d0 Mon Sep 17 00:00:00 2001 From: Serhii Turivnyi Date: Nov 21 2017 09:18:07 +0000 Subject: Add additional disk to the Atomic VM To test this feature the environment variable has to be exported: export EXTEND_DISK_SIZE=8G Any disk size can be set according to the `qemu-img` documentation. Additional space will be mounted to the /var/lib/docker --- diff --git a/inventory/standard-inventory-qcow2 b/inventory/standard-inventory-qcow2 index 24978dc..aa75166 100755 --- a/inventory/standard-inventory-qcow2 +++ b/inventory/standard-inventory-qcow2 @@ -12,7 +12,6 @@ import subprocess import sys import tempfile import time -import traceback import distutils.util IDENTITY = """ @@ -49,6 +48,8 @@ USER_DATA = """#cloud-config users: - default - name: root + groups: sudo + shell: /bin/bash ssh_authorized_keys: - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDUOtNJdBEXyKxBB898rdT54ULjMGuO6v4jLXmRsdRhR5Id/lKNc9hsdioPWUePgYlqML2iSV72vKQoVhkyYkpcsjr3zvBny9+5xej3+TBLoEMAm2hmllKPmxYJDU8jQJ7wJuRrOVOnk0iSNF+FcY/yaQ0owSF02Nphx47j2KWc0IjGGlt4fl0fmHJuZBA2afN/4IYIIsEWZziDewVtaEjWV3InMRLllfdqGMllhFR+ed2hQz9PN2QcapmEvUR4UCy/mJXrke5htyFyHi8ECfyMMyYeHwbWLFQIve4CWix9qtksvKjcetnxT+WWrutdr3c9cfIj/c0v/Zg/c4zETxtp standard-test-qcow2 ssh_pwauth: True @@ -58,6 +59,7 @@ chpasswd: expire: False """ + def main(argv): parser = argparse.ArgumentParser(description="Inventory for a QCow2 test image") parser.add_argument("--list", action="store_true", help="Verbose output") @@ -77,39 +79,48 @@ def main(argv): return 0 + def list(subjects): - hosts = [ ] - variables = { } + hosts = [] + variables = {} for subject in subjects: if subject.endswith((".qcow2", ".qcow2c")): vars = host(subject) if vars: hosts.append(subject) variables[subject] = vars - return { "localhost": { "hosts": hosts, "vars": { } }, "subjects": { "hosts": hosts, "vars": { } }, "_meta": { "hostvars": variables } } + return {"localhost": {"hosts": hosts, "vars": {}}, + "subjects": {"hosts": hosts, "vars": {}}, + "_meta": {"hostvars": variables}} -def start_qemu(image, cloudinit, log, portrange=(2222, 5555)): +def start_qemu(image, cloudinit, log, disk_directory="", portrange=(2222, 5555)): for port in xrange(*portrange): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + + # Shape cmd to sturt qemu + disk_name = "" if disk_directory == "" else "-hdb" + + cmd = ("/usr/bin/qemu-system-x86_64 -m 1024 {0} -enable-kvm " + "-snapshot -cdrom {1} {2} {3} " + "-net nic,model=virtio -net " + "user,hostfwd=tcp:127.0.0.3:{4}-:22 -device " + "isa-serial,chardev=pts2 -chardev " + "file,id=pts2,path={5} -display none").format( + image, cloudinit, disk_name, disk_directory, port, log).split() + try: sock.bind(("127.0.0.3", port)) + return subprocess.Popen(cmd, stdout=open(os.devnull, 'w')), port + except IOError: pass - else: - break finally: sock.close() else: raise RuntimeError("unable to find free local port to map SSH to") - return subprocess.Popen(["/usr/bin/qemu-system-x86_64", "-m", "1024", image, - "-enable-kvm", "-snapshot", "-cdrom", cloudinit, - "-net", "nic,model=virtio", "-net", "user,hostfwd=tcp:127.0.0.3:{0}-:22".format(port), - "-device", "isa-serial,chardev=pts2", "-chardev", "file,id=pts2,path=" + log, - "-display", "none"], stdout=open(os.devnull, 'w')), port - def host(image): null = open(os.devnull, 'w') @@ -134,11 +145,28 @@ def host(image): with open(userdata, 'w') as f: f.write(USER_DATA) + # Create additional disk if environment variable EXTEND_DISK_SIZE + # was provided. + # Optional suffixes "k" or "K" (kilobyte, 1024) "M" (megabyte, 1024k) and + # "G" (gigabyte, 1024M) and T (terabyte, 1024G) are supported. + disk_size = os.environ.get("EXTEND_DISK_SIZE") + disk_directory = "{}/atomic-host-disk2-{}".format(directory, disk_size) + try: + subprocess.check_call([ + "qemu-img", "create", "-f", "qcow2", disk_directory, disk_size], + stdout=null) + sys.stderr.write( + "\nCreate additional cloud init disk DISK SIZE {}\n".format( + disk_size)) + except TypeError: + disk_directory ="" + # Create our cloud init so we can log in cloudinit = os.path.join(directory, "cloud-init.iso") subprocess.check_call(["/usr/bin/genisoimage", "-input-charset", "utf-8", "-volid", "cidata", "-joliet", "-rock", "-quiet", - "-output", cloudinit, userdata, metadata], stdout=null) + "-output", cloudinit, userdata, metadata], + stdout=null) # Determine if virtual machine should be kept available for diagnosis after completion try: @@ -161,7 +189,8 @@ def host(image): cpe = None # for exception scoping for tries in xrange(0, 5): try: - proc, port = start_qemu(image, cloudinit, log) + proc, port = start_qemu(image, cloudinit, log, + disk_directory=disk_directory) break except subprocess.CalledProcessError as cpe: time.sleep(1) @@ -170,36 +199,25 @@ def host(image): raise RuntimeError("Could not launch VM for qcow2 image" " '{0}':{1}".format(image, cpe.output)) + # The variables + variables = {"ansible_ssh_port": "{0}".format(port), + "ansible_ssh_host": "127.0.0.3", + "ansible_ssh_user": "root", + "ansible_ssh_pass": "foobar", + "ansible_ssh_private_key_file": identity, + "ansible_ssh_common_args": "-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"} + + # Write out a handy inventory file, for our use and for debugging + args = " ".join(["{0}='{1}'".format(*item) for item in variables.items()]) + inventory = os.path.join(directory, "inventory") + with open(inventory, "w") as f: + f.write("[subjects]\nlocalhost {1}\n".format(image, args)) + + # Wait for ssh to come up + ping = ["/usr/bin/ansible", "--inventory", inventory, "localhost", "--module-name", "raw", "--args", "/bin/true"] + for tries in xrange(0, 30): try: - # The variables - variables = { - "ansible_ssh_port": "{0}".format(port), - "ansible_ssh_host": "127.0.0.3", - "ansible_ssh_user": "root", - "ansible_ssh_pass": "foobar", - "ansible_ssh_private_key_file": identity, - "ansible_ssh_common_args": "-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" - } - - # Write out a handy inventory file, for our use and for debugging - args = " ".join([ "{0}='{1}'".format(*item) for item in variables.items() ]) - inventory = os.path.join(directory, "inventory") - with open(inventory, "w") as f: - f.write("[subjects]\nlocalhost {1}\n".format(image, args)) - - # Wait for ssh to come up - ping = [ - "/usr/bin/ansible", - "--inventory", - inventory, - "localhost", - "--module-name", - "raw", - "--args", - "/bin/true" - ] - (pid, ret) = os.waitpid(proc.pid, os.WNOHANG) if pid != 0: raise RuntimeError("qemu failed to launch qcow2 image: {0}".format(image)) @@ -233,16 +251,16 @@ def host(image): # Now wait for the parent process to go away, then kill the VM while True: time.sleep(3) - try: os.kill(ppid, 0) os.kill(proc.pid, 0) except OSError: - break # Either of the processes no longer exist + break # Either of the processes no longer exist if diagnose: sys.stderr.write("\n") - sys.stderr.write("DIAGNOSE: ssh -p {0} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null root@{1} # password: {2}\n".format(port, "127.0.0.3", "foobar")) + sys.stderr.write("DIAGNOSE: ssh -p {0} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null " + "root@{1} # password: {2}\n".format(port, "127.0.0.3", "foobar")) sys.stderr.write("DIAGNOSE: export ANSIBLE_INVENTORY={0}\n".format(inventory)) sys.stderr.write("DIAGNOSE: kill {0} # when finished\n".format(os.getpid())) @@ -261,5 +279,6 @@ def host(image): shutil.rmtree(directory) sys.exit(0) + if __name__ == '__main__': sys.exit(main(sys.argv))