This repository has been archived by the owner on Oct 6, 2018. It is now read-only.
forked from marius311/boinc2docker
-
Notifications
You must be signed in to change notification settings - Fork 1
/
boinc2docker_create_app
executable file
·176 lines (146 loc) · 6.3 KB
/
boinc2docker_create_app
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
#!/usr/bin/env python
import argparse
from os import fchmod, environ, chmod, makedirs as _makedirs
from os.path import join, exists, basename, dirname, abspath
import yaml
from zipfile import ZipFile
from functools import partial
from subprocess import check_output
from shutil import copy as _copy
from distutils.dir_util import copy_tree
import xml.etree.ElementTree as et
from xml.dom import minidom
#some convenience stuff
rootdir=dirname(abspath(__file__))
sh = lambda cmd: check_output(['sh','-c',cmd])
fmt = partial(lambda s,l: s.format(**l),l=locals())
def download(f):
tgt=join(args.tmpdir,basename(f))
sh('wget --progress=bar:force --content-disposition %s -O %s'%(f,tgt))
return tgt
def makedirs(d):
if not exists(d): _makedirs(d)
class attrdict(dict):
def __init__(self,*args,**kwargs):
super(attrdict, self).__init__(*args, **kwargs)
self.__dict__ = self
def copy(src,dst,clobber=True):
if clobber or not exists(dst): _copy(src,dst)
#functions for downloading ISO and vboxwrapper
def get_vboxwrapper(platform):
"""
Download and unzip vboxwrapper executables from http://boinc.berkeley.edu/dl
"""
vboxwrapper_root = fmt(("vboxwrapper_{args.vboxwrapper[%s]}_"%platform)+platform)
vboxwrapper_file = join(args.tmpdir,vboxwrapper_root+('.exe' if 'windows' in platform else ''))
if not exists(vboxwrapper_file):
with ZipFile(download('http://boinc.berkeley.edu/dl/'+vboxwrapper_root+'.zip')) as zf:
with open(vboxwrapper_file,'wb') as f:
zi={basename(z.filename):z for z in zf.filelist}[basename(vboxwrapper_file)]
f.write(zf.read(zi))
fchmod(f.fileno(), 0o775)
return vboxwrapper_file
def get_iso():
"""
Download ISO from Github
"""
iso_file = join(args.tmpdir,fmt("vm_isocontext_v{args.iso}.iso"))
if not exists(iso_file):
download(fmt("https://github.com/marius311/boinc2docker/releases/download/iso%2Fv{args.iso}/vm_isocontext_v{args.iso}.iso"))
return iso_file
# load and parse options
defaults = yaml.load(open(join(rootdir,'boinc2docker.yml')))
defaults.update({
'tmpdir':join(rootdir,'build'),
'projhome':environ.get('PROJHOME')
})
args = [
['iso', 'boinc2docker ISO version to use'],
['vboxwrapper', 'vboxwrapper version to use'],
['projhome', 'project home'],
['appname', 'name to give the app'],
['appver', 'version to give the app'],
['resultsdir', 'where to assimilate results to (default: /results/APPNAME)'],
['tmpdir', "where to store downloaded ISO and vboxwrapper exe's"],
['dont_install', 'one or more of ["template_in","template_out","assimilator"'],
]
parser = argparse.ArgumentParser(prog='boinc2docker_create_app')
for a,h in args:
if a == 'dont_install':
parser.add_argument('--'+a, default=[], nargs='+', help=h)
elif a in defaults:
parser.add_argument('--'+a, default=defaults[a], help=h+' (default: %s)'%defaults[a])
else:
parser.add_argument('--'+a, help=h)
parser.add_argument('boinc2docker.yml', nargs='?', help="boinc2docker.yml file containing confirugation options")
args = attrdict(defaults,**vars(parser.parse_args()))
if args['boinc2docker.yml'] is not None:
args.update(yaml.load(open(args['boinc2docker.yml'])))
if args.resultsdir is None:
args.resultsdir = join('/results',args.appname)
if not args.projhome: raise ValueError("Please specify either --projhome option or $PROJHOME variable")
for x in args.dont_install:
if x not in ['template_in','template_out','assimilator']:
raise ValueError("Unrecognized argument '%s' given to --dont_install"%x)
approot=join(args.projhome,'apps',args.appname,args.appver)
# create app versions
makedirs(args.tmpdir)
platforms = ["x86_64-pc-linux-gnu","windows_x86_64", "x86_64-apple-darwin"]
if isinstance(args.vboxwrapper,str):
args.vboxwrapper = {platform:args.vboxwrapper for platform in platforms}
for platform in platforms:
appfolder = join(approot,platform+'__vbox64_mt')
makedirs(appfolder)
vboxwrapper_file = get_vboxwrapper(platform)
iso_file = get_iso()
#version.xml
open(join(appfolder,'version.xml'),'w').write(
open(join(rootdir,'version.xml')).read().format(vboxwrapper=basename(vboxwrapper_file),iso=basename(iso_file))
)
#vboxwrapper and ISO
copy(vboxwrapper_file,appfolder)
copy(iso_file,appfolder)
# project files
for d in ['bin','templates']: makedirs(join(args.projhome,d))
copy_tree(join(rootdir,'py'),join(args.projhome,'py'))
for t in ['in','out']:
if fmt('template_{t}') not in args.dont_install:
copy(join(rootdir,fmt('templates/boinc2docker_{t}')),
join(args.projhome,'templates',fmt('{args.appname}_{t}')))
copy(join(rootdir,'bin','boinc2docker_create_work.py'),join(args.projhome,'bin'))
if "assimilator" not in args.dont_install:
assimilator_file=join(args.projhome,'bin',fmt('{args.appname}_assimilator'))
open(assimilator_file,'w').write(
open(join(rootdir,'bin','boinc2docker_assimilator')).read().replace('{results}',args.resultsdir)
)
chmod(assimilator_file,0755)
# merge stuff into plan_class_spec.xml and project.xml
def xmlmerge(src,dst,idkey='name'):
"""
Merge the XML elements from the string `src` into the file at filename
`dst`. Merges only at the first level and compares elements via their
child tag `idkey`.
"""
dtree=et.parse(dst)
droot=dtree.getroot()
for sc in et.fromstring(src).findall('./'):
for dc in droot.findall(sc.tag):
if dc.find(idkey).text==sc.find(idkey).text: break
else:
droot.append(sc)
#from boincxml.py
def strip_white_space(node):
for child in node.childNodes[:]:
if child.nodeType == child.TEXT_NODE:
child.data = child.data.strip()
if not child.data: node.removeChild(child)
else:
strip_white_space(child)
return node
open(dst,'w').write(strip_white_space(minidom.parseString(et.tostring(droot))).toprettyxml(indent=" "*4))
for f in ['plan_class_spec.xml','project.xml']:
src=fmt(open(join(rootdir,f)).read())
if exists(join(args.projhome,f)):
xmlmerge(src,join(args.projhome,f))
else:
open(join(args.projhome,f),'w').write(src)