mirror of https://github.com/BOINC/boinc.git
310 lines
10 KiB
Python
Executable File
310 lines
10 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
# $Id$
|
|
# Creates a new BOINC project.
|
|
|
|
# TODO: use database.py (mainly for setup_project.py)
|
|
# TODO: don't add app / app version here.
|
|
# TODO: create 'apps' subdirectory and set it in config.xml
|
|
# TODO: use configxml module
|
|
|
|
import boinc_path_config
|
|
from Boinc.setup_project import *
|
|
from Boinc import database, db_mid, configxml, tools
|
|
import sys, os, getopt, re, socket
|
|
|
|
def gethostname():
|
|
try:
|
|
return socket.gethostbyaddr(socket.gethostname())[0]
|
|
except:
|
|
return 'localhost'
|
|
|
|
def isurl(s):
|
|
return s.startswith('http://') or s.startswith('https://')
|
|
|
|
argv0 = sys.argv[0]
|
|
HOME = os.path.expanduser('~')
|
|
USER = os.environ['USER']
|
|
NODENAME = gethostname()
|
|
|
|
HELP = """
|
|
syntax: %(argv0)s [options] project ['Project Long Name']
|
|
|
|
Creates a new project with given name with everything running on a single
|
|
server.
|
|
|
|
Misc options:
|
|
--verbose={0,1,2} default: 1
|
|
-v alias for --verbose=2
|
|
--no_query accept all directories without querying
|
|
--user_name default: $USER (%(USER)s)
|
|
--delete_prev_inst delete project-root first (from prev installation)
|
|
--drop_db_first drop database first (from prev installation)
|
|
|
|
Dir-options:
|
|
--base default: $HOME (%(HOME)s)
|
|
--key_dir default: BASE/keys
|
|
--project_root default: BASE/projects/PROJECT
|
|
--url_base default: http://$NODENAME/ (http://%(NODENAME)s/)
|
|
|
|
--html_user_url default: URL_BASE/PROJECT/
|
|
--html_ops_url default: URL_BASE/PROJECT_ops/
|
|
--cgi_url default: URL_BASE/PROJECT_cgi/
|
|
|
|
Other:
|
|
--db_name default: PROJECT
|
|
|
|
Example command line:
|
|
./make_project --base $HOME/boinc --url_base http://boink/ yah 'YETI @ Home'
|
|
|
|
Then upload_dir = $HOME/boinc/projects/yah/upload
|
|
and cgi_url = http://boink/yah_cgi/
|
|
|
|
By default, directory options will be queried if they do not exist yet.
|
|
|
|
""" %locals()
|
|
|
|
# Project-specific directory structure that you probably don't need to change:
|
|
|
|
# --bin_dir default: PROJECT_ROOT/bin
|
|
# --cgi_bin_dir default: PROJECT_ROOT/cgi-bin
|
|
# --html_user_dir default: PROJECT_ROOT/html_user
|
|
# --html_ops_dir default: PROJECT_ROOT/html_ops
|
|
# --download_dir default: PROJECT_ROOT/download
|
|
# --upload_dir default: PROJECT_ROOT/upload
|
|
# --log_dir default: PROJECT_ROOT/log
|
|
# --pid_dir default: PROJECT_ROOT/pid
|
|
|
|
def syntax_error(str):
|
|
raise SystemExit('%s; See "%s --help" for help\n' % (str,sys.argv[0]))
|
|
|
|
def usage():
|
|
print HELP
|
|
raise SystemExit
|
|
|
|
try:
|
|
opts, args = getopt.getopt(sys.argv[1:],
|
|
'hv',
|
|
[ 'help',
|
|
'verbose=',
|
|
'no_query',
|
|
'user_name=',
|
|
'drop_db_first',
|
|
'delete_prev_inst',
|
|
'base=',
|
|
'key_dir=',
|
|
'project_root=',
|
|
'url_base=',
|
|
'html_user_url=',
|
|
'html_ops_url=',
|
|
'cgi_url=',
|
|
# 'bin_dir=',
|
|
# 'cgi_bin_dir=',
|
|
# 'html_user_dir=',
|
|
# 'html_ops_dir=',
|
|
# 'download_dir=',
|
|
# 'upload_dir=',
|
|
# 'log_dir=',
|
|
# 'pid_dir='
|
|
])
|
|
except getopt.GetoptError, e:
|
|
syntax_error(e)
|
|
|
|
options.url_base = None
|
|
options.no_query = False
|
|
options.delete_prev_inst = False
|
|
|
|
for o,a in opts:
|
|
if o == '-h' or o == '--help': usage()
|
|
elif o == '-v': options.echo_verbose = 2
|
|
elif o == '--verbose': options.echo_verbose = int(a)
|
|
elif o == '--no_query': options.no_query = True
|
|
elif o == '--user_name': options.user_name = a
|
|
elif o == '--drop_db_first': options.drop_db_first = True
|
|
elif o == '--delete_prev_inst': options.delete_prev_inst = True
|
|
elif o == '--base': options.base = a
|
|
elif o == '--key_dir': options.key_dir = a
|
|
elif o == '--project_root': options.project_root = a
|
|
elif o == '--url_base': options.url_base = a
|
|
elif o == '--html_user_url': options.html_user_url = a
|
|
elif o == '--html_ops_url': options.html_ops_url = a
|
|
elif o == '--cgi_url': options.cgi_url = a
|
|
elif o == '--db_name': options.db_name = a
|
|
# elif o == '--bin_dir': options.bin_dir = a
|
|
# elif o == '--cgi_bin_dir': options.cgi_bin_dir = a
|
|
# elif o == '--html_user_dir': options.html_user_dir = a
|
|
# elif o == '--html_ops_dir': options.html_ops_dir = a
|
|
# elif o == '--download_dir': options.download_dir = a
|
|
# elif o == '--upload_dir': options.upload_dir = a
|
|
# elif o == '--log_dir': options.log_dir = a
|
|
# elif o == '--pid_dir': options.pid_dir = a
|
|
else:
|
|
raise SystemExit('internal error o=%s'%o)
|
|
|
|
if len(args) == 2:
|
|
(project_shortname, project_longname) = args
|
|
elif len(args) == 1:
|
|
(project_shortname, project_longname) = args[0], args[0].capitalize()
|
|
else:
|
|
syntax_error('Need one or two arguments')
|
|
|
|
opt_repls = {'PROJECT':project_shortname,
|
|
'PROJECT_ops':project_shortname+'_ops',
|
|
'PROJECT_cgi':project_shortname+'_cgi'}
|
|
def delete_slash(str):
|
|
return os.path.join(str,'')[:-1]
|
|
def add_slash(str, action=True):
|
|
if action:
|
|
return os.path.join(str,'')
|
|
else:
|
|
return str
|
|
def replopt(str):
|
|
for key in opt_repls:
|
|
str = str.replace(key, delete_slash(opt_repls[key]))
|
|
return str
|
|
def defopt(name, v, isdir=True):
|
|
options.__dict__[name] = opt_repls[name.upper()] = add_slash(replopt(options.__dict__.get(name) or v), isdir)
|
|
|
|
defopt('url_base' , 'http://%s/'%NODENAME)
|
|
|
|
if not isurl(options.url_base):
|
|
syntax_error('url_base needs to be an URL')
|
|
|
|
defopt('html_user_url' , 'URL_BASE/PROJECT')
|
|
defopt('html_ops_url' , 'URL_BASE/PROJECT_ops')
|
|
defopt('cgi_url' , 'URL_BASE/PROJECT_cgi')
|
|
|
|
defopt('user_name' , USER, isdir=False)
|
|
defopt('base' , HOME)
|
|
defopt('key_dir' , 'BASE/keys')
|
|
defopt('project_root' , 'BASE/projects/PROJECT')
|
|
|
|
defopt('db_name' , 'PROJECT', isdir=False)
|
|
|
|
print "Creating project '%s' (short name '%s'):" %(project_longname, project_shortname)
|
|
for k in ['base',
|
|
'key_dir',
|
|
'project_root',
|
|
'url_base',
|
|
'html_user_url',
|
|
'html_ops_url',
|
|
'cgi_url' ]:
|
|
print k.upper().rjust(15), "=", options.__dict__[k]
|
|
|
|
project_root_parent = os.path.realpath(os.path.join(options.project_root,'..'))
|
|
if not os.path.exists(project_root_parent):
|
|
os.makedirs(project_root_parent)
|
|
|
|
if os.path.exists(options.project_root):
|
|
if options.delete_prev_inst:
|
|
if not options.no_query:
|
|
if not query_noyes('Delete %s?'%options.project_root):
|
|
raise SystemExit('Aborted')
|
|
print "Deleting", options.project_root
|
|
rmtree(options.project_root)
|
|
else:
|
|
raise SystemExit('Project root already exists! Specify --delete_prev_inst --drop_db_first to clobber')
|
|
|
|
if not options.no_query:
|
|
if not query_yesno("Continue?"):
|
|
raise SystemExit('Aborted')
|
|
|
|
options.install_method = 'copy'
|
|
init()
|
|
project = Project(project_shortname, project_longname,
|
|
project_dir = options.project_root,
|
|
master_url = options.html_user_url,
|
|
cgi_url = options.cgi_url,
|
|
key_dir = options.key_dir,
|
|
db_name = options.db_name
|
|
)
|
|
|
|
project.install_project()
|
|
|
|
# project.sched_install('feeder')
|
|
# project.sched_install('transitioner')
|
|
# project.sched_install('validate_test')
|
|
# project.sched_install('assimilator')
|
|
# project.sched_install('file_deleter')
|
|
|
|
httpd_conf_template_filename = os.path.join(options.project_root,
|
|
project_shortname+'.httpd.conf')
|
|
|
|
proot = delete_slash(options.project_root)
|
|
html_user_url = options.html_user_url
|
|
html_ops_url = options.html_ops_url
|
|
|
|
print >>open(httpd_conf_template_filename,'w'), '''
|
|
|
|
## Settings for BOINC project %(project_longname)s
|
|
|
|
Alias /%(project_shortname)s %(proot)s/html_user
|
|
Alias /%(project_shortname)s_ops %(proot)s/html_ops
|
|
ScriptAlias /%(project_shortname)s_cgi %(proot)s/cgi-bin
|
|
|
|
# Note: projects/*/keys/ should NOT be readable!
|
|
|
|
<Directory "%(proot)s/html_user">
|
|
Options Indexes FollowSymlinks MultiViews
|
|
AllowOverride None
|
|
Order allow,deny
|
|
Allow from all
|
|
</Directory>
|
|
|
|
<Directory "%(proot)s/html_ops">
|
|
Options FollowSymLinks
|
|
AllowOverride AuthConfig
|
|
Order allow,deny
|
|
Allow from all
|
|
</Directory>
|
|
|
|
<Directory "%(proot)s/cgi-bin">
|
|
Options ExecCGI
|
|
Order allow,deny
|
|
Allow from all
|
|
</Directory>
|
|
''' %locals()
|
|
|
|
print '''Done installing files.
|
|
|
|
Steps to complete installation:
|
|
|
|
1. Set permissions for Apache:
|
|
|
|
cat %(httpd_conf_template_filename)s >> /etc/apache/httpd.conf && apachectl restart
|
|
|
|
# (path to httpd.conf varies)
|
|
|
|
2. Add to crontab (as %(USER)s)
|
|
(If cron cannot run "start", try using a helper script to set PATH and
|
|
PYTHONPATH)
|
|
|
|
0,5,10,15,20,25,30,35,40,45,50,55 * * * * %(proot)s/bin/start --cron
|
|
|
|
To start, show status, stop BOINC daemons run:
|
|
|
|
%(proot)s/bin/start
|
|
%(proot)s/bin/status
|
|
%(proot)s/bin/stop
|
|
|
|
Master URL: %(html_user_url)s
|
|
Administration URL: %(html_ops_url)s
|
|
|
|
Tasks to do:
|
|
|
|
1. Add platform(s)
|
|
%(proot)s/bin/add platform --name=c64 --user_f="Commodore 64"
|
|
%(proot)s/bin/add platform --name=i686-pc-linux-gnu --user_f="Linux x86"
|
|
|
|
2. Add application(s)
|
|
%(proot)s/bin/add app --name=SpaghettiAtHome
|
|
|
|
3. Add core client and application binaries
|
|
|
|
3a. Place compiled clients in %(proot)s/apps/boinc/ and %(proot)s/apps/APP/
|
|
3b. Run %(proot)s/bin/update_versions
|
|
|
|
4. Generate work : read documentation at http://boinc.berkeley.edu/
|
|
|
|
'''%locals()
|