package com.sequenceiq.cloudbreak.cloud.gcp;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
import com.google.api.services.compute.Compute;
import com.google.api.services.compute.model.Instance;
import com.sequenceiq.cloudbreak.cloud.context.AuthenticatedContext;
import com.sequenceiq.cloudbreak.cloud.context.CloudContext;
import com.sequenceiq.cloudbreak.cloud.exception.CloudOperationNotSupportedException;
import com.sequenceiq.cloudbreak.cloud.gcp.util.GcpStackUtil;
import com.sequenceiq.cloudbreak.cloud.model.CloudCredential;
import com.sequenceiq.cloudbreak.cloud.model.CloudInstance;
import com.sequenceiq.cloudbreak.cloud.model.CloudVmInstanceStatus;
import com.sequenceiq.cloudbreak.cloud.model.InstanceStatus;
import com.sequenceiq.cloudbreak.cloud.template.AbstractInstanceConnector;
@Service
public class GcpInstanceConnector extends AbstractInstanceConnector {
private static final Logger LOGGER = LoggerFactory.getLogger(GcpInstanceConnector.class);
@Value("${cb.gcp.hostkey.verify:}")
private boolean verifyHostKey;
@Override
public List<CloudVmInstanceStatus> check(AuthenticatedContext ac, List<CloudInstance> vms) {
List<CloudVmInstanceStatus> statuses = new ArrayList<>();
CloudCredential credential = ac.getCloudCredential();
CloudContext cloudContext = ac.getCloudContext();
Compute compute = GcpStackUtil.buildCompute(credential);
for (CloudInstance instance : vms) {
InstanceStatus status = InstanceStatus.UNKNOWN;
try {
Instance executeInstance = getInstance(cloudContext, credential, compute, instance.getInstanceId());
if ("RUNNING".equals(executeInstance.getStatus())) {
status = InstanceStatus.STARTED;
} else if ("TERMINATED".equals(executeInstance.getStatus())) {
status = InstanceStatus.STOPPED;
}
} catch (GoogleJsonResponseException e) {
if (e.getStatusCode() == HttpStatus.SC_NOT_FOUND) {
status = InstanceStatus.TERMINATED;
} else {
LOGGER.warn(String.format("Instance %s is not reachable", instance), e);
}
} catch (IOException e) {
LOGGER.warn(String.format("Instance %s is not reachable", instance), e);
}
statuses.add(new CloudVmInstanceStatus(instance, status));
}
return statuses;
}
@Override
public String getConsoleOutput(AuthenticatedContext authenticatedContext, CloudInstance vm) {
if (!verifyHostKey) {
throw new CloudOperationNotSupportedException("Host key verification is disabled on GCP");
}
CloudCredential credential = authenticatedContext.getCloudCredential();
try {
Compute.Instances.GetSerialPortOutput instanceGet = GcpStackUtil.buildCompute(credential).instances()
.getSerialPortOutput(GcpStackUtil.getProjectId(credential),
authenticatedContext.getCloudContext().getLocation().getAvailabilityZone().value(), vm.getInstanceId());
return instanceGet.execute().getContents();
} catch (Exception e) {
throw new GcpResourceException("Couldn't parse SSH fingerprint from console output.", e);
}
}
private Instance getInstance(CloudContext context, CloudCredential credential, Compute compute, String instanceName) throws IOException {
return compute.instances().get(GcpStackUtil.getProjectId(credential),
context.getLocation().getAvailabilityZone().value(), instanceName).execute();
}
}