From 89dc85733c9b95bd4f5d34b4a3d1a325c2c97253 Mon Sep 17 00:00:00 2001 From: Serhii Turivnyi Date: Nov 15 2017 13:54:34 +0000 Subject: [PATCH 1/5] 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..5bd8efd 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 @@ -56,6 +57,12 @@ chpasswd: list: | root:foobar expire: False +runcmd: + - mkfs.ext4 /dev/sdb + - mount /dev/sdb /mnt + - cp -r /var/lib/docker /mnt + - umount /mnt + - mount /dev/sdb /var/lib/docker """ def main(argv): @@ -77,39 +84,49 @@ 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=None, disk_size=None, 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) try: sock.bind(("127.0.0.3", port)) + + if disk_size: + return subprocess.Popen(["/usr/bin/qemu-system-x86_64", "-m", "1024", image, + "-enable-kvm", "-snapshot", "-cdrom", cloudinit, + "-hdb", disk_directory, + "-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 + else: + 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 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,6 +151,21 @@ def host(image): with open(userdata, 'w') as f: f.write(USER_DATA) + # Create additional disk + disk_size = None + disk_directory = None + try: + disk_size = os.environ.get("EXTEND_DISK_SIZE") + if disk_size: + sys.stderr.write("\nCreate additional cloud init disk DISK SIZE {}\n".format(disk_size)) + + disk_directory = "{}/atomic-host-disk2-{}".format(directory, disk_size) + subprocess.check_call(["qemu-img", "create", "-f", "qcow2", disk_directory, disk_size], stdout=null) + + except KeyError: + sys.stderr.write("\nCouldn't create additional cloud init disk DISK SIZE\n") + pass + # 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", @@ -161,7 +193,7 @@ 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, disk_size=disk_size) break except subprocess.CalledProcessError as cpe: time.sleep(1) @@ -170,36 +202,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)) @@ -208,6 +229,11 @@ def host(image): except subprocess.CalledProcessError: time.sleep(3) else: + # Kill the qemu process + try: + os.kill(proc.pid, signal.SIGTERM) + except OSError: + pass raise RuntimeError("could not access launched qcow2 image: {0}".format(image)) # Process of our parent @@ -233,16 +259,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 +287,6 @@ def host(image): shutil.rmtree(directory) sys.exit(0) + if __name__ == '__main__': sys.exit(main(sys.argv)) From 611456eaafa2c206d1e55649e7e0f0c3efeb8e98 Mon Sep 17 00:00:00 2001 From: Serhii Turivnyi Date: Nov 17 2017 13:47:07 +0000 Subject: [PATCH 2/5] 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..ea16ee1 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 @@ -56,8 +57,15 @@ chpasswd: list: | root:foobar expire: False +runcmd: + - mkfs.ext4 /dev/sdb + - mount /dev/sdb /mnt + - cp -r /var/lib/docker /mnt + - umount /mnt + - mount /dev/sdb /var/lib/docker """ + 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 +85,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 +151,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 +195,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 +205,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 +257,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 +285,6 @@ def host(image): shutil.rmtree(directory) sys.exit(0) + if __name__ == '__main__': sys.exit(main(sys.argv)) From 12667a6aad6155fc1a683d7ebf166f4853f7a507 Mon Sep 17 00:00:00 2001 From: Serhii Turivny Date: Nov 17 2017 13:50:01 +0000 Subject: [PATCH 3/5] Merge branch 'add-additional-disk-space' of ssh://pagure.io/forks/sturivny/standard-test-roles into add-additional-disk-space --- diff --git a/inventory/standard-inventory-qcow2 b/inventory/standard-inventory-qcow2 index ea16ee1..86a3d7e 100755 --- a/inventory/standard-inventory-qcow2 +++ b/inventory/standard-inventory-qcow2 @@ -154,7 +154,7 @@ def host(image): # 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. + # "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: From 48a0524bfe293508e4784798e91384d068a70473 Mon Sep 17 00:00:00 2001 From: Serhii Turivny Date: Nov 17 2017 13:54:21 +0000 Subject: [PATCH 4/5] Merge branch 'add-additional-disk-space' of ssh://pagure.io/forks/sturivny/standard-test-roles into add-additional-disk-space --- diff --git a/inventory/standard-inventory-qcow2 b/inventory/standard-inventory-qcow2 index ea16ee1..aa75166 100755 --- a/inventory/standard-inventory-qcow2 +++ b/inventory/standard-inventory-qcow2 @@ -57,12 +57,6 @@ chpasswd: list: | root:foobar expire: False -runcmd: - - mkfs.ext4 /dev/sdb - - mount /dev/sdb /mnt - - cp -r /var/lib/docker /mnt - - umount /mnt - - mount /dev/sdb /var/lib/docker """ @@ -154,7 +148,7 @@ def host(image): # 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. + # "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: