X-Git-Url: https://code.grnet.gr/git/ganeti-local/blobdiff_plain/7e8f03e3d9e998eb66cf11d39c970d655b95feda..46d21495a980f667e89f10e4172350fff3af6989:/lib/objects.py diff --git a/lib/objects.py b/lib/objects.py index 2f90ea5..51e13f8 100644 --- a/lib/objects.py +++ b/lib/objects.py @@ -1,7 +1,7 @@ # # -# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Google Inc. +# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 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 @@ -45,7 +45,7 @@ from cStringIO import StringIO from ganeti import errors from ganeti import constants from ganeti import netutils -from ganeti import objectutils +from ganeti import outils from ganeti import utils from socket import AF_INET @@ -193,7 +193,7 @@ def MakeEmptyIPolicy(): ]) -class ConfigObject(objectutils.ValidatedSlots): +class ConfigObject(outils.ValidatedSlots): """A generic config object. It has the following properties: @@ -264,47 +264,6 @@ class ConfigObject(objectutils.ValidatedSlots): obj = cls(**val_str) # pylint: disable=W0142 return obj - @staticmethod - def _ContainerToDicts(container): - """Convert the elements of a container to standard python types. - - This method converts a container with elements derived from - ConfigData to standard python types. If the container is a dict, - we don't touch the keys, only the values. - - """ - if isinstance(container, dict): - ret = dict([(k, v.ToDict()) for k, v in container.iteritems()]) - elif isinstance(container, (list, tuple, set, frozenset)): - ret = [elem.ToDict() for elem in container] - else: - raise TypeError("Invalid type %s passed to _ContainerToDicts" % - type(container)) - return ret - - @staticmethod - def _ContainerFromDicts(source, c_type, e_type): - """Convert a container from standard python types. - - This method converts a container with standard python types to - ConfigData objects. If the container is a dict, we don't touch the - keys, only the values. - - """ - if not isinstance(c_type, type): - raise TypeError("Container type %s passed to _ContainerFromDicts is" - " not a type" % type(c_type)) - if source is None: - source = c_type() - if c_type is dict: - ret = dict([(k, e_type.FromDict(v)) for k, v in source.iteritems()]) - elif c_type in (list, tuple, set, frozenset): - ret = c_type([e_type.FromDict(elem) for elem in source]) - else: - raise TypeError("Invalid container type %s passed to" - " _ContainerFromDicts" % c_type) - return ret - def Copy(self): """Makes a deep copy of the current object and its children. @@ -447,7 +406,7 @@ class ConfigData(ConfigObject): mydict = super(ConfigData, self).ToDict() mydict["cluster"] = mydict["cluster"].ToDict() for key in "nodes", "instances", "nodegroups", "networks": - mydict[key] = self._ContainerToDicts(mydict[key]) + mydict[key] = outils.ContainerToDicts(mydict[key]) return mydict @@ -458,10 +417,12 @@ class ConfigData(ConfigObject): """ obj = super(ConfigData, cls).FromDict(val) obj.cluster = Cluster.FromDict(obj.cluster) - obj.nodes = cls._ContainerFromDicts(obj.nodes, dict, Node) - obj.instances = cls._ContainerFromDicts(obj.instances, dict, Instance) - obj.nodegroups = cls._ContainerFromDicts(obj.nodegroups, dict, NodeGroup) - obj.networks = cls._ContainerFromDicts(obj.networks, dict, Network) + obj.nodes = outils.ContainerFromDicts(obj.nodes, dict, Node) + obj.instances = \ + outils.ContainerFromDicts(obj.instances, dict, Instance) + obj.nodegroups = \ + outils.ContainerFromDicts(obj.nodegroups, dict, NodeGroup) + obj.networks = outils.ContainerFromDicts(obj.networks, dict, Network) return obj def HasAnyDiskOfType(self, dev_type): @@ -771,7 +732,7 @@ class Disk(ConfigObject): for attr in ("children",): alist = bo.get(attr, None) if alist: - bo[attr] = self._ContainerToDicts(alist) + bo[attr] = outils.ContainerToDicts(alist) return bo @classmethod @@ -781,7 +742,7 @@ class Disk(ConfigObject): """ obj = super(Disk, cls).FromDict(val) if obj.children: - obj.children = cls._ContainerFromDicts(obj.children, list, Disk) + obj.children = outils.ContainerFromDicts(obj.children, list, Disk) if obj.logical_id and isinstance(obj.logical_id, list): obj.logical_id = tuple(obj.logical_id) if obj.physical_id and isinstance(obj.physical_id, list): @@ -981,6 +942,9 @@ class InstancePolicy(ConfigObject): """Checks the disk templates for validity. """ + if not disk_templates: + raise errors.ConfigurationError("Instance policy must contain" + + " at least one disk template") wrong = frozenset(disk_templates).difference(constants.DISK_TEMPLATES) if wrong: raise errors.ConfigurationError("Invalid disk template(s) %s" % @@ -1139,7 +1103,7 @@ class Instance(TaggableObject): for attr in "nics", "disks": alist = bo.get(attr, None) if alist: - nlist = self._ContainerToDicts(alist) + nlist = outils.ContainerToDicts(alist) else: nlist = [] bo[attr] = nlist @@ -1158,8 +1122,8 @@ class Instance(TaggableObject): if "admin_up" in val: del val["admin_up"] obj = super(Instance, cls).FromDict(val) - obj.nics = cls._ContainerFromDicts(obj.nics, list, NIC) - obj.disks = cls._ContainerFromDicts(obj.disks, list, Disk) + obj.nics = outils.ContainerFromDicts(obj.nics, list, NIC) + obj.disks = outils.ContainerFromDicts(obj.disks, list, Disk) return obj def UpgradeConfig(self): @@ -1353,12 +1317,12 @@ class Node(TaggableObject): hv_state = data.get("hv_state", None) if hv_state is not None: - data["hv_state"] = self._ContainerToDicts(hv_state) + data["hv_state"] = outils.ContainerToDicts(hv_state) disk_state = data.get("disk_state", None) if disk_state is not None: data["disk_state"] = \ - dict((key, self._ContainerToDicts(value)) + dict((key, outils.ContainerToDicts(value)) for (key, value) in disk_state.items()) return data @@ -1371,11 +1335,12 @@ class Node(TaggableObject): obj = super(Node, cls).FromDict(val) if obj.hv_state is not None: - obj.hv_state = cls._ContainerFromDicts(obj.hv_state, dict, NodeHvState) + obj.hv_state = \ + outils.ContainerFromDicts(obj.hv_state, dict, NodeHvState) if obj.disk_state is not None: obj.disk_state = \ - dict((key, cls._ContainerFromDicts(value, dict, NodeDiskState)) + dict((key, outils.ContainerFromDicts(value, dict, NodeDiskState)) for (key, value) in obj.disk_state.items()) return obj @@ -1616,6 +1581,12 @@ class Cluster(TaggableObject): # we can either make sure to upgrade the ipolicy always, or only # do it in some corner cases (e.g. missing keys); note that this # will break any removal of keys from the ipolicy dict + wrongkeys = frozenset(self.ipolicy.keys()) - constants.IPOLICY_ALL_KEYS + if wrongkeys: + # These keys would be silently removed by FillIPolicy() + msg = ("Cluster instance policy contains spourious keys: %s" % + utils.CommaJoin(wrongkeys)) + raise errors.ConfigurationError(msg) self.ipolicy = FillIPolicy(constants.IPOLICY_DEFAULTS, self.ipolicy) @property @@ -1632,7 +1603,14 @@ class Cluster(TaggableObject): """ mydict = super(Cluster, self).ToDict() - mydict["tcpudp_port_pool"] = list(self.tcpudp_port_pool) + + if self.tcpudp_port_pool is None: + tcpudp_port_pool = [] + else: + tcpudp_port_pool = list(self.tcpudp_port_pool) + + mydict["tcpudp_port_pool"] = tcpudp_port_pool + return mydict @classmethod @@ -1641,8 +1619,12 @@ class Cluster(TaggableObject): """ obj = super(Cluster, cls).FromDict(val) - if not isinstance(obj.tcpudp_port_pool, set): + + if obj.tcpudp_port_pool is None: + obj.tcpudp_port_pool = set() + elif not isinstance(obj.tcpudp_port_pool, set): obj.tcpudp_port_pool = set(obj.tcpudp_port_pool) + return obj def SimpleFillDP(self, diskparams): @@ -1933,7 +1915,7 @@ class _QueryResponseBase(ConfigObject): """ mydict = super(_QueryResponseBase, self).ToDict() - mydict["fields"] = self._ContainerToDicts(mydict["fields"]) + mydict["fields"] = outils.ContainerToDicts(mydict["fields"]) return mydict @classmethod @@ -1942,7 +1924,8 @@ class _QueryResponseBase(ConfigObject): """ obj = super(_QueryResponseBase, cls).FromDict(val) - obj.fields = cls._ContainerFromDicts(obj.fields, list, QueryFieldDefinition) + obj.fields = \ + outils.ContainerFromDicts(obj.fields, list, QueryFieldDefinition) return obj @@ -2053,7 +2036,7 @@ class Network(TaggableObject): result = { "%sNETWORK_NAME" % prefix: self.name, "%sNETWORK_UUID" % prefix: self.uuid, - "%sNETWORK_TAGS" % prefix: " ".join(self.tags), + "%sNETWORK_TAGS" % prefix: " ".join(self.GetTags()), } if self.network: result["%sNETWORK_SUBNET" % prefix] = self.network