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
