root/management/bs-admin/trunk/bs-admin.py

Revision 402, 9.9 kB (checked in by gallardj, 5 months ago)

bs-admin changes for migration. refs #4227

  • Property svn:executable set to *
Line 
1 #!/usr/bin/python
2 # vim:set ts=4 sw=4 sts=4 expandtab:
3
4 import optparse
5 import ConfigParser
6 import beaversource
7 from pprint import PrettyPrinter
8 import sys,os
9 import trac.db_default as tracdefaultdata
10 import trac.db.postgres_backend as tracpg
11 import datetime
12 import shutil
13 import psycopg2
14 import re
15
16 # config options:
17 config_file = '/data/management/beaversource.ini'
18 if not os.path.exists(config_file):
19     print >> sys.stderr, 'beaversource.ini not found in ' + os.getcwd()
20     sys.exit(1)
21
22 config = ConfigParser.ConfigParser()
23 config.read(config_file)
24
25 p = optparse.OptionParser(conflict_handler="resolve")
26
27 # initial creation time
28 p.add_option('--create', action="store_const", const="create", dest="action")
29 p.add_option('--destroy', action="store_const", const="destroy", dest="action")
30 p.add_option('--rename', action="store_const", const="rename", dest="action")
31 #defined by request project model: A=Publicly Visible Project, O=Campus/VPN Access Only, M=Project Members Only
32 p.add_option('--visibility', action='store', default='A', type='choice', choices=['A','O','M'])
33 p.add_option('--license', default='none', action='store')
34 p.add_option('--licensefile', default='none', action='store')
35 p.add_option('--owner-name', action='store')
36 p.add_option('--owner-email', action='store')
37 p.add_option('--owner-username', action='store')
38
39 # database options
40 p.add_option('--db-pass')
41 p.add_option('--db-user')
42 p.add_option('--new-db-user')
43 p.add_option('--db-host', default='dogwood.osuosl.org')
44 p.add_option('--db', action='store', default='bsc_projects')
45
46 # svn options
47 p.add_option('--svn-path', action='store')
48 p.add_option('--svn-base-path', action='store', default='/data/svn')
49 p.add_option('--svn-base-hooks', action='store', default='/data/master-svn/hooks')
50 p.add_option('--svn-commit-size', action='store', type='int', default= 5 * 1024 * 1024)
51 p.add_option('--svn-initial-data', action='store', default='/data/master-svn/initial-data/init.svn')
52 # useful only for --rename:
53 p.add_option('--new-svn-path', action='store')
54
55 # trac options
56 p.add_option('--trac-desc', default = "BeaverSource Project")
57 p.add_option('--trac-footer')
58 p.add_option('--trac-name')
59 p.add_option('--trac-base-url', action='store', default='http://beaversource.oregonstate.edu/projects')
60 p.add_option('--trac-base-path', action='store', default='/data/trac/sites')
61 p.add_option('--trac-base-wiki', action='store', default='/usr/share/trac/wiki-default')
62 p.add_option('--trac-base-plugins', action='store', default='/data/master-trac/plugins')
63 p.add_option('--trac-sso-service', action='store', default = config.get('sso', 'service'))
64 p.add_option('--trac-sso-password', action='store', default = config.get('sso', 'password'))
65 p.add_option('--trac-sso-host', action='store', default = config.get('sso', 'host'))
66 p.add_option('--trac-sso-path', action='store', default = config.get('sso', 'path'))
67 p.add_option('--trac-sso-cookie', action='store', default = config.get('sso', 'cookie'))
68 p.add_option('--trac-sso-login-url', action='store', default = config.get('sso', 'login_url'))
69 p.add_option('--trac-default-permission', action='store', default = 'TRAC_ADMIN')
70 p.add_option('--trac-db-admin-user', action='store', default = config.get('trac', 'dbadmin'))
71 p.add_option('--trac-db-admin-pass', action='store', default = config.get('trac', 'dbpass'))
72
73 p.add_option('--users')
74
75 options, args = p.parse_args()
76
77 if options.action == 'rename':
78     if len(args) != 2:
79         print >> sys.stderr, "Error: Specify old name and new name"
80         sys.exit(1)
81     else:
82         options.newproject = args[1]
83         options.project = args[0]
84 elif len(args) != 1:
85     print >> sys.stderr, "Error: Specify one project"
86     sys.exit(1)
87 else:
88     # @todo: scrub project into a clean string
89     # and a unique string!
90     options.project = args[0]
91
92 if not options.action:
93     print >>sys.stderr, "One of --create, --rename, or --remove must be specified"
94     sys.exit(1)
95
96 # Make sure a base set of options is always set
97 if not options.db_user:
98     options.db_user = 'bs_' + options.project + '_user'
99
100 if not options.db_pass:
101     # be sure to pull off the trailing newline:
102     options.db_pass = os.popen('/usr/bin/apg  -a 1 -n 1 -m 16 -x 24 -M NCL -c cl_seed').read().rstrip()
103
104 if not options.svn_path:
105     options.svn_path = options.project
106
107 if options.action == 'rename' and options.newproject:
108     if not options.new_svn_path:
109         options.new_svn_path = options.newproject
110     if not options.new_db_user:
111         options.new_db_user = 'bs_' + options.newproject + '_user'
112
113 if not options.trac_name:
114     options.trac_name = options.project
115
116
117
118 def destroy_svn(repo, options):
119     # mv the repository to /data/boneyard-svn/yyyymmdd-<project>
120     dest = '/data/boneyard-svn/%s-%s' % (datetime.date.today().strftime('%Y%m%d'), options.project)
121     if repo.exists():
122         if not os.path.exists(dest):
123             move_svn( repo, dest )
124         else: #just remove the repository
125             shutil.rmtree(repo.path)
126     else:
127         print >>sys.stderr, "Repository %s does not exist" % repo.path
128
129 def move_svn(repository, dest):
130     return repository.rename(dest)
131
132
133 def destroy_trac(repository, options):
134     # mv the trac instance to /data/boneyard-trac/yyyymmdd-<project>
135     trac = beaversource.TracInstall(options.project, options.trac_base_path + os.sep + options.project, repository)
136     dest = '/data/boneyard-trac/%s-%s' % (datetime.date.today().strftime('%Y%m%d'), options.project)
137     if trac.exists():
138         if not os.path.exists(dest):
139             os.rename( trac.path, dest )
140         else: # just remove the trac instance
141             shutil.rmtree(trac.path)
142     else:
143         print >> sys.stderr, "Trac instance %s does not exist" % trac.path
144
145     # destroy the trac db entries/user
146     trac_db = beaversource.TracDB(options.db_host, options.db, options.trac_db_admin_user, options.trac_db_admin_pass, options.db_user, options.db_pass)
147     if trac_db.exists():
148         trac_db.destroy()
149     else:
150         print >> sys.stderr, "Trac database/user %s does not exist" % trac_db.project_user
151
152
153 def create_svn(options):
154
155     # Create SVN repository
156     repo = beaversource.Repository(options.svn_base_path + os.sep + options.svn_path)
157     if not repo.exists():
158         repo.create()
159         repo.populate(options.svn_initial_data)
160
161         # Add all the globally defined hooks:
162         for hookname in repo.hook_arg_map.keys():
163             hookpath = options.svn_base_hooks + os.sep + hookname
164             if not os.path.exists(hookpath):
165                 continue
166             hooklist = [ hookpath + os.sep + hook for hook in os.listdir(hookpath) if hook.endswith('.hook') ]
167             hooklist.sort()
168             for hookscript in hooklist:
169                 repo.add_hook(hookname, hookscript)
170
171     return repo
172
173 def move_trac(repository, options):
174     trac_db = beaversource.TracDB(options.db_host, options.db, options.trac_db_admin_user, options.trac_db_admin_pass, options.db_user, options.db_pass)
175     trac_db.rename(options.new_db_user)
176     trac = beaversource.TracInstall(options.project, options.trac_base_path + os.sep + options.project, repository)
177
178     trac.rename(options.newproject, options)
179
180     trac.config.set('trac', 'database', 'postgres://%s:%s@%s/%s' %
181             ( trac_db.project_user, trac_db.project_pass, trac_db.host, trac_db.db) )
182
183     trac.config.set('trac', 'repository_dir', repository.path)
184     trac.config.set('project', 'shortname', options.newproject)
185     trac.config.set('project', 'name', options.newproject)
186     trac.config.set('project', 'url', options.trac_base_url + os.sep + options.newproject)
187     trac.config.set('header_logo', 'link', options.trac_base_url + os.sep + options.newproject)
188
189     trac.write_config()
190     trac.run_command("/usr/bin/trac-admin %s resync" % trac.path)
191
192
193
194 def create_trac(repository, options):
195
196     # Create Trac database
197     trac_db = beaversource.TracDB(options.db_host, options.db, options.trac_db_admin_user, options.trac_db_admin_pass, options.db_user, options.db_pass)
198     trac_db.create()
199
200     # Create trac instance
201
202     trac = beaversource.TracInstall(options.project, options.trac_base_path + os.sep + options.project, repository, options.visibility, options.license, options.licensefile)
203     if not trac.exists():
204         trac.create()
205
206     # now fix the busted trac configuration:
207     # @todo: modules are going to need config options, too
208     #  look for <module>.ini snippet?
209     trac.config.set('trac', 'database', 'postgres://%s:%s@%s/%s' %
210             ( trac_db.project_user, trac_db.project_pass, trac_db.host, trac_db.db) )
211     trac.config.set('trac', 'repository_dir', repository.path)
212     trac.config.set('trac', 'repository_type', 'svn')
213
214     trac.config.set('project', 'shortname', options.project)
215     trac.config.set('project', 'url', options.trac_base_url + os.sep + options.project)
216     trac.config.set('project', 'descr', options.trac_desc)
217     trac.config.set('header_logo', 'link', options.trac_base_url + os.sep + options.project)
218
219     if options.trac_name:
220         trac.config.set('project', 'name', options.trac_name)
221     else:
222         trac.config.set('project', 'name', options.project)
223
224     if options.trac_footer:
225         trac.config.set('project', 'footer', options.trac_footer)
226
227     trac.write_config()
228
229     # update the trac database:
230     trac.init_db(options.db, options.db_user, options.db_pass, options.db_host)
231
232     # add the default wiki pages:
233     trac.populate_wiki(options.trac_base_wiki)
234
235     # add any specified users
236     if options.users:
237         for user in options.users.split(','):
238             trac.add_user(user, options.trac_default_permission)
239     trac.postprocess() #sets visibility and license stuff
240
241 if options.action == 'create':
242     repository = create_svn(options)
243     create_trac(repository, options)
244
245 elif options.action == 'destroy':
246     repository = create_svn(options)
247     destroy_trac(repository, options)
248     destroy_svn(repository, options)
249
250 elif options.action == 'rename':
251     repository = create_svn(options)
252     move_svn(repository, options.svn_base_path + os.sep + options.new_svn_path)
253     move_trac(repository, options)
254
Note: See TracBrowser for help on using the browser.