/* This file is part of Eclat. Copyright (C) 2013-2014 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 . */ #include "eclat.h" #include "mkinst-cl.h" /* 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", ifspec, 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(env, 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) eclat_encode_devmap(q, devmap); 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; }