/*
* Copyright (c) 2015 Google, Inc.
*
* 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 com.cloudera.director.google.compute;
import com.cloudera.director.google.util.Dates;
import com.cloudera.director.google.util.Urls;
import com.cloudera.director.spi.v1.compute.util.AbstractComputeInstance;
import com.cloudera.director.spi.v1.model.DisplayProperty;
import com.cloudera.director.spi.v1.model.DisplayPropertyToken;
import com.cloudera.director.spi.v1.model.util.SimpleDisplayPropertyBuilder;
import com.cloudera.director.spi.v1.util.DisplayPropertiesUtil;
import com.google.api.services.compute.model.AccessConfig;
import com.google.api.services.compute.model.Disk;
import com.google.api.services.compute.model.Instance;
import com.google.api.services.compute.model.NetworkInterface;
import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* Google Compute instance.
*/
public class GoogleComputeInstance
extends AbstractComputeInstance<GoogleComputeInstanceTemplate, Instance> {
private static final Logger LOG = LoggerFactory.getLogger(GoogleComputeInstance.class);
/**
* The list of display properties (including inherited properties).
*/
private static final List<DisplayProperty> DISPLAY_PROPERTIES =
DisplayPropertiesUtil.asDisplayPropertyList(GoogleComputeInstanceDisplayPropertyToken.values());
/**
* Returns the list of display properties for a Google instance, including inherited properties.
*
* @return the list of display properties for a Google instance, including inherited properties
*/
public static List<DisplayProperty> getDisplayProperties() {
return DISPLAY_PROPERTIES;
}
/**
* Google compute instance display properties.
*/
public enum GoogleComputeInstanceDisplayPropertyToken implements DisplayPropertyToken {
IMAGE_ID(new SimpleDisplayPropertyBuilder()
.displayKey("imageId")
.name("Image ID")
.defaultDescription("The ID of the image used to launch the instance.")
.sensitive(false)
.build()) {
@Override
protected String getPropertyValue(Instance instance, Disk bootDisk) {
return Urls.getLocalName(bootDisk.getSourceImage());
}
},
/**
* The ID of the instance.
*/
INSTANCE_ID(new SimpleDisplayPropertyBuilder()
.displayKey("instanceId")
.name("Instance ID")
.defaultDescription("The ID of the instance.")
.sensitive(false)
.build()) {
@Override
protected String getPropertyValue(Instance instance, Disk bootDisk) {
return instance.getName();
}
},
/**
* The instance type.
*/
INSTANCE_TYPE(new SimpleDisplayPropertyBuilder()
.displayKey("instanceType")
.name("Machine type")
.defaultDescription("The instance type.")
.sensitive(false)
.build()) {
@Override
protected String getPropertyValue(Instance instance, Disk bootDisk) {
return Urls.getLocalName(instance.getMachineType());
}
},
/**
* The time the instance was launched.
*/
LAUNCH_TIME(new SimpleDisplayPropertyBuilder()
.displayKey("launchTime")
.name("Launch time")
.defaultDescription("The time the instance was launched.")
.sensitive(false)
.build()) {
@Override
protected String getPropertyValue(Instance instance, Disk bootDisk) {
String creationTimestampStr = null;
try {
creationTimestampStr = instance.getCreationTimestamp();
Date creationTimestamp = null;
if (creationTimestampStr != null) {
creationTimestamp = Dates.getDateFromTimestamp(creationTimestampStr);
}
if (creationTimestamp != null) {
// TODO(duftler): Use appropriate date formatting.
return creationTimestamp.toString();
}
} catch (IllegalArgumentException e) {
LOG.info("Problem parsing creation timestamp '{}' of instance '{}': {}",
creationTimestampStr, instance.getName(), e.getMessage());
}
return null;
}
},
/**
* The private IP address assigned to the instance.
*/
PRIVATE_IP_ADDRESS(new SimpleDisplayPropertyBuilder()
.displayKey("privateIpAddress")
.name("Internal IP")
.defaultDescription("The private IP address assigned to the instance.")
.sensitive(false)
.build()) {
@Override
protected String getPropertyValue(Instance instance, Disk bootDisk) {
List<NetworkInterface> networkInterfaceList = instance.getNetworkInterfaces();
if (networkInterfaceList != null && networkInterfaceList.size() > 0) {
return networkInterfaceList.get(0).getNetworkIP();
}
return null;
}
},
/**
* The public IP address assigned to the instance.
*/
PUBLIC_IP_ADDRESS(new SimpleDisplayPropertyBuilder()
.displayKey("publicIpAddress")
.name("External IP")
.defaultDescription("The public IP address assigned to the instance.")
.sensitive(false)
.build()) {
@Override
protected String getPropertyValue(Instance instance, Disk bootDisk) {
List<NetworkInterface> networkInterfaceList = instance.getNetworkInterfaces();
if (networkInterfaceList != null && networkInterfaceList.size() > 0) {
List<AccessConfig> accessConfigList = networkInterfaceList.get(0).getAccessConfigs();
if (accessConfigList != null && accessConfigList.size() > 0) {
return accessConfigList.get(0).getNatIP();
}
}
return null;
}
};
/**
* The display property.
*/
private final DisplayProperty displayProperty;
/**
* Creates a Google instance display property token with the specified parameters.
*
* @param displayProperty the display property
*/
GoogleComputeInstanceDisplayPropertyToken(DisplayProperty displayProperty) {
this.displayProperty = displayProperty;
}
/**
* Returns the value of the property from the specified instance.
*
* @param instance the instance
* @return the value of the property from the specified instance
*/
protected abstract String getPropertyValue(Instance instance, Disk bootDisk);
@Override
public DisplayProperty unwrap() {
return displayProperty;
}
}
public static final Type TYPE = new ResourceType("GoogleComputeInstance");
private Disk bootDisk = null;
/**
* Creates a Google compute instance with the specified parameters.
*
* @param template the template from which the instance was created
* @param instanceId the instance identifier
* @param instanceDetails the provider-specific instance details
* @throws IllegalArgumentException if the instance does not have a valid private IP address
*/
protected GoogleComputeInstance(GoogleComputeInstanceTemplate template,
String instanceId, Instance instanceDetails, Disk bootDisk) {
super(template, instanceId, getPrivateIpAddress(instanceDetails), null, instanceDetails);
this.bootDisk = bootDisk;
}
/**
* Returns the private IP address of the specified Google instance.
*
* @param instance the instance
* @return the private IP address of the specified Google instance
* @throws IllegalArgumentException if the instance does not have a valid private IP address
*/
private static InetAddress getPrivateIpAddress(Instance instance) {
Preconditions.checkNotNull(instance, "instance is null");
List<NetworkInterface> networkInterfaceList = instance.getNetworkInterfaces();
if (networkInterfaceList == null || networkInterfaceList.isEmpty()) {
throw new IllegalArgumentException("No network interfaces found for instance '" + instance.getName() + "'.");
} else {
try {
return InetAddress.getByName(networkInterfaceList.get(0).getNetworkIP());
} catch (UnknownHostException e) {
throw new IllegalArgumentException("Invalid private IP address", e);
}
}
}
@Override
public Type getType() {
return TYPE;
}
public Disk getBootDisk() {
return bootDisk;
}
@Override
public Map<String, String> getProperties() {
Map<String, String> properties = Maps.newHashMap();
Instance instance = unwrap();
if (instance != null) {
for (GoogleComputeInstanceDisplayPropertyToken propertyToken : GoogleComputeInstanceDisplayPropertyToken.values()) {
properties.put(propertyToken.unwrap().getDisplayKey(), propertyToken.getPropertyValue(instance, bootDisk));
}
}
return properties;
}
/**
* Sets the Google instance.
*
* @param instance the Google instance
* @throws IllegalArgumentException if the instance does not have a valid private IP address
*/
protected void setInstance(Instance instance) {
super.setDetails(instance);
InetAddress privateIpAddress = getPrivateIpAddress(instance);
setPrivateIpAddress(privateIpAddress);
}
}