Example #1
0
class SlurmctldCharm(CharmBase):
    slurm_instance_manager_cls = SlurmSnapInstanceManager

    def __init__(self, *args):
        super().__init__(*args)

        self.dbd_requires = HostPortRequires(self, "slurmdbd-host-port")
        self.fw_adapter = FrameworkAdapter(self.framework)
        self.slurm_snap = self.slurm_instance_manager_cls(self, "slurmdctld")
        self.munge = MungeProvides(self, "munge")

        event_handler_bindings = {
            self.on.install:
            self._on_install,
            self.dbd_requires.on.host_port_available:
            self._on_dbd_host_port_available,
        }
        for event, handler in event_handler_bindings.items():
            self.fw_adapter.observe(event, handler)

    def _on_install(self, event):
        handle_install(
            event,
            self.fw_adapter,
            self.slurm_snap,
        )

    def _on_dbd_host_port_available(self, event):
        handle_dbd_host_port_available(
            event,
            self.fw_adapter,
        )
Example #2
0
class SlurmdbdCharm(CharmBase):
    _state = StoredState() 
    slurm_instance_manager_cls = SlurmSnapInstanceManager

    def __init__(self, *args):
        super().__init__(*args)

        self._state.set_default(db_info=None)
        self._state.set_default(munge_key=None)
        
        # provides host port to slurmctld
        self.dbd_provides = HostPortProvides(self, "slurmdbd-host-port", f'{socket.gethostname()}', '6819')
        self.slurm_snap = self.slurm_instance_manager_cls(self, "slurmdbd")
        self.fw_adapter = FrameworkAdapter(self.framework) 
        self.db = MySQLClient(self, "db")
        self.munge = MungeRequires(self, "munge")

        event_handler_bindings = {
            self.db.on.database_available: self._on_database_available,
            self.munge.on.munge_available: self._on_munge_available,
            self.on.install: self._on_install,
            self.on.start: self._on_start,
        }
        for event, handler in event_handler_bindings.items():
            self.fw_adapter.observe(event, handler)
        
    def _on_install(self, event):
        handle_install(
            event,
            self.fw_adapter,
            self.slurm_snap,
            self.dbd_provides,
        )

    def _on_start(self, event):
        handle_start(
            event,
            self.fw_adapter,
            self.slurm_snap,
            self._state,
        )

    def _on_database_available(self, event):
        handle_database_available(
            event,
            self.fw_adapter,
            self._state,
        )

    def _on_munge_available(self, event):
        handle_munge_available(
            event,
            self.fw_adapter,
            self.slurm_snap,
            self._state,
        )
Example #3
0
class Charm(CharmBase):
    _stored = StoredState()

    def __init__(self, *args):
        super().__init__(*args)

        # Abstract out framework and friends so that this object is not
        # too tightly coupled with the underlying framework's implementation.
        # From this point forward, our Charm object will only interact with the
        # adapter and not directly with the framework.
        self.fw_adapter = FrameworkAdapter(self.framework)
        self.prometheus = PrometheusInterface(self, 'http-api')
        self.alertmanager = AlertManagerInterface(self, 'alertmanager')
        # Bind event handlers to events
        event_handler_bindings = {
            self.on.start: self.on_start,
            self.on.config_changed: self.on_config_changed,
            self.on.upgrade_charm: self.on_upgrade,
            self.on.stop: self.on_stop,
            self.alertmanager.on.new_relation:
            self.on_new_alertmanager_relation
        }
        for event, handler in event_handler_bindings.items():
            self.fw_adapter.observe(event, handler)

        self._stored.set_default(is_started=False)

    # DELEGATORS

    # These delegators exist to decouple the actual handlers from the
    # underlying framework which has some very specific requirements that
    # do not always apply to every event. For instance if we were to add
    # an interface in our initializer, we would be forced to write unit
    # tests that mock out that object even for handlers that do not need
    # it. This hard coupling results in verbose tests that contain unused
    # mocks. These tests tend to be hard to follow. To counter that, the
    # logic is moved away from this class.

    def on_config_changed(self, event):
        on_config_changed_handler(event, self.fw_adapter, self._stored)

    def on_new_alertmanager_relation(self, event):
        on_new_alertmanager_relation_handler(event, self.fw_adapter)

    def on_start(self, event):
        on_start_handler(event, self.fw_adapter)

    def on_upgrade(self, event):
        on_upgrade_handler(event, self.fw_adapter)

    def on_stop(self, event):
        on_stop_handler(event, self.fw_adapter)
class PrometheusInterface(Object):
    on = PrometheusEvents()

    def __init__(self, charm, relation_name):
        super().__init__(charm, relation_name)

        self.fw_adapter = FrameworkAdapter(self.framework)
        self.relation_name = relation_name

        self.fw_adapter.observe(charm.on[relation_name].relation_changed,
                                self.on_relation_changed)

    def on_relation_changed(self, event):
        logger.debug("Emitting new_prom_rel event")
        self.on.new_prom_rel.emit()
        logger.debug("Done emitting new_prom_rel_event")
Example #5
0
class AlertManagerInterface(Object):
    on = AlertManagerEvents()

    def __init__(self, charm, relation_name):
        super().__init__(charm, relation_name)

        self.fw_adapter = FrameworkAdapter(self.framework)
        self.relation_name = relation_name

        self.fw_adapter.observe(charm.on[relation_name].relation_changed,
                                self.on_relation_changed)

    def on_relation_changed(self, event):
        remote_data = event.relation.data[event.unit]
        logging.debug("Received remote_data: {}".format(dict(remote_data)))

        logger.debug("Emitting new_relation event")
        self.on.new_relation.emit(remote_data)
Example #6
0
class PrometheusInterface(Object):
    on = PrometheusEvents()

    def __init__(self, charm, relation_name):
        super().__init__(charm, relation_name)
        self.fw = FrameworkAdapter(self.framework)
        self.relation_name = relation_name
        self.fw.observe(charm.on[relation_name].relation_joined,
                        self.on_relation_joined)

    def render_relation_data(self):
        logging.debug('render-relation-data in')
        for relation in self.model.relations[self.relation_name]:
            relation.data[self.model.unit]['prometheus-port'] = \
                str(PROMETHEUS_ADVERTISED_PORT)
        logging.debug('render-relation-data out')

    def on_relation_joined(self, event):
        logging.debug("on-joined; emit new-client")
        self.on.new_client.emit(event.relation)
        self.render_relation_data()