Changeset 182 for cleverbox/trunk
- Timestamp:
- 08/13/07 20:38:39 (5 years ago)
- Location:
- cleverbox/trunk/cleverbox
- Files:
-
- 2 modified
-
client.py (modified) (2 diffs)
-
scripts/admin.py (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
cleverbox/trunk/cleverbox/client.py
r178 r182 1 """ 2 This module regroups all the logic for manipulating client data in a given environment. 3 """ 4 5 import os 6 from cleverbox import project 7 from cleverbox.utils import filesystem 8 9 client_dir_layout = ('htdocs', 'logs', 'tmp', 'uploads', 'var/svn', 'var/trac') 10 1 11 def exists(environment, client_name): 12 """ 13 Returns true if requested client exists in supplied environment. 14 """ 2 15 return client_name in get(environment) 3 16 4 def get( self,environment, only = False):17 def get(environment, only = False): 5 18 ''' 6 Returns a list of clients .19 Returns a list of clients in supplied environment. 7 20 The "only" parameter is used to restrict returned clients list. Recognized values are "enabled" and "disabled". 8 21 ''' … … 34 47 35 48 return list_clients 49 50 def 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 111 Include %(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 166 def 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 205 def 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 223 def 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 9 9 from cleverbox.environment import Environment 10 10 from cleverbox import client 11 12 _defaults = {13 'client_dir_layout' : ('htdocs', 'logs', 'tmp', 'uploads',14 'var/svn', 'var/trac')15 }16 11 17 12 _version = '0.5dev' … … 224 219 comp = complete_func.__call__() 225 220 226 return self.word_complete( text, comp)221 return self.word_complete(text, comp) 227 222 228 223 … … 231 226 Displays enabled and disabled clients. 232 227 ''' 233 228 234 229 print "Enabled :\n" \ 235 230 "%s\n\n" \ 236 231 "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')) 238 233 239 234 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) 358 236 359 237 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) 398 239 399 240 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) 417 242 418 243 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) 440 245 441 246 def _complete_client_remove(self): 442 return self._get_clients()247 return client.get(self.env) 443 248 444 249 def _complete_client_enable(self): 445 return self._get_clients('disabled')250 return client.get(self.env, 'disabled') 446 251 447 252 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') 491 254 492 255 # … … 523 286 client_projects = {} 524 287 525 clients = self._get_clients()288 clients = client.get() 526 289 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) 528 291 529 292 print client_projects … … 1007 770 return [a for a in words if a.startswith (text)] 1008 771 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 1030 772 def _arg_tokenize (self, argstr): 1031 773 """ … … 1034 776 argstr = util.to_utf8(argstr, sys.stdin.encoding) 1035 777 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']1042 778 1043 779 def run(args):
