예제 #1
0
 def NodeStageVolume(self, request, context):
     img_file = rawfile_util.img_file(request.volume_id)
     loop_file = attach_loop(img_file)
     staging_path = request.staging_target_path
     staging_dev_path = Path(f"{staging_path}/dev")
     be_symlink(path=staging_dev_path, to=loop_file)
     return csi_pb2.NodeStageVolumeResponse()
예제 #2
0
 def NodeUnstageVolume(self, request, context):
     img_file = rawfile_util.img_file(request.volume_id)
     staging_path = request.staging_target_path
     staging_dev_path = Path(f"{staging_path}/dev")
     be_absent(staging_dev_path)
     detach_loops(img_file)
     return csi_pb2.NodeUnstageVolumeResponse()
예제 #3
0
 def NodeStageVolume(self, request, context):
     img_file = rawfile_util.img_file(request.volume_id)
     loop_file = attach_loop(img_file)
     staging_path = request.staging_target_path
     device_path = Path(f"{staging_path}/device")
     be_symlink(path=device_path, to=loop_file)
     mount_path = Path(f"{staging_path}/mount")
     mount_path.mkdir(exist_ok=True)
     be_mounted(dev=device_path, mountpoint=mount_path)
     return csi_pb2.NodeStageVolumeResponse()
예제 #4
0
 def NodeExpandVolume(self, request, context):
     volume_id = request.volume_id
     size = request.capacity_range.required_bytes
     img_file = rawfile_util.img_file(volume_id)
     for dev in rawfile_util.attached_loops(img_file):
         run(f"losetup -c {dev}")
         if True:  # TODO: is ext2/ext3/ext4
             run(f"resize2fs {dev}")
         break
     return csi_pb2.NodeExpandVolumeResponse(capacity_bytes=size)
예제 #5
0
def expand_rawfile(volume_id, size):
    import rawfile_util
    from util import run

    img_file = rawfile_util.img_file(volume_id)
    if rawfile_util.metadata(volume_id)["size"] >= size:
        return
    rawfile_util.patch_metadata(
        volume_id,
        {"size": size},
    )
    run(f"truncate -s {size} {img_file}")
예제 #6
0
 def NodeExpandVolume(self, request, context):
     volume_id = request.volume_id
     volume_path = request.volume_path
     size = request.capacity_range.required_bytes
     fs_type = rawfile_util.metadata(volume_id)["fs_type"]
     img_file = rawfile_util.img_file(volume_id)
     for dev in rawfile_util.attached_loops(img_file):
         run(f"losetup -c {dev}")
         if fs_type == "ext4":
             run(f"resize2fs {dev}")
         elif fs_type == "btrfs":
             run(f"btrfs filesystem resize max {volume_path}")
         else:
             raise Exception(f"Unsupported fsType: {fs_type}")
         break
     return csi_pb2.NodeExpandVolumeResponse(capacity_bytes=size)
예제 #7
0
    def collect(self):
        VOLUME_ID = "volume_id"
        fs_size = GaugeMetricFamily(
            "rawfile_filesystem_size_bytes",
            "Filesystem size in bytes.",
            labels=[VOLUME_ID],
        )
        fs_free = GaugeMetricFamily(
            "rawfile_filesystem_avail_bytes",
            "Filesystem free space in bytes",
            labels=[VOLUME_ID],
        )
        fs_files = GaugeMetricFamily(
            "rawfile_filesystem_files",
            "Filesystem total file nodes.",
            labels=[VOLUME_ID],
        )
        fs_files_free = GaugeMetricFamily(
            "rawfile_filesystem_files_free",
            "Filesystem total free file nodes",
            labels=[VOLUME_ID],
        )
        dev_size = GaugeMetricFamily("rawfile_device_size_bytes",
                                     "Device size in bytes.",
                                     labels=[VOLUME_ID])
        dev_free = GaugeMetricFamily(
            "rawfile_device_free_bytes",
            "Device free space in bytes.",
            labels=[VOLUME_ID],
        )

        for volume_id in rawfile_util.list_all_volumes():
            img_file = rawfile_util.img_file(volume_id)
            labels = [volume_id]
            dev_stat = img_file.stat()
            dev_size.add_metric(labels, dev_stat.st_size)
            dev_free.add_metric(labels,
                                dev_stat.st_size - dev_stat.st_blocks * 512)
            mountpoint = volume_to_mountpoint(img_file)
            if mountpoint is not None:
                fs_stat = os.statvfs(mountpoint)
                fs_size.add_metric(labels, fs_stat.f_frsize * fs_stat.f_blocks)
                fs_free.add_metric(labels, fs_stat.f_frsize * fs_stat.f_bfree)
                fs_files.add_metric(labels, fs_stat.f_files)
                fs_files_free.add_metric(labels, fs_stat.f_ffree)

        return [fs_size, fs_free, fs_files, fs_files_free, dev_size, dev_free]
예제 #8
0
def expand_rawfile(volume_id, size):
    import rawfile_util

    from util import run
    from consts import RESOURCE_EXHAUSTED_EXIT_CODE

    img_file = rawfile_util.img_file(volume_id)
    size_inc = size - rawfile_util.metadata(volume_id)["size"]
    if size_inc <= 0:
        return
    if rawfile_util.get_capacity() < size_inc:
        exit(RESOURCE_EXHAUSTED_EXIT_CODE)

    rawfile_util.patch_metadata(
        volume_id,
        {"size": size},
    )
    run(f"truncate -s {size} {img_file}")
예제 #9
0
def volume_stats(volume_id: str) -> dict:
    img_file = rawfile_util.img_file(volume_id)
    dev_stat = img_file.stat()
    stats = {
        "dev_size": dev_stat.st_size,
        "dev_free": dev_stat.st_size - dev_stat.st_blocks * 512,
    }
    mountpoint = volume_to_mountpoint(img_file)
    if mountpoint is not None:
        fs_stat = os.statvfs(mountpoint)
        stats.update(
            {
                "fs_size": fs_stat.f_frsize * fs_stat.f_blocks,
                "fs_free": fs_stat.f_frsize * fs_stat.f_bfree,
                "fs_files": fs_stat.f_files,
                "fs_files_free": fs_stat.f_ffree,
            }
        )
    return stats
예제 #10
0
def scrub(volume_id):
    import time
    from subprocess import CalledProcessError

    import rawfile_util
    from consts import VOLUME_IN_USE_EXIT_CODE

    img_dir = rawfile_util.img_dir(volume_id)
    if not img_dir.exists():
        return

    img_file = rawfile_util.img_file(volume_id)
    loops = rawfile_util.attached_loops(img_file)
    if len(loops) > 0:
        raise CalledProcessError(returncode=VOLUME_IN_USE_EXIT_CODE, cmd="")

    now = time.time()
    deleted_at = now
    gc_at = now  # TODO: GC sensitive PVCs later
    rawfile_util.patch_metadata(volume_id, {
        "deleted_at": deleted_at,
        "gc_at": gc_at
    })
    rawfile_util.gc_if_needed(volume_id, dry_run=False)