diff options
3 files changed, 533 insertions, 487 deletions
diff --git a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/onap/appc/adapter/iaas/provider/operation/impl/DettachVolumeServer.java b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/onap/appc/adapter/iaas/provider/operation/impl/DettachVolumeServer.java index d9b30cbb8..5874939b3 100644 --- a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/onap/appc/adapter/iaas/provider/operation/impl/DettachVolumeServer.java +++ b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/onap/appc/adapter/iaas/provider/operation/impl/DettachVolumeServer.java @@ -37,21 +37,29 @@ import com.att.eelf.configuration.EELFManager; import com.att.eelf.i18n.EELFResourceManager; import java.util.List; import java.util.Map; +import java.util.Map.Entry; +import java.util.Iterator; import org.glassfish.grizzly.http.util.HttpStatus; import org.onap.appc.Constants; import org.onap.appc.adapter.iaas.ProviderAdapter; import org.onap.appc.adapter.iaas.impl.IdentityURL; import org.onap.appc.adapter.iaas.impl.RequestContext; import org.onap.appc.adapter.iaas.impl.RequestFailedException; +import org.onap.appc.configuration.Configuration; +import org.onap.appc.configuration.ConfigurationFactory; import org.onap.appc.adapter.iaas.impl.VMURL; import org.onap.appc.adapter.iaas.provider.operation.common.enums.Operation; import org.onap.appc.adapter.iaas.provider.operation.impl.base.ProviderServerOperation; import org.onap.appc.exceptions.APPCException; +import com.att.cdp.exceptions.TimeoutException; +import com.att.cdp.openstack.util.ExceptionMapper; import org.onap.appc.i18n.Msg; +import com.woorea.openstack.base.client.OpenStackBaseException; import org.onap.ccsdk.sli.core.sli.SvcLogicContext; public class DettachVolumeServer extends ProviderServerOperation { private final EELFLogger logger = EELFManager.getInstance().getLogger(DettachVolumeServer.class); + private static final Configuration config = ConfigurationFactory.getConfiguration(); @Override protected ModelObject executeProviderOperation(Map<String, String> params, SvcLogicContext context) @@ -87,31 +95,32 @@ public class DettachVolumeServer extends ProviderServerOperation { logger.debug(Msg.SERVER_FOUND, vmUrl, context.getTenantName(), server.getStatus().toString()); Context contx = server.getContext(); ComputeService service = contx.getComputeService(); - VolumeService volumeService = contx.getVolumeService(); - logger.info("collecting volume status for volume -id: " + volumeId); - List<Volume> volumes = volumeService.getVolumes(); Volume volume = new Volume(); - logger.info("Size of volume list: " + volumes.size()); - if (volumes != null && !volumes.isEmpty()) { - if (volumes.contains(volumeId)) { - volume.setId(volumeId); - logger.info("Ready to Detach Volume from the server: " + Volume.Status.DETACHING); - service.detachVolume(server, volume); - logger.info("Volume status after performing detach: " + volume.getStatus()); - if (validateDetach(volumeService, volumeId)) { - doSuccess(requestContext); - } else { - String msg = "Volume with volume id " + volumeId + " cannot be detached "; - ctx.setAttribute("VOLUME_STATUS", "FAILURE"); - doFailure(requestContext, HttpStatus.NOT_IMPLEMENTED_501, msg); - logger.info("unable to detach volume from the server"); - } - } else { - String msg = "Volume with volume id " + volumeId + " cannot be detached as it doesn't exists"; + VolumeService vs = contx.getVolumeService(); + Volume s = vs.getVolume(volumeId); + boolean flag = false; + if (validateDetach(service, vm.getServerId(), volumeId)) { + volume.setId(volumeId); + logger.info("Ready to Detach Volume from the server:"); + service.detachVolume(server, volume); + flag = true; + } else { + String msg = "Volume with volume id " + volumeId + " cannot be detached as it does not exists"; + logger.info("Volume doesnot exists:"); + ctx.setAttribute("VOLUME_STATUS", "FAILURE"); + doFailure(requestContext, HttpStatus.METHOD_NOT_ALLOWED_405, msg); + flag = false; + } + if (flag) { + if (validateDetach(requestContext, service, vm.getServerId(), volumeId)) { + String msg = "Volume with volume id " + volumeId + " cannot be detached "; ctx.setAttribute("VOLUME_STATUS", "FAILURE"); - doFailure(requestContext, HttpStatus.NOT_IMPLEMENTED_501, msg); + doFailure(requestContext, HttpStatus.CONFLICT_409, msg); + } else { + logger.info("status of detaching volume"); + ctx.setAttribute("VOLUME_STATUS", "SUCCESS"); + doSuccess(requestContext); } - logger.info("volumestatus:" + ctx.getAttribute("VOLUME_STATUS")); } context.close(); } else { @@ -125,24 +134,85 @@ public class DettachVolumeServer extends ProviderServerOperation { logger.error("An error occurred when processing the request", e); doFailure(requestContext, e.getStatus(), e.getMessage()); } catch (Exception e) { - String msg = EELFResourceManager.format(Msg.SERVER_OPERATION_EXCEPTION, e, e.getClass().getSimpleName(), + String msg = EELFResourceManager.format(Msg.DETTACHINGVOLUME_SERVER, e, e.getClass().getSimpleName(), DETACHVOLUME_SERVICE.toString(), vmUrl, tenantName); logger.error(msg, e); + try { + ExceptionMapper.mapException((OpenStackBaseException) e); + } catch (ZoneException e1) { + logger.error(e1.getMessage()); + } + doFailure(requestContext, HttpStatus.INTERNAL_SERVER_ERROR_500, msg); } return server; } - protected boolean validateDetach(VolumeService volumeService, String volId) + protected boolean validateDetach(ComputeService ser, String vm, String volumeId) + throws RequestFailedException, ZoneException { + boolean flag = false; + Map<String, String> map = ser.getAttachments(vm); + if (map != null && !(map.isEmpty())) { + Iterator<Entry<String, String>> it = map.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry volumes = (Map.Entry) it.next(); + logger.info("volumes available in before detach"); + logger.info("device" + volumes.getKey() + "volume" + volumes.getValue()); + if (volumes.getValue().equals(volumeId)) { + flag = true; + } + } + } + logger.info("DettachVolume Flag" + flag); + return flag; + } + + protected boolean validateDetach(RequestContext rc, ComputeService ser, String vm, String volumeId) throws RequestFailedException, ZoneException { boolean flag = false; - List<Volume> volumes = volumeService.getVolumes(); - if (!volumes.contains(volId)) { - flag = true; - } else { - flag = false; + String msg = null; + config.setProperty(Constants.PROPERTY_RETRY_DELAY, "10"); + config.setProperty(Constants.PROPERTY_RETRY_LIMIT, "30"); + while (rc.attempt()) { + Map<String, String> map = ser.getAttachments(vm); + if (map != null && !(map.isEmpty())) { + Iterator<Entry<String, String>> it = map.entrySet().iterator(); + logger.info("volumes available after detach "); + while (it.hasNext()) { + Map.Entry volumes = (Map.Entry) it.next(); + logger.info(" devices " + volumes.getKey() + " volumes" + volumes.getValue()); + if (volumes.getValue().equals(volumeId)) { + logger.info("Device" + volumes.getKey() + "Volume" + volumes.getValue()); + flag = true; + break; + } else { + flag = false; + } + logger.info("Dettachvolume flag-->" + flag+"Attempts"+rc.getAttempts()); + } + if (flag) { + rc.delay(); + } else { + flag = false; + break; + } } - logger.info("validateDetach flag-->" + flag); + else + { + flag = false; + logger.info( rc.getAttempts() + "No.of attempts"); + break; + } + } + if ((rc.getAttempts() == 30) && (!flag)) { + msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, Long.toString(rc.getRetryDelay()), + Integer.toString(rc.getAttempts()), Integer.toString(rc.getRetryLimit())); + logger.error(msg); + logger.info(msg); + throw new TimeoutException(msg); + } + logger.info("DettachVolume Flag -->" + flag); return flag; } + } diff --git a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/onap/appc/adapter/iaas/provider/operation/impl/MigrateServer.java b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/onap/appc/adapter/iaas/provider/operation/impl/MigrateServer.java index b93511ae2..cb08c7742 100644 --- a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/onap/appc/adapter/iaas/provider/operation/impl/MigrateServer.java +++ b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/onap/appc/adapter/iaas/provider/operation/impl/MigrateServer.java @@ -56,7 +56,7 @@ import java.util.Collection; import java.util.Date; import java.util.Map; import java.util.TimeZone; - +import java.util.Iterator; import static org.onap.appc.adapter.iaas.provider.operation.common.enums.Operation.MIGRATE_SERVICE; import static org.onap.appc.adapter.utils.Constants.ADAPTER_NAME; diff --git a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/onap/appc/adapter/iaas/provider/operation/impl/base/ProviderOperation.java b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/onap/appc/adapter/iaas/provider/operation/impl/base/ProviderOperation.java index 2a48e27b6..87d287271 100644 --- a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/onap/appc/adapter/iaas/provider/operation/impl/base/ProviderOperation.java +++ b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/onap/appc/adapter/iaas/provider/operation/impl/base/ProviderOperation.java @@ -1,456 +1,432 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP : APPC - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Copyright (C) 2017 Amdocs - * ============================================================================= - * 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. - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - * ============LICENSE_END========================================================= - */ - -package org.onap.appc.adapter.iaas.provider.operation.impl.base; - -import static com.att.eelf.configuration.Configuration.MDC_SERVICE_NAME; -import static org.onap.appc.adapter.iaas.provider.operation.common.constants.Constants.MDC_ADAPTER; -import static org.onap.appc.adapter.iaas.provider.operation.common.constants.Constants.MDC_SERVICE; - -import com.att.cdp.exceptions.ZoneException; -import com.att.cdp.zones.Context; -import com.att.cdp.zones.model.ModelObject; -import com.att.cdp.zones.model.Server; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; -import com.att.eelf.i18n.EELFResourceManager; -import java.net.URI; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.regex.Pattern; -import org.glassfish.grizzly.http.util.HttpStatus; -import org.onap.appc.adapter.iaas.ProviderAdapter; -import org.onap.appc.adapter.iaas.impl.IdentityURL; -import org.onap.appc.adapter.iaas.impl.ProviderCache; -import org.onap.appc.adapter.iaas.impl.RequestContext; -import org.onap.appc.adapter.iaas.impl.RequestFailedException; -import org.onap.appc.adapter.iaas.impl.TenantCache; -import org.onap.appc.adapter.iaas.impl.VMURL; -import org.onap.appc.adapter.iaas.provider.operation.api.IProviderOperation; -import org.onap.appc.adapter.iaas.provider.operation.common.constants.Constants; -import org.onap.appc.adapter.iaas.provider.operation.common.enums.Outcome; -import org.onap.appc.configuration.Configuration; -import org.onap.appc.configuration.ConfigurationFactory; -import org.onap.appc.exceptions.APPCException; -import org.onap.appc.i18n.Msg; -import org.onap.appc.pool.Pool; -import org.onap.appc.pool.PoolExtensionException; -import org.onap.ccsdk.sli.core.sli.SvcLogicContext; -import org.slf4j.MDC; - -public abstract class ProviderOperation implements IProviderOperation { - - private static final EELFLogger logger = EELFManager.getInstance().getLogger(ProviderOperation.class); - protected static final Configuration configuration = ConfigurationFactory.getConfiguration(); - - - /** - * A cache of providers that are predefined. - */ - private Map<String /* provider name */, ProviderCache> providerCache; - - /** - * The username and password to use for dynamically created connections - */ - private String defaultUser; - private String defaultPassword; - private String defaultDomain; - - @Override - public void setDefaultUser(String defaultUser) { - this.defaultUser = defaultUser; - } - - @Override - public void setDefaultPassword(String defaultPassword) { - this.defaultPassword = defaultPassword; - } - - @Override - public void setProviderCache(Map<String, ProviderCache> providerCache) { - this.providerCache = providerCache; - } - - @Override - public void setDefaultDomain(String defaultDomain) { - this.defaultDomain = defaultDomain; - } - - /** - * set MDC props - */ - protected void setMDC(String service, String serviceName, String adapterName) { - MDC.put(MDC_ADAPTER, adapterName); - MDC.put(MDC_SERVICE, service); - MDC.put(MDC_SERVICE_NAME, serviceName); - } - - /** - * initial log of the operation - */ - protected void logOperation(Msg msg, Map<String, String> params, SvcLogicContext context) { - - String appName = configuration.getProperty(org.onap.appc.Constants.PROPERTY_APPLICATION_NAME); - logger.info(msg, appName); - - debugParameters(params); - debugContext(context); - } - - /** - * This method is used to dump the value of the parameters to the log for debugging purposes. - * - * @param parameters The parameters to be printed to the log - */ - private void debugParameters(Map<String, String> parameters) { - for (Entry<String, String> entry : parameters.entrySet()) { - logger.debug(Msg.PROPERTY_VALUE, entry.getKey(), entry.getValue()); - } - } - - /** - * This method is used to create a diagnostic dump of the context for the log - * - * @param context The context to be dumped - */ - @SuppressWarnings({"nls", "static-method"}) - private void debugContext(SvcLogicContext context) { - Set<String> keys = context.getAttributeKeySet(); - StringBuilder builder = new StringBuilder(); - - builder.append("Service Logic Context: Status "); - builder.append(Constants.LPAREN); - builder.append(context.getStatus()); - builder.append(Constants.RPAREN); - builder.append(", Attribute count "); - builder.append(Constants.LPAREN); - builder.append(keys == null ? "none" : Integer.toString(keys.size())); - builder.append(Constants.RPAREN); - if (keys != null && !keys.isEmpty()) { - builder.append(Constants.NL); - for (String key : keys) { - String value = context.getAttribute(key); - builder.append("Attribute "); - builder.append(Constants.LPAREN); - builder.append(key); - builder.append(Constants.RPAREN); - builder.append(", value "); - builder.append(Constants.LPAREN); - builder.append(value == null ? "" : value); - builder.append(Constants.RPAREN); - builder.append(Constants.NL); - } - } - - logger.debug(builder.toString()); - } - - - /** - * This method is used to validate that the parameters contain all required property names, and that the values are - * non-null and non-empty strings. We are still not ensured that the value is valid, but at least it exists. - * - * @param parameters The parameters to be checked - * @param propertyNames The list of property names that are required to be present. - * @throws RequestFailedException If the parameters are not valid - */ - protected void validateParametersExist(Map<String, String> parameters, String... propertyNames) - throws RequestFailedException { - boolean success = true; - StringBuilder msg = - new StringBuilder(EELFResourceManager.format(Msg.MISSING_REQUIRED_PROPERTIES, MDC.get(MDC_SERVICE))); - msg.append(Constants.NL); - for (String propertyName : propertyNames) { - String value = parameters.get(propertyName); - if (value == null || value.trim().length() == 0) { - success = false; - msg.append(Constants.QUOTE); - msg.append(propertyName); - msg.append(Constants.QUOTE); - msg.append(Constants.SPACE); - } - } - - if (!success) { - logger.error(msg.toString()); - throw new RequestFailedException("Check Parameters", msg.toString(), HttpStatus.BAD_REQUEST_400, - (Server) null); - } - } - - /** - * @param rc The request context that manages the state and recovery of the request for the life of its processing. - */ - protected void doFailure(RequestContext rc, HttpStatus code, String message) { - try { - doFailure(rc, code, message, null); - } catch (APPCException e) { - logger.error("An APPC exception caught. Should never happen", e); - } - } - - protected void doFailure(RequestContext rc, HttpStatus code, String message, Throwable cause) throws APPCException { - SvcLogicContext svcLogic = rc.getSvcLogicContext(); - String msg = (message == null) ? code.getReasonPhrase() : message; - if (msg.contains("\n")) { - msg = msg.substring(0, msg.indexOf('\n')); - } - String status; - try { - status = Integer.toString(code.getStatusCode()); - } catch (Exception e) { - logger.error("Error when parsing status code", e); - status = "500"; - } - svcLogic.setStatus(Outcome.FAILURE.toString()); - svcLogic.setAttribute(org.onap.appc.Constants.ATTRIBUTE_ERROR_CODE, status); - svcLogic.setAttribute(org.onap.appc.Constants.ATTRIBUTE_ERROR_MESSAGE, msg); - - if (null != cause) { - throw new APPCException(cause); - } - } - - /** - * @param rc The request context that manages the state and recovery of the request for the life of its processing. - */ - @SuppressWarnings("static-method") - protected void doSuccess(RequestContext rc) { - SvcLogicContext svcLogic = rc.getSvcLogicContext(); - svcLogic.setStatus(Outcome.SUCCESS.toString()); - svcLogic.setAttribute(org.onap.appc.Constants.ATTRIBUTE_ERROR_CODE, - Integer.toString(HttpStatus.OK_200.getStatusCode())); - } - - protected boolean validateVM(RequestContext rc, String appName, String vmUrl, VMURL vm) - throws RequestFailedException { - String msg; - if (vm == null) { - msg = EELFResourceManager.format(Msg.INVALID_SELF_LINK_URL, appName, vmUrl); - logger.error(msg); - doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg); - return true; - } - validateVMURL(vm); - return false; - } - - protected void validateVMURL(VMURL vm) throws RequestFailedException { - String name = "vm-id"; - if (vm == null) { - throw new RequestFailedException(String.format("The value %s cannot be null.", name)); - } - - // Check that its a good uri - // This will probably never get hit bc of an earlier check while parsing - // the string to a VMURL - try { - // noinspection ResultOfMethodCallIgnored - URI.create(vm.toString()); - } catch (Exception e) { - logger.error("An error occurred when validating vm url", e); - throw new RequestFailedException( - String.format("The value %s is not well formed [%s].", name, vm.toString())); - } - - // Check the tenant and vmid segments - String patternRegex = "([0-9a-f]{8}(-)?[0-9a-f]{4}(-)?[0-9a-f]{4}(-)?[0-9a-f]{4}(-)?[0-9a-f]{12})"; - Pattern pattern = Pattern.compile(patternRegex, Pattern.CASE_INSENSITIVE); - - if (!pattern.matcher(vm.getTenantId()).matches()) { - throw new RequestFailedException( - String.format("The value %s has an invalid tenantId [%s].", name, vm.getTenantId())); - } - if (!pattern.matcher(vm.getServerId()).matches()) { - throw new RequestFailedException( - String.format("The value %s has an invalid serverId [%s].", name, vm.getServerId())); - } - } - - private ProviderCache createProviderCache(VMURL vm, IdentityURL ident) { - if (vm != null && ident != null) { - ProviderCache cache = new ProviderCache(); - - cache.setIdentityURL(ident.toString()); - cache.setProviderName(ident.toString()); - - TenantCache tenant = cache.addTenant(vm.getTenantId(), null, defaultUser, defaultPassword, defaultDomain); - - // Make sure we could initialize the the cache otherwise return null - if (tenant != null && tenant.isInitialized()) { - return cache; - } - } - return null; - } - - /** - * This method is a general helper method used to locate a server given its fully-qualified self-link URL on a - * supported provider, regardless of region(s), and to return an opened context that can be used to access that - * server. - * - * @param rc The request context that wraps and manages the state of the request - * @param selfLinkURL The fully-qualified self-link URL of the server - * @param providerName The name of the provider to be searched - * @return The context that can be used to access the server, or null if not found. - */ - @SuppressWarnings("nls") - protected Context getContext(RequestContext rc, String selfLinkURL, String providerName) { - VMURL vm = VMURL.parseURL(selfLinkURL); - IdentityURL ident = IdentityURL.parseURL(providerName); - String appName = configuration.getProperty(org.onap.appc.Constants.PROPERTY_APPLICATION_NAME); - - if (vm == null) { - String msg = EELFResourceManager.format(Msg.INVALID_SELF_LINK_URL, appName, selfLinkURL); - logger.error(msg); - doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg); - return null; - } - - /* - * Get the cache of tenants and contexts for the named provider, if one exists - */ - ProviderCache cache = providerCache.get(providerName); - - /* - * If one doesn't exist, try and create it. If we have enough information to create it successfully, add it to - * the cache and continue, otherwise fail the request. - */ - if (cache == null) { - if (ident != null) { - cache = createProviderCache(vm, ident); - } - if (cache != null) { - providerCache.put(cache.getProviderName(), cache); - } else { - String msg = EELFResourceManager.format(Msg.UNKNOWN_PROVIDER, providerName, - providerCache.keySet().toString()); - logger.error(msg); - doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg); - return null; - } - } - - if (providerName == null) { - logger.debug( - String.format("Using the default provider cache [%s] since no valid identity url was passed in.", - cache.getIdentityURL())); - } - - // get the tenant cache for the vm - String identityURL = cache.getIdentityURL(); - TenantCache tenantCache = cache.getTenant(vm.getTenantId()); - - if (tenantCache == null) { - // no tenantCache matching tenant, add tenant to the provider cache - tenantCache = cache.addTenant(vm.getTenantId(), null, defaultUser, defaultPassword, defaultDomain); - if (tenantCache == null) { - // tenant not found - String msg = EELFResourceManager.format(Msg.SERVER_NOT_FOUND, selfLinkURL); - logger.error(msg); - doFailure(rc, HttpStatus.NOT_FOUND_404, msg); - return null; - } - } - - // reserve the context - String tenantName = tenantCache.getTenantName(); - String tenantId = tenantCache.getTenantId(); - String region = tenantCache.determineRegion(vm); - - if (region != null) { - Pool<Context> pool = tenantCache.getPools().get(region); - - while (rc.attempt()) { - try { - Context context = pool.reserve(); - /* - * Insert logic here to test the context for connectivity because we may have gotten one from the - * pool that was previously created. - */ - reloginIfNeeded(context); - return context; - } catch (PoolExtensionException e) { - String msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, providerName, identityURL, - tenantName, tenantId, e.getMessage(), Long.toString(rc.getRetryDelay()), - Integer.toString(rc.getAttempts()), Integer.toString(rc.getRetryLimit())); - logger.error(msg, e); - rc.delay(); - } catch (Exception e) { - String msg = EELFResourceManager.format(Msg.SERVER_OPERATION_EXCEPTION, e, - e.getClass().getSimpleName(), "find", selfLinkURL, tenantCache.getTenantName()); - - logger.error(msg, e); - doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg); - return null; - } - } - - String msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, providerName, identityURL); - logger.error(msg); - doFailure(rc, HttpStatus.BAD_GATEWAY_502, msg); - return null; - } - - String msg = EELFResourceManager.format(Msg.SERVER_NOT_FOUND, selfLinkURL); - logger.error(msg); - doFailure(rc, HttpStatus.NOT_FOUND_404, msg); - return null; - } - - private void reloginIfNeeded(Context context) throws ZoneException { - if (context.isStale()) { - context.relogin(); - } - } - - protected Context resolveContext(RequestContext rc, Map<String, String> params, String appName, String vmUrl) - throws RequestFailedException { - - VMURL vm = VMURL.parseURL(vmUrl); - if (vm == null) { - String msg = EELFResourceManager.format(Msg.INVALID_SELF_LINK_URL, appName, vmUrl); - doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg); - logger.error(msg); - return null; - } - validateVMURL(vm); - IdentityURL ident = IdentityURL.parseURL(params.get(ProviderAdapter.PROPERTY_IDENTITY_URL)); - String identStr = (ident == null) ? null : ident.toString(); - - return getContext(rc, vmUrl, identStr); - - } - - - protected abstract ModelObject executeProviderOperation(Map<String, String> params, SvcLogicContext context) - throws APPCException; - - @Override - public ModelObject doOperation(Map<String, String> params, SvcLogicContext context) throws APPCException { - - return executeProviderOperation(params, context); - } -} +/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * 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.
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.appc.adapter.iaas.provider.operation.impl.base;
+
+import static com.att.eelf.configuration.Configuration.MDC_SERVICE_NAME;
+import static org.onap.appc.adapter.iaas.provider.operation.common.constants.Constants.MDC_ADAPTER;
+import static org.onap.appc.adapter.iaas.provider.operation.common.constants.Constants.MDC_SERVICE;
+
+import com.att.cdp.exceptions.ZoneException;
+import com.att.cdp.zones.Context;
+import com.att.cdp.zones.model.ModelObject;
+import com.att.cdp.zones.model.Server;
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.att.eelf.i18n.EELFResourceManager;
+import java.net.URI;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.regex.Pattern;
+import org.glassfish.grizzly.http.util.HttpStatus;
+import org.onap.appc.adapter.iaas.ProviderAdapter;
+import org.onap.appc.adapter.iaas.impl.IdentityURL;
+import org.onap.appc.adapter.iaas.impl.ProviderCache;
+import org.onap.appc.adapter.iaas.impl.RequestContext;
+import org.onap.appc.adapter.iaas.impl.RequestFailedException;
+import org.onap.appc.adapter.iaas.impl.TenantCache;
+import org.onap.appc.adapter.iaas.impl.VMURL;
+import org.onap.appc.adapter.iaas.provider.operation.api.IProviderOperation;
+import org.onap.appc.adapter.iaas.provider.operation.common.constants.Constants;
+import org.onap.appc.adapter.iaas.provider.operation.common.enums.Outcome;
+import org.onap.appc.configuration.Configuration;
+import org.onap.appc.configuration.ConfigurationFactory;
+import org.onap.appc.exceptions.APPCException;
+import org.onap.appc.i18n.Msg;
+import org.onap.appc.pool.Pool;
+import org.onap.appc.pool.PoolExtensionException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.slf4j.MDC;
+
+public abstract class ProviderOperation implements IProviderOperation {
+
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(ProviderOperation.class);
+ protected static final Configuration configuration = ConfigurationFactory.getConfiguration();
+
+
+ /**
+ * A cache of providers that are predefined.
+ */
+ private Map<String /* provider name */, ProviderCache> providerCache;
+
+ /**
+ * The username and password to use for dynamically created connections
+ */
+ private String defaultUser;
+ private String defaultPassword;
+ private String defaultDomain;
+
+ @Override
+ public void setDefaultUser(String defaultUser) {
+ this.defaultUser = defaultUser;
+ }
+
+ @Override
+ public void setDefaultPassword(String defaultPassword) {
+ this.defaultPassword = defaultPassword;
+ }
+
+ @Override
+ public void setProviderCache(Map<String, ProviderCache> providerCache) {
+ this.providerCache = providerCache;
+ }
+
+ @Override
+ public void setDefaultDomain(String defaultDomain) {
+ this.defaultDomain = defaultDomain;
+ }
+
+ /**
+ * set MDC props
+ */
+ protected void setMDC(String service, String serviceName, String adapterName) {
+ MDC.put(MDC_ADAPTER, adapterName);
+ MDC.put(MDC_SERVICE, service);
+ MDC.put(MDC_SERVICE_NAME, serviceName);
+ }
+
+ /**
+ * initial log of the operation
+ */
+ protected void logOperation(Msg msg, Map<String, String> params, SvcLogicContext context) {
+
+ String appName = configuration.getProperty(org.onap.appc.Constants.PROPERTY_APPLICATION_NAME);
+ logger.info(msg, appName);
+
+ debugParameters(params);
+ debugContext(context);
+ }
+ /**
+ * This method is used to dump the value of the parameters to the log for debugging purposes.
+ *
+ * @param parameters The parameters to be printed to the log
+ */
+ private void debugParameters(Map<String, String> parameters) {
+ for (Entry<String, String> entry : parameters.entrySet()) {
+ logger.debug(Msg.PROPERTY_VALUE, entry.getKey(), entry.getValue());
+ }
+ }
+ /**
+ * This method is used to create a diagnostic dump of the context for the log
+ *
+ * @param context The context to be dumped
+ */
+ @SuppressWarnings({"nls", "static-method"})
+ private void debugContext(SvcLogicContext context) {
+ Set<String> keys = context.getAttributeKeySet();
+ StringBuilder builder = new StringBuilder();
+ builder.append("Service Logic Context: Status ");
+ builder.append(Constants.LPAREN);
+ builder.append(context.getStatus());
+ builder.append(Constants.RPAREN);
+ builder.append(", Attribute count ");
+ builder.append(Constants.LPAREN);
+ builder.append(keys == null ? "none" : Integer.toString(keys.size()));
+ builder.append(Constants.RPAREN);
+ if (keys != null && !keys.isEmpty()) {
+ builder.append(Constants.NL);
+ for (String key : keys) {
+ String value = context.getAttribute(key);
+ builder.append("Attribute ");
+ builder.append(Constants.LPAREN);
+ builder.append(key);
+ builder.append(Constants.RPAREN);
+ builder.append(", value ");
+ builder.append(Constants.LPAREN);
+ builder.append(value == null ? "" : value);
+ builder.append(Constants.RPAREN);
+ builder.append(Constants.NL);
+ }
+ }
+ logger.debug(builder.toString());
+ }
+
+
+ /**
+ * This method is used to validate that the parameters contain all required property names, and that the values are
+ * non-null and non-empty strings. We are still not ensured that the value is valid, but at least it exists.
+ *
+ * @param parameters The parameters to be checked
+ * @param propertyNames The list of property names that are required to be present.
+ * @throws RequestFailedException If the parameters are not valid
+ */
+ protected void validateParametersExist(Map<String, String> parameters, String... propertyNames)
+ throws RequestFailedException {
+ boolean success = true;
+ StringBuilder msg =
+ new StringBuilder(EELFResourceManager.format(Msg.MISSING_REQUIRED_PROPERTIES, MDC.get(MDC_SERVICE)));
+ msg.append(Constants.NL);
+ for (String propertyName : propertyNames) {
+ String value = parameters.get(propertyName);
+ if (value == null || value.trim().length() == 0) {
+ success = false;
+ msg.append(Constants.QUOTE);
+ msg.append(propertyName);
+ msg.append(Constants.QUOTE);
+ msg.append(Constants.SPACE);
+ }
+ }
+
+ if (!success) {
+ logger.error(msg.toString());
+ throw new RequestFailedException("Check Parameters", msg.toString(), HttpStatus.BAD_REQUEST_400,
+ (Server) null);
+ }
+ }
+
+ /**
+ * @param rc The request context that manages the state and recovery of the request for the life of its processing.
+ */
+ protected void doFailure(RequestContext rc, HttpStatus code, String message) {
+ try {
+ doFailure(rc, code, message, null);
+ } catch (APPCException e) {
+ logger.error("An APPC exception caught. Should never happen", e);
+ }
+ }
+
+ protected void doFailure(RequestContext rc, HttpStatus code, String message, Throwable cause) throws APPCException {
+ SvcLogicContext svcLogic = rc.getSvcLogicContext();
+ String msg = (message == null) ? code.getReasonPhrase() : message;
+ if ((msg.contains("PALOS"))) {
+ msg = msg.substring(msg.indexOf("PALOS"), msg.length());
+ msg = msg.substring(msg.indexOf("PALOS"), msg.indexOf("\n"));
+ } else {
+ if (msg.contains("\n")) {
+ msg = msg.substring(0, msg.indexOf('\n'));
+ }
+ }
+ String status;
+ try {
+ status = Integer.toString(code.getStatusCode());
+ } catch (Exception e) {
+ logger.error("Error when parsing status code", e);
+ status = "500";
+ }
+ svcLogic.setStatus(Outcome.FAILURE.toString());
+ svcLogic.setAttribute(org.onap.appc.Constants.ATTRIBUTE_ERROR_CODE, status);
+ svcLogic.setAttribute(org.onap.appc.Constants.ATTRIBUTE_ERROR_MESSAGE, msg);
+ if (null != cause) {
+ throw new APPCException(cause);
+ }
+ }
+
+ /**
+ * @param rc The request context that manages the state and recovery of the request for the life of its processing.
+ */
+ @SuppressWarnings("static-method")
+ protected void doSuccess(RequestContext rc) {
+ SvcLogicContext svcLogic = rc.getSvcLogicContext();
+ svcLogic.setStatus(Outcome.SUCCESS.toString());
+ svcLogic.setAttribute(org.onap.appc.Constants.ATTRIBUTE_ERROR_CODE,
+ Integer.toString(HttpStatus.OK_200.getStatusCode()));
+ }
+
+ protected boolean validateVM(RequestContext rc, String appName, String vmUrl, VMURL vm)
+ throws RequestFailedException {
+ String msg;
+ if (vm == null) {
+ msg = EELFResourceManager.format(Msg.INVALID_SELF_LINK_URL, appName, vmUrl);
+ logger.error(msg);
+ doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg);
+ return true;
+ }
+ validateVMURL(vm);
+ return false;
+ }
+
+ protected void validateVMURL(VMURL vm) throws RequestFailedException {
+ String name = "vm-id";
+ if (vm == null) {
+ throw new RequestFailedException(String.format("The value %s cannot be null.", name));
+ }
+ // Check that its a good uri
+ // This will probably never get hit bc of an earlier check while parsing
+ // the string to a VMURL
+ try {
+ // noinspection ResultOfMethodCallIgnored
+ URI.create(vm.toString());
+ } catch (Exception e) {
+ logger.error("An error occurred when validating vm url", e);
+ throw new RequestFailedException(
+ String.format("The value %s is not well formed [%s].", name, vm.toString()));
+ }
+ // Check the tenant and vmid segments
+ String patternRegex = "([0-9a-f]{8}(-)?[0-9a-f]{4}(-)?[0-9a-f]{4}(-)?[0-9a-f]{4}(-)?[0-9a-f]{12})";
+ Pattern pattern = Pattern.compile(patternRegex, Pattern.CASE_INSENSITIVE);
+ if (!pattern.matcher(vm.getTenantId()).matches()) {
+ throw new RequestFailedException(
+ String.format("The value %s has an invalid tenantId [%s].", name, vm.getTenantId()));
+ }
+ if (!pattern.matcher(vm.getServerId()).matches()) {
+ throw new RequestFailedException(
+ String.format("The value %s has an invalid serverId [%s].", name, vm.getServerId()));
+ }
+ }
+
+ private ProviderCache createProviderCache(VMURL vm, IdentityURL ident) {
+ if (vm != null && ident != null) {
+ ProviderCache cache = new ProviderCache();
+ cache.setIdentityURL(ident.toString());
+ cache.setProviderName(ident.toString());
+ TenantCache tenant = cache.addTenant(vm.getTenantId(), null, defaultUser, defaultPassword, defaultDomain);
+ // Make sure we could initialize the the cache otherwise return null
+ if (tenant != null && tenant.isInitialized()) {
+ return cache;
+ }
+ }
+ return null;
+ }
+ /**
+ * This method is a general helper method used to locate a server given its fully-qualified self-link URL on a
+ * supported provider, regardless of region(s), and to return an opened context that can be used to access that
+ * server.
+ *
+ * @param rc The request context that wraps and manages the state of the request
+ * @param selfLinkURL The fully-qualified self-link URL of the server
+ * @param providerName The name of the provider to be searched
+ * @return The context that can be used to access the server, or null if not found.
+ */
+ @SuppressWarnings("nls")
+ protected Context getContext(RequestContext rc, String selfLinkURL, String providerName) {
+ VMURL vm = VMURL.parseURL(selfLinkURL);
+ IdentityURL ident = IdentityURL.parseURL(providerName);
+ String appName = configuration.getProperty(org.onap.appc.Constants.PROPERTY_APPLICATION_NAME);
+ if (vm == null) {
+ String msg = EELFResourceManager.format(Msg.INVALID_SELF_LINK_URL, appName, selfLinkURL);
+ logger.error(msg);
+ doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg);
+ return null;
+ }
+ /*
+ * Get the cache of tenants and contexts for the named provider, if one exists
+ */
+ ProviderCache cache = providerCache.get(providerName);
+ /*
+ * If one doesn't exist, try and create it. If we have enough information to create it successfully, add it to
+ * the cache and continue, otherwise fail the request.
+ */
+ if (cache == null) {
+ if (ident != null) {
+ cache = createProviderCache(vm, ident);
+ }
+ if (cache != null) {
+ providerCache.put(cache.getProviderName(), cache);
+ } else {
+ String msg = EELFResourceManager.format(Msg.UNKNOWN_PROVIDER, providerName,
+ providerCache.keySet().toString());
+ logger.error(msg);
+ doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg);
+ return null;
+ }
+ }
+ if (providerName == null) {
+ logger.debug(
+ String.format("Using the default provider cache [%s] since no valid identity url was passed in.",
+ cache.getIdentityURL()));
+ }
+ // get the tenant cache for the vm
+ String identityURL = cache.getIdentityURL();
+ TenantCache tenantCache = cache.getTenant(vm.getTenantId());
+ if (tenantCache == null) {
+ // no tenantCache matching tenant, add tenant to the provider cache
+ tenantCache = cache.addTenant(vm.getTenantId(), null, defaultUser, defaultPassword, defaultDomain);
+ if (tenantCache == null) {
+ // tenant not found
+ String msg = EELFResourceManager.format(Msg.SERVER_NOT_FOUND, selfLinkURL);
+ logger.error(msg);
+ doFailure(rc, HttpStatus.NOT_FOUND_404, msg);
+ return null;
+ }
+ }
+ // reserve the context
+ String tenantName = tenantCache.getTenantName();
+ String tenantId = tenantCache.getTenantId();
+ String region = tenantCache.determineRegion(vm);
+
+ if (region != null) {
+ Pool<Context> pool = tenantCache.getPools().get(region);
+ while (rc.attempt()) {
+ try {
+ Context context = pool.reserve();
+ /*
+ * Insert logic here to test the context for connectivity because we may have gotten one from the
+ * pool that was previously created.
+ */
+ reloginIfNeeded(context);
+ return context;
+ } catch (PoolExtensionException e) {
+ String msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, providerName, identityURL,
+ tenantName, tenantId, e.getMessage(), Long.toString(rc.getRetryDelay()),
+ Integer.toString(rc.getAttempts()), Integer.toString(rc.getRetryLimit()));
+ logger.error(msg, e);
+ rc.delay();
+ } catch (Exception e) {
+ String msg = EELFResourceManager.format(Msg.SERVER_OPERATION_EXCEPTION, e,
+ e.getClass().getSimpleName(), "find", selfLinkURL, tenantCache.getTenantName());
+ logger.error(msg, e);
+ doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg);
+ return null;
+ }
+ }
+ String msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, providerName, identityURL);
+ logger.error(msg);
+ doFailure(rc, HttpStatus.BAD_GATEWAY_502, msg);
+ return null;
+ }
+ String msg = EELFResourceManager.format(Msg.SERVER_NOT_FOUND, selfLinkURL);
+ logger.error(msg);
+ doFailure(rc, HttpStatus.NOT_FOUND_404, msg);
+ return null;
+ }
+
+ private void reloginIfNeeded(Context context) throws ZoneException {
+ if (context.isStale()) {
+ context.relogin();
+ }
+ }
+
+ protected Context resolveContext(RequestContext rc, Map<String, String> params, String appName, String vmUrl)
+ throws RequestFailedException {
+ VMURL vm = VMURL.parseURL(vmUrl);
+ if (vm == null) {
+ String msg = EELFResourceManager.format(Msg.INVALID_SELF_LINK_URL, appName, vmUrl);
+ doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg);
+ logger.error(msg);
+ return null;
+ }
+ validateVMURL(vm);
+ IdentityURL ident = IdentityURL.parseURL(params.get(ProviderAdapter.PROPERTY_IDENTITY_URL));
+ String identStr = (ident == null) ? null : ident.toString();
+ return getContext(rc, vmUrl, identStr);
+ }
+
+ protected abstract ModelObject executeProviderOperation(Map<String, String> params, SvcLogicContext context)
+ throws APPCException;
+ @Override
+ public ModelObject doOperation(Map<String, String> params, SvcLogicContext context) throws APPCException {
+ return executeProviderOperation(params, context);
+ }
+}
|