/**
* Copyright (C) 2012-2015 Dell, Inc
* See annotations for authorship information
*
* ====================================================================
* 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 org.dasein.cloud.ci;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.annotation.Nonnull;
import org.dasein.cloud.CloudErrorType;
import org.dasein.cloud.CloudException;
import org.dasein.cloud.InternalException;
import org.dasein.cloud.ci.Topology.VLANDevice;
import org.dasein.cloud.ci.Topology.VMDevice;
import org.dasein.cloud.ci.TopologyProvisionOptions.Disk;
import org.dasein.cloud.ci.TopologyProvisionOptions.Network;
import org.dasein.cloud.compute.Architecture;
import org.dasein.cloud.compute.VirtualMachineProduct;
import org.dasein.cloud.google.Google;
import org.dasein.cloud.google.GoogleException;
import org.dasein.cloud.google.GoogleMethod;
import org.dasein.cloud.google.GoogleOperationType;
import org.dasein.cloud.google.compute.server.ServerSupport;
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
import com.google.api.services.compute.Compute.InstanceTemplates;
import com.google.api.services.compute.model.AccessConfig;
import com.google.api.services.compute.model.AttachedDisk;
import com.google.api.services.compute.model.AttachedDiskInitializeParams;
import com.google.api.services.compute.model.InstanceProperties;
import com.google.api.services.compute.model.InstanceTemplate;
import com.google.api.services.compute.model.InstanceTemplateList;
import com.google.api.services.compute.model.Metadata;
import com.google.api.services.compute.model.Metadata.Items;
import com.google.api.services.compute.model.NetworkInterface;
import com.google.api.services.compute.model.Operation;
import com.google.api.services.compute.model.Scheduling;
import com.google.api.services.compute.model.Tags;
public class GoogleTopologySupport extends AbstractTopologySupport<Google> {
private InstanceTemplates instanceTemplates = null;;
public GoogleTopologySupport(Google provider) {
super(provider);
try {
instanceTemplates = getProvider().getGoogleCompute().instanceTemplates();
} catch ( CloudException e ) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch ( InternalException e ) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public String getProviderTermForTopology(Locale locale) {
return "Instance Template";
}
@Override
public boolean isSubscribed() throws CloudException, InternalException {
return true;
}
@Override
public Iterable<Topology> listTopologies(TopologyFilterOptions options) throws CloudException, InternalException {
List<Topology> topologies = new ArrayList<Topology>();
try {
InstanceTemplateList templateList = instanceTemplates.list(getContext().getAccountNumber()).execute();
for (InstanceTemplate template : templateList.getItems()) {
InstanceProperties templateProperties = template.getProperties();
VMDevice vmDevices = null;
String machineType = templateProperties.getMachineType();
ServerSupport server = new ServerSupport(getProvider());
Iterable<VirtualMachineProduct> vmProducts = server.listProducts(Architecture.I64, "us-central1-f");
for (VirtualMachineProduct vmProduct: vmProducts) {
if (vmProduct.getName().equals(machineType)) {
vmDevices = VMDevice.getInstance(machineType, machineType, vmProduct.getCpuCount(), vmProduct.getRamSize(), (String) null);
}
}
List<NetworkInterface> networkInterfaces = templateProperties.getNetworkInterfaces();
String name = null;
String deviceId = null;
for (NetworkInterface networkInterface: networkInterfaces) {
deviceId = networkInterface.getNetwork();
name = deviceId.replaceAll(".*/", "");
}
Topology topology = Topology.getInstance(getContext().getAccountNumber(), null, template.getName(), TopologyState.ACTIVE, template.getName(), template.getDescription());
if (null != vmDevices) {
topology = topology.withVirtualMachines(vmDevices);
}
if ((null != name) && (null != deviceId)) {
topology = topology.withVLANs(VLANDevice.getInstance(deviceId, name));
}
if ((null == options) || (options.matches(topology))) {
topologies.add(topology);
}
}
} catch ( IOException e ) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return topologies;
}
@Override
public boolean createTopology(@Nonnull TopologyProvisionOptions withTopologyOptions) throws CloudException, InternalException {
InstanceTemplate newInstanceTemplate = new InstanceTemplate();
newInstanceTemplate.setName(getCapabilities().getTopologyNamingConstraints().convertToValidName(withTopologyOptions.getProductName(), Locale.US));
newInstanceTemplate.setDescription(withTopologyOptions.getProductDescription());
InstanceProperties instanceProperties = new InstanceProperties();
instanceProperties.setCanIpForward(withTopologyOptions.getCanIpForward());
instanceProperties.setDescription(withTopologyOptions.getProductDescription());
instanceProperties.setMachineType(withTopologyOptions.getMachineType());
List<Disk> disks = withTopologyOptions.getDiskArray();
List<AttachedDisk> attachedDisks = new ArrayList<AttachedDisk>();
for (Disk topologyDisk : disks) {
AttachedDisk disk = new AttachedDisk();
disk.setAutoDelete(topologyDisk.getAutoDelete());
disk.setBoot(topologyDisk.getBootable());
disk.setDeviceName(withTopologyOptions.getProductName());
AttachedDiskInitializeParams attachedDiskInitializeParams = new AttachedDiskInitializeParams();
attachedDiskInitializeParams.setSourceImage(topologyDisk.getDeviceSource());
attachedDiskInitializeParams.setDiskType(topologyDisk.getDeviceType().toString());
disk.setInitializeParams(attachedDiskInitializeParams);
attachedDisks.add(disk);
}
instanceProperties.setDisks(attachedDisks); //must provide at least one AttachedDisk definition.
List<Network> topologyNetworksList = withTopologyOptions.getNetworkArray();
List<NetworkInterface> networks = new ArrayList<NetworkInterface>();
for (Network topologyNetwork : topologyNetworksList) {
NetworkInterface networkInterface = new NetworkInterface();
networkInterface.setName(topologyNetwork.getNetworkName());
networkInterface.setNetwork(topologyNetwork.getNetworkSelfUrl());
List<TopologyProvisionOptions.AccessConfig> topologyNetworksAccessConfig = topologyNetwork.getAccessConfig();
List<AccessConfig> accessConfig = new ArrayList<AccessConfig>();
for (TopologyProvisionOptions.AccessConfig topologyAccessConfig : topologyNetworksAccessConfig) {
AccessConfig cfg = new AccessConfig();
cfg.setName(topologyAccessConfig.getName());
cfg.setKind(topologyAccessConfig.getKind());
cfg.setType(topologyAccessConfig.getType());
accessConfig.add(cfg);
}
networkInterface.setAccessConfigs(accessConfig);
networks.add(networkInterface);
}
instanceProperties.setNetworkInterfaces(networks);
Tags tags = new Tags();
tags.setItems(withTopologyOptions.getTags());
instanceProperties.setTags(tags);
String[] sshKeys = withTopologyOptions.getSshKeys();
Metadata metadata = new Metadata();
List<Items> metadataItems = new ArrayList<Items>();
for (String sshKey : sshKeys) {
Metadata.Items item = new Metadata.Items() ;
item.setKey("sshKeys");
item.setValue(sshKey);
metadataItems.add(item);
}
Map<String, String> metaDataItems = withTopologyOptions.getMetadata();
for (String itemKey : metaDataItems.keySet()) {
Metadata.Items item = new Metadata.Items() ;
item.setKey(itemKey);
item.setValue(metaDataItems.get(itemKey));
metadataItems.add(item);
}
metadata.setItems(metadataItems);
instanceProperties.setMetadata(metadata);
Scheduling scheduling = new Scheduling();
scheduling.setAutomaticRestart(withTopologyOptions.getAutomaticRestart());
scheduling.setOnHostMaintenance(withTopologyOptions.getMaintenenceAction().toString());
instanceProperties.setScheduling(scheduling);
/*
List<ServiceAccount> serviceAccounts = new ArrayList<ServiceAccount>();
ServiceAccount serviceAccount = new ServiceAccount();
serviceAccount.setEmail("email");
List<String> scopes = new ArrayList<String>();
serviceAccount.setScopes(scopes);
serviceAccounts.add(serviceAccount);
instanceProperties.setServiceAccounts(serviceAccounts);
*/
newInstanceTemplate.setProperties(instanceProperties);
try {
Operation job = instanceTemplates.insert(getContext().getAccountNumber(), newInstanceTemplate).execute();
GoogleMethod method = new GoogleMethod(getProvider());
method.getOperationComplete(getContext(), job, GoogleOperationType.GLOBAL_OPERATION, "", "");
} catch (IOException ex) {
if (ex.getClass() == GoogleJsonResponseException.class) {
GoogleJsonResponseException gjre = (GoogleJsonResponseException)ex;
throw new GoogleException(CloudErrorType.GENERAL, gjre.getStatusCode(), gjre.getContent(), gjre.getDetails().getMessage());
} else
throw new CloudException(ex.getMessage());
}
return true;
}
@Override
public boolean removeTopologies(@Nonnull String[] topologyIds) throws CloudException, InternalException {
for (String topologyName: topologyIds) {
try {
Operation job = instanceTemplates.delete(getContext().getAccountNumber(), topologyName).execute();
GoogleMethod method = new GoogleMethod(getProvider());
method.getOperationComplete(getContext(), job, GoogleOperationType.GLOBAL_OPERATION, "", "");
} catch (IOException ex) {
if (ex.getClass() == GoogleJsonResponseException.class) {
GoogleJsonResponseException gjre = (GoogleJsonResponseException)ex;
throw new GoogleException(CloudErrorType.GENERAL, gjre.getStatusCode(), gjre.getContent(), gjre.getDetails().getMessage());
} else
throw new CloudException(ex.getMessage());
}
}
return true;
}
private transient volatile GCETopologyCapabilities capabilities;
@Override
public @Nonnull GCETopologyCapabilities getCapabilities() throws CloudException, InternalException {
if( capabilities == null ) {
capabilities = new GCETopologyCapabilities(getProvider());
}
return capabilities;
}
}