summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/PVE/API2/Network/SDN.pm96
-rw-r--r--src/PVE/API2/Network/SDN/Controllers.pm293
-rw-r--r--src/PVE/API2/Network/SDN/Dns.pm241
-rw-r--r--src/PVE/API2/Network/SDN/Ipams.pm351
-rw-r--r--src/PVE/API2/Network/SDN/Ips.pm144
-rw-r--r--src/PVE/API2/Network/SDN/Subnets.pm360
-rw-r--r--src/PVE/API2/Network/SDN/Vnets.pm376
-rw-r--r--src/PVE/API2/Network/SDN/Zones.pm428
-rw-r--r--src/PVE/API2/Network/SDN/Zones/Content.pm92
-rw-r--r--src/PVE/API2/Network/SDN/Zones/Status.pm112
-rw-r--r--src/PVE/Network/SDN.pm222
-rw-r--r--src/PVE/Network/SDN/Controllers.pm110
-rw-r--r--src/PVE/Network/SDN/Controllers/BgpPlugin.pm120
-rw-r--r--src/PVE/Network/SDN/Controllers/EvpnPlugin.pm706
-rw-r--r--src/PVE/Network/SDN/Controllers/FaucetPlugin.pm16
-rw-r--r--src/PVE/Network/SDN/Controllers/IsisPlugin.pm54
-rw-r--r--src/PVE/Network/SDN/Controllers/Plugin.pm52
-rw-r--r--src/PVE/Network/SDN/Dhcp.pm74
-rw-r--r--src/PVE/Network/SDN/Dhcp/Dnsmasq.pm160
-rw-r--r--src/PVE/Network/SDN/Dhcp/Plugin.pm10
-rw-r--r--src/PVE/Network/SDN/Dns.pm5
-rw-r--r--src/PVE/Network/SDN/Dns/Plugin.pm55
-rw-r--r--src/PVE/Network/SDN/Dns/PowerdnsPlugin.pm205
-rw-r--r--src/PVE/Network/SDN/Ipams.pm88
-rw-r--r--src/PVE/Network/SDN/Ipams/NetboxPlugin.pm329
-rw-r--r--src/PVE/Network/SDN/Ipams/PVEPlugin.pm339
-rw-r--r--src/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm164
-rw-r--r--src/PVE/Network/SDN/Ipams/Plugin.pm87
-rw-r--r--src/PVE/Network/SDN/SubnetPlugin.pm252
-rw-r--r--src/PVE/Network/SDN/Subnets.pm257
-rw-r--r--src/PVE/Network/SDN/VnetPlugin.pm70
-rw-r--r--src/PVE/Network/SDN/Vnets.pm110
-rw-r--r--src/PVE/Network/SDN/Zones.pm238
-rw-r--r--src/PVE/Network/SDN/Zones/EvpnPlugin.pm378
-rw-r--r--src/PVE/Network/SDN/Zones/FaucetPlugin.pm24
-rw-r--r--src/PVE/Network/SDN/Zones/Plugin.pm222
-rw-r--r--src/PVE/Network/SDN/Zones/QinQPlugin.pm202
-rw-r--r--src/PVE/Network/SDN/Zones/SimplePlugin.pm156
-rw-r--r--src/PVE/Network/SDN/Zones/VlanPlugin.pm183
-rw-r--r--src/PVE/Network/SDN/Zones/VxlanPlugin.pm80
-rwxr-xr-xsrc/test/run_test_dns.pl396
-rwxr-xr-xsrc/test/run_test_ipams.pl133
-rwxr-xr-xsrc/test/run_test_subnets.pl362
-rwxr-xr-xsrc/test/run_test_vnets_blackbox.pl737
-rwxr-xr-xsrc/test/run_test_zones.pl148
45 files changed, 4949 insertions, 4288 deletions
diff --git a/src/PVE/API2/Network/SDN.pm b/src/PVE/API2/Network/SDN.pm
index d216e48..b514803 100644
--- a/src/PVE/API2/Network/SDN.pm
+++ b/src/PVE/API2/Network/SDN.pm
@@ -20,27 +20,27 @@ use PVE::API2::Network::SDN::Dns;
use base qw(PVE::RESTHandler);
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
subclass => "PVE::API2::Network::SDN::Vnets",
path => 'vnets',
});
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
subclass => "PVE::API2::Network::SDN::Zones",
path => 'zones',
});
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
subclass => "PVE::API2::Network::SDN::Controllers",
path => 'controllers',
});
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
subclass => "PVE::API2::Network::SDN::Ipams",
path => 'ipams',
});
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
subclass => "PVE::API2::Network::SDN::Dns",
path => 'dns',
});
@@ -51,35 +51,36 @@ __PACKAGE__->register_method({
method => 'GET',
description => "Directory index.",
permissions => {
- check => ['perm', '/sdn', [ 'SDN.Audit' ]],
+ check => ['perm', '/sdn', ['SDN.Audit']],
},
parameters => {
- additionalProperties => 0,
- properties => {},
+ additionalProperties => 0,
+ properties => {},
},
returns => {
- type => 'array',
- items => {
- type => "object",
- properties => {
- id => { type => 'string' },
- },
- },
- links => [ { rel => 'child', href => "{id}" } ],
+ type => 'array',
+ items => {
+ type => "object",
+ properties => {
+ id => { type => 'string' },
+ },
+ },
+ links => [{ rel => 'child', href => "{id}" }],
},
code => sub {
- my ($param) = @_;
+ my ($param) = @_;
- my $res = [
- { id => 'vnets' },
- { id => 'zones' },
- { id => 'controllers' },
- { id => 'ipams' },
- { id => 'dns' },
- ];
+ my $res = [
+ { id => 'vnets' },
+ { id => 'zones' },
+ { id => 'controllers' },
+ { id => 'ipams' },
+ { id => 'dns' },
+ ];
- return $res;
- }});
+ return $res;
+ },
+});
my $create_reload_network_worker = sub {
my ($nodename) = @_;
@@ -87,26 +88,29 @@ my $create_reload_network_worker = sub {
# FIXME: how to proxy to final node ?
my $upid;
print "$nodename: reloading network config\n";
- run_command(['pvesh', 'set', "/nodes/$nodename/network"], outfunc => sub {
- my $line = shift;
- if ($line =~ /["']?(UPID:[^\s"']+)["']?$/) {
- $upid = $1;
- }
- });
+ run_command(
+ ['pvesh', 'set', "/nodes/$nodename/network"],
+ outfunc => sub {
+ my $line = shift;
+ if ($line =~ /["']?(UPID:[^\s"']+)["']?$/) {
+ $upid = $1;
+ }
+ },
+ );
#my $upid = PVE::API2::Network->reload_network_config(node => $nodename});
my $res = PVE::Tools::upid_decode($upid);
return $res->{pid};
};
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
name => 'reload',
protected => 1,
path => '',
method => 'PUT',
description => "Apply sdn controller changes && reload.",
permissions => {
- check => ['perm', '/sdn', ['SDN.Allocate']],
+ check => ['perm', '/sdn', ['SDN.Allocate']],
},
parameters => {
additionalProperties => 0,
@@ -120,26 +124,26 @@ __PACKAGE__->register_method ({
my $rpcenv = PVE::RPCEnvironment::get();
my $authuser = $rpcenv->get_user();
- PVE::Network::SDN::commit_config();
+ PVE::Network::SDN::commit_config();
my $code = sub {
$rpcenv->{type} = 'priv'; # to start tasks in background
- PVE::Cluster::check_cfs_quorum();
- my $nodelist = PVE::Cluster::get_nodelist();
- for my $node (@$nodelist) {
- my $pid = eval { $create_reload_network_worker->($node) };
- warn $@ if $@;
- }
+ PVE::Cluster::check_cfs_quorum();
+ my $nodelist = PVE::Cluster::get_nodelist();
+ for my $node (@$nodelist) {
+ my $pid = eval { $create_reload_network_worker->($node) };
+ warn $@ if $@;
+ }
- # FIXME: use libpve-apiclient (like in cluster join) to create
- # tasks and moitor the tasks.
+ # FIXME: use libpve-apiclient (like in cluster join) to create
+ # tasks and moitor the tasks.
- return;
+ return;
};
return $rpcenv->fork_worker('reloadnetworkall', undef, $authuser, $code);
- }});
-
+ },
+});
1;
diff --git a/src/PVE/API2/Network/SDN/Controllers.pm b/src/PVE/API2/Network/SDN/Controllers.pm
index b776273..e6eb4cb 100644
--- a/src/PVE/API2/Network/SDN/Controllers.pm
+++ b/src/PVE/API2/Network/SDN/Controllers.pm
@@ -34,56 +34,58 @@ my $api_sdn_controllers_config = sub {
return $scfg;
};
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
name => 'index',
path => '',
method => 'GET',
description => "SDN controllers index.",
permissions => {
- description => "Only list entries where you have 'SDN.Audit' or 'SDN.Allocate' permissions on '/sdn/controllers/<controller>'",
- user => 'all',
+ description =>
+ "Only list entries where you have 'SDN.Audit' or 'SDN.Allocate' permissions on '/sdn/controllers/<controller>'",
+ user => 'all',
},
parameters => {
- additionalProperties => 0,
- properties => {
- type => {
- description => "Only list sdn controllers of specific type",
- type => 'string',
- enum => $sdn_controllers_type_enum,
- optional => 1,
- },
- running => {
- type => 'boolean',
- optional => 1,
- description => "Display running config.",
- },
- pending => {
- type => 'boolean',
- optional => 1,
- description => "Display pending config.",
- },
- },
+ additionalProperties => 0,
+ properties => {
+ type => {
+ description => "Only list sdn controllers of specific type",
+ type => 'string',
+ enum => $sdn_controllers_type_enum,
+ optional => 1,
+ },
+ running => {
+ type => 'boolean',
+ optional => 1,
+ description => "Display running config.",
+ },
+ pending => {
+ type => 'boolean',
+ optional => 1,
+ description => "Display pending config.",
+ },
+ },
},
returns => {
- type => 'array',
- items => {
- type => "object",
- properties => { controller => { type => 'string' },
- type => { type => 'string' },
- state => { type => 'string', optional => 1 },
- pending => { type => 'boolean', optional => 1 },
- },
- },
- links => [ { rel => 'child', href => "{controller}" } ],
+ type => 'array',
+ items => {
+ type => "object",
+ properties => {
+ controller => { type => 'string' },
+ type => { type => 'string' },
+ state => { type => 'string', optional => 1 },
+ pending => { type => 'boolean', optional => 1 },
+ },
+ },
+ links => [{ rel => 'child', href => "{controller}" }],
},
code => sub {
- my ($param) = @_;
+ my ($param) = @_;
- my $rpcenv = PVE::RPCEnvironment::get();
- my $authuser = $rpcenv->get_user();
+ my $rpcenv = PVE::RPCEnvironment::get();
+ my $authuser = $rpcenv->get_user();
my $cfg = {};
- if($param->{pending}) {
+ if ($param->{pending}) {
my $running_cfg = PVE::Network::SDN::running_config();
my $config = PVE::Network::SDN::Controllers::config();
$cfg = PVE::Network::SDN::pending_config($running_cfg, $config, 'controllers');
@@ -94,54 +96,55 @@ __PACKAGE__->register_method ({
$cfg = PVE::Network::SDN::Controllers::config();
}
- my @sids = PVE::Network::SDN::Controllers::sdn_controllers_ids($cfg);
- my $res = [];
- foreach my $id (@sids) {
- my $privs = [ 'SDN.Audit', 'SDN.Allocate' ];
- next if !$rpcenv->check_any($authuser, "/sdn/controllers/$id", $privs, 1);
+ my @sids = PVE::Network::SDN::Controllers::sdn_controllers_ids($cfg);
+ my $res = [];
+ foreach my $id (@sids) {
+ my $privs = ['SDN.Audit', 'SDN.Allocate'];
+ next if !$rpcenv->check_any($authuser, "/sdn/controllers/$id", $privs, 1);
- my $scfg = &$api_sdn_controllers_config($cfg, $id);
- next if $param->{type} && $param->{type} ne $scfg->{type};
+ my $scfg = &$api_sdn_controllers_config($cfg, $id);
+ next if $param->{type} && $param->{type} ne $scfg->{type};
- my $plugin_config = $cfg->{ids}->{$id};
- my $plugin = PVE::Network::SDN::Controllers::Plugin->lookup($plugin_config->{type});
- push @$res, $scfg;
- }
+ my $plugin_config = $cfg->{ids}->{$id};
+ my $plugin = PVE::Network::SDN::Controllers::Plugin->lookup($plugin_config->{type});
+ push @$res, $scfg;
+ }
- return $res;
- }});
+ return $res;
+ },
+});
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
name => 'read',
path => '{controller}',
method => 'GET',
description => "Read sdn controller configuration.",
permissions => {
- check => ['perm', '/sdn/controllers/{controller}', ['SDN.Allocate']],
- },
+ check => ['perm', '/sdn/controllers/{controller}', ['SDN.Allocate']],
+ },
parameters => {
- additionalProperties => 0,
- properties => {
- controller => get_standard_option('pve-sdn-controller-id'),
- running => {
- type => 'boolean',
- optional => 1,
- description => "Display running config.",
- },
- pending => {
- type => 'boolean',
- optional => 1,
- description => "Display pending config.",
- },
- },
+ additionalProperties => 0,
+ properties => {
+ controller => get_standard_option('pve-sdn-controller-id'),
+ running => {
+ type => 'boolean',
+ optional => 1,
+ description => "Display running config.",
+ },
+ pending => {
+ type => 'boolean',
+ optional => 1,
+ description => "Display pending config.",
+ },
+ },
},
returns => { type => 'object' },
code => sub {
- my ($param) = @_;
+ my ($param) = @_;
my $cfg = {};
- if($param->{pending}) {
+ if ($param->{pending}) {
my $running_cfg = PVE::Network::SDN::running_config();
my $config = PVE::Network::SDN::Controllers::config();
$cfg = PVE::Network::SDN::pending_config($running_cfg, $config, 'controllers');
@@ -152,146 +155,162 @@ __PACKAGE__->register_method ({
$cfg = PVE::Network::SDN::Controllers::config();
}
- return &$api_sdn_controllers_config($cfg, $param->{controller});
- }});
+ return &$api_sdn_controllers_config($cfg, $param->{controller});
+ },
+});
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
name => 'create',
protected => 1,
path => '',
method => 'POST',
description => "Create a new sdn controller object.",
permissions => {
- check => ['perm', '/sdn/controllers', ['SDN.Allocate']],
+ check => ['perm', '/sdn/controllers', ['SDN.Allocate']],
},
parameters => PVE::Network::SDN::Controllers::Plugin->createSchema(),
returns => { type => 'null' },
code => sub {
- my ($param) = @_;
+ my ($param) = @_;
- my $type = extract_param($param, 'type');
- my $id = extract_param($param, 'controller');
+ my $type = extract_param($param, 'type');
+ my $id = extract_param($param, 'controller');
- my $plugin = PVE::Network::SDN::Controllers::Plugin->lookup($type);
- my $opts = $plugin->check_config($id, $param, 1, 1);
+ my $plugin = PVE::Network::SDN::Controllers::Plugin->lookup($type);
+ my $opts = $plugin->check_config($id, $param, 1, 1);
# create /etc/pve/sdn directory
PVE::Cluster::check_cfs_quorum();
mkdir("/etc/pve/sdn");
PVE::Network::SDN::lock_sdn_config(
- sub {
+ sub {
- my $controller_cfg = PVE::Network::SDN::Controllers::config();
+ my $controller_cfg = PVE::Network::SDN::Controllers::config();
- my $scfg = undef;
- if ($scfg = PVE::Network::SDN::Controllers::sdn_controllers_config($controller_cfg, $id, 1)) {
- die "sdn controller object ID '$id' already defined\n";
- }
+ my $scfg = undef;
+ if (
+ $scfg = PVE::Network::SDN::Controllers::sdn_controllers_config(
+ $controller_cfg, $id, 1,
+ )
+ ) {
+ die "sdn controller object ID '$id' already defined\n";
+ }
- $controller_cfg->{ids}->{$id} = $opts;
- $plugin->on_update_hook($id, $controller_cfg);
+ $controller_cfg->{ids}->{$id} = $opts;
+ $plugin->on_update_hook($id, $controller_cfg);
- PVE::Network::SDN::Controllers::write_config($controller_cfg);
+ PVE::Network::SDN::Controllers::write_config($controller_cfg);
- }, "create sdn controller object failed");
+ },
+ "create sdn controller object failed",
+ );
- return undef;
- }});
+ return undef;
+ },
+});
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
name => 'update',
protected => 1,
path => '{controller}',
method => 'PUT',
description => "Update sdn controller object configuration.",
permissions => {
- check => ['perm', '/sdn/controllers', ['SDN.Allocate']],
+ check => ['perm', '/sdn/controllers', ['SDN.Allocate']],
},
parameters => PVE::Network::SDN::Controllers::Plugin->updateSchema(),
returns => { type => 'null' },
code => sub {
- my ($param) = @_;
+ my ($param) = @_;
- my $id = extract_param($param, 'controller');
- my $digest = extract_param($param, 'digest');
- my $delete = extract_param($param, 'delete');
+ my $id = extract_param($param, 'controller');
+ my $digest = extract_param($param, 'digest');
+ my $delete = extract_param($param, 'delete');
PVE::Network::SDN::lock_sdn_config(
- sub {
+ sub {
- my $controller_cfg = PVE::Network::SDN::Controllers::config();
+ my $controller_cfg = PVE::Network::SDN::Controllers::config();
- PVE::SectionConfig::assert_if_modified($controller_cfg, $digest);
+ PVE::SectionConfig::assert_if_modified($controller_cfg, $digest);
- my $scfg = PVE::Network::SDN::Controllers::sdn_controllers_config($controller_cfg, $id);
+ my $scfg =
+ PVE::Network::SDN::Controllers::sdn_controllers_config($controller_cfg, $id);
- my $plugin = PVE::Network::SDN::Controllers::Plugin->lookup($scfg->{type});
- my $opts = $plugin->check_config($id, $param, 0, 1);
+ my $plugin = PVE::Network::SDN::Controllers::Plugin->lookup($scfg->{type});
+ my $opts = $plugin->check_config($id, $param, 0, 1);
- if ($delete) {
- $delete = [ PVE::Tools::split_list($delete) ];
- my $options = $plugin->private()->{options}->{$scfg->{type}};
- PVE::SectionConfig::delete_from_config($scfg, $options, $opts, $delete);
- }
+ if ($delete) {
+ $delete = [PVE::Tools::split_list($delete)];
+ my $options = $plugin->private()->{options}->{ $scfg->{type} };
+ PVE::SectionConfig::delete_from_config($scfg, $options, $opts, $delete);
+ }
- for my $k (keys %{$opts}) {
- $scfg->{$k} = $opts->{$k};
- }
+ for my $k (keys %{$opts}) {
+ $scfg->{$k} = $opts->{$k};
+ }
- $plugin->on_update_hook($id, $controller_cfg);
+ $plugin->on_update_hook($id, $controller_cfg);
- PVE::Network::SDN::Controllers::write_config($controller_cfg);
+ PVE::Network::SDN::Controllers::write_config($controller_cfg);
+ },
+ "update sdn controller object failed",
+ );
- }, "update sdn controller object failed");
-
- return undef;
- }});
+ return undef;
+ },
+});
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
name => 'delete',
protected => 1,
path => '{controller}',
method => 'DELETE',
description => "Delete sdn controller object configuration.",
permissions => {
- check => ['perm', '/sdn/controllers', ['SDN.Allocate']],
+ check => ['perm', '/sdn/controllers', ['SDN.Allocate']],
},
parameters => {
- additionalProperties => 0,
- properties => {
- controller => get_standard_option('pve-sdn-controller-id', {
- completion => \&PVE::Network::SDN::Controllers::complete_sdn_controllers,
- }),
- },
+ additionalProperties => 0,
+ properties => {
+ controller => get_standard_option(
+ 'pve-sdn-controller-id',
+ {
+ completion => \&PVE::Network::SDN::Controllers::complete_sdn_controllers,
+ },
+ ),
+ },
},
returns => { type => 'null' },
code => sub {
- my ($param) = @_;
+ my ($param) = @_;
- my $id = extract_param($param, 'controller');
+ my $id = extract_param($param, 'controller');
PVE::Network::SDN::lock_sdn_config(
- sub {
+ sub {
- my $cfg = PVE::Network::SDN::Controllers::config();
+ my $cfg = PVE::Network::SDN::Controllers::config();
- my $scfg = PVE::Network::SDN::Controllers::sdn_controllers_config($cfg, $id);
+ my $scfg = PVE::Network::SDN::Controllers::sdn_controllers_config($cfg, $id);
- my $plugin = PVE::Network::SDN::Controllers::Plugin->lookup($scfg->{type});
+ my $plugin = PVE::Network::SDN::Controllers::Plugin->lookup($scfg->{type});
- my $zone_cfg = PVE::Network::SDN::Zones::config();
+ my $zone_cfg = PVE::Network::SDN::Zones::config();
- $plugin->on_delete_hook($id, $zone_cfg);
+ $plugin->on_delete_hook($id, $zone_cfg);
- delete $cfg->{ids}->{$id};
- PVE::Network::SDN::Controllers::write_config($cfg);
+ delete $cfg->{ids}->{$id};
+ PVE::Network::SDN::Controllers::write_config($cfg);
- }, "delete sdn controller object failed");
+ },
+ "delete sdn controller object failed",
+ );
-
- return undef;
- }});
+ return undef;
+ },
+});
1;
diff --git a/src/PVE/API2/Network/SDN/Dns.pm b/src/PVE/API2/Network/SDN/Dns.pm
index 826d111..c82e354 100644
--- a/src/PVE/API2/Network/SDN/Dns.pm
+++ b/src/PVE/API2/Network/SDN/Dns.pm
@@ -31,219 +31,234 @@ my $api_sdn_dns_config = sub {
return $scfg;
};
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
name => 'index',
path => '',
method => 'GET',
description => "SDN dns index.",
permissions => {
- description => "Only list entries where you have 'SDN.Audit' or 'SDN.Allocate' permissions on '/sdn/dns/<dns>'",
- user => 'all',
+ description =>
+ "Only list entries where you have 'SDN.Audit' or 'SDN.Allocate' permissions on '/sdn/dns/<dns>'",
+ user => 'all',
},
parameters => {
- additionalProperties => 0,
- properties => {
- type => {
- description => "Only list sdn dns of specific type",
- type => 'string',
- enum => $sdn_dns_type_enum,
- optional => 1,
- },
- },
+ additionalProperties => 0,
+ properties => {
+ type => {
+ description => "Only list sdn dns of specific type",
+ type => 'string',
+ enum => $sdn_dns_type_enum,
+ optional => 1,
+ },
+ },
},
returns => {
- type => 'array',
- items => {
- type => "object",
- properties => { dns => { type => 'string'},
- type => { type => 'string'},
- },
- },
- links => [ { rel => 'child', href => "{dns}" } ],
+ type => 'array',
+ items => {
+ type => "object",
+ properties => {
+ dns => { type => 'string' },
+ type => { type => 'string' },
+ },
+ },
+ links => [{ rel => 'child', href => "{dns}" }],
},
code => sub {
- my ($param) = @_;
+ my ($param) = @_;
- my $rpcenv = PVE::RPCEnvironment::get();
- my $authuser = $rpcenv->get_user();
+ my $rpcenv = PVE::RPCEnvironment::get();
+ my $authuser = $rpcenv->get_user();
+ my $cfg = PVE::Network::SDN::Dns::config();
- my $cfg = PVE::Network::SDN::Dns::config();
+ my @sids = PVE::Network::SDN::Dns::sdn_dns_ids($cfg);
+ my $res = [];
+ foreach my $id (@sids) {
+ my $privs = ['SDN.Audit', 'SDN.Allocate'];
+ next if !$rpcenv->check_any($authuser, "/sdn/dns/$id", $privs, 1);
- my @sids = PVE::Network::SDN::Dns::sdn_dns_ids($cfg);
- my $res = [];
- foreach my $id (@sids) {
- my $privs = [ 'SDN.Audit', 'SDN.Allocate' ];
- next if !$rpcenv->check_any($authuser, "/sdn/dns/$id", $privs, 1);
+ my $scfg = &$api_sdn_dns_config($cfg, $id);
+ next if $param->{type} && $param->{type} ne $scfg->{type};
- my $scfg = &$api_sdn_dns_config($cfg, $id);
- next if $param->{type} && $param->{type} ne $scfg->{type};
+ my $plugin_config = $cfg->{ids}->{$id};
+ my $plugin = PVE::Network::SDN::Dns::Plugin->lookup($plugin_config->{type});
+ push @$res, $scfg;
+ }
- my $plugin_config = $cfg->{ids}->{$id};
- my $plugin = PVE::Network::SDN::Dns::Plugin->lookup($plugin_config->{type});
- push @$res, $scfg;
- }
-
- return $res;
- }});
+ return $res;
+ },
+});
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
name => 'read',
path => '{dns}',
method => 'GET',
description => "Read sdn dns configuration.",
permissions => {
- check => ['perm', '/sdn/dns/{dns}', ['SDN.Allocate']],
- },
+ check => ['perm', '/sdn/dns/{dns}', ['SDN.Allocate']],
+ },
parameters => {
- additionalProperties => 0,
- properties => {
- dns => get_standard_option('pve-sdn-dns-id'),
- },
+ additionalProperties => 0,
+ properties => {
+ dns => get_standard_option('pve-sdn-dns-id'),
+ },
},
returns => { type => 'object' },
code => sub {
- my ($param) = @_;
+ my ($param) = @_;
- my $cfg = PVE::Network::SDN::Dns::config();
+ my $cfg = PVE::Network::SDN::Dns::config();
- return &$api_sdn_dns_config($cfg, $param->{dns});
- }});
+ return &$api_sdn_dns_config($cfg, $param->{dns});
+ },
+});
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
name => 'create',
protected => 1,
path => '',
method => 'POST',
description => "Create a new sdn dns object.",
permissions => {
- check => ['perm', '/sdn/dns', ['SDN.Allocate']],
+ check => ['perm', '/sdn/dns', ['SDN.Allocate']],
},
parameters => PVE::Network::SDN::Dns::Plugin->createSchema(),
returns => { type => 'null' },
code => sub {
- my ($param) = @_;
+ my ($param) = @_;
- my $type = extract_param($param, 'type');
- my $id = extract_param($param, 'dns');
+ my $type = extract_param($param, 'type');
+ my $id = extract_param($param, 'dns');
- my $plugin = PVE::Network::SDN::Dns::Plugin->lookup($type);
- my $opts = $plugin->check_config($id, $param, 1, 1);
+ my $plugin = PVE::Network::SDN::Dns::Plugin->lookup($type);
+ my $opts = $plugin->check_config($id, $param, 1, 1);
# create /etc/pve/sdn directory
PVE::Cluster::check_cfs_quorum();
mkdir("/etc/pve/sdn");
PVE::Network::SDN::lock_sdn_config(
- sub {
+ sub {
- my $dns_cfg = PVE::Network::SDN::Dns::config();
+ my $dns_cfg = PVE::Network::SDN::Dns::config();
- my $scfg = undef;
- if ($scfg = PVE::Network::SDN::Dns::sdn_dns_config($dns_cfg, $id, 1)) {
- die "sdn dns object ID '$id' already defined\n";
- }
+ my $scfg = undef;
+ if ($scfg = PVE::Network::SDN::Dns::sdn_dns_config($dns_cfg, $id, 1)) {
+ die "sdn dns object ID '$id' already defined\n";
+ }
- $dns_cfg->{ids}->{$id} = $opts;
+ $dns_cfg->{ids}->{$id} = $opts;
- my $plugin = PVE::Network::SDN::Dns::Plugin->lookup($opts->{type});
- $plugin->on_update_hook($opts);
+ my $plugin = PVE::Network::SDN::Dns::Plugin->lookup($opts->{type});
+ $plugin->on_update_hook($opts);
- PVE::Network::SDN::Dns::write_config($dns_cfg);
+ PVE::Network::SDN::Dns::write_config($dns_cfg);
- }, "create sdn dns object failed");
+ },
+ "create sdn dns object failed",
+ );
- return undef;
- }});
+ return undef;
+ },
+});
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
name => 'update',
protected => 1,
path => '{dns}',
method => 'PUT',
description => "Update sdn dns object configuration.",
permissions => {
- check => ['perm', '/sdn/dns', ['SDN.Allocate']],
+ check => ['perm', '/sdn/dns', ['SDN.Allocate']],
},
parameters => PVE::Network::SDN::Dns::Plugin->updateSchema(),
returns => { type => 'null' },
code => sub {
- my ($param) = @_;
+ my ($param) = @_;
- my $id = extract_param($param, 'dns');
- my $digest = extract_param($param, 'digest');
- my $delete = extract_param($param, 'delete');
+ my $id = extract_param($param, 'dns');
+ my $digest = extract_param($param, 'digest');
+ my $delete = extract_param($param, 'delete');
PVE::Network::SDN::lock_sdn_config(
- sub {
+ sub {
- my $dns_cfg = PVE::Network::SDN::Dns::config();
+ my $dns_cfg = PVE::Network::SDN::Dns::config();
- PVE::SectionConfig::assert_if_modified($dns_cfg, $digest);
+ PVE::SectionConfig::assert_if_modified($dns_cfg, $digest);
- my $scfg = PVE::Network::SDN::Dns::sdn_dns_config($dns_cfg, $id);
+ my $scfg = PVE::Network::SDN::Dns::sdn_dns_config($dns_cfg, $id);
- my $plugin = PVE::Network::SDN::Dns::Plugin->lookup($scfg->{type});
- my $opts = $plugin->check_config($id, $param, 0, 1);
+ my $plugin = PVE::Network::SDN::Dns::Plugin->lookup($scfg->{type});
+ my $opts = $plugin->check_config($id, $param, 0, 1);
- if ($delete) {
- $delete = [ PVE::Tools::split_list($delete) ];
- my $options = $plugin->private()->{options}->{$scfg->{type}};
- PVE::SectionConfig::delete_from_config($scfg, $options, $opts, $delete);
- }
+ if ($delete) {
+ $delete = [PVE::Tools::split_list($delete)];
+ my $options = $plugin->private()->{options}->{ $scfg->{type} };
+ PVE::SectionConfig::delete_from_config($scfg, $options, $opts, $delete);
+ }
- foreach my $k (%$opts) {
- $scfg->{$k} = $opts->{$k};
- }
+ foreach my $k (%$opts) {
+ $scfg->{$k} = $opts->{$k};
+ }
- $plugin->on_update_hook($scfg);
+ $plugin->on_update_hook($scfg);
- PVE::Network::SDN::Dns::write_config($dns_cfg);
+ PVE::Network::SDN::Dns::write_config($dns_cfg);
- }, "update sdn dns object failed");
+ },
+ "update sdn dns object failed",
+ );
- return undef;
- }});
+ return undef;
+ },
+});
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
name => 'delete',
protected => 1,
path => '{dns}',
method => 'DELETE',
description => "Delete sdn dns object configuration.",
permissions => {
- check => ['perm', '/sdn/dns', ['SDN.Allocate']],
+ check => ['perm', '/sdn/dns', ['SDN.Allocate']],
},
parameters => {
- additionalProperties => 0,
- properties => {
- dns => get_standard_option('pve-sdn-dns-id', {
- completion => \&PVE::Network::SDN::Dns::complete_sdn_dns,
- }),
- },
+ additionalProperties => 0,
+ properties => {
+ dns => get_standard_option(
+ 'pve-sdn-dns-id',
+ {
+ completion => \&PVE::Network::SDN::Dns::complete_sdn_dns,
+ },
+ ),
+ },
},
returns => { type => 'null' },
code => sub {
- my ($param) = @_;
+ my ($param) = @_;
- my $id = extract_param($param, 'dns');
+ my $id = extract_param($param, 'dns');
PVE::Network::SDN::lock_sdn_config(
- sub {
+ sub {
- my $cfg = PVE::Network::SDN::Dns::config();
+ my $cfg = PVE::Network::SDN::Dns::config();
- my $scfg = PVE::Network::SDN::Dns::sdn_dns_config($cfg, $id);
+ my $scfg = PVE::Network::SDN::Dns::sdn_dns_config($cfg, $id);
- my $plugin = PVE::Network::SDN::Dns::Plugin->lookup($scfg->{type});
+ my $plugin = PVE::Network::SDN::Dns::Plugin->lookup($scfg->{type});
- delete $cfg->{ids}->{$id};
- PVE::Network::SDN::Dns::write_config($cfg);
+ delete $cfg->{ids}->{$id};
+ PVE::Network::SDN::Dns::write_config($cfg);
- }, "delete sdn dns object failed");
+ },
+ "delete sdn dns object failed",
+ );
- return undef;
- }});
+ return undef;
+ },
+});
1;
diff --git a/src/PVE/API2/Network/SDN/Ipams.pm b/src/PVE/API2/Network/SDN/Ipams.pm
index 27ead02..e30d28f 100644
--- a/src/PVE/API2/Network/SDN/Ipams.pm
+++ b/src/PVE/API2/Network/SDN/Ipams.pm
@@ -36,302 +36,323 @@ my $api_sdn_ipams_config = sub {
return $scfg;
};
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
name => 'index',
path => '',
method => 'GET',
description => "SDN ipams index.",
permissions => {
- description => "Only list entries where you have 'SDN.Audit' or 'SDN.Allocate' permissions on '/sdn/ipams/<ipam>'",
- user => 'all',
+ description =>
+ "Only list entries where you have 'SDN.Audit' or 'SDN.Allocate' permissions on '/sdn/ipams/<ipam>'",
+ user => 'all',
},
parameters => {
- additionalProperties => 0,
- properties => {
- type => {
- description => "Only list sdn ipams of specific type",
- type => 'string',
- enum => $sdn_ipams_type_enum,
- optional => 1,
- },
- },
+ additionalProperties => 0,
+ properties => {
+ type => {
+ description => "Only list sdn ipams of specific type",
+ type => 'string',
+ enum => $sdn_ipams_type_enum,
+ optional => 1,
+ },
+ },
},
returns => {
- type => 'array',
- items => {
- type => "object",
- properties => { ipam => { type => 'string'},
- type => { type => 'string'},
- },
- },
- links => [ { rel => 'child', href => "{ipam}" } ],
+ type => 'array',
+ items => {
+ type => "object",
+ properties => {
+ ipam => { type => 'string' },
+ type => { type => 'string' },
+ },
+ },
+ links => [{ rel => 'child', href => "{ipam}" }],
},
code => sub {
- my ($param) = @_;
+ my ($param) = @_;
- my $rpcenv = PVE::RPCEnvironment::get();
- my $authuser = $rpcenv->get_user();
+ my $rpcenv = PVE::RPCEnvironment::get();
+ my $authuser = $rpcenv->get_user();
+ my $cfg = PVE::Network::SDN::Ipams::config();
- my $cfg = PVE::Network::SDN::Ipams::config();
+ my @sids = PVE::Network::SDN::Ipams::sdn_ipams_ids($cfg);
+ my $res = [];
+ foreach my $id (@sids) {
+ my $privs = ['SDN.Audit', 'SDN.Allocate'];
+ next if !$rpcenv->check_any($authuser, "/sdn/ipams/$id", $privs, 1);
- my @sids = PVE::Network::SDN::Ipams::sdn_ipams_ids($cfg);
- my $res = [];
- foreach my $id (@sids) {
- my $privs = [ 'SDN.Audit', 'SDN.Allocate' ];
- next if !$rpcenv->check_any($authuser, "/sdn/ipams/$id", $privs, 1);
+ my $scfg = &$api_sdn_ipams_config($cfg, $id);
+ next if $param->{type} && $param->{type} ne $scfg->{type};
- my $scfg = &$api_sdn_ipams_config($cfg, $id);
- next if $param->{type} && $param->{type} ne $scfg->{type};
+ my $plugin_config = $cfg->{ids}->{$id};
+ my $plugin = PVE::Network::SDN::Ipams::Plugin->lookup($plugin_config->{type});
+ push @$res, $scfg;
+ }
- my $plugin_config = $cfg->{ids}->{$id};
- my $plugin = PVE::Network::SDN::Ipams::Plugin->lookup($plugin_config->{type});
- push @$res, $scfg;
- }
-
- return $res;
- }});
+ return $res;
+ },
+});
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
name => 'read',
path => '{ipam}',
method => 'GET',
description => "Read sdn ipam configuration.",
permissions => {
- check => ['perm', '/sdn/ipams/{ipam}', ['SDN.Allocate']],
- },
+ check => ['perm', '/sdn/ipams/{ipam}', ['SDN.Allocate']],
+ },
parameters => {
- additionalProperties => 0,
- properties => {
- ipam => get_standard_option('pve-sdn-ipam-id'),
- },
+ additionalProperties => 0,
+ properties => {
+ ipam => get_standard_option('pve-sdn-ipam-id'),
+ },
},
returns => { type => 'object' },
code => sub {
- my ($param) = @_;
+ my ($param) = @_;
- my $cfg = PVE::Network::SDN::Ipams::config();
+ my $cfg = PVE::Network::SDN::Ipams::config();
- return &$api_sdn_ipams_config($cfg, $param->{ipam});
- }});
+ return &$api_sdn_ipams_config($cfg, $param->{ipam});
+ },
+});
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
name => 'create',
protected => 1,
path => '',
method => 'POST',
description => "Create a new sdn ipam object.",
permissions => {
- check => ['perm', '/sdn/ipams', ['SDN.Allocate']],
+ check => ['perm', '/sdn/ipams', ['SDN.Allocate']],
},
parameters => PVE::Network::SDN::Ipams::Plugin->createSchema(),
returns => { type => 'null' },
code => sub {
- my ($param) = @_;
+ my ($param) = @_;
- my $type = extract_param($param, 'type');
- my $id = extract_param($param, 'ipam');
+ my $type = extract_param($param, 'type');
+ my $id = extract_param($param, 'ipam');
- my $plugin = PVE::Network::SDN::Ipams::Plugin->lookup($type);
- my $opts = $plugin->check_config($id, $param, 1, 1);
+ my $plugin = PVE::Network::SDN::Ipams::Plugin->lookup($type);
+ my $opts = $plugin->check_config($id, $param, 1, 1);
# create /etc/pve/sdn directory
PVE::Cluster::check_cfs_quorum();
mkdir("/etc/pve/sdn");
PVE::Network::SDN::lock_sdn_config(
- sub {
+ sub {
- my $ipam_cfg = PVE::Network::SDN::Ipams::config();
- my $controller_cfg = PVE::Network::SDN::Controllers::config();
+ my $ipam_cfg = PVE::Network::SDN::Ipams::config();
+ my $controller_cfg = PVE::Network::SDN::Controllers::config();
- my $scfg = undef;
- if ($scfg = PVE::Network::SDN::Ipams::sdn_ipams_config($ipam_cfg, $id, 1)) {
- die "sdn ipam object ID '$id' already defined\n";
- }
+ my $scfg = undef;
+ if ($scfg = PVE::Network::SDN::Ipams::sdn_ipams_config($ipam_cfg, $id, 1)) {
+ die "sdn ipam object ID '$id' already defined\n";
+ }
- $ipam_cfg->{ids}->{$id} = $opts;
+ $ipam_cfg->{ids}->{$id} = $opts;
- my $plugin_config = $opts;
- my $plugin = PVE::Network::SDN::Ipams::Plugin->lookup($plugin_config->{type});
- $plugin->on_update_hook($plugin_config);
+ my $plugin_config = $opts;
+ my $plugin = PVE::Network::SDN::Ipams::Plugin->lookup($plugin_config->{type});
+ $plugin->on_update_hook($plugin_config);
- PVE::Network::SDN::Ipams::write_config($ipam_cfg);
+ PVE::Network::SDN::Ipams::write_config($ipam_cfg);
- }, "create sdn ipam object failed");
+ },
+ "create sdn ipam object failed",
+ );
- return undef;
- }});
+ return undef;
+ },
+});
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
name => 'update',
protected => 1,
path => '{ipam}',
method => 'PUT',
description => "Update sdn ipam object configuration.",
permissions => {
- check => ['perm', '/sdn/ipams', ['SDN.Allocate']],
+ check => ['perm', '/sdn/ipams', ['SDN.Allocate']],
},
parameters => PVE::Network::SDN::Ipams::Plugin->updateSchema(),
returns => { type => 'null' },
code => sub {
- my ($param) = @_;
+ my ($param) = @_;
- my $id = extract_param($param, 'ipam');
- my $digest = extract_param($param, 'digest');
- my $delete = extract_param($param, 'delete');
+ my $id = extract_param($param, 'ipam');
+ my $digest = extract_param($param, 'digest');
+ my $delete = extract_param($param, 'delete');
PVE::Network::SDN::lock_sdn_config(
- sub {
+ sub {
- my $ipam_cfg = PVE::Network::SDN::Ipams::config();
+ my $ipam_cfg = PVE::Network::SDN::Ipams::config();
- PVE::SectionConfig::assert_if_modified($ipam_cfg, $digest);
+ PVE::SectionConfig::assert_if_modified($ipam_cfg, $digest);
- my $scfg = PVE::Network::SDN::Ipams::sdn_ipams_config($ipam_cfg, $id);
+ my $scfg = PVE::Network::SDN::Ipams::sdn_ipams_config($ipam_cfg, $id);
- my $plugin = PVE::Network::SDN::Ipams::Plugin->lookup($scfg->{type});
- my $opts = $plugin->check_config($id, $param, 0, 1);
+ my $plugin = PVE::Network::SDN::Ipams::Plugin->lookup($scfg->{type});
+ my $opts = $plugin->check_config($id, $param, 0, 1);
- if ($delete) {
- $delete = [ PVE::Tools::split_list($delete) ];
- my $options = $plugin->private()->{options}->{$scfg->{type}};
- PVE::SectionConfig::delete_from_config($scfg, $options, $opts, $delete);
- }
+ if ($delete) {
+ $delete = [PVE::Tools::split_list($delete)];
+ my $options = $plugin->private()->{options}->{ $scfg->{type} };
+ PVE::SectionConfig::delete_from_config($scfg, $options, $opts, $delete);
+ }
- foreach my $k (%$opts) {
- $scfg->{$k} = $opts->{$k};
- }
+ foreach my $k (%$opts) {
+ $scfg->{$k} = $opts->{$k};
+ }
- $plugin->on_update_hook($scfg);
+ $plugin->on_update_hook($scfg);
- PVE::Network::SDN::Ipams::write_config($ipam_cfg);
+ PVE::Network::SDN::Ipams::write_config($ipam_cfg);
- }, "update sdn ipam object failed");
+ },
+ "update sdn ipam object failed",
+ );
- return undef;
- }});
+ return undef;
+ },
+});
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
name => 'delete',
protected => 1,
path => '{ipam}',
method => 'DELETE',
description => "Delete sdn ipam object configuration.",
permissions => {
- check => ['perm', '/sdn/ipams', ['SDN.Allocate']],
+ check => ['perm', '/sdn/ipams', ['SDN.Allocate']],
},
parameters => {
- additionalProperties => 0,
- properties => {
- ipam => get_standard_option('pve-sdn-ipam-id', {
- completion => \&PVE::Network::SDN::Ipams::complete_sdn_ipams,
- }),
- },
+ additionalProperties => 0,
+ properties => {
+ ipam => get_standard_option(
+ 'pve-sdn-ipam-id',
+ {
+ completion => \&PVE::Network::SDN::Ipams::complete_sdn_ipams,
+ },
+ ),
+ },
},
returns => { type => 'null' },
code => sub {
- my ($param) = @_;
+ my ($param) = @_;
- my $id = extract_param($param, 'ipam');
+ my $id = extract_param($param, 'ipam');
PVE::Network::SDN::lock_sdn_config(
- sub {
+ sub {
- my $cfg = PVE::Network::SDN::Ipams::config();
+ my $cfg = PVE::Network::SDN::Ipams::config();
- my $scfg = PVE::Network::SDN::Ipams::sdn_ipams_config($cfg, $id);
+ my $scfg = PVE::Network::SDN::Ipams::sdn_ipams_config($cfg, $id);
- my $plugin = PVE::Network::SDN::Ipams::Plugin->lookup($scfg->{type});
+ my $plugin = PVE::Network::SDN::Ipams::Plugin->lookup($scfg->{type});
- my $vnet_cfg = PVE::Network::SDN::Vnets::config();
+ my $vnet_cfg = PVE::Network::SDN::Vnets::config();
- delete $cfg->{ids}->{$id};
- PVE::Network::SDN::Ipams::write_config($cfg);
+ delete $cfg->{ids}->{$id};
+ PVE::Network::SDN::Ipams::write_config($cfg);
- }, "delete sdn zone object failed");
+ },
+ "delete sdn zone object failed",
+ );
- return undef;
- }});
+ return undef;
+ },
+});
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
name => 'ipamindex',
path => '{ipam}/status',
method => 'GET',
description => 'List PVE IPAM Entries',
protected => 1,
permissions => {
- description => "Only list entries where you have 'SDN.Audit' or 'SDN.Allocate' permissions on '/sdn/zones/<zone>/<vnet>'",
- user => 'all',
+ description =>
+ "Only list entries where you have 'SDN.Audit' or 'SDN.Allocate' permissions on '/sdn/zones/<zone>/<vnet>'",
+ user => 'all',
},
parameters => {
- additionalProperties => 0,
- properties => {
- ipam => get_standard_option('pve-sdn-ipam-id', {
- completion => \&PVE::Network::SDN::Ipams::complete_sdn_ipams,
- }),
- },
+ additionalProperties => 0,
+ properties => {
+ ipam => get_standard_option(
+ 'pve-sdn-ipam-id',
+ {
+ completion => \&PVE::Network::SDN::Ipams::complete_sdn_ipams,
+ },
+ ),
+ },
},
returns => {
- type => 'array',
+ type => 'array',
},
code => sub {
- my ($param) = @_;
+ my ($param) = @_;
- my $id = extract_param($param, 'ipam');
- die "Currently only PVE IPAM is supported!" if $id ne 'pve';
+ my $id = extract_param($param, 'ipam');
+ die "Currently only PVE IPAM is supported!" if $id ne 'pve';
- my $rpcenv = PVE::RPCEnvironment::get();
- my $authuser = $rpcenv->get_user();
- my $privs = [ 'SDN.Audit', 'SDN.Allocate' ];
+ my $rpcenv = PVE::RPCEnvironment::get();
+ my $authuser = $rpcenv->get_user();
+ my $privs = ['SDN.Audit', 'SDN.Allocate'];
- my $ipam_plugin = PVE::Network::SDN::Ipams::Plugin->lookup('pve');
- my $ipam_db = $ipam_plugin->read_db();
+ my $ipam_plugin = PVE::Network::SDN::Ipams::Plugin->lookup('pve');
+ my $ipam_db = $ipam_plugin->read_db();
- my $result = [];
+ my $result = [];
- for my $zone_id (keys %{$ipam_db->{zones}}) {
- my $zone_config = PVE::Network::SDN::Zones::get_zone($zone_id, 1);
+ for my $zone_id (keys %{ $ipam_db->{zones} }) {
+ my $zone_config = PVE::Network::SDN::Zones::get_zone($zone_id, 1);
next if !$zone_config || $zone_config->{ipam} ne 'pve' || !$zone_config->{dhcp};
- my $zone = $ipam_db->{zones}->{$zone_id};
+ my $zone = $ipam_db->{zones}->{$zone_id};
- my $vnets = PVE::Network::SDN::Zones::get_vnets($zone_id, 1);
+ my $vnets = PVE::Network::SDN::Zones::get_vnets($zone_id, 1);
- for my $subnet_cidr (keys %{$zone->{subnets}}) {
- my $subnet = $zone->{subnets}->{$subnet_cidr};
- my $ip = new NetAddr::IP($subnet_cidr) or die 'Found invalid CIDR in IPAM';
+ for my $subnet_cidr (keys %{ $zone->{subnets} }) {
+ my $subnet = $zone->{subnets}->{$subnet_cidr};
+ my $ip = new NetAddr::IP($subnet_cidr) or die 'Found invalid CIDR in IPAM';
- my $vnet = undef;
- for my $vnet_id (keys %$vnets) {
- eval {
- my ($zone, $subnetid, $subnet_cfg, $ip) = PVE::Network::SDN::Vnets::get_subnet_from_vnet_ip(
- $vnet_id,
- $ip->addr,
- );
+ my $vnet = undef;
+ for my $vnet_id (keys %$vnets) {
+ eval {
+ my ($zone, $subnetid, $subnet_cfg, $ip) =
+ PVE::Network::SDN::Vnets::get_subnet_from_vnet_ip(
+ $vnet_id, $ip->addr,
+ );
- $vnet = $subnet_cfg->{vnet};
- };
+ $vnet = $subnet_cfg->{vnet};
+ };
- last if $vnet;
- }
+ last if $vnet;
+ }
- next if !$vnet || !$rpcenv->check_any($authuser, "/sdn/zones/$zone_id/$vnet", $privs, 1);
+ next
+ if !$vnet
+ || !$rpcenv->check_any($authuser, "/sdn/zones/$zone_id/$vnet", $privs, 1);
- for my $ip (keys %{$subnet->{ips}}) {
- my $entry = $subnet->{ips}->{$ip};
- $entry->{zone} = $zone_id;
- $entry->{subnet} = $subnet_cidr;
- $entry->{ip} = $ip;
- $entry->{vnet} = $vnet;
+ for my $ip (keys %{ $subnet->{ips} }) {
+ my $entry = $subnet->{ips}->{$ip};
+ $entry->{zone} = $zone_id;
+ $entry->{subnet} = $subnet_cidr;
+ $entry->{ip} = $ip;
+ $entry->{vnet} = $vnet;
- push @$result, $entry;
- }
- }
- }
+ push @$result, $entry;
+ }
+ }
+ }
- return $result;
+ return $result;
},
});
diff --git a/src/PVE/API2/Network/SDN/Ips.pm b/src/PVE/API2/Network/SDN/Ips.pm
index 0003b2a..5ff05e7 100644
--- a/src/PVE/API2/Network/SDN/Ips.pm
+++ b/src/PVE/API2/Network/SDN/Ips.pm
@@ -13,130 +13,126 @@ use PVE::RESTHandler;
use base qw(PVE::RESTHandler);
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
name => 'ipdelete',
path => '',
method => 'DELETE',
description => 'Delete IP Mappings in a VNet',
protected => 1,
permissions => {
- check => ['perm', '/sdn/zones/{zone}/{vnet}', [ 'SDN.Allocate' ]],
+ check => ['perm', '/sdn/zones/{zone}/{vnet}', ['SDN.Allocate']],
},
parameters => {
- additionalProperties => 0,
- properties => {
- zone => get_standard_option('pve-sdn-zone-id'),
- vnet => get_standard_option('pve-sdn-vnet-id'),
- mac => get_standard_option('mac-addr'),
- ip => {
- type => 'string',
- format => 'ip',
- description => 'The IP address to delete',
- },
- },
+ additionalProperties => 0,
+ properties => {
+ zone => get_standard_option('pve-sdn-zone-id'),
+ vnet => get_standard_option('pve-sdn-vnet-id'),
+ mac => get_standard_option('mac-addr'),
+ ip => {
+ type => 'string',
+ format => 'ip',
+ description => 'The IP address to delete',
+ },
+ },
},
returns => { type => 'null' },
code => sub {
- my ($param) = @_;
+ my ($param) = @_;
- my $vnet = extract_param($param, 'vnet');
- my $mac = extract_param($param, 'mac');
- my $ip = extract_param($param, 'ip');
+ my $vnet = extract_param($param, 'vnet');
+ my $mac = extract_param($param, 'mac');
+ my $ip = extract_param($param, 'ip');
- eval {
- PVE::Network::SDN::Vnets::del_ip($vnet, $ip, '', $mac);
- };
- die "$@\n" if $@;
+ eval { PVE::Network::SDN::Vnets::del_ip($vnet, $ip, '', $mac); };
+ die "$@\n" if $@;
- return undef;
+ return undef;
},
});
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
name => 'ipcreate',
path => '',
method => 'POST',
description => 'Create IP Mapping in a VNet',
protected => 1,
permissions => {
- check => ['perm', '/sdn/zones/{zone}/{vnet}', [ 'SDN.Allocate' ]],
+ check => ['perm', '/sdn/zones/{zone}/{vnet}', ['SDN.Allocate']],
},
parameters => {
- additionalProperties => 0,
- properties => {
- zone => get_standard_option('pve-sdn-zone-id'),
- vnet => get_standard_option('pve-sdn-vnet-id'),
- mac => get_standard_option('mac-addr'),
- ip => {
- type => 'string',
- format => 'ip',
- description => 'The IP address to associate with the given MAC address',
- },
- },
+ additionalProperties => 0,
+ properties => {
+ zone => get_standard_option('pve-sdn-zone-id'),
+ vnet => get_standard_option('pve-sdn-vnet-id'),
+ mac => get_standard_option('mac-addr'),
+ ip => {
+ type => 'string',
+ format => 'ip',
+ description => 'The IP address to associate with the given MAC address',
+ },
+ },
},
returns => { type => 'null' },
code => sub {
- my ($param) = @_;
+ my ($param) = @_;
- my $vnet = extract_param($param, 'vnet');
- my $mac = extract_param($param, 'mac');
- my $ip = extract_param($param, 'ip');
+ my $vnet = extract_param($param, 'vnet');
+ my $mac = extract_param($param, 'mac');
+ my $ip = extract_param($param, 'ip');
- PVE::Network::SDN::Vnets::add_ip($vnet, $ip, '', $mac, undef);
+ PVE::Network::SDN::Vnets::add_ip($vnet, $ip, '', $mac, undef);
- return undef;
+ return undef;
},
});
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
name => 'ipupdate',
path => '',
method => 'PUT',
description => 'Update IP Mapping in a VNet',
protected => 1,
permissions => {
- check => ['perm', '/sdn/zones/{zone}/{vnet}', [ 'SDN.Allocate' ]],
+ check => ['perm', '/sdn/zones/{zone}/{vnet}', ['SDN.Allocate']],
},
parameters => {
- additionalProperties => 0,
- properties => {
- zone => get_standard_option('pve-sdn-zone-id'),
- vnet => get_standard_option('pve-sdn-vnet-id'),
- vmid => get_standard_option('pve-vmid', {
- optional => 1,
- }),
- mac => get_standard_option('mac-addr'),
- ip => {
- type => 'string',
- format => 'ip',
- description => 'The IP address to associate with the given MAC address',
- },
- },
+ additionalProperties => 0,
+ properties => {
+ zone => get_standard_option('pve-sdn-zone-id'),
+ vnet => get_standard_option('pve-sdn-vnet-id'),
+ vmid => get_standard_option('pve-vmid', {
+ optional => 1,
+ }),
+ mac => get_standard_option('mac-addr'),
+ ip => {
+ type => 'string',
+ format => 'ip',
+ description => 'The IP address to associate with the given MAC address',
+ },
+ },
},
returns => { type => 'null' },
code => sub {
- my ($param) = @_;
+ my ($param) = @_;
- my $vnet = extract_param($param, 'vnet');
- my $mac = extract_param($param, 'mac');
- my $vmid = extract_param($param, 'vmid');
- my $ip = extract_param($param, 'ip');
+ my $vnet = extract_param($param, 'vnet');
+ my $mac = extract_param($param, 'mac');
+ my $vmid = extract_param($param, 'vmid');
+ my $ip = extract_param($param, 'ip');
- my ($old_ip4, $old_ip6) = PVE::Network::SDN::Vnets::get_ips_from_mac($vnet, $mac);
- my $old_ip = (Net::IP::ip_get_version($ip) == 4) ? $old_ip4 : $old_ip6;
+ my ($old_ip4, $old_ip6) = PVE::Network::SDN::Vnets::get_ips_from_mac($vnet, $mac);
+ my $old_ip = (Net::IP::ip_get_version($ip) == 4) ? $old_ip4 : $old_ip6;
- PVE::Network::SDN::Vnets::del_ip($vnet, $old_ip, '', $mac);
+ PVE::Network::SDN::Vnets::del_ip($vnet, $old_ip, '', $mac);
- eval {
- PVE::Network::SDN::Vnets::add_ip($vnet, $ip, '', $mac, $vmid);
- };
- my $error = $@;
+ eval { PVE::Network::SDN::Vnets::add_ip($vnet, $ip, '', $mac, $vmid); };
+ my $error = $@;
- if ($error) {
- PVE::Network::SDN::Vnets::add_ip($vnet, $old_ip, '', $mac, $vmid);
- }
+ if ($error) {
+ PVE::Network::SDN::Vnets::add_ip($vnet, $old_ip, '', $mac, $vmid);
+ }
- die "$error\n" if $error;
- return undef;
+ die "$error\n" if $error;
+ return undef;
},
});
diff --git a/src/PVE/API2/Network/SDN/Subnets.pm b/src/PVE/API2/Network/SDN/Subnets.pm
index 7a4c331..c9f5452 100644
--- a/src/PVE/API2/Network/SDN/Subnets.pm
+++ b/src/PVE/API2/Network/SDN/Subnets.pm
@@ -55,291 +55,309 @@ my $check_vnet_access = sub {
$rpcenv->check_any($authuser, "/sdn/zones/$zoneid/$vnet", $privs);
};
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
name => 'index',
path => '',
method => 'GET',
description => "SDN subnets index.",
permissions => {
- description => "Only list entries where you have 'SDN.Audit' or 'SDN.Allocate' permissions on '/sdn/zones/<zone>/<vnet>'",
- user => 'all',
+ description =>
+ "Only list entries where you have 'SDN.Audit' or 'SDN.Allocate' permissions on '/sdn/zones/<zone>/<vnet>'",
+ user => 'all',
},
parameters => {
- additionalProperties => 0,
- properties => {
- vnet => get_standard_option('pve-sdn-vnet-id'),
- running => {
- type => 'boolean',
- optional => 1,
- description => "Display running config.",
- },
- pending => {
- type => 'boolean',
- optional => 1,
- description => "Display pending config.",
- },
+ additionalProperties => 0,
+ properties => {
+ vnet => get_standard_option('pve-sdn-vnet-id'),
+ running => {
+ type => 'boolean',
+ optional => 1,
+ description => "Display running config.",
+ },
+ pending => {
+ type => 'boolean',
+ optional => 1,
+ description => "Display pending config.",
+ },
},
},
returns => {
- type => 'array',
- items => {
- type => "object",
- properties => {},
- },
- links => [ { rel => 'child', href => "{subnet}" } ],
+ type => 'array',
+ items => {
+ type => "object",
+ properties => {},
+ },
+ links => [{ rel => 'child', href => "{subnet}" }],
},
code => sub {
- my ($param) = @_;
+ my ($param) = @_;
- my $vnetid = $param->{vnet};
- my $privs = [ 'SDN.Audit', 'SDN.Allocate' ];
- &$check_vnet_access($vnetid, $privs);
+ my $vnetid = $param->{vnet};
+ my $privs = ['SDN.Audit', 'SDN.Allocate'];
+ &$check_vnet_access($vnetid, $privs);
my $cfg = {};
- if($param->{pending}) {
- my $running_cfg = PVE::Network::SDN::running_config();
- my $config = PVE::Network::SDN::Subnets::config();
- $cfg = PVE::Network::SDN::pending_config($running_cfg, $config, 'subnets');
+ if ($param->{pending}) {
+ my $running_cfg = PVE::Network::SDN::running_config();
+ my $config = PVE::Network::SDN::Subnets::config();
+ $cfg = PVE::Network::SDN::pending_config($running_cfg, $config, 'subnets');
} elsif ($param->{running}) {
- my $running_cfg = PVE::Network::SDN::running_config();
- $cfg = $running_cfg->{subnets};
+ my $running_cfg = PVE::Network::SDN::running_config();
+ $cfg = $running_cfg->{subnets};
} else {
- $cfg = PVE::Network::SDN::Subnets::config();
+ $cfg = PVE::Network::SDN::Subnets::config();
}
- my @sids = PVE::Network::SDN::Subnets::sdn_subnets_ids($cfg);
- my $res = [];
- foreach my $id (@sids) {
- my $scfg = &$api_sdn_subnets_config($cfg, $id);
- next if !$scfg->{vnet} || $scfg->{vnet} ne $vnetid;
- push @$res, $scfg;
- }
+ my @sids = PVE::Network::SDN::Subnets::sdn_subnets_ids($cfg);
+ my $res = [];
+ foreach my $id (@sids) {
+ my $scfg = &$api_sdn_subnets_config($cfg, $id);
+ next if !$scfg->{vnet} || $scfg->{vnet} ne $vnetid;
+ push @$res, $scfg;
+ }
- return $res;
- }});
+ return $res;
+ },
+});
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
name => 'read',
path => '{subnet}',
method => 'GET',
description => "Read sdn subnet configuration.",
permissions => {
- description => "Require 'SDN.Audit' or 'SDN.Allocate' permissions on '/sdn/zones/<zone>/<vnet>'",
- user => 'all',
+ description =>
+ "Require 'SDN.Audit' or 'SDN.Allocate' permissions on '/sdn/zones/<zone>/<vnet>'",
+ user => 'all',
},
parameters => {
- additionalProperties => 0,
- properties => {
- vnet => get_standard_option('pve-sdn-vnet-id'),
- subnet => get_standard_option('pve-sdn-subnet-id', {
- completion => \&PVE::Network::SDN::Subnets::complete_sdn_subnets,
- }),
- running => {
- type => 'boolean',
- optional => 1,
- description => "Display running config.",
- },
- pending => {
- type => 'boolean',
- optional => 1,
- description => "Display pending config.",
- },
+ additionalProperties => 0,
+ properties => {
+ vnet => get_standard_option('pve-sdn-vnet-id'),
+ subnet => get_standard_option(
+ 'pve-sdn-subnet-id',
+ {
+ completion => \&PVE::Network::SDN::Subnets::complete_sdn_subnets,
+ },
+ ),
+ running => {
+ type => 'boolean',
+ optional => 1,
+ description => "Display running config.",
+ },
+ pending => {
+ type => 'boolean',
+ optional => 1,
+ description => "Display pending config.",
+ },
},
},
returns => { type => 'object' },
code => sub {
- my ($param) = @_;
+ my ($param) = @_;
- my $vnet = extract_param($param, 'vnet');
- my $privs = [ 'SDN.Audit', 'SDN.Allocate' ];
- &$check_vnet_access($vnet, $privs);
+ my $vnet = extract_param($param, 'vnet');
+ my $privs = ['SDN.Audit', 'SDN.Allocate'];
+ &$check_vnet_access($vnet, $privs);
my $cfg = {};
- if($param->{pending}) {
- my $running_cfg = PVE::Network::SDN::running_config();
- my $config = PVE::Network::SDN::Subnets::config();
- $cfg = PVE::Network::SDN::pending_config($running_cfg, $config, 'subnets');
+ if ($param->{pending}) {
+ my $running_cfg = PVE::Network::SDN::running_config();
+ my $config = PVE::Network::SDN::Subnets::config();
+ $cfg = PVE::Network::SDN::pending_config($running_cfg, $config, 'subnets');
} elsif ($param->{running}) {
- my $running_cfg = PVE::Network::SDN::running_config();
- $cfg = $running_cfg->{subnets};
+ my $running_cfg = PVE::Network::SDN::running_config();
+ $cfg = $running_cfg->{subnets};
} else {
- $cfg = PVE::Network::SDN::Subnets::config();
+ $cfg = PVE::Network::SDN::Subnets::config();
}
my $scfg = &$api_sdn_subnets_config($cfg, $param->{subnet});
- raise_param_exc({ vnet => "wrong vnet"}) if $vnet ne $scfg->{vnet};
+ raise_param_exc({ vnet => "wrong vnet" }) if $vnet ne $scfg->{vnet};
- return $scfg;
- }});
+ return $scfg;
+ },
+});
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
name => 'create',
protected => 1,
path => '',
method => 'POST',
description => "Create a new sdn subnet object.",
permissions => {
- description => "Require 'SDN.Allocate' permission on '/sdn/zones/<zone>/<vnet>'",
- user => 'all',
+ description => "Require 'SDN.Allocate' permission on '/sdn/zones/<zone>/<vnet>'",
+ user => 'all',
},
parameters => PVE::Network::SDN::SubnetPlugin->createSchema(),
returns => { type => 'null' },
code => sub {
- my ($param) = @_;
+ my ($param) = @_;
- my $type = extract_param($param, 'type');
- my $cidr = extract_param($param, 'subnet');
+ my $type = extract_param($param, 'type');
+ my $cidr = extract_param($param, 'subnet');
- my $vnet = $param->{vnet};
- my $privs = [ 'SDN.Allocate' ];
- &$check_vnet_access($vnet, $privs);
+ my $vnet = $param->{vnet};
+ my $privs = ['SDN.Allocate'];
+ &$check_vnet_access($vnet, $privs);
- # create /etc/pve/sdn directory
- PVE::Cluster::check_cfs_quorum();
- mkdir("/etc/pve/sdn") if ! -d '/etc/pve/sdn';
+ # create /etc/pve/sdn directory
+ PVE::Cluster::check_cfs_quorum();
+ mkdir("/etc/pve/sdn") if !-d '/etc/pve/sdn';
PVE::Network::SDN::lock_sdn_config(
- sub {
+ sub {
- my $cfg = PVE::Network::SDN::Subnets::config();
- my $zone_cfg = PVE::Network::SDN::Zones::config();
- my $vnet_cfg = PVE::Network::SDN::Vnets::config();
- my $vnet = $param->{vnet};
- my $zoneid = $vnet_cfg->{ids}->{$vnet}->{zone};
- my $zone = $zone_cfg->{ids}->{$zoneid};
- my $id = $cidr =~ s/\//-/r;
- $id = "$zoneid-$id";
-
- my $opts = PVE::Network::SDN::SubnetPlugin->check_config($id, $param, 1, 1);
+ my $cfg = PVE::Network::SDN::Subnets::config();
+ my $zone_cfg = PVE::Network::SDN::Zones::config();
+ my $vnet_cfg = PVE::Network::SDN::Vnets::config();
+ my $vnet = $param->{vnet};
+ my $zoneid = $vnet_cfg->{ids}->{$vnet}->{zone};
+ my $zone = $zone_cfg->{ids}->{$zoneid};
+ my $id = $cidr =~ s/\//-/r;
+ $id = "$zoneid-$id";
- my $scfg = undef;
- if ($scfg = PVE::Network::SDN::Subnets::sdn_subnets_config($cfg, $id, 1)) {
- die "sdn subnet object ID '$id' already defined\n";
- }
+ my $opts = PVE::Network::SDN::SubnetPlugin->check_config($id, $param, 1, 1);
- $cfg->{ids}->{$id} = $opts;
+ my $scfg = undef;
+ if ($scfg = PVE::Network::SDN::Subnets::sdn_subnets_config($cfg, $id, 1)) {
+ die "sdn subnet object ID '$id' already defined\n";
+ }
- my $subnet = PVE::Network::SDN::Subnets::sdn_subnets_config($cfg, $id);
- PVE::Network::SDN::SubnetPlugin->on_update_hook($zone, $id, $subnet);
+ $cfg->{ids}->{$id} = $opts;
- PVE::Network::SDN::Subnets::write_config($cfg);
+ my $subnet = PVE::Network::SDN::Subnets::sdn_subnets_config($cfg, $id);
+ PVE::Network::SDN::SubnetPlugin->on_update_hook($zone, $id, $subnet);
- }, "create sdn subnet object failed");
+ PVE::Network::SDN::Subnets::write_config($cfg);
- return undef;
- }});
+ },
+ "create sdn subnet object failed",
+ );
-__PACKAGE__->register_method ({
+ return undef;
+ },
+});
+
+__PACKAGE__->register_method({
name => 'update',
protected => 1,
path => '{subnet}',
method => 'PUT',
description => "Update sdn subnet object configuration.",
permissions => {
- description => "Require 'SDN.Allocate' permission on '/sdn/zones/<zone>/<vnet>'",
- user => 'all',
+ description => "Require 'SDN.Allocate' permission on '/sdn/zones/<zone>/<vnet>'",
+ user => 'all',
},
parameters => PVE::Network::SDN::SubnetPlugin->updateSchema(),
returns => { type => 'null' },
code => sub {
- my ($param) = @_;
+ my ($param) = @_;
- my $id = extract_param($param, 'subnet');
- my $digest = extract_param($param, 'digest');
- my $delete = extract_param($param, 'delete');
+ my $id = extract_param($param, 'subnet');
+ my $digest = extract_param($param, 'digest');
+ my $delete = extract_param($param, 'delete');
- my $vnet = $param->{vnet};
+ my $vnet = $param->{vnet};
- my $privs = [ 'SDN.Allocate' ];
- &$check_vnet_access($vnet, $privs);
+ my $privs = ['SDN.Allocate'];
+ &$check_vnet_access($vnet, $privs);
PVE::Network::SDN::lock_sdn_config(
- sub {
+ sub {
- my $cfg = PVE::Network::SDN::Subnets::config();
- my $zone_cfg = PVE::Network::SDN::Zones::config();
- my $vnet_cfg = PVE::Network::SDN::Vnets::config();
- my $zoneid = $vnet_cfg->{ids}->{$vnet}->{zone};
- my $zone = $zone_cfg->{ids}->{$zoneid};
+ my $cfg = PVE::Network::SDN::Subnets::config();
+ my $zone_cfg = PVE::Network::SDN::Zones::config();
+ my $vnet_cfg = PVE::Network::SDN::Vnets::config();
+ my $zoneid = $vnet_cfg->{ids}->{$vnet}->{zone};
+ my $zone = $zone_cfg->{ids}->{$zoneid};
- my $scfg = &$api_sdn_subnets_config($cfg, $id);
+ my $scfg = &$api_sdn_subnets_config($cfg, $id);
- PVE::SectionConfig::assert_if_modified($cfg, $digest);
+ PVE::SectionConfig::assert_if_modified($cfg, $digest);
- my $opts = PVE::Network::SDN::SubnetPlugin->check_config($id, $param, 0, 1);
+ my $opts = PVE::Network::SDN::SubnetPlugin->check_config($id, $param, 0, 1);
- my $data = $cfg->{ids}->{$id};
- if ($delete) {
- $delete = [ PVE::Tools::split_list($delete) ];
- my $options =
- PVE::Network::SDN::SubnetPlugin->private()->{options}->{$data->{type}};
- PVE::SectionConfig::delete_from_config($data, $options, $opts, $delete);
- }
- $data->{$_} = $opts->{$_} for keys $opts->%*;
+ my $data = $cfg->{ids}->{$id};
+ if ($delete) {
+ $delete = [PVE::Tools::split_list($delete)];
+ my $options =
+ PVE::Network::SDN::SubnetPlugin->private()->{options}->{ $data->{type} };
+ PVE::SectionConfig::delete_from_config($data, $options, $opts, $delete);
+ }
+ $data->{$_} = $opts->{$_} for keys $opts->%*;
- my $subnet = PVE::Network::SDN::Subnets::sdn_subnets_config($cfg, $id);
- PVE::Network::SDN::SubnetPlugin->on_update_hook($zone, $id, $subnet, $scfg);
+ my $subnet = PVE::Network::SDN::Subnets::sdn_subnets_config($cfg, $id);
+ PVE::Network::SDN::SubnetPlugin->on_update_hook($zone, $id, $subnet, $scfg);
- PVE::Network::SDN::Subnets::write_config($cfg);
+ PVE::Network::SDN::Subnets::write_config($cfg);
- }, "update sdn subnet object failed");
+ },
+ "update sdn subnet object failed",
+ );
- return undef;
- }});
+ return undef;
+ },
+});
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
name => 'delete',
protected => 1,
path => '{subnet}',
method => 'DELETE',
description => "Delete sdn subnet object configuration.",
permissions => {
- description => "Require 'SDN.Allocate' permission on '/sdn/zones/<zone>/<vnet>'",
- user => 'all',
+ description => "Require 'SDN.Allocate' permission on '/sdn/zones/<zone>/<vnet>'",
+ user => 'all',
},
parameters => {
- additionalProperties => 0,
- properties => {
+ additionalProperties => 0,
+ properties => {
vnet => get_standard_option('pve-sdn-vnet-id'),
- subnet => get_standard_option('pve-sdn-subnet-id', {
- completion => \&PVE::Network::SDN::Subnets::complete_sdn_subnets,
- }),
- },
+ subnet => get_standard_option(
+ 'pve-sdn-subnet-id',
+ {
+ completion => \&PVE::Network::SDN::Subnets::complete_sdn_subnets,
+ },
+ ),
+ },
},
returns => { type => 'null' },
code => sub {
- my ($param) = @_;
+ my ($param) = @_;
- my $id = extract_param($param, 'subnet');
- my $vnet = extract_param($param, 'vnet');
- my $privs = [ 'SDN.Allocate' ];
- &$check_vnet_access($vnet, $privs);
+ my $id = extract_param($param, 'subnet');
+ my $vnet = extract_param($param, 'vnet');
+ my $privs = ['SDN.Allocate'];
+ &$check_vnet_access($vnet, $privs);
PVE::Network::SDN::lock_sdn_config(
- sub {
- my $cfg = PVE::Network::SDN::Subnets::config();
-
- my $scfg = PVE::Network::SDN::Subnets::sdn_subnets_config($cfg, $id, 1);
+ sub {
+ my $cfg = PVE::Network::SDN::Subnets::config();
- my $vnets_cfg = PVE::Network::SDN::Vnets::config();
+ my $scfg = PVE::Network::SDN::Subnets::sdn_subnets_config($cfg, $id, 1);
- PVE::Network::SDN::SubnetPlugin->on_delete_hook($id, $cfg, $vnets_cfg);
+ my $vnets_cfg = PVE::Network::SDN::Vnets::config();
- my $zone_cfg = PVE::Network::SDN::Zones::config();
- my $zoneid = $vnets_cfg->{ids}->{$vnet}->{zone};
- my $zone = $zone_cfg->{ids}->{$zoneid};
+ PVE::Network::SDN::SubnetPlugin->on_delete_hook($id, $cfg, $vnets_cfg);
- PVE::Network::SDN::Subnets::del_subnet($zone, $id, $scfg);
+ my $zone_cfg = PVE::Network::SDN::Zones::config();
+ my $zoneid = $vnets_cfg->{ids}->{$vnet}->{zone};
+ my $zone = $zone_cfg->{ids}->{$zoneid};
- delete $cfg->{ids}->{$id};
+ PVE::Network::SDN::Subnets::del_subnet($zone, $id, $scfg);
- PVE::Network::SDN::Subnets::write_config($cfg);
+ delete $cfg->{ids}->{$id};
- }, "delete sdn subnet object failed");
+ PVE::Network::SDN::Subnets::write_config($cfg);
+ },
+ "delete sdn subnet object failed",
+ );
- return undef;
- }});
+ return undef;
+ },
+});
1;
diff --git a/src/PVE/API2/Network/SDN/Vnets.pm b/src/PVE/API2/Network/SDN/Vnets.pm
index e48b048..5608283 100644
--- a/src/PVE/API2/Network/SDN/Vnets.pm
+++ b/src/PVE/API2/Network/SDN/Vnets.pm
@@ -25,17 +25,17 @@ use PVE::RESTHandler;
use base qw(PVE::RESTHandler);
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
subclass => "PVE::API2::Firewall::Vnet",
path => '{vnet}/firewall',
});
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
subclass => "PVE::API2::Network::SDN::Subnets",
path => '{vnet}/subnets',
});
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
subclass => "PVE::API2::Network::SDN::Ips",
path => '{vnet}/ips',
});
@@ -46,7 +46,7 @@ my $api_sdn_vnets_config = sub {
my $scfg = dclone(PVE::Network::SDN::Vnets::sdn_vnets_config($cfg, $id));
$scfg->{vnet} = $id;
$scfg->{digest} = $cfg->{digest};
-
+
return $scfg;
};
@@ -55,10 +55,11 @@ my $api_sdn_vnets_deleted_config = sub {
if (!$cfg->{ids}->{$id}) {
- my $vnet_cfg = dclone(PVE::Network::SDN::Vnets::sdn_vnets_config($running_cfg->{vnets}, $id));
- $vnet_cfg->{state} = "deleted";
- $vnet_cfg->{vnet} = $id;
- return $vnet_cfg;
+ my $vnet_cfg =
+ dclone(PVE::Network::SDN::Vnets::sdn_vnets_config($running_cfg->{vnets}, $id));
+ $vnet_cfg->{state} = "deleted";
+ $vnet_cfg->{vnet} = $id;
+ return $vnet_cfg;
}
};
@@ -73,273 +74,292 @@ my $check_vnet_access = sub {
$rpcenv->check_any($authuser, "/sdn/zones/$zoneid/$vnet", $privs);
};
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
name => 'index',
path => '',
method => 'GET',
description => "SDN vnets index.",
permissions => {
- description => "Only list entries where you have 'SDN.Audit' or 'SDN.Allocate'"
- ." permissions on '/sdn/zones/<zone>/<vnet>'",
- user => 'all',
+ description => "Only list entries where you have 'SDN.Audit' or 'SDN.Allocate'"
+ . " permissions on '/sdn/zones/<zone>/<vnet>'",
+ user => 'all',
},
parameters => {
- additionalProperties => 0,
- properties => {
+ additionalProperties => 0,
+ properties => {
running => {
type => 'boolean',
optional => 1,
description => "Display running config.",
},
- pending => {
- type => 'boolean',
- optional => 1,
- description => "Display pending config.",
- },
- },
+ pending => {
+ type => 'boolean',
+ optional => 1,
+ description => "Display pending config.",
+ },
+ },
},
returns => {
- type => 'array',
- items => {
- type => "object",
- properties => {},
- },
- links => [ { rel => 'child', href => "{vnet}" } ],
+ type => 'array',
+ items => {
+ type => "object",
+ properties => {},
+ },
+ links => [{ rel => 'child', href => "{vnet}" }],
},
code => sub {
- my ($param) = @_;
-
- my $rpcenv = PVE::RPCEnvironment::get();
- my $authuser = $rpcenv->get_user();
-
- my $cfg = {};
- if($param->{pending}) {
- my $running_cfg = PVE::Network::SDN::running_config();
- my $config = PVE::Network::SDN::Vnets::config();
- $cfg = PVE::Network::SDN::pending_config($running_cfg, $config, 'vnets');
- } elsif ($param->{running}) {
- my $running_cfg = PVE::Network::SDN::running_config();
- $cfg = $running_cfg->{vnets};
- } else {
- $cfg = PVE::Network::SDN::Vnets::config();
- }
-
- my @sids = PVE::Network::SDN::Vnets::sdn_vnets_ids($cfg);
- my $res = [];
- foreach my $id (@sids) {
- my $privs = [ 'SDN.Audit', 'SDN.Allocate' ];
- my $scfg = &$api_sdn_vnets_config($cfg, $id);
- my $zoneid = $scfg->{zone} // $scfg->{pending}->{zone};
- next if !$rpcenv->check_any($authuser, "/sdn/zones/$zoneid/$id", $privs, 1);
-
- push @$res, $scfg;
- }
-
- return $res;
- }});
-
-__PACKAGE__->register_method ({
+ my ($param) = @_;
+
+ my $rpcenv = PVE::RPCEnvironment::get();
+ my $authuser = $rpcenv->get_user();
+
+ my $cfg = {};
+ if ($param->{pending}) {
+ my $running_cfg = PVE::Network::SDN::running_config();
+ my $config = PVE::Network::SDN::Vnets::config();
+ $cfg = PVE::Network::SDN::pending_config($running_cfg, $config, 'vnets');
+ } elsif ($param->{running}) {
+ my $running_cfg = PVE::Network::SDN::running_config();
+ $cfg = $running_cfg->{vnets};
+ } else {
+ $cfg = PVE::Network::SDN::Vnets::config();
+ }
+
+ my @sids = PVE::Network::SDN::Vnets::sdn_vnets_ids($cfg);
+ my $res = [];
+ foreach my $id (@sids) {
+ my $privs = ['SDN.Audit', 'SDN.Allocate'];
+ my $scfg = &$api_sdn_vnets_config($cfg, $id);
+ my $zoneid = $scfg->{zone} // $scfg->{pending}->{zone};
+ next if !$rpcenv->check_any($authuser, "/sdn/zones/$zoneid/$id", $privs, 1);
+
+ push @$res, $scfg;
+ }
+
+ return $res;
+ },
+});
+
+__PACKAGE__->register_method({
name => 'read',
path => '{vnet}',
method => 'GET',
description => "Read sdn vnet configuration.",
permissions => {
- description => "Require 'SDN.Audit' or 'SDN.Allocate' permissions on '/sdn/zones/<zone>/<vnet>'",
- user => 'all',
+ description =>
+ "Require 'SDN.Audit' or 'SDN.Allocate' permissions on '/sdn/zones/<zone>/<vnet>'",
+ user => 'all',
},
parameters => {
- additionalProperties => 0,
- properties => {
- vnet => get_standard_option('pve-sdn-vnet-id', {
- completion => \&PVE::Network::SDN::Vnets::complete_sdn_vnets,
- }),
+ additionalProperties => 0,
+ properties => {
+ vnet => get_standard_option(
+ 'pve-sdn-vnet-id',
+ {
+ completion => \&PVE::Network::SDN::Vnets::complete_sdn_vnets,
+ },
+ ),
running => {
type => 'boolean',
optional => 1,
description => "Display running config.",
},
- pending => {
- type => 'boolean',
- optional => 1,
- description => "Display pending config.",
- },
- },
+ pending => {
+ type => 'boolean',
+ optional => 1,
+ description => "Display pending config.",
+ },
+ },
},
returns => { type => 'object' },
code => sub {
- my ($param) = @_;
-
- my $id = extract_param($param, 'vnet');
-
- my $privs = [ 'SDN.Audit', 'SDN.Allocate' ];
- &$check_vnet_access($id, $privs);
-
- my $cfg = {};
- if($param->{pending}) {
- my $running_cfg = PVE::Network::SDN::running_config();
- my $config = PVE::Network::SDN::Vnets::config();
- $cfg = PVE::Network::SDN::pending_config($running_cfg, $config, 'vnets');
- } elsif ($param->{running}) {
- my $running_cfg = PVE::Network::SDN::running_config();
- $cfg = $running_cfg->{vnets};
- } else {
- $cfg = PVE::Network::SDN::Vnets::config();
- }
-
- return $api_sdn_vnets_config->($cfg, $id);
- }});
+ my ($param) = @_;
+
+ my $id = extract_param($param, 'vnet');
+
+ my $privs = ['SDN.Audit', 'SDN.Allocate'];
+ &$check_vnet_access($id, $privs);
+
+ my $cfg = {};
+ if ($param->{pending}) {
+ my $running_cfg = PVE::Network::SDN::running_config();
+ my $config = PVE::Network::SDN::Vnets::config();
+ $cfg = PVE::Network::SDN::pending_config($running_cfg, $config, 'vnets');
+ } elsif ($param->{running}) {
+ my $running_cfg = PVE::Network::SDN::running_config();
+ $cfg = $running_cfg->{vnets};
+ } else {
+ $cfg = PVE::Network::SDN::Vnets::config();
+ }
+
+ return $api_sdn_vnets_config->($cfg, $id);
+ },
+});
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
name => 'create',
protected => 1,
path => '',
method => 'POST',
description => "Create a new sdn vnet object.",
permissions => {
- check => ['perm', '/sdn/zones/{zone}', ['SDN.Allocate']],
+ check => ['perm', '/sdn/zones/{zone}', ['SDN.Allocate']],
},
parameters => PVE::Network::SDN::VnetPlugin->createSchema(),
returns => { type => 'null' },
code => sub {
- my ($param) = @_;
+ my ($param) = @_;
- my $type = extract_param($param, 'type');
- my $id = extract_param($param, 'vnet');
+ my $type = extract_param($param, 'type');
+ my $id = extract_param($param, 'vnet');
- PVE::Cluster::check_cfs_quorum();
- mkdir("/etc/pve/sdn");
+ PVE::Cluster::check_cfs_quorum();
+ mkdir("/etc/pve/sdn");
- PVE::Network::SDN::lock_sdn_config(sub {
- my $cfg = PVE::Network::SDN::Vnets::config();
- my $opts = PVE::Network::SDN::VnetPlugin->check_config($id, $param, 1, 1);
+ PVE::Network::SDN::lock_sdn_config(
+ sub {
+ my $cfg = PVE::Network::SDN::Vnets::config();
+ my $opts = PVE::Network::SDN::VnetPlugin->check_config($id, $param, 1, 1);
- if (PVE::Network::SDN::Vnets::sdn_vnets_config($cfg, $id, 1)) {
- die "sdn vnet object ID '$id' already defined\n";
- }
- $cfg->{ids}->{$id} = $opts;
+ if (PVE::Network::SDN::Vnets::sdn_vnets_config($cfg, $id, 1)) {
+ die "sdn vnet object ID '$id' already defined\n";
+ }
+ $cfg->{ids}->{$id} = $opts;
- my $zone_cfg = PVE::Network::SDN::Zones::config();
- my $zoneid = $cfg->{ids}->{$id}->{zone};
- my $plugin_config = $zone_cfg->{ids}->{$zoneid};
- my $plugin = PVE::Network::SDN::Zones::Plugin->lookup($plugin_config->{type});
- $plugin->vnet_update_hook($cfg, $id, $zone_cfg);
+ my $zone_cfg = PVE::Network::SDN::Zones::config();
+ my $zoneid = $cfg->{ids}->{$id}->{zone};
+ my $plugin_config = $zone_cfg->{ids}->{$zoneid};
+ my $plugin = PVE::Network::SDN::Zones::Plugin->lookup($plugin_config->{type});
+ $plugin->vnet_update_hook($cfg, $id, $zone_cfg);
- PVE::Network::SDN::VnetPlugin->on_update_hook($id, $cfg);
+ PVE::Network::SDN::VnetPlugin->on_update_hook($id, $cfg);
- PVE::Network::SDN::Vnets::write_config($cfg);
+ PVE::Network::SDN::Vnets::write_config($cfg);
- }, "create sdn vnet object failed");
+ },
+ "create sdn vnet object failed",
+ );
- return undef;
- }});
+ return undef;
+ },
+});
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
name => 'update',
protected => 1,
path => '{vnet}',
method => 'PUT',
description => "Update sdn vnet object configuration.",
permissions => {
- description => "Require 'SDN.Allocate' permission on '/sdn/zones/<zone>/<vnet>'",
- user => 'all',
+ description => "Require 'SDN.Allocate' permission on '/sdn/zones/<zone>/<vnet>'",
+ user => 'all',
},
parameters => PVE::Network::SDN::VnetPlugin->updateSchema(),
returns => { type => 'null' },
code => sub {
- my ($param) = @_;
+ my ($param) = @_;
- my $id = extract_param($param, 'vnet');
- my $digest = extract_param($param, 'digest');
- my $delete = extract_param($param, 'delete');
+ my $id = extract_param($param, 'vnet');
+ my $digest = extract_param($param, 'digest');
+ my $delete = extract_param($param, 'delete');
- my $privs = [ 'SDN.Allocate' ];
- &$check_vnet_access($id, $privs);
+ my $privs = ['SDN.Allocate'];
+ &$check_vnet_access($id, $privs);
- if ($delete) {
- $delete = [ PVE::Tools::split_list($delete) ];
- }
+ if ($delete) {
+ $delete = [PVE::Tools::split_list($delete)];
+ }
- PVE::Network::SDN::lock_sdn_config(sub {
- my $cfg = PVE::Network::SDN::Vnets::config();
+ PVE::Network::SDN::lock_sdn_config(
+ sub {
+ my $cfg = PVE::Network::SDN::Vnets::config();
- PVE::SectionConfig::assert_if_modified($cfg, $digest);
+ PVE::SectionConfig::assert_if_modified($cfg, $digest);
- my $opts = PVE::Network::SDN::VnetPlugin->check_config($id, $param, 0, 1);
+ my $opts = PVE::Network::SDN::VnetPlugin->check_config($id, $param, 0, 1);
- my $data = $cfg->{ids}->{$id};
- my $old_zone = $data->{zone};
+ my $data = $cfg->{ids}->{$id};
+ my $old_zone = $data->{zone};
- if ($delete) {
- my $options = PVE::Network::SDN::VnetPlugin->private()->{options}->{$data->{type}};
- PVE::SectionConfig::delete_from_config($data, $options, $opts, $delete);
- }
+ if ($delete) {
+ my $options =
+ PVE::Network::SDN::VnetPlugin->private()->{options}->{ $data->{type} };
+ PVE::SectionConfig::delete_from_config($data, $options, $opts, $delete);
+ }
- $data->{$_} = $opts->{$_} for keys $opts->%*;
+ $data->{$_} = $opts->{$_} for keys $opts->%*;
- my $new_zone = $data->{zone};
- raise_param_exc({ zone => "cannot delete zone"}) if !$new_zone;
- my $subnets = PVE::Network::SDN::Vnets::get_subnets($id);
- raise_param_exc({ zone => "can't change zone if subnets exist"})
- if $subnets && $old_zone ne $new_zone;
+ my $new_zone = $data->{zone};
+ raise_param_exc({ zone => "cannot delete zone" }) if !$new_zone;
+ my $subnets = PVE::Network::SDN::Vnets::get_subnets($id);
+ raise_param_exc({ zone => "can't change zone if subnets exist" })
+ if $subnets && $old_zone ne $new_zone;
- my $zone_cfg = PVE::Network::SDN::Zones::config();
- my $zoneid = $cfg->{ids}->{$id}->{zone};
- my $plugin_config = $zone_cfg->{ids}->{$zoneid};
- my $plugin = PVE::Network::SDN::Zones::Plugin->lookup($plugin_config->{type});
- $plugin->vnet_update_hook($cfg, $id, $zone_cfg);
+ my $zone_cfg = PVE::Network::SDN::Zones::config();
+ my $zoneid = $cfg->{ids}->{$id}->{zone};
+ my $plugin_config = $zone_cfg->{ids}->{$zoneid};
+ my $plugin = PVE::Network::SDN::Zones::Plugin->lookup($plugin_config->{type});
+ $plugin->vnet_update_hook($cfg, $id, $zone_cfg);
- PVE::Network::SDN::VnetPlugin->on_update_hook($id, $cfg);
+ PVE::Network::SDN::VnetPlugin->on_update_hook($id, $cfg);
- PVE::Network::SDN::Vnets::write_config($cfg);
+ PVE::Network::SDN::Vnets::write_config($cfg);
- }, "update sdn vnet object failed");
+ },
+ "update sdn vnet object failed",
+ );
- return undef;
- }
+ return undef;
+ },
});
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
name => 'delete',
protected => 1,
path => '{vnet}',
method => 'DELETE',
description => "Delete sdn vnet object configuration.",
permissions => {
- description => "Require 'SDN.Allocate' permission on '/sdn/zones/<zone>/<vnet>'",
- user => 'all',
+ description => "Require 'SDN.Allocate' permission on '/sdn/zones/<zone>/<vnet>'",
+ user => 'all',
},
parameters => {
- additionalProperties => 0,
- properties => {
- vnet => get_standard_option('pve-sdn-vnet-id', {
- completion => \&PVE::Network::SDN::Vnets::complete_sdn_vnets,
- }),
- },
+ additionalProperties => 0,
+ properties => {
+ vnet => get_standard_option(
+ 'pve-sdn-vnet-id',
+ {
+ completion => \&PVE::Network::SDN::Vnets::complete_sdn_vnets,
+ },
+ ),
+ },
},
returns => { type => 'null' },
code => sub {
- my ($param) = @_;
-
- my $id = extract_param($param, 'vnet');
+ my ($param) = @_;
- my $privs = [ 'SDN.Allocate' ];
- &$check_vnet_access($id, $privs);
+ my $id = extract_param($param, 'vnet');
- PVE::Network::SDN::lock_sdn_config(sub {
- my $cfg = PVE::Network::SDN::Vnets::config();
- my $scfg = PVE::Network::SDN::Vnets::sdn_vnets_config($cfg, $id); # check if exists
- my $vnet_cfg = PVE::Network::SDN::Vnets::config();
+ my $privs = ['SDN.Allocate'];
+ &$check_vnet_access($id, $privs);
- PVE::Network::SDN::VnetPlugin->on_delete_hook($id, $vnet_cfg);
+ PVE::Network::SDN::lock_sdn_config(
+ sub {
+ my $cfg = PVE::Network::SDN::Vnets::config();
+ my $scfg = PVE::Network::SDN::Vnets::sdn_vnets_config($cfg, $id); # check if exists
+ my $vnet_cfg = PVE::Network::SDN::Vnets::config();
- delete $cfg->{ids}->{$id};
- PVE::Network::SDN::Vnets::write_config($cfg);
+ PVE::Network::SDN::VnetPlugin->on_delete_hook($id, $vnet_cfg);
- }, "delete sdn vnet object failed");
+ delete $cfg->{ids}->{$id};
+ PVE::Network::SDN::Vnets::write_config($cfg);
+ },
+ "delete sdn vnet object failed",
+ );
- return undef;
- }
+ return undef;
+ },
});
1;
diff --git a/src/PVE/API2/Network/SDN/Zones.pm b/src/PVE/API2/Network/SDN/Zones.pm
index 2c27983..e53e6e7 100644
--- a/src/PVE/API2/Network/SDN/Zones.pm
+++ b/src/PVE/API2/Network/SDN/Zones.pm
@@ -39,330 +39,362 @@ my $api_sdn_zones_config = sub {
$scfg->{digest} = $cfg->{digest};
if ($scfg->{nodes}) {
- $scfg->{nodes} = PVE::Network::SDN::encode_value($scfg->{type}, 'nodes', $scfg->{nodes});
+ $scfg->{nodes} =
+ PVE::Network::SDN::encode_value($scfg->{type}, 'nodes', $scfg->{nodes});
}
if ($scfg->{exitnodes}) {
- $scfg->{exitnodes} = PVE::Network::SDN::encode_value($scfg->{type}, 'exitnodes', $scfg->{exitnodes});
+ $scfg->{exitnodes} =
+ PVE::Network::SDN::encode_value($scfg->{type}, 'exitnodes', $scfg->{exitnodes});
}
my $pending = $scfg->{pending};
if ($pending->{nodes}) {
- $pending->{nodes} = PVE::Network::SDN::encode_value($scfg->{type}, 'nodes', $pending->{nodes});
+ $pending->{nodes} =
+ PVE::Network::SDN::encode_value($scfg->{type}, 'nodes', $pending->{nodes});
}
if ($pending->{exitnodes}) {
- $pending->{exitnodes} = PVE::Network::SDN::encode_value($scfg->{type}, 'exitnodes', $pending->{exitnodes});
+ $pending->{exitnodes} =
+ PVE::Network::SDN::encode_value($scfg->{type}, 'exitnodes', $pending->{exitnodes});
}
return $scfg;
};
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
name => 'index',
path => '',
method => 'GET',
description => "SDN zones index.",
permissions => {
- description => "Only list entries where you have 'SDN.Audit' or 'SDN.Allocate' permissions on '/sdn/zones/<zone>'",
- user => 'all',
+ description =>
+ "Only list entries where you have 'SDN.Audit' or 'SDN.Allocate' permissions on '/sdn/zones/<zone>'",
+ user => 'all',
},
parameters => {
- additionalProperties => 0,
- properties => {
- type => {
- description => "Only list SDN zones of specific type",
- type => 'string',
- enum => $sdn_zones_type_enum,
- optional => 1,
- },
- running => {
- type => 'boolean',
- optional => 1,
- description => "Display running config.",
- },
- pending => {
- type => 'boolean',
- optional => 1,
- description => "Display pending config.",
- },
- },
+ additionalProperties => 0,
+ properties => {
+ type => {
+ description => "Only list SDN zones of specific type",
+ type => 'string',
+ enum => $sdn_zones_type_enum,
+ optional => 1,
+ },
+ running => {
+ type => 'boolean',
+ optional => 1,
+ description => "Display running config.",
+ },
+ pending => {
+ type => 'boolean',
+ optional => 1,
+ description => "Display pending config.",
+ },
+ },
},
returns => {
- type => 'array',
- items => {
- type => "object",
- properties => { zone => { type => 'string'},
- type => { type => 'string'},
- mtu => { type => 'integer', optional => 1 },
- dns => { type => 'string', optional => 1},
- reversedns => { type => 'string', optional => 1},
- dnszone => { type => 'string', optional => 1},
- ipam => { type => 'string', optional => 1},
- dhcp => { type => 'string', optional => 1},
- pending => { type => 'boolean', optional => 1 },
- state => { type => 'string', optional => 1},
- nodes => { type => 'string', optional => 1},
- },
- },
- links => [ { rel => 'child', href => "{zone}" } ],
+ type => 'array',
+ items => {
+ type => "object",
+ properties => {
+ zone => { type => 'string' },
+ type => { type => 'string' },
+ mtu => { type => 'integer', optional => 1 },
+ dns => { type => 'string', optional => 1 },
+ reversedns => { type => 'string', optional => 1 },
+ dnszone => { type => 'string', optional => 1 },
+ ipam => { type => 'string', optional => 1 },
+ dhcp => { type => 'string', optional => 1 },
+ pending => { type => 'boolean', optional => 1 },
+ state => { type => 'string', optional => 1 },
+ nodes => { type => 'string', optional => 1 },
+ },
+ },
+ links => [{ rel => 'child', href => "{zone}" }],
},
code => sub {
- my ($param) = @_;
+ my ($param) = @_;
- my $rpcenv = PVE::RPCEnvironment::get();
- my $authuser = $rpcenv->get_user();
+ my $rpcenv = PVE::RPCEnvironment::get();
+ my $authuser = $rpcenv->get_user();
- my $cfg = {};
- if ($param->{pending}) {
- my $running_cfg = PVE::Network::SDN::running_config();
- my $config = PVE::Network::SDN::Zones::config();
- $cfg = PVE::Network::SDN::pending_config($running_cfg, $config, 'zones');
+ my $cfg = {};
+ if ($param->{pending}) {
+ my $running_cfg = PVE::Network::SDN::running_config();
+ my $config = PVE::Network::SDN::Zones::config();
+ $cfg = PVE::Network::SDN::pending_config($running_cfg, $config, 'zones');
} elsif ($param->{running}) {
- my $running_cfg = PVE::Network::SDN::running_config();
- $cfg = $running_cfg->{zones};
+ my $running_cfg = PVE::Network::SDN::running_config();
+ $cfg = $running_cfg->{zones};
} else {
- $cfg = PVE::Network::SDN::Zones::config();
+ $cfg = PVE::Network::SDN::Zones::config();
}
- my @sids = PVE::Network::SDN::Zones::sdn_zones_ids($cfg);
- my $res = [];
- for my $id (@sids) {
- my $privs = [ 'SDN.Audit', 'SDN.Allocate' ];
- next if !$rpcenv->check_any($authuser, "/sdn/zones/$id", $privs, 1);
+ my @sids = PVE::Network::SDN::Zones::sdn_zones_ids($cfg);
+ my $res = [];
+ for my $id (@sids) {
+ my $privs = ['SDN.Audit', 'SDN.Allocate'];
+ next if !$rpcenv->check_any($authuser, "/sdn/zones/$id", $privs, 1);
- my $scfg = &$api_sdn_zones_config($cfg, $id);
- next if $param->{type} && $param->{type} ne $scfg->{type};
+ my $scfg = &$api_sdn_zones_config($cfg, $id);
+ next if $param->{type} && $param->{type} ne $scfg->{type};
- my $plugin_config = $cfg->{ids}->{$id};
- my $plugin = PVE::Network::SDN::Zones::Plugin->lookup($plugin_config->{type});
- push @$res, $scfg;
- }
+ my $plugin_config = $cfg->{ids}->{$id};
+ my $plugin = PVE::Network::SDN::Zones::Plugin->lookup($plugin_config->{type});
+ push @$res, $scfg;
+ }
- return $res;
- }});
+ return $res;
+ },
+});
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
name => 'read',
path => '{zone}',
method => 'GET',
description => "Read sdn zone configuration.",
permissions => {
- check => ['perm', '/sdn/zones/{zone}', ['SDN.Allocate']],
- },
+ check => ['perm', '/sdn/zones/{zone}', ['SDN.Allocate']],
+ },
parameters => {
- additionalProperties => 0,
- properties => {
- zone => get_standard_option('pve-sdn-zone-id'),
- running => {
- type => 'boolean',
- optional => 1,
- description => "Display running config.",
- },
- pending => {
- type => 'boolean',
- optional => 1,
- description => "Display pending config.",
- }
- },
+ additionalProperties => 0,
+ properties => {
+ zone => get_standard_option('pve-sdn-zone-id'),
+ running => {
+ type => 'boolean',
+ optional => 1,
+ description => "Display running config.",
+ },
+ pending => {
+ type => 'boolean',
+ optional => 1,
+ description => "Display pending config.",
+ },
+ },
},
returns => { type => 'object' },
code => sub {
- my ($param) = @_;
+ my ($param) = @_;
- my $cfg = {};
- if ($param->{pending}) {
- my $running_cfg = PVE::Network::SDN::running_config();
- my $config = PVE::Network::SDN::Zones::config();
- $cfg = PVE::Network::SDN::pending_config($running_cfg, $config, 'zones');
+ my $cfg = {};
+ if ($param->{pending}) {
+ my $running_cfg = PVE::Network::SDN::running_config();
+ my $config = PVE::Network::SDN::Zones::config();
+ $cfg = PVE::Network::SDN::pending_config($running_cfg, $config, 'zones');
} elsif ($param->{running}) {
- my $running_cfg = PVE::Network::SDN::running_config();
- $cfg = $running_cfg->{zones};
+ my $running_cfg = PVE::Network::SDN::running_config();
+ $cfg = $running_cfg->{zones};
} else {
- $cfg = PVE::Network::SDN::Zones::config();
+ $cfg = PVE::Network::SDN::Zones::config();
}
- return &$api_sdn_zones_config($cfg, $param->{zone});
- }});
+ return &$api_sdn_zones_config($cfg, $param->{zone});
+ },
+});
sub create_etc_interfaces_sdn_dir {
mkdir("/etc/pve/sdn");
}
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
name => 'create',
protected => 1,
path => '',
method => 'POST',
description => "Create a new sdn zone object.",
permissions => {
- check => ['perm', '/sdn/zones', ['SDN.Allocate']],
+ check => ['perm', '/sdn/zones', ['SDN.Allocate']],
},
parameters => PVE::Network::SDN::Zones::Plugin->createSchema(),
returns => { type => 'null' },
code => sub {
- my ($param) = @_;
+ my ($param) = @_;
- my $type = extract_param($param, 'type');
- my $id = extract_param($param, 'zone');
+ my $type = extract_param($param, 'type');
+ my $id = extract_param($param, 'zone');
- my $plugin = PVE::Network::SDN::Zones::Plugin->lookup($type);
- my $opts = $plugin->check_config($id, $param, 1, 1);
+ my $plugin = PVE::Network::SDN::Zones::Plugin->lookup($type);
+ my $opts = $plugin->check_config($id, $param, 1, 1);
- PVE::Cluster::check_cfs_quorum();
- create_etc_interfaces_sdn_dir();
+ PVE::Cluster::check_cfs_quorum();
+ create_etc_interfaces_sdn_dir();
- PVE::Network::SDN::lock_sdn_config(sub {
- my $zone_cfg = PVE::Network::SDN::Zones::config();
- my $controller_cfg = PVE::Network::SDN::Controllers::config();
- my $dns_cfg = PVE::Network::SDN::Dns::config();
+ PVE::Network::SDN::lock_sdn_config(
+ sub {
+ my $zone_cfg = PVE::Network::SDN::Zones::config();
+ my $controller_cfg = PVE::Network::SDN::Controllers::config();
+ my $dns_cfg = PVE::Network::SDN::Dns::config();
- my $scfg = undef;
- if ($scfg = PVE::Network::SDN::Zones::sdn_zones_config($zone_cfg, $id, 1)) {
- die "sdn zone object ID '$id' already defined\n";
- }
+ my $scfg = undef;
+ if ($scfg = PVE::Network::SDN::Zones::sdn_zones_config($zone_cfg, $id, 1)) {
+ die "sdn zone object ID '$id' already defined\n";
+ }
- my $dnsserver = $opts->{dns};
- raise_param_exc({ dns => "$dnsserver don't exist"})
- if $dnsserver && !$dns_cfg->{ids}->{$dnsserver};
+ my $dnsserver = $opts->{dns};
+ raise_param_exc({ dns => "$dnsserver don't exist" })
+ if $dnsserver && !$dns_cfg->{ids}->{$dnsserver};
- my $reversednsserver = $opts->{reversedns};
- raise_param_exc({ reversedns => "$reversednsserver don't exist"})
- if $reversednsserver && !$dns_cfg->{ids}->{$reversednsserver};
+ my $reversednsserver = $opts->{reversedns};
+ raise_param_exc({ reversedns => "$reversednsserver don't exist" })
+ if $reversednsserver && !$dns_cfg->{ids}->{$reversednsserver};
- my $dnszone = $opts->{dnszone};
- raise_param_exc({ dnszone => "missing dns server"})
- if $dnszone && !$dnsserver;
+ my $dnszone = $opts->{dnszone};
+ raise_param_exc({ dnszone => "missing dns server" })
+ if $dnszone && !$dnsserver;
- my $ipam = $opts->{ipam};
- my $ipam_cfg = PVE::Network::SDN::Ipams::config();
- raise_param_exc({ ipam => "$ipam not existing"}) if $ipam && !$ipam_cfg->{ids}->{$ipam};
+ my $ipam = $opts->{ipam};
+ my $ipam_cfg = PVE::Network::SDN::Ipams::config();
+ raise_param_exc({ ipam => "$ipam not existing" })
+ if $ipam && !$ipam_cfg->{ids}->{$ipam};
- $zone_cfg->{ids}->{$id} = $opts;
- $plugin->on_update_hook($id, $zone_cfg, $controller_cfg);
+ $zone_cfg->{ids}->{$id} = $opts;
+ $plugin->on_update_hook($id, $zone_cfg, $controller_cfg);
- PVE::Network::SDN::Zones::write_config($zone_cfg);
+ PVE::Network::SDN::Zones::write_config($zone_cfg);
- }, "create sdn zone object failed");
+ },
+ "create sdn zone object failed",
+ );
- return;
- }});
+ return;
+ },
+});
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
name => 'update',
protected => 1,
path => '{zone}',
method => 'PUT',
description => "Update sdn zone object configuration.",
permissions => {
- check => ['perm', '/sdn/zones/{zone}', ['SDN.Allocate']],
+ check => ['perm', '/sdn/zones/{zone}', ['SDN.Allocate']],
},
parameters => PVE::Network::SDN::Zones::Plugin->updateSchema(),
returns => { type => 'null' },
code => sub {
- my ($param) = @_;
+ my ($param) = @_;
- my $id = extract_param($param, 'zone');
- my $digest = extract_param($param, 'digest');
- my $delete = extract_param($param, 'delete');
+ my $id = extract_param($param, 'zone');
+ my $digest = extract_param($param, 'digest');
+ my $delete = extract_param($param, 'delete');
- if ($delete) {
- $delete = [ PVE::Tools::split_list($delete) ];
- }
+ if ($delete) {
+ $delete = [PVE::Tools::split_list($delete)];
+ }
- PVE::Network::SDN::lock_sdn_config(sub {
- my $zone_cfg = PVE::Network::SDN::Zones::config();
- my $controller_cfg = PVE::Network::SDN::Controllers::config();
- my $dns_cfg = PVE::Network::SDN::Dns::config();
+ PVE::Network::SDN::lock_sdn_config(
+ sub {
+ my $zone_cfg = PVE::Network::SDN::Zones::config();
+ my $controller_cfg = PVE::Network::SDN::Controllers::config();
+ my $dns_cfg = PVE::Network::SDN::Dns::config();
- PVE::SectionConfig::assert_if_modified($zone_cfg, $digest);
+ PVE::SectionConfig::assert_if_modified($zone_cfg, $digest);
- my $scfg = PVE::Network::SDN::Zones::sdn_zones_config($zone_cfg, $id);
+ my $scfg = PVE::Network::SDN::Zones::sdn_zones_config($zone_cfg, $id);
- my $plugin = PVE::Network::SDN::Zones::Plugin->lookup($scfg->{type});
- my $opts = $plugin->check_config($id, $param, 0, 1);
+ my $plugin = PVE::Network::SDN::Zones::Plugin->lookup($scfg->{type});
+ my $opts = $plugin->check_config($id, $param, 0, 1);
- my $old_ipam = $scfg->{ipam};
+ my $old_ipam = $scfg->{ipam};
- if ($delete) {
- my $options = $plugin->private()->{options}->{$scfg->{type}};
- PVE::SectionConfig::delete_from_config($scfg, $options, $opts, $delete);
- }
+ if ($delete) {
+ my $options = $plugin->private()->{options}->{ $scfg->{type} };
+ PVE::SectionConfig::delete_from_config($scfg, $options, $opts, $delete);
+ }
- $scfg->{$_} = $opts->{$_} for keys $opts->%*;
+ $scfg->{$_} = $opts->{$_} for keys $opts->%*;
- my $new_ipam = $scfg->{ipam};
- if (!$new_ipam != !$old_ipam || (($new_ipam//'') ne ($old_ipam//''))) {
- # don't allow ipam change if subnet are defined for now, need to implement resync ipam content
- my $subnets_cfg = PVE::Network::SDN::Subnets::config();
- for my $subnetid (sort keys %{$subnets_cfg->{ids}}) {
- my $subnet = PVE::Network::SDN::Subnets::sdn_subnets_config($subnets_cfg, $subnetid);
- raise_param_exc({ ipam => "can't change ipam if a subnet is already defined in this zone"})
- if $subnet->{zone} eq $id;
- }
- }
+ my $new_ipam = $scfg->{ipam};
+ if (!$new_ipam != !$old_ipam || (($new_ipam // '') ne ($old_ipam // ''))) {
+ # don't allow ipam change if subnet are defined for now, need to implement resync ipam content
+ my $subnets_cfg = PVE::Network::SDN::Subnets::config();
+ for my $subnetid (sort keys %{ $subnets_cfg->{ids} }) {
+ my $subnet =
+ PVE::Network::SDN::Subnets::sdn_subnets_config($subnets_cfg, $subnetid);
+ raise_param_exc(
+ {
+ ipam =>
+ "can't change ipam if a subnet is already defined in this zone",
+ },
+ ) if $subnet->{zone} eq $id;
+ }
+ }
- my $dnsserver = $opts->{dns};
- raise_param_exc({ dns => "$dnsserver don't exist"}) if $dnsserver && !$dns_cfg->{ids}->{$dnsserver};
+ my $dnsserver = $opts->{dns};
+ raise_param_exc({ dns => "$dnsserver don't exist" })
+ if $dnsserver && !$dns_cfg->{ids}->{$dnsserver};
- my $reversednsserver = $opts->{reversedns};
- raise_param_exc({ reversedns => "$reversednsserver don't exist"}) if $reversednsserver && !$dns_cfg->{ids}->{$reversednsserver};
+ my $reversednsserver = $opts->{reversedns};
+ raise_param_exc({ reversedns => "$reversednsserver don't exist" })
+ if $reversednsserver && !$dns_cfg->{ids}->{$reversednsserver};
- my $dnszone = $opts->{dnszone};
- raise_param_exc({ dnszone => "missing dns server"}) if $dnszone && !$dnsserver;
+ my $dnszone = $opts->{dnszone};
+ raise_param_exc({ dnszone => "missing dns server" }) if $dnszone && !$dnsserver;
- my $ipam = $opts->{ipam};
- my $ipam_cfg = PVE::Network::SDN::Ipams::config();
- raise_param_exc({ ipam => "$ipam not existing"}) if $ipam && !$ipam_cfg->{ids}->{$ipam};
+ my $ipam = $opts->{ipam};
+ my $ipam_cfg = PVE::Network::SDN::Ipams::config();
+ raise_param_exc({ ipam => "$ipam not existing" })
+ if $ipam && !$ipam_cfg->{ids}->{$ipam};
- $plugin->on_update_hook($id, $zone_cfg, $controller_cfg);
+ $plugin->on_update_hook($id, $zone_cfg, $controller_cfg);
- PVE::Network::SDN::Zones::write_config($zone_cfg);
+ PVE::Network::SDN::Zones::write_config($zone_cfg);
- }, "update sdn zone object failed");
+ },
+ "update sdn zone object failed",
+ );
- return;
- }});
+ return;
+ },
+});
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
name => 'delete',
protected => 1,
path => '{zone}',
method => 'DELETE',
description => "Delete sdn zone object configuration.",
permissions => {
- check => ['perm', '/sdn/zones/{zone}', ['SDN.Allocate']],
+ check => ['perm', '/sdn/zones/{zone}', ['SDN.Allocate']],
},
parameters => {
- additionalProperties => 0,
- properties => {
- zone => get_standard_option('pve-sdn-zone-id', {
- completion => \&PVE::Network::SDN::Zones::complete_sdn_zones,
- }),
- },
+ additionalProperties => 0,
+ properties => {
+ zone => get_standard_option(
+ 'pve-sdn-zone-id',
+ {
+ completion => \&PVE::Network::SDN::Zones::complete_sdn_zones,
+ },
+ ),
+ },
},
returns => { type => 'null' },
code => sub {
- my ($param) = @_;
+ my ($param) = @_;
- my $id = extract_param($param, 'zone');
+ my $id = extract_param($param, 'zone');
- PVE::Network::SDN::lock_sdn_config(sub {
- my $cfg = PVE::Network::SDN::Zones::config();
- my $scfg = PVE::Network::SDN::Zones::sdn_zones_config($cfg, $id);
+ PVE::Network::SDN::lock_sdn_config(
+ sub {
+ my $cfg = PVE::Network::SDN::Zones::config();
+ my $scfg = PVE::Network::SDN::Zones::sdn_zones_config($cfg, $id);
- my $plugin = PVE::Network::SDN::Zones::Plugin->lookup($scfg->{type});
- my $vnet_cfg = PVE::Network::SDN::Vnets::config();
+ my $plugin = PVE::Network::SDN::Zones::Plugin->lookup($scfg->{type});
+ my $vnet_cfg = PVE::Network::SDN::Vnets::config();
- $plugin->on_delete_hook($id, $vnet_cfg);
+ $plugin->on_delete_hook($id, $vnet_cfg);
- delete $cfg->{ids}->{$id};
+ delete $cfg->{ids}->{$id};
- PVE::Network::SDN::Zones::write_config($cfg);
- }, "delete sdn zone object failed");
+ PVE::Network::SDN::Zones::write_config($cfg);
+ },
+ "delete sdn zone object failed",
+ );
- return;
- }});
+ return;
+ },
+});
1;
diff --git a/src/PVE/API2/Network/SDN/Zones/Content.pm b/src/PVE/API2/Network/SDN/Zones/Content.pm
index 211e71b..7666321 100644
--- a/src/PVE/API2/Network/SDN/Zones/Content.pm
+++ b/src/PVE/API2/Network/SDN/Zones/Content.pm
@@ -14,71 +14,75 @@ use PVE::Network::SDN;
use base qw(PVE::RESTHandler);
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
name => 'index',
path => '',
method => 'GET',
description => "List zone content.",
permissions => {
- check => ['perm', '/sdn/zones/{zone}', ['SDN.Audit'], any => 1],
+ check => ['perm', '/sdn/zones/{zone}', ['SDN.Audit'], any => 1],
},
protected => 1,
proxyto => 'node',
parameters => {
- additionalProperties => 0,
- properties => {
- node => get_standard_option('pve-node'),
- zone => get_standard_option('pve-sdn-zone-id', {
- completion => \&PVE::Network::SDN::Zones::complete_sdn_zone,
- }),
- },
+ additionalProperties => 0,
+ properties => {
+ node => get_standard_option('pve-node'),
+ zone => get_standard_option(
+ 'pve-sdn-zone-id',
+ {
+ completion => \&PVE::Network::SDN::Zones::complete_sdn_zone,
+ },
+ ),
+ },
},
returns => {
- type => 'array',
- items => {
- type => "object",
- properties => {
- vnet => {
- description => "Vnet identifier.",
- type => 'string',
- },
- status => {
- description => "Status.",
- type => 'string',
- optional => 1,
- },
- statusmsg => {
- description => "Status details",
- type => 'string',
- optional => 1,
- },
- },
- },
- links => [ { rel => 'child', href => "{vnet}" } ],
+ type => 'array',
+ items => {
+ type => "object",
+ properties => {
+ vnet => {
+ description => "Vnet identifier.",
+ type => 'string',
+ },
+ status => {
+ description => "Status.",
+ type => 'string',
+ optional => 1,
+ },
+ statusmsg => {
+ description => "Status details",
+ type => 'string',
+ optional => 1,
+ },
+ },
+ },
+ links => [{ rel => 'child', href => "{vnet}" }],
},
code => sub {
- my ($param) = @_;
+ my ($param) = @_;
- my $rpcenv = PVE::RPCEnvironment::get();
+ my $rpcenv = PVE::RPCEnvironment::get();
- my $authuser = $rpcenv->get_user();
+ my $authuser = $rpcenv->get_user();
- my $zoneid = $param->{zone};
+ my $zoneid = $param->{zone};
- my $res = [];
+ my $res = [];
my ($zone_status, $vnet_status) = PVE::Network::SDN::status();
- foreach my $id (keys %{$vnet_status}) {
- if ($vnet_status->{$id}->{zone} eq $zoneid) {
- my $item->{vnet} = $id;
- $item->{status} = $vnet_status->{$id}->{'status'};
- $item->{statusmsg} = $vnet_status->{$id}->{'statusmsg'};
- push @$res,$item;
- }
+ foreach my $id (keys %{$vnet_status}) {
+ if ($vnet_status->{$id}->{zone} eq $zoneid) {
+ my $item->{vnet} = $id;
+ $item->{status} = $vnet_status->{$id}->{'status'};
+ $item->{statusmsg} = $vnet_status->{$id}->{'statusmsg'};
+ push @$res, $item;
+ }
}
- return $res;
- }});
+ return $res;
+ },
+});
1;
diff --git a/src/PVE/API2/Network/SDN/Zones/Status.pm b/src/PVE/API2/Network/SDN/Zones/Status.pm
index 17de68f..4957567 100644
--- a/src/PVE/API2/Network/SDN/Zones/Status.pm
+++ b/src/PVE/API2/Network/SDN/Zones/Status.pm
@@ -16,96 +16,98 @@ use PVE::Exception qw(raise_param_exc);
use base qw(PVE::RESTHandler);
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
subclass => "PVE::API2::Network::SDN::Zones::Content",
path => '{zone}/content',
});
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
name => 'index',
path => '',
method => 'GET',
description => "Get status for all zones.",
permissions => {
- description => "Only list entries where you have 'SDN.Audit'",
- user => 'all',
+ description => "Only list entries where you have 'SDN.Audit'",
+ user => 'all',
},
protected => 1,
proxyto => 'node',
parameters => {
- additionalProperties => 0,
- properties => {
- node => get_standard_option('pve-node')
- },
+ additionalProperties => 0,
+ properties => {
+ node => get_standard_option('pve-node'),
+ },
},
returns => {
- type => 'array',
- items => {
- type => "object",
- properties => {
- zone => get_standard_option('pve-sdn-zone-id'),
- status => {
- description => "Status of zone",
- type => 'string',
- enum => ['available', 'pending', 'error'],
- },
- },
- },
- links => [ { rel => 'child', href => "{zone}" } ],
+ type => 'array',
+ items => {
+ type => "object",
+ properties => {
+ zone => get_standard_option('pve-sdn-zone-id'),
+ status => {
+ description => "Status of zone",
+ type => 'string',
+ enum => ['available', 'pending', 'error'],
+ },
+ },
+ },
+ links => [{ rel => 'child', href => "{zone}" }],
},
code => sub {
- my ($param) = @_;
+ my ($param) = @_;
- my $rpcenv = PVE::RPCEnvironment::get();
- my $authuser = $rpcenv->get_user();
+ my $rpcenv = PVE::RPCEnvironment::get();
+ my $authuser = $rpcenv->get_user();
- my $localnode = PVE::INotify::nodename();
+ my $localnode = PVE::INotify::nodename();
- my $res = [];
+ my $res = [];
- my ($zone_status, $vnet_status) = PVE::Network::SDN::status();
+ my ($zone_status, $vnet_status) = PVE::Network::SDN::status();
- foreach my $id (sort keys %{$zone_status}) {
- my $item->{zone} = $id;
- $item->{status} = $zone_status->{$id}->{'status'};
- push @$res, $item;
- }
+ foreach my $id (sort keys %{$zone_status}) {
+ my $item->{zone} = $id;
+ $item->{status} = $zone_status->{$id}->{'status'};
+ push @$res, $item;
+ }
- return $res;
- }});
+ return $res;
+ },
+});
-__PACKAGE__->register_method ({
+__PACKAGE__->register_method({
name => 'diridx',
path => '{zone}',
method => 'GET',
description => "",
permissions => {
- check => ['perm', '/sdn/zones/{zone}', ['SDN.Audit'], any => 1],
+ check => ['perm', '/sdn/zones/{zone}', ['SDN.Audit'], any => 1],
},
parameters => {
- additionalProperties => 0,
- properties => {
- node => get_standard_option('pve-node'),
- zone => get_standard_option('pve-sdn-zone-id'),
- },
+ additionalProperties => 0,
+ properties => {
+ node => get_standard_option('pve-node'),
+ zone => get_standard_option('pve-sdn-zone-id'),
+ },
},
returns => {
- type => 'array',
- items => {
- type => "object",
- properties => {
- subdir => { type => 'string' },
- },
- },
- links => [ { rel => 'child', href => "{subdir}" } ],
+ type => 'array',
+ items => {
+ type => "object",
+ properties => {
+ subdir => { type => 'string' },
+ },
+ },
+ links => [{ rel => 'child', href => "{subdir}" }],
},
code => sub {
- my ($param) = @_;
- my $res = [
- { subdir => 'content' },
- ];
+ my ($param) = @_;
+ my $res = [
+ { subdir => 'content' },
+ ];
- return $res;
- }});
+ return $res;
+ },
+});
1;
diff --git a/src/PVE/Network/SDN.pm b/src/PVE/Network/SDN.pm
index 68f9e0f..ef938c4 100644
--- a/src/PVE/Network/SDN.pm
+++ b/src/PVE/Network/SDN.pm
@@ -30,9 +30,7 @@ my $parse_running_cfg = sub {
return $cfg if !defined($raw) || $raw eq '';
- eval {
- $cfg = from_json($raw);
- };
+ eval { $cfg = from_json($raw); };
return {} if $@;
return $cfg;
@@ -48,30 +46,27 @@ my $write_running_cfg = sub {
PVE::Cluster::cfs_register_file($running_cfg, $parse_running_cfg, $write_running_cfg);
-
# improve me : move status code inside plugins ?
sub ifquery_check {
- my $cmd = ['ifquery', '-a', '-c', '-o','json'];
+ my $cmd = ['ifquery', '-a', '-c', '-o', 'json'];
my $result = '';
my $reader = sub { $result .= shift };
- eval {
- run_command($cmd, outfunc => $reader);
- };
+ eval { run_command($cmd, outfunc => $reader); };
my $resultjson = decode_json($result);
my $interfaces = {};
foreach my $interface (@$resultjson) {
- my $name = $interface->{name};
- $interfaces->{$name} = {
- status => $interface->{status},
- config => $interface->{config},
- config_status => $interface->{config_status},
- };
+ my $name = $interface->{name};
+ $interfaces->{$name} = {
+ status => $interface->{status},
+ config => $interface->{config},
+ config_status => $interface->{config_status},
+ };
}
return $interfaces;
@@ -80,7 +75,7 @@ sub ifquery_check {
sub status {
my ($zone_status, $vnet_status) = PVE::Network::SDN::Zones::status();
- return($zone_status, $vnet_status);
+ return ($zone_status, $vnet_status);
}
sub running_config {
@@ -96,45 +91,50 @@ sub pending_config {
my $config_objects = $cfg->{ids};
foreach my $id (sort keys %{$running_objects}) {
- my $running_object = $running_objects->{$id};
- my $config_object = $config_objects->{$id};
- foreach my $key (sort keys %{$running_object}) {
- $pending->{$id}->{$key} = $running_object->{$key};
- if(!keys %{$config_object}) {
- $pending->{$id}->{state} = "deleted";
- } elsif (!defined($config_object->{$key})) {
- $pending->{$id}->{"pending"}->{$key} = 'deleted';
- $pending->{$id}->{state} = "changed";
- } elsif (PVE::Network::SDN::encode_value(undef, $key, $running_object->{$key})
- ne PVE::Network::SDN::encode_value(undef, $key, $config_object->{$key})) {
- $pending->{$id}->{state} = "changed";
- }
- }
- $pending->{$id}->{"pending"} = {} if $pending->{$id}->{state} && !defined($pending->{$id}->{"pending"});
+ my $running_object = $running_objects->{$id};
+ my $config_object = $config_objects->{$id};
+ foreach my $key (sort keys %{$running_object}) {
+ $pending->{$id}->{$key} = $running_object->{$key};
+ if (!keys %{$config_object}) {
+ $pending->{$id}->{state} = "deleted";
+ } elsif (!defined($config_object->{$key})) {
+ $pending->{$id}->{"pending"}->{$key} = 'deleted';
+ $pending->{$id}->{state} = "changed";
+ } elsif (PVE::Network::SDN::encode_value(undef, $key, $running_object->{$key}) ne
+ PVE::Network::SDN::encode_value(undef, $key, $config_object->{$key})
+ ) {
+ $pending->{$id}->{state} = "changed";
+ }
+ }
+ $pending->{$id}->{"pending"} = {}
+ if $pending->{$id}->{state} && !defined($pending->{$id}->{"pending"});
}
- foreach my $id (sort keys %{$config_objects}) {
- my $running_object = $running_objects->{$id};
- my $config_object = $config_objects->{$id};
-
- foreach my $key (sort keys %{$config_object}) {
- my $config_value = PVE::Network::SDN::encode_value(undef, $key, $config_object->{$key});
- my $running_value = PVE::Network::SDN::encode_value(undef, $key, $running_object->{$key});
- if($key eq 'type' || $key eq 'vnet') {
- $pending->{$id}->{$key} = $config_value;
- } else {
- $pending->{$id}->{"pending"}->{$key} = $config_value if !defined($running_value) || ($config_value ne $running_value);
- }
- if(!keys %{$running_object}) {
- $pending->{$id}->{state} = "new";
- } elsif (!defined($running_value) && defined($config_value)) {
- $pending->{$id}->{state} = "changed";
- }
- }
- $pending->{$id}->{"pending"} = {} if $pending->{$id}->{state} && !defined($pending->{$id}->{"pending"});
- }
-
- return {ids => $pending};
+ foreach my $id (sort keys %{$config_objects}) {
+ my $running_object = $running_objects->{$id};
+ my $config_object = $config_objects->{$id};
+
+ foreach my $key (sort keys %{$config_object}) {
+ my $config_value = PVE::Network::SDN::encode_value(undef, $key, $config_object->{$key});
+ my $running_value =
+ PVE::Network::SDN::encode_value(undef, $key, $running_object->{$key});
+ if ($key eq 'type' || $key eq 'vnet') {
+ $pending->{$id}->{$key} = $config_value;
+ } else {
+ $pending->{$id}->{"pending"}->{$key} = $config_value
+ if !defined($running_value) || ($config_value ne $running_value);
+ }
+ if (!keys %{$running_object}) {
+ $pending->{$id}->{state} = "new";
+ } elsif (!defined($running_value) && defined($config_value)) {
+ $pending->{$id}->{state} = "changed";
+ }
+ }
+ $pending->{$id}->{"pending"} = {}
+ if $pending->{$id}->{state} && !defined($pending->{$id}->{"pending"});
+ }
+
+ return { ids => $pending };
}
@@ -144,9 +144,9 @@ sub commit_config {
my $version = $cfg->{version};
if ($version) {
- $version++;
+ $version++;
} else {
- $version = 1;
+ $version = 1;
}
my $vnets_cfg = PVE::Network::SDN::Vnets::config();
@@ -159,7 +159,13 @@ sub commit_config {
my $controllers = { ids => $controllers_cfg->{ids} };
my $subnets = { ids => $subnets_cfg->{ids} };
- $cfg = { version => $version, vnets => $vnets, zones => $zones, controllers => $controllers, subnets => $subnets };
+ $cfg = {
+ version => $version,
+ vnets => $vnets,
+ zones => $zones,
+ controllers => $controllers,
+ subnets => $subnets,
+ };
cfs_write_file($running_cfg, $cfg);
}
@@ -192,21 +198,27 @@ sub get_local_vnets {
foreach my $vnetid (@vnetids) {
- my $vnet = PVE::Network::SDN::Vnets::sdn_vnets_config($vnets_cfg, $vnetid);
- my $zoneid = $vnet->{zone};
- my $comments = $vnet->{alias};
+ my $vnet = PVE::Network::SDN::Vnets::sdn_vnets_config($vnets_cfg, $vnetid);
+ my $zoneid = $vnet->{zone};
+ my $comments = $vnet->{alias};
- my $privs = [ 'SDN.Audit', 'SDN.Use' ];
+ my $privs = ['SDN.Audit', 'SDN.Use'];
- next if !$zoneid;
- next if !$rpcenv->check_sdn_bridge($authuser, $zoneid, $vnetid, $privs, 1);
+ next if !$zoneid;
+ next if !$rpcenv->check_sdn_bridge($authuser, $zoneid, $vnetid, $privs, 1);
- my $zone_config = PVE::Network::SDN::Zones::sdn_zones_config($zones_cfg, $zoneid);
+ my $zone_config = PVE::Network::SDN::Zones::sdn_zones_config($zones_cfg, $zoneid);
- next if defined($zone_config->{nodes}) && !$zone_config->{nodes}->{$nodename};
- my $ipam = $zone_config->{ipam} ? 1 : 0;
- my $vlanaware = $vnet->{vlanaware} ? 1 : 0;
- $vnets->{$vnetid} = { type => 'vnet', active => '1', ipam => $ipam, vlanaware => $vlanaware, comments => $comments };
+ next if defined($zone_config->{nodes}) && !$zone_config->{nodes}->{$nodename};
+ my $ipam = $zone_config->{ipam} ? 1 : 0;
+ my $vlanaware = $vnet->{vlanaware} ? 1 : 0;
+ $vnets->{$vnetid} = {
+ type => 'vnet',
+ active => '1',
+ ipam => $ipam,
+ vlanaware => $vlanaware,
+ comments => $comments,
+ };
}
return $vnets;
@@ -215,13 +227,14 @@ sub get_local_vnets {
sub generate_zone_config {
my $raw_config = PVE::Network::SDN::Zones::generate_etc_network_config();
if ($raw_config) {
- eval {
- my $net_cfg = PVE::INotify::read_file('interfaces', 1);
- my $opts = $net_cfg->{data}->{options};
- log_warn("missing 'source /etc/network/interfaces.d/sdn' directive for SDN support!\n")
- if ! grep { $_->[1] =~ m!^source /etc/network/interfaces.d/(:?sdn|\*)! } @$opts;
- };
- log_warn("Failed to read network interfaces definition - $@") if $@;
+ eval {
+ my $net_cfg = PVE::INotify::read_file('interfaces', 1);
+ my $opts = $net_cfg->{data}->{options};
+ log_warn(
+ "missing 'source /etc/network/interfaces.d/sdn' directive for SDN support!\n")
+ if !grep { $_->[1] =~ m!^source /etc/network/interfaces.d/(:?sdn|\*)! } @$opts;
+ };
+ log_warn("Failed to read network interfaces definition - $@") if $@;
}
PVE::Network::SDN::Zones::write_etc_network_config($raw_config);
}
@@ -245,67 +258,66 @@ sub encode_value {
my ($type, $key, $value) = @_;
if ($key eq 'nodes' || $key eq 'exitnodes' || $key eq 'dhcp-range') {
- if (ref($value) eq 'HASH') {
- return join(',', sort keys(%$value));
- } elsif (ref($value) eq 'ARRAY') {
- return join(',', sort @$value);
- } else {
- return $value;
- }
+ if (ref($value) eq 'HASH') {
+ return join(',', sort keys(%$value));
+ } elsif (ref($value) eq 'ARRAY') {
+ return join(',', sort @$value);
+ } else {
+ return $value;
+ }
}
return $value;
}
-
#helpers
sub api_request {
my ($method, $url, $headers, $data, $expected_fingerprint) = @_;
my $encoded_data = $data ? to_json($data) : undef;
- my $req = HTTP::Request->new($method,$url, $headers, $encoded_data);
+ my $req = HTTP::Request->new($method, $url, $headers, $encoded_data);
my $ua = LWP::UserAgent->new(protocols_allowed => ['http', 'https'], timeout => 30);
my $datacenter_cfg = PVE::Cluster::cfs_read_file('datacenter.cfg');
if (my $proxy = $datacenter_cfg->{http_proxy}) {
- $ua->proxy(['http', 'https'], $proxy);
+ $ua->proxy(['http', 'https'], $proxy);
} else {
- $ua->env_proxy;
+ $ua->env_proxy;
}
if (defined($expected_fingerprint)) {
- my $ssl_verify_callback = sub {
- my (undef, undef, undef, undef, $cert, $depth) = @_;
-
- # we don't care about intermediate or root certificates, always return as valid as the
- # callback will be executed for all levels and all must be valid.
- return 1 if $depth != 0;
-
- my $fingerprint = Net::SSLeay::X509_get_fingerprint($cert, 'sha256');
-
- return $fingerprint eq $expected_fingerprint ? 1 : 0;
- };
- $ua->ssl_opts(
- verify_hostname => 0,
- SSL_verify_mode => SSL_VERIFY_PEER,
- SSL_verify_callback => $ssl_verify_callback,
- );
+ my $ssl_verify_callback = sub {
+ my (undef, undef, undef, undef, $cert, $depth) = @_;
+
+ # we don't care about intermediate or root certificates, always return as valid as the
+ # callback will be executed for all levels and all must be valid.
+ return 1 if $depth != 0;
+
+ my $fingerprint = Net::SSLeay::X509_get_fingerprint($cert, 'sha256');
+
+ return $fingerprint eq $expected_fingerprint ? 1 : 0;
+ };
+ $ua->ssl_opts(
+ verify_hostname => 0,
+ SSL_verify_mode => SSL_VERIFY_PEER,
+ SSL_verify_callback => $ssl_verify_callback,
+ );
}
my $response = $ua->request($req);
if (!$response->is_success) {
- my $msg = $response->message || 'unknown';
- my $code = $response->code;
- die "Invalid response from server: $code $msg\n";
+ my $msg = $response->message || 'unknown';
+ my $code = $response->code;
+ die "Invalid response from server: $code $msg\n";
}
my $raw = '';
if (defined($response->decoded_content)) {
- $raw = $response->decoded_content;
+ $raw = $response->decoded_content;
} else {
- $raw = $response->content;
+ $raw = $response->content;
}
return if $raw eq '';
diff --git a/src/PVE/Network/SDN/Controllers.pm b/src/PVE/Network/SDN/Controllers.pm
index 9e8f3aa..6024f22 100644
--- a/src/PVE/Network/SDN/Controllers.pm
+++ b/src/PVE/Network/SDN/Controllers.pm
@@ -22,7 +22,6 @@ PVE::Network::SDN::Controllers::IsisPlugin->register();
PVE::Network::SDN::Controllers::FaucetPlugin->register();
PVE::Network::SDN::Controllers::Plugin->init();
-
sub sdn_controllers_config {
my ($cfg, $id, $noerr) = @_;
@@ -36,7 +35,7 @@ sub sdn_controllers_config {
sub config {
my $config = cfs_read_file("sdn/controllers.cfg");
- $config = cfs_read_file("sdn/controllers.cfg") if !keys %{$config->{ids}};
+ $config = cfs_read_file("sdn/controllers.cfg") if !keys %{ $config->{ids} };
return $config;
}
@@ -58,7 +57,7 @@ sub lock_sdn_controllers_config {
sub sdn_controllers_ids {
my ($cfg) = @_;
- return sort keys %{$cfg->{ids}};
+ return sort keys %{ $cfg->{ids} };
}
sub complete_sdn_controller {
@@ -66,13 +65,14 @@ sub complete_sdn_controller {
my $cfg = PVE::Network::SDN::running_config();
- return $cmdname eq 'add' ? [] : [ PVE::Network::SDN::sdn_controllers_ids($cfg) ];
+ return $cmdname eq 'add' ? [] : [PVE::Network::SDN::sdn_controllers_ids($cfg)];
}
sub read_etc_network_interfaces {
# read main config for physical interfaces
my $current_config_file = "/etc/network/interfaces";
- my $fh = IO::File->new($current_config_file) or die "failed to open $current_config_file - $!\n";
+ my $fh = IO::File->new($current_config_file)
+ or die "failed to open $current_config_file - $!\n";
my $interfaces_config = PVE::INotify::read_etc_network_interfaces($current_config_file, $fh);
$fh->close();
@@ -92,54 +92,62 @@ sub generate_controller_config {
# check uplinks
my $uplinks = {};
- foreach my $id (keys %{$interfaces_config->{ifaces}}) {
- my $interface = $interfaces_config->{ifaces}->{$id};
- if (my $uplink = $interface->{'uplink-id'}) {
- die "uplink-id $uplink is already defined on $uplinks->{$uplink}" if $uplinks->{$uplink};
- $interface->{name} = $id;
- $uplinks->{$interface->{'uplink-id'}} = $interface;
- }
+ foreach my $id (keys %{ $interfaces_config->{ifaces} }) {
+ my $interface = $interfaces_config->{ifaces}->{$id};
+ if (my $uplink = $interface->{'uplink-id'}) {
+ die "uplink-id $uplink is already defined on $uplinks->{$uplink}"
+ if $uplinks->{$uplink};
+ $interface->{name} = $id;
+ $uplinks->{ $interface->{'uplink-id'} } = $interface;
+ }
}
# generate configuration
my $config = {};
- foreach my $id (sort keys %{$controller_cfg->{ids}}) {
- my $plugin_config = $controller_cfg->{ids}->{$id};
- my $plugin = PVE::Network::SDN::Controllers::Plugin->lookup($plugin_config->{type});
- $plugin->generate_controller_config($plugin_config, $controller_cfg, $id, $uplinks, $config);
+ foreach my $id (sort keys %{ $controller_cfg->{ids} }) {
+ my $plugin_config = $controller_cfg->{ids}->{$id};
+ my $plugin = PVE::Network::SDN::Controllers::Plugin->lookup($plugin_config->{type});
+ $plugin->generate_controller_config($plugin_config, $controller_cfg, $id, $uplinks,
+ $config);
}
- foreach my $id (sort keys %{$zone_cfg->{ids}}) {
- my $plugin_config = $zone_cfg->{ids}->{$id};
- my $controllerid = $plugin_config->{controller};
- next if !$controllerid;
- my $controller = $controller_cfg->{ids}->{$controllerid};
- if ($controller) {
- my $controller_plugin = PVE::Network::SDN::Controllers::Plugin->lookup($controller->{type});
- $controller_plugin->generate_controller_zone_config($plugin_config, $controller, $controller_cfg, $id, $uplinks, $config);
- }
+ foreach my $id (sort keys %{ $zone_cfg->{ids} }) {
+ my $plugin_config = $zone_cfg->{ids}->{$id};
+ my $controllerid = $plugin_config->{controller};
+ next if !$controllerid;
+ my $controller = $controller_cfg->{ids}->{$controllerid};
+ if ($controller) {
+ my $controller_plugin =
+ PVE::Network::SDN::Controllers::Plugin->lookup($controller->{type});
+ $controller_plugin->generate_controller_zone_config(
+ $plugin_config, $controller, $controller_cfg, $id, $uplinks, $config,
+ );
+ }
}
- foreach my $id (sort keys %{$vnet_cfg->{ids}}) {
- my $plugin_config = $vnet_cfg->{ids}->{$id};
- my $zoneid = $plugin_config->{zone};
- next if !$zoneid;
- my $zone = $zone_cfg->{ids}->{$zoneid};
- next if !$zone;
- my $controllerid = $zone->{controller};
- next if !$controllerid;
- my $controller = $controller_cfg->{ids}->{$controllerid};
- if ($controller) {
- my $controller_plugin = PVE::Network::SDN::Controllers::Plugin->lookup($controller->{type});
- $controller_plugin->generate_controller_vnet_config($plugin_config, $controller, $zone, $zoneid, $id, $config);
- }
+ foreach my $id (sort keys %{ $vnet_cfg->{ids} }) {
+ my $plugin_config = $vnet_cfg->{ids}->{$id};
+ my $zoneid = $plugin_config->{zone};
+ next if !$zoneid;
+ my $zone = $zone_cfg->{ids}->{$zoneid};
+ next if !$zone;
+ my $controllerid = $zone->{controller};
+ next if !$controllerid;
+ my $controller = $controller_cfg->{ids}->{$controllerid};
+
+ if ($controller) {
+ my $controller_plugin =
+ PVE::Network::SDN::Controllers::Plugin->lookup($controller->{type});
+ $controller_plugin->generate_controller_vnet_config(
+ $plugin_config, $controller, $zone, $zoneid, $id, $config,
+ );
+ }
}
return $config;
}
-
sub reload_controller {
my $cfg = PVE::Network::SDN::running_config();
@@ -147,10 +155,10 @@ sub reload_controller {
return if !$controller_cfg;
- foreach my $id (keys %{$controller_cfg->{ids}}) {
- my $plugin_config = $controller_cfg->{ids}->{$id};
- my $plugin = PVE::Network::SDN::Controllers::Plugin->lookup($plugin_config->{type});
- $plugin->reload_controller();
+ foreach my $id (keys %{ $controller_cfg->{ids} }) {
+ my $plugin_config = $controller_cfg->{ids}->{$id};
+ my $plugin = PVE::Network::SDN::Controllers::Plugin->lookup($plugin_config->{type});
+ $plugin->reload_controller();
}
}
@@ -162,10 +170,10 @@ sub generate_controller_rawconfig {
return if !$controller_cfg;
my $rawconfig = "";
- foreach my $id (keys %{$controller_cfg->{ids}}) {
- my $plugin_config = $controller_cfg->{ids}->{$id};
- my $plugin = PVE::Network::SDN::Controllers::Plugin->lookup($plugin_config->{type});
- $rawconfig .= $plugin->generate_controller_rawconfig($plugin_config, $config);
+ foreach my $id (keys %{ $controller_cfg->{ids} }) {
+ my $plugin_config = $controller_cfg->{ids}->{$id};
+ my $plugin = PVE::Network::SDN::Controllers::Plugin->lookup($plugin_config->{type});
+ $rawconfig .= $plugin->generate_controller_rawconfig($plugin_config, $config);
}
return $rawconfig;
}
@@ -177,10 +185,10 @@ sub write_controller_config {
my $controller_cfg = $cfg->{controllers};
return if !$controller_cfg;
- foreach my $id (keys %{$controller_cfg->{ids}}) {
- my $plugin_config = $controller_cfg->{ids}->{$id};
- my $plugin = PVE::Network::SDN::Controllers::Plugin->lookup($plugin_config->{type});
- $plugin->write_controller_config($plugin_config, $config);
+ foreach my $id (keys %{ $controller_cfg->{ids} }) {
+ my $plugin_config = $controller_cfg->{ids}->{$id};
+ my $plugin = PVE::Network::SDN::Controllers::Plugin->lookup($plugin_config->{type});
+ $plugin->write_controller_config($plugin_config, $config);
}
}
diff --git a/src/PVE/Network/SDN/Controllers/BgpPlugin.pm b/src/PVE/Network/SDN/Controllers/BgpPlugin.pm
index 53963e5..dd835e4 100644
--- a/src/PVE/Network/SDN/Controllers/BgpPlugin.pm
+++ b/src/PVE/Network/SDN/Controllers/BgpPlugin.pm
@@ -19,36 +19,36 @@ sub type {
sub properties {
return {
- 'bgp-multipath-as-path-relax' => {
- type => 'boolean',
- optional => 1,
- },
- ebgp => {
- type => 'boolean',
- optional => 1,
- description => "Enable ebgp. (remote-as external)",
- },
- 'ebgp-multihop' => {
- type => 'integer',
- optional => 1,
- },
- loopback => {
- description => "source loopback interface.",
- type => 'string'
- },
+ 'bgp-multipath-as-path-relax' => {
+ type => 'boolean',
+ optional => 1,
+ },
+ ebgp => {
+ type => 'boolean',
+ optional => 1,
+ description => "Enable ebgp. (remote-as external)",
+ },
+ 'ebgp-multihop' => {
+ type => 'integer',
+ optional => 1,
+ },
+ loopback => {
+ description => "source loopback interface.",
+ type => 'string',
+ },
node => get_standard_option('pve-node'),
};
}
sub options {
return {
- 'node' => { optional => 0 },
- 'asn' => { optional => 0 },
- 'peers' => { optional => 0 },
- 'bgp-multipath-as-path-relax' => { optional => 1 },
- 'ebgp' => { optional => 1 },
- 'ebgp-multihop' => { optional => 1 },
- 'loopback' => { optional => 1 },
+ 'node' => { optional => 0 },
+ 'asn' => { optional => 0 },
+ 'peers' => { optional => 0 },
+ 'bgp-multipath-as-path-relax' => { optional => 1 },
+ 'ebgp' => { optional => 1 },
+ 'ebgp-multihop' => { optional => 1 },
+ 'loopback' => { optional => 1 },
};
}
@@ -67,66 +67,69 @@ sub generate_controller_config {
my $local_node = PVE::INotify::nodename();
-
return if !$asn;
return if $local_node ne $plugin_config->{node};
my $bgp = $config->{frr}->{router}->{"bgp $asn"} //= {};
- my ($ifaceip, $interface) = PVE::Network::SDN::Zones::Plugin::find_local_ip_interface_peers(\@peers, $loopback);
+ my ($ifaceip, $interface) =
+ PVE::Network::SDN::Zones::Plugin::find_local_ip_interface_peers(\@peers, $loopback);
my $routerid = PVE::Network::SDN::Controllers::Plugin::get_router_id($ifaceip, $interface);
my $remoteas = $ebgp ? "external" : $asn;
#global options
my @controller_config = (
- "bgp router-id $routerid",
- "no bgp default ipv4-unicast",
- "coalesce-time 1000"
+ "bgp router-id $routerid", "no bgp default ipv4-unicast", "coalesce-time 1000",
);
- push(@{$bgp->{""}}, @controller_config) if keys %{$bgp} == 0;
+ push(@{ $bgp->{""} }, @controller_config) if keys %{$bgp} == 0;
@controller_config = ();
- if($ebgp) {
- push @controller_config, "bgp disable-ebgp-connected-route-check" if $loopback;
+ if ($ebgp) {
+ push @controller_config, "bgp disable-ebgp-connected-route-check" if $loopback;
}
push @controller_config, "bgp bestpath as-path multipath-relax" if $multipath_relax;
#BGP neighbors
- if(@peers) {
- push @controller_config, "neighbor BGP peer-group";
- push @controller_config, "neighbor BGP remote-as $remoteas";
- push @controller_config, "neighbor BGP bfd";
- push @controller_config, "neighbor BGP ebgp-multihop $ebgp_multihop" if $ebgp && $ebgp_multihop;
+ if (@peers) {
+ push @controller_config, "neighbor BGP peer-group";
+ push @controller_config, "neighbor BGP remote-as $remoteas";
+ push @controller_config, "neighbor BGP bfd";
+ push @controller_config, "neighbor BGP ebgp-multihop $ebgp_multihop"
+ if $ebgp && $ebgp_multihop;
}
# BGP peers
foreach my $address (@peers) {
- push @controller_config, "neighbor $address peer-group BGP";
+ push @controller_config, "neighbor $address peer-group BGP";
}
- push(@{$bgp->{""}}, @controller_config);
+ push(@{ $bgp->{""} }, @controller_config);
# address-family unicast
if (@peers) {
- my $ipversion = Net::IP::ip_is_ipv6($ifaceip) ? "ipv6" : "ipv4";
- my $mask = Net::IP::ip_is_ipv6($ifaceip) ? "/128" : "32";
-
- push(@{$bgp->{"address-family"}->{"$ipversion unicast"}}, "network $ifaceip/$mask") if $loopback;
- push(@{$bgp->{"address-family"}->{"$ipversion unicast"}}, "neighbor BGP activate");
- push(@{$bgp->{"address-family"}->{"$ipversion unicast"}}, "neighbor BGP soft-reconfiguration inbound");
+ my $ipversion = Net::IP::ip_is_ipv6($ifaceip) ? "ipv6" : "ipv4";
+ my $mask = Net::IP::ip_is_ipv6($ifaceip) ? "/128" : "32";
+
+ push(@{ $bgp->{"address-family"}->{"$ipversion unicast"} }, "network $ifaceip/$mask")
+ if $loopback;
+ push(@{ $bgp->{"address-family"}->{"$ipversion unicast"} }, "neighbor BGP activate");
+ push(
+ @{ $bgp->{"address-family"}->{"$ipversion unicast"} },
+ "neighbor BGP soft-reconfiguration inbound",
+ );
}
if ($loopback) {
- $config->{frr_prefix_list}->{loopbacks_ips}->{10} = "permit 0.0.0.0/0 le 32";
- push(@{$config->{frr_ip_protocol}}, "ip protocol bgp route-map correct_src");
-
- my $routemap_config = ();
- push @{$routemap_config}, "match ip address prefix-list loopbacks_ips";
- push @{$routemap_config}, "set src $ifaceip";
- my $routemap = { rule => $routemap_config, action => "permit" };
- push(@{$config->{frr_routemap}->{'correct_src'}}, $routemap);
+ $config->{frr_prefix_list}->{loopbacks_ips}->{10} = "permit 0.0.0.0/0 le 32";
+ push(@{ $config->{frr_ip_protocol} }, "ip protocol bgp route-map correct_src");
+
+ my $routemap_config = ();
+ push @{$routemap_config}, "match ip address prefix-list loopbacks_ips";
+ push @{$routemap_config}, "set src $ifaceip";
+ my $routemap = { rule => $routemap_config, action => "permit" };
+ push(@{ $config->{frr_routemap}->{'correct_src'} }, $routemap);
}
return $config;
@@ -141,10 +144,10 @@ sub on_delete_hook {
my ($class, $controllerid, $zone_cfg) = @_;
# verify that zone is associated to this controller
- foreach my $id (keys %{$zone_cfg->{ids}}) {
- my $zone = $zone_cfg->{ids}->{$id};
- die "controller $controllerid is used by $id"
- if (defined($zone->{controller}) && $zone->{controller} eq $controllerid);
+ foreach my $id (keys %{ $zone_cfg->{ids} }) {
+ my $zone = $zone_cfg->{ids}->{$id};
+ die "controller $controllerid is used by $id"
+ if (defined($zone->{controller}) && $zone->{controller} eq $controllerid);
}
}
@@ -154,7 +157,7 @@ sub on_update_hook {
# we can only have 1 bgp controller by node
my $local_node = PVE::INotify::nodename();
my $controllernb = 0;
- foreach my $id (keys %{$controller_cfg->{ids}}) {
+ foreach my $id (keys %{ $controller_cfg->{ids} }) {
next if $id eq $controllerid;
my $controller = $controller_cfg->{ids}->{$id};
next if $controller->{type} ne "bgp";
@@ -181,4 +184,3 @@ sub reload_controller {
1;
-
diff --git a/src/PVE/Network/SDN/Controllers/EvpnPlugin.pm b/src/PVE/Network/SDN/Controllers/EvpnPlugin.pm
index 5b1a9aa..7211510 100644
--- a/src/PVE/Network/SDN/Controllers/EvpnPlugin.pm
+++ b/src/PVE/Network/SDN/Controllers/EvpnPlugin.pm
@@ -20,23 +20,24 @@ sub type {
sub properties {
return {
- asn => {
- type => 'integer',
- description => "autonomous system number",
- minimum => 0,
- maximum => 4294967296
- },
- peers => {
- description => "peers address list.",
- type => 'string', format => 'ip-list'
- },
+ asn => {
+ type => 'integer',
+ description => "autonomous system number",
+ minimum => 0,
+ maximum => 4294967296,
+ },
+ peers => {
+ description => "peers address list.",
+ type => 'string',
+ format => 'ip-list',
+ },
};
}
sub options {
return {
- 'asn' => { optional => 0 },
- 'peers' => { optional => 0 },
+ 'asn' => { optional => 0 },
+ 'peers' => { optional => 0 },
};
}
@@ -57,33 +58,34 @@ sub generate_controller_config {
my $isisrouter = find_isis_controller($local_node, $controller_cfg);
if ($bgprouter) {
- $ebgp = 1 if $plugin_config->{'asn'} ne $bgprouter->{asn};
- $loopback = $bgprouter->{loopback} if $bgprouter->{loopback};
- $asn = $bgprouter->{asn} if $bgprouter->{asn};
- $autortas = $plugin_config->{'asn'} if $ebgp;
+ $ebgp = 1 if $plugin_config->{'asn'} ne $bgprouter->{asn};
+ $loopback = $bgprouter->{loopback} if $bgprouter->{loopback};
+ $asn = $bgprouter->{asn} if $bgprouter->{asn};
+ $autortas = $plugin_config->{'asn'} if $ebgp;
} elsif ($isisrouter) {
- $loopback = $isisrouter->{loopback} if $isisrouter->{loopback};
+ $loopback = $isisrouter->{loopback} if $isisrouter->{loopback};
}
return if !$asn;
my $bgp = $config->{frr}->{router}->{"bgp $asn"} //= {};
- my ($ifaceip, $interface) = PVE::Network::SDN::Zones::Plugin::find_local_ip_interface_peers(\@peers, $loopback);
+ my ($ifaceip, $interface) =
+ PVE::Network::SDN::Zones::Plugin::find_local_ip_interface_peers(\@peers, $loopback);
my $routerid = PVE::Network::SDN::Controllers::Plugin::get_router_id($ifaceip, $interface);
my $remoteas = $ebgp ? "external" : $asn;
#global options
my @controller_config = (
- "bgp router-id $routerid",
- "no bgp hard-administrative-reset",
- "no bgp default ipv4-unicast",
- "coalesce-time 1000",
- "no bgp graceful-restart notification",
+ "bgp router-id $routerid",
+ "no bgp hard-administrative-reset",
+ "no bgp default ipv4-unicast",
+ "coalesce-time 1000",
+ "no bgp graceful-restart notification",
);
- push(@{$bgp->{""}}, @controller_config) if keys %{$bgp} == 0;
+ push(@{ $bgp->{""} }, @controller_config) if keys %{$bgp} == 0;
@controller_config = ();
@@ -97,11 +99,11 @@ sub generate_controller_config {
# VTEP peers
foreach my $address (@peers) {
- next if $address eq $ifaceip;
- push @controller_config, "neighbor $address peer-group VTEP";
+ next if $address eq $ifaceip;
+ push @controller_config, "neighbor $address peer-group VTEP";
}
- push(@{$bgp->{""}}, @controller_config);
+ push(@{ $bgp->{""} }, @controller_config);
# address-family l2vpn
@controller_config = ();
@@ -110,11 +112,11 @@ sub generate_controller_config {
push @controller_config, "neighbor VTEP route-map MAP_VTEP_OUT out";
push @controller_config, "advertise-all-vni";
push @controller_config, "autort as $autortas" if $autortas;
- push(@{$bgp->{"address-family"}->{"l2vpn evpn"}}, @controller_config);
+ push(@{ $bgp->{"address-family"}->{"l2vpn evpn"} }, @controller_config);
my $routemap = { rule => undef, action => "permit" };
- push(@{$config->{frr_routemap}->{'MAP_VTEP_IN'}}, $routemap );
- push(@{$config->{frr_routemap}->{'MAP_VTEP_OUT'}}, $routemap );
+ push(@{ $config->{frr_routemap}->{'MAP_VTEP_IN'} }, $routemap);
+ push(@{ $config->{frr_routemap}->{'MAP_VTEP_OUT'} }, $routemap);
return $config;
}
@@ -131,7 +133,8 @@ sub generate_controller_zone_config {
my $advertisesubnets = $plugin_config->{'advertise-subnets'};
my $exitnodes_local_routing = $plugin_config->{'exitnodes-local-routing'};
my $rt_import;
- $rt_import = [PVE::Tools::split_list($plugin_config->{'rt-import'})] if $plugin_config->{'rt-import'};
+ $rt_import = [PVE::Tools::split_list($plugin_config->{'rt-import'})]
+ if $plugin_config->{'rt-import'};
my $asn = $controller->{asn};
my @peers;
@@ -142,18 +145,19 @@ sub generate_controller_zone_config {
my $bgprouter = find_bgp_controller($local_node, $controller_cfg);
my $isisrouter = find_isis_controller($local_node, $controller_cfg);
- if($bgprouter) {
+ if ($bgprouter) {
$ebgp = 1 if $controller->{'asn'} ne $bgprouter->{asn};
- $loopback = $bgprouter->{loopback} if $bgprouter->{loopback};
- $asn = $bgprouter->{asn} if $bgprouter->{asn};
- $autortas = $controller->{'asn'} if $ebgp;
+ $loopback = $bgprouter->{loopback} if $bgprouter->{loopback};
+ $asn = $bgprouter->{asn} if $bgprouter->{asn};
+ $autortas = $controller->{'asn'} if $ebgp;
} elsif ($isisrouter) {
$loopback = $isisrouter->{loopback} if $isisrouter->{loopback};
}
return if !$vrf || !$vrfvxlan || !$asn;
- my ($ifaceip, $interface) = PVE::Network::SDN::Zones::Plugin::find_local_ip_interface_peers(\@peers, $loopback);
+ my ($ifaceip, $interface) =
+ PVE::Network::SDN::Zones::Plugin::find_local_ip_interface_peers(\@peers, $loopback);
my $routerid = PVE::Network::SDN::Controllers::Plugin::get_router_id($ifaceip, $interface);
my $is_gateway = $exitnodes->{$local_node};
@@ -164,30 +168,31 @@ sub generate_controller_zone_config {
#avoid to routes between nodes through the exit nodes
#null routes subnets of other zones
if ($is_gateway) {
- my $subnets = PVE::Network::SDN::Vnets::get_subnets();
- my $cidrs = {};
- foreach my $subnetid (sort keys %{$subnets}) {
- my $subnet = $subnets->{$subnetid};
- my $cidr = $subnet->{cidr};
- my $zone = $subnet->{zone};
- my ($ip, $mask) = split(/\//, $cidr);
- $cidrs->{$ip} = $mask if $zone ne $id;
-
- }
-
- my @sorted_ip =
- map { $_->[0] }
- sort { $a->[1] <=> $b->[1] }
- map { [ $_, eval { Net::IP->new( $_ )->intip } ] }
- keys %{$cidrs} if $cidrs;
-
- foreach my $ip (@sorted_ip) {
- my $ipversion = Net::IP::ip_is_ipv4($ip) ? 'ip' : 'ipv6';
- push @controller_config, "$ipversion route $ip/$cidrs->{$ip} null0";
- }
+ my $subnets = PVE::Network::SDN::Vnets::get_subnets();
+ my $cidrs = {};
+ foreach my $subnetid (sort keys %{$subnets}) {
+ my $subnet = $subnets->{$subnetid};
+ my $cidr = $subnet->{cidr};
+ my $zone = $subnet->{zone};
+ my ($ip, $mask) = split(/\//, $cidr);
+ $cidrs->{$ip} = $mask if $zone ne $id;
+
+ }
+
+ my @sorted_ip =
+ map { $_->[0] }
+ sort { $a->[1] <=> $b->[1] }
+ map { [$_, eval { Net::IP->new($_)->intip }] }
+ keys %{$cidrs}
+ if $cidrs;
+
+ foreach my $ip (@sorted_ip) {
+ my $ipversion = Net::IP::ip_is_ipv4($ip) ? 'ip' : 'ipv6';
+ push @controller_config, "$ipversion route $ip/$cidrs->{$ip} null0";
+ }
}
- push(@{$config->{frr}->{vrf}->{"$vrf"}}, @controller_config);
+ push(@{ $config->{frr}->{vrf}->{"$vrf"} }, @controller_config);
#main vrf router
@controller_config = ();
@@ -195,85 +200,149 @@ sub generate_controller_zone_config {
push @controller_config, "no bgp hard-administrative-reset";
push @controller_config, "no bgp graceful-restart notification";
-# push @controller_config, "!";
- push(@{$config->{frr}->{router}->{"bgp $asn vrf $vrf"}->{""}}, @controller_config);
+ # push @controller_config, "!";
+ push(@{ $config->{frr}->{router}->{"bgp $asn vrf $vrf"}->{""} }, @controller_config);
if ($autortas) {
- push(@{$config->{frr}->{router}->{"bgp $asn vrf $vrf"}->{"address-family"}->{"l2vpn evpn"}}, "route-target import $autortas:$vrfvxlan");
- push(@{$config->{frr}->{router}->{"bgp $asn vrf $vrf"}->{"address-family"}->{"l2vpn evpn"}}, "route-target export $autortas:$vrfvxlan");
+ push(
+ @{
+ $config->{frr}->{router}->{"bgp $asn vrf $vrf"}->{"address-family"}
+ ->{"l2vpn evpn"}
+ },
+ "route-target import $autortas:$vrfvxlan",
+ );
+ push(
+ @{
+ $config->{frr}->{router}->{"bgp $asn vrf $vrf"}->{"address-family"}
+ ->{"l2vpn evpn"}
+ },
+ "route-target export $autortas:$vrfvxlan",
+ );
}
if ($is_gateway) {
- $config->{frr_prefix_list}->{'only_default'}->{1} = "permit 0.0.0.0/0";
- $config->{frr_prefix_list_v6}->{'only_default_v6'}->{1} = "permit ::/0";
-
- if (!$exitnodes_primary || $exitnodes_primary eq $local_node) {
- #filter default route coming from other exit nodes on primary node or both nodes if no primary is defined.
- my $routemap_config_v6 = ();
- push @{$routemap_config_v6}, "match ipv6 address prefix-list only_default_v6";
- my $routemap_v6 = { rule => $routemap_config_v6, action => "deny" };
- unshift(@{$config->{frr_routemap}->{'MAP_VTEP_IN'}}, $routemap_v6);
-
- my $routemap_config = ();
- push @{$routemap_config}, "match ip address prefix-list only_default";
- my $routemap = { rule => $routemap_config, action => "deny" };
- unshift(@{$config->{frr_routemap}->{'MAP_VTEP_IN'}}, $routemap);
-
- } elsif ($exitnodes_primary ne $local_node) {
- my $routemap_config_v6 = ();
- push @{$routemap_config_v6}, "match ipv6 address prefix-list only_default_v6";
- push @{$routemap_config_v6}, "set metric 200";
- my $routemap_v6 = { rule => $routemap_config_v6, action => "permit" };
- unshift(@{$config->{frr_routemap}->{'MAP_VTEP_OUT'}}, $routemap_v6);
-
- my $routemap_config = ();
- push @{$routemap_config}, "match ip address prefix-list only_default";
- push @{$routemap_config}, "set metric 200";
- my $routemap = { rule => $routemap_config, action => "permit" };
- unshift(@{$config->{frr_routemap}->{'MAP_VTEP_OUT'}}, $routemap);
- }
-
- if (!$exitnodes_local_routing) {
- @controller_config = ();
- #import /32 routes of evpn network from vrf1 to default vrf (for packet return)
- push @controller_config, "import vrf $vrf";
- push(@{$config->{frr}->{router}->{"bgp $asn"}->{"address-family"}->{"ipv4 unicast"}}, @controller_config);
- push(@{$config->{frr}->{router}->{"bgp $asn"}->{"address-family"}->{"ipv6 unicast"}}, @controller_config);
-
- @controller_config = ();
- #redistribute connected to be able to route to local vms on the gateway
- push @controller_config, "redistribute connected";
- push(@{$config->{frr}->{router}->{"bgp $asn vrf $vrf"}->{"address-family"}->{"ipv4 unicast"}}, @controller_config);
- push(@{$config->{frr}->{router}->{"bgp $asn vrf $vrf"}->{"address-family"}->{"ipv6 unicast"}}, @controller_config);
- }
-
- @controller_config = ();
- #add default originate to announce 0.0.0.0/0 type5 route in evpn
- push @controller_config, "default-originate ipv4";
- push @controller_config, "default-originate ipv6";
- push(@{$config->{frr}->{router}->{"bgp $asn vrf $vrf"}->{"address-family"}->{"l2vpn evpn"}}, @controller_config);
+ $config->{frr_prefix_list}->{'only_default'}->{1} = "permit 0.0.0.0/0";
+ $config->{frr_prefix_list_v6}->{'only_default_v6'}->{1} = "permit ::/0";
+
+ if (!$exitnodes_primary || $exitnodes_primary eq $local_node) {
+ #filter default route coming from other exit nodes on primary node or both nodes if no primary is defined.
+ my $routemap_config_v6 = ();
+ push @{$routemap_config_v6}, "match ipv6 address prefix-list only_default_v6";
+ my $routemap_v6 = { rule => $routemap_config_v6, action => "deny" };
+ unshift(@{ $config->{frr_routemap}->{'MAP_VTEP_IN'} }, $routemap_v6);
+
+ my $routemap_config = ();
+ push @{$routemap_config}, "match ip address prefix-list only_default";
+ my $routemap = { rule => $routemap_config, action => "deny" };
+ unshift(@{ $config->{frr_routemap}->{'MAP_VTEP_IN'} }, $routemap);
+
+ } elsif ($exitnodes_primary ne $local_node) {
+ my $routemap_config_v6 = ();
+ push @{$routemap_config_v6}, "match ipv6 address prefix-list only_default_v6";
+ push @{$routemap_config_v6}, "set metric 200";
+ my $routemap_v6 = { rule => $routemap_config_v6, action => "permit" };
+ unshift(@{ $config->{frr_routemap}->{'MAP_VTEP_OUT'} }, $routemap_v6);
+
+ my $routemap_config = ();
+ push @{$routemap_config}, "match ip address prefix-list only_default";
+ push @{$routemap_config}, "set metric 200";
+ my $routemap = { rule => $routemap_config, action => "permit" };
+ unshift(@{ $config->{frr_routemap}->{'MAP_VTEP_OUT'} }, $routemap);
+ }
+
+ if (!$exitnodes_local_routing) {
+ @controller_config = ();
+ #import /32 routes of evpn network from vrf1 to default vrf (for packet return)
+ push @controller_config, "import vrf $vrf";
+ push(
+ @{
+ $config->{frr}->{router}->{"bgp $asn"}->{"address-family"}->{"ipv4 unicast"}
+ },
+ @controller_config,
+ );
+ push(
+ @{
+ $config->{frr}->{router}->{"bgp $asn"}->{"address-family"}->{"ipv6 unicast"}
+ },
+ @controller_config,
+ );
+
+ @controller_config = ();
+ #redistribute connected to be able to route to local vms on the gateway
+ push @controller_config, "redistribute connected";
+ push(
+ @{
+ $config->{frr}->{router}->{"bgp $asn vrf $vrf"}->{"address-family"}
+ ->{"ipv4 unicast"}
+ },
+ @controller_config,
+ );
+ push(
+ @{
+ $config->{frr}->{router}->{"bgp $asn vrf $vrf"}->{"address-family"}
+ ->{"ipv6 unicast"}
+ },
+ @controller_config,
+ );
+ }
+
+ @controller_config = ();
+ #add default originate to announce 0.0.0.0/0 type5 route in evpn
+ push @controller_config, "default-originate ipv4";
+ push @controller_config, "default-originate ipv6";
+ push(
+ @{
+ $config->{frr}->{router}->{"bgp $asn vrf $vrf"}->{"address-family"}
+ ->{"l2vpn evpn"}
+ },
+ @controller_config,
+ );
} elsif ($advertisesubnets) {
- @controller_config = ();
- #redistribute connected networks
- push @controller_config, "redistribute connected";
- push(@{$config->{frr}->{router}->{"bgp $asn vrf $vrf"}->{"address-family"}->{"ipv4 unicast"}}, @controller_config);
- push(@{$config->{frr}->{router}->{"bgp $asn vrf $vrf"}->{"address-family"}->{"ipv6 unicast"}}, @controller_config);
-
- @controller_config = ();
- #advertise connected networks type5 route in evpn
- push @controller_config, "advertise ipv4 unicast";
- push @controller_config, "advertise ipv6 unicast";
- push(@{$config->{frr}->{router}->{"bgp $asn vrf $vrf"}->{"address-family"}->{"l2vpn evpn"}}, @controller_config);
+ @controller_config = ();
+ #redistribute connected networks
+ push @controller_config, "redistribute connected";
+ push(
+ @{
+ $config->{frr}->{router}->{"bgp $asn vrf $vrf"}->{"address-family"}
+ ->{"ipv4 unicast"}
+ },
+ @controller_config,
+ );
+ push(
+ @{
+ $config->{frr}->{router}->{"bgp $asn vrf $vrf"}->{"address-family"}
+ ->{"ipv6 unicast"}
+ },
+ @controller_config,
+ );
+
+ @controller_config = ();
+ #advertise connected networks type5 route in evpn
+ push @controller_config, "advertise ipv4 unicast";
+ push @controller_config, "advertise ipv6 unicast";
+ push(
+ @{
+ $config->{frr}->{router}->{"bgp $asn vrf $vrf"}->{"address-family"}
+ ->{"l2vpn evpn"}
+ },
+ @controller_config,
+ );
}
if ($rt_import) {
- @controller_config = ();
- foreach my $rt (sort @{$rt_import}) {
- push @controller_config, "route-target import $rt";
- }
- push(@{$config->{frr}->{router}->{"bgp $asn vrf $vrf"}->{"address-family"}->{"l2vpn evpn"}}, @controller_config);
+ @controller_config = ();
+ foreach my $rt (sort @{$rt_import}) {
+ push @controller_config, "route-target import $rt";
+ }
+ push(
+ @{
+ $config->{frr}->{router}->{"bgp $asn vrf $vrf"}->{"address-family"}
+ ->{"l2vpn evpn"}
+ },
+ @controller_config,
+ );
}
return $config;
@@ -296,20 +365,20 @@ sub generate_controller_vnet_config {
my @controller_config = ();
foreach my $subnetid (sort keys %{$subnets}) {
my $subnet = $subnets->{$subnetid};
- my $cidr = $subnet->{cidr};
- push @controller_config, "ip route $cidr 10.255.255.2 xvrf_$zoneid";
+ my $cidr = $subnet->{cidr};
+ push @controller_config, "ip route $cidr 10.255.255.2 xvrf_$zoneid";
}
- push(@{$config->{frr_ip_protocol}}, @controller_config);
+ push(@{ $config->{frr_ip_protocol} }, @controller_config);
}
sub on_delete_hook {
my ($class, $controllerid, $zone_cfg) = @_;
# verify that zone is associated to this controller
- foreach my $id (keys %{$zone_cfg->{ids}}) {
- my $zone = $zone_cfg->{ids}->{$id};
- die "controller $controllerid is used by $id"
- if (defined($zone->{controller}) && $zone->{controller} eq $controllerid);
+ foreach my $id (keys %{ $zone_cfg->{ids} }) {
+ my $zone = $zone_cfg->{ids}->{$id};
+ die "controller $controllerid is used by $id"
+ if (defined($zone->{controller}) && $zone->{controller} eq $controllerid);
}
}
@@ -319,12 +388,12 @@ sub on_update_hook {
# we can only have 1 evpn controller / 1 asn by server
my $controllernb = 0;
- foreach my $id (keys %{$controller_cfg->{ids}}) {
- next if $id eq $controllerid;
- my $controller = $controller_cfg->{ids}->{$id};
- next if $controller->{type} ne "evpn";
- $controllernb++;
- die "only 1 global evpn controller can be defined" if $controllernb >= 1;
+ foreach my $id (keys %{ $controller_cfg->{ids} }) {
+ next if $id eq $controllerid;
+ my $controller = $controller_cfg->{ids}->{$id};
+ next if $controller->{type} ne "evpn";
+ $controllernb++;
+ die "only 1 global evpn controller can be defined" if $controllernb >= 1;
}
}
@@ -332,12 +401,12 @@ sub find_bgp_controller {
my ($nodename, $controller_cfg) = @_;
my $res = undef;
- foreach my $id (keys %{$controller_cfg->{ids}}) {
- my $controller = $controller_cfg->{ids}->{$id};
- next if $controller->{type} ne 'bgp';
- next if $controller->{node} ne $nodename;
- $res = $controller;
- last;
+ foreach my $id (keys %{ $controller_cfg->{ids} }) {
+ my $controller = $controller_cfg->{ids}->{$id};
+ next if $controller->{type} ne 'bgp';
+ next if $controller->{node} ne $nodename;
+ $res = $controller;
+ last;
}
return $res;
}
@@ -346,128 +415,130 @@ sub find_isis_controller {
my ($nodename, $controller_cfg) = @_;
my $res = undef;
- foreach my $id (keys %{$controller_cfg->{ids}}) {
- my $controller = $controller_cfg->{ids}->{$id};
- next if $controller->{type} ne 'isis';
- next if $controller->{node} ne $nodename;
- $res = $controller;
- last;
+ foreach my $id (keys %{ $controller_cfg->{ids} }) {
+ my $controller = $controller_cfg->{ids}->{$id};
+ next if $controller->{type} ne 'isis';
+ next if $controller->{node} ne $nodename;
+ $res = $controller;
+ last;
}
return $res;
}
-sub generate_frr_recurse{
- my ($final_config, $content, $parentkey, $level) = @_;
-
- my $keylist = {};
- $keylist->{'address-family'} = 1;
- $keylist->{router} = 1;
-
- my $exitkeylist = {};
- $exitkeylist->{'address-family'} = 1;
-
- my $simple_exitkeylist = {};
- $simple_exitkeylist->{router} = 1;
-
- # FIXME: make this generic
- my $paddinglevel = undef;
- if ($level == 1 || $level == 2) {
- $paddinglevel = $level - 1;
- } elsif ($level == 3 || $level == 4) {
- $paddinglevel = $level - 2;
- }
-
- my $padding = "";
- $padding = ' ' x ($paddinglevel) if $paddinglevel;
-
- if (ref $content eq 'HASH') {
- foreach my $key (sort keys %$content) {
- next if $key eq 'vrf';
- if ($parentkey && defined($keylist->{$parentkey})) {
- push @{$final_config}, $padding."!";
- push @{$final_config}, $padding."$parentkey $key";
- } elsif ($key ne '' && !defined($keylist->{$key})) {
- push @{$final_config}, $padding."$key";
- }
-
- my $option = $content->{$key};
- generate_frr_recurse($final_config, $option, $key, $level+1);
-
- push @{$final_config}, $padding."exit-$parentkey" if $parentkey && defined($exitkeylist->{$parentkey});
- push @{$final_config}, $padding."exit" if $parentkey && defined($simple_exitkeylist->{$parentkey});
- }
+sub generate_frr_recurse {
+ my ($final_config, $content, $parentkey, $level) = @_;
+
+ my $keylist = {};
+ $keylist->{'address-family'} = 1;
+ $keylist->{router} = 1;
+
+ my $exitkeylist = {};
+ $exitkeylist->{'address-family'} = 1;
+
+ my $simple_exitkeylist = {};
+ $simple_exitkeylist->{router} = 1;
+
+ # FIXME: make this generic
+ my $paddinglevel = undef;
+ if ($level == 1 || $level == 2) {
+ $paddinglevel = $level - 1;
+ } elsif ($level == 3 || $level == 4) {
+ $paddinglevel = $level - 2;
+ }
+
+ my $padding = "";
+ $padding = ' ' x ($paddinglevel) if $paddinglevel;
+
+ if (ref $content eq 'HASH') {
+ foreach my $key (sort keys %$content) {
+ next if $key eq 'vrf';
+ if ($parentkey && defined($keylist->{$parentkey})) {
+ push @{$final_config}, $padding . "!";
+ push @{$final_config}, $padding . "$parentkey $key";
+ } elsif ($key ne '' && !defined($keylist->{$key})) {
+ push @{$final_config}, $padding . "$key";
+ }
+
+ my $option = $content->{$key};
+ generate_frr_recurse($final_config, $option, $key, $level + 1);
+
+ push @{$final_config}, $padding . "exit-$parentkey"
+ if $parentkey && defined($exitkeylist->{$parentkey});
+ push @{$final_config}, $padding . "exit"
+ if $parentkey && defined($simple_exitkeylist->{$parentkey});
+ }
}
if (ref $content eq 'ARRAY') {
- push @{$final_config}, map { $padding . "$_" } @$content;
+ push @{$final_config}, map { $padding . "$_" } @$content;
}
}
sub generate_frr_vrf {
- my ($final_config, $vrfs) = @_;
+ my ($final_config, $vrfs) = @_;
- return if !$vrfs;
+ return if !$vrfs;
- my @config = ();
+ my @config = ();
- foreach my $id (sort keys %$vrfs) {
- my $vrf = $vrfs->{$id};
- push @config, "!";
- push @config, "vrf $id";
- foreach my $rule (@$vrf) {
- push @config, " $rule";
+ foreach my $id (sort keys %$vrfs) {
+ my $vrf = $vrfs->{$id};
+ push @config, "!";
+ push @config, "vrf $id";
+ foreach my $rule (@$vrf) {
+ push @config, " $rule";
- }
- push @config, "exit-vrf";
+ }
+ push @config, "exit-vrf";
}
push @{$final_config}, @config;
}
sub generate_frr_simple_list {
- my ($final_config, $rules) = @_;
+ my ($final_config, $rules) = @_;
- return if !$rules;
+ return if !$rules;
- my @config = ();
- push @{$final_config}, "!";
- foreach my $rule (sort @$rules) {
- push @{$final_config}, $rule;
- }
+ my @config = ();
+ push @{$final_config}, "!";
+ foreach my $rule (sort @$rules) {
+ push @{$final_config}, $rule;
+ }
}
sub generate_frr_interfaces {
- my ($final_config, $interfaces) = @_;
-
- foreach my $k (sort keys %$interfaces) {
- my $iface = $interfaces->{$k};
- push @{$final_config}, "!";
- push @{$final_config}, "interface $k";
- foreach my $rule (sort @$iface) {
- push @{$final_config}, " $rule";
- }
- }
+ my ($final_config, $interfaces) = @_;
+
+ foreach my $k (sort keys %$interfaces) {
+ my $iface = $interfaces->{$k};
+ push @{$final_config}, "!";
+ push @{$final_config}, "interface $k";
+ foreach my $rule (sort @$iface) {
+ push @{$final_config}, " $rule";
+ }
+ }
}
sub generate_frr_routemap {
- my ($final_config, $routemaps) = @_;
-
- foreach my $id (sort keys %$routemaps) {
-
- my $routemap = $routemaps->{$id};
- my $order = 0;
- foreach my $seq (@$routemap) {
- $order++;
- next if !defined($seq->{action});
- my @config = ();
- push @config, "!";
- push @config, "route-map $id $seq->{action} $order";
- my $rule = $seq->{rule};
- push @config, map { " $_" } @$rule;
- push @{$final_config}, @config;
- push @{$final_config}, "exit";
- }
- }
+ my ($final_config, $routemaps) = @_;
+
+ foreach my $id (sort keys %$routemaps) {
+
+ my $routemap = $routemaps->{$id};
+ my $order = 0;
+ foreach my $seq (@$routemap) {
+ $order++;
+ next if !defined($seq->{action});
+ my @config = ();
+ push @config, "!";
+ push @config, "route-map $id $seq->{action} $order";
+ my $rule = $seq->{rule};
+ push @config, map { " $_" } @$rule;
+ push @{$final_config}, @config;
+ push @{$final_config}, "exit";
+ }
+ }
}
sub generate_frr_list {
@@ -476,24 +547,24 @@ sub generate_frr_list {
my $config = [];
for my $id (sort keys %$lists) {
- my $list = $lists->{$id};
+ my $list = $lists->{$id};
- for my $seq (sort keys %$list) {
- my $rule = $list->{$seq};
- push @$config, "$type $id seq $seq $rule";
- }
+ for my $seq (sort keys %$list) {
+ my $rule = $list->{$seq};
+ push @$config, "$type $id seq $seq $rule";
+ }
}
if (@$config > 0) {
- push @{$final_config}, "!", @$config;
+ push @{$final_config}, "!", @$config;
}
}
sub read_local_frr_config {
if (-e "/etc/frr/frr.conf.local") {
- return file_get_contents("/etc/frr/frr.conf.local");
+ return file_get_contents("/etc/frr/frr.conf.local");
}
-};
+}
sub generate_controller_rawconfig {
my ($class, $plugin_config, $config) = @_;
@@ -510,7 +581,7 @@ sub generate_controller_rawconfig {
my $local_conf = read_local_frr_config();
if ($local_conf) {
- parse_merge_frr_local_config($config, $local_conf);
+ parse_merge_frr_local_config($config, $local_conf);
}
generate_frr_vrf($final_config, $config->{frr}->{vrf});
@@ -544,63 +615,63 @@ sub parse_merge_frr_local_config {
while ($local_conf =~ /^\s*(.+?)\s*$/gm) {
my $line = $1;
- $line =~ s/^\s+|\s+$//g;
-
- if ($line =~ m/^router (.+)$/) {
- $router = $1;
- $section = \$config->{'frr'}->{'router'}->{$router}->{""};
- next;
- } elsif ($line =~ m/^vrf (.+)$/) {
- $section = \$config->{'frr'}->{'vrf'}->{$1};
- next;
- } elsif ($line =~ m/^interface (.+)$/) {
- $section = \$config->{'frr_interfaces'}->{$1};
- next;
- } elsif ($line =~ m/^bgp community-list (.+)$/) {
- push(@{$config->{'frr_bgp_community_list'}}, $line);
- next;
- } elsif ($line =~ m/address-family (.+)$/) {
- $section = \$config->{'frr'}->{'router'}->{$router}->{'address-family'}->{$1};
- next;
- } elsif ($line =~ m/^route-map (.+) (permit|deny) (\d+)/) {
- $routemap = $1;
- $routemap_config = ();
- $routemap_action = $2;
- $section = \$config->{'frr_routemap'}->{$routemap};
- next;
- } elsif ($line =~ m/^access-list (.+) seq (\d+) (.+)$/) {
- $config->{'frr_access_list'}->{$1}->{$2} = $3;
- next;
- } elsif ($line =~ m/^ip prefix-list (.+) seq (\d+) (.*)$/) {
- $config->{'frr_prefix_list'}->{$1}->{$2} = $3;
- next;
- } elsif ($line =~ m/^ipv6 prefix-list (.+) seq (\d+) (.*)$/) {
- $config->{'frr_prefix_list_v6'}->{$1}->{$2} = $3;
- next;
- } elsif($line =~ m/^exit-address-family$/) {
- next;
- } elsif($line =~ m/^exit$/) {
- if($router) {
- $section = \$config->{''};
- $router = undef;
- } elsif($routemap) {
- push(@{$$section}, { rule => $routemap_config, action => $routemap_action });
- $section = \$config->{''};
- $routemap = undef;
- $routemap_action = undef;
- $routemap_config = ();
- }
- next;
- } elsif($line =~ m/!/) {
- next;
- }
-
- next if !$section;
- if($routemap) {
- push(@{$routemap_config}, $line);
- } else {
- push(@{$$section}, $line);
- }
+ $line =~ s/^\s+|\s+$//g;
+
+ if ($line =~ m/^router (.+)$/) {
+ $router = $1;
+ $section = \$config->{'frr'}->{'router'}->{$router}->{""};
+ next;
+ } elsif ($line =~ m/^vrf (.+)$/) {
+ $section = \$config->{'frr'}->{'vrf'}->{$1};
+ next;
+ } elsif ($line =~ m/^interface (.+)$/) {
+ $section = \$config->{'frr_interfaces'}->{$1};
+ next;
+ } elsif ($line =~ m/^bgp community-list (.+)$/) {
+ push(@{ $config->{'frr_bgp_community_list'} }, $line);
+ next;
+ } elsif ($line =~ m/address-family (.+)$/) {
+ $section = \$config->{'frr'}->{'router'}->{$router}->{'address-family'}->{$1};
+ next;
+ } elsif ($line =~ m/^route-map (.+) (permit|deny) (\d+)/) {
+ $routemap = $1;
+ $routemap_config = ();
+ $routemap_action = $2;
+ $section = \$config->{'frr_routemap'}->{$routemap};
+ next;
+ } elsif ($line =~ m/^access-list (.+) seq (\d+) (.+)$/) {
+ $config->{'frr_access_list'}->{$1}->{$2} = $3;
+ next;
+ } elsif ($line =~ m/^ip prefix-list (.+) seq (\d+) (.*)$/) {
+ $config->{'frr_prefix_list'}->{$1}->{$2} = $3;
+ next;
+ } elsif ($line =~ m/^ipv6 prefix-list (.+) seq (\d+) (.*)$/) {
+ $config->{'frr_prefix_list_v6'}->{$1}->{$2} = $3;
+ next;
+ } elsif ($line =~ m/^exit-address-family$/) {
+ next;
+ } elsif ($line =~ m/^exit$/) {
+ if ($router) {
+ $section = \$config->{''};
+ $router = undef;
+ } elsif ($routemap) {
+ push(@{$$section}, { rule => $routemap_config, action => $routemap_action });
+ $section = \$config->{''};
+ $routemap = undef;
+ $routemap_action = undef;
+ $routemap_config = ();
+ }
+ next;
+ } elsif ($line =~ m/!/) {
+ next;
+ }
+
+ next if !$section;
+ if ($routemap) {
+ push(@{$routemap_config}, $line);
+ } else {
+ push(@{$$section}, $line);
+ }
}
}
@@ -621,31 +692,28 @@ sub reload_controller {
my $bin_path = "/usr/lib/frr/frr-reload.py";
if (!-e $bin_path) {
- log_warn("missing $bin_path. Please install frr-pythontools package");
- return;
+ log_warn("missing $bin_path. Please install frr-pythontools package");
+ return;
}
run_command(['systemctl', 'enable', '--now', 'frr'])
- if !-e "/etc/systemd/system/multi-user.target.wants/frr.service";
+ if !-e "/etc/systemd/system/multi-user.target.wants/frr.service";
my $err = sub {
- my $line = shift;
- if ($line =~ /ERROR:/) {
- warn "$line \n";
- }
+ my $line = shift;
+ if ($line =~ /ERROR:/) {
+ warn "$line \n";
+ }
};
if (-e $conf_file && -e $bin_path) {
- eval {
- run_command([$bin_path, '--stdout', '--reload', $conf_file], errfunc => $err);
- };
- if ($@) {
- warn "frr reload command fail. Restarting frr.";
- eval { run_command(['systemctl', 'restart', 'frr']); };
- }
+ eval { run_command([$bin_path, '--stdout', '--reload', $conf_file], errfunc => $err); };
+ if ($@) {
+ warn "frr reload command fail. Restarting frr.";
+ eval { run_command(['systemctl', 'restart', 'frr']); };
+ }
}
}
1;
-
diff --git a/src/PVE/Network/SDN/Controllers/FaucetPlugin.pm b/src/PVE/Network/SDN/Controllers/FaucetPlugin.pm
index 4f3bb5c..5024bed 100644
--- a/src/PVE/Network/SDN/Controllers/FaucetPlugin.pm
+++ b/src/PVE/Network/SDN/Controllers/FaucetPlugin.pm
@@ -16,8 +16,7 @@ sub type {
}
sub properties {
- return {
- };
+ return {};
}
# Plugin implementation
@@ -30,18 +29,17 @@ sub generate_controller_zone_config {
my ($class, $plugin_config, $controller, $controller_cfg, $id, $uplinks, $config) = @_;
my $dpid = $plugin_config->{'dp-id'};
- my $dphex = printf("%x",$dpid);
+ my $dphex = printf("%x", $dpid);
my $zone_config = {
- dp_id => $dphex,
- hardware => "Open vSwitch",
- };
+ dp_id => $dphex,
+ hardware => "Open vSwitch",
+ };
$config->{faucet}->{dps}->{$id} = $zone_config;
}
-
sub generate_controller_vnet_config {
my ($class, $plugin_config, $controller, $zone, $zoneid, $vnetid, $config) = @_;
@@ -63,7 +61,7 @@ sub generate_controller_vnet_config {
$config->{faucet}->{vlans}->{$vnetid} = $vlan_config;
- push(@{$config->{faucet}->{routers}->{$zoneid}->{vlans}} , $vnetid);
+ push(@{ $config->{faucet}->{routers}->{$zoneid}->{vlans} }, $vnetid);
}
@@ -77,7 +75,7 @@ sub write_controller_config {
my $frr_config_file = "/etc/faucet/faucet.yaml";
- my $writefh = IO::File->new($frr_config_file,">");
+ my $writefh = IO::File->new($frr_config_file, ">");
print $writefh $rawconfig;
$writefh->close();
}
diff --git a/src/PVE/Network/SDN/Controllers/IsisPlugin.pm b/src/PVE/Network/SDN/Controllers/IsisPlugin.pm
index 97c6876..6e3574d 100644
--- a/src/PVE/Network/SDN/Controllers/IsisPlugin.pm
+++ b/src/PVE/Network/SDN/Controllers/IsisPlugin.pm
@@ -18,37 +18,40 @@ sub type {
}
PVE::JSONSchema::register_format('pve-sdn-isis-net', \&pve_verify_sdn_isis_net);
+
sub pve_verify_sdn_isis_net {
my ($net) = @_;
if ($net !~ m/^[a-fA-F0-9]{2}(\.[a-fA-F0-9]{4}){3,9}\.[a-fA-F0-9]{2}$/) {
- die "value does not look like a valid isis net\n";
+ die "value does not look like a valid isis net\n";
}
return $net;
}
sub properties {
return {
- 'isis-domain' => {
- description => "ISIS domain.",
- type => 'string'
- },
- 'isis-ifaces' => {
- description => "ISIS interface.",
- type => 'string', format => 'pve-iface-list',
- },
- 'isis-net' => {
- description => "ISIS network entity title.",
- type => 'string', format => 'pve-sdn-isis-net',
- },
+ 'isis-domain' => {
+ description => "ISIS domain.",
+ type => 'string',
+ },
+ 'isis-ifaces' => {
+ description => "ISIS interface.",
+ type => 'string',
+ format => 'pve-iface-list',
+ },
+ 'isis-net' => {
+ description => "ISIS network entity title.",
+ type => 'string',
+ format => 'pve-sdn-isis-net',
+ },
};
}
sub options {
return {
- 'isis-domain' => { optional => 0 },
- 'isis-net' => { optional => 0 },
- 'isis-ifaces' => { optional => 0 },
+ 'isis-domain' => { optional => 0 },
+ 'isis-net' => { optional => 0 },
+ 'isis-ifaces' => { optional => 0 },
'node' => { optional => 0 },
'loopback' => { optional => 1 },
};
@@ -67,21 +70,19 @@ sub generate_controller_config {
return if $local_node ne $plugin_config->{node};
my @router_config = (
- "net $isis_net",
- "redistribute ipv4 connected level-1",
- "redistribute ipv6 connected level-1",
- "log-adjacency-changes",
+ "net $isis_net",
+ "redistribute ipv4 connected level-1",
+ "redistribute ipv6 connected level-1",
+ "log-adjacency-changes",
);
- push(@{$config->{frr}->{router}->{"isis $isis_domain"}}, @router_config);
+ push(@{ $config->{frr}->{router}->{"isis $isis_domain"} }, @router_config);
- my @iface_config = (
- "ip router isis $isis_domain"
- );
+ my @iface_config = ("ip router isis $isis_domain");
my @ifaces = PVE::Tools::split_list($isis_ifaces);
for my $iface (sort @ifaces) {
- push(@{$config->{frr_interfaces}->{$iface}}, @iface_config);
+ push(@{ $config->{frr_interfaces}->{$iface} }, @iface_config);
}
return $config;
@@ -103,7 +104,7 @@ sub on_update_hook {
# we can only have 1 bgp controller by node
my $local_node = PVE::INotify::nodename();
my $controllernb = 0;
- foreach my $id (keys %{$controller_cfg->{ids}}) {
+ foreach my $id (keys %{ $controller_cfg->{ids} }) {
next if $id eq $controllerid;
my $controller = $controller_cfg->{ids}->{$id};
next if $controller->{type} ne "isis";
@@ -130,4 +131,3 @@ sub reload_controller {
1;
-
diff --git a/src/PVE/Network/SDN/Controllers/Plugin.pm b/src/PVE/Network/SDN/Controllers/Plugin.pm
index d6ffc5f..3de1af7 100644
--- a/src/PVE/Network/SDN/Controllers/Plugin.pm
+++ b/src/PVE/Network/SDN/Controllers/Plugin.pm
@@ -10,17 +10,23 @@ use PVE::Cluster;
use PVE::JSONSchema qw(get_standard_option);
use base qw(PVE::SectionConfig);
-PVE::Cluster::cfs_register_file('sdn/controllers.cfg',
+PVE::Cluster::cfs_register_file(
+ 'sdn/controllers.cfg',
sub { __PACKAGE__->parse_config(@_); },
- sub { __PACKAGE__->write_config(@_); }
+ sub { __PACKAGE__->write_config(@_); },
);
-PVE::JSONSchema::register_standard_option('pve-sdn-controller-id', {
- description => "The SDN controller object identifier.",
- type => 'string', format => 'pve-sdn-controller-id',
-});
+PVE::JSONSchema::register_standard_option(
+ 'pve-sdn-controller-id',
+ {
+ description => "The SDN controller object identifier.",
+ type => 'string',
+ format => 'pve-sdn-controller-id',
+ },
+);
PVE::JSONSchema::register_format('pve-sdn-controller-id', \&parse_sdn_controller_id);
+
sub parse_sdn_controller_id {
my ($id, $noerr) = @_;
@@ -35,13 +41,16 @@ sub parse_sdn_controller_id {
my $defaultData = {
propertyList => {
- type => {
- description => "Plugin type.",
- type => 'string', format => 'pve-configid',
- type => 'string',
- },
- controller => get_standard_option('pve-sdn-controller-id',
- { completion => \&PVE::Network::SDN::complete_sdn_controller }),
+ type => {
+ description => "Plugin type.",
+ type => 'string',
+ format => 'pve-configid',
+ type => 'string',
+ },
+ controller => get_standard_option(
+ 'pve-sdn-controller-id',
+ { completion => \&PVE::Network::SDN::complete_sdn_controller },
+ ),
},
};
@@ -54,11 +63,11 @@ sub parse_section_header {
if ($line =~ m/^(\S+):\s*(\S+)\s*$/) {
my ($type, $id) = (lc($1), $2);
- my $errmsg = undef; # set if you want to skip whole section
- eval { PVE::JSONSchema::pve_verify_configid($type); };
- $errmsg = $@ if $@;
- my $config = {}; # to return additional attributes
- return ($type, $id, $errmsg, $config);
+ my $errmsg = undef; # set if you want to skip whole section
+ eval { PVE::JSONSchema::pve_verify_configid($type); };
+ $errmsg = $@ if $@;
+ my $config = {}; # to return additional attributes
+ return ($type, $id, $errmsg, $config);
}
return undef;
}
@@ -75,7 +84,6 @@ sub generate_controller_config {
die "please implement inside plugin";
}
-
sub generate_controller_zone_config {
my ($class, $plugin_config, $controller, $controller_cfg, $id, $uplinks, $config) = @_;
@@ -135,7 +143,11 @@ sub get_router_id {
die "can't autofind a router-id value from ip or mac" if !$mac;
my @mac_bytes = split(':', $mac);
- return hex($mac_bytes[2]).".".hex($mac_bytes[3]).".".hex($mac_bytes[4]).".".hex($mac_bytes[5]);
+ return
+ hex($mac_bytes[2]) . "."
+ . hex($mac_bytes[3]) . "."
+ . hex($mac_bytes[4]) . "."
+ . hex($mac_bytes[5]);
}
1;
diff --git a/src/PVE/Network/SDN/Dhcp.pm b/src/PVE/Network/SDN/Dhcp.pm
index 8bbc210..8032b54 100644
--- a/src/PVE/Network/SDN/Dhcp.pm
+++ b/src/PVE/Network/SDN/Dhcp.pm
@@ -35,7 +35,7 @@ sub add_mapping {
my $macdb = PVE::Network::SDN::Ipams::read_macdb();
my $dhcp_plugin = PVE::Network::SDN::Dhcp::Plugin->lookup($dhcptype);
- $dhcp_plugin->add_ip_mapping($zoneid, $macdb, $mac, $ip4, $ip6)
+ $dhcp_plugin->add_ip_mapping($zoneid, $macdb, $mac, $ip4, $ip6);
}
sub remove_mapping {
@@ -70,60 +70,64 @@ sub regenerate_config {
my $any_zone_needs_dhcp = grep { $_->{dhcp} } values $zone_cfg->{ids}->%*;
foreach my $plugin_name (@$plugins) {
- my $plugin = PVE::Network::SDN::Dhcp::Plugin->lookup($plugin_name);
- eval { $plugin->before_regenerate(!$any_zone_needs_dhcp) };
- die "Could not run before_regenerate for DHCP plugin $plugin_name $@\n" if $@;
+ my $plugin = PVE::Network::SDN::Dhcp::Plugin->lookup($plugin_name);
+ eval { $plugin->before_regenerate(!$any_zone_needs_dhcp) };
+ die "Could not run before_regenerate for DHCP plugin $plugin_name $@\n" if $@;
}
- foreach my $zoneid (sort keys %{$zone_cfg->{ids}}) {
+ foreach my $zoneid (sort keys %{ $zone_cfg->{ids} }) {
my $zone = $zone_cfg->{ids}->{$zoneid};
next if !$zone->{dhcp};
- my $dhcp_plugin_name = $zone->{dhcp};
- my $dhcp_plugin = PVE::Network::SDN::Dhcp::Plugin->lookup($dhcp_plugin_name);
+ my $dhcp_plugin_name = $zone->{dhcp};
+ my $dhcp_plugin = PVE::Network::SDN::Dhcp::Plugin->lookup($dhcp_plugin_name);
- die "Could not find DHCP plugin: $dhcp_plugin_name" if !$dhcp_plugin;
+ die "Could not find DHCP plugin: $dhcp_plugin_name" if !$dhcp_plugin;
- eval { $dhcp_plugin->before_configure($zoneid, $zone) };
- die "Could not run before_configure for DHCP server $zoneid $@\n" if $@;
+ eval { $dhcp_plugin->before_configure($zoneid, $zone) };
+ die "Could not run before_configure for DHCP server $zoneid $@\n" if $@;
- for my $vnetid (sort keys %{$vnet_cfg->{ids}}) {
- my $vnet = $vnet_cfg->{ids}->{$vnetid};
- next if $vnet->{zone} ne $zoneid;
+ for my $vnetid (sort keys %{ $vnet_cfg->{ids} }) {
+ my $vnet = $vnet_cfg->{ids}->{$vnetid};
+ next if $vnet->{zone} ne $zoneid;
- my $config = [];
- my $subnets = PVE::Network::SDN::Vnets::get_subnets($vnetid);
+ my $config = [];
+ my $subnets = PVE::Network::SDN::Vnets::get_subnets($vnetid);
- foreach my $subnet_id (sort keys %{$subnets}) {
- my $subnet_config = $subnets->{$subnet_id};
- my $dhcp_ranges = PVE::Network::SDN::Subnets::get_dhcp_ranges($subnet_config);
+ foreach my $subnet_id (sort keys %{$subnets}) {
+ my $subnet_config = $subnets->{$subnet_id};
+ my $dhcp_ranges = PVE::Network::SDN::Subnets::get_dhcp_ranges($subnet_config);
- my ($zone, $subnet_network, $subnet_mask) = split(/-/, $subnet_id);
- next if $zone ne $zoneid;
+ my ($zone, $subnet_network, $subnet_mask) = split(/-/, $subnet_id);
+ next if $zone ne $zoneid;
- eval { $dhcp_plugin->configure_subnet($config, $zoneid, $vnetid, $subnet_config) };
- warn "Could not configure subnet $subnet_id: $@\n" if $@;
+ eval { $dhcp_plugin->configure_subnet($config, $zoneid, $vnetid, $subnet_config) };
+ warn "Could not configure subnet $subnet_id: $@\n" if $@;
- foreach my $dhcp_range (@$dhcp_ranges) {
- eval { $dhcp_plugin->configure_range($config, $zoneid, $vnetid, $subnet_config, $dhcp_range) };
- warn "Could not configure DHCP range for $subnet_id: $@\n" if $@;
- }
- }
+ foreach my $dhcp_range (@$dhcp_ranges) {
+ eval {
+ $dhcp_plugin->configure_range(
+ $config, $zoneid, $vnetid, $subnet_config, $dhcp_range,
+ );
+ };
+ warn "Could not configure DHCP range for $subnet_id: $@\n" if $@;
+ }
+ }
- eval { $dhcp_plugin->configure_vnet($config, $zoneid, $vnetid, $vnet) };
- warn "Could not configure vnet $vnetid: $@\n" if $@;
- }
+ eval { $dhcp_plugin->configure_vnet($config, $zoneid, $vnetid, $vnet) };
+ warn "Could not configure vnet $vnetid: $@\n" if $@;
+ }
- eval { $dhcp_plugin->after_configure($zoneid, !$any_zone_needs_dhcp) };
- warn "Could not run after_configure for DHCP server $zoneid $@\n" if $@;
+ eval { $dhcp_plugin->after_configure($zoneid, !$any_zone_needs_dhcp) };
+ warn "Could not run after_configure for DHCP server $zoneid $@\n" if $@;
}
foreach my $plugin_name (@$plugins) {
- my $plugin = PVE::Network::SDN::Dhcp::Plugin->lookup($plugin_name);
+ my $plugin = PVE::Network::SDN::Dhcp::Plugin->lookup($plugin_name);
- eval { $plugin->after_regenerate() };
- warn "Could not run after_regenerate for DHCP plugin $plugin_name $@\n" if $@;
+ eval { $plugin->after_regenerate() };
+ warn "Could not run after_regenerate for DHCP plugin $plugin_name $@\n" if $@;
}
}
diff --git a/src/PVE/Network/SDN/Dhcp/Dnsmasq.pm b/src/PVE/Network/SDN/Dhcp/Dnsmasq.pm
index 263d24f..dd34278 100644
--- a/src/PVE/Network/SDN/Dhcp/Dnsmasq.pm
+++ b/src/PVE/Network/SDN/Dhcp/Dnsmasq.pm
@@ -26,9 +26,9 @@ my sub assert_dnsmasq_installed {
my $bin_path = "/usr/sbin/dnsmasq";
if (!-e $bin_path) {
- return if $noerr; # just ignore, e.g., in case zone doesn't use DHCP at all
- log_warn("please install the 'dnsmasq' package in order to use the DHCP feature!");
- die "cannot reload with missing 'dnsmasq' package\n";
+ return if $noerr; # just ignore, e.g., in case zone doesn't use DHCP at all
+ log_warn("please install the 'dnsmasq' package in order to use the DHCP feature!");
+ die "cannot reload with missing 'dnsmasq' package\n";
}
return 1;
}
@@ -43,7 +43,8 @@ sub update_lease {
#update lease as ip could still be associated to an old removed mac
my $bus = Net::DBus->system();
my $dnsmasq = $bus->get_service("uk.org.thekelleys.dnsmasq.$dhcpid");
- my $manager = $dnsmasq->get_object("/uk/org/thekelleys/dnsmasq","uk.org.thekelleys.dnsmasq.$dhcpid");
+ my $manager =
+ $dnsmasq->get_object("/uk/org/thekelleys/dnsmasq", "uk.org.thekelleys.dnsmasq.$dhcpid");
my @hostname = unpack("C*", "*");
$manager->AddDhcpLease($ip4, $mac, \@hostname, undef, 0, 0, 0) if $ip4;
@@ -58,62 +59,69 @@ sub add_ip_mapping {
my $reload = undef;
my $appendFn = sub {
- open(my $in, '<', $ethers_file) or die "Could not open file '$ethers_file' $!\n";
- open(my $out, '>', $ethers_tmp_file) or die "Could not open file '$ethers_tmp_file' $!\n";
-
- my $match = undef;
-
- while (my $line = <$in>) {
- chomp($line);
- my $parsed_ip4 = undef;
- my $parsed_ip6 = undef;
- my ($parsed_mac, $parsed_ip1, $parsed_ip2) = split(/,/, $line);
-
- if ($parsed_ip2) {
- $parsed_ip4 = $parsed_ip1;
- $parsed_ip6 = $parsed_ip2;
- } elsif (Net::IP::ip_is_ipv4($parsed_ip1)) {
- $parsed_ip4 = $parsed_ip1;
- } else {
- $parsed_ip6 = $parsed_ip1;
- }
- $parsed_ip6 = $1 if $parsed_ip6 && $parsed_ip6 =~ m/\[(\S+)\]/;
-
- #delete changed
- if (!defined($macdb->{macs}->{$parsed_mac}) ||
- ($parsed_ip4 && $macdb->{macs}->{$parsed_mac}->{'ip4'} && $macdb->{macs}->{$parsed_mac}->{'ip4'} ne $parsed_ip4) ||
- ($parsed_ip6 && $macdb->{macs}->{$parsed_mac}->{'ip6'} && $macdb->{macs}->{$parsed_mac}->{'ip6'} ne $parsed_ip6)) {
- $reload = 1;
- next;
- }
-
- if ($parsed_mac eq $mac) {
- $match = 1 if $ip4 && $parsed_ip4 && $ip4;
- $match = 1 if $ip6 && $parsed_ip6 && $ip6;
- }
-
- print $out "$line\n";
- }
-
- if(!$match) {
- my $reservation = $mac;
- $reservation .= ",$ip4" if $ip4;
- $reservation .= ",[$ip6]" if $ip6;
- print $out "$reservation\n";
- $reload = 1;
- }
-
- close $in;
- close $out;
- move $ethers_tmp_file, $ethers_file;
- chmod 0644, $ethers_file;
+ open(my $in, '<', $ethers_file) or die "Could not open file '$ethers_file' $!\n";
+ open(my $out, '>', $ethers_tmp_file)
+ or die "Could not open file '$ethers_tmp_file' $!\n";
+
+ my $match = undef;
+
+ while (my $line = <$in>) {
+ chomp($line);
+ my $parsed_ip4 = undef;
+ my $parsed_ip6 = undef;
+ my ($parsed_mac, $parsed_ip1, $parsed_ip2) = split(/,/, $line);
+
+ if ($parsed_ip2) {
+ $parsed_ip4 = $parsed_ip1;
+ $parsed_ip6 = $parsed_ip2;
+ } elsif (Net::IP::ip_is_ipv4($parsed_ip1)) {
+ $parsed_ip4 = $parsed_ip1;
+ } else {
+ $parsed_ip6 = $parsed_ip1;
+ }
+ $parsed_ip6 = $1 if $parsed_ip6 && $parsed_ip6 =~ m/\[(\S+)\]/;
+
+ #delete changed
+ if (
+ !defined($macdb->{macs}->{$parsed_mac})
+ || ($parsed_ip4
+ && $macdb->{macs}->{$parsed_mac}->{'ip4'}
+ && $macdb->{macs}->{$parsed_mac}->{'ip4'} ne $parsed_ip4)
+ || ($parsed_ip6
+ && $macdb->{macs}->{$parsed_mac}->{'ip6'}
+ && $macdb->{macs}->{$parsed_mac}->{'ip6'} ne $parsed_ip6)
+ ) {
+ $reload = 1;
+ next;
+ }
+
+ if ($parsed_mac eq $mac) {
+ $match = 1 if $ip4 && $parsed_ip4 && $ip4;
+ $match = 1 if $ip6 && $parsed_ip6 && $ip6;
+ }
+
+ print $out "$line\n";
+ }
+
+ if (!$match) {
+ my $reservation = $mac;
+ $reservation .= ",$ip4" if $ip4;
+ $reservation .= ",[$ip6]" if $ip6;
+ print $out "$reservation\n";
+ $reload = 1;
+ }
+
+ close $in;
+ close $out;
+ move $ethers_tmp_file, $ethers_file;
+ chmod 0644, $ethers_file;
};
PVE::Tools::lock_file($ethers_file, 10, $appendFn);
if ($@) {
- warn "Unable to add $mac to the dnsmasq configuration: $@\n";
- return;
+ warn "Unable to add $mac to the dnsmasq configuration: $@\n";
+ return;
}
my $service_name = "dnsmasq\@$dhcpid";
@@ -125,29 +133,30 @@ sub configure_subnet {
my ($class, $config, $dhcpid, $vnetid, $subnet_config) = @_;
die "No gateway defined for subnet $subnet_config->{id}"
- if !$subnet_config->{gateway};
+ if !$subnet_config->{gateway};
my $tag = $subnet_config->{id};
my ($zone, $network, $mask) = split(/-/, $tag);
if (Net::IP::ip_is_ipv4($network)) {
- $mask = (2 ** $mask - 1) << (32 - $mask);
- $mask = join( '.', unpack( "C4", pack( "N", $mask ) ) );
+ $mask = (2**$mask - 1) << (32 - $mask);
+ $mask = join('.', unpack("C4", pack("N", $mask)));
}
push @{$config}, "dhcp-range=set:$tag,$network,static,$mask,infinite";
my $option_string;
if (ip_is_ipv6($subnet_config->{network})) {
- $option_string = 'option6';
+ $option_string = 'option6';
} else {
- $option_string = 'option';
- push @{$config}, "dhcp-option=tag:$tag,$option_string:router,$subnet_config->{gateway}";
+ $option_string = 'option';
+ push @{$config}, "dhcp-option=tag:$tag,$option_string:router,$subnet_config->{gateway}";
}
- push @{$config}, "dhcp-option=tag:$tag,$option_string:dns-server,$subnet_config->{'dhcp-dns-server'}"
- if $subnet_config->{'dhcp-dns-server'};
+ push @{$config},
+ "dhcp-option=tag:$tag,$option_string:dns-server,$subnet_config->{'dhcp-dns-server'}"
+ if $subnet_config->{'dhcp-dns-server'};
}
sub configure_range {
@@ -162,8 +171,8 @@ sub configure_vnet {
push @{$config}, "interface=$vnetid";
PVE::Tools::file_set_contents(
- "$DNSMASQ_CONFIG_ROOT/$dhcpid/10-$vnetid.conf",
- join("\n", @{$config}) . "\n"
+ "$DNSMASQ_CONFIG_ROOT/$dhcpid/10-$vnetid.conf",
+ join("\n", @{$config}) . "\n",
);
}
@@ -197,8 +206,7 @@ sub before_configure {
DBUSCFG
PVE::Tools::file_set_contents(
- "/etc/dbus-1/system.d/dnsmasq.$dhcpid.conf",
- $dbus_config
+ "/etc/dbus-1/system.d/dnsmasq.$dhcpid.conf", $dbus_config,
);
my $config_directory = "$DNSMASQ_CONFIG_ROOT/$dhcpid";
@@ -211,8 +219,7 @@ DNSMASQ_OPTS="--conf-file=/dev/null --enable-dbus=uk.org.thekelleys.dnsmasq.$dhc
CFG
PVE::Tools::file_set_contents(
- "$DNSMASQ_DEFAULT_ROOT/dnsmasq.$dhcpid",
- $default_config
+ "$DNSMASQ_DEFAULT_ROOT/dnsmasq.$dhcpid", $default_config,
);
my $mtu = PVE::Network::SDN::Zones::get_mtu($zone_cfg);
@@ -245,15 +252,18 @@ dhcp-ignore-names=tag:wpad-ignore
CFG
PVE::Tools::file_set_contents(
- "$config_directory/00-default.conf",
- $default_dnsmasq_config
+ "$config_directory/00-default.conf", $default_dnsmasq_config,
);
my @config_files = ();
- PVE::Tools::dir_glob_foreach($config_directory, '10-.*\.conf', sub {
- my ($file) = @_;
- push @config_files, "$config_directory/$file";
- });
+ PVE::Tools::dir_glob_foreach(
+ $config_directory,
+ '10-.*\.conf',
+ sub {
+ my ($file) = @_;
+ push @config_files, "$config_directory/$file";
+ },
+ );
unlink @config_files;
}
diff --git a/src/PVE/Network/SDN/Dhcp/Plugin.pm b/src/PVE/Network/SDN/Dhcp/Plugin.pm
index 1757915..b5d32fa 100644
--- a/src/PVE/Network/SDN/Dhcp/Plugin.pm
+++ b/src/PVE/Network/SDN/Dhcp/Plugin.pm
@@ -10,11 +10,11 @@ use base qw(PVE::SectionConfig);
my $defaultData = {
propertyList => {
- type => {
- description => "Plugin type.",
- format => 'pve-configid',
- type => 'string',
- },
+ type => {
+ description => "Plugin type.",
+ format => 'pve-configid',
+ type => 'string',
+ },
},
};
diff --git a/src/PVE/Network/SDN/Dns.pm b/src/PVE/Network/SDN/Dns.pm
index 581b467..76833ea 100644
--- a/src/PVE/Network/SDN/Dns.pm
+++ b/src/PVE/Network/SDN/Dns.pm
@@ -15,7 +15,6 @@ use PVE::Network::SDN::Dns::Plugin;
PVE::Network::SDN::Dns::PowerdnsPlugin->register();
PVE::Network::SDN::Dns::Plugin->init();
-
sub sdn_dns_config {
my ($cfg, $id, $noerr) = @_;
@@ -41,7 +40,7 @@ sub write_config {
sub sdn_dns_ids {
my ($cfg) = @_;
- return keys %{$cfg->{ids}};
+ return keys %{ $cfg->{ids} };
}
sub complete_sdn_dns {
@@ -49,7 +48,7 @@ sub complete_sdn_dns {
my $cfg = PVE::Network::SDN::Dns::config();
- return $cmdname eq 'add' ? [] : [ PVE::Network::SDN::Dns::sdn_dns_ids($cfg) ];
+ return $cmdname eq 'add' ? [] : [PVE::Network::SDN::Dns::sdn_dns_ids($cfg)];
}
1;
diff --git a/src/PVE/Network/SDN/Dns/Plugin.pm b/src/PVE/Network/SDN/Dns/Plugin.pm
index e5daa7d..2864d4c 100644
--- a/src/PVE/Network/SDN/Dns/Plugin.pm
+++ b/src/PVE/Network/SDN/Dns/Plugin.pm
@@ -12,22 +12,29 @@ use LWP::UserAgent;
use PVE::JSONSchema qw(get_standard_option);
use base qw(PVE::SectionConfig);
-PVE::Cluster::cfs_register_file('sdn/dns.cfg',
- sub { __PACKAGE__->parse_config(@_); },
- sub { __PACKAGE__->write_config(@_); });
-
-PVE::JSONSchema::register_standard_option('pve-sdn-dns-id', {
- description => "The SDN dns object identifier.",
- type => 'string', format => 'pve-sdn-dns-id',
-});
+PVE::Cluster::cfs_register_file(
+ 'sdn/dns.cfg',
+ sub { __PACKAGE__->parse_config(@_); },
+ sub { __PACKAGE__->write_config(@_); },
+);
+
+PVE::JSONSchema::register_standard_option(
+ 'pve-sdn-dns-id',
+ {
+ description => "The SDN dns object identifier.",
+ type => 'string',
+ format => 'pve-sdn-dns-id',
+ },
+);
PVE::JSONSchema::register_format('pve-sdn-dns-id', \&parse_sdn_dns_id);
+
sub parse_sdn_dns_id {
my ($id, $noerr) = @_;
if ($id !~ m/^[a-z][a-z0-9]*[a-z0-9]$/i) {
- return undef if $noerr;
- die "dns ID '$id' contains illegal characters\n";
+ return undef if $noerr;
+ die "dns ID '$id' contains illegal characters\n";
}
return $id;
}
@@ -35,15 +42,18 @@ sub parse_sdn_dns_id {
my $defaultData = {
propertyList => {
- type => {
- description => "Plugin type.",
- type => 'string', format => 'pve-configid',
- },
+ type => {
+ description => "Plugin type.",
+ type => 'string',
+ format => 'pve-configid',
+ },
ttl => { type => 'integer', optional => 1 },
reversev6mask => { type => 'integer', optional => 1 },
- dns => get_standard_option('pve-sdn-dns-id',
- { completion => \&PVE::Network::SDN::Dns::complete_sdn_dns }),
- fingerprint => get_standard_option('fingerprint-sha256', { optional => 1 }),
+ dns => get_standard_option(
+ 'pve-sdn-dns-id',
+ { completion => \&PVE::Network::SDN::Dns::complete_sdn_dns },
+ ),
+ fingerprint => get_standard_option('fingerprint-sha256', { optional => 1 }),
},
};
@@ -56,16 +66,15 @@ sub parse_section_header {
if ($line =~ m/^(\S+):\s*(\S+)\s*$/) {
my ($type, $id) = (lc($1), $2);
- my $errmsg = undef; # set if you want to skip whole section
- eval { PVE::JSONSchema::pve_verify_configid($type); };
- $errmsg = $@ if $@;
- my $config = {}; # to return additional attributes
- return ($type, $id, $errmsg, $config);
+ my $errmsg = undef; # set if you want to skip whole section
+ eval { PVE::JSONSchema::pve_verify_configid($type); };
+ $errmsg = $@ if $@;
+ my $config = {}; # to return additional attributes
+ return ($type, $id, $errmsg, $config);
}
return undef;
}
-
sub add_a_record {
my ($class, $plugin_config, $zone, $hostname, $ip, $noerr) = @_;
diff --git a/src/PVE/Network/SDN/Dns/PowerdnsPlugin.pm b/src/PVE/Network/SDN/Dns/PowerdnsPlugin.pm
index aad8b6f..dfb7932 100644
--- a/src/PVE/Network/SDN/Dns/PowerdnsPlugin.pm
+++ b/src/PVE/Network/SDN/Dns/PowerdnsPlugin.pm
@@ -19,28 +19,28 @@ sub type {
sub properties {
return {
- url => {
- type => 'string',
- },
- key => {
- type => 'string',
- },
- reversemaskv6 => {
- type => 'integer'
- },
+ url => {
+ type => 'string',
+ },
+ key => {
+ type => 'string',
+ },
+ reversemaskv6 => {
+ type => 'integer',
+ },
};
}
sub options {
return {
- url => { optional => 0},
- key => { optional => 0 },
- ttl => { optional => 1 },
- reversemaskv6 => {
- optional => 1,
- description => "force a different netmask for the ipv6 reverse zone name.",
- },
- fingerprint => { optional => 1 },
+ url => { optional => 0 },
+ key => { optional => 0 },
+ ttl => { optional => 1 },
+ reversemaskv6 => {
+ optional => 1,
+ description => "force a different netmask for the ipv6 reverse zone name.",
+ },
+ fingerprint => { optional => 1 },
};
}
@@ -48,11 +48,11 @@ my sub powerdns_api_request {
my ($config, $method, $path, $params) = @_;
return PVE::Network::SDN::api_request(
- $method,
- "$config->{url}${path}",
- ['Content-Type' => 'application/json; charset=UTF-8', 'X-API-Key' => $config->{key}],
- $params,
- $config->{fingerprint},
+ $method,
+ "$config->{url}${path}",
+ ['Content-Type' => 'application/json; charset=UTF-8', 'X-API-Key' => $config->{key}],
+ $params,
+ $config->{fingerprint},
);
}
@@ -63,35 +63,35 @@ sub add_a_record {
my $ttl = $plugin_config->{ttl} ? $plugin_config->{ttl} : 14400;
my $type = Net::IP::ip_is_ipv6($ip) ? "AAAA" : "A";
- my $fqdn = $hostname.".".$zone.".";
+ my $fqdn = $hostname . "." . $zone . ".";
my $zonecontent = get_zone_content($plugin_config, $zone);
my $existing_rrset = get_zone_rrset($zonecontent, $fqdn, $type);
my $final_records = [];
- for my $record (@{$existing_rrset->{records}}) {
- if ($record->{content} eq $ip) {
- return; # the record already exist so return early
- }
- push @$final_records, $record;
+ for my $record (@{ $existing_rrset->{records} }) {
+ if ($record->{content} eq $ip) {
+ return; # the record already exist so return early
+ }
+ push @$final_records, $record;
}
my $record = {
- content => $ip,
- disabled => JSON::false,
- name => $fqdn,
- type => $type,
+ content => $ip,
+ disabled => JSON::false,
+ name => $fqdn,
+ type => $type,
};
push @$final_records, $record;
my $params = {
- rrsets => [{
- name => $fqdn,
- type => $type,
- ttl => $ttl,
- changetype => "REPLACE",
- records => $final_records,
- }],
+ rrsets => [{
+ name => $fqdn,
+ type => $type,
+ ttl => $ttl,
+ changetype => "REPLACE",
+ records => $final_records,
+ }],
};
eval { powerdns_api_request($plugin_config, 'PATCH', "/zones/$zone", $params) };
@@ -109,20 +109,20 @@ sub add_ptr_record {
my $type = "PTR";
my $record = {
- content => $hostname,
- disabled => JSON::false,
- name => $reverseip,
- type => $type,
+ content => $hostname,
+ disabled => JSON::false,
+ name => $reverseip,
+ type => $type,
};
my $params = {
- rrsets => [{
- name => $reverseip,
- type => $type,
- ttl => $ttl,
- changetype => "REPLACE",
- records => [ $record ],
- }],
+ rrsets => [{
+ name => $reverseip,
+ type => $type,
+ ttl => $ttl,
+ changetype => "REPLACE",
+ records => [$record],
+ }],
};
eval { powerdns_api_request($plugin_config, 'PATCH', "/zones/$zone", $params) };
@@ -132,33 +132,33 @@ sub add_ptr_record {
sub del_a_record {
my ($class, $plugin_config, $zone, $hostname, $ip, $noerr) = @_;
- my $fqdn = $hostname.".".$zone.".";
+ my $fqdn = $hostname . "." . $zone . ".";
my $type = Net::IP::ip_is_ipv6($ip) ? "AAAA" : "A";
my $zonecontent = get_zone_content($plugin_config, $zone);
my $existing_rrset = get_zone_rrset($zonecontent, $fqdn, $type);
- my $final_records = [ grep { $_->{content} ne $ip } $existing_rrset->{records}->@* ];
+ my $final_records = [grep { $_->{content} ne $ip } $existing_rrset->{records}->@*];
my $final_records_size = scalar($final_records->@*);
# early return if we didn't find our record (i.e., un/filtered record sets have the same size)
return if scalar($existing_rrset->{records}->@*) == $final_records_size;
my $rrset = {
- name => $fqdn,
- type => $type,
+ name => $fqdn,
+ type => $type,
};
if ($final_records_size > 0) {
- # if we still have other records, we rewrite them with the $ip removed
- $rrset->{ttl} = $existing_rrset->{ttl};
- $rrset->{changetype} = "REPLACE";
- $rrset->{records} = $final_records;
+ # if we still have other records, we rewrite them with the $ip removed
+ $rrset->{ttl} = $existing_rrset->{ttl};
+ $rrset->{changetype} = "REPLACE";
+ $rrset->{records} = $final_records;
} else {
- $rrset->{changetype} = "DELETE";
- $rrset->{records} = [];
+ $rrset->{changetype} = "DELETE";
+ $rrset->{records} = [];
}
- my $params = { rrsets => [ $rrset ] };
+ my $params = { rrsets => [$rrset] };
eval { powerdns_api_request($plugin_config, 'PATCH', "/zones/$zone", $params) };
die "error delete $fqdn from zone $zone: $@" if $@ && !$noerr;
@@ -172,12 +172,12 @@ sub del_ptr_record {
my $type = "PTR";
my $params = {
- rrsets => [{
- name => $reverseip,
- type => $type,
- changetype => "DELETE",
- records => [],
- }],
+ rrsets => [{
+ name => $reverseip,
+ type => $type,
+ changetype => "DELETE",
+ records => [],
+ }],
};
eval { powerdns_api_request($plugin_config, 'PATCH', "/zones/$zone", $params) };
@@ -201,47 +201,46 @@ sub get_reversedns_zone {
my $zone = "";
if (Net::IP::ip_is_ipv4($ip)) {
- my ($ipblock1, $ipblock2, $ipblock3, $ipblock4) = split(/\./, $ip);
+ my ($ipblock1, $ipblock2, $ipblock3, $ipblock4) = split(/\./, $ip);
my $ipv4 = NetAddr::IP->new($cidr);
- #private addresse #powerdns built-in private zone : serve-rfc1918
- if($ipv4->is_rfc1918()) {
- if ($ipblock1 == 192) {
- $zone = "168.192.in-addr.arpa.";
- } elsif ($ipblock1 == 172) {
- $zone = "16-31.172.in-addr.arpa.";
- } elsif ($ipblock1 == 10) {
- $zone = "10.in-addr.arpa.";
- }
-
- } else {
- # public ipv4 : RIPE,ARIN,AFRNIC
- # Delegations can be managed in IPv4 on bit boundaries (/8, /16 or /24s), and IPv6
- # networks can be managed on nibble boundaries (every 4 bits of the IPv6 address)
- # One or more /24 type zones need to be created if your address space has a prefix
- # length between /17 and /24.
- # If your prefix length is between /16 and /9 you will have to request one or more
- # delegations for /16 type zones.
-
- if ($mask <= 24) {
- $zone = "$ipblock3.$ipblock2.$ipblock1.in-addr.arpa.";
- } elsif ($mask <= 16) {
- $zone = "$ipblock2.$ipblock1.in-addr.arpa.";
- } elsif ($mask <= 8) {
- $zone = "$ipblock1.in-addr.arpa.";
- }
- }
+ #private addresse #powerdns built-in private zone : serve-rfc1918
+ if ($ipv4->is_rfc1918()) {
+ if ($ipblock1 == 192) {
+ $zone = "168.192.in-addr.arpa.";
+ } elsif ($ipblock1 == 172) {
+ $zone = "16-31.172.in-addr.arpa.";
+ } elsif ($ipblock1 == 10) {
+ $zone = "10.in-addr.arpa.";
+ }
+
+ } else {
+ # public ipv4 : RIPE,ARIN,AFRNIC
+ # Delegations can be managed in IPv4 on bit boundaries (/8, /16 or /24s), and IPv6
+ # networks can be managed on nibble boundaries (every 4 bits of the IPv6 address)
+ # One or more /24 type zones need to be created if your address space has a prefix
+ # length between /17 and /24.
+ # If your prefix length is between /16 and /9 you will have to request one or more
+ # delegations for /16 type zones.
+
+ if ($mask <= 24) {
+ $zone = "$ipblock3.$ipblock2.$ipblock1.in-addr.arpa.";
+ } elsif ($mask <= 16) {
+ $zone = "$ipblock2.$ipblock1.in-addr.arpa.";
+ } elsif ($mask <= 8) {
+ $zone = "$ipblock1.in-addr.arpa.";
+ }
+ }
} else {
- $mask = $plugin_config->{reversemaskv6} if $plugin_config->{reversemaskv6};
- die "reverse dns zone mask need to be a multiple of 4" if ($mask % 4);
- my $networkv6 = NetAddr::IP->new($cidr)->network();
- $zone = Net::IP->new($networkv6)->reverse_ip();
+ $mask = $plugin_config->{reversemaskv6} if $plugin_config->{reversemaskv6};
+ die "reverse dns zone mask need to be a multiple of 4" if ($mask % 4);
+ my $networkv6 = NetAddr::IP->new($cidr)->network();
+ $zone = Net::IP->new($networkv6)->reverse_ip();
}
return $zone;
}
-
sub on_update_hook {
my ($class, $plugin_config) = @_;
@@ -250,7 +249,6 @@ sub on_update_hook {
die "dns api error: $@" if $@;
}
-
sub get_zone_content {
my ($plugin_config, $zone) = @_;
@@ -264,12 +262,11 @@ sub get_zone_content {
sub get_zone_rrset {
my ($zonecontent, $name, $type) = @_;
- for my $rrset (@{$zonecontent->{rrsets}}) {
- return $rrset if $rrset->{name} eq $name and ($rrset->{type} eq $type);
+ for my $rrset (@{ $zonecontent->{rrsets} }) {
+ return $rrset if $rrset->{name} eq $name and ($rrset->{type} eq $type);
}
return; # not found
}
1;
-
diff --git a/src/PVE/Network/SDN/Ipams.pm b/src/PVE/Network/SDN/Ipams.pm
index c689b8f..7ec0f06 100644
--- a/src/PVE/Network/SDN/Ipams.pm
+++ b/src/PVE/Network/SDN/Ipams.pm
@@ -26,24 +26,26 @@ my $macdb_filename_legacy = 'priv/macs.db';
cfs_register_file(
$macdb_filename,
sub {
- my ($filename , $data) = @_;
- if (defined($data)) {
- return json_reader($filename, $data);
- } else {
- # TODO: remove legacy cache file handling with PVE 9+ after ensuring all call sites got
- # switched over.
- return cfs_read_file($macdb_filename_legacy);
- }
+ my ($filename, $data) = @_;
+ if (defined($data)) {
+ return json_reader($filename, $data);
+ } else {
+ # TODO: remove legacy cache file handling with PVE 9+ after ensuring all call sites got
+ # switched over.
+ return cfs_read_file($macdb_filename_legacy);
+ }
},
sub {
- my ($filename , $data) = @_;
- # TODO: remove below with PVE 9+, add a pve8to9 check to allow doing so.
- if (-e $macdb_filename_legacy && -e $macdb_filename) {
- # only clean-up if we succeeded to write the new path at least once
- unlink $macdb_filename_legacy or $!{ENOENT} or warn "failed to unlink legacy MAC cache - $!\n";
- }
- return json_writer->($filename, $data);
- }
+ my ($filename, $data) = @_;
+ # TODO: remove below with PVE 9+, add a pve8to9 check to allow doing so.
+ if (-e $macdb_filename_legacy && -e $macdb_filename) {
+ # only clean-up if we succeeded to write the new path at least once
+ unlink $macdb_filename_legacy
+ or $!{ENOENT}
+ or warn "failed to unlink legacy MAC cache - $!\n";
+ }
+ return json_writer->($filename, $data);
+ },
);
# drop reading $macdb_filename_legacy with PVE 9+ - for now do not write it anymore.
@@ -76,31 +78,40 @@ sub write_macdb {
sub add_cache_mac_ip {
my ($mac, $ip) = @_;
- cfs_lock_file($macdb_filename, undef, sub {
- my $db = read_macdb();
- if (Net::IP::ip_is_ipv4($ip)) {
- $db->{macs}->{$mac}->{ip4} = $ip;
- } else {
- $db->{macs}->{$mac}->{ip6} = $ip;
- }
- write_macdb($db);
- });
+ cfs_lock_file(
+ $macdb_filename,
+ undef,
+ sub {
+ my $db = read_macdb();
+ if (Net::IP::ip_is_ipv4($ip)) {
+ $db->{macs}->{$mac}->{ip4} = $ip;
+ } else {
+ $db->{macs}->{$mac}->{ip6} = $ip;
+ }
+ write_macdb($db);
+ },
+ );
warn "$@" if $@;
}
sub del_cache_mac_ip {
my ($mac, $ip) = @_;
- cfs_lock_file($macdb_filename, undef, sub {
- my $db = read_macdb();
- if (Net::IP::ip_is_ipv4($ip)) {
- delete $db->{macs}->{$mac}->{ip4};
- } else {
- delete $db->{macs}->{$mac}->{ip6};
- }
- delete $db->{macs}->{$mac} if !defined($db->{macs}->{$mac}->{ip4}) && !defined($db->{macs}->{$mac}->{ip6});
- write_macdb($db);
- });
+ cfs_lock_file(
+ $macdb_filename,
+ undef,
+ sub {
+ my $db = read_macdb();
+ if (Net::IP::ip_is_ipv4($ip)) {
+ delete $db->{macs}->{$mac}->{ip4};
+ } else {
+ delete $db->{macs}->{$mac}->{ip6};
+ }
+ delete $db->{macs}->{$mac}
+ if !defined($db->{macs}->{$mac}->{ip4}) && !defined($db->{macs}->{$mac}->{ip6});
+ write_macdb($db);
+ },
+ );
warn "$@" if $@;
}
@@ -138,7 +149,7 @@ sub write_config {
sub sdn_ipams_ids {
my ($cfg) = @_;
- return keys %{$cfg->{ids}};
+ return keys %{ $cfg->{ids} };
}
sub complete_sdn_vnet {
@@ -146,7 +157,7 @@ sub complete_sdn_vnet {
my $cfg = PVE::Network::SDN::Ipams::config();
- return $cmdname eq 'add' ? [] : [ PVE::Network::SDN::Vnets::sdn_ipams_ids($cfg) ];
+ return $cmdname eq 'add' ? [] : [PVE::Network::SDN::Vnets::sdn_ipams_ids($cfg)];
}
sub get_ips_from_mac {
@@ -157,7 +168,8 @@ sub get_ips_from_mac {
my $plugin_config = get_plugin_config($zone);
my $plugin = PVE::Network::SDN::Ipams::Plugin->lookup($plugin_config->{type});
- ($macdb->{macs}->{$mac}->{ip4}, $macdb->{macs}->{$mac}->{ip6}) = $plugin->get_ips_from_mac($plugin_config, $mac, $zoneid);
+ ($macdb->{macs}->{$mac}->{ip4}, $macdb->{macs}->{$mac}->{ip6}) =
+ $plugin->get_ips_from_mac($plugin_config, $mac, $zoneid);
write_macdb($macdb);
diff --git a/src/PVE/Network/SDN/Ipams/NetboxPlugin.pm b/src/PVE/Network/SDN/Ipams/NetboxPlugin.pm
index 97a0c3f..e118d03 100644
--- a/src/PVE/Network/SDN/Ipams/NetboxPlugin.pm
+++ b/src/PVE/Network/SDN/Ipams/NetboxPlugin.pm
@@ -13,13 +13,12 @@ sub type {
}
sub properties {
- return {
- };
+ return {};
}
sub options {
return {
- url => { optional => 0},
+ url => { optional => 0 },
token => { optional => 0 },
fingerprint => { optional => 1 },
};
@@ -29,14 +28,14 @@ sub netbox_api_request {
my ($config, $method, $path, $params) = @_;
return PVE::Network::SDN::api_request(
- $method,
- "$config->{url}${path}",
- [
- 'Content-Type' => 'application/json; charset=UTF-8',
- 'Authorization' => "token $config->{token}"
- ],
- $params,
- $config->{fingerprint},
+ $method,
+ "$config->{url}${path}",
+ [
+ 'Content-Type' => 'application/json; charset=UTF-8',
+ 'Authorization' => "token $config->{token}",
+ ],
+ $params,
+ $config->{fingerprint},
);
}
@@ -44,14 +43,20 @@ sub add_dhcp_range {
my ($config, $dhcp_range, $noerr) = @_;
my $result = eval {
- netbox_api_request($config, "POST", "/ipam/ip-ranges/", {
- start_address => $dhcp_range->{'start-address'},
- end_address => $dhcp_range->{'end-address'},
- });
+ netbox_api_request(
+ $config,
+ "POST",
+ "/ipam/ip-ranges/",
+ {
+ start_address => $dhcp_range->{'start-address'},
+ end_address => $dhcp_range->{'end-address'},
+ },
+ );
};
if ($@) {
- return if $noerr;
- die "could not create ip range $dhcp_range->{'start-address'}:$dhcp_range->{'end-address'}: $@";
+ return if $noerr;
+ die
+ "could not create ip range $dhcp_range->{'start-address'}:$dhcp_range->{'end-address'}: $@";
}
return $result->{id};
@@ -60,9 +65,7 @@ sub add_dhcp_range {
sub del_dhcp_range {
my ($config, $id, $noerr) = @_;
- eval {
- netbox_api_request($config, "DELETE", "/ipam/ip-ranges/$id/");
- };
+ eval { netbox_api_request($config, "DELETE", "/ipam/ip-ranges/$id/"); };
die "could not create dhcp range: $@" if $@ && !$noerr;
}
@@ -76,23 +79,19 @@ sub add_subnet {
my $gateway = $subnet->{gateway};
if (get_prefix_id($plugin_config, $cidr, $noerr)) {
- return if $noerr;
- die "prefix $cidr already exists in netbox";
+ return if $noerr;
+ die "prefix $cidr already exists in netbox";
}
- eval {
- netbox_api_request($plugin_config, "POST", "/ipam/prefixes/", {
- prefix => $cidr
- });
- };
+ eval { netbox_api_request($plugin_config, "POST", "/ipam/prefixes/", { prefix => $cidr }); };
if ($@) {
- return if $noerr;
- die "error adding subnet to ipam: $@";
+ return if $noerr;
+ die "error adding subnet to ipam: $@";
}
my $dhcp_ranges = PVE::Network::SDN::Subnets::get_dhcp_ranges($subnet);
for my $dhcp_range (@$dhcp_ranges) {
- add_dhcp_range($plugin_config, $dhcp_range, $noerr);
+ add_dhcp_range($plugin_config, $dhcp_range, $noerr);
}
}
@@ -105,48 +104,49 @@ sub update_subnet {
my $new_dhcp_ranges = PVE::Network::SDN::Subnets::get_dhcp_ranges($subnet);
my $hash_range = sub {
- my ($dhcp_range) = @_;
- "$dhcp_range->{'start-address'} - $dhcp_range->{'end-address'}"
+ my ($dhcp_range) = @_;
+ "$dhcp_range->{'start-address'} - $dhcp_range->{'end-address'}";
};
my $old_lookup = {};
for my $dhcp_range (@$old_dhcp_ranges) {
- my $hash = $hash_range->($dhcp_range);
- $old_lookup->{$hash} = undef;
+ my $hash = $hash_range->($dhcp_range);
+ $old_lookup->{$hash} = undef;
}
my $new_lookup = {};
for my $dhcp_range (@$new_dhcp_ranges) {
- my $hash = $hash_range->($dhcp_range);
- $new_lookup->{$hash} = undef;
+ my $hash = $hash_range->($dhcp_range);
+ $new_lookup->{$hash} = undef;
}
my $to_delete_ids = ();
# delete first so we don't get errors with overlapping ranges
for my $dhcp_range (@$old_dhcp_ranges) {
- my $hash = $hash_range->($dhcp_range);
+ my $hash = $hash_range->($dhcp_range);
- if (exists($new_lookup->{$hash})) {
- next;
- }
+ if (exists($new_lookup->{$hash})) {
+ next;
+ }
- my $internalid = get_iprange_id($plugin_config, $dhcp_range, $noerr);
+ my $internalid = get_iprange_id($plugin_config, $dhcp_range, $noerr);
- # definedness check, because ID could be 0
- if (!defined($internalid)) {
- warn "could not find id for ip range $dhcp_range->{'start-address'}:$dhcp_range->{'end-address'}";
- next;
- }
+ # definedness check, because ID could be 0
+ if (!defined($internalid)) {
+ warn
+ "could not find id for ip range $dhcp_range->{'start-address'}:$dhcp_range->{'end-address'}";
+ next;
+ }
- del_dhcp_range($plugin_config, $internalid, $noerr);
+ del_dhcp_range($plugin_config, $internalid, $noerr);
}
for my $dhcp_range (@$new_dhcp_ranges) {
- my $hash = $hash_range->($dhcp_range);
+ my $hash = $hash_range->($dhcp_range);
- add_dhcp_range($plugin_config, $dhcp_range, $noerr)
- if !exists($old_lookup->{$hash});
+ add_dhcp_range($plugin_config, $dhcp_range, $noerr)
+ if !exists($old_lookup->{$hash});
}
}
@@ -159,105 +159,126 @@ sub del_subnet {
# definedness check, because ID could be 0
if (!defined($internalid)) {
- warn "could not find id for ip prefix $cidr";
- return;
+ warn "could not find id for ip prefix $cidr";
+ return;
}
if (!is_prefix_empty($plugin_config, $cidr, $noerr)) {
- return if $noerr;
- die "not deleting prefix $cidr because it still contains entries";
+ return if $noerr;
+ die "not deleting prefix $cidr because it still contains entries";
}
# last IP is assumed to be the gateway, delete it
if (!$class->del_ip($plugin_config, $subnetid, $subnet, $subnet->{gateway}, $noerr)) {
- return if $noerr;
- die "could not delete gateway ip from subnet $subnetid";
+ return if $noerr;
+ die "could not delete gateway ip from subnet $subnetid";
}
my $dhcp_ranges = PVE::Network::SDN::Subnets::get_dhcp_ranges($subnet);
for my $dhcp_range (@$dhcp_ranges) {
- my $internalid = get_iprange_id($plugin_config, $dhcp_range, $noerr);
+ my $internalid = get_iprange_id($plugin_config, $dhcp_range, $noerr);
- # definedness check, because ID could be 0
- if (!defined($internalid)) {
- warn "could not find id for ip range $dhcp_range->{'start-address'}:$dhcp_range->{'end-address'}";
- next;
- }
+ # definedness check, because ID could be 0
+ if (!defined($internalid)) {
+ warn
+ "could not find id for ip range $dhcp_range->{'start-address'}:$dhcp_range->{'end-address'}";
+ next;
+ }
- del_dhcp_range($plugin_config, $internalid, $noerr);
+ del_dhcp_range($plugin_config, $internalid, $noerr);
}
- eval {
- netbox_api_request($plugin_config, "DELETE", "/ipam/prefixes/$internalid/");
- };
+ eval { netbox_api_request($plugin_config, "DELETE", "/ipam/prefixes/$internalid/"); };
die "error deleting subnet from ipam: $@" if $@ && !$noerr;
}
sub add_ip {
- my ($class, $plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $vmid, $is_gateway, $noerr) = @_;
+ my (
+ $class,
+ $plugin_config,
+ $subnetid,
+ $subnet,
+ $ip,
+ $hostname,
+ $mac,
+ $vmid,
+ $is_gateway,
+ $noerr,
+ ) = @_;
my $mask = $subnet->{mask};
my $description = undef;
if ($is_gateway) {
- $description = 'gateway'
+ $description = 'gateway';
} elsif ($mac) {
- $description = "mac:$mac";
+ $description = "mac:$mac";
}
eval {
- my $params = {
- address => "$ip/$mask",
- description => $description,
- };
+ my $params = {
+ address => "$ip/$mask",
+ description => $description,
+ };
- $params->{dns_name} = $hostname if $hostname;
+ $params->{dns_name} = $hostname if $hostname;
- netbox_api_request($plugin_config, "POST", "/ipam/ip-addresses/", $params);
+ netbox_api_request($plugin_config, "POST", "/ipam/ip-addresses/", $params);
};
if ($@) {
- if ($is_gateway) {
- die "error add subnet ip to ipam: ip $ip already exist: $@"
- if !is_ip_gateway($plugin_config, $ip, $noerr);
- } elsif (!$noerr) {
- die "error add subnet ip to ipam: ip already exist: $@";
- }
+ if ($is_gateway) {
+ die "error add subnet ip to ipam: ip $ip already exist: $@"
+ if !is_ip_gateway($plugin_config, $ip, $noerr);
+ } elsif (!$noerr) {
+ die "error add subnet ip to ipam: ip already exist: $@";
+ }
}
}
sub update_ip {
- my ($class, $plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $vmid, $is_gateway, $noerr) = @_;
+ my (
+ $class,
+ $plugin_config,
+ $subnetid,
+ $subnet,
+ $ip,
+ $hostname,
+ $mac,
+ $vmid,
+ $is_gateway,
+ $noerr,
+ ) = @_;
my $mask = $subnet->{mask};
my $description = undef;
if ($is_gateway) {
- $description = 'gateway'
+ $description = 'gateway';
} elsif ($mac) {
- $description = "mac:$mac";
+ $description = "mac:$mac";
}
my $ip_id = get_ip_id($plugin_config, $ip, $noerr);
# definedness check, because ID could be 0
if (!defined($ip_id)) {
- return if $noerr;
- die "could not find id for ip address $ip";
+ return if $noerr;
+ die "could not find id for ip address $ip";
}
eval {
- my $params = {
- address => "$ip/$mask",
- description => $description,
- };
+ my $params = {
+ address => "$ip/$mask",
+ description => $description,
+ };
- $params->{dns_name} = $hostname if $hostname;
+ $params->{dns_name} = $hostname if $hostname;
- netbox_api_request($plugin_config, "PATCH", "/ipam/ip-addresses/$ip_id/", $params);
+ netbox_api_request($plugin_config, "PATCH", "/ipam/ip-addresses/$ip_id/", $params);
};
if ($@) {
- die "error update ip $ip : $@" if !$noerr;
+ die "error update ip $ip : $@" if !$noerr;
}
}
@@ -270,28 +291,30 @@ sub add_next_freeip {
# definedness check, because ID could be 0
if (!defined($internalid)) {
- return if $noerr;
- die "could not find id for prefix $cidr";
+ return if $noerr;
+ die "could not find id for prefix $cidr";
}
my $description = undef;
$description = "mac:$mac" if $mac;
my $ip = eval {
- my $params = {
- description => $description,
- };
+ my $params = {
+ description => $description,
+ };
- $params->{dns_name} = $hostname if $hostname;
+ $params->{dns_name} = $hostname if $hostname;
- my $result = netbox_api_request($plugin_config, "POST", "/ipam/prefixes/$internalid/available-ips/", $params);
+ my $result = netbox_api_request(
+ $plugin_config, "POST", "/ipam/prefixes/$internalid/available-ips/", $params,
+ );
- my ($ip, undef) = split(/\//, $result->{address});
- return $ip;
+ my ($ip, undef) = split(/\//, $result->{address});
+ return $ip;
};
if ($@) {
- die "can't find free ip in subnet $cidr: $@" if !$noerr;
+ die "can't find free ip in subnet $cidr: $@" if !$noerr;
}
return $ip;
@@ -304,29 +327,33 @@ sub add_range_next_freeip {
# definedness check, because ID could be 0
if (!defined($internalid)) {
- return if $noerr;
- die "could not find id for ip range $range->{'start-address'}:$range->{'end-address'}";
+ return if $noerr;
+ die "could not find id for ip range $range->{'start-address'}:$range->{'end-address'}";
}
my $description = undef;
$description = "mac:$data->{mac}" if $data->{mac};
my $ip = eval {
- my $params = {
- description => $description,
- };
+ my $params = {
+ description => $description,
+ };
- $params->{dns_name} = $data->{hostname} if $data->{hostname};
+ $params->{dns_name} = $data->{hostname} if $data->{hostname};
- my $result = netbox_api_request($plugin_config, "POST", "/ipam/ip-ranges/$internalid/available-ips/", $params);
+ my $result = netbox_api_request(
+ $plugin_config, "POST", "/ipam/ip-ranges/$internalid/available-ips/", $params,
+ );
- my ($ip, undef) = split(/\//, $result->{address});
- print "found ip free $ip in range $range->{'start-address'}-$range->{'end-address'}\n" if $ip;
- return $ip;
+ my ($ip, undef) = split(/\//, $result->{address});
+ print "found ip free $ip in range $range->{'start-address'}-$range->{'end-address'}\n"
+ if $ip;
+ return $ip;
};
if ($@) {
- die "can't find free ip in range $range->{'start-address'}-$range->{'end-address'}: $@" if !$noerr;
+ die "can't find free ip in range $range->{'start-address'}-$range->{'end-address'}: $@"
+ if !$noerr;
}
return $ip;
@@ -339,15 +366,13 @@ sub del_ip {
my $ip_id = get_ip_id($plugin_config, $ip, $noerr);
if (!defined($ip_id)) {
- warn "could not find id for ip $ip";
- return;
+ warn "could not find id for ip $ip";
+ return;
}
- eval {
- netbox_api_request($plugin_config, "DELETE", "/ipam/ip-addresses/$ip_id/");
- };
+ eval { netbox_api_request($plugin_config, "DELETE", "/ipam/ip-addresses/$ip_id/"); };
if ($@) {
- die "error delete ip $ip : $@" if !$noerr;
+ die "error delete ip $ip : $@" if !$noerr;
}
return 1;
@@ -360,21 +385,21 @@ sub get_ips_from_mac {
my $ip6 = undef;
my $data = eval {
- netbox_api_request($plugin_config, "GET", "/ipam/ip-addresses/?description__ic=$mac");
+ netbox_api_request($plugin_config, "GET", "/ipam/ip-addresses/?description__ic=$mac");
};
if ($@) {
- return if $noerr;
- die "could not query ip address entry for mac $mac: $@";
+ return if $noerr;
+ die "could not query ip address entry for mac $mac: $@";
}
- for my $ip (@{$data->{results}}) {
- if ($ip->{family}->{value} == 4 && !$ip4) {
- ($ip4, undef) = split(/\//, $ip->{address});
- }
+ for my $ip (@{ $data->{results} }) {
+ if ($ip->{family}->{value} == 4 && !$ip4) {
+ ($ip4, undef) = split(/\//, $ip->{address});
+ }
- if ($ip->{family}->{value} == 6 && !$ip6) {
- ($ip6, undef) = split(/\//, $ip->{address});
- }
+ if ($ip->{family}->{value} == 6 && !$ip6) {
+ ($ip6, undef) = split(/\//, $ip->{address});
+ }
}
return ($ip4, $ip6);
@@ -385,7 +410,7 @@ sub verify_api {
eval { netbox_api_request($plugin_config, "GET", "/ipam/aggregates/"); };
if ($@) {
- die "Can't connect to netbox api: $@";
+ die "Can't connect to netbox api: $@";
}
}
@@ -404,11 +429,11 @@ sub get_prefix_id {
my $result = eval { netbox_api_request($config, "GET", "/ipam/prefixes/?q=$ip") };
if ($@) {
- return if $noerr;
- die "could not obtain ID for prefix $cidr: $@";
+ return if $noerr;
+ die "could not obtain ID for prefix $cidr: $@";
}
- my $data = @{$result->{results}}[0];
+ my $data = @{ $result->{results} }[0];
return $data->{id};
}
@@ -416,18 +441,19 @@ sub get_iprange_id {
my ($config, $range, $noerr) = @_;
my $result = eval {
- netbox_api_request(
- $config,
- "GET",
- "/ipam/ip-ranges/?start_address=$range->{'start-address'}&end_address=$range->{'end-address'}",
- );
+ netbox_api_request(
+ $config,
+ "GET",
+ "/ipam/ip-ranges/?start_address=$range->{'start-address'}&end_address=$range->{'end-address'}",
+ );
};
if ($@) {
- return if $noerr;
- die "could not obtain ID for IP range $range->{'start-address'}:$range->{'end-address'}: $@";
+ return if $noerr;
+ die
+ "could not obtain ID for IP range $range->{'start-address'}:$range->{'end-address'}: $@";
}
- my $data = @{$result->{results}}[0];
+ my $data = @{ $result->{results} }[0];
return $data->{id};
}
@@ -436,11 +462,11 @@ sub get_ip_id {
my $result = eval { netbox_api_request($config, "GET", "/ipam/ip-addresses/?q=$ip") };
if ($@) {
- return if $noerr;
- die "could not obtain ID for IP $ip: $@";
+ return if $noerr;
+ die "could not obtain ID for IP $ip: $@";
}
- my $data = @{$result->{results}}[0];
+ my $data = @{ $result->{results} }[0];
return $data->{id};
}
@@ -449,11 +475,11 @@ sub is_ip_gateway {
my $result = eval { netbox_api_request($config, "GET", "/ipam/ip-addresses/?q=$ip") };
if ($@) {
- return if $noerr;
- die "could not obtain ipam entry for address $ip: $@";
+ return if $noerr;
+ die "could not obtain ipam entry for address $ip: $@";
}
- my $data = @{$result->{data}}[0];
+ my $data = @{ $result->{data} }[0];
return $data->{description} eq 'gateway';
}
@@ -462,14 +488,13 @@ sub is_prefix_empty {
my $result = eval { netbox_api_request($config, "GET", "/ipam/ip-addresses/?parent=$cidr") };
if ($@) {
- return if $noerr;
- die "could not query children for prefix $cidr: $@";
+ return if $noerr;
+ die "could not query children for prefix $cidr: $@";
}
# checking against 1, because we do not count the gateway
- return scalar(@{$result->{results}}) <= 1;
+ return scalar(@{ $result->{results} }) <= 1;
}
1;
-
diff --git a/src/PVE/Network/SDN/Ipams/PVEPlugin.pm b/src/PVE/Network/SDN/Ipams/PVEPlugin.pm
index 5e72e65..6764d79 100644
--- a/src/PVE/Network/SDN/Ipams/PVEPlugin.pm
+++ b/src/PVE/Network/SDN/Ipams/PVEPlugin.pm
@@ -13,30 +13,31 @@ use Digest::SHA;
use base('PVE::Network::SDN::Ipams::Plugin');
-
my $ipamdb_file = "sdn/pve-ipam-state.json";
my $ipamdb_file_legacy = "priv/ipam.db";
PVE::Cluster::cfs_register_file(
$ipamdb_file,
sub {
- my ($filename, $data) = @_;
- if (defined($data)) {
- return PVE::Network::SDN::Ipams::PVEPlugin->parse_config($filename, $data);
- } else {
- # TODO: remove legacy state file handling with PVE 9+ after ensuring all call sites got
- # switched over.
- return cfs_read_file($ipamdb_file_legacy);
- }
+ my ($filename, $data) = @_;
+ if (defined($data)) {
+ return PVE::Network::SDN::Ipams::PVEPlugin->parse_config($filename, $data);
+ } else {
+ # TODO: remove legacy state file handling with PVE 9+ after ensuring all call sites got
+ # switched over.
+ return cfs_read_file($ipamdb_file_legacy);
+ }
},
sub {
- my ($filename, $data) = @_;
- # TODO: remove below with PVE 9+, add a pve8to9 check to allow doing so.
- if (-e $ipamdb_file_legacy && -e $ipamdb_file) {
- # only clean-up if we succeeded to write the new path at least once
- unlink $ipamdb_file_legacy or $!{ENOENT} or warn "failed to unlink legacy IPAM DB - $!\n";
- }
- return PVE::Network::SDN::Ipams::PVEPlugin->write_config($filename, $data);
+ my ($filename, $data) = @_;
+ # TODO: remove below with PVE 9+, add a pve8to9 check to allow doing so.
+ if (-e $ipamdb_file_legacy && -e $ipamdb_file) {
+ # only clean-up if we succeeded to write the new path at least once
+ unlink $ipamdb_file_legacy
+ or $!{ENOENT}
+ or warn "failed to unlink legacy IPAM DB - $!\n";
+ }
+ return PVE::Network::SDN::Ipams::PVEPlugin->write_config($filename, $data);
},
);
@@ -65,20 +66,23 @@ sub add_subnet {
my $zone = $subnet->{zone};
my $gateway = $subnet->{gateway};
-
- cfs_lock_file($ipamdb_file, undef, sub {
- my $db = {};
- $db = read_db();
-
- $db->{zones}->{$zone} = {} if !$db->{zones}->{$zone};
- my $zonedb = $db->{zones}->{$zone};
-
- if(!$zonedb->{subnets}->{$cidr}) {
- #create subnet
- $zonedb->{subnets}->{$cidr}->{ips} = {};
- write_db($db);
- }
- });
+ cfs_lock_file(
+ $ipamdb_file,
+ undef,
+ sub {
+ my $db = {};
+ $db = read_db();
+
+ $db->{zones}->{$zone} = {} if !$db->{zones}->{$zone};
+ my $zonedb = $db->{zones}->{$zone};
+
+ if (!$zonedb->{subnets}->{$cidr}) {
+ #create subnet
+ $zonedb->{subnets}->{$cidr}->{ips} = {};
+ write_db($db);
+ }
+ },
+ );
die "$@" if $@;
}
@@ -90,12 +94,14 @@ sub update_subnet {
sub only_gateway_remains {
my ($ips) = @_;
- if (keys %{$ips} == 1 &&
- (values %{$ips})[0]->{gateway} == 1) {
- return 1;
+ if (
+ keys %{$ips} == 1
+ && (values %{$ips})[0]->{gateway} == 1
+ ) {
+ return 1;
}
return 0;
-};
+}
sub del_subnet {
my ($class, $plugin_config, $subnetid, $subnet) = @_;
@@ -103,25 +109,29 @@ sub del_subnet {
my $cidr = $subnet->{cidr};
my $zone = $subnet->{zone};
- cfs_lock_file($ipamdb_file, undef, sub {
+ cfs_lock_file(
+ $ipamdb_file,
+ undef,
+ sub {
- my $db = read_db();
+ my $db = read_db();
- my $dbzone = $db->{zones}->{$zone};
- die "zone '$zone' doesn't exist in IPAM DB\n" if !$dbzone;
- my $dbsubnet = $dbzone->{subnets}->{$cidr};
- die "subnet '$cidr' doesn't exist in IPAM DB\n" if !$dbsubnet;
+ my $dbzone = $db->{zones}->{$zone};
+ die "zone '$zone' doesn't exist in IPAM DB\n" if !$dbzone;
+ my $dbsubnet = $dbzone->{subnets}->{$cidr};
+ die "subnet '$cidr' doesn't exist in IPAM DB\n" if !$dbsubnet;
- my $ips = $dbsubnet->{ips};
+ my $ips = $dbsubnet->{ips};
- if (keys %{$ips} > 0 && !only_gateway_remains($ips)) {
- die "cannot delete subnet '$cidr', not empty\n";
- }
+ if (keys %{$ips} > 0 && !only_gateway_remains($ips)) {
+ die "cannot delete subnet '$cidr', not empty\n";
+ }
- delete $dbzone->{subnets}->{$cidr};
+ delete $dbzone->{subnets}->{$cidr};
- write_db($db);
- });
+ write_db($db);
+ },
+ );
die "$@" if $@;
}
@@ -132,29 +142,37 @@ sub add_ip {
my $cidr = $subnet->{cidr};
my $zone = $subnet->{zone};
- cfs_lock_file($ipamdb_file, undef, sub {
-
- my $db = read_db();
- my $dbzone = $db->{zones}->{$zone};
- die "zone '$zone' doesn't exist in IPAM DB\n" if !$dbzone;
- my $dbsubnet = $dbzone->{subnets}->{$cidr};
- die "subnet '$cidr' doesn't exist in IPAM DB\n" if !$dbsubnet;
-
- die "IP '$ip' already exist\n" if (!$is_gateway && defined($dbsubnet->{ips}->{$ip})) || ($is_gateway && defined($dbsubnet->{ips}->{$ip}) && !defined($dbsubnet->{ips}->{$ip}->{gateway}));
-
- my $data = {};
- if ($is_gateway) {
- $data->{gateway} = 1;
- } else {
- $data->{vmid} = $vmid if $vmid;
- $data->{hostname} = $hostname if $hostname;
- $data->{mac} = $mac if $mac;
- }
-
- $dbsubnet->{ips}->{$ip} = $data;
-
- write_db($db);
- });
+ cfs_lock_file(
+ $ipamdb_file,
+ undef,
+ sub {
+
+ my $db = read_db();
+ my $dbzone = $db->{zones}->{$zone};
+ die "zone '$zone' doesn't exist in IPAM DB\n" if !$dbzone;
+ my $dbsubnet = $dbzone->{subnets}->{$cidr};
+ die "subnet '$cidr' doesn't exist in IPAM DB\n" if !$dbsubnet;
+
+ die "IP '$ip' already exist\n"
+ if (!$is_gateway && defined($dbsubnet->{ips}->{$ip}))
+ || ($is_gateway
+ && defined($dbsubnet->{ips}->{$ip})
+ && !defined($dbsubnet->{ips}->{$ip}->{gateway}));
+
+ my $data = {};
+ if ($is_gateway) {
+ $data->{gateway} = 1;
+ } else {
+ $data->{vmid} = $vmid if $vmid;
+ $data->{hostname} = $hostname if $hostname;
+ $data->{mac} = $mac if $mac;
+ }
+
+ $dbsubnet->{ips}->{$ip} = $data;
+
+ write_db($db);
+ },
+ );
die "$@" if $@;
}
@@ -172,43 +190,48 @@ sub add_next_freeip {
my $mask = $subnet->{mask};
my $freeip = undef;
- cfs_lock_file($ipamdb_file, undef, sub {
-
- my $db = read_db();
- my $dbzone = $db->{zones}->{$zone};
- die "zone '$zone' doesn't exist in IPAM DB\n" if !$dbzone;
- my $dbsubnet = $dbzone->{subnets}->{$cidr};
- die "subnet '$cidr' doesn't exist in IPAM DB" if !$dbsubnet;
-
- if (Net::IP::ip_is_ipv4($network) && $mask == 32) {
- die "cannot find free IP in subnet '$cidr'\n" if defined($dbsubnet->{ips}->{$network});
- $freeip = $network;
- } else {
- my $iplist = NetAddr::IP->new($cidr);
- my $lastip = $iplist->last()->canon();
- $iplist++ if Net::IP::ip_is_ipv4($network); #skip network address for ipv4
- while(1) {
- my $ip = $iplist->canon();
- if (defined($dbsubnet->{ips}->{$ip})) {
- last if $ip eq $lastip;
- $iplist++;
- next;
- }
- $freeip = $ip;
- last;
- }
- }
-
- die "can't find free ip in subnet '$cidr'\n" if !$freeip;
-
- $dbsubnet->{ips}->{$freeip} = {
- mac => $mac,
- hostname => $hostname,
- vmid => $vmid
- };
-
- write_db($db);
- });
+ cfs_lock_file(
+ $ipamdb_file,
+ undef,
+ sub {
+
+ my $db = read_db();
+ my $dbzone = $db->{zones}->{$zone};
+ die "zone '$zone' doesn't exist in IPAM DB\n" if !$dbzone;
+ my $dbsubnet = $dbzone->{subnets}->{$cidr};
+ die "subnet '$cidr' doesn't exist in IPAM DB" if !$dbsubnet;
+
+ if (Net::IP::ip_is_ipv4($network) && $mask == 32) {
+ die "cannot find free IP in subnet '$cidr'\n"
+ if defined($dbsubnet->{ips}->{$network});
+ $freeip = $network;
+ } else {
+ my $iplist = NetAddr::IP->new($cidr);
+ my $lastip = $iplist->last()->canon();
+ $iplist++ if Net::IP::ip_is_ipv4($network); #skip network address for ipv4
+ while (1) {
+ my $ip = $iplist->canon();
+ if (defined($dbsubnet->{ips}->{$ip})) {
+ last if $ip eq $lastip;
+ $iplist++;
+ next;
+ }
+ $freeip = $ip;
+ last;
+ }
+ }
+
+ die "can't find free ip in subnet '$cidr'\n" if !$freeip;
+
+ $dbsubnet->{ips}->{$freeip} = {
+ mac => $mac,
+ hostname => $hostname,
+ vmid => $vmid,
+ };
+
+ write_db($db);
+ },
+ );
die "$@" if $@;
return $freeip;
@@ -220,31 +243,35 @@ sub add_range_next_freeip {
my $cidr = $subnet->{cidr};
my $zone = $subnet->{zone};
- cfs_lock_file($ipamdb_file, undef, sub {
- my $db = read_db();
+ cfs_lock_file(
+ $ipamdb_file,
+ undef,
+ sub {
+ my $db = read_db();
- my $dbzone = $db->{zones}->{$zone};
- die "zone '$zone' doesn't exist in IPAM DB\n" if !$dbzone;
+ my $dbzone = $db->{zones}->{$zone};
+ die "zone '$zone' doesn't exist in IPAM DB\n" if !$dbzone;
- my $dbsubnet = $dbzone->{subnets}->{$cidr};
- die "subnet '$cidr' doesn't exist in IPAM DB\n" if !$dbsubnet;
+ my $dbsubnet = $dbzone->{subnets}->{$cidr};
+ die "subnet '$cidr' doesn't exist in IPAM DB\n" if !$dbsubnet;
- my $ip = new Net::IP ("$range->{'start-address'} - $range->{'end-address'}")
- or die "Invalid IP address(es) in Range!\n";
- my $mac = $data->{mac};
+ my $ip = new Net::IP("$range->{'start-address'} - $range->{'end-address'}")
+ or die "Invalid IP address(es) in Range!\n";
+ my $mac = $data->{mac};
- do {
- my $ip_address = $ip->version() == 6 ? $ip->short() : $ip->ip();
- if (!$dbsubnet->{ips}->{$ip_address}) {
- $dbsubnet->{ips}->{$ip_address} = $data;
- write_db($db);
+ do {
+ my $ip_address = $ip->version() == 6 ? $ip->short() : $ip->ip();
+ if (!$dbsubnet->{ips}->{$ip_address}) {
+ $dbsubnet->{ips}->{$ip_address} = $data;
+ write_db($db);
- return $ip_address;
- }
- } while (++$ip);
+ return $ip_address;
+ }
+ } while (++$ip);
- die "No free IP left in Range $range->{'start-address'}:$range->{'end-address'}}\n";
- });
+ die "No free IP left in Range $range->{'start-address'}:$range->{'end-address'}}\n";
+ },
+ );
}
sub del_ip {
@@ -253,18 +280,22 @@ sub del_ip {
my $cidr = $subnet->{cidr};
my $zone = $subnet->{zone};
- cfs_lock_file($ipamdb_file, undef, sub {
-
- my $db = read_db();
- die "zone $zone don't exist in ipam db" if !$db->{zones}->{$zone};
- my $dbzone = $db->{zones}->{$zone};
- die "subnet $cidr don't exist in ipam db" if !$dbzone->{subnets}->{$cidr};
- my $dbsubnet = $dbzone->{subnets}->{$cidr};
-
- die "IP '$ip' does not exist in IPAM DB\n" if !defined($dbsubnet->{ips}->{$ip});
- delete $dbsubnet->{ips}->{$ip};
- write_db($db);
- });
+ cfs_lock_file(
+ $ipamdb_file,
+ undef,
+ sub {
+
+ my $db = read_db();
+ die "zone $zone don't exist in ipam db" if !$db->{zones}->{$zone};
+ my $dbzone = $db->{zones}->{$zone};
+ die "subnet $cidr don't exist in ipam db" if !$dbzone->{subnets}->{$cidr};
+ my $dbsubnet = $dbzone->{subnets}->{$cidr};
+
+ die "IP '$ip' does not exist in IPAM DB\n" if !defined($dbsubnet->{ips}->{$ip});
+ delete $dbsubnet->{ips}->{$ip};
+ write_db($db);
+ },
+ );
die "$@" if $@;
}
@@ -281,21 +312,21 @@ sub get_ips_from_mac {
my $dbzone = $db->{zones}->{$zoneid};
my $subnets = $dbzone->{subnets};
- for my $subnet ( keys %$subnets) {
- next if Net::IP::ip_is_ipv4($subnet) && $ip4;
- next if $ip6;
- my $ips = $subnets->{$subnet}->{ips};
- for my $ip (keys %$ips) {
- my $ipobject = $ips->{$ip};
- if ($ipobject->{mac} && $ipobject->{mac} eq $mac) {
- if (Net::IP::ip_is_ipv4($ip)) {
- $ip4 = $ip;
- } else {
- $ip6 = $ip;
- }
- }
- }
- last if $ip4 && $ip6;
+ for my $subnet (keys %$subnets) {
+ next if Net::IP::ip_is_ipv4($subnet) && $ip4;
+ next if $ip6;
+ my $ips = $subnets->{$subnet}->{ips};
+ for my $ip (keys %$ips) {
+ my $ipobject = $ips->{$ip};
+ if ($ipobject->{mac} && $ipobject->{mac} eq $mac) {
+ if (Net::IP::ip_is_ipv4($ip)) {
+ $ip4 = $ip;
+ } else {
+ $ip6 = $ip;
+ }
+ }
+ }
+ last if $ip4 && $ip6;
}
return ($ip4, $ip6);
}
@@ -323,7 +354,7 @@ sub write_config {
sub parse_config {
my ($class, $filename, $raw) = @_;
- $raw = '{}' if !defined($raw) ||$raw eq '';
+ $raw = '{}' if !defined($raw) || $raw eq '';
my $cfg = from_json($raw);
return $cfg;
diff --git a/src/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm b/src/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm
index 8ee430a..1265797 100644
--- a/src/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm
+++ b/src/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm
@@ -14,22 +14,22 @@ sub type {
sub properties {
return {
- url => {
- type => 'string',
- },
- token => {
- type => 'string',
- },
- section => {
- type => 'integer',
- },
+ url => {
+ type => 'string',
+ },
+ token => {
+ type => 'string',
+ },
+ section => {
+ type => 'integer',
+ },
};
}
sub options {
return {
- url => { optional => 0},
+ url => { optional => 0 },
token => { optional => 0 },
section => { optional => 0 },
fingerprint => { optional => 1 },
@@ -56,14 +56,18 @@ sub add_subnet {
#create subnet
if (!$internalid) {
- my $params = {
- subnet => $network,
- mask => $mask,
- sectionId => $section,
- };
-
- eval { PVE::Network::SDN::api_request("POST", "$url/subnets/", $headers, $params, $fingerprint) };
- die "error add subnet to ipam: $@" if $@ && !$noerr;
+ my $params = {
+ subnet => $network,
+ mask => $mask,
+ sectionId => $section,
+ };
+
+ eval {
+ PVE::Network::SDN::api_request(
+ "POST", "$url/subnets/", $headers, $params, $fingerprint,
+ );
+ };
+ die "error add subnet to ipam: $@" if $@ && !$noerr;
}
}
@@ -86,12 +90,27 @@ sub del_subnet {
return; #fixme: check that prefix is empty exluding gateway, before delete
- eval { PVE::Network::SDN::api_request("DELETE", "$url/subnets/$internalid", $headers, undef, $fingerprint) };
+ eval {
+ PVE::Network::SDN::api_request(
+ "DELETE", "$url/subnets/$internalid", $headers, undef, $fingerprint,
+ );
+ };
die "error deleting subnet from ipam: $@" if $@ && !$noerr;
}
sub add_ip {
- my ($class, $plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description, $is_gateway, $noerr) = @_;
+ my (
+ $class,
+ $plugin_config,
+ $subnetid,
+ $subnet,
+ $ip,
+ $hostname,
+ $mac,
+ $description,
+ $is_gateway,
+ $noerr,
+ ) = @_;
my $cidr = $subnet->{cidr};
my $url = $plugin_config->{url};
@@ -102,29 +121,43 @@ sub add_ip {
my $internalid = get_prefix_id($url, $cidr, $headers);
my $params = {
- ip => $ip,
- subnetId => $internalid,
- hostname => $hostname,
- description => $description,
+ ip => $ip,
+ subnetId => $internalid,
+ hostname => $hostname,
+ description => $description,
};
$params->{is_gateway} = 1 if $is_gateway;
$params->{mac} = $mac if $mac;
eval {
- PVE::Network::SDN::api_request("POST", "$url/addresses/", $headers, $params, $fingerprint);
+ PVE::Network::SDN::api_request(
+ "POST", "$url/addresses/", $headers, $params, $fingerprint,
+ );
};
if ($@) {
- if($is_gateway) {
- die "error add subnet ip to ipam: ip $ip already exist: $@" if !is_ip_gateway($url, $ip, $headers) && !$noerr;
- } else {
- die "error add subnet ip to ipam: ip $ip already exist: $@" if !$noerr;
- }
+ if ($is_gateway) {
+ die "error add subnet ip to ipam: ip $ip already exist: $@"
+ if !is_ip_gateway($url, $ip, $headers) && !$noerr;
+ } else {
+ die "error add subnet ip to ipam: ip $ip already exist: $@" if !$noerr;
+ }
}
}
sub update_ip {
- my ($class, $plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description, $is_gateway, $noerr) = @_;
+ my (
+ $class,
+ $plugin_config,
+ $subnetid,
+ $subnet,
+ $ip,
+ $hostname,
+ $mac,
+ $description,
+ $is_gateway,
+ $noerr,
+ ) = @_;
my $cidr = $subnet->{cidr};
my $url = $plugin_config->{url};
@@ -136,18 +169,20 @@ sub update_ip {
die "can't find ip addresse in ipam" if !$ip_id;
my $params = {
- hostname => $hostname,
- description => $description,
+ hostname => $hostname,
+ description => $description,
};
$params->{is_gateway} = 1 if $is_gateway;
$params->{mac} = $mac if $mac;
eval {
- PVE::Network::SDN::api_request("PATCH", "$url/addresses/$ip_id", $headers, $params,$fingerprint);
+ PVE::Network::SDN::api_request(
+ "PATCH", "$url/addresses/$ip_id", $headers, $params, $fingerprint,
+ );
};
if ($@) {
- die "ipam: error update subnet ip $ip: $@" if !$noerr;
+ die "ipam: error update subnet ip $ip: $@" if !$noerr;
}
}
@@ -164,16 +199,22 @@ sub add_next_freeip {
my $internalid = get_prefix_id($url, $cidr, $headers);
my $params = {
- hostname => $hostname,
- description => $description,
+ hostname => $hostname,
+ description => $description,
};
$params->{mac} = $mac if $mac;
my $ip = undef;
eval {
- my $result = PVE::Network::SDN::api_request("POST", "$url/addresses/first_free/$internalid/", $headers, $params, $fingerprint);
- $ip = $result->{data};
+ my $result = PVE::Network::SDN::api_request(
+ "POST",
+ "$url/addresses/first_free/$internalid/",
+ $headers,
+ $params,
+ $fingerprint,
+ );
+ $ip = $result->{data};
};
if ($@) {
@@ -209,17 +250,18 @@ sub del_ip {
return if !$ip_id;
eval {
- PVE::Network::SDN::api_request("DELETE", "$url/addresses/$ip_id", $headers, undef, $fingerprint);
+ PVE::Network::SDN::api_request(
+ "DELETE", "$url/addresses/$ip_id", $headers, undef, $fingerprint,
+ );
};
if ($@) {
- die "error delete ip $ip: $@" if !$noerr;
+ die "error delete ip $ip: $@" if !$noerr;
}
}
sub get_ips_from_mac {
my ($class, $plugin_config, $mac, $zoneid) = @_;
-
my $url = $plugin_config->{url};
my $token = $plugin_config->{token};
my $fingerprint = $plugin_config->{fingerprint};
@@ -228,20 +270,28 @@ sub get_ips_from_mac {
my $ip4 = undef;
my $ip6 = undef;
- my $ips = eval { PVE::Network::SDN::api_request("GET", "$url/addresses/search_mac/$mac", $headers, undef, $fingerprint) };
+ my $ips = eval {
+ PVE::Network::SDN::api_request(
+ "GET",
+ "$url/addresses/search_mac/$mac",
+ $headers,
+ undef,
+ $fingerprint,
+ );
+ };
return if $@;
#fixme
die "parsing of result not yet implemented";
for my $ip (@$ips) {
-# if ($ip->{family}->{value} == 4 && !$ip4) {
-# ($ip4, undef) = split(/\//, $ip->{address});
-# }
-#
-# if ($ip->{family}->{value} == 6 && !$ip6) {
-# ($ip6, undef) = split(/\//, $ip->{address});
-# }
+ # if ($ip->{family}->{value} == 4 && !$ip4) {
+ # ($ip4, undef) = split(/\//, $ip->{address});
+ # }
+ #
+ # if ($ip->{family}->{value} == 6 && !$ip6) {
+ # ($ip6, undef) = split(/\//, $ip->{address});
+ # }
}
return ($ip4, $ip6);
@@ -257,10 +307,12 @@ sub verify_api {
my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'Token' => $token];
eval {
- PVE::Network::SDN::api_request("GET", "$url/sections/$sectionid", $headers, undef, $fingerprint);
+ PVE::Network::SDN::api_request(
+ "GET", "$url/sections/$sectionid", $headers, undef, $fingerprint,
+ );
};
if ($@) {
- die "Can't connect to phpipam api: $@";
+ die "Can't connect to phpipam api: $@";
}
}
@@ -270,14 +322,13 @@ sub on_update_hook {
PVE::Network::SDN::Ipams::PhpIpamPlugin::verify_api($class, $plugin_config);
}
-
#helpers
sub get_prefix_id {
my ($url, $cidr, $headers) = @_;
my $result = PVE::Network::SDN::api_request("GET", "$url/subnets/cidr/$cidr", $headers);
- my $data = @{$result->{data}}[0];
+ my $data = @{ $result->{data} }[0];
my $internalid = $data->{id};
return $internalid;
}
@@ -285,7 +336,7 @@ sub get_prefix_id {
sub get_ip_id {
my ($url, $ip, $headers) = @_;
my $result = PVE::Network::SDN::api_request("GET", "$url/addresses/search/$ip", $headers);
- my $data = @{$result->{data}}[0];
+ my $data = @{ $result->{data} }[0];
my $ip_id = $data->{id};
return $ip_id;
}
@@ -293,11 +344,10 @@ sub get_ip_id {
sub is_ip_gateway {
my ($url, $ip, $headers) = @_;
my $result = PVE::Network::SDN::api_request("GET", "$url/addresses/search/$ip", $headers);
- my $data = @{$result->{data}}[0];
+ my $data = @{ $result->{data} }[0];
my $is_gateway = $data->{is_gateway};
return $is_gateway;
}
1;
-
diff --git a/src/PVE/Network/SDN/Ipams/Plugin.pm b/src/PVE/Network/SDN/Ipams/Plugin.pm
index 6190c24..a986a92 100644
--- a/src/PVE/Network/SDN/Ipams/Plugin.pm
+++ b/src/PVE/Network/SDN/Ipams/Plugin.pm
@@ -15,22 +15,27 @@ use base qw(PVE::SectionConfig);
PVE::Cluster::cfs_register_file(
'sdn/ipams.cfg',
- sub { __PACKAGE__->parse_config(@_); },
- sub { __PACKAGE__->write_config(@_); },
- );
-
-PVE::JSONSchema::register_standard_option('pve-sdn-ipam-id', {
- description => "The SDN ipam object identifier.",
- type => 'string', format => 'pve-sdn-ipam-id',
-});
+ sub { __PACKAGE__->parse_config(@_); },
+ sub { __PACKAGE__->write_config(@_); },
+);
+
+PVE::JSONSchema::register_standard_option(
+ 'pve-sdn-ipam-id',
+ {
+ description => "The SDN ipam object identifier.",
+ type => 'string',
+ format => 'pve-sdn-ipam-id',
+ },
+);
PVE::JSONSchema::register_format('pve-sdn-ipam-id', \&parse_sdn_ipam_id);
+
sub parse_sdn_ipam_id {
my ($id, $noerr) = @_;
if ($id !~ m/^[a-z][a-z0-9]*[a-z0-9]$/i) {
- return undef if $noerr;
- die "ipam ID '$id' contains illegal characters\n";
+ return undef if $noerr;
+ die "ipam ID '$id' contains illegal characters\n";
}
return $id;
}
@@ -38,15 +43,19 @@ sub parse_sdn_ipam_id {
my $defaultData = {
propertyList => {
- type => {
- description => "Plugin type.",
- type => 'string', format => 'pve-configid',
- type => 'string',
- },
- ipam => get_standard_option('pve-sdn-ipam-id', {
- completion => \&PVE::Network::SDN::Ipams::complete_sdn_ipam,
- }),
- fingerprint => get_standard_option('fingerprint-sha256', { optional => 1 }),
+ type => {
+ description => "Plugin type.",
+ type => 'string',
+ format => 'pve-configid',
+ type => 'string',
+ },
+ ipam => get_standard_option(
+ 'pve-sdn-ipam-id',
+ {
+ completion => \&PVE::Network::SDN::Ipams::complete_sdn_ipam,
+ },
+ ),
+ fingerprint => get_standard_option('fingerprint-sha256', { optional => 1 }),
},
};
@@ -59,16 +68,15 @@ sub parse_section_header {
if ($line =~ m/^(\S+):\s*(\S+)\s*$/) {
my ($type, $id) = (lc($1), $2);
- my $errmsg = undef; # set if you want to skip whole section
- eval { PVE::JSONSchema::pve_verify_configid($type); };
- $errmsg = $@ if $@;
- my $config = {}; # to return additional attributes
- return ($type, $id, $errmsg, $config);
+ my $errmsg = undef; # set if you want to skip whole section
+ eval { PVE::JSONSchema::pve_verify_configid($type); };
+ $errmsg = $@ if $@;
+ my $config = {}; # to return additional attributes
+ return ($type, $id, $errmsg, $config);
}
return undef;
}
-
sub add_subnet {
my ($class, $plugin_config, $subnetid, $subnet, $noerr) = @_;
@@ -88,13 +96,35 @@ sub del_subnet {
}
sub add_ip {
- my ($class, $plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $vmid, $is_gateway, $noerr) = @_;
+ my (
+ $class,
+ $plugin_config,
+ $subnetid,
+ $subnet,
+ $ip,
+ $hostname,
+ $mac,
+ $vmid,
+ $is_gateway,
+ $noerr,
+ ) = @_;
die "please implement inside plugin";
}
sub update_ip {
- my ($class, $plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $vmid, $is_gateway, $noerr) = @_;
+ my (
+ $class,
+ $plugin_config,
+ $subnetid,
+ $subnet,
+ $ip,
+ $hostname,
+ $mac,
+ $vmid,
+ $is_gateway,
+ $noerr,
+ ) = @_;
# only update ip attributes (mac,hostname,..). Don't change the ip addresses itself, as some ipam
# don't allow ip address change without del/add
@@ -107,7 +137,6 @@ sub add_next_freeip {
die "please implement inside plugin";
}
-
sub add_range_next_freeip {
my ($class, $plugin_config, $subnet, $range, $data, $noerr) = @_;
@@ -127,7 +156,7 @@ sub get_ips_from_mac {
}
sub on_update_hook {
- my ($class, $plugin_config) = @_;
+ my ($class, $plugin_config) = @_;
}
1;
diff --git a/src/PVE/Network/SDN/SubnetPlugin.pm b/src/PVE/Network/SDN/SubnetPlugin.pm
index 8a79eae..b47379d 100644
--- a/src/PVE/Network/SDN/SubnetPlugin.pm
+++ b/src/PVE/Network/SDN/SubnetPlugin.pm
@@ -14,31 +14,39 @@ use PVE::Network::SDN::Vnets;
use base qw(PVE::SectionConfig);
-PVE::Cluster::cfs_register_file('sdn/subnets.cfg',
- sub { __PACKAGE__->parse_config(@_); },
- sub { __PACKAGE__->write_config(@_); });
-
-PVE::JSONSchema::register_standard_option('pve-sdn-subnet-id', {
- description => "The SDN subnet object identifier.",
- type => 'string', format => 'pve-sdn-subnet-id',
- type => 'string'
-});
+PVE::Cluster::cfs_register_file(
+ 'sdn/subnets.cfg',
+ sub { __PACKAGE__->parse_config(@_); },
+ sub { __PACKAGE__->write_config(@_); },
+);
+
+PVE::JSONSchema::register_standard_option(
+ 'pve-sdn-subnet-id',
+ {
+ description => "The SDN subnet object identifier.",
+ type => 'string',
+ format => 'pve-sdn-subnet-id',
+ type => 'string',
+ },
+);
PVE::JSONSchema::register_format('pve-sdn-subnet-id', \&parse_sdn_subnet_id);
+
sub parse_sdn_subnet_id {
my ($id, $noerr) = @_;
my $cidr = "";
- if($id =~ /\//) {
- $cidr = $id;
+ if ($id =~ /\//) {
+ $cidr = $id;
} else {
- my ($zone, $ip, $mask) = split(/-/, $id);
- $cidr = "$ip/$mask";
+ my ($zone, $ip, $mask) = split(/-/, $id);
+ $cidr = "$ip/$mask";
}
- if (!(PVE::JSONSchema::pve_verify_cidrv4($cidr, 1) ||
- PVE::JSONSchema::pve_verify_cidrv6($cidr, 1)))
- {
+ if (!(
+ PVE::JSONSchema::pve_verify_cidrv4($cidr, 1)
+ || PVE::JSONSchema::pve_verify_cidrv6($cidr, 1)
+ )) {
return undef if $noerr;
die "value does not look like a valid CIDR network\n";
}
@@ -48,8 +56,10 @@ sub parse_sdn_subnet_id {
my $defaultData = {
propertyList => {
- subnet => get_standard_option('pve-sdn-subnet-id',
- { completion => \&PVE::Network::SDN::Subnets::complete_sdn_subnet }),
+ subnet => get_standard_option(
+ 'pve-sdn-subnet-id',
+ { completion => \&PVE::Network::SDN::Subnets::complete_sdn_subnet },
+ ),
},
};
@@ -63,12 +73,12 @@ sub private {
my $dhcp_range_fmt = {
'start-address' => {
- type => 'ip',
- description => 'Start address for the DHCP IP range',
+ type => 'ip',
+ description => 'Start address for the DHCP IP range',
},
'end-address' => {
- type => 'ip',
- description => 'End address for the DHCP IP range',
+ type => 'ip',
+ description => 'End address for the DHCP IP range',
},
};
@@ -85,34 +95,45 @@ sub validate_dhcp_ranges {
my $validated_ranges = [];
foreach my $dhcp_range (@$dhcp_ranges) {
- my $dhcp_start = $dhcp_range->{'start-address'};
- my $dhcp_end = $dhcp_range->{'end-address'};
-
- my $start_ip = Net::IP->new($dhcp_start);
- raise_param_exc({ 'dhcp-range' => "start-address is not a valid IP $dhcp_start" }) if !$start_ip;
- raise_param_exc({ 'dhcp-range' => "start-address must be a singular IP" }) if $start_ip->size() != 1;
- $dhcp_range->{'start-address'} = $start_ip->ip();
-
- my $end_ip = Net::IP->new($dhcp_end);
- raise_param_exc({ 'dhcp-range' => "end-address is not a valid IP $dhcp_end" }) if !$end_ip;
- raise_param_exc({ 'dhcp-range' => "end-address must be a singular IP" }) if $end_ip->size() != 1;
- $dhcp_range->{'end-address'} = $end_ip->ip();
-
- if ($start_ip->bincomp('gt', $end_ip)) {
- raise_param_exc({ 'dhcp-range' => "start-address $dhcp_start must be smaller than end-address $dhcp_end" })
- }
-
- raise_param_exc({ 'dhcp-range' => "start-address $dhcp_start is not in subnet $cidr" }) if !$subnet_matcher->($dhcp_start);
- raise_param_exc({ 'dhcp-range' => "end-address $dhcp_end is not in subnet $cidr" }) if !$subnet_matcher->($dhcp_end);
-
- my $ip_range = Net::IP->new("$dhcp_range->{'start-address'} - $dhcp_range->{'end-address'}");
- for my $other_range (@$validated_ranges) {
- if ($ip_range->overlaps($other_range) != $Net::IP::IP_NO_OVERLAP) {
- raise_param_exc({ 'dhcp-range' => "dhcp ranges must not overlap" });
- }
- }
-
- push @$validated_ranges, $ip_range;
+ my $dhcp_start = $dhcp_range->{'start-address'};
+ my $dhcp_end = $dhcp_range->{'end-address'};
+
+ my $start_ip = Net::IP->new($dhcp_start);
+ raise_param_exc({ 'dhcp-range' => "start-address is not a valid IP $dhcp_start" })
+ if !$start_ip;
+ raise_param_exc({ 'dhcp-range' => "start-address must be a singular IP" })
+ if $start_ip->size() != 1;
+ $dhcp_range->{'start-address'} = $start_ip->ip();
+
+ my $end_ip = Net::IP->new($dhcp_end);
+ raise_param_exc({ 'dhcp-range' => "end-address is not a valid IP $dhcp_end" }) if !$end_ip;
+ raise_param_exc({ 'dhcp-range' => "end-address must be a singular IP" })
+ if $end_ip->size() != 1;
+ $dhcp_range->{'end-address'} = $end_ip->ip();
+
+ if ($start_ip->bincomp('gt', $end_ip)) {
+ raise_param_exc(
+ {
+ 'dhcp-range' =>
+ "start-address $dhcp_start must be smaller than end-address $dhcp_end",
+ },
+ );
+ }
+
+ raise_param_exc({ 'dhcp-range' => "start-address $dhcp_start is not in subnet $cidr" })
+ if !$subnet_matcher->($dhcp_start);
+ raise_param_exc({ 'dhcp-range' => "end-address $dhcp_end is not in subnet $cidr" })
+ if !$subnet_matcher->($dhcp_end);
+
+ my $ip_range =
+ Net::IP->new("$dhcp_range->{'start-address'} - $dhcp_range->{'end-address'}");
+ for my $other_range (@$validated_ranges) {
+ if ($ip_range->overlaps($other_range) != $Net::IP::IP_NO_OVERLAP) {
+ raise_param_exc({ 'dhcp-range' => "dhcp ranges must not overlap" });
+ }
+ }
+
+ push @$validated_ranges, $ip_range;
}
}
@@ -123,48 +144,51 @@ sub properties {
description => "associated vnet",
},
gateway => {
- type => 'string', format => 'ip',
+ type => 'string',
+ format => 'ip',
description => "Subnet Gateway: Will be assign on vnet for layer3 zones",
},
snat => {
type => 'boolean',
description => "enable masquerade for this subnet if pve-firewall",
},
-# #cloudinit, dhcp options
-# routes => {
-# type => 'string',
-# description => "static routes [network=<network>:gateway=<ip>,network=<network>:gateway=<ip>,... ]",
-# },
+ # #cloudinit, dhcp options
+ # routes => {
+ # type => 'string',
+ # description => "static routes [network=<network>:gateway=<ip>,network=<network>:gateway=<ip>,... ]",
+ # },
dnszoneprefix => {
- type => 'string', format => 'dns-name',
+ type => 'string',
+ format => 'dns-name',
description => "dns domain zone prefix ex: 'adm' -> <hostname>.adm.mydomain.com",
},
- 'dhcp-range' => {
- type => 'array',
- description => 'A list of DHCP ranges for this subnet',
- optional => 1,
- items => {
- type => 'string',
- format => 'pve-sdn-dhcp-range',
- }
- },
- 'dhcp-dns-server' => {
- type => 'string', format => 'ip',
- description => 'IP address for the DNS server',
- optional => 1,
- },
+ 'dhcp-range' => {
+ type => 'array',
+ description => 'A list of DHCP ranges for this subnet',
+ optional => 1,
+ items => {
+ type => 'string',
+ format => 'pve-sdn-dhcp-range',
+ },
+ },
+ 'dhcp-dns-server' => {
+ type => 'string',
+ format => 'ip',
+ description => 'IP address for the DNS server',
+ optional => 1,
+ },
};
}
sub options {
return {
- vnet => { optional => 0 },
- gateway => { optional => 1 },
-# routes => { optional => 1 },
- snat => { optional => 1 },
- dnszoneprefix => { optional => 1 },
- 'dhcp-range' => { optional => 1 },
- 'dhcp-dns-server' => { optional => 1 },
+ vnet => { optional => 0 },
+ gateway => { optional => 1 },
+ # routes => { optional => 1 },
+ snat => { optional => 1 },
+ dnszoneprefix => { optional => 1 },
+ 'dhcp-range' => { optional => 1 },
+ 'dhcp-dns-server' => { optional => 1 },
};
}
@@ -186,49 +210,53 @@ sub on_update_hook {
my $old_gateway = $old_subnet->{gateway} if $old_subnet;
my $mac = undef;
- if($vnetid) {
- my $vnet = PVE::Network::SDN::Vnets::get_vnet($vnetid);
- raise_param_exc({ vnet => "$vnetid don't exist"}) if !$vnet;
- raise_param_exc({ vnet => "you can't add a subnet on a vlanaware vnet"}) if $vnet->{vlanaware};
- $mac = $vnet->{mac};
+ if ($vnetid) {
+ my $vnet = PVE::Network::SDN::Vnets::get_vnet($vnetid);
+ raise_param_exc({ vnet => "$vnetid don't exist" }) if !$vnet;
+ raise_param_exc({ vnet => "you can't add a subnet on a vlanaware vnet" })
+ if $vnet->{vlanaware};
+ $mac = $vnet->{mac};
}
my $pointopoint = 1 if Net::IP::ip_is_ipv4($gateway) && $mask == 32;
#for /32 pointopoint, we allow gateway outside the subnet
- raise_param_exc({ gateway => "$gateway is not in subnet $cidr"}) if $gateway && !$subnet_matcher->($gateway) && !$pointopoint;
+ raise_param_exc({ gateway => "$gateway is not in subnet $cidr" })
+ if $gateway && !$subnet_matcher->($gateway) && !$pointopoint;
validate_dhcp_ranges($subnet);
if ($ipam) {
- if ($old_subnet) {
- PVE::Network::SDN::Subnets::update_subnet($zone, $subnetid, $subnet, $old_subnet);
- } else {
- PVE::Network::SDN::Subnets::add_subnet($zone, $subnetid, $subnet);
- }
-
- #don't register gateway for pointopoint
- return if $pointopoint;
-
- #delete gateway on removal
- if (!defined($gateway) && $old_gateway) {
- eval {
- PVE::Network::SDN::Subnets::del_ip($zone, $subnetid, $old_subnet, $old_gateway);
- };
- warn if $@;
- }
- if(!$old_gateway || $gateway && $gateway ne $old_gateway) {
- my $hostname = "$vnetid-gw";
- PVE::Network::SDN::Subnets::add_ip($zone, $subnetid, $subnet, $gateway, $hostname, $mac, undef, 1);
- }
-
- #delete old gateway after update
- if($gateway && $old_gateway && $gateway ne $old_gateway) {
- eval {
- PVE::Network::SDN::Subnets::del_ip($zone, $subnetid, $old_subnet, $old_gateway);
- };
- warn if $@;
- }
+ if ($old_subnet) {
+ PVE::Network::SDN::Subnets::update_subnet($zone, $subnetid, $subnet, $old_subnet);
+ } else {
+ PVE::Network::SDN::Subnets::add_subnet($zone, $subnetid, $subnet);
+ }
+
+ #don't register gateway for pointopoint
+ return if $pointopoint;
+
+ #delete gateway on removal
+ if (!defined($gateway) && $old_gateway) {
+ eval {
+ PVE::Network::SDN::Subnets::del_ip($zone, $subnetid, $old_subnet, $old_gateway);
+ };
+ warn if $@;
+ }
+ if (!$old_gateway || $gateway && $gateway ne $old_gateway) {
+ my $hostname = "$vnetid-gw";
+ PVE::Network::SDN::Subnets::add_ip(
+ $zone, $subnetid, $subnet, $gateway, $hostname, $mac, undef, 1,
+ );
+ }
+
+ #delete old gateway after update
+ if ($gateway && $old_gateway && $gateway ne $old_gateway) {
+ eval {
+ PVE::Network::SDN::Subnets::del_ip($zone, $subnetid, $old_subnet, $old_gateway);
+ };
+ warn if $@;
+ }
}
}
diff --git a/src/PVE/Network/SDN/Subnets.pm b/src/PVE/Network/SDN/Subnets.pm
index 18847c2..1bcb47a 100644
--- a/src/PVE/Network/SDN/Subnets.pm
+++ b/src/PVE/Network/SDN/Subnets.pm
@@ -25,13 +25,13 @@ sub sdn_subnets_config {
die "sdn subnet '$id' does not exist\n" if (!$noerr && !$scfg);
if ($scfg) {
- $scfg->{id} = $id;
+ $scfg->{id} = $id;
- my ($zone, $network, $mask) = split(/-/, $id);
- $scfg->{cidr} = "$network/$mask";
- $scfg->{zone} = $zone;
- $scfg->{network} = $network;
- $scfg->{mask} = $mask;
+ my ($zone, $network, $mask) = split(/-/, $id);
+ $scfg->{cidr} = "$network/$mask";
+ $scfg->{zone} = $zone;
+ $scfg->{network} = $network;
+ $scfg->{mask} = $mask;
}
return $scfg;
@@ -43,17 +43,17 @@ sub get_dhcp_ranges {
my @dhcp_ranges = ();
if ($subnet_config->{'dhcp-range'}) {
- foreach my $element (@{$subnet_config->{'dhcp-range'}}) {
- my $dhcp_range = eval { parse_property_string('pve-sdn-dhcp-range', $element) };
+ foreach my $element (@{ $subnet_config->{'dhcp-range'} }) {
+ my $dhcp_range = eval { parse_property_string('pve-sdn-dhcp-range', $element) };
- if ($@ || !$dhcp_range) {
- warn "Unable to parse dhcp-range string: $element\n";
- warn "$@\n" if $@;
- next;
- }
+ if ($@ || !$dhcp_range) {
+ warn "Unable to parse dhcp-range string: $element\n";
+ warn "$@\n" if $@;
+ next;
+ }
- push @dhcp_ranges, $dhcp_range;
- }
+ push @dhcp_ranges, $dhcp_range;
+ }
}
return \@dhcp_ranges;
@@ -63,8 +63,8 @@ sub config {
my ($running) = @_;
if ($running) {
- my $cfg = PVE::Network::SDN::running_config();
- return $cfg->{subnets};
+ my $cfg = PVE::Network::SDN::running_config();
+ return $cfg->{subnets};
}
return cfs_read_file("sdn/subnets.cfg");
@@ -79,7 +79,7 @@ sub write_config {
sub sdn_subnets_ids {
my ($cfg) = @_;
- return sort keys %{$cfg->{ids}};
+ return sort keys %{ $cfg->{ids} };
}
sub complete_sdn_subnet {
@@ -87,7 +87,7 @@ sub complete_sdn_subnet {
my $cfg = PVE::Network::SDN::Subnets::config();
- return $cmdname eq 'add' ? [] : [ PVE::Network::SDN::Subnets::sdn_subnets_ids($cfg) ];
+ return $cmdname eq 'add' ? [] : [PVE::Network::SDN::Subnets::sdn_subnets_ids($cfg)];
}
sub get_subnet {
@@ -104,14 +104,14 @@ sub find_ip_subnet {
my $subnetid = undef;
foreach my $id (sort keys %{$subnets}) {
- my $cidr = $subnets->{$id}->{cidr};
- my $subnet_matcher = subnet_matcher($cidr);
- next if !$subnet_matcher->($ip);
- $subnet = $subnets->{$id};
- $subnetid = $id;
- last;
+ my $cidr = $subnets->{$id}->{cidr};
+ my $subnet_matcher = subnet_matcher($cidr);
+ next if !$subnet_matcher->($ip);
+ $subnet = $subnets->{$id};
+ $subnetid = $id;
+ last;
}
- die "can't find any subnet for ip $ip" if !$subnet;
+ die "can't find any subnet for ip $ip" if !$subnet;
return ($subnetid, $subnet);
}
@@ -234,52 +234,53 @@ sub add_next_free_ip {
#verify dns zones before ipam
verify_dns_zone($dnszone, $dns) if !$skipdns;
- if($ipamid) {
- my $ipam_cfg = PVE::Network::SDN::Ipams::config();
- my $plugin_config = $ipam_cfg->{ids}->{$ipamid};
- my $plugin = PVE::Network::SDN::Ipams::Plugin->lookup($plugin_config->{type});
- eval {
- if ($dhcprange) {
- my $data = {
- mac => $mac,
- hostname => $hostname,
- vmid => $vmid,
- };
-
- my $dhcp_ranges = PVE::Network::SDN::Subnets::get_dhcp_ranges($subnet);
-
- foreach my $range (@$dhcp_ranges) {
- $ip = $plugin->add_range_next_freeip($plugin_config, $subnet, $range, $data);
- last if $ip;
- }
- } else {
- $ip = $plugin->add_next_freeip($plugin_config, $subnetid, $subnet, $hostname, $mac, $vmid);
- }
- };
-
- die $@ if $@;
-
- eval { PVE::Network::SDN::Ipams::add_cache_mac_ip($mac, $ip); };
- warn $@ if $@;
+ if ($ipamid) {
+ my $ipam_cfg = PVE::Network::SDN::Ipams::config();
+ my $plugin_config = $ipam_cfg->{ids}->{$ipamid};
+ my $plugin = PVE::Network::SDN::Ipams::Plugin->lookup($plugin_config->{type});
+ eval {
+ if ($dhcprange) {
+ my $data = {
+ mac => $mac,
+ hostname => $hostname,
+ vmid => $vmid,
+ };
+
+ my $dhcp_ranges = PVE::Network::SDN::Subnets::get_dhcp_ranges($subnet);
+
+ foreach my $range (@$dhcp_ranges) {
+ $ip =
+ $plugin->add_range_next_freeip($plugin_config, $subnet, $range, $data);
+ last if $ip;
+ }
+ } else {
+ $ip = $plugin->add_next_freeip(
+ $plugin_config, $subnetid, $subnet, $hostname, $mac, $vmid,
+ );
+ }
+ };
+
+ die $@ if $@;
+
+ eval { PVE::Network::SDN::Ipams::add_cache_mac_ip($mac, $ip); };
+ warn $@ if $@;
}
eval {
- my $reversednszone = get_reversedns_zone($subnetid, $subnet, $reversedns, $ip);
-
- if(!$skipdns) {
- #add dns
- add_dns_record($dnszone, $dns, $hostname, $ip);
- #add reverse dns
- add_dns_ptr_record($reversednszone, $dnszone, $reversedns, $hostname, $ip);
- }
+ my $reversednszone = get_reversedns_zone($subnetid, $subnet, $reversedns, $ip);
+
+ if (!$skipdns) {
+ #add dns
+ add_dns_record($dnszone, $dns, $hostname, $ip);
+ #add reverse dns
+ add_dns_ptr_record($reversednszone, $dnszone, $reversedns, $hostname, $ip);
+ }
};
if ($@) {
- #rollback
- my $err = $@;
- eval {
- PVE::Network::SDN::Subnets::del_ip($zone, $subnetid, $subnet, $ip, $hostname, $mac)
- };
- die $err;
+ #rollback
+ my $err = $@;
+ eval { PVE::Network::SDN::Subnets::del_ip($zone, $subnetid, $subnet, $ip, $hostname, $mac) };
+ die $err;
}
return $ip;
}
@@ -287,7 +288,7 @@ sub add_next_free_ip {
sub add_ip {
my ($zone, $subnetid, $subnet, $ip, $hostname, $mac, $vmid, $is_gateway, $skipdns) = @_;
- return if !$subnet || !$ip;
+ return if !$subnet || !$ip;
my $ipaddr = NetAddr::IP->new($ip);
$ip = $ipaddr->canon();
@@ -302,48 +303,48 @@ sub add_ip {
$hostname .= ".$dnszoneprefix" if $dnszoneprefix;
#verify dns zones before ipam
- if(!$skipdns) {
- verify_dns_zone($dnszone, $dns);
- verify_dns_zone($reversednszone, $reversedns);
+ if (!$skipdns) {
+ verify_dns_zone($dnszone, $dns);
+ verify_dns_zone($reversednszone, $reversedns);
}
if ($ipamid) {
- my $ipam_cfg = PVE::Network::SDN::Ipams::config();
- my $plugin_config = $ipam_cfg->{ids}->{$ipamid};
- my $plugin = PVE::Network::SDN::Ipams::Plugin->lookup($plugin_config->{type});
+ my $ipam_cfg = PVE::Network::SDN::Ipams::config();
+ my $plugin_config = $ipam_cfg->{ids}->{$ipamid};
+ my $plugin = PVE::Network::SDN::Ipams::Plugin->lookup($plugin_config->{type});
- eval {
- $plugin->add_ip($plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $vmid, $is_gateway);
- };
- die $@ if $@;
+ eval {
+ $plugin->add_ip(
+ $plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $vmid, $is_gateway,
+ );
+ };
+ die $@ if $@;
- eval { PVE::Network::SDN::Ipams::add_cache_mac_ip($mac, $ip) if $mac; };
- warn $@ if $@;
+ eval { PVE::Network::SDN::Ipams::add_cache_mac_ip($mac, $ip) if $mac; };
+ warn $@ if $@;
}
eval {
- if(!$skipdns) {
- #add dns
- add_dns_record($dnszone, $dns, $hostname, $ip);
- #add reverse dns
- add_dns_ptr_record($reversednszone, $dnszone, $reversedns, $hostname, $ip);
- }
+ if (!$skipdns) {
+ #add dns
+ add_dns_record($dnszone, $dns, $hostname, $ip);
+ #add reverse dns
+ add_dns_ptr_record($reversednszone, $dnszone, $reversedns, $hostname, $ip);
+ }
};
if ($@) {
- #rollback
- my $err = $@;
- eval {
- PVE::Network::SDN::Subnets::del_ip($zone, $subnetid, $subnet, $ip, $hostname, $mac)
- };
- die $err;
+ #rollback
+ my $err = $@;
+ eval { PVE::Network::SDN::Subnets::del_ip($zone, $subnetid, $subnet, $ip, $hostname, $mac) };
+ die $err;
}
}
sub update_ip {
my ($zone, $subnetid, $subnet, $ip, $hostname, $oldhostname, $mac, $vmid, $skipdns) = @_;
- return if !$subnet || !$ip;
+ return if !$subnet || !$ip;
my $ipaddr = NetAddr::IP->new($ip);
$ip = $ipaddr->canon();
@@ -358,32 +359,32 @@ sub update_ip {
$hostname .= ".$dnszoneprefix" if $dnszoneprefix;
#verify dns zones before ipam
- if(!$skipdns) {
- verify_dns_zone($dnszone, $dns);
- verify_dns_zone($reversednszone, $reversedns);
+ if (!$skipdns) {
+ verify_dns_zone($dnszone, $dns);
+ verify_dns_zone($reversednszone, $reversedns);
}
if ($ipamid) {
- my $ipam_cfg = PVE::Network::SDN::Ipams::config();
- my $plugin_config = $ipam_cfg->{ids}->{$ipamid};
- my $plugin = PVE::Network::SDN::Ipams::Plugin->lookup($plugin_config->{type});
- eval {
- $plugin->update_ip($plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $vmid);
- };
- die $@ if $@;
+ my $ipam_cfg = PVE::Network::SDN::Ipams::config();
+ my $plugin_config = $ipam_cfg->{ids}->{$ipamid};
+ my $plugin = PVE::Network::SDN::Ipams::Plugin->lookup($plugin_config->{type});
+ eval {
+ $plugin->update_ip($plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $vmid);
+ };
+ die $@ if $@;
}
return if $hostname eq $oldhostname;
eval {
- if(!$skipdns) {
- #add dns
- del_dns_record($dnszone, $dns, $oldhostname, $ip);
- add_dns_record($dnszone, $dns, $hostname, $ip);
- #add reverse dns
- del_dns_ptr_record($reversednszone, $reversedns, $ip);
- add_dns_ptr_record($reversednszone, $dnszone, $reversedns, $hostname, $ip);
- }
+ if (!$skipdns) {
+ #add dns
+ del_dns_record($dnszone, $dns, $oldhostname, $ip);
+ add_dns_record($dnszone, $dns, $hostname, $ip);
+ #add reverse dns
+ del_dns_ptr_record($reversednszone, $reversedns, $ip);
+ add_dns_ptr_record($reversednszone, $dnszone, $reversedns, $hostname, $ip);
+ }
};
}
@@ -403,31 +404,31 @@ sub del_ip {
my $dnszoneprefix = $subnet->{dnszoneprefix};
$hostname .= ".$dnszoneprefix" if $dnszoneprefix;
- if(!$skipdns) {
- verify_dns_zone($dnszone, $dns);
- verify_dns_zone($reversednszone, $reversedns);
+ if (!$skipdns) {
+ verify_dns_zone($dnszone, $dns);
+ verify_dns_zone($reversednszone, $reversedns);
}
if ($ipamid) {
- my $ipam_cfg = PVE::Network::SDN::Ipams::config();
- my $plugin_config = $ipam_cfg->{ids}->{$ipamid};
- my $plugin = PVE::Network::SDN::Ipams::Plugin->lookup($plugin_config->{type});
- $plugin->del_ip($plugin_config, $subnetid, $subnet, $ip);
-
- if ($mac) {
- eval { PVE::Network::SDN::Ipams::del_cache_mac_ip($mac, $ip) };
- warn $@ if $@;
- }
+ my $ipam_cfg = PVE::Network::SDN::Ipams::config();
+ my $plugin_config = $ipam_cfg->{ids}->{$ipamid};
+ my $plugin = PVE::Network::SDN::Ipams::Plugin->lookup($plugin_config->{type});
+ $plugin->del_ip($plugin_config, $subnetid, $subnet, $ip);
+
+ if ($mac) {
+ eval { PVE::Network::SDN::Ipams::del_cache_mac_ip($mac, $ip) };
+ warn $@ if $@;
+ }
}
eval {
- if(!$skipdns) {
- del_dns_record($dnszone, $dns, $hostname, $ip);
- del_dns_ptr_record($reversednszone, $reversedns, $ip);
- }
+ if (!$skipdns) {
+ del_dns_record($dnszone, $dns, $hostname, $ip);
+ del_dns_ptr_record($reversednszone, $reversedns, $ip);
+ }
};
if ($@) {
- warn $@;
+ warn $@;
}
}
diff --git a/src/PVE/Network/SDN/VnetPlugin.pm b/src/PVE/Network/SDN/VnetPlugin.pm
index f44380a..035aaca 100644
--- a/src/PVE/Network/SDN/VnetPlugin.pm
+++ b/src/PVE/Network/SDN/VnetPlugin.pm
@@ -10,16 +10,23 @@ use PVE::JSONSchema qw(get_standard_option);
use PVE::SectionConfig;
use base qw(PVE::SectionConfig);
-PVE::Cluster::cfs_register_file('sdn/vnets.cfg',
- sub { __PACKAGE__->parse_config(@_); },
- sub { __PACKAGE__->write_config(@_); });
-
-PVE::JSONSchema::register_standard_option('pve-sdn-vnet-id', {
- description => "The SDN vnet object identifier.",
- type => 'string', format => 'pve-sdn-vnet-id',
-});
+PVE::Cluster::cfs_register_file(
+ 'sdn/vnets.cfg',
+ sub { __PACKAGE__->parse_config(@_); },
+ sub { __PACKAGE__->write_config(@_); },
+);
+
+PVE::JSONSchema::register_standard_option(
+ 'pve-sdn-vnet-id',
+ {
+ description => "The SDN vnet object identifier.",
+ type => 'string',
+ format => 'pve-sdn-vnet-id',
+ },
+);
PVE::JSONSchema::register_format('pve-sdn-vnet-id', \&parse_sdn_vnet_id);
+
sub parse_sdn_vnet_id {
my ($id, $noerr) = @_;
@@ -34,8 +41,10 @@ sub parse_sdn_vnet_id {
my $defaultData = {
propertyList => {
- vnet => get_standard_option('pve-sdn-vnet-id',
- { completion => \&PVE::Network::SDN::Vnets::complete_sdn_vnet }),
+ vnet => get_standard_option(
+ 'pve-sdn-vnet-id',
+ { completion => \&PVE::Network::SDN::Vnets::complete_sdn_vnet },
+ ),
},
};
@@ -49,43 +58,43 @@ sub private {
sub properties {
return {
- zone => {
+ zone => {
type => 'string',
description => "zone id",
- },
+ },
type => {
description => "Type",
optional => 1,
},
- tag => {
+ tag => {
type => 'integer',
description => "vlan or vxlan id",
- },
- vlanaware => {
- type => 'boolean',
- description => 'Allow vm VLANs to pass through this vnet.',
- },
+ },
+ vlanaware => {
+ type => 'boolean',
+ description => 'Allow vm VLANs to pass through this vnet.',
+ },
alias => {
type => 'string',
description => "alias name of the vnet",
pattern => qr/[\(\)-_.\w\d\s]{0,256}/i,
maxLength => 256,
- optional => 1,
+ optional => 1,
+ },
+ 'isolate-ports' => {
+ type => 'boolean',
+ description => "If true, sets the isolated property for all members of this VNet",
},
- 'isolate-ports' => {
- type => 'boolean',
- description => "If true, sets the isolated property for all members of this VNet",
- }
};
}
sub options {
return {
- zone => { optional => 0},
- tag => { optional => 1},
+ zone => { optional => 0 },
+ tag => { optional => 1 },
alias => { optional => 1 },
vlanaware => { optional => 1 },
- 'isolate-ports' => { optional => 1 },
+ 'isolate-ports' => { optional => 1 },
};
}
@@ -94,7 +103,7 @@ sub on_delete_hook {
#verify if subnets are associated
my $subnets = PVE::Network::SDN::Vnets::get_subnets($vnetid);
- raise_param_exc({ vnet => "Can't delete vnet if subnets exists"}) if $subnets;
+ raise_param_exc({ vnet => "Can't delete vnet if subnets exists" }) if $subnets;
}
sub on_update_hook {
@@ -105,9 +114,10 @@ sub on_update_hook {
my $vlanaware = $vnet->{vlanaware};
#don't allow vlanaware change if subnets are defined
- if($vnet->{vlanaware}) {
- my $subnets = PVE::Network::SDN::Vnets::get_subnets($vnetid);
- raise_param_exc({ vlanaware => "vlanaware vnet is not compatible with subnets"}) if $subnets;
+ if ($vnet->{vlanaware}) {
+ my $subnets = PVE::Network::SDN::Vnets::get_subnets($vnetid);
+ raise_param_exc({ vlanaware => "vlanaware vnet is not compatible with subnets" })
+ if $subnets;
}
}
diff --git a/src/PVE/Network/SDN/Vnets.pm b/src/PVE/Network/SDN/Vnets.pm
index 4e795f2..c16e7e5 100644
--- a/src/PVE/Network/SDN/Vnets.pm
+++ b/src/PVE/Network/SDN/Vnets.pm
@@ -30,8 +30,8 @@ sub config {
my ($running) = @_;
if ($running) {
- my $cfg = PVE::Network::SDN::running_config();
- return $cfg->{vnets};
+ my $cfg = PVE::Network::SDN::running_config();
+ return $cfg->{vnets};
}
return cfs_read_file("sdn/vnets.cfg");
@@ -46,7 +46,7 @@ sub write_config {
sub sdn_vnets_ids {
my ($cfg) = @_;
- return sort keys %{$cfg->{ids}};
+ return sort keys %{ $cfg->{ids} };
}
sub complete_sdn_vnet {
@@ -54,7 +54,7 @@ sub complete_sdn_vnet {
my $cfg = PVE::Network::SDN::Vnets::config();
- return $cmdname eq 'add' ? [] : [ PVE::Network::SDN::Vnets::sdn_vnet_ids($cfg) ];
+ return $cmdname eq 'add' ? [] : [PVE::Network::SDN::Vnets::sdn_vnet_ids($cfg)];
}
sub get_vnet {
@@ -72,10 +72,10 @@ sub get_subnets {
my $subnets = undef;
my $subnets_cfg = PVE::Network::SDN::Subnets::config($running);
- foreach my $subnetid (sort keys %{$subnets_cfg->{ids}}) {
- my $subnet = PVE::Network::SDN::Subnets::sdn_subnets_config($subnets_cfg, $subnetid);
- next if !$subnet->{vnet} || ($vnetid && $subnet->{vnet} ne $vnetid);
- $subnets->{$subnetid} = $subnet;
+ foreach my $subnetid (sort keys %{ $subnets_cfg->{ids} }) {
+ my $subnet = PVE::Network::SDN::Subnets::sdn_subnets_config($subnets_cfg, $subnetid);
+ next if !$subnet->{vnet} || ($vnetid && $subnet->{vnet} ne $vnetid);
+ $subnets->{$subnetid} = $subnet;
}
return $subnets;
@@ -111,36 +111,47 @@ sub add_next_free_cidr {
my @ipversions = defined($ipversion) ? ($ipversion) : qw/ 4 6 /;
for my $ipversion (@ipversions) {
- my $ip = undef;
- my $subnetcount = 0;
- foreach my $subnetid (sort keys %{$subnets}) {
- my $subnet = $subnets->{$subnetid};
- my $network = $subnet->{network};
-
- next if Net::IP::ip_get_version($network) != $ipversion || $ips->{$ipversion};
- $subnetcount++;
-
- eval {
- $ip = PVE::Network::SDN::Subnets::add_next_free_ip($zone, $subnetid, $subnet, $hostname, $mac, $vmid, $skipdns, $subnet->{'dhcp-range'});
- };
- die $@ if $@;
-
- if ($ip) {
- $ips->{$ipversion} = $ip;
- last;
- }
- }
-
- if (!$ip && $subnetcount > 0) {
- foreach my $version (sort keys %{$ips}) {
- my $ip = $ips->{$version};
- my ($subnetid, $subnet) = PVE::Network::SDN::Subnets::find_ip_subnet($ip, $subnets);
-
- PVE::Network::SDN::Subnets::del_ip($zone, $subnetid, $subnet, $ip, $hostname, $mac, $skipdns);
- }
-
- die "can't find any free ip in zone $zoneid for IPv$ipversion";
- }
+ my $ip = undef;
+ my $subnetcount = 0;
+ foreach my $subnetid (sort keys %{$subnets}) {
+ my $subnet = $subnets->{$subnetid};
+ my $network = $subnet->{network};
+
+ next if Net::IP::ip_get_version($network) != $ipversion || $ips->{$ipversion};
+ $subnetcount++;
+
+ eval {
+ $ip = PVE::Network::SDN::Subnets::add_next_free_ip(
+ $zone,
+ $subnetid,
+ $subnet,
+ $hostname,
+ $mac,
+ $vmid,
+ $skipdns,
+ $subnet->{'dhcp-range'},
+ );
+ };
+ die $@ if $@;
+
+ if ($ip) {
+ $ips->{$ipversion} = $ip;
+ last;
+ }
+ }
+
+ if (!$ip && $subnetcount > 0) {
+ foreach my $version (sort keys %{$ips}) {
+ my $ip = $ips->{$version};
+ my ($subnetid, $subnet) = PVE::Network::SDN::Subnets::find_ip_subnet($ip, $subnets);
+
+ PVE::Network::SDN::Subnets::del_ip(
+ $zone, $subnetid, $subnet, $ip, $hostname, $mac, $skipdns,
+ );
+ }
+
+ die "can't find any free ip in zone $zoneid for IPv$ipversion";
+ }
}
}
@@ -148,9 +159,12 @@ sub add_ip {
my ($vnetid, $ip, $hostname, $mac, $vmid, $skipdns) = @_;
return if !$vnetid;
-
- my ($zone, $subnetid, $subnet) = PVE::Network::SDN::Vnets::get_subnet_from_vnet_ip($vnetid, $ip);
- PVE::Network::SDN::Subnets::add_ip($zone, $subnetid, $subnet, $ip, $hostname, $mac, $vmid, undef, $skipdns);
+
+ my ($zone, $subnetid, $subnet) =
+ PVE::Network::SDN::Vnets::get_subnet_from_vnet_ip($vnetid, $ip);
+ PVE::Network::SDN::Subnets::add_ip(
+ $zone, $subnetid, $subnet, $ip, $hostname, $mac, $vmid, undef, $skipdns,
+ );
}
sub update_ip {
@@ -158,8 +172,11 @@ sub update_ip {
return if !$vnetid;
- my ($zone, $subnetid, $subnet) = PVE::Network::SDN::Vnets::get_subnet_from_vnet_ip($vnetid, $ip);
- PVE::Network::SDN::Subnets::update_ip($zone, $subnetid, $subnet, $ip, $hostname, $oldhostname, $mac, $vmid, $skipdns);
+ my ($zone, $subnetid, $subnet) =
+ PVE::Network::SDN::Vnets::get_subnet_from_vnet_ip($vnetid, $ip);
+ PVE::Network::SDN::Subnets::update_ip(
+ $zone, $subnetid, $subnet, $ip, $hostname, $oldhostname, $mac, $vmid, $skipdns,
+ );
}
sub del_ip {
@@ -167,7 +184,8 @@ sub del_ip {
return if !$vnetid;
- my ($zone, $subnetid, $subnet) = PVE::Network::SDN::Vnets::get_subnet_from_vnet_ip($vnetid, $ip);
+ my ($zone, $subnetid, $subnet) =
+ PVE::Network::SDN::Vnets::get_subnet_from_vnet_ip($vnetid, $ip);
PVE::Network::SDN::Subnets::del_ip($zone, $subnetid, $subnet, $ip, $hostname, $mac, $skipdns);
}
@@ -206,8 +224,8 @@ sub add_dhcp_mapping {
return if !$zone->{ipam} || !$zone->{dhcp};
my ($ip4, $ip6) = PVE::Network::SDN::Vnets::get_ips_from_mac($vnetid, $mac);
- add_next_free_cidr($vnetid, $name, $mac, "$vmid", undef, 1, 4) if ! $ip4;
- add_next_free_cidr($vnetid, $name, $mac, "$vmid", undef, 1, 6) if ! $ip6;
+ add_next_free_cidr($vnetid, $name, $mac, "$vmid", undef, 1, 4) if !$ip4;
+ add_next_free_cidr($vnetid, $name, $mac, "$vmid", undef, 1, 6) if !$ip6;
($ip4, $ip6) = PVE::Network::SDN::Vnets::get_ips_from_mac($vnetid, $mac);
PVE::Network::SDN::Dhcp::add_mapping($vnetid, $mac, $ip4, $ip6) if $ip4 || $ip6;
diff --git a/src/PVE/Network/SDN/Zones.pm b/src/PVE/Network/SDN/Zones.pm
index c1c7745..01c168c 100644
--- a/src/PVE/Network/SDN/Zones.pm
+++ b/src/PVE/Network/SDN/Zones.pm
@@ -44,8 +44,8 @@ sub config {
my ($running) = @_;
if ($running) {
- my $cfg = PVE::Network::SDN::running_config();
- return $cfg->{zones};
+ my $cfg = PVE::Network::SDN::running_config();
+ return $cfg->{zones};
}
return cfs_read_file("sdn/zones.cfg");
@@ -67,7 +67,7 @@ sub write_config {
sub sdn_zones_ids {
my ($cfg) = @_;
- return sort keys %{$cfg->{ids}};
+ return sort keys %{ $cfg->{ids} };
}
sub complete_sdn_zone {
@@ -75,7 +75,7 @@ sub complete_sdn_zone {
my $cfg = PVE::Network::SDN::running_config();
- return $cmdname eq 'add' ? [] : [ PVE::Network::SDN::sdn_zones_ids($cfg) ];
+ return $cmdname eq 'add' ? [] : [PVE::Network::SDN::sdn_zones_ids($cfg)];
}
sub get_zone {
@@ -96,7 +96,7 @@ sub get_vnets {
my $vnets_config = PVE::Network::SDN::Vnets::config($running);
my $vnets = undef;
- for my $vnetid (keys %{$vnets_config->{ids}}) {
+ for my $vnetid (keys %{ $vnets_config->{ids} }) {
my $vnet = PVE::Network::SDN::Vnets::sdn_vnets_config($vnets_config, $vnetid);
next if !$vnet->{zone} || $vnet->{zone} ne $zoneid;
$vnets->{$vnetid} = $vnet;
@@ -122,47 +122,57 @@ sub generate_etc_network_config {
my $config = {};
my $nodename = PVE::INotify::nodename();
- for my $id (sort keys %{$vnet_cfg->{ids}}) {
- my $vnet = $vnet_cfg->{ids}->{$id};
- my $zone = $vnet->{zone};
-
- if (!$zone) {
- warn "can't generate vnet '$id': no zone assigned!\n";
- next;
- }
-
- my $plugin_config = $zone_cfg->{ids}->{$zone};
-
- if (!defined($plugin_config)) {
- warn "can't generate vnet '$id': zone $zone don't exist\n";
- next;
- }
-
- next if defined($plugin_config->{nodes}) && !$plugin_config->{nodes}->{$nodename};
-
- my $controller;
- if (my $controllerid = $plugin_config->{controller}) {
- $controller = $controller_cfg->{ids}->{$controllerid};
- }
-
- my $plugin = PVE::Network::SDN::Zones::Plugin->lookup($plugin_config->{type});
- eval {
- $plugin->generate_sdn_config($plugin_config, $zone, $id, $vnet, $controller, $controller_cfg, $subnet_cfg, $interfaces_config, $config);
- };
- if (my $err = $@) {
- warn "zone $zone : vnet $id : $err\n";
- next;
- }
+ for my $id (sort keys %{ $vnet_cfg->{ids} }) {
+ my $vnet = $vnet_cfg->{ids}->{$id};
+ my $zone = $vnet->{zone};
+
+ if (!$zone) {
+ warn "can't generate vnet '$id': no zone assigned!\n";
+ next;
+ }
+
+ my $plugin_config = $zone_cfg->{ids}->{$zone};
+
+ if (!defined($plugin_config)) {
+ warn "can't generate vnet '$id': zone $zone don't exist\n";
+ next;
+ }
+
+ next if defined($plugin_config->{nodes}) && !$plugin_config->{nodes}->{$nodename};
+
+ my $controller;
+ if (my $controllerid = $plugin_config->{controller}) {
+ $controller = $controller_cfg->{ids}->{$controllerid};
+ }
+
+ my $plugin = PVE::Network::SDN::Zones::Plugin->lookup($plugin_config->{type});
+ eval {
+ $plugin->generate_sdn_config(
+ $plugin_config,
+ $zone,
+ $id,
+ $vnet,
+ $controller,
+ $controller_cfg,
+ $subnet_cfg,
+ $interfaces_config,
+ $config,
+ );
+ };
+ if (my $err = $@) {
+ warn "zone $zone : vnet $id : $err\n";
+ next;
+ }
}
my $raw_network_config = "\#version:$version\n";
foreach my $iface (sort keys %$config) {
- $raw_network_config .= "\n";
- $raw_network_config .= "auto $iface\n";
- $raw_network_config .= "iface $iface\n";
- foreach my $option (@{$config->{$iface}}) {
- $raw_network_config .= "\t$option\n";
- }
+ $raw_network_config .= "\n";
+ $raw_network_config .= "auto $iface\n";
+ $raw_network_config .= "iface $iface\n";
+ foreach my $option (@{ $config->{$iface} }) {
+ $raw_network_config .= "\t$option\n";
+ }
}
return $raw_network_config;
@@ -173,7 +183,7 @@ sub write_etc_network_config {
return if !$rawconfig;
- my $writefh = IO::File->new($local_network_sdn_file,">");
+ my $writefh = IO::File->new($local_network_sdn_file, ">");
print $writefh $rawconfig;
$writefh->close();
}
@@ -184,31 +194,29 @@ sub read_etc_network_config_version {
return if !defined($versionstr);
if ($versionstr =~ m/^\#version:(\d+)$/) {
- return $1;
+ return $1;
}
}
sub ifquery_check {
- my $cmd = ['ifquery', '-a', '-c', '-o','json'];
+ my $cmd = ['ifquery', '-a', '-c', '-o', 'json'];
my $result = '';
my $reader = sub { $result .= shift };
- eval {
- run_command($cmd, outfunc => $reader);
- };
+ eval { run_command($cmd, outfunc => $reader); };
my $resultjson = decode_json($result);
my $interfaces = {};
foreach my $interface (@$resultjson) {
- my $name = $interface->{name};
- $interfaces->{$name} = {
- status => $interface->{status},
- config => $interface->{config},
- config_status => $interface->{config_status},
- };
+ my $name = $interface->{name};
+ $interfaces->{$name} = {
+ status => $interface->{status},
+ config => $interface->{config},
+ config_status => $interface->{config_status},
+ };
}
return $interfaces;
@@ -227,19 +235,19 @@ sub status {
return if !$sdn_version;
if (!$local_version) {
- $err_config = "local sdn network configuration is not yet generated, please reload";
- if (!$warned_about_reload) {
- $warned_about_reload = 1;
- warn "$err_config\n";
- }
+ $err_config = "local sdn network configuration is not yet generated, please reload";
+ if (!$warned_about_reload) {
+ $warned_about_reload = 1;
+ warn "$err_config\n";
+ }
} elsif ($local_version < $sdn_version) {
- $err_config = "local sdn network configuration is too old, please reload";
- if (!$warned_about_reload) {
- $warned_about_reload = 1;
- warn "$err_config\n";
- }
+ $err_config = "local sdn network configuration is too old, please reload";
+ if (!$warned_about_reload) {
+ $warned_about_reload = 1;
+ warn "$err_config\n";
+ }
} else {
- $warned_about_reload = 0;
+ $warned_about_reload = 0;
}
my $status = ifquery_check();
@@ -251,42 +259,44 @@ sub status {
my $vnet_status = {};
my $zone_status = {};
- for my $id (sort keys %{$zone_cfg->{ids}}) {
- next if defined($zone_cfg->{ids}->{$id}->{nodes}) && !$zone_cfg->{ids}->{$id}->{nodes}->{$nodename};
- $zone_status->{$id}->{status} = $err_config ? 'pending' : 'available';
+ for my $id (sort keys %{ $zone_cfg->{ids} }) {
+ next
+ if defined($zone_cfg->{ids}->{$id}->{nodes})
+ && !$zone_cfg->{ids}->{$id}->{nodes}->{$nodename};
+ $zone_status->{$id}->{status} = $err_config ? 'pending' : 'available';
}
- foreach my $id (sort keys %{$vnet_cfg->{ids}}) {
- my $vnet = $vnet_cfg->{ids}->{$id};
- my $zone = $vnet->{zone};
- next if !defined($zone);
-
- my $plugin_config = $zone_cfg->{ids}->{$zone};
-
- if (!defined($plugin_config)) {
- $vnet_status->{$id}->{status} = 'error';
- $vnet_status->{$id}->{statusmsg} = "unknown zone '$zone' configured";
- next;
- }
-
- next if defined($plugin_config->{nodes}) && !$plugin_config->{nodes}->{$nodename};
-
- $vnet_status->{$id}->{zone} = $zone;
- $vnet_status->{$id}->{status} = 'available';
-
- if ($err_config) {
- $vnet_status->{$id}->{status} = 'pending';
- $vnet_status->{$id}->{statusmsg} = $err_config;
- next;
- }
-
- my $plugin = PVE::Network::SDN::Zones::Plugin->lookup($plugin_config->{type});
- my $err_msg = $plugin->status($plugin_config, $zone, $id, $vnet, $status);
- if (@{$err_msg} > 0) {
- $vnet_status->{$id}->{status} = 'error';
- $vnet_status->{$id}->{statusmsg} = join(',', @{$err_msg});
- $zone_status->{$zone}->{status} = 'error';
- }
+ foreach my $id (sort keys %{ $vnet_cfg->{ids} }) {
+ my $vnet = $vnet_cfg->{ids}->{$id};
+ my $zone = $vnet->{zone};
+ next if !defined($zone);
+
+ my $plugin_config = $zone_cfg->{ids}->{$zone};
+
+ if (!defined($plugin_config)) {
+ $vnet_status->{$id}->{status} = 'error';
+ $vnet_status->{$id}->{statusmsg} = "unknown zone '$zone' configured";
+ next;
+ }
+
+ next if defined($plugin_config->{nodes}) && !$plugin_config->{nodes}->{$nodename};
+
+ $vnet_status->{$id}->{zone} = $zone;
+ $vnet_status->{$id}->{status} = 'available';
+
+ if ($err_config) {
+ $vnet_status->{$id}->{status} = 'pending';
+ $vnet_status->{$id}->{statusmsg} = $err_config;
+ next;
+ }
+
+ my $plugin = PVE::Network::SDN::Zones::Plugin->lookup($plugin_config->{type});
+ my $err_msg = $plugin->status($plugin_config, $zone, $id, $vnet, $status);
+ if (@{$err_msg} > 0) {
+ $vnet_status->{$id}->{status} = 'error';
+ $vnet_status->{$id}->{statusmsg} = join(',', @{$err_msg});
+ $zone_status->{$zone}->{status} = 'error';
+ }
}
return ($zone_status, $vnet_status);
@@ -297,8 +307,8 @@ sub tap_create {
my $vnet = PVE::Network::SDN::Vnets::get_vnet($bridge, 1);
if (!$vnet) { # fallback for classic bridge
- PVE::Network::tap_create($iface, $bridge);
- return;
+ PVE::Network::tap_create($iface, $bridge);
+ return;
}
my $plugin_config = get_plugin_config($vnet);
@@ -311,8 +321,8 @@ sub veth_create {
my $vnet = PVE::Network::SDN::Vnets::get_vnet($bridge, 1);
if (!$vnet) { # fallback for classic bridge
- PVE::Network::veth_create($veth, $vethpeer, $bridge, $hwaddr);
- return;
+ PVE::Network::veth_create($veth, $vethpeer, $bridge, $hwaddr);
+ return;
}
my $plugin_config = get_plugin_config($vnet);
@@ -325,18 +335,20 @@ sub tap_plug {
my $vnet = PVE::Network::SDN::Vnets::get_vnet($bridge, 1);
if (!$vnet) { # fallback for classic bridge
- my $interfaces_config = PVE::INotify::read_file('interfaces');
- my $opts = {};
- $opts->{learning} = 0 if $interfaces_config->{ifaces}->{$bridge} && $interfaces_config->{ifaces}->{$bridge}->{'bridge-disable-mac-learning'};
- PVE::Network::tap_plug($iface, $bridge, $tag, $firewall, $trunks, $rate, $opts);
- return;
+ my $interfaces_config = PVE::INotify::read_file('interfaces');
+ my $opts = {};
+ $opts->{learning} = 0
+ if $interfaces_config->{ifaces}->{$bridge}
+ && $interfaces_config->{ifaces}->{$bridge}->{'bridge-disable-mac-learning'};
+ PVE::Network::tap_plug($iface, $bridge, $tag, $firewall, $trunks, $rate, $opts);
+ return;
}
my $plugin_config = get_plugin_config($vnet);
my $nodename = PVE::INotify::nodename();
die "vnet $bridge is not allowed on this node\n"
- if $plugin_config->{nodes} && !defined($plugin_config->{nodes}->{$nodename});
+ if $plugin_config->{nodes} && !defined($plugin_config->{nodes}->{$nodename});
my $plugin = PVE::Network::SDN::Zones::Plugin->lookup($plugin_config->{type});
$plugin->tap_plug($plugin_config, $vnet, $tag, $iface, $bridge, $firewall, $trunks, $rate);
@@ -347,8 +359,8 @@ sub add_bridge_fdb {
my $vnet = PVE::Network::SDN::Vnets::get_vnet($bridge, 1);
if (!$vnet) { # fallback for classic bridge
- PVE::Network::add_bridge_fdb($iface, $macaddr);
- return;
+ PVE::Network::add_bridge_fdb($iface, $macaddr);
+ return;
}
my $plugin_config = get_plugin_config($vnet);
@@ -361,8 +373,8 @@ sub del_bridge_fdb {
my $vnet = PVE::Network::SDN::Vnets::get_vnet($bridge, 1);
if (!$vnet) { # fallback for classic bridge
- PVE::Network::del_bridge_fdb($iface, $macaddr);
- return;
+ PVE::Network::del_bridge_fdb($iface, $macaddr);
+ return;
}
my $plugin_config = get_plugin_config($vnet);
diff --git a/src/PVE/Network/SDN/Zones/EvpnPlugin.pm b/src/PVE/Network/SDN/Zones/EvpnPlugin.pm
index 4843756..7d26e1b 100644
--- a/src/PVE/Network/SDN/Zones/EvpnPlugin.pm
+++ b/src/PVE/Network/SDN/Zones/EvpnPlugin.pm
@@ -21,91 +21,107 @@ sub type {
}
PVE::JSONSchema::register_format('pve-sdn-bgp-rt', \&pve_verify_sdn_bgp_rt);
+
sub pve_verify_sdn_bgp_rt {
my ($rt) = @_;
if ($rt =~ m/^(\d+):(\d+)$/) {
- my $asn = $1;
- my $id = $2;
-
- if ($asn < 0 || $asn > 4294967295) {
- die "value does not look like a valid bgp route-target\n";
- }
- if ($id < 0 || $id > 4294967295) {
- die "value does not look like a valid bgp route-target\n";
- }
+ my $asn = $1;
+ my $id = $2;
+
+ if ($asn < 0 || $asn > 4294967295) {
+ die "value does not look like a valid bgp route-target\n";
+ }
+ if ($id < 0 || $id > 4294967295) {
+ die "value does not look like a valid bgp route-target\n";
+ }
} else {
- die "value does not look like a valid bgp route-target\n";
+ die "value does not look like a valid bgp route-target\n";
}
return $rt;
}
sub properties {
return {
- 'vrf-vxlan' => {
- type => 'integer',
- description => "l3vni.",
- },
- 'controller' => {
- type => 'string',
- description => "Frr router name",
- },
- 'mac' => {
- type => 'string',
- description => "Anycast logical router mac address",
- optional => 1, format => 'mac-addr'
- },
- 'exitnodes' => get_standard_option('pve-node-list'),
- 'exitnodes-local-routing' => {
- type => 'boolean',
- description => "Allow exitnodes to connect to evpn guests",
- optional => 1
- },
- 'exitnodes-primary' => get_standard_option('pve-node', {
- description => "Force traffic to this exitnode first."}),
- 'advertise-subnets' => {
- type => 'boolean',
- description => "Advertise evpn subnets if you have silent hosts",
- optional => 1
- },
- 'disable-arp-nd-suppression' => {
- type => 'boolean',
- description => "Disable ipv4 arp && ipv6 neighbour discovery suppression",
- optional => 1
- },
- 'rt-import' => {
- type => 'string',
- description => "Route-Target import",
- optional => 1, format => 'pve-sdn-bgp-rt-list'
- }
+ 'vrf-vxlan' => {
+ type => 'integer',
+ description => "l3vni.",
+ },
+ 'controller' => {
+ type => 'string',
+ description => "Frr router name",
+ },
+ 'mac' => {
+ type => 'string',
+ description => "Anycast logical router mac address",
+ optional => 1,
+ format => 'mac-addr',
+ },
+ 'exitnodes' => get_standard_option('pve-node-list'),
+ 'exitnodes-local-routing' => {
+ type => 'boolean',
+ description => "Allow exitnodes to connect to evpn guests",
+ optional => 1,
+ },
+ 'exitnodes-primary' => get_standard_option(
+ 'pve-node',
+ { description => "Force traffic to this exitnode first." },
+ ),
+ 'advertise-subnets' => {
+ type => 'boolean',
+ description => "Advertise evpn subnets if you have silent hosts",
+ optional => 1,
+ },
+ 'disable-arp-nd-suppression' => {
+ type => 'boolean',
+ description => "Disable ipv4 arp && ipv6 neighbour discovery suppression",
+ optional => 1,
+ },
+ 'rt-import' => {
+ type => 'string',
+ description => "Route-Target import",
+ optional => 1,
+ format => 'pve-sdn-bgp-rt-list',
+ },
};
}
sub options {
return {
- nodes => { optional => 1},
- 'vrf-vxlan' => { optional => 0 },
- controller => { optional => 0 },
- exitnodes => { optional => 1 },
- 'exitnodes-local-routing' => { optional => 1 },
- 'exitnodes-primary' => { optional => 1 },
- 'advertise-subnets' => { optional => 1 },
- 'disable-arp-nd-suppression' => { optional => 1 },
+ nodes => { optional => 1 },
+ 'vrf-vxlan' => { optional => 0 },
+ controller => { optional => 0 },
+ exitnodes => { optional => 1 },
+ 'exitnodes-local-routing' => { optional => 1 },
+ 'exitnodes-primary' => { optional => 1 },
+ 'advertise-subnets' => { optional => 1 },
+ 'disable-arp-nd-suppression' => { optional => 1 },
'bridge-disable-mac-learning' => { optional => 1 },
- 'rt-import' => { optional => 1 },
- 'vxlan-port' => { optional => 1 },
- mtu => { optional => 1 },
- mac => { optional => 1 },
- dns => { optional => 1 },
- reversedns => { optional => 1 },
- dnszone => { optional => 1 },
- ipam => { optional => 1 },
+ 'rt-import' => { optional => 1 },
+ 'vxlan-port' => { optional => 1 },
+ mtu => { optional => 1 },
+ mac => { optional => 1 },
+ dns => { optional => 1 },
+ reversedns => { optional => 1 },
+ dnszone => { optional => 1 },
+ ipam => { optional => 1 },
};
}
# Plugin implementation
sub generate_sdn_config {
- my ($class, $plugin_config, $zoneid, $vnetid, $vnet, $controller, $controller_cfg, $subnet_cfg, $interfaces_config, $config) = @_;
+ my (
+ $class,
+ $plugin_config,
+ $zoneid,
+ $vnetid,
+ $vnet,
+ $controller,
+ $controller_cfg,
+ $subnet_cfg,
+ $interfaces_config,
+ $config,
+ ) = @_;
my $tag = $vnet->{tag};
my $alias = $vnet->{alias};
@@ -122,19 +138,23 @@ sub generate_sdn_config {
my @peers = PVE::Tools::split_list($controller->{'peers'});
my $loopback = undef;
- my $bgprouter = PVE::Network::SDN::Controllers::EvpnPlugin::find_bgp_controller($local_node, $controller_cfg);
- my $isisrouter = PVE::Network::SDN::Controllers::EvpnPlugin::find_isis_controller($local_node, $controller_cfg);
+ my $bgprouter = PVE::Network::SDN::Controllers::EvpnPlugin::find_bgp_controller(
+ $local_node, $controller_cfg,
+ );
+ my $isisrouter = PVE::Network::SDN::Controllers::EvpnPlugin::find_isis_controller(
+ $local_node, $controller_cfg,
+ );
if ($bgprouter->{loopback}) {
- $loopback = $bgprouter->{loopback};
+ $loopback = $bgprouter->{loopback};
} elsif ($isisrouter->{loopback}) {
- $loopback = $isisrouter->{loopback};
+ $loopback = $isisrouter->{loopback};
}
- my ($ifaceip, $iface) = PVE::Network::SDN::Zones::Plugin::find_local_ip_interface_peers(\@peers, $loopback);
+ my ($ifaceip, $iface) =
+ PVE::Network::SDN::Zones::Plugin::find_local_ip_interface_peers(\@peers, $loopback);
my $is_evpn_gateway = $plugin_config->{'exitnodes'}->{$local_node};
my $exitnodes_local_routing = $plugin_config->{'exitnodes-local-routing'};
-
my $mtu = 1450;
$mtu = $interfaces_config->{$iface}->{mtu} - 50 if $interfaces_config->{$iface}->{mtu};
$mtu = $plugin_config->{mtu} if $plugin_config->{mtu};
@@ -146,10 +166,11 @@ sub generate_sdn_config {
push @iface_config, "vxlan-local-tunnelip $ifaceip" if $ifaceip;
push @iface_config, "vxlan-port $vxlanport" if $vxlanport;
push @iface_config, "bridge-learning off";
- push @iface_config, "bridge-arp-nd-suppress on" if !$plugin_config->{'disable-arp-nd-suppression'};
+ push @iface_config, "bridge-arp-nd-suppress on"
+ if !$plugin_config->{'disable-arp-nd-suppression'};
push @iface_config, "mtu $mtu" if $mtu;
- push(@{$config->{$vxlan_iface}}, @iface_config) if !$config->{$vxlan_iface};
+ push(@{ $config->{$vxlan_iface} }, @iface_config) if !$config->{$vxlan_iface};
#vnet bridge
@iface_config = ();
@@ -161,43 +182,48 @@ sub generate_sdn_config {
my $enable_forward_v6 = undef;
my $subnets = PVE::Network::SDN::Vnets::get_subnets($vnetid, 1);
foreach my $subnetid (sort keys %{$subnets}) {
- my $subnet = $subnets->{$subnetid};
- my $cidr = $subnet->{cidr};
- my $mask = $subnet->{mask};
-
- my $gateway = $subnet->{gateway};
- if ($gateway) {
- push @iface_config, "address $gateway/$mask" if !defined($address->{$gateway});
- $address->{$gateway} = 1;
- }
+ my $subnet = $subnets->{$subnetid};
+ my $cidr = $subnet->{cidr};
+ my $mask = $subnet->{mask};
+
+ my $gateway = $subnet->{gateway};
+ if ($gateway) {
+ push @iface_config, "address $gateway/$mask" if !defined($address->{$gateway});
+ $address->{$gateway} = 1;
+ }
my $iptables = undef;
my $checkrouteip = undef;
my $ipversion = Net::IP::ip_is_ipv6($gateway) ? 6 : 4;
- if ($ipversion == 6) {
- $ipv6 = 1;
- $iptables = "ip6tables";
- $checkrouteip = '2001:4860:4860::8888';
- $enable_forward_v6 = 1 if $gateway;
- } else {
- $ipv4 = 1;
- $iptables = "iptables";
- $checkrouteip = '8.8.8.8';
- $enable_forward_v4 = 1 if $gateway;
- }
+ if ($ipversion == 6) {
+ $ipv6 = 1;
+ $iptables = "ip6tables";
+ $checkrouteip = '2001:4860:4860::8888';
+ $enable_forward_v6 = 1 if $gateway;
+ } else {
+ $ipv4 = 1;
+ $iptables = "iptables";
+ $checkrouteip = '8.8.8.8';
+ $enable_forward_v4 = 1 if $gateway;
+ }
- if ($subnet->{snat}) {
+ if ($subnet->{snat}) {
#find outgoing interface
- my ($outip, $outiface) = PVE::Network::SDN::Zones::Plugin::get_local_route_ip($checkrouteip);
+ my ($outip, $outiface) =
+ PVE::Network::SDN::Zones::Plugin::get_local_route_ip($checkrouteip);
if ($outip && $outiface && $is_evpn_gateway) {
#use snat, faster than masquerade
- push @iface_config, "post-up $iptables -t nat -A POSTROUTING -s '$cidr' -o $outiface -j SNAT --to-source $outip";
- push @iface_config, "post-down $iptables -t nat -D POSTROUTING -s '$cidr' -o $outiface -j SNAT --to-source $outip";
+ push @iface_config,
+ "post-up $iptables -t nat -A POSTROUTING -s '$cidr' -o $outiface -j SNAT --to-source $outip";
+ push @iface_config,
+ "post-down $iptables -t nat -D POSTROUTING -s '$cidr' -o $outiface -j SNAT --to-source $outip";
#add conntrack zone once on outgoing interface
- push @iface_config, "post-up $iptables -t raw -I PREROUTING -i fwbr+ -j CT --zone 1";
- push @iface_config, "post-down $iptables -t raw -D PREROUTING -i fwbr+ -j CT --zone 1";
+ push @iface_config,
+ "post-up $iptables -t raw -I PREROUTING -i fwbr+ -j CT --zone 1";
+ push @iface_config,
+ "post-down $iptables -t raw -D PREROUTING -i fwbr+ -j CT --zone 1";
}
}
}
@@ -210,65 +236,68 @@ sub generate_sdn_config {
push @iface_config, "alias $alias" if $alias;
push @iface_config, "ip-forward on" if $enable_forward_v4;
push @iface_config, "ip6-forward on" if $enable_forward_v6;
- push @iface_config, "arp-accept on" if $ipv4||$ipv6;
+ push @iface_config, "arp-accept on" if $ipv4 || $ipv6;
push @iface_config, "vrf $vrf_iface" if $vrf_iface;
- push(@{$config->{$vnetid}}, @iface_config) if !$config->{$vnetid};
+ push(@{ $config->{$vnetid} }, @iface_config) if !$config->{$vnetid};
if ($vrf_iface) {
- #vrf interface
- @iface_config = ();
- push @iface_config, "vrf-table auto";
- if(!$is_evpn_gateway) {
- push @iface_config, "post-up ip route add vrf $vrf_iface unreachable default metric 4278198272";
- } else {
- push @iface_config, "post-up ip route del vrf $vrf_iface unreachable default metric 4278198272";
- }
-
- push(@{$config->{$vrf_iface}}, @iface_config) if !$config->{$vrf_iface};
-
- if ($vrfvxlan) {
- #l3vni vxlan interface
- my $iface_vrf_vxlan = "vrfvx_$zoneid";
- @iface_config = ();
- push @iface_config, "vxlan-id $vrfvxlan";
- push @iface_config, "vxlan-local-tunnelip $ifaceip" if $ifaceip;
- push @iface_config, "vxlan-port $vxlanport" if $vxlanport;
- push @iface_config, "bridge-learning off";
- push @iface_config, "bridge-arp-nd-suppress on" if !$plugin_config->{'disable-arp-nd-suppression'};
- push @iface_config, "mtu $mtu" if $mtu;
- push(@{$config->{$iface_vrf_vxlan}}, @iface_config) if !$config->{$iface_vrf_vxlan};
-
- #l3vni bridge
- my $brvrf = "vrfbr_$zoneid";
- @iface_config = ();
- push @iface_config, "bridge-ports $iface_vrf_vxlan";
- push @iface_config, "bridge_stp off";
- push @iface_config, "bridge_fd 0";
- push @iface_config, "mtu $mtu" if $mtu;
- push @iface_config, "vrf $vrf_iface";
- push(@{$config->{$brvrf}}, @iface_config) if !$config->{$brvrf};
- }
-
- if ( $is_evpn_gateway && $exitnodes_local_routing ) {
- #add a veth pair for local cross-vrf routing
- my $iface_xvrf = "xvrf_$zoneid";
- my $iface_xvrfp = "xvrfp_$zoneid";
-
- @iface_config = ();
- push @iface_config, "link-type veth";
- push @iface_config, "address 10.255.255.1/30";
- push @iface_config, "veth-peer-name $iface_xvrfp";
- push @iface_config, "mtu ".($mtu+50) if $mtu;
- push(@{$config->{$iface_xvrf}}, @iface_config) if !$config->{$iface_xvrf};
-
- @iface_config = ();
- push @iface_config, "link-type veth";
- push @iface_config, "address 10.255.255.2/30";
- push @iface_config, "veth-peer-name $iface_xvrf";
- push @iface_config, "vrf $vrf_iface";
- push @iface_config, "mtu ".($mtu+50) if $mtu;
- push(@{$config->{$iface_xvrfp}}, @iface_config) if !$config->{$iface_xvrfp};
- }
+ #vrf interface
+ @iface_config = ();
+ push @iface_config, "vrf-table auto";
+ if (!$is_evpn_gateway) {
+ push @iface_config,
+ "post-up ip route add vrf $vrf_iface unreachable default metric 4278198272";
+ } else {
+ push @iface_config,
+ "post-up ip route del vrf $vrf_iface unreachable default metric 4278198272";
+ }
+
+ push(@{ $config->{$vrf_iface} }, @iface_config) if !$config->{$vrf_iface};
+
+ if ($vrfvxlan) {
+ #l3vni vxlan interface
+ my $iface_vrf_vxlan = "vrfvx_$zoneid";
+ @iface_config = ();
+ push @iface_config, "vxlan-id $vrfvxlan";
+ push @iface_config, "vxlan-local-tunnelip $ifaceip" if $ifaceip;
+ push @iface_config, "vxlan-port $vxlanport" if $vxlanport;
+ push @iface_config, "bridge-learning off";
+ push @iface_config, "bridge-arp-nd-suppress on"
+ if !$plugin_config->{'disable-arp-nd-suppression'};
+ push @iface_config, "mtu $mtu" if $mtu;
+ push(@{ $config->{$iface_vrf_vxlan} }, @iface_config) if !$config->{$iface_vrf_vxlan};
+
+ #l3vni bridge
+ my $brvrf = "vrfbr_$zoneid";
+ @iface_config = ();
+ push @iface_config, "bridge-ports $iface_vrf_vxlan";
+ push @iface_config, "bridge_stp off";
+ push @iface_config, "bridge_fd 0";
+ push @iface_config, "mtu $mtu" if $mtu;
+ push @iface_config, "vrf $vrf_iface";
+ push(@{ $config->{$brvrf} }, @iface_config) if !$config->{$brvrf};
+ }
+
+ if ($is_evpn_gateway && $exitnodes_local_routing) {
+ #add a veth pair for local cross-vrf routing
+ my $iface_xvrf = "xvrf_$zoneid";
+ my $iface_xvrfp = "xvrfp_$zoneid";
+
+ @iface_config = ();
+ push @iface_config, "link-type veth";
+ push @iface_config, "address 10.255.255.1/30";
+ push @iface_config, "veth-peer-name $iface_xvrfp";
+ push @iface_config, "mtu " . ($mtu + 50) if $mtu;
+ push(@{ $config->{$iface_xvrf} }, @iface_config) if !$config->{$iface_xvrf};
+
+ @iface_config = ();
+ push @iface_config, "link-type veth";
+ push @iface_config, "address 10.255.255.2/30";
+ push @iface_config, "veth-peer-name $iface_xvrf";
+ push @iface_config, "vrf $vrf_iface";
+ push @iface_config, "mtu " . ($mtu + 50) if $mtu;
+ push(@{ $config->{$iface_xvrfp} }, @iface_config) if !$config->{$iface_xvrfp};
+ }
}
return $config;
}
@@ -279,50 +308,53 @@ sub on_update_hook {
# verify that controller exist
my $controller = $zone_cfg->{ids}->{$zoneid}->{controller};
if (!defined($controller_cfg->{ids}->{$controller})) {
- die "controller $controller don't exist";
+ die "controller $controller don't exist";
} else {
- die "$controller is not a evpn controller type" if $controller_cfg->{ids}->{$controller}->{type} ne 'evpn';
+ die "$controller is not a evpn controller type"
+ if $controller_cfg->{ids}->{$controller}->{type} ne 'evpn';
}
#vrf-vxlan need to be defined
my $vrfvxlan = $zone_cfg->{ids}->{$zoneid}->{'vrf-vxlan'};
# verify that vrf-vxlan is not already declared in another zone
- foreach my $id (keys %{$zone_cfg->{ids}}) {
- next if $id eq $zoneid;
- die "vrf-vxlan $vrfvxlan is already declared in $id"
- if (defined($zone_cfg->{ids}->{$id}->{'vrf-vxlan'}) && $zone_cfg->{ids}->{$id}->{'vrf-vxlan'} eq $vrfvxlan);
+ foreach my $id (keys %{ $zone_cfg->{ids} }) {
+ next if $id eq $zoneid;
+ die "vrf-vxlan $vrfvxlan is already declared in $id"
+ if (defined($zone_cfg->{ids}->{$id}->{'vrf-vxlan'})
+ && $zone_cfg->{ids}->{$id}->{'vrf-vxlan'} eq $vrfvxlan);
}
if (!defined($zone_cfg->{ids}->{$zoneid}->{'mac'})) {
my $dc = PVE::Network::SDN::Zones::Plugin->datacenter_config();
- $zone_cfg->{ids}->{$zoneid}->{'mac'} = PVE::Tools::random_ether_addr($dc->{mac_prefix});
+ $zone_cfg->{ids}->{$zoneid}->{'mac'} = PVE::Tools::random_ether_addr($dc->{mac_prefix});
}
}
-
sub vnet_update_hook {
my ($class, $vnet_cfg, $vnetid, $zone_cfg) = @_;
my $vnet = $vnet_cfg->{ids}->{$vnetid};
my $tag = $vnet->{tag};
- raise_param_exc({ tag => "missing vxlan tag"}) if !defined($tag);
- raise_param_exc({ tag => "vxlan tag max value is 16777216"}) if $tag > 16777216;
- raise_param_exc({ 'vlan-aware' => "vlan-aware option can't be enabled with evpn"}) if $vnet->{vlanaware};
+ raise_param_exc({ tag => "missing vxlan tag" }) if !defined($tag);
+ raise_param_exc({ tag => "vxlan tag max value is 16777216" }) if $tag > 16777216;
+ raise_param_exc({ 'vlan-aware' => "vlan-aware option can't be enabled with evpn" })
+ if $vnet->{vlanaware};
# verify that tag is not already defined globally (vxlan-id are unique)
- foreach my $id (keys %{$vnet_cfg->{ids}}) {
- next if $id eq $vnetid;
- my $othervnet = $vnet_cfg->{ids}->{$id};
- my $other_tag = $othervnet->{tag};
- my $other_zoneid = $othervnet->{zone};
- my $other_zone = $zone_cfg->{ids}->{$other_zoneid};
- next if $other_zone->{type} ne 'vxlan' && $other_zone->{type} ne 'evpn';
- raise_param_exc({ tag => "vxlan tag $tag already exist in vnet $id in zone $other_zoneid "}) if $other_tag && $tag eq $other_tag;
+ foreach my $id (keys %{ $vnet_cfg->{ids} }) {
+ next if $id eq $vnetid;
+ my $othervnet = $vnet_cfg->{ids}->{$id};
+ my $other_tag = $othervnet->{tag};
+ my $other_zoneid = $othervnet->{zone};
+ my $other_zone = $zone_cfg->{ids}->{$other_zoneid};
+ next if $other_zone->{type} ne 'vxlan' && $other_zone->{type} ne 'evpn';
+ raise_param_exc(
+ { tag => "vxlan tag $tag already exist in vnet $id in zone $other_zoneid " })
+ if $other_tag && $tag eq $other_tag;
}
}
1;
-
diff --git a/src/PVE/Network/SDN/Zones/FaucetPlugin.pm b/src/PVE/Network/SDN/Zones/FaucetPlugin.pm
index a237d17..5f069ae 100644
--- a/src/PVE/Network/SDN/Zones/FaucetPlugin.pm
+++ b/src/PVE/Network/SDN/Zones/FaucetPlugin.pm
@@ -22,14 +22,14 @@ sub properties {
sub options {
return {
- nodes => { optional => 1},
- 'dp-id' => { optional => 0 },
-# 'uplink-id' => { optional => 0 },
- 'controller' => { optional => 0 },
- dns => { optional => 1 },
- reversedns => { optional => 1 },
- dnszone => { optional => 1 },
- ipam => { optional => 1 },
+ nodes => { optional => 1 },
+ 'dp-id' => { optional => 0 },
+ # 'uplink-id' => { optional => 0 },
+ 'controller' => { optional => 0 },
+ dns => { optional => 1 },
+ reversedns => { optional => 1 },
+ dnszone => { optional => 1 },
+ ipam => { optional => 1 },
};
}
@@ -40,7 +40,7 @@ sub generate_sdn_config {
my $mtu = $vnet->{mtu};
my $uplink = $plugin_config->{'uplink-id'};
my $dpid = $plugin_config->{'dp-id'};
- my $dphex = printf("%x",$dpid); #fixme :should be 16characters hex
+ my $dphex = printf("%x", $dpid); #fixme :should be 16characters hex
my $iface = $uplinks->{$uplink}->{name};
$iface = "uplink${uplink}" if !$iface;
@@ -50,7 +50,7 @@ sub generate_sdn_config {
push @iface_config, "ovs_type OVSPort";
push @iface_config, "ovs_bridge $zoneid";
push @iface_config, "ovs_mtu $mtu" if $mtu;
- push(@{$config->{$iface}}, @iface_config) if !$config->{$iface};
+ push(@{ $config->{$iface} }, @iface_config) if !$config->{$iface};
#vnet bridge
@iface_config = ();
@@ -63,12 +63,10 @@ sub generate_sdn_config {
push @iface_config, "ovs_extra set bridge $zoneid fail_mode=secure";
push @iface_config, "ovs_extra set-controller $vnetid tcp:127.0.0.1:6653";
- push(@{$config->{$zoneid}}, @iface_config) if !$config->{$zoneid};
+ push(@{ $config->{$zoneid} }, @iface_config) if !$config->{$zoneid};
return $config;
}
-
1;
-
diff --git a/src/PVE/Network/SDN/Zones/Plugin.pm b/src/PVE/Network/SDN/Zones/Plugin.pm
index a860168..5f49357 100644
--- a/src/PVE/Network/SDN/Zones/Plugin.pm
+++ b/src/PVE/Network/SDN/Zones/Plugin.pm
@@ -17,18 +17,23 @@ PVE::Cluster::cfs_register_file(
sub { __PACKAGE__->write_config(@_); },
);
-PVE::JSONSchema::register_standard_option('pve-sdn-zone-id', {
- description => "The SDN zone object identifier.",
- type => 'string', format => 'pve-sdn-zone-id',
-});
+PVE::JSONSchema::register_standard_option(
+ 'pve-sdn-zone-id',
+ {
+ description => "The SDN zone object identifier.",
+ type => 'string',
+ format => 'pve-sdn-zone-id',
+ },
+);
PVE::JSONSchema::register_format('pve-sdn-zone-id', \&parse_sdn_zone_id);
+
sub parse_sdn_zone_id {
my ($id, $noerr) = @_;
if ($id !~ m/^[a-z][a-z0-9]*[a-z0-9]$/i) {
- return undef if $noerr;
- die "zone ID '$id' contains illegal characters\n";
+ return undef if $noerr;
+ die "zone ID '$id' contains illegal characters\n";
}
die "zone ID '$id' can't be more length than 8 characters\n" if length($id) > 8;
return $id;
@@ -37,20 +42,24 @@ sub parse_sdn_zone_id {
my $defaultData = {
propertyList => {
- type => {
- description => "Plugin type.",
- type => 'string', format => 'pve-configid',
- type => 'string',
- },
- nodes => get_standard_option('pve-node-list', { optional => 1 }),
- zone => get_standard_option('pve-sdn-zone-id', {
- completion => \&PVE::Network::SDN::Zones::complete_sdn_zone,
- }),
- ipam => {
- type => 'string',
- description => "use a specific ipam",
- optional => 1,
- },
+ type => {
+ description => "Plugin type.",
+ type => 'string',
+ format => 'pve-configid',
+ type => 'string',
+ },
+ nodes => get_standard_option('pve-node-list', { optional => 1 }),
+ zone => get_standard_option(
+ 'pve-sdn-zone-id',
+ {
+ completion => \&PVE::Network::SDN::Zones::complete_sdn_zone,
+ },
+ ),
+ ipam => {
+ type => 'string',
+ description => "use a specific ipam",
+ optional => 1,
+ },
},
};
@@ -63,11 +72,11 @@ sub parse_section_header {
if ($line =~ m/^(\S+):\s*(\S+)\s*$/) {
my ($type, $id) = (lc($1), $2);
- my $errmsg = undef; # set if you want to skip whole section
- eval { PVE::JSONSchema::pve_verify_configid($type); };
- $errmsg = $@ if $@;
- my $config = {}; # to return additional attributes
- return ($type, $id, $errmsg, $config);
+ my $errmsg = undef; # set if you want to skip whole section
+ eval { PVE::JSONSchema::pve_verify_configid($type); };
+ $errmsg = $@ if $@;
+ my $config = {}; # to return additional attributes
+ return ($type, $id, $errmsg, $config);
}
return undef;
}
@@ -76,15 +85,15 @@ sub decode_value {
my ($class, $type, $key, $value) = @_;
if ($key eq 'nodes' || $key eq 'exitnodes') {
- my $res = {};
+ my $res = {};
- foreach my $node (PVE::Tools::split_list($value)) {
- if (PVE::JSONSchema::pve_verify_node_name($node)) {
- $res->{$node} = 1;
- }
- }
+ foreach my $node (PVE::Tools::split_list($value)) {
+ if (PVE::JSONSchema::pve_verify_node_name($node)) {
+ $res->{$node} = 1;
+ }
+ }
- return $res;
+ return $res;
}
return $value;
@@ -94,14 +103,25 @@ sub encode_value {
my ($class, $type, $key, $value) = @_;
if ($key eq 'nodes' || $key eq 'exitnodes') {
- return join(',', keys(%$value));
+ return join(',', keys(%$value));
}
return $value;
}
sub generate_sdn_config {
- my ($class, $plugin_config, $zoneid, $vnetid, $vnet, $controller, $controller_cfg, $subnet_cfg, $interfaces_config, $config) = @_;
+ my (
+ $class,
+ $plugin_config,
+ $zoneid,
+ $vnetid,
+ $vnet,
+ $controller,
+ $controller_cfg,
+ $subnet_cfg,
+ $interfaces_config,
+ $config,
+ ) = @_;
die "please implement inside plugin";
}
@@ -133,10 +153,10 @@ sub on_delete_hook {
my ($class, $zoneid, $vnet_cfg) = @_;
# verify that no vnet are associated to this zone
- foreach my $id (keys %{$vnet_cfg->{ids}}) {
- my $vnet = $vnet_cfg->{ids}->{$id};
- die "zone $zoneid is used by vnet $id"
- if ($vnet->{type} eq 'vnet' && defined($vnet->{zone}) && $vnet->{zone} eq $zoneid);
+ foreach my $id (keys %{ $vnet_cfg->{ids} }) {
+ my $vnet = $vnet_cfg->{ids}->{$id};
+ die "zone $zoneid is used by vnet $id"
+ if ($vnet->{type} eq 'vnet' && defined($vnet->{zone}) && $vnet->{zone} eq $zoneid);
}
}
@@ -162,28 +182,29 @@ sub parse_tag_number_or_range {
die "extraneous commas in list\n" if $str ne join(',', @elements);
foreach my $item (@elements) {
- if ($item =~ m/^([0-9]+)-([0-9]+)$/) {
- $count += 2;
- my ($port1, $port2) = ($1, $2);
- die "invalid port '$port1'\n" if $port1 > $max;
- die "invalid port '$port2'\n" if $port2 > $max;
- die "backwards range '$port1:$port2' not allowed, did you mean '$port2:$port1'?\n" if $port1 > $port2;
-
- if ($tag && $tag >= $port1 && $tag <= $port2){
- $allowed = 1;
- last;
- }
-
- } elsif ($item =~ m/^([0-9]+)$/) {
- $count += 1;
- my $port = $1;
- die "invalid port '$port'\n" if $port > $max;
-
- if ($tag && $tag == $port){
- $allowed = 1;
- last;
- }
- }
+ if ($item =~ m/^([0-9]+)-([0-9]+)$/) {
+ $count += 2;
+ my ($port1, $port2) = ($1, $2);
+ die "invalid port '$port1'\n" if $port1 > $max;
+ die "invalid port '$port2'\n" if $port2 > $max;
+ die "backwards range '$port1:$port2' not allowed, did you mean '$port2:$port1'?\n"
+ if $port1 > $port2;
+
+ if ($tag && $tag >= $port1 && $tag <= $port2) {
+ $allowed = 1;
+ last;
+ }
+
+ } elsif ($item =~ m/^([0-9]+)$/) {
+ $count += 1;
+ my $port = $1;
+ die "invalid port '$port'\n" if $port > $max;
+
+ if ($tag && $tag == $port) {
+ $allowed = 1;
+ last;
+ }
+ }
}
die "tag $tag is not allowed" if $tag && !$allowed;
@@ -196,13 +217,13 @@ sub generate_status_message {
my $err_msg = [];
return ["vnet is not generated. Please check the 'reload network' task log."]
- if !$status->{$vnetid}->{status};
+ if !$status->{$vnetid}->{status};
foreach my $iface (@{$ifaces}) {
if (!$status->{$iface}->{status}) {
- push @$err_msg, "missing $iface";
+ push @$err_msg, "missing $iface";
} elsif ($status->{$iface}->{status} ne 'pass') {
- push @$err_msg, "error $iface";
+ push @$err_msg, "error $iface";
}
}
@@ -215,7 +236,6 @@ sub status {
return $class->generate_status_message($vnetid, $status);
}
-
sub tap_create {
my ($class, $plugin_config, $vnet, $iface, $vnetid) = @_;
@@ -231,7 +251,8 @@ sub veth_create {
sub tap_plug {
my ($class, $plugin_config, $vnet, $tag, $iface, $vnetid, $firewall, $trunks, $rate) = @_;
- my $vlan_aware = PVE::Tools::file_read_firstline("/sys/class/net/$vnetid/bridge/vlan_filtering");
+ my $vlan_aware =
+ PVE::Tools::file_read_firstline("/sys/class/net/$vnetid/bridge/vlan_filtering");
die "vm vlans are not allowed on vnet $vnetid" if !$vlan_aware && ($tag || $trunks);
my $opts = {};
@@ -243,13 +264,15 @@ sub tap_plug {
sub add_bridge_fdb {
my ($class, $plugin_config, $iface, $macaddr) = @_;
- PVE::Network::add_bridge_fdb($iface, $macaddr) if $plugin_config->{'bridge-disable-mac-learning'};
+ PVE::Network::add_bridge_fdb($iface, $macaddr)
+ if $plugin_config->{'bridge-disable-mac-learning'};
}
sub del_bridge_fdb {
my ($class, $plugin_config, $iface, $macaddr) = @_;
- PVE::Network::del_bridge_fdb($iface, $macaddr) if $plugin_config->{'bridge-disable-mac-learning'};
+ PVE::Network::del_bridge_fdb($iface, $macaddr)
+ if $plugin_config->{'bridge-disable-mac-learning'};
}
#helper
@@ -258,20 +281,20 @@ sub get_uplink_iface {
my ($interfaces_config, $uplink) = @_;
my $iface = undef;
- foreach my $id (keys %{$interfaces_config->{ifaces}}) {
+ foreach my $id (keys %{ $interfaces_config->{ifaces} }) {
my $interface = $interfaces_config->{ifaces}->{$id};
if (my $iface_uplink = $interface->{'uplink-id'}) {
- next if $iface_uplink ne $uplink;
- if($interface->{type} ne 'eth' && $interface->{type} ne 'bond') {
+ next if $iface_uplink ne $uplink;
+ if ($interface->{type} ne 'eth' && $interface->{type} ne 'bond') {
warn "uplink $uplink is not a physical or bond interface";
next;
}
- $iface = $id;
+ $iface = $id;
}
}
#create a dummy uplink interface if no uplink found
- if(!$iface) {
+ if (!$iface) {
warn "can't find uplink $uplink in physical interface";
$iface = "uplink${uplink}";
}
@@ -285,45 +308,47 @@ sub get_local_route_ip {
my $ip = undef;
my $interface = undef;
- run_command(['/sbin/ip', 'route', 'get', $targetip], outfunc => sub {
- if ($_[0] =~ m/src ($PVE::Tools::IPRE)/) {
- $ip = $1;
- }
- if ($_[0] =~ m/dev (\S+)/) {
- $interface = $1;
- }
+ run_command(
+ ['/sbin/ip', 'route', 'get', $targetip],
+ outfunc => sub {
+ if ($_[0] =~ m/src ($PVE::Tools::IPRE)/) {
+ $ip = $1;
+ }
+ if ($_[0] =~ m/dev (\S+)/) {
+ $interface = $1;
+ }
- });
+ },
+ );
return ($ip, $interface);
}
-
sub find_local_ip_interface_peers {
my ($peers, $iface) = @_;
my $network_config = PVE::INotify::read_file('interfaces');
my $ifaces = $network_config->{ifaces};
-
+
#if iface is defined, return ip if exist (if not,try to find it on other ifaces)
if ($iface) {
- my $ip = $ifaces->{$iface}->{address};
- return ($ip,$iface) if $ip;
+ my $ip = $ifaces->{$iface}->{address};
+ return ($ip, $iface) if $ip;
}
#is a local ip member of peers list ?
foreach my $address (@{$peers}) {
- while (my $interface = each %$ifaces) {
- my $ip = $ifaces->{$interface}->{address};
- if ($ip && $ip eq $address) {
- return ($ip, $interface);
- }
- }
+ while (my $interface = each %$ifaces) {
+ my $ip = $ifaces->{$interface}->{address};
+ if ($ip && $ip eq $address) {
+ return ($ip, $interface);
+ }
+ }
}
#if peer is remote, find source with ip route
foreach my $address (@{$peers}) {
- my ($ip, $interface) = get_local_route_ip($address);
- return ($ip, $interface);
+ my ($ip, $interface) = get_local_route_ip($address);
+ return ($ip, $interface);
}
}
@@ -343,7 +368,7 @@ sub is_ovs {
my ($bridge) = @_;
my $is_ovs = !-d "/sys/class/net/$bridge/brif";
- return $is_ovs;
+ return $is_ovs;
}
sub get_bridge_ifaces {
@@ -351,9 +376,13 @@ sub get_bridge_ifaces {
my @bridge_ifaces = ();
my $dir = "/sys/class/net/$bridge/brif";
- PVE::Tools::dir_glob_foreach($dir, '(((eth|bond)\d+|en[^.]+)(\.\d+)?)', sub {
- push @bridge_ifaces, $_[0];
- });
+ PVE::Tools::dir_glob_foreach(
+ $dir,
+ '(((eth|bond)\d+|en[^.]+)(\.\d+)?)',
+ sub {
+ push @bridge_ifaces, $_[0];
+ },
+ );
return @bridge_ifaces;
}
@@ -362,7 +391,6 @@ sub datacenter_config {
return PVE::Cluster::cfs_read_file('datacenter.cfg');
}
-
sub get_mtu {
my ($class, $plugin_config) = @_;
diff --git a/src/PVE/Network/SDN/Zones/QinQPlugin.pm b/src/PVE/Network/SDN/Zones/QinQPlugin.pm
index 4c4be64..606c9f9 100644
--- a/src/PVE/Network/SDN/Zones/QinQPlugin.pm
+++ b/src/PVE/Network/SDN/Zones/QinQPlugin.pm
@@ -15,45 +15,56 @@ sub type {
sub properties {
return {
- tag => {
- type => 'integer',
- minimum => 0,
- description => "Service-VLAN Tag",
- },
- mtu => {
- type => 'integer',
- description => "MTU",
- optional => 1,
- },
- 'vlan-protocol' => {
- type => 'string',
- enum => ['802.1q', '802.1ad'],
- default => '802.1q',
- optional => 1,
- }
+ tag => {
+ type => 'integer',
+ minimum => 0,
+ description => "Service-VLAN Tag",
+ },
+ mtu => {
+ type => 'integer',
+ description => "MTU",
+ optional => 1,
+ },
+ 'vlan-protocol' => {
+ type => 'string',
+ enum => ['802.1q', '802.1ad'],
+ default => '802.1q',
+ optional => 1,
+ },
};
}
sub options {
return {
- nodes => { optional => 1},
- 'tag' => { optional => 0 },
- 'bridge' => { optional => 0 },
+ nodes => { optional => 1 },
+ 'tag' => { optional => 0 },
+ 'bridge' => { optional => 0 },
'bridge-disable-mac-learning' => { optional => 1 },
- 'mtu' => { optional => 1 },
- 'vlan-protocol' => { optional => 1 },
- dns => { optional => 1 },
- reversedns => { optional => 1 },
- dnszone => { optional => 1 },
- ipam => { optional => 1 },
+ 'mtu' => { optional => 1 },
+ 'vlan-protocol' => { optional => 1 },
+ dns => { optional => 1 },
+ reversedns => { optional => 1 },
+ dnszone => { optional => 1 },
+ ipam => { optional => 1 },
};
}
# Plugin implementation
sub generate_sdn_config {
- my ($class, $plugin_config, $zoneid, $vnetid, $vnet, $controller, $controller_cfg, $subnet_cfg, $interfaces_config, $config) = @_;
-
- my ($bridge, $mtu, $stag) = $plugin_config->@{'bridge', 'mtu', 'tag'};
+ my (
+ $class,
+ $plugin_config,
+ $zoneid,
+ $vnetid,
+ $vnet,
+ $controller,
+ $controller_cfg,
+ $subnet_cfg,
+ $interfaces_config,
+ $config,
+ ) = @_;
+
+ my ($bridge, $mtu, $stag) = $plugin_config->@{ 'bridge', 'mtu', 'tag' };
my $vlanprotocol = $plugin_config->{'vlan-protocol'};
PVE::Network::SDN::Zones::Plugin::find_bridge($bridge);
@@ -68,79 +79,82 @@ sub generate_sdn_config {
my $vnet_bridge_ports = "";
if (my $ctag = $vnet->{tag}) {
- $vnet_bridge_ports = "$zone.$ctag";
+ $vnet_bridge_ports = "$zone.$ctag";
} else {
- $vnet_bridge_ports = $zone_notag_uplinkpeer;
+ $vnet_bridge_ports = $zone_notag_uplinkpeer;
}
my $zone_bridge_ports = "";
if ($is_ovs) {
# ovs--->ovsintport(dot1q-tunnel tag)------->vlanawarebrige-----(tag)--->vnet
- $vlanprotocol = "802.1q" if !$vlanprotocol;
- my $svlan_iface = "sv_".$zoneid;
+ $vlanprotocol = "802.1q" if !$vlanprotocol;
+ my $svlan_iface = "sv_" . $zoneid;
- # ovs dot1q-tunnel port
- @iface_config = ();
- push @iface_config, "ovs_type OVSIntPort";
- push @iface_config, "ovs_bridge $bridge";
- push @iface_config, "ovs_mtu $mtu" if $mtu;
- push @iface_config, "ovs_options vlan_mode=dot1q-tunnel tag=$stag other_config:qinq-ethtype=$vlanprotocol";
- push(@{$config->{$svlan_iface}}, @iface_config) if !$config->{$svlan_iface};
+ # ovs dot1q-tunnel port
+ @iface_config = ();
+ push @iface_config, "ovs_type OVSIntPort";
+ push @iface_config, "ovs_bridge $bridge";
+ push @iface_config, "ovs_mtu $mtu" if $mtu;
+ push @iface_config,
+ "ovs_options vlan_mode=dot1q-tunnel tag=$stag other_config:qinq-ethtype=$vlanprotocol";
+ push(@{ $config->{$svlan_iface} }, @iface_config) if !$config->{$svlan_iface};
# redefine main ovs bridge, ifupdown2 will merge ovs_ports
- @{$config->{$bridge}}[0] = "ovs_ports" if !@{$config->{$bridge}}[0];
- my @ovs_ports = split / / , @{$config->{$bridge}}[0];
- @{$config->{$bridge}}[0] .= " $svlan_iface" if !grep( $_ eq $svlan_iface, @ovs_ports );
+ @{ $config->{$bridge} }[0] = "ovs_ports" if !@{ $config->{$bridge} }[0];
+ my @ovs_ports = split / /, @{ $config->{$bridge} }[0];
+ @{ $config->{$bridge} }[0] .= " $svlan_iface" if !grep($_ eq $svlan_iface, @ovs_ports);
- $zone_bridge_ports = $svlan_iface;
+ $zone_bridge_ports = $svlan_iface;
} elsif ($vlan_aware) {
# VLAN_aware_brige-(tag)----->vlanwarebridge-(tag)----->vnet
- $zone_bridge_ports = "$bridge.$stag";
+ $zone_bridge_ports = "$bridge.$stag";
- if ($vlanprotocol) {
- @iface_config = ();
- push @iface_config, "bridge-vlan-protocol $vlanprotocol";
- push(@{$config->{$bridge}}, @iface_config) if !$config->{$bridge};
+ if ($vlanprotocol) {
+ @iface_config = ();
+ push @iface_config, "bridge-vlan-protocol $vlanprotocol";
+ push(@{ $config->{$bridge} }, @iface_config) if !$config->{$bridge};
- @iface_config = ();
- push @iface_config, "vlan-protocol $vlanprotocol";
- push(@{$config->{$zone_bridge_ports}}, @iface_config) if !$config->{$zone_bridge_ports};
- }
+ @iface_config = ();
+ push @iface_config, "vlan-protocol $vlanprotocol";
+ push(@{ $config->{$zone_bridge_ports} }, @iface_config)
+ if !$config->{$zone_bridge_ports};
+ }
} else {
- # eth--->eth.x(svlan)----->vlanwarebridge-(tag)----->vnet---->vnet
+ # eth--->eth.x(svlan)----->vlanwarebridge-(tag)----->vnet---->vnet
- my @bridge_ifaces = PVE::Network::SDN::Zones::Plugin::get_bridge_ifaces($bridge);
+ my @bridge_ifaces = PVE::Network::SDN::Zones::Plugin::get_bridge_ifaces($bridge);
- for my $bridge_iface (@bridge_ifaces) {
- # use named vlan interface to avoid too long names
- my $svlan_iface = "sv_$zoneid";
+ for my $bridge_iface (@bridge_ifaces) {
+ # use named vlan interface to avoid too long names
+ my $svlan_iface = "sv_$zoneid";
- # svlan
- @iface_config = ();
- push @iface_config, "vlan-raw-device $bridge_iface";
- push @iface_config, "vlan-id $stag";
- push @iface_config, "vlan-protocol $vlanprotocol" if $vlanprotocol;
- push(@{$config->{$svlan_iface}}, @iface_config) if !$config->{$svlan_iface};
+ # svlan
+ @iface_config = ();
+ push @iface_config, "vlan-raw-device $bridge_iface";
+ push @iface_config, "vlan-id $stag";
+ push @iface_config, "vlan-protocol $vlanprotocol" if $vlanprotocol;
+ push(@{ $config->{$svlan_iface} }, @iface_config) if !$config->{$svlan_iface};
- $zone_bridge_ports = $svlan_iface;
- last;
+ $zone_bridge_ports = $svlan_iface;
+ last;
}
- }
+ }
# veth peer for notag vnet
@iface_config = ();
push @iface_config, "link-type veth";
push @iface_config, "veth-peer-name $zone_notag_uplinkpeer";
- push(@{$config->{$zone_notag_uplink}}, @iface_config) if !$config->{$zone_notag_uplink};
+ push(@{ $config->{$zone_notag_uplink} }, @iface_config) if !$config->{$zone_notag_uplink};
@iface_config = ();
push @iface_config, "link-type veth";
push @iface_config, "veth-peer-name $zone_notag_uplink";
- push(@{$config->{$zone_notag_uplinkpeer}}, @iface_config) if !$config->{$zone_notag_uplinkpeer};
+ push(@{ $config->{$zone_notag_uplinkpeer} }, @iface_config)
+ if !$config->{$zone_notag_uplinkpeer};
# zone vlan aware bridge
@iface_config = ();
@@ -150,20 +164,20 @@ sub generate_sdn_config {
push @iface_config, "bridge-fd 0";
push @iface_config, "bridge-vlan-aware yes";
push @iface_config, "bridge-vids 2-4094";
- push(@{$config->{$zone}}, @iface_config) if !$config->{$zone};
+ push(@{ $config->{$zone} }, @iface_config) if !$config->{$zone};
# vnet bridge
@iface_config = ();
push @iface_config, "bridge_ports $vnet_bridge_ports";
push @iface_config, "bridge_stp off";
push @iface_config, "bridge_fd 0";
- if($vnet->{vlanaware}) {
- push @iface_config, "bridge-vlan-aware yes";
- push @iface_config, "bridge-vids 2-4094";
+ if ($vnet->{vlanaware}) {
+ push @iface_config, "bridge-vlan-aware yes";
+ push @iface_config, "bridge-vids 2-4094";
}
push @iface_config, "mtu $mtu" if $mtu;
push @iface_config, "alias $vnet->{alias}" if $vnet->{alias};
- push(@{$config->{$vnetid}}, @iface_config) if !$config->{$vnetid};
+ push(@{ $config->{$vnetid} }, @iface_config) if !$config->{$vnetid};
}
sub status {
@@ -172,28 +186,28 @@ sub status {
my $bridge = $plugin_config->{bridge};
if (!-d "/sys/class/net/$bridge") {
- return ["missing $bridge"];
+ return ["missing $bridge"];
}
my $vlan_aware = PVE::Network::SDN::Zones::Plugin::is_vlanaware($bridge);
my $tag = $vnet->{tag};
- my $vnet_uplink = "ln_".$vnetid;
- my $vnet_uplinkpeer = "pr_".$vnetid;
- my $zone_notag_uplink = "ln_".$zone;
- my $zone_notag_uplinkpeer = "pr_".$zone;
+ my $vnet_uplink = "ln_" . $vnetid;
+ my $vnet_uplinkpeer = "pr_" . $vnetid;
+ my $zone_notag_uplink = "ln_" . $zone;
+ my $zone_notag_uplinkpeer = "pr_" . $zone;
my $zonebridge = "z_$zone";
# ifaces to check
- my $ifaces = [ $vnetid, $bridge ];
+ my $ifaces = [$vnetid, $bridge];
push @$ifaces, $zonebridge;
push @$ifaces, $zone_notag_uplink;
push @$ifaces, $zone_notag_uplinkpeer;
if (!$vlan_aware) {
- my $svlan_iface = "sv_$zone";
- push @$ifaces, $svlan_iface;
+ my $svlan_iface = "sv_$zone";
+ push @$ifaces, $svlan_iface;
}
return $class->generate_status_message($vnetid, $status, $ifaces);
@@ -208,21 +222,21 @@ sub vnet_update_hook {
raise_param_exc({ tag => "VLAN tag maximal value is 4096" }) if $tag && $tag > 4096;
# verify that tag is not already defined in another vnet on same zone
- for my $id (sort keys %{$vnet_cfg->{ids}}) {
- next if $id eq $vnetid;
- my $other_vnet = $vnet_cfg->{ids}->{$id};
- next if $vnet->{zone} ne $other_vnet->{zone};
- my $other_tag = $other_vnet->{tag};
- if ($tag) {
- raise_param_exc({ tag => "tag $tag already exist in zone $vnet->{zone} vnet $id"})
- if $other_tag && $tag eq $other_tag;
- } else {
- raise_param_exc({ tag => "tag-less vnet already exists in zone $vnet->{zone} vnet $id"})
- if !$other_tag;
- }
+ for my $id (sort keys %{ $vnet_cfg->{ids} }) {
+ next if $id eq $vnetid;
+ my $other_vnet = $vnet_cfg->{ids}->{$id};
+ next if $vnet->{zone} ne $other_vnet->{zone};
+ my $other_tag = $other_vnet->{tag};
+ if ($tag) {
+ raise_param_exc({ tag => "tag $tag already exist in zone $vnet->{zone} vnet $id" })
+ if $other_tag && $tag eq $other_tag;
+ } else {
+ raise_param_exc(
+ { tag => "tag-less vnet already exists in zone $vnet->{zone} vnet $id" })
+ if !$other_tag;
+ }
}
}
1;
-
diff --git a/src/PVE/Network/SDN/Zones/SimplePlugin.pm b/src/PVE/Network/SDN/Zones/SimplePlugin.pm
index 1416d39..97cf29e 100644
--- a/src/PVE/Network/SDN/Zones/SimplePlugin.pm
+++ b/src/PVE/Network/SDN/Zones/SimplePlugin.pm
@@ -16,43 +16,55 @@ sub type {
sub properties {
return {
- dns => {
- type => 'string',
- description => "dns api server",
- },
- reversedns => {
- type => 'string',
- description => "reverse dns api server",
- },
- dnszone => {
- type => 'string', format => 'dns-name',
- description => "dns domain zone ex: mydomain.com",
- },
- dhcp => {
- description => 'Type of the DHCP backend for this zone',
- type => 'string',
- enum => PVE::Network::SDN::Dhcp::Plugin->lookup_types(),
- },
+ dns => {
+ type => 'string',
+ description => "dns api server",
+ },
+ reversedns => {
+ type => 'string',
+ description => "reverse dns api server",
+ },
+ dnszone => {
+ type => 'string',
+ format => 'dns-name',
+ description => "dns domain zone ex: mydomain.com",
+ },
+ dhcp => {
+ description => 'Type of the DHCP backend for this zone',
+ type => 'string',
+ enum => PVE::Network::SDN::Dhcp::Plugin->lookup_types(),
+ },
};
}
sub options {
return {
- nodes => { optional => 1},
- mtu => { optional => 1 },
- dns => { optional => 1 },
- reversedns => { optional => 1 },
- dnszone => { optional => 1 },
- ipam => { optional => 1 },
- dhcp => { optional => 1 },
+ nodes => { optional => 1 },
+ mtu => { optional => 1 },
+ dns => { optional => 1 },
+ reversedns => { optional => 1 },
+ dnszone => { optional => 1 },
+ ipam => { optional => 1 },
+ dhcp => { optional => 1 },
};
}
# Plugin implementation
sub generate_sdn_config {
- my ($class, $plugin_config, $zoneid, $vnetid, $vnet, $controller, $controller_cfg, $subnet_cfg, $interfaces_config, $config) = @_;
-
- return $config if$config->{$vnetid}; # nothing to do
+ my (
+ $class,
+ $plugin_config,
+ $zoneid,
+ $vnetid,
+ $vnet,
+ $controller,
+ $controller_cfg,
+ $subnet_cfg,
+ $interfaces_config,
+ $config,
+ ) = @_;
+
+ return $config if $config->{$vnetid}; # nothing to do
my $mac = $vnet->{mac};
my $alias = $vnet->{alias};
@@ -70,46 +82,51 @@ sub generate_sdn_config {
my $enable_forward_v6 = undef;
foreach my $subnetid (sort keys %{$subnets}) {
- my $subnet = $subnets->{$subnetid};
- my $cidr = $subnet->{cidr};
- my $mask = $subnet->{mask};
-
- my $gateway = $subnet->{gateway};
- if ($gateway) {
- push @iface_config, "address $gateway/$mask" if !defined($address->{$gateway});
- $address->{$gateway} = 1;
- }
-
- my $iptables = undef;
- my $checkrouteip = undef;
- my $ipversion = Net::IP::ip_is_ipv6($gateway) ? 6 : 4;
-
- if ( $ipversion == 6) {
- $ipv6 = 1;
- $iptables = "ip6tables";
- $checkrouteip = '2001:4860:4860::8888';
- $enable_forward_v6 = 1 if $gateway;
- } else {
- $ipv4 = 1;
- $iptables = "iptables";
- $checkrouteip = '8.8.8.8';
- $enable_forward_v4 = 1 if $gateway;
- }
-
- #add route for /32 pointtopoint
- push @iface_config, "up ip route add $cidr dev $vnetid" if $mask == 32 && $ipversion == 4;
- if ($subnet->{snat}) {
- #find outgoing interface
- my ($outip, $outiface) = PVE::Network::SDN::Zones::Plugin::get_local_route_ip($checkrouteip);
- if ($outip && $outiface) {
- #use snat, faster than masquerade
- push @iface_config, "post-up $iptables -t nat -A POSTROUTING -s '$cidr' -o $outiface -j SNAT --to-source $outip";
- push @iface_config, "post-down $iptables -t nat -D POSTROUTING -s '$cidr' -o $outiface -j SNAT --to-source $outip";
- #add conntrack zone once on outgoing interface
- push @iface_config, "post-up $iptables -t raw -I PREROUTING -i fwbr+ -j CT --zone 1";
- push @iface_config, "post-down $iptables -t raw -D PREROUTING -i fwbr+ -j CT --zone 1";
- }
- }
+ my $subnet = $subnets->{$subnetid};
+ my $cidr = $subnet->{cidr};
+ my $mask = $subnet->{mask};
+
+ my $gateway = $subnet->{gateway};
+ if ($gateway) {
+ push @iface_config, "address $gateway/$mask" if !defined($address->{$gateway});
+ $address->{$gateway} = 1;
+ }
+
+ my $iptables = undef;
+ my $checkrouteip = undef;
+ my $ipversion = Net::IP::ip_is_ipv6($gateway) ? 6 : 4;
+
+ if ($ipversion == 6) {
+ $ipv6 = 1;
+ $iptables = "ip6tables";
+ $checkrouteip = '2001:4860:4860::8888';
+ $enable_forward_v6 = 1 if $gateway;
+ } else {
+ $ipv4 = 1;
+ $iptables = "iptables";
+ $checkrouteip = '8.8.8.8';
+ $enable_forward_v4 = 1 if $gateway;
+ }
+
+ #add route for /32 pointtopoint
+ push @iface_config, "up ip route add $cidr dev $vnetid" if $mask == 32 && $ipversion == 4;
+ if ($subnet->{snat}) {
+ #find outgoing interface
+ my ($outip, $outiface) =
+ PVE::Network::SDN::Zones::Plugin::get_local_route_ip($checkrouteip);
+ if ($outip && $outiface) {
+ #use snat, faster than masquerade
+ push @iface_config,
+ "post-up $iptables -t nat -A POSTROUTING -s '$cidr' -o $outiface -j SNAT --to-source $outip";
+ push @iface_config,
+ "post-down $iptables -t nat -D POSTROUTING -s '$cidr' -o $outiface -j SNAT --to-source $outip";
+ #add conntrack zone once on outgoing interface
+ push @iface_config,
+ "post-up $iptables -t raw -I PREROUTING -i fwbr+ -j CT --zone 1";
+ push @iface_config,
+ "post-down $iptables -t raw -D PREROUTING -i fwbr+ -j CT --zone 1";
+ }
+ }
}
push @iface_config, "hwaddress $mac" if $mac;
@@ -125,7 +142,7 @@ sub generate_sdn_config {
push @iface_config, "ip-forward on" if $enable_forward_v4;
push @iface_config, "ip6-forward on" if $enable_forward_v6;
- push @{$config->{$vnetid}}, @iface_config;
+ push @{ $config->{$vnetid} }, @iface_config;
return $config;
}
@@ -136,7 +153,7 @@ sub vnet_update_hook {
my $vnet = $vnet_cfg->{ids}->{$vnetid};
my $tag = $vnet->{tag};
- raise_param_exc({ tag => "vlan tag is not allowed on simple zone"}) if defined($tag);
+ raise_param_exc({ tag => "vlan tag is not allowed on simple zone" }) if defined($tag);
if (!defined($vnet->{mac})) {
my $dc = PVE::Network::SDN::Zones::Plugin::datacenter_config();
@@ -152,4 +169,3 @@ sub get_mtu {
1;
-
diff --git a/src/PVE/Network/SDN/Zones/VlanPlugin.pm b/src/PVE/Network/SDN/Zones/VlanPlugin.pm
index 13fb49e..155042e 100644
--- a/src/PVE/Network/SDN/Zones/VlanPlugin.pm
+++ b/src/PVE/Network/SDN/Zones/VlanPlugin.pm
@@ -12,43 +12,55 @@ sub type {
}
PVE::JSONSchema::register_format('pve-sdn-vlanrange', \&pve_verify_sdn_vlanrange);
+
sub pve_verify_sdn_vlanrange {
- my ($vlanstr) = @_;
+ my ($vlanstr) = @_;
- PVE::Network::SDN::Zones::Plugin::parse_tag_number_or_range($vlanstr, '4096');
+ PVE::Network::SDN::Zones::Plugin::parse_tag_number_or_range($vlanstr, '4096');
- return $vlanstr;
+ return $vlanstr;
}
sub properties {
return {
- 'bridge' => {
- type => 'string',
- },
- 'bridge-disable-mac-learning' => {
- type => 'boolean',
+ 'bridge' => {
+ type => 'string',
+ },
+ 'bridge-disable-mac-learning' => {
+ type => 'boolean',
description => "Disable auto mac learning.",
- }
+ },
};
}
sub options {
return {
- nodes => { optional => 1},
- 'bridge' => { optional => 0 },
- 'bridge-disable-mac-learning' => { optional => 1 },
- mtu => { optional => 1 },
- dns => { optional => 1 },
- reversedns => { optional => 1 },
- dnszone => { optional => 1 },
- ipam => { optional => 1 },
+ nodes => { optional => 1 },
+ 'bridge' => { optional => 0 },
+ 'bridge-disable-mac-learning' => { optional => 1 },
+ mtu => { optional => 1 },
+ dns => { optional => 1 },
+ reversedns => { optional => 1 },
+ dnszone => { optional => 1 },
+ ipam => { optional => 1 },
};
}
# Plugin implementation
sub generate_sdn_config {
- my ($class, $plugin_config, $zoneid, $vnetid, $vnet, $controller, $controller_cfg, $subnet_cfg, $interfaces_config, $config) = @_;
+ my (
+ $class,
+ $plugin_config,
+ $zoneid,
+ $vnetid,
+ $vnet,
+ $controller,
+ $controller_cfg,
+ $subnet_cfg,
+ $interfaces_config,
+ $config,
+ ) = @_;
my $bridge = $plugin_config->{bridge};
PVE::Network::SDN::Zones::Plugin::find_bridge($bridge);
@@ -60,67 +72,68 @@ sub generate_sdn_config {
my $alias = $vnet->{alias};
my $mtu = $plugin_config->{mtu};
- my $vnet_uplink = "ln_".$vnetid;
- my $vnet_uplinkpeer = "pr_".$vnetid;
+ my $vnet_uplink = "ln_" . $vnetid;
+ my $vnet_uplinkpeer = "pr_" . $vnetid;
my @iface_config = ();
- if($is_ovs) {
+ if ($is_ovs) {
# keep vmbrXvY for compatibility with existing network
# eth0----ovs vmbr0--(ovsintport tag)---->vnet---->vm
- @iface_config = ();
- push @iface_config, "ovs_type OVSIntPort";
- push @iface_config, "ovs_bridge $bridge";
- push @iface_config, "ovs_mtu $mtu" if $mtu;
- if($vnet->{vlanaware}) {
- push @iface_config, "ovs_options vlan_mode=dot1q-tunnel other_config:qinq-ethtype=802.1q tag=$tag";
- } else {
- push @iface_config, "ovs_options tag=$tag";
- }
- push(@{$config->{$vnet_uplink}}, @iface_config) if !$config->{$vnet_uplink};
-
- #redefine main ovs bridge, ifupdown2 will merge ovs_ports
- @iface_config = ();
- push @iface_config, "ovs_ports $vnet_uplink";
- push(@{$config->{$bridge}}, @iface_config);
+ @iface_config = ();
+ push @iface_config, "ovs_type OVSIntPort";
+ push @iface_config, "ovs_bridge $bridge";
+ push @iface_config, "ovs_mtu $mtu" if $mtu;
+ if ($vnet->{vlanaware}) {
+ push @iface_config,
+ "ovs_options vlan_mode=dot1q-tunnel other_config:qinq-ethtype=802.1q tag=$tag";
+ } else {
+ push @iface_config, "ovs_options tag=$tag";
+ }
+ push(@{ $config->{$vnet_uplink} }, @iface_config) if !$config->{$vnet_uplink};
+
+ #redefine main ovs bridge, ifupdown2 will merge ovs_ports
+ @iface_config = ();
+ push @iface_config, "ovs_ports $vnet_uplink";
+ push(@{ $config->{$bridge} }, @iface_config);
} elsif ($vlan_aware) {
# eth0----vlanaware bridge vmbr0--(vmbr0.X tag)---->vnet---->vm
- $vnet_uplink = "$bridge.$tag";
+ $vnet_uplink = "$bridge.$tag";
} else {
# keep vmbrXvY for compatibility with existing network
# eth0<---->eth0.X----vmbr0v10------vnet---->vm
- my $bridgevlan = $bridge."v".$tag;
-
- my @bridge_ifaces = PVE::Network::SDN::Zones::Plugin::get_bridge_ifaces($bridge);
-
- my $bridge_ports = "";
- foreach my $bridge_iface (@bridge_ifaces) {
- $bridge_ports .= " $bridge_iface.$tag";
- }
-
- @iface_config = ();
- push @iface_config, "link-type veth";
- push @iface_config, "veth-peer-name $vnet_uplinkpeer";
- push @iface_config, "mtu $mtu" if $mtu;
- push(@{$config->{$vnet_uplink}}, @iface_config) if !$config->{$vnet_uplink};
-
- @iface_config = ();
- push @iface_config, "link-type veth";
- push @iface_config, "veth-peer-name $vnet_uplink";
- push @iface_config, "mtu $mtu" if $mtu;
- push(@{$config->{$vnet_uplinkpeer}}, @iface_config) if !$config->{$vnet_uplinkpeer};
-
- @iface_config = ();
- push @iface_config, "bridge_ports $bridge_ports $vnet_uplinkpeer";
- push @iface_config, "bridge_stp off";
- push @iface_config, "bridge_fd 0";
- push @iface_config, "mtu $mtu" if $mtu;
- push(@{$config->{$bridgevlan}}, @iface_config) if !$config->{$bridgevlan};
+ my $bridgevlan = $bridge . "v" . $tag;
+
+ my @bridge_ifaces = PVE::Network::SDN::Zones::Plugin::get_bridge_ifaces($bridge);
+
+ my $bridge_ports = "";
+ foreach my $bridge_iface (@bridge_ifaces) {
+ $bridge_ports .= " $bridge_iface.$tag";
+ }
+
+ @iface_config = ();
+ push @iface_config, "link-type veth";
+ push @iface_config, "veth-peer-name $vnet_uplinkpeer";
+ push @iface_config, "mtu $mtu" if $mtu;
+ push(@{ $config->{$vnet_uplink} }, @iface_config) if !$config->{$vnet_uplink};
+
+ @iface_config = ();
+ push @iface_config, "link-type veth";
+ push @iface_config, "veth-peer-name $vnet_uplink";
+ push @iface_config, "mtu $mtu" if $mtu;
+ push(@{ $config->{$vnet_uplinkpeer} }, @iface_config) if !$config->{$vnet_uplinkpeer};
+
+ @iface_config = ();
+ push @iface_config, "bridge_ports $bridge_ports $vnet_uplinkpeer";
+ push @iface_config, "bridge_stp off";
+ push @iface_config, "bridge_fd 0";
+ push @iface_config, "mtu $mtu" if $mtu;
+ push(@{ $config->{$bridgevlan} }, @iface_config) if !$config->{$bridgevlan};
}
#vnet bridge
@@ -128,13 +141,13 @@ sub generate_sdn_config {
push @iface_config, "bridge_ports $vnet_uplink";
push @iface_config, "bridge_stp off";
push @iface_config, "bridge_fd 0";
- if($vnet->{vlanaware}) {
+ if ($vnet->{vlanaware}) {
push @iface_config, "bridge-vlan-aware yes";
push @iface_config, "bridge-vids 2-4094";
}
push @iface_config, "mtu $mtu" if $mtu;
push @iface_config, "alias $alias" if $alias;
- push(@{$config->{$vnetid}}, @iface_config) if !$config->{$vnetid};
+ push(@{ $config->{$vnetid} }, @iface_config) if !$config->{$vnetid};
return $config;
}
@@ -145,25 +158,25 @@ sub status {
my $bridge = $plugin_config->{bridge};
if (!-d "/sys/class/net/$bridge") {
- return ["missing $bridge"];
+ return ["missing $bridge"];
}
my $vlan_aware = PVE::Network::SDN::Zones::Plugin::is_vlanaware($bridge);
my $is_ovs = PVE::Network::SDN::Zones::Plugin::is_ovs($bridge);
my $tag = $vnet->{tag};
- my $vnet_uplink = "ln_".$vnetid;
- my $vnet_uplinkpeer = "pr_".$vnetid;
+ my $vnet_uplink = "ln_" . $vnetid;
+ my $vnet_uplinkpeer = "pr_" . $vnetid;
# ifaces to check
- my $ifaces = [ $vnetid, $bridge ];
- if($is_ovs) {
- push @$ifaces, $vnet_uplink;
+ my $ifaces = [$vnetid, $bridge];
+ if ($is_ovs) {
+ push @$ifaces, $vnet_uplink;
} elsif (!$vlan_aware) {
- my $bridgevlan = $bridge."v".$tag;
- push @$ifaces, $bridgevlan;
- push @$ifaces, $vnet_uplink;
- push @$ifaces, $vnet_uplinkpeer;
+ my $bridgevlan = $bridge . "v" . $tag;
+ push @$ifaces, $bridgevlan;
+ push @$ifaces, $vnet_uplink;
+ push @$ifaces, $vnet_uplinkpeer;
}
return $class->generate_status_message($vnetid, $status, $ifaces);
@@ -175,19 +188,19 @@ sub vnet_update_hook {
my $vnet = $vnet_cfg->{ids}->{$vnetid};
my $tag = $vnet->{tag};
- raise_param_exc({ tag => "missing vlan tag"}) if !defined($vnet->{tag});
- raise_param_exc({ tag => "vlan tag max value is 4096"}) if $vnet->{tag} > 4096;
+ raise_param_exc({ tag => "missing vlan tag" }) if !defined($vnet->{tag});
+ raise_param_exc({ tag => "vlan tag max value is 4096" }) if $vnet->{tag} > 4096;
# verify that tag is not already defined in another vnet on same zone
- foreach my $id (keys %{$vnet_cfg->{ids}}) {
- next if $id eq $vnetid;
- my $othervnet = $vnet_cfg->{ids}->{$id};
- my $other_tag = $othervnet->{tag};
- next if $vnet->{zone} ne $othervnet->{zone};
- raise_param_exc({ tag => "tag $tag already exist in vnet $id"}) if $other_tag && $tag eq $other_tag;
+ foreach my $id (keys %{ $vnet_cfg->{ids} }) {
+ next if $id eq $vnetid;
+ my $othervnet = $vnet_cfg->{ids}->{$id};
+ my $other_tag = $othervnet->{tag};
+ next if $vnet->{zone} ne $othervnet->{zone};
+ raise_param_exc({ tag => "tag $tag already exist in vnet $id" })
+ if $other_tag && $tag eq $other_tag;
}
}
1;
-
diff --git a/src/PVE/Network/SDN/Zones/VxlanPlugin.pm b/src/PVE/Network/SDN/Zones/VxlanPlugin.pm
index 9a77bb9..018d412 100644
--- a/src/PVE/Network/SDN/Zones/VxlanPlugin.pm
+++ b/src/PVE/Network/SDN/Zones/VxlanPlugin.pm
@@ -11,12 +11,13 @@ use PVE::Exception qw(raise raise_param_exc);
use base('PVE::Network::SDN::Zones::Plugin');
PVE::JSONSchema::register_format('pve-sdn-vxlanrange', \&pve_verify_sdn_vxlanrange);
+
sub pve_verify_sdn_vxlanrange {
- my ($vxlanstr) = @_;
+ my ($vxlanstr) = @_;
- PVE::Network::SDN::Zones::Plugin::parse_tag_number_or_range($vxlanstr, '16777216');
+ PVE::Network::SDN::Zones::Plugin::parse_tag_number_or_range($vxlanstr, '16777216');
- return $vxlanstr;
+ return $vxlanstr;
}
sub type {
@@ -27,33 +28,45 @@ sub properties {
return {
'peers' => {
description => "peers address list.",
- type => 'string', format => 'ip-list'
+ type => 'string',
+ format => 'ip-list',
},
'vxlan-port' => {
description => "Vxlan tunnel udp port (default 4789).",
minimum => 1,
maximum => 65536,
- type => 'integer'
+ type => 'integer',
},
};
}
sub options {
return {
- nodes => { optional => 1},
- peers => { optional => 0 },
- 'vxlan-port' => { optional => 1 },
- mtu => { optional => 1 },
- dns => { optional => 1 },
- reversedns => { optional => 1 },
- dnszone => { optional => 1 },
- ipam => { optional => 1 },
+ nodes => { optional => 1 },
+ peers => { optional => 0 },
+ 'vxlan-port' => { optional => 1 },
+ mtu => { optional => 1 },
+ dns => { optional => 1 },
+ reversedns => { optional => 1 },
+ dnszone => { optional => 1 },
+ ipam => { optional => 1 },
};
}
# Plugin implementation
sub generate_sdn_config {
- my ($class, $plugin_config, $zoneid, $vnetid, $vnet, $controller, $controller_cfg, $subnet_cfg, $interfaces_config, $config) = @_;
+ my (
+ $class,
+ $plugin_config,
+ $zoneid,
+ $vnetid,
+ $vnet,
+ $controller,
+ $controller_cfg,
+ $subnet_cfg,
+ $interfaces_config,
+ $config,
+ ) = @_;
my $tag = $vnet->{tag};
my $alias = $vnet->{alias};
@@ -65,7 +78,8 @@ sub generate_sdn_config {
die "missing vxlan tag" if !$tag;
- my ($ifaceip, $iface) = PVE::Network::SDN::Zones::Plugin::find_local_ip_interface_peers(\@peers);
+ my ($ifaceip, $iface) =
+ PVE::Network::SDN::Zones::Plugin::find_local_ip_interface_peers(\@peers);
my $mtu = 1450;
$mtu = $interfaces_config->{$iface}->{mtu} - 50 if $interfaces_config->{$iface}->{mtu};
@@ -76,14 +90,13 @@ sub generate_sdn_config {
push @iface_config, "vxlan-id $tag";
for my $address (@peers) {
- next if $address eq $ifaceip;
- push @iface_config, "vxlan_remoteip $address";
+ next if $address eq $ifaceip;
+ push @iface_config, "vxlan_remoteip $address";
}
push @iface_config, "vxlan-port $vxlanport" if $vxlanport;
-
push @iface_config, "mtu $mtu" if $mtu;
- push(@{$config->{$vxlan_iface}}, @iface_config) if !$config->{$vxlan_iface};
+ push(@{ $config->{$vxlan_iface} }, @iface_config) if !$config->{$vxlan_iface};
#vnet bridge
@iface_config = ();
@@ -91,12 +104,12 @@ sub generate_sdn_config {
push @iface_config, "bridge_stp off";
push @iface_config, "bridge_fd 0";
if ($vnet->{vlanaware}) {
- push @iface_config, "bridge-vlan-aware yes";
- push @iface_config, "bridge-vids 2-4094";
+ push @iface_config, "bridge-vlan-aware yes";
+ push @iface_config, "bridge-vids 2-4094";
}
push @iface_config, "mtu $mtu" if $mtu;
push @iface_config, "alias $alias" if $alias;
- push(@{$config->{$vnetid}}, @iface_config) if !$config->{$vnetid};
+ push(@{ $config->{$vnetid} }, @iface_config) if !$config->{$vnetid};
return $config;
}
@@ -107,21 +120,22 @@ sub vnet_update_hook {
my $vnet = $vnet_cfg->{ids}->{$vnetid};
my $tag = $vnet->{tag};
- raise_param_exc({ tag => "missing vxlan tag"}) if !defined($tag);
- raise_param_exc({ tag => "vxlan tag max value is 16777216"}) if $tag > 16777216;
+ raise_param_exc({ tag => "missing vxlan tag" }) if !defined($tag);
+ raise_param_exc({ tag => "vxlan tag max value is 16777216" }) if $tag > 16777216;
# verify that tag is not already defined globally (vxlan-id are unique)
- for my $id (sort keys %{$vnet_cfg->{ids}}) {
- next if $id eq $vnetid;
- my $othervnet = $vnet_cfg->{ids}->{$id};
- my $other_tag = $othervnet->{tag};
- my $other_zoneid = $othervnet->{zone};
- my $other_zone = $zone_cfg->{ids}->{$other_zoneid};
- next if $other_zone->{type} ne 'vxlan' && $other_zone->{type} ne 'evpn';
- raise_param_exc({ tag => "vxlan tag $tag already exist in vnet $id in zone $other_zoneid "}) if $other_tag && $tag eq $other_tag;
+ for my $id (sort keys %{ $vnet_cfg->{ids} }) {
+ next if $id eq $vnetid;
+ my $othervnet = $vnet_cfg->{ids}->{$id};
+ my $other_tag = $othervnet->{tag};
+ my $other_zoneid = $othervnet->{zone};
+ my $other_zone = $zone_cfg->{ids}->{$other_zoneid};
+ next if $other_zone->{type} ne 'vxlan' && $other_zone->{type} ne 'evpn';
+ raise_param_exc(
+ { tag => "vxlan tag $tag already exist in vnet $id in zone $other_zoneid " })
+ if $other_tag && $tag eq $other_tag;
}
}
1;
-
diff --git a/src/test/run_test_dns.pl b/src/test/run_test_dns.pl
index 43280dc..26fbfaf 100755
--- a/src/test/run_test_dns.pl
+++ b/src/test/run_test_dns.pl
@@ -25,8 +25,8 @@ sub read_sdn_config {
open my $in, '<', $file or die $!;
my $sdn_config;
{
- local $/; # slurp mode
- $sdn_config = eval <$in>;
+ local $/; # slurp mode
+ $sdn_config = eval <$in>;
}
close $in;
@@ -43,27 +43,27 @@ foreach my $path (@plugins) {
my $pve_sdn_dns;
$pve_sdn_dns = Test::MockModule->new('PVE::Network::SDN::Dns');
$pve_sdn_dns->mock(
- config => sub {
- my $dns_config = read_sdn_config("$path/dns_config");
- return $dns_config;
- },
+ config => sub {
+ my $dns_config = read_sdn_config("$path/dns_config");
+ return $dns_config;
+ },
);
my $sdn_module = Test::MockModule->new("PVE::Network::SDN");
$sdn_module->mock(
- config => sub {
- return $sdn_config;
- },
- api_request => sub {
- my ($method, $url, $headers, $data) = @_;
-
- my $js = JSON->new;
- $js->canonical(1);
-
- my $encoded_data = $js->encode($data) if $data;
- my $req = HTTP::Request->new($method, $url, $headers, $encoded_data);
- die Dumper($req);
- },
+ config => sub {
+ return $sdn_config;
+ },
+ api_request => sub {
+ my ($method, $url, $headers, $data) = @_;
+
+ my $js = JSON->new;
+ $js->canonical(1);
+
+ my $encoded_data = $js->encode($data) if $data;
+ my $req = HTTP::Request->new($method, $url, $headers, $encoded_data);
+ die Dumper($req);
+ },
);
my $dns_cfg = PVE::Network::SDN::Dns::config();
@@ -77,183 +77,183 @@ foreach my $path (@plugins) {
foreach my $ip (@ips) {
- my $ipversion = Net::IP::ip_is_ipv6($ip) ? "ipv6" : "ipv4";
- my $type = Net::IP::ip_is_ipv6($ip) ? "AAAA" : "A";
- my $ip2 = $type eq 'AAAA' ? '2001:4860:4860::8844' : '127.0.0.1';
- my $fqdn = $hostname . "." . $zone . ".";
-
- my $sdn_dns_plugin = Test::MockModule->new($plugin);
- $sdn_dns_plugin->mock(
-
- get_zone_content => sub {
- return undef;
- },
- get_zone_rrset => sub {
- return undef;
- },
- );
-
- ## add_a_record
- my $test = "add_a_record";
- my $expected = Dumper read_sdn_config("$path/expected.$test.$ipversion");
- my $name = "$dnsid $test";
-
- $plugin->add_a_record($plugin_config, $zone, $hostname, $ip, 1);
-
- if ($@) {
- is($@, $expected, $name);
- } else {
- fail($name);
- }
-
- ## add_ptr_record
- $test = "add_ptr_record";
- $expected = Dumper read_sdn_config("$path/expected.$test.$ipversion");
- $name = "$dnsid $test";
-
- $plugin->add_ptr_record($plugin_config, $zone, $hostname, $ip, 1);
-
- if ($@) {
- is($@, $expected, $name);
- } else {
- fail($name);
- }
-
- ## del_ptr_record
- $test = "del_ptr_record";
- $expected = Dumper read_sdn_config("$path/expected.$test.$ipversion");
- $name = "$dnsid $test";
-
- $plugin->del_ptr_record($plugin_config, $zone, $ip, 1);
-
- if ($@) {
- is($@, $expected, $name);
- } else {
- fail($name);
- }
-
- ## del_a_record
-
- $sdn_dns_plugin->mock(
-
- get_zone_content => sub {
- return undef;
- },
- get_zone_rrset => sub {
-
- my $type = Net::IP::ip_is_ipv6($ip) ? "AAAA" : "A";
- my $fqdn = $hostname . "." . $zone . ".";
- my $record = {
- content => $ip,
- disabled => JSON::false,
- name => $fqdn,
- type => $type,
- };
-
- my $rrset = {
- name => $fqdn,
- type => $type,
- ttl => '3600',
- records => [$record],
- };
- return $rrset;
- },
- );
-
- $test = "del_a_record";
- $expected = Dumper read_sdn_config("$path/expected.$test.$ipversion");
- $name = "$dnsid $test";
-
- $plugin->del_a_record($plugin_config, $zone, $hostname, $ip, 1);
-
- if ($@) {
- is($@, $expected, $name);
- } else {
- fail($name);
- }
-
- ## del_a_multiple_record
-
- $sdn_dns_plugin->mock(
-
- get_zone_content => sub {
- return undef;
- },
- get_zone_rrset => sub {
-
- my $record = {
- content => $ip,
- disabled => JSON::false,
- name => $fqdn,
- type => $type,
- };
-
- my $record2 = {
- content => $ip2,
- disabled => JSON::false,
- name => $fqdn,
- type => $type,
- };
-
- my $rrset = {
- name => $fqdn,
- type => $type,
- ttl => '3600',
- records => [$record, $record2],
- };
- return $rrset;
- },
- );
-
- $test = "del_a_multiple_record";
- $expected = Dumper read_sdn_config("$path/expected.$test.$ipversion");
- $name = "$dnsid $test";
-
- $plugin->del_a_record($plugin_config, $zone, $hostname, $ip, 1);
-
- if ($@) {
- is($@, $expected, $name);
- } else {
- fail($name);
- }
-
- ## add_a_multiple_record
-
- $sdn_dns_plugin->mock(
-
- get_zone_content => sub {
- return undef;
- },
- get_zone_rrset => sub {
-
- my $record2 = {
- content => $ip2,
- disabled => JSON::false,
- name => $fqdn,
- type => $type,
- };
-
- my $rrset = {
- name => $fqdn,
- type => $type,
- ttl => '3600',
- records => [$record2],
- };
- return $rrset;
- },
- );
-
- $test = "add_a_multiple_record";
- $expected = Dumper read_sdn_config("$path/expected.$test.$ipversion");
- $name = "$dnsid $test";
-
- $plugin->add_a_record($plugin_config, $zone, $hostname, $ip, 1);
-
- if ($@) {
- is($@, $expected, $name);
- } else {
- fail($name);
- }
+ my $ipversion = Net::IP::ip_is_ipv6($ip) ? "ipv6" : "ipv4";
+ my $type = Net::IP::ip_is_ipv6($ip) ? "AAAA" : "A";
+ my $ip2 = $type eq 'AAAA' ? '2001:4860:4860::8844' : '127.0.0.1';
+ my $fqdn = $hostname . "." . $zone . ".";
+
+ my $sdn_dns_plugin = Test::MockModule->new($plugin);
+ $sdn_dns_plugin->mock(
+
+ get_zone_content => sub {
+ return undef;
+ },
+ get_zone_rrset => sub {
+ return undef;
+ },
+ );
+
+ ## add_a_record
+ my $test = "add_a_record";
+ my $expected = Dumper read_sdn_config("$path/expected.$test.$ipversion");
+ my $name = "$dnsid $test";
+
+ $plugin->add_a_record($plugin_config, $zone, $hostname, $ip, 1);
+
+ if ($@) {
+ is($@, $expected, $name);
+ } else {
+ fail($name);
+ }
+
+ ## add_ptr_record
+ $test = "add_ptr_record";
+ $expected = Dumper read_sdn_config("$path/expected.$test.$ipversion");
+ $name = "$dnsid $test";
+
+ $plugin->add_ptr_record($plugin_config, $zone, $hostname, $ip, 1);
+
+ if ($@) {
+ is($@, $expected, $name);
+ } else {
+ fail($name);
+ }
+
+ ## del_ptr_record
+ $test = "del_ptr_record";
+ $expected = Dumper read_sdn_config("$path/expected.$test.$ipversion");
+ $name = "$dnsid $test";
+
+ $plugin->del_ptr_record($plugin_config, $zone, $ip, 1);
+
+ if ($@) {
+ is($@, $expected, $name);
+ } else {
+ fail($name);
+ }
+
+ ## del_a_record
+
+ $sdn_dns_plugin->mock(
+
+ get_zone_content => sub {
+ return undef;
+ },
+ get_zone_rrset => sub {
+
+ my $type = Net::IP::ip_is_ipv6($ip) ? "AAAA" : "A";
+ my $fqdn = $hostname . "." . $zone . ".";
+ my $record = {
+ content => $ip,
+ disabled => JSON::false,
+ name => $fqdn,
+ type => $type,
+ };
+
+ my $rrset = {
+ name => $fqdn,
+ type => $type,
+ ttl => '3600',
+ records => [$record],
+ };
+ return $rrset;
+ },
+ );
+
+ $test = "del_a_record";
+ $expected = Dumper read_sdn_config("$path/expected.$test.$ipversion");
+ $name = "$dnsid $test";
+
+ $plugin->del_a_record($plugin_config, $zone, $hostname, $ip, 1);
+
+ if ($@) {
+ is($@, $expected, $name);
+ } else {
+ fail($name);
+ }
+
+ ## del_a_multiple_record
+
+ $sdn_dns_plugin->mock(
+
+ get_zone_content => sub {
+ return undef;
+ },
+ get_zone_rrset => sub {
+
+ my $record = {
+ content => $ip,
+ disabled => JSON::false,
+ name => $fqdn,
+ type => $type,
+ };
+
+ my $record2 = {
+ content => $ip2,
+ disabled => JSON::false,
+ name => $fqdn,
+ type => $type,
+ };
+
+ my $rrset = {
+ name => $fqdn,
+ type => $type,
+ ttl => '3600',
+ records => [$record, $record2],
+ };
+ return $rrset;
+ },
+ );
+
+ $test = "del_a_multiple_record";
+ $expected = Dumper read_sdn_config("$path/expected.$test.$ipversion");
+ $name = "$dnsid $test";
+
+ $plugin->del_a_record($plugin_config, $zone, $hostname, $ip, 1);
+
+ if ($@) {
+ is($@, $expected, $name);
+ } else {
+ fail($name);
+ }
+
+ ## add_a_multiple_record
+
+ $sdn_dns_plugin->mock(
+
+ get_zone_content => sub {
+ return undef;
+ },
+ get_zone_rrset => sub {
+
+ my $record2 = {
+ content => $ip2,
+ disabled => JSON::false,
+ name => $fqdn,
+ type => $type,
+ };
+
+ my $rrset = {
+ name => $fqdn,
+ type => $type,
+ ttl => '3600',
+ records => [$record2],
+ };
+ return $rrset;
+ },
+ );
+
+ $test = "add_a_multiple_record";
+ $expected = Dumper read_sdn_config("$path/expected.$test.$ipversion");
+ $name = "$dnsid $test";
+
+ $plugin->add_a_record($plugin_config, $zone, $hostname, $ip, 1);
+
+ if ($@) {
+ is($@, $expected, $name);
+ } else {
+ fail($name);
+ }
}
## verify_zone
@@ -264,9 +264,9 @@ foreach my $path (@plugins) {
$plugin->verify_zone($plugin_config, $zone, 1);
if ($@) {
- is($@, $expected, $name);
+ is($@, $expected, $name);
} else {
- fail($name);
+ fail($name);
}
}
diff --git a/src/test/run_test_ipams.pl b/src/test/run_test_ipams.pl
index 2196079..193b34b 100755
--- a/src/test/run_test_ipams.pl
+++ b/src/test/run_test_ipams.pl
@@ -25,8 +25,8 @@ sub read_sdn_config {
open my $in, '<', $file or die $!;
my $sdn_config;
{
- local $/; # slurp mode
- $sdn_config = eval <$in>;
+ local $/; # slurp mode
+ $sdn_config = eval <$in>;
}
close $in;
@@ -44,35 +44,35 @@ foreach my $path (@plugins) {
my $pve_sdn_subnets;
$pve_sdn_subnets = Test::MockModule->new('PVE::Network::SDN::Subnets');
$pve_sdn_subnets->mock(
- config => sub {
- return $sdn_config->{subnets};
- },
+ config => sub {
+ return $sdn_config->{subnets};
+ },
);
my $pve_sdn_ipam;
$pve_sdn_subnets = Test::MockModule->new('PVE::Network::SDN::Ipams');
$pve_sdn_subnets->mock(
- config => sub {
- my $ipam_config = read_sdn_config("$path/ipam_config");
- return $ipam_config;
- },
+ config => sub {
+ my $ipam_config = read_sdn_config("$path/ipam_config");
+ return $ipam_config;
+ },
);
my $sdn_module = Test::MockModule->new("PVE::Network::SDN");
$sdn_module->mock(
- config => sub {
- return $sdn_config;
- },
- api_request => sub {
- my ($method, $url, $headers, $data) = @_;
-
- my $js = JSON->new;
- $js->canonical(1);
-
- my $encoded_data = $js->encode($data) if $data;
- my $req = HTTP::Request->new($method, $url, $headers, $encoded_data);
- die Dumper($req);
- },
+ config => sub {
+ return $sdn_config;
+ },
+ api_request => sub {
+ my ($method, $url, $headers, $data) = @_;
+
+ my $js = JSON->new;
+ $js->canonical(1);
+
+ my $encoded_data = $js->encode($data) if $data;
+ my $req = HTTP::Request->new($method, $url, $headers, $encoded_data);
+ die Dumper($req);
+ },
);
#test params;
@@ -84,22 +84,22 @@ foreach my $path (@plugins) {
my $is_gateway = 1;
my $subnet =
- PVE::Network::SDN::Subnets::sdn_subnets_config($sdn_config->{subnets}, $subnetid, 1);
+ PVE::Network::SDN::Subnets::sdn_subnets_config($sdn_config->{subnets}, $subnetid, 1);
my $ipam_cfg = PVE::Network::SDN::Ipams::config();
my $plugin_config = $ipam_cfg->{ids}->{$ipamid};
my $plugin = PVE::Network::SDN::Ipams::Plugin->lookup($plugin_config->{type});
my $sdn_ipam_plugin = Test::MockModule->new($plugin);
$sdn_ipam_plugin->mock(
- get_prefix_id => sub {
- return 1;
- },
- get_ip_id => sub {
- return 1;
- },
- is_ip_gateway => sub {
- return 1;
- },
+ get_prefix_id => sub {
+ return 1;
+ },
+ get_ip_id => sub {
+ return 1;
+ },
+ is_ip_gateway => sub {
+ return 1;
+ },
);
## add_ip
@@ -107,13 +107,22 @@ foreach my $path (@plugins) {
my $expected = Dumper read_sdn_config("$path/expected.$test");
my $name = "$ipamid $test";
- $plugin->add_ip($plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description,
- $is_gateway, 1);
+ $plugin->add_ip(
+ $plugin_config,
+ $subnetid,
+ $subnet,
+ $ip,
+ $hostname,
+ $mac,
+ $description,
+ $is_gateway,
+ 1,
+ );
if ($@) {
- is($@, $expected, $name);
+ is($@, $expected, $name);
} else {
- fail($name);
+ fail($name);
}
## add_next_freeip
@@ -124,9 +133,9 @@ foreach my $path (@plugins) {
$plugin->add_next_freeip($plugin_config, $subnetid, $subnet, $hostname, $mac, $description, 1);
if ($@) {
- is($@, $expected, $name);
+ is($@, $expected, $name);
} else {
- fail($name);
+ fail($name);
}
## del_ip
@@ -137,22 +146,31 @@ foreach my $path (@plugins) {
$plugin->del_ip($plugin_config, $subnetid, $subnet, $ip, 1);
if ($@) {
- is($@, $expected, $name);
+ is($@, $expected, $name);
} else {
- fail($name);
+ fail($name);
}
## update_ip
$test = "update_ip";
$expected = Dumper read_sdn_config("$path/expected.$test");
$name = "$ipamid $test";
- $plugin->update_ip($plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description,
- $is_gateway, 1);
+ $plugin->update_ip(
+ $plugin_config,
+ $subnetid,
+ $subnet,
+ $ip,
+ $hostname,
+ $mac,
+ $description,
+ $is_gateway,
+ 1,
+ );
if ($@) {
- is($@, $expected, $name);
+ is($@, $expected, $name);
} else {
- fail($name);
+ fail($name);
}
## add_ip_notgateway
@@ -161,19 +179,28 @@ foreach my $path (@plugins) {
$expected = Dumper read_sdn_config("$path/expected.$test");
$name = "$ipamid $test";
- $plugin->add_ip($plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description,
- $is_gateway, 1);
+ $plugin->add_ip(
+ $plugin_config,
+ $subnetid,
+ $subnet,
+ $ip,
+ $hostname,
+ $mac,
+ $description,
+ $is_gateway,
+ 1,
+ );
if ($@) {
- is($@, $expected, $name);
+ is($@, $expected, $name);
} else {
- fail($name);
+ fail($name);
}
$sdn_ipam_plugin->mock(
- get_prefix_id => sub {
- return undef;
- },
+ get_prefix_id => sub {
+ return undef;
+ },
);
## add_subnet
@@ -184,9 +211,9 @@ foreach my $path (@plugins) {
$plugin->add_subnet($plugin_config, $subnetid, $subnet, 1);
if ($@) {
- is($@, $expected, $name);
+ is($@, $expected, $name);
} else {
- fail($name);
+ fail($name);
}
}
diff --git a/src/test/run_test_subnets.pl b/src/test/run_test_subnets.pl
index 79186c2..d4f8d66 100755
--- a/src/test/run_test_subnets.pl
+++ b/src/test/run_test_subnets.pl
@@ -41,8 +41,8 @@ sub read_sdn_config {
open my $in, '<', $file or die $!;
my $sdn_config;
{
- local $/; # slurp mode
- $sdn_config = eval <$in>;
+ local $/; # slurp mode
+ $sdn_config = eval <$in>;
}
close $in;
@@ -61,15 +61,15 @@ foreach my $path (@plugins) {
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;
- },
+ config => sub {
+ return $sdn_config->{subnets};
+ },
+ verify_dns_zone => sub {
+ return;
+ },
+ add_dns_record => sub {
+ return;
+ },
);
my $js = JSON->new;
@@ -79,7 +79,7 @@ foreach my $path (@plugins) {
my $subnets = $sdn_config->{subnets}->{ids};
my $subnetid = (keys %{$subnets})[0];
my $subnet =
- PVE::Network::SDN::Subnets::sdn_subnets_config($sdn_config->{subnets}, $subnetid, 1);
+ PVE::Network::SDN::Subnets::sdn_subnets_config($sdn_config->{subnets}, $subnetid, 1);
my $subnet_cidr = $subnet->{cidr};
my $iplist = NetAddr::IP->new($subnet_cidr);
@@ -103,33 +103,33 @@ foreach my $path (@plugins) {
my $plugin;
my $sdn_ipam_plugin;
if ($ipam) {
- $plugin = PVE::Network::SDN::Ipams::Plugin->lookup($ipam);
- $sdn_ipam_plugin = Test::MockModule->new($plugin);
- $sdn_ipam_plugin->mock(
- read_db => sub {
- return $ipamdb;
- },
- write_db => sub {
- my ($cfg) = @_;
- $ipamdb = $cfg;
- },
- cfs_lock_file => $mocked_cfs_lock_file,
- );
+ $plugin = PVE::Network::SDN::Ipams::Plugin->lookup($ipam);
+ $sdn_ipam_plugin = Test::MockModule->new($plugin);
+ $sdn_ipam_plugin->mock(
+ read_db => sub {
+ return $ipamdb;
+ },
+ write_db => sub {
+ my ($cfg) = @_;
+ $ipamdb = $cfg;
+ },
+ cfs_lock_file => $mocked_cfs_lock_file,
+ );
}
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_cache_mac_ip => sub {
- return;
- },
- del_cache_mac_ip => sub {
- return;
- },
+ config => sub {
+ my $ipam_config = read_sdn_config("$path/ipam_config");
+ return $ipam_config;
+ },
+ add_cache_mac_ip => sub {
+ return;
+ },
+ del_cache_mac_ip => sub {
+ return;
+ },
);
## add_subnet
@@ -139,17 +139,17 @@ foreach my $path (@plugins) {
my $expected = '{"zones":{"myzone":{"subnets":{"' . $subnet_cidr . '":{"ips":{}}}}}}';
eval {
- PVE::Network::SDN::Subnets::add_subnet($zone, $subnetid, $subnet);
+ PVE::Network::SDN::Subnets::add_subnet($zone, $subnetid, $subnet);
};
if ($@) {
- fail("$name : $@");
+ fail("$name : $@");
} elsif ($ipam) {
- $result = $js->encode($plugin->read_db());
- is($result, $expected, $name);
+ $result = $js->encode($plugin->read_db());
+ is($result, $expected, $name);
} else {
- is(undef, undef, $name);
+ is(undef, undef, $name);
}
## add_ip
@@ -157,41 +157,43 @@ foreach my $path (@plugins) {
$name = "$testid $test";
$result = undef;
$expected =
- '{"zones":{"myzone":{"subnets":{"'
- . $subnet_cidr
- . '":{"ips":{"'
- . $ip
- . '":{"gateway":1}}}}}}}';
+ '{"zones":{"myzone":{"subnets":{"'
+ . $subnet_cidr
+ . '":{"ips":{"'
+ . $ip
+ . '":{"gateway":1}}}}}}}';
eval {
- PVE::Network::SDN::Subnets::add_ip($zone, $subnetid, $subnet, $ip, $hostname, $mac, $vmid,
- $is_gateway);
+ PVE::Network::SDN::Subnets::add_ip(
+ $zone, $subnetid, $subnet, $ip, $hostname, $mac, $vmid, $is_gateway,
+ );
};
if ($@) {
- fail("$name : $@");
+ fail("$name : $@");
} elsif ($ipam) {
- $result = $js->encode($plugin->read_db());
- is($result, $expected, $name);
+ $result = $js->encode($plugin->read_db());
+ is($result, $expected, $name);
} else {
- is(undef, undef, $name);
+ is(undef, undef, $name);
}
if ($ipam) {
- ## add_already_exist_ip
- $test = "add_already_exist_ip $ip";
- $name = "$testid $test";
-
- eval {
- PVE::Network::SDN::Subnets::add_ip($zone, $subnetid, $subnet, $ip, $hostname, $mac,
- $vmid);
- };
-
- if ($@) {
- is(undef, undef, $name);
- } else {
- fail("$name : $@");
- }
+ ## add_already_exist_ip
+ $test = "add_already_exist_ip $ip";
+ $name = "$testid $test";
+
+ eval {
+ PVE::Network::SDN::Subnets::add_ip(
+ $zone, $subnetid, $subnet, $ip, $hostname, $mac, $vmid,
+ );
+ };
+
+ if ($@) {
+ is(undef, undef, $name);
+ } else {
+ fail("$name : $@");
+ }
}
## add_second_ip
@@ -199,31 +201,33 @@ foreach my $path (@plugins) {
$name = "$testid $test";
$result = undef;
$expected =
- '{"zones":{"myzone":{"subnets":{"'
- . $subnet_cidr
- . '":{"ips":{"'
- . $ip
- . '":{"gateway":1},"'
- . $ip2
- . '":{"hostname":"'
- . $hostname
- . '","mac":"'
- . $mac
- . '","vmid":"'
- . $vmid
- . '"}}}}}}}';
+ '{"zones":{"myzone":{"subnets":{"'
+ . $subnet_cidr
+ . '":{"ips":{"'
+ . $ip
+ . '":{"gateway":1},"'
+ . $ip2
+ . '":{"hostname":"'
+ . $hostname
+ . '","mac":"'
+ . $mac
+ . '","vmid":"'
+ . $vmid
+ . '"}}}}}}}';
eval {
- PVE::Network::SDN::Subnets::add_ip($zone, $subnetid, $subnet, $ip2, $hostname, $mac, $vmid);
+ PVE::Network::SDN::Subnets::add_ip(
+ $zone, $subnetid, $subnet, $ip2, $hostname, $mac, $vmid,
+ );
};
if ($@) {
- fail("$name : $@");
+ fail("$name : $@");
} elsif ($ipam) {
- $result = $js->encode($plugin->read_db());
- is($result, $expected, $name);
+ $result = $js->encode($plugin->read_db());
+ is($result, $expected, $name);
} else {
- is(undef, undef, $name);
+ is(undef, undef, $name);
}
## add_next_free
@@ -231,38 +235,38 @@ foreach my $path (@plugins) {
$name = "$testid $test";
$result = undef;
$expected =
- '{"zones":{"myzone":{"subnets":{"'
- . $subnet_cidr
- . '":{"ips":{"'
- . $ip
- . '":{"gateway":1},"'
- . $ipnextfree
- . '":{"hostname":"'
+ '{"zones":{"myzone":{"subnets":{"'
+ . $subnet_cidr
+ . '":{"ips":{"'
+ . $ip
+ . '":{"gateway":1},"'
+ . $ipnextfree
+ . '":{"hostname":"'
+ . $hostname
+ . '","mac":"'
+ . $mac
+ . '","vmid":"'
+ . $vmid . '"},"'
+ . $ip2
+ . '":{"hostname":"'
. $hostname
. '","mac":"'
- . $mac
- . '","vmid":"'
- . $vmid
- . '"},"'
- . $ip2
- . '":{"hostname":"'
- . $hostname
- . '","mac":"'
- . $mac
- . '","vmid":"'
- . $vmid
- . '"}}}}}}}';
+ . $mac
+ . '","vmid":"'
+ . $vmid
+ . '"}}}}}}}';
eval {
- $ip3 = PVE::Network::SDN::Subnets::add_next_free_ip($zone, $subnetid, $subnet, $hostname,
- $mac, $vmid);
+ $ip3 = PVE::Network::SDN::Subnets::add_next_free_ip(
+ $zone, $subnetid, $subnet, $hostname, $mac, $vmid,
+ );
};
if ($@) {
- fail("$name : $@");
+ fail("$name : $@");
} elsif ($ipam) {
- $result = $js->encode($plugin->read_db());
- is($result, $expected, $name);
+ $result = $js->encode($plugin->read_db());
+ is($result, $expected, $name);
}
## del_ip
@@ -270,105 +274,105 @@ foreach my $path (@plugins) {
$name = "$testid $test";
$result = undef;
$expected =
- '{"zones":{"myzone":{"subnets":{"'
- . $subnet_cidr
- . '":{"ips":{"'
- . $ipnextfree
- . '":{"hostname":"'
+ '{"zones":{"myzone":{"subnets":{"'
+ . $subnet_cidr
+ . '":{"ips":{"'
+ . $ipnextfree
+ . '":{"hostname":"'
. $hostname
. '","mac":"'
- . $mac
- . '","vmid":"'
- . $vmid
- . '"},"'
- . $ip2
- . '":{"hostname":"'
- . $hostname
- . '","mac":"'
- . $mac
- . '","vmid":"'
- . $vmid
- . '"}}}}}}}';
+ . $mac
+ . '","vmid":"'
+ . $vmid . '"},"'
+ . $ip2
+ . '":{"hostname":"'
+ . $hostname
+ . '","mac":"'
+ . $mac
+ . '","vmid":"'
+ . $vmid
+ . '"}}}}}}}';
eval { PVE::Network::SDN::Subnets::del_ip($zone, $subnetid, $subnet, $ip, $hostname); };
if ($@) {
- fail("$name : $@");
+ fail("$name : $@");
} elsif ($ipam) {
- $result = $js->encode($plugin->read_db());
- is($result, $expected, $name);
+ $result = $js->encode($plugin->read_db());
+ is($result, $expected, $name);
} else {
- is(undef, undef, $name);
+ is(undef, undef, $name);
}
if ($ipam) {
- ## del_subnet_not_empty
- $test = "del_subnet_not_empty $subnetid";
- $name = "$testid $test";
- $result = undef;
- $expected = undef;
-
- eval { PVE::Network::SDN::Subnets::del_subnet($zone, $subnetid, $subnet); };
-
- if ($@) {
- is($result, $expected, $name);
- } else {
- fail("$name : $@");
- }
+ ## del_subnet_not_empty
+ $test = "del_subnet_not_empty $subnetid";
+ $name = "$testid $test";
+ $result = undef;
+ $expected = undef;
+
+ eval { PVE::Network::SDN::Subnets::del_subnet($zone, $subnetid, $subnet); };
+
+ if ($@) {
+ is($result, $expected, $name);
+ } else {
+ fail("$name : $@");
+ }
}
## add_ip_rollback_failing_dns
$test = "add_ip_rollback_failing_dns";
$pve_sdn_subnets->mock(
- config => sub {
- return $sdn_config->{subnets};
- },
- verify_dns_zone => sub {
- return;
- },
- add_dns_record => sub {
- die "error add dns record";
- return;
- },
+ config => sub {
+ return $sdn_config->{subnets};
+ },
+ verify_dns_zone => sub {
+ return;
+ },
+ add_dns_record => sub {
+ die "error add dns record";
+ return;
+ },
);
$name = "$testid $test";
$result = undef;
$expected =
- '{"zones":{"myzone":{"subnets":{"'
- . $subnet_cidr
- . '":{"ips":{"'
- . $ipnextfree
- . '":{"hostname":"'
+ '{"zones":{"myzone":{"subnets":{"'
+ . $subnet_cidr
+ . '":{"ips":{"'
+ . $ipnextfree
+ . '":{"hostname":"'
+ . $hostname
+ . '","mac":"'
+ . $mac
+ . '","vmid":"'
+ . $vmid . '"},"'
+ . $ip2
+ . '":{"hostname":"'
. $hostname
. '","mac":"'
- . $mac
- . '","vmid":"'
- . $vmid
- . '"},"'
- . $ip2
- . '":{"hostname":"'
- . $hostname
- . '","mac":"'
- . $mac
- . '","vmid":"'
- . $vmid
- . '"}}}}}}}';
+ . $mac
+ . '","vmid":"'
+ . $vmid
+ . '"}}}}}}}';
eval {
- PVE::Network::SDN::Subnets::add_ip($zone, $subnetid, $subnet, $ip, $hostname, $mac, $vmid);
+ PVE::Network::SDN::Subnets::add_ip(
+ $zone, $subnetid, $subnet, $ip, $hostname, $mac, $vmid,
+ );
};
if ($@) {
- if ($ipam) {
- $result = $js->encode($plugin->read_db());
- is($result, $expected, $name);
- } else {
- is(undef, undef, $name);
- }
+ if ($ipam) {
+ $result = $js->encode($plugin->read_db());
+ is($result, $expected, $name);
+ } else {
+ is(undef, undef, $name);
+ }
} else {
- fail("$name : $@");
+ fail("$name : $@");
}
## del_empty_subnet
@@ -383,12 +387,12 @@ foreach my $path (@plugins) {
eval { PVE::Network::SDN::Subnets::del_subnet($zone, $subnetid, $subnet); };
if ($@) {
- fail("$name : $@");
+ fail("$name : $@");
} elsif ($ipam) {
- $result = $js->encode($plugin->read_db());
- is($result, $expected, $name);
+ $result = $js->encode($plugin->read_db());
+ is($result, $expected, $name);
} else {
- is(undef, undef, $name);
+ is(undef, undef, $name);
}
}
diff --git a/src/test/run_test_vnets_blackbox.pl b/src/test/run_test_vnets_blackbox.pl
index b79e1dc..2e1c505 100755
--- a/src/test/run_test_vnets_blackbox.pl
+++ b/src/test/run_test_vnets_blackbox.pl
@@ -30,24 +30,25 @@ use PVE::API2::Network::SDN::Ipams;
my $TMP_ETHERS_FILE = "/tmp/ethers";
my $test_state = undef;
+
sub clear_test_state {
$test_state = {
- locks => {},
- datacenter_config => {},
- subnets_config => {},
- controller_config => {},
- dns_config => {},
- zones_config => {},
- vnets_config => {},
- macdb => {},
- ipamdb => {},
- ipam_config => {
- 'ids' => {
- 'pve' => {
- 'type' => 'pve'
- },
- }
- },
+ locks => {},
+ datacenter_config => {},
+ subnets_config => {},
+ controller_config => {},
+ dns_config => {},
+ zones_config => {},
+ vnets_config => {},
+ macdb => {},
+ ipamdb => {},
+ ipam_config => {
+ 'ids' => {
+ 'pve' => {
+ 'type' => 'pve',
+ },
+ },
+ },
};
PVE::Tools::file_set_contents($TMP_ETHERS_FILE, "\n");
}
@@ -73,8 +74,8 @@ sub read_sdn_config {
open my $in, '<', $file or die $!;
my $sdn_config;
{
- local $/; # slurp mode
- $sdn_config = eval <$in>;
+ local $/; # slurp mode
+ $sdn_config = eval <$in>;
}
close $in;
return $sdn_config;
@@ -95,11 +96,11 @@ my $mocked_sdn_zones;
$mocked_sdn_zones = Test::MockModule->new('PVE::Network::SDN::Zones');
$mocked_sdn_zones->mock(
config => sub {
- return $test_state->{zones_config};
+ return $test_state->{zones_config};
},
write_config => sub {
- my ($cfg) = @_;
- $test_state->{zones_config} = $cfg;
+ my ($cfg) = @_;
+ $test_state->{zones_config} = $cfg;
},
);
@@ -107,7 +108,7 @@ my $mocked_sdn_zones_super_plugin;
$mocked_sdn_zones_super_plugin = Test::MockModule->new('PVE::Network::SDN::Zones::Plugin');
$mocked_sdn_zones_super_plugin->mock(
datacenter_config => sub {
- return $test_state->{datacenter_config};
+ return $test_state->{datacenter_config};
},
);
@@ -115,11 +116,11 @@ my $mocked_sdn_vnets;
$mocked_sdn_vnets = Test::MockModule->new('PVE::Network::SDN::Vnets');
$mocked_sdn_vnets->mock(
config => sub {
- return $test_state->{vnets_config};
+ return $test_state->{vnets_config};
},
write_config => sub {
- my ($cfg) = @_;
- $test_state->{vnets_config} = $cfg;
+ my ($cfg) = @_;
+ $test_state->{vnets_config} = $cfg;
},
cfs_lock_file => $mocked_cfs_lock_file,
);
@@ -128,11 +129,11 @@ my $mocked_sdn_subnets;
$mocked_sdn_subnets = Test::MockModule->new('PVE::Network::SDN::Subnets');
$mocked_sdn_subnets->mock(
config => sub {
- return $test_state->{subnets_config};
+ return $test_state->{subnets_config};
},
write_config => sub {
- my ($cfg) = @_;
- $test_state->{subnets_config} = $cfg;
+ my ($cfg) = @_;
+ $test_state->{subnets_config} = $cfg;
},
cfs_lock_file => $mocked_cfs_lock_file,
);
@@ -141,46 +142,44 @@ my $mocked_sdn_controller;
$mocked_sdn_controller = Test::MockModule->new('PVE::Network::SDN::Controllers');
$mocked_sdn_controller->mock(
config => sub {
- return $test_state->{controller_config};
+ return $test_state->{controller_config};
},
write_config => sub {
- my ($cfg) = @_;
- $test_state->{controller_config} = $cfg;
+ my ($cfg) = @_;
+ $test_state->{controller_config} = $cfg;
},
cfs_lock_file => $mocked_cfs_lock_file,
);
-
my $mocked_sdn_dns;
$mocked_sdn_dns = Test::MockModule->new('PVE::Network::SDN::Dns');
$mocked_sdn_dns->mock(
config => sub {
- return $test_state->{dns_config};
+ return $test_state->{dns_config};
},
write_config => sub {
- my ($cfg) = @_;
- $test_state->{dns_config} = $cfg;
+ my ($cfg) = @_;
+ $test_state->{dns_config} = $cfg;
},
cfs_lock_file => $mocked_cfs_lock_file,
);
-
my $mocked_sdn_ipams;
$mocked_sdn_ipams = Test::MockModule->new('PVE::Network::SDN::Ipams');
$mocked_sdn_ipams->mock(
config => sub {
- return $test_state->{ipam_config};
+ return $test_state->{ipam_config};
},
write_config => sub {
- my ($cfg) = @_;
- $test_state->{ipam_config} = $cfg;
+ my ($cfg) = @_;
+ $test_state->{ipam_config} = $cfg;
},
read_macdb => sub {
- return $test_state->{macdb};
+ return $test_state->{macdb};
},
write_macdb => sub {
- my ($cfg) = @_;
- $test_state->{macdb} = $cfg;
+ my ($cfg) = @_;
+ $test_state->{macdb} = $cfg;
},
cfs_lock_file => $mocked_cfs_lock_file,
);
@@ -189,11 +188,11 @@ my $ipam_plugin = PVE::Network::SDN::Ipams::Plugin->lookup("pve"); # NOTE this i
my $mocked_ipam_plugin = Test::MockModule->new($ipam_plugin);
$mocked_ipam_plugin->mock(
read_db => sub {
- return $test_state->{ipamdb};
+ return $test_state->{ipamdb};
},
write_db => sub {
- my ($cfg) = @_;
- $test_state->{ipamdb} = $cfg;
+ my ($cfg) = @_;
+ $test_state->{ipamdb} = $cfg;
},
cfs_lock_file => $mocked_cfs_lock_file,
);
@@ -201,15 +200,15 @@ $mocked_ipam_plugin->mock(
my $mocked_sdn_dhcp_dnsmasq = Test::MockModule->new('PVE::Network::SDN::Dhcp::Dnsmasq');
$mocked_sdn_dhcp_dnsmasq->mock(
assert_dnsmasq_installed => sub { return 1; },
- before_configure => sub {},
+ before_configure => sub { },
ethers_file => sub { return "/tmp/ethers"; },
- systemctl_service => sub {},
- update_lease => sub {},
+ systemctl_service => sub { },
+ update_lease => sub { },
);
my $mocked_api_zones = Test::MockModule->new('PVE::API2::Network::SDN::Zones');
$mocked_api_zones->mock(
- create_etc_interfaces_sdn_dir => sub {},
+ create_etc_interfaces_sdn_dir => sub { },
);
my $rpcenv = PVE::RESTEnvironment->init('priv');
@@ -231,7 +230,8 @@ $mocked_pve_cluster_obj->mock(
sub nic_join {
my ($vnetid, $mac, $hostname, $vmid) = @_;
- return PVE::Network::SDN::Vnets::add_next_free_cidr($vnetid, $hostname, $mac, "$vmid", undef, 1);
+ return PVE::Network::SDN::Vnets::add_next_free_cidr($vnetid, $hostname, $mac, "$vmid", undef,
+ 1);
}
sub nic_leave {
@@ -244,13 +244,13 @@ sub nic_start {
return PVE::Network::SDN::Vnets::add_dhcp_mapping($vnetid, $mac, $vmid, $hostname);
}
-
# ---- API HELPER FUNCTIONS FOR THE TESTS -----
my $t_invalid;
+
sub get_zone {
my ($id) = @_;
- return eval { PVE::API2::Network::SDN::Zones->read({zone => $id}); };
+ return eval { PVE::API2::Network::SDN::Zones->read({ zone => $id }); };
}
# verify get_zone actually fails if invalid
$t_invalid = get_zone("invalid");
@@ -265,13 +265,13 @@ sub create_zone {
die("creating zone failed: $@") if ($@);
my $zone = get_zone($zoneid);
- die ("test setup: zone ($zoneid) not defined") if (!defined $zone);
+ die("test setup: zone ($zoneid) not defined") if (!defined $zone);
return $zone;
}
sub get_vnet {
my ($id) = @_;
- return eval { PVE::API2::Network::SDN::Vnets->read({vnet => $id}); };
+ return eval { PVE::API2::Network::SDN::Vnets->read({ vnet => $id }); };
}
# verify get_vnet
$t_invalid = get_vnet("invalid");
@@ -284,13 +284,13 @@ sub create_vnet {
PVE::API2::Network::SDN::Vnets->create($params);
my $vnet = get_vnet($vnetid);
- die ("test setup: vnet ($vnetid) not defined") if (!defined $vnet);
+ die("test setup: vnet ($vnetid) not defined") if (!defined $vnet);
return $vnet;
}
sub get_subnet {
my ($id) = @_;
- return eval { PVE::API2::Network::SDN::Subnets->read({subnet => $id}); };
+ return eval { PVE::API2::Network::SDN::Subnets->read({ subnet => $id }); };
}
# verify get_subnet
$t_invalid = get_subnet("invalid");
@@ -303,7 +303,7 @@ sub create_subnet {
}
sub get_ipam_entries {
- return PVE::API2::Network::SDN::Ipams->ipamindex({ipam => "pve"});
+ return PVE::API2::Network::SDN::Ipams->ipamindex({ ipam => "pve" });
}
sub create_ip {
@@ -333,560 +333,609 @@ sub get_ip6 {
return $ip6->{ip} if defined $ip6;
}
-
# -------------- ACTUAL TESTS -----------------------
sub test_create_vnet_with_gateway {
- my $test_name = (split(/::/,(caller(0))[3]))[-1];
+ my $test_name = (split(/::/, (caller(0))[3]))[-1];
my $zoneid = "TESTZONE";
my $vnetid = "testvnet";
my $zone = create_zone({
- type => "simple",
- dhcp => "dnsmasq",
- ipam => "pve",
- zone => $zoneid,
+ type => "simple",
+ dhcp => "dnsmasq",
+ ipam => "pve",
+ zone => $zoneid,
});
my $vnet = create_vnet({
- type => "vnet",
- zone => $zoneid,
- vnet => $vnetid,
+ type => "vnet",
+ zone => $zoneid,
+ vnet => $vnetid,
});
create_subnet({
- type => "subnet",
- vnet => $vnetid,
- subnet => "10.0.0.0/24",
- gateway => "10.0.0.1",
- 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.200"],
+ type => "subnet",
+ vnet => $vnetid,
+ subnet => "10.0.0.0/24",
+ gateway => "10.0.0.1",
+ 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.200"],
});
my ($p) = first { $_->{gateway} == 1 } get_ipam_entries()->@*;
- ok ($p, "$test_name: Gateway IP was created in IPAM");
+ ok($p, "$test_name: Gateway IP was created in IPAM");
}
run_test(\&test_create_vnet_with_gateway);
-
sub test_without_subnet {
- my $test_name = (split(/::/,(caller(0))[3]))[-1];
+ my $test_name = (split(/::/, (caller(0))[3]))[-1];
my $zoneid = "TESTZONE";
my $vnetid = "testvnet";
my $zone = create_zone({
- type => "simple",
- dhcp => "dnsmasq",
- ipam => "pve",
- zone => $zoneid,
+ type => "simple",
+ dhcp => "dnsmasq",
+ ipam => "pve",
+ zone => $zoneid,
});
my $vnet = create_vnet({
- type => "vnet",
- zone => $zoneid,
- vnet => $vnetid,
+ type => "vnet",
+ zone => $zoneid,
+ vnet => $vnetid,
});
my $hostname = "testhostname";
my $mac = "da:65:8f:18:9b:6f";
my $vmid = "999";
- eval {
- nic_join($vnetid, $mac, $hostname, $vmid);
- };
+ eval { nic_join($vnetid, $mac, $hostname, $vmid); };
if ($@) {
- fail("$test_name: $@");
- return;
+ fail("$test_name: $@");
+ return;
}
my @ips = get_ips_from_mac($mac);
my $num_ips = scalar @ips;
- is ($num_ips, 0, "$test_name: No IP allocated in IPAM");
+ is($num_ips, 0, "$test_name: No IP allocated in IPAM");
}
run_test(\&test_without_subnet);
-
sub test_nic_join {
my ($test_name, $subnets) = @_;
die "$test_name: we're expecting an array of subnets" if !$subnets;
my $num_subnets = scalar $subnets->@*;
- die "$test_name: we're expecting an array of subnets. $num_subnets elements found" if ($num_subnets < 1);
+ die "$test_name: we're expecting an array of subnets. $num_subnets elements found"
+ if ($num_subnets < 1);
my $zoneid = "TESTZONE";
my $vnetid = "testvnet";
my $zone = create_zone({
- type => "simple",
- dhcp => "dnsmasq",
- ipam => "pve",
- zone => $zoneid,
+ type => "simple",
+ dhcp => "dnsmasq",
+ ipam => "pve",
+ zone => $zoneid,
});
my $vnet = create_vnet({
- type => "vnet",
- zone => $zoneid,
- vnet => $vnetid,
+ type => "vnet",
+ zone => $zoneid,
+ vnet => $vnetid,
});
foreach my $subnet ($subnets->@*) {
- $subnet->{type} = "subnet";
- $subnet->{vnet} = $vnetid;
- create_subnet($subnet);
- };
+ $subnet->{type} = "subnet";
+ $subnet->{vnet} = $vnetid;
+ create_subnet($subnet);
+ }
my $hostname = "testhostname";
my $mac = "da:65:8f:18:9b:6f";
my $vmid = "999";
- eval {
- nic_join($vnetid, $mac, $hostname, $vmid);
- };
+ eval { nic_join($vnetid, $mac, $hostname, $vmid); };
if ($@) {
- fail("$test_name: $@");
- return;
+ fail("$test_name: $@");
+ return;
}
my @ips = get_ips_from_mac($mac);
my $num_ips = scalar @ips;
- is ($num_ips, $num_subnets, "$test_name: Expecting $num_subnets IPs, found $num_ips");
- ok ((all { ($_->{vnet} eq $vnetid && $_->{zone} eq $zoneid) } @ips),
- "$test_name: all IPs in correct vnet and zone"
+ is($num_ips, $num_subnets, "$test_name: Expecting $num_subnets IPs, found $num_ips");
+ ok(
+ (all { ($_->{vnet} eq $vnetid && $_->{zone} eq $zoneid) } @ips),
+ "$test_name: all IPs in correct vnet and zone",
);
}
run_test(
\&test_nic_join,
"nic_join IPv4 no dhcp",
- [{
- subnet => "10.0.0.0/24",
- gateway => "10.0.0.1",
- },
-]);
+ [
+ {
+ subnet => "10.0.0.0/24",
+ gateway => "10.0.0.1",
+ },
+ ],
+);
run_test(
\&test_nic_join,
"nic_join IPv6 no dhcp",
- [{
- subnet => "8888::/64",
- gateway => "8888::1",
- },
-]);
+ [
+ {
+ subnet => "8888::/64",
+ gateway => "8888::1",
+ },
+ ],
+);
run_test(
\&test_nic_join,
"nic_join IPv4+6 no dhcp",
- [{
- subnet => "10.0.0.0/24",
- gateway => "10.0.0.1",
- }, {
- subnet => "8888::/64",
- gateway => "8888::1",
- },
-]);
+ [
+ {
+ subnet => "10.0.0.0/24",
+ gateway => "10.0.0.1",
+ },
+ {
+ subnet => "8888::/64",
+ gateway => "8888::1",
+ },
+ ],
+);
run_test(
\&test_nic_join,
"nic_join IPv4 with dhcp",
- [{
- subnet => "10.0.0.0/24",
- gateway => "10.0.0.1",
- 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.200"],
- },
-]);
+ [
+ {
+ subnet => "10.0.0.0/24",
+ gateway => "10.0.0.1",
+ 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.200"],
+ },
+ ],
+);
run_test(
\&test_nic_join,
"nic_join IPv6 with dhcp",
- [{
- subnet => "8888::/64",
- gateway => "8888::1",
- 'dhcp-range' => ["start-address=8888::100,end-address=8888::200"],
- },
-]);
+ [
+ {
+ subnet => "8888::/64",
+ gateway => "8888::1",
+ 'dhcp-range' => ["start-address=8888::100,end-address=8888::200"],
+ },
+ ],
+);
run_test(
\&test_nic_join,
"nic_join IPv4+6 with dhcp",
- [{
- subnet => "10.0.0.0/24",
- gateway => "10.0.0.1",
- 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.200"],
- }, {
- subnet => "8888::/64",
- gateway => "8888::1",
- 'dhcp-range' => ["start-address=8888::100,end-address=8888::200"],
- },
-]);
+ [
+ {
+ subnet => "10.0.0.0/24",
+ gateway => "10.0.0.1",
+ 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.200"],
+ },
+ {
+ subnet => "8888::/64",
+ gateway => "8888::1",
+ 'dhcp-range' => ["start-address=8888::100,end-address=8888::200"],
+ },
+ ],
+);
run_test(
\&test_nic_join,
"nic_join IPv4 no DHCP, IPv6 with DHCP",
- [{
- subnet => "10.0.0.0/24",
- gateway => "10.0.0.1",
- }, {
- subnet => "8888::/64",
- gateway => "8888::1",
- 'dhcp-range' => ["start-address=8888::100,end-address=8888::200"],
- },
-]);
+ [
+ {
+ subnet => "10.0.0.0/24",
+ gateway => "10.0.0.1",
+ },
+ {
+ subnet => "8888::/64",
+ gateway => "8888::1",
+ 'dhcp-range' => ["start-address=8888::100,end-address=8888::200"],
+ },
+ ],
+);
run_test(
\&test_nic_join,
"nic_join IPv4 with DHCP, IPv6 no DHCP",
- [{
- subnet => "10.0.0.0/24",
- gateway => "10.0.0.1",
- 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.200"],
- }, {
- subnet => "8888::/64",
- gateway => "8888::1",
- },
-]);
-
+ [
+ {
+ subnet => "10.0.0.0/24",
+ gateway => "10.0.0.1",
+ 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.200"],
+ },
+ {
+ subnet => "8888::/64",
+ gateway => "8888::1",
+ },
+ ],
+);
sub test_nic_join_full_dhcp_range {
my ($test_name, $subnets, $expected_ip4, $expected_ip6) = @_;
die "$test_name: we're expecting an array of subnets" if !$subnets;
my $num_subnets = scalar $subnets->@*;
- die "$test_name: we're expecting an array of subnets. $num_subnets elements found" if ($num_subnets < 1);
+ die "$test_name: we're expecting an array of subnets. $num_subnets elements found"
+ if ($num_subnets < 1);
my $zoneid = "TESTZONE";
my $vnetid = "testvnet";
my $zone = create_zone({
- type => "simple",
- dhcp => "dnsmasq",
- ipam => "pve",
- zone => $zoneid,
+ type => "simple",
+ dhcp => "dnsmasq",
+ ipam => "pve",
+ zone => $zoneid,
});
my $vnet = create_vnet({
- type => "vnet",
- zone => $zoneid,
- vnet => $vnetid,
+ type => "vnet",
+ zone => $zoneid,
+ vnet => $vnetid,
});
foreach my $subnet ($subnets->@*) {
- $subnet->{type} = "subnet";
- $subnet->{vnet} = $vnetid;
- create_subnet($subnet);
- };
+ $subnet->{type} = "subnet";
+ $subnet->{vnet} = $vnetid;
+ create_subnet($subnet);
+ }
my $hostname = "testhostname";
my $mac = "da:65:8f:18:9b:6f";
my $vmid = "999";
- eval {
- nic_join($vnetid, $mac, $hostname, $vmid);
- };
+ eval { nic_join($vnetid, $mac, $hostname, $vmid); };
- if (! $@) {
- fail ("$test_name: nic_join() is expected to fail because we cannot allocate all IPs");
+ if (!$@) {
+ fail("$test_name: nic_join() is expected to fail because we cannot allocate all IPs");
}
my @ips = get_ips_from_mac($mac);
my $num_ips = scalar @ips;
- is ($num_ips, 0, "$test_name: No IP allocated in IPAM");
+ is($num_ips, 0, "$test_name: No IP allocated in IPAM");
}
run_test(
\&test_nic_join_full_dhcp_range,
"nic_join IPv4 with DHCP, dhcp-range full",
- [{
- subnet => "10.0.0.0/24",
- gateway => "10.0.0.100", # the gateway uses the only available IP in the dhcp-range
- 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.100"],
- }
-]);
+ [
+ {
+ subnet => "10.0.0.0/24",
+ gateway => "10.0.0.100", # the gateway uses the only available IP in the dhcp-range
+ 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.100"],
+ },
+ ],
+);
run_test(
\&test_nic_join_full_dhcp_range,
"nic_join IPv6 with DHCP, dhcp-range full",
- [{
- subnet => "8888::/64",
- gateway => "8888::100", # the gateway uses the only available IP in the dhcp-range
- 'dhcp-range' => ["start-address=8888::100,end-address=8888::100"],
- },
-]);
+ [
+ {
+ subnet => "8888::/64",
+ gateway => "8888::100", # the gateway uses the only available IP in the dhcp-range
+ 'dhcp-range' => ["start-address=8888::100,end-address=8888::100"],
+ },
+ ],
+);
run_test(
\&test_nic_join_full_dhcp_range,
"nic_join IPv4+6 with DHCP, dhcp-range full for both",
- [{
- subnet => "10.0.0.0/24",
- gateway => "10.0.0.100",
- 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.100"],
- }, {
- subnet => "8888::/64",
- gateway => "8888::100",
- 'dhcp-range' => ["start-address=8888::100,end-address=8888::100"],
- }
-]);
+ [
+ {
+ subnet => "10.0.0.0/24",
+ gateway => "10.0.0.100",
+ 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.100"],
+ },
+ {
+ subnet => "8888::/64",
+ gateway => "8888::100",
+ 'dhcp-range' => ["start-address=8888::100,end-address=8888::100"],
+ },
+ ],
+);
run_test(
\&test_nic_join_full_dhcp_range,
"nic_join IPv4+6 with DHCP, dhcp-range full for IPv4",
- [{
- subnet => "10.0.0.0/24",
- gateway => "10.0.0.100", # the gateway uses the only available IP in the dhcp-range
- 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.100"],
- }, {
- subnet => "8888::/64",
- gateway => "8888::1",
- 'dhcp-range' => ["start-address=8888::100,end-address=8888::100"],
- }],
+ [
+ {
+ subnet => "10.0.0.0/24",
+ gateway => "10.0.0.100", # the gateway uses the only available IP in the dhcp-range
+ 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.100"],
+ },
+ {
+ subnet => "8888::/64",
+ gateway => "8888::1",
+ 'dhcp-range' => ["start-address=8888::100,end-address=8888::100"],
+ },
+ ],
);
run_test(
\&test_nic_join_full_dhcp_range,
"nic_join IPv4+6 with DHCP, dhcp-range full for IPv6",
- [{
- subnet => "10.0.0.0/24",
- gateway => "10.0.0.1",
- 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.100"],
- }, {
- subnet => "8888::/64",
- gateway => "8888::100",
- 'dhcp-range' => ["start-address=8888::100,end-address=8888::100"],
- }],
+ [
+ {
+ subnet => "10.0.0.0/24",
+ gateway => "10.0.0.1",
+ 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.100"],
+ },
+ {
+ subnet => "8888::/64",
+ gateway => "8888::100",
+ 'dhcp-range' => ["start-address=8888::100,end-address=8888::100"],
+ },
+ ],
);
run_test(
\&test_nic_join_full_dhcp_range,
"nic_join IPv4 no DHCP, dhcp-range full for IPv6",
- [{
- subnet => "10.0.0.0/24",
- gateway => "10.0.0.1",
- }, {
- subnet => "8888::/64",
- gateway => "8888::100",
- 'dhcp-range' => ["start-address=8888::100,end-address=8888::100"],
- }],
+ [
+ {
+ subnet => "10.0.0.0/24",
+ gateway => "10.0.0.1",
+ },
+ {
+ subnet => "8888::/64",
+ gateway => "8888::100",
+ 'dhcp-range' => ["start-address=8888::100,end-address=8888::100"],
+ },
+ ],
);
-
# -------------- nic_start
sub test_nic_start {
my ($test_name, $subnets, $current_ip4, $current_ip6, $num_expected_ips) = @_;
die "$test_name: we're expecting an array of subnets" if !$subnets;
my $num_subnets = scalar $subnets->@*;
- die "$test_name: we're expecting an array of subnets. $num_subnets elements found" if ($num_subnets < 1);
+ die "$test_name: we're expecting an array of subnets. $num_subnets elements found"
+ if ($num_subnets < 1);
$num_expected_ips = $num_subnets if !defined $num_expected_ips;
my $zoneid = "TESTZONE";
my $vnetid = "testvnet";
my $zone = create_zone({
- type => "simple",
- dhcp => "dnsmasq",
- ipam => "pve",
- zone => $zoneid,
+ type => "simple",
+ dhcp => "dnsmasq",
+ ipam => "pve",
+ zone => $zoneid,
});
my $vnet = create_vnet({
- type => "vnet",
- zone => $zoneid,
- vnet => $vnetid,
+ type => "vnet",
+ zone => $zoneid,
+ vnet => $vnetid,
});
foreach my $subnet ($subnets->@*) {
- $subnet->{type} = "subnet";
- $subnet->{vnet} = $vnetid;
- create_subnet($subnet);
- };
+ $subnet->{type} = "subnet";
+ $subnet->{vnet} = $vnetid;
+ create_subnet($subnet);
+ }
my $hostname = "testhostname";
my $mac = "da:65:8f:18:9b:6f";
my $vmid = "999";
if ($current_ip4) {
- create_ip({
- zone => $zoneid,
- vnet => $vnetid,
- mac => $mac,
- ip => $current_ip4,
- });
+ create_ip({
+ zone => $zoneid,
+ vnet => $vnetid,
+ mac => $mac,
+ ip => $current_ip4,
+ });
}
if ($current_ip6) {
- create_ip({
- zone => $zoneid,
- vnet => $vnetid,
- mac => $mac,
- ip => $current_ip6,
- });
+ create_ip({
+ zone => $zoneid,
+ vnet => $vnetid,
+ mac => $mac,
+ ip => $current_ip6,
+ });
}
my @current_ips = get_ips_from_mac($mac);
- is ( get_ip4(@current_ips), $current_ip4, "$test_name: setup current IPv4: $current_ip4" ) if defined $current_ip4;
- is ( get_ip6(@current_ips), $current_ip6, "$test_name: setup current IPv6: $current_ip6" ) if defined $current_ip6;
+ is(get_ip4(@current_ips), $current_ip4, "$test_name: setup current IPv4: $current_ip4")
+ if defined $current_ip4;
+ is(get_ip6(@current_ips), $current_ip6, "$test_name: setup current IPv6: $current_ip6")
+ if defined $current_ip6;
- eval {
- nic_start($vnetid, $mac, $hostname, $vmid);
- };
+ eval { nic_start($vnetid, $mac, $hostname, $vmid); };
if ($@) {
- fail("$test_name: $@");
- return;
+ fail("$test_name: $@");
+ return;
}
my @ips = get_ips_from_mac($mac);
my $num_ips = scalar @ips;
- is ($num_ips, $num_expected_ips, "$test_name: Expecting $num_expected_ips IPs, found $num_ips");
- ok ((all { ($_->{vnet} eq $vnetid && $_->{zone} eq $zoneid) } @ips),
- "$test_name: all IPs in correct vnet and zone"
+ is($num_ips, $num_expected_ips, "$test_name: Expecting $num_expected_ips IPs, found $num_ips");
+ ok(
+ (all { ($_->{vnet} eq $vnetid && $_->{zone} eq $zoneid) } @ips),
+ "$test_name: all IPs in correct vnet and zone",
);
- is ( get_ip4(@ips), $current_ip4, "$test_name: still current IPv4: $current_ip4" ) if $current_ip4;
- is ( get_ip6(@ips), $current_ip6, "$test_name: still current IPv6: $current_ip6" ) if $current_ip6;
+ is(get_ip4(@ips), $current_ip4, "$test_name: still current IPv4: $current_ip4") if $current_ip4;
+ is(get_ip6(@ips), $current_ip6, "$test_name: still current IPv6: $current_ip6") if $current_ip6;
}
run_test(
\&test_nic_start,
"nic_start no IP, IPv4 without dhcp",
- [{
- subnet => "10.0.0.0/24",
- gateway => "10.0.0.1",
- },
-]);
+ [
+ {
+ subnet => "10.0.0.0/24",
+ gateway => "10.0.0.1",
+ },
+ ],
+);
run_test(
\&test_nic_start,
"nic_start already IP, IPv4 without dhcp",
[{
- subnet => "10.0.0.0/24",
- gateway => "10.0.0.1",
+ subnet => "10.0.0.0/24",
+ gateway => "10.0.0.1",
}],
"10.0.0.99",
undef,
- 1
+ 1,
);
run_test(
\&test_nic_start,
"nic_start already IPv6, IPv6 without dhcp",
[{
- subnet => "8888::/64",
- gateway => "8888::1",
+ subnet => "8888::/64",
+ gateway => "8888::1",
}],
undef,
"8888::99",
- 1
+ 1,
);
run_test(
\&test_nic_start,
"nic_start no IP, IPv4 subnet with dhcp",
- [{
- subnet => "10.0.0.0/24",
- gateway => "10.0.0.1",
- 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.200"],
- },
-]);
+ [
+ {
+ subnet => "10.0.0.0/24",
+ gateway => "10.0.0.1",
+ 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.200"],
+ },
+ ],
+);
run_test(
\&test_nic_start,
"nic_start already IP, IPv4 subnet with dhcp",
[{
- subnet => "10.0.0.0/24",
- gateway => "10.0.0.1",
- 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.200"],
+ subnet => "10.0.0.0/24",
+ gateway => "10.0.0.1",
+ 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.200"],
}],
- "10.0.0.99"
+ "10.0.0.99",
);
run_test(
\&test_nic_start,
"nic_start already IP, IPv6 subnet with dhcp",
[{
- subnet => "8888::/64",
- gateway => "8888::1",
- 'dhcp-range' => ["start-address=8888::100,end-address=8888::200"],
+ subnet => "8888::/64",
+ gateway => "8888::1",
+ 'dhcp-range' => ["start-address=8888::100,end-address=8888::200"],
}],
undef,
- "8888::99"
+ "8888::99",
);
run_test(
\&test_nic_start,
"nic_start IP, IPv4+6 subnet with dhcp",
- [{
- subnet => "10.0.0.0/24",
- gateway => "10.0.0.1",
- 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.200"],
- }, {
- subnet => "8888::/64",
- gateway => "8888::1",
- 'dhcp-range' => ["start-address=8888::100,end-address=8888::200"],
- },
-]);
+ [
+ {
+ subnet => "10.0.0.0/24",
+ gateway => "10.0.0.1",
+ 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.200"],
+ },
+ {
+ subnet => "8888::/64",
+ gateway => "8888::1",
+ 'dhcp-range' => ["start-address=8888::100,end-address=8888::200"],
+ },
+ ],
+);
run_test(
\&test_nic_start,
"nic_start already IPv4, IPv4+6 subnet with dhcp",
- [{
- subnet => "10.0.0.0/24",
- gateway => "10.0.0.1",
- 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.200"],
- }, {
- subnet => "8888::/64",
- gateway => "8888::1",
- 'dhcp-range' => ["start-address=8888::100,end-address=8888::200"],
- }],
- "10.0.0.99"
+ [
+ {
+ subnet => "10.0.0.0/24",
+ gateway => "10.0.0.1",
+ 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.200"],
+ },
+ {
+ subnet => "8888::/64",
+ gateway => "8888::1",
+ 'dhcp-range' => ["start-address=8888::100,end-address=8888::200"],
+ },
+ ],
+ "10.0.0.99",
);
run_test(
\&test_nic_start,
"nic_start already IPv6, IPv4+6 subnet with dhcp",
- [{
- subnet => "10.0.0.0/24",
- gateway => "10.0.0.1",
- 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.200"],
- }, {
- subnet => "8888::/64",
- gateway => "8888::1",
- 'dhcp-range' => ["start-address=8888::100,end-address=8888::200"],
- }],
+ [
+ {
+ subnet => "10.0.0.0/24",
+ gateway => "10.0.0.1",
+ 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.200"],
+ },
+ {
+ subnet => "8888::/64",
+ gateway => "8888::1",
+ 'dhcp-range' => ["start-address=8888::100,end-address=8888::200"],
+ },
+ ],
undef,
- "8888::99"
+ "8888::99",
);
run_test(
\&test_nic_start,
"nic_start already IPv4+6, IPv4+6 subnets with dhcp",
- [{
- subnet => "10.0.0.0/24",
- gateway => "10.0.0.1",
- 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.200"],
- }, {
- subnet => "8888::/64",
- gateway => "8888::1",
- 'dhcp-range' => ["start-address=8888::100,end-address=8888::200"],
- }],
+ [
+ {
+ subnet => "10.0.0.0/24",
+ gateway => "10.0.0.1",
+ 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.200"],
+ },
+ {
+ subnet => "8888::/64",
+ gateway => "8888::1",
+ 'dhcp-range' => ["start-address=8888::100,end-address=8888::200"],
+ },
+ ],
"10.0.0.99",
- "8888::99"
+ "8888::99",
);
run_test(
\&test_nic_start,
"nic_start already IPv4+6, only IPv4 subnet with dhcp",
- [{
- subnet => "10.0.0.0/24",
- gateway => "10.0.0.1",
- 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.200"],
- }, {
- subnet => "8888::/64",
- gateway => "8888::1",
- }],
+ [
+ {
+ subnet => "10.0.0.0/24",
+ gateway => "10.0.0.1",
+ 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.200"],
+ },
+ {
+ subnet => "8888::/64",
+ gateway => "8888::1",
+ },
+ ],
"10.0.0.99",
"8888::99",
- 2
+ 2,
);
done_testing();
diff --git a/src/test/run_test_zones.pl b/src/test/run_test_zones.pl
index e506bea..86aa0ea 100755
--- a/src/test/run_test_zones.pl
+++ b/src/test/run_test_zones.pl
@@ -21,8 +21,8 @@ sub read_sdn_config {
open my $in, '<', $file or die $!;
my $sdn_config;
{
- local $/; # slurp mode
- $sdn_config = eval <$in>;
+ local $/; # slurp mode
+ $sdn_config = eval <$in>;
}
close $in;
@@ -42,88 +42,88 @@ foreach my $test (@tests) {
my $pve_common_inotify;
$pve_common_inotify = Test::MockModule->new('PVE::INotify');
$pve_common_inotify->mock(
- nodename => sub {
- return 'localhost';
- },
- read_file => sub {
- # HACK this assumes we are always calling PVE::INotify::read_file('interfaces');
- return $interfaces_config;
- },
- read_etc_network_interfaces => sub {
- return $interfaces_config;
- },
+ nodename => sub {
+ return 'localhost';
+ },
+ read_file => sub {
+ # HACK this assumes we are always calling PVE::INotify::read_file('interfaces');
+ return $interfaces_config;
+ },
+ read_etc_network_interfaces => sub {
+ return $interfaces_config;
+ },
);
my $mocked_pve_sdn_controllers;
$mocked_pve_sdn_controllers = Test::MockModule->new('PVE::Network::SDN::Controllers');
$mocked_pve_sdn_controllers->mock(
- read_etc_network_interfaces => sub {
- return $interfaces_config;
- }
+ read_etc_network_interfaces => sub {
+ return $interfaces_config;
+ },
);
my $pve_sdn_subnets;
$pve_sdn_subnets = Test::MockModule->new('PVE::Network::SDN::Subnets');
$pve_sdn_subnets->mock(
- config => sub {
- return $sdn_config->{subnets};
- },
+ config => sub {
+ return $sdn_config->{subnets};
+ },
);
my $pve_sdn_zones_plugin;
$pve_sdn_zones_plugin = Test::MockModule->new('PVE::Network::SDN::Zones::Plugin');
$pve_sdn_zones_plugin->mock(
- get_local_route_ip => sub {
- my $outiface = "vmbr0";
- my $outip = $interfaces_config->{ifaces}->{$outiface}->{address};
- return ($outip, $outiface);
- },
- is_vlanaware => sub {
- return $interfaces_config->{ifaces}->{vmbr0}->{'bridge_vlan_aware'};
- },
- is_ovs => sub {
- return 1 if $interfaces_config->{ifaces}->{vmbr0}->{'type'} eq 'OVSBridge';
- },
- get_bridge_ifaces => sub {
- return ('eth0');
- },
- find_bridge => sub {
- return;
- },
+ get_local_route_ip => sub {
+ my $outiface = "vmbr0";
+ my $outip = $interfaces_config->{ifaces}->{$outiface}->{address};
+ return ($outip, $outiface);
+ },
+ is_vlanaware => sub {
+ return $interfaces_config->{ifaces}->{vmbr0}->{'bridge_vlan_aware'};
+ },
+ is_ovs => sub {
+ return 1 if $interfaces_config->{ifaces}->{vmbr0}->{'type'} eq 'OVSBridge';
+ },
+ get_bridge_ifaces => sub {
+ return ('eth0');
+ },
+ find_bridge => sub {
+ return;
+ },
);
my $sdn_module = Test::MockModule->new("PVE::Network::SDN");
$sdn_module->mock(
- running_config => sub {
- return $sdn_config;
- },
+ running_config => sub {
+ return $sdn_config;
+ },
);
my $pve_sdn_controllers_plugin;
$pve_sdn_controllers_plugin = Test::MockModule->new('PVE::Network::SDN::Controllers::Plugin');
$pve_sdn_controllers_plugin->mock(
- read_iface_mac => sub {
- return "bc:24:11:1d:69:60";
- },
+ read_iface_mac => sub {
+ return "bc:24:11:1d:69:60";
+ },
);
- my ($first_plugin) = %{$sdn_config->{controllers}->{ids}} if defined $sdn_config->{controllers};
+ my ($first_plugin) = %{ $sdn_config->{controllers}->{ids} }
+ if defined $sdn_config->{controllers};
if ($first_plugin) {
- my $controller_plugin = PVE::Network::SDN::Controllers::Plugin->lookup(
- $sdn_config->{controllers}->{ids}->{$first_plugin}->{type}
- );
- my $mocked_controller_plugin = Test::MockModule->new($controller_plugin);
- $mocked_controller_plugin->mock(
- write_controller_config => sub {
- return;
- },
- reload_controller => sub {
- return;
- },
- read_local_frr_config => sub {
- return;
- },
- );
+ my $controller_plugin = PVE::Network::SDN::Controllers::Plugin->lookup(
+ $sdn_config->{controllers}->{ids}->{$first_plugin}->{type});
+ my $mocked_controller_plugin = Test::MockModule->new($controller_plugin);
+ $mocked_controller_plugin->mock(
+ write_controller_config => sub {
+ return;
+ },
+ reload_controller => sub {
+ return;
+ },
+ read_local_frr_config => sub {
+ return;
+ },
+ );
}
my $name = $test;
@@ -132,27 +132,27 @@ foreach my $test (@tests) {
my $result = eval { PVE::Network::SDN::Zones::generate_etc_network_config() };
if (my $err = $@) {
- diag("got unexpected error - $err");
- fail($name);
+ diag("got unexpected error - $err");
+ fail($name);
} else {
- is($result, $expected, $name);
+ is($result, $expected, $name);
}
if ($sdn_config->{controllers}) {
- my $expected = read_file("./$test/expected_controller_config");
- my $controller_rawconfig = "";
-
- eval {
- my $config = PVE::Network::SDN::Controllers::generate_controller_config();
- $controller_rawconfig =
- PVE::Network::SDN::Controllers::generate_controller_rawconfig($config);
- };
- if (my $err = $@) {
- diag("got unexpected error - $err");
- fail($name);
- } else {
- is($controller_rawconfig, $expected, $name);
- }
+ my $expected = read_file("./$test/expected_controller_config");
+ my $controller_rawconfig = "";
+
+ eval {
+ my $config = PVE::Network::SDN::Controllers::generate_controller_config();
+ $controller_rawconfig =
+ PVE::Network::SDN::Controllers::generate_controller_rawconfig($config);
+ };
+ if (my $err = $@) {
+ diag("got unexpected error - $err");
+ fail($name);
+ } else {
+ is($controller_rawconfig, $expected, $name);
+ }
}
}