#94 Add additional disk to the Atomic VM
Closed 6 years ago by sturivny. Opened 6 years ago by sturivny.
Unknown source add-disk-atomic-vm  into  master

@@ -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,11 +59,14 @@

    expire: False

  """

  

+ 

  def main(argv):

-     parser = argparse.ArgumentParser(description="Inventory for a QCow2 test image")

+     parser = argparse.ArgumentParser(

+         description="Inventory for a QCow2 test image")

      parser.add_argument("--list", action="store_true", help="Verbose output")

      parser.add_argument('--host', help="Get host variables")

-     parser.add_argument("subjects", nargs="*", default=shlex.split(os.environ.get("TEST_SUBJECTS", "")))

+     parser.add_argument("subjects", nargs="*", default=shlex.split(

+         os.environ.get("TEST_SUBJECTS", "")))

      opts = parser.parse_args()

  

      try:
@@ -72,44 +76,55 @@

              data = list(opts.subjects)

          sys.stdout.write(json.dumps(data, indent=4, separators=(',', ': ')))

      except RuntimeError as ex:

-         sys.stderr.write("{0}: {1}\n".format(os.path.basename(sys.argv[0]), str(ex)))

+         sys.stderr.write("{0}: {1}\n".format(os.path.basename(sys.argv[0]),

+                                              str(ex)))

          return 1

  

      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 start 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,13 +149,31 @@

      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

+     # Determine if virtual machine should be kept available for diagnosis after

+     # completion

      try:

          diagnose = distutils.util.strtobool(os.getenv("TEST_DEBUG", "0"))

      except ValueError:
@@ -149,7 +182,8 @@

      sys.stderr.write("Launching virtual machine for {0}\n".format(image))

  

      # And launch the actual VM

-     artifacts = os.environ.get("TEST_ARTIFACTS", os.path.join(os.getcwd(), "artifacts"))

+     artifacts = os.environ.get("TEST_ARTIFACTS", os.path.join(os.getcwd(),

+                                                               "artifacts"))

      try:

          os.makedirs(artifacts)

      except OSError as exc:
@@ -161,7 +195,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,45 +205,38 @@

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

+                 raise RuntimeError(

+                     "qemu failed to launch qcow2 image: {0}".format(image))

              subprocess.check_call(ping, stdout=null, stderr=null)

              break

          except subprocess.CalledProcessError:

              time.sleep(3)

      else:

-         raise RuntimeError("could not access launched qcow2 image: {0}".format(image))

+         raise RuntimeError(

+             "could not access launched qcow2 image: {0}".format(image))

  

      # Process of our parent

      ppid = os.getppid()
@@ -233,18 +261,22 @@

      # 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: export ANSIBLE_INVENTORY={0}\n".format(inventory))

-         sys.stderr.write("DIAGNOSE: kill {0} # when finished\n".format(os.getpid()))

+         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()))

  

          def _signal_handler(*args):

              sys.stderr.write("\nDIAGNOSE ending...\n")
@@ -261,5 +293,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.
Additional space will be mounted to the /var/lib/docker

Pull-Request has been closed by sturivny

6 years ago
Metadata