* [pve-devel] [PATCH v2 ha-manager 7/7] tests: add test for shutdown policy override
2023-06-20 10:54 [pve-devel] [PATCH-SERIES v2 (ha-)manager] allow node HA shutdown policy override Fiona Ebner
` (5 preceding siblings ...)
2023-06-20 10:54 ` [pve-devel] [PATCH v2 ha-manager 6/7] sim env: add support for datacenter config overrides Fiona Ebner
@ 2023-06-20 10:54 ` Fiona Ebner
2023-06-20 10:54 ` [pve-devel] [PATCH v2 manager 1/2] api: nodes: allow setting HA shutdown policy during shutdown/reboot Fiona Ebner
2023-06-20 10:54 ` [pve-devel] [PATCH v2 manager 2/2] ui: allow specifying shutdown policy during node shutdown/reboot Fiona Ebner
8 siblings, 0 replies; 10+ messages in thread
From: Fiona Ebner @ 2023-06-20 10:54 UTC (permalink / raw)
To: pve-devel
Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
---
No changes in v2.
src/test/test-shutdown-policy-override/README | 3 +
.../test-shutdown-policy-override/cmdlist | 4 ++
.../datacenter.cfg | 10 ++++
.../hardware_status | 5 ++
.../test-shutdown-policy-override/log.expect | 57 +++++++++++++++++++
.../manager_status | 1 +
.../service_config | 6 ++
7 files changed, 86 insertions(+)
create mode 100644 src/test/test-shutdown-policy-override/README
create mode 100644 src/test/test-shutdown-policy-override/cmdlist
create mode 100644 src/test/test-shutdown-policy-override/datacenter.cfg
create mode 100644 src/test/test-shutdown-policy-override/hardware_status
create mode 100644 src/test/test-shutdown-policy-override/log.expect
create mode 100644 src/test/test-shutdown-policy-override/manager_status
create mode 100644 src/test/test-shutdown-policy-override/service_config
diff --git a/src/test/test-shutdown-policy-override/README b/src/test/test-shutdown-policy-override/README
new file mode 100644
index 0000000..b9c71ce
--- /dev/null
+++ b/src/test/test-shutdown-policy-override/README
@@ -0,0 +1,3 @@
+Test shutdown policy override.
+
+Expect that the policy from the override is used.
diff --git a/src/test/test-shutdown-policy-override/cmdlist b/src/test/test-shutdown-policy-override/cmdlist
new file mode 100644
index 0000000..a86b9e2
--- /dev/null
+++ b/src/test/test-shutdown-policy-override/cmdlist
@@ -0,0 +1,4 @@
+[
+ [ "power node1 on", "power node2 on", "power node3 on"],
+ [ "shutdown node3" ]
+]
diff --git a/src/test/test-shutdown-policy-override/datacenter.cfg b/src/test/test-shutdown-policy-override/datacenter.cfg
new file mode 100644
index 0000000..0a188bd
--- /dev/null
+++ b/src/test/test-shutdown-policy-override/datacenter.cfg
@@ -0,0 +1,10 @@
+{
+ "ha": {
+ "shutdown_policy": "migrate"
+ },
+ "local-overrides": {
+ "ha": {
+ "shutdown_policy": "freeze"
+ }
+ }
+}
diff --git a/src/test/test-shutdown-policy-override/hardware_status b/src/test/test-shutdown-policy-override/hardware_status
new file mode 100644
index 0000000..451beb1
--- /dev/null
+++ b/src/test/test-shutdown-policy-override/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-shutdown-policy-override/log.expect b/src/test/test-shutdown-policy-override/log.expect
new file mode 100644
index 0000000..4aecc4f
--- /dev/null
+++ b/src/test/test-shutdown-policy-override/log.expect
@@ -0,0 +1,57 @@
+info 0 hardware: starting simulation
+info 20 cmdlist: execute power node1 on
+info 20 node1/crm: status change startup => wait_for_quorum
+info 20 node1/lrm: status change startup => wait_for_agent_lock
+info 20 cmdlist: execute power node2 on
+info 20 node2/crm: status change startup => wait_for_quorum
+info 20 node2/lrm: status change startup => wait_for_agent_lock
+info 20 cmdlist: execute power node3 on
+info 20 node3/crm: status change startup => wait_for_quorum
+info 20 node3/lrm: status change startup => wait_for_agent_lock
+info 20 node1/crm: got lock 'ha_manager_lock'
+info 20 node1/crm: status change wait_for_quorum => master
+info 20 node1/crm: node 'node1': state changed from 'unknown' => 'online'
+info 20 node1/crm: node 'node2': state changed from 'unknown' => 'online'
+info 20 node1/crm: node 'node3': state changed from 'unknown' => 'online'
+info 20 node1/crm: adding new service 'vm:103' on node 'node3'
+info 20 node1/crm: adding new service 'vm:104' on node 'node3'
+info 20 node1/crm: adding new service 'vm:105' on node 'node3'
+info 20 node1/crm: adding new service 'vm:106' on node 'node3'
+info 20 node1/crm: service 'vm:103': state changed from 'request_start' to 'started' (node = node3)
+info 20 node1/crm: service 'vm:104': state changed from 'request_start' to 'started' (node = node3)
+info 20 node1/crm: service 'vm:105': state changed from 'request_start' to 'started' (node = node3)
+info 20 node1/crm: service 'vm:106': state changed from 'request_start' to 'started' (node = node3)
+info 22 node2/crm: status change wait_for_quorum => slave
+info 24 node3/crm: status change wait_for_quorum => slave
+info 25 node3/lrm: got lock 'ha_agent_node3_lock'
+info 25 node3/lrm: status change wait_for_agent_lock => active
+info 25 node3/lrm: starting service vm:103
+info 25 node3/lrm: service status vm:103 started
+info 25 node3/lrm: starting service vm:104
+info 25 node3/lrm: service status vm:104 started
+info 25 node3/lrm: starting service vm:105
+info 25 node3/lrm: service status vm:105 started
+info 25 node3/lrm: starting service vm:106
+info 25 node3/lrm: service status vm:106 started
+info 120 cmdlist: execute shutdown node3
+info 120 node3/lrm: got shutdown request with shutdown policy 'freeze'
+info 120 node3/lrm: shutdown LRM, stop and freeze all services
+info 120 node1/crm: service 'vm:103': state changed from 'started' to 'freeze'
+info 120 node1/crm: service 'vm:104': state changed from 'started' to 'freeze'
+info 120 node1/crm: service 'vm:105': state changed from 'started' to 'freeze'
+info 120 node1/crm: service 'vm:106': state changed from 'started' to 'freeze'
+info 125 node3/lrm: stopping service vm:103
+info 125 node3/lrm: service status vm:103 stopped
+info 125 node3/lrm: stopping service vm:104
+info 125 node3/lrm: service status vm:104 stopped
+info 125 node3/lrm: stopping service vm:105
+info 125 node3/lrm: service status vm:105 stopped
+info 125 node3/lrm: stopping service vm:106
+info 125 node3/lrm: service status vm:106 stopped
+info 126 node3/lrm: exit (loop end)
+info 126 shutdown: execute crm node3 stop
+info 125 node3/crm: server received shutdown request
+info 145 node3/crm: exit (loop end)
+info 145 shutdown: execute power node3 off
+info 160 node1/crm: node 'node3': state changed from 'online' => 'unknown'
+info 720 hardware: exit simulation - done
diff --git a/src/test/test-shutdown-policy-override/manager_status b/src/test/test-shutdown-policy-override/manager_status
new file mode 100644
index 0000000..0967ef4
--- /dev/null
+++ b/src/test/test-shutdown-policy-override/manager_status
@@ -0,0 +1 @@
+{}
diff --git a/src/test/test-shutdown-policy-override/service_config b/src/test/test-shutdown-policy-override/service_config
new file mode 100644
index 0000000..d6f4fd9
--- /dev/null
+++ b/src/test/test-shutdown-policy-override/service_config
@@ -0,0 +1,6 @@
+{
+ "vm:103": { "node": "node3", "state": "enabled" },
+ "vm:104": { "node": "node3", "state": "enabled" },
+ "vm:105": { "node": "node3", "state": "enabled" },
+ "vm:106": { "node": "node3", "state": "enabled" }
+}
--
2.39.2
^ permalink raw reply [flat|nested] 10+ messages in thread
* [pve-devel] [PATCH v2 manager 1/2] api: nodes: allow setting HA shutdown policy during shutdown/reboot
2023-06-20 10:54 [pve-devel] [PATCH-SERIES v2 (ha-)manager] allow node HA shutdown policy override Fiona Ebner
` (6 preceding siblings ...)
2023-06-20 10:54 ` [pve-devel] [PATCH v2 ha-manager 7/7] tests: add test for shutdown policy override Fiona Ebner
@ 2023-06-20 10:54 ` Fiona Ebner
2023-06-20 10:54 ` [pve-devel] [PATCH v2 manager 2/2] ui: allow specifying shutdown policy during node shutdown/reboot Fiona Ebner
8 siblings, 0 replies; 10+ messages in thread
From: Fiona Ebner @ 2023-06-20 10:54 UTC (permalink / raw)
To: pve-devel
Increases flexibility/user-friendliness.
In the edge case that an override is already present, but the user
doesn't have Sys.Modify privilege, just proceed with the existing
override. Could in principle happen when the requests from a
privileged user with a policy and an unprivileged user without a
policy arrive at the same time.
Suggested-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
---
(Build-)dependency bump for libpve-cluster-perl needed.
Changes in v2:
* Also check for Sys.Modify privilege when parameter is specified.
PVE/API2/Nodes.pm | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/PVE/API2/Nodes.pm b/PVE/API2/Nodes.pm
index 9269694d..b8f0c6ce 100644
--- a/PVE/API2/Nodes.pm
+++ b/PVE/API2/Nodes.pm
@@ -8,7 +8,7 @@ use Digest::SHA;
use Filesys::Df;
use HTTP::Status qw(:constants);
use JSON;
-use POSIX qw(LONG_MAX);
+use POSIX qw(ENOENT LONG_MAX);
use Time::Local qw(timegm_nocheck);
use Socket;
use IO::Socket::SSL;
@@ -544,6 +544,7 @@ __PACKAGE__->register_method({
method => 'POST',
permissions => {
check => ['perm', '/nodes/{node}', [ 'Sys.PowerMgmt' ]],
+ description => "The 'shutdown-policy' parameter additionally requires 'Sys.Modify'.",
},
protected => 1,
description => "Reboot or shutdown a node.",
@@ -557,12 +558,27 @@ __PACKAGE__->register_method({
type => 'string',
enum => [qw(reboot shutdown)],
},
+ 'shutdown-policy' => get_standard_option('pve-ha-shutdown-policy', { optional => 1 }),
},
},
returns => { type => "null" },
code => sub {
my ($param) = @_;
+ my $rpcenv = PVE::RPCEnvironment::get();
+ my $user = $rpcenv->get_user();
+ my $node = $param->{node};
+
+ my $sp_override_fn = '/run/pve-ha-lrm/shutdown-policy.local-override';
+
+ if ($param->{'shutdown-policy'}) {
+ $rpcenv->check($user, "/nodes/$node", ['Sys.Modify']);
+ eval { PVE::Tools::file_set_contents($sp_override_fn, $param->{'shutdown-policy'}); };
+ die "could not write shutdown policy override to $sp_override_fn - $@" if $@;
+ } elsif (-e $sp_override_fn && $rpcenv->check($user, "/nodes/$node", ['Sys.Modify'], 1)) {
+ unlink $sp_override_fn or die "unable to remove $sp_override_fn - $!";
+ }
+
if ($param->{command} eq 'reboot') {
system ("(sleep 2;/sbin/reboot)&");
} elsif ($param->{command} eq 'shutdown') {
--
2.39.2
^ permalink raw reply [flat|nested] 10+ messages in thread
* [pve-devel] [PATCH v2 manager 2/2] ui: allow specifying shutdown policy during node shutdown/reboot
2023-06-20 10:54 [pve-devel] [PATCH-SERIES v2 (ha-)manager] allow node HA shutdown policy override Fiona Ebner
` (7 preceding siblings ...)
2023-06-20 10:54 ` [pve-devel] [PATCH v2 manager 1/2] api: nodes: allow setting HA shutdown policy during shutdown/reboot Fiona Ebner
@ 2023-06-20 10:54 ` Fiona Ebner
8 siblings, 0 replies; 10+ messages in thread
From: Fiona Ebner @ 2023-06-20 10:54 UTC (permalink / raw)
To: pve-devel
Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
---
New in v2, was sent separately before (no changes to that).
Used a new window, because it's small and couldn't find a good
fit with the existing ones. Maybe SafeDestroy, but not in name and
would require a few modifications too.
Not sure about using gettext() for the option names either.
www/manager6/Makefile | 1 +
www/manager6/node/Config.js | 32 +++----
www/manager6/window/NodeShutdown.js | 126 ++++++++++++++++++++++++++++
3 files changed, 139 insertions(+), 20 deletions(-)
create mode 100644 www/manager6/window/NodeShutdown.js
diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index 9b6dd13b..94c8c05e 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -107,6 +107,7 @@ JSSRC= \
window/FirewallLograteEdit.js \
window/LoginWindow.js \
window/Migrate.js \
+ window/NodeShutdown.js \
window/Prune.js \
window/Restore.js \
window/SafeDestroyGuest.js \
diff --git a/www/manager6/node/Config.js b/www/manager6/node/Config.js
index 6ed2172a..7a074879 100644
--- a/www/manager6/node/Config.js
+++ b/www/manager6/node/Config.js
@@ -19,18 +19,6 @@ Ext.define('PVE.node.Config', {
interval: 5000,
});
- var node_command = function(cmd) {
- Proxmox.Utils.API2Request({
- params: { command: cmd },
- url: '/nodes/' + nodename + '/status',
- method: 'POST',
- waitMsgTarget: me,
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- });
- };
-
var actionBtn = Ext.create('Ext.Button', {
text: gettext('Bulk Actions'),
iconCls: 'fa fa-fw fa-ellipsis-v',
@@ -83,24 +71,28 @@ Ext.define('PVE.node.Config', {
}),
});
- let restartBtn = Ext.create('Proxmox.button.Button', {
+ let restartBtn = Ext.create('Ext.button.Button', {
text: gettext('Reboot'),
disabled: !caps.nodes['Sys.PowerMgmt'],
- dangerous: true,
- confirmMsg: Ext.String.format(gettext("Reboot node '{0}'?"), nodename),
handler: function() {
- node_command('reboot');
+ Ext.create('PVE.window.NodeShutdown', {
+ confirmMsg: Ext.String.format(gettext("Reboot node '{0}'?"), nodename),
+ url: '/nodes/' + nodename + '/status',
+ command: 'reboot',
+ }).show();
},
iconCls: 'fa fa-undo',
});
- var shutdownBtn = Ext.create('Proxmox.button.Button', {
+ let shutdownBtn = Ext.create('Ext.button.Button', {
text: gettext('Shutdown'),
disabled: !caps.nodes['Sys.PowerMgmt'],
- dangerous: true,
- confirmMsg: Ext.String.format(gettext("Shutdown node '{0}'?"), nodename),
handler: function() {
- node_command('shutdown');
+ Ext.create('PVE.window.NodeShutdown', {
+ confirmMsg: Ext.String.format(gettext("Shutdown node '{0}'?"), nodename),
+ url: '/nodes/' + nodename + '/status',
+ command: 'shutdown',
+ }).show();
},
iconCls: 'fa fa-power-off',
});
diff --git a/www/manager6/window/NodeShutdown.js b/www/manager6/window/NodeShutdown.js
new file mode 100644
index 00000000..4cdc541c
--- /dev/null
+++ b/www/manager6/window/NodeShutdown.js
@@ -0,0 +1,126 @@
+Ext.define('PVE.window.NodeShutdown', {
+ extend: 'Ext.window.Window',
+ alias: 'widget.pveNodeShutdown',
+ mixins: ['Proxmox.Mixin.CBind'],
+
+ title: gettext('Confirm'),
+ modal: true,
+ buttonAlign: 'center',
+ bodyPadding: 10,
+ width: 450,
+ layout: { type: 'hbox' },
+ defaultFocus: 'nodeShutdownNoButton',
+
+ config: {
+ url: undefined,
+ confirmMsg: undefined,
+ command: undefined,
+ },
+
+ getParams: function() {
+ let me = this;
+ let params = { command: me.getCommand(), };
+
+ let shutdownPolicy = me.lookup('shutdownPolicy').getValue();
+ if (shutdownPolicy && shutdownPolicy !== '__default__') {
+ params['shutdown-policy'] = shutdownPolicy;
+ }
+
+ return params;
+ },
+
+ controller: {
+ xclass: 'Ext.app.ViewController',
+
+ control: {
+ 'button[reference=yesButton]': {
+ click: function() {
+ const view = this.getView();
+ Proxmox.Utils.API2Request({
+ params: view.getParams(),
+ url: view.getUrl(),
+ method: 'POST',
+ waitMsgTarget: view,
+ failure: function(response, opts) {
+ Ext.Msg.alert(gettext('Error'), response.htmlStatus);
+ },
+ success: function(response, options) {
+ view.close();
+ },
+ });
+ },
+ },
+ 'button[reference=noButton]': {
+ click: function() {
+ this.getView().close();
+ },
+ },
+ },
+ },
+
+ buttons: [
+ {
+ xtype: 'proxmoxHelpButton',
+ listeners: {
+ beforerender: () => {
+ Ext.GlobalEvents.fireEvent('proxmoxShowHelp', 'ha_manager_shutdown_policy');
+ },
+ },
+ },
+ '->',
+ {
+ reference: 'yesButton',
+ text: gettext('Yes'),
+ },
+ {
+ id: 'nodeShutdownNoButton',
+ reference: 'noButton',
+ text: gettext('No'),
+ },
+ ],
+
+ items: [
+ {
+ xtype: 'component',
+ cls: [
+ Ext.baseCSSPrefix + 'message-box-icon',
+ Ext.baseCSSPrefix + 'message-box-warning',
+ Ext.baseCSSPrefix + 'dlg-icon',
+ ],
+ },
+ {
+ xtype: 'container',
+ flex: 1,
+ layout: {
+ type: 'vbox',
+ align: 'stretch',
+ },
+ items: [
+ {
+ xtype: 'displayfield',
+ reference: 'messageCmp',
+ cbind: {
+ value: '{confirmMsg}',
+ },
+ },
+ {
+ reference: 'shutdownPolicy',
+ fieldLabel: gettext('HA Shutdown Policy'),
+ labelWidth: 130,
+ xtype: 'proxmoxKVComboBox',
+ comboItems: [
+ [
+ '__default__',
+ Ext.String.format(gettext("Fallback from {0}"), "datacenter.cfg")
+ ],
+ ['migrate', gettext("Migrate")],
+ ['conditional', gettext("Conditional")],
+ ['freeze', gettext("Freeze")],
+ ['failover', gettext("Failover")],
+ ],
+ value: '__default__',
+ },
+ ],
+ },
+ ],
+});
--
2.39.2
^ permalink raw reply [flat|nested] 10+ messages in thread