Currently hv/disk_state_static parameters are supported only for cluster
object properly. For node groups and nodes they were introduced in
2da9f556, however only on the python side. Convert hv_state_static from
None to {} in ConfigUpgrade for NodeGroup and Node as well. Haskell
objects are extended with these parameters as well.Also mock config objects modified to return empty dictionaries for hv_state_static instead of None. Signed-off-by: Oleg Ponomarev <[email protected]> --- Makefile.am | 1 + lib/objects.py | 10 ++++++ src/Ganeti/Objects.hs | 71 ++++++++++++++++++++++------------------ src/Ganeti/Objects/HvState.hs | 60 +++++++++++++++++++++++++++++++++ test/hs/Test/Ganeti/Objects.hs | 31 ++++++++++++++++-- test/py/testutils/config_mock.py | 5 +-- 6 files changed, 141 insertions(+), 37 deletions(-) create mode 100644 src/Ganeti/Objects/HvState.hs diff --git a/Makefile.am b/Makefile.am index 7a0ec87..62027fe 100644 --- a/Makefile.am +++ b/Makefile.am @@ -996,6 +996,7 @@ HS_LIB_SRCS = \ src/Ganeti/Objects/BitArray.hs \ src/Ganeti/Objects/Disk.hs \ src/Ganeti/Objects/Instance.hs \ + src/Ganeti/Objects/HvState.hs \ src/Ganeti/Objects/Lens.hs \ src/Ganeti/Objects/Maintenance.hs \ src/Ganeti/Objects/Nic.hs \ diff --git a/lib/objects.py b/lib/objects.py index 02db0e3..c6648f1 100644 --- a/lib/objects.py +++ b/lib/objects.py @@ -1490,6 +1490,11 @@ class Node(TaggableObject): if self.powered is None: self.powered = True + if self.hv_state_static is None: + self.hv_state_static = {} + if self.disk_state_static is None: + self.disk_state_static = {} + def ToDict(self, _with_private=False): """Custom function for serializing. @@ -1587,6 +1592,11 @@ class NodeGroup(TaggableObject): if self.ipolicy is None: self.ipolicy = MakeEmptyIPolicy() + if self.hv_state_static is None: + self.hv_state_static = {} + if self.disk_state_static is None: + self.disk_state_static = {} + if self.networks is None: self.networks = {} diff --git a/src/Ganeti/Objects.hs b/src/Ganeti/Objects.hs index 98f0ac9..9c6a3d5 100644 --- a/src/Ganeti/Objects.hs +++ b/src/Ganeti/Objects.hs @@ -104,7 +104,11 @@ module Ganeti.Objects , module Ganeti.Objects.Disk , module Ganeti.Objects.Instance , module Ganeti.Objects.Maintenance - ) where + , FilledHvStateParams(..) + , PartialHvStateParams(..) + , allHvStateParamFields + , FilledHvState + , PartialHvState ) where import Prelude () import Ganeti.Prelude @@ -131,6 +135,7 @@ import Ganeti.Objects.Disk import Ganeti.Objects.Maintenance import Ganeti.Objects.Nic import Ganeti.Objects.Instance +import Ganeti.Objects.HvState import Ganeti.Query.Language import Ganeti.PartialParams import Ganeti.Types @@ -389,6 +394,12 @@ instance PartialParams FilledIPolicy PartialIPolicy where FilledIPolicy <$> pminmax <*> (toFilled =<< pstd) <*> pspindleRatio <*> pmemoryRatio <*> pvcpuRatio <*> pdiskTemplates +-- | Disk state parameters. +-- +-- As according to the documentation this option is unused by Ganeti, +-- the content is just a 'JSValue'. +type DiskState = Container JSValue + -- * Node definitions $(buildParam "ND" "ndp" @@ -403,17 +414,21 @@ $(buildParam "ND" "ndp" ]) $(buildObject "Node" "node" $ - [ simpleField "name" [t| String |] - , simpleField "primary_ip" [t| String |] - , simpleField "secondary_ip" [t| String |] - , simpleField "master_candidate" [t| Bool |] - , simpleField "offline" [t| Bool |] - , simpleField "drained" [t| Bool |] - , simpleField "group" [t| String |] - , simpleField "master_capable" [t| Bool |] - , simpleField "vm_capable" [t| Bool |] - , simpleField "ndparams" [t| PartialNDParams |] - , simpleField "powered" [t| Bool |] + [ simpleField "name" [t| String |] + , simpleField "primary_ip" [t| String |] + , simpleField "secondary_ip" [t| String |] + , simpleField "master_candidate" [t| Bool |] + , simpleField "offline" [t| Bool |] + , simpleField "drained" [t| Bool |] + , simpleField "group" [t| String |] + , simpleField "master_capable" [t| Bool |] + , simpleField "vm_capable" [t| Bool |] + , simpleField "ndparams" [t| PartialNDParams |] + , simpleField "powered" [t| Bool |] + , defaultField [| emptyContainer |] $ + simpleField "hv_state_static" [t| PartialHvState |] + , defaultField [| emptyContainer |] $ + simpleField "disk_state_static" [t| DiskState |] ] ++ timeStampFields ++ uuidFields @@ -442,13 +457,17 @@ type GroupDiskParams = Container DiskParams type Networks = Container PartialNicParams $(buildObject "NodeGroup" "group" $ - [ simpleField "name" [t| String |] + [ simpleField "name" [t| String |] , defaultField [| [] |] $ simpleField "members" [t| [String] |] - , simpleField "ndparams" [t| PartialNDParams |] - , simpleField "alloc_policy" [t| AllocPolicy |] - , simpleField "ipolicy" [t| PartialIPolicy |] - , simpleField "diskparams" [t| GroupDiskParams |] - , simpleField "networks" [t| Networks |] + , simpleField "ndparams" [t| PartialNDParams |] + , simpleField "alloc_policy" [t| AllocPolicy |] + , simpleField "ipolicy" [t| PartialIPolicy |] + , simpleField "diskparams" [t| GroupDiskParams |] + , simpleField "networks" [t| Networks |] + , defaultField [| emptyContainer |] $ + simpleField "hv_state_static" [t| PartialHvState |] + , defaultField [| emptyContainer |] $ + simpleField "disk_state_static" [t| DiskState |] ] ++ timeStampFields ++ uuidFields @@ -614,18 +633,6 @@ type IAllocatorParams = Container JSValue -- | The master candidate client certificate digests type CandidateCertificates = Container String --- | Disk state parameters. --- --- As according to the documentation this option is unused by Ganeti, --- the content is just a 'JSValue'. -type DiskState = Container JSValue - --- | Hypervisor state parameters. --- --- As according to the documentation this option is unused by Ganeti, --- the content is just a 'JSValue'. -type HypervisorState = Container JSValue - -- * Cluster definitions $(buildObject "Cluster" "cluster" $ [ simpleField "rsahostkeypub" [t| String |] @@ -670,9 +677,9 @@ $(buildObject "Cluster" "cluster" $ , simpleField "prealloc_wipe_disks" [t| Bool |] , simpleField "ipolicy" [t| FilledIPolicy |] , defaultField [| emptyContainer |] $ - simpleField "hv_state_static" [t| HypervisorState |] + simpleField "hv_state_static" [t| FilledHvState |] , defaultField [| emptyContainer |] $ - simpleField "disk_state_static" [t| DiskState |] + simpleField "disk_state_static" [t| DiskState |] , simpleField "enabled_disk_templates" [t| [DiskTemplate] |] , simpleField "candidate_certs" [t| CandidateCertificates |] , simpleField "max_running_jobs" [t| Int |] diff --git a/src/Ganeti/Objects/HvState.hs b/src/Ganeti/Objects/HvState.hs new file mode 100644 index 0000000..de2599f --- /dev/null +++ b/src/Ganeti/Objects/HvState.hs @@ -0,0 +1,60 @@ +{-# LANGUAGE TemplateHaskell, FunctionalDependencies #-} + +{-| Implementation of the Ganeti HvState config object. + +-} + +{- + +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.HvState + ( FilledHvStateParams(..) + , PartialHvStateParams(..) + , allHvStateParamFields + , FilledHvState + , PartialHvState ) where + +import Ganeti.THH +import Ganeti.JSON +import Ganeti.Types + +$(buildParam "HvState" "hvstate" + [ simpleField "cpu_node" [t| Int |] + , simpleField "cpu_total" [t| Int |] + , simpleField "mem_hv" [t| Int |] + , simpleField "mem_node" [t| Int |] + , simpleField "mem_total" [t| Int |] + ]) + +-- | Static filled hypervisor state (hvtype to hvstate mapping) +type FilledHvState = GenericContainer Hypervisor FilledHvStateParams + +-- | Static partial hypervisor state (hvtype to hvstate mapping) +type PartialHvState = GenericContainer Hypervisor PartialHvStateParams diff --git a/test/hs/Test/Ganeti/Objects.hs b/test/hs/Test/Ganeti/Objects.hs index db43835..6d8deef 100644 --- a/test/hs/Test/Ganeti/Objects.hs +++ b/test/hs/Test/Ganeti/Objects.hs @@ -91,14 +91,37 @@ instance Arbitrary (Container DataCollectorConfig) where return GenericContainer { fromContainer = Map.fromList $ zip names configs } +-- FYI: Currently only memory node value is used +instance Arbitrary PartialHvStateParams where + arbitrary = PartialHvStateParams <$> pure Nothing <*> pure Nothing + <*> pure Nothing <*> genMaybe (fromPositive <$> arbitrary) + <*> pure Nothing + +instance Arbitrary PartialHvState where + arbitrary = do + hv_params <- arbitrary + return GenericContainer { + fromContainer = Map.fromList [ hv_params ] } + +-- FYI: Currently only memory node value is used +instance Arbitrary FilledHvStateParams where + arbitrary = FilledHvStateParams <$> pure 0 <*> pure 0 <*> pure 0 + <*> (fromPositive <$> arbitrary) <*> pure 0 + +instance Arbitrary FilledHvState where + arbitrary = do + hv_params <- arbitrary + return GenericContainer { + fromContainer = Map.fromList [ hv_params ] } + $(genArbitrary ''PartialNDParams) instance Arbitrary Node where arbitrary = Node <$> genFQDN <*> genFQDN <*> genFQDN <*> arbitrary <*> arbitrary <*> arbitrary <*> genFQDN <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary - <*> arbitrary <*> arbitrary <*> genFQDN <*> arbitrary - <*> (Set.fromList <$> genTags) + <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary + <*> genFQDN <*> arbitrary <*> (Set.fromList <$> genTags) $(genArbitrary ''BlockDriver) @@ -662,6 +685,8 @@ genNodeGroup = do nic_param_list <- vectorOf num_networks (arbitrary::Gen PartialNicParams) net_map <- pure (GenericContainer . Map.fromList $ zip net_uuid_list nic_param_list) + hv_state <- arbitrary + disk_state <- arbitrary -- timestamp fields ctime <- arbitrary mtime <- arbitrary @@ -669,7 +694,7 @@ genNodeGroup = do serial <- arbitrary tags <- Set.fromList <$> genTags let group = NodeGroup name members ndparams alloc_policy ipolicy diskparams - net_map ctime mtime uuid serial tags + net_map hv_state disk_state ctime mtime uuid serial tags return group instance Arbitrary NodeGroup where diff --git a/test/py/testutils/config_mock.py b/test/py/testutils/config_mock.py index 7ae27bc..7e31cf3 100644 --- a/test/py/testutils/config_mock.py +++ b/test/py/testutils/config_mock.py @@ -64,6 +64,7 @@ def _UpdateIvNames(base_idx, disks): # pylint: disable=R0904 +# pylint: disable=W0102 class ConfigMock(config.ConfigWriter): """A mocked cluster configuration with added methods for easy customization. @@ -109,7 +110,7 @@ class ConfigMock(config.ConfigWriter): ndparams=None, diskparams=None, ipolicy=None, - hv_state_static=None, + hv_state_static={}, disk_state_static=None, alloc_policy=None, networks=None): @@ -160,7 +161,7 @@ class ConfigMock(config.ConfigWriter): ndparams=None, powered=True, hv_state=None, - hv_state_static=None, + hv_state_static={}, disk_state=None, disk_state_static=None): """Add a new L{objects.Node} to the cluster configuration -- 2.6.0.rc2.230.g3dd15c0
