Statistics
| Branch: | Tag: | Revision:

root / lib / utils / __init__.py @ 7ebd876f

History | View | Annotate | Download (21.7 kB)

1
#
2
#
3

    
4
# Copyright (C) 2006, 2007, 2010, 2011 Google Inc.
5
#
6
# This program is free software; you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation; either version 2 of the License, or
9
# (at your option) any later version.
10
#
11
# This program is distributed in the hope that it will be useful, but
12
# WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
# General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with this program; if not, write to the Free Software
18
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
# 02110-1301, USA.
20

    
21

    
22
"""Ganeti utility module.
23

24
This module holds functions that can be used in both daemons (all) and
25
the command line scripts.
26

27
"""
28

    
29

    
30
import os
31
import sys
32
import time
33
import subprocess
34
import re
35
import socket
36
import tempfile
37
import shutil
38
import errno
39
import pwd
40
import itertools
41
import select
42
import fcntl
43
import resource
44
import logging
45
import signal
46
import datetime
47
import calendar
48

    
49
from cStringIO import StringIO
50

    
51
from ganeti import errors
52
from ganeti import constants
53
from ganeti import compat
54

    
55
from ganeti.utils.algo import * # pylint: disable-msg=W0401
56
from ganeti.utils.retry import * # pylint: disable-msg=W0401
57
from ganeti.utils.text import * # pylint: disable-msg=W0401
58
from ganeti.utils.mlock import * # pylint: disable-msg=W0401
59
from ganeti.utils.log import * # pylint: disable-msg=W0401
60
from ganeti.utils.hash import * # pylint: disable-msg=W0401
61
from ganeti.utils.wrapper import * # pylint: disable-msg=W0401
62
from ganeti.utils.filelock import * # pylint: disable-msg=W0401
63
from ganeti.utils.io import * # pylint: disable-msg=W0401
64
from ganeti.utils.x509 import * # pylint: disable-msg=W0401
65
from ganeti.utils.nodesetup import * # pylint: disable-msg=W0401
66
from ganeti.utils.process import * # pylint: disable-msg=W0401
67

    
68

    
69
_RANDOM_UUID_FILE = "/proc/sys/kernel/random/uuid"
70

    
71
_VALID_SERVICE_NAME_RE = re.compile("^[-_.a-zA-Z0-9]{1,128}$")
72

    
73
UUID_RE = re.compile('^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-'
74
                     '[a-f0-9]{4}-[a-f0-9]{12}$')
75

    
76

    
77
def ForceDictType(target, key_types, allowed_values=None):
78
  """Force the values of a dict to have certain types.
79

80
  @type target: dict
81
  @param target: the dict to update
82
  @type key_types: dict
83
  @param key_types: dict mapping target dict keys to types
84
                    in constants.ENFORCEABLE_TYPES
85
  @type allowed_values: list
86
  @keyword allowed_values: list of specially allowed values
87

88
  """
89
  if allowed_values is None:
90
    allowed_values = []
91

    
92
  if not isinstance(target, dict):
93
    msg = "Expected dictionary, got '%s'" % target
94
    raise errors.TypeEnforcementError(msg)
95

    
96
  for key in target:
97
    if key not in key_types:
98
      msg = "Unknown key '%s'" % key
99
      raise errors.TypeEnforcementError(msg)
100

    
101
    if target[key] in allowed_values:
102
      continue
103

    
104
    ktype = key_types[key]
105
    if ktype not in constants.ENFORCEABLE_TYPES:
106
      msg = "'%s' has non-enforceable type %s" % (key, ktype)
107
      raise errors.ProgrammerError(msg)
108

    
109
    if ktype in (constants.VTYPE_STRING, constants.VTYPE_MAYBE_STRING):
110
      if target[key] is None and ktype == constants.VTYPE_MAYBE_STRING:
111
        pass
112
      elif not isinstance(target[key], basestring):
113
        if isinstance(target[key], bool) and not target[key]:
114
          target[key] = ''
115
        else:
116
          msg = "'%s' (value %s) is not a valid string" % (key, target[key])
117
          raise errors.TypeEnforcementError(msg)
118
    elif ktype == constants.VTYPE_BOOL:
119
      if isinstance(target[key], basestring) and target[key]:
120
        if target[key].lower() == constants.VALUE_FALSE:
121
          target[key] = False
122
        elif target[key].lower() == constants.VALUE_TRUE:
123
          target[key] = True
124
        else:
125
          msg = "'%s' (value %s) is not a valid boolean" % (key, target[key])
126
          raise errors.TypeEnforcementError(msg)
127
      elif target[key]:
128
        target[key] = True
129
      else:
130
        target[key] = False
131
    elif ktype == constants.VTYPE_SIZE:
132
      try:
133
        target[key] = ParseUnit(target[key])
134
      except errors.UnitParseError, err:
135
        msg = "'%s' (value %s) is not a valid size. error: %s" % \
136
              (key, target[key], err)
137
        raise errors.TypeEnforcementError(msg)
138
    elif ktype == constants.VTYPE_INT:
139
      try:
140
        target[key] = int(target[key])
141
      except (ValueError, TypeError):
142
        msg = "'%s' (value %s) is not a valid integer" % (key, target[key])
143
        raise errors.TypeEnforcementError(msg)
144

    
145

    
146
def ValidateServiceName(name):
147
  """Validate the given service name.
148

149
  @type name: number or string
150
  @param name: Service name or port specification
151

152
  """
153
  try:
154
    numport = int(name)
155
  except (ValueError, TypeError):
156
    # Non-numeric service name
157
    valid = _VALID_SERVICE_NAME_RE.match(name)
158
  else:
159
    # Numeric port (protocols other than TCP or UDP might need adjustments
160
    # here)
161
    valid = (numport >= 0 and numport < (1 << 16))
162

    
163
  if not valid:
164
    raise errors.OpPrereqError("Invalid service name '%s'" % name,
165
                               errors.ECODE_INVAL)
166

    
167
  return name
168

    
169

    
170
def ListVolumeGroups():
171
  """List volume groups and their size
172

173
  @rtype: dict
174
  @return:
175
       Dictionary with keys volume name and values
176
       the size of the volume
177

178
  """
179
  command = "vgs --noheadings --units m --nosuffix -o name,size"
180
  result = RunCmd(command)
181
  retval = {}
182
  if result.failed:
183
    return retval
184

    
185
  for line in result.stdout.splitlines():
186
    try:
187
      name, size = line.split()
188
      size = int(float(size))
189
    except (IndexError, ValueError), err:
190
      logging.error("Invalid output from vgs (%s): %s", err, line)
191
      continue
192

    
193
    retval[name] = size
194

    
195
  return retval
196

    
197

    
198
def BridgeExists(bridge):
199
  """Check whether the given bridge exists in the system
200

201
  @type bridge: str
202
  @param bridge: the bridge name to check
203
  @rtype: boolean
204
  @return: True if it does
205

206
  """
207
  return os.path.isdir("/sys/class/net/%s/bridge" % bridge)
208

    
209

    
210
def TryConvert(fn, val):
211
  """Try to convert a value ignoring errors.
212

213
  This function tries to apply function I{fn} to I{val}. If no
214
  C{ValueError} or C{TypeError} exceptions are raised, it will return
215
  the result, else it will return the original value. Any other
216
  exceptions are propagated to the caller.
217

218
  @type fn: callable
219
  @param fn: function to apply to the value
220
  @param val: the value to be converted
221
  @return: The converted value if the conversion was successful,
222
      otherwise the original value.
223

224
  """
225
  try:
226
    nv = fn(val)
227
  except (ValueError, TypeError):
228
    nv = val
229
  return nv
230

    
231

    
232
def ParseCpuMask(cpu_mask):
233
  """Parse a CPU mask definition and return the list of CPU IDs.
234

235
  CPU mask format: comma-separated list of CPU IDs
236
  or dash-separated ID ranges
237
  Example: "0-2,5" -> "0,1,2,5"
238

239
  @type cpu_mask: str
240
  @param cpu_mask: CPU mask definition
241
  @rtype: list of int
242
  @return: list of CPU IDs
243

244
  """
245
  if not cpu_mask:
246
    return []
247
  cpu_list = []
248
  for range_def in cpu_mask.split(","):
249
    boundaries = range_def.split("-")
250
    n_elements = len(boundaries)
251
    if n_elements > 2:
252
      raise errors.ParseError("Invalid CPU ID range definition"
253
                              " (only one hyphen allowed): %s" % range_def)
254
    try:
255
      lower = int(boundaries[0])
256
    except (ValueError, TypeError), err:
257
      raise errors.ParseError("Invalid CPU ID value for lower boundary of"
258
                              " CPU ID range: %s" % str(err))
259
    try:
260
      higher = int(boundaries[-1])
261
    except (ValueError, TypeError), err:
262
      raise errors.ParseError("Invalid CPU ID value for higher boundary of"
263
                              " CPU ID range: %s" % str(err))
264
    if lower > higher:
265
      raise errors.ParseError("Invalid CPU ID range definition"
266
                              " (%d > %d): %s" % (lower, higher, range_def))
267
    cpu_list.extend(range(lower, higher + 1))
268
  return cpu_list
269

    
270

    
271
def GetHomeDir(user, default=None):
272
  """Try to get the homedir of the given user.
273

274
  The user can be passed either as a string (denoting the name) or as
275
  an integer (denoting the user id). If the user is not found, the
276
  'default' argument is returned, which defaults to None.
277

278
  """
279
  try:
280
    if isinstance(user, basestring):
281
      result = pwd.getpwnam(user)
282
    elif isinstance(user, (int, long)):
283
      result = pwd.getpwuid(user)
284
    else:
285
      raise errors.ProgrammerError("Invalid type passed to GetHomeDir (%s)" %
286
                                   type(user))
287
  except KeyError:
288
    return default
289
  return result.pw_dir
290

    
291

    
292
def NewUUID():
293
  """Returns a random UUID.
294

295
  @note: This is a Linux-specific method as it uses the /proc
296
      filesystem.
297
  @rtype: str
298

299
  """
300
  return ReadFile(_RANDOM_UUID_FILE, size=128).rstrip("\n")
301

    
302

    
303
def FirstFree(seq, base=0):
304
  """Returns the first non-existing integer from seq.
305

306
  The seq argument should be a sorted list of positive integers. The
307
  first time the index of an element is smaller than the element
308
  value, the index will be returned.
309

310
  The base argument is used to start at a different offset,
311
  i.e. C{[3, 4, 6]} with I{offset=3} will return 5.
312

313
  Example: C{[0, 1, 3]} will return I{2}.
314

315
  @type seq: sequence
316
  @param seq: the sequence to be analyzed.
317
  @type base: int
318
  @param base: use this value as the base index of the sequence
319
  @rtype: int
320
  @return: the first non-used index in the sequence
321

322
  """
323
  for idx, elem in enumerate(seq):
324
    assert elem >= base, "Passed element is higher than base offset"
325
    if elem > idx + base:
326
      # idx is not used
327
      return idx + base
328
  return None
329

    
330

    
331
def SingleWaitForFdCondition(fdobj, event, timeout):
332
  """Waits for a condition to occur on the socket.
333

334
  Immediately returns at the first interruption.
335

336
  @type fdobj: integer or object supporting a fileno() method
337
  @param fdobj: entity to wait for events on
338
  @type event: integer
339
  @param event: ORed condition (see select module)
340
  @type timeout: float or None
341
  @param timeout: Timeout in seconds
342
  @rtype: int or None
343
  @return: None for timeout, otherwise occured conditions
344

345
  """
346
  check = (event | select.POLLPRI |
347
           select.POLLNVAL | select.POLLHUP | select.POLLERR)
348

    
349
  if timeout is not None:
350
    # Poller object expects milliseconds
351
    timeout *= 1000
352

    
353
  poller = select.poll()
354
  poller.register(fdobj, event)
355
  try:
356
    # TODO: If the main thread receives a signal and we have no timeout, we
357
    # could wait forever. This should check a global "quit" flag or something
358
    # every so often.
359
    io_events = poller.poll(timeout)
360
  except select.error, err:
361
    if err[0] != errno.EINTR:
362
      raise
363
    io_events = []
364
  if io_events and io_events[0][1] & check:
365
    return io_events[0][1]
366
  else:
367
    return None
368

    
369

    
370
class FdConditionWaiterHelper(object):
371
  """Retry helper for WaitForFdCondition.
372

373
  This class contains the retried and wait functions that make sure
374
  WaitForFdCondition can continue waiting until the timeout is actually
375
  expired.
376

377
  """
378

    
379
  def __init__(self, timeout):
380
    self.timeout = timeout
381

    
382
  def Poll(self, fdobj, event):
383
    result = SingleWaitForFdCondition(fdobj, event, self.timeout)
384
    if result is None:
385
      raise RetryAgain()
386
    else:
387
      return result
388

    
389
  def UpdateTimeout(self, timeout):
390
    self.timeout = timeout
391

    
392

    
393
def WaitForFdCondition(fdobj, event, timeout):
394
  """Waits for a condition to occur on the socket.
395

396
  Retries until the timeout is expired, even if interrupted.
397

398
  @type fdobj: integer or object supporting a fileno() method
399
  @param fdobj: entity to wait for events on
400
  @type event: integer
401
  @param event: ORed condition (see select module)
402
  @type timeout: float or None
403
  @param timeout: Timeout in seconds
404
  @rtype: int or None
405
  @return: None for timeout, otherwise occured conditions
406

407
  """
408
  if timeout is not None:
409
    retrywaiter = FdConditionWaiterHelper(timeout)
410
    try:
411
      result = Retry(retrywaiter.Poll, RETRY_REMAINING_TIME, timeout,
412
                     args=(fdobj, event), wait_fn=retrywaiter.UpdateTimeout)
413
    except RetryTimeout:
414
      result = None
415
  else:
416
    result = None
417
    while result is None:
418
      result = SingleWaitForFdCondition(fdobj, event, timeout)
419
  return result
420

    
421

    
422
def EnsureDaemon(name):
423
  """Check for and start daemon if not alive.
424

425
  """
426
  result = RunCmd([constants.DAEMON_UTIL, "check-and-start", name])
427
  if result.failed:
428
    logging.error("Can't start daemon '%s', failure %s, output: %s",
429
                  name, result.fail_reason, result.output)
430
    return False
431

    
432
  return True
433

    
434

    
435
def StopDaemon(name):
436
  """Stop daemon
437

438
  """
439
  result = RunCmd([constants.DAEMON_UTIL, "stop", name])
440
  if result.failed:
441
    logging.error("Can't stop daemon '%s', failure %s, output: %s",
442
                  name, result.fail_reason, result.output)
443
    return False
444

    
445
  return True
446

    
447

    
448
def CheckVolumeGroupSize(vglist, vgname, minsize):
449
  """Checks if the volume group list is valid.
450

451
  The function will check if a given volume group is in the list of
452
  volume groups and has a minimum size.
453

454
  @type vglist: dict
455
  @param vglist: dictionary of volume group names and their size
456
  @type vgname: str
457
  @param vgname: the volume group we should check
458
  @type minsize: int
459
  @param minsize: the minimum size we accept
460
  @rtype: None or str
461
  @return: None for success, otherwise the error message
462

463
  """
464
  vgsize = vglist.get(vgname, None)
465
  if vgsize is None:
466
    return "volume group '%s' missing" % vgname
467
  elif vgsize < minsize:
468
    return ("volume group '%s' too small (%s MiB required, %d MiB found)" %
469
            (vgname, minsize, vgsize))
470
  return None
471

    
472

    
473
def SplitTime(value):
474
  """Splits time as floating point number into a tuple.
475

476
  @param value: Time in seconds
477
  @type value: int or float
478
  @return: Tuple containing (seconds, microseconds)
479

480
  """
481
  (seconds, microseconds) = divmod(int(value * 1000000), 1000000)
482

    
483
  assert 0 <= seconds, \
484
    "Seconds must be larger than or equal to 0, but are %s" % seconds
485
  assert 0 <= microseconds <= 999999, \
486
    "Microseconds must be 0-999999, but are %s" % microseconds
487

    
488
  return (int(seconds), int(microseconds))
489

    
490

    
491
def MergeTime(timetuple):
492
  """Merges a tuple into time as a floating point number.
493

494
  @param timetuple: Time as tuple, (seconds, microseconds)
495
  @type timetuple: tuple
496
  @return: Time as a floating point number expressed in seconds
497

498
  """
499
  (seconds, microseconds) = timetuple
500

    
501
  assert 0 <= seconds, \
502
    "Seconds must be larger than or equal to 0, but are %s" % seconds
503
  assert 0 <= microseconds <= 999999, \
504
    "Microseconds must be 0-999999, but are %s" % microseconds
505

    
506
  return float(seconds) + (float(microseconds) * 0.000001)
507

    
508

    
509
def FindMatch(data, name):
510
  """Tries to find an item in a dictionary matching a name.
511

512
  Callers have to ensure the data names aren't contradictory (e.g. a regexp
513
  that matches a string). If the name isn't a direct key, all regular
514
  expression objects in the dictionary are matched against it.
515

516
  @type data: dict
517
  @param data: Dictionary containing data
518
  @type name: string
519
  @param name: Name to look for
520
  @rtype: tuple; (value in dictionary, matched groups as list)
521

522
  """
523
  if name in data:
524
    return (data[name], [])
525

    
526
  for key, value in data.items():
527
    # Regex objects
528
    if hasattr(key, "match"):
529
      m = key.match(name)
530
      if m:
531
        return (value, list(m.groups()))
532

    
533
  return None
534

    
535

    
536
def GetMounts(filename=constants.PROC_MOUNTS):
537
  """Returns the list of mounted filesystems.
538

539
  This function is Linux-specific.
540

541
  @param filename: path of mounts file (/proc/mounts by default)
542
  @rtype: list of tuples
543
  @return: list of mount entries (device, mountpoint, fstype, options)
544

545
  """
546
  # TODO(iustin): investigate non-Linux options (e.g. via mount output)
547
  data = []
548
  mountlines = ReadFile(filename).splitlines()
549
  for line in mountlines:
550
    device, mountpoint, fstype, options, _ = line.split(None, 4)
551
    data.append((device, mountpoint, fstype, options))
552

    
553
  return data
554

    
555

    
556
def SignalHandled(signums):
557
  """Signal Handled decoration.
558

559
  This special decorator installs a signal handler and then calls the target
560
  function. The function must accept a 'signal_handlers' keyword argument,
561
  which will contain a dict indexed by signal number, with SignalHandler
562
  objects as values.
563

564
  The decorator can be safely stacked with iself, to handle multiple signals
565
  with different handlers.
566

567
  @type signums: list
568
  @param signums: signals to intercept
569

570
  """
571
  def wrap(fn):
572
    def sig_function(*args, **kwargs):
573
      assert 'signal_handlers' not in kwargs or \
574
             kwargs['signal_handlers'] is None or \
575
             isinstance(kwargs['signal_handlers'], dict), \
576
             "Wrong signal_handlers parameter in original function call"
577
      if 'signal_handlers' in kwargs and kwargs['signal_handlers'] is not None:
578
        signal_handlers = kwargs['signal_handlers']
579
      else:
580
        signal_handlers = {}
581
        kwargs['signal_handlers'] = signal_handlers
582
      sighandler = SignalHandler(signums)
583
      try:
584
        for sig in signums:
585
          signal_handlers[sig] = sighandler
586
        return fn(*args, **kwargs)
587
      finally:
588
        sighandler.Reset()
589
    return sig_function
590
  return wrap
591

    
592

    
593
class SignalWakeupFd(object):
594
  try:
595
    # This is only supported in Python 2.5 and above (some distributions
596
    # backported it to Python 2.4)
597
    _set_wakeup_fd_fn = signal.set_wakeup_fd
598
  except AttributeError:
599
    # Not supported
600
    def _SetWakeupFd(self, _): # pylint: disable-msg=R0201
601
      return -1
602
  else:
603
    def _SetWakeupFd(self, fd):
604
      return self._set_wakeup_fd_fn(fd)
605

    
606
  def __init__(self):
607
    """Initializes this class.
608

609
    """
610
    (read_fd, write_fd) = os.pipe()
611

    
612
    # Once these succeeded, the file descriptors will be closed automatically.
613
    # Buffer size 0 is important, otherwise .read() with a specified length
614
    # might buffer data and the file descriptors won't be marked readable.
615
    self._read_fh = os.fdopen(read_fd, "r", 0)
616
    self._write_fh = os.fdopen(write_fd, "w", 0)
617

    
618
    self._previous = self._SetWakeupFd(self._write_fh.fileno())
619

    
620
    # Utility functions
621
    self.fileno = self._read_fh.fileno
622
    self.read = self._read_fh.read
623

    
624
  def Reset(self):
625
    """Restores the previous wakeup file descriptor.
626

627
    """
628
    if hasattr(self, "_previous") and self._previous is not None:
629
      self._SetWakeupFd(self._previous)
630
      self._previous = None
631

    
632
  def Notify(self):
633
    """Notifies the wakeup file descriptor.
634

635
    """
636
    self._write_fh.write("\0")
637

    
638
  def __del__(self):
639
    """Called before object deletion.
640

641
    """
642
    self.Reset()
643

    
644

    
645
class SignalHandler(object):
646
  """Generic signal handler class.
647

648
  It automatically restores the original handler when deconstructed or
649
  when L{Reset} is called. You can either pass your own handler
650
  function in or query the L{called} attribute to detect whether the
651
  signal was sent.
652

653
  @type signum: list
654
  @ivar signum: the signals we handle
655
  @type called: boolean
656
  @ivar called: tracks whether any of the signals have been raised
657

658
  """
659
  def __init__(self, signum, handler_fn=None, wakeup=None):
660
    """Constructs a new SignalHandler instance.
661

662
    @type signum: int or list of ints
663
    @param signum: Single signal number or set of signal numbers
664
    @type handler_fn: callable
665
    @param handler_fn: Signal handling function
666

667
    """
668
    assert handler_fn is None or callable(handler_fn)
669

    
670
    self.signum = set(signum)
671
    self.called = False
672

    
673
    self._handler_fn = handler_fn
674
    self._wakeup = wakeup
675

    
676
    self._previous = {}
677
    try:
678
      for signum in self.signum:
679
        # Setup handler
680
        prev_handler = signal.signal(signum, self._HandleSignal)
681
        try:
682
          self._previous[signum] = prev_handler
683
        except:
684
          # Restore previous handler
685
          signal.signal(signum, prev_handler)
686
          raise
687
    except:
688
      # Reset all handlers
689
      self.Reset()
690
      # Here we have a race condition: a handler may have already been called,
691
      # but there's not much we can do about it at this point.
692
      raise
693

    
694
  def __del__(self):
695
    self.Reset()
696

    
697
  def Reset(self):
698
    """Restore previous handler.
699

700
    This will reset all the signals to their previous handlers.
701

702
    """
703
    for signum, prev_handler in self._previous.items():
704
      signal.signal(signum, prev_handler)
705
      # If successful, remove from dict
706
      del self._previous[signum]
707

    
708
  def Clear(self):
709
    """Unsets the L{called} flag.
710

711
    This function can be used in case a signal may arrive several times.
712

713
    """
714
    self.called = False
715

    
716
  def _HandleSignal(self, signum, frame):
717
    """Actual signal handling function.
718

719
    """
720
    # This is not nice and not absolutely atomic, but it appears to be the only
721
    # solution in Python -- there are no atomic types.
722
    self.called = True
723

    
724
    if self._wakeup:
725
      # Notify whoever is interested in signals
726
      self._wakeup.Notify()
727

    
728
    if self._handler_fn:
729
      self._handler_fn(signum, frame)
730

    
731

    
732
class FieldSet(object):
733
  """A simple field set.
734

735
  Among the features are:
736
    - checking if a string is among a list of static string or regex objects
737
    - checking if a whole list of string matches
738
    - returning the matching groups from a regex match
739

740
  Internally, all fields are held as regular expression objects.
741

742
  """
743
  def __init__(self, *items):
744
    self.items = [re.compile("^%s$" % value) for value in items]
745

    
746
  def Extend(self, other_set):
747
    """Extend the field set with the items from another one"""
748
    self.items.extend(other_set.items)
749

    
750
  def Matches(self, field):
751
    """Checks if a field matches the current set
752

753
    @type field: str
754
    @param field: the string to match
755
    @return: either None or a regular expression match object
756

757
    """
758
    for m in itertools.ifilter(None, (val.match(field) for val in self.items)):
759
      return m
760
    return None
761

    
762
  def NonMatching(self, items):
763
    """Returns the list of fields not matching the current set
764

765
    @type items: list
766
    @param items: the list of fields to check
767
    @rtype: list
768
    @return: list of non-matching fields
769

770
    """
771
    return [val for val in items if not self.Matches(val)]