Commit 922eb8be authored by Aaron Karper' via ganeti-devel's avatar Aaron Karper' via ganeti-devel Committed by Michele Tartara

Remove xen data collectors from KVM cluster

Generally a data collector can be deactivated in the config and each
data collector defines own conditions to show/hide it.

A hidden data collector is not shown in /1/list/collectors,
/1/report/all. 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
   * Move Ganeti.Monitoring.{Server,Types}.DataCollector
   * Move {Monitoring.Server,DataCollectors.Types}.DataCollector

Implements Issue 870: inst-status-xen should not be shown for KVM
cluster.
Signed-off-by: default avatarAaron Karper <akarper@google.com>
Signed-off-by: default avatarMichele Tartara <mtartara@google.com>
Reviewed-by: default avatarMichele Tartara <mtartara@google.com>
parent 30369fa6
......@@ -790,6 +790,7 @@ HS_LIB_SRCS = \
src/Ganeti/Curl/Multi.hs \
src/Ganeti/Daemon.hs \
src/Ganeti/Daemon/Utils.hs \
src/Ganeti/DataCollectors.hs \
src/Ganeti/DataCollectors/CLI.hs \
src/Ganeti/DataCollectors/CPUload.hs \
src/Ganeti/DataCollectors/Diskstats.hs \
......
......@@ -407,6 +407,7 @@ class ConfigData(ConfigObject):
"networks",
"disks",
"serial_no",
"datacollectors",
] + _TIMESTAMPS
def ToDict(self, _with_private=False):
......
......@@ -55,6 +55,8 @@ import Ganeti.Logging
import qualified Ganeti.Constants as C
import qualified Ganeti.Query.Cluster as QCluster
import Ganeti.Utils
import Ganeti.DataCollectors.Types (DataCollector(..))
import Ganeti.DataCollectors (collectors)
-- * Types and constants definitions
......@@ -245,6 +247,13 @@ buildResponse cdata req@(ConfdRequest { confdRqType = ReqConfigQuery
J.Ok jsvalue -> return (ReplyStatusOk, jsvalue)
J.Error _ -> return queryArgumentError
-- | Returns activation state of data collectors.
buildResponse (cdata,_) (ConfdRequest { confdRqType = ReqDataCollectors }) = do
let mkConfig col =
(dName col, DataCollectorConfig $ dActive col (dName col) cdata)
datacollectors = containerFromList $ map mkConfig collectors
return (ReplyStatusOk, J.showJSON datacollectors)
-- | Creates a ConfdReply from a given answer.
serializeResponse :: Result StatusAnswer -> ConfdReply
serializeResponse r =
......
......@@ -65,6 +65,7 @@ $(declareILADT "ConfdRequestType"
, ("ReqNodeInstances", 8)
, ("ReqInstanceDisks", 9)
, ("ReqConfigQuery", 10)
, ("ReqDataCollectors", 11)
])
$(makeJSONInstance ''ConfdRequestType)
......
......@@ -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,29 @@ ipv4NetworkMinSize = 30
-- for performance tuning was successful.
ipv4NetworkMaxSize :: Int
ipv4NetworkMaxSize = 30
-- * Data Collectors
dataCollectorCPULoad :: String
dataCollectorCPULoad = "cpu-avg-load"
dataCollectorDiskStats :: String
dataCollectorDiskStats = "diskstats"
dataCollectorDrbd :: String
dataCollectorDrbd = "drbd"
dataCollectorLv :: String
dataCollectorLv = "lv"
dataCollectorInstStatus :: String
dataCollectorInstStatus = "inst-status-xen"
dataCollectorNames :: FrozenSet String
dataCollectorNames =
ConstantUtils.mkSet [ dataCollectorCPULoad
, dataCollectorDiskStats
, dataCollectorDrbd
, dataCollectorLv
, dataCollectorInstStatus
]
{-| Definition of the data collectors used by MonD.
-}
{-
Copyright (C) 2014 Google Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
-}
module Ganeti.DataCollectors( collectors ) where
import Data.Map (findWithDefault)
import Data.Monoid (mempty)
import qualified Ganeti.DataCollectors.CPUload as CPUload
import qualified Ganeti.DataCollectors.Diskstats as Diskstats
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 (DataCollector(..),ReportBuilder(..))
import Ganeti.JSON (GenericContainer(..))
import Ganeti.Objects
import Ganeti.Types
-- | The list of available builtin data collectors.
collectors :: [DataCollector]
collectors =
[ cpuLoadCollector
, diskStatsCollector
, drdbCollector
, instStatusCollector
, lvCollector
]
where
f .&&. g = \x y -> f x y && g x y
xenHypervisor = flip elem [XenPvm, XenHvm]
xenCluster _ cfg =
any xenHypervisor . clusterEnabledHypervisors $ configCluster cfg
activeConfig name cfg =
let config = fromContainer . clusterDataCollectors $ configCluster cfg
collectorConfig = findWithDefault mempty name config
in dataCollectorActive collectorConfig
diskStatsCollector =
DataCollector Diskstats.dcName Diskstats.dcCategory
Diskstats.dcKind (StatelessR Diskstats.dcReport) Nothing activeConfig
drdbCollector =
DataCollector Drbd.dcName Drbd.dcCategory Drbd.dcKind
(StatelessR Drbd.dcReport) Nothing activeConfig
instStatusCollector =
DataCollector InstStatus.dcName InstStatus.dcCategory
InstStatus.dcKind (StatelessR InstStatus.dcReport) Nothing
$ xenCluster .&&. activeConfig
lvCollector =
DataCollector Lv.dcName Lv.dcCategory Lv.dcKind
(StatelessR Lv.dcReport) Nothing activeConfig
cpuLoadCollector =
DataCollector CPUload.dcName CPUload.dcCategory CPUload.dcKind
(StatefulR CPUload.dcReport) (Just CPUload.dcUpdate) activeConfig
......@@ -69,7 +69,7 @@ defaultCharNum = 80*20
-- | The name of this data collector.
dcName :: String
dcName = "cpu-avg-load"
dcName = C.dataCollectorCPULoad
-- | The version of this data collector.
dcVersion :: DCVersion
......
......@@ -66,7 +66,7 @@ defaultCharNum = 80*20
-- | The name of this data collector.
dcName :: String
dcName = "diskstats"
dcName = C.dataCollectorDiskStats
-- | The version of this data collector.
dcVersion :: DCVersion
......
......@@ -71,7 +71,7 @@ defaultCharNum = 80*20
-- | The name of this data collector.
dcName :: String
dcName = "drbd"
dcName = C.dataCollectorDrbd
-- | The version of this data collector.
dcVersion :: DCVersion
......
......@@ -46,6 +46,7 @@ import qualified Text.JSON as J
import Ganeti.BasicTypes as BT
import Ganeti.Confd.ClientFunctions
import Ganeti.Common
import qualified Ganeti.Constants as C
import Ganeti.DataCollectors.CLI
import Ganeti.DataCollectors.InstStatusTypes
import Ganeti.DataCollectors.Types
......@@ -60,7 +61,7 @@ import Ganeti.Utils
-- | The name of this data collector.
dcName :: String
dcName = "inst-status-xen"
dcName = C.dataCollectorInstStatus
-- | The version of this data collector.
dcVersion :: DCVersion
......
......@@ -47,6 +47,7 @@ import qualified Text.JSON as J
import qualified Ganeti.BasicTypes as BT
import Ganeti.Common
import qualified Ganeti.Constants as C
import Ganeti.Confd.ClientFunctions
import Ganeti.DataCollectors.CLI
import Ganeti.DataCollectors.Types
......@@ -66,7 +67,7 @@ defaultCharNum = 80*20
-- | The name of this data collector.
dcName :: String
dcName = "lv"
dcName = C.dataCollectorLv
-- | The version of this data collector.
dcVersion :: DCVersion
......
......@@ -38,6 +38,8 @@ module Ganeti.DataCollectors.Types
, buildReport
, mergeStatuses
, getCategoryName
, ReportBuilder(..)
, DataCollector(..)
) where
import Data.Char
......@@ -47,6 +49,7 @@ import qualified Data.Sequence as Seq
import Text.JSON
import Ganeti.Constants as C
import Ganeti.Objects (ConfigData)
import Ganeti.THH
import Ganeti.Utils (getCurrentTime)
......@@ -177,3 +180,23 @@ buildReport name version format_version category kind jsonData = do
return $
DCReport name version format_version timestamp category kind
jsonData
-- | A report of a data collector might be stateful or stateless.
data ReportBuilder = StatelessR (IO DCReport)
| StatefulR (Maybe CollectorData -> IO DCReport)
type Name = String
-- | Type describing a data collector basic information
data DataCollector = DataCollector
{ dName :: Name -- ^ Name of the data collector
, dCategory :: Maybe DCCategory -- ^ Category (storage, instance, ecc)
-- of the collector
, dKind :: DCKind -- ^ Kind (performance or status reporting) of
-- the data collector
, dReport :: ReportBuilder -- ^ Report produced by the collector
, dUpdate :: Maybe (Maybe CollectorData -> IO CollectorData)
-- ^ Update operation for stateful collectors.
, dActive :: Name -> ConfigData -> Bool
-- ^ Checks if the collector applies for the cluster.
}
......@@ -65,7 +65,7 @@ import Ganeti.HTools.Loader (mergeData, checkData, ClusterData(..)
import Ganeti.BasicTypes
import Ganeti.Cpu.Types
import Ganeti.DataCollectors.Types
import Ganeti.DataCollectors.Types hiding (DataCollector(..))
import Ganeti.HTools.Types
import Ganeti.HTools.CLI
import Ganeti.JSON
......
......@@ -48,6 +48,7 @@ module Ganeti.JSON
, toArray
, optionalJSField
, optFieldsToObj
, containerFromList
, lookupContainer
, alterContainerL
, readContainer
......@@ -321,6 +322,10 @@ instance F.Traversable (GenericContainer a) where
-- | Type alias for string keys.
type Container = GenericContainer String
-- | Creates a GenericContainer from a list of key-value pairs.
containerFromList :: Ord a => [(a,b)] -> GenericContainer a b
containerFromList = GenericContainer . Map.fromList
-- | Looks up a value in a container with a default value.
-- If a key has no value, a given monadic default is returned.
-- This allows simple error handling, as the default can be
......
......@@ -35,6 +35,7 @@ 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,13 +44,13 @@ 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
import qualified Ganeti.DataCollectors.Drbd as Drbd
import qualified Ganeti.DataCollectors.InstStatus as InstStatus
import qualified Ganeti.DataCollectors.Lv as Lv
import qualified Ganeti.DataCollectors as DC
import Ganeti.DataCollectors.Types
import qualified Ganeti.JSON as GJ
import Ganeti.Objects (DataCollectorConfig(..))
import qualified Ganeti.Constants as C
import Ganeti.Runtime
......@@ -65,38 +66,6 @@ type PrepResult = Config Snap ()
latestAPIVersion :: Int
latestAPIVersion = C.mondLatestApiVersion
-- | A report of a data collector might be stateful or stateless.
data Report = StatelessR (IO DCReport)
| StatefulR (Maybe CollectorData -> IO DCReport)
-- | Type describing a data collector basic information
data DataCollector = DataCollector
{ dName :: String -- ^ Name of the data collector
, dCategory :: Maybe DCCategory -- ^ Category (storage, instance, ecc)
-- of the collector
, dKind :: DCKind -- ^ Kind (performance or status reporting) of
-- the data collector
, dReport :: Report -- ^ Report produced by the collector
, dUpdate :: Maybe (Maybe CollectorData -> IO CollectorData)
-- ^ Update operation for stateful collectors.
}
-- | 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)
]
-- * Configuration handling
-- | The default configuration for the HTTP server.
......@@ -141,6 +110,23 @@ version1Api mvar =
, ("report", reportHandler mvar)
]
activeCollectors :: IO [DataCollector]
activeCollectors = do
confdClient <- getConfdClient Nothing Nothing
response <- query confdClient CT.ReqDataCollectors CT.EmptyQuery
let isActive = fromMaybe True . parseActive response
return $ filter isActive DC.collectors
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
-- | Get the JSON representation of a data collector to be used in the collector
-- list.
dcListItem :: DataCollector -> J.JSValue
......@@ -155,8 +141,10 @@ dcListItem dc =
-- | Handler for returning lists.
listHandler :: Snap ()
listHandler =
dir "collectors" . writeBS . pack . J.encode $ map dcListItem collectors
listHandler = dir "collectors" $ do
collectors' <- liftIO activeCollectors
writeBS . pack . J.encode $ map dcListItem collectors'
-- | Handler for returning data collector reports.
reportHandler :: MVar CollectorMap -> Snap ()
......@@ -170,7 +158,8 @@ reportHandler mvar =
-- | Return the report of all the available collectors.
allReports :: MVar CollectorMap -> Snap ()
allReports mvar = do
reports <- mapM (liftIO . getReport mvar) collectors
collectors' <- liftIO activeCollectors
reports <- mapM (liftIO . getReport mvar) collectors'
writeBS . pack . J.encode $ reports
-- | Takes the CollectorMap and a DataCollector and returns the report for this
......@@ -213,6 +202,7 @@ error404 = do
-- | Return the report of one collector.
oneReport :: MVar CollectorMap -> Snap ()
oneReport mvar = do
collectors' <- liftIO activeCollectors
categoryName <- maybe mzero unpack <$> getParam "category"
collectorName <- maybe mzero unpack <$> getParam "collector"
category <-
......@@ -222,7 +212,7 @@ oneReport mvar = do
collector <-
case
find (\col -> collectorName == dName col) $
filter (\c -> category == dCategory c) collectors of
filter (\c -> category == dCategory c) collectors' of
Just col -> return col
Nothing -> fail "Unable to find the requested collector"
dcr <- liftIO $ getReport mvar collector
......@@ -249,7 +239,7 @@ collect m collector =
-- | Invokes collect for each data collector.
collection :: CollectorMap -> IO CollectorMap
collection m = foldM collect m collectors
collection m = liftIO activeCollectors >>= foldM collect m
-- | The thread responsible for the periodical collection of data for each data
-- data collector.
......
......@@ -39,6 +39,7 @@ module Ganeti.Objects
, PartialNic(..)
, FileDriver(..)
, DRBDSecret
, DataCollectorConfig(..)
, LogicalVolume(..)
, DiskLogicalId(..)
, Disk(..)
......@@ -110,6 +111,7 @@ import Data.Char
import Data.List (foldl', isPrefixOf, isInfixOf, intercalate)
import Data.Maybe
import qualified Data.Map as Map
import Data.Monoid
import qualified Data.Set as Set
import Data.Tuple (swap)
import Data.Word
......@@ -312,6 +314,17 @@ $(buildObject "PartialNic" "nic" $
instance UuidObject PartialNic where
uuidOf = nicUuid
-- * Datacollector definitions
-- | The configuration regarding a single data collector.
$(buildObject "DataCollectorConfig" "dataCollector" [
simpleField "active" [t| Bool|]
])
-- | Central default values of the data collector config.
instance Monoid DataCollectorConfig where
mempty = DataCollectorConfig { dataCollectorActive = True }
mappend _ a = a
-- * Disk definitions
-- | Constant for the dev_type key entry in the disk config.
......@@ -801,58 +814,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
......
......@@ -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
......
{-# LANGUAGE TemplateHaskell #-}
{-| Ganeti monitoring agent daemon
-}
......@@ -25,10 +26,25 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
module Main (main) where
import qualified Ganeti.Monitoring.Server
import Data.List ((\\))
import Ganeti.Daemon
import Ganeti.DataCollectors (collectors)
import Ganeti.DataCollectors.Types (dName)
import Ganeti.Runtime
import qualified Ganeti.Monitoring.Server as S
import qualified Ganeti.Constants as C
import qualified Ganeti.ConstantUtils as CU
-- Check constistency of defined data collectors and their names used for the
-- Python constant generation:
$(let names = map dName collectors
missing = names \\ CU.toList C.dataCollectorNames
in if null missing
then return []
else fail $ "Please add " ++ show missing
++ " to the Ganeti.Constants.dataCollectorNames.")
-- | Options list and functions.
options :: [OptType]
......@@ -44,6 +60,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
......@@ -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