main.c 9.12 KB
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <sys/types.h>

#define MAX_NODES       128
#define MAX_SENSORS     8
#define MAX_BUFFER      1024
#define USERNAME        "antoine"
#define FILES_PATH      "/home/antoine/PFE_DEMO/files/"
#define TOFLASH_PATH    "/home/antoine/PFE_DEMO/toflash/"
#define PLAYBOOK_PATH	"/home/antoine/PFE_DEMO/ansible.yml"

typedef struct node {
    char *ip;
    char *sensors[MAX_SENSORS];
    int n_sensors;
} Node;

typedef struct experiment {
    int exp_id;
    int n_nodes;
    char *date;
    char *file;
    char *duration;
    char *name;
    char *arch;
    char *dir;
	char *exp_name;
    Node nodes[MAX_NODES];
} Experiment;

void process_line(char *line, Experiment *experiment) {
    char *key;
    char *value;
    char *save_ptr;
    key = strtok_r(line, ":", &save_ptr);
    if(!strcmp(key, "date")) {
        value = strtok_r(NULL, "\n", &save_ptr);
        experiment->date = strdup(value + 1);
    }
    else if(!strcmp(key, "name")) {
        value = strtok_r(NULL, "\n", &save_ptr);
        experiment->name = strdup(value + 1);       
    }
    else if(!strcmp(key, "dir")) {
        value = strtok_r(NULL, "\n", &save_ptr);
        experiment->dir = strdup(value + 1);       
    }
    else if(!strcmp(key, "arch")) {
        value = strtok_r(NULL, "\n", &save_ptr);
        experiment->arch = strdup(value + 1);       
    }
    else if(!strcmp(key, "exp_id")) {
        value = strtok_r(NULL, "\n", &save_ptr);
        experiment->exp_id = atoi(value + 1);   
    }
    else if(!strcmp(key, "time")) {
        value = strtok_r(NULL, "\n", &save_ptr);
        experiment->duration = strdup(value + 1);
    }        
    else if(!strcmp(key, "file")) {
        value = strtok_r(NULL, "\n", &save_ptr);
        experiment->file = strdup(value + 1);
    }
    else if(!strcmp(key, "nodes")) {
        value = strtok_r(NULL, "\n", &save_ptr) + 2;
        char *nodes_list = strtok_r(value, "]", &save_ptr);
        char *node;
        char *save_ptr_node;
        int present = 0;

        node = strtok_r(nodes_list, ",", &save_ptr);

        while(node != NULL) {
            char *sensor = strtok_r(node, "@", &save_ptr_node);
            char *ip = strtok_r(NULL, "@", &save_ptr_node);

            if(experiment->n_nodes == 0) {
                Node n;
                n.n_sensors = 1;
                n.ip = strdup(ip);
                n.sensors[0] = strdup(sensor);
                experiment->nodes[0] = n;
                experiment->n_nodes++;
            }

            else {
                for(int i = 0; i < experiment->n_nodes; i++) {
                    if(!strcmp(experiment->nodes[i].ip, ip)) {
                        int nb = experiment->nodes[i].n_sensors;
                        experiment->nodes[i].sensors[nb] = strdup(sensor);
                        experiment->nodes[i].n_sensors++;
                        present = 1;
                    }
                }
                if(!present) {
                    Node n;
                    n.n_sensors = 1;
                    n.ip = strdup(ip);
                    n.sensors[0] = strdup(sensor);
                    experiment->nodes[experiment->n_nodes] = n;
                    experiment->n_nodes++;
                }
                present = 0;
            }

            node = strtok_r(NULL, ",", &save_ptr);
            if(node != NULL && *node == ' ') {
                node++;
            }
        }
    }
}

Experiment *read_file(char *file_name) {
    char ch;
    char buffer[MAX_BUFFER];
    FILE *fp;
    Experiment *experiment = (Experiment*) malloc(sizeof(Experiment));
    experiment->n_nodes = 0;

    fp = fopen(file_name, "r");

    if(fp == NULL) {
        perror("Error while opening the file.\n");
        exit(EXIT_FAILURE);
    }

    while(fgets(buffer, MAX_BUFFER, fp) != NULL) {
        process_line(buffer, experiment);
    }

    fclose(fp);
    return experiment;
}

int check_date(Experiment *experiment) {
    time_t now;
    time(&now);
    struct tm tm = { 0 };
    strptime(experiment->date, "%Y-%m-%dT%H:%M", &tm);
    time_t t = mktime(&tm);

    if(t <= now) {
        printf("Starting deployment of \"[%d] %s\" ...\n", experiment->exp_id, experiment->name);
        return 0;
    }
    return 1;
}

int process_time(Experiment *experiment) {
    char duration[8];
    strcpy(duration, experiment->duration);
    char *hour;
    char *min;
    hour = strtok(duration, ":");
    min = strtok(NULL, "\0");
    return atoi(hour) * 3600 + atoi(min) * 60;
}

int binary_not_present(Experiment *experiment) {
    char path[512];
    strcpy(path, FILES_PATH);
    strcat(path, experiment->dir);
    strcat(path, "/out.bin");
    FILE *file;
    if(file = fopen(path, "r")) {
        fclose(file);
        return 0;
    }
    return 1;
}

int process_exp(Experiment *experiment) {
    if(check_date(experiment)) {
        return 1;
    }

    char docker_cmd[1024];

    if(!strcmp(experiment->arch, "arm")) {
        if(binary_not_present(experiment)) {
            sprintf(docker_cmd, "docker run --rm -v %s:/exp -e SRC_NAME=\"%s\" -e SRC_DIR=\"%s\" arm_compiler",
                FILES_PATH,
                experiment->file,
                experiment->dir
            );
            exec_prog(docker_cmd);
        }
    }

    int time_sec = process_time(experiment);
    char cmd1[1024];
    char cmd2[1024];
    char sensors_list[512];
    strcpy(sensors_list, "");
    for(int i = 0; i < experiment->n_nodes; i++) {
        for(int j = 0; j < experiment->nodes[i].n_sensors; j++) {
            strcat(sensors_list, experiment->nodes[i].sensors[j]);
            if(j < experiment->nodes[i].n_sensors - 1) {
                strcat(sensors_list, "\n");
            }
        }
        sprintf(cmd2, "mkdir ~/exp_%d", experiment->exp_id);
        sprintf(cmd1, "runuser -l %s -c \'echo \"%s\" | ssh pi@%s \"%s && cat > ~/exp_%d/config_experimentation.txt\"\'", 
            USERNAME,
            sensors_list, 
            experiment->nodes[i].ip, 
            cmd2, 
            experiment->exp_id);
        exec_prog(cmd1);
    }

    char hosts_filename[64];
    sprintf(hosts_filename, "/etc/ansible/exp_%d.hosts", experiment->exp_id);
    FILE *hosts_fp = fopen(hosts_filename, "w");
    fprintf(hosts_fp, "[exp_%d]\n", experiment->exp_id);
    for(int i = 0; i < experiment->n_nodes; i++) {
        fprintf(hosts_fp, "%s ansible_user=pi\n", experiment->nodes[i].ip);
    }
    fclose(hosts_fp);

    char ansible_command[512];
    sprintf(ansible_command, "runuser -l %s -c \'ansible-playbook %s -i %s -e \"servernames=exp_%d exp_duration=%d binary_dir=%s exp_name=%s\"\'",
        USERNAME,
	PLAYBOOK_PATH,
        hosts_filename,
        experiment->exp_id,
        time_sec,
        experiment->dir,
		experiment->exp_name);
    exec_prog_background(ansible_command);

    return 0;
}

void print_exp(Experiment *experiment) {
    printf("== EXP[%d] : %s ==\n%s during %s with the file %s (%s) on the %d nodes :\n",
        experiment->exp_id,
        experiment->exp_name,
        experiment->date,
        experiment->duration,
        experiment->file,
        experiment->arch,
        experiment->n_nodes);
    for(int i = 0; i < experiment->n_nodes; i++) {
        printf("* %s\n", experiment->nodes[i].ip);
        for(int j = 0; j < experiment->nodes[i].n_sensors; j++) {
            printf("    - %s\n", experiment->nodes[i].sensors[j]);
        }
    }
}

void free_exp(Experiment *experiment) {
    free(experiment->date);
    free(experiment->duration);
    free(experiment->file);
    free(experiment->arch);
    free(experiment->dir);
    free(experiment->name);
	free(experiment->exp_name);
    for(int i = 0; i < experiment->n_nodes; i++) {
        for(int j = 0; j < experiment->nodes[i].n_sensors; j++) {
            free(experiment->nodes[i].sensors[j]);
        }
        free(experiment->nodes[i].ip);
    }
    free(experiment);
}

void check_files() {
    DIR *dir;
    struct dirent *dirent;
    dir = opendir(TOFLASH_PATH);

    if(dir != NULL) {
        while(dirent = readdir(dir)) {
            if((dirent->d_type == DT_REG) && (strstr(dirent->d_name, ".started") == NULL)) {
                char file_name[128];
				char new_file_name[128];
                strcpy(file_name, TOFLASH_PATH);
                strcat(file_name, dirent->d_name);
                Experiment *experiment = read_file(file_name);
				experiment->exp_name = strdup(dirent->d_name);
#ifdef DEBUG                
                print_exp(experiment);
#endif
                if(!process_exp(experiment)) {
					strcpy(new_file_name, file_name);
					strcat(new_file_name, ".started");
                    rename(file_name, new_file_name);
                }
                free_exp(experiment);
            }
        }
        closedir(dir);
    }
    else {
        perror("Dossier toflash non trouvable");
        exit(EXIT_FAILURE);
    }

    return;
}

int exec_prog(char *cmd) {
    if(system(cmd) == -1) {
        return 1;
    }
    return 0;
}

int exec_prog_background(char *cmd) {
    if(!fork()) {
        system(cmd);
        return 0;
    }
    return 1;
}

int main(int argc, char **argv) {
    while(1) {
        check_files();
        sleep(10);
    }
    return 0;
}