On Tue, Feb 04, 2014 at 05:00:26PM +0100, Santi Raffa wrote:
> This updates objects, constructors and mocks for Instance and Cluster
> objects in Python and Haskell.
>
> Signed-off-by: Santi Raffa <[email protected]>
> ---
> lib/bootstrap.py | 2 +
> lib/config.py | 2 +
> lib/luxi.py | 5 +-
> lib/objects.py | 138
> ++++++++++++++++++++++++------
> src/Ganeti/Config.hs | 2 +-
> src/Ganeti/HTools/Program/Harep.hs | 4 +
> src/Ganeti/Objects.hs | 109 ++++++++++++-----------
> test/data/instance-prim-sec.txt | 1 +
> test/hs/Test/Ganeti/Objects.hs | 7 +-
> test/hs/Test/Ganeti/Query/Instance.hs | 2 +-
> test/py/cmdlib/testsupport/config_mock.py | 5 ++
> test/py/ganeti.config_unittest.py | 4 +-
> test/py/ganeti.ovf_unittest.py | 2 +
> 13 files changed, 202 insertions(+), 81 deletions(-)
>
> diff --git a/lib/bootstrap.py b/lib/bootstrap.py
> index 772134e..2169563 100644
> --- a/lib/bootstrap.py
> +++ b/lib/bootstrap.py
> @@ -786,6 +786,8 @@ def InitCluster(cluster_name, mac_prefix, # pylint:
> disable=R0913, R0914
> disk_state_static=disk_state,
> enabled_disk_templates=enabled_disk_templates,
> candidate_certs=candidate_certs,
> + osparams={},
> + osparams_private_cluster={}
> )
> master_node_config = objects.Node(name=hostname.name,
> primary_ip=hostname.ip,
> diff --git a/lib/config.py b/lib/config.py
> index 67a117c..8db03c2 100644
> --- a/lib/config.py
> +++ b/lib/config.py
> @@ -2506,6 +2506,8 @@ class ConfigWriter(object):
> finally:
> os.close(fd)
>
> + del txt # No need to keep it around.
> +
Don't like this too much. And down here, given that it was last used
up there, makes it even more confusing.
A less worse option is to None after the SafeWriteFile? For example,
try:
fd = utils.SafeWriteFile ... data=txt ...
txt = None
except ...
...
> self.write_count += 1
>
> # and redistribute the config file to master candidates
> diff --git a/lib/luxi.py b/lib/luxi.py
> index 5c69f46..28cdd82 100644
> --- a/lib/luxi.py
> +++ b/lib/luxi.py
> @@ -95,7 +95,10 @@ class Client(cl.AbstractClient):
> return self.CallMethod(REQ_PICKUP_JOB, (job,))
>
> def SubmitJob(self, ops):
> - ops_state = map(lambda op: op.__getstate__(), ops)
> +
Unnecessary newline.
> + ops_state = map(lambda op: op.__getstate__()
> + if not isinstance(op, objects.ConfigObject)
> + else op.ToDict(_with_private=True), ops)
> return self.CallMethod(REQ_SUBMIT_JOB, (ops_state, ))
>
> def SubmitJobToDrainedQueue(self, ops):
> diff --git a/lib/objects.py b/lib/objects.py
> index 2537c39..9a81216 100644
> --- a/lib/objects.py
> +++ b/lib/objects.py
> @@ -47,6 +47,7 @@ from ganeti import constants
> from ganeti import netutils
> from ganeti import outils
> from ganeti import utils
> +from ganeti import serializer
>
> from socket import AF_INET
>
> @@ -213,7 +214,7 @@ class ConfigObject(outils.ValidatedSlots):
>
> """
>
> - def ToDict(self):
> + def ToDict(self, _with_private=False):
> """Convert to a dict holding only standard python types.
Do we need to change Copy() as well?
Copy(self, _with_private=False)
And Disk too?
>
> The generic routine just dumps all of this object's attributes in
> @@ -222,6 +223,15 @@ class ConfigObject(outils.ValidatedSlots):
> which case the object should subclass the function in order to
> make sure all objects returned are only standard python types.
>
> + Private fields can be included or not with the _with_private switch.
> + The actual implementation of this switch is left for those subclassses
> + with private fields to implement.
> +
> + @type _with_private: bool
> + @param _with_private: if True, the object will leak its private fields in
> + the dictionary representation. If False, the values
> + will be replaced with None.
> +
> """
> result = {}
> for name in self.GetAllSlots():
> @@ -333,13 +343,13 @@ class TaggableObject(ConfigObject):
> except KeyError:
> raise errors.TagError("Tag not found")
>
> - def ToDict(self):
> + def ToDict(self, _with_private=False):
> """Taggable-object-specific conversion to standard python types.
>
> This replaces the tags set with a list.
>
> """
> - bo = super(TaggableObject, self).ToDict()
> + bo = super(TaggableObject, self).ToDict(_with_private=_with_private)
>
> tags = bo.get("tags", None)
> if isinstance(tags, set):
> @@ -388,14 +398,14 @@ class ConfigData(ConfigObject):
> "serial_no",
> ] + _TIMESTAMPS
>
> - def ToDict(self):
> + def ToDict(self, _with_private=False):
> """Custom function for top-level config data.
>
> This just replaces the list of instances, nodes and the cluster
> with standard python types.
>
> """
> - mydict = super(ConfigData, self).ToDict()
> + mydict = super(ConfigData, self).ToDict(_with_private=_with_private)
> mydict["cluster"] = mydict["cluster"].ToDict()
> for key in "nodes", "instances", "nodegroups", "networks":
> mydict[key] = outils.ContainerToDicts(mydict[key])
> @@ -1063,6 +1073,7 @@ class Instance(TaggableObject):
> "hvparams",
> "beparams",
> "osparams",
> + "osparams_private",
> "admin_state",
> "nics",
> "disks",
> @@ -1187,14 +1198,18 @@ class Instance(TaggableObject):
> " 0 to %d" % (idx, len(self.disks) - 1),
> errors.ECODE_INVAL)
>
> - def ToDict(self):
> + def ToDict(self, _with_private=False):
> """Instance-specific conversion to standard python types.
>
> This replaces the children lists of objects with lists of standard
> python types.
>
> """
> - bo = super(Instance, self).ToDict()
> +
Unnecessary newline.
> + bo = super(Instance, self).ToDict(_with_private=_with_private)
> +
> + if _with_private:
> + bo["osparams_private"] = self.osparams_private.Unprivate()
>
> for attr in "nics", "disks":
> alist = bo.get(attr, None)
> @@ -1238,6 +1253,8 @@ class Instance(TaggableObject):
> pass
> if self.osparams is None:
> self.osparams = {}
> + if self.osparams_private is None:
> + self.osparams_private = serializer.PrivateDict()
> UpgradeBeParams(self.beparams)
> if self.disks_active is None:
> self.disks_active = self.admin_state == constants.ADMINST_UP
> @@ -1407,11 +1424,11 @@ class Node(TaggableObject):
> if self.powered is None:
> self.powered = True
>
> - def ToDict(self):
> + def ToDict(self, _with_private=False):
> """Custom function for serializing.
>
> """
> - data = super(Node, self).ToDict()
> + data = super(Node, self).ToDict(_with_private=_with_private)
>
> hv_state = data.get("hv_state", None)
> if hv_state is not None:
> @@ -1459,14 +1476,14 @@ class NodeGroup(TaggableObject):
> "networks",
> ] + _TIMESTAMPS + _UUID
>
> - def ToDict(self):
> + def ToDict(self, _with_private=False):
> """Custom function for nodegroup.
>
> This discards the members object, which gets recalculated and is only
> kept
> in memory.
>
> """
> - mydict = super(NodeGroup, self).ToDict()
> + mydict = super(NodeGroup, self).ToDict(_with_private=_with_private)
> del mydict["members"]
> return mydict
>
> @@ -1559,6 +1576,7 @@ class Cluster(TaggableObject):
> "os_hvp",
> "beparams",
> "osparams",
> + "osparams_private_cluster",
> "nicparams",
> "ndparams",
> "diskparams",
> @@ -1600,9 +1618,11 @@ class Cluster(TaggableObject):
> if self.os_hvp is None:
> self.os_hvp = {}
>
> - # osparams added before 2.2
> if self.osparams is None:
> self.osparams = {}
> + # osparams_private_cluster added in 2.12
> + if self.osparams_private_cluster is None:
> + self.osparams_private_cluster = {}
>
> self.ndparams = UpgradeNDParams(self.ndparams)
>
> @@ -1719,12 +1739,18 @@ class Cluster(TaggableObject):
> """
> return self.enabled_hypervisors[0]
>
> - def ToDict(self):
> + def ToDict(self, _with_private=False):
> """Custom function for cluster.
>
> """
> mydict = super(Cluster, self).ToDict()
>
Super call missing _with_private ?
Also shouldn't 'mydict' be 'bo' to be consistent with the others?
Alghout, I don't really know what 'bo' means... :)
Thanks,
Jose
> + # Explicitly save private parameters.
> + if _with_private:
> + for os in mydict["osparams_private_cluster"]:
> + mydict["osparams_private_cluster"][os] = \
> + self.osparams_private_cluster[os].Unprivate()
> +
> if self.tcpudp_port_pool is None:
> tcpudp_port_pool = []
> else:
> @@ -1855,25 +1881,89 @@ class Cluster(TaggableObject):
> """
> return FillDict(self.nicparams.get(constants.PP_DEFAULT, {}), nicparams)
>
> - def SimpleFillOS(self, os_name, os_params):
> + def SimpleFillOS(self, os_name,
> + os_params_public,
> + os_params_private=None,
> + os_params_secret=None):
> """Fill an instance's osparams dict with cluster defaults.
>
> @type os_name: string
> @param os_name: the OS name to use
> - @type os_params: dict
> - @param os_params: the dict to fill with default values
> + @type os_params_public: dict
> + @param os_params_public: the dict to fill with default values
> + @type os_params_private: dict
> + @param os_params_private: the dict with private fields to fill
> + with default values. Not passing this field
> + results in no private fields being added to the
> + return value. Private fields will be wrapped in
> + L{Private} objects.
> + @type os_params_secret: dict
> + @param os_params_secret: the dict with secret fields to fill
> + with default values. Not passing this field
> + results in no secret fields being added to the
> + return value. Private fields will be wrapped in
> + L{Private} objects.
> @rtype: dict
> @return: a copy of the instance's osparams with missing keys filled from
> - the cluster defaults
> + the cluster defaults. Private and secret parameters are not included
> + unless the respective optional parameters are supplied.
>
> """
> name_only = os_name.split("+", 1)[0]
> - # base OS
> - result = self.osparams.get(name_only, {})
> - # OS with variant
> - result = FillDict(result, self.osparams.get(os_name, {}))
> - # specified params
> - return FillDict(result, os_params)
> +
> + defaults_base_public = self.osparams.get(name_only, {})
> + defaults_public = FillDict(defaults_base_public,
> + self.osparams.get(os_name, {}))
> + params_public = FillDict(defaults_public, os_params_public)
> +
> + if os_params_private is not None:
> + defaults_base_private = self.osparams_private_cluster.get(name_only,
> {})
> + defaults_private = FillDict(defaults_base_private,
> + self.osparams_private_cluster.get(os_name,
> + {}))
> + params_private = FillDict(defaults_private, os_params_private)
> + else:
> + params_private = {}
> +
> + if os_params_secret is not None:
> + # There can't be default secret settings, so there's nothing to be
> done.
> + params_secret = os_params_secret
> + else:
> + params_secret = {}
> +
> + # Enforce that the set of keys be distinct:
> + duplicate_keys = utils.GetRepeatedKeys(params_public,
> + params_private,
> + params_secret)
> + if not duplicate_keys:
> +
> + # Actually update them:
> + params_public.update(params_private)
> + params_public.update(params_secret)
> +
> + return params_public
> +
> + else:
> +
> + def formatter(keys):
> + return utils.CommaJoin(sorted(map(repr, keys))) if keys else "(none)"
> +
> + #Lose the values.
> + params_public = set(params_public)
> + params_private = set(params_private)
> + params_secret = set(params_secret)
> +
> + msg = """Cannot assign multiple values to OS parameters.
> +
> + Conflicting OS parameters that would have been set by this operation:
> + - at public visibility: {public}
> + - at private visibility: {private}
> + - at secret visibility: {secret}
> + """.format(dupes=formatter(duplicate_keys),
> + public=formatter(params_public & duplicate_keys),
> + private=formatter(params_private & duplicate_keys),
> + secret=formatter(params_secret & duplicate_keys))
> + raise errors.OpPrereqError(msg)
>
> @staticmethod
> def SimpleFillHvState(hv_state):
> @@ -2061,7 +2151,7 @@ class _QueryResponseBase(ConfigObject):
> "fields",
> ]
>
> - def ToDict(self):
> + def ToDict(self, _with_private=False):
> """Custom function for serializing.
>
> """
> diff --git a/src/Ganeti/Config.hs b/src/Ganeti/Config.hs
> index aa86866..69ed991 100644
> --- a/src/Ganeti/Config.hs
> +++ b/src/Ganeti/Config.hs
> @@ -275,7 +275,7 @@ getFilledInstBeParams cfg inst = do
> return $ fillBeParams parentParams (instBeparams inst)
>
> -- | Retrieves the instance os params, missing values filled with cluster
> --- defaults.
> +-- defaults. This does NOT include private and secret parameters.
> getFilledInstOsParams :: ConfigData -> Instance -> OsParams
> getFilledInstOsParams cfg inst =
> let osLookupName = takeWhile (/= '+') (instOs inst)
> diff --git a/src/Ganeti/HTools/Program/Harep.hs
> b/src/Ganeti/HTools/Program/Harep.hs
> index 0bd2104..933410d 100644
> --- a/src/Ganeti/HTools/Program/Harep.hs
> +++ b/src/Ganeti/HTools/Program/Harep.hs
> @@ -307,6 +307,8 @@ detectBroken nl inst =
> , opInstanceUuid = Nothing
> , opOsType = Nothing
> , opTempOsParams = Nothing
> + , opOsparamsPrivate = Nothing
> + , opOsparamsSecret = Nothing
> , opForceVariant = False
> }
> ])
> @@ -359,6 +361,8 @@ detectBroken nl inst =
> , opInstanceUuid = Nothing
> , opOsType = Nothing
> , opTempOsParams = Nothing
> + , opOsparamsPrivate = Nothing
> + , opOsparamsSecret = Nothing
> , opForceVariant = False
> }
> ])
> diff --git a/src/Ganeti/Objects.hs b/src/Ganeti/Objects.hs
> index d0eba27..68fb0b2 100644
> --- a/src/Ganeti/Objects.hs
> +++ b/src/Ganeti/Objects.hs
> @@ -31,6 +31,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
> MA
> module Ganeti.Objects
> ( HvParams
> , OsParams
> + , OsParamsPrivate
> , PartialNicParams(..)
> , FilledNicParams(..)
> , fillNicParams
> @@ -123,6 +124,7 @@ type HvParams = Container JSValue
> -- container, since the keys are dynamically declared by the OSes, and
> -- the values are always strings.
> type OsParams = Container String
> +type OsParamsPrivate = Container (Private String)
>
> -- | Class of objects that have timestamps.
> class TimeStampObject a where
> @@ -440,18 +442,19 @@ $(buildParam "Be" "bep"
> ])
>
> $(buildObject "Instance" "inst" $
> - [ simpleField "name" [t| String |]
> - , simpleField "primary_node" [t| String |]
> - , simpleField "os" [t| String |]
> - , simpleField "hypervisor" [t| Hypervisor |]
> - , simpleField "hvparams" [t| HvParams |]
> - , simpleField "beparams" [t| PartialBeParams |]
> - , simpleField "osparams" [t| OsParams |]
> - , simpleField "admin_state" [t| AdminState |]
> - , simpleField "nics" [t| [PartialNic] |]
> - , simpleField "disks" [t| [Disk] |]
> - , simpleField "disk_template" [t| DiskTemplate |]
> - , simpleField "disks_active" [t| Bool |]
> + [ simpleField "name" [t| String |]
> + , simpleField "primary_node" [t| String |]
> + , simpleField "os" [t| String |]
> + , simpleField "hypervisor" [t| Hypervisor |]
> + , simpleField "hvparams" [t| HvParams |]
> + , simpleField "beparams" [t| PartialBeParams |]
> + , simpleField "osparams" [t| OsParams |]
> + , simpleField "osparams_private" [t| OsParamsPrivate |]
> + , simpleField "admin_state" [t| AdminState |]
> + , simpleField "nics" [t| [PartialNic] |]
> + , simpleField "disks" [t| [Disk] |]
> + , simpleField "disk_template" [t| DiskTemplate |]
> + , simpleField "disks_active" [t| Bool |]
> , optionalField $ simpleField "network_port" [t| Int |]
> ]
> ++ timeStampFields
> @@ -650,6 +653,7 @@ type ClusterBeParams = Container FilledBeParams
>
> -- | Cluster OsParams.
> type ClusterOsParams = Container OsParams
> +type ClusterOsParamsPrivate = Container (Private OsParams)
>
> -- | Cluster NicParams.
> type ClusterNicParams = Container FilledNicParams
> @@ -665,49 +669,50 @@ type CandidateCertificates = Container String
>
> -- * 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 "nicparams" [t| ClusterNicParams |]
> - , simpleField "ndparams" [t| FilledNDParams |]
> - , simpleField "diskparams" [t| DiskParams |]
> - , 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 "enabled_disk_templates" [t| [DiskTemplate] |]
> - , simpleField "candidate_certs" [t| CandidateCertificates |]
> - , simpleField "max_running_jobs" [t| Int |]
> + 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| DiskParams |]
> + , 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 "enabled_disk_templates" [t| [DiskTemplate] |]
> + , simpleField "candidate_certs" [t| CandidateCertificates |]
> + , simpleField "max_running_jobs" [t| Int |]
> ]
> ++ timeStampFields
> ++ uuidFields
> diff --git a/test/data/instance-prim-sec.txt b/test/data/instance-prim-sec.txt
> index a947dfb..b159439 100644
> --- a/test/data/instance-prim-sec.txt
> +++ b/test/data/instance-prim-sec.txt
> @@ -72,6 +72,7 @@
> ],
> "os": "busybox",
> "osparams": {},
> + "osparams_private": {},
> "primary_node": "60e687a0-21fc-4577-997f-ccd08925fa65",
> "serial_no": 2,
> "uuid": "aec390cb-5eae-44e6-bcc2-ec14d31347f0"
> diff --git a/test/hs/Test/Ganeti/Objects.hs b/test/hs/Test/Ganeti/Objects.hs
> index dbae17f..61debaf 100644
> --- a/test/hs/Test/Ganeti/Objects.hs
> +++ b/test/hs/Test/Ganeti/Objects.hs
> @@ -123,6 +123,8 @@ instance Arbitrary Instance where
> <*> arbitrary
> -- osparams
> <*> pure (GenericContainer Map.empty)
> + -- osparams_private
> + <*> pure (GenericContainer Map.empty)
> -- admin_state
> <*> arbitrary
> -- nics
> @@ -219,6 +221,9 @@ instance Arbitrary ClusterNicParams where
> instance Arbitrary OsParams where
> arbitrary = (GenericContainer . Map.fromList) <$> arbitrary
>
> +instance Arbitrary Objects.ClusterOsParamsPrivate where
> + arbitrary = (GenericContainer . Map.fromList) <$> arbitrary
> +
> instance (Arbitrary a) => Arbitrary (Private a) where
> arbitrary = Private <$> arbitrary
>
> @@ -555,7 +560,7 @@ caseIncludeLogicalIdDrbd :: HUnit.Assertion
> caseIncludeLogicalIdDrbd =
> let vg_name = "xenvg" :: String
> lv_name = "1234sdf-qwef-2134-asff-asd2-23145d.data" :: String
> - d =
> + d =
> Disk
> (LIDDrbd8 "node1.example.com" "node2.example.com" 2000 1 5
> "secret")
> [ Disk (LIDPlain "onevg" "onelv") [] "disk1" 1000 DiskRdWr Nothing
> diff --git a/test/hs/Test/Ganeti/Query/Instance.hs
> b/test/hs/Test/Ganeti/Query/Instance.hs
> index 4c1e7c2..ffd3ea6 100644
> --- a/test/hs/Test/Ganeti/Query/Instance.hs
> +++ b/test/hs/Test/Ganeti/Query/Instance.hs
> @@ -52,7 +52,7 @@ createInstance name pnodeUuid adminState =
> Instance name pnodeUuid "" Kvm
> (GenericContainer Map.empty)
> (PartialBeParams Nothing Nothing Nothing Nothing Nothing Nothing)
> - (GenericContainer Map.empty)
> + (GenericContainer Map.empty) (GenericContainer Map.empty)
> adminState [] [] DTDrbd8 False Nothing epochTime epochTime "" 0 Set.empty
> where epochTime = TOD 0 0
>
> diff --git a/test/py/cmdlib/testsupport/config_mock.py
> b/test/py/cmdlib/testsupport/config_mock.py
> index d485453..669a8e4 100644
> --- a/test/py/cmdlib/testsupport/config_mock.py
> +++ b/test/py/cmdlib/testsupport/config_mock.py
> @@ -181,6 +181,7 @@ class ConfigMock(config.ConfigWriter):
> hvparams=None,
> beparams=None,
> osparams=None,
> + osparams_private=None,
> admin_state=None,
> nics=None,
> disks=None,
> @@ -217,6 +218,8 @@ class ConfigMock(config.ConfigWriter):
> beparams = {}
> if osparams is None:
> osparams = {}
> + if osparams_private is None:
> + osparams_private = {}
> if admin_state is None:
> admin_state = constants.ADMINST_DOWN
> if nics is None:
> @@ -247,6 +250,7 @@ class ConfigMock(config.ConfigWriter):
> hvparams=hvparams,
> beparams=beparams,
> osparams=osparams,
> + osparams_private=osparams_private,
> admin_state=admin_state,
> nics=nics,
> disks=disks,
> @@ -571,6 +575,7 @@ class ConfigMock(config.ConfigWriter):
> os_hvp={self.GetDefaultOs().name: constants.HVC_DEFAULTS.copy()},
> beparams=None,
> osparams=None,
> + osparams_private_cluster=None,
> nicparams={constants.PP_DEFAULT: constants.NICC_DEFAULTS},
> ndparams=None,
> diskparams=None,
> diff --git a/test/py/ganeti.config_unittest.py
> b/test/py/ganeti.config_unittest.py
> index 55918cc..5f341a4 100755
> --- a/test/py/ganeti.config_unittest.py
> +++ b/test/py/ganeti.config_unittest.py
> @@ -35,6 +35,7 @@ from ganeti import objects
> from ganeti import utils
> from ganeti import netutils
> from ganeti import compat
> +from ganeti import serializer
> from ganeti.cmdlib import instance
>
> from ganeti.config import TemporaryReservationManager
> @@ -109,7 +110,8 @@ class TestConfigRunner(unittest.TestCase):
> uuid="test-uuid",
> disks=[], nics=[],
> disk_template=constants.DT_DISKLESS,
> - primary_node=self._get_object().GetMasterNode())
> + primary_node=self._get_object().GetMasterNode(),
> + osparams_private=serializer.PrivateDict())
> return inst
>
> def testEmpty(self):
> diff --git a/test/py/ganeti.ovf_unittest.py b/test/py/ganeti.ovf_unittest.py
> index bc72496..6e2ce40 100755
> --- a/test/py/ganeti.ovf_unittest.py
> +++ b/test/py/ganeti.ovf_unittest.py
> @@ -173,6 +173,7 @@ ARGS_VBOX = dict(ARGS_EXPORT_DIR, **{
> "os": "lenny-image",
> "hypervisor": ("xen-pvm", {}),
> "osparams":{},
> + "osparams_private":{},
> "disks": [],
> })
> ARGS_COMPLETE = dict(ARGS_VBOX, **{
> @@ -188,6 +189,7 @@ ARGS_BROKEN = dict(ARGS_EXPORT_DIR , **{
> "name": "test-instance",
> "os": "lenny-image",
> "osparams": {},
> + "osparams_private":{},
> })
>
> EXP_ARGS_COMPRESSED = dict(ARGS_EXPORT_DIR, **{
> --
> 1.9.0.rc1.175.g0b1dcb5
>
--
Jose Antonio Lopes
Ganeti Engineering
Google Germany GmbH
Dienerstr. 12, 80331, München
Registergericht und -nummer: Hamburg, HRB 86891
Sitz der Gesellschaft: Hamburg
Geschäftsführer: Graham Law, Christine Elizabeth Flores
Steuernummer: 48/725/00206
Umsatzsteueridentifikationsnummer: DE813741370