def hostlist_to_hosts(session, hostlist): dbdns_env = DnsEnvironment.get_unique_or_default(session) failed = [] dbhosts = [] dns_domains = {} for host in hostlist: if "." not in host: failed.append("%s: Not an FQDN." % host) continue short, dns_domain = host.split(".", 1) try: if dns_domain not in dns_domains: dbdns_domain = DnsDomain.get_unique(session, dns_domain, compel=True) dns_domains[dns_domain] = dbdns_domain dbdns_rec = DnsRecord.get_unique(session, name=short, dns_domain=dns_domains[dns_domain], dns_environment=dbdns_env, query_options=[joinedload('hardware_entity')], compel=True) if not dbdns_rec.hardware_entity or \ not dbdns_rec.hardware_entity.host: raise NotFoundException("Host %s not found." % host) dbhosts.append(dbdns_rec.hardware_entity.host) except NotFoundException, err: failed.append("%s: %s" % (host, err)) continue except ArgumentError, err: failed.append("%s: %s" % (host, err)) continue
def render(self, session, hostname, machine, cpuname, cpuvendor, cpuspeed, cpucount, memory, cluster, share, fullinfo, style, **arguments): if fullinfo or style != 'raw': q = search_hardware_entity_query(session, Machine, **arguments) else: q = search_hardware_entity_query(session, Machine.label, **arguments) if machine: q = q.filter_by(label=machine) if hostname: dns_rec = DnsRecord.get_unique(session, fqdn=hostname, compel=True) q = q.filter(Machine.primary_name_id == dns_rec.id) if cpuname or cpuvendor or cpuspeed is not None: subq = Cpu.get_matching_query(session, name=cpuname, vendor=cpuvendor, speed=cpuspeed, compel=True) q = q.filter(Machine.cpu_id.in_(subq)) if cpucount is not None: q = q.filter_by(cpu_quantity=cpucount) if memory is not None: q = q.filter_by(memory=memory) if cluster: dbcluster = Cluster.get_unique(session, cluster, compel=True) if isinstance(dbcluster, MetaCluster): q = q.join('vm_container', ClusterResource, Cluster) q = q.filter_by(metacluster=dbcluster) else: q = q.join('vm_container', ClusterResource) q = q.filter_by(cluster=dbcluster) q = q.reset_joinpoint() if share: v2shares = session.query(Share.id).filter_by(name=share) if not v2shares.count(): raise NotFoundException("No shares found with name {0}." .format(share)) NasAlias = aliased(VirtualNasDisk) q = q.join('disks', (NasAlias, NasAlias.id == Disk.id)) q = q.filter(NasAlias.share_id.in_(v2shares.subquery())) q = q.reset_joinpoint() if fullinfo or style != "raw": q = q.options(joinedload('location'), subqueryload('interfaces'), lazyload('interfaces.hardware_entity'), joinedload('interfaces.assignments'), joinedload('interfaces.assignments.dns_records'), joinedload('chassis_slot'), subqueryload('chassis_slot.chassis'), subqueryload('disks'), subqueryload('host'), lazyload('host.hardware_entity'), subqueryload('host.services_used'), subqueryload('host._cluster'), lazyload('host._cluster.host')) return q.all() return StringAttributeList(q.all(), "label")
def render(self, session, logger, fqdn, dns_environment, target, comments, **kwargs): dbdns_env = DnsEnvironment.get_unique_or_default(session, dns_environment) dbfqdn = Fqdn.get_or_create(session, dns_environment=dbdns_env, fqdn=fqdn) if dbfqdn.dns_domain.restricted: raise ArgumentError("{0} is restricted, aliases are not allowed." .format(dbfqdn.dns_domain)) DnsRecord.get_unique(session, fqdn=dbfqdn, preclude=True) dbtarget = create_target_if_needed(session, logger, target, dbdns_env) try: db_record = Alias(fqdn=dbfqdn, target=dbtarget, comments=comments) session.add(db_record) except ValueError, err: raise ArgumentError(err.message)
def render(self, session, hostname, machine, cpuname, cpuvendor, cpuspeed, cpucount, memory, cluster, share, fullinfo, style, **arguments): if fullinfo or style != 'raw': q = search_hardware_entity_query(session, Machine, **arguments) else: q = search_hardware_entity_query(session, Machine.label, **arguments) if machine: q = q.filter_by(label=machine) if hostname: dns_rec = DnsRecord.get_unique(session, fqdn=hostname, compel=True) q = q.filter(Machine.primary_name_id==dns_rec.id) if cpuname or cpuvendor or cpuspeed is not None: subq = Cpu.get_matching_query(session, name=cpuname, vendor=cpuvendor, speed=cpuspeed, compel=True) q = q.filter(Machine.cpu_id.in_(subq)) if cpucount is not None: q = q.filter_by(cpu_quantity=cpucount) if memory is not None: q = q.filter_by(memory=memory) if cluster: dbcluster = Cluster.get_unique(session, cluster, compel=True) if isinstance(dbcluster, MetaCluster): q = q.join('vm_container', ClusterResource, Cluster) q = q.filter_by(metacluster=dbcluster) else: q = q.join('vm_container', ClusterResource) q = q.filter_by(cluster=dbcluster) q = q.reset_joinpoint() if share: #v2 v2shares = session.query(Share.id).filter_by(name=share).all() if v2shares: NasAlias = aliased(VirtualDisk) q = q.join('disks', (NasAlias, NasAlias.id == Disk.id)) q = q.filter( NasAlias.share_id.in_(map(lambda s: s[0], v2shares))) q = q.reset_joinpoint() if fullinfo: q = q.options(joinedload('location'), subqueryload('interfaces'), joinedload('interfaces.assignments'), joinedload('interfaces.assignments.dns_records'), joinedload('chassis_slot'), subqueryload('chassis_slot.chassis'), subqueryload('disks'), subqueryload('host'), subqueryload('host.services_used'), subqueryload('host._cluster')) return q.all() return SimpleMachineList(q.all())
def render(self, session, logger, fqdn, dns_environment, target, comments, **kwargs): dbdns_env = DnsEnvironment.get_unique_or_default( session, dns_environment) dbfqdn = Fqdn.get_or_create(session, dns_environment=dbdns_env, fqdn=fqdn) if dbfqdn.dns_domain.restricted: raise ArgumentError( "{0} is restricted, aliases are not allowed.".format( dbfqdn.dns_domain)) DnsRecord.get_unique(session, fqdn=dbfqdn, preclude=True) dbtarget = create_target_if_needed(session, logger, target, dbdns_env) try: db_record = Alias(fqdn=dbfqdn, target=dbtarget, comments=comments) session.add(db_record) except ValueError, err: raise ArgumentError(err.message)
def get_unique(cls, sess, name, hardware_type=None, compel=False, preclude=False, query_options=None): """ Returns a unique HardwareEntity given session and fqdn """ # If the hardware_type param isn't explicitly set and we have a # polymorphic identity, assume we're querying only for items of our # hardware_type. if hardware_type: if isclass(hardware_type): clslabel = hardware_type._get_class_label() hardware_type = hardware_type.__mapper_args__['polymorphic_identity'] else: pcls = cls.__mapper__.polymorphic_map[hardware_type].class_ clslabel = pcls._get_class_label() else: if 'polymorphic_identity' in cls.__mapper_args__: hardware_type = cls.__mapper_args__['polymorphic_identity'] clslabel = cls._get_class_label() # The automagic DNS lookup does not really make sense with preclude=True if preclude: name = AqStr.normalize(name) cls.check_label(name) q = sess.query(cls) if "." in name: dns_rec = DnsRecord.get_unique(sess, fqdn=name, compel=True) # We know the primary name, do not load it again q = q.options(lazyload('primary_name')) q = q.filter_by(primary_name=dns_rec) else: dns_rec = None q = q.filter_by(label=name) if query_options: q = q.options(*query_options) try: hwe = q.one() except NoResultFound: # Check if the name is in use by a different hardware type q = sess.query(HardwareEntity) if dns_rec: # We know the primary name, do not load it again q = q.options(lazyload('primary_name')) q = q.filter_by(primary_name=dns_rec) else: q = q.filter_by(label=name) try: hwe = q.one() if dns_rec: # We know the primary name, do not load it again set_committed_value(hwe, 'primary_name', dns_rec) raise ArgumentError("{0} exists, but is not a {1}." .format(hwe, clslabel.lower())) except NoResultFound: hwe = None if compel: raise NotFoundException("%s %s not found." % (clslabel, name)) if hwe: if preclude: raise ArgumentError('{0} already exists.'.format(hwe)) if dns_rec: # We know the primary name, do not load it again set_committed_value(hwe, 'primary_name', dns_rec) return hwe
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(): mac_addresses = [iface.mac for iface in dbhost.machine.interfaces] if dbhost.fqdn in windows_hosts and \ windows_hosts[dbhost.fqdn] in mac_addresses: # All is well continue deps = get_host_dependencies(session, dbhost) if deps: msg = "Skipping removal of host %s with dependencies: %s" % \ (dbhost.fqdn, ", ".join(deps)) failed.append(msg) logger.info(msg) continue dbmachine = dbhost.machine success.append("Removed host entry for %s (%s)" % (dbmachine.label, dbmachine.fqdn)) if dbmachine.vm_container: containers.add(dbmachine.vm_container) session.delete(dbhost) dbdns_rec = dbmachine.primary_name dbmachine.primary_name = None delete_dns_record(dbdns_rec) session.flush() # The Host() creations below fail when autoflush is enabled. session.autoflush = False dbdomain = Domain.get_unique(session, self.config.get("archetype_windows", "host_domain"), compel=InternalError) dbarchetype = Archetype.get_unique(session, "windows", compel=InternalError) dbpersonality = Personality.get_unique(session, archetype=dbarchetype, name="generic", compel=InternalError) dbstatus = HostLifecycle.get_unique(session, "ready", compel=InternalError) dbos = OperatingSystem.get_unique(session, name="windows", version="generic", archetype=dbarchetype, compel=InternalError) for (host, mac) in windows_hosts.items(): try: (short, dbdns_domain) = parse_fqdn(session, host) except AquilonError, err: msg = "Skipping host %s: %s" % (host, err) failed.append(msg) logger.info(msg) continue existing = DnsRecord.get_unique(session, name=short, dns_domain=dbdns_domain) if existing: if not existing.hardware_entity: msg = "Skipping host %s: It is not a primary name." % host failed.append(msg) logger.info(msg) continue # If these are invalid there should have been a deletion # attempt above. if not existing.hardware_entity.interfaces: msg = "Skipping host %s: Host already exists but has " \ "no interface attached." % host failed.append(msg) logger.info(msg) elif existing.hardware_entity.interfaces[0].mac != mac: msg = "Skipping host %s: Host already exists but with " \ "MAC address %s and not %s." % \ (host, existing.hardware_entity.interfaces[0].mac, mac) failed.append(msg) logger.info(msg) continue dbinterface = session.query(Interface).filter_by(mac=mac).first() if not dbinterface: msg = "Skipping host %s: MAC address %s is not present in " \ "AQDB." % (host, mac) failed.append(msg) logger.info(msg) continue q = session.query(Machine) q = q.filter_by(id=dbinterface.hardware_entity.id) dbmachine = q.first() if not dbmachine: msg = "Skipping host %s: The AQDB interface with MAC address " \ "%s is tied to hardware %s instead of a virtual " \ "machine." % \ (host, mac, dbinterface.hardware_entity.label) failed.append(msg) logger.info(msg) continue if dbinterface.assignments: msg = "Skipping host %s: The AQDB interface with MAC address " \ "%s is already tied to %s." % \ (host, mac, dbinterface.assignments[0].fqdns[0]) failed.append(msg) logger.info(msg) continue if dbmachine.host: msg = "Skipping host %s: The AQDB interface with MAC address " \ "%s is already tied to %s." % \ (host, mac, dbmachine.fqdn) failed.append(msg) logger.info(msg) continue dbhost = Host(machine=dbmachine, branch=dbdomain, status=dbstatus, owner_grn=dbpersonality.owner_grn, personality=dbpersonality, operating_system=dbos, comments="Created by refresh_windows_host") session.add(dbhost) if self.config.has_option("archetype_windows", "default_grn_target"): dbhost.grns.append((dbhost, dbgrn, self.config.get("archetype_", "default_grn_target"))) dbfqdn = Fqdn.get_or_create(session, name=short, dns_domain=dbdns_domain, preclude=True) dbdns_rec = ReservedName(fqdn=dbfqdn) session.add(dbdns_rec) dbmachine.primary_name = dbdns_rec success.append("Added host entry for %s (%s)." % (dbmachine.label, dbdns_rec.fqdn)) if dbmachine.vm_container: containers.add(dbmachine.vm_container) session.flush()
name="generic", compel=InternalError) dbstatus = Ready.get_instance(session) dbos = OperatingSystem.get_unique(session, name="windows", version="generic", archetype=dbarchetype, compel=InternalError) for (host, mac) in windows_hosts.items(): try: (short, dbdns_domain) = parse_fqdn(session, host) except AquilonError, err: msg = "Skipping host %s: %s" % (host, err) failed.append(msg) logger.info(msg) continue existing = DnsRecord.get_unique(session, name=short, dns_domain=dbdns_domain) if existing: if not existing.hardware_entity: msg = "Skipping host %s: It is not a primary name." % host failed.append(msg) logger.info(msg) continue # If these are invalid there should have been a deletion # attempt above. if not existing.hardware_entity.interfaces: msg = "Skipping host %s: Host already exists but has " \ "no interface attached." % host failed.append(msg) logger.info(msg) elif existing.hardware_entity.interfaces[0].mac != mac: msg = "Skipping host %s: Host already exists but with " \
def get_unique(cls, sess, name, hardware_type=None, compel=False, preclude=False, query_options=None): """ Returns a unique HardwareEntity given session and fqdn """ # If the hardware_type param isn't explicitly set and we have a # polymorphic identity, assume we're querying only for items of our # hardware_type. if hardware_type: if isclass(hardware_type): clslabel = hardware_type._get_class_label() hardware_type = hardware_type.__mapper_args__[ 'polymorphic_identity'] else: pcls = cls.__mapper__.polymorphic_map[hardware_type].class_ clslabel = pcls._get_class_label() else: if 'polymorphic_identity' in cls.__mapper_args__: hardware_type = cls.__mapper_args__['polymorphic_identity'] clslabel = cls._get_class_label() # The automagic DNS lookup does not really make sense with preclude=True if preclude: name = AqStr.normalize(name) cls.check_label(name) q = sess.query(cls) if "." in name: dns_rec = DnsRecord.get_unique(sess, fqdn=name, compel=True) # We know the primary name, do not load it again q = q.options(lazyload('primary_name')) q = q.filter_by(primary_name=dns_rec) else: dns_rec = None q = q.filter_by(label=name) if query_options: q = q.options(*query_options) try: hwe = q.one() except NoResultFound: # Check if the name is in use by a different hardware type q = sess.query(HardwareEntity) if dns_rec: # We know the primary name, do not load it again q = q.options(lazyload('primary_name')) q = q.filter_by(primary_name=dns_rec) else: q = q.filter_by(label=name) try: hwe = q.one() if dns_rec: # We know the primary name, do not load it again set_committed_value(hwe, 'primary_name', dns_rec) raise ArgumentError("{0} exists, but is not a {1}.".format( hwe, hardware_type)) except NoResultFound: hwe = None if compel: raise NotFoundException("%s %s not found." % (clslabel, name)) if hwe: if preclude: raise ArgumentError('{0} already exists.'.format(hwe)) if dns_rec: # We know the primary name, do not load it again set_committed_value(hwe, 'primary_name', dns_rec) return hwe