[pve-devel] [PATCH v2 ha-manager 04/12] Implement update_service_config for simulation

2019-09-30 Thread Fabian Ebner
Signed-off-by: Fabian Ebner 
---
 src/PVE/HA/Sim/Hardware.pm | 16 
 1 file changed, 16 insertions(+)

diff --git a/src/PVE/HA/Sim/Hardware.pm b/src/PVE/HA/Sim/Hardware.pm
index 8bd5cbd..d2c0ec0 100644
--- a/src/PVE/HA/Sim/Hardware.pm
+++ b/src/PVE/HA/Sim/Hardware.pm
@@ -109,6 +109,22 @@ sub read_service_config {
 return $conf;
 }
 
+sub update_service_config {
+my ($self, $digest, $delete, $sid, $param) = @_;
+
+die "not implemented" if ($digest || $delete);
+
+my $conf = $self->read_service_config();
+
+my $sconf = $conf->{$sid} || die "no such resource '$sid'\n";
+
+foreach my $k (%$param) {
+   $sconf->{$k} = $param->{$k};
+}
+
+$self->write_service_config($conf);
+}
+
 sub write_service_config {
 my ($self, $conf) = @_;
 
-- 
2.20.1


___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v2 ha-manager 06/12] Use timeout for shutdown in LRM

2019-09-30 Thread Fabian Ebner
Signed-off-by: Fabian Ebner 
---
 src/PVE/HA/LRM.pm | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/PVE/HA/LRM.pm b/src/PVE/HA/LRM.pm
index 3b4a572..e5eee94 100644
--- a/src/PVE/HA/LRM.pm
+++ b/src/PVE/HA/LRM.pm
@@ -535,7 +535,7 @@ sub manage_resources {
my $req_state = $sd->{state};
next if !defined($req_state);
next if $req_state eq 'freeze';
-   $self->queue_resource_command($sid, $sd->{uid}, $req_state, {'target' 
=> $sd->{target}});
+   $self->queue_resource_command($sid, $sd->{uid}, $req_state, {'target' 
=> $sd->{target}, 'timeout' => $sd->{timeout}});
 }
 
 return $self->run_workers();
@@ -776,7 +776,7 @@ sub exec_resource_agent {
 
$haenv->log("info", "stopping service $sid");
 
-   $plugin->shutdown($haenv, $id);
+   $plugin->shutdown($haenv, $id, $params->{timeout});
 
$running = $plugin->check_running($haenv, $id);
 
-- 
2.20.1


___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v2 ha-manager 01/12] Make parameters for LRM resource commands more flexible

2019-09-30 Thread Fabian Ebner
This will allow for new parameters beside 'target' to be used.
This is in preparation to allow for a 'timeout' parameter for a new 'stop' 
command.

Signed-off-by: Fabian Ebner 
---
 src/PVE/HA/LRM.pm | 14 +++---
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/src/PVE/HA/LRM.pm b/src/PVE/HA/LRM.pm
index af4e21e..3b4a572 100644
--- a/src/PVE/HA/LRM.pm
+++ b/src/PVE/HA/LRM.pm
@@ -477,7 +477,7 @@ sub run_workers {
# do work
my $res = -1;
eval {
-   $res = $self->exec_resource_agent($sid, 
$sc->{$sid}, $w->{state}, $w->{target});
+   $res = $self->exec_resource_agent($sid, 
$sc->{$sid}, $w->{state}, $w->{params});
};
if (my $err = $@) {
$haenv->log('err', $err);
@@ -491,7 +491,7 @@ sub run_workers {
} else {
my $res = -1;
eval {
-   $res = $self->exec_resource_agent($sid, $sc->{$sid}, 
$w->{state}, $w->{target});
+   $res = $self->exec_resource_agent($sid, $sc->{$sid}, 
$w->{state}, $w->{params});
$res = $res << 8 if $res > 0;
};
if (my $err = $@) {
@@ -535,14 +535,14 @@ sub manage_resources {
my $req_state = $sd->{state};
next if !defined($req_state);
next if $req_state eq 'freeze';
-   $self->queue_resource_command($sid, $sd->{uid}, $req_state, 
$sd->{target});
+   $self->queue_resource_command($sid, $sd->{uid}, $req_state, {'target' 
=> $sd->{target}});
 }
 
 return $self->run_workers();
 }
 
 sub queue_resource_command {
-my ($self, $sid, $uid, $state, $target) = @_;
+my ($self, $sid, $uid, $state, $params) = @_;
 
 # do not queue the excatly same command twice as this may lead to
 # an inconsistent HA state when the first command fails but the CRM
@@ -564,7 +564,7 @@ sub queue_resource_command {
state => $state,
 };
 
-$self->{workers}->{$sid}->{target} = $target if $target;
+$self->{workers}->{$sid}->{params} = $params if $params;
 }
 
 sub check_active_workers {
@@ -711,7 +711,7 @@ sub handle_service_exitcode {
 }
 
 sub exec_resource_agent {
-my ($self, $sid, $service_config, $cmd, @params) = @_;
+my ($self, $sid, $service_config, $cmd, $params) = @_;
 
 # setup execution environment
 
@@ -790,7 +790,7 @@ sub exec_resource_agent {
 
 } elsif ($cmd eq 'migrate' || $cmd eq 'relocate') {
 
-   my $target = $params[0];
+   my $target = $params->{target};
if (!defined($target)) {
die "$cmd '$sid' failed - missing target\n" if !defined($target);
return EINVALID_PARAMETER;
-- 
2.20.1


___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v2 ha-manager 11/12] Log timeout parameter when present

2019-09-30 Thread Fabian Ebner
Signed-off-by: Fabian Ebner 
---
 src/PVE/HA/LRM.pm | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/src/PVE/HA/LRM.pm b/src/PVE/HA/LRM.pm
index e5eee94..95ec351 100644
--- a/src/PVE/HA/LRM.pm
+++ b/src/PVE/HA/LRM.pm
@@ -774,7 +774,11 @@ sub exec_resource_agent {
 
return SUCCESS if !$running;
 
-   $haenv->log("info", "stopping service $sid");
+   if (defined($params->{timeout})) {
+   $haenv->log("info", "stopping service $sid 
(timeout=$params->{timeout})");
+   } else {
+   $haenv->log("info", "stopping service $sid");
+   }
 
$plugin->shutdown($haenv, $id, $params->{timeout});
 
-- 
2.20.1


___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v2 ha-manager 07/12] Add stop command to the API

2019-09-30 Thread Fabian Ebner
Signed-off-by: Fabian Ebner 
---
 src/PVE/API2/HA/Resources.pm | 37 
 src/PVE/CLI/ha_manager.pm|  2 ++
 2 files changed, 39 insertions(+)

diff --git a/src/PVE/API2/HA/Resources.pm b/src/PVE/API2/HA/Resources.pm
index 2b62ee8..ecc5f0c 100644
--- a/src/PVE/API2/HA/Resources.pm
+++ b/src/PVE/API2/HA/Resources.pm
@@ -353,4 +353,41 @@ __PACKAGE__->register_method ({
return undef;
 }});
 
+__PACKAGE__->register_method ({
+name => 'stop',
+protected => 1,
+path => '{sid}/stop',
+method => 'POST',
+description => "Request the service to be stopped.",
+permissions => {
+   check => ['perm', '/', [ 'Sys.Console' ]],
+},
+parameters => {
+   additionalProperties => 0,
+   properties => {
+   sid => get_standard_option('pve-ha-resource-or-vm-id',
+ { completion => 
\&PVE::HA::Tools::complete_sid }),
+   timeout => {
+   description => "Timeout in seconds. If set to 0 a hard stop 
will be performed.",
+   type => 'integer',
+   minimum => 0,
+   optional => 1,
+   },
+   },
+},
+returns => { type => 'null' },
+code => sub {
+   my ($param) = @_;
+
+   my ($sid, $type, $name) = 
PVE::HA::Config::parse_sid(extract_param($param, 'sid'));
+
+   PVE::HA::Config::service_is_ha_managed($sid);
+
+   check_service_state($sid);
+
+   PVE::HA::Config::queue_crm_commands("stop $sid $param->{timeout}");
+
+   return undef;
+}});
+
 1;
diff --git a/src/PVE/CLI/ha_manager.pm b/src/PVE/CLI/ha_manager.pm
index 5ce4c30..c9d4e7f 100644
--- a/src/PVE/CLI/ha_manager.pm
+++ b/src/PVE/CLI/ha_manager.pm
@@ -114,6 +114,8 @@ our $cmddef = {
 migrate => [ "PVE::API2::HA::Resources", 'migrate', ['sid', 'node'] ],
 relocate => [ "PVE::API2::HA::Resources", 'relocate', ['sid', 'node'] ],
 
+stop => [ "PVE::API2::HA::Resources", 'stop', ['sid', 'timeout'] ],
+
 };
 
 1;
-- 
2.20.1


___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v2 ha-manager 08/12] Rename target to param in simulation

2019-09-30 Thread Fabian Ebner
In preparation to introduce a stop command with a timeout parameter.

Signed-off-by: Fabian Ebner 
---
 src/PVE/HA/Sim/Hardware.pm | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/src/PVE/HA/Sim/Hardware.pm b/src/PVE/HA/Sim/Hardware.pm
index d2c0ec0..ac0c142 100644
--- a/src/PVE/HA/Sim/Hardware.pm
+++ b/src/PVE/HA/Sim/Hardware.pm
@@ -553,7 +553,7 @@ sub sim_hardware_cmd {
 
my $cstatus = $self->read_hardware_status_nolock();
 
-   my ($cmd, $objid, $action, $target) = split(/\s+/, $cmdstr);
+   my ($cmd, $objid, $action, $param) = split(/\s+/, $cmdstr);
 
die "sim_hardware_cmd: no node or service for command specified"
if !$objid;
@@ -617,10 +617,10 @@ sub sim_hardware_cmd {
} elsif ($cmd eq 'cfs') {
die "sim_hardware_cmd: unknown cfs action '$action' for node 
'$node'"
if $action !~ m/^(rw|update)$/;
-   die "sim_hardware_cmd: unknown cfs command '$target' for '$action' 
on node '$node'"
-   if $target !~ m/^(work|fail)$/;
+   die "sim_hardware_cmd: unknown cfs command '$param' for '$action' 
on node '$node'"
+   if $param !~ m/^(work|fail)$/;
 
-   $cstatus->{$node}->{cfs}->{$action} = $target eq 'work';
+   $cstatus->{$node}->{cfs}->{$action} = $param eq 'work';
$self->write_hardware_status_nolock($cstatus);
 
} elsif ($cmd eq 'reboot' || $cmd eq 'shutdown') {
@@ -656,13 +656,13 @@ sub sim_hardware_cmd {
} elsif ($action eq 'migrate' || $action eq 'relocate') {
 
die "sim_hardware_cmd: missing target node for '$action' 
command"
-   if !$target;
+   if !$param;
 
-   $self->queue_crm_commands_nolock("$action $sid $target");
+   $self->queue_crm_commands_nolock("$action $sid $param");
 
} elsif ($action eq 'add') {
 
-   $self->add_service($sid, {state => 'started', node => $target});
+   $self->add_service($sid, {state => 'started', node => $param});
 
} elsif ($action eq 'delete') {
 
@@ -670,11 +670,11 @@ sub sim_hardware_cmd {
 
} elsif ($action eq 'lock') {
 
-   $self->lock_service($sid, $target);
+   $self->lock_service($sid, $param);
 
} elsif ($action eq 'unlock') {
 
-   $self->unlock_service($sid, $target);
+   $self->unlock_service($sid, $param);
 
} else {
die "sim_hardware_cmd: unknown service action '$action' " .
-- 
2.20.1


___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v2 ha-manager 09/12] Add stop command to simulation

2019-09-30 Thread Fabian Ebner
Signed-off-by: Fabian Ebner 
---
 src/PVE/HA/Sim/Hardware.pm | 8 
 1 file changed, 8 insertions(+)

diff --git a/src/PVE/HA/Sim/Hardware.pm b/src/PVE/HA/Sim/Hardware.pm
index ac0c142..7e1a8bc 100644
--- a/src/PVE/HA/Sim/Hardware.pm
+++ b/src/PVE/HA/Sim/Hardware.pm
@@ -543,6 +543,7 @@ sub get_cfs_state {
 # restart-lrm 
 # service  
 # service   
+# service  stop 
 # service  lock/unlock [lockname]
 
 sub sim_hardware_cmd {
@@ -660,6 +661,13 @@ sub sim_hardware_cmd {
 
$self->queue_crm_commands_nolock("$action $sid $param");
 
+   } elsif ($action eq 'stop') {
+
+   die "sim_hardware_cmd: missing timeout for '$action' command"
+   if !defined($param);
+
+   $self->queue_crm_commands_nolock("$action $sid $param");
+
} elsif ($action eq 'add') {
 
$self->add_service($sid, {state => 'started', node => $param});
-- 
2.20.1


___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v2 ha-manager 05/12] Add timeout parameter for shutdown

2019-09-30 Thread Fabian Ebner
Introduces a timeout parameter for shutting a resource down.
If the parameter is 0, we perform a hard stop instead of a shutdown.

Signed-off-by: Fabian Ebner 
---
 src/PVE/HA/Resources.pm   |  2 +-
 src/PVE/HA/Resources/PVECT.pm | 14 ++
 src/PVE/HA/Resources/PVEVM.pm | 16 +++-
 3 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/src/PVE/HA/Resources.pm b/src/PVE/HA/Resources.pm
index 7c373bc..835c314 100644
--- a/src/PVE/HA/Resources.pm
+++ b/src/PVE/HA/Resources.pm
@@ -126,7 +126,7 @@ sub start {
 }
 
 sub shutdown {
-my ($class, $haenv, $id) = @_;
+my ($class, $haenv, $id, $timeout) = @_;
 
 die "implement in subclass";
 }
diff --git a/src/PVE/HA/Resources/PVECT.pm b/src/PVE/HA/Resources/PVECT.pm
index a0f05f4..282f4ef 100644
--- a/src/PVE/HA/Resources/PVECT.pm
+++ b/src/PVE/HA/Resources/PVECT.pm
@@ -74,18 +74,24 @@ sub start {
 }
 
 sub shutdown {
-my ($class, $haenv, $id) = @_;
+my ($class, $haenv, $id, $timeout) = @_;
 
 my $nodename = $haenv->nodename();
-my $shutdown_timeout = 60; # fixme: make this configurable
+my $shutdown_timeout = $timeout // 60;
 
+my $upid;
 my $params = {
node => $nodename,
vmid => $id,
-   timeout => $shutdown_timeout,
 };
 
-my $upid = PVE::API2::LXC::Status->vm_shutdown($params);
+if ($shutdown_timeout) {
+   $params->{timeout} = $shutdown_timeout;
+   $upid = PVE::API2::LXC::Status->vm_shutdown($params);
+} else {
+   $upid = PVE::API2::LXC::Status->vm_stop($params);
+}
+
 PVE::HA::Tools::upid_wait($upid, $haenv);
 }
 
diff --git a/src/PVE/HA/Resources/PVEVM.pm b/src/PVE/HA/Resources/PVEVM.pm
index 9dcf558..45d87e8 100644
--- a/src/PVE/HA/Resources/PVEVM.pm
+++ b/src/PVE/HA/Resources/PVEVM.pm
@@ -72,19 +72,25 @@ sub start {
 }
 
 sub shutdown {
-my ($class, $haenv, $id) = @_;
+my ($class, $haenv, $id, $timeout) = @_;
 
 my $nodename = $haenv->nodename();
-my $shutdown_timeout = 60; # fixme: make this configurable
+my $shutdown_timeout = $timeout // 60;
 
+my $upid;
 my $params = {
node => $nodename,
vmid => $id,
-   timeout => $shutdown_timeout,
-   forceStop => 1,
 };
 
-my $upid = PVE::API2::Qemu->vm_shutdown($params);
+if ($shutdown_timeout) {
+   $params->{timeout} = $shutdown_timeout;
+   $params->{forceStop} = 1;
+   $upid = PVE::API2::Qemu->vm_shutdown($params);
+} else {
+   $upid = PVE::API2::Qemu->vm_stop($params);
+}
+
 PVE::HA::Tools::upid_wait($upid, $haenv);
 }
 
-- 
2.20.1


___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v2 ha-manager 00/12] Implement a stop command for HA

2019-09-30 Thread Fabian Ebner
This patch series introduces a new 'stop' command for ha-manager.
The command takes a timeout parameter and in case it is 0, it performs a hard 
stop.
The series also includes a test for the new command.
A few changes to how parameters were handled in CRM/LRM were necessary
as well as allowing the service config to be updated from within the manager.

Changes from v1:
* Lock HA domain inside update_resources_config
* Don't set a default timeout in LRM
* Different logging depending on whether timeout parameter is present
* Split old 08/13 into two patches to separate renaming and adding the new 
command

Fabian Ebner (12):
  Make parameters for LRM resource commands more flexible
  Move code updating resource config from API2::HA::Resources to
HA::Config
  Add update_service_config to HA environment interface
  Implement update_service_config for simulation
  Add timeout parameter for shutdown
  Use timeout for shutdown in LRM
  Add stop command to the API
  Rename target to param in simulation
  Add stop command to simulation
  Add crm command 'stop'
  Log timeout parameter when present
  Add test for the stop command

 src/PVE/API2/HA/Resources.pm| 71 +++--
 src/PVE/CLI/ha_manager.pm   |  2 +
 src/PVE/HA/Config.pm| 37 +++
 src/PVE/HA/Env.pm   |  6 ++
 src/PVE/HA/Env/PVE2.pm  |  6 ++
 src/PVE/HA/LRM.pm   | 22 ---
 src/PVE/HA/Manager.pm   | 27 ++--
 src/PVE/HA/Resources.pm |  2 +-
 src/PVE/HA/Resources/PVECT.pm   | 14 ++--
 src/PVE/HA/Resources/PVEVM.pm   | 16 +++--
 src/PVE/HA/Sim/Env.pm   |  6 ++
 src/PVE/HA/Sim/Hardware.pm  | 42 +---
 src/test/test-stop-command1/README  |  2 +
 src/test/test-stop-command1/cmdlist |  8 +++
 src/test/test-stop-command1/hardware_status |  5 ++
 src/test/test-stop-command1/log.expect  | 69 
 src/test/test-stop-command1/manager_status  |  1 +
 src/test/test-stop-command1/service_config  |  6 ++
 18 files changed, 277 insertions(+), 65 deletions(-)
 create mode 100644 src/test/test-stop-command1/README
 create mode 100644 src/test/test-stop-command1/cmdlist
 create mode 100644 src/test/test-stop-command1/hardware_status
 create mode 100644 src/test/test-stop-command1/log.expect
 create mode 100644 src/test/test-stop-command1/manager_status
 create mode 100644 src/test/test-stop-command1/service_config

-- 
2.20.1


___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v2 ha-manager 03/12] Add update_service_config to HA environment interface

2019-09-30 Thread Fabian Ebner
Signed-off-by: Fabian Ebner 
---
 src/PVE/HA/Env.pm  | 6 ++
 src/PVE/HA/Env/PVE2.pm | 6 ++
 src/PVE/HA/Sim/Env.pm  | 6 ++
 3 files changed, 18 insertions(+)

diff --git a/src/PVE/HA/Env.pm b/src/PVE/HA/Env.pm
index bb37486..7acd7c5 100644
--- a/src/PVE/HA/Env.pm
+++ b/src/PVE/HA/Env.pm
@@ -87,6 +87,12 @@ sub read_service_config {
 return $self->{plug}->read_service_config();
 }
 
+sub update_service_config {
+my ($self, $digest, $delete, $sid, $param) = @_;
+
+return $self->{plug}->update_service_config($digest, $delete, $sid, 
$param);
+}
+
 sub parse_sid {
 my ($self, $sid) = @_;
 
diff --git a/src/PVE/HA/Env/PVE2.pm b/src/PVE/HA/Env/PVE2.pm
index 796acd9..1e92687 100644
--- a/src/PVE/HA/Env/PVE2.pm
+++ b/src/PVE/HA/Env/PVE2.pm
@@ -120,6 +120,12 @@ sub read_service_config {
 return PVE::HA::Config::read_and_check_resources_config();
 }
 
+sub update_service_config {
+my ($self, $digest, $delete, $sid, $param) = @_;
+
+return PVE::HA::Config::update_resources_config($digest, $delete, $sid, 
$param);
+}
+
 sub parse_sid {
 my ($self, $sid) = @_;
 
diff --git a/src/PVE/HA/Sim/Env.pm b/src/PVE/HA/Sim/Env.pm
index 22e13e6..f400365 100644
--- a/src/PVE/HA/Sim/Env.pm
+++ b/src/PVE/HA/Sim/Env.pm
@@ -203,6 +203,12 @@ sub read_service_config {
 return $self->{hardware}->read_service_config();
 }
 
+sub update_service_config {
+my ($self, $digest, $delete, $sid, $param) = @_;
+
+return $self->{hardware}->update_service_config($digest, $delete, $sid, 
$param);
+}
+
 sub parse_sid {
 my ($self, $sid) = @_;
 
-- 
2.20.1


___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v2 ha-manager 02/12] Move code updating resource config from API2::HA::Resources to HA::Config

2019-09-30 Thread Fabian Ebner
This makes it easier to update the resource configuration from within the 
CRM/LRM stack,
which is needed for the new 'stop' command.

Signed-off-by: Fabian Ebner 
---
 src/PVE/API2/HA/Resources.pm | 34 +
 src/PVE/HA/Config.pm | 37 
 2 files changed, 38 insertions(+), 33 deletions(-)

diff --git a/src/PVE/API2/HA/Resources.pm b/src/PVE/API2/HA/Resources.pm
index 22d7f28..2b62ee8 100644
--- a/src/PVE/API2/HA/Resources.pm
+++ b/src/PVE/API2/HA/Resources.pm
@@ -237,39 +237,7 @@ __PACKAGE__->register_method ({
 
check_service_state($sid, $param->{state});
 
-   PVE::HA::Config::lock_ha_domain(
-   sub {
-
-   my $cfg = PVE::HA::Config::read_resources_config();
-
-   PVE::SectionConfig::assert_if_modified($cfg, $digest);
-
-   my $scfg = $cfg->{ids}->{$sid} ||
-   die "no such resource '$sid'\n";
-
-   my $plugin = PVE::HA::Resources->lookup($scfg->{type});
-   my $opts = $plugin->check_config($sid, $param, 0, 1);
-
-   foreach my $k (%$opts) {
-   $scfg->{$k} = $opts->{$k};
-   }
-
-   if ($delete) {
-   my $options = $plugin->private()->{options}->{$type};
-   foreach my $k (PVE::Tools::split_list($delete)) {
-   my $d = $options->{$k} ||
-   die "no such option '$k'\n";
-   die "unable to delete required option '$k'\n"
-   if !$d->{optional};
-   die "unable to delete fixed option '$k'\n"
-   if $d->{fixed};
-   delete $scfg->{$k};
-   }
-   }
-
-   PVE::HA::Config::write_resources_config($cfg)
-
-   }, "update resource failed");
+   PVE::HA::Config::update_resources_config($digest, $delete, $sid, 
$param);
 
return undef;
 }});
diff --git a/src/PVE/HA/Config.pm b/src/PVE/HA/Config.pm
index ead1ee2..e800154 100644
--- a/src/PVE/HA/Config.pm
+++ b/src/PVE/HA/Config.pm
@@ -125,6 +125,43 @@ sub read_and_check_resources_config {
 return $conf;
 }
 
+sub update_resources_config {
+my ($digest, $delete, $sid, $param) = @_;
+
+lock_ha_domain(
+   sub {
+   my $cfg = read_resources_config();
+   ($sid, my $type, my $name) = parse_sid($sid);
+
+   PVE::SectionConfig::assert_if_modified($cfg, $digest);
+
+   my $scfg = $cfg->{ids}->{$sid} ||
+   die "no such resource '$sid'\n";
+
+   my $plugin = PVE::HA::Resources->lookup($scfg->{type});
+   my $opts = $plugin->check_config($sid, $param, 0, 1);
+
+   foreach my $k (%$opts) {
+   $scfg->{$k} = $opts->{$k};
+   }
+
+   if ($delete) {
+   my $options = $plugin->private()->{options}->{$type};
+   foreach my $k (PVE::Tools::split_list($delete)) {
+   my $d = $options->{$k} ||
+   die "no such option '$k'\n";
+   die "unable to delete required option '$k'\n"
+   if !$d->{optional};
+   die "unable to delete fixed option '$k'\n"
+   if $d->{fixed};
+   delete $scfg->{$k};
+   }
+   }
+
+   write_resources_config($cfg);
+   }, "update resources config failed");
+}
+
 sub parse_sid {
 my ($sid) = @_;
 
-- 
2.20.1


___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v2 ha-manager 12/12] Add test for the stop command

2019-09-30 Thread Fabian Ebner
Signed-off-by: Fabian Ebner 
---
 src/test/test-stop-command1/README  |  2 +
 src/test/test-stop-command1/cmdlist |  8 +++
 src/test/test-stop-command1/hardware_status |  5 ++
 src/test/test-stop-command1/log.expect  | 69 +
 src/test/test-stop-command1/manager_status  |  1 +
 src/test/test-stop-command1/service_config  |  6 ++
 6 files changed, 91 insertions(+)
 create mode 100644 src/test/test-stop-command1/README
 create mode 100644 src/test/test-stop-command1/cmdlist
 create mode 100644 src/test/test-stop-command1/hardware_status
 create mode 100644 src/test/test-stop-command1/log.expect
 create mode 100644 src/test/test-stop-command1/manager_status
 create mode 100644 src/test/test-stop-command1/service_config

diff --git a/src/test/test-stop-command1/README 
b/src/test/test-stop-command1/README
new file mode 100644
index 000..d725380
--- /dev/null
+++ b/src/test/test-stop-command1/README
@@ -0,0 +1,2 @@
+Test the stop command with different timeouts
+and what happens with a failed service.
diff --git a/src/test/test-stop-command1/cmdlist 
b/src/test/test-stop-command1/cmdlist
new file mode 100644
index 000..c7c9e67
--- /dev/null
+++ b/src/test/test-stop-command1/cmdlist
@@ -0,0 +1,8 @@
+[
+[ "power node1 on", "power node2 on", "power node3 on" ],
+[ "service vm:101 stop 0" ],
+[ "service vm:101 stop 1" ],
+[ "service vm:102 stop 37" ],
+[ "service vm:103 stop 60" ],
+[ "service fa:1001 stop 0" ]
+]
diff --git a/src/test/test-stop-command1/hardware_status 
b/src/test/test-stop-command1/hardware_status
new file mode 100644
index 000..451beb1
--- /dev/null
+++ b/src/test/test-stop-command1/hardware_status
@@ -0,0 +1,5 @@
+{
+  "node1": { "power": "off", "network": "off" },
+  "node2": { "power": "off", "network": "off" },
+  "node3": { "power": "off", "network": "off" }
+}
diff --git a/src/test/test-stop-command1/log.expect 
b/src/test/test-stop-command1/log.expect
new file mode 100644
index 000..05f9712
--- /dev/null
+++ b/src/test/test-stop-command1/log.expect
@@ -0,0 +1,69 @@
+info  0 hardware: starting simulation
+info 20  cmdlist: execute power node1 on
+info 20node1/crm: status change startup => wait_for_quorum
+info 20node1/lrm: status change startup => wait_for_agent_lock
+info 20  cmdlist: execute power node2 on
+info 20node2/crm: status change startup => wait_for_quorum
+info 20node2/lrm: status change startup => wait_for_agent_lock
+info 20  cmdlist: execute power node3 on
+info 20node3/crm: status change startup => wait_for_quorum
+info 20node3/lrm: status change startup => wait_for_agent_lock
+info 20node1/crm: got lock 'ha_manager_lock'
+info 20node1/crm: status change wait_for_quorum => master
+info 20node1/crm: node 'node1': state changed from 'unknown' => 
'online'
+info 20node1/crm: node 'node2': state changed from 'unknown' => 
'online'
+info 20node1/crm: node 'node3': state changed from 'unknown' => 
'online'
+info 20node1/crm: adding new service 'fa:1001' on node 'node3'
+info 20node1/crm: adding new service 'vm:101' on node 'node1'
+info 20node1/crm: adding new service 'vm:102' on node 'node2'
+info 20node1/crm: adding new service 'vm:103' on node 'node3'
+info 21node1/lrm: got lock 'ha_agent_node1_lock'
+info 21node1/lrm: status change wait_for_agent_lock => active
+info 21node1/lrm: starting service vm:101
+info 21node1/lrm: service status vm:101 started
+info 22node2/crm: status change wait_for_quorum => slave
+info 23node2/lrm: got lock 'ha_agent_node2_lock'
+info 23node2/lrm: status change wait_for_agent_lock => active
+info 23node2/lrm: starting service vm:102
+info 23node2/lrm: service status vm:102 started
+info 24node3/crm: status change wait_for_quorum => slave
+info 25node3/lrm: got lock 'ha_agent_node3_lock'
+info 25node3/lrm: status change wait_for_agent_lock => active
+info 25node3/lrm: starting service fa:1001
+info 25node3/lrm: service status fa:1001 started
+info 25node3/lrm: starting service vm:103
+info 25node3/lrm: service status vm:103 started
+info120  cmdlist: execute service vm:101 stop 0
+info120node1/crm: got crm command: stop vm:101 0
+info120node1/crm: stop service with timeout '0'
+info120node1/crm: service 'vm:101': state changed from 'started' to 
'request_stop'  (timeout = 0)
+info121node1/lrm: stopping service vm:101 (timeout=0)
+info121node1/lrm: service status vm:101 stopped
+info140node1/crm: service 'vm:101': state changed from 'request_stop' 
to 'stopped'
+info220  cmdlist: execute service vm:101 stop 1
+info220node1/crm: got crm command: stop vm:101 1
+info220node1/crm: ignore service 'vm:101' stop request - serv

[pve-devel] [PATCH v2 ha-manager 10/12] Add crm command 'stop'

2019-09-30 Thread Fabian Ebner
Not every command parameter is 'target' anymore, so
it was necessary to modify the parsing of $sd->{cmd}.

Just changing the state to request_stop is not enough,
we need to actually update the service configuration as well.

Signed-off-by: Fabian Ebner 
---
 src/PVE/HA/Manager.pm | 27 +++
 1 file changed, 23 insertions(+), 4 deletions(-)

diff --git a/src/PVE/HA/Manager.pm b/src/PVE/HA/Manager.pm
index 5137de8..3c4cf61 100644
--- a/src/PVE/HA/Manager.pm
+++ b/src/PVE/HA/Manager.pm
@@ -349,6 +349,14 @@ sub update_crm_commands {
$haenv->log('err', "crm command error - no such service: $cmd");
}
 
+   } elsif ($cmd =~ m/^stop\s+(\S+)\s+(\S+)$/) {
+   my ($sid, $timeout) = ($1, $2);
+   if (my $sd = $ss->{$sid}) {
+   $haenv->log('info', "got crm command: $cmd");
+   $ss->{$sid}->{cmd} = [ 'stop', $timeout ];
+   } else {
+   $haenv->log('err', "crm command error - no such service: $cmd");
+   }
} else {
$haenv->log('err', "unable to parse crm command: $cmd");
}
@@ -561,10 +569,10 @@ sub next_state_stopped {
 }
 
 if ($sd->{cmd}) {
-   my ($cmd, $target) = @{$sd->{cmd}};
-   delete $sd->{cmd};
+   my $cmd = shift @{$sd->{cmd}};
 
if ($cmd eq 'migrate' || $cmd eq 'relocate') {
+   my $target = shift @{$sd->{cmd}};
if (!$ns->node_is_online($target)) {
$haenv->log('err', "ignore service '$sid' $cmd request - node 
'$target' not online");
} elsif ($sd->{node} eq $target) {
@@ -574,9 +582,12 @@ sub next_state_stopped {
   target => $target);
return;
}
+   } elsif ($cmd eq 'stop') {
+   $haenv->log('info', "ignore service '$sid' $cmd request - 
service already stopped");
} else {
$haenv->log('err', "unknown command '$cmd' for service '$sid'");
}
+   delete $sd->{cmd};
 }
 
 if ($cd->{state} eq 'disabled') {
@@ -638,10 +649,10 @@ sub next_state_started {
 if ($cd->{state} eq 'started') {
 
if ($sd->{cmd}) {
-   my ($cmd, $target) = @{$sd->{cmd}};
-   delete $sd->{cmd};
+   my $cmd = shift @{$sd->{cmd}};
 
if ($cmd eq 'migrate' || $cmd eq 'relocate') {
+   my $target = shift @{$sd->{cmd}};
if (!$ns->node_is_online($target)) {
$haenv->log('err', "ignore service '$sid' $cmd request - 
node '$target' not online");
} elsif ($sd->{node} eq $target) {
@@ -650,9 +661,17 @@ sub next_state_started {
$haenv->log('info', "$cmd service '$sid' to node 
'$target'");
&$change_service_state($self, $sid, $cmd, node => 
$sd->{node}, target => $target);
}
+   } elsif ($cmd eq 'stop') {
+   my $timeout = shift @{$sd->{cmd}};
+   $haenv->log('info', "$cmd service with timeout '$timeout'");
+   &$change_service_state($self, $sid, 'request_stop', timeout => 
$timeout);
+   $haenv->update_service_config(0, 0, $sid, {'state' => 
'stopped'});
} else {
$haenv->log('err', "unknown command '$cmd' for service '$sid'");
}
+
+   delete $sd->{cmd};
+
} else {
 
my $try_next = 0;
-- 
2.20.1


___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH pve-network 3/8] add faucet sdn controller plugins

2019-09-30 Thread Alexandre Derumier
1 plugin for controller, 1 plugin for dataplane

This is not 100% complete, but it's a proof of concept
to test differents sdn controller

Signed-off-by: Alexandre Derumier 
---
 PVE/API2/Network/SDN.pm|   3 +
 PVE/Network/SDN.pm |  19 ++
 PVE/Network/SDN/FaucetPlugin.pm| 102 +
 PVE/Network/SDN/Makefile   |   2 +-
 PVE/Network/SDN/OVSFaucetPlugin.pm |  76 +
 PVE/Network/SDN/Plugin.pm  |   5 ++
 6 files changed, 206 insertions(+), 1 deletion(-)
 create mode 100644 PVE/Network/SDN/FaucetPlugin.pm
 create mode 100644 PVE/Network/SDN/OVSFaucetPlugin.pm

diff --git a/PVE/API2/Network/SDN.pm b/PVE/API2/Network/SDN.pm
index 043aa0d..e4ed5cc 100644
--- a/PVE/API2/Network/SDN.pm
+++ b/PVE/API2/Network/SDN.pm
@@ -12,6 +12,9 @@ use PVE::Network::SDN::VlanPlugin;
 use PVE::Network::SDN::VxlanPlugin;
 use PVE::Network::SDN::VnetPlugin;
 use PVE::Network::SDN::FrrPlugin;
+use PVE::Network::SDN::OVSFaucetPlugin;
+use PVE::Network::SDN::FaucetPlugin;
+
 use Storable qw(dclone);
 use PVE::JSONSchema qw(get_standard_option);
 use PVE::RPCEnvironment;
diff --git a/PVE/Network/SDN.pm b/PVE/Network/SDN.pm
index b5d98b7..1946bc5 100644
--- a/PVE/Network/SDN.pm
+++ b/PVE/Network/SDN.pm
@@ -13,11 +13,15 @@ use PVE::Network::SDN::VnetPlugin;
 use PVE::Network::SDN::VlanPlugin;
 use PVE::Network::SDN::VxlanPlugin;
 use PVE::Network::SDN::FrrPlugin;
+use PVE::Network::SDN::OVSFaucetPlugin;
+use PVE::Network::SDN::FaucetPlugin;
 
 PVE::Network::SDN::VnetPlugin->register();
 PVE::Network::SDN::VlanPlugin->register();
 PVE::Network::SDN::VxlanPlugin->register();
 PVE::Network::SDN::FrrPlugin->register();
+PVE::Network::SDN::OVSFaucetPlugin->register();
+PVE::Network::SDN::FaucetPlugin->register();
 PVE::Network::SDN::Plugin->init();
 
 
@@ -203,6 +207,21 @@ sub generate_controller_config {

$controller_plugin->generate_controller_transport_config($plugin_config, 
$controller, $id, $uplinks, $config);
}
}
+   } elsif ($role eq 'vnet') {
+   my $transportid = $plugin_config->{transportzone};
+   if ($transportid) {
+   my $transport = $sdn_cfg->{ids}->{$transportid};
+   if ($transport) {
+   my $controllerid = $transport->{controller};
+   if ($controllerid) {
+   my $controller = $sdn_cfg->{ids}->{$controllerid};
+   if ($controller) {
+   my $controller_plugin = 
PVE::Network::SDN::Plugin->lookup($controller->{type});
+   
$controller_plugin->generate_controller_vnet_config($plugin_config, 
$controller, $transportid, $id, $config);
+   }
+   }
+   }
+   }
}
 }
 
diff --git a/PVE/Network/SDN/FaucetPlugin.pm b/PVE/Network/SDN/FaucetPlugin.pm
new file mode 100644
index 000..9e313c3
--- /dev/null
+++ b/PVE/Network/SDN/FaucetPlugin.pm
@@ -0,0 +1,102 @@
+package PVE::Network::SDN::FaucetPlugin;
+
+use strict;
+use warnings;
+use PVE::Network::SDN::Plugin;
+use PVE::Tools;
+use PVE::INotify;
+use PVE::JSONSchema qw(get_standard_option);
+use CPAN::Meta::YAML;
+use Encode;
+
+use base('PVE::Network::SDN::Plugin');
+
+sub type {
+return 'faucet';
+}
+
+sub plugindata {
+return {
+role => 'controller',
+};
+}
+
+sub properties {
+return {
+};
+}
+
+# Plugin implementation
+sub generate_controller_config {
+my ($class, $plugin_config, $router, $id, $uplinks, $config) = @_;
+
+}
+
+sub generate_controller_transport_config {
+my ($class, $plugin_config, $router, $id, $uplinks, $config) = @_;
+
+my $dpid = $plugin_config->{'dp-id'};
+my $dphex = printf("%x",$dpid);
+
+my $transport_config = {
+   dp_id => $dphex,
+   hardware => "Open vSwitch",
+  };
+
+$config->{faucet}->{dps}->{$id} = $transport_config;
+
+}
+
+
+sub generate_controller_vnet_config {
+my ($class, $plugin_config, $controller, $transportid, $vnetid, $config) = 
@_;
+
+my $mac = $plugin_config->{mac};
+my $ipv4 = $plugin_config->{ipv4};
+my $ipv6 = $plugin_config->{ipv6};
+my $tag = $plugin_config->{tag};
+my $alias = $plugin_config->{alias};
+
+my @ips = ();
+push @ips, $ipv4 if $ipv4;
+push @ips, $ipv6 if $ipv6;
+
+my $vlan_config = { vid => $tag };
+
+$vlan_config->{description} = $alias if $alias;
+$vlan_config->{faucet_mac} = $mac if $mac;
+$vlan_config->{faucet_vips} = \@ips if scalar @ips > 0;
+
+$config->{faucet}->{vlans}->{$vnetid} = $vlan_config;
+
+push(@{$config->{faucet}->{routers}->{$transportid}->{vlans}} , $vnetid);
+
+}
+
+sub on_delete_hook {
+my ($class, $routerid, $sdn_cfg) = @_;
+
+}
+
+sub on_update_hook {
+my ($class, $routerid, $sdn_cfg) = @_;
+
+}
+
+sub write_controller_config {
+

[pve-devel] [PATCH pve-network 4/8] add evpnplugin (splitted from vxlanplugin)

2019-09-30 Thread Alexandre Derumier
Signed-off-by: Alexandre Derumier 
---
 PVE/API2/Network/SDN.pm|   1 +
 PVE/Network/SDN.pm |   2 +
 PVE/Network/SDN/EvpnPlugin.pm  | 200 +
 PVE/Network/SDN/Makefile   |   2 +-
 PVE/Network/SDN/VxlanPlugin.pm |  54 -
 test/documentation.txt |   4 +-
 6 files changed, 206 insertions(+), 57 deletions(-)
 create mode 100644 PVE/Network/SDN/EvpnPlugin.pm

diff --git a/PVE/API2/Network/SDN.pm b/PVE/API2/Network/SDN.pm
index e4ed5cc..cbd393e 100644
--- a/PVE/API2/Network/SDN.pm
+++ b/PVE/API2/Network/SDN.pm
@@ -14,6 +14,7 @@ use PVE::Network::SDN::VnetPlugin;
 use PVE::Network::SDN::FrrPlugin;
 use PVE::Network::SDN::OVSFaucetPlugin;
 use PVE::Network::SDN::FaucetPlugin;
+use PVE::Network::SDN::EvpnPlugin;
 
 use Storable qw(dclone);
 use PVE::JSONSchema qw(get_standard_option);
diff --git a/PVE/Network/SDN.pm b/PVE/Network/SDN.pm
index 1946bc5..137f9f9 100644
--- a/PVE/Network/SDN.pm
+++ b/PVE/Network/SDN.pm
@@ -15,6 +15,7 @@ use PVE::Network::SDN::VxlanPlugin;
 use PVE::Network::SDN::FrrPlugin;
 use PVE::Network::SDN::OVSFaucetPlugin;
 use PVE::Network::SDN::FaucetPlugin;
+use PVE::Network::SDN::EvpnPlugin;
 
 PVE::Network::SDN::VnetPlugin->register();
 PVE::Network::SDN::VlanPlugin->register();
@@ -22,6 +23,7 @@ PVE::Network::SDN::VxlanPlugin->register();
 PVE::Network::SDN::FrrPlugin->register();
 PVE::Network::SDN::OVSFaucetPlugin->register();
 PVE::Network::SDN::FaucetPlugin->register();
+PVE::Network::SDN::EvpnPlugin->register();
 PVE::Network::SDN::Plugin->init();
 
 
diff --git a/PVE/Network/SDN/EvpnPlugin.pm b/PVE/Network/SDN/EvpnPlugin.pm
new file mode 100644
index 000..f570f2f
--- /dev/null
+++ b/PVE/Network/SDN/EvpnPlugin.pm
@@ -0,0 +1,200 @@
+package PVE::Network::SDN::EvpnPlugin;
+
+use strict;
+use warnings;
+use PVE::Network::SDN::Plugin;
+use PVE::Tools qw($IPV4RE);
+use PVE::INotify;
+
+use base('PVE::Network::SDN::VxlanPlugin');
+
+sub type {
+return 'evpn';
+}
+
+sub plugindata {
+return {
+role => 'transport',
+};
+}
+
+sub properties {
+return {
+   'vrf' => {
+   description => "vrf name.",
+   type => 'string',  #fixme: format
+   },
+   'vrf-vxlan' => {
+   type => 'integer',
+   description => "l3vni.",
+   },
+   'controller' => {
+   type => 'string',
+   description => "Frr router name",
+   },
+};
+}
+
+sub options {
+
+return {
+   'uplink-id' => { optional => 0 },
+'vxlan-allowed' => { optional => 1 },
+'vrf' => { optional => 0 },
+'vrf-vxlan' => { optional => 0 },
+'controller' => { optional => 0 },
+};
+}
+
+# Plugin implementation
+sub generate_sdn_config {
+my ($class, $plugin_config, $zoneid, $vnetid, $vnet, $uplinks, $config) = 
@_;
+
+my $tag = $vnet->{tag};
+my $alias = $vnet->{alias};
+my $ipv4 = $vnet->{ipv4};
+my $ipv6 = $vnet->{ipv6};
+my $mac = $vnet->{mac};
+
+my $uplink = $plugin_config->{'uplink-id'};
+my $vxlanallowed = $plugin_config->{'vxlan-allowed'};
+my $vrf = $plugin_config->{'vrf'};
+my $vrfvxlan = $plugin_config->{'vrf-vxlan'};
+
+die "missing vxlan tag" if !$tag;
+my $iface = "uplink$uplink";
+my $ifaceip = "";
+
+if($uplinks->{$uplink}->{name}) {
+   $iface = $uplinks->{$uplink}->{name};
+   $ifaceip = 
PVE::Network::SDN::Plugin::get_first_local_ipv4_from_interface($iface);
+}
+
+my $mtu = 1450;
+$mtu = $uplinks->{$uplink}->{mtu} - 50 if $uplinks->{$uplink}->{mtu};
+$mtu = $vnet->{mtu} if $vnet->{mtu};
+
+#vxlan interface
+my @iface_config = ();
+push @iface_config, "vxlan-id $tag";
+
+push @iface_config, "vxlan-local-tunnelip $ifaceip" if $ifaceip;
+push @iface_config, "bridge-learning off";
+push @iface_config, "bridge-arp-nd-suppress on";
+
+push @iface_config, "mtu $mtu" if $mtu;
+push(@{$config->{"vxlan$vnetid"}}, @iface_config) if 
!$config->{"vxlan$vnetid"};
+
+#vnet bridge
+@iface_config = ();
+push @iface_config, "address $ipv4" if $ipv4;
+push @iface_config, "address $ipv6" if $ipv6;
+push @iface_config, "hwaddress $mac" if $mac;
+push @iface_config, "bridge_ports vxlan$vnetid";
+push @iface_config, "bridge_stp off";
+push @iface_config, "bridge_fd 0";
+push @iface_config, "mtu $mtu" if $mtu;
+push @iface_config, "alias $alias" if $alias;
+push @iface_config, "ip-forward on" if $ipv4;
+push @iface_config, "ip6-forward on" if $ipv6;
+push @iface_config, "arp-accept on" if $ipv4||$ipv6;
+push @iface_config, "vrf $vrf" if $vrf;
+push(@{$config->{$vnetid}}, @iface_config) if !$config->{$vnetid};
+
+if ($vrf) {
+   #vrf interface
+   @iface_config = ();
+   push @iface_config, "vrf-table auto";
+   push(@{$config->{$vrf}}, @iface_config) if !$config->{$vrf};
+
+   if ($vrfvxlan) {
+   #l3vni vxlan interface
+   my $iface_vxla

[pve-devel] [PATCH pve-network 5/8] add controller_reload

2019-09-30 Thread Alexandre Derumier
Signed-off-by: Alexandre Derumier 
---
 PVE/Network/SDN.pm  | 17 +
 PVE/Network/SDN/FaucetPlugin.pm | 11 +++
 PVE/Network/SDN/FrrPlugin.pm| 18 ++
 PVE/Network/SDN/Plugin.pm   |  6 ++
 4 files changed, 52 insertions(+)

diff --git a/PVE/Network/SDN.pm b/PVE/Network/SDN.pm
index 137f9f9..8e96084 100644
--- a/PVE/Network/SDN.pm
+++ b/PVE/Network/SDN.pm
@@ -230,6 +230,23 @@ sub generate_controller_config {
 return $config;
 }
 
+
+sub reload_controller {
+
+my $sdn_cfg = PVE::Cluster::cfs_read_file('sdn.cfg');
+return if !$sdn_cfg;
+
+foreach my $id (keys %{$sdn_cfg->{ids}}) {
+   my $plugin_config = $sdn_cfg->{ids}->{$id};
+   my $plugin = PVE::Network::SDN::Plugin->lookup($plugin_config->{type});
+   my $pd = $plugin->plugindata();
+   my $role = $pd->{role};
+   if ($role eq 'controller') {
+   $plugin->reload_controller();
+   }
+}
+}
+
 sub write_etc_network_config {
 my ($rawconfig) = @_;
 
diff --git a/PVE/Network/SDN/FaucetPlugin.pm b/PVE/Network/SDN/FaucetPlugin.pm
index 9e313c3..fe75efb 100644
--- a/PVE/Network/SDN/FaucetPlugin.pm
+++ b/PVE/Network/SDN/FaucetPlugin.pm
@@ -98,5 +98,16 @@ sub write_controller_config {
 $writefh->close();
 }
 
+sub reload_controller {
+my ($class) = @_;
+
+my $conf_file = "/etc/faucet/faucet.yaml";
+my $bin_path = "/usr/bin/faucet";
+
+if (-e $conf_file && -e $bin_path) {
+PVE::Tools::run_command(['systemctl', 'reload', 'faucet']);
+}
+}
+
 1;
 
diff --git a/PVE/Network/SDN/FrrPlugin.pm b/PVE/Network/SDN/FrrPlugin.pm
index 532247a..3410844 100644
--- a/PVE/Network/SDN/FrrPlugin.pm
+++ b/PVE/Network/SDN/FrrPlugin.pm
@@ -290,6 +290,24 @@ sub write_controller_config {
 $writefh->close();
 }
 
+sub reload_controller {
+my ($class) = @_;
+
+my $conf_file = "/etc/frr/frr.conf";
+my $bin_path = "/usr/bin/vtysh";
+
+my $err = sub {
+   my $line = shift;
+   if ($line =~ /^line (\S+)/) {
+   print "$line \n";
+   }
+};
+
+if (-e $conf_file && -e $bin_path) {
+   PVE::Tools::run_command([$bin_path, '-m', '-f', $conf_file], outfunc => 
{}, errfunc => $err);
+}
+}
+
 1;
 
 
diff --git a/PVE/Network/SDN/Plugin.pm b/PVE/Network/SDN/Plugin.pm
index 605fd06..0c6eaf0 100644
--- a/PVE/Network/SDN/Plugin.pm
+++ b/PVE/Network/SDN/Plugin.pm
@@ -88,6 +88,12 @@ sub write_controller_config {
 die "please implement inside plugin";
 }
 
+sub controller_reload {
+my ($class) = @_;
+
+die "please implement inside plugin";
+}
+
 sub on_delete_hook {
 my ($class, $sndid, $scfg) = @_;
 
-- 
2.20.1

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH pve-network 7/8] add qinq plugin

2019-09-30 Thread Alexandre Derumier
move code from vlanplugin, add transport tag option

Signed-off-by: Alexandre Derumier 
---
 PVE/API2/Network/SDN.pm   |  1 +
 PVE/Network/SDN.pm|  2 +
 PVE/Network/SDN/Makefile  |  2 +-
 PVE/Network/SDN/QinQPlugin.pm | 81 +++
 PVE/Network/SDN/VlanPlugin.pm | 19 
 5 files changed, 85 insertions(+), 20 deletions(-)
 create mode 100644 PVE/Network/SDN/QinQPlugin.pm

diff --git a/PVE/API2/Network/SDN.pm b/PVE/API2/Network/SDN.pm
index 8294cb8..36d293d 100644
--- a/PVE/API2/Network/SDN.pm
+++ b/PVE/API2/Network/SDN.pm
@@ -15,6 +15,7 @@ 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);
diff --git a/PVE/Network/SDN.pm b/PVE/Network/SDN.pm
index 8e8e637..96f76d1 100644
--- a/PVE/Network/SDN.pm
+++ b/PVE/Network/SDN.pm
@@ -16,6 +16,7 @@ use PVE::Network::SDN::FaucetPlugin;
 use PVE::Network::SDN::FaucetControllerPlugin;
 use PVE::Network::SDN::EvpnPlugin;
 use PVE::Network::SDN::EvpnControllerPlugin;
+use PVE::Network::SDN::QinQPlugin;
 
 PVE::Network::SDN::VnetPlugin->register();
 PVE::Network::SDN::VlanPlugin->register();
@@ -24,6 +25,7 @@ PVE::Network::SDN::FaucetControllerPlugin->register();
 PVE::Network::SDN::FaucetPlugin->register();
 PVE::Network::SDN::EvpnPlugin->register();
 PVE::Network::SDN::EvpnControllerPlugin->register();
+PVE::Network::SDN::QinQPlugin->register();
 PVE::Network::SDN::Plugin->init();
 
 
diff --git a/PVE/Network/SDN/Makefile b/PVE/Network/SDN/Makefile
index ba8f903..232db52 100644
--- a/PVE/Network/SDN/Makefile
+++ b/PVE/Network/SDN/Makefile
@@ -1,4 +1,4 @@
-SOURCES=Plugin.pm VnetPlugin.pm VlanPlugin.pm VxlanPlugin.pm 
FaucetControllerPlugin.pm FaucetPlugin.pm EvpnPlugin.pm EvpnControllerPlugin.pm
+SOURCES=Plugin.pm VnetPlugin.pm VlanPlugin.pm VxlanPlugin.pm 
FaucetControllerPlugin.pm FaucetPlugin.pm EvpnPlugin.pm EvpnControllerPlugin.pm 
QinQPlugin.pm
 
 
 PERL5DIR=${DESTDIR}/usr/share/perl5
diff --git a/PVE/Network/SDN/QinQPlugin.pm b/PVE/Network/SDN/QinQPlugin.pm
new file mode 100644
index 000..9f40e84
--- /dev/null
+++ b/PVE/Network/SDN/QinQPlugin.pm
@@ -0,0 +1,81 @@
+package PVE::Network::SDN::QinQPlugin;
+
+use strict;
+use warnings;
+use PVE::Network::SDN::VlanPlugin;
+
+use base('PVE::Network::SDN::VlanPlugin');
+
+sub type {
+return 'qinq';
+}
+
+sub plugindata {
+return {
+   role => 'transport',
+};
+}
+
+sub properties {
+return {
+   'vlan-protocol' => {
+   type => 'string',
+enum => ['802.1q', '802.1ad'],
+   default => '802.1q',
+   optional => 1,
+   description => "vlan protocol",
+   }
+};
+}
+
+sub options {
+
+return {
+   'uplink-id' => { optional => 0 },
+   'tag' => { optional => 0 },
+'vlan-allowed' => { optional => 1 },
+   'vlan-protocol' => { optional => 1 },
+};
+}
+
+# Plugin implementation
+sub generate_sdn_config {
+my ($class, $plugin_config, $zoneid, $vnetid, $vnet, $uplinks, $config) = 
@_;
+
+my $tag = $vnet->{tag};
+my $transport_tag = $plugin_config->{tag};
+my $mtu = $vnet->{mtu};
+my $alias = $vnet->{alias};
+my $vlanprotocol = $plugin_config->{'vlan-protocol'};
+my $uplink = $plugin_config->{'uplink-id'};
+my $vlanallowed = $plugin_config->{'vlan-allowed'};
+
+die "missing vlan tag" if !$tag;
+die "missing transport vlan tag" if !$transport_tag;
+
+my $iface = $uplinks->{$uplink}->{name};
+$iface = "uplink${uplink}" if !$iface;
+$iface .= ".$transport_tag";
+
+#tagged interface
+my @iface_config = ();
+push @iface_config, "vlan-protocol $vlanprotocol" if $vlanprotocol;
+push @iface_config, "mtu $mtu" if $mtu;
+push(@{$config->{$iface}}, @iface_config) if !$config->{$iface};
+
+$iface .= ".$tag";
+#vnet bridge
+@iface_config = ();
+push @iface_config, "bridge_ports $iface";
+push @iface_config, "bridge_stp off";
+push @iface_config, "bridge_fd 0";
+push @iface_config, "mtu $mtu" if $mtu;
+push @iface_config, "alias $alias" if $alias;
+push(@{$config->{$vnetid}}, @iface_config) if !$config->{$vnetid};
+
+return $config;
+}
+
+1;
+
+
diff --git a/PVE/Network/SDN/VlanPlugin.pm b/PVE/Network/SDN/VlanPlugin.pm
index 6078206..5a38f59 100644
--- a/PVE/Network/SDN/VlanPlugin.pm
+++ b/PVE/Network/SDN/VlanPlugin.pm
@@ -36,17 +36,6 @@ sub properties {
type => 'string', format => 'pve-sdn-vlanrange',
description => "Allowed vlan range",
},
-   'vlan-aware' => {
-type => 'boolean',
-   description => "enable 802.1q stacked vlan",
-   },
-   'vlan-protocol' => {
-   type => 'string',
-enum => ['802.1q', '802.1ad'],
-   default => '802.1q',
-   optional => 1,
-  

[pve-devel] [PATCH pve-network 0/8] generic sdn controller plugins + improvments

2019-09-30 Thread Alexandre Derumier
This patch serie mainly rework the plugins to manage sdn controllers.
currently it was working with frr only,
now it's possible to define differents plugins for sdn controllers.
Frr specific code has been move to his own plugins too.

For true sdn, we have 2 plugins, 1 for dataplane (switch/bridge setup),
1 for controlplane (the controller).
(As we can have multiple dataplanes for 1 controller)


I have added a (not fully working yet) poc with faucet sdn controller plugin.

I have made also split of some plugins (evpn,qinq) to their own plugins.


Alexandre Derumier (8):
  make sdn controller plugin generic
  vxlan: move transport controller config to frrplugin
  add faucet sdn controller plugins
  add evpnplugin (splitted from vxlanplugin)
  add controller_reload
  rename plugins with controllers
  add qinq plugin
  api2 : sdn : add role and type to index

 PVE/API2/Network/SDN.pm   |  18 +-
 PVE/Network/SDN.pm| 180 +
 PVE/Network/SDN/EvpnControllerPlugin.pm   | 313 ++
 PVE/Network/SDN/EvpnPlugin.pm | 200 ++
 PVE/Network/SDN/FaucetControllerPlugin.pm | 113 
 PVE/Network/SDN/FaucetPlugin.pm   |  76 ++
 PVE/Network/SDN/FrrPlugin.pm  | 142 --
 PVE/Network/SDN/Makefile  |   2 +-
 PVE/Network/SDN/Plugin.pm |  19 +-
 PVE/Network/SDN/QinQPlugin.pm |  81 ++
 PVE/Network/SDN/VlanPlugin.pm |  25 +-
 PVE/Network/SDN/VnetPlugin.pm |   6 +
 PVE/Network/SDN/VxlanPlugin.pm| 110 +---
 test/documentation.txt|   8 +-
 test/generateconfig.pl|  10 +-
 15 files changed, 910 insertions(+), 393 deletions(-)
 create mode 100644 PVE/Network/SDN/EvpnControllerPlugin.pm
 create mode 100644 PVE/Network/SDN/EvpnPlugin.pm
 create mode 100644 PVE/Network/SDN/FaucetControllerPlugin.pm
 create mode 100644 PVE/Network/SDN/FaucetPlugin.pm
 delete mode 100644 PVE/Network/SDN/FrrPlugin.pm
 create mode 100644 PVE/Network/SDN/QinQPlugin.pm

-- 
2.20.1

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH pve-network 8/8] api2 : sdn : add role and type to index

2019-09-30 Thread Alexandre Derumier
Signed-off-by: Alexandre Derumier 
---
 PVE/API2/Network/SDN.pm | 11 ++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/PVE/API2/Network/SDN.pm b/PVE/API2/Network/SDN.pm
index 36d293d..b6dd23e 100644
--- a/PVE/API2/Network/SDN.pm
+++ b/PVE/API2/Network/SDN.pm
@@ -61,7 +61,10 @@ __PACKAGE__->register_method ({
type => 'array',
items => {
type => "object",
-   properties => { sdn => { type => 'string'} },
+   properties => { sdn => { type => 'string'}, 
+   type => { type => 'string'},
+   role => { type => 'string'}
+ },
},
links => [ { rel => 'child', href => "{sdn}" } ],
 },
@@ -82,6 +85,12 @@ __PACKAGE__->register_method ({
 
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;
}
 
-- 
2.20.1

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH pve-network 2/8] vxlan: move transport controller config to frrplugin

2019-09-30 Thread Alexandre Derumier
To be able to use differents controllers model

Signed-off-by: Alexandre Derumier 
---
 PVE/Network/SDN.pm |  4 +--
 PVE/Network/SDN/FrrPlugin.pm   | 51 ++
 PVE/Network/SDN/VxlanPlugin.pm | 50 -
 3 files changed, 53 insertions(+), 52 deletions(-)

diff --git a/PVE/Network/SDN.pm b/PVE/Network/SDN.pm
index 1e5ba67..b5d98b7 100644
--- a/PVE/Network/SDN.pm
+++ b/PVE/Network/SDN.pm
@@ -199,8 +199,8 @@ sub generate_controller_config {
if ($controllerid) {
my $controller = $sdn_cfg->{ids}->{$controllerid};
if ($controller) {
-   my $controller_plugin = 
PVE::Network::SDN::Plugin->lookup($plugin_config->{type});
-   
$controller_plugin->generate_controller_config($plugin_config, $controller, 
$id, $uplinks, $config);
+   my $controller_plugin = 
PVE::Network::SDN::Plugin->lookup($controller->{type});
+   
$controller_plugin->generate_controller_transport_config($plugin_config, 
$controller, $id, $uplinks, $config);
}
}
}
diff --git a/PVE/Network/SDN/FrrPlugin.pm b/PVE/Network/SDN/FrrPlugin.pm
index 455b185..532247a 100644
--- a/PVE/Network/SDN/FrrPlugin.pm
+++ b/PVE/Network/SDN/FrrPlugin.pm
@@ -119,6 +119,56 @@ sub generate_controller_config {
 return $config;
 }
 
+sub generate_controller_transport_config {
+my ($class, $plugin_config, $router, $id, $uplinks, $config) = @_;
+
+my $vrf = $plugin_config->{'vrf'};
+my $vrfvxlan = $plugin_config->{'vrf-vxlan'};
+my $asn = $router->{asn};
+my $gatewaynodes = $router->{'gateway-nodes'};
+
+return if !$vrf || !$vrfvxlan || !$asn;
+
+#vrf
+my @router_config = ();
+push @router_config, "vni $vrfvxlan";
+push(@{$config->{frr}->{vrf}->{"$vrf"}}, @router_config);
+
+@router_config = ();
+
+my $is_gateway = undef;
+my $local_node = PVE::INotify::nodename();
+
+foreach my $gatewaynode (PVE::Tools::split_list($gatewaynodes)) {
+   $is_gateway = 1 if $gatewaynode eq $local_node;
+}
+
+if ($is_gateway) {
+
+   @router_config = ();
+   #import /32 routes of evpn network from vrf1 to default vrf (for packet 
return)
+   #frr 7.1 tag is bugged -> works fine with 7.1 stable 
branch(20190829-02-g6ba76bbc1)
+   #https://github.com/FRRouting/frr/issues/4905
+   push @router_config, "import vrf $vrf";
+   push(@{$config->{frr}->{router}->{"bgp 
$asn"}->{"address-family"}->{"ipv4 unicast"}}, @router_config);
+   push(@{$config->{frr}->{router}->{"bgp 
$asn"}->{"address-family"}->{"ipv6 unicast"}}, @router_config);
+
+   @router_config = ();
+   #redistribute connected to be able to route to local vms on the gateway
+   push @router_config, "redistribute connected";
+   push(@{$config->{frr}->{router}->{"bgp $asn vrf 
$vrf"}->{"address-family"}->{"ipv4 unicast"}}, @router_config);
+   push(@{$config->{frr}->{router}->{"bgp $asn vrf 
$vrf"}->{"address-family"}->{"ipv6 unicast"}}, @router_config);
+
+   @router_config = ();
+   #add default originate to announce 0.0.0.0/0 type5 route in evpn
+   push @router_config, "default-originate ipv4";
+   push @router_config, "default-originate ipv6";
+   push(@{$config->{frr}->{router}->{"bgp $asn vrf 
$vrf"}->{"address-family"}->{"l2vpn evpn"}}, @router_config);
+}
+
+return $config;
+}
+
 sub on_delete_hook {
 my ($class, $routerid, $sdn_cfg) = @_;
 
@@ -242,3 +292,4 @@ sub write_controller_config {
 
 1;
 
+
diff --git a/PVE/Network/SDN/VxlanPlugin.pm b/PVE/Network/SDN/VxlanPlugin.pm
index 986a250..d39a533 100644
--- a/PVE/Network/SDN/VxlanPlugin.pm
+++ b/PVE/Network/SDN/VxlanPlugin.pm
@@ -188,56 +188,6 @@ sub generate_sdn_config {
 return $config;
 }
 
-sub generate_controller_config {
-my ($class, $plugin_config, $router, $id, $uplinks, $config) = @_;
-
-my $vrf = $plugin_config->{'vrf'};
-my $vrfvxlan = $plugin_config->{'vrf-vxlan'};
-my $asn = $router->{asn};
-my $gatewaynodes = $router->{'gateway-nodes'};
-
-return if !$vrf || !$vrfvxlan || !$asn;
-
-#vrf
-my @router_config = ();
-push @router_config, "vni $vrfvxlan";
-push(@{$config->{frr}->{vrf}->{"$vrf"}}, @router_config);
-
-@router_config = ();
-
-my $is_gateway = undef;
-my $local_node = PVE::INotify::nodename();
-
-foreach my $gatewaynode (PVE::Tools::split_list($gatewaynodes)) {
-   $is_gateway = 1 if $gatewaynode eq $local_node;
-}
-
-if ($is_gateway) {
-
-   @router_config = ();
-   #import /32 routes of evpn network from vrf1 to default vrf (for packet 
return)
-   #frr 7.1 tag is bugged -> works fine with 7.1 stable 
branch(20190829-02-g6ba76bbc1)
-   #https://github.com/FRRouting/frr/issues/4905
-   push @router_config, "import vrf $vrf";
-   push(@{$config->{frr}->{router}->{"bgp 
$asn"}->{"address-family"}->{"ipv4 uni

[pve-devel] [PATCH pve-network 6/8] rename plugins with controllers

2019-09-30 Thread Alexandre Derumier
For true sdn, We have 2 plugins, 1 for dataplane (switch), 1 for controlplane 
(controller)

rename:

- Frr to EvpnController
- Faucet to FaucetController
- OvsFaucet to Faucet

Signed-off-by: Alexandre Derumier 
---
 PVE/API2/Network/SDN.pm   |   4 +-
 PVE/Network/SDN.pm|   8 +-
 .../{FrrPlugin.pm => EvpnControllerPlugin.pm} |   4 +-
 PVE/Network/SDN/FaucetControllerPlugin.pm | 113 +
 PVE/Network/SDN/FaucetPlugin.pm   | 117 ++
 PVE/Network/SDN/Makefile  |   2 +-
 PVE/Network/SDN/OVSFaucetPlugin.pm|  76 
 test/documentation.txt|   4 +-
 8 files changed, 164 insertions(+), 164 deletions(-)
 rename PVE/Network/SDN/{FrrPlugin.pm => EvpnControllerPlugin.pm} (99%)
 create mode 100644 PVE/Network/SDN/FaucetControllerPlugin.pm
 delete mode 100644 PVE/Network/SDN/OVSFaucetPlugin.pm

diff --git a/PVE/API2/Network/SDN.pm b/PVE/API2/Network/SDN.pm
index cbd393e..8294cb8 100644
--- a/PVE/API2/Network/SDN.pm
+++ b/PVE/API2/Network/SDN.pm
@@ -11,9 +11,9 @@ use PVE::Network::SDN::Plugin;
 use PVE::Network::SDN::VlanPlugin;
 use PVE::Network::SDN::VxlanPlugin;
 use PVE::Network::SDN::VnetPlugin;
-use PVE::Network::SDN::FrrPlugin;
-use PVE::Network::SDN::OVSFaucetPlugin;
+use PVE::Network::SDN::FaucetControllerPlugin;
 use PVE::Network::SDN::FaucetPlugin;
+use PVE::Network::SDN::EvpnControllerPlugin;
 use PVE::Network::SDN::EvpnPlugin;
 
 use Storable qw(dclone);
diff --git a/PVE/Network/SDN.pm b/PVE/Network/SDN.pm
index 8e96084..8e8e637 100644
--- a/PVE/Network/SDN.pm
+++ b/PVE/Network/SDN.pm
@@ -12,18 +12,18 @@ use PVE::Network::SDN::Plugin;
 use PVE::Network::SDN::VnetPlugin;
 use PVE::Network::SDN::VlanPlugin;
 use PVE::Network::SDN::VxlanPlugin;
-use PVE::Network::SDN::FrrPlugin;
-use PVE::Network::SDN::OVSFaucetPlugin;
 use PVE::Network::SDN::FaucetPlugin;
+use PVE::Network::SDN::FaucetControllerPlugin;
 use PVE::Network::SDN::EvpnPlugin;
+use PVE::Network::SDN::EvpnControllerPlugin;
 
 PVE::Network::SDN::VnetPlugin->register();
 PVE::Network::SDN::VlanPlugin->register();
 PVE::Network::SDN::VxlanPlugin->register();
-PVE::Network::SDN::FrrPlugin->register();
-PVE::Network::SDN::OVSFaucetPlugin->register();
+PVE::Network::SDN::FaucetControllerPlugin->register();
 PVE::Network::SDN::FaucetPlugin->register();
 PVE::Network::SDN::EvpnPlugin->register();
+PVE::Network::SDN::EvpnControllerPlugin->register();
 PVE::Network::SDN::Plugin->init();
 
 
diff --git a/PVE/Network/SDN/FrrPlugin.pm 
b/PVE/Network/SDN/EvpnControllerPlugin.pm
similarity index 99%
rename from PVE/Network/SDN/FrrPlugin.pm
rename to PVE/Network/SDN/EvpnControllerPlugin.pm
index 3410844..b2c9345 100644
--- a/PVE/Network/SDN/FrrPlugin.pm
+++ b/PVE/Network/SDN/EvpnControllerPlugin.pm
@@ -1,4 +1,4 @@
-package PVE::Network::SDN::FrrPlugin;
+package PVE::Network::SDN::EvpnControllerPlugin;
 
 use strict;
 use warnings;
@@ -10,7 +10,7 @@ use PVE::JSONSchema qw(get_standard_option);
 use base('PVE::Network::SDN::Plugin');
 
 sub type {
-return 'frr';
+return 'evpncontroller';
 }
 
 sub plugindata {
diff --git a/PVE/Network/SDN/FaucetControllerPlugin.pm 
b/PVE/Network/SDN/FaucetControllerPlugin.pm
new file mode 100644
index 000..ee15bdf
--- /dev/null
+++ b/PVE/Network/SDN/FaucetControllerPlugin.pm
@@ -0,0 +1,113 @@
+package PVE::Network::SDN::FaucetControllerPlugin;
+
+use strict;
+use warnings;
+use PVE::Network::SDN::Plugin;
+use PVE::Tools;
+use PVE::INotify;
+use PVE::JSONSchema qw(get_standard_option);
+use CPAN::Meta::YAML;
+use Encode;
+
+use base('PVE::Network::SDN::Plugin');
+
+sub type {
+return 'faucetcontroller';
+}
+
+sub plugindata {
+return {
+role => 'controller',
+};
+}
+
+sub properties {
+return {
+};
+}
+
+# Plugin implementation
+sub generate_controller_config {
+my ($class, $plugin_config, $router, $id, $uplinks, $config) = @_;
+
+}
+
+sub generate_controller_transport_config {
+my ($class, $plugin_config, $router, $id, $uplinks, $config) = @_;
+
+my $dpid = $plugin_config->{'dp-id'};
+my $dphex = printf("%x",$dpid);
+
+my $transport_config = {
+   dp_id => $dphex,
+   hardware => "Open vSwitch",
+  };
+
+$config->{faucet}->{dps}->{$id} = $transport_config;
+
+}
+
+
+sub generate_controller_vnet_config {
+my ($class, $plugin_config, $controller, $transportid, $vnetid, $config) = 
@_;
+
+my $mac = $plugin_config->{mac};
+my $ipv4 = $plugin_config->{ipv4};
+my $ipv6 = $plugin_config->{ipv6};
+my $tag = $plugin_config->{tag};
+my $alias = $plugin_config->{alias};
+
+my @ips = ();
+push @ips, $ipv4 if $ipv4;
+push @ips, $ipv6 if $ipv6;
+
+my $vlan_config = { vid => $tag };
+
+$vlan_config->{description} = $alias if $alias;
+$vlan_config->{faucet_mac} = $mac if $mac;
+$vlan_config->{faucet_vip

[pve-devel] [PATCH pve-network 1/8] make sdn controller plugin generic

2019-09-30 Thread Alexandre Derumier
move all code for frr to frrplugin,
rename router option to controller.

This will allow to manage more controller in the future (ovn, faucet,)

Signed-off-by: Alexandre Derumier 
---
 PVE/Network/SDN.pm | 148 +++--
 PVE/Network/SDN/FrrPlugin.pm   | 114 +++--
 PVE/Network/SDN/Plugin.pm  |   8 +-
 PVE/Network/SDN/VlanPlugin.pm  |   6 ++
 PVE/Network/SDN/VnetPlugin.pm  |   6 ++
 PVE/Network/SDN/VxlanPlugin.pm |  24 --
 test/documentation.txt |   6 +-
 test/generateconfig.pl |  10 +--
 8 files changed, 179 insertions(+), 143 deletions(-)

diff --git a/PVE/Network/SDN.pm b/PVE/Network/SDN.pm
index 101464b..1e5ba67 100644
--- a/PVE/Network/SDN.pm
+++ b/PVE/Network/SDN.pm
@@ -162,7 +162,7 @@ sub generate_etc_network_config {
 return $raw_network_config;
 }
 
-sub generate_frr_config {
+sub generate_controller_config {
 
 my $sdn_cfg = PVE::Cluster::cfs_read_file('sdn.cfg');
 return if !$sdn_cfg;
@@ -184,124 +184,31 @@ sub generate_frr_config {
}
 }
 
-my $frr_cfg = undef;
-my $transport_cfg = undef;
-
-foreach my $id (keys %{$sdn_cfg->{ids}}) {
-   if ($sdn_cfg->{ids}->{$id}->{type} eq 'frr') {
-   $frr_cfg->{ids}->{$id} = $sdn_cfg->{ids}->{$id};
-   } elsif ($sdn_cfg->{ids}->{$id}->{type} ne 'vnet') {
-   $transport_cfg->{ids}->{$id} = $sdn_cfg->{ids}->{$id};
-   }
-}
-
-return undef if !$frr_cfg;
-
 #generate configuration
 my $config = {};
 
-foreach my $id (sort keys %{$frr_cfg->{ids}}) {
-   my $plugin_config = $frr_cfg->{ids}->{$id};
+foreach my $id (keys %{$sdn_cfg->{ids}}) {
+   my $plugin_config = $sdn_cfg->{ids}->{$id};
my $plugin = PVE::Network::SDN::Plugin->lookup($plugin_config->{type});
-   $plugin->generate_frr_config($plugin_config, $plugin_config, $id, 
$uplinks, $config);
-}
-
-foreach my $id (sort keys %{$transport_cfg->{ids}}) {
-   my $plugin_config = $transport_cfg->{ids}->{$id};
-   my $routerid = $plugin_config->{router};
-   if ($routerid) {
-   my $router = $frr_cfg->{ids}->{$routerid};
-   if ($router) {
-   my $plugin = 
PVE::Network::SDN::Plugin->lookup($plugin_config->{type});
-   $plugin->generate_frr_config($plugin_config, $router, $id, 
$uplinks, $config);
+   my $pd = $plugin->plugindata();
+   my $role = $pd->{role};
+   if ($role eq 'controller') {
+   $plugin->generate_controller_config($plugin_config, $plugin_config, 
$id, $uplinks, $config);
+   } elsif ($role eq 'transport') {
+   my $controllerid = $plugin_config->{controller};
+   if ($controllerid) {
+   my $controller = $sdn_cfg->{ids}->{$controllerid};
+   if ($controller) {
+   my $controller_plugin = 
PVE::Network::SDN::Plugin->lookup($plugin_config->{type});
+   
$controller_plugin->generate_controller_config($plugin_config, $controller, 
$id, $uplinks, $config);
+   }
}
}
 }
 
-my $final_config = [];
-push @{$final_config}, "log syslog informational";
-push @{$final_config}, "!";
-
-generate_frr_recurse($final_config, $config, undef, 0);
-
-push @{$final_config}, "!";
-push @{$final_config}, "line vty";
-push @{$final_config}, "!";
-
-my $raw_frr_config = join("\n", @{$final_config});
-return $raw_frr_config;
-}
-
-sub sort_frr_config {
-my $order = {};
-$order->{''} = 0;
-$order->{'vrf'} = 1;
-$order->{'ipv4 unicast'} = 1;
-$order->{'ipv6 unicast'} = 2;
-$order->{'l2vpn evpn'} = 3;
-
-my $a_val = 100;
-my $b_val = 100;
-
-$a_val = $order->{$a} if defined($order->{$a});
-$b_val = $order->{$b} if defined($order->{$b});
-
-if($a =~ /bgp (\d+)$/) {
-   $a_val = 2;
-}
-
-if($b =~ /bgp (\d+)$/) {
-   $b_val = 2;
-}
-
-return $a_val <=> $b_val;
+return $config;
 }
 
-sub generate_frr_recurse{
-   my ($final_config, $content, $parentkey, $level) = @_;
-
-   my $keylist = {};
-   $keylist->{vrf} = 1;
-   $keylist->{'address-family'} = 1;
-   $keylist->{router} = 1;
-
-   my $exitkeylist = {};
-   $exitkeylist->{vrf} = 1;
-   $exitkeylist->{'address-family'} = 1;
-
-   #fix me, 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 ref {}) {
-   foreach my $key (sort sort_frr_config keys %$content) {
-   if ($parentkey && defined($keylist->{$parentkey})) {
-   push @{$final_config}, $padding."!";
-   push @{$final_config}, $padding."$parentkey $key";
-   } else {
-   push @{$final_config}, $padding."$key" if $key ne '' &&

[pve-devel] [PATCH pve-manager] api2: network : reload sdn controller generic

2019-09-30 Thread Alexandre Derumier
From: root 

use config generation && reloading from plugins
(require my last pve-network patch serie)

Signed-off-by: Alexandre Derumier 
---
 PVE/API2/Network.pm | 25 +
 1 file changed, 5 insertions(+), 20 deletions(-)

diff --git a/PVE/API2/Network.pm b/PVE/API2/Network.pm
index fa605ba7..194b300a 100644
--- a/PVE/API2/Network.pm
+++ b/PVE/API2/Network.pm
@@ -554,22 +554,12 @@ __PACKAGE__->register_method({
my $new_config_file = "/etc/network/interfaces.new";
 
die "you need ifupdown2 to reload networking\n" if !-e 
'/usr/share/ifupdown2';
-   die "ifupdown2 reload is not compatible if openvswitch currently" if -x 
'/usr/bin/ovs-vsctl';
+   warn "openvswitch config can't be reloaded currently. Please reboot to 
apply ovs changes" if -x '/usr/bin/ovs-vsctl';
 
my $worker = sub {
 
rename($new_config_file, $current_config_file) if -e 
$new_config_file;
 
-   my $frr_config;
-   if ($have_sdn) {
-   my $network_config = 
PVE::Network::SDN::generate_etc_network_config();
-   PVE::Network::SDN::write_etc_network_config($network_config);
-
-   $frr_config = PVE::Network::SDN::generate_frr_config();
-   PVE::Network::SDN::write_frr_config($frr_config) if $frr_config;
-   }
-
-
my $err = sub {
my $line = shift;
if ($line =~ /(warning|error): (\S+):/) {
@@ -578,15 +568,10 @@ __PACKAGE__->register_method({
};
PVE::Tools::run_command(['ifreload', '-a'], errfunc => $err);
 
-   my $err_frr = sub {
-   my $line = shift;
-   if ($line =~ /^line (\S+)/) {
-   print "$line \n";
-   }
-   };
-
-   if ($frr_config && -e "/usr/bin/vtysh") {
-   PVE::Tools::run_command(['/usr/bin/vtysh', '-m', '-f', 
'/etc/frr/frr.conf'], outfunc => {}, errfunc => $err_frr);
+   if ($have_sdn) {
+   my $controller_config = 
PVE::Network::SDN::generate_controller_config();
+   PVE::Network::SDN::write_controller_config($controller_config) 
if ($controller_config);
+   PVE::Network::SDN::reload_controller();
}
};
return $rpcenv->fork_worker('srvreload', 'networking', $authuser, 
$worker);
-- 
2.20.1

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


Re: [pve-devel] [PATCH v2 container] don't duplicate lxc.idmap entries during restore

2019-09-30 Thread Oguz Bektas
seems good to me. (note: maybe send in again as separate mail? had to
edit the mail because commit message wasn't picked up right and apply with
--ignore-whitespace)

Tested-by: Oguz Bektas 

On Wed, Sep 25, 2019 at 02:37:32PM +0200, Fabian Grünbichler wrote:
> On September 25, 2019 1:30 pm, Oguz Bektas wrote:
> > merging $conf->{lxc} causes lxc.idmap entries to be duplicated in the
> > restored configuration. instead, we can overwrite the contents from the
> > extracted configuration file. this way we don't duplicate these entries.
> > (having duplicate idmap entries causes container to crash during start)
> > 
> > Co-developed-by: Stefan Reiter 
> > Signed-off-by: Oguz Bektas 
> 
> What about the following instead (note, generated with -w for 
> readability)? seems simpler, and with less potential for future breakage 
> ;)
> 
> From 8e0679858748be369d5ddc5695376b12504daa50 Mon Sep 17 00:00:00 2001
> From: =?UTF-8?q?Fabian=20Gr=C3=BCnbichler?= 
> Date: Wed, 25 Sep 2019 14:35:04 +0200
> Subject: [PATCH container] restore lxc.* entries once
> MIME-Version: 1.0
> Content-Type: text/plain; charset=UTF-8
> Content-Transfer-Encoding: 8bit
> 
> either via recover_config, OR via restore_configuration. non-root behaviour 
> stays the same.
> 
> Signed-off-by: Fabian Grünbichler 
> ---
>  src/PVE/API2/LXC.pm   | 4 ++--
>  src/PVE/LXC/Create.pm | 6 +-
>  2 files changed, 3 insertions(+), 7 deletions(-)
> 
> diff --git a/src/PVE/API2/LXC.pm b/src/PVE/API2/LXC.pm
> index 07280fb..28c9047 100644
> --- a/src/PVE/API2/LXC.pm
> +++ b/src/PVE/API2/LXC.pm
> @@ -353,11 +353,11 @@ __PACKAGE__->register_method({
>   my $orig_conf;
>   ($orig_conf, $orig_mp_param) = 
> PVE::LXC::Create::recover_config($archive);
>   $was_template = delete $orig_conf->{template};
> - # When we're root call 'restore_configuration' with 
> ristricted=0,
> + # When we're root call 'restore_configuration' with 
> restricted=0,
>   # causing it to restore the raw lxc entries, among 
> which there may be
>   # 'lxc.idmap' entries. We need to make sure that the 
> extracted contents
>   # of the container match up with the restored 
> configuration afterwards:
> - $conf->{lxc} = [grep { $_->[0] eq 'lxc.idmap' } 
> @{$orig_conf->{lxc}}];
> + $conf->{lxc} = $orig_conf->{lxc};
>   }
>   }
>   if ($storage_only_mode) {
> diff --git a/src/PVE/LXC/Create.pm b/src/PVE/LXC/Create.pm
> index a46a50c..241ca88 100644
> --- a/src/PVE/LXC/Create.pm
> +++ b/src/PVE/LXC/Create.pm
> @@ -176,18 +176,14 @@ sub restore_configuration {
>   # storage supports creating a template there
>   next if $key =~ /^template$/;
>  
> - if ($key eq 'lxc') {
> + if ($key eq 'lxc' && $restricted) {
>   my $lxc_list = $oldconf->{'lxc'};
> - if ($restricted) {
>   warn "skipping custom lxc options, restore manually as root:\n";
>   warn "\n";
>   foreach my $lxc_opt (@$lxc_list) {
>   warn "$lxc_opt->[0]: $lxc_opt->[1]\n"
>   }
>   warn "\n";
> - } else {
> - @{$conf->{$key}} = (@$lxc_list, @{$conf->{$key}});
> - }
>   next;
>   }
>  
> -- 
> 2.20.1
> 
> > ---
> >  src/PVE/LXC/Create.pm | 4 +++-
> >  1 file changed, 3 insertions(+), 1 deletion(-)
> > 
> > diff --git a/src/PVE/LXC/Create.pm b/src/PVE/LXC/Create.pm
> > index a46a50c..8b2cfc9 100644
> > --- a/src/PVE/LXC/Create.pm
> > +++ b/src/PVE/LXC/Create.pm
> > @@ -186,7 +186,9 @@ sub restore_configuration {
> > }
> > warn "\n";
> > } else {
> > -   @{$conf->{$key}} = (@$lxc_list, @{$conf->{$key}});
> > +   # $conf->{lxc} can only have lxc.idmap
> > +   # so we can overwrite the current $conf from $oldconf
> > +   $conf->{$key} = $lxc_list;
> > }
> > next;
> > }
> > -- 
> > 2.20.1
> > 
> > ___
> > pve-devel mailing list
> > pve-devel@pve.proxmox.com
> > https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
> > 
> > 
> 
> ___
> pve-devel mailing list
> pve-devel@pve.proxmox.com
> https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v2 pve-manager] api2: network : reload sdn controller generic

2019-09-30 Thread Alexandre Derumier
use config generation && reloading from plugins
(require my last pve-network patch serie)

Signed-off-by: Alexandre Derumier 
---
 PVE/API2/Network.pm | 25 +
 1 file changed, 5 insertions(+), 20 deletions(-)

diff --git a/PVE/API2/Network.pm b/PVE/API2/Network.pm
index fa605ba7..194b300a 100644
--- a/PVE/API2/Network.pm
+++ b/PVE/API2/Network.pm
@@ -554,22 +554,12 @@ __PACKAGE__->register_method({
my $new_config_file = "/etc/network/interfaces.new";
 
die "you need ifupdown2 to reload networking\n" if !-e 
'/usr/share/ifupdown2';
-   die "ifupdown2 reload is not compatible if openvswitch currently" if -x 
'/usr/bin/ovs-vsctl';
+   warn "openvswitch config can't be reloaded currently. Please reboot to 
apply ovs changes" if -x '/usr/bin/ovs-vsctl';
 
my $worker = sub {
 
rename($new_config_file, $current_config_file) if -e 
$new_config_file;
 
-   my $frr_config;
-   if ($have_sdn) {
-   my $network_config = 
PVE::Network::SDN::generate_etc_network_config();
-   PVE::Network::SDN::write_etc_network_config($network_config);
-
-   $frr_config = PVE::Network::SDN::generate_frr_config();
-   PVE::Network::SDN::write_frr_config($frr_config) if $frr_config;
-   }
-
-
my $err = sub {
my $line = shift;
if ($line =~ /(warning|error): (\S+):/) {
@@ -578,15 +568,10 @@ __PACKAGE__->register_method({
};
PVE::Tools::run_command(['ifreload', '-a'], errfunc => $err);
 
-   my $err_frr = sub {
-   my $line = shift;
-   if ($line =~ /^line (\S+)/) {
-   print "$line \n";
-   }
-   };
-
-   if ($frr_config && -e "/usr/bin/vtysh") {
-   PVE::Tools::run_command(['/usr/bin/vtysh', '-m', '-f', 
'/etc/frr/frr.conf'], outfunc => {}, errfunc => $err_frr);
+   if ($have_sdn) {
+   my $controller_config = 
PVE::Network::SDN::generate_controller_config();
+   PVE::Network::SDN::write_controller_config($controller_config) 
if ($controller_config);
+   PVE::Network::SDN::reload_controller();
}
};
return $rpcenv->fork_worker('srvreload', 'networking', $authuser, 
$worker);
-- 
2.20.1

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] applied: [PATCH RESEND container] restore lxc.* entries once

2019-09-30 Thread Fabian Grünbichler
either via recover_config, OR via restore_configuration. non-root behaviour 
stays the same.

Tested-by: Oguz Bektas 
Signed-off-by: Fabian Grünbichler 
---
Note: added Tested-by

 src/PVE/API2/LXC.pm   |  4 ++--
 src/PVE/LXC/Create.pm | 16 ++--
 2 files changed, 8 insertions(+), 12 deletions(-)

diff --git a/src/PVE/API2/LXC.pm b/src/PVE/API2/LXC.pm
index 07280fb..28c9047 100644
--- a/src/PVE/API2/LXC.pm
+++ b/src/PVE/API2/LXC.pm
@@ -353,11 +353,11 @@ __PACKAGE__->register_method({
my $orig_conf;
($orig_conf, $orig_mp_param) = 
PVE::LXC::Create::recover_config($archive);
$was_template = delete $orig_conf->{template};
-   # When we're root call 'restore_configuration' with 
ristricted=0,
+   # When we're root call 'restore_configuration' with 
restricted=0,
# causing it to restore the raw lxc entries, among 
which there may be
# 'lxc.idmap' entries. We need to make sure that the 
extracted contents
# of the container match up with the restored 
configuration afterwards:
-   $conf->{lxc} = [grep { $_->[0] eq 'lxc.idmap' } 
@{$orig_conf->{lxc}}];
+   $conf->{lxc} = $orig_conf->{lxc};
}
}
if ($storage_only_mode) {
diff --git a/src/PVE/LXC/Create.pm b/src/PVE/LXC/Create.pm
index a46a50c..241ca88 100644
--- a/src/PVE/LXC/Create.pm
+++ b/src/PVE/LXC/Create.pm
@@ -176,18 +176,14 @@ sub restore_configuration {
# storage supports creating a template there
next if $key =~ /^template$/;
 
-   if ($key eq 'lxc') {
+   if ($key eq 'lxc' && $restricted) {
my $lxc_list = $oldconf->{'lxc'};
-   if ($restricted) {
-   warn "skipping custom lxc options, restore manually as 
root:\n";
-   warn "\n";
-   foreach my $lxc_opt (@$lxc_list) {
-   warn "$lxc_opt->[0]: $lxc_opt->[1]\n"
-   }
-   warn "\n";
-   } else {
-   @{$conf->{$key}} = (@$lxc_list, @{$conf->{$key}});
+   warn "skipping custom lxc options, restore manually as root:\n";
+   warn "\n";
+   foreach my $lxc_opt (@$lxc_list) {
+   warn "$lxc_opt->[0]: $lxc_opt->[1]\n"
}
+   warn "\n";
next;
}
 
-- 
2.20.1


___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH manager] ui: qemubiosedit: add gettext to efi disk hint

2019-09-30 Thread Aaron Lauterer
Signed-off-by: Aaron Lauterer 
---

Put the hint in one line because AFAIU our tooling cannot handle
multiline gettext calls.

 www/manager6/qemu/QemuBiosEdit.js | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/www/manager6/qemu/QemuBiosEdit.js 
b/www/manager6/qemu/QemuBiosEdit.js
index 7283df74..54c0271d 100644
--- a/www/manager6/qemu/QemuBiosEdit.js
+++ b/www/manager6/qemu/QemuBiosEdit.js
@@ -9,8 +9,7 @@ Ext.define('PVE.qemu.BiosEdit', {
var EFIHint = Ext.createWidget({
xtype: 'displayfield', //submitValue is false, so we don't get 
submitted
userCls: 'pve-hint',
-   value: 'You need to add an EFI disk for storing the ' +
-   'EFI settings. See the online help for details.',
+   value: gettext('You need to add an EFI disk for storing the EFI 
settings. See the online help for details.'),
hidden: true
});
 
-- 
2.20.1


___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH qemu-server] qemu 4.0 : add Cascadelake-Server && KnightsMill cpu models

2019-09-30 Thread Alexandre Derumier
Signed-off-by: Alexandre Derumier 
---
 PVE/QemuServer.pm | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 70ed910..8376260 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -146,6 +146,9 @@ my $cpu_vendor_list = {
 'Skylake-Client-IBRS' => 'GenuineIntel',
 'Skylake-Server' => 'GenuineIntel',
 'Skylake-Server-IBRS' => 'GenuineIntel',
+'Cascadelake-Server' => 'GenuineIntel',
+KnightsMill => 'GenuineIntel',
+
 
 # AMD CPUs
 athlon => 'AuthenticAMD',
-- 
2.20.1

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH pve-manager] cpumodel: qemu 4.0: add Skylake-Server, Cascadelake-Server, KnightsMill

2019-09-30 Thread Alexandre Derumier
Signed-off-by: Alexandre Derumier 
---
 www/manager6/form/CPUModelSelector.js | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/www/manager6/form/CPUModelSelector.js 
b/www/manager6/form/CPUModelSelector.js
index 9eb5b0e9..505d27c8 100644
--- a/www/manager6/form/CPUModelSelector.js
+++ b/www/manager6/form/CPUModelSelector.js
@@ -26,6 +26,9 @@ Ext.define('PVE.form.CPUModelSelector', {
['Broadwell', 'Broadwell'],
['Broadwell-noTSX','Broadwell-noTSX'],
['Skylake-Client','Skylake-Client'],
+   ['Skylake-Server','Skylake-Server'],
+   ['Cascadelake-Server','Cascadelake-Server'],
+   ['KnightsMill','KnightsMill'],
['Opteron_G1', 'Opteron_G1'],
['Opteron_G2', 'Opteron_G2'],
['Opteron_G3', 'Opteron_G3'],
-- 
2.20.1

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


Re: [pve-devel] scsi-hd vs scsi-generic with iSCSI

2019-09-30 Thread Thomas Lamprecht
On 9/30/19 8:00 AM, Daniel Berteaud wrote:
> - Le 30 Sep 19, à 7:04, Thomas Lamprecht t.lampre...@proxmox.com a écrit :
> 
>> But the interesting thing would be, why is there an issue with scsi-generic,
>> i.e., the underlying issue for the two Bugs. IIUC, Dietmar had in mind to
>> try to fix those - and thus help all scsi-generic users, instead of working
>> around the issue.
>>
>> The initial question would be: what does the scsi-hd type differently.
>> (maybe hard to tell if they're both complete different implementations)
> 
> As much as I'd like to find this out, it's a above my skills. I can help as I 
> can reproduce it easily, but I won't be able to track it further.

We'll see if we can get some infos about this here...

> Waiting for this to be solved, would you accept a patch to either force 
> scsi-hd, or disable scsi-generic/scsi-block ? (not sure yet if it should be a 
> VM tuning, or at the DC level)

Depends on the outcome of above, but effectively we would like to
not have the choice between "working or not", so ideally we can
just either fix it in QEMU or set the respective (working) option
for all new started VMs (QEMU machine versioned, to not break live
migration due to changed VM HW).

cheers,
Thomas


___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH pve-zsync] Allow detecting a syncing instance of a job

2019-09-30 Thread Fabian Ebner
Before, the check whether a syncing instance of the same job is already present
was inside the locked section. This caused cron to continuously spawn new
instances of pve-zsync on syncs (or rather groups of syncs) taking longer
than 15 minutes, see [0] in the forum. This patch introduces a new locked
section for checking the current status and a new 'waiting' status.
The 'waiting' status is needed to mark jobs which are currently waiting
for the lock for syncing. So if job A is syncing and job B is waiting for
the lock then all new instances of job B will see that one instance is
already scheduled to sync.

[0]: 
https://forum.proxmox.com/threads/pve-zsync-bug-spawns-endless-cron-processes.58087/

Signed-off-by: Fabian Ebner 
---
 pve-zsync | 25 -
 1 file changed, 20 insertions(+), 5 deletions(-)

diff --git a/pve-zsync b/pve-zsync
index 425ffa2..90c1bb3 100755
--- a/pve-zsync
+++ b/pve-zsync
@@ -19,6 +19,7 @@ my $PVE_DIR = "/etc/pve/local";
 my $QEMU_CONF = "${PVE_DIR}/qemu-server";
 my $LXC_CONF = "${PVE_DIR}/lxc";
 my $LOCKFILE = "$CONFIG_PATH/${PROGNAME}.lock";
+my $LOCKFILE_STATUS_CHECK = "$CONFIG_PATH/${PROGNAME}_status_check.lock";
 my $PROG_PATH = "$PATH/${PROGNAME}";
 my $INTERVAL = 15;
 my $DEBUG;
@@ -578,20 +579,34 @@ sub destroy_job {
 sub sync {
 my ($param) = @_;
 
+my $lock_status_check_fh = IO::File->new("> $LOCKFILE_STATUS_CHECK");
+die "Can't open Lock File: $LOCKFILE_STATUS_CHECK $!\n" if 
!$lock_status_check_fh;
+lock($lock_status_check_fh);
+
+my $job;
+eval {
+   $job = get_job($param);
+};
+
+if ($job && defined($job->{state}) && ($job->{state} eq "syncing" || 
$job->{state} eq "waiting")) {
+   unlock($lock_status_check_fh);
+   die "Job --source $param->{source} --name $param->{name} is already 
scheduled to sync\n";
+}
+
+$job->{state} = "waiting";
+update_state($job);
+unlock($lock_status_check_fh);
+
 my $lock_fh = IO::File->new("> $LOCKFILE");
 die "Can't open Lock File: $LOCKFILE $!\n" if !$lock_fh;
 lock($lock_fh);
 
+#job might've changed while we waited for the lock, but we can be sure 
it's not syncing
 my $date = get_date();
-my $job;
 eval {
$job = get_job($param);
 };
 
-if ($job && defined($job->{state}) && $job->{state} eq "syncing") {
-   die "Job --source $param->{source} --name $param->{name} is syncing at 
the moment";
-}
-
 my $dest = parse_target($param->{dest});
 my $source = parse_target($param->{source});
 
-- 
2.20.1


___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v2 00/12] Add basics for custom CPU models

2019-09-30 Thread Stefan Reiter
Based on the RFC and following on- and off-list discussion about custom CPU
models [0].

In essence, this revised patch allows a user to specify custom CPU models in
/etc/pve/cpu-models.conf (section-config style [1]), where VMs using that CPU
model inherit details from the definition. This removes any fragile
"auto-magical" CPU flag detection, while still giving the user a way to create
VMs with the best possible subset of CPU features maintaining live-migration
compatibility.

Includes the infrastructure for broadcasting supported CPU flags for each
cluster-node via the key-value store - this is not necessary for the
custom-cpu feature in particular, but I think could prove useful for
implementing the GUI part (e.g. show the user which flags are supported on which
nodes).

I intentionally wanted to send this series before starting any GUI or new API
work, to get some feedback if this approach works better than the cluster-cpu
one.

v1 -> v2:

Quite a big change to v1. Once I began reusing the $cpu_fmt hash for both custom
CPU models and VM-specific settings, I realized the approach mentioned by Fabian
- to move some helpers from QemuServer to the new CPUConfig
- would actually make a lot of sense.

* Re-query supported CPU flags when QEMU/KVM updates (without needing to
  restart pvestatd) using kvm_user_version
* Improve documentation and error handling on CPU flag querying helpers
* Rename CustomCPUConfig -> CPUConfig
* Extract some CPU helpers from QemuServer to CPUConfig
* Use cfs_ functions for IO, don't use 'bless'
* Merge $cpu_fmt for custom models and VM-specific CPU settings
* Rename 'basemodel' -> 'reported-model', only support default models as
  reported (avoids custom models depending on each other for now)
* Add new CPU flag resolving infrastructure
* Add and fix test cases

Does not include any fix for versioning/live-migration with custom models for
now, felt these changes were big enough.


[0]: https://pve.proxmox.com/pipermail/pve-devel/2019-July/038268.html
[1]: e.g.:
cpu-model: custom-cpu-name
host-phys-bits 1
flags +aes;+avx;+avx2
reported-model kvm64


manager: Stefan Reiter (1):
  Broadcast supported CPU flags

 PVE/Service/pvestatd.pm | 40 ++--
 1 file changed, 38 insertions(+), 2 deletions(-)

qemu-server: Stefan Reiter (11):
  Add QEMU CPU flag querying helpers
  Add CPUConfig file and migrate some CPU helpers
  Adapt CPUConfig to handle custom models
  Add overrides and convenience functions to CPUConfig
  Verify VM-specific CPU configs seperately
  Add helpers to better structure CPU option handling
  Rework get_cpu_options and allow custom CPU models
  fix #2318: allow phys-bits and host-phys-bits CPU settings
  cfg2cmd: fix tests for new CPU flag resolving
  cfg2cmd: add test case for custom CPU model
  cfg2cmd: fix descriptions of cfg2cmd test cases

 PVE/QemuServer.pm  | 334 
 PVE/QemuServer/CPUConfig.pm| 595 +
 PVE/QemuServer/Makefile|   1 +
 test/cfg2cmd/custom-cpu-model.conf |   8 +
 test/cfg2cmd/i440fx-win10-hostpci.conf |   2 +-
 test/cfg2cmd/i440fx-win10-hostpci.conf.cmd |   2 +-
 test/cfg2cmd/minimal-defaults.conf.cmd |   2 +-
 test/cfg2cmd/q35-linux-hostpci.conf|   2 +-
 test/cfg2cmd/q35-linux-hostpci.conf.cmd|   2 +-
 test/cfg2cmd/q35-win10-hostpci.conf.cmd|   2 +-
 test/cfg2cmd/simple1.conf.cmd  |   2 +-
 test/cfg2cmd/spice-usb3.conf.cmd   |   2 +-
 test/run_config2command_tests.pl   |  21 +
 13 files changed, 739 insertions(+), 236 deletions(-)
 create mode 100644 PVE/QemuServer/CPUConfig.pm
 create mode 100644 test/cfg2cmd/custom-cpu-model.conf

-- 
2.20.1

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v2 manager 01/12] Broadcast supported CPU flags

2019-09-30 Thread Stefan Reiter
pvestatd will check if the KVM version has changed using
kvm_user_version (which automatically clears its cache if QEMU/KVM
updates), and if it has, query supported CPU flags and broadcast them as
a key-value pair to the cluster.

Detects value regressions and handles them gracefully (i.e. if
query_supported_cpu_flags fails, we try to retain the previously
detected flags).

Signed-off-by: Stefan Reiter 
---

v1 -> v2:
* broadcast directly in update_supported_cpuflags
* use kvm_user_version to determine when to re-query CPU flags
* don't broadcast flags when unchanged or empty


 PVE/Service/pvestatd.pm | 40 ++--
 1 file changed, 38 insertions(+), 2 deletions(-)

diff --git a/PVE/Service/pvestatd.pm b/PVE/Service/pvestatd.pm
index bad1b73d..5ac97c98 100755
--- a/PVE/Service/pvestatd.pm
+++ b/PVE/Service/pvestatd.pm
@@ -78,6 +78,40 @@ sub hup {
 $restart_request = 1;
 }
 
+my $last_kvm_version = '';
+
+sub update_supported_cpuflags {
+my $kvm_version = PVE::QemuServer::kvm_user_version();
+
+# only update when QEMU/KVM version has changed, as that is the only reason
+# why flags could change without restarting pvestatd
+return if $last_kvm_version eq $kvm_version;
+$last_kvm_version = $kvm_version;
+
+my $supported_cpuflags;
+
+eval {
+   $supported_cpuflags = join(" ", 
@{PVE::QemuServer::query_supported_cpu_flags()});
+};
+warn $@ if $@;
+
+# detect regression
+if (!$supported_cpuflags || $supported_cpuflags eq '') {
+   my $prev_cpuflags = PVE::Cluster::get_node_kv('cpuflags', 
$nodename)->{$nodename};
+   if ($prev_cpuflags && $prev_cpuflags ne '') {
+   warn "CPU flag detection failed, using old values\n";
+   } else {
+   warn "CPU flag detection failed and no previous values found\n";
+   }
+
+   # either flags are already in kv store, so no need to re-broadcast,
+   # or we don't have valid flags, and no point broadcasting empty string
+   return;
+}
+
+PVE::Cluster::broadcast_node_kv('cpuflags', $supported_cpuflags);
+}
+
 my $generate_rrd_string = sub {
 my ($data) = @_;
 
@@ -97,7 +131,9 @@ sub update_node_status {
 
 my $cpuinfo = PVE::ProcFSTools::read_cpuinfo();
 
-my $maxcpu = $cpuinfo->{cpus}; 
+my $maxcpu = $cpuinfo->{cpus};
+
+update_supported_cpuflags();
 
 my $subinfo = PVE::INotify::read_file('subscription');
 my $sublevel = $subinfo->{level} || '';
@@ -110,7 +146,7 @@ sub update_node_status {
$netin += $netdev->{$dev}->{receive};
$netout += $netdev->{$dev}->{transmit};
 }
- 
+
 my $meminfo = PVE::ProcFSTools::read_meminfo();
 
 my $dinfo = df('/', 1); # output is bytes
-- 
2.20.1


___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v2 qemu-server 02/12] Add QEMU CPU flag querying helpers

2019-09-30 Thread Stefan Reiter
* query_understood_cpu_flags returns all flags that QEMU/KVM knows about
* query_supported_cpu_flags returns all flags that QEMU/KVM can use on
  this particular host.

To get supported flags, a temporary VM is started with QEMU, so we can
issue the "query-cpu-model-expansion" QMP command. This is how libvirt
queries supported flags for its "host-passthrough" CPU type.
query_supported_cpu_flags is thus rather slow and shouldn't be called
unnecessarily.

Currently only supports x86_64, because QEMU-aarch64 doesn't provide the
necessary querying functions.

Signed-off-by: Stefan Reiter 
---

query_understood_cpu_flags is currently not used, but will be very useful for
the later UI part. I think it thematically fits best with this patch though.

v1 -> v2:
* Change order of functions and add a single, more useful comment on usage
* Do s/\.|-/_/g directly in query_understood_cpu_flags, since the other format
  is useless anyway
* Add "die" and FIXME for aarch64, since it doesn't support querying atm
  (still, use get_host_arch()/get_basic_machine_info() for now, so once QEMU
  supports it, we theoretically just have to remove the "die")
* Do QMP in extra eval, so we don't die before calling vm_stop


 PVE/QemuServer.pm | 112 ++
 1 file changed, 112 insertions(+)

diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 70ed910..20c1061 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -3531,6 +3531,118 @@ sub get_command_for_arch($) {
 return $cmd;
 }
 
+# To use query_supported_cpu_flags and query_understood_cpu_flags to get flags
+# to use in a QEMU command line (-cpu element), first array_intersect the 
result
+# of query_supported_ with query_understood_. This is necessary because:
+#
+# a) query_understood_ returns flags the host cannot use and
+# b) query_supported_ (rather the QMP call) doesn't actually return CPU
+#flags, but CPU settings - with most of them being flags. Those settings
+#(and some flags, curiously) cannot be specified as a "-cpu" argument
+#however.
+#
+# query_supported_ needs to start a temporary VM and is therefore rather
+# expensive.  If you need the value returned from this, you can get it much
+# cheaper from pmxcfs using PVE::Cluster::get_node_kv('cpuflags').
+#
+sub query_supported_cpu_flags {
+my $flags = [];
+
+my $vmid = -1;
+my $pidfile = pidfile_name($vmid);
+
+my ($arch, $default_machine) = get_basic_machine_info();
+
+# FIXME: Once this is merged, the code below should work for ARM without 
any
+# further modifications:
+# https://lists.nongnu.org/archive/html/qemu-devel/2019-06/msg04947.html
+die "QEMU/KVM cannot detect CPU flags on ARM (aarch64)\n" if
+   $arch eq "aarch64";
+
+PVE::QemuConfig->lock_config($vmid, sub {
+   # We start a temporary (frozen) VM with vmid -1 to allow us to send a 
QMP command
+   my $rc = run_command([
+   get_command_for_arch($arch),
+   '-machine', $default_machine,
+   '-display', 'none',
+   '-chardev', 
"socket,id=qmp,path=/var/run/qemu-server/$vmid.qmp,server,nowait",
+   '-mon', 'chardev=qmp,mode=control',
+   '-pidfile', $pidfile,
+   '-S', '-daemonize'
+   ], noerr => 1, quiet => 0);
+   return if $rc;
+
+   eval {
+   my $cmd_result = vm_mon_cmd_nocheck(
+   $vmid,
+   'query-cpu-model-expansion',
+   type => 'full',
+   model => { name => 'host' }
+   );
+
+   my $props = $cmd_result->{model}->{props};
+   if (%$props) {
+   foreach my $prop (keys %$props) {
+   push @$flags, $prop if "$props->{$prop}" eq '1';
+   }
+   }
+   };
+   my $err = $@;
+
+   # force stop with 10 sec timeout and 'nocheck'
+   # always stop, even if QMP failed
+   vm_stop(undef, $vmid, 1, 1, 10, 0, 1);
+
+   die $err if $err;
+});
+
+# QEMU returns some flags multiple times, with '_', '.' or '-' as separator
+# (e.g. lahf_lm and lahf-lm; sse4.2, sse4-2 and sse4_2; ...).
+# We only keep those with underscores, since they match the ones from
+# /proc/cpuinfo (they do the same thing, but we get rid of duplicates).
+@$flags = grep {
+   my $replaced = (my $underscore = $_) =~ s/\.|-/_/g;
+   !($replaced && grep { $_ eq $underscore } @$flags)
+} @$flags;
+
+return $flags;
+}
+
+sub query_understood_cpu_flags {
+my $flags = [];
+my $flag_section = 0;
+
+my $arch = get_host_arch();
+
+# FIXME: Once the patch mentioned in query_supported_cpu_flags is merged,
+# depending on if the ARM version of query-cpu-model-expansion also returns
+# non-flags, this function might become irrelevant for ARM entirely.
+die "CPU Flag detection only supported on x86_64\n"
+   if $arch ne "x86_64";
+
+run_command(
+   [get_command_for_arch($arch), '-cpu', 'help'],
+   

[pve-devel] [PATCH v2 qemu-server 04/12] Adapt CPUConfig to handle custom models

2019-09-30 Thread Stefan Reiter
Turn CPUConfig into a SectionConfig with parsing/writing support for
custom CPU models. IO is handled using cfs.

The "custom" parameter provides differentiation between custom and
default types, even if the name is the same ('namespacing').

Signed-off-by: Stefan Reiter 
---
 PVE/QemuServer/CPUConfig.pm | 59 ++---
 1 file changed, 55 insertions(+), 4 deletions(-)

diff --git a/PVE/QemuServer/CPUConfig.pm b/PVE/QemuServer/CPUConfig.pm
index c994228..3fde987 100644
--- a/PVE/QemuServer/CPUConfig.pm
+++ b/PVE/QemuServer/CPUConfig.pm
@@ -3,6 +3,8 @@ package PVE::QemuServer::CPUConfig;
 use strict;
 use warnings;
 use PVE::JSONSchema;
+use PVE::Cluster qw(cfs_register_file cfs_read_file);
+use base qw(PVE::SectionConfig);
 
 use base 'Exporter';
 our @EXPORT_OK = qw(
@@ -11,6 +13,15 @@ get_cpu_options
 qemu_machine_feature_enabled
 );
 
+my $default_filename = "cpu-models.conf";
+cfs_register_file($default_filename,
+ sub { PVE::QemuServer::CPUConfig->parse_config(@_); },
+ sub { PVE::QemuServer::CPUConfig->write_config(@_); });
+
+sub load_custom_model_conf {
+return cfs_read_file($default_filename);
+}
+
 my $cpu_vendor_list = {
 # Intel CPUs
 486 => 'GenuineIntel',
@@ -80,11 +91,27 @@ my $cpu_flag = qr/[+-](@{[join('|', 
@supported_cpu_flags)]})/;
 
 our $cpu_fmt = {
 cputype => {
-   description => "Emulated CPU type.",
+   description => "Emulated CPU type. Can be default or custom name.",
type => 'string',
-   enum => [ sort { "\L$a" cmp "\L$b" } keys %$cpu_vendor_list ],
+   format_description => 'string',
default => 'kvm64',
default_key => 1,
+   optional => 1,
+},
+custom => {
+   description => "True if 'cputype' is a custom model, false if 
otherwise.",
+   type => 'boolean',
+   default => 0,
+   optional => 1,
+},
+'reported-model' => {
+   description => "CPU model and vendor to report to the guest. Must be a 
QEMU/KVM supported model."
+. " Only valid for custom CPU model definitions, default 
models will always report themselves to the guest OS.",
+   type => 'string',
+   enum => [ sort { "\L$a" cmp "\L$b" } keys %$cpu_vendor_list ],
+   default => 'kvm64',
+   custom_only => 1,
+   optional => 1,
 },
 hidden => {
description => "Do not identify as a KVM virtual machine.",
@@ -102,14 +129,34 @@ our $cpu_fmt = {
 flags => {
description => "List of additional CPU flags separated by ';'."
 . " Use '+FLAG' to enable, '-FLAG' to disable a flag."
-. " Currently supported flags: @{[join(', ', 
@supported_cpu_flags)]}.",
+. " Custom CPU models can specify any flag supported by"
+. " QEMU/KVM, VM-specific flags must be from the following"
+. " set for security reasons: @{[join(', ', 
@supported_cpu_flags)]}.",
format_description => '+FLAG[;-FLAG...]',
type => 'string',
-   pattern => qr/$cpu_flag(;$cpu_flag)*/,
+   pattern => qr/[+-][a-zA-Z0-9\-_\.]+(;[+-][a-zA-Z0-9\-_\.]+)*/,
optional => 1,
 },
 };
 
+# Section config settings
+my $defaultData = {
+# shallow copy, since SectionConfig modifies propertyList internally
+propertyList => { %$cpu_fmt },
+};
+
+sub private {
+return $defaultData;
+}
+
+sub options {
+return { %$cpu_fmt };
+}
+
+sub type {
+return 'cpu-model';
+}
+
 # Print a QEMU device node for a given VM configuration for hotplugging CPUs
 sub print_cpu_device {
 my ($conf, $id) = @_;
@@ -248,4 +295,8 @@ sub qemu_machine_feature_enabled {
 $current_minor >= $version_minor);
 }
 
+
+__PACKAGE__->register();
+__PACKAGE__->init();
+
 1;
-- 
2.20.1


___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v2 qemu-server 09/12] fix #2318: allow phys-bits and host-phys-bits CPU settings

2019-09-30 Thread Stefan Reiter
Can be specified for a particular VM or via a custom CPU model (VM takes
precedence).

Signed-off-by: Stefan Reiter 
---
 PVE/QemuServer/CPUConfig.pm | 24 
 1 file changed, 24 insertions(+)

diff --git a/PVE/QemuServer/CPUConfig.pm b/PVE/QemuServer/CPUConfig.pm
index e595a69..f0bfeee 100644
--- a/PVE/QemuServer/CPUConfig.pm
+++ b/PVE/QemuServer/CPUConfig.pm
@@ -137,6 +137,19 @@ my $cpu_fmt = {
pattern => qr/[+-][a-zA-Z0-9\-_\.]+(;[+-][a-zA-Z0-9\-_\.]+)*/,
optional => 1,
 },
+'phys-bits' => {
+   type => 'integer',
+   minimum => 1,
+   maximum => 64,
+   description => "The physical memory address bits that are reported to 
the guest OS. Should be smaller or equal to the host's.",
+   optional => 1,
+},
+'host-phys-bits' => {
+   type => 'boolean',
+   default => 0,
+   description => "Whether to report the host's physical memory address 
bits. Overrides 'phys-bits' when set.",
+   optional => 1,
+},
 };
 
 # $cpu_fmt describes both the CPU config passed as part of a VM config, as well
@@ -445,6 +458,17 @@ sub get_cpu_options {
 $cpu .= resolve_cpu_flags($pve_flags, $hv_flags, $custom_cputype_flags,
  $vm_flags, $pve_forced_flags);
 
+my $phys_bits = '';
+foreach my $conf ($custom_cpuconf, $cpuconf) {
+   next if !defined($conf);
+   if ($conf->{'host-phys-bits'}) {
+   $phys_bits = ",host-phys-bits=true";
+   } elsif ($conf->{'phys-bits'}) {
+   $phys_bits = ",phys-bits=$conf->{'phys-bits'}";
+   }
+}
+$cpu .= $phys_bits;
+
 return ('-cpu', $cpu);
 }
 
-- 
2.20.1


___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v2 qemu-server 12/12] cfg2cmd: fix descriptions of cfg2cmd test cases

2019-09-30 Thread Stefan Reiter
Signed-off-by: Stefan Reiter 
---

Independant from the rest of the series.

 test/cfg2cmd/i440fx-win10-hostpci.conf | 2 +-
 test/cfg2cmd/q35-linux-hostpci.conf| 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/test/cfg2cmd/i440fx-win10-hostpci.conf 
b/test/cfg2cmd/i440fx-win10-hostpci.conf
index 0df1378..2ab2dda 100644
--- a/test/cfg2cmd/i440fx-win10-hostpci.conf
+++ b/test/cfg2cmd/i440fx-win10-hostpci.conf
@@ -1,4 +1,4 @@
-# TEST: Config with q35, NUMA, hostpci passthrough, EFI & Windows
+# TEST: Config with i440fx, NUMA, hostpci passthrough, EFI & Windows
 bios: ovmf
 bootdisk: scsi0
 cores: 1
diff --git a/test/cfg2cmd/q35-linux-hostpci.conf 
b/test/cfg2cmd/q35-linux-hostpci.conf
index 8fd2193..749f983 100644
--- a/test/cfg2cmd/q35-linux-hostpci.conf
+++ b/test/cfg2cmd/q35-linux-hostpci.conf
@@ -1,4 +1,4 @@
-# TEST: Config with q35, NUMA, hostpci passthrough, EFI & Windows
+# TEST: Config with q35, NUMA, hostpci passthrough, EFI & Linux
 bios: ovmf
 bootdisk: scsi0
 cores: 1
-- 
2.20.1


___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v2 qemu-server 06/12] Verify VM-specific CPU configs seperately

2019-09-30 Thread Stefan Reiter
$cpu_fmt is being reused for custom CPUs as well as VM-specific CPU
settings. The "pve-vm-cpu-conf" format is introduced to verify a config
specifically for use as VM-specific settings.

Signed-off-by: Stefan Reiter 
---
 PVE/QemuServer.pm   |  2 +-
 PVE/QemuServer/CPUConfig.pm | 68 +++--
 2 files changed, 67 insertions(+), 3 deletions(-)

diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index a95006f..abf5578 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -505,7 +505,7 @@ EODESCR
optional => 1,
description => "Emulated CPU type.",
type => 'string',
-   format => $PVE::QemuServer::CPUConfig::cpu_fmt,
+   format => 'pve-vm-cpu-conf',
 },
 parent => get_standard_option('pve-snapshot-name', {
optional => 1,
diff --git a/PVE/QemuServer/CPUConfig.pm b/PVE/QemuServer/CPUConfig.pm
index 125b636..61bd024 100644
--- a/PVE/QemuServer/CPUConfig.pm
+++ b/PVE/QemuServer/CPUConfig.pm
@@ -87,9 +87,9 @@ my @supported_cpu_flags = (
 'hv-evmcs',
 'aes'
 );
-my $cpu_flag = qr/[+-](@{[join('|', @supported_cpu_flags)]})/;
+my $cpu_flag_re = qr/([+-])(@{[join('|', @supported_cpu_flags)]})/;
 
-our $cpu_fmt = {
+my $cpu_fmt = {
 cputype => {
description => "Emulated CPU type. Can be default or custom name.",
type => 'string',
@@ -139,6 +139,70 @@ our $cpu_fmt = {
 },
 };
 
+# $cpu_fmt describes both the CPU config passed as part of a VM config, as well
+# as the definition of a custom CPU model. There are some slight differences
+# though, which we catch in the custom verification function below.
+sub verify_cpu_conf_basic {
+my ($cpu, $noerr) = @_;
+
+eval {
+$cpu = PVE::JSONSchema::parse_property_string($cpu_fmt, $cpu);
+};
+if ($@) {
+die $@ if !$noerr;
+return undef;
+}
+
+# required, but can't be made "optional => 0" since it's not included as a
+# seperate property in config file
+if (!$cpu->{cputype}) {
+   die "CPU is missing cputype\n" if !$noerr;
+   return undef;
+}
+
+return $cpu;
+}
+
+PVE::JSONSchema::register_format('pve-vm-cpu-conf', \&verify_vm_cpu_conf);
+sub verify_vm_cpu_conf {
+my ($cpu, $noerr) = @_;
+
+$cpu = verify_cpu_conf_basic($cpu, $noerr);
+return undef if !$cpu;
+
+my $cputype = $cpu->{cputype};
+
+# Model must exist
+if ($cpu->{custom}) {
+   my $config = load_custom_model_conf();
+   return $cpu if $config && defined($config->{ids}->{$cputype});
+
+   die "Custom cputype '$cputype' not found\n" if !$noerr;
+   return undef;
+} else {
+   return $cpu if defined($cpu_vendor_list->{$cputype});
+
+   die "Default cputype '$cputype' not found\n" if !$noerr;
+   return undef;
+}
+
+if ($cpu->{flags} && $cpu->{flags} !~ m/$cpu_flag_re(;$cpu_flag_re)*/) {
+   die "VM-specific CPU flags must be a subset of: @{[join(', ', 
@supported_cpu_flags)]}\n"
+   if !$noerr;
+   return undef;
+}
+
+for my $prop (keys %$cpu) {
+   if ($cpu->{$prop}->{custom_only}) {
+   die "Property '$prop' not allowed in VM-specific CPU config.\n"
+   if !$noerr;
+   return undef;
+   }
+}
+
+return $cpu;
+}
+
 # Section config settings
 my $defaultData = {
 # shallow copy, since SectionConfig modifies propertyList internally
-- 
2.20.1


___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v2 qemu-server 11/12] cfg2cmd: add test case for custom CPU model

2019-09-30 Thread Stefan Reiter
Requires a mock CPU-model config, which is given as a raw string to also
test parsing capabilities.

Signed-off-by: Stefan Reiter 
---
 test/cfg2cmd/custom-cpu-model.conf |  8 
 test/run_config2command_tests.pl   | 21 +
 2 files changed, 29 insertions(+)
 create mode 100644 test/cfg2cmd/custom-cpu-model.conf

diff --git a/test/cfg2cmd/custom-cpu-model.conf 
b/test/cfg2cmd/custom-cpu-model.conf
new file mode 100644
index 000..d4db550
--- /dev/null
+++ b/test/cfg2cmd/custom-cpu-model.conf
@@ -0,0 +1,8 @@
+# TEST: Check if custom CPU models are resolved correctly
+cores: 3
+cpu: qemu64,custom=1,flags=+virt-ssbd,host-phys-bits=true
+name: customcpu
+numa: 0
+ostype: win10
+smbios1: uuid=2ea3f676-dfa5-11e9-ae82-c721e12f3fcf
+sockets: 1
diff --git a/test/run_config2command_tests.pl b/test/run_config2command_tests.pl
index 6f2fe28..c734133 100755
--- a/test/run_config2command_tests.pl
+++ b/test/run_config2command_tests.pl
@@ -11,6 +11,7 @@ use Test::MockModule;
 use PVE::Tools qw(file_get_contents file_set_contents run_command);
 use PVE::QemuConfig;
 use PVE::QemuServer;
+use PVE::QemuServer::CPUConfig;
 
 my $base_env = {
 storage_config => {
@@ -146,6 +147,26 @@ $pve_common_tools->mock(
 },
 );
 
+my $pve_cpuconfig;
+$pve_cpuconfig = Test::MockModule->new('PVE::QemuServer::CPUConfig');
+$pve_cpuconfig->mock(
+load_custom_model_conf => sub {
+   # mock custom CPU model config
+   return PVE::QemuServer::CPUConfig->parse_config("cpu-models.conf",
+

[pve-devel] [PATCH v2 qemu-server 10/12] cfg2cmd: fix tests for new CPU flag resolving

2019-09-30 Thread Stefan Reiter
The new flag resolving outputs flags in sorted order for consistency,
adapt the test cases to not break.

Only the order is changed, not which flags are present.

Signed-off-by: Stefan Reiter 
---
 test/cfg2cmd/i440fx-win10-hostpci.conf.cmd | 2 +-
 test/cfg2cmd/minimal-defaults.conf.cmd | 2 +-
 test/cfg2cmd/q35-linux-hostpci.conf.cmd| 2 +-
 test/cfg2cmd/q35-win10-hostpci.conf.cmd| 2 +-
 test/cfg2cmd/simple1.conf.cmd  | 2 +-
 test/cfg2cmd/spice-usb3.conf.cmd   | 2 +-
 6 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/test/cfg2cmd/i440fx-win10-hostpci.conf.cmd 
b/test/cfg2cmd/i440fx-win10-hostpci.conf.cmd
index ff5d635..2a9174d 100644
--- a/test/cfg2cmd/i440fx-win10-hostpci.conf.cmd
+++ b/test/cfg2cmd/i440fx-win10-hostpci.conf.cmd
@@ -15,7 +15,7 @@
   -boot 
'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg'
 \
   -vnc unix:/var/run/qemu-server/8006.vnc,password \
   -no-hpet \
-  -cpu 
'kvm64,+lahf_lm,+sep,+kvm_pv_unhalt,+kvm_pv_eoi,hv_spinlocks=0x1fff,hv_vapic,hv_time,hv_reset,hv_vpindex,hv_runtime,hv_relaxed,hv_synic,hv_stimer,hv_ipi,enforce'
 \
+  -cpu 
'kvm64,enforce,hv_ipi,hv_relaxed,hv_reset,hv_runtime,hv_spinlocks=0x1fff,hv_stimer,hv_synic,hv_time,hv_vapic,hv_vpindex,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep'
 \
   -m 512 \
   -object 'memory-backend-ram,id=ram-node0,size=256M' \
   -numa 'node,nodeid=0,cpus=0,memdev=ram-node0' \
diff --git a/test/cfg2cmd/minimal-defaults.conf.cmd 
b/test/cfg2cmd/minimal-defaults.conf.cmd
index 5abebe9..444050b 100644
--- a/test/cfg2cmd/minimal-defaults.conf.cmd
+++ b/test/cfg2cmd/minimal-defaults.conf.cmd
@@ -12,7 +12,7 @@
   -nodefaults \
   -boot 
'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg'
 \
   -vnc unix:/var/run/qemu-server/8006.vnc,password \
-  -cpu kvm64,+lahf_lm,+sep,+kvm_pv_unhalt,+kvm_pv_eoi,enforce \
+  -cpu kvm64,enforce,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep \
   -m 512 \
   -device 'pci-bridge,id=pci.1,chassis_nr=1,bus=pci.0,addr=0x1e' \
   -device 'pci-bridge,id=pci.2,chassis_nr=2,bus=pci.0,addr=0x1f' \
diff --git a/test/cfg2cmd/q35-linux-hostpci.conf.cmd 
b/test/cfg2cmd/q35-linux-hostpci.conf.cmd
index 21fb18b..2072295 100644
--- a/test/cfg2cmd/q35-linux-hostpci.conf.cmd
+++ b/test/cfg2cmd/q35-linux-hostpci.conf.cmd
@@ -14,7 +14,7 @@
   -nodefaults \
   -boot 
'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg'
 \
   -vnc unix:/var/run/qemu-server/8006.vnc,password \
-  -cpu kvm64,+lahf_lm,+sep,+kvm_pv_unhalt,+kvm_pv_eoi,enforce \
+  -cpu kvm64,enforce,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep \
   -m 512 \
   -object 'memory-backend-ram,id=ram-node0,size=256M' \
   -numa 'node,nodeid=0,cpus=0,memdev=ram-node0' \
diff --git a/test/cfg2cmd/q35-win10-hostpci.conf.cmd 
b/test/cfg2cmd/q35-win10-hostpci.conf.cmd
index f2c08ca..81e43d4 100644
--- a/test/cfg2cmd/q35-win10-hostpci.conf.cmd
+++ b/test/cfg2cmd/q35-win10-hostpci.conf.cmd
@@ -15,7 +15,7 @@
   -boot 
'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg'
 \
   -vnc unix:/var/run/qemu-server/8006.vnc,password \
   -no-hpet \
-  -cpu 
'kvm64,+lahf_lm,+sep,+kvm_pv_unhalt,+kvm_pv_eoi,hv_spinlocks=0x1fff,hv_vapic,hv_time,hv_reset,hv_vpindex,hv_runtime,hv_relaxed,hv_synic,hv_stimer,hv_ipi,enforce'
 \
+  -cpu 
'kvm64,enforce,hv_ipi,hv_relaxed,hv_reset,hv_runtime,hv_spinlocks=0x1fff,hv_stimer,hv_synic,hv_time,hv_vapic,hv_vpindex,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep'
 \
   -m 512 \
   -object 'memory-backend-ram,id=ram-node0,size=256M' \
   -numa 'node,nodeid=0,cpus=0,memdev=ram-node0' \
diff --git a/test/cfg2cmd/simple1.conf.cmd b/test/cfg2cmd/simple1.conf.cmd
index b5c06cf..3485064 100644
--- a/test/cfg2cmd/simple1.conf.cmd
+++ b/test/cfg2cmd/simple1.conf.cmd
@@ -12,7 +12,7 @@
   -nodefaults \
   -boot 
'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg'
 \
   -vnc unix:/var/run/qemu-server/8006.vnc,password \
-  -cpu kvm64,+lahf_lm,+sep,+kvm_pv_unhalt,+kvm_pv_eoi,enforce \
+  -cpu kvm64,enforce,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep \
   -m 768 \
   -device 'pci-bridge,id=pci.1,chassis_nr=1,bus=pci.0,addr=0x1e' \
   -device 'pci-bridge,id=pci.2,chassis_nr=2,bus=pci.0,addr=0x1f' \
diff --git a/test/cfg2cmd/spice-usb3.conf.cmd b/test/cfg2cmd/spice-usb3.conf.cmd
index 680fa64..66b4e8d 100644
--- a/test/cfg2cmd/spice-usb3.conf.cmd
+++ b/test/cfg2cmd/spice-usb3.conf.cmd
@@ -12,7 +12,7 @@
   -nodefaults \
   -boot 
'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg'
 \
   -vnc unix:/var/run/qemu-server/8006.vnc,password \
-  -cpu kvm64,+lahf_lm,+sep,+kvm_pv_unhalt,+kvm_pv_eoi,enforce \
+  -cpu kvm64,enforce,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep \
   -m 768 \
   -device 'pci-bridge,id=pci.2,chassis_nr=2,bus=pci.0,addr=0x1f' \
   -device 'pci-bridge,id=pci.1,chassis_nr=1,bus=pci.0,addr=0x1e' \
-- 
2.20.1


___
pv

[pve-devel] [PATCH v2 qemu-server 07/12] Add helpers to better structure CPU option handling

2019-09-30 Thread Stefan Reiter
To avoid hardcoding even more CPU-flag related things for custom CPU
models, introduce a dynamic approach to resolving flags.

resolve_cpu_flags takes a list of hashes (as documented in the
comment) and resolves them to a valid "-cpu" argument without
duplicates. This also helps by providing a reason why specific CPU flags
have been added, and thus allows for useful warning messages should a
flag be overwritten by another.

Signed-off-by: Stefan Reiter 
---
 PVE/QemuServer/CPUConfig.pm | 67 +
 1 file changed, 67 insertions(+)

diff --git a/PVE/QemuServer/CPUConfig.pm b/PVE/QemuServer/CPUConfig.pm
index 61bd024..6f19c2c 100644
--- a/PVE/QemuServer/CPUConfig.pm
+++ b/PVE/QemuServer/CPUConfig.pm
@@ -289,6 +289,73 @@ sub print_cpu_device {
 return 
"$cpu-x86_64-cpu,id=cpu$id,socket-id=$current_socket,core-id=$current_core,thread-id=0";
 }
 
+# Resolves multiple arrays of hashes representing CPU flags with metadata to a
+# single string in QEMU "-cpu" compatible format. Later arrays have higher
+# priority.
+#
+# Hashes take the following format:
+# {
+# aes => {
+# op => "+", # defaults to "" if undefined
+# reason => "to support AES acceleration", # for override warnings
+# value => "" # needed for kvm=off (value: off) etc...
+# },
+# ...
+# }
+sub resolve_cpu_flags {
+my $flag_hashes = \@_;
+
+my $flags = {};
+
+for my $hash (@$flag_hashes) {
+   for my $flag_name (keys %$hash) {
+   my $flag = $hash->{$flag_name};
+   my $old_flag = $flags->{$flag_name};
+
+   $flag->{op} //= "";
+
+   if ($old_flag) {
+   my $value_changed = defined($flag->{value}) != 
defined($old_flag->{value});
+   if (!$value_changed && defined($flag->{value})) {
+   $value_changed = $flag->{value} eq $old_flag->{value};
+   }
+
+   if ($old_flag->{op} eq $flag->{op} && !$value_changed) {
+   $flags->{$flag_name}->{reason} .= " & $flag->{reason}";
+   next;
+   }
+
+   my $old = print_cpuflag_hash($flag_name, $flags->{$flag_name});
+   my $new = print_cpuflag_hash($flag_name, $flag);
+   warn "warning: CPU flag/setting $new overwrites $old\n";
+   }
+
+   $flags->{$flag_name} = $flag;
+   }
+}
+
+my $flag_str = '';
+# sort for command line stability
+for my $flag_name (sort keys %$flags) {
+   $flag_str .= ',';
+   $flag_str .= $flags->{$flag_name}->{op};
+   $flag_str .= $flag_name;
+   $flag_str .= "=$flags->{$flag_name}->{value}"
+   if $flags->{$flag_name}->{value};
+}
+
+return $flag_str;
+}
+
+sub print_cpuflag_hash {
+my ($flag_name, $flag) = @_;
+my $formatted = "'$flag->{op}$flag_name";
+$formatted .= "=$flag->{value}" if defined($flag->{value});
+$formatted .= "'";
+$formatted .= " ($flag->{reason})" if defined($flag->{reason});
+return $formatted;
+}
+
 # Calculate QEMU's '-cpu' argument from a given VM configuration
 sub get_cpu_options {
 my ($conf, $arch, $kvm, $machine_type, $kvm_off, $kvmver, $winversion, 
$gpu_passthrough) = @_;
-- 
2.20.1


___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v2 qemu-server 03/12] Add CPUConfig file and migrate some CPU helpers

2019-09-30 Thread Stefan Reiter
The package will be used for custom CPU models as a SectionConfig, hence
the name. For now we simply move some CPU related helper functions and
declarations over from QemuServer to reduce clutter there.

Signed-off-by: Stefan Reiter 
---
 PVE/QemuServer.pm   | 242 +-
 PVE/QemuServer/CPUConfig.pm | 251 
 PVE/QemuServer/Makefile |   1 +
 3 files changed, 256 insertions(+), 238 deletions(-)
 create mode 100644 PVE/QemuServer/CPUConfig.pm

diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 20c1061..a95006f 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -33,6 +33,7 @@ use PVE::QemuConfig;
 use PVE::QMPClient;
 use PVE::RPCEnvironment;
 use PVE::GuestHelpers;
+use PVE::QemuServer::CPUConfig qw(qemu_machine_feature_enabled 
print_cpu_device get_cpu_options);
 use PVE::QemuServer::PCI qw(print_pci_addr print_pcie_addr 
print_pcie_root_port);
 use PVE::QemuServer::Memory;
 use PVE::QemuServer::USB qw(parse_usb_device);
@@ -116,105 +117,6 @@ mkdir $var_run_tmpdir;
 my $lock_dir = "/var/lock/qemu-server";
 mkdir $lock_dir;
 
-my $cpu_vendor_list = {
-# Intel CPUs
-486 => 'GenuineIntel',
-pentium => 'GenuineIntel',
-pentium2  => 'GenuineIntel',
-pentium3  => 'GenuineIntel',
-coreduo => 'GenuineIntel',
-core2duo => 'GenuineIntel',
-Conroe  => 'GenuineIntel',
-Penryn  => 'GenuineIntel',
-Nehalem  => 'GenuineIntel',
-'Nehalem-IBRS'  => 'GenuineIntel',
-Westmere => 'GenuineIntel',
-'Westmere-IBRS' => 'GenuineIntel',
-SandyBridge => 'GenuineIntel',
-'SandyBridge-IBRS' => 'GenuineIntel',
-IvyBridge => 'GenuineIntel',
-'IvyBridge-IBRS' => 'GenuineIntel',
-Haswell => 'GenuineIntel',
-'Haswell-IBRS' => 'GenuineIntel',
-'Haswell-noTSX' => 'GenuineIntel',
-'Haswell-noTSX-IBRS' => 'GenuineIntel',
-Broadwell => 'GenuineIntel',
-'Broadwell-IBRS' => 'GenuineIntel',
-'Broadwell-noTSX' => 'GenuineIntel',
-'Broadwell-noTSX-IBRS' => 'GenuineIntel',
-'Skylake-Client' => 'GenuineIntel',
-'Skylake-Client-IBRS' => 'GenuineIntel',
-'Skylake-Server' => 'GenuineIntel',
-'Skylake-Server-IBRS' => 'GenuineIntel',
-
-# AMD CPUs
-athlon => 'AuthenticAMD',
-phenom  => 'AuthenticAMD',
-Opteron_G1  => 'AuthenticAMD',
-Opteron_G2  => 'AuthenticAMD',
-Opteron_G3  => 'AuthenticAMD',
-Opteron_G4  => 'AuthenticAMD',
-Opteron_G5  => 'AuthenticAMD',
-EPYC => 'AuthenticAMD',
-'EPYC-IBPB' => 'AuthenticAMD',
-
-# generic types, use vendor from host node
-host => 'default',
-kvm32 => 'default',
-kvm64 => 'default',
-qemu32 => 'default',
-qemu64 => 'default',
-max => 'default',
-};
-
-my @supported_cpu_flags = (
-'pcid',
-'spec-ctrl',
-'ibpb',
-'ssbd',
-'virt-ssbd',
-'amd-ssbd',
-'amd-no-ssb',
-'pdpe1gb',
-'md-clear',
-'hv-tlbflush',
-'hv-evmcs',
-'aes'
-);
-my $cpu_flag = qr/[+-](@{[join('|', @supported_cpu_flags)]})/;
-
-my $cpu_fmt = {
-cputype => {
-   description => "Emulated CPU type.",
-   type => 'string',
-   enum => [ sort { "\L$a" cmp "\L$b" } keys %$cpu_vendor_list ],
-   default => 'kvm64',
-   default_key => 1,
-},
-hidden => {
-   description => "Do not identify as a KVM virtual machine.",
-   type => 'boolean',
-   optional => 1,
-   default => 0
-},
-'hv-vendor-id' => {
-   type => 'string',
-   pattern => qr/[a-zA-Z0-9]{1,12}/,
-   format_description => 'vendor-id',
-   description => 'The Hyper-V vendor ID. Some drivers or programs inside 
Windows guests need a specific ID.',
-   optional => 1,
-},
-flags => {
-   description => "List of additional CPU flags separated by ';'."
-. " Use '+FLAG' to enable, '-FLAG' to disable a flag."
-. " Currently supported flags: @{[join(', ', 
@supported_cpu_flags)]}.",
-   format_description => '+FLAG[;-FLAG...]',
-   type => 'string',
-   pattern => qr/$cpu_flag(;$cpu_flag)*/,
-   optional => 1,
-},
-};
-
 my $watchdog_fmt = {
 model => {
default_key => 1,
@@ -603,7 +505,7 @@ EODESCR
optional => 1,
description => "Emulated CPU type.",
type => 'string',
-   format => $cpu_fmt,
+   format => $PVE::QemuServer::CPUConfig::cpu_fmt,
 },
 parent => get_standard_option('pve-snapshot-name', {
optional => 1,
@@ -2133,26 +2035,6 @@ sub print_netdev_full {
 return $netdev;
 }
 
-
-sub print_cpu_device {
-my ($conf, $id) = @_;
-
-my $kvm = $conf->{kvm} // 1;
-my $cpu = $kvm ? "kvm64" : "qemu64";
-if (my $cputype = $conf->{cpu}) {
-   my $cpuconf = PVE::JSONSchema::parse_property_string($cpu_fmt, $cputype)
-   or die "Cannot parse cpu description: $cputype\n";
-   $cpu = $cpuconf->{cputype};
-}
-
-my $cores = $conf->{cores} || 1;
-
-my $current_cor

[pve-devel] [PATCH v2 qemu-server 08/12] Rework get_cpu_options and allow custom CPU models

2019-09-30 Thread Stefan Reiter
If the "custom" property on the cpu config is set, try to load the
cputype from the custom CPU model config, and set values accordingly.

While at it, extract currently hardcoded values into seperate sub and add
reasonings.

Signed-off-by: Stefan Reiter 
---

It was quite interesting to dig through old commit messages/mail archives to
find the actual reasons some of our hardcoded flags are included. I do feel like
the "reason" field is quite useful though, both for future developers and users.

 PVE/QemuServer/CPUConfig.pm | 188 ++--
 1 file changed, 139 insertions(+), 49 deletions(-)

diff --git a/PVE/QemuServer/CPUConfig.pm b/PVE/QemuServer/CPUConfig.pm
index 6f19c2c..e595a69 100644
--- a/PVE/QemuServer/CPUConfig.pm
+++ b/PVE/QemuServer/CPUConfig.pm
@@ -360,96 +360,186 @@ sub print_cpuflag_hash {
 sub get_cpu_options {
 my ($conf, $arch, $kvm, $machine_type, $kvm_off, $kvmver, $winversion, 
$gpu_passthrough) = @_;
 
-my $cpuFlags = [];
-my $ostype = $conf->{ostype};
-
-my $cpu = $kvm ? "kvm64" : "qemu64";
+my $cputype = $kvm ? "kvm64" : "qemu64";
 if ($arch eq 'aarch64') {
-   $cpu = 'cortex-a57';
+   $cputype = 'cortex-a57';
 }
-my $hv_vendor_id;
-if (my $cputype = $conf->{cpu}) {
-   my $cpuconf = PVE::JSONSchema::parse_property_string($cpu_fmt, $cputype)
-   or die "Cannot parse cpu description: $cputype\n";
-   $cpu = $cpuconf->{cputype};
-   $kvm_off = 1 if $cpuconf->{hidden};
-   $hv_vendor_id = $cpuconf->{'hv-vendor-id'};
 
-   if (defined(my $flags = $cpuconf->{flags})) {
-   push @$cpuFlags, split(";", $flags);
+my $cpuconf = {};
+my $custom_cpuconf;
+my $hv_vendor_id;
+if (my $cpu_prop_str = $conf->{cpu}) {
+   $cpuconf = verify_vm_cpu_conf($cpu_prop_str)
+   or die "Cannot parse cpu description: $cpu_prop_str\n";
+
+   $cputype = $cpuconf->{cputype};
+   if ($cpuconf->{custom}) {
+   my $custom_conf = load_custom_model_conf();
+   $custom_cpuconf = get_model_by_name($custom_conf, $cputype)
+   or die "invalid custom model definition for '$cputype'\n";
+
+   $cputype = $custom_cpuconf->{'reported-model'};
+   $kvm_off = $custom_cpuconf->{hidden};
+   $hv_vendor_id = $custom_cpuconf->{'hv-vendor-id'};
}
-}
-
-push @$cpuFlags , '+lahf_lm' if $cpu eq 'kvm64' && $arch eq 'x86_64';
 
-push @$cpuFlags , '-x2apic'
-   if $conf->{ostype} && $conf->{ostype} eq 'solaris';
-
-push @$cpuFlags, '+sep' if $cpu eq 'kvm64' || $cpu eq 'kvm32';
+   # VM-specific settings override custom CPU config
+   $kvm_off = $cpuconf->{hidden}
+   if defined($cpuconf->{hidden});
+   $hv_vendor_id = $cpuconf->{'hv-vendor-id'}
+   if defined($cpuconf->{'hv-vendor-id'});
+}
 
-push @$cpuFlags, '-rdtscp' if $cpu =~ m/^Opteron/;
+my $pve_flags = get_pve_cpu_flags($conf, $kvm, $cputype, $arch,
+ $machine_type, $kvmver);
 
-if (qemu_machine_feature_enabled ($machine_type, $kvmver, 2, 3) && $arch 
eq 'x86_64') {
+my $hv_flags = get_hyperv_enlightenments($winversion, $machine_type, 
$kvmver,
+   $conf->{bios}, $gpu_passthrough, $hv_vendor_id) if $kvm;
 
-   push @$cpuFlags , '+kvm_pv_unhalt' if $kvm;
-   push @$cpuFlags , '+kvm_pv_eoi' if $kvm;
+my $custom_cputype_flags = {};
+if ($custom_cpuconf && defined($custom_cpuconf->{flags})) {
+   foreach my $flag (split(";", $custom_cpuconf->{flags})) {
+   $flag =~ m/^([+-])(.*)$/;
+   $custom_cputype_flags->{$2} = {
+   op => $1,
+   reason => "set by custom CPU model",
+   }
+   }
 }
 
-add_hyperv_enlightenments($cpuFlags, $winversion, $machine_type, $kvmver, 
$conf->{bios}, $gpu_passthrough, $hv_vendor_id) if $kvm;
-
-push @$cpuFlags, 'enforce' if $cpu ne 'host' && $kvm && $arch eq 'x86_64';
-
-push @$cpuFlags, 'kvm=off' if $kvm_off;
+my $vm_flags = {};
+if (defined(my $flags = $cpuconf->{flags})) {
+   foreach my $flag (split(";", $flags)) {
+   if ($flag =~ $cpu_flag_re) {
+   $vm_flags->{$2} = {
+   op => $1,
+   reason => "manually set for VM",
+   }
+   }
+   }
+}
 
-if (my $cpu_vendor = $cpu_vendor_list->{$cpu}) {
-   push @$cpuFlags, "vendor=${cpu_vendor}"
-   if $cpu_vendor ne 'default';
+my $pve_forced_flags = {};
+$pve_forced_flags->{'enforce'} = {
+   reason => "error if requested CPU settings not available",
+} if $cputype ne 'host' && $kvm && $arch eq 'x86_64';
+$pve_forced_flags->{'kvm'} = {
+   value => "off",
+   reason => "hide KVM virtualization from guest",
+} if $kvm_off;
+
+# $cputype is the "reported-model" for custom types, so we can just look up
+# the vendor in the default list
+my $cpu_vendor = $cpu_vendor_list->{$c

[pve-devel] [PATCH v2 qemu-server 05/12] Add overrides and convenience functions to CPUConfig

2019-09-30 Thread Stefan Reiter
Add two overrides to avoid writing redundant information to the config
file.

get_model_by_name is used to return a cpu config with default values
filled out.

Signed-off-by: Stefan Reiter 
---
 PVE/QemuServer/CPUConfig.pm | 48 +
 1 file changed, 48 insertions(+)

diff --git a/PVE/QemuServer/CPUConfig.pm b/PVE/QemuServer/CPUConfig.pm
index 3fde987..125b636 100644
--- a/PVE/QemuServer/CPUConfig.pm
+++ b/PVE/QemuServer/CPUConfig.pm
@@ -157,6 +157,54 @@ sub type {
 return 'cpu-model';
 }
 
+sub parse_section_header {
+my ($class, $line) = @_;
+
+my ($type, $sectionId, $errmsg, $config) =
+   $class->SUPER::parse_section_header($line);
+
+return undef if !$type;
+return ($type, $sectionId, $errmsg, {
+   # to avoid duplicate model name in config file, parse id as cputype
+   cputype => $sectionId,
+   # models parsed from file are by definition always custom
+   custom => 1,
+});
+}
+
+sub write_config {
+my ($class, $filename, $cfg) = @_;
+
+# remove redundant properties
+for my $prop (keys %{$cfg->{ids}}) {
+   delete $cfg->{ids}->{$prop}->{custom};
+   delete $cfg->{ids}->{$prop}->{cputype};
+}
+
+$class->SUPER::write_config($filename, $cfg);
+}
+
+# Use this to get a single model in the format described by $cpu_fmt.
+# Returns undef for unknown $name.
+sub get_model_by_name {
+my ($conf, $name) = @_;
+
+return undef if !defined($conf->{ids}->{$name});
+
+my $model = {};
+for my $property (keys %{$defaultData->{propertyList}}) {
+   next if $property eq 'type';
+
+   if (my $value = $conf->{ids}->{$name}->{$property}) {
+   $model->{$property} = $value;
+   } elsif (my $default = 
$defaultData->{propertyList}->{$property}->{default}) {
+   $model->{$property} = $default;
+   }
+}
+
+return $model;
+}
+
 # Print a QEMU device node for a given VM configuration for hotplugging CPUs
 sub print_cpu_device {
 my ($conf, $id) = @_;
-- 
2.20.1


___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v2 guest-common 01/18] refactor pending changes related config code into AbstractConfig

2019-09-30 Thread Oguz Bektas
also use a better naming scheme for methods:

split_flagged_list -> parse_pending_delete
join_flagged_list -> print_pending_delete
vmconfig_delete_pending_option -> add_to_pending_delete
vmconfig_undelete_pending_option -> remove_from_pending_delete
vmconfig_cleanup_pending -> cleanup_pending

Signed-off-by: Oguz Bektas 
---
 PVE/AbstractConfig.pm | 68 +++
 1 file changed, 68 insertions(+)

diff --git a/PVE/AbstractConfig.pm b/PVE/AbstractConfig.pm
index e0d0f10..910ca86 100644
--- a/PVE/AbstractConfig.pm
+++ b/PVE/AbstractConfig.pm
@@ -68,6 +68,74 @@ sub write_config {
 PVE::Cluster::cfs_write_file($cfspath, $conf);
 }
 
+# Pending changes related
+
+sub parse_pending_delete {
+my ($class, $text) = @_;
+$text ||= '';
+$text =~ s/[,;]/ /g;
+$text =~ s/^\s+//;
+return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
+}
+
+sub print_pending_delete {
+my ($class, $how, $lst) = @_;
+join $how, map { $lst->{$_} . $_ } keys %$lst;
+}
+
+sub add_to_pending_delete {
+my ($class, $conf, $key, $force) = @_;
+
+delete $conf->{pending}->{$key};
+my $pending_delete_hash = 
$class->parse_pending_delete($conf->{pending}->{delete});
+$pending_delete_hash->{$key} = $force ? '!' : '';
+$conf->{pending}->{delete} = $class->print_pending_delete(',', 
$pending_delete_hash);
+}
+
+sub remove_from_pending_delete {
+my ($class, $conf, $key) = @_;
+
+my $pending_delete_hash = 
$class->parse_pending_delete($conf->{pending}->{delete});
+delete $pending_delete_hash->{$key};
+
+if (%$pending_delete_hash) {
+   $conf->{pending}->{delete} = $class->print_pending_delete(',', 
$pending_delete_hash);
+} else {
+   delete $conf->{pending}->{delete};
+}
+}
+
+sub cleanup_pending {
+my ($class, $conf) = @_;
+
+# remove pending changes when nothing changed
+my $changes;
+foreach my $opt (keys %{$conf->{pending}}) {
+   if (defined($conf->{$opt}) && ($conf->{pending}->{$opt} eq  
$conf->{$opt})) {
+   $changes = 1;
+   delete $conf->{pending}->{$opt};
+   }
+}
+
+my $current_delete_hash = 
$class->parse_pending_delete($conf->{pending}->{delete});
+my $pending_delete_hash = {};
+while (my ($opt, $force) = each %$current_delete_hash) {
+   if (defined($conf->{$opt})) {
+   $pending_delete_hash->{$opt} = $force;
+   } else {
+   $changes = 1;
+   }
+}
+
+if (%$pending_delete_hash) {
+   $conf->{pending}->{delete} = $class->print_pending_delete(',', 
$pending_delete_hash);
+} else {
+   delete $conf->{pending}->{delete};
+}
+
+return $changes;
+}
+
 # Lock config file using flock, run $code with @param, unlock config file.
 # $timeout is the maximum time to aquire the flock
 sub lock_config_full {
-- 
2.20.1

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v2 qemu-server 06/18] refactor pending changes related code

2019-09-30 Thread Oguz Bektas
most of the pending changes related code has been moved into
AbstractConfig, so we have to call them as class methods from QemuConfig 
instead.

Signed-off-by: Oguz Bektas 
---
 PVE/API2/Qemu.pm  | 14 -
 PVE/QemuServer.pm | 79 +--
 2 files changed, 15 insertions(+), 78 deletions(-)

diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index aa1cd16..9dc07a6 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -919,7 +919,7 @@ __PACKAGE__->register_method({
 
my $conf = PVE::QemuConfig->load_config($param->{vmid});
 
-   my $pending_delete_hash = 
PVE::QemuServer::split_flagged_list($conf->{pending}->{delete});
+   my $pending_delete_hash = 
PVE::QemuConfig->parse_pending_delete($conf->{pending}->{delete});
 
my $res = [];
 
@@ -1170,7 +1170,7 @@ my $update_vm_api  = sub {
$rpcenv->check_vm_perm($authuser, $vmid, undef, 
['VM.Config.Disk']);
PVE::QemuServer::vmconfig_register_unused_drive($storecfg, 
$vmid, $conf, PVE::QemuServer::parse_drive($opt, $val))
if $is_pending_val;
-   PVE::QemuServer::vmconfig_delete_pending_option($conf, 
$opt, $force);
+   PVE::QemuConfig->add_to_pending_delete($conf, $opt, $force);
PVE::QemuConfig->write_config($vmid, $conf);
} elsif ($opt =~ m/^serial\d+$/) {
if ($val eq 'socket') {
@@ -1178,7 +1178,7 @@ my $update_vm_api  = sub {
} elsif ($authuser ne 'root@pam') {
die "only root can delete '$opt' config for real 
devices\n";
}
-   PVE::QemuServer::vmconfig_delete_pending_option($conf, 
$opt, $force);
+   PVE::QemuConfig->add_to_pending_delete($conf, $opt, $force);
PVE::QemuConfig->write_config($vmid, $conf);
} elsif ($opt =~ m/^usb\d+$/) {
if ($val =~ m/spice/) {
@@ -1186,10 +1186,10 @@ my $update_vm_api  = sub {
} elsif ($authuser ne 'root@pam') {
die "only root can delete '$opt' config for real 
devices\n";
}
-   PVE::QemuServer::vmconfig_delete_pending_option($conf, 
$opt, $force);
+   PVE::QemuConfig->add_to_pending_delete($conf, $opt, $force);
PVE::QemuConfig->write_config($vmid, $conf);
} else {
-   PVE::QemuServer::vmconfig_delete_pending_option($conf, 
$opt, $force);
+   PVE::QemuConfig->add_to_pending_delete($conf, $opt, $force);
PVE::QemuConfig->write_config($vmid, $conf);
}
}
@@ -1230,13 +1230,13 @@ my $update_vm_api  = sub {
} else {
$conf->{pending}->{$opt} = $param->{$opt};
}
-   PVE::QemuServer::vmconfig_undelete_pending_option($conf, $opt);
+   PVE::QemuConfig->remove_from_pending_delete($conf, $opt);
PVE::QemuConfig->write_config($vmid, $conf);
}
 
# remove pending changes when nothing changed
$conf = PVE::QemuConfig->load_config($vmid); # update/reload
-   my $changes = PVE::QemuServer::vmconfig_cleanup_pending($conf);
+   my $changes = PVE::QemuConfig->cleanup_pending($conf);
PVE::QemuConfig->write_config($vmid, $conf) if $changes;
 
return if !scalar(keys %{$conf->{pending}});
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 70ed910..6c499c9 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -2345,40 +2345,6 @@ sub vm_is_volid_owner {
 return undef;
 }
 
-sub split_flagged_list {
-my $text = shift || '';
-$text =~ s/[,;]/ /g;
-$text =~ s/^\s+//;
-return { map { /^(!?)(.*)$/ && ($2, $1) } ($text =~ /\S+/g) };
-}
-
-sub join_flagged_list {
-my ($how, $lst) = @_;
-join $how, map { $lst->{$_} . $_ } keys %$lst;
-}
-
-sub vmconfig_delete_pending_option {
-my ($conf, $key, $force) = @_;
-
-delete $conf->{pending}->{$key};
-my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
-$pending_delete_hash->{$key} = $force ? '!' : '';
-$conf->{pending}->{delete} = join_flagged_list(',', $pending_delete_hash);
-}
-
-sub vmconfig_undelete_pending_option {
-my ($conf, $key) = @_;
-
-my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
-delete $pending_delete_hash->{$key};
-
-if (%$pending_delete_hash) {
-   $conf->{pending}->{delete} = join_flagged_list(',', 
$pending_delete_hash);
-} else {
-   delete $conf->{pending}->{delete};
-}
-}
-
 sub vmconfig_register_unused_drive {
 my ($storecfg, $vmid, $conf, $drive) = @_;
 
@@ -2393,37 +2359,6 @@ sub vmconfig_register_unused_drive {
 }
 }
 
-sub vmconfig_cleanup_pending {
-my ($conf) = @_;
-
-# remove pending changes when nothing ch

[pve-devel] [PATCH v2 qemu-server 05/18] use load_current_config for config GET call

2019-09-30 Thread Oguz Bektas
Signed-off-by: Oguz Bektas 
---
 PVE/API2/Qemu.pm | 35 +--
 1 file changed, 1 insertion(+), 34 deletions(-)

diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index 267a08e..aa1cd16 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -865,40 +865,7 @@ __PACKAGE__->register_method({
 code => sub {
my ($param) = @_;
 
-   my $conf = PVE::QemuConfig->load_config($param->{vmid});
-
-   if (my $snapname = $param->{snapshot}) {
-   my $snapshot = $conf->{snapshots}->{$snapname};
-   die "snapshot '$snapname' does not exist\n" if !defined($snapshot);
-
-   $snapshot->{digest} = $conf->{digest}; # keep file digest for API
-
-   $conf = $snapshot;
-   }
-
-   delete $conf->{snapshots};
-
-   if (!$param->{current}) {
-   foreach my $opt (keys %{$conf->{pending}}) {
-   next if $opt eq 'delete';
-   my $value = $conf->{pending}->{$opt};
-   next if ref($value); # just to be sure
-   $conf->{$opt} = $value;
-   }
-   my $pending_delete_hash = 
PVE::QemuServer::split_flagged_list($conf->{pending}->{delete});
-   foreach my $opt (keys %$pending_delete_hash) {
-   delete $conf->{$opt} if $conf->{$opt};
-   }
-   }
-
-   delete $conf->{pending};
-
-   # hide cloudinit password
-   if ($conf->{cipassword}) {
-   $conf->{cipassword} = '**';
-   }
-
-   return $conf;
+   return PVE::QemuConfig->load_current_config($param->{vmid}, 
$param->{snapshot}, $param->{current});
 }});
 
 __PACKAGE__->register_method({
-- 
2.20.1

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v2 qemu-server 07/18] use format_pending from GuestHelpers for 'qm pending' command

2019-09-30 Thread Oguz Bektas
Signed-off-by: Oguz Bektas 
---
 PVE/CLI/qm.pm | 28 +---
 1 file changed, 1 insertion(+), 27 deletions(-)

diff --git a/PVE/CLI/qm.pm b/PVE/CLI/qm.pm
index 17935d0..2f1969a 100755
--- a/PVE/CLI/qm.pm
+++ b/PVE/CLI/qm.pm
@@ -898,33 +898,7 @@ our $cmddef = {
}
}],
 
-pending => [ "PVE::API2::Qemu", 'vm_pending', ['vmid'],
-   { node => $nodename }, sub {
-   my $data = shift;
-   foreach my $item (sort { $a->{key} cmp $b->{key}} @$data) {
-   my $k = $item->{key};
-   next if $k eq 'digest';
-   my $v = $item->{value};
-   my $p = $item->{pending};
-   if ($k eq 'description') {
-   $v = PVE::Tools::encode_text($v) if defined($v);
-   $p = PVE::Tools::encode_text($p) if defined($p);
-   }
-   if (defined($v)) {
-   if ($item->{delete}) {
-   print "del $k: $v\n";
-   } elsif (defined($p)) {
-   print "cur $k: $v\n";
-   print "new $k: $p\n";
-   } else {
-   print "cur $k: $v\n";
-   }
-   } elsif (defined($p)) {
-   print "new $k: $p\n";
-   }
-   }
-   }],
-
+pending => [ "PVE::API2::Qemu", 'vm_pending', ['vmid'], { node => 
$nodename }, \&PVE::GuestHelpers::format_pending ],
 showcmd => [ __PACKAGE__, 'showcmd', ['vmid']],
 
 status => [ __PACKAGE__, 'status', ['vmid']],
-- 
2.20.1

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v2 00/18] lxc pending changes

2019-09-30 Thread Oguz Bektas
this series makes it possible to add/delete/revert pending changes in
the backend for containers.

this v2 took longer than expected, mainly because there were small bugs
popping up everywhere, everytime i tried to change anything :)

big thanks to fabian for the extensive review on v1, and for putting up
with me :D


v1 -> v2:
* better refactoring into guest-common, as suggested by fabian and
thomas
* fixed up some bugs (probably added some too):
* backup/restore
* cloning
* unlimited swap bug
* mountpoint handling (more on that)
* other stuff that i can't remember right now :D
* small changes with style
* in v1, mountpoints were a special-special case, since they were
handled earlier in code before going into the hotplug/apply pending
routines. after much discussion, they're now created/deleted in these
phases instead of update_pct_config. unused disks can still be removed
directly.
* some other small changes around helper functions, mainly adding them
support for handling $conf->{pending}

pve-container:

Oguz Bektas (11):
  add lxc/pending API path
  add 'pct pending'
  adapt CT config parser for pending changes
  use load_current_config for config GET call
  skip pending changes while cloning
  skip pending changes while taking backup
  apply pending changes during container start
  add revert parameter to config PUT
  adapt config PUT method for the new update_pct_config
  rework update_pct_config to write into pending section
  add vmconfig_hotplug_pending and vmconfig_apply_pending

 src/PVE/API2/LXC.pm|  89 ++
 src/PVE/API2/LXC/Config.pm |  82 ++
 src/PVE/CLI/pct.pm |   3 +
 src/PVE/LXC.pm |  21 +-
 src/PVE/LXC/Config.pm  | 566 +
 src/PVE/VZDump/LXC.pm  |   1 +
 6 files changed, 457 insertions(+), 305 deletions(-)

qemu-server:

Oguz Bektas (4):
  overwrite load_current_config from AbstractConfig
  use load_current_config for config GET call
  refactor pending changes related code
  use format_pending from GuestHelpers for 'qm pending' command

 PVE/API2/Qemu.pm  | 49 +
 PVE/CLI/qm.pm | 28 +
 PVE/QemuConfig.pm | 14 +
 PVE/QemuServer.pm | 79 +--
 4 files changed, 31 insertions(+), 139 deletions(-)

pve-guest-common:
Oguz Bektas (3):
  refactor pending changes related config code into AbstractConfig
  refactor method used by config GET calls into AbstractConfig
  refactor code from qm/pct 'pending' call into AbstractConfig

 PVE/AbstractConfig.pm | 103 ++
 PVE/GuestHelpers.pm   |  26 +++
 2 files changed, 129 insertions(+)

-- 
2.20.1

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v2 qemu-server 04/18] overwrite load_current_config from AbstractConfig

2019-09-30 Thread Oguz Bektas
we overwrite the load_current_config method from AbstractConfig, in
order to handle cipassword.

Signed-off-by: Oguz Bektas 
---
 PVE/QemuConfig.pm | 14 ++
 1 file changed, 14 insertions(+)

diff --git a/PVE/QemuConfig.pm b/PVE/QemuConfig.pm
index edbf1a7..7f229b3 100644
--- a/PVE/QemuConfig.pm
+++ b/PVE/QemuConfig.pm
@@ -397,6 +397,20 @@ sub __snapshot_foreach_volume {
 
 PVE::QemuServer::foreach_drive($conf, $func);
 }
+
+sub load_current_config {
+my ($class, $vmid, $snapname, $current) = @_;
+
+my $conf = $class->SUPER::load_current_config($vmid, $snapname, $current);
+
+if ($conf->{cipassword}) {
+   $conf->{cipassword} = '**';
+}
+
+return $conf;
+}
+
+
 # END implemented abstract methods from PVE::AbstractConfig
 
 1;
-- 
2.20.1

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v2 container 11/18] use load_current_config for config GET call

2019-09-30 Thread Oguz Bektas
Signed-off-by: Oguz Bektas 
---
 src/PVE/API2/LXC/Config.pm | 22 --
 1 file changed, 8 insertions(+), 14 deletions(-)

diff --git a/src/PVE/API2/LXC/Config.pm b/src/PVE/API2/LXC/Config.pm
index 769fc3b..7eaef74 100644
--- a/src/PVE/API2/LXC/Config.pm
+++ b/src/PVE/API2/LXC/Config.pm
@@ -34,6 +34,12 @@ __PACKAGE__->register_method({
properties => {
node => get_standard_option('pve-node'),
vmid => get_standard_option('pve-vmid', { completion => 
\&PVE::LXC::complete_ctid }),
+   current => {
+   description => "Get current values (instead of pending 
values).",
+   optional => 1,
+   default => 0,
+   type => 'boolean',
+   },
snapshot => get_standard_option('pve-snapshot-name', {
description => "Fetch config values from given snapshot.",
optional => 1,
@@ -62,22 +68,10 @@ __PACKAGE__->register_method({
 code => sub {
my ($param) = @_;
 
-   my $conf = PVE::LXC::Config->load_config($param->{vmid});
-
-   if (my $snapname = $param->{snapshot}) {
-   my $snapshot = $conf->{snapshots}->{$snapname};
-   die "snapshot '$snapname' does not exist\n" if !defined($snapshot);
-
-   # we need the digest of the file
-   $snapshot->{digest} = $conf->{digest};
-   $conf = $snapshot;
-   }
-
-   delete $conf->{snapshots};
-
-   return $conf;
+   return PVE::LXC::Config->load_current_config($param->{vmid}, 
$param->{snapshot}, $param->{current})
 }});
 
+
 my $vm_config_perm_list = [
 'VM.Config.Disk',
 'VM.Config.CPU',
-- 
2.20.1

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v2 guest-common 02/18] refactor method used by config GET calls into AbstractConfig

2019-09-30 Thread Oguz Bektas
since this method will be both used by qemu and lxc config GET calls, it
makes sense to move it into AbstractConfig. only difference is that qemu
also hides the cipassword when it's set. this can be handled by having
qemu overwrite the method and add the cipassword code.

Signed-off-by: Oguz Bektas 
---
 PVE/AbstractConfig.pm | 35 +++
 1 file changed, 35 insertions(+)

diff --git a/PVE/AbstractConfig.pm b/PVE/AbstractConfig.pm
index 910ca86..6d3f169 100644
--- a/PVE/AbstractConfig.pm
+++ b/PVE/AbstractConfig.pm
@@ -136,6 +136,41 @@ sub cleanup_pending {
 return $changes;
 }
 
+sub load_current_config {
+my ($class, $vmid, $snapname, $current) = @_;
+
+my $conf = $class->load_config($vmid);
+
+if ($snapname) {
+   my $snapshot = $conf->{snapshots}->{$snapname};
+   die "snapshot '$snapname' does not exist\n" if !defined($snapshot);
+
+   # we need the digest of the file
+   $snapshot->{digest} = $conf->{digest};
+   $conf = $snapshot;
+}
+
+# take pending changes in
+if (!$current) {
+   foreach my $opt (keys %{$conf->{pending}}) {
+   next if $opt eq 'delete';
+   my $value = $conf->{pending}->{$opt};
+   next if ref($value); # just to be sure
+   $conf->{$opt} = $value;
+   }
+   my $pending_delete_hash = 
$class->parse_pending_delete($conf->{pending}->{delete});
+   foreach my $opt (keys %$pending_delete_hash) {
+   delete $conf->{$opt} if $conf->{$opt};
+   }
+}
+
+delete $conf->{snapshots};
+delete $conf->{pending};
+
+return $conf;
+}
+
+
 # Lock config file using flock, run $code with @param, unlock config file.
 # $timeout is the maximum time to aquire the flock
 sub lock_config_full {
-- 
2.20.1

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v2 guest-common 03/18] refactor code from qm/pct 'pending' call into AbstractConfig

2019-09-30 Thread Oguz Bektas
Signed-off-by: Oguz Bektas 
---
 PVE/GuestHelpers.pm | 26 ++
 1 file changed, 26 insertions(+)

diff --git a/PVE/GuestHelpers.pm b/PVE/GuestHelpers.pm
index ebe2781..a16433f 100644
--- a/PVE/GuestHelpers.pm
+++ b/PVE/GuestHelpers.pm
@@ -60,4 +60,30 @@ sub exec_hookscript {
 }
 }
 
+sub format_pending {
+my ($data) = @_;
+foreach my $item (sort { $a->{key} cmp $b->{key}} @$data) {
+   my $k = $item->{key};
+   next if $k eq 'digest';
+   my $v = $item->{value};
+   my $p = $item->{pending};
+   if ($k eq 'description') {
+   $v = PVE::Tools::encode_text($v) if defined($v);
+   $p = PVE::Tools::encode_text($p) if defined($p);
+   }
+   if (defined($v)) {
+   if ($item->{delete}) {
+   print "del $k: $v\n";
+   } elsif (defined($p)) {
+   print "cur $k: $v\n";
+   print "new $k: $p\n";
+   } else {
+   print "cur $k: $v\n";
+   }
+   } elsif (defined($p)) {
+   print "new $k: $p\n";
+   }
+}
+}
+
 1;
-- 
2.20.1

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v2 container 10/18] adapt CT config parser for pending changes

2019-09-30 Thread Oguz Bektas
config parser can now read/write [pve:pending] section. this was named
such, instead of [PENDING], after on- and offline discussion regarding
namespacing the pending section and snapshots.

this also adds an optional non-capturing regex group into the parser for
[snap: snapname] entries which can be supported in PVE 7.0

Signed-off-by: Oguz Bektas 
---
 src/PVE/LXC/Config.pm | 37 -
 1 file changed, 32 insertions(+), 5 deletions(-)

diff --git a/src/PVE/LXC/Config.pm b/src/PVE/LXC/Config.pm
index 9790345..47bd4bb 100644
--- a/src/PVE/LXC/Config.pm
+++ b/src/PVE/LXC/Config.pm
@@ -751,6 +751,7 @@ sub parse_pct_config {
 my $res = {
digest => Digest::SHA::sha1_hex($raw),
snapshots => {},
+   pending => {},
 };
 
 $filename =~ m|/lxc/(\d+).conf$|
@@ -766,7 +767,14 @@ sub parse_pct_config {
 foreach my $line (@lines) {
next if $line =~ m/^\s*$/;
 
-   if ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
+   if ($line =~ m/^\[pve:pending\]\s*$/i) {
+   $section = 'pending';
+   $conf->{description} = $descr if $descr;
+   $descr = '';
+   $conf = $res->{$section} = {};
+   next;
+   } elsif ($line =~ m/^\[(?:snap:)?([a-z][a-z0-9_\-]+)\]\s*$/i) {
+   # extended regex for namespacing snapshots in PVE 7.0
$section = $1;
$conf->{description} = $descr if $descr;
$descr = '';
@@ -794,6 +802,13 @@ sub parse_pct_config {
$descr .= PVE::Tools::decode_text($2);
} elsif ($line =~ m/snapstate:\s*(prepare|delete)\s*$/) {
$conf->{snapstate} = $1;
+   } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
+   my $value = $1;
+   if ($section eq 'pending') {
+   $conf->{delete} = $value;
+   } else {
+   warn "vm $vmid - property 'delete' is only allowed in 
[pve:pending]\n";
+   }
} elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S.*)\s*$/) {
my $key = $1;
my $value = $2;
@@ -832,14 +847,19 @@ sub write_pct_config {
 }
 
 my $generate_raw_config = sub {
-   my ($conf) = @_;
+   my ($conf, $pending) = @_;
 
my $raw = '';
 
# add description as comment to top of file
-   my $descr = $conf->{description} || '';
-   foreach my $cl (split(/\n/, $descr)) {
-   $raw .= '#' .  PVE::Tools::encode_text($cl) . "\n";
+   if (defined(my $descr = $conf->{description})) {
+   if ($descr) {
+   foreach my $cl (split(/\n/, $descr)) {
+   $raw .= '#' .  PVE::Tools::encode_text($cl) . "\n";
+   }
+   } else {
+   $raw .= "#\n" if $pending;
+   }
}
 
foreach my $key (sort keys %$conf) {
@@ -864,7 +884,14 @@ sub write_pct_config {
 
 my $raw = &$generate_raw_config($conf);
 
+if (scalar(keys %{$conf->{pending}})){
+   $raw .= "\n[pve:pending]\n";
+   $raw .= &$generate_raw_config($conf->{pending}, 1);
+}
+
 foreach my $snapname (sort keys %{$conf->{snapshots}}) {
+   # TODO: namespace snapshots for PVE 7.0
+   #$raw .= "\n[snap:$snapname]\n";
$raw .= "\n[$snapname]\n";
$raw .= &$generate_raw_config($conf->{snapshots}->{$snapname});
 }
-- 
2.20.1

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v2 container 08/18] add lxc/pending API path

2019-09-30 Thread Oguz Bektas
Signed-off-by: Oguz Bektas 
---
 src/PVE/API2/LXC.pm | 88 +
 1 file changed, 88 insertions(+)

diff --git a/src/PVE/API2/LXC.pm b/src/PVE/API2/LXC.pm
index 07280fb..9c040d1 100644
--- a/src/PVE/API2/LXC.pm
+++ b/src/PVE/API2/LXC.pm
@@ -515,6 +515,7 @@ __PACKAGE__->register_method({
 
my $res = [
{ subdir => 'config' },
+   { subdir => 'pending' },
{ subdir => 'status' },
{ subdir => 'vncproxy' },
{ subdir => 'termproxy' },
@@ -1865,4 +1866,91 @@ __PACKAGE__->register_method({
return $task;
   }});
 
+__PACKAGE__->register_method({
+name => 'vm_pending',
+path => '{vmid}/pending',
+method => 'GET',
+proxyto => 'node',
+description => 'Get container configuration, including pending changes.',
+permissions => {
+   check => ['perm', '/vms/{vmid}', [ 'VM.Audit' ]],
+},
+parameters => {
+   additionalProperties => 0,
+   properties => {
+   node => get_standard_option('pve-node'),
+   vmid => get_standard_option('pve-vmid', { completion => 
\&PVE::LXC::complete_ctid }),
+   },
+},
+returns => {
+   type => "array",
+   items => {
+   type => "object",
+   properties => {
+   key => {
+   description => 'Configuration option name.',
+   type => 'string',
+   },
+   value => {
+   description => 'Current value.',
+   type => 'string',
+   optional => 1,
+   },
+   pending => {
+   description => 'Pending value.',
+   type => 'string',
+   optional => 1,
+   },
+   delete => {
+   description => "Indicates a pending delete request if 
present and not 0.",
+   type => 'integer',
+   minimum => 0,
+   maximum => 1,
+   optional => 1,
+   },
+   },
+   },
+},
+code => sub {
+   my ($param) = @_;
+
+   my $conf = PVE::LXC::Config->load_config($param->{vmid});
+
+   my $pending_delete_hash = 
PVE::LXC::Config->parse_pending_delete($conf->{pending}->{delete});
+
+   my $res = [];
+
+   foreach my $opt (keys %$conf) {
+   next if ref($conf->{$opt});
+   next if $opt eq 'pending';
+   my $item = { key => $opt } ;
+   $item->{value} = $conf->{$opt} if defined($conf->{$opt});
+   $item->{pending} = $conf->{pending}->{$opt} if 
defined($conf->{pending}->{$opt});
+   $item->{delete} = ($pending_delete_hash->{$opt} ? 2 : 1) if exists 
$pending_delete_hash->{$opt};
+
+   push @$res, $item;
+   }
+
+   foreach my $opt (keys %{$conf->{pending}}) {
+   next if $opt eq 'delete';
+   next if ref($conf->{pending}->{$opt});
+   next if defined($conf->{$opt});
+   my $item = { key => $opt };
+   $item->{pending} = $conf->{pending}->{$opt};
+
+   push @$res, $item;
+   }
+
+   # FIXME: $force delete is not implemented for CTs
+   while (my ($opt, undef) = each %$pending_delete_hash) {
+   next if $conf->{pending}->{$opt};
+   next if $conf->{$opt};
+   my $item = { key => $opt, delete => 1 };
+   push @$res, $item;
+   }
+
+   return $res;
+
+}});
+
 1;
-- 
2.20.1

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v2 container 09/18] add 'pct pending'

2019-09-30 Thread Oguz Bektas
same as 'qm pending', the code is shared via GuestHelpers

Signed-off-by: Oguz Bektas 
---
 src/PVE/CLI/pct.pm | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/PVE/CLI/pct.pm b/src/PVE/CLI/pct.pm
index 35ad72f..476f44d 100755
--- a/src/PVE/CLI/pct.pm
+++ b/src/PVE/CLI/pct.pm
@@ -7,6 +7,7 @@ use POSIX;
 use Fcntl;
 use File::Copy 'copy';
 
+use PVE::GuestHelpers;
 use PVE::SafeSyslog;
 use PVE::Tools qw(extract_param);
 use PVE::CpuSet;
@@ -821,6 +822,8 @@ our $cmddef = {
}
}
}],
+
+pending => [ "PVE::API2::LXC", "vm_pending", ['vmid'], { node => $nodename 
}, \&PVE::GuestHelpers::format_pending ],
 set => [ 'PVE::API2::LXC::Config', 'update_vm', ['vmid'], { node => 
$nodename }],
 
 resize => [ "PVE::API2::LXC", 'resize_vm', ['vmid', 'disk', 'size'], { 
node => $nodename } ],
-- 
2.20.1

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v2 container 12/18] skip pending changes while cloning

2019-09-30 Thread Oguz Bektas
Signed-off-by: Oguz Bektas 
---
 src/PVE/API2/LXC.pm | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/PVE/API2/LXC.pm b/src/PVE/API2/LXC.pm
index 9c040d1..2cb9f9d 100644
--- a/src/PVE/API2/LXC.pm
+++ b/src/PVE/API2/LXC.pm
@@ -1441,6 +1441,7 @@ __PACKAGE__->register_method({
# Replace the 'disk' lock with a 'create' lock.
$newconf->{lock} = 'create';
 
+   delete $newconf->{pending};
delete $newconf->{template};
if ($param->{hostname}) {
$newconf->{hostname} = $param->{hostname};
-- 
2.20.1

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v2 container 15/18] add revert parameter to config PUT

2019-09-30 Thread Oguz Bektas
Signed-off-by: Oguz Bektas 
---
 src/PVE/API2/LXC/Config.pm | 5 +
 1 file changed, 5 insertions(+)

diff --git a/src/PVE/API2/LXC/Config.pm b/src/PVE/API2/LXC/Config.pm
index 7eaef74..2c036f5 100644
--- a/src/PVE/API2/LXC/Config.pm
+++ b/src/PVE/API2/LXC/Config.pm
@@ -102,6 +102,11 @@ __PACKAGE__->register_method({
description => "A list of settings you want to delete.",
optional => 1,
},
+   revert => {
+   type => 'string', format => 'pve-configid-list',
+   description => "Revert a pending change.",
+   optional => 1,
+   },
digest => {
type => 'string',
description => 'Prevent changes if current configuration 
file has different SHA1 digest. This can be used to prevent concurrent 
modifications.',
-- 
2.20.1

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v2 container 18/18] add vmconfig_hotplug_pending and vmconfig_apply_pending

2019-09-30 Thread Oguz Bektas
vmconfig_hotplug_pending is responsible for checking if a key/value pair in the
pending section can be hotplugged, if yes; perform a generic replace,
or perform specific actions for hotplugging the special cases.

vmconfig_apply_pending is only supposed to be called when ct isn't live.

Signed-off-by: Oguz Bektas 
---
 src/PVE/LXC.pm|  14 +--
 src/PVE/LXC/Config.pm | 199 --
 2 files changed, 203 insertions(+), 10 deletions(-)

diff --git a/src/PVE/LXC.pm b/src/PVE/LXC.pm
index 65c41f5..f91e27d 100644
--- a/src/PVE/LXC.pm
+++ b/src/PVE/LXC.pm
@@ -1632,7 +1632,7 @@ sub alloc_disk {
 
 our $NEW_DISK_RE = qr/^([^:\s]+):(\d+(\.\d+)?)$/;
 sub create_disks {
-my ($storecfg, $vmid, $settings, $conf) = @_;
+my ($storecfg, $vmid, $settings, $conf, $pending) = @_;
 
 my $vollist = [];
 
@@ -1659,10 +1659,14 @@ sub create_disks {
push @$vollist, $volid;
$mountpoint->{volume} = $volid;
$mountpoint->{size} = $size_kb * 1024;
-   $conf->{$ms} = 
PVE::LXC::Config->print_ct_mountpoint($mountpoint, $ms eq 'rootfs');
+   if ($pending) {
+   $conf->{pending}->{$ms} = 
PVE::LXC::Config->print_ct_mountpoint($mountpoint, $ms eq 'rootfs');
+   } else {
+   $conf->{$ms} = 
PVE::LXC::Config->print_ct_mountpoint($mountpoint, $ms eq 'rootfs');
+   }
} else {
-# use specified/existing volid/dir/device
-$conf->{$ms} = 
PVE::LXC::Config->print_ct_mountpoint($mountpoint, $ms eq 'rootfs');
+   # use specified/existing volid/dir/device
+   $conf->{$ms} = 
PVE::LXC::Config->print_ct_mountpoint($mountpoint, $ms eq 'rootfs');
}
});
 
@@ -1676,7 +1680,7 @@ sub create_disks {
 # free allocated images on error
 if (my $err = $@) {
destroy_disks($storecfg, $vollist);
-die $err;
+   die $err;
 }
 return $vollist;
 }
diff --git a/src/PVE/LXC/Config.pm b/src/PVE/LXC/Config.pm
index 14c26bc..10dfc75 100644
--- a/src/PVE/LXC/Config.pm
+++ b/src/PVE/LXC/Config.pm
@@ -1177,6 +1177,194 @@ sub option_exists {
 }
 # END JSON config code
 
+my $LXC_FASTPLUG_OPTIONS= {
+'description' => 1,
+'onboot' => 1,
+'startup' => 1,
+'protection' => 1,
+'hostname' => 1,
+'hookscript' => 1,
+'cores' => 1,
+'tags' => 1,
+};
+
+sub vmconfig_hotplug_pending {
+my ($class, $vmid, $conf, $storecfg, $selection, $errors) = @_;
+
+my $pid = PVE::LXC::find_lxc_pid($vmid);
+my $rootdir = "/proc/$pid/root";
+
+my $add_error = sub {
+   my ($opt, $msg) = @_;
+   $errors->{$opt} = "hotplug problem - $msg";
+};
+
+my $changes;
+foreach my $opt (keys %{$conf->{pending}}) { # add/change
+   next if $selection && !$selection->{$opt};
+   if ($LXC_FASTPLUG_OPTIONS->{$opt}) {
+   $conf->{$opt} = delete $conf->{pending}->{$opt};
+   $changes = 1;
+   }
+}
+
+if ($changes) {
+   $class->write_config($vmid, $conf);
+}
+
+# There's no separate swap size to configure, there's memory and "total"
+# memory (iow. memory+swap). This means we have to change them together.
+my $hotplug_memory_done;
+my $hotplug_memory = sub {
+   my ($wanted_memory, $wanted_swap) = @_;
+   my $old_memory = ($conf->{memory} || $confdesc->{memory}->{default});
+   my $old_swap = ($conf->{swap} || $confdesc->{swap}->{default});
+
+   $wanted_memory //= $old_memory;
+   $wanted_swap //= $old_swap;
+
+   my $total = $wanted_memory + $wanted_swap;
+   my $old_total = $old_memory + $old_swap;
+
+   if ($total > $old_total) {
+   PVE::LXC::write_cgroup_value("memory", $vmid,
+"memory.memsw.limit_in_bytes",
+int($total*1024*1024));
+   PVE::LXC::write_cgroup_value("memory", $vmid,
+"memory.limit_in_bytes",
+int($wanted_memory*1024*1024));
+   } else {
+   PVE::LXC::write_cgroup_value("memory", $vmid,
+"memory.limit_in_bytes",
+int($wanted_memory*1024*1024));
+   PVE::LXC::write_cgroup_value("memory", $vmid,
+"memory.memsw.limit_in_bytes",
+int($total*1024*1024));
+   }
+   $hotplug_memory_done = 1;
+};
+
+my $pending_delete_hash = 
$class->parse_pending_delete($conf->{pending}->{delete});
+# FIXME: $force deletion is not implemented for CTs
+while (my ($opt, undef) = each %$pending_delete_hash) {
+   next if $selection && !$selection->{$opt};
+   eval {
+   if ($LXC_FASTPLUG_OPTIONS->{$opt}) {
+   # pass
+   } elsif ($opt =~ m/^unused(\d+)$/) {
+

[pve-devel] [PATCH v2 container 16/18] adapt config PUT method for the new update_pct_config

2019-09-30 Thread Oguz Bektas
we don't need to extract 'delete' here, instead we pass it all as $param
and extract 'delete', 'revert' and most other things in
update_pct_config

Signed-off-by: Oguz Bektas 
---
 src/PVE/API2/LXC/Config.pm | 55 --
 1 file changed, 5 insertions(+), 50 deletions(-)

diff --git a/src/PVE/API2/LXC/Config.pm b/src/PVE/API2/LXC/Config.pm
index 2c036f5..46d8e2f 100644
--- a/src/PVE/API2/LXC/Config.pm
+++ b/src/PVE/API2/LXC/Config.pm
@@ -119,58 +119,10 @@ __PACKAGE__->register_method({
 code => sub {
my ($param) = @_;
 
-   my $rpcenv = PVE::RPCEnvironment::get();
-   my $authuser = $rpcenv->get_user();
-
my $node = extract_param($param, 'node');
my $vmid = extract_param($param, 'vmid');
-
my $digest = extract_param($param, 'digest');
 
-   die "no options specified\n" if !scalar(keys %$param);
-
-   my $delete_str = extract_param($param, 'delete');
-   my @delete = PVE::Tools::split_list($delete_str);
-
-   PVE::LXC::check_ct_modify_config_perm($rpcenv, $authuser, $vmid, undef, 
{}, [@delete]);
-
-   foreach my $opt (@delete) {
-   raise_param_exc({ delete => "you can't use '-$opt' and -delete 
$opt' at the same time" })
-   if defined($param->{$opt});
-
-   if (!PVE::LXC::Config->option_exists($opt)) {
-   raise_param_exc({ delete => "unknown option '$opt'" });
-   }
-   }
-
-   PVE::LXC::check_ct_modify_config_perm($rpcenv, $authuser, $vmid, undef, 
$param, []);
-
-   my $storage_cfg = cfs_read_file("storage.cfg");
-
-   my $repl_conf = PVE::ReplicationConfig->new();
-   my $is_replicated = $repl_conf->check_for_existing_jobs($vmid, 1);
-   if ($is_replicated) {
-   PVE::LXC::Config->foreach_mountpoint_full($param, 0, sub {
-   my ($opt, $mountpoint) = @_;
-   my $volid = $mountpoint->{volume};
-   return if !$volid || !($mountpoint->{replicate}//1);
-   if ($mountpoint->{type} eq 'volume') {
-   my ($storeid, $format);
-   if ($volid =~ $PVE::LXC::NEW_DISK_RE) {
-   $storeid = $1;
-   $format = $mountpoint->{format} || 
PVE::Storage::storage_default_format($storage_cfg, $storeid);
-   } else {
-   ($storeid, undef) = 
PVE::Storage::parse_volume_id($volid, 1);
-   $format = (PVE::Storage::parse_volname($storage_cfg, 
$volid))[6];
-   }
-   return if PVE::Storage::storage_can_replicate($storage_cfg, 
$storeid, $format);
-   my $scfg = PVE::Storage::storage_config($storage_cfg, 
$storeid);
-   return if $scfg->{shared};
-   }
-   die "cannot add non-replicatable volume to a replicated VM\n";
-   });
-   }
-
my $code = sub {
 
my $conf = PVE::LXC::Config->load_config($vmid);
@@ -180,10 +132,13 @@ __PACKAGE__->register_method({
 
my $running = PVE::LXC::check_running($vmid);
 
-   PVE::LXC::Config->update_pct_config($vmid, $conf, $running, $param, 
\@delete);
+   die "no options specified\n" if !scalar(keys %$param);
+
+   PVE::LXC::Config->update_pct_config($vmid, $conf, $running, $param);
+   $conf = PVE::LXC::Config->load_config($vmid);
 
-   PVE::LXC::Config->write_config($vmid, $conf);
PVE::LXC::update_lxc_config($vmid, $conf);
+
};
 
PVE::LXC::Config->lock_config($vmid, $code);
-- 
2.20.1

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v2 container 14/18] apply pending changes during container start

2019-09-30 Thread Oguz Bektas
Signed-off-by: Oguz Bektas 
---
 src/PVE/LXC.pm | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/src/PVE/LXC.pm b/src/PVE/LXC.pm
index 475d9be..65c41f5 100644
--- a/src/PVE/LXC.pm
+++ b/src/PVE/LXC.pm
@@ -1930,6 +1930,13 @@ sub userns_command {
 sub vm_start {
 my ($vmid, $conf, $skiplock) = @_;
 
+# apply pending changes while starting
+my $storecfg = PVE::Storage::config();
+if (scalar(keys %{$conf->{pending}})) {
+   PVE::LXC::Config->vmconfig_apply_pending($vmid, $conf, $storecfg);
+   $conf = PVE::LXC::Config->load_config($vmid); # update/reload
+}
+
 update_lxc_config($vmid, $conf);
 
 my $skiplock_flag_fn = "/run/lxc/skiplock-$vmid";
-- 
2.20.1

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v2 container 13/18] skip pending changes while taking backup

2019-09-30 Thread Oguz Bektas
Signed-off-by: Oguz Bektas 
---
 src/PVE/VZDump/LXC.pm | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/PVE/VZDump/LXC.pm b/src/PVE/VZDump/LXC.pm
index ad5ecc8..2a6449c 100644
--- a/src/PVE/VZDump/LXC.pm
+++ b/src/PVE/VZDump/LXC.pm
@@ -288,6 +288,7 @@ sub assemble {
 delete $conf->{lock};
 delete $conf->{snapshots};
 delete $conf->{parent};
+delete $conf->{pending};
 
 PVE::Tools::file_set_contents("$tmpdir/etc/vzdump/pct.conf", 
PVE::LXC::Config::write_pct_config("/lxc/$vmid.conf", $conf));
 
-- 
2.20.1

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v2 container 17/18] rework update_pct_config to write into pending section

2019-09-30 Thread Oguz Bektas
use vmconfig_hotplug_pending or vmconfig_apply_pending to apply the
pending changes, depending on whether the CT is on- or offline.

Signed-off-by: Oguz Bektas 
---
 src/PVE/LXC/Config.pm | 334 ++
 1 file changed, 106 insertions(+), 228 deletions(-)

diff --git a/src/PVE/LXC/Config.pm b/src/PVE/LXC/Config.pm
index 47bd4bb..14c26bc 100644
--- a/src/PVE/LXC/Config.pm
+++ b/src/PVE/LXC/Config.pm
@@ -4,11 +4,13 @@ use strict;
 use warnings;
 
 use PVE::AbstractConfig;
+use PVE::RPCEnvironment;
 use PVE::Cluster qw(cfs_register_file);
 use PVE::GuestHelpers;
 use PVE::INotify;
+use PVE::Exception qw(raise_param_exc);
 use PVE::JSONSchema qw(get_standard_option);
-use PVE::Tools;
+use PVE::Tools qw(extract_param);
 
 use base qw(PVE::AbstractConfig);
 
@@ -900,267 +902,143 @@ sub write_pct_config {
 }
 
 sub update_pct_config {
-my ($class, $vmid, $conf, $running, $param, $delete) = @_;
+my ($class, $vmid, $conf, $running, $param) = @_;
 
-my @nohotplug;
+my $rpcenv = PVE::RPCEnvironment::get();
+my $authuser = $rpcenv->get_user();
 
-my $new_disks = 0;
-my @deleted_volumes;
+my $delete_str = extract_param($param, 'delete');
+my @delete = PVE::Tools::split_list($delete_str);
+my $revert_str = extract_param($param, 'revert');
+my @revert = PVE::Tools::split_list($revert_str);
 
-my $rootdir;
-if ($running) {
-   my $pid = PVE::LXC::find_lxc_pid($vmid);
-   $rootdir = "/proc/$pid/root";
+PVE::LXC::check_ct_modify_config_perm($rpcenv, $authuser, $vmid, undef, 
{}, [@delete]);
+
+foreach my $opt (PVE::Tools::split_list($revert_str)) {
+   raise_param_exc({ revert => "unknown option '$opt'" })
+   if !$class->option_exists($opt);
+
+   raise_param_exc({ delete => "you can't use '-$opt' and " .
+ "'-revert $opt' at the same time" })
+   if defined($param->{$opt});
+
+   push @revert, $opt;
 }
 
-my $hotplug_error = sub {
-   if ($running) {
-   push @nohotplug, @_;
-   return 1;
-   } else {
-   return 0;
-   }
-};
+foreach my $opt (@revert) {
+   delete $conf->{pending}->{$opt};
+   # FIXME: maybe check before doing this?
+   $class->remove_from_pending_delete($conf, $opt); # remove from deletion 
queue
+}
+$class->write_config($vmid, $conf);
 
-if (defined($delete)) {
-   foreach my $opt (@$delete) {
-   if (!exists($conf->{$opt})) {
-   # silently ignore
-   next;
-   }
+foreach my $opt (@delete) {
+   raise_param_exc({ delete => "you can't use '-$opt' and -delete $opt' at 
the same time" })
+   if defined($param->{$opt});
 
-   if ($opt eq 'memory' || $opt eq 'rootfs') {
-   die "unable to delete required option '$opt'\n";
-   } elsif ($opt eq 'hostname') {
-   delete $conf->{$opt};
-   } elsif ($opt eq 'swap') {
-   delete $conf->{$opt};
-   PVE::LXC::write_cgroup_value("memory", $vmid,
-"memory.memsw.limit_in_bytes", -1);
-   } elsif ($opt eq 'description' || $opt eq 'onboot' || $opt eq 
'startup' || $opt eq 'hookscript') {
-   delete $conf->{$opt};
-   } elsif ($opt eq 'nameserver' || $opt eq 'searchdomain' ||
-$opt eq 'tty' || $opt eq 'console' || $opt eq 'cmode') {
-   next if $hotplug_error->($opt);
-   delete $conf->{$opt};
-   } elsif ($opt eq 'cores') {
-   delete $conf->{$opt}; # rest is handled by pvestatd
-   } elsif ($opt eq 'cpulimit') {
-   PVE::LXC::write_cgroup_value("cpu", $vmid, "cpu.cfs_quota_us", 
-1);
-   delete $conf->{$opt};
-   } elsif ($opt eq 'cpuunits') {
-   PVE::LXC::write_cgroup_value("cpu", $vmid, "cpu.shares", 
$confdesc->{cpuunits}->{default});
-   delete $conf->{$opt};
-   } elsif ($opt =~ m/^net(\d)$/) {
-   delete $conf->{$opt};
-   next if !$running;
-   my $netid = $1;
-   PVE::Network::veth_delete("veth${vmid}i$netid");
-   } elsif ($opt eq 'protection') {
-   delete $conf->{$opt};
-   } elsif ($opt =~ m/^unused(\d+)$/) {
-   next if $hotplug_error->($opt);
-   PVE::LXC::Config->check_protection($conf, "can't remove CT 
$vmid drive '$opt'");
-   push @deleted_volumes, $conf->{$opt};
-   delete $conf->{$opt};
-   } elsif ($opt =~ m/^mp(\d+)$/) {
-   next if $hotplug_error->($opt);
-   PVE::LXC::Config->check_protection($conf, "can't remove CT 
$vmid drive '$opt'");
-   my $mp = PVE::LXC::Config->parse_ct_mountpoint($conf->{$opt});
-   delete $conf->{$opt};
-   if ($mp->{type} eq 'volume') {
-   PVE::LXC::Co

Re: [pve-devel] [PATCH pve-zsync] Allow detecting a syncing instance of a job

2019-09-30 Thread Thomas Lamprecht
On 9/30/19 12:55 PM, Fabian Ebner wrote:
> Before, the check whether a syncing instance of the same job is already 
> present
> was inside the locked section. This caused cron to continuously spawn new
> instances of pve-zsync on syncs (or rather groups of syncs) taking longer
> than 15 minutes, see [0] in the forum. This patch introduces a new locked
> section for checking the current status and a new 'waiting' status.
> The 'waiting' status is needed to mark jobs which are currently waiting
> for the lock for syncing. So if job A is syncing and job B is waiting for
> the lock then all new instances of job B will see that one instance is
> already scheduled to sync.
> 
> [0]: 
> https://forum.proxmox.com/threads/pve-zsync-bug-spawns-endless-cron-processes.58087/
> 
> Signed-off-by: Fabian Ebner 
> ---
>  pve-zsync | 25 -
>  1 file changed, 20 insertions(+), 5 deletions(-)
> 

Looks OK, a small style nit and proposal for eventual refactoring in-line

> diff --git a/pve-zsync b/pve-zsync
> index 425ffa2..90c1bb3 100755
> --- a/pve-zsync
> +++ b/pve-zsync
> @@ -19,6 +19,7 @@ my $PVE_DIR = "/etc/pve/local";
>  my $QEMU_CONF = "${PVE_DIR}/qemu-server";
>  my $LXC_CONF = "${PVE_DIR}/lxc";
>  my $LOCKFILE = "$CONFIG_PATH/${PROGNAME}.lock";
> +my $LOCKFILE_STATUS_CHECK = "$CONFIG_PATH/${PROGNAME}_status_check.lock";
>  my $PROG_PATH = "$PATH/${PROGNAME}";
>  my $INTERVAL = 15;
>  my $DEBUG;
> @@ -578,20 +579,34 @@ sub destroy_job {
>  sub sync {
>  my ($param) = @_;
>  
> +my $lock_status_check_fh = IO::File->new("> $LOCKFILE_STATUS_CHECK");
> +die "Can't open Lock File: $LOCKFILE_STATUS_CHECK $!\n" if 
> !$lock_status_check_fh;
> +lock($lock_status_check_fh);

Above pattern is repeated quite a few times in this file, maybe we could 
replace it
by something like:

sub locked {
my ($lock_fn, $code) = @_;

my $lock_fh = File...
 
flock($lock_fh, LOCK_EX) || die ...;
my $res = eval { $code->() };
my $err = $@;

flock($fh, LOCK_UN) || warn ...; # always unlock
die "$err" if $err;

close($lock_fh); # or maybe cache this one and keep around? not sure though
return $res;
}


Then we'd have explicit locked segments where we know for sure that unlocking
is always done. But as said, that's some refactoring that could be great nothing
important.

> +
> +my $job;
> +eval {
> + $job = get_job($param);
> +};

Above could be also written as one-liner without losing expressiveness:
my $job = eval { get_job($param) };

This uses the fact that eval (and most blocks in general) in perl implicitly
return the result of the last statement, if no explicit return is (in all
branches). I know you just used a pattern already existent in this file,
but such a "cleanup" could be OK to even to then, IMO.

Not sure, depending if you want to refactor a bit here you could send a v2
else I could apply this and just fixup those "eval assignment" places here,
whatever you prefer.

> +
> +if ($job && defined($job->{state}) && ($job->{state} eq "syncing" || 
> $job->{state} eq "waiting")) {
> + unlock($lock_status_check_fh);
> + die "Job --source $param->{source} --name $param->{name} is already 
> scheduled to sync\n";
> +}
> +
> +$job->{state} = "waiting";
> +update_state($job);
> +unlock($lock_status_check_fh);
> +
>  my $lock_fh = IO::File->new("> $LOCKFILE");
>  die "Can't open Lock File: $LOCKFILE $!\n" if !$lock_fh;
>  lock($lock_fh);
>  
> +#job might've changed while we waited for the lock, but we can be sure 
> it's not syncing
>  my $date = get_date();
> -my $job;
>  eval {
>   $job = get_job($param);
>  };
>  
> -if ($job && defined($job->{state}) && $job->{state} eq "syncing") {
> - die "Job --source $param->{source} --name $param->{name} is syncing at 
> the moment";
> -}
> -
>  my $dest = parse_target($param->{dest});
>  my $source = parse_target($param->{source});
>  
> 


___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] applied: [PATCH qemu-server] qemu 4.0 : add Cascadelake-Server && KnightsMill cpu models

2019-09-30 Thread Thomas Lamprecht
On 9/30/19 11:43 AM, Alexandre Derumier wrote:
> Signed-off-by: Alexandre Derumier 
> ---
>  PVE/QemuServer.pm | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
> index 70ed910..8376260 100644
> --- a/PVE/QemuServer.pm
> +++ b/PVE/QemuServer.pm
> @@ -146,6 +146,9 @@ my $cpu_vendor_list = {
>  'Skylake-Client-IBRS' => 'GenuineIntel',
>  'Skylake-Server' => 'GenuineIntel',
>  'Skylake-Server-IBRS' => 'GenuineIntel',
> +'Cascadelake-Server' => 'GenuineIntel',
> +KnightsMill => 'GenuineIntel',
> +
>  
>  # AMD CPUs
>  athlon => 'AuthenticAMD',
> 

applied, thanks!

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] applied: [PATCH manager] ui: qemubiosedit: add gettext to efi disk hint

2019-09-30 Thread Thomas Lamprecht
On 9/30/19 11:42 AM, Aaron Lauterer wrote:
> Signed-off-by: Aaron Lauterer 
> ---
> 
> Put the hint in one line because AFAIU our tooling cannot handle
> multiline gettext calls.
> 

applied, and yes that's the case.

>  www/manager6/qemu/QemuBiosEdit.js | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
> 
> diff --git a/www/manager6/qemu/QemuBiosEdit.js 
> b/www/manager6/qemu/QemuBiosEdit.js
> index 7283df74..54c0271d 100644
> --- a/www/manager6/qemu/QemuBiosEdit.js
> +++ b/www/manager6/qemu/QemuBiosEdit.js
> @@ -9,8 +9,7 @@ Ext.define('PVE.qemu.BiosEdit', {
>   var EFIHint = Ext.createWidget({
>   xtype: 'displayfield', //submitValue is false, so we don't get 
> submitted
>   userCls: 'pve-hint',
> - value: 'You need to add an EFI disk for storing the ' +
> - 'EFI settings. See the online help for details.',
> + value: gettext('You need to add an EFI disk for storing the EFI 
> settings. See the online help for details.'),
>   hidden: true
>   });
>  
> 


___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] applied: [PATCH pve-manager] cpumodel: qemu 4.0: add Skylake-Server, Cascadelake-Server, KnightsMill

2019-09-30 Thread Thomas Lamprecht
On 9/30/19 11:47 AM, Alexandre Derumier wrote:
> Signed-off-by: Alexandre Derumier 
> ---
>  www/manager6/form/CPUModelSelector.js | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/www/manager6/form/CPUModelSelector.js 
> b/www/manager6/form/CPUModelSelector.js
> index 9eb5b0e9..505d27c8 100644
> --- a/www/manager6/form/CPUModelSelector.js
> +++ b/www/manager6/form/CPUModelSelector.js
> @@ -26,6 +26,9 @@ Ext.define('PVE.form.CPUModelSelector', {
>   ['Broadwell', 'Broadwell'],
>   ['Broadwell-noTSX','Broadwell-noTSX'],
>   ['Skylake-Client','Skylake-Client'],
> + ['Skylake-Server','Skylake-Server'],
> + ['Cascadelake-Server','Cascadelake-Server'],
> + ['KnightsMill','KnightsMill'],
>   ['Opteron_G1', 'Opteron_G1'],
>   ['Opteron_G2', 'Opteron_G2'],
>   ['Opteron_G3', 'Opteron_G3'],
> 

applied, thanks

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] applied: [PATCH v2 ha-manager 01/12] Make parameters for LRM resource commands more flexible

2019-09-30 Thread Thomas Lamprecht
On 9/30/19 9:22 AM, Fabian Ebner wrote:
> This will allow for new parameters beside 'target' to be used.
> This is in preparation to allow for a 'timeout' parameter for a new 'stop' 
> command.
> 
> Signed-off-by: Fabian Ebner 
> ---
>  src/PVE/HA/LRM.pm | 14 +++---
>  1 file changed, 7 insertions(+), 7 deletions(-)
> 

applied, thanks!

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


Re: [pve-devel] [PATCH v2 ha-manager 02/12] Move code updating resource config from API2::HA::Resources to HA::Config

2019-09-30 Thread Thomas Lamprecht
On 9/30/19 9:22 AM, Fabian Ebner wrote:
> This makes it easier to update the resource configuration from within the 
> CRM/LRM stack,
> which is needed for the new 'stop' command.
> 
> Signed-off-by: Fabian Ebner 
> ---
>  src/PVE/API2/HA/Resources.pm | 34 +
>  src/PVE/HA/Config.pm | 37 
>  2 files changed, 38 insertions(+), 33 deletions(-)
> 
> diff --git a/src/PVE/API2/HA/Resources.pm b/src/PVE/API2/HA/Resources.pm
> index 22d7f28..2b62ee8 100644
> --- a/src/PVE/API2/HA/Resources.pm
> +++ b/src/PVE/API2/HA/Resources.pm
> @@ -237,39 +237,7 @@ __PACKAGE__->register_method ({
>  
>   check_service_state($sid, $param->{state});
>  
> - PVE::HA::Config::lock_ha_domain(
> - sub {
> -
> - my $cfg = PVE::HA::Config::read_resources_config();
> -
> - PVE::SectionConfig::assert_if_modified($cfg, $digest);
> -
> - my $scfg = $cfg->{ids}->{$sid} ||
> - die "no such resource '$sid'\n";
> -
> - my $plugin = PVE::HA::Resources->lookup($scfg->{type});
> - my $opts = $plugin->check_config($sid, $param, 0, 1);
> -
> - foreach my $k (%$opts) {
> - $scfg->{$k} = $opts->{$k};
> - }
> -
> - if ($delete) {
> - my $options = $plugin->private()->{options}->{$type};
> - foreach my $k (PVE::Tools::split_list($delete)) {
> - my $d = $options->{$k} ||
> - die "no such option '$k'\n";
> - die "unable to delete required option '$k'\n"
> - if !$d->{optional};
> - die "unable to delete fixed option '$k'\n"
> - if $d->{fixed};
> - delete $scfg->{$k};
> - }
> - }
> -
> - PVE::HA::Config::write_resources_config($cfg)
> -
> - }, "update resource failed");
> + PVE::HA::Config::update_resources_config($digest, $delete, $sid, 
> $param);
>  
>   return undef;
>  }});
> diff --git a/src/PVE/HA/Config.pm b/src/PVE/HA/Config.pm
> index ead1ee2..e800154 100644
> --- a/src/PVE/HA/Config.pm
> +++ b/src/PVE/HA/Config.pm
> @@ -125,6 +125,43 @@ sub read_and_check_resources_config {
>  return $conf;
>  }
>  
> +sub update_resources_config {
> +my ($digest, $delete, $sid, $param) = @_;

Hmm, I do not like the order of arguments, IMO it's better to have
optional and less likely ones at the end, so that they can just
be omitted allowing to write
foo("bar");
vs-
foo(undef, undef, "bar");

I'd propose
my ($sid, $param, $delete, $digest) = @_;

The $digest is only for the API, the CRM does not cares as it just
enforces a state from a locked context and does no "read-change-update"
cycle where other changes from other API users could be overwritten.

$delete is also something the API will rather use, in your in-service
usage of this method you have both set to "0" anyway.

Sorry, this could've been said on v1 already, missed it.

> +
> +lock_ha_domain(
> + sub {
> + my $cfg = read_resources_config();
> + ($sid, my $type, my $name) = parse_sid($sid);
> +
> + PVE::SectionConfig::assert_if_modified($cfg, $digest);
> +
> + my $scfg = $cfg->{ids}->{$sid} ||
> + die "no such resource '$sid'\n";
> +
> + my $plugin = PVE::HA::Resources->lookup($scfg->{type});
> + my $opts = $plugin->check_config($sid, $param, 0, 1);
> +
> + foreach my $k (%$opts) {
> + $scfg->{$k} = $opts->{$k};
> + }
> +
> + if ($delete) {
> + my $options = $plugin->private()->{options}->{$type};
> + foreach my $k (PVE::Tools::split_list($delete)) {
> + my $d = $options->{$k} ||
> + die "no such option '$k'\n";
> + die "unable to delete required option '$k'\n"
> + if !$d->{optional};
> + die "unable to delete fixed option '$k'\n"
> + if $d->{fixed};
> + delete $scfg->{$k};
> + }
> + }
> +
> + write_resources_config($cfg);
> + }, "update resources config failed");
> +}
> +
>  sub parse_sid {
>  my ($sid) = @_;
>  
> 


___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


Re: [pve-devel] [PATCH v2 ha-manager 03/12] Add update_service_config to HA environment interface

2019-09-30 Thread Thomas Lamprecht
On 9/30/19 9:22 AM, Fabian Ebner wrote:
> Signed-off-by: Fabian Ebner 
> ---
>  src/PVE/HA/Env.pm  | 6 ++
>  src/PVE/HA/Env/PVE2.pm | 6 ++
>  src/PVE/HA/Sim/Env.pm  | 6 ++
>  3 files changed, 18 insertions(+)
> 
> diff --git a/src/PVE/HA/Env.pm b/src/PVE/HA/Env.pm
> index bb37486..7acd7c5 100644
> --- a/src/PVE/HA/Env.pm
> +++ b/src/PVE/HA/Env.pm
> @@ -87,6 +87,12 @@ sub read_service_config {
>  return $self->{plug}->read_service_config();
>  }
>  
> +sub update_service_config {
> +my ($self, $digest, $delete, $sid, $param) = @_;

see reply to patch 02/12 regarding parameter order; here I'd even
omit $digest completely, it cannot really matter here anyway, or?

> +
> +return $self->{plug}->update_service_config($digest, $delete, $sid, 
> $param);
> +}
> +
>  sub parse_sid {
>  my ($self, $sid) = @_;
>  
> diff --git a/src/PVE/HA/Env/PVE2.pm b/src/PVE/HA/Env/PVE2.pm
> index 796acd9..1e92687 100644
> --- a/src/PVE/HA/Env/PVE2.pm
> +++ b/src/PVE/HA/Env/PVE2.pm
> @@ -120,6 +120,12 @@ sub read_service_config {
>  return PVE::HA::Config::read_and_check_resources_config();
>  }
>  
> +sub update_service_config {
> +my ($self, $digest, $delete, $sid, $param) = @_;
> +
> +return PVE::HA::Config::update_resources_config($digest, $delete, $sid, 
> $param);
> +}
> +
>  sub parse_sid {
>  my ($self, $sid) = @_;
>  
> diff --git a/src/PVE/HA/Sim/Env.pm b/src/PVE/HA/Sim/Env.pm
> index 22e13e6..f400365 100644
> --- a/src/PVE/HA/Sim/Env.pm
> +++ b/src/PVE/HA/Sim/Env.pm
> @@ -203,6 +203,12 @@ sub read_service_config {
>  return $self->{hardware}->read_service_config();
>  }
>  
> +sub update_service_config {
> +my ($self, $digest, $delete, $sid, $param) = @_;
> +
> +return $self->{hardware}->update_service_config($digest, $delete, $sid, 
> $param);
> +}
> +
>  sub parse_sid {
>  my ($self, $sid) = @_;
>  
> 


___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


Re: [pve-devel] [PATCH v2 ha-manager 04/12] Implement update_service_config for simulation

2019-09-30 Thread Thomas Lamprecht
On 9/30/19 9:22 AM, Fabian Ebner wrote:
> Signed-off-by: Fabian Ebner 
> ---
>  src/PVE/HA/Sim/Hardware.pm | 16 
>  1 file changed, 16 insertions(+)
> 
> diff --git a/src/PVE/HA/Sim/Hardware.pm b/src/PVE/HA/Sim/Hardware.pm
> index 8bd5cbd..d2c0ec0 100644
> --- a/src/PVE/HA/Sim/Hardware.pm
> +++ b/src/PVE/HA/Sim/Hardware.pm
> @@ -109,6 +109,22 @@ sub read_service_config {
>  return $conf;
>  }
>  
> +sub update_service_config {
> +my ($self, $digest, $delete, $sid, $param) = @_;
> +
> +die "not implemented" if ($digest || $delete);

and not required if we agree with my points from 02/12 and 03/12 replies :)
(at least the digest one)

> +
> +my $conf = $self->read_service_config();
> +
> +my $sconf = $conf->{$sid} || die "no such resource '$sid'\n";
> +
> +foreach my $k (%$param) {
> + $sconf->{$k} = $param->{$k};
> +}
> +
> +$self->write_service_config($conf);
> +}
> +
>  sub write_service_config {
>  my ($self, $conf) = @_;
>  
> 


___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


Re: [pve-devel] [PATCH v2 ha-manager 06/12] Use timeout for shutdown in LRM

2019-09-30 Thread Thomas Lamprecht
On 9/30/19 9:22 AM, Fabian Ebner wrote:
> Signed-off-by: Fabian Ebner 
> ---
>  src/PVE/HA/LRM.pm | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/src/PVE/HA/LRM.pm b/src/PVE/HA/LRM.pm
> index 3b4a572..e5eee94 100644
> --- a/src/PVE/HA/LRM.pm
> +++ b/src/PVE/HA/LRM.pm
> @@ -535,7 +535,7 @@ sub manage_resources {
>   my $req_state = $sd->{state};
>   next if !defined($req_state);
>   next if $req_state eq 'freeze';
> - $self->queue_resource_command($sid, $sd->{uid}, $req_state, {'target' 
> => $sd->{target}});
> + $self->queue_resource_command($sid, $sd->{uid}, $req_state, {'target' 
> => $sd->{target}, 'timeout' => $sd->{timeout}});
>  }
>  
>  return $self->run_workers();
> @@ -776,7 +776,7 @@ sub exec_resource_agent {
>  
>   $haenv->log("info", "stopping service $sid");
>  
> - $plugin->shutdown($haenv, $id);
> + $plugin->shutdown($haenv, $id, $params->{timeout});
>  
>   $running = $plugin->check_running($haenv, $id);
>  
> 

I'd squash this into 05/12, does not has much use as a standalone patch,
I think 05 + 06 combined are single logical change.

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


Re: [pve-devel] [PATCH v2 ha-manager 07/12] Add stop command to the API

2019-09-30 Thread Thomas Lamprecht
On 9/30/19 9:22 AM, Fabian Ebner wrote:
> Signed-off-by: Fabian Ebner 
> ---
>  src/PVE/API2/HA/Resources.pm | 37 
>  src/PVE/CLI/ha_manager.pm|  2 ++
>  2 files changed, 39 insertions(+)

besides the nit^Wfact that the commit subject should read
"Add stop command to the API and CLI", not sure if this is required?

Couldn't we just have a common helper somewhere and then the
qm stop or pct stop just calls that (indirectly?).

Just need to rethink concepts for this one, code itself looks OK.

> 
> diff --git a/src/PVE/API2/HA/Resources.pm b/src/PVE/API2/HA/Resources.pm
> index 2b62ee8..ecc5f0c 100644
> --- a/src/PVE/API2/HA/Resources.pm
> +++ b/src/PVE/API2/HA/Resources.pm
> @@ -353,4 +353,41 @@ __PACKAGE__->register_method ({
>   return undef;
>  }});
>  
> +__PACKAGE__->register_method ({
> +name => 'stop',
> +protected => 1,
> +path => '{sid}/stop',
> +method => 'POST',
> +description => "Request the service to be stopped.",
> +permissions => {
> + check => ['perm', '/', [ 'Sys.Console' ]],
> +},
> +parameters => {
> + additionalProperties => 0,
> + properties => {
> + sid => get_standard_option('pve-ha-resource-or-vm-id',
> +   { completion => 
> \&PVE::HA::Tools::complete_sid }),
> + timeout => {
> + description => "Timeout in seconds. If set to 0 a hard stop 
> will be performed.",
> + type => 'integer',
> + minimum => 0,
> + optional => 1,
> + },
> + },
> +},
> +returns => { type => 'null' },
> +code => sub {
> + my ($param) = @_;
> +
> + my ($sid, $type, $name) = 
> PVE::HA::Config::parse_sid(extract_param($param, 'sid'));
> +
> + PVE::HA::Config::service_is_ha_managed($sid);
> +
> + check_service_state($sid);
> +
> + PVE::HA::Config::queue_crm_commands("stop $sid $param->{timeout}");
> +
> + return undef;
> +}});
> +
>  1;
> diff --git a/src/PVE/CLI/ha_manager.pm b/src/PVE/CLI/ha_manager.pm
> index 5ce4c30..c9d4e7f 100644
> --- a/src/PVE/CLI/ha_manager.pm
> +++ b/src/PVE/CLI/ha_manager.pm
> @@ -114,6 +114,8 @@ our $cmddef = {
>  migrate => [ "PVE::API2::HA::Resources", 'migrate', ['sid', 'node'] ],
>  relocate => [ "PVE::API2::HA::Resources", 'relocate', ['sid', 'node'] ],
>  
> +stop => [ "PVE::API2::HA::Resources", 'stop', ['sid', 'timeout'] ],
> +
>  };
>  
>  1;
> 


___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] applied: [PATCH v2 ha-manager 08/12] Rename target to param in simulation

2019-09-30 Thread Thomas Lamprecht
On 9/30/19 9:22 AM, Fabian Ebner wrote:
> In preparation to introduce a stop command with a timeout parameter.
> 
> Signed-off-by: Fabian Ebner 
> ---
>  src/PVE/HA/Sim/Hardware.pm | 18 +-
>  1 file changed, 9 insertions(+), 9 deletions(-)
> 

applied

___
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel