def attach_volume(vm, volume): """Attach a volume to a server. The volume must be in 'AVAILABLE' status in order to be attached. Also, number of the volumes that are attached to the server must remain less than 'GANETI_MAX_DISKS_PER_INSTANCE' setting. This function will send the corresponding job to Ganeti backend and update the status of the volume to 'ATTACHING'. """ # Check volume state if volume.status not in ["AVAILABLE", "CREATING"]: raise faults.BadRequest("Cannot attach volume while volume is in" " '%s' status." % volume.status) # Check that disk templates are the same if volume.volume_type_id != vm.flavor.volume_type_id: msg = ("Volume and server must have the same volume type. Volume has" " volume type '%s' while server has '%s'" % (volume.volume_type_id, vm.flavor.volume_type_id)) raise faults.BadRequest(msg) # Check maximum disk per instance hard limit vm_volumes_num = vm.volumes.filter(deleted=False).count() if vm_volumes_num == settings.GANETI_MAX_DISKS_PER_INSTANCE: raise faults.BadRequest("Maximum volumes per server limit reached") if volume.status == "CREATING": action_fields = {"disks": [("add", volume, {})]} else: action_fields = {} comm = commands.server_command("ATTACH_VOLUME", action_fields=action_fields) return comm(_attach_volume)(vm, volume)
def detach_volume(vm, volume): """Detach a Volume from a VM The volume must be in 'IN_USE' status in order to be detached. Also, the root volume of the instance (index=0) can not be detached. This function will send the corresponding job to Ganeti backend and update the status of the volume to 'DETACHING'. """ util.assert_detachable_volume_type(volume.volume_type) _check_attachment(vm, volume) if volume.status not in ["IN_USE", "ERROR"]: raise faults.BadRequest("Cannot detach volume while volume is in" " '%s' status." % volume.status) if volume.index == 0: raise faults.BadRequest("Cannot detach the root volume of server %s." % vm) comm = commands.server_command("DETACH_VOLUME") return comm(_detach_volume)(vm, volume)
def delete_volume(vm, volume): """Delete attached volume and update its status The volume must be in 'IN_USE' status in order to be deleted. This function will send the corresponding job to Ganeti backend and update the status of the volume to 'DELETING'. """ _check_attachment(vm, volume) if volume.status not in ["IN_USE", "ERROR"]: raise faults.BadRequest("Cannot delete volume while volume is in" " '%s' status." % volume.status) if volume.index == 0: raise faults.BadRequest("Cannot delete the root volume of server %s." % vm) action_fields = {"disks": [("remove", volume, {})]} comm = commands.server_command("DELETE_VOLUME", action_fields=action_fields, for_user=volume.userid) return comm(_delete_volume)(vm, volume)
def detach_volume(vm, volume): """Detach a Volume from a VM The volume must be in 'IN_USE' status in order to be detached. Also, the root volume of the instance (index=0) can not be detached. This function will send the corresponding job to Ganeti backend and update the status of the volume to 'DETACHING'. """ _check_attachment(vm, volume) if volume.status not in ["IN_USE", "ERROR"]: raise faults.BadRequest("Cannot detach volume while volume is in" " '%s' status." % volume.status) if volume.index == 0: raise faults.BadRequest("Cannot detach the root volume of a server") action_fields = {"disks": [("remove", volume, {})]} comm = commands.server_command("DETACH_VOLUME", action_fields=action_fields) return comm(_detach_volume)(vm, volume)
def resize(vm, flavor): action_fields = {"beparams": {"vcpus": flavor.cpu, "maxmem": flavor.ram}} comm = commands.server_command("RESIZE", action_fields=action_fields) return comm(_resize)(vm, flavor)