[CVP] Refactor salt client class
Change-Id: I91cfffe1c8d5df0224657ce9e36be9063b56f0b3
Related-PROD: PROD-28981
Related-PROD: PROD-28729
Related-PROD: PROD-28624
Related-PROD: PROD-29286
diff --git a/test_set/cvp-sanity/utils/__init__.py b/test_set/cvp-sanity/utils/__init__.py
index aeb4cd8..62ccae7 100644
--- a/test_set/cvp-sanity/utils/__init__.py
+++ b/test_set/cvp-sanity/utils/__init__.py
@@ -3,6 +3,7 @@
import requests
import re
import sys, traceback
+import time
class AuthenticationError(Exception):
@@ -10,46 +11,100 @@
class salt_remote:
- def cmd(self, tgt, fun, param=None, expr_form=None, tgt_type=None):
- config = get_configuration()
- url = config['SALT_URL'].strip()
- if not re.match("^(http|https)://", url):
+ def __init__(self):
+ self.config = get_configuration()
+ self.skipped_nodes = self.config.get('skipped_nodes') or []
+ self.url = self.config['SALT_URL'].strip()
+ if not re.match("^(http|https)://", self.url):
raise AuthenticationError("Salt URL should start \
with http or https, given - {}".format(url))
- proxies = {"http": None, "https": None}
- headers = {'Accept': 'application/json'}
- login_payload = {'username': config['SALT_USERNAME'],
- 'password': config['SALT_PASSWORD'], 'eauth': 'pam'}
- accept_key_payload = {'fun': fun, 'tgt': tgt, 'client': 'local',
- 'expr_form': expr_form, 'tgt_type': tgt_type,
- 'timeout': config['salt_timeout']}
- if param:
- accept_key_payload['arg'] = param
+ self.login_payload = {'username': self.config['SALT_USERNAME'],
+ 'password': self.config['SALT_PASSWORD'], 'eauth': 'pam'}
+ # TODO: proxies
+ self.proxies = {"http": None, "https": None}
+ self.expires = ''
+ self.cookies = []
+ self.headers = {'Accept': 'application/json'}
+ self._login()
+ def _login (self):
try:
- login_request = requests.post(os.path.join(url, 'login'),
- headers=headers, data=login_payload,
- proxies=proxies)
+ login_request = requests.post(os.path.join(self.url, 'login'),
+ headers={'Accept': 'application/json'},
+ data=self.login_payload,
+ proxies=self.proxies)
if not login_request.ok:
raise AuthenticationError("Authentication to SaltMaster failed")
-
- request = requests.post(url, headers=headers,
- data=accept_key_payload,
- cookies=login_request.cookies,
- proxies=proxies)
-
- response = request.json()['return'][0]
- return response
-
except Exception as e:
print ("\033[91m\nConnection to SaltMaster "
"was not established.\n"
"Please make sure that you "
"provided correct credentials.\n"
- "Error message: {}\033[0m\n".format(e.message or e)
- )
+ "Error message: {}\033[0m\n".format(e.message or e))
traceback.print_exc(file=sys.stdout)
sys.exit()
+ self.expire = login_request.json()['return'][0]['expire']
+ self.cookies = login_request.cookies
+ self.headers['X-Auth-Token'] = login_request.json()['return'][0]['token']
+
+ def cmd(self, tgt, fun='cmd.run', param=None, expr_form=None, tgt_type=None, check_status=False, retries=3):
+ if self.expire < time.time() + 300:
+ self.headers['X-Auth-Token'] = self._login()
+ accept_key_payload = {'fun': fun, 'tgt': tgt, 'client': 'local',
+ 'expr_form': expr_form, 'tgt_type': tgt_type,
+ 'timeout': self.config['salt_timeout']}
+ if param:
+ accept_key_payload['arg'] = param
+
+ for i in range(retries):
+ request = requests.post(self.url, headers=self.headers,
+ data=accept_key_payload,
+ cookies=self.cookies,
+ proxies=self.proxies)
+ if not request.ok or not isinstance(request.json()['return'][0], dict):
+ print("Salt master is not responding or response is incorrect. Output: {}".format(request))
+ continue
+ response = request.json()['return'][0]
+ result = {key: response[key] for key in response if key not in self.skipped_nodes}
+ if check_status:
+ if False in result.values():
+ print(
+ "One or several nodes are not responding. Output {}".format(json.dumps(result, indent=4)))
+ continue
+ break
+ else:
+ raise Exception("Error with Salt Master response")
+ return result
+
+ def test_ping(self, tgt, expr_form='pillar'):
+ return self.cmd(tgt=tgt, fun='test.ping', param=None, expr_form=expr_form)
+
+ def cmd_any(self, tgt, param=None, expr_form='pillar'):
+ """
+ This method returns first non-empty result on node or nodes.
+ If all nodes returns nothing, then exception is thrown.
+ """
+ response = self.cmd(tgt=tgt, param=param, expr_form=expr_form)
+ for node in response.keys():
+ if response[node] or response[node] == '':
+ return response[node]
+ else:
+ raise Exception("All minions are down")
+
+ def pillar_get(self, tgt='salt:master', param=None, expr_form='pillar', fail_if_empty=False):
+ """
+ This method is for fetching pillars only.
+ Returns value for pillar, False (if no such pillar) or if fail_if_empty=True - exception
+ """
+ response = self.cmd(tgt=tgt, fun='pillar.get', param=param, expr_form=expr_form)
+ for node in response.keys():
+ if response[node] or response[node] != '':
+ return response[node]
+ else:
+ if fail_if_empty:
+ raise Exception("No pillar found or it is empty.")
+ else:
+ return False
def init_salt_client():
@@ -63,43 +118,14 @@
return separator.join(node_list)
-def get_monitoring_ip(param_name):
- local_salt_client = init_salt_client()
- salt_output = local_salt_client.cmd(
- 'salt:master',
- 'pillar.get',
- ['_param:{}'.format(param_name)],
- expr_form='pillar')
- return salt_output[salt_output.keys()[0]]
-
-
-def get_active_nodes(test=None):
- config = get_configuration()
- local_salt_client = init_salt_client()
-
- skipped_nodes = config.get('skipped_nodes') or []
- if test:
- testname = test.split('.')[0]
- if 'skipped_nodes' in config.get(testname).keys():
- skipped_nodes += config.get(testname)['skipped_nodes'] or []
- if skipped_nodes != ['']:
- print "\nNotice: {0} nodes will be skipped".format(skipped_nodes)
- nodes = local_salt_client.cmd(
- '* and not ' + list_to_target_string(skipped_nodes, 'and not'),
- 'test.ping',
- expr_form='compound')
- else:
- nodes = local_salt_client.cmd('*', 'test.ping')
- return nodes
-
-
def calculate_groups():
config = get_configuration()
local_salt_client = init_salt_client()
node_groups = {}
nodes_names = set ()
expr_form = ''
- all_nodes = set(local_salt_client.cmd('*', 'test.ping'))
+ all_nodes = set(local_salt_client.test_ping(tgt='*',expr_form=None))
+ print all_nodes
if 'groups' in config.keys() and 'PB_GROUPS' in os.environ.keys() and \
os.environ['PB_GROUPS'].lower() != 'false':
nodes_names.update(config['groups'].keys())
@@ -113,25 +139,23 @@
nodes_names.add(node)
expr_form = 'pcre'
- gluster_nodes = local_salt_client.cmd('I@salt:control and '
+ gluster_nodes = local_salt_client.test_ping(tgt='I@salt:control and '
'I@glusterfs:server',
- 'test.ping', expr_form='compound')
- kvm_nodes = local_salt_client.cmd('I@salt:control and not '
+ expr_form='compound')
+ kvm_nodes = local_salt_client.test_ping(tgt='I@salt:control and not '
'I@glusterfs:server',
- 'test.ping', expr_form='compound')
+ expr_form='compound')
for node_name in nodes_names:
skipped_groups = config.get('skipped_groups') or []
if node_name in skipped_groups:
continue
if expr_form == 'pcre':
- nodes = local_salt_client.cmd('{}[0-9]{{1,3}}'.format(node_name),
- 'test.ping',
- expr_form=expr_form)
+ nodes = local_salt_client.test_ping(tgt='{}[0-9]{{1,3}}'.format(node_name),
+ expr_form=expr_form)
else:
- nodes = local_salt_client.cmd(config['groups'][node_name],
- 'test.ping',
- expr_form=expr_form)
+ nodes = local_salt_client.test_ping(tgt=config['groups'][node_name],
+ expr_form=expr_form)
if nodes == {}:
continue