blob: d269393e5c077c337f62cc35033d717b9e3b67d9 [file] [log] [blame]
Alex Savatieiev9b2f6512019-02-20 18:05:00 -06001import json
2import os
3import sys
4
5from copy import deepcopy
6
7from cfg_checker.common import utils, const
8from cfg_checker.common import config, logger, logger_cli, pkg_dir
9from cfg_checker.common import salt_utils
10
11node_tmpl = {
12 'role': '',
13 'node_group': '',
14 'status': const.NODE_DOWN,
15 'pillars': {},
16 'grains': {}
17}
18
19
20class SaltNodes(object):
21 def __init__(self):
Alex Savatieieve9613992019-02-21 18:20:35 -060022 logger_cli.info("### Collecting nodes")
Alex Savatieiev9b2f6512019-02-20 18:05:00 -060023 # simple salt rest client
24 self.salt = salt_utils.SaltRemote()
25
26 # Keys for all nodes
27 # this is not working in scope of 2016.8.3, will overide with list
Alex Savatieiev9df93a92019-02-27 17:40:16 -060028 logger_cli.info("# Collecting node names existing in the cloud")
29 try:
30 _keys = self.salt.list_keys()
31 _str = []
32 for _k, _v in _keys.iteritems():
33 _str.append("{}: {}".format(_k, len(_v)))
34 logger_cli.info("-> keys collected: {}".format(", ".join(_str)))
Alex Savatieiev9b2f6512019-02-20 18:05:00 -060035
Alex Savatieiev9df93a92019-02-27 17:40:16 -060036 self.node_keys = {
37 'minions': _keys['minions']
38 }
39 except Exception as e:
40 _keys = None
41 self.node_keys = None
42
43 # List of minions with grains
44 _minions = self.salt.list_minions()
45 if _minions:
46 logger_cli.info("-> api reported {} active minions".format(len(_minions)))
47 elif not self.node_keys:
48 # this is the last resort
49 _minions = config.load_nodes_list()
50 logger_cli.info("-> {} nodes loaded from list file".format(len(_minions)))
51 else:
52 _minions = self.node_keys['minions']
Alex Savatieiev9b2f6512019-02-20 18:05:00 -060053
Alex Savatieiev9df93a92019-02-27 17:40:16 -060054 # in case API not listed minions, we need all that answer ping
Alex Savatieiev9b2f6512019-02-20 18:05:00 -060055 _active = self.salt.get_active_nodes()
Alex Savatieiev9df93a92019-02-27 17:40:16 -060056 logger_cli.info("-> nodes responded: {}".format(len(_active)))
Alex Savatieiev9b2f6512019-02-20 18:05:00 -060057 # just inventory for faster interaction
58 # iterate through all accepted nodes and create a dict for it
59 self.nodes = {}
Alex Savatieiev9df93a92019-02-27 17:40:16 -060060 for _name in _minions:
Alex Savatieiev9b2f6512019-02-20 18:05:00 -060061 _nc = utils.get_node_code(_name)
62 _rmap = const.all_roles_map
63 _role = _rmap[_nc] if _nc in _rmap else 'unknown'
64 _status = const.NODE_UP if _name in _active else const.NODE_DOWN
65
66 self.nodes[_name] = deepcopy(node_tmpl)
67 self.nodes[_name]['node_group'] = _nc
68 self.nodes[_name]['role'] = _role
69 self.nodes[_name]['status'] = _status
70
71 logger_cli.info("-> {} nodes collected".format(len(self.nodes)))
72
73 def get_nodes(self):
74 return self.nodes
75
76 def execute_script(self, script_filename, args=[]):
77 # form an all nodes compound string to use in salt
78 _active_nodes_string = self.salt.compound_string_from_list(
79 filter(
80 lambda nd: self.nodes[nd]['status'] == const.NODE_UP,
81 self.nodes
82 )
83 )
84 # Prepare script
85 _p = os.path.join(pkg_dir, 'scripts', script_filename)
86 with open(_p, 'rt') as fd:
87 _script = fd.read().splitlines()
88 _storage_path = os.path.join(
89 config.salt_file_root, config.salt_scripts_folder
90 )
91 logger_cli.debug(
92 "# Uploading script {} to master's file cache folder: '{}'".format(
93 script_filename,
94 _storage_path
95 )
96 )
97 _result = self.salt.mkdir("cfg01*", _storage_path)
98 # Form cache, source and target path
99 _cache_path = os.path.join(_storage_path, script_filename)
100 _source_path = os.path.join(
101 'salt://',
102 config.salt_scripts_folder,
103 script_filename
104 )
105 _target_path = os.path.join(
106 '/root',
107 config.salt_scripts_folder,
108 script_filename
109 )
110
111 logger_cli.debug("# Creating file in cache '{}'".format(_cache_path))
112 _result = self.salt.f_touch_master(_cache_path)
113 _result = self.salt.f_append_master(_cache_path, _script)
114 # command salt to copy file to minions
115 logger_cli.debug("# Creating script target folder '{}'".format(_cache_path))
116 _result = self.salt.mkdir(
117 _active_nodes_string,
118 os.path.join(
119 '/root',
120 config.salt_scripts_folder
121 ),
122 tgt_type="compound"
123 )
124 logger_cli.info("-> Running script to all active nodes")
125 _result = self.salt.get_file(
126 _active_nodes_string,
127 _source_path,
128 _target_path,
129 tgt_type="compound"
130 )
131 # execute pkg collecting script
132 logger.debug("Running script to all nodes")
133 # handle results for each node
134 _script_arguments = " ".join(args) if args else ""
135 _result = self.salt.cmd(
136 _active_nodes_string,
137 'cmd.run',
138 param='python {} {}'.format(_target_path, _script_arguments),
139 expr_form="compound"
140 )
141
142 # TODO: Handle error result
143
144 return _result