def restart(web, supervisor, systemd): from bench.utils import restart_supervisor_processes, restart_systemd_processes from bench.config.common_site_config import get_config if get_config('.').get('restart_supervisor_on_update') or supervisor: restart_supervisor_processes(bench_path='.', web_workers=web) if get_config('.').get('restart_systemd_on_update') or systemd: restart_systemd_processes(bench_path='.', web_workers=web)
def setup_production(user, bench_path='.', yes=False): if get_config(bench_path).get('restart_supervisor_on_update') and get_config(bench_path).get('restart_systemd_on_update'): raise Exception("You cannot use supervisor and systemd at the same time. Modify your common_site_config accordingly." ) if get_config(bench_path).get('restart_systemd_on_update'): generate_systemd_config(bench_path=bench_path, user=user, yes=yes) else: generate_supervisor_config(bench_path=bench_path, user=user, yes=yes) make_nginx_conf(bench_path=bench_path, yes=yes) fix_prod_setup_perms(bench_path, dataent_user=user) remove_default_nginx_configs() bench_name = get_bench_name(bench_path) nginx_conf = '/etc/nginx/conf.d/{bench_name}.conf'.format(bench_name=bench_name) if get_config(bench_path).get('restart_supervisor_on_update'): supervisor_conf_extn = "ini" if is_centos7() else "conf" supervisor_conf = os.path.join(get_supervisor_confdir(), '{bench_name}.{extn}'.format( bench_name=bench_name, extn=supervisor_conf_extn)) # Check if symlink exists, If not then create it. if not os.path.islink(supervisor_conf): os.symlink(os.path.abspath(os.path.join(bench_path, 'config', 'supervisor.conf')), supervisor_conf) if not os.path.islink(nginx_conf): os.symlink(os.path.abspath(os.path.join(bench_path, 'config', 'nginx.conf')), nginx_conf) if get_config(bench_path).get('restart_supervisor_on_update'): reload_supervisor() if os.environ.get('NO_SERVICE_RESTART'): return reload_nginx()
def setup_production(user, bench_path='.', yes=False): if get_config(bench_path).get('restart_supervisor_on_update') and get_config(bench_path).get('restart_systemd_on_update'): raise Exception("You cannot use supervisor and systemd at the same time. Modify your common_site_config accordingly." ) if get_config(bench_path).get('restart_systemd_on_update'): generate_systemd_config(bench_path=bench_path, user=user, yes=yes) else: generate_supervisor_config(bench_path=bench_path, user=user, yes=yes) make_nginx_conf(bench_path=bench_path, yes=yes) fix_prod_setup_perms(bench_path, frappe_user=user) remove_default_nginx_configs() bench_name = get_bench_name(bench_path) nginx_conf = '/etc/nginx/conf.d/{bench_name}.conf'.format(bench_name=bench_name) if get_config(bench_path).get('restart_supervisor_on_update'): supervisor_conf_extn = "ini" if is_centos7() else "conf" supervisor_conf = os.path.join(get_supervisor_confdir(), '{bench_name}.{extn}'.format( bench_name=bench_name, extn=supervisor_conf_extn)) # Check if symlink exists, If not then create it. if not os.path.islink(supervisor_conf): os.symlink(os.path.abspath(os.path.join(bench_path, 'config', 'supervisor.conf')), supervisor_conf) if not os.path.islink(nginx_conf): os.symlink(os.path.abspath(os.path.join(bench_path, 'config', 'nginx.conf')), nginx_conf) if get_config(bench_path).get('restart_supervisor_on_update'): reload_supervisor() if os.environ.get('NO_SERVICE_RESTART'): return reload_nginx()
def remove_app(app, bench_path='.'): if app not in get_apps(bench_path): print("No app named {0}".format(app)) sys.exit(1) app_path = os.path.join(bench_path, 'apps', app) site_path = os.path.join(bench_path, 'sites') pip = os.path.join(bench_path, 'env', 'bin', 'pip') for site in os.listdir(site_path): req_file = os.path.join(site_path, site, 'site_config.json') if os.path.exists(req_file): out = subprocess.check_output( ["bench", "--site", site, "list-apps"], cwd=bench_path).decode('utf-8') if re.search(r'\b' + app + r'\b', out): print("Cannot remove, app is installed on site: {0}".format( site)) sys.exit(1) exec_cmd("{0} uninstall -y {1}".format(pip, app), cwd=bench_path) remove_from_appstxt(app, bench_path) shutil.rmtree(app_path) run_frappe_cmd("build", bench_path=bench_path) if get_config(bench_path).get('restart_supervisor_on_update'): restart_supervisor_processes(bench_path=bench_path) if get_config(bench_path).get('restart_systemd_on_update'): restart_systemd_processes(bench_path=bench_path)
def restart(web, supervisor, systemd): "Restart supervisor processes or systemd units" from bench.utils import restart_supervisor_processes, restart_systemd_processes from bench.config.common_site_config import get_config if get_config('.').get('restart_supervisor_on_update') or supervisor: restart_supervisor_processes(bench_path='.', web_workers=web) if get_config('.').get('restart_systemd_on_update') or systemd: restart_systemd_processes(bench_path='.', web_workers=web)
def get_sites_with_config(bench_path): from bench.config.common_site_config import get_config from bench.config.site_config import get_site_config sites = get_sites(bench_path=bench_path) dns_multitenant = get_config(bench_path).get('dns_multitenant') ret = [] for site in sites: try: site_config = get_site_config(site, bench_path=bench_path) except Exception as e: strict_nginx = get_config(bench_path).get('strict_nginx') if strict_nginx: print( "\n\nERROR: The site config for the site {} is broken.". format(site), "If you want this command to pass, instead of just throwing an error,", "You may remove the 'strict_nginx' flag from common_site_config.json or set it to 0", "\n\n") raise (e) else: print( "\n\nWARNING: The site config for the site {} is broken.". format(site), "If you want this command to fail, instead of just showing a warning,", "You may add the 'strict_nginx' flag to common_site_config.json and set it to 1", "\n\n") continue ret.append({ "name": site, "port": site_config.get('nginx_port'), "ssl_certificate": site_config.get('ssl_certificate'), "ssl_certificate_key": site_config.get('ssl_certificate_key') }) if dns_multitenant and site_config.get('domains'): for domain in site_config.get('domains'): # domain can be a string or a dict with 'domain', 'ssl_certificate', 'ssl_certificate_key' if isinstance(domain, str) or isinstance(domain, unicode): domain = {'domain': domain} domain['name'] = site ret.append(domain) use_wildcard_certificate(bench_path, ret) return ret
def install_app(app, bench_path=".", verbose=False, no_cache=False, restart_bench=True, skip_assets=False): print('\n{0}Installing {1}{2}'.format(color.yellow, app, color.nc)) logger.log("installing {}".format(app)) pip_path = os.path.join(bench_path, "env", "bin", "pip") quiet_flag = "-q" if not verbose else "" app_path = os.path.join(bench_path, "apps", app) cache_flag = "--no-cache-dir" if no_cache else "" exec_cmd("{pip} install {quiet} -U -e {app} {no_cache}".format( pip=pip_path, quiet=quiet_flag, app=app_path, no_cache=cache_flag)) if os.path.exists(os.path.join(app_path, 'package.json')): exec_cmd("yarn install", cwd=app_path) add_to_appstxt(app, bench_path=bench_path) if not skip_assets: build_assets(bench_path=bench_path, app=app) if restart_bench: conf = get_config(bench_path=bench_path) if conf.get('restart_supervisor_on_update'): restart_supervisor_processes(bench_path=bench_path) if conf.get('restart_systemd_on_update'): restart_systemd_processes(bench_path=bench_path)
def setup_backups(bench_path='.'): from bench.config.common_site_config import get_config logger.log('setting up backups') bench_dir = os.path.abspath(bench_path) user = get_config(bench_path=bench_dir).get('frappe_user') logfile = os.path.join(bench_dir, 'logs', 'backup.log') bench.set_frappe_version(bench_path=bench_path) system_crontab = CronTab(user=user) if bench.FRAPPE_VERSION == 4: backup_command = "cd {sites_dir} && {frappe} --backup all".format( frappe=get_frappe(bench_path=bench_path), ) else: backup_command = "cd {bench_dir} && {bench} --verbose --site all backup".format( bench_dir=bench_dir, bench=sys.argv[0]) job_command = "{backup_command} >> {logfile} 2>&1".format( backup_command=backup_command, logfile=logfile) if job_command not in str(system_crontab): job = system_crontab.new( command=job_command, comment="bench auto backups set for every 6 hours") job.every(6).hours() system_crontab.write()
def pull_all_apps(bench_path='.', reset=False): '''Check all apps if there no local changes, pull''' rebase = '--rebase' if get_config(bench_path).get('rebase_on_pull') else '' # chech for local changes if not reset: for app in get_apps(bench_path=bench_path): excluded_apps = get_excluded_apps() if app in excluded_apps: print("Skipping reset for app {}".format(app)) continue app_dir = get_repo_dir(app, bench_path=bench_path) if os.path.exists(os.path.join(app_dir, '.git')): out = subprocess.check_output(["git", "status"], cwd=app_dir) out = out.decode('utf-8') if not re.search( r'nothing to commit, working (directory|tree) clean', out): print(''' Cannot proceed with update: You have local changes in app "{0}" that are not committed. Here are your choices: 1. Merge the {0} app manually with "git pull" / "git pull --rebase" and fix conflicts. 1. Temporarily remove your changes with "git stash" or discard them completely with "bench update --reset" or for individual repositries "git reset --hard" 2. If your changes are helpful for others, send in a pull request via GitHub and wait for them to be merged in the core.'''.format(app)) sys.exit(1) excluded_apps = get_excluded_apps() for app in get_apps(bench_path=bench_path): if app in excluded_apps: print("Skipping pull for app {}".format(app)) continue app_dir = get_repo_dir(app, bench_path=bench_path) if os.path.exists(os.path.join(app_dir, '.git')): remote = get_remote(app) if not remote: # remote is False, i.e. remote doesn't exist, add the app to excluded_apps.txt add_to_excluded_apps_txt(app, bench_path=bench_path) print( "Skipping pull for app {}, since remote doesn't exist, and adding it to excluded apps" .format(app)) continue logger.info('pulling {0}'.format(app)) if reset: exec_cmd("git fetch --all", cwd=app_dir) exec_cmd("git reset --hard {remote}/{branch}".format( remote=remote, branch=get_current_branch(app, bench_path=bench_path)), cwd=app_dir) else: exec_cmd("git pull {rebase} {remote} {branch}".format( rebase=rebase, remote=remote, branch=get_current_branch(app, bench_path=bench_path)), cwd=app_dir) exec_cmd('find . -name "*.pyc" -delete', cwd=app_dir)
def use_wildcard_certificate(bench_path, ret): ''' stored in common_site_config.json as: "wildcard": { "domain": "*.erpnext.com", "ssl_certificate": "/path/to/erpnext.com.cert", "ssl_certificate_key": "/path/to/erpnext.com.key" } ''' from bench.config.common_site_config import get_config config = get_config(bench_path=bench_path) wildcard = config.get('wildcard') if not wildcard: return domain = wildcard['domain'] ssl_certificate = wildcard['ssl_certificate'] ssl_certificate_key = wildcard['ssl_certificate_key'] if domain.startswith('*.'): domain = domain[1:] else: domain = '.' + domain for site in ret: if site.get('ssl_certificate'): continue if (site.get('domain') or site['name']).endswith(domain): # example: ends with .erpnext.com site['ssl_certificate'] = ssl_certificate site['ssl_certificate_key'] = ssl_certificate_key site['wildcard'] = 1
def setup_manager(yes=False, port=23624, domain=None): "Setup bench-manager.local site with the bench_manager app installed on it" from six.moves import input create_new_site = True if 'bench-manager.local' in os.listdir('sites'): ans = input('Site aleady exists. Overwrite existing new site? [Y/n]: ') while ans.lower() not in ['y', 'n', '']: ans = input('Please type "y" or "n". Site aleady exists. Overwrite existing new site? [Y/n]: ') if ans=='n': create_new_site = False if create_new_site: exec_cmd("bench new-site --force bench-manager.local") if 'bench_manager' in os.listdir('apps'): print('App aleady exists. Skipping downloading the app') else: exec_cmd("bench get-app bench_manager") exec_cmd("bench --site bench-manager.local install-app bench_manager") from bench.config.common_site_config import get_config bench_path = '.' conf = get_config(bench_path) if conf.get('restart_supervisor_on_update') or conf.get('restart_systemd_on_update'): # implicates a production setup or so I presume if not domain: print("Please specify the site name on which you want to host bench-manager using the 'domain' flag") sys.exit(1) from bench.utils import get_sites, get_bench_name bench_name = get_bench_name(bench_path) if domain not in get_sites(bench_path): raise Exception("No such site") from bench.config.nginx import make_bench_manager_nginx_conf make_bench_manager_nginx_conf(bench_path, yes=yes, port=port, domain=domain)
def make_nginx_conf(bench_path, force=False): from bench import env from bench.config.common_site_config import get_config template = env.get_template('nginx.conf') bench_path = os.path.abspath(bench_path) sites_path = os.path.join(bench_path, "sites") config = get_config(bench_path) sites = prepare_sites(config, bench_path) nginx_conf = template.render(**{ "sites_path": sites_path, "http_timeout": config.get("http_timeout"), "sites": sites, "webserver_port": config.get('webserver_port'), "socketio_port": config.get('socketio_port'), "bench_name": get_bench_name(bench_path) }) conf_path = os.path.join(bench_path, "config", "nginx.conf") if not force and os.path.exists(conf_path): click.confirm('nginx.conf already exists and this will overwrite it. Do you want to continue?', abort=True) with open(conf_path, "w") as f: f.write(nginx_conf)
def update(pull=False, patch=False, build=False, bench=False, auto=False, restart_supervisor=False, requirements=False, no_backup=False, force=False, reset=False): "Update bench" if not (pull or patch or build or bench or requirements): pull, patch, build, bench, requirements = True, True, True, True, True if auto: sys.exit(1) patches.run(bench_path='.') conf = get_config(".") if bench and conf.get('update_bench_on_update'): update_bench() restart_update({ 'pull': pull, 'patch': patch, 'build': build, 'requirements': requirements, 'no-backup': no_backup, 'restart-supervisor': restart_supervisor, 'reset': reset }) if conf.get('release_bench'): print('Release bench, cannot update') sys.exit(1) version_upgrade = is_version_upgrade() if version_upgrade[0]: print() print() print( "This update will cause a major version change in Frappe/ERPNext from {0} to {1}." .format(*version_upgrade[1:])) print( "This would take significant time to migrate and might break custom apps." ) click.confirm('Do you want to continue?', abort=True) _update(pull, patch, build, bench, auto, restart_supervisor, requirements, no_backup, force=force, reset=reset)
def _update(pull=False, patch=False, build=False, update_bench=False, auto=False, restart_supervisor=False, requirements=False, no_backup=False, upgrade=False, bench_path='.', force=False, reset=False, force_frappe=False, force_erpnext=False, force_frappe_erpnext=False): conf = get_config(bench_path=bench_path) version_upgrade = is_version_upgrade(bench_path=bench_path) # if version_upgrade[0] and not upgrade: # raise Exception("Major Version Upgrade") # # if upgrade and (version_upgrade[0] or (not version_upgrade[0] and force)): # validate_upgrade(version_upgrade[1], version_upgrade[2], bench_path=bench_path) before_update(bench_path=bench_path, requirements=requirements) if pull: pull_all_apps(bench_path=bench_path, reset=reset, force_frappe=force_frappe, force_erpnext=force_erpnext, force_frappe_erpnext=force_frappe_erpnext) # if requirements: # update_requirements(bench_path=bench_path) if upgrade and (version_upgrade[0] or (not version_upgrade[0] and force)): pre_upgrade(version_upgrade[1], version_upgrade[2], bench_path=bench_path) import bench.utils, bench.app reload(bench.utils) reload(bench.app) if patch: if not no_backup: backup_all_sites(bench_path=bench_path) patch_sites(bench_path=bench_path) if build: build_assets(bench_path=bench_path) if upgrade and (version_upgrade[0] or (not version_upgrade[0] and force)): post_upgrade(version_upgrade[1], version_upgrade[2], bench_path=bench_path) if restart_supervisor or conf.get('restart_supervisor_on_update'): restart_supervisor_processes(bench_path=bench_path) print "_" * 80 print "Bench: Open source installer + admin for Frappe and ERPNext (https://erpnext.com)" print
def setup_letsencrypt(site, custom_domain, bench_path, interactive): site_path = os.path.join(bench_path, "sites", site, "site_config.json") if not os.path.exists(os.path.dirname(site_path)): print("No site named " + site) return if custom_domain: domains = get_domains(site, bench_path) for d in domains: if (isinstance(d, dict) and d['domain'] == custom_domain): print( "SSL for Domain {0} already exists".format(custom_domain)) return if not custom_domain in domains: print("No custom domain named {0} set for site".format( custom_domain)) return click.confirm( 'Running this will stop the nginx service temporarily causing your sites to go offline\n' 'Do you want to continue?', abort=True) if not get_config(bench_path).get("dns_multitenant"): print("You cannot setup SSL without DNS Multitenancy") return create_config(site, custom_domain) run_certbot_and_setup_ssl(site, custom_domain, bench_path, interactive) setup_crontab()
def setup_letsencrypt(site, custom_domain, bench_path): site_path = os.path.join(bench_path, "sites", site, "site_config.json") if not os.path.exists(os.path.dirname(site_path)): print "No site named "+site return if custom_domain: domains = get_domains(site, bench_path) for d in domains: if (isinstance(d, dict) and d['domain']==custom_domain): print "SSL for Domain {0} already exists".format(custom_domain) return if not custom_domain in domains: print "No custom domain named {0} set for site".format(custom_domain) return click.confirm('Running this will stop the nginx service temporarily causing your sites to go offline\n' 'Do you want to continue?', abort=True) if not get_config(bench_path).get("dns_multitenant"): print "You cannot setup SSL without DNS Multitenancy" return create_config(site, custom_domain) run_certbot_and_setup_ssl(site, custom_domain, bench_path) setup_crontab()
def disable_production(bench_path='.'): bench_name = get_bench_name(bench_path) # supervisorctl supervisor_conf_extn = "ini" if is_centos7() else "conf" supervisor_conf = os.path.join( get_supervisor_confdir(), '{bench_name}.{extn}'.format(bench_name=bench_name, extn=supervisor_conf_extn)) if os.path.islink(supervisor_conf): os.unlink(supervisor_conf) if get_config(bench_path).get('restart_supervisor_on_update'): exec_cmd('sudo supervisorctl reread') exec_cmd('sudo supervisorctl update') # nginx nginx_conf = '/etc/nginx/conf.d/{bench_name}.conf'.format( bench_name=bench_name) if os.path.islink(nginx_conf): os.unlink(nginx_conf) reload_nginx()
def get_sites_with_config(bench_path): from bench.config.common_site_config import get_config from bench.config.site_config import get_site_config sites = get_sites(bench_path=bench_path) dns_multitenant = get_config(bench_path).get('dns_multitenant') ret = [] for site in sites: site_config = get_site_config(site, bench_path=bench_path) ret.append({ "name": site, "port": site_config.get('nginx_port'), "ssl_certificate": site_config.get('ssl_certificate'), "ssl_certificate_key": site_config.get('ssl_certificate_key') }) if dns_multitenant and site_config.get('domains'): for domain in site_config.get('domains'): # domain can be a string or a dict with 'domain', 'ssl_certificate', 'ssl_certificate_key' if isinstance(domain, basestring): domain = { 'domain': domain } domain['name'] = site ret.append(domain) use_wildcard_certificate(bench_path, ret) return ret
def get_sites_with_config(bench_path): from bench.config.common_site_config import get_config from bench.config.site_config import get_site_config sites = get_sites(bench_path=bench_path) dns_multitenant = get_config(bench_path).get('dns_multitenant') ret = [] for site in sites: site_config = get_site_config(site, bench_path=bench_path) ret.append({ "name": site, "port": site_config.get('nginx_port'), "ssl_certificate": site_config.get('ssl_certificate'), "ssl_certificate_key": site_config.get('ssl_certificate_key') }) if dns_multitenant and site_config.get('domains'): for domain in site_config.get('domains'): # domain can be a string or a dict with 'domain', 'ssl_certificate', 'ssl_certificate_key' if isinstance(domain, basestring): domain = {'domain': domain} domain['name'] = site ret.append(domain) use_wildcard_certificate(bench_path, ret) return ret
def remove_common_config(keys): common_site_config = get_config('.') for key in keys: if key in common_site_config: del common_site_config[key] put_config(common_site_config)
def post_upgrade(from_ver, to_ver, bench_path='.'): from .config.common_site_config import get_config from .config import redis from .config.supervisor import generate_supervisor_config from .config.nginx import make_nginx_conf conf = get_config(bench_path=bench_path) print("-" * 80 + "Your bench was upgraded to version {0}".format(to_ver)) if conf.get('restart_supervisor_on_update'): redis.generate_config(bench_path=bench_path) generate_supervisor_config(bench_path=bench_path) make_nginx_conf(bench_path=bench_path) if from_ver == 4 and to_ver == 5: setup_backups(bench_path=bench_path) if from_ver <= 5 and to_ver == 6: setup_socketio(bench_path=bench_path) message = """ As you have setup your bench for production, you will have to reload configuration for nginx and supervisor. To complete the migration, please run the following commands sudo service nginx restart sudo supervisorctl reload """.strip() print(message)
def make_nginx_conf(bench_path, force=False): from bench import env from bench.config.common_site_config import get_config template = env.get_template('nginx.conf') bench_path = os.path.abspath(bench_path) sites_path = os.path.join(bench_path, "sites") config = get_config(bench_path) sites = prepare_sites(config, bench_path) nginx_conf = template.render( **{ "sites_path": sites_path, "http_timeout": config.get("http_timeout"), "sites": sites, "webserver_port": config.get('webserver_port'), "socketio_port": config.get('socketio_port'), "bench_name": get_bench_name(bench_path) }) conf_path = os.path.join(bench_path, "config", "nginx.conf") if not force and os.path.exists(conf_path): click.confirm( 'nginx.conf already exists and this will overwrite it. Do you want to continue?', abort=True) with open(conf_path, "w") as f: f.write(nginx_conf)
def install_app(app, bench_path=".", verbose=False, no_cache=False, postprocess=True, skip_assets=False): logger.info("installing {}".format(app)) pip_path = os.path.join(bench_path, "env", "bin", "pip") quiet_flag = "-q" if not verbose else "" app_path = os.path.join(bench_path, "apps", app) cache_flag = "--no-cache-dir" if no_cache else "" exec_cmd("{pip} install {quiet} -U -e {app} {no_cache}".format( pip=pip_path, quiet=quiet_flag, app=app_path, no_cache=cache_flag)) add_to_appstxt(app, bench_path=bench_path) if postprocess: if not skip_assets: build_assets(bench_path=bench_path, app=app) conf = get_config(bench_path=bench_path) if conf.get('restart_supervisor_on_update'): restart_supervisor_processes(bench_path=bench_path) if conf.get('restart_systemd_on_update'): restart_systemd_processes(bench_path=bench_path)
def execute(bench_path): # deprecate bench config bench_config_path = os.path.join(bench_path, 'config.json') if not os.path.exists(bench_config_path): return with open(bench_config_path, "r") as f: bench_config = json.loads(f.read()) common_site_config = get_common_site_config(bench_path) common_site_config.update(bench_config) put_config(common_site_config, bench_path) # remove bench/config.json os.remove(bench_config_path) # change keys config = get_config(bench_path) changed = False for from_key, to_key, default in ( ("celery_broker", "redis_queue", "redis://localhost:6379"), ("async_redis_server", "redis_socketio", "redis://localhost:12311"), ("cache_redis_server", "redis_cache", "redis://localhost:11311") ): if from_key in config: config[to_key] = config[from_key] del config[from_key] changed = True elif to_key not in config: config[to_key] = default changed = True if changed: put_config(config, bench_path)
def generate_supervisor_config(bench_path, user=None): from bench.app import get_current_frappe_version from bench.utils import get_bench_name, find_executable from bench.config.common_site_config import get_config, update_config, get_gunicorn_workers template = bench.env.get_template('supervisor.conf') if not user: user = getpass.getuser() config = get_config(bench=bench_path) bench_dir = os.path.abspath(bench_path) config = template.render(**{ "bench_dir": bench_dir, "sites_dir": os.path.join(bench_dir, 'sites'), "user": user, "http_timeout": config.get("http_timeout", 120), "redis_server": find_executable('redis-server'), "node": find_executable('node') or find_executable('nodejs'), "redis_cache_config": os.path.join(bench_dir, 'config', 'redis_cache.conf'), "redis_socketio_config": os.path.join(bench_dir, 'config', 'redis_socketio.conf'), "redis_queue_config": os.path.join(bench_dir, 'config', 'redis_queue.conf'), "frappe_version": get_current_frappe_version(), "webserver_port": config.get('webserver_port', 8000), "gunicorn_workers": config.get('gunicorn_workers', get_gunicorn_workers()["gunicorn_workers"]), "bench_name": get_bench_name(bench_path) }) with open(os.path.join(bench_path, 'config', 'supervisor.conf'), 'w') as f: f.write(config) update_config({'restart_supervisor_on_update': True}, bench=bench_path)
def _update(pull=False, patch=False, build=False, update_bench=False, auto=False, restart_supervisor=False, requirements=False, no_backup=False, bench_path='.', force=False, reset=False): conf = get_config(bench_path=bench_path) version_upgrade = is_version_upgrade(bench_path=bench_path) if version_upgrade[0] or (not version_upgrade[0] and force): validate_upgrade(version_upgrade[1], version_upgrade[2], bench_path=bench_path) before_update(bench_path=bench_path, requirements=requirements) if pull: pull_all_apps(bench_path=bench_path, reset=reset) if requirements: update_requirements(bench_path=bench_path) update_npm_packages(bench_path=bench_path) if version_upgrade[0] or (not version_upgrade[0] and force): pre_upgrade(version_upgrade[1], version_upgrade[2], bench_path=bench_path) import bench.utils, bench.app print('Reloading bench...') reload(bench.utils) reload(bench.app) if patch: if not no_backup: print('Backing up sites...') backup_all_sites(bench_path=bench_path) print('Patching sites...') patch_sites(bench_path=bench_path) if build: build_assets(bench_path=bench_path) if version_upgrade[0] or (not version_upgrade[0] and force): post_upgrade(version_upgrade[1], version_upgrade[2], bench_path=bench_path) if restart_supervisor or conf.get('restart_supervisor_on_update'): restart_supervisor_processes(bench_path=bench_path) print("_" * 80) print( "Bench: Deployment tool for Frappe and ERPNext (https://erpnext.org).") print( "Open source depends on your contributions, so please contribute bug reports, patches, fixes or cash and be a part of the community" ) print()
def update(pull=False, patch=False, build=False, bench=False, auto=False, restart_supervisor=False, requirements=False, no_backup=False, upgrade=False, force=False): "Update bench" if not (pull or patch or build or bench or requirements): pull, patch, build, bench, requirements = True, True, True, True, True if auto: sys.exit(1) patches.run(bench_path='.') conf = get_config(".") if bench and conf.get('update_bench_on_update'): update_bench() restart_update({ 'pull': pull, 'patch': patch, 'build': build, 'requirements': requirements, 'no-backup': no_backup, 'restart-supervisor': restart_supervisor, 'upgrade': upgrade }) if conf.get('release_bench'): print 'Release bench, cannot update' sys.exit(1) version_upgrade = is_version_upgrade() if version_upgrade[0] and not upgrade: print print print "This update will cause a major version change in Frappe/ERPNext from {0} to {1}.".format( *version_upgrade[1:]) print "This would take significant time to migrate and might break custom apps. Please run `bench update --upgrade` to confirm." print print "You can stay on the latest stable release by running `bench switch-to-master` or pin your bench to {0} by running `bench switch-to-v{0}`".format( version_upgrade[1]) sys.exit(1) _update(pull, patch, build, bench, auto, restart_supervisor, requirements, no_backup, upgrade, force=force)
def make_nginx_conf(bench_path, yes=False): from bench import env from bench.config.common_site_config import get_config template = env.get_template('nginx.conf') bench_path = os.path.abspath(bench_path) sites_path = os.path.join(bench_path, "sites") config = get_config(bench_path) sites = prepare_sites(config, bench_path) nginx_conf = template.render(**{ "sites_path": sites_path, "http_timeout": config.get("http_timeout"), "sites": sites, "webserver_port": config.get('webserver_port'), "socketio_port": config.get('socketio_port'), "bench_name": get_bench_name(bench_path), "error_pages": get_error_pages(), # for nginx map variable "random_string": "".join(random.choice(string.ascii_lowercase) for i in xrange(7)) }) conf_path = os.path.join(bench_path, "config", "nginx.conf") if not yes and os.path.exists(conf_path): click.confirm('nginx.conf already exists and this will overwrite it. Do you want to continue?', abort=True) with open(conf_path, "w") as f: f.write(nginx_conf)
def restart_supervisor_processes(bench_path='.', web_workers=False): from .config.common_site_config import get_config conf = get_config(bench_path=bench_path) bench_name = get_bench_name(bench_path) cmd = conf.get('supervisor_restart_cmd') if cmd: exec_cmd(cmd, cwd=bench_path) else: supervisor_status = subprocess.check_output( ['sudo', 'supervisorctl', 'status'], cwd=bench_path) supervisor_status = safe_decode(supervisor_status) if web_workers and '{bench_name}-web:'.format( bench_name=bench_name) in supervisor_status: group = '{bench_name}-web: '.format(bench_name=bench_name) elif '{bench_name}-workers:'.format( bench_name=bench_name) in supervisor_status: group = '{bench_name}-workers: {bench_name}-web:'.format( bench_name=bench_name) # backward compatibility elif '{bench_name}-processes:'.format( bench_name=bench_name) in supervisor_status: group = '{bench_name}-processes:'.format(bench_name=bench_name) # backward compatibility else: group = 'frappe:' exec_cmd('sudo supervisorctl restart {group}'.format(group=group), cwd=bench_path)
def migrate_env(python, backup=False): from bench.config.common_site_config import get_config from bench.app import get_apps log = logging.getLogger(__name__) log.setLevel(logging.DEBUG) nvenv = 'env' path = os.getcwd() python = which(python) virtualenv = which('virtualenv') pvenv = os.path.join(path, nvenv) pip = os.path.join(pvenv, 'bin', 'pip') # Clear Cache before Bench Dies. try: config = get_config(bench_path=os.getcwd()) rredis = urlparse(config['redis_cache']) redis = '{redis} -p {port}'.format(redis=which('redis-cli'), port=rredis.port) log.debug('Clearing Redis Cache...') exec_cmd('{redis} FLUSHALL'.format(redis=redis)) log.debug('Clearing Redis DataBase...') exec_cmd('{redis} FLUSHDB'.format(redis=redis)) except: log.warn('Please ensure Redis Connections are running or Daemonized.') # Backup venv: restore using `virtualenv --relocatable` if needed if backup: parch = os.path.join(path, 'archived_envs') if not os.path.exists(parch): os.mkdir(parch) source = os.path.join(path, 'env') target = parch log.debug('Backing up Virtual Environment') stamp = datetime.now().strftime('%Y%m%d_%H%M%S') dest = os.path.join(path, str(stamp)) os.rename(source, dest) shutil.move(dest, target) # Create virtualenv using specified python try: log.debug('Setting up a New Virtual {} Environment'.format(python)) exec_cmd('{virtualenv} --python {python} {pvenv}'.format( virtualenv=virtualenv, python=python, pvenv=pvenv)) apps = ' '.join( ["-e {}".format(os.path.join("apps", app)) for app in get_apps()]) exec_cmd('{0} install -q -U {1}'.format(pip, apps)) log.debug('Migration Successful to {}'.format(python)) except: log.debug('Migration Error') raise
def remove_common_config(keys): from bench.config.common_site_config import get_config, put_config common_site_config = get_config('.') for key in keys: if key in common_site_config: del common_site_config[key] put_config(common_site_config)
def generate_supervisor_config(bench_path, user=None, force=False): from bench.app import get_current_frappe_version, use_rq from bench.utils import get_bench_name, find_executable from bench.config.common_site_config import get_config, update_config, get_gunicorn_workers template = bench.env.get_template('supervisor.conf') if not user: user = getpass.getuser() config = get_config(bench=bench_path) bench_dir = os.path.abspath(bench_path) config = template.render( **{ "bench_dir": bench_dir, "sites_dir": os.path.join(bench_dir, 'sites'), "user": user, "frappe_version": get_current_frappe_version(bench_path), "use_rq": use_rq(bench_path), "http_timeout": config.get("http_timeout", 120), "redis_server": find_executable('redis-server'), "node": find_executable('node') or find_executable('nodejs'), "redis_cache_config": os.path.join(bench_dir, 'config', 'redis_cache.conf'), "redis_socketio_config": os.path.join(bench_dir, 'config', 'redis_socketio.conf'), "redis_queue_config": os.path.join(bench_dir, 'config', 'redis_queue.conf'), "webserver_port": config.get('webserver_port', 8000), "gunicorn_workers": config.get('gunicorn_workers', get_gunicorn_workers()["gunicorn_workers"]), "bench_name": get_bench_name(bench_path), "background_workers": config.get('background_workers') or 1 }) conf_path = os.path.join(bench_path, 'config', 'supervisor.conf') if not force and os.path.exists(conf_path): click.confirm( 'supervisor.conf already exists and this will overwrite it. Do you want to continue?', abort=True) with open(conf_path, 'w') as f: f.write(config) update_config({'restart_supervisor_on_update': True}, bench=bench_path)
def get_sites_with_config(bench_path): from bench.config.common_site_config import get_config from bench.config.site_config import get_site_config sites = get_sites(bench_path=bench_path) dns_multitenant = get_config(bench_path).get('dns_multitenant') ret = [] for site in sites: try: site_config = get_site_config(site, bench_path=bench_path) except Exception as e: strict_nginx = get_config(bench_path).get('strict_nginx') if strict_nginx: print("\n\nERROR: The site config for the site {} is broken.".format(site), "If you want this command to pass, instead of just throwing an error,", "You may remove the 'strict_nginx' flag from common_site_config.json or set it to 0", "\n\n") raise (e) else: print("\n\nWARNING: The site config for the site {} is broken.".format(site), "If you want this command to fail, instead of just showing a warning,", "You may add the 'strict_nginx' flag to common_site_config.json and set it to 1", "\n\n") continue ret.append({ "name": site, "port": site_config.get('nginx_port'), "ssl_certificate": site_config.get('ssl_certificate'), "ssl_certificate_key": site_config.get('ssl_certificate_key') }) if dns_multitenant and site_config.get('domains'): for domain in site_config.get('domains'): # domain can be a string or a dict with 'domain', 'ssl_certificate', 'ssl_certificate_key' if isinstance(domain, str) or isinstance(domain, unicode): domain = { 'domain': domain } domain['name'] = site ret.append(domain) use_wildcard_certificate(bench_path, ret) return ret
def change_uid(): if is_root() and not cmd_requires_root(): frappe_user = get_config(".").get('frappe_user') if frappe_user: drop_privileges(uid_name=frappe_user, gid_name=frappe_user) os.environ['HOME'] = pwd.getpwnam(frappe_user).pw_dir else: print 'You should not run this command as root' sys.exit(1)
def change_uid(): if is_root() and not cmd_requires_root(): frappe_user = get_config(".").get('frappe_user') if frappe_user: drop_privileges(uid_name=frappe_user, gid_name=frappe_user) os.environ['HOME'] = pwd.getpwnam(frappe_user).pw_dir else: log(change_uid_msg, level=3) sys.exit(1)
def make_nginx_conf(bench_path, yes=False): conf_path = os.path.join(bench_path, "config", "nginx.conf") if not yes and os.path.exists(conf_path): if not click.confirm( 'nginx.conf already exists and this will overwrite it. Do you want to continue?' ): return from bench import env from bench.config.common_site_config import get_config template = env.get_template('nginx.conf') bench_path = os.path.abspath(bench_path) sites_path = os.path.join(bench_path, "sites") config = get_config(bench_path) sites = prepare_sites(config, bench_path) bench_name = get_bench_name(bench_path) allow_rate_limiting = config.get('allow_rate_limiting', False) template_vars = { "sites_path": sites_path, "http_timeout": config.get("http_timeout"), "sites": sites, "webserver_port": config.get('webserver_port'), "socketio_port": config.get('socketio_port'), "bench_name": bench_name, "error_pages": get_error_pages(), "allow_rate_limiting": allow_rate_limiting, # for nginx map variable "random_string": "".join(random.choice(string.ascii_lowercase) for i in range(7)) } if allow_rate_limiting: template_vars.update({ 'bench_name_hash': hashlib.sha256(bench_name).hexdigest()[:16], 'limit_conn_shared_memory': get_limit_conn_shared_memory() }) nginx_conf = template.render(**template_vars) with open(conf_path, "w") as f: f.write(nginx_conf)
def execute(bench_path): """This patch checks if bench sudoers is set and regenerate supervisor and sudoers files""" user = get_config('.').get("frappe_user") or getpass.getuser() if is_sudoers_set(): if is_production_set(bench_path): exec_cmd("sudo bench setup supervisor --yes --user {user}".format( user=user)) service("supervisord", "restart") exec_cmd("sudo bench setup sudoers {user}".format(user=user))
def setup_wildcard_ssl(domain, email, bench_path, exclude_base_domain): def _get_domains(domain): domain_list = [domain] if not domain.startswith('*.'): # add wildcard caracter to domain if missing domain_list.append('*.{0}'.format(domain)) else: # include base domain based on flag domain_list.append(domain.replace('*.', '')) if exclude_base_domain: domain_list.remove(domain.replace('*.', '')) return domain_list if not get_config(bench_path).get("dns_multitenant"): print("You cannot setup SSL without DNS Multitenancy") return get_certbot() domain_list = _get_domains(domain.strip()) email_param = '' if email: email_param = '--email {0}'.format(email) try: exec_cmd( "{path} certonly --manual --preferred-challenges=dns {email_param} \ --server https://acme-v02.api.letsencrypt.org/directory \ --agree-tos -d {domain}".format(path=get_certbot_path(), domain=' -d '.join(domain_list), email_param=email_param)) except CommandFailedError: print("There was a problem trying to setup SSL") return ssl_path = "/etc/letsencrypt/live/{domain}/".format(domain=domain) ssl_config = { "wildcard": { "domain": domain, "ssl_certificate": os.path.join(ssl_path, "fullchain.pem"), "ssl_certificate_key": os.path.join(ssl_path, "privkey.pem") } } update_common_site_config(ssl_config) setup_crontab() make_nginx_conf(bench_path) print("Restrting Nginx service") service('nginx', 'restart')
def setup_wildcard_ssl(domain, email, bench_path, exclude_base_domain): def _get_domains(domain): domain_list = [domain] if not domain.startswith('*.'): # add wildcard caracter to domain if missing domain_list.append('*.{0}'.format(domain)) else: # include base domain based on flag domain_list.append(domain.replace('*.', '')) if exclude_base_domain: domain_list.remove(domain.replace('*.', '')) return domain_list if not get_config(bench_path).get("dns_multitenant"): print("You cannot setup SSL without DNS Multitenancy") return get_certbot() domain_list = _get_domains(domain.strip()) email_param = '' if email: email_param = '--email {0}'.format(email) try: exec_cmd("{path} certonly --manual --preferred-challenges=dns {email_param} \ --server https://acme-v02.api.letsencrypt.org/directory \ --agree-tos -d {domain}".format(path=get_certbot_path(), domain=' -d '.join(domain_list), email_param=email_param)) except CommandFailedError: print("There was a problem trying to setup SSL") return ssl_path = "/etc/letsencrypt/live/{domain}/".format(domain=domain) ssl_config = { "wildcard": { "domain": domain, "ssl_certificate": os.path.join(ssl_path, "fullchain.pem"), "ssl_certificate_key": os.path.join(ssl_path, "privkey.pem") } } update_common_site_config(ssl_config) setup_crontab() make_nginx_conf(bench_path) print("Restrting Nginx service") service('nginx', 'restart')
def execute(bench_path): """ This patch fixes a cron job that would backup sites every minute per 6 hours """ user = get_config(bench_path=bench_path).get('frappe_user') user_crontab = CronTab(user=user) for job in user_crontab.find_comment( "bench auto backups set for every 6 hours"): job.every(6).hours() user_crontab.write()
def setup_procfile(bench_path, yes=False): config = get_config(bench_path=bench_path) procfile_path = os.path.join(bench_path, 'Procfile') if not yes and os.path.exists(procfile_path): click.confirm('A Procfile already exists and this will overwrite it. Do you want to continue?', abort=True) procfile = bench.env.get_template('Procfile').render( node=find_executable("node") or find_executable("nodejs"), use_rq=use_rq(bench_path), webserver_port=config.get('webserver_port')) with open(procfile_path, 'w') as f: f.write(procfile)
def _update(pull=False, patch=False, build=False, update_bench=False, auto=False, restart_supervisor=False, restart_systemd=False, requirements=False, no_backup=False, bench_path='.', force=False, reset=False): conf = get_config(bench_path=bench_path) version_upgrade = is_version_upgrade(bench_path=bench_path) if version_upgrade[0] or (not version_upgrade[0] and force): validate_upgrade(version_upgrade[1], version_upgrade[2], bench_path=bench_path) before_update(bench_path=bench_path, requirements=requirements) if pull: pull_all_apps(bench_path=bench_path, reset=reset) if requirements: update_requirements(bench_path=bench_path) update_node_packages(bench_path=bench_path) if version_upgrade[0] or (not version_upgrade[0] and force): pre_upgrade(version_upgrade[1], version_upgrade[2], bench_path=bench_path) import bench.utils, bench.app print('Reloading bench...') if sys.version_info >= (3, 4): import importlib importlib.reload(bench.utils) importlib.reload(bench.app) else: reload(bench.utils) reload(bench.app) if patch: if not no_backup: print('Backing up sites...') backup_all_sites(bench_path=bench_path) print('Patching sites...') patch_sites(bench_path=bench_path) if build: build_assets(bench_path=bench_path) if version_upgrade[0] or (not version_upgrade[0] and force): post_upgrade(version_upgrade[1], version_upgrade[2], bench_path=bench_path) if restart_supervisor or conf.get('restart_supervisor_on_update'): restart_supervisor_processes(bench_path=bench_path) if restart_systemd or conf.get('restart_systemd_on_update'): restart_systemd_processes(bench_path=bench_path) print("_"*80) print("Bench: Deployment tool for Frappe and ERPNext (https://erpnext.org).") print("Open source depends on your contributions, so please contribute bug reports, patches, fixes or cash and be a part of the community") print()
def setup_letsencrypt(site, bench_path): site_path = os.path.join(bench_path, "sites", site, "site_config.json") if not os.path.exists(os.path.dirname(site_path)): print "No site named "+site return click.confirm('Running this will stop the nginx service temporarily causing your sites to go offline\n' 'Do you want to continue?', abort=True) if not get_config(bench_path).get("dns_multitenant"): print "You cannot setup SSL without DNS Multitenancy" return create_config(site) run_certbot_and_setup_ssl(site, bench_path) setup_crontab()
def _update(pull=False, patch=False, build=False, update_bench=False, auto=False, restart_supervisor=False, requirements=False, no_backup=False, upgrade=False, bench_path='.', force=False, reset=False): conf = get_config(bench_path=bench_path) version_upgrade = is_version_upgrade(bench_path=bench_path) if version_upgrade[0] and not upgrade: raise Exception("Major Version Upgrade") if upgrade and (version_upgrade[0] or (not version_upgrade[0] and force)): validate_upgrade(version_upgrade[1], version_upgrade[2], bench_path=bench_path) before_update(bench_path=bench_path, requirements=requirements) if pull: pull_all_apps(bench_path=bench_path, reset=reset) if requirements: print 'Updating Python libraries...' update_requirements(bench_path=bench_path) if upgrade and (version_upgrade[0] or (not version_upgrade[0] and force)): pre_upgrade(version_upgrade[1], version_upgrade[2], bench_path=bench_path) import bench.utils, bench.app print 'Reloading bench...' reload(bench.utils) reload(bench.app) if patch: if not no_backup: print 'Backing up sites...' backup_all_sites(bench_path=bench_path) print 'Patching sites...' patch_sites(bench_path=bench_path) if build: build_assets(bench_path=bench_path) if upgrade and (version_upgrade[0] or (not version_upgrade[0] and force)): post_upgrade(version_upgrade[1], version_upgrade[2], bench_path=bench_path) if restart_supervisor or conf.get('restart_supervisor_on_update'): restart_supervisor_processes(bench_path=bench_path) print "_"*80 print "Bench: Deployment tool for Frappe and ERPNext (https://erpnext.org)." print "Open source depends on your contributions, so please contribute bug reports, patches, fixes or cash and be a part of the community" print
def make_nginx_conf(bench_path, yes=False): from bench import env from bench.config.common_site_config import get_config template = env.get_template('nginx.conf') bench_path = os.path.abspath(bench_path) sites_path = os.path.join(bench_path, "sites") config = get_config(bench_path) sites = prepare_sites(config, bench_path) bench_name = get_bench_name(bench_path) allow_rate_limiting = config.get('allow_rate_limiting', False) template_vars = { "sites_path": sites_path, "http_timeout": config.get("http_timeout"), "sites": sites, "webserver_port": config.get('webserver_port'), "socketio_port": config.get('socketio_port'), "bench_name": bench_name, "error_pages": get_error_pages(), "allow_rate_limiting": allow_rate_limiting, # for nginx map variable "random_string": "".join(random.choice(string.ascii_lowercase) for i in xrange(7)) } if allow_rate_limiting: template_vars.update({ 'bench_name_hash': hashlib.sha256(bench_name).hexdigest()[:16], 'limit_conn_shared_memory': get_limit_conn_shared_memory() }) nginx_conf = template.render(**template_vars) conf_path = os.path.join(bench_path, "config", "nginx.conf") if not yes and os.path.exists(conf_path): click.confirm('nginx.conf already exists and this will overwrite it. Do you want to continue?', abort=True) with open(conf_path, "w") as f: f.write(nginx_conf)
def generate_supervisor_config(bench_path, user=None, yes=False): from bench.app import get_current_frappe_version, use_rq from bench.utils import get_bench_name, find_executable from bench.config.common_site_config import get_config, update_config, get_gunicorn_workers template = bench.env.get_template('supervisor.conf') if not user: user = getpass.getuser() config = get_config(bench_path=bench_path) bench_dir = os.path.abspath(bench_path) config = template.render(**{ "bench_dir": bench_dir, "sites_dir": os.path.join(bench_dir, 'sites'), "user": user, "frappe_version": get_current_frappe_version(bench_path), "use_rq": use_rq(bench_path), "http_timeout": config.get("http_timeout", 120), "redis_server": find_executable('redis-server'), "node": find_executable('node') or find_executable('nodejs'), "redis_cache_config": os.path.join(bench_dir, 'config', 'redis_cache.conf'), "redis_socketio_config": os.path.join(bench_dir, 'config', 'redis_socketio.conf'), "redis_queue_config": os.path.join(bench_dir, 'config', 'redis_queue.conf'), "webserver_port": config.get('webserver_port', 8000), "gunicorn_workers": config.get('gunicorn_workers', get_gunicorn_workers()["gunicorn_workers"]), "bench_name": get_bench_name(bench_path), "background_workers": config.get('background_workers') or 1, "bench_cmd": find_executable('bench') }) conf_path = os.path.join(bench_path, 'config', 'supervisor.conf') if not yes and os.path.exists(conf_path): click.confirm('supervisor.conf already exists and this will overwrite it. Do you want to continue?', abort=True) with open(conf_path, 'w') as f: f.write(config) update_config({'restart_supervisor_on_update': True}, bench_path=bench_path) update_config({'restart_systemd_on_update': False}, bench_path=bench_path)
def update(pull=False, patch=False, build=False, bench=False, auto=False, restart_supervisor=False, requirements=False, no_backup=False, upgrade=False, force=False): "Update bench" if not (pull or patch or build or bench or requirements): pull, patch, build, bench, requirements = True, True, True, True, True patches.run(bench_path='.') conf = get_config(".") version_upgrade = is_version_upgrade() if version_upgrade[0] and not upgrade: print print print "This update will cause a major version change in Frappe/ERPNext from {0} to {1}.".format(*version_upgrade[1:]) print "This would take significant time to migrate and might break custom apps. Please run `bench update --upgrade` to confirm." print print "You can stay on the latest stable release by running `bench switch-to-master` or pin your bench to {0} by running `bench switch-to-v{0}`".format(version_upgrade[1]) sys.exit(1) if conf.get('release_bench'): print 'Release bench, cannot update' sys.exit(1) if auto: sys.exit(1) if bench and conf.get('update_bench_on_update'): update_bench() restart_update({ 'pull': pull, 'patch': patch, 'build': build, 'requirements': requirements, 'no-backup': no_backup, 'restart-supervisor': restart_supervisor, 'upgrade': upgrade }) _update(pull, patch, build, bench, auto, restart_supervisor, requirements, no_backup, upgrade, force=force)
def disable_production(bench_path='.'): bench_name = get_bench_name(bench_path) # supervisorctl supervisor_conf_extn = "ini" if is_centos7() else "conf" supervisor_conf = os.path.join(get_supervisor_confdir(), '{bench_name}.{extn}'.format( bench_name=bench_name, extn=supervisor_conf_extn)) if os.path.islink(supervisor_conf): os.unlink(supervisor_conf) if get_config(bench_path).get('restart_supervisor_on_update'): reload_supervisor() # nginx nginx_conf = '/etc/nginx/conf.d/{bench_name}.conf'.format(bench_name=bench_name) if os.path.islink(nginx_conf): os.unlink(nginx_conf) reload_nginx()
def make_nginx_conf(bench_path): from bench import env from bench.config.common_site_config import get_config template = env.get_template('nginx.conf') bench_path = os.path.abspath(bench_path) sites_path = os.path.join(bench_path, "sites") config = get_config(bench_path) sites = prepare_sites(config, bench_path) nginx_conf = template.render(**{ "sites_path": sites_path, "http_timeout": config.get("http_timeout"), "sites": sites, "webserver_port": config.get('webserver_port'), "socketio_port": config.get('socketio_port'), "bench_name": get_bench_name(bench_path) }) with open(os.path.join(bench_path, "config", "nginx.conf"), "w") as f: f.write(nginx_conf)
def _update(pull=False, patch=False, build=False, bench=False, auto=False, restart_supervisor=False, requirements=False, no_backup=False, upgrade=False, bench_path='.', force=False): conf = get_config(bench=bench_path) version_upgrade = is_version_upgrade(bench=bench_path) if version_upgrade[0] and not upgrade: raise Exception("Major Version Upgrade") if upgrade and (version_upgrade[0] or (not version_upgrade[0] and force)): validate_upgrade(version_upgrade[1], version_upgrade[2], bench=bench_path) before_update(bench=bench_path, requirements=requirements) if pull: pull_all_apps(bench=bench_path) if requirements: update_requirements(bench=bench_path) if upgrade and (version_upgrade[0] or (not version_upgrade[0] and force)): pre_upgrade(version_upgrade[1], version_upgrade[2], bench=bench_path) import utils, app reload(utils) reload(app) if patch: if not no_backup: backup_all_sites(bench=bench_path) patch_sites(bench=bench_path) if build: build_assets(bench=bench_path) if upgrade and (version_upgrade[0] or (not version_upgrade[0] and force)): post_upgrade(version_upgrade[1], version_upgrade[2], bench=bench_path) if restart_supervisor or conf.get('restart_supervisor_on_update'): restart_supervisor_processes(bench=bench_path) print "_"*80 print "Bench: Open source installer + admin for Frappe and ERPNext (https://erpnext.com)" print
def make_bench_manager_nginx_conf(bench_path, yes=False, port=23624, domain=None): from bench import env from bench.config.site_config import get_site_config from bench.config.common_site_config import get_config template = env.get_template('bench_manager_nginx.conf') bench_path = os.path.abspath(bench_path) sites_path = os.path.join(bench_path, "sites") config = get_config(bench_path) site_config = get_site_config(domain, bench_path=bench_path) sites = prepare_sites(config, bench_path) bench_name = get_bench_name(bench_path) template_vars = { "port": port, "domain": domain, "bench_manager_site_name": "bench-manager.local", "sites_path": sites_path, "http_timeout": config.get("http_timeout"), "webserver_port": config.get('webserver_port'), "socketio_port": config.get('socketio_port'), "bench_name": bench_name, "error_pages": get_error_pages(), "ssl_certificate": site_config.get('ssl_certificate'), "ssl_certificate_key": site_config.get('ssl_certificate_key') } bench_manager_nginx_conf = template.render(**template_vars) conf_path = os.path.join(bench_path, "config", "nginx.conf") if not yes and os.path.exists(conf_path): click.confirm('nginx.conf already exists and bench-manager configuration will be appended to it. Do you want to continue?', abort=True) with open(conf_path, "a") as myfile: myfile.write(bench_manager_nginx_conf)
def update(pull=False, patch=False, build=False, bench=False, auto=False, restart_supervisor=False, restart_systemd=False, requirements=False, no_backup=False, force=False, reset=False): "Update bench" if not (pull or patch or build or bench or requirements): pull, patch, build, bench, requirements = True, True, True, True, True if auto: sys.exit(1) patches.run(bench_path='.') conf = get_config(".") if bench and conf.get('update_bench_on_update'): update_bench() restart_update({ 'pull': pull, 'patch': patch, 'build': build, 'requirements': requirements, 'no-backup': no_backup, 'restart-supervisor': restart_supervisor, 'reset': reset }) if conf.get('release_bench'): print('Release bench, cannot update') sys.exit(1) version_upgrade = is_version_upgrade() if version_upgrade[0]: print() print() print("This update will cause a major version change in Frappe/ERPNext from {0} to {1}.".format(*version_upgrade[1:])) print("This would take significant time to migrate and might break custom apps.") click.confirm('Do you want to continue?', abort=True) _update(pull, patch, build, bench, auto, restart_supervisor, restart_systemd, requirements, no_backup, force=force, reset=reset)
def generate_systemd_config(bench_path, user=None, yes=False, stop=False, create_symlinks=False, delete_symlinks=False): if not user: user = getpass.getuser() config = get_config(bench_path=bench_path) bench_dir = os.path.abspath(bench_path) bench_name = get_bench_name(bench_path) if stop: exec_cmd('sudo systemctl stop -- $(systemctl show -p Requires {bench_name}.target | cut -d= -f2)'.format(bench_name=bench_name)) return if create_symlinks: _create_symlinks(bench_path) return if delete_symlinks: _delete_symlinks(bench_path) return number_of_workers = config.get('background_workers') or 1 background_workers = [] for i in range(number_of_workers): background_workers.append(get_bench_name(bench_path) + "-frappe-default-worker@" + str(i+1) + ".service") for i in range(number_of_workers): background_workers.append(get_bench_name(bench_path) + "-frappe-short-worker@" + str(i+1) + ".service") for i in range(number_of_workers): background_workers.append(get_bench_name(bench_path) + "-frappe-long-worker@" + str(i+1) + ".service") bench_info = { "bench_dir": bench_dir, "sites_dir": os.path.join(bench_dir, 'sites'), "user": user, "frappe_version": get_current_frappe_version(bench_path), "use_rq": use_rq(bench_path), "http_timeout": config.get("http_timeout", 120), "redis_server": find_executable('redis-server'), "node": find_executable('node') or find_executable('nodejs'), "redis_cache_config": os.path.join(bench_dir, 'config', 'redis_cache.conf'), "redis_socketio_config": os.path.join(bench_dir, 'config', 'redis_socketio.conf'), "redis_queue_config": os.path.join(bench_dir, 'config', 'redis_queue.conf'), "webserver_port": config.get('webserver_port', 8000), "gunicorn_workers": config.get('gunicorn_workers', get_gunicorn_workers()["gunicorn_workers"]), "bench_name": get_bench_name(bench_path), "worker_target_wants": " ".join(background_workers), "bench_cmd": find_executable('bench') } if not yes: click.confirm('current systemd configuration will be overwritten. Do you want to continue?', abort=True) setup_systemd_directory(bench_path) setup_main_config(bench_info, bench_path) setup_workers_config(bench_info, bench_path) setup_web_config(bench_info, bench_path) setup_redis_config(bench_info, bench_path) update_config({'restart_systemd_on_update': True}, bench_path=bench_path) update_config({'restart_supervisor_on_update': False}, bench_path=bench_path)
def migrate_env(python, no_backup = False): """ Migrate Virtual Environment to desired Python Version. """ try: # Clear Cache before Bench Dies. config = get_config(bench_path = os.getcwd()) rredis = urlparse(config['redis_cache']) redis = '{redis} -p {port}'.format( redis = which('redis-cli'), port = rredis.port ) log.debug('Clearing Redis Cache...') exec_cmd('{redis} FLUSHALL'.format(redis = redis)) log.debug('Clearing Redis DataBase...') exec_cmd('{redis} FLUSHDB'.format(redis = redis)) except Exception: log.warn('Please ensure Redis Connections are running or Daemonized.') try: # This is with the assumption that a bench is set-up within path. path = os.getcwd() # I know, bad name for a flag. Thanks, Ameya! :| - <*****@*****.**> if not no_backup: # Back, the f*ck up. parch = osp.join(path, 'archived_envs') if not osp.exists(parch): os.mkdir(parch) # Simply moving. Thanks, Ameya. # I'm keen to zip. source = osp.join(path, 'env') target = parch log.debug('Backing up Virtual Environment') stamp = datetime.now().strftime('%Y%m%d_%H%M%S') dest = osp.join(path, str(stamp)) # WARNING: This is an archive, you might have to use virtualenv --relocate # That's because virtualenv creates symlinks with shebangs pointing to executables. # shebangs, shebangs - ricky martin. # ...and shutil.copytree is a f*cking mess. os.rename(source, dest) shutil.move(dest, target) log.debug('Setting up a New Virtual {python} Environment'.format( python = python )) # Path to Python Executable (Basically $PYTHONPTH) python = which(python) virtualenv = which('virtualenv') nvenv = 'env' pvenv = osp.join(path, nvenv) exec_cmd('{virtualenv} --python {python} {pvenv}'.format( virtualenv = virtualenv, python = python, pvenv = pvenv ), cwd = path) pip = osp.join(pvenv, 'bin', 'pip') # pip 10 seems to have a few problems associated with it, temporary freeze pip at 9.0.3 exec_cmd('{pip} install --upgrade pip==9.0.3'.format(pip=pip)) exec_cmd('{pip} install --upgrade setuptools'.format(pip=pip)) # TODO: Options papps = osp.join(path, 'apps') apps = ['frappe', 'erpnext'] + [app for app in os.listdir(papps) if app not in ['frappe', 'erpnext']] for app in apps: papp = osp.join(papps, app) if osp.isdir(papp) and osp.exists(osp.join(papp, 'setup.py')): exec_cmd('{pip} install -e {app}'.format( pip = pip, app = papp )) log.debug('Migration Successful to {python}'.format( python = python )) except: log.debug('Migration Error') raise