From 4140be9e7918d97f8b0a5da7856714dbd61ea083 Mon Sep 17 00:00:00 2001 From: Alexandre Derumier Date: Tue, 26 Nov 2019 10:00:17 +0100 Subject: [PATCH] api2 : split vnets/zones/controllers Signed-off-by: Alexandre Derumier --- PVE/API2/Network/Makefile | 1 - PVE/API2/Network/SDN.pm | 310 +++----------------- PVE/API2/Network/SDN/Controllers.pm | 288 ++++++++++++++++++ PVE/API2/Network/SDN/Makefile | 4 +- PVE/API2/Network/SDN/Vnets.pm | 265 +++++++++++++++++ PVE/API2/Network/SDN/Zones.pm | 291 ++++++++++++++++++ PVE/API2/Network/SDN/{ => Zones}/Content.pm | 8 +- PVE/API2/Network/SDN/Zones/Makefile | 8 + PVE/API2/Network/SDN/{ => Zones}/Status.pm | 18 +- 9 files changed, 903 insertions(+), 290 deletions(-) create mode 100644 PVE/API2/Network/SDN/Controllers.pm create mode 100644 PVE/API2/Network/SDN/Vnets.pm create mode 100644 PVE/API2/Network/SDN/Zones.pm rename PVE/API2/Network/SDN/{ => Zones}/Content.pm (88%) create mode 100644 PVE/API2/Network/SDN/Zones/Makefile rename PVE/API2/Network/SDN/{ => Zones}/Status.pm (83%) diff --git a/PVE/API2/Network/Makefile b/PVE/API2/Network/Makefile index 80a3b25..396f79d 100644 --- a/PVE/API2/Network/Makefile +++ b/PVE/API2/Network/Makefile @@ -7,4 +7,3 @@ PERL5DIR=${DESTDIR}/usr/share/perl5 install: for i in ${SOURCES}; do install -D -m 0644 $$i ${PERL5DIR}/PVE/API2/Network/$$i; done make -C SDN install - diff --git a/PVE/API2/Network/SDN.pm b/PVE/API2/Network/SDN.pm index b6dd23e..512e0b2 100644 --- a/PVE/API2/Network/SDN.pm +++ b/PVE/API2/Network/SDN.pm @@ -4,306 +4,66 @@ use strict; use warnings; use PVE::SafeSyslog; -use PVE::Tools qw(extract_param); -use PVE::Cluster qw(cfs_read_file cfs_write_file); -use PVE::Network::SDN; -use PVE::Network::SDN::Plugin; -use PVE::Network::SDN::VlanPlugin; -use PVE::Network::SDN::VxlanPlugin; -use PVE::Network::SDN::VnetPlugin; -use PVE::Network::SDN::FaucetControllerPlugin; -use PVE::Network::SDN::FaucetPlugin; -use PVE::Network::SDN::EvpnControllerPlugin; -use PVE::Network::SDN::EvpnPlugin; -use PVE::Network::SDN::QinQPlugin; - -use Storable qw(dclone); -use PVE::JSONSchema qw(get_standard_option); -use PVE::RPCEnvironment; - +use PVE::Tools; +use PVE::Cluster qw(cfs_lock_file cfs_read_file cfs_write_file); use PVE::RESTHandler; +use PVE::RPCEnvironment; +use PVE::JSONSchema qw(get_standard_option); +use PVE::Exception qw(raise_param_exc); +use PVE::API2::Network::SDN::Vnets; +use PVE::API2::Network::SDN::Zones; +use PVE::API2::Network::SDN::Controllers; use base qw(PVE::RESTHandler); -my $sdn_type_enum = PVE::Network::SDN::Plugin->lookup_types(); - -my $api_sdn_config = sub { - my ($cfg, $sdnid) = @_; - - my $scfg = dclone(PVE::Network::SDN::sdn_config($cfg, $sdnid)); - $scfg->{sdn} = $sdnid; - $scfg->{digest} = $cfg->{digest}; +__PACKAGE__->register_method ({ + subclass => "PVE::API2::Network::SDN::Vnets", + path => 'vnets', + }); - return $scfg; -}; +__PACKAGE__->register_method ({ + subclass => "PVE::API2::Network::SDN::Zones", + path => 'zones', + }); __PACKAGE__->register_method ({ - name => 'index', - path => '', + subclass => "PVE::API2::Network::SDN::Controllers", + path => 'controllers', +}); + +__PACKAGE__->register_method({ + name => 'index', + path => '', method => 'GET', - description => "SDN index.", + description => "Directory index.", permissions => { - description => "Only list entries where you have 'SDN.Audit' or 'SDN.Allocate' permissions on '/cluster/sdn/'", - user => 'all', + check => ['perm', '/', [ 'Sys.Audit' ]], }, parameters => { additionalProperties => 0, - properties => { - type => { - description => "Only list sdn of specific type", - type => 'string', - enum => $sdn_type_enum, - optional => 1, - }, - }, + properties => {}, }, returns => { type => 'array', items => { type => "object", - properties => { sdn => { type => 'string'}, - type => { type => 'string'}, - role => { type => 'string'} - }, + properties => { + id => { type => 'string' }, + }, }, - links => [ { rel => 'child', href => "{sdn}" } ], + links => [ { rel => 'child', href => "{id}" } ], }, code => sub { my ($param) = @_; - my $rpcenv = PVE::RPCEnvironment::get(); - my $authuser = $rpcenv->get_user(); - - - my $cfg = PVE::Network::SDN::config(); - - my @sids = PVE::Network::SDN::sdn_ids($cfg); - my $res = []; - foreach my $sdnid (@sids) { -# my $privs = [ 'SDN.Audit', 'SDN.Allocate' ]; -# next if !$rpcenv->check_any($authuser, "/cluster/sdn/$sdnid", $privs, 1); - - my $scfg = &$api_sdn_config($cfg, $sdnid); - next if $param->{type} && $param->{type} ne $scfg->{type}; - - my $plugin_config = $cfg->{ids}->{$sdnid}; - my $plugin = PVE::Network::SDN::Plugin->lookup($plugin_config->{type}); - my $pd = $plugin->plugindata(); - my $role = $pd->{role}; - $scfg->{role} = $role; - push @$res, $scfg; - } + my $res = [ + { id => 'vnets' }, + { id => 'zones' }, + { id => 'controllers' }, + ]; return $res; }}); -__PACKAGE__->register_method ({ - name => 'read', - path => '{sdn}', - method => 'GET', - description => "Read sdn configuration.", -# permissions => { -# check => ['perm', '/cluster/sdn/{sdn}', ['SDN.Allocate']], -# }, - - parameters => { - additionalProperties => 0, - properties => { - sdn => get_standard_option('pve-sdn-id'), - }, - }, - returns => { type => 'object' }, - code => sub { - my ($param) = @_; - - my $cfg = PVE::Network::SDN::config(); - - return &$api_sdn_config($cfg, $param->{sdn}); - }}); - -__PACKAGE__->register_method ({ - name => 'create', - protected => 1, - path => '', - method => 'POST', - description => "Create a new sdn object.", -# permissions => { -# check => ['perm', '/cluster/sdn', ['SDN.Allocate']], -# }, - parameters => PVE::Network::SDN::Plugin->createSchema(), - returns => { type => 'null' }, - code => sub { - my ($param) = @_; - - my $type = extract_param($param, 'type'); - my $sdnid = extract_param($param, 'sdn'); - - my $plugin = PVE::Network::SDN::Plugin->lookup($type); - my $opts = $plugin->check_config($sdnid, $param, 1, 1); - - PVE::Network::SDN::lock_sdn_config( - sub { - - my $cfg = PVE::Network::SDN::config(); - - my $scfg = undef; - if ($scfg = PVE::Network::SDN::sdn_config($cfg, $sdnid, 1)) { - die "sdn object ID '$sdnid' already defined\n"; - } - - $cfg->{ids}->{$sdnid} = $opts; - $plugin->on_update_hook($sdnid, $cfg); - #also verify transport associated to vnet - if($scfg && $scfg->{type} eq 'vnet') { - my $transportid = $scfg->{transportzone}; - die "missing transportzone" if !$transportid; - my $transport_cfg = $cfg->{ids}->{$transportid}; - my $transport_plugin = PVE::Network::SDN::Plugin->lookup($transport_cfg->{type}); - $transport_plugin->on_update_hook($transportid, $cfg); - } - - PVE::Network::SDN::write_config($cfg); - - }, "create sdn object failed"); - - return undef; - }}); - -__PACKAGE__->register_method ({ - name => 'apply_configuration', - protected => 1, - path => '', - method => 'PUT', - description => "Apply sdn changes.", -# permissions => { -# check => ['perm', '/cluster/sdn', ['SDN.Allocate']], -# }, - parameters => { - additionalProperties => 0, - }, - returns => { type => 'null' }, - code => sub { - my ($param) = @_; - - die "no sdn changes to apply" if !-e "/etc/pve/sdn.cfg.new"; - rename("/etc/pve/sdn.cfg.new", "/etc/pve/sdn.cfg") - || die "applying sdn.cfg changes failed - $!\n"; - - - return undef; - }}); - -__PACKAGE__->register_method ({ - name => 'revert_configuration', - protected => 1, - path => '', - method => 'DELETE', - description => "Revert sdn changes.", -# permissions => { -# check => ['perm', '/cluster/sdn', ['SDN.Allocate']], -# }, - parameters => { - additionalProperties => 0, - }, - returns => { type => 'null' }, - code => sub { - my ($param) = @_; - - die "no sdn changes to revert" if !-e "/etc/pve/sdn.cfg.new"; - unlink "/etc/pve/sdn.cfg.new"; - - return undef; - }}); - -__PACKAGE__->register_method ({ - name => 'update', - protected => 1, - path => '{sdn}', - method => 'PUT', - description => "Update sdn object configuration.", -# permissions => { -# check => ['perm', '/cluster/sdn', ['SDN.Allocate']], -# }, - parameters => PVE::Network::SDN::Plugin->updateSchema(), - returns => { type => 'null' }, - code => sub { - my ($param) = @_; - - my $sdnid = extract_param($param, 'sdn'); - my $digest = extract_param($param, 'digest'); - - PVE::Network::SDN::lock_sdn_config( - sub { - - my $cfg = PVE::Network::SDN::config(); - - PVE::SectionConfig::assert_if_modified($cfg, $digest); - - my $scfg = PVE::Network::SDN::sdn_config($cfg, $sdnid); - - my $plugin = PVE::Network::SDN::Plugin->lookup($scfg->{type}); - my $opts = $plugin->check_config($sdnid, $param, 0, 1); - - foreach my $k (%$opts) { - $scfg->{$k} = $opts->{$k}; - } - - $plugin->on_update_hook($sdnid, $cfg); - #also verify transport associated to vnet - if($scfg->{type} eq 'vnet') { - my $transportid = $scfg->{transportzone}; - die "missing transportzone" if !$transportid; - my $transport_cfg = $cfg->{ids}->{$transportid}; - my $transport_plugin = PVE::Network::SDN::Plugin->lookup($transport_cfg->{type}); - $transport_plugin->on_update_hook($transportid, $cfg); - } - PVE::Network::SDN::write_config($cfg); - - }, "update sdn object failed"); - - return undef; - }}); - -__PACKAGE__->register_method ({ - name => 'delete', - protected => 1, - path => '{sdn}', - method => 'DELETE', - description => "Delete sdn object configuration.", -# permissions => { -# check => ['perm', '/cluster/sdn', ['SDN.Allocate']], -# }, - parameters => { - additionalProperties => 0, - properties => { - sdn => get_standard_option('pve-sdn-id', { - completion => \&PVE::Network::SDN::complete_sdn, - }), - }, - }, - returns => { type => 'null' }, - code => sub { - my ($param) = @_; - - my $sdnid = extract_param($param, 'sdn'); - - PVE::Network::SDN::lock_sdn_config( - sub { - - my $cfg = PVE::Network::SDN::config(); - - my $scfg = PVE::Network::SDN::sdn_config($cfg, $sdnid); - - my $plugin = PVE::Network::SDN::Plugin->lookup($scfg->{type}); - $plugin->on_delete_hook($sdnid, $cfg); - - delete $cfg->{ids}->{$sdnid}; - PVE::Network::SDN::write_config($cfg); - - }, "delete sdn object failed"); - - - return undef; - }}); 1; diff --git a/PVE/API2/Network/SDN/Controllers.pm b/PVE/API2/Network/SDN/Controllers.pm new file mode 100644 index 0000000..99fd138 --- /dev/null +++ b/PVE/API2/Network/SDN/Controllers.pm @@ -0,0 +1,288 @@ +package PVE::API2::Network::SDN::Controllers; + +use strict; +use warnings; + +use PVE::SafeSyslog; +use PVE::Tools qw(extract_param); +use PVE::Cluster qw(cfs_read_file cfs_write_file); +use PVE::Network::SDN::Zones; +use PVE::Network::SDN::Controllers; +use PVE::Network::SDN::Controllers::Plugin; +use PVE::Network::SDN::Controllers::FrrEvpnPlugin; +use PVE::Network::SDN::Controllers::FaucetPlugin; + +use Storable qw(dclone); +use PVE::JSONSchema qw(get_standard_option); +use PVE::RPCEnvironment; + +use PVE::RESTHandler; + +use base qw(PVE::RESTHandler); + +my $sdn_controllers_type_enum = PVE::Network::SDN::Controllers::Plugin->lookup_types(); + +my $api_sdn_controllers_config = sub { + my ($cfg, $id) = @_; + + my $scfg = dclone(PVE::Network::SDN::Controllers::sdn_controllers_config($cfg, $id)); + $scfg->{controller} = $id; + $scfg->{digest} = $cfg->{digest}; + + return $scfg; +}; + +__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 '/cluster/sdn/controllers/'", + user => 'all', + }, + parameters => { + additionalProperties => 0, + properties => { + type => { + description => "Only list sdn controllers of specific type", + type => 'string', + enum => $sdn_controllers_type_enum, + optional => 1, + }, + }, + }, + returns => { + type => 'array', + items => { + type => "object", + properties => { controller => { type => 'string'}, + type => { type => 'string'}, + }, + }, + links => [ { rel => 'child', href => "{controller}" } ], + }, + code => sub { + my ($param) = @_; + + my $rpcenv = PVE::RPCEnvironment::get(); + my $authuser = $rpcenv->get_user(); + + + my $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, "/cluster/sdn/controllers/$id", $privs, 1); + + 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; + } + + return $res; + }}); + +__PACKAGE__->register_method ({ + name => 'read', + path => '{controller}', + method => 'GET', + description => "Read sdn controller configuration.", +# permissions => { +# check => ['perm', '/cluster/sdn/controllers/{controller}', ['SDN.Allocate']], +# }, + + parameters => { + additionalProperties => 0, + properties => { + controller => get_standard_option('pve-sdn-controller-id'), + }, + }, + returns => { type => 'object' }, + code => sub { + my ($param) = @_; + + my $cfg = PVE::Network::SDN::Controllers::config(); + + return &$api_sdn_controllers_config($cfg, $param->{controller}); + }}); + +__PACKAGE__->register_method ({ + name => 'create', + protected => 1, + path => '', + method => 'POST', + description => "Create a new sdn controller object.", +# permissions => { +# check => ['perm', '/cluster/sdn/controllers', ['SDN.Allocate']], +# }, + parameters => PVE::Network::SDN::Controllers::Plugin->createSchema(), + returns => { type => 'null' }, + code => sub { + my ($param) = @_; + + 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); + + PVE::Network::SDN::Controllers::lock_sdn_controllers_config( + sub { + + my $cfg = PVE::Network::SDN::Controllers::config(); + + my $scfg = undef; + if ($scfg = PVE::Network::SDN::Controllers::sdn_controllers_config($cfg, $id, 1)) { + die "sdn controller object ID '$id' already defined\n"; + } + + $cfg->{ids}->{$id} = $opts; + $plugin->on_update_hook($id, $cfg); + + PVE::Network::SDN::Controllers::write_config($cfg); + + }, "create sdn controller object failed"); + + return undef; + }}); + +__PACKAGE__->register_method ({ + name => 'apply_configuration', + protected => 1, + path => '', + method => 'PUT', + description => "Apply sdn controller changes.", +# permissions => { +# check => ['perm', '/cluster/sdn/controllers', ['SDN.Allocate']], +# }, + parameters => { + additionalProperties => 0, + }, + returns => { type => 'null' }, + code => sub { + my ($param) = @_; + + die "no sdn controller changes to apply" if !-e "/etc/pve/sdn/controllers.cfg.new"; + rename("/etc/pve/sdn/controllers.cfg.new", "/etc/pve/sdn/controllers.cfg") + || die "applying sdn/controllers.cfg changes failed - $!\n"; + + + return undef; + }}); + +__PACKAGE__->register_method ({ + name => 'revert_configuration', + protected => 1, + path => '', + method => 'DELETE', + description => "Revert sdn controller changes.", +# permissions => { +# check => ['perm', '/cluster/sdn/controllers', ['SDN.Allocate']], +# }, + parameters => { + additionalProperties => 0, + }, + returns => { type => 'null' }, + code => sub { + my ($param) = @_; + + die "no sdn controllers changes to revert" if !-e "/etc/pve/sdn/controllers.cfg.new"; + unlink "/etc/pve/sdn/controllers.cfg.new"; + + return undef; + }}); + +__PACKAGE__->register_method ({ + name => 'update', + protected => 1, + path => '{controller}', + method => 'PUT', + description => "Update sdn controller object configuration.", +# permissions => { +# check => ['perm', '/cluster/sdn/controllers', ['SDN.Allocate']], +# }, + parameters => PVE::Network::SDN::Controllers::Plugin->updateSchema(), + returns => { type => 'null' }, + code => sub { + my ($param) = @_; + + my $id = extract_param($param, 'controller'); + my $digest = extract_param($param, 'digest'); + + PVE::Network::SDN::Controllers::lock_sdn_controllers_config( + sub { + + my $cfg = PVE::Network::SDN::Controllers::config(); + + PVE::SectionConfig::assert_if_modified($cfg, $digest); + + my $scfg = PVE::Network::SDN::Controllers::sdn_controllers_config($cfg, $id); + + my $plugin = PVE::Network::SDN::Controllers::Plugin->lookup($scfg->{type}); + my $opts = $plugin->check_config($id, $param, 0, 1); + + foreach my $k (%$opts) { + $scfg->{$k} = $opts->{$k}; + } + + $plugin->on_update_hook($id, $cfg); + + PVE::Network::SDN::Controllers::write_config($cfg); + + }, "update sdn controller object failed"); + + return undef; + }}); + +__PACKAGE__->register_method ({ + name => 'delete', + protected => 1, + path => '{controller}', + method => 'DELETE', + description => "Delete sdn controller object configuration.", +# permissions => { +# check => ['perm', '/cluster/sdn/controllers', ['SDN.Allocate']], +# }, + parameters => { + 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 $id = extract_param($param, 'controller'); + + PVE::Network::SDN::Controllers::lock_sdn_controllers_config( + sub { + + my $cfg = PVE::Network::SDN::Controllers::config(); + + my $scfg = PVE::Network::SDN::Controllers::sdn_controllers_config($cfg, $id); + + my $plugin = PVE::Network::SDN::Controllers::Plugin->lookup($scfg->{type}); + + my $transport_cfg = PVE::Network::SDN::Zones::config(); + + $plugin->on_delete_hook($id, $transport_cfg); + + delete $cfg->{ids}->{$id}; + PVE::Network::SDN::Controllers::write_config($cfg); + + }, "delete sdn controller object failed"); + + + return undef; + }}); + +1; diff --git a/PVE/API2/Network/SDN/Makefile b/PVE/API2/Network/SDN/Makefile index 9fa8cb0..6f20d4a 100644 --- a/PVE/API2/Network/SDN/Makefile +++ b/PVE/API2/Network/SDN/Makefile @@ -1,4 +1,4 @@ -SOURCES=Content.pm Status.pm +SOURCES=Vnets.pm Zones.pm Controllers.pm PERL5DIR=${DESTDIR}/usr/share/perl5 @@ -6,3 +6,5 @@ PERL5DIR=${DESTDIR}/usr/share/perl5 .PHONY: install install: for i in ${SOURCES}; do install -D -m 0644 $$i ${PERL5DIR}/PVE/API2/Network/SDN/$$i; done + make -C Zones install + diff --git a/PVE/API2/Network/SDN/Vnets.pm b/PVE/API2/Network/SDN/Vnets.pm new file mode 100644 index 0000000..0526b06 --- /dev/null +++ b/PVE/API2/Network/SDN/Vnets.pm @@ -0,0 +1,265 @@ +package PVE::API2::Network::SDN::Vnets; + +use strict; +use warnings; + +use PVE::SafeSyslog; +use PVE::Tools qw(extract_param); +use PVE::Cluster qw(cfs_read_file cfs_write_file); +use PVE::Network::SDN::Vnets; +use PVE::Network::SDN::VnetPlugin; + +use Storable qw(dclone); +use PVE::JSONSchema qw(get_standard_option); +use PVE::RPCEnvironment; + +use PVE::RESTHandler; + +use base qw(PVE::RESTHandler); + +my $api_sdn_vnets_config = sub { + my ($cfg, $id) = @_; + + my $scfg = dclone(PVE::Network::SDN::Vnets::sdn_vnets_config($cfg, $id)); + $scfg->{vnet} = $id; + $scfg->{digest} = $cfg->{digest}; + + return $scfg; +}; + +__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 '/cluster/sdn/vnets/'", + user => 'all', + }, + parameters => { + additionalProperties => 0, + }, + returns => { + 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 = 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' ]; +# next if !$rpcenv->check_any($authuser, "/cluster/sdn/vnets/$id", $privs, 1); + + my $scfg = &$api_sdn_vnets_config($cfg, $id); + push @$res, $scfg; + } + + return $res; + }}); + +__PACKAGE__->register_method ({ + name => 'read', + path => '{vnet}', + method => 'GET', + description => "Read sdn vnet configuration.", +# permissions => { +# check => ['perm', '/cluster/sdn/vnets/{vnet}', ['SDN.Allocate']], +# }, + + parameters => { + additionalProperties => 0, + properties => { + vnet => get_standard_option('pve-sdn-vnet-id', { + completion => \&PVE::Network::SDN::Vnets::complete_sdn_vnets, + }), + }, + }, + returns => { type => 'object' }, + code => sub { + my ($param) = @_; + + my $cfg = PVE::Network::SDN::Vnets::config(); + + return &$api_sdn_vnets_config($cfg, $param->{vnet}); + }}); + +__PACKAGE__->register_method ({ + name => 'create', + protected => 1, + path => '', + method => 'POST', + description => "Create a new sdn vnet object.", +# permissions => { +# check => ['perm', '/cluster/sdn/vnets', ['SDN.Allocate']], +# }, + parameters => PVE::Network::SDN::VnetPlugin->createSchema(), + returns => { type => 'null' }, + code => sub { + my ($param) = @_; + + my $type = extract_param($param, 'type'); + my $id = extract_param($param, 'vnet'); + + PVE::Network::SDN::Vnets::lock_sdn_vnets_config( + sub { + + my $cfg = PVE::Network::SDN::Vnets::config(); + my $opts = PVE::Network::SDN::VnetPlugin->check_config($id, $param, 1, 1); + + my $scfg = undef; + if ($scfg = PVE::Network::SDN::Vnets::sdn_vnets_config($cfg, $id, 1)) { + die "sdn vnet object ID '$id' already defined\n"; + } + + $cfg->{ids}->{$id} = $opts; + PVE::Network::SDN::VnetPlugin->on_update_hook($id, $cfg); + + PVE::Network::SDN::Vnets::write_config($cfg); + + }, "create sdn vnet object failed"); + + return undef; + }}); + +__PACKAGE__->register_method ({ + name => 'apply_configuration', + protected => 1, + path => '', + method => 'PUT', + description => "Apply sdn vnet changes.", +# permissions => { +# check => ['perm', '/cluster/sdn/vnets', ['SDN.Allocate']], +# }, + parameters => { + additionalProperties => 0, + }, + returns => { type => 'null' }, + code => sub { + my ($param) = @_; + + die "no sdn vnet changes to apply" if !-e "/etc/pve/sdn/vnets.cfg.new"; + rename("/etc/pve/sdn/vnets.cfg.new", "/etc/pve/sdn/vnets.cfg") + || die "applying sdn/vnets.cfg changes failed - $!\n"; + + + return undef; + }}); + +__PACKAGE__->register_method ({ + name => 'revert_configuration', + protected => 1, + path => '', + method => 'DELETE', + description => "Revert sdn vnet changes.", +# permissions => { +# check => ['perm', '/cluster/sdn/vnets', ['SDN.Allocate']], +# }, + parameters => { + additionalProperties => 0, + }, + returns => { type => 'null' }, + code => sub { + my ($param) = @_; + + die "no sdn vnets changes to revert" if !-e "/etc/pve/sdn/vnets.cfg.new"; + unlink "/etc/pve/sdn/vnets.cfg.new"; + + return undef; + }}); + +__PACKAGE__->register_method ({ + name => 'update', + protected => 1, + path => '{vnet}', + method => 'PUT', + description => "Update sdn vnet object configuration.", +# permissions => { +# check => ['perm', '/cluster/sdn/vnets', ['SDN.Allocate']], +# }, + parameters => PVE::Network::SDN::VnetPlugin->updateSchema(), + returns => { type => 'null' }, + code => sub { + my ($param) = @_; + + my $id = extract_param($param, 'vnet'); + my $digest = extract_param($param, 'digest'); + + PVE::Network::SDN::Vnets::lock_sdn_vnets_config( + sub { + + my $cfg = PVE::Network::SDN::Vnets::config(); + + PVE::SectionConfig::assert_if_modified($cfg, $digest); + + my $scfg = PVE::Network::SDN::Vnets::sdn_vnets_config($cfg, $id); + my $opts = PVE::Network::SDN::VnetPlugin->check_config($id, $param, 0, 1); + + foreach my $k (%$opts) { + $scfg->{$k} = $opts->{$k}; + } + + PVE::Network::SDN::VnetPlugin->on_update_hook($id, $cfg); + + PVE::Network::SDN::Vnets::write_config($cfg); + + }, "update sdn vnet object failed"); + + return undef; + }}); + +__PACKAGE__->register_method ({ + name => 'delete', + protected => 1, + path => '{vnet}', + method => 'DELETE', + description => "Delete sdn vnet object configuration.", +# permissions => { +# check => ['perm', '/cluster/sdn/vnets', ['SDN.Allocate']], +# }, + parameters => { + 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'); + + PVE::Network::SDN::Vnets::lock_sdn_vnets_config( + sub { + + my $cfg = PVE::Network::SDN::Vnets::config(); + + my $scfg = PVE::Network::SDN::Vnets::sdn_vnets_config($cfg, $id); + + my $vnet_cfg = PVE::Network::SDN::Vnets::config(); + + PVE::Network::SDN::VnetPlugin->on_delete_hook($id, $vnet_cfg); + + delete $cfg->{ids}->{$id}; + PVE::Network::SDN::Vnets::write_config($cfg); + + }, "delete sdn vnet object failed"); + + + return undef; + }}); + +1; diff --git a/PVE/API2/Network/SDN/Zones.pm b/PVE/API2/Network/SDN/Zones.pm new file mode 100644 index 0000000..a447813 --- /dev/null +++ b/PVE/API2/Network/SDN/Zones.pm @@ -0,0 +1,291 @@ +package PVE::API2::Network::SDN::Zones; + +use strict; +use warnings; + +use PVE::SafeSyslog; +use PVE::Tools qw(extract_param); +use PVE::Cluster qw(cfs_read_file cfs_write_file); +use PVE::Network::SDN::Vnets; +use PVE::Network::SDN::Zones; +use PVE::Network::SDN::Zones::Plugin; +use PVE::Network::SDN::Zones::VlanPlugin; +use PVE::Network::SDN::Zones::QinQPlugin; +use PVE::Network::SDN::Zones::VxlanPlugin; +use PVE::Network::SDN::Zones::EvpnPlugin; +use PVE::Network::SDN::Zones::FaucetPlugin; + +use Storable qw(dclone); +use PVE::JSONSchema qw(get_standard_option); +use PVE::RPCEnvironment; + +use PVE::RESTHandler; + +use base qw(PVE::RESTHandler); + +my $sdn_zones_type_enum = PVE::Network::SDN::Zones::Plugin->lookup_types(); + +my $api_sdn_zones_config = sub { + my ($cfg, $id) = @_; + + my $scfg = dclone(PVE::Network::SDN::Zones::sdn_zones_config($cfg, $id)); + $scfg->{zone} = $id; + $scfg->{digest} = $cfg->{digest}; + + return $scfg; +}; + +__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 '/cluster/sdn/zones/'", + user => 'all', + }, + parameters => { + additionalProperties => 0, + properties => { + type => { + description => "Only list sdn zones of specific type", + type => 'string', + enum => $sdn_zones_type_enum, + optional => 1, + }, + }, + }, + returns => { + type => 'array', + items => { + type => "object", + properties => { zone => { type => 'string'}, + type => { type => 'string'}, + }, + }, + links => [ { rel => 'child', href => "{zone}" } ], + }, + code => sub { + my ($param) = @_; + + my $rpcenv = PVE::RPCEnvironment::get(); + my $authuser = $rpcenv->get_user(); + + + my $cfg = PVE::Network::SDN::Zones::config(); + + my @sids = PVE::Network::SDN::Zones::sdn_zones_ids($cfg); + my $res = []; + foreach my $id (@sids) { +# my $privs = [ 'SDN.Audit', 'SDN.Allocate' ]; +# next if !$rpcenv->check_any($authuser, "/cluster/sdn/zones/$id", $privs, 1); + + 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; + } + + return $res; + }}); + +__PACKAGE__->register_method ({ + name => 'read', + path => '{zone}', + method => 'GET', + description => "Read sdn zone configuration.", +# permissions => { +# check => ['perm', '/cluster/sdn/zones/{zone}', ['SDN.Allocate']], +# }, + + parameters => { + additionalProperties => 0, + properties => { + zone => get_standard_option('pve-sdn-zone-id'), + }, + }, + returns => { type => 'object' }, + code => sub { + my ($param) = @_; + + my $cfg = PVE::Network::SDN::Zones::config(); + + return &$api_sdn_zones_config($cfg, $param->{zone}); + }}); + +__PACKAGE__->register_method ({ + name => 'create', + protected => 1, + path => '', + method => 'POST', + description => "Create a new sdn zone object.", +# permissions => { +# check => ['perm', '/cluster/sdn/zones', ['SDN.Allocate']], +# }, + parameters => PVE::Network::SDN::Zones::Plugin->createSchema(), + returns => { type => 'null' }, + code => sub { + my ($param) = @_; + + 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); + + PVE::Network::SDN::Zones::lock_sdn_zones_config( + sub { + + my $cfg = PVE::Network::SDN::Zones::config(); + + my $scfg = undef; + if ($scfg = PVE::Network::SDN::Zones::sdn_zones_config($cfg, $id, 1)) { + die "sdn zone object ID '$id' already defined\n"; + } + + $cfg->{ids}->{$id} = $opts; + $plugin->on_update_hook($id, $cfg); + + PVE::Network::SDN::Zones::write_config($cfg); + + }, "create sdn zone object failed"); + + return undef; + }}); + +__PACKAGE__->register_method ({ + name => 'apply_configuration', + protected => 1, + path => '', + method => 'PUT', + description => "Apply sdn zone changes.", +# permissions => { +# check => ['perm', '/cluster/sdn/zones', ['SDN.Allocate']], +# }, + parameters => { + additionalProperties => 0, + }, + returns => { type => 'null' }, + code => sub { + my ($param) = @_; + + die "no sdn zone changes to apply" if !-e "/etc/pve/sdn/zones.cfg.new"; + rename("/etc/pve/sdn/zones.cfg.new", "/etc/pve/sdn/zones.cfg") + || die "applying sdn/zones.cfg changes failed - $!\n"; + + + return undef; + }}); + +__PACKAGE__->register_method ({ + name => 'revert_configuration', + protected => 1, + path => '', + method => 'DELETE', + description => "Revert sdn zone changes.", +# permissions => { +# check => ['perm', '/cluster/sdn/zones', ['SDN.Allocate']], +# }, + parameters => { + additionalProperties => 0, + }, + returns => { type => 'null' }, + code => sub { + my ($param) = @_; + + die "no sdn zones changes to revert" if !-e "/etc/pve/sdn/zones.cfg.new"; + unlink "/etc/pve/sdn/zones.cfg.new"; + + return undef; + }}); + +__PACKAGE__->register_method ({ + name => 'update', + protected => 1, + path => '{zone}', + method => 'PUT', + description => "Update sdn zone object configuration.", +# permissions => { +# check => ['perm', '/cluster/sdn/zones', ['SDN.Allocate']], +# }, + parameters => PVE::Network::SDN::Zones::Plugin->updateSchema(), + returns => { type => 'null' }, + code => sub { + my ($param) = @_; + + my $id = extract_param($param, 'zone'); + my $digest = extract_param($param, 'digest'); + + PVE::Network::SDN::Zones::lock_sdn_zones_config( + sub { + + my $cfg = PVE::Network::SDN::Zones::config(); + + PVE::SectionConfig::assert_if_modified($cfg, $digest); + + my $scfg = PVE::Network::SDN::Zones::sdn_zones_config($cfg, $id); + + my $plugin = PVE::Network::SDN::Zones::Plugin->lookup($scfg->{type}); + my $opts = $plugin->check_config($id, $param, 0, 1); + + foreach my $k (%$opts) { + $scfg->{$k} = $opts->{$k}; + } + + $plugin->on_update_hook($id, $cfg); + + PVE::Network::SDN::Zones::write_config($cfg); + + }, "update sdn zone object failed"); + + return undef; + }}); + +__PACKAGE__->register_method ({ + name => 'delete', + protected => 1, + path => '{zone}', + method => 'DELETE', + description => "Delete sdn zone object configuration.", +# permissions => { +# check => ['perm', '/cluster/sdn/zones', ['SDN.Allocate']], +# }, + parameters => { + 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 $id = extract_param($param, 'zone'); + + PVE::Network::SDN::Zones::lock_sdn_zones_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(); + + $plugin->on_delete_hook($id, $vnet_cfg); + + delete $cfg->{ids}->{$id}; + PVE::Network::SDN::Zones::write_config($cfg); + + }, "delete sdn zone object failed"); + + + return undef; + }}); + +1; diff --git a/PVE/API2/Network/SDN/Content.pm b/PVE/API2/Network/SDN/Zones/Content.pm similarity index 88% rename from PVE/API2/Network/SDN/Content.pm rename to PVE/API2/Network/SDN/Zones/Content.pm index 1b45ce5..0ee6059 100644 --- a/PVE/API2/Network/SDN/Content.pm +++ b/PVE/API2/Network/SDN/Zones/Content.pm @@ -1,4 +1,4 @@ -package PVE::API2::Network::SDN::Content; +package PVE::API2::Network::SDN::Zones::Content; use strict; use warnings; @@ -30,8 +30,8 @@ __PACKAGE__->register_method ({ additionalProperties => 0, properties => { node => get_standard_option('pve-node'), - sdn => get_standard_option('pve-sdn-id', { - completion => \&PVE::Network::SDN::complete_sdn, + zone => get_standard_option('pve-sdn-zone-id', { + completion => \&PVE::Network::SDN::Zones::complete_sdn_zone, }), }, }, @@ -60,7 +60,7 @@ __PACKAGE__->register_method ({ my $authuser = $rpcenv->get_user(); - my $transportid = $param->{sdn}; + my $transportid = $param->{zone}; my $res = []; diff --git a/PVE/API2/Network/SDN/Zones/Makefile b/PVE/API2/Network/SDN/Zones/Makefile new file mode 100644 index 0000000..9b0a42b --- /dev/null +++ b/PVE/API2/Network/SDN/Zones/Makefile @@ -0,0 +1,8 @@ +SOURCES=Status.pm Content.pm + + +PERL5DIR=${DESTDIR}/usr/share/perl5 + +.PHONY: install +install: + for i in ${SOURCES}; do install -D -m 0644 $$i ${PERL5DIR}/PVE/API2/Network/SDN/Zones/$$i; done diff --git a/PVE/API2/Network/SDN/Status.pm b/PVE/API2/Network/SDN/Zones/Status.pm similarity index 83% rename from PVE/API2/Network/SDN/Status.pm rename to PVE/API2/Network/SDN/Zones/Status.pm index 7f23214..68af1ad 100644 --- a/PVE/API2/Network/SDN/Status.pm +++ b/PVE/API2/Network/SDN/Zones/Status.pm @@ -1,4 +1,4 @@ -package PVE::API2::Network::SDN::Status; +package PVE::API2::Network::SDN::Zones::Status; use strict; use warnings; @@ -8,7 +8,7 @@ use File::Basename; use PVE::Tools; use PVE::INotify; use PVE::Cluster; -use PVE::API2::Network::SDN::Content; +use PVE::API2::Network::SDN::Zones::Content; use PVE::RESTHandler; use PVE::RPCEnvironment; use PVE::JSONSchema qw(get_standard_option); @@ -17,8 +17,8 @@ use PVE::Exception qw(raise_param_exc); use base qw(PVE::RESTHandler); __PACKAGE__->register_method ({ - subclass => "PVE::API2::Network::SDN::Content", - path => '{sdn}/content', + subclass => "PVE::API2::Network::SDN::Zones::Content", + path => '{zone}/content', }); __PACKAGE__->register_method ({ @@ -43,14 +43,14 @@ __PACKAGE__->register_method ({ items => { type => "object", properties => { - sdn => get_standard_option('pve-sdn-id'), + zone => get_standard_option('pve-sdn-zone-id'), status => { description => "Status of transportzone", type => 'string', }, }, }, - links => [ { rel => 'child', href => "{sdn}" } ], + links => [ { rel => 'child', href => "{zone}" } ], }, code => sub { my ($param) = @_; @@ -65,7 +65,7 @@ __PACKAGE__->register_method ({ my ($transport_status, $vnet_status) = PVE::Network::SDN::status(); foreach my $id (keys %{$transport_status}) { - my $item->{sdn} = $id; + my $item->{zone} = $id; $item->{status} = $transport_status->{$id}->{'status'}; push @$res,$item; } @@ -75,7 +75,7 @@ __PACKAGE__->register_method ({ __PACKAGE__->register_method ({ name => 'diridx', - path => '{sdn}', + path => '{zone}', method => 'GET', description => "", # permissions => { @@ -85,7 +85,7 @@ __PACKAGE__->register_method ({ additionalProperties => 0, properties => { node => get_standard_option('pve-node'), - sdn => get_standard_option('pve-sdn-id'), + zone => get_standard_option('pve-sdn-zone-id'), }, }, returns => { -- 2.39.2