Example #1
0
def cli(ctx, dname, site):
    """
    List all domains if no <domain> is provided. If <domain> is provided but <site> is not, lists all sites
    hosted under <domain>. If both <domain> and <site> are provided, lists information on the specified site.
    """
    assert isinstance(ctx, Context)

    if dname:
        dname = domain_parse(dname).hostname
        domain = Session.query(Domain).filter(Domain.name == dname).first()

        # No such domain
        if not domain:
            click.secho("No such domain: {dn}".format(dn=dname), fg="red", bold=True, err=True)
            return

    if site:
        site_name = site
        site = Site.get(domain, site)
        if not site:
            click.secho("No such site: {site}".format(site=site_name), fg="red", bold=True, err=True)
            return

        click.secho("Name: {n}".format(n=site.name), bold=True)
        click.secho("Domain: {dn}".format(dn=site.domain.name), bold=True)
        click.secho("Version: {v}".format(v=site.version), bold=True)
        click.secho("License Key: {lk}".format(lk=site.license_key), bold=True)
        click.secho("Status: {s}".format(s=styled_status(site.enabled)), bold=True)
        click.secho("IN_DEV: {id}".format(id=styled_status(site.in_dev)), bold=True)
        click.secho("SSL: {s}".format(s=styled_status(site.ssl)), bold=True)
        click.secho("SPDY: {s}".format(s=styled_status(site.spdy)), bold=True)
        click.secho("GZIP: {g}".format(g=styled_status(site.gzip)), bold=True)
        return

    # Print sites
    if dname:
        # Get sites
        sites = Site.all(domain)
        if not sites:
            click.secho("No sites active under domain: {dn}".format(dn=dname), fg="red", bold=True, err=True)
            return

        # Display site data
        for site in sites:
            prefix = "[DEV] " if site.in_dev else ""
            fg = "green" if site.enabled else "white"
            click.secho("{pre}{name} ({ver})".format(pre=prefix, name=site.name, ver=site.version), fg=fg, bold=True)

        return

    # Print domains
    domains = Domain.all()
    for domain in domains:
        # Extra domains
        extras = ""
        if domain.extras:
            extras = " ({dnames})".format(dnames=str(domain.extras).replace(",", ", "))

        click.secho("{dname}{extras}".format(dname=domain.name, extras=extras), bold=True)
Example #2
0
def cli(ctx, dname, site):
    """
    Enable the <site> under the specified <domain>
    """
    assert isinstance(ctx, Context)

    dname = domain_parse(dname).hostname
    domain = Session.query(Domain).filter(Domain.name == dname).first()
    if not domain:
        click.secho('No such domain: {dn}'.format(dn=dname), fg='red', bold=True, err=True)
        return

    site_name = site
    site = Site.get(domain, site_name)
    if not site:
        click.secho('No such site: {site}'.format(site=site_name), fg='red', bold=True, err=True)
        return

    p = Echo('Constructing paths and configuration files...')
    site.enable()
    p.done()

    # Restart Nginx
    p = Echo('Restarting web server...')
    FNULL = open(os.devnull, 'w')
    subprocess.check_call(['service', 'nginx', 'restart'], stdout=FNULL, stderr=subprocess.STDOUT)
    p.done()
Example #3
0
def cli(ctx, dname, site):
    """
    Enable the <site> under the specified <domain>
    """
    assert isinstance(ctx, Context)

    dname = domain_parse(dname).hostname
    domain = Session.query(Domain).filter(Domain.name == dname).first()
    if not domain:
        click.secho('No such domain: {dn}'.format(dn=dname),
                    fg='red',
                    bold=True,
                    err=True)
        return

    site_name = site
    site = Site.get(domain, site_name)
    if not site:
        click.secho('No such site: {site}'.format(site=site_name),
                    fg='red',
                    bold=True,
                    err=True)
        return

    p = Echo('Constructing paths and configuration files...')
    site.enable()
    p.done()

    # Restart Nginx
    p = Echo('Restarting web server...')
    FNULL = open(os.devnull, 'w')
    subprocess.check_call(['service', 'nginx', 'restart'],
                          stdout=FNULL,
                          stderr=subprocess.STDOUT)
    p.done()
Example #4
0
def cli(ctx, dname, site):
    """
    Launches a MySQL CLI session for the database of the specified IPS installation.
    """
    assert isinstance(ctx, Context)
    log = logging.getLogger('ipsv.mysql')

    dname = domain_parse(dname).hostname
    domain = Session.query(Domain).filter(Domain.name == dname).first()

    # No such domain
    if not domain:
        click.secho('No such domain: {dn}'.format(dn=dname),
                    fg='red',
                    bold=True,
                    err=True)
        return

    site_name = site
    site = Site.get(domain, site_name)

    # No such site
    if not site:
        click.secho('No such site: {site}'.format(site=site_name),
                    fg='red',
                    bold=True,
                    err=True)
        return

    # Connect to the MySQL database and exit
    log.info('Connecting to MySQL database: {db}'.format(db=site.db_name))
    log.debug('MySQL host: {host}'.format(host=site.db_host))
    log.debug('MySQL username: {user}'.format(user=site.db_user))
    log.debug('MySQL password: {pwd}'.format(pwd=site.db_pass))

    os.execl('/usr/bin/mysql', '/usr/bin/mysql',
             '--database={db}'.format(db=site.db_name),
             '--user={user}'.format(user=site.db_user),
             '--password={pwd}'.format(pwd=site.db_pass))
Example #5
0
def cli(ctx, dname, site):
    """
    Launches a MySQL CLI session for the database of the specified IPS installation.
    """
    assert isinstance(ctx, Context)
    log = logging.getLogger('ipsv.mysql')

    dname = domain_parse(dname).hostname
    domain = Session.query(Domain).filter(Domain.name == dname).first()

    # No such domain
    if not domain:
        click.secho('No such domain: {dn}'.format(dn=dname), fg='red', bold=True, err=True)
        return

    site_name = site
    site = Site.get(domain, site_name)

    # No such site
    if not site:
        click.secho('No such site: {site}'.format(site=site_name), fg='red', bold=True, err=True)
        return

    # Connect to the MySQL database and exit
    log.info('Connecting to MySQL database: {db}'.format(db=site.db_name))
    log.debug('MySQL host: {host}'.format(host=site.db_host))
    log.debug('MySQL username: {user}'.format(user=site.db_user))
    log.debug('MySQL password: {pwd}'.format(pwd=site.db_pass))

    os.execl(
        '/usr/bin/mysql',
        '/usr/bin/mysql',
        '--database={db}'.format(db=site.db_name),
        '--user={user}'.format(user=site.db_user),
        '--password={pwd}'.format(pwd=site.db_pass)
    )
Example #6
0
def cli(ctx, name, dname, license_key, ips_version, force, enable, ssl, spdy, gzip, cache, install, dev):
    """
    Downloads and installs a new instance of the latest Invision Power Suite release.
    """
    assert isinstance(ctx, Context)
    login_session = ctx.get_login()
    log = logging.getLogger("ipsv.new")
    ctx.cache = cache

    # Prompt for our desired license
    def get_license():
        """
        Prompt the user for a license selection
        @rtype: ips_vagrant.scraper.licenses.LicenseMeta
        """
        licenses = Licenses(login_session).get()
        user_license = license_key or ctx.config.get("User", "LicenseKey")

        # If we already have a license key saved, skip the prompt and use it instead
        if user_license:
            licenses = {license.license_key: license for license in licenses}
            if user_license in licenses:
                return licenses[user_license]

        # Ask the user to select a license key
        opt = choice(
            [
                (key, "{u} ({k})".format(u=license.community_url, k=license.license_key))
                for key, license in enumerate(licenses)
            ],
            1,
            "Which license key would you like to use?",
        )
        license = licenses[opt]

        # Should we save this license?
        if click.confirm("Would you like to save and use this license for future requests?", True):
            ctx.log.debug("Saving license key {k}".format(k=license.license_key))
            ctx.config.set("User", "LicenseKey", license.license_key)
            with open(ctx.config_path, "wb") as configfile:
                ctx.config.write(configfile)

        return license

    # Get the latest IPS release
    lmeta = get_license()
    p = Echo("Fetching IPS version information...")
    ips = IpsManager(ctx, lmeta)
    p.done()
    if ips_version:
        if ips_version == "latest_dev":
            v = ips.dev_version
            if not v:
                click.secho("There is no IPS development release available for download", err=True, fg="red", bold=True)
                raise Exception("There is no IPS development release available for download")
            p = Echo("Downloading IPS development release {vs}...".format(vs=v.version.vstring))
        else:
            ips_version = Version(ips_version)
            v = ips.versions[ips_version.vtuple]
            p = Echo("Fetching IPS version {iv}".format(iv=ips_version.vstring))
    else:
        v = ips.latest
        p = Echo("Downloading IPS release {vs}...".format(vs=v.version.vstring))
    filename = ips.get(v, cache)
    p.done()

    # Parse the specific domain and make sure it's valid
    log.debug("Parsing domain name: %s", dname)
    dname = domain_parse(dname)
    if ssl is None:
        ssl = dname.scheme == "https"
    log.debug("Domain name parsed: %s", dname)

    domain = Domain.get_or_create(dname)

    # Make sure this site does not already exist
    p = Echo("Constructing site data...")
    site = ctx.db.query(Site).filter(Site.domain == domain).filter(collate(Site.name, "NOCASE") == name).count()
    if site:
        p.done(p.FAIL)
        log.error("Site already exists")
        click.secho(
            'An installation named "{s}" has already been created for the domain {d}'.format(s=name, d=dname.hostname),
            err=True,
            fg="red",
            bold=True,
        )
        raise click.Abort

    # Create the site database entry
    site = Site(
        name=name,
        domain=domain,
        license_key=lmeta.license_key,
        version=v.version.vstring,
        ssl=ssl,
        spdy=spdy,
        gzip=gzip,
        enabled=enable,
        in_dev=dev,
    )

    status = p.OK
    if os.path.exists(site.root):
        if not force:
            p.done(p.FAIL)
            click.secho(
                "Installation path already exists and --force was not passed:\n{p}".format(p=site.root),
                err=True,
                fg="red",
                bold=True,
            )
            log.info("Aborting installation, path already exists: {p}".format(p=site.root))
            raise click.Abort

        log.warn("Overwriting existing installation path: {p}".format(p=site.root))
        status = p.WARN

    ctx.db.add(site)
    ctx.db.commit()
    p.done(status)

    # Construct the HTTP path
    p = Echo("Constructing paths and configuration files...")
    site.write_nginx_config()
    p.done()

    # Generate SSL certificates if enabled
    if ssl:
        p = Echo("Generating SSL certificate...")
        ssl_path = os.path.join(ctx.config.get("Paths", "NginxSSL"), domain.name)
        if not os.path.exists(ssl_path):
            log.debug("Creating new SSL path: %s", ssl_path)
            os.makedirs(ssl_path, 0o755)

        sc = CertificateFactory(site).get()
        site.ssl_key = sc.key
        site.ssl_certificate = sc.certificate

        with open(os.path.join(ssl_path, "{s}.key".format(s=site.slug)), "w") as f:
            f.write(sc.key)
        with open(os.path.join(ssl_path, "{s}.pem").format(s=site.slug), "w") as f:
            f.write(sc.certificate)
        p.done()

    # Create a symlink if this site is being enabled
    if site.enabled:
        site.enable(force)

        # Restart Nginx
        p = Echo("Restarting web server...")
        FNULL = open(os.devnull, "w")
        subprocess.check_call(["service", "nginx", "restart"], stdout=FNULL, stderr=subprocess.STDOUT)
        p.done()

    # Extract IPS setup files
    p = Echo("Extracting setup files to tmp...")
    tmpdir = tempfile.mkdtemp("ips")
    setup_zip = os.path.join(tmpdir, "setup.zip")
    setup_dir = os.path.join(tmpdir, "setup")
    os.mkdir(setup_dir)

    log.info("Extracting setup files")
    shutil.copyfile(filename, setup_zip)
    with zipfile.ZipFile(setup_zip) as z:
        namelist = z.namelist()
        if re.match(r"^ips_\w{5}\/?$", namelist[0]):
            log.debug("Setup directory matched: %s", namelist[0])
        else:
            log.error("No setup directory matched, unable to continue")
            raise Exception("Unrecognized setup file format, aborting")

        z.extractall(setup_dir)
        log.debug("Setup files extracted to: %s", setup_dir)
        p.done()
        p = MarkerProgressBar("Copying setup files...")
        setup_tmpdir = os.path.join(setup_dir, namelist[0])
        for dirname, dirnames, filenames in p(os.walk(setup_tmpdir)):
            for filepath in dirnames:
                site_path = os.path.join(site.root, dirname.replace(setup_tmpdir, ""), filepath)
                if not os.path.exists(site_path):
                    log.debug("Creating directory: %s", site_path)
                    os.mkdir(site_path, 0o755)

            for filepath in filenames:
                tmp_path = os.path.join(dirname, filepath)
                site_path = os.path.join(site.root, dirname.replace(setup_tmpdir, ""), filepath)
                shutil.copy(tmp_path, site_path)

        log.info("Setup files copied to: %s", site.root)
    shutil.rmtree(tmpdir)

    # Apply proper permissions
    # p = MarkerProgressBar('Setting file permissions...')
    writeable_dirs = ["uploads", "plugins", "applications", "datastore"]

    for wdir in writeable_dirs:
        log.debug("Setting file permissions in %s", wdir)
        os.chmod(os.path.join(site.root, wdir), 0o777)
        p = MarkerProgressBar("Setting file permissions...", nl=False)
        for dirname, dirnames, filenames in p(os.walk(os.path.join(site.root, wdir))):
            for filename in filenames:
                os.chmod(os.path.join(dirname, filename), 0o666)

            for filename in dirnames:
                os.chmod(os.path.join(dirname, filename), 0o777)
    Echo("Setting file permissions...").done()

    shutil.move(os.path.join(site.root, "conf_global.dist.php"), os.path.join(site.root, "conf_global.php"))
    os.chmod(os.path.join(site.root, "conf_global.php"), 0o777)

    # Run the installation
    if install:
        p = Echo("Initializing installer...")
        i = installer(v.version, ctx, site, force)
        p.done()
        i.start()
    else:
        db_info = None
        if click.confirm("Would you like to create the database for this installation now?", default=True):
            db_info = create_database(site)

        click.echo("------")

        if db_info:
            db_name, db_user, db_pass = db_info

            log.debug("MySQL Database Name: %s", db_name)
            log.debug("MySQL Database User: %s", db_user)
            log.debug("MySQL Database Password: %s", db_pass)

            click.secho("MySQL Database Name: {dbn}".format(dbn=db_name), bold=True)
            click.secho("MySQL Database User: {dbu}".format(dbu=db_user), bold=True)
            click.secho("MySQL Database Password: {dbp}".format(dbp=db_pass), bold=True)

        click.secho(
            "IPS is now ready to be installed. To proceed with the installation, follow the link below",
            fg="yellow",
            bold=True,
        )
        click.echo("{schema}://{host}".format(schema="https" if site.ssl else "http", host=site.domain.name))
Example #7
0
def cli(ctx, name, dname, license_key, ips_version, force, enable, ssl, spdy,
        gzip, cache, install, dev):
    """
    Downloads and installs a new instance of the latest Invision Power Suite release.
    """
    assert isinstance(ctx, Context)
    login_session = ctx.get_login()
    log = logging.getLogger('ipsv.new')
    ctx.cache = cache

    # Prompt for our desired license
    def get_license():
        """
        Prompt the user for a license selection
        @rtype: ips_vagrant.scraper.licenses.LicenseMeta
        """
        licenses = Licenses(login_session).get()
        user_license = license_key or ctx.config.get('User', 'LicenseKey')

        # If we already have a license key saved, skip the prompt and use it instead
        if user_license:
            licenses = {license.license_key: license for license in licenses}
            if user_license in licenses:
                return licenses[user_license]

        # Ask the user to select a license key
        opt = choice([(key, '{u} ({k})'.format(u=license.community_url,
                                               k=license.license_key))
                      for key, license in enumerate(licenses)], 1,
                     'Which license key would you like to use?')
        license = licenses[opt]

        # Should we save this license?
        if click.confirm(
                'Would you like to save and use this license for future requests?',
                True):
            ctx.log.debug(
                'Saving license key {k}'.format(k=license.license_key))
            ctx.config.set('User', 'LicenseKey', license.license_key)
            with open(ctx.config_path, 'wb') as configfile:
                ctx.config.write(configfile)

        return license

    # Get the latest IPS release
    lmeta = get_license()
    p = Echo('Fetching IPS version information...')
    ips = IpsManager(ctx, lmeta)
    p.done()
    if ips_version:
        if ips_version == 'latest_dev':
            v = ips.dev_version
            if not v:
                click.secho(
                    'There is no IPS development release available for download',
                    err=True,
                    fg='red',
                    bold=True)
                raise Exception(
                    'There is no IPS development release available for download'
                )
            p = Echo('Downloading IPS development release {vs}...'.format(
                vs=v.version.vstring))
        else:
            ips_version = Version(ips_version)
            v = ips.versions[ips_version.vtuple]
            p = Echo(
                'Fetching IPS version {iv}'.format(iv=ips_version.vstring))
    else:
        v = ips.latest
        p = Echo(
            'Downloading IPS release {vs}...'.format(vs=v.version.vstring))
    filename = ips.get(v, cache)
    p.done()

    # Parse the specific domain and make sure it's valid
    log.debug('Parsing domain name: %s', dname)
    dname = domain_parse(dname)
    if ssl is None:
        ssl = dname.scheme == 'https'
    log.debug('Domain name parsed: %s', dname)

    domain = Domain.get_or_create(dname)

    # Make sure this site does not already exist
    p = Echo('Constructing site data...')
    site = ctx.db.query(Site).filter(Site.domain == domain).filter(
        collate(Site.name, 'NOCASE') == name).count()
    if site:
        p.done(p.FAIL)
        log.error('Site already exists')
        click.secho(
            'An installation named "{s}" has already been created for the domain {d}'
            .format(s=name, d=dname.hostname),
            err=True,
            fg='red',
            bold=True)
        raise click.Abort

    # Create the site database entry
    site = Site(name=name,
                domain=domain,
                license_key=lmeta.license_key,
                version=v.version.vstring,
                ssl=ssl,
                spdy=spdy,
                gzip=gzip,
                enabled=enable,
                in_dev=dev)

    status = p.OK
    if os.path.exists(site.root):
        if not force:
            p.done(p.FAIL)
            click.secho(
                "Installation path already exists and --force was not passed:\n{p}"
                .format(p=site.root),
                err=True,
                fg='red',
                bold=True)
            log.info('Aborting installation, path already exists: {p}'.format(
                p=site.root))
            raise click.Abort

        log.warn(
            'Overwriting existing installation path: {p}'.format(p=site.root))
        status = p.WARN

    ctx.db.add(site)
    ctx.db.commit()
    p.done(status)

    # Construct the HTTP path
    p = Echo('Constructing paths and configuration files...')
    site.write_nginx_config()
    p.done()

    # Generate SSL certificates if enabled
    if ssl:
        p = Echo('Generating SSL certificate...')
        ssl_path = os.path.join(ctx.config.get('Paths', 'NginxSSL'),
                                domain.name)
        if not os.path.exists(ssl_path):
            log.debug('Creating new SSL path: %s', ssl_path)
            os.makedirs(ssl_path, 0o755)

        sc = CertificateFactory(site).get()
        site.ssl_key = sc.key
        site.ssl_certificate = sc.certificate

        with open(os.path.join(ssl_path, '{s}.key'.format(s=site.slug)),
                  'w') as f:
            f.write(sc.key)
        with open(os.path.join(ssl_path, '{s}.pem').format(s=site.slug),
                  'w') as f:
            f.write(sc.certificate)
        p.done()

    # Create a symlink if this site is being enabled
    if site.enabled:
        site.enable(force)

        # Restart Nginx
        p = Echo('Restarting web server...')
        FNULL = open(os.devnull, 'w')
        subprocess.check_call(['service', 'nginx', 'restart'],
                              stdout=FNULL,
                              stderr=subprocess.STDOUT)
        p.done()

    # Extract IPS setup files
    p = Echo('Extracting setup files to tmp...')
    tmpdir = tempfile.mkdtemp('ips')
    setup_zip = os.path.join(tmpdir, 'setup.zip')
    setup_dir = os.path.join(tmpdir, 'setup')
    os.mkdir(setup_dir)

    log.info('Extracting setup files')
    shutil.copyfile(filename, setup_zip)
    with zipfile.ZipFile(setup_zip) as z:
        namelist = z.namelist()
        if re.match(r'^ips_\w{5}\/?$', namelist[0]):
            log.debug('Setup directory matched: %s', namelist[0])
        else:
            log.error('No setup directory matched, unable to continue')
            raise Exception('Unrecognized setup file format, aborting')

        z.extractall(setup_dir)
        log.debug('Setup files extracted to: %s', setup_dir)
        p.done()
        p = MarkerProgressBar('Copying setup files...')
        setup_tmpdir = os.path.join(setup_dir, namelist[0])
        for dirname, dirnames, filenames in p(os.walk(setup_tmpdir)):
            for filepath in dirnames:
                site_path = os.path.join(site.root,
                                         dirname.replace(setup_tmpdir, ''),
                                         filepath)
                if not os.path.exists(site_path):
                    log.debug('Creating directory: %s', site_path)
                    os.mkdir(site_path, 0o755)

            for filepath in filenames:
                tmp_path = os.path.join(dirname, filepath)
                site_path = os.path.join(site.root,
                                         dirname.replace(setup_tmpdir, ''),
                                         filepath)
                shutil.copy(tmp_path, site_path)

        log.info('Setup files copied to: %s', site.root)
    shutil.rmtree(tmpdir)

    # Apply proper permissions
    # p = MarkerProgressBar('Setting file permissions...')
    writeable_dirs = ['uploads', 'plugins', 'applications', 'datastore']

    for wdir in writeable_dirs:
        log.debug('Setting file permissions in %s', wdir)
        os.chmod(os.path.join(site.root, wdir), 0o777)
        p = MarkerProgressBar('Setting file permissions...', nl=False)
        for dirname, dirnames, filenames in p(
                os.walk(os.path.join(site.root, wdir))):
            for filename in filenames:
                os.chmod(os.path.join(dirname, filename), 0o666)

            for filename in dirnames:
                os.chmod(os.path.join(dirname, filename), 0o777)
    Echo('Setting file permissions...').done()

    shutil.move(os.path.join(site.root, 'conf_global.dist.php'),
                os.path.join(site.root, 'conf_global.php'))
    os.chmod(os.path.join(site.root, 'conf_global.php'), 0o777)

    # Run the installation
    if install:
        p = Echo('Initializing installer...')
        i = installer(v.version, ctx, site, force)
        p.done()
        i.start()
    else:
        db_info = None
        if click.confirm(
                'Would you like to create the database for this installation now?',
                default=True):
            db_info = create_database(site)

        click.echo('------')

        if db_info:
            db_name, db_user, db_pass = db_info

            log.debug('MySQL Database Name: %s', db_name)
            log.debug('MySQL Database User: %s', db_user)
            log.debug('MySQL Database Password: %s', db_pass)

            click.secho('MySQL Database Name: {dbn}'.format(dbn=db_name),
                        bold=True)
            click.secho('MySQL Database User: {dbu}'.format(dbu=db_user),
                        bold=True)
            click.secho('MySQL Database Password: {dbp}'.format(dbp=db_pass),
                        bold=True)

        click.secho(
            'IPS is now ready to be installed. To proceed with the installation, follow the link below',
            fg='yellow',
            bold=True)
        click.echo('{schema}://{host}'.format(
            schema='https' if site.ssl else 'http', host=site.domain.name))
Example #8
0
def cli(ctx, name, dname, license_key, ips_version, force, enable, ssl, spdy, gzip, cache, install, dev):
    """
    Downloads and installs a new instance of the latest Invision Power Suite release.
    """
    assert isinstance(ctx, Context)
    login_session = ctx.get_login()
    log = logging.getLogger('ipsv.new')
    ctx.cache = cache

    # Prompt for our desired license
    def get_license():
        """
        Prompt the user for a license selection
        @rtype: ips_vagrant.scraper.licenses.LicenseMeta
        """
        licenses = Licenses(login_session).get()
        user_license = license_key or ctx.config.get('User', 'LicenseKey')

        # If we already have a license key saved, skip the prompt and use it instead
        if user_license:
            licenses = {license.license_key: license for license in licenses}
            if user_license in licenses:
                return licenses[user_license]

        # Ask the user to select a license key
        opt = choice([
            (key, '{u} ({k})'.format(u=license.community_url, k=license.license_key))
            for key, license in enumerate(licenses)
        ], 1, 'Which license key would you like to use?')
        license = licenses[opt]

        # Should we save this license?
        if click.confirm('Would you like to save and use this license for future requests?', True):
            ctx.log.debug('Saving license key {k}'.format(k=license.license_key))
            ctx.config.set('User', 'LicenseKey', license.license_key)
            with open(ctx.config_path, 'wb') as configfile:
                ctx.config.write(configfile)

        return license

    # Get the latest IPS release
    lmeta = get_license()
    p = Echo('Fetching IPS version information...')
    ips = IpsManager(ctx, lmeta)
    p.done()
    if ips_version:
        if ips_version == 'latest_dev':
            v = ips.dev_version
            if not v:
                click.secho('There is no IPS development release available for download', err=True, fg='red', bold=True)
                raise Exception('There is no IPS development release available for download')
            p = Echo('Downloading IPS development release {vs}...'.format(vs=v.version.vstring))
        else:
            ips_version = Version(ips_version)
            v = ips.versions[ips_version.vtuple]
            p = Echo('Fetching IPS version {iv}'.format(iv=ips_version.vstring))
    else:
        v = ips.latest
        p = Echo('Downloading IPS release {vs}...'.format(vs=v.version.vstring))
    filename = ips.get(v, cache)
    p.done()

    # Parse the specific domain and make sure it's valid
    log.debug('Parsing domain name: %s', dname)
    dname = domain_parse(dname)
    if ssl is None:
        ssl = dname.scheme == 'https'
    log.debug('Domain name parsed: %s', dname)

    domain = Domain.get_or_create(dname)

    # Make sure this site does not already exist
    p = Echo('Constructing site data...')
    site = ctx.db.query(Site).filter(Site.domain == domain).filter(collate(Site.name, 'NOCASE') == name).count()
    if site:
        p.done(p.FAIL)
        log.error('Site already exists')
        click.secho('An installation named "{s}" has already been created for the domain {d}'
                    .format(s=name, d=dname.hostname),
                    err=True, fg='red', bold=True)
        raise click.Abort

    # Create the site database entry
    site = Site(name=name, domain=domain, license_key=lmeta.license_key, version=v.version.vstring, ssl=ssl, spdy=spdy,
                gzip=gzip, enabled=enable, in_dev=dev)

    status = p.OK
    if os.path.exists(site.root):
        if not force:
            p.done(p.FAIL)
            click.secho("Installation path already exists and --force was not passed:\n{p}".format(p=site.root),
                        err=True, fg='red', bold=True)
            log.info('Aborting installation, path already exists: {p}'.format(p=site.root))
            raise click.Abort

        log.warn('Overwriting existing installation path: {p}'.format(p=site.root))
        status = p.WARN

    ctx.db.add(site)
    ctx.db.commit()
    p.done(status)

    # Construct the HTTP path
    p = Echo('Constructing paths and configuration files...')
    site.write_nginx_config()
    p.done()

    # Generate SSL certificates if enabled
    if ssl:
        p = Echo('Generating SSL certificate...')
        ssl_path = os.path.join(ctx.config.get('Paths', 'NginxSSL'), domain.name)
        if not os.path.exists(ssl_path):
            log.debug('Creating new SSL path: %s', ssl_path)
            os.makedirs(ssl_path, 0o755)

        sc = CertificateFactory(site).get()
        site.ssl_key = sc.key
        site.ssl_certificate = sc.certificate

        with open(os.path.join(ssl_path, '{s}.key'.format(s=site.slug)), 'w') as f:
            f.write(sc.key)
        with open(os.path.join(ssl_path, '{s}.pem').format(s=site.slug), 'w') as f:
            f.write(sc.certificate)
        p.done()

    # Create a symlink if this site is being enabled
    if site.enabled:
        site.enable(force)

        # Restart Nginx
        p = Echo('Restarting web server...')
        FNULL = open(os.devnull, 'w')
        subprocess.check_call(['service', 'nginx', 'restart'], stdout=FNULL, stderr=subprocess.STDOUT)
        p.done()

    # Extract IPS setup files
    p = Echo('Extracting setup files to tmp...')
    tmpdir = tempfile.mkdtemp('ips')
    setup_zip = os.path.join(tmpdir, 'setup.zip')
    setup_dir = os.path.join(tmpdir, 'setup')
    os.mkdir(setup_dir)

    log.info('Extracting setup files')
    shutil.copyfile(filename, setup_zip)
    with zipfile.ZipFile(setup_zip) as z:
        namelist = z.namelist()
        if re.match(r'^ips_\w{5}\/?$', namelist[0]):
            log.debug('Setup directory matched: %s', namelist[0])
        else:
            log.error('No setup directory matched, unable to continue')
            raise Exception('Unrecognized setup file format, aborting')

        z.extractall(setup_dir)
        log.debug('Setup files extracted to: %s', setup_dir)
        p.done()
        p = MarkerProgressBar('Copying setup files...')
        setup_tmpdir = os.path.join(setup_dir, namelist[0])
        for dirname, dirnames, filenames in p(os.walk(setup_tmpdir)):
            for filepath in dirnames:
                site_path = os.path.join(site.root, dirname.replace(setup_tmpdir, ''), filepath)
                if not os.path.exists(site_path):
                    log.debug('Creating directory: %s', site_path)
                    os.mkdir(site_path, 0o755)

            for filepath in filenames:
                tmp_path = os.path.join(dirname, filepath)
                site_path = os.path.join(site.root, dirname.replace(setup_tmpdir, ''), filepath)
                shutil.copy(tmp_path, site_path)

        log.info('Setup files copied to: %s', site.root)
    shutil.rmtree(tmpdir)

    # Apply proper permissions
    # p = MarkerProgressBar('Setting file permissions...')
    writeable_dirs = ['uploads', 'plugins', 'applications', 'datastore']
    
    for wdir in writeable_dirs:
        log.debug('Setting file permissions in %s', wdir)
        os.chmod(os.path.join(site.root, wdir), 0o777)
        p = MarkerProgressBar('Setting file permissions...', nl=False)
        for dirname, dirnames, filenames in p(os.walk(os.path.join(site.root, wdir))):
            for filename in filenames:
                os.chmod(os.path.join(dirname, filename), 0o666)

            for filename in dirnames:
                os.chmod(os.path.join(dirname, filename), 0o777)
    Echo('Setting file permissions...').done()

    shutil.move(os.path.join(site.root, 'conf_global.dist.php'), os.path.join(site.root, 'conf_global.php'))
    os.chmod(os.path.join(site.root, 'conf_global.php'), 0o777)

    # Run the installation
    if install:
        p = Echo('Initializing installer...')
        i = installer(v.version, ctx, site, force)
        p.done()
        i.start()
    else:
        click.echo('------')
        click.secho('IPS is now ready to be installed. To proceed with the installation, follow the link below',
                    fg='yellow', bold=True)
        click.echo('{schema}://{host}'.format(schema='https' if site.ssl else 'http', host=site.domain.name))
Example #9
0
def cli(ctx, dname, site):
    """
    List all domains if no <domain> is provided. If <domain> is provided but <site> is not, lists all sites
    hosted under <domain>. If both <domain> and <site> are provided, lists information on the specified site.
    """
    assert isinstance(ctx, Context)

    if dname:
        dname = domain_parse(dname).hostname
        domain = Session.query(Domain).filter(Domain.name == dname).first()

        # No such domain
        if not domain:
            click.secho('No such domain: {dn}'.format(dn=dname), fg='red', bold=True, err=True)
            return

    if site:
        site_name = site
        site = Site.get(domain, site)
        if not site:
            click.secho('No such site: {site}'.format(site=site_name), fg='red', bold=True, err=True)
            return

        click.secho('Name: {n}'.format(n=site.name), bold=True)
        click.secho('Domain: {dn}'.format(dn=site.domain.name), bold=True)
        click.secho('Version: {v}'.format(v=site.version), bold=True)
        click.secho('License Key: {lk}'.format(lk=site.license_key), bold=True)
        click.secho('Status: {s}'.format(s=styled_status(site.enabled)), bold=True)
        click.secho('IN_DEV: {id}'.format(id=styled_status(site.in_dev)), bold=True)
        click.secho('SSL: {s}'.format(s=styled_status(site.ssl)), bold=True)
        click.secho('SPDY: {s}'.format(s=styled_status(site.spdy)), bold=True)
        click.secho('GZIP: {g}'.format(g=styled_status(site.gzip)), bold=True)
        click.secho('MySQL Database: {db}'.format(db=site.db_name), bold=True)
        click.secho('MySQL User: {u}'.format(u=site.db_user), bold=True)
        click.secho('MySQL Password: {u}'.format(u=site.db_pass), bold=True)
        return

    # Print sites
    if dname:
        # Get sites
        sites = Site.all(domain)
        if not sites:
            click.secho('No sites active under domain: {dn}'.format(dn=dname), fg='red', bold=True, err=True)
            return

        # Display site data
        for site in sites:
            prefix = '[DEV] ' if site.in_dev else ''
            fg = 'green' if site.enabled else 'white'
            click.secho('{pre}{name} ({ver})'.format(pre=prefix, name=site.name, ver=site.version), fg=fg, bold=True)

        return

    # Print domains
    domains = Domain.all()
    for domain in domains:
        # Extra domains
        extras = ''
        if domain.extras:
            extras = ' ({dnames})'.format(dnames=str(domain.extras).replace(',', ', '))

        click.secho('{dname}{extras}'.format(dname=domain.name, extras=extras), bold=True)