blob: b65c74f74a337e76ba0290daa4c2e50095bcdb56 [file] [log] [blame]
Dennis Dmitriev010f4cd2016-11-01 20:43:51 +02001# Copyright 2016 Mirantis, Inc.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
Dmitry Tyzhnenko2b730a02017-04-07 19:31:32 +030014# import time
Dennis Dmitriev010f4cd2016-11-01 20:43:51 +020015
Dmitry Tyzhnenko2b730a02017-04-07 19:31:32 +030016from collections import defaultdict
17
18from datetime import datetime
19from pepper.libpepper import Pepper
20from tcp_tests import settings
21from tcp_tests import logger
22from tcp_tests.managers.execute_commands import ExecuteCommandsMixin
23
24LOG = logger.logger
25
26
27class SaltManager(ExecuteCommandsMixin):
Dennis Dmitriev010f4cd2016-11-01 20:43:51 +020028 """docstring for SaltManager"""
29
Dmitry Tyzhnenko2b730a02017-04-07 19:31:32 +030030 _config = None
31 _underlay = None
32 _map = {
33 'enforceState': 'enforce_state',
34 'enforceStates': 'enforce_states',
35 'runState': 'run_state',
36 'runStates': 'run_states',
37 }
Dennis Dmitriev010f4cd2016-11-01 20:43:51 +020038
Dmitry Tyzhnenko2b730a02017-04-07 19:31:32 +030039 def __init__(self, config, underlay, host=None, port='6969'):
40 self._config = config
41 self._underlay = underlay
42 self._port = port
43 self._host = host
44 self._api = None
45 self._user = settings.SALT_USER
46 self._password = settings.SALT_PASSWORD
47 self._salt = self
Dennis Dmitriev010f4cd2016-11-01 20:43:51 +020048
49 super(SaltManager, self).__init__()
50
51 def install(self, commands):
Dmitry Tyzhnenko2b730a02017-04-07 19:31:32 +030052 if commands[0].get('do'):
53 self.install2(commands)
54 else:
55 self.install1(commands)
Dennis Dmitriev010f4cd2016-11-01 20:43:51 +020056
Dmitry Tyzhnenko2b730a02017-04-07 19:31:32 +030057 def install1(self, commands):
58 if self._config.salt.salt_master_host == '0.0.0.0':
59 # Temporary workaround. Underlay should be extended with roles
60 salt_nodes = self._underlay.node_names()
61 self._config.salt.salt_master_host = \
62 self._underlay.host_by_node_name(salt_nodes[0])
63
64 # self._underlay.execute_commands(commands=commands,
65 # label="Install and configure salt")
66 self.execute_commands(commands=commands,
67 label="Install and configure salt")
68
69 def install2(self, commands):
70 if self._config.salt.salt_master_host == '0.0.0.0':
71 # Temporary workaround. Underlay should be extended with roles
72 salt_nodes = self._underlay.node_names()
73 self._config.salt.salt_master_host = \
74 self._underlay.host_by_node_name(salt_nodes[0])
75
76 # self.run_commands(commands=commands,
77 # label="Install and configure salt")
78 self.execute_commands(commands=commands,
79 label="Install and configure salt")
80
81 @property
82 def port(self):
83 return self._port
84
85 @property
86 def host(self):
87 if self._host:
88 return self._host
89 elif self._config.salt.salt_master_host == '0.0.0.0':
90 # Temporary workaround. Underlay should be extended with roles
91 salt_nodes = self._underlay.node_names()
92 self._config.salt.salt_master_host = \
93 self._underlay.host_by_node_name(salt_nodes[0])
94
95 return self._config.salt.salt_master_host
96
97 @property
98 def api(self):
99 def login():
100 LOG.info("Authentication in Salt API")
101 self._api.login(
102 username=self._user,
103 password=self._password,
104 eauth='pam')
105 return datetime.now()
106
107 if self._api:
108 if (datetime.now() - self.__session_start).seconds < 5 * 60:
109 return self._api
110 else:
111 # FIXXME: Change to debug
112 LOG.info("Session's expired")
113 self.__session_start = login()
114 return self._api
115
116 LOG.info("Connect to Salt API")
117 url = "http://{host}:{port}".format(
118 host=self.host, port=self.port)
119 self._api = Pepper(url)
120 self.__session_start = login()
121 return self._api
122
123 def local(self, tgt, fun, args=None, kwargs=None):
124 return self.api.local(tgt, fun, args, kwargs, expr_form='compound')
125
126 def local_async(self, tgt, fun, args=None, kwargs=None):
127 return self.api.local_async(tgt, fun, args, kwargs)
128
129 def lookup_result(self, jid):
130 return self.api.lookup_jid(jid)
131
132 def check_result(self, r):
133 if len(r.get('return', [])) == 0:
134 raise LookupError("Result is empty or absent")
135
136 result = r['return'][0]
137 LOG.info("Job has result for %s nodes", result.keys())
138 fails = defaultdict(list)
139 for h in result:
140 host_result = result[h]
141 LOG.info("On %s executed:", h)
142 if isinstance(host_result, list):
143 fails[h].append(host_result)
144 continue
145 for t in host_result:
146 task = host_result[t]
147 if task['result'] is False:
148 fails[h].append(task)
149 LOG.error("%s - %s", t, task['result'])
150 else:
151 LOG.info("%s - %s", t, task['result'])
152
153 return fails if fails else None
154
155 def enforce_state(self, tgt, state, args=None, kwargs=None):
156 r = self.local(tgt=tgt, fun='state.sls', args=state)
157 f = self.check_result(r)
158 return r, f
159
160 def enforce_states(self, tgt, state, args=None, kwargs=None):
161 rets = []
162 for s in state:
163 r = self.enforce_state(tgt=tgt, state=s)
164 rets.append(r)
165 return rets
166
167 def run_state(self, tgt, state, args=None, kwargs=None):
168 return self.local(tgt=tgt, fun=state, args=args, kwargs=kwargs), None
169
170 def run_states(self, tgt, state, args=None, kwargs=None):
171 rets = []
172 for s in state:
173 r = self.run_state(tgt=tgt, state=s, args=args, kwargs=kwargs)
174 rets.append(r)
175 return rets