public Server createInstance(OpenstackCloud cloud, String serverName, MachineCreationRequest request)
throws OpsException {
OpenstackComputeClient computeClient = getComputeClient(cloud);
try {
Image foundImage = null;
CloudBehaviours cloudBehaviours = new CloudBehaviours(cloud);
if (!cloudBehaviours.canUploadImages()) {
// For now, we presume this is the HP cloud and hard-code the name
// if (!cloudBehaviours.isHpCloud()) {
// throw new UnsupportedOperationException();
// }
DiskImageRecipe recipe = null;
if (request.recipeId != null) {
recipe = platformLayerClient.getItem(request.recipeId, DiskImageRecipe.class);
}
OperatingSystemRecipe operatingSystem = null;
if (recipe != null) {
operatingSystem = recipe.getOperatingSystem();
}
log.info("Listing images to pick best image");
Iterable<Image> images = computeClient.root().images().list();
if (cloudBehaviours.isHpCloud()) {
// TODO: We need a better solution here!!
Set<String> imageNames = Sets.newHashSet("Debian Squeeze 6.0.3 Server 64-bit 20120123");
log.warn("Hard coding image name (presuming HP cloud)");
// TODO: Match OS
for (Image image : images) {
if (imageNames.contains(image.getName())) {
foundImage = image;
break;
}
}
} else if (cloudBehaviours.isRackspaceCloud()) {
if (operatingSystem == null) {
operatingSystem = new OperatingSystemRecipe();
operatingSystem.setDistribution("debian");
operatingSystem.setVersion("squeeze");
}
for (Image image : images) {
boolean matchesDistribution = false;
boolean matchesVersion = false;
for (Image.ImageMetadata.ImageMetadataItem item : image.getMetadata()) {
// if (item.getKey().equals("platformlayer.org__type")) {
// if (item.getValue().equals("base")) {
// isMatch = true;
// }
// }
if (item.getKey().equals("os_distro")) {
if (operatingSystem != null && operatingSystem.getDistribution() != null) {
if (Comparisons
.equalsIgnoreCase(operatingSystem.getDistribution(), item.getValue())) {
matchesDistribution = true;
}
}
}
if (item.getKey().equals("os_version")) {
if (operatingSystem != null && operatingSystem.getVersion() != null) {
if (Comparisons.equalsIgnoreCase(operatingSystem.getVersion(), item.getValue())) {
matchesVersion = true;
} else if (Comparisons
.equalsIgnoreCase(operatingSystem.getDistribution(), "debian")) {
// Lenny is no longer getting security updates
// if (Strings.equalsIgnoreCase(operatingSystem.getVersion(), "lenny") &&
// Strings.equalsIgnoreCase(item.getValue(), "5")) {
// matchesVersion = true;
// } else
if (Comparisons.equalsIgnoreCase(operatingSystem.getVersion(), "squeeze")
&& Comparisons.equalsIgnoreCase(item.getValue(), "6")) {
matchesVersion = true;
} else {
matchesVersion = false;
}
} else if (Comparisons
.equalsIgnoreCase(operatingSystem.getDistribution(), "ubuntu")) {
if (Comparisons.equalsIgnoreCase(operatingSystem.getVersion(), "lucid")
&& Comparisons.equalsIgnoreCase(item.getValue(), "10.04LTS")) {
matchesVersion = true;
} else {
matchesVersion = false;
}
} else {
matchesVersion = false;
}
}
}
}
if (matchesDistribution && matchesVersion) {
foundImage = image;
break;
}
}
} else {
for (Image image : images) {
boolean isMatch = false;
for (Image.ImageMetadata.ImageMetadataItem item : image.getMetadata()) {
// if (item.getKey().equals(Tag.IMAGE_TYPE)) {
// if (item.getValue().equals("base")) {
// isMatch = true;
// }
// }
if (item.getKey().equals(Tag.IMAGE_OS_DISTRIBUTION)) {
if (operatingSystem != null && operatingSystem.getDistribution() != null) {
if (!Comparisons.equalsIgnoreCase(operatingSystem.getDistribution(),
item.getValue())) {
isMatch = false;
}
}
}
if (item.getKey().equals(Tag.IMAGE_OS_VERSION)) {
if (operatingSystem != null && operatingSystem.getVersion() != null) {
if (!Comparisons.equalsIgnoreCase(operatingSystem.getVersion(), item.getValue())) {
isMatch = false;
}
}
}
}
if (isMatch) {
foundImage = image;
break;
}
}
}
if (foundImage == null) {
throw new IllegalArgumentException("Could not find image");
}
} else {
List<ImageFormat> formats = Collections.singletonList(ImageFormat.DiskQcow2);
CloudImage image = imageFactory.getOrCreateImageId(cloud, formats, request.recipeId);
String imageId = image.getId();
log.info("Getting image details for image: " + imageId);
foundImage = computeClient.root().images().image(imageId).show();
if (foundImage == null) {
throw new IllegalArgumentException("Could not find image: " + imageId);
}
}
SecurityGroup createdSecurityGroup = null;
if (cloudBehaviours.supportsSecurityGroups()) {
SecurityGroup createTemplate = new SecurityGroup();
createTemplate.setName(SECURITY_GROUP_PREFIX + serverName);
createTemplate.setDescription("Security group for instance: " + serverName);
try {
log.info("Creating security group: " + createTemplate.getName());
createdSecurityGroup = computeClient.root().securityGroups().create(createTemplate);
} catch (OpenstackException e) {
for (SecurityGroup candidate : computeClient.root().securityGroups().list()) {
if (Objects.equal(candidate.getName(), createTemplate.getName())) {
createdSecurityGroup = candidate;
break;
}
}
if (createdSecurityGroup != null) {
// Ignore
log.warn("Ignoring 'security group already exists' error: " + e.getMessage());
} else {
throw new OpsException("Error creating security group", e);
}
}
{
CreateSecurityGroupRuleRequest newRule = new CreateSecurityGroupRuleRequest();
newRule.setCidr("0.0.0.0/0");
newRule.setFromPort(22);
newRule.setToPort(22);
newRule.setIpProtocol("tcp");
newRule.setParentGroupId(createdSecurityGroup.getId());
try {
log.info("Creating security group rule for port: " + newRule.getToPort());
SecurityGroupRule createdRule = computeClient.root().securityGroupRules().create(newRule);
} catch (OpenstackException e) {
String message = e.getMessage();
if (message != null && message.contains("This rule already exists")) {
log.warn("Ignoring 'rule already exists': " + e.getMessage());
} else {
throw new OpsException("Error creating security group access", e);
}
}
}
}
AsyncServerOperation createServerOperation;
{
ServerForCreate create = new ServerForCreate();
create.setName(serverName);
if (request.sshPublicKey != null) {
if (cloudBehaviours.supportsPublicKeys()) {
OpenstackCloudHelpers cloudHelpers = new OpenstackCloudHelpers();
KeyPair keyPair = cloudHelpers.ensurePublicKeyUploaded(computeClient, request.sshPublicKeyName,
request.sshPublicKey);
create.setKeyName(keyPair.getName());
} else if (cloudBehaviours.supportsFileInjection()) {
String fileContents = SshKeys.serialize(request.sshPublicKey);
create.addUploadFile("/root/.ssh/authorized_keys", Utf8.getBytes(fileContents));
} else {
throw new OpsException("No supported SSH key mechanism on cloud");
}
}
create.setImageRef(foundImage.getId());
Flavor flavor = getClosestInstanceType(computeClient, request);
if (flavor == null) {
throw new OpsException("Cannot determine instance type for request");
}