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