ui: osd: mon: mds: warn if stop/destroy actions are problematic

Check if stopping of a service (OSD, MON, MDS) will be problematic for
Ceph. The warning still allows the user to proceed.

Ceph also has a check if the destruction of a MON is okay, so let's use
it.

Instead of the common OK button, label it with `Stop OSD` and so forth
to hopefully reduce the "click OK by habit" incidents.

This will not catch it every time as Ceph can need a few moments after a
change to establish its current status. For example, stopping one of 3
MONs and then right away destroying one of the last two running MONs
will most likely not trigger the warning. Doing so after a few seconds
should show the warning though.

Signed-off-by: Aaron Lauterer <a.lauterer@proxmox.com>
This commit is contained in:
Aaron Lauterer 2022-11-17 15:10:02 +01:00 committed by Thomas Lamprecht
parent d9415cc4f7
commit 6242a6009d
2 changed files with 145 additions and 30 deletions

View File

@ -527,23 +527,60 @@ Ext.define('PVE.node.CephOsdTree', {
let me = this;
let vm = this.getViewModel();
let cmd = comp.cmd || comp;
Proxmox.Utils.API2Request({
url: "/nodes/" + vm.get('osdhost') + "/ceph/" + cmd,
params: { service: "osd." + vm.get('osdid') },
waitMsgTarget: me.getView(),
method: 'POST',
success: function(response, options) {
let upid = response.result.data;
let win = Ext.create('Proxmox.window.TaskProgress', {
upid: upid,
taskDone: () => { me.reload(); },
});
win.show();
},
failure: function(response, opts) {
Ext.Msg.alert(gettext('Error'), response.htmlStatus);
},
});
let doRequest = function() {
Proxmox.Utils.API2Request({
url: `/nodes/${vm.get('osdhost')}/ceph/${cmd}`,
params: { service: "osd." + vm.get('osdid') },
waitMsgTarget: me.getView(),
method: 'POST',
success: function(response, options) {
let upid = response.result.data;
let win = Ext.create('Proxmox.window.TaskProgress', {
upid: upid,
taskDone: () => { me.reload(); },
});
win.show();
},
failure: function(response, opts) {
Ext.Msg.alert(gettext('Error'), response.htmlStatus);
},
});
};
if (cmd === "stop") {
Proxmox.Utils.API2Request({
url: `/nodes/${vm.get('osdhost')}/ceph/cmd-safety`,
params: {
service: 'osd',
id: vm.get('osdid'),
action: 'stop',
},
waitMsgTarget: me.getView(),
method: 'GET',
success: function({ result: { data } }) {
if (!data.safe) {
Ext.Msg.show({
title: gettext('Warning'),
message: data.status,
icon: Ext.Msg.WARNING,
buttons: Ext.Msg.OKCANCEL,
buttonText: { ok: gettext('Stop OSD') },
fn: function(selection) {
if (selection === 'ok') {
doRequest();
}
},
});
} else {
doRequest();
}
},
failure: response => Ext.Msg.alert(gettext('Error'), response.htmlStatus),
});
} else {
doRequest();
}
},
set_selection_status: function(tp, selection) {

View File

@ -148,19 +148,57 @@ Ext.define('PVE.node.CephServiceController', {
Ext.Msg.alert(gettext('Error'), "entry has no host");
return;
}
Proxmox.Utils.API2Request({
url: `/nodes/${rec.data.host}/ceph/${cmd}`,
method: 'POST',
params: { service: view.type + '.' + rec.data.name },
success: function(response, options) {
Ext.create('Proxmox.window.TaskProgress', {
autoShow: true,
upid: response.result.data,
taskDone: () => view.rstore.load(),
});
},
failure: (response, _opts) => Ext.Msg.alert(gettext('Error'), response.htmlStatus),
});
let doRequest = function() {
Proxmox.Utils.API2Request({
url: `/nodes/${rec.data.host}/ceph/${cmd}`,
method: 'POST',
params: { service: view.type + '.' + rec.data.name },
success: function(response, options) {
Ext.create('Proxmox.window.TaskProgress', {
autoShow: true,
upid: response.result.data,
taskDone: () => view.rstore.load(),
});
},
failure: (response, _opts) => Ext.Msg.alert(gettext('Error'), response.htmlStatus),
});
};
if (cmd === "stop" && ['mon', 'mds'].includes(view.type)) {
Proxmox.Utils.API2Request({
url: `/nodes/${rec.data.host}/ceph/cmd-safety`,
params: {
service: view.type,
id: rec.data.name,
action: 'stop',
},
method: 'GET',
success: function({ result: { data } }) {
let stopText = {
mon: gettext('Stop MON'),
mds: gettext('Stop MDS'),
};
if (!data.safe) {
Ext.Msg.show({
title: gettext('Warning'),
message: data.status,
icon: Ext.Msg.WARNING,
buttons: Ext.Msg.OKCANCEL,
buttonText: { ok: stopText[view.type] },
fn: function(selection) {
if (selection === 'ok') {
doRequest();
}
},
});
} else {
doRequest();
}
},
failure: (response, _opts) => Ext.Msg.alert(gettext('Error'), response.htmlStatus),
});
} else {
doRequest();
}
},
onChangeService: function(button) {
let me = this;
@ -273,6 +311,46 @@ Ext.define('PVE.node.CephServiceList', {
taskDone: () => view.rstore.load(),
});
},
handler: function(btn, event, rec) {
let me = this;
let view = me.up('grid');
let doRequest = function() {
Proxmox.button.StdRemoveButton.prototype.handler.call(me, btn, event, rec);
};
if (view.type === 'mon') {
Proxmox.Utils.API2Request({
url: `/nodes/${rec.data.host}/ceph/cmd-safety`,
params: {
service: view.type,
id: rec.data.name,
action: 'destroy',
},
method: 'GET',
success: function({ result: { data } }) {
if (!data.safe) {
Ext.Msg.show({
title: gettext('Warning'),
message: data.status,
icon: Ext.Msg.WARNING,
buttons: Ext.Msg.OKCANCEL,
buttonText: { ok: gettext('Destroy MON') },
fn: function(selection) {
if (selection === 'ok') {
doRequest();
}
},
});
} else {
doRequest();
}
},
failure: (response, _opts) => Ext.Msg.alert(gettext('Error'), response.htmlStatus),
});
} else {
doRequest();
}
},
},
'-',
{