Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix xfs_grow arguments #16

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
FROM python:3.9-slim-buster
FROM python:3.10-slim-buster as builder
RUN apt-get update && apt-get install -y build-essential libbtrfsutil-dev
RUN pip wheel -w /wheels "https://github.com/kdave/btrfs-progs/archive/refs/tags/v5.16.1.tar.gz#egg=btrfsutil&subdirectory=libbtrfsutil/python"

FROM python:3.10-slim-buster

WORKDIR /app/

RUN apt-get update && \
apt-get install -y e2fsprogs btrfs-progs xfsprogs && \
apt-get install -y e2fsprogs btrfs-progs libbtrfsutil1 xfsprogs && \
rm -rf /var/lib/apt/lists/*

COPY --from=builder /wheels/ /wheels/
RUN pip install /wheels/*

ENV PIP_NO_CACHE_DIR 1
ADD ./requirements.txt ./
RUN pip install -r ./requirements.txt
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ Features
- [ ] Online shrinking: If fs supports it (e.g. btrfs)
- [ ] Offline expansion/shrinking
- [ ] Ephemeral inline volume
- [ ] Snapshots: If the fs supports it (e.g. btrfs)
- [x] Filesystem-level snapshots: `btrfs` supported

Motivation
---
Expand Down
40 changes: 36 additions & 4 deletions bd2fs.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from pathlib import Path

import grpc

from csi import csi_pb2, csi_pb2_grpc
from csi.csi_pb2 import (
NodeStageVolumeRequest,
Expand All @@ -11,6 +10,8 @@
NodeExpandVolumeRequest,
CreateVolumeRequest,
)
from google.protobuf.timestamp_pb2 import Timestamp

from declarative import (
be_mounted,
be_unmounted,
Expand All @@ -19,6 +20,8 @@
be_fs_expanded,
)
from fs_util import path_stats, mountpoint_to_dev
from orchestrator.k8s import volume_to_node, run_on_node
from remote import btrfs_create_snapshot, btrfs_delete_snapshot
from util import log_grpc_request


Expand All @@ -30,7 +33,7 @@ def get_fs(request):


class Bd2FsIdentityServicer(csi_pb2_grpc.IdentityServicer):
def __init__(self, bds):
def __init__(self, bds: csi_pb2_grpc.IdentityServicer):
self.bds = bds

@log_grpc_request
Expand All @@ -47,7 +50,7 @@ def Probe(self, request, context):


class Bd2FsNodeServicer(csi_pb2_grpc.NodeServicer):
def __init__(self, bds):
def __init__(self, bds: csi_pb2_grpc.NodeServicer):
self.bds = bds

# @log_grpc_request
Expand Down Expand Up @@ -167,7 +170,7 @@ def NodeExpandVolume(self, request, context):


class Bd2FsControllerServicer(csi_pb2_grpc.ControllerServicer):
def __init__(self, bds):
def __init__(self, bds: csi_pb2_grpc.ControllerServicer):
self.bds = bds

@log_grpc_request
Expand Down Expand Up @@ -219,3 +222,32 @@ def ControllerExpandVolume(self, request, context):
response = self.bds.ControllerExpandVolume(request, context)
assert response.node_expansion_required
return response

@log_grpc_request
def CreateSnapshot(self, request: csi_pb2.CreateSnapshotRequest, context):
volume_id = request.source_volume_id
name = request.name

snapshot_id, creation_time_ns = btrfs_create_snapshot(
volume_id=volume_id, name=name
)

nano = 10**9
return csi_pb2.CreateSnapshotResponse(
snapshot=csi_pb2.Snapshot(
size_bytes=0,
snapshot_id=snapshot_id,
source_volume_id=volume_id,
creation_time=Timestamp(
seconds=creation_time_ns // nano, nanos=creation_time_ns % nano
),
ready_to_use=True,
)
)

@log_grpc_request
def DeleteSnapshot(self, request: csi_pb2.DeleteSnapshotRequest, context):
snapshot_id = request.snapshot_id
volume_id, name = snapshot_id.rsplit("/", 1)
btrfs_delete_snapshot(volume_id=volume_id, name=name)
return csi_pb2.DeleteSnapshotResponse()
2 changes: 1 addition & 1 deletion consts.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import os

PROVISIONER_NAME = os.getenv("PROVISIONER_NAME", "rawfile.csi.openebs.io")
PROVISIONER_VERSION = "0.7.0"
PROVISIONER_VERSION = "0.8.0"
DATA_DIR = "/data"
CONFIG = {}
RESOURCE_EXHAUSTED_EXIT_CODE = 101
Expand Down
2 changes: 1 addition & 1 deletion declarative.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,6 @@ def be_fs_expanded(dev, path):
elif fs == "btrfs":
run(f"btrfs filesystem resize max {path}")
elif fs == "xfs":
run(f"xfs_growfs -d {dev}")
run(f"xfs_growfs -d {path}")
else:
raise Exception(f"Unsupported fsType: {fs}")
4 changes: 2 additions & 2 deletions deploy/charts/rawfile-csi/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ apiVersion: v2
name: rawfile-csi
description: RawFile Driver Container Storage Interface
type: application
version: 0.7.0
appVersion: 0.7.0
version: 0.8.0
appVersion: 0.8.0
31 changes: 31 additions & 0 deletions deploy/charts/rawfile-csi/templates/00-rbac.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,34 @@ roleRef:
kind: ClusterRole
name: {{ include "rawfile-csi.fullname" . }}-resizer
apiGroup: rbac.authorization.k8s.io
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: {{ include "rawfile-csi.fullname" . }}-snapshotter
rules:
- apiGroups: [""]
resources: ["events"]
verbs: ["list", "watch", "create", "update", "patch"]
- apiGroups: ["snapshot.storage.k8s.io"]
resources: ["volumesnapshotclasses"]
verbs: ["get", "list", "watch"]
- apiGroups: ["snapshot.storage.k8s.io"]
resources: ["volumesnapshotcontents"]
verbs: ["create", "get", "list", "watch", "update", "delete", "patch"]
- apiGroups: ["snapshot.storage.k8s.io"]
resources: ["volumesnapshotcontents/status"]
verbs: ["update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: {{ include "rawfile-csi.fullname" . }}-snapshotter
subjects:
- kind: ServiceAccount
name: {{ include "rawfile-csi.fullname" . }}-driver
namespace: {{ .Release.Namespace }}
roleRef:
kind: ClusterRole
name: {{ include "rawfile-csi.fullname" . }}-snapshotter
apiGroup: rbac.authorization.k8s.io
17 changes: 17 additions & 0 deletions deploy/charts/rawfile-csi/templates/01-node-plugin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -153,3 +153,20 @@ spec:
volumeMounts:
- name: socket-dir
mountPath: /csi
- name: external-snapshotter
image: gcr.io/k8s-staging-sig-storage/csi-snapshotter:v5.0.1
imagePullPolicy: IfNotPresent
args:
- "--csi-address=$(ADDRESS)"
- "--node-deployment=true"
- "--extra-create-metadata=true"
env:
- name: ADDRESS
value: /csi/csi.sock
- name: NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
volumeMounts:
- name: socket-dir
mountPath: /csi
2 changes: 1 addition & 1 deletion deploy/charts/rawfile-csi/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ provisionerName: "rawfile.csi.openebs.io"
defaults: &defaults
image:
repository: docker.io/openebs/rawfile-localpv
tag: 0.7.0
tag: 0.8.0
pullPolicy: Always
resources:
limits:
Expand Down
2 changes: 1 addition & 1 deletion orchestrator/k8s.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@ def is_finished():
return False

wait_for(is_finished, "task to finish")
task_pod.delete()
if task_pod.obj["status"]["phase"] != "Succeeded":
exit_code = task_pod.obj["status"]["containerStatuses"][0]["state"][
"terminated"
]["exitCode"]
raise CalledProcessError(returncode=exit_code, cmd=f"Task: {name}")
task_pod.delete()
1 change: 1 addition & 0 deletions rawfile_servicer.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ def ControllerGetCapabilities(self, request, context):
Cap(rpc=Cap.RPC(type=Cap.RPC.CREATE_DELETE_VOLUME)),
Cap(rpc=Cap.RPC(type=Cap.RPC.GET_CAPACITY)),
Cap(rpc=Cap.RPC(type=Cap.RPC.EXPAND_VOLUME)),
Cap(rpc=Cap.RPC(type=Cap.RPC.CREATE_DELETE_SNAPSHOT)),
]
)

Expand Down
60 changes: 55 additions & 5 deletions remote.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from contextlib import contextmanager

from util import remote_fn


Expand Down Expand Up @@ -34,9 +36,6 @@ def init_rawfile(volume_id, size):
from util import run
from consts import RESOURCE_EXHAUSTED_EXIT_CODE

if rawfile_util.get_capacity() < size:
raise CalledProcessError(returncode=RESOURCE_EXHAUSTED_EXIT_CODE, cmd="")

img_dir = rawfile_util.img_dir(volume_id)
img_dir.mkdir(exist_ok=True)
img_file = Path(f"{img_dir}/disk.img")
Expand Down Expand Up @@ -73,11 +72,62 @@ def expand_rawfile(volume_id, size):
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}")


@contextmanager
def mount_root_subvol(volume_id):
import tempfile
import pathlib

import rawfile_util
from util import run

root_subvol = tempfile.mkdtemp(prefix="rawfile-")

img_file = rawfile_util.img_file(volume_id)
loop_dev = rawfile_util.attach_loop(img_file)

run(f"mount -t btrfs -o subvolid=0 {loop_dev} {root_subvol}")
try:
yield root_subvol
finally:
run(f"umount {root_subvol}")
pathlib.Path(root_subvol).rmdir()


def btrfs_delete_snapshot(volume_id, name):
import btrfsutil

with mount_root_subvol(volume_id) as root_subvol:
snapshots_dir = f"{root_subvol}/.snapshots"
snapshot_path = f"{snapshots_dir}/{name}"
btrfsutil.delete_subvolume(snapshot_path)


def btrfs_create_snapshot(volume_id, name):
import btrfsutil
import time
import pathlib

# TODO: check fstype

with mount_root_subvol(volume_id) as root_subvol:
default_subvol_id = btrfsutil.get_default_subvolume(root_subvol)
default_subvol = btrfsutil.subvolume_path(root_subvol, default_subvol_id)
default_subvol = f"{root_subvol}/{default_subvol}"

snapshots_dir = f"{root_subvol}/.snapshots"
pathlib.Path(snapshots_dir).mkdir(parents=True, exist_ok=True)

snapshot_subvol = f"{snapshots_dir}/{name}"
btrfsutil.create_snapshot(default_subvol, snapshot_subvol, read_only=True)

snapshot_id = f"{volume_id}/{name}"
creation_time_ns = time.time_ns()
return snapshot_id, creation_time_ns
1 change: 1 addition & 0 deletions requirements.in
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ pyyaml
pykube-ng
munch
prometheus_client
#https://github.com/kdave/btrfs-progs/archive/refs/tags/v5.16.1.tar.gz#egg=btrfsutil&subdirectory=libbtrfsutil/python
27 changes: 13 additions & 14 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,43 +1,42 @@
#
# This file is autogenerated by pip-compile with python 3.9
# This file is autogenerated by pip-compile with python 3.10
# To update, run:
#
# pip-compile
#
certifi==2021.5.30
certifi==2021.10.8
# via requests
chardet==4.0.0
charset-normalizer==2.0.12
# via requests
click==8.0.1
click==8.0.3
# via -r requirements.in
grpcio==1.38.1
grpcio==1.43.0
# via
# -r requirements.in
# grpcio-tools
grpcio-tools==1.38.1
grpcio-tools==1.43.0
# via -r requirements.in
idna==2.10
idna==3.3
# via requests
munch==2.5.0
# via -r requirements.in
prometheus-client==0.11.0
prometheus-client==0.13.1
# via -r requirements.in
protobuf==3.17.3
protobuf==3.19.4
# via grpcio-tools
pykube-ng==21.3.0
pykube-ng==22.1.0
# via -r requirements.in
pyyaml==5.4.1
pyyaml==6.0
# via
# -r requirements.in
# pykube-ng
requests==2.25.1
requests==2.27.1
# via pykube-ng
six==1.16.0
# via
# grpcio
# munch
# protobuf
urllib3==1.26.6
urllib3==1.26.8
# via requests

# The following packages are considered to be unsafe in a requirements file:
Expand Down