aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2013-02-15 17:20:53 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2013-02-15 17:25:58 +0200
commit9205135a977cacebb79df1309ef5eaab57127f06 (patch)
treefd9ed7ba7476d8d9c4272238119bcd644150463d /src
parent62f22e19e0953022d68f220463104117a1a5b7e2 (diff)
downloadeclat-9205135a977cacebb79df1309ef5eaab57127f06.tar.gz
eclat-9205135a977cacebb79df1309ef5eaab57127f06.tar.bz2
Implement DescribeImages and RunInstances.
* TODO: Update. * etc/describe-images.fln: New file. * etc/run-instances.fln: New file. * etc/Makefile.am: Add new files. * lib/q2url.c (add_param): Accept NULL values. * lib/qaddparm.c (eclat_query_add_param): Likewise. * lib/qencode.c (encode_param): Likewise. * lib/reqsign.c (eclat_query_signature): Likewise. * src/dscrimgs-cl.opt: New file. * src/dscrimgs.c: New file. * src/runinsts-cl.opt: New file. * src/runinsts.c: New file. * src/Makefile.am: Add new files. * src/eclat.c (cmdtab): Register new commands. * src/eclat.h (eclat_run_instances) (eclat_describe_images): New protos.
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am6
-rw-r--r--src/dscrimgs-cl.opt104
-rw-r--r--src/dscrimgs.c34
-rw-r--r--src/eclat.c4
-rw-r--r--src/eclat.h2
-rw-r--r--src/runinsts-cl.opt231
-rw-r--r--src/runinsts.c374
7 files changed, 754 insertions, 1 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 10c5cf0..0492bd9 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -36,6 +36,7 @@ eclat_SOURCES=\
dscrsnapattr.c\
dscrregs.c\
dscrtags.c\
+ dscrimgs.c\
dscrinstattr.c\
dscrinsts.c\
dscrinststat.c\
@@ -47,6 +48,7 @@ eclat_SOURCES=\
getconout.c\
modinstattr.c\
reladdr.c\
+ runinsts.c\
startinst.c\
util.c
@@ -66,12 +68,14 @@ OPTFILES=\
detvol-cl.opt\
disassaddr-cl.opt\
dscraddrs-cl.opt\
+ dscrimgs-cl.opt\
dscrinststat-cl.opt\
dscrsecgrps-cl.opt\
dscrsnap-cl.opt\
dscrtags-cl.opt\
generic-cl.opt\
- reladdr-cl.opt
+ reladdr-cl.opt\
+ runinsts-cl.opt
eclat_SOURCES += $(OPTFILES:.opt=.h)
diff --git a/src/dscrimgs-cl.opt b/src/dscrimgs-cl.opt
new file mode 100644
index 0000000..b358058
--- /dev/null
+++ b/src/dscrimgs-cl.opt
@@ -0,0 +1,104 @@
+/* This file is part of Eclat.
+ Copyright (C) 2013 Sergey Poznyakoff.
+
+ Eclat is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ Eclat is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Eclat. If not, see <http://www.gnu.org/licenses/>. */
+
+static int owner_n;
+static int xby_n;
+
+OPTIONS_BEGIN("eclat describe-images",
+ [<describe Amazon images>],
+ [<[FILTER...] [AMI...]>],
+ [<gnu>],
+ [<nousage>],
+ [<noversion>])
+
+OPTION(all,a,,
+ [<describe all images>])
+BEGIN
+ grecs_asprintf(&bufptr, &bufsize, "Owner.%d", ++owner_n);
+ eclat_query_add_param(q, bufptr, "all");
+END
+
+OPTION(owner,o,[<ID|amazon|aws-marketplace|self|all>],
+ [<select AMIs with a particular owner>])
+BEGIN
+ grecs_asprintf(&bufptr, &bufsize, "Owner.%d", ++owner_n);
+ eclat_query_add_param(q, bufptr, optarg);
+END
+
+OPTION(executable-by, x, [<ID|all|self>],
+ [<select images executable by the given user>])
+BEGIN
+ grecs_asprintf(&bufptr, &bufsize, "ExecutableBy.%d", ++xby_n);
+ eclat_query_add_param(q, bufptr, optarg);
+END
+
+OPTIONS_END
+
+static void
+parse_options(struct ec2_query *q, int argc, char *argv[], int *idx)
+{
+ char *bufptr = NULL;
+ size_t bufsize = 0;
+ static char *arch[] = { "i386", "x86_64", NULL };
+ static char *voltype[] = { "standard", "io1", NULL };
+ static char *imgtype[] = { "machine", "kernel", "ramdisk", NULL };
+ static char *prodcode[] = { "devpay", "marketplace", NULL };
+ static char *rootdevtype[] = { "ebs", "instance-store", NULL };
+ static char *states[] = { "available", "pending", "failed", NULL };
+ static char *virttype[] = { "paravirtual", "hvm", NULL };
+ static char *hvstype[] = { "ovm", "xen", NULL };
+ static struct filter_descr filters[] = {
+ { "architecture", FILTER_ENUM, arch },
+ { "block-device-mapping.delete-on-termination", FILTER_BOOL },
+ { "block-device-mapping.device-name", FILTER_STRING },
+ { "block-device-mapping.snapshot-id", FILTER_STRING },
+ { "block-device-mapping.volume-size", FILTER_INT },
+ { "block-device-mapping.volume-type", FILTER_ENUM, voltype },
+ { "description", FILTER_STRING },
+ { "image-id", FILTER_STRING },
+ { "image-type", FILTER_ENUM, imgtype },
+ { "is-public", FILTER_BOOL },
+ { "kernel-id", FILTER_STRING },
+ { "manifest-location", FILTER_STRING },
+ { "name", FILTER_STRING },
+ { "owner-alias", FILTER_STRING },
+ { "owner-id", FILTER_STRING },
+ { "platform", FILTER_STRING },
+ { "product-code", FILTER_STRING },
+ { "product-code.type", FILTER_ENUM, prodcode },
+ { "ramdisk-id", FILTER_STRING },
+ { "root-device-name", FILTER_STRING },
+ { "root-device-type", FILTER_ENUM, rootdevtype },
+ { "state", FILTER_ENUM, states },
+ { "state-reason-code", FILTER_STRING },
+ { "state-reason-message", FILTER_STRING },
+ { "tag-key", FILTER_STRING },
+ { "tag-value", FILTER_STRING },
+ { "tag:<key>", FILTER_STRING },
+ { "virtualization-type", FILTER_ENUM, virttype },
+ { "hypervisor", FILTER_ENUM, hvstype },
+ { NULL }
+ };
+
+ available_filters = filters;
+ proginfo.print_help_hook = list_filters;
+ GETOPT(argc, argv, *idx, exit(EX_USAGE))
+ free(bufptr);
+}
+
+
+
+
diff --git a/src/dscrimgs.c b/src/dscrimgs.c
new file mode 100644
index 0000000..51d85b1
--- /dev/null
+++ b/src/dscrimgs.c
@@ -0,0 +1,34 @@
+/* This file is part of Eclat.
+ Copyright (C) 2013 Sergey Poznyakoff.
+
+ Eclat is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ Eclat is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Eclat. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "eclat.h"
+#include "dscrimgs-cl.h"
+
+int
+eclat_describe_images(eclat_command_env_t *env, int argc, char **argv)
+{
+ int i;
+
+ parse_options(env->query, argc, argv, &i);
+
+ argc -= i;
+ argv += i;
+
+ translate_ids(argc, argv, "ImageId");
+ describe_query_create(env, argc, argv, "ImageId");
+
+ return 0;
+}
diff --git a/src/eclat.c b/src/eclat.c
index eca1b71..d198345 100644
--- a/src/eclat.c
+++ b/src/eclat.c
@@ -272,6 +272,10 @@ struct command cmdtab[] = {
eclat_detach_volume, CMD_MOD|CMD_DESTR },
{ "modify-instance-attribute", "ModifyInstanceAttribute",
eclat_modify_instance_attribute, CMD_MOD },
+ { "describe-images", "DescribeImages",
+ eclat_describe_images },
+ { "run-instances", "RunInstances",
+ eclat_run_instances, CMD_MOD },
};
size_t cmdcnt = sizeof(cmdtab) / sizeof(cmdtab[0]);
diff --git a/src/eclat.h b/src/eclat.h
index ba5d57b..011b666 100644
--- a/src/eclat.h
+++ b/src/eclat.h
@@ -107,6 +107,8 @@ int eclat_attach_volume(eclat_command_env_t *env, int argc, char **argv);
int eclat_detach_volume(eclat_command_env_t *env, int argc, char **argv);
int eclat_modify_instance_attribute(eclat_command_env_t *env,
int argc, char **argv);
+int eclat_run_instances(eclat_command_env_t *env, int argc, char **argv);
+int eclat_describe_images(eclat_command_env_t *env, int argc, char **argv);
char *region_to_endpoint(const char *region);
diff --git a/src/runinsts-cl.opt b/src/runinsts-cl.opt
new file mode 100644
index 0000000..9852e70
--- /dev/null
+++ b/src/runinsts-cl.opt
@@ -0,0 +1,231 @@
+/* This file is part of Eclat.
+ Copyright (C) 2013 Sergey Poznyakoff.
+
+ Eclat is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ Eclat is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Eclat. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <sys/stat.h>
+#include <stdio.h>
+
+static char *ami;
+static char *instance_count = "1";
+static struct grecs_list *secgrp, *devmap, *iface, *privip;
+static char *keypair;
+static char *user_data;
+static char *type;
+static char *zone;
+static char *kernel;
+static char *ramdisk;
+static char *shutdown_behavior;
+static char *placement_group;
+static char *tenancy;
+static char *subnet;
+static char *private_ip;
+static char *secipcount;
+static char *profile_name;
+
+static int monitor;
+static int disable_term;
+static int ebs_opt;
+
+static void
+read_user_data(const char *file)
+{
+ struct stat st;
+ FILE *fp;
+
+ if (stat(file, &st))
+ die(EX_USAGE, "cannot stat file %s: %s", file,
+ strerror(errno));
+
+ /* FIXME: Use limits.h to check st.st_size */
+ user_data = grecs_malloc(st.st_size+1);
+ fp = fopen(file, "r");
+ if (!fp)
+ die(EX_UNAVAILABLE, "cannot open file %s: %s", file,
+ strerror(errno));
+ if (fread(user_data, st.st_size, 1, fp) != 1)
+ die(EX_UNAVAILABLE, "error reading from %s: %s", file,
+ strerror(errno));
+ fclose(fp);
+ user_data[st.st_size] = 0;
+}
+
+OPTIONS_BEGIN("eclat run-instances",
+ [<launch new instances>],
+ [<AMI-ID>],
+ [<gnu>],
+ [<nousage>],
+ [<noversion>])
+
+OPTION(,n,[<N>],
+ [<number of instances to launch>])
+BEGIN
+ /* FIXME: check if it's a valid number */
+ instance_count = optarg;
+END
+
+OPTION(security-group,g,[<STRING>],
+ [<The name of the security group>])
+BEGIN
+ if (!secgrp)
+ secgrp = grecs_list_create();
+ grecs_list_append(secgrp, optarg);
+END
+
+OPTION(keypair,k,[<ID>],
+ [<Key pair name>])
+BEGIN
+ keypair = optarg;
+END
+
+OPTION(data,d,[<STRING>],
+ [<user data to pass to the instance>])
+BEGIN
+ user_data = optarg;
+END
+
+OPTION(data-file,f,[<FILE>],
+ [<read user data from FILE>])
+BEGIN
+ read_user_data(optarg);
+END
+
+OPTION(type,t,[<TYPE>],
+ [<instance type>])
+ALIAS(instance-type)
+BEGIN
+ type = optarg;
+END
+
+OPTION(zone,z,[<ZONE>],
+ [<set availablility zone>])
+ALIAS(availability-zone)
+BEGIN
+ zone = optarg;
+END
+
+OPTION(kernel,,[<ID>],
+ [<select kernel ID>])
+BEGIN
+ kernel = optarg;
+END
+
+OPTION(ramdisk,,[<ID>],
+ [<select ramdisk ID>])
+BEGIN
+ ramdisk = optarg;
+END
+
+OPTION(devmap,m,[<DEV=SPEC>],
+ [<set block device mapping>])
+ALIAS(block-device-mapping)
+BEGIN
+ if (!devmap)
+ devmap = grecs_list_create();
+ grecs_list_append(devmap, optarg);
+END
+
+OPTION(monitor,,,
+ [<enable monitoring>])
+BEGIN
+ monitor = 1;
+END
+
+OPTION(disable-api-termination,,,
+ [<disable API termination>])
+BEGIN
+ disable_term = 1;
+END
+
+OPTION(shutdown,,[<stop|terminate>],
+ [<what to do on shutdown>])
+ALIAS(instance-initiated-shutdown-behavior)
+BEGIN
+ shutdown_behavior = optarg;
+END
+
+OPTION(placement-group,,[<NAME>],
+ [<name of the placement group>])
+BEGIN
+ placement_group = optarg;
+END
+
+OPTION(tenancy,,[<STRING>],
+ [<placement tenancy>])
+BEGIN
+ tenancy = optarg;
+END
+
+OPTION(subnet,s,[<ID>],
+ [<subnet to launch the instance into>])
+BEGIN
+ subnet = optarg;
+END
+
+OPTION(private-ip-address,,[<IP>],
+ [<assign a specific private IP to the VPC instance>])
+BEGIN
+ private_ip = optarg;
+END
+
+dnl [--client-token token]
+
+OPTION(network-interface,a,[<IFACE>],
+ [<specify the network attachment for a VPC instance>])
+ALIAS(iface)
+BEGIN
+ if (!iface)
+ iface = grecs_list_create();
+ grecs_list_append(iface, optarg);
+END
+
+OPTION(secondary-ip,,[<IP>],
+ [<assign the IP as a secondary private IP address>])
+ALIAS(secondary-private-ip-address)
+BEGIN
+ if (!privip)
+ privip = grecs_list_create();
+ grecs_list_append(privip, privip);
+END
+
+OPTION(number-secondary-ip,,[<N>],
+ [<number of secondary IP addresses to assign>])
+ALIAS(secondary-private-ip-address-count)
+BEGIN
+ secipcount = optarg;
+END
+
+OPTION(iam-profile,p,[<NAME>],
+ [<IAM instance profile to associate with the launched instances>])
+BEGIN
+ profile_name = optarg;
+END
+
+OPTION(ebs-optimized,,,
+ [<optimize the instances for EBS I/O>])
+BEGIN
+ ebs_opt = 1;
+END
+
+OPTIONS_END
+
+static void
+parse_options(int argc, char *argv[])
+{
+ int idx;
+ GETOPT(argc, argv, idx, exit(EX_USAGE))
+ if (idx != argc-1)
+ die(EX_USAGE, "bad number of arguments");
+ ami = argv[idx];
+}
diff --git a/src/runinsts.c b/src/runinsts.c
new file mode 100644
index 0000000..826377d
--- /dev/null
+++ b/src/runinsts.c
@@ -0,0 +1,374 @@
+/* This file is part of Eclat.
+ Copyright (C) 2013 Sergey Poznyakoff.
+
+ Eclat is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ Eclat is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Eclat. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "eclat.h"
+#include "runinsts-cl.h"
+
+static int
+isnumstr(const char *p)
+{
+ for (; *p; p++)
+ if (!isdigit(*p))
+ return 0;
+ return 1;
+}
+
+static void
+encode_devmap(struct ec2_query *q)
+{
+ int i;
+ char *bufptr = NULL;
+ size_t bufsize = 0;
+ struct grecs_list_entry *ep;
+
+ for (i = 1, ep = devmap->head; ep; ep = ep->next, i++) {
+ char *dev = ep->data;
+ char *p = strchr(dev, '=');
+
+ if (!p)
+ die(EX_USAGE, "malformed device mapping: %s", dev);
+ *p++ = 0;
+
+ grecs_asprintf(&bufptr, &bufsize,
+ "BlockDeviceMapping.%d.DeviceName",
+ i);
+ eclat_query_add_param(q, bufptr, dev);
+
+ if (strcmp(p, "none") == 0) {
+ grecs_asprintf(&bufptr, &bufsize,
+ "BlockDeviceMapping.%d.NoDevice",
+ i);
+ eclat_query_add_param(q, bufptr, NULL);
+ } else if (strncmp(p, "ephemeral", 9) == 0) {
+ grecs_asprintf(&bufptr, &bufsize,
+ "BlockDeviceMapping.%d.VirtualName",
+ i);
+ eclat_query_add_param(q, bufptr, p);
+ } else {
+ struct wordsplit ws;
+
+ /* [snapshot-id]:[volume-size]:[true|false]:[standard|io1[:iops]] */
+ ws.ws_delim = ":";
+ if (wordsplit(p, &ws,
+ WRDSF_NOVAR | WRDSF_NOCMD | WRDSF_DELIM))
+ die(EX_SOFTWARE,
+ "failed to split string %s: %s",
+ p,
+ wordsplit_strerror(&ws));
+ if (ws.ws_wordc == 1) {
+ if (strncmp(ws.ws_wordv[0], "snap-", 5) == 0) {
+ grecs_asprintf(&bufptr, &bufsize,
+ "BlockDeviceMapping.%d."
+ "Ebs.SnapshotId",
+ i);
+ } else if (isnumstr(ws.ws_wordv[0])) {
+ grecs_asprintf(&bufptr, &bufsize,
+ "BlockDeviceMapping.%d."
+ "Ebs.VolumeSize",
+ i);
+ } else
+ die(EX_USAGE,
+ "unrecognized word \"%s\", "
+ "expected either a snapshot ID, "
+ "or disk size",
+ ws.ws_wordv[0]);
+ eclat_query_add_param(q, bufptr,
+ ws.ws_wordv[0]);
+ } else {
+ if (ws.ws_wordv[0]) {
+ grecs_asprintf(&bufptr, &bufsize,
+ "BlockDeviceMapping.%d."
+ "Ebs.SnapshotId",
+ i);
+ eclat_query_add_param(q, bufptr,
+ ws.ws_wordv[0]);
+ }
+
+ if (ws.ws_wordv[1]) {
+ grecs_asprintf(&bufptr, &bufsize,
+ "BlockDeviceMapping.%d."
+ "Ebs.VolumeSize",
+ i);
+ eclat_query_add_param(q, bufptr,
+ ws.ws_wordv[1]);
+ }
+ }
+
+ switch (ws.ws_wordc) {
+ default:
+ die(EX_USAGE,
+ "too many parts in device mapping \"%s\"",
+ p);
+ case 5:
+ grecs_asprintf(&bufptr, &bufsize,
+ "BlockDeviceMapping.%d.Ebs.Iops",
+ i);
+ eclat_query_add_param(q, bufptr,
+ ws.ws_wordv[4]);
+ /* fall through */
+ case 4:
+ grecs_asprintf(&bufptr, &bufsize,
+ "BlockDeviceMapping.%d.Ebs.VolumeType",
+ i);
+ eclat_query_add_param(q, bufptr,
+ ws.ws_wordv[3]);
+ /* fall through */
+ case 3:
+ if (strcmp(ws.ws_wordv[2], "false") &&
+ strcmp(ws.ws_wordv[2], "true"))
+ die(EX_USAGE,
+ "expected \"true\" or \"false\", "
+ "but found \"%s\"",
+ ws.ws_wordv[2]);
+ grecs_asprintf(&bufptr, &bufsize,
+ "BlockDeviceMapping.%d."
+ "Ebs.DeleteOnTermination",
+ i);
+ eclat_query_add_param(q, bufptr,
+ ws.ws_wordv[2]);
+ }
+ wordsplit_free(&ws);
+ }
+ }
+ free(bufptr);
+}
+
+/* format:
+
+ dev-index:subnet:description:priv-ip:sgs:DOT:sip-count:sips
+ 0 1 2 3 4 5 6 7
+
+ where:
+
+ dev-index device index
+ subnet subnet ID
+ sgs a comma-separated list of security group IDs
+ DOT delete the interface on termination: true or false
+ sip-count number of secondary IP addresses to assign
+ sips a comma-separated list of secondary IP addresses
+
+ only dev-index and subnet are mandatory;
+ either sip-count or sips can be specified, but not both.
+*/
+void
+add_iface(struct ec2_query *q, int ifno, char *ifspec)
+{
+ struct wordsplit ws;
+ char *bufptr = NULL;
+ size_t bufsize = 0;
+ char *p;
+ int i;
+
+ ws.ws_delim = ":";
+ if (wordsplit(ifspec, &ws, WRDSF_NOVAR | WRDSF_NOCMD | WRDSF_DELIM))
+ die(EX_SOFTWARE,
+ "failed to split string %s: %s",
+ p,
+ wordsplit_strerror(&ws));
+
+ switch (ws.ws_wordc) {
+ default:
+ die(EX_USAGE,
+ "bad number of parts in interface specification \"%s\": %d",
+ ifspec, ws.ws_wordc);
+ case 8:
+ for (i = 1, p = strtok(ws.ws_wordv[7], ","); p;
+ i++, p = strtok(NULL, ",")) {
+ grecs_asprintf(&bufptr, &bufsize,
+ "NetworkInterface.%d."
+ "PrivateIpAddresses.%d.PrivateIpAddress",
+ ifno, i);
+ eclat_query_add_param(q, bufptr, p);
+ }
+ /* fall through */
+ case 7:
+ if (ws.ws_wordv[6][0]) {
+ grecs_asprintf(&bufptr, &bufsize,
+ "NetworkInterface.%d."
+ "SecondaryPrivateIpAddressCount",
+ ifno);
+ eclat_query_add_param(q, bufptr, ws.ws_wordv[6]);
+ }
+ case 6:
+ if (ws.ws_wordv[5][0]) {
+ grecs_asprintf(&bufptr, &bufsize,
+ "NetworkInterface.%d."
+ "DeleteOnTermination",
+ ifno);
+ eclat_query_add_param(q, bufptr, ws.ws_wordv[5]);
+ }
+ case 5:
+ if (ws.ws_wordv[4])
+ for (i = 1, p = strtok(ws.ws_wordv[4], ","); p;
+ i++, p = strtok(NULL, ",")) {
+ grecs_asprintf(&bufptr, &bufsize,
+ "NetworkInterface.%d."
+ "SecurityGroupId.%d",
+ ifno, i);
+ eclat_query_add_param(q, bufptr, p);
+ }
+ case 4:
+ if (ws.ws_wordv[3]) {
+ grecs_asprintf(&bufptr, &bufsize,
+ "NetworkInterface.%d.PrivateIpAddress",
+ ifno);
+ eclat_query_add_param(q, bufptr, ws.ws_wordv[3]);
+ }
+ case 3:
+ if (ws.ws_wordv[2]) {
+ grecs_asprintf(&bufptr, &bufsize,
+ "NetworkInterface.%d.Description",
+ ifno);
+ eclat_query_add_param(q, bufptr, ws.ws_wordv[2]);
+ }
+ case 2:
+ if (!ws.ws_wordv[1][0])
+ die(EX_USAGE,
+ "no subnet ID in interface specification \"%s\"",
+ ifspec);
+ }
+ grecs_asprintf(&bufptr, &bufsize, "NetworkInterface.%d.SubnetId",
+ ifno);
+ eclat_query_add_param(q, bufptr,
+ ws.ws_wordv[1][0] ? ws.ws_wordv[1] : "0");
+
+ if (ws.ws_wordv[0][0]) {
+ grecs_asprintf(&bufptr, &bufsize,
+ "NetworkInterface.%d.DeviceIndex",
+ ifno);
+ eclat_query_add_param(q, bufptr, ws.ws_wordv[0]);
+ }
+
+ wordsplit_free(&ws);
+ free(bufptr);
+}
+
+int
+eclat_run_instances(eclat_command_env_t *env, int argc, char **argv)
+{
+ int i;
+ char *bufptr = NULL;
+ size_t bufsize = 0;
+ struct grecs_list_entry *ep;
+ struct ec2_query *q = env->query;
+ char *p;
+ int iface_no = 1;
+
+ parse_options(argc, argv);
+
+ eclat_query_add_param(q, "ImageId", ami);
+ p = strchr(instance_count, '-');
+ eclat_query_add_param(q, "MinCount", instance_count);
+ if (p) {
+ *p++ = 0;
+ eclat_query_add_param(q, "MaxCount", p);
+ } else
+ eclat_query_add_param(q, "MaxCount", instance_count);
+
+ if (keypair)
+ eclat_query_add_param(q, "KeyName", keypair);
+
+ if (secgrp) {
+ for (i = 1, ep = secgrp->head; ep; ep = ep->next, i++) {
+ grecs_asprintf(&bufptr, &bufsize,
+ "SecurityGroup.%d", i);
+ eclat_query_add_param(q, bufptr, ep->data);
+ }
+ }
+
+ if (type)
+ eclat_query_add_param(q, "InstanceType", type);
+
+ if (zone)
+ eclat_query_add_param(q, "Placement.AvailabilityZone", zone);
+
+ if (kernel)
+ eclat_query_add_param(q, "KernelId", kernel);
+
+ if (ramdisk)
+ eclat_query_add_param(q, "RamdiskId", ramdisk);
+
+ if (devmap)
+ encode_devmap(q);
+
+ if (monitor)
+ eclat_query_add_param(q, "Monitoring.Enabled", "true");
+
+ if (disable_term)
+ eclat_query_add_param(q, "DisableApiTermination", "true");
+
+ if (shutdown_behavior)
+ eclat_query_add_param(q, "InstanceInitiatedShutdownBehavior",
+ "true");
+ if (placement_group)
+ eclat_query_add_param(q, "Placement.GroupName",
+ placement_group);
+
+ if (tenancy)
+ eclat_query_add_param(q, "Placement.Tenancy", tenancy);
+
+ if (subnet)
+ eclat_query_add_param(q, "SubnetId", subnet);
+
+ if (private_ip)
+ eclat_query_add_param(q, "PrivateIpAddress", private_ip);
+
+ /* FIXME: I'm not at all sure whether this is the right way of
+ doing it. */
+ if (privip) {
+ for (i = 1, ep = privip->head; ep; i++, ep = ep->next) {
+ grecs_asprintf(&bufptr, &bufsize,
+ "NetworkInterface.1."
+ "PrivateIpAddresses.%d.PrivateIpAddress",
+ i);
+ eclat_query_add_param(q, bufptr, ep->data);
+ }
+ iface_no++;
+ } else if (secipcount) {
+ eclat_query_add_param(q,
+ "NetworkInterface.1."
+ "SecondaryPrivateIpAddressCount",
+ secipcount);
+ iface_no++;
+ }
+
+ if (iface)
+ for (ep = iface->head; ep; ep = ep->next)
+ add_iface(q, iface_no++, ep->data);
+
+ if (profile_name)
+ eclat_query_add_param(q,
+ strncmp(profile_name, "arn:", 4) == 0 ?
+ "IamInstanceProfile.Arn" :
+ "IamInstanceProfile.Name",
+ profile_name);
+
+ if (ebs_opt)
+ eclat_query_add_param(q, "EbsOptimized", "true");
+
+ if (user_data) {
+ size_t enclen;
+
+ eclat_base64_encode((unsigned char *)user_data,
+ strlen(user_data),
+ (unsigned char**) &p, &enclen);
+
+ eclat_query_add_param(q, "UserData", p);
+ free(p);
+ }
+
+ return 0;
+}

Return to:

Send suggestions and report system problems to the System administrator.