Changeset 182 for cleverbox/trunk

Show
Ignore:
Timestamp:
08/13/07 20:38:39 (5 years ago)
Author:
trivoallan
Message:

cleverbox : refactored projects in their own module.

Location:
cleverbox/trunk/cleverbox
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • cleverbox/trunk/cleverbox/client.py

    r178 r182  
     1""" 
     2This module regroups all the logic for manipulating client data in a given environment. 
     3""" 
     4 
     5import os 
     6from cleverbox import project 
     7from cleverbox.utils import filesystem 
     8 
     9client_dir_layout = ('htdocs', 'logs', 'tmp', 'uploads', 'var/svn', 'var/trac') 
     10 
    111def exists(environment, client_name): 
     12    """ 
     13    Returns true if requested client exists in supplied environment. 
     14    """ 
    215    return client_name in get(environment) 
    316 
    4 def get(self, environment, only = False): 
     17def get(environment, only = False): 
    518    ''' 
    6     Returns a list of clients. 
     19    Returns a list of clients in supplied environment. 
    720    The "only" parameter is used to restrict returned clients list. Recognized values are "enabled" and "disabled". 
    821    ''' 
     
    3447 
    3548    return list_clients 
     49 
     50def add(environment, client_name): 
     51    """ 
     52    Creates a new client in supplied environment. 
     53      * Checks if client not already exists 
     54      * Collects informations about client 
     55      * Checks informations are correct 
     56      * Create clients environment directory layout 
     57      * Creates apache configuration fragment 
     58    """ 
     59 
     60    if (exists(environment, client_name)): 
     61        raise Exception, 'Client "%s" already exists' % client_name 
     62 
     63    # Client name cannot contain strokes 
     64    if client_name.count('-') != 0: 
     65        print "** Client's identifier can not contain the '-' character." 
     66        return 
     67 
     68    # Information collection 
     69    collected_infos = {'full_name' : None, 
     70                       'home_dir'  : None} 
     71     
     72    collected_infos['home_dir'] = os.path.join(environment.config.get('general', 'clients_root'), client_name) 
     73 
     74    # A few checks before effectively creating client 
     75    # -- homedir 
     76    parent_dir = os.path.normpath(os.path.join(collected_infos['home_dir'], os.pardir)) 
     77    dir_is_ok = os.access(parent_dir, os.W_OK) and not os.access(collected_infos['home_dir'], os.R_OK) 
     78    if not dir_is_ok: 
     79        print "Directory %s is not writable or already exists, aborting." % collected_infos['home_dir'] 
     80        raise os.error 
     81 
     82 
     83    print 
     84    print "Creating a new client." 
     85    print "Let's collect some informations about him : " 
     86    print 
     87    print "  Please enter client's full name." 
     88    print "  This will be used in several interface screens and in emails." 
     89    print 
     90 
     91    dfn = client_name.capitalize() 
     92    collected_infos['full_name'] = raw_input('Full Name [%s]> ' % dfn).strip() or dfn 
     93 
     94    print 
     95    print "Supplied informations verified." 
     96    print "Let's proceed with client creation :" 
     97    print 
     98 
     99    # Client creation 
     100    # -- Homedir layout 
     101    homedir_layout = [] 
     102    for d in client_dir_layout: 
     103        homedir_layout.append(os.path.join(collected_infos['home_dir'], d)) 
     104    map(os.makedirs, homedir_layout) 
     105 
     106    print "  Directory layout created in %s\n" % collected_infos['home_dir'] 
     107 
     108    # -- Apache configuration 
     109    apache_conf = """ 
     110# -- Include enabled projects configuration files 
     111Include %(env_dir)s/projects-enabled/%(client_name)s-* 
     112""" % { 'client_name' : client_name, 
     113'home_dir'    : collected_infos['home_dir'], 
     114'env_dir'     : environment.path } 
     115 
     116    # -- Write conf to filesystem 
     117    apache_conf_filepath = os.path.join( environment.path, 'clients-available', client_name ) 
     118    f = file(apache_conf_filepath, 'w+') 
     119    f.write(apache_conf) 
     120    f.close() 
     121 
     122    print "  Apache configuration written to %s\n" % apache_conf_filepath 
     123 
     124    # -- Fix permissions 
     125    """ 
     126    chown -R dev:dev /$CLIENTSROOT/$CLIENTNAME 
     127    chown dev:www-data /$CLIENTSROOT/$CLIENTNAME/logs 
     128    chmod g+w /$CLIENTSROOT/$CLIENTNAME/logs 
     129    chown dev:www-data /$CLIENTSROOT/$CLIENTNAME/uploads 
     130    chmod g+w /$CLIENTSROOT/$CLIENTNAME/uploads 
     131    """ 
     132    filesystem.chowntree(collected_infos['home_dir'], 
     133                         filesystem.get_uid_from_name(environment.config.get('general', 'ssh_user')), 
     134                         filesystem.get_gid_from_name(environment.config.get('general', 'ssh_group'))) 
     135     
     136    os.chown(os.path.join(collected_infos['home_dir'], 'logs'), 
     137             filesystem.get_uid_from_name(environment.config.get('general', 'ssh_user')),  
     138             filesystem.get_gid_from_name(environment.config.get('general', 'apache_group')) ) 
     139     
     140    os.chmod(os.path.join(collected_infos['home_dir'], 'logs'), 0775) 
     141     
     142    os.chown(os.path.join(collected_infos['home_dir'], 'uploads'), 
     143             filesystem.get_uid_from_name(environment.config.get('general', 'ssh_user')), 
     144             filesystem.get_gid_from_name(environment.config.get('general', 'apache_group'))) 
     145     
     146    os.chmod(os.path.join(collected_infos['home_dir'], 'uploads'), 0775) 
     147 
     148    print "  Fixed permissions in %s\n" % collected_infos['home_dir'] 
     149 
     150    #  Final steps 
     151    # -- Enable client ? 
     152    print "Client has been created. Do you want to enable it ?" 
     153    print 
     154    enable_client = raw_input('Enable client ? [y/N]> ').strip() or False 
     155 
     156    if enable_client == 'y': 
     157        self._do_client_enable(client_name) 
     158 
     159    print 
     160    print "Client %s was successfully created." % collected_infos['full_name'] 
     161    print "Apache configuration need to be reloaded for this to be effective." 
     162    print 
     163    print "You may want create some projects now. Try 'help project' for some documentation." 
     164    print 
     165 
     166def remove(environment, client_name): 
     167    """ 
     168    Deletes client from supplied environment. 
     169    """ 
     170     
     171    if not exists(environment, client_name): 
     172        raise Exception, 'Client "%s" does not exists.' 
     173 
     174    continue_removal = False 
     175    print "You are about to remove client '%s'." % client_name 
     176    confirm_removal = raw_input('Remove client ? [y/N]> ').strip() or False 
     177    if confirm_removal == 'y': 
     178        continue_removal = True 
     179 
     180    if not continue_removal: 
     181        print "Client '%s' was *not* removed" % client_name 
     182        return 
     183 
     184    # Client is enabled, propose disabling it 
     185    client_disabled = True 
     186    if client_name in self._get_clients('enabled'): 
     187        client_disabled = False 
     188        print "You can not remove an enabled client. Disabling it." 
     189        try: 
     190            disable(environment, client_name) 
     191        except Exception, e: 
     192            print e 
     193 
     194    # Disable client's projects 
     195    for project_name in project.get(environment, client_name, 'enabled'): 
     196        project.disable(environment, (client_name, project_name)) 
     197 
     198    # Disable client 
     199    client_apacheconf = os.path.join( self.env.path, 'clients-available', client_name ) 
     200    os.unlink(client_apacheconf) 
     201     
     202    print "Client '%s' has been removed." % client_name 
     203    print "Apache configuration needs to be reloaded for this to be effective." 
     204 
     205def enable(environment, client_name): 
     206    """ 
     207    Enables client in supplied environment. 
     208    """ 
     209     
     210    if not exists(environment, client_name): 
     211        raise Exception, 'Client "%s" does not exist.' % client_name 
     212 
     213    if client_name in get(environment, 'enabled'): 
     214        raise Exception, 'Client "%s" is already enabled.' % client_name 
     215 
     216    target = os.path.join(self.env.path, 'clients-available', client_name) 
     217    linkname = os.path.join(self.env.path, 'clients-enabled', client_name) 
     218    os.symlink(target, linkname) 
     219 
     220    print "Client '%s' has been enabled" % client_name 
     221    print "Apache configuration needs to be reloaded for this to be effective." 
     222 
     223def disable(environment, client_name): 
     224    """ 
     225    Disables a client in supplied environment. 
     226    TODO : disable client's projects. 
     227    """ 
     228    if not exists(environment, client_name): 
     229        raise Exception, 'Client "%s" does not exist.' % client_name 
     230 
     231    if client_name in get(environment, 'disabled'): 
     232        raise Exception, 'Client "%s" is already enabled.' % client_name 
     233 
     234    linkname = os.path.join(self.env.path, 'clients-enabled', client_name) 
     235    os.unlink(linkname) 
     236     
     237    print "Client '%s' has been disabled" % client_name 
     238    print "Apache configuration needs to be reloaded for this to be effective." 
  • cleverbox/trunk/cleverbox/scripts/admin.py

    r180 r182  
    99from cleverbox.environment import Environment 
    1010from cleverbox import client 
    11  
    12 _defaults = { 
    13     'client_dir_layout' : ('htdocs', 'logs', 'tmp', 'uploads', 
    14                            'var/svn', 'var/trac') 
    15 } 
    1611 
    1712_version = '0.5dev' 
     
    224219                comp = complete_func.__call__() 
    225220 
    226         return self.word_complete( text, comp ) 
     221        return self.word_complete(text, comp) 
    227222 
    228223 
     
    231226        Displays enabled and disabled clients. 
    232227        ''' 
    233  
     228         
    234229        print "Enabled :\n" \ 
    235230              "%s\n\n" \ 
    236231              "Disabled : \n" \ 
    237               "%s\n" % (self._get_clients('enabled'), self._get_clients('disabled')) 
     232              "%s\n" % (client.get(self.env, 'enabled'), client.get(self.env, 'disabled')) 
    238233 
    239234    def _do_client_add(self, client_name): 
    240         """ 
    241         Creates a new client. 
    242           * Checks if client not already exists. 
    243           * Collects informations about client 
    244           * Checks informations are correct 
    245           * Create clients environment directory layout 
    246           * Creates apache conf for apache 
    247           * Inserts client into LDAP 
    248         """ 
    249  
    250         if not client.exists(self.env, client_name): 
    251  
    252             # Client name cannot contain strokes 
    253             if client_name.count('-') != 0: 
    254                 print "** Client's identifier can not contain the '-' character." 
    255                 return 
    256  
    257             # Information collection 
    258             collected_infos = { 'full_name'    : None, 
    259                                 'home_dir'     : None, 
    260                                 'ftp_password' : None } 
    261  
    262             collected_infos['home_dir'] = os.path.join(self.env.config.get('general', 'clients_root'), client_name) 
    263  
    264             # A few checks before effectively creating client 
    265             # -- homedir 
    266             parent_dir = os.path.normpath(os.path.join(collected_infos['home_dir'], os.pardir)) 
    267             dir_is_ok = os.access(parent_dir, os.W_OK) and not os.access(collected_infos['home_dir'], os.R_OK) 
    268             if not dir_is_ok: 
    269                 print "Directory %s is not writable or already exists, aborting." % collected_infos['home_dir'] 
    270                 raise os.error 
    271  
    272  
    273             print 
    274             print "Creating a new client." 
    275             print "Let's collect some informations about him : " 
    276             print 
    277             print "  Please enter client's full name." 
    278             print "  This will be used in several interface screens and in emails." 
    279             print 
    280  
    281             dfn = client_name.capitalize() 
    282             collected_infos['full_name'] = raw_input('Full Name [%s]> ' % dfn).strip() or dfn 
    283  
    284             print 
    285             print "Supplied informations verified." 
    286             print "Let's proceed with client creation :" 
    287             print 
    288  
    289             # Client creation 
    290             # -- Homedir layout 
    291             homedir_layout = [] 
    292             for d in _defaults['client_dir_layout']: 
    293                 homedir_layout.append( os.path.join(collected_infos['home_dir'], d) ) 
    294             map( os.makedirs, homedir_layout ) 
    295  
    296             print "  Directory layout created in %s\n" % collected_infos['home_dir'] 
    297  
    298             # -- Apache configuration 
    299             apache_conf = """ 
    300 # -- Include enabled projects configuration files 
    301 Include %(env_dir)s/projects-enabled/%(client_name)s-* 
    302 """ % { 'client_name' : client_name, 
    303         'home_dir'    : collected_infos['home_dir'], 
    304         'env_dir'     : self.env.path } 
    305  
    306             # -- Write conf to filesystem 
    307             apache_conf_filepath = os.path.join( self.env.path, 'clients-available', client_name ) 
    308             f = file(apache_conf_filepath, 'w+') 
    309             f.write(apache_conf) 
    310             f.close() 
    311  
    312             print "  Apache configuration written to %s\n" % apache_conf_filepath 
    313  
    314             # -- Fix permissions 
    315             """ 
    316             chown -R dev:dev /$CLIENTSROOT/$CLIENTNAME 
    317             chown dev:www-data /$CLIENTSROOT/$CLIENTNAME/logs 
    318             chmod g+w /$CLIENTSROOT/$CLIENTNAME/logs 
    319             chown dev:www-data /$CLIENTSROOT/$CLIENTNAME/uploads 
    320             chmod g+w /$CLIENTSROOT/$CLIENTNAME/uploads 
    321             """ 
    322             self._rchown(collected_infos['home_dir'], 
    323                          self.get_uid_from_name(username)(self.env.config.get('general', 'ssh_user')), 
    324                          self.get_gid_from_name(self.env.config.get('general', 'ssh_group'))) 
    325              
    326             os.chown(os.path.join(collected_infos['home_dir'], 'logs'), 
    327                      get_uid_from_name(self.env.config.get('general', 'ssh_user')),  
    328                      get_gid_from_name(self.env.config.get('general', 'apache_group')) ) 
    329              
    330             os.chmod(os.path.join(collected_infos['home_dir'], 'logs'), 0775) 
    331              
    332             os.chown(os.path.join(collected_infos['home_dir'], 'uploads'), 
    333                      get_uid_from_name(self.env.config.get('general', 'ssh_user')), 
    334                      get_gid_from_name(self.env.config.get('general', 'apache_group'))) 
    335              
    336             os.chmod(os.path.join(collected_infos['home_dir'], 'uploads'), 0775) 
    337  
    338             print "  Fixed permissions in %s\n" % collected_infos['home_dir'] 
    339  
    340             #  Final steps 
    341             # -- Enable client ? 
    342             print "Client has been created. Do you want to enable it ?" 
    343             print 
    344             enable_client = raw_input('Enable client ? [y/N]> ').strip() or False 
    345  
    346             if enable_client == 'y': 
    347                 self._do_client_enable(client_name) 
    348  
    349             print 
    350             print "Client %s was successfully created." % collected_infos['full_name'] 
    351             print "Apache configuration need to be reloaded for this to be effective." 
    352             print 
    353             print "You may want create some projects now. Try 'help project' for some documentation." 
    354             print 
    355  
    356         else: 
    357             print "This client already exists !" 
     235        client.create(self.env, client_name) 
    358236 
    359237    def _do_client_remove(self, client_name): 
    360         """ 
    361         Suppression d'un client. 
    362         Un client actif ne peut être supprimé. 
    363         TODO : suppression du répertoire du client. (bof) 
    364         """ 
    365  
    366         if self._client_exists(client_name): 
    367             continue_removal = False 
    368             print "You are about to remove client '%s'." % client_name 
    369             confirm_removal = raw_input('Remove client ? [y/N]> ').strip() or False 
    370             if confirm_removal == 'y': 
    371                 continue_removal = True 
    372  
    373             if not continue_removal: 
    374                 print "Client '%s' was *not* removed" % client_name 
    375                 return 
    376  
    377             # Client is enabled, propose disabling it 
    378             client_disabled = True 
    379             if client_name in self._get_clients('enabled'): 
    380                 client_disabled = False 
    381                 print "You can not remove an enabled client. Disabling it." 
    382                 try: 
    383                     self._do_client_disable(client_name) 
    384                 except Exception, e: 
    385                     print e 
    386  
    387             # Disable client's projects 
    388             for project_name in self._get_projects(client_name, 'enabled'): 
    389                 self._do_project_disable((client_name, project_name)) 
    390  
    391             # Disable client 
    392             client_apacheconf = os.path.join( self.env.path, 'clients-available', client_name ) 
    393             os.unlink(client_apacheconf) 
    394             print "Client '%s' has been removed." % client_name 
    395             print "Apache configuration needs to be reloaded for this to be effective." 
    396         else: 
    397             print "This client does not exist !" 
     238        client.remove(self.env, client_name) 
    398239 
    399240    def _do_client_enable(self, client_name): 
    400         enable_client = True 
    401         if not self._client_exists(client_name): 
    402             print "This client does not exist !" 
    403             enable_client = False 
    404  
    405         if client_name in self._get_clients('enabled'): 
    406             print "This client is already enabled !" 
    407             enable_client = False 
    408  
    409         if enable_client: 
    410             target = os.path.join( self.env.path, 'clients-available', client_name ) 
    411             linkname = os.path.join( self.env.path, 'clients-enabled', client_name ) 
    412             os.symlink( target, linkname ) 
    413             print "Client '%s' has been enabled" % client_name 
    414             print "Apache configuration needs to be reloaded for this to be effective." 
    415         else: 
    416             print "Client '%s' was *not* enabled" % client_name 
     241        client.enable(self.env, client_name) 
    417242 
    418243    def _do_client_disable(self, client_name): 
    419         """ 
    420         Disables a client. 
    421         TODO : disable client's projects. 
    422         """ 
    423         disable_client = True 
    424         if not self._client_exists(client_name): 
    425             print "This client does not exist !" 
    426             disable_client = False 
    427  
    428         if client_name in self._get_clients('disabled'): 
    429             print "This client is already disabled !" 
    430             disable_client = False 
    431  
    432         if disable_client: 
    433             linkname = os.path.join( self.env.path, 'clients-enabled', client_name ) 
    434             os.unlink( linkname ) 
    435             print "Client '%s' has been disabled" % client_name 
    436             print "Apache configuration needs to be reloaded for this to be effective." 
    437         else: 
    438             print "Client '%s' was *not* disabled" % client_name 
    439  
     244        client.disable(self.env, client_name) 
    440245 
    441246    def _complete_client_remove(self): 
    442         return self._get_clients() 
     247        return client.get(self.env) 
    443248 
    444249    def _complete_client_enable(self): 
    445         return self._get_clients('disabled') 
     250        return client.get(self.env, 'disabled') 
    446251 
    447252    def _complete_client_disable(self): 
    448         return self._get_clients('enabled') 
    449  
    450  
    451     def _client_exists(self, name): 
    452         """ 
    453         Tells whether or not a client exists. 
    454         return bool 
    455         """ 
    456         return name in self._get_clients() 
    457  
    458     def _get_clients(self, only = False): 
    459         ''' 
    460         Returns a list of clients. 
    461         The "only" parameter is used to restrict returned clients list. Recognized values are "enabled" and "disabled". 
    462         ''' 
    463  
    464         list_clients = [] 
    465  
    466         # Each client 
    467         if not only: 
    468             list_clients = os.listdir(os.path.join(self.env.path, 'clients-available')) 
    469  
    470         # Only enabled clients 
    471         elif only == 'enabled': 
    472             list_clients = os.listdir(os.path.join(self.env.path, 'clients-enabled')) 
    473  
    474         # Only disabled clients (ie. not enabled) 
    475         elif only == 'disabled': 
    476  
    477             disabled_clients = [] 
    478             available_clients = os.listdir(os.path.join(self.env.path, 'clients-available')) 
    479             enabled_clients = os.listdir(os.path.join(self.env.path, 'clients-enabled')) 
    480  
    481             # Expect poor performances for this intersection algorithm 
    482             # see http://python.project.cwi.nl/search/hypermail/python-recent/0159.html 
    483             for e in available_clients: 
    484                 if e not in enabled_clients: 
    485                     disabled_clients.append(e) 
    486  
    487             list_clients = disabled_clients 
    488  
    489         return list_clients 
    490  
     253        return client.get(self.env, 'enabled') 
    491254 
    492255    # 
     
    523286        client_projects = {} 
    524287 
    525         clients = self._get_clients() 
     288        clients = client.get() 
    526289        for client_name in clients: 
    527             client_projects[client_name] = self._get_projects(client_name) 
     290            client_projects[client_name] = project.get(environment, client_name) 
    528291 
    529292        print client_projects 
     
    1007770        return [a for a in words if a.startswith (text)] 
    1008771 
    1009     def _rchown(self, directory, uid, gid): 
    1010         """ 
    1011         Recursive chown. 
    1012         """ 
    1013         try: 
    1014             if (os.path.isdir(directory)): 
    1015                 os.chown(directory, uid, gid) 
    1016                 direntries = os.listdir(directory) 
    1017                 for direntry in direntries: 
    1018                     direntry = os.path.join(directory, direntry) 
    1019                     if (os.path.isdir(direntry)): 
    1020                         os.chown(direntry, uid, gid) 
    1021                         os.chdir(direntry) 
    1022                         self._rchown(direntry, uid, gid) 
    1023                     else: 
    1024                         os.chown(direntry, uid, gid) 
    1025             else: 
    1026                 os.chown(directory, uid, gid) 
    1027         except (IOError, os.error), why: 
    1028             print "rchown %s: %s" % (str(directory), str(why)) 
    1029  
    1030772    def _arg_tokenize (self, argstr): 
    1031773        """ 
     
    1034776        argstr = util.to_utf8(argstr, sys.stdin.encoding) 
    1035777        return shlex.split(argstr) or [''] 
    1036  
    1037     def get_uid_from_name(self, username): 
    1038         return posix.pwd.getpwnam(username)['pw_uid'] 
    1039          
    1040     def get_gid_from_name(self, groupname): 
    1041         return posix.grp.getgrnam(groupname)['gr_gid'] 
    1042778 
    1043779def run(args):