diff options
Diffstat (limited to 'src/PVE/API2/Network/SDN/Vnets.pm')
| -rw-r--r-- | src/PVE/API2/Network/SDN/Vnets.pm | 292 |
1 files changed, 292 insertions, 0 deletions
diff --git a/src/PVE/API2/Network/SDN/Vnets.pm b/src/PVE/API2/Network/SDN/Vnets.pm new file mode 100644 index 0000000..811a2e8 --- /dev/null +++ b/src/PVE/API2/Network/SDN/Vnets.pm @@ -0,0 +1,292 @@ +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; +use PVE::Network::SDN::Zones; +use PVE::Network::SDN::Zones::Plugin; +use PVE::Network::SDN::Vnets; +use PVE::Network::SDN::VnetPlugin; +use PVE::Network::SDN::Subnets; +use PVE::API2::Network::SDN::Subnets; + +use Storable qw(dclone); +use PVE::JSONSchema qw(get_standard_option); +use PVE::RPCEnvironment; +use PVE::Exception qw(raise raise_param_exc); + +use PVE::RESTHandler; + +use base qw(PVE::RESTHandler); + +__PACKAGE__->register_method ({ + subclass => "PVE::API2::Network::SDN::Subnets", + path => '{vnet}/subnets', +}); + +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; +}; + +my $api_sdn_vnets_deleted_config = sub { + my ($cfg, $running_cfg, $id) = @_; + + 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; + } +}; + +__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/vnets/<vnet>'", + user => 'all', + }, + parameters => { + additionalProperties => 0, + properties => { + 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 => "{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' ]; + next if !$rpcenv->check_any($authuser, "/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', '/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, + }), + 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 $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, $param->{vnet}); + }}); + +__PACKAGE__->register_method ({ + name => 'create', + protected => 1, + path => '', + method => 'POST', + description => "Create a new sdn vnet object.", + permissions => { + check => ['perm', '/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::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); + + 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); + + 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 => 'update', + protected => 1, + path => '{vnet}', + method => 'PUT', + description => "Update sdn vnet object configuration.", + permissions => { + check => ['perm', '/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::lock_sdn_config(sub { + my $cfg = PVE::Network::SDN::Vnets::config(); + + PVE::SectionConfig::assert_if_modified($cfg, $digest); + + + my $opts = PVE::Network::SDN::VnetPlugin->check_config($id, $param, 0, 1); + raise_param_exc({ zone => "missing zone"}) if !$opts->{zone}; + my $subnets = PVE::Network::SDN::Vnets::get_subnets($id); + raise_param_exc({ zone => "can't change zone if subnets exists"}) if($subnets && $opts->{zone} ne $cfg->{ids}->{$id}->{zone}); + + $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); + + 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', '/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::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(); + + 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; |
