Revision a2d2e1a7

b/lib/cmdlib.py
32 32
import platform
33 33
import logging
34 34
import copy
35
import itertools
36 35

  
37 36
from ganeti import ssh
38 37
from ganeti import utils
......
323 322
  HTYPE = None
324 323

  
325 324

  
326
class _FieldSet(object):
327
  """A simple field set.
328

  
329
  Among the features are:
330
    - checking if a string is among a list of static string or regex objects
331
    - checking if a whole list of string matches
332
    - returning the matching groups from a regex match
333

  
334
  Internally, all fields are held as regular expression objects.
335

  
336
  """
337
  def __init__(self, *items):
338
    self.items = [re.compile("^%s$" % value) for value in items]
339

  
340
  def Extend(self, other_set):
341
    """Extend the field set with the items from another one"""
342
    self.items.extend(other_set.items)
343

  
344
  def Matches(self, field):
345
    """Checks if a field matches the current set
346

  
347
    @type field: str
348
    @param field: the string to match
349
    @return: either False or a regular expression match object
350

  
351
    """
352
    for m in itertools.ifilter(None, (val.match(field) for val in self.items)):
353
      return m
354
    return False
355

  
356
  def NonMatching(self, items):
357
    """Returns the list of fields not matching the current set
358

  
359
    @type items: list
360
    @param items: the list of fields to check
361
    @rtype: list
362
    @return: list of non-matching fields
363

  
364
    """
365
    return [val for val in items if not self.Matches(val)]
366

  
367

  
368 325
def _GetWantedNodes(lu, nodes):
369 326
  """Returns list of checked and expanded node names.
370 327

  
......
416 373
def _CheckOutputFields(static, dynamic, selected):
417 374
  """Checks whether all selected fields are valid.
418 375

  
419
  @type static: L{_FieldSet}
376
  @type static: L{utils.FieldSet}
420 377
  @param static: static fields set
421
  @type dynamic: L{_FieldSet}
378
  @type dynamic: L{utils.FieldSet}
422 379
  @param dynamic: dynamic fields set
423 380

  
424 381
  """
425
  f = _FieldSet()
382
  f = utils.FieldSet()
426 383
  f.Extend(static)
427 384
  f.Extend(dynamic)
428 385

  
......
1362 1319
  """
1363 1320
  _OP_REQP = ["output_fields", "names"]
1364 1321
  REQ_BGL = False
1365
  _FIELDS_STATIC = _FieldSet()
1366
  _FIELDS_DYNAMIC = _FieldSet("name", "valid", "node_status")
1322
  _FIELDS_STATIC = utils.FieldSet()
1323
  _FIELDS_DYNAMIC = utils.FieldSet("name", "valid", "node_status")
1367 1324

  
1368 1325
  def ExpandNames(self):
1369 1326
    if self.op.names:
......
1518 1475
  """
1519 1476
  _OP_REQP = ["output_fields", "names"]
1520 1477
  REQ_BGL = False
1521
  _FIELDS_DYNAMIC = _FieldSet(
1478
  _FIELDS_DYNAMIC = utils.FieldSet(
1522 1479
    "dtotal", "dfree",
1523 1480
    "mtotal", "mnode", "mfree",
1524 1481
    "bootid",
1525 1482
    "ctotal",
1526 1483
    )
1527 1484

  
1528
  _FIELDS_STATIC = _FieldSet(
1485
  _FIELDS_STATIC = utils.FieldSet(
1529 1486
    "name", "pinst_cnt", "sinst_cnt",
1530 1487
    "pinst_list", "sinst_list",
1531 1488
    "pip", "sip", "tags",
......
1657 1614
  """
1658 1615
  _OP_REQP = ["nodes", "output_fields"]
1659 1616
  REQ_BGL = False
1660
  _FIELDS_DYNAMIC = _FieldSet("phys", "vg", "name", "size", "instance")
1661
  _FIELDS_STATIC = _FieldSet("node")
1617
  _FIELDS_DYNAMIC = utils.FieldSet("phys", "vg", "name", "size", "instance")
1618
  _FIELDS_STATIC = utils.FieldSet("node")
1662 1619

  
1663 1620
  def ExpandNames(self):
1664 1621
    _CheckOutputFields(static=self._FIELDS_STATIC,
......
1979 1936
  """
1980 1937
  _OP_REQP = []
1981 1938
  REQ_BGL = False
1982
  _FIELDS_DYNAMIC = _FieldSet()
1983
  _FIELDS_STATIC = _FieldSet("cluster_name", "master_node", "drain_flag")
1939
  _FIELDS_DYNAMIC = utils.FieldSet()
1940
  _FIELDS_STATIC = utils.FieldSet("cluster_name", "master_node", "drain_flag")
1984 1941

  
1985 1942
  def ExpandNames(self):
1986 1943
    self.needed_locks = {}
......
2714 2671
  """
2715 2672
  _OP_REQP = ["output_fields", "names"]
2716 2673
  REQ_BGL = False
2717
  _FIELDS_STATIC = _FieldSet(*["name", "os", "pnode", "snodes",
2718
                               "admin_state", "admin_ram",
2719
                               "disk_template", "ip", "mac", "bridge",
2720
                               "sda_size", "sdb_size", "vcpus", "tags",
2721
                               "network_port", "beparams",
2722
                               "(disk).(size)/([0-9]+)",
2723
                               "(disk).(sizes)",
2724
                               "(nic).(mac|ip|bridge)/([0-9]+)",
2725
                               "(nic).(macs|ips|bridges)",
2726
                               "(disk|nic).(count)",
2727
                               "serial_no", "hypervisor", "hvparams",] +
2728
                             ["hv/%s" % name
2729
                              for name in constants.HVS_PARAMETERS] +
2730
                             ["be/%s" % name
2731
                              for name in constants.BES_PARAMETERS])
2732
  _FIELDS_DYNAMIC = _FieldSet("oper_state", "oper_ram", "status")
2674
  _FIELDS_STATIC = utils.FieldSet(*["name", "os", "pnode", "snodes",
2675
                                    "admin_state", "admin_ram",
2676
                                    "disk_template", "ip", "mac", "bridge",
2677
                                    "sda_size", "sdb_size", "vcpus", "tags",
2678
                                    "network_port", "beparams",
2679
                                    "(disk).(size)/([0-9]+)",
2680
                                    "(disk).(sizes)",
2681
                                    "(nic).(mac|ip|bridge)/([0-9]+)",
2682
                                    "(nic).(macs|ips|bridges)",
2683
                                    "(disk|nic).(count)",
2684
                                    "serial_no", "hypervisor", "hvparams",] +
2685
                                  ["hv/%s" % name
2686
                                   for name in constants.HVS_PARAMETERS] +
2687
                                  ["be/%s" % name
2688
                                   for name in constants.BES_PARAMETERS])
2689
  _FIELDS_DYNAMIC = utils.FieldSet("oper_state", "oper_ram", "status")
2733 2690

  
2734 2691

  
2735 2692
  def ExpandNames(self):
b/lib/utils.py
1818 1818
    # This is not nice and not absolutely atomic, but it appears to be the only
1819 1819
    # solution in Python -- there are no atomic types.
1820 1820
    self.called = True
1821

  
1822

  
1823
class FieldSet(object):
1824
  """A simple field set.
1825

  
1826
  Among the features are:
1827
    - checking if a string is among a list of static string or regex objects
1828
    - checking if a whole list of string matches
1829
    - returning the matching groups from a regex match
1830

  
1831
  Internally, all fields are held as regular expression objects.
1832

  
1833
  """
1834
  def __init__(self, *items):
1835
    self.items = [re.compile("^%s$" % value) for value in items]
1836

  
1837
  def Extend(self, other_set):
1838
    """Extend the field set with the items from another one"""
1839
    self.items.extend(other_set.items)
1840

  
1841
  def Matches(self, field):
1842
    """Checks if a field matches the current set
1843

  
1844
    @type field: str
1845
    @param field: the string to match
1846
    @return: either False or a regular expression match object
1847

  
1848
    """
1849
    for m in itertools.ifilter(None, (val.match(field) for val in self.items)):
1850
      return m
1851
    return False
1852

  
1853
  def NonMatching(self, items):
1854
    """Returns the list of fields not matching the current set
1855

  
1856
    @type items: list
1857
    @param items: the list of fields to check
1858
    @rtype: list
1859
    @return: list of non-matching fields
1860

  
1861
    """
1862
    return [val for val in items if not self.Matches(val)]
b/test/ganeti.cmdlib_unittest.py
31 31
from ganeti import errors
32 32

  
33 33

  
34
class FieldSetTestCase(unittest.TestCase):
35
  """Test case for FieldSets"""
36

  
37
  def testSimpleMatch(self):
38
    f = cmdlib._FieldSet("a", "b", "c", "def")
39
    self.failUnless(f.Matches("a"))
40
    self.failIf(f.Matches("d"), "Substring matched")
41
    self.failIf(f.Matches("defghi"), "Prefix string matched")
42
    self.failIf(f.NonMatching(["b", "c"]))
43
    self.failIf(f.NonMatching(["a", "b", "c", "def"]))
44
    self.failUnless(f.NonMatching(["a", "d"]))
45

  
46
  def testRegexMatch(self):
47
    f = cmdlib._FieldSet("a", "b([0-9]+)", "c")
48
    self.failUnless(f.Matches("b1"))
49
    self.failUnless(f.Matches("b99"))
50
    self.failIf(f.Matches("b/1"))
51
    self.failIf(f.NonMatching(["b12", "c"]))
52
    self.failUnless(f.NonMatching(["a", "1"]))
53

  
54 34
if __name__ == '__main__':
55 35
  unittest.main()
b/test/ganeti.utils_unittest.py
824 824
    self.assertRaises(AssertionError, utils.MergeTime, (-9999, 0))
825 825

  
826 826

  
827
class FieldSetTestCase(unittest.TestCase):
828
  """Test case for FieldSets"""
829

  
830
  def testSimpleMatch(self):
831
    f = utils.FieldSet("a", "b", "c", "def")
832
    self.failUnless(f.Matches("a"))
833
    self.failIf(f.Matches("d"), "Substring matched")
834
    self.failIf(f.Matches("defghi"), "Prefix string matched")
835
    self.failIf(f.NonMatching(["b", "c"]))
836
    self.failIf(f.NonMatching(["a", "b", "c", "def"]))
837
    self.failUnless(f.NonMatching(["a", "d"]))
838

  
839
  def testRegexMatch(self):
840
    f = utils.FieldSet("a", "b([0-9]+)", "c")
841
    self.failUnless(f.Matches("b1"))
842
    self.failUnless(f.Matches("b99"))
843
    self.failIf(f.Matches("b/1"))
844
    self.failIf(f.NonMatching(["b12", "c"]))
845
    self.failUnless(f.NonMatching(["a", "1"]))
846

  
847

  
827 848
if __name__ == '__main__':
828 849
  unittest.main()

Also available in: Unified diff