From fe40f9c5d66916cad4cee8d5b2d9e172fc1c0477 Mon Sep 17 00:00:00 2001 From: Alejandro Sirgo Rica Date: Thu, 8 Aug 2024 10:26:06 +0200 Subject: src: add POST cache/fetch method Add API REST method to fetch an image. Consolidate image fetch loging for cache/fetch and image/restore. Resquest payload structure: { 'image': 'linux.img' 'type': 'TIPTORRENT' 'repository': '12.141.10.2' } The client will try to fetch'image' from 'repository' into cache. Resquest response structure: { 'cache': [ {'name': 'windows.img', 'size': 2432370213, checksum: '5d4dcc677bc19f40a647d0002f4ade90'}, {'name': 'linux.img', 'size': 243234534213, checksum: '3eb22f888f88a55ad954f55644e1192e'} ] } --- src/linux/ogOperations.py | 3 +++ src/live/ogOperations.py | 55 ++++++++++++++++++++++++++++++++------------- src/ogRest.py | 18 +++++++++++++++ src/restRequest.py | 3 +++ src/virtual/ogOperations.py | 3 +++ src/windows/ogOperations.py | 3 +++ 6 files changed, 69 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/linux/ogOperations.py b/src/linux/ogOperations.py index 7686956..63afd12 100644 --- a/src/linux/ogOperations.py +++ b/src/linux/ogOperations.py @@ -58,6 +58,9 @@ class OgLinuxOperations: def cache_delete(self, request, ogRest): raise NotImplementedError + def cache_fetch(self, request, ogRest): + raise NotImplementedError + def refresh(self, ogRest): return {"status": "LINUX"} diff --git a/src/live/ogOperations.py b/src/live/ogOperations.py index 9cc5b97..b22d8b2 100644 --- a/src/live/ogOperations.py +++ b/src/live/ogOperations.py @@ -178,14 +178,21 @@ class OgLiveOperations: return 0 - def _copy_image_to_cache(self, image_name): + def _fetch_image_unicast(self, repo, image_name): """ Copies /opt/opengnsys/image/{image_name} into /opt/opengnsys/cache/opt/opengnsys/images/ Implies a unicast transfer. Does not use tiptorrent. """ + if not get_cache_dev_path(): + raise OgError('No cache partition is mounted') + dst = f'{OG_CACHE_IMAGE_PATH}{image_name}.img' + + if (os.path.exists(dst) and tip_check_csum(repo, image_name)): + return + try: if os.path.exists(dst): os.unlink(dst) @@ -203,26 +210,19 @@ class OgLiveOperations: except (OSError, OgError) as e: raise OgError(f'Error copying image {image_name} to cache. Reported: {e}') from e + if (not os.path.exists(dst)): + raise OgError(f'could not find {dst} in cache') + if (not tip_check_csum(repo, image_name)): + raise OgError(f'Failed to validate checksum for {image_name}.img') + def _restore_image_unicast(self, repo, name, devpath, cache=False): if ogChangeRepo(repo, smb_user=self._smb_user, smb_pass=self._smb_pass) != 0: self._restartBrowser(self._url) raise OgError(f'Cannot change repository to {repo}') if cache: - if not get_cache_dev_path(): - raise OgError('No cache partition is mounted') - - fetch = False - image_path = f'{OG_CACHE_IMAGE_PATH}{name}.img' - if (not os.path.exists(image_path) or not tip_check_csum(repo, name)): - self._copy_image_to_cache(name) - fetch = True - - if fetch: - if (not os.path.exists(image_path)): - raise OgError(f'could not find {image_path} in cache') - if (not tip_check_csum(repo, name)): - raise OgError(f'Failed to validate checksum for {name}.img') + self._fetch_image_unicast(repo, name) + image_path = f'{OG_CACHE_IMAGE_PATH}{image_name}.img' else: if os.access(f'/opt/opengnsys/images', os.R_OK) == False: raise OgError('Cannot access /opt/opengnsys/images in read mode, check permissions') @@ -232,7 +232,7 @@ class OgLiveOperations: self._restore_image(image_path, devpath) - def _restore_image_tiptorrent(self, repo, name, devpath): + def _fetch_image_tiptorrent(self, repo, name): if not get_cache_dev_path(): raise OgError('No cache partition is mounted') @@ -251,7 +251,10 @@ class OgLiveOperations: raise OgError(f'could not find {image_path} in cache') if (not tip_check_csum(repo, name)): raise OgError(f'Failed to validate checksum for {name}.img') + return image_path + def _restore_image_tiptorrent(self, repo, name, devpath): + image_path = self._fetch_image_tiptorrent(repo, name) self._restore_image(image_path, devpath) def _restore_image(self, image_path, devpath): @@ -677,6 +680,26 @@ class OgLiveOperations: logging.info('Delete file from cache request OK') return result + def cache_fetch(self, request, ogRest): + image = request.getImages() + repo = request.getRepo() + ctype = request.getType() + + logging.info(f'Request to cache image {image}.img via {ctype} from {repo}') + + if ctype == 'UNICAST': + self._fetch_image_unicast(repo, image) + elif ctype == 'TIPTORRENT': + self._fetch_image_tiptorrent(repo, image) + else: + raise OgError(f'Invalid image fetch type {ctype}') + + logging.info('Cache fetch command OK') + + result = {'cache': self._get_cache_contents()} + + return result + def refresh(self, ogRest): self._restartBrowser(self._url_log) diff --git a/src/ogRest.py b/src/ogRest.py index 4a734f7..fc46e8d 100644 --- a/src/ogRest.py +++ b/src/ogRest.py @@ -228,6 +228,19 @@ class ogThread(): client.send(response.get()) ogRest.state = ThreadState.IDLE + def cache_fetch(client, request, ogRest): + try: + out = ogRest.operations.cache_fetch(request, ogRest) + except Exception as e: + ogRest.send_internal_server_error(client, exc=e) + return + + json_body = jsonBody(out) + + response = restResponse(ogResponses.OK, json_body, seq=client.seq) + client.send(response.get()) + ogRest.state = ThreadState.IDLE + def refresh(client, ogRest): try: out = ogRest.operations.refresh(ogRest) @@ -343,6 +356,8 @@ class ogRest(): self.process_imagecreate(client, request) elif ("cache/delete" in URI): self.process_cache_delete(client, request) + elif ("cache/fetch" in URI): + self.process_cache_fetch(client, request) else: logging.warn('Unsupported request: %s', URI[:ogRest.LOG_LENGTH]) @@ -448,5 +463,8 @@ class ogRest(): def process_cache_delete(self, client, request): threading.Thread(target=ogThread.cache_delete, args=(client, request, self,)).start() + def process_cache_fetch(self, client, request): + threading.Thread(target=ogThread.cache_fetch, args=(client, request, self,)).start() + def process_refresh(self, client): threading.Thread(target=ogThread.refresh, args=(client, self,)).start() diff --git a/src/restRequest.py b/src/restRequest.py index fdfe633..3098c1a 100644 --- a/src/restRequest.py +++ b/src/restRequest.py @@ -79,6 +79,9 @@ class restRequest: if "images" in json_param: self.images = json_param["images"] + if "image" in json_param: + self.images = json_param["image"] + if "disk" in json_param: self.disk = json_param["disk"] diff --git a/src/virtual/ogOperations.py b/src/virtual/ogOperations.py index 34ba9fd..c17bfb4 100644 --- a/src/virtual/ogOperations.py +++ b/src/virtual/ogOperations.py @@ -469,6 +469,9 @@ class OgVirtualOperations: def cache_delete(self, request, ogRest): raise NotImplementedError + def cache_fetch(self, request, ogRest): + raise NotImplementedError + def software(self, request, path, ogRest): DPKG_PATH = '/var/lib/dpkg/status' diff --git a/src/windows/ogOperations.py b/src/windows/ogOperations.py index d0230eb..45413ba 100644 --- a/src/windows/ogOperations.py +++ b/src/windows/ogOperations.py @@ -113,6 +113,9 @@ class OgWindowsOperations: def cache_delete(self, request, ogRest): raise NotImplementedError + def cache_fetch(self, request, ogRest): + raise NotImplementedError + def refresh(self, ogRest): return {"status": "WIN"} -- cgit v1.2.3-18-g5258