diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..cd40f6d --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ + +all: install + +install: + install -o root -g root -m 0755 provisioner.sh /usr/local/bin/run-iscsi-provisioner + + [ -d /etc/default ] || install -o root -g root -m 0755 -d /etc/default + [ -f /etc/default/iscsi-provisioner ] || install -o root -g root -m 0755 systemd/iscsi-provisioner.conf.sample /etc/default/iscsi-provisioner + + install -o root -g root -m 0644 systemd/iscsi-provisioner.service /usr/lib/systemd/system + install -o root -g root -m 0644 systemd/iscsi-provisioner.timer /usr/lib/systemd/system + systemctl daemon-reload && systemctl enable iscsi-provisioner.timer diff --git a/provisioner.sh b/provisioner.sh new file mode 100755 index 0000000..602495a --- /dev/null +++ b/provisioner.sh @@ -0,0 +1,76 @@ +#!/bin/bash +set -euo pipefail + +# Used to make sure PersistantVolumes don't clash with one another +NORMALIZE_PATTERN='s|/|-|g;s|--|-|g' + + +log () { + echo "$@" | ts >&2 +} + + +[ ! -f "${STATEFILE}" ] && touch "${STATEFILE}" + + +pending_volumes="$(kubectl get -A persistentvolumeclaims -o json | jq '.items[] | select(.spec.storageClassName=="iscsi" and .status.phase=="Pending" and .spec.volumeName==null)')" + +for claim in $(echo "${pending_volumes}" | jq -r '. | .metadata.namespace + "/" + .metadata.name'); do \ + namespace="$(echo "${claim}" | cut -d/ -f1)" + name="$(echo "${claim}" | cut -d/ -f2)" + + manifest="$(echo "${pending_volumes}" | jq '. | select(.metadata.namespace=="'"${namespace}"'" and .metadata.name=="'"${name}"'")')" + requested_size="$(echo "${manifest}" | jq -r .spec.resources.requests.storage)" + filesystem="$(echo "${manifest}" | jq -er '.metadata.annotations."iscsi-provisioner/filesystem"')" || filesystem="${FILESYSTEM}" + + blockname="$(echo "${namespace}" | sed -E "${NORMALIZE_PATTERN}")--$(echo "${name}" | sed -E "${NORMALIZE_PATTERN}")" + lvname="iscsi--${blockname}" + + log "Found pending persistent volume claim '${name}' for ${requested_size} in namespace '${namespace}'" + + if ! sudo lvs "${LVM_GROUP}/${lvname}" > /dev/null 2>&1; then \ + if [ -z "${notdef:-}" ]; then \ + sudo lvcreate -L "${requested_size}" -n "${lvname}" "${LVM_GROUP}" + else + sudo lvcreate -V "${requested_size}" -n "${lvname}" -T "${LVM_GROUP}/${LV_THIN_POOL}" + fi + log "Created new logical volume '${LVM_GROUP}/${lvname}'" + fi + + if ! grep -xnF -- "${blockname}" "${STATEFILE}" > /dev/null 2>&1; then \ + echo "${blockname}" >> ${STATEFILE} + fi + lun="$(grep -xnF -- "${blockname}" "${STATEFILE}" | cut -d: -f1)" + + if ! sudo targetcli /backstores/block ls "${blockname}" >/dev/null 2>&1; then + sudo targetcli /backstores/block create "${blockname}" "/dev/${LVM_GROUP}/${lvname}" + log "Created new backing block storage volume '${blockname}' -> '/dev/${LVM_GROUP}/${lvname}'" + fi + + if ! sudo targetcli /iscsi/$IQN/tpg1/luns ls "lun${lun}" >/dev/null 2>&1; then + sudo targetcli /iscsi/$IQN/tpg1/luns create "/backstores/block/${blockname}" "${lun}" + log "Added LUN ${lun} to '/iscsi/$IQN/tpg1'" + fi + + kubectl apply --field-manager iscsi-provisioner --server-side -f - <