def deploy_wsgi(): """ deploy python wsgi file(s) """ remote_dir = "/".join([deployment_root(), "env", env.project_fullname, "wsgi"]) deployed = [] if env.verbosity: print env.host, "DEPLOYING wsgi", remote_dir domains = domain_sites() for domain in domains: deployed += mkdirs(remote_dir) with cd(remote_dir): u_domain = domain.replace(".", "_") filename = "%s.wsgi" % u_domain context = { "deployment_root": deployment_root(), "user": env.user, "project_name": env.project_name, "u_domain": u_domain, "root_domain": env.root_domain, } upload_template("/".join(["woven", "django-wsgi-template.txt"]), filename, context) if env.verbosity: print " * uploaded", filename # finally set the ownership/permissions # We'll use the group to allow www-data execute sudo("chown %s:www-data %s" % (env.user, filename)) run("chmod ug+xr %s" % filename) return deployed
def migration(): """ Integrate with south schema migration """ #activate env with cd('/'.join([deployment_root(),'env',env.project_fullname,'project',env.project_package_name,'sitesettings'])): #migrates all or specific env.migration venv = '/'.join([deployment_root(),'env',env.project_fullname,'bin','activate']) cmdpt1 = ' '.join(['source',venv,'&&']) sites = _get_django_sites() site_ids = sites.keys() site_ids.sort() for site in site_ids: for settings_file in _sitesettings_files(): site_settings = '.'.join([env.project_package_name,'sitesettings',settings_file.replace('.py','')]) cmdpt2 = ' '.join(["python manage.py migrate",env.migration]) if hasattr(env,"fakemigration"): cmdpt2 = ' '.join([cmdpt2,'--fake']) cmdpt2 = ''.join([cmdpt2,'--settings=',site_settings]) if env.verbosity: print " *", cmdpt2 output = sudo(' '.join([cmdpt1,cmdpt2]),user='******'% site) if env.verbosity: print output return
def deploy_project(): """ Deploy to the project directory in the virtualenv """ project_root = '/'.join([deployment_root(),'env',env.project_fullname,'project']) local_dir = os.getcwd() if env.verbosity: print env.host,"DEPLOYING project", env.project_fullname #Exclude a few things that we don't want deployed as part of the project folder rsync_exclude = ['local_settings*','*.pyc','*.log','.*','/build','/dist','/media*','/static*','/www','/public','/template*'] #make site local settings if they don't already exist _make_local_sitesettings() created = deploy_files(local_dir, project_root, rsync_exclude=rsync_exclude) if not env.patch: #hook the project into sys.path pyvers = run('python -V').split(' ')[1].split('.')[0:2] #Python x.x.x sitepackages = ''.join(['lib/python',pyvers[0],'.',pyvers[1],'/site-packages']) link_name = '/'.join([deployment_root(),'env',env.project_fullname,sitepackages,env.project_package_name]) target = '/'.join([project_root,env.project_package_name]) run(' '.join(['ln -s',target,link_name])) #make sure manage.py has exec permissions managepy = '/'.join([target,'sitesettings','manage.py']) if exists(managepy): sudo('chmod ugo+x %s'% managepy) return created
def _get_django_sites(): """ Get a list of sites as dictionaries {site_id:'domain.name'} """ deployed = version_state('deploy_project') if not env.sites and 'django.contrib.sites' in env.INSTALLED_APPS and deployed: with cd('/'.join([deployment_root(),'env',env.project_fullname,'project',env.project_package_name,'sitesettings'])): venv = '/'.join([deployment_root(),'env',env.project_fullname,'bin','activate']) #since this is the first time we run ./manage.py on the server it can be #a point of failure for installations with settings(warn_only=True): output = run(' '.join(['source',venv,'&&',"django-admin.py dumpdata sites --settings=%s.sitesettings.settings"% env.project_package_name])) if output.failed: print "ERROR: There was an error running ./manage.py on the node" print "See the troubleshooting docs for hints on how to diagnose deployment issues" if hasattr(output, 'stderr'): print output.stderr sys.exit(1) output = output.split('\n')[-1] #ignore any lines prior to the data being dumped sites = json.loads(output) env.sites = {} for s in sites: env.sites[s['pk']] = s['fields']['domain'] return env.sites
def _get_django_sites(): """ Get a list of sites as dictionaries {site_id:'domain.name'} """ deployed = version_state('deploy_project') if not env.sites and 'django.contrib.sites' in env.INSTALLED_APPS and deployed: with cd('/'.join([deployment_root(),'env',env.project_fullname,'project',env.project_package_name,'sitesettings'])): venv = '/'.join([deployment_root(),'env',env.project_fullname,'bin','activate']) #since this is the first time we run ./manage.py on the server it can be #a point of failure for installations with settings(warn_only=True): output = run(' '.join(['source',venv,'&&',"./manage.py dumpdata sites"])) if output.failed: print "ERROR: There was an error running ./manage.py on the node" print "See the troubleshooting docs for hints on how to diagnose deployment issues" if hasattr(output, 'stderr'): print output.stderr sys.exit(1) output = output.split('\n')[-1] #ignore any lines prior to the data being dumped sites = json.loads(output) env.sites = {} for s in sites: env.sites[s['pk']] = s['fields']['domain'] return env.sites
def sync_db(): """ Runs the django syncdb command """ with cd('/'.join([ deployment_root(), 'env', env.project_fullname, 'project', env.project_package_name, 'sitesettings' ])): venv = '/'.join([ deployment_root(), 'env', env.project_fullname, 'bin', 'activate' ]) sites = _get_django_sites() site_ids = sites.keys() site_ids.sort() for site in site_ids: for settings_file in _sitesettings_files(): site_settings = '.'.join([ env.project_package_name, 'sitesettings', settings_file.replace('.py', '') ]) if env.verbosity: print " * django-admin.py syncdb --noinput --settings=%s" % site_settings output = sudo(' '.join([ 'source', venv, '&&', "django-admin.py syncdb --noinput --settings=%s" % site_settings ]), user='******' % site) if env.verbosity: print output
def deploy_project(): """ Deploy to the project directory in the virtualenv """ project_root = '/'.join([deployment_root(),'env',env.project_fullname,'project']) local_dir = os.getcwd() if env.verbosity: print env.host,"DEPLOYING project", env.project_fullname #Exclude a few things that we don't want deployed as part of the project folder rsync_exclude = ['local_settings*','*.pyc','*.log','.*','/build','/dist','/media*','/static*','/www','/public','/template*'] #make site local settings if they don't already exist _make_local_sitesettings() created = deploy_files(local_dir, project_root, rsync_exclude=rsync_exclude) if not env.patch: #hook the project into sys.path remote_python_version = run('''python -c "import sys; print 'python%d.%d' % (sys.version_info.major, sys.version_info.minor)"''').strip() link_name = '/'.join([deployment_root(),'env',env.project_fullname,'lib', remote_python_version, 'site-packages',env.project_package_name]) target = '/'.join([project_root,env.project_package_name]) #create any missing dirs run('mkdir -p ' + os.path.dirname(link_name)) run(' '.join(['ln -s',target,link_name])) #make sure manage.py has exec permissions managepy = '/'.join([target,'sitesettings','manage.py']) if exists(managepy): sudo('chmod ugo+x %s'% managepy) return created
def rmvirtualenv(): """ Remove the current or ``env.project_version`` environment and all content in it """ path = '/'.join([deployment_root(), 'env', env.project_fullname]) link = '/'.join([deployment_root(), 'env', env.project_name]) if version_state('mkvirtualenv'): sudo(' '.join(['rm -rf', path])) sudo(' '.join(['rm -f', link])) sudo('rm -f /var/local/woven/%s*' % env.project_fullname) set_version_state('mkvirtualenv', delete=True)
def rmvirtualenv(): """ Remove the current or ``env.project_version`` environment and all content in it """ path = '/'.join([deployment_root(),'env',env.project_fullname]) if server_state('mkvirtualenv'): sudo(' '.join(['rm -rf',path])) set_server_state('mkvirtualenv',delete=True) #If there are no further remaining envs we'll delete the home directory to effectively teardown the project if not server_state('mkvirtualenv',prefix=True): sudo('rm -rf '+deployment_root())
def rmvirtualenv(): """ Remove the current or ``env.project_version`` environment and all content in it """ path = '/'.join([deployment_root(),'env',env.project_fullname]) link = '/'.join([deployment_root(),'env',env.project_name]) if version_state('mkvirtualenv'): sudo(' '.join(['rm -rf',path])) sudo(' '.join(['rm -f',link])) sudo('rm -f /var/local/woven/%s*'% env.project_fullname) set_version_state('mkvirtualenv',delete=True)
def sync_db(): """ Runs the django syncdb command """ with cd('/'.join([deployment_root(),'env',env.project_fullname,'project',env.project_name,'sitesettings'])): venv = '/'.join([deployment_root(),'env',env.project_fullname,'bin','activate']) if env.verbosity: print " * python manage.py syncdb --noinput" output = run(' '.join(['source',venv,'&&',"./manage.py syncdb --noinput"])) if env.verbosity: print output
def _deploy_webconf(remote_dir, template): if not 'http:' in env.MEDIA_URL: media_url = env.MEDIA_URL else: media_url = '' if not 'http:' in env.STATIC_URL: static_url = env.STATIC_URL else: static_url = '' if not static_url: static_url = env.ADMIN_MEDIA_PREFIX log_dir = '/'.join([deployment_root(), 'log']) deployed = [] users_added = [] domains = domain_sites() for d in domains: u_domain = d.name.replace('.', '_') wsgi_filename = d.settings.replace('.py', '.wsgi') site_user = ''.join(['site_', str(d.site_id)]) filename = ''.join( [remote_dir, '/', u_domain, '-', env.project_version, '.conf']) context = { "project_name": env.project_name, "deployment_root": deployment_root(), "u_domain": u_domain, "domain": d.name, "root_domain": env.root_domain, "user": env.user, "site_user": site_user, "SITE_ID": d.site_id, "host_ip": socket.gethostbyname(env.host), "wsgi_filename": wsgi_filename, "MEDIA_URL": media_url, "STATIC_URL": static_url, } upload_template('/'.join(['woven', template]), filename, context, use_sudo=True) if env.verbosity: print " * uploaded", filename #add site users if necessary site_users = _site_users() if site_user not in users_added and site_user not in site_users: add_user(username=site_user, group='www-data', site_user=True) users_added.append(site_user) if env.verbosity: print " * useradded", site_user return deployed
def mkvirtualenv(): """ Create the virtualenv project environment """ root = '/'.join([deployment_root(), 'env']) path = '/'.join([root, env.project_fullname]) dirs_created = [] if env.verbosity: print env.host, 'CREATING VIRTUALENV', path if not exists(root): dirs_created += mkdirs(root) with cd(root): run(' '.join(["virtualenv", env.project_fullname])) with cd(path): dirs_created += mkdirs('egg_cache') sudo('chown -R %s:www-data egg_cache' % env.user) sudo('chmod -R g+w egg_cache') run(''.join([ "echo 'cd ", path, '/', 'project', '/', env.project_package_name, '/sitesettings', "' > bin/postactivate" ])) sudo('chmod ugo+rwx bin/postactivate') #Create a state out = State(' '.join([env.host, 'virtualenv', path, 'created'])) out.object = dirs_created + ['bin', 'lib', 'include'] out.failed = False return out
def deploy_webconf(): """ Deploy nginx and other wsgi server site configurations to the host """ deployed = [] log_dir = '/'.join([deployment_root(), 'log']) #TODO - incorrect - check for actual package to confirm installation if webserver_list(): if env.verbosity: print env.host, "DEPLOYING webconf:" if not exists(log_dir): run('ln -s /var/log log') #deploys confs for each domain based on sites app if 'apache2' in get_packages(): deployed += _deploy_webconf('/etc/apache2/sites-available', 'django-apache-template.txt') deployed += _deploy_webconf('/etc/nginx/sites-available', 'nginx-template.txt') elif 'gunicorn' in get_packages(): deployed += _deploy_webconf('/etc/nginx/sites-available', 'nginx-gunicorn-template.txt') upload_template('woven/maintenance.html', '/var/www/nginx-default/maintenance.html', use_sudo=True) sudo('chmod ugo+r /var/www/nginx-default/maintenance.html') else: print env.host, """WARNING: Apache or Nginx not installed""" return deployed
def _make_local_sitesettings(overwrite=False): local_settings_dir = os.path.join(os.getcwd(),env.project_package_name,'sitesettings') if not os.path.exists(local_settings_dir) or overwrite: if overwrite: shutil.rmtree(local_settings_dir,ignore_errors=True) os.mkdir(local_settings_dir) f = open(os.path.join(local_settings_dir,'__init__.py'),"w") f.close() settings_file_path = os.path.join(local_settings_dir,'settings.py') if not os.path.exists(settings_file_path): root_domain = _root_domain() u_domain = root_domain.replace('.','_') output = render_to_string('woven/sitesettings.txt', {"deployment_root":deployment_root(), "site_id":"1", "project_name": env.project_name, "project_fullname": env.project_fullname, "project_package_name": env.project_package_name, "u_domain":u_domain, "domain":root_domain, "user":env, "MEDIA_URL":env.MEDIA_URL, "STATIC_URL":env.STATIC_URL} ) f = open(settings_file_path,"w+") f.writelines(output) f.close() #copy manage.py into that directory manage_path = os.path.join(os.getcwd(),env.project_package_name,'manage.py') dest_manage_path = os.path.join(os.getcwd(),env.project_package_name,'sitesettings','manage.py') shutil.copy(manage_path, dest_manage_path) return
def mkvirtualenv(): """ Create the virtualenv project environment """ root = '/'.join([deployment_root(), 'env']) path = '/'.join([root, env.project_fullname]) dirs_created = [] if env.verbosity: print env.host, 'CREATING VIRTUALENV', path if not exists(root): dirs_created += mkdirs(root) with cd(root): run(' '.join(["virtualenv", env.project_fullname])) with cd(path): dirs_created += mkdirs('egg_cache') sudo('chown -R %s:www-data egg_cache' % env.user) sudo('chmod -R g+w egg_cache') run(''.join([ "echo 'cd ", path, '/', 'project', '/', env.project_package_name, '/sitesettings', "' > bin/postactivate"])) sudo('chmod ugo+rwx bin/postactivate') #Create a state out = State(' '.join([env.host, 'virtualenv', path, 'created'])) out.object = dirs_created + ['bin', 'lib', 'include'] out.failed = False return out
def deploy_templates(): """ Deploy any templates from your shortest TEMPLATE_DIRS setting. """ deployed = None if not hasattr(env, 'project_template_dir'): # The normal pattern would mean the shortest path is the main # one. It's probably the last listed. length = 1000 for directory in env.TEMPLATE_DIRS: if directory: len_dir = len(directory) if len_dir < length: length = len_dir env.project_template_dir = directory if hasattr(env, 'project_template_dir'): remote_dir = '/'.join([ deployment_root(), 'env', env.project_fullname, 'templates', ]) if env.verbosity: print env.host, "DEPLOYING templates", remote_dir deployed = deploy_files(env.project_template_dir, remote_dir) return deployed
def deploy_static(): """ Deploy static (application) versioned media """ if (not env.STATIC_ROOT and not env.ADMIN_MEDIA_PREFIX) or 'http://' in env.STATIC_URL: return remote_dir = '/'.join([deployment_root(),'env',env.project_fullname,'static']) #if app media is not handled by django-staticfiles we can install admin media by default if 'django.contrib.admin' in env.INSTALLED_APPS and not env.STATIC_ROOT: if env.MEDIA_URL in env.ADMIN_MEDIA_PREFIX: print "ERROR: Your ADMIN_MEDIA_PREFIX must not be on the same path as your MEDIA_URL" print "for example you cannot use MEDIA_URL = /media/ and ADMIN_MEDIA_PREFIX = /media/admin/" sys.exit(1) env.STATIC_URL = env.ADMIN_MEDIA_PREFIX admin = AdminMediaHandler('DummyApp') local_dir = admin.media_dir remote_dir = ''.join([remote_dir,env.ADMIN_MEDIA_PREFIX]) else: if env.MEDIA_URL in env.STATIC_URL: print "ERROR: Your STATIC_URL must not be on the same path as your MEDIA_URL" print "for example you cannot use MEDIA_URL = /media/ and STATIC_URL = /media/static/" sys.exit(1) elif env.STATIC_ROOT: local_dir = env.STATIC_ROOT static_url = env.STATIC_URL[1:] if static_url: remote_dir = '/'.join([remote_dir,static_url]) else: return if env.verbosity: print env.host,"DEPLOYING static",remote_dir return deploy_files(local_dir,remote_dir)
def deploy_db(rollback=False): """ Deploy a sqlite database from development """ db_name = ''.join([env.project_name,'.db']) db_dir = '/'.join([deployment_root(),'database']) db_path = '/'.join([db_dir,db_name]) if not rollback: if env.DEFAULT_DATABASE_ENGINE=='django.db.backends.sqlite3' and not exists(db_path): if env.verbosity: print env.host,"DEPLOYING DEFAULT SQLITE DATABASE",db_path if not os.path.exists(env.DEFAULT_DATABASE_NAME) or not env.DEFAULT_DATABASE_NAME: print "ERROR: the database does not exist. Run python manage.py syncdb to create your database first." sys.exit(1) run('mkdir -p '+db_dir) put(env.DEFAULT_DATABASE_NAME,db_path) #directory and file must be writable by webserver sudo("chown -R %s:www-data %s"% (env.user,db_dir)) sudo("chmod -R ug+w %s"% db_dir) elif rollback and env.DEFAULT_DATABASE_ENGINE=='django.db.backends.sqlite3': if env.INTERACTIVE: delete = confirm('DELETE the database on the host?',default=False) if delete: run('rm -f '+db_name) return
def deploy_static(): """ Deploy static (application) versioned media """ if not env.STATIC_URL or 'http://' in env.STATIC_URL: return from django.core.servers.basehttp import AdminMediaHandler remote_dir = '/'.join( [deployment_root(), 'env', env.project_fullname, 'static']) m_prefix = len(env.MEDIA_URL) #if app media is not handled by django-staticfiles we can install admin media by default if 'django.contrib.admin' in env.INSTALLED_APPS and not 'django.contrib.staticfiles' in env.INSTALLED_APPS: if env.MEDIA_URL and env.MEDIA_URL == env.ADMIN_MEDIA_PREFIX[:m_prefix]: print "ERROR: Your ADMIN_MEDIA_PREFIX (Application media) must not be on the same path as your MEDIA_URL (User media)" sys.exit(1) admin = AdminMediaHandler('DummyApp') local_dir = admin.base_dir remote_dir = ''.join([remote_dir, env.ADMIN_MEDIA_PREFIX]) else: if env.MEDIA_URL and env.MEDIA_URL == env.STATIC_URL[:m_prefix]: print "ERROR: Your STATIC_URL (Application media) must not be on the same path as your MEDIA_URL (User media)" sys.exit(1) elif env.STATIC_ROOT: local_dir = env.STATIC_ROOT static_url = env.STATIC_URL[1:] if static_url: remote_dir = '/'.join([remote_dir, static_url]) else: return if env.verbosity: print env.host, "DEPLOYING static", remote_dir return deploy_files(local_dir, remote_dir)
def deploy_webconf(): """ Deploy nginx and other wsgi server site configurations to the host """ deployed = [] log_dir = '/'.join([deployment_root(),'log']) #TODO - incorrect - check for actual package to confirm installation if webserver_list(): if env.verbosity: print env.host,"DEPLOYING webconf:" if not exists(log_dir): run('ln -s /var/log log') #deploys confs for each domain based on sites app if 'apache2' in get_packages(): deployed += _deploy_webconf('/etc/apache2/sites-available','django-apache-template.txt') deployed += _deploy_webconf('/etc/nginx/sites-available','nginx-template.txt') elif 'gunicorn' in get_packages(): deployed += _deploy_webconf('/etc/nginx/sites-available','nginx-gunicorn-template.txt') if not exists('/var/www/nginx-default'): sudo('mkdir /var/www/nginx-default') upload_template('woven/maintenance.html','/var/www/nginx-default/maintenance.html',use_sudo=True) sudo('chmod ugo+r /var/www/nginx-default/maintenance.html') else: print env.host,"""WARNING: Apache or Nginx not installed""" return deployed
def deploy_static(): """ Deploy static (application) versioned media """ if not env.STATIC_URL or 'http://' in env.STATIC_URL: return from django.core.servers.basehttp import AdminMediaHandler remote_dir = '/'.join([deployment_root(),'env',env.project_fullname,'static']) m_prefix = len(env.MEDIA_URL) #if app media is not handled by django-staticfiles we can install admin media by default if 'django.contrib.admin' in env.INSTALLED_APPS and not 'django.contrib.staticfiles' in env.INSTALLED_APPS: if env.MEDIA_URL and env.MEDIA_URL == env.ADMIN_MEDIA_PREFIX[:m_prefix]: print "ERROR: Your ADMIN_MEDIA_PREFIX (Application media) must not be on the same path as your MEDIA_URL (User media)" sys.exit(1) admin = AdminMediaHandler('DummyApp') local_dir = admin.base_dir remote_dir = ''.join([remote_dir,env.ADMIN_MEDIA_PREFIX]) else: if env.MEDIA_URL and env.MEDIA_URL == env.STATIC_URL[:m_prefix]: print "ERROR: Your STATIC_URL (Application media) must not be on the same path as your MEDIA_URL (User media)" sys.exit(1) elif env.STATIC_ROOT: local_dir = env.STATIC_ROOT static_url = env.STATIC_URL[1:] if static_url: remote_dir = '/'.join([remote_dir,static_url]) else: return if env.verbosity: print env.host,"DEPLOYING static",remote_dir return deploy_files(local_dir,remote_dir)
def _deploy_webconf(remote_dir,template): if not 'http:' in env.MEDIA_URL: media_url = env.MEDIA_URL else: media_url = '' if not 'http:' in env.STATIC_URL: static_url = env.STATIC_URL else: static_url = '' if not static_url: static_url = env.ADMIN_MEDIA_PREFIX log_dir = '/'.join([deployment_root(),'log']) deployed = [] users_added = [] domains = domain_sites() for d in domains: u_domain = d.name.replace('.','_') wsgi_filename = d.settings.replace('.py','.wsgi') site_user = ''.join(['site_',str(d.site_id)]) filename = ''.join([remote_dir,'/',u_domain,'-',env.project_version,'.conf']) context = {"project_name": env.project_name, "deployment_root":deployment_root(), "u_domain":u_domain, "domain":d.name, "root_domain":env.root_domain, "user":env.user, "site_user":site_user, "SITE_ID":d.site_id, "host_ip":socket.gethostbyname(env.host), "wsgi_filename":wsgi_filename, "MEDIA_URL":media_url, "STATIC_URL":static_url, } upload_template('/'.join(['woven',template]), filename, context, use_sudo=True) if env.verbosity: print " * uploaded", filename #add site users if necessary site_users = _site_users() if site_user not in users_added and site_user not in site_users: add_user(username=site_user,group='www-data',site_user=True) users_added.append(site_user) if env.verbosity: print " * useradded",site_user return deployed
def _get_django_sites(): """ Get a list of sites as dictionaries {site_id:'domain.name'} """ deployed = server_state("deploy_project") if not env.sites and "django.contrib.sites" in env.INSTALLED_APPS and deployed: with cd( "/".join([deployment_root(), "env", env.project_fullname, "project", env.project_name, "sitesettings"]) ): venv = "/".join([deployment_root(), "env", env.project_fullname, "bin", "activate"]) output = run(" ".join(["source", venv, "&&", "./manage.py dumpdata sites"])) sites = json.loads(output) env.sites = {} for s in sites: env.sites[s["pk"]] = s["fields"]["domain"] return env.sites
def deploy_files(local_dir, remote_dir, pattern = '',rsync_exclude=['*.pyc','.*'], use_sudo=False): """ Generic deploy function for cases where one or more files are being deployed to a host. Wraps around ``rsync_project`` and stages files locally and/or remotely for network efficiency. ``local_dir`` is the directory that will be deployed. ``remote_dir`` is the directory the files will be deployed to. Directories will be created if necessary. Note: Unlike other ways of deploying files, all files under local_dir will be deployed into remote_dir. This is the equivalent to cp -R local_dir/* remote_dir. ``pattern`` finds all the pathnames matching a specified glob pattern relative to the local_dir according to the rules used by the Unix shell. ``pattern`` enhances the basic functionality by allowing the python | to include multiple patterns. eg '*.txt|Django*' ``rsync_exclude`` as per ``rsync_project`` Returns a list of directories and files created on the host. """ #normalise paths if local_dir[-1] == os.sep: local_dir = local_dir[:-1] if remote_dir[-1] == '/': remote_dir = remote_dir[:-1] created_list = [] staging_dir = local_dir #resolve pattern into a dir:filename dict local_files = _get_local_files(local_dir,pattern) #If we are only copying specific files or rendering templates we need to stage locally if local_files: staging_dir = _stage_local_files(local_dir, local_files) remote_staging_dir = os.path.join(deployment_root(), '.staging') if not exists(remote_staging_dir): run(' '.join(['mkdir -pv',remote_staging_dir])).split('\n') created_list = [remote_staging_dir] #upload into remote staging rsync_project(local_dir=staging_dir,remote_dir=remote_staging_dir,exclude=rsync_exclude,delete=True) #create the final destination created_dir_list = mkdirs(remote_dir, use_sudo) if not os.listdir(staging_dir): return created_list func = use_sudo and sudo or run #cp recursively -R from the staging to the destination and keep a list remote_base_path = '/'.join([remote_staging_dir,os.path.basename(local_dir),'*']) copy_file_list = func(' '.join(['cp -Ruv',remote_base_path,remote_dir])).split('\n') if copy_file_list[0]: created_list += [file.split(' ')[2][1:-1] for file in copy_file_list if file] #cleanup any tmp staging dir if staging_dir <> local_dir: shutil.rmtree(staging_dir,ignore_errors=True) return created_list
def sync_db(): """ Runs the django syncdb command """ with cd('/'.join([deployment_root(),'env',env.project_fullname,'project',env.project_package_name,'sitesettings'])): venv = '/'.join([deployment_root(),'env',env.project_fullname,'bin','activate']) sites = _get_django_sites() site_ids = sites.keys() site_ids.sort() for site in site_ids: for settings_file in _sitesettings_files(): site_settings = '.'.join([env.project_package_name,'sitesettings',settings_file.replace('.py','')]) if env.verbosity: print " * python manage.py syncdb --noinput --settings=%s"% site_settings output = sudo(' '.join(['source',venv,'&&',"./manage.py syncdb --noinput --settings=%s"% site_settings]), user='******'% site) if env.verbosity: print output
def handle_host(self,*args, **options): opts = options.get('options') command = args[0] root = deployment_root() path = '%s/%s/env/%s/project/%s/'% (root,root_domain(),env.project_fullname,env.project_name) pythonpath = '%s/%s/env/%s/bin/python'% (root,env.root_domain,env.project_fullname) with cd(path): result = run(' '.join([pythonpath,'manage.py',command,opts])) if env.verbosity: print result
def active_version(): """ Determine the current active version on the server Just examine the which environment is symlinked """ link = '/'.join([deployment_root(), 'env', env.project_name]) if not exists(link): return None active = os.path.split(run('ls -al ' + link).split(' -> ')[1])[1] return active
def active_version(): """ Determine the current active version on the server Just examine the which environment is symlinked """ link = '/'.join([deployment_root(),'env',env.project_name]) if not exists(link): return None active = os.path.split(run('ls -al '+link).split(' -> ')[1])[1] return active
def migration(): """ Integrate with south schema migration """ #activate env with cd('/'.join([deployment_root(),'env',env.project_fullname,'project',env.project_name,'sitesettings'])): #migrates all or specific env.migration venv = '/'.join([deployment_root(),'env',env.project_fullname,'bin','activate']) cmdpt1 = ' '.join(['source',venv,'&&']) cmdpt2 = ' '.join(["python manage.py migrate",env.migration]) if hasattr(env,"fakemigration"): cmdpt2 = ' '.join([cmdpt2,'--fake']) if env.verbosity: print " *", cmdpt2 output = run(' '.join([cmdpt1,cmdpt2])) if env.verbosity: print output return
def deploy_project(): """ Deploy to the project directory in the virtualenv """ project_root = '/'.join( [deployment_root(), 'env', env.project_fullname, 'project']) local_dir = os.getcwd() if env.verbosity: print env.host, "DEPLOYING project", env.project_fullname #Exclude a few things that we don't want deployed as part of the project folder rsync_exclude = [ 'local_settings*', '*.pyc', '*.log', '.*', '/build', '/dist', '/media*', '/static*', '/www', '/public', '/template*' ] #make site local settings if they don't already exist _make_local_sitesettings() created = deploy_files(local_dir, project_root, rsync_exclude=rsync_exclude) if not env.patch: #hook the project into sys.path pyvers = run('python -V').split(' ')[1].split('.')[0:2] #Python x.x.x sitepackages = ''.join( ['lib/python', pyvers[0], '.', pyvers[1], '/site-packages']) link_name = '/'.join([ deployment_root(), 'env', env.project_fullname, sitepackages, env.project_package_name ]) target = '/'.join([project_root, env.project_package_name]) run(' '.join(['ln -s', target, link_name])) #make sure manage.py has exec permissions managepy = '/'.join([target, 'sitesettings', 'manage.py']) if exists(managepy): sudo('chmod ugo+x %s' % managepy) return created
def deploy_sitesettings(): """ Deploy to the project directory in the virtualenv """ sitesettings = '/'.join([deployment_root(),'env',env.project_fullname,'project',env.project_name,'sitesettings']) local_dir = os.path.join(os.getcwd(),env.project_name,'sitesettings') created = deploy_files(local_dir, sitesettings) if env.verbosity and created: print env.host,"DEPLOYING sitesettings" for path in created: tail = path.split('/')[-1] print ' * uploaded',tail
def deploy_project(): """ Deploy to the project directory in the virtualenv """ project_root = '/'.join([deployment_root(),'env',env.project_fullname,'project']) local_dir = os.getcwd() if env.verbosity: print env.host,"DEPLOYING project", env.project_fullname #Exclude a few things that we don't want deployed as part of the project folder rsync_exclude = ['*.pyc','*.log','.*','/build','/dist','/media*','/static*','/www','/public','/templates'] #make site local settings if they don't already exist _make_local_sitesettings() created = deploy_files(local_dir, project_root, rsync_exclude=rsync_exclude) if not env.patch: #hook the project into sys.path - #TODO make the python version not fixed link_name = '/'.join([deployment_root(),'env',env.project_fullname,'lib/python2.6/site-packages',env.project_name]) target = '/'.join([project_root,env.project_name]) run(' '.join(['ln -s',target,link_name])) return created
def _deploy_webconf(remote_dir, template): if not "http:" in env.MEDIA_URL: media_url = env.MEDIA_URL else: media_url = "" if not "http:" in env.STATIC_URL: static_url = env.STATIC_URL else: static_url = "" if not static_url: static_url = env.ADMIN_MEDIA_PREFIX log_dir = "/".join([deployment_root(), "log"]) deployed = [] domains = domain_sites() for d in domains: u_domain = d.replace(".", "_") filename = "".join([remote_dir, "/", u_domain, "-", env.project_version, ".conf"]) context = { "project_name": env.project_name, "deployment_root": deployment_root(), "u_domain": u_domain, "domain": d, "root_domain": env.root_domain, "user": env.user, "host_ip": socket.gethostbyname(env.host), "media_url": media_url, "static_url": static_url, } upload_template("/".join(["woven", template]), filename, context, use_sudo=True) if env.verbosity: print " * uploaded", filename return deployed
def deploy_db(rollback=False): """ Deploy a sqlite database from development """ if not rollback: if env.DEFAULT_DATABASE_ENGINE == 'django.db.backends.sqlite3': db_dir = '/'.join([deployment_root(), 'database']) db_name = ''.join([env.project_name, '_', 'site_1', '.db']) dest_db_path = '/'.join([db_dir, db_name]) if exists(dest_db_path): return if env.verbosity: print env.host, "DEPLOYING DEFAULT SQLITE DATABASE" if not env.DEFAULT_DATABASE_NAME: print "ERROR: A database name has not been defined in your Django settings file" sys.exit(1) if env.DEFAULT_DATABASE_NAME[0] not in [os.path.sep, '.']: #relative path db_path = os.path.join(os.getcwd(), env.project_package_name, env.DEFAULT_DATABASE_NAME) elif env.DEFAULT_DATABASE_NAME[:2] == '..': print "ERROR: Use a full expanded path to the database in your Django settings" sys.exit(1) else: db_path = env.DEFAULT_DATABASE_NAME if not db_path or not os.path.exists(db_path): print "ERROR: the database %s does not exist. \nRun python manage.py syncdb to create your database locally first, or check your settings." % db_path sys.exit(1) db_name = os.path.split(db_path)[1] run('mkdir -p ' + db_dir) put(db_path, dest_db_path) #directory and file must be writable by webserver sudo("chown -R %s:www-data %s" % (env.user, db_dir)) sudo("chmod -R ug+w %s" % db_dir) elif env.DEFAULT_DATABASE_ENGINE == 'django.db.backends.': print "ERROR: The default database engine has not been defined in your Django settings file" print "At a minimum you must define an sqlite3 database for woven to deploy, or define a database that is managed outside of woven." sys.exit(1) elif rollback and env.DEFAULT_DATABASE_ENGINE == 'django.db.backends.sqlite3': if env.INTERACTIVE: delete = confirm('DELETE the database on the host?', default=False) if delete: run('rm -f ' + db_name) return
def migration(): """ Integrate with south schema migration """ #activate env with cd('/'.join([ deployment_root(), 'env', env.project_fullname, 'project', env.project_package_name, 'sitesettings' ])): #migrates all or specific env.migration venv = '/'.join([ deployment_root(), 'env', env.project_fullname, 'bin', 'activate' ]) cmdpt1 = ' '.join(['source', venv, '&&']) sites = _get_django_sites() site_ids = sites.keys() site_ids.sort() for site in site_ids: for settings_file in _sitesettings_files(): site_settings = '.'.join([ env.project_package_name, 'sitesettings', settings_file.replace('.py', '') ]) cmdpt2 = ' '.join(["django-admin.py migrate", env.migration]) if hasattr(env, "fakemigration"): cmdpt2 = ' '.join([cmdpt2, '--fake']) cmdpt2 = ''.join([cmdpt2, '--settings=', site_settings]) if env.verbosity: print " *", cmdpt2 output = sudo(' '.join([cmdpt1, cmdpt2]), user='******' % site) if env.verbosity: print output return
def deploy_db(rollback=False): """ Deploy a sqlite database from development """ if not rollback: if env.DEFAULT_DATABASE_ENGINE=='django.db.backends.sqlite3': db_dir = '/'.join([deployment_root(),'database']) db_name = ''.join([env.project_name,'_','site_1','.db']) dest_db_path = '/'.join([db_dir,db_name]) if exists(dest_db_path): return if env.verbosity: print env.host,"DEPLOYING DEFAULT SQLITE DATABASE" if not env.DEFAULT_DATABASE_NAME: print "ERROR: A database name has not been defined in your Django settings file" sys.exit(1) if env.DEFAULT_DATABASE_NAME[0] not in [os.path.sep,'.']: #relative path db_path = os.path.join(os.getcwd(),env.project_package_name,env.DEFAULT_DATABASE_NAME) elif env.DEFAULT_DATABASE_NAME[:2] == '..': print "ERROR: Use a full expanded path to the database in your Django settings" sys.exit(1) else: db_path = env.DEFAULT_DATABASE_NAME if not db_path or not os.path.exists(db_path): print "ERROR: the database %s does not exist. \nRun python manage.py syncdb to create your database locally first, or check your settings."% db_path sys.exit(1) db_name = os.path.split(db_path)[1] run('mkdir -p '+db_dir) put(db_path,dest_db_path) #directory and file must be writable by webserver sudo("chown -R %s:www-data %s"% (env.user,db_dir)) sudo("chmod -R ug+w %s"% db_dir) elif env.DEFAULT_DATABASE_ENGINE=='django.db.backends.': print "ERROR: The default database engine has not been defined in your Django settings file" print "At a minimum you must define an sqlite3 database for woven to deploy, or define a database that is managed outside of woven." sys.exit(1) elif rollback and env.DEFAULT_DATABASE_ENGINE=='django.db.backends.sqlite3': if env.INTERACTIVE: delete = confirm('DELETE the database on the host?',default=False) if delete: run('rm -f '+db_name) return
def deploy_sitesettings(): """ Deploy to the project directory in the virtualenv """ sitesettings = '/'.join([ deployment_root(), 'env', env.project_fullname, 'project', env.project_package_name, 'sitesettings' ]) local_dir = os.path.join(os.getcwd(), env.project_package_name, 'sitesettings') created = deploy_files(local_dir, sitesettings) if env.verbosity and created: print env.host, "DEPLOYING sitesettings" for path in created: tail = path.split('/')[-1] print ' * uploaded', tail
def deploy_webconf(): """ Deploy apache & nginx site configurations to the host """ deployed = [] log_dir = "/".join([deployment_root(), "log"]) # TODO - incorrect - check for actual package to confirm installation if exists("/etc/apache2/sites-enabled/") and exists("/etc/nginx/sites-enabled"): if env.verbosity: print env.host, "DEPLOYING webconf:" if not exists(log_dir): run("ln -s /var/log log") deployed += _deploy_webconf("/etc/apache2/sites-available", "django-apache-template.txt") deployed += _deploy_webconf("/etc/nginx/sites-available", "nginx-template.txt") upload_template("woven/maintenance.html", "/var/www/nginx-default/maintenance.html", use_sudo=True) sudo("chmod ugo+r /var/www/nginx-default/maintenance.html") else: print env.host, """WARNING: Apache or Nginx not installed""" return deployed
def deploy_public(): """ Deploy MEDIA_ROOT unversioned on host """ if not env.MEDIA_ROOT or 'http://' in env.MEDIA_URL: return local_dir = env.MEDIA_ROOT remote_dir = '/'.join([deployment_root(),'public']) media_url = env.MEDIA_URL[1:] if media_url: remote_dir = '/'.join([remote_dir,media_url]) if env.verbosity: print env.host,"DEPLOYING public",remote_dir deployed = deploy_files(local_dir,remote_dir) #make writable for www-data for file uploads sudo("chown -R www-data:sudo %s" % remote_dir) sudo("chmod -R ug+w %s"% remote_dir) return deployed
def deploy_media(): """ Deploy MEDIA_ROOT unversioned on host """ if not env.MEDIA_URL or not env.MEDIA_ROOT or 'http://' in env.MEDIA_URL: return local_dir = env.MEDIA_ROOT remote_dir = '/'.join([deployment_root(), 'public']) media_url = env.MEDIA_URL[1:] if media_url: remote_dir = '/'.join([remote_dir, media_url]) if env.verbosity: print env.host, "DEPLOYING media", remote_dir deployed = deploy_files(local_dir, remote_dir) #make writable for www-data for file uploads sudo("chown -R www-data:sudo %s" % remote_dir) sudo("chmod -R ug+w %s" % remote_dir) return deployed
def _make_local_sitesettings(overwrite=False): local_settings_dir = os.path.join(os.getcwd(), env.project_package_name, 'sitesettings') if not os.path.exists(local_settings_dir) or overwrite: if overwrite: shutil.rmtree(local_settings_dir, ignore_errors=True) os.mkdir(local_settings_dir) f = open(os.path.join(local_settings_dir, '__init__.py'), "w") f.close() settings_file_path = os.path.join(local_settings_dir, 'settings.py') if not os.path.exists(settings_file_path): root_domain = _root_domain() u_domain = root_domain.replace('.', '_') output = render_to_string( 'woven/sitesettings.txt', { "deployment_root": deployment_root(), "site_id": "1", "project_name": env.project_name, "project_fullname": env.project_fullname, "project_package_name": env.project_package_name, "u_domain": u_domain, "domain": root_domain, "user": env, "MEDIA_URL": env.MEDIA_URL, "STATIC_URL": env.STATIC_URL }) f = open(settings_file_path, "w+") f.writelines(output) f.close() if env.verbosity: print "Created local sitesettings folder and default settings file" #copy manage.py into that directory manage_path = os.path.join(os.getcwd(), env.project_package_name, 'manage.py') dest_manage_path = os.path.join(os.getcwd(), env.project_package_name, 'sitesettings', 'manage.py') shutil.copy(manage_path, dest_manage_path) return
def _make_local_sitesettings(overwrite=False): local_settings_dir = os.path.join(os.getcwd(),env.project_name,'sitesettings') if not os.path.exists(local_settings_dir) or overwrite: if overwrite: shutil.rmtree(local_settings_dir,ignore_errors=True) os.mkdir(local_settings_dir) f = open(os.path.join(local_settings_dir,'__init__.py'),"w") f.close() settings_file_path = os.path.join(local_settings_dir,'settings.py') if not os.path.exists(settings_file_path): root_domain = _root_domain() u_domain = root_domain.replace('.','_') output = render_to_string('woven/sitesettings.txt', {"deployment_root":deployment_root(), "site_id":"1", "project_name": env.project_name, "project_fullname": env.project_fullname, "u_domain":u_domain, "domain":root_domain, "user":env.user}, ) f = open(settings_file_path,"w+") f.writelines(output) f.close() #create a convenience settings file link for the first site settings_file_path = os.path.join(local_settings_dir,''.join([u_domain,'.py'])) if not os.path.exists(settings_file_path): f = open(settings_file_path, "w+") f.write("from %s.sitesettings.settings import *"% env.project_name) f.write("\nSITE_ID=1\n") f.close() #copy manage.py into that directory manage_path = os.path.join(os.getcwd(),env.project_name,'manage.py') dest_manage_path = os.path.join(os.getcwd(),env.project_name,'sitesettings','manage.py') shutil.copy(manage_path, dest_manage_path) return
def deploy_templates(): """ Deploy any templates from your shortest TEMPLATE_DIRS setting """ deployed = None if not hasattr(env, 'project_template_dir'): #the normal pattern would mean the shortest path is the main one. #its probably the last listed length = 1000 for dir in env.TEMPLATE_DIRS: if dir: len_dir = len(dir) if len_dir < length: length = len_dir env.project_template_dir = dir if hasattr(env, 'project_template_dir'): remote_dir = '/'.join( [deployment_root(), 'env', env.project_fullname, 'templates']) if env.verbosity: print env.host, "DEPLOYING templates", remote_dir deployed = deploy_files(env.project_template_dir, remote_dir) return deployed
def activate(): """ Activates the version specified in ``env.project_version`` if it is different from the current active version. An active version is just the version that is symlinked. """ env_path = '/'.join([deployment_root(),'env',env.project_fullname]) if not exists(env_path): print env.host,"ERROR: The version",env.project_version,"does not exist at" print env_path sys.exit(1) active = active_version() if env.patch or active <> env.project_fullname: stop_webservers() if not env.patch and active <> env.project_fullname: if env.verbosity: print env.host, "ACTIVATING version", env_path if not env.nomigration: sync_db() #south migration if 'south' in env.INSTALLED_APPS and not env.nomigration and not env.manualmigration: migration() if env.manualmigration or env.MANUAL_MIGRATION: manual_migration() #activate sites activate_sites = [''.join([d.replace('.','_'),'-',env.project_version,'.conf']) for d in domain_sites()] site_paths = ['/etc/apache2','/etc/nginx'] #disable existing sites for path in site_paths: for site in _ls_sites('/'.join([path,'sites-enabled'])): if site not in activate_sites: sudo("rm %s/sites-enabled/%s"% (path,site)) #activate new sites for path in site_paths: for site in activate_sites: if not exists('/'.join([path,'sites-enabled',site])): sudo("chmod 644 %s" % '/'.join([path,'sites-available',site])) sudo("ln -s %s/sites-available/%s %s/sites-enabled/%s"% (path,site,path,site)) if env.verbosity: print " * enabled", "%s/sites-enabled/%s"% (path,site) #delete existing symlink ln_path = '/'.join([deployment_root(),'env',env.project_name]) run('rm -f '+ln_path) run('ln -s %s %s'% (env_path,ln_path)) if env.verbosity: print env.host,env.project_fullname, "ACTIVATED" else: if env.verbosity and not env.patch: print env.project_fullname,"is the active version" if env.patch or active <> env.project_fullname: start_webservers() print return
def deploy_wsgi(): """ deploy python wsgi file(s) """ if 'libapache2-mod-wsgi' in get_packages(): remote_dir = '/'.join( [deployment_root(), 'env', env.project_fullname, 'wsgi']) wsgi = 'apache2' elif 'gunicorn' in get_packages(): remote_dir = '/etc/init' wsgi = 'gunicorn' deployed = [] #ensure project apps path is also added to environment variables as well as wsgi if env.PROJECT_APPS_PATH: pap = '/'.join([ deployment_root(), 'env', env.project_name, 'project', env.project_package_name, env.PROJECT_APPS_PATH ]) pap = ''.join(['export PYTHONPATH=$PYTHONPATH:', pap]) postactivate = '/'.join([deployment_root(), 'env', 'postactivate']) if not exists(postactivate): append('#!/bin/bash', postactivate) run('chmod +x %s' % postactivate) if not contains('PYTHONPATH', postactivate): append(pap, postactivate) if env.verbosity: print env.host, "DEPLOYING wsgi", wsgi, remote_dir for file in _sitesettings_files(): deployed += mkdirs(remote_dir) with cd(remote_dir): settings_module = file.replace('.py', '') context = { "deployment_root": deployment_root(), "user": env.user, "project_name": env.project_name, "project_package_name": env.project_package_name, "project_apps_path": env.PROJECT_APPS_PATH, "settings": settings_module, } if wsgi == 'apache2': filename = file.replace('.py', '.wsgi') upload_template( '/'.join(['woven', 'django-wsgi-template.txt']), filename, context, ) elif wsgi == 'gunicorn': filename = 'gunicorn-%s.conf' % env.project_name upload_template('/'.join(['woven', 'gunicorn.conf']), filename, context, backup=False, use_sudo=True) if env.verbosity: print " * uploaded", filename #finally set the ownership/permissions #We'll use the group to allow www-data execute if wsgi == 'apache2': sudo("chown %s:www-data %s" % (env.user, filename)) run("chmod ug+xr %s" % filename) elif wsgi == 'gunicorn': sudo("chown root:root %s" % filename) sudo("chmod go+r %s" % filename) return deployed
def pip_install_requirements(): """ Install on current installed virtualenv version from a pip bundle [dist/project name-version].zip or pip ``req.txt``|``requirements.txt`` or a env.pip_requirements list. By default it will look for a zip bundle in the dist directory first then a requirements file. The limitations of installing requirements are that you cannot point directly to packages in your local filesystem. In this case you would bundle instead. """ if not version_state('mkvirtualenv'): print env.host, 'Error: Cannot run pip_install_requirements. A virtualenv is not created for this version. Run mkvirtualenv first' return if env.verbosity: print env.host, 'PIP INSTALLING REQUIREMENTS:' #Remove any pre-existing pip-log from any previous failed installation pip_log_dir = '/'.join(['/home', env.user, '.pip']) if exists(pip_log_dir): run('rm -f %s/*.txt' % pip_log_dir) #determine what req files or bundle files we need to deploy if not env.PIP_REQUIREMENTS: req_files = {}.fromkeys(glob('req*')) else: req_files = {}.fromkeys(env.PIP_REQUIREMENTS) for key in req_files: bundle = ''.join([key.split('.')[0], '.zip']) if os.path.exists(os.path.join('dist', bundle)): req_files[key] = bundle #determine the django version file_patterns = '' django_version = get_version() svn_version = django_version.find('SVN') if svn_version > -1: django_version = django_version[svn_version + 4:] django_req = ''.join([ '-e svn+http://code.djangoproject.com/svn/django/trunk@', django_version, '#egg=Django' ]) else: other_builds = ['alpha', 'beta', 'rc'] for b in other_builds: if b in django_version: print "ERROR: Unsupported Django version", django_version print "Define a DJANGO_REQUIREMENT pointing to the tar.gz for", django_version print "and re-deploy, or use the official or SVN release of Django." sys.exit(1) django_req = ''.join(['Django==', django_version]) #if no requirements file exists create one if not req_files: f = open("requirements.txt", "w+") text = render_to_string('woven/requirements.txt', {'django': django_req}) f.write(text) f.close() if env.verbosity: print "Created local requirements.txt" req_files["requirements.txt"] = '' req_files_list = req_files.keys() req_files_list.sort() #patterns for bundles if req_files: file_patterns = '|'.join([file_patterns, 'req*.zip']) #create a pip cache & src directory cache = '/'.join([deployment_root(), '.pip', 'cache']) src = '/'.join([deployment_root(), '.pip', 'src']) deployed = mkdirs(cache) deployed += mkdirs(src) #deploy bundles and any local copy of django local_dir = os.path.join(os.getcwd(), 'dist') remote_dir = '/'.join( [deployment_root(), 'env', env.project_fullname, 'dist']) if os.path.exists(local_dir): if file_patterns: deployed += deploy_files(local_dir, remote_dir, pattern=file_patterns) #deploy any requirement files deployed += deploy_files(os.getcwd(), remote_dir, pattern='req*') #install in the env out = State(' '.join([env.host, 'pip install requirements'])) python_path = '/'.join( [deployment_root(), 'env', env.project_fullname, 'bin', 'python']) with settings(warn_only=True): with cd(remote_dir): for req in req_files_list: bundle = req_files[req] if bundle: req = bundle if env.verbosity: print ' * installing', req if '.zip' in req.lower(): install = run( 'pip install %s -q --environment=%s --log=/home/%s/.pip/%s_pip_log.txt' % (req, python_path, env.user, req.replace('.', '_'))) else: install = run( 'pip install -q --environment=%s --src=%s --download-cache=%s --requirement=%s --log=/home/%s/.pip/%s_pip_log.txt' % (python_path, src, cache, req, env.user, req.replace('.', '_'))) if install.failed: out.failed = True out.stderr += ' '.join( [env.host, "ERROR INSTALLING", req, '\n']) out.object = deployed if out.failed: print out.stderr print "Review the pip install logs at %s/.pip and re-deploy" % deployment_root( ) sys.exit(1) return out
def activate(): """ Activates the version specified in ``env.project_version`` if it is different from the current active version. An active version is just the version that is symlinked. """ env_path = '/'.join([deployment_root(), 'env', env.project_fullname]) if not exists(env_path): print env.host, "ERROR: The version", env.project_version, "does not exist at" print env_path sys.exit(1) active = active_version() servers = webserver_list() if env.patch or active <> env.project_fullname: for s in servers: stop_webserver(s) if not env.patch and active <> env.project_fullname: if env.verbosity: print env.host, "ACTIVATING version", env_path if not env.nomigration: sync_db() #south migration if 'south' in env.INSTALLED_APPS and not env.nomigration and not env.manualmigration: migration() if env.manualmigration or env.MANUAL_MIGRATION: manual_migration() #activate sites activate_sites = [ ''.join( [d.name.replace('.', '_'), '-', env.project_version, '.conf']) for d in domain_sites() ] if 'apache2' in get_packages(): site_paths = ['/etc/apache2', '/etc/nginx'] else: site_paths = ['/etc/nginx'] #disable existing sites for path in site_paths: for site in _ls_sites('/'.join([path, 'sites-enabled'])): if site not in activate_sites: sudo("rm %s/sites-enabled/%s" % (path, site)) #activate new sites for path in site_paths: for site in activate_sites: if not exists('/'.join([path, 'sites-enabled', site])): sudo("chmod 644 %s" % '/'.join([path, 'sites-available', site])) sudo("ln -s %s/sites-available/%s %s/sites-enabled/%s" % (path, site, path, site)) if env.verbosity: print " * enabled", "%s/sites-enabled/%s" % (path, site) #delete existing symlink ln_path = '/'.join([deployment_root(), 'env', env.project_name]) run('rm -f ' + ln_path) #run post deploy hooks post_exec_hook('post_deploy') #activate run('ln -s %s %s' % (env_path, ln_path)) if env.verbosity: print env.host, env.project_fullname, "ACTIVATED" else: if env.verbosity and not env.patch: print env.project_fullname, "is the active version" if env.patch or active <> env.project_fullname: for s in servers: start_webserver(s) print return