Skip to content

Commit cc9eca5

Browse files
sp-viktoridupondje
authored andcommitted
storage: add dynamic managed storage dispatcher
Add an optional "adapter" field in the ManagedVolumeConnection struct, allowing dispatching to vendor managedvolume-helper adapters. Drop the Python 2 workaround when running the helper, also dropping the requirement for it (and thus the vendor-provided adapters) to be a Python script. Signed-off-by: Viktor Ivanov <viktor.ivanov@storpool.com>
1 parent 72844d8 commit cc9eca5

3 files changed

Lines changed: 69 additions & 5 deletions

File tree

doc/managed-volume-adapters.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<!--
2+
SPDX-FileCopyrightText: oVirt Developers
3+
SPDX-License-Identifier: GPL-2.0-or-later
4+
-->
5+
6+
# Managed Volume Adapters
7+
8+
By default the managed volumes in Vdsm are manipulated through an external
9+
helper that interfaces with the `os_brick` package (part of OpenStack).
10+
11+
Similarly on the oVirt Engine side there is another external helper that
12+
interfaces with CinderLib.
13+
14+
The two together can expose any supported Cinder storage driver to oVirt.
15+
16+
- on the oVirt Engine side the helper deals with creating and managing volumes,
17+
snapshots and preparing them to be attached to a VM;
18+
19+
- on the Vdsm side the helper deals only with attaching and detaching volumes
20+
that have been created by the oVirt Engine.
21+
22+
The adapter mechanism redirects the execution to vendor-provided helper
23+
executables. To facilitate this redirection both the oVirt Engine and Vdsm have
24+
the notion of `adapter`.
25+
26+
This allows storage vendors to integrate their managed storage directly in
27+
oVirt/Vdsm.
28+
29+
## oVirt Engine
30+
31+
Managed Storage Domains with adapter dispatch have an `adapter` field in their
32+
`driver_options` map that indicates the helper executable to run instead of
33+
the default `cinderlib-client.py` helper.
34+
35+
The vendor packaging is expected to install a symlink in the Managed Block
36+
Storage data directory (defaults to `/usr/share/ovirt-engine/managedblock/`)
37+
named `{adapter}-adapter`.
38+
39+
## Vdsm
40+
41+
The `adapter` field is passed to Vdsm in the `connection_info` parameter (of
42+
type `ManagedVolumeConnection`).
43+
44+
If the `adapter` field is not present, Vdsm uses the default OS-Brick helper
45+
`managedvolume-helper`.
46+
47+
If the `adapter` field is present, Vdsm will instead execute
48+
`managedvolume-helper-{adapter}` when attaching and detaching volumes.
49+
50+
The default install path for the helper (and where Vdsm would be looking for the
51+
adapter) is `/usr/libexec/vdsm`. Vendors should add a symlink in that directory
52+
to their own installation path.

lib/vdsm/api/vdsm-api.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1185,6 +1185,11 @@ types:
11851185
volume type.
11861186
name: data
11871187
type: *StringMap
1188+
- defaultvalue: null
1189+
description: Adapter vendor
1190+
name: adapter
1191+
type: string
1192+
added: '4.5.8'
11881193
type: object
11891194

11901195
ManagedVolumeAttachement: &ManagedVolumeAttachement

lib/vdsm/storage/managedvolume.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
import json
1818
import logging
1919
import os
20-
import sys
2120

2221
from contextlib import closing
2322

@@ -190,13 +189,21 @@ def run_helper(sub_cmd, vol_info=None):
190189
return supervdsm.getProxy().managedvolume_run_helper(
191190
sub_cmd, vol_info=vol_info)
192191
try:
192+
adapter = None
193193
cmd_input = None
194194
if vol_info:
195195
cmd_input = json.dumps(vol_info).encode("utf-8")
196-
# This is the only sane way to run python scripts that work with both
197-
# python2 and python3 in the tests.
198-
# TODO: Remove when we drop python 2.
199-
cmd = [sys.executable, HELPER, sub_cmd]
196+
adapter = vol_info.get("connection_info", {}).get("adapter")
197+
helper = HELPER
198+
if adapter:
199+
helper = f"{HELPER}-{adapter}"
200+
if not (
201+
os.path.exists(helper) and os.access(helper, os.X_OK)
202+
):
203+
raise se.ManagedVolumeHelperFailed(
204+
f"Helper for adapter '{adapter}' not found or"
205+
f" not executable at '{helper}'")
206+
cmd = [helper, sub_cmd]
200207
result = commands.run(cmd, input=cmd_input)
201208
except cmdutils.Error as e:
202209
raise se.ManagedVolumeHelperFailed("Error executing helper: %s" % e)

0 commit comments

Comments
 (0)