From 0d7ee650f6198c70f2ff06bc16ba160129de70cf Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Thu, 20 Sep 2012 01:36:01 +0300 Subject: Implement multiple regions and StopInstance command. * src/config.c: Change configuration statements. * src/eclat.c: Translate endpoint if region is given. * src/eclat.h: Update. * src/startinst.c: Implement stop instance. --- src/config.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- src/eclat.c | 9 ++++++++- src/eclat.h | 4 +++- src/startinst.c | 22 +++++++++++++-------- 4 files changed, 80 insertions(+), 14 deletions(-) diff --git a/src/config.c b/src/config.c index 5727167..c40d307 100644 --- a/src/config.c +++ b/src/config.c @@ -50,14 +50,63 @@ run_config_finish_hooks() return rc; } +/* Translation table: region -> endpoint. Its elements are of + struct ec2_param type. */ +struct grecs_symtab *ec2_regtab; + +char * +region_to_endpoint(const char *region) +{ + struct ec2_param *p, key; + + key.name = (char*) region; + p = grecs_symtab_lookup_or_install(ec2_regtab, &key, NULL); + return p ? p->value : NULL; +} + +static int +cb_region(enum grecs_callback_command cmd, + grecs_locus_t *locus, + void *varptr, + grecs_value_t *value, + void *cb_data) +{ + struct ec2_param *p, key; + int install = 1; + + if (cmd != grecs_callback_set_value) { + grecs_error(locus, 0, "Unexpected block statement"); + return 1; + } + if (!value || value->type != GRECS_TYPE_ARRAY || value->v.arg.c != 2) { + grecs_error(locus, 0, "expected two strings"); + return 1; + } + if (value->v.arg.v[0]->type != GRECS_TYPE_STRING || + value->v.arg.v[1]->type != GRECS_TYPE_STRING) { + grecs_error(locus, 0, "expected two strings"); + return 1; + } + + key.name = value->v.arg.v[0]->v.string; + p = grecs_symtab_lookup_or_install(ec2_regtab, &key, &install); + if (!install) + free(p->value); /* FIXME: Redefinition warning */ + p->value = grecs_strdup(value->v.arg.v[1]->v.string); + return 0; +} + static struct grecs_keyword eclat_kw[] = { - { "host", "hostname", - "Send queries to instead of the default host", - grecs_type_string, GRECS_DFLT, &default_host }, + { "default-endpoint", "hostname", + "Set default EC2 endpoint", + grecs_type_string, GRECS_DFLT, &endpoint }, + { "region", " ", + "Define a region", + grecs_type_string, GRECS_MULT, NULL, 0, cb_region }, { "access-file", "file", "Specify a file containing `accessID:accessKey' pairs", grecs_type_string, GRECS_DFLT, &access_file_name }, - { "region", "name", + { "default-region", "name", "Define default AWS region", grecs_type_string, GRECS_DFLT, ®ion_name }, @@ -90,6 +139,8 @@ config_init() grecs_log_to_stderr = 1; grecs_adjust_string_locations = 1; grecs_print_diag_fun = grecs_print_diag; + + ec2_regtab = grecs_symtab_create_default(sizeof(struct ec2_param)); } void diff --git a/src/eclat.c b/src/eclat.c index 5625076..f0440e3 100644 --- a/src/eclat.c +++ b/src/eclat.c @@ -22,7 +22,7 @@ int debug_level[ECLAT_DEBCAT_MAX]; int dry_run_mode; int preprocess_only = 0; -char *default_host = "ec2.amazonaws.com"; +char *endpoint = "ec2.amazonaws.com"; int use_ssl; char *access_key; char *secret_key; @@ -222,6 +222,13 @@ main(int argc, char **argv) if (lint_mode) exit(0); + if (region_name) { + endpoint = region_to_endpoint(region_name); + if (!endpoint) + die(EX_USAGE, + "cannot find endpoint for region %s", region_name); + } + if (!secret_key) { if (access_file_lookup(access_key, &access_key, &secret_key)) die(EX_UNAVAILABLE, diff --git a/src/eclat.h b/src/eclat.h index 953c34c..31914a0 100644 --- a/src/eclat.h +++ b/src/eclat.h @@ -37,7 +37,7 @@ extern const char *program_name; extern int debug_level[]; -extern char *default_host; +extern char *endpoint; extern int use_ssl; extern char *region_name; extern char *access_file_name; @@ -79,3 +79,5 @@ typedef int (*eclat_command_handler_t) (CURL *curl, int argc, char **argv); int eclat_start_instance(CURL *curl, int argc, char **argv); int eclat_stop_instance(CURL *curl, int argc, char **argv); + +char *region_to_endpoint(const char *region); diff --git a/src/startinst.c b/src/startinst.c index f2d3ea8..d2b9cad 100644 --- a/src/startinst.c +++ b/src/startinst.c @@ -16,21 +16,20 @@ #include "eclat.h" -int -eclat_start_instance(CURL *curl, int argc, char **argv) +static int +start_stop_instance(CURL *curl, const char *action, int argc, char **argv) { int i; struct ec2_query *q; char buf[128], *bend, *url; size_t bs; CURLcode res; + + if (argc == 0) + die(EX_USAGE, "no instance ids"); - q = eclat_query_create(use_ssl ? EC2_QF_HTTPS : 0, - default_host, "/"); - if (region_name) - eclat_query_add_param(q, "Placement.AvailabilityZone", - region_name); - eclat_query_add_param(q, "Action", "StartInstances"); + q = eclat_query_create(use_ssl ? EC2_QF_HTTPS : 0, endpoint, "/"); + eclat_query_add_param(q, "Action", action); strcpy(buf, "InstanceId."); bend = buf + strlen(buf); @@ -60,8 +59,15 @@ eclat_start_instance(CURL *curl, int argc, char **argv) } +int +eclat_start_instance(CURL *curl, int argc, char **argv) +{ + start_stop_instance(curl, "StartInstances", argc, argv); +} + int eclat_stop_instance(CURL *curl, int argc, char **argv) { + start_stop_instance(curl, "StopInstances", argc, argv); } -- cgit v1.2.1