2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Copyright (C) 2017 Amdocs
8 * =============================================================================
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
21 * ECOMP is a trademark and service mark of AT&T Intellectual Property.
22 * ============LICENSE_END=========================================================
25 package org.openecomp.appc.adapter.iaas.provider.operation.impl.base;
27 import org.openecomp.appc.adapter.iaas.ProviderAdapter;
28 import org.openecomp.appc.adapter.iaas.impl.*;
29 import org.openecomp.appc.adapter.iaas.provider.operation.api.IProviderOperation;
30 import org.openecomp.appc.adapter.iaas.provider.operation.common.constants.Constants;
31 import org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Outcome;
32 import org.openecomp.appc.configuration.Configuration;
33 import org.openecomp.appc.configuration.ConfigurationFactory;
34 import org.openecomp.appc.exceptions.APPCException;
35 import org.openecomp.appc.i18n.Msg;
36 import org.openecomp.appc.pool.Pool;
37 import org.openecomp.appc.pool.PoolExtensionException;
38 import com.att.cdp.zones.Context;
39 import com.att.cdp.zones.model.ModelObject;
40 import com.att.cdp.zones.model.Server;
41 import com.att.eelf.configuration.EELFLogger;
42 import com.att.eelf.configuration.EELFManager;
43 import com.att.eelf.i18n.EELFResourceManager;
44 import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
45 import org.glassfish.grizzly.http.util.HttpStatus;
50 import java.util.regex.Pattern;
51 import static org.openecomp.appc.adapter.iaas.provider.operation.common.constants.Constants.MDC_ADAPTER;
52 import static org.openecomp.appc.adapter.iaas.provider.operation.common.constants.Constants.MDC_SERVICE;
53 import static com.att.eelf.configuration.Configuration.MDC_SERVICE_NAME;
55 public abstract class ProviderOperation implements IProviderOperation {
57 private static final EELFLogger logger = EELFManager.getInstance().getLogger(ProviderOperation.class);
58 protected static final Configuration configuration = ConfigurationFactory.getConfiguration();
60 public void setProviderCache(Map<String, ProviderCache> providerCache) {
61 this.providerCache = providerCache;
65 * A cache of providers that are predefined.
67 private Map<String /* provider name */, ProviderCache> providerCache;
70 public void setDefaultUser(String defaultUser) {
71 DEFAULT_USER = defaultUser;
74 public void setDefaultPass(String defaultPass) {
75 DEFAULT_PASS = defaultPass;
79 public void setDefaultDomain(String defaultDomain) {
80 DEFAULT_DOMAIN = defaultDomain;
84 * The username and password to use for dynamically created connections
86 private static String DEFAULT_USER;
87 private static String DEFAULT_PASS;
88 private static String DEFAULT_DOMAIN;
98 protected void setMDC(String service, String serviceName, String adapterName) {
99 MDC.put(MDC_ADAPTER, adapterName);
100 MDC.put(MDC_SERVICE, service);
101 MDC.put(MDC_SERVICE_NAME, serviceName);
105 * initial log of the operation
111 protected void logOperation(Msg msg, Map<String, String> params, SvcLogicContext context) {
113 String appName = configuration.getProperty(org.openecomp.appc.Constants.PROPERTY_APPLICATION_NAME);
114 logger.info(msg, appName);
116 debugParameters(params);
117 debugContext(context);
121 * This method is used to dump the value of the parameters to the log for debugging purposes.
123 * @param parameters The parameters to be printed to the log
125 private void debugParameters(Map<String, String> parameters) {
126 for (String key : parameters.keySet()) {
127 logger.debug(Msg.PROPERTY_VALUE, key, parameters.get(key));
132 * This method is used to create a diagnostic dump of the context for the log
134 * @param context The context to be dumped
136 @SuppressWarnings({"nls", "static-method"})
137 private void debugContext(SvcLogicContext context) {
138 Set<String> keys = context.getAttributeKeySet();
139 StringBuilder builder = new StringBuilder();
141 builder.append("Service Logic Context: Status ");
142 builder.append(Constants.LPAREN);
143 builder.append(context.getStatus());
144 builder.append(Constants.RPAREN);
145 builder.append(", Attribute count ");
146 builder.append(Constants.LPAREN);
147 builder.append(keys == null ? "none" : Integer.toString(keys.size()));
148 builder.append(Constants.RPAREN);
149 if (keys != null && !keys.isEmpty()) {
150 builder.append(Constants.NL);
151 for (String key : keys) {
152 String value = context.getAttribute(key);
153 builder.append("Attribute ");
154 builder.append(Constants.LPAREN);
156 builder.append(Constants.RPAREN);
157 builder.append(", value ");
158 builder.append(Constants.LPAREN);
159 builder.append(value == null ? "" : value);
160 builder.append(Constants.RPAREN);
161 builder.append(Constants.NL);
165 logger.debug(builder.toString());
170 * This method is used to validate that the parameters contain all required property names, and that the values are
171 * non-null and non-empty strings. We are still not ensured that the value is valid, but at least it exists.
173 * @param parameters The parameters to be checked
174 * @param propertyNames The list of property names that are required to be present.
175 * @throws RequestFailedException If the parameters are not valid
177 protected void validateParametersExist(Map<String, String> parameters, String... propertyNames)
178 throws RequestFailedException {
179 boolean success = true;
181 new StringBuilder(EELFResourceManager.format(Msg.MISSING_REQUIRED_PROPERTIES, MDC.get(MDC_SERVICE)));
182 msg.append(Constants.NL);
183 for (String propertyName : propertyNames) {
184 String value = parameters.get(propertyName);
185 if (value == null || value.trim().length() == 0) {
187 msg.append(Constants.QUOTE);
188 msg.append(propertyName);
189 msg.append(Constants.QUOTE);
190 msg.append(Constants.SPACE);
195 logger.error(msg.toString());
196 throw new RequestFailedException("Check Parameters", msg.toString(), HttpStatus.BAD_REQUEST_400,
202 * @param rc The request context that manages the state and recovery of the request for the life of its processing.
206 protected void doFailure(RequestContext rc, HttpStatus code, String message) {
208 doFailure(rc, code, message, null);
209 } catch (APPCException ignored) {
213 protected void doFailure(RequestContext rc, HttpStatus code, String message, Throwable cause) throws APPCException {
214 SvcLogicContext svcLogic = rc.getSvcLogicContext();
215 String msg = (message == null) ? code.getReasonPhrase() : message;
216 if (msg.contains("\n")) {
217 msg = msg.substring(0, msg.indexOf("\n"));
221 status = Integer.toString(code.getStatusCode());
222 } catch (Exception e) {
225 svcLogic.setStatus(Outcome.FAILURE.toString());
226 svcLogic.setAttribute(org.openecomp.appc.Constants.ATTRIBUTE_ERROR_CODE, status);
227 svcLogic.setAttribute(org.openecomp.appc.Constants.ATTRIBUTE_ERROR_MESSAGE, msg);
230 throw new APPCException(cause);
234 * @param rc The request context that manages the state and recovery of the request for the life of its processing.
236 @SuppressWarnings("static-method")
237 protected void doSuccess(RequestContext rc) {
238 SvcLogicContext svcLogic = rc.getSvcLogicContext();
239 svcLogic.setStatus(Outcome.SUCCESS.toString());
240 svcLogic.setAttribute(org.openecomp.appc.Constants.ATTRIBUTE_ERROR_CODE,
241 Integer.toString(HttpStatus.OK_200.getStatusCode()));
244 protected boolean validateVM(RequestContext rc, String appName, String vm_url, VMURL vm)
245 throws RequestFailedException {
248 msg = EELFResourceManager.format(Msg.INVALID_SELF_LINK_URL, appName, vm_url);
250 doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg);
257 protected void validateVMURL(VMURL vm) throws RequestFailedException {
258 String name = "vm-id";
260 throw new RequestFailedException(String.format("The value %s cannot be null.", name));
263 // Check that its a good uri
264 // This will probably never get hit bc of an earlier check while parsing
265 // the string to a VMURL
267 // noinspection ResultOfMethodCallIgnored
268 URI.create(vm.toString());
269 } catch (Exception e) {
270 throw new RequestFailedException(
271 String.format("The value %s is not well formed [%s].", name, vm.toString()));
274 // Check the tenant and vmid segments
275 String patternRegex = "([0-9a-f]{8}(-)?[0-9a-f]{4}(-)?[0-9a-f]{4}(-)?[0-9a-f]{4}(-)?[0-9a-f]{12})";
276 Pattern pattern = Pattern.compile(patternRegex, Pattern.CASE_INSENSITIVE);
278 if (!pattern.matcher(vm.getTenantId()).matches()) {
279 throw new RequestFailedException(
280 String.format("The value %s has an invalid tenantId [%s].", name, vm.getTenantId()));
282 if (!pattern.matcher(vm.getServerId()).matches()) {
283 throw new RequestFailedException(
284 String.format("The value %s has an invalid serverId [%s].", name, vm.getServerId()));
288 private ProviderCache createProviderCache(VMURL vm, IdentityURL ident) {
289 if (vm != null && ident != null) {
290 ProviderCache cache = new ProviderCache();
292 cache.setIdentityURL(ident.toString());
293 cache.setProviderName(ident.toString());
294 // cache.setProviderType("OpenStack");
296 TenantCache tenant = cache.addTenant(vm.getTenantId(), null, DEFAULT_USER, DEFAULT_PASS, DEFAULT_DOMAIN);
298 // Make sure we could initialize the the cache otherwise return null
299 if (tenant != null && tenant.isInitialized()) {
307 * This method is a general helper method used to locate a server given its fully-qualified self-link URL on a
308 * supported provider, regardless of region(s), and to return an opened context that can be used to access that
311 * @param rc The request context that wraps and manages the state of the request
312 * @param selfLinkURL The fully-qualified self-link URL of the server
313 * @param providerName The name of the provider to be searched
314 * @return The context that can be used to access the server, or null if not found.
316 @SuppressWarnings("nls")
317 protected Context getContext(RequestContext rc, String selfLinkURL, String providerName) {
318 VMURL vm = VMURL.parseURL(selfLinkURL);
319 IdentityURL ident = IdentityURL.parseURL(providerName);
320 String appName = configuration.getProperty(org.openecomp.appc.Constants.PROPERTY_APPLICATION_NAME);
323 String msg = EELFResourceManager.format(Msg.INVALID_SELF_LINK_URL, appName, selfLinkURL);
325 doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg);
330 * Get the cache of tenants and contexts for the named provider, if one exists
332 ProviderCache cache = providerCache.get(providerName);
335 * If one doesn't exist, try and create it. If we have enough information to create it successfully, add it to
336 * the cache and continue, otherwise fail the request.
340 cache = createProviderCache(vm, ident);
343 providerCache.put(cache.getProviderName(), cache);
345 String msg = EELFResourceManager.format(Msg.UNKNOWN_PROVIDER, providerName,
346 providerCache.keySet().toString());
348 doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg);
353 if (providerName == null) {
355 String.format("Using the default provider cache [%s] since no valid identity url was passed in.",
356 cache.getIdentityURL()));
359 // get the tenant cache for the vm
360 String identityURL = cache.getIdentityURL();
361 TenantCache tenantCache = cache.getTenant(vm.getTenantId());
363 if (tenantCache == null) {
364 // no tenantCache matching tenant, add tenant to the provider cache
365 tenantCache = cache.addTenant(vm.getTenantId(), null, DEFAULT_USER, DEFAULT_PASS, DEFAULT_DOMAIN);
367 if (tenantCache == null) {
369 String msg = EELFResourceManager.format(Msg.SERVER_NOT_FOUND, selfLinkURL);
371 doFailure(rc, HttpStatus.NOT_FOUND_404, msg);
376 // reserve the context
377 String tenantName = tenantCache.getTenantName();
378 String tenantId = tenantCache.getTenantId();
379 String region = tenantCache.determineRegion(vm);
381 if (region != null) {
382 Pool<Context> pool = tenantCache.getPools().get(region);
384 while (rc.attempt()) {
386 Context context = pool.reserve();
389 * Insert logic here to test the context for connectivity because we may have gotten one from the
390 * pool that was previously created.
392 if (context.isStale()) {
396 } catch (PoolExtensionException e) {
397 String msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, providerName, identityURL,
398 tenantName, tenantId, e.getMessage(), Long.toString(rc.getRetryDelay()),
399 Integer.toString(rc.getAttempts()), Integer.toString(rc.getRetryLimit()));
400 logger.error(msg, e);
402 } catch (Exception e) {
403 String msg = EELFResourceManager.format(Msg.SERVER_OPERATION_EXCEPTION, e,
404 e.getClass().getSimpleName(), "find", selfLinkURL, tenantCache.getTenantName());
406 logger.error(msg, e);
407 doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg);
412 String msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, providerName, identityURL);
414 doFailure(rc, HttpStatus.BAD_GATEWAY_502, msg);
419 String msg = EELFResourceManager.format(Msg.SERVER_NOT_FOUND, selfLinkURL);
421 doFailure(rc, HttpStatus.NOT_FOUND_404, msg);
425 protected Context resolveContext(RequestContext rc, Map<String, String> params, String appName, String vm_url)
426 throws RequestFailedException {
428 VMURL vm = VMURL.parseURL(vm_url);
430 String msg = EELFResourceManager.format(Msg.INVALID_SELF_LINK_URL, appName, vm_url);
431 doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg);
436 IdentityURL ident = IdentityURL.parseURL(params.get(ProviderAdapter.PROPERTY_IDENTITY_URL));
437 String identStr = (ident == null) ? null : ident.toString();
439 return getContext(rc, vm_url, identStr);
445 protected abstract ModelObject executeProviderOperation(Map<String, String> params, SvcLogicContext context)
446 throws APPCException;
449 public ModelObject doOperation(Map<String, String> params, SvcLogicContext context) throws APPCException {
451 return executeProviderOperation(params, context);