blob: 737edcd6096a1d053c9fbe1ba3ccb1e4c842a9c0 [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.
14
Dmitry Tyzhnenkob8641832017-11-07 17:02:47 +020015import netaddr
Dennis Dmitrievad5f8582019-04-12 13:15:08 +030016import pkg_resources
Oleksii Butenkoa39ad542019-05-20 16:50:47 +030017import yaml
Dmitry Tyzhnenkob8641832017-11-07 17:02:47 +020018
Dmitry Tyzhnenko2b730a02017-04-07 19:31:32 +030019from collections import defaultdict
20
21from datetime import datetime
Dennis Dmitrievb8115f52017-12-15 13:09:56 +020022from pepper import libpepper
23from tcp_tests.helpers import utils
Dmitry Tyzhnenko2b730a02017-04-07 19:31:32 +030024from tcp_tests import logger
Dmitry Tyzhnenko35413c02018-03-05 14:12:37 +020025from tcp_tests import settings
Dmitry Tyzhnenko2b730a02017-04-07 19:31:32 +030026from tcp_tests.managers.execute_commands import ExecuteCommandsMixin
27
28LOG = logger.logger
29
30
31class SaltManager(ExecuteCommandsMixin):
Dennis Dmitriev010f4cd2016-11-01 20:43:51 +020032 """docstring for SaltManager"""
33
Dmitry Tyzhnenkobc0f8262017-04-28 15:39:26 +030034 __config = None
35 __underlay = None
Dmitry Tyzhnenko2b730a02017-04-07 19:31:32 +030036 _map = {
37 'enforceState': 'enforce_state',
38 'enforceStates': 'enforce_states',
39 'runState': 'run_state',
40 'runStates': 'run_states',
41 }
Dennis Dmitriev010f4cd2016-11-01 20:43:51 +020042
Dmitry Tyzhnenko5a5d8da2017-12-14 14:14:42 +020043 def __init__(self, config, underlay, host=None, port='6969',
44 username=None, password=None):
Dmitry Tyzhnenkobc0f8262017-04-28 15:39:26 +030045 self.__config = config
46 self.__underlay = underlay
Dennis Dmitriev2d60c8e2017-05-12 18:34:01 +030047 self.__port = port
48 self.__host = host
49 self.__api = None
Dmitry Tyzhnenko5a5d8da2017-12-14 14:14:42 +020050 self.__user = username or settings.SALT_USER
51 self.__password = password or settings.SALT_PASSWORD
Dennis Dmitrieveac3aab2017-07-12 16:36:41 +030052 self._salt = self
Dennis Dmitriev010f4cd2016-11-01 20:43:51 +020053
Dmitry Tyzhnenkobc0f8262017-04-28 15:39:26 +030054 super(SaltManager, self).__init__(config=config, underlay=underlay)
Dennis Dmitriev010f4cd2016-11-01 20:43:51 +020055
56 def install(self, commands):
Dina Belovae6fdffb2017-09-19 13:58:34 -070057 # if self.__config.salt.salt_master_host == '0.0.0.0':
Dennis Dmitriev2d60c8e2017-05-12 18:34:01 +030058 # # Temporary workaround. Underlay should be extended with roles
59 # salt_nodes = self.__underlay.node_names()
60 # self.__config.salt.salt_master_host = \
61 # self.__underlay.host_by_node_name(salt_nodes[0])
Dennis Dmitriev010f4cd2016-11-01 20:43:51 +020062
Dmitry Tyzhnenko2b730a02017-04-07 19:31:32 +030063 self.execute_commands(commands=commands,
64 label="Install and configure salt")
Dennis Dmitrievad5f8582019-04-12 13:15:08 +030065 self.create_env_salt()
66 self.create_env_jenkins_day01()
67 self.create_env_jenkins_cicd()
68 self.create_env_k8s()
Dmitry Tyzhnenko2b730a02017-04-07 19:31:32 +030069
Dmitry Tyzhnenko5a5d8da2017-12-14 14:14:42 +020070 def change_creds(self, username, password):
71 self.__user = username
72 self.__password = password
73
Dmitry Tyzhnenko2b730a02017-04-07 19:31:32 +030074 @property
75 def port(self):
Dennis Dmitriev2d60c8e2017-05-12 18:34:01 +030076 return self.__port
Dmitry Tyzhnenko2b730a02017-04-07 19:31:32 +030077
78 @property
79 def host(self):
Dennis Dmitriev2d60c8e2017-05-12 18:34:01 +030080 if self.__host:
81 return self.__host
82 else:
Dina Belovae6fdffb2017-09-19 13:58:34 -070083 # TODO(ddmitriev): consider to add a check and raise
Dennis Dmitriev2d60c8e2017-05-12 18:34:01 +030084 # exception if 'salt_master_host' is not initialized.
85 return self.__config.salt.salt_master_host
Dmitry Tyzhnenko2b730a02017-04-07 19:31:32 +030086
87 @property
88 def api(self):
89 def login():
90 LOG.info("Authentication in Salt API")
Dennis Dmitriev2d60c8e2017-05-12 18:34:01 +030091 self.__api.login(
92 username=self.__user,
93 password=self.__password,
Dmitry Tyzhnenko2b730a02017-04-07 19:31:32 +030094 eauth='pam')
95 return datetime.now()
96
Dennis Dmitriev2d60c8e2017-05-12 18:34:01 +030097 if self.__api:
Dmitry Tyzhnenko2b730a02017-04-07 19:31:32 +030098 if (datetime.now() - self.__session_start).seconds < 5 * 60:
Dennis Dmitriev2d60c8e2017-05-12 18:34:01 +030099 return self.__api
Dmitry Tyzhnenko2b730a02017-04-07 19:31:32 +0300100 else:
101 # FIXXME: Change to debug
102 LOG.info("Session's expired")
103 self.__session_start = login()
Dennis Dmitriev2d60c8e2017-05-12 18:34:01 +0300104 return self.__api
Dmitry Tyzhnenko2b730a02017-04-07 19:31:32 +0300105
Dmitry Tyzhnenko2b730a02017-04-07 19:31:32 +0300106 url = "http://{host}:{port}".format(
107 host=self.host, port=self.port)
Dennis Dmitriev2d60c8e2017-05-12 18:34:01 +0300108 LOG.info("Connecting to Salt API {0}".format(url))
Dennis Dmitrievb8115f52017-12-15 13:09:56 +0200109 self.__api = libpepper.Pepper(url)
Dmitry Tyzhnenko2b730a02017-04-07 19:31:32 +0300110 self.__session_start = login()
Dennis Dmitriev2d60c8e2017-05-12 18:34:01 +0300111 return self.__api
Dmitry Tyzhnenko2b730a02017-04-07 19:31:32 +0300112
Dennis Dmitrievb6bcc5c2018-09-26 11:07:53 +0000113 def local(self, tgt, fun, args=None, kwargs=None, timeout=None):
114 return self.api.local(tgt, fun, args, kwargs, timeout=timeout,
115 expr_form='compound')
Dmitry Tyzhnenko2b730a02017-04-07 19:31:32 +0300116
Dennis Dmitrievb6bcc5c2018-09-26 11:07:53 +0000117 def local_async(self, tgt, fun, args=None, kwargs=None, timeout=None):
118 return self.api.local_async(tgt, fun, args, kwargs, timeout=timeout)
Dmitry Tyzhnenko2b730a02017-04-07 19:31:32 +0300119
120 def lookup_result(self, jid):
121 return self.api.lookup_jid(jid)
122
123 def check_result(self, r):
124 if len(r.get('return', [])) == 0:
125 raise LookupError("Result is empty or absent")
126
127 result = r['return'][0]
Dmitry Tyzhnenkobc0f8262017-04-28 15:39:26 +0300128 if len(result) == 0:
129 raise LookupError("Result is empty or absent")
Dmitry Tyzhnenko2b730a02017-04-07 19:31:32 +0300130 LOG.info("Job has result for %s nodes", result.keys())
131 fails = defaultdict(list)
132 for h in result:
133 host_result = result[h]
134 LOG.info("On %s executed:", h)
135 if isinstance(host_result, list):
136 fails[h].append(host_result)
137 continue
138 for t in host_result:
139 task = host_result[t]
140 if task['result'] is False:
141 fails[h].append(task)
142 LOG.error("%s - %s", t, task['result'])
143 else:
144 LOG.info("%s - %s", t, task['result'])
145
146 return fails if fails else None
147
Dennis Dmitrievb6bcc5c2018-09-26 11:07:53 +0000148 def enforce_state(self, tgt, state, args=None, kwargs=None, timeout=None):
149 r = self.local(tgt=tgt, fun='state.sls', args=state, timeout=timeout)
Dmitry Tyzhnenko2b730a02017-04-07 19:31:32 +0300150 f = self.check_result(r)
151 return r, f
152
Dennis Dmitrievb6bcc5c2018-09-26 11:07:53 +0000153 def enforce_states(self, tgt, state, args=None, kwargs=None, timeout=None):
Dmitry Tyzhnenko2b730a02017-04-07 19:31:32 +0300154 rets = []
155 for s in state:
Dennis Dmitrievb6bcc5c2018-09-26 11:07:53 +0000156 r = self.enforce_state(tgt=tgt, state=s, timeout=timeout)
Dmitry Tyzhnenko2b730a02017-04-07 19:31:32 +0300157 rets.append(r)
158 return rets
159
Dennis Dmitrievb6bcc5c2018-09-26 11:07:53 +0000160 def run_state(self, tgt, state, args=None, kwargs=None, timeout=None):
161 return self.local(tgt=tgt, fun=state, args=args, kwargs=kwargs,
162 timeout=timeout), None
Dmitry Tyzhnenko2b730a02017-04-07 19:31:32 +0300163
Dennis Dmitrievb6bcc5c2018-09-26 11:07:53 +0000164 def run_states(self, tgt, state, args=None, kwargs=None, timeout=None):
Dmitry Tyzhnenko2b730a02017-04-07 19:31:32 +0300165 rets = []
166 for s in state:
Dennis Dmitrievb6bcc5c2018-09-26 11:07:53 +0000167 r = self.run_state(tgt=tgt, state=s, args=args, kwargs=kwargs,
168 timeout=timeout)
Dmitry Tyzhnenko2b730a02017-04-07 19:31:32 +0300169 rets.append(r)
170 return rets
Artem Panchenko0594cd72017-06-12 13:25:26 +0300171
172 def get_pillar(self, tgt, pillar):
173 result = self.local(tgt=tgt, fun='pillar.get', args=pillar)
174 return result['return']
Dmitry Tyzhnenkob8641832017-11-07 17:02:47 +0200175
Dennis Dmitriev2a498732018-12-21 18:30:23 +0200176 def get_single_pillar(self, tgt, pillar):
177 """Get a scalar value from a single node
178
179 :return: pillar value
180 """
181
182 result = self.get_pillar(tgt, pillar)
183 nodes = result[0].keys()
184
185 if not nodes:
186 raise LookupError("No minions selected "
187 "for the target '{0}'".format(tgt))
188 if len(nodes) > 1:
189 raise LookupError("Too many minions selected "
190 "for the target '{0}' , expected one: {1}"
191 .format(tgt, nodes))
192 return result[0][nodes[0]]
193
Dennis Dmitriev2d643bc2017-12-04 12:23:47 +0200194 def get_grains(self, tgt, grains):
195 result = self.local(tgt=tgt, fun='grains.get', args=grains)
196 return result['return']
197
Dmitry Tyzhnenkob8641832017-11-07 17:02:47 +0200198 def get_ssh_data(self):
199 """Generate ssh config for Underlay
200
201 :param roles: list of strings
202 """
203
204 pool_name = self.__config.underlay.net_mgmt
205 pool_net = netaddr.IPNetwork(self.__config.underlay.address_pools[
206 self.__config.underlay.net_mgmt])
207 hosts = self.local('*', 'grains.item', ['host', 'ipv4'])
208
209 if len(hosts.get('return', [])) == 0:
210 raise LookupError("Hosts is empty or absent")
211 hosts = hosts['return'][0]
212 if len(hosts) == 0:
213 raise LookupError("Hosts is empty or absent")
214
Dennis Dmitriev83cc1d52018-11-09 15:35:30 +0200215 def host(minion_id, ip):
Dmitry Tyzhnenkob8641832017-11-07 17:02:47 +0200216 return {
217 'roles': ['salt_minion'],
218 'keys': [
219 k['private'] for k in self.__config.underlay.ssh_keys
220 ],
Dennis Dmitriev83cc1d52018-11-09 15:35:30 +0200221 'node_name': minion_id,
222 'minion_id': minion_id,
Dmitry Tyzhnenkob8641832017-11-07 17:02:47 +0200223 'host': ip,
224 'address_pool': pool_name,
225 'login': settings.SSH_NODE_CREDENTIALS['login'],
226 'password': settings.SSH_NODE_CREDENTIALS['password']
227 }
228
Dmitry Tyzhnenkob610afd2018-02-19 15:43:45 +0200229 try:
230 ret = [
231 host(k, next(i for i in v['ipv4'] if i in pool_net))
232 for k, v in hosts.items()
233 if next(i for i in v['ipv4'] if i in pool_net)]
234 LOG.debug("Fetched ssh data from salt grains - {}".format(ret))
235 return ret
236 except StopIteration:
237 msg = ("Can't match nodes ip address with network cidr\n"
238 "Managment network - {net}\n"
239 "Host with address - {host_list}".format(
240 net=pool_net,
241 host_list={k: v['ipv4'] for k, v in hosts.items()}))
242 raise StopIteration(msg)
Dennis Dmitriev2d643bc2017-12-04 12:23:47 +0200243
Dennis Dmitriev83cc1d52018-11-09 15:35:30 +0200244 def update_ssh_data_from_minions(self):
245 """Combine existing underlay.ssh with VCP salt minions"""
246 salt_nodes = self.get_ssh_data()
247
248 for salt_node in salt_nodes:
249 nodes = [n for n in self.__config.underlay.ssh
250 if salt_node['host'] == n['host']
251 and salt_node['address_pool'] == n['address_pool']]
252 if nodes:
253 # Assume that there can be only one node with such IP address
254 # Just update minion_id for this node
255 nodes[0]['minion_id'] = salt_node['minion_id']
256 else:
257 # New node, add to config.underlay.ssh
258 self.__config.underlay.ssh.append(salt_node)
259
260 self.__underlay.config_ssh = []
261 self.__underlay.add_config_ssh(self.__config.underlay.ssh)
262
Dennis Dmitriev2d643bc2017-12-04 12:23:47 +0200263 def service_status(self, tgt, service):
264 result = self.local(tgt=tgt, fun='service.status', args=service)
265 return result['return']
266
267 def service_restart(self, tgt, service):
268 result = self.local(tgt=tgt, fun='service.restart', args=service)
269 return result['return']
270
271 def service_stop(self, tgt, service):
272 result = self.local(tgt=tgt, fun='service.stop', args=service)
273 return result['return']
Dennis Dmitrievb8115f52017-12-15 13:09:56 +0200274
Victor Ryzhenkin95046882018-12-29 19:18:40 +0400275 def cmd_run(self, tgt, cmd):
276 result = self.local(tgt=tgt, fun='cmd.run', args=cmd)
277 return result['return']
278
Dennis Dmitrievb8115f52017-12-15 13:09:56 +0200279 @utils.retry(3, exception=libpepper.PepperException)
Dennis Dmitriev427e4152019-05-08 15:12:43 +0300280 def sync_time(self, tgt='*'):
Dennis Dmitrievb8115f52017-12-15 13:09:56 +0200281 LOG.info("NTP time sync on the salt minions '{0}'".format(tgt))
282 # Force authentication update on the next API access
283 # because previous authentication most probably is not valid
284 # before or after time sync.
285 self.__api = None
Dmitry Tyzhnenko80ce0202019-02-07 13:27:19 +0200286 if not settings.SKIP_SYNC_TIME:
Dennis Dmitriev427e4152019-05-08 15:12:43 +0300287 cmd = ('service ntp stop;'
288 'if systemctl is-active --quiet maas-rackd; then'
289 ' systemctl stop maas-rackd; RACKD=true;'
290 'else'
291 ' RACKD=false;'
292 'fi;'
293 'if systemctl is-active --quiet maas-regiond; then'
294 ' systemctl stop maas-regiond; REGIOND=true;'
295 'else'
296 ' REGIOND=false;'
297 'fi;'
298 'if [ -x /usr/sbin/ntpdate ]; then'
299 ' ntpdate -s ntp.ubuntu.com;'
300 'else'
301 ' ntpd -gq;'
302 'fi;'
303 'service ntp start;'
304 'if $RACKD; then systemctl start maas-rackd; fi;'
305 'if $REGIOND; then systemctl start maas-regiond; fi;')
Dmitry Tyzhnenko80ce0202019-02-07 13:27:19 +0200306 self.run_state(
307 tgt,
Dennis Dmitriev427e4152019-05-08 15:12:43 +0300308 'cmd.run', cmd) # noqa
Dennis Dmitrievb8115f52017-12-15 13:09:56 +0200309 new_time_res = self.run_state(tgt, 'cmd.run', 'date')
310 for node_name, time in sorted(new_time_res[0]['return'][0].items()):
311 LOG.info("{0}: {1}".format(node_name, time))
312 self.__api = None
Dennis Dmitrievad5f8582019-04-12 13:15:08 +0300313
314 def create_env_salt(self):
315 """Creates static utils/env_salt file"""
316
317 env_salt_filename = pkg_resources.resource_filename(
318 settings.__name__, 'utils/env_salt')
319 with open(env_salt_filename, 'w') as f:
320 f.write(
321 'export SALT_MASTER_IP={host}\n'
322 'export SALTAPI_URL=http://{host}:{port}/\n'
323 'export SALTAPI_USER="{user}"\n'
324 'export SALTAPI_PASS="{password}"\n'
325 'export SALTAPI_EAUTH="pam"\n'
326 'echo "export SALT_MASTER_IP=${{SALT_MASTER_IP}}"\n'
327 'echo "export SALTAPI_URL=${{SALTAPI_URL}}"\n'
328 'echo "export SALTAPI_USER=${{SALTAPI_USER}}"\n'
329 'echo "export SALTAPI_PASS=${{SALTAPI_PASS}}"\n'
330 'echo "export SALTAPI_EAUTH=${{SALTAPI_EAUTH}}"\n'
331 .format(host=self.host, port=self.port,
332 user=self.__user, password=self.__password)
333 )
334
335 def create_env_jenkins_day01(self):
336 """Creates static utils/env_jenkins_day01 file"""
337
338 env_jenkins_day01_filename = pkg_resources.resource_filename(
339 settings.__name__, 'utils/env_jenkins_day01')
340
341 tgt = 'I@docker:client:stack:jenkins and cfg01*'
342 jenkins_params = self.get_single_pillar(
343 tgt=tgt, pillar="jenkins:client:master")
344 jenkins_port = jenkins_params['port']
345 jenkins_user = jenkins_params['username']
346 jenkins_pass = jenkins_params['password']
347
348 with open(env_jenkins_day01_filename, 'w') as f:
349 f.write(
350 'export JENKINS_URL=http://{host}:{port}\n'
351 'export JENKINS_USER={user}\n'
352 'export JENKINS_PASS={password}\n'
353 'export JENKINS_START_TIMEOUT=60\n'
354 'export JENKINS_BUILD_TIMEOUT=1800\n'
355 'echo "export JENKINS_URL=${{JENKINS_URL}}'
356 ' # Jenkins API URL"\n'
357 'echo "export JENKINS_USER=${{JENKINS_USER}}'
358 ' # Jenkins API username"\n'
359 'echo "export JENKINS_PASS=${{JENKINS_PASS}}'
360 ' # Jenkins API password or token"n\n'
361 'echo "export JENKINS_START_TIMEOUT=${{JENKINS_START_TIMEOUT}}'
362 ' # Timeout waiting for job in queue to start building"\n'
363 'echo "export JENKINS_BUILD_TIMEOUT=${{JENKINS_BUILD_TIMEOUT}}'
364 ' # Timeout waiting for building job to complete"\n'
365 .format(host=self.host, port=jenkins_port,
366 user=jenkins_user, password=jenkins_pass)
367 )
368
369 def create_env_jenkins_cicd(self):
370 """Creates static utils/env_jenkins_cicd file"""
371
372 env_jenkins_cicd_filename = pkg_resources.resource_filename(
373 settings.__name__, 'utils/env_jenkins_cicd')
Oleksii Butenkoa39ad542019-05-20 16:50:47 +0300374 domain_name = self.get_single_pillar(
375 tgt="I@salt:master", pillar="_param:cluster_domain")
376 LOG.info("Domain: {}".format(domain_name))
377 cid01 = 'cid01.' + domain_name
378 LOG.info("{}".format(cid01))
379 command = "reclass -n {}".format(cid01)
380 LOG.info("{}".format(command))
381 cfg = self.__underlay.get_target_node_names('cfg01')[0]
382 LOG.info("cfg node_name: {}".format(cfg))
383 output = self.__underlay.check_call(
384 node_name=cfg,
385 cmd=command)
386 result = yaml.load(output.stdout_str)
387 jenkins_params = result.get(
388 'parameters', {}).get(
389 'jenkins', {}).get(
390 'client', {}).get(
391 'master', {})
392 if not jenkins_params:
Dennis Dmitrievad5f8582019-04-12 13:15:08 +0300393 return
Dennis Dmitrievad5f8582019-04-12 13:15:08 +0300394 jenkins_host = jenkins_params['host']
Oleksii Butenkoa39ad542019-05-20 16:50:47 +0300395 LOG.info("jenkins_host: {}".format(jenkins_host))
Dennis Dmitrievad5f8582019-04-12 13:15:08 +0300396 jenkins_port = jenkins_params['port']
Oleksii Butenkoa39ad542019-05-20 16:50:47 +0300397 LOG.info("jenkins_port: {}".format(jenkins_port))
Dennis Dmitrievad5f8582019-04-12 13:15:08 +0300398 jenkins_user = jenkins_params['username']
Oleksii Butenkoa39ad542019-05-20 16:50:47 +0300399 LOG.info("jenkins_user: {}".format(jenkins_user))
Dennis Dmitrievad5f8582019-04-12 13:15:08 +0300400 jenkins_pass = jenkins_params['password']
Oleksii Butenkoa39ad542019-05-20 16:50:47 +0300401 LOG.info("jenkins_pass: {}".format(jenkins_pass))
Dennis Dmitrievad5f8582019-04-12 13:15:08 +0300402
403 with open(env_jenkins_cicd_filename, 'w') as f:
404 f.write(
405 'export JENKINS_URL=http://{host}:{port}\n'
406 'export JENKINS_USER={user}\n'
407 'export JENKINS_PASS={password}\n'
408 'export JENKINS_START_TIMEOUT=60\n'
409 'export JENKINS_BUILD_TIMEOUT=1800\n'
410 'echo "export JENKINS_URL=${{JENKINS_URL}}'
411 ' # Jenkins API URL"\n'
412 'echo "export JENKINS_USER=${{JENKINS_USER}}'
413 ' # Jenkins API username"\n'
414 'echo "export JENKINS_PASS=${{JENKINS_PASS}}'
415 ' # Jenkins API password or token"n\n'
416 'echo "export JENKINS_START_TIMEOUT=${{JENKINS_START_TIMEOUT}}'
417 ' # Timeout waiting for job in queue to start building"\n'
418 'echo "export JENKINS_BUILD_TIMEOUT=${{JENKINS_BUILD_TIMEOUT}}'
419 ' # Timeout waiting for building job to complete"\n'
420 .format(host=jenkins_host, port=jenkins_port,
421 user=jenkins_user, password=jenkins_pass)
422 )
423
424 def create_env_k8s(self):
425 """Creates static utils/env_k8s file"""
426
427 env_k8s_filename = pkg_resources.resource_filename(
428 settings.__name__, 'utils/env_k8s')
Oleksii Butenkoa39ad542019-05-20 16:50:47 +0300429 domain_name = self.get_single_pillar(
430 tgt="I@salt:master", pillar="_param:cluster_domain")
431 LOG.info("Domain: {}".format(domain_name))
432 ctl01 = 'ctl01.' + domain_name
433 LOG.info("{}".format(ctl01))
434 command = "reclass -n {}".format(ctl01)
435 LOG.info("{}".format(command))
436 cfg = self.__underlay.get_target_node_names('cfg01')[0]
437 LOG.info("cfg node_name: {}".format(cfg))
438 output = self.__underlay.check_call(
439 node_name=cfg,
440 cmd=command)
441 result = yaml.load(output.stdout_str)
442 haproxy_params = result.get(
443 'parameters', {}).get(
444 'haproxy', {}).get(
445 'proxy', {}).get(
446 'listen', {}).get(
447 'k8s_secure', {}).get(
448 'binds', {})
449 if not haproxy_params:
Dennis Dmitrievad5f8582019-04-12 13:15:08 +0300450 return
Oleksii Butenkoa39ad542019-05-20 16:50:47 +0300451 k8s_params = result.get(
452 'kubernetes', {}).get(
453 'master', {}).get(
454 'admin', {})
455 if not k8s_params:
456 return
Dennis Dmitrievad5f8582019-04-12 13:15:08 +0300457 kube_host = haproxy_params['address']
Oleksii Butenkoa39ad542019-05-20 16:50:47 +0300458 LOG.info("kube_host: {}".
459 format(kube_host))
Dennis Dmitrievad5f8582019-04-12 13:15:08 +0300460 kube_apiserver_port = haproxy_params['port']
Oleksii Butenkoa39ad542019-05-20 16:50:47 +0300461 LOG.info("kube_apiserver_port: {}".
462 format(kube_apiserver_port))
Dennis Dmitrievad5f8582019-04-12 13:15:08 +0300463 kubernetes_admin_user = k8s_params['username']
Oleksii Butenkoa39ad542019-05-20 16:50:47 +0300464 LOG.info("kubernetes_admin_user: {}".
465 format(kubernetes_admin_user))
Dennis Dmitrievad5f8582019-04-12 13:15:08 +0300466 kubernetes_admin_password = k8s_params['password']
Oleksii Butenkoa39ad542019-05-20 16:50:47 +0300467 LOG.info("kubernetes_admin_password: {}".
468 format(kubernetes_admin_password))
Dennis Dmitrievad5f8582019-04-12 13:15:08 +0300469
470 with open(env_k8s_filename, 'w') as f:
471 f.write(
472 'export kube_host={host}\n'
473 'export kube_apiserver_port={port}\n'
474 'export kubernetes_admin_user={user}\n'
475 'export kubernetes_admin_password={password}\n'
476 'echo "export kube_host=${{kube_host}}'
477 ' # Kube API host"\n'
478 'echo "export kube_apiserver_port=${{kube_apiserver_port}}'
479 ' # Kube API port"\n'
480 'echo "export kubernetes_admin_user=${{kubernetes_admin_user}}'
481 ' # Kube API username"\n'
482 'echo "export kubernetes_admin_password='
483 '${{kubernetes_admin_password}} # Kube API password"n\n'
484 .format(host=kube_host, port=kube_apiserver_port,
485 user=kubernetes_admin_user,
486 password=kubernetes_admin_password)
487 )