summaryrefslogtreecommitdiffstats
path: root/src/lib/Bcfg2/Utils.py
diff options
context:
space:
mode:
authorChris St. Pierre <chris.a.st.pierre@gmail.com>2013-06-27 10:35:06 -0400
committerChris St. Pierre <chris.a.st.pierre@gmail.com>2013-06-27 10:42:24 -0400
commit3261f7cf5314a76b85884942d077146fe8f8fc24 (patch)
treef1581e2c407ffeffe54500683aa131d0a383b0df /src/lib/Bcfg2/Utils.py
parentb38471cf7627e79ea3bdbe6d1ed822a42bf0622d (diff)
downloadbcfg2-3261f7cf5314a76b85884942d077146fe8f8fc24.tar.gz
bcfg2-3261f7cf5314a76b85884942d077146fe8f8fc24.tar.bz2
bcfg2-3261f7cf5314a76b85884942d077146fe8f8fc24.zip
Options: migrated common utils to new parser
Diffstat (limited to 'src/lib/Bcfg2/Utils.py')
-rw-r--r--src/lib/Bcfg2/Utils.py67
1 files changed, 66 insertions, 1 deletions
diff --git a/src/lib/Bcfg2/Utils.py b/src/lib/Bcfg2/Utils.py
index d087f4f87..5d8204460 100644
--- a/src/lib/Bcfg2/Utils.py
+++ b/src/lib/Bcfg2/Utils.py
@@ -2,12 +2,16 @@
used by both client and server. Stuff that doesn't fit anywhere
else. """
+import os
+import re
+import sys
import shlex
import fcntl
+import select
import logging
import threading
import subprocess
-from Bcfg2.Compat import any # pylint: disable=W0622
+from Bcfg2.Compat import input, any # pylint: disable=W0622
class ClassName(object):
@@ -250,3 +254,64 @@ class Executor(object):
finally:
if timeout is not None:
timer.cancel()
+
+
+def list2range(lst):
+ ''' convert a list of integers to a set of human-readable ranges. e.g.:
+
+ [1, 2, 3, 6, 9, 10, 11] -> "[1-3,6,9-11]" '''
+ ilst = sorted(int(i) for i in lst)
+ ranges = []
+ start = None
+ last = None
+ for i in ilst:
+ if not last or i != last + 1:
+ if start:
+ if start == last:
+ ranges.append(str(start))
+ else:
+ ranges.append("%d-%d" % (start, last))
+ start = i
+ last = i
+ if start:
+ if start == last:
+ ranges.append(str(start))
+ else:
+ ranges.append("%d-%d" % (start, last))
+ if not ranges:
+ return ""
+ elif len(ranges) > 1 or "-" in ranges[0]:
+ return "[%s]" % ",".join(ranges)
+ else:
+ # only one range consisting of only a single number
+ return ranges[0]
+
+
+def hostnames2ranges(hostnames):
+ ''' convert a list of hostnames to a set of human-readable ranges. e.g.:
+
+ ["foo1.example.com", "foo2.example.com", "foo3.example.com",
+ "foo6.example.com"] -> ["foo[1-3,6].example.com"]'''
+ hosts = {}
+ hostre = re.compile(r'(\w+?)(\d+)(\..*)$')
+ for host in hostnames:
+ match = hostre.match(host)
+ if match:
+ key = (match.group(1), match.group(3))
+ try:
+ hosts[key].append(match.group(2))
+ except KeyError:
+ hosts[key] = [match.group(2)]
+
+ ranges = []
+ for name, nums in hosts.items():
+ ranges.append(name[0] + list2range(nums) + name[1])
+ return ranges
+
+
+def safe_input(msg):
+ """ input() that flushes the input buffer before accepting input """
+ # flush input buffer
+ while len(select.select([sys.stdin.fileno()], [], [], 0.0)[0]) > 0:
+ os.read(sys.stdin.fileno(), 4096)
+ return input(msg)