cwctl.py
changeset 9402 2c48c091b6a2
parent 9372 e87a808a4c32
child 9511 241b1232ed7f
child 9700 da7d341cca76
equal deleted inserted replaced
9127:aff75b69db92 9402:2c48c091b6a2
     1 # copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
     1 # copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
     2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
     2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
     3 #
     3 #
     4 # This file is part of CubicWeb.
     4 # This file is part of CubicWeb.
     5 #
     5 #
     6 # CubicWeb is free software: you can redistribute it and/or modify it under the
     6 # CubicWeb is free software: you can redistribute it and/or modify it under the
    46 from cubicweb.utils import support_args
    46 from cubicweb.utils import support_args
    47 from cubicweb.cwconfig import CubicWebConfiguration as cwcfg, CWDEV, CONFIGURATIONS
    47 from cubicweb.cwconfig import CubicWebConfiguration as cwcfg, CWDEV, CONFIGURATIONS
    48 from cubicweb.toolsutils import Command, rm, create_dir, underline_title
    48 from cubicweb.toolsutils import Command, rm, create_dir, underline_title
    49 from cubicweb.__pkginfo__ import version
    49 from cubicweb.__pkginfo__ import version
    50 
    50 
    51 if support_args(CommandLine, 'check_duplicated_command'):
    51 # don't check duplicated commands, it occurs when reloading site_cubicweb
    52     # don't check duplicated commands, it occurs when reloading site_cubicweb
    52 CWCTL = CommandLine('cubicweb-ctl', 'The CubicWeb swiss-knife.',
    53     CWCTL = CommandLine('cubicweb-ctl', 'The CubicWeb swiss-knife.',
    53                     version=version, check_duplicated_command=False)
    54                         version=version, check_duplicated_command=False)
       
    55 else:
       
    56     CWCTL = CommandLine('cubicweb-ctl', 'The CubicWeb swiss-knife.',
       
    57                         version=version)
       
    58 
    54 
    59 def wait_process_end(pid, maxtry=10, waittime=1):
    55 def wait_process_end(pid, maxtry=10, waittime=1):
    60     """wait for a process to actually die"""
    56     """wait for a process to actually die"""
    61     import signal
    57     import signal
    62     from time import sleep
    58     from time import sleep
   264                     print '* %s %s' % (cube.ljust(namesize), tversion)
   260                     print '* %s %s' % (cube.ljust(namesize), tversion)
   265                     if self.config.verbose:
   261                     if self.config.verbose:
   266                         if tinfo:
   262                         if tinfo:
   267                             descr = getattr(tinfo, 'description', '')
   263                             descr = getattr(tinfo, 'description', '')
   268                             if not descr:
   264                             if not descr:
   269                                 descr = getattr(tinfo, 'short_desc', '')
   265                                 descr = tinfo.__doc__
   270                                 if descr:
       
   271                                     warn('[3.8] short_desc is deprecated, update %s'
       
   272                                          ' pkginfo' % cube, DeprecationWarning)
       
   273                                 else:
       
   274                                     descr = tinfo.__doc__
       
   275                             if descr:
   266                             if descr:
   276                                 print '    '+ '    \n'.join(descr.splitlines())
   267                                 print '    '+ '    \n'.join(descr.splitlines())
   277                         modes = detect_available_modes(cwcfg.cube_dir(cube))
   268                         modes = detect_available_modes(cwcfg.cube_dir(cube))
   278                         print '    available modes: %s' % ', '.join(modes)
   269                         print '    available modes: %s' % ', '.join(modes)
   279             print
   270             print
   355           'help': 'configuration level (0..2): 0 will ask for essential '
   346           'help': 'configuration level (0..2): 0 will ask for essential '
   356           'configuration parameters only while 2 will ask for all parameters',
   347           'configuration parameters only while 2 will ask for all parameters',
   357           }),
   348           }),
   358         ('config',
   349         ('config',
   359          {'short': 'c', 'type' : 'choice', 'metavar': '<install type>',
   350          {'short': 'c', 'type' : 'choice', 'metavar': '<install type>',
   360           'choices': ('all-in-one', 'repository', 'twisted'),
   351           'choices': ('all-in-one', 'repository'),
   361           'default': 'all-in-one',
   352           'default': 'all-in-one',
   362           'help': 'installation type, telling which part of an instance '
   353           'help': 'installation type, telling which part of an instance '
   363           'should be installed. You can list available configurations using the'
   354           'should be installed. You can list available configurations using the'
   364           ' "list" command. Default to "all-in-one", e.g. an installation '
   355           ' "list" command. Default to "all-in-one", e.g. an installation '
   365           'embedding both the RQL repository and the web server.',
   356           'embedding both the RQL repository and the web server.',
   749 
   740 
   750     def upgrade_instance(self, appid):
   741     def upgrade_instance(self, appid):
   751         print '\n' + underline_title('Upgrading the instance %s' % appid)
   742         print '\n' + underline_title('Upgrading the instance %s' % appid)
   752         from logilab.common.changelog import Version
   743         from logilab.common.changelog import Version
   753         config = cwcfg.config_for(appid)
   744         config = cwcfg.config_for(appid)
       
   745         instance_running = exists(config['pid-file'])
   754         config.repairing = True # notice we're not starting the server
   746         config.repairing = True # notice we're not starting the server
   755         config.verbosity = self.config.verbosity
   747         config.verbosity = self.config.verbosity
   756         set_sources_mode = getattr(config, 'set_sources_mode', None)
   748         set_sources_mode = getattr(config, 'set_sources_mode', None)
   757         if set_sources_mode is not None:
   749         if set_sources_mode is not None:
   758             set_sources_mode(self.config.ext_sources or ('migration',))
   750             set_sources_mode(self.config.ext_sources or ('migration',))
   759         # get instance and installed versions for the server and the componants
   751         # get instance and installed versions for the server and the componants
   760         mih = config.migration_handler()
   752         mih = config.migration_handler()
   761         repo = mih.repo_connect()
   753         repo = mih.repo_connect()
   762         vcconf = repo.get_versions()
   754         vcconf = repo.get_versions()
       
   755         helper = self.config_helper(config, required=False)
   763         if self.config.force_cube_version:
   756         if self.config.force_cube_version:
   764             for cube, version in self.config.force_cube_version.iteritems():
   757             for cube, version in self.config.force_cube_version.iteritems():
   765                 vcconf[cube] = Version(version)
   758                 vcconf[cube] = Version(version)
   766         toupgrade = []
   759         toupgrade = []
   767         for cube in config.cubes():
   760         for cube in config.cubes():
   780         else:
   773         else:
   781             applcubicwebversion = vcconf.get('cubicweb')
   774             applcubicwebversion = vcconf.get('cubicweb')
   782         if cubicwebversion > applcubicwebversion:
   775         if cubicwebversion > applcubicwebversion:
   783             toupgrade.append(('cubicweb', applcubicwebversion, cubicwebversion))
   776             toupgrade.append(('cubicweb', applcubicwebversion, cubicwebversion))
   784         # only stop once we're sure we have something to do
   777         # only stop once we're sure we have something to do
   785         if not (CWDEV or self.config.nostartstop):
   778         if instance_running and not (CWDEV or self.config.nostartstop):
   786             StopInstanceCommand(self.logger).stop_instance(appid)
   779             StopInstanceCommand(self.logger).stop_instance(appid)
   787         # run cubicweb/componants migration scripts
   780         # run cubicweb/componants migration scripts
   788         if self.config.fs_only or toupgrade:
   781         if self.config.fs_only or toupgrade:
   789             for cube, fromversion, toversion in toupgrade:
   782             for cube, fromversion, toversion in toupgrade:
   790                 print '-> migration needed from %s to %s for %s' % (fromversion, toversion, cube)
   783                 print '-> migration needed from %s to %s for %s' % (fromversion, toversion, cube)
   796         mih.shutdown()
   789         mih.shutdown()
   797         # handle i18n upgrade
   790         # handle i18n upgrade
   798         if not self.i18nupgrade(config):
   791         if not self.i18nupgrade(config):
   799             return
   792             return
   800         print
   793         print
       
   794         if helper:
       
   795             helper.postupgrade(repo)
   801         print '-> instance migrated.'
   796         print '-> instance migrated.'
   802         if not (CWDEV or self.config.nostartstop):
   797         if instance_running and not (CWDEV or self.config.nostartstop):
   803             # restart instance through fork to get a proper environment, avoid
   798             # restart instance through fork to get a proper environment, avoid
   804             # uicfg pb (and probably gettext catalogs, to check...)
   799             # uicfg pb (and probably gettext catalogs, to check...)
   805             forkcmd = '%s start %s' % (sys.argv[0], appid)
   800             forkcmd = '%s start %s' % (sys.argv[0], appid)
   806             status = system(forkcmd)
   801             status = system(forkcmd)
   807             if status:
   802             if status:
  1036                     appcfg.global_set_option(key, value)
  1031                     appcfg.global_set_option(key, value)
  1037                 except KeyError:
  1032                 except KeyError:
  1038                     raise ConfigurationError('unknown configuration key "%s" for mode %s' % (key, appcfg.name))
  1033                     raise ConfigurationError('unknown configuration key "%s" for mode %s' % (key, appcfg.name))
  1039             appcfg.save()
  1034             appcfg.save()
  1040 
  1035 
       
  1036 
       
  1037 # WSGI #########
       
  1038 
       
  1039 def wsgichoices():
       
  1040     try:
       
  1041         from werkzeug import serving
       
  1042     except ImportError:
       
  1043         return ('stdlib',)
       
  1044     return ('stdlib', 'werkzeug')
       
  1045 
       
  1046 class WSGIDebugStartHandler(InstanceCommand):
       
  1047     """Start an interactive wsgi server """
       
  1048     name = 'wsgi'
       
  1049     actionverb = 'started'
       
  1050     arguments = '<instance>'
       
  1051     options = (
       
  1052         ('method',
       
  1053          {'short': 'm',
       
  1054           'type': 'choice',
       
  1055           'metavar': '<method>',
       
  1056           'default': 'stdlib',
       
  1057           'choices': wsgichoices(),
       
  1058           'help': 'wsgi utility/method'}),
       
  1059         ('loglevel',
       
  1060          {'short': 'l',
       
  1061           'type' : 'choice',
       
  1062           'metavar': '<log level>',
       
  1063           'default': 'debug',
       
  1064           'choices': ('debug', 'info', 'warning', 'error'),
       
  1065           'help': 'debug if -D is set, error otherwise',
       
  1066           }),
       
  1067         )
       
  1068 
       
  1069     def wsgi_instance(self, appid):
       
  1070         config = cwcfg.config_for(appid, debugmode=1)
       
  1071         init_cmdline_log_threshold(config, self['loglevel'])
       
  1072         assert config.name == 'all-in-one'
       
  1073         meth = self['method']
       
  1074         if meth == 'stdlib':
       
  1075             from cubicweb.wsgi import server
       
  1076         else:
       
  1077             from cubicweb.wsgi import wz as server
       
  1078         return server.run(config)
       
  1079 
       
  1080 
       
  1081 
  1041 for cmdcls in (ListCommand,
  1082 for cmdcls in (ListCommand,
  1042                CreateInstanceCommand, DeleteInstanceCommand,
  1083                CreateInstanceCommand, DeleteInstanceCommand,
  1043                StartInstanceCommand, StopInstanceCommand, RestartInstanceCommand,
  1084                StartInstanceCommand, StopInstanceCommand, RestartInstanceCommand,
       
  1085                WSGIDebugStartHandler,
  1044                ReloadConfigurationCommand, StatusCommand,
  1086                ReloadConfigurationCommand, StatusCommand,
  1045                UpgradeInstanceCommand,
  1087                UpgradeInstanceCommand,
  1046                ListVersionsInstanceCommand,
  1088                ListVersionsInstanceCommand,
  1047                ShellCommand,
  1089                ShellCommand,
  1048                RecompileInstanceCatalogsCommand,
  1090                RecompileInstanceCatalogsCommand,
  1049                ListInstancesCommand, ListCubesCommand,
  1091                ListInstancesCommand, ListCubesCommand,
  1050                ConfigureInstanceCommand,
  1092                ConfigureInstanceCommand,
  1051                ):
  1093                ):
  1052     CWCTL.register(cmdcls)
  1094     CWCTL.register(cmdcls)
       
  1095 
       
  1096 
  1053 
  1097 
  1054 def run(args):
  1098 def run(args):
  1055     """command line tool"""
  1099     """command line tool"""
  1056     import os
  1100     import os
  1057     sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
  1101     sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)