def del_cluster(session, logger, dbcluster, config): check_no_provided_service(dbcluster) if hasattr(dbcluster, 'members') and dbcluster.members: raise ArgumentError("%s is still in use by clusters: %s." % (format(dbcluster), ", ".join([c.name for c in dbcluster.members]))) elif dbcluster.hosts: hosts = ", ".join([h.fqdn for h in dbcluster.hosts]) raise ArgumentError("%s is still in use by hosts: %s." % (format(dbcluster), hosts)) plenaries = PlenaryCollection(logger=logger) plenaries.append(Plenary.get_plenary(dbcluster)) if dbcluster.resholder: for res in dbcluster.resholder.resources: plenaries.append(Plenary.get_plenary(res)) session.delete(dbcluster) session.flush() plenaries.remove(remove_profile=True) trigger_notifications(config, logger, CLIENT_INFO) return
def refresh_windows_hosts(self, session, logger, containers): conn = sqlite3.connect(self.config.get("broker", "windows_host_info")) # Enable dictionary-style access to the rows. conn.row_factory = sqlite3.Row windows_hosts = {} interfaces = {} cur = conn.cursor() # There are more fields in the dataset like machine and # aqhostname that might be useful for error messages but these # are sufficient. cur.execute("select ether, windowshostname from machines") for row in cur: host = row["windowshostname"] if host: host = host.strip().lower() else: continue mac = row["ether"] if mac: mac = mac.strip().lower() windows_hosts[host] = mac interfaces[mac] = host success = [] failed = [] q = session.query(Host) q = q.filter_by(comments='Created by refresh_windows_host') for dbhost in q.all(): dbmachine = dbhost.hardware_entity mac_addresses = [iface.mac for iface in dbmachine.interfaces] if dbhost.fqdn in windows_hosts and \ windows_hosts[dbhost.fqdn] in mac_addresses: # All is well continue try: check_no_provided_service(dbhost) except ArgumentError, err: msg = "Skipping removal of host %s due to: %s" % \ (dbhost.fqdn, err) failed.append(msg) logger.info(msg) continue success.append("Removed host entry for %s (%s)" % (dbmachine.label, dbmachine.fqdn)) if dbmachine.vm_container: containers.add(dbmachine.vm_container) logger.info("Deleting {0:l} (machine {1.label})" .format(dbhost, dbmachine)) session.delete(dbhost) dbdns_rec = dbmachine.primary_name dbmachine.primary_name = None delete_dns_record(dbdns_rec)
def render(self, session, logger, name, hostname, cluster, resourcegroup, keep_dns, **arguments): 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) check_no_provided_service(dbsrv) if isinstance(holder.holder_object, Host): oldinfo = DSDBRunner.snapshot_hw(holder.holder_object.hardware_entity) 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 render(self, session, logger, fqdn, dns_environment, **kwargs): dbdns_env = DnsEnvironment.get_unique_or_default(session, dns_environment) dbdns_rec = Alias.get_unique(session, fqdn=fqdn, dns_environment=dbdns_env, compel=True) domain = dbdns_rec.fqdn.dns_domain.name check_no_provided_service(dbdns_rec) old_target_fqdn = str(dbdns_rec.target) old_comments = dbdns_rec.comments target_is_restricted = dbdns_rec.target.dns_domain.restricted delete_dns_record(dbdns_rec) session.flush() if dbdns_env.is_default and domain == "ms.com" and not target_is_restricted: dsdb_runner = DSDBRunner(logger=logger) dsdb_runner.del_alias(fqdn, old_target_fqdn, old_comments) dsdb_runner.commit_or_rollback("Could not delete alias from DSDB") return
def render(self, session, logger, machine, chassis, network_device, interface, fqdn, ip, label, keep_dns, network_environment, **kwargs): if machine: hwtype = 'machine' hwname = machine elif chassis: hwtype = 'chassis' hwname = chassis elif network_device: hwtype = 'network_device' hwname = network_device dbhw_ent = HardwareEntity.get_unique(session, hwname, hardware_type=hwtype, compel=True) dbinterface = Interface.get_unique(session, hardware_entity=dbhw_ent, name=interface, compel=True) dbnet_env = NetworkEnvironment.get_unique_or_default(session, network_environment) oldinfo = DSDBRunner.snapshot_hw(dbhw_ent) if fqdn: dbdns_rec = ARecord.get_unique(session, fqdn=fqdn, dns_environment=dbnet_env.dns_environment, compel=True) ip = dbdns_rec.ip addr = None if ip: addr = first_of(dbinterface.assignments, lambda x: x.ip == ip) if not addr: raise ArgumentError("{0} does not have IP address {1} assigned to " "it.".format(dbinterface, ip)) elif label is not None: addr = first_of(dbinterface.assignments, lambda x: x.label == label) if not addr: raise ArgumentError("{0} does not have an address with label " "{1}.".format(dbinterface, label)) if not addr: raise ArgumentError("Please specify the address to be removed " "using either --ip, --label, or --fqdn.") dbnetwork = addr.network ip = addr.ip if dbnetwork.network_environment != dbnet_env: raise ArgumentError("The specified address lives in {0:l}, not in " "{1:l}. Use the --network_environment option " "to select the correct environment." .format(dbnetwork.network_environment, dbnet_env)) # Forbid removing the primary name if ip == dbhw_ent.primary_ip: raise ArgumentError("The primary IP address of a hardware entity " "cannot be removed.") check_no_provided_service(addr) dbinterface.assignments.remove(addr) # 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=dbnetwork) q = q.filter_by(ip=ip) other_uses = q.all() if not other_uses and not keep_dns: q = session.query(ARecord) q = q.filter_by(network=dbnetwork) q = q.filter_by(ip=ip) q = q.join(ARecord.fqdn) q = q.filter_by(dns_environment=dbnet_env.dns_environment) map(delete_dns_record, q.all()) session.flush() dbhost = getattr(dbhw_ent, "host", None) if dbhost: plenary_info = Plenary.get_plenary(dbhost, logger=logger) with plenary_info.get_key(): try: try: plenary_info.write(locked=True) except IncompleteError: # FIXME: if this command is used after "add host" but # before "make", then writing out the template will fail # due to required services not being assigned. Ignore # this error for now. plenary_info.restore_stash() dsdb_runner = DSDBRunner(logger=logger) dsdb_runner.update_host(dbhw_ent, oldinfo) if not other_uses and keep_dns: q = session.query(ARecord) q = q.filter_by(network=dbnetwork) q = q.filter_by(ip=ip) dbdns_rec = q.first() dsdb_runner.add_host_details(dbdns_rec.fqdn, ip) dsdb_runner.commit_or_rollback("Could not add host to DSDB") except: plenary_info.restore_stash() raise else: dsdb_runner = DSDBRunner(logger=logger) dsdb_runner.update_host(dbhw_ent, oldinfo) dsdb_runner.commit_or_rollback("Could not add host to DSDB") return
def render(self, session, logger, hostname, **arguments): # Check dependencies, translate into user-friendly message dbhost = hostname_to_host(session, hostname) dbhost.lock_row() check_no_provided_service(dbhost) # Any service bindings that we need to clean up afterwards plenaries = PlenaryCollection(logger=logger) remove_plenaries = PlenaryCollection(logger=logger) remove_plenaries.append(Plenary.get_plenary(dbhost)) archetype = dbhost.archetype.name dbmachine = dbhost.hardware_entity oldinfo = DSDBRunner.snapshot_hw(dbmachine) ip = dbmachine.primary_ip for si in dbhost.services_used: plenaries.append(PlenaryServiceInstanceServer.get_plenary(si)) logger.info("Before deleting {0:l}, removing binding to {1:l}" .format(dbhost, si)) del dbhost.services_used[:] if dbhost.resholder: for res in dbhost.resholder.resources: remove_plenaries.append(Plenary.get_plenary(res)) # In case of Zebra, the IP may be configured on multiple interfaces for iface in dbmachine.interfaces: if ip in iface.addresses: iface.addresses.remove(ip) if dbhost.cluster: dbcluster = dbhost.cluster dbcluster.hosts.remove(dbhost) set_committed_value(dbhost, '_cluster', None) dbcluster.validate() plenaries.append(Plenary.get_plenary(dbcluster)) dbdns_rec = dbmachine.primary_name dbmachine.primary_name = None dbmachine.host = None session.delete(dbhost) delete_dns_record(dbdns_rec) session.flush() if dbmachine.vm_container: plenaries.append(Plenary.get_plenary(dbmachine.vm_container)) with CompileKey.merge([plenaries.get_key(), remove_plenaries.get_key()]): plenaries.stash() remove_plenaries.stash() try: plenaries.write(locked=True) remove_plenaries.remove(locked=True, remove_profile=True) if archetype != 'aurora' and ip is not None: dsdb_runner = DSDBRunner(logger=logger) dsdb_runner.update_host(dbmachine, oldinfo) dsdb_runner.commit_or_rollback("Could not remove host %s from " "DSDB" % hostname) if archetype == 'aurora': logger.client_info("WARNING: removing host %s from AQDB and " "*not* changing DSDB." % hostname) except: plenaries.restore_stash() remove_plenaries.restore_stash() raise trigger_notifications(self.config, logger, CLIENT_INFO) return