/**
* 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.google;
import java.io.IOException;
import javax.annotation.Nonnull;
import org.apache.log4j.Logger;
import org.dasein.cloud.CloudErrorType;
import org.dasein.cloud.CloudException;
import org.dasein.cloud.InternalException;
import org.dasein.cloud.ProviderContext;
import org.dasein.util.CalendarWrapper;
import com.google.api.services.compute.Compute;
import com.google.api.services.compute.model.Operation;
import com.google.api.services.replicapool.Replicapool;
import com.google.api.services.replicapool.model.Operation.Error.Errors;
import com.google.api.services.sqladmin.SQLAdmin;
import com.google.api.services.sqladmin.model.OperationError;
import org.dasein.cloud.google.GoogleOperationType;
/**
* Represents the interaction point between Dasein Cloud and the underlying REST API.
* @author Drew Lyall
* @version 2014.03 initial version
* @since 2014.03
*/
public class GoogleMethod {
static private final Logger logger = Google.getLogger(GoogleMethod.class);
static private final Logger wire = Google.getWireLogger(GoogleMethod.class);
private Google provider;
public GoogleMethod(@Nonnull Google provider) {
this.provider = provider;
}
public @Nonnull String getOperationTarget(@Nonnull ProviderContext ctx, @Nonnull Operation job, @Nonnull GoogleOperationType operationType, String regionId, String dataCenterId, boolean getLink)throws CloudException, InternalException{
long timeout = System.currentTimeMillis() + (CalendarWrapper.MINUTE * 20L);
while(timeout > System.currentTimeMillis()) {
if(job.getError() != null){
for(Operation.Error.Errors error : job.getError().getErrors()){
throw new CloudException("An error occurred: " + error.getMessage());
}
}
else if(job.getStatus().equals("DONE")){
if(getLink) return job.getTargetLink();
else return job.getTargetLink().substring(job.getTargetLink().lastIndexOf("/") + 1);
}
try{
Thread.sleep(1000L);
}
catch(InterruptedException ignore){}
try{
Compute gce = provider.getGoogleCompute();
switch(operationType){
case GLOBAL_OPERATION:{
job = gce.globalOperations().get(ctx.getAccountNumber(), job.getName()).execute();
break;
}
case REGION_OPERATION:{
job = gce.regionOperations().get(ctx.getAccountNumber(), regionId, job.getName()).execute();
break;
}
case ZONE_OPERATION:{
job = gce.zoneOperations().get(ctx.getAccountNumber(), dataCenterId, job.getName()).execute();
break;
}
}
}
catch(IOException ex){
logger.error(ex.getMessage());
}
}
throw new CloudException(CloudErrorType.COMMUNICATION, 408, "", "System timed out waiting for Operation to complete");
}
public @Nonnull boolean getOperationComplete(ProviderContext ctx, Operation job, GoogleOperationType operationType, String regionId, String dataCenterId)throws CloudException, InternalException{
long timeout = System.currentTimeMillis() + (CalendarWrapper.MINUTE * 20L);
while(timeout > System.currentTimeMillis()) {
if(job.getError() != null){
for(Operation.Error.Errors error : job.getError().getErrors()){
throw new CloudException("An error occurred: " + error.getMessage());
}
}
else if(job.getStatus().equals("DONE")){
return true;
}
try{
Thread.sleep(1000L);
}
catch(InterruptedException ignore){}
try{
Compute gce = provider.getGoogleCompute();
switch(operationType){
case GLOBAL_OPERATION:{
job = gce.globalOperations().get(ctx.getAccountNumber(), job.getName()).execute();
break;
}
case REGION_OPERATION:{
job = gce.regionOperations().get(ctx.getAccountNumber(), regionId, job.getName()).execute();
break;
}
case ZONE_OPERATION:{
job = gce.zoneOperations().get(ctx.getAccountNumber(), dataCenterId, job.getName()).execute();
break;
}
}
}
catch(IOException ex){
}
}
throw new CloudException(CloudErrorType.COMMUNICATION, 408, "", "System timed out waiting for Operation to complete");
}
/*
* RDS gets its blocking method!
*/
public void getRDSOperationComplete(ProviderContext ctx, String operation) throws CloudException, InternalException {
SQLAdmin sqlAdmin = provider.getGoogleSQLAdmin();
long timeout = System.currentTimeMillis() + (CalendarWrapper.MINUTE * 20L);
while(timeout > System.currentTimeMillis()) {
com.google.api.services.sqladmin.model.Operation instanceOperation = null;
try {
instanceOperation = sqlAdmin.operations().get(ctx.getAccountNumber(), operation).execute();
} catch ( IOException e ) {
logger.warn("getRDSOperationComplete Ignoring " + e.getMessage());
}
if (instanceOperation.getError() != null) {
for (OperationError error : instanceOperation.getError().getErrors()) {
throw new CloudException("An error occurred: " + error.getCode() + " : " + error.getKind());
}
} else if (instanceOperation.getStatus().equals("DONE")) {
return;
}
try {
Thread.sleep(1000L);
} catch (InterruptedException ignore) {}
}
throw new CloudException(CloudErrorType.COMMUNICATION, 408, "", "System timed out waiting for Operation to complete");
}
public void getRDSOperationCompleteLong(ProviderContext ctx, String operation) throws CloudException, InternalException {
SQLAdmin sqlAdmin = provider.getGoogleSQLAdmin();
if (null == ctx) {
throw new InternalException("ctx cannot be null");
}
if (null == operation) {
throw new InternalException("operation cannot be null");
}
long timeout = System.currentTimeMillis() + (CalendarWrapper.MINUTE * 20L);
while (timeout > System.currentTimeMillis()) {
com.google.api.services.sqladmin.model.Operation instanceOperation = null;
try {
instanceOperation = sqlAdmin.operations().get(ctx.getAccountNumber(), operation).execute();
} catch ( IOException e ) {
logger.warn("Ignoring sqlAdmin.operations().get() exception: " + e.getMessage());
}
if (null != instanceOperation) {
if (null != instanceOperation.getError()) {
for (OperationError error : instanceOperation.getError().getErrors()) {
throw new CloudException("An error occurred: " + error.getCode() + " : " + error.getKind());
}
} else if (instanceOperation.getStatus().equals("DONE")) {
return;
}
}
try {
Thread.sleep(30000L); // 30 seconds
} catch (InterruptedException ignore) {}
}
throw new CloudException(CloudErrorType.COMMUNICATION, 408, "", "System timed out waiting for Operation to complete");
}
public @Nonnull boolean getCIOperationComplete(ProviderContext ctx, com.google.api.services.replicapool.model.Operation job, GoogleOperationType operationType, String regionId, String dataCenterId) throws CloudException, InternalException {
long timeout = System.currentTimeMillis() + (CalendarWrapper.MINUTE * 20L);
Replicapool rp;
try {
rp = provider.getGoogleReplicapool();
} catch ( InternalException e ) {
throw new InternalException("Cannot get Compute(google)");
}
while (timeout > System.currentTimeMillis()) {
try {
job = rp.zoneOperations().get(ctx.getAccountNumber(), dataCenterId, job.getName()).execute();
} catch(IOException ex) {
System.out.println(ex);
}
if (job.getError() != null) {
for (Errors error : job.getError().getErrors()) {
throw new CloudException("An error occurred: " + error.getMessage());
}
}
else if (job.getStatus().equals("DONE")) {
return true;
}
try {
Thread.sleep(1000L);
} catch (InterruptedException ignore) { }
}
throw new CloudException(CloudErrorType.COMMUNICATION, 408, "", "System timed out waiting for Operation to complete");
}
}