timely_util/
ec2.rs

1/*
2    Configuration for running Timely experiments on EC2.
3
4    The following functions are not EC2-related, but are just for
5    localhost computations. These correspond to the similar EC2
6    versions of these functions.
7    - prepare_local_host_file (corresponds to prepare_ec2_host_file)
8*/
9
10use crate::util::file_util;
11use crate::util::network_util::barrier;
12
13use std::process::Command;
14
15const EC2_IP_FILE: &str = "hosts/ec2_local_ips.txt";
16const EC2_HOST_TEMP_FILE: &str = "hosts/temp_ec2_hosts.txt";
17const EC2_REGION: &str = "us-east-2";
18
19const LOCAL_HOST_INPUT: &str = "hosts/localhost_20.txt";
20const LOCAL_HOST_TEMP_FILE: &str = "hosts/temp_local_hosts.txt";
21
22pub fn get_ec2_ipv4() -> String {
23    // example output: 172.31.27.62
24    let output = Command::new("curl")
25        .arg("http://169.254.169.254/latest/meta-data/local-ipv4")
26        .output()
27        .expect(
28            "Couldn't get local ipv4 address with curl command; \
29             are you running on an EC2 instance?",
30        );
31    if output.stdout.is_empty() {
32        panic!(
33            "Couldn't get local ipv4 address with curl command; \
34             are you running on an EC2 instance?",
35        )
36    }
37    String::from_utf8_lossy(&output.stdout).to_string()
38}
39
40pub fn get_ec2_host_port_str(ipv4: &str, port: u64) -> String {
41    // example output: ip-172-31-27-62.us-east-2.compute.internal:4000
42    let ipv4 = str::replace(ipv4, ".", "-");
43    format!("ip-{}.{}.compute.internal:{}", ipv4, EC2_REGION, port)
44}
45
46pub fn get_ec2_node_number() -> u64 {
47    let ipv4 = get_ec2_ipv4();
48    file_util::match_line_in_file(&ipv4, EC2_IP_FILE).unwrap_or_else(|err| {
49        panic!(
50            "failed to calculate ec2 node number from ip file {}: {}",
51            EC2_IP_FILE, err
52        )
53    }) as u64
54}
55
56// Create/overwrite the file with EC2 host information, then return the new file.
57pub fn prepare_ec2_host_file(port: u64) -> &'static str {
58    file_util::replace_lines_in_file(
59        EC2_IP_FILE,
60        EC2_HOST_TEMP_FILE,
61        |_line_num, ipv4| get_ec2_host_port_str(ipv4, port),
62    )
63    .unwrap();
64    EC2_HOST_TEMP_FILE
65}
66
67// Create/overwrite the file with local host information, then return the new file.
68// Hosts are localhost:port where the ports are in increasing order starting from
69// starting_port.
70pub fn prepare_local_host_file(starting_port: u64) -> &'static str {
71    file_util::replace_lines_in_file(
72        LOCAL_HOST_INPUT,
73        LOCAL_HOST_TEMP_FILE,
74        |line_num, _line| {
75            format!("localhost:{}", (starting_port as usize) + line_num)
76        },
77    )
78    .unwrap();
79    LOCAL_HOST_TEMP_FILE
80}
81
82// A logical barrier between EC2 nodes.
83// (each node waits for every node to reach the barrier)
84pub fn ec2_barrier(num_nodes: u64, this_node: u64, start_port: u16) {
85    let host0 = file_util::first_line_in_file(EC2_IP_FILE);
86    barrier(&host0, num_nodes, this_node, start_port);
87}
88
89pub fn local_barrier(num_nodes: u64, this_node: u64, start_port: u16) {
90    barrier("localhost", num_nodes, this_node, start_port);
91}