#!/usr/bin/python from datetime import date,datetime import os, errno, sqlite3, sys, getopt, shutil registry_paths=["/etc/domainctl/registry"] registry = "domains.db" database = "domains.db" def main(argv): try: opts, args = getopt.getopt(argv, "acd:Dhlvz", ["add", "create", "delete=", "dir", "help", "list", "vhost", "zone"]) except getopt.GetoptError: usage() sys.exit(2) for opt, arg in opts: if opt in ("-a", "--add"): if len(args) < 3: usage() sys.exit(2) user, subdomain, domain, email = split_args(args) add_domain(user, subdomain, domain, email) elif opt in ("-c", "--create"): create_db() elif opt in ("-d", "--delete"): if len(args) < 1: usage() sys.exit(2) if arg in ("u", "user"): delete_user(args[0]) elif arg in ("d", "domain"): if args[0].count(".") < 2: delete_domain(args[0]) else: subdomain, domain = args[0].split(".", 1) delete_subdomain(subdomain, domain) else: usage() sys.exit(2) elif opt in ("-D", "--dir"): if len(args) < 1: usage() sys.exit(2) if args[0].count(".") < 2: subdomain, domain = ("", args[0]) else: subdomain, domain = args[0].split(".", 1) build_structure(subdomain, domain) elif opt in ("-h", "--help"): usage() sys.exit(2) elif opt in ("-l", "--list"): list_domains() elif opt in ("-v", "--vhost"): if len(args) < 1: usage() sys.exit(2) if args[0].count(".") < 2: subdomain = '' domain = args[0] else: subdomain, domain = args[0].split(".", 1) build_vhost(subdomain, domain) elif opt in ("-z", "--zone"): if len(args) < 1: usage() sys.exit(2) build_zone(args[0]) else: usage() sys.exit(2) sys.exit(0) def split_args(args): user = args[0] if args[1].count(".") < 2: subdomain, domain = ("", args[1]) else: subdomain, domain = args[1].split(".", 1) email = args[2] return user, subdomain, domain, email def add_domain(user, subdomain, domain, email): try: db = sqlite3.connect(database) db.execute(""" insert into store (user, subdomain, domain, email) values (?, ?, ?, ?) """, (user.lower(), subdomain.lower(), domain.lower(), email.lower(),)) db.commit() except sqlite3.OperationalError as e: print "error: %s" % e sys.exit(1) def create_db(): """Creates the database for tracking control info.""" try: db = sqlite3.connect(database) db.execute(""" create table store ( id integer primary key, user text not null, subdomain text not null, domain text not null, email text not null ) """) except sqlite3.OperationalError as e: print "error: %s" % e sys.exit(1) def delete_user(user): """Drops a user entry, and all associated domains, from the database.""" try: db = sqlite3.connect(database) resultset = db.execute(""" select 1 from store where user = ? """, (user,)).fetchall() if len(resultset) == 0: print "User '%s' does not exist." % user sys.exit(1) resultset = db.execute(""" select subdomain, domain from store where user = ? """, (user,)).fetchall() print "WARNING! You are about to delete the user '%s' and the following domains:" for subdomain, domain in resultset: if subdomain != '': domain = subdomain + "." + domain print domain answer = raw_input("Are you sure that you want to do this? (y/N): ") if answer.lower() == "y" or answer.lower() == "yes": db.execute(""" delete from store where user = ? """, (user,)) db.commit() else: print "Aborted." except sqlite3.OperationalError as e: print "error: %s" % e sys.exit(1) def delete_domain(domain): """Drops a domain (or subdomain), and all associated subdomains, from the database.""" if domain.count(".") < 2: subdomain, domain = ("", args[1]) else: subdomain, domain = domain.split(".", 1) try: db = sqlite3.connect(database) resultset = db.execute(""" select 1 from store where domain = ? """, (domain,)).fetchall() if len(resultset) == 0: print "Domain '%s' does not exist." % domain sys.exit(1) resultset = db.execute(""" select subdomain, domain from store where domain = ? and subdomain != '' """, (domain,)).fetchall() print "WARNING! You are about to delete the domain '%s' and the following subdomains:" % domain for subdomain, domain in resultset: print "%s.%s" % (subdomain, domain) answer = raw_input("Are you sure that you want to do this? (y/N): ") if answer.lower() == "y" or answer.lower() == "yes": db.execute(""" delete from store where domain = ? """, (domain,)) else: print "Aborted." except sqlite3.OperationalError as e: print "error: %s" % e sys.exit(1) def delete_subdomain(subdomain, domain): """Drops a subdomain from the database.""" try: db = sqlite3.connect(database) resultset = db.execute(""" select 1 from store where domain = ? and subdomain = ? """, (domain, subdomain,)).fetchall() if len(resultset) == 0: print "Subdomain '%s.%s' does not exist." % (subdomain, domain) sys.exit(1) print "WARNING! You are about to delete the subdomain '%s.%s'." % (subdomain, domain) answer = raw_input("Are you sure that you want to do this? (y/N): ") if answer.lower() == "y" or answer.lower() == "yes": db.execute(""" delete from store where domain = ? and subdomain = ? """, (domain, subdomain,)) else: print "Aborted." except sqlite3.OperationalError as e: print "error: %s" % e sys.exit(1) def list_domains(): """Prints the stored domains in a visually helpful manner.""" try: db = sqlite3.connect(database) resultset = db.execute(""" select * from store """).fetchall() for id, user, subdomain, domain, email in resultset: if subdomain != "": domain = subdomain + "." + domain print "%s%s%s" % (user.ljust(16), email.ljust(32), domain) except sqlite3.OperationalError as e: print "error: %s" % e sys.exit(1) def is_registered(user, domain, subdomain): db = sqlite3.connect(registry) try: resultset = db.execute("""select 1 from domains where user = ? and domain = ? and subdomain = ? """).fetchall() except sqlite3.OperationalError as e: create_db() exit(1) for result in resultset: print result line = registry.readline() while line: line = line.rstrip("\n") if line.startswith("%s:%s" % (user, domain)) == True: registry.close() return "domain" elif line == "%s:%s:%s" % (user, domain, subdomain): registry.close() return "subdomain" line = registry.readline() registry.close() return None def register(user, domain, subdomain): registry = open("registry", "a") registry.write("%s:%s:%s\n" % (user, domain, subdomain)) registry.close() def build_zone(domain): zone_file = "%s.zone" % domain try: db = sqlite3.connect(database) resultset = db.execute(""" select user from store where domain = ? and subdomain = '' """, (domain,)).fetchall() user = resultset[0][0] resultset = db.execute(""" select subdomain from store where domain = ? and subdomain != '' """, (domain,)).fetchall() except sqlite3.OperationalError as e: print "error: %s" % e sys.exit(1) if os.path.isfile(zone_file): shutil.copy(zone_file, zone_file + ".old") template = open("zone_template.txt", "r") zone = open(zone_file, "w") line = template.readline() while line: line = line.replace("[user]", user) line = line.replace("[domain]", domain) line = line.replace("[serial]", date.strftime(datetime.today(), format="%Y%m%d%M")) zone.write(line) line = template.readline() zone.seek(0, os.SEEK_END) for subdomain in resultset: zone.write("%sIN CNAME %s.\n" % (subdomain[0].ljust(32), domain)) zone.close() template.close() def add_sub_to_zone(domain, subdomain): zone_file = "%s.zone" % domain zone = open(zone_file, "a") zone.seek(0, os.SEEK_END) zone.write("%s\tIN\tCNAME\t%s.\n" % (subdomain, domain)) zone.close() def build_vhost(subdomain, domain): if subdomain: vhost_file = "%s.%s" % (subdomain, domain) else: vhost_file = domain try: db = sqlite3.connect(database) resultset = db.execute(""" select user from store where domain = ? and subdomain = ? limit 1 """, (domain, subdomain,)).fetchall() user = resultset[0][0] except sqlite3.OperationalError as e: print "error: %s" % e sys.exit(1) if os.path.isfile(vhost_file): shutil.copy(vhost_file, vhost_file + ".old") template = open("vhost_template.txt", "r") vhost = open(vhost_file, "w") line = template.readline() while line: if not subdomain: line = line.replace("[subdomain].[domain]", domain) line = line.replace("[ServerAlias]", "ServerAlias www.%s" % domain) else: line = line.replace("[ServerAlias]", "") line = line.replace("[user]", user) line = line.replace("[domain]", domain) line = line.replace("[subdomain]", subdomain) line = line.replace("//", "/") vhost.write(line) line = template.readline() vhost.close() template.close() def build_structure(subdomain, domain): try: db = sqlite3.connect(database) resultset = db.execute(""" select user from store where domain = ? and subdomain = ? limit 1 """, (domain, subdomain,)).fetchall() if len(resultset) == 0: if subdomain: print "Subdomain '%s.%s' does not exist." % (subdomain, domain) else: print "Domain '%s' does not exist." % domain sys.exit(1) user = resultset[0][0] if not subdomain: os.makedirs(name="/var/www/%s/%s/public_html" % (user, domain), mode=0755) os.makedirs(name="/var/www/%s/%s/cgi-bin" % (user, domain), mode=0755) else: os.makedirs(name="/var/www/%s/%s/%s/public_html" % (user, domain, subdomain), mode=0755) os.makedirs(name="/var/www/%s/%s/%s/cgi-bin" % (user, domain, subdomain), mode=0755) except OSError as exc: if exc.errno == errno.EEXIST: pass else: raise except sqlite3.OperationalError as e: print "error: %s" % e sys.exit(1) def usage(): print "domainctl