Skip to content
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
27 changes: 21 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,28 @@ The CSI driver needs to map OpenNebula virtual machines to Kubernetes nodes in a
try to find out the OpenNebula VM ID in the list of its arguments. If it fails, the driver will try to read the VM ID
from a file located at `/var/lib/cloud/vm-id`.

The recommended approach is to add the contents of the `contrib/one-context.sh` script to the start-up script of the
virtual machine. The script will take care of creating the `/var/lib/cloud/vm-id` file and populating its contents with
the correct VM ID.
#### VM ID Discovery

> [!NOTE]
> After adding the code from `contrib/one-context.sh` to the start-up script of a virtual machine, the virtual machine
> must be restarted for the new start-up script to be executed.
The CSI driver now automatically discovers the VM ID using an initContainer that queries the OpenNebula API. This eliminates the need for manual VM configuration scripts.

The initContainer (`one-vmid:latest`) runs before the main CSI containers and:
1. Connects to the OpenNebula API using credentials from the `sp-one` secret
2. Queries the VM pool to find the VM matching the Kubernetes node name
3. Writes the VM ID to `/var/lib/cloud/vm-id` for the main container to use

#### Required Secret

Create a secret named `sp-one` in the `kube-system` namespace with the following keys:
- `ONE_API_ENDPOINT`: The OpenNebula API endpoint URL
- `ONE_API_USERNAME`: OpenNebula API username
- `ONE_API_PASSWORD`: OpenNebula API password

```shell
kubectl create secret generic sp-one -n kube-system \
--from-literal=ONE_API_ENDPOINT=http://your-opennebula-endpoint:2633/RPC2 \
--from-literal=ONE_API_USERNAME=your-username \
--from-literal=ONE_API_PASSWORD=your-password
```

### Starting the CSI driver

Expand Down
22 changes: 19 additions & 3 deletions manifests/opennebula-csi-controllerplugin-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,21 @@ spec:
labels:
name: storpool-csi-controllerplugin
spec:
initContainers:
- image: one-vmid:latest
name: one-vmid-init
env:
- name: SP_NODE_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: spec.nodeName
envFrom:
- secretRef:
name: sp-one
volumeMounts:
- mountPath: /var/lib/cloud
name: cloud-dir
containers:
- args:
- python3
Expand All @@ -29,6 +44,9 @@ spec:
fieldPath: spec.nodeName
- name: PYTHONUNBUFFERED
value: "1"
envFrom:
- secretRef:
name: sp-one
image: cts.storpool.com/opennebula-csi/pre-release:v0.0.24
name: opennebula-csi-plugin
ports:
Expand Down Expand Up @@ -136,9 +154,7 @@ spec:
serviceAccountName: opennebula-csi-controller-sa
terminationGracePeriodSeconds: 30
volumes:
- hostPath:
path: /var/lib/cloud
type: Directory
- emptyDir: {}
name: cloud-dir
- emptyDir: {}
name: socket-dir
24 changes: 20 additions & 4 deletions manifests/opennebula-csi-nodeplugin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,21 @@ spec:
labels:
name: opennebula-csi-nodeplugin
spec:
initContainers:
- image: one-vmid:latest
name: one-vmid-init
env:
- name: SP_NODE_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: spec.nodeName
envFrom:
- secretRef:
name: sp-one
volumeMounts:
- mountPath: /var/lib/cloud
name: cloud-dir
containers:
- args:
- python3
Expand All @@ -28,6 +43,9 @@ spec:
fieldPath: spec.nodeName
- name: PYTHONUNBUFFERED
value: "1"
envFrom:
- secretRef:
name: sp-one
image: cts.storpool.com/opennebula-csi/pre-release:v0.0.24
livenessProbe:
failureThreshold: 5
Expand Down Expand Up @@ -64,7 +82,7 @@ spec:
readOnly: true
- args:
- --csi-address=/csi/csi.sock
- --kubelet-registration-path=/var/lib/kubelet/plugins/csi.storpool.com/csi.sock
- --kubelet-registration-path=/var/lib/kubelet/plugins/csi.opennebula.com/csi.sock
image: registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.8.0
imagePullPolicy: IfNotPresent
name: node-driver-registrar
Expand Down Expand Up @@ -97,9 +115,7 @@ spec:
path: /dev
type: Directory
name: dev-dir
- hostPath:
path: /var/lib/cloud
type: Directory
- emptyDir: {}
name: cloud-dir
- hostPath:
path: /var/lib/kubelet/plugins/csi.opennebula.io
Expand Down
14 changes: 14 additions & 0 deletions vmid-discover/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
FROM python:3.10-slim-bookworm

WORKDIR /app
RUN pip install pyone
ADD https://github.com/Yelp/dumb-init/releases/download/v1.2.5/dumb-init_1.2.5_x86_64 /usr/sbin/dumb-init
RUN chmod +x /usr/sbin/dumb-init

COPY vmid-discover.py .

VOLUME ["/var/lib/cloud"]

ENTRYPOINT ["/usr/sbin/dumb-init", "--"]

CMD [ "python3", "vmid-discover.py" ]
65 changes: 65 additions & 0 deletions vmid-discover/vmid-discover.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#!/usr/bin/env python3

import os
import sys
import pyone


def get_config():
"""Get configuration from environment variables."""
config = {}
required_vars = [
"SP_NODE_NAME",
"ONE_API_ENDPOINT",
"ONE_API_USERNAME",
"ONE_API_PASSWORD",
]

missing_vars = []
for var in required_vars:
value = os.environ.get(var)
if not value:
missing_vars.append(var)
else:
config[var] = value

if missing_vars:
print(
f"Error: Missing required environment variables: {', '.join(missing_vars)}",
file=sys.stderr,
)
sys.exit(1)

return config


if __name__ == "__main__":
config = get_config()

# Create API proxy
api = pyone.OneServer(
config["ONE_API_ENDPOINT"],
session=f"{config['ONE_API_USERNAME']}:{config['ONE_API_PASSWORD']}",
)

try:
for vm in api.vmpool.info(-1, -1, -1, 3).VM:
if vm.get_NAME() == config["SP_NODE_NAME"]:
vmid = vm.get_ID()
print("Found VM ID:", vmid)
with open("/var/lib/cloud/vm-id", "w") as f:
f.write(str(vmid))
# Add a newline for consistency with contrib/one-context.sh
f.write("\n")
break
else:
print(
f"Error: No VM found with name {config['SP_NODE_NAME']}",
file=sys.stderr,
)
sys.exit(1)
except pyone.OneException as e:
print(f"Error from the OpenNebula API: {e}", file=sys.stderr)
sys.exit(1)
finally:
api.server_close()