def reconnect_to_clients(self): router_obj = config_tools.RouterObject(self.log) self.log("reconnecting to {}".format(logging_tools.get_plural("client", len(Client.name_set)))) all_servers = config_tools.icswDeviceWithConfig(service_type_enum=icswServiceEnum.package_server) if icswServiceEnum.package_server not in all_servers: self.log("no package_server defined, strange...", logging_tools.LOG_LEVEL_ERROR) else: _pserver = all_servers[icswServiceEnum.package_server][0] if _pserver.effective_device.pk != global_config["SERVER_IDX"]: self.log( "effective_device pk differs from SERVER_IDX: {:d} != {:d}".format( _pserver.effective_device.pk, global_config["SERVER_IDX"] ), logging_tools.LOG_LEVEL_ERROR ) else: for target_name in Client.name_set: cur_c = Client.get(target_name) dev_sc = config_tools.icswServerCheck( device=cur_c.device, # config="", fetch_network_info=True ) act_routing_info = _pserver.get_route_to_other_device( router_obj, dev_sc, allow_route_to_other_networks=True, prefer_production_net=True, ) if act_routing_info: _ip = act_routing_info[0][3][1][0] self.log("found routing_info for {}, IP is {}".format(str(cur_c.device), _ip)) self.connect_client(cur_c.device, _ip) # self.send_reply(cur_c.uid, server_command.srv_command(command="hello")) else: self.log("no routing_info found for {}".format(str(cur_c.device)))
def _generate_config_step2(self, cur_c, b_dev, act_prod_net, boot_netdev, dev_sc): self.router_obj.check_for_update() running_ip = [ ip.ip for ip in dev_sc.identifier_ip_lut["p"] if dev_sc.ip_netdevice_lut[ip.ip].pk == boot_netdev.pk ][0] cur_c.log( "IP in production network '{}' is {}, network_postfix is '{}'". format(act_prod_net.identifier, running_ip, act_prod_net.postfix)) # multiple configs multiple_configs = [icswServiceEnum.cluster_server] all_servers = config_tools.icswDeviceWithConfig(service_type_enum=None) def_servers = all_servers.get(icswServiceEnum.cluster_server, []) # def_servers = [] if not def_servers: cur_c.log("no Servers found", logging_tools.LOG_LEVEL_ERROR, state="done") else: srv_names = sorted([ "{}{}".format(cur_srv.short_host_name, act_prod_net.postfix) for cur_srv in def_servers ]) cur_c.log("{} found: {}".format( logging_tools.get_plural("server", len(def_servers)), ", ".join(srv_names))) # store in act_prod_net conf_dict = {} conf_dict["servers"] = srv_names # custom Enum cannot be compared against each other for srv_type in all_servers.keys(): if srv_type not in multiple_configs: routing_info, act_server, routes_found = ([66666666], None, 0) for actual_server in all_servers[srv_type]: act_routing_info = actual_server.get_route_to_other_device( self.router_obj, dev_sc, filter_ip=running_ip, allow_route_to_other_networks=True) if act_routing_info: routes_found += 1 # store in some dict-like structure # print "***", actual_server.short_host_name, dir(actual_server) # FIXME, postfix not handled conf_dict["{}:{}".format( actual_server.short_host_name, srv_type.name )] = actual_server.device.full_name conf_dict["{}:{}_ip".format( actual_server.short_host_name, srv_type.name)] = act_routing_info[0][2][1][0] if srv_type in [ icswServiceEnum.config_server, icswServiceEnum.mother_server ] and actual_server.device.pk == b_dev.bootserver_id: routing_info, act_server = ( act_routing_info[0], actual_server) else: if act_routing_info[0][0] < routing_info[0]: routing_info, act_server = ( act_routing_info[0], actual_server) else: cur_c.log( "empty routing info for {} to {}".format( srv_type.name, actual_server.device.name, ), logging_tools.LOG_LEVEL_WARN) if act_server: server_ip = routing_info[2][1][0] # map from server_ip to localized name try: conf_dict[srv_type.name] = net_ip.objects.get( Q(ip=server_ip)).full_name except net_ip.MultipleObjectsReturned: cur_c.log( "more than one net_ip found for server_type {} (IP {})" .format( srv_type.name, server_ip, ), logging_tools.LOG_LEVEL_ERROR) raise conf_dict["{}_ip".format(srv_type.name)] = server_ip try: conf_dict["{}_uuid".format( srv_type.name)] = get_server_uuid( srv_type, act_server.device.uuid) except KeyError: self.log( " ... encountered slave config {}".format( srv_type.name), logging_tools.LOG_LEVEL_WARN) cur_c.log(" {:<20s}: {:<25s} (IP {:15s}){}".format( srv_type.name, conf_dict[srv_type.name], server_ip, " (best of {} found)".format( logging_tools.get_plural( "route", routes_found)) if routes_found > 1 else "")) else: cur_c.log(" {:20s}: not found".format(srv_type.name)) new_img = b_dev.new_image if new_img: conf_dict["system"] = { "vendor": new_img.sys_vendor, "version": new_img.sys_version, "release": new_img.sys_release, } else: self.log("no image defined, using defaults") conf_dict["system"] = { "vendor": "suse", "version": 13, "release": 1, } conf_dict["device"] = b_dev conf_dict["net"] = act_prod_net conf_dict["host"] = b_dev.name conf_dict["hostfq"] = b_dev.full_name conf_dict["device_idx"] = b_dev.pk # image is missing, FIXME # # dc.execute("SELECT * FROM image WHERE image_idx=%s", (self["new_image"])) # # if dc.rowcount: # # act_prod_net["image"] = dc.fetchone() # # else: # # act_prod_net["image"] = {} config_pks = list( config.objects.filter( Q(device_config__device=b_dev) | (Q(device_config__device__device_group=b_dev. device_group_id) & Q(device_config__device__is_meta_device=True))). order_by("-priority", "name").distinct().values_list("pk", flat=True)) pseudo_config_list = config.objects.all().prefetch_related( "config_str_set", "config_int_set", "config_bool_set", "config_blob_set", "config_script_set").order_by("-priority", "name") config_dict = {cur_pc.pk: cur_pc for cur_pc in pseudo_config_list} # copy variables for p_config in pseudo_config_list: for var_type in ["str", "int", "bool", "blob"]: for cur_var in getattr( p_config, "config_{}_set".format(var_type)).all(): conf_dict["{}.{}".format(p_config.name, cur_var.name)] = cur_var.value for _cur_conf in pseudo_config_list: # cur_conf.show_variables(cur_c.log, detail=global_config["DEBUG"]) pass cur_c.log("{} found: {}".format( logging_tools.get_plural("config", len(config_pks)), ", ".join([config_dict[pk].name for pk in config_pks]) if config_pks else "no configs", )) # node interfaces conf_dict["node_if"] = [] taken_list, not_taken_list = ([], []) for cur_net in b_dev.netdevice_set.exclude( Q(enabled=False)).prefetch_related( "net_ip_set", "net_ip_set__network", "net_ip_set__network__network_type", "net_ip_set__domain_tree_node"): for cur_ip in cur_net.net_ip_set.all(): # if cur_ip.network_id if cur_ip.network_id in act_prod_net.idx_list: take_it, cause = (True, "network_index in list") elif cur_ip.network.network_type.identifier == "l": take_it, cause = (True, "network_type is loopback") else: if cur_ip.domain_tree_node and cur_ip.domain_tree_node.always_create_ip: take_it, cause = ( True, "network_index not in list but always_create_ip set" ) else: take_it, cause = ( False, "network_index not in list and always_create_ip not set" ) if take_it: conf_dict["node_if"].append(cur_ip) taken_list.append((cur_ip, cause)) else: not_taken_list.append((cur_ip, cause)) cur_c.log("{} in taken_list".format( logging_tools.get_plural("Netdevice", len(taken_list)))) for entry, cause in taken_list: cur_c.log( " - {:<6s} (IP {:<15s}, network {:<20s}) : {}".format( entry.netdevice.devname, entry.ip, str(entry.network), cause)) cur_c.log("{} in not_taken_list".format( logging_tools.get_plural("Netdevice", len(not_taken_list)))) for entry, cause in not_taken_list: cur_c.log( " - {:<6s} (IP {:<15s}, network {:<20s}) : {}".format( entry.netdevice.devname, entry.ip, str(entry.network), cause)) if cur_c.command == "get_config_vars": cur_c.var_tuple_list = self._generate_vtl(conf_dict) cur_c.add_set_keys("var_tuple_list") cur_c.log("vars created", state="done") elif cur_c.command == "build_config": # create config # dict: which config was called (sucessfully) conf_dict["called"] = {} cur_c.conf_dict, cur_c.link_dict, cur_c.erase_dict = ({}, {}, {}) # cur_c.conf_dict[config_obj.dest] = config_obj new_tree = GeneratedTree() cur_bc = BuildContainer(cur_c, config_dict, conf_dict, new_tree, self.router_obj) for pk in config_pks: cur_bc.process_scripts(pk) new_tree.write_node_config(cur_c, cur_bc) if False in conf_dict["called"]: cur_c.log("error in scripts for {}: {}".format( logging_tools.get_plural( "config", len(conf_dict["called"][False])), ", ".join( sorted([ str(config_dict[pk]) for pk, err_lines in conf_dict["called"][False] ]))), logging_tools.LOG_LEVEL_ERROR, state="done") cur_c.add_set_keys("error_dict") cur_c.error_dict = { str(config_dict[pk]): err_lines for pk, err_lines in conf_dict["called"][False] } else: cur_c.log("config built", state="done") cur_bc.close() else: cur_c.log("unknown action '{}'".format(cur_c.command), logging_tools.LOG_LEVEL_ERROR, state="done")
def _build_resolv_dict(self): # local device _myself = icswServerCheck(fetch_network_info=True) _router = RouterObject(self.logger) enum_set = set() # build reverse lut _rv_lut = {} _INSTANCES_WITH_NAMES = set() # list of configs with node-splitting enabled node_split_list = [] for _inst in _INSTANCE.get_all_instances(): _inst_name = _inst.attrib["name"] if _INSTANCE.do_node_split(_inst): node_split_list.append(_inst_name) for _enum_name in _INSTANCE.get_config_enums(_inst): _srv_enum = getattr(icswServiceEnum, _enum_name) if _srv_enum.value.server_service: enum_set.add(_srv_enum) _INSTANCES_WITH_NAMES.add(_srv_enum.name) _rv_lut.setdefault(_srv_enum, []).append( _inst_name) # [_conf_name] = _inst_name # for key, value in _SRV_NAME_TYPE_MAPPING.iteritems(): # _rv_lut.update({_name: key for _name in value}) # resolve dict _resolv_dict = {} # list of all already used srv_type / config_name / device_idx tuples _used_tuples = set() # dict resolving all srv_type / device_idx to set configs _dev_srv_type_lut = {} # simple routing cache routing_cache = {} # unroutable configs _unroutable_configs = {} # device -> network cache dn_cache = {} # get all configs for _enum in enum_set: _srv_type_list = _rv_lut[_enum] _sc = icswDeviceWithConfig( service_type_enum=_enum, dn_cache=dn_cache, ) if _enum in _sc: for _dev in _sc[_enum]: _dev_scr = _dev.get_result() if _dev_scr.effective_device is None: # may be the case when the local system is too old (database-wise) continue # routing info if _dev_scr.effective_device.is_meta_device: # server-like config is set for an md-device, not good self.log( "device '{}' (srv_type_list {}) is a meta-device". format( _dev_scr.effective_device.full_name, self._srv_type_to_string(_srv_type_list), ), logging_tools.LOG_LEVEL_ERROR) else: if _myself.device and _dev_scr.effective_device.pk == _myself.device.pk: _first_ip = "127.0.0.1" _penalty = 1 else: # print _myself, dir(_myself) _ri = _dev.get_route_to_other_device( _router, _myself, allow_route_to_other_networks=True, prefer_production_net=True, cache=routing_cache, ) if _ri: _first_ri = _ri[0] _first_ip = _first_ri[2][1][0] _penalty = _first_ri[0] else: _first_ip = None if _first_ip: # print "*", _srv_type_list # for _srv_type in _srv_type_list: if True: _add_t = (_enum, _dev_scr.effective_device.pk) if _add_t not in _used_tuples: _used_tuples.add(_add_t) # lookup for simply adding new config names _dst_key = (_enum, _dev_scr.effective_device.pk) if _dst_key in _dev_srv_type_lut: _ce = [ _entry for _entry in _resolv_dict[_enum] if _entry[2] == _dev_scr.effective_device.pk ][0] _ce[4].append(_enum.name) else: _resolv_dict.setdefault( _enum.name, []).append(( _dev_scr.effective_device. full_name, _first_ip, _dev_scr.effective_device.pk, _penalty, [_enum.name], )) _dev_srv_type_lut.setdefault( _dst_key, []).append(_enum_name) self.log( "adding device '{}' (IP {}, EffPK={:d}) to srv_type {}" .format( _dev_scr.effective_device. full_name, _first_ip, _dev_scr.effective_device.pk, _enum.name, )) else: if not self.ignore_errors: self.log( "no route to device '{}' found (srv_type_list {})" .format( _dev_scr.effective_device.full_name, self._srv_type_to_string( _srv_type_list), ), logging_tools.LOG_LEVEL_ERROR, ) _unroutable_configs.setdefault( _enum_name, []).append(_dev_scr.effective_device.full_name) # missing routes _missing_srv = _INSTANCES_WITH_NAMES - set(_resolv_dict.keys()) if _missing_srv: for _srv_type in sorted(_missing_srv): self.log("no device for srv_type '{}' found".format(_srv_type), logging_tools.LOG_LEVEL_WARN) # sort entry for key, value in _resolv_dict.items(): # format: device name, device IP, device_pk, penalty _resolv_dict[key] = [ _v2[1] for _v2 in sorted([(_v[3], _v) for _v in value]) ] # set local device if _myself.device is not None: _resolv_dict["_local_device"] = (_myself.device.pk, ) _resolv_dict["_server_info_str"] = _myself.get_result().server_info_str _resolv_dict["_alias_dict"] = _INSTANCE.get_alias_dict() _resolv_dict["_node_split_list"] = node_split_list _resolv_dict["_unroutable_configs"] = _unroutable_configs # import pprint # pprint.pprint(_resolv_dict) # valid for 15 minutes cache.set(self.ROUTING_KEY, json.dumps(_resolv_dict), 60 * 15) return _resolv_dict
def write_dhcp_config(self): if not global_config["WRITE_DHCP_CONFIG"]: self.log("altering the DHCP-config disabled", logging_tools.LOG_LEVEL_WARN) return is_authoritative = global_config["DHCP_AUTHORITATIVE"] self.log("writing dhcp-config, {}".format("auth" if is_authoritative else "not auth")) my_c = config_tools.icswServerCheck(service_type_enum=icswServiceEnum.mother_server) boot_ips = my_c.identifier_ip_lut.get("b", []) if not boot_ips: self.log( "error no boot-net found", logging_tools.LOG_LEVEL_ERROR, ) else: add_nets = list( [ ( cur_net.network_type.identifier, cur_net ) for cur_net in network.objects.exclude( pk__in=[boot_ip.network.pk for boot_ip in boot_ips] ).filter( Q(net_ip__netdevice__device=my_c.get_result().effective_device) & Q(network_type__identifier__in=["s", "p", "o"]) ).distinct() ] ) add_nets = sum( [ [ _sub_net for _value, _sub_net in add_nets if _value == _t_val ] for _t_val in ["p", "s", "o"] ], [] ) dhcpd_c = [ "", "# created from mother on {}".format(time.ctime(time.time())), "", "ddns-update-style none;", "omapi-port 7911;", "ddns-domainname \"{}\";".format(global_config["SERVER_SHORT_NAME"]), "allow booting;\nallow bootp;", "", "option space PXE;", "option PXE.mtftp-ip code 1 = ip-address;", "option PXE.mtftp-cport code 2 = unsigned integer 16;", "option PXE.mtftp-tmout code 4 = unsigned integer 8;", "option PXE.mtftp-delay code 5 = unsigned integer 8;", "option arch code 93 = unsigned integer 16;", "", ] if is_authoritative: dhcpd_c.extend( [ "authoritative;", "", ] ) # get gateway and domain-servers for the various nets gw_pri, gateway = (-10000, "0.0.0.0") cur_dc = config_tools.icswDeviceWithConfig(service_type_enum=icswServiceEnum.mother_server) found_dict = {} for act_net in [boot_ip.network for boot_ip in boot_ips] + add_nets: if act_net.gw_pri > gw_pri: gw_pri, gateway = (act_net.gw_pri, act_net.gateway) for key, configs, _add_dict in [ ("domain-name-servers", ["name_server", "name_slave"], {}), ("ntp-servers", ["xntp_server"], {}), ("nis-servers", ["yp_server"], {"domainname": "nis-domain"}) ]: found_confs = set(cur_dc.keys()) & set(configs) if found_confs: # some configs found for found_conf in found_confs: for cur_srv in cur_dc[found_conf]: match_list = [cur_ip for cur_ip in cur_srv.ip_list if cur_ip.network.pk == act_net.pk] if match_list: found_dict.setdefault(act_net.pk, {}).setdefault(key, []).append((cur_srv.device, match_list)) dhcpd_c.extend( [ "shared-network {} {{".format(global_config["SERVER_SHORT_NAME"]), # do not write routers (gateway may be invalid) # " option routers {};".format(gateway) ] ) DHCPNetwork.setup(my_c, found_dict) for act_net in [boot_ip.network for boot_ip in boot_ips] + add_nets: if act_net.netmask == "0.0.0.0": self.log( "refuse network {} with netmask '{}'".format( str(act_net), act_net.netmask, ), logging_tools.LOG_LEVEL_ERROR ) else: _net = DHCPNetwork(act_net) if global_config["DHCP_ONLY_BOOT_NETWORKS"] and act_net.network_type.identifier != "b": _net.comment_content() dhcpd_c.extend(_net.content) dhcpd_c.extend( [ "}", "", ] ) _target_file = None for _tf in ["/etc/dhcp/dhcpd.conf", "/etc/dhcp3/dhcpd.conf", "/etc/dhcpd.conf"]: if os.path.isfile(_tf): self.log("found dhcp-config in {}".format(_tf)) _target_file = _tf break if not _target_file: self.log("no DHCP config file found", logging_tools.LOG_LEVEL_ERROR) else: open(_target_file, "w").write("\n".join(dhcpd_c)) self.log("wrote DHCP config to {}".format(_target_file)) for _srv_name in self.srv_helper.find_services(".*dhcpd.*"): self.srv_helper.service_command(_srv_name, "restart")
def run(self, cur_bg): # step 1: create user homes _uo = user.objects create_user_list = _uo.exclude(Q(export=None)).filter( Q(home_dir_created=False) & Q(active=True) & Q(group__active=True)).select_related("export__device") to_run = [] if create_user_list.count(): self.log("{} to create".format( logging_tools.get_plural("user home", len(create_user_list)))) for create_user in create_user_list: srv_com = server_command.srv_command( command="create_user_home") srv_com["server_key:username"] = create_user.login to_run.append(( background_job_run( background_job=cur_bg, server=create_user.export.device, command_xml=str(srv_com), start=cluster_timezone.localize( datetime.datetime.now()), ), srv_com, icswServiceEnum.cluster_server, # )) else: self.log("no user homes to create", logging_tools.LOG_LEVEL_WARN) # check directory sync requests no_device = [] for _config, _command, _srv_type in [ ("ldap_server", "sync_ldap_config", icswServiceEnum.cluster_server), ("yp_server", "write_yp_config", icswServiceEnum.cluster_server), ("monitor_server", "sync_http_users", icswServiceEnum.monitor_server), ]: _cdict = config_tools.icswDeviceWithConfig( service_type_enum=_srv_type) for _sc_list in _cdict.values(): for _sc in _sc_list: _sc_result = _sc.get_result() if _sc_result.effective_device: self.log("effective device for {} (command {}) is {}". format( _config, _command, str(_sc_result.effective_device), )) srv_com = server_command.srv_command(command=_command) to_run.append(( background_job_run( background_job=cur_bg, server=_sc_result.effective_device, command_xml=str(srv_com), start=cluster_timezone.localize( datetime.datetime.now()), ), srv_com, _srv_type, )) if not _cdict: no_device.append(_command) if no_device: self.log("no device(s) found for {}".format(", ".join(no_device)), logging_tools.LOG_LEVEL_WARN) return to_run
def _check_kernel_dir(self, srv_com): self.log("checking kernel dir") # build option dict opt_dict = {} for key, def_value in { "ignore_kernel_build_machine": False, "kernels_to_insert": [], "check_list": [], "insert_all_found": False, "kernels_to_sync": {} }.items(): if key in srv_com: cur_val = srv_com[key].text if isinstance(def_value, bool): cur_val = True if int(cur_val) else False else: cur_val = def_value opt_dict[key] = cur_val # self.__ks_check._check(dc) self.log("option_dict has {}: {}".format( logging_tools.get_plural("key", len(list(opt_dict.keys()))), ", ".join([ "{} ({}, {})".format(key, str(type(value)), str(value)) for key, value in opt_dict.items() ]))) srv_com.update_source() # problems are global problems, not kernel local kernels_found, problems = ([], []) if not self.kernel_dev.effective_device: self.log("no kernel_server, skipping check ...", logging_tools.LOG_LEVEL_ERROR) srv_com.set_result("no kernel server", server_command.SRV_REPLY_STATE_ERROR) else: all_k_servers = config_tools.icswDeviceWithConfig( service_type_enum=icswServiceEnum.kernel_server) def_k_servers = all_k_servers.get(icswServiceEnum.kernel_server, []) self.log("found {}: {}".format( logging_tools.get_plural("kernel_server", len(def_k_servers)), ", ".join( sorted([ str(s_struct.effective_device) for s_struct in def_k_servers ])))) all_kernels = { cur_kern.name: cur_kern for cur_kern in kernel.objects.all() } any_found_in_database = len(all_kernels) > 0 if any_found_in_database: self.log( "some kernels already present in database, not inserting all found", logging_tools.LOG_LEVEL_WARN) opt_dict["insert_all_found"] = False kct_start = time.time() self.log( "Checking for kernels ({:d} already in database) ...".format( len(list(all_kernels.keys())))) if opt_dict["kernels_to_insert"]: self.log(" - only {} to insert: {}".format( logging_tools.get_plural( "kernels", len(opt_dict["kernels_to_insert"])), ", ".join(opt_dict["kernels_to_insert"]))) if "TFTP_DIR" in global_config: if not os.path.isdir(global_config["TFTP_DIR"]): self.log( "TFTP_DIR '{}' is not a directory".format( global_config["TFTP_DIR"]), logging_tools.LOG_LEVEL_ERROR) problems.append("TFTP_DIR '{}' is not a directory".format( global_config["TFTP_DIR"])) kern_dir = global_config["KERNEL_DIR"] if not os.path.isdir(kern_dir): self.log("kernel_dir '{}' is not a directory".format(kern_dir), logging_tools.LOG_LEVEL_ERROR) problems.append("kernel_dir '%s' is not a directory" % (kern_dir)) else: for entry in os.listdir(kern_dir): if not opt_dict["check_list"] or entry in opt_dict[ "check_list"]: try: act_kernel = KernelHelper( entry, kern_dir, self.log, global_config, master_server=self.kernel_dev.effective_device) except: self.log( "error in kernel handling ({}): {}".format( entry, process_tools.get_except_info(), ), logging_tools.LOG_LEVEL_ERROR) problems.append( str(process_tools.get_except_info())) for _log_line in process_tools.icswExceptionInfo( ).log_lines: self.log(" {}".format(_log_line), logging_tools.LOG_LEVEL_ERROR) else: # handle initrd generated by old populate_ramdisk.py act_kernel.move_old_initrd() act_kernel.check_md5_sums() act_kernel.check_kernel_dir() act_kernel.set_option_dict_values() # determine if we should insert the kernel into the database if act_kernel.check_for_db_insert(opt_dict): act_kernel.insert_into_database() act_kernel.check_initrd() kernels_found.append(act_kernel.name) act_kernel.log_statistics() del act_kernel kct_end = time.time() _ret_str = "checking of kernel_dir took {}{}".format( logging_tools.get_diff_time_str(kct_end - kct_start), ", problems: {}".format(", ".join(problems)) if problems else "", ) self.log( _ret_str, logging_tools.LOG_LEVEL_ERROR if problems else logging_tools.LOG_LEVEL_OK) srv_com.set_result( _ret_str, server_command.SRV_REPLY_STATE_ERROR if problems else server_command.SRV_REPLY_STATE_OK)