Example #1
0
    def render_config(self, *args):
        """
        Render Kerberos configuration file and Apache configuration to be used
        by Keystone.
        """
        # ensure that a directory we need is there
        ch_host.mkdir(APACHE_LOCATION)

        self.render_configs(self.string_templates.keys())

        core.templating.render(
            source=APACHE_CONF_TEMPLATE,
            template_loader=os_templating.get_loader(
                'templates/', self.release),
            target='{}/{}'.format(APACHE_LOCATION, APACHE_CONF_TEMPLATE),
            context=self.adapters_class(args, charm_instance=self),
        )

        core.templating.render(
            source=KERBEROS_CONF_TEMPLATE,
            template_loader=os_templating.get_loader(
                'templates/', self.release),
            target="/etc/krb5.conf",
            context=self.adapters_class(args, charm_instance=self),
        )
Example #2
0
    def install(self):
        """Custom install function.

        :param self: Self
        :type self: MySQLRouterCharm instance
        :side effect: Executes other functions
        :returns: This function is called for its side effect
        :rtype: None
        """
        # TODO: charms.openstack should probably do this
        # Need to configure source first
        self.configure_source()
        super().install()

        # Neither MySQL Router nor MySQL common packaging creates a user, group
        # or home dir. As we want it to run as a system user in a predictable
        # location create all of these.
        # Create the group
        if not ch_core.host.group_exists(self.mysqlrouter_group):
            ch_core.host.add_group(
                self.mysqlrouter_group, system_group=True)
        # Create the user
        if not ch_core.host.user_exists(self.mysqlrouter_user):
            ch_core.host.adduser(
                self.mysqlrouter_user, shell="/usr/sbin/nologin",
                system_user=True, primary_group=self.mysqlrouter_group,
                home_dir=self.mysqlrouter_home_dir)
        # Create the directory
        if not os.path.exists(self.mysqlrouter_home_dir):
            ch_core.host.mkdir(
                self.mysqlrouter_home_dir,
                owner=self.mysqlrouter_user,
                group=self.mysqlrouter_group,
                perms=0o755)

        # Systemd File
        ch_core.templating.render(
            source="mysqlrouter.service",
            template_loader=os_templating.get_loader(
                'templates/', self.release),
            target=self.systemd_file,
            context=self.adapters_instance,
            group=self.group,
            perms=0o755,
        )
        cmd = ["systemctl", "enable", self.name]
        subprocess.check_output(cmd, stderr=subprocess.STDOUT)

        # Logrotate File
        ch_core.templating.render(
            source="logrotate",
            template_loader=os_templating.get_loader(
                "templates/", self.release),
            target=self.logrotate_file,
            context={
                "owner": self.mysqlrouter_user,
                "group": self.mysqlrouter_group
            },
            perms=0o644,
        )
Example #3
0
def manage():
    config = hookenv.config()
    release = os_release('neutron-common')
    manager = ServiceManager([
        # Actions which have no prerequisites and can be rerun
        {
            'service': 'odl-setup',
            'data_ready': [
                odl_utils.install_packages,
            ],
            'provided_data': [
                odl_data.NeutronApiSDNRelation(),
            ],
        },
        {
            'service': 'api-render',
            'required_data': [
                odl_data.ODLControllerRelation(),
                config,
                odl_data.ConfigTranslation(),
            ],
            'data_ready': [
                helpers.render_template(
                    source='ml2_conf.ini',
                    template_loader=get_loader('templates/', release),
                    target='/etc/neutron/plugins/ml2/ml2_conf.ini',
                    on_change_action=(partial(remote_restart,
                                              'neutron-plugin-api-subordinate',
                                              'neutron-server')),
                ),
            ]
        },
    ])
    manager.manage()
    def render_config(self, restart_trigger):
        """Render the domain specific LDAP configuration for the application
        """
        checksum = ch_host.file_hash(self.configuration_file)
        core.templating.render(source=KEYSTONE_CONF_TEMPLATE,
                               template_loader=os_templating.get_loader(
                                   'templates/', self.release),
                               target=self.configuration_file,
                               context=self.adapters_instance)

        tmpl_changed = (checksum != ch_host.file_hash(self.configuration_file))

        cert = hookenv.config('tls-ca-ldap')

        cert_changed = False
        if cert:
            ca_file = self.options.backend_ca_file
            old_cert_csum = ch_host.file_hash(ca_file)
            ch_host.write_file(ca_file,
                               cert,
                               owner='root',
                               group='root',
                               perms=0o644)
            cert_csum = ch_host.file_hash(ca_file)
            cert_changed = (old_cert_csum != cert_csum)

        if tmpl_changed or cert_changed:
            restart_trigger()
Example #5
0
def manage():
    config = hookenv.config()
    release = os_release('neutron-common')
    manager = ServiceManager([
        # onos services setup
        {
            'service': 'onos-setup',
            'data_ready': [
                onos_package.install_packages,
            ],
            'provided_data': [
                onos_relation.BuildSDNRelation(),
            ],
        },
        {
            'service':
            'api-render',
            'required_data': [
                onos_relation.ONOSControllerRelation(),
                config,
                onos_relation.ConfigTranslation(),
            ],
            'data_ready': [
                helpers.render_template(
                    source='ml2_conf.ini',
                    template_loader=get_loader('templates/', release),
                    target='/etc/neutron/plugins/ml2/ml2_conf.ini',
                    on_change_action=(partial(
                        remote_restart, 'neutron-plugin-api-subordinate',
                        'neutron-server')),
                ),
            ],
        },
    ])
    manager.manage()
def manage():
    config = hookenv.config()
    release = os_release('neutron-common')
    manager = ServiceManager([
        # onos services setup
        {
            'service': 'onos-setup',
            'data_ready': [
                onos_package.install_packages,
            ],
            'provided_data': [
                onos_relation.BuildSDNRelation(),
            ],
        },
        {
            'service': 'api-render',
            'required_data': [
                onos_relation.ONOSControllerRelation(),
                config,
                onos_relation.ConfigTranslation(),
            ],
            'data_ready': [
                helpers.render_template(
                    source='ml2_conf.ini',
                    template_loader=get_loader('templates/', release),
                    target='/etc/neutron/plugins/ml2/ml2_conf.ini',
                    on_change_action=(partial(remote_restart,
                                              'neutron-plugin-api-subordinate',
                                              'neutron-server')),
                ),
            ],
        },
    ])
    manager.manage()
Example #7
0
 def render_configs(self, configs):
     with self.restart_on_change():
         for conf in configs:
             render(source=os.path.basename(conf),
                    template_loader=get_loader('templates/', self.release),
                    target=conf,
                    context=self.adapter_instance)
Example #8
0
    def render_config(self, *args):
        """
        Render Service Provider configuration file to be used by Apache
        and provided to idP out of band to establish mutual trust.
        """
        owner = 'root'
        group = 'www-data'
        # group read and exec is needed for mellon to read the rendered
        # files, otherwise it will fail in a cryptic way
        dperms = 0o650
        # file permissions are a bit more restrictive than defaults in
        # charm-helpers but directory permissions are the main protection
        # mechanism in this case
        fileperms = 0o440
        # ensure that a directory we need is there
        ch_host.mkdir('/etc/apache2/mellon',
                      perms=dperms,
                      owner=owner,
                      group=group)

        self.render_configs(self.string_templates.keys())

        # For now the template name does not match
        # basename(file_path/file_name). This is necessary to enable multiple
        # instantiations of keystone-saml-mellon using service_name() in the
        # file names. So not using self.render_with_interfaces(args)
        # TODO: Make a mapping mechanism between target and source templates
        # in charms.openstack
        core.templating.render(
            source='mellon-sp-metadata.xml',
            template_loader=os_templating.get_loader('templates/',
                                                     self.release),
            target=self.options.sp_metadata_file,
            context=self.adapters_class(args, charm_instance=self),
            owner=owner,
            group=group,
            perms=fileperms)

        core.templating.render(
            source='apache-mellon-location.conf',
            template_loader=os_templating.get_loader('templates/',
                                                     self.release),
            target=self.options.sp_location_config,
            context=self.adapters_class(args, charm_instance=self),
            owner=owner,
            group=group,
            perms=fileperms)
    def get_template_for_release_and_server(self, os_release, server,
                                            mock_log):

        if not server:
            server = 'object'

        loader = get_loader('./templates', os_release)
        env = Environment(loader=loader)

        return env.get_template('{}-server.conf'.format(server))
 def render_config(self, restart_trigger):
     """Render the domain specific LDAP configuration for the application
     """
     checksum = ch_host.path_hash(self.configuration_file)
     core.templating.render(source=KEYSTONE_CONF_TEMPLATE,
                            template_loader=os_templating.get_loader(
                                'templates/', self.release),
                            target=self.configuration_file,
                            context=self.adapters_instance)
     if checksum != ch_host.path_hash(self.configuration_file):
         restart_trigger()
    def render_config(self, *args):
        """
        Render Service Provider configuration file to be used by Apache
        and provided to idP out of band to establish mutual trust.
        """
        owner = 'root'
        group = 'www-data'
        # group read and exec is needed for mellon to read the rendered
        # files, otherwise it will fail in a cryptic way
        dperms = 0o650
        # file permissions are a bit more restrictive than defaults in
        # charm-helpers but directory permissions are the main protection
        # mechanism in this case
        fileperms = 0o440
        # ensure that a directory we need is there
        ch_host.mkdir('/etc/apache2/mellon',
                      perms=dperms,
                      owner=owner,
                      group=group)

        core.templating.render(
            source='apache-oidc-location.conf',
            template_loader=os_templating.get_loader('templates/',
                                                     self.release),
            target=self.options.oidc_location_config,
            context=self.adapters_class(args, charm_instance=self),
            owner=owner,
            group=group,
            perms=fileperms)

        core.templating.render(
            source='oidc.conf',
            template_loader=os_templating.get_loader('templates/',
                                                     self.release),
            target=self.options.oidc_conf,
            context=self.adapters_class(args, charm_instance=self),
            owner=owner,
            group=group,
            perms=fileperms)
    def test_get_loader_some_search_paths(self, isdir):
        '''Ensure loader reverse searches of some release template dirs'''
        isdir.return_value = True
        choice_loader = templating.get_loader('/tmp/foo', os_release='grizzly')
        dirs = [l.searchpath for l in choice_loader.loaders]

        common_tmplts = os.path.join(os.path.dirname(templating.__file__),
                                     'templates')

        expected = [['/tmp/foo/grizzly'], ['/tmp/foo/folsom'],
                    ['/tmp/foo/essex'], ['/tmp/foo/diablo'], ['/tmp/foo'],
                    [common_tmplts]]
        self.assertEquals(dirs, expected)
    def get_template_for_release_and_server(
            self,
            os_release,
            server,
            mock_log):

        if not server:
            server = 'object'

        loader = get_loader('./templates', os_release)
        env = Environment(loader=loader)

        return env.get_template('{}-server.conf'.format(server))
    def get_config_for_principal(self, auth_data):
        """Assuming that the configuration data is valid, return the
        configuration data for the principal charm.

        The format of the complete returned data is:
        {
            "<config file>: <string>
        }

        If the configuration is not complete, or we don't have auth data from
        the principal charm, then we return and emtpy dictionary {}

        :param auth_data: the raw dictionary received from the principal charm
        :returns: structure described above.
        """
        # If there is no auth_data yet, then we can't write our config.
        if not auth_data:
            return {}
        # If the state from the assess_status is not None then we're blocked,
        # so don't send any config to the principal.
        state, message = self.custom_assess_status_check()
        if state:
            return {}
        options = self.options  # tiny optimisation for less typing.

        # If there is no backend name, then we can't send the data yet as the
        # manila-charm won't know what to do with it.
        if not options.share_backend_name:
            return {}

        # We have the auth data & the config is reasonably sensible.
        # We can try and render the config file segment.
        # TODO this is horrible, and we should have something in
        # charms.openstack to do this, but we need a c.r relation to be able to
        # add it to the adapters_instance
        manila_plugin = relations.endpoint_from_flag('manila-plugin.available')
        self.adapters_instance.add_relation(manila_plugin)
        rendered_configs = charmhelpers.core.templating.render(
            source=os.path.basename(MANILA_CONF),
            template_loader=os_templating.get_loader(
                'templates/', self.release),
            target=None,
            context=self.adapters_instance)

        return {
            MANILA_CONF: rendered_configs
        }
Example #15
0
    def render_configs(self, configs, adapters_instance=None):
        """Render the configuration files identified in the list passed as
        configs.

        Configs may not only be loaded via OpenStack loaders but also via
        string templates passed via config options or from relation data.
        This must be explicitly declared via string_templates dict of a given
        derived charm class by using a relation name that identifies a relation
        adapter or config option adapter and a property to be used from that
        adapter instance.

        :param configs: list of strings, the names of the configuration files.
        :param adapters_instance: [optional] the adapters_instance to use.
        """
        if adapters_instance is None:
            interfaces = []
            for f in flags.get_flags():
                ep_from_f = relations.endpoint_from_flag(f)
                if ep_from_f:
                    interfaces.append(ep_from_f)
            try:
                adapters_instance = self.adapters_class(interfaces,
                                                        charm_instance=self)
            except TypeError:
                adapters_instance = self.adapters_class(interfaces)

        with self.restart_on_change():
            for conf in configs:
                # check if we need to load a template from a string
                config_template = self._get_string_template(
                    conf, adapters_instance)
                if config_template is False:
                    # got a string template but it was not provided which
                    # means we need to skip this config to avoid rendering
                    return

                charmhelpers.core.templating.render(
                    source=os.path.basename(conf),
                    template_loader=os_templating.get_loader(
                        'templates/', self.release),
                    target=conf,
                    context=adapters_instance,
                    config_template=config_template,
                    group=self.group,
                    perms=0o640,
                )
Example #16
0
 def send_config(self, event):
     if not self.custom_status_check():
         return
     if self.options.driver_handles_share_servers:
         if not self.manila_plugin.authentication_data:
             logging.warning(
                 "Manila plugin authentication_data is required when "
                 "'driver-handles-share-servers' config is enabled.")
             event.defer()
             return
     rendered_configs = ch_templating.render(
         source=os.path.basename(interface_manila_plugin.MANILA_CONF),
         template_loader=os_templating.get_loader('templates/',
                                                  self.release),
         target=None,
         context=self.adapters)
     self.manila_plugin.send_backend_config(self.options.share_backend_name,
                                            rendered_configs)
     self.state.is_started = True
     self.update_status()
Example #17
0
    def render_configs(self, configs, adapters_instance=None):
        """Render the configuration files identified in the list passed as
        configs.

        If adapters_instance is None then the self.adapters_instance is used
        that was setup in the __init__() method.

        :param configs: list of strings, the names of the configuration files.
        :param adapters_instance: [optional] the adapters_instance to use.
        """
        if adapters_instance is None:
            adapters_instance = self.adapters_instance
        with self.restart_on_change():
            for conf in configs:
                charmhelpers.core.templating.render(
                    source=os.path.basename(conf),
                    template_loader=os_templating.get_loader(
                        'templates/', self.release),
                    target=conf,
                    context=adapters_instance)
Example #18
0
    def render_configs(self, configs, adapters_instance=None):
        """Render the configuration files identified in the list passed as
        configs.

        If adapters_instance is None then the self.adapters_instance is used
        that was setup in the __init__() method.

        :param configs: list of strings, the names of the configuration files.
        :param adapters_instance: [optional] the adapters_instance to use.
        """
        if adapters_instance is None:
            adapters_instance = self.adapters_instance
        with self.restart_on_change():
            for conf in configs:
                charmhelpers.core.templating.render(
                    source=os.path.basename(conf),
                    template_loader=os_templating.get_loader(
                        'templates/', self.release),
                    target=conf,
                    context=adapters_instance)
Example #19
0
    def render_configs(self, configs, adapters_instance=None):
        """Render the configuration files identified in the list passed as
        configs.

        If adapters_instance is None then the self.adapters_instance is used
        that was setup in the __init__() method.  Note, if no interfaces were
        passed (the default) then there will be no interfaces.

        TODO: need to work out how to make this function more useful - at the
        moment, with a default setup, this function is only useful to
        render_with_interfaces() which constructs a new adapters_instance
        anyway.

        Configs may not only be loaded via OpenStack loaders but also via
        string templates passed via config options or from relation data.
        This must be explicitly declared via string_templates dict of a given
        derived charm class by using a relation name that identifies a relation
        adapter or config option adapter and a property to be used from that
        adapter instance.

        :param configs: list of strings, the names of the configuration files.
        :param adapters_instance: [optional] the adapters_instance to use.
        """
        if adapters_instance is None:
            adapters_instance = self.adapters_instance

        def get_str_tmpl(conf, adapters_instance):
            """
            Find out if a charm class provides meta information about whether
            this is a template to be fetched from a string dynamically or not.
            """
            config_template = None
            tmpl_meta = self.string_templates.get(conf)
            if tmpl_meta:
                # meta information exists but not clear if an attribute has
                # been set yet either via config option or via relation data
                config_template = False
                rel_name, property = tmpl_meta
                if hasattr(adapters_instance, rel_name):
                    conf_tmpl_adapter = getattr(adapters_instance, rel_name)
                    if hasattr(conf_tmpl_adapter, property):
                        config_template = getattr(conf_tmpl_adapter, property)
                    else:
                        raise Exception('{} does not contain {} property'
                                        ''.format(conf_tmpl_adapter, property))
            return config_template

        with self.restart_on_change():
            for conf in configs:
                # check if we need to load a template from a string
                config_template = get_str_tmpl(conf, adapters_instance)
                if config_template is False:
                    # got a string template but it was not provided which
                    # means we need to skip this config to avoid rendering
                    return

                charmhelpers.core.templating.render(
                    source=os.path.basename(conf),
                    template_loader=os_templating.get_loader(
                        'templates/', self.release),
                    target=conf,
                    context=adapters_instance, config_template=config_template)
    def get_template_for_release(self, os_release, mock_log):
        loader = get_loader('./templates', os_release)
        env = Environment(loader=loader)

        return env.get_template('proxy-server.conf')
    def get_template_for_release(self, os_release, mock_log):
        loader = get_loader('./templates', os_release)
        env = Environment(loader=loader)

        return env.get_template('proxy-server.conf')