* [pve-devel] [PATCH v3 pve-container 0/1] add ipam support
@ 2021-05-24 15:19 Alexandre Derumier
2021-05-24 15:19 ` [pve-devel] [PATCH v3 pve-container 1/1] " Alexandre Derumier
0 siblings, 1 reply; 2+ messages in thread
From: Alexandre Derumier @ 2021-05-24 15:19 UTC (permalink / raw)
To: pve-devel
Changelog v2:
- refactor code
- move code from PVE::LXC::Config to PVE::LXC
- add update_net_ip tests
- fix bugs when changing from vnet ipam to vnet without ipam/ without subnets / classic vmbr
- add support for snasphot rollback
- add support for backup restore
Changelog v3:
- small fix with forgot PVE::LXC change on del_net_ip
Alexandre Derumier (1):
add ipam support
src/PVE/LXC.pm | 144 ++++++++++++++++++
src/PVE/LXC/Config.pm | 58 +++++++
src/PVE/LXC/Create.pm | 33 +++-
src/test/Makefile | 5 +-
.../ipam.db | 18 +++
.../ipam.db.expected | 17 +++
.../ipam_config | 7 +
.../net | 7 +
.../net.expected | 7 +
.../oldnet | 7 +
.../sdn_config | 35 +++++
.../ipam.db | 18 +++
.../ipam.db.expected | 18 +++
.../ipam_config | 7 +
.../net | 7 +
.../net.expected | 7 +
.../oldnet | 7 +
.../sdn_config | 35 +++++
.../ipam.db | 18 +++
.../ipam.db.expected | 17 +++
.../ipam_config | 7 +
.../net | 7 +
.../net.expected | 7 +
.../oldnet | 7 +
.../sdn_config | 35 +++++
.../ipam.db | 18 +++
.../ipam.db.expected | 18 +++
.../ipam_config | 7 +
.../net | 6 +
.../net.expected | 7 +
.../oldnet | 7 +
.../sdn_config | 35 +++++
.../ipam.db | 18 +++
.../ipam.db.expected | 18 +++
.../ipam_config | 7 +
.../net | 6 +
.../net.expected | 7 +
.../oldnet | 7 +
.../sdn_config | 35 +++++
.../ipv4_changeip_samevnet_with_ipam/ipam.db | 18 +++
.../ipam.db.expected | 18 +++
.../ipam_config | 7 +
.../ipv4_changeip_samevnet_with_ipam/net | 7 +
.../net.expected | 7 +
.../ipv4_changeip_samevnet_with_ipam/oldnet | 7 +
.../sdn_config | 35 +++++
.../ipv4_changeip_vmbr0_to_ipamvnet/ipam.db | 17 +++
.../ipam.db.expected | 18 +++
.../ipam_config | 7 +
.../ipams/ipv4_changeip_vmbr0_to_ipamvnet/net | 7 +
.../net.expected | 7 +
.../ipv4_changeip_vmbr0_to_ipamvnet/oldnet | 7 +
.../sdn_config | 35 +++++
.../ipv4_changeip_vmbr0_to_noipamvnet/ipam.db | 17 +++
.../ipam.db.expected | 17 +++
.../ipam_config | 7 +
.../ipv4_changeip_vmbr0_to_noipamvnet/net | 7 +
.../net.expected | 7 +
.../ipv4_changeip_vmbr0_to_noipamvnet/oldnet | 7 +
.../sdn_config | 35 +++++
.../ipam.db | 18 +++
.../ipam.db.expected | 18 +++
.../ipam_config | 7 +
.../net | 7 +
.../net.expected | 8 +
.../oldnet | 7 +
.../sdn_config | 38 +++++
.../ipam.db | 18 +++
.../ipam.db.expected | 17 +++
.../ipam_config | 7 +
.../net | 8 +
.../net.expected | 8 +
.../oldnet | 7 +
.../sdn_config | 38 +++++
.../ipam.db | 18 +++
.../ipam.db.expected | 18 +++
.../ipam_config | 7 +
.../net | 7 +
.../net.expected | 7 +
.../oldnet | 8 +
.../sdn_config | 36 +++++
.../ipams/ipv4_updateipam_ipamvnet/ipam.db | 18 +++
.../ipv4_updateipam_ipamvnet/ipam.db.expected | 18 +++
.../ipv4_updateipam_ipamvnet/ipam_config | 7 +
src/test/ipams/ipv4_updateipam_ipamvnet/net | 7 +
.../ipv4_updateipam_ipamvnet/net.expected | 7 +
.../ipams/ipv4_updateipam_ipamvnet/oldnet | 7 +
.../ipams/ipv4_updateipam_ipamvnet/sdn_config | 35 +++++
.../ipam.db | 19 +++
.../ipam.db.expected | 19 +++
.../ipam_config | 7 +
.../ipv4v6_next_free_samevnet_with_ipam/net | 6 +
.../net.expected | 8 +
.../oldnet | 8 +
.../sdn_config | 39 +++++
.../ipam.db | 20 +++
.../ipam.db.expected | 20 +++
.../ipam_config | 7 +
.../net | 6 +
.../net.expected | 8 +
.../oldnet | 8 +
.../sdn_config | 39 +++++
.../ipams/ipv4v6_updateipam_ipamvnet/ipam.db | 19 +++
.../ipam.db.expected | 19 +++
.../ipv4v6_updateipam_ipamvnet/ipam_config | 7 +
src/test/ipams/ipv4v6_updateipam_ipamvnet/net | 8 +
.../ipv4v6_updateipam_ipamvnet/net.expected | 8 +
.../ipams/ipv4v6_updateipam_ipamvnet/oldnet | 8 +
.../ipv4v6_updateipam_ipamvnet/sdn_config | 39 +++++
.../ipam.db | 19 +++
.../ipam.db.expected | 19 +++
.../ipam_config | 7 +
.../ipv4v6_updateipam_ipamvnet_failingv6/net | 8 +
.../net.expected | 8 +
.../oldnet | 8 +
.../sdn_config | 35 +++++
.../ipam.db | 18 +++
.../ipam.db.expected | 18 +++
.../ipam_config | 7 +
.../net | 7 +
.../net.expected | 7 +
.../oldnet | 7 +
.../sdn_config | 35 +++++
.../ipam.db | 18 +++
.../ipam.db.expected | 18 +++
.../ipam_config | 7 +
.../net | 7 +
.../net.expected | 8 +
.../oldnet | 7 +
.../sdn_config | 37 +++++
.../ipams/ipv6_updateipam_ipamvnet/ipam.db | 14 ++
.../ipv6_updateipam_ipamvnet/ipam.db.expected | 14 ++
.../ipv6_updateipam_ipamvnet/ipam_config | 7 +
src/test/ipams/ipv6_updateipam_ipamvnet/net | 7 +
.../ipv6_updateipam_ipamvnet/net.expected | 7 +
.../ipams/ipv6_updateipam_ipamvnet/oldnet | 7 +
.../ipams/ipv6_updateipam_ipamvnet/sdn_config | 35 +++++
src/test/run_ipam_tests.pl | 126 +++++++++++++++
src/test/snapshot-input/sdn/subnets.cfg | 0
src/test/snapshot-test.pm | 1 -
140 files changed, 2266 insertions(+), 10 deletions(-)
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_othervnet_noipam/ipam.db
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_othervnet_noipam/ipam.db.expected
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_othervnet_noipam/ipam_config
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_othervnet_noipam/net
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_othervnet_noipam/net.expected
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_othervnet_noipam/oldnet
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_othervnet_noipam/sdn_config
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_othervnetipam/ipam.db
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_othervnetipam/ipam.db.expected
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_othervnetipam/ipam_config
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_othervnetipam/net
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_othervnetipam/net.expected
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_othervnetipam/oldnet
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_othervnetipam/sdn_config
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_vmbr0_noipam/ipam.db
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_vmbr0_noipam/ipam.db.expected
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_vmbr0_noipam/ipam_config
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_vmbr0_noipam/net
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_vmbr0_noipam/net.expected
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_vmbr0_noipam/oldnet
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_vmbr0_noipam/sdn_config
create mode 100644 src/test/ipams/ipv4_changeip_next_free_othervnet_with_ipam/ipam.db
create mode 100644 src/test/ipams/ipv4_changeip_next_free_othervnet_with_ipam/ipam.db.expected
create mode 100644 src/test/ipams/ipv4_changeip_next_free_othervnet_with_ipam/ipam_config
create mode 100644 src/test/ipams/ipv4_changeip_next_free_othervnet_with_ipam/net
create mode 100644 src/test/ipams/ipv4_changeip_next_free_othervnet_with_ipam/net.expected
create mode 100644 src/test/ipams/ipv4_changeip_next_free_othervnet_with_ipam/oldnet
create mode 100644 src/test/ipams/ipv4_changeip_next_free_othervnet_with_ipam/sdn_config
create mode 100644 src/test/ipams/ipv4_changeip_next_free_samevnet_with_ipam/ipam.db
create mode 100644 src/test/ipams/ipv4_changeip_next_free_samevnet_with_ipam/ipam.db.expected
create mode 100644 src/test/ipams/ipv4_changeip_next_free_samevnet_with_ipam/ipam_config
create mode 100644 src/test/ipams/ipv4_changeip_next_free_samevnet_with_ipam/net
create mode 100644 src/test/ipams/ipv4_changeip_next_free_samevnet_with_ipam/net.expected
create mode 100644 src/test/ipams/ipv4_changeip_next_free_samevnet_with_ipam/oldnet
create mode 100644 src/test/ipams/ipv4_changeip_next_free_samevnet_with_ipam/sdn_config
create mode 100644 src/test/ipams/ipv4_changeip_samevnet_with_ipam/ipam.db
create mode 100644 src/test/ipams/ipv4_changeip_samevnet_with_ipam/ipam.db.expected
create mode 100644 src/test/ipams/ipv4_changeip_samevnet_with_ipam/ipam_config
create mode 100644 src/test/ipams/ipv4_changeip_samevnet_with_ipam/net
create mode 100644 src/test/ipams/ipv4_changeip_samevnet_with_ipam/net.expected
create mode 100644 src/test/ipams/ipv4_changeip_samevnet_with_ipam/oldnet
create mode 100644 src/test/ipams/ipv4_changeip_samevnet_with_ipam/sdn_config
create mode 100644 src/test/ipams/ipv4_changeip_vmbr0_to_ipamvnet/ipam.db
create mode 100644 src/test/ipams/ipv4_changeip_vmbr0_to_ipamvnet/ipam.db.expected
create mode 100644 src/test/ipams/ipv4_changeip_vmbr0_to_ipamvnet/ipam_config
create mode 100644 src/test/ipams/ipv4_changeip_vmbr0_to_ipamvnet/net
create mode 100644 src/test/ipams/ipv4_changeip_vmbr0_to_ipamvnet/net.expected
create mode 100644 src/test/ipams/ipv4_changeip_vmbr0_to_ipamvnet/oldnet
create mode 100644 src/test/ipams/ipv4_changeip_vmbr0_to_ipamvnet/sdn_config
create mode 100644 src/test/ipams/ipv4_changeip_vmbr0_to_noipamvnet/ipam.db
create mode 100644 src/test/ipams/ipv4_changeip_vmbr0_to_noipamvnet/ipam.db.expected
create mode 100644 src/test/ipams/ipv4_changeip_vmbr0_to_noipamvnet/ipam_config
create mode 100644 src/test/ipams/ipv4_changeip_vmbr0_to_noipamvnet/net
create mode 100644 src/test/ipams/ipv4_changeip_vmbr0_to_noipamvnet/net.expected
create mode 100644 src/test/ipams/ipv4_changeip_vmbr0_to_noipamvnet/oldnet
create mode 100644 src/test/ipams/ipv4_changeip_vmbr0_to_noipamvnet/sdn_config
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetipam/ipam.db
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetipam/ipam.db.expected
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetipam/ipam_config
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetipam/net
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetipam/net.expected
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetipam/oldnet
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetipam/sdn_config
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetnoipam/ipam.db
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetnoipam/ipam.db.expected
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetnoipam/ipam_config
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetnoipam/net
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetnoipam/net.expected
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetnoipam/oldnet
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetnoipam/sdn_config
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_nogateway_othervnetipam/ipam.db
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_nogateway_othervnetipam/ipam.db.expected
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_nogateway_othervnetipam/ipam_config
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_nogateway_othervnetipam/net
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_nogateway_othervnetipam/net.expected
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_nogateway_othervnetipam/oldnet
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_nogateway_othervnetipam/sdn_config
create mode 100644 src/test/ipams/ipv4_updateipam_ipamvnet/ipam.db
create mode 100644 src/test/ipams/ipv4_updateipam_ipamvnet/ipam.db.expected
create mode 100644 src/test/ipams/ipv4_updateipam_ipamvnet/ipam_config
create mode 100644 src/test/ipams/ipv4_updateipam_ipamvnet/net
create mode 100644 src/test/ipams/ipv4_updateipam_ipamvnet/net.expected
create mode 100644 src/test/ipams/ipv4_updateipam_ipamvnet/oldnet
create mode 100644 src/test/ipams/ipv4_updateipam_ipamvnet/sdn_config
create mode 100644 src/test/ipams/ipv4v6_next_free_samevnet_with_ipam/ipam.db
create mode 100644 src/test/ipams/ipv4v6_next_free_samevnet_with_ipam/ipam.db.expected
create mode 100644 src/test/ipams/ipv4v6_next_free_samevnet_with_ipam/ipam_config
create mode 100644 src/test/ipams/ipv4v6_next_free_samevnet_with_ipam/net
create mode 100644 src/test/ipams/ipv4v6_next_free_samevnet_with_ipam/net.expected
create mode 100644 src/test/ipams/ipv4v6_next_free_samevnet_with_ipam/oldnet
create mode 100644 src/test/ipams/ipv4v6_next_free_samevnet_with_ipam/sdn_config
create mode 100644 src/test/ipams/ipv4v6_next_free_samevnet_with_ipam_failingv6/ipam.db
create mode 100644 src/test/ipams/ipv4v6_next_free_samevnet_with_ipam_failingv6/ipam.db.expected
create mode 100644 src/test/ipams/ipv4v6_next_free_samevnet_with_ipam_failingv6/ipam_config
create mode 100644 src/test/ipams/ipv4v6_next_free_samevnet_with_ipam_failingv6/net
create mode 100644 src/test/ipams/ipv4v6_next_free_samevnet_with_ipam_failingv6/net.expected
create mode 100644 src/test/ipams/ipv4v6_next_free_samevnet_with_ipam_failingv6/oldnet
create mode 100644 src/test/ipams/ipv4v6_next_free_samevnet_with_ipam_failingv6/sdn_config
create mode 100644 src/test/ipams/ipv4v6_updateipam_ipamvnet/ipam.db
create mode 100644 src/test/ipams/ipv4v6_updateipam_ipamvnet/ipam.db.expected
create mode 100644 src/test/ipams/ipv4v6_updateipam_ipamvnet/ipam_config
create mode 100644 src/test/ipams/ipv4v6_updateipam_ipamvnet/net
create mode 100644 src/test/ipams/ipv4v6_updateipam_ipamvnet/net.expected
create mode 100644 src/test/ipams/ipv4v6_updateipam_ipamvnet/oldnet
create mode 100644 src/test/ipams/ipv4v6_updateipam_ipamvnet/sdn_config
create mode 100644 src/test/ipams/ipv4v6_updateipam_ipamvnet_failingv6/ipam.db
create mode 100644 src/test/ipams/ipv4v6_updateipam_ipamvnet_failingv6/ipam.db.expected
create mode 100644 src/test/ipams/ipv4v6_updateipam_ipamvnet_failingv6/ipam_config
create mode 100644 src/test/ipams/ipv4v6_updateipam_ipamvnet_failingv6/net
create mode 100644 src/test/ipams/ipv4v6_updateipam_ipamvnet_failingv6/net.expected
create mode 100644 src/test/ipams/ipv4v6_updateipam_ipamvnet_failingv6/oldnet
create mode 100644 src/test/ipams/ipv4v6_updateipam_ipamvnet_failingv6/sdn_config
create mode 100644 src/test/ipams/ipv6_changeip_ipamvnet_to_othervnetipam/ipam.db
create mode 100644 src/test/ipams/ipv6_changeip_ipamvnet_to_othervnetipam/ipam.db.expected
create mode 100644 src/test/ipams/ipv6_changeip_ipamvnet_to_othervnetipam/ipam_config
create mode 100644 src/test/ipams/ipv6_changeip_ipamvnet_to_othervnetipam/net
create mode 100644 src/test/ipams/ipv6_changeip_ipamvnet_to_othervnetipam/net.expected
create mode 100644 src/test/ipams/ipv6_changeip_ipamvnet_to_othervnetipam/oldnet
create mode 100644 src/test/ipams/ipv6_changeip_ipamvnet_to_othervnetipam/sdn_config
create mode 100644 src/test/ipams/ipv6_gateway_changeip_ipamvnet_to_gateway_othervnetipam/ipam.db
create mode 100644 src/test/ipams/ipv6_gateway_changeip_ipamvnet_to_gateway_othervnetipam/ipam.db.expected
create mode 100644 src/test/ipams/ipv6_gateway_changeip_ipamvnet_to_gateway_othervnetipam/ipam_config
create mode 100644 src/test/ipams/ipv6_gateway_changeip_ipamvnet_to_gateway_othervnetipam/net
create mode 100644 src/test/ipams/ipv6_gateway_changeip_ipamvnet_to_gateway_othervnetipam/net.expected
create mode 100644 src/test/ipams/ipv6_gateway_changeip_ipamvnet_to_gateway_othervnetipam/oldnet
create mode 100644 src/test/ipams/ipv6_gateway_changeip_ipamvnet_to_gateway_othervnetipam/sdn_config
create mode 100644 src/test/ipams/ipv6_updateipam_ipamvnet/ipam.db
create mode 100644 src/test/ipams/ipv6_updateipam_ipamvnet/ipam.db.expected
create mode 100644 src/test/ipams/ipv6_updateipam_ipamvnet/ipam_config
create mode 100644 src/test/ipams/ipv6_updateipam_ipamvnet/net
create mode 100644 src/test/ipams/ipv6_updateipam_ipamvnet/net.expected
create mode 100644 src/test/ipams/ipv6_updateipam_ipamvnet/oldnet
create mode 100644 src/test/ipams/ipv6_updateipam_ipamvnet/sdn_config
create mode 100755 src/test/run_ipam_tests.pl
create mode 100644 src/test/snapshot-input/sdn/subnets.cfg
--
2.20.1
^ permalink raw reply [flat|nested] 2+ messages in thread
* [pve-devel] [PATCH v3 pve-container 1/1] add ipam support
2021-05-24 15:19 [pve-devel] [PATCH v3 pve-container 0/1] add ipam support Alexandre Derumier
@ 2021-05-24 15:19 ` Alexandre Derumier
0 siblings, 0 replies; 2+ messages in thread
From: Alexandre Derumier @ 2021-05-24 15:19 UTC (permalink / raw)
To: pve-devel
This add ipam support for nic using sdn vnets.
- if ips are specified manally, we verify that subnet exist on vnet, and we register ip in ipam
- if nic is on a vnet, but no ip is specified, we auto find the next available ips in this vnet subnet
- if a gateway is defined on the subnet, we override current vm nc gateway
- extra informations like mac address,hostname are registered in external ipam.
- if dns server exist in the zone, we register vm hostname in ipam for each ip address
- ips addresses are removed on ct destroy, nic destroy, ip change or vnet change
- snapshot rollback: if ip from snapshot is already used, we keep the current running ip
- backup restore to new vmid: if ip from backup is already used, we set ips has undef
---
src/PVE/LXC.pm | 144 ++++++++++++++++++
src/PVE/LXC/Config.pm | 58 +++++++
src/PVE/LXC/Create.pm | 33 +++-
src/test/Makefile | 5 +-
.../ipam.db | 18 +++
.../ipam.db.expected | 17 +++
.../ipam_config | 7 +
.../net | 7 +
.../net.expected | 7 +
.../oldnet | 7 +
.../sdn_config | 35 +++++
.../ipam.db | 18 +++
.../ipam.db.expected | 18 +++
.../ipam_config | 7 +
.../net | 7 +
.../net.expected | 7 +
.../oldnet | 7 +
.../sdn_config | 35 +++++
.../ipam.db | 18 +++
.../ipam.db.expected | 17 +++
.../ipam_config | 7 +
.../net | 7 +
.../net.expected | 7 +
.../oldnet | 7 +
.../sdn_config | 35 +++++
.../ipam.db | 18 +++
.../ipam.db.expected | 18 +++
.../ipam_config | 7 +
.../net | 6 +
.../net.expected | 7 +
.../oldnet | 7 +
.../sdn_config | 35 +++++
.../ipam.db | 18 +++
.../ipam.db.expected | 18 +++
.../ipam_config | 7 +
.../net | 6 +
.../net.expected | 7 +
.../oldnet | 7 +
.../sdn_config | 35 +++++
.../ipv4_changeip_samevnet_with_ipam/ipam.db | 18 +++
.../ipam.db.expected | 18 +++
.../ipam_config | 7 +
.../ipv4_changeip_samevnet_with_ipam/net | 7 +
.../net.expected | 7 +
.../ipv4_changeip_samevnet_with_ipam/oldnet | 7 +
.../sdn_config | 35 +++++
.../ipv4_changeip_vmbr0_to_ipamvnet/ipam.db | 17 +++
.../ipam.db.expected | 18 +++
.../ipam_config | 7 +
.../ipams/ipv4_changeip_vmbr0_to_ipamvnet/net | 7 +
.../net.expected | 7 +
.../ipv4_changeip_vmbr0_to_ipamvnet/oldnet | 7 +
.../sdn_config | 35 +++++
.../ipv4_changeip_vmbr0_to_noipamvnet/ipam.db | 17 +++
.../ipam.db.expected | 17 +++
.../ipam_config | 7 +
.../ipv4_changeip_vmbr0_to_noipamvnet/net | 7 +
.../net.expected | 7 +
.../ipv4_changeip_vmbr0_to_noipamvnet/oldnet | 7 +
.../sdn_config | 35 +++++
.../ipam.db | 18 +++
.../ipam.db.expected | 18 +++
.../ipam_config | 7 +
.../net | 7 +
.../net.expected | 8 +
.../oldnet | 7 +
.../sdn_config | 38 +++++
.../ipam.db | 18 +++
.../ipam.db.expected | 17 +++
.../ipam_config | 7 +
.../net | 8 +
.../net.expected | 8 +
.../oldnet | 7 +
.../sdn_config | 38 +++++
.../ipam.db | 18 +++
.../ipam.db.expected | 18 +++
.../ipam_config | 7 +
.../net | 7 +
.../net.expected | 7 +
.../oldnet | 8 +
.../sdn_config | 36 +++++
.../ipams/ipv4_updateipam_ipamvnet/ipam.db | 18 +++
.../ipv4_updateipam_ipamvnet/ipam.db.expected | 18 +++
.../ipv4_updateipam_ipamvnet/ipam_config | 7 +
src/test/ipams/ipv4_updateipam_ipamvnet/net | 7 +
.../ipv4_updateipam_ipamvnet/net.expected | 7 +
.../ipams/ipv4_updateipam_ipamvnet/oldnet | 7 +
.../ipams/ipv4_updateipam_ipamvnet/sdn_config | 35 +++++
.../ipam.db | 19 +++
.../ipam.db.expected | 19 +++
.../ipam_config | 7 +
.../ipv4v6_next_free_samevnet_with_ipam/net | 6 +
.../net.expected | 8 +
.../oldnet | 8 +
.../sdn_config | 39 +++++
.../ipam.db | 20 +++
.../ipam.db.expected | 20 +++
.../ipam_config | 7 +
.../net | 6 +
.../net.expected | 8 +
.../oldnet | 8 +
.../sdn_config | 39 +++++
.../ipams/ipv4v6_updateipam_ipamvnet/ipam.db | 19 +++
.../ipam.db.expected | 19 +++
.../ipv4v6_updateipam_ipamvnet/ipam_config | 7 +
src/test/ipams/ipv4v6_updateipam_ipamvnet/net | 8 +
.../ipv4v6_updateipam_ipamvnet/net.expected | 8 +
.../ipams/ipv4v6_updateipam_ipamvnet/oldnet | 8 +
.../ipv4v6_updateipam_ipamvnet/sdn_config | 39 +++++
.../ipam.db | 19 +++
.../ipam.db.expected | 19 +++
.../ipam_config | 7 +
.../ipv4v6_updateipam_ipamvnet_failingv6/net | 8 +
.../net.expected | 8 +
.../oldnet | 8 +
.../sdn_config | 35 +++++
.../ipam.db | 18 +++
.../ipam.db.expected | 18 +++
.../ipam_config | 7 +
.../net | 7 +
.../net.expected | 7 +
.../oldnet | 7 +
.../sdn_config | 35 +++++
.../ipam.db | 18 +++
.../ipam.db.expected | 18 +++
.../ipam_config | 7 +
.../net | 7 +
.../net.expected | 8 +
.../oldnet | 7 +
.../sdn_config | 37 +++++
.../ipams/ipv6_updateipam_ipamvnet/ipam.db | 14 ++
.../ipv6_updateipam_ipamvnet/ipam.db.expected | 14 ++
.../ipv6_updateipam_ipamvnet/ipam_config | 7 +
src/test/ipams/ipv6_updateipam_ipamvnet/net | 7 +
.../ipv6_updateipam_ipamvnet/net.expected | 7 +
.../ipams/ipv6_updateipam_ipamvnet/oldnet | 7 +
.../ipams/ipv6_updateipam_ipamvnet/sdn_config | 35 +++++
src/test/run_ipam_tests.pl | 126 +++++++++++++++
src/test/snapshot-input/sdn/subnets.cfg | 0
src/test/snapshot-test.pm | 1 -
140 files changed, 2266 insertions(+), 10 deletions(-)
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_othervnet_noipam/ipam.db
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_othervnet_noipam/ipam.db.expected
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_othervnet_noipam/ipam_config
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_othervnet_noipam/net
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_othervnet_noipam/net.expected
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_othervnet_noipam/oldnet
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_othervnet_noipam/sdn_config
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_othervnetipam/ipam.db
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_othervnetipam/ipam.db.expected
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_othervnetipam/ipam_config
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_othervnetipam/net
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_othervnetipam/net.expected
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_othervnetipam/oldnet
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_othervnetipam/sdn_config
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_vmbr0_noipam/ipam.db
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_vmbr0_noipam/ipam.db.expected
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_vmbr0_noipam/ipam_config
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_vmbr0_noipam/net
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_vmbr0_noipam/net.expected
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_vmbr0_noipam/oldnet
create mode 100644 src/test/ipams/ipv4_changeip_ipamvnet_to_vmbr0_noipam/sdn_config
create mode 100644 src/test/ipams/ipv4_changeip_next_free_othervnet_with_ipam/ipam.db
create mode 100644 src/test/ipams/ipv4_changeip_next_free_othervnet_with_ipam/ipam.db.expected
create mode 100644 src/test/ipams/ipv4_changeip_next_free_othervnet_with_ipam/ipam_config
create mode 100644 src/test/ipams/ipv4_changeip_next_free_othervnet_with_ipam/net
create mode 100644 src/test/ipams/ipv4_changeip_next_free_othervnet_with_ipam/net.expected
create mode 100644 src/test/ipams/ipv4_changeip_next_free_othervnet_with_ipam/oldnet
create mode 100644 src/test/ipams/ipv4_changeip_next_free_othervnet_with_ipam/sdn_config
create mode 100644 src/test/ipams/ipv4_changeip_next_free_samevnet_with_ipam/ipam.db
create mode 100644 src/test/ipams/ipv4_changeip_next_free_samevnet_with_ipam/ipam.db.expected
create mode 100644 src/test/ipams/ipv4_changeip_next_free_samevnet_with_ipam/ipam_config
create mode 100644 src/test/ipams/ipv4_changeip_next_free_samevnet_with_ipam/net
create mode 100644 src/test/ipams/ipv4_changeip_next_free_samevnet_with_ipam/net.expected
create mode 100644 src/test/ipams/ipv4_changeip_next_free_samevnet_with_ipam/oldnet
create mode 100644 src/test/ipams/ipv4_changeip_next_free_samevnet_with_ipam/sdn_config
create mode 100644 src/test/ipams/ipv4_changeip_samevnet_with_ipam/ipam.db
create mode 100644 src/test/ipams/ipv4_changeip_samevnet_with_ipam/ipam.db.expected
create mode 100644 src/test/ipams/ipv4_changeip_samevnet_with_ipam/ipam_config
create mode 100644 src/test/ipams/ipv4_changeip_samevnet_with_ipam/net
create mode 100644 src/test/ipams/ipv4_changeip_samevnet_with_ipam/net.expected
create mode 100644 src/test/ipams/ipv4_changeip_samevnet_with_ipam/oldnet
create mode 100644 src/test/ipams/ipv4_changeip_samevnet_with_ipam/sdn_config
create mode 100644 src/test/ipams/ipv4_changeip_vmbr0_to_ipamvnet/ipam.db
create mode 100644 src/test/ipams/ipv4_changeip_vmbr0_to_ipamvnet/ipam.db.expected
create mode 100644 src/test/ipams/ipv4_changeip_vmbr0_to_ipamvnet/ipam_config
create mode 100644 src/test/ipams/ipv4_changeip_vmbr0_to_ipamvnet/net
create mode 100644 src/test/ipams/ipv4_changeip_vmbr0_to_ipamvnet/net.expected
create mode 100644 src/test/ipams/ipv4_changeip_vmbr0_to_ipamvnet/oldnet
create mode 100644 src/test/ipams/ipv4_changeip_vmbr0_to_ipamvnet/sdn_config
create mode 100644 src/test/ipams/ipv4_changeip_vmbr0_to_noipamvnet/ipam.db
create mode 100644 src/test/ipams/ipv4_changeip_vmbr0_to_noipamvnet/ipam.db.expected
create mode 100644 src/test/ipams/ipv4_changeip_vmbr0_to_noipamvnet/ipam_config
create mode 100644 src/test/ipams/ipv4_changeip_vmbr0_to_noipamvnet/net
create mode 100644 src/test/ipams/ipv4_changeip_vmbr0_to_noipamvnet/net.expected
create mode 100644 src/test/ipams/ipv4_changeip_vmbr0_to_noipamvnet/oldnet
create mode 100644 src/test/ipams/ipv4_changeip_vmbr0_to_noipamvnet/sdn_config
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetipam/ipam.db
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetipam/ipam.db.expected
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetipam/ipam_config
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetipam/net
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetipam/net.expected
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetipam/oldnet
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetipam/sdn_config
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetnoipam/ipam.db
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetnoipam/ipam.db.expected
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetnoipam/ipam_config
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetnoipam/net
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetnoipam/net.expected
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetnoipam/oldnet
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetnoipam/sdn_config
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_nogateway_othervnetipam/ipam.db
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_nogateway_othervnetipam/ipam.db.expected
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_nogateway_othervnetipam/ipam_config
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_nogateway_othervnetipam/net
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_nogateway_othervnetipam/net.expected
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_nogateway_othervnetipam/oldnet
create mode 100644 src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_nogateway_othervnetipam/sdn_config
create mode 100644 src/test/ipams/ipv4_updateipam_ipamvnet/ipam.db
create mode 100644 src/test/ipams/ipv4_updateipam_ipamvnet/ipam.db.expected
create mode 100644 src/test/ipams/ipv4_updateipam_ipamvnet/ipam_config
create mode 100644 src/test/ipams/ipv4_updateipam_ipamvnet/net
create mode 100644 src/test/ipams/ipv4_updateipam_ipamvnet/net.expected
create mode 100644 src/test/ipams/ipv4_updateipam_ipamvnet/oldnet
create mode 100644 src/test/ipams/ipv4_updateipam_ipamvnet/sdn_config
create mode 100644 src/test/ipams/ipv4v6_next_free_samevnet_with_ipam/ipam.db
create mode 100644 src/test/ipams/ipv4v6_next_free_samevnet_with_ipam/ipam.db.expected
create mode 100644 src/test/ipams/ipv4v6_next_free_samevnet_with_ipam/ipam_config
create mode 100644 src/test/ipams/ipv4v6_next_free_samevnet_with_ipam/net
create mode 100644 src/test/ipams/ipv4v6_next_free_samevnet_with_ipam/net.expected
create mode 100644 src/test/ipams/ipv4v6_next_free_samevnet_with_ipam/oldnet
create mode 100644 src/test/ipams/ipv4v6_next_free_samevnet_with_ipam/sdn_config
create mode 100644 src/test/ipams/ipv4v6_next_free_samevnet_with_ipam_failingv6/ipam.db
create mode 100644 src/test/ipams/ipv4v6_next_free_samevnet_with_ipam_failingv6/ipam.db.expected
create mode 100644 src/test/ipams/ipv4v6_next_free_samevnet_with_ipam_failingv6/ipam_config
create mode 100644 src/test/ipams/ipv4v6_next_free_samevnet_with_ipam_failingv6/net
create mode 100644 src/test/ipams/ipv4v6_next_free_samevnet_with_ipam_failingv6/net.expected
create mode 100644 src/test/ipams/ipv4v6_next_free_samevnet_with_ipam_failingv6/oldnet
create mode 100644 src/test/ipams/ipv4v6_next_free_samevnet_with_ipam_failingv6/sdn_config
create mode 100644 src/test/ipams/ipv4v6_updateipam_ipamvnet/ipam.db
create mode 100644 src/test/ipams/ipv4v6_updateipam_ipamvnet/ipam.db.expected
create mode 100644 src/test/ipams/ipv4v6_updateipam_ipamvnet/ipam_config
create mode 100644 src/test/ipams/ipv4v6_updateipam_ipamvnet/net
create mode 100644 src/test/ipams/ipv4v6_updateipam_ipamvnet/net.expected
create mode 100644 src/test/ipams/ipv4v6_updateipam_ipamvnet/oldnet
create mode 100644 src/test/ipams/ipv4v6_updateipam_ipamvnet/sdn_config
create mode 100644 src/test/ipams/ipv4v6_updateipam_ipamvnet_failingv6/ipam.db
create mode 100644 src/test/ipams/ipv4v6_updateipam_ipamvnet_failingv6/ipam.db.expected
create mode 100644 src/test/ipams/ipv4v6_updateipam_ipamvnet_failingv6/ipam_config
create mode 100644 src/test/ipams/ipv4v6_updateipam_ipamvnet_failingv6/net
create mode 100644 src/test/ipams/ipv4v6_updateipam_ipamvnet_failingv6/net.expected
create mode 100644 src/test/ipams/ipv4v6_updateipam_ipamvnet_failingv6/oldnet
create mode 100644 src/test/ipams/ipv4v6_updateipam_ipamvnet_failingv6/sdn_config
create mode 100644 src/test/ipams/ipv6_changeip_ipamvnet_to_othervnetipam/ipam.db
create mode 100644 src/test/ipams/ipv6_changeip_ipamvnet_to_othervnetipam/ipam.db.expected
create mode 100644 src/test/ipams/ipv6_changeip_ipamvnet_to_othervnetipam/ipam_config
create mode 100644 src/test/ipams/ipv6_changeip_ipamvnet_to_othervnetipam/net
create mode 100644 src/test/ipams/ipv6_changeip_ipamvnet_to_othervnetipam/net.expected
create mode 100644 src/test/ipams/ipv6_changeip_ipamvnet_to_othervnetipam/oldnet
create mode 100644 src/test/ipams/ipv6_changeip_ipamvnet_to_othervnetipam/sdn_config
create mode 100644 src/test/ipams/ipv6_gateway_changeip_ipamvnet_to_gateway_othervnetipam/ipam.db
create mode 100644 src/test/ipams/ipv6_gateway_changeip_ipamvnet_to_gateway_othervnetipam/ipam.db.expected
create mode 100644 src/test/ipams/ipv6_gateway_changeip_ipamvnet_to_gateway_othervnetipam/ipam_config
create mode 100644 src/test/ipams/ipv6_gateway_changeip_ipamvnet_to_gateway_othervnetipam/net
create mode 100644 src/test/ipams/ipv6_gateway_changeip_ipamvnet_to_gateway_othervnetipam/net.expected
create mode 100644 src/test/ipams/ipv6_gateway_changeip_ipamvnet_to_gateway_othervnetipam/oldnet
create mode 100644 src/test/ipams/ipv6_gateway_changeip_ipamvnet_to_gateway_othervnetipam/sdn_config
create mode 100644 src/test/ipams/ipv6_updateipam_ipamvnet/ipam.db
create mode 100644 src/test/ipams/ipv6_updateipam_ipamvnet/ipam.db.expected
create mode 100644 src/test/ipams/ipv6_updateipam_ipamvnet/ipam_config
create mode 100644 src/test/ipams/ipv6_updateipam_ipamvnet/net
create mode 100644 src/test/ipams/ipv6_updateipam_ipamvnet/net.expected
create mode 100644 src/test/ipams/ipv6_updateipam_ipamvnet/oldnet
create mode 100644 src/test/ipams/ipv6_updateipam_ipamvnet/sdn_config
create mode 100755 src/test/run_ipam_tests.pl
create mode 100644 src/test/snapshot-input/sdn/subnets.cfg
diff --git a/src/PVE/LXC.pm b/src/PVE/LXC.pm
index 7e6f378..a1eee0e 100644
--- a/src/PVE/LXC.pm
+++ b/src/PVE/LXC.pm
@@ -847,6 +847,9 @@ sub destroy_lxc_container {
rmdir "/var/lib/lxc/$vmid/rootfs";
unlink "/var/lib/lxc/$vmid/config";
rmdir "/var/lib/lxc/$vmid";
+
+ PVE::LXC::destroy_net_ip($conf);
+
if (defined $replacement_conf) {
PVE::LXC::Config->write_config($vmid, $replacement_conf);
} else {
@@ -1077,6 +1080,147 @@ sub update_ipconfig {
}
+sub is_static_ip {
+ my ($ip) = @_;
+
+ return 1 if $ip !~ m/(dhcp|manual|auto)$/;
+}
+
+sub ip_has_changed {
+ my ($oldip, $ip) = @_;
+
+ return 1 if !$oldip && $ip;
+ return 1 if !$ip && $oldip;
+ return 1 if $ip && $oldip && $ip ne $oldip;
+}
+
+my $add_net_ip = sub {
+ my ($version, $net, $oldnet, $hostname, $oldhostname, $description) = @_;
+
+ my $oldbridge = $oldnet->{bridge};
+ my $bridge = $net->{bridge};
+ my $mac = $net->{hwaddr};
+ my $ipfield = $version == 4 ? "ip" : "ip6";
+ my $ip = $net->{$ipfield};
+ my $oldip = $oldnet->{$ipfield};
+ my $subnets = PVE::Network::SDN::Vnets::get_subnets($bridge);
+ return if !keys %{$subnets};
+
+ eval {
+ if (!$ip) {
+ my $next_free_ip = PVE::Network::SDN::Vnets::get_next_free_cidr($bridge, $hostname, $mac, $description, $version);
+ $net->{$ipfield} = $next_free_ip if $next_free_ip;
+ } elsif (is_static_ip($ip)) {
+ if (!ip_has_changed($oldip, $ip)) {
+ #update ip attributes if no ip address change
+ PVE::Network::SDN::Vnets::update_cidr($bridge, $ip, $hostname, $oldhostname, $mac, $description);
+ } else {
+ PVE::Network::SDN::Vnets::add_cidr($bridge, $ip, $hostname, $mac, $description);
+ }
+ }
+ };
+ if ($@) {
+ die $@;
+ }
+};
+
+my $del_net_ip = sub {
+ my ($version, $oldnet, $net, $hostname, $description) = @_;
+
+ my $oldbridge = $oldnet->{bridge};
+ my $bridge = $net->{bridge};
+ my $ip = $version == 4 ? $net->{ip} : $net->{ip6};
+ my $oldip = $version == 4 ? $oldnet->{ip} : $oldnet->{ip6};
+
+ return if !$oldip || !is_static_ip($oldip);
+
+ my $subnets = PVE::Network::SDN::Vnets::get_subnets($oldbridge);
+ return if !keys %{$subnets};
+
+ eval {
+ PVE::Network::SDN::Vnets::del_cidr($oldbridge, $oldip, $hostname, $description) if !$bridge || $bridge ne $oldbridge || !$ip || $ip ne $oldip;
+ };
+ warn $@ if $@;
+};
+
+
+my $update_net_gateway = sub {
+ my ($version, $net) = @_;
+
+ my $bridge = $net->{bridge};
+ my $netip = $version == 4 ? $net->{ip} : $net->{ip6};
+ my $gwfield = $version == 4 ? "gw" : "gw6";
+
+ return if (!$netip || !is_static_ip($netip));
+
+ my $subnets = PVE::Network::SDN::Vnets::get_subnets($bridge);
+ return if !keys %{$subnets};
+
+ #update gateway
+ my ($ip, $mask) = split(/\//, $netip);
+ my ($subnetid, $subnet) = PVE::Network::SDN::Subnets::find_ip_subnet($ip, $mask, $subnets);
+ my $gw = $subnet->{gateway} if $subnet->{gateway};
+ $net->{$gwfield} = $gw if $gw;
+
+};
+
+sub destroy_net_ip {
+ my ($conf) = @_;
+
+ return if !$have_sdn;
+
+ foreach my $opt (keys %$conf) {
+ next if $opt !~ m/^net(\d+)$/;
+ my $netid = $1;
+ my $oldnet = PVE::LXC::Config->parse_lxc_network($conf->{$opt});
+ my $hostname = $conf->{hostname};
+ my $description = '';
+ delete_net_ip($hostname, $oldnet, undef, $description);
+ }
+}
+
+sub update_net_ip {
+ my ($net, $oldnet, $hostname, $oldhostname, $description) = @_;
+
+ return if !$have_sdn;
+
+ eval {
+ &$add_net_ip(4, $net, $oldnet, $hostname, $oldhostname, $description);
+ };
+ if ($@) {
+ $net->{ip} = $oldnet->{ip};
+ die "can't change ip4: $@\n";
+ }
+
+ eval {
+ &$add_net_ip(6, $net, $oldnet, $hostname, $oldhostname, $description);
+ };
+ if ($@) {
+ my $err = $@;
+ #if error, delete previously added ipv4
+ eval {
+ PVE::Network::SDN::Vnets::del_cidr($net->{bridge}, $net->{ip}, $hostname, $description) if ip_has_changed($oldnet->{ip}, $net->{ip});
+ };
+ $net->{ip6} = $oldnet->{ip6};
+ $net->{ip} = $oldnet->{ip};
+ die "error change ipv6: $err\n";
+ }
+
+ delete_net_ip($oldhostname, $oldnet, $net, $description);
+
+ &$update_net_gateway(4, $net);
+ &$update_net_gateway(6, $net);
+}
+
+sub delete_net_ip {
+ my ($hostname, $oldnet, $net, $description) = @_;
+
+ return if !$have_sdn;
+
+ &$del_net_ip(4, $oldnet, $net, $hostname, $description);
+ &$del_net_ip(6, $oldnet, $net, $hostname, $description);
+}
+
my $open_namespace = sub {
my ($vmid, $pid, $kind) = @_;
sysopen my $fd, "/proc/$pid/ns/$kind", O_RDONLY
diff --git a/src/PVE/LXC/Config.pm b/src/PVE/LXC/Config.pm
index 7b82f65..da8cbfa 100644
--- a/src/PVE/LXC/Config.pm
+++ b/src/PVE/LXC/Config.pm
@@ -213,6 +213,43 @@ sub __snapshot_delete_vol_snapshot {
push @$unused, $mountpoint->{volume};
}
+sub __snapshot_rollback_hook {
+ my ($class, $vmid, $conf, $snap, $prepare, $data) = @_;
+
+ if($prepare) {
+ $data->{oldconf} = $conf;
+ } else {
+ my $noerr = 1; #if ip change and already use, we keep the current ip
+ my $oldconf = $data->{oldconf};
+ #update ip of current and new net interface
+ foreach my $opt (keys %$conf) {
+ next if $opt !~ m/^net(\d+)$/;
+ my $netid = $1;
+ my $oldnet = $class->parse_lxc_network($oldconf->{$opt});
+ my $net = $class->parse_lxc_network($conf->{$opt});
+ my $hostname = $conf->{hostname};
+ my $description = "vm:$vmid net:$netid";
+ eval {
+ PVE::LXC::update_net_ip($net, $oldnet, $hostname, $hostname, $description);
+ };
+ if ($@) {
+ warn "error: $@ : keep current ip configuration\n";
+ $conf->{$opt} = $class->print_lxc_network($net);
+ }
+ }
+
+ #remove ip of removed net interface
+ foreach my $opt (keys %$oldconf) {
+ next if $opt !~ m/^net(\d+)$/;
+ next if defined($conf->{$opt});
+ my $netid = $1;
+ my $oldnet = $class->parse_lxc_network($oldconf->{$opt});
+ my $hostname = $oldconf->{hostname};
+ my $description = "vm:$vmid net:$netid";
+ PVE::LXC::delete_net_ip($hostname, $oldnet, undef, "vm:$vmid net:$netid");
+ }
+ }
+}
sub __snapshot_rollback_vol_possible {
my ($class, $mountpoint, $snapname) = @_;
@@ -1044,6 +1081,10 @@ sub update_pct_config {
$class->check_protection($conf, "can't remove CT $vmid drive '$opt'");
} elsif ($opt eq 'unprivileged') {
die "unable to delete read-only option: '$opt'\n";
+ } elsif ($opt =~ m/^net(\d+)$/) {
+ my $netid = $1;
+ my $oldnet = $class->parse_lxc_network($conf->{$opt});
+ PVE::LXC::delete_net_ip($conf->{hostname}, $oldnet, undef, "vm:$vmid net:$netid");
}
$class->add_to_pending_delete($conf, $opt);
}
@@ -1071,7 +1112,23 @@ sub update_pct_config {
$value = PVE::LXC::verify_searchdomain_list($value);
} elsif ($opt eq 'unprivileged') {
die "unable to modify read-only option: '$opt'\n";
+ } elsif ($opt =~ m/^net(\d+)$/) {
+ my $netid = $1;
+ my $net = $class->parse_lxc_network($value);
+ my $oldnet = $class->parse_lxc_network($conf->{$opt});
+ my $hostname = $param->{hostname} ? $param->{hostname} : $conf->{hostname};
+ PVE::LXC::update_net_ip($net, $oldnet, $hostname, $hostname, "vm:$vmid net:$netid");
+ $value = $class->print_lxc_network($net);
+ } elsif ($opt eq 'hostname') {
+ #if hostname change, update ipam + dns for each ip
+ foreach my $netopt (sort keys %$conf) {
+ next if $netopt !~ m/^net(\d+)$/;
+ my $netid = $1;
+ my $net = $class->parse_lxc_network($conf->{$netopt});
+ PVE::LXC::update_net_ip($net, $net, $value, $conf->{hostname}, "vm:$vmid net:$netid");
+ }
}
+
$conf->{pending}->{$opt} = $value;
$class->remove_from_pending_delete($conf, $opt);
}
@@ -1663,4 +1720,5 @@ sub get_backup_volumes {
return $return_volumes;
}
+
1;
diff --git a/src/PVE/LXC/Create.pm b/src/PVE/LXC/Create.pm
index 82d7ad9..e43433b 100644
--- a/src/PVE/LXC/Create.pm
+++ b/src/PVE/LXC/Create.pm
@@ -278,7 +278,7 @@ sub restore_configuration_from_proxmox_backup {
my $oldconf = recover_config_from_proxmox_backup($storage_cfg, $archive, $vmid);
- sanitize_and_merge_config($conf, $oldconf, $restricted, $unique);
+ sanitize_and_merge_config($conf, $oldconf, $restricted, $unique, $vmid);
my $cmd = "files";
@@ -304,7 +304,7 @@ sub restore_configuration_from_proxmox_backup {
}
sub sanitize_and_merge_config {
- my ($conf, $oldconf, $restricted, $unique) = @_;
+ my ($conf, $oldconf, $restricted, $unique, $vmid) = @_;
foreach my $key (keys %$oldconf) {
next if $key eq 'digest' || $key eq 'rootfs' || $key eq 'snapshots' || $key eq 'unprivileged' || $key eq 'parent';
@@ -325,12 +325,29 @@ sub sanitize_and_merge_config {
next;
}
- if ($unique && $key =~ /^net\d+$/) {
+ if ($key =~ m/^net(\d+)$/) {
+ my $netid = $1;
my $net = PVE::LXC::Config->parse_lxc_network($oldconf->{$key});
- my $dc = PVE::Cluster::cfs_read_file('datacenter.cfg');
- $net->{hwaddr} = PVE::Tools::random_ether_addr($dc->{mac_prefix});
- $conf->{$key} = PVE::LXC::Config->print_lxc_network($net);
- next;
+ my $hostname = $oldconf->{hostname};
+ my $description = "vm:$vmid net:$netid";
+
+ if ($unique) {
+ my $dc = PVE::Cluster::cfs_read_file('datacenter.cfg');
+ $net->{hwaddr} = PVE::Tools::random_ether_addr($dc->{mac_prefix});
+ $conf->{$key} = PVE::LXC::Config->print_lxc_network($net);
+ }
+
+ eval {
+ PVE::LXC::update_net_ip($net, undef, $hostname, $hostname, $description);
+ };
+ if ($@) {
+ warn "error: $@ : remove ipconfig from net$netid\n";
+ $net->{ip} = undef;
+ $net->{gw} = undef;
+ $net->{ip6} = undef;
+ $net->{gw6} = undef;
+ $conf->{$key} = PVE::LXC::Config->print_lxc_network($net);
+ }
}
$conf->{$key} = $oldconf->{$key} if !defined($conf->{$key});
}
@@ -348,7 +365,7 @@ sub restore_configuration_from_etc_vzdump {
my $raw = PVE::Tools::file_get_contents($pct_cfg_fn);
my $oldconf = PVE::LXC::Config::parse_pct_config("/lxc/$vmid.conf", $raw);
- sanitize_and_merge_config($conf, $oldconf, $restricted, $unique);
+ sanitize_and_merge_config($conf, $oldconf, $restricted, $unique, $vmid);
unlink($pct_cfg_fn);
diff --git a/src/test/Makefile b/src/test/Makefile
index 8734879..68133aa 100644
--- a/src/test/Makefile
+++ b/src/test/Makefile
@@ -2,7 +2,7 @@ RUN_USERNS := lxc-usernsexec -m "u:0:`id -u`:1" -m "g:0:`id -g`:1" --
all: test
-test: test_setup test_snapshot test_bindmount
+test: test_setup test_snapshot test_bindmount test_ipam
test_setup: run_setup_tests.pl
$(RUN_USERNS) ./run_setup_tests.pl
@@ -13,5 +13,8 @@ test_snapshot: run_snapshot_tests.pl
test_bindmount: bindmount_test.pl
$(RUN_USERNS) ./bindmount_test.pl
+test_ipam: run_ipam_tests.pl
+ ./run_ipam_tests.pl
+
clean:
rm -rf tmprootfs
diff --git a/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnet_noipam/ipam.db b/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnet_noipam/ipam.db
new file mode 100644
index 0000000..d03cc04
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnet_noipam/ipam.db
@@ -0,0 +1,18 @@
+{
+ "zones" => {
+ "myzone" => {
+ "subnets" => {
+ "192.168.0.0/30" => {
+ "ips" =>{
+ "192.168.0.1" => {}
+ }
+ },
+ "192.168.1.0/30" => {
+ "ips" =>{
+ }
+ },
+ }
+ },
+ }
+}
+
diff --git a/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnet_noipam/ipam.db.expected b/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnet_noipam/ipam.db.expected
new file mode 100644
index 0000000..3d36a24
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnet_noipam/ipam.db.expected
@@ -0,0 +1,17 @@
+{
+ "zones" => {
+ "myzone" => {
+ "subnets" => {
+ "192.168.0.0/30" => {
+ "ips" =>{
+ }
+ },
+ "192.168.1.0/30" => {
+ "ips" =>{
+ }
+ },
+ }
+ },
+ }
+}
+
diff --git a/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnet_noipam/ipam_config b/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnet_noipam/ipam_config
new file mode 100644
index 0000000..f5f36ad
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnet_noipam/ipam_config
@@ -0,0 +1,7 @@
+{
+ 'ids' => {
+ 'pve' => {
+ 'type' => 'pve'
+ },
+ },
+}
diff --git a/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnet_noipam/net b/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnet_noipam/net
new file mode 100644
index 0000000..26740b4
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnet_noipam/net
@@ -0,0 +1,7 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet3',
+ 'ip' => '192.168.2.1/30',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnet_noipam/net.expected b/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnet_noipam/net.expected
new file mode 100644
index 0000000..26740b4
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnet_noipam/net.expected
@@ -0,0 +1,7 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet3',
+ 'ip' => '192.168.2.1/30',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnet_noipam/oldnet b/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnet_noipam/oldnet
new file mode 100644
index 0000000..fe003a3
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnet_noipam/oldnet
@@ -0,0 +1,7 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet',
+ 'ip' => '192.168.0.1/30',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnet_noipam/sdn_config b/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnet_noipam/sdn_config
new file mode 100644
index 0000000..43e142f
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnet_noipam/sdn_config
@@ -0,0 +1,35 @@
+{
+ version => 1,
+ vnets => {
+ ids => {
+ myvnet => { type => "vnet", zone => "myzone" },
+ myvnet2 => { type => "vnet", zone => "myzone" },
+ myvnet3 => { type => "vnet", zone => "myzone2" },
+ },
+ },
+
+ zones => {
+ ids => {
+ myzone => { ipam => "pve", type =>"simple" },
+ myzone2 => { type =>"simple" },
+ },
+ },
+
+ subnets => {
+ ids => {
+ 'myzone-192.168.0.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet',
+ },
+ 'myzone-192.168.1.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet2',
+ },
+ 'myzone2-192.168.2.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet3',
+ },
+ }
+
+ }
+}
diff --git a/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnetipam/ipam.db b/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnetipam/ipam.db
new file mode 100644
index 0000000..d03cc04
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnetipam/ipam.db
@@ -0,0 +1,18 @@
+{
+ "zones" => {
+ "myzone" => {
+ "subnets" => {
+ "192.168.0.0/30" => {
+ "ips" =>{
+ "192.168.0.1" => {}
+ }
+ },
+ "192.168.1.0/30" => {
+ "ips" =>{
+ }
+ },
+ }
+ },
+ }
+}
+
diff --git a/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnetipam/ipam.db.expected b/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnetipam/ipam.db.expected
new file mode 100644
index 0000000..f576915
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnetipam/ipam.db.expected
@@ -0,0 +1,18 @@
+{
+ "zones" => {
+ "myzone" => {
+ "subnets" => {
+ "192.168.0.0/30" => {
+ "ips" =>{
+ }
+ },
+ "192.168.1.0/30" => {
+ "ips" =>{
+ "192.168.1.1" => {}
+ }
+ },
+ }
+ },
+ }
+}
+
diff --git a/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnetipam/ipam_config b/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnetipam/ipam_config
new file mode 100644
index 0000000..f5f36ad
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnetipam/ipam_config
@@ -0,0 +1,7 @@
+{
+ 'ids' => {
+ 'pve' => {
+ 'type' => 'pve'
+ },
+ },
+}
diff --git a/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnetipam/net b/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnetipam/net
new file mode 100644
index 0000000..4031d65
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnetipam/net
@@ -0,0 +1,7 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet2',
+ 'ip' => '192.168.1.1/30',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnetipam/net.expected b/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnetipam/net.expected
new file mode 100644
index 0000000..4031d65
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnetipam/net.expected
@@ -0,0 +1,7 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet2',
+ 'ip' => '192.168.1.1/30',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnetipam/oldnet b/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnetipam/oldnet
new file mode 100644
index 0000000..fe003a3
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnetipam/oldnet
@@ -0,0 +1,7 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet',
+ 'ip' => '192.168.0.1/30',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnetipam/sdn_config b/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnetipam/sdn_config
new file mode 100644
index 0000000..43e142f
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_ipamvnet_to_othervnetipam/sdn_config
@@ -0,0 +1,35 @@
+{
+ version => 1,
+ vnets => {
+ ids => {
+ myvnet => { type => "vnet", zone => "myzone" },
+ myvnet2 => { type => "vnet", zone => "myzone" },
+ myvnet3 => { type => "vnet", zone => "myzone2" },
+ },
+ },
+
+ zones => {
+ ids => {
+ myzone => { ipam => "pve", type =>"simple" },
+ myzone2 => { type =>"simple" },
+ },
+ },
+
+ subnets => {
+ ids => {
+ 'myzone-192.168.0.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet',
+ },
+ 'myzone-192.168.1.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet2',
+ },
+ 'myzone2-192.168.2.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet3',
+ },
+ }
+
+ }
+}
diff --git a/src/test/ipams/ipv4_changeip_ipamvnet_to_vmbr0_noipam/ipam.db b/src/test/ipams/ipv4_changeip_ipamvnet_to_vmbr0_noipam/ipam.db
new file mode 100644
index 0000000..d03cc04
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_ipamvnet_to_vmbr0_noipam/ipam.db
@@ -0,0 +1,18 @@
+{
+ "zones" => {
+ "myzone" => {
+ "subnets" => {
+ "192.168.0.0/30" => {
+ "ips" =>{
+ "192.168.0.1" => {}
+ }
+ },
+ "192.168.1.0/30" => {
+ "ips" =>{
+ }
+ },
+ }
+ },
+ }
+}
+
diff --git a/src/test/ipams/ipv4_changeip_ipamvnet_to_vmbr0_noipam/ipam.db.expected b/src/test/ipams/ipv4_changeip_ipamvnet_to_vmbr0_noipam/ipam.db.expected
new file mode 100644
index 0000000..3d36a24
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_ipamvnet_to_vmbr0_noipam/ipam.db.expected
@@ -0,0 +1,17 @@
+{
+ "zones" => {
+ "myzone" => {
+ "subnets" => {
+ "192.168.0.0/30" => {
+ "ips" =>{
+ }
+ },
+ "192.168.1.0/30" => {
+ "ips" =>{
+ }
+ },
+ }
+ },
+ }
+}
+
diff --git a/src/test/ipams/ipv4_changeip_ipamvnet_to_vmbr0_noipam/ipam_config b/src/test/ipams/ipv4_changeip_ipamvnet_to_vmbr0_noipam/ipam_config
new file mode 100644
index 0000000..f5f36ad
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_ipamvnet_to_vmbr0_noipam/ipam_config
@@ -0,0 +1,7 @@
+{
+ 'ids' => {
+ 'pve' => {
+ 'type' => 'pve'
+ },
+ },
+}
diff --git a/src/test/ipams/ipv4_changeip_ipamvnet_to_vmbr0_noipam/net b/src/test/ipams/ipv4_changeip_ipamvnet_to_vmbr0_noipam/net
new file mode 100644
index 0000000..908f573
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_ipamvnet_to_vmbr0_noipam/net
@@ -0,0 +1,7 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'vmbr0',
+ 'ip' => '192.168.0.1/30',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4_changeip_ipamvnet_to_vmbr0_noipam/net.expected b/src/test/ipams/ipv4_changeip_ipamvnet_to_vmbr0_noipam/net.expected
new file mode 100644
index 0000000..908f573
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_ipamvnet_to_vmbr0_noipam/net.expected
@@ -0,0 +1,7 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'vmbr0',
+ 'ip' => '192.168.0.1/30',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4_changeip_ipamvnet_to_vmbr0_noipam/oldnet b/src/test/ipams/ipv4_changeip_ipamvnet_to_vmbr0_noipam/oldnet
new file mode 100644
index 0000000..fe003a3
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_ipamvnet_to_vmbr0_noipam/oldnet
@@ -0,0 +1,7 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet',
+ 'ip' => '192.168.0.1/30',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4_changeip_ipamvnet_to_vmbr0_noipam/sdn_config b/src/test/ipams/ipv4_changeip_ipamvnet_to_vmbr0_noipam/sdn_config
new file mode 100644
index 0000000..43e142f
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_ipamvnet_to_vmbr0_noipam/sdn_config
@@ -0,0 +1,35 @@
+{
+ version => 1,
+ vnets => {
+ ids => {
+ myvnet => { type => "vnet", zone => "myzone" },
+ myvnet2 => { type => "vnet", zone => "myzone" },
+ myvnet3 => { type => "vnet", zone => "myzone2" },
+ },
+ },
+
+ zones => {
+ ids => {
+ myzone => { ipam => "pve", type =>"simple" },
+ myzone2 => { type =>"simple" },
+ },
+ },
+
+ subnets => {
+ ids => {
+ 'myzone-192.168.0.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet',
+ },
+ 'myzone-192.168.1.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet2',
+ },
+ 'myzone2-192.168.2.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet3',
+ },
+ }
+
+ }
+}
diff --git a/src/test/ipams/ipv4_changeip_next_free_othervnet_with_ipam/ipam.db b/src/test/ipams/ipv4_changeip_next_free_othervnet_with_ipam/ipam.db
new file mode 100644
index 0000000..d03cc04
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_next_free_othervnet_with_ipam/ipam.db
@@ -0,0 +1,18 @@
+{
+ "zones" => {
+ "myzone" => {
+ "subnets" => {
+ "192.168.0.0/30" => {
+ "ips" =>{
+ "192.168.0.1" => {}
+ }
+ },
+ "192.168.1.0/30" => {
+ "ips" =>{
+ }
+ },
+ }
+ },
+ }
+}
+
diff --git a/src/test/ipams/ipv4_changeip_next_free_othervnet_with_ipam/ipam.db.expected b/src/test/ipams/ipv4_changeip_next_free_othervnet_with_ipam/ipam.db.expected
new file mode 100644
index 0000000..f576915
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_next_free_othervnet_with_ipam/ipam.db.expected
@@ -0,0 +1,18 @@
+{
+ "zones" => {
+ "myzone" => {
+ "subnets" => {
+ "192.168.0.0/30" => {
+ "ips" =>{
+ }
+ },
+ "192.168.1.0/30" => {
+ "ips" =>{
+ "192.168.1.1" => {}
+ }
+ },
+ }
+ },
+ }
+}
+
diff --git a/src/test/ipams/ipv4_changeip_next_free_othervnet_with_ipam/ipam_config b/src/test/ipams/ipv4_changeip_next_free_othervnet_with_ipam/ipam_config
new file mode 100644
index 0000000..f5f36ad
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_next_free_othervnet_with_ipam/ipam_config
@@ -0,0 +1,7 @@
+{
+ 'ids' => {
+ 'pve' => {
+ 'type' => 'pve'
+ },
+ },
+}
diff --git a/src/test/ipams/ipv4_changeip_next_free_othervnet_with_ipam/net b/src/test/ipams/ipv4_changeip_next_free_othervnet_with_ipam/net
new file mode 100644
index 0000000..a73e889
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_next_free_othervnet_with_ipam/net
@@ -0,0 +1,6 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet2',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4_changeip_next_free_othervnet_with_ipam/net.expected b/src/test/ipams/ipv4_changeip_next_free_othervnet_with_ipam/net.expected
new file mode 100644
index 0000000..4031d65
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_next_free_othervnet_with_ipam/net.expected
@@ -0,0 +1,7 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet2',
+ 'ip' => '192.168.1.1/30',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4_changeip_next_free_othervnet_with_ipam/oldnet b/src/test/ipams/ipv4_changeip_next_free_othervnet_with_ipam/oldnet
new file mode 100644
index 0000000..fe003a3
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_next_free_othervnet_with_ipam/oldnet
@@ -0,0 +1,7 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet',
+ 'ip' => '192.168.0.1/30',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4_changeip_next_free_othervnet_with_ipam/sdn_config b/src/test/ipams/ipv4_changeip_next_free_othervnet_with_ipam/sdn_config
new file mode 100644
index 0000000..43e142f
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_next_free_othervnet_with_ipam/sdn_config
@@ -0,0 +1,35 @@
+{
+ version => 1,
+ vnets => {
+ ids => {
+ myvnet => { type => "vnet", zone => "myzone" },
+ myvnet2 => { type => "vnet", zone => "myzone" },
+ myvnet3 => { type => "vnet", zone => "myzone2" },
+ },
+ },
+
+ zones => {
+ ids => {
+ myzone => { ipam => "pve", type =>"simple" },
+ myzone2 => { type =>"simple" },
+ },
+ },
+
+ subnets => {
+ ids => {
+ 'myzone-192.168.0.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet',
+ },
+ 'myzone-192.168.1.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet2',
+ },
+ 'myzone2-192.168.2.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet3',
+ },
+ }
+
+ }
+}
diff --git a/src/test/ipams/ipv4_changeip_next_free_samevnet_with_ipam/ipam.db b/src/test/ipams/ipv4_changeip_next_free_samevnet_with_ipam/ipam.db
new file mode 100644
index 0000000..d03cc04
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_next_free_samevnet_with_ipam/ipam.db
@@ -0,0 +1,18 @@
+{
+ "zones" => {
+ "myzone" => {
+ "subnets" => {
+ "192.168.0.0/30" => {
+ "ips" =>{
+ "192.168.0.1" => {}
+ }
+ },
+ "192.168.1.0/30" => {
+ "ips" =>{
+ }
+ },
+ }
+ },
+ }
+}
+
diff --git a/src/test/ipams/ipv4_changeip_next_free_samevnet_with_ipam/ipam.db.expected b/src/test/ipams/ipv4_changeip_next_free_samevnet_with_ipam/ipam.db.expected
new file mode 100644
index 0000000..2287b85
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_next_free_samevnet_with_ipam/ipam.db.expected
@@ -0,0 +1,18 @@
+{
+ "zones" => {
+ "myzone" => {
+ "subnets" => {
+ "192.168.0.0/30" => {
+ "ips" =>{
+ "192.168.0.2" => {}
+ }
+ },
+ "192.168.1.0/30" => {
+ "ips" =>{
+ }
+ },
+ }
+ },
+ }
+}
+
diff --git a/src/test/ipams/ipv4_changeip_next_free_samevnet_with_ipam/ipam_config b/src/test/ipams/ipv4_changeip_next_free_samevnet_with_ipam/ipam_config
new file mode 100644
index 0000000..f5f36ad
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_next_free_samevnet_with_ipam/ipam_config
@@ -0,0 +1,7 @@
+{
+ 'ids' => {
+ 'pve' => {
+ 'type' => 'pve'
+ },
+ },
+}
diff --git a/src/test/ipams/ipv4_changeip_next_free_samevnet_with_ipam/net b/src/test/ipams/ipv4_changeip_next_free_samevnet_with_ipam/net
new file mode 100644
index 0000000..b68d367
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_next_free_samevnet_with_ipam/net
@@ -0,0 +1,6 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4_changeip_next_free_samevnet_with_ipam/net.expected b/src/test/ipams/ipv4_changeip_next_free_samevnet_with_ipam/net.expected
new file mode 100644
index 0000000..97a3915
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_next_free_samevnet_with_ipam/net.expected
@@ -0,0 +1,7 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet',
+ 'ip' => '192.168.0.2/30',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4_changeip_next_free_samevnet_with_ipam/oldnet b/src/test/ipams/ipv4_changeip_next_free_samevnet_with_ipam/oldnet
new file mode 100644
index 0000000..fe003a3
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_next_free_samevnet_with_ipam/oldnet
@@ -0,0 +1,7 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet',
+ 'ip' => '192.168.0.1/30',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4_changeip_next_free_samevnet_with_ipam/sdn_config b/src/test/ipams/ipv4_changeip_next_free_samevnet_with_ipam/sdn_config
new file mode 100644
index 0000000..43e142f
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_next_free_samevnet_with_ipam/sdn_config
@@ -0,0 +1,35 @@
+{
+ version => 1,
+ vnets => {
+ ids => {
+ myvnet => { type => "vnet", zone => "myzone" },
+ myvnet2 => { type => "vnet", zone => "myzone" },
+ myvnet3 => { type => "vnet", zone => "myzone2" },
+ },
+ },
+
+ zones => {
+ ids => {
+ myzone => { ipam => "pve", type =>"simple" },
+ myzone2 => { type =>"simple" },
+ },
+ },
+
+ subnets => {
+ ids => {
+ 'myzone-192.168.0.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet',
+ },
+ 'myzone-192.168.1.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet2',
+ },
+ 'myzone2-192.168.2.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet3',
+ },
+ }
+
+ }
+}
diff --git a/src/test/ipams/ipv4_changeip_samevnet_with_ipam/ipam.db b/src/test/ipams/ipv4_changeip_samevnet_with_ipam/ipam.db
new file mode 100644
index 0000000..d03cc04
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_samevnet_with_ipam/ipam.db
@@ -0,0 +1,18 @@
+{
+ "zones" => {
+ "myzone" => {
+ "subnets" => {
+ "192.168.0.0/30" => {
+ "ips" =>{
+ "192.168.0.1" => {}
+ }
+ },
+ "192.168.1.0/30" => {
+ "ips" =>{
+ }
+ },
+ }
+ },
+ }
+}
+
diff --git a/src/test/ipams/ipv4_changeip_samevnet_with_ipam/ipam.db.expected b/src/test/ipams/ipv4_changeip_samevnet_with_ipam/ipam.db.expected
new file mode 100644
index 0000000..2287b85
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_samevnet_with_ipam/ipam.db.expected
@@ -0,0 +1,18 @@
+{
+ "zones" => {
+ "myzone" => {
+ "subnets" => {
+ "192.168.0.0/30" => {
+ "ips" =>{
+ "192.168.0.2" => {}
+ }
+ },
+ "192.168.1.0/30" => {
+ "ips" =>{
+ }
+ },
+ }
+ },
+ }
+}
+
diff --git a/src/test/ipams/ipv4_changeip_samevnet_with_ipam/ipam_config b/src/test/ipams/ipv4_changeip_samevnet_with_ipam/ipam_config
new file mode 100644
index 0000000..f5f36ad
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_samevnet_with_ipam/ipam_config
@@ -0,0 +1,7 @@
+{
+ 'ids' => {
+ 'pve' => {
+ 'type' => 'pve'
+ },
+ },
+}
diff --git a/src/test/ipams/ipv4_changeip_samevnet_with_ipam/net b/src/test/ipams/ipv4_changeip_samevnet_with_ipam/net
new file mode 100644
index 0000000..97a3915
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_samevnet_with_ipam/net
@@ -0,0 +1,7 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet',
+ 'ip' => '192.168.0.2/30',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4_changeip_samevnet_with_ipam/net.expected b/src/test/ipams/ipv4_changeip_samevnet_with_ipam/net.expected
new file mode 100644
index 0000000..97a3915
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_samevnet_with_ipam/net.expected
@@ -0,0 +1,7 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet',
+ 'ip' => '192.168.0.2/30',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4_changeip_samevnet_with_ipam/oldnet b/src/test/ipams/ipv4_changeip_samevnet_with_ipam/oldnet
new file mode 100644
index 0000000..fe003a3
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_samevnet_with_ipam/oldnet
@@ -0,0 +1,7 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet',
+ 'ip' => '192.168.0.1/30',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4_changeip_samevnet_with_ipam/sdn_config b/src/test/ipams/ipv4_changeip_samevnet_with_ipam/sdn_config
new file mode 100644
index 0000000..43e142f
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_samevnet_with_ipam/sdn_config
@@ -0,0 +1,35 @@
+{
+ version => 1,
+ vnets => {
+ ids => {
+ myvnet => { type => "vnet", zone => "myzone" },
+ myvnet2 => { type => "vnet", zone => "myzone" },
+ myvnet3 => { type => "vnet", zone => "myzone2" },
+ },
+ },
+
+ zones => {
+ ids => {
+ myzone => { ipam => "pve", type =>"simple" },
+ myzone2 => { type =>"simple" },
+ },
+ },
+
+ subnets => {
+ ids => {
+ 'myzone-192.168.0.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet',
+ },
+ 'myzone-192.168.1.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet2',
+ },
+ 'myzone2-192.168.2.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet3',
+ },
+ }
+
+ }
+}
diff --git a/src/test/ipams/ipv4_changeip_vmbr0_to_ipamvnet/ipam.db b/src/test/ipams/ipv4_changeip_vmbr0_to_ipamvnet/ipam.db
new file mode 100644
index 0000000..3d36a24
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_vmbr0_to_ipamvnet/ipam.db
@@ -0,0 +1,17 @@
+{
+ "zones" => {
+ "myzone" => {
+ "subnets" => {
+ "192.168.0.0/30" => {
+ "ips" =>{
+ }
+ },
+ "192.168.1.0/30" => {
+ "ips" =>{
+ }
+ },
+ }
+ },
+ }
+}
+
diff --git a/src/test/ipams/ipv4_changeip_vmbr0_to_ipamvnet/ipam.db.expected b/src/test/ipams/ipv4_changeip_vmbr0_to_ipamvnet/ipam.db.expected
new file mode 100644
index 0000000..e0906aa
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_vmbr0_to_ipamvnet/ipam.db.expected
@@ -0,0 +1,18 @@
+{
+ "zones" => {
+ "myzone" => {
+ "subnets" => {
+ "192.168.0.0/30" => {
+ "ips" =>{
+ '192.168.0.1' => {}
+ }
+ },
+ "192.168.1.0/30" => {
+ "ips" =>{
+ }
+ },
+ }
+ },
+ }
+}
+
diff --git a/src/test/ipams/ipv4_changeip_vmbr0_to_ipamvnet/ipam_config b/src/test/ipams/ipv4_changeip_vmbr0_to_ipamvnet/ipam_config
new file mode 100644
index 0000000..f5f36ad
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_vmbr0_to_ipamvnet/ipam_config
@@ -0,0 +1,7 @@
+{
+ 'ids' => {
+ 'pve' => {
+ 'type' => 'pve'
+ },
+ },
+}
diff --git a/src/test/ipams/ipv4_changeip_vmbr0_to_ipamvnet/net b/src/test/ipams/ipv4_changeip_vmbr0_to_ipamvnet/net
new file mode 100644
index 0000000..fe003a3
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_vmbr0_to_ipamvnet/net
@@ -0,0 +1,7 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet',
+ 'ip' => '192.168.0.1/30',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4_changeip_vmbr0_to_ipamvnet/net.expected b/src/test/ipams/ipv4_changeip_vmbr0_to_ipamvnet/net.expected
new file mode 100644
index 0000000..fe003a3
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_vmbr0_to_ipamvnet/net.expected
@@ -0,0 +1,7 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet',
+ 'ip' => '192.168.0.1/30',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4_changeip_vmbr0_to_ipamvnet/oldnet b/src/test/ipams/ipv4_changeip_vmbr0_to_ipamvnet/oldnet
new file mode 100644
index 0000000..dbd70c4
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_vmbr0_to_ipamvnet/oldnet
@@ -0,0 +1,7 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'vmbr0',
+ 'ip' => '10.0.0.1/24',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4_changeip_vmbr0_to_ipamvnet/sdn_config b/src/test/ipams/ipv4_changeip_vmbr0_to_ipamvnet/sdn_config
new file mode 100644
index 0000000..43e142f
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_vmbr0_to_ipamvnet/sdn_config
@@ -0,0 +1,35 @@
+{
+ version => 1,
+ vnets => {
+ ids => {
+ myvnet => { type => "vnet", zone => "myzone" },
+ myvnet2 => { type => "vnet", zone => "myzone" },
+ myvnet3 => { type => "vnet", zone => "myzone2" },
+ },
+ },
+
+ zones => {
+ ids => {
+ myzone => { ipam => "pve", type =>"simple" },
+ myzone2 => { type =>"simple" },
+ },
+ },
+
+ subnets => {
+ ids => {
+ 'myzone-192.168.0.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet',
+ },
+ 'myzone-192.168.1.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet2',
+ },
+ 'myzone2-192.168.2.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet3',
+ },
+ }
+
+ }
+}
diff --git a/src/test/ipams/ipv4_changeip_vmbr0_to_noipamvnet/ipam.db b/src/test/ipams/ipv4_changeip_vmbr0_to_noipamvnet/ipam.db
new file mode 100644
index 0000000..3d36a24
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_vmbr0_to_noipamvnet/ipam.db
@@ -0,0 +1,17 @@
+{
+ "zones" => {
+ "myzone" => {
+ "subnets" => {
+ "192.168.0.0/30" => {
+ "ips" =>{
+ }
+ },
+ "192.168.1.0/30" => {
+ "ips" =>{
+ }
+ },
+ }
+ },
+ }
+}
+
diff --git a/src/test/ipams/ipv4_changeip_vmbr0_to_noipamvnet/ipam.db.expected b/src/test/ipams/ipv4_changeip_vmbr0_to_noipamvnet/ipam.db.expected
new file mode 100644
index 0000000..3d36a24
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_vmbr0_to_noipamvnet/ipam.db.expected
@@ -0,0 +1,17 @@
+{
+ "zones" => {
+ "myzone" => {
+ "subnets" => {
+ "192.168.0.0/30" => {
+ "ips" =>{
+ }
+ },
+ "192.168.1.0/30" => {
+ "ips" =>{
+ }
+ },
+ }
+ },
+ }
+}
+
diff --git a/src/test/ipams/ipv4_changeip_vmbr0_to_noipamvnet/ipam_config b/src/test/ipams/ipv4_changeip_vmbr0_to_noipamvnet/ipam_config
new file mode 100644
index 0000000..f5f36ad
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_vmbr0_to_noipamvnet/ipam_config
@@ -0,0 +1,7 @@
+{
+ 'ids' => {
+ 'pve' => {
+ 'type' => 'pve'
+ },
+ },
+}
diff --git a/src/test/ipams/ipv4_changeip_vmbr0_to_noipamvnet/net b/src/test/ipams/ipv4_changeip_vmbr0_to_noipamvnet/net
new file mode 100644
index 0000000..26740b4
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_vmbr0_to_noipamvnet/net
@@ -0,0 +1,7 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet3',
+ 'ip' => '192.168.2.1/30',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4_changeip_vmbr0_to_noipamvnet/net.expected b/src/test/ipams/ipv4_changeip_vmbr0_to_noipamvnet/net.expected
new file mode 100644
index 0000000..26740b4
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_vmbr0_to_noipamvnet/net.expected
@@ -0,0 +1,7 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet3',
+ 'ip' => '192.168.2.1/30',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4_changeip_vmbr0_to_noipamvnet/oldnet b/src/test/ipams/ipv4_changeip_vmbr0_to_noipamvnet/oldnet
new file mode 100644
index 0000000..dbd70c4
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_vmbr0_to_noipamvnet/oldnet
@@ -0,0 +1,7 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'vmbr0',
+ 'ip' => '10.0.0.1/24',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4_changeip_vmbr0_to_noipamvnet/sdn_config b/src/test/ipams/ipv4_changeip_vmbr0_to_noipamvnet/sdn_config
new file mode 100644
index 0000000..43e142f
--- /dev/null
+++ b/src/test/ipams/ipv4_changeip_vmbr0_to_noipamvnet/sdn_config
@@ -0,0 +1,35 @@
+{
+ version => 1,
+ vnets => {
+ ids => {
+ myvnet => { type => "vnet", zone => "myzone" },
+ myvnet2 => { type => "vnet", zone => "myzone" },
+ myvnet3 => { type => "vnet", zone => "myzone2" },
+ },
+ },
+
+ zones => {
+ ids => {
+ myzone => { ipam => "pve", type =>"simple" },
+ myzone2 => { type =>"simple" },
+ },
+ },
+
+ subnets => {
+ ids => {
+ 'myzone-192.168.0.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet',
+ },
+ 'myzone-192.168.1.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet2',
+ },
+ 'myzone2-192.168.2.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet3',
+ },
+ }
+
+ }
+}
diff --git a/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetipam/ipam.db b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetipam/ipam.db
new file mode 100644
index 0000000..d03cc04
--- /dev/null
+++ b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetipam/ipam.db
@@ -0,0 +1,18 @@
+{
+ "zones" => {
+ "myzone" => {
+ "subnets" => {
+ "192.168.0.0/30" => {
+ "ips" =>{
+ "192.168.0.1" => {}
+ }
+ },
+ "192.168.1.0/30" => {
+ "ips" =>{
+ }
+ },
+ }
+ },
+ }
+}
+
diff --git a/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetipam/ipam.db.expected b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetipam/ipam.db.expected
new file mode 100644
index 0000000..f576915
--- /dev/null
+++ b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetipam/ipam.db.expected
@@ -0,0 +1,18 @@
+{
+ "zones" => {
+ "myzone" => {
+ "subnets" => {
+ "192.168.0.0/30" => {
+ "ips" =>{
+ }
+ },
+ "192.168.1.0/30" => {
+ "ips" =>{
+ "192.168.1.1" => {}
+ }
+ },
+ }
+ },
+ }
+}
+
diff --git a/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetipam/ipam_config b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetipam/ipam_config
new file mode 100644
index 0000000..f5f36ad
--- /dev/null
+++ b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetipam/ipam_config
@@ -0,0 +1,7 @@
+{
+ 'ids' => {
+ 'pve' => {
+ 'type' => 'pve'
+ },
+ },
+}
diff --git a/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetipam/net b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetipam/net
new file mode 100644
index 0000000..4031d65
--- /dev/null
+++ b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetipam/net
@@ -0,0 +1,7 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet2',
+ 'ip' => '192.168.1.1/30',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetipam/net.expected b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetipam/net.expected
new file mode 100644
index 0000000..d79ce80
--- /dev/null
+++ b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetipam/net.expected
@@ -0,0 +1,8 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet2',
+ 'ip' => '192.168.1.1/30',
+ 'gw' => '192.168.1.2',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetipam/oldnet b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetipam/oldnet
new file mode 100644
index 0000000..fe003a3
--- /dev/null
+++ b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetipam/oldnet
@@ -0,0 +1,7 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet',
+ 'ip' => '192.168.0.1/30',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetipam/sdn_config b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetipam/sdn_config
new file mode 100644
index 0000000..da2eded
--- /dev/null
+++ b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetipam/sdn_config
@@ -0,0 +1,38 @@
+{
+ version => 1,
+ vnets => {
+ ids => {
+ myvnet => { type => "vnet", zone => "myzone" },
+ myvnet2 => { type => "vnet", zone => "myzone" },
+ myvnet3 => { type => "vnet", zone => "myzone2" },
+ },
+ },
+
+ zones => {
+ ids => {
+ myzone => { ipam => "pve", type =>"simple" },
+ myzone2 => { type =>"simple" },
+ },
+ },
+
+ subnets => {
+ ids => {
+ 'myzone-192.168.0.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet',
+ 'gateway' => '192.168.0.2'
+ },
+ 'myzone-192.168.1.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet2',
+ 'gateway' => '192.168.1.2'
+ },
+ 'myzone2-192.168.2.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet3',
+ 'gateway' => '192.168.2.3'
+ },
+ }
+
+ }
+}
diff --git a/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetnoipam/ipam.db b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetnoipam/ipam.db
new file mode 100644
index 0000000..d03cc04
--- /dev/null
+++ b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetnoipam/ipam.db
@@ -0,0 +1,18 @@
+{
+ "zones" => {
+ "myzone" => {
+ "subnets" => {
+ "192.168.0.0/30" => {
+ "ips" =>{
+ "192.168.0.1" => {}
+ }
+ },
+ "192.168.1.0/30" => {
+ "ips" =>{
+ }
+ },
+ }
+ },
+ }
+}
+
diff --git a/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetnoipam/ipam.db.expected b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetnoipam/ipam.db.expected
new file mode 100644
index 0000000..3d36a24
--- /dev/null
+++ b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetnoipam/ipam.db.expected
@@ -0,0 +1,17 @@
+{
+ "zones" => {
+ "myzone" => {
+ "subnets" => {
+ "192.168.0.0/30" => {
+ "ips" =>{
+ }
+ },
+ "192.168.1.0/30" => {
+ "ips" =>{
+ }
+ },
+ }
+ },
+ }
+}
+
diff --git a/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetnoipam/ipam_config b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetnoipam/ipam_config
new file mode 100644
index 0000000..f5f36ad
--- /dev/null
+++ b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetnoipam/ipam_config
@@ -0,0 +1,7 @@
+{
+ 'ids' => {
+ 'pve' => {
+ 'type' => 'pve'
+ },
+ },
+}
diff --git a/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetnoipam/net b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetnoipam/net
new file mode 100644
index 0000000..ae2b7bc
--- /dev/null
+++ b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetnoipam/net
@@ -0,0 +1,8 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet3',
+ 'ip' => '192.168.2.1/30',
+ 'gw' => '192.168.2.2',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetnoipam/net.expected b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetnoipam/net.expected
new file mode 100644
index 0000000..ae2b7bc
--- /dev/null
+++ b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetnoipam/net.expected
@@ -0,0 +1,8 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet3',
+ 'ip' => '192.168.2.1/30',
+ 'gw' => '192.168.2.2',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetnoipam/oldnet b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetnoipam/oldnet
new file mode 100644
index 0000000..fe003a3
--- /dev/null
+++ b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetnoipam/oldnet
@@ -0,0 +1,7 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet',
+ 'ip' => '192.168.0.1/30',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetnoipam/sdn_config b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetnoipam/sdn_config
new file mode 100644
index 0000000..56b17ae
--- /dev/null
+++ b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_gateway_othervnetnoipam/sdn_config
@@ -0,0 +1,38 @@
+{
+ version => 1,
+ vnets => {
+ ids => {
+ myvnet => { type => "vnet", zone => "myzone" },
+ myvnet2 => { type => "vnet", zone => "myzone" },
+ myvnet3 => { type => "vnet", zone => "myzone2" },
+ },
+ },
+
+ zones => {
+ ids => {
+ myzone => { ipam => "pve", type =>"simple" },
+ myzone2 => { type =>"simple" },
+ },
+ },
+
+ subnets => {
+ ids => {
+ 'myzone-192.168.0.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet',
+ 'gateway' => '192.168.0.2'
+ },
+ 'myzone-192.168.1.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet2',
+ 'gateway' => '192.168.1.2'
+ },
+ 'myzone2-192.168.2.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet3',
+ 'gateway' => '192.168.2.2'
+ },
+ }
+
+ }
+}
diff --git a/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_nogateway_othervnetipam/ipam.db b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_nogateway_othervnetipam/ipam.db
new file mode 100644
index 0000000..d03cc04
--- /dev/null
+++ b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_nogateway_othervnetipam/ipam.db
@@ -0,0 +1,18 @@
+{
+ "zones" => {
+ "myzone" => {
+ "subnets" => {
+ "192.168.0.0/30" => {
+ "ips" =>{
+ "192.168.0.1" => {}
+ }
+ },
+ "192.168.1.0/30" => {
+ "ips" =>{
+ }
+ },
+ }
+ },
+ }
+}
+
diff --git a/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_nogateway_othervnetipam/ipam.db.expected b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_nogateway_othervnetipam/ipam.db.expected
new file mode 100644
index 0000000..f576915
--- /dev/null
+++ b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_nogateway_othervnetipam/ipam.db.expected
@@ -0,0 +1,18 @@
+{
+ "zones" => {
+ "myzone" => {
+ "subnets" => {
+ "192.168.0.0/30" => {
+ "ips" =>{
+ }
+ },
+ "192.168.1.0/30" => {
+ "ips" =>{
+ "192.168.1.1" => {}
+ }
+ },
+ }
+ },
+ }
+}
+
diff --git a/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_nogateway_othervnetipam/ipam_config b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_nogateway_othervnetipam/ipam_config
new file mode 100644
index 0000000..f5f36ad
--- /dev/null
+++ b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_nogateway_othervnetipam/ipam_config
@@ -0,0 +1,7 @@
+{
+ 'ids' => {
+ 'pve' => {
+ 'type' => 'pve'
+ },
+ },
+}
diff --git a/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_nogateway_othervnetipam/net b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_nogateway_othervnetipam/net
new file mode 100644
index 0000000..4031d65
--- /dev/null
+++ b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_nogateway_othervnetipam/net
@@ -0,0 +1,7 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet2',
+ 'ip' => '192.168.1.1/30',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_nogateway_othervnetipam/net.expected b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_nogateway_othervnetipam/net.expected
new file mode 100644
index 0000000..4031d65
--- /dev/null
+++ b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_nogateway_othervnetipam/net.expected
@@ -0,0 +1,7 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet2',
+ 'ip' => '192.168.1.1/30',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_nogateway_othervnetipam/oldnet b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_nogateway_othervnetipam/oldnet
new file mode 100644
index 0000000..e3e093c
--- /dev/null
+++ b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_nogateway_othervnetipam/oldnet
@@ -0,0 +1,8 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet',
+ 'ip' => '192.168.0.1/30',
+ 'gw' => '192.168.0.2',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_nogateway_othervnetipam/sdn_config b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_nogateway_othervnetipam/sdn_config
new file mode 100644
index 0000000..20785d0
--- /dev/null
+++ b/src/test/ipams/ipv4_gateway_changeip_ipamvnet_to_nogateway_othervnetipam/sdn_config
@@ -0,0 +1,36 @@
+{
+ version => 1,
+ vnets => {
+ ids => {
+ myvnet => { type => "vnet", zone => "myzone" },
+ myvnet2 => { type => "vnet", zone => "myzone" },
+ myvnet3 => { type => "vnet", zone => "myzone2" },
+ },
+ },
+
+ zones => {
+ ids => {
+ myzone => { ipam => "pve", type =>"simple" },
+ myzone2 => { type =>"simple" },
+ },
+ },
+
+ subnets => {
+ ids => {
+ 'myzone-192.168.0.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet',
+ 'gateway' => '192.168.0.2'
+ },
+ 'myzone-192.168.1.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet2',
+ },
+ 'myzone2-192.168.2.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet3',
+ },
+ }
+
+ }
+}
diff --git a/src/test/ipams/ipv4_updateipam_ipamvnet/ipam.db b/src/test/ipams/ipv4_updateipam_ipamvnet/ipam.db
new file mode 100644
index 0000000..d03cc04
--- /dev/null
+++ b/src/test/ipams/ipv4_updateipam_ipamvnet/ipam.db
@@ -0,0 +1,18 @@
+{
+ "zones" => {
+ "myzone" => {
+ "subnets" => {
+ "192.168.0.0/30" => {
+ "ips" =>{
+ "192.168.0.1" => {}
+ }
+ },
+ "192.168.1.0/30" => {
+ "ips" =>{
+ }
+ },
+ }
+ },
+ }
+}
+
diff --git a/src/test/ipams/ipv4_updateipam_ipamvnet/ipam.db.expected b/src/test/ipams/ipv4_updateipam_ipamvnet/ipam.db.expected
new file mode 100644
index 0000000..d03cc04
--- /dev/null
+++ b/src/test/ipams/ipv4_updateipam_ipamvnet/ipam.db.expected
@@ -0,0 +1,18 @@
+{
+ "zones" => {
+ "myzone" => {
+ "subnets" => {
+ "192.168.0.0/30" => {
+ "ips" =>{
+ "192.168.0.1" => {}
+ }
+ },
+ "192.168.1.0/30" => {
+ "ips" =>{
+ }
+ },
+ }
+ },
+ }
+}
+
diff --git a/src/test/ipams/ipv4_updateipam_ipamvnet/ipam_config b/src/test/ipams/ipv4_updateipam_ipamvnet/ipam_config
new file mode 100644
index 0000000..f5f36ad
--- /dev/null
+++ b/src/test/ipams/ipv4_updateipam_ipamvnet/ipam_config
@@ -0,0 +1,7 @@
+{
+ 'ids' => {
+ 'pve' => {
+ 'type' => 'pve'
+ },
+ },
+}
diff --git a/src/test/ipams/ipv4_updateipam_ipamvnet/net b/src/test/ipams/ipv4_updateipam_ipamvnet/net
new file mode 100644
index 0000000..fe003a3
--- /dev/null
+++ b/src/test/ipams/ipv4_updateipam_ipamvnet/net
@@ -0,0 +1,7 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet',
+ 'ip' => '192.168.0.1/30',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4_updateipam_ipamvnet/net.expected b/src/test/ipams/ipv4_updateipam_ipamvnet/net.expected
new file mode 100644
index 0000000..fe003a3
--- /dev/null
+++ b/src/test/ipams/ipv4_updateipam_ipamvnet/net.expected
@@ -0,0 +1,7 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet',
+ 'ip' => '192.168.0.1/30',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4_updateipam_ipamvnet/oldnet b/src/test/ipams/ipv4_updateipam_ipamvnet/oldnet
new file mode 100644
index 0000000..fe003a3
--- /dev/null
+++ b/src/test/ipams/ipv4_updateipam_ipamvnet/oldnet
@@ -0,0 +1,7 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet',
+ 'ip' => '192.168.0.1/30',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4_updateipam_ipamvnet/sdn_config b/src/test/ipams/ipv4_updateipam_ipamvnet/sdn_config
new file mode 100644
index 0000000..43e142f
--- /dev/null
+++ b/src/test/ipams/ipv4_updateipam_ipamvnet/sdn_config
@@ -0,0 +1,35 @@
+{
+ version => 1,
+ vnets => {
+ ids => {
+ myvnet => { type => "vnet", zone => "myzone" },
+ myvnet2 => { type => "vnet", zone => "myzone" },
+ myvnet3 => { type => "vnet", zone => "myzone2" },
+ },
+ },
+
+ zones => {
+ ids => {
+ myzone => { ipam => "pve", type =>"simple" },
+ myzone2 => { type =>"simple" },
+ },
+ },
+
+ subnets => {
+ ids => {
+ 'myzone-192.168.0.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet',
+ },
+ 'myzone-192.168.1.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet2',
+ },
+ 'myzone2-192.168.2.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet3',
+ },
+ }
+
+ }
+}
diff --git a/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam/ipam.db b/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam/ipam.db
new file mode 100644
index 0000000..252c95a
--- /dev/null
+++ b/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam/ipam.db
@@ -0,0 +1,19 @@
+{
+ "zones" => {
+ "myzone" => {
+ "subnets" => {
+ "192.168.0.0/30" => {
+ "ips" =>{
+ "192.168.0.1" => {}
+ }
+ },
+ "2001:db8:85a3::8a2e:370:7334/127" => {
+ "ips" =>{
+ "2001:db8:85a3::8a2e:370:7334" => {}
+ }
+ },
+ }
+ },
+ }
+}
+
diff --git a/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam/ipam.db.expected b/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam/ipam.db.expected
new file mode 100644
index 0000000..8dcf09b
--- /dev/null
+++ b/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam/ipam.db.expected
@@ -0,0 +1,19 @@
+{
+ "zones" => {
+ "myzone" => {
+ "subnets" => {
+ "192.168.0.0/30" => {
+ "ips" =>{
+ "192.168.0.2" => {}
+ }
+ },
+ "2001:db8:85a3::8a2e:370:7334/127" => {
+ "ips" =>{
+ "2001:db8:85a3::8a2e:370:7335" => {}
+ }
+ },
+ }
+ },
+ }
+}
+
diff --git a/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam/ipam_config b/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam/ipam_config
new file mode 100644
index 0000000..f5f36ad
--- /dev/null
+++ b/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam/ipam_config
@@ -0,0 +1,7 @@
+{
+ 'ids' => {
+ 'pve' => {
+ 'type' => 'pve'
+ },
+ },
+}
diff --git a/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam/net b/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam/net
new file mode 100644
index 0000000..b68d367
--- /dev/null
+++ b/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam/net
@@ -0,0 +1,6 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam/net.expected b/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam/net.expected
new file mode 100644
index 0000000..3b6e3c5
--- /dev/null
+++ b/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam/net.expected
@@ -0,0 +1,8 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet',
+ 'ip' => '192.168.0.2/30',
+ 'ip6' => '2001:db8:85a3::8a2e:370:7335/127',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam/oldnet b/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam/oldnet
new file mode 100644
index 0000000..929f90d
--- /dev/null
+++ b/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam/oldnet
@@ -0,0 +1,8 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet',
+ 'ip' => '192.168.0.1/30',
+ 'ip6' => '2001:db8:85a3::8a2e:370:7334/127',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam/sdn_config b/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam/sdn_config
new file mode 100644
index 0000000..171cb08
--- /dev/null
+++ b/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam/sdn_config
@@ -0,0 +1,39 @@
+{
+ version => 1,
+ vnets => {
+ ids => {
+ myvnet => { type => "vnet", zone => "myzone" },
+ myvnet2 => { type => "vnet", zone => "myzone" },
+ myvnet3 => { type => "vnet", zone => "myzone2" },
+ },
+ },
+
+ zones => {
+ ids => {
+ myzone => { ipam => "pve", type =>"simple" },
+ myzone2 => { type =>"simple" },
+ },
+ },
+
+ subnets => {
+ ids => {
+ 'myzone-192.168.0.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet',
+ },
+ 'myzone-2001:db8:85a3::8a2e:370:7334-127' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet',
+ },
+ 'myzone-192.168.1.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet2',
+ },
+ 'myzone2-192.168.2.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet3',
+ },
+ }
+
+ }
+}
diff --git a/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam_failingv6/ipam.db b/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam_failingv6/ipam.db
new file mode 100644
index 0000000..de920d7
--- /dev/null
+++ b/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam_failingv6/ipam.db
@@ -0,0 +1,20 @@
+{
+ "zones" => {
+ "myzone" => {
+ "subnets" => {
+ "192.168.0.0/30" => {
+ "ips" =>{
+ "192.168.0.1" => {}
+ }
+ },
+ "2001:db8:85a3::8a2e:370:7334/127" => {
+ "ips" =>{
+ "2001:db8:85a3::8a2e:370:7334" => {},
+ "2001:db8:85a3::8a2e:370:7335" => {}
+ }
+ },
+ }
+ },
+ }
+}
+
diff --git a/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam_failingv6/ipam.db.expected b/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam_failingv6/ipam.db.expected
new file mode 100644
index 0000000..de920d7
--- /dev/null
+++ b/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam_failingv6/ipam.db.expected
@@ -0,0 +1,20 @@
+{
+ "zones" => {
+ "myzone" => {
+ "subnets" => {
+ "192.168.0.0/30" => {
+ "ips" =>{
+ "192.168.0.1" => {}
+ }
+ },
+ "2001:db8:85a3::8a2e:370:7334/127" => {
+ "ips" =>{
+ "2001:db8:85a3::8a2e:370:7334" => {},
+ "2001:db8:85a3::8a2e:370:7335" => {}
+ }
+ },
+ }
+ },
+ }
+}
+
diff --git a/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam_failingv6/ipam_config b/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam_failingv6/ipam_config
new file mode 100644
index 0000000..f5f36ad
--- /dev/null
+++ b/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam_failingv6/ipam_config
@@ -0,0 +1,7 @@
+{
+ 'ids' => {
+ 'pve' => {
+ 'type' => 'pve'
+ },
+ },
+}
diff --git a/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam_failingv6/net b/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam_failingv6/net
new file mode 100644
index 0000000..b68d367
--- /dev/null
+++ b/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam_failingv6/net
@@ -0,0 +1,6 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam_failingv6/net.expected b/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam_failingv6/net.expected
new file mode 100644
index 0000000..929f90d
--- /dev/null
+++ b/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam_failingv6/net.expected
@@ -0,0 +1,8 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet',
+ 'ip' => '192.168.0.1/30',
+ 'ip6' => '2001:db8:85a3::8a2e:370:7334/127',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam_failingv6/oldnet b/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam_failingv6/oldnet
new file mode 100644
index 0000000..929f90d
--- /dev/null
+++ b/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam_failingv6/oldnet
@@ -0,0 +1,8 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet',
+ 'ip' => '192.168.0.1/30',
+ 'ip6' => '2001:db8:85a3::8a2e:370:7334/127',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam_failingv6/sdn_config b/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam_failingv6/sdn_config
new file mode 100644
index 0000000..171cb08
--- /dev/null
+++ b/src/test/ipams/ipv4v6_next_free_samevnet_with_ipam_failingv6/sdn_config
@@ -0,0 +1,39 @@
+{
+ version => 1,
+ vnets => {
+ ids => {
+ myvnet => { type => "vnet", zone => "myzone" },
+ myvnet2 => { type => "vnet", zone => "myzone" },
+ myvnet3 => { type => "vnet", zone => "myzone2" },
+ },
+ },
+
+ zones => {
+ ids => {
+ myzone => { ipam => "pve", type =>"simple" },
+ myzone2 => { type =>"simple" },
+ },
+ },
+
+ subnets => {
+ ids => {
+ 'myzone-192.168.0.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet',
+ },
+ 'myzone-2001:db8:85a3::8a2e:370:7334-127' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet',
+ },
+ 'myzone-192.168.1.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet2',
+ },
+ 'myzone2-192.168.2.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet3',
+ },
+ }
+
+ }
+}
diff --git a/src/test/ipams/ipv4v6_updateipam_ipamvnet/ipam.db b/src/test/ipams/ipv4v6_updateipam_ipamvnet/ipam.db
new file mode 100644
index 0000000..252c95a
--- /dev/null
+++ b/src/test/ipams/ipv4v6_updateipam_ipamvnet/ipam.db
@@ -0,0 +1,19 @@
+{
+ "zones" => {
+ "myzone" => {
+ "subnets" => {
+ "192.168.0.0/30" => {
+ "ips" =>{
+ "192.168.0.1" => {}
+ }
+ },
+ "2001:db8:85a3::8a2e:370:7334/127" => {
+ "ips" =>{
+ "2001:db8:85a3::8a2e:370:7334" => {}
+ }
+ },
+ }
+ },
+ }
+}
+
diff --git a/src/test/ipams/ipv4v6_updateipam_ipamvnet/ipam.db.expected b/src/test/ipams/ipv4v6_updateipam_ipamvnet/ipam.db.expected
new file mode 100644
index 0000000..adb6fc7
--- /dev/null
+++ b/src/test/ipams/ipv4v6_updateipam_ipamvnet/ipam.db.expected
@@ -0,0 +1,19 @@
+{
+ "zones" => {
+ "myzone" => {
+ "subnets" => {
+ "192.168.0.0/30" => {
+ "ips" =>{
+ "192.168.0.1" => {}
+ }
+ },
+ "2001:db8:85a3::8a2e:370:7334/127" => {
+ "ips" =>{
+ "2001:db8:85a3::8a2e:370:7335" => {}
+ }
+ },
+ }
+ },
+ }
+}
+
diff --git a/src/test/ipams/ipv4v6_updateipam_ipamvnet/ipam_config b/src/test/ipams/ipv4v6_updateipam_ipamvnet/ipam_config
new file mode 100644
index 0000000..f5f36ad
--- /dev/null
+++ b/src/test/ipams/ipv4v6_updateipam_ipamvnet/ipam_config
@@ -0,0 +1,7 @@
+{
+ 'ids' => {
+ 'pve' => {
+ 'type' => 'pve'
+ },
+ },
+}
diff --git a/src/test/ipams/ipv4v6_updateipam_ipamvnet/net b/src/test/ipams/ipv4v6_updateipam_ipamvnet/net
new file mode 100644
index 0000000..e7052bc
--- /dev/null
+++ b/src/test/ipams/ipv4v6_updateipam_ipamvnet/net
@@ -0,0 +1,8 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet',
+ 'ip' => '192.168.0.1/30',
+ 'ip6' => '2001:db8:85a3::8a2e:370:7335/127',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4v6_updateipam_ipamvnet/net.expected b/src/test/ipams/ipv4v6_updateipam_ipamvnet/net.expected
new file mode 100644
index 0000000..e7052bc
--- /dev/null
+++ b/src/test/ipams/ipv4v6_updateipam_ipamvnet/net.expected
@@ -0,0 +1,8 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet',
+ 'ip' => '192.168.0.1/30',
+ 'ip6' => '2001:db8:85a3::8a2e:370:7335/127',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4v6_updateipam_ipamvnet/oldnet b/src/test/ipams/ipv4v6_updateipam_ipamvnet/oldnet
new file mode 100644
index 0000000..929f90d
--- /dev/null
+++ b/src/test/ipams/ipv4v6_updateipam_ipamvnet/oldnet
@@ -0,0 +1,8 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet',
+ 'ip' => '192.168.0.1/30',
+ 'ip6' => '2001:db8:85a3::8a2e:370:7334/127',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4v6_updateipam_ipamvnet/sdn_config b/src/test/ipams/ipv4v6_updateipam_ipamvnet/sdn_config
new file mode 100644
index 0000000..171cb08
--- /dev/null
+++ b/src/test/ipams/ipv4v6_updateipam_ipamvnet/sdn_config
@@ -0,0 +1,39 @@
+{
+ version => 1,
+ vnets => {
+ ids => {
+ myvnet => { type => "vnet", zone => "myzone" },
+ myvnet2 => { type => "vnet", zone => "myzone" },
+ myvnet3 => { type => "vnet", zone => "myzone2" },
+ },
+ },
+
+ zones => {
+ ids => {
+ myzone => { ipam => "pve", type =>"simple" },
+ myzone2 => { type =>"simple" },
+ },
+ },
+
+ subnets => {
+ ids => {
+ 'myzone-192.168.0.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet',
+ },
+ 'myzone-2001:db8:85a3::8a2e:370:7334-127' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet',
+ },
+ 'myzone-192.168.1.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet2',
+ },
+ 'myzone2-192.168.2.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet3',
+ },
+ }
+
+ }
+}
diff --git a/src/test/ipams/ipv4v6_updateipam_ipamvnet_failingv6/ipam.db b/src/test/ipams/ipv4v6_updateipam_ipamvnet_failingv6/ipam.db
new file mode 100644
index 0000000..252c95a
--- /dev/null
+++ b/src/test/ipams/ipv4v6_updateipam_ipamvnet_failingv6/ipam.db
@@ -0,0 +1,19 @@
+{
+ "zones" => {
+ "myzone" => {
+ "subnets" => {
+ "192.168.0.0/30" => {
+ "ips" =>{
+ "192.168.0.1" => {}
+ }
+ },
+ "2001:db8:85a3::8a2e:370:7334/127" => {
+ "ips" =>{
+ "2001:db8:85a3::8a2e:370:7334" => {}
+ }
+ },
+ }
+ },
+ }
+}
+
diff --git a/src/test/ipams/ipv4v6_updateipam_ipamvnet_failingv6/ipam.db.expected b/src/test/ipams/ipv4v6_updateipam_ipamvnet_failingv6/ipam.db.expected
new file mode 100644
index 0000000..252c95a
--- /dev/null
+++ b/src/test/ipams/ipv4v6_updateipam_ipamvnet_failingv6/ipam.db.expected
@@ -0,0 +1,19 @@
+{
+ "zones" => {
+ "myzone" => {
+ "subnets" => {
+ "192.168.0.0/30" => {
+ "ips" =>{
+ "192.168.0.1" => {}
+ }
+ },
+ "2001:db8:85a3::8a2e:370:7334/127" => {
+ "ips" =>{
+ "2001:db8:85a3::8a2e:370:7334" => {}
+ }
+ },
+ }
+ },
+ }
+}
+
diff --git a/src/test/ipams/ipv4v6_updateipam_ipamvnet_failingv6/ipam_config b/src/test/ipams/ipv4v6_updateipam_ipamvnet_failingv6/ipam_config
new file mode 100644
index 0000000..f5f36ad
--- /dev/null
+++ b/src/test/ipams/ipv4v6_updateipam_ipamvnet_failingv6/ipam_config
@@ -0,0 +1,7 @@
+{
+ 'ids' => {
+ 'pve' => {
+ 'type' => 'pve'
+ },
+ },
+}
diff --git a/src/test/ipams/ipv4v6_updateipam_ipamvnet_failingv6/net b/src/test/ipams/ipv4v6_updateipam_ipamvnet_failingv6/net
new file mode 100644
index 0000000..872a354
--- /dev/null
+++ b/src/test/ipams/ipv4v6_updateipam_ipamvnet_failingv6/net
@@ -0,0 +1,8 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet',
+ 'ip' => '192.168.0.1/30',
+ 'ip6' => '2001:db8:85a3::8a2e:370:7336/127',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4v6_updateipam_ipamvnet_failingv6/net.expected b/src/test/ipams/ipv4v6_updateipam_ipamvnet_failingv6/net.expected
new file mode 100644
index 0000000..929f90d
--- /dev/null
+++ b/src/test/ipams/ipv4v6_updateipam_ipamvnet_failingv6/net.expected
@@ -0,0 +1,8 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet',
+ 'ip' => '192.168.0.1/30',
+ 'ip6' => '2001:db8:85a3::8a2e:370:7334/127',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4v6_updateipam_ipamvnet_failingv6/oldnet b/src/test/ipams/ipv4v6_updateipam_ipamvnet_failingv6/oldnet
new file mode 100644
index 0000000..929f90d
--- /dev/null
+++ b/src/test/ipams/ipv4v6_updateipam_ipamvnet_failingv6/oldnet
@@ -0,0 +1,8 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet',
+ 'ip' => '192.168.0.1/30',
+ 'ip6' => '2001:db8:85a3::8a2e:370:7334/127',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv4v6_updateipam_ipamvnet_failingv6/sdn_config b/src/test/ipams/ipv4v6_updateipam_ipamvnet_failingv6/sdn_config
new file mode 100644
index 0000000..43e142f
--- /dev/null
+++ b/src/test/ipams/ipv4v6_updateipam_ipamvnet_failingv6/sdn_config
@@ -0,0 +1,35 @@
+{
+ version => 1,
+ vnets => {
+ ids => {
+ myvnet => { type => "vnet", zone => "myzone" },
+ myvnet2 => { type => "vnet", zone => "myzone" },
+ myvnet3 => { type => "vnet", zone => "myzone2" },
+ },
+ },
+
+ zones => {
+ ids => {
+ myzone => { ipam => "pve", type =>"simple" },
+ myzone2 => { type =>"simple" },
+ },
+ },
+
+ subnets => {
+ ids => {
+ 'myzone-192.168.0.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet',
+ },
+ 'myzone-192.168.1.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet2',
+ },
+ 'myzone2-192.168.2.0-30' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet3',
+ },
+ }
+
+ }
+}
diff --git a/src/test/ipams/ipv6_changeip_ipamvnet_to_othervnetipam/ipam.db b/src/test/ipams/ipv6_changeip_ipamvnet_to_othervnetipam/ipam.db
new file mode 100644
index 0000000..16c5af3
--- /dev/null
+++ b/src/test/ipams/ipv6_changeip_ipamvnet_to_othervnetipam/ipam.db
@@ -0,0 +1,18 @@
+{
+ "zones" => {
+ "myzone" => {
+ "subnets" => {
+ "2001:db8:85a3::8a2e:370:7334/127" => {
+ "ips" =>{
+ "2001:db8:85a3::8a2e:370:7334" => {}
+ }
+ },
+ "2001:db8:85a3::8a2e:371:7334/127" => {
+ "ips" =>{
+ }
+ },
+ }
+ },
+ }
+}
+
diff --git a/src/test/ipams/ipv6_changeip_ipamvnet_to_othervnetipam/ipam.db.expected b/src/test/ipams/ipv6_changeip_ipamvnet_to_othervnetipam/ipam.db.expected
new file mode 100644
index 0000000..4039793
--- /dev/null
+++ b/src/test/ipams/ipv6_changeip_ipamvnet_to_othervnetipam/ipam.db.expected
@@ -0,0 +1,18 @@
+{
+ "zones" => {
+ "myzone" => {
+ "subnets" => {
+ "2001:db8:85a3::8a2e:370:7334/127" => {
+ "ips" =>{
+ }
+ },
+ "2001:db8:85a3::8a2e:371:7334/127" => {
+ "ips" =>{
+ "2001:db8:85a3::8a2e:371:7334" => {}
+ }
+ },
+ }
+ },
+ }
+}
+
diff --git a/src/test/ipams/ipv6_changeip_ipamvnet_to_othervnetipam/ipam_config b/src/test/ipams/ipv6_changeip_ipamvnet_to_othervnetipam/ipam_config
new file mode 100644
index 0000000..f5f36ad
--- /dev/null
+++ b/src/test/ipams/ipv6_changeip_ipamvnet_to_othervnetipam/ipam_config
@@ -0,0 +1,7 @@
+{
+ 'ids' => {
+ 'pve' => {
+ 'type' => 'pve'
+ },
+ },
+}
diff --git a/src/test/ipams/ipv6_changeip_ipamvnet_to_othervnetipam/net b/src/test/ipams/ipv6_changeip_ipamvnet_to_othervnetipam/net
new file mode 100644
index 0000000..b4bee3a
--- /dev/null
+++ b/src/test/ipams/ipv6_changeip_ipamvnet_to_othervnetipam/net
@@ -0,0 +1,7 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet2',
+ 'ip6' => '2001:db8:85a3::8a2e:371:7334/127',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv6_changeip_ipamvnet_to_othervnetipam/net.expected b/src/test/ipams/ipv6_changeip_ipamvnet_to_othervnetipam/net.expected
new file mode 100644
index 0000000..b4bee3a
--- /dev/null
+++ b/src/test/ipams/ipv6_changeip_ipamvnet_to_othervnetipam/net.expected
@@ -0,0 +1,7 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet2',
+ 'ip6' => '2001:db8:85a3::8a2e:371:7334/127',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv6_changeip_ipamvnet_to_othervnetipam/oldnet b/src/test/ipams/ipv6_changeip_ipamvnet_to_othervnetipam/oldnet
new file mode 100644
index 0000000..b1c5472
--- /dev/null
+++ b/src/test/ipams/ipv6_changeip_ipamvnet_to_othervnetipam/oldnet
@@ -0,0 +1,7 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet',
+ 'ip6' => '2001:db8:85a3::8a2e:370:7334/127',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv6_changeip_ipamvnet_to_othervnetipam/sdn_config b/src/test/ipams/ipv6_changeip_ipamvnet_to_othervnetipam/sdn_config
new file mode 100644
index 0000000..5d48a4e
--- /dev/null
+++ b/src/test/ipams/ipv6_changeip_ipamvnet_to_othervnetipam/sdn_config
@@ -0,0 +1,35 @@
+{
+ version => 1,
+ vnets => {
+ ids => {
+ myvnet => { type => "vnet", zone => "myzone" },
+ myvnet2 => { type => "vnet", zone => "myzone" },
+ myvnet3 => { type => "vnet", zone => "myzone2" },
+ },
+ },
+
+ zones => {
+ ids => {
+ myzone => { ipam => "pve", type =>"simple" },
+ myzone2 => { type =>"simple" },
+ },
+ },
+
+ subnets => {
+ ids => {
+ 'myzone-2001:db8:85a3::8a2e:370:7334-127' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet',
+ },
+ 'myzone-2001:db8:85a3::8a2e:371:7334-127' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet2',
+ },
+ 'myzone2-2001:db8:85a3::8a2e:372:7334-127' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet3',
+ },
+ }
+
+ }
+}
diff --git a/src/test/ipams/ipv6_gateway_changeip_ipamvnet_to_gateway_othervnetipam/ipam.db b/src/test/ipams/ipv6_gateway_changeip_ipamvnet_to_gateway_othervnetipam/ipam.db
new file mode 100644
index 0000000..16c5af3
--- /dev/null
+++ b/src/test/ipams/ipv6_gateway_changeip_ipamvnet_to_gateway_othervnetipam/ipam.db
@@ -0,0 +1,18 @@
+{
+ "zones" => {
+ "myzone" => {
+ "subnets" => {
+ "2001:db8:85a3::8a2e:370:7334/127" => {
+ "ips" =>{
+ "2001:db8:85a3::8a2e:370:7334" => {}
+ }
+ },
+ "2001:db8:85a3::8a2e:371:7334/127" => {
+ "ips" =>{
+ }
+ },
+ }
+ },
+ }
+}
+
diff --git a/src/test/ipams/ipv6_gateway_changeip_ipamvnet_to_gateway_othervnetipam/ipam.db.expected b/src/test/ipams/ipv6_gateway_changeip_ipamvnet_to_gateway_othervnetipam/ipam.db.expected
new file mode 100644
index 0000000..4039793
--- /dev/null
+++ b/src/test/ipams/ipv6_gateway_changeip_ipamvnet_to_gateway_othervnetipam/ipam.db.expected
@@ -0,0 +1,18 @@
+{
+ "zones" => {
+ "myzone" => {
+ "subnets" => {
+ "2001:db8:85a3::8a2e:370:7334/127" => {
+ "ips" =>{
+ }
+ },
+ "2001:db8:85a3::8a2e:371:7334/127" => {
+ "ips" =>{
+ "2001:db8:85a3::8a2e:371:7334" => {}
+ }
+ },
+ }
+ },
+ }
+}
+
diff --git a/src/test/ipams/ipv6_gateway_changeip_ipamvnet_to_gateway_othervnetipam/ipam_config b/src/test/ipams/ipv6_gateway_changeip_ipamvnet_to_gateway_othervnetipam/ipam_config
new file mode 100644
index 0000000..f5f36ad
--- /dev/null
+++ b/src/test/ipams/ipv6_gateway_changeip_ipamvnet_to_gateway_othervnetipam/ipam_config
@@ -0,0 +1,7 @@
+{
+ 'ids' => {
+ 'pve' => {
+ 'type' => 'pve'
+ },
+ },
+}
diff --git a/src/test/ipams/ipv6_gateway_changeip_ipamvnet_to_gateway_othervnetipam/net b/src/test/ipams/ipv6_gateway_changeip_ipamvnet_to_gateway_othervnetipam/net
new file mode 100644
index 0000000..b4bee3a
--- /dev/null
+++ b/src/test/ipams/ipv6_gateway_changeip_ipamvnet_to_gateway_othervnetipam/net
@@ -0,0 +1,7 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet2',
+ 'ip6' => '2001:db8:85a3::8a2e:371:7334/127',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv6_gateway_changeip_ipamvnet_to_gateway_othervnetipam/net.expected b/src/test/ipams/ipv6_gateway_changeip_ipamvnet_to_gateway_othervnetipam/net.expected
new file mode 100644
index 0000000..689f7cc
--- /dev/null
+++ b/src/test/ipams/ipv6_gateway_changeip_ipamvnet_to_gateway_othervnetipam/net.expected
@@ -0,0 +1,8 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet2',
+ 'gw6' => '2001:db8:85a3::8a2e:371:7335',
+ 'ip6' => '2001:db8:85a3::8a2e:371:7334/127',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv6_gateway_changeip_ipamvnet_to_gateway_othervnetipam/oldnet b/src/test/ipams/ipv6_gateway_changeip_ipamvnet_to_gateway_othervnetipam/oldnet
new file mode 100644
index 0000000..b1c5472
--- /dev/null
+++ b/src/test/ipams/ipv6_gateway_changeip_ipamvnet_to_gateway_othervnetipam/oldnet
@@ -0,0 +1,7 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet',
+ 'ip6' => '2001:db8:85a3::8a2e:370:7334/127',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv6_gateway_changeip_ipamvnet_to_gateway_othervnetipam/sdn_config b/src/test/ipams/ipv6_gateway_changeip_ipamvnet_to_gateway_othervnetipam/sdn_config
new file mode 100644
index 0000000..3652eca
--- /dev/null
+++ b/src/test/ipams/ipv6_gateway_changeip_ipamvnet_to_gateway_othervnetipam/sdn_config
@@ -0,0 +1,37 @@
+{
+ version => 1,
+ vnets => {
+ ids => {
+ myvnet => { type => "vnet", zone => "myzone" },
+ myvnet2 => { type => "vnet", zone => "myzone" },
+ myvnet3 => { type => "vnet", zone => "myzone2" },
+ },
+ },
+
+ zones => {
+ ids => {
+ myzone => { ipam => "pve", type =>"simple" },
+ myzone2 => { type =>"simple" },
+ },
+ },
+
+ subnets => {
+ ids => {
+ 'myzone-2001:db8:85a3::8a2e:370:7334-127' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet',
+ 'gateway' => '2001:db8:85a3::8a2e:370:7335'
+ },
+ 'myzone-2001:db8:85a3::8a2e:371:7334-127' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet2',
+ 'gateway' => '2001:db8:85a3::8a2e:371:7335'
+ },
+ 'myzone2-2001:db8:85a3::8a2e:372:7334-127' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet3',
+ },
+ }
+
+ }
+}
diff --git a/src/test/ipams/ipv6_updateipam_ipamvnet/ipam.db b/src/test/ipams/ipv6_updateipam_ipamvnet/ipam.db
new file mode 100644
index 0000000..d8e3ce5
--- /dev/null
+++ b/src/test/ipams/ipv6_updateipam_ipamvnet/ipam.db
@@ -0,0 +1,14 @@
+{
+ "zones" => {
+ "myzone" => {
+ "subnets" => {
+ "2001:db8:85a3::8a2e:370:7334/127" => {
+ "ips" =>{
+ "2001:db8:85a3::8a2e:370:7334" => {}
+ }
+ },
+ }
+ },
+ }
+}
+
diff --git a/src/test/ipams/ipv6_updateipam_ipamvnet/ipam.db.expected b/src/test/ipams/ipv6_updateipam_ipamvnet/ipam.db.expected
new file mode 100644
index 0000000..89b6e8c
--- /dev/null
+++ b/src/test/ipams/ipv6_updateipam_ipamvnet/ipam.db.expected
@@ -0,0 +1,14 @@
+{
+ "zones" => {
+ "myzone" => {
+ "subnets" => {
+ "2001:db8:85a3::8a2e:370:7334/127" => {
+ "ips" =>{
+ "2001:db8:85a3::8a2e:370:7335" => {}
+ }
+ },
+ }
+ },
+ }
+}
+
diff --git a/src/test/ipams/ipv6_updateipam_ipamvnet/ipam_config b/src/test/ipams/ipv6_updateipam_ipamvnet/ipam_config
new file mode 100644
index 0000000..f5f36ad
--- /dev/null
+++ b/src/test/ipams/ipv6_updateipam_ipamvnet/ipam_config
@@ -0,0 +1,7 @@
+{
+ 'ids' => {
+ 'pve' => {
+ 'type' => 'pve'
+ },
+ },
+}
diff --git a/src/test/ipams/ipv6_updateipam_ipamvnet/net b/src/test/ipams/ipv6_updateipam_ipamvnet/net
new file mode 100644
index 0000000..4f83ab2
--- /dev/null
+++ b/src/test/ipams/ipv6_updateipam_ipamvnet/net
@@ -0,0 +1,7 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet',
+ 'ip6' => '2001:db8:85a3::8a2e:370:7335/127',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv6_updateipam_ipamvnet/net.expected b/src/test/ipams/ipv6_updateipam_ipamvnet/net.expected
new file mode 100644
index 0000000..4f83ab2
--- /dev/null
+++ b/src/test/ipams/ipv6_updateipam_ipamvnet/net.expected
@@ -0,0 +1,7 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet',
+ 'ip6' => '2001:db8:85a3::8a2e:370:7335/127',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv6_updateipam_ipamvnet/oldnet b/src/test/ipams/ipv6_updateipam_ipamvnet/oldnet
new file mode 100644
index 0000000..b1c5472
--- /dev/null
+++ b/src/test/ipams/ipv6_updateipam_ipamvnet/oldnet
@@ -0,0 +1,7 @@
+{
+ 'name' => 'eth0',
+ 'bridge' => 'myvnet',
+ 'ip6' => '2001:db8:85a3::8a2e:370:7334/127',
+ 'type' => 'veth',
+ 'hwaddr' => '8A:4C:75:11:58:1D'
+}
diff --git a/src/test/ipams/ipv6_updateipam_ipamvnet/sdn_config b/src/test/ipams/ipv6_updateipam_ipamvnet/sdn_config
new file mode 100644
index 0000000..5d48a4e
--- /dev/null
+++ b/src/test/ipams/ipv6_updateipam_ipamvnet/sdn_config
@@ -0,0 +1,35 @@
+{
+ version => 1,
+ vnets => {
+ ids => {
+ myvnet => { type => "vnet", zone => "myzone" },
+ myvnet2 => { type => "vnet", zone => "myzone" },
+ myvnet3 => { type => "vnet", zone => "myzone2" },
+ },
+ },
+
+ zones => {
+ ids => {
+ myzone => { ipam => "pve", type =>"simple" },
+ myzone2 => { type =>"simple" },
+ },
+ },
+
+ subnets => {
+ ids => {
+ 'myzone-2001:db8:85a3::8a2e:370:7334-127' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet',
+ },
+ 'myzone-2001:db8:85a3::8a2e:371:7334-127' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet2',
+ },
+ 'myzone2-2001:db8:85a3::8a2e:372:7334-127' => {
+ 'type' => 'subnet',
+ 'vnet' => 'myvnet3',
+ },
+ }
+
+ }
+}
diff --git a/src/test/run_ipam_tests.pl b/src/test/run_ipam_tests.pl
new file mode 100755
index 0000000..ab8c7ac
--- /dev/null
+++ b/src/test/run_ipam_tests.pl
@@ -0,0 +1,126 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use lib qw(..);
+use File::Slurp;
+use NetAddr::IP qw(:lower);
+
+use Test::More;
+use Test::MockModule;
+
+use PVE::Network::SDN;
+use PVE::Network::SDN::Zones;
+use PVE::INotify;
+use PVE::LXC;
+use JSON;
+
+use Data::Dumper qw(Dumper);
+$Data::Dumper::Sortkeys = 1;
+
+sub read_sdn_config {
+ my ($file) = @_;
+ # Read structure back in again
+ open my $in, '<', $file or die $!;
+ my $sdn_config;
+ {
+ local $/; # slurp mode
+ $sdn_config = eval <$in>;
+ }
+ close $in;
+ return $sdn_config;
+}
+
+
+my @plugins = read_dir( './ipams/', prefix => 1 ) ;
+
+foreach my $path (@plugins) {
+
+ my (undef, $testid) = split(/\//, $path);
+
+ print "test: $testid\n";
+ my $sdn_config = read_sdn_config ("$path/sdn_config");
+ my $pve_sdn_zones;
+ $pve_sdn_zones = Test::MockModule->new('PVE::Network::SDN::Zones');
+ $pve_sdn_zones->mock(
+ config => sub {
+ return $sdn_config->{zones};
+ },
+ );
+
+ my $pve_sdn_vnets;
+ $pve_sdn_vnets = Test::MockModule->new('PVE::Network::SDN::Vnets');
+ $pve_sdn_vnets->mock(
+ config => sub {
+ return $sdn_config->{vnets};
+ },
+ );
+
+ my $pve_sdn_subnets;
+ $pve_sdn_subnets = Test::MockModule->new('PVE::Network::SDN::Subnets');
+ $pve_sdn_subnets->mock(
+ config => sub {
+ return $sdn_config->{subnets};
+ },
+ verify_dns_zone => sub {
+ return;
+ },
+ add_dns_record => sub {
+ return;
+ }
+ );
+
+ my $js = JSON->new;
+ $js->canonical(1);
+
+ my $hostname = "myhostname";
+ my $mac = "da:65:8f:18:9b:6f";
+ my $description = "mydescription";
+ my $ipamdb = read_sdn_config ("$path/ipam.db");
+
+ my $plugin;
+ my $sdn_ipam_plugin;
+ $plugin = PVE::Network::SDN::Ipams::Plugin->lookup('pve');
+ $sdn_ipam_plugin = Test::MockModule->new($plugin);
+ $sdn_ipam_plugin->mock(
+ read_db => sub {
+ return $ipamdb;
+ },
+ write_db => sub {
+ my ($cfg) = @_;
+ $ipamdb = $cfg;
+ }
+ );
+
+ my $pve_sdn_ipams;
+ $pve_sdn_ipams = Test::MockModule->new('PVE::Network::SDN::Ipams');
+ $pve_sdn_ipams->mock(
+ config => sub {
+ my $ipam_config = read_sdn_config ("$path/ipam_config");
+ return $ipam_config;
+ },
+ );
+
+
+ ## add_ip
+ my $test = "update_net";
+ my $name = "$testid $test";
+ my $oldnet = read_sdn_config("$path/oldnet");
+ my $net = read_sdn_config("$path/net");
+ my $expected_net = read_sdn_config("$path/net.expected");
+ my $expected_ipamdb = read_sdn_config("$path/ipam.db.expected");
+
+ eval {
+ PVE::LXC::update_net_ip($net, $oldnet, $hostname, $hostname, "description");
+ };
+ is(Dumper($net), Dumper($expected_net), "verify net");
+ is(Dumper($ipamdb), Dumper($expected_ipamdb), "verify ipam.db");
+
+
+
+}
+
+done_testing();
+
+
diff --git a/src/test/snapshot-input/sdn/subnets.cfg b/src/test/snapshot-input/sdn/subnets.cfg
new file mode 100644
index 0000000..e69de29
diff --git a/src/test/snapshot-test.pm b/src/test/snapshot-test.pm
index 91a2af9..73a0532 100644
--- a/src/test/snapshot-test.pm
+++ b/src/test/snapshot-test.pm
@@ -281,7 +281,6 @@ sub mocked_write_config {
# END mocked PVE::LXC methods
-
PVE::Tools::run_command("rm -rf snapshot-working");
PVE::Tools::run_command("cp -a snapshot-input snapshot-working");
--
2.20.1
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2021-05-24 15:20 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-24 15:19 [pve-devel] [PATCH v3 pve-container 0/1] add ipam support Alexandre Derumier
2021-05-24 15:19 ` [pve-devel] [PATCH v3 pve-container 1/1] " Alexandre Derumier
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal