Revision a5efec93 lib/objects.py
b/lib/objects.py | ||
---|---|---|
47 | 47 |
from ganeti import netutils |
48 | 48 |
from ganeti import outils |
49 | 49 |
from ganeti import utils |
50 |
from ganeti import serializer |
|
50 | 51 |
|
51 | 52 |
from socket import AF_INET |
52 | 53 |
|
... | ... | |
213 | 214 |
|
214 | 215 |
""" |
215 | 216 |
|
216 |
def ToDict(self): |
|
217 |
def ToDict(self, _with_private=False):
|
|
217 | 218 |
"""Convert to a dict holding only standard python types. |
218 | 219 |
|
219 | 220 |
The generic routine just dumps all of this object's attributes in |
... | ... | |
222 | 223 |
which case the object should subclass the function in order to |
223 | 224 |
make sure all objects returned are only standard python types. |
224 | 225 |
|
226 |
Private fields can be included or not with the _with_private switch. |
|
227 |
The actual implementation of this switch is left for those subclassses |
|
228 |
with private fields to implement. |
|
229 |
|
|
230 |
@type _with_private: bool |
|
231 |
@param _with_private: if True, the object will leak its private fields in |
|
232 |
the dictionary representation. If False, the values |
|
233 |
will be replaced with None. |
|
234 |
|
|
225 | 235 |
""" |
226 | 236 |
result = {} |
227 | 237 |
for name in self.GetAllSlots(): |
... | ... | |
333 | 343 |
except KeyError: |
334 | 344 |
raise errors.TagError("Tag not found") |
335 | 345 |
|
336 |
def ToDict(self): |
|
346 |
def ToDict(self, _with_private=False):
|
|
337 | 347 |
"""Taggable-object-specific conversion to standard python types. |
338 | 348 |
|
339 | 349 |
This replaces the tags set with a list. |
340 | 350 |
|
341 | 351 |
""" |
342 |
bo = super(TaggableObject, self).ToDict() |
|
352 |
bo = super(TaggableObject, self).ToDict(_with_private=_with_private)
|
|
343 | 353 |
|
344 | 354 |
tags = bo.get("tags", None) |
345 | 355 |
if isinstance(tags, set): |
... | ... | |
388 | 398 |
"serial_no", |
389 | 399 |
] + _TIMESTAMPS |
390 | 400 |
|
391 |
def ToDict(self): |
|
401 |
def ToDict(self, _with_private=False):
|
|
392 | 402 |
"""Custom function for top-level config data. |
393 | 403 |
|
394 | 404 |
This just replaces the list of instances, nodes and the cluster |
395 | 405 |
with standard python types. |
396 | 406 |
|
397 | 407 |
""" |
398 |
mydict = super(ConfigData, self).ToDict() |
|
408 |
mydict = super(ConfigData, self).ToDict(_with_private=_with_private)
|
|
399 | 409 |
mydict["cluster"] = mydict["cluster"].ToDict() |
400 | 410 |
for key in "nodes", "instances", "nodegroups", "networks": |
401 | 411 |
mydict[key] = outils.ContainerToDicts(mydict[key]) |
... | ... | |
746 | 756 |
self.dynamic_params = dyn_disk_params |
747 | 757 |
|
748 | 758 |
# pylint: disable=W0221 |
749 |
def ToDict(self, include_dynamic_params=False): |
|
759 |
def ToDict(self, include_dynamic_params=False, |
|
760 |
_with_private=False): |
|
750 | 761 |
"""Disk-specific conversion to standard python types. |
751 | 762 |
|
752 | 763 |
This replaces the children lists of objects with lists of |
... | ... | |
1063 | 1074 |
"hvparams", |
1064 | 1075 |
"beparams", |
1065 | 1076 |
"osparams", |
1077 |
"osparams_private", |
|
1066 | 1078 |
"admin_state", |
1067 | 1079 |
"nics", |
1068 | 1080 |
"disks", |
... | ... | |
1187 | 1199 |
" 0 to %d" % (idx, len(self.disks) - 1), |
1188 | 1200 |
errors.ECODE_INVAL) |
1189 | 1201 |
|
1190 |
def ToDict(self): |
|
1202 |
def ToDict(self, _with_private=False):
|
|
1191 | 1203 |
"""Instance-specific conversion to standard python types. |
1192 | 1204 |
|
1193 | 1205 |
This replaces the children lists of objects with lists of standard |
1194 | 1206 |
python types. |
1195 | 1207 |
|
1196 | 1208 |
""" |
1197 |
bo = super(Instance, self).ToDict() |
|
1209 |
bo = super(Instance, self).ToDict(_with_private=_with_private) |
|
1210 |
|
|
1211 |
if _with_private: |
|
1212 |
bo["osparams_private"] = self.osparams_private.Unprivate() |
|
1198 | 1213 |
|
1199 | 1214 |
for attr in "nics", "disks": |
1200 | 1215 |
alist = bo.get(attr, None) |
... | ... | |
1238 | 1253 |
pass |
1239 | 1254 |
if self.osparams is None: |
1240 | 1255 |
self.osparams = {} |
1256 |
if self.osparams_private is None: |
|
1257 |
self.osparams_private = serializer.PrivateDict() |
|
1241 | 1258 |
UpgradeBeParams(self.beparams) |
1242 | 1259 |
if self.disks_active is None: |
1243 | 1260 |
self.disks_active = self.admin_state == constants.ADMINST_UP |
... | ... | |
1407 | 1424 |
if self.powered is None: |
1408 | 1425 |
self.powered = True |
1409 | 1426 |
|
1410 |
def ToDict(self): |
|
1427 |
def ToDict(self, _with_private=False):
|
|
1411 | 1428 |
"""Custom function for serializing. |
1412 | 1429 |
|
1413 | 1430 |
""" |
1414 |
data = super(Node, self).ToDict() |
|
1431 |
data = super(Node, self).ToDict(_with_private=_with_private)
|
|
1415 | 1432 |
|
1416 | 1433 |
hv_state = data.get("hv_state", None) |
1417 | 1434 |
if hv_state is not None: |
... | ... | |
1459 | 1476 |
"networks", |
1460 | 1477 |
] + _TIMESTAMPS + _UUID |
1461 | 1478 |
|
1462 |
def ToDict(self): |
|
1479 |
def ToDict(self, _with_private=False):
|
|
1463 | 1480 |
"""Custom function for nodegroup. |
1464 | 1481 |
|
1465 | 1482 |
This discards the members object, which gets recalculated and is only kept |
1466 | 1483 |
in memory. |
1467 | 1484 |
|
1468 | 1485 |
""" |
1469 |
mydict = super(NodeGroup, self).ToDict() |
|
1486 |
mydict = super(NodeGroup, self).ToDict(_with_private=_with_private)
|
|
1470 | 1487 |
del mydict["members"] |
1471 | 1488 |
return mydict |
1472 | 1489 |
|
... | ... | |
1559 | 1576 |
"os_hvp", |
1560 | 1577 |
"beparams", |
1561 | 1578 |
"osparams", |
1579 |
"osparams_private_cluster", |
|
1562 | 1580 |
"nicparams", |
1563 | 1581 |
"ndparams", |
1564 | 1582 |
"diskparams", |
... | ... | |
1600 | 1618 |
if self.os_hvp is None: |
1601 | 1619 |
self.os_hvp = {} |
1602 | 1620 |
|
1603 |
# osparams added before 2.2 |
|
1604 | 1621 |
if self.osparams is None: |
1605 | 1622 |
self.osparams = {} |
1623 |
# osparams_private_cluster added in 2.12 |
|
1624 |
if self.osparams_private_cluster is None: |
|
1625 |
self.osparams_private_cluster = {} |
|
1606 | 1626 |
|
1607 | 1627 |
self.ndparams = UpgradeNDParams(self.ndparams) |
1608 | 1628 |
|
... | ... | |
1719 | 1739 |
""" |
1720 | 1740 |
return self.enabled_hypervisors[0] |
1721 | 1741 |
|
1722 |
def ToDict(self): |
|
1742 |
def ToDict(self, _with_private=False):
|
|
1723 | 1743 |
"""Custom function for cluster. |
1724 | 1744 |
|
1725 | 1745 |
""" |
1726 |
mydict = super(Cluster, self).ToDict() |
|
1746 |
mydict = super(Cluster, self).ToDict(_with_private=_with_private) |
|
1747 |
|
|
1748 |
# Explicitly save private parameters. |
|
1749 |
if _with_private: |
|
1750 |
for os in mydict["osparams_private_cluster"]: |
|
1751 |
mydict["osparams_private_cluster"][os] = \ |
|
1752 |
self.osparams_private_cluster[os].Unprivate() |
|
1727 | 1753 |
|
1728 | 1754 |
if self.tcpudp_port_pool is None: |
1729 | 1755 |
tcpudp_port_pool = [] |
... | ... | |
1855 | 1881 |
""" |
1856 | 1882 |
return FillDict(self.nicparams.get(constants.PP_DEFAULT, {}), nicparams) |
1857 | 1883 |
|
1858 |
def SimpleFillOS(self, os_name, os_params): |
|
1884 |
def SimpleFillOS(self, os_name, |
|
1885 |
os_params_public, |
|
1886 |
os_params_private=None, |
|
1887 |
os_params_secret=None): |
|
1859 | 1888 |
"""Fill an instance's osparams dict with cluster defaults. |
1860 | 1889 |
|
1861 | 1890 |
@type os_name: string |
1862 | 1891 |
@param os_name: the OS name to use |
1863 |
@type os_params: dict |
|
1864 |
@param os_params: the dict to fill with default values |
|
1892 |
@type os_params_public: dict |
|
1893 |
@param os_params_public: the dict to fill with default values |
|
1894 |
@type os_params_private: dict |
|
1895 |
@param os_params_private: the dict with private fields to fill |
|
1896 |
with default values. Not passing this field |
|
1897 |
results in no private fields being added to the |
|
1898 |
return value. Private fields will be wrapped in |
|
1899 |
L{Private} objects. |
|
1900 |
@type os_params_secret: dict |
|
1901 |
@param os_params_secret: the dict with secret fields to fill |
|
1902 |
with default values. Not passing this field |
|
1903 |
results in no secret fields being added to the |
|
1904 |
return value. Private fields will be wrapped in |
|
1905 |
L{Private} objects. |
|
1865 | 1906 |
@rtype: dict |
1866 | 1907 |
@return: a copy of the instance's osparams with missing keys filled from |
1867 |
the cluster defaults |
|
1908 |
the cluster defaults. Private and secret parameters are not included |
|
1909 |
unless the respective optional parameters are supplied. |
|
1868 | 1910 |
|
1869 | 1911 |
""" |
1870 | 1912 |
name_only = os_name.split("+", 1)[0] |
1871 |
# base OS |
|
1872 |
result = self.osparams.get(name_only, {}) |
|
1873 |
# OS with variant |
|
1874 |
result = FillDict(result, self.osparams.get(os_name, {})) |
|
1875 |
# specified params |
|
1876 |
return FillDict(result, os_params) |
|
1913 |
|
|
1914 |
defaults_base_public = self.osparams.get(name_only, {}) |
|
1915 |
defaults_public = FillDict(defaults_base_public, |
|
1916 |
self.osparams.get(os_name, {})) |
|
1917 |
params_public = FillDict(defaults_public, os_params_public) |
|
1918 |
|
|
1919 |
if os_params_private is not None: |
|
1920 |
defaults_base_private = self.osparams_private_cluster.get(name_only, {}) |
|
1921 |
defaults_private = FillDict(defaults_base_private, |
|
1922 |
self.osparams_private_cluster.get(os_name, |
|
1923 |
{})) |
|
1924 |
params_private = FillDict(defaults_private, os_params_private) |
|
1925 |
else: |
|
1926 |
params_private = {} |
|
1927 |
|
|
1928 |
if os_params_secret is not None: |
|
1929 |
# There can't be default secret settings, so there's nothing to be done. |
|
1930 |
params_secret = os_params_secret |
|
1931 |
else: |
|
1932 |
params_secret = {} |
|
1933 |
|
|
1934 |
# Enforce that the set of keys be distinct: |
|
1935 |
duplicate_keys = utils.GetRepeatedKeys(params_public, |
|
1936 |
params_private, |
|
1937 |
params_secret) |
|
1938 |
if not duplicate_keys: |
|
1939 |
|
|
1940 |
# Actually update them: |
|
1941 |
params_public.update(params_private) |
|
1942 |
params_public.update(params_secret) |
|
1943 |
|
|
1944 |
return params_public |
|
1945 |
|
|
1946 |
else: |
|
1947 |
|
|
1948 |
def formatter(keys): |
|
1949 |
return utils.CommaJoin(sorted(map(repr, keys))) if keys else "(none)" |
|
1950 |
|
|
1951 |
#Lose the values. |
|
1952 |
params_public = set(params_public) |
|
1953 |
params_private = set(params_private) |
|
1954 |
params_secret = set(params_secret) |
|
1955 |
|
|
1956 |
msg = """Cannot assign multiple values to OS parameters. |
|
1957 |
|
|
1958 |
Conflicting OS parameters that would have been set by this operation: |
|
1959 |
- at public visibility: {public} |
|
1960 |
- at private visibility: {private} |
|
1961 |
- at secret visibility: {secret} |
|
1962 |
""".format(dupes=formatter(duplicate_keys), |
|
1963 |
public=formatter(params_public & duplicate_keys), |
|
1964 |
private=formatter(params_private & duplicate_keys), |
|
1965 |
secret=formatter(params_secret & duplicate_keys)) |
|
1966 |
raise errors.OpPrereqError(msg) |
|
1877 | 1967 |
|
1878 | 1968 |
@staticmethod |
1879 | 1969 |
def SimpleFillHvState(hv_state): |
... | ... | |
2061 | 2151 |
"fields", |
2062 | 2152 |
] |
2063 | 2153 |
|
2064 |
def ToDict(self): |
|
2154 |
def ToDict(self, _with_private=False):
|
|
2065 | 2155 |
"""Custom function for serializing. |
2066 | 2156 |
|
2067 | 2157 |
""" |
Also available in: Unified diff