Skip to content

Commit

Permalink
Merge pull request #278 from aleksei-burlakov/update-option-box-in-cr…
Browse files Browse the repository at this point in the history
…m-configuration

Update the drop-down options boxes in the Cluster Configuration
  • Loading branch information
aleksei-burlakov committed May 14, 2024
2 parents f9838ba + d339d14 commit a8881f4
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 20 deletions.
78 changes: 71 additions & 7 deletions e2e_test/hawk_test_driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ class Xpath:
HREF_CONFIGURATION = '//a[contains(@href, "#configurationMenu")]'
HREF_CONFIG_EDIT = '//a[contains(@href, "config/edit")]'
HREF_CRM_CONFIG_EDIT = '//a[contains(@href, "crm_config/edit")]'
HREF_CRM_CONFIG_FENCE_REACTION = '//option[contains(@value, "fence-reaction")]'
HREF_CRM_CONFIG_NO_QUORUM_POLICY = '//option[contains(@value, "no-quorum-policy")]'
HREF_CRM_CONFIG_STONITH_ACTION = '//option[contains(@value, "stonith-action")]'
HREF_CRM_CONFIG_NODE_HEALTH_STRATEGY = '//option[contains(@value, "node-health-strategy")]'
HREF_CRM_CONFIG_NODE_PLACEMENT_STRATEGY = '//option[contains(@value, "placement-strategy")]'
HREF_CONSTRAINTS = '//a[contains(@href, "#constraints")]'
HREF_DASHBOARD = '//a[contains(@href, "/dashboard")]'
HREF_DELETE_FORMAT = '//a[contains(@href, "{}") and contains(@title, "Delete")]'
Expand Down Expand Up @@ -77,7 +82,7 @@ class Xpath:
class LongLiterals:
RSC_DEFAULT_ATTRIBUTES='allow-migrate\ndescription\nfailure-timeout\nis-managed\nmaintenance\nmigration-threshold\nmultiple-active\n\
priority\nremote-addr\nremote-connect-timeout\nremote-node\nremote-port\nrequires\nresource-stickiness\nrestart-type\ntarget-role'
OP_DEFAULT_ATTRIBUTES='description\nenabled\ninterval\ninterval-origin\non-fail\nrequires\nrole\nstart-delay'
OP_DEFAULT_ATTRIBUTES='timeout\nrecord-pending\ndescription\nenabled\ninterval\ninterval-origin\non-fail\nrequires\nrole\nstart-delay'
CRM_CONFIG_ATTRIBUTES='batch-limit\ncluster-delay\ncluster-ipc-limit\ncluster-name\ncluster-recheck-interval\nconcurrent-fencing\n\
dc-deadtime\nenable-acl\nenable-startup-probes\nfence-reaction\nload-threshold\nmaintenance-mode\nmigration-limit\nno-quorum-policy\n\
node-action-limit\nnode-health-base\nnode-health-green\nnode-health-red\nnode-health-strategy\nnode-health-yellow\nnode-pending-timeout\n\
Expand Down Expand Up @@ -551,30 +556,55 @@ def test_add_group(self, group):
return False

def test_check_cluster_configuration(self, ssh):
"""
The test does two things.
First, it checks that the available resources are correct.
Second, that the options of select-type resources are correct.
The test doesn't create those resources.
"""
print(f"TEST: test_check_cluster_configuration: Check crm options")
self.click_if_major_version("15", 'configuration')
self.check_and_click_by_xpath("Click on Cluster Configuration", [Xpath.HREF_CRM_CONFIG_EDIT])

### 1.
# The rsc_defaults and op_defaults are hardcoded in app/models/tableless.rb
elem = self.find_element(By.NAME, 'temp_crm_config[rsc_defaults]')
if not elem:
print(f"ERROR: Couldn't find element temp_crm_config[rsc_defaults]")
return False
if elem.text != LongLiterals.RSC_DEFAULT_ATTRIBUTES:
print(f"ERROR: temp_crm_config[rsc_defaults] has WRONG values")
lst = elem.text.split('\n')
for a in ['migration-threshold']:
if a not in lst:
lst.append(a)
lst.sort()
lst2 = LongLiterals.RSC_DEFAULT_ATTRIBUTES.split('\n')
lst2.sort()
if lst != lst2:
print(f"ERROR: temp_crm_config[rsc_defaults] has WRONG values.")
print(f" Expected: {lst}")
print(f" Exist: {lst2}")
return False

elem = self.find_element(By.NAME, 'temp_crm_config[op_defaults]')
if not elem:
print(f"ERROR: Couldn't find element temp_crm_config[op_defaults]")
return False
if elem.text != LongLiterals.OP_DEFAULT_ATTRIBUTES:
lst = elem.text.split('\n')
for a in ['timeout', 'record-pending']:
if a not in lst:
lst.append(a)
lst.sort()
lst2 = LongLiterals.OP_DEFAULT_ATTRIBUTES.split('\n')
lst2.sort()
if lst != lst2:
print(f"ERROR: temp_crm_config[op_defaults] has WRONG values")
print(f" Expected: {lst}")
print(f" Exist: {lst2}")
return False

# The crm_config is trickier. We should get those attribute from the crm_attribute
# in the newer versions of pacemaker.If it's an older version of pacemaker
# let's simply compare with a literal.
# The crm_config is trickier. We should get those attributes from the crm_attribute
# in the newer versions of pacemaker. If it's an older version of pacemaker
# let's simply compare it against LongLiterals.CRM_CONFIG_ATTRIBUTES.
elem = self.find_element(By.NAME, 'temp_crm_config[crm_config]')
if not elem:
print(f"ERROR: Couldn't find element temp_crm_config[crm_config]")
Expand All @@ -597,6 +627,40 @@ def test_check_cluster_configuration(self, ssh):
if a not in LongLiterals.CRM_CONFIG_ATTRIBUTES:
print(f'ERROR: {Error.CRM_CONFIG_ADVANCED_ATTRIBUTES}, attr: {a}')
return False
print(f"INFO: Available resources are correct")

### 2.
# Show out all but fence-reaction select-type resources
# (fence-reaction is a string the pacemaker-controld
# and a select in the crm_attribute. Let's not overengineer.)
elem.click()
for xref in [Xpath.HREF_CRM_CONFIG_NO_QUORUM_POLICY,
Xpath.HREF_CRM_CONFIG_STONITH_ACTION,
Xpath.HREF_CRM_CONFIG_NODE_HEALTH_STRATEGY,
Xpath.HREF_CRM_CONFIG_NODE_PLACEMENT_STRATEGY]:
self.check_and_click_by_xpath(f'Couldn\'t find {xref} resource in the drop-down list',
[xref])
time.sleep(1)

# ["<resource name>", ["<option1>", "<option2>,..."]]
for check_options in [ ["no-quorum-policy", ["stop", "freeze", "ignore", "demote", "suicide"]],
["stonith-action", ["reboot", "off", "poweroff"]],
["node-health-strategy", ["none", "migrate-on-red", "only-green", "progressive", "custom"]],
["placement-strategy", ["default", "utilization", "minimal", "balanced"]]]:
elem = self.find_element(By.NAME, f'crm_config[crm_config][{check_options[0]}]')
if not elem:
print(f'ERROR: Couldn\'t find {check_options[0]}')
return False

lst = elem.text.split('\n')
lst.sort()
check_options[1].sort()
if lst != check_options[1]:
print(f'ERROR: {check_options[0]} has WRONG options.')
print(f" Expected: {lst}")
print(f" Exist: {check_options[1]}")
return False
print(f"INFO: Resource options are correct")

time.sleep(self.timeout_scale)
return self.test_status
Expand Down
2 changes: 1 addition & 1 deletion hawk/app/assets/javascripts/module/attrlist.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@

'<div class="col-sm-7">',
'<div class="input-group">',
'{^{if ~root.mapping[key]["type"] == "enum"}}',
'{^{if (~root.mapping[key]["type"] == "enum" || ~root.mapping[key]["type"] == "select" )}}',
'<select class="form-control select" name="{{>~root.prefix}}[{{>key}}]" id="{{>key}}" data-link="prop">',
'<option></option>',
'{^{for ~root.mapping[key]["values"]}}',
Expand Down
34 changes: 22 additions & 12 deletions hawk/app/models/crm_config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,28 +62,38 @@ def get_parameters_from(crm_config, cmd)
type = content.attributes["type"]
default = content.attributes["default"]

advanced = param.attributes["advanced"] || shortdesc.match(/advanced use only/i) || longdesc.match(/advanced use only/i)
advanced = false
advanced = true if param.attributes["advanced"] && (param.attributes["advanced"]=="1")
advanced = true if shortdesc.match(/advanced use only/i) || longdesc.match(/advanced use only/i)

crm_config[name] = {
type: content.attributes["type"],
readonly: false,
shortdesc: shortdesc,
longdesc: longdesc,
advanced: (advanced and (advanced=="1")) ? true : false,
advanced: advanced,
default: default
}

if type == "enum"
match = longdesc.match(/Allowed values:(.*)/i)
if type == "enum" or type == "select"

if match
values = match[1].split(",").map do |value|
value.strip
end.reject do |value|
value.empty?
end
# First try to get options from the content section
crm_config[name][:values] = []
content.each_element("option") do |opt|
crm_config[name][:values] << opt.attributes["value"]
end

crm_config[name][:values] = values unless values.empty?
# If didn't find then try to get them from the long description
if crm_config[name][:values].empty?
match = longdesc.match(/Allowed values:(.*)/i)
if match
values = match[1].split(",").map do |value|
value.strip
end.reject do |value|
value.empty?
end
crm_config[name][:values] = values unless values.empty?
end
end
end
end
Expand Down Expand Up @@ -201,7 +211,7 @@ def persist!
new_value, old_value = change

if new_value.nil? || new_value.empty?
Invoker.instance.run("crm_attribute", "--attr-name", key, "--delete-attr")
Invoker.instance.run("crm_attribute", "--attr-name", key, "--delete-attr", key)
else
writer[:crm_config][key] = new_value
end
Expand Down

0 comments on commit a8881f4

Please sign in to comment.