Exemplo n.º 1
0
    def __init__(self, cli_args, config_dir):
        """
        Run the action.
        """

        self._args = cli_args

        self._config_dir = config_dir
        self._config     = ConfigurationFactory.get('hypernova')
        self._servers    = ConfigurationFactory.get('hypernova.servers')
Exemplo n.º 2
0
    def do_rm_record(params):
        """
        Remove a record.
        """

        config = ConfigurationFactory.get('hypernova')
        server = get_authoritative_server(config['dns']['adapter'],
                                          config['dns'])

        result = {'records': []}

        try:
            zone = server.get_zone(params['zone'])
            params['rtype'] = params['record'].pop('type')

            records = zone.filter_records_for(params['record'])
            for r in records:
                result['records'].append(r.to_encodable())
                server.rm_record(zone, r)

            successful = True

            if len(result['records']) == 0:
                successful = False
                result['error'] = 'NoMatchingRecords'

        except NonexistentZoneError:
            successful = False
            result = {'error': 'NonexistentZoneError'}

        return AgentRequestHandler._format_response(
            result,
            successful=successful
        )
Exemplo n.º 3
0
    def do_add_record(params):
        """
        Add a record to an existing zone.
        """

        config = ConfigurationFactory.get('hypernova')
        server = get_authoritative_server(config['dns']['adapter'],
                                          config['dns'])

        try:
            zone = server.get_zone(params['zone'])
            record = Record(params['record']['name'],
                            params['record']['type'],
                            params['record']['content'],
                            params['record']['ttl'],
                            params['record']['priority'])
            server.add_record(zone, record)

            successful = True
            result = {'record': record.to_encodable()}
        except NonexistentZoneError:
            successful = False
            result = {'error': 'NonexistentZone'}

        return AgentRequestHandler._format_response(
            result,
            successful=successful
        )
Exemplo n.º 4
0
    def do_get_zone(params):
        """
        Get a zone.
        """

        config = ConfigurationFactory.get('hypernova')

        try:
            server = get_authoritative_server(config['dns']['adapter'],
                                              config['dns'])

            try:
                successful = True
                result     = {
                    'zone': server.get_zone(params['domain']).to_encodable(),
                }
            except NonexistentZoneError:
                successful = False
                result     = {'error': 'NonexistentZone'}
        except ServerCommunicationError:
            successful = False
            result     = {'error': 'ServerCommunication'}

        return AgentRequestHandler._format_response(
            result,
            successful=successful,
            error_code=0
        )
Exemplo n.º 5
0
def elevate_cmd(cmd):
    """
    Return an elevated command, ready for execution.

    When cmd is a list, we prepend the options necessary for the command to run
    as the system's root/administrative user as seperate, self-contained
    arguments. When it's a string, we prepend to the string the space-delimited
    parameters.

    If the object is of any other type, a TypeError will be thrown.
    """

    try:
        config = ConfigurationFactory.get('hypernova')['elevation']
        if config['method'] == 'elevator':
            prefix = [config['binary']]
    except KeyError:
        prefix = None
    finally:
        if not prefix:
            return cmd

    if isinstance(cmd, list):
        prefix.extend(cmd)
        cmd = prefix
    elif isinstance(cmd, str):
        cmd = '%s %s' %(' '.join(prefix), cmd)
    else:
        raise TypeError('list or str expected')

    return cmd
Exemplo n.º 6
0
    def _init_config(self):
        """
        Load the client's configuration.
        """

        self._config_file  = os.path.join(self._config_dir, 'client.ini')
        self._servers_file = os.path.join(self._config_dir, 'servers.ini')

        try:
            os.listdir(self._config_dir)
        except (LoadError, OSError):
            print('Creating configuration in %s' %(self._config_dir), file=sys.stderr)
            self._init_config_runonce(self._config_dir)
        finally:
            self._config = ConfigurationFactory.get('hypernova',
                                                    root_dir=self._config_file)
            self._servers = ConfigurationFactory.get('hypernova.servers',
                                                     root_dir=self._servers_file)
Exemplo n.º 7
0
    def _init_config(self, config_root_dir):
        """
        Initialise configuration values.

        See __init__() for more information.
        """

        self._main_log.info('loading configuration from directory %s'
                            %(config_root_dir))
        self._config = ConfigurationFactory.get('hypernova', config_root_dir,
                                                self._main_log)

        if not self._config:
            self._main_log.critical('loading configuration failed')
            sys.exit(78)
Exemplo n.º 8
0
    def __init__(self, **args):
        """
        Initialise the provisioner.
        """

        self.parameters = args

        config = ConfigurationFactory.get('hypernova')

        # This will only be possible when in the context of the agent, so if we
        # fail, it's not an issue. This ought to be cleaned up.
        try:
            self._base_cmd.append(config['provisioner']['config_dir'])
        except KeyError:
            pass
Exemplo n.º 9
0
def get_package_db(pdb_name=None):
    """
    Get the system's associated package DB.
    """

    prof_dir = ConfigurationFactory.get('hypernova')['platforms']['profile_dir']
    pdb_fmt = os.path.join(prof_dir, '%s', 'packages.json')

    if not pdb_name:
        os_info = platform.dist()

        if os_info[0].lower() in ('centos', 'fedora'):
            pdb_name = 'rhel-6'

    return PackageDB(pdb_fmt %(pdb_name))
Exemplo n.º 10
0
    def __init__(self, *args):
        """
        Initialise the provisioner.
        """

        self.parameters = args
        self.config     = ConfigurationFactory.get('hypernova')
        self.env        = deepcopy(environ)

        # Attempt to guess the provsioner's configuration directory; we can only
        # do this if it's set in the agent's configuration
        try:
            self.env['CONFDIR'] = self.config['provisioner']['config_dir']
        except KeyError:
            pass
Exemplo n.º 11
0
    def do_add_zone(params):
        """
        Add a zone.
        """

        config = ConfigurationFactory.get('hypernova')

        try:
            result = {'error': 'ValidationError'}

            server = get_authoritative_server(config['dns']['adapter'],
                                              config['dns'])
            zone = Zone(new_domain=params['zone']['domain'],
                        new_origin=params['zone']['origin'],
                        new_ttl=params['zone']['ttl'])
            zone.soa_record = SoaRecord(new_primary_ns=params['soa']['primary_ns'],
                                        new_responsible_person=params['soa']['responsible_person'],
                                        new_serial=params['soa']['serial'],
                                        new_refresh=params['soa']['refresh'],
                                        new_retry=params['soa']['retry'],
                                        new_expire=params['soa']['expire'],
                                        new_min_ttl=params['soa']['min_ttl'])

            try:
                server.add_zone(zone)
                successful = True
                result = {'zone': zone.to_encodable()}
            except DuplicateZoneError:
                successful = False
                result = {'error': 'DuplicateZone'}

        except ServerCommunicationError:
            successful = False
            result = {'error': 'ServerCommunicationError'}

        return AgentRequestHandler._format_response(
            result,
            successful=successful,
            error_code=0
        )
Exemplo n.º 12
0
    def setUp(self):
        """
        Construct environment.

        Here, we adopt the configuration used by the production or development
        installation and make the necessary changes before writing it to a new
        file in the etc directory. When we're finished, we'll remove it in the
        tearDown() function.
        """

        if not os.path.exists(self.client_env['CONFDIR']):

            # Don't waste time and entropy on keys if we can't write configuration
            # files -- that's a very distressing experience.
            assert len(sys.argv) == 2

            # Prepare two GPG keypairs; one for the agent, one for the client
            agent_gpg_dir  = os.path.join(self.client_env['CONFDIR'], 'agent_gpg')
            agent_gpg      = GPG(gnupghome=agent_gpg_dir)
            agent_key      = agent_gpg.gen_key(agent_gpg.gen_key_input(**self.gpg_params))
            client_gpg_dir = os.path.join(self.client_env['CONFDIR'], 'client_gpg')
            client_gpg     = GPG(gnupghome=client_gpg_dir)
            client_key     = client_gpg.gen_key(client_gpg.gen_key_input(**self.gpg_params))

            # Export both public keys; import them into the opposing side
            agent_key_blob  = agent_gpg.export_keys(agent_key.fingerprint)
            client_gpg.import_keys(agent_key_blob)
            client_gpg.sign_key(agent_key.fingerprint)
            client_key_blob = client_gpg.export_keys(client_key.fingerprint)
            agent_gpg.import_keys(client_key_blob)
            agent_gpg.sign_key(client_key.fingerprint)

            # Configure the agent to run in a development-safe configuration.
            #
            # Here, we load the base configuration we ship with the application
            # as the default. All other configuration will be ignored for the
            # purposes of the test run, since this is outside of our scope.
            with open(self.agent_env['CONFDIR'], 'w') as f:
                l = os.path.join(self.client_env['CONFDIR'], 'agent_%s.log')
                agent_cfg = ConfigurationFactory.get('hypernova.agent',
                                                     root_dir=sys.argv[1])
                agent_cfg.set('server',  'address',     self.agent_addr[0])
                agent_cfg.set('server',  'port',        self.agent_addr[1])
                agent_cfg.set('server',  'daemon',      'false')
                agent_cfg.set('gpg',     'key_store',   agent_gpg_dir)
                agent_cfg.set('gpg',     'fingerprint', agent_key.fingerprint)
                agent_cfg.set('logging', 'main_log',    l %('main'))
                agent_cfg.set('logging', 'request_log', l %('request'))
                agent_cfg.set('logging', 'error_log',   l %('error'))
                agent_cfg.write(f)

            # The client has to use two different configuration files, both in
            # the same directory.
            client_cfg_dir = self.client_env['CONFDIR']

            # Configure the client to use its temporary key.
            #
            # To communicate with the agent (which will be running in a limited
            # testing mode), we'll need to reconfigure the client with a keypair
            # we've imported into the agent. This keystore manipulation has
            # already taken place, so we know the fingerprint of our new private
            # key.
            client_cfg_file = os.path.join(client_cfg_dir, 'client.ini')
            with open(client_cfg_file, 'w') as f:
                client_cfg      = configparser.SafeConfigParser()
                client_cfg.add_section('client')
                client_cfg.set('client', 'privkey', client_key.fingerprint)
                client_cfg.write(f)

            # Pair the client to the agent.
            #
            # We do this manually, since the importer requires that we write the
            # public key to a file before we import it. This would be a
            # pointless exercise and an unnecessary complication.
            client_srv_file = os.path.join(client_cfg_dir, 'servers.ini')
            with open(client_srv_file, 'w') as f:
                client_srv_cfg  = configparser.SafeConfigParser()
                client_srv_cfg.add_section('local')
                client_srv_cfg.set('local', 'addr', ':'.join(self.agent_addr))
                client_srv_cfg.set('local', 'pubkey', agent_key.fingerprint)
                client_srv_cfg.write(f)

        # TODO: instead of lazily and unreliably falling asleep on the job,
        #       we should probably use a regular expression to check the output.
        #       Time is of the essence, though!
        #       No, we'll use pexpect instead, since it's now shipped as a py3k
        #       dependency.
        agent_cmd = [
            'hn-agent',
            self.agent_env['CONFDIR']
        ]
        self.agent_proc = subprocess.Popen(agent_cmd, env=self.agent_env,
                                           stdin=subprocess.PIPE,
                                           stdout=subprocess.PIPE,
                                           stderr=subprocess.PIPE)
        time.sleep(self.agent_init_time)