#!/usr/bin/env python3 # -*- coding: utf-8 -*- ''' Script to set the domain of an existing MediaServer, Miris Manager 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), "mm" (Miris Manager), "mon" (Monitor). It is possible to specify which MediaServer 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]+' def __init__(self, *args): args = list(args) # Check if help is required if '-h' in args: log(self.USAGE) 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.') log(self.USAGE) 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() # Get Nginx conf path and instance user key = None instance = None if app == 'mm': nginx_conf = '/etc/nginx/sites-available/skyreach.conf' key = 'CM_SERVER_NAME' elif app == 'mon': nginx_conf = '/etc/nginx/sites-available/msmonitor.conf' key = 'MONITOR_SERVER_NAME' 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 MediaServer 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 if instance == 'msuser': key = 'MS_SERVER_NAME' else: log('Invalid app name requested.') log(self.USAGE) sys.exit(1) # Change domain self.change_nginx_domain(nginx_conf, new_domain) self.change_hosts_file(new_domain) if key: self.change_envsetup_conf(key, new_domain) if app == 'mm': warning = self.change_mm_domain(new_domain) elif app == 'mon': warning = None else: warning = self.change_ms_domain(new_domain, instance) log('\033[92mDone\033[0m') if warning: log('\033[93mWarning:\033[0m') log(warning) 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(r'\s*server_name\s+([\w\-\_\.\ ]+);', line): line = re.sub(r'server_name\s+([\w\-\_\.\ ]+);', 'server_name %s;' % new_domain, line) changed_lines += 1 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) def change_hosts_file(self, new_domain): with open('/etc/hosts', 'r') as fo: hosts = fo.read() ori_hosts = hosts 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 != ori_hosts: if self.debug: log('New hosts:') log(new_hosts) else: with open('/etc/hosts', 'w') as fo: fo.write(new_hosts) log('The "/etc/hosts" file has been update.') try: utils.run_commands(['service nscd restart']) except Exception as nscd_err: log(nscd_err) else: log('The "/etc/hosts" file is already up to date.') def change_envsetup_conf(self, key, new_domain): confs = ( 'conf.sh', 'auto-generated-conf.sh', ) replaced = False for path in confs: if os.path.exists(path): with open(path, 'r') as fo: content = fo.read() if key in content: content = re.sub(r'%s=.*' % key, '%s=\'%s\'' % (key, new_domain), content) with open(path, 'w') as fo: fo.write(content) replaced = True log('Envsetup configration file "%s" updated.' % path) break if not replaced: with open(confs[0], 'a') as fo: fo.write('\n%s=\'%s\'' % (key, new_domain)) log('Envsetup configration file "%s" updated.' % confs[0]) def change_ms_domain(self, new_domain, instance): try: 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 %s %s site_url="%s"' % (os.path.join(ms_path, 'scripts', 'mssiteconfig.py'), instance, new_url), # reset all local resources managers 'python3 %s %s local' % (os.path.join(ms_path, 'scripts', 'reset_service_resources.py'), instance), # change configuration of celerity in MS and in workers 'python3 %s update %s' % (os.path.join(ms_path, 'scripts', 'celerity_config_updater.py'), instance), # restart ms 'mscontroller.py restart -u %s' % instance, ] utils.run_commands(cmds) except Exception as e: log('Unable to set domain in MediaServer database and Celerity config:\n%s' % e) sys.exit(1) else: log('Domain changed in MediaServer database and Celerity config.') msg = 'Some steps to change the domain should be done manually:' msg += '\n - Change the domain of MediaServer used in Miris Manager stations configuration.' return msg def change_mm_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 -i python"' % new_url, ] utils.run_commands(cmds) except Exception as e: log('Unable to set domain in Miris Manager database:\n%s' % e) sys.exit(1) else: log('Domain changed in Miris Manager database.') msg = 'Some steps to change the domain should be done manually:' msg += '\n - Change the url of Miris Manager in the related MediaServer.' return msg if __name__ == '__main__': SetAppDomain(*sys.argv[1:])