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

com.vmware.photon.controller.model.adapters.util.BaseAdapterContext Maven / Gradle / Ivy

The newest version!
/*
 * 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.util;

import static com.vmware.photon.controller.model.util.PhotonModelUriUtils.createInventoryUri;

import java.net.URI;
import java.util.function.Function;
import java.util.logging.Level;

import com.vmware.photon.controller.model.adapterapi.ResourceRequest;
import com.vmware.photon.controller.model.resources.ComputeService.ComputeStateWithDescription;
import com.vmware.photon.controller.model.resources.EndpointService;
import com.vmware.xenon.common.DeferredResult;
import com.vmware.xenon.common.Operation;
import com.vmware.xenon.common.StatelessService;
import com.vmware.xenon.common.UriUtils;
import com.vmware.xenon.services.common.AuthCredentialsService.AuthCredentialsServiceState;

/**
 * Base class for contexts used by adapters. It {@link #populateBaseContext(BaseAdapterStage) loads}:
 * 
    *
  • {@link ComputeStateWithDescription child}
  • *
  • {@link ComputeStateWithDescription parent}
  • *
  • {@link AuthCredentialsServiceState parentAuth}
  • *
  • {@link EndpointService.EndpointState endpoint}
  • *
  • {@link AuthCredentialsServiceState endpointAuth}
  • *
*/ public class BaseAdapterContext> { /** * Default version of {@link BaseAdapterContext} used when there's no need to extend from base. */ public static final class DefaultAdapterContext extends BaseAdapterContext { public DefaultAdapterContext(StatelessService service, ResourceRequest resourceRequest) { super(service, resourceRequest); } } public enum BaseAdapterStage { VMDESC, PARENTDESC, ENDPOINTSTATE, PARENTAUTH, CUSTOMIZE } public final StatelessService service; public final URI resourceReference; /** * URI reference of endpoint. This value is not expected to be null but to support backward compatibility * it will read endpoint from parent resource if this value is null. */ public URI endpointReference; /** * The compute state that is to be provisioned. */ public ComputeStateWithDescription child; public ComputeStateWithDescription parent; public EndpointService.EndpointState endpoint; @Deprecated public AuthCredentialsServiceState parentAuth; // This will be same as parentAuth. Since the auth details will be read from endpoint but not from computeHost, // naming it as appropriate. public AuthCredentialsServiceState endpointAuth; /** * The error that has occurred while transitioning to the error stage. */ public Throwable error; /** * Used to store the calling operation. */ public Operation operation; public TaskManager taskManager; /** * @param service * The service that is creating and using this context. * @param resourceRequest * The ResourceRequest that is used to start the * {@link #populateBaseContext(BaseAdapterStage) state machine}. *
    *
  • If {@code populateContext} is called with {@code BaseAdapterStage#VMDESC} then * this should point to child resource.
  • *
  • If {@code populateContext} is called with {@code BaseAdapterStage#PARENTDESC} * then this should point to parent resource.
  • *
  • If {@code populateContext} is called with {@code BaseAdapterStage#PARENTAUTH} * then this should point to parent auth resource.
  • *
  • If {@code populateContext} is called with {@code BaseAdapterStage#ENDPOINTSTATE} * then this should point to endpoint resource.
  • *
*/ public BaseAdapterContext(StatelessService service, ResourceRequest resourceRequest) { this.service = service; this.resourceReference = resourceRequest.resourceReference; this.endpointReference = resourceRequest.endpointLinkReference; this.taskManager = new TaskManager(this.service, resourceRequest.taskReference, resourceRequest.resourceLink()); } public final DeferredResult populateBaseContext(BaseAdapterStage stage) { if (stage == null) { stage = BaseAdapterStage.VMDESC; } switch (stage) { case VMDESC: return getVMDescription(self()) .thenApply(log("getVMDescription")) .thenCompose(c -> populateBaseContext(BaseAdapterStage.PARENTDESC)); case PARENTDESC: return getParentDescription(self()) .thenApply(log("getParentDescription")) .thenCompose(c -> populateBaseContext(BaseAdapterStage.ENDPOINTSTATE)); case ENDPOINTSTATE: return getEndPointState(self()) .thenApply(log("getEndPointState")) .thenCompose(c -> populateBaseContext(BaseAdapterStage.PARENTAUTH)); case PARENTAUTH: return getParentAuth(self()) .thenApply(log("getParentAuth")) .thenCompose(c -> populateBaseContext(BaseAdapterStage.CUSTOMIZE)); case CUSTOMIZE: return customizeBaseContext(self()).thenApply(log("customizeBaseContext")); default: return DeferredResult.completed(self()); } } /** * Isolate all cases when this instance should be cast to T. For internal use only. */ @SuppressWarnings("unchecked") protected T self() { return (T) this; } /** * Use this to log success after completing async execution stage. */ protected Function log(String stage) { return (ctx) -> { ctx.service.log(Level.FINE, "%s.%s: SUCCESS", this.getClass().getSimpleName(), stage); return ctx; }; } /** * Populate context with child {@code ComputeStateWithDescription}. */ protected DeferredResult getVMDescription(T context) { URI ref = ComputeStateWithDescription.buildUri(context.resourceReference); Operation op = Operation.createGet(ref); return context.service .sendWithDeferredResult(op, ComputeStateWithDescription.class) .thenApply(state -> { context.child = state; return context; }); } /** * Populate context with parent {@code ComputeStateWithDescription}. *

*

* By default {@code context.child.parentLink} is used as source. */ protected DeferredResult getParentDescription(T context) { URI ref = context.child != null // 'child' is already resolved so used it ? UriUtils.buildUri(context.service.getHost(), context.child.parentLink) // state machine starts from here so resRef should point to the parent : context.resourceReference; ref = ComputeStateWithDescription.buildUri(ref); Operation op = Operation.createGet(ref); return context.service .sendWithDeferredResult(op, ComputeStateWithDescription.class) .thenApply(state -> { context.parent = state; return context; }); } /** * Populate context with {@code EndpointState}. */ protected DeferredResult getEndPointState(T context) { // Fallback on compute endpointLink, if it is not set explicitly (to support backward compatibility) if (context.endpointReference == null && context.parent != null) { // first try with endpointLinks as endpointLink may be invalid in the case of de-dup if (context.parent.endpointLinks != null && !context.parent.endpointLinks.isEmpty()) { context.endpointReference = createInventoryUri(context.service.getHost(), context .parent.endpointLinks.iterator().next()); } else { context.endpointReference = createInventoryUri(context.service.getHost(), context.parent.endpointLink); } } if (context.endpointReference != null) { Operation op = Operation.createGet(context.endpointReference); return context.service .sendWithDeferredResult(op, EndpointService.EndpointState.class) .thenApply(state -> { context.endpoint = state; return context; }); } else { return DeferredResult.completed(context); } } /** * Populate context with endpoint {@code AuthCredentialsServiceState}. * * @see #getParentAuthRef(BaseAdapterContext) for any customization. */ protected DeferredResult getParentAuth(T context) { URI parentAuthRef = getParentAuthRef(context); Operation op = Operation.createGet(parentAuthRef); return context.service .sendWithDeferredResult(op, AuthCredentialsServiceState.class) .thenApply(state -> { context.parentAuth = state; context.endpointAuth = state; return context; }); } /** * Descendants might implement this hook to provide custom link to endpoint auth. */ protected URI getParentAuthRef(T context) { return context.endpoint != null // 'parent' is already resolved so used it ? createInventoryUri(context.service.getHost(), context.endpoint.authCredentialsLink) // state machine starts from here so resRef should point to the parentAuth : createInventoryUri(context.service.getHost(), context.resourceReference); } /** * Hook that might be implemented by descendants to extend * {@link #populateBaseContext(BaseAdapterStage)} populate logic} and customize the context. */ protected DeferredResult customizeBaseContext(T context) { return DeferredResult.completed(context); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy