100 |
100 |
101 def run_args(self, args, askconfirm): |
101 def run_args(self, args, askconfirm): |
102 for appid in args: |
102 for appid in args: |
103 if askconfirm: |
103 if askconfirm: |
104 print '*'*72 |
104 print '*'*72 |
105 if not confirm('%s application %r ?' % (self.name, appid)): |
105 if not confirm('%s instance %r ?' % (self.name, appid)): |
106 continue |
106 continue |
107 self.run_arg(appid) |
107 self.run_arg(appid) |
108 |
108 |
109 def run_arg(self, appid): |
109 def run_arg(self, appid): |
110 cmdmeth = getattr(self, '%s_application' % self.name) |
110 cmdmeth = getattr(self, '%s_instance' % self.name) |
111 try: |
111 try: |
112 cmdmeth(appid) |
112 cmdmeth(appid) |
113 except (KeyboardInterrupt, SystemExit): |
113 except (KeyboardInterrupt, SystemExit): |
114 print >> sys.stderr, '%s aborted' % self.name |
114 print >> sys.stderr, '%s aborted' % self.name |
115 sys.exit(2) # specific error code |
115 sys.exit(2) # specific error code |
116 except (ExecutionError, ConfigurationError), ex: |
116 except (ExecutionError, ConfigurationError), ex: |
117 print >> sys.stderr, 'application %s not %s: %s' % ( |
117 print >> sys.stderr, 'instance %s not %s: %s' % ( |
118 appid, self.actionverb, ex) |
118 appid, self.actionverb, ex) |
119 except Exception, ex: |
119 except Exception, ex: |
120 import traceback |
120 import traceback |
121 traceback.print_exc() |
121 traceback.print_exc() |
122 print >> sys.stderr, 'application %s not %s: %s' % ( |
122 print >> sys.stderr, 'instance %s not %s: %s' % ( |
123 appid, self.actionverb, ex) |
123 appid, self.actionverb, ex) |
124 |
124 |
125 |
125 |
126 class ApplicationCommandFork(ApplicationCommand): |
126 class InstanceCommandFork(InstanceCommand): |
127 """Same as `ApplicationCommand`, but command is forked in a new environment |
127 """Same as `InstanceCommand`, but command is forked in a new environment |
128 for each argument |
128 for each argument |
129 """ |
129 """ |
130 |
130 |
131 def run_args(self, args, askconfirm): |
131 def run_args(self, args, askconfirm): |
132 if len(args) > 1: |
132 if len(args) > 1: |
204 print ' available modes: %s' % ', '.join(modes) |
203 print ' available modes: %s' % ', '.join(modes) |
205 print |
204 print |
206 try: |
205 try: |
207 regdir = cwcfg.registry_dir() |
206 regdir = cwcfg.registry_dir() |
208 except ConfigurationError, ex: |
207 except ConfigurationError, ex: |
209 print 'No application available:', ex |
208 print 'No instance available:', ex |
210 print |
209 print |
211 return |
210 return |
212 instances = list_instances(regdir) |
211 instances = list_instances(regdir) |
213 if instances: |
212 if instances: |
214 print 'Available applications (%s):' % regdir |
213 print 'Available instances (%s):' % regdir |
215 for appid in instances: |
214 for appid in instances: |
216 modes = cwcfg.possible_configurations(appid) |
215 modes = cwcfg.possible_configurations(appid) |
217 if not modes: |
216 if not modes: |
218 print '* %s (BROKEN application, no configuration found)' % appid |
217 print '* %s (BROKEN instance, no configuration found)' % appid |
219 continue |
218 continue |
220 print '* %s (%s)' % (appid, ', '.join(modes)) |
219 print '* %s (%s)' % (appid, ', '.join(modes)) |
221 try: |
220 try: |
222 config = cwcfg.config_for(appid, modes[0]) |
221 config = cwcfg.config_for(appid, modes[0]) |
223 except Exception, exc: |
222 except Exception, exc: |
224 print ' (BROKEN application, %s)' % exc |
223 print ' (BROKEN instance, %s)' % exc |
225 continue |
224 continue |
226 else: |
225 else: |
227 print 'No application available in %s' % regdir |
226 print 'No instance available in %s' % regdir |
228 print |
227 print |
229 |
228 |
230 |
229 |
231 class CreateApplicationCommand(Command): |
230 class CreateInstanceCommand(Command): |
232 """Create an application from a cube. This is an unified |
231 """Create an instance from a cube. This is an unified |
233 command which can handle web / server / all-in-one installation |
232 command which can handle web / server / all-in-one installation |
234 according to available parts of the software library and of the |
233 according to available parts of the software library and of the |
235 desired cube. |
234 desired cube. |
236 |
235 |
237 <cube> |
236 <cube> |
238 the name of cube to use (list available cube names using |
237 the name of cube to use (list available cube names using |
239 the "list" command). You can use several cubes by separating |
238 the "list" command). You can use several cubes by separating |
240 them using comma (e.g. 'jpl,eemail') |
239 them using comma (e.g. 'jpl,eemail') |
241 <application> |
240 <instance> |
242 an identifier for the application to create |
241 an identifier for the instance to create |
243 """ |
242 """ |
244 name = 'create' |
243 name = 'create' |
245 arguments = '<cube> <application>' |
244 arguments = '<cube> <instance>' |
246 options = ( |
245 options = ( |
247 ("config-level", |
246 ("config-level", |
248 {'short': 'l', 'type' : 'int', 'metavar': '<level>', |
247 {'short': 'l', 'type' : 'int', 'metavar': '<level>', |
249 'default': 0, |
248 'default': 0, |
250 'help': 'configuration level (0..2): 0 will ask for essential \ |
249 'help': 'configuration level (0..2): 0 will ask for essential \ |
253 ), |
252 ), |
254 ("config", |
253 ("config", |
255 {'short': 'c', 'type' : 'choice', 'metavar': '<install type>', |
254 {'short': 'c', 'type' : 'choice', 'metavar': '<install type>', |
256 'choices': ('all-in-one', 'repository', 'twisted'), |
255 'choices': ('all-in-one', 'repository', 'twisted'), |
257 'default': 'all-in-one', |
256 'default': 'all-in-one', |
258 'help': 'installation type, telling which part of an application \ |
257 'help': 'installation type, telling which part of an instance \ |
259 should be installed. You can list available configurations using the "list" \ |
258 should be installed. You can list available configurations using the "list" \ |
260 command. Default to "all-in-one", e.g. an installation embedding both the RQL \ |
259 command. Default to "all-in-one", e.g. an installation embedding both the RQL \ |
261 repository and the web server.', |
260 repository and the web server.', |
262 } |
261 } |
263 ), |
262 ), |
283 except ConfigurationError, ex: |
282 except ConfigurationError, ex: |
284 print ex |
283 print ex |
285 print '\navailable cubes:', |
284 print '\navailable cubes:', |
286 print ', '.join(cwcfg.available_cubes()) |
285 print ', '.join(cwcfg.available_cubes()) |
287 return |
286 return |
288 # create the registry directory for this application |
287 # create the registry directory for this instance |
289 print '\n'+underline_title('Creating the application %s' % appid) |
288 print '\n'+underline_title('Creating the instance %s' % appid) |
290 create_dir(config.apphome) |
289 create_dir(config.apphome) |
291 # load site_cubicweb from the cubes dir (if any) |
290 # load site_cubicweb from the cubes dir (if any) |
292 config.load_site_cubicweb() |
291 config.load_site_cubicweb() |
293 # cubicweb-ctl configuration |
292 # cubicweb-ctl configuration |
294 print '\n'+underline_title('Configuring the application (%s.conf)' % configname) |
293 print '\n'+underline_title('Configuring the instance (%s.conf)' % configname) |
295 config.input_config('main', self.config.config_level) |
294 config.input_config('main', self.config.config_level) |
296 # configuration'specific stuff |
295 # configuration'specific stuff |
297 print |
296 print |
298 helper.bootstrap(cubes, self.config.config_level) |
297 helper.bootstrap(cubes, self.config.config_level) |
299 # write down configuration |
298 # write down configuration |
321 chown(config.appdatahome, config['uid']) |
320 chown(config.appdatahome, config['uid']) |
322 print '\n-> creation done for %r.\n' % config.apphome |
321 print '\n-> creation done for %r.\n' % config.apphome |
323 helper.postcreate() |
322 helper.postcreate() |
324 |
323 |
325 |
324 |
326 class DeleteApplicationCommand(Command): |
325 class DeleteInstanceCommand(Command): |
327 """Delete an application. Will remove application's files and |
326 """Delete an instance. Will remove instance's files and |
328 unregister it. |
327 unregister it. |
329 """ |
328 """ |
330 name = 'delete' |
329 name = 'delete' |
331 arguments = '<application>' |
330 arguments = '<instance>' |
332 |
331 |
333 options = () |
332 options = () |
334 |
333 |
335 def run(self, args): |
334 def run(self, args): |
336 """run the command with its specific arguments""" |
335 """run the command with its specific arguments""" |
337 appid = pop_arg(args, msg="No application specified !") |
336 appid = pop_arg(args, msg="No instance specified !") |
338 configs = [cwcfg.config_for(appid, configname) |
337 configs = [cwcfg.config_for(appid, configname) |
339 for configname in cwcfg.possible_configurations(appid)] |
338 for configname in cwcfg.possible_configurations(appid)] |
340 if not configs: |
339 if not configs: |
341 raise ExecutionError('unable to guess configuration for %s' % appid) |
340 raise ExecutionError('unable to guess configuration for %s' % appid) |
342 for config in configs: |
341 for config in configs: |
351 except OSError, ex: |
350 except OSError, ex: |
352 import errno |
351 import errno |
353 if ex.errno != errno.ENOENT: |
352 if ex.errno != errno.ENOENT: |
354 raise |
353 raise |
355 confignames = ', '.join([config.name for config in configs]) |
354 confignames = ', '.join([config.name for config in configs]) |
356 print 'application %s (%s) deleted' % (appid, confignames) |
355 print 'instance %s (%s) deleted' % (appid, confignames) |
357 |
356 |
358 |
357 |
359 # application commands ######################################################## |
358 # instance commands ######################################################## |
360 |
359 |
361 class StartApplicationCommand(ApplicationCommand): |
360 class StartInstanceCommand(InstanceCommand): |
362 """Start the given applications. If no application is given, start them all. |
361 """Start the given instances. If no instance is given, start them all. |
363 |
362 |
364 <application>... |
363 <instance>... |
365 identifiers of the applications to start. If no application is |
364 identifiers of the instances to start. If no instance is |
366 given, start them all. |
365 given, start them all. |
367 """ |
366 """ |
368 name = 'start' |
367 name = 'start' |
369 actionverb = 'started' |
368 actionverb = 'started' |
370 options = ( |
369 options = ( |
372 {'short': 'D', 'action' : 'store_true', |
371 {'short': 'D', 'action' : 'store_true', |
373 'help': 'start server in debug mode.'}), |
372 'help': 'start server in debug mode.'}), |
374 ("force", |
373 ("force", |
375 {'short': 'f', 'action' : 'store_true', |
374 {'short': 'f', 'action' : 'store_true', |
376 'default': False, |
375 'default': False, |
377 'help': 'start the application even if it seems to be already \ |
376 'help': 'start the instance even if it seems to be already \ |
378 running.'}), |
377 running.'}), |
379 ('profile', |
378 ('profile', |
380 {'short': 'P', 'type' : 'string', 'metavar': '<stat file>', |
379 {'short': 'P', 'type' : 'string', 'metavar': '<stat file>', |
381 'default': None, |
380 'default': None, |
382 'help': 'profile code and use the specified file to store stats', |
381 'help': 'profile code and use the specified file to store stats', |
383 }), |
382 }), |
384 ) |
383 ) |
385 |
384 |
386 def start_application(self, appid): |
385 def start_instance(self, appid): |
387 """start the application's server""" |
386 """start the instance's server""" |
388 # use get() since start may be used from other commands (eg upgrade) |
387 # use get() since start may be used from other commands (eg upgrade) |
389 # without all options defined |
388 # without all options defined |
390 debug = self.get('debug') |
389 debug = self.get('debug') |
391 force = self.get('force') |
390 force = self.get('force') |
392 config = cwcfg.config_for(appid) |
391 config = cwcfg.config_for(appid) |
401 command = helper.start_command(config, debug) |
400 command = helper.start_command(config, debug) |
402 if debug: |
401 if debug: |
403 print "starting server with command :" |
402 print "starting server with command :" |
404 print command |
403 print command |
405 if system(command): |
404 if system(command): |
406 print 'an error occured while starting the application, not started' |
405 print 'an error occured while starting the instance, not started' |
407 print |
406 print |
408 return False |
407 return False |
409 if not debug: |
408 if not debug: |
410 print 'application %s started' % appid |
409 print 'instance %s started' % appid |
411 return True |
410 return True |
412 |
411 |
413 |
412 |
414 class StopApplicationCommand(ApplicationCommand): |
413 class StopInstanceCommand(InstanceCommand): |
415 """Stop the given applications. |
414 """Stop the given instances. |
416 |
415 |
417 <application>... |
416 <instance>... |
418 identifiers of the applications to stop. If no application is |
417 identifiers of the instances to stop. If no instance is |
419 given, stop them all. |
418 given, stop them all. |
420 """ |
419 """ |
421 name = 'stop' |
420 name = 'stop' |
422 actionverb = 'stopped' |
421 actionverb = 'stopped' |
423 |
422 |
424 def ordered_instances(self): |
423 def ordered_instances(self): |
425 instances = super(StopApplicationCommand, self).ordered_instances() |
424 instances = super(StopInstanceCommand, self).ordered_instances() |
426 instances.reverse() |
425 instances.reverse() |
427 return instances |
426 return instances |
428 |
427 |
429 def stop_application(self, appid): |
428 def stop_instance(self, appid): |
430 """stop the application's server""" |
429 """stop the instance's server""" |
431 config = cwcfg.config_for(appid) |
430 config = cwcfg.config_for(appid) |
432 helper = self.config_helper(config, cmdname='stop') |
431 helper = self.config_helper(config, cmdname='stop') |
433 helper.poststop() # do this anyway |
432 helper.poststop() # do this anyway |
434 pidf = config['pid-file'] |
433 pidf = config['pid-file'] |
435 if not exists(pidf): |
434 if not exists(pidf): |
456 try: |
455 try: |
457 remove(pidf) |
456 remove(pidf) |
458 except OSError: |
457 except OSError: |
459 # already removed by twistd |
458 # already removed by twistd |
460 pass |
459 pass |
461 print 'application %s stopped' % appid |
460 print 'instance %s stopped' % appid |
462 |
461 |
463 |
462 |
464 class RestartApplicationCommand(StartApplicationCommand, |
463 class RestartInstanceCommand(StartInstanceCommand, |
465 StopApplicationCommand): |
464 StopInstanceCommand): |
466 """Restart the given applications. |
465 """Restart the given instances. |
467 |
466 |
468 <application>... |
467 <instance>... |
469 identifiers of the applications to restart. If no application is |
468 identifiers of the instances to restart. If no instance is |
470 given, restart them all. |
469 given, restart them all. |
471 """ |
470 """ |
472 name = 'restart' |
471 name = 'restart' |
473 actionverb = 'restarted' |
472 actionverb = 'restarted' |
474 |
473 |
475 def run_args(self, args, askconfirm): |
474 def run_args(self, args, askconfirm): |
476 regdir = cwcfg.registry_dir() |
475 regdir = cwcfg.registry_dir() |
477 if not isfile(join(regdir, 'startorder')) or len(args) <= 1: |
476 if not isfile(join(regdir, 'startorder')) or len(args) <= 1: |
478 # no specific startorder |
477 # no specific startorder |
479 super(RestartApplicationCommand, self).run_args(args, askconfirm) |
478 super(RestartInstanceCommand, self).run_args(args, askconfirm) |
480 return |
479 return |
481 print ('some specific start order is specified, will first stop all ' |
480 print ('some specific start order is specified, will first stop all ' |
482 'applications then restart them.') |
481 'instances then restart them.') |
483 # get instances in startorder |
482 # get instances in startorder |
484 stopped = [] |
483 stopped = [] |
485 for appid in args: |
484 for appid in args: |
486 if askconfirm: |
485 if askconfirm: |
487 print '*'*72 |
486 print '*'*72 |
488 if not confirm('%s application %r ?' % (self.name, appid)): |
487 if not confirm('%s instance %r ?' % (self.name, appid)): |
489 continue |
488 continue |
490 self.stop_application(appid) |
489 self.stop_instance(appid) |
491 stopped.append(appid) |
490 stopped.append(appid) |
492 forkcmd = [w for w in sys.argv if not w in args] |
491 forkcmd = [w for w in sys.argv if not w in args] |
493 forkcmd[1] = 'start' |
492 forkcmd[1] = 'start' |
494 forkcmd = ' '.join(forkcmd) |
493 forkcmd = ' '.join(forkcmd) |
495 for appid in reversed(args): |
494 for appid in reversed(args): |
496 status = system('%s %s' % (forkcmd, appid)) |
495 status = system('%s %s' % (forkcmd, appid)) |
497 if status: |
496 if status: |
498 sys.exit(status) |
497 sys.exit(status) |
499 |
498 |
500 def restart_application(self, appid): |
499 def restart_instance(self, appid): |
501 self.stop_application(appid) |
500 self.stop_instance(appid) |
502 if self.start_application(appid): |
501 if self.start_instance(appid): |
503 print 'application %s %s' % (appid, self.actionverb) |
502 print 'instance %s %s' % (appid, self.actionverb) |
504 |
503 |
505 |
504 |
506 class ReloadConfigurationCommand(RestartApplicationCommand): |
505 class ReloadConfigurationCommand(RestartInstanceCommand): |
507 """Reload the given applications. This command is equivalent to a |
506 """Reload the given instances. This command is equivalent to a |
508 restart for now. |
507 restart for now. |
509 |
508 |
510 <application>... |
509 <instance>... |
511 identifiers of the applications to reload. If no application is |
510 identifiers of the instances to reload. If no instance is |
512 given, reload them all. |
511 given, reload them all. |
513 """ |
512 """ |
514 name = 'reload' |
513 name = 'reload' |
515 |
514 |
516 def reload_application(self, appid): |
515 def reload_instance(self, appid): |
517 self.restart_application(appid) |
516 self.restart_instance(appid) |
518 |
517 |
519 |
518 |
520 class StatusCommand(ApplicationCommand): |
519 class StatusCommand(InstanceCommand): |
521 """Display status information about the given applications. |
520 """Display status information about the given instances. |
522 |
521 |
523 <application>... |
522 <instance>... |
524 identifiers of the applications to status. If no application is |
523 identifiers of the instances to status. If no instance is |
525 given, get status information about all registered applications. |
524 given, get status information about all registered instances. |
526 """ |
525 """ |
527 name = 'status' |
526 name = 'status' |
528 options = () |
527 options = () |
529 |
528 |
530 @staticmethod |
529 @staticmethod |
531 def status_application(appid): |
530 def status_instance(appid): |
532 """print running status information for an application""" |
531 """print running status information for an instance""" |
533 for mode in cwcfg.possible_configurations(appid): |
532 for mode in cwcfg.possible_configurations(appid): |
534 config = cwcfg.config_for(appid, mode) |
533 config = cwcfg.config_for(appid, mode) |
535 print '[%s-%s]' % (appid, mode), |
534 print '[%s-%s]' % (appid, mode), |
536 try: |
535 try: |
537 pidf = config['pid-file'] |
536 pidf = config['pid-file'] |
538 except KeyError: |
537 except KeyError: |
539 print 'buggy application, pid file not specified' |
538 print 'buggy instance, pid file not specified' |
540 continue |
539 continue |
541 if not exists(pidf): |
540 if not exists(pidf): |
542 print "doesn't seem to be running" |
541 print "doesn't seem to be running" |
543 continue |
542 continue |
544 pid = int(open(pidf).read().strip()) |
543 pid = int(open(pidf).read().strip()) |
549 print "should be running with pid %s but the process can not be found" % pid |
548 print "should be running with pid %s but the process can not be found" % pid |
550 continue |
549 continue |
551 print "running with pid %s" % (pid) |
550 print "running with pid %s" % (pid) |
552 |
551 |
553 |
552 |
554 class UpgradeApplicationCommand(ApplicationCommandFork, |
553 class UpgradeInstanceCommand(InstanceCommandFork, |
555 StartApplicationCommand, |
554 StartInstanceCommand, |
556 StopApplicationCommand): |
555 StopInstanceCommand): |
557 """Upgrade an application after cubicweb and/or component(s) upgrade. |
556 """Upgrade an instance after cubicweb and/or component(s) upgrade. |
558 |
557 |
559 For repository update, you will be prompted for a login / password to use |
558 For repository update, you will be prompted for a login / password to use |
560 to connect to the system database. For some upgrades, the given user |
559 to connect to the system database. For some upgrades, the given user |
561 should have create or alter table permissions. |
560 should have create or alter table permissions. |
562 |
561 |
563 <application>... |
562 <instance>... |
564 identifiers of the applications to upgrade. If no application is |
563 identifiers of the instances to upgrade. If no instance is |
565 given, upgrade them all. |
564 given, upgrade them all. |
566 """ |
565 """ |
567 name = 'upgrade' |
566 name = 'upgrade' |
568 actionverb = 'upgraded' |
567 actionverb = 'upgraded' |
569 options = ApplicationCommand.options + ( |
568 options = InstanceCommand.options + ( |
570 ('force-componant-version', |
569 ('force-componant-version', |
571 {'short': 't', 'type' : 'csv', 'metavar': 'cube1=X.Y.Z,cube2=X.Y.Z', |
570 {'short': 't', 'type' : 'csv', 'metavar': 'cube1=X.Y.Z,cube2=X.Y.Z', |
572 'default': None, |
571 'default': None, |
573 'help': 'force migration from the indicated version for the specified cube.'}), |
572 'help': 'force migration from the indicated version for the specified cube.'}), |
574 ('force-cubicweb-version', |
573 ('force-cubicweb-version', |
582 'help': 'only upgrade files on the file system, not the database.'}), |
581 'help': 'only upgrade files on the file system, not the database.'}), |
583 |
582 |
584 ('nostartstop', |
583 ('nostartstop', |
585 {'short': 'n', 'action' : 'store_true', |
584 {'short': 'n', 'action' : 'store_true', |
586 'default': False, |
585 'default': False, |
587 'help': 'don\'t try to stop application before migration and to restart it after.'}), |
586 'help': 'don\'t try to stop instance before migration and to restart it after.'}), |
588 |
587 |
589 ('verbosity', |
588 ('verbosity', |
590 {'short': 'v', 'type' : 'int', 'metavar': '<0..2>', |
589 {'short': 'v', 'type' : 'int', 'metavar': '<0..2>', |
591 'default': 1, |
590 'default': 1, |
592 'help': "0: no confirmation, 1: only main commands confirmed, 2 ask \ |
591 'help': "0: no confirmation, 1: only main commands confirmed, 2 ask \ |
593 for everything."}), |
592 for everything."}), |
594 |
593 |
595 ('backup-db', |
594 ('backup-db', |
596 {'short': 'b', 'type' : 'yn', 'metavar': '<y or n>', |
595 {'short': 'b', 'type' : 'yn', 'metavar': '<y or n>', |
597 'default': None, |
596 'default': None, |
598 'help': "Backup the application database before upgrade.\n"\ |
597 'help': "Backup the instance database before upgrade.\n"\ |
599 "If the option is ommitted, confirmation will be ask.", |
598 "If the option is ommitted, confirmation will be ask.", |
600 }), |
599 }), |
601 |
600 |
602 ('ext-sources', |
601 ('ext-sources', |
603 {'short': 'E', 'type' : 'csv', 'metavar': '<sources>', |
602 {'short': 'E', 'type' : 'csv', 'metavar': '<sources>', |
608 (recommended). If 'all' is given, will connect to all defined sources.", |
607 (recommended). If 'all' is given, will connect to all defined sources.", |
609 }), |
608 }), |
610 ) |
609 ) |
611 |
610 |
612 def ordered_instances(self): |
611 def ordered_instances(self): |
613 # need this since mro return StopApplicationCommand implementation |
612 # need this since mro return StopInstanceCommand implementation |
614 return ApplicationCommand.ordered_instances(self) |
613 return InstanceCommand.ordered_instances(self) |
615 |
614 |
616 def upgrade_application(self, appid): |
615 def upgrade_instance(self, appid): |
617 from logilab.common.changelog import Version |
616 from logilab.common.changelog import Version |
618 config = cwcfg.config_for(appid) |
617 config = cwcfg.config_for(appid) |
619 config.repairing = True # notice we're not starting the server |
618 config.repairing = True # notice we're not starting the server |
620 config.verbosity = self.config.verbosity |
619 config.verbosity = self.config.verbosity |
621 try: |
620 try: |
622 config.set_sources_mode(self.config.ext_sources or ('migration',)) |
621 config.set_sources_mode(self.config.ext_sources or ('migration',)) |
623 except AttributeError: |
622 except AttributeError: |
624 # not a server config |
623 # not a server config |
625 pass |
624 pass |
626 # get application and installed versions for the server and the componants |
625 # get instance and installed versions for the server and the componants |
627 print 'getting versions configuration from the repository...' |
626 print 'getting versions configuration from the repository...' |
628 mih = config.migration_handler() |
627 mih = config.migration_handler() |
629 repo = mih.repo_connect() |
628 repo = mih.repo_connect() |
630 vcconf = repo.get_versions() |
629 vcconf = repo.get_versions() |
631 print 'done' |
630 print 'done' |
652 else: |
651 else: |
653 applcubicwebversion = vcconf.get('cubicweb') |
652 applcubicwebversion = vcconf.get('cubicweb') |
654 if cubicwebversion > applcubicwebversion: |
653 if cubicwebversion > applcubicwebversion: |
655 toupgrade.append(('cubicweb', applcubicwebversion, cubicwebversion)) |
654 toupgrade.append(('cubicweb', applcubicwebversion, cubicwebversion)) |
656 if not self.config.fs_only and not toupgrade: |
655 if not self.config.fs_only and not toupgrade: |
657 print 'no software migration needed for application %s' % appid |
656 print 'no software migration needed for instance %s' % appid |
658 return |
657 return |
659 for cube, fromversion, toversion in toupgrade: |
658 for cube, fromversion, toversion in toupgrade: |
660 print '**** %s migration %s -> %s' % (cube, fromversion, toversion) |
659 print '**** %s migration %s -> %s' % (cube, fromversion, toversion) |
661 # only stop once we're sure we have something to do |
660 # only stop once we're sure we have something to do |
662 if not (cwcfg.mode == 'dev' or self.config.nostartstop): |
661 if not (cwcfg.mode == 'dev' or self.config.nostartstop): |
663 self.stop_application(appid) |
662 self.stop_instance(appid) |
664 # run cubicweb/componants migration scripts |
663 # run cubicweb/componants migration scripts |
665 mih.migrate(vcconf, reversed(toupgrade), self.config) |
664 mih.migrate(vcconf, reversed(toupgrade), self.config) |
666 # rewrite main configuration file |
665 # rewrite main configuration file |
667 mih.rewrite_configuration() |
666 mih.rewrite_configuration() |
668 # handle i18n upgrade: |
667 # handle i18n upgrade: |
679 'continue anyway ?'): |
678 'continue anyway ?'): |
680 print 'migration not completed' |
679 print 'migration not completed' |
681 return |
680 return |
682 mih.shutdown() |
681 mih.shutdown() |
683 print |
682 print |
684 print 'application migrated' |
683 print 'instance migrated' |
685 if not (cwcfg.mode == 'dev' or self.config.nostartstop): |
684 if not (cwcfg.mode == 'dev' or self.config.nostartstop): |
686 self.start_application(appid) |
685 self.start_instance(appid) |
687 print |
686 print |
688 |
687 |
689 |
688 |
690 class ShellCommand(Command): |
689 class ShellCommand(Command): |
691 """Run an interactive migration shell. This is a python shell with |
690 """Run an interactive migration shell. This is a python shell with |
692 enhanced migration commands predefined in the namespace. An additional |
691 enhanced migration commands predefined in the namespace. An additional |
693 argument may be given corresponding to a file containing commands to |
692 argument may be given corresponding to a file containing commands to |
694 execute in batch mode. |
693 execute in batch mode. |
695 |
694 |
696 <application> |
695 <instance> |
697 the identifier of the application to connect. |
696 the identifier of the instance to connect. |
698 """ |
697 """ |
699 name = 'shell' |
698 name = 'shell' |
700 arguments = '<application> [batch command file]' |
699 arguments = '<instance> [batch command file]' |
701 options = ( |
700 options = ( |
702 ('system-only', |
701 ('system-only', |
703 {'short': 'S', 'action' : 'store_true', |
702 {'short': 'S', 'action' : 'store_true', |
704 'default': False, |
703 'default': False, |
705 'help': 'only connect to the system source when the instance is ' |
704 'help': 'only connect to the system source when the instance is ' |
734 else: |
733 else: |
735 mih.interactive_shell() |
734 mih.interactive_shell() |
736 mih.shutdown() |
735 mih.shutdown() |
737 |
736 |
738 |
737 |
739 class RecompileApplicationCatalogsCommand(ApplicationCommand): |
738 class RecompileInstanceCatalogsCommand(InstanceCommand): |
740 """Recompile i18n catalogs for applications. |
739 """Recompile i18n catalogs for instances. |
741 |
740 |
742 <application>... |
741 <instance>... |
743 identifiers of the applications to consider. If no application is |
742 identifiers of the instances to consider. If no instance is |
744 given, recompile for all registered applications. |
743 given, recompile for all registered instances. |
745 """ |
744 """ |
746 name = 'i18ninstance' |
745 name = 'i18ninstance' |
747 |
746 |
748 @staticmethod |
747 @staticmethod |
749 def i18ninstance_application(appid): |
748 def i18ninstance_instance(appid): |
750 """recompile application's messages catalogs""" |
749 """recompile instance's messages catalogs""" |
751 config = cwcfg.config_for(appid) |
750 config = cwcfg.config_for(appid) |
752 try: |
751 try: |
753 config.bootstrap_cubes() |
752 config.bootstrap_cubes() |
754 except IOError, ex: |
753 except IOError, ex: |
755 import errno |
754 import errno |
756 if ex.errno != errno.ENOENT: |
755 if ex.errno != errno.ENOENT: |
757 raise |
756 raise |
758 # bootstrap_cubes files doesn't exist |
757 # bootstrap_cubes files doesn't exist |
759 # set creating to notify this is not a regular start |
758 # notify this is not a regular start |
760 config.creating = True |
759 config.repairing = True |
761 # create an in-memory repository, will call config.init_cubes() |
760 # create an in-memory repository, will call config.init_cubes() |
762 config.repository() |
761 config.repository() |
763 except AttributeError: |
762 except AttributeError: |
764 # web only config |
763 # web only config |
765 config.init_cubes(config.repository().get_cubes()) |
764 config.init_cubes(config.repository().get_cubes()) |
789 """run the command with its specific arguments""" |
788 """run the command with its specific arguments""" |
790 for cube in cwcfg.available_cubes(): |
789 for cube in cwcfg.available_cubes(): |
791 print cube |
790 print cube |
792 |
791 |
793 register_commands((ListCommand, |
792 register_commands((ListCommand, |
794 CreateApplicationCommand, |
793 CreateInstanceCommand, |
795 DeleteApplicationCommand, |
794 DeleteInstanceCommand, |
796 StartApplicationCommand, |
795 StartInstanceCommand, |
797 StopApplicationCommand, |
796 StopInstanceCommand, |
798 RestartApplicationCommand, |
797 RestartInstanceCommand, |
799 ReloadConfigurationCommand, |
798 ReloadConfigurationCommand, |
800 StatusCommand, |
799 StatusCommand, |
801 UpgradeApplicationCommand, |
800 UpgradeInstanceCommand, |
802 ShellCommand, |
801 ShellCommand, |
803 RecompileApplicationCatalogsCommand, |
802 RecompileInstanceCatalogsCommand, |
804 ListInstancesCommand, ListCubesCommand, |
803 ListInstancesCommand, ListCubesCommand, |
805 )) |
804 )) |
806 |
805 |
807 |
806 |
808 def run(args): |
807 def run(args): |