Commit f19481c0 authored by Klaus Aehlig's avatar Klaus Aehlig

Add configuration for maintenance daemon

As per our design, the maintenance daemons stores its state
in the configuration; also, various of its aspects are
configurable. So add a corresponding configuration object.
Signed-off-by: default avatarKlaus Aehlig <aehlig@google.com>
Reviewed-by: default avatarPetr Pudlak <pudlak@google.com>
parent ec34a57f
...@@ -983,6 +983,7 @@ HS_LIB_SRCS = \ ...@@ -983,6 +983,7 @@ HS_LIB_SRCS = \
src/Ganeti/Objects/Disk.hs \ src/Ganeti/Objects/Disk.hs \
src/Ganeti/Objects/Instance.hs \ src/Ganeti/Objects/Instance.hs \
src/Ganeti/Objects/Lens.hs \ src/Ganeti/Objects/Lens.hs \
src/Ganeti/Objects/Maintenance.hs \
src/Ganeti/Objects/Nic.hs \ src/Ganeti/Objects/Nic.hs \
src/Ganeti/OpCodes.hs \ src/Ganeti/OpCodes.hs \
src/Ganeti/OpCodes/Lens.hs \ src/Ganeti/OpCodes/Lens.hs \
......
...@@ -863,6 +863,7 @@ def InitConfig(version, cluster_config, master_node_config, ...@@ -863,6 +863,7 @@ def InitConfig(version, cluster_config, master_node_config,
default_nodegroup.uuid: default_nodegroup, default_nodegroup.uuid: default_nodegroup,
} }
now = time.time() now = time.time()
maintenance = objects.Maintenance(serial_no=1, ctime=now, mtime=now)
config_data = objects.ConfigData(version=version, config_data = objects.ConfigData(version=version,
cluster=cluster_config, cluster=cluster_config,
nodegroups=nodegroups, nodegroups=nodegroups,
...@@ -871,6 +872,7 @@ def InitConfig(version, cluster_config, master_node_config, ...@@ -871,6 +872,7 @@ def InitConfig(version, cluster_config, master_node_config,
networks={}, networks={},
disks={}, disks={},
filters={}, filters={},
maintenance=maintenance,
serial_no=1, serial_no=1,
ctime=now, mtime=now) ctime=now, mtime=now)
utils.WriteFile(cfg_file, utils.WriteFile(cfg_file,
......
...@@ -63,7 +63,7 @@ from socket import AF_INET ...@@ -63,7 +63,7 @@ from socket import AF_INET
__all__ = ["ConfigObject", "ConfigData", "NIC", "Disk", "Instance", __all__ = ["ConfigObject", "ConfigData", "NIC", "Disk", "Instance",
"OS", "Node", "NodeGroup", "Cluster", "FillDict", "Network", "OS", "Node", "NodeGroup", "Cluster", "FillDict", "Network",
"Filter"] "Filter", "Maintenance"]
_TIMESTAMPS = ["ctime", "mtime"] _TIMESTAMPS = ["ctime", "mtime"]
_UUID = ["uuid"] _UUID = ["uuid"]
...@@ -416,6 +416,7 @@ class ConfigData(ConfigObject): ...@@ -416,6 +416,7 @@ class ConfigData(ConfigObject):
"networks", "networks",
"disks", "disks",
"filters", "filters",
"maintenance",
"serial_no", "serial_no",
] + _TIMESTAMPS ] + _TIMESTAMPS
...@@ -428,6 +429,7 @@ class ConfigData(ConfigObject): ...@@ -428,6 +429,7 @@ class ConfigData(ConfigObject):
""" """
mydict = super(ConfigData, self).ToDict(_with_private=_with_private) mydict = super(ConfigData, self).ToDict(_with_private=_with_private)
mydict["cluster"] = mydict["cluster"].ToDict() mydict["cluster"] = mydict["cluster"].ToDict()
mydict["maintenance"] = mydict["maintenance"].ToDict()
for key in ("nodes", "instances", "nodegroups", "networks", "disks", for key in ("nodes", "instances", "nodegroups", "networks", "disks",
"filters"): "filters"):
mydict[key] = outils.ContainerToDicts(mydict[key]) mydict[key] = outils.ContainerToDicts(mydict[key])
...@@ -449,6 +451,7 @@ class ConfigData(ConfigObject): ...@@ -449,6 +451,7 @@ class ConfigData(ConfigObject):
obj.networks = outils.ContainerFromDicts(obj.networks, dict, Network) obj.networks = outils.ContainerFromDicts(obj.networks, dict, Network)
obj.disks = outils.ContainerFromDicts(obj.disks, dict, Disk) obj.disks = outils.ContainerFromDicts(obj.disks, dict, Disk)
obj.filters = outils.ContainerFromDicts(obj.filters, dict, Filter) obj.filters = outils.ContainerFromDicts(obj.filters, dict, Filter)
obj.maintenance = Maintenance.FromDict(obj.maintenance)
return obj return obj
def DisksOfType(self, dev_type): def DisksOfType(self, dev_type):
...@@ -491,6 +494,9 @@ class ConfigData(ConfigObject): ...@@ -491,6 +494,9 @@ class ConfigData(ConfigObject):
disk.UpgradeConfig() disk.UpgradeConfig()
if self.filters is None: if self.filters is None:
self.filters = {} self.filters = {}
if self.maintenance is None:
self.maintenance = Maintenance.FromDict({})
self.maintenance.UpgradeConfig()
def _UpgradeEnabledDiskTemplates(self): def _UpgradeEnabledDiskTemplates(self):
"""Upgrade the cluster's enabled disk templates by inspecting the currently """Upgrade the cluster's enabled disk templates by inspecting the currently
...@@ -549,6 +555,19 @@ class Filter(ConfigObject): ...@@ -549,6 +555,19 @@ class Filter(ConfigObject):
"predicates", "action", "reason_trail"] + _UUID "predicates", "action", "reason_trail"] + _UUID
class Maintenance(ConfigObject):
"""Config object representing the state of the maintenance daemon"""
__slots__ = ["roundDelay", "jobs", "serial_no"] + _TIMESTAMPS
def UpgradeConfig(self):
if self.serial_no is None:
self.serial_no = 1
if self.mtime is None:
self.mtime = time.time()
if self.ctime is None:
self.ctime = time.time()
class Disk(ConfigObject): class Disk(ConfigObject):
"""Config object representing a block device.""" """Config object representing a block device."""
__slots__ = [ __slots__ = [
......
...@@ -677,6 +677,14 @@ class CfgUpgrade(object): ...@@ -677,6 +677,14 @@ class CfgUpgrade(object):
else: else:
disk["nodes"] = [] disk["nodes"] = []
@OrFail("Upgrading maintenance data")
def UpgradeMaintenance(self):
# pylint can't infer config_data type
# pylint: disable=E1103
maintenance = self.config_data.get("maintenance", None)
if maintenance is None:
self.config_data["maintenance"] = {}
def UpgradeAll(self): def UpgradeAll(self):
self.config_data["version"] = version.BuildVersion(TARGET_MAJOR, self.config_data["version"] = version.BuildVersion(TARGET_MAJOR,
TARGET_MINOR, 0) TARGET_MINOR, 0)
...@@ -692,7 +700,8 @@ class CfgUpgrade(object): ...@@ -692,7 +700,8 @@ class CfgUpgrade(object):
self.UpgradeInstanceIndices, self.UpgradeInstanceIndices,
self.UpgradeFilters, self.UpgradeFilters,
self.UpgradeDiskNodes, self.UpgradeDiskNodes,
self.UpgradeDiskTemplate] self.UpgradeDiskTemplate,
self.UpgradeMaintenance]
for s in steps: for s in steps:
s() s()
return not self.errors return not self.errors
...@@ -700,6 +709,8 @@ class CfgUpgrade(object): ...@@ -700,6 +709,8 @@ class CfgUpgrade(object):
# DOWNGRADE ------------------------------------------------------------ # DOWNGRADE ------------------------------------------------------------
def DowngradeAll(self): def DowngradeAll(self):
if "maintenance" in self.config_data:
del self.config_data["maintenance"]
self.config_data["version"] = version.BuildVersion(DOWNGRADE_MAJOR, self.config_data["version"] = version.BuildVersion(DOWNGRADE_MAJOR,
DOWNGRADE_MINOR, 0) DOWNGRADE_MINOR, 0)
return True return True
......
...@@ -103,6 +103,7 @@ module Ganeti.Objects ...@@ -103,6 +103,7 @@ module Ganeti.Objects
, module Ganeti.PartialParams , module Ganeti.PartialParams
, module Ganeti.Objects.Disk , module Ganeti.Objects.Disk
, module Ganeti.Objects.Instance , module Ganeti.Objects.Instance
, module Ganeti.Objects.Maintenance
) where ) where
import Control.Applicative import Control.Applicative
...@@ -126,6 +127,7 @@ import qualified Ganeti.ConstantUtils as ConstantUtils ...@@ -126,6 +127,7 @@ import qualified Ganeti.ConstantUtils as ConstantUtils
import Ganeti.JSON import Ganeti.JSON
import Ganeti.Objects.BitArray (BitArray) import Ganeti.Objects.BitArray (BitArray)
import Ganeti.Objects.Disk import Ganeti.Objects.Disk
import Ganeti.Objects.Maintenance
import Ganeti.Objects.Nic import Ganeti.Objects.Nic
import Ganeti.Objects.Instance import Ganeti.Objects.Instance
import Ganeti.Query.Language import Ganeti.Query.Language
...@@ -701,6 +703,7 @@ $(buildObject "ConfigData" "config" $ ...@@ -701,6 +703,7 @@ $(buildObject "ConfigData" "config" $
, simpleField "networks" [t| Container Network |] , simpleField "networks" [t| Container Network |]
, simpleField "disks" [t| Container Disk |] , simpleField "disks" [t| Container Disk |]
, simpleField "filters" [t| Container FilterRule |] , simpleField "filters" [t| Container FilterRule |]
, simpleField "maintenance" [t| MaintenanceData |]
] ]
++ timeStampFields ++ timeStampFields
++ serialFields) ++ serialFields)
......
...@@ -149,6 +149,14 @@ instance SerialNoObjectL Cluster where ...@@ -149,6 +149,14 @@ instance SerialNoObjectL Cluster where
instance TagsObjectL Cluster where instance TagsObjectL Cluster where
tagsL = clusterTagsL tagsL = clusterTagsL
$(makeCustomLenses ''MaintenanceData)
instance TimeStampObjectL MaintenanceData where
mTimeL = maintMtimeL
instance SerialNoObjectL MaintenanceData where
serialL = maintSerialL
$(makeCustomLenses ''ConfigData) $(makeCustomLenses ''ConfigData)
instance SerialNoObjectL ConfigData where instance SerialNoObjectL ConfigData where
......
{-# LANGUAGE TemplateHaskell #-}
{-| Implementation of the Ganeti configuration for the maintenance daemon.
-}
{-
Copyright (C) 2015 Google Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-}
module Ganeti.Objects.Maintenance
( MaintenanceData(..)
) where
import qualified Ganeti.Constants as C
import Ganeti.THH
import Ganeti.THH.Field
import Ganeti.Types
$(buildObject "MaintenanceData" "maint" $
[ defaultField [| C.maintdDefaultRoundDelay |]
$ simpleField "roundDelay" [t| Int |]
, defaultField [| [] |] $ simpleField "jobs" [t| [ JobId ] |]
]
++ timeStampFields
++ serialFields)
instance SerialNoObject MaintenanceData where
serialOf = maintSerial
instance TimeStampObject MaintenanceData where
cTimeOf = maintCtime
mTimeOf = maintMtime
...@@ -375,6 +375,13 @@ instance Arbitrary FilterRule where ...@@ -375,6 +375,13 @@ instance Arbitrary FilterRule where
<*> arbitrary <*> arbitrary
<*> genUUID <*> genUUID
instance Arbitrary MaintenanceData where
arbitrary = MaintenanceData <$> (fromPositive <$> arbitrary)
<*> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
-- | Generates a network instance with minimum netmasks of /24. Generating -- | Generates a network instance with minimum netmasks of /24. Generating
-- bigger networks slows down the tests, because long bit strings are generated -- bigger networks slows down the tests, because long bit strings are generated
-- for the reservations. -- for the reservations.
...@@ -431,6 +438,7 @@ genEmptyCluster ncount = do ...@@ -431,6 +438,7 @@ genEmptyCluster ncount = do
networks = GenericContainer Map.empty networks = GenericContainer Map.empty
disks = GenericContainer Map.empty disks = GenericContainer Map.empty
filters = GenericContainer Map.empty filters = GenericContainer Map.empty
maintenance <- arbitrary
let contgroups = GenericContainer $ Map.singleton guuid grp let contgroups = GenericContainer $ Map.singleton guuid grp
serial <- arbitrary serial <- arbitrary
-- timestamp fields -- timestamp fields
...@@ -438,7 +446,7 @@ genEmptyCluster ncount = do ...@@ -438,7 +446,7 @@ genEmptyCluster ncount = do
mtime <- arbitrary mtime <- arbitrary
cluster <- resize 8 arbitrary cluster <- resize 8 arbitrary
let c = ConfigData version cluster contnodes contgroups continsts networks let c = ConfigData version cluster contnodes contgroups continsts networks
disks filters ctime mtime serial disks filters ctime maintenance mtime serial
return c return c
-- | FIXME: make an even simpler base version of creating a cluster. -- | FIXME: make an even simpler base version of creating a cluster.
......
...@@ -79,6 +79,7 @@ def GetMinimalConfig(): ...@@ -79,6 +79,7 @@ def GetMinimalConfig():
"disks": {}, "disks": {},
"networks": {}, "networks": {},
"filters": {}, "filters": {},
"maintenance": {},
"nodegroups": {}, "nodegroups": {},
"nodes": { "nodes": {
"node1-uuid": { "node1-uuid": {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment