|
11 | 11 | from omegaconf import DictConfig, ListConfig, OmegaConf |
12 | 12 |
|
13 | 13 | import constants |
| 14 | +from experiment_utils.providers.factory import create_provider |
14 | 15 |
|
15 | 16 |
|
16 | 17 | def validate_basic_config( |
@@ -532,6 +533,19 @@ def __init__(self, cfg: DictConfig): |
532 | 533 | self.cloudlab_username = cfg.providers.cloudlab.username |
533 | 534 | self.hostname_suffix = cfg.providers.cloudlab.hostname_suffix |
534 | 535 |
|
| 536 | + # Single source of truth for the infrastructure provider: build it here |
| 537 | + # (from cfg alone) so every node-dependent value derived from it — |
| 538 | + # remote_write_ip included — is computed in exactly one place instead |
| 539 | + # of being re-derived (and potentially forgotten) in each script. |
| 540 | + self.provider = create_provider(cfg) |
| 541 | + |
| 542 | + # Remote write IP (127.0.0.1 for local mode, CloudLab's 10.10.1.x |
| 543 | + # scheme otherwise). Written back onto cfg.streaming.remote_write.ip |
| 544 | + # too, since generate_prometheus_config reads it from cfg directly |
| 545 | + # rather than through this Args object. |
| 546 | + self.remote_write_ip = self.provider.get_node_ip(self.node_offset) |
| 547 | + cfg.streaming.remote_write.ip = self.remote_write_ip |
| 548 | + |
535 | 549 | # Logging and debugging |
536 | 550 | self.log_level = cfg.logging.level |
537 | 551 |
|
@@ -565,10 +579,8 @@ def __init__(self, cfg: DictConfig): |
565 | 579 | self.do_local_flink = cfg.streaming.do_local_flink |
566 | 580 | self.forward_unsupported_queries = cfg.streaming.forward_unsupported_queries |
567 | 581 | self.use_kafka_ingest = cfg.streaming.use_kafka_ingest |
568 | | - # Remote write configuration |
569 | | - self.remote_write_ip = ( |
570 | | - None # set by caller: provider.get_node_ip(self.node_offset) |
571 | | - ) |
| 582 | + # Remote write configuration (self.remote_write_ip set above, near |
| 583 | + # provider construction) |
572 | 584 | self.remote_write_base_port = cfg.streaming.remote_write.base_port |
573 | 585 | self.remote_write_path = cfg.streaming.remote_write.path |
574 | 586 |
|
@@ -624,6 +636,15 @@ def get_coordinator_node(self) -> int: |
624 | 636 | """Get the coordinator node index (first node in the range).""" |
625 | 637 | return self.node_offset |
626 | 638 |
|
| 639 | + def to_dict(self) -> Dict[str, Any]: |
| 640 | + """JSON-serializable snapshot of this Args instance. |
| 641 | +
|
| 642 | + `provider` holds a live InfrastructureProvider object, so it's |
| 643 | + swapped for its repr() (e.g. "CloudLabProvider(username='...', ...)") |
| 644 | + rather than dropped. |
| 645 | + """ |
| 646 | + return {k: (repr(v) if k == "provider" else v) for k, v in vars(self).items()} |
| 647 | + |
627 | 648 |
|
628 | 649 | def validate_config(cfg: DictConfig, script_name: str = "experiment_run_e2e"): |
629 | 650 | """ |
|
0 commit comments