All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.vmware.photon.controller.model.adapters.azure.utils.AzureDecommissionCallback Maven / Gradle / Ivy

/*
 * Copyright (c) 2015-2016 VMware, Inc. All Rights Reserved.
 *
 * 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.vmware.photon.controller.model.adapters.azure.utils;

import java.util.concurrent.TimeUnit;

import com.microsoft.rest.ServiceCallback;

import com.vmware.photon.controller.model.adapters.azure.AzureAsyncCallback;
import com.vmware.photon.controller.model.adapters.azure.utils.AzureUtils.ExponentialRetryStrategy;
import com.vmware.photon.controller.model.adapters.azure.utils.AzureUtils.RetryStrategy;
import com.vmware.xenon.common.DeferredResult;
import com.vmware.xenon.common.StatelessService;

/**
 * Use this Azure callback in case of Azure decommission call (such as delete Resource Group) with a
 * method signature similar to:
 * {@code ServiceCall deleteAsync(..., ServiceCallback deleteCallback)}
 * 

* This callback is responsible to wait until the resource does not exist on the Azure. */ public abstract class AzureDecommissionCallback extends AzureDeferredResultServiceCallback { private static final String MSG = "WAIT decommission to succeed"; // Used by waitProvisioningToSucceed logic to signal completion private final DeferredResult waitDecommissionToSucceed = new DeferredResult<>(); private final RetryStrategy retryStrategy; /** * Create a new {@link AzureDecommissionCallback}. */ public AzureDecommissionCallback(StatelessService service, String message) { super(service, message); // It seems that 'delete' takes time so increase // maxDelayTime to 15secs and maxWaitTime to 20mins ExponentialRetryStrategy expRetryStrategy = new ExponentialRetryStrategy(); expRetryStrategy.maxDelayMillis = TimeUnit.SECONDS.toMillis(15); expRetryStrategy.maxWaitMillis = TimeUnit.MINUTES.toMillis(20); this.retryStrategy = expRetryStrategy; } @Override protected final DeferredResult consumeSuccess(Void body) { // Assume the resource STILL EXISTs upon deleteAsync method completion final Boolean existence = true; return waitDecommissionToSucceed(existence).thenCompose(this::consumeDecommissionSuccess); } /** * Hook to be implemented by descendants to handle 'Succeeded' Azure resource decommission. * Since implementations might decide to trigger/initiate sync operation they are required to * return {@link DeferredResult} to track its completion. *

* This call is introduced by analogy with {@link #consumeSuccess(Object)}. */ protected abstract DeferredResult consumeDecommissionSuccess(Void body); /** * This Runnable abstracts/models the Azure 'check resource existence' call. * * @param checkExistenceCallback * The special callback that should be used while creating the Azure 'check resource * existence' call. */ protected abstract Runnable checkExistenceCall( ServiceCallback checkExistenceCallback); /** * The core logic that waits for decommission to succeed. It polls periodically Azure for * resource existence. */ private DeferredResult waitDecommissionToSucceed(Boolean existence) { this.service.logFine(this.message + ": existence = " + existence); long nextDelayMillis = this.retryStrategy.nextDelayMillis(); if (!existence) { // checkExistence has returned FALSE so resource has been decommissioned successfully // Completes 'waitDecommissionToSucceed' task with SUCCESS this.waitDecommissionToSucceed.complete((Void) null); } else if (nextDelayMillis == RetryStrategy.EXHAUSTED) { // Max number of re-tries has reached. // Completes 'waitDecommissionToSucceed' task with EXCEPTION. this.waitDecommissionToSucceed.fail(new IllegalStateException( MSG + ": max wait time (" + TimeUnit.MILLISECONDS.toSeconds(this.retryStrategy.maxWaitMillis) + " secs) exceeded")); } else { // Retry one more time this.service.getHost().schedule( checkExistenceCall(new CheckExistenceCallback()), nextDelayMillis, TimeUnit.MILLISECONDS); } return this.waitDecommissionToSucceed; } /** * Specialization of Azure callback used by {@link AzureDecommissionCallback} to handle 'check * resource existence' call. Should be passed to Azure SDK methods with a signature similar to: * {@code ServiceCall checkExistenceAsync(..., ServiceCallback checkExistenceCallback)} */ private class CheckExistenceCallback extends AzureAsyncCallback { @Override public void onError(Throwable e) { e = new IllegalStateException(MSG + ": FAILED", e); AzureDecommissionCallback.this.waitDecommissionToSucceed.fail(e); } @Override public void onSuccess(Boolean result) { AzureDecommissionCallback.this .waitDecommissionToSucceed(result); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy