def remove_state(self, state): """ Remove this conversation from the given state, and potentially deactivate the state if no more conversations are in it. The relation name will be interpolated in the state name, and it is recommended that it be included to avoid conflicts with states from other relations. For example:: conversation.remove_state('{relation_name}.state') If called from a converation handling the relation "foo", this will remove the conversation from the "foo.state" state, and, if no more conversations are in this the state, will deactivate it. """ state = state.format(relation_name=self.relation_name) value = get_state(state) if not value: return if self.key in value['conversations']: value['conversations'].remove(self.key) if value['conversations']: set_state(state, value) else: remove_state(state)
def remove_state(self, state): """ Remove this conversation from the given state, and potentially deactivate the state if no more conversations are in it. The relation name will be interpolated in the state name, and it is recommended that it be included to avoid conflicts with states from other relations. For example:: conversation.remove_state('{relation_name}.state') If called from a converation handling the relation "foo", this will remove the conversation from the "foo.state" state, and, if no more conversations are in this the state, will deactivate it. """ state = state.format(relation_name=self.relation_name) value = get_state(state) if not value: return if self.key in value['conversations']: value['conversations'].remove(self.key) if value['conversations']: set_state(state, value) else: remove_state(state)
def set_state(self, state): """ Activate and put this conversation into the given state. The relation name will be interpolated in the state name, and it is recommended that it be included to avoid conflicts with states from other relations. For example:: conversation.set_state('{relation_name}.state') If called from a converation handling the relation "foo", this will activate the "foo.state" state, and will add this conversation to that state. Note: This uses :mod:`charmhelpers.core.unitdata` and requires that :meth:`~charmhelpers.core.unitdata.Storage.flush` be called. """ state = state.format(relation_name=self.relation_name) value = get_state(state, { 'relation': self.relation_name, 'conversations': [], }) if self.key not in value['conversations']: value['conversations'].append(self.key) set_state(state, value)
def set_state(self, state): """ Activate and put this conversation into the given state. The relation name will be interpolated in the state name, and it is recommended that it be included to avoid conflicts with states from other relations. For example:: conversation.set_state('{relation_name}.state') If called from a converation handling the relation "foo", this will activate the "foo.state" state, and will add this conversation to that state. Note: This uses :mod:`charmhelpers.core.unitdata` and requires that :meth:`~charmhelpers.core.unitdata.Storage.flush` be called. """ state = state.format(relation_name=self.relation_name) value = get_state(state, { 'relation': self.relation_name, 'conversations': [], }) if self.key not in value['conversations']: value['conversations'].append(self.key) set_state(state, value)
def test_basic_config(mocker, config): service_restart = mocker.patch('reactive.telegraf.host.service_restart') bus.set_state('telegraf.installed') assert not base_dir().join('telegraf.conf').exists() bus.dispatch() assert 'telegraf.configured' in bus.get_states().keys() assert base_dir().join('telegraf.conf').exists() service_restart.assert_called_once_with('telegraf')
def configure_platform(): #hpcc_config = HPCCConfig() #platform.open_ports() config = hookenv.config() if config['node-type'] == 'standalone': set_state('platform.configured') else: hookenv.status_set('active', 'ready') set_state('platform.ready')
def start_platform(): remove_state('platform.started') remove_state('platform.start.failed') platform = HPCCSystemsPlatformConfig() if platform.start(): set_state('platform.start.failed') hookenv.status_set('blocked', 'hpcc start failed') else: set_state('platform.started') hookenv.status_set('active', 'started')
def storage_detaching(): remove_state('platform.stopped') remove_state('platform.stop.failed') hpcc_init = HPCCInit() if hpcc_init.stop(): set_state('platform.stopped') hookenv.status_set('maintainance', 'stopped') else: set_state('platform.stop.failed') hookenv.status_set('blocked', 'hpcc stop failed')
def install_platform(): if is_state('platform.installed'): return platform = HPCCSystemsPlatformConfig() platform.install_prerequsites() platform.install_platform() # ssh keys? config = hookenv.config() if config['ssh-key-private']: install_keys_from_config(config) set_state('platform.installed')
def setup_mysqldb(mysql): if not os.path.exists(HPCCEnv.JUJU_HPCC_DIR): os.makedirs(HPCCEnv.JUJU_HPCC_DIR) mysql_cfg_file = HPCCEnv.JUJU_HPCC_DIR + '/mysqlembed.cfg' f = open(mysql_cfg_file, 'w') f.write('export MYSQLDB_HOST=' + mysql.host() + '\n') f.write('export MYSQLDB_DATABASE=' + mysql.database() + '\n') f.write('export MYSQLDB_USER='******'\n') f.write('export MYSQLDB_PASSWORD='******'\n') f.close() set_state('mysql-db.configured')
def restart_platform(plugin): if is_state('platform.started'): remove_state('platform.started') if is_state('platform.start.failed'): remove_state('platform.start.failed') remove_state('hpcc-plugins.restart.platform') platform = HPCCSystemsPlatformConfig() if platform.restart(): set_state('platform.start.failed') hookenv.status_set('blocked', 'hpcc start failed') else: set_state('platform.started') hookenv.status_set('active', 'started')
def test_config_changed_apt(mocker, config): service_restart = mocker.patch('reactive.telegraf.host.service_restart') apt_install = mocker.patch('reactive.telegraf.apt_install') apt_update = mocker.patch('reactive.telegraf.apt_update') add_source = mocker.patch('reactive.telegraf.add_source') bus.set_state('telegraf.installed') config.save() config['apt_repository'] = "ppa:test-repo" config['apt_repository_key'] = "test-repo-key" bus.set_state('config.changed') bus.dispatch() add_source.assert_called_once_with('ppa:test-repo', 'test-repo-key') assert apt_update.called and apt_update.call_count == 1 apt_install.assert_called_once_with('telegraf', fatal=True) service_restart.assert_called_once_with('telegraf')
def test_restart_on_output_plugin_relation_departed(mocker, monkeypatch, config): service_restart = mocker.patch('reactive.telegraf.host.service_restart') monkeypatch.setattr(telegraf.hookenv, 'relations_of_type', lambda n: []) monkeypatch.setattr(telegraf.hookenv, 'open_port', lambda p: None) bus.discover() bus.set_state('telegraf.installed') bus.set_state('telegraf.configured') interface = mocker.Mock(spec=RelationBase) interface.configure = mocker.Mock() telegraf.prometheus_client(interface) assert configs_dir().join('prometheus-client.conf').exists() # dispatch, file should be gone and telegraf restarted. bus.dispatch() assert not configs_dir().join('prometheus-client.conf').exists() service_restart.assert_called_once_with('telegraf')
def install_platform(): if is_state('platform.installed'): return hpccInstaller = HPCCInstallation() hpccInstaller.install() # ssh keys? #config = hookenv.config() #if config['ssh-key-private']: # install_keys_from_config(config) config = hookenv.config() if (config['node-type'] == "standalone" ): hpcc_config = HPCCConfig() hpcc_config.open_ports() set_state('platform.installed')
def config_changed(): pass #not working correctly config = hookenv.config() if config.changed('ssh-key-private'): install_keys_from_config(config) platform = HPCCSystemsPlatformConfig() if config.changed('hpcc-version') or config.changed('hpcc-type'): hpcc_installed = platform.installed_platform() if (config.changed('hpcc-version') != hpcc_installed[0]) or \ (config.changed('hpcc-type') != hpcc_installed[1]) : remove_state('platform.installed') platform.uninstall_platform() platform.install_platform() set_state('platform.installed')
def start_platform(): config = hookenv.config() #if config['node-type'] != 'standalone': # hookenv.status_set('active', 'ready') # set_state('platform.ready') # return True remove_state('platform.started') remove_state('platform.start.failed') hpcc_init = HPCCInit() if hpcc_init.start(): set_state('platform.started') hookenv.status_set('active', 'started') else: set_state('platform.start.failed') hookenv.status_set('blocked', 'hpcc start failed')
def test_config_changed_extra_plugins(mocker, config): service_restart = mocker.patch('reactive.telegraf.host.service_restart') bus.set_state('telegraf.installed') assert not configs_dir().join('extra_plugins.conf').exists() config.save() config.load_previous() # once the config is saved, change it. This will also trigger a service # restart config['extra_plugins'] = """[[inputs.foo]] some_option = "http://foo.bar.com" [[outputs.baz]] option = "enabled" """ bus.set_state('config.changed') bus.dispatch() assert configs_dir().join('extra_plugins.conf').exists() assert configs_dir().join('extra_plugins.conf').read() == config['extra_plugins'] service_restart.assert_called_once_with('telegraf')
def _migrate_conversations(): """ Due to issue #28 (https://github.com/juju-solutions/charms.reactive/issues/28), conversations needed to be updated to be namespaced per relation ID for SERVICE and UNIT scope. To ensure backwards compatibility, this updates all convs in the old format to the new. TODO: Remove in 2.0.0 """ for key, data in unitdata.kv().getrange('reactive.conversations.').items(): if 'local-data' in key: continue if 'namespace' in data: continue relation_name = data.pop('relation_name') if data['scope'] == scopes.GLOBAL: data['namespace'] = relation_name unitdata.kv().set(key, data) else: # split the conv based on the relation ID new_keys = [] for rel_id in hookenv.relation_ids(relation_name): new_key = Conversation._key(rel_id, data['scope']) new_units = set(hookenv.related_units(rel_id)) & set( data['units']) if new_units: unitdata.kv().set( new_key, { 'namespace': rel_id, 'scope': data['scope'], 'units': sorted(new_units), }) new_keys.append(new_key) unitdata.kv().unset(key) # update the states pointing to the old conv key to point to the # (potentially multiple) new key(s) for state, value in get_states().items(): if not value: continue if key not in value['conversations']: continue value['conversations'].remove(key) value['conversations'].extend(new_keys) set_state(state, value)
def toggle_state(state, should_set): """ Helper that calls either :func:`set_state` or :func:`remove_state`, depending on the value of `should_set`. Equivalent to:: if should_set: set_state(state) else: remove_state(state) :param str state: Name of state to toggle. :param bool should_set: Whether to set the state, or remove it. """ if should_set: set_state(state) else: remove_state(state)
def toggle_state(state, should_set): """ Helper that calls either :func:`set_state` or :func:`remove_state`, depending on the value of `should_set`. Equivalent to:: if should_set: set_state(state) else: remove_state(state) :param str state: Name of state to toggle. :param bool should_set: Whether to set the state, or remove it. """ if should_set: set_state(state) else: remove_state(state)
def _migrate_conversations(): """ Due to issue #28 (https://github.com/juju-solutions/charms.reactive/issues/28), conversations needed to be updated to be namespaced per relation ID for SERVICE and UNIT scope. To ensure backwards compatibility, this updates all convs in the old format to the new. TODO: Remove in 2.0.0 """ for key, data in unitdata.kv().getrange('reactive.conversations.').items(): if 'local-data' in key: continue if 'namespace' in data: continue relation_name = data.pop('relation_name') if data['scope'] == scopes.GLOBAL: data['namespace'] = relation_name unitdata.kv().set(key, data) else: # split the conv based on the relation ID new_keys = [] for rel_id in hookenv.relation_ids(relation_name): new_key = Conversation._key(rel_id, data['scope']) new_units = set(hookenv.related_units(rel_id)) & set(data['units']) if new_units: unitdata.kv().set(new_key, { 'namespace': rel_id, 'scope': data['scope'], 'units': sorted(new_units), }) new_keys.append(new_key) unitdata.kv().unset(key) # update the states pointing to the old conv key to point to the # (potentially multiple) new key(s) for state, value in get_states().items(): if not value: continue if key not in value['conversations']: continue value['conversations'].remove(key) value['conversations'].extend(new_keys) set_state(state, value)
def test_config_changed_extra_options(mocker, config): service_restart = mocker.patch('reactive.telegraf.host.service_restart') bus.set_state('telegraf.installed') bus.set_state('plugins.haproxy.configured') config.save() config.load_previous() config['extra_options'] = yaml.dump({'inputs': {'haproxy': {'timeout': 10}}}) bus.set_state('config.changed') bus.dispatch() assert 'plugins.haproxy.configured' not in bus.get_states().keys() service_restart.assert_called_once_with('telegraf')
def configure_platform(): platform = HPCCSystemsPlatformConfig() platform.open_ports() set_state('platform.configured')
def set_state(self, state, value=None): set_state(state, value)
def install_keys_from_config(config): sshKey = SSHKey('hpcc', 'hpcc', '/home/hpcc') priKey = config['ssh-key-private'] pubKey = config['ssh-key-public'] sshKey.install_key(priKey, pubKey) set_state('platform.sshkeys.changed')