Repository: ChameleonCloud/CC-Images
Pull request #24: Replace cloudfuse with rclone
Author: login: pdmars
Created: 2025-03-21T22:30:00Z | Merged: 2025-03-25T20:19:33Z

I tested this with Ubuntu24.04, Ubuntu22.04, and Centos9. Also verified the behavior on KVM@TACC with no object store.


Diff:
diff --git a/elements/cc-cloudfuse/bin/cc-mount-object-store b/elements/cc-cloudfuse/bin/cc-mount-object-store
deleted file mode 100644
index 405aa10..0000000
--- a/elements/cc-cloudfuse/bin/cc-mount-object-store
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/bin/bash
-mkdir /home/cc/my_mounting_point
-
-TOKEN=$(cc-read-vendordata "service_token")
-PROJECT_ID=$(cc-read-vendordata "project_id")
-AUTH_URL_V3=$(cc-read-vendordata "auth_url_v3")
-REGION=$(cc-read-vendordata "region")
-
-cc-cloudfuse mount /home/cc/my_mounting_point -o authtoken="$TOKEN",projectid="$PROJECT_ID",authurl="$AUTH_URL_V3",region="$REGION"
-RESULT=$?
-if [ $RESULT -eq 0 ]; then
-  sudo mv /etc/auto_mount_readme /home/cc/README
-  sudo chown -R cc:cc /home/cc/README
-else
-  rm -rf /home/cc/my_mounting_point
-fi
diff --git a/elements/cc-cloudfuse/element-deps b/elements/cc-cloudfuse/element-deps
deleted file mode 100644
index d909f3e..0000000
--- a/elements/cc-cloudfuse/element-deps
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg-map
-install-static
-install-bin
diff --git a/elements/cc-cloudfuse/install.d/05-cc-cloudfuse b/elements/cc-cloudfuse/install.d/05-cc-cloudfuse
deleted file mode 100755
index 7ca5238..0000000
--- a/elements/cc-cloudfuse/install.d/05-cc-cloudfuse
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/bin/bash
-
-if [ "${DIB_DEBUG_TRACE:-0}" -gt 0 ]; then
-    set -x
-fi
-set -eu
-set -o pipefail
-
-# install cloudfuse
-git clone https://github.com/ChameleonCloud/cc-cloudfuse.git
-cd cc-cloudfuse/
-./configure
-make
-echo "Testing cloudfuse binary..."
-test_code=1
-./cloudfuse || test_code=$?
-# We expect code 1 because authentication will fail.
-# Other codes usually indicate a fatal signal was sent
-if  [[ 1 != "${test_code}" ]]; then
-  echo "Issue building cloudfuse binary!"
-  exit ${test_code}
-fi
-make install
-
-# clean up
-cd ..
-rm -rf cc-cloudfuse
-
-exit 0
diff --git a/elements/cc-cloudfuse/package-installs.yaml b/elements/cc-cloudfuse/package-installs.yaml
deleted file mode 100644
index acc23ea..0000000
--- a/elements/cc-cloudfuse/package-installs.yaml
+++ /dev/null
@@ -1,23 +0,0 @@
----
-libcurl-openssl-dev:
-  build-only: True
-libfuse-dev:
-  build-only: True
-libjson-c-dev:
-  build-only: True
-libneon-dev:
-  build-only: True
-  when: DISTRO_NAME = ubuntu
-libssl-dev:
-  build-only: True
-libxml:
-libxml-dev:
-  build-only: True
-neon:
-  when: DISTRO_NAME = centos
-gcc:
-  when: DISTRO_NAME = centos
-gcc-c++:
-  when: DISTRO_NAME = centos
-make:
-  when: DISTRO_NAME = centos
\ No newline at end of file
diff --git a/elements/cc-cloudfuse/pkg-map b/elements/cc-cloudfuse/pkg-map
deleted file mode 100644
index 7e3dc0f..0000000
--- a/elements/cc-cloudfuse/pkg-map
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-  "family": {
-    "debian": {
-      "libcurl-openssl-dev": "libcurl4-openssl-dev",
-      "libfuse-dev": "libfuse-dev",
-      "libjson-c-dev": "libjson-c-dev",
-      "libneon-dev": "libneon27-dev",
-      "libssl-dev": "libssl-dev",
-      "libxml": "libxml2",
-      "libxml-dev": "libxml2-dev"
-    },
-    "redhat": {
-      "libcurl-openssl-dev": "curl-devel",
-      "libfuse-dev": "fuse-devel",
-      "libjson-c-dev": "json-c-devel",
-      "libssl-dev": "openssl-devel",
-      "libxml": "libxml2-devel",
-      "libxml-dev": "libxml2-devel"
-    }
-  }
-}
diff --git a/elements/cc-cloudfuse/static/etc/auto_mount_readme b/elements/cc-cloudfuse/static/etc/auto_mount_readme
deleted file mode 100644
index 972b5d4..0000000
--- a/elements/cc-cloudfuse/static/etc/auto_mount_readme
+++ /dev/null
@@ -1,21 +0,0 @@
-cc-cloudfuse
-___________________________________________________________________
-The "my_mounting_point" directory under /home/cc is the mounting
-point to the Chameleon object store, so that you can access the
-object store as a file system.
-
-A mounting tool known as cc-cloudfuse has been installed. You can
-use cc-cloudfuse to mount/unmout the Chameleon object store.
-
-To mount:
-cc-cloudfuse mount <mounting_dir> [options]
-
-To see details about mount options:
-cc-cloudfuse mount -h
-
-To unmount:
-cc-cloudfuse unmount <mounting_dir>
-
-You can learn more about cc-cloudfuse by visiting Chameleon user
-documentation at
-https://chameleoncloud.readthedocs.io/en/latest/technical/swift.html#mounting-object-store-as-a-file-system
diff --git a/elements/cc-common/element-deps b/elements/cc-common/element-deps
index 023e02a..cefd958 100644
--- a/elements/cc-common/element-deps
+++ b/elements/cc-common/element-deps
@@ -1,5 +1,5 @@
 block-device-efi
-cc-cloudfuse
+cc-rclone
 cc-snapshot
 cc-firewall
 vm
diff --git a/elements/cc-rclone/bin/cc-mount-object-store b/elements/cc-rclone/bin/cc-mount-object-store
new file mode 100755
index 0000000..2d9fdb4
--- /dev/null
+++ b/elements/cc-rclone/bin/cc-mount-object-store
@@ -0,0 +1,141 @@
+#!/bin/bash
+
+REGION=$(cc-read-vendordata "region")
+if [ "${REGION}" = "KVM@TACC" ]; then
+  echo "${REGION} does not support object store mounts!"
+  exit 1
+fi
+
+MOUNT_BASE="$HOME/cc_my_mounting_point"
+RCLONE_REMOTE="rclone_s3"
+LOG_DIR="$HOME/.rclone/logs"
+PID_DIR="$HOME/.rclone/pids"
+
+mkdir -p "${LOG_DIR}" "${PID_DIR}"
+
+check_container_name() {
+  if [ -z "${1}" ]; then
+    echo "Error: Container name not provided"
+    echo "Usage: ${0} ${2} <container-name>"
+    return 1
+  fi
+  return 0
+}
+
+start() {
+  check_container_name "${1}" "start" || return 1
+  local container_name="${1}"
+
+  local mount_point="${MOUNT_BASE}/${container_name}"
+  local pid_file="${PID_DIR}/${container_name}.pid"
+  local log_file="${LOG_DIR}/${container_name}.log"
+
+  if [ -f "${pid_file}" ]; then
+    echo "Mount for ${container_name} already exists (PID: $(cat "${pid_file}"))"
+    return 1
+  fi
+
+  mkdir -p "${mount_point}"
+  if [ ! -f "${mount_point}/THIS_IS_NOT_MOUNTED" ]; then
+    touch "${mount_point}/THIS_IS_NOT_MOUNTED"
+  fi
+  rclone mount "${RCLONE_REMOTE}":"${container_name}" "${mount_point}" \
+    --daemon \
+    --allow-non-empty \
+    --log-level INFO \
+    --log-file="${log_file}" &
+
+  # Wait a moment for the process to start
+  sleep 2
+
+  local pid=$(pgrep -f "rclone mount ${RCLONE_REMOTE}:${container_name} ${mount_point}")
+
+  if [ -n "${pid}" ]; then
+    echo ${pid} > "${pid_file}"
+    echo "Started mount for ${container_name} (PID: ${pid})"
+  else
+    echo "Failed to start mount for ${container_name}"
+    return 1
+  fi
+}
+
+stop() {
+  check_container_name "${1}" "stop" || return 1
+  local container_name="${1}"
+
+  local pid_file="${PID_DIR}/${container_name}.pid"
+  local mount_point="${MOUNT_BASE}/${container_name}"
+
+  if [ ! -f "${pid_file}" ]; then
+    echo "No mount found for ${container_name}. Is it running?"
+    return 1
+  fi
+
+  local pid=$(cat "${pid_file}")
+  kill "${pid}"
+  fusermount -uz "${mount_point}"
+  rm "${pid_file}"
+  echo "Stopped mount for ${container_name}"
+}
+
+status() {
+  check_container_name "${1}" "status" || return 1
+  local container_name="${1}"
+
+  local pid_file="${PID_DIR}/${container_name}.pid"
+  local mount_point="${MOUNT_BASE}/${container_name}"
+
+  if [ -f "${pid_file}" ]; then
+    local pid=$(cat "${pid_file}")
+    if kill -0 "${pid}" 2>/dev/null; then
+      echo "Mount for ${container_name} is active (PID: ${pid})"
+      echo "Mount point: ${mount_point}"
+    else
+      echo "Mount for ${container_name} exists but process is not running"
+      echo "You may want to clean up the stale PID file: ${pid_file}"
+    fi
+  else
+      echo "No mount found for ${container_name}. Is it running?"
+  fi
+}
+
+list_mounts() {
+  echo "Active mounts:"
+  local found_mounts=false
+  for pid_file in "${PID_DIR}"/*.pid; do
+    if [ -f "${pid_file}" ]; then
+      local container_name=$(basename "${pid_file}" .pid)
+      local pid=$(cat "${pid_file}")
+      local mount_point="${MOUNT_BASE}/${container_name}"
+      if kill -0 "${pid}" 2>/dev/null; then
+        printf "%-20s - PID: %-6s - Mount: %s\n" "${container_name}" "${pid}" "${mount_point}"
+        found_mounts=true
+      else
+        printf "%-20s - Stale PID: %-6s - NOT MOUNTED!\n" "$container_name" "${pid}"
+      fi
+    fi
+  done
+
+  if [ "${found_mounts}" = false ]; then
+    echo "  No active mounts found"
+  fi
+}
+
+case "${1}" in
+  start)
+    start "${2}"
+    ;;
+  stop)
+    stop "${2}"
+    ;;
+  status)
+    status "${2}"
+    ;;
+  list)
+    list_mounts
+    ;;
+  *)
+    echo "Usage: ${0} {start|stop|status|list} [<container-name>]"
+    exit 1
+    ;;
+esac
diff --git a/elements/cc-rclone/bin/setup-cc-mount-object-store b/elements/cc-rclone/bin/setup-cc-mount-object-store
new file mode 100644
index 0000000..f2c15dc
--- /dev/null
+++ b/elements/cc-rclone/bin/setup-cc-mount-object-store
@@ -0,0 +1,59 @@
+#!/bin/bash
+
+exit_failure() {
+  echo "$(date '+%Y-%m-%d %H:%M:%S'): Failed to create object store mount!" >> cc_my_mounting_point.failure
+}
+
+trap 'exit_failure' EXIT
+
+set -e
+
+if [ ! -f /home/cc/openrc ]; then
+  OPENRC=$(cc-read-vendordata "openrc")
+  if [ "${OPENRC}" != "null" ]; then
+    cc-read-vendordata "openrc" >  /home/cc/openrc
+    sed -i 's/^ *//g' /home/cc/openrc
+  else
+    echo "$(date '+%Y-%m-%d %H:%M:%S'): Unable to read OPENRC" >> /home/cc/cc_my_mounting_point.failure
+    exit 1
+  fi
+fi
+
+source /home/cc/openrc
+if [ -z "${OS_STORAGE_URL}" ]; then
+  echo "$(date '+%Y-%m-%d %H:%M:%S'): OS_STORAGE_URL was not set" >> /home/cc/cc_my_mounting_point.failure
+  REGION=$(cc-read-vendordata "region")
+  if [ "${REGION}" = "KVM@TACC" ]; then
+    echo "$(date '+%Y-%m-%d %H:%M:%S'): KVM@TACC does not have an object store available" >> /home/cc/cc_my_mounting_point.failure
+  fi
+  exit 1
+fi
+
+EC2_STORAGE_ENDPOINT=${OS_STORAGE_URL%/swift*}
+EC2_CREDS="$(openstack ec2 credential list -f json 2>/dev/null)"
+if [ $? -eq 0 ] && [ ! -z "$output" ]; then
+  ACCESS_KEY=$(echo "$output" | jq -r '.[0].Access')
+  SECRET_KEY=$(echo "$output" | jq -r '.[0].Secret')
+else
+  EC2_CREDS="$(openstack ec2 credential create -f json 2>/dev/null)"
+  ACCESS_KEY=$(echo ${EC2_CREDS} | jq -r '.access')
+  SECRET_KEY=$(echo ${EC2_CREDS} | jq -r '.secret')
+fi
+
+if [ -z "$EC2_STORAGE_ENDPOINT" ] || [ -z "$ACCESS_KEY" ] || [ -z "$SECRET_KEY" ]; then
+  echo "$(date '+%Y-%m-%d %H:%M:%S'): EC2 vars not set" >> /home/cc/cc_my_mounting_point.failure
+  exit 1
+fi
+
+mkdir -p /home/cc/.config/rclone/
+cat << EOF > /home/cc/.config/rclone/rclone.conf
+[rclone_s3]
+type = s3
+provider = Ceph
+endpoint = ${EC2_STORAGE_ENDPOINT}
+access_key_id = ${ACCESS_KEY}
+secret_access_key = ${SECRET_KEY}
+EOF
+
+sudo mv /etc/auto_mount_readme /home/cc/README
+sudo chown -R cc:cc /home/cc/README
diff --git a/elements/cc-rclone/element-deps b/elements/cc-rclone/element-deps
new file mode 100644
index 0000000..d888ae5
--- /dev/null
+++ b/elements/cc-rclone/element-deps
@@ -0,0 +1 @@
+install-bin
diff --git a/elements/cc-rclone/environment.d/00-rclone-env b/elements/cc-rclone/environment.d/00-rclone-env
new file mode 100644
index 0000000..1416b69
--- /dev/null
+++ b/elements/cc-rclone/environment.d/00-rclone-env
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+export RCLONE_V="v1.69.1"
+export RCLONE_URL_BASE="https://github.com/rclone/rclone/releases/download/${RCLONE_V}"
+export RCLONE_AMD_DEB_URL="${RCLONE_URL_BASE}/rclone-${RCLONE_V}-linux-amd64.deb"
+export RCLONE_ARM_DEB_URL="${RCLONE_URL_BASE}/rclone-${RCLONE_V}-linux-arm64.deb"
+export RCLONE_AMD_RPM_URL="${RCLONE_URL_BASE}/rclone-${RCLONE_V}-linux-amd64.rpm"
diff --git a/elements/cc-rclone/install.d/05-cc-rclone b/elements/cc-rclone/install.d/05-cc-rclone
new file mode 100755
index 0000000..752c1e3
--- /dev/null
+++ b/elements/cc-rclone/install.d/05-cc-rclone
@@ -0,0 +1,67 @@
+#!/bin/bash
+
+if [ "${DIB_DEBUG_TRACE:-0}" -gt 0 ]; then
+    set -x
+fi
+set -eu
+set -o pipefail
+
+OS="unknown"
+ARCH="unknown"
+
+case $(uname -m) in
+  x86_64|amd64) ARCH="amd" ;;
+  arm64|aarch64) ARCH="arm" ;;
+  *) echo "Unsupported architecture"; exit 1 ;;
+esac
+
+if [ -f /etc/debian_version ]; then
+  OS="ubuntu"
+elif [ -f /etc/centos-release ]; then
+  OS="centos"
+else
+  echo "Unsupported operating system"
+  exit 1
+fi
+
+URL=""
+case "${OS}-${ARCH}" in
+  "ubuntu-amd")
+    [ -z "${RCLONE_AMD_DEB_URL}" ] && { echo "RCLONE_AMD_DEB_URL not set"; exit 1; }
+    URL="${RCLONE_AMD_DEB_URL}"
+    ;;
+  "ubuntu-arm")
+    [ -z "${RCLONE_ARM_DEB_URL}" ] && { echo "RCLONE_ARM_DEB_URL not set"; exit 1; }
+    URL="${RCLONE_ARM_DEB_URL}"
+    ;;
+  "centos-amd")
+    [ -z "${RCLONE_AMD_RPM_URL}" ] && { echo "RCLONE_AMD_RPM_URL not set"; exit 1; }
+    URL="${RCLONE_AMD_RPM_URL}"
+    ;;
+  *)
+    echo "Unsupported OS-architecture combination: ${OS}-${ARCH}"
+    exit 1
+    ;;
+esac
+
+FILENAME=$(basename "${URL}")
+TMP_FILE="/tmp/${FILENAME}"
+
+echo "Downloading ${FILENAME}..."
+if ! curl -sL "${URL}" -o "${TMP_FILE}"; then
+  echo "Failed to download package"
+  exit 1
+fi
+
+echo "Installing ${FILENAME}..."
+case "${OS}" in
+  "ubuntu")
+    sudo dpkg -i "${TMP_FILE}"
+    ;;
+  "centos")
+    sudo rpm -i "${TMP_FILE}"
+    ;;
+esac
+
+rm -f "${TMP_FILE}"
+echo "rclone installation complete!"
diff --git a/elements/cc-rclone/package-installs.yaml b/elements/cc-rclone/package-installs.yaml
new file mode 100644
index 0000000..30f5620
--- /dev/null
+++ b/elements/cc-rclone/package-installs.yaml
@@ -0,0 +1,3 @@
+# required by rclone, and not automatically installed
+# via the rpm package in centos9
+fuse3:
diff --git a/elements/cc-rclone/static/etc/auto_mount_readme b/elements/cc-rclone/static/etc/auto_mount_readme
new file mode 100644
index 0000000..aba4381
--- /dev/null
+++ b/elements/cc-rclone/static/etc/auto_mount_readme
@@ -0,0 +1,48 @@
+cc-rclone
+___________________________________________________________________
+The "cc_my_mounting_point" directory under /home/cc is the base
+mounting point to the Chameleon object store, so that you can access
+the object store as a file system. Within this directory different
+directories map to containers you have mounted in the object store.
+
+The mount is facilitated by rclone [1].
+
+You can mount the object store by running:
+
+cc-mount-object-store start your_container_name
+
+You can check if the mount is running with:
+
+cc-mount-object-store status your_container_name
+
+And you can terminate the rclone mount with:
+
+cc-mount-object-store stop your_container_name
+
+Finally, you can list all running mounts with:
+
+cc-mount-object-store list
+
+If there is a directory that is unmounted, it should have an empty
+file in the directory named THIS_IS_NOT_MOUNTED, for example:
+~/cc_my_mounting_point/your_container_name/THIS_IS_NOT_MOUNTED.
+
+If there is no container with the name you provide when you
+start the mount, it will be created by rclone as soon as you copy
+files into the directory.
+
+WARNING:
+
+The use of "cc_my_mounting_point" to sync files between your instance
+and the object store is a best effort tool. It is the responsibilty
+of the user to verify the files sync'd correctly and are valid.
+
+Given the challenges of mapping files in a file system to an object
+store over a network, numerous problems can occur that may impact
+the availability of files on the object store. If you attempt
+to copy files into the mount point and receive errors, it is
+important that you verify the existence and contents of the file
+in the object store and not simply assume the file has been
+persisted there (even if it is present in the mount point).
+
+1. rclone: https://rclone.org/
diff --git a/elements/cc-cloudfuse/static/etc/cloud/cloud.cfg.d/95_chi_cloudfuse.cfg b/elements/cc-rclone/static/etc/cloud/cloud.cfg.d/95_chi_rclone.cfg
similarity index 68%
rename from elements/cc-cloudfuse/static/etc/cloud/cloud.cfg.d/95_chi_cloudfuse.cfg
rename to elements/cc-rclone/static/etc/cloud/cloud.cfg.d/95_chi_rclone.cfg
index 32958e9..ff74855 100644
--- a/elements/cc-cloudfuse/static/etc/cloud/cloud.cfg.d/95_chi_cloudfuse.cfg
+++ b/elements/cc-rclone/static/etc/cloud/cloud.cfg.d/95_chi_rclone.cfg
@@ -6,4 +6,4 @@ merge_how:
    settings: [no_replace, recurse_list]
 
 runcmd:
-  - su cc -c /usr/local/bin/cc-mount-object-store
+  - su cc -c /usr/local/bin/setup-cc-mount-object-store


Reviews:
user: login: msherman64
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-21T22:32:31Z
user: login: pdmars
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-24T13:57:46Z
user: login: msherman64
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-24T16:00:00Z
user: login: msherman64
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-24T16:17:58Z
user: login: pdmars
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-24T19:56:18Z
user: login: msherman64
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-24T20:19:31Z
user: login: pdmars
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-24T20:28:35Z
user: login: msherman64
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-24T20:31:36Z
user: login: msherman64
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-24T20:53:27Z
user: login: msherman64
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-24T20:57:22Z
user: login: msherman64
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-25T16:01:42Z
user: login: msherman64
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-25T16:04:50Z
user: login: msherman64
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-25T16:05:25Z
user: login: msherman64
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-25T16:09:54Z
user: login: pdmars
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-25T16:10:28Z
user: login: msherman64
body: Minor comments mostly about where files live, but:

What's the difference between:
`elements/cc-rclone/static/etc/cc-mount-object-store and  `elements/cc-rclone/bin/cc-mount-object-store`

is the one under /etc/ meant to replace it?
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-25T16:12:27Z
user: login: pdmars
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-25T16:12:36Z
user: login: pdmars
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-25T16:41:56Z
user: login: msherman64
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-25T16:43:43Z
user: login: msherman64
body: Looking good to me!
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-25T16:46:38Z
user: login: msherman64
body: Looks good to me! Feel free to go ahead on the squash+merge 👍 
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-25T20:18:07Z

Review comments:
diff_hunk: @@ -0,0 +1,65 @@
+#!/bin/bash
+
+exit_failure() {
+  echo "$(date '+%Y-%m-%d %H:%M:%S'): Failed to create object store mount!" >> my_mounting_point.failure
+}
+
+trap 'exit_failure' EXIT
+
+set -e
+
+if [ ! -f /home/cc/openrc ]; then
+  OPENRC=$(cc-read-vendordata "openrc")
+  if [ "${OPENRC}" != "null" ]; then
+    cc-read-vendordata "openrc" >  /home/cc/openrc
+    sed -i 's/^ *//g' /home/cc/openrc
+  else
+    echo "$(date '+%Y-%m-%d %H:%M:%S'): Unable to read OPENRC" >> /home/cc/my_mounting_point.failure
+    exit 1
+  fi
+fi
+
+source /home/cc/openrc
+if [ -z "${OS_STORAGE_URL}" ]; then
+  echo "$(date '+%Y-%m-%d %H:%M:%S'): OS_STORAGE_URL was not set" >> /home/cc/my_mounting_point.failure
+  REGION=$(cc-read-vendordata "region")
+  if [ "${REGION}" = "KVM@TACC" ]; then
+    echo "$(date '+%Y-%m-%d %H:%M:%S'): KVM@TACC does not have an object store available" >> /home/cc/my_mounting_point.failure
+  fi
+  exit 1
+fi
+
+mkdir /home/cc/my_mounting_point
+touch /home/cc/my_mounting_point/THIS_IS_NOT_MOUNTED
+mkdir -p /home/cc/.config/rclone/
+
+EC2_STORAGE_ENDPOINT=${OS_STORAGE_URL%/swift*}
+EC2_CREDS="$(openstack ec2 credential create -f json)"
path: elements/cc-rclone/bin/cc-mount-object-store
user: login: msherman64
body: Main concern here is this will  create a new credential every time it runs
created_at: 2025-03-21T22:32:31Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,65 @@
+#!/bin/bash
+
+exit_failure() {
+  echo "$(date '+%Y-%m-%d %H:%M:%S'): Failed to create object store mount!" >> my_mounting_point.failure
+}
+
+trap 'exit_failure' EXIT
+
+set -e
+
+if [ ! -f /home/cc/openrc ]; then
+  OPENRC=$(cc-read-vendordata "openrc")
+  if [ "${OPENRC}" != "null" ]; then
+    cc-read-vendordata "openrc" >  /home/cc/openrc
+    sed -i 's/^ *//g' /home/cc/openrc
+  else
+    echo "$(date '+%Y-%m-%d %H:%M:%S'): Unable to read OPENRC" >> /home/cc/my_mounting_point.failure
+    exit 1
+  fi
+fi
+
+source /home/cc/openrc
+if [ -z "${OS_STORAGE_URL}" ]; then
+  echo "$(date '+%Y-%m-%d %H:%M:%S'): OS_STORAGE_URL was not set" >> /home/cc/my_mounting_point.failure
+  REGION=$(cc-read-vendordata "region")
+  if [ "${REGION}" = "KVM@TACC" ]; then
+    echo "$(date '+%Y-%m-%d %H:%M:%S'): KVM@TACC does not have an object store available" >> /home/cc/my_mounting_point.failure
+  fi
+  exit 1
+fi
+
+mkdir /home/cc/my_mounting_point
+touch /home/cc/my_mounting_point/THIS_IS_NOT_MOUNTED
+mkdir -p /home/cc/.config/rclone/
+
+EC2_STORAGE_ENDPOINT=${OS_STORAGE_URL%/swift*}
+EC2_CREDS="$(openstack ec2 credential create -f json)"
path: elements/cc-rclone/bin/cc-mount-object-store
user: login: pdmars
body: Are there possibilities for generating a single long-term use credentials up front but reusing it for subsequent mounts of this?

Otherwise we can go the route of "user brings / manages their own credential."
created_at: 2025-03-24T13:57:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,65 @@
+#!/bin/bash
+
+exit_failure() {
+  echo "$(date '+%Y-%m-%d %H:%M:%S'): Failed to create object store mount!" >> my_mounting_point.failure
+}
+
+trap 'exit_failure' EXIT
+
+set -e
+
+if [ ! -f /home/cc/openrc ]; then
+  OPENRC=$(cc-read-vendordata "openrc")
+  if [ "${OPENRC}" != "null" ]; then
+    cc-read-vendordata "openrc" >  /home/cc/openrc
+    sed -i 's/^ *//g' /home/cc/openrc
+  else
+    echo "$(date '+%Y-%m-%d %H:%M:%S'): Unable to read OPENRC" >> /home/cc/my_mounting_point.failure
+    exit 1
+  fi
+fi
+
+source /home/cc/openrc
+if [ -z "${OS_STORAGE_URL}" ]; then
+  echo "$(date '+%Y-%m-%d %H:%M:%S'): OS_STORAGE_URL was not set" >> /home/cc/my_mounting_point.failure
+  REGION=$(cc-read-vendordata "region")
+  if [ "${REGION}" = "KVM@TACC" ]; then
+    echo "$(date '+%Y-%m-%d %H:%M:%S'): KVM@TACC does not have an object store available" >> /home/cc/my_mounting_point.failure
+  fi
+  exit 1
+fi
+
+mkdir /home/cc/my_mounting_point
+touch /home/cc/my_mounting_point/THIS_IS_NOT_MOUNTED
+mkdir -p /home/cc/.config/rclone/
+
+EC2_STORAGE_ENDPOINT=${OS_STORAGE_URL%/swift*}
+EC2_CREDS="$(openstack ec2 credential create -f json)"
path: elements/cc-rclone/bin/cc-mount-object-store
user: login: msherman64
body: it's a little messy with the ec2 credentials. We could do something like "list credentials, and create if missing", the downside is that there's no way to tag or otherwise label ec2 credentials via the openstack api, and I'm unsure if there's any issue from reusing one that was previously created. (just dunno all the edges)

created_at: 2025-03-24T16:00:00Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,65 @@
+#!/bin/bash
+
+exit_failure() {
+  echo "$(date '+%Y-%m-%d %H:%M:%S'): Failed to create object store mount!" >> my_mounting_point.failure
+}
+
+trap 'exit_failure' EXIT
+
+set -e
+
+if [ ! -f /home/cc/openrc ]; then
+  OPENRC=$(cc-read-vendordata "openrc")
+  if [ "${OPENRC}" != "null" ]; then
+    cc-read-vendordata "openrc" >  /home/cc/openrc
+    sed -i 's/^ *//g' /home/cc/openrc
+  else
+    echo "$(date '+%Y-%m-%d %H:%M:%S'): Unable to read OPENRC" >> /home/cc/my_mounting_point.failure
+    exit 1
+  fi
+fi
+
+source /home/cc/openrc
+if [ -z "${OS_STORAGE_URL}" ]; then
+  echo "$(date '+%Y-%m-%d %H:%M:%S'): OS_STORAGE_URL was not set" >> /home/cc/my_mounting_point.failure
+  REGION=$(cc-read-vendordata "region")
+  if [ "${REGION}" = "KVM@TACC" ]; then
+    echo "$(date '+%Y-%m-%d %H:%M:%S'): KVM@TACC does not have an object store available" >> /home/cc/my_mounting_point.failure
+  fi
+  exit 1
+fi
+
+mkdir /home/cc/my_mounting_point
+touch /home/cc/my_mounting_point/THIS_IS_NOT_MOUNTED
+mkdir -p /home/cc/.config/rclone/
+
+EC2_STORAGE_ENDPOINT=${OS_STORAGE_URL%/swift*}
+EC2_CREDS="$(openstack ec2 credential create -f json)"
path: elements/cc-rclone/bin/cc-mount-object-store
user: login: msherman64
body: more general thoughts, I do think making this "run command to opt in" instead of "run automatically on boot" gives us more flexibility.

I think we could either have it create/reuse an ec2 credential, as above, or if using the swift backend, use the openrc credential directly. Assuming the mount still works ok, the swift backend would work more simply from an authentication perspective.
created_at: 2025-03-24T16:17:58Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,65 @@
+#!/bin/bash
+
+exit_failure() {
+  echo "$(date '+%Y-%m-%d %H:%M:%S'): Failed to create object store mount!" >> my_mounting_point.failure
+}
+
+trap 'exit_failure' EXIT
+
+set -e
+
+if [ ! -f /home/cc/openrc ]; then
+  OPENRC=$(cc-read-vendordata "openrc")
+  if [ "${OPENRC}" != "null" ]; then
+    cc-read-vendordata "openrc" >  /home/cc/openrc
+    sed -i 's/^ *//g' /home/cc/openrc
+  else
+    echo "$(date '+%Y-%m-%d %H:%M:%S'): Unable to read OPENRC" >> /home/cc/my_mounting_point.failure
+    exit 1
+  fi
+fi
+
+source /home/cc/openrc
+if [ -z "${OS_STORAGE_URL}" ]; then
+  echo "$(date '+%Y-%m-%d %H:%M:%S'): OS_STORAGE_URL was not set" >> /home/cc/my_mounting_point.failure
+  REGION=$(cc-read-vendordata "region")
+  if [ "${REGION}" = "KVM@TACC" ]; then
+    echo "$(date '+%Y-%m-%d %H:%M:%S'): KVM@TACC does not have an object store available" >> /home/cc/my_mounting_point.failure
+  fi
+  exit 1
+fi
+
+mkdir /home/cc/my_mounting_point
+touch /home/cc/my_mounting_point/THIS_IS_NOT_MOUNTED
+mkdir -p /home/cc/.config/rclone/
+
+EC2_STORAGE_ENDPOINT=${OS_STORAGE_URL%/swift*}
+EC2_CREDS="$(openstack ec2 credential create -f json)"
path: elements/cc-rclone/bin/cc-mount-object-store
user: login: pdmars
body: Even with a newer rclone I still am having issues with the Swift backend and files >100mb. Maybe I'm missing something else though.
created_at: 2025-03-24T19:56:17Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,65 @@
+#!/bin/bash
+
+exit_failure() {
+  echo "$(date '+%Y-%m-%d %H:%M:%S'): Failed to create object store mount!" >> my_mounting_point.failure
+}
+
+trap 'exit_failure' EXIT
+
+set -e
+
+if [ ! -f /home/cc/openrc ]; then
+  OPENRC=$(cc-read-vendordata "openrc")
+  if [ "${OPENRC}" != "null" ]; then
+    cc-read-vendordata "openrc" >  /home/cc/openrc
+    sed -i 's/^ *//g' /home/cc/openrc
+  else
+    echo "$(date '+%Y-%m-%d %H:%M:%S'): Unable to read OPENRC" >> /home/cc/my_mounting_point.failure
+    exit 1
+  fi
+fi
+
+source /home/cc/openrc
+if [ -z "${OS_STORAGE_URL}" ]; then
+  echo "$(date '+%Y-%m-%d %H:%M:%S'): OS_STORAGE_URL was not set" >> /home/cc/my_mounting_point.failure
+  REGION=$(cc-read-vendordata "region")
+  if [ "${REGION}" = "KVM@TACC" ]; then
+    echo "$(date '+%Y-%m-%d %H:%M:%S'): KVM@TACC does not have an object store available" >> /home/cc/my_mounting_point.failure
+  fi
+  exit 1
+fi
+
+mkdir /home/cc/my_mounting_point
+touch /home/cc/my_mounting_point/THIS_IS_NOT_MOUNTED
+mkdir -p /home/cc/.config/rclone/
+
+EC2_STORAGE_ENDPOINT=${OS_STORAGE_URL%/swift*}
+EC2_CREDS="$(openstack ec2 credential create -f json)"
path: elements/cc-rclone/bin/cc-mount-object-store
user: login: msherman64
body: nah, that's fair. I think just using the first entry from `openstack ec2 credential list` is reasonable, and creating it if missing.

[One thing I wasn't clear on from our current cloudfuse docs](https://chameleoncloud.readthedocs.io/en/latest/technical/swift.html#mounting-object-store-as-a-file-system), is how the bucket gets named, and what "site" the bucket is at. I think we assume it's always named after the username, and at the "local" site, but what if the username has characters that aren't permitted in a bucket?

 
created_at: 2025-03-24T20:19:31Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,65 @@
+#!/bin/bash
+
+exit_failure() {
+  echo "$(date '+%Y-%m-%d %H:%M:%S'): Failed to create object store mount!" >> my_mounting_point.failure
+}
+
+trap 'exit_failure' EXIT
+
+set -e
+
+if [ ! -f /home/cc/openrc ]; then
+  OPENRC=$(cc-read-vendordata "openrc")
+  if [ "${OPENRC}" != "null" ]; then
+    cc-read-vendordata "openrc" >  /home/cc/openrc
+    sed -i 's/^ *//g' /home/cc/openrc
+  else
+    echo "$(date '+%Y-%m-%d %H:%M:%S'): Unable to read OPENRC" >> /home/cc/my_mounting_point.failure
+    exit 1
+  fi
+fi
+
+source /home/cc/openrc
+if [ -z "${OS_STORAGE_URL}" ]; then
+  echo "$(date '+%Y-%m-%d %H:%M:%S'): OS_STORAGE_URL was not set" >> /home/cc/my_mounting_point.failure
+  REGION=$(cc-read-vendordata "region")
+  if [ "${REGION}" = "KVM@TACC" ]; then
+    echo "$(date '+%Y-%m-%d %H:%M:%S'): KVM@TACC does not have an object store available" >> /home/cc/my_mounting_point.failure
+  fi
+  exit 1
+fi
+
+mkdir /home/cc/my_mounting_point
+touch /home/cc/my_mounting_point/THIS_IS_NOT_MOUNTED
+mkdir -p /home/cc/.config/rclone/
+
+EC2_STORAGE_ENDPOINT=${OS_STORAGE_URL%/swift*}
+EC2_CREDS="$(openstack ec2 credential create -f json)"
path: elements/cc-rclone/bin/cc-mount-object-store
user: login: pdmars
body: To start I was just mounting the entire object store they have permissions for, but scoping it to something more specific makes sense. Instead of their username, we could also make them specify the bucket when they start the mount? It introduces friction which might reduce the willingness to use it. On the other hand, it's not _that_ much friction and helps make it more clear what/where it is mounting since they have to take some ownership over understanding and providing that argument.
created_at: 2025-03-24T20:28:35Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,65 @@
+#!/bin/bash
+
+exit_failure() {
+  echo "$(date '+%Y-%m-%d %H:%M:%S'): Failed to create object store mount!" >> my_mounting_point.failure
+}
+
+trap 'exit_failure' EXIT
+
+set -e
+
+if [ ! -f /home/cc/openrc ]; then
+  OPENRC=$(cc-read-vendordata "openrc")
+  if [ "${OPENRC}" != "null" ]; then
+    cc-read-vendordata "openrc" >  /home/cc/openrc
+    sed -i 's/^ *//g' /home/cc/openrc
+  else
+    echo "$(date '+%Y-%m-%d %H:%M:%S'): Unable to read OPENRC" >> /home/cc/my_mounting_point.failure
+    exit 1
+  fi
+fi
+
+source /home/cc/openrc
+if [ -z "${OS_STORAGE_URL}" ]; then
+  echo "$(date '+%Y-%m-%d %H:%M:%S'): OS_STORAGE_URL was not set" >> /home/cc/my_mounting_point.failure
+  REGION=$(cc-read-vendordata "region")
+  if [ "${REGION}" = "KVM@TACC" ]; then
+    echo "$(date '+%Y-%m-%d %H:%M:%S'): KVM@TACC does not have an object store available" >> /home/cc/my_mounting_point.failure
+  fi
+  exit 1
+fi
+
+mkdir /home/cc/my_mounting_point
+touch /home/cc/my_mounting_point/THIS_IS_NOT_MOUNTED
+mkdir -p /home/cc/.config/rclone/
+
+EC2_STORAGE_ENDPOINT=${OS_STORAGE_URL%/swift*}
+EC2_CREDS="$(openstack ec2 credential create -f json)"
+ACCESS_KEY=$(echo ${EC2_CREDS} | jq -r '.access')
+SECRET_KEY=$(echo ${EC2_CREDS} | jq -r '.secret')
+
+if [ -z "$EC2_STORAGE_ENDPOINT" ] || [ -z "$ACCESS_KEY" ] || [ -z "$SECRET_KEY" ]; then
+  echo "$(date '+%Y-%m-%d %H:%M:%S'): EC2 vars not set" >> /home/cc/my_mounting_point.failure
+  exit 1
+fi
+
+cat << EOF > /home/cc/.config/rclone/rclone.conf
+[rclone_s3]
+type = s3
+provider = Ceph
+endpoint = ${EC2_STORAGE_ENDPOINT}
+access_key_id = ${ACCESS_KEY}
+secret_access_key = ${SECRET_KEY}
+EOF
path: elements/cc-rclone/bin/cc-mount-object-store
user: login: msherman64
body: I think this is fine, but we can can also use the env vars directly if desired:
https://rclone.org/docs/#config-file

e.g. 
```
$ export RCLONE_CONFIG_MYS3_TYPE=s3
$ export RCLONE_CONFIG_MYS3_ACCESS_KEY_ID=XXX
$ export RCLONE_CONFIG_MYS3_SECRET_ACCESS_KEY=XXX
$ rclone lsd mys3:
          -1 2016-09-21 12:54:21        -1 my-bucket
$ rclone listremotes | grep mys3
mys3:
```
created_at: 2025-03-24T20:31:35Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,65 @@
+#!/bin/bash
+
+exit_failure() {
+  echo "$(date '+%Y-%m-%d %H:%M:%S'): Failed to create object store mount!" >> my_mounting_point.failure
+}
+
+trap 'exit_failure' EXIT
+
+set -e
+
+if [ ! -f /home/cc/openrc ]; then
+  OPENRC=$(cc-read-vendordata "openrc")
+  if [ "${OPENRC}" != "null" ]; then
+    cc-read-vendordata "openrc" >  /home/cc/openrc
+    sed -i 's/^ *//g' /home/cc/openrc
+  else
+    echo "$(date '+%Y-%m-%d %H:%M:%S'): Unable to read OPENRC" >> /home/cc/my_mounting_point.failure
+    exit 1
+  fi
+fi
+
+source /home/cc/openrc
+if [ -z "${OS_STORAGE_URL}" ]; then
+  echo "$(date '+%Y-%m-%d %H:%M:%S'): OS_STORAGE_URL was not set" >> /home/cc/my_mounting_point.failure
+  REGION=$(cc-read-vendordata "region")
+  if [ "${REGION}" = "KVM@TACC" ]; then
+    echo "$(date '+%Y-%m-%d %H:%M:%S'): KVM@TACC does not have an object store available" >> /home/cc/my_mounting_point.failure
+  fi
+  exit 1
+fi
+
+mkdir /home/cc/my_mounting_point
+touch /home/cc/my_mounting_point/THIS_IS_NOT_MOUNTED
+mkdir -p /home/cc/.config/rclone/
+
+EC2_STORAGE_ENDPOINT=${OS_STORAGE_URL%/swift*}
+EC2_CREDS="$(openstack ec2 credential create -f json)"
path: elements/cc-rclone/bin/cc-mount-object-store
user: login: msherman64
body: Actually, I think I might have been imagining the "mount a container named after your username" behavior, pretty sure what cloudfuse did was mount the "root" path, same as you're doing

my main concern is in classroom cases, having 200 students deleting each others files  with an rm -rf

If they've gotta run it from the commandline manually anyway, having to specify a bucket name seems sane to me
created_at: 2025-03-24T20:53:27Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,65 @@
+#!/bin/bash
+
+exit_failure() {
+  echo "$(date '+%Y-%m-%d %H:%M:%S'): Failed to create object store mount!" >> my_mounting_point.failure
+}
+
+trap 'exit_failure' EXIT
+
+set -e
+
+if [ ! -f /home/cc/openrc ]; then
+  OPENRC=$(cc-read-vendordata "openrc")
+  if [ "${OPENRC}" != "null" ]; then
+    cc-read-vendordata "openrc" >  /home/cc/openrc
+    sed -i 's/^ *//g' /home/cc/openrc
+  else
+    echo "$(date '+%Y-%m-%d %H:%M:%S'): Unable to read OPENRC" >> /home/cc/my_mounting_point.failure
+    exit 1
+  fi
+fi
+
+source /home/cc/openrc
+if [ -z "${OS_STORAGE_URL}" ]; then
+  echo "$(date '+%Y-%m-%d %H:%M:%S'): OS_STORAGE_URL was not set" >> /home/cc/my_mounting_point.failure
+  REGION=$(cc-read-vendordata "region")
+  if [ "${REGION}" = "KVM@TACC" ]; then
+    echo "$(date '+%Y-%m-%d %H:%M:%S'): KVM@TACC does not have an object store available" >> /home/cc/my_mounting_point.failure
+  fi
+  exit 1
+fi
+
+mkdir /home/cc/my_mounting_point
+touch /home/cc/my_mounting_point/THIS_IS_NOT_MOUNTED
+mkdir -p /home/cc/.config/rclone/
+
+EC2_STORAGE_ENDPOINT=${OS_STORAGE_URL%/swift*}
+EC2_CREDS="$(openstack ec2 credential create -f json)"
path: elements/cc-rclone/bin/cc-mount-object-store
user: login: msherman64
body: For automation (later) , something leveraging systemd mount units could work nicely, since it keeps the user from having to worry about their process dying, or racing the network on startup
https://rclone.org/commands/rclone_mount/#systemd
created_at: 2025-03-24T20:57:22Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,9 @@
+---
+# we install rclone via the package manager
+# to get all the dependences, however, we will
+# upgrade it directly from rclone's site to get
+# latest version
+rclone:
path: elements/cc-rclone/package-installs.yaml
user: login: msherman64
body: What dependencies do we miss if we just fetch a tarball from rclone's github releases?
I'm concerned that mixing repo install and script-based install could cause issues, but rclone does provide deb and rpm packages in their releases.
created_at: 2025-03-25T16:01:41Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,10 @@
+#!/bin/bash
+
+if [ "${DIB_DEBUG_TRACE:-0}" -gt 0 ]; then
+    set -x
+fi
+set -eu
+set -o pipefail
+
+# upgrade rclone
+curl https://rclone.org/install.sh | sudo bash
path: elements/cc-rclone/install.d/05-cc-rclone
user: login: msherman64
body: maybe instead of this, we could do something explicitly, e.g. 

```
#!/bin/bash
RCLONE_VERSION="v1.69.1"
RCLONE_URL_BASE="https://github.com/rclone/rclone/releases/download/${RCLONE_VERSION}"
RCLONE_DEB="${RCLONE_URL_BASE}/rclone-${RCLONE_VERSION}-linux-amd64.deb"

curl -L "${RCLONE_DEB}" -o rclone.deb \
  && dpkg -i rclone.deb \
  && rm rclone.deb
```
created_at: 2025-03-25T16:04:50Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,10 @@
+#!/bin/bash
+
+if [ "${DIB_DEBUG_TRACE:-0}" -gt 0 ]; then
+    set -x
+fi
+set -eu
+set -o pipefail
+
+# upgrade rclone
+curl https://rclone.org/install.sh | sudo bash
path: elements/cc-rclone/install.d/05-cc-rclone
user: login: msherman64
body: and the version / url can be stuck into cc-rclone/environment.d for later configuration
created_at: 2025-03-25T16:05:25Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,63 @@
+#!/bin/bash
+
+exit_failure() {
+  echo "$(date '+%Y-%m-%d %H:%M:%S'): Failed to create object store mount!" >> cc_my_mounting_point.failure
+}
+
+trap 'exit_failure' EXIT
+
+set -e
+
+if [ ! -f /home/cc/openrc ]; then
+  OPENRC=$(cc-read-vendordata "openrc")
+  if [ "${OPENRC}" != "null" ]; then
+    cc-read-vendordata "openrc" >  /home/cc/openrc
+    sed -i 's/^ *//g' /home/cc/openrc
+  else
+    echo "$(date '+%Y-%m-%d %H:%M:%S'): Unable to read OPENRC" >> /home/cc/cc_my_mounting_point.failure
+    exit 1
+  fi
+fi
+
+source /home/cc/openrc
+if [ -z "${OS_STORAGE_URL}" ]; then
+  echo "$(date '+%Y-%m-%d %H:%M:%S'): OS_STORAGE_URL was not set" >> /home/cc/cc_my_mounting_point.failure
+  REGION=$(cc-read-vendordata "region")
+  if [ "${REGION}" = "KVM@TACC" ]; then
+    echo "$(date '+%Y-%m-%d %H:%M:%S'): KVM@TACC does not have an object store available" >> /home/cc/cc_my_mounting_point.failure
+  fi
+  exit 1
+fi
+
+EC2_STORAGE_ENDPOINT=${OS_STORAGE_URL%/swift*}
+EC2_CREDS="$(openstack ec2 credential list -f json 2>/dev/null)"
+if [ $? -eq 0 ] && [ ! -z "$output" ]; then
+  ACCESS_KEY=$(echo "$output" | jq -r '.[0].Access')
+  SECRET_KEY=$(echo "$output" | jq -r '.[0].Secret')
+else
+  EC2_CREDS="$(openstack ec2 credential create -f json 2>/dev/null)"
+  ACCESS_KEY=$(echo ${EC2_CREDS} | jq -r '.access')
+  SECRET_KEY=$(echo ${EC2_CREDS} | jq -r '.secret')
+fi
+
+if [ -z "$EC2_STORAGE_ENDPOINT" ] || [ -z "$ACCESS_KEY" ] || [ -z "$SECRET_KEY" ]; then
+  echo "$(date '+%Y-%m-%d %H:%M:%S'): EC2 vars not set" >> /home/cc/cc_my_mounting_point.failure
+  exit 1
+fi
+
+mkdir -p /home/cc/.config/rclone/
+cat << EOF > /home/cc/.config/rclone/rclone.conf
+[rclone_s3]
+type = s3
+provider = Ceph
+endpoint = ${EC2_STORAGE_ENDPOINT}
+access_key_id = ${ACCESS_KEY}
+secret_access_key = ${SECRET_KEY}
+EOF
+
+sudo mv /etc/auto_mount_readme /home/cc/README
+sudo chown -R cc:cc /home/cc/README
+
+sudo mv /etc/cc-mount-object-store /usr/local/bin/cc-mount-object-store
+sudo chown -R cc:cc /usr/local/bin/cc-mount-object-store
+sudo chmod +x /usr/local/bin/cc-mount-object-store
path: elements/cc-rclone/bin/cc-mount-object-store
user: login: msherman64
body: Rather than `sudo mv` and such here, I think we can just keep using the [install-bin element](https://github.com/openstack/diskimage-builder/tree/master/diskimage_builder/elements/install-bin) for the mount script


created_at: 2025-03-25T16:09:54Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,10 @@
+#!/bin/bash
+
+if [ "${DIB_DEBUG_TRACE:-0}" -gt 0 ]; then
+    set -x
+fi
+set -eu
+set -o pipefail
+
+# upgrade rclone
+curl https://rclone.org/install.sh | sudo bash
path: elements/cc-rclone/install.d/05-cc-rclone
user: login: pdmars
body: sure, we can do that. the advantage of the other approach was that the same recipe works for both ubuntu and centos.
created_at: 2025-03-25T16:10:28Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,10 @@
+#!/bin/bash
+
+if [ "${DIB_DEBUG_TRACE:-0}" -gt 0 ]; then
+    set -x
+fi
+set -eu
+set -o pipefail
+
+# upgrade rclone
+curl https://rclone.org/install.sh | sudo bash
path: elements/cc-rclone/install.d/05-cc-rclone
user: login: pdmars
body: do we have an example in here where we flesh out different debs and rpms like this as well as the arm packages? or is it mostly just bash and custom urls to detect the different envs and get/install the correct package?
created_at: 2025-03-25T16:12:36Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,10 @@
+#!/bin/bash
+
+if [ "${DIB_DEBUG_TRACE:-0}" -gt 0 ]; then
+    set -x
+fi
+set -eu
+set -o pipefail
+
+# upgrade rclone
+curl https://rclone.org/install.sh | sudo bash
path: elements/cc-rclone/install.d/05-cc-rclone
user: login: pdmars
body: I did it in bash for now, but if we have a better pattern for resolving cases like this, def point me at it and I'm happy to change it.
created_at: 2025-03-25T16:41:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,10 @@
+#!/bin/bash
+
+if [ "${DIB_DEBUG_TRACE:-0}" -gt 0 ]; then
+    set -x
+fi
+set -eu
+set -o pipefail
+
+# upgrade rclone
+curl https://rclone.org/install.sh | sudo bash
path: elements/cc-rclone/install.d/05-cc-rclone
user: login: msherman64
body: mostly just bash and custom URLs, rclone is nice enough to consistently format the arch and deb/rpm paths in their releases.

our cuda elements provide [some examples, using the `extra-data` stage to fetch packages](https://github.com/ChameleonCloud/CC-Images/blob/main/elements/cc-ubuntu-cuda/extra-data.d/04-download-cuda-keyring-package)
[and then installing it manually](https://github.com/ChameleonCloud/CC-Images/blob/main/elements/cc-ubuntu-cuda/pre-install.d/00-install-nvidia-keyring)

For which URL to use, the env var `ARCH` is available, so something like the following in environment.d

```
if [[ "amd64 x86_64" =~ "$ARCH" ]]; then
    RCLONE_ARCH='amd64'
elif [[ "arm64 aarch64" =~ "$ARCH" ]]; then
    RCLONE_ARCH='arm64'
else
    echo "********************"
    echo "Unknown arch '$ARCH'"
    echo "********************"
    exit 1
fi
```

and tbh the rclone packages are just the binary + readme + manpage, so we could use the zip file for both centos/ubuntu if we wanted to 

created_at: 2025-03-25T16:43:43Z
author_association: CONTRIBUTOR

PR comments:
user: login: pdmars
created_at: 2025-03-25T16:16:59Z
body: > Minor comments mostly about where files live, but:
> 
> What's the difference between: `elements/cc-rclone/static/etc/cc-mount-object-store and `elements/cc-rclone/bin/cc-mount-object-store`
> 
> is the one under /etc/ meant to replace it?

Ah, that is mostly just an artifact of replacing and then iterating how how the setup worked before, and then the (unfortunate?) fact they ended up being named the same. But the one is the setup script that runs on boot, the other is the tool that is for the user to manage the mounts. It probably shouldn't (or doesn't need to) replace the setup script that runs on boot.
author_association: CONTRIBUTOR
user: login: pdmars
created_at: 2025-03-25T16:48:15Z
body: > Looking good to me!

Ok, testing this now. May have more tweaks depending on what I messed up. I'll let you know when everything appears to work.
author_association: CONTRIBUTOR
user: login: pdmars
created_at: 2025-03-25T19:30:26Z
body: @msherman64 ok if you are good with my last couple of commits I'll squash and merge this. All my testing looks good now.
author_association: CONTRIBUTOR