def render(self, session, logger, chassis, label, rack, model, vendor, ip, interface, mac, serial, comments, **arguments): dbdns_rec, newly_created = grab_address(session, chassis, ip, allow_restricted_domain=True, allow_reserved=True, preclude=True) if not label: label = dbdns_rec.fqdn.name try: Chassis.check_label(label) except ArgumentError: raise ArgumentError("Could not deduce a valid hardware label " "from the chassis name. Please specify " "--label.") dblocation = get_location(session, rack=rack) dbmodel = Model.get_unique(session, name=model, vendor=vendor, machine_type='chassis', compel=True) # FIXME: Precreate chassis slots? dbchassis = Chassis(label=label, location=dblocation, model=dbmodel, serial_no=serial, comments=comments) session.add(dbchassis) dbchassis.primary_name = dbdns_rec # FIXME: get default name from the model if not interface: interface = "oa" ifcomments = "Created automatically by add_chassis" else: ifcomments = None dbinterface = get_or_create_interface(session, dbchassis, name=interface, mac=mac, interface_type="oa", comments=ifcomments) if ip: dbnetwork = get_net_id_from_ip(session, ip) check_ip_restrictions(dbnetwork, ip) assign_address(dbinterface, ip, dbnetwork) session.flush() if ip: dsdb_runner = DSDBRunner(logger=logger) dsdb_runner.update_host(dbchassis, None) dsdb_runner.commit_or_rollback("Could not add chassis to DSDB") return
def render(self, session, logger, chassis, model, rack, ip, vendor, serial, comments, **arguments): dbchassis = Chassis.get_unique(session, chassis, compel=True) oldinfo = DSDBRunner.snapshot_hw(dbchassis) if vendor and not model: model = dbchassis.model.name if model: dbmodel = Model.get_unique(session, name=model, vendor=vendor, model_type=ChassisType.Chassis, compel=True) dbchassis.model = dbmodel dblocation = get_location(session, rack=rack) if dblocation: dbchassis.location = dblocation if serial is not None: dbchassis.serial_no = serial if ip: update_primary_ip(session, logger, dbchassis, ip) if comments is not None: dbchassis.comments = comments session.flush() dsdb_runner = DSDBRunner(logger=logger) dsdb_runner.update_host(dbchassis, oldinfo) dsdb_runner.commit_or_rollback("Could not update chassis in DSDB") return
def format_raw(self, machines, indent=""): if machines: session = object_session(machines[0]) commands = [] for machine in machines: # Try to guess the name of the chassis result = chassis_re.match(machine.label) if result: chassis = "%sc%s" % (result.group(1), result.group(2)) slot = result.group(3) dbchassis = Chassis.get_unique(session, chassis) if not dbchassis and machine.primary_name: fqdn = "%s.%s" % ( chassis, machine.primary_name.fqdn.dns_domain.name) commands.append("aq add chassis --chassis '%s' " "--rack 'RACK' --model 'MODEL'" % fqdn) else: chassis = 'CHASSIS' slot = 'SLOT' commands.append("aq update machine --machine '%s' " "--chassis '%s' --slot '%s'" % (machine.label, chassis, slot)) return "\n".join(commands)
def render(self, session, machine, model, vendor, machine_type, chassis, slot, **arguments): q = session.query(Machine) if machine: # TODO: This command still mixes search/show facilities. # For now, give an error if machine name not found, but # also allow the command to be used to check if the machine has # the requested attributes (via the standard query filters). # In the future, this should be clearly separated as 'show machine' # and 'search machine'. machine = AqStr.normalize(machine) Machine.check_label(machine) Machine.get_unique(session, machine, compel=True) q = q.filter_by(label=machine) dblocation = get_location(session, **arguments) if dblocation: q = q.filter_by(location=dblocation) if chassis: dbchassis = Chassis.get_unique(session, chassis, compel=True) q = q.join('chassis_slot') q = q.filter_by(chassis=dbchassis) q = q.reset_joinpoint() if slot is not None: q = q.join('chassis_slot') q = q.filter_by(slot_number=slot) q = q.reset_joinpoint() if model or vendor or machine_type: subq = Model.get_matching_query(session, name=model, vendor=vendor, machine_type=machine_type, compel=True) q = q.filter(Machine.model_id.in_(subq)) return q.order_by(Machine.label).all()
def render(self, session, machine, model, vendor, machine_type, chassis, slot, **arguments): q = session.query(Machine) if machine: # TODO: This command still mixes search/show facilities. # For now, give an error if machine name not found, but # also allow the command to be used to check if the machine has # the requested attributes (via the standard query filters). # In the future, this should be clearly separated as 'show machine' # and 'search machine'. machine = AqStr.normalize(machine) Machine.check_label(machine) Machine.get_unique(session, machine, compel=True) q = q.filter_by(label=machine) dblocation = get_location(session, **arguments) if dblocation: q = q.filter_by(location=dblocation) if chassis: dbchassis = Chassis.get_unique(session, chassis, compel=True) q = q.join('chassis_slot') q = q.filter_by(chassis=dbchassis) q = q.reset_joinpoint() if slot is not None: q = q.join('chassis_slot') q = q.filter_by(slot_number=slot) q = q.reset_joinpoint() if model or vendor or machine_type: subq = Model.get_matching_query(session, name=model, vendor=vendor, model_type=machine_type, compel=True) q = q.filter(Machine.model_id.in_(subq)) return q.order_by(Machine.label).all()
def render(self, session, logger, chassis, model, rack, ip, vendor, serial, comments, **arguments): dbchassis = Chassis.get_unique(session, chassis, compel=True) oldinfo = DSDBRunner.snapshot_hw(dbchassis) if vendor and not model: model = dbchassis.model.name if model: dbmodel = Model.get_unique(session, name=model, vendor=vendor, machine_type='chassis', compel=True) dbchassis.model = dbmodel dblocation = get_location(session, rack=rack) if dblocation: dbchassis.location = dblocation if serial is not None: dbchassis.serial_no = serial if ip: update_primary_ip(session, dbchassis, ip) if comments is not None: dbchassis.comments = comments session.add(dbchassis) session.flush() dsdb_runner = DSDBRunner(logger=logger) dsdb_runner.update_host(dbchassis, oldinfo) dsdb_runner.commit_or_rollback("Could not update chassis in DSDB") return
def format_raw(self, machines, indent=""): if machines: session = object_session(machines[0]) commands = [] for machine in machines: # Try to guess the name of the chassis result = chassis_re.match(machine.label) if result: chassis = "%sc%s" % (result.group(1), result.group(2)) slot = result.group(3) dbchassis = Chassis.get_unique(session, chassis) if not dbchassis and machine.primary_name: fqdn = "%s.%s" % (chassis, machine.primary_name.fqdn.dns_domain.name) commands.append("aq add chassis --chassis '%s' " "--rack 'RACK' --model 'MODEL'" % fqdn) else: chassis = 'CHASSIS' slot = 'SLOT' commands.append("aq update machine --machine '%s' " "--chassis '%s' --slot '%s'" % (machine.label, chassis, slot)) return "\n".join(commands)
def render(self, session, logger, interface, chassis, mac, iftype, type, comments, **arguments): if type: self.deprecated_option("type", "Please use --iftype " "instead.", logger=logger, **arguments) if not iftype: iftype = type if iftype and iftype != "oa": raise ArgumentError("Only 'oa' is allowed as the interface type " "for chassis.") for arg in self.invalid_parameters: if arguments.get(arg) is not None: raise ArgumentError("Cannot use argument --%s when adding an " "interface to a chassis." % arg) dbchassis = Chassis.get_unique(session, chassis, compel=True) oldinfo = DSDBRunner.snapshot_hw(dbchassis) get_or_create_interface(session, dbchassis, name=interface, mac=mac, interface_type='oa', comments=comments, preclude=True) session.flush() dsdb_runner = DSDBRunner(logger=logger) dsdb_runner.update_host(dbchassis, oldinfo) dsdb_runner.commit_or_rollback("Could not update chassis in DSDB") return
def render(self, session, logger, interface, chassis, mac, type, comments, **arguments): if type and type != "oa": raise ArgumentError("Only 'oa' is allowed as the interface type " "for chassis.") for arg in self.invalid_parameters: if arguments.get(arg) is not None: raise ArgumentError("Cannot use argument --%s when adding an " "interface to a chassis." % arg) dbchassis = Chassis.get_unique(session, chassis, compel=True) oldinfo = DSDBRunner.snapshot_hw(dbchassis) dbinterface = get_or_create_interface(session, dbchassis, name=interface, mac=mac, interface_type='oa', comments=comments, preclude=True) session.flush() dsdb_runner = DSDBRunner(logger=logger) dsdb_runner.update_host(dbchassis, oldinfo) dsdb_runner.commit_or_rollback("Could not update chassis in DSDB") return
def render(self, session, logger, interface, chassis, mac, comments, rename_to, **arguments): for arg in self.invalid_parameters: if arguments.get(arg) is not None: raise UnimplementedError("update_interface --chassis cannot use " "the --%s option." % arg) dbchassis = Chassis.get_unique(session, chassis, compel=True) dbinterface = Interface.get_unique(session, hardware_entity=dbchassis, name=interface, compel=True) oldinfo = DSDBRunner.snapshot_hw(dbchassis) if comments: dbinterface.comments = comments if mac: dbinterface.mac = mac if rename_to: rename_interface(session, dbinterface, rename_to) session.flush() dsdb_runner = DSDBRunner(logger=logger) dsdb_runner.update_host(dbchassis, oldinfo) dsdb_runner.commit_or_rollback("Could not update chassis in DSDB") return
def render(self, session, logger, chassis, clear_slots, **arguments): dbchassis = Chassis.get_unique(session, chassis, compel=True) # Check and complain if the chassis has any other addresses than its # primary address addrs = [] for addr in dbchassis.all_addresses(): if addr.ip == dbchassis.primary_ip: continue addrs.append(str(addr.ip)) if addrs: raise ArgumentError("{0} still provides the following addresses, " "delete them first: {1}.".format (dbchassis, ", ".join(addrs))) q = session.query(ChassisSlot) q = q.filter_by(chassis=dbchassis) q = q.filter(ChassisSlot.machine_id != None) machine_count = q.count() if machine_count > 0 and not clear_slots: raise ArgumentError("{0} is still in use by {1} machines. Use " "--clear_slots if you really want to delete " "it.".format(dbchassis, machine_count)) # Order matters here dbdns_rec = dbchassis.primary_name ip = dbchassis.primary_ip old_fqdn = str(dbchassis.primary_name.fqdn) old_comments = dbchassis.primary_name.comments session.delete(dbchassis) if dbdns_rec: delete_dns_record(dbdns_rec) session.flush() if ip: dsdb_runner = DSDBRunner(logger=logger) dsdb_runner.delete_host_details(old_fqdn, ip, comments=old_comments) dsdb_runner.commit_or_rollback("Could not remove chassis from DSDB") return
def render(self, session, chassis, **arguments): return Chassis.get_unique(session, chassis, compel=True)
def render(self, session, logger, interface, machine, network_device, switch, chassis, mac, user, **arguments): if switch: self.deprecated_option("switch", "Please use --network_device " "instead.", logger=logger, user=user, **arguments) if not network_device: network_device = switch self.require_one_of(machine=machine, network_device=network_device, chassis=chassis, mac=mac) if machine: dbhw_ent = Machine.get_unique(session, machine, compel=True) elif network_device: dbhw_ent = NetworkDevice.get_unique(session, network_device, compel=True) elif chassis: dbhw_ent = Chassis.get_unique(session, chassis, compel=True) else: dbhw_ent = None dbinterface = Interface.get_unique(session, hardware_entity=dbhw_ent, name=interface, mac=mac, compel=True) if not dbhw_ent: dbhw_ent = dbinterface.hardware_entity if dbinterface.vlans: vlans = ", ".join([iface.name for iface in dbinterface.vlans.values()]) raise ArgumentError("{0} is the parent of the following VLAN " "interfaces, delete them first: " "{1}.".format(dbinterface, vlans)) if dbinterface.slaves: slaves = ", ".join([iface.name for iface in dbinterface.slaves]) raise ArgumentError("{0} is the master of the following slave " "interfaces, delete them first: " "{1}.".format(dbinterface, slaves)) for addr in dbinterface.assignments: if addr.ip != dbhw_ent.primary_ip: continue # If this is a machine, it is possible to delete the host to get rid # of the primary name if dbhw_ent.hardware_type == "machine": msg = " You should delete the host first." else: msg = "" raise ArgumentError("{0} holds the primary address of the {1:cl}, " "therefore it cannot be deleted." "{2}".format(dbinterface, dbhw_ent, msg)) addrs = ", ".join(["%s: %s" % (addr.logical_name, addr.ip) for addr in dbinterface.assignments]) if addrs: raise ArgumentError("{0} still has the following addresses " "configured, delete them first: " "{1}.".format(dbinterface, addrs)) dbhw_ent.interfaces.remove(dbinterface) session.flush() if dbhw_ent.hardware_type == 'machine': plenary_info = Plenary.get_plenary(dbhw_ent, logger=logger) plenary_info.write() return
def render(self, session, logger, machine, model, vendor, serial, chassis, slot, cpuname, cpuvendor, cpuspeed, cpucount, memory, cluster, vmhost, uri, comments, **arguments): dblocation = get_location(session, query_options=[subqueryload('parents'), joinedload('parents.dns_maps')], **arguments) if chassis: dbchassis = Chassis.get_unique(session, chassis, compel=True) if slot is None: raise ArgumentError("The --chassis option requires a --slot.") if dblocation and dblocation != dbchassis.location: raise ArgumentError("{0} conflicts with chassis location " "{1}.".format(dblocation, dbchassis.location)) dblocation = dbchassis.location elif slot is not None: raise ArgumentError("The --slot option requires a --chassis.") dbmodel = Model.get_unique(session, name=model, vendor=vendor, compel=True) if not dbmodel.model_type.isMachineType(): raise ArgumentError("The add_machine command cannot add machines " "of type %s." % str(dbmodel.model_type)) vmholder = None if cluster or vmhost: if cluster and vmhost: raise ArgumentError("Cluster and vmhost cannot be specified " "together.") if not dbmodel.model_type.isVirtualMachineType(): raise ArgumentError("{0} is not a virtual machine." .format(dbmodel)) # TODO: do we need VMs inside resource groups? vmholder = get_resource_holder(session, hostname=vmhost, cluster=cluster, resgroup=None, compel=False) if vmholder.holder_object.status.name == 'decommissioned': raise ArgumentError("Cannot add virtual machines to " "decommissioned clusters.") if cluster: container_loc = vmholder.holder_object.location_constraint else: container_loc = vmholder.holder_object.hardware_entity.location if dblocation and dblocation != container_loc: raise ArgumentError("Cannot override container location {0} " "with location {1}.".format(container_loc, dblocation)) dblocation = container_loc elif dbmodel.model_type.isVirtualMachineType(): raise ArgumentError("Virtual machines must be assigned to a " "cluster or a host.") Machine.get_unique(session, machine, preclude=True) dbmachine = create_machine(session, machine, dblocation, dbmodel, cpuname, cpuvendor, cpuspeed, cpucount, memory, serial, comments) if uri and not dbmodel.model_type.isVirtualAppliance(): raise ArgumentError("URI can be specified only for virtual " "appliances and the model's type is %s." % dbmodel.model_type) dbmachine.uri = uri if chassis: # FIXME: Are virtual machines allowed to be in a chassis? dbslot = session.query(ChassisSlot).filter_by(chassis=dbchassis, slot_number=slot).first() if not dbslot: dbslot = ChassisSlot(chassis=dbchassis, slot_number=slot) dbslot.machine = dbmachine session.add(dbslot) if vmholder: dbvm = VirtualMachine(machine=dbmachine, name=dbmachine.label, holder=vmholder) if hasattr(vmholder.holder_object, "validate") and \ callable(vmholder.holder_object.validate): vmholder.holder_object.validate() session.flush() plenaries = PlenaryCollection(logger=logger) plenaries.append(Plenary.get_plenary(dbmachine)) if vmholder: plenaries.append(Plenary.get_plenary(vmholder.holder_object)) plenaries.append(Plenary.get_plenary(dbvm)) # The check to make sure a plenary file is not written out for # dummy aurora hardware is within the call to write(). This way # it is consistent without altering (and forgetting to alter) # all the calls to the method. plenaries.write() return
def render(self, session, logger, machine, model, vendor, serial, chassis, slot, clearchassis, multislot, vmhost, cluster, allow_metacluster_change, cpuname, cpuvendor, cpuspeed, cpucount, memory, ip, **arguments): dbmachine = Machine.get_unique(session, machine, compel=True) plenaries = PlenaryCollection(logger=logger) oldinfo = DSDBRunner.snapshot_hw(dbmachine) if clearchassis: del dbmachine.chassis_slot[:] remove_plenaries = PlenaryCollection(logger=logger) if chassis: dbchassis = Chassis.get_unique(session, chassis, compel=True) if machine_plenary_will_move(old=dbmachine.location, new=dbchassis.location): remove_plenaries.append(Plenary.get_plenary(dbmachine)) dbmachine.location = dbchassis.location if slot is None: raise ArgumentError("Option --chassis requires --slot " "information.") self.adjust_slot(session, logger, dbmachine, dbchassis, slot, multislot) elif slot is not None: dbchassis = None for dbslot in dbmachine.chassis_slot: if dbchassis and dbslot.chassis != dbchassis: raise ArgumentError("Machine in multiple chassis, please " "use --chassis argument.") dbchassis = dbslot.chassis if not dbchassis: raise ArgumentError("Option --slot requires --chassis " "information.") self.adjust_slot(session, logger, dbmachine, dbchassis, slot, multislot) dblocation = get_location(session, **arguments) if dblocation: loc_clear_chassis = False for dbslot in dbmachine.chassis_slot: dbcl = dbslot.chassis.location if dbcl != dblocation: if chassis or slot is not None: raise ArgumentError("{0} conflicts with chassis {1!s} " "location {2}.".format(dblocation, dbslot.chassis, dbcl)) else: loc_clear_chassis = True if loc_clear_chassis: del dbmachine.chassis_slot[:] if machine_plenary_will_move(old=dbmachine.location, new=dblocation): remove_plenaries.append(Plenary.get_plenary(dbmachine)) dbmachine.location = dblocation if model or vendor: # If overriding model, should probably overwrite default # machine specs as well. if not model: model = dbmachine.model.name if not vendor: vendor = dbmachine.model.vendor.name dbmodel = Model.get_unique(session, name=model, vendor=vendor, compel=True) if dbmodel.machine_type not in ['blade', 'rackmount', 'workstation', 'aurora_node', 'virtual_machine']: raise ArgumentError("The update_machine command cannot update " "machines of type %s." % dbmodel.machine_type) # We probably could do this by forcing either cluster or # location data to be available as appropriate, but really? # Failing seems reasonable. if dbmodel.machine_type != dbmachine.model.machine_type and \ 'virtual_machine' in [dbmodel.machine_type, dbmachine.model.machine_type]: raise ArgumentError("Cannot change machine from %s to %s." % (dbmachine.model.machine_type, dbmodel.machine_type)) old_nic_model = dbmachine.model.nic_model new_nic_model = dbmodel.nic_model if old_nic_model != new_nic_model: for iface in dbmachine.interfaces: if iface.model == old_nic_model: iface.model = new_nic_model dbmachine.model = dbmodel if cpuname or cpuvendor or cpuspeed is not None: dbcpu = Cpu.get_unique(session, name=cpuname, vendor=cpuvendor, speed=cpuspeed, compel=True) dbmachine.cpu = dbcpu if cpucount is not None: dbmachine.cpu_quantity = cpucount if memory is not None: dbmachine.memory = memory if serial: dbmachine.serial_no = serial if ip: update_primary_ip(session, dbmachine, ip) # FIXME: For now, if a machine has its interface(s) in a portgroup # this command will need to be followed by an update_interface to # re-evaluate the portgroup for overflow. # It would be better to have --pg and --autopg options to let it # happen at this point. if cluster or vmhost: if not dbmachine.vm_container: raise ArgumentError("Cannot convert a physical machine to " "virtual.") old_holder = dbmachine.vm_container.holder.holder_object resholder = get_resource_holder(session, hostname=vmhost, cluster=cluster, compel=False) new_holder = resholder.holder_object # TODO: do we want to allow moving machines between the cluster and # metacluster level? if new_holder.__class__ != old_holder.__class__: raise ArgumentError("Cannot move a VM between a cluster and a " "stand-alone host.") if cluster: if new_holder.metacluster != old_holder.metacluster \ and not allow_metacluster_change: raise ArgumentError("Current {0:l} does not match " "new {1:l}." .format(old_holder.metacluster, new_holder.metacluster)) remove_plenaries.append(Plenary.get_plenary(dbmachine.vm_container)) dbmachine.vm_container.holder = resholder for dbdisk in dbmachine.disks: if not isinstance(dbdisk, VirtualDisk): continue old_share = dbdisk.share if isinstance(old_share.holder, BundleResource): resourcegroup = old_share.holder.name else: resourcegroup = None new_share = find_share(new_holder, resourcegroup, old_share.name, error=ArgumentError) # If the shares are registered at the metacluster level and both # clusters are in the same metacluster, then there will be no # real change here if new_share != old_share: old_share.disks.remove(dbdisk) new_share.disks.append(dbdisk) if isinstance(new_holder, Cluster): dbmachine.location = new_holder.location_constraint else: dbmachine.location = new_holder.location session.flush() plenaries.append(Plenary.get_plenary(old_holder)) plenaries.append(Plenary.get_plenary(new_holder)) if dbmachine.vm_container: plenaries.append(Plenary.get_plenary(dbmachine.vm_container)) session.flush() # Check if the changed parameters still meet cluster capacity # requiremets if dbmachine.cluster: dbmachine.cluster.validate() if allow_metacluster_change: dbmachine.cluster.metacluster.validate() if dbmachine.host and dbmachine.host.cluster: dbmachine.host.cluster.validate() # The check to make sure a plenary file is not written out for # dummy aurora hardware is within the call to write(). This way # it is consistent without altering (and forgetting to alter) # all the calls to the method. plenaries.append(Plenary.get_plenary(dbmachine)) if remove_plenaries.plenaries and dbmachine.host: plenaries.append(Plenary.get_plenary(dbmachine.host)) key = CompileKey.merge([plenaries.get_write_key(), remove_plenaries.get_remove_key()]) try: lock_queue.acquire(key) remove_plenaries.stash() plenaries.write(locked=True) remove_plenaries.remove(locked=True) if dbmachine.host: # XXX: May need to reconfigure. pass dsdb_runner = DSDBRunner(logger=logger) dsdb_runner.update_host(dbmachine, oldinfo) dsdb_runner.commit_or_rollback("Could not update machine in DSDB") except: plenaries.restore_stash() remove_plenaries.restore_stash() raise finally: lock_queue.release(key) return
def render(self, session, logger, machine, model, vendor, serial, chassis, slot, clearchassis, multislot, vmhost, cluster, allow_metacluster_change, cpuname, cpuvendor, cpuspeed, cpucount, memory, ip, uri, **arguments): dbmachine = Machine.get_unique(session, machine, compel=True) oldinfo = DSDBRunner.snapshot_hw(dbmachine) plenaries = PlenaryCollection(logger=logger) plenaries.append(Plenary.get_plenary(dbmachine)) if dbmachine.vm_container: plenaries.append(Plenary.get_plenary(dbmachine.vm_container)) if dbmachine.host: # Using PlenaryHostData directly, to avoid warnings if the host has # not been configured yet plenaries.append(PlenaryHostData.get_plenary(dbmachine.host)) if clearchassis: del dbmachine.chassis_slot[:] if chassis: dbchassis = Chassis.get_unique(session, chassis, compel=True) dbmachine.location = dbchassis.location if slot is None: raise ArgumentError("Option --chassis requires --slot " "information.") self.adjust_slot(session, logger, dbmachine, dbchassis, slot, multislot) elif slot is not None: dbchassis = None for dbslot in dbmachine.chassis_slot: if dbchassis and dbslot.chassis != dbchassis: raise ArgumentError("Machine in multiple chassis, please " "use --chassis argument.") dbchassis = dbslot.chassis if not dbchassis: raise ArgumentError("Option --slot requires --chassis " "information.") self.adjust_slot(session, logger, dbmachine, dbchassis, slot, multislot) dblocation = get_location(session, **arguments) if dblocation: loc_clear_chassis = False for dbslot in dbmachine.chassis_slot: dbcl = dbslot.chassis.location if dbcl != dblocation: if chassis or slot is not None: raise ArgumentError("{0} conflicts with chassis {1!s} " "location {2}." .format(dblocation, dbslot.chassis, dbcl)) else: loc_clear_chassis = True if loc_clear_chassis: del dbmachine.chassis_slot[:] dbmachine.location = dblocation if dbmachine.host: for vm in dbmachine.host.virtual_machines: plenaries.append(Plenary.get_plenary(vm)) vm.location = dblocation if model or vendor: # If overriding model, should probably overwrite default # machine specs as well. if not model: model = dbmachine.model.name if not vendor: vendor = dbmachine.model.vendor.name dbmodel = Model.get_unique(session, name=model, vendor=vendor, compel=True) if not dbmodel.model_type.isMachineType(): raise ArgumentError("The update_machine command cannot update " "machines of type %s." % dbmodel.model_type) # We probably could do this by forcing either cluster or # location data to be available as appropriate, but really? # Failing seems reasonable. if dbmodel.model_type != dbmachine.model.model_type and \ (dbmodel.model_type.isVirtualMachineType() or dbmachine.model.model_type.isVirtualMachineType()): raise ArgumentError("Cannot change machine from %s to %s." % (dbmachine.model.model_type, dbmodel.model_type)) old_nic_model = dbmachine.model.nic_model new_nic_model = dbmodel.nic_model if old_nic_model != new_nic_model: for iface in dbmachine.interfaces: if iface.model == old_nic_model: iface.model = new_nic_model dbmachine.model = dbmodel if cpuname or cpuvendor or cpuspeed is not None: dbcpu = Cpu.get_unique(session, name=cpuname, vendor=cpuvendor, speed=cpuspeed, compel=True) dbmachine.cpu = dbcpu if cpucount is not None: dbmachine.cpu_quantity = cpucount if memory is not None: dbmachine.memory = memory if serial: dbmachine.serial_no = serial if ip: update_primary_ip(session, logger, dbmachine, ip) if uri and not dbmachine.model.model_type.isVirtualAppliance(): raise ArgumentError("URI can be specified only for virtual " "appliances and the model's type is %s" % dbmachine.model.model_type) if uri: dbmachine.uri = uri # FIXME: For now, if a machine has its interface(s) in a portgroup # this command will need to be followed by an update_interface to # re-evaluate the portgroup for overflow. # It would be better to have --pg and --autopg options to let it # happen at this point. if cluster or vmhost: if not dbmachine.vm_container: raise ArgumentError("Cannot convert a physical machine to " "virtual.") old_holder = dbmachine.vm_container.holder.holder_object resholder = get_resource_holder(session, hostname=vmhost, cluster=cluster, compel=False) new_holder = resholder.holder_object if self.get_metacluster(new_holder) != self.get_metacluster(old_holder) \ and not allow_metacluster_change: raise ArgumentError("Current {0:l} does not match " "new {1:l}." .format(self.get_metacluster(old_holder), self.get_metacluster(new_holder))) plenaries.append(Plenary.get_plenary(old_holder)) plenaries.append(Plenary.get_plenary(new_holder)) dbmachine.vm_container.holder = resholder for dbdisk in dbmachine.disks: if isinstance(dbdisk, VirtualNasDisk): old_share = dbdisk.share if isinstance(old_share.holder, BundleResource): resourcegroup = old_share.holder.resourcegroup.name else: resourcegroup = None new_share = find_resource(Share, new_holder, resourcegroup, old_share.name, error=ArgumentError) # If the shares are registered at the metacluster level and both # clusters are in the same metacluster, then there will be no # real change here if new_share != old_share: old_share.disks.remove(dbdisk) new_share.disks.append(dbdisk) if isinstance(dbdisk, VirtualLocalDisk): old_filesystem = dbdisk.filesystem new_filesystem = find_resource(Filesystem, new_holder, None, old_filesystem.name, error=ArgumentError) if new_filesystem != old_filesystem: old_filesystem.disks.remove(dbdisk) new_filesystem.disks.append(dbdisk) if isinstance(new_holder, Cluster): dbmachine.location = new_holder.location_constraint else: # vmhost dbmachine.location = new_holder.hardware_entity.location session.flush() # Check if the changed parameters still meet cluster capacity # requiremets if dbmachine.cluster: dbmachine.cluster.validate() if allow_metacluster_change: dbmachine.cluster.metacluster.validate() if dbmachine.host and dbmachine.host.cluster: dbmachine.host.cluster.validate() # The check to make sure a plenary file is not written out for # dummy aurora hardware is within the call to write(). This way # it is consistent without altering (and forgetting to alter) # all the calls to the method. with plenaries.get_key(): plenaries.stash() try: plenaries.write(locked=True) dsdb_runner = DSDBRunner(logger=logger) dsdb_runner.update_host(dbmachine, oldinfo) dsdb_runner.commit_or_rollback("Could not update machine in DSDB") except: plenaries.restore_stash() raise return
def render(self, session, logger, interface, machine, switch, chassis, mac, user, **arguments): if not (machine or switch or chassis or mac): raise ArgumentError("Please specify at least one of --chassis, " "--machine, --switch or --mac.") if machine: dbhw_ent = Machine.get_unique(session, machine, compel=True) elif switch: dbhw_ent = Switch.get_unique(session, switch, compel=True) elif chassis: dbhw_ent = Chassis.get_unique(session, chassis, compel=True) else: dbhw_ent = None dbinterface = Interface.get_unique(session, hardware_entity=dbhw_ent, name=interface, mac=mac, compel=True) if not dbhw_ent: dbhw_ent = dbinterface.hardware_entity if dbinterface.vlans: vlans = ", ".join([iface.name for iface in dbinterface.vlans.values()]) raise ArgumentError("{0} is the parent of the following VLAN " "interfaces, delete them first: " "{1}.".format(dbinterface, vlans)) if dbinterface.slaves: slaves = ", ".join([iface.name for iface in dbinterface.slaves]) raise ArgumentError("{0} is the master of the following slave " "interfaces, delete them first: " "{1}.".format(dbinterface, slaves)) try: for addr in dbinterface.assignments: if addr.ip != dbhw_ent.primary_ip: continue # Special handling: if this interface was created automatically, # and there is exactly one other interface with no IP address, # then re-assign the primary address to that interface if not dbinterface.mac and dbinterface.comments is not None and \ dbinterface.comments.startswith("Created automatically") and \ len(dbhw_ent.interfaces) == 2: if dbinterface == dbhw_ent.interfaces[0]: other = dbhw_ent.interfaces[1] else: other = dbhw_ent.interfaces[0] if len(other.assignments) == 0: assign_address(other, dbhw_ent.primary_ip, dbhw_ent.primary_name.network) dbinterface.addresses.remove(dbhw_ent.primary_ip) raise _Goto # If this is a machine, it is possible to delete the host to get rid # of the primary name if dbhw_ent.hardware_type == "machine": msg = " You should delete the host first." else: msg = "" raise ArgumentError("{0} holds the primary address of the {1:cl}, " "therefore it cannot be deleted." "{2}".format(dbinterface, dbhw_ent, msg)) except _Goto: pass addrs = ", ".join(["%s: %s" % (addr.logical_name, addr.ip) for addr in dbinterface.assignments]) if addrs: raise ArgumentError("{0} still has the following addresses " "configured, delete them first: " "{1}.".format(dbinterface, addrs)) dbhw_ent.interfaces.remove(dbinterface) session.flush() if dbhw_ent.hardware_type == 'machine': plenary_info = PlenaryMachineInfo(dbhw_ent, logger=logger) plenary_info.write() return
def render(self, session, logger, machine, model, vendor, serial, chassis, slot, cpuname, cpuvendor, cpuspeed, cpucount, memory, cluster, comments, **arguments): dblocation = get_location(session, query_options=[subqueryload('parents'), joinedload('parents.dns_maps')], **arguments) if chassis: dbchassis = Chassis.get_unique(session, chassis, compel=True) if slot is None: raise ArgumentError("The --chassis option requires a --slot.") if dblocation and dblocation != dbchassis.location: raise ArgumentError("{0} conflicts with chassis location " "{1}.".format(dblocation, dbchassis.location)) dblocation = dbchassis.location elif slot is not None: raise ArgumentError("The --slot option requires a --chassis.") dbmodel = Model.get_unique(session, name=model, vendor=vendor, compel=True) if dbmodel.machine_type not in ['blade', 'rackmount', 'workstation', 'aurora_node', 'virtual_machine']: raise ArgumentError("The add_machine command cannot add machines " "of type %(type)s. Try 'add %(type)s'." % {"type": dbmodel.machine_type}) if cluster: if dbmodel.machine_type != 'virtual_machine': raise ArgumentError("Only virtual machines can have a cluster " "attribute.") dbcluster = Cluster.get_unique(session, cluster, compel=ArgumentError) # This test could be either archetype or cluster_type if dbcluster.personality.archetype.name != 'esx_cluster': raise ArgumentError("Can only add virtual machines to " "clusters with archetype esx_cluster.") # TODO implement the same to vmhosts. if dbcluster.status.name == 'decommissioned': raise ArgumentError("Cannot add virtual machines to " "decommissioned clusters.") if dblocation and dbcluster.location_constraint != dblocation: raise ArgumentError("Cannot override cluster location {0} " "with location {1}.".format( dbcluster.location_constraint, dblocation)) dblocation = dbcluster.location_constraint elif dbmodel.machine_type == 'virtual_machine': raise ArgumentError("Virtual machines must be assigned to a " "cluster.") Machine.get_unique(session, machine, preclude=True) dbmachine = create_machine(session, machine, dblocation, dbmodel, cpuname, cpuvendor, cpuspeed, cpucount, memory, serial, comments) if chassis: # FIXME: Are virtual machines allowed to be in a chassis? dbslot = session.query(ChassisSlot).filter_by(chassis=dbchassis, slot_number=slot).first() if not dbslot: dbslot = ChassisSlot(chassis=dbchassis, slot_number=slot) dbslot.machine = dbmachine session.add(dbslot) if cluster: if not dbcluster.resholder: dbcluster.resholder = ClusterResource(cluster=dbcluster) dbvm = VirtualMachine(machine=dbmachine, name=dbmachine.label, holder=dbcluster.resholder) dbcluster.validate() session.flush() plenaries = PlenaryCollection(logger=logger) plenaries.append(Plenary.get_plenary(dbmachine)) if cluster: plenaries.append(Plenary.get_plenary(dbcluster)) plenaries.append(Plenary.get_plenary(dbvm)) # The check to make sure a plenary file is not written out for # dummy aurora hardware is within the call to write(). This way # it is consistent without altering (and forgetting to alter) # all the calls to the method. plenaries.write() return
def render(self, session, logger, machine, model, vendor, serial, chassis, slot, cpuname, cpuvendor, cpuspeed, cpucount, memory, cluster, comments, **arguments): dblocation = get_location(session, query_options=[ subqueryload('parents'), joinedload('parents.dns_maps') ], **arguments) if chassis: dbchassis = Chassis.get_unique(session, chassis, compel=True) if slot is None: raise ArgumentError("The --chassis option requires a --slot.") if dblocation and dblocation != dbchassis.location: raise ArgumentError("{0} conflicts with chassis location " "{1}.".format(dblocation, dbchassis.location)) dblocation = dbchassis.location elif slot is not None: raise ArgumentError("The --slot option requires a --chassis.") dbmodel = Model.get_unique(session, name=model, vendor=vendor, compel=True) if dbmodel.machine_type not in [ 'blade', 'rackmount', 'workstation', 'aurora_node', 'virtual_machine' ]: raise ArgumentError("The add_machine command cannot add machines " "of type %(type)s. Try 'add %(type)s'." % {"type": dbmodel.machine_type}) if cluster: if dbmodel.machine_type != 'virtual_machine': raise ArgumentError("Only virtual machines can have a cluster " "attribute.") dbcluster = Cluster.get_unique(session, cluster, compel=ArgumentError) # This test could be either archetype or cluster_type if dbcluster.personality.archetype.name != 'esx_cluster': raise ArgumentError("Can only add virtual machines to " "clusters with archetype esx_cluster.") # TODO implement the same to vmhosts. if dbcluster.status.name == 'decommissioned': raise ArgumentError("Cannot add virtual machines to " "decommissioned clusters.") if dblocation and dbcluster.location_constraint != dblocation: raise ArgumentError("Cannot override cluster location {0} " "with location {1}.".format( dbcluster.location_constraint, dblocation)) dblocation = dbcluster.location_constraint elif dbmodel.machine_type == 'virtual_machine': raise ArgumentError("Virtual machines must be assigned to a " "cluster.") Machine.get_unique(session, machine, preclude=True) dbmachine = create_machine(session, machine, dblocation, dbmodel, cpuname, cpuvendor, cpuspeed, cpucount, memory, serial, comments) if chassis: # FIXME: Are virtual machines allowed to be in a chassis? dbslot = session.query(ChassisSlot).filter_by( chassis=dbchassis, slot_number=slot).first() if not dbslot: dbslot = ChassisSlot(chassis=dbchassis, slot_number=slot) dbslot.machine = dbmachine session.add(dbslot) if cluster: if not dbcluster.resholder: dbcluster.resholder = ClusterResource(cluster=dbcluster) dbvm = VirtualMachine(machine=dbmachine, name=dbmachine.label, holder=dbcluster.resholder) dbcluster.validate() session.flush() plenaries = PlenaryCollection(logger=logger) plenaries.append(Plenary.get_plenary(dbmachine)) if cluster: plenaries.append(Plenary.get_plenary(dbcluster)) plenaries.append(Plenary.get_plenary(dbvm)) # The check to make sure a plenary file is not written out for # dummy aurora hardware is within the call to write(). This way # it is consistent without altering (and forgetting to alter) # all the calls to the method. plenaries.write() return
class CommandAddAuroraHost(CommandAddHost): required_parameters = ["hostname"] # Look for node name like <building><rack_id>c<chassis_id>n<node_num> nodename_re = re.compile(r'^\s*([a-zA-Z]+)(\d+)c(\d+)n(\d+)\s*$') def render(self, session, logger, hostname, osname, osversion, **kwargs): # Pull relevant info out of dsdb... dsdb_runner = DSDBRunner(logger=logger) try: fields = dsdb_runner.show_host(hostname) except ProcessException, e: raise ArgumentError("Could not find %s in DSDB: %s" % (hostname, e)) fqdn = fields["fqdn"] dsdb_lookup = fields["dsdb_lookup"] if fields["node"]: machine = fields["node"] elif fields["primary_name"]: machine = fields["primary_name"] else: machine = dsdb_lookup # Create a machine dbmodel = Model.get_unique(session, name="aurora_model", vendor="aurora_vendor", compel=True) dbmachine = Machine.get_unique(session, machine) dbslot = None if not dbmachine: m = self.nodename_re.search(machine) if m: (building, rid, cid, nodenum) = m.groups() dbbuilding = session.query(Building).filter_by( name=building).first() if not dbbuilding: raise ArgumentError("Failed to find building %s for " "node %s, please add an Aurora " "machine manually and follow with " "add_host." % (building, machine)) rack = building + rid dbrack = session.query(Rack).filter_by(name=rack).first() if not dbrack: try: rack_fields = dsdb_runner.show_rack(rack) dbrack = Rack(name=rack, fullname=rack, parent=dbbuilding, rack_row=rack_fields["rack_row"], rack_column=rack_fields["rack_col"]) session.add(dbrack) except (ProcessException, ValueError), e: logger.client_info("Rack %s not defined in DSDB." % rack) dblocation = dbrack or dbbuilding chassis = rack + "c" + cid dbdns_domain = session.query(DnsDomain).filter_by( name="ms.com").first() dbchassis = Chassis.get_unique(session, chassis) if not dbchassis: dbchassis_model = Model.get_unique(session, name="aurora_chassis_model", vendor="aurora_vendor", compel=True) dbchassis = Chassis(label=chassis, location=dblocation, model=dbchassis_model) session.add(dbchassis) dbfqdn = Fqdn.get_or_create(session, name=chassis, dns_domain=dbdns_domain, preclude=True) dbdns_rec = ReservedName(fqdn=dbfqdn) session.add(dbdns_rec) dbchassis.primary_name = dbdns_rec dbslot = session.query(ChassisSlot).filter_by( chassis=dbchassis, slot_number=nodenum).first() # Note: Could be even more persnickity here and check that # the slot is currently empty. Seems like overkill. if not dbslot: dbslot = ChassisSlot(chassis=dbchassis, slot_number=nodenum) session.add(dbslot) else: dbnet_env = NetworkEnvironment.get_unique_or_default(session) try: host_ip = gethostbyname(hostname) except gaierror, e: raise ArgumentError("Error when looking up host: %d, %s" % (e.errno, e.strerror)) dbnetwork = get_net_id_from_ip(session, IPv4Address(host_ip), dbnet_env) dblocation = dbnetwork.location.building