Skip to content
This repository has been archived by the owner on Mar 9, 2021. It is now read-only.

Added initial creator for loopback based files #18

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
25 changes: 25 additions & 0 deletions blockstore/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Overview

This repo contains files necessary to use files in Gluster volumes as loop
mounted XFS formatted persistent volumes in Kubernetes and OpenShift. It
consists of three main items:

1. `flex-volume`
This is a a flex volume plugin to allow loop mounting Gluster files as XFS
based mounts into containers.
2. `creator`
This is a script that can be run on a Gluster server to pre-create the
files and format them with XFS.
3. `pv-recycler-pod`
This is a pod that is run in the cluster to watch for PVs that get released.
It deletes the files used as a loop device, recreates a fresh file for PV
reuse and marks the PV as available.

Further the `test` directory contains tests, that help sanitize the scripts and
future changes to the same.

---
# License

This code is licensed under Apache v2.0 with the exception of JQ which is
covered by the MIT license (see [COPYING_JQ](glfs-subvol/COPYING_JQ)).
3 changes: 3 additions & 0 deletions blockstore/creator/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Creating sub-volume block device PVs

TODO
157 changes: 157 additions & 0 deletions blockstore/creator/creator.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
#! /bin/bash
# vim: set ts=4 sw=4 et :

# Copyright 2018 Red Hat, Inc. and/or its affiliates.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

blockstore_base="blockstore"

function usage() {
echo "Usage: $0 <server1:server2:...> <volume> <base_path> <quota_in_GB> <start> <end>"
echo " 0 <= start <= end <= 65535"
}

function tohexpath() {
local -i l1=$1/256
local -i l2=$1%256
printf '%02x/%02x' "$l1" "$l2"
}

function tohexname() {
local -i l1=$1/256
local -i l2=$1%256
printf '%02x%02x' "$l1" "$l2"
}

function mkPvTemplate() {
local servers=$1
local volume=$2
local subdir=$3
local blockfile=$4
local capacity=$5
local uuid=$6

local pv_name
pv_name=$(echo "gluster-block-${uuid}-${subdir}-${blockfile}" | tr '/' '-')
cat - << EOT
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: "$pv_name"
labels:
cluster: "$(echo "$servers" | tr ':' '-')"
volume: "$volume"
subdir: "$(echo "${blockstore_base}/${subdir}" | tr '/' '-')"
supervol: "$uuid"
spec:
capacity:
storage: $capacity
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: gluster-block-subvol
flexVolume:
driver: "rht/glfs-block-subvol"
options:
cluster: $servers
volume: $volume
dir: ${blockstore_base}/${subdir}
file: $blockfile
EOT
}


servers=$1
volume_name=$2
base_path_in=$3
volsize_gb=$4
declare -i i_start=$5
declare -i i_end=$6

declare -i i=$i_start

if [ $# -ne 6 ]; then usage; exit 1; fi
if [ "$i" -lt 0 ]; then usage; exit 1; fi
if [ "$i" -gt "$i_end" ]; then usage; exit 1; fi
if [ "$i_end" -gt 65535 ]; then usage; exit 1; fi

base_path="${base_path_in}/${blockstore_base}"
if [ ! -d "${base_path}" ]; then
if ! mkdir "${base_path}"; then
echo "Unable to create $base_path"
exit 2
fi
fi

if [ ! -f "${base_path}/supervol-uuid" ]; then
uuidgen -r > "${base_path}/supervol-uuid"
fi
supervol_uuid=$(cat "${base_path}/supervol-uuid")

if [ -f "${base_path}/pvs-${i_start}-${i_end}.yml" ]; then
rm "${base_path}/pvs-${i_start}-${i_end}.yml"
fi

while [ "$i" -le "$i_end" ]; do
subdir=$(tohexpath "$i")
dir="${base_path}/${subdir}"
echo "creating: ${dir} (${i}/${i_end})"
if ! mkdir -p "$dir"; then
echo "Unable to create $dir"
exit 2
fi
if ! chmod 777 "$dir"; then
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure we need to open up the perms here. It exists on subvol because this last level directory needs to be writable by the random uid assigned to the pod where this acts as the PV. In this case, nothing but uid=0 touches this directory and the blockfile... creator is root, recycler is root, and so is kubelet when it calls the plugin.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack, will update in the next commit.

echo "Unable to set permissions on $dir"
exit 2
fi
blockfile=$(tohexname "$i")
blockfqpath="${base_path}/${subdir}/${blockfile}"
# File should not exist, or do not mess up existing devices here!
if [ -f "$blockfqpath" ]; then
echo "Found an existing device file with at $blockfile; skipping device creation"
((++i))
continue
fi
if ! touch "$blockfqpath"; then
echo "Unable to create file ${blockfile}"
exit 2
fi
if ! chmod 777 "$blockfqpath"; then
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

permissions here too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack, will update in the next commit.

echo "Unable to set permissions on ${blockfile}"
exit 2
fi
# Create a sparse file of required volume size
# 2097152 = 1024 * 1024 * 1024 (GB to bytes) / 512 (obs in dd)
seek_end=$((volsize_gb*2097152))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion by @JohnStrunk to use 1 byte and normal 1GB math, than this 512 byte conversion, still to process.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dd bs=1 count=1 if=/dev/zero of="${blockfqpath}" seek="$((volsize_gb * 1024 * 1024 *1024))"
Don't need bs=512 since it's not actually a block device.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack, will update in the next commit.

if [ $? -eq 3 ]; then
echo "Arithmetic error in expr, unable to setup ${blockfile}"
exit 2
fi
if ! dd seek="${seek_end}" obs=512 ibs=512 count=1 if=/dev/null of="${blockfqpath}" status=none ; then
echo "Error in dd to ${blockfile}"
exit 2
fi
# Format the file with XFS
if ! mkfs.xfs -q "${blockfqpath}"; then
echo "mkfs.xfs failed for ${blockfqpath}"
exit 2
fi
# TODO: Check mount (?)
# TODO: mkPvTemplate is as is, may need modifications
mkPvTemplate "$servers" "$volume_name" "$subdir" "$blockfile" "${volsize_gb}Gi" "$supervol_uuid" >> "${base_path}/pvs-${i_start}-${i_end}.yml"
((++i))
done

exit 0
9 changes: 9 additions & 0 deletions blockstore/creator/gluster-block-subvol-sc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: gluster-block-subvol
annotations:
storageclass.kubernetes.io/is-default-class: "true"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably don't want this. If a user wants this as the default storageclass, they can patch it once it's been added. Having it automatically set itself as cluster default raises the possibility of accidentally having 2 that are set as default. In that case, neither acts as default and default provisioning breaks.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This yml is a helper/reminder for anyone who wants to add this as the default, right? Normally we do not need to add this as a storage class, as we use the Flexvol scheme. Isn't that right?

Assuming so, I would assume we leave this as is, for interested users to set this as a default. If my assumptions are wrong, then I would need to change it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes good point. Since we use static provisioning, there is no need for the StorageClass object unless one wants it to become the default class. (not related to flex)

provisioner: none
5 changes: 5 additions & 0 deletions blockstore/flex-volume/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Installation of flex volume plugin

This is a flex volume plugin that needs to be installed on each Kubernetes node.

TODO
Loading