DNS Locations: extend server-* command with locations

Server find, server show, server mod should work with IPA locations.

https://fedorahosted.org/freeipa/ticket/2008

Reviewed-By: Petr Spacek <pspacek@redhat.com>
Reviewed-By: Jan Cholasta <jcholast@redhat.com>
This commit is contained in:
Martin Basti 2016-05-11 18:27:37 +02:00
parent 121e34b90e
commit 15abfcf0f7
4 changed files with 121 additions and 9 deletions

20
API.txt
View File

@ -4006,14 +4006,16 @@ output: Output('result', type=[<type 'dict'>])
output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>]) output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
output: ListOfPrimaryKeys('value') output: ListOfPrimaryKeys('value')
command: server_find command: server_find
args: 1,12,4 args: 1,14,4
arg: Str('criteria?') arg: Str('criteria?')
option: Flag('all', autofill=True, cli_name='all', default=False) option: Flag('all', autofill=True, cli_name='all', default=False)
option: Str('cn?', autofill=False, cli_name='name') option: Str('cn?', autofill=False, cli_name='name')
option: DNSNameParam('in_location*', cli_name='in_locations')
option: Int('ipamaxdomainlevel?', autofill=False, cli_name='maxlevel') option: Int('ipamaxdomainlevel?', autofill=False, cli_name='maxlevel')
option: Int('ipamindomainlevel?', autofill=False, cli_name='minlevel') option: Int('ipamindomainlevel?', autofill=False, cli_name='minlevel')
option: Flag('no_members', autofill=True, default=True) option: Flag('no_members', autofill=True, default=True)
option: Str('no_topologysuffix*', cli_name='no_topologysuffixes') option: Str('no_topologysuffix*', cli_name='no_topologysuffixes')
option: DNSNameParam('not_in_location*', cli_name='not_in_locations')
option: Flag('pkey_only?', autofill=True, default=False) option: Flag('pkey_only?', autofill=True, default=False)
option: Flag('raw', autofill=True, cli_name='raw', default=False) option: Flag('raw', autofill=True, cli_name='raw', default=False)
option: Int('sizelimit?', autofill=False) option: Int('sizelimit?', autofill=False)
@ -4024,6 +4026,22 @@ output: Output('count', type=[<type 'int'>])
output: ListOfEntries('result') output: ListOfEntries('result')
output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>]) output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
output: Output('truncated', type=[<type 'bool'>]) output: Output('truncated', type=[<type 'bool'>])
command: server_mod
args: 1,10,3
arg: Str('cn', cli_name='name')
option: Str('addattr*', cli_name='addattr')
option: Flag('all', autofill=True, cli_name='all', default=False)
option: Str('delattr*', cli_name='delattr')
option: DNSNameParam('ipalocation_location?', autofill=False, cli_name='location')
option: Int('ipalocationweight?', autofill=False, cli_name='location_weight')
option: Flag('no_members', autofill=True, default=False)
option: Flag('raw', autofill=True, cli_name='raw', default=False)
option: Flag('rights', autofill=True, default=False)
option: Str('setattr*', cli_name='setattr')
option: Str('version?')
output: Entry('result')
output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
output: PrimaryKey('value')
command: server_show command: server_show
args: 1,5,3 args: 1,5,3
arg: Str('cn', cli_name='name') arg: Str('cn', cli_name='name')

View File

@ -90,5 +90,5 @@ IPA_DATA_VERSION=20100614120000
# # # #
######################################################## ########################################################
IPA_API_VERSION_MAJOR=2 IPA_API_VERSION_MAJOR=2
IPA_API_VERSION_MINOR=174 IPA_API_VERSION_MINOR=175
# Last change: mbasti - location-* commands # Last change: mbasti - server-mod: locations added

View File

@ -106,7 +106,7 @@ class location(LDAPObject):
) )
def get_dn(self, *keys, **options): def get_dn(self, *keys, **options):
loc = keys[-1] loc = keys[0]
assert isinstance(loc, DNSName) assert isinstance(loc, DNSName)
loc_a = loc.ToASCII() loc_a = loc.ToASCII()

View File

@ -6,16 +6,21 @@ import dbus
import dbus.mainloop.glib import dbus.mainloop.glib
from ipalib import api, crud, errors, messages from ipalib import api, crud, errors, messages
from ipalib import Int, Str from ipalib import Int, Str, DNSNameParam
from ipalib.plugable import Registry from ipalib.plugable import Registry
from .baseldap import ( from .baseldap import (
LDAPSearch, LDAPSearch,
LDAPRetrieve, LDAPRetrieve,
LDAPDelete, LDAPDelete,
LDAPObject) LDAPObject,
LDAPUpdate,
)
from ipalib.request import context from ipalib.request import context
from ipalib import _, ngettext from ipalib import _, ngettext
from ipalib import output from ipalib import output
from ipapython.dn import DN
from ipapython.dnsutil import DNSName
__doc__ = _(""" __doc__ = _("""
IPA servers IPA servers
@ -43,18 +48,21 @@ class server(LDAPObject):
object_name = _('server') object_name = _('server')
object_name_plural = _('servers') object_name_plural = _('servers')
object_class = ['top'] object_class = ['top']
possible_objectclasses = ['ipaLocationMember']
search_attributes = ['cn'] search_attributes = ['cn']
default_attributes = [ default_attributes = [
'cn', 'iparepltopomanagedsuffix', 'ipamindomainlevel', 'cn', 'iparepltopomanagedsuffix', 'ipamindomainlevel',
'ipamaxdomainlevel' 'ipamaxdomainlevel', 'ipalocation', 'ipalocationweight'
] ]
label = _('IPA Servers') label = _('IPA Servers')
label_singular = _('IPA Server') label_singular = _('IPA Server')
attribute_members = { attribute_members = {
'iparepltopomanagedsuffix': ['topologysuffix'], 'iparepltopomanagedsuffix': ['topologysuffix'],
'ipalocation': ['location'],
} }
relationships = { relationships = {
'iparepltopomanagedsuffix': ('Managed', '', 'no_'), 'iparepltopomanagedsuffix': ('Managed', '', 'no_'),
'ipalocation': ('IPA', 'in_', 'not_in_'),
} }
takes_params = ( takes_params = (
Str( Str(
@ -87,6 +95,23 @@ class server(LDAPObject):
doc=_('Maximum domain level'), doc=_('Maximum domain level'),
flags={'no_create', 'no_update'}, flags={'no_create', 'no_update'},
), ),
DNSNameParam(
'ipalocation_location?',
cli_name='location',
label=_('Location'),
doc=_('Server location'),
only_relative=True,
flags={'no_search'},
),
Int(
'ipalocationweight?',
cli_name='location_weight',
label=_('Location weight'),
doc=_('Location weight for server'),
minvalue=0,
maxvalue=65535,
flags={'no_search'},
)
) )
def _get_suffixes(self): def _get_suffixes(self):
@ -105,6 +130,67 @@ class server(LDAPObject):
suffixes.get(m, m) for m in entry['iparepltopomanagedsuffix'] suffixes.get(m, m) for m in entry['iparepltopomanagedsuffix']
] ]
def normalize_location(self, kw, **options):
"""
Return the DN of location
"""
if 'ipalocation_location' in kw:
location = kw.pop('ipalocation_location')
kw['ipalocation'] = (
[self.api.Object.location.get_dn(location)]
if location is not None else location
)
def convert_location(self, entry_attrs, **options):
"""
Return a location name from DN
"""
if options.get('raw'):
return
converted_locations = [
DNSName(location_dn['idnsname']) for
location_dn in entry_attrs.pop('ipalocation', [])
]
if converted_locations:
entry_attrs['ipalocation_location'] = converted_locations
@register()
class server_mod(LDAPUpdate):
__doc__ = _('Modify information about an IPA server.')
msg_summary = _('Modified IPA server "%(value)s"')
def args_options_2_entry(self, *args, **options):
kw = super(server_mod, self).args_options_2_entry(
*args, **options)
self.obj.normalize_location(kw, **options)
return kw
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
if entry_attrs.get('ipalocation'):
if not ldap.entry_exists(entry_attrs['ipalocation'][0]):
self.api.Object.location.handle_not_found(
options['ipalocation_location'])
if 'ipalocation' or 'ipalocationweight' in entry_attrs:
server_entry = ldap.get_entry(dn, ['objectclass'])
# we need to extend object with ipaLocationMember objectclass
entry_attrs['objectclass'] = (
server_entry['objectclass'] + ['ipalocationmember']
)
return dn
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
self.obj.convert_location(entry_attrs, **options)
return dn
@register() @register()
class server_find(LDAPSearch): class server_find(LDAPSearch):
@ -114,7 +200,13 @@ class server_find(LDAPSearch):
'%(count)d IPA server matched', '%(count)d IPA server matched',
'%(count)d IPA servers matched', 0 '%(count)d IPA servers matched', 0
) )
member_attributes = ['iparepltopomanagedsuffix'] member_attributes = ['iparepltopomanagedsuffix', 'ipalocation']
def args_options_2_entry(self, *args, **options):
kw = super(server_find, self).args_options_2_entry(
*args, **options)
self.obj.normalize_location(kw, **options)
return kw
def get_options(self): def get_options(self):
for option in super(server_find, self).get_options(): for option in super(server_find, self).get_options():
@ -173,6 +265,8 @@ class server_find(LDAPSearch):
for entry in entries: for entry in entries:
self.obj._apply_suffixes(entry, suffixes) self.obj._apply_suffixes(entry, suffixes)
for entry in entries:
self.obj.convert_location(entry, **options)
return truncated return truncated
@ -184,7 +278,7 @@ class server_show(LDAPRetrieve):
if not options.get('raw', False): if not options.get('raw', False):
suffixes = self.obj._get_suffixes() suffixes = self.obj._get_suffixes()
self.obj._apply_suffixes(entry, suffixes) self.obj._apply_suffixes(entry, suffixes)
self.obj.convert_location(entry, **options)
return dn return dn