#89 Add additional disk to the Atomic VM
Closed 6 years ago by sturivny. Opened 6 years ago by sturivny.

@@ -12,7 +12,6 @@

  import sys

  import tempfile

  import time

- import traceback

  import distutils.util

  

  IDENTITY = """
@@ -49,6 +48,8 @@

  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 @@

    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 @@

  

      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 @@

      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 @@

      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 @@

          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 @@

      # 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 @@

      shutil.rmtree(directory)

      sys.exit(0)

  

+ 

  if __name__ == '__main__':

      sys.exit(main(sys.argv))

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.

This PR has 5 commits. Is it necessary to have all above commits in git history?

Pull-Request has been closed by sturivny

6 years ago
Metadata