Exemple #1
0
    def stop(self):
        """Stop the daemon."""
        log("info", "Enter stop")
        # Get the pid from the pidfile
        try:
            pf = file(self.pidfile, 'r')
            pid = int(pf.read().strip())
            pf.close()
        except IOError:
            pid = None

        if not pid:
            message = "pidfile %s does not exist. Daemon not running?"
            # sys.stderr.write(message % self.pidfile)
            log("fail", message % self.pidfile)
            return  # not an error in a restart

        # Try killing the daemon process
        try:
            while 1:
                os.kill(pid, SIGTERM)
                time.sleep(0.1)
        except OSError, err:
            err = str(err)
            if err.find("No such process") > 0:
                if os.path.exists(self.pidfile):
                    os.remove(self.pidfile)
            else:
                print str(err)
                sys.exit(1)
Exemple #2
0
 def __init__(
         self,
         pidfile,
         stdin='/dev/null',
         stdout='/dev/null',
         stderr='/dev/null'):
     """Save settings."""
     log("info", "Enter init")
     self.stdin = stdin
     self.stdout = stdout
     self.stderr = stderr
     self.pidfile = pidfile
     log("info", "Exit init")
Exemple #3
0
 def set_disc_quota(self):
     """Set disc quota."""
     try:
         subprocess.check_call([
             "setquota",
             "-u", self.username,
             str(self.disc_quotum * 1024),  # soft limit (blocks)
             str(int(self.disc_quotum * 1024 * 1.5)),  # hard limit (blocks)
             "0",  # soft limit (inodes)
             "0",  # hard limit (inodes)
             "-a"])  # on all volumes in /etc/mtab
     except (OSError, subprocess.CalledProcessError) as error:
         log("fail", "Failed to set disc quotum.")
         log("fail", error)
Exemple #4
0
    def prompt(self, to_do):
        """Get data for virtual host."""
        self.username = raw_input("Username: "******"Domain name: ").lower()

        if to_do['user'] or to_do['mysql']:
            self.password = gen_passwd()

        if to_do['mysql']:
            self.dbuser = cap16(self.domain).replace(".", "_").replace("-", "_")

        self.homedir = raw_input("Homedir[/home/%s]: " % self.username)
        if self.homedir == "":
            self.homedir = "/home/%s" % self.username

        if to_do['user']:
            self.skel = raw_input("Skeleton dir[/home/vhostskel]: ")
            if self.skel == "":
                self.skel = "/home/vhostskel"

            try:
                self.disc_quotum = int(raw_input("Disc quotum (in MB): "))
            except ValueError:
                log("warn", "Invalid entry - disc quotum set to 0")
                self.disc_quotum = 0

        if to_do['nginx']:
            self.hostnames = raw_input("Server name(s) (space separated): ")

            self.nginx = {
                'ssl': str_to_bool(raw_input("Use ssl (yes/no): ")),
                'sslred': str_to_bool(raw_input(
                    "Redirect to https? (yes/no): ")),
                'sslcert': str_to_bool(raw_input(
                    "Create self-signed certificates? (yes/no): ")),
                'wwwred': str_to_bool(raw_input(
                    "Redirect to www? (yes/no): ")),
                'php': str_to_bool(raw_input("Use php (yes/no): ")),
                'ipv6': str_to_bool(raw_input("Use ipv6 (yes/no): ")),
                'wp': str_to_bool(raw_input("Wordpress settings? (yes/no): "))}

        self.mailto = raw_input("Mail summary to: ")
Exemple #5
0
    def daemonize(self):
        """
        Do the UNIX double-fork magic.

        See Stevens' "Advanced Programming in the UNIX Environment"
        for details (ISBN 0201563177)
        http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16
        """
        log("info", "Enter daemonize")
        try:
            pid = os.fork()
            if pid > 0:
                # exit first parent
                sys.exit(0)
        except OSError, e:
            # sys.stderr.write("fork #1 failed: %d (%s)" % (e.errno, e.strerror))
            log(
                "fail",
                "fork #1 failed: %d (%s)" % (e.errno, e.strerror))
            sys.exit(1)
Exemple #6
0
 def create_user(self):
     """Create user account."""
     try:
         subprocess.check_call([
             "useradd",
             "-d", self.homedir,  # home directory
             "-k", self.skel,  # skeleton directory for homedir
             "-m",  # create home directory if it doesn't exist
             "-p", crypt.crypt(self.password, "22"),  # encrypted password
             self.username])
     except (OSError, subprocess.CalledProcessError) as error:
         log("fail", "Failed to create user account.")
         log("fail", error)
         return 1
     else:
         log("ok", "User creation successful!")
Exemple #7
0
    def start(self):
        """Start the daemon."""
        log("info", "Enter start")
        # Check for a pidfile to see if the daemon already runs
        try:
            pf = file(self.pidfile, 'r')
            pid = int(pf.read().strip())
            pf.close()
        except IOError:
            pid = None

        if pid:
            message = "pidfile %s already exist. Daemon already running?"
            # sys.stderr.write(message % self.pidfile)
            log("fail", message % self.pidfile)
            sys.exit(1)

        # Start the daemon
        self.daemonize()
        self.run()
        log("info", "Exit start")
Exemple #8
0
    def create_wordpress(self, docroot):
        """Arrange all the wordpress stuff."""
        lang = str(raw_input(
            "Choose wordpress language. (eng/nl)[eng]: "))
        if lang == "":
            lang = "eng"
        # add to /etc/pyvhost/wordpress list for maintenance
        try:
            line = "%s %s %s" % (lang.upper(), docroot, self.domain)
            line_pres = False
            with open("/etc/pyvhost/wordpress", 'r') as mfile:
                content = mfile.read().split('\n')
                for rule in content:
                    if rule == line:
                        line_pres = True
                if not line_pres:
                    content.append(line)
            with open("/etc/pyvhost/wordpress", 'w') as mfile:
                mfile.write('\n'.join(content))
        except (OSError, IOError) as error:
            log(
                "fail",
                "Failed to add domain to wordpress maintenance list")
            log("fail", error)
            log(
                "info",
                "Try adding this line to /etc/pyvhost/wordpress manually:")
            log("info", "%s %s %s\n" % (
                lang.upper(),
                docroot,
                self.domain))
        else:
            log("ok", "Added domain to wordpress maintenance list.")

        # install wordpress if necessary
        install = str_to_bool(raw_input("Install wordpress? (y/n): "))
        if install:
            try:
                subprocess.check_call(
                    "cp -r /etc/pyvhost/wp-%s/* %s/." % (lang, docroot),
                    shell=True)
            except (OSError, subprocess.CalledProcessError) as error:
                log("fail", "Failed to copy wordpress files to docroot.")
                log("fail", error)
            else:
                log("ok", "Copied wordpress files to docroot.")
            # Now chown directory!
            try:
                subprocess.check_call([
                    "chown",
                    "-R",
                    "%s:" % self.username,
                    "%s" % docroot])
            except (OSError, subprocess.CalledProcessError) as error:
                log("fail", "Failed to set owner of wordpress install")
                log("fail", error)
Exemple #9
0
    def create_nginx(self):
        """Create nginx config file."""
        docroot = os.path.join(self.homedir, self.domain, "www")
        try:
            with open("/usr/share/pyVhost/default", "r") as source_file:
                template = string.Template(source_file.read())
                template = template.safe_substitute(
                    hostnames=self.hostnames,
                    domain=self.domain,
                    docroot=docroot,
                    ssl="" if self.nginx["ssl"] else "#",
                    sslred="" if self.nginx["sslred"] else "#",
                    nosslred="#" if self.nginx["sslred"] else "",
                    wp="" if self.nginx["wp"] else "#",
                    nowp="#" if self.nginx["wp"] else "",
                    php="" if self.nginx["php"] else "#",
                    nophp="#" if self.nginx["php"] else "",
                    wwwred="" if self.nginx["wwwred"] else "#",
                    ipv6="" if self.nginx["ipv6"] else "#")
                path = os.path.join(
                    "/etc/nginx/sites-available",
                    self.domain)
                with open(path, "w") as config_file:
                    config_file.write(template)
        except (OSError, IOError) as error:
            log("fail", "Failed to create config file for nginx.")
            log("fail", error)
        else:  # only attempt symlink creation and nginx restart at success
            log("ok", "Nginx config created")

            # if indicated, create self-signed certificates
            if self.nginx["sslcert"]:
                try:
                    subprocess.check_call([
                        "openssl",
                        "req",
                        "-new",
                        "-x509",
                        "-sha256",
                        "-days",
                        "365",
                        "-nodes",
                        "-newkey",
                        "rsa:2048",
                        "-out",
                        os.path.join("/etc/nginx/certs", self.domain + ".pem"),
                        "-keyout",
                        os.path.join("/etc/nginx/certs", self.domain + ".key")
                        ])
                except (OSError, subprocess.CalledProcessError) as error:
                    log("fail", "Failed to create certificates.")
                    log("fail", error)
                else:
                    log("ok", "Created self-signed certificates.")

            # now link this config file in sites-enabled and restart nginx
            try:
                subprocess.check_call([
                    "ln",
                    "-s",
                    path,
                    "/etc/nginx/sites-enabled/."])
            except (OSError, subprocess.CalledProcessError) as error:
                log("fail", "Failed to create symlink.")
                log("fail", error)
            else:
                log("ok", "Created symlink to enable virtual host.")

            try:
                subprocess.check_call([
                    "/etc/init.d/nginx",
                    "configtest"])
            except (OSError, subprocess.CalledProcessError) as error:
                log("fail", "Invalid nginx config - fix manually!")
                log("fail", error)
            else:
                log("ok", "Nginx config valid - now restarting nginx...")
                try:
                    subprocess.check_call([
                        "/etc/init.d/nginx",
                        "restart"])
                except (OSError, subprocess.CalledProcessError) as error:
                    log("fail", "Failed to restart nginx.")
                    log("fail", error)
                else:
                    log("ok", "Restarted nginx.")
        # Now do some wordpress magic
        # I added this here, because create_nginx has all
        # the right info and it was too much work to separate
        # out the wordpress stuff
        if self.nginx['wp']:
            self.create_wordpress(docroot)
Exemple #10
0
    def create_domain(self):
        """Create domain folder inside user account."""
        try:
            subprocess.check_call([
                "mkdir",
                "-p",
                os.path.join(self.homedir, self.domain, "www")])
        except (OSError, subprocess.CalledProcessError) as error:
            log("fail", "Failed to create domain folder.")
            log("fail", error)
        else:
            log("ok", "Created domain folder.")

        try:
            subprocess.check_call([
                "mkdir",
                "-p",
                os.path.join(self.homedir, self.domain, "backup")])
        except (OSError, subprocess.CalledProcessError) as error:
            log("fail", "Failed to create backup folder.")
            log("fail", error)
        else:
            log("ok", "Created backup folder.")

        try:
            subprocess.check_call([
                "chown",
                "-R",
                self.username + ":",
                os.path.join(self.homedir, self.domain)])
        except (OSError, subprocess.CalledProcessError) as error:
            log("fail", "Failed to chown domain folder.")
            log("fail", error)
        else:
            log(
                "ok",
                "Set %s as owner of domain folder." % self.username)
Exemple #11
0
 def create_db(self):
     """Create database."""
     # pylint: disable=no-member
     mysql_pass = getpass.getpass("Password for mysql root user: "******"create database %s;\n" % self.dbuser
     sql += "grant all privileges on %s.* " % self.dbuser
     sql += "to %s@'localhost' " % self.dbuser
     sql += "identified by '%s';\n" % self.password
     sql += "flush privileges;\n"
     try:
         connection = db.connect(
             host="localhost",
             user="******",
             passwd=mysql_pass)
         cursor = connection.cursor()
         cursor.execute(sql)
         cursor.close()
         connection.close()
     except db.Error as error:
         log("fail", "Database creation failed:")
         log("fail", "Error %d: %s" % (error.args[0], error.args[1]))
         log("info", "Try executing the sql manually:")
         log("info", sql)
     else:
         log("ok", "Database creation successful!")
     # now set backup script
     command = "mysqldump -h 127.0.0.1 "
     command += "--user %s " % self.dbuser
     command += "--password=%s " % self.password
     command += "%s > " % self.dbuser
     command += "%s/" % os.path.join(self.homedir, self.domain, "backup")
     command += "%s-dump-" % self.dbuser
     command += "`date \"+\\%Y-\\%m-\\%d-\\%H-\\%M\"`.sql"
     dbrotate = "find %s" % os.path.join(
         self.homedir,
         self.domain,
         "backup")
     dbrotate += " -type f -mtime +2|xargs -i rm -f {}"
     cron = CronTab(user=self.username)
     backup = cron.new(command=command)
     minute = random.choice(range(60))
     hour = random.choice(range(24))
     backup.setall("%d %d * * *" % (minute, hour))
     rotate = cron.new(command=dbrotate)
     minute = random.choice(range(60))
     hour = random.choice(range(24))
     rotate.setall("%d %d * * *" % (minute, hour))
     try:
         assert backup.is_valid() == True
         assert rotate.is_valid() == True
     except AssertionError:
         log("fail", "Invalid cron command for db backups.")
     else:
         cron.write_to_user(user=self.username)
         log("ok", "Added cron for db backup and backup rotation.")
Exemple #12
0
                self.devices.append(device)
                device.grab()
                InputDeviceDispatcher(device)
        loop()

    def stop(self):
        """Teardown."""
        for device in self.devices:
            device.ungrab()
        Daemon.stop(self)

if __name__ == "__main__":
    daemon = Harmony(CONFIG['config']['pid_file'])
    if len(sys.argv) == 2:
        if sys.argv[1] == "start":
            log("info", "Starting Harmony")
            daemon.start()
        elif sys.argv[1] == "stop":
            log("info", "Stopping Harmony")
            daemon.stop()
        elif sys.argv[1] == "restart":
            log("info", "Restarting Harmony")
            daemon.restart()
        else:
            log("fail", "Unknown command")
            sys.exit(2)
        sys.exit(0)
    else:
        log("info", "Usage %s start|stop|restart" % sys.argv[0])
        sys.exit(2)
Exemple #13
0
    def create(self, action):
        """Execute appropriate parts after confirmation."""
        to_do = {
            'user': False,
            'domain': False,
            'mysql': False,
            'nginx': False}
        if action == "create-user":
            to_do['user'] = True
        elif action == "add-domain":
            to_do['domain'] = True
            to_do['mysql'] = True
            to_do['nginx'] = True
        elif action == "create-db":
            to_do['mysql'] = True
        elif action == "create-nginx-config":
            to_do['nginx'] = True
        elif action == "all":
            to_do['user'] = True
            to_do['domain'] = True
            to_do['mysql'] = True
            to_do['nginx'] = True

        self.prompt(to_do)

        log("header", "#########################")
        log("header", "#        Summary        #")
        log("header", "#########################")
        log("header", "")
        log("info", self)
        log("info", "")
        log("info", to_do)
        log("info", "")
        if to_do['nginx']:
            log(
                "warn",
                ("WARNING: this will overwrite nginx "
                 "config if the file exists!"))
        raw_input("Cancel by pressing Ctrl-C or confirm by pressing Enter")

        exit_code = 0
        if to_do['user']:
            code = self.create_user()
            exit_code = code if code != 0 else exit_code
            code = self.set_disc_quota()
            exit_code = code if code != 0 else exit_code
        if to_do['domain']:
            code = self.create_domain()
            exit_code = code if code != 0 else exit_code
        if to_do['mysql']:
            code = self.create_db()
            exit_code = code if code != 0 else exit_code
        if to_do['nginx']:
            code = self.create_nginx()
            exit_code = code if code != 0 else exit_code
        code = self.mail_summary()
        exit_code = code if code != 0 else exit_code

        return exit_code
Exemple #14
0
 def restart(self):
     """Restart the daemon."""
     log("info", "Enter restart")
     self.stop()
     self.start()
     log("info", "Exit restart")
Exemple #15
0
        os.setsid()
        os.umask(0)

        # do second fork
        try:
            pid = os.fork()
            if pid > 0:
                # exit from second parent
                sys.exit(0)
        except OSError, e:
            # sys.stderr.write("fork #2 failed: %d (%s)" % (e.errno, e.strerror))
            log(
                "fail",
                "fork #2 failed: %d (%s)" % (e.errno, e.strerror))
            sys.exit(1)
        log("info", "split off second fork")

        # if not self.debug:
        #    # redirect standard file descriptors
        #    sys.stdout.flush()
        #    sys.stderr.flush()
        #    si = file(self.stdin, 'r')
        #    so = file(self.stdout, 'a+')
        #    se = file(self.stderr, 'a+', 0)
        #    os.dup2(si.fileno(), sys.stdin.fileno())
        #    os.dup2(so.fileno(), sys.stdout.fileno())
        #    os.dup2(se.fileno(), sys.stderr.fileno())

        log("info", "write pidfile")
        # write pidfile
        atexit.register(self.delpid)
Exemple #16
0
 def mail_summary(self):
     """Send a summary to specified mail addresses via pgp if possible."""
     gpg = gnupg.GPG(gnupghome='/root/.gnupg')
     encrypted_data = gpg.encrypt(str(self), self.mailto, always_trust=True)
     if encrypted_data.status != "encryption ok":
         # pylint: disable=no-member
         log("fail", "PGP encryption failed.")
         log("fail", encrypted_data.status)
         log("fail", encrypted_data.stderr)
         log("info", "Do you want to send the summary unencrypted instead?")
         raw_input("Press Ctrl-C to cancel, press Enter to continue.")
         msg = MIMEText(str(self))
     else:
         msg = MIMEText(str(encrypted_data))
     msg["From"] = "*****@*****.**"
     msg["To"] = self.mailto
     msg["Subject"] = "Virtual host (%s:%s) created" % (
         self.username,
         self.domain)
     try:
         pipe = subprocess.Popen(
             ["/usr/sbin/sendmail", "-t", "-oi"],
             stdin=subprocess.PIPE)
         pipe.communicate(msg.as_string())
     except OSError as error:
         log("fail", "Failed to send summary email.")
         log("fail", error)
     else:
         log("ok", "Summary email sent.")
Exemple #17
0
 def delpid(self):
     """Delete pid file."""
     log("info", "Enter delpid")
     os.remove(self.pidfile)
     log("info", "Exit delpid")
Exemple #18
0
from colorlog import log

import MySQLdb as db
import gnupg
from email.mime.text import MIMEText
import argparse
from crontab import CronTab


# Dirty check for root privileges
try:
    os.rename('/etc/foo', '/etc/bar')
except (OSError, IOError) as error:
    if error[0] == errno.EPERM:
        log("fail", "You need root privileges to execute this script.")
        sys.exit(1)


def gen_passwd(length=12):
    """Generate password."""
    chars = string.letters + string.digits
    return ''.join(choice(chars) for _ in range(length))


def str_to_bool(text):
    """Convert string to boolean."""
    text = text.lower()
    if text == "yes" or text == "y" or text == "true":
        return True
    else:
Exemple #19
0
"""Upgrade all wp installations at once."""

import subprocess
import argparse
import os
import sys
import errno

from colorlog import log

# Dirty check for root privileges
try:
    os.rename('/etc/foo', '/etc/bar')
except (OSError, IOError) as error:
    if error[0] == errno.EPERM:
        log("fail", "You need root privileges to execute this script.")
        sys.exit(1)

# I don't care about constant naming in short scripts.
# I kinda hate typing in all caps.
# pylint: disable=invalid-name
parser = argparse.ArgumentParser(
    prog="upgradewp",
    description="Upgrade all wordpress installations in one go.")
parser.add_argument(
    'action',
    choices=[
        "system",
        "plugin",
        "theme"],
    help="upgrade a plugin, a theme, or wordpress itself (system)")