Esempio n. 1
0
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)
Esempio n. 2
0
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)
Esempio n. 4
0
    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)
Esempio n. 6
0
    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)
Esempio n. 8
0
    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()