예제 #1
0
파일: sites.py 프로젝트: aspc/piccolo
 def addUser(self, user, suppress_welcome=False):
     if shell.is_pretend():
         suppress_welcome = True
         logger.info("Pretending to add {0} to site {1}".format(user, self))
     
     session = db.Session()
     logger.debug('Users in {0}: {1}'.format(self.shortname, self.users))
     if user in self.users:
         raise Site.AlreadyHasUser
     if not shell.is_pretend():
         self.users.append(user)
         session.commit()
     try:
         do("gpasswd -a {0} {1}".format(user.username, self.shortname))
         do("ln -s {0} {1}".format(self._get_home(), shell.join(user._get_home(), self.shortname)))
     except shell.ShellActionFailed:
         if not shell.is_pretend():
             self.users.remove(user)
             session.commit()
         raise
     else:
         if not suppress_welcome:
             email_vars = {
                 "$FULL_NAME": user.full_name,
                 "$SITE_SHORTNAME": self.shortname,
             }
             
             email_message = shell.format(open(shell.join(config.TEMPLATE_ROOT, 'site_adduser_email.txt')).read(), email_vars)
             email_subject = "Peninsula Account Update: {0} added to site {1}".format(user.username, self.shortname)
             user.send_email(email_subject, email_message)
             logger.info("Sent adduser email to {0}".format(user.email))
         logger.info('Added {0} to {1}'.format(user.username, self.shortname))
예제 #2
0
파일: users.py 프로젝트: aspc/piccolo
 def archive(destination=None):
     archive_name = '{0}.tar.gz'.format(theuser.username)
     if not destination:
         destination = shell.join(DATA_DIR, 'deleted_users', archive_name)
     else:
         destination = shell.join(destination, archive_name)
     try:
         subprocess.check_output(
             ["/bin/tar", "cvzf",],
             stderr=subprocess.STDOUT
         )
     except subprocess.CalledProcessError, err:
         raise User.ShellActionFailed(err)
예제 #3
0
파일: users.py 프로젝트: aspc/piccolo
 def _shell_create(self):
     do("useradd -U -b {0} -m -s /bin/bash {1}".format(
         config.USERS_ROOT,
         self.username
     ))
     self._format_append("user_bash_profile.sh", shell.join(self._get_home(), ".profile"))
     tmppass = shell.join(self._get_home(), '.tmppass')
     with open(tmppass, 'w') as t:
         os.chmod(tmppass, stat.S_IRWXU)
         t.write("{0}\n{0}\n".format(self._temp_password))
         t.close()
     do("passwd {0} < {1}".format(self.username, tmppass), shell=True)
     do("passwd -e {0}".format(self.username))
     do("rm {0}".format(tmppass))
예제 #4
0
파일: sites.py 프로젝트: aspc/piccolo
 def create(shortname, full_name):
     session = db.Session()
     if Site.get(shortname):
         raise Site.Exists
     elif shell.exists(shell.join(config.SITES_ROOT, shortname)):
         raise Site.Exists
     elif not config.NAME_REGEX.match(shortname) or len(shortname) > config.NAME_LIMIT:
         raise Site.BadName("Site names must be between 2 and {0} characters and be valid hostnames (only letters, numbers, and dashes)".format(config.NAME_LIMIT))
     elif Domain.get('.'.join([shortname, config.DEFAULT_DOMAIN])):
         existing = Domain.get('.'.join([shortname, config.DEFAULT_DOMAIN]))
         raise Site.BadName("There is already a domain {0} in piccolo, so adding this site would "\
             "create a name conflict. Remove {0} from {1} before "\
             "adding this site.".format(existing.domain_name, existing.site.shortname))
     else:
         logger.debug("site doesn't exist yet in db")
         new_site = Site(shortname, full_name)
     
     new_site.db_password = shell.generate_password(length=20)
     new_site.db_username = re.sub(r'[^\w\d]', '_', new_site.shortname)
     new_site.db_username_mysql = new_site.db_username[:16] # grrr
     
     if not shell.is_pretend():
         session.add(new_site)
         session.commit()
     try:
         new_site._shell_create()
         if not shell.is_pretend():
             Domain.create('.'.join([new_site.shortname, config.DEFAULT_DOMAIN]), new_site)
     except shell.ShellActionFailed as e:
         logger.exception("Shell action failed")
         raise
     else:
         do("service nginx reload")
         logger.info('Created site "{0}" [{1}]'.format(full_name, shortname))
예제 #5
0
파일: users.py 프로젝트: aspc/piccolo
 def create(username, full_name, email, suppress_welcome=False, fake_create=False):
     if fake_create:
         suppress_welcome = True
     session = db.Session()
     if not config.NAME_REGEX.match(username) or len(username) > config.NAME_LIMIT:
         raise User.BadName("{0} is not a valid username (containing only letters, numbers, and dashes and being between 2 and {1} characters)".format(username, config.NAME_LIMIT))
     
     if User.get(username):
         raise User.Exists("There is already a user named {0} in piccolo".format(username))
     
     try:
         pwd.getpwnam(username)
     except KeyError:
         pass
     else:
         if not fake_create:
             raise User.Exists("There is already a user named {0} in /etc/passwd".format(username))
     
     if shell.exists(shell.join(config.USERS_ROOT, username)) and not fake_create:
         raise User.BadName("Cannot create user {1} because folder {0} already exists.".format(shell.join(config.USERS_ROOT, username), username))
     logger.debug("user doesn't exist yet")
     new_user = User(username, full_name, email)
     session.add(new_user)
     session.commit()
     new_user._temp_password = shell.generate_password(length=12)
     try:
         if not fake_create:
             new_user._shell_create()
     except User.ShellActionFailed:
         session.delete(new_user)
         session.commit()
         raise
     else:
         logger.info('Created user "{0}" [{1}] with contact email <{2}>'.format(full_name, username, email))
         if not suppress_welcome:
             user_vars = new_user._vars()
             user_vars.update({"$INITIAL_PASSWORD": new_user._temp_password,})
             email_message = shell.format(open(shell.join(config.TEMPLATE_ROOT, 'user_email.txt')).read(), user_vars)
             email_subject = "New Peninsula Account {0}".format(new_user.username)
             new_user.send_email(email_subject, email_message)
             logger.info("Sent welcome email to {0}".format(new_user.email))
         elif not fake_create:
             logger.info("User's initial password: {0}".format(new_user._temp_password))
예제 #6
0
파일: databases.py 프로젝트: aspc/piccolo
 def delete(dbname, site):
     session = db.Session()
     the_db = Database.get(dbname)
     if not the_db:
         raise Database.DoesNotExist
     if the_db.site is not site:
         raise Database.Mismatch("Database {0} exists, but is owned by {1}, not {2}".format(
             dbname,
             the_db.site.shortname,
             site.shortname,
         ))
     the_db._drop()
     if not shell.is_pretend():
         dbms_string = the_db._dbms_string()
         session.delete(the_db)
         session.commit()
         old_db_list = open(shell.join(site._get_home(), 'config', 'databases.txt'), 'r').read()
         new_db_list = old_db_list.replace("[{0}] {1}\n".format(dbms_string, dbname), '')
         with open(shell.join(site._get_home(), 'config', 'databases.txt'), 'w') as db_list:
             db_list.write(new_db_list)
예제 #7
0
파일: databases.py 프로젝트: aspc/piccolo
 def create(dbname, site, dbms, fake_create):
     session = db.Session()
     if Database.get(dbname):
         raise Database.Exists # do not ignore db already existing in piccolo...
     if len(dbname) > 63:
         raise Database.BadName("Database names must be < 63 characters long")
     new_db = Database(dbname, site, dbms)
     new_db._create(fake_create)
     if not shell.is_pretend():
         session.add(new_db)
         session.commit()
         with open(shell.join(site._get_home(), 'config', 'databases.txt'), 'a') as db_list:
             db_list.write("[{0}] {1}\n".format(new_db._dbms_string(), new_db.dbname))
예제 #8
0
파일: sites.py 프로젝트: aspc/piccolo
 def _shell_delete(self):
     for service in ("httpd.sh", "php.sh"):
         do("sudo -u {0} {1} stop".format(self.shortname, shell.join(self._get_home(), "bin", service)))
     do("pkill -u {0}".format(self.shortname), ignore_errors=True)
     
     wait("Waiting for services to be removed from process list")
     
     try:
         self._drop_db_accounts()
     except:
         if not shell.is_forced():
             raise
     
     do("rm /etc/sudoers.d/{0}".format(self.shortname))
     do("rm /etc/piccolo/nginx/{0}.conf".format(self.shortname))
     do("rm -rf /etc/piccolo/nginx/{0}_domains".format(self.shortname))
     do("userdel -r {0}".format(self.shortname))
     do("groupdel {0}".format(self.shortname), ignore_errors=True)
예제 #9
0
파일: sites.py 프로젝트: aspc/piccolo
    def removeUser(self, user):
        if shell.is_pretend():
            logger.info("Pretending to remove {0} from site {1}".format(user, self))

        session = db.Session()
        logger.debug('Users in {0}: {1}'.format(self.shortname, self.users))
        if not user in self.users:
            raise Site.NoSuchUser
        try:
            do("gpasswd -d {0} {1}".format(user.username, self.shortname))
            do("rm {0}".format(shell.join(user._get_home(), self.shortname)))
        except shell.ShellActionFailed:
            logger.exception("Removal failed; user is still member of site in DB.")
            raise
        else:
            if not shell.is_pretend():
                self.users.remove(user)
                session.commit()
            logger.info('Removed {0} from {1}'.format(user.username, self.shortname))
예제 #10
0
파일: sites.py 프로젝트: aspc/piccolo
 def _get_home(self):
     return shell.join(config.SITES_ROOT, self.shortname)
예제 #11
0
파일: sites.py 프로젝트: aspc/piccolo
 def _format_copy(self, src, dest):
     src = shell.join(config.TEMPLATE_ROOT, src)
     shell.template_copy(src, dest, self._vars())
예제 #12
0
파일: sites.py 프로젝트: aspc/piccolo
 def _get_path(self):
     return shell.join(self._get_folder(), "{0}.conf".format(self.domain_name))
예제 #13
0
파일: sites.py 프로젝트: aspc/piccolo
 def _get_folder(self):
     return shell.join(config.NGINX_CONF_ROOT, "{0}_domains".format(self.site.shortname))
예제 #14
0
파일: sites.py 프로젝트: aspc/piccolo
 def _format_template(self, src):
     src = shell.join(config.TEMPLATE_ROOT, src)
     return shell.format(open(src, 'r').read(), self._vars())
예제 #15
0
파일: sites.py 프로젝트: aspc/piccolo
 def _shell_create(self, pretend=False):
     # Actual shell-level business of provisioning the site goes here
     
     # Set up siteuser and sitegroup
     do("useradd -U -b {0} -m -s /bin/bash {1}".format(
         config.SITES_ROOT,
         self.shortname
     ))
     
     # Set up template and permissions
     do("chmod u=rwX,g=rwXs,o=X {0}".format(self._get_home()))
     
     for path in glob.glob(shell.join(config.TEMPLATE_ROOT, 'site', '*')):
         do("cp -R {0} {1}".format(path, self._get_home()))
     
     for d in Site._additional_dirs:
         do("mkdir {0}".format(shell.join(self._get_home(), d)))
     
     do("chown -R {0}:{0} {1}".format(self.shortname, self._get_home()))
     
     for p in Site._permissions:
         do("chmod {0} {1}".format(p[1], shell.join(self._get_home(), p[0])))
     
     # Do variable substitution in template files
     
     for root, dirs, files in os.walk(self._get_home()):
         for name in files:
             shell.format_file(shell.join(root, name), self._vars())
     
     for root, dirs, files in os.walk(shell.join(self._get_home(), "bin")):
         for name in files:
             do("chmod u=rwx,g=rx,o= {0}".format(shell.join(root, name)))
     
     for root, dirs, files in os.walk(shell.join(self._get_home(), "config")):
         for name in files:
             do("chmod u=rw,g=rw,o= {0}".format(shell.join(root, name)))
     
     # Install crontab from temp file
     
     crontab_path = shell.join(self._get_home(), 'crontab')
     self._format_copy('site.crontab', crontab_path)
     
     do("crontab -u {0} {1}".format(self.shortname, crontab_path))
     do("rm {0}".format(crontab_path))
     
     # Install sudoers
     sudoers_dest = '/etc/sudoers.d/{0}'.format(self.shortname)
     if shell.exists(sudoers_dest):
         raise shell.ShellActionFailed("{0} exists. Abort!".format(sudoers_dest))
     self._format_copy('site.sudoers', sudoers_dest)
     do("chmod u=r,g=r,o= {0}".format(sudoers_dest))
     do("chown root:root {0}".format(sudoers_dest))
     
     # Install nginx config
     nginx_dest = shell.join(config.NGINX_CONF_ROOT, "{0}.conf".format(self.shortname))
     if shell.exists(nginx_dest):
         raise shell.ShellActionFailed("{0} exists. Abort!".format(nginx_dest))
     self._format_copy('site.nginx.conf', nginx_dest)
     do("chmod u=rw,g=rw,o=r {0}".format(nginx_dest))
     do("chown root:admin {0}".format(nginx_dest))
     
     do("mkdir {0}".format(shell.join(config.NGINX_CONF_ROOT, "{0}_domains".format(self.shortname))))
     
     # Set up db users
     self._create_db_accounts()
     
     # Start site
     for service in ("httpd.sh", "php.sh"):
         do("sudo -u {0} {1} start".format(self.shortname, shell.join(self._get_home(), "bin", service)))
예제 #16
0
파일: users.py 프로젝트: aspc/piccolo
 def _get_home(self):
     return shell.join(config.USERS_ROOT, self.username)