AETHER-3321 Refactor configuration code in enodebd

AETHER-3520 Make enodebd containerized
AETHER-3504 Geomap of Grafana with enodeb coordinate information

Change-Id: Ie425254fa1a8b286004d2bcd366cf6c7057c925c
diff --git a/state_machines/enb_acs_states.py b/state_machines/enb_acs_states.py
index bfd0824..071cd49 100644
--- a/state_machines/enb_acs_states.py
+++ b/state_machines/enb_acs_states.py
@@ -136,16 +136,25 @@
         """
         if not isinstance(message, models.Inform):
             return AcsReadMsgResult(False, None)
+
         process_inform_message(
             message, self.acs.data_model,
             self.acs.device_cfg,
         )
+
+        # Switch enodeb status to connected
+        metrics.set_enb_status(
+            self.acs.device_cfg.get_parameter("Serial number"),
+            status="connected"
+        )
+
         if does_inform_have_event(message, '1 BOOT'):
             return AcsReadMsgResult(True, self.boot_transition)
         return AcsReadMsgResult(True, None)
 
     def get_msg(self, message: Any) -> AcsMsgAndTransition:
         """ Reply with InformResponse """
+        
         response = models.InformResponse()
         # Set maxEnvelopes to 1, as per TR-069 spec
         response.MaxEnvelopes = 1
@@ -962,16 +971,23 @@
                     )
             self._mark_as_configured()
 
-            metrics.STAT_ENODEB_LAST_CONFIGURED.labels(
-                serial_number=self.acs.device_cfg.get_parameter("Serial number"),
-                ip_address=self.acs.device_cfg.get_parameter("ip_address"),
-                gps_lat=self.acs.device_cfg.get_parameter("GPS lat"),
-                gps_lon=self.acs.device_cfg.get_parameter("GPS long")
-            ).set(int(time.time()))
+            metrics.set_enb_last_configured_time(
+                self.acs.device_cfg.get_parameter("Serial number"),
+                self.acs.device_cfg.get_parameter("ip_address"),
+                int(time.time())
+            )
+
+            # Switch enodeb status to configured
+            metrics.set_enb_status(
+                self.acs.device_cfg.get_parameter("Serial number"),
+                status="configured"
+            )
 
             if not self.acs.are_invasive_changes_applied:
                 return AcsReadMsgResult(True, self.apply_invasive_transition)
+
             return AcsReadMsgResult(True, self.done_transition)
+
         elif type(message) == models.Fault:
             logger.error(
                 'Received Fault in response to SetParameterValues, '
@@ -1046,6 +1062,12 @@
         return AcsReadMsgResult(False, None)
 
     def get_msg(self, message: Any) -> AcsMsgAndTransition:
+        # Switch enodeb status to disconnected
+        metrics.set_enb_status(
+            self.acs.device_cfg.get_parameter("Serial number"),
+            status="disconnected"
+        )
+
         request = models.DummyInput()
         return AcsMsgAndTransition(request, None)
 
@@ -1274,20 +1296,24 @@
 
     def get_msg(self, message: Any) -> AcsMsgAndTransition:
 
-        print("ACS Device CFG")
-        print(self.acs.device_cfg._param_to_value)
+        # Switch enodeb status to firmware upgrading
+        metrics.set_enb_status(
+            self.acs.device_cfg.get_parameter("Serial number"),
+            status="firmware_upgrading"
+        )
 
         request = models.Download()
         request.CommandKey = "20220206215200"
         request.FileType = "1 Firmware Upgrade Image"
-        request.URL = "http://10.128.250.131/firmware/Qproject_TEST3918_2102241222.ffw"
+        request.URL = "http://10.128.250.131/firmware/Qproject_RC3923_2202151120.ffw"
         request.Username = ""
         request.Password = ""
-        request.FileSize = 57208579
-        request.TargetFileName = "Qproject_TEST3918_2102241222.ffw"
+        request.FileSize = 57399275
+        request.TargetFileName = "Qproject_RC3923_2202151120.ffw"
         request.DelaySeconds = 0
         request.SuccessURL = ""
         request.FailureURL = ""
+
         return AcsMsgAndTransition(request, self.done_transition)
 
     def state_description(self) -> str:
@@ -1371,6 +1397,77 @@
     def state_description(self) -> str:
         return "Wait DownloadResponse message"
 
+class CheckStatusState(EnodebAcsState):
+    """
+    Sent a request to enodeb to get the basic status from device
+    """
+
+    def __init__(
+        self,
+        acs: EnodebAcsStateMachine,
+        when_done: str,
+    ):
+        super().__init__()
+        self.acs = acs
+        self.done_transition = when_done
+
+    def get_msg(self, message: Any) -> AcsMsgAndTransition:
+        """
+        Send with GetParameterValuesRequest
+        """
+
+        self.PARAMETERS = [
+            ParameterName.RF_TX_STATUS,
+            ParameterName.GPS_STATUS,
+            ParameterName.GPS_LAT,
+            ParameterName.GPS_LONG,
+        ]
+
+        request = models.GetParameterValues()
+        request.ParameterNames = models.ParameterNames()
+        request.ParameterNames.arrayType = 'xsd:string[1]'
+        request.ParameterNames.string = []
+
+        for name in self.PARAMETERS:
+            if self.acs.data_model.is_parameter_present(name):
+                path = self.acs.data_model.get_parameter(name).path
+                request.ParameterNames.string.append(path)
+
+        request.ParameterNames.arrayType = \
+            'xsd:string[%d]' % len(request.ParameterNames.string)
+
+        return AcsMsgAndTransition(request, self.done_transition)
+
+    def read_msg(self, message: Any) -> AcsReadMsgResult:
+
+        if not isinstance(message, models.GetParameterValuesResponse):
+            return AcsReadMsgResult(msg_handled=False, next_state=when_done)
+        
+        name_to_val = parse_get_parameter_values_response(self.acs.data_model, message, )
+        logger.info("CheckStatusState: %s", str(name_to_val))
+
+        # Call set_enb_gps_status to update the parameter in prometheus api
+        metrics.set_enb_gps_status(
+            self.acs.device_cfg.get_parameter("Serial number"),
+            name_to_val["GPS lat"], name_to_val["GPS long"],
+            name_to_val["gps_status"]
+        )
+
+        # Call set_enb_op_status to update the parameter in prometheus api
+        metrics.set_enb_op_status(
+            self.acs.device_cfg.get_parameter("Serial number"),
+            name_to_val["Opstate"]
+        )
+
+        # Sleep 1 minute and check status again
+        time.sleep(60)
+
+        return AcsReadMsgResult(msg_handled=True, next_state=self.done_transition)
+
+    def state_description(self) -> str:
+        return 'Getting'
+
+
 class ErrorState(EnodebAcsState):
     """
     The eNB handler will enter this state when an unhandled Fault is received.