Newer
Older
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
'''
Script to set the domain of an existing MS, CM or Monitor
'''
import os
import re
import subprocess
import sys
import utils
from utils import log
class SetAppDomain():
USAGE = '''USAGE: %s [-d] [-f] [-h] [app] <domain>
-d: Debug mode (can be started with non root users).
-f: Force mode (to force replacement of configuration even if there are warnings).
-h: Show this message.
app: The application for which the new domain should be set.
Possible values:
"ms" (MediaServer), "cm" (Campus Manager), "mon" (Monitor).
It is possible to specify which MS instance should be targetted
by using this format: ms-<instance name> (for example ms-msuser).
domain: The new domain.''' % __file__
UNIX_USER_PATTERN = r'[a-z0-9\-]+'
DOMAIN_PATTERN = r'[a-z0-9\-]+\.[a-z0-9\-]+\.[a-z]+'
NGINX_SERVER_NAME_PATTERN = r'\s*server_name\s+([\w\-\_\.\ ]+);'
def __init__(self, *args):
args = list(args)
# Check if help is required
if '-h' in args:
sys.exit(0)
# Check current dir
root_dir = utils.get_dir(__file__)
if root_dir != '':
os.chdir(root_dir)
self.root_dir = root_dir
# Add to python path
if root_dir not in sys.path:
sys.path.append(root_dir)
# Check if force mode is enabled
self.force = '-f' in args
if self.force:
args.remove('-f')
# Check that this script is run by root
self.debug = '-d' in args
if self.debug:
args.remove('-d')
whoami = subprocess.check_output(['whoami']).decode('utf-8').strip()
if whoami != 'root' and not self.debug:
log('This script should be run as root user.')
sys.exit(1)
# Parse args
if not args:
log('Not enough arguments.')
sys.exit(1)
new_domain = args.pop()
if not re.match(self.DOMAIN_PATTERN, new_domain):
log('The given domain "%s" does not match the expected pattern (%s).\n' % (new_domain, self.DOMAIN_PATTERN))
log(self.USAGE)
sys.exit(1)
if args:
app = args.pop()
# Change domain
instance = None
if app == 'cm':
nginx_conf = '/etc/nginx/sites-available/skyreach.conf'
self.change_cm_domain(new_domain)
elif app == 'mon':
nginx_conf = '/etc/nginx/sites-available/msmonitor.conf'
elif app == 'ms' or app.startswith('ms-'):
if app.startswith('ms-'):
instance = app[3:].strip('. -\t\n')
if not re.match(self.UNIX_USER_PATTERN, instance):
log('Invalid MS instance requested. Validation reg exp is: %s' % self.UNIX_USER_PATTERN)
sys.exit(1)
else:
instance = 'msuser'
nginx_conf = '/etc/nginx/sites-available/mediaserver-%s.conf' % instance
self.change_ms_domain(new_domain, instance)
else:
log('Invalid app name requested.')
sys.exit(1)
self.change_nginx_domain(nginx_conf, new_domain)
self.change_hosts_file(new_domain)
sys.exit(0)
def change_nginx_domain(self, path, new_domain):
log('Checking Nginx configuration file "%s".' % path)
if not os.path.exists(path):
log('The configuration file does not exist.')
sys.exit(1)
with open(path, 'r') as fo:
vhost = fo.read()
new_vhost = ''
changed_lines = 0
for line in vhost.split('\n'):
if re.match(self.NGINX_SERVER_NAME_PATTERN, line):
new_vhost += re.sub(self.NGINX_SERVER_NAME_PATTERN, line, new_domain) + '\n'
changed_lines += 1
else:
new_vhost += line + '\n'
if changed_lines != 2:
log('Warning the number of server_name occurence changed in Nginx configuration is not the expected number (2) but is %s.' % changed_lines)
if not self.force:
log('New configuration will be:')
log(new_vhost)
log('Use -f to force the replacement of the configuration.')
sys.exit(1)
new_vhost = new_vhost.strip() + '\n'
if new_vhost != vhost:
if self.debug:
log('New Nginx conf:')
log(new_vhost)
else:
with open(path, 'w') as fo:
fo.write(new_vhost)
log('The configuration file "%s" has been update.' % path)
utils.run_commands(['service nginx restart'])
else:
log('The configuration file "%s" is already up to date.' % path)
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
def change_hosts_file(self, new_domain):
with open('/etc/hosts', 'r') as fo:
hosts = fo.read()
if ' ' + new_domain in hosts:
hosts = hosts.replace(' ' + new_domain, '')
elif '\t' + new_domain in hosts:
hosts = hosts.replace('\t' + new_domain, '')
hosts = hosts.strip()
new_hosts = ''
for line in hosts.split('\n'):
new_hosts += '\n' + line
if line.startswith('127.0.0.1'):
new_hosts += ' ' + new_domain
if new_hosts != hosts:
if self.debug:
log('New hosts:')
log(new_hosts)
else:
with open('/etc/hosts', 'w') as fo:
fo.write(new_hosts)
log('The hosts file has been update.')
utils.run_commands(['service nscd restart'])
else:
log('The hosts file is already up to date.')
def change_ms_domain(self, new_domain, instance):
import mediaserver
ms_path = mediaserver.__path__[0]
new_url = 'https://%s' % new_domain
log('Assuming that the new url is using HTTPS: "%s"' % new_url)
cmds = [
# set site url in site settings
'python3', os.path.join(ms_path, 'scripts', 'mssiteconfig.py'), instance, 'site_url="%s"' % new_url,
# reset all local resources managers
'python3', os.path.join(ms_path, 'scripts', 'reset_service_resources.py'), instance, 'local',
# change configuration of worker on MS side
'sed -i "s@\'url\': \'\\(http[s]*\\)://.*\'@\'url\': \'\\1://%s\'@" /etc/celerity/config.py' % new_domain,
]
worker_ips = utils.get_conf('CELERITY_WORKER_IP') or '127.0.1.1'
# change configuration of worker on worker side
for worker_ip in worker_ips.split(','):
cmds.append('ssh root@%s sed -i "s@\'url\': \'\\(http[s]*\\)://.*\'@\'url\': \'\\1://%s\'@" /etc/celerity/config.py' % (worker_ip, new_domain))
utils.run_commands(cmds)
except Exception as e:
log('Unable to set MS domain:\n%s' % e)
sys.exit(1)
else:
log('MS domain changed')
log('Some steps to change the domain should be done manually:')
log(' - Change the domain of MS used in CM stations configuration.')
def change_cm_domain(self, new_domain):
try:
new_url = 'https://%s' % new_domain
log('Assuming that the new url is using HTTPS: "%s"' % new_url)
cmds = [
# set site url in site settings
'echo \'from skyreach_site.base.models import SiteSettings; ss = SiteSettings.get_singleton(); ss.url = "%s"; ss.save(); print("site settings saved")\' | su skyreach -c "python3 /home/skyreach/htdocs/skyreach_site/manage.py shell --plain --no-startup"' % new_url,
]
utils.run_commands(cmds)
except Exception as e:
log('Unable to set CM domain:\n%s' % e)
sys.exit(1)
else:
log('CM domain changed')
log('Some steps to change the domain should be done manually:')
log(' - Change the url of CM in the related MS.')
if __name__ == '__main__':
SetAppDomain(*sys.argv[1:])