From e5bec4ae39e7a369e1475bed90505565cbd8c847 Mon Sep 17 00:00:00 2001 From: Rob Crittenden Date: Wed, 13 May 2009 17:16:05 -0400 Subject: [PATCH] Schema change so the nisnetgroup triples work properly. If we use cn for hostname there is no easy way to distinguish between a host and a hostgroup. So adding a fqdn attribute to be used to store the hostname instead. --- install/share/60basev2.ldif | 3 +- ipalib/plugins/host.py | 17 ++++++------ ipaserver/plugins/ldapapi.py | 2 +- tests/test_xmlrpc/test_host_plugin.py | 32 +++++++++++----------- tests/test_xmlrpc/test_hostgroup_plugin.py | 18 ++++++------ tests/test_xmlrpc/test_netgroup_plugin.py | 24 ++++++++-------- 6 files changed, 49 insertions(+), 47 deletions(-) diff --git a/install/share/60basev2.ldif b/install/share/60basev2.ldif index 14ccbf108..3d5089e1f 100644 --- a/install/share/60basev2.ldif +++ b/install/share/60basev2.ldif @@ -3,7 +3,8 @@ attributeTypes: (2.16.840.1.113730.3.8.3.1 NAME 'ipaUniqueID' DESC 'Unique ident attributeTypes: (2.16.840.1.113730.3.8.3.2 NAME 'ipaClientVersion' DESC 'Text string describing client version of the IPA software installed' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'IPA v2' ) attributeTypes: (2.16.840.1.113730.3.8.3.3 NAME 'enrolledBy' DESC 'DN of administrator who performed manual enrollment of the host' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 X-ORIGIN 'IPA v2' ) attributeTypes: (2.16.840.1.113730.3.8.3.4 NAME 'enrollmentPwd' DESC 'Password used to bulk enroll machines' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{128} X-ORIGIN 'IPA v2' ) -objectClasses: (2.16.840.1.113730.3.8.4.1 NAME 'ipaHost' AUXILIARY MAY ( userPassword $ ipaClientVersion $ enrolledBy) X-ORIGIN 'IPA v2' ) +attributeTypes: (2.16.840.1.113730.3.8.3.43 NAME 'fqdn' DESC 'FQDN' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 X-ORIGIN 'IPA v2' ) +objectClasses: (2.16.840.1.113730.3.8.4.1 NAME 'ipaHost' AUXILIARY MUST ( fqdn ) MAY ( userPassword $ ipaClientVersion $ enrolledBy) X-ORIGIN 'IPA v2' ) objectClasses: (2.16.840.1.113730.3.8.4.2 NAME 'ipaService' DESC 'IPA service objectclass' AUXILIARY X-ORIGIN 'IPA v2' ) objectClasses: (2.16.840.1.113730.3.8.4.3 NAME 'nestedGroup' DESC 'Group that supports nesting' SUP groupOfNames STRUCTURAL MAY memberOf X-ORIGIN 'IPA v2' ) objectClasses: (2.16.840.1.113730.3.8.4.4 NAME 'ipaUserGroup' DESC 'IPA user group object class' SUP nestedGroup STRUCTURAL X-ORIGIN 'IPA v2' ) diff --git a/ipalib/plugins/host.py b/ipalib/plugins/host.py index c136ccabd..cd62c6221 100644 --- a/ipalib/plugins/host.py +++ b/ipalib/plugins/host.py @@ -40,21 +40,21 @@ def get_host(hostname): if hostname.endswith('.'): hostname = hostname[:-1] try: - dn = ldap.find_entry_dn("cn", hostname, "ipaHost") + dn = ldap.find_entry_dn("fqdn", hostname, "ipaHost") except errors.NotFound: dn = ldap.find_entry_dn("serverhostname", hostname, "ipaHost") return dn -def validate_host(ugettext, cn): +def validate_host(ugettext, fqdn): """ Require at least one dot in the hostname (to support localhost.localdomain) """ - dots = len(cn.split('.')) + dots = len(fqdn.split('.')) if dots < 2: return 'Fully-qualified hostname required' return None -default_attributes = ['cn','description','localityname','nshostlocation','nshardwareplatform','nsosversion'] +default_attributes = ['fqdn','description','localityname','nshostlocation','nshardwareplatform','nsosversion'] def determine_os(): (sysname, nodename, release, version, machine) = os.uname() @@ -74,7 +74,7 @@ class host(Object): Host object. """ takes_params = ( - Str('cn', validate_host, + Str('fqdn', validate_host, cli_name='hostname', primary_key=True, normalizer=lambda value: value.lower(), @@ -127,11 +127,13 @@ class host_add(crud.Add): :param hostname: The name of the host being added. :param kw: Keyword arguments for the other LDAP attributes. """ + assert 'fqdn' not in kw assert 'cn' not in kw assert 'dn' not in kw assert 'krbprincipalname' not in kw ldap = self.api.Backend.ldap + kw['fqdn'] = hostname kw['cn'] = hostname kw['serverhostname'] = hostname.split('.',1)[0] kw['dn'] = ldap.make_host_dn(hostname) @@ -221,7 +223,7 @@ class host_mod(crud.Mod): :param hostname: The name of the host to retrieve. :param kw: Keyword arguments for the other LDAP attributes. """ - assert 'cn' not in kw + assert 'fqdn' not in kw assert 'dn' not in kw ldap = self.api.Backend.ldap dn = get_host(hostname) @@ -258,13 +260,12 @@ class host_find(crud.Find): # FIXME: add this attribute to cn=ipaconfig #search_fields_conf_str = config.get('ipahostsearchfields') #search_fields = search_fields_conf_str.split(",") - search_fields = ['cn','serverhostname','description','localityname','nshostlocation','nshardwareplatform','nsosversion'] + search_fields = ['fqdn','serverhostname','description','localityname','nshostlocation','nshardwareplatform','nsosversion'] search_kw = {} for s in search_fields: search_kw[s] = term - # Can't use ldap.get_object_type() since cn is also used for group dns search_kw['objectclass'] = "ipaHost" if kw.get('all', False): search_kw['attributes'] = ['*'] diff --git a/ipaserver/plugins/ldapapi.py b/ipaserver/plugins/ldapapi.py index cb55f1cfa..3d62507e7 100644 --- a/ipaserver/plugins/ldapapi.py +++ b/ipaserver/plugins/ldapapi.py @@ -109,7 +109,7 @@ class ldap(CrudBackend): """ Construct host dn from hostname """ - return 'cn=%s,%s,%s' % ( + return 'fqdn=%s,%s,%s' % ( self.dn.escape_dn_chars(hostname), self.api.env.container_host, self.api.env.basedn, diff --git a/tests/test_xmlrpc/test_host_plugin.py b/tests/test_xmlrpc/test_host_plugin.py index 11676d08a..6af53834f 100644 --- a/tests/test_xmlrpc/test_host_plugin.py +++ b/tests/test_xmlrpc/test_host_plugin.py @@ -31,10 +31,10 @@ class test_Host(XMLRPC_test): """ Test the `f_host` plugin. """ - cn = u'ipatesthost.%s' % api.env.domain + fqdn = u'ipatesthost.%s' % api.env.domain description = u'Test host' localityname = u'Undisclosed location' - kw={'cn': cn, 'description': description, 'localityname': localityname} + kw={'fqdn': fqdn, 'description': description, 'localityname': localityname} def test_add(self): """ @@ -43,52 +43,52 @@ class test_Host(XMLRPC_test): res = api.Command['host_add'](**self.kw) assert type(res) is dict assert res['description'] == self.description - assert res['cn'] == self.cn + assert res['fqdn'] == self.fqdn assert res['l'] == self.localityname def test_doshow_all(self): """ Test the `xmlrpc.host_show` method with all attributes. """ - kw={'cn':self.cn, 'all': True} + kw={'fqdn':self.fqdn, 'all': True} res = api.Command['host_show'](**kw) assert res assert res.get('description','') == self.description - assert res.get('cn','') == self.cn + assert res.get('fqdn','') == self.fqdn assert res.get('l','') == self.localityname def test_doshow_minimal(self): """ Test the `xmlrpc.host_show` method with default attributes. """ - kw={'cn':self.cn} + kw={'fqdn':self.fqdn} res = api.Command['host_show'](**kw) assert res assert res.get('description','') == self.description - assert res.get('cn','') == self.cn + assert res.get('fqdn','') == self.fqdn assert res.get('localityname','') == self.localityname def test_find_all(self): """ Test the `xmlrpc.host_find` method with all attributes. """ - kw={'cn':self.cn, 'all': True} + kw={'fqdn':self.fqdn, 'all': True} res = api.Command['host_find'](**kw) assert res assert len(res) == 2 assert res[1].get('description','') == self.description - assert res[1].get('cn','') == self.cn + assert res[1].get('fqdn','') == self.fqdn assert res[1].get('l','') == self.localityname def test_find_minimal(self): """ Test the `xmlrpc.host_find` method with default attributes. """ - res = api.Command['host_find'](self.cn) + res = api.Command['host_find'](self.fqdn) assert res assert len(res) == 2 assert res[1].get('description','') == self.description - assert res[1].get('cn','') == self.cn + assert res[1].get('fqdn','') == self.fqdn assert res[1].get('localityname','') == self.localityname def test_mod(self): @@ -96,27 +96,27 @@ class test_Host(XMLRPC_test): Test the `xmlrpc.host_mod` method. """ newdesc = u'Updated host' - modkw={'cn': self.cn, 'description': newdesc} + modkw={'fqdn': self.fqdn, 'description': newdesc} res = api.Command['host_mod'](**modkw) assert res assert res.get('description','') == newdesc # Ok, double-check that it was changed - res = api.Command['host_show'](self.cn) + res = api.Command['host_show'](self.fqdn) assert res assert res.get('description','') == newdesc - assert res.get('cn','') == self.cn + assert res.get('fqdn','') == self.fqdn def test_remove(self): """ Test the `xmlrpc.host_del` method. """ - res = api.Command['host_del'](self.cn) + res = api.Command['host_del'](self.fqdn) assert res == True # Verify that it is gone try: - res = api.Command['host_show'](self.cn) + res = api.Command['host_show'](self.fqdn) except errors.NotFound: pass else: diff --git a/tests/test_xmlrpc/test_hostgroup_plugin.py b/tests/test_xmlrpc/test_hostgroup_plugin.py index 34aea6724..23e1c6b8c 100644 --- a/tests/test_xmlrpc/test_hostgroup_plugin.py +++ b/tests/test_xmlrpc/test_hostgroup_plugin.py @@ -35,7 +35,7 @@ class test_Host(XMLRPC_test): description=u'Test host group' kw={'cn': cn, 'description': description} - host_cn = u'ipatesthost.%s' % api.env.domain + host_fqdn = u'ipatesthost.%s' % api.env.domain host_description = u'Test host' host_localityname = u'Undisclosed location' @@ -52,18 +52,18 @@ class test_Host(XMLRPC_test): """ Add a host to test add/remove member. """ - kw={'cn': self.host_cn, 'description': self.host_description, 'localityname': self.host_localityname} + kw={'fqdn': self.host_fqdn, 'description': self.host_description, 'localityname': self.host_localityname} res = api.Command['host_add'](**kw) assert res assert res.get('description','') == self.host_description - assert res.get('cn','') == self.host_cn + assert res.get('fqdn','') == self.host_fqdn def test_addmember(self): """ Test the `xmlrpc.hostgroup_add_member` method. """ kw={} - kw['hosts'] = self.host_cn + kw['hosts'] = self.host_fqdn res = api.Command['hostgroup_add_member'](self.cn, **kw) assert res == tuple() @@ -75,7 +75,7 @@ class test_Host(XMLRPC_test): assert res assert res.get('description','') == self.description assert res.get('cn','') == self.cn - assert res.get('member','').startswith('cn=%s' % self.host_cn) + assert res.get('member','').startswith('fqdn=%s' % self.host_fqdn) def test_find(self): """ @@ -86,7 +86,7 @@ class test_Host(XMLRPC_test): assert len(res) == 2, res assert res[1].get('description','') == self.description assert res[1].get('cn','') == self.cn - assert res[1].get('member','').startswith('cn=%s' % self.host_cn) + assert res[1].get('member','').startswith('fqdn=%s' % self.host_fqdn) def test_mod(self): """ @@ -109,7 +109,7 @@ class test_Host(XMLRPC_test): Test the `xmlrpc.hostgroup_remove_member` method. """ kw={} - kw['hosts'] = self.host_cn + kw['hosts'] = self.host_fqdn res = api.Command['hostgroup_remove_member'](self.cn, **kw) assert res == tuple() @@ -132,12 +132,12 @@ class test_Host(XMLRPC_test): """ Test the `xmlrpc.host_del` method. """ - res = api.Command['host_del'](self.host_cn) + res = api.Command['host_del'](self.host_fqdn) assert res == True # Verify that it is gone try: - res = api.Command['host_show'](self.host_cn) + res = api.Command['host_show'](self.host_fqdn) except errors.NotFound: pass else: diff --git a/tests/test_xmlrpc/test_netgroup_plugin.py b/tests/test_xmlrpc/test_netgroup_plugin.py index 84986fa52..e5de2557d 100644 --- a/tests/test_xmlrpc/test_netgroup_plugin.py +++ b/tests/test_xmlrpc/test_netgroup_plugin.py @@ -45,10 +45,10 @@ class test_Netgroup(XMLRPC_test): ng_description=u'Netgroup' ng_kw={'cn': ng_cn, 'description': ng_description, 'nisdomainname': u'example.com'} - host_cn = u'ipatesthost.%s' % api.env.domain + host_fqdn = u'ipatesthost.%s' % api.env.domain host_description=u'Test host' host_localityname=u'Undisclosed location' - host_kw={'cn': host_cn, 'description': host_description, 'localityname': host_localityname} + host_kw={'fqdn': host_fqdn, 'description': host_description, 'localityname': host_localityname} hg_cn=u'ng1' hg_description=u'Netgroup' @@ -82,7 +82,7 @@ class test_Netgroup(XMLRPC_test): res = api.Command['host_add'](**self.host_kw) assert res assert res.get('description','') == self.host_description - assert res.get('cn','') == self.host_cn + assert res.get('fqdn','') == self.host_fqdn # Add a hostgroup res = api.Command['hostgroup_add'](**self.hg_kw) @@ -107,7 +107,7 @@ class test_Netgroup(XMLRPC_test): Test the `xmlrpc.netgroup_add_member` method. """ kw={} - kw['hosts'] = self.host_cn + kw['hosts'] = self.host_fqdn res = api.Command['netgroup_add_member'](self.ng_cn, **kw) assert res == tuple() @@ -131,9 +131,9 @@ class test_Netgroup(XMLRPC_test): Test the `xmlrpc.netgroup_add_member` method again to test dupes. """ kw={} - kw['hosts'] = self.host_cn + kw['hosts'] = self.host_fqdn res = api.Command['netgroup_add_member'](self.ng_cn, **kw) - assert is_member_of(res, 'cn=%s' % self.host_cn) + assert is_member_of(res, 'fqdn=%s' % self.host_fqdn) kw={} kw['hostgroups'] = self.hg_cn @@ -170,7 +170,7 @@ class test_Netgroup(XMLRPC_test): assert res assert res.get('description','') == self.ng_description assert res.get('cn','') == self.ng_cn - assert is_member_of(res.get('memberhost',[]), 'cn=%s' % self.host_cn) + assert is_member_of(res.get('memberhost',[]), 'fqdn=%s' % self.host_fqdn) assert is_member_of(res.get('memberhost',[]), 'cn=%s' % self.hg_cn) assert is_member_of(res.get('memberuser',[]), 'uid=%s' % self.user_uid) assert is_member_of(res.get('memberuser',[]), 'cn=%s' % self.group_cn) @@ -206,7 +206,7 @@ class test_Netgroup(XMLRPC_test): Test the `xmlrpc.hostgroup_remove_member` method. """ kw={} - kw['hosts'] = self.host_cn + kw['hosts'] = self.host_fqdn res = api.Command['netgroup_remove_member'](self.ng_cn, **kw) assert res == tuple() @@ -230,9 +230,9 @@ class test_Netgroup(XMLRPC_test): Test the `xmlrpc.netgroup_remove_member` method again to test not found. """ kw={} - kw['hosts'] = self.host_cn + kw['hosts'] = self.host_fqdn res = api.Command['netgroup_remove_member'](self.ng_cn, **kw) - assert is_member_of(res, 'cn=%s' % self.host_cn) + assert is_member_of(res, 'fqdn=%s' % self.host_fqdn) kw={} kw['hostgroups'] = self.hg_cn @@ -269,12 +269,12 @@ class test_Netgroup(XMLRPC_test): Remove the test data we added """ # Remove the host - res = api.Command['host_del'](self.host_cn) + res = api.Command['host_del'](self.host_fqdn) assert res == True # Verify that it is gone try: - res = api.Command['host_show'](self.host_cn) + res = api.Command['host_show'](self.host_fqdn) except errors.NotFound: pass else: