Beispiel #1
0
    def test_parse_shards_valid2(self) -> None:
        # Parse multiple inputs
        self.assertEqual(
            {
                ShardID(node=NodeID(node_index=0), shard_index=1),
                ShardID(node=NodeID(node_index=1), shard_index=2),
            },
            helpers.parse_shards(["N0:S1", "N1:S2"]),
        )

        # Remove duplicates
        self.assertEqual(
            {
                ShardID(node=NodeID(node_index=0), shard_index=1),
                ShardID(node=NodeID(node_index=1), shard_index=2),
            },
            helpers.parse_shards(["N0:S1", "N1:S2", "N0:s1"]),
        )
Beispiel #2
0
    def _combine(
        cv: ClusterView,
        shards: Optional[List[str]] = None,
        node_names: Optional[List[str]] = None,
        node_indexes: Optional[List[int]] = None,
    ) -> Tuple[ShardID, ...]:

        shards = list(shards or [])
        node_names = list(node_names or [])
        node_indexes = list(node_indexes or [])

        shard_ids = parse_shards(shards)
        for nn in node_names:
            shard_ids.add(ShardID(node=cv.get_node_id(node_name=nn), shard_index=-1))
        for ni in node_indexes:
            shard_ids.add(ShardID(node=NodeID(node_index=ni), shard_index=-1))
        shard_ids_expanded = cv.expand_shards(shard_ids)

        return shard_ids_expanded
Beispiel #3
0
    def test_parse_shards_invalid(self) -> None:
        """
        Invalid shards should throw ValueError exceptions.
        """
        # N0:S1, N0, or 0 format should be accepted
        with self.assertRaises(ValueError):
            print(helpers.parse_shards([":S2"]))

        with self.assertRaises(ValueError):
            print(helpers.parse_shards(["N:S2"]))

        with self.assertRaises(ValueError):
            print(helpers.parse_shards(["X0"]))

        with self.assertRaises(ValueError):
            helpers.parse_shards(["N0:B1"])

        with self.assertRaises(ValueError):
            helpers.parse_shards(["N0:S1X"])
Beispiel #4
0
    def test_parse_shards_valid1(self) -> None:
        # 5
        self.assertEqual(
            {ShardID(node=NodeID(node_index=5), shard_index=ALL_SHARDS)},
            helpers.parse_shards(["5"]),
        )
        # 5:1
        self.assertEqual(
            {ShardID(node=NodeID(node_index=5), shard_index=1)},
            helpers.parse_shards(["5:1"]),
        )
        # 0:S1
        self.assertEqual(
            {ShardID(node=NodeID(node_index=0), shard_index=1)},
            helpers.parse_shards(["0:S1"]),
        )
        # N0:S1
        self.assertEqual(
            {ShardID(node=NodeID(node_index=0), shard_index=1)},
            helpers.parse_shards(["N0:S1"]),
        )

        # N0 == ShardID(0, ALL_SHARDS)
        self.assertEqual(
            {ShardID(node=NodeID(node_index=0), shard_index=ALL_SHARDS)},
            helpers.parse_shards(["N0"]),
        )

        # N1:S4 == ShardID(1, 4)
        self.assertEqual(
            {ShardID(node=NodeID(node_index=1), shard_index=4)},
            helpers.parse_shards(["N1:S4"]),
        )

        # Allow ignored case
        # n1:S4 == ShardID(1, 4)
        self.assertEqual(
            {ShardID(node=NodeID(node_index=1), shard_index=4)},
            helpers.parse_shards(["n1:S4"]),
        )
Beispiel #5
0
    async def apply(
        self,
        reason: str,
        node_indexes: Optional[List[int]] = None,
        node_names: Optional[List[str]] = None,
        shards: Optional[List[str]] = None,
        shard_target_state: Optional[str] = "may-disappear",
        sequencer_node_indexes: Optional[List[int]] = None,
        sequencer_node_names: Optional[List[str]] = None,
        user: Optional[str] = "",
        group: Optional[bool] = True,
        skip_safety_checks: Optional[bool] = False,
        ttl: Optional[int] = 0,
        allow_passive_drains: Optional[bool] = False,
        force_restore_rebuilding: Optional[bool] = False,
    ):
        """
        Applies new maintenance to Maintenance Manager
        """
        ctx = context.get_context()

        try:
            async with ctx.get_cluster_admin_client() as client:
                cv = await get_cluster_view(client)

            all_node_indexes = set()
            if node_indexes is not None:
                all_node_indexes = all_node_indexes.union(set(node_indexes))
            if node_names is not None:
                all_node_indexes = all_node_indexes.union({
                    cv.get_node_index(node_name=node_name)
                    for node_name in set(node_names)
                })

            shard_ids = set()
            sequencer_nodes = set()
            for ni in all_node_indexes:
                nv = cv.get_node_view(node_index=ni)
                if nv.is_storage:
                    shard_ids.add(ShardID(node=nv.node_id, shard_index=-1))
                if nv.is_sequencer:
                    sequencer_nodes.add(nv.node_id)

            if sequencer_node_indexes is not None:
                for ni in set(sequencer_node_indexes):
                    nv = cv.get_node_view(node_index=ni)
                    if nv.is_sequencer:
                        sequencer_nodes.add(nv.node_id)

            if sequencer_node_names is not None:
                for nn in set(sequencer_node_names):
                    nv = cv.get_node_view(node_name=nn)
                    if nv.is_sequencer:
                        sequencer_nodes.add(nv.node_id)

            if shards is not None:
                shard_ids = shard_ids.union(
                    cv.expand_shards(parse_shards(shards)))

        except NodeNotFoundError as e:
            print(colored(f"Node not found: {e}", "red"))
            return

        try:
            async with ctx.get_cluster_admin_client() as client:
                maintenances: Collection[MaintenanceDefinition]
                maintenances = await apply_maintenance(
                    client=client,
                    shards=shard_ids,
                    shard_target_state=_parse_shard_target_state(
                        shard_target_state),
                    sequencer_nodes=list(sequencer_nodes),
                    group=group,
                    ttl=timedelta(seconds=ttl),
                    user=user or getuser(),
                    reason=reason,
                    skip_safety_checks=skip_safety_checks,
                    allow_passive_drains=allow_passive_drains,
                    force_restore_rebuilding=force_restore_rebuilding,
                )
                cv = await get_cluster_view(client)
        except Exception as e:
            print(colored(f"Cannot apply maintenance: {e}", "red"))
            return

        print(
            _render(
                [
                    cv.get_maintenance_view_by_id(id)
                    for id in [mnt.group_id for mnt in maintenances]
                ],
                cv,
                mode=RenderingMode.EXPANDED,
            ))
Beispiel #6
0
 def test_parse_shards_empty(self) -> None:
     """
     Empty input should produce empty output
     """
     self.assertEqual(set(), helpers.parse_shards([]))