aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorModaboina, Kusumakumari (km583p) <km583p@us.att.com>2018-03-19 22:09:28 -0400
committerTakamune Cho <tc012c@att.com>2018-03-21 17:28:59 +0000
commit151be4c7b1da50c85553e11328a72c5207749a29 (patch)
tree8df4cd4020df0e49421d53fd244189ff986c5748
parent2c73e06f03d6b3d83ead42b4eec3cd40c81865e5 (diff)
bugfix for error handling while detaching volumes
Change-Id: I96f7d017a63b0741d87666f4608356567932ff77 Issue-ID: APPC-762 Signed-off-by: Modaboina, Kusumakumari (km583p) <km583p@us.att.com>
-rw-r--r--appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/onap/appc/adapter/iaas/provider/operation/impl/DettachVolumeServer.java130
-rw-r--r--appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/onap/appc/adapter/iaas/provider/operation/impl/MigrateServer.java2
-rw-r--r--appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/onap/appc/adapter/iaas/provider/operation/impl/base/ProviderOperation.java888
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);
+ }
+}