From 4674090cb2513c5754d457fe6ed6a2628a32fcf7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Diemer?= <stephane.diemer@ubicast.eu>
Date: Wed, 21 Jun 2017 15:49:35 +0200
Subject: [PATCH] Added a script to set domain of an app (refs #21163).

---
 set_app_domain.py | 91 ++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 78 insertions(+), 13 deletions(-)

diff --git a/set_app_domain.py b/set_app_domain.py
index 88570e2c..dd6e45c0 100755
--- a/set_app_domain.py
+++ b/set_app_domain.py
@@ -13,7 +13,7 @@ from utils import log
 
 
 class SetAppDomain():
-    USAGE = '''%s [-d] [-f] [-h] [app] <domain>
+    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.
@@ -23,7 +23,8 @@ class SetAppDomain():
          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__
-    MS_INSTANCE_USER_PATTERN = r'[a-z0-9\-]+'
+    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):
@@ -31,7 +32,7 @@ class SetAppDomain():
         args = list(args)
         # Check if help is required
         if '-h' in args:
-            log('USAGE: ' + self.USAGE)
+            log(self.USAGE)
             sys.exit(0)
         # Check current dir
         root_dir = utils.get_dir(__file__)
@@ -56,33 +57,38 @@ class SetAppDomain():
         # Parse args
         if not args:
             log('Not enough arguments.')
-            log('USAGE: ' + self.USAGE)
+            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()
         # 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.MS_INSTANCE_USER_PATTERN, instance):
-                    log('Invalid MS instance requested. Validation reg exp is: %s' % self.MS_INSTANCE_USER_PATTERN)
+                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.')
-            log('USAGE: ' + self.USAGE)
+            log(self.USAGE)
             sys.exit(1)
         self.change_nginx_domain(nginx_conf, new_domain)
-        if instance:
-            self.change_ms_instance_domain(instance, new_domain)
+        self.change_hosts_file(new_domain)
         sys.exit(0)
 
     def change_nginx_domain(self, path, new_domain):
@@ -117,19 +123,78 @@ class SetAppDomain():
                 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_ms_instance_domain(self, instance, new_domain):
-        # TODO: set MS url in site settings
-        # TODO: reset all local resources managers
+    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):
         try:
-            utils.run_commands(['sudo su %s -c "ls"' % 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__':
-- 
GitLab