From cf1c95354a9db8b81712d7b98d0cc55e777e0516 Mon Sep 17 00:00:00 2001 From: Ondrej Mular 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 '' + this.get('status') + ''; }.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 @@
+
{{#if resource.stonith}}
@@ -174,7 +175,32 @@
+
+
+ {{#if Pcs.is_supported_unmanaged_resource}} +
+
+ +
+
+
+ +
+ {{/if}} {{/if}} +