summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/ogRest.py8
-rw-r--r--src/utils/legacy.py118
2 files changed, 108 insertions, 18 deletions
diff --git a/src/ogRest.py b/src/ogRest.py
index 8e54612..02d3d0c 100644
--- a/src/ogRest.py
+++ b/src/ogRest.py
@@ -205,7 +205,7 @@ class ogThread():
return
kibi = 1024
- datasize = int(image_info['datasize']) * kibi
+ datasize = int(image_info.datasize) * kibi
json_body = jsonBody()
json_body.add_element('disk', request.getDisk())
@@ -215,9 +215,9 @@ class ogThread():
json_body.add_element('name', request.getName())
json_body.add_element('repository', request.getRepo())
json_body.add_element('software', software)
- json_body.add_element('clonator', image_info['clonator'])
- json_body.add_element('compressor', image_info['compressor'])
- json_body.add_element('filesystem', image_info['filesystem'])
+ json_body.add_element('clonator', image_info.clonator)
+ json_body.add_element('compressor', image_info.compressor)
+ json_body.add_element('filesystem', image_info.filesystem)
json_body.add_element('datasize', datasize)
response = restResponse(ogResponses.OK, json_body)
diff --git a/src/utils/legacy.py b/src/utils/legacy.py
index 509b9b0..51d98f3 100644
--- a/src/utils/legacy.py
+++ b/src/utils/legacy.py
@@ -5,28 +5,118 @@ import subprocess
import shlex
import shutil
-from subprocess import PIPE, DEVNULL, CalledProcessError
+from subprocess import PIPE, DEVNULL, STDOUT, CalledProcessError
from src.utils.fs import umount
-def ogGetImageInfo(path):
+class ImageInfo:
"""
- Bash function 'ogGetImageInfo' wrapper (client/engine/Image.lib)
+ Class that stores the OpenGnsys partition image information.
"""
- proc = subprocess.run(f'ogGetImageInfo {path}',
- stdout=PIPE, shell=True,
- encoding='utf-8')
+ def __init__(self, filesystem=None, datasize=None):
+ self.filesystem = filesystem
+ self.datasize = datasize
+ self.clonator = 'PARTCLONE'
+ self.compressor = 'LZOP'
- if proc.stdout.count(':') != 3:
- return ''
- image_info = {}
- (image_info['clonator'],
- image_info['compressor'],
- image_info['filesystem'],
- image_info['datasize']) = proc.stdout.rstrip().split(':', 4)
- image_info['clientname'] = os.getenv('HOSTNAME')
+def human_to_kb(size, unit):
+ """
+ Returns the KB conversion of a human readable string size and unit.
+ """
+ size = float(size.replace(',', '.'))
+ if unit == 'GB':
+ return size * 1000000
+ if unit == 'MB':
+ return size * 1000
+ return 0
+
+
+def fill_imageinfo(line, image_info):
+ """
+ Updates ImageInfo object with information processed from
+ a single partclone.info output line.
+
+ ImageInfo object may not be updated if the line is invalid or does not
+ contain filesystem or device size information.
+ """
+ if 'File system' in line:
+ filesystem = line.rstrip().split(' ')[-1]
+ image_info.filesystem = filesystem
+ elif 'Device size' in line:
+ l = [word for word in line.rstrip().split(' ') if word][2:4]
+ device_size = human_to_kb(*l)
+ image_info.datasize = device_size
+
+
+def process_output_partcloneinfo(output):
+ """
+ Parses image information from partclone.info output.
+
+ Returns an ImageInfo object.
+ """
+ image_info = ImageInfo()
+ for n, line in enumerate(output.split('\n')):
+ if n < 2:
+ continue
+ if image_info.datasize and image_info.filesystem:
+ break
+ fill_imageinfo(line, image_info)
+
+ if not image_info.datasize:
+ raise ValueError("Missing device size from partclone.info output")
+ elif not image_info.filesystem:
+ raise ValueError("Missing filesystem from partclone.info output")
+
+ return image_info
+
+
+def process_image_partcloneinfo(filename):
+ """
+ Decompress using lzop and executes partclone.info to
+ fetch a partition image's information.
+
+ Returns partclone.info stdout and stderr.
+ """
+ cmd1 = f'{shutil.which("lzop")} -dc {filename}'
+ cmd2 = f'{shutil.which("partclone.info")} -s -'
+ args1 = shlex.split(cmd1)
+ args2 = shlex.split(cmd2)
+ p1 = subprocess.Popen(args1, stdout=PIPE, stderr=DEVNULL)
+ p2 = subprocess.Popen(args2, stdout=PIPE, stdin=p1.stdout,
+ stderr=STDOUT, encoding='utf-8')
+ p1.stdout.close()
+ p2_out, p2_err = p2.communicate()
+
+ if p2.returncode != 0:
+ raise ValueError('Unable to process image {filename}')
+
+ return p2_out
+
+
+def ogGetImageInfo(filename):
+ """
+ Obtain filesystem and device size information of an OpenGnsys partition
+ image.
+
+ This method supports compressed images with lzop that have been created
+ with partclone.
+
+ Returns an ImageInfo object.
+
+ >>> image_info = ogGetImageInfo('/opt/opengnsys/images/foobar.img')
+ >>> image_info.filesystem
+ >>> 'NTFS'
+ >>> image_info.datasize
+ >>> 140000000
+ >>> image_info.compressor
+ >>> 'LZOP'
+ >>> image_info.clonator
+ >>> 'PARTCLONE'
+ """
+ out = process_image_partcloneinfo(filename)
+ image_info = process_output_partcloneinfo(out)
return image_info