Disable the check of the release notes
[osm/RO.git] / NG-RO / osm_ng_ro / ro_main.py
index 2a2c076..51c22bf 100644 (file)
@@ -35,6 +35,7 @@ from osm_common.fsbase import FsException
 from osm_common.msgbase import MsgException
 from osm_ng_ro import version as ro_version, version_date as ro_version_date
 import osm_ng_ro.html_out as html
+from osm_ng_ro.monitor import start_monitoring, stop_monitoring
 from osm_ng_ro.ns import Ns, NsException
 from osm_ng_ro.validation import ValidationError
 from osm_ng_ro.vim_admin import VimAdminThread
@@ -83,6 +84,30 @@ valid_url_methods = {
     },
     "ns": {
         "v1": {
+            "rebuild": {
+                "METHODS": ("POST",),
+                "ROLE_PERMISSION": "rebuild:",
+                "<ID>": {
+                    "METHODS": ("POST",),
+                    "ROLE_PERMISSION": "rebuild:id:",
+                },
+            },
+            "start": {
+                "METHODS": ("POST",),
+                "ROLE_PERMISSION": "start:",
+                "<ID>": {
+                    "METHODS": ("POST",),
+                    "ROLE_PERMISSION": "start:id:",
+                },
+            },
+            "stop": {
+                "METHODS": ("POST",),
+                "ROLE_PERMISSION": "stop:",
+                "<ID>": {
+                    "METHODS": ("POST",),
+                    "ROLE_PERMISSION": "stop:id:",
+                },
+            },
             "deploy": {
                 "METHODS": ("GET",),
                 "ROLE_PERMISSION": "deploy:",
@@ -109,6 +134,26 @@ valid_url_methods = {
                     },
                 },
             },
+            "migrate": {
+                "<ID>": {
+                    "METHODS": ("POST"),
+                    "ROLE_PERMISSION": "migrate:id:",
+                    "<ID>": {
+                        "METHODS": ("GET",),
+                        "ROLE_PERMISSION": "migrate:id:id:",
+                    },
+                },
+            },
+            "verticalscale": {
+                "<ID>": {
+                    "METHODS": ("POST"),
+                    "ROLE_PERMISSION": "verticalscale:id:",
+                    "<ID>": {
+                        "METHODS": ("GET",),
+                        "ROLE_PERMISSION": "verticalscale:id:id:",
+                    },
+                },
+            },
         }
     },
 }
@@ -160,11 +205,17 @@ class Server(object):
             "deploy:id:delete": self.ns.delete,
             "deploy:id:id:get": self.ns.status,
             "deploy:id:id:cancel:post": self.ns.cancel,
+            "rebuild:id:post": self.ns.rebuild_start_stop,
+            "start:id:post": self.ns.rebuild_start_stop,
+            "stop:id:post": self.ns.rebuild_start_stop,
             "recreate:id:post": self.ns.recreate,
             "recreate:id:id:get": self.ns.recreate_status,
+            "migrate:id:post": self.ns.migrate,
+            "verticalscale:id:post": self.ns.verticalscale,
         }
 
     def _format_in(self, kwargs):
+        error_text = ""
         try:
             indata = None
 
@@ -178,9 +229,7 @@ class Server(object):
                         cherrypy.request.headers.pop("Content-File-MD5", None)
                     elif "application/yaml" in cherrypy.request.headers["Content-Type"]:
                         error_text = "Invalid yaml format "
-                        indata = yaml.load(
-                            cherrypy.request.body, Loader=yaml.SafeLoader
-                        )
+                        indata = yaml.safe_load(cherrypy.request.body)
                         cherrypy.request.headers.pop("Content-File-MD5", None)
                     elif (
                         "application/binary" in cherrypy.request.headers["Content-Type"]
@@ -205,21 +254,19 @@ class Server(object):
                             indata = filecontent.file  # .read()
 
                             if filecontent.content_type.value:
-                                cherrypy.request.headers[
-                                    "Content-Type"
-                                ] = filecontent.content_type.value
+                                cherrypy.request.headers["Content-Type"] = (
+                                    filecontent.content_type.value
+                                )
                     else:
                         # raise cherrypy.HTTPError(HTTPStatus.Not_Acceptable,
                         #                          "Only 'Content-Type' of type 'application/json' or
                         # 'application/yaml' for input format are available")
                         error_text = "Invalid yaml format "
-                        indata = yaml.load(
-                            cherrypy.request.body, Loader=yaml.SafeLoader
-                        )
+                        indata = yaml.safe_load(cherrypy.request.body)
                         cherrypy.request.headers.pop("Content-File-MD5", None)
                 else:
                     error_text = "Invalid yaml format "
-                    indata = yaml.load(cherrypy.request.body, Loader=yaml.SafeLoader)
+                    indata = yaml.safe_load(cherrypy.request.body)
                     cherrypy.request.headers.pop("Content-File-MD5", None)
 
             if not indata:
@@ -235,9 +282,11 @@ class Server(object):
                         kwargs[k] = None
                     elif format_yaml:
                         try:
-                            kwargs[k] = yaml.load(v, Loader=yaml.SafeLoader)
-                        except Exception:
-                            pass
+                            kwargs[k] = yaml.safe_load(v)
+                        except Exception as yaml_error:
+                            logging.exception(
+                                f"{yaml_error} occured while parsing the yaml"
+                            )
                     elif (
                         k.endswith(".gt")
                         or k.endswith(".lt")
@@ -249,8 +298,10 @@ class Server(object):
                         except Exception:
                             try:
                                 kwargs[k] = float(v)
-                            except Exception:
-                                pass
+                            except Exception as keyword_error:
+                                logging.exception(
+                                    f"{keyword_error} occured while getting the keyword arguments"
+                                )
                     elif v.find(",") > 0:
                         kwargs[k] = v.split(",")
                 elif isinstance(v, (list, tuple)):
@@ -259,9 +310,11 @@ class Server(object):
                             v[index] = None
                         elif format_yaml:
                             try:
-                                v[index] = yaml.load(v[index], Loader=yaml.SafeLoader)
-                            except Exception:
-                                pass
+                                v[index] = yaml.safe_load(v[index])
+                            except Exception as error:
+                                logging.exception(
+                                    f"{error} occured while parsing the yaml"
+                                )
 
             return indata
         except (ValueError, yaml.YAMLError) as exc:
@@ -303,9 +356,9 @@ class Server(object):
 
         if accept:
             if "application/json" in accept:
-                cherrypy.response.headers[
-                    "Content-Type"
-                ] = "application/json; charset=utf-8"
+                cherrypy.response.headers["Content-Type"] = (
+                    "application/json; charset=utf-8"
+                )
                 a = json.dumps(data, indent=4) + "\n"
 
                 return a.encode("utf8")
@@ -486,15 +539,15 @@ class Server(object):
             return ",".join(folders) + " folders deleted\n"
         elif args and args[0] == "login":
             if not cherrypy.request.headers.get("Authorization"):
-                cherrypy.response.headers[
-                    "WWW-Authenticate"
-                ] = 'Basic realm="Access to OSM site", charset="UTF-8"'
+                cherrypy.response.headers["WWW-Authenticate"] = (
+                    'Basic realm="Access to OSM site", charset="UTF-8"'
+                )
                 cherrypy.response.status = HTTPStatus.UNAUTHORIZED.value
         elif args and args[0] == "login2":
             if not cherrypy.request.headers.get("Authorization"):
-                cherrypy.response.headers[
-                    "WWW-Authenticate"
-                ] = 'Bearer realm="Access to OSM site"'
+                cherrypy.response.headers["WWW-Authenticate"] = (
+                    'Bearer realm="Access to OSM site"'
+                )
                 cherrypy.response.status = HTTPStatus.UNAUTHORIZED.value
         elif args and args[0] == "sleep":
             sleep_time = 5
@@ -515,18 +568,14 @@ class Server(object):
 
             try:
                 if cherrypy.request.method == "POST":
-                    to_send = yaml.load(cherrypy.request.body, Loader=yaml.SafeLoader)
+                    to_send = yaml.safe_load(cherrypy.request.body)
                     for k, v in to_send.items():
                         self.ns.msg.write(main_topic, k, v)
                         return_text += "  {}: {}\n".format(k, v)
                 elif cherrypy.request.method == "GET":
                     for k, v in kwargs.items():
-                        self.ns.msg.write(
-                            main_topic, k, yaml.load(v, Loader=yaml.SafeLoader)
-                        )
-                        return_text += "  {}: {}\n".format(
-                            k, yaml.load(v, Loader=yaml.SafeLoader)
-                        )
+                        self.ns.msg.write(main_topic, k, yaml.safe_load(v))
+                        return_text += "  {}: {}\n".format(k, yaml.safe_load(v))
             except Exception as e:
                 return_text += "Error: " + str(e)
 
@@ -638,7 +687,7 @@ class Server(object):
         **kwargs,
     ):
         token_info = None
-        outdata = None
+        outdata = {}
         _format = None
         method = "DONE"
         rollback = []
@@ -694,9 +743,11 @@ class Server(object):
             cherrypy.response.status = (
                 HTTPStatus.ACCEPTED.value
                 if not done
-                else HTTPStatus.OK.value
-                if outdata is not None
-                else HTTPStatus.NO_CONTENT.value
+                else (
+                    HTTPStatus.OK.value
+                    if outdata is not None
+                    else HTTPStatus.NO_CONTENT.value
+                )
             )
 
             return self._format_out(outdata, token_info, _format)
@@ -717,9 +768,9 @@ class Server(object):
                 http_code_name = e.http_code.name
                 cherrypy.log("Exception {}".format(e))
             else:
-                http_code_value = (
-                    cherrypy.response.status
-                ) = HTTPStatus.BAD_REQUEST.value  # INTERNAL_SERVER_ERROR
+                http_code_value = cherrypy.response.status = (
+                    HTTPStatus.BAD_REQUEST.value
+                )  # INTERNAL_SERVER_ERROR
                 cherrypy.log("CRITICAL: Exception {}".format(e), traceback=True)
                 http_code_name = HTTPStatus.BAD_REQUEST.name
 
@@ -805,7 +856,7 @@ def _start_service():
             elif k1 == "tools":
                 # update [/] configuration
                 engine_config["/"]["tools." + k2.replace("_", ".")] = yaml.safe_load(v)
-            elif k1 in ("message", "database", "storage", "authentication"):
+            elif k1 in ("message", "database", "storage", "authentication", "period"):
                 engine_config[k1][k2] = yaml.safe_load(v)
 
         except Exception as e:
@@ -882,6 +933,8 @@ def _start_service():
     # # start subscriptions thread:
     vim_admin_thread = VimAdminThread(config=engine_config, engine=ro_server.ns)
     vim_admin_thread.start()
+    start_monitoring(config=engine_config)
+
     # # Do not capture except SubscriptionException
 
     # backend = engine_config["authentication"]["backend"]
@@ -899,7 +952,7 @@ def _stop_service():
     # terminate vim_admin_thread
     if vim_admin_thread:
         vim_admin_thread.terminate()
-
+    stop_monitoring()
     vim_admin_thread = None
     cherrypy.tree.apps["/ro"].root.ns.stop()
     cherrypy.log.error("Stopping osm_ng_ro")
@@ -941,7 +994,7 @@ if __name__ == "__main__":
             elif o in ("-c", "--config"):
                 config_file = a
             else:
-                assert False, "Unhandled option"
+                raise ValueError("Unhandled option")
 
         if config_file:
             if not path.isfile(config_file):