tools/stx/lib/stx/stx_control.py

298 lines
13 KiB
Python

#!/usr/bin/env python3
#
# Copyright (c) 2021 Wind River Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import getpass
import logging
import os
import shutil
import subprocess
import sys
import time
from stx import helper # pylint: disable=E0611
from stx.k8s import KubeHelper
from stx import stx_shell
from stx import utils # pylint: disable=E0611
helmchartdir = 'stx/stx-build-tools-chart/stx-builder'
class HandleControlTask:
'''Handle the task for the control sub-command'''
def __init__(self, config):
self.config = config
self.k8s = KubeHelper(config)
self.projectname = self.config.get('project', 'name')
self.logger = logging.getLogger('STX-Control')
self.abs_helmchartdir = os.path.join(os.environ['PRJDIR'],
helmchartdir)
self.shell = stx_shell.HandleShellTask(config)
utils.set_logger(self.logger)
def configurePulp(self):
'''Initial the password of the pulp service.'''
# wait three times when the pulp service is not initialized yet.
count = 3
remote_cmd = ' -- bash /etc/pulp/changepasswd'
pulpname = ' stx-pulp'
while count:
podname = self.k8s.get_pod_name(pulpname)
if podname:
cmd = self.config.kubectl() + ' exec -ti '
cmd = cmd + podname + remote_cmd
subprocess.call(cmd, shell=True)
count = 0
else:
self.logger.info('Waiting for pulp to finish the setup...')
time.sleep(60)
count = count - 1
if count == 0:
self.logger.error('Pulp service initialization failed.\n')
sys.exit(1)
def finish_configure(self):
'''Before starting, we need to finish the setup'''
max_cpus = os.environ['STX_BUILD_CPUS']
projectname = self.config.get('project', 'name')
builder_uid = self.config.get('builder', 'uid')
builder_myuname = self.config.get('builder', 'myuname')
builder_release = self.config.get('builder', 'release')
builder_dist = self.config.get('builder', 'dist')
builder_stx_dist = self.config.get('builder', 'stx_dist')
builder_debfullname = self.config.get('builder', 'debfullname')
builder_debemail = self.config.get('builder', 'debemail')
repomgr_type = self.config.get('repomgr', 'type')
repomgr_origin = self.config.get('repomgr', 'origin')
gituser = self.config.get('project', 'gituser')
gitemail = self.config.get('project', 'gitemail')
proxy = self.config.get('project', 'proxy')
proxyserver = self.config.get('project', 'proxyserver')
proxyport = self.config.get('project', 'proxyport')
buildbranch = self.config.get('project', 'buildbranch')
manifest = self.config.get('project', 'manifest')
cengnurl = self.config.get('repomgr', 'cengnurl')
cengnstrategy = self.config.get('repomgr', 'cengnstrategy')
sourceslist = self.config.get('repomgr', 'sourceslist')
deblist = self.config.get('repomgr', 'deblist')
dsclist = self.config.get('repomgr', 'dsclist')
ostree_osname = self.config.get('project', 'ostree_osname')
debian_snapshot = \
self.config.get('project', 'debian_snapshot_base') + \
'/' + \
self.config.get('project', 'debian_snapshot_timestamp')
debian_security_snapshot = \
self.config.get('project', 'debian_security_snapshot_base') + \
'/' + \
self.config.get('project', 'debian_snapshot_timestamp')
debian_distribution = self.config.get('project', 'debian_distribution')
debian_version = self.config.get('project', 'debian_version')
if sourceslist:
if not (deblist or dsclist):
self.logger.warning('*************************************\
*********************************')
self.logger.warning('Either Deblist or Dsclist must exist \
when sourceslist is enabled!!!')
self.logger.warning('*************************************\
*********************************')
sys.exit(1)
repomgr_type = self.config.get('repomgr', 'type')
if repomgr_type not in ('aptly', 'pulp'):
self.logger.warning('Repomgr type only supports [aptly] or [pulp],\
please modify the value with config command!!!')
sys.exit(1)
builder_chartfile = os.path.join(self.abs_helmchartdir, 'Chart.yaml')
cmd = 'sed -i -e "s:aptly:%s:g" %s' % (repomgr_type, builder_chartfile)
self.logger.debug('Write the repomgr type [%s] to the chart file \
with the command [%s]', repomgr_type, cmd)
# Fix Me:
# Now we always use aptly as the repomgr.
# Don't switch to pulp, since it will trigger the sshd block issue.
# Later if we find the root cause and fix it, we will enable the
# following function.
# os.system(cmd)
configmap_dir = os.path.join(self.abs_helmchartdir, 'configmap/')
self.logger.debug('builder localrc file is located at %s',
configmap_dir)
pkgbuilder_configmap_dir = os.path.join(self.abs_helmchartdir,
'dependency_chart/\
stx-pkgbuilder/configmap/')
self.logger.debug('pkgbuilder localrc file is located at %s',
pkgbuilder_configmap_dir)
if not os.path.exists(pkgbuilder_configmap_dir):
os.mkdir(pkgbuilder_configmap_dir)
localrcsample = os.path.join(configmap_dir, 'localrc.sample')
localrc = os.path.join(configmap_dir, 'stx-localrc')
if os.path.exists(localrc):
os.remove(localrc)
hostusername = getpass.getuser()
with open(localrcsample, "r") as rf:
message = ''
for line in rf:
line = line.replace("@PROJECT@", projectname)
line = line.replace("@MYUID@", builder_uid)
line = line.replace("@MYUNAME@", builder_myuname)
line = line.replace("@MY_RELEASE@", builder_release)
line = line.replace("@DIST@", builder_dist)
line = line.replace("@STX_DIST@", builder_stx_dist)
line = line.replace("@DEBFULLNAME@", builder_debfullname)
line = line.replace("@DEBEMAIL@", builder_debemail)
line = line.replace("@REPOMGR_TYPE@", repomgr_type)
line = line.replace("@REPOMGR_ORIGIN@", repomgr_origin)
line = line.replace("@GITUSER@", gituser)
line = line.replace("@GITEMAIL@", gitemail)
line = line.replace("@PROXY@", proxy)
line = line.replace("@PROXYSERVER@", proxyserver)
line = line.replace("@PROXYPORT@", proxyport)
line = line.replace("@BUILDBRANCH@", buildbranch)
line = line.replace("@MANIFEST@", manifest)
line = line.replace("@HOSTUSERNAME@", hostusername)
line = line.replace("@CENGNURL@", cengnurl)
line = line.replace("@CENGNSTRATEGY@", cengnstrategy)
line = line.replace("@OSTREE_OSNAME@", ostree_osname)
line = line.replace("@DEBIAN_SNAPSHOT@", debian_snapshot)
line = line.replace("@DEBIAN_SECURITY_SNAPSHOT@", debian_security_snapshot)
line = line.replace("@DEBIAN_DISTRIBUTION@", debian_distribution)
line = line.replace("@DEBIAN_VERSION@", debian_version)
line = line.replace("@MAX_CPUS@", max_cpus)
if sourceslist:
line = line.replace("@fetch@", "true")
line = line.replace("@SOURCESLIST@", sourceslist)
line = line.replace("@DEBLIST@", deblist)
line = line.replace("@DSCLIST@", dsclist)
message += line
with open(localrc, "w") as wf:
wf.write(message)
# Update LAT configmap for patching
lat_configmap_dir = os.path.join(self.abs_helmchartdir,
'dependency_chart/stx-lat-tool/configmap/')
patch_env_sample = os.path.join(lat_configmap_dir, 'patch.env.sample')
patch_env = os.path.join(lat_configmap_dir, 'stx-patch-env.sh')
with open(patch_env_sample, "r") as rf:
message = rf.read()
message = message.replace("@PROJECT@", projectname)
message = message.replace("@MYUNAME@", builder_myuname)
with open(patch_env, "w") as wf:
wf.write(message)
# Copy stx-localrc file of builder container to pkgbuilder
cmd = 'cp -f %s %s' % (localrc, pkgbuilder_configmap_dir)
os.system(cmd)
# Update the dependency charts
cmd = self.config.helm() + ' dependency update ' + self.abs_helmchartdir
self.logger.debug('Dependency build command: %s', cmd)
subprocess.call(cmd, shell=True)
return repomgr_type
def handleStartTask(self, projectname):
cmd = self.config.helm() + ' install ' + projectname + ' ' \
+ self.abs_helmchartdir \
+ ' --set global.image.tag=' + self.config.docker_tag
if not self.config.use_minikube:
# Override hostDir for k8s local host mount
# need to review this to support multi node (PV/PVCs)
cmd += ' --set global.hostDir=' + self.config.build_home
for reg_index, reg in enumerate(self.config.insecure_docker_reg_list):
cmd += f' --set stx-docker.insecureRegistries[{reg_index}]={reg}'
if self.config.container_mtu:
cmd += f' --set stx-docker.mtu={self.config.container_mtu}'
self.logger.debug('Execute the helm start command: %s', cmd)
helm_status = self.k8s.helm_release_exists(self.projectname)
if helm_status:
self.logger.warning('The helm release %s already exists - nothing to do',
projectname)
else:
repomgr_type = self.finish_configure()
subprocess.check_call(cmd, shell=True, cwd=os.environ['PRJDIR'])
if repomgr_type == 'pulp':
self.configurePulp()
def handleStopTask(self, projectname):
helm_status = self.k8s.helm_release_exists(self.projectname)
if helm_status:
cmd = self.config.helm() + ' uninstall ' + projectname
self.logger.debug('Execute the helm stop command: %s', cmd)
subprocess.check_call(cmd, shell=True)
else:
self.logger.warning('The helm release %s does not exist - nothing to do',
projectname)
def handleUpgradeTask(self, projectname):
self.finish_configure()
helm_status = self.k8s.helm_release_exists(self.projectname)
if helm_status:
cmd = self.config.helm() + ' upgrade ' + projectname + ' ' \
+ self.abs_helmchartdir
self.logger.debug('Execute the upgrade command: %s', cmd)
subprocess.call(cmd, shell=True, cwd=os.environ['PRJDIR'])
else:
self.logger.error('The helm release %s does not exist.',
projectname)
sys.exit(1)
def handleEnterTask(self, args):
self.shell.cmd_control_enter(args)
def handleControl(self, args):
self.logger.setLevel(args.loglevel)
projectname = self.config.get('project', 'name')
if not projectname:
projectname = 'stx'
if args.ctl_task == 'start':
self.handleStartTask(projectname)
elif args.ctl_task == 'stop':
self.handleStopTask(projectname)
elif args.ctl_task == 'upgrade':
self.handleUpgradeTask(projectname)
elif args.ctl_task == 'enter':
self.handleEnterTask(args)
elif args.ctl_task == 'status':
self.k8s.get_helm_info()
self.k8s.get_deployment_info()
self.k8s.get_pods_info()
else:
self.logger.error('Control module doesn\'t support your \
subcommand: [%s].\n', args.ctl_task)
print(helper.help_control())