summaryrefslogtreecommitdiffstats
path: root/src/live/ogOperations.py
diff options
context:
space:
mode:
authorJose M. Guisado <jguisado@soleta.eu>2022-07-05 17:11:26 +0200
committerJose M. Guisado <jguisado@soleta.eu>2022-08-24 09:48:35 +0200
commit3550da73e6da062d69dd0d7f1f6889b684abb15d (patch)
tree56d75bcc720468d6bebe889d21e06148e7322033 /src/live/ogOperations.py
parent74a61d6a7d71fa0bfb2a762bad7f754f33f63895 (diff)
image_create: partial integration into pythonv1.2.2
Integrates some parts of this operation into native code, eg: the md5 checksum computation. Wraps non native processes and commands using the subprocess module. For example, legacy.py stores bash commands pending integration. Supports python >=3.6, expected until more modern ogLives are put into production environments.
Diffstat (limited to 'src/live/ogOperations.py')
-rw-r--r--src/live/ogOperations.py105
1 files changed, 80 insertions, 25 deletions
diff --git a/src/live/ogOperations.py b/src/live/ogOperations.py
index 1b2c3dd..439d1d7 100644
--- a/src/live/ogOperations.py
+++ b/src/live/ogOperations.py
@@ -6,9 +6,13 @@
# Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
+import hashlib
import logging
import os
import subprocess
+import shlex
+
+from subprocess import Popen, PIPE
import fdisk
@@ -16,9 +20,10 @@ from src.ogClient import ogClient
from src.ogRest import ThreadState
from src.live.partcodes import GUID_MAP
+from src.utils.legacy import *
from src.utils.net import ethtool
from src.utils.menu import generate_menu
-from src.utils.fs import mount_mkdir, umount, get_usedperc
+from src.utils.fs import *
from src.utils.probe import os_probe, cache_probe
from src.utils.disk import get_disks
from src.utils.cache import generate_cache_txt
@@ -30,6 +35,8 @@ class OgLiveOperations:
def __init__(self, config):
self._url = config['opengnsys']['url']
self._url_log = config['opengnsys']['url_log']
+ self._smb_user = config['samba']['user']
+ self._smb_pass = config['samba']['pass']
def _restartBrowser(self, url):
try:
@@ -91,6 +98,25 @@ class OgLiveOperations:
part_setup['filesystem'] = 'CACHE'
part_setup['code'] = 'ca'
+ def _compute_md5(self, path, bs=2**20):
+ m = hashlib.md5()
+ with open(path, 'rb') as f:
+ while True:
+ buf = f.read(bs)
+ if not buf:
+ break
+ m.update(buf)
+ return m.hexdigest()
+
+ def _write_md5_file(self, path):
+ if not os.path.exists(path):
+ logging.error('Invalid path in _write_md5_file')
+ raise ValueError('Invalid image path when computing md5 checksum')
+ filename = path + ".full.sum"
+ dig = self._compute_md5(path)
+ with open(filename, 'w') as f:
+ f.write(dig)
+
def poweroff(self):
logging.info('Powering off client')
if os.path.exists('/scripts/oginit'):
@@ -262,17 +288,20 @@ class OgLiveOperations:
return output.decode('utf-8')
def image_create(self, path, request, ogRest):
- disk = request.getDisk()
- partition = request.getPartition()
+ disk = int(request.getDisk())
+ partition = int(request.getPartition())
name = request.getName()
repo = request.getRepo()
cmd_software = f'{ogClient.OG_PATH}interfaceAdm/InventarioSoftware {disk} ' \
f'{partition} {path}'
- cmd_create_image = f'{ogClient.OG_PATH}interfaceAdm/CrearImagen {disk} ' \
- f'{partition} {name} {repo}'
+ image_path = f'/opt/opengnsys/images/{name}.img'
self._restartBrowser(self._url_log)
+ if ogChangeRepo(repo).returncode != 0:
+ logging.error('ogChangeRepo could not change repository to %s', repo)
+ raise ValueError(f'Error: Cannot change repository to {repo}')
+
try:
ogRest.proc = subprocess.Popen([cmd_software],
stdout=subprocess.PIPE,
@@ -287,31 +316,57 @@ class OgLiveOperations:
return
try:
- ogRest.proc = subprocess.Popen([cmd_create_image],
- stdout=subprocess.PIPE,
- shell=True,
- executable=OG_SHELL)
- ogRest.proc.communicate()
- except:
- logging.error('Exception when running "image create" subprocess')
- raise ValueError('Error: Incorrect command value')
+ diskname = get_disks()[disk-1]
+ cxt = fdisk.Context(f'/dev/{diskname}', details=True)
+ pa = None
- if ogRest.proc.returncode != 0:
- logging.warn('Image creation failed')
- raise ValueError('Error: Image creation failed')
+ for i, p in enumerate(cxt.partitions):
+ if (p.partno + 1) == partition:
+ pa = cxt.partitions[i]
- with open('/tmp/image.info') as file_info:
- line = file_info.readline().rstrip()
+ if pa is None:
+ logging.error('Target partition not found')
+ raise ValueError('Target partition number not found')
- image_info = {}
+ padev = cxt.partition_to_string(pa, fdisk.FDISK_FIELD_DEVICE)
+ fstype = cxt.partition_to_string(pa, fdisk.FDISK_FIELD_FSTYPE)
+ if not fstype:
+ logging.error('No filesystem detected. Aborting image creation.')
+ raise ValueError('Target partition has no filesystem present')
- (image_info['clonator'],
- image_info['compressor'],
- image_info['filesystem'],
- image_info['datasize'],
- image_info['clientname']) = line.split(':', 5)
+ cambiar_acceso(user=self._smb_user, pwd=self._smb_pass)
+ ogReduceFs(disk, partition)
+
+ cmd1 = shlex.split(f'partclone.{fstype} -I -C --clone -s {padev} -O -')
+ cmd2 = shlex.split(f'lzop -1 -fo {image_path}')
+
+ logfile = open('/tmp/command.log', 'wb', 0)
+
+ p1 = Popen(cmd1, stdout=PIPE, stderr=logfile)
+ p2 = Popen(cmd2, stdin=p1.stdout)
+ p1.stdout.close()
+
+ try:
+ retdata = p2.communicate()
+ except OSError as e:
+ logging.error('Unexpected error when running partclone and lzop commands')
+ finally:
+ logfile.close()
+ p2.terminate()
+ p1.poll()
+
+ logging.info(f'partclone process exited with code {p1.returncode}')
+ logging.info(f'lzop process exited with code {p2.returncode}')
+
+ if ogExtendFs(disk, partition) != 0:
+ logging.warn('Error extending filesystem after image creation')
+
+ image_info = ogGetImageInfo(image_path)
+ except:
+ logging.error('Exception when running "image create" subprocess')
+ raise ValueError('Error: Incorrect command value')
- os.remove('/tmp/image.info')
+ self._write_md5_file(f'/opt/opengnsys/images/{name}.img')
self._restartBrowser(self._url)