diff --git a/box.py b/box.py index f336f4a..6e59632 100755 --- a/box.py +++ b/box.py @@ -7,8 +7,23 @@ import tempfile class VMCreate: + """ + Create vbox VM of Ubuntu server from cloud image with the following steps: + - grab the image, unless it exists in XDG_CACHE_HOME + - convert it to raw, than to VDI, remove raw + - resize it to the right size + - create cloud ISO image with some basic bootstrap + - create and register VM definition + - tweak its params + - move disk image to the Machine directory + - attach disk and iso images to it + - run and wait for initial bootstrap, than acpishutdown + - detach iso image and remove it + """ CLOUD_IMAGE = "ci.iso" CLOUD_INIT_FINISHED_CMD = "test /var/lib/cloud/instance/boot-finished" + CACHE_DIR = os.environ.get('XDG_CACHE_HOME', + os.path.expanduser('~/.cache')) def __init__(self, args): self.vm_name = args.name @@ -16,6 +31,7 @@ class VMCreate: self.memory = args.memory self.disk_size = args.disk_size self.ubuntu_version = args.version + self._img = f"ubuntu-{self.ubuntu_version}-server-cloudimg-amd64.img" self._temp_path = None self._disk_img = self.vm_name + '.vdi' self._tmp = None @@ -31,14 +47,51 @@ class VMCreate: def _prepare_temp(self): self._tmp = tempfile.mkdtemp() + def _checksum(self): + expected_sum = None + fname = 'SHA256SUMS' + url = "https://cloud-images.ubuntu.com/releases/" + url += f"{self.ubuntu_version}/release/{fname}" + # TODO: make the verbosity switch be dependent from verbosity of the + # script. + subprocess.call(['wget', url, '-q', '-O', + os.path.join(self._tmp, fname)]) + + with open(os.path.join(self._tmp, fname)) as fobj: + for line in fobj.readlines(): + if self._img in line: + expected_sum = line.split(' ')[0] + break + + if not expected_sum: + raise AttributeError('Cannot find provided cloud image') + + if os.path.exists(os.path.join(self.CACHE_DIR, self._img)): + cmd = 'sha256sum ' + os.path.join(self.CACHE_DIR, self._img) + calulated_sum = subprocess.getoutput(cmd).split(' ')[0] + return calulated_sum == expected_sum + + return False + def _download_image(self): + if self._checksum(): + print(f'Image already downloaded: {self._img}') + return + url = "https://cloud-images.ubuntu.com/releases/" url += f"{self.ubuntu_version}/release/" img = f"ubuntu-{self.ubuntu_version}-server-cloudimg-amd64.img" url += img - print(url) + print(f'Downloading image {self._img}') + subprocess.call(['wget', '-q', url, '-O', + os.path.join(self.CACHE_DIR, self._img)]) - subprocess.call(['wget', url, '-O', os.path.join(self._tmp, img)]) + if not self._checksum(): + # TODO: make some retry mechanism? + raise AttributeError('Checksum for downloaded image differ from' + ' expected') + else: + print(f'downloaded image {self._img}') def _cleanup(self): subprocess.call(['rm', '-fr', self._tmp]) @@ -71,9 +124,7 @@ def main(): args = parser.parse_args() - return args.func(args) try: - # __import__('ipdb').set_trace() return args.func(args) except AttributeError: parser.print_help()