[REF][FIX]: Windows packaging: lint, cleanup and make it work
[odoo/odoo.git] / setup / package.py
1 #!/usr/bin/env python2
2 import glob
3 import os
4 import optparse
5 import signal
6 import shutil
7 import socket
8 import subprocess
9 import time
10 import xmlrpclib
11
12 #----------------------------------------------------------
13 # Utils
14 #----------------------------------------------------------
15 join = os.path.join
16
17 def mkdir(d):
18     if not os.path.isdir(d):
19         os.makedirs(d)
20
21 def system(l,chdir=None):
22     print l
23     if chdir:
24         cwd = os.getcwd()
25         os.chdir(chdir)
26     if isinstance(l,list):
27         rc=os.spawnvp(os.P_WAIT, l[0], l)
28     elif isinstance(l,str):
29         tmp=['sh','-c',l]
30         rc=os.spawnvp(os.P_WAIT, tmp[0], tmp)
31     if chdir:
32         os.chdir(cwd)
33     return rc
34
35 #----------------------------------------------------------
36 # Stages
37 #----------------------------------------------------------
38
39 def rsync(o):
40     pre = 'rsync -a --exclude .bzr --exclude .git --exclude *.pyc'
41     cmd = pre.split(' ')
42     system(cmd + ['%s/'%o.root, o.build])
43     for i in glob.glob(join(o.build,'addons/*')):
44         shutil.move(i, join(o.build,'openerp/addons'))
45     for i in glob.glob(join(o.build,'setup/*')):
46         shutil.move(i, join(o.build))
47     open(join(o.build,'openerp','release.py'),'a').write('version = "%s-%s"\n'%(o.version,o.timestamp))
48
49 def publish_move(o,srcs,dest):
50     for i in srcs:
51         shutil.move(i,dest)
52         # do the symlink
53         bn = os.path.basename(i)
54         latest = bn.replace(o.timestamp,'latest')
55         latest_full = join(dest,latest)
56         if bn != latest:
57             if os.path.islink(latest_full):
58                 os.unlink(latest_full)
59             os.symlink(bn,latest_full)
60
61 def sdist(o):
62     cmd=['python2','setup.py', '--quiet', 'sdist']
63     system(cmd,o.build)
64     #l = glob.glob(join(o.pkg,'*%s*.tar.gz'%o.timestamp))
65     #publish_move(o,l,join(o.pub,'src'))
66
67 def bdist_rpm(o):
68     cmd=['python2','setup.py', '--quiet', 'bdist_rpm']
69     system(cmd,o.build)
70     #l = glob.glob(join(o.build,'dist/*%s-1*.rpm'%o.timestamp.replace('-','_')))
71     #publish_move(o,l,join(o.pub,'rpm'))
72
73 def debian(o):
74     cmd=['sed','-i','1s/^.*$/openerp (%s-%s-1) testing; urgency=low/'%(o.version,o.timestamp),'debian/changelog']
75     system(cmd,o.build)
76     cmd=['dpkg-buildpackage','-rfakeroot']
77     system(cmd,o.build)
78
79     #l = glob.glob(join(o.pkg,'*_*%s-1*'%o.timestamp))
80     #publish_move(o,l,join(o.pub,'deb'))
81     #system('dpkg-scanpackages . /dev/null | gzip -9c > Packages.gz',join(o.pub,'deb'))
82
83 class KVM(object):
84     def __init__(self, o, image, ssh_key='', login='openerp'):
85         self.o = o
86         self.image = image
87         self.ssh_key = ssh_key
88         self.login = login
89
90     def timeout(self,signum,frame):
91         print "vm timeout kill",self.pid
92         os.kill(self.pid,15)
93
94     def start(self):
95         l="kvm -net nic -net user,hostfwd=tcp:127.0.0.1:10022-:22,hostfwd=tcp:127.0.0.1:18069-:8069,hostfwd=tcp:127.0.0.1:15432-:5432 -drive".split(" ")
96         #l.append('file=%s,if=virtio,index=0,boot=on,snapshot=on'%self.image)
97         l.append('file=%s,snapshot=on'%self.image)
98         #l.extend(['-vnc','127.0.0.1:1'])
99         l.append('-nographic')
100         print " ".join(l)
101         self.pid=os.spawnvp(os.P_NOWAIT, l[0], l)
102         time.sleep(10)
103         signal.alarm(2400)
104         signal.signal(signal.SIGALRM, self.timeout)
105         try:
106             self.run()
107         finally:
108             signal.signal(signal.SIGALRM, signal.SIG_DFL)
109             os.kill(self.pid,15)
110             time.sleep(10)
111
112     def ssh(self,cmd):
113         l=['ssh','-o','UserKnownHostsFile=/dev/null','-o','StrictHostKeyChecking=no','-p','10022','-i',self.ssh_key,'%s@127.0.0.1'%self.login,cmd]
114         system(l)
115
116     def rsync(self,args,options='--delete --exclude .bzrignore'):
117         cmd ='rsync -rt -e "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -p 10022 -i %s" %s %s' % (self.ssh_key, options, args)
118         system(cmd)
119
120     def run(self):
121         pass
122
123 class KVMDebianTestTgz(KVM):
124     def run(self):
125         l = glob.glob(join(self.o.pkg,'*%s.tar.gz'%self.o.timestamp))
126         self.rsync('%s openerp@127.0.0.1:src/'%l[0])
127         script = """
128             tar xzvf src/*.tar.gz
129             cd openerp*
130             sudo python setup.py install
131             sudo su - postgres -c "createuser -s $USER"
132             createdb t1
133             openerp-server --stop-after-init -d t1 -i ` python -c "import os;print ','.join([i for i in os.listdir('openerp/addons') if i not in ['auth_openid','caldav','document_ftp','base_gengo', 'im', 'im_livechat'] and not i.startswith('hw_')]),;" `
134         """
135         self.ssh(script)
136         self.ssh('nohup openerp-server >/dev/null 2>&1 &')
137         time.sleep(5)
138         l = xmlrpclib.ServerProxy('http://127.0.0.1:18069/xmlrpc/object').execute('t1',1,'admin','ir.module.module','search',[('state','=','installed')])
139         i = len(l)
140         if i >= 190:
141             print "Tgz install: ",i," module installed"
142         else:
143             raise Exception("Tgz install failed only %s installed"%i)
144         time.sleep(2)
145
146 class KVMDebianTestDeb(KVM):
147     def run(self):
148         l = glob.glob(join(self.o.pkg,'*%s*.deb'%self.o.timestamp))
149         self.rsync('%s openerp@127.0.0.1:deb/'%l[0])
150         script = """
151             sudo dpkg -i deb/*
152             sudo su - postgres -c "createuser -s $USER"
153             createdb t1
154             openerp-server --stop-after-init -d t1 -i base
155         """
156         #` python -c "import os;print ','.join([i for i in os.listdir('/usr/share/pyshared/openerp/addons') if i not in ['auth_openid','caldav','document_ftp', 'base_gengo'] and not i.startswith('hw_')]),;" `
157         self.ssh(script)
158         time.sleep(5)
159         l = xmlrpclib.ServerProxy('http://127.0.0.1:18069/xmlrpc/object').execute('t1',1,'admin','ir.module.module','search',[('state','=','installed')])
160         i = len(l)
161         if i >= 1:
162             print "Deb install: ",i," module installed"
163         else:
164             raise Exception("Tgz install failed only %s installed"%i)
165         time.sleep(2)
166
167 class KVMWinBuildExe(KVM):
168     def run(self):
169         self.ssh("mkdir -p build")
170         self.rsync('%s/ %s@127.0.0.1:build/server/' % (self.o.build, self.login))
171         with open('windows/Makefile.version', 'w') as f:
172             f.write("VERSION=%s\n" % self.o.version_full)
173         with open('windows/Makefile.python', 'w') as f:
174             f.write("PYTHON_VERSION=%s\n" % self.o.vm_win_python_version.replace('.', ''))
175         self.rsync('windows/ %s@127.0.0.1:build/windows/' % self.login)
176         self.rsync('windows/wkhtmltopdf/ %s@127.0.0.1:build/server/win32/wkhtmltopdf/' % self.login)
177         self.ssh("cd build/windows;time make allinone;")
178         self.rsync('%s@127.0.0.1:build/windows/files/ %s/' % (self.login, self.o.pkg), '')
179         print "KVMWinBuildExe.run(): done"
180
181 class KVMWinTestExe(KVM):
182     def run(self):
183         setuppath = "%s/openerp-allinone-setup-%s.exe" % (self.o.pkg, self.o.version_full)
184         setuplog = setuppath.replace('exe','log')
185         self.rsync('"%s" %s@127.0.0.1:' % (setuppath, self.login))
186         self.ssh("TEMP=/tmp ./openerp-allinone-setup-%s.exe /S" % self.o.version_full)
187         self.ssh('ls /cygdrive/c/"Program Files"/"OpenERP %s"/' % self.o.version_full)
188         self.rsync('"repo/lpopenerp_openobject-addons_7.0/" %s@127.0.0.1:/cygdrive/c/Program?Files/OpenERP?%s/Server/server/openerp/addons/' % (self.login, self.o.version_full), options='--exclude .bzrignore --exclude .bzr')
189         self.ssh('ls /cygdrive/c/"Program Files"/"OpenERP %s"/Server/server/openerp/addons/' % self.o.version_full)
190
191         self.ssh('PGPASSWORD=openpgpwd /cygdrive/c/"Program Files"/"OpenERP %s"/PostgreSQL/bin/createdb.exe -e -U openpg pack' % self.o.version_full)
192         self.ssh('net stop "PostgreSQL_For_OpenERP"')
193         self.ssh('net start "PostgreSQL_For_OpenERP"')
194         self.ssh('mkdir test-reports')
195
196         self.ssh('/cygdrive/c/"Program Files"/"OpenERP %s"/Server/server/openerp-server.exe -d pack -i base,report_webkit,product --stop-after-init --test-enable --log-level=test --test-report-directory=test-reports'%self.o.version_full)
197         self.rsync('%s@127.0.0.1:/cygdrive/c/Program?Files/OpenERP?%s/Server/server/openerp-server.log "%s"' % (self.login, self.o.version_full, setuplog))
198         self.rsync('%s@127.0.0.1:test-reports/ "%s"' % (self.login, self.o.pkg), options='')
199
200 #----------------------------------------------------------
201 # Options and Main
202 #----------------------------------------------------------
203
204 def options():
205     op = optparse.OptionParser()
206     timestamp = time.strftime("%Y%m%d-%H%M%S",time.gmtime())
207     root = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
208     build = "%s-%s" % (root, timestamp)
209
210     op.add_option("-b", "--build", default=build, help="build directory (%default)", metavar="DIR")
211     op.add_option("-p", "--pub", default=None, help="pub directory (%default)", metavar="DIR")
212     op.add_option("-v", "--version", default='7.0', help="version (%default)")
213
214     op.add_option("", "--vm-debian-image", default='/home/odoo/vm/debian6/debian6.vmdk', help="%default")
215     op.add_option("", "--vm-debian-ssh-key", default='/home/odoo/vm/debian6/debian6_id_rsa', help="%default")
216     op.add_option("", "--vm-debian-login", default='openerp', help="Debian login (%default)")
217
218     op.add_option("", "--vm-winxp-image", default='/home/odoo/vm/winxp26/winxp26.vdi', help="%default")
219     op.add_option("", "--vm-winxp-ssh-key", default='/home/odoo/vm/winxp26/id_rsa', help="%default")
220     op.add_option("", "--vm-win-login", default='Naresh', help="Windows login (%default)")
221     op.add_option("", "--vm-win-python-version", default='2.6', help="Windows Python version installed in the VM (default: %default)")
222
223     op.add_option("", "--no-debian", action="store_true", help="don't build the debian package")
224     op.add_option("", "--no-rpm", action="store_true", help="don't build the rpm package")
225     op.add_option("", "--no-tarball", action="store_true", help="don't build the tarball")
226     op.add_option("", "--no-windows", action="store_true", help="don't build the windows package")
227
228     (o, args) = op.parse_args()
229     # derive other options
230     o.root = root
231     o.timestamp = timestamp
232     o.version_full = '%s-%s'%(o.version,o.timestamp)
233     return o
234
235 def main():
236     o = options()
237     rsync(o)
238     try:
239         # tgz
240         sdist(o)
241         if os.path.isfile(o.vm_debian_image):
242             KVMDebianTestTgz(o, o.vm_debian_image, o.vm_debian_ssh_key, o.vm_debian_login).start()
243
244         # deb
245         debian(o)
246         if os.path.isfile(o.vm_debian_image):
247             KVMDebianTestDeb(o, o.vm_debian_image, o.vm_debian_ssh_key, o.vm_debian_login).start()
248
249         # exe
250         if os.path.isfile(o.vm_winxp_image):
251             KVMWinBuildExe(o, o.vm_winxp_image, o.vm_winxp_ssh_key, o.vm_win_login).start()
252             KVMWinTestExe(o, o.vm_winxp_image, o.vm_winxp_ssh_key, o.vm_win_login).start()
253             l = glob.glob(join(o.pkg,'*all*%s*.exe'%o.timestamp))
254             publish_move(o,l,join(o.pub,'exe'))
255
256         # rpm
257         bdist_rpm(o)
258
259     finally:
260         #shutil.rmtree(o.build)
261         pass
262
263 if __name__ == '__main__':
264     main()