mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
ca48917b4f
* added some cases for unsupported network interface and multi-nic without IP addresses * added changelog fragment * lint fixes and added option for ansible_host setting * added description about the new option * lint fix too long line * Update changelogs/fragments/2259-proxmox-multi-nic-and-unsupported.yml Co-authored-by: Felix Fontein <felix@fontein.de> * Update plugins/inventory/proxmox.py Co-authored-by: Felix Fontein <felix@fontein.de> * Update plugins/inventory/proxmox.py Co-authored-by: Felix Fontein <felix@fontein.de> * Update plugins/inventory/proxmox.py Co-authored-by: Felix Fontein <felix@fontein.de> * Added CommandDisabled * refactored to code and added a test case where an interfaces doesnt have a mac address or is invalid to reset it to 00:00:00:00:00:00 * Update tests/unit/plugins/inventory/test_proxmox.py Co-authored-by: Ajpantuso <ajpantuso@gmail.com> * Update tests/unit/plugins/inventory/test_proxmox.py Co-authored-by: Ajpantuso <ajpantuso@gmail.com> * mac-address is set to None instead of 00:00:... when not defined * changed None to empty string for mac-address Co-authored-by: Felix Fontein <felix@fontein.de> Co-authored-by: Ajpantuso <ajpantuso@gmail.com>
580 lines
21 KiB
Python
580 lines
21 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Copyright (c) 2020, Jeffrey van Pelt <jeff@vanpelt.one>
|
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
|
#
|
|
# The API responses used in these tests were recorded from PVE version 6.2.
|
|
|
|
from __future__ import (absolute_import, division, print_function)
|
|
__metaclass__ = type
|
|
|
|
import pytest
|
|
|
|
from ansible.errors import AnsibleError, AnsibleParserError
|
|
from ansible.inventory.data import InventoryData
|
|
from ansible_collections.community.general.plugins.inventory.proxmox import InventoryModule
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def inventory():
|
|
r = InventoryModule()
|
|
r.inventory = InventoryData()
|
|
return r
|
|
|
|
|
|
def test_verify_file_bad_config(inventory):
|
|
assert inventory.verify_file('foobar.proxmox.yml') is False
|
|
|
|
|
|
def get_auth():
|
|
return True
|
|
|
|
|
|
# NOTE: when updating/adding replies to this function,
|
|
# be sure to only add only the _contents_ of the 'data' dict in the API reply
|
|
def get_json(url):
|
|
if url == "https://localhost:8006/api2/json/nodes":
|
|
# _get_nodes
|
|
return [{"type": "node",
|
|
"cpu": 0.01,
|
|
"maxdisk": 500,
|
|
"mem": 500,
|
|
"node": "testnode",
|
|
"id": "node/testnode",
|
|
"maxcpu": 1,
|
|
"status": "online",
|
|
"ssl_fingerprint": "xx",
|
|
"disk": 1000,
|
|
"maxmem": 1000,
|
|
"uptime": 10000,
|
|
"level": ""}]
|
|
elif url == "https://localhost:8006/api2/json/pools":
|
|
# _get_pools
|
|
return [{"poolid": "test"}]
|
|
elif url == "https://localhost:8006/api2/json/nodes/testnode/lxc":
|
|
# _get_lxc_per_node
|
|
return [{"cpus": 1,
|
|
"name": "test-lxc",
|
|
"cpu": 0.01,
|
|
"diskwrite": 0,
|
|
"lock": "",
|
|
"maxmem": 1000,
|
|
"template": "",
|
|
"diskread": 0,
|
|
"mem": 1000,
|
|
"swap": 0,
|
|
"type": "lxc",
|
|
"maxswap": 0,
|
|
"maxdisk": "1000",
|
|
"netout": 1000,
|
|
"pid": "1000",
|
|
"netin": 1000,
|
|
"status": "running",
|
|
"vmid": "100",
|
|
"disk": "1000",
|
|
"uptime": 1000}]
|
|
elif url == "https://localhost:8006/api2/json/nodes/testnode/qemu":
|
|
# _get_qemu_per_node
|
|
return [{"name": "test-qemu",
|
|
"cpus": 1,
|
|
"mem": 1000,
|
|
"template": "",
|
|
"diskread": 0,
|
|
"cpu": 0.01,
|
|
"maxmem": 1000,
|
|
"diskwrite": 0,
|
|
"netout": 1000,
|
|
"pid": "1001",
|
|
"netin": 1000,
|
|
"maxdisk": 1000,
|
|
"vmid": "101",
|
|
"uptime": 1000,
|
|
"disk": 0,
|
|
"status": "running"},
|
|
{"name": "test-qemu-windows",
|
|
"cpus": 1,
|
|
"mem": 1000,
|
|
"template": "",
|
|
"diskread": 0,
|
|
"cpu": 0.01,
|
|
"maxmem": 1000,
|
|
"diskwrite": 0,
|
|
"netout": 1000,
|
|
"pid": "1001",
|
|
"netin": 1000,
|
|
"maxdisk": 1000,
|
|
"vmid": "102",
|
|
"uptime": 1000,
|
|
"disk": 0,
|
|
"status": "running"},
|
|
{"name": "test-qemu-multi-nic",
|
|
"cpus": 1,
|
|
"mem": 1000,
|
|
"template": "",
|
|
"diskread": 0,
|
|
"cpu": 0.01,
|
|
"maxmem": 1000,
|
|
"diskwrite": 0,
|
|
"netout": 1000,
|
|
"pid": "1001",
|
|
"netin": 1000,
|
|
"maxdisk": 1000,
|
|
"vmid": "103",
|
|
"uptime": 1000,
|
|
"disk": 0,
|
|
"status": "running"},
|
|
{"name": "test-qemu-template",
|
|
"cpus": 1,
|
|
"mem": 0,
|
|
"template": 1,
|
|
"diskread": 0,
|
|
"cpu": 0,
|
|
"maxmem": 1000,
|
|
"diskwrite": 0,
|
|
"netout": 0,
|
|
"pid": "1001",
|
|
"netin": 0,
|
|
"maxdisk": 1000,
|
|
"vmid": "9001",
|
|
"uptime": 0,
|
|
"disk": 0,
|
|
"status": "stopped"}]
|
|
elif url == "https://localhost:8006/api2/json/pools/test":
|
|
# _get_members_per_pool
|
|
return {"members": [{"uptime": 1000,
|
|
"template": 0,
|
|
"id": "qemu/101",
|
|
"mem": 1000,
|
|
"status": "running",
|
|
"cpu": 0.01,
|
|
"maxmem": 1000,
|
|
"diskwrite": 1000,
|
|
"name": "test-qemu",
|
|
"netout": 1000,
|
|
"netin": 1000,
|
|
"vmid": 101,
|
|
"node": "testnode",
|
|
"maxcpu": 1,
|
|
"type": "qemu",
|
|
"maxdisk": 1000,
|
|
"disk": 0,
|
|
"diskread": 1000}]}
|
|
elif url == "https://localhost:8006/api2/json/nodes/testnode/network":
|
|
# _get_node_ip
|
|
return [{"families": ["inet"],
|
|
"priority": 3,
|
|
"active": 1,
|
|
"cidr": "10.1.1.2/24",
|
|
"iface": "eth0",
|
|
"method": "static",
|
|
"exists": 1,
|
|
"type": "eth",
|
|
"netmask": "24",
|
|
"gateway": "10.1.1.1",
|
|
"address": "10.1.1.2",
|
|
"method6": "manual",
|
|
"autostart": 1},
|
|
{"method6": "manual",
|
|
"autostart": 1,
|
|
"type": "OVSPort",
|
|
"exists": 1,
|
|
"method": "manual",
|
|
"iface": "eth1",
|
|
"ovs_bridge": "vmbr0",
|
|
"active": 1,
|
|
"families": ["inet"],
|
|
"priority": 5,
|
|
"ovs_type": "OVSPort"},
|
|
{"type": "OVSBridge",
|
|
"method": "manual",
|
|
"iface": "vmbr0",
|
|
"families": ["inet"],
|
|
"priority": 4,
|
|
"ovs_ports": "eth1",
|
|
"ovs_type": "OVSBridge",
|
|
"method6": "manual",
|
|
"autostart": 1,
|
|
"active": 1}]
|
|
elif url == "https://localhost:8006/api2/json/nodes/testnode/lxc/100/config":
|
|
# _get_vm_config (lxc)
|
|
return {
|
|
"console": 1,
|
|
"rootfs": "local-lvm:vm-100-disk-0,size=4G",
|
|
"cmode": "tty",
|
|
"description": "A testnode",
|
|
"cores": 1,
|
|
"hostname": "test-lxc",
|
|
"arch": "amd64",
|
|
"tty": 2,
|
|
"swap": 0,
|
|
"cpulimit": "0",
|
|
"net0": "name=eth0,bridge=vmbr0,gw=10.1.1.1,hwaddr=FF:FF:FF:FF:FF:FF,ip=10.1.1.3/24,type=veth",
|
|
"ostype": "ubuntu",
|
|
"digest": "123456789abcdef0123456789abcdef01234567890",
|
|
"protection": 0,
|
|
"memory": 1000,
|
|
"onboot": 0,
|
|
"cpuunits": 1024,
|
|
"tags": "one, two, three",
|
|
}
|
|
elif url == "https://localhost:8006/api2/json/nodes/testnode/qemu/101/config":
|
|
# _get_vm_config (qemu)
|
|
return {
|
|
"tags": "one, two, three",
|
|
"cores": 1,
|
|
"ide2": "none,media=cdrom",
|
|
"memory": 1000,
|
|
"kvm": 1,
|
|
"digest": "0123456789abcdef0123456789abcdef0123456789",
|
|
"description": "A test qemu",
|
|
"sockets": 1,
|
|
"onboot": 1,
|
|
"vmgenid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
|
|
"numa": 0,
|
|
"bootdisk": "scsi0",
|
|
"cpu": "host",
|
|
"name": "test-qemu",
|
|
"ostype": "l26",
|
|
"hotplug": "network,disk,usb",
|
|
"scsi0": "local-lvm:vm-101-disk-0,size=8G",
|
|
"net0": "virtio=ff:ff:ff:ff:ff:ff,bridge=vmbr0,firewall=1",
|
|
"agent": "1,fstrim_cloned_disks=1",
|
|
"bios": "seabios",
|
|
"ide0": "local-lvm:vm-101-cloudinit,media=cdrom,size=4M",
|
|
"boot": "cdn",
|
|
"scsihw": "virtio-scsi-pci",
|
|
"smbios1": "uuid=ffffffff-ffff-ffff-ffff-ffffffffffff"
|
|
}
|
|
elif url == "https://localhost:8006/api2/json/nodes/testnode/qemu/102/config":
|
|
# _get_vm_config (qemu)
|
|
return {
|
|
"numa": 0,
|
|
"digest": "460add1531a7068d2ae62d54f67e8fb9493dece9",
|
|
"ide2": "none,media=cdrom",
|
|
"bootdisk": "sata0",
|
|
"name": "test-qemu-windows",
|
|
"balloon": 0,
|
|
"cpulimit": "4",
|
|
"agent": "1",
|
|
"cores": 6,
|
|
"sata0": "storage:vm-102-disk-0,size=100G",
|
|
"memory": 10240,
|
|
"smbios1": "uuid=127301fc-0122-48d5-8fc5-c04fa78d8146",
|
|
"scsihw": "virtio-scsi-pci",
|
|
"sockets": 1,
|
|
"ostype": "win8",
|
|
"net0": "virtio=ff:ff:ff:ff:ff:ff,bridge=vmbr0",
|
|
"onboot": 1
|
|
}
|
|
elif url == "https://localhost:8006/api2/json/nodes/testnode/qemu/103/config":
|
|
# _get_vm_config (qemu)
|
|
return {
|
|
'scsi1': 'storage:vm-103-disk-3,size=30G',
|
|
'sockets': 1,
|
|
'memory': 8192,
|
|
'ostype': 'l26',
|
|
'scsihw': 'virtio-scsi-pci',
|
|
"net0": "virtio=ff:ff:ff:ff:ff:ff,bridge=vmbr0",
|
|
"net1": "virtio=ff:ff:ff:ff:ff:ff,bridge=vmbr1",
|
|
'bootdisk': 'scsi0',
|
|
'scsi0': 'storage:vm-103-disk-0,size=10G',
|
|
'name': 'test-qemu-multi-nic',
|
|
'cores': 4,
|
|
'digest': '51b7599f869b9a3f564804a0aed290f3de803292',
|
|
'smbios1': 'uuid=863b31c3-42ca-4a92-aed7-4111f342f70a',
|
|
'agent': '1,type=virtio',
|
|
'ide2': 'none,media=cdrom',
|
|
'balloon': 0,
|
|
'numa': 0,
|
|
'scsi2': 'storage:vm-103-disk-2,size=10G',
|
|
'serial0': 'socket',
|
|
'vmgenid': 'ddfb79b2-b484-4d66-88e7-6e76f2d1be77',
|
|
'onboot': 1,
|
|
'tablet': 0
|
|
}
|
|
|
|
elif url == "https://localhost:8006/api2/json/nodes/testnode/qemu/101/agent/network-get-interfaces":
|
|
# _get_agent_network_interfaces
|
|
return {"result": [
|
|
{
|
|
"hardware-address": "00:00:00:00:00:00",
|
|
"ip-addresses": [
|
|
{
|
|
"prefix": 8,
|
|
"ip-address-type": "ipv4",
|
|
"ip-address": "127.0.0.1"
|
|
},
|
|
{
|
|
"ip-address-type": "ipv6",
|
|
"ip-address": "::1",
|
|
"prefix": 128
|
|
}],
|
|
"statistics": {
|
|
"rx-errs": 0,
|
|
"rx-bytes": 163244,
|
|
"rx-packets": 1623,
|
|
"rx-dropped": 0,
|
|
"tx-dropped": 0,
|
|
"tx-packets": 1623,
|
|
"tx-bytes": 163244,
|
|
"tx-errs": 0},
|
|
"name": "lo"},
|
|
{
|
|
"statistics": {
|
|
"rx-packets": 4025,
|
|
"rx-dropped": 12,
|
|
"rx-bytes": 324105,
|
|
"rx-errs": 0,
|
|
"tx-errs": 0,
|
|
"tx-bytes": 368860,
|
|
"tx-packets": 3479,
|
|
"tx-dropped": 0},
|
|
"name": "eth0",
|
|
"ip-addresses": [
|
|
{
|
|
"prefix": 24,
|
|
"ip-address-type": "ipv4",
|
|
"ip-address": "10.1.2.3"
|
|
},
|
|
{
|
|
"prefix": 64,
|
|
"ip-address": "fd8c:4687:e88d:1be3:5b70:7b88:c79c:293",
|
|
"ip-address-type": "ipv6"
|
|
}],
|
|
"hardware-address": "ff:ff:ff:ff:ff:ff"
|
|
},
|
|
{
|
|
"hardware-address": "ff:ff:ff:ff:ff:ff",
|
|
"ip-addresses": [
|
|
{
|
|
"prefix": 16,
|
|
"ip-address": "10.10.2.3",
|
|
"ip-address-type": "ipv4"
|
|
}],
|
|
"name": "docker0",
|
|
"statistics": {
|
|
"rx-bytes": 0,
|
|
"rx-errs": 0,
|
|
"rx-dropped": 0,
|
|
"rx-packets": 0,
|
|
"tx-packets": 0,
|
|
"tx-dropped": 0,
|
|
"tx-errs": 0,
|
|
"tx-bytes": 0
|
|
}}]}
|
|
elif url == "https://localhost:8006/api2/json/nodes/testnode/qemu/102/agent/network-get-interfaces":
|
|
# _get_agent_network_interfaces
|
|
return {"result": {'error': {'desc': 'this feature or command is not currently supported', 'class': 'Unsupported'}}}
|
|
elif url == "https://localhost:8006/api2/json/nodes/testnode/qemu/103/agent/network-get-interfaces":
|
|
# _get_agent_network_interfaces
|
|
return {
|
|
"result": [
|
|
{
|
|
"statistics": {
|
|
"tx-errs": 0,
|
|
"rx-errs": 0,
|
|
"rx-dropped": 0,
|
|
"tx-bytes": 48132932372,
|
|
"tx-dropped": 0,
|
|
"rx-bytes": 48132932372,
|
|
"tx-packets": 178578980,
|
|
"rx-packets": 178578980
|
|
},
|
|
"hardware-address": "ff:ff:ff:ff:ff:ff",
|
|
"ip-addresses": [
|
|
{
|
|
"ip-address-type": "ipv4",
|
|
"prefix": 8,
|
|
"ip-address": "127.0.0.1"
|
|
}
|
|
],
|
|
"name": "lo"
|
|
},
|
|
{
|
|
"name": "eth0",
|
|
"ip-addresses": [
|
|
{
|
|
"ip-address-type": "ipv4",
|
|
"prefix": 24,
|
|
"ip-address": "172.16.0.143"
|
|
}
|
|
],
|
|
"statistics": {
|
|
"rx-errs": 0,
|
|
"tx-errs": 0,
|
|
"rx-packets": 660028,
|
|
"tx-packets": 304599,
|
|
"tx-dropped": 0,
|
|
"rx-bytes": 1846743499,
|
|
"tx-bytes": 1287844926,
|
|
"rx-dropped": 0
|
|
},
|
|
"hardware-address": "ff:ff:ff:ff:ff:ff"
|
|
},
|
|
{
|
|
"name": "eth1",
|
|
"hardware-address": "ff:ff:ff:ff:ff:ff",
|
|
"statistics": {
|
|
"rx-bytes": 235717091946,
|
|
"tx-dropped": 0,
|
|
"rx-dropped": 0,
|
|
"tx-bytes": 123411636251,
|
|
"rx-packets": 540431277,
|
|
"tx-packets": 468411864,
|
|
"rx-errs": 0,
|
|
"tx-errs": 0
|
|
},
|
|
"ip-addresses": [
|
|
{
|
|
"ip-address": "10.0.0.133",
|
|
"prefix": 24,
|
|
"ip-address-type": "ipv4"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"name": "docker0",
|
|
"ip-addresses": [
|
|
{
|
|
"ip-address": "172.17.0.1",
|
|
"prefix": 16,
|
|
"ip-address-type": "ipv4"
|
|
}
|
|
],
|
|
"hardware-address": "ff:ff:ff:ff:ff:ff",
|
|
"statistics": {
|
|
"rx-errs": 0,
|
|
"tx-errs": 0,
|
|
"rx-packets": 0,
|
|
"tx-packets": 0,
|
|
"tx-dropped": 0,
|
|
"rx-bytes": 0,
|
|
"rx-dropped": 0,
|
|
"tx-bytes": 0
|
|
}
|
|
},
|
|
{
|
|
"hardware-address": "ff:ff:ff:ff:ff:ff",
|
|
"name": "datapath"
|
|
},
|
|
{
|
|
"name": "weave",
|
|
"ip-addresses": [
|
|
{
|
|
"ip-address": "10.42.0.1",
|
|
"ip-address-type": "ipv4",
|
|
"prefix": 16
|
|
}
|
|
],
|
|
"hardware-address": "ff:ff:ff:ff:ff:ff",
|
|
"statistics": {
|
|
"rx-bytes": 127289123306,
|
|
"tx-dropped": 0,
|
|
"rx-dropped": 0,
|
|
"tx-bytes": 43827573343,
|
|
"rx-packets": 132750542,
|
|
"tx-packets": 74218762,
|
|
"rx-errs": 0,
|
|
"tx-errs": 0
|
|
}
|
|
},
|
|
{
|
|
"name": "vethwe-datapath",
|
|
"hardware-address": "ff:ff:ff:ff:ff:ff"
|
|
},
|
|
{
|
|
"name": "vethwe-bridge",
|
|
"hardware-address": "ff:ff:ff:ff:ff:ff"
|
|
},
|
|
{
|
|
"hardware-address": "ff:ff:ff:ff:ff:ff",
|
|
"name": "vxlan-6784"
|
|
},
|
|
{
|
|
"name": "vethwepl0dfe1fe",
|
|
"hardware-address": "ff:ff:ff:ff:ff:ff"
|
|
},
|
|
{
|
|
"name": "vethweplf1e7715",
|
|
"hardware-address": "ff:ff:ff:ff:ff:ff"
|
|
},
|
|
{
|
|
"hardware-address": "ff:ff:ff:ff:ff:ff",
|
|
"name": "vethwepl9d244a1"
|
|
},
|
|
{
|
|
"hardware-address": "ff:ff:ff:ff:ff:ff",
|
|
"name": "vethwepl2ca477b"
|
|
},
|
|
{
|
|
"name": "nomacorip",
|
|
}
|
|
]
|
|
}
|
|
|
|
|
|
def get_vm_status(node, vmtype, vmid, name):
|
|
return True
|
|
|
|
|
|
def get_option(option):
|
|
if option == 'group_prefix':
|
|
return 'proxmox_'
|
|
if option == 'facts_prefix':
|
|
return 'proxmox_'
|
|
elif option == 'want_facts':
|
|
return True
|
|
elif option == 'want_proxmox_nodes_ansible_host':
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
|
|
def test_populate(inventory, mocker):
|
|
# module settings
|
|
inventory.proxmox_user = 'root@pam'
|
|
inventory.proxmox_password = 'password'
|
|
inventory.proxmox_url = 'https://localhost:8006'
|
|
|
|
# bypass authentication and API fetch calls
|
|
inventory._get_auth = mocker.MagicMock(side_effect=get_auth)
|
|
inventory._get_json = mocker.MagicMock(side_effect=get_json)
|
|
inventory._get_vm_status = mocker.MagicMock(side_effect=get_vm_status)
|
|
inventory.get_option = mocker.MagicMock(side_effect=get_option)
|
|
inventory._populate()
|
|
|
|
# get different hosts
|
|
host_qemu = inventory.inventory.get_host('test-qemu')
|
|
host_qemu_windows = inventory.inventory.get_host('test-qemu-windows')
|
|
host_qemu_multi_nic = inventory.inventory.get_host('test-qemu-multi-nic')
|
|
host_qemu_template = inventory.inventory.get_host('test-qemu-template')
|
|
host_lxc = inventory.inventory.get_host('test-lxc')
|
|
host_node = inventory.inventory.get_host('testnode')
|
|
|
|
# check if qemu-test is in the proxmox_pool_test group
|
|
assert 'proxmox_pool_test' in inventory.inventory.groups
|
|
group_qemu = inventory.inventory.groups['proxmox_pool_test']
|
|
assert group_qemu.hosts == [host_qemu]
|
|
|
|
# check if qemu-test has eth0 interface in agent_interfaces fact
|
|
assert 'eth0' in [d['name'] for d in host_qemu.get_vars()['proxmox_agent_interfaces']]
|
|
|
|
# check if qemu-multi-nic has multiple network interfaces
|
|
for iface_name in ['eth0', 'eth1', 'weave']:
|
|
assert iface_name in [d['name'] for d in host_qemu_multi_nic.get_vars()['proxmox_agent_interfaces']]
|
|
|
|
# check if interface with no mac-address or ip-address defaults correctly
|
|
assert [iface for iface in host_qemu_multi_nic.get_vars()['proxmox_agent_interfaces']
|
|
if iface['name'] == 'nomacorip'
|
|
and iface['mac-address'] == ''
|
|
and iface['ip-addresses'] == []
|
|
]
|
|
|
|
# check to make sure qemu-windows doesn't have proxmox_agent_interfaces
|
|
assert "proxmox_agent_interfaces" not in host_qemu_windows.get_vars()
|
|
|
|
# check if lxc-test has been discovered correctly
|
|
group_lxc = inventory.inventory.groups['proxmox_all_lxc']
|
|
assert group_lxc.hosts == [host_lxc]
|
|
|
|
# check if qemu template is not present
|
|
assert host_qemu_template is None
|