mirror of
https://github.com/gryf/boxpy.git
synced 2025-12-19 13:37:58 +01:00
Introducing custom exceptions tree.
This commit is contained in:
56
box.py
56
box.py
@@ -34,6 +34,26 @@ power_state:
|
|||||||
''')
|
''')
|
||||||
|
|
||||||
|
|
||||||
|
class BoxError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class BoxNotFound(BoxError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class BoxVBoxFailure(BoxError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class BoxConvertionError(BoxError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class BoxSysCommandError(BoxError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class VMCreate:
|
class VMCreate:
|
||||||
"""
|
"""
|
||||||
Create vbox VM of Ubuntu server from cloud image with the following steps:
|
Create vbox VM of Ubuntu server from cloud image with the following steps:
|
||||||
@@ -64,8 +84,8 @@ class VMCreate:
|
|||||||
if not self.ssh_key_path.endswith('.pub'):
|
if not self.ssh_key_path.endswith('.pub'):
|
||||||
self.ssh_key_path += '.pub'
|
self.ssh_key_path += '.pub'
|
||||||
if not os.path.exists(self.ssh_key_path):
|
if not os.path.exists(self.ssh_key_path):
|
||||||
raise AttributeError(f'Cannot find default ssh public key: '
|
raise BoxNotFound(f'Cannot find default ssh public key: '
|
||||||
f'{self.ssh_key_path}')
|
f'{self.ssh_key_path}')
|
||||||
|
|
||||||
self._img = f"ubuntu-{self.ubuntu_version}-server-cloudimg-amd64.img"
|
self._img = f"ubuntu-{self.ubuntu_version}-server-cloudimg-amd64.img"
|
||||||
self._temp_path = None
|
self._temp_path = None
|
||||||
@@ -89,7 +109,7 @@ class VMCreate:
|
|||||||
def _power_on_and_wait_for_ci_finish(self):
|
def _power_on_and_wait_for_ci_finish(self):
|
||||||
if subprocess.call(['vboxmanage', 'startvm', self._vm_uuid, '--type',
|
if subprocess.call(['vboxmanage', 'startvm', self._vm_uuid, '--type',
|
||||||
'headless']) != 0:
|
'headless']) != 0:
|
||||||
raise AttributeError(f'Failed to start: {self.vm_name}.')
|
raise BoxVBoxFailure(f'Failed to start: {self.vm_name}.')
|
||||||
|
|
||||||
# give VBox some time to actually change the state of the VM before
|
# give VBox some time to actually change the state of the VM before
|
||||||
# query
|
# query
|
||||||
@@ -112,13 +132,13 @@ class VMCreate:
|
|||||||
'--device', '0',
|
'--device', '0',
|
||||||
'--type', 'dvddrive',
|
'--type', 'dvddrive',
|
||||||
'--medium', 'none']) != 0:
|
'--medium', 'none']) != 0:
|
||||||
raise AttributeError(f'Failed to detach cloud image from '
|
raise BoxVBoxFailure(f'Failed to detach cloud image from '
|
||||||
f'{self.vm_name} VM.')
|
f'{self.vm_name} VM.')
|
||||||
|
|
||||||
# and start it again
|
# and start it again
|
||||||
if subprocess.call(['vboxmanage', 'startvm', self._vm_uuid, '--type',
|
if subprocess.call(['vboxmanage', 'startvm', self._vm_uuid, '--type',
|
||||||
'headless']) != 0:
|
'headless']) != 0:
|
||||||
raise AttributeError(f'Failed to start: {self.vm_name}.')
|
raise BoxVBoxFailure(f'Failed to start: {self.vm_name}.')
|
||||||
|
|
||||||
print('You can access your VM by issuing:')
|
print('You can access your VM by issuing:')
|
||||||
print(f'ssh -p 2222 -i {self.ssh_key_path[:-4]} ubuntu@localhost')
|
print(f'ssh -p 2222 -i {self.ssh_key_path[:-4]} ubuntu@localhost')
|
||||||
@@ -154,7 +174,7 @@ class VMCreate:
|
|||||||
for cmd in commands:
|
for cmd in commands:
|
||||||
if subprocess.call(cmd) != 0:
|
if subprocess.call(cmd) != 0:
|
||||||
cmd = ' '.join(cmd)
|
cmd = ' '.join(cmd)
|
||||||
raise AttributeError(f'command: {cmd} has failed')
|
raise BoxVBoxFailure(f'command: {cmd} has failed')
|
||||||
|
|
||||||
def _create_and_setup_vm(self):
|
def _create_and_setup_vm(self):
|
||||||
out = subprocess.check_output(['vboxmanage', 'createvm', '--name',
|
out = subprocess.check_output(['vboxmanage', 'createvm', '--name',
|
||||||
@@ -166,7 +186,7 @@ class VMCreate:
|
|||||||
self._vm_uuid = line.split('UUID:')[1].strip()
|
self._vm_uuid = line.split('UUID:')[1].strip()
|
||||||
|
|
||||||
if not self._vm_uuid:
|
if not self._vm_uuid:
|
||||||
raise OSError(f'Cannot create VM "{self.vm_name}".')
|
raise BoxVBoxFailure(f'Cannot create VM "{self.vm_name}".')
|
||||||
|
|
||||||
if subprocess.call(['vboxmanage', 'modifyvm', self._vm_uuid,
|
if subprocess.call(['vboxmanage', 'modifyvm', self._vm_uuid,
|
||||||
'--memory', str(self.memory),
|
'--memory', str(self.memory),
|
||||||
@@ -176,7 +196,7 @@ class VMCreate:
|
|||||||
'--audio', 'none',
|
'--audio', 'none',
|
||||||
'--nic1', 'nat',
|
'--nic1', 'nat',
|
||||||
'--natpf1', 'guestssh,tcp,,2222,,22']) != 0:
|
'--natpf1', 'guestssh,tcp,,2222,,22']) != 0:
|
||||||
raise OSError(f'Cannot modify VM "{self._vm_uuid}".')
|
raise BoxVBoxFailure(f'Cannot modify VM "{self._vm_uuid}".')
|
||||||
out = subprocess.check_output(['vboxmanage', 'showvminfo',
|
out = subprocess.check_output(['vboxmanage', 'showvminfo',
|
||||||
self._vm_uuid],
|
self._vm_uuid],
|
||||||
encoding=sys.getdefaultencoding())
|
encoding=sys.getdefaultencoding())
|
||||||
@@ -186,7 +206,7 @@ class VMCreate:
|
|||||||
path = os.path.dirname(line.split('Config file:')[1].strip())
|
path = os.path.dirname(line.split('Config file:')[1].strip())
|
||||||
|
|
||||||
if not path:
|
if not path:
|
||||||
raise AttributeError(f'There is something wrong doing VM '
|
raise BoxVBoxFailure(f'There is something wrong doing VM '
|
||||||
f'"{self.vm_name}" creation and registration')
|
f'"{self.vm_name}" creation and registration')
|
||||||
|
|
||||||
self._vm_base_path = path
|
self._vm_base_path = path
|
||||||
@@ -212,7 +232,8 @@ class VMCreate:
|
|||||||
os.path.join(self._tmp, self.CLOUD_IMAGE),
|
os.path.join(self._tmp, self.CLOUD_IMAGE),
|
||||||
os.path.join(self._tmp, 'user-data'),
|
os.path.join(self._tmp, 'user-data'),
|
||||||
os.path.join(self._tmp, 'meta-data')]) != 0:
|
os.path.join(self._tmp, 'meta-data')]) != 0:
|
||||||
raise AttributeError('Cannot create ISO image for config drive')
|
raise BoxSysCommandError('Cannot create ISO image for config '
|
||||||
|
'drive')
|
||||||
|
|
||||||
def _prepare_temp(self):
|
def _prepare_temp(self):
|
||||||
self._tmp = tempfile.mkdtemp()
|
self._tmp = tempfile.mkdtemp()
|
||||||
@@ -234,7 +255,7 @@ class VMCreate:
|
|||||||
break
|
break
|
||||||
|
|
||||||
if not expected_sum:
|
if not expected_sum:
|
||||||
raise AttributeError('Cannot find provided cloud image')
|
raise BoxError('Cannot find provided cloud image')
|
||||||
|
|
||||||
if os.path.exists(os.path.join(self.CACHE_DIR, self._img)):
|
if os.path.exists(os.path.join(self.CACHE_DIR, self._img)):
|
||||||
cmd = 'sha256sum ' + os.path.join(self.CACHE_DIR, self._img)
|
cmd = 'sha256sum ' + os.path.join(self.CACHE_DIR, self._img)
|
||||||
@@ -248,7 +269,8 @@ class VMCreate:
|
|||||||
raw_path = os.path.join(self._tmp, self._img + ".raw")
|
raw_path = os.path.join(self._tmp, self._img + ".raw")
|
||||||
if subprocess.call(['qemu-img', 'convert', '-O', 'raw',
|
if subprocess.call(['qemu-img', 'convert', '-O', 'raw',
|
||||||
img_path, raw_path]) != 0:
|
img_path, raw_path]) != 0:
|
||||||
raise AttributeError(f'Cannot convert image {self._img} to RAW.')
|
raise BoxConvertionError(f'Cannot convert image {self._img} to '
|
||||||
|
'RAW.')
|
||||||
|
|
||||||
def _convert_and_resize(self):
|
def _convert_and_resize(self):
|
||||||
self._convert_to_raw()
|
self._convert_to_raw()
|
||||||
@@ -256,8 +278,8 @@ class VMCreate:
|
|||||||
vdi_path = os.path.join(self._tmp, self._disk_img)
|
vdi_path = os.path.join(self._tmp, self._disk_img)
|
||||||
if subprocess.call(["vboxmanage", "convertfromraw", raw_path,
|
if subprocess.call(["vboxmanage", "convertfromraw", raw_path,
|
||||||
vdi_path]) != 0:
|
vdi_path]) != 0:
|
||||||
raise AttributeError(f'Cannot convert image {self._disk_img} '
|
raise BoxVBoxFailure(f'Cannot convert image {self._disk_img} '
|
||||||
'to VDI.')
|
f'to VDI.')
|
||||||
os.unlink(raw_path)
|
os.unlink(raw_path)
|
||||||
|
|
||||||
def _download_image(self):
|
def _download_image(self):
|
||||||
@@ -275,8 +297,8 @@ class VMCreate:
|
|||||||
|
|
||||||
if not self._checksum():
|
if not self._checksum():
|
||||||
# TODO: make some retry mechanism?
|
# TODO: make some retry mechanism?
|
||||||
raise AttributeError('Checksum for downloaded image differ from'
|
raise BoxSysCommandError('Checksum for downloaded image differ '
|
||||||
' expected')
|
'from expected.')
|
||||||
else:
|
else:
|
||||||
print(f'Downloaded image {self._img}')
|
print(f'Downloaded image {self._img}')
|
||||||
|
|
||||||
@@ -295,7 +317,7 @@ class VMDestroy:
|
|||||||
'poweroff'], stderr=subprocess.DEVNULL)
|
'poweroff'], stderr=subprocess.DEVNULL)
|
||||||
if subprocess.call(['vboxmanage', 'unregistervm', self.vm_name_or_uuid,
|
if subprocess.call(['vboxmanage', 'unregistervm', self.vm_name_or_uuid,
|
||||||
'--delete']) != 0:
|
'--delete']) != 0:
|
||||||
raise AttributeError(f'Removing VM {self.vm_name_or_uuid} failed')
|
raise BoxVBoxFailure(f'Removing VM {self.vm_name_or_uuid} failed')
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
Reference in New Issue
Block a user