From cf1c95354a9db8b81712d7b98d0cc55e777e0516 Mon Sep 17 00:00:00 2001
From: Ondrej Mular <omular@redhat.com>
Date: Thu, 4 Aug 2016 00:59:11 +0200
Subject: [PATCH] web UI: add support for unmanaged resources
---
pcsd/cluster_entity.rb | 13 ++++++++--
pcsd/pcs.rb | 1 +
pcsd/public/js/nodes-ember.js | 22 +++++++++++++----
pcsd/public/js/pcsd.js | 52 ++++++++++++++++++++++++++++++++++++++++
pcsd/remote.rb | 55 +++++++++++++++++++++++++++++++++++++++----
pcsd/views/main.erb | 26 ++++++++++++++++++++
6 files changed, 158 insertions(+), 11 deletions(-)
diff --git a/pcsd/cluster_entity.rb b/pcsd/cluster_entity.rb
index fa56fe2..7216626 100644
--- a/pcsd/cluster_entity.rb
+++ b/pcsd/cluster_entity.rb
@@ -332,7 +332,11 @@ module ClusterEntity
:unknown => {
:val => 6,
:str => 'unknown'
- }
+ },
+ :unmanaged => {
+ :val => 7,
+ :str => 'unmanaged'
+ },
}
def initialize(status=:unknown)
@@ -532,8 +536,11 @@ module ClusterEntity
def get_status
running = 0
failed = 0
+ unmanaged = 0
@crm_status.each do |s|
- if s.active
+ if !s.managed
+ unmanaged += 1
+ elsif s.active
running += 1
elsif s.failed
failed += 1
@@ -542,6 +549,8 @@ module ClusterEntity
if disabled?
status = ClusterEntity::ResourceStatus.new(:disabled)
+ elsif unmanaged >0
+ status = ClusterEntity::ResourceStatus.new(:unmanaged)
elsif running > 0
status = ClusterEntity::ResourceStatus.new(:running)
elsif failed > 0 or @error_list.length > 0
diff --git a/pcsd/pcs.rb b/pcsd/pcs.rb
index 1eb9e9e..553a20c 100644
--- a/pcsd/pcs.rb
+++ b/pcsd/pcs.rb
@@ -1703,6 +1703,7 @@ def get_node_status(auth_user, cib_dom)
'sbd',
'ticket_constraints',
'moving_resource_in_group',
+ 'unmanaged_resource',
]
}
diff --git a/pcsd/public/js/nodes-ember.js b/pcsd/public/js/nodes-ember.js
index 3d4fe79..c51a341 100644
--- a/pcsd/public/js/nodes-ember.js
+++ b/pcsd/public/js/nodes-ember.js
@@ -57,6 +57,9 @@ Pcs = Ember.Application.createWithMixins({
this.get("available_features").indexOf("moving_resource_in_group") != -1
);
}.property("available_features"),
+ is_supported_unmanaged_resource: function() {
+ return (this.get("available_features").indexOf("unmanaged_resource") != -1);
+ }.property("available_features"),
is_sbd_running: false,
is_sbd_enabled: false,
is_sbd_enabled_or_running: function() {
@@ -869,9 +872,17 @@ Pcs.ResourceObj = Ember.Object.extend({
return '<span style="' + this.get('status_style') + '">' + this.get('status') + '</span>';
}.property("status_style", "disabled"),
status_class: function() {
- var show = ((Pcs.clusterController.get("show_all_resources"))? "" : "hidden ");
- return ((this.get("status_val") == get_status_value("ok") || this.status == "disabled") ? show + "default-hidden" : "");
- }.property("status_val"),
+ if (
+ this.get("status_val") == get_status_value("ok") ||
+ ["disabled", "unmanaged"].indexOf(this.get("status")) != -1
+ ) {
+ return (
+ Pcs.clusterController.get("show_all_resources") ? "" : "hidden "
+ ) + "default-hidden";
+ } else {
+ return "";
+ }
+ }.property("status_val", "status"),
status_class_fence: function() {
var show = ((Pcs.clusterController.get("show_all_fence"))? "" : "hidden ");
return ((this.get("status_val") == get_status_value("ok")) ? show + "default-hidden" : "");
@@ -1681,8 +1692,9 @@ Pcs.Cluster = Ember.Object.extend({
var num = 0;
$.each(this.get(type), function(key, value) {
if (value.get("status_val") < get_status_value("ok") &&
- value.status != "disabled" && value.status != "standby" &&
- value.status != "maintenance"
+ [
+ "unmanaged", "disabled", "standby", "maintenance"
+ ].indexOf(value.status) == -1
) {
num++;
}
diff --git a/pcsd/public/js/pcsd.js b/pcsd/public/js/pcsd.js
index 82187ef..56219d4 100644
--- a/pcsd/public/js/pcsd.js
+++ b/pcsd/public/js/pcsd.js
@@ -1333,6 +1333,9 @@ function remove_resource(ids, force) {
message += "\n\n" + xhr.responseText.replace(
"--force", "'Enforce removal'"
);
+ alert(message);
+ $("#verify_remove_submit_btn").button("option", "disabled", false);
+ return;
}
}
alert(message);
@@ -1957,6 +1960,7 @@ function get_status_value(status) {
maintenance: 2,
"partially running": 2,
disabled: 3,
+ unmanaged: 3,
unknown: 4,
ok: 5,
running: 5,
@@ -2987,3 +2991,51 @@ function sbd_status_dialog() {
buttons: buttonsOpts
});
}
+
+function unmanage_resource(resource_id) {
+ if (!resource_id) {
+ return;
+ }
+ fade_in_out("#resource_unmanage_link");
+ ajax_wrapper({
+ type: 'POST',
+ url: get_cluster_remote_url() + "unmanage_resource",
+ data: {
+ resource_list_json: JSON.stringify([resource_id]),
+ },
+ timeout: pcs_timeout,
+ complete: function() {
+ Pcs.update();
+ },
+ error: function (xhr, status, error) {
+ alert(
+ `Unable to unmanage '${resource_id}': ` +
+ ajax_simple_error(xhr, status, error)
+ );
+ },
+ });
+}
+
+function manage_resource(resource_id) {
+ if (!resource_id) {
+ return;
+ }
+ fade_in_out("#resource_manage_link");
+ ajax_wrapper({
+ type: 'POST',
+ url: get_cluster_remote_url() + "manage_resource",
+ data: {
+ resource_list_json: JSON.stringify([resource_id]),
+ },
+ timeout: pcs_timeout,
+ complete: function() {
+ Pcs.update();
+ },
+ error: function (xhr, status, error) {
+ alert(
+ `Unable to manage '${resource_id}': ` +
+ ajax_simple_error(xhr, status, error)
+ );
+ }
+ });
+}
diff --git a/pcsd/remote.rb b/pcsd/remote.rb
index 4844adf..ebf425c 100644
--- a/pcsd/remote.rb
+++ b/pcsd/remote.rb
@@ -116,7 +116,9 @@ def remote(params, request, auth_user)
:set_resource_utilization => method(:set_resource_utilization),
:set_node_utilization => method(:set_node_utilization),
:get_resource_agent_metadata => method(:get_resource_agent_metadata),
- :get_fence_agent_metadata => method(:get_fence_agent_metadata)
+ :get_fence_agent_metadata => method(:get_fence_agent_metadata),
+ :manage_resource => method(:manage_resource),
+ :unmanage_resource => method(:unmanage_resource),
}
command = params[:command].to_sym
@@ -1575,10 +1577,10 @@ def remove_resource(params, request, auth_user)
end
cmd = [PCS, '-f', tmp_file.path, 'resource', 'disable']
resource_list.each { |resource|
- _, err, retval = run_cmd(user, *(cmd + [resource]))
+ out, err, retval = run_cmd(user, *(cmd + [resource]))
if retval != 0
unless (
- err.join('').index('unable to find a resource') != -1 and
+ (out + err).join('').include?(' does not exist.') and
no_error_if_not_exists
)
errors += "Unable to stop resource '#{resource}': #{err.join('')}"
@@ -1613,7 +1615,10 @@ def remove_resource(params, request, auth_user)
end
out, err, retval = run_cmd(auth_user, *cmd)
if retval != 0
- unless out.index(' does not exist.') != -1 and no_error_if_not_exists
+ unless (
+ (out + err).join('').include?(' does not exist.') and
+ no_error_if_not_exists
+ )
errors += err.join(' ').strip + "\n"
end
end
@@ -2630,3 +2635,45 @@ def qdevice_client_start(param, request, auth_user)
return [400, msg]
end
end
+
+def manage_resource(param, request, auth_user)
+ unless allowed_for_local_cluster(auth_user, Permissions::WRITE)
+ return 403, 'Permission denied'
+ end
+ unless param[:resource_list_json]
+ return [400, "Required parameter 'resource_list_json' is missing."]
+ end
+ begin
+ resource_list = JSON.parse(param[:resource_list_json])
+ _, err, retval = run_cmd(
+ auth_user, PCS, 'resource', 'manage', *resource_list
+ )
+ if retval != 0
+ return [400, err.join('')]
+ end
+ return [200, '']
+ rescue JSON::ParserError
+ return [400, 'Invalid input data format']
+ end
+end
+
+def unmanage_resource(param, request, auth_user)
+ unless allowed_for_local_cluster(auth_user, Permissions::WRITE)
+ return 403, 'Permission denied'
+ end
+ unless param[:resource_list_json]
+ return [400, "Required parameter 'resource_list_json' is missing."]
+ end
+ begin
+ resource_list = JSON.parse(param[:resource_list_json])
+ _, err, retval = run_cmd(
+ auth_user, PCS, 'resource', 'unmanage', *resource_list
+ )
+ if retval != 0
+ return [400, err.join('')]
+ end
+ return [200, '']
+ rescue JSON::ParserError
+ return [400, 'Invalid input data format']
+ end
+end
diff --git a/pcsd/views/main.erb b/pcsd/views/main.erb
index 1b21f92..64fe560 100644
--- a/pcsd/views/main.erb
+++ b/pcsd/views/main.erb
@@ -160,6 +160,7 @@
</table>
</div>
<div id="node_options_buttons">
+ <div>
{{#if resource.stonith}}
<div class="xdark sprites" style="float: left"></div>
<div id="stonith_delete_link" class="link" onclick="verify_remove_fence_devices(curStonith());">Remove</div>
@@ -174,7 +175,32 @@
<div id="resource_cleanup_link" class="link" onclick="cleanup_resource();">Cleanup</div>
<div class="xdark sprites" style="float: left"></div>
<div id="resource_delete_link" class="link" onclick="verify_remove_resources(curResource());">Remove</div>
+ </div>
+ <div>
+ {{#if Pcs.is_supported_unmanaged_resource}}
+ <div>
+ <div class="checkdark sprites" style="float: left"></div>
+ <div
+ id="resource_manage_link"
+ class="link"
+ onclick="manage_resource(curResource());"
+ >
+ Manage
+ </div>
+ </div>
+ <div>
+ <div class="cancel sprites" style="float: left"></div>
+ <div
+ id="resource_unmanage_link"
+ class="link"
+ onclick="unmanage_resource(curResource());"
+ >
+ Unmanage
+ </div>
+ </div>
+ {{/if}}
{{/if}}
+ </div>
<!--
<div class="move sprites" style="float: left"></div>
<div id="resource_move_link" class="link">Move</div>
--
1.8.3.1