Skip to content

Commit 9de6013

Browse files
authored
Enhance virt_install and virt_cloud_instance to support primary value attribute (ansible-collections#225)
- Added support for a special attribute `_value` and `value` to specify a primary value in the command line options. - Updated the `_dict2options` function to prioritize `_value` over `value` and handle its formatting correctly. - Reverted networks.source_opts parameter because it can be simplified by primary value attribute - Added an example usage of PCI passthrough for a network device in the module documentation.
1 parent 49adb55 commit 9de6013

File tree

6 files changed

+358
-156
lines changed

6 files changed

+358
-156
lines changed

changelogs/fragments/221-networks-source-opts.yaml

Lines changed: 0 additions & 5 deletions
This file was deleted.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
minor_changes:
2+
- virt_install - added support for primary value attribute (_value or value) in dynamic dict options that require a primary value alongside additional attributes.
3+
- virt_cloud_instance - added support for primary value attribute (_value or value) in dynamic dict options that require a primary value alongside additional attributes.

plugins/doc_fragments/virt_install.py

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1301,19 +1301,12 @@ class ModuleDocFragment(object):
13011301
- Specify the interface ROM BIOS configuration
13021302
- The dictionary contains key/value pairs that define individual properties.
13031303
source:
1304-
type: raw
1305-
description:
1306-
- Specify the source host interface.
1307-
- Can be either a string of IFACE name or a dictionary with detailed configuration.
1308-
- When provided as a string, use I(source_opts) to specify additional source properties.
1309-
- "Example as string: V(bond0)"
1310-
- "Example with source_opts: I(source=bond0) and I(source_opts={mode: bridge})"
1311-
source_opts:
13121304
type: dict
13131305
description:
1314-
- Additional options for the direct attached macvtap interface.
1306+
- Specify the details of the direct attached macvtap interface.
13151307
- The dictionary contains key/value pairs that define individual properties.
1316-
version_added: '2.1.0'
1308+
- "You can use the special attribute I(value) to specify a primary value that appears before other properties in the command line."
1309+
- "Example: I(source={value: bond0, mode: bridge})"
13171310
target:
13181311
type: dict
13191312
description:
@@ -1391,6 +1384,7 @@ class ModuleDocFragment(object):
13911384
- Attach a controller device to the guest.
13921385
- The dictionary contains key/value pairs that define individual controller properties.
13931386
- Examples include I(type=usb,model=none) to disable USB, or I(type=scsi,model=virtio-scsi) for VirtIO SCSI.
1387+
- "You can use the special attribute I(value) to specify a primary value that appears before other properties in the command line."
13941388
controller_devices:
13951389
type: list
13961390
elements: dict
@@ -1406,6 +1400,7 @@ class ModuleDocFragment(object):
14061400
- Attach an input device to the guest.
14071401
- Input device types include mouse, tablet, or keyboard.
14081402
- The dictionary contains key/value pairs that define individual input device properties.
1403+
- "You can use the special attribute I(value) to specify a primary value that appears before other properties in the command line."
14091404
input_devices:
14101405
type: list
14111406
elements: dict
@@ -1420,6 +1415,7 @@ class ModuleDocFragment(object):
14201415
description:
14211416
- Attach a physical host device to the guest.
14221417
- The dictionary contains key/value pairs that define individual host device properties.
1418+
- "You can use the special attribute I(value) to specify a primary value that appears before other properties in the command line."
14231419
host_devices:
14241420
type: list
14251421
elements: dict
@@ -1435,6 +1431,7 @@ class ModuleDocFragment(object):
14351431
- Attach a virtual audio device to the guest.
14361432
- The dictionary contains key/value pairs that define individual sound device properties.
14371433
- Common properties include I(model) (e.g. V(ich6), V(ich9), V(ac97)).
1434+
- "You can use the special attribute I(value) to specify a primary value that appears before other properties in the command line."
14381435
sound_devices:
14391436
type: list
14401437
elements: dict
@@ -1449,6 +1446,7 @@ class ModuleDocFragment(object):
14491446
description:
14501447
- Configure host audio output for the guest's sound hardware.
14511448
- The dictionary contains key/value pairs that define individual audio backend properties.
1449+
- "You can use the special attribute I(value) to specify a primary value that appears before other properties in the command line."
14521450
audio_devices:
14531451
type: list
14541452
elements: dict
@@ -1463,6 +1461,7 @@ class ModuleDocFragment(object):
14631461
description:
14641462
- Attach a virtual hardware watchdog device to the guest.
14651463
- The dictionary contains key/value pairs that define individual watchdog properties.
1464+
- "You can use the special attribute I(value) to specify a primary value that appears before other properties in the command line."
14661465
watchdog_devices:
14671466
type: list
14681467
elements: dict
@@ -1477,6 +1476,7 @@ class ModuleDocFragment(object):
14771476
description:
14781477
- Attach a serial device to the guest with various redirection options.
14791478
- The dictionary contains key/value pairs that define individual serial device properties.
1479+
- "You can use the special attribute I(value) to specify a primary value that appears before other properties in the command line."
14801480
serial_devices:
14811481
type: list
14821482
elements: dict
@@ -1491,6 +1491,7 @@ class ModuleDocFragment(object):
14911491
description:
14921492
- Attach a parallel device to the guest.
14931493
- The dictionary contains key/value pairs that define individual parallel device properties.
1494+
- "You can use the special attribute I(value) to specify a primary value that appears before other properties in the command line."
14941495
parallel_devices:
14951496
type: list
14961497
elements: dict
@@ -1505,6 +1506,7 @@ class ModuleDocFragment(object):
15051506
description:
15061507
- Attach a communication channel device to connect the guest and host machine.
15071508
- The dictionary contains key/value pairs that define individual channel properties.
1509+
- "You can use the special attribute I(value) to specify a primary value that appears before other properties in the command line."
15081510
channel_devices:
15091511
type: list
15101512
elements: dict
@@ -1520,6 +1522,7 @@ class ModuleDocFragment(object):
15201522
- Connect a text console between the guest and host.
15211523
- The dictionary contains key/value pairs that define individual console properties.
15221524
- Common properties include I(type) and I(target) for different console types.
1525+
- "You can use the special attribute I(value) to specify a primary value that appears before other properties in the command line."
15231526
console_devices:
15241527
type: list
15251528
elements: dict
@@ -1534,6 +1537,7 @@ class ModuleDocFragment(object):
15341537
description:
15351538
- Specify what video device model will be attached to the guest.
15361539
- The dictionary contains key/value pairs that define individual video device properties.
1540+
- "You can use the special attribute I(value) to specify a primary value that appears before other properties in the command line."
15371541
video_devices:
15381542
type: list
15391543
elements: dict
@@ -1548,6 +1552,7 @@ class ModuleDocFragment(object):
15481552
description:
15491553
- Configure a virtual smartcard device.
15501554
- The dictionary contains key/value pairs that define individual smartcard properties.
1555+
- "You can use the special attribute I(value) to specify a primary value that appears before other properties in the command line."
15511556
smartcard_devices:
15521557
type: list
15531558
elements: dict
@@ -1563,6 +1568,7 @@ class ModuleDocFragment(object):
15631568
- Add a redirected device for USB or other device redirection.
15641569
- The dictionary contains key/value pairs that define individual redirection properties.
15651570
- Common properties include I(bus=usb), I(type=tcp) or I(type=spicevmc).
1571+
- "You can use the special attribute I(value) to specify a primary value that appears before other properties in the command line."
15661572
redirected_devices:
15671573
type: list
15681574
elements: dict
@@ -1578,6 +1584,7 @@ class ModuleDocFragment(object):
15781584
- Attach a virtual memory balloon device to the guest.
15791585
- The dictionary contains key/value pairs that define individual memory balloon properties.
15801586
- Common properties include I(model) (e.g. V(virtio), V(xen)).
1587+
- "You can use the special attribute I(value) to specify a primary value that appears before other properties in the command line."
15811588
memballoon_devices:
15821589
type: list
15831590
elements: dict
@@ -1592,6 +1599,7 @@ class ModuleDocFragment(object):
15921599
description:
15931600
- Configure a virtual TPM (Trusted Platform Module) device.
15941601
- The dictionary contains key/value pairs that define individual TPM properties.
1602+
- "You can use the special attribute I(value) to specify a primary value that appears before other properties in the command line."
15951603
tpm_devices:
15961604
type: list
15971605
elements: dict
@@ -1606,6 +1614,7 @@ class ModuleDocFragment(object):
16061614
description:
16071615
- Configure a virtual random number generator (RNG) device.
16081616
- The dictionary contains key/value pairs that define individual RNG properties.
1617+
- "You can use the special attribute I(value) to specify a primary value that appears before other properties in the command line."
16091618
rng_devices:
16101619
type: list
16111620
elements: dict
@@ -1620,6 +1629,7 @@ class ModuleDocFragment(object):
16201629
description:
16211630
- Attach a panic notifier device to the guest.
16221631
- The dictionary contains key/value pairs that define individual panic device properties.
1632+
- "You can use the special attribute I(value) to specify a primary value that appears before other properties in the command line."
16231633
panic_devices:
16241634
type: list
16251635
elements: dict
@@ -1634,6 +1644,7 @@ class ModuleDocFragment(object):
16341644
description:
16351645
- Attach a shared memory device to the guest.
16361646
- The dictionary contains key/value pairs that define individual shared memory properties.
1647+
- "You can use the special attribute I(value) to specify a primary value that appears before other properties in the command line."
16371648
shmem_devices:
16381649
type: list
16391650
elements: dict
@@ -1648,6 +1659,7 @@ class ModuleDocFragment(object):
16481659
description:
16491660
- Configure a vsock host/guest interface.
16501661
- The dictionary contains key/value pairs that define individual vsock properties.
1662+
- "You can use the special attribute I(value) to specify a primary value that appears before other properties in the command line."
16511663
vsock_devices:
16521664
type: list
16531665
elements: dict
@@ -1662,6 +1674,7 @@ class ModuleDocFragment(object):
16621674
description:
16631675
- Add an IOMMU device to the guest.
16641676
- The dictionary contains key/value pairs that define individual IOMMU properties.
1677+
- "You can use the special attribute I(value) to specify a primary value that appears before other properties in the command line."
16651678
iommu_devices:
16661679
type: list
16671680
elements: dict

plugins/module_utils/virt_install.py

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,25 @@ def _dict2options(obj, mapping, prefix=""):
7373
if not isinstance(obj, dict):
7474
return str(obj)
7575

76+
# Extract primary value if present
77+
# Priority: _value takes precedence over value
78+
primary_value = None
79+
primary_key = None
80+
81+
if '_value' in obj:
82+
primary_value = obj['_value']
83+
primary_key = '_value'
84+
elif 'value' in obj:
85+
primary_value = obj['value']
86+
primary_key = 'value'
87+
88+
# Create a copy of the dict without the primary key for processing
89+
obj_copy = obj.copy()
90+
if primary_key:
91+
del obj_copy[primary_key]
92+
7693
parts = []
77-
for k, v in obj.items():
94+
for k, v in obj_copy.items():
7895
if v is None:
7996
continue
8097

@@ -122,7 +139,24 @@ def _dict2options(obj, mapping, prefix=""):
122139
else:
123140
parts.append("{}{}={}".format(prefix, name, str(v)))
124141

125-
if parts:
142+
# Combine primary value with other parts
143+
if primary_value is not None:
144+
primary_str = str(primary_value)
145+
146+
# If we have a prefix, the primary value should be associated with it
147+
# Remove trailing dot from prefix for the primary value assignment
148+
if prefix:
149+
prefix_without_dot = prefix.rstrip('.')
150+
primary_part = "{}={}".format(prefix_without_dot, primary_str)
151+
else:
152+
# At root level, primary value stands alone
153+
primary_part = primary_str
154+
155+
if parts:
156+
return "{},{}".format(primary_part, ",".join(parts))
157+
else:
158+
return primary_part
159+
elif parts:
126160
return ",".join(parts)
127161
else:
128162
return ""
@@ -524,7 +558,6 @@ def _build_network_options(self):
524558
network_mapping = {
525559
'trust_guest_rx_filters': ('trustGuestRxFilters', None),
526560
'state': ('link.state', None),
527-
'source_opts': ('source', None),
528561
}
529562
for network in network_param:
530563
self._add_parameter('--network',
@@ -776,19 +809,6 @@ def _validate_params(self):
776809
msg="cloud_init.{} must be a string or dictionary, got {}".format(
777810
param_name, type(param_value).__name__))
778811

779-
if self.params.get('networks') is not None:
780-
for idx, network in enumerate(self.params['networks']):
781-
if network.get('source') is not None:
782-
source_value = network['source']
783-
if not isinstance(source_value, (str, dict)):
784-
self.module.fail_json(
785-
msg="networks[{}].source must be a string or dictionary, got {}".format(
786-
idx, type(source_value).__name__))
787-
788-
if isinstance(source_value, dict) and network.get('source_opts') is not None:
789-
self.module.fail_json(
790-
msg="networks[{}].source and networks[{}].source_opts cannot both be dictionaries.")
791-
792812
def _build_command(self):
793813
"""Build the complete virt-install command"""
794814
self._validate_params()
@@ -1505,8 +1525,7 @@ def get_networks_args():
15051525
network=dict(type='str'),
15061526
bridge=dict(type='str'),
15071527
hostdev=dict(type='str'),
1508-
source=dict(type='raw'),
1509-
source_opts=dict(type='dict'),
1528+
source=dict(type='dict'),
15101529
mac=dict(type='dict', options=dict(address=dict(type='str'))),
15111530
mtu=dict(type='dict'),
15121531
state=dict(type='dict'),

plugins/modules/virt_install.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,20 @@
283283
import: true
284284
285285
286+
# VM with PCI passthrough for a network device
287+
- name: Create VM with PCI network passthrough
288+
community.libvirt.virt_install:
289+
name: passthrough-vm
290+
memory: 4096
291+
vcpus: 4
292+
disks:
293+
- size: 30
294+
osinfo:
295+
name: ubuntu20.04
296+
import: true
297+
host_devices:
298+
- value: "81:00.0"
299+
286300
# Recreate existing VM
287301
- name: Recreate existing VM with new configuration
288302
community.libvirt.virt_install:

0 commit comments

Comments
 (0)