summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlejandro Sirgo Rica <asirgo@soleta.eu>2024-11-26 11:50:52 +0100
committerAlejandro Sirgo Rica <asirgo@soleta.eu>2024-11-27 13:53:19 +0100
commite4be5c34eb71da9a705bc62fdfcfe6d763022747 (patch)
tree70883c72fd8baa07ca225e5a7fee173158283bd2
parenta36c4daa23d32aeee9539374aa591152ef2c914b (diff)
src: add support for direct command executionv1.3.2-25
Update live shell run mode for the new REST API interface. Evaluate the "inline" field to diferentiate between execution of script in /opt/opengnsys/shell/ and a cmd execution. Remove usage of echo argument of the API REST. Update Windows and Linux mode for direct command execution. Set OutputEncoding environment variable to 'utf-8' in Windows to unify the encoding of stdout for the invoked programs. Decode stdout to utf-8-sig to remove potential BOM. While at this, remove strange legacy ;|\n\r terminator.
-rw-r--r--src/linux/ogOperations.py30
-rw-r--r--src/live/ogOperations.py45
-rw-r--r--src/ogRest.py16
-rw-r--r--src/restRequest.py8
-rw-r--r--src/windows/ogOperations.py35
5 files changed, 72 insertions, 62 deletions
diff --git a/src/linux/ogOperations.py b/src/linux/ogOperations.py
index bbce41a..5813cf7 100644
--- a/src/linux/ogOperations.py
+++ b/src/linux/ogOperations.py
@@ -7,9 +7,9 @@
# (at your option) any later version.
import os
+import shlex
import psutil
import subprocess
-from subprocess import CalledProcessError
from src.log import OgError
from src.ogRest import ThreadState
@@ -30,20 +30,22 @@ class OgLinuxOperations:
def shellrun(self, request, ogRest):
cmd = request.getrun()
+ is_inline = request.get_inline()
+
+ if not is_inline:
+ raise OgError("Only inline mode is supported on Linux")
+
try:
- result = subprocess.run(cmd,
- shell=True,
- stdin=subprocess.DEVNULL,
- capture_output=True,
- text=True,
- check=True)
- except CalledProcessError as error:
- if error.stderr:
- return error.stderr
- if error.stdout:
- return error.stdout
- return "{Non zero exit code and empty output}"
- return result.stdout
+ ogRest.proc = subprocess.Popen(
+ cmd,
+ stdout=subprocess.PIPE,
+ shell=True)
+ (output, error) = ogRest.proc.communicate()
+ except (OSError, subprocess.SubprocessError) as e:
+ raise OgError(f'Error when running "shell run" subprocess: {e}') from e
+
+ output = output.decode('utf-8-sig', errors='replace')
+ return (ogRest.proc.returncode, cmd, output)
def session(self, request, ogRest):
raise OgError('Function not implemented')
diff --git a/src/live/ogOperations.py b/src/live/ogOperations.py
index ef18e33..ee83c4a 100644
--- a/src/live/ogOperations.py
+++ b/src/live/ogOperations.py
@@ -38,8 +38,6 @@ from src.utils.hw_inventory import get_hardware_inventory, legacy_list_hardware_
from src.log import OgError
-OG_SHELL = '/bin/bash'
-
class OgLiveOperations:
def __init__(self, config):
self._url = config['opengnsys']['url']
@@ -381,32 +379,38 @@ class OgLiveOperations:
def shellrun(self, request, ogRest):
cmd = request.getrun()
- cmds = cmd.split(";|\n\r")
+ is_inline = request.get_inline()
self._restartBrowser(self._url_log)
- shell_path = '/opt/opengnsys/shell/'
+ if is_inline:
+ cmds = cmd
+ else:
+ cmds = shlex.split(cmd)
+ shell_path = '/opt/opengnsys/shell/'
- restricted_mode = False
+ try:
+ shell_path_files = os.listdir(shell_path)
+ except OSError as e:
+ raise OgError(f'Error accessing {shell_path}: {e}') from e
- for file_name in os.listdir(shell_path):
- file_path = os.path.join(shell_path, file_name)
+ for file_name in shell_path_files:
+ file_path = os.path.join(shell_path, file_name)
- if cmds[0] == file_name:
- cmds[0] = file_path
- restricted_mode = True
- break
+ if cmds[0] == file_name:
+ cmds[0] = file_path
+ cmd = " ".join(cmds)
+ break
+ else:
+ raise OgError(f'Script {cmds[0]} not found in {shell_path}')
try:
- if restricted_mode:
- ogRest.proc = subprocess.Popen(cmds, stdout=subprocess.PIPE)
- else:
- ogRest.proc = subprocess.Popen(cmds,
- stdout=subprocess.PIPE,
- shell=True,
- executable=OG_SHELL)
+ ogRest.proc = subprocess.Popen(
+ cmds,
+ stdout=subprocess.PIPE,
+ shell=is_inline)
(output, error) = ogRest.proc.communicate()
- except OSError as e:
+ except (OSError, subprocess.SubprocessError) as e:
raise OgError(f'Error when running "shell run" subprocess: {e}') from e
if ogRest.proc.returncode != 0:
@@ -416,7 +420,8 @@ class OgLiveOperations:
self.refresh(ogRest)
- return (ogRest.proc.returncode, " ".join(cmds), output.decode('utf-8'))
+ output = output.decode('utf-8-sig', errors='replace')
+ return (ogRest.proc.returncode, cmd, output)
def session(self, request, ogRest):
disk = request.getDisk()
diff --git a/src/ogRest.py b/src/ogRest.py
index 5731350..a30c494 100644
--- a/src/ogRest.py
+++ b/src/ogRest.py
@@ -97,16 +97,12 @@ class ogThread():
ogRest.send_internal_server_error(client, exc=e)
return
- if request.getEcho():
- json_body = jsonBody()
- json_body.add_element('cmd', cmd)
- json_body.add_element('out', shellout)
- json_body.add_element('retcode', retcode)
- response = restResponse(ogResponses.OK, json_body, seq=client.seq)
- client.send(response.get())
- else:
- response = restResponse(ogResponses.OK, seq=client.seq)
- client.send(response.get())
+ json_body = jsonBody()
+ json_body.add_element('cmd', cmd)
+ json_body.add_element('out', shellout)
+ json_body.add_element('retcode', retcode)
+ response = restResponse(ogResponses.OK, json_body, seq=client.seq)
+ client.send(response.get())
ogRest.state = ThreadState.IDLE
diff --git a/src/restRequest.py b/src/restRequest.py
index 3098c1a..dc0e656 100644
--- a/src/restRequest.py
+++ b/src/restRequest.py
@@ -33,7 +33,7 @@ class restRequest:
self.type = None
self.profile = None
self.id = None
- self.echo = None
+ self.inline = None
self.code = None
self.seq = None
self.backup = None
@@ -72,7 +72,7 @@ class restRequest:
if "run" in json_param:
self.run = json_param["run"]
try:
- self.echo = json_param["echo"]
+ self.inline = json_param["inline"]
except:
pass
@@ -160,8 +160,8 @@ class restRequest:
def getId(self):
return self.id
- def getEcho(self):
- return self.echo
+ def get_inline(self):
+ return self.inline
def getCode(self):
return self.code
diff --git a/src/windows/ogOperations.py b/src/windows/ogOperations.py
index 23e962c..9a80b0a 100644
--- a/src/windows/ogOperations.py
+++ b/src/windows/ogOperations.py
@@ -7,10 +7,10 @@
# (at your option) any later version.
import os
+import locale
import ctypes
import psutil
import subprocess
-from subprocess import CalledProcessError
import multiprocessing as mp
from multiprocessing import Process, freeze_support
from src.log import OgError
@@ -84,20 +84,27 @@ class OgWindowsOperations:
def shellrun(self, request, ogRest):
cmd = request.getrun()
+ is_inline = request.get_inline()
+
+ if not is_inline:
+ raise OgError("Only inline mode is supported on Windows")
+
+ env = os.environ.copy()
+ env['OutputEncoding'] = 'utf8'
+
try:
- result = subprocess.run(cmd,
- shell=True,
- stdin=subprocess.DEVNULL,
- capture_output=True,
- text=True,
- check=True)
- except CalledProcessError as error:
- if error.stderr:
- return error.stderr
- if error.stdout:
- return error.stdout
- return "{Non zero exit code and empty output}"
- return (result.returncode, cmd, result.stdout)
+ ogRest.proc = subprocess.Popen(
+ cmd,
+ stdout=subprocess.PIPE,
+ shell=True,
+ env=env,
+ )
+ output, error = ogRest.proc.communicate()
+ except (OSError, subprocess.SubprocessError) as e:
+ raise OgError(f'Error when running "shell run" subprocess: {e}') from e
+
+ output = output.decode('utf-8-sig', errors='replace')
+ return (ogRest.proc.returncode, cmd, output)
def session(self, request, ogRest):
raise OgError('Function not implemented')