sbin/sync/fabfile.py
changeset 23 7df43b86c425
parent 11 fc7cc9667de1
child 24 6b79d5424407
equal deleted inserted replaced
19:cdb1030d63a8 23:7df43b86c425
     1 from fabric.api import task, run, local, env, cd, put, prefix, sudo, lcd
     1 from fabric.api import task, env, sudo
     2 from fabric.colors import green
     2 from fabric.colors import green
     3 from fabric.contrib.project import rsync_project
     3 from fabric.tasks import Task
     4 from fabric.contrib.files import exists, upload_template
     4 from ldt_fablib import (check_folder_access, syncdb, collectstatic, 
     5 from fabric.context_managers import settings 
     5     export_version, do_sync_web, create_config, clean_export_folder, do_sync_comp, 
     6 from mercurial import commands, ui, hg, cmdutil
     6     sync_install_build, do_create_virtualenv, clean_rsync_folder, rsync_export, 
       
     7     get_comp_versions_dict)
     7 import imp
     8 import imp
     8 import os, os.path
     9 import os.path
     9 import shutil
       
    10 import sys
       
    11 import urlparse
       
    12 
    10 
    13 import config
       
    14 
       
    15 def get_export_path(version):
       
    16     base_path = os.path.join(env.base_export_path,env.export_prefix).rstrip("/")
       
    17     return os.path.expanduser(base_path) + "_%s" % (str(version))
       
    18 
       
    19 def clean_export_folder(path):
       
    20     print("Removing %s" % path)
       
    21     if os.path.isdir(path):
       
    22         shutil.rmtree(path, ignore_errors=True)
       
    23 
       
    24 def do_export_version(path, **export_keys):
       
    25     print("Export version %s " % (repr(export_keys)))
       
    26 
       
    27     for export_key, version in export_keys.items():
       
    28         export_path = os.path.join(path,export_key)
       
    29         
       
    30         repo_url = env.repos[export_key]
       
    31         url_part = urlparse.urlparse(repo_url)
       
    32         if url_part.scheme or url_part.netloc:
       
    33             # this is a remote repo. Let's clone first
       
    34             clone_path = os.path.join(path,'clone',export_keys)
       
    35             os.makedirs(clone_path)
       
    36             local("hg clone \"%s\" \"%s\"" % (repo_url,clone_path))
       
    37         else:
       
    38             clone_path = repo_url
       
    39         
       
    40         with lcd(clone_path):
       
    41             local("hg archive -r \'%s\' \"%s\"" % (str(version),export_path))
       
    42     
       
    43     print("Export version %s done"%repr(export_keys))
       
    44 
       
    45     
       
    46 def get_remote_env(remotepath, remotevirtualenvpath, platform_web_module, settings_key):
       
    47     activate_path = os.path.join(remotevirtualenvpath, "bin/activate")
       
    48     res = ""
       
    49     with prefix("source \"%s\"" % activate_path), prefix("export PYTHONPATH=\"%s\"" % remotepath), cd(remotepath):
       
    50         tempfilepath = run("mktemp -t ldtplatform.XXXXXX")
       
    51         with settings(warn_only=True):
       
    52             run("echo \"import os\" > %s" % (tempfilepath))
       
    53             map(lambda str: run("echo \"%s\" >> %s" % (str, tempfilepath)),
       
    54                 ["os.environ.setdefault('DJANGO_SETTINGS_MODULE', '%s.settings')" % (platform_web_module),
       
    55                  "from django.conf import settings",
       
    56                  "print settings.%s" % (settings_key)])
       
    57             res = run("python < %s" % (tempfilepath))
       
    58         run("rm -f \"%s\"" % (tempfilepath))
       
    59     return res
       
    60     
       
    61     
       
    62     
       
    63 def rsync_export(path, remotepath, filters):
       
    64     print("Rsync %s to %s",(path,remotepath))
       
    65     
       
    66     filter_option_str = "--progress --stats"
       
    67     if filters:
       
    68         filter_option_str += " " + " ".join(["--filter \"%s\"" % (f) for f in filters])
       
    69     
       
    70     run("mkdir -p \"%s\"" % remotepath)
       
    71     rsync_project(remotepath, local_dir=path, extra_opts=filter_option_str, delete=True)
       
    72     print("Rsync %s to %s done",(path,remotepath))
       
    73     
       
    74 def clean_rsync_folder(remotepath):
       
    75     print("clean rsync folder %s" % remotepath)
       
    76     run("rm -fr \"%s\"" % remotepath)
       
    77     
       
    78 def build_src(path):
       
    79     print("Build source dist at %s" % path)
       
    80     f = None
       
    81     try:
       
    82         f, pathname, description = imp.find_module("setup", [path])
       
    83         print(" 2 Build source dist at %s" % path)
       
    84         setup_mod = imp.load_module("setup", f, pathname, description)
       
    85         print(" 3 Build source dist at %s" % path)
       
    86     finally:
       
    87         if f:
       
    88             f.close()
       
    89         
       
    90     setup_mod.launch_setup("setup.py", ['sdist'])
       
    91     
       
    92     print("Build source dist at %s done" % path)
       
    93     
       
    94 
       
    95 def get_src_version(path):
       
    96     print("get src version at %s" % path)
       
    97     f = None
       
    98     try:
       
    99         f, pathname, description = imp.find_module("ldt", [path])
       
   100         ldt_mod = imp.load_module("ldt", f, pathname, description)
       
   101     finally:
       
   102         if f:
       
   103             f.close()
       
   104     version = ldt_mod.VERSION
       
   105     version_str = ldt_mod.get_version()
       
   106     
       
   107     return (version, version_str) 
       
   108     
       
   109 
       
   110 def sync_build(path):
       
   111     print("Sync build %s" % path)
       
   112     with cd(env.remote_path['ldt_base']):
       
   113         filename = os.path.basename(path)
       
   114         res_trans = put(path, os.path.join(env.remote_path['ldt_base'], filename))
       
   115         print("Sync build %s to %s" % (path,repr(res_trans)))
       
   116         return res_trans
       
   117 
       
   118 def remove_build(path):
       
   119     print("remove build build %s" % path)
       
   120     run("rm \"%s\"" % path)
       
   121         
       
   122 
       
   123 def install_build(remotepath, remotevirtualenvpath, module_to_uninstall= None):
       
   124     print("Install build %s in %s" % (remotepath, remotevirtualenvpath))
       
   125     activate_path = os.path.join(remotevirtualenvpath, "bin/activate")
       
   126     
       
   127     with prefix("source %s" % activate_path):
       
   128         if module_to_uninstall:
       
   129             with settings(warn_only=True):
       
   130                 run("pip uninstall -y %s" % module_to_uninstall)
       
   131         run("pip install \"%s\"" % remotepath)
       
   132 
       
   133 def collectstatic(remotepath, remotevirtualenvpath, platform_web_module):
       
   134     print("Collect static in %s with %s" % (remotepath, remotevirtualenvpath))
       
   135     remotestaticsitepath = get_remote_env(remotepath, remotevirtualenvpath, platform_web_module, "STATIC_ROOT")
       
   136     activate_path = os.path.join(remotevirtualenvpath, "bin/activate")
       
   137     with prefix("source \"%s\"" % activate_path), prefix("export PYTHONPATH=\"%s\"" % remotepath), cd(remotepath):
       
   138         #remocve old files optio -c of collect static fail !
       
   139         run("rm -fr \"%s\"" % (remotestaticsitepath))
       
   140         run("python manage.py collectstatic --noinput")
       
   141 
       
   142 def syncdb(remotepath, remotevirtualenvpath):
       
   143     activate_path = os.path.join(remotevirtualenvpath, "bin/activate")
       
   144     with prefix("source \"%s\"" % activate_path), prefix("export PYTHONPATH=\"%s\"" % remotepath), cd(remotepath):
       
   145         run("python manage.py syncdb --migrate --noinput")
       
   146         
       
   147 def create_config(export_path):    
       
   148     print("Create config from %s" % (export_path,))
       
   149     remotepath = env.remote_path['src']
       
   150     remote_config_path = os.path.join(remotepath, env.platform_web_module, "config.py")
       
   151     template_path = os.path.join(export_path, "src", env.platform_web_module, "config.py.tmpl")
       
   152     
       
   153     context = {
       
   154         'base_dir': os.path.join(remotepath, env.platform_web_module).rstrip("/")+"/",
       
   155         'asctime': '%(asctime)s',
       
   156         'levelname': '%(levelname)s',
       
   157         'message': '%(message)s',
       
   158         'module': '%(module)s',
       
   159     }
       
   160     context.update(env.config['web'])
       
   161     
       
   162     if not exists(remote_config_path, verbose=True):
       
   163         upload_template(template_path, remote_config_path, context=context)
       
   164 
       
   165 def export_version(**kwargs):
       
   166     print("export version %s" % (repr(kwargs)))
       
   167     
       
   168     export_path = get_export_path("_".join(["%s_%s" % (k,v) for k,v in kwargs.items()]))
       
   169     
       
   170     clean_export_folder(export_path)
       
   171     
       
   172     do_export_version(export_path,**kwargs)
       
   173     
       
   174     return export_path
       
   175 
       
   176 def do_create_virtualenv(remote_venv_export_path, remotevirtualenvpath):
       
   177     print("Create virtualenv export_path : %s - remote venvpath : %s" % (remote_venv_export_path, remotevirtualenvpath))
       
   178     activate_path = os.path.join(remotevirtualenvpath, "bin/activate")
       
   179     if "remote_baseline_venv" in env and env.remote_baseline_venv:
       
   180         prefix_str = "source \"%s\"" % os.path.join(env.remote_baseline_venv, "bin/activate")
       
   181     else:
       
   182         prefix_str = "echo"
       
   183     with settings(warn_only=True):
       
   184         run("rm -fr \"%s\"" % remotevirtualenvpath)
       
   185     run("mkdir -p \"%s\"" % remotevirtualenvpath)
       
   186     with prefix(prefix_str), cd(os.path.join(remote_venv_export_path,"virtualenv","web")):
       
   187         run("python create_python_env.py")
       
   188         run("python project-boot.py \"%s\"" % remotevirtualenvpath)
       
   189     with prefix("source \"%s\"" % activate_path):
       
   190         run("pip install -r \"%s\"" % os.path.join(remote_venv_export_path,"virtualenv","web","res","srvr_requirements.txt"))
       
   191 
       
   192 def do_sync_ldt(version, export_path):
       
   193     print("do_sync_ldt with version %s and path %s" % (version,export_path))
       
   194     
       
   195     ##
       
   196     src_path = export_path + "/src/ldt"
       
   197     build_src(src_path)
       
   198     (_,version_str) = get_src_version(src_path)
       
   199     build_path = os.path.join(src_path,"dist","ldt-%s.tar.gz" % version_str)
       
   200     sync_install_build(build_path, 'ldt')
       
   201         
       
   202 
       
   203 def sync_install_build(build_path, module_to_uninstall=None):
       
   204     res_trans = None
       
   205     try:
       
   206         res_trans = sync_build(build_path)
       
   207         install_build(res_trans[0], env.remote_path['virtualenv'], module_to_uninstall)        
       
   208     finally:
       
   209         if res_trans:
       
   210             remove_build(res_trans[0])
       
   211 
       
   212 
       
   213 def do_sync_web(version, export_path):
       
   214     print("do_sync_web with version %s and path %s" % (version,export_path))
       
   215     #sync web
       
   216     web_path = os.path.join(export_path,"web/") 
       
   217     rsync_export(web_path, env.remote_path['web'], env.rsync_filters['web'])
       
   218     #sync src
       
   219     src_path = os.path.join(export_path,"src/") 
       
   220     rsync_export(src_path, env.remote_path['src'], env.rsync_filters['src'])
       
   221         
       
   222     
       
   223 def check_folder_access():
       
   224     print("Check folder access")
       
   225     # get remote user
       
   226     for folder_path in env.folders:
       
   227         if not os.path.isabs(folder_path):
       
   228             folder_path = env.remote_path['web'].rstrip("/")+ "/" + folder_path
       
   229             with settings(warn_only=True):
       
   230                 if not exists(folder_path):
       
   231                     run("mkdir -p \"%s\"" % folder_path)
       
   232                 run("chown -R -c :%s \"%s\"" % (env.web_group, folder_path))
       
   233                 run("chmod -R -c g+w \"%s\"" % folder_path)
       
   234 @task
    11 @task
   235 def relaunch_server(do_collectstatic=True, do_syncdb=True):
    12 def relaunch_server(do_collectstatic=True, do_syncdb=True):
   236     print("Relaunch server")
    13     print("Relaunch server")
   237     check_folder_access()
    14     check_folder_access()
   238     if do_syncdb:
    15     if do_syncdb:
   248     export_path_full = os.path.join(export_path,'web')
    25     export_path_full = os.path.join(export_path,'web')
   249     do_sync_web(version, export_path_full)
    26     do_sync_web(version, export_path_full)
   250     create_config(export_path_full)
    27     create_config(export_path_full)
   251     clean_export_folder(export_path)
    28     clean_export_folder(export_path)
   252     relaunch_server()
    29     relaunch_server()
   253 
       
   254 @task
       
   255 def sync_ldt(version):
       
   256     print(green("sync ldt with version %s" % version))
       
   257     export_path = export_version(ldt=version)
       
   258     export_path_full = os.path.join(export_path,'ldt')
       
   259     do_sync_ldt(version, export_path_full)
       
   260     clean_export_folder(export_path)
       
   261     relaunch_server()
       
   262     
    30     
   263 @task
    31 @task
   264 def update_lib(version, package):
    32 def update_lib(version, package):
   265     print(green("update ldt with version %s" % version))
    33     print(green("update ldt with version %s" % version))
   266     export_path = export_version(web=version)
    34     export_path = export_version(web=version)
   267     export_path_full = os.path.join(export_path,'web')
    35     export_path_full = os.path.join(export_path,'web')
   268     lib_path = os.path.join(export_path_full, "virtualenv", "res", "lib")
    36     lib_path = os.path.join(export_path_full, "virtualenv", "res", "lib")
   269     
    37     
   270     f, pathname, description = imp.find_module("patch", [lib_path])
    38     f, pathname, description = imp.find_module("patch", [lib_path])
   271     patch = imp.load_module("patch", f, pathname, description)
    39     imp.load_module("patch", f, pathname, description)
   272     f, pathname, description = imp.find_module("lib_create_env", [lib_path])
    40     f, pathname, description = imp.find_module("lib_create_env", [lib_path])
   273     lib_create_env = imp.load_module("lib_create_env", f, pathname, description)
    41     lib_create_env = imp.load_module("lib_create_env", f, pathname, description)
   274     
    42     
   275     package_path = os.path.join(export_path_full, "virtualenv", "res", "src", lib_create_env.URLS[package]['local'])
    43     package_path_full = os.path.join(export_path_full, "virtualenv", "res", "src", lib_create_env.URLS[package]['local'])
   276     
    44     
   277     sync_install_build(package_path_full)
    45     sync_install_build(package_path_full)
   278     clean_export_folder(export_path)
    46     clean_export_folder(export_path)
   279     relaunch_server()
    47     relaunch_server()
   280     
    48     
   281 @task
    49 @task
   282 def sync_platform(version_web, version_ldt):
    50 def sync_platform(version):
   283     print(green("sync platform with version web %s, ldt %s" % (version_web, version_ldt)))
    51     print(green("sync platform with version web %s" % (version)))
   284     export_path = export_version(ldt=version_ldt, web=version_web)
    52     export_path = export_version(web=version)
   285     export_path_ldt = os.path.join(export_path,'ldt')
    53     
   286     export_path_web = os.path.join(export_path,'web')
    54     export_path_web = os.path.join(export_path,'web')
   287     do_sync_ldt(version_ldt, export_path_ldt)
    55     do_sync_web(version, export_path_web)    
   288     do_sync_web(version_web, export_path_web)
    56 
       
    57     comp_versions = get_comp_versions_dict(export_path_web)  
       
    58 
       
    59     for key in [k for k in env.repos if key != 'web']:
       
    60         export_path_key = export_version(**{key: comp_versions[key]})
       
    61         export_path_comp = os.path.join(export_path_key, key)
       
    62         do_sync_comp(key, export_path_comp)
       
    63         clean_export_folder(export_path_key)    
       
    64     
   289     create_config(export_path_web)
    65     create_config(export_path_web)
   290     clean_export_folder(export_path)
    66     clean_export_folder(export_path)
   291     relaunch_server()
    67     relaunch_server()
   292 
    68 
   293 @task
    69 @task
   305     finally:
    81     finally:
   306         clean_export_folder(export_path)
    82         clean_export_folder(export_path)
   307         if venv_remote_export_path:
    83         if venv_remote_export_path:
   308             clean_rsync_folder(venv_remote_export_path)
    84             clean_rsync_folder(venv_remote_export_path)
   309 
    85 
       
    86 class SyncComp(Task):
       
    87     
       
    88     def __init__(self, key):
       
    89         self.key = key
   310 
    90 
       
    91     def __get_name(self):
       
    92         return "sync_" + self.key
       
    93     
       
    94     name = property(__get_name)
       
    95     
       
    96     def run(self, version):
       
    97         print(green("sync ldt with version %s" % version))
       
    98         export_path_web = export_version(web=version)    
       
    99         export_path_web_full = os.path.join(export_path_web,'web')
       
   100         comp_versions = get_comp_versions_dict(export_path_web_full)
       
   101 
       
   102         export_path = export_version(**{self.key:comp_versions[self.key]})
       
   103         export_path_full = os.path.join(export_path,self.key)
       
   104         do_sync_comp(self.key, export_path_full)
       
   105         clean_export_folder(export_path)
       
   106         clean_export_folder(export_path_web)
       
   107         
       
   108         relaunch_server()
       
   109 
       
   110 for sync_name in [key for key in env.repos if key != 'web']:
       
   111     globals()[sync_name] = SyncComp(sync_name)