From 36f3c329c2df0e78f2f5da933d9729a872fb2a11 Mon Sep 17 00:00:00 2001
From: Viacheslav Hletenko <v.gletenko@vyos.io>
Date: Tue, 21 Nov 2023 10:17:53 +0000
Subject: T5767: HTTPS API add reboot and poweroff endpoints

Add ability to reboot and poweroff the system via API

curl -k --location --request POST 'https://vyos/reboot' \
  --form data='{"op": "reboot", "path": ["now"]}' \
  --form key='apikey'

curl -k --location --request POST 'https://vyos/poweroff' \
  --form data='{"op": "poweroff", "path": ["now"]}' \
  --form key='apikey'
---
 src/services/vyos-http-api-server | 66 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 66 insertions(+)

(limited to 'src/services')

diff --git a/src/services/vyos-http-api-server b/src/services/vyos-http-api-server
index daee24257..85d7884b6 100755
--- a/src/services/vyos-http-api-server
+++ b/src/services/vyos-http-api-server
@@ -223,6 +223,19 @@ class ShowModel(ApiModel):
             }
         }
 
+class RebootModel(ApiModel):
+    op: StrictStr
+    path: List[StrictStr]
+
+    class Config:
+        schema_extra = {
+            "example": {
+                "key": "id_key",
+                "op": "reboot",
+                "path": ["op", "mode", "path"],
+            }
+        }
+
 class ResetModel(ApiModel):
     op: StrictStr
     path: List[StrictStr]
@@ -236,6 +249,19 @@ class ResetModel(ApiModel):
             }
         }
 
+class PoweroffModel(ApiModel):
+    op: StrictStr
+    path: List[StrictStr]
+
+    class Config:
+        schema_extra = {
+            "example": {
+                "key": "id_key",
+                "op": "poweroff",
+                "path": ["op", "mode", "path"],
+            }
+        }
+
 
 class Success(BaseModel):
     success: bool
@@ -713,6 +739,26 @@ def show_op(data: ShowModel):
 
     return success(res)
 
+@app.post('/reboot')
+def reboot_op(data: RebootModel):
+    session = app.state.vyos_session
+
+    op = data.op
+    path = data.path
+
+    try:
+        if op == 'reboot':
+            res = session.reboot(path)
+        else:
+            return error(400, f"'{op}' is not a valid operation")
+    except ConfigSessionError as e:
+        return error(400, str(e))
+    except Exception as e:
+        logger.critical(traceback.format_exc())
+        return error(500, "An internal error occured. Check the logs for details.")
+
+    return success(res)
+
 @app.post('/reset')
 def reset_op(data: ResetModel):
     session = app.state.vyos_session
@@ -733,6 +779,26 @@ def reset_op(data: ResetModel):
 
     return success(res)
 
+@app.post('/poweroff')
+def poweroff_op(data: PoweroffModel):
+    session = app.state.vyos_session
+
+    op = data.op
+    path = data.path
+
+    try:
+        if op == 'poweroff':
+            res = session.poweroff(path)
+        else:
+            return error(400, f"'{op}' is not a valid operation")
+    except ConfigSessionError as e:
+        return error(400, str(e))
+    except Exception as e:
+        logger.critical(traceback.format_exc())
+        return error(500, "An internal error occured. Check the logs for details.")
+
+    return success(res)
+
 
 ###
 # GraphQL integration
-- 
cgit v1.2.3