From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id 9E6D766D8F for ; Sun, 8 Nov 2020 15:20:20 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id C889EEC8E for ; Sun, 8 Nov 2020 15:20:10 +0100 (CET) Received: from kvmformation1.odiso.net (globalOdiso.M6Lille.odiso.net [89.248.211.242]) by firstgate.proxmox.com (Proxmox) with ESMTP id 3BBF3E8EE for ; Sun, 8 Nov 2020 15:19:48 +0100 (CET) Received: by kvmformation1.odiso.net (Postfix, from userid 0) id 6E867713868; Sun, 8 Nov 2020 15:19:42 +0100 (CET) From: Alexandre Derumier To: pve-devel@lists.proxmox.com Date: Sun, 8 Nov 2020 15:19:28 +0100 Message-Id: <20201108141940.1028443-27-aderumier@odiso.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20201108141940.1028443-1-aderumier@odiso.com> References: <20201108141940.1028443-1-aderumier@odiso.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 1 AWL -0.204 Adjusted score from AWL reputation of From: address HEADER_FROM_DIFFERENT_DOMAINS 0.25 From and EnvelopeFrom 2nd level mail domains are different KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment KAM_LAZY_DOMAIN_SECURITY 1 Sending domain does not have any anti-forgery methods KHOP_HELO_FCRDNS 0.276 Relay HELO differs from its IP's reverse DNS NO_DNS_FOR_FROM 0.379 Envelope sender has no MX or A DNS records SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_NONE 0.001 SPF: sender does not publish an SPF Record URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [zones.pm, controllers.pm, sdn.pm, vnets.pm, subnets.pm] Subject: [pve-devel] [PATCH pve-network 26/38] api: add running/pending zones/vnets/subnets/controllers X-BeenThere: pve-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox VE development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 08 Nov 2020 14:20:21 -0000 --- PVE/API2/Network/SDN/Controllers.pm | 53 +++++++++++++++++++++--- PVE/API2/Network/SDN/Subnets.pm | 45 ++++++++++++++++++++- PVE/API2/Network/SDN/Vnets.pm | 62 +++++++++++++++++++++++++++-- PVE/API2/Network/SDN/Zones.pm | 54 +++++++++++++++++++++++-- PVE/Network/SDN.pm | 45 +++++++++++++++++++++ 5 files changed, 245 insertions(+), 14 deletions(-) diff --git a/PVE/API2/Network/SDN/Controllers.pm b/PVE/API2/Network/SDN/Controllers.pm index 919d343..75beb6b 100644 --- a/PVE/API2/Network/SDN/Controllers.pm +++ b/PVE/API2/Network/SDN/Controllers.pm @@ -51,15 +51,27 @@ __PACKAGE__->register_method ({ 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'}, - }, + properties => { controller => { type => 'string' }, + type => { type => 'string' }, + state => { type => 'string', optional => 1 }, + pending => { optional => 1}, + }, }, links => [ { rel => 'child', href => "{controller}" } ], }, @@ -69,8 +81,17 @@ __PACKAGE__->register_method ({ my $rpcenv = PVE::RPCEnvironment::get(); my $authuser = $rpcenv->get_user(); - - my $cfg = PVE::Network::SDN::Controllers::config(); + my $cfg = {}; + if($param->{pending}) { + my $running_cfg = PVE::Network::SDN::config(); + my $config = PVE::Network::SDN::Controllers::config(); + $cfg = PVE::Network::SDN::pending_config($running_cfg, $config, 'controllers'); + } elsif ($param->{running}) { + my $running_cfg = PVE::Network::SDN::config(); + $cfg = $running_cfg->{controllers}; + } else { + $cfg = PVE::Network::SDN::Controllers::config(); + } my @sids = PVE::Network::SDN::Controllers::sdn_controllers_ids($cfg); my $res = []; @@ -102,13 +123,33 @@ __PACKAGE__->register_method ({ 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 $cfg = PVE::Network::SDN::Controllers::config(); + my $cfg = {}; + if($param->{pending}) { + my $running_cfg = PVE::Network::SDN::config(); + my $config = PVE::Network::SDN::Controllers::config(); + $cfg = PVE::Network::SDN::pending_config($running_cfg, $config, 'controllers'); + } elsif ($param->{running}) { + my $running_cfg = PVE::Network::SDN::config(); + $cfg = $running_cfg->{controllers}; + } else { + $cfg = PVE::Network::SDN::Controllers::config(); + } return &$api_sdn_controllers_config($cfg, $param->{controller}); }}); diff --git a/PVE/API2/Network/SDN/Subnets.pm b/PVE/API2/Network/SDN/Subnets.pm index 2dd80a3..34fb714 100644 --- a/PVE/API2/Network/SDN/Subnets.pm +++ b/PVE/API2/Network/SDN/Subnets.pm @@ -46,6 +46,16 @@ __PACKAGE__->register_method ({ 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.", + }, }, }, @@ -65,7 +75,17 @@ __PACKAGE__->register_method ({ my $vnetid = $param->{vnet}; - my $cfg = PVE::Network::SDN::Subnets::config(); + my $cfg = {}; + if($param->{pending}) { + my $running_cfg = PVE::Network::SDN::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::config(); + $cfg = $running_cfg->{subnets}; + } else { + $cfg = PVE::Network::SDN::Subnets::config(); + } my @sids = PVE::Network::SDN::Subnets::sdn_subnets_ids($cfg); my $res = []; @@ -97,13 +117,34 @@ __PACKAGE__->register_method ({ 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 $cfg = PVE::Network::SDN::Subnets::config(); + my $cfg = {}; + if($param->{pending}) { + my $running_cfg = PVE::Network::SDN::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::config(); + $cfg = $running_cfg->{subnets}; + } else { + $cfg = PVE::Network::SDN::Subnets::config(); + } + my $scfg = &$api_sdn_subnets_config($cfg, $param->{subnet}); raise_param_exc({ vnet => "wrong vnet"}) if $param->{vnet} ne $scfg->{vnet}; diff --git a/PVE/API2/Network/SDN/Vnets.pm b/PVE/API2/Network/SDN/Vnets.pm index 0fbb747..6ff61c5 100644 --- a/PVE/API2/Network/SDN/Vnets.pm +++ b/PVE/API2/Network/SDN/Vnets.pm @@ -3,6 +3,8 @@ package PVE::API2::Network::SDN::Vnets; use strict; use warnings; +use Hash::Diff qw( diff ); + use PVE::SafeSyslog; use PVE::Tools qw(extract_param); use PVE::Cluster qw(cfs_read_file cfs_write_file); @@ -33,10 +35,22 @@ 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; }; +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 => '', @@ -49,6 +63,18 @@ __PACKAGE__->register_method ({ }, 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', @@ -64,7 +90,17 @@ __PACKAGE__->register_method ({ my $rpcenv = PVE::RPCEnvironment::get(); my $authuser = $rpcenv->get_user(); - my $cfg = PVE::Network::SDN::Vnets::config(); + my $cfg = {}; + if($param->{pending}) { + my $running_cfg = PVE::Network::SDN::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::config(); + $cfg = $running_cfg->{vnets}; + } else { + $cfg = PVE::Network::SDN::Vnets::config(); + } my @sids = PVE::Network::SDN::Vnets::sdn_vnets_ids($cfg); my $res = []; @@ -93,13 +129,33 @@ __PACKAGE__->register_method ({ 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 = PVE::Network::SDN::Vnets::config(); + my $cfg = {}; + if($param->{pending}) { + my $running_cfg = PVE::Network::SDN::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::config(); + $cfg = $running_cfg->{vnets}; + } else { + $cfg = PVE::Network::SDN::Vnets::config(); + } return $api_sdn_vnets_config->($cfg, $param->{vnet}); }}); diff --git a/PVE/API2/Network/SDN/Zones.pm b/PVE/API2/Network/SDN/Zones.pm index a37df3d..512945c 100644 --- a/PVE/API2/Network/SDN/Zones.pm +++ b/PVE/API2/Network/SDN/Zones.pm @@ -38,6 +38,11 @@ my $api_sdn_zones_config = sub { $scfg->{nodes} = PVE::Network::SDN::Zones::Plugin->encode_value($scfg->{type}, 'nodes', $scfg->{nodes}); } + my $pending = $scfg->{pending}; + if ($pending->{nodes}) { + $pending->{nodes} = PVE::Network::SDN::Zones::Plugin->encode_value($scfg->{type}, 'nodes', $pending->{nodes}); + } + return $scfg; }; @@ -59,6 +64,16 @@ __PACKAGE__->register_method ({ 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 => { @@ -67,6 +82,10 @@ __PACKAGE__->register_method ({ type => "object", properties => { zone => { type => 'string'}, type => { type => 'string'}, + mtu => { type => 'integer', optional => 1 }, + pending => { optional => 1}, + state => { type => 'string', optional => 1}, + nodes => { type => 'string', optional => 1}, }, }, links => [ { rel => 'child', href => "{zone}" } ], @@ -77,8 +96,17 @@ __PACKAGE__->register_method ({ my $rpcenv = PVE::RPCEnvironment::get(); my $authuser = $rpcenv->get_user(); - - my $cfg = PVE::Network::SDN::Zones::config(); + my $cfg = {}; + if($param->{pending}) { + my $running_cfg = PVE::Network::SDN::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::config(); + $cfg = $running_cfg->{zones}; + } else { + $cfg = PVE::Network::SDN::Zones::config(); + } my @sids = PVE::Network::SDN::Zones::sdn_zones_ids($cfg); my $res = []; @@ -110,13 +138,33 @@ __PACKAGE__->register_method ({ 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 $cfg = PVE::Network::SDN::Zones::config(); + my $cfg = {}; + if($param->{pending}) { + my $running_cfg = PVE::Network::SDN::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::config(); + $cfg = $running_cfg->{zones}; + } else { + $cfg = PVE::Network::SDN::Zones::config(); + } return &$api_sdn_zones_config($cfg, $param->{zone}); }}); diff --git a/PVE/Network/SDN.pm b/PVE/Network/SDN.pm index f21de15..3cd73ff 100644 --- a/PVE/Network/SDN.pm +++ b/PVE/Network/SDN.pm @@ -81,6 +81,51 @@ sub config { return cfs_read_file($running_cfg); } +sub pending_config { + my ($running_cfg, $cfg, $type) = @_; + + my $pending = {}; + + my $running_objects = $running_cfg->{$type}->{ids}; + 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 ($running_object->{$key} ne $config_object->{$key}) { + $pending->{$id}->{state} = "changed"; + } + } + } + + 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 = $config_object->{$key} if $config_object->{$key}; + my $running_value = $running_object->{$key} if $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"; + } + } + } + + return {ids => $pending}; + +} + sub commit_config { my $cfg = cfs_read_file($running_cfg); -- 2.20.1