ignore other status in case of timeout/disk full, etc.
[build-farm.git] / admin.py
1 #!/usr/bin/python
2 # Samba.org buildfarm
3 # Copyright (C) 2008 Andrew Bartlett <abartlet@samba.org>
4 # Copyright (C) 2008 Jelmer Vernooij <jelmer@samba.org>
5 #
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 3 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 #
19
20 from buildfarm import (
21     hostdb,
22     )
23 from buildfarm.sqldb import StormCachingBuildFarm
24 import commands
25 import os
26 import smtplib
27 import sys
28 import time
29 from email.MIMEText import MIMEText
30
31 buildfarm = StormCachingBuildFarm()
32
33 def update_rsyncd_secrets():
34     temp_rsyncd_secrets = os.path.join(os.path.dirname(__file__), "../rsyncd.secrets.new")
35     f = open(temp_rsyncd_secrets, "w")
36     f.writelines(buildfarm.hostdb.create_rsync_secrets())
37     f.close()
38
39     os.rename(temp_rsyncd_secrets, "../rsyncd.secrets")
40
41 def update_hosts_list():
42     temp_hosts_list_file = os.path.join(os.path.dirname(__file__), "web", "hosts.list.new")
43     f = open(temp_hosts_list_file, "w")
44     f.writelines(buildfarm.hostdb.create_hosts_list())
45     f.close()
46
47     os.rename(temp_hosts_list_file, os.path.join(os.path.dirname(__file__), "web/hosts.list"))
48
49 dry_run = False
50
51 print "Samba Build farm management tool"
52 print "================================"
53
54 args = sys.argv[1:]
55
56 try:
57     op = args.pop(0)
58 except IndexError:
59     print "Initialize the buildfarm:       init"
60     print "Add Machine to build farm:      add"
61     print "Remove Machine from build farm: remove"
62     print "Modify build farm account:      modify"
63     print "Print build farm host info:     info"
64     print "Print build farm host list:     list"
65
66     op = raw_input("Select Operation: [add] ").lower()
67
68     if op == "":
69         op = "add"
70
71 if op == "init":
72     buildfarm.commit()
73 elif op == "remove":
74     if not args:
75         args = [raw_input("Please enter hostname to delete: ")]
76     for hostname in args:
77         try:
78             buildfarm.hostdb.deletehost(hostname)
79         except hostdb.NoSuchHost, e:
80             print "No such host '%s'" % e.name
81             sys.exit(1)
82         else:
83             buildfarm.hostdb.commit()
84             update_rsyncd_secrets()
85             update_hosts_list()
86 elif op == "modify":
87     hostname = raw_input("Please enter hostname to modify: ")
88     try:
89         host = buildfarm.hostdb[hostname]
90     except hostdb.NoSuchHost, e:
91         print "No such host '%s'" % e.name
92         sys.exit(1)
93     print "Owner: %s <%s>" % host.owner
94     print "Platform: %s" % host.platform
95     print ""
96     mod_op = raw_input("Modify owner or platform: [platform] ")
97     if mod_op == "":
98         mod_op = "platform"
99     if mod_op == "platform":
100         platform = raw_input("Enter new platform: ")
101         host.update_platform(platform)
102         buildfarm.commit()
103     elif mod_op == "owner":
104         owner = raw_input("Enter new owner's name: ")
105         owner_email = raw_input("Enter new owner's e-mail address: ")
106         host.update_owner(owner, owner_email.decode("utf-8"))
107         buildfarm.commit()
108     else:
109         print "Unknown subcommand %s" % mod_op
110         sys.exit(1)
111     update_rsyncd_secrets()
112     update_hosts_list()
113 elif op == "add":
114     hostname = raw_input("Machine hostname: ")
115     try:
116         buildfarm.hostdb[hostname]
117     except hostdb.NoSuchHost, e:
118         pass
119     else:
120         print "A host with the name %s already exists." % e.name
121         sys.exit(1)
122     platform = raw_input("Machine platform (eg Fedora 9 x86_64): ")
123     owner = raw_input("Machine Owner Name: ")
124     owner_email = raw_input("Machine Owner E-mail: ")
125     password = raw_input("Enter password: [generate random] ")
126     if password == "":
127         password = commands.getoutput("pwgen 16 1").strip()
128         print "Password will be: %s" % password
129     permission = []
130     print "Enter permission e-mail, finish with a ."
131     line = raw_input("")
132     while line != ".":
133         permission += line
134         line = raw_input("")
135
136     try:
137         buildfarm.hostdb.createhost(hostname, platform.decode("utf-8"),
138             owner.decode("utf-8"), owner_email.decode("utf-8"),
139             password.decode("utf-8"),
140             "".join(permission).decode("utf-8", "replace"))
141     except hostdb.HostAlreadyExists, e:
142         print "A host with the name %s already exists." % e.name
143         sys.exit(1)
144     else:
145         buildfarm.commit()
146
147     body = """
148 Welcome to the Samba.org build farm.  
149
150 Your host %(hostname)s has been added to the Samba Build farm.  
151
152 We have recorded that it is running %(platform)s.  
153
154 If you have not already done so, please read:
155 http://build.samba.org/instructions.html
156
157 The password for your rsync .password file is %(password)s
158
159 An e-mail asking you to subscribe to the build-farmers mailing
160 list will arrive shortly.  Please ensure you maintain your 
161 subscription to this list while you have hosts in the build farm.
162
163 Thank you for your contribution to ensuring portability and quality
164 of Samba.org projects.
165
166
167 """ % { "hostname": hostname, "platform": platform, "password": password }
168
169     msg_notification = MIMEText(body)
170
171     # send the password in an e-mail to that address
172     msg_notification["Subject"] = "Your new build farm host %s" % hostname
173     msg_notification["To"] = "\"%s\" <%s>" % (owner, owner_email)
174     msg_notification["Bcc"] = "build@samba.org"
175     msg_notification["From"] = "\"Samba Build Farm\" <build@samba.org>"
176
177     msg_subscribe = MIMEText("""Please subscribe %s to the build-farmers mailing list
178
179 Thanks, your friendly Samba build farm administrator <build@samba.org>""" % owner)
180     msg_subscribe["From"] = "\"%s\" <%s>" % (owner, owner_email)
181     msg_subscribe["Subject"] = 'Subscribe to build-farmers mailing list'
182     msg_subscribe["To"] = 'build-farmers-join@lists.samba.org'
183
184     if dry_run:
185         print msg_notification
186     else:
187         s = smtplib.SMTP()
188         s.connect()
189         for msg in (msg_notification, msg_subscribe):
190             recipients = [msg["To"]]
191             if msg["Bcc"]:
192                 recipients.append(msg["Bcc"])
193             s.sendmail(msg["From"], recipients, msg.as_string())
194         s.quit()
195         update_rsyncd_secrets()
196         update_hosts_list()
197 elif op == "info":
198     if not args:
199         args = [raw_input("Hostname: ")]
200     for hostname in args:
201         try:
202             host = buildfarm.hostdb[hostname]
203         except hostdb.NoSuchHost, e:
204             print "No such host '%s'" % e.name
205             sys.exit(1)
206         if host.fqdn:
207             opt_fqdn = " (%s)" % host.fqdn
208         else:
209             opt_fqdn = ""
210         print "Host: %s%s" % (host.name, opt_fqdn)
211         print "Platform: %s" % host.platform
212         print "Owner: %s <%s>" % host.owner
213 elif op == "list":
214     for host in buildfarm.hostdb.host_ages():
215         if host.last_update:
216             age = time.time() - host.last_update
217         else:
218             age = ""
219         print "%-12s %s" % (age, host.name)
220 else:
221     print "Unknown command %s" % op
222     sys.exit(1)