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