def notify_storage_rings_available(broker_timestamp): """Notify peer swift-storage relations that they should synchronise ring and builder files. Note that this should only be called from the leader unit. @param broker_timestamp: timestamp for peer and storage sync - this MUST be the same as the one used for peer sync. """ if not is_elected_leader(SWIFT_HA_RES): log("Ring availability storage-relation broadcast requested by " "non-leader - skipping", level=WARNING) return hostname = get_hostaddr() hostname = format_ipv6_addr(hostname) or hostname path = os.path.basename(get_www_dir()) rings_url = 'http://{}/{}'.format(hostname, path) # TODO(hopem): consider getting rid of this trigger since the timestamp # should do the job. trigger = uuid.uuid4() # Notify storage nodes that there is a new ring to fetch. log("Notifying storage nodes that new rings are ready for sync.", level=INFO) for relid in relation_ids('swift-storage'): relation_set(relation_id=relid, swift_hash=get_swift_hash(), rings_url=rings_url, broker_timestamp=broker_timestamp, trigger=trigger)
def notify_storage_rings_available(): """Notify peer swift-storage relations that they should synchronise ring and builder files. Note that this should only be called from the leader unit. """ if not is_elected_leader(SWIFT_HA_RES): log( "Ring availability storage-relation broadcast requested by " "non-leader - skipping", level=WARNING) return hostname = get_hostaddr() hostname = format_ipv6_addr(hostname) or hostname path = os.path.basename(get_www_dir()) rings_url = 'http://{}/{}'.format(hostname, path) trigger = uuid.uuid4() # Notify storage nodes that there is a new ring to fetch. log("Notifying storage nodes that new rings are ready for sync.", level=INFO) for relid in relation_ids('swift-storage'): relation_set(relation_id=relid, swift_hash=get_swift_hash(), rings_url=rings_url, trigger=trigger)
def test_get_swift_hash_file(self, mock_config): expected = '##FILEHASH##' with tempfile.NamedTemporaryFile() as tmpfile: swift_context.SWIFT_HASH_FILE = tmpfile.name tmpfile.write(expected) tmpfile.seek(0) os.fsync(tmpfile) hash = swift_context.get_swift_hash() self.assertFalse(mock_config.called) self.assertEqual(expected, hash)
def test_get_swift_hash_file(self, mock_config): expected = '##FILEHASH##' with tempfile.NamedTemporaryFile() as tmpfile: swift_context.SWIFT_HASH_FILE = tmpfile.name tmpfile.write(expected.encode('UTF-8')) tmpfile.seek(0) os.fsync(tmpfile) hash = swift_context.get_swift_hash() self.assertFalse(mock_config.called) self.assertEqual(expected, hash)
def test_get_swift_hash_config(self, mock_config): expected = '##CFGHASH##' mock_config.return_value = expected tmpfile = tempfile.mktemp() swift_context.SWIFT_HASH_FILE = tmpfile hash = swift_context.get_swift_hash() with open(tmpfile, 'r') as fd: self.assertEqual(expected, fd.read()) self.assertTrue(mock_config.called) self.assertEqual(expected, hash)
def test_get_swift_hash_env(self, mock_config, mock_service_name): mock_config.return_value = None mock_service_name.return_value = "testsvc" tmpfile = tempfile.mktemp() swift_context.SWIFT_HASH_FILE = tmpfile with mock.patch('lib.swift_context.os.environ.get') as mock_env_get: mock_env_get.return_value = str(uuid.uuid4()) hash_ = swift_context.get_swift_hash() mock_env_get.assert_called_with('JUJU_ENV_UUID') with open(tmpfile, 'r') as fd: self.assertEqual(hash_, fd.read()) self.assertTrue(mock_config.called)
def test_get_swift_hash_env(self, mock_config, mock_service_name): mock_config.return_value = None mock_service_name.return_value = "testsvc" tmpfile = tempfile.mktemp() swift_context.SWIFT_HASH_FILE = tmpfile with mock.patch('lib.swift_context.os.environ.get') as mock_env_get: mock_env_get.return_value = str(uuid.uuid4()) hash_ = swift_context.get_swift_hash() mock_env_get.assert_has_calls([ mock.call('JUJU_MODEL_UUID'), mock.call('JUJU_ENV_UUID', mock_env_get.return_value) ]) with open(tmpfile, 'r') as fd: self.assertEqual(hash_, fd.read()) self.assertTrue(mock_config.called)
def rings_consumer_changed(): """Based on 'swift_storage_relation_changed' function from the swift-storage charm.""" rings_url = relation_get('rings_url') swift_hash = relation_get('swift_hash') if not all([rings_url, swift_hash]): log('rings_consumer_relation_changed: Peer not ready?') return if swift_hash != get_swift_hash(): msg = "Swift hash has to be unique in multi-region setup" status_set('blocked', msg) raise SwiftProxyCharmException(msg) try: fetch_swift_rings_and_builders(rings_url) except CalledProcessError: log("Failed to sync rings from {} - no longer available from that " "unit?".format(rings_url), level=WARNING) broadcast_rings_available()