Skip to content

Commit

Permalink
kubevirt: automatically pick volume_mode/volume_access
Browse files Browse the repository at this point in the history
  • Loading branch information
karmab committed Feb 24, 2025
1 parent 85d97bd commit 875bacc
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 37 deletions.
4 changes: 2 additions & 2 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -488,8 +488,8 @@ You can use additional parameters for the Kubevirt section:
- `namespace` target namespace.
- `tags` additional list of tags in a key=value format to put to all created vms in their *nodeSelector*. Can be further indicated at profile or plan level in which case values are combined. This provides an easy way to force vms to run on specific nodes, by matching labels.
- `access_mode` Way to access vms other ssh. Defaults to NodePort,in which case a svc with a nodeport pointing to the ssh port of the vm will be created. Otherpossible values are LoadBalancer to create a svc of type loadbalancer to point to the vm or External to connect using the sdn ip of the vm. If tunnel options are set, they take precedence
- `volume_mode` Volume Mode. Defaults to Filesystem (Block can be specified instead).
- `volume_access` Volume access mode. Defaults to ReadWriteOnce.
- `volume_mode` Volume Mode. Defaults to None
- `volume_access` Volume access mode. Defaults to None
- `disk_hotplug` Whether to allow to hotplug (and unplug) disks. Defaults to false. Note it also requires to enable The HotplugVolumes featureGate within Kubevirt
- `embed_userdata` Whether to embed userdata directly in the vm spec. Defaults to false
- `registry` Specific registry where to gather karmab/curl image used when pool/sc has a volume binding mode of WaitForFirstConsumer. Defaults to quay.io
Expand Down
4 changes: 2 additions & 2 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -513,8 +513,8 @@ You can use additional parameters for the Kubevirt section:
- ``namespace`` target namespace.
- ``tags`` additional list of tags in a key=value format to put to all created vms in their *nodeSelector*. Can be further indicated at profile or plan level in which case values are combined. This provides an easy way to force vms to run on specific nodes, by matching labels.
- ``access_mode`` Way to access vms other ssh. Defaults to NodePort,in which case a svc with a nodeport pointing to the ssh port of the vm will be created. Otherpossible values are LoadBalancer to create a svc of type loadbalancer to point to the vm or External to connect using the sdn ip of the vm. If tunnel options are set, they take precedence
- ``volume_mode`` Volume Mode. Defaults to Filesystem (Block can be specified instead).
- ``volume_access`` Volume access mode. Defaults to ReadWriteOnce.
- ``volume_mode`` Volume Mode. Defaults to None
- ``volume_access`` Volume access mode. Defaults to None
- ``disk_hotplug`` Whether to allow to hotplug (and unplug) disks. Defaults to false. Note it also requires to enable The HotplugVolumes featureGate within Kubevirt
- ``embed_userdata`` Whether to embed userdata directly in the vm spec. Defaults to false
- ``registry`` Specific registry where to gather karmab/curl image used when pool/sc has a volume binding mode of WaitForFirstConsumer. Defaults to quay.io
Expand Down
12 changes: 2 additions & 10 deletions kvirt/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,16 +85,8 @@ def __init__(self, client=None, debug=False, quiet=False, region=None, zone=None
msg = f"Incorrect access_mode {access_mode}. Should be External, NodePort or LoadBalancer"
error(msg)
sys.exit(1)
volume_mode = KUBEVIRT_VOLUME_MODE or options.get('volume_mode', KUBEVIRT['volume_mode'])
if volume_mode not in ['Filesystem', 'Block']:
msg = f"Incorrect volume_mode {volume_mode}. Should be Filesystem or Block"
error(msg)
sys.exit(1)
volume_access = KUBEVIRT_VOLUME_ACCESS or options.get('volume_access', KUBEVIRT['volume_access'])
if volume_access not in ['ReadWriteMany', 'ReadWriteOnce']:
msg = f"Incorrect volume_access {volume_access}. Should be ReadWriteOnce or ReadWriteOnce"
error(msg)
sys.exit(1)
volume_mode = KUBEVIRT_VOLUME_MODE or options.get('volume_mode')
volume_access = KUBEVIRT_VOLUME_ACCESS or options.get('volume_access')
harvester = KUBEVIRT_HARVESTER or options.get('harvester', KUBEVIRT['harvester'])
embed_userdata = KUBEVIRT_EMBED_USERDATA or options.get('embed_userdata', KUBEVIRT['embed_userdata'])
registry = KUBEVIRT_REGISTRY or options.get('registry', KUBEVIRT['registry'])
Expand Down
3 changes: 1 addition & 2 deletions kvirt/defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,8 +267,7 @@
GCP = {'region': 'europe-west1'}

KUBEVIRT = {'readwritemany': False, 'disk_hotplug': False, 'access_mode': 'NodePort',
'volume_mode': 'Filesystem', 'volume_access': 'ReadWriteOnce', 'harvester': False, 'embed_userdata': False,
'registry': 'quay.io'}
'harvester': False, 'embed_userdata': False, 'registry': 'quay.io'}

OPENSTACK = {'version': '2', 'domain': 'Default', 'user': 'admin', 'project': 'admin'}

Expand Down
57 changes: 36 additions & 21 deletions kvirt/providers/kubevirt/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,11 +358,11 @@ def create(self, name, virttype=None, profile='', flavor=None, plan='kvirt', cpu
if 'name' in disk:
existingpvc = True
pool = self.check_pool(diskpool)
pool_details = self.get_sc_details(pool)
if volume_mode not in pool_details:
return {'result': 'failure', 'reason': f"Pool {pool} doesn't support volume mode {volume_mode}"}
elif volume_access not in pool_details[volume_mode]:
return {'result': 'failure', 'reason': f"Pool {pool} doesn't support volume access {volume_access}"}
volume_mode, volume_access = self.get_volume_details(pool, volume_mode, volume_access)
if volume_mode is None:
return {'result': 'failure', 'reason': "Incorrect volume_mode"}
if volume_access is None:
return {'result': 'failure', 'reason': "Incorrect volume_access"}
myvolume = {'name': diskname}
if image is not None and index == 0:
if '/' in image:
Expand Down Expand Up @@ -1106,13 +1106,11 @@ def add_disk(self, name, size, pool=None, thin=True, image=None, shareable=False
index = len(currentdisks)
diskname = f'{name}-disk{index}'
pool = self.check_pool(pool)
pool_details = self.get_sc_details(pool)
volume_mode = self.volume_mode
volume_access = self.volume_access
if volume_mode not in pool_details:
return {'result': 'failure', 'reason': f"Pool {pool} doesn't support volume mode {volume_mode}"}
elif volume_access not in pool_details[volume_mode]:
return {'result': 'failure', 'reason': f"Pool {pool} doesn't support volume access {volume_access}"}
volume_mode, volume_access = self.get_volume_details(pool, self.volume_mode, self.volume_access)
if volume_mode is None:
return {'result': 'failure', 'reason': "Incorrect volume_mode"}
if volume_access is None:
return {'result': 'failure', 'reason': "Incorrect volume_access"}
myvolume = {'name': diskname, 'persistentVolumeClaim': {'claimName': diskname}}
if self.disk_hotplug:
pprint(f"Hotplugging disk {diskname}")
Expand Down Expand Up @@ -1269,13 +1267,11 @@ def add_image(self, url, pool, short=None, cmds=[], name=None, size=None, conver
size = _base_image_size(url)
warning(f"Setting size of image to {size}G. This will be the size of primary disks using this")
pool = self.check_pool(pool)
pool_details = self.get_sc_details(pool)
volume_mode = self.volume_mode
volume_access = self.volume_access
if volume_mode not in pool_details:
return {'result': 'failure', 'reason': f"Pool {pool} doesn't support volume mode {volume_mode}"}
elif volume_access not in pool_details[volume_mode]:
return {'result': 'failure', 'reason': f"Pool {pool} doesn't support volume access {volume_access}"}
volume_mode, volume_access = self.get_volume_details(pool, self.volume_mode, self.volume_access)
if volume_mode is None:
return {'result': 'failure', 'reason': "Incorrect volume_mode"}
if volume_access is None:
return {'result': 'failure', 'reason': "Incorrect volume_access"}
namespace = self.namespace
harvester = self.harvester
shortimage = os.path.basename(url).split('?')[0]
Expand Down Expand Up @@ -1759,16 +1755,35 @@ def get_default_sc(self):
default_sc = sc['metadata']['name']
return default_sc

def get_sc_details(self, name):
def get_sc_details(self, pool):
kubectl = self.kubectl
data = {}
for entry in _get_all_resources(kubectl, 'storageprofile', debug=self.debug):
if entry['metadata']['name'] == name and 'claimPropertySets' in entry['status']:
if entry['metadata']['name'] == pool and 'claimPropertySets' in entry['status']:
for claimset in entry['status']['claimPropertySets']:
data[claimset['volumeMode']] = claimset['accessModes']
break
return data

def get_volume_details(self, pool, volume_mode, volume_access):
pool_details = self.get_sc_details(pool)
if volume_mode is None:
volume_modes = list(pool_details.keys())
if volume_modes:
volume_mode = volume_modes[0]
volume_access = pool_details[volume_mode][0]
else:
volume_mode = 'Filesystem'
volume_access = 'ReadWriteOnce'
elif volume_mode in pool_details:
if volume_access is None:
volume_access = pool_details[volume_mode][0]
elif volume_access not in pool_details[volume_mode]:
volume_access = None
elif volume_mode not in pool_details:
volume_mode = None
return volume_mode, volume_access

def update_reference(self, owners, namespace, reference):
kubectl = self.kubectl
namespace = self.namespace
Expand Down

0 comments on commit 875bacc

Please sign in to comment.