def lookup_target(session, plenaries, hostname, ip, cluster, resourcegroup, service_address, alias): """ Check the parameters of the server providing a given service Look for potential conflicts, and return a dict that is suitable to be passed to either the constructor of ServiceInstanceServer, or to the find_server() function. """ params = {} if cluster and hostname: raise ArgumentError("Only one of --cluster and --hostname may be " "specified.") if alias: dbdns_env = DnsEnvironment.get_unique_or_default(session) dbdns_rec = Alias.get_unique(session, fqdn=alias, dns_environment=dbdns_env, compel=True) params["alias"] = dbdns_rec if hostname: params["host"] = hostname_to_host(session, hostname) plenaries.append(Plenary.get_plenary(params["host"])) if cluster: params["cluster"] = Cluster.get_unique(session, cluster, compel=True) plenaries.append(Plenary.get_plenary(params["cluster"])) if service_address: # TODO: calling get_resource_holder() means doing redundant DB lookups # TODO: it would be nice to also accept an FQDN for the service address, # to be consistent with the usage of the --service_address option in # add_service_address/del_service_address holder = get_resource_holder(session, hostname=hostname, cluster=cluster, resgroup=resourcegroup, compel=True) dbsrv_addr = ServiceAddress.get_unique(session, name=service_address, holder=holder, compel=True) params["service_address"] = dbsrv_addr elif ip: for addr in params["host"].hardware_entity.all_addresses(): if ip != addr.ip: continue if addr.service_address: params["service_address"] = addr.service_address else: params["address_assignment"] = addr break return params
def render(self, session, logger, name, hostname, cluster, resourcegroup, keep_dns, **arguments): validate_basic("name", name) if name == "hostname": raise ArgumentError("The primary address of the host cannot " "be deleted.") holder = get_resource_holder(session, hostname, cluster, resourcegroup, compel=False) dbsrv = ServiceAddress.get_unique(session, name=name, holder=holder, compel=True) if isinstance(holder.holder_object, Host): oldinfo = DSDBRunner.snapshot_hw(holder.holder_object.machine) else: oldinfo = None dbdns_rec = dbsrv.dns_record for addr in dbsrv.assignments: addr.interface.assignments.remove(addr) session.expire(dbsrv, ['assignments']) session.flush() # Check if the address was assigned to multiple interfaces, and remove # the DNS entries if this was the last use q = session.query(AddressAssignment) q = q.filter_by(network=dbdns_rec.network) q = q.filter_by(ip=dbdns_rec.ip) other_uses = q.all() del_resource(session, logger, dbsrv, dsdb_callback=del_srv_dsdb_callback, oldinfo=oldinfo, keep_dns=other_uses or keep_dns) if not other_uses and not keep_dns: delete_dns_record(dbdns_rec) return
def assign_zebra_address(self, session, dbmachine, dbdns_rec, zebra_interfaces): """ Assign a Zebra-managed address to multiple interfaces """ # Reset the routing configuration for iface in dbmachine.interfaces: if iface.default_route: iface.default_route = False # Disable autoflush, since the ServiceAddress object won't be complete # until add_resource() is called with session.no_autoflush: resholder = HostResource(host=dbmachine.host) session.add(resholder) dbsrv_addr = ServiceAddress(name="hostname", dns_record=dbdns_rec) resholder.resources.append(dbsrv_addr) for name in zebra_interfaces.split(","): dbinterface = None for iface in dbmachine.interfaces: if iface.name == name: dbinterface = iface if not dbinterface: raise ArgumentError("{0} does not have an interface named " "{1}.".format(dbmachine, name)) assign_address(dbinterface, dbdns_rec.ip, dbdns_rec.network, label="hostname", resource=dbsrv_addr) # Make sure the transit IPs resolve to the primary name for addr in dbinterface.assignments: if addr.label: continue for dnr in addr.dns_records: dnr.reverse_ptr = dbdns_rec.fqdn # Transits should be providers of the default route dbinterface.default_route = True return dbsrv_addr
def render(self, session, logger, service_address, ip, name, interfaces, hostname, cluster, resourcegroup, network_environment, map_to_primary, comments, **arguments): validate_basic("name", name) # TODO: generalize the error message - Layer-3 failover may be # implemented by other software, not just Zebra. if name == "hostname": raise ArgumentError( "The hostname service address is reserved for " "Zebra. Please specify the --zebra_interfaces " "option when calling add_host if you want the " "primary name of the host to be managed by " "Zebra.") ifnames = [ifname.strip().lower() for ifname in interfaces.split(",")] if not ifnames: raise ArgumentError("Please specify at least one interface name.") holder = get_resource_holder(session, hostname, cluster, resourcegroup, compel=False) # Address assignments should be added based on the host/cluster, so we # have to resolve resource groups first if isinstance(holder.holder_object, ResourceGroup): real_holder = holder.holder_object.holder.holder_object else: real_holder = holder.holder_object ServiceAddress.get_unique(session, name=name, holder=holder, preclude=True) # TODO: add allow_multi=True dbdns_rec, newly_created = grab_address(session, service_address, ip, network_environment) ip = dbdns_rec.ip dbnetwork = dbdns_rec.network if map_to_primary: if not isinstance(real_holder, Host): raise ArgumentError("The --map_to_primary option works only " "for host-based service addresses.") dbdns_rec.reverse_ptr = real_holder.machine.primary_name.fqdn # Disable autoflush, since the ServiceAddress object won't be complete # until add_resource() is called with session.no_autoflush: dbsrv = ServiceAddress(name=name, dns_record=dbdns_rec, comments=comments) holder.resources.append(dbsrv) oldinfo = None if isinstance(real_holder, Cluster): if not real_holder.hosts: # The interface names are only stored in the # AddressAssignment objects, so we can't handle a cluster # with no hosts and thus no interfaces raise ArgumentError("Cannot assign a service address to a " "cluster that has no members.") for host in real_holder.hosts: apply_service_address(host, ifnames, dbsrv) elif isinstance(real_holder, Host): oldinfo = DSDBRunner.snapshot_hw(real_holder.machine) apply_service_address(real_holder, ifnames, dbsrv) else: # pragma: no cover raise UnimplementedError("{0} as a resource holder is not " "implemented.".format(real_holder)) add_resource(session, logger, holder, dbsrv, dsdb_callback=add_srv_dsdb_callback, real_holder=real_holder, oldinfo=oldinfo, newly_created=newly_created, comments=comments) return
def render(self, session, logger, service_address, ip, name, interfaces, hostname, cluster, resourcegroup, network_environment, map_to_primary, comments, **arguments): validate_nlist_key("name", name) # TODO: generalize the error message - Layer-3 failover may be # implemented by other software, not just Zebra. if name == "hostname": raise ArgumentError("The hostname service address is reserved for " "Zebra. Please specify the --zebra_interfaces " "option when calling add_host if you want the " "primary name of the host to be managed by " "Zebra.") ifnames = [ifname.strip().lower() for ifname in interfaces.split(",")] if not ifnames: raise ArgumentError("Please specify at least one interface name.") holder = get_resource_holder(session, hostname, cluster, resourcegroup, compel=False) toplevel_holder = holder.toplevel_holder_object ServiceAddress.get_unique(session, name=name, holder=holder, preclude=True) # TODO: add allow_multi=True dbdns_rec, newly_created = grab_address(session, service_address, ip, network_environment) ip = dbdns_rec.ip if map_to_primary: if not isinstance(toplevel_holder, Host): raise ArgumentError("The --map_to_primary option works only " "for host-based service addresses.") dbdns_rec.reverse_ptr = toplevel_holder.hardware_entity.primary_name.fqdn # Disable autoflush, since the ServiceAddress object won't be complete # until add_resource() is called with session.no_autoflush: dbsrv = ServiceAddress(name=name, dns_record=dbdns_rec, comments=comments) holder.resources.append(dbsrv) oldinfo = None if isinstance(toplevel_holder, Cluster): if not toplevel_holder.hosts: # The interface names are only stored in the # AddressAssignment objects, so we can't handle a cluster # with no hosts and thus no interfaces raise ArgumentError("Cannot assign a service address to a " "cluster that has no members.") for host in toplevel_holder.hosts: apply_service_address(host, ifnames, dbsrv, logger) elif isinstance(toplevel_holder, Host): oldinfo = DSDBRunner.snapshot_hw(toplevel_holder.hardware_entity) apply_service_address(toplevel_holder, ifnames, dbsrv, logger) else: # pragma: no cover raise UnimplementedError("{0} as a resource holder is not " "implemented.".format(toplevel_holder)) add_resource(session, logger, holder, dbsrv, dsdb_callback=add_srv_dsdb_callback, toplevel_holder=toplevel_holder, oldinfo=oldinfo, newly_created=newly_created, comments=comments) return