diff options
author | Petr Viktorin <pviktori@redhat.com> | 2012-04-18 11:22:35 -0400 |
---|---|---|
committer | Martin Kosek <mkosek@redhat.com> | 2012-05-09 11:54:20 +0200 |
commit | f19218f7d87f5847d51f79b5d2850f90b0ae8407 (patch) | |
tree | 500d3101dc1375d3eb75ffb927040c2593216aa9 | |
parent | c02fcf5d34ad880e082cbc0c7f59fc3812d11c9e (diff) | |
download | freeipa-f19218f7d87f5847d51f79b5d2850f90b0ae8407.tar.gz freeipa-f19218f7d87f5847d51f79b5d2850f90b0ae8407.tar.xz freeipa-f19218f7d87f5847d51f79b5d2850f90b0ae8407.zip |
Remove duplicate and unused utility code
IPA has some unused code from abandoned features (Radius, ipa 1.x user
input, commant-line tab completion), as well as some duplicate utilities.
This patch cleans up the utility modules.
Duplicate code consolidated into ipapython.ipautil:
{ipalib.util,ipaserver.ipautil,ipapython.ipautil}.realm_to_suffix
{ipaserver,ipapython}.ipautil.CIDict
(with style improvements from the ipaserver version)
{ipapython.entity,ipaserver.ipautil}.utf8_encode_value
{ipapython.entity,ipaserver.ipautil}.utf8_encode_values
ipalib.util.get_fqdn was removed in favor of the same function in
ipaserver.install.installutils
Removed unused code:
ipalib.util:
load_plugins_in_dir
import_plugins_subpackage
make_repr (was imported but unused; also removed from tests)
ipapython.ipautil:
format_list
parse_key_value_pairs
read_pairs_file
read_items_file
user_input_plain
AttributeValueCompleter
ItemCompleter
ipaserver.ipautil:
get_gsserror (a different version exists in ipapython.ipautil)
ipaserver.ipautil ended up empty and is removed entirely.
https://fedorahosted.org/freeipa/ticket/2650
-rwxr-xr-x | install/tools/ipa-ca-install | 2 | ||||
-rwxr-xr-x | install/tools/ipa-csreplica-manage | 4 | ||||
-rwxr-xr-x | install/tools/ipa-replica-install | 8 | ||||
-rwxr-xr-x | install/tools/ipa-replica-manage | 6 | ||||
-rwxr-xr-x | install/tools/ipa-replica-prepare | 2 | ||||
-rwxr-xr-x | install/tools/ipa-server-install | 9 | ||||
-rw-r--r-- | ipalib/frontend.py | 1 | ||||
-rw-r--r-- | ipalib/parameters.py | 1 | ||||
-rw-r--r-- | ipalib/util.py | 47 | ||||
-rw-r--r-- | ipapython/entity.py | 31 | ||||
-rw-r--r-- | ipapython/ipautil.py | 506 | ||||
-rw-r--r-- | ipaserver/install/bindinstance.py | 6 | ||||
-rw-r--r-- | ipaserver/install/cainstance.py | 4 | ||||
-rw-r--r-- | ipaserver/install/dsinstance.py | 6 | ||||
-rw-r--r-- | ipaserver/install/httpinstance.py | 2 | ||||
-rw-r--r-- | ipaserver/install/krbinstance.py | 2 | ||||
-rw-r--r-- | ipaserver/install/ldapupdate.py | 2 | ||||
-rw-r--r-- | ipaserver/install/replication.py | 2 | ||||
-rw-r--r-- | ipaserver/ipaldap.py | 2 | ||||
-rw-r--r-- | ipaserver/ipautil.py | 141 | ||||
-rw-r--r-- | ipaserver/plugins/join.py | 6 | ||||
-rw-r--r-- | ipaserver/rpcserver.py | 2 | ||||
-rw-r--r-- | tests/test_ipalib/test_util.py | 11 |
23 files changed, 78 insertions, 725 deletions
diff --git a/install/tools/ipa-ca-install b/install/tools/ipa-ca-install index 57f867e70..55b4dbfb8 100755 --- a/install/tools/ipa-ca-install +++ b/install/tools/ipa-ca-install @@ -143,7 +143,7 @@ def main(): # We need to ldap_enable the CA now that DS is up and running CA.ldap_enable('CA', config.host_name, config.dirman_password, - util.realm_to_suffix(config.realm_name)) + ipautil.realm_to_suffix(config.realm_name)) cs.add_simple_service('dogtagldap/%s@%s' % (config.host_name, config.realm_name)) cs.add_cert_to_service() diff --git a/install/tools/ipa-csreplica-manage b/install/tools/ipa-csreplica-manage index 97c504552..938201fed 100755 --- a/install/tools/ipa-csreplica-manage +++ b/install/tools/ipa-csreplica-manage @@ -165,7 +165,7 @@ def list_replicas(realm, host, replica, dirman_passwd, verbose): conn = ipaldap.IPAdmin(host, 636, cacert=CACERT) conn.do_simple_bind(bindpw=dirman_passwd) - dn = str(DN('cn=masters,cn=ipa,cn=etc,%s' % util.realm_to_suffix(realm))) + dn = str(DN('cn=masters,cn=ipa,cn=etc,%s' % ipautil.realm_to_suffix(realm))) entries = conn.search_s(dn, ldap.SCOPE_ONELEVEL) for ent in entries: @@ -316,7 +316,7 @@ def add_link(realm, replica1, replica2, dirman_passwd, options): conn = ipaldap.IPAdmin(replica2, 636, cacert=CACERT) conn.do_simple_bind(bindpw=dirman_passwd) - dn = str(DN('cn=CA,cn=%s,cn=masters,cn=ipa,cn=etc,%s' % (replica2, util.realm_to_suffix(realm)))) + dn = str(DN('cn=CA,cn=%s,cn=masters,cn=ipa,cn=etc,%s' % (replica2, ipautil.realm_to_suffix(realm)))) conn.search_s(dn, ldap.SCOPE_ONELEVEL) conn.unbind_s() except ldap.NO_SUCH_OBJECT: diff --git a/install/tools/ipa-replica-install b/install/tools/ipa-replica-install index 07b1781ee..39ce09bf1 100755 --- a/install/tools/ipa-replica-install +++ b/install/tools/ipa-replica-install @@ -186,7 +186,7 @@ def install_http(config, auto_redirect): config.dir + "/http_pin.txt") memcache = memcacheinstance.MemcacheInstance() - memcache.create_instance('MEMCACHE', config.host_name, config.dirman_password, util.realm_to_suffix(config.realm_name)) + memcache.create_instance('MEMCACHE', config.host_name, config.dirman_password, ipautil.realm_to_suffix(config.realm_name)) http = httpinstance.HTTPInstance() http.create_instance(config.realm_name, config.host_name, config.domain_name, config.dirman_password, False, pkcs12_info, self_signed_ca=True, auto_redirect=auto_redirect) @@ -236,7 +236,7 @@ def install_bind(config, options): def install_dns_records(config, options): if not bindinstance.dns_container_exists(config.master_host_name, - util.realm_to_suffix(config.realm_name), + ipautil.realm_to_suffix(config.realm_name), dm_password=config.dirman_password): return @@ -355,7 +355,7 @@ def main(): fd = open("/etc/ipa/default.conf", "w") fd.write("[global]\n") fd.write("host=" + config.host_name + "\n") - fd.write("basedn=" + util.realm_to_suffix(config.realm_name) + "\n") + fd.write("basedn=" + ipautil.realm_to_suffix(config.realm_name) + "\n") fd.write("realm=" + config.realm_name + "\n") fd.write("domain=" + config.domain_name + "\n") fd.write("xmlrpc_uri=https://%s/ipa/xml\n" % ipautil.format_netloc(config.host_name)) @@ -434,7 +434,7 @@ def main(): # We need to ldap_enable the CA now that DS is up and running if CA and config.setup_ca: CA.ldap_enable('CA', config.host_name, config.dirman_password, - util.realm_to_suffix(config.realm_name)) + ipautil.realm_to_suffix(config.realm_name)) cs.add_simple_service('dogtagldap/%s@%s' % (config.host_name, config.realm_name)) cs.add_cert_to_service() diff --git a/install/tools/ipa-replica-manage b/install/tools/ipa-replica-manage index f1f5425ca..e23781738 100755 --- a/install/tools/ipa-replica-manage +++ b/install/tools/ipa-replica-manage @@ -126,13 +126,13 @@ def list_replicas(realm, host, replica, dirman_passwd, verbose): else: conn.do_sasl_gssapi_bind() - dn = 'cn=masters,cn=ipa,cn=etc,%s' % util.realm_to_suffix(realm) + dn = 'cn=masters,cn=ipa,cn=etc,%s' % ipautil.realm_to_suffix(realm) entries = conn.search_s(dn, ldap.SCOPE_ONELEVEL) for ent in entries: peers[ent.cn] = ['master', ''] - dn = 'cn=replicas,cn=ipa,cn=etc,%s' % util.realm_to_suffix(realm) + dn = 'cn=replicas,cn=ipa,cn=etc,%s' % ipautil.realm_to_suffix(realm) entries = conn.search_s(dn, ldap.SCOPE_ONELEVEL) for ent in entries: @@ -255,7 +255,7 @@ def del_link(realm, replica1, replica2, dirman_passwd, force=False): if type1 == replication.WINSYNC: try: dn = 'cn=%s,cn=replicas,cn=ipa,cn=etc,%s' % (replica2, - util.realm_to_suffix(realm)) + ipautil.realm_to_suffix(realm)) entries = repl1.conn.search_s(dn, ldap.SCOPE_SUBTREE) if len(entries) != 0: dnset = repl1.conn.get_dns_sorted_by_length(entries, diff --git a/install/tools/ipa-replica-prepare b/install/tools/ipa-replica-prepare index c54aa62b8..3b6911288 100755 --- a/install/tools/ipa-replica-prepare +++ b/install/tools/ipa-replica-prepare @@ -307,7 +307,7 @@ def main(): enable_replication_version_checking(api.env.host, api.env.realm, dirman_password) - subject_base = get_subject_base(api.env.host, dirman_password, util.realm_to_suffix(api.env.realm)) + subject_base = get_subject_base(api.env.host, dirman_password, ipautil.realm_to_suffix(api.env.realm)) top_dir = tempfile.mkdtemp("ipa") dir = top_dir + "/realm_info" diff --git a/install/tools/ipa-server-install b/install/tools/ipa-server-install index 1dd02ba87..f3377df6d 100755 --- a/install/tools/ipa-server-install +++ b/install/tools/ipa-server-install @@ -57,6 +57,7 @@ from ipaserver.plugins.ldap2 import ldap2 from ipapython import sysrestore from ipapython.ipautil import * +from ipapython import ipautil from ipalib import api, errors, util from ipapython.config import IPAOptionParser from ipalib.dn import DN @@ -812,7 +813,7 @@ def main(): fd = open(target_fname, "w") fd.write("[global]\n") fd.write("host=" + host_name + "\n") - fd.write("basedn=" + util.realm_to_suffix(realm_name) + "\n") + fd.write("basedn=" + ipautil.realm_to_suffix(realm_name) + "\n") fd.write("realm=" + realm_name + "\n") fd.write("domain=" + domain_name + "\n") fd.write("xmlrpc_uri=https://%s/ipa/xml\n" % format_netloc(host_name)) @@ -938,7 +939,7 @@ def main(): # We need to ldap_enable the CA now that DS is up and running if not options.selfsign: ca.ldap_enable('CA', host_name, dm_password, - util.realm_to_suffix(realm_name)) + ipautil.realm_to_suffix(realm_name)) # Turn on SSL in the dogtag LDAP instance. This will get restarted # later, we don't need SSL now. @@ -984,7 +985,7 @@ def main(): os.close(pw_fd) memcache = memcacheinstance.MemcacheInstance() - memcache.create_instance('MEMCACHE', host_name, dm_password, util.realm_to_suffix(realm_name)) + memcache.create_instance('MEMCACHE', host_name, dm_password, ipautil.realm_to_suffix(realm_name)) http = httpinstance.HTTPInstance(fstore) if options.http_pkcs12: @@ -995,7 +996,7 @@ def main(): http.create_instance(realm_name, host_name, domain_name, dm_password, autoconfig=True, self_signed_ca=options.selfsign, subject_base=options.subject, auto_redirect=options.ui_redirect) ipaservices.restore_context("/var/cache/ipa/sessions") - set_subject_in_config(realm_name, dm_password, util.realm_to_suffix(realm_name), options.subject) + set_subject_in_config(realm_name, dm_password, ipautil.realm_to_suffix(realm_name), options.subject) # Apply any LDAP updates. Needs to be done after the configuration file # is created diff --git a/ipalib/frontend.py b/ipalib/frontend.py index b31d6d4b8..e8a84eabe 100644 --- a/ipalib/frontend.py +++ b/ipalib/frontend.py @@ -26,7 +26,6 @@ import inspect from base import lock, check_name, NameSpace from plugable import Plugin, is_production_mode from parameters import create_param, parse_param_spec, Param, Str, Flag, Password -from util import make_repr from output import Output, Entry, ListOfEntries from text import _, ngettext diff --git a/ipalib/parameters.py b/ipalib/parameters.py index e9951a1c8..83a86544d 100644 --- a/ipalib/parameters.py +++ b/ipalib/parameters.py @@ -106,7 +106,6 @@ import csv from xmlrpclib import MAXINT, MININT from types import NoneType -from util import make_repr from text import _ as ugettext from plugable import ReadOnly, lock, check_name from errors import ConversionError, RequirementError, ValidationError diff --git a/ipalib/util.py b/ipalib/util.py index 6fa69e7af..64ac6b2cf 100644 --- a/ipalib/util.py +++ b/ipalib/util.py @@ -61,16 +61,6 @@ def get_current_principal(): #TODO: do a kinit? raise errors.CCacheError() -def get_fqdn(): - fqdn = "" - try: - fqdn = socket.getfqdn() - except: - try: - fqdn = socket.gethostname() - except: - fqdn = "" - return fqdn # FIXME: This function has no unit test def find_modules_in_dir(src_dir): @@ -94,43 +84,6 @@ def find_modules_in_dir(src_dir): yield (module, pyfile) -# FIXME: This function has no unit test -def load_plugins_in_dir(src_dir): - """ - Import each Python module found in ``src_dir``. - """ - for module in find_modules_in_dir(src_dir): - imp.load_module(module, *imp.find_module(module, [src_dir])) - - -# FIXME: This function has no unit test -def import_plugins_subpackage(name): - """ - Import everythig in ``plugins`` sub-package of package named ``name``. - """ - try: - plugins = __import__(name + '.plugins').plugins - except ImportError: - return - src_dir = os.path.dirname(os.path.abspath(plugins.__file__)) - for name in find_modules_in_dir(src_dir): - full_name = '%s.%s' % (plugins.__name__, name) - __import__(full_name) - - -def make_repr(name, *args, **kw): - """ - Construct a standard representation of a class instance. - """ - args = [repr(a) for a in args] - kw = ['%s=%r' % (k, kw[k]) for k in sorted(kw)] - return '%s(%s)' % (name, ', '.join(args + kw)) - -def realm_to_suffix(realm_name): - s = realm_name.split(".") - terms = ["dc=" + x.lower() for x in s] - return ",".join(terms) - def validate_host_dns(log, fqdn): """ See if the hostname has a DNS A record. diff --git a/ipapython/entity.py b/ipapython/entity.py index 527adface..27d517879 100644 --- a/ipapython/entity.py +++ b/ipapython/entity.py @@ -17,18 +17,7 @@ import copy -import ipapython.ipautil - -def utf8_encode_value(value): - if isinstance(value,unicode): - return value.encode('utf-8') - return value - -def utf8_encode_values(values): - if isinstance(values,list) or isinstance(values,tuple): - return map(utf8_encode_value, values) - else: - return utf8_encode_value(values) +from ipapython import ipautil def copy_CIDict(x): """Do a deep copy of a CIDict""" @@ -55,19 +44,19 @@ class Entity: if entrydata: if isinstance(entrydata,tuple): self.dn = entrydata[0] - self.data = ipapython.ipautil.CIDict(entrydata[1]) + self.data = ipautil.CIDict(entrydata[1]) elif isinstance(entrydata,str) or isinstance(entrydata,unicode): self.dn = entrydata - self.data = ipapython.ipautil.CIDict() + self.data = ipautil.CIDict() elif isinstance(entrydata,dict): self.dn = entrydata['dn'] del entrydata['dn'] - self.data = ipapython.ipautil.CIDict(entrydata) + self.data = ipautil.CIDict(entrydata) else: self.dn = '' - self.data = ipapython.ipautil.CIDict() + self.data = ipautil.CIDict() - self.orig_data = ipapython.ipautil.CIDict(copy_CIDict(self.data)) + self.orig_data = ipautil.CIDict(copy_CIDict(self.data)) def __nonzero__(self): """This allows us to do tests like if entry: returns false if there is no data, @@ -120,9 +109,9 @@ class Entity: if (len(value) < 1): return if (len(value) == 1): - self.data[name] = utf8_encode_values(value[0]) + self.data[name] = ipautil.utf8_encode_values(value[0]) else: - self.data[name] = utf8_encode_values(value) + self.data[name] = ipautil.utf8_encode_values(value) setValues = setValue @@ -161,7 +150,7 @@ class Entity: def toDict(self): """Convert the attrs and values to a dict. The dict is keyed on the attribute name. The value is either single value or a list of values.""" - result = ipapython.ipautil.CIDict(self.data) + result = ipautil.CIDict(self.data) result['dn'] = self.dn return result @@ -171,7 +160,7 @@ class Entity: def origDataDict(self): """Returns a dict of the original values of the user. Used for updates.""" - result = ipapython.ipautil.CIDict(self.orig_data) + result = ipautil.CIDict(self.orig_data) result['dn'] = self.dn return result diff --git a/ipapython/ipautil.py b/ipapython/ipautil.py index 69c328934..4a9db11e2 100644 --- a/ipapython/ipautil.py +++ b/ipapython/ipautil.py @@ -195,6 +195,7 @@ def format_netloc(host, port=None): return '%s:%s' % (host, str(port)) def realm_to_suffix(realm_name): + """Convert a kerberos realm into the IPA suffix.""" s = realm_name.split(".") terms = ["dc=" + x.lower() for x in s] return ",".join(terms) @@ -406,32 +407,32 @@ class CIDict(dict): If you extend UserDict, isinstance(foo, dict) returns false. """ - def __init__(self,default=None): + def __init__(self, default=None): super(CIDict, self).__init__() self._keys = {} self.update(default or {}) - def __getitem__(self,key): - return super(CIDict,self).__getitem__(string.lower(key)) + def __getitem__(self, key): + return super(CIDict, self).__getitem__(key.lower()) - def __setitem__(self,key,value): - lower_key = string.lower(key) + def __setitem__(self, key, value): + lower_key = key.lower() self._keys[lower_key] = key - return super(CIDict,self).__setitem__(string.lower(key),value) + return super(CIDict, self).__setitem__(lower_key, value) - def __delitem__(self,key): - lower_key = string.lower(key) + def __delitem__(self, key): + lower_key = key.lower() del self._keys[lower_key] - return super(CIDict,self).__delitem__(string.lower(key)) + return super(CIDict, self).__delitem__(key.lower()) - def update(self,dict): + def update(self, dict): for key in dict.keys(): self[key] = dict[key] - def has_key(self,key): - return super(CIDict, self).has_key(string.lower(key)) + def has_key(self, key): + return super(CIDict, self).has_key(key.lower()) - def get(self,key,failobj=None): + def get(self, key, failobj=None): try: return self[key] except KeyError: @@ -443,7 +444,7 @@ class CIDict(dict): def items(self): result = [] for k in self._keys.values(): - result.append((k,self[k])) + result.append((k, self[k])) return result def copy(self): @@ -458,7 +459,7 @@ class CIDict(dict): def iterkeys(self): return self.copy().iterkeys() - def setdefault(self,key,value=None): + def setdefault(self, key, value=None): try: return self[key] except KeyError: @@ -476,11 +477,11 @@ class CIDict(dict): raise def popitem(self): - (lower_key,value) = super(CIDict,self).popitem() + (lower_key, value) = super(CIDict, self).popitem() key = self._keys[lower_key] del self._keys[lower_key] - return (key,value) + return (key, value) class GeneralizedTimeZone(datetime.tzinfo): @@ -610,118 +611,17 @@ def ipa_generate_password(characters=None,pwd_len=None): rndpwd += rndchar return rndpwd -def format_list(items, quote=None, page_width=80): - '''Format a list of items formatting them so they wrap to fit the - available width. The items will be sorted. +def parse_items(text): + '''Given text with items separated by whitespace or comma, return a list of those items - The items may optionally be quoted. The quote parameter may either be - a string, in which case it is added before and after the item. Or the - quote parameter may be a pair (either a tuple or list). In this case - quote[0] is left hand quote and quote[1] is the right hand quote. - ''' - left_quote = right_quote = '' - num_items = len(items) - if not num_items: return "" - - if quote is not None: - if type(quote) in StringTypes: - left_quote = right_quote = quote - elif type(quote) is TupleType or type(quote) is ListType: - left_quote = quote[0] - right_quote = quote[1] - - max_len = max(map(len, items)) - max_len += len(left_quote) + len(right_quote) - num_columns = (page_width + max_len) / (max_len+1) - num_rows = (num_items + num_columns - 1) / num_columns - items.sort() - - rows = [''] * num_rows - i = row = col = 0 - - while i < num_items: - row = 0 - if col == 0: - separator = '' - else: - separator = ' ' - - while i < num_items and row < num_rows: - rows[row] += "%s%*s" % (separator, -max_len, "%s%s%s" % (left_quote, items[i], right_quote)) - i += 1 - row += 1 - col += 1 - return '\n'.join(rows) - -key_value_re = re.compile("(\w+)\s*=\s*(([^\s'\\\"]+)|(?P<quote>['\\\"])((?P=quote)|(.*?[^\\\])(?P=quote)))") -def parse_key_value_pairs(input): - ''' Given a string composed of key=value pairs parse it and return - a dict of the key/value pairs. Keys must be a word, a key must be followed - by an equal sign (=) and a value. The value may be a single word or may be - quoted. Quotes may be either single or double quotes, but must be balanced. - Inside the quoted text the same quote used to start the quoted value may be - used if it is escaped by preceding it with a backslash (\). - White space between the key, the equal sign, and the value is ignored. - Values are always strings. Empty values must be specified with an empty - quoted string, it's value after parsing will be an empty string. - - Example: The string - - arg0 = '' arg1 = 1 arg2='two' arg3 = "three's a crowd" arg4 = "this is a \" quote" - - will produce - - arg0= arg1=1 - arg2=two - arg3=three's a crowd - arg4=this is a " quote + The returned list only contains non-empty items. ''' - - kv_dict = {} - for match in key_value_re.finditer(input): - key = match.group(1) - quote = match.group('quote') - if match.group(5): - value = match.group(6) - if value is None: value = '' - value = re.sub('\\\%s' % quote, quote, value) - else: - value = match.group(2) - kv_dict[key] = value - return kv_dict - -def parse_items(text): - '''Given text with items separated by whitespace or comma, return a list of those items''' split_re = re.compile('[ ,\t\n]+') items = split_re.split(text) for item in items[:]: if not item: items.remove(item) return items -def read_pairs_file(filename): - comment_re = re.compile('#.*$', re.MULTILINE) - if filename == '-': - fd = sys.stdin - else: - fd = open(filename) - text = fd.read() - text = comment_re.sub('', text) # kill comments - pairs = parse_key_value_pairs(text) - if fd != sys.stdin: fd.close() - return pairs - -def read_items_file(filename): - comment_re = re.compile('#.*$', re.MULTILINE) - if filename == '-': - fd = sys.stdin - else: - fd = open(filename) - text = fd.read() - text = comment_re.sub('', text) # kill comments - items = parse_items(text) - if fd != sys.stdin: fd.close() - return items - def user_input(prompt, default = None, allow_empty = True): if default == None: while True: @@ -761,357 +661,6 @@ def user_input(prompt, default = None, allow_empty = True): else: return ret -def user_input_plain(prompt, default = None, allow_empty = True, allow_spaces = True): - while True: - ret = user_input(prompt, default, allow_empty) - if ipavalidate.Plain(ret, not allow_empty, allow_spaces): - return ret - -class AttributeValueCompleter: - ''' - Gets input from the user in the form "lhs operator rhs" - TAB completes partial input. - lhs completes to a name in @lhs_names - The lhs is fully parsed if a lhs_delim delimiter is seen, then TAB will - complete to the operator and a default value. - Default values for a lhs value can specified as: - - a string, all lhs values will use this default - - a dict, the lhs value is looked up in the dict to return the default or None - - a function with a single arg, the lhs value, it returns the default or None - - After creating the completer you must open it to set the terminal - up, Then get a line of input from the user by calling read_input() - which returns two values, the lhs and rhs, which might be None if - lhs or rhs was not parsed. After you are done getting input you - should close the completer to restore the terminal. - - Example: (note this is essentially what the convenience function get_pairs() does) - - This will allow the user to autocomplete foo & foobar, both have - defaults defined in a dict. In addition the foobar attribute must - be specified before the prompting loop will exit. Also, this - example show how to require that each attrbute entered by the user - is valid. - - attrs = ['foo', 'foobar'] - defaults = {'foo' : 'foo_default', 'foobar' : 'foobar_default'} - mandatory_attrs = ['foobar'] - - c = AttributeValueCompleter(attrs, defaults) - c.open() - mandatory_attrs_remaining = mandatory_attrs[:] - - while True: - if mandatory_attrs_remaining: - attribute, value = c.read_input("Enter: ", mandatory_attrs_remaining[0]) - try: - mandatory_attrs_remaining.remove(attribute) - except ValueError: - pass - else: - attribute, value = c.read_input("Enter: ") - if attribute is None: - # Are we done? - if mandatory_attrs_remaining: - print "ERROR, you must specify: %s" % (','.join(mandatory_attrs_remaining)) - continue - else: - break - if attribute not in attrs: - print "ERROR: %s is not a valid attribute" % (attribute) - else: - print "got '%s' = '%s'" % (attribute, value) - - c.close() - print "exiting..." - ''' - - def __init__(self, lhs_names, default_value=None, lhs_regexp=r'^\s*(?P<lhs>[^ =]+)', lhs_delims=' =', - operator='=', strip_rhs=True): - self.lhs_names = lhs_names - self.default_value = default_value - # lhs_regexp must have named group 'lhs' which returns the contents of the lhs - self.lhs_regexp = lhs_regexp - self.lhs_re = re.compile(self.lhs_regexp) - self.lhs_delims = lhs_delims - self.operator = operator - self.strip_rhs = strip_rhs - self.pairs = None - self._reset() - - def _reset(self): - self.lhs = None - self.lhs_complete = False - self.operator_complete = False - self.rhs = None - - def open(self): - # Save state - self.prev_completer = readline.get_completer() - self.prev_completer_delims = readline.get_completer_delims() - - # Set up for ourself - readline.parse_and_bind("tab: complete") - readline.set_completer(self.complete) - readline.set_completer_delims(self.lhs_delims) - - def close(self): - # Restore previous state - readline.set_completer_delims(self.prev_completer_delims) - readline.set_completer(self.prev_completer) - - def parse_input(self): - '''We are looking for 3 tokens: <lhs,op,rhs> - Extract as much of each token as possible. - Set flags indicating if token is fully parsed. - ''' - try: - self._reset() - buf_len = len(self.line_buffer) - pos = 0 - lhs_match = self.lhs_re.search(self.line_buffer, pos) - if not lhs_match: return # no lhs content - self.lhs = lhs_match.group('lhs') # get lhs contents - pos = lhs_match.end('lhs') # new scanning position - if pos == buf_len: return # nothing after lhs, lhs incomplete - self.lhs_complete = True # something trails the lhs, lhs is complete - operator_beg = self.line_buffer.find(self.operator, pos) # locate operator - if operator_beg == -1: return # did not find the operator - self.operator_complete = True # operator fully parsed - operator_end = operator_beg + len(self.operator) - pos = operator_end # step over the operator - self.rhs = self.line_buffer[pos:] - except Exception, e: - traceback.print_exc() - print "Exception in %s.parse_input(): %s" % (self.__class__.__name__, e) - - def get_default_value(self): - '''default_value can be a string, a dict, or a function. - If it's a string it's a global default for all attributes. - If it's a dict the default is looked up in the dict index by attribute. - If it's a function, the function is called with 1 parameter, the attribute - and it should return the default value for the attriubte or None''' - - if not self.lhs_complete: raise ValueError("attribute not parsed") - - # If the user previously provided a value let that override the supplied default - if self.pairs is not None: - prev_value = self.pairs.get(self.lhs) - if prev_value is not None: return prev_value - - # No previous user provided value, query for a default - default_value_type = type(self.default_value) - if default_value_type is DictType: - return self.default_value.get(self.lhs, None) - elif default_value_type is FunctionType: - return self.default_value(self.lhs) - elif default_value_type is StringType: - return self.default_value - else: - return None - - def get_lhs_completions(self, text): - if text: - self.completions = [lhs for lhs in self.lhs_names if lhs.startswith(text)] - else: - self.completions = self.lhs_names - - def complete(self, state): - self.line_buffer= readline.get_line_buffer() - self.parse_input() - if not self.lhs_complete: - # lhs is not complete, set up to complete the lhs - if state == 0: - beg = readline.get_begidx() - end = readline.get_endidx() - self.get_lhs_completions(self.line_buffer[beg:end]) - if state >= len(self.completions): return None - return self.completions[state] - - - elif not self.operator_complete: - # lhs is complete, but the operator is not so we complete - # by inserting the operator manually. - # Also try to complete the default value at this time. - readline.insert_text('%s ' % self.operator) - default_value = self.get_default_value() - if default_value is not None: - readline.insert_text(default_value) - readline.redisplay() - return None - else: - # lhs and operator are complete, if the rhs is blank - # (either empty or only only whitespace) then attempt - # to complete by inserting the default value, otherwise - # there is nothing we can complete to so we're done. - if self.rhs.strip(): - return None - default_value = self.get_default_value() - if default_value is not None: - readline.insert_text(default_value) - readline.redisplay() - return None - - def pre_input_hook(self): - readline.insert_text('%s %s ' % (self.initial_lhs, self.operator)) - readline.redisplay() - - def read_input(self, prompt, initial_lhs=None): - self.initial_lhs = initial_lhs - try: - self._reset() - if initial_lhs is None: - readline.set_pre_input_hook(None) - else: - readline.set_pre_input_hook(self.pre_input_hook) - self.line_buffer = raw_input(prompt).strip() - self.parse_input() - if self.strip_rhs and self.rhs is not None: - return self.lhs, self.rhs.strip() - else: - return self.lhs, self.rhs - except EOFError: - return None, None - - def get_pairs(self, prompt, mandatory_attrs=None, validate_callback=None, must_match=True, value_required=True): - self.pairs = {} - if mandatory_attrs: - mandatory_attrs_remaining = mandatory_attrs[:] - else: - mandatory_attrs_remaining = [] - - print "Enter name = value" - print "Press <ENTER> to accept, a blank line terminates input" - print "Pressing <TAB> will auto completes name, assignment, and value" - print - while True: - if mandatory_attrs_remaining: - attribute, value = self.read_input(prompt, mandatory_attrs_remaining[0]) - else: - attribute, value = self.read_input(prompt) - if attribute is None: - # Are we done? - if mandatory_attrs_remaining: - print "ERROR, you must specify: %s" % (','.join(mandatory_attrs_remaining)) - continue - else: - break - if value is None: - if value_required: - print "ERROR: you must specify a value for %s" % attribute - continue - else: - if must_match and attribute not in self.lhs_names: - print "ERROR: %s is not a valid name" % (attribute) - continue - if validate_callback is not None: - if not validate_callback(attribute, value): - print "ERROR: %s is not valid for %s" % (value, attribute) - continue - try: - mandatory_attrs_remaining.remove(attribute) - except ValueError: - pass - - self.pairs[attribute] = value - return self.pairs - -class ItemCompleter: - ''' - Prompts the user for items in a list of items with auto completion. - TAB completes partial input. - More than one item can be specifed during input, whitespace and/or comma's seperate. - Example: - - possible_items = ['foo', 'bar'] - c = ItemCompleter(possible_items) - c.open() - # Use read_input() to limit input to a single carriage return (e.g. <ENTER>) - #items = c.read_input("Enter: ") - # Use get_items to iterate until a blank line is entered. - items = c.get_items("Enter: ") - c.close() - print "items=%s" % (items) - - ''' - - def __init__(self, items): - self.items = items - self.initial_input = None - self.item_delims = ' \t,' - self.operator = '=' - self.split_re = re.compile('[%s]+' % self.item_delims) - - def open(self): - # Save state - self.prev_completer = readline.get_completer() - self.prev_completer_delims = readline.get_completer_delims() - - # Set up for ourself - readline.parse_and_bind("tab: complete") - readline.set_completer(self.complete) - readline.set_completer_delims(self.item_delims) - - def close(self): - # Restore previous state - readline.set_completer_delims(self.prev_completer_delims) - readline.set_completer(self.prev_completer) - - def get_item_completions(self, text): - if text: - self.completions = [lhs for lhs in self.items if lhs.startswith(text)] - else: - self.completions = self.items - - def complete(self, state): - self.line_buffer= readline.get_line_buffer() - if state == 0: - beg = readline.get_begidx() - end = readline.get_endidx() - self.get_item_completions(self.line_buffer[beg:end]) - if state >= len(self.completions): return None - return self.completions[state] - - def pre_input_hook(self): - readline.insert_text('%s %s ' % (self.initial_input, self.operator)) - readline.redisplay() - - def read_input(self, prompt, initial_input=None): - items = [] - - self.initial_input = initial_input - try: - if initial_input is None: - readline.set_pre_input_hook(None) - else: - readline.set_pre_input_hook(self.pre_input_hook) - self.line_buffer = raw_input(prompt).strip() - items = self.split_re.split(self.line_buffer) - for item in items[:]: - if not item: items.remove(item) - return items - except EOFError: - return items - - def get_items(self, prompt, must_match=True): - items = [] - - print "Enter name [name ...]" - print "Press <ENTER> to accept, blank line or control-D terminates input" - print "Pressing <TAB> auto completes name" - print - while True: - new_items = self.read_input(prompt) - if not new_items: break - for item in new_items: - if must_match: - if item not in self.items: - print "ERROR: %s is not valid" % (item) - continue - if item in items: continue - items.append(item) - - return items def get_gsserror(e): """ @@ -1446,3 +995,16 @@ def make_sshfp(key): else: return return '%d 1 %s' % (algo, fp) + + +def utf8_encode_value(value): + if isinstance(value, unicode): + return value.encode('utf-8') + return value + + +def utf8_encode_values(values): + if isinstance(values, list) or isinstance(values, tuple): + return map(utf8_encode_value, values) + else: + return utf8_encode_value(values) diff --git a/ipaserver/install/bindinstance.py b/ipaserver/install/bindinstance.py index ce3166122..fa3864a22 100644 --- a/ipaserver/install/bindinstance.py +++ b/ipaserver/install/bindinstance.py @@ -395,7 +395,7 @@ class BindInstance(service.Service): self.domain = domain_name self.forwarders = forwarders self.host = fqdn.split(".")[0] - self.suffix = util.realm_to_suffix(self.realm) + self.suffix = ipautil.realm_to_suffix(self.realm) self.ntp = ntp self.reverse_zone = reverse_zone self.zone_refresh = zone_refresh @@ -614,7 +614,7 @@ class BindInstance(service.Service): self.realm = realm_name self.domain = domain_name self.host = fqdn.split(".")[0] - self.suffix = util.realm_to_suffix(self.realm) + self.suffix = ipautil.realm_to_suffix(self.realm) self.ntp = ntp self.reverse_zone = reverse_zone @@ -622,7 +622,7 @@ class BindInstance(service.Service): def remove_master_dns_records(self, fqdn, realm_name, domain_name): host = fqdn.split(".")[0] - suffix = util.realm_to_suffix(realm_name) + suffix = ipautil.realm_to_suffix(realm_name) zone = domain_name resource_records = ( diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py index 56b84fcd8..af8d39aa5 100644 --- a/ipaserver/install/cainstance.py +++ b/ipaserver/install/cainstance.py @@ -240,7 +240,7 @@ class CADSInstance(service.Service): if host_name and realm_name: self.principal = "dogtagldap/%s@%s" % (self.fqdn, self.realm_name) if realm_name: - self.suffix = util.realm_to_suffix(self.realm_name) + self.suffix = ipautil.realm_to_suffix(self.realm_name) self.__setup_sub_dict() else: self.suffix = None @@ -250,7 +250,7 @@ class CADSInstance(service.Service): subject_base=None): self.ds_port = ds_port self.realm_name = realm_name.upper() - self.suffix = util.realm_to_suffix(self.realm_name) + self.suffix = ipautil.realm_to_suffix(self.realm_name) self.fqdn = host_name self.dm_password = dm_password self.domain = domain_name diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py index 827f69136..359d76664 100644 --- a/ipaserver/install/dsinstance.py +++ b/ipaserver/install/dsinstance.py @@ -167,7 +167,7 @@ class DsInstance(service.Service): self.open_ports = [] self.run_init_memberof = True if realm_name: - self.suffix = util.realm_to_suffix(self.realm_name) + self.suffix = ipautil.realm_to_suffix(self.realm_name) self.__setup_sub_dict() else: self.suffix = None @@ -218,7 +218,7 @@ class DsInstance(service.Service): hbac_allow=True): self.realm_name = realm_name.upper() self.serverid = realm_to_serverid(self.realm_name) - self.suffix = util.realm_to_suffix(self.realm_name) + self.suffix = ipautil.realm_to_suffix(self.realm_name) self.fqdn = fqdn self.dm_password = dm_password self.domain = domain_name @@ -251,7 +251,7 @@ class DsInstance(service.Service): domain_name, dm_password, pkcs12_info=None): self.realm_name = realm_name.upper() self.serverid = realm_to_serverid(self.realm_name) - self.suffix = util.realm_to_suffix(self.realm_name) + self.suffix = ipautil.realm_to_suffix(self.realm_name) self.master_fqdn = master_fqdn self.fqdn = fqdn self.dm_password = dm_password diff --git a/ipaserver/install/httpinstance.py b/ipaserver/install/httpinstance.py index e1bbc30a1..a14115115 100644 --- a/ipaserver/install/httpinstance.py +++ b/ipaserver/install/httpinstance.py @@ -62,7 +62,7 @@ class HTTPInstance(service.Service): self.realm = realm self.domain = domain_name self.dm_password = dm_password - self.suffix = util.realm_to_suffix(self.realm) + self.suffix = ipautil.realm_to_suffix(self.realm) self.pkcs12_info = pkcs12_info self.self_signed_ca = self_signed_ca self.principal = "HTTP/%s@%s" % (self.fqdn, self.realm) diff --git a/ipaserver/install/krbinstance.py b/ipaserver/install/krbinstance.py index f38ae9b42..2faf8e196 100644 --- a/ipaserver/install/krbinstance.py +++ b/ipaserver/install/krbinstance.py @@ -132,7 +132,7 @@ class KrbInstance(service.Service): self.host = host_name.split(".")[0] self.ip = socket.getaddrinfo(host_name, None, socket.AF_UNSPEC, socket.SOCK_STREAM)[0][4][0] self.domain = domain_name - self.suffix = util.realm_to_suffix(self.realm) + self.suffix = ipautil.realm_to_suffix(self.realm) self.kdc_password = ipautil.ipa_generate_password() self.admin_password = admin_password self.dm_password = admin_password diff --git a/ipaserver/install/ldapupdate.py b/ipaserver/install/ldapupdate.py index 90b3691a8..e803df8a2 100644 --- a/ipaserver/install/ldapupdate.py +++ b/ipaserver/install/ldapupdate.py @@ -79,7 +79,7 @@ class LDAPUpdate: krbctx = krbV.default_context() try: self.realm = krbctx.default_realm - suffix = util.realm_to_suffix(self.realm) + suffix = ipautil.realm_to_suffix(self.realm) except krbV.Krb5Error: self.realm = None suffix = None diff --git a/ipaserver/install/replication.py b/ipaserver/install/replication.py index c8c5bc139..ed4caeb7b 100644 --- a/ipaserver/install/replication.py +++ b/ipaserver/install/replication.py @@ -105,7 +105,7 @@ class ReplicationManager(object): self.dirman_passwd = dirman_passwd self.realm = realm self.starttls = starttls - tmp = util.realm_to_suffix(realm) + tmp = ipautil.realm_to_suffix(realm) self.suffix = str(DN(tmp)).lower() self.need_memberof_fixup = False diff --git a/ipaserver/ipaldap.py b/ipaserver/ipaldap.py index 7174072a6..23279aa0b 100644 --- a/ipaserver/ipaldap.py +++ b/ipaserver/ipaldap.py @@ -34,7 +34,7 @@ import ldap.sasl import ldapurl from ldap.controls import LDAPControl from ldap.ldapobject import SimpleLDAPObject -from ipaserver import ipautil +from ipapython import ipautil from ipalib import errors from ipapython.ipautil import format_netloc from ipapython.entity import Entity diff --git a/ipaserver/ipautil.py b/ipaserver/ipautil.py deleted file mode 100644 index 311f50ec3..000000000 --- a/ipaserver/ipautil.py +++ /dev/null @@ -1,141 +0,0 @@ -# Authors: Simo Sorce <ssorce@redhat.com> -# -# Copyright (C) 2007 Red Hat -# see file 'COPYING' for use and warranty information -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# - -import xmlrpclib -import re - -def realm_to_suffix(realm_name): - """ - Convert a kerberos realm into the IPA suffix. - """ - s = realm_name.split(".") - terms = ["dc=" + x.lower() for x in s] - return ",".join(terms) - -class CIDict(dict): - """ - Case-insensitive but case-respecting dictionary. - - This code is derived from python-ldap's cidict.py module, - written by stroeder: http://python-ldap.sourceforge.net/ - - This version extends 'dict' so it works properly with TurboGears. - If you extend UserDict, isinstance(foo, dict) returns false. - """ - - def __init__(self, default=None): - super(CIDict, self).__init__() - self._keys = {} - self.update(default or {}) - - def __getitem__(self, key): - return super(CIDict, self).__getitem__(key.lower()) - - def __setitem__(self, key, value): - lower_key = key.lower() - self._keys[lower_key] = key - return super(CIDict, self).__setitem__(lower_key, value) - - def __delitem__(self, key): - lower_key = key.lower() - del self._keys[lower_key] - return super(CIDict, self).__delitem__(key.lower()) - - def update(self, dict): - for key in dict.keys(): - self[key] = dict[key] - - def has_key(self, key): - return super(CIDict, self).has_key(key.lower()) - - def get(self, key, failobj=None): - try: - return self[key] - except KeyError: - return failobj - - def keys(self): - return self._keys.values() - - def items(self): - result = [] - for k in self._keys.values(): - result.append((k, self[k])) - return result - - def copy(self): - copy = {} - for k in self._keys.values(): - copy[k] = self[k] - return copy - - def iteritems(self): - return self.copy().iteritems() - - def iterkeys(self): - return self.copy().iterkeys() - - def setdefault(self, key, value=None): - try: - return self[key] - except KeyError: - self[key] = value - return value - - def pop(self, key, *args): - try: - value = self[key] - del self[key] - return value - except KeyError: - if len(args) == 1: - return args[0] - raise - - def popitem(self): - (lower_key, value) = super(CIDict, self).popitem() - key = self._keys[lower_key] - del self._keys[lower_key] - - return (key, value) - - -def get_gsserror(e): - """A GSSError exception looks differently in python 2.4 than it does - in python 2.5, deal with it.""" - - try: - primary = e[0] - secondary = e[1] - except Exception: - primary = e[0][0] - secondary = e[0][1] - - return (primary[0], secondary[0]) - -def utf8_encode_value(value): - if isinstance(value, unicode): - return value.encode('utf-8') - return value - -def utf8_encode_values(values): - if isinstance(values, list) or isinstance(values, tuple): - return map(utf8_encode_value, values) - else: - return utf8_encode_value(values) diff --git a/ipaserver/plugins/join.py b/ipaserver/plugins/join.py index 007336387..e7713dc06 100644 --- a/ipaserver/plugins/join.py +++ b/ipaserver/plugins/join.py @@ -21,11 +21,13 @@ Joining an IPA domain """ +import krbV + from ipalib import api, util from ipalib import Command, Str from ipalib import errors -import krbV from ipalib import _ +from ipaserver.install import installutils def get_realm(): """ @@ -52,7 +54,7 @@ class join(Command): validate_host, cli_name='hostname', doc=_("The hostname to register as"), - default_from=lambda: unicode(util.get_fqdn()), + default_from=lambda: unicode(installutils.get_fqdn()), autofill=True, #normalizer=lamda value: value.lower(), ), diff --git a/ipaserver/rpcserver.py b/ipaserver/rpcserver.py index 83c5c2d67..f9a549f4e 100644 --- a/ipaserver/rpcserver.py +++ b/ipaserver/rpcserver.py @@ -31,7 +31,7 @@ from ipalib.backend import Executioner from ipalib.errors import PublicError, InternalError, CommandError, JSONError, ConversionError, CCacheError, RefererError, InvalidSessionPassword from ipalib.request import context, Connection, destroy_context from ipalib.rpc import xml_dumps, xml_loads -from ipalib.util import make_repr, parse_time_duration +from ipalib.util import parse_time_duration from ipalib.dn import DN from ipaserver.plugins.ldap2 import ldap2 from ipapython.compat import json diff --git a/tests/test_ipalib/test_util.py b/tests/test_ipalib/test_util.py index 8304d117b..9d19dfb2c 100644 --- a/tests/test_ipalib/test_util.py +++ b/tests/test_ipalib/test_util.py @@ -21,17 +21,6 @@ Test the `ipalib.util` module. """ -from tests.util import raises from ipalib import util -def test_make_repr(): - """ - Test the `ipalib.util.make_repr` function. - """ - f = util.make_repr - assert f('my') == 'my()' - assert f('my', True, u'hello') == "my(True, u'hello')" - assert f('my', one=1, two='two') == "my(one=1, two='two')" - assert f('my', None, 3, dog='animal', apple='fruit') == \ - "my(None, 3, apple='fruit', dog='animal')" |