Add a data structure for the presentation of incidents
reported by the node-status data collector. It contains
all the information the maintenance daemons associates
with an incident, including jobs submitted. Again, the
information is stored in the configuration.

Signed-off-by: Klaus Aehlig <[email protected]>
---
 lib/objects.py                           |  2 +-
 src/Ganeti/Objects/Maintenance.hs        | 51 ++++++++++++++++++++++++++++++++
 src/Ganeti/WConfd/ConfigModifications.hs | 15 ++++++++++
 src/Ganeti/WConfd/Core.hs                |  6 ++++
 test/hs/Test/Ganeti/Objects.hs           | 19 ++++++++++++
 5 files changed, 92 insertions(+), 1 deletion(-)

diff --git a/lib/objects.py b/lib/objects.py
index 22ef009..02db0e3 100644
--- a/lib/objects.py
+++ b/lib/objects.py
@@ -558,7 +558,7 @@ class Filter(ConfigObject):
 class Maintenance(ConfigObject):
   """Config object representing the state of the maintenance daemon"""
   __slots__ = ["roundDelay", "jobs", "evacuated", "balance", 
"balanceThreshold",
-               "serial_no"] + _TIMESTAMPS
+               "incidents", "serial_no"] + _TIMESTAMPS
 
   def UpgradeConfig(self):
     if self.serial_no is None:
diff --git a/src/Ganeti/Objects/Maintenance.hs 
b/src/Ganeti/Objects/Maintenance.hs
index 6011e3d..6bf091c 100644
--- a/src/Ganeti/Objects/Maintenance.hs
+++ b/src/Ganeti/Objects/Maintenance.hs
@@ -36,13 +36,63 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 module Ganeti.Objects.Maintenance
   ( MaintenanceData(..)
+  , RepairAction(..)
+  , RepairStatus(..)
+  , Incident(..)
   ) where
 
+import qualified Text.JSON as J
+
 import qualified Ganeti.Constants as C
 import Ganeti.THH
 import Ganeti.THH.Field
 import Ganeti.Types
 
+-- | Action to be taken for a certain repair event. Note
+-- that he order is important, as we rely on values higher
+-- in the derived order to be more intrusive actions.
+$(declareLADT ''String "RepairAction"
+    [ ("RANoop", "Ok")
+    , ("RALiveRepair", "live-repair")
+    , ("RAEvacuate", "evacuate")
+    , ("RAEvacuateFailover", "evacute-failover")
+    ])
+$(makeJSONInstance ''RepairAction)
+
+-- | Progress made on the particular repair event. Again we rely
+-- on the order in that everything larger than `RSPending` is finalized
+-- in the sense that no further jobs will be submitted.
+$(declareLADT ''String "RepairStatus"
+   [ ("RSNoted", "noted")
+   , ("RSPending", "pending")
+   , ("RSCanceled", "canceled")
+   , ("RSFailed", "failed")
+   , ("RSCompleted", "completed")
+   ])
+$(makeJSONInstance ''RepairStatus)
+
+$(buildObject "Incident" "incident" $
+   [ simpleField "original" [t| J.JSValue |]
+   , simpleField "action" [t| RepairAction |]
+   , defaultField [| [] |] $ simpleField "jobs" [t| [ JobId ] |]
+   , simpleField "node" [t| String |]
+   , simpleField "repair-status" [t| RepairStatus |]
+   , simpleField "tag" [t| String |]
+   ]
+   ++ uuidFields
+   ++ timeStampFields
+   ++ serialFields)
+
+instance SerialNoObject Incident where
+  serialOf = incidentSerial
+
+instance TimeStampObject Incident where
+  cTimeOf = incidentCtime
+  mTimeOf = incidentMtime
+
+instance UuidObject Incident where
+  uuidOf = incidentUuid
+
 $(buildObject "MaintenanceData" "maint" $
   [ defaultField [| C.maintdDefaultRoundDelay |]
     $ simpleField "roundDelay" [t| Int |]
@@ -51,6 +101,7 @@ $(buildObject "MaintenanceData" "maint" $
   , defaultField [| 0.1 :: Double |]
     $ simpleField "balanceThreshold" [t| Double |]
   , defaultField [| [] |] $ simpleField "evacuated" [t| [ String ] |]
+  , defaultField [| [] |] $ simpleField "incidents" [t| [ Incident ] |]
   ]
   ++ timeStampFields
   ++ serialFields)
diff --git a/src/Ganeti/WConfd/ConfigModifications.hs 
b/src/Ganeti/WConfd/ConfigModifications.hs
index 25448c6..fe09a9d 100644
--- a/src/Ganeti/WConfd/ConfigModifications.hs
+++ b/src/Ganeti/WConfd/ConfigModifications.hs
@@ -711,6 +711,19 @@ rmMaintdEvacuated :: String -> WConfdMonad Bool
 rmMaintdEvacuated name = changeAndBumpMaint . over maintEvacuatedL
                           $ filter (/= name)
 
+-- | Update an incident to the list of known incidents; if the incident,
+-- as identified by the UUID, is not present, it is added.
+updateMaintdIncident :: Incident -> WConfdMonad Bool
+updateMaintdIncident incident =
+  changeAndBumpMaint . over maintIncidentsL
+    $ (incident :) . filter ((/= uuidOf incident) . uuidOf)
+
+-- | Remove an incident from the list of known incidents.
+rmMaintdIncident :: String -> WConfdMonad Bool
+rmMaintdIncident uuid =
+  changeAndBumpMaint . over maintIncidentsL
+    $ filter ((/= uuid) . uuidOf)
+
 -- * The list of functions exported to RPC.
 
 exportedFunctions :: [Name]
@@ -737,4 +750,6 @@ exportedFunctions = [ 'addInstance
                     , 'setMaintdBalanceThreshold
                     , 'addMaintdEvacuated
                     , 'rmMaintdEvacuated
+                    , 'updateMaintdIncident
+                    , 'rmMaintdIncident
                     ]
diff --git a/src/Ganeti/WConfd/Core.hs b/src/Ganeti/WConfd/Core.hs
index 3edccb6..fcbf235 100644
--- a/src/Ganeti/WConfd/Core.hs
+++ b/src/Ganeti/WConfd/Core.hs
@@ -64,6 +64,7 @@ import qualified Ganeti.Locking.Waiting as LW
 import Ganeti.Objects ( ConfigData, DRBDSecret, LogicalVolume, Ip4Address
                       , configMaintenance, maintRoundDelay, maintJobs
                       , maintBalance, maintBalanceThreshold, maintEvacuated
+                      , Incident, maintIncidents
                       )
 import Ganeti.Objects.Lens (configClusterL, clusterMasterNodeL)
 import Ganeti.Types (JobId)
@@ -178,6 +179,10 @@ maintenanceBalancing = liftM ((maintBalance &&& 
maintBalanceThreshold)
 maintenanceEvacuated :: WConfdMonad [String]
 maintenanceEvacuated = liftM (maintEvacuated . configMaintenance) CW.readConfig
 
+-- | Get the list of current incidents.
+maintenanceIncidents :: WConfdMonad [Incident]
+maintenanceIncidents = liftM (maintIncidents . configMaintenance) CW.readConfig
+
 -- ** Temporary reservations related functions
 
 dropAllReservations :: ClientId -> WConfdMonad ()
@@ -412,6 +417,7 @@ exportedFunctions = [ 'echo
                     , 'maintenanceJobs
                     , 'maintenanceBalancing
                     , 'maintenanceEvacuated
+                    , 'maintenanceIncidents
                     -- temporary reservations (common)
                     , 'dropAllReservations
                     -- DRBD
diff --git a/test/hs/Test/Ganeti/Objects.hs b/test/hs/Test/Ganeti/Objects.hs
index 525c96a..857f822 100644
--- a/test/hs/Test/Ganeti/Objects.hs
+++ b/test/hs/Test/Ganeti/Objects.hs
@@ -375,6 +375,24 @@ instance Arbitrary FilterRule where
                          <*> arbitrary
                          <*> genUUID
 
+instance Arbitrary RepairStatus where
+  arbitrary = elements [ RSNoted, RSPending, RSCanceled, RSFailed, RSCompleted 
]
+
+instance Arbitrary RepairAction where
+  arbitrary = elements [ RANoop, RALiveRepair, RAEvacuate, RAEvacuateFailover ]
+
+instance Arbitrary Incident where
+  arbitrary = Incident <$> pure (J.JSObject $ J.toJSObject [])
+                       <*> arbitrary
+                       <*> arbitrary
+                       <*> arbitrary
+                       <*> arbitrary
+                       <*> arbitrary
+                       <*> arbitrary
+                       <*> arbitrary
+                       <*> arbitrary
+                       <*> arbitrary
+
 instance Arbitrary MaintenanceData where
   arbitrary = MaintenanceData <$> (fromPositive <$> arbitrary)
                               <*> arbitrary
@@ -384,6 +402,7 @@ instance Arbitrary MaintenanceData where
                               <*> arbitrary
                               <*> arbitrary
                               <*> arbitrary
+                              <*> arbitrary
 
 -- | Generates a network instance with minimum netmasks of /24. Generating
 -- bigger networks slows down the tests, because long bit strings are generated
-- 
2.5.0.rc2.392.g76e840b

Reply via email to