X-Git-Url: https://code.grnet.gr/git/ganeti-local/blobdiff_plain/c8fcde472922e4ee664d904e0bf1a583f1d5040d..087ed2edee08da7bd3c4872cabde13c57585ca5a:/lib/objects.py?ds=sidebyside diff --git a/lib/objects.py b/lib/objects.py index 64b4418..e2154db 100644 --- a/lib/objects.py +++ b/lib/objects.py @@ -39,20 +39,22 @@ from ganeti import constants __all__ = ["ConfigObject", "ConfigData", "NIC", "Disk", "Instance", "OS", "Node", "Cluster", "FillDict"] +_TIMESTAMPS = ["ctime", "mtime"] + def FillDict(defaults_dict, custom_dict): - """Basic function to apply settings on top a default dict. + """Basic function to apply settings on top a default dict. - @type defaults_dict: dict - @param defaults_dict: dictionary holding the default values - @type custom_dict: dict - @param custom_dict: dictionary holding customized value - @rtype: dict - @return: dict with the 'full' values + @type defaults_dict: dict + @param defaults_dict: dictionary holding the default values + @type custom_dict: dict + @param custom_dict: dictionary holding customized value + @rtype: dict + @return: dict with the 'full' values - """ - ret_dict = copy.deepcopy(defaults_dict) - ret_dict.update(custom_dict) - return ret_dict + """ + ret_dict = copy.deepcopy(defaults_dict) + ret_dict.update(custom_dict) + return ret_dict def UpgradeGroupedParams(target, defaults): @@ -98,18 +100,6 @@ class ConfigObject(object): (type(self).__name__, name)) return None - def __setitem__(self, key, value): - if key not in self.__slots__: - raise KeyError(key) - setattr(self, key, value) - - def __getstate__(self): - state = {} - for name in self.__slots__: - if hasattr(self, name): - state[name] = getattr(self, name) - return state - def __setstate__(self, state): for name in state: if name in self.__slots__: @@ -125,7 +115,14 @@ class ConfigObject(object): make sure all objects returned are only standard python types. """ - return dict([(k, getattr(self, k, None)) for k in self.__slots__]) + result = {} + for name in self.__slots__: + value = getattr(self, name, None) + if value is not None: + result[name] = value + return result + + __getstate__ = ToDict @classmethod def FromDict(cls, val): @@ -186,6 +183,14 @@ class ConfigObject(object): " _ContainerFromDicts" % c_type) return ret + def Copy(self): + """Makes a deep copy of the current object and its children. + + """ + dict_form = self.ToDict() + clone_obj = self.__class__.FromDict(dict_form) + return clone_obj + def __repr__(self): """Implement __repr__ for ConfigObjects.""" return repr(self.ToDict()) @@ -280,7 +285,8 @@ class TaggableObject(ConfigObject): class ConfigData(ConfigObject): """Top-level config object.""" - __slots__ = ["version", "cluster", "nodes", "instances", "serial_no"] + __slots__ = (["version", "cluster", "nodes", "instances", "serial_no"] + + _TIMESTAMPS) def ToDict(self): """Custom function for top-level config data. @@ -310,7 +316,7 @@ class ConfigData(ConfigObject): class NIC(ConfigObject): """Config object representing a network card.""" - __slots__ = ["mac", "ip", "bridge"] + __slots__ = ["mac", "ip", "bridge", "nicparams"] @classmethod def CheckParameterSyntax(cls, nicparams): @@ -330,6 +336,20 @@ class NIC(ConfigObject): err = "Missing bridged nic link" raise errors.ConfigurationError(err) + def UpgradeConfig(self): + """Fill defaults for missing configuration values. + + """ + if self.nicparams is None: + self.nicparams = {} + if self.bridge is not None: + self.nicparams[constants.NIC_MODE] = constants.NIC_MODE_BRIDGED + self.nicparams[constants.NIC_LINK] = self.bridge + # bridge is no longer used it 2.1. The slot is left there to support + # upgrading, but will be removed in 2.2 + if self.bridge is not None: + self.bridge = None + class Disk(ConfigObject): """Config object representing a block device.""" @@ -448,6 +468,15 @@ class Disk(ConfigObject): raise errors.ProgrammerError("Disk.RecordGrow called for unsupported" " disk type %s" % self.dev_type) + def UnsetSize(self): + """Sets recursively the size to zero for the disk and its children. + + """ + if self.children: + for child in self.children: + child.UnsetSize() + self.size = 0 + def SetPhysicalID(self, target_node, nodes_ip): """Convert the logical ID to the physical ID. @@ -564,10 +593,10 @@ class Disk(ConfigObject): """Checks that this disk is correctly configured. """ - errors = [] + all_errors = [] if self.mode not in constants.DISK_ACCESS_SET: - errors.append("Disk access mode '%s' is invalid" % (self.mode, )) - return errors + all_errors.append("Disk access mode '%s' is invalid" % (self.mode, )) + return all_errors class Instance(TaggableObject): @@ -585,7 +614,7 @@ class Instance(TaggableObject): "disk_template", "network_port", "serial_no", - ] + ] + _TIMESTAMPS def _ComputeSecondaryNodes(self): """Compute the list of secondary nodes. @@ -724,7 +753,6 @@ class OS(ConfigObject): __slots__ = [ "name", "path", - "status", "api_versions", "create_script", "export_script", @@ -732,25 +760,6 @@ class OS(ConfigObject): "rename_script", ] - @classmethod - def FromInvalidOS(cls, err): - """Create an OS from an InvalidOS error. - - This routine knows how to convert an InvalidOS error to an OS - object representing the broken OS with a meaningful error message. - - """ - if not isinstance(err, errors.InvalidOS): - raise errors.ProgrammerError("Trying to initialize an OS from an" - " invalid object of type %s" % type(err)) - - return cls(name=err.args[0], path=err.args[1], status=err.args[2]) - - def __nonzero__(self): - return self.status == constants.OS_VALID_STATUS - - __bool__ = __nonzero__ - class Node(TaggableObject): """Config object representing a node.""" @@ -762,7 +771,7 @@ class Node(TaggableObject): "master_candidate", "offline", "drained", - ] + ] + _TIMESTAMPS class Cluster(TaggableObject): @@ -787,7 +796,7 @@ class Cluster(TaggableObject): "nicparams", "candidate_pool_size", "modify_etc_hosts", - ] + ] + _TIMESTAMPS def UpgradeConfig(self): """Fill defaults for missing configuration values. @@ -812,6 +821,18 @@ class Cluster(TaggableObject): if self.modify_etc_hosts is None: self.modify_etc_hosts = True + # default_bridge is no longer used it 2.1. The slot is left there to + # support auto-upgrading, but will be removed in 2.2 + if self.default_bridge is not None: + self.default_bridge = None + + # default_hypervisor is just the first enabled one in 2.1 + if self.default_hypervisor is not None: + self.enabled_hypervisors = ([self.default_hypervisor] + + [hvname for hvname in self.enabled_hypervisors + if hvname != self.default_hypervisor]) + self.default_hypervisor = None + def ToDict(self): """Custom function for cluster. @@ -833,7 +854,7 @@ class Cluster(TaggableObject): def FillHV(self, instance): """Fill an instance's hvparams dict. - @type instance: object + @type instance: L{objects.Instance} @param instance: the instance parameter to fill @rtype: dict @return: a copy of the instance's hvparams with missing keys filled from @@ -846,7 +867,7 @@ class Cluster(TaggableObject): def FillBE(self, instance): """Fill an instance's beparams dict. - @type instance: object + @type instance: L{objects.Instance} @param instance: the instance parameter to fill @rtype: dict @return: a copy of the instance's beparams with missing keys filled from @@ -857,6 +878,53 @@ class Cluster(TaggableObject): instance.beparams) +class BlockDevStatus(ConfigObject): + """Config object representing the status of a block device.""" + __slots__ = [ + "dev_path", + "major", + "minor", + "sync_percent", + "estimated_time", + "is_degraded", + "ldisk_status", + ] + + +class ConfdRequest(ConfigObject): + """Object holding a confd request. + + @ivar protocol: confd protocol version + @ivar type: confd query type + @ivar query: query request + @ivar rsalt: requested reply salt + + """ + __slots__ = [ + "protocol", + "type", + "query", + "rsalt", + ] + + +class ConfdReply(ConfigObject): + """Object holding a confd reply. + + @ivar protocol: confd protocol version + @ivar status: reply status code (ok, error) + @ivar answer: confd query reply + @ivar serial: configuration serial number + + """ + __slots__ = [ + "protocol", + "status", + "answer", + "serial", + ] + + class SerializableConfigParser(ConfigParser.SafeConfigParser): """Simple wrapper over ConfigParse that allows serialization.