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, machine, disk, controller, share, filesystem, resourcegroup, address, comments, size, boot, snapshot, **kw): if controller not in controller_types: raise ArgumentError("%s is not a valid controller type, use one " "of: %s." % (controller, ", ".join(controller_types))) dbmachine = Machine.get_unique(session, machine, compel=True) for dbdisk in dbmachine.disks: if dbdisk.device_name == disk: raise ArgumentError("Machine %s already has a disk named %s." % (machine, disk)) if dbdisk.bootable: if boot is None: boot = False elif boot: raise ArgumentError("Machine %s already has a boot disk." % machine) if boot is None: # Backward compatibility: "sda"/"c0d0" is bootable, except if there # is already a boot disk boot = (disk == "sda" or disk == "c0d0") if share: if not dbmachine.vm_container: raise ArgumentError("{0} is not a virtual machine, it is not " "possible to define a virtual disk." .format(dbmachine)) dbshare = find_resource(Share, dbmachine.vm_container.holder.holder_object, resourcegroup, share) dbdisk = VirtualNasDisk(device_name=disk, controller_type=controller, bootable=boot, capacity=size, address=address, snapshotable=snapshot, comments=comments) dbshare.disks.append(dbdisk) elif filesystem: if not dbmachine.vm_container: raise ArgumentError("{0} is not a virtual machine, it is not " "possible to define a virtual disk." .format(dbmachine)) dbfs = Filesystem.get_unique(session, name=filesystem, holder=dbmachine.vm_container.holder, compel=True) dbdisk = VirtualLocalDisk(device_name=disk, controller_type=controller, bootable=boot, capacity=size, address=address, snapshotable=snapshot, comments=comments) dbfs.disks.append(dbdisk) else: dbdisk = LocalDisk(device_name=disk, controller_type=controller, capacity=size, bootable=boot, comments=comments) dbmachine.disks.append(dbdisk) plenary_info = Plenary.get_plenary(dbmachine, logger=logger) plenary_info.write() return
def render(self, session, logger, machine, disk, controller, share, filesystem, resourcegroup, address, comments, size, boot, snapshot, rename_to, **kw): dbmachine = Machine.get_unique(session, machine, compel=True) dbdisk = Disk.get_unique(session, device_name=disk, machine=dbmachine, compel=True) plenaries = PlenaryCollection(logger=logger) plenaries.append(Plenary.get_plenary(dbmachine)) if rename_to: Disk.get_unique(session, device_name=rename_to, machine=dbmachine, preclude=True) dbdisk.device_name = rename_to if comments is not None: dbdisk.comments = comments if size is not None: dbdisk.capacity = size if controller: if controller not in controller_types: raise ArgumentError("%s is not a valid controller type, use " "one of: %s." % (controller, ", ".join(controller_types))) dbdisk.controller_type = controller if boot is not None: dbdisk.bootable = boot # There should be just one boot disk. We may need to re-think this # if we want to model software RAID in the database. for disk in dbmachine.disks: if disk == dbdisk: continue if boot and disk.bootable: disk.bootable = False if address: # TODO: do we really care? Bus address makes sense for physical # disks as well, even if we cannot use that information today. if not isinstance(dbdisk, VirtualDisk): raise ArgumentError("Bus address can only be set for virtual " "disks.") dbdisk.address = address if snapshot is not None: if not isinstance(dbdisk, VirtualDisk): raise ArgumentError("Snapshot capability can only be set for " "virtual disks.") dbdisk.snapshotable = snapshot if share or filesystem: if isinstance(dbdisk, VirtualNasDisk): old_share = dbdisk.share old_share.disks.remove(dbdisk) elif isinstance(dbdisk, VirtualLocalDisk): old_fs = dbdisk.filesystem old_fs.disks.remove(dbdisk) else: raise ArgumentError("Disk {0!s} of {1:l} is not a virtual " "disk, changing the backend store is not " "possible.".format(dbdisk, dbmachine)) if share: if not isinstance(dbdisk, VirtualNasDisk): new_dbdisk = copy_virt_disk(session, VirtualNasDisk, dbdisk) session.delete(dbdisk) session.flush() session.add(new_dbdisk) dbdisk = new_dbdisk new_share = find_resource(Share, dbmachine.vm_container.holder.holder_object, resourcegroup, share) new_share.disks.append(dbdisk) if filesystem: if not isinstance(dbdisk, VirtualLocalDisk): new_dbdisk = copy_virt_disk(session, VirtualLocalDisk, dbdisk) session.delete(dbdisk) session.flush() session.add(new_dbdisk) dbdisk = new_dbdisk new_fs = find_resource(Filesystem, dbmachine.vm_container.holder.holder_object, resourcegroup, filesystem) new_fs.disks.append(dbdisk) session.flush() plenaries.write() return