They are not shown in /1/list/collectors. The relevant config is
requested from the RConfD.
* Added new constant dataCollectorNames: The consistency is checked
at compile time thanks to template haskell.
* cfgupgrade: add datacollectors section in cluster. The section
currently has a single entry: 'active'
* Added Arbitrary instances for the relevant types
Implements 870
Signed-off-by: Aaron Karper <[email protected]>
---
lib/objects.py | 1 +
src/Ganeti/Confd/Server.hs | 5 ++
src/Ganeti/Confd/Types.hs | 1 +
src/Ganeti/Constants.hs | 14 ++++++
src/Ganeti/Monitoring/Server.hs | 57 +++++++++++++++++-----
src/Ganeti/Objects.hs | 105 +++++++++++++++++++++-------------------
src/Ganeti/Query/Server.hs | 2 +
src/ganeti-mond.hs | 20 ++++++--
test/hs/Test/Ganeti/Objects.hs | 9 ++++
test/hs/Test/Ganeti/OpCodes.hs | 9 ++++
tools/cfgupgrade | 11 +++++
11 files changed, 169 insertions(+), 65 deletions(-)
diff --git a/lib/objects.py b/lib/objects.py
index 553c5a8..2fa72a0 100644
--- a/lib/objects.py
+++ b/lib/objects.py
@@ -407,6 +407,7 @@ class ConfigData(ConfigObject):
"networks",
"disks",
"serial_no",
+ "datacollectors",
] + _TIMESTAMPS
def ToDict(self, _with_private=False):
diff --git a/src/Ganeti/Confd/Server.hs b/src/Ganeti/Confd/Server.hs
index 3fbdc26..349e996 100644
--- a/src/Ganeti/Confd/Server.hs
+++ b/src/Ganeti/Confd/Server.hs
@@ -245,6 +245,11 @@ buildResponse cdata req@(ConfdRequest { confdRqType =
ReqConfigQuery
J.Ok jsvalue -> return (ReplyStatusOk, jsvalue)
J.Error _ -> return queryArgumentError
+-- | Return activation state of data collectors
+buildResponse (cdata,_) (ConfdRequest { confdRqType = ReqDataCollectors }) = do
+ let datacollectors = clusterDataCollectors $ configCluster cdata
+ return (ReplyStatusOk, J.showJSON datacollectors)
+
-- | Creates a ConfdReply from a given answer.
serializeResponse :: Result StatusAnswer -> ConfdReply
serializeResponse r =
diff --git a/src/Ganeti/Confd/Types.hs b/src/Ganeti/Confd/Types.hs
index 8eed390..33eab6b 100644
--- a/src/Ganeti/Confd/Types.hs
+++ b/src/Ganeti/Confd/Types.hs
@@ -65,6 +65,7 @@ $(declareILADT "ConfdRequestType"
, ("ReqNodeInstances", 8)
, ("ReqInstanceDisks", 9)
, ("ReqConfigQuery", 10)
+ , ("ReqDataCollectors", 11)
])
$(makeJSONInstance ''ConfdRequestType)
diff --git a/src/Ganeti/Constants.hs b/src/Ganeti/Constants.hs
index eb33ba8..eb6f4f1 100644
--- a/src/Ganeti/Constants.hs
+++ b/src/Ganeti/Constants.hs
@@ -4220,6 +4220,9 @@ confdReqInstanceDisks = Types.confdRequestTypeToRaw
ReqInstanceDisks
confdReqConfigQuery :: Int
confdReqConfigQuery = Types.confdRequestTypeToRaw ReqConfigQuery
+confdReqDataCollectors :: Int
+confdReqDataCollectors = Types.confdRequestTypeToRaw ReqDataCollectors
+
confdReqs :: FrozenSet Int
confdReqs =
ConstantUtils.mkSet .
@@ -5105,3 +5108,14 @@ ipv4NetworkMinSize = 30
-- for performance tuning was successful.
ipv4NetworkMaxSize :: Int
ipv4NetworkMaxSize = 30
+
+-- * Data Collectors
+
+dataCollectorNames :: FrozenSet String
+dataCollectorNames =
+ ConstantUtils.mkSet [ "diskstats"
+ , "drbd"
+ , "lv"
+ , "inst-status-xen"
+ , "cpu-avg-load"
+ ]
diff --git a/src/Ganeti/Monitoring/Server.hs b/src/Ganeti/Monitoring/Server.hs
index bc860bd..1855dae 100644
--- a/src/Ganeti/Monitoring/Server.hs
+++ b/src/Ganeti/Monitoring/Server.hs
@@ -29,12 +29,15 @@ module Ganeti.Monitoring.Server
( main
, checkMain
, prepMain
+ , DataCollector(..)
+ , collectors
) where
import Control.Applicative
import Control.Monad
import Control.Monad.IO.Class
import Data.ByteString.Char8 hiding (map, filter, find)
+import Data.Maybe (fromMaybe)
import Data.List
import qualified Data.Map as Map
import Snap.Core
@@ -43,6 +46,8 @@ import qualified Text.JSON as J
import Control.Concurrent
import qualified Ganeti.BasicTypes as BT
+import Ganeti.Confd.Client
+import qualified Ganeti.Confd.Types as CT
import Ganeti.Daemon
import qualified Ganeti.DataCollectors.CPUload as CPUload
import qualified Ganeti.DataCollectors.Diskstats as Diskstats
@@ -50,6 +55,8 @@ import qualified Ganeti.DataCollectors.Drbd as Drbd
import qualified Ganeti.DataCollectors.InstStatus as InstStatus
import qualified Ganeti.DataCollectors.Lv as Lv
import Ganeti.DataCollectors.Types
+import qualified Ganeti.JSON as GJ
+import Ganeti.Objects (DataCollectorConfig(..))
import qualified Ganeti.Constants as C
import Ganeti.Runtime
@@ -85,17 +92,28 @@ data DataCollector = DataCollector
-- | The list of available builtin data collectors.
collectors :: [DataCollector]
collectors =
- [ DataCollector Diskstats.dcName Diskstats.dcCategory Diskstats.dcKind
- (StatelessR Diskstats.dcReport) Nothing
- , DataCollector Drbd.dcName Drbd.dcCategory Drbd.dcKind
- (StatelessR Drbd.dcReport) Nothing
- , DataCollector InstStatus.dcName InstStatus.dcCategory InstStatus.dcKind
- (StatelessR InstStatus.dcReport) Nothing
- , DataCollector Lv.dcName Lv.dcCategory Lv.dcKind
- (StatelessR Lv.dcReport) Nothing
- , DataCollector CPUload.dcName CPUload.dcCategory CPUload.dcKind
- (StatefulR CPUload.dcReport) (Just CPUload.dcUpdate)
+ [ diskStatsCollector
+ , drdbCollector
+ , instStatusCollector
+ , lvCollector
+ , cpuLoadCollector
]
+ where
+ diskStatsCollector =
+ DataCollector Diskstats.dcName Diskstats.dcCategory Diskstats.dcKind
+ (StatelessR Diskstats.dcReport) Nothing
+ drdbCollector =
+ DataCollector Drbd.dcName Drbd.dcCategory Drbd.dcKind
+ (StatelessR Drbd.dcReport) Nothing
+ instStatusCollector =
+ DataCollector InstStatus.dcName InstStatus.dcCategory InstStatus.dcKind
+ (StatelessR InstStatus.dcReport) Nothing
+ lvCollector =
+ DataCollector Lv.dcName Lv.dcCategory Lv.dcKind
+ (StatelessR Lv.dcReport) Nothing
+ cpuLoadCollector =
+ DataCollector CPUload.dcName CPUload.dcCategory CPUload.dcKind
+ (StatefulR CPUload.dcReport) (Just CPUload.dcUpdate)
-- * Configuration handling
@@ -155,8 +173,23 @@ dcListItem dc =
-- | Handler for returning lists.
listHandler :: Snap ()
-listHandler =
- dir "collectors" . writeBS . pack . J.encode $ map dcListItem collectors
+listHandler = dir "collectors" $ do
+ confdClient <- liftIO $ getConfdClient Nothing Nothing
+ response <- liftIO $ query confdClient CT.ReqDataCollectors CT.EmptyQuery
+ let isActive = fromMaybe True . parseActive response
+ activeCollectors = filter isActive collectors
+ writeBS . pack . J.encode $ map dcListItem activeCollectors
+ where
+ parseActive :: Maybe CT.ConfdReply -> DataCollector -> Maybe Bool
+ parseActive response dc = do
+ confdReply <- response
+ let answer = CT.confdReplyAnswer confdReply
+ case J.readJSON answer :: J.Result (GJ.Container DataCollectorConfig) of
+ J.Error _ -> Nothing
+ J.Ok container -> do
+ config <- GJ.lookupContainer Nothing (dName dc) container
+ return $ dataCollectorActive config
+
-- | Handler for returning data collector reports.
reportHandler :: MVar CollectorMap -> Snap ()
diff --git a/src/Ganeti/Objects.hs b/src/Ganeti/Objects.hs
index fbbfc83..53bf61e 100644
--- a/src/Ganeti/Objects.hs
+++ b/src/Ganeti/Objects.hs
@@ -39,6 +39,7 @@ module Ganeti.Objects
, PartialNic(..)
, FileDriver(..)
, DRBDSecret
+ , DataCollectorConfig(..)
, LogicalVolume(..)
, DiskLogicalId(..)
, Disk(..)
@@ -312,6 +313,11 @@ $(buildObject "PartialNic" "nic" $
instance UuidObject PartialNic where
uuidOf = nicUuid
+-- * Datacollector definitions
+$(buildObject "DataCollectorConfig" "dataCollector" [
+ simpleField "active" [t| Bool|]
+ ])
+
-- * Disk definitions
-- | Constant for the dev_type key entry in the disk config.
@@ -801,58 +807,59 @@ type HypervisorState = Container JSValue
-- * Cluster definitions
$(buildObject "Cluster" "cluster" $
- [ simpleField "rsahostkeypub" [t| String |]
+ [ simpleField "rsahostkeypub" [t| String
|]
, optionalField $
- simpleField "dsahostkeypub" [t| String |]
- , simpleField "highest_used_port" [t| Int |]
- , simpleField "tcpudp_port_pool" [t| [Int] |]
- , simpleField "mac_prefix" [t| String |]
+ simpleField "dsahostkeypub" [t| String
|]
+ , simpleField "highest_used_port" [t| Int
|]
+ , simpleField "tcpudp_port_pool" [t| [Int]
|]
+ , simpleField "mac_prefix" [t| String
|]
, optionalField $
- simpleField "volume_group_name" [t| String |]
- , simpleField "reserved_lvs" [t| [String] |]
+ simpleField "volume_group_name" [t| String
|]
+ , simpleField "reserved_lvs" [t| [String]
|]
, optionalField $
- simpleField "drbd_usermode_helper" [t| String |]
- , simpleField "master_node" [t| String |]
- , simpleField "master_ip" [t| String |]
- , simpleField "master_netdev" [t| String |]
- , simpleField "master_netmask" [t| Int |]
- , simpleField "use_external_mip_script" [t| Bool |]
- , simpleField "cluster_name" [t| String |]
- , simpleField "file_storage_dir" [t| String |]
- , simpleField "shared_file_storage_dir" [t| String |]
- , simpleField "gluster_storage_dir" [t| String |]
- , simpleField "enabled_hypervisors" [t| [Hypervisor] |]
- , simpleField "hvparams" [t| ClusterHvParams |]
- , simpleField "os_hvp" [t| OsHvParams |]
- , simpleField "beparams" [t| ClusterBeParams |]
- , simpleField "osparams" [t| ClusterOsParams |]
- , simpleField "osparams_private_cluster" [t| ClusterOsParamsPrivate |]
- , simpleField "nicparams" [t| ClusterNicParams |]
- , simpleField "ndparams" [t| FilledNDParams |]
- , simpleField "diskparams" [t| GroupDiskParams |]
- , simpleField "candidate_pool_size" [t| Int |]
- , simpleField "modify_etc_hosts" [t| Bool |]
- , simpleField "modify_ssh_setup" [t| Bool |]
- , simpleField "maintain_node_health" [t| Bool |]
- , simpleField "uid_pool" [t| UidPool |]
- , simpleField "default_iallocator" [t| String |]
- , simpleField "default_iallocator_params" [t| IAllocatorParams |]
- , simpleField "hidden_os" [t| [String] |]
- , simpleField "blacklisted_os" [t| [String] |]
- , simpleField "primary_ip_family" [t| IpFamily |]
- , simpleField "prealloc_wipe_disks" [t| Bool |]
- , simpleField "ipolicy" [t| FilledIPolicy |]
- , simpleField "hv_state_static" [t| HypervisorState |]
- , simpleField "disk_state_static" [t| DiskState |]
- , simpleField "enabled_disk_templates" [t| [DiskTemplate] |]
- , simpleField "candidate_certs" [t| CandidateCertificates |]
- , simpleField "max_running_jobs" [t| Int |]
- , simpleField "max_tracked_jobs" [t| Int |]
- , simpleField "install_image" [t| String |]
- , simpleField "instance_communication_network" [t| String |]
- , simpleField "zeroing_image" [t| String |]
- , simpleField "compression_tools" [t| [String] |]
- , simpleField "enabled_user_shutdown" [t| Bool |]
+ simpleField "drbd_usermode_helper" [t| String
|]
+ , simpleField "master_node" [t| String
|]
+ , simpleField "master_ip" [t| String
|]
+ , simpleField "master_netdev" [t| String
|]
+ , simpleField "master_netmask" [t| Int
|]
+ , simpleField "use_external_mip_script" [t| Bool
|]
+ , simpleField "cluster_name" [t| String
|]
+ , simpleField "file_storage_dir" [t| String
|]
+ , simpleField "shared_file_storage_dir" [t| String
|]
+ , simpleField "gluster_storage_dir" [t| String
|]
+ , simpleField "enabled_hypervisors" [t| [Hypervisor]
|]
+ , simpleField "hvparams" [t| ClusterHvParams
|]
+ , simpleField "os_hvp" [t| OsHvParams
|]
+ , simpleField "beparams" [t| ClusterBeParams
|]
+ , simpleField "osparams" [t| ClusterOsParams
|]
+ , simpleField "osparams_private_cluster" [t| ClusterOsParamsPrivate
|]
+ , simpleField "nicparams" [t| ClusterNicParams
|]
+ , simpleField "ndparams" [t| FilledNDParams
|]
+ , simpleField "diskparams" [t| GroupDiskParams
|]
+ , simpleField "candidate_pool_size" [t| Int
|]
+ , simpleField "modify_etc_hosts" [t| Bool
|]
+ , simpleField "modify_ssh_setup" [t| Bool
|]
+ , simpleField "maintain_node_health" [t| Bool
|]
+ , simpleField "uid_pool" [t| UidPool
|]
+ , simpleField "default_iallocator" [t| String
|]
+ , simpleField "default_iallocator_params" [t| IAllocatorParams
|]
+ , simpleField "hidden_os" [t| [String]
|]
+ , simpleField "blacklisted_os" [t| [String]
|]
+ , simpleField "primary_ip_family" [t| IpFamily
|]
+ , simpleField "prealloc_wipe_disks" [t| Bool
|]
+ , simpleField "ipolicy" [t| FilledIPolicy
|]
+ , simpleField "hv_state_static" [t| HypervisorState
|]
+ , simpleField "disk_state_static" [t| DiskState
|]
+ , simpleField "enabled_disk_templates" [t| [DiskTemplate]
|]
+ , simpleField "candidate_certs" [t| CandidateCertificates
|]
+ , simpleField "max_running_jobs" [t| Int
|]
+ , simpleField "max_tracked_jobs" [t| Int
|]
+ , simpleField "install_image" [t| String
|]
+ , simpleField "instance_communication_network" [t| String
|]
+ , simpleField "zeroing_image" [t| String
|]
+ , simpleField "compression_tools" [t| [String]
|]
+ , simpleField "enabled_user_shutdown" [t| Bool
|]
+ , simpleField "data_collectors" [t| Container
DataCollectorConfig |]
]
++ timeStampFields
++ uuidFields
diff --git a/src/Ganeti/Query/Server.hs b/src/Ganeti/Query/Server.hs
index d6c942d..2930aa5 100644
--- a/src/Ganeti/Query/Server.hs
+++ b/src/Ganeti/Query/Server.hs
@@ -183,6 +183,8 @@ handleCall _ _ cdata QueryClusterInfo =
showJSON $ clusterCompressionTools cluster)
, ("enabled_user_shutdown",
showJSON $ clusterEnabledUserShutdown cluster)
+ , ("data_collectors",
+ showJSON $ clusterDataCollectors cluster)
]
in case master of
diff --git a/src/ganeti-mond.hs b/src/ganeti-mond.hs
index 33897df..eda7202 100644
--- a/src/ganeti-mond.hs
+++ b/src/ganeti-mond.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE TemplateHaskell #-}
{-| Ganeti monitoring agent daemon
-}
@@ -25,10 +26,21 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA
module Main (main) where
-import qualified Ganeti.Monitoring.Server
+import Data.List ((\\))
+
+import qualified Ganeti.Monitoring.Server as S
import Ganeti.Daemon
import Ganeti.Runtime
import qualified Ganeti.Constants as C
+import qualified Ganeti.ConstantUtils as CU
+
+$(let names = map S.dName S.collectors
+ missing = names \\ CU.toList C.dataCollectorNames
+ in if missing == []
+ then return []
+ else fail $ "Please add " ++ show missing
+ ++ " to the Ganeti.Constants.dataCollectorNames.")
+
-- | Options list and functions.
options :: [OptType]
@@ -44,6 +56,6 @@ options =
main :: IO ()
main =
genericMain GanetiMond options
- Ganeti.Monitoring.Server.checkMain
- Ganeti.Monitoring.Server.prepMain
- Ganeti.Monitoring.Server.main
+ S.checkMain
+ S.prepMain
+ S.main
diff --git a/test/hs/Test/Ganeti/Objects.hs b/test/hs/Test/Ganeti/Objects.hs
index 4c5da26..bd442a3 100644
--- a/test/hs/Test/Ganeti/Objects.hs
+++ b/test/hs/Test/Ganeti/Objects.hs
@@ -60,6 +60,7 @@ import Test.Ganeti.TestCommon
import Test.Ganeti.Types ()
import qualified Ganeti.Constants as C
+import qualified Ganeti.ConstantUtils as CU
import Ganeti.Network
import Ganeti.Objects as Objects
import qualified Ganeti.Objects.BitArray as BA
@@ -68,6 +69,14 @@ import Ganeti.Types
-- * Arbitrary instances
+instance Arbitrary (Container DataCollectorConfig) where
+ arbitrary = do
+ let names = CU.toList C.dataCollectorNames
+ activations <- vector $ length names
+ let configs = map DataCollectorConfig activations
+ return GenericContainer {
+ fromContainer = Map.fromList $ zip names configs }
+
$(genArbitrary ''PartialNDParams)
instance Arbitrary Node where
diff --git a/test/hs/Test/Ganeti/OpCodes.hs b/test/hs/Test/Ganeti/OpCodes.hs
index 57e96cf..f881731 100644
--- a/test/hs/Test/Ganeti/OpCodes.hs
+++ b/test/hs/Test/Ganeti/OpCodes.hs
@@ -39,6 +39,7 @@ import Control.Monad
import Data.Char
import Data.List
import qualified Data.Map as Map
+import qualified Data.Set as Set
import qualified Text.JSON as J
import Text.Printf (printf)
@@ -50,6 +51,7 @@ import Test.Ganeti.Types ()
import Ganeti.BasicTypes
import qualified Ganeti.Constants as C
+import qualified Ganeti.ConstantUtils as CU
import qualified Ganeti.OpCodes as OpCodes
import Ganeti.Types
import Ganeti.OpParams
@@ -116,6 +118,11 @@ instance Arbitrary ExportTarget where
, ExportTargetRemote <$> pure []
]
+arbitraryDataCollector :: Gen (ListSet String)
+arbitraryDataCollector = do
+ els <- listOf . elements $ CU.toList C.dataCollectorNames
+ return . ListSet $ Set.fromList els
+
instance Arbitrary OpCodes.OpCode where
arbitrary = do
op_id <- elements OpCodes.allOpIDs
@@ -224,6 +231,8 @@ instance Arbitrary OpCodes.OpCode where
<*> genMaybe (listOf genPrintableAsciiStringNE)
-- compression_tools
<*> arbitrary -- enabled_user_shutdown
+ <*> arbitraryDataCollector -- activate_data_collectors
+ <*> arbitraryDataCollector -- deactivate_data_collectors
"OP_CLUSTER_REDIST_CONF" -> pure OpCodes.OpClusterRedistConf
"OP_CLUSTER_ACTIVATE_MASTER_IP" ->
pure OpCodes.OpClusterActivateMasterIp
diff --git a/tools/cfgupgrade b/tools/cfgupgrade
index fd87a30..b97ebd4 100755
--- a/tools/cfgupgrade
+++ b/tools/cfgupgrade
@@ -162,6 +162,8 @@ def UpgradeCluster(config_data):
cluster.get("compression_tools", constants.IEC_DEFAULT_TOOLS)
if "enabled_user_shutdown" not in cluster:
cluster["enabled_user_shutdown"] = False
+ cluster["data_collectors"] = dict(
+ (name, dict(active=True)) for name in constants.DATA_COLLECTOR_NAMES)
def UpgradeGroups(config_data):
@@ -435,6 +437,8 @@ def UpgradeTopLevelDisks(config_data):
iobj["disks"] = disk_uuids
+
+
def UpgradeAll(config_data):
config_data["version"] = version.BuildVersion(TARGET_MAJOR, TARGET_MINOR, 0)
UpgradeRapiUsers()
@@ -466,12 +470,19 @@ def DowngradeExtAccess(config_data):
del group_extparams["access"]
+def DowngradeDataCollectors(config_data):
+ cluster = config_data["cluster"]
+ if "data_collectors" in cluster:
+ del cluster["data_collectors"]
+
+
def DowngradeAll(config_data):
# Any code specific to a particular version should be labeled that way, so
# it can be removed when updating to the next version.
config_data["version"] = version.BuildVersion(DOWNGRADE_MAJOR,
DOWNGRADE_MINOR, 0)
DowngradeExtAccess(config_data)
+ DowngradeDataCollectors(config_data)
def _ParseOptions():
--
2.1.0.rc2.206.gedb03e5