def create_without_hooks(self, lo, validate): district = self.get_district() if district: ou = OU(name=district) ou.position = ucr.get('ldap/base') ou.create(lo, False) # setting class_share_file_server and home_share_file_server: # 1. set to None # 2. create school # 3. (maybe) create file_servers <- that is why this is necessary # 4. set file_servers # 5. modify school saved_class_share_file_server = self.class_share_file_server saved_home_share_file_server = self.home_share_file_server self.class_share_file_server = None self.home_share_file_server = None try: success = super(School, self).create_without_hooks(lo, validate) if not success: logger.warning('Creating %r failed (maybe it already exists?)! Trying to set it up nonetheless', self) self.modify_without_hooks(lo) # In a single server environment the default DHCP container must # be set to the DHCP container in the school ou. Otherwise newly # imported computers have the DHCP objects in the wrong DHCP container if ucr.is_true('ucsschool/singlemaster', False): if not ucr.get('dhcpd/ldap/base'): handler_set(['dhcpd/ldap/base=cn=dhcp,%s' % (self.dn)]) ucr.load() self.create_default_containers(lo) self.create_default_groups(lo) self.add_host_to_dc_group(lo) if not self.add_domain_controllers(lo): return False if self.dc_name_administrative: self.create_dc_slave(lo, self.dc_name_administrative, administrative=True) dhcp_service = self.get_dhcp_service(self.dc_name_administrative) dhcp_service.create(lo) dhcp_service.add_server(self.dc_name_administrative, lo) finally: logger.debug('Resetting share file servers from None to %r and %r', saved_home_share_file_server, saved_class_share_file_server) self.class_share_file_server = saved_class_share_file_server self.home_share_file_server = saved_home_share_file_server self.class_share_file_server = self.get_class_share_file_server(lo) self.home_share_file_server = self.get_home_share_file_server(lo) logger.debug('Now it is %r and %r - %r should be modified accordingly', self.home_share_file_server, self.class_share_file_server, self) self.modify_without_hooks(lo) # if requested, then create dhcp_dns policy that clears univentionDhcpDomainNameServers at OU level # to prevent problems with "wrong" DHCP DNS policy connected to ldap base if ucr.is_true('ucsschool/import/generate/policy/dhcp/dns/clearou', False): policy = DHCPDNSPolicy(name='dhcp-dns-clear', school=self.name, empty_attributes=['univentionDhcpDomainNameServers']) policy.create(lo) policy.attach(self, lo) return success
def create_default_groups(self, lo): # DC groups administrative_group_container = 'cn=ucsschool,cn=groups,%s' % ucr.get('ldap/base') # DC-Edukativnetz # OU%s-DC-Edukativnetz # Member-Edukativnetz # OU%s-Member-Edukativnetz administrative_group_names = self.get_administrative_group_name('educational', domain_controller='both', ou_specific='both') if self.shall_create_administrative_objects(): administrative_group_names.extend(self.get_administrative_group_name('administrative', domain_controller='both', ou_specific='both')) # same with Verwaltungsnetz for administrative_group_name in administrative_group_names: group = BasicGroup.cache(name=administrative_group_name, container=administrative_group_container) group.create(lo) # cn=ouadmins admin_group_container = 'cn=ouadmins,cn=groups,%s' % ucr.get('ldap/base') group = BasicGroup.cache(self.group_name('admins', 'admins-'), container=admin_group_container) group.create(lo) group.add_umc_policy(self.get_umc_policy_dn('admins'), lo) try: udm_obj = group.get_udm_object(lo) except noObject: logger.error('Could not load OU admin group %r for adding "school" value', group.dn) else: admin_option = 'ucsschoolAdministratorGroup' if admin_option not in udm_obj.options: udm_obj.options.append(admin_option) udm_obj['school'] = [self.name] udm_obj.modify() # cn=schueler group = Group.cache(self.group_name('pupils', 'schueler-'), self.name) group.create(lo) group.add_umc_policy(self.get_umc_policy_dn('pupils'), lo) # cn=lehrer group = Group.cache(self.group_name('teachers', 'lehrer-'), self.name) group.create(lo) group.add_umc_policy(self.get_umc_policy_dn('teachers'), lo) # cn=mitarbeiter if self.shall_create_administrative_objects(): group = Group.cache(self.group_name('staff', 'mitarbeiter-'), self.name) group.create(lo) group.add_umc_policy(self.get_umc_policy_dn('staff'), lo) if ucr.is_true('ucsschool/import/attach/policy/default-umc-users', True): # cn=Domain Users %s group = Group.cache("Domain Users %s" % (self.name,), self.name) group.create(lo) group.add_umc_policy("cn=default-umc-users,cn=UMC,cn=policies,%s" % (ucr.get('ldap/base'),), lo)
def get_dc_name(self, administrative=False, or_fallback=True): if ucr.is_true('ucsschool/singlemaster', False): return ucr.get('hostname') elif self.dc_name: if administrative: return '%sv' % self.dc_name else: return self.dc_name else: if or_fallback: return self.get_dc_name_fallback(administrative=administrative) else: return None
def validate(self, value): super(DCName, self).validate(value) if value: regex = re.compile('^[a-zA-Z0-9](([a-zA-Z0-9-]*)([a-zA-Z0-9]$))?$') if not regex.match(value): raise ValueError(_('Invalid Domain Controller name')) if ucr.is_true('ucsschool/singlemaster', False): if len(value) > 12: raise ValueError( _('A valid NetBIOS hostname can not be longer than 12 characters.' )) if sum([len(value), 1, len(ucr.get('domainname', ''))]) > 63: raise ValueError( _('The length of fully qualified domain name is greater than 63 characters.' ))
def get_samba_home_path(self, lo): school = School.cache(self.school) # if defined then use UCR value ucr_variable = ucr.get('ucsschool/import/set/sambahome') if ucr_variable is not None: samba_home_path = r'\\%s' % ucr_variable.strip('\\') # in single server environments the master is always the fileserver elif ucr.is_true('ucsschool/singlemaster', False): samba_home_path = r'\\%s' % ucr.get('hostname') # if there's a cached result then use it elif school.dn not in self._samba_home_path_cache: samba_home_path = None # get windows home server from OU object school = self.get_school_obj(lo) home_share_file_server = school.home_share_file_server if home_share_file_server: samba_home_path = r'\\%s' % self.get_name_from_dn( home_share_file_server) self._samba_home_path_cache[school.dn] = samba_home_path else: samba_home_path = self._samba_home_path_cache[school.dn] if samba_home_path is not None: return r'%s\%s' % (samba_home_path, self.name)
def get_district(self): if ucr.is_true('ucsschool/ldap/district/enable'): return self.name[:2]
def shall_create_administrative_objects(self): return ucr.is_true('ucsschool/ldap/noneducational/create/objects', True)
def shall_create_mail_domain(cls): return ucr.is_true('ucsschool/import/generate/mail/domain')
def get_share_path(self): if ucr.is_true('ucsschool/import/roleshare', True): return '/home/%s/groups/%s' % (self.school_group.school, self.name) else: return '/home/groups/%s' % self.name
def add_server(self, dc_name, lo, force_dhcp_server_move=False): """ Create the given DHCP server within the DHCP service. If the DHCP server object already exists somewhere else within the LDAP tree, it may be moved to the DHCP service. PLEASE NOTE: In multiserver environments an existing DHCP server object is always moved to the current DHCP service. In single server environments the DHCP server object is *ONLY* moved, if the UCR variable dhcpd/ldap/base matches to the current DHCP service. """ from ucsschool.lib.models.school import School # create dhcp-server if not exsistant school = School.cache(self.school) dhcp_server = DHCPServer(name=dc_name, school=school.name, dhcp_service=self) existing_dhcp_server_dn = DHCPServer.find_any_dn_with_name(dc_name, lo) if existing_dhcp_server_dn: logger.info('DHCP server %s exists!', existing_dhcp_server_dn) old_dhcp_server_container = lo.parentDn(existing_dhcp_server_dn) dhcpd_ldap_base = ucr.get('dhcpd/ldap/base', '') # only move if # - forced via kwargs OR # - in multiserver environments OR # - desired dhcp server DN matches with UCR config if force_dhcp_server_move or not ucr.is_true( 'ucsschool/singlemaster', False) or dhcp_server.dn.endswith(',%s' % dhcpd_ldap_base): # move if existing DN does not match with desired DN if existing_dhcp_server_dn != dhcp_server.dn: # move existing dhcp server object to OU/DHCP service logger.info( 'DHCP server %s not in school %r! Removing and creating new one at %s!', existing_dhcp_server_dn, school, dhcp_server.dn) old_superordinate = DHCPServer.find_udm_superordinate( existing_dhcp_server_dn, lo) old_dhcp_server = DHCPServer.from_dn( existing_dhcp_server_dn, None, lo, superordinate=old_superordinate) old_dhcp_server.remove(lo) dhcp_server.create(lo) # copy subnets # find local interfaces interfaces = [] for interface_name in set([ key.split('/')[1] for key in ucr.keys() if key.startswith('interfaces/eth') ]): try: address = ipaddr.IPv4Network('%s/%s' % ( ucr['interfaces/%s/address' % interface_name], ucr['interfaces/%s/netmask' % interface_name], )) interfaces.append(address) except ValueError as exc: logger.info('Skipping invalid interface %s:\n%s', interface_name, exc) subnet_dns = DHCPSubnet.find_all_dns_below_base( old_dhcp_server_container, lo) for subnet_dn in subnet_dns: dhcp_service = DHCPSubnet.find_udm_superordinate(subnet_dn, lo) dhcp_subnet = DHCPSubnet.from_dn(subnet_dn, self.school, lo, superordinate=dhcp_service) subnet = dhcp_subnet.get_ipv4_subnet() if subnet in interfaces: # subnet matches any local subnet logger.info('Creating new DHCPSubnet from %s', subnet_dn) new_dhcp_subnet = DHCPSubnet(**dhcp_subnet.to_dict()) new_dhcp_subnet.dhcp_service = self new_dhcp_subnet.position = new_dhcp_subnet.get_own_container( ) new_dhcp_subnet.set_dn(new_dhcp_subnet.dn) new_dhcp_subnet.create(lo) else: logger.info('Skipping non-local subnet %s', subnet) else: logger.info('No DHCP server named %s found! Creating new one!', dc_name) dhcp_server.create(lo)
def validate(self, value): super(SchoolName, self).validate(value) if ucr.is_true('ucsschool/singlemaster', False): regex = re.compile('^[a-zA-Z0-9](([a-zA-Z0-9-]*)([a-zA-Z0-9]$))?$') if not regex.match(value): raise ValueError(_('Invalid school name'))