/*
* Copyright 2008-2012 Xebia and the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package fr.xebia.workshop.bigdata;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.amazonaws.services.ec2.AmazonEC2;
import com.amazonaws.services.ec2.model.CreateTagsRequest;
import com.amazonaws.services.ec2.model.Instance;
import com.amazonaws.services.ec2.model.InstanceType;
import com.amazonaws.services.ec2.model.RunInstancesRequest;
import com.amazonaws.services.ec2.model.Tag;
import com.amazonaws.services.route53.AmazonRoute53;
import com.amazonaws.services.route53.model.GetHostedZoneRequest;
import com.amazonaws.services.route53.model.HostedZone;
import com.google.common.collect.Maps;
import fr.xebia.cloud.amazon.aws.tools.AmazonAwsUtils;
public class CreateTomcatServers implements Runnable {
private final Logger logger = LoggerFactory.getLogger(getClass());
protected AmazonEC2 ec2;
protected AmazonRoute53 route53;
protected HostedZone hostedZoneId;
protected WorkshopInfrastructure workshopInfrastructure;
// TODO JMA à remplacer par la bonne AMI
protected static final String AMI_TOMCAT_SYSLOG_FLUME = "ami-a56f54d1";
public static final String XEBIA_TECH_EVENT_INFO_DOMAIN_NAME = "Z28O5PDK1WPCSR";
protected CreateTomcatServers(AmazonEC2 ec2, AmazonRoute53 route53,
WorkshopInfrastructure workshopInfrastructure) {
this.ec2 = ec2;
this.route53 = route53;
this.workshopInfrastructure = workshopInfrastructure;
this.hostedZoneId = route53.getHostedZone(
new GetHostedZoneRequest(XEBIA_TECH_EVENT_INFO_DOMAIN_NAME))
.getHostedZone();
}
public String getCnamePrefix() {
return "tomcat-syslog-teamid";
}
public String getTagRole() {
return "log-generator";
}
protected void tagInstances(Map<String, List<Instance>> instancesByTeamId) {
for (Map.Entry<String, List<Instance>> entry : instancesByTeamId
.entrySet()) {
String teamId = entry.getKey();
List<Instance> instances = entry.getValue();
for (int instanceIndex = 0; instanceIndex < instances.size(); instanceIndex++) {
String serverName = getCnamePrefix() + teamId + "-instance"
+ instanceIndex;
Instance instance = instances.get(instanceIndex);
logger.info("Tagging {} - {}", serverName,
instance.getInstanceId());
CreateTagsRequest createTagsRequest = new CreateTagsRequest() //
.withResources(instance.getInstanceId()) //
.withTags(
//
new Tag("Name", serverName), //
new Tag("TeamIdentifier", teamId), //
new Tag("Workshop", "flume-hadoop"), //
new Tag("Role", getTagRole()), //
new Tag("CNAME", buildCname(teamId,
instanceIndex))//
);
AmazonAwsUtils.createTags(instance, createTagsRequest, ec2);
}
}
}
protected String buildCname(String teamId, int instanceId) {
return getCnamePrefix() + teamId + "-instance" + instanceId + "."
+ hostedZoneId.getName();
}
protected Map<String, List<Instance>> associateInstancesToTeamIds(
List<Instance> instances, List<String> teamIdentifiers,
int numberOfServersPerTeam) {
Map<String, List<Instance>> instancesByTeamId = Maps.newHashMap();
int teamIdIndex = 0;
for (String teamId : teamIdentifiers) {
List<Instance> instancesForTeam = createListOfInstancesForTheTeam(
instances, teamIdIndex, numberOfServersPerTeam);
instancesByTeamId.put(teamId, instancesForTeam);
teamIdIndex += numberOfServersPerTeam;
}
return instancesByTeamId;
}
private List<Instance> createListOfInstancesForTheTeam(
List<Instance> instances, int teamId, int numberOfServersPerTeam) {
return instances.subList(teamId, teamId + numberOfServersPerTeam);
}
protected void bindInstancesToDnsCnames(
Map<String, List<Instance>> instancesByTeamId) {
logger.info("Process {}", hostedZoneId);
Map<String, Instance> cnamesToInstance = Maps.newHashMap();
for (Map.Entry<String, List<Instance>> entry : instancesByTeamId
.entrySet()) {
String teamId = entry.getKey();
List<Instance> instances = entry.getValue();
for (int instanceIndex = 0; instanceIndex < instances.size(); instanceIndex++) {
String cname = buildCname(teamId, instanceIndex);
cnamesToInstance.put(cname, instances.get(instanceIndex));
}
}
AmazonAwsUtils.deleteCnameIfExist(cnamesToInstance.keySet(),
hostedZoneId, route53);
AmazonAwsUtils.createCnamesForInstances(cnamesToInstance, hostedZoneId,
route53);
logger.info("Syslog servers creation SUCCESSFUL");
}
protected List<Instance> createNewInstances() {
int instanceCount = workshopInfrastructure.getTeamCount()
* workshopInfrastructure.getNumberOfServersPerTeam();
RunInstancesRequest runInstancesRequest = new RunInstancesRequest() //
.withInstanceType(InstanceType.T1Micro.toString()) //
.withImageId(AMI_TOMCAT_SYSLOG_FLUME) //
.withMinCount(instanceCount) //
.withMaxCount(instanceCount) //
.withSecurityGroupIds("accept-all") //
.withKeyName(workshopInfrastructure.getKeyPairName());
List<Instance> instances = AmazonAwsUtils.reliableEc2RunInstances(
runInstancesRequest, ec2);
if (instances.size() != instanceCount) {
logger.warn(
"Unexpected number of instances created: {} instead of {} expected",
instances.size(), instanceCount);
}
return instances;
}
@Override
public void run() {
List<Instance> instances = createNewInstances();
Map<String, List<Instance>> instancesByTeamId = associateInstancesToTeamIds(
instances, workshopInfrastructure.getTeamIdentifiers(),
workshopInfrastructure.getNumberOfServersPerTeam());
tagInstances(instancesByTeamId);
bindInstancesToDnsCnames(instancesByTeamId);
}
}