2
0
mirror of https://github.com/frappe/bench.git synced 2025-01-23 23:18:24 +00:00

[enhancement] multi-bench setup and test cases for bench with [travis]

This commit is contained in:
Anand Doshi 2016-02-25 17:41:08 +05:30
parent 2a4665ca37
commit 6797768572
11 changed files with 257 additions and 93 deletions

16
.travis.yml Normal file
View File

@ -0,0 +1,16 @@
language: python
python:
- "2.7"
install:
- sudo apt-get purge -y mysql-common
- sudo bash $TRAVIS_BUILD_DIR/install_scripts/setup_frappe.sh --skip-install-bench --mysql-root-password travis
- mkdir -p ~/bench-repo
- cp -r $TRAVIS_BUILD_DIR/* ~/bench-repo/
script:
- cd ~
- sudo pip install --upgrade pip
- sudo pip install -e bench-repo
- sudo python -m unittest bench.tests.test_setup_production

View File

@ -18,7 +18,7 @@ from .utils import (build_assets, patch_sites, exec_cmd, update_bench, get_env_c
from .app import get_app as _get_app from .app import get_app as _get_app
from .app import new_app as _new_app from .app import new_app as _new_app
from .app import pull_all_apps, get_apps, get_current_frappe_version, is_version_upgrade, switch_to_v4, switch_to_v5, switch_to_master, switch_to_develop from .app import pull_all_apps, get_apps, get_current_frappe_version, is_version_upgrade, switch_to_v4, switch_to_v5, switch_to_master, switch_to_develop
from .config import generate_nginx_config, generate_supervisor_config, generate_redis_cache_config, generate_redis_async_broker_config from .config import generate_nginx_config, generate_supervisor_config, generate_redis_cache_config, generate_redis_async_broker_config, generate_redis_celery_broker_config
from .production_setup import setup_production as _setup_production from .production_setup import setup_production as _setup_production
from .migrate_to_v5 import migrate_to_v5 from .migrate_to_v5 import migrate_to_v5
import os import os
@ -74,7 +74,7 @@ def check_uid():
def change_uid(): def change_uid():
if is_root() and not cmd_requires_root(): if is_root() and not cmd_requires_root():
frappe_user = get_config().get('frappe_user') frappe_user = get_config(".").get('frappe_user')
if frappe_user: if frappe_user:
drop_privileges(uid_name=frappe_user, gid_name=frappe_user) drop_privileges(uid_name=frappe_user, gid_name=frappe_user)
os.environ['HOME'] = pwd.getpwnam(frappe_user).pw_dir os.environ['HOME'] = pwd.getpwnam(frappe_user).pw_dir
@ -206,7 +206,7 @@ def _update(pull=False, patch=False, build=False, bench=False, auto=False, resta
if not (pull or patch or build or bench or requirements): if not (pull or patch or build or bench or requirements):
pull, patch, build, bench, requirements = True, True, True, True, True pull, patch, build, bench, requirements = True, True, True, True, True
conf = get_config() conf = get_config(".")
version_upgrade = is_version_upgrade() version_upgrade = is_version_upgrade()
@ -449,6 +449,11 @@ def setup_redis_async_broker():
"generate config for redis async broker" "generate config for redis async broker"
generate_redis_async_broker_config() generate_redis_async_broker_config()
@click.command('redis-celery-broker')
def setup_redis_celery_broker():
"generate config for redis celery broker"
generate_redis_celery_broker_config()
@click.command('production') @click.command('production')
@click.argument('user') @click.argument('user')
def setup_production(user): def setup_production(user):
@ -496,6 +501,7 @@ setup.add_command(setup_sudoers)
setup.add_command(setup_supervisor) setup.add_command(setup_supervisor)
setup.add_command(setup_redis_cache) setup.add_command(setup_redis_cache)
setup.add_command(setup_redis_async_broker) setup.add_command(setup_redis_async_broker)
setup.add_command(setup_redis_celery_broker)
setup.add_command(setup_auto_update) setup.add_command(setup_auto_update)
setup.add_command(setup_dnsmasq) setup.add_command(setup_dnsmasq)
setup.add_command(setup_backups) setup.add_command(setup_backups)

View File

@ -6,7 +6,7 @@ import shutil
import socket import socket
from distutils.spawn import find_executable from distutils.spawn import find_executable
from jinja2 import Environment, PackageLoader from jinja2 import Environment, PackageLoader
from .utils import get_sites, get_config, update_config, get_redis_version from .utils import get_sites, get_config, update_config, get_redis_version, update_common_site_config
env = Environment(loader=PackageLoader('bench', 'templates'), trim_blocks=True) env = Environment(loader=PackageLoader('bench', 'templates'), trim_blocks=True)
@ -30,6 +30,7 @@ def generate_supervisor_config(bench='.', user=None):
sites = get_sites(bench=bench) sites = get_sites(bench=bench)
if not user: if not user:
user = getpass.getuser() user = getpass.getuser()
config = get_config(bench=bench) config = get_config(bench=bench)
config = template.render(**{ config = template.render(**{
@ -41,9 +42,11 @@ def generate_supervisor_config(bench='.', user=None):
"node": find_executable('node') or find_executable('nodejs'), "node": find_executable('node') or find_executable('nodejs'),
"redis_cache_config": os.path.join(bench_dir, 'config', 'redis_cache.conf'), "redis_cache_config": os.path.join(bench_dir, 'config', 'redis_cache.conf'),
"redis_async_broker_config": os.path.join(bench_dir, 'config', 'redis_async_broker.conf'), "redis_async_broker_config": os.path.join(bench_dir, 'config', 'redis_async_broker.conf'),
"redis_celery_broker_config": os.path.join(bench_dir, 'config', 'redis_celery_broker.conf'),
"frappe_version": get_current_frappe_version(), "frappe_version": get_current_frappe_version(),
"webserver_port": config.get('webserver_port'), "webserver_port": config.get('webserver_port', 8000),
"n_workers": config.get('max_workers') "n_workers": config.get('max_workers', 2),
"bench_name": os.path.basename(os.path.abspath(bench))
}) })
write_config_file(bench, 'supervisor.conf', config) write_config_file(bench, 'supervisor.conf', config)
update_config({'restart_supervisor_on_update': True}) update_config({'restart_supervisor_on_update': True})
@ -55,26 +58,23 @@ def get_site_config(site, bench='.'):
def generate_common_site_config(bench='.'): def generate_common_site_config(bench='.'):
'''Generates the default common_site_config.json while a new bench is created''' '''Generates the default common_site_config.json while a new bench is created'''
config = get_config(bench=bench) config = get_config(bench=bench)
common_site_config = {}
celery_broker_port = config.get('redis_celery_broker_port', '11311') for bench_config_field, site_config_field in (
celery_broker = 'redis://localhost:{0}'.format(celery_broker_port) ("redis_celery_broker_port", "celery_broker"),
("redis_async_broker_port", "async_redis_server"),
("redis_cache_port", "cache_redis_server")
):
async_redis_server_port = config.get('redis_async_broker_port', '12311') port = config.get(bench_config_field)
async_redis_server = 'redis://localhost:{0}'.format(async_redis_server_port) if config.get(bench_config_field):
redis_url = "redis://localhost:{0}".format(port)
common_site_config[site_config_field] = redis_url
cache_redis_server_port = config.get('redis_cache_port', '13311') # TODO Optionally we need to add the host or domain name in case dns_multitenant is false
cache_redis_server = 'redis://localhost:{0}'.format(cache_redis_server_port)
default_common_site_config = { if common_site_config:
"celery_broker" : celery_broker, update_common_site_config(common_site_config, bench=bench)
"async_redis_server": async_redis_server,
"cache_redis_server": cache_redis_server
}
#TODO Optionally we need to add the host or domain name in case dns_multitenant is false
with open(os.path.join(bench, 'sites', 'common_site_config.json'), 'wb') as f:
json.dump(default_common_site_config, f, indent=1, sort_keys=True)
def get_sites_with_config(bench='.'): def get_sites_with_config(bench='.'):
sites = get_sites(bench=bench) sites = get_sites(bench=bench)
@ -111,7 +111,10 @@ def generate_nginx_config(bench='.'):
"http_timeout": config.get("http_timeout", 120), "http_timeout": config.get("http_timeout", 120),
"default_site": default_site, "default_site": default_site,
"dns_multitenant": config.get('dns_multitenant'), "dns_multitenant": config.get('dns_multitenant'),
"sites": sites "sites": sites,
"webserver_port": config.get('webserver_port', 8000),
"socketio_port": config.get('socketio_port', 3000),
"bench_name": os.path.basename(os.path.abspath(bench))
}) })
write_config_file(bench, 'nginx.conf', config) write_config_file(bench, 'nginx.conf', config)

View File

@ -55,16 +55,21 @@ def setup_production(user, bench='.'):
fix_prod_setup_perms(bench, frappe_user=user) fix_prod_setup_perms(bench, frappe_user=user)
remove_default_nginx_configs() remove_default_nginx_configs()
bench_name = os.path.basename(os.path.abspath(bench))
nginx_conf = '/etc/nginx/conf.d/{bench_name}.conf'.format(bench_name=bench_name)
if is_centos7(): if is_centos7():
supervisor_conf_filename = 'frappe.ini' supervisor_conf_extn = "ini"
copy_default_nginx_config() copy_default_nginx_config()
else: else:
supervisor_conf_filename = 'frappe.conf' supervisor_conf_extn = "conf"
supervisor_conf = os.path.join(get_supervisor_confdir(), '{bench_name}.{extn}'.format(
bench_name=bench_name, extn=supervisor_conf_extn))
links = ( links = (
(os.path.abspath(os.path.join(bench, 'config', 'nginx.conf')), '/etc/nginx/conf.d/frappe.conf'), (os.path.abspath(os.path.join(bench, 'config', 'nginx.conf')), nginx_conf),
(os.path.abspath(os.path.join(bench, 'config', 'supervisor.conf')), os.path.join(get_supervisor_confdir(), supervisor_conf_filename)), (os.path.abspath(os.path.join(bench, 'config', 'supervisor.conf')), supervisor_conf),
) )
for src, dest in links: for src, dest in links:
@ -74,4 +79,5 @@ def setup_production(user, bench='.'):
exec_cmd('supervisorctl reload') exec_cmd('supervisorctl reload')
if os.environ.get('NO_SERVICE_RESTART'): if os.environ.get('NO_SERVICE_RESTART'):
return return
restart_service('nginx') restart_service('nginx')

View File

@ -1,12 +1,9 @@
upstream {{ bench_name }}-frappe {
server_names_hash_bucket_size 64; server 127.0.0.1:{{ webserver_port }} fail_timeout=0;
upstream frappe {
server 127.0.0.1:8000 fail_timeout=0;
} }
upstream socketio-server { upstream {{ bench_name}}-socketio-server {
server 127.0.0.1:3000 fail_timeout=0; server 127.0.0.1:{{ socketio_port }} fail_timeout=0;
} }
{% macro location_block(site, port=80, default=False, server_name=None, sites=None, dns_multitenant=False) -%} {% macro location_block(site, port=80, default=False, server_name=None, sites=None, dns_multitenant=False) -%}
@ -24,7 +21,7 @@ upstream socketio-server {
} }
location /socket.io { location /socket.io {
proxy_pass http://socketio-server; proxy_pass http://{{ bench_name }}-socketio-server;
proxy_http_version 1.1; proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade; proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade"; proxy_set_header Connection "upgrade";
@ -36,10 +33,10 @@ upstream socketio-server {
} }
location / { location / {
try_files /{{ "$host" if dns_multitenant else site.name }}/public/$uri @magic; try_files /{{ "$host" if dns_multitenant else site.name }}/public/$uri @webserver;
} }
location @magic { location @webserver {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Proto $scheme;
{% if not dns_multitenant %} {% if not dns_multitenant %}
@ -47,9 +44,9 @@ upstream socketio-server {
{% endif %} {% endif %}
proxy_set_header Host $host; proxy_set_header Host $host;
proxy_set_header X-Use-X-Accel-Redirect True; proxy_set_header X-Use-X-Accel-Redirect True;
proxy_read_timeout {{http_timeout}}; proxy_read_timeout {{ http_timeout }};
proxy_redirect off; proxy_redirect off;
proxy_pass http://frappe; proxy_pass http://{{ bench_name }}-frappe;
} }
{%- endmacro %} {%- endmacro %}

View File

@ -33,6 +33,8 @@ http {
#keepalive_timeout 0; #keepalive_timeout 0;
keepalive_timeout 65; keepalive_timeout 65;
server_names_hash_bucket_size 64;
#gzip on; #gzip on;
index index.html index.htm; index index.html index.htm;

View File

@ -2,8 +2,8 @@
; priority=1 --> Lower priorities indicate programs that start first and shut down last ; priority=1 --> Lower priorities indicate programs that start first and shut down last
; killasgroup=true --> send kill signal to child processes too ; killasgroup=true --> send kill signal to child processes too
[program:frappe-web] [program:{{ bench_name }}-frappe-web]
command={{ bench_dir }}/env/bin/gunicorn -b 127.0.0.1:{{webserver_port}} -w {{n_workers}} -t {{http_timeout}} frappe.app:application command={{ bench_dir }}/env/bin/gunicorn -b 127.0.0.1:{{ webserver_port }} -w {{ n_workers }} -t {{ http_timeout }} frappe.app:application --preload
priority=4 priority=4
autostart=true autostart=true
autorestart=true autorestart=true
@ -12,7 +12,7 @@ stderr_logfile={{ bench_dir }}/logs/web.error.log
user={{ user }} user={{ user }}
directory={{ sites_dir }} directory={{ sites_dir }}
[program:frappe-worker] [program:{{ bench_name }}-frappe-worker]
command={{ bench_dir }}/env/bin/python -m frappe.celery_app worker -n jobs@%%h --soft-time-limit 360 --time-limit 390 --loglevel INFO -Ofair command={{ bench_dir }}/env/bin/python -m frappe.celery_app worker -n jobs@%%h --soft-time-limit 360 --time-limit 390 --loglevel INFO -Ofair
priority=4 priority=4
autostart=true autostart=true
@ -24,7 +24,7 @@ stopwaitsecs=400
directory={{ sites_dir }} directory={{ sites_dir }}
killasgroup=true killasgroup=true
[program:frappe-longjob-worker] [program:{{ bench_name }}-frappe-longjob-worker]
command={{ bench_dir }}/env/bin/python -m frappe.celery_app worker -n longjobs@%%h --soft-time-limit 1500 --time-limit 1530 --loglevel INFO command={{ bench_dir }}/env/bin/python -m frappe.celery_app worker -n longjobs@%%h --soft-time-limit 1500 --time-limit 1530 --loglevel INFO
priority=2 priority=2
autostart=true autostart=true
@ -36,7 +36,7 @@ stopwaitsecs=1540
directory={{ sites_dir }} directory={{ sites_dir }}
killasgroup=true killasgroup=true
[program:frappe-async-worker] [program:{{ bench_name }}-frappe-async-worker]
command={{ bench_dir }}/env/bin/python -m frappe.celery_app worker -n async@%%h --soft-time-limit 1500 --time-limit 1530 --loglevel INFO command={{ bench_dir }}/env/bin/python -m frappe.celery_app worker -n async@%%h --soft-time-limit 1500 --time-limit 1530 --loglevel INFO
priority=2 priority=2
autostart=true autostart=true
@ -48,7 +48,7 @@ stopwaitsecs=1540
directory={{ sites_dir }} directory={{ sites_dir }}
killasgroup=true killasgroup=true
[program:frappe-workerbeat] [program:{{ bench_name }}-frappe-workerbeat]
command={{ bench_dir }}/env/bin/python -m frappe.celery_app beat -s beat.schedule command={{ bench_dir }}/env/bin/python -m frappe.celery_app beat -s beat.schedule
priority=3 priority=3
autostart=true autostart=true
@ -58,9 +58,7 @@ stderr_logfile={{ bench_dir }}/logs/workerbeat.error.log
user={{ user }} user={{ user }}
directory={{ sites_dir }} directory={{ sites_dir }}
[program:{{ bench_name }}-redis-cache]
{% if frappe_version > 4%}
[program:redis-cache]
command={{ redis_server }} {{ redis_cache_config }} command={{ redis_server }} {{ redis_cache_config }}
priority=1 priority=1
autostart=true autostart=true
@ -69,10 +67,19 @@ stdout_logfile={{ bench_dir }}/logs/redis-cache.log
stderr_logfile={{ bench_dir }}/logs/redis-cache.error.log stderr_logfile={{ bench_dir }}/logs/redis-cache.error.log
user={{ user }} user={{ user }}
directory={{ sites_dir }} directory={{ sites_dir }}
{% endif %}
{% if frappe_version > 5%} [program:{{ bench_name }}-redis-celery-broker]
[program:redis-async-broker] command={{ redis_server }} {{ redis_celery_broker_config }}
priority=1
autostart=true
autorestart=true
stdout_logfile={{ bench_dir }}/logs/redis-celery-broker.log
stderr_logfile={{ bench_dir }}/logs/redis-celery-broker.error.log
user={{ user }}
directory={{ sites_dir }}
{% if frappe_version > 5 %}
[program:{{ bench_name }}-redis-async-broker]
command={{ redis_server }} {{ redis_async_broker_config }} command={{ redis_server }} {{ redis_async_broker_config }}
priority=1 priority=1
autostart=true autostart=true
@ -83,7 +90,7 @@ user={{ user }}
directory={{ sites_dir }} directory={{ sites_dir }}
{% if node %} {% if node %}
[program:node-socketio] [program:{{ bench_name }}-node-socketio]
command={{ node }} {{ bench_dir }}/apps/frappe/socketio.js command={{ node }} {{ bench_dir }}/apps/frappe/socketio.js
priority=4 priority=4
autostart=true autostart=true
@ -96,5 +103,8 @@ directory={{ sites_dir }}
{% endif %} {% endif %}
[group:frappe] [group:{{ bench_name }}-processes]
programs=frappe-web,frappe-worker,frappe-workerbeat programs={{ bench_name }}-frappe-web,{{ bench_name }}-frappe-worker,{{ bench_name }}-frappe-longjob-worker,{{ bench_name }}-frappe-async-worker,{{ bench_name }}-frappe-workerbeat {%- if node -%} ,{{ bench_name }}-node-socketio {%- endif%}
[group:{{ bench_name }}-redis]
programs={{ bench_name }}-redis-cache,{{ bench_name }}-redis-celery-broker {%- if frappe_version > 5 -%} ,{{ bench_name }}-redis-async-broker {%- endif %}

View File

@ -5,7 +5,6 @@ import bench.utils
import json import json
import os import os
import shutil import shutil
import socket
class TestBenchInit(unittest.TestCase): class TestBenchInit(unittest.TestCase):
def setUp(self): def setUp(self):
@ -19,9 +18,7 @@ class TestBenchInit(unittest.TestCase):
shutil.rmtree(bench_path) shutil.rmtree(bench_path)
def test_init(self, bench_name="test-bench"): def test_init(self, bench_name="test-bench"):
self.benches.append(bench_name) self.init_bench(bench_name)
bench.utils.init(bench_name)
self.assert_folders(bench_name) self.assert_folders(bench_name)
@ -34,25 +31,43 @@ class TestBenchInit(unittest.TestCase):
self.assert_socketio(bench_name) self.assert_socketio(bench_name)
def test_multiple_benches(self): def test_multiple_benches(self):
# 1st bench
self.test_init("test-bench-1") self.test_init("test-bench-1")
test_bench_1_ports = {
self.assert_ports("test-bench-1", {
"webserver_port": 8000, "webserver_port": 8000,
"socketio_port": 9000, "socketio_port": 9000,
"redis_celery_broker_port": 11000, "redis_celery_broker_port": 11000,
"redis_async_broker_port": 12000, "redis_async_broker_port": 12000,
"redis_cache_port": 13000 "redis_cache_port": 13000
} })
self.assert_ports("test-bench-1", test_bench_1_ports)
self.assert_common_site_config("test-bench-1", {
"celery_broker": "redis://localhost:11000",
"async_redis_server": "redis://localhost:12000",
"cache_redis_server": "redis://localhost:13000"
})
# 2nd bench
self.test_init("test-bench-2") self.test_init("test-bench-2")
test_bench_2_ports = {
self.assert_ports("test-bench-2", {
"webserver_port": 8001, "webserver_port": 8001,
"socketio_port": 9001, "socketio_port": 9001,
"redis_celery_broker_port": 11001, "redis_celery_broker_port": 11001,
"redis_async_broker_port": 12001, "redis_async_broker_port": 12001,
"redis_cache_port": 13001 "redis_cache_port": 13001
} })
self.assert_ports("test-bench-2", test_bench_2_ports)
self.assert_common_site_config("test-bench-2", {
"celery_broker": "redis://localhost:11001",
"async_redis_server": "redis://localhost:12001",
"cache_redis_server": "redis://localhost:13001"
})
def init_bench(self, bench_name):
self.benches.append(bench_name)
bench.utils.init(bench_name)
def assert_folders(self, bench_name): def assert_folders(self, bench_name):
for folder in bench.utils.folders_in_bench: for folder in bench.utils.folders_in_bench:
@ -70,13 +85,12 @@ class TestBenchInit(unittest.TestCase):
self.assert_exists(bench_name, "env", "lib", "python2.7", "site-packages", "pip") self.assert_exists(bench_name, "env", "lib", "python2.7", "site-packages", "pip")
def assert_bench_config(self, bench_name): def assert_bench_config(self, bench_name):
config_json = os.path.exists(os.path.join(bench_name, "config.json")) config_json = os.path.join(bench_name, "config.json")
self.assertTrue(config_json) self.assertTrue(os.path.exists(config_json))
with open(config_json, "r") as f:
print f config = self.load_json(config_json)
config_dict = json.loads(f.read().decode("utf-8")) for key, value in bench.utils.default_config.items():
for key, value in bench.utils.default_config.items(): self.assertEquals(config.get(key), value)
self.assertEquals(config_dict.get(key), value)
def assert_config(self, bench_name): def assert_config(self, bench_name):
for config, search_key in ( for config, search_key in (
@ -86,7 +100,7 @@ class TestBenchInit(unittest.TestCase):
self.assert_exists(bench_name, "config", config) self.assert_exists(bench_name, "config", config)
with open(os.path.join(self.bench, "config", config), "r") as f: with open(os.path.join(bench_name, "config", config), "r") as f:
f = f.read().decode("utf-8") f = f.read().decode("utf-8")
self.assertTrue(search_key in f) self.assertTrue(search_key in f)
@ -95,16 +109,22 @@ class TestBenchInit(unittest.TestCase):
self.assert_exists(bench_name, "node_modules", "socket.io") self.assert_exists(bench_name, "node_modules", "socket.io")
def assert_ports(self, bench_name, ports): def assert_ports(self, bench_name, ports):
config_path = os.path.join(self.benches_path, bench_name, 'config', 'config.json') config_path = os.path.join(bench_name, 'config.json')
config = self.load_json(config_path)
with open(config_path, "r") as f: for key, port in ports.items():
config_json = json.load(f) self.assertEquals(config.get(key), port)
for key, port in ports: def assert_common_site_config(self, bench_name, expected_config):
self.assertEqual(config_json.get(key), port) common_site_config_path = os.path.join(bench_name, 'sites', 'common_site_config.json')
config = self.load_json(common_site_config_path)
def assert_site_config(self, bench_name): for key, value in expected_config.items():
pass self.assertEquals(config.get(key), value)
def assert_exists(self, *args): def assert_exists(self, *args):
self.assertTrue(os.path.exists(os.path.join(*args))) self.assertTrue(os.path.exists(os.path.join(*args)))
def load_json(self, path):
with open(path, "r") as f:
return json.loads(f.read().decode("utf-8"))

View File

@ -0,0 +1,95 @@
from __future__ import unicode_literals
from bench.tests.test_init import TestBenchInit
from bench.production_setup import setup_production
import bench.utils
import os
import getpass
import re
import unittest
class TestSetupProduction(TestBenchInit):
# setUp, tearDown and other tests are defiend in TestBenchInit
def test_setup_production(self):
self.test_multiple_benches()
user = getpass.getuser()
for bench_name in ("test-bench-1", "test-bench-2"):
setup_production(user, bench_name)
self.assert_nginx_config(bench_name)
self.assert_supervisor_config(bench_name)
self.assert_supervisor_process(bench_name)
self.assert_nginx_process()
def assert_nginx_config(self, bench_name):
conf_src = os.path.join(os.path.abspath(bench_name), 'config', 'nginx.conf')
conf_dest = "/etc/nginx/conf.d/{bench_name}.conf".format(bench_name=bench_name)
self.assertTrue(os.path.exists(conf_src))
self.assertTrue(os.path.exists(conf_dest))
# symlink matches
self.assertEquals(os.path.realpath(conf_dest), conf_src)
# file content
with open(conf_src, "r") as f:
f = f.read().decode("utf-8")
for key in (
"upstream { bench_name }-frappe",
"upstream { bench_name}-socketio-server"
):
self.assertTrue(key.format(bench_name) in f)
def assert_supervisor_config(self, bench_name):
conf_src = os.path.join(os.path.abspath(bench_name), 'config', 'supervisor.conf')
conf_dest = "/etc/supervisor.d/{bench_name}.conf".format(bench_name=bench_name)
self.assertTrue(os.path.exists(conf_src))
self.assertTrue(os.path.exists(conf_dest))
# symlink matches
self.assertEquals(os.path.realpath(conf_dest), conf_src)
# file content
with open(conf_src, "r") as f:
f = f.read().decode("utf-8")
for key in (
"program:{ bench_name }-frappe-web",
"program:{ bench_name }-frappe-worker",
"program:{ bench_name }-frappe-longjob-worker",
"program:{ bench_name }-frappe-async-worker",
"program:{ bench_name }-frappe-workerbeat",
"program:{ bench_name }-redis-cache",
"program:{ bench_name }-redis-celery-broker",
"program:{ bench_name }-redis-async-broker",
"program:{ bench_name }-node-socketio",
"group:{ bench_name }-processes",
"group:{ bench_name }-redis"
):
self.assertTrue(key.format(bench_name) in f)
def assert_supervisor_process(self, bench_name):
out = bench.utils.get_cmd_output("sudo supervisorctl status")
for key in (
"{bench_name}-process:{ bench_name }-frappe-web[\s]*RUNNING",
"{bench_name}-process:{ bench_name }-frappe-worker[\s]*RUNNING",
"{bench_name}-process:{ bench_name }-frappe-longjob-worker[\s]*RUNNING",
"{bench_name}-process:{ bench_name }-frappe-async-worker[\s]*RUNNING",
"{bench_name}-process:{ bench_name }-frappe-workerbeat[\s]*RUNNING",
"{bench_name}-process:{ bench_name }-node-socketio[\s]*RUNNING",
"{bench_name}-redis:{ bench_name }-redis-cache[\s]*RUNNING",
"{bench_name}-redis:{bench_name}-redis-celery-broker[\s]*RUNNING",
"{bench_name}-redis:{bench_name}-redis-async-broker[\s]*RUNNING",
):
self.assertTrue(re.match(key.format(bench_name), out))
def assert_nginx_process(self):
out = bench.utils.get_cmd_output("sudo nginx -t")
self.assertTrue("nginx: configuration file /etc/nginx/nginx.conf test is successful" in out)

View File

@ -105,8 +105,9 @@ def get_max_worker_count():
'''This function will return the maximum workers that can be started depending upon '''This function will return the maximum workers that can be started depending upon
number of cpu's present on the machine''' number of cpu's present on the machine'''
n_cpus = multiprocessing.cpu_count() n_cpus = multiprocessing.cpu_count()
return dict(max_workers=2 * n_cpus) return {
"max_workers": (2 * n_cpus) + 1
}
def make_ports(benches_path="."): def make_ports(benches_path="."):
default_ports = { default_ports = {
@ -449,11 +450,16 @@ def update_common_site_config(ddict, bench='.'):
update_json_file(os.path.join(bench, 'sites', 'common_site_config.json'), ddict) update_json_file(os.path.join(bench, 'sites', 'common_site_config.json'), ddict)
def update_json_file(filename, ddict): def update_json_file(filename, ddict):
with open(filename, 'r') as f: if os.path.exists(filename):
content = json.load(f) with open(filename, 'r') as f:
content = json.load(f)
else:
content = {}
content.update(ddict) content.update(ddict)
with open(filename, 'w') as f: with open(filename, 'w') as f:
content = json.dump(content, f, indent=1) content = json.dump(content, f, indent=1, sort_keys=True)
def drop_privileges(uid_name='nobody', gid_name='nogroup'): def drop_privileges(uid_name='nobody', gid_name='nogroup'):
# from http://stackoverflow.com/a/2699996 # from http://stackoverflow.com/a/2699996

View File

@ -16,7 +16,7 @@ get_passwd() {
} }
set_opts () { set_opts () {
OPTS=`getopt -o v --long verbose,mysql-root-password:,frappe-user:,bench-branch:,setup-production,skip-setup-bench,help -n 'parse-options' -- "$@"` OPTS=`getopt -o v --long verbose,mysql-root-password:,frappe-user:,bench-branch:,setup-production,skip-install-bench,skip-setup-bench,help -n 'parse-options' -- "$@"`
if [ $? != 0 ] ; then echo "Failed parsing options." >&2 ; exit 1 ; fi if [ $? != 0 ] ; then echo "Failed parsing options." >&2 ; exit 1 ; fi
@ -27,6 +27,7 @@ set_opts () {
FRAPPE_USER=false FRAPPE_USER=false
BENCH_BRANCH="master" BENCH_BRANCH="master"
SETUP_PROD=false SETUP_PROD=false
INSTALL_BENCH=true
SETUP_BENCH=true SETUP_BENCH=true
if [ -f ~/frappe_passwords.sh ]; then if [ -f ~/frappe_passwords.sh ]; then
@ -50,6 +51,7 @@ set_opts () {
--setup-production ) SETUP_PROD=true; shift;; --setup-production ) SETUP_PROD=true; shift;;
--bench-branch ) BENCH_BRANCH="$2"; shift;; --bench-branch ) BENCH_BRANCH="$2"; shift;;
--skip-setup-bench ) SETUP_BENCH=false; shift;; --skip-setup-bench ) SETUP_BENCH=false; shift;;
--skip-install-bench ) INSTALL_BENCH=false; shift;;
-- ) shift; break ;; -- ) shift; break ;;
* ) break ;; * ) break ;;
esac esac
@ -202,14 +204,12 @@ install_packages() {
elif [ $OS == "debian" ] || [ $OS == "Ubuntu" ]; then elif [ $OS == "debian" ] || [ $OS == "Ubuntu" ]; then
export DEBIAN_FRONTEND=noninteractive export DEBIAN_FRONTEND=noninteractive
setup_debconf setup_debconf
if [ $OS == "debian" ]; then run_cmd bash -c "curl -sL https://deb.nodesource.com/setup_0.12 | sudo bash -"
run_cmd bash -c "curl -sL https://deb.nodesource.com/setup_0.12 | bash -"
fi
run_cmd sudo apt-get update run_cmd sudo apt-get update
run_cmd sudo apt-get install -y python-dev python-setuptools build-essential python-mysqldb git \ run_cmd sudo apt-get install -y python-dev python-setuptools build-essential python-mysqldb git \
ntp vim screen htop mariadb-server mariadb-common libmariadbclient-dev \ ntp vim screen htop mariadb-server mariadb-common libmariadbclient-dev \
libxslt1.1 libxslt1-dev redis-server libssl-dev libcrypto++-dev postfix nginx \ libxslt1.1 libxslt1-dev redis-server libssl-dev libcrypto++-dev postfix nginx \
supervisor python-pip fontconfig libxrender1 libxext6 xfonts-75dpi xfonts-base nodejs npm supervisor python-pip fontconfig libxrender1 libxext6 xfonts-75dpi xfonts-base nodejs
if [ $OS_VER == "precise" ]; then if [ $OS_VER == "precise" ]; then
run_cmd sudo apt-get install -y libtiff4-dev libjpeg8-dev zlib1g-dev libfreetype6-dev liblcms2-dev libwebp-dev tcl8.5-dev tk8.5-dev python-tk run_cmd sudo apt-get install -y libtiff4-dev libjpeg8-dev zlib1g-dev libfreetype6-dev liblcms2-dev libwebp-dev tcl8.5-dev tk8.5-dev python-tk
@ -454,9 +454,12 @@ main() {
configure_mariadb configure_mariadb
echo "Adding frappe user" echo "Adding frappe user"
add_user add_user
install_bench
if $SETUP_BENCH; then if $INSTALL_BENCH; then
setup_bench install_bench
if $SETUP_BENCH; then
setup_bench
fi
fi fi
echo echo