diff options
Diffstat (limited to 'appc-adapters')
121 files changed, 10451 insertions, 3124 deletions
diff --git a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/pom.xml b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/pom.xml index 1ef168a24..2ccf432f5 100644 --- a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/pom.xml +++ b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/pom.xml @@ -12,6 +12,11 @@ <name>chef Adapter - bundle</name> <dependencies> + <dependency> + <groupId>org.json</groupId> + <artifactId>json</artifactId> + <version>20160810</version> + </dependency> <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> @@ -29,33 +34,33 @@ <version>4.4.4</version> </dependency> - <dependency> + <!-- <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.1</version> - </dependency> + </dependency> --> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcpkix-jdk15on</artifactId> - <version>1.47</version> + <version>1.55</version> </dependency> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> - <version>1.47</version> + <version>1.55</version> </dependency> <dependency> <groupId>org.openecomp.appc</groupId> <artifactId>appc-common</artifactId> <version>${project.version}</version> - <classifier>jar-with-dependencies</classifier> - <scope>compile</scope> +<!-- <classifier>jar-with-dependencies</classifier> --> + <scope>test</scope> </dependency> <dependency> <groupId>org.openecomp.appc</groupId> <artifactId>appc-common</artifactId> <version>${project.version}</version> - <scope>test</scope> + </dependency> <dependency> <groupId>javax</groupId> @@ -216,11 +221,11 @@ <Bundle-Activator>org.openecomp.appc.adapter.chef.ChefActivator</Bundle-Activator> <Export-Package>org.openecomp.appc.adapter.chef</Export-Package> <Import-Package>org.openecomp.sdnc.sli.*,org.osgi.framework.*,org.slf4j.*,com.vmware.*,org.apache.xerces.*,javax.net.*,javax.net.ssl.*,org.xml.sax.*,javax.xml.bind.*,javax.naming.*</Import-Package> - <Embed-Dependency>*;scope=compile|runtime;artifactId=!sli-common|org.eclipse.osgi|slf4j-api|jcl-over-slf4j|mysql-connector-java|xml-apis</Embed-Dependency> + <Embed-Dependency>*;scope=compile|runtime;artifactId=!sli-common|!appc-common|org.eclipse.osgi|slf4j-api|jcl-over-slf4j|mysql-connector-java|xml-apis</Embed-Dependency> <Embed-Transitive>true</Embed-Transitive> </instructions> - <manifestLocation>${project.basedir}/src/main/resources/META-INF</manifestLocation> + <manifestLocation>${project.basedir}/src/main/resources/META-INF</manifestLocation> </configuration> </plugin> </plugins> diff --git a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/openecomp/appc/adapter/chef/ChefAdapter.java b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/openecomp/appc/adapter/chef/ChefAdapter.java index 907ded5d2..7859d6bbc 100644 --- a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/openecomp/appc/adapter/chef/ChefAdapter.java +++ b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/openecomp/appc/adapter/chef/ChefAdapter.java @@ -199,5 +199,19 @@ public interface ChefAdapter extends SvcLogicJavaPlugin { void chefGet(Map<String, String> params, SvcLogicContext ctx) ; void chefPut(Map<String, String> params, SvcLogicContext ctx) ; + +void chefPost(Map<String, String> params, SvcLogicContext ctx) ; + + void chefDelete(Map<String, String> params, SvcLogicContext ctx) ; + + void nodeObejctBuilder(Map<String, String> params, SvcLogicContext ctx) ; + + void checkPushJob(Map<String, String> params, SvcLogicContext ctx) ; + + void pushJob(Map<String, String> params, SvcLogicContext ctx) ; + + void retrieveData (Map<String, String> params, SvcLogicContext ctx) ; + + void combineStrings (Map<String, String> params, SvcLogicContext ctx) ; } diff --git a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/openecomp/appc/adapter/chef/chefapi/Delete.java b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/openecomp/appc/adapter/chef/chefapi/Delete.java new file mode 100644 index 000000000..410f00a94 --- /dev/null +++ b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/openecomp/appc/adapter/chef/chefapi/Delete.java @@ -0,0 +1,33 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.adapter.chef.chefapi; + +import org.apache.http.client.methods.HttpDelete; + +public class Delete extends ApiMethod{ + + public Delete(HttpDelete method) { + super("DELETE"); + this.method = method; + } + +} diff --git a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/openecomp/appc/adapter/chef/chefapi/Post.java b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/openecomp/appc/adapter/chef/chefapi/Post.java new file mode 100644 index 000000000..7dc8baa40 --- /dev/null +++ b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/openecomp/appc/adapter/chef/chefapi/Post.java @@ -0,0 +1,43 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.adapter.chef.chefapi; + +import org.apache.http.client.methods.*; +import org.apache.http.entity.StringEntity; + +public class Post extends ApiMethod{ + + public Post(HttpRequestBase method) { + super("POST"); + this.method = method; + } + + public ApiMethod body(String body){ + this.reqBody = body; + StringEntity params =new StringEntity (body,"UTF-8"); + params.setContentType("application/json"); + HttpPost post = (HttpPost) method; + post.setEntity(params); + return this; + } + +} diff --git a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/openecomp/appc/adapter/chef/chefclient/ChefApiClient.java b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/openecomp/appc/adapter/chef/chefclient/ChefApiClient.java index 743fe8456..ca36aa4b6 100644 --- a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/openecomp/appc/adapter/chef/chefclient/ChefApiClient.java +++ b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/openecomp/appc/adapter/chef/chefclient/ChefApiClient.java @@ -67,4 +67,28 @@ public class ChefApiClient { put.setChefPath(path); return put; } + public Post post(String path){ + Post post = new Post(new HttpPost(endpoint+path)); + post.setPemPath(pemPath); + post.setUserId(userId); + post.setOrganizations(organizations); + post.setChefPath(path); + return post; + } + + public Delete delete(String path){ + Delete del = new Delete(new HttpDelete(endpoint+path)); + del.setPemPath(pemPath); + del.setUserId(userId); + del.setOrganizations(organizations); + del.setChefPath(path); + return del; + } + + +/* public Header[] buildHeaders(){ + + return null; + } +*/ } diff --git a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/openecomp/appc/adapter/chef/chefclient/Utils.java b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/openecomp/appc/adapter/chef/chefclient/Utils.java index d814762f8..cb479fc2e 100644 --- a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/openecomp/appc/adapter/chef/chefclient/Utils.java +++ b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/openecomp/appc/adapter/chef/chefclient/Utils.java @@ -35,8 +35,10 @@ import java.security.Signature; import java.security.SignatureException; import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.bouncycastle.openssl.PEMReader; +import org.bouncycastle.openssl.PEMParser; import org.bouncycastle.util.encoders.Base64; +import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; +import org.bouncycastle.openssl.PEMKeyPair; public class Utils { private Utils(){} @@ -66,7 +68,10 @@ public class Utils { Security.addProvider(new BouncyCastleProvider()); try { - KeyPair kp = (KeyPair) new PEMReader(br).readObject(); + PEMParser pemParser = new PEMParser(br); + JcaPEMKeyConverter converter = new JcaPEMKeyConverter(); + Object object = pemParser.readObject(); + KeyPair kp = converter.getKeyPair((PEMKeyPair) object);; PrivateKey privateKey = kp.getPrivate(); Signature instance = Signature.getInstance("RSA"); instance.initSign(privateKey); diff --git a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/openecomp/appc/adapter/chef/impl/ChefAdapterImpl.java b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/openecomp/appc/adapter/chef/impl/ChefAdapterImpl.java index 5985bcfd1..01e256d08 100644 --- a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/openecomp/appc/adapter/chef/impl/ChefAdapterImpl.java +++ b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/openecomp/appc/adapter/chef/impl/ChefAdapterImpl.java @@ -78,6 +78,23 @@ import static com.att.eelf.configuration.Configuration.*; import java.io.IOException; import java.net.InetAddress; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Properties; +//chef +import org.openecomp.appc.adapter.chef.chefapi.*; +import org.openecomp.appc.adapter.chef.chefclient.*; + +//json +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; /** * This class implements the {@link ChefAdapter} interface. This interface * defines the behaviors that our service provides. @@ -279,6 +296,94 @@ public class ChefAdapterImpl implements ChefAdapter { * org.openecomp.sdnc.sli.SvcLogicContext) */ + + /** + * build node object + */ + + @SuppressWarnings("nls") + @Override + public void nodeObejctBuilder(Map<String, String> params, SvcLogicContext ctx) { + logger.info("nodeObejctBuilder"); + String name = params.get("org.openecomp.appc.instance.nodeobject.name"); + String normal = params.get("org.openecomp.appc.instance.nodeobject.normal"); + String overrides = params.get("org.openecomp.appc.instance.nodeobject.overrides"); + String defaults = params.get("org.openecomp.appc.instance.nodeobject.defaults"); + String run_list = params.get("org.openecomp.appc.instance.nodeobject.run_list"); + String chef_environment = params.get("org.openecomp.appc.instance.nodeobject.chef_environment"); + String nodeObject = "{\"json_class\":\"Chef::Node\",\"default\":{" + defaults + + "},\"chef_type\":\"node\",\"run_list\":[" + run_list + "],\"override\":{" + overrides + + "},\"normal\": {" + normal + "},\"automatic\":{},\"name\":\"" + name + "\",\"chef_environment\":\"" + + chef_environment + "\"}"; + logger.info(nodeObject); + + RequestContext rc = new RequestContext(ctx); + rc.isAlive(); + SvcLogicContext svcLogic = rc.getSvcLogicContext(); + svcLogic.setAttribute("org.openecomp.appc.chef.nodeObject", nodeObject); + + } + + /** + * Send get request to chef server + */ + + public void chefInfo(Map<String, String> params) { + clientName = params.get("org.openecomp.appc.instance.username"); + serverAddress = params.get("org.openecomp.appc.instance.serverAddress"); + organizations = params.get("org.openecomp.appc.instance.organizations"); + chefserver = "https://" + serverAddress + "/organizations/" + organizations; + clientPrivatekey = "/opt/openecomp/appc/chef/" + serverAddress + "/" + organizations + "/" + clientName + ".pem"; + } + + public Boolean privateKeyCheck() { + File f = new File(clientPrivatekey); + if (f.exists()) { + return true; + } else { + return false; + } + } + + @SuppressWarnings("nls") + @Override + public void retrieveData(Map<String, String> params, SvcLogicContext ctx) { + String contextData = "someValue"; + String allConfigData = params.get("org.openecomp.appc.instance.allConfig"); + String key = params.get("org.openecomp.appc.instance.key"); + String dgContext = params.get("org.openecomp.appc.instance.dgContext"); + JSONObject josnConfig = new JSONObject(allConfigData); + try { + contextData = josnConfig.getString(key); + } catch (Exception ex) { + try { + contextData = josnConfig.getJSONObject(key).toString(); + } catch (Exception exc) { + contextData = josnConfig.getJSONArray(key).toString(); + } + } + + RequestContext rc = new RequestContext(ctx); + rc.isAlive(); + SvcLogicContext svcLogic = rc.getSvcLogicContext(); + svcLogic.setAttribute(dgContext, contextData); + } + + @SuppressWarnings("nls") + @Override + public void combineStrings(Map<String, String> params, SvcLogicContext ctx) { + + String String1 = params.get("org.openecomp.appc.instance.String1"); + String String2 = params.get("org.openecomp.appc.instance.String2"); + String dgContext = params.get("org.openecomp.appc.instance.dgContext"); + String contextData = String1 + String2; + RequestContext rc = new RequestContext(ctx); + rc.isAlive(); + SvcLogicContext svcLogic = rc.getSvcLogicContext(); + svcLogic.setAttribute(dgContext, contextData); + } + + /** * Send GET request to chef server */ @@ -287,19 +392,25 @@ public class ChefAdapterImpl implements ChefAdapter { @Override public void chefGet(Map<String, String> params, SvcLogicContext ctx) { logger.info("chef get method"); - String chefAction= params.get("org.openecomp.appc.instance.chefAction"); + chefInfo(params); + String chefAction = params.get("org.openecomp.appc.instance.chefAction"); RequestContext rc = new RequestContext(ctx); rc.isAlive(); - //should load pem from somewhere else - ChefApiClient cac = new ChefApiClient(clientName,clientPrivatekey,chefserver,organizations); - // need pass path into it - //"/nodes" - ApiMethod am = cac.get(chefAction); - am.execute(); - int code = am.getReturnCode(); - String message = am.getResponseBodyAsString(); - logger.info(code + " " + message); - chefServerResult(rc,Integer.toString(code),message); + int code; + String message = null; + if (privateKeyCheck()) { + ChefApiClient cac = new ChefApiClient(clientName, clientPrivatekey, chefserver, organizations); + ApiMethod am = cac.get(chefAction); + am.execute(); + code = am.getReturnCode(); + message = am.getResponseBodyAsString(); + } else { + code = 500; + message = "Cannot find the private key in the APPC file system, please load the private key to " + + clientPrivatekey; + } + chefServerResult(rc, Integer.toString(code), message); + } /** @@ -309,29 +420,93 @@ public class ChefAdapterImpl implements ChefAdapter { @SuppressWarnings("nls") @Override public void chefPut(Map<String, String> params, SvcLogicContext ctx) { - - logger.info("chef PUT method"); - logger.info(clientName+" "+clientPrivatekey+" "+chefserver+" "+organizations); - String chefAction= params.get("org.openecomp.appc.instance.chefAction"); - String runList= params.get("org.openecomp.appc.instance.runList"); - String attributes= params.get("org.openecomp.appc.instance.attributes"); - logger.info(attributes); - String CHEF_NODE_STR = "{\"json_class\":\"Chef::Node\",\"default\":{},\"chef_type\":\"node\",\"run_list\":[\""+runList+"\"],\"override\":{},\"automatic\":{},\"normal\":{"+attributes+"},\"name\":\"testnode\",\"chef_environment\":\"_default\"}"; + chefInfo(params); + String chefAction = params.get("org.openecomp.appc.instance.chefAction"); + String CHEF_NODE_STR = params.get("org.openecomp.appc.instance.chefRequestBody"); RequestContext rc = new RequestContext(ctx); rc.isAlive(); - //should load pem from somewhere else - ChefApiClient cac = new ChefApiClient(clientName,clientPrivatekey,chefserver,organizations); - - // need pass path into it - //"/nodes/testnode" - ApiMethod am = cac.put(chefAction).body(CHEF_NODE_STR); - am.execute(); - int code = am.getReturnCode(); - String message = am.getResponseBodyAsString(); + int code; + String message = null; + if (privateKeyCheck()) { + ChefApiClient cac = new ChefApiClient(clientName, clientPrivatekey, chefserver, organizations); + + ApiMethod am = cac.put(chefAction).body(CHEF_NODE_STR); + am.execute(); + code = am.getReturnCode(); + message = am.getResponseBodyAsString(); + } else { + code = 500; + message = "Cannot find the private key in the APPC file system, please load the private key to " + + clientPrivatekey; + } logger.info(code + " " + message); - chefServerResult(rc,Integer.toString(code),message); + chefServerResult(rc, Integer.toString(code), message); + } + /** + * Send Post request to chef server + */ + + @SuppressWarnings("nls") + @Override + public void chefPost(Map<String, String> params, SvcLogicContext ctx) { + chefInfo(params); + logger.info("chef Post method"); + logger.info(clientName + " " + clientPrivatekey + " " + chefserver + " " + organizations); + String CHEF_NODE_STR = params.get("org.openecomp.appc.instance.chefRequestBody"); + String chefAction = params.get("org.openecomp.appc.instance.chefAction"); + RequestContext rc = new RequestContext(ctx); + rc.isAlive(); + int code; + String message = null; + // should load pem from somewhere else + if (privateKeyCheck()) { + ChefApiClient cac = new ChefApiClient(clientName, clientPrivatekey, chefserver, organizations); + + // need pass path into it + // "/nodes/testnode" + ApiMethod am = cac.post(chefAction).body(CHEF_NODE_STR); + am.execute(); + code = am.getReturnCode(); + message = am.getResponseBodyAsString(); + } else { + code = 500; + message = "Cannot find the private key in the APPC file system, please load the private key to " + + clientPrivatekey; + } + logger.info(code + " " + message); + chefServerResult(rc, Integer.toString(code), message); + } + + /** + * Send delete request to chef server + */ + + @SuppressWarnings("nls") + @Override + public void chefDelete(Map<String, String> params, SvcLogicContext ctx) { + logger.info("chef delete method"); + chefInfo(params); + String chefAction = params.get("org.openecomp.appc.instance.chefAction"); + RequestContext rc = new RequestContext(ctx); + rc.isAlive(); + int code; + String message = null; + if (privateKeyCheck()) { + ChefApiClient cac = new ChefApiClient(clientName, clientPrivatekey, chefserver, organizations); + ApiMethod am = cac.delete(chefAction); + am.execute(); + code = am.getReturnCode(); + message = am.getResponseBodyAsString(); + } else { + code = 500; + message = "Cannot find the private key in the APPC file system, please load the private key to " + + clientPrivatekey; + } + logger.info(code + " " + message); + chefServerResult(rc, Integer.toString(code), message); + } /** @@ -362,6 +537,78 @@ public class ChefAdapterImpl implements ChefAdapter { } + @SuppressWarnings("nls") + @Override + public void checkPushJob(Map<String, String> params, SvcLogicContext ctx) { + chefInfo(params); + String jobID = params.get("org.openecomp.appc.instance.jobid"); + int retryTimes = Integer.parseInt(params.get("org.openecomp.appc.instance.retryTimes")); + int retryInterval = Integer.parseInt(params.get("org.openecomp.appc.instance.retryInterval")); + String chefAction = "/pushy/jobs/" + jobID; + + RequestContext rc = new RequestContext(ctx); + rc.isAlive(); + SvcLogicContext svcLogic = rc.getSvcLogicContext(); + String message = ""; + String status = ""; + for (int i = 0; i < retryTimes; i++) { + try { + Thread.sleep(retryInterval); // 1000 milliseconds is one second. + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + } + ChefApiClient cac = new ChefApiClient(clientName, clientPrivatekey, chefserver, organizations); + ApiMethod am = cac.get(chefAction); + am.execute(); + int code = am.getReturnCode(); + message = am.getResponseBodyAsString(); + JSONObject obj = new JSONObject(message); + status = obj.getString("status"); + if (!status.equals("running")) { + logger.info(i + " time " + code + " " + status); + break; + } + + } + if (status.equals("complete")) { + svcLogic.setAttribute("org.openecomp.appc.chefServerResult.code", "200"); + svcLogic.setAttribute("org.openecomp.appc.chefServerResult.message", message); + } else { + if (status.equals("running")) { + svcLogic.setAttribute("org.openecomp.appc.chefServerResult.code", "202"); + svcLogic.setAttribute("org.openecomp.appc.chefServerResult.message", "chef client runtime out"); + } else { + svcLogic.setAttribute("org.openecomp.appc.chefServerResult.code", "500"); + svcLogic.setAttribute("org.openecomp.appc.chefServerResult.message", message); + } + } + } + + + @SuppressWarnings("nls") + @Override + public void pushJob(Map<String, String> params, SvcLogicContext ctx) { + chefInfo(params); + String pushRequest = params.get("org.openecomp.appc.instance.pushRequest"); + String chefAction = "/pushy/jobs"; + RequestContext rc = new RequestContext(ctx); + rc.isAlive(); + SvcLogicContext svcLogic = rc.getSvcLogicContext(); + ChefApiClient cac = new ChefApiClient(clientName, clientPrivatekey, chefserver, organizations); + ApiMethod am = cac.post(chefAction).body(pushRequest); + ; + am.execute(); + int code = am.getReturnCode(); + String message = am.getResponseBodyAsString(); + if (code == 201) { + int startIndex = message.indexOf("jobs") + 6; + int endIndex = message.length() - 2; + String jobID = message.substring(startIndex, endIndex); + svcLogic.setAttribute("org.openecomp.appc.jobID", jobID); + logger.info(jobID); + } + chefServerResult(rc, Integer.toString(code), message); + } @SuppressWarnings("static-method") diff --git a/appc-adapters/appc-chef-adapter/appc-chef-adapter-features/src/main/resources/features.xml b/appc-adapters/appc-chef-adapter/appc-chef-adapter-features/src/main/resources/features.xml index 85b7941d8..8235f2b03 100644 --- a/appc-adapters/appc-chef-adapter/appc-chef-adapter-features/src/main/resources/features.xml +++ b/appc-adapters/appc-chef-adapter/appc-chef-adapter-features/src/main/resources/features.xml @@ -31,6 +31,7 @@ <!-- Most applications will have a dependency on the ODL MD-SAL Broker --> <feature version="${broker-mdsal.version}">odl-mdsal-broker</feature> <feature>sdnc-sli</feature> + <bundle dependency="true">mvn:org.openecomp.appc/appc-common/${project.version}</bundle> <bundle>mvn:org.openecomp.appc/appc-chef-adapter-bundle/${project.version}</bundle> </feature> diff --git a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/pom.xml b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/pom.xml index 44ca150d1..449ce92d2 100644 --- a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/pom.xml +++ b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/pom.xml @@ -14,13 +14,17 @@ <dependencies> <dependency> <groupId>org.openecomp.appc</groupId> + <artifactId>appc-message-adapter-api</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.openecomp.appc</groupId> <artifactId>appc-metric-bundle</artifactId> - <version>1.1.0-SNAPSHOT</version> + <version>${project.version}</version> </dependency> <dependency> <groupId>org.openecomp.appc</groupId> <artifactId>appc-common</artifactId> - <classifier>jar-with-dependencies</classifier> <version>${project.version}</version> </dependency> @@ -65,7 +69,6 @@ <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-api-mockito</artifactId> - <version>1.6.2</version> <scope>test</scope> </dependency> <dependency> @@ -85,10 +88,17 @@ <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-module-junit4</artifactId> - <version>1.6.2</version> <scope>test</scope> </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>jcl-over-slf4j</artifactId> + </dependency> <dependency> <groupId>org.openecomp.sdnc.core</groupId> <artifactId>sli-common</artifactId> @@ -119,6 +129,14 @@ </exclusions> </dependency> + <!-- DMaaP Client --> + <dependency> + <groupId>com.att.nsa</groupId> + <artifactId>dmaapClient</artifactId> + <version>0.2.12</version> +<!-- <version>${dmaap.client.version}</version> --> + </dependency> + <dependency> <groupId>org.json</groupId> <artifactId>json</artifactId> @@ -129,8 +147,6 @@ </dependency> </dependencies> - - <build> <plugins> <plugin> @@ -139,12 +155,13 @@ <extensions>true</extensions> <configuration> <instructions> - <Bundle-SymbolicName>org.openecomp.appc.adapter.dmaap</Bundle-SymbolicName> - <Bundle-Activator>org.openecomp.appc.adapter.dmaap.AppcDmaapAdapterActivator</Bundle-Activator> - <Export-Package>org.openecomp.appc.adapter.dmaap.*</Export-Package> - <Export-Serice>org.openecomp.appc.adapter.dmaap.EventSender</Export-Serice> - <Import-Package>org.openecomp.appc.metricservice.*,org.openecomp.sdnc.sli.*,org.osgi.framework.*,!org.osgi.service.event.*,org.osgi.service.*,org.osgi.util.*,org.slf4j.*,com.vmware.*,org.apache.xerces.*,javax.net.ssl.*,org.xml.sax.*,javax.xml.*,javax.naming.*,javax.crypto.*, com.sun.jersey.spi.container.servlet,org.eclipse.jetty.servlets</Import-Package> - <Embed-Dependency>*;scope=compile|runtime;artifactId=!appc-metric-bundle|sli-common|org.eclipse.osgi|slf4j-api|jcl-over-slf4j|mysql-connector-java|xml-apis|pax-*</Embed-Dependency> + <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName> + <Bundle-Version>${project.version}</Bundle-Version> + <!--<Bundle-SymbolicName>org.openecomp.appc.adapter.messaging.dmaap</Bundle-SymbolicName>--> + <Bundle-Activator>org.openecomp.appc.adapter.messaging.dmaap.AppcDmaapAdapterActivator</Bundle-Activator> + <Export-Package>org.openecomp.appc.adapter.messaging.*</Export-Package> + <Import-Package>!org.slf4j.event,org.openecomp.appc.adapter.message.*,org.openecomp.appc.metricservice.*,com.att.nsa.*,org.openecomp.sdnc.sli.*,org.osgi.framework.*,!org.osgi.service.event.*,org.osgi.service.*,org.osgi.util.*,org.slf4j.*,com.vmware.*,org.apache.xerces.*,javax.net.ssl.*,org.xml.sax.*,javax.xml.*,javax.naming.*,javax.crypto.*, com.sun.jersey.spi.container.servlet,org.eclipse.jetty.servlets</Import-Package> + <Embed-Dependency>*;scope=compile|runtime;artifactId=!appc-metric-bundle|appc-message-adapter-api|sli-common|org.eclipse.osgi|slf4j-api|jcl-over-slf4j|mysql-connector-java|xml-apis|pax-*</Embed-Dependency> <Embed-Transitive>true</Embed-Transitive> <Bundle-Blueprint>OSGI-INF/blueprint/blueprint.xml</Bundle-Blueprint> </instructions> diff --git a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/dmaap/AppcDmaapAdapterActivator.java b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/messaging/dmaap/AppcDmaapAdapterActivator.java index c02553dfe..c7be330cf 100644 --- a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/dmaap/AppcDmaapAdapterActivator.java +++ b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/messaging/dmaap/AppcDmaapAdapterActivator.java @@ -19,7 +19,7 @@ * ============LICENSE_END========================================================= */ -package org.openecomp.appc.adapter.dmaap; +package org.openecomp.appc.adapter.messaging.dmaap; import org.openecomp.appc.configuration.ConfigurationFactory; import com.att.eelf.configuration.EELFLogger; diff --git a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/dmaap/CommonHttpClient.java b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/messaging/dmaap/http/CommonHttpClient.java index 654ec6f7f..0d0450681 100644 --- a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/dmaap/CommonHttpClient.java +++ b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/messaging/dmaap/http/CommonHttpClient.java @@ -19,7 +19,7 @@ * ============LICENSE_END========================================================= */ -package org.openecomp.appc.adapter.dmaap; +package org.openecomp.appc.adapter.messaging.dmaap.http; import java.net.URI; diff --git a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/dmaap/DmaapConsumer.java b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/messaging/dmaap/http/HttpDmaapConsumerImpl.java index 6e16d896b..2145eaa70 100644 --- a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/dmaap/DmaapConsumer.java +++ b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/messaging/dmaap/http/HttpDmaapConsumerImpl.java @@ -19,14 +19,13 @@ * ============LICENSE_END========================================================= */ -package org.openecomp.appc.adapter.dmaap; +package org.openecomp.appc.adapter.messaging.dmaap.http; import java.net.URI; import java.util.ArrayList; import java.util.Collection; import java.util.List; - import com.att.eelf.configuration.EELFLogger; import com.att.eelf.configuration.EELFManager; @@ -38,10 +37,11 @@ import org.apache.http.client.utils.URIBuilder; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; import org.json.JSONArray; +import org.openecomp.appc.adapter.message.Consumer; -public class DmaapConsumer extends CommonHttpClient implements Consumer { +public class HttpDmaapConsumerImpl extends CommonHttpClient implements Consumer { - private static final EELFLogger LOG = EELFManager.getInstance().getLogger(DmaapConsumer.class); + private static final EELFLogger LOG = EELFManager.getInstance().getLogger(HttpDmaapConsumerImpl.class); // Default values private static final int DEFAULT_TIMEOUT_MS = 15000; @@ -54,17 +54,17 @@ public class DmaapConsumer extends CommonHttpClient implements Consumer { private boolean useHttps = false; - public DmaapConsumer(Collection<String> hosts, String topicName, String consumerName, String consumerId) { + public HttpDmaapConsumerImpl(Collection<String> hosts, String topicName, String consumerName, String consumerId) { this(hosts, topicName, consumerName, consumerId, null); } - public DmaapConsumer(Collection<String> hosts, String topicName, String consumerName, String consumerId, - String filter) { + public HttpDmaapConsumerImpl(Collection<String> hosts, String topicName, String consumerName, String consumerId, + String filter) { this(hosts, topicName, consumerName, consumerId, filter, null, null); } - public DmaapConsumer(Collection<String> hosts, String topicName, String consumerName, String consumerId, - String filter, String user, String password) { + public HttpDmaapConsumerImpl(Collection<String> hosts, String topicName, String consumerName, String consumerId, + String filter, String user, String password) { urls = new ArrayList<String>(); for (String host : hosts) { urls.add(String.format(URL_TEMPLATE, formatHostString(host), topicName, consumerName, consumerId)); @@ -155,9 +155,10 @@ public class DmaapConsumer extends CommonHttpClient implements Consumer { LOG.error("Interrupted while sleeping"); } } - - public void close(){ - //not used yet - } + + @Override + public void close() { + // Nothing to do + } } diff --git a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/dmaap/DmaapProducer.java b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/messaging/dmaap/http/HttpDmaapProducerImpl.java index 6845177b1..85e446dca 100644 --- a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/dmaap/DmaapProducer.java +++ b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/messaging/dmaap/http/HttpDmaapProducerImpl.java @@ -19,7 +19,7 @@ * ============LICENSE_END========================================================= */ -package org.openecomp.appc.adapter.dmaap; +package org.openecomp.appc.adapter.messaging.dmaap.http; import java.net.URI; import java.util.ArrayList; @@ -34,10 +34,11 @@ import com.att.eelf.configuration.EELFManager; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; +import org.openecomp.appc.adapter.message.Producer; -public class DmaapProducer extends CommonHttpClient implements Producer { +public class HttpDmaapProducerImpl extends CommonHttpClient implements Producer { - private static final EELFLogger LOG = EELFManager.getInstance().getLogger(DmaapProducer.class); + private static final EELFLogger LOG = EELFManager.getInstance().getLogger(HttpDmaapProducerImpl.class); private static final String CONTENT_TYPE = "application/cambria"; private static final String URL_TEMPLATE = "%s/events/%s"; @@ -47,7 +48,7 @@ public class DmaapProducer extends CommonHttpClient implements Producer { private boolean useHttps = false; - public DmaapProducer(Collection<String> urls, String topicName) { + public HttpDmaapProducerImpl(Collection<String> urls, String topicName) { hosts = new ArrayList<String>(); topics = new HashSet<String>(); topics.add(topicName); @@ -57,7 +58,7 @@ public class DmaapProducer extends CommonHttpClient implements Producer { } } - public DmaapProducer(Collection<String> urls, Set<String> topicNames) { + public HttpDmaapProducerImpl(Collection<String> urls, Set<String> topicNames) { hosts = new ArrayList<String>(); topics = topicNames; @@ -126,8 +127,9 @@ public class DmaapProducer extends CommonHttpClient implements Producer { String m = (msg == null) ? "" : msg; return String.format("%d.%d.%s%s", p.length(), m.length(), p, m); } - - public void close(){ - //not used yet - } + + @Override + public void close() { + // Nothing to do + } } diff --git a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/messaging/dmaap/impl/DmaapConsumerImpl.java b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/messaging/dmaap/impl/DmaapConsumerImpl.java new file mode 100644 index 000000000..342d52448 --- /dev/null +++ b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/messaging/dmaap/impl/DmaapConsumerImpl.java @@ -0,0 +1,231 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.adapter.messaging.dmaap.impl; + +import java.io.IOException; +import java.util.*; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +//import com.att.nsa.cambria.client.CambriaClientBuilders; +//import com.att.nsa.cambria.client.CambriaClientBuilders.ConsumerBuilder; +//import com.att.nsa.cambria.client.CambriaConsumer; + +import com.att.nsa.mr.client.MRClientFactory; +import com.att.nsa.mr.client.MRConsumer; +import org.apache.commons.lang3.StringUtils; +import org.openecomp.appc.adapter.message.Consumer; +import org.openecomp.appc.configuration.Configuration; +import org.openecomp.appc.configuration.ConfigurationFactory; +import org.openecomp.appc.metricservice.MetricRegistry; +import org.openecomp.appc.metricservice.MetricService; +import org.openecomp.appc.metricservice.impl.MetricServiceImpl; +import org.openecomp.appc.metricservice.metric.Metric; +import org.openecomp.appc.metricservice.metric.MetricType; +import org.openecomp.appc.metricservice.metric.DmaapRequestCounterMetric; +import org.openecomp.appc.metricservice.policy.PublishingPolicy; +import org.openecomp.appc.metricservice.publisher.LogPublisher; +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.ServiceReference; + +public class DmaapConsumerImpl implements Consumer { + + private static final EELFLogger LOG = EELFManager.getInstance().getLogger(DmaapConsumerImpl.class); + private static final Configuration configuration = ConfigurationFactory.getConfiguration(); + // Default values + private static final int DEFAULT_TIMEOUT_MS = 60000; + private static final int DEFAULT_LIMIT = 1000; + private static MetricRegistry metricRegistry; + private String topic; + private DmaapRequestCounterMetric dmaapKpiMetric; + private boolean isMetricEnabled=false; + private boolean useHttps = false; + private MRConsumer client = null; + private Properties props = null; + + + public DmaapConsumerImpl(Collection<String> urls, String topicName, String consumerGroupName, String consumerId,String user, String password) { + this(urls, topicName, consumerGroupName, consumerId,user, password,null); + + } + + public DmaapConsumerImpl(Collection<String> urls, String topicName, String consumerGroupName, String consumerId,String user, String password,String filter) { + this.topic = topicName; + this.props = new Properties(); + String urlsStr = StringUtils.join(urls, ','); + props.setProperty("host",urlsStr); + props.setProperty("group",consumerGroupName); + props.setProperty("id",consumerId); + props.setProperty("username",user); + props.setProperty("password",password); + if(filter != null) { + props.setProperty("filter", filter); + } + } + + + private void initMetric() { + LOG.debug("Metric getting initialized"); + MetricService metricService = getMetricservice(); + metricRegistry = metricService.createRegistry("APPC"); + dmaapKpiMetric = metricRegistry.metricBuilderFactory(). + dmaapRequestCounterBuilder(). + withName("DMAAP_KPI").withType(MetricType.COUNTER). + withRecievedMessage(0) + .withPublishedMessage(0) + .build(); + if (metricRegistry.register(dmaapKpiMetric)) { + Metric[] metrics = new Metric[]{dmaapKpiMetric}; + LogPublisher logPublisher = new LogPublisher(metricRegistry, metrics); + LogPublisher[] logPublishers = new LogPublisher[1]; + logPublishers[0] = logPublisher; + PublishingPolicy manuallyScheduledPublishingPolicy = metricRegistry.policyBuilderFactory(). + scheduledPolicyBuilder().withPublishers(logPublishers). + withMetrics(metrics). + build(); + LOG.debug("Policy getting initialized"); + manuallyScheduledPublishingPolicy.init(); + LOG.debug("Metric initialized"); + } + } + private MRConsumer getClient() { + return getClient(DEFAULT_TIMEOUT_MS, DEFAULT_LIMIT); + } + + /** + * @return An instance of MRConsumer created from our class variables + */ + private synchronized MRConsumer getClient(int waitMs, int limit) { + try { + props.setProperty("timeout",String.valueOf(waitMs)); + props.setProperty("limit",String.valueOf(limit)); + String topicProducerPropFileName = DmaapUtil.createConsumerPropFile(topic,props); + return MRClientFactory.createConsumer ( topicProducerPropFileName); + } catch (IOException e1) { + LOG.error("failed to createConsumer",e1); + return null; + } + } + + @Override + public synchronized void updateCredentials(String key, String secret) { + LOG.info(String.format("Setting auth to %s for %s", key, this.toString())); + String user = key; + String password = secret; + props.setProperty("user",String.valueOf(user)); + props.setProperty("password",String.valueOf(password)); + client = null; + } + + @Override + public List<String> fetch(int waitMs, int limit) { + Properties properties=configuration.getProperties(); + if(properties!=null && properties.getProperty("metric.enabled")!=null ){ + isMetricEnabled=Boolean.valueOf(properties.getProperty("metric.enabled")); + } + if(isMetricEnabled){ + initMetric(); + } + LOG.debug(String.format("Fetching up to %d records with %dms wait on %s", limit, waitMs, this.toString())); + List<String> out = new ArrayList<String>(); + + // Create client once and reuse it on subsequent fetches. This is + // to support failover to other servers in the DMaaP cluster. + if (client == null) { + LOG.info("Getting DMaaP Client ..."); + client = getClient(waitMs, limit); + } + try { + for (String s : client.fetch(waitMs, limit)) { + out.add(s); + if(isMetricEnabled){ + ((DmaapRequestCounterMetric)metricRegistry.metric("DMAAP_KPI")).incrementRecievedMessage(); + } + } + LOG.debug(String.format("Got %d records from %s", out.size(), this.toString())); + } catch (Exception e) { + // Connection exception + LOG.error(String.format("Dmaap Connection Issue Detected. %s", e.getMessage())); + e.printStackTrace(); + try { + LOG.warn(String.format("Sleeping for %dms to compensate for connection failure", waitMs)); + Thread.sleep(waitMs); + } catch (InterruptedException e2) { + LOG.warn(String.format("Failed to wait for %dms after bad fetch", waitMs)); + } + } + + + return out; + } + + /** + * Close consumer Dmaap client + */ + @Override + public void close() { + LOG.debug("Closing Dmaap consumer client...."); + if (client != null) { + client.close(); + } + } + + @Override + public List<String> fetch() { + return fetch(DEFAULT_TIMEOUT_MS, DEFAULT_LIMIT); + } + + @Override + public String toString() { + String hostStr = (props == null || props.getProperty("host") == null? "N/A" : props.getProperty("host")); + String group = (props == null || props.getProperty("group") == null? "N/A" : props.getProperty("group")); + String id = (props == null || props.getProperty("id") == null? "N/A" : props.getProperty("id")); + return String.format("Consumer %s/%s listening to %s on [%s]", group, id, topic, hostStr); + } + + @Override + public void useHttps(boolean yes) { + useHttps = yes; + } + + + private MetricService getMetricservice() { + BundleContext bctx = FrameworkUtil.getBundle(MetricService.class).getBundleContext(); + // Get AAIadapter reference + ServiceReference sref = bctx.getServiceReference(MetricService.class.getName()); + if (sref != null) { + LOG.info("Metric Service from bundlecontext"); + return (MetricServiceImpl) bctx.getService(sref); + + } else { + LOG.info("Metric Service error from bundlecontext"); + LOG.warn("Cannot find service reference for org.openecomp.appc.metricservice.MetricService"); + return null; + + } + } + + public Metric getMetric(String name){ + return metricRegistry.metric(name); + } +} diff --git a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/messaging/dmaap/impl/DmaapProducerImpl.java b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/messaging/dmaap/impl/DmaapProducerImpl.java new file mode 100644 index 000000000..79d6b3db7 --- /dev/null +++ b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/messaging/dmaap/impl/DmaapProducerImpl.java @@ -0,0 +1,220 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.adapter.messaging.dmaap.impl; + +import java.io.*; +import java.util.*; +import java.util.concurrent.TimeUnit; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +//import com.att.nsa.cambria.client.CambriaBatchingPublisher; +//import com.att.nsa.cambria.client.CambriaClientBuilders; +//import com.att.nsa.cambria.client.CambriaClientBuilders.PublisherBuilder; + +import com.att.nsa.mr.client.MRBatchingPublisher; +import com.att.nsa.mr.client.MRClientFactory; +import org.apache.commons.lang3.StringUtils; +import org.openecomp.appc.adapter.message.Producer; +import org.openecomp.appc.adapter.messaging.dmaap.impl.DmaapUtil; +import org.openecomp.appc.configuration.Configuration; +import org.openecomp.appc.configuration.ConfigurationFactory; +import org.openecomp.appc.metricservice.MetricRegistry; +import org.openecomp.appc.metricservice.MetricService; +import org.openecomp.appc.metricservice.metric.Metric; +import org.openecomp.appc.metricservice.metric.MetricType; +import org.openecomp.appc.metricservice.metric.DmaapRequestCounterMetric; +import org.openecomp.appc.metricservice.policy.PublishingPolicy; +import org.openecomp.appc.metricservice.publisher.LogPublisher; +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.ServiceReference; + +public class DmaapProducerImpl implements Producer { + + private static final EELFLogger LOG = EELFManager.getInstance().getLogger(DmaapProducerImpl.class); + private static final Configuration configuration = ConfigurationFactory.getConfiguration(); + + private Set<String> topics = new HashSet<String>(); + + private Properties props = null; + private static MetricRegistry metricRegistry; + private boolean useHttps = false; + private DmaapRequestCounterMetric dmaapKpiMetric; + private boolean isMetricEnabled=false; + + private Set<MRBatchingPublisher> clients; + + + public DmaapProducerImpl(Collection<String> urls, String topicName, String user, String password) { + this(urls, (Set<String>)null, user, password); + this.topics = new HashSet<>(); + if (topicName != null) { + for (String topic : topicName.split(",")) { + topics.add(topic); + } + } + } + + public DmaapProducerImpl(Collection<String> urls, Set<String> topicNames, String user, String password) { + topics = topicNames; + if(urls == null || user == null || password == null){ + throw new IllegalArgumentException("one of these mandaory argument is null: urls, user, password" ); + } + this.props = new Properties(); + String urlsStr = StringUtils.join(urls, ','); + props.setProperty("host",urlsStr); + props.setProperty("id", UUID.randomUUID().toString()); + props.setProperty("username",user); + props.setProperty("password",password); + } + private void initMetric() { + LOG.debug("Metric getting initialized"); + MetricService metricService = getMetricservice(); + metricRegistry=metricService.createRegistry("APPC"); + dmaapKpiMetric = metricRegistry.metricBuilderFactory(). + dmaapRequestCounterBuilder(). + withName("DMAAP_KPI").withType(MetricType.COUNTER). + withRecievedMessage(0) + .withPublishedMessage(0) + .build(); + if(metricRegistry.register(dmaapKpiMetric)) { + Metric[] metrics = new Metric[]{dmaapKpiMetric}; + LogPublisher logPublisher = new LogPublisher(metricRegistry, metrics); + LogPublisher[] logPublishers = new LogPublisher[1]; + logPublishers[0] = logPublisher; + PublishingPolicy manuallyScheduledPublishingPolicy = metricRegistry.policyBuilderFactory(). + scheduledPolicyBuilder().withPublishers(logPublishers). + withMetrics(metrics). + build(); + LOG.debug("Policy getting initialized"); + manuallyScheduledPublishingPolicy.init(); + LOG.debug("Metric initialized"); + } + + } + private Set<MRBatchingPublisher> getClients() { + Set<MRBatchingPublisher> out = new HashSet<MRBatchingPublisher>(); + for (String topic : topics) { + try { + String topicProducerPropFileName = DmaapUtil.createProducerPropFile(topic,props); + final MRBatchingPublisher client = MRClientFactory.createBatchingPublisher (topicProducerPropFileName); + out.add(client); + } catch (Exception e) { + e.printStackTrace(); + } + } + + return out; + } + + @Override + public synchronized void updateCredentials(String key, String secret) { + LOG.info(String.format("Setting auth to %s for %s", key, this.toString())); + String user = key; + String password = secret; + props.setProperty("user",String.valueOf(user)); + props.setProperty("password",String.valueOf(password)); + clients = null; + } + + @Override + public boolean post(String partition, String data) { + boolean success = true; + Properties properties=configuration.getProperties(); + if(properties!=null && properties.getProperty("metric.enabled")!=null ){ + isMetricEnabled=Boolean.valueOf(properties.getProperty("metric.enabled")); + } + if(isMetricEnabled){ + initMetric(); + } + + // Create clients once and reuse them on subsequent posts. This is + // to support failover to other servers in the Dmaap cluster. + if ((clients == null) || (clients.isEmpty())) { + LOG.info("Getting CambriaBatchingPublisher Clients ..."); + clients = getClients(); + } + + for (MRBatchingPublisher client : clients) { + try { + LOG.debug(String.format("Posting %s to %s", data, client)); + client.send(partition, data); + } catch (IOException e) { + e.printStackTrace(); + success = false; + } + } + if(isMetricEnabled){ + ( (DmaapRequestCounterMetric) metricRegistry.metric("DMAAP_KPI")).incrementPublishedMessage(); + } + return success; + } + + /** + * Close producer Dmaap client + */ + @Override + public void close() { + if ((clients == null) || (clients.isEmpty())) { + return; + } + + LOG.debug("Closing Dmaap producer clients...."); + for (MRBatchingPublisher client : clients) { + try { + client.close(1, TimeUnit.SECONDS); + } catch (IOException | InterruptedException e) { + LOG.warn(String.format("Failed to cleanly close Dmaap connection for [%s]", client)); + e.printStackTrace(); + } + } + } + + @Override + public void useHttps(boolean yes) { + useHttps = yes; + } + + private MetricService getMetricservice() { +/* + return AppcDmaapAdapterActivator.getMetricService(); +*/ + + BundleContext bctx = FrameworkUtil.getBundle(MetricService.class).getBundleContext(); + ServiceReference sref = bctx.getServiceReference(MetricService.class.getName()); + if (sref != null) { + LOG.info("Metric Service from bundlecontext"); + return (MetricService) bctx.getService(sref); + + } else { + LOG.info("Metric Service error from bundlecontext"); + LOG.warn("Cannot find service reference for org.openecomp.appc.metricservice.MetricService"); + return null; + + } + } + + public Metric getMetric(String name){ + return metricRegistry.metric(name); + } +} diff --git a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/messaging/dmaap/impl/DmaapUtil.java b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/messaging/dmaap/impl/DmaapUtil.java new file mode 100644 index 000000000..39857b856 --- /dev/null +++ b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/messaging/dmaap/impl/DmaapUtil.java @@ -0,0 +1,83 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.adapter.messaging.dmaap.impl; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +public class DmaapUtil { + private final static String delimiter = "_"; + private static String createPreferredRouteFileIfNotExist(String topic) throws IOException { + String topicPreferredRouteFileName = null; + topicPreferredRouteFileName = topic+"preferredRoute.properties"; + File fo= new File(topicPreferredRouteFileName); + if(!fo.exists()) { + ClassLoader classLoader = DmaapUtil.class.getClassLoader(); + InputStream inputStream = classLoader.getResourceAsStream("preferredRoute.txt"); + Properties props = new Properties(); + props.load(inputStream); + String fileName = topic != null ? topic+delimiter+"MR1" : delimiter+"MR1"; + props.setProperty("preferredRouteKey", fileName); + topicPreferredRouteFileName = topic + "preferredRoute.properties"; + props.store(new FileOutputStream(topicPreferredRouteFileName), "preferredRoute.properties file created on the fly for topic:" + topic + " on:" + System.currentTimeMillis()); + } + return topicPreferredRouteFileName; + } + + public static String createConsumerPropFile(String topic, Properties props)throws IOException { + String defaultProfFileName = "consumer.properties"; + String topicConsumerPropFileName = createConsumerProducerPropFile(topic, defaultProfFileName,props); + return topicConsumerPropFileName; + } + + public static String createProducerPropFile(String topic, Properties props)throws IOException { + String defaultProfFileName = "producer.properties"; + String topicConsumerPropFileName = createConsumerProducerPropFile(topic, defaultProfFileName,props); + return topicConsumerPropFileName; + } + + private static String createConsumerProducerPropFile(String topic, String defaultProfFileName, Properties props) throws IOException { + ClassLoader classLoader = DmaapUtil.class.getClassLoader(); + InputStream inputStream = classLoader.getResourceAsStream(defaultProfFileName); + Properties defaultProps = new Properties(); + defaultProps.load(inputStream); + defaultProps.setProperty("topic",topic); + + String preferredRouteFileName = DmaapUtil.createPreferredRouteFileIfNotExist(topic); + if(props != null && !props.isEmpty()){ + defaultProps.putAll(props); + } + defaultProps.setProperty("topic",topic); + defaultProps.setProperty("DME2preferredRouterFilePath",preferredRouteFileName); + String id = defaultProps.getProperty("id"); + String topicConsumerPropFileName = defaultProfFileName; + topicConsumerPropFileName = id != null ? id+delimiter+topicConsumerPropFileName : delimiter+topicConsumerPropFileName; + topicConsumerPropFileName = topic != null ? topic+delimiter+topicConsumerPropFileName : delimiter+topicConsumerPropFileName; + + defaultProps.store(new FileOutputStream(topicConsumerPropFileName), defaultProfFileName+" file created on the fly for topic:"+topic+" on:"+System.currentTimeMillis()); + return topicConsumerPropFileName; + } + +} diff --git a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/dmaap/impl/EventSenderImpl.java b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/messaging/dmaap/impl/EventSenderDmaapImpl.java index 0f7d40f5b..c671c6fdb 100644 --- a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/dmaap/impl/EventSenderImpl.java +++ b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/messaging/dmaap/impl/EventSenderDmaapImpl.java @@ -19,33 +19,33 @@ * ============LICENSE_END========================================================= */ -package org.openecomp.appc.adapter.dmaap.impl; +package org.openecomp.appc.adapter.messaging.dmaap.impl; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import org.openecomp.sdnc.sli.SvcLogicContext; import java.util.*; import java.util.concurrent.ConcurrentHashMap; -import org.openecomp.appc.adapter.dmaap.EventSender; -import org.openecomp.appc.adapter.dmaap.Producer; -import org.openecomp.appc.adapter.dmaap.DmaapDestination; -import org.openecomp.appc.adapter.dmaap.event.EventHeader; -import org.openecomp.appc.adapter.dmaap.event.EventMessage; -import org.openecomp.appc.adapter.dmaap.event.EventStatus; -import org.openecomp.appc.adapter.dmaap.DmaapProducer; +import org.openecomp.appc.adapter.message.EventSender; +import org.openecomp.appc.adapter.message.MessageDestination; +import org.openecomp.appc.adapter.message.Producer; +import org.openecomp.appc.adapter.message.event.EventHeader; +import org.openecomp.appc.adapter.message.event.EventMessage; +import org.openecomp.appc.adapter.message.event.EventStatus; +import org.openecomp.appc.adapter.messaging.dmaap.impl.DmaapProducerImpl; import org.openecomp.appc.configuration.Configuration; import org.openecomp.appc.configuration.ConfigurationFactory; import org.openecomp.appc.exceptions.APPCException; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; -import org.openecomp.sdnc.sli.SvcLogicContext; - -public class EventSenderImpl implements EventSender +public class EventSenderDmaapImpl implements EventSender { - private static final EELFLogger LOG = EELFManager.getInstance().getLogger(EventSenderImpl.class); - public static final String EVENT_TOPIC_WRITE = "event.topic.write"; - public static final String EVENT_CLIENT_KEY = "event.client.key"; - public static final String EVENT_CLIENT_SECRET = "event.client.secret"; - public static final String EVENT_POOL_MEMBERS = "event.pool.members"; + private static final EELFLogger LOG = EELFManager.getInstance().getLogger(EventSenderDmaapImpl.class); + public static final String EVENT_TOPIC_WRITE = "dmaap.event.topic.write"; + public static final String DMAAP_USERNAME = "dmaap.appc.username"; + public static final String DMAAP_PASSWORD = "dmaap.appc.password"; + public static final String EVENT_POOL_MEMBERS = "dmaap.event.pool.members"; private static Configuration configuration = ConfigurationFactory.getConfiguration(); @@ -59,21 +59,21 @@ public class EventSenderImpl implements EventSender this.producerMap = producerMap; } - public EventSenderImpl(){ + public EventSenderDmaapImpl(){ } public void initialize(){ Properties properties = configuration.getProperties(); String writeTopic; - String apiKey; - String apiSecret; + String username; + String password; final List<String> pool = new ArrayList<>(); - for(DmaapDestination destination:DmaapDestination.values()){ + for(MessageDestination destination: MessageDestination.values()){ writeTopic = properties.getProperty(destination + "." + EVENT_TOPIC_WRITE); - apiKey = properties.getProperty(destination + "." + EVENT_CLIENT_KEY); - apiSecret = properties.getProperty(destination + "." + EVENT_CLIENT_SECRET); + username = properties.getProperty(destination + "." + DMAAP_USERNAME); + password = properties.getProperty(destination + "." + DMAAP_PASSWORD); String hostNames = properties.getProperty(destination + "." + EVENT_POOL_MEMBERS); if (hostNames != null && !hostNames.isEmpty()) { @@ -83,12 +83,8 @@ public class EventSenderImpl implements EventSender LOG.debug(String.format("pool = %s, taken from property: %s", pool, destination + "." + EVENT_POOL_MEMBERS)); LOG.debug(String.format("writeTopic = %s, taken from property: %s", writeTopic, destination + "." + EVENT_TOPIC_WRITE)); - LOG.debug(String.format("apiKey = %s, taken from property: %s", apiKey, destination + "." + EVENT_CLIENT_KEY)); - Producer producer = new DmaapProducer(pool, writeTopic); - - if (apiKey != null && apiSecret != null) { - producer.updateCredentials(apiKey, apiSecret); - } + LOG.debug(String.format("username = %s, taken from property: %s", username, destination + "." + DMAAP_USERNAME)); + Producer producer = new DmaapProducerImpl(pool, writeTopic,username, password); for (String url : pool) { if (url.contains("3905") || url.contains("https")) { @@ -103,7 +99,7 @@ public class EventSenderImpl implements EventSender } @Override - public boolean sendEvent(DmaapDestination destination,EventMessage msg) { + public boolean sendEvent(MessageDestination destination, EventMessage msg) { String jsonStr = msg.toJson(); String id = msg.getEventHeader().getEventId(); LOG.info(String.format("Posting Message [%s - %s]", id, jsonStr)); @@ -112,7 +108,43 @@ public class EventSenderImpl implements EventSender } @Override - public boolean sendEvent(DmaapDestination destination,Map<String, String> params, SvcLogicContext ctx) throws APPCException { + public boolean sendEvent(MessageDestination destination, EventMessage msg, String eventTopicName) { + String jsonStr = msg.toJson(); + String id = msg.getEventHeader().getEventId(); + LOG.info(String.format("Posting Message [%s - %s]", id, jsonStr)); + Producer producer = createProducer(destination, eventTopicName); + return producer.post(id, jsonStr); + } + + private Producer createProducer(MessageDestination destination, String eventTopicName) { + Properties properties = configuration.getProperties(); + final List<String> pool = new ArrayList<>(); + String username = properties.getProperty(destination + "." + DMAAP_USERNAME); + String password = properties.getProperty(destination + "." + DMAAP_PASSWORD); + String hostNames = properties.getProperty(destination + "." + EVENT_POOL_MEMBERS); + + if (hostNames != null && !hostNames.isEmpty()) { + LOG.debug(String.format("hostNames = %s, taken from property: %s", hostNames, destination + "." + EVENT_POOL_MEMBERS)); + Collections.addAll(pool, hostNames.split(",")); + } + + LOG.debug(String.format("pool = %s, taken from property: %s", pool, destination + "." + EVENT_POOL_MEMBERS)); + LOG.debug(String.format("writeTopic = %s, taken from property: %s", eventTopicName, destination + "." + EVENT_TOPIC_WRITE)); + LOG.debug(String.format("username = %s, taken from property: %s", username, destination + "." + DMAAP_USERNAME)); + Producer producer = new DmaapProducerImpl(pool, eventTopicName,username, password); + + for (String url : pool) { + if (url.contains("3905") || url.contains("https")) { + LOG.debug("Producer should use HTTPS"); + producer.useHttps(true); + break; + } + } + return producer; + } + + @Override + public boolean sendEvent(MessageDestination destination, Map<String, String> params, SvcLogicContext ctx) throws APPCException { if (params == null) { String message = "Parameters map is empty (null)"; @@ -134,10 +166,10 @@ public class EventSenderImpl implements EventSender LOG.error(message); throw new APPCException(message); } - EventMessage dmaapEventMessage = new EventMessage( + EventMessage eventMessage = new EventMessage( new EventHeader(eventTime, apiVer, eventId), new EventStatus(code, reason)); - return sendEvent(destination,dmaapEventMessage); + return sendEvent(destination,eventMessage); } } diff --git a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml index a8caf666f..eefe8e504 100644 --- a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml +++ b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -24,10 +24,10 @@ <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd"> - <bean id="eventSenderBean" class="org.openecomp.appc.adapter.dmaap.impl.EventSenderImpl" + <bean id="eventSenderBean" class="org.openecomp.appc.adapter.messaging.dmaap.impl.EventSenderDmaapImpl" init-method="initialize" scope="singleton"> </bean> - <service id="eventSenderService" interface="org.openecomp.appc.adapter.dmaap.EventSender" ref="eventSenderBean" /> + <service id="eventSenderService" interface="org.openecomp.appc.adapter.message.EventSender" ref="eventSenderBean" /> </blueprint> diff --git a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/resources/consumer.properties b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/resources/consumer.properties new file mode 100644 index 000000000..facd33e4d --- /dev/null +++ b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/resources/consumer.properties @@ -0,0 +1,57 @@ +### +# ============LICENSE_START======================================================= +# openECOMP : APP-C +# ================================================================================ +# Copyright (C) 2017 AT&T Intellectual Property. All rights +# reserved. +# ================================================================================ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============LICENSE_END========================================================= +### + +#TransportType-Specify which way user want to use. I.e. <HTTPAAF,DME2,HTTPAUTH > +TransportType=HTTPAAF +Latitude =50.000000 +Longitude =-100.000000 +Version =1.0 +ServiceName =dmaap-v1.dev.dmaap.dt.saat.acsi.openecomp.org/events +Environment =TEST +Partner=BOT_R +routeOffer=MR1 +SubContextPath =/ +Protocol =http +MethodType =GET +username =admin +password =admin +contenttype =application/json +authKey=01234567890abcde:01234567890abcdefghijklmn +authDate=2016-02-18T13:57:37-0800 +host=127.0.0.1 +topic=org.openecomp.appc.UNIT-TEST +group=jmsgrp +id=2 +timeout=15000 +limit=1000 +filter= +AFT_DME2_EXCHANGE_REQUEST_HANDLERS=com.att.nsa.test.PreferredRouteRequestHandler +AFT_DME2_EXCHANGE_REPLY_HANDLERS=com.att.nsa.test.PreferredRouteReplyHandler +AFT_DME2_REQ_TRACE_ON=true +AFT_ENVIRONMENT=AFTUAT +AFT_DME2_EP_CONN_TIMEOUT=15000 +AFT_DME2_ROUNDTRIP_TIMEOUT_MS=240000 +AFT_DME2_EP_READ_TIMEOUT_MS=50000 +sessionstickinessrequired=NO +DME2preferredRouterFilePath=preferredRoute.txt + + + diff --git a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/resources/preferredRoute.txt b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/resources/preferredRoute.txt new file mode 100644 index 000000000..662b0aa7d --- /dev/null +++ b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/resources/preferredRoute.txt @@ -0,0 +1 @@ +preferredRouteKey=MR1
\ No newline at end of file diff --git a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/resources/producer.properties b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/resources/producer.properties new file mode 100644 index 000000000..4901d517e --- /dev/null +++ b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/resources/producer.properties @@ -0,0 +1,52 @@ +### +# ============LICENSE_START======================================================= +# openECOMP : APP-C +# ================================================================================ +# Copyright (C) 2017 AT&T Intellectual Property. All rights +# reserved. +# ================================================================================ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============LICENSE_END========================================================= +### + +#TransportType-Specify which way user want to use. I.e. <HTTPAAF,DME2,HTTPAUTH > +TransportType=HTTPAAF +Latitude =50.000000 +Longitude =-100.000000 +Version =1.0 +ServiceName =dmaap-v1.dev.dmaap.dt.saat.acsi.openecomp.org/events +Environment =TEST +Partner=BOT_R +SubContextPath =/ +Protocol =http +MethodType =POST +username =admin +password =admin +contenttype = application/json +authKey=01234567890abcde:01234567890abcdefghijklmn +authDate=2016-07-20T11:30:56-0700 +host=127.0.0.1 +topic=org.openecomp.appc.UNIT-TEST +partition=2 +maxBatchSize=100 +maxAgeMs=250 +AFT_DME2_EXCHANGE_REQUEST_HANDLERS=com.att.nsa.test.PreferredRouteRequestHandler +AFT_DME2_EXCHANGE_REPLY_HANDLERS=com.att.nsa.test.PreferredRouteReplyHandler +AFT_DME2_REQ_TRACE_ON=true +AFT_ENVIRONMENT=AFTUAT +AFT_DME2_EP_CONN_TIMEOUT=15000 +AFT_DME2_ROUNDTRIP_TIMEOUT_MS=240000 +AFT_DME2_EP_READ_TIMEOUT_MS=50000 +sessionstickinessrequired=NO +DME2preferredRouterFilePath=preferredRoute.txt +MessageSentThreadOccurance=50 diff --git a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/test/java/org/openecomp/appc/adapter/messaging/dmaap/SimpleExamplePublisher.java b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/test/java/org/openecomp/appc/adapter/messaging/dmaap/SimpleExamplePublisher.java new file mode 100644 index 000000000..a0ae92ea8 --- /dev/null +++ b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/test/java/org/openecomp/appc/adapter/messaging/dmaap/SimpleExamplePublisher.java @@ -0,0 +1,134 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.adapter.messaging.dmaap; + +import java.io.*; +import java.util.List; +import java.util.Properties; +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +import com.att.nsa.mr.client.MRConsumer; +import org.json.JSONObject; +import org.openecomp.appc.adapter.messaging.dmaap.impl.DmaapUtil; + +import com.att.nsa.mr.client.MRBatchingPublisher; +import com.att.nsa.mr.client.MRClientFactory; +import com.att.nsa.mr.client.MRPublisher.message; + + +/** + *An example of how to use the Java publisher. + */ +public class SimpleExamplePublisher +{ + + public static void main(String []args) throws InterruptedException, Exception{ + int msgCount = 1; + SimpleExamplePublisher publisher = new SimpleExamplePublisher(); + + int i=0; + + String topicProducerPropFileName = DmaapUtil.createProducerPropFile("org.openecomp.appc.UNIT-TEST", null); + while (i< msgCount) + { + publisher.publishMessage(topicProducerPropFileName,i); + i++; + } + + fetchMessage(); + } + + + public void publishMessage( String producerFilePath,int count ) throws IOException, InterruptedException, Exception + { + // create our publisher + final MRBatchingPublisher pub = MRClientFactory.createBatchingPublisher (producerFilePath); + // publish some messages + final JSONObject msg1 = new JSONObject (); + msg1.put ( "Partition:2", "Message:" +count); + //msg1.put ( "greeting", "Hello .." ); + + pub.send ( "2", msg1.toString()); + // close the publisher to make sure everything's sent before exiting. The batching + // publisher interface allows the app to get the set of unsent messages. It could + // write them to disk, for example, to try to send them later. + final List<message> stuck = pub.close ( 20, TimeUnit.SECONDS ); + if ( stuck.size () > 0 ) + { + System.err.println ( stuck.size() + " messages unsent" ); + } + else + { + System.out.println ( "Clean exit; all messages sent." ); + } + } + + + public static void fetchMessage() + { + int count = 0; + + try + { + String topic = "org.openecomp.appc.UNIT-TEST"; + Properties props = new Properties(); + props.put("id", "1"); + props.put("group", "group1"); + String topicConsumerPropFileName1 = DmaapUtil.createConsumerPropFile(topic,props); + final MRConsumer consumer1 = MRClientFactory.createConsumer ( topicConsumerPropFileName1); + + props = new Properties(); + props.put("id", "2"); + props.put("group", "group2"); + String topicConsumerPropFileName2 = DmaapUtil.createConsumerPropFile(topic,props); + final MRConsumer consumer2 = MRClientFactory.createConsumer ( topicConsumerPropFileName2); + + for ( String msg : consumer1.fetch () ) + { + count++; + System.out.println ( "consumer1 "+count + ": " + msg ); + } + for ( String msg : consumer2.fetch () ) + { + count++; + System.out.println ( "consumer1 "+count + ": " + msg ); + } + + + } + catch ( Exception x ) + { + System.out.println("inside cons exc"); + System.err.println ( x.getClass().getName () + ": " + x.getMessage () ); + } + } +} + + + + + + + + + diff --git a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/test/java/org/openecomp/appc/adapter/dmaap/TestAppcDmaapAdapterActivator.java b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/test/java/org/openecomp/appc/adapter/messaging/dmaap/TestAppcDmaapAdapterActivator.java index e97014198..6626938a7 100644 --- a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/test/java/org/openecomp/appc/adapter/dmaap/TestAppcDmaapAdapterActivator.java +++ b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/test/java/org/openecomp/appc/adapter/messaging/dmaap/TestAppcDmaapAdapterActivator.java @@ -19,13 +19,13 @@ * ============LICENSE_END========================================================= */ -package org.openecomp.appc.adapter.dmaap; +package org.openecomp.appc.adapter.messaging.dmaap; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; import org.junit.Test; -import org.openecomp.appc.adapter.dmaap.AppcDmaapAdapterActivator; +import org.openecomp.appc.adapter.messaging.dmaap.AppcDmaapAdapterActivator; public class TestAppcDmaapAdapterActivator { diff --git a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/test/java/org/openecomp/appc/adapter/messaging/dmaap/TestDmaapConsuming.java b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/test/java/org/openecomp/appc/adapter/messaging/dmaap/TestDmaapConsuming.java new file mode 100644 index 000000000..23647d61a --- /dev/null +++ b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/test/java/org/openecomp/appc/adapter/messaging/dmaap/TestDmaapConsuming.java @@ -0,0 +1,84 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.adapter.messaging.dmaap; + + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.openecomp.appc.adapter.message.Consumer; +import org.openecomp.appc.adapter.messaging.dmaap.http.HttpDmaapConsumerImpl; +import org.openecomp.appc.adapter.messaging.dmaap.impl.DmaapConsumerImpl; +import org.openecomp.appc.configuration.Configuration; +import org.openecomp.appc.configuration.ConfigurationFactory; +import org.junit.Ignore; + +import java.util.Arrays; +import java.util.List; + +/** + * Must have a DMaaP cluster or simulator up and running + * Update the hostname, topic, client properties in + * resources/org/openecomp/appc/default.properties + * + */ +public class TestDmaapConsuming { + + private static Consumer dmaapConsumer; + private static Consumer httpConsumer; + + @BeforeClass + public static void setUp() { + + Configuration configuration = ConfigurationFactory.getConfiguration(); + + List<String> hosts = Arrays.asList(configuration.getProperty("poolMembers").split(",")); + String topic = configuration.getProperty("topic.read"); + String consumerName = configuration.getProperty("client.name"); + String consumerId = configuration.getProperty("client.name.id"); + String msgFilter = configuration.getProperty("message.filter"); + String user = configuration.getProperty("dmaap.appc.username"); + String password = configuration.getProperty("dmaap.appc.password"); + + httpConsumer = new HttpDmaapConsumerImpl(hosts, topic, consumerName, consumerId, msgFilter); + dmaapConsumer = new DmaapConsumerImpl(hosts, topic, consumerName, consumerId,user,password,msgFilter); + } + + @Test + @Ignore + public void testHttpFetchMessages() { + testFetchMessages(httpConsumer); + } + + @Test + @Ignore + public void testFetchMessages() { + testFetchMessages(dmaapConsumer); + } + + private void testFetchMessages(Consumer consumer) { + List<String> messages = consumer.fetch(1000, 100); + Assert.assertNotNull(messages); + Assert.assertFalse(messages.isEmpty()); + } + +} diff --git a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/test/java/org/openecomp/appc/adapter/messaging/dmaap/TestDmaapEventSender.java b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/test/java/org/openecomp/appc/adapter/messaging/dmaap/TestDmaapEventSender.java new file mode 100644 index 000000000..b35f9871d --- /dev/null +++ b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/test/java/org/openecomp/appc/adapter/messaging/dmaap/TestDmaapEventSender.java @@ -0,0 +1,169 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.adapter.messaging.dmaap; + +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; +import org.mockito.Matchers; +import org.mockito.Mockito; +import org.openecomp.appc.adapter.message.MessageDestination; +import org.openecomp.appc.adapter.message.Producer; +import org.openecomp.appc.adapter.message.event.EventHeader; +import org.openecomp.appc.adapter.message.event.EventMessage; +import org.openecomp.appc.adapter.message.event.EventStatus; +import org.openecomp.appc.adapter.messaging.dmaap.impl.DmaapProducerImpl; +import org.openecomp.appc.adapter.messaging.dmaap.impl.EventSenderDmaapImpl; +import org.openecomp.appc.configuration.Configuration; +import org.openecomp.appc.configuration.ConfigurationFactory; +import org.openecomp.appc.exceptions.APPCException; + +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + + +public class TestDmaapEventSender { + + private static Properties props; + private static Map<String,Producer> producerMap = new HashMap<>(); + private static EventMessage eventMessage; + + @BeforeClass + public static void setUp() { + + Configuration configuration = ConfigurationFactory.getConfiguration(); // test.properties file placed in home dir. + + props = new Properties(); + props.setProperty(EventSenderDmaapImpl.EVENT_POOL_MEMBERS, + configuration.getProperty(EventSenderDmaapImpl.EVENT_POOL_MEMBERS) != null ? + configuration.getProperty(EventSenderDmaapImpl.EVENT_POOL_MEMBERS) : "member1,member2,member3"); + props.setProperty(EventSenderDmaapImpl.EVENT_TOPIC_WRITE, + configuration.getProperty(EventSenderDmaapImpl.EVENT_TOPIC_WRITE) != null ? + configuration.getProperty(EventSenderDmaapImpl.EVENT_TOPIC_WRITE) : "topic1"); + + String eventClientKey = configuration.getProperty(EventSenderDmaapImpl.DMAAP_USERNAME); + if (eventClientKey != null) { + props.setProperty(EventSenderDmaapImpl.DMAAP_USERNAME,eventClientKey); + } + String eventClientSecret = configuration.getProperty(EventSenderDmaapImpl.DMAAP_PASSWORD); + if (eventClientSecret != null) { + props.setProperty(EventSenderDmaapImpl.DMAAP_PASSWORD, eventClientSecret); + } + + Producer producer = Mockito.mock(DmaapProducerImpl.class); + producerMap.put(MessageDestination.DCAE.toString(),producer); + Mockito.when(producer.post(Matchers.anyString(), Matchers.anyString())).thenReturn(true); + + eventMessage = new EventMessage( + new EventHeader("2016-03-15T10:59:33.79Z", "1.01", "17"), + new EventStatus(404, "No krokodil found")); + } + + @Test + @Ignore // requires connection to a live DMaaP server + public void testDmaapEventSenderWithProperties() { + EventSenderDmaapImpl eventSender = new EventSenderDmaapImpl(); + eventSender.initialize(); + eventSender.setProducerMap(producerMap); + Assert.assertTrue(eventSender.sendEvent(MessageDestination.DCAE, eventMessage)); + } + + @Test + public void testDmaapEventSenderWithNullProperties() { + EventSenderDmaapImpl eventSender = new EventSenderDmaapImpl(); +// eventSender.initialize(); + eventSender.setProducerMap(producerMap); + Assert.assertTrue(eventSender.sendEvent(MessageDestination.DCAE, eventMessage)); + } + + /* + * This test runs agains a real Dmaap (or a simulator) that should be cofigured in test.properties file. + */ + @Test + @Ignore // requires connection to a live DMaaP server + public void testDmaapEventSenderWithDmaapSim() { + EventSenderDmaapImpl eventSender = new EventSenderDmaapImpl(); + eventSender.initialize(); + Assert.assertTrue(eventSender.sendEvent(MessageDestination.DCAE, eventMessage)); + } + + + @Test + @Ignore // requires connection to a live DMaaP server + public void testDmaapEventSenderDG() throws APPCException { + EventSenderDmaapImpl eventSender = new EventSenderDmaapImpl(); + eventSender.initialize(); + eventSender.setProducerMap(producerMap); + Map<String,String> params = new HashMap<>(); + + params.put("eventTime", eventMessage.getEventHeader().getEventTime()); + params.put("apiVer", eventMessage.getEventHeader().getApiVer()); + params.put("eventId", eventMessage.getEventHeader().getEventId()); + params.put("reason", eventMessage.getEventStatus().getReason()); + params.put("code", "200"); + + Assert.assertTrue(eventSender.sendEvent(MessageDestination.DCAE,params, new SvcLogicContext())); + } + + @Test(expected = APPCException.class) + @Ignore // requires connection to a live DMaaP server + public void testDmaapEventSenderDGNoParams() throws APPCException { + EventSenderDmaapImpl eventSender = new EventSenderDmaapImpl(); + eventSender.initialize(); + eventSender.setProducerMap(producerMap); + Map<String,String> params = new HashMap<>(); + + Assert.assertFalse(eventSender.sendEvent(MessageDestination.DCAE,params, new SvcLogicContext())); + } + + + @Test(expected = APPCException.class) + @Ignore // requires connection to a live DMaaP server + public void testDmaapEventSenderDGNullParam() throws APPCException { + EventSenderDmaapImpl eventSender = new EventSenderDmaapImpl(); + eventSender.initialize(); + eventSender.setProducerMap(producerMap); + Map<String,String> params = null; + + Assert.assertFalse(eventSender.sendEvent(MessageDestination.DCAE,params, new SvcLogicContext())); + } + + @Test(expected = APPCException.class) + @Ignore // requires connection to a live DMaaP server + public void testDmaapEventSenderDGNoParam() throws APPCException { + EventSenderDmaapImpl eventSender = new EventSenderDmaapImpl(); + eventSender.initialize(); + eventSender.setProducerMap(producerMap); + Map<String,String> params = new HashMap<>(); + +// params.put("apiVer", eventMessage.getEventHeader().getApiVer()); + params.put("eventId", eventMessage.getEventHeader().getEventId()); + params.put("reason", eventMessage.getEventStatus().getReason()); + params.put("code", "200"); + + eventSender.sendEvent(MessageDestination.DCAE,params, new SvcLogicContext()); + } + +} diff --git a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/test/java/org/openecomp/appc/adapter/messaging/dmaap/TestDmaapProducing.java b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/test/java/org/openecomp/appc/adapter/messaging/dmaap/TestDmaapProducing.java new file mode 100644 index 000000000..b5b7c9538 --- /dev/null +++ b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/test/java/org/openecomp/appc/adapter/messaging/dmaap/TestDmaapProducing.java @@ -0,0 +1,80 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.adapter.messaging.dmaap; + + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; +import org.openecomp.appc.adapter.message.Producer; +import org.openecomp.appc.adapter.messaging.dmaap.http.HttpDmaapProducerImpl; +import org.openecomp.appc.adapter.messaging.dmaap.impl.DmaapProducerImpl; +import org.openecomp.appc.configuration.Configuration; +import org.openecomp.appc.configuration.ConfigurationFactory; + +import java.util.Arrays; +import java.util.List; + +/** + * Must have a DMaaP cluster or simulator up and running + * Update the hostname, topic, client properties in + * resources/org/openecomp/appc/default.properties + * + */ +public class TestDmaapProducing { + + private static Producer httpProducer; + private static Producer dmaapProducer; + + @BeforeClass + public static void setUp() { + + Configuration configuration = ConfigurationFactory.getConfiguration(); + + List<String> hosts = Arrays.asList(configuration.getProperty("poolMembers").split(",")); + String topic = configuration.getProperty("topic.write"); + String user = configuration.getProperty("dmaap.appc.username"); + String password = configuration.getProperty("dmaap.appc.password"); + + dmaapProducer = new DmaapProducerImpl(hosts, topic,user,password); + httpProducer = new HttpDmaapProducerImpl(hosts, topic); + httpProducer.updateCredentials(user,password); + } + + @Test + @Ignore + public void testHttpPostMessage() { + testPostMessage(httpProducer); + } + + @Test + @Ignore + public void testPostMessages() { + testPostMessage(dmaapProducer); + } + + private void testPostMessage(Producer producer) { + Assert.assertTrue(producer.post("partition", "{\"message\": \"Hello, world!\"}")); + } + +} diff --git a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/test/java/org/openecomp/appc/adapter/messaging/dmaap/impl/TestConsumerProducerImpl.java b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/test/java/org/openecomp/appc/adapter/messaging/dmaap/impl/TestConsumerProducerImpl.java new file mode 100644 index 000000000..4b936351a --- /dev/null +++ b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/test/java/org/openecomp/appc/adapter/messaging/dmaap/impl/TestConsumerProducerImpl.java @@ -0,0 +1,242 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.adapter.messaging.dmaap.impl; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.*; + +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.openecomp.appc.adapter.message.Consumer; +import org.openecomp.appc.adapter.message.Producer; +import org.openecomp.appc.adapter.messaging.dmaap.impl.DmaapConsumerImpl; +import org.openecomp.appc.adapter.messaging.dmaap.impl.DmaapProducerImpl; +import org.openecomp.appc.configuration.Configuration; +import org.openecomp.appc.configuration.ConfigurationFactory; + +public class TestConsumerProducerImpl { + + private Collection<String> urls; + private String topicRead; + private String topicWrite; + private String group; + private String groupId; + private String user; + private String password; + + @Before + public void setup() { + System.out.println("setup entry..."); +// urls = new HashSet<String>(); +// urls.add("dmaaphost1"); +// urls.add("dmaaphost2"); +// //remove unavailable dmaap instance for build +// //urls.add("dmaaphost3"); +// +// topicRead = "APPC-UNIT-TEST"; +// topicWrite = "APPC-UNIT-TEST"; +// group = "APPC-CLIENT"; +// groupId = "0"; + Configuration configuration = ConfigurationFactory.getConfiguration(); + List<String> hosts = Arrays.asList(configuration.getProperty("poolMembers").split(",")); + urls = new HashSet<String>(hosts); + topicRead = configuration.getProperty("topic.read"); + topicWrite = configuration.getProperty("topic.write"); + user = configuration.getProperty("dmaap.appc.username"); + password = configuration.getProperty("dmaap.appc.password"); + group = "APPC-CLIENT"; + groupId = "0"; + + + runoff(); + } + + /** + * Test that we can read and write and that the messages come back in order + */ + @Ignore + @Test + public void testWriteRead() { + System.out.println("testWriteRead entry..."); + Producer p = new DmaapProducerImpl(urls, topicWrite,user,password); + + String s1 = UUID.randomUUID().toString(); + String s2 = UUID.randomUUID().toString(); + if (p.post("TEST", s1) == false) { + // try again - 2nd attempt may succeed if cambria client failed over + p.post("TEST", s1); + } + if (p.post("TEST", s2) == false) { + // try again - 2nd attempt may succeed if cambria client failed over + p.post("TEST", s2); + } + + Consumer c = new DmaapConsumerImpl(urls, topicRead, group, groupId,user,password); + List<String> out = c.fetch(); + // if fetch is empty, try again - a 2nd attempt may succeed if + // cambria client has failed over + if ((out == null) || out.isEmpty()) { + out = c.fetch(); + } + + assertNotNull(out); + assertEquals(2, out.size()); + assertEquals(s1, out.get(0)); + assertEquals(s2, out.get(1)); + + } + + /** + * Test that we can read and write and that the messages come back in order + */ + @Test + @Ignore // Https Not support on jenkins server + public void testWriteReadHttps() { + System.out.println("testWriteReadHttps entry..."); + Producer p = new DmaapProducerImpl(urls, topicWrite,user,password); + p.useHttps(true); + + String s1 = UUID.randomUUID().toString(); + String s2 = UUID.randomUUID().toString(); + if (p.post("TEST", s1) == false) { + // try again - 2nd attempt may succeed if cambria client failed over + p.post("TEST", s1); + } + if (p.post("TEST", s2) == false) { + // try again - 2nd attempt may succeed if cambria client failed over + p.post("TEST", s2); + } + + Consumer c = new DmaapConsumerImpl(urls, topicRead, group, groupId,user,password); + c.useHttps(true); + + List<String> out = c.fetch(); + // if fetch is empty, try again - a 2nd attempt may succeed if + // cambria client has failed over + if ((out == null) || out.isEmpty()) { + out = c.fetch(); + } + + assertNotNull(out); + assertEquals(2, out.size()); + assertEquals(s1, out.get(0)); + assertEquals(s2, out.get(1)); + + } + + @Test + @Ignore // requires connection to a live DMaaP server + public void testBadUrl() { + System.out.println("testBadUrl entry..."); + urls.clear(); + urls.add("something.local"); + + // Producer p = new DmaapProducerImpl(urls, topicWrite); + Consumer c = new DmaapConsumerImpl(urls, topicRead, group, groupId,user,password); + List<String> result = c.fetch(1000, 1000); + + assertNotNull(result); + assertTrue(result.isEmpty()); + } + + @Test + @Ignore // requires connection to a live DMaaP server + public void testAuth() { + System.out.println("testAuth entry..."); + Producer p = new DmaapProducerImpl(urls, topicWrite,user,password); + Consumer c = new DmaapConsumerImpl(urls, topicRead, group, groupId,user,password); + + p.updateCredentials("key", "secret"); + c.updateCredentials("key", "secret"); + + // TODO - Do some protected dmaap queries when the apis are updated + } + + /** + * Test DMaaP client failover to another server when a bad url is encountered + + */ + @Ignore + @Test + public void testFailover() { + System.out.println("testFailover entry..."); + urls.clear(); + urls.add("openecomp2.org"); // bad url + urls.add("dmaaphost2"); + Producer p = new DmaapProducerImpl(urls, topicWrite,user,password); + + String s1 = UUID.randomUUID().toString(); + if (p.post("TEST", s1) == false) { + // try again - cambria client should have failed over + p.post("TEST", s1); + } + + urls.clear(); + urls.add("openecomp3.org"); // bad url + urls.add("dmaaphost3"); + + Consumer c = new DmaapConsumerImpl(urls, topicRead, group, groupId,user,password); + List<String> out = c.fetch(1000, 1000); + // if fetch is empty, try again - cambria client should have failed over + if ((out == null) || out.isEmpty()) { + out = c.fetch(); + } + + assertNotNull(out); + assertEquals(1, out.size()); + assertEquals(s1, out.get(0)); + } + + /** + * Reads through the entire topic so it is clean for testing. WARNING - ONLY USE ON TOPICS WHERE YOU ARE THE ONLY + * WRITER. Could end in an infinite loop otherwise. + */ + private void runoff() { + Consumer c = new DmaapConsumerImpl(urls, topicRead, group, groupId,user,password); + List<String> data; + do { + data = c.fetch(1000, 10000); + } while (!data.isEmpty() && data.size()!=1); + } + + @Test + @Ignore + public void testFilter() { + System.out.println("testFilter entry..."); + List<String> res; + String filter = "{\"class\":\"Assigned\",\"field\":\"request\"}"; + Consumer c = new DmaapConsumerImpl(urls, "DCAE-CLOSED-LOOP-EVENTS-DEV1510SIM", group, groupId,user,password,filter); + res = c.fetch(2000, 10); + assertFalse(res.isEmpty()); + + res.clear(); + filter = "{\"class\":\"Assigned\",\"field\":\"response\"}"; + c = new DmaapConsumerImpl(urls, "DCAE-CLOSED-LOOP-EVENTS-DEV1510SIM", group, groupId,user,password, filter); + res = c.fetch(2000, 10); + assertTrue(res.isEmpty()); + } +} diff --git a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-features/pom.xml b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-features/pom.xml index 2181888fc..8f5b55c73 100644 --- a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-features/pom.xml +++ b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-features/pom.xml @@ -19,6 +19,12 @@ </dependency> <dependency> + <groupId>org.openecomp.appc</groupId> + <artifactId>appc-message-adapter-factory</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> <scope>compile</scope> diff --git a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-features/src/main/resources/features.xml b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-features/src/main/resources/features.xml index 90a31629e..baf04ddec 100644 --- a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-features/src/main/resources/features.xml +++ b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-features/src/main/resources/features.xml @@ -34,6 +34,8 @@ <feature version="${broker-mdsal.version}">odl-mdsal-broker</feature> <!-- <feature version="${sdnctl.sli.version}">sdnc-sli</feature> --> <bundle>mvn:org.openecomp.appc/appc-dmaap-adapter-bundle/${project.version}</bundle> + <bundle>mvn:org.openecomp.appc/appc-message-adapter-factory/${project.version}</bundle> + <bundle>mvn:org.openecomp.appc/appc-message-adapter-api/${project.version}</bundle> </feature> diff --git a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-installer/pom.xml b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-installer/pom.xml index 851c3a19e..845c477f4 100644 --- a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-installer/pom.xml +++ b/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-installer/pom.xml @@ -37,6 +37,16 @@ <artifactId>appc-dmaap-adapter-bundle</artifactId> <version>${project.version}</version> </dependency> + <dependency> + <groupId>org.openecomp.appc</groupId> + <artifactId>appc-message-adapter-api</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.openecomp.appc</groupId> + <artifactId>appc-message-adapter-factory</artifactId> + <version>${project.version}</version> + </dependency> </dependencies> <build> diff --git a/appc-adapters/appc-dmaap-adapter/appc-message-adapter-api/pom.xml b/appc-adapters/appc-dmaap-adapter/appc-message-adapter-api/pom.xml new file mode 100644 index 000000000..5e2e6c6b2 --- /dev/null +++ b/appc-adapters/appc-dmaap-adapter/appc-message-adapter-api/pom.xml @@ -0,0 +1,141 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.openecomp.appc</groupId> + <artifactId>appc-dmaap-adapter</artifactId> + <version>1.1.0-SNAPSHOT</version> + </parent> + + <artifactId>appc-message-adapter-api</artifactId> + <packaging>bundle</packaging> + <name>appc-message-adapter-api</name> + + <dependencies> + <dependency> + <groupId>org.openecomp.appc</groupId> + <artifactId>appc-metric-bundle</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.openecomp.appc</groupId> + <artifactId>appc-common</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>equinoxSDK381</groupId> + <artifactId>org.eclipse.osgi</artifactId> + </dependency> + + <dependency> + <groupId>commons-codec</groupId> + <artifactId>commons-codec</artifactId> + </dependency> + + <dependency> + <groupId>commons-lang</groupId> + <artifactId>commons-lang</artifactId> + </dependency> + + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-databind</artifactId> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-core</artifactId> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-annotations</artifactId> + </dependency> + + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.powermock</groupId> + <artifactId>powermock-api-mockito</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.hamcrest</groupId> + <artifactId>hamcrest-core</artifactId> + </dependency> + <dependency> + <groupId>org.objenesis</groupId> + <artifactId>objenesis</artifactId> + <version>2.2</version> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-all</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.powermock</groupId> + <artifactId>powermock-module-junit4</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sli-common</artifactId> + <scope>compile</scope> + <!-- Added exclusion to prevent missing dependency issue on dblib --> + <exclusions> + <exclusion> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>dblib-provider</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sli-provider</artifactId> + <scope>compile</scope> + <!-- Added exclusion to prevent missing dependency issue on dblib --> + <exclusions> + <exclusion> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>dblib-provider</artifactId> + </exclusion> + </exclusions> + </dependency> + + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName> + <Bundle-Version>${project.version}</Bundle-Version> + <Export-Package>org.openecomp.appc.adapter.message.*</Export-Package> + <!--<Export-Serice>org.openecomp.appc.adapter.message.EventSender</Export-Serice>--> + <Import-Package>org.openecomp.appc.metricservice.*,com.att.nsa.*,org.openecomp.sdnc.sli.*,org.osgi.framework.*,!org.osgi.service.event.*,org.osgi.service.*,org.osgi.util.*,org.slf4j.*,com.vmware.*,org.apache.xerces.*,javax.net.ssl.*,org.xml.sax.*,javax.xml.*,javax.naming.*,javax.crypto.*, com.sun.jersey.spi.container.servlet,org.eclipse.jetty.servlets</Import-Package> + <!--<Embed-Dependency>appc-common</Embed-Dependency>--> + <Embed-Dependency>*;scope=compile|runtime;artifactId=!appc-metric-bundle|sli-common|sli-provider|org.eclipse.osgi|slf4j-api|jcl-over-slf4j|mysql-connector-java|xml-apis|pax-*</Embed-Dependency> + <Embed-Transitive>true</Embed-Transitive> + <Bundle-Blueprint>OSGI-INF/blueprint/blueprint.xml</Bundle-Blueprint> + </instructions> + </configuration> + </plugin> + </plugins> + </build> +</project> diff --git a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/dmaap/CallableConsumer.java b/appc-adapters/appc-dmaap-adapter/appc-message-adapter-api/src/main/java/org/openecomp/appc/adapter/message/CallableConsumer.java index 7c282911d..bbc541167 100644 --- a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/dmaap/CallableConsumer.java +++ b/appc-adapters/appc-dmaap-adapter/appc-message-adapter-api/src/main/java/org/openecomp/appc/adapter/message/CallableConsumer.java @@ -19,7 +19,7 @@ * ============LICENSE_END========================================================= */ -package org.openecomp.appc.adapter.dmaap; +package org.openecomp.appc.adapter.message; import java.util.List; import java.util.concurrent.Callable; diff --git a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/dmaap/Consumer.java b/appc-adapters/appc-dmaap-adapter/appc-message-adapter-api/src/main/java/org/openecomp/appc/adapter/message/Consumer.java index 32034e5fb..e99f884a2 100644 --- a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/dmaap/Consumer.java +++ b/appc-adapters/appc-dmaap-adapter/appc-message-adapter-api/src/main/java/org/openecomp/appc/adapter/message/Consumer.java @@ -19,7 +19,7 @@ * ============LICENSE_END========================================================= */ -package org.openecomp.appc.adapter.dmaap; +package org.openecomp.appc.adapter.message; import java.util.List; @@ -54,9 +54,6 @@ public interface Consumer { */ public void updateCredentials(String apiKey, String apiSecret); - // TODO - Implement once Cambria allows you to set outside of constructor - // public void setFilter(String filter); - /** * Creates a dmaap client using a https connection * @@ -65,4 +62,9 @@ public interface Consumer { */ public void useHttps(boolean yes); + /** + * Closes the dmaap client https connection + */ + void close(); + } diff --git a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/dmaap/EventSender.java b/appc-adapters/appc-dmaap-adapter/appc-message-adapter-api/src/main/java/org/openecomp/appc/adapter/message/EventSender.java index 7d4a7c090..e4338f0e4 100644 --- a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/dmaap/EventSender.java +++ b/appc-adapters/appc-dmaap-adapter/appc-message-adapter-api/src/main/java/org/openecomp/appc/adapter/message/EventSender.java @@ -19,17 +19,18 @@ * ============LICENSE_END========================================================= */ -package org.openecomp.appc.adapter.dmaap; +package org.openecomp.appc.adapter.message; -import java.util.Map; - -import org.openecomp.appc.adapter.dmaap.event.EventMessage; import org.openecomp.appc.exceptions.APPCException; import org.openecomp.sdnc.sli.SvcLogicContext; import org.openecomp.sdnc.sli.SvcLogicJavaPlugin; +import java.util.Map; + +import org.openecomp.appc.adapter.message.event.EventMessage; public interface EventSender extends SvcLogicJavaPlugin{ - boolean sendEvent(DmaapDestination destination, EventMessage msg); - boolean sendEvent(DmaapDestination destination, Map<String, String> params, SvcLogicContext ctx) throws APPCException; + boolean sendEvent(MessageDestination destination, EventMessage msg); + boolean sendEvent(MessageDestination destination, EventMessage msg,String eventTopicName); + boolean sendEvent(MessageDestination destination, Map<String, String> params, SvcLogicContext ctx) throws APPCException; } diff --git a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/dmaap/Manager.java b/appc-adapters/appc-dmaap-adapter/appc-message-adapter-api/src/main/java/org/openecomp/appc/adapter/message/Manager.java index 183e618ba..2990036f5 100644 --- a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/dmaap/Manager.java +++ b/appc-adapters/appc-dmaap-adapter/appc-message-adapter-api/src/main/java/org/openecomp/appc/adapter/message/Manager.java @@ -19,7 +19,7 @@ * ============LICENSE_END========================================================= */ -package org.openecomp.appc.adapter.dmaap; +package org.openecomp.appc.adapter.message; import java.util.Set; diff --git a/appc-adapters/appc-dmaap-adapter/appc-message-adapter-api/src/main/java/org/openecomp/appc/adapter/message/MessageAdapterFactory.java b/appc-adapters/appc-dmaap-adapter/appc-message-adapter-api/src/main/java/org/openecomp/appc/adapter/message/MessageAdapterFactory.java new file mode 100644 index 000000000..741563b58 --- /dev/null +++ b/appc-adapters/appc-dmaap-adapter/appc-message-adapter-api/src/main/java/org/openecomp/appc/adapter/message/MessageAdapterFactory.java @@ -0,0 +1,39 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.openecomp.appc.adapter.message; + +import java.util.Collection; +import java.util.Set; + +import org.openecomp.appc.adapter.message.Consumer; +import org.openecomp.appc.adapter.message.Producer; + +public interface MessageAdapterFactory { + + // TODO: how do you configure the MessageService type? + + public Producer createProducer(Collection<String> pools, String writeTopic, String apiKey, String apiSecret); + + public Producer createProducer(Collection<String> pools, Set<String> writeTopics, String apiKey, String apiSecret); + + public Consumer createConsumer(Collection<String> pool, String readTopic, + String clientName, String clientId, String filter_json, String apiKey, String apiSecret); +} diff --git a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/dmaap/DmaapDestination.java b/appc-adapters/appc-dmaap-adapter/appc-message-adapter-api/src/main/java/org/openecomp/appc/adapter/message/MessageDestination.java index efbe194ba..b952441e1 100644 --- a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/dmaap/DmaapDestination.java +++ b/appc-adapters/appc-dmaap-adapter/appc-message-adapter-api/src/main/java/org/openecomp/appc/adapter/message/MessageDestination.java @@ -19,8 +19,8 @@ * ============LICENSE_END========================================================= */ -package org.openecomp.appc.adapter.dmaap; +package org.openecomp.appc.adapter.message; -public enum DmaapDestination { +public enum MessageDestination { DCAE } diff --git a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/dmaap/Producer.java b/appc-adapters/appc-dmaap-adapter/appc-message-adapter-api/src/main/java/org/openecomp/appc/adapter/message/Producer.java index f19c516be..5981606cb 100644 --- a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/dmaap/Producer.java +++ b/appc-adapters/appc-dmaap-adapter/appc-message-adapter-api/src/main/java/org/openecomp/appc/adapter/message/Producer.java @@ -19,7 +19,7 @@ * ============LICENSE_END========================================================= */ -package org.openecomp.appc.adapter.dmaap; +package org.openecomp.appc.adapter.message; public interface Producer { @@ -43,4 +43,9 @@ public interface Producer { */ public void useHttps(boolean yes); + /** + * Closes the dmaap client https connection + */ + void close(); + } diff --git a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/dmaap/event/EventHeader.java b/appc-adapters/appc-dmaap-adapter/appc-message-adapter-api/src/main/java/org/openecomp/appc/adapter/message/event/EventHeader.java index dd951fe37..3d897d42a 100644 --- a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/dmaap/event/EventHeader.java +++ b/appc-adapters/appc-dmaap-adapter/appc-message-adapter-api/src/main/java/org/openecomp/appc/adapter/message/event/EventHeader.java @@ -19,11 +19,10 @@ * ============LICENSE_END========================================================= */ -package org.openecomp.appc.adapter.dmaap.event; +package org.openecomp.appc.adapter.message.event; import com.fasterxml.jackson.annotation.JsonProperty; - public class EventHeader { @JsonProperty("eventTime") diff --git a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/dmaap/event/EventMessage.java b/appc-adapters/appc-dmaap-adapter/appc-message-adapter-api/src/main/java/org/openecomp/appc/adapter/message/event/EventMessage.java index af5cff2f9..e5fad6089 100644 --- a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/dmaap/event/EventMessage.java +++ b/appc-adapters/appc-dmaap-adapter/appc-message-adapter-api/src/main/java/org/openecomp/appc/adapter/message/event/EventMessage.java @@ -19,7 +19,7 @@ * ============LICENSE_END========================================================= */ -package org.openecomp.appc.adapter.dmaap.event; +package org.openecomp.appc.adapter.message.event; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; @@ -45,8 +45,6 @@ import java.io.Serializable; */ - - @JsonSerialize(include = Inclusion.NON_NULL) @JsonIgnoreProperties(ignoreUnknown = true) public class EventMessage implements Serializable { diff --git a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/dmaap/event/EventStatus.java b/appc-adapters/appc-dmaap-adapter/appc-message-adapter-api/src/main/java/org/openecomp/appc/adapter/message/event/EventStatus.java index f5d7a59d4..85b4db02f 100644 --- a/appc-adapters/appc-dmaap-adapter/appc-dmaap-adapter-bundle/src/main/java/org/openecomp/appc/adapter/dmaap/event/EventStatus.java +++ b/appc-adapters/appc-dmaap-adapter/appc-message-adapter-api/src/main/java/org/openecomp/appc/adapter/message/event/EventStatus.java @@ -19,11 +19,10 @@ * ============LICENSE_END========================================================= */ -package org.openecomp.appc.adapter.dmaap.event; +package org.openecomp.appc.adapter.message.event; import com.fasterxml.jackson.annotation.JsonProperty; - public class EventStatus { @JsonProperty("code") diff --git a/appc-adapters/appc-dmaap-adapter/appc-message-adapter-api/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/appc-adapters/appc-dmaap-adapter/appc-message-adapter-api/src/main/resources/OSGI-INF/blueprint/blueprint.xml new file mode 100644 index 000000000..a1e5c7172 --- /dev/null +++ b/appc-adapters/appc-dmaap-adapter/appc-message-adapter-api/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============LICENSE_START======================================================= + openECOMP : APP-C + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights + reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + + +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd"> + +</blueprint> diff --git a/appc-adapters/appc-dmaap-adapter/appc-message-adapter-api/src/main/resources/org/openecomp/appc/default.properties b/appc-adapters/appc-dmaap-adapter/appc-message-adapter-api/src/main/resources/org/openecomp/appc/default.properties new file mode 100644 index 000000000..00c95bca1 --- /dev/null +++ b/appc-adapters/appc-dmaap-adapter/appc-message-adapter-api/src/main/resources/org/openecomp/appc/default.properties @@ -0,0 +1,23 @@ +### +# ============LICENSE_START======================================================= +# openECOMP : APP-C +# ================================================================================ +# Copyright (C) 2017 AT&T Intellectual Property. All rights +# reserved. +# ================================================================================ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============LICENSE_END========================================================= +### + +org.openecomp.appc.bootstrap.file=appc.properties +org.openecomp.appc.bootstrap.path=/opt/openecomp/appc/data/properties,${user.home},. diff --git a/appc-adapters/appc-dmaap-adapter/appc-message-adapter-factory/pom.xml b/appc-adapters/appc-dmaap-adapter/appc-message-adapter-factory/pom.xml new file mode 100644 index 000000000..21cba8179 --- /dev/null +++ b/appc-adapters/appc-dmaap-adapter/appc-message-adapter-factory/pom.xml @@ -0,0 +1,150 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.openecomp.appc</groupId> + <artifactId>appc-dmaap-adapter</artifactId> + <version>1.1.0-SNAPSHOT</version> + </parent> + + <artifactId>appc-message-adapter-factory</artifactId> + <packaging>bundle</packaging> + <name>appc-message-adapter-factory</name> + + <dependencies> + <dependency> + <groupId>org.openecomp.appc</groupId> + <artifactId>appc-common</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>org.openecomp.appc</groupId> + <artifactId>appc-dmaap-adapter-bundle</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>org.openecomp.appc</groupId> + <artifactId>appc-message-adapter-api</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>equinoxSDK381</groupId> + <artifactId>org.eclipse.osgi</artifactId> + </dependency> + + <dependency> + <groupId>commons-codec</groupId> + <artifactId>commons-codec</artifactId> + </dependency> + + <dependency> + <groupId>commons-lang</groupId> + <artifactId>commons-lang</artifactId> + </dependency> + + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-databind</artifactId> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-core</artifactId> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-annotations</artifactId> + </dependency> + + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.powermock</groupId> + <artifactId>powermock-api-mockito</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.hamcrest</groupId> + <artifactId>hamcrest-core</artifactId> + </dependency> + <dependency> + <groupId>org.objenesis</groupId> + <artifactId>objenesis</artifactId> + <version>2.2</version> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-all</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.powermock</groupId> + <artifactId>powermock-module-junit4</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sli-common</artifactId> + <scope>compile</scope> + <!-- Added exclusion to prevent missing dependency issue on dblib --> + <exclusions> + <exclusion> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>dblib-provider</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sli-provider</artifactId> + <scope>compile</scope> + <!-- Added exclusion to prevent missing dependency issue on dblib --> + <exclusions> + <exclusion> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>dblib-provider</artifactId> + </exclusion> + </exclusions> + </dependency> + + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName> + <Bundle-Version>${project.version}</Bundle-Version> + <Export-Package>org.openecomp.appc.adapter.factory</Export-Package> + <Bundle-Activator>org.openecomp.appc.adapter.factory.DmaapMessageAdapterFactoryActivator</Bundle-Activator> + <Export-Service>org.openecomp.appc.adapter.message.MessageAdapterFactory</Export-Service> + <Import-Package>org.openecomp.appc.adapter.messaging.*,org.openecomp.appc.adapter.message.*,org.openecomp.appc.metricservice.*,com.att.nsa.*org.openecomp.sdnc.core.sli.*,org.osgi.framework.*,!org.osgi.service.event.*,org.osgi.service.*,org.osgi.util.*,org.slf4j.*,com.vmware.*,org.apache.xerces.*,javax.net.ssl.*,org.xml.sax.*,javax.xml.*,javax.naming.*,javax.crypto.*, com.sun.jersey.spi.container.servlet,org.eclipse.jetty.servlets</Import-Package> + <Embed-Dependency>*;scope=compile|runtime;artifactId=!appc-metric-bundle|sli-common|org.eclipse.osgi|slf4j-api|jcl-over-slf4j|mysql-connector-java|xml-apis|pax-*</Embed-Dependency> + <Embed-Transitive>true</Embed-Transitive> + <Bundle-Blueprint>OSGI-INF/blueprint/blueprint.xml</Bundle-Blueprint> + </instructions> + </configuration> + </plugin> + </plugins> + </build> +</project> diff --git a/appc-adapters/appc-dmaap-adapter/appc-message-adapter-factory/src/main/java/org/openecomp/appc/adapter/factory/DmaapMessageAdapterFactoryActivator.java b/appc-adapters/appc-dmaap-adapter/appc-message-adapter-factory/src/main/java/org/openecomp/appc/adapter/factory/DmaapMessageAdapterFactoryActivator.java new file mode 100644 index 000000000..26e0f3da9 --- /dev/null +++ b/appc-adapters/appc-dmaap-adapter/appc-message-adapter-factory/src/main/java/org/openecomp/appc/adapter/factory/DmaapMessageAdapterFactoryActivator.java @@ -0,0 +1,44 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.openecomp.appc.adapter.factory; + +import org.openecomp.appc.adapter.message.MessageAdapterFactory; +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; + +public class DmaapMessageAdapterFactoryActivator implements BundleActivator { + private ServiceRegistration registration; + + @Override + public void start(BundleContext context) throws Exception { + registration = context.registerService( + MessageAdapterFactory.class.getName(), + new DmaapMessageAdapterFactoryImpl(), + null); + } + + @Override + public void stop(BundleContext context) throws Exception { + registration.unregister(); + } + +} diff --git a/appc-adapters/appc-dmaap-adapter/appc-message-adapter-factory/src/main/java/org/openecomp/appc/adapter/factory/DmaapMessageAdapterFactoryImpl.java b/appc-adapters/appc-dmaap-adapter/appc-message-adapter-factory/src/main/java/org/openecomp/appc/adapter/factory/DmaapMessageAdapterFactoryImpl.java new file mode 100644 index 000000000..604cbf738 --- /dev/null +++ b/appc-adapters/appc-dmaap-adapter/appc-message-adapter-factory/src/main/java/org/openecomp/appc/adapter/factory/DmaapMessageAdapterFactoryImpl.java @@ -0,0 +1,47 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.adapter.factory; + +import java.util.Collection; +import java.util.Set; + +import org.openecomp.appc.adapter.message.Consumer; +import org.openecomp.appc.adapter.message.MessageAdapterFactory; +import org.openecomp.appc.adapter.message.Producer; +import org.openecomp.appc.adapter.messaging.dmaap.http.HttpDmaapConsumerImpl; +import org.openecomp.appc.adapter.messaging.dmaap.http.HttpDmaapProducerImpl; + +public class DmaapMessageAdapterFactoryImpl implements MessageAdapterFactory { + + public Producer createProducer(Collection<String> pools, String writeTopic, String apiKey, String apiSecret) { + return new HttpDmaapProducerImpl(pools, writeTopic); + } + + public Producer createProducer(Collection<String> pools, Set<String> writeTopics, String apiKey, String apiSecret) { + return new HttpDmaapProducerImpl(pools, writeTopics); + } + + public Consumer createConsumer(Collection<String> pool, String readTopic, + String clientName, String clientId, String filter_json, String apiKey, String apiSecret) { + return new HttpDmaapConsumerImpl(pool, readTopic, clientName, clientId, apiKey, apiSecret, filter_json); + } +} diff --git a/appc-adapters/appc-dmaap-adapter/appc-message-adapter-factory/src/main/java/org/openecomp/appc/adapter/factory/MessageService.java b/appc-adapters/appc-dmaap-adapter/appc-message-adapter-factory/src/main/java/org/openecomp/appc/adapter/factory/MessageService.java new file mode 100644 index 000000000..5bbfd6ddb --- /dev/null +++ b/appc-adapters/appc-dmaap-adapter/appc-message-adapter-factory/src/main/java/org/openecomp/appc/adapter/factory/MessageService.java @@ -0,0 +1,56 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.adapter.factory; +/** + * The message service types that are available. Only DMaaP available + **/ +public enum MessageService { + DMaaP("dmaap"); + + private String val; + + private MessageService(String val) { + this.val = val; + } + + public String getValue() { + return val; + } + + /** + * Tries to match a string to a MessageService. If no match is found, returns the default (DMaaP) + * + * @param input + * the string to try and match + * @return A MessasgeService + */ + public static MessageService parse(String input) { + if (input != null) { + for (MessageService ms : MessageService.values()) { + if (ms.getValue().equals(input.toLowerCase())) { + return ms; + } + } + } + return MessageService.DMaaP; // Default + } +} diff --git a/appc-adapters/appc-dmaap-adapter/appc-message-adapter-factory/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/appc-adapters/appc-dmaap-adapter/appc-message-adapter-factory/src/main/resources/OSGI-INF/blueprint/blueprint.xml new file mode 100644 index 000000000..a1e5c7172 --- /dev/null +++ b/appc-adapters/appc-dmaap-adapter/appc-message-adapter-factory/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============LICENSE_START======================================================= + openECOMP : APP-C + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights + reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + + +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd"> + +</blueprint> diff --git a/appc-adapters/appc-dmaap-adapter/appc-message-adapter-factory/src/main/resources/org/openecomp/appc/default.properties b/appc-adapters/appc-dmaap-adapter/appc-message-adapter-factory/src/main/resources/org/openecomp/appc/default.properties new file mode 100644 index 000000000..00c95bca1 --- /dev/null +++ b/appc-adapters/appc-dmaap-adapter/appc-message-adapter-factory/src/main/resources/org/openecomp/appc/default.properties @@ -0,0 +1,23 @@ +### +# ============LICENSE_START======================================================= +# openECOMP : APP-C +# ================================================================================ +# Copyright (C) 2017 AT&T Intellectual Property. All rights +# reserved. +# ================================================================================ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============LICENSE_END========================================================= +### + +org.openecomp.appc.bootstrap.file=appc.properties +org.openecomp.appc.bootstrap.path=/opt/openecomp/appc/data/properties,${user.home},. diff --git a/appc-adapters/appc-dmaap-adapter/pom.xml b/appc-adapters/appc-dmaap-adapter/pom.xml index 5d90baacd..212488a2c 100644 --- a/appc-adapters/appc-dmaap-adapter/pom.xml +++ b/appc-adapters/appc-dmaap-adapter/pom.xml @@ -9,7 +9,7 @@ <artifactId>appc-dmaap-adapter</artifactId> <name>DMaaP Adapter</name> - <description>Adapter to read and write messages on the Universal Event Broker (Cambria).</description> + <description>Adapter to read and write messages on the DMaaP Service</description> <packaging>pom</packaging> <reporting> @@ -98,8 +98,10 @@ </reporting> <modules> + <module>appc-message-adapter-api</module> <module>appc-dmaap-adapter-bundle</module> <module>appc-dmaap-adapter-features</module> <module>appc-dmaap-adapter-installer</module> + <module>appc-message-adapter-factory</module> </modules> </project> diff --git a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/pom.xml b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/pom.xml index db08ff17e..061ec5a09 100644 --- a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/pom.xml +++ b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/pom.xml @@ -16,84 +16,137 @@ <groupId>org.openecomp.appc</groupId> <artifactId>appc-common</artifactId> <version>${project.version}</version> - <classifier>jar-with-dependencies</classifier> <scope>compile</scope> - </dependency> - <dependency> - <groupId>org.openecomp.appc</groupId> - <artifactId>appc-common</artifactId> - <version>${project.version}</version> - <scope>test</scope> - </dependency> - <dependency> - <groupId>javax</groupId> - <artifactId>javaee-api</artifactId> - <version>7.0</version> - </dependency> - - <dependency> - <groupId>com.att.cdp</groupId> - <artifactId>cdp-pal-common</artifactId> - <scope>compile</scope> - </dependency> - - <dependency> - <groupId>com.att.cdp</groupId> - <artifactId>cdp-pal-openstack</artifactId> - <scope>compile</scope> - </dependency> - - <dependency> - <groupId>javax.ws.rs</groupId> - <artifactId>javax.ws.rs-api</artifactId> - </dependency> - - <!-- Jersey support needed for OpenStack connector and API version logic --> - <dependency> - <groupId>com.sun.jersey</groupId> - <artifactId>jersey-client</artifactId> - </dependency> - - <dependency> - <groupId>com.sun.jersey</groupId> - <artifactId>jersey-json</artifactId> - </dependency> - - <dependency> - <groupId>javax.xml.bind</groupId> - <artifactId>jaxb-api</artifactId> - <version>2.1</version> - </dependency> - - <dependency> - <groupId>javax.xml</groupId> - <artifactId>jaxp-api</artifactId> - <version>1.4.2</version> - </dependency> - - <!-- Needed to run test cases --> - <dependency> - <groupId>org.glassfish.jersey.core</groupId> - <artifactId>jersey-common</artifactId> - <version>2.9.1</version> - </dependency> - - <dependency> - <groupId>org.codehaus.jackson</groupId> - <artifactId>jackson-jaxrs</artifactId> - <version>1.9.12</version> - </dependency> - - <dependency> - <groupId>commons-codec</groupId> - <artifactId>commons-codec</artifactId> - </dependency> - - <dependency> - <groupId>org.apache.httpcomponents</groupId> - <artifactId>httpclient</artifactId> - <version>4.5.1</version> - </dependency> + <exclusions> + <exclusion> + <groupId>javax</groupId> + <artifactId>javaee-api</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>com.att.cdp</groupId> + <artifactId>cdp-pal-openstack</artifactId> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>org.glassfish.jersey.core</groupId> + <artifactId>jersey-common</artifactId> + <version>2.25.1</version> + <scope>compile</scope> + </dependency> + + + <dependency> + <groupId>org.glassfish.jersey.core</groupId> + <artifactId>jersey-client</artifactId> + <version>2.25.1</version> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>org.glassfish.jersey.core</groupId> + <artifactId>jersey-server</artifactId> + <version>2.25.1</version> + <scope>compile</scope> + </dependency> + +<!-- <dependency> --> +<!-- <groupId>javax</groupId> --> +<!-- <artifactId>javaee-api</artifactId> --> +<!-- <version>7.0</version> --> +<!-- </dependency> --> + + <dependency> + <groupId>javax.ws.rs</groupId> + <artifactId>javax.ws.rs-api</artifactId> + <version>2.0.1</version> + <scope>compile</scope> + </dependency> + +<!-- <dependency> --> +<!-- <groupId>org.glassfish.jersey.containers</groupId> --> +<!-- <artifactId>jersey-container-servlet</artifactId> --> +<!-- <version>2.25.1</version> --> +<!-- <scope>provided</scope> --> +<!-- </dependency> --> + + <dependency> + <groupId>org.glassfish.jersey.connectors</groupId> + <artifactId>jersey-grizzly-connector</artifactId> + <version>2.25.1</version> + <scope>compile</scope> + </dependency> +<!-- <dependency> --> +<!-- <groupId>org.glassfish.jersey.media</groupId> --> +<!-- <artifactId>jersey-media-json-jackson</artifactId> --> +<!-- <version>2.25.1</version> --> +<!-- </dependency> --> + +<!-- <dependency> --> +<!-- <groupId>com.fasterxml.jackson.jaxrs</groupId> --> +<!-- <artifactId>jackson-jaxrs-base</artifactId> --> +<!-- </dependency> --> + + <dependency> + <groupId>javax.xml</groupId> + <artifactId>jaxp-api</artifactId> + <version>1.4.2</version> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>javax.xml.bind</groupId> + <artifactId>jaxb-api</artifactId> + <version>2.2</version> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sli-common</artifactId> + <scope>provided</scope> + <!-- Added exclusion to prevent missing dependency issue on dblib --> + <exclusions> + <exclusion> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>dblib-provider</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sli-provider</artifactId> + <scope>provided</scope> + <!-- Added exclusion to prevent missing dependency issue on dblib --> + <exclusions> + <exclusion> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>dblib-provider</artifactId> + </exclusion> + </exclusions> + </dependency> + + +<!-- <dependency> --> +<!-- <groupId>org.codehaus.jackson</groupId> --> +<!-- <artifactId>jackson-jaxrs</artifactId> --> +<!-- <version>1.9.12</version> --> +<!-- </dependency> --> + +<!-- <dependency> --> +<!-- <groupId>commons-codec</groupId> --> +<!-- <artifactId>commons-codec</artifactId> --> +<!-- </dependency> --> + +<!-- <dependency> --> +<!-- <groupId>org.apache.httpcomponents</groupId> --> +<!-- <artifactId>httpclient</artifactId> --> +<!-- <version>4.5.1</version> --> +<!-- </dependency> --> <dependency> <groupId>junit</groupId> @@ -101,80 +154,56 @@ <scope>test</scope> </dependency> - <dependency> - <groupId>org.openecomp.sdnc.core</groupId> - <artifactId>sli-common</artifactId> - <scope>compile</scope> - <!-- Added exclusion to prevent missing dependency issue on dblib --> - <exclusions> - <exclusion> - <groupId>org.openecomp.sdnc.core</groupId> - <artifactId>dblib-provider</artifactId> - </exclusion> - </exclusions> - </dependency> - - <dependency> - <groupId>org.openecomp.sdnc.core</groupId> - <artifactId>sli-provider</artifactId> - <scope>compile</scope> - <!-- Added exclusion to prevent missing dependency issue on dblib --> - <exclusions> - <exclusion> - <groupId>org.openecomp.sdnc.core</groupId> - <artifactId>dblib-provider</artifactId> - </exclusion> - </exclusions> - </dependency> - - <dependency> - <groupId>equinoxSDK381</groupId> - <artifactId>org.eclipse.osgi</artifactId> - </dependency> - <dependency> - <groupId>org.slf4j</groupId> - <artifactId>slf4j-api</artifactId> - </dependency> - <dependency> - <groupId>org.slf4j</groupId> - <artifactId>jcl-over-slf4j</artifactId> - </dependency> - - <dependency> - <groupId>mysql</groupId> - <artifactId>mysql-connector-java</artifactId> - <version>5.1.31</version> - <type>jar</type> - <scope>compile</scope> - </dependency> - - <dependency> - <groupId>com.vmware</groupId> - <artifactId>vijava</artifactId> - <version>5.1</version> - <scope>compile</scope> - </dependency> - - <dependency> - <groupId>xerces</groupId> - <artifactId>xerces</artifactId> - <version>2.4.0</version> - <scope>provided</scope> - </dependency> - - <dependency> - <groupId>org.apache.httpcomponents</groupId> - <artifactId>httpcore</artifactId> - <version>${apache.httpcomponents.version}</version> - </dependency> - - <dependency> - <groupId>commons-logging</groupId> - <artifactId>commons-logging</artifactId> - <version>1.2</version> - </dependency> +<!-- <dependency> --> +<!-- <groupId>equinoxSDK381</groupId> --> +<!-- <artifactId>org.eclipse.osgi</artifactId> --> +<!-- </dependency> --> + +<!-- <dependency> --> +<!-- <groupId>org.slf4j</groupId> --> +<!-- <artifactId>slf4j-api</artifactId> --> +<!-- </dependency> --> + +<!-- <dependency> --> +<!-- <groupId>org.slf4j</groupId> --> +<!-- <artifactId>jcl-over-slf4j</artifactId> --> +<!-- </dependency> --> + +<!-- <dependency> --> +<!-- <groupId>mysql</groupId> --> +<!-- <artifactId>mysql-connector-java</artifactId> --> +<!-- <version>5.1.31</version> --> +<!-- <type>jar</type> --> +<!-- <scope>compile</scope> --> +<!-- </dependency> --> + +<!-- <dependency> --> +<!-- <groupId>com.vmware</groupId> --> +<!-- <artifactId>vijava</artifactId> --> +<!-- <version>5.1</version> --> +<!-- <scope>compile</scope> --> +<!-- </dependency> --> + +<!-- <dependency> --> +<!-- <groupId>xerces</groupId> --> +<!-- <artifactId>xerces</artifactId> --> +<!-- <version>2.4.0</version> --> +<!-- <scope>provided</scope> --> +<!-- </dependency> --> + +<!-- <dependency> --> +<!-- <groupId>org.apache.httpcomponents</groupId> --> +<!-- <artifactId>httpcore</artifactId> --> +<!-- <version>${apache.httpcomponents.version}</version> --> +<!-- </dependency> --> + +<!-- <dependency> --> +<!-- <groupId>commons-logging</groupId> --> +<!-- <artifactId>commons-logging</artifactId> --> +<!-- <version>1.2</version> --> +<!-- </dependency> --> </dependencies> @@ -188,13 +217,15 @@ <instructions> <Bundle-SymbolicName>appc-iaas-adapter</Bundle-SymbolicName> <Bundle-Activator>org.openecomp.appc.adapter.iaas.AppcProviderAdapterActivator</Bundle-Activator> - <Export-Package>org.openecomp.appc.adapter.iaas</Export-Package> - <Import-Package>org.openecomp.sdnc.sli.*,org.osgi.framework.*,org.slf4j.*,com.vmware.*,org.apache.xerces.*,javax.net.*,javax.net.ssl.*,org.xml.sax.*,javax.xml.bind.*,javax.naming.*,com.sun.jersey.*</Import-Package> - <Embed-Dependency>*;scope=compile|runtime;artifactId=!sli-common|org.eclipse.osgi|slf4j-api|jcl-over-slf4j|mysql-connector-java|xml-apis</Embed-Dependency> + <Export-Package>org.openecomp.appc.adapter.iaas,com.att.cdp.zones.model</Export-Package> + <DynamicImport-Package>javax.*</DynamicImport-Package> + <Import-Package>org.openecomp.sdnc.sli.*,org.osgi.framework.*,org.slf4j.*,javax.net.ssl,org.xml.sax</Import-Package> +<!-- <Import-Package>org.openecomp.sdnc.sli.*,org.osgi.framework.*,org.slf4j.*,javax.ws.rs.*,javax.net.*,javax.xml.*,org.xml.*</Import-Package> --> +<!-- <Import-Package>org.openecomp.sdnc.sli.*,org.osgi.framework.*,org.slf4j.*,com.vmware.*,org.apache.xerces.*,javax.net.*,javax.net.ssl.*,org.xml.sax.*,javax.xml.bind.*,javax.naming.*,javax.xml.*</Import-Package> --> + <Embed-Dependency>*;scope=compile|runtime;artifactId=!org.eclipse.osgi|slf4j-api|jcl-over-slf4j|</Embed-Dependency> +<!-- <Embed-Dependency>*;scope=compile|runtime;artifactId=!sli-common|org.eclipse.osgi|slf4j-api|jcl-over-slf4j|mysql-connector-java|xml-apis</Embed-Dependency> --> <Embed-Transitive>true</Embed-Transitive> </instructions> - - <manifestLocation>${project.basedir}/src/main/resources/META-INF</manifestLocation> </configuration> </plugin> </plugins> diff --git a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/AppcProviderAdapterActivator.java b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/AppcProviderAdapterActivator.java index dec975cfb..0e68b7d69 100644 --- a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/AppcProviderAdapterActivator.java +++ b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/AppcProviderAdapterActivator.java @@ -26,12 +26,13 @@ import org.openecomp.appc.adapter.iaas.impl.ProviderAdapterImpl; import org.openecomp.appc.configuration.Configuration; import org.openecomp.appc.configuration.ConfigurationFactory; import org.openecomp.appc.i18n.Msg; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceRegistration; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + /** * This activator is used to initialize and terminate the connection pool to one or more providers. * <p> @@ -94,7 +95,13 @@ public class AppcProviderAdapterActivator implements BundleActivator { configuration = ConfigurationFactory.getConfiguration(); String appName = configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME); logger.info(Msg.COMPONENT_INITIALIZING, appName, "IAAS adapter"); - adapter = new ProviderAdapterImpl(configuration.getProperties()); + try{ + adapter = new ProviderAdapterImpl(configuration.getProperties()); + }catch(Throwable t){ + logger.error("Error initializing APPC IAAS ProviderAdapterImpl",t); + throw t; + } + if (registration == null) { logger.info(Msg.REGISTERING_SERVICE, appName, adapter.getAdapterName(), ProviderAdapter.class.getSimpleName()); diff --git a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/ProviderAdapter.java b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/ProviderAdapter.java index f7a8b30ed..4f14e14ff 100644 --- a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/ProviderAdapter.java +++ b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/ProviderAdapter.java @@ -65,6 +65,17 @@ public interface ProviderAdapter extends SvcLogicJavaPlugin { * The fully-qualified URL of the instance to be manipulated as it is known to the provider. */ static final String PROPERTY_IDENTITY_URL = "org.openecomp.appc.identity.url"; + + /** + * The Rebuild VM flag is an optional payload parameter for the Evacuate API. + */ + static final String PROPERTY_REBUILD_VM = "org.openecomp.appc.rebuildvm"; + + /** + * The target host id is an optional payload parameter for the Evacuate API. + */ + static final String PROPERTY_TARGETHOST_ID = "org.openecomp.appc.targethost.id"; + /** * heat stack id to perform operation on stack */ @@ -75,6 +86,8 @@ public interface ProviderAdapter extends SvcLogicJavaPlugin { static final String PROPERTY_INPUT_SNAPSHOT_ID = "org.openecomp.appc.snapshot.id"; static final String DG_OUTPUT_PARAM_NAMESPACE = "output."; + + static final String SKIP_HYPERVISOR_CHECK = "org.openecomp.appc.skiphypervisorcheck"; /** * This method is used to restart an existing virtual machine given the fully qualified URL of the machine. diff --git a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/impl/ProviderAdapterImpl.java b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/impl/ProviderAdapterImpl.java index b1bba0918..683bc141c 100644 --- a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/impl/ProviderAdapterImpl.java +++ b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/impl/ProviderAdapterImpl.java @@ -19,52 +19,32 @@ * ============LICENSE_END========================================================= */ + package org.openecomp.appc.adapter.iaas.impl; -import com.woorea.openstack.base.client.OpenStackBaseException; -import com.woorea.openstack.heat.Heat; -import org.glassfish.grizzly.http.util.HttpStatus; import org.openecomp.appc.Constants; import org.openecomp.appc.adapter.iaas.ProviderAdapter; -import org.openecomp.appc.adapter.openstack.heat.SnapshotResource; -import org.openecomp.appc.adapter.openstack.heat.StackResource; -import org.openecomp.appc.adapter.openstack.heat.model.CreateSnapshotParams; -import org.openecomp.appc.adapter.openstack.heat.model.Snapshot; +import org.openecomp.appc.adapter.iaas.provider.operation.api.IProviderOperation; +import org.openecomp.appc.adapter.iaas.provider.operation.api.ProviderOperationFactory; +import org.openecomp.appc.adapter.iaas.provider.operation.common.constants.Property; +import org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Operation; +import org.openecomp.appc.adapter.iaas.provider.operation.impl.EvacuateServer; import org.openecomp.appc.configuration.Configuration; import org.openecomp.appc.configuration.ConfigurationFactory; import org.openecomp.appc.exceptions.APPCException; -import org.openecomp.appc.exceptions.UnknownProviderException; -import org.openecomp.appc.i18n.Msg; -import org.openecomp.appc.pool.Pool; -import org.openecomp.appc.pool.PoolExtensionException; import org.openecomp.appc.util.StructuredPropertyHelper; import org.openecomp.appc.util.StructuredPropertyHelper.Node; -import com.att.cdp.exceptions.*; -import com.att.cdp.openstack.OpenStackContext; -import com.att.cdp.openstack.connectors.HeatConnector; -import com.att.cdp.openstack.util.ExceptionMapper; -import com.att.cdp.pal.util.StringHelper; -import com.att.cdp.zones.*; import com.att.cdp.zones.model.Image; import com.att.cdp.zones.model.Server; -import com.att.cdp.zones.model.ServerBootSource; import com.att.cdp.zones.model.Stack; -import com.att.cdp.zones.model.Server.Status; -import com.att.cdp.zones.spi.AbstractService; -import com.att.cdp.zones.spi.RequestState; import com.att.eelf.configuration.EELFLogger; import com.att.eelf.configuration.EELFManager; -import com.att.eelf.i18n.EELFResourceManager; import org.openecomp.sdnc.sli.SvcLogicContext; -import org.slf4j.MDC; - -import static com.att.eelf.configuration.Configuration.MDC_SERVICE_NAME; -import java.io.IOException; -import java.net.URI; -import java.text.SimpleDateFormat; -import java.util.*; -import java.util.regex.Pattern; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; /** * This class implements the {@link ProviderAdapter} interface. This interface defines the behaviors that our service @@ -74,192 +54,18 @@ import java.util.regex.Pattern; public class ProviderAdapterImpl implements ProviderAdapter { /** - * The name of the adapter - */ - @SuppressWarnings("nls") - private static final String ADAPTER_NAME = "Appc IaaS Adapter"; - - /** - * The username and password to use for dynamically created connections - */ - private static String DEFAULT_USER; - private static String DEFAULT_PASS; - - /** - * The constant used to define the adapter name in the mapped diagnostic context - */ - @SuppressWarnings("nls") - private static final String MDC_ADAPTER = "adapter"; - - /** - * The constant used to define the service name in the mapped diagnostic context - */ - @SuppressWarnings("nls") - static final String MDC_SERVICE = "service"; - - /** - * The constant for the status code for a failed outcome - */ - @SuppressWarnings("nls") - private static final String OUTCOME_FAILURE = "failure"; - - /** - * The constant for the status code for a successful outcome - */ - @SuppressWarnings("nls") - private static final String OUTCOME_SUCCESS = "success"; - - /** - * A constant for the property token "provider" used in the structured property specifications - */ - @SuppressWarnings("nls") - private static final String PROPERTY_PROVIDER = "provider"; - - /** - * A constant for the property token "identity" used in the structured property specifications - */ - @SuppressWarnings("nls") - private static final String PROPERTY_PROVIDER_IDENTITY = "identity"; - - /** - * A constant for the property token "tenant" used in the structured property specifications - */ - @SuppressWarnings("nls") - private static final String PROPERTY_PROVIDER_TENANT = "tenant"; - - /** - * A constant for the property token "tenant name" used in the structured property specifications - */ - @SuppressWarnings("nls") - private static final String PROPERTY_PROVIDER_TENANT_NAME = "name"; - - /** - * A constant for the property token "password" used in the structured property specifications - */ - @SuppressWarnings("nls") - private static final String PROPERTY_PROVIDER_TENANT_PASSWORD = "password"; // NOSONAR - - /** - * A constant for the property token "userid" used in the structured property specifications - */ - @SuppressWarnings("nls") - private static final String PROPERTY_PROVIDER_TENANT_USERID = "userid"; - - /** - * A constant for the property token "type" used in the structured property specifications - */ - @SuppressWarnings("nls") - private static final String PROPERTY_PROVIDER_TYPE = "type"; - - /** - * The name of the service to evacuate a server - */ - @SuppressWarnings("nls") - private static final String EVACUATE_SERVICE = "evacuateServer"; - - /** - * The name of the service to migrate a server - */ - @SuppressWarnings("nls") - private static final String MIGRATE_SERVICE = "migrateServer"; - - /** - * The name of the service to rebuild a server - */ - @SuppressWarnings("nls") - private static final String REBUILD_SERVICE = "rebuildServer"; - - /** - * The name of the service to restart a server - */ - @SuppressWarnings("nls") - private static final String RESTART_SERVICE = "restartServer"; - - /** - * The name of the service to check status of a server - */ - @SuppressWarnings("nls") - private static final String VMSTATUSCHECK_SERVICE = "vmStatuschecker"; - - - /** - * The name of the service to restart a server - */ - @SuppressWarnings("nls") - private static final String SNAPSHOT_SERVICE = "createSnapshot"; - - /** - * The name of the service to terminate a stack - */ - @SuppressWarnings("nls") - private static final String TERMINATE_STACK = "terminateStack"; - - /** - * The name of the service to snapshot a stack - */ - @SuppressWarnings("nls") - private static final String SNAPSHOT_STACK = "snapshotStack"; - - /** - * The name of a service to start a server - */ - @SuppressWarnings("nls") - private static final String START_SERVICE = "startServer"; - - /** - * The name of the service to stop a server - */ - @SuppressWarnings("nls") - private static final String STOP_SERVICE = "stopServer"; - - /** - * The name of the service to stop a server - */ - @SuppressWarnings("nls") - private static final String TERMINATE_SERVICE = "terminateServer"; - - /** - * The name of the service to lookup a server - */ - @SuppressWarnings("nls") - private static final String LOOKUP_SERVICE = "lookupServer"; - - /** * The logger to be used */ private static final EELFLogger logger = EELFManager.getInstance().getLogger(ProviderAdapterImpl.class); - - private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; - - /** - * The constant for a left parenthesis - */ - private static final char LPAREN = '('; - - /** - * The constant for a new line control code - */ - private static final char NL = '\n'; - - /** - * The constant for a single quote - */ - private static final char QUOTE = '\''; - /** - * The constant for a right parenthesis - */ - private static final char RPAREN = ')'; - - /** - * The constant for a space + * A reference to the adapter configuration object. */ - private static final char SPACE = ' '; + private Configuration configuration; /** - * A reference to the adapter configuration object. + * reference to operation factory */ - private Configuration configuration; + ProviderOperationFactory factory = ProviderOperationFactory.getInstance(); /** * A cache of providers that are predefined. @@ -267,9 +73,11 @@ public class ProviderAdapterImpl implements ProviderAdapter { private Map<String /* provider name */, ProviderCache> providerCache; /** - * A list of valid initial VM statuses for a migrate operations + * The username and password to use for dynamically created connections */ - private static final Collection<Status> migratableStatuses = Arrays.asList(Status.READY, Status.RUNNING, Status.SUSPENDED); + private static String DEFAULT_USER; + private static String DEFAULT_PASS; + /** * This default constructor is used as a work around because the activator wasnt getting called @@ -304,999 +112,149 @@ public class ProviderAdapterImpl implements ProviderAdapter { } - /** - * Returns the symbolic name of the adapter - * - * @return The adapter name - * @see org.openecomp.appc.adapter.iaas.ProviderAdapter#getAdapterName() - */ - @Override - public String getAdapterName() { - return configuration.getProperty(Constants.PROPERTY_ADAPTER_NAME); - } - - @SuppressWarnings("nls") @Override - public Image createSnapshot(Map<String, String> params, SvcLogicContext ctx) throws APPCException { - Image snapshot = null; - RequestContext rc = new RequestContext(ctx); - rc.isAlive(); - MDC.put(MDC_ADAPTER, ADAPTER_NAME); - MDC.put(MDC_SERVICE, SNAPSHOT_SERVICE); - MDC.put(MDC_SERVICE_NAME, "App-C IaaS Adapter:Snapshot"); - String appName = configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME); - logger.info(Msg.SNAPSHOTING_SERVER, appName); - String msg; - - try { - validateParametersExist(rc, params, ProviderAdapter.PROPERTY_INSTANCE_URL, - ProviderAdapter.PROPERTY_PROVIDER_NAME); - String vm_url = params.get(ProviderAdapter.PROPERTY_INSTANCE_URL); - debugParameters(params); - debugContext(ctx); - - VMURL vm = VMURL.parseURL(vm_url); - if (validateVM(rc, appName, vm_url, vm)) return null; - - IdentityURL ident = IdentityURL.parseURL(params.get(ProviderAdapter.PROPERTY_IDENTITY_URL)); - String identStr = (ident == null) ? null : ident.toString(); - - Context context = null; - try { - context = getContext(rc, vm_url, identStr); - if (context != null) { - Server server = lookupServer(rc, context, vm.getServerId()); - logger.debug(Msg.SERVER_FOUND, vm_url, context.getTenantName(), server.getStatus().toString()); - - if (hasImageAccess(rc, context)) { - snapshot = createSnapshot(rc, server); - doSuccess(rc); - } else { - msg = EELFResourceManager.format(Msg.REBUILD_SERVER_FAILED, server.getName(), server.getId(), - "Accessing Image Service Failed"); - logger.error(msg); - doFailure(rc, HttpStatus.FORBIDDEN_403, msg); - } - context.close(); - } - } catch (ResourceNotFoundException e) { - msg = EELFResourceManager.format(Msg.SERVER_NOT_FOUND, e, vm_url); - logger.error(msg); - doFailure(rc, HttpStatus.NOT_FOUND_404, msg); - } catch (Throwable t) { - msg = EELFResourceManager.format(Msg.SERVER_OPERATION_EXCEPTION, t, t.getClass().getSimpleName(), - SNAPSHOT_SERVICE, vm_url, context == null ? "Unknown" : context.getTenantName()); - logger.error(msg, t); - doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg); - } - } catch (RequestFailedException e) { - doFailure(rc, e.getStatus(), e.getMessage()); - } - return snapshot; - } - - private boolean validateVM(RequestContext rc, String appName, String vm_url, VMURL vm) - throws RequestFailedException { - String msg; - if (vm == null) { - msg = EELFResourceManager.format(Msg.INVALID_SELF_LINK_URL, appName, vm_url); - logger.error(msg); - doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg); - return true; - } - validateVMURL(vm); - return false; - } - - private Image createSnapshot(RequestContext rc, Server server) throws ZoneException, RequestFailedException { - Context context = server.getContext(); - Provider provider = context.getProvider(); - ImageService service = context.getImageService(); // Already checked access by this point - - String snapshotName = generateSnapshotName(server.getName()); - - logger.info(String.format("Creating snapshot of server %s (%s) with name %s", server.getName(), server.getId(), - snapshotName)); - - // Request Snapshot - String msg; - while (rc.attempt()) { - try { - server.createSnapshot(snapshotName); - break; - } catch (ContextConnectionException e) { - msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(), - context.getTenant().getName(), context.getTenant().getId(), e.getMessage(), - Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()), - Integer.toString(rc.getRetryLimit())); - logger.error(msg, e); - rc.delay(); - } - } - if (rc.isFailed()) { - msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL()); - logger.error(msg); - throw new RequestFailedException("Stop Server", msg, HttpStatus.BAD_GATEWAY_502, server); - } - rc.reset(); - - // Locate snapshot image - Image snapshot = null; - while (rc.attempt()) { - try { - snapshot = service.getImageByName(snapshotName); - if (snapshot != null) { - break; - } - } catch (ContextConnectionException e) { - msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(), - context.getTenant().getName(), context.getTenant().getId(), e.getMessage(), - Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()), - Integer.toString(rc.getRetryLimit())); - logger.error(msg, e); - rc.delay(); - } - } - if (rc.isFailed()) { - msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL()); - logger.error(msg); - throw new RequestFailedException("Stop Server", msg, HttpStatus.BAD_GATEWAY_502, server); - } - rc.reset(); - - // Wait for it to be ready - waitForStateChange(rc, snapshot, Image.Status.ACTIVE); - - return snapshot; - } + public Server restartServer(Map<String, String> params, SvcLogicContext context) throws APPCException { - private String generateSnapshotName(String server) { - SimpleDateFormat df = new SimpleDateFormat(DATE_FORMAT); - return String.format("Snapshot of %s at %s", server, df.format(new Date())); + IProviderOperation op = factory.getOperationObject(Operation.RESTART_SERVICE); + op.setProviderCache(this.providerCache); + op.setDefaultPass(DEFAULT_PASS); + op.setDefaultUser(DEFAULT_USER); + return (Server) op.doOperation(params, context); } - /** - * @see org.openecomp.appc.adapter.iaas.ProviderAdapter#evacuateServer(java.util.Map, org.openecomp.sdnc.sli.SvcLogicContext) - */ - @SuppressWarnings("nls") @Override - public Server evacuateServer(Map<String, String> params, SvcLogicContext ctx) throws APPCException { - Server server = null; - RequestContext rc = new RequestContext(ctx); - rc.isAlive(); - MDC.put(MDC_ADAPTER, ADAPTER_NAME); - MDC.put(MDC_SERVICE, EVACUATE_SERVICE); - MDC.put(MDC_SERVICE_NAME, "App-C IaaS Adapter:Evacuate"); - String appName = configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME); - logger.info(Msg.EVACUATING_SERVER, appName); - String msg; - - try { - validateParametersExist(rc, params, ProviderAdapter.PROPERTY_INSTANCE_URL, - ProviderAdapter.PROPERTY_PROVIDER_NAME); - String vm_url = params.get(ProviderAdapter.PROPERTY_INSTANCE_URL); - String providerName = params.get(ProviderAdapter.PROPERTY_PROVIDER_NAME); - debugParameters(params); - debugContext(ctx); - - VMURL vm = VMURL.parseURL(vm_url); - if (validateVM(rc, appName, vm_url, vm)) return null; + public Server stopServer(Map<String, String> params, SvcLogicContext context) throws APPCException { - Context context = null; - try { - context = getContext(rc, vm_url, providerName); - if (context != null) { - server = lookupServer(rc, context, vm.getServerId()); - logger.debug(Msg.SERVER_FOUND, vm_url, context.getTenantName(), server.getStatus().toString()); - evacuateServer(rc, server); - server.refreshStatus(); - context.close(); - doSuccess(rc); - } - } catch (ResourceNotFoundException e) { - msg = EELFResourceManager.format(Msg.SERVER_NOT_FOUND, e, vm_url); - logger.error(msg); - doFailure(rc, HttpStatus.NOT_FOUND_404, msg); - } catch (Throwable t) { - msg = EELFResourceManager.format(Msg.SERVER_OPERATION_EXCEPTION, t, t.getClass().getSimpleName(), - EVACUATE_SERVICE, vm_url, context == null ? "Unknown" : context.getTenantName()); - logger.error(msg, t); - doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg); - } - } catch (RequestFailedException e) { - doFailure(rc, e.getStatus(), e.getMessage()); - } - - return server; + IProviderOperation op = factory.getOperationObject(Operation.STOP_SERVICE); + op.setProviderCache(this.providerCache); + op.setDefaultPass(DEFAULT_PASS); + op.setDefaultUser(DEFAULT_USER); + return (Server) op.doOperation(params, context); } - /** - * @see org.openecomp.appc.adapter.iaas.ProviderAdapter#migrateServer(java.util.Map, org.openecomp.sdnc.sli.SvcLogicContext) - */ - @SuppressWarnings("nls") @Override - public Server migrateServer(Map<String, String> params, SvcLogicContext ctx) throws APPCException { - Server server = null; - RequestContext rc = new RequestContext(ctx); - rc.isAlive(); - MDC.put(MDC_ADAPTER, ADAPTER_NAME); - MDC.put(MDC_SERVICE, MIGRATE_SERVICE); - MDC.put(MDC_SERVICE_NAME, "App-C IaaS Adapter:Migrate"); - String appName = configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME); - logger.info(Msg.MIGRATING_SERVER, appName); - String msg; - - try { - validateParametersExist(rc, params, ProviderAdapter.PROPERTY_INSTANCE_URL, - ProviderAdapter.PROPERTY_PROVIDER_NAME); - String vm_url = params.get(ProviderAdapter.PROPERTY_INSTANCE_URL); - debugParameters(params); - debugContext(ctx); - - VMURL vm = VMURL.parseURL(vm_url); - if (validateVM(rc, appName, vm_url, vm)) return null; - - IdentityURL ident = IdentityURL.parseURL(params.get(ProviderAdapter.PROPERTY_IDENTITY_URL)); - String identStr = (ident == null) ? null : ident.toString(); - - Context context = null; - try { - context = getContext(rc, vm_url, identStr); - if (context != null) { - server = lookupServer(rc, context, vm.getServerId()); - logger.debug(Msg.SERVER_FOUND, vm_url, context.getTenantName(), server.getStatus().toString()); - migrateServer(rc, server); - server.refreshStatus(); - context.close(); - doSuccess(rc); - } - } catch (ResourceNotFoundException e) { - msg = EELFResourceManager.format(Msg.SERVER_NOT_FOUND, e, vm_url); - logger.error(msg); - doFailure(rc, HttpStatus.NOT_FOUND_404, msg); - } catch (Throwable t) { - msg = EELFResourceManager.format(Msg.SERVER_OPERATION_EXCEPTION, t, t.getClass().getSimpleName(), - MIGRATE_SERVICE, vm_url, context == null ? "Unknown" : context.getTenantName()); - logger.error(msg, t); - doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg); - } - } catch (RequestFailedException e) { - doFailure(rc, e.getStatus(), e.getMessage()); - } - - return server; - } + public Server startServer(Map<String, String> params, SvcLogicContext context) throws APPCException { - private void evacuateServer(RequestContext rc, @SuppressWarnings("unused") Server server) throws ZoneException, RequestFailedException { - doFailure(rc, HttpStatus.NOT_IMPLEMENTED_501, "The operation 'EVACUATE' is not yet implemented"); + IProviderOperation op = factory.getOperationObject(Operation.START_SERVICE); + op.setProviderCache(this.providerCache); + op.setDefaultPass(DEFAULT_PASS); + op.setDefaultUser(DEFAULT_USER); + return (Server) op.doOperation(params, context); } - private void migrateServer(RequestContext rc, Server server) throws ZoneException, RequestFailedException { - String msg; - Context ctx = server.getContext(); - ComputeService service = ctx.getComputeService(); - - // Init status will equal final status - Status initialStatus = server.getStatus(); - - if (initialStatus == null) { - throw new ZoneException("Failed to determine server's starting status"); - } - - // We can only migrate certain statuses - if (!migratableStatuses.contains(initialStatus)) { - throw new ZoneException(String.format("Cannot migrate server that is in %s state. Must be in one of [%s]", - initialStatus, migratableStatuses)); - } - - boolean inConfirmPhase = false; - try { - while (rc.attempt()) { - try { - if (!inConfirmPhase) { - // Initial migrate request - service.migrateServer(server.getId()); - // Wait for change to verify resize - waitForStateChange(rc, server, Status.READY); - inConfirmPhase = true; - } - - // Verify resize - service.processResize(server); - // Wait for complete. will go back to init status - waitForStateChange(rc, server, initialStatus); - logger.info("Completed migrate request successfully"); - return; - } catch (ContextConnectionException e) { - msg = getConnectionExceptionMessage(rc, ctx, e); - logger.error(msg, e); - rc.delay(); - } - } - } catch (ZoneException e) { - String phase = inConfirmPhase ? "VERIFY MIGRATE" : "REQUEST MIGRATE"; - msg = EELFResourceManager.format(Msg.MIGRATE_SERVER_FAILED, server.getName(), server.getId(), phase, - e.getMessage()); - generateEvent(rc, false, msg); - logger.error(msg, e); - throw new RequestFailedException("Migrate Server", msg, HttpStatus.METHOD_NOT_ALLOWED_405, server); - } - - } - - /** - * @see org.openecomp.appc.adapter.iaas.ProviderAdapter#rebuildServer(java.util.Map, org.openecomp.sdnc.sli.SvcLogicContext) - */ - @SuppressWarnings("nls") @Override - public Server rebuildServer(Map<String, String> params, SvcLogicContext ctx) throws APPCException { - Server server = null; - RequestContext rc = new RequestContext(ctx); - rc.isAlive(); - MDC.put(MDC_ADAPTER, ADAPTER_NAME); - MDC.put(MDC_SERVICE, REBUILD_SERVICE); - MDC.put(MDC_SERVICE_NAME, "App-C IaaS Adapter:Rebuild"); - String appName = configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME); - logger.info(Msg.REBUILDING_SERVER, appName); - String msg; - - try { - validateParametersExist(rc, params, ProviderAdapter.PROPERTY_INSTANCE_URL, - ProviderAdapter.PROPERTY_PROVIDER_NAME); - String vm_url = params.get(ProviderAdapter.PROPERTY_INSTANCE_URL); - debugParameters(params); - debugContext(ctx); - - VMURL vm = VMURL.parseURL(vm_url); - if (validateVM(rc, appName, vm_url, vm)) return null; - - IdentityURL ident = IdentityURL.parseURL(params.get(ProviderAdapter.PROPERTY_IDENTITY_URL)); - String identStr = (ident == null) ? null : ident.toString(); - - Context context = null; - try { - context = getContext(rc, vm_url, identStr); - if (context != null) { - server = lookupServer(rc, context, vm.getServerId()); - logger.debug(Msg.SERVER_FOUND, vm_url, context.getTenantName(), server.getStatus().toString()); + public Server rebuildServer(Map<String, String> params, SvcLogicContext context) throws APPCException { - // Manually checking image service until new PAL release - if (hasImageAccess(rc, context)) { - rebuildServer(rc, server); - doSuccess(rc); - } else { - msg = EELFResourceManager.format(Msg.REBUILD_SERVER_FAILED, server.getName(), server.getId(), - "Accessing Image Service Failed"); - logger.error(msg); - doFailure(rc, HttpStatus.FORBIDDEN_403, msg); - } - context.close(); - } - } catch (ResourceNotFoundException e) { - msg = EELFResourceManager.format(Msg.SERVER_NOT_FOUND, e, vm_url); - logger.error(msg); - doFailure(rc, HttpStatus.NOT_FOUND_404, msg); - } catch (Throwable t) { - msg = EELFResourceManager.format(Msg.SERVER_OPERATION_EXCEPTION, t, t.getClass().getSimpleName(), - STOP_SERVICE, vm_url, context == null ? "Unknown" : context.getTenantName()); - logger.error(msg, t); - doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg); - } - } catch (RequestFailedException e) { - doFailure(rc, e.getStatus(), e.getMessage()); - } - - return server; + IProviderOperation op = factory.getOperationObject(Operation.REBUILD_SERVICE); + op.setProviderCache(this.providerCache); + op.setDefaultPass(DEFAULT_PASS); + op.setDefaultUser(DEFAULT_USER); + return (Server) op.doOperation(params, context); } - /** - * This method is used to restart an existing virtual machine given the fully qualified URL of the machine. - * <p> - * The fully qualified URL contains enough information to locate the appropriate server. The URL is of the form - * <pre> - * [scheme]://[host[:port]] / [path] / [tenant_id] / servers / [vm_id] - * </pre> Where the various parts of the URL can be parsed and extracted and used to locate the appropriate service - * in the provider service catalog. This then allows us to open a context using the CDP abstraction, obtain the - * server by its UUID, and then perform the restart. - * </p> - * - * @throws UnknownProviderException - * If the provider cannot be found - * @throws IllegalArgumentException - * if the expected argument(s) are not defined or are invalid - * @see org.openecomp.appc.adapter.iaas.ProviderAdapter#restartServer(java.util.Map, org.openecomp.sdnc.sli.SvcLogicContext) - */ - @SuppressWarnings("nls") @Override - public Server restartServer(Map<String, String> params, SvcLogicContext ctx) - throws UnknownProviderException, IllegalArgumentException { - Server server = null; - RequestContext rc = new RequestContext(ctx); - rc.isAlive(); - MDC.put(MDC_ADAPTER, ADAPTER_NAME); - MDC.put(MDC_SERVICE, RESTART_SERVICE); - MDC.put(MDC_SERVICE_NAME, "App-C IaaS Adapter:Restart"); - String appName = configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME); - logger.info(Msg.RESTARTING_SERVER, appName); - - try { - validateParametersExist(rc, params, ProviderAdapter.PROPERTY_INSTANCE_URL, - ProviderAdapter.PROPERTY_PROVIDER_NAME); - debugParameters(params); - debugContext(ctx); - String vm_url = params.get(ProviderAdapter.PROPERTY_INSTANCE_URL); - - VMURL vm = VMURL.parseURL(vm_url); - if (validateVM(rc, appName, vm_url, vm)) return null; + public Server terminateServer(Map<String, String> params, SvcLogicContext context) throws APPCException { - IdentityURL ident = IdentityURL.parseURL(params.get(ProviderAdapter.PROPERTY_IDENTITY_URL)); - String identStr = (ident == null) ? null : ident.toString(); - - Context context = null; - try { - context = getContext(rc, vm_url, identStr); - if (context != null) { - server = lookupServer(rc, context, vm.getServerId()); - logger.debug(Msg.SERVER_FOUND, vm_url, context.getTenantName(), server.getStatus().toString()); - restartServer(rc, server); - context.close(); - doSuccess(rc); - } - } catch (ResourceNotFoundException e) { - String msg = EELFResourceManager.format(Msg.SERVER_NOT_FOUND, e, vm_url); - logger.error(msg); - doFailure(rc, HttpStatus.NOT_FOUND_404, msg); - } catch (Throwable t) { - String msg = EELFResourceManager.format(Msg.SERVER_OPERATION_EXCEPTION, t, t.getClass().getSimpleName(), - RESTART_SERVICE, vm_url, context == null ? "Unknown" : context.getTenantName()); - logger.error(msg, t); - doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg); - } - } catch (RequestFailedException e) { - doFailure(rc, e.getStatus(), e.getMessage()); - } - - return server; + IProviderOperation op = factory.getOperationObject(Operation.TERMINATE_SERVICE); + op.setProviderCache(this.providerCache); + op.setDefaultPass(DEFAULT_PASS); + op.setDefaultUser(DEFAULT_USER); + return (Server) op.doOperation(params, context); } - /* *********************************************************************************/ - /* DEVEN PANCHAL: This method is used to check the status of the VM */ - /**********************************************************************************/ - public Server vmStatuschecker(Map<String, String> params, SvcLogicContext ctx) throws UnknownProviderException, IllegalArgumentException { - Server server = null; - RequestContext rc = new RequestContext(ctx); - rc.isAlive(); - MDC.put(MDC_ADAPTER, ADAPTER_NAME); - MDC.put(MDC_SERVICE, VMSTATUSCHECK_SERVICE); - MDC.put(MDC_SERVICE_NAME, "App-C IaaS Adapter: vmstatuscheck"); - String appName = configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME); - - try { - validateParametersExist(rc, params, ProviderAdapter.PROPERTY_INSTANCE_URL, - ProviderAdapter.PROPERTY_PROVIDER_NAME); - debugParameters(params); - debugContext(ctx); - String vm_url = params.get(ProviderAdapter.PROPERTY_INSTANCE_URL); - - VMURL vm = VMURL.parseURL(vm_url); - if (validateVM(rc, appName, vm_url, vm)) return null; - - IdentityURL ident = IdentityURL.parseURL(params.get(ProviderAdapter.PROPERTY_IDENTITY_URL)); - String identStr = (ident == null) ? null : ident.toString(); - - Context context = null; - try { - context = getContext(rc, vm_url, identStr); - if (context != null) { - server = lookupServer(rc, context, vm.getServerId()); - logger.debug(Msg.SERVER_FOUND, vm_url, context.getTenantName(), server.getStatus().toString()); - - String statusvm; - switch (server.getStatus()) { - case DELETED: - statusvm = "deleted"; - break; - - case RUNNING: - statusvm = "running"; - break; - - case ERROR: - statusvm = "error"; - break; - - case READY: - statusvm = "ready"; - break; - - case PAUSED: - statusvm = "paused"; - break; - - case SUSPENDED: - statusvm = "suspended"; - break; - - case PENDING: - statusvm = "pending"; - break; - - default: - statusvm = "default-unknown state-should never occur"; - break; - } - - - String statusofVM = statusvm; - context.close(); - SvcLogicContext svcLogic = rc.getSvcLogicContext(); - svcLogic.setStatus(OUTCOME_SUCCESS); - svcLogic.setAttribute("org.openecomp.statusofvm", statusofVM); - svcLogic.setAttribute(Constants.STATUS_OF_VM, statusofVM); - svcLogic.setAttribute(Constants.ATTRIBUTE_ERROR_CODE, Integer.toString(HttpStatus.OK_200.getStatusCode())); - } - } catch (ResourceNotFoundException e) { - String msg = EELFResourceManager.format(Msg.SERVER_NOT_FOUND, e, vm_url); - logger.error(msg); - doFailure(rc, HttpStatus.NOT_FOUND_404, msg); - } catch (Throwable t) { - String msg = EELFResourceManager.format(Msg.SERVER_OPERATION_EXCEPTION, t, t.getClass().getSimpleName(), - RESTART_SERVICE, vm_url, context == null ? "Unknown" : context.getTenantName()); - logger.error(msg, t); - doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg); - } - } catch (RequestFailedException e) { - doFailure(rc, e.getStatus(), e.getMessage()); - } - - return server; - } - - /* *********************************************************************************/ - - - /** - * @see org.openecomp.appc.adapter.iaas.ProviderAdapter#startServer(java.util.Map, org.openecomp.sdnc.sli.SvcLogicContext) - */ - @SuppressWarnings("nls") @Override - public Server startServer(Map<String, String> params, SvcLogicContext ctx) throws APPCException { - Server server = null; - RequestContext rc = new RequestContext(ctx); - rc.isAlive(); - MDC.put(MDC_ADAPTER, ADAPTER_NAME); - MDC.put(MDC_SERVICE, START_SERVICE); - String appName = configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME); - logger.info(Msg.RESTARTING_SERVER, appName); - - try { - validateParametersExist(rc, params, ProviderAdapter.PROPERTY_INSTANCE_URL, - ProviderAdapter.PROPERTY_PROVIDER_NAME); - debugParameters(params); - debugContext(ctx); - String vm_url = params.get(ProviderAdapter.PROPERTY_INSTANCE_URL); - String providerName = params.get(ProviderAdapter.PROPERTY_PROVIDER_NAME); - - VMURL vm = VMURL.parseURL(vm_url); - if (validateVM(rc, appName, vm_url, vm)) return null; - - Context context = null; - try { - context = getContext(rc, vm_url, providerName); - if (context != null) { - server = lookupServer(rc, context, vm.getServerId()); - logger.debug(Msg.SERVER_FOUND, vm_url, context.getTenantName(), server.getStatus().toString()); - stopServer(rc, server); - server.refreshStatus(); - context.close(); - doSuccess(rc); - } - } catch (ResourceNotFoundException e) { - String msg = EELFResourceManager.format(Msg.SERVER_NOT_FOUND, e, vm_url); - logger.error(msg); - doFailure(rc, HttpStatus.NOT_FOUND_404, msg); - } catch (Throwable t) { - String msg = EELFResourceManager.format(Msg.SERVER_OPERATION_EXCEPTION, t, t.getClass().getSimpleName(), - START_SERVICE, vm_url, context == null ? "Unknown" : context.getTenantName()); - logger.error(msg, t); - doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg); - } - } catch (RequestFailedException e) { - doFailure(rc, e.getStatus(), e.getMessage()); - } + public Server evacuateServer(Map<String, String> params, SvcLogicContext context) throws APPCException { - return server; + IProviderOperation op = factory.getOperationObject(Operation.EVACUATE_SERVICE); + op.setProviderCache(this.providerCache); + op.setDefaultPass(DEFAULT_PASS); + op.setDefaultUser(DEFAULT_USER); + // pass this object's reference to EvacuateServer to allow rebuild after evacuate + ((EvacuateServer) op).setProvideAdapterRef(this); + return (Server) op.doOperation(params, context); } - /** - * @see org.openecomp.appc.adapter.iaas.ProviderAdapter#stopServer(java.util.Map, org.openecomp.sdnc.sli.SvcLogicContext) - */ - @SuppressWarnings("nls") @Override - public Server stopServer(Map<String, String> params, SvcLogicContext ctx) throws APPCException { - Server server = null; - RequestContext rc = new RequestContext(ctx); - rc.isAlive(); - MDC.put(MDC_ADAPTER, ADAPTER_NAME); - MDC.put(MDC_SERVICE, STOP_SERVICE); - String appName = configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME); - logger.info(Msg.STOPPING_SERVER, appName); - - try { - validateParametersExist(rc, params, ProviderAdapter.PROPERTY_INSTANCE_URL, - ProviderAdapter.PROPERTY_PROVIDER_NAME); - debugParameters(params); - debugContext(ctx); - String vm_url = params.get(ProviderAdapter.PROPERTY_INSTANCE_URL); - ctx.setAttribute("STOP_STATUS", "SUCCESS"); - - VMURL vm = VMURL.parseURL(vm_url); - if (validateVM(rc, appName, vm_url, vm)) return null; - - IdentityURL ident = IdentityURL.parseURL(params.get(ProviderAdapter.PROPERTY_IDENTITY_URL)); - String identStr = (ident == null) ? null : ident.toString(); - - Context context = null; - try { - context = getContext(rc, vm_url, identStr); - if (context != null) { - server = lookupServer(rc, context, vm.getServerId()); - logger.debug(Msg.SERVER_FOUND, vm_url, context.getTenantName(), server.getStatus().toString()); - if (server.getStatus().equals(Status.PENDING)) { - throw new RequestFailedException("Server is in pending Status"); - } - stopServer(rc, server); - server.refreshStatus(); - if (server.getStatus().equals(Status.ERROR)) { - throw new RequestFailedException("Server is in ERROR state after operation"); - } - context.close(); - doSuccess(rc); - }else{ - ctx.setAttribute("STOP_STATUS", "SERVER_NOT_FOUND"); - } - } catch (ResourceNotFoundException e) { - String msg = EELFResourceManager.format(Msg.SERVER_NOT_FOUND, e, vm_url); - ctx.setAttribute("STOP_STATUS", "SERVER_NOT_FOUND"); - logger.error(msg); - doFailure(rc, HttpStatus.NOT_FOUND_404, msg); - } catch (Throwable t) { - String msg = EELFResourceManager.format(Msg.SERVER_OPERATION_EXCEPTION, t, t.getClass().getSimpleName(), - STOP_SERVICE, vm_url, context == null ? "Unknown" : context.getTenantName()); - logger.error(msg, t); - ctx.setAttribute("STOP_STATUS", "ERROR"); - doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg); - } - } catch (RequestFailedException e) { - logger.error(EELFResourceManager.format(Msg.STOP_SERVER_FAILED, appName, "n/a", "n/a", e.getMessage())); - ctx.setAttribute("STOP_STATUS", "ERROR"); - doFailure(rc, e.getStatus(), e.getMessage()); - } + public Server migrateServer(Map<String, String> params, SvcLogicContext context) throws APPCException { - return server; + IProviderOperation op = factory.getOperationObject(Operation.MIGRATE_SERVICE); + op.setProviderCache(this.providerCache); + op.setDefaultPass(DEFAULT_PASS); + op.setDefaultUser(DEFAULT_USER); + return (Server) op.doOperation(params, context); } - /** - * 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 ctx - * The request context object that manages the request - * @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 - */ - @SuppressWarnings({ - "nls", "static-method" - }) - private void validateParametersExist(@SuppressWarnings("unused") RequestContext ctx, 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(NL); - for (String propertyName : propertyNames) { - String value = parameters.get(propertyName); - if (value == null || value.trim().length() == 0) { - success = false; - msg.append(QUOTE); - msg.append(propertyName); - msg.append(QUOTE); - msg.append(SPACE); - } - } + @Override + public Server vmStatuschecker(Map<String, String> params, SvcLogicContext context) throws APPCException { - if (!success) { - logger.error(msg.toString()); - throw new RequestFailedException("Check Parameters", msg.toString(), HttpStatus.BAD_REQUEST_400, (Server)null); - } + IProviderOperation op = factory.getOperationObject(Operation.VMSTATUSCHECK_SERVICE); + op.setProviderCache(this.providerCache); + op.setDefaultPass(DEFAULT_PASS); + op.setDefaultUser(DEFAULT_USER); + return (Server) op.doOperation(params, context); } - /** - * 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(LPAREN); - builder.append(context.getStatus()); - builder.append(RPAREN); - builder.append(", Attribute count "); - builder.append(LPAREN); - builder.append(keys == null ? "none" : Integer.toString(keys.size())); - builder.append(RPAREN); - if (keys != null && !keys.isEmpty()) { - builder.append(NL); - for (String key : keys) { - String value = context.getAttribute(key); - builder.append("Attribute "); - builder.append(LPAREN); - builder.append(key); - builder.append(RPAREN); - builder.append(", value "); - builder.append(LPAREN); - builder.append(value == null ? "" : value); - builder.append(RPAREN); - builder.append(NL); - } - } + @Override + public Stack terminateStack(Map<String, String> params, SvcLogicContext context) throws APPCException { - logger.debug(builder.toString()); + IProviderOperation op = factory.getOperationObject(Operation.TERMINATE_STACK); + op.setProviderCache(this.providerCache); + op.setDefaultPass(DEFAULT_PASS); + op.setDefaultUser(DEFAULT_USER); + return (Stack) op.doOperation(params, context); } - 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) { - 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); + @Override + public Stack snapshotStack(Map<String, String> params, SvcLogicContext context) throws APPCException { - 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())); - } + IProviderOperation op = factory.getOperationObject(Operation.SNAPSHOT_STACK); + op.setProviderCache(this.providerCache); + op.setDefaultPass(DEFAULT_PASS); + op.setDefaultUser(DEFAULT_USER); + return (Stack) op.doOperation(params, context); } - @SuppressWarnings("unused") - private void validateIdentityURL(IdentityURL id) throws RequestFailedException { - String name = "identity-url"; - if (id == null) { - throw new RequestFailedException(String.format("The value %s cannot be null.", name)); - } + @Override + public Stack restoreStack(Map<String, String> params, SvcLogicContext context) throws APPCException { - // 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(id.toString()); - } catch (Exception e) { - throw new RequestFailedException( - String.format("The value %s is not well formed [%s].", name, id.toString())); - } + IProviderOperation op = factory.getOperationObject(Operation.RESTORE_STACK); + op.setProviderCache(this.providerCache); + op.setDefaultPass(DEFAULT_PASS); + op.setDefaultUser(DEFAULT_USER); + return (Stack) op.doOperation(params, 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 - */ - @SuppressWarnings("static-method") - private void debugParameters(Map<String, String> parameters) { - for (String key : parameters.keySet()) { - logger.debug(Msg.PROPERTY_VALUE, key, parameters.get(key)); - } - } + @Override + public Server lookupServer(Map<String, String> params, SvcLogicContext context) throws APPCException { - /** - * @param rc - * The request context that manages the state and recovery of the request for the life of its processing. - * @param code - * @param message - */ - @SuppressWarnings("static-method") - private void doFailure(RequestContext rc, HttpStatus code, String message) { - try { - doFailure(rc, code, message, null); - } catch (APPCException ignored) {/* never happens */} + IProviderOperation op = factory.getOperationObject(Operation.LOOKUP_SERVICE); + op.setProviderCache(this.providerCache); + op.setDefaultPass(DEFAULT_PASS); + op.setDefaultUser(DEFAULT_USER); + return (Server) op.doOperation(params, context); } + @Override + public Image createSnapshot(Map<String, String> params, SvcLogicContext context) throws APPCException { - private 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) { - status = "500"; - } - svcLogic.setStatus(OUTCOME_FAILURE); - svcLogic.setAttribute(Constants.ATTRIBUTE_ERROR_CODE, status); - svcLogic.setAttribute(Constants.ATTRIBUTE_ERROR_MESSAGE, msg); - svcLogic.setAttribute(Constants.DG_OUTPUT_STATUS_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") - private void doSuccess(RequestContext rc) { - SvcLogicContext svcLogic = rc.getSvcLogicContext(); - svcLogic.setStatus(OUTCOME_SUCCESS); - svcLogic.setAttribute(Constants.ATTRIBUTE_ERROR_CODE, Integer.toString(HttpStatus.OK_200.getStatusCode())); + IProviderOperation op = factory.getOperationObject(Operation.SNAPSHOT_SERVICE); + op.setProviderCache(this.providerCache); + op.setDefaultPass(DEFAULT_PASS); + op.setDefaultUser(DEFAULT_USER); + return (Image) op.doOperation(params, context); } /** - * Generates the event indicating what happened + * Returns the symbolic name of the adapter * - * @param rc - * The request context that manages the state and recovery of the request for the life of its processing. - * @param success - * True if the event represents a successful outcome - * @param msg - * The detailed message + * @return The adapter name + * @see org.openecomp.appc.adapter.iaas.ProviderAdapter#getAdapterName() */ - private void generateEvent(@SuppressWarnings("unused") RequestContext rc, @SuppressWarnings("unused") boolean success, @SuppressWarnings("unused") String msg) { - // indication to the DG to generate the event? + @Override + public String getAdapterName() { + return configuration.getProperty(Constants.PROPERTY_ADAPTER_NAME); } - /** - * 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") - private Context getContext(RequestContext rc, String selfLinkURL, String providerName) { - VMURL vm = VMURL.parseURL(selfLinkURL); - IdentityURL ident = IdentityURL.parseURL(providerName); - String appName = configuration.getProperty(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,DEFAULT_USER, DEFAULT_PASS); - - 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. - */ - if (context.isStale()) { - context.relogin(); - } - 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; - } /** * initialize the provider adapter by building the context cache @@ -1313,57 +271,57 @@ public class ProviderAdapterImpl implements ProviderAdapter { * <p> * For example, the following definitions show how the namespace hierarchy is defined for two providers, with * two tenants on the first provider and a single tenant for the second provider. <pre> - * provider1.type=OpenStackProvider1 - * provider1.name=OpenStackProviderName1 - * provider1.identity=http://192.168.1.2:5000/v2.0 - * provider1.tenant1.name=MY-TENANT-NAME - * provider1.tenant1.userid=userid - * provider1.tenant1.password=userid@123 - * provider1.tenant2.name=MY-TENANT-NAME - * provider1.tenant2.userid=userid - * provider1.tenant2.password=userid@123 - * provider2.type=OpenStackProvider2 - * provider2.name=OpenStackProviderName2 - * provider2.identity=http://192.168.1.2:5000/v2.0 - * provider2.tenant1.name=MY-TENANT-NAME - * provider2.tenant1.userid=userid - * provider2.tenant1.password=userid@123 + * provider1.type=OpenStackProvider + * provider1.name=ILAB + * provider1.identity=http://provider1:5000/v2.0 + * provider1.tenant1.name=CDP-ONAP-APPC + * provider1.tenant1.userid=cdpdev + * provider1.tenant1.password=cdpdev@123 + * provider1.tenant2.name=TEST-TENANT + * provider1.tenant2.userid=testUser + * provider1.tenant2.password=testPassword + * provider2.type=OpenStackProvider + * provider2.name=PDK1 + * provider2.identity=http://provider2:5000/v2.0 + * provider2.tenant1.name=someName + * provider2.tenant1.userid=someUser + * provider2.tenant1.password=somePassword * </pre> * </p> */ providerCache = new HashMap<>(); Properties properties = configuration.getProperties(); - List<Node> providers = StructuredPropertyHelper.getStructuredProperties(properties, PROPERTY_PROVIDER); + List<Node> providers = StructuredPropertyHelper.getStructuredProperties(properties, Property.PROVIDER); for (Node provider : providers) { ProviderCache cache = new ProviderCache(); List<Node> providerNodes = provider.getChildren(); for (Node node : providerNodes) { - if (node.getName().equals(PROPERTY_PROVIDER_TYPE)) { + if (node.getName().equals(Property.PROVIDER_TYPE)) { cache.setProviderType(node.getValue()); - } else if (node.getName().equals(PROPERTY_PROVIDER_IDENTITY)) { + } else if (node.getName().equals(Property.PROVIDER_IDENTITY)) { cache.setIdentityURL(node.getValue()); cache.setProviderName(node.getValue()); - } else if (node.getName().startsWith(PROPERTY_PROVIDER_TENANT)) { + } else if (node.getName().startsWith(Property.PROVIDER_TENANT)) { String tenantName = null; String userId = null; String password = null; for (Node node2 : node.getChildren()) { switch (node2.getName()) { - case PROPERTY_PROVIDER_TENANT_NAME: + case Property.PROVIDER_TENANT_NAME: tenantName = node2.getValue(); break; - case PROPERTY_PROVIDER_TENANT_USERID: + case Property.PROVIDER_TENANT_USERID: userId = node2.getValue(); DEFAULT_USER = node2.getValue(); break; - case PROPERTY_PROVIDER_TENANT_PASSWORD: + case Property.PROVIDER_TENANT_PASSWORD: password = node2.getValue(); DEFAULT_PASS = node2.getValue(); break; } } - + cache.addTenant(null, tenantName, userId, password); } } @@ -1383,1341 +341,4 @@ public class ProviderAdapterImpl implements ProviderAdapter { } } - /** - * This method is called to rebuild the provided server. - * <p> - * If the server was booted from a volume, then the request is failed immediately and no action is taken. Rebuilding - * a VM from a bootable volume, where the bootable volume itself is not rebuilt, serves no purpose. - * </p> - * - * @param rc - * The request context that manages the state and recovery of the request for the life of its processing. - * @param server - * @throws ZoneException - * @throws RequestFailedException - */ - @SuppressWarnings("nls") - private void rebuildServer(RequestContext rc, Server server) throws ZoneException, RequestFailedException { - - ServerBootSource builtFrom = server.getBootSource(); - String msg; - - // Throw exception for non image/snap boot source - if (ServerBootSource.VOLUME.equals(builtFrom)) { - msg = String.format("Rebuilding is currently not supported for servers built from bootable volumes [%s]", - server.getId()); - generateEvent(rc, false, msg); - logger.error(msg); - throw new RequestFailedException("Rebuild Server", msg, HttpStatus.FORBIDDEN_403, server); - } - /* - * Pending is a bit of a special case. If we find the server is in a pending state, then the provider is in the - * process of changing state of the server. So, lets try to wait a little bit and see if the state settles down - * to one we can deal with. If not, then we have to fail the request. - */ - Context context = server.getContext(); - Provider provider = context.getProvider(); - ComputeService service = context.getComputeService(); - if (server.getStatus().equals(Status.PENDING)) { - waitForStateChange(rc, server, Status.READY, Status.RUNNING, Status.ERROR, Status.SUSPENDED, Status.PAUSED); - } - - /* - * Get the image to use. This is determined by the presence or absence of snapshot images. If any snapshots - * exist, then the latest snapshot is used, otherwise the image used to construct the VM is used. - */ - List<Image> snapshots = server.getSnapshots(); - String imageToUse; - if (snapshots != null && !snapshots.isEmpty()) { - imageToUse = snapshots.get(0).getId(); - } else { - imageToUse = server.getImage(); - ImageService imageService = server.getContext().getImageService(); - try { - while (rc.attempt()) { - try { - /* - * We are just trying to make sure that the image exists. We arent interested in the details at - * this point. - */ - imageService.getImage(imageToUse); - break; - } catch (ContextConnectionException e) { - msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), - imageService.getURL(), context.getTenant().getName(), context.getTenant().getId(), - e.getMessage(), Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()), - Integer.toString(rc.getRetryLimit())); - logger.error(msg, e); - rc.delay(); - } - } - } catch (ZoneException e) { - msg = EELFResourceManager.format(Msg.IMAGE_NOT_FOUND, imageToUse, "rebuild"); - generateEvent(rc, false, msg); - logger.error(msg); - throw new RequestFailedException("Rebuild Server", msg, HttpStatus.METHOD_NOT_ALLOWED_405, server); - } - } - if (rc.isFailed()) { - msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL()); - logger.error(msg); - throw new RequestFailedException("Rebuild Server", msg, HttpStatus.BAD_GATEWAY_502, server); - } - rc.reset(); - - /* - * We determine what to do based on the current state of the server - */ - switch (server.getStatus()) { - case DELETED: - // Nothing to do, the server is gone - msg = EELFResourceManager.format(Msg.SERVER_DELETED, server.getName(), server.getId(), - server.getTenantId(), "rebuilt"); - generateEvent(rc, false, msg); - logger.error(msg); - throw new RequestFailedException("Rebuild Server", msg, HttpStatus.METHOD_NOT_ALLOWED_405, server); - - case RUNNING: - // Attempt to stop the server, then rebuild it - stopServer(rc, server); - rebuildServer(rc, server, imageToUse); - startServer(rc, server); - generateEvent(rc, true, OUTCOME_SUCCESS); - break; - - case ERROR: - msg = EELFResourceManager.format(Msg.SERVER_ERROR_STATE, server.getName(), server.getId(), - server.getTenantId(), "rebuild"); - generateEvent(rc, false, msg); - logger.error(msg); - throw new RequestFailedException("Rebuild Server", msg, HttpStatus.METHOD_NOT_ALLOWED_405, server); - - case READY: - // Attempt to rebuild the server - rebuildServer(rc, server, imageToUse); - startServer(rc, server); - generateEvent(rc, true, OUTCOME_SUCCESS); - break; - - case PAUSED: - // if paused, un-pause it, stop it, and rebuild it - unpauseServer(rc, server); - stopServer(rc, server); - rebuildServer(rc, server, imageToUse); - startServer(rc, server); - generateEvent(rc, true, OUTCOME_SUCCESS); - break; - - case SUSPENDED: - // Attempt to resume the suspended server, stop it, and rebuild it - resumeServer(rc, server); - stopServer(rc, server); - rebuildServer(rc, server, imageToUse); - startServer(rc, server); - generateEvent(rc, true, OUTCOME_SUCCESS); - break; - - default: - // Hmmm, unknown status, should never occur - msg = EELFResourceManager.format(Msg.UNKNOWN_SERVER_STATE, server.getName(), server.getId(), - server.getTenantId(), server.getStatus().name()); - generateEvent(rc, false, msg); - logger.error(msg); - throw new RequestFailedException("Rebuild Server", msg, HttpStatus.METHOD_NOT_ALLOWED_405, server); - } - } - - /** - * This method handles the case of restarting a server once we have found the server and have obtained the abstract - * representation of the server via the context (i.e., the "Server" object from the CDP-Zones abstraction). - * - * @param rc - * The request context that manages the state and recovery of the request for the life of its processing. - * @param server - * The server object representing the server we want to operate on - * @throws ZoneException - */ - @SuppressWarnings("nls") - private void restartServer(RequestContext rc, Server server) throws ZoneException, RequestFailedException { - /* - * Pending is a bit of a special case. If we find the server is in a pending state, then the provider is in the - * process of changing state of the server. So, lets try to wait a little bit and see if the state settles down - * to one we can deal with. If not, then we have to fail the request. - */ - String msg; - if (server.getStatus().equals(Status.PENDING)) { - waitForStateChange(rc, server, Status.READY, Status.RUNNING, Status.ERROR, Status.SUSPENDED, Status.PAUSED); - } - - /* - * We determine what to do based on the current state of the server - */ - switch (server.getStatus()) { - case DELETED: - // Nothing to do, the server is gone - msg = EELFResourceManager.format(Msg.SERVER_DELETED, server.getName(), server.getId(), - server.getTenantId(), "restarted"); - generateEvent(rc, false, msg); - logger.error(msg); - break; - - case RUNNING: - // Attempt to stop and start the server - stopServer(rc, server); - startServer(rc, server); - generateEvent(rc, true, OUTCOME_SUCCESS); - break; - - case ERROR: - msg = EELFResourceManager.format(Msg.SERVER_ERROR_STATE, server.getName(), server.getId(), - server.getTenantId(), "rebuild"); - generateEvent(rc, false, msg); - logger.error(msg); - throw new RequestFailedException("Rebuild Server", msg, HttpStatus.METHOD_NOT_ALLOWED_405, server); - - case READY: - // Attempt to start the server - startServer(rc, server); - generateEvent(rc, true, OUTCOME_SUCCESS); - break; - - case PAUSED: - // if paused, un-pause it - unpauseServer(rc, server); - generateEvent(rc, true, OUTCOME_SUCCESS); - break; - - case SUSPENDED: - // Attempt to resume the suspended server - resumeServer(rc, server); - generateEvent(rc, true, OUTCOME_SUCCESS); - break; - - default: - // Hmmm, unknown status, should never occur - msg = EELFResourceManager.format(Msg.UNKNOWN_SERVER_STATE, server.getName(), server.getId(), - server.getTenantId(), server.getStatus().name()); - generateEvent(rc, false, msg); - logger.error(msg); - break; - } - - } - - /** - * Resume a suspended server and wait for it to enter a running state - * - * @param rc - * The request context that manages the state and recovery of the request for the life of its processing. - * @param server - * The server to be resumed - * @throws ZoneException - * @throws RequestFailedException - */ - @SuppressWarnings("nls") - private void resumeServer(RequestContext rc, Server server) throws ZoneException, RequestFailedException { - logger.debug(Msg.RESUME_SERVER, server.getId()); - - Context context = server.getContext(); - String msg; - Provider provider = context.getProvider(); - ComputeService service = context.getComputeService(); - while (rc.attempt()) { - try { - server.resume(); - break; - } catch (ContextConnectionException e) { - msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(), - context.getTenant().getName(), context.getTenant().getId(), e.getMessage(), - Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()), - Integer.toString(rc.getRetryLimit())); - logger.error(msg, e); - rc.delay(); - } - } - if (rc.isFailed()) { - msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL()); - logger.error(msg); - throw new RequestFailedException("Resume Server", msg, HttpStatus.BAD_GATEWAY_502, server); - } - rc.reset(); - waitForStateChange(rc, server, Status.RUNNING); - } - - /** - * Start the server and wait for it to enter a running state - * - * @param rc - * The request context that manages the state and recovery of the request for the life of its processing. - * @param server - * The server to be started - * @throws ZoneException - * @throws RequestFailedException - */ - @SuppressWarnings("nls") - private void startServer(RequestContext rc, Server server) throws ZoneException, RequestFailedException { - logger.debug(Msg.START_SERVER, server.getId()); - String msg; - Context context = server.getContext(); - Provider provider = context.getProvider(); - ComputeService service = context.getComputeService(); - while (rc.attempt()) { - try { - server.start(); - break; - } catch (ContextConnectionException e) { - msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(), - context.getTenant().getName(), context.getTenant().getId(), e.getMessage(), - Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()), - Integer.toString(rc.getRetryLimit())); - logger.error(msg, e); - rc.delay(); - } - } - if (rc.isFailed()) { - msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL()); - logger.error(msg); - throw new RequestFailedException("Start Server", msg, HttpStatus.BAD_GATEWAY_502, server); - } - rc.reset(); - waitForStateChange(rc, server, Status.RUNNING); - } - - /** - * Stop the specified server and wait for it to stop - * - * @param rc - * The request context that manages the state and recovery of the request for the life of its processing. - * @param server - * The server to be stopped - * @throws ZoneException - * @throws RequestFailedException - */ - @SuppressWarnings("nls") - private void stopServer(RequestContext rc, Server server) throws ZoneException, RequestFailedException { - logger.debug(Msg.STOP_SERVER, server.getId()); - - String msg; - Context context = server.getContext(); - Provider provider = context.getProvider(); - ComputeService service = context.getComputeService(); - while (rc.attempt()) { - try { - server.stop(); - break; - } catch (ContextConnectionException e) { - msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(), - context.getTenant().getName(), context.getTenant().getId(), e.getMessage(), - Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()), - Integer.toString(rc.getRetryLimit())); - logger.error(msg, e); - rc.delay(); - } - } - if (rc.isFailed()) { - msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL()); - logger.error(msg); - throw new RequestFailedException("Stop Server", msg, HttpStatus.BAD_GATEWAY_502, server); - } - rc.reset(); - waitForStateChange(rc, server, Status.READY, Status.ERROR); - } - - /** - * Un-Pause a paused server and wait for it to enter a running state - * - * @param rc - * The request context that manages the state and recovery of the request for the life of its processing. - * @param server - * The server to be un-paused - * @throws ZoneException - * @throws RequestFailedException - */ - @SuppressWarnings("nls") - private void unpauseServer(RequestContext rc, Server server) throws ZoneException, RequestFailedException { - logger.debug(Msg.UNPAUSE_SERVER, server.getId()); - - String msg; - Context context = server.getContext(); - Provider provider = context.getProvider(); - ComputeService service = context.getComputeService(); - while (rc.attempt()) { - try { - server.unpause(); - break; - } catch (ContextConnectionException e) { - msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(), - context.getTenant().getName(), context.getTenant().getId(), e.getMessage(), - Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()), - Integer.toString(rc.getRetryLimit())); - logger.error(msg, e); - rc.delay(); - } - } - if (rc.isFailed()) { - msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL()); - logger.error(msg); - throw new RequestFailedException("Unpause Server", msg, HttpStatus.BAD_GATEWAY_502, server); - } - rc.reset(); - waitForStateChange(rc, server, Status.RUNNING, Status.READY); - } - - /** - * Enter a pool-wait loop checking the server state to see if it has entered one of the desired states or not. - * <p> - * This method checks the state of the server periodically for one of the desired states. When the server enters one - * of the desired states, the method returns a successful indication (true). If the server never enters one of the - * desired states within the allocated timeout period, then the method returns a failed response (false). No - * exceptions are thrown from this method. - * </p> - * - * @param rc - * The request context that manages the state and recovery of the request for the life of its processing. - * @param server - * The server to wait on - * @param desiredStates - * A variable list of desired states, any one of which is allowed. - * @throws RequestFailedException - * If the request times out or fails for some reason - */ - @SuppressWarnings("nls") - private void waitForStateChange(RequestContext rc, Server server, Server.Status... desiredStates) - throws RequestFailedException { - int pollInterval = configuration.getIntegerProperty(Constants.PROPERTY_OPENSTACK_POLL_INTERVAL); - int timeout = configuration.getIntegerProperty(Constants.PROPERTY_SERVER_STATE_CHANGE_TIMEOUT); - Context context = server.getContext(); - Provider provider = context.getProvider(); - ComputeService service = context.getComputeService(); - String msg; - - long endTime = System.currentTimeMillis() + (timeout * 1000); // - - while (rc.attempt()) { - try { - try { - server.waitForStateChange(pollInterval, timeout, desiredStates); - break; - } catch (TimeoutException e) { - @SuppressWarnings("MismatchedQueryAndUpdateOfCollection") - List<String> list = new ArrayList<>(); - for (Server.Status desiredState : desiredStates) { - list.add(desiredState.name()); - } - msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(), - context.getTenant().getName(), context.getTenant().getId(), e.getMessage(), - Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()), - Integer.toString(rc.getRetryLimit())); - logger.error(msg, e); - rc.delay(); - } - } catch (ZoneException e) { - List<String> list = new ArrayList<>(); - for (Server.Status desiredState : desiredStates) { - list.add(desiredState.name()); - } - String reason = EELFResourceManager.format(Msg.STATE_CHANGE_EXCEPTION, e.getClass().getSimpleName(), - "server", server.getName(), server.getId(), StringHelper.asList(list), server.getStatus().name(), - e.getMessage()); - logger.error(reason); - logger.error(EELFResourceManager.format(e)); - - // Instead of failing we are going to wait and try again. - // Timeout is reduced by delay time - logger.info(String.format("Retrying in %ds", rc.getRetryDelay())); - rc.delay(); - timeout = (int) (endTime - System.currentTimeMillis()) / 1000; - // throw new RequestFailedException(e, operation, reason, - // HttpStatus.BAD_GATEWAY_502, server); - } - } - - if (rc.isFailed()) { - msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL()); - logger.error(msg); - throw new RequestFailedException("Waiting for State Change", msg, HttpStatus.BAD_GATEWAY_502, server); - } - rc.reset(); - } - - /** - * Enter a pool-wait loop checking the server state to see if it has entered one of the desired states or not. - * <p> - * This method checks the state of the server periodically for one of the desired states. When the server enters one - * of the desired states, the method returns a successful indication (true). If the server never enters one of the - * desired states within the allocated timeout period, then the method returns a failed response (false). No - * exceptions are thrown from this method. - * </p> - * - * @param rc - * The request context that manages the state and recovery of the request for the life of its processing. - * @param image - * The server to wait on - * @param desiredStates - * A variable list of desired states, any one of which is allowed. - * @throws RequestFailedException - * If the request times out or fails for some reason - * @throws NotLoggedInException - */ - @SuppressWarnings("nls") - private void waitForStateChange(RequestContext rc, Image image, Image.Status... desiredStates) - throws RequestFailedException, NotLoggedInException { - int pollInterval = configuration.getIntegerProperty(Constants.PROPERTY_OPENSTACK_POLL_INTERVAL); - int timeout = configuration.getIntegerProperty(Constants.PROPERTY_SERVER_STATE_CHANGE_TIMEOUT); - Context context = image.getContext(); - Provider provider = context.getProvider(); - ImageService service = context.getImageService(); - String msg; - - long endTime = System.currentTimeMillis() + (timeout * 1000); // - - while (rc.attempt()) { - try { - try { - image.waitForStateChange(pollInterval, timeout, desiredStates); - break; - } catch (TimeoutException e) { - @SuppressWarnings("MismatchedQueryAndUpdateOfCollection") - List<String> list = new ArrayList<>(); - for (Image.Status desiredState : desiredStates) { - list.add(desiredState.name()); - } - msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(), - context.getTenant().getName(), context.getTenant().getId(), e.getMessage(), - Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()), - Integer.toString(rc.getRetryLimit())); - logger.error(msg, e); - rc.delay(); - } - } catch (ZoneException e) { - List<String> list = new ArrayList<>(); - for (Image.Status desiredState : desiredStates) { - list.add(desiredState.name()); - } - String reason = EELFResourceManager.format(Msg.STATE_CHANGE_EXCEPTION, e.getClass().getSimpleName(), - "server", image.getName(), image.getId(), StringHelper.asList(list), image.getStatus().name(), - e.getMessage()); - logger.error(reason); - logger.error(EELFResourceManager.format(e)); - - // Instead of failing we are going to wait and try again. - // Timeout is reduced by delay time - logger.info(String.format("Retrying in %ds", rc.getRetryDelay())); - rc.delay(); - timeout = (int) (endTime - System.currentTimeMillis()) / 1000; - // throw new RequestFailedException(e, operation, reason, - // HttpStatus.BAD_GATEWAY_502, server); - } - } - - if (rc.isFailed()) { - msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL()); - logger.error(msg); - throw new RequestFailedException("Waiting for State Change", msg, HttpStatus.BAD_GATEWAY_502, new Server()); - } - rc.reset(); - } - - /** - * Rebuild the indicated server with the indicated image. This method assumes the server has been determined to be - * in the correct state to do the rebuild. - * - * @param rc - * The request context that manages the state and recovery of the request for the life of its processing. - * @param server - * the server to be rebuilt - * @param image - * The image to be used (or snapshot) - * @throws RequestFailedException - * if the server does not change state in the allotted time - */ - @SuppressWarnings("nls") - private void rebuildServer(RequestContext rc, Server server, String image) throws RequestFailedException { - String msg; - Context context = server.getContext(); - Provider provider = context.getProvider(); - ComputeService service = context.getComputeService(); - - try { - while (rc.attempt()) { - try { - server.rebuild(image); - break; - } catch (ContextConnectionException e) { - msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(), - context.getTenant().getName(), context.getTenant().getId(), e.getMessage(), - Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()), - Integer.toString(rc.getRetryLimit())); - logger.error(msg, e); - rc.delay(); - } - } - - /* - * We need to provide some time for OpenStack to start processing the request. - */ - try { - Thread.sleep(10L * 1000L); - } catch (InterruptedException e) { - logger.trace("Sleep threw interrupted exception, should never occur"); - } - } catch (ZoneException e) { - msg = - EELFResourceManager.format(Msg.REBUILD_SERVER_FAILED, server.getName(), server.getId(), e.getMessage()); - logger.error(msg); - throw new RequestFailedException("Rebuild Server", msg, HttpStatus.BAD_GATEWAY_502, server); - } - - /* - * Once we have started the process, now we wait for the final state of stopped. This should be the final state - * (since we started the rebuild with the server stopped). - */ - waitForStateChange(rc, server, Status.READY); - - if (rc.isFailed()) { - msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL()); - logger.error(msg); - throw new RequestFailedException("Rebuild Server", msg, HttpStatus.BAD_GATEWAY_502, server); - } - rc.reset(); - } - - /** - * Looks up the indicated server using the provided context and returns the server to the caller - * - * @param rc - * The request context - * @param context - * The provider context - * @param id - * The id of the server - * @return The server, or null if there is a problem - * @throws ZoneException - * If the server cannot be found - * @throws RequestFailedException - * If the server cannot be found because we cant connect to the provider - */ - @SuppressWarnings("nls") - private Server lookupServer(RequestContext rc, Context context, String id) - throws ZoneException, RequestFailedException { - ComputeService service = context.getComputeService(); - Server server = null; - String msg; - Provider provider = context.getProvider(); - - while (rc.attempt()) { - try { - server = service.getServer(id); - break; - } catch (ContextConnectionException e) { - msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(), - context.getTenant().getName(), context.getTenant().getId(), e.getMessage(), - Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()), - Integer.toString(rc.getRetryLimit())); - logger.error(msg, e); - rc.delay(); - } - } - if (rc.isFailed()) { - msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL()); - logger.error(msg); - doFailure(rc, HttpStatus.BAD_GATEWAY_502, msg); - throw new RequestFailedException("Lookup Server", msg, HttpStatus.BAD_GATEWAY_502, server); - } - return server; - } - - private String getConnectionExceptionMessage(RequestContext rc, Context ctx, ContextConnectionException e) - throws ZoneException { - return EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, ctx.getProvider().getName(), - ctx.getComputeService().getURL(), ctx.getTenant().getName(), ctx.getTenant().getId(), e.getMessage(), - Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()), - Integer.toString(rc.getRetryLimit())); - } - - private ProviderCache createProviderCache(VMURL vm, IdentityURL ident) { - if (vm != null && ident != null) { - ProviderCache cache = new ProviderCache(); - - cache.setIdentityURL(ident.toString()); - cache.setProviderName(ident.toString()); - // cache.setProviderType("OpenStack"); - - TenantCache tenant = cache.addTenant(vm.getTenantId(),null, DEFAULT_USER, DEFAULT_PASS); - - // Make sure we could initialize the the cache otherwise return null - if (tenant != null && tenant.isInitialized()) { - return cache; - } - } - return null; - } - - /** - * This method is used to delete an existing virtual machine given the fully qualified URL of the machine. - * <p> - * The fully qualified URL contains enough information to locate the appropriate server. The URL is of the form - * <pre> - * [scheme]://[host[:port]] / [path] / [tenant_id] / servers / [vm_id] - * </pre> Where the various parts of the URL can be parsed and extracted and used to locate the appropriate service - * in the provider service catalog. This then allows us to open a context using the CDP abstraction, obtain the - * server by its UUID, and then perform the restart. - * </p> - * - * @throws UnknownProviderException - * If the provider cannot be found - * @throws IllegalArgumentException - * if the expected argument(s) are not defined or are invalid - * @see org.openecomp.appc.adapter.iaas.ProviderAdapter#terminateServer(java.util.Map, org.openecomp.sdnc.sli.SvcLogicContext) - */ - @SuppressWarnings("nls") - @Override - public Server terminateServer(Map<String, String> params, SvcLogicContext ctx) - throws UnknownProviderException, IllegalArgumentException { - Server server = null; - RequestContext rc = new RequestContext(ctx); - rc.isAlive(); - MDC.put(MDC_ADAPTER, ADAPTER_NAME); - MDC.put(MDC_SERVICE, TERMINATE_SERVICE); - MDC.put(MDC_SERVICE_NAME, "App-C IaaS Adapter:Terminate"); - String appName = configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME); - if (logger.isDebugEnabled()) { - logger.debug("Inside org.openecomp.appc.adapter.iaas.impl.ProviderAdapter.terminateServer"); - } - - try { - validateParametersExist(rc, params, ProviderAdapter.PROPERTY_INSTANCE_URL, - ProviderAdapter.PROPERTY_PROVIDER_NAME); - debugParameters(params); - debugContext(ctx); - String vm_url = params.get(ProviderAdapter.PROPERTY_INSTANCE_URL); - ctx.setAttribute("TERMINATE_STATUS", "SUCCESS"); - - VMURL vm = VMURL.parseURL(vm_url); - if (validateVM(rc, appName, vm_url, vm)) return null; - - IdentityURL ident = IdentityURL.parseURL(params.get(ProviderAdapter.PROPERTY_IDENTITY_URL)); - String identStr = (ident == null) ? null : ident.toString(); - - Context context = null; - try { - context = getContext(rc, vm_url, identStr); - if (context != null) { - server = lookupServer(rc, context, vm.getServerId()); - logger.debug(Msg.SERVER_FOUND, vm_url, context.getTenantName(), server.getStatus().toString()); - logger.info(EELFResourceManager.format(Msg.TERMINATING_SERVER, server.getName())); - terminateServer(rc, server); - logger.info(EELFResourceManager.format(Msg.TERMINATE_SERVER, server.getName())); - context.close(); - doSuccess(rc); - }else{ - ctx.setAttribute("TERMINATE_STATUS", "SERVER_NOT_FOUND"); - } - } catch (ResourceNotFoundException e) { - String msg = EELFResourceManager.format(Msg.SERVER_NOT_FOUND, e, vm_url); - logger.error(msg); - doFailure(rc, HttpStatus.NOT_FOUND_404, msg); - ctx.setAttribute("TERMINATE_STATUS", "SERVER_NOT_FOUND"); - } catch (Throwable t) { - String msg = EELFResourceManager.format(Msg.SERVER_OPERATION_EXCEPTION, t, t.getClass().getSimpleName(), - RESTART_SERVICE, vm_url, context == null ? "Unknown" : context.getTenantName()); - logger.error(msg, t); - doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg); - } - } catch (RequestFailedException e) { - logger.error(EELFResourceManager.format(Msg.TERMINATE_SERVER_FAILED, appName, "n/a", "n/a", e.getMessage())); - doFailure(rc, e.getStatus(), e.getMessage()); - ctx.setAttribute("TERMINATE_STATUS", "ERROR"); - } - - return server; - } - - /** - * This method handles the case of restarting a server once we have found the server and have obtained the abstract - * representation of the server via the context (i.e., the "Server" object from the CDP-Zones abstraction). - * - * @param rc - * The request context that manages the state and recovery of the request for the life of its processing. - * @param server - * The server object representing the server we want to operate on - * @throws ZoneException - */ - @SuppressWarnings("nls") - private void terminateServer(RequestContext rc, Server server) throws ZoneException, RequestFailedException { - /* - * Pending is a bit of a special case. If we find the server is in a pending state, then the provider is in the - * process of changing state of the server. So, lets try to wait a little bit and see if the state settles down - * to one we can deal with. If not, then we have to fail the request. - */ - String msg; - if (server.getStatus().equals(Status.PENDING)) { - waitForStateChange(rc, server, Status.READY, Status.RUNNING, Status.ERROR, Status.SUSPENDED, Status.PAUSED); - } - - /* - * We determine what to do based on the current state of the server - */ - switch (server.getStatus()) { - case DELETED: - // Nothing to do, the server is gone - msg = EELFResourceManager.format(Msg.SERVER_DELETED, server.getName(), server.getId(), - server.getTenantId(), "restarted"); - generateEvent(rc, false, msg); - logger.error(msg); - break; - - case RUNNING: - // Attempt to stop and start the server - logger.info("stopping SERVER"); - stopServer(rc, server); - deleteServer(rc, server); - logger.info("after delete SERVER"); - generateEvent(rc, true, OUTCOME_SUCCESS); - break; - - case ERROR: - - case READY: - - case PAUSED: - - case SUSPENDED: - // Attempt to delete the suspended server - deleteServer(rc, server); - generateEvent(rc, true, OUTCOME_SUCCESS); - break; - - default: - // Hmmm, unknown status, should never occur - msg = EELFResourceManager.format(Msg.UNKNOWN_SERVER_STATE, server.getName(), server.getId(), - server.getTenantId(), server.getStatus().name()); - generateEvent(rc, false, msg); - logger.error(msg); - break; - } - - } - - /** - * Start the server and wait for it to enter a running state - * - * @param rc - * The request context that manages the state and recovery of the request for the life of its processing. - * @param server - * The server to be started - * @throws ZoneException - * @throws RequestFailedException - */ - @SuppressWarnings("nls") - private void deleteServer(RequestContext rc, Server server) throws ZoneException, RequestFailedException { - String msg; - Context context = server.getContext(); - Provider provider = context.getProvider(); - ComputeService service = context.getComputeService(); - while (rc.attempt()) { - try { - logger.info("deleting SERVER"); - server.delete(); - break; - } catch (ContextConnectionException e) { - msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(), - context.getTenant().getName(), context.getTenant().getId(), e.getMessage(), - Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()), - Integer.toString(rc.getRetryLimit())); - logger.error(msg, e); - rc.delay(); - } - } - if (rc.isFailed()) { - msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL()); - logger.error(msg); - throw new RequestFailedException("Delete Server", msg, HttpStatus.BAD_GATEWAY_502, server); - } - rc.reset(); - } - - private boolean hasImageAccess(@SuppressWarnings("unused") RequestContext rc, Context context) { - logger.info("Checking permissions for image service."); - try { - ImageService service = context.getImageService(); - service.getImageByName("CHECK_IMAGE_ACCESS"); - logger.info("Image service is accessible."); - return true; - } catch (ZoneException e) { - logger.warn("Image service could not be accessed. Some operations may fail.", e); - return false; - } - } - - @SuppressWarnings("nls") - @Override - public Stack terminateStack(Map<String, String> params, SvcLogicContext ctx) throws IllegalArgumentException, APPCException { - Stack stack = null; - RequestContext rc = new RequestContext(ctx); - rc.isAlive(); - - ctx.setAttribute("TERMINATE_STATUS", "STACK_NOT_FOUND"); - String appName = configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME); - - try { - - logAndValidate(params, ctx, rc, TERMINATE_STACK, "Terminate Stack", - ProviderAdapter.PROPERTY_INSTANCE_URL, - ProviderAdapter.PROPERTY_PROVIDER_NAME, - ProviderAdapter.PROPERTY_STACK_ID); - - String stackId = params.get(ProviderAdapter.PROPERTY_STACK_ID); - String vm_url = params.get(ProviderAdapter.PROPERTY_INSTANCE_URL); - - Context context = resolveContext(rc, params, appName, vm_url); - - try { - if (context != null) { - stack = lookupStack(rc, context, stackId); - logger.debug(Msg.STACK_FOUND, vm_url, context.getTenantName(), stack.getStatus().toString()); - logger.info(EELFResourceManager.format(Msg.TERMINATING_STACK, stack.getName())); - deleteStack(rc, stack); - logger.info(EELFResourceManager.format(Msg.TERMINATE_STACK, stack.getName())); - context.close(); - doSuccess(rc); - }else{ - ctx.setAttribute("TERMINATE_STATUS", "SERVER_NOT_FOUND"); - } - } catch (ResourceNotFoundException e) { - String msg = EELFResourceManager.format(Msg.STACK_NOT_FOUND, e, vm_url); - logger.error(msg); - doFailure(rc, HttpStatus.NOT_FOUND_404, msg); - } catch (Throwable t) { - String msg = EELFResourceManager.format(Msg.STACK_OPERATION_EXCEPTION, t, t.getClass().getSimpleName(), - TERMINATE_STACK, vm_url, context.getTenantName()); - logger.error(msg, t); - doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg); - } - } catch (RequestFailedException e) { - logger.error(EELFResourceManager.format(Msg.TERMINATE_STACK_FAILED, appName, "n/a", "n/a")); - doFailure(rc, e.getStatus(), e.getMessage()); - } - return stack; - } - - @Override - public Stack snapshotStack(Map<String, String> params, SvcLogicContext ctx) throws IllegalArgumentException, APPCException { - Stack stack = null; - RequestContext rc = new RequestContext(ctx); - rc.isAlive(); - - ctx.setAttribute("SNAPSHOT_STATUS", "STACK_NOT_FOUND"); - String appName = configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME); - - String vm_url = null; - Context context = null; - try { - - logAndValidate(params, ctx, rc, SNAPSHOT_STACK, "Snapshot Stack", - ProviderAdapter.PROPERTY_INSTANCE_URL, - ProviderAdapter.PROPERTY_PROVIDER_NAME, - ProviderAdapter.PROPERTY_STACK_ID); - - String stackId = params.get(ProviderAdapter.PROPERTY_STACK_ID); - vm_url = params.get(ProviderAdapter.PROPERTY_INSTANCE_URL); - - context = resolveContext(rc, params, appName, vm_url); - - if (context != null) { - stack = lookupStack(rc, context, stackId); - logger.debug(Msg.STACK_FOUND, vm_url, context.getTenantName(), stack.getStatus().toString()); - logger.info(EELFResourceManager.format(Msg.SNAPSHOTING_STACK, stack.getName())); - - Snapshot snapshot = snapshotStack(rc, stack); - - ctx.setAttribute(ProviderAdapter.DG_OUTPUT_PARAM_NAMESPACE + - ProviderAdapter.PROPERTY_SNAPSHOT_ID, snapshot.getId()); - - logger.info(EELFResourceManager.format(Msg.STACK_SNAPSHOTED, stack.getName(), snapshot.getId())); - context.close(); - doSuccess(rc); - } else { - ctx.setAttribute(Constants.DG_ATTRIBUTE_STATUS, "failure"); - } - - } catch (ResourceNotFoundException e) { - String msg = EELFResourceManager.format(Msg.STACK_NOT_FOUND, e, vm_url); - logger.error(msg); - doFailure(rc, HttpStatus.NOT_FOUND_404, msg, e); - } catch (RequestFailedException e) { - logger.error(EELFResourceManager.format(Msg.MISSING_PARAMETER_IN_REQUEST, e.getReason(), "snapshotStack")); - doFailure(rc, e.getStatus(), e.getMessage(), e); - } catch (Throwable t) { - String msg = EELFResourceManager.format(Msg.STACK_OPERATION_EXCEPTION, t, t.getClass().getSimpleName(), - "snapshotStack", vm_url, null == context ? "n/a" : context.getTenantName()); - logger.error(msg, t); - doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg, t); - } - return stack; - } - - @Override - public Stack restoreStack(Map<String, String> params, SvcLogicContext ctx) throws IllegalArgumentException, APPCException { - Stack stack = null; - RequestContext rc = new RequestContext(ctx); - rc.isAlive(); - - ctx.setAttribute("SNAPSHOT_STATUS", "STACK_NOT_FOUND"); - String appName = configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME); - - String vm_url = null; - Context context = null; - - try { - - logAndValidate(params, ctx, rc, SNAPSHOT_STACK, "Snapshot Stack", - ProviderAdapter.PROPERTY_INSTANCE_URL, - ProviderAdapter.PROPERTY_PROVIDER_NAME, - ProviderAdapter.PROPERTY_STACK_ID, - ProviderAdapter.PROPERTY_INPUT_SNAPSHOT_ID); - - String stackId = params.get(ProviderAdapter.PROPERTY_STACK_ID); - vm_url = params.get(ProviderAdapter.PROPERTY_INSTANCE_URL); - - String snapshotId = params.get(ProviderAdapter.PROPERTY_INPUT_SNAPSHOT_ID); - - context = resolveContext(rc, params, appName, vm_url); - - if (context != null) { - stack = lookupStack(rc, context, stackId); - logger.debug(Msg.STACK_FOUND, vm_url, context.getTenantName(), stack.getStatus().toString()); - logger.info(EELFResourceManager.format(Msg.RESTORING_STACK, stack.getName(), snapshotId)); - restoreStack(stack, snapshotId); - logger.info(EELFResourceManager.format(Msg.STACK_RESTORED, stack.getName(), snapshotId)); - context.close(); - doSuccess(rc); - } else { - ctx.setAttribute(Constants.DG_ATTRIBUTE_STATUS, "failure"); - } - - } catch (ResourceNotFoundException e) { - String msg = EELFResourceManager.format(Msg.STACK_NOT_FOUND, e, vm_url); - logger.error(msg); - doFailure(rc, HttpStatus.NOT_FOUND_404, msg, e); - } catch (RequestFailedException e) { - logger.error(EELFResourceManager.format(Msg.MISSING_PARAMETER_IN_REQUEST, e.getReason(), "restoreStack")); - doFailure(rc, e.getStatus(), e.getMessage(), e); - } catch (Throwable t) { - String msg = EELFResourceManager.format(Msg.STACK_OPERATION_EXCEPTION, t, t.getClass().getSimpleName(), - "restoreStack", vm_url, null == context ? "n/a" : context.getTenantName()); - logger.error(msg, t); - doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg, t); - } - return stack; - } - - private void logAndValidate(Map<String, String> params, SvcLogicContext ctx, RequestContext rc, String methodName, String serviceName, String ... attributes) - throws RequestFailedException { - MDC.put(MDC_ADAPTER, ADAPTER_NAME); - MDC.put(MDC_SERVICE, SNAPSHOT_STACK); - MDC.put(MDC_SERVICE_NAME, String.format("App-C IaaS Adapter:%s", serviceName)); - if (logger.isDebugEnabled()) { - logger.debug(String.format("Inside org.openecomp.appc.adapter.iaas.impl.ProviderAdapter.%s", methodName)); - } - - validateParametersExist(rc, params, attributes); - - debugParameters(params); - debugContext(ctx); - } - - private Context resolveContext(RequestContext rc, Map<String, String> params, String appName, String vm_url) - throws RequestFailedException { - - VMURL vm = VMURL.parseURL(vm_url); - if (vm == null) { - String msg = EELFResourceManager.format(Msg.INVALID_SELF_LINK_URL, appName, vm_url); - 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, vm_url, identStr); - - } - - private void deleteStack(RequestContext rc, Stack stack) throws ZoneException, RequestFailedException { - SvcLogicContext ctx = rc.getSvcLogicContext(); - Context context = stack.getContext(); - StackService stackService = context.getStackService(); - logger.debug("Deleting Stack: " + "id:{ " + stack.getId() + "}"); - stackService.deleteStack(stack); - - // wait for the stack deletion - boolean success = waitForStackStatus(rc, stack, Stack.Status.DELETED); - if (success) { - ctx.setAttribute("TERMINATE_STATUS", "SUCCESS"); - } else { - ctx.setAttribute("TERMINATE_STATUS", "ERROR"); - throw new RequestFailedException("Delete Stack failure : " + Msg.STACK_OPERATION_EXCEPTION.toString()); - } - } - - private boolean waitForStackStatus(RequestContext rc, Stack stack, Stack.Status expectedStatus) throws ZoneException, RequestFailedException { - SvcLogicContext ctx = rc.getSvcLogicContext(); - Context context = stack.getContext(); - StackService stackService = context.getStackService(); - - int pollInterval = configuration.getIntegerProperty(Constants.PROPERTY_OPENSTACK_POLL_INTERVAL); - int timeout = configuration.getIntegerProperty(Constants.PROPERTY_STACK_STATE_CHANGE_TIMEOUT); - long maxTimeToWait = System.currentTimeMillis() + (long) timeout * 1000; - Stack.Status stackStatus; - while (System.currentTimeMillis() < maxTimeToWait) { - stackStatus = stackService.getStack(stack.getName(), stack.getId()).getStatus(); - logger.debug("Stack status : " + stackStatus.toString()); - if (stackStatus == expectedStatus) { - return true; - } else if (stackStatus == Stack.Status.FAILED) { - return false; - } else { - try { - Thread.sleep(pollInterval * 1000); - } catch (InterruptedException e) { - logger.trace("Sleep threw interrupted exception, should never occur"); - } - } - } - - ctx.setAttribute("TERMINATE_STATUS", "ERROR"); - throw new TimeoutException("Timeout waiting for stack status change"); - - } - - private Snapshot snapshotStack(@SuppressWarnings("unused") RequestContext rc, Stack stack) throws ZoneException, RequestFailedException { - Snapshot snapshot = new Snapshot(); - Context context = stack.getContext(); - - OpenStackContext osContext = (OpenStackContext)context; - - final HeatConnector heatConnector = osContext.getHeatConnector(); - ((OpenStackContext)context).refreshIfStale(heatConnector); - - trackRequest(context); - RequestState.put("SERVICE", "Orchestration"); - RequestState.put("SERVICE_URL", heatConnector.getEndpoint()); - - Heat heat = heatConnector.getClient(); - - SnapshotResource snapshotResource = new SnapshotResource(heat); - - try { - - snapshot = snapshotResource.create(stack.getName(), stack.getId(), new CreateSnapshotParams()).execute(); - - // wait for the stack deletion - StackResource stackResource = new StackResource(heat); - if (!waitForStack(stack, stackResource, "SNAPSHOT_COMPLETE")) { - throw new RequestFailedException("Stack Snapshot failed."); - } - - } catch (OpenStackBaseException e) { - ExceptionMapper.mapException(e); - } - - return snapshot; - } - - private void restoreStack(Stack stack, String snapshotId) throws ZoneException, RequestFailedException { - Context context = stack.getContext(); - - OpenStackContext osContext = (OpenStackContext)context; - - final HeatConnector heatConnector = osContext.getHeatConnector(); - ((OpenStackContext)context).refreshIfStale(heatConnector); - - trackRequest(context); - RequestState.put("SERVICE", "Orchestration"); - RequestState.put("SERVICE_URL", heatConnector.getEndpoint()); - - Heat heat = heatConnector.getClient(); - - SnapshotResource snapshotResource = new SnapshotResource(heat); - - try { - - snapshotResource.restore(stack.getName(), stack.getId(), snapshotId).execute(); - - // wait for the snapshot restore - StackResource stackResource = new StackResource(heat); - if (!waitForStack(stack, stackResource, "RESTORE_COMPLETE")) { - throw new RequestFailedException("Snapshot restore failed."); - } - - } catch (OpenStackBaseException e) { - ExceptionMapper.mapException(e); - } - - } - - private boolean waitForStack(Stack stack, StackResource stackResource, String expectedStatus) - throws OpenStackBaseException, TimeoutException { - int pollInterval = configuration.getIntegerProperty(Constants.PROPERTY_OPENSTACK_POLL_INTERVAL); - int timeout = configuration.getIntegerProperty(Constants.PROPERTY_STACK_STATE_CHANGE_TIMEOUT); - long maxTimeToWait = System.currentTimeMillis() + (long) timeout * 1000; - - while (System.currentTimeMillis() < maxTimeToWait) { - String stackStatus = stackResource.show(stack.getName(), stack.getId()).execute().getStackStatus(); - logger.debug("Stack status : " + stackStatus); - if (stackStatus.toUpperCase().contains("FAILED")) return false; - if(checkStatus(expectedStatus, pollInterval, stackStatus)) return true; - } - throw new TimeoutException("Timeout waiting for stack status change"); - } - - private boolean checkStatus(String expectedStatus, int pollInterval, String actualStatus) { - if (actualStatus.toUpperCase().equals(expectedStatus)) { - return true; - } else { - try { - Thread.sleep(pollInterval * 1000); - } catch (InterruptedException ignored) { - } - } - return false; - } - - private void trackRequest(Context context, AbstractService.State... states) { - RequestState.clear(); - - if (null == states) return; - for (AbstractService.State state : states) { - RequestState.put(state.getName(), state.getValue()); - } - - Thread currentThread = Thread.currentThread(); - StackTraceElement[] stack = currentThread.getStackTrace(); - if (stack != null && stack.length > 0) { - int index = 0; - StackTraceElement element; - for (; index < stack.length; index++) { - element = stack[index]; - if ("trackRequest".equals(element.getMethodName())) { //$NON-NLS-1$ - break; - } - } - index++; - - if (index < stack.length) { - element = stack[index]; - RequestState.put(RequestState.METHOD, element.getMethodName()); - RequestState.put(RequestState.CLASS, element.getClassName()); - RequestState.put(RequestState.LINE_NUMBER, Integer.toString(element.getLineNumber())); - RequestState.put(RequestState.THREAD, currentThread.getName()); - RequestState.put(RequestState.PROVIDER, context.getProvider().getName()); - RequestState.put(RequestState.TENANT, context.getTenantName()); - RequestState.put(RequestState.PRINCIPAL, context.getPrincipal()); - } - } - } - - private Stack lookupStack(RequestContext rc, Context context, String id) - throws ZoneException, RequestFailedException { - StackService stackService = context.getStackService(); - Stack stack = null; - String msg; - Provider provider = context.getProvider(); - while (rc.attempt()) { - try { - List<Stack> stackList = stackService.getStacks(); - for (Stack stackObj : stackList) { - if (stackObj.getId().equals(id)) { - stack = stackObj; - break; - } - } - break; - } catch (ContextConnectionException e) { - msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), stackService.getURL(), - context.getTenant().getName(), context.getTenant().getId(), e.getMessage(), - Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()), - Integer.toString(rc.getRetryLimit())); - logger.error(msg, e); - rc.delay(); - } - - } - if (rc.isFailed()) { - msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), stackService.getURL()); - logger.error(msg); - doFailure(rc, HttpStatus.BAD_GATEWAY_502, msg); - throw new RequestFailedException("Lookup Stack", msg, HttpStatus.BAD_GATEWAY_502, stack); - } - - if (stack == null) { - throw new ResourceNotFoundException("Stack not found with Id : {" + id + "}"); - } - return stack; - } - - @SuppressWarnings("nls") - @Override - public Server lookupServer(Map<String, String> params, SvcLogicContext ctx) throws APPCException { - Server server = null; - RequestContext rc = new RequestContext(ctx); - rc.isAlive(); //should we test the return and fail if false? - MDC.put(MDC_ADAPTER, ADAPTER_NAME); - MDC.put(MDC_SERVICE, LOOKUP_SERVICE); - MDC.put(MDC_SERVICE_NAME, "App-C IaaS Adapter:LookupServer"); - String appName = configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME); - - //for debugging merge into single method? - debugParameters(params); - debugContext(ctx); - - String vm_url = null; - VMURL vm = null; - try { - - //process vm_url - validateParametersExist(rc, params, ProviderAdapter.PROPERTY_INSTANCE_URL, - ProviderAdapter.PROPERTY_PROVIDER_NAME); - vm_url = params.get(ProviderAdapter.PROPERTY_INSTANCE_URL); - vm = VMURL.parseURL(vm_url); - if (validateVM(rc, appName, vm_url, vm)) return null; - - - //use try with resource to ensure context is closed (returned to pool) - try(Context context = resolveContext(rc, params, appName, vm_url)){ - //resloveContext & getContext call doFailure and log errors before returning null - if (context != null){ - server = lookupServer(rc, context, vm.getServerId()); - logger.debug(Msg.SERVER_FOUND, vm_url, context.getTenantName(), server.getStatus().toString()); - ctx.setAttribute("serverFound", "success"); - doSuccess(rc); - } - } catch (ZoneException e) { - //server not found - String msg = EELFResourceManager.format(Msg.SERVER_NOT_FOUND, e, vm_url); - logger.error(msg); - doFailure(rc, HttpStatus.NOT_FOUND_404, msg); - ctx.setAttribute("serverFound", "failure"); - } catch (IOException e) { - //exception closing context - String msg = EELFResourceManager.format(Msg.CLOSE_CONTEXT_FAILED, e, vm_url); - logger.error(msg); - } catch (Throwable t) { - String msg = EELFResourceManager.format(Msg.SERVER_OPERATION_EXCEPTION, t, t.getClass().getSimpleName(), - LOOKUP_SERVICE, vm_url, "Unknown" ); - logger.error(msg, t); - doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg); - } - - } catch (RequestFailedException e) { - // parameters not valid, unable to connect to provider - String msg = EELFResourceManager.format(Msg.SERVER_NOT_FOUND, e, vm_url); - logger.error(msg); - doFailure(rc, HttpStatus.NOT_FOUND_404, msg); - ctx.setAttribute("serverFound", "failure"); - } - return server; - } } diff --git a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/impl/ServiceCatalog.java b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/impl/ServiceCatalog.java index 8ac81b2b9..adf6a4039 100644 --- a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/impl/ServiceCatalog.java +++ b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/impl/ServiceCatalog.java @@ -45,7 +45,6 @@ import com.att.cdp.zones.spi.AbstractService; import com.att.cdp.zones.spi.RequestState; import com.att.cdp.zones.spi.AbstractService.State; -import com.sun.jersey.api.client.ClientHandlerException; import com.woorea.openstack.base.client.OpenStackBaseException; import com.woorea.openstack.base.client.OpenStackClientConnector; import com.woorea.openstack.base.client.OpenStackResponseException; @@ -168,7 +167,7 @@ public class ServiceCatalog { */ private OpenStackSimpleTokenProvider tokenProvider; - public static final String CLIENT_CONNECTOR_CLASS = "com.woorea.openstack.connector.JerseyConnector"; + public static final String CLIENT_CONNECTOR_CLASS = "com.woorea.openstack.connector.JaxRs20Connector"; /** * Create the ServiceCatalog cache and load it from the specified provider diff --git a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/impl/TenantCache.java b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/impl/TenantCache.java index c0c114dc8..07c934004 100644 --- a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/impl/TenantCache.java +++ b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/impl/TenantCache.java @@ -43,8 +43,8 @@ import com.att.cdp.zones.ContextFactory; import com.att.cdp.zones.Provider; import com.att.eelf.configuration.EELFLogger; import com.att.eelf.configuration.EELFManager; - -import com.sun.jersey.api.client.ClientHandlerException; +import com.woorea.openstack.connector.JaxRs20Connector; +//import com.sun.jersey.api.client.ClientHandlerException; import com.woorea.openstack.keystone.model.Access.Service.Endpoint; /** @@ -60,8 +60,8 @@ public class TenantCache implements Allocator<Context>, Destructor<Context> { public static final String POOL_PROVIDER_NAME = "pool.provider.name"; public static final String POOL_TENANT_NAME = "pool.tenant.name"; - public static final String CLIENT_CONNECTOR_CLASS = "com.woorea.openstack.connector.JerseyConnector"; - + //public static final String CLIENT_CONNECTOR_CLASS = "com.woorea.openstack.connector.JerseyConnector"; + public static final String CLIENT_CONNECTOR_CLASS = "com.woorea.openstack.connector.JaxRs20Connector"; /** * The provider we are part of */ @@ -198,15 +198,17 @@ public class TenantCache implements Allocator<Context>, Destructor<Context> { break; } catch (ContextConnectionException e) { attempt++; - logger.error(Msg.CONNECTION_FAILED_RETRY, provider.getProviderName(), url, tenantName, tenantId, e.getMessage(), Integer.toString(delay), Integer.toString(attempt), - Integer.toString(limit)); + if (attempt <= limit) { + logger.error(Msg.CONNECTION_FAILED_RETRY, provider.getProviderName(), url, tenantName, tenantId, e.getMessage(), Integer.toString(delay), Integer.toString(attempt), + Integer.toString(limit)); - try { - Thread.sleep(delay * 1000L); - } catch (InterruptedException ie) { - // ignore + try { + Thread.sleep(delay * 1000L); + } catch (InterruptedException ie) { + // ignore + } } - } catch (ClientHandlerException | ZoneException e) { + } catch ( ZoneException e) { logger.error(e.getMessage()); break; } diff --git a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/api/IProviderOperation.java b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/api/IProviderOperation.java new file mode 100644 index 000000000..0bdc7669f --- /dev/null +++ b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/api/IProviderOperation.java @@ -0,0 +1,61 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.adapter.iaas.provider.operation.api; + +import org.openecomp.appc.adapter.iaas.impl.ProviderCache; +import org.openecomp.appc.exceptions.APPCException; +import com.att.cdp.zones.model.ModelObject; +import org.openecomp.sdnc.sli.SvcLogicContext; + +import java.util.Map; + +/** + * @since September 26, 2016 + */ +public interface IProviderOperation { + + /** + * perform specific provider operation + * @param params + * @param context + * @return Object represents Stack, Server Or Image + */ + ModelObject doOperation(Map<String,String> params, SvcLogicContext context) throws APPCException; + + /** + * sets a cache of providers that are predefined. + * @param providerCache + */ + void setProviderCache(Map<String /* provider name */, ProviderCache> providerCache); + + /** + * should be initialized by user + * @param defaultUser + */ + void setDefaultUser(String defaultUser); + + /** + * should be initialized by user + * @param defaultPass + */ + void setDefaultPass(String defaultPass); +} diff --git a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/api/ProviderOperationFactory.java b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/api/ProviderOperationFactory.java new file mode 100644 index 000000000..dd604a555 --- /dev/null +++ b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/api/ProviderOperationFactory.java @@ -0,0 +1,119 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.adapter.iaas.provider.operation.api; + +import org.openecomp.appc.adapter.iaas.provider.operation.impl.*; +import org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Operation; +import org.openecomp.appc.exceptions.APPCException; + +import java.util.HashMap; +import java.util.Map; + +/** + * Singleton factory of provider operations objects with cache + * @since September 26, 2016 + */ +public class ProviderOperationFactory { + + /** + * holds instance of the class + */ + private static ProviderOperationFactory instance; + + /** + * holds concrete operations objects + */ + private Map<Operation, IProviderOperation> operations; + + /** + * private constructor + */ + private ProviderOperationFactory() { + this.operations = new HashMap<>(); + } + + /** + * @return instance of the factory + */ + public static ProviderOperationFactory getInstance() { + if (instance == null) { + instance = new ProviderOperationFactory(); + } + return instance; + } + + /** + * @param op + * @return concrete operation impl + */ + public IProviderOperation getOperationObject(Operation op) throws APPCException { + + IProviderOperation opObject = operations.get(op); + if (opObject == null) { + switch (op) { + case EVACUATE_SERVICE: + opObject = new EvacuateServer(); + break; + case MIGRATE_SERVICE: + opObject = new MigrateServer(); + break; + case REBUILD_SERVICE: + opObject = new RebuildServer(); + break; + case RESTART_SERVICE: + opObject = new RestartServer(); + break; + case VMSTATUSCHECK_SERVICE: + opObject = new VmStatuschecker(); + break; + case SNAPSHOT_SERVICE: + opObject = new CreateSnapshot(); + break; + case TERMINATE_STACK: + opObject = new TerminateStack(); + break; + case SNAPSHOT_STACK: + opObject = new SnapshotStack(); + break; + case RESTORE_STACK: + opObject = new RestoreStack(); + break; + case START_SERVICE: + opObject = new StartServer(); + break; + case STOP_SERVICE: + opObject = new StopServer(); + break; + case TERMINATE_SERVICE: + opObject = new TerminateServer(); + break; + case LOOKUP_SERVICE: + opObject = new LookupServer(); + break; + default: + throw new APPCException("Unsupported provider operation."); + } + operations.put(op,opObject); + } + return opObject; + } +} diff --git a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/common/constants/Constants.java b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/common/constants/Constants.java new file mode 100644 index 000000000..e3c592c89 --- /dev/null +++ b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/common/constants/Constants.java @@ -0,0 +1,58 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.adapter.iaas.provider.operation.common.constants; + +/** + * @since September 26, 2016 + */ +public class Constants { + + public static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; + + public static final String MDC_SERVICE = "service"; + public static final String MDC_ADAPTER = "adapter"; + + /** + * The constant for a left parenthesis + */ + public static final char LPAREN = '('; + + /** + * The constant for a new line control code + */ + public static final char NL = '\n'; + + /** + * The constant for a single quote + */ + public static final char QUOTE = '\''; + + /** + * The constant for a right parenthesis + */ + public static final char RPAREN = ')'; + + /** + * The constant for a space + */ + public static final char SPACE = ' '; +} diff --git a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/common/constants/Property.java b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/common/constants/Property.java new file mode 100644 index 000000000..702c469cb --- /dev/null +++ b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/common/constants/Property.java @@ -0,0 +1,36 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.adapter.iaas.provider.operation.common.constants; + +/** + * @since September 26, 2016 + */ +public class Property { + + public static final String PROVIDER = "provider"; + public static final String PROVIDER_IDENTITY = "identity"; + public static final String PROVIDER_TENANT = "tenant"; + public static final String PROVIDER_TENANT_NAME = "name"; + public static final String PROVIDER_TENANT_PASSWORD = "password"; + public static final String PROVIDER_TENANT_USERID = "userid"; + public static final String PROVIDER_TYPE = "type"; +} diff --git a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/common/enums/Operation.java b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/common/enums/Operation.java new file mode 100644 index 000000000..768ccc0c0 --- /dev/null +++ b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/common/enums/Operation.java @@ -0,0 +1,93 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.adapter.iaas.provider.operation.common.enums; + +/** + * @since September 26, 2016 + */ +public enum Operation { + EVACUATE_SERVICE { + public String toString(){ + return "evacuateServer"; + } + }, + MIGRATE_SERVICE { + public String toString(){ + return "migrateServer"; + } + }, + REBUILD_SERVICE { + public String toString(){ + return "rebuildServer"; + } + }, + RESTART_SERVICE { + public String toString(){ + return "restartServer"; + } + }, + VMSTATUSCHECK_SERVICE { + public String toString(){ + return "vmStatuschecker"; + } + }, + SNAPSHOT_SERVICE { + public String toString(){ + return "createSnapshot"; + } + }, + TERMINATE_STACK { + public String toString(){ + return "terminateStack"; + } + }, + SNAPSHOT_STACK { + public String toString(){ + return "snapshotStack"; + } + }, + START_SERVICE { + public String toString(){ + return "startServer"; + } + }, + STOP_SERVICE { + public String toString(){ + return "stopServer"; + } + }, + TERMINATE_SERVICE { + public String toString(){ + return "terminateServer"; + } + }, + LOOKUP_SERVICE { + public String toString(){ + return "lookupServer"; + } + }, + RESTORE_STACK{ + public String toString(){ + return "restoreStack"; + } + } +} diff --git a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/common/enums/Outcome.java b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/common/enums/Outcome.java new file mode 100644 index 000000000..017c69879 --- /dev/null +++ b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/common/enums/Outcome.java @@ -0,0 +1,38 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.adapter.iaas.provider.operation.common.enums; + +/** + * @since September 26, 2016 + */ +public enum Outcome { + FAILURE { + public String toString(){ + return "failure"; + } + }, + SUCCESS { + public String toString(){ + return "success"; + } + } +} diff --git a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/CreateSnapshot.java b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/CreateSnapshot.java new file mode 100644 index 000000000..c96dc6e84 --- /dev/null +++ b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/CreateSnapshot.java @@ -0,0 +1,291 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.adapter.iaas.provider.operation.impl; + +import org.openecomp.appc.Constants; +import org.openecomp.appc.adapter.iaas.ProviderAdapter; +import org.openecomp.appc.adapter.iaas.impl.IdentityURL; +import org.openecomp.appc.adapter.iaas.impl.RequestContext; +import org.openecomp.appc.adapter.iaas.impl.RequestFailedException; +import org.openecomp.appc.adapter.iaas.impl.VMURL; +import org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Operation; +import org.openecomp.appc.adapter.iaas.provider.operation.impl.base.ProviderServerOperation; +import org.openecomp.appc.configuration.Configuration; +import org.openecomp.appc.configuration.ConfigurationFactory; +import org.openecomp.appc.exceptions.APPCException; +import org.openecomp.appc.i18n.Msg; +import com.att.cdp.exceptions.ContextConnectionException; +import com.att.cdp.exceptions.ResourceNotFoundException; +import com.att.cdp.exceptions.ZoneException; +import com.att.cdp.zones.Context; +import com.att.cdp.zones.ImageService; +import com.att.cdp.zones.Provider; +import com.att.cdp.zones.model.Image; +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 org.openecomp.sdnc.sli.SvcLogicContext; +import org.glassfish.grizzly.http.util.HttpStatus; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Map; + +import static org.openecomp.appc.adapter.iaas.provider.operation.common.constants.Constants.DATE_FORMAT; +import static org.openecomp.appc.adapter.utils.Constants.ADAPTER_NAME; + +import org.slf4j.MDC; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.TimeZone; + + +public class CreateSnapshot extends ProviderServerOperation { + + private static final EELFLogger logger = EELFManager.getInstance().getLogger(CreateSnapshot.class); + private static EELFLogger metricsLogger = EELFManager.getInstance().getMetricsLogger(); + private static final Configuration configuration = ConfigurationFactory.getConfiguration(); + + + private String generateSnapshotName(String server) { + SimpleDateFormat df = new SimpleDateFormat(DATE_FORMAT); + + /* + * Set Time for Metrics Logger + */ + long startTime = System.currentTimeMillis(); + TimeZone tz = TimeZone.getTimeZone("UTC"); + DateFormat df2 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); + df2.setTimeZone(tz); + String startTimeStr = df.format(new Date()); + long endTime = System.currentTimeMillis(); + long duration = endTime - startTime; + String endTimeStr = String.valueOf(endTime); + String durationStr = String.valueOf(duration); + String endTimeStrUTC = df.format(new Date()); + MDC.put("EndTimestamp", endTimeStrUTC); + MDC.put("ElapsedTime", durationStr); + MDC.put("TargetEntity", "cdp"); + MDC.put("TargetServiceName", "create snapshot"); + MDC.put("ClassName", "org.openecomp.appc.adapter.iaas.provider.operation.impl.CreateSnapshot"); + + metricsLogger.info("Snapshot Name Generated: Snapshot of %s at %s", server, df.format(new Date())); + + return String.format("Snapshot of %s at %s", server, df.format(new Date())); + } + + private Image createSnapshot(RequestContext rc, Server server) throws ZoneException, RequestFailedException { + Context context = server.getContext(); + Provider provider = context.getProvider(); + ImageService service = context.getImageService(); // Already checked access by this point + + String snapshotName = generateSnapshotName(server.getName()); + + /* + * Set Time for Metrics Logger + */ + long startTime = System.currentTimeMillis(); + TimeZone tz = TimeZone.getTimeZone("UTC"); + DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); + df.setTimeZone(tz); + String startTimeStr = df.format(new Date()); + long endTime = System.currentTimeMillis(); + long duration = endTime - startTime; + String endTimeStr = String.valueOf(endTime); + String durationStr = String.valueOf(duration); + String endTimeStrUTC = df.format(new Date()); + MDC.put("EndTimestamp", endTimeStrUTC); + MDC.put("ElapsedTime", durationStr); + MDC.put("TargetEntity", "cdp"); + MDC.put("TargetServiceName", "create snapshot"); + MDC.put("ClassName", "org.openecomp.appc.adapter.iaas.provider.operation.impl.CreateSnapshot"); + + logger.info(String.format("Creating snapshot of server %s (%s) with name %s", server.getName(), server.getId(), + snapshotName)); + metricsLogger.info(String.format("Creating snapshot of server %s (%s) with name %s", server.getName(), server.getId(), + snapshotName)); + + // Request Snapshot + String msg; + while (rc.attempt()) { + try { + server.createSnapshot(snapshotName); + break; + } catch (ContextConnectionException e) { + msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(), + context.getTenant().getName(), context.getTenant().getId(), e.getMessage(), + Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()), + Integer.toString(rc.getRetryLimit())); + logger.error(msg, e); + metricsLogger.error(msg, e); + rc.delay(); + } + } + if (rc.isFailed()) { + msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL()); + logger.error(msg); + metricsLogger.error(msg); + throw new RequestFailedException("Stop Server", msg, HttpStatus.BAD_GATEWAY_502, server); + } + rc.reset(); + + // Locate snapshot image + Image snapshot = null; + while (rc.attempt()) { + try { + snapshot = service.getImageByName(snapshotName); + if (snapshot != null) { + break; + } + } catch (ContextConnectionException e) { + msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(), + context.getTenant().getName(), context.getTenant().getId(), e.getMessage(), + Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()), + Integer.toString(rc.getRetryLimit())); + logger.error(msg, e); + metricsLogger.error(msg, e); + rc.delay(); + } + } + if (rc.isFailed()) { + msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL()); + logger.error(msg); + metricsLogger.error(msg); + throw new RequestFailedException("Stop Server", msg, HttpStatus.BAD_GATEWAY_502, server); + } + rc.reset(); + + // Wait for it to be ready + waitForStateChange(rc, snapshot, Image.Status.ACTIVE); + + return snapshot; + } + + private Image createSnapshot(Map<String, String> params, SvcLogicContext ctx) throws APPCException { + + Image snapshot = null; + RequestContext rc = new RequestContext(ctx); + rc.isAlive(); + + String appName = configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME); + String msg; + + + /* + * Set Time for Metrics Logger + */ + long startTime = System.currentTimeMillis(); + TimeZone tz = TimeZone.getTimeZone("UTC"); + DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); + df.setTimeZone(tz); + String startTimeStr = df.format(new Date()); + long endTime = System.currentTimeMillis(); + long duration = endTime - startTime; + String endTimeStr = String.valueOf(endTime); + String durationStr = String.valueOf(duration); + String endTimeStrUTC = df.format(new Date()); + MDC.put("EndTimestamp", endTimeStrUTC); + MDC.put("ElapsedTime", durationStr); + MDC.put("TargetEntity", "cdp"); + MDC.put("TargetServiceName", "create snapshot"); + MDC.put("ClassName", "org.openecomp.appc.adapter.iaas.provider.operation.impl.CreateSnapshot"); + + try { + validateParametersExist(params, ProviderAdapter.PROPERTY_INSTANCE_URL, + ProviderAdapter.PROPERTY_PROVIDER_NAME); + String vm_url = params.get(ProviderAdapter.PROPERTY_INSTANCE_URL); + + VMURL vm = VMURL.parseURL(vm_url); + if (validateVM(rc, appName, vm_url, vm)) return null; + + IdentityURL ident = IdentityURL.parseURL(params.get(ProviderAdapter.PROPERTY_IDENTITY_URL)); + String identStr = (ident == null) ? null : ident.toString(); + + Context context = null; + try { + context = getContext(rc, vm_url, identStr); + if (context != null) { + Server server = lookupServer(rc, context, vm.getServerId()); + logger.debug(Msg.SERVER_FOUND, vm_url, context.getTenantName(), server.getStatus().toString()); + + if (hasImageAccess(rc, context)) { + snapshot = createSnapshot(rc, server); + doSuccess(rc); + } else { + msg = EELFResourceManager.format(Msg.REBUILD_SERVER_FAILED, server.getName(), server.getId(), + "Accessing Image Service Failed"); + logger.error(msg); + metricsLogger.error(msg); + doFailure(rc, HttpStatus.FORBIDDEN_403, msg); + } + context.close(); + } + } catch (ResourceNotFoundException e) { + msg = EELFResourceManager.format(Msg.SERVER_NOT_FOUND, e, vm_url); + logger.error(msg); + metricsLogger.error(msg, e); + doFailure(rc, HttpStatus.NOT_FOUND_404, msg); + } catch (Throwable t) { + msg = EELFResourceManager.format(Msg.SERVER_OPERATION_EXCEPTION, t, t.getClass().getSimpleName(), + Operation.SNAPSHOT_SERVICE.toString(), vm_url, context == null ? "Unknown" : context.getTenantName()); + logger.error(msg, t); + doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg); + } + } catch (RequestFailedException e) { + doFailure(rc, e.getStatus(), e.getMessage()); + } + return snapshot; + } + + @Override + protected ModelObject executeProviderOperation(Map<String, String> params, SvcLogicContext context) throws APPCException { + + setMDC(Operation.SNAPSHOT_SERVICE.toString(), "App-C IaaS Adapter:Snapshot", ADAPTER_NAME); + logOperation(Msg.SNAPSHOTING_SERVER, params, context); + + /* + * Set Time for Metrics Logger + */ + long startTime = System.currentTimeMillis(); + TimeZone tz = TimeZone.getTimeZone("UTC"); + DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); + df.setTimeZone(tz); + String startTimeStr = df.format(new Date()); + long endTime = System.currentTimeMillis(); + long duration = endTime - startTime; + String endTimeStr = String.valueOf(endTime); + String durationStr = String.valueOf(duration); + String endTimeStrUTC = df.format(new Date()); + MDC.put("EndTimestamp", endTimeStrUTC); + MDC.put("ElapsedTime", durationStr); + MDC.put("TargetEntity", "cdp"); + MDC.put("TargetServiceName", "create snapshot"); + MDC.put("ClassName", "org.openecomp.appc.adapter.iaas.provider.operation.impl.CreateSnapshot"); + + metricsLogger.info("Executing Provider Operation: Create Snapshot"); + + return createSnapshot(params, context); + } +} diff --git a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/EvacuateServer.java b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/EvacuateServer.java new file mode 100644 index 000000000..d749fc225 --- /dev/null +++ b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/EvacuateServer.java @@ -0,0 +1,378 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.adapter.iaas.provider.operation.impl; + +import org.openecomp.appc.Constants; +import org.openecomp.appc.adapter.iaas.ProviderAdapter; +import org.openecomp.appc.adapter.iaas.impl.IdentityURL; +import org.openecomp.appc.adapter.iaas.impl.ProviderAdapterImpl; +import org.openecomp.appc.adapter.iaas.impl.RequestContext; +import org.openecomp.appc.adapter.iaas.impl.RequestFailedException; +import org.openecomp.appc.adapter.iaas.impl.VMURL; +import org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Operation; +import org.openecomp.appc.adapter.iaas.provider.operation.impl.base.ProviderServerOperation; +import org.openecomp.appc.configuration.Configuration; +import org.openecomp.appc.configuration.ConfigurationFactory; +import org.openecomp.appc.exceptions.APPCException; +import org.openecomp.appc.i18n.Msg; +import com.att.cdp.exceptions.ContextConnectionException; +import com.att.cdp.exceptions.ResourceNotFoundException; +import com.att.cdp.exceptions.ZoneException; +import com.att.cdp.zones.ComputeService; +import com.att.cdp.zones.Context; +import com.att.cdp.zones.Provider; +import com.att.cdp.zones.model.Hypervisor; +import com.att.cdp.zones.model.Hypervisor.Status; +import com.att.cdp.zones.model.Hypervisor.State; +import com.att.cdp.zones.model.Image; +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 org.openecomp.sdnc.sli.SvcLogicContext; +import org.glassfish.grizzly.http.util.HttpStatus; +import org.slf4j.MDC; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.TimeZone; + +import static org.openecomp.appc.adapter.utils.Constants.ADAPTER_NAME; + +public class EvacuateServer extends ProviderServerOperation { + + private static final EELFLogger logger = EELFManager.getInstance().getLogger(EvacuateServer.class); + private static EELFLogger metricsLogger = EELFManager.getInstance().getMetricsLogger(); + private static final Configuration configuration = ConfigurationFactory.getConfiguration(); + private ProviderAdapterImpl paImpl = null; + + + private void evacuateServer(RequestContext rc, @SuppressWarnings("unused") Server server, String target_host) throws ZoneException, RequestFailedException { + + String msg; + Context ctx = server.getContext(); + Provider provider = ctx.getProvider(); + ComputeService service = ctx.getComputeService(); + + /* + * Pending is a bit of a special case. If we find the server is in a pending state, then the provider is in the + * process of changing state of the server. So, lets try to wait a little bit and see if the state settles down + * to one we can deal with. If not, then we have to fail the request. + */ + try { + if (server.getStatus().equals(Server.Status.PENDING)) { + waitForStateChange(rc, server, Server.Status.READY, Server.Status.RUNNING, Server.Status.ERROR, Server.Status.SUSPENDED, Server.Status.PAUSED); + } + } catch (RequestFailedException e) { + // evacuate is a special case. If the server is still in a Pending state, we want to continue with evacuate + logger.info("Evacuate server - ignore RequestFailedException from waitForStateChange() ..."); + } + + /* + * Set Time for Metrics Logger + */ + long startTime = System.currentTimeMillis(); + TimeZone tz = TimeZone.getTimeZone("UTC"); + DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); + df.setTimeZone(tz); + String startTimeStr = df.format(new Date()); + long endTime = System.currentTimeMillis(); + long duration = endTime - startTime; + String endTimeStr = String.valueOf(endTime); + String durationStr = String.valueOf(duration); + String endTimeStrUTC = df.format(new Date()); + MDC.put("EndTimestamp", endTimeStrUTC); + MDC.put("ElapsedTime", durationStr); + MDC.put("TargetEntity", "cdp"); + MDC.put("TargetServiceName", "evacuate server"); + MDC.put("ClassName", "org.openecomp.appc.adapter.iaas.provider.operation.impl.EvacuteServer"); + + + try { + while (rc.attempt()) { + try { + logger.debug("Calling CDP moveServer - server id = " + server.getId()); + service.moveServer(server.getId(), target_host); + // Wait for completion, expecting the server to go to a non pending state + waitForStateChange(rc, server, Server.Status.READY, Server.Status.RUNNING, Server.Status.ERROR, Server.Status.SUSPENDED, Server.Status.PAUSED); + break; + } catch (ContextConnectionException e) { + msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(), + ctx.getTenant().getName(), ctx.getTenant().getId(), e.getMessage(), + Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()), + Integer.toString(rc.getRetryLimit())); + logger.error(msg, e); + metricsLogger.error(msg,e); + rc.delay(); + } + } + + } catch (ZoneException e) { + msg = + EELFResourceManager.format(Msg.EVACUATE_SERVER_FAILED, server.getName(), server.getId(), e.getMessage()); + logger.error(msg); + metricsLogger.error(msg); + throw new RequestFailedException("Evacute Server", msg, HttpStatus.BAD_GATEWAY_502, server); + } + + if (rc.isFailed()) { + msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL()); + logger.error(msg); + metricsLogger.error(msg); + throw new RequestFailedException("Evacuate Server", msg, HttpStatus.BAD_GATEWAY_502, server); + } + rc.reset(); + } + + + /** + * @see org.openecomp.appc.adapter.iaas.ProviderAdapter#evacuateServer(java.util.Map, org.openecomp.sdnc.sli.SvcLogicContext) + */ + private Server evacuateServer(Map<String, String> params, SvcLogicContext ctx) throws APPCException { + Server server = null; + RequestContext rc = new RequestContext(ctx); + rc.isAlive(); + + String appName = configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME); + String msg; + + /* + * Set Time for Metrics Logger + */ + long startTime = System.currentTimeMillis(); + TimeZone tz = TimeZone.getTimeZone("UTC"); + DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); + df.setTimeZone(tz); + String startTimeStr = df.format(new Date()); + long endTime = System.currentTimeMillis(); + long duration = endTime - startTime; + String endTimeStr = String.valueOf(endTime); + String durationStr = String.valueOf(duration); + String endTimeStrUTC = df.format(new Date()); + MDC.put("EndTimestamp", endTimeStrUTC); + MDC.put("ElapsedTime", durationStr); + MDC.put("TargetEntity", "cdp"); + MDC.put("TargetServiceName", "evacuate server"); + MDC.put("ClassName", "org.openecomp.appc.adapter.iaas.provider.operation.impl.EvacuateServer"); + + ctx.setAttribute("EVACUATE_STATUS", "ERROR"); + try { + validateParametersExist(params, ProviderAdapter.PROPERTY_INSTANCE_URL, + ProviderAdapter.PROPERTY_PROVIDER_NAME); + String vm_url = params.get(ProviderAdapter.PROPERTY_INSTANCE_URL); + + VMURL vm = VMURL.parseURL(vm_url); + if (validateVM(rc, appName, vm_url, vm)) return null; + + IdentityURL ident = IdentityURL.parseURL(params.get(ProviderAdapter.PROPERTY_IDENTITY_URL)); + String identStr = (ident == null) ? null : ident.toString(); + + // retrieve the optional parameters + String rebuild_vm = params.get(ProviderAdapter.PROPERTY_REBUILD_VM); + String targethost_id = params.get(ProviderAdapter.PROPERTY_TARGETHOST_ID); + + Context context = null; + try { + context = getContext(rc, vm_url, identStr); + if (context != null) { + + server = lookupServer(rc, context, vm.getServerId()); + logger.debug(Msg.SERVER_FOUND, vm_url, context.getTenantName(), server.getStatus().toString()); + + // check target host status + if (isComputeNodeDown(context, targethost_id)) { + msg = EELFResourceManager.format(Msg.EVACUATE_SERVER_FAILED, server.getName(), server.getId(), + "Target host " + targethost_id +" status is not UP/ENABLED"); + logger.error(msg); + metricsLogger.error(msg); + throw new RequestFailedException("Evacuate Server", msg, HttpStatus.BAD_REQUEST_400, server); + } + + // save hypervisor name before evacuate + String hypervisor = server.getHypervisor().getHostName(); + + evacuateServer(rc, server, targethost_id); + + server.refreshAll(); + String hypervisor_after_evacuate = server.getHypervisor().getHostName(); + logger.debug("Hostname before evacuate: " + hypervisor + ", After evacuate: " + hypervisor_after_evacuate); + + // check hypervisor host name after evacuate. If it is unchanged, the evacuate failed. + if ((hypervisor != null) && (hypervisor.equals(hypervisor_after_evacuate))) { + msg = EELFResourceManager.format(Msg.EVACUATE_SERVER_FAILED, server.getName(), server.getId(), + "Hypervisor host " + hypervisor + " after evacuate is the same as before evacuate. Provider (ex. Openstack) recovery actions may be needed."); + logger.error(msg); + metricsLogger.error(msg); + throw new RequestFailedException("Evacuate Server", msg, HttpStatus.INTERNAL_SERVER_ERROR_500, server); + + } + + // check VM status after evacuate + if (server.getStatus() == Server.Status.ERROR) { + msg = EELFResourceManager.format(Msg.EVACUATE_SERVER_FAILED, server.getName(), server.getId(), + "VM is in ERROR state after evacuate. Provider (ex. Openstack) recovery actions may be needed."); + logger.error(msg); + metricsLogger.error(msg); + throw new RequestFailedException("Evacuate Server", msg, HttpStatus.INTERNAL_SERVER_ERROR_500, server); + } + + context.close(); + doSuccess(rc); + ctx.setAttribute("EVACUATE_STATUS", "SUCCESS"); + + // If a snapshot exists, do a rebuild to apply the latest snapshot to the evacuated server. + // This is the default behavior unless the optional parameter is set to FALSE. + if ((rebuild_vm == null) || !(rebuild_vm.equalsIgnoreCase("false"))) { + List<Image> snapshots = server.getSnapshots(); + if (snapshots == null || snapshots.isEmpty()) { + logger.debug("No snapshots available - skipping rebuild after evacuate"); + } else if (paImpl != null) { + logger.debug("Executing a rebuild after evacuate"); + paImpl.rebuildServer(params, ctx); + // Check error code for rebuild errors. Evacuate had set it to 200 after + // a successful evacuate. Rebuild updates the error code. + String rebuildErrorCode = ctx.getAttribute(org.openecomp.appc.Constants.ATTRIBUTE_ERROR_CODE); + if (rebuildErrorCode != null) { + try { + int error_code = Integer.parseInt(rebuildErrorCode); + if (error_code != HttpStatus.OK_200.getStatusCode()) { + logger.debug("Rebuild after evacuate failed - error code=" + error_code + + ", message=" + ctx.getAttribute(org.openecomp.appc.Constants.ATTRIBUTE_ERROR_MESSAGE)); + msg = EELFResourceManager.format(Msg.EVACUATE_SERVER_REBUILD_FAILED, server.getName(), hypervisor, + hypervisor_after_evacuate, ctx.getAttribute(org.openecomp.appc.Constants.ATTRIBUTE_ERROR_MESSAGE)); + logger.error(msg); + metricsLogger.error(msg); + ctx.setAttribute("EVACUATE_STATUS", "ERROR"); + // update error message while keeping the error code the same as before + doFailure(rc, HttpStatus.getHttpStatus(error_code), msg); + } + } catch (NumberFormatException e) { + // ignore + } + } + } + } + + } + } catch (ResourceNotFoundException e) { + msg = EELFResourceManager.format(Msg.SERVER_NOT_FOUND, e, vm_url); + logger.error(msg); + metricsLogger.error(msg); + doFailure(rc, HttpStatus.NOT_FOUND_404, msg); + } catch (RequestFailedException e) { + doFailure(rc, e.getStatus(), e.getMessage()); + } catch (Throwable t) { + msg = EELFResourceManager.format(Msg.SERVER_OPERATION_EXCEPTION, t, t.getClass().getSimpleName(), + Operation.EVACUATE_SERVICE.toString(), vm_url, context == null ? "Unknown" : context.getTenantName()); + logger.error(msg, t); + metricsLogger.error(msg, t); + doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg); + } + } catch (RequestFailedException e) { + msg = EELFResourceManager.format(Msg.EVACUATE_SERVER_FAILED, "n/a", "n/a", e.getMessage()); + logger.error(msg); + metricsLogger.error(msg); + doFailure(rc, e.getStatus(), e.getMessage()); + } + + return server; + } + + /* + * Check if a Compute node is down. + * + * This method attempts to find a given host in the list of hypervisors for a given + * context. The only case where a node is considered down is if a matching hypervisor + * is found and it's state and status are not UP/ENABLED. + * + * @param context + * The current context + * @param host + * The host name (short or fully qualified) of a compute node + * @return true if the node is determined as down, false for all other cases + */ + private boolean isComputeNodeDown(Context context, String host) throws ZoneException { + ComputeService service = context.getComputeService(); + boolean node_down = false; + + // Check host status. A node is considered down only if a matching target host is + // found and it's state/status is not UP/ENABLED. + if ((host != null) && !(host.isEmpty())) { + List<Hypervisor> hypervisors = service.getHypervisors(); + logger.debug("List of Hypervisors retrieved: " + Arrays.toString(hypervisors.toArray())); + for (Hypervisor h : hypervisors) { + if (h.getHostName().startsWith(host)) { + // host matches one of the hypervisors + State hstate = h.getState(); + Status hstatus = h.getStatus(); + logger.debug("Host matching hypervisor: " + h.getHostName() + ", State/Status: " + + hstate.toString() + "/" + hstatus.toString()); + if ((hstate != null) && (hstatus != null)) { + if (!(hstate.equals(State.UP)) || !(hstatus.equals(Status.ENABLED))) { + node_down = true; + } + } + } + } + } + return node_down; + } + + @Override + protected ModelObject executeProviderOperation(Map<String, String> params, SvcLogicContext context) throws APPCException { + + setMDC(Operation.EVACUATE_SERVICE.toString(), "App-C IaaS Adapter:Evacuate", ADAPTER_NAME); + logOperation(Msg.EVACUATING_SERVER, params, context); + + /* + * Set Time for Metrics Logger + */ + long startTime = System.currentTimeMillis(); + TimeZone tz = TimeZone.getTimeZone("UTC"); + DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); + df.setTimeZone(tz); + String startTimeStr = df.format(new Date()); + long endTime = System.currentTimeMillis(); + long duration = endTime - startTime; + String endTimeStr = String.valueOf(endTime); + String durationStr = String.valueOf(duration); + String endTimeStrUTC = df.format(new Date()); + MDC.put("EndTimestamp", endTimeStrUTC); + MDC.put("ElapsedTime", durationStr); + MDC.put("TargetEntity", "cdp"); + MDC.put("TargetServiceName", "evacuate server"); + MDC.put("ClassName", "org.openecomp.appc.adapter.iaas.provider.operation.impl.EvacuateServer"); + + + metricsLogger.info("Executing Provider Operation: Evacuate"); + return evacuateServer(params, context); + } + + public void setProvideAdapterRef(ProviderAdapterImpl pai) { + paImpl = pai; + } +} diff --git a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/LookupServer.java b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/LookupServer.java new file mode 100644 index 000000000..03a76cb8b --- /dev/null +++ b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/LookupServer.java @@ -0,0 +1,124 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.adapter.iaas.provider.operation.impl; + +import org.openecomp.appc.Constants; +import org.openecomp.appc.adapter.iaas.ProviderAdapter; +import org.openecomp.appc.adapter.iaas.impl.RequestContext; +import org.openecomp.appc.adapter.iaas.impl.RequestFailedException; +import org.openecomp.appc.adapter.iaas.impl.VMURL; +import org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Operation; +import org.openecomp.appc.adapter.iaas.provider.operation.impl.base.ProviderServerOperation; +import org.openecomp.appc.configuration.Configuration; +import org.openecomp.appc.configuration.ConfigurationFactory; +import org.openecomp.appc.exceptions.APPCException; +import org.openecomp.appc.i18n.Msg; +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 org.openecomp.sdnc.sli.SvcLogicContext; +import org.glassfish.grizzly.http.util.HttpStatus; + +import java.io.IOException; +import java.util.Map; + +import static org.openecomp.appc.adapter.utils.Constants.ADAPTER_NAME; + +/** + * @since September 26, 2016 + */ +public class LookupServer extends ProviderServerOperation { + + private static final EELFLogger logger = EELFManager.getInstance().getLogger(EvacuateServer.class); + private static final Configuration configuration = ConfigurationFactory.getConfiguration(); + + + public Server lookupServer(Map<String, String> params, SvcLogicContext ctx) throws APPCException { + Server server = null; + RequestContext rc = new RequestContext(ctx); + rc.isAlive(); //should we test the return and fail if false? + + String appName = configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME); + + String vm_url = null; + VMURL vm = null; + try { + + //process vm_url + validateParametersExist(params, ProviderAdapter.PROPERTY_INSTANCE_URL, + ProviderAdapter.PROPERTY_PROVIDER_NAME); + vm_url = params.get(ProviderAdapter.PROPERTY_INSTANCE_URL); + vm = VMURL.parseURL(vm_url); + if (validateVM(rc, appName, vm_url, vm)) return null; + + + //use try with resource to ensure context is closed (returned to pool) + try(Context context = resolveContext(rc, params, appName, vm_url)){ + //resloveContext & getContext call doFailure and log errors before returning null + if (context != null){ + rc.reset(); + server = lookupServer(rc, context, vm.getServerId()); + logger.debug(Msg.SERVER_FOUND, vm_url, context.getTenantName(), server.getStatus().toString()); + ctx.setAttribute("serverFound", "success"); + String msg = EELFResourceManager.format(Msg.SUCCESS_EVENT_MESSAGE, "LookupServer", vm_url); + ctx.setAttribute(org.openecomp.appc.Constants.ATTRIBUTE_SUCCESS_MESSAGE, msg); + doSuccess(rc); + } + } catch (ZoneException e) { + //server not found + String msg = EELFResourceManager.format(Msg.SERVER_NOT_FOUND, e, vm_url); + logger.error(msg); + doFailure(rc, HttpStatus.NOT_FOUND_404, msg); + ctx.setAttribute("serverFound", "failure"); + } catch (IOException e) { + //exception closing context + String msg = EELFResourceManager.format(Msg.CLOSE_CONTEXT_FAILED, e, vm_url); + logger.error(msg); + } catch (Throwable t) { + String msg = EELFResourceManager.format(Msg.SERVER_OPERATION_EXCEPTION, t, t.getClass().getSimpleName(), + Operation.LOOKUP_SERVICE.toString(), vm_url, "Unknown" ); + logger.error(msg, t); + doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg); + } + + } catch (RequestFailedException e) { + // parameters not valid, unable to connect to provider + String msg = EELFResourceManager.format(Msg.SERVER_NOT_FOUND, e, vm_url); + logger.error(msg); + doFailure(rc, HttpStatus.NOT_FOUND_404, msg); + ctx.setAttribute("serverFound", "failure"); + } + return server; + } + + @Override + protected ModelObject executeProviderOperation(Map<String, String> params, SvcLogicContext context) throws APPCException { + + setMDC(Operation.LOOKUP_SERVICE.toString(), "App-C IaaS Adapter:LookupServer", ADAPTER_NAME); + logOperation(Msg.LOOKING_SERVER_UP, params, context); + return lookupServer(params, context); + } +} diff --git a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/MigrateServer.java b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/MigrateServer.java new file mode 100644 index 000000000..1b17d1c5c --- /dev/null +++ b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/MigrateServer.java @@ -0,0 +1,284 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.adapter.iaas.provider.operation.impl; + +import org.openecomp.appc.Constants; +import org.openecomp.appc.adapter.iaas.ProviderAdapter; +import org.openecomp.appc.adapter.iaas.impl.IdentityURL; +import org.openecomp.appc.adapter.iaas.impl.RequestContext; +import org.openecomp.appc.adapter.iaas.impl.RequestFailedException; +import org.openecomp.appc.adapter.iaas.impl.VMURL; +import org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Operation; +import org.openecomp.appc.adapter.iaas.provider.operation.impl.base.ProviderServerOperation; +import org.openecomp.appc.configuration.Configuration; +import org.openecomp.appc.configuration.ConfigurationFactory; +import org.openecomp.appc.exceptions.APPCException; +import org.openecomp.appc.i18n.Msg; +import com.att.cdp.exceptions.ContextConnectionException; +import com.att.cdp.exceptions.ResourceNotFoundException; +import com.att.cdp.exceptions.ZoneException; +import com.att.cdp.zones.ComputeService; +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 org.openecomp.sdnc.sli.SvcLogicContext; +import org.glassfish.grizzly.http.util.HttpStatus; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Map; + +import static org.openecomp.appc.adapter.iaas.provider.operation.common.constants.Constants.MDC_SERVICE; +import static org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Operation.MIGRATE_SERVICE; +import static org.openecomp.appc.adapter.utils.Constants.ADAPTER_NAME; + +import org.slf4j.MDC; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.TimeZone; + + +/** + * @since September 26, 2016 + */ +public class MigrateServer extends ProviderServerOperation { + + private static final EELFLogger logger = EELFManager.getInstance().getLogger(EvacuateServer.class); + private static EELFLogger metricsLogger = EELFManager.getInstance().getMetricsLogger(); + private static final Configuration configuration = ConfigurationFactory.getConfiguration(); + + /** + * A list of valid initial VM statuses for a migrate operations + */ + private final Collection<Server.Status> migratableStatuses = Arrays.asList(Server.Status.READY, Server.Status.RUNNING, Server.Status.SUSPENDED); + + + private String getConnectionExceptionMessage(RequestContext rc, Context ctx, ContextConnectionException e) + throws ZoneException { + return EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, ctx.getProvider().getName(), + ctx.getComputeService().getURL(), ctx.getTenant().getName(), ctx.getTenant().getId(), e.getMessage(), + Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()), + Integer.toString(rc.getRetryLimit())); + } + + private void migrateServer(RequestContext rc, Server server, SvcLogicContext svcCtx) + throws ZoneException, RequestFailedException { + String msg; + Context ctx = server.getContext(); + ComputeService service = ctx.getComputeService(); + + // Init status will equal final status + Server.Status initialStatus = server.getStatus(); + + if (initialStatus == null) { + throw new ZoneException("Failed to determine server's starting status"); + } + + // We can only migrate certain statuses + if (!migratableStatuses.contains(initialStatus)) { + throw new ZoneException(String.format("Cannot migrate server that is in %s state. Must be in one of [%s]", + initialStatus, migratableStatuses)); + } + + /* + * Set Time for Metrics Logger + */ + long startTime = System.currentTimeMillis(); + TimeZone tz = TimeZone.getTimeZone("UTC"); + DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); + df.setTimeZone(tz); + String startTimeStr = df.format(new Date()); + long endTime = System.currentTimeMillis(); + long duration = endTime - startTime; + String endTimeStr = String.valueOf(endTime); + String durationStr = String.valueOf(duration); + String endTimeStrUTC = df.format(new Date()); + MDC.put("EndTimestamp", endTimeStrUTC); + MDC.put("ElapsedTime", durationStr); + MDC.put("TargetEntity", "cdp"); + MDC.put("TargetServiceName", "migrate server"); + MDC.put("ClassName", "org.openecomp.appc.adapter.iaas.provider.operation.impl.MigrateServer"); + // Is the skip Hypervisor check attribute populated? + String skipHypervisorCheck = null; + if (svcCtx != null) { + skipHypervisorCheck = svcCtx.getAttribute(ProviderAdapter.SKIP_HYPERVISOR_CHECK); + + } + + // // Always perform Hypervisor check + // unless the skip is set to true + + if (skipHypervisorCheck == null || (!skipHypervisorCheck.equalsIgnoreCase("true"))) { + + // Check of the Hypervisor for the VM Server is UP and reachable + + checkHypervisor(server); + + } + + boolean inConfirmPhase = false; + try { + while (rc.attempt()) { + try { + if (!inConfirmPhase) { + // Initial migrate request + service.migrateServer(server.getId()); + // Wait for change to verify resize + waitForStateChange(rc, server, Server.Status.READY); + inConfirmPhase = true; + } + + // Verify resize + service.processResize(server); + // Wait for complete. will go back to init status + waitForStateChange(rc, server, initialStatus); + logger.info("Completed migrate request successfully"); + metricsLogger.info("Completed migrate request successfully"); + return; + } catch (ContextConnectionException e) { + msg = getConnectionExceptionMessage(rc, ctx, e); + logger.error(msg, e); + metricsLogger.error(msg, e); + rc.delay(); + } + } + } catch (ZoneException e) { + String phase = inConfirmPhase ? "VERIFY MIGRATE" : "REQUEST MIGRATE"; + msg = EELFResourceManager.format(Msg.MIGRATE_SERVER_FAILED, server.getName(), server.getId(), phase, + e.getMessage()); + generateEvent(rc, false, msg); + logger.error(msg, e); + metricsLogger.error(msg, e); + throw new RequestFailedException("Migrate Server", msg, HttpStatus.METHOD_NOT_ALLOWED_405, server); + } + + } + + /** + * @see org.openecomp.appc.adapter.iaas.ProviderAdapter#migrateServer(java.util.Map, org.openecomp.sdnc.sli.SvcLogicContext) + */ + private Server migrateServer(Map<String, String> params, SvcLogicContext ctx) throws APPCException { + Server server = null; + RequestContext rc = new RequestContext(ctx); + rc.isAlive(); + + String appName = configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME); + String msg; + + /* + * Set Time for Metrics Logger + */ + long startTime = System.currentTimeMillis(); + TimeZone tz = TimeZone.getTimeZone("UTC"); + DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); + df.setTimeZone(tz); + String startTimeStr = df.format(new Date()); + long endTime = System.currentTimeMillis(); + long duration = endTime - startTime; + String endTimeStr = String.valueOf(endTime); + String durationStr = String.valueOf(duration); + String endTimeStrUTC = df.format(new Date()); + MDC.put("EndTimestamp", endTimeStrUTC); + MDC.put("ElapsedTime", durationStr); + MDC.put("TargetEntity", "cdp"); + MDC.put("TargetServiceName", "migrate server"); + MDC.put("ClassName", "org.openecomp.appc.adapter.iaas.provider.operation.impl.MigrateServer"); + + try { + validateParametersExist(params, ProviderAdapter.PROPERTY_INSTANCE_URL, + ProviderAdapter.PROPERTY_PROVIDER_NAME); + String vm_url = params.get(ProviderAdapter.PROPERTY_INSTANCE_URL); + + VMURL vm = VMURL.parseURL(vm_url); + if (validateVM(rc, appName, vm_url, vm)) return null; + + IdentityURL ident = IdentityURL.parseURL(params.get(ProviderAdapter.PROPERTY_IDENTITY_URL)); + String identStr = (ident == null) ? null : ident.toString(); + + Context context = null; + try { + context = getContext(rc, vm_url, identStr); + if (context != null) { + server = lookupServer(rc, context, vm.getServerId()); + logger.debug(Msg.SERVER_FOUND, vm_url, context.getTenantName(), server.getStatus().toString()); + migrateServer(rc, server, ctx); + server.refreshStatus(); + context.close(); + doSuccess(rc); + } + } catch (RequestFailedException e) { + doFailure(rc, e.getStatus(), e.getMessage()); + } + catch (ResourceNotFoundException e) { + msg = EELFResourceManager.format(Msg.SERVER_NOT_FOUND, e, vm_url); + logger.error(msg); + metricsLogger.error(msg); + doFailure(rc, HttpStatus.NOT_FOUND_404, msg); + } catch (Throwable t) { + msg = EELFResourceManager.format(Msg.SERVER_OPERATION_EXCEPTION, t, t.getClass().getSimpleName(), + MIGRATE_SERVICE.toString(), vm_url, context == null ? "Unknown" : context.getTenantName()); + logger.error(msg, t); + metricsLogger.error(msg); + doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg); + } + } catch (RequestFailedException e) { + doFailure(rc, e.getStatus(), e.getMessage()); + } + + return server; + } + + @Override + protected ModelObject executeProviderOperation(Map<String, String> params, SvcLogicContext context) throws APPCException { + + setMDC(Operation.MIGRATE_SERVICE.toString(), "App-C IaaS Adapter:Migrate", ADAPTER_NAME); + logOperation(Msg.MIGRATING_SERVER, params, context); + + /* + * Set Time for Metrics Logger + */ + long startTime = System.currentTimeMillis(); + TimeZone tz = TimeZone.getTimeZone("UTC"); + DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); + df.setTimeZone(tz); + String startTimeStr = df.format(new Date()); + long endTime = System.currentTimeMillis(); + long duration = endTime - startTime; + String endTimeStr = String.valueOf(endTime); + String durationStr = String.valueOf(duration); + String endTimeStrUTC = df.format(new Date()); + MDC.put("EndTimestamp", endTimeStrUTC); + MDC.put("ElapsedTime", durationStr); + MDC.put("TargetEntity", "cdp"); + MDC.put("TargetServiceName", "migrate server"); + MDC.put("ClassName", "org.openecomp.appc.adapter.iaas.provider.operation.impl.MigrateServer"); + + + metricsLogger.info("Executing Provider Operation: Migrate"); + + return migrateServer(params,context); + } +} diff --git a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/RebuildServer.java b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/RebuildServer.java new file mode 100644 index 000000000..959c1ad41 --- /dev/null +++ b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/RebuildServer.java @@ -0,0 +1,503 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.adapter.iaas.provider.operation.impl; + +import org.openecomp.appc.Constants; +import org.openecomp.appc.adapter.iaas.ProviderAdapter; +import org.openecomp.appc.adapter.iaas.impl.IdentityURL; +import org.openecomp.appc.adapter.iaas.impl.RequestContext; +import org.openecomp.appc.adapter.iaas.impl.RequestFailedException; +import org.openecomp.appc.adapter.iaas.impl.VMURL; +import org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Operation; +import org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Outcome; +import org.openecomp.appc.adapter.iaas.provider.operation.impl.base.ProviderServerOperation; +import org.openecomp.appc.configuration.Configuration; +import org.openecomp.appc.configuration.ConfigurationFactory; +import org.openecomp.appc.exceptions.APPCException; +import org.openecomp.appc.i18n.Msg; +import com.att.cdp.exceptions.ContextConnectionException; +import com.att.cdp.exceptions.ResourceNotFoundException; +import com.att.cdp.exceptions.ZoneException; +import com.att.cdp.zones.ComputeService; +import com.att.cdp.zones.Context; +import com.att.cdp.zones.ImageService; +import com.att.cdp.zones.Provider; +import com.att.cdp.zones.model.Image; +import com.att.cdp.zones.model.ModelObject; +import com.att.cdp.zones.model.Server; +import com.att.cdp.zones.model.ServerBootSource; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.att.eelf.i18n.EELFResourceManager; +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.glassfish.grizzly.http.util.HttpStatus; + +import java.util.List; +import java.util.Map; + +import static org.openecomp.appc.adapter.iaas.provider.operation.common.constants.Constants.MDC_SERVICE; +import static org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Operation.STOP_SERVICE; +import static org.openecomp.appc.adapter.utils.Constants.ADAPTER_NAME; + +import org.slf4j.MDC; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.TimeZone; + +/** + * @since September 26, 2016 + */ +public class RebuildServer extends ProviderServerOperation { + + private static final EELFLogger logger = EELFManager.getInstance().getLogger(RebuildServer.class); + private static EELFLogger metricsLogger = EELFManager.getInstance().getMetricsLogger(); + private static final Configuration configuration = ConfigurationFactory.getConfiguration(); + + /** + * Rebuild the indicated server with the indicated image. This method assumes the server has been determined to be + * in the correct state to do the rebuild. + * + * @param rc + * The request context that manages the state and recovery of the request for the life of its processing. + * @param server + * the server to be rebuilt + * @param image + * The image to be used (or snapshot) + * @throws RequestFailedException + * if the server does not change state in the allotted time + */ + @SuppressWarnings("nls") + private void rebuildServer(RequestContext rc, Server server, String image) throws RequestFailedException { + logger.debug(Msg.REBUILD_SERVER, server.getId()); + + String msg; + Context context = server.getContext(); + Provider provider = context.getProvider(); + ComputeService service = context.getComputeService(); + + /* + * Set Time for Metrics Logger + */ + long startTime = System.currentTimeMillis(); + TimeZone tz = TimeZone.getTimeZone("UTC"); + DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); + df.setTimeZone(tz); + String startTimeStr = df.format(new Date()); + long endTime = System.currentTimeMillis(); + long duration = endTime - startTime; + String endTimeStr = String.valueOf(endTime); + String durationStr = String.valueOf(duration); + String endTimeStrUTC = df.format(new Date()); + MDC.put("EndTimestamp", endTimeStrUTC); + MDC.put("ElapsedTime", durationStr); + MDC.put("TargetEntity", "cdp"); + MDC.put("TargetServiceName", "rebuild server"); + MDC.put("ClassName", "org.openecomp.appc.adapter.iaas.provider.operation.impl.RebuildServer"); + + try { + while (rc.attempt()) { + try { + server.rebuild(image); + break; + } catch (ContextConnectionException e) { + msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(), + context.getTenant().getName(), context.getTenant().getId(), e.getMessage(), + Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()), + Integer.toString(rc.getRetryLimit())); + logger.error(msg, e); + metricsLogger.error(msg,e); + rc.delay(); + } + } + + /* + * We need to provide some time for OpenStack to start processing the request. + */ + try { + Thread.sleep(10L * 1000L); + } catch (InterruptedException e) { + logger.trace("Sleep threw interrupted exception, should never occur"); + metricsLogger.trace("Sleep threw interrupted exception, should never occur"); + } + } catch (ZoneException e) { + msg = + EELFResourceManager.format(Msg.REBUILD_SERVER_FAILED, server.getName(), server.getId(), e.getMessage()); + logger.error(msg); + metricsLogger.error(msg); + throw new RequestFailedException("Rebuild Server", msg, HttpStatus.BAD_GATEWAY_502, server); + } + + rc.reset(); + /* + * Once we have started the process, now we wait for the final state of stopped. This should be the final state + * (since we started the rebuild with the server stopped). + */ + waitForStateChange(rc, server, Server.Status.READY); + + if (rc.isFailed()) { + msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL()); + logger.error(msg); + metricsLogger.error(msg); + throw new RequestFailedException("Rebuild Server", msg, HttpStatus.BAD_GATEWAY_502, server); + } + rc.reset(); + } + + /** + * This method is called to rebuild the provided server. + * <p> + * If the server was booted from a volume, then the request is failed immediately and no action is taken. Rebuilding + * a VM from a bootable volume, where the bootable volume itself is not rebuilt, serves no purpose. + * </p> + * + * @param rc + * The request context that manages the state and recovery of the request for the life of its processing. + * @param server + * @throws ZoneException + * @throws RequestFailedException + */ + @SuppressWarnings("nls") + private void rebuildServer(RequestContext rc, Server server, SvcLogicContext ctx) + throws ZoneException, RequestFailedException { + + ServerBootSource builtFrom = server.getBootSource(); + String msg; + + /* + * Set Time for Metrics Logger + */ + long startTime = System.currentTimeMillis(); + TimeZone tz = TimeZone.getTimeZone("UTC"); + DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); + df.setTimeZone(tz); + String startTimeStr = df.format(new Date()); + long endTime = System.currentTimeMillis(); + long duration = endTime - startTime; + String endTimeStr = String.valueOf(endTime); + String durationStr = String.valueOf(duration); + String endTimeStrUTC = df.format(new Date()); + MDC.put("EndTimestamp", endTimeStrUTC); + MDC.put("ElapsedTime", durationStr); + MDC.put("TargetEntity", "cdp"); + MDC.put("TargetServiceName", "rebuild server"); + MDC.put("ClassName", "org.openecomp.appc.adapter.iaas.provider.operation.impl.RebuildServer"); + + // Throw exception for non image/snap boot source + if (ServerBootSource.VOLUME.equals(builtFrom)) { + msg = String.format("Rebuilding is currently not supported for servers built from bootable volumes [%s]", + server.getId()); + generateEvent(rc, false, msg); + logger.error(msg); + metricsLogger.error(msg); + throw new RequestFailedException("Rebuild Server", msg, HttpStatus.FORBIDDEN_403, server); + } + + /* + * Pending is a bit of a special case. If we find the server is in a + * pending state, then the provider is in the process of changing state + * of the server. So, lets try to wait a little bit and see if the state + * settles down to one we can deal with. If not, then we have to fail + * the request. + */ + Context context = server.getContext(); + Provider provider = context.getProvider(); + ComputeService service = context.getComputeService(); + if (server.getStatus().equals(Server.Status.PENDING)) { + rc.reset(); + waitForStateChange(rc, server, Server.Status.READY, Server.Status.RUNNING, Server.Status.ERROR, + Server.Status.SUSPENDED, Server.Status.PAUSED); + } + + // Is the skip Hypervisor check attribute populated? + String skipHypervisorCheck = null; + if (ctx != null) { + skipHypervisorCheck = ctx.getAttribute(ProviderAdapter.SKIP_HYPERVISOR_CHECK); + + } + + // Always perform Hypervisor Status checks + // unless the skip is set to true + if (skipHypervisorCheck == null || (!skipHypervisorCheck.equalsIgnoreCase("true"))) { + + // Check of the Hypervisor for the VM Server is UP and reachable + checkHypervisor(server); + } + + /* + * Get the image to use. This is determined by the presence or + * absence of snapshot images. If any snapshots exist, then the + * latest snapshot is used, otherwise the image used to construct + * the VM is used. + */ + List<Image> snapshots = server.getSnapshots(); + String imageToUse; + if (snapshots != null && !snapshots.isEmpty()) { + imageToUse = snapshots.get(0).getId(); + } else { + imageToUse = server.getImage(); + ImageService imageService = server.getContext().getImageService(); + rc.reset(); + try { + while (rc.attempt()) { + try { + /* + * We are just trying to make sure that the image + * exists. We arent interested in the details at + * this point. + */ + imageService.getImage(imageToUse); + break; + } catch (ContextConnectionException e) { + msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), + imageService.getURL(), context.getTenant().getName(), context.getTenant().getId(), + e.getMessage(), Long.toString(rc.getRetryDelay()), + Integer.toString(rc.getAttempts()), Integer.toString(rc.getRetryLimit())); + logger.error(msg, e); + metricsLogger.error(msg); + rc.delay(); + } + } + } catch (ZoneException e) { + msg = EELFResourceManager.format(Msg.IMAGE_NOT_FOUND, imageToUse, "rebuild"); + generateEvent(rc, false, msg); + logger.error(msg); + metricsLogger.error(msg); + throw new RequestFailedException("Rebuild Server", msg, HttpStatus.METHOD_NOT_ALLOWED_405, server); + } + } + if (rc.isFailed()) { + msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL()); + logger.error(msg); + metricsLogger.error(msg); + throw new RequestFailedException("Rebuild Server", msg, HttpStatus.BAD_GATEWAY_502, server); + } + rc.reset(); + + /* + * We determine what to do based on the current state of the server + */ + switch (server.getStatus()) { + case DELETED: + // Nothing to do, the server is gone + msg = EELFResourceManager.format(Msg.SERVER_DELETED, server.getName(), server.getId(), + server.getTenantId(), "rebuilt"); + generateEvent(rc, false, msg); + logger.error(msg); + metricsLogger.error(msg); + throw new RequestFailedException("Rebuild Server", msg, HttpStatus.METHOD_NOT_ALLOWED_405, server); + + case RUNNING: + // Attempt to stop the server, then rebuild it + stopServer(rc, server); + rc.reset(); + rebuildServer(rc, server, imageToUse); + rc.reset(); + startServer(rc, server); + generateEvent(rc, true, Outcome.SUCCESS.toString()); + metricsLogger.info("Server status: RUNNING"); + break; + + case ERROR: + msg = EELFResourceManager.format(Msg.SERVER_ERROR_STATE, server.getName(), server.getId(), + server.getTenantId(), "rebuild"); + generateEvent(rc, false, msg); + logger.error(msg); + metricsLogger.error(msg); + throw new RequestFailedException("Rebuild Server", msg, HttpStatus.METHOD_NOT_ALLOWED_405, server); + + case READY: + // Attempt to rebuild the server + rebuildServer(rc, server, imageToUse); + rc.reset(); + startServer(rc, server); + generateEvent(rc, true, Outcome.SUCCESS.toString()); + metricsLogger.info("Server status: READY"); + break; + + case PAUSED: + // if paused, un-pause it, stop it, and rebuild it + unpauseServer(rc, server); + rc.reset(); + stopServer(rc, server); + rc.reset(); + rebuildServer(rc, server, imageToUse); + rc.reset(); + startServer(rc, server); + generateEvent(rc, true, Outcome.SUCCESS.toString()); + metricsLogger.info("Server status: PAUSED"); + break; + + case SUSPENDED: + // Attempt to resume the suspended server, stop it, and rebuild it + resumeServer(rc, server); + rc.reset(); + stopServer(rc, server); + rc.reset(); + rebuildServer(rc, server, imageToUse); + rc.reset(); + startServer(rc, server); + generateEvent(rc, true, Outcome.SUCCESS.toString()); + metricsLogger.info("Server status: SUSPENDED"); + break; + + default: + // Hmmm, unknown status, should never occur + msg = EELFResourceManager.format(Msg.UNKNOWN_SERVER_STATE, server.getName(), server.getId(), + server.getTenantId(), server.getStatus().name()); + generateEvent(rc, false, msg); + logger.error(msg); + metricsLogger.error(msg); + throw new RequestFailedException("Rebuild Server", msg, HttpStatus.METHOD_NOT_ALLOWED_405, server); + } + + + } + + /** + * @see org.openecomp.appc.adapter.iaas.ProviderAdapter#rebuildServer(java.util.Map, org.openecomp.sdnc.sli.SvcLogicContext) + */ + @SuppressWarnings("nls") + public Server rebuildServer(Map<String, String> params, SvcLogicContext ctx) throws APPCException { + Server server = null; + RequestContext rc = new RequestContext(ctx); + rc.isAlive(); + + String appName = configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME); + String msg; + + /* + * Set Time for Metrics Logger + */ + long startTime = System.currentTimeMillis(); + TimeZone tz = TimeZone.getTimeZone("UTC"); + DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); + df.setTimeZone(tz); + String startTimeStr = df.format(new Date()); + long endTime = System.currentTimeMillis(); + long duration = endTime - startTime; + String endTimeStr = String.valueOf(endTime); + String durationStr = String.valueOf(duration); + String endTimeStrUTC = df.format(new Date()); + MDC.put("EndTimestamp", endTimeStrUTC); + MDC.put("ElapsedTime", durationStr); + MDC.put("TargetEntity", "cdp"); + MDC.put("TargetServiceName", "rebuild server"); + MDC.put("ClassName", "org.openecomp.appc.adapter.iaas.provider.operation.impl.RebuildServer"); + + try { + validateParametersExist(params, ProviderAdapter.PROPERTY_INSTANCE_URL, + ProviderAdapter.PROPERTY_PROVIDER_NAME); + String vm_url = params.get(ProviderAdapter.PROPERTY_INSTANCE_URL); + + VMURL vm = VMURL.parseURL(vm_url); + if (validateVM(rc, appName, vm_url, vm)) return null; + + IdentityURL ident = IdentityURL.parseURL(params.get(ProviderAdapter.PROPERTY_IDENTITY_URL)); + String identStr = (ident == null) ? null : ident.toString(); + ctx.setAttribute("REBUILD_STATUS", "ERROR"); + + Context context = null; + try { + context = getContext(rc, vm_url, identStr); + if (context != null) { + rc.reset(); + server = lookupServer(rc, context, vm.getServerId()); + logger.debug(Msg.SERVER_FOUND, vm_url, context.getTenantName(), server.getStatus().toString()); + + // Manually checking image service until new PAL release + if (hasImageAccess(rc, context)) { + rebuildServer(rc, server, ctx); + doSuccess(rc); + ctx.setAttribute("REBUILD_STATUS", "SUCCESS"); + } else { + msg = EELFResourceManager.format(Msg.REBUILD_SERVER_FAILED, server.getName(), server.getId(), + "Accessing Image Service Failed"); + logger.error(msg); + metricsLogger.error(msg); + doFailure(rc, HttpStatus.FORBIDDEN_403, msg); + } + context.close(); + } + else + { + ctx.setAttribute("REBUILD_STATUS", "CONTEXT_NOT_FOUND"); + } + } + catch (RequestFailedException e) { + doFailure(rc, e.getStatus(), e.getMessage()); + ctx.setAttribute("REBUILD_STATUS", "ERROR"); + } + catch (ResourceNotFoundException e) { + msg = EELFResourceManager.format(Msg.SERVER_NOT_FOUND, e, vm_url); + ctx.setAttribute("REBUILD_STATUS", "ERROR"); + logger.error(msg); + metricsLogger.error(msg); + doFailure(rc, HttpStatus.NOT_FOUND_404, msg); + } catch (Throwable t) { + msg = EELFResourceManager.format(Msg.SERVER_OPERATION_EXCEPTION, t, t.getClass().getSimpleName(), + STOP_SERVICE.toString(), vm_url, context == null ? "Unknown" : context.getTenantName()); + ctx.setAttribute("REBUILD_STATUS", "ERROR"); + logger.error(msg, t); + metricsLogger.error(msg); + doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg); + } + } catch (RequestFailedException e) { + doFailure(rc, e.getStatus(), e.getMessage()); + ctx.setAttribute("REBUILD_STATUS", "ERROR"); + } + + return server; + } + + @Override + protected ModelObject executeProviderOperation(Map<String, String> params, SvcLogicContext context) throws APPCException { + + setMDC(Operation.REBUILD_SERVICE.toString(), "App-C IaaS Adapter:Rebuild", ADAPTER_NAME); + logOperation(Msg.REBUILDING_SERVER, params, context); + + /* + * Set Time for Metrics Logger + */ + long startTime = System.currentTimeMillis(); + TimeZone tz = TimeZone.getTimeZone("UTC"); + DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); + df.setTimeZone(tz); + String startTimeStr = df.format(new Date()); + long endTime = System.currentTimeMillis(); + long duration = endTime - startTime; + String endTimeStr = String.valueOf(endTime); + String durationStr = String.valueOf(duration); + String endTimeStrUTC = df.format(new Date()); + MDC.put("EndTimestamp", endTimeStrUTC); + MDC.put("ElapsedTime", durationStr); + MDC.put("TargetEntity", "cdp"); + MDC.put("TargetServiceName", "rebuild server"); + MDC.put("ClassName", "org.openecomp.appc.adapter.iaas.provider.operation.impl.RebuildServer"); + + + metricsLogger.info("Executing Provider Operation: Rebuild"); + + + return rebuildServer(params, context); + } +} diff --git a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/RestartServer.java b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/RestartServer.java new file mode 100644 index 000000000..45e8f469f --- /dev/null +++ b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/RestartServer.java @@ -0,0 +1,320 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.adapter.iaas.provider.operation.impl; + +import org.openecomp.appc.Constants; +import org.openecomp.appc.adapter.iaas.ProviderAdapter; +import org.openecomp.appc.adapter.iaas.impl.IdentityURL; +import org.openecomp.appc.adapter.iaas.impl.RequestContext; +import org.openecomp.appc.adapter.iaas.impl.RequestFailedException; +import org.openecomp.appc.adapter.iaas.impl.VMURL; +import org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Outcome; +import org.openecomp.appc.adapter.iaas.provider.operation.impl.base.ProviderServerOperation; +import org.openecomp.appc.exceptions.UnknownProviderException; +import org.openecomp.appc.i18n.Msg; +import com.att.cdp.exceptions.ResourceNotFoundException; +import com.att.cdp.exceptions.ZoneException; +import com.att.cdp.zones.Context; +import com.att.cdp.zones.NetworkService; +import com.att.cdp.zones.model.ModelObject; +import com.att.cdp.zones.model.Network; +import com.att.cdp.zones.model.Port; +import com.att.cdp.zones.model.Server; +import com.att.cdp.zones.model.Subnet; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.att.eelf.i18n.EELFResourceManager; +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.glassfish.grizzly.http.util.HttpStatus; +import org.slf4j.MDC; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.TimeZone; + +import static org.openecomp.appc.adapter.iaas.provider.operation.common.constants.Constants.MDC_SERVICE; +import static org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Operation.RESTART_SERVICE; +import static org.openecomp.appc.adapter.utils.Constants.ADAPTER_NAME; + + +public class RestartServer extends ProviderServerOperation { + + private static final EELFLogger logger = EELFManager.getInstance().getLogger(RestartServer.class); + private static EELFLogger metricsLogger = EELFManager.getInstance().getMetricsLogger(); + + + /** + * This method handles the case of restarting a server once we have found the server and have obtained the abstract + * representation of the server via the context (i.e., the "Server" object from the CDP-Zones abstraction). + * + * @param rc + * The request context that manages the state and recovery of the request for the life of its processing. + * @param server + * The server object representing the server we want to operate on + * @throws ZoneException + */ + @SuppressWarnings("nls") + private void restartServer(RequestContext rc, Server server, SvcLogicContext ctx) + throws ZoneException, RequestFailedException { + + /* + * Pending is a bit of a special case. If we find the server is in a + * pending state, then the provider is in the process of changing state + * of the server. So, lets try to wait a little bit and see if the state + * settles down to one we can deal with. If not, then we have to fail + * the request. + */ + String msg; + if (server.getStatus().equals(Server.Status.PENDING)) { + waitForStateChange(rc, server, Server.Status.READY, Server.Status.RUNNING, Server.Status.ERROR, + Server.Status.SUSPENDED, Server.Status.PAUSED); + } + + /* + * Set Time for Metrics Logger + */ + long startTime = System.currentTimeMillis(); + TimeZone tz = TimeZone.getTimeZone("UTC"); + DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); + df.setTimeZone(tz); + String startTimeStr = df.format(new Date()); + long endTime = System.currentTimeMillis(); + long duration = endTime - startTime; + String endTimeStr = String.valueOf(endTime); + String durationStr = String.valueOf(duration); + String endTimeStrUTC = df.format(new Date()); + MDC.put("EndTimestamp", endTimeStrUTC); + MDC.put("ElapsedTime", durationStr); + MDC.put("TargetEntity", "cdp"); + MDC.put("TargetServiceName", "restart server"); + MDC.put("ClassName", "org.openecomp.appc.adapter.iaas.provider.operation.impl.RestartServer"); + + String skipHypervisorCheck = null; + if (ctx != null) { + skipHypervisorCheck = ctx.getAttribute(ProviderAdapter.SKIP_HYPERVISOR_CHECK); + + } + + // Always perform Virtual Machine/Hypervisor Status/Network checks + // unless the skip is set to true + if (skipHypervisorCheck == null || (!skipHypervisorCheck.equalsIgnoreCase("true"))) { + + // Check of the Hypervisor for the VM Server is UP and reachable + + checkHypervisor(server); + + } + + /* + * We determine what to do based on the current state of the server + */ + + switch (server.getStatus()) { + case DELETED: + // Nothing to do, the server is gone + msg = EELFResourceManager.format(Msg.SERVER_DELETED, server.getName(), server.getId(), + server.getTenantId(), "restarted"); + generateEvent(rc, false, msg); + logger.error(msg); + metricsLogger.error(msg); + break; + + case RUNNING: + // Attempt to stop and start the server + stopServer(rc, server); + startServer(rc, server); + generateEvent(rc, true, Outcome.SUCCESS.toString()); + metricsLogger.info("Server status: RUNNING"); + break; + + case ERROR: + msg = EELFResourceManager.format(Msg.SERVER_ERROR_STATE, server.getName(), server.getId(), + server.getTenantId(), "rebuild"); + generateEvent(rc, false, msg); + logger.error(msg); + metricsLogger.error(msg); + throw new RequestFailedException("Rebuild Server", msg, HttpStatus.METHOD_NOT_ALLOWED_405, server); + + case READY: + // Attempt to start the server + startServer(rc, server); + generateEvent(rc, true, Outcome.SUCCESS.toString()); + metricsLogger.info("Server status: READY"); + break; + + case PAUSED: + // if paused, un-pause it + unpauseServer(rc, server); + generateEvent(rc, true, Outcome.SUCCESS.toString()); + metricsLogger.info("Server status: PAUSED"); + break; + + case SUSPENDED: + // Attempt to resume the suspended server + resumeServer(rc, server); + generateEvent(rc, true, Outcome.SUCCESS.toString()); + metricsLogger.info("Server status: SUSPENDED"); + break; + + default: + // Hmmm, unknown status, should never occur + msg = EELFResourceManager.format(Msg.UNKNOWN_SERVER_STATE, server.getName(), server.getId(), + server.getTenantId(), server.getStatus().name()); + generateEvent(rc, false, msg); + logger.error(msg); + metricsLogger.error(msg); + break; + } + + + } + + /** + * This method is used to restart an existing virtual machine given the fully qualified URL of the machine. + * <p> + * The fully qualified URL contains enough information to locate the appropriate server. The URL is of the form + * <pre> + * [scheme]://[host[:port]] / [path] / [tenant_id] / servers / [vm_id] + * </pre> Where the various parts of the URL can be parsed and extracted and used to locate the appropriate service + * in the provider service catalog. This then allows us to open a context using the CDP abstraction, obtain the + * server by its UUID, and then perform the restart. + * </p> + * + * @throws UnknownProviderException + * If the provider cannot be found + * @throws IllegalArgumentException + * if the expected argument(s) are not defined or are invalid + * @see org.openecomp.appc.adapter.iaas.ProviderAdapter#restartServer(java.util.Map, org.openecomp.sdnc.sli.SvcLogicContext) + */ + @SuppressWarnings("nls") + private Server restartServer(Map<String, String> params, SvcLogicContext ctx) + throws UnknownProviderException, IllegalArgumentException { + Server server = null; + RequestContext rc = new RequestContext(ctx); + rc.isAlive(); + + String appName = configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME); + + + /* + * Set Time for Metrics Logger + */ + long startTime = System.currentTimeMillis(); + TimeZone tz = TimeZone.getTimeZone("UTC"); + DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); + df.setTimeZone(tz); + String startTimeStr = df.format(new Date()); + long endTime = System.currentTimeMillis(); + long duration = endTime - startTime; + String endTimeStr = String.valueOf(endTime); + String durationStr = String.valueOf(duration); + String endTimeStrUTC = df.format(new Date()); + MDC.put("EndTimestamp", endTimeStrUTC); + MDC.put("ElapsedTime", durationStr); + MDC.put("TargetEntity", "cdp"); + MDC.put("TargetServiceName", "GET server status"); + MDC.put("ClassName", "org.openecomp.appc.adapter.iaas.provider.operation.impl.RestartServer"); + + ctx.setAttribute("RESTART_STATUS", "ERROR"); + try { + validateParametersExist(params, ProviderAdapter.PROPERTY_INSTANCE_URL, + ProviderAdapter.PROPERTY_PROVIDER_NAME); + + String vm_url = params.get(ProviderAdapter.PROPERTY_INSTANCE_URL); + + VMURL vm = VMURL.parseURL(vm_url); + if (validateVM(rc, appName, vm_url, vm)) return null; + + IdentityURL ident = IdentityURL.parseURL(params.get(ProviderAdapter.PROPERTY_IDENTITY_URL)); + String identStr = (ident == null) ? null : ident.toString(); + + Context context = null; + try { + context = getContext(rc, vm_url, identStr); + if (context != null) { + rc.reset(); + server = lookupServer(rc, context, vm.getServerId()); + logger.debug(Msg.SERVER_FOUND, vm_url, context.getTenantName(), server.getStatus().toString()); + rc.reset(); + restartServer(rc, server, ctx); + context.close(); + doSuccess(rc); + ctx.setAttribute("RESTART_STATUS", "SUCCESS"); + String msg = EELFResourceManager.format(Msg.SUCCESS_EVENT_MESSAGE, "RestartServer", vm_url); + ctx.setAttribute(org.openecomp.appc.Constants.ATTRIBUTE_SUCCESS_MESSAGE, msg); + } + } catch (RequestFailedException e) { + doFailure(rc, e.getStatus(), e.getMessage()); + } + catch (ResourceNotFoundException e) { + String msg = EELFResourceManager.format(Msg.SERVER_NOT_FOUND, e, vm_url); + logger.error(msg); + metricsLogger.error(msg); + doFailure(rc, HttpStatus.NOT_FOUND_404, msg); + } catch (Throwable t) { + String msg = EELFResourceManager.format(Msg.SERVER_OPERATION_EXCEPTION, t, t.getClass().getSimpleName(), + RESTART_SERVICE.toString(), vm_url, context == null ? "Unknown" : context.getTenantName()); + logger.error(msg, t); + metricsLogger.error(msg, t); + doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg); + } + } catch (RequestFailedException e) { + doFailure(rc, e.getStatus(), e.getMessage()); + } + + return server; + } + + @Override + protected ModelObject executeProviderOperation(Map<String, String> params, SvcLogicContext context) throws UnknownProviderException { + + setMDC(RESTART_SERVICE.toString(), "App-C IaaS Adapter:Restart", ADAPTER_NAME); + logOperation(Msg.RESTARTING_SERVER, params, context); + + /* + * Set Time for Metrics Logger + */ + long startTime = System.currentTimeMillis(); + TimeZone tz = TimeZone.getTimeZone("UTC"); + DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); + df.setTimeZone(tz); + String startTimeStr = df.format(new Date()); + long endTime = System.currentTimeMillis(); + long duration = endTime - startTime; + String endTimeStr = String.valueOf(endTime); + String durationStr = String.valueOf(duration); + String endTimeStrUTC = df.format(new Date()); + MDC.put("EndTimestamp", endTimeStrUTC); + MDC.put("ElapsedTime", durationStr); + MDC.put("TargetEntity", "cdp"); + MDC.put("TargetServiceName", "execute restart"); + MDC.put("ClassName", "org.openecomp.appc.adapter.iaas.provider.operation.impl.RestartServer"); + + metricsLogger.info("Executing Provider Operation: Restart"); + + + return restartServer(params, context); + } +} diff --git a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/RestoreStack.java b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/RestoreStack.java new file mode 100644 index 000000000..018c8e2e6 --- /dev/null +++ b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/RestoreStack.java @@ -0,0 +1,152 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.adapter.iaas.provider.operation.impl; + +import org.openecomp.appc.Constants; +import org.openecomp.appc.adapter.iaas.ProviderAdapter; +import org.openecomp.appc.adapter.iaas.impl.RequestContext; +import org.openecomp.appc.adapter.iaas.impl.RequestFailedException; +import org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Operation; +import org.openecomp.appc.adapter.iaas.provider.operation.impl.base.ProviderStackOperation; +import org.openecomp.appc.adapter.openstack.heat.SnapshotResource; +import org.openecomp.appc.adapter.openstack.heat.StackResource; +import org.openecomp.appc.exceptions.APPCException; +import org.openecomp.appc.exceptions.UnknownProviderException; +import org.openecomp.appc.i18n.Msg; +import com.att.cdp.exceptions.ResourceNotFoundException; +import com.att.cdp.exceptions.ZoneException; +import com.att.cdp.openstack.OpenStackContext; +import com.att.cdp.openstack.connectors.HeatConnector; +import com.att.cdp.openstack.util.ExceptionMapper; +import com.att.cdp.zones.Context; +import com.att.cdp.zones.model.ModelObject; +import com.att.cdp.zones.model.Stack; +import com.att.cdp.zones.spi.RequestState; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.att.eelf.i18n.EELFResourceManager; +import org.openecomp.sdnc.sli.SvcLogicContext; +import com.woorea.openstack.base.client.OpenStackBaseException; +import com.woorea.openstack.heat.Heat; +import org.glassfish.grizzly.http.util.HttpStatus; + +import java.util.Map; + +import static org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Operation.RESTART_SERVICE; +import static org.openecomp.appc.adapter.utils.Constants.ADAPTER_NAME; + + +public class RestoreStack extends ProviderStackOperation { + + private static final EELFLogger logger = EELFManager.getInstance().getLogger(RestoreStack.class); + + private void restoreStack(Stack stack, String snapshotId) throws ZoneException, RequestFailedException { + Context context = stack.getContext(); + + OpenStackContext osContext = (OpenStackContext)context; + + final HeatConnector heatConnector = osContext.getHeatConnector(); + ((OpenStackContext)context).refreshIfStale(heatConnector); + + trackRequest(context); + RequestState.put("SERVICE", "Orchestration"); + RequestState.put("SERVICE_URL", heatConnector.getEndpoint()); + + Heat heat = heatConnector.getClient(); + + SnapshotResource snapshotResource = new SnapshotResource(heat); + + try { + + snapshotResource.restore(stack.getName(), stack.getId(), snapshotId).execute(); + + // wait for the snapshot restore + StackResource stackResource = new StackResource(heat); + if (!waitForStack(stack, stackResource, "RESTORE_COMPLETE")) { + throw new RequestFailedException("Snapshot restore failed."); + } + + } catch (OpenStackBaseException e) { + ExceptionMapper.mapException(e); + } + + } + + public Stack restoreStack(Map<String, String> params, SvcLogicContext ctx) throws IllegalArgumentException, APPCException { + Stack stack = null; + RequestContext rc = new RequestContext(ctx); + rc.isAlive(); + + ctx.setAttribute("SNAPSHOT_STATUS", "STACK_NOT_FOUND"); + String appName = configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME); + + String vm_url = null; + Context context = null; + + try { + + validateParametersExist(params, ProviderAdapter.PROPERTY_INSTANCE_URL, ProviderAdapter.PROPERTY_PROVIDER_NAME, + ProviderAdapter.PROPERTY_STACK_ID, ProviderAdapter.PROPERTY_INPUT_SNAPSHOT_ID); + + String stackId = params.get(ProviderAdapter.PROPERTY_STACK_ID); + vm_url = params.get(ProviderAdapter.PROPERTY_INSTANCE_URL); + String snapshotId = params.get(ProviderAdapter.PROPERTY_INPUT_SNAPSHOT_ID); + + context = resolveContext(rc, params, appName, vm_url); + + + if (context != null) { + stack = lookupStack(rc, context, stackId); + logger.debug(Msg.STACK_FOUND, vm_url, context.getTenantName(), stack.getStatus().toString()); + logger.info(EELFResourceManager.format(Msg.TERMINATING_STACK, stack.getName())); + restoreStack(stack, snapshotId); + logger.info(EELFResourceManager.format(Msg.TERMINATE_STACK, stack.getName())); + context.close(); + doSuccess(rc); + }else { + ctx.setAttribute(Constants.DG_ATTRIBUTE_STATUS, "failure"); + } + + } catch (ResourceNotFoundException e) { + String msg = EELFResourceManager.format(Msg.STACK_NOT_FOUND, e, vm_url); + logger.error(msg); + doFailure(rc, HttpStatus.NOT_FOUND_404, msg, e); + } catch (RequestFailedException e) { + logger.error(EELFResourceManager.format(Msg.MISSING_PARAMETER_IN_REQUEST, e.getReason(), "restoreStack")); + doFailure(rc, e.getStatus(), e.getMessage(), e); + } catch (Throwable t) { + String msg = EELFResourceManager.format(Msg.STACK_OPERATION_EXCEPTION, t, t.getClass().getSimpleName(), + "restoreStack", vm_url, null == context ? "n/a" : context.getTenantName()); + logger.error(msg, t); + doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg, t); + } + return stack; + } + + @Override + protected ModelObject executeProviderOperation(Map<String, String> params, SvcLogicContext context) throws APPCException { + + setMDC(Operation.RESTORE_STACK.toString(), "App-C IaaS Adapter:Restore-Stack", ADAPTER_NAME); + logOperation(Msg.RESTORING_STACK, params, context); + return restoreStack(params, context); + } +} diff --git a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/SnapshotStack.java b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/SnapshotStack.java new file mode 100644 index 000000000..5014e759f --- /dev/null +++ b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/SnapshotStack.java @@ -0,0 +1,237 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.adapter.iaas.provider.operation.impl; + +import org.openecomp.appc.Constants; +import org.openecomp.appc.adapter.iaas.ProviderAdapter; +import org.openecomp.appc.adapter.iaas.impl.RequestContext; +import org.openecomp.appc.adapter.iaas.impl.RequestFailedException; +import org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Operation; +import org.openecomp.appc.adapter.iaas.provider.operation.impl.base.ProviderOperation; +import org.openecomp.appc.adapter.iaas.provider.operation.impl.base.ProviderStackOperation; +import org.openecomp.appc.adapter.openstack.heat.SnapshotResource; +import org.openecomp.appc.adapter.openstack.heat.StackResource; +import org.openecomp.appc.adapter.openstack.heat.model.CreateSnapshotParams; +import org.openecomp.appc.adapter.openstack.heat.model.Snapshot; +import org.openecomp.appc.configuration.Configuration; +import org.openecomp.appc.configuration.ConfigurationFactory; +import org.openecomp.appc.exceptions.APPCException; +import org.openecomp.appc.i18n.Msg; +import com.att.cdp.exceptions.ResourceNotFoundException; +import com.att.cdp.exceptions.ZoneException; +import com.att.cdp.openstack.OpenStackContext; +import com.att.cdp.openstack.connectors.HeatConnector; +import com.att.cdp.openstack.util.ExceptionMapper; +import com.att.cdp.zones.Context; +import com.att.cdp.zones.model.ModelObject; +import com.att.cdp.zones.model.Stack; +import com.att.cdp.zones.spi.RequestState; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.att.eelf.i18n.EELFResourceManager; +import org.openecomp.sdnc.sli.SvcLogicContext; +import com.woorea.openstack.base.client.OpenStackBaseException; +import com.woorea.openstack.heat.Heat; +import org.glassfish.grizzly.http.util.HttpStatus; + +import java.util.Map; + +import static org.openecomp.appc.adapter.utils.Constants.ADAPTER_NAME; + +import org.slf4j.MDC; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.TimeZone; + + +/** + * @since September 26, 2016 + */ +public class SnapshotStack extends ProviderStackOperation { + + private static final EELFLogger logger = EELFManager.getInstance().getLogger(SnapshotStack.class); + private static EELFLogger metricsLogger = EELFManager.getInstance().getMetricsLogger(); + + + private Snapshot snapshotStack(@SuppressWarnings("unused") RequestContext rc, Stack stack) throws ZoneException, RequestFailedException { + Snapshot snapshot = new Snapshot(); + Context context = stack.getContext(); + + OpenStackContext osContext = (OpenStackContext)context; + + final HeatConnector heatConnector = osContext.getHeatConnector(); + ((OpenStackContext)context).refreshIfStale(heatConnector); + + trackRequest(context); + RequestState.put("SERVICE", "Orchestration"); + RequestState.put("SERVICE_URL", heatConnector.getEndpoint()); + + Heat heat = heatConnector.getClient(); + + SnapshotResource snapshotResource = new SnapshotResource(heat); + + /* + * Set Time for Metrics Logger + */ + long startTime = System.currentTimeMillis(); + TimeZone tz = TimeZone.getTimeZone("UTC"); + DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); + df.setTimeZone(tz); + String startTimeStr = df.format(new Date()); + long endTime = System.currentTimeMillis(); + long duration = endTime - startTime; + String endTimeStr = String.valueOf(endTime); + String durationStr = String.valueOf(duration); + String endTimeStrUTC = df.format(new Date()); + MDC.put("EndTimestamp", endTimeStrUTC); + MDC.put("ElapsedTime", durationStr); + MDC.put("TargetEntity", "cdp"); + MDC.put("TargetServiceName", "snapshot stack"); + MDC.put("ClassName", "org.openecomp.appc.adapter.iaas.provider.operation.impl.SnapshotStack"); + + try { + + snapshot = snapshotResource.create(stack.getName(), stack.getId(), new CreateSnapshotParams()).execute(); + + // wait for the stack deletion + StackResource stackResource = new StackResource(heat); + if (!waitForStack(stack, stackResource, "SNAPSHOT_COMPLETE")) { + throw new RequestFailedException("Stack Snapshot failed."); + } + + } catch (OpenStackBaseException e) { + ExceptionMapper.mapException(e); + } + + return snapshot; + } + + + public Stack snapshotStack(Map<String, String> params, SvcLogicContext ctx) throws IllegalArgumentException, APPCException { + Stack stack = null; + RequestContext rc = new RequestContext(ctx); + rc.isAlive(); + + ctx.setAttribute("SNAPSHOT_STATUS", "STACK_NOT_FOUND"); + String appName = configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME); + + String vm_url = null; + Context context = null; + + /* + * Set Time for Metrics Logger + */ + long startTime = System.currentTimeMillis(); + TimeZone tz = TimeZone.getTimeZone("UTC"); + DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); + df.setTimeZone(tz); + String startTimeStr = df.format(new Date()); + long endTime = System.currentTimeMillis(); + long duration = endTime - startTime; + String endTimeStr = String.valueOf(endTime); + String durationStr = String.valueOf(duration); + String endTimeStrUTC = df.format(new Date()); + MDC.put("EndTimestamp", endTimeStrUTC); + MDC.put("ElapsedTime", durationStr); + MDC.put("TargetEntity", "cdp"); + MDC.put("TargetServiceName", "snapshot stack"); + MDC.put("ClassName", "org.openecomp.appc.adapter.iaas.provider.operation.impl.SnapshotStack"); + + + try { + + validateParametersExist(params, ProviderAdapter.PROPERTY_INSTANCE_URL, + ProviderAdapter.PROPERTY_PROVIDER_NAME, ProviderAdapter.PROPERTY_STACK_ID); + + String stackId = params.get(ProviderAdapter.PROPERTY_STACK_ID); + vm_url = params.get(ProviderAdapter.PROPERTY_INSTANCE_URL); + + context = resolveContext(rc, params, appName, vm_url); + + if (context != null) { + stack = lookupStack(rc, context, stackId); + logger.debug(Msg.STACK_FOUND, vm_url, context.getTenantName(), stack.getStatus().toString()); + logger.info(EELFResourceManager.format(Msg.SNAPSHOTING_STACK, stack.getName())); + metricsLogger.info(EELFResourceManager.format(Msg.SNAPSHOTING_STACK, stack.getName())); + + Snapshot snapshot = snapshotStack(rc, stack); + + ctx.setAttribute(ProviderAdapter.DG_OUTPUT_PARAM_NAMESPACE + + ProviderAdapter.PROPERTY_SNAPSHOT_ID, snapshot.getId()); + + logger.info(EELFResourceManager.format(Msg.STACK_SNAPSHOTED, stack.getName(), snapshot.getId())); + metricsLogger.info(EELFResourceManager.format(Msg.STACK_SNAPSHOTED, stack.getName(), snapshot.getId())); + context.close(); + doSuccess(rc); + } else { + ctx.setAttribute(Constants.DG_ATTRIBUTE_STATUS, "failure"); + } + + } catch (ResourceNotFoundException e) { + String msg = EELFResourceManager.format(Msg.STACK_NOT_FOUND, e, vm_url); + logger.error(msg); + metricsLogger.error(msg); + doFailure(rc, HttpStatus.NOT_FOUND_404, msg, e); + } catch (RequestFailedException e) { + logger.error(EELFResourceManager.format(Msg.MISSING_PARAMETER_IN_REQUEST, e.getReason(), "snapshotStack")); + metricsLogger.error(EELFResourceManager.format(Msg.MISSING_PARAMETER_IN_REQUEST, e.getReason(), "snapshotStack")); + doFailure(rc, e.getStatus(), e.getMessage(), e); + } catch (Throwable t) { + String msg = EELFResourceManager.format(Msg.STACK_OPERATION_EXCEPTION, t, t.getClass().getSimpleName(), + "snapshotStack", vm_url, null == context ? "n/a" : context.getTenantName()); + logger.error(msg, t); + metricsLogger.error(msg); + doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg, t); + } + return stack; + } + + @Override + protected ModelObject executeProviderOperation(Map<String, String> params, SvcLogicContext context) throws APPCException { + setMDC(Operation.SNAPSHOT_STACK.toString(), "App-C IaaS Adapter:Snapshot-Stack", ADAPTER_NAME); + logOperation(Msg.SNAPSHOTING_STACK, params, context); + + /* + * Set Time for Metrics Logger + */ + long startTime = System.currentTimeMillis(); + TimeZone tz = TimeZone.getTimeZone("UTC"); + DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); + df.setTimeZone(tz); + String startTimeStr = df.format(new Date()); + long endTime = System.currentTimeMillis(); + long duration = endTime - startTime; + String endTimeStr = String.valueOf(endTime); + String durationStr = String.valueOf(duration); + String endTimeStrUTC = df.format(new Date()); + MDC.put("EndTimestamp", endTimeStrUTC); + MDC.put("ElapsedTime", durationStr); + MDC.put("TargetEntity", "cdp"); + MDC.put("TargetServiceName", "snapshot stack"); + MDC.put("ClassName", "org.openecomp.appc.adapter.iaas.provider.operation.impl.SnapshotStack"); + + metricsLogger.info("Executing Provider Operation: Snapshot Stack"); + + return snapshotStack(params, context); + } +} diff --git a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/StartServer.java b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/StartServer.java new file mode 100644 index 000000000..41b0afd69 --- /dev/null +++ b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/StartServer.java @@ -0,0 +1,186 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.adapter.iaas.provider.operation.impl; + +import org.openecomp.appc.Constants; +import org.openecomp.appc.adapter.iaas.ProviderAdapter; +import org.openecomp.appc.adapter.iaas.impl.IdentityURL; +import org.openecomp.appc.adapter.iaas.impl.RequestContext; +import org.openecomp.appc.adapter.iaas.impl.RequestFailedException; +import org.openecomp.appc.adapter.iaas.impl.VMURL; +import org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Operation; +import org.openecomp.appc.adapter.iaas.provider.operation.impl.base.ProviderServerOperation; +import org.openecomp.appc.exceptions.APPCException; +import org.openecomp.appc.i18n.Msg; +import com.att.cdp.exceptions.ResourceNotFoundException; +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 org.openecomp.sdnc.sli.SvcLogicContext; +import org.glassfish.grizzly.http.util.HttpStatus; + +import java.util.Map; + +import static org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Operation.START_SERVICE; +import static org.openecomp.appc.adapter.utils.Constants.ADAPTER_NAME; + +public class StartServer extends ProviderServerOperation { + + private static final EELFLogger logger = EELFManager.getInstance().getLogger(StartServer.class); + + /** + * @see org.openecomp.appc.adapter.iaas.ProviderAdapter#startServer(java.util.Map, org.openecomp.sdnc.sli.SvcLogicContext) + */ + @SuppressWarnings("nls") + public Server startServer(Map<String, String> params, SvcLogicContext ctx) throws APPCException { + Server server = null; + RequestContext rc = new RequestContext(ctx); + rc.isAlive(); + + String appName = configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME); + + try { + validateParametersExist(params, ProviderAdapter.PROPERTY_INSTANCE_URL, + ProviderAdapter.PROPERTY_PROVIDER_NAME); + + String vm_url = params.get(ProviderAdapter.PROPERTY_INSTANCE_URL); + + VMURL vm = VMURL.parseURL(vm_url); + if (validateVM(rc, appName, vm_url, vm)) return null; + + IdentityURL ident = IdentityURL.parseURL(params.get(ProviderAdapter.PROPERTY_IDENTITY_URL)); + String identStr = (ident == null) ? null : ident.toString(); + + Context context = null; + ctx.setAttribute("START_STATUS", "ERROR"); + try { + context = getContext(rc, vm_url, identStr); + if (context != null) { + rc.reset(); + server = lookupServer(rc, context, vm.getServerId()); + logger.debug(Msg.SERVER_FOUND, vm_url, context.getTenantName(), server.getStatus().toString()); + String msg; + + /* + * We determine what to do based on the current state of the server + */ + + /* + * Pending is a bit of a special case. If we find the server is in a + * pending state, then the provider is in the process of changing state + * of the server. So, lets try to wait a little bit and see if the state + * settles down to one we can deal with. If not, then we have to fail + * the request. + */ + + if (server.getStatus().equals(Server.Status.PENDING)) { + waitForStateChange(rc, server, Server.Status.READY, Server.Status.RUNNING, Server.Status.ERROR, + Server.Status.SUSPENDED, Server.Status.PAUSED, Server.Status.DELETED); + } + + switch (server.getStatus()) { + case DELETED: + // Nothing to do, the server is gone + msg = EELFResourceManager.format(Msg.SERVER_DELETED, server.getName(), server.getId(), + server.getTenantId(), "started"); + logger.error(msg); + // metricsLogger.error(msg); + throw new RequestFailedException("Start Server", msg, HttpStatus.METHOD_NOT_ALLOWED_405, server); + + case RUNNING: + // Nothing to do, the server is already running + logger.info("Server was already running"); + break; + + case ERROR: + // Server is in error state + msg = EELFResourceManager.format(Msg.SERVER_ERROR_STATE, server.getName(), server.getId(), + server.getTenantId(), "start"); + logger.error(msg); + // metricsLogger.error(msg); + throw new RequestFailedException("Start Server", msg, HttpStatus.METHOD_NOT_ALLOWED_405, server); + + case READY: + // Server is stopped attempt to start the server + rc.reset(); + startServer(rc, server); + break; + + case PAUSED: + // if paused, un-pause it + rc.reset(); + unpauseServer(rc, server); + // metricsLogger.info("Server status: PAUSED"); + break; + + case SUSPENDED: + // Attempt to resume the suspended server + rc.reset(); + resumeServer(rc, server); + // metricsLogger.info("Server status: SUSPENDED"); + break; + + default: + // Hmmm, unknown status, should never occur + msg = EELFResourceManager.format(Msg.UNKNOWN_SERVER_STATE, server.getName(), server.getId(), + server.getTenantId(), server.getStatus().name()); + generateEvent(rc, false, msg); + logger.error(msg); + // metricsLogger.error(msg); + throw new RequestFailedException("Start Server", msg, HttpStatus.METHOD_NOT_ALLOWED_405, server); + } + context.close(); + doSuccess(rc); + ctx.setAttribute("START_STATUS", "SUCCESS"); + } + else + { + ctx.setAttribute("START_STATUS", "CONTEXT_NOT_FOUND"); + } + } catch (ResourceNotFoundException e) { + String msg = EELFResourceManager.format(Msg.SERVER_NOT_FOUND, e, vm_url); + logger.error(msg); + doFailure(rc, HttpStatus.NOT_FOUND_404, msg); + } catch (Throwable t) { + String msg = EELFResourceManager.format(Msg.SERVER_OPERATION_EXCEPTION, t, t.getClass().getSimpleName(), + START_SERVICE.toString(), vm_url, context == null ? "Unknown" : context.getTenantName()); + logger.error(msg, t); + doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg); + } + } catch (RequestFailedException e) { + doFailure(rc, e.getStatus(), e.getMessage()); + } + + return server; + } + + @Override + protected ModelObject executeProviderOperation(Map<String, String> params, SvcLogicContext context) throws APPCException { + + setMDC(Operation.START_SERVICE.toString(), "App-C IaaS Adapter:Start", ADAPTER_NAME); + logOperation(Msg.STARTING_SERVER, params, context); + return startServer(params, context); + } +} diff --git a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/StopServer.java b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/StopServer.java new file mode 100644 index 000000000..9429d5654 --- /dev/null +++ b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/StopServer.java @@ -0,0 +1,198 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.adapter.iaas.provider.operation.impl; + +import org.openecomp.appc.Constants; +import org.openecomp.appc.adapter.iaas.ProviderAdapter; +import org.openecomp.appc.adapter.iaas.impl.IdentityURL; +import org.openecomp.appc.adapter.iaas.impl.RequestContext; +import org.openecomp.appc.adapter.iaas.impl.RequestFailedException; +import org.openecomp.appc.adapter.iaas.impl.VMURL; +import org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Outcome; +import org.openecomp.appc.adapter.iaas.provider.operation.impl.base.ProviderServerOperation; +import org.openecomp.appc.exceptions.APPCException; +import org.openecomp.appc.i18n.Msg; +import com.att.cdp.exceptions.ResourceNotFoundException; +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 org.openecomp.sdnc.sli.SvcLogicContext; +import org.glassfish.grizzly.http.util.HttpStatus; + +import java.util.Map; + +import static org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Operation.STOP_SERVICE; +import static org.openecomp.appc.adapter.utils.Constants.ADAPTER_NAME; + + +public class StopServer extends ProviderServerOperation { + + private static final EELFLogger logger = EELFManager.getInstance().getLogger(StopServer.class); + private static EELFLogger metricsLogger = EELFManager.getInstance().getMetricsLogger(); + + /** + * @see org.openecomp.appc.adapter.iaas.ProviderAdapter#stopServer(java.util.Map, org.openecomp.sdnc.sli.SvcLogicContext) + */ + @SuppressWarnings("nls") + public Server stopServer(Map<String, String> params, SvcLogicContext ctx) throws APPCException { + Server server = null; + RequestContext rc = new RequestContext(ctx); + rc.isAlive(); + + String appName = configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME); + + try { + validateParametersExist(params, ProviderAdapter.PROPERTY_INSTANCE_URL, + ProviderAdapter.PROPERTY_PROVIDER_NAME); + + String vm_url = params.get(ProviderAdapter.PROPERTY_INSTANCE_URL); + ctx.setAttribute("STOP_STATUS", "SUCCESS"); + + VMURL vm = VMURL.parseURL(vm_url); + if (validateVM(rc, appName, vm_url, vm)) return null; + + IdentityURL ident = IdentityURL.parseURL(params.get(ProviderAdapter.PROPERTY_IDENTITY_URL)); + String identStr = (ident == null) ? null : ident.toString(); + + Context context = null; + ctx.setAttribute("STOP_STATUS", "ERROR"); + try { + context = getContext(rc, vm_url, identStr); + if (context != null) { + rc.reset(); + server = lookupServer(rc, context, vm.getServerId()); + logger.debug(Msg.SERVER_FOUND, vm_url, context.getTenantName(), server.getStatus().toString()); + + String msg; + /* + * We determine what to do based on the current state of the server + */ + + /* + * Pending is a bit of a special case. If we find the server is in a + * pending state, then the provider is in the process of changing state + * of the server. So, lets try to wait a little bit and see if the state + * settles down to one we can deal with. If not, then we have to fail + * the request. + */ + + if (server.getStatus().equals(Server.Status.PENDING)) { + waitForStateChange(rc, server, Server.Status.READY, Server.Status.RUNNING, Server.Status.ERROR, + Server.Status.SUSPENDED, Server.Status.PAUSED, Server.Status.DELETED); + } + + switch (server.getStatus()) { + case DELETED: + // Nothing to do, the server is gone + msg = EELFResourceManager.format(Msg.SERVER_DELETED, server.getName(), server.getId(), + server.getTenantId(), "stopped"); + generateEvent(rc, false, msg); + logger.error(msg); + metricsLogger.error(msg); + throw new RequestFailedException("Stop Server", msg, HttpStatus.METHOD_NOT_ALLOWED_405, server); + + case RUNNING: + // Attempt to stop the server + rc.reset(); + stopServer(rc, server); + generateEvent(rc, true, Outcome.SUCCESS.toString()); + break; + + case ERROR: + // Server is in error state + msg = EELFResourceManager.format(Msg.SERVER_ERROR_STATE, server.getName(), server.getId(), + server.getTenantId(), "stop"); + generateEvent(rc, false, msg); + logger.error(msg); + metricsLogger.error(msg); + throw new RequestFailedException("Stop Server", msg, HttpStatus.METHOD_NOT_ALLOWED_405, server); + + case READY: + // Nothing to do, the server was already stopped + logger.info("Server was already stopped"); + break; + + case PAUSED: + // if paused, un-pause it and then stop it + rc.reset(); + unpauseServer(rc, server); + rc.reset(); + stopServer(rc, server); + generateEvent(rc, true, Outcome.SUCCESS.toString()); + break; + + case SUSPENDED: + // Attempt to resume the suspended server and after that stop it + rc.reset(); + resumeServer(rc, server); + rc.reset(); + stopServer(rc, server); + generateEvent(rc, true, Outcome.SUCCESS.toString()); + break; + + default: + // Hmmm, unknown status, should never occur + msg = EELFResourceManager.format(Msg.UNKNOWN_SERVER_STATE, server.getName(), server.getId(), + server.getTenantId(), server.getStatus().name()); + generateEvent(rc, false, msg); + logger.error(msg); + metricsLogger.error(msg); + throw new RequestFailedException("Stop Server", msg, HttpStatus.METHOD_NOT_ALLOWED_405, server); + } + context.close(); + doSuccess(rc); + ctx.setAttribute("STOP_STATUS", "SUCCESS"); + msg = EELFResourceManager.format(Msg.SUCCESS_EVENT_MESSAGE, "StopServer", vm_url); + ctx.setAttribute(org.openecomp.appc.Constants.ATTRIBUTE_SUCCESS_MESSAGE, msg); + + }else{ + ctx.setAttribute("STOP_STATUS", "CONTEXT_NOT_FOUND"); + } + } catch (ResourceNotFoundException e) { + String msg = EELFResourceManager.format(Msg.SERVER_NOT_FOUND, e, vm_url); + logger.error(msg); + doFailure(rc, HttpStatus.NOT_FOUND_404, msg); + } catch (Throwable t) { + String msg = EELFResourceManager.format(Msg.SERVER_OPERATION_EXCEPTION, t, t.getClass().getSimpleName(), + STOP_SERVICE.toString(), vm_url, context == null ? "Unknown" : context.getTenantName()); + logger.error(msg, t); + doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg); + } + } catch (RequestFailedException e) { + logger.error(EELFResourceManager.format(Msg.STOP_SERVER_FAILED, appName, "n/a", "n/a", e.getMessage())); + doFailure(rc, e.getStatus(), e.getMessage()); + } + + return server; + } + + @Override + protected ModelObject executeProviderOperation(Map<String, String> params, SvcLogicContext context) throws APPCException { + + setMDC(STOP_SERVICE.toString(), "App-C IaaS Adapter:Stop", ADAPTER_NAME); + logOperation(Msg.STOPPING_SERVER, params, context); + return stopServer(params, context); + } +} diff --git a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/TerminateServer.java b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/TerminateServer.java new file mode 100644 index 000000000..d0deda741 --- /dev/null +++ b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/TerminateServer.java @@ -0,0 +1,248 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.adapter.iaas.provider.operation.impl; + +import org.openecomp.appc.Constants; +import org.openecomp.appc.adapter.iaas.ProviderAdapter; +import org.openecomp.appc.adapter.iaas.impl.IdentityURL; +import org.openecomp.appc.adapter.iaas.impl.RequestContext; +import org.openecomp.appc.adapter.iaas.impl.RequestFailedException; +import org.openecomp.appc.adapter.iaas.impl.VMURL; +import org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Outcome; +import org.openecomp.appc.adapter.iaas.provider.operation.impl.base.ProviderOperation; +import org.openecomp.appc.adapter.iaas.provider.operation.impl.base.ProviderServerOperation; +import org.openecomp.appc.configuration.Configuration; +import org.openecomp.appc.configuration.ConfigurationFactory; +import org.openecomp.appc.exceptions.UnknownProviderException; +import org.openecomp.appc.i18n.Msg; +import com.att.cdp.exceptions.ContextConnectionException; +import com.att.cdp.exceptions.ResourceNotFoundException; +import com.att.cdp.exceptions.ZoneException; +import com.att.cdp.zones.ComputeService; +import com.att.cdp.zones.Context; +import com.att.cdp.zones.Provider; +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 org.openecomp.sdnc.sli.SvcLogicContext; +import org.glassfish.grizzly.http.util.HttpStatus; +import org.slf4j.MDC; + +import java.util.Map; + +import static org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Operation.RESTART_SERVICE; +import static org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Operation.STOP_SERVICE; +import static org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Operation.TERMINATE_SERVICE; +import static org.openecomp.appc.adapter.utils.Constants.ADAPTER_NAME; +import static com.att.eelf.configuration.Configuration.MDC_SERVICE_NAME; + +public class TerminateServer extends ProviderServerOperation { + + private static final EELFLogger logger = EELFManager.getInstance().getLogger(EvacuateServer.class); + + /** + * Start the server and wait for it to enter a running state + * + * @param rc + * The request context that manages the state and recovery of the request for the life of its processing. + * @param server + * The server to be started + * @throws ZoneException + * @throws RequestFailedException + */ + @SuppressWarnings("nls") + private void deleteServer(RequestContext rc, Server server) throws ZoneException, RequestFailedException { + String msg; + Context context = server.getContext(); + Provider provider = context.getProvider(); + ComputeService service = context.getComputeService(); + while (rc.attempt()) { + try { + logger.info("deleting SERVER"); + server.delete(); + break; + } catch (ContextConnectionException e) { + msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(), + context.getTenant().getName(), context.getTenant().getId(), e.getMessage(), + Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()), + Integer.toString(rc.getRetryLimit())); + logger.error(msg, e); + rc.delay(); + } + } + if (rc.isFailed()) { + msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL()); + logger.error(msg); + throw new RequestFailedException("Delete Server", msg, HttpStatus.BAD_GATEWAY_502, server); + } + rc.reset(); + } + + /** + * This method handles the case of restarting a server once we have found the server and have obtained the abstract + * representation of the server via the context (i.e., the "Server" object from the CDP-Zones abstraction). + * + * @param rc + * The request context that manages the state and recovery of the request for the life of its processing. + * @param server + * The server object representing the server we want to operate on + * @throws ZoneException + */ + @SuppressWarnings("nls") + private void terminateServer(RequestContext rc, Server server) throws ZoneException, RequestFailedException { + /* + * Pending is a bit of a special case. If we find the server is in a pending state, then the provider is in the + * process of changing state of the server. So, lets try to wait a little bit and see if the state settles down + * to one we can deal with. If not, then we have to fail the request. + */ + String msg; + if (server.getStatus().equals(Server.Status.PENDING)) { + waitForStateChange(rc, server, Server.Status.READY, Server.Status.RUNNING, Server.Status.ERROR, Server.Status.SUSPENDED, Server.Status.PAUSED); + } + + /* + * We determine what to do based on the current state of the server + */ + switch (server.getStatus()) { + case DELETED: + // Nothing to do, the server is gone + msg = EELFResourceManager.format(Msg.SERVER_DELETED, server.getName(), server.getId(), + server.getTenantId(), "restarted"); + generateEvent(rc, false, msg); + logger.error(msg); + break; + + case RUNNING: + // Attempt to stop and start the server + logger.info("stopping SERVER"); + stopServer(rc, server); + deleteServer(rc, server); + logger.info("after delete SERVER"); + generateEvent(rc, true, Outcome.SUCCESS.toString()); + break; + + case ERROR: + + case READY: + + case PAUSED: + + case SUSPENDED: + // Attempt to delete the suspended server + deleteServer(rc, server); + generateEvent(rc, true, Outcome.SUCCESS.toString()); + break; + + default: + // Hmmm, unknown status, should never occur + msg = EELFResourceManager.format(Msg.UNKNOWN_SERVER_STATE, server.getName(), server.getId(), + server.getTenantId(), server.getStatus().name()); + generateEvent(rc, false, msg); + logger.error(msg); + break; + } + + } + + /** + * This method is used to delete an existing virtual machine given the fully qualified URL of the machine. + * <p> + * The fully qualified URL contains enough information to locate the appropriate server. The URL is of the form + * <pre> + * [scheme]://[host[:port]] / [path] / [tenant_id] / servers / [vm_id] + * </pre> Where the various parts of the URL can be parsed and extracted and used to locate the appropriate service + * in the provider service catalog. This then allows us to open a context using the CDP abstraction, obtain the + * server by its UUID, and then perform the restart. + * </p> + * + * @throws UnknownProviderException + * If the provider cannot be found + * @throws IllegalArgumentException + * if the expected argument(s) are not defined or are invalid + * @see org.openecomp.appc.adapter.iaas.ProviderAdapter#terminateServer(java.util.Map, org.openecomp.sdnc.sli.SvcLogicContext) + */ + @SuppressWarnings("nls") + public Server terminateServer(Map<String, String> params, SvcLogicContext ctx) + throws UnknownProviderException, IllegalArgumentException { + Server server = null; + RequestContext rc = new RequestContext(ctx); + rc.isAlive(); + + String appName = configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME); + + try { + validateParametersExist(params, ProviderAdapter.PROPERTY_INSTANCE_URL, + ProviderAdapter.PROPERTY_PROVIDER_NAME); + + String vm_url = params.get(ProviderAdapter.PROPERTY_INSTANCE_URL); + ctx.setAttribute("TERMINATE_STATUS", "SUCCESS"); + + VMURL vm = VMURL.parseURL(vm_url); + if (validateVM(rc, appName, vm_url, vm)) return null; + + IdentityURL ident = IdentityURL.parseURL(params.get(ProviderAdapter.PROPERTY_IDENTITY_URL)); + String identStr = (ident == null) ? null : ident.toString(); + + Context context = null; + try { + context = getContext(rc, vm_url, identStr); + if (context != null) { + server = lookupServer(rc, context, vm.getServerId()); + logger.debug(Msg.SERVER_FOUND, vm_url, context.getTenantName(), server.getStatus().toString()); + logger.info(EELFResourceManager.format(Msg.TERMINATING_SERVER, server.getName())); + terminateServer(rc, server); + logger.info(EELFResourceManager.format(Msg.TERMINATE_SERVER, server.getName())); + context.close(); + doSuccess(rc); + }else{ + ctx.setAttribute("TERMINATE_STATUS", "SERVER_NOT_FOUND"); + } + } catch (ResourceNotFoundException e) { + String msg = EELFResourceManager.format(Msg.SERVER_NOT_FOUND, e, vm_url); + logger.error(msg); + doFailure(rc, HttpStatus.NOT_FOUND_404, msg); + ctx.setAttribute("TERMINATE_STATUS", "SERVER_NOT_FOUND"); + } catch (Throwable t) { + String msg = EELFResourceManager.format(Msg.SERVER_OPERATION_EXCEPTION, t, t.getClass().getSimpleName(), + RESTART_SERVICE.toString(), vm_url, context == null ? "Unknown" : context.getTenantName()); + logger.error(msg, t); + doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg); + } + } catch (RequestFailedException e) { + logger.error(EELFResourceManager.format(Msg.TERMINATE_SERVER_FAILED, appName, "n/a", "n/a", e.getMessage())); + doFailure(rc, e.getStatus(), e.getMessage()); + ctx.setAttribute("TERMINATE_STATUS", "ERROR"); + } + + return server; + } + + @Override + protected ModelObject executeProviderOperation(Map<String, String> params, SvcLogicContext context) throws UnknownProviderException { + + setMDC(TERMINATE_SERVICE.toString(), "App-C IaaS Adapter:Terminate", ADAPTER_NAME); + logOperation(Msg.TERMINATING_SERVER, params, context); + return terminateServer(params,context); + } +} diff --git a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/TerminateStack.java b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/TerminateStack.java new file mode 100644 index 000000000..220c00d8c --- /dev/null +++ b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/TerminateStack.java @@ -0,0 +1,128 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.adapter.iaas.provider.operation.impl; + +import org.openecomp.appc.Constants; +import org.openecomp.appc.adapter.iaas.ProviderAdapter; +import org.openecomp.appc.adapter.iaas.impl.RequestContext; +import org.openecomp.appc.adapter.iaas.impl.RequestFailedException; +import org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Operation; +import org.openecomp.appc.adapter.iaas.provider.operation.impl.base.ProviderStackOperation; +import org.openecomp.appc.exceptions.APPCException; +import org.openecomp.appc.i18n.Msg; +import com.att.cdp.exceptions.ResourceNotFoundException; +import com.att.cdp.exceptions.ZoneException; +import com.att.cdp.zones.Context; +import com.att.cdp.zones.StackService; +import com.att.cdp.zones.model.ModelObject; +import com.att.cdp.zones.model.Stack; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.att.eelf.i18n.EELFResourceManager; +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.glassfish.grizzly.http.util.HttpStatus; + +import java.util.Map; + +import static org.openecomp.appc.adapter.utils.Constants.ADAPTER_NAME; + +/** + * @since September 26, 2016 + */ +public class TerminateStack extends ProviderStackOperation { + + private static final EELFLogger logger = EELFManager.getInstance().getLogger(EvacuateServer.class); + + private void deleteStack(RequestContext rc, Stack stack) throws ZoneException, RequestFailedException { + SvcLogicContext ctx = rc.getSvcLogicContext(); + Context context = stack.getContext(); + StackService stackService = context.getStackService(); + logger.debug("Deleting Stack: " + "id:{ " + stack.getId() + "}"); + stackService.deleteStack(stack); + + // wait for the stack deletion + boolean success = waitForStackStatus(rc, stack, Stack.Status.DELETED); + if (success) { + ctx.setAttribute("TERMINATE_STATUS", "SUCCESS"); + } else { + ctx.setAttribute("TERMINATE_STATUS", "ERROR"); + throw new RequestFailedException("Delete Stack failure : " + Msg.STACK_OPERATION_EXCEPTION.toString()); + } + } + + @SuppressWarnings("nls") + public Stack terminateStack(Map<String, String> params, SvcLogicContext ctx) throws IllegalArgumentException, APPCException { + Stack stack = null; + RequestContext rc = new RequestContext(ctx); + rc.isAlive(); + + ctx.setAttribute("TERMINATE_STATUS", "STACK_NOT_FOUND"); + String appName = configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME); + + try { + + validateParametersExist(params, ProviderAdapter.PROPERTY_INSTANCE_URL, + ProviderAdapter.PROPERTY_PROVIDER_NAME, ProviderAdapter.PROPERTY_STACK_ID); + + String stackId = params.get(ProviderAdapter.PROPERTY_STACK_ID); + String vm_url = params.get(ProviderAdapter.PROPERTY_INSTANCE_URL); + + Context context = resolveContext(rc, params, appName, vm_url); + + try { + if (context != null) { + rc.reset(); + stack = lookupStack(rc, context, stackId); + logger.debug(Msg.STACK_FOUND, vm_url, context.getTenantName(), stack.getStatus().toString()); + logger.info(EELFResourceManager.format(Msg.TERMINATING_STACK, stack.getName())); + deleteStack(rc, stack); + logger.info(EELFResourceManager.format(Msg.TERMINATE_STACK, stack.getName())); + context.close(); + doSuccess(rc); + String msg = EELFResourceManager.format(Msg.SUCCESS_EVENT_MESSAGE, "TerminateStack", vm_url); + ctx.setAttribute(org.openecomp.appc.Constants.ATTRIBUTE_SUCCESS_MESSAGE, msg); + } + } catch (ResourceNotFoundException e) { + String msg = EELFResourceManager.format(Msg.STACK_NOT_FOUND, e, vm_url); + logger.error(msg); + doFailure(rc, HttpStatus.NOT_FOUND_404, msg); + } catch (Throwable t) { + String msg = EELFResourceManager.format(Msg.STACK_OPERATION_EXCEPTION, t, t.getClass().getSimpleName(), + Operation.TERMINATE_STACK.toString(), vm_url, context.getTenantName()); + logger.error(msg, t); + doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg); + } + } catch (RequestFailedException e) { + logger.error(EELFResourceManager.format(Msg.TERMINATE_STACK_FAILED, appName, "n/a", "n/a")); + doFailure(rc, e.getStatus(), e.getMessage()); + } + return stack; + } + + @Override + protected ModelObject executeProviderOperation(Map<String, String> params, SvcLogicContext context) throws APPCException { + + setMDC(Operation.TERMINATE_STACK.toString(), "App-C IaaS Adapter:Terminate-Stack", ADAPTER_NAME); + logOperation(Msg.TERMINATING_STACK, params, context); + return terminateStack(params, context); + } +} diff --git a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/VmStatuschecker.java b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/VmStatuschecker.java new file mode 100644 index 000000000..0df17caa4 --- /dev/null +++ b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/VmStatuschecker.java @@ -0,0 +1,160 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.adapter.iaas.provider.operation.impl; + +import org.openecomp.appc.Constants; +import org.openecomp.appc.adapter.iaas.ProviderAdapter; +import org.openecomp.appc.adapter.iaas.impl.IdentityURL; +import org.openecomp.appc.adapter.iaas.impl.RequestContext; +import org.openecomp.appc.adapter.iaas.impl.RequestFailedException; +import org.openecomp.appc.adapter.iaas.impl.VMURL; +import org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Operation; +import org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Outcome; +import org.openecomp.appc.adapter.iaas.provider.operation.impl.base.ProviderOperation; +import org.openecomp.appc.adapter.iaas.provider.operation.impl.base.ProviderServerOperation; +import org.openecomp.appc.configuration.Configuration; +import org.openecomp.appc.configuration.ConfigurationFactory; +import org.openecomp.appc.exceptions.UnknownProviderException; +import org.openecomp.appc.i18n.Msg; +import com.att.cdp.exceptions.ResourceNotFoundException; +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 org.openecomp.sdnc.sli.SvcLogicContext; +import org.glassfish.grizzly.http.util.HttpStatus; +import org.slf4j.MDC; + +import java.util.Map; + +import static org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Operation.RESTART_SERVICE; +import static org.openecomp.appc.adapter.utils.Constants.ADAPTER_NAME; +import static com.att.eelf.configuration.Configuration.MDC_SERVICE_NAME; + + +public class VmStatuschecker extends ProviderServerOperation { + + private static final EELFLogger logger = EELFManager.getInstance().getLogger(VmStatuschecker.class); + private static final Configuration configuration = ConfigurationFactory.getConfiguration(); + + /* *********************************************************************************/ + /* DEVEN PANCHAL: This method is used to check the status of the VM */ + /**********************************************************************************/ + public Server vmStatuschecker(Map<String, String> params, SvcLogicContext ctx) throws UnknownProviderException, IllegalArgumentException { + Server server = null; + RequestContext rc = new RequestContext(ctx); + rc.isAlive(); + + String appName = configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME); + + try { + validateParametersExist(params, ProviderAdapter.PROPERTY_INSTANCE_URL, + ProviderAdapter.PROPERTY_PROVIDER_NAME); + + String vm_url = params.get(ProviderAdapter.PROPERTY_INSTANCE_URL); + + VMURL vm = VMURL.parseURL(vm_url); + if (validateVM(rc, appName, vm_url, vm)) return null; + + IdentityURL ident = IdentityURL.parseURL(params.get(ProviderAdapter.PROPERTY_IDENTITY_URL)); + String identStr = (ident == null) ? null : ident.toString(); + + Context context = null; + try { + context = getContext(rc, vm_url, identStr); + if (context != null) { + server = lookupServer(rc, context, vm.getServerId()); + logger.debug(Msg.SERVER_FOUND, vm_url, context.getTenantName(), server.getStatus().toString()); + + String statusvm; + switch (server.getStatus()) { + case DELETED: + statusvm = "deleted"; + break; + + case RUNNING: + statusvm = "running"; + break; + + case ERROR: + statusvm = "error"; + break; + + case READY: + statusvm = "ready"; + break; + + case PAUSED: + statusvm = "paused"; + break; + + case SUSPENDED: + statusvm = "suspended"; + break; + + case PENDING: + statusvm = "pending"; + break; + + default: + statusvm = "default-unknown state-should never occur"; + break; + } + + + String statusofVM = statusvm; + context.close(); + SvcLogicContext svcLogic = rc.getSvcLogicContext(); + svcLogic.setStatus(Outcome.SUCCESS.toString()); + svcLogic.setAttribute("org.openecomp.statusofvm", statusofVM); + svcLogic.setAttribute(Constants.STATUS_OF_VM, statusofVM); + svcLogic.setAttribute(Constants.ATTRIBUTE_ERROR_CODE, Integer.toString(HttpStatus.OK_200.getStatusCode())); + } + } catch (ResourceNotFoundException e) { + String msg = EELFResourceManager.format(Msg.SERVER_NOT_FOUND, e, vm_url); + logger.error(msg); + doFailure(rc, HttpStatus.NOT_FOUND_404, msg); + } catch (Throwable t) { + String msg = EELFResourceManager.format(Msg.SERVER_OPERATION_EXCEPTION, t, t.getClass().getSimpleName(), + RESTART_SERVICE.toString(), vm_url, context == null ? "Unknown" : context.getTenantName()); + logger.error(msg, t); + doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, msg); + } + } catch (RequestFailedException e) { + doFailure(rc, e.getStatus(), e.getMessage()); + } + + return server; + } + + /* *********************************************************************************/ + + @Override + protected ModelObject executeProviderOperation(Map<String, String> params, SvcLogicContext context) throws UnknownProviderException { + + setMDC(Operation.VMSTATUSCHECK_SERVICE.toString(), "App-C IaaS Adapter:VmStatusCheck", ADAPTER_NAME); + logOperation(Msg.CHECKING_SERVER, params, context); + return vmStatuschecker(params, context); + } +} diff --git a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/base/ProviderOperation.java b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/base/ProviderOperation.java new file mode 100644 index 000000000..58753f527 --- /dev/null +++ b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/base/ProviderOperation.java @@ -0,0 +1,457 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.adapter.iaas.provider.operation.impl.base; + +import org.openecomp.appc.adapter.iaas.ProviderAdapter; +import org.openecomp.appc.adapter.iaas.impl.*; +import org.openecomp.appc.adapter.iaas.provider.operation.api.IProviderOperation; +import org.openecomp.appc.adapter.iaas.provider.operation.common.constants.Constants; +import org.openecomp.appc.adapter.iaas.provider.operation.common.enums.Outcome; +import org.openecomp.appc.configuration.Configuration; +import org.openecomp.appc.configuration.ConfigurationFactory; +import org.openecomp.appc.exceptions.APPCException; +import org.openecomp.appc.i18n.Msg; +import org.openecomp.appc.pool.Pool; +import org.openecomp.appc.pool.PoolExtensionException; +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 org.openecomp.sdnc.sli.SvcLogicContext; +import org.glassfish.grizzly.http.util.HttpStatus; +import org.slf4j.MDC; + +import java.net.URI; +import java.util.Map; +import java.util.Set; +import java.util.regex.Pattern; + +import static org.openecomp.appc.adapter.iaas.provider.operation.common.constants.Constants.MDC_ADAPTER; +import static org.openecomp.appc.adapter.iaas.provider.operation.common.constants.Constants.MDC_SERVICE; +import static com.att.eelf.configuration.Configuration.MDC_SERVICE_NAME; + +/** + * @since September 26, 2016 + */ +public abstract class ProviderOperation implements IProviderOperation { + + private static final EELFLogger logger = EELFManager.getInstance().getLogger(ProviderOperation.class); + protected static final Configuration configuration = ConfigurationFactory.getConfiguration(); + + public void setProviderCache(Map<String, ProviderCache> providerCache) { + this.providerCache = providerCache; + } + + /** + * A cache of providers that are predefined. + */ + private Map<String /* provider name */, ProviderCache> providerCache; + + + public void setDefaultUser(String defaultUser) { + DEFAULT_USER = defaultUser; + } + + public void setDefaultPass(String defaultPass) { + DEFAULT_PASS = defaultPass; + } + + /** + * The username and password to use for dynamically created connections + */ + private static String DEFAULT_USER; + private static String DEFAULT_PASS; + + + /** + * set MDC props + * @param service + * @param serviceName + * @param adapterName + */ + 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 + * @param msg + * @param params + * @param context + */ + protected void logOperation(Msg msg, Map<String, String> params, SvcLogicContext context){ + + String appName = configuration.getProperty(org.openecomp.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 (String key : parameters.keySet()) { + logger.debug(Msg.PROPERTY_VALUE, key, parameters.get(key)); + } + } + + /** + * 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. + * @param code + * @param message + */ + protected void doFailure(RequestContext rc, HttpStatus code, String message) { + try { + doFailure(rc, code, message, null); + } catch (APPCException ignored) {/* never happens */} + } + + 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) { + status = "500"; + } + svcLogic.setStatus(Outcome.FAILURE.toString()); + svcLogic.setAttribute(org.openecomp.appc.Constants.ATTRIBUTE_ERROR_CODE, status); + svcLogic.setAttribute(org.openecomp.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.openecomp.appc.Constants.ATTRIBUTE_ERROR_CODE, Integer.toString(HttpStatus.OK_200.getStatusCode())); + } + + protected boolean validateVM(RequestContext rc, String appName, String vm_url, VMURL vm) + throws RequestFailedException { + String msg; + if (vm == null) { + msg = EELFResourceManager.format(Msg.INVALID_SELF_LINK_URL, appName, vm_url); + 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) { + 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()); + // cache.setProviderType("OpenStack"); + + TenantCache tenant = cache.addTenant(vm.getTenantId(),null, DEFAULT_USER, DEFAULT_PASS); + + // 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.openecomp.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,DEFAULT_USER, DEFAULT_PASS); + + 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. + */ + if (context.isStale()) { + context.relogin(); + } + 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; + } + + protected Context resolveContext(RequestContext rc, Map<String, String> params, String appName, String vm_url) + throws RequestFailedException { + + VMURL vm = VMURL.parseURL(vm_url); + if (vm == null) { + String msg = EELFResourceManager.format(Msg.INVALID_SELF_LINK_URL, appName, vm_url); + 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, vm_url, 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); + } +} diff --git a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/base/ProviderServerOperation.java b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/base/ProviderServerOperation.java new file mode 100644 index 000000000..0a27a7ac9 --- /dev/null +++ b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/base/ProviderServerOperation.java @@ -0,0 +1,573 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.adapter.iaas.provider.operation.impl.base; + +import org.openecomp.appc.Constants; +import org.openecomp.appc.adapter.iaas.impl.*; +import org.openecomp.appc.i18n.Msg; +import com.att.cdp.exceptions.ContextConnectionException; +import com.att.cdp.exceptions.NotLoggedInException; +import com.att.cdp.exceptions.TimeoutException; +import com.att.cdp.exceptions.ZoneException; +import com.att.cdp.pal.util.StringHelper; +import com.att.cdp.zones.ComputeService; +import com.att.cdp.zones.Context; +import com.att.cdp.zones.ImageService; +import com.att.cdp.zones.NetworkService; +import com.att.cdp.zones.Provider; +import com.att.cdp.zones.model.Hypervisor; +import com.att.cdp.zones.model.Image; +import com.att.cdp.zones.model.Network; +import com.att.cdp.zones.model.Port; +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 org.glassfish.grizzly.http.util.HttpStatus; +import java.util.ArrayList; +import java.util.List; + +/** + * @since September 29, 2016 + */ +public abstract class ProviderServerOperation extends ProviderOperation{ + + private static final EELFLogger logger = EELFManager.getInstance().getLogger(ProviderServerOperation.class); + + /** + * Looks up the indicated server using the provided context and returns the server to the caller + * + * @param rc + * The request context + * @param context + * The provider context + * @param id + * The id of the server + * @return The server, or null if there is a problem + * @throws ZoneException + * If the server cannot be found + * @throws RequestFailedException + * If the server cannot be found because we cant connect to the provider + */ + @SuppressWarnings("nls") + protected Server lookupServer(RequestContext rc, Context context, String id) + throws ZoneException, RequestFailedException { + ComputeService service = context.getComputeService(); + Server server = null; + String msg; + Provider provider = context.getProvider(); + + while (rc.attempt()) { + try { + server = service.getServer(id); + break; + } catch (ContextConnectionException e) { + msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(), + context.getTenant().getName(), context.getTenant().getId(), e.getMessage(), + Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()), + Integer.toString(rc.getRetryLimit())); + logger.error(msg, e); + rc.delay(); + } + } + if (rc.isFailed()) { + msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL()); + logger.error(msg); + doFailure(rc, HttpStatus.BAD_GATEWAY_502, msg); + throw new RequestFailedException("Lookup Server", msg, HttpStatus.BAD_GATEWAY_502, server); + } + return server; + } + + + + /** + * Resume a suspended server and wait for it to enter a running state + * + * @param rc + * The request context that manages the state and recovery of the request for the life of its processing. + * @param server + * The server to be resumed + * @throws ZoneException + * @throws RequestFailedException + */ + @SuppressWarnings("nls") + protected void resumeServer(RequestContext rc, Server server) throws ZoneException, RequestFailedException { + logger.debug(Msg.RESUME_SERVER, server.getId()); + + Context context = server.getContext(); + String msg; + Provider provider = context.getProvider(); + ComputeService service = context.getComputeService(); + while (rc.attempt()) { + try { + server.resume(); + break; + } catch (ContextConnectionException e) { + msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(), + context.getTenant().getName(), context.getTenant().getId(), e.getMessage(), + Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()), + Integer.toString(rc.getRetryLimit())); + logger.error(msg, e); + rc.delay(); + } + } + if (rc.isFailed()) { + msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL()); + logger.error(msg); + throw new RequestFailedException("Resume Server", msg, HttpStatus.BAD_GATEWAY_502, server); + } + rc.reset(); + waitForStateChange(rc, server, Server.Status.RUNNING); + } + + + protected boolean hasImageAccess(@SuppressWarnings("unused") RequestContext rc, Context context) { + logger.info("Checking permissions for image service."); + try { + ImageService service = context.getImageService(); + service.getImageByName("CHECK_IMAGE_ACCESS"); + logger.info("Image service is accessible."); + return true; + } catch (ZoneException e) { + logger.warn("Image service could not be accessed. Some operations may fail.", e); + return false; + } + } + + + /** + * Enter a pool-wait loop checking the server state to see if it has entered one of the desired states or not. + * <p> + * This method checks the state of the server periodically for one of the desired states. When the server enters one + * of the desired states, the method returns a successful indication (true). If the server never enters one of the + * desired states within the allocated timeout period, then the method returns a failed response (false). No + * exceptions are thrown from this method. + * </p> + * + * @param rc + * The request context that manages the state and recovery of the request for the life of its processing. + * @param image + * The server to wait on + * @param desiredStates + * A variable list of desired states, any one of which is allowed. + * @throws RequestFailedException + * If the request times out or fails for some reason + * @throws NotLoggedInException + */ + @SuppressWarnings("nls") + protected void waitForStateChange(RequestContext rc, Image image, Image.Status... desiredStates) + throws RequestFailedException, NotLoggedInException { + int pollInterval = configuration.getIntegerProperty(Constants.PROPERTY_OPENSTACK_POLL_INTERVAL); + int timeout = configuration.getIntegerProperty(Constants.PROPERTY_SERVER_STATE_CHANGE_TIMEOUT); + Context context = image.getContext(); + Provider provider = context.getProvider(); + ImageService service = context.getImageService(); + String msg; + + long endTime = System.currentTimeMillis() + (timeout * 1000); // + + while (rc.attempt()) { + try { + try { + image.waitForStateChange(pollInterval, timeout, desiredStates); + break; + } catch (TimeoutException e) { + @SuppressWarnings("MismatchedQueryAndUpdateOfCollection") + List<String> list = new ArrayList<>(); + for (Image.Status desiredState : desiredStates) { + list.add(desiredState.name()); + } + msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(), + context.getTenant().getName(), context.getTenant().getId(), e.getMessage(), + Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()), + Integer.toString(rc.getRetryLimit())); + logger.error(msg, e); + rc.delay(); + } + } catch (ZoneException e) { + List<String> list = new ArrayList<>(); + for (Image.Status desiredState : desiredStates) { + list.add(desiredState.name()); + } + String reason = EELFResourceManager.format(Msg.STATE_CHANGE_EXCEPTION, e.getClass().getSimpleName(), + "server", image.getName(), image.getId(), StringHelper.asList(list), image.getStatus().name(), + e.getMessage()); + logger.error(reason); + logger.error(EELFResourceManager.format(e)); + + // Instead of failing we are going to wait and try again. + // Timeout is reduced by delay time + logger.info(String.format("Retrying in %ds", rc.getRetryDelay())); + rc.delay(); + timeout = (int) (endTime - System.currentTimeMillis()) / 1000; + // throw new RequestFailedException(e, operation, reason, + // HttpStatus.BAD_GATEWAY_502, server); + } + } + + if (rc.isFailed()) { + msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL()); + logger.error(msg); + throw new RequestFailedException("Waiting for State Change", msg, HttpStatus.BAD_GATEWAY_502, new Server()); + } + rc.reset(); + } + + + /** + * Enter a pool-wait loop checking the server state to see if it has entered one of the desired states or not. + * <p> + * This method checks the state of the server periodically for one of the desired states. When the server enters one + * of the desired states, the method returns a successful indication (true). If the server never enters one of the + * desired states within the allocated timeout period, then the method returns a failed response (false). No + * exceptions are thrown from this method. + * </p> + * + * @param rc + * The request context that manages the state and recovery of the request for the life of its processing. + * @param server + * The server to wait on + * @param desiredStates + * A variable list of desired states, any one of which is allowed. + * @throws RequestFailedException + * If the request times out or fails for some reason + */ + @SuppressWarnings("nls") + protected void waitForStateChange(RequestContext rc, Server server, Server.Status... desiredStates) + throws RequestFailedException { + int pollInterval = configuration.getIntegerProperty(Constants.PROPERTY_OPENSTACK_POLL_INTERVAL); + int timeout = configuration.getIntegerProperty(Constants.PROPERTY_SERVER_STATE_CHANGE_TIMEOUT); + Context context = server.getContext(); + Provider provider = context.getProvider(); + ComputeService service = context.getComputeService(); + String msg; + + long endTime = System.currentTimeMillis() + (timeout * 1000); // + + while (rc.attempt()) { + try { + try { + server.waitForStateChange(pollInterval, timeout, desiredStates); + break; + } catch (TimeoutException e) { + @SuppressWarnings("MismatchedQueryAndUpdateOfCollection") + List<String> list = new ArrayList<>(); + for (Server.Status desiredState : desiredStates) { + list.add(desiredState.name()); + } + msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(), + context.getTenant().getName(), context.getTenant().getId(), e.getMessage(), + Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()), + Integer.toString(rc.getRetryLimit())); + logger.error(msg, e); + rc.delay(); + } + } catch (ZoneException e) { + List<String> list = new ArrayList<>(); + for (Server.Status desiredState : desiredStates) { + list.add(desiredState.name()); + } + String reason = EELFResourceManager.format(Msg.STATE_CHANGE_EXCEPTION, e.getClass().getSimpleName(), + "server", server.getName(), server.getId(), StringHelper.asList(list), server.getStatus().name(), + e.getMessage()); + logger.error(reason); + logger.error(EELFResourceManager.format(e)); + + // Instead of failing we are going to wait and try again. + // Timeout is reduced by delay time + logger.info(String.format("Retrying in %ds", rc.getRetryDelay())); + rc.delay(); + timeout = (int) (endTime - System.currentTimeMillis()) / 1000; + // throw new RequestFailedException(e, operation, reason, + // HttpStatus.BAD_GATEWAY_502, server); + } + } + + if (rc.isFailed()) { + msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL()); + logger.error(msg); + throw new RequestFailedException("Waiting for State Change", msg, HttpStatus.BAD_GATEWAY_502, server); + } + rc.reset(); + } + + /** + * Stop the specified server and wait for it to stop + * + * @param rc + * The request context that manages the state and recovery of the request for the life of its processing. + * @param server + * The server to be stopped + * @throws ZoneException + * @throws RequestFailedException + */ + @SuppressWarnings("nls") + protected void stopServer(RequestContext rc, Server server) throws ZoneException, RequestFailedException { + logger.debug(Msg.STOP_SERVER, server.getId()); + + String msg; + Context context = server.getContext(); + Provider provider = context.getProvider(); + ComputeService service = context.getComputeService(); + while (rc.attempt()) { + try { + server.stop(); + break; + } catch (ContextConnectionException e) { + msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(), + context.getTenant().getName(), context.getTenant().getId(), e.getMessage(), + Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()), + Integer.toString(rc.getRetryLimit())); + logger.error(msg, e); + rc.delay(); + } + } + if (rc.isFailed()) { + msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL()); + logger.error(msg); + throw new RequestFailedException("Stop Server", msg, HttpStatus.BAD_GATEWAY_502, server); + } + rc.reset(); + waitForStateChange(rc, server, Server.Status.READY, Server.Status.ERROR); + } + + /** + * Start the server and wait for it to enter a running state + * + * @param rc + * The request context that manages the state and recovery of the request for the life of its processing. + * @param server + * The server to be started + * @throws ZoneException + * @throws RequestFailedException + */ + @SuppressWarnings("nls") + protected void startServer(RequestContext rc, Server server) throws ZoneException, RequestFailedException { + logger.debug(Msg.START_SERVER, server.getId()); + String msg; + Context context = server.getContext(); + Provider provider = context.getProvider(); + ComputeService service = context.getComputeService(); + while (rc.attempt()) { + try { + server.start(); + break; + } catch (ContextConnectionException e) { + msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(), + context.getTenant().getName(), context.getTenant().getId(), e.getMessage(), + Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()), + Integer.toString(rc.getRetryLimit())); + logger.error(msg, e); + rc.delay(); + } + } + if (rc.isFailed()) { + msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL()); + logger.error(msg); + throw new RequestFailedException("Start Server", msg, HttpStatus.BAD_GATEWAY_502, server); + } + rc.reset(); + waitForStateChange(rc, server, Server.Status.RUNNING); + } + + + /** + * Un-Pause a paused server and wait for it to enter a running state + * + * @param rc + * The request context that manages the state and recovery of the request for the life of its processing. + * @param server + * The server to be un-paused + * @throws ZoneException + * @throws RequestFailedException + */ + @SuppressWarnings("nls") + protected void unpauseServer(RequestContext rc, Server server) throws ZoneException, RequestFailedException { + logger.debug(Msg.UNPAUSE_SERVER, server.getId()); + + String msg; + Context context = server.getContext(); + Provider provider = context.getProvider(); + ComputeService service = context.getComputeService(); + while (rc.attempt()) { + try { + server.unpause(); + break; + } catch (ContextConnectionException e) { + msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(), + context.getTenant().getName(), context.getTenant().getId(), e.getMessage(), + Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()), + Integer.toString(rc.getRetryLimit())); + logger.error(msg, e); + rc.delay(); + } + } + if (rc.isFailed()) { + msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL()); + logger.error(msg); + throw new RequestFailedException("Unpause Server", msg, HttpStatus.BAD_GATEWAY_502, server); + } + rc.reset(); + waitForStateChange(rc, server, Server.Status.RUNNING, Server.Status.READY); + } + + + /** + * Generates the event indicating what happened + * + * @param rc + * The request context that manages the state and recovery of the request for the life of its processing. + * @param success + * True if the event represents a successful outcome + * @param msg + * The detailed message + */ + protected void generateEvent(@SuppressWarnings("unused") RequestContext rc, @SuppressWarnings("unused") boolean success, @SuppressWarnings("unused") String msg) { + // indication to the DG to generate the event? + } + + /** + * Checks if the VM is connected to the Virtual Network and reachable + * + * @param rc + * The request context that manages the state and recovery of the request for the life of its processing. + * @param server + * The server object representing the server we want to operate on + * @param context + * The interface cloud service provider to access services or the object model, or both + + */ + protected void checkVirtualMachineNetworkStatus(RequestContext rc, Server server, Context context) + throws ZoneException, RequestFailedException { + + logger.info("Performing the VM Server networking status checks..."); + List<Port> ports = server.getPorts(); + + NetworkService netSvc = context.getNetworkService(); + + String msg; + for (Port port : ports) { + + switch (port.getPortState().toString().toUpperCase()) { + /** + * The port is connected, configured, and usable for communication + */ + case "ONLINE": + Network network = netSvc.getNetworkById(port.getNetwork()); + // Subnet subnet = netSvc.getSubnetById(port.getSubnetId()); + if (!network.getStatus().equals(Network.Status.ACTIVE.toString())) { + msg = EELFResourceManager.format(Msg.SERVER_NETWORK_ERROR, server.getName(), port.getId()); + logger.error(msg); + doFailure(rc, HttpStatus.PRECONDITION_FAILED_412, msg); + throw new RequestFailedException("VM Server Network is DOWN", msg.toString(), HttpStatus.PRECONDITION_FAILED_412, + server); + } + break; + + /** + * The port is disconnected or powered-off and cannot be used for + * communication + */ + case "OFFLINE": + msg = EELFResourceManager.format(Msg.SERVER_NETWORK_ERROR, server.getName(), port.getId()); + logger.error(msg); + doFailure(rc, HttpStatus.PRECONDITION_FAILED_412, msg); + throw new RequestFailedException("VM Server Port status is OFFLINE", msg.toString(), HttpStatus.PRECONDITION_FAILED_412, + server); + + /** + * The port's status is changing because of some event or operation. + * The final state is yet to be determined. + */ + case "PENDING": + msg = EELFResourceManager.format(Msg.SERVER_NETWORK_ERROR, server.getName(), port.getId()); + logger.error(msg); + doFailure(rc, HttpStatus.PRECONDITION_FAILED_412, msg); + throw new RequestFailedException("VM Server Port status is PENDING", msg.toString(), HttpStatus.PRECONDITION_FAILED_412, + server); + + /** + * The port is in an unknown state and cannot be used. + */ + case "UNKNOWN": + msg = EELFResourceManager.format(Msg.SERVER_NETWORK_ERROR, server.getName(), port.getId()); + logger.error(msg); + doFailure(rc, HttpStatus.PRECONDITION_FAILED_412, msg); + throw new RequestFailedException("VM Server Port status is UNKNOWN", msg.toString(), HttpStatus.PRECONDITION_FAILED_412, + server); + } + + } + logger.info("Passed the VM Server the Hypervisor status checks.."); + + } + + /** + * Checks if the VM is connected to the Virtual Network and reachable + * + * @param server + * The server object representing the server we want to operate on + */ + protected void checkHypervisor(Server server) + throws ZoneException, RequestFailedException { + + logger.info("Performing the Hypervisor status checks.."); + String status = null, state = null, msg = null; + + status = server.getHypervisor().getStatus().toString(); + state = server.getHypervisor().getState().toString(); + + if (!status.equals(Hypervisor.Status.ENABLED.toString()) || !state.equals(Hypervisor.State.UP.toString())) { + msg = EELFResourceManager.format(Msg.HYPERVISOR_DOWN_ERROR, server.getHypervisor().getHostName(), server.getName()); + logger.error(msg.toString()); + + //doFailure(rc, HttpStatus.PRECONDITION_FAILED_412, msg); + throw new RequestFailedException("Hypervisor status DOWN or NOT ENABLED", msg.toString(), HttpStatus.PRECONDITION_FAILED_412, + server); + + } + + logger.info("Passed the Hypervisor status checks.."); + + } + + /** + * Checks if a Host machine is reachable + * + * @param ipAddress + * IP Address of the Host Machine. + * @param server + * The server object representing the Virtual Machine server + * @return boolean + * + */ + /*private boolean isHostReachable(String ipAddress) throws IOException { + + InetAddress address = InetAddress.getByName(ipAddress); + + return address.isReachable(15000); + + + }*/ + +} diff --git a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/base/ProviderStackOperation.java b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/base/ProviderStackOperation.java new file mode 100644 index 000000000..2eb2b69cf --- /dev/null +++ b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/iaas/provider/operation/impl/base/ProviderStackOperation.java @@ -0,0 +1,186 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.adapter.iaas.provider.operation.impl.base; + +import org.openecomp.appc.Constants; +import org.openecomp.appc.adapter.iaas.impl.RequestContext; +import org.openecomp.appc.adapter.iaas.impl.RequestFailedException; +import org.openecomp.appc.adapter.openstack.heat.StackResource; +import org.openecomp.appc.i18n.Msg; +import com.att.cdp.exceptions.ContextConnectionException; +import com.att.cdp.exceptions.ResourceNotFoundException; +import com.att.cdp.exceptions.TimeoutException; +import com.att.cdp.exceptions.ZoneException; +import com.att.cdp.zones.Context; +import com.att.cdp.zones.Provider; +import com.att.cdp.zones.StackService; +import com.att.cdp.zones.model.Stack; +import com.att.cdp.zones.spi.AbstractService; +import com.att.cdp.zones.spi.RequestState; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.att.eelf.i18n.EELFResourceManager; +import org.openecomp.sdnc.sli.SvcLogicContext; +import com.woorea.openstack.base.client.OpenStackBaseException; +import org.glassfish.grizzly.http.util.HttpStatus; + +import java.util.List; + +/** + * @since September 29, 2016 + */ +public abstract class ProviderStackOperation extends ProviderOperation{ + + private static final EELFLogger logger = EELFManager.getInstance().getLogger(ProviderStackOperation.class); + + + protected void trackRequest(Context context, AbstractService.State... states) { + RequestState.clear(); + + if (null == states) return; + for (AbstractService.State state : states) { + RequestState.put(state.getName(), state.getValue()); + } + + Thread currentThread = Thread.currentThread(); + StackTraceElement[] stack = currentThread.getStackTrace(); + if (stack != null && stack.length > 0) { + int index = 0; + StackTraceElement element; + for (; index < stack.length; index++) { + element = stack[index]; + if ("trackRequest".equals(element.getMethodName())) { //$NON-NLS-1$ + break; + } + } + index++; + + if (index < stack.length) { + element = stack[index]; + RequestState.put(RequestState.METHOD, element.getMethodName()); + RequestState.put(RequestState.CLASS, element.getClassName()); + RequestState.put(RequestState.LINE_NUMBER, Integer.toString(element.getLineNumber())); + RequestState.put(RequestState.THREAD, currentThread.getName()); + RequestState.put(RequestState.PROVIDER, context.getProvider().getName()); + RequestState.put(RequestState.TENANT, context.getTenantName()); + RequestState.put(RequestState.PRINCIPAL, context.getPrincipal()); + } + } + } + + private boolean checkStatus(String expectedStatus, int pollInterval, String actualStatus) { + if (actualStatus.toUpperCase().equals(expectedStatus)) { + return true; + } else { + try { + Thread.sleep(pollInterval * 1000); + } catch (InterruptedException ignored) { + } + } + return false; + } + + protected boolean waitForStack(Stack stack, StackResource stackResource, String expectedStatus) + throws OpenStackBaseException, TimeoutException { + int pollInterval = configuration.getIntegerProperty(Constants.PROPERTY_OPENSTACK_POLL_INTERVAL); + int timeout = configuration.getIntegerProperty(Constants.PROPERTY_STACK_STATE_CHANGE_TIMEOUT); + long maxTimeToWait = System.currentTimeMillis() + (long) timeout * 1000; + + while (System.currentTimeMillis() < maxTimeToWait) { + String stackStatus = stackResource.show(stack.getName(), stack.getId()).execute().getStackStatus(); + logger.debug("Stack status : " + stackStatus); + if (stackStatus.toUpperCase().contains("FAILED")) return false; + if(checkStatus(expectedStatus, pollInterval, stackStatus)) return true; + } + throw new TimeoutException("Timeout waiting for stack status change"); + } + + protected Stack lookupStack(RequestContext rc, Context context, String id) + throws ZoneException, RequestFailedException { + StackService stackService = context.getStackService(); + Stack stack = null; + String msg; + Provider provider = context.getProvider(); + while (rc.attempt()) { + try { + List<Stack> stackList = stackService.getStacks(); + for (Stack stackObj : stackList) { + if (stackObj.getId().equals(id)) { + stack = stackObj; + break; + } + } + break; + } catch (ContextConnectionException e) { + msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), stackService.getURL(), + context.getTenant().getName(), context.getTenant().getId(), e.getMessage(), + Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()), + Integer.toString(rc.getRetryLimit())); + logger.error(msg, e); + rc.delay(); + } + + } + if (rc.isFailed()) { + msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), stackService.getURL()); + logger.error(msg); + doFailure(rc, HttpStatus.BAD_GATEWAY_502, msg); + throw new RequestFailedException("Lookup Stack", msg, HttpStatus.BAD_GATEWAY_502, stack); + } + + if (stack == null) { + throw new ResourceNotFoundException("Stack not found with Id : {" + id + "}"); + } + return stack; + } + + + protected boolean waitForStackStatus(RequestContext rc, Stack stack, Stack.Status expectedStatus) throws ZoneException, RequestFailedException { + SvcLogicContext ctx = rc.getSvcLogicContext(); + Context context = stack.getContext(); + StackService stackService = context.getStackService(); + + int pollInterval = configuration.getIntegerProperty(Constants.PROPERTY_OPENSTACK_POLL_INTERVAL); + int timeout = configuration.getIntegerProperty(Constants.PROPERTY_STACK_STATE_CHANGE_TIMEOUT); + long maxTimeToWait = System.currentTimeMillis() + (long) timeout * 1000; + Stack.Status stackStatus; + while (System.currentTimeMillis() < maxTimeToWait) { + stackStatus = stackService.getStack(stack.getName(), stack.getId()).getStatus(); + logger.debug("Stack status : " + stackStatus.toString()); + if (stackStatus == expectedStatus) { + return true; + } else if (stackStatus == Stack.Status.FAILED) { + return false; + } else { + try { + Thread.sleep(pollInterval * 1000); + } catch (InterruptedException e) { + logger.trace("Sleep threw interrupted exception, should never occur"); + } + } + } + + ctx.setAttribute("TERMINATE_STATUS", "ERROR"); + throw new TimeoutException("Timeout waiting for stack status change"); + + } +} diff --git a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/utils/Constants.java b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/utils/Constants.java new file mode 100644 index 000000000..7d896c451 --- /dev/null +++ b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/main/java/org/openecomp/appc/adapter/utils/Constants.java @@ -0,0 +1,31 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.adapter.utils; + + +public class Constants { + + /** + * The name of the adapter + */ + public static final String ADAPTER_NAME = "Appc IaaS Adapter"; +} diff --git a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/test/java/org/openecomp/appc/adapter/iaas/impl/TestProviderAdapterImpl.java b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/test/java/org/openecomp/appc/adapter/iaas/impl/TestProviderAdapterImpl.java index d83c18b04..abf35db39 100644 --- a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/test/java/org/openecomp/appc/adapter/iaas/impl/TestProviderAdapterImpl.java +++ b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/test/java/org/openecomp/appc/adapter/iaas/impl/TestProviderAdapterImpl.java @@ -259,13 +259,12 @@ public class TestProviderAdapterImpl { * If the identity service is not available or cannot be created * @throws IOException * if an I/O error occurs - * @throws UnknownProviderException - * If the provider cannot be found + * @throws APPCException */ // @Ignore @Test public void testRestartRunningServer() - throws IllegalStateException, IllegalArgumentException, ZoneException, UnknownProviderException, IOException { + throws IllegalStateException, IllegalArgumentException, ZoneException, IOException, APPCException { Properties properties = new Properties(); properties.setProperty(ContextFactory.PROPERTY_IDENTITY_URL, IDENTITY_URL); properties.setProperty(ContextFactory.PROPERTY_REGION, REGION_NAME); @@ -350,15 +349,14 @@ public class TestProviderAdapterImpl { * or are invalid. * @throws IllegalStateException * If the identity service is not available or cannot be created - * @throws UnknownProviderException - * If the provider cannot be found * @throws IOException * if an I/O error occurs + * @throws APPCException */ // @Ignore @Test public void testRestartStoppedServer() - throws IllegalStateException, IllegalArgumentException, ZoneException, UnknownProviderException, IOException { + throws IllegalStateException, IllegalArgumentException, ZoneException, IOException, APPCException { Properties properties = new Properties(); properties.setProperty(ContextFactory.PROPERTY_IDENTITY_URL, IDENTITY_URL); properties.setProperty(ContextFactory.PROPERTY_REGION, REGION_NAME); diff --git a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/test/java/org/openecomp/appc/adapter/iaas/impl/TestProviderAdapterImplNoConnection.java b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/test/java/org/openecomp/appc/adapter/iaas/impl/TestProviderOperation.java index d4683aa80..f9b571320 100644 --- a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/test/java/org/openecomp/appc/adapter/iaas/impl/TestProviderAdapterImplNoConnection.java +++ b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/test/java/org/openecomp/appc/adapter/iaas/impl/TestProviderOperation.java @@ -19,41 +19,43 @@ * ============LICENSE_END========================================================= */ - - package org.openecomp.appc.adapter.iaas.impl; import java.lang.reflect.Field; +import java.util.Map; +import org.openecomp.appc.adapter.iaas.provider.operation.impl.base.ProviderOperation; +import org.openecomp.appc.exceptions.APPCException; +import com.att.cdp.zones.model.ModelObject; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; -import org.openecomp.appc.adapter.iaas.impl.ProviderAdapterImpl; -import org.openecomp.appc.adapter.iaas.impl.RequestContext; -import org.openecomp.appc.adapter.iaas.impl.RequestFailedException; -import org.openecomp.appc.adapter.iaas.impl.VMURL; +import org.slf4j.MDC; + import org.openecomp.appc.configuration.ConfigurationFactory; import org.openecomp.sdnc.sli.SvcLogicContext; -import org.slf4j.MDC; + +import static org.openecomp.appc.adapter.iaas.provider.operation.common.constants.Constants.MDC_SERVICE; /** * This class is used to test methods and functions of the adapter implementation that do not require and do not set up * connections to any providers. + * + * @since Jan 20, 2016 + * @version $Id$ */ -public class TestProviderAdapterImplNoConnection { +public class TestProviderOperation extends ProviderOperation{ private static Class<?> providerAdapterImplClass; private static Class<?> configurationFactoryClass; private static Field providerCacheField; private static Field configField; - private ProviderAdapterImpl adapter; - /** * Use reflection to locate fields and methods so that they can be manipulated during the test to change the * internal state accordingly. - * + * * @throws NoSuchFieldException * if the field(s) dont exist * @throws SecurityException @@ -75,96 +77,93 @@ public class TestProviderAdapterImplNoConnection { } /** - * initialize the test cases - */ - @Before - public void setup() { - adapter = new ProviderAdapterImpl(false); - } - - /** * This test expects a failure because the value to be validated is a null URL - * + * * @throws RequestFailedException * Expected */ @SuppressWarnings("nls") @Test(expected = RequestFailedException.class) public void testValidateParameterPatternExpectFailNullValue() throws RequestFailedException { - MDC.put(ProviderAdapterImpl.MDC_SERVICE, "junit"); + MDC.put(MDC_SERVICE, "junit"); SvcLogicContext svcContext = new SvcLogicContext(); RequestContext rc = new RequestContext(svcContext); String link = null; - adapter.validateVMURL(VMURL.parseURL(link)); + validateVMURL(VMURL.parseURL(link)); } /** * This test expects a failure because the value to be validated is an empty URL - * + * * @throws RequestFailedException * Expected */ @SuppressWarnings("nls") @Test(expected = RequestFailedException.class) public void testValidateParameterPatternExpectFailEmptyValue() throws RequestFailedException { - MDC.put(ProviderAdapterImpl.MDC_SERVICE, "junit"); + MDC.put(MDC_SERVICE, "junit"); SvcLogicContext svcContext = new SvcLogicContext(); RequestContext rc = new RequestContext(svcContext); String link = ""; - adapter.validateVMURL(VMURL.parseURL(link)); + validateVMURL(VMURL.parseURL(link)); } /** * This test expects a failure because the value to be validated is a blank URL - * + * * @throws RequestFailedException * Expected */ @SuppressWarnings("nls") @Test(expected = RequestFailedException.class) public void testValidateParameterPatternExpectFailBlankValue() throws RequestFailedException { - MDC.put(ProviderAdapterImpl.MDC_SERVICE, "junit"); + MDC.put(MDC_SERVICE, "junit"); SvcLogicContext svcContext = new SvcLogicContext(); RequestContext rc = new RequestContext(svcContext); String link = " "; - adapter.validateVMURL(VMURL.parseURL(link)); + validateVMURL(VMURL.parseURL(link)); } /** * This test expects a failure because the value to be validated is a bad URL - * + * * @throws RequestFailedException * Expected */ @SuppressWarnings("nls") @Test(expected = RequestFailedException.class) public void testValidateParameterPatternExpectFailBadURL() throws RequestFailedException { - MDC.put(ProviderAdapterImpl.MDC_SERVICE, "junit"); + MDC.put(MDC_SERVICE, "junit"); SvcLogicContext svcContext = new SvcLogicContext(); RequestContext rc = new RequestContext(svcContext); String link = "http://some.host:1234/01d82c08594a4b23a0f9260c94be0c4d/"; - adapter.validateVMURL(VMURL.parseURL(link)); + validateVMURL(VMURL.parseURL(link)); } /** * This test expects to pass - * + * * @throws RequestFailedException * Un-Expected */ @SuppressWarnings("nls") @Test public void testValidateParameterPatternValidURL() throws RequestFailedException { - MDC.put(ProviderAdapterImpl.MDC_SERVICE, "junit"); + MDC.put(MDC_SERVICE, "junit"); SvcLogicContext svcContext = new SvcLogicContext(); RequestContext rc = new RequestContext(svcContext); String link = "http://some.host:1234/v2/01d82c08594a4b23a0f9260c94be0c4d/servers/f888f89f-096b-421e-ba36-34f714071551"; - adapter.validateVMURL(VMURL.parseURL(link)); + validateVMURL(VMURL.parseURL(link)); + } + + @Override + protected ModelObject executeProviderOperation(Map<String, String> params, SvcLogicContext context) throws APPCException { + return null; } } diff --git a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/test/java/org/openecomp/appc/adapter/iaas/impl/TestVMURL.java b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/test/java/org/openecomp/appc/adapter/iaas/impl/TestVMURL.java index 852bb4137..d99f89b29 100644 --- a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/test/java/org/openecomp/appc/adapter/iaas/impl/TestVMURL.java +++ b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-bundle/src/test/java/org/openecomp/appc/adapter/iaas/impl/TestVMURL.java @@ -43,11 +43,10 @@ public class TestVMURL { @BeforeClass public static void before() { - Properties props = ConfigurationFactory.getConfiguration().getProperties(); - IP = props.getProperty("test.ip"); - PORT = props.getProperty("test.port"); - TENANTID = props.getProperty("test.tenantid"); - VMID = props.getProperty("test.vmid"); + IP = "192.168.1.2"; + PORT = "5000"; + TENANTID = "abcde12345fghijk6789lmnopq123rst"; + VMID = "abc12345-1234-5678-890a-abcdefg12345"; URL = String.format("http://%s:%s/v2/%s/servers/%s", IP, PORT, TENANTID, VMID); } diff --git a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-features/pom.xml b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-features/pom.xml index aef1e03f6..4a58e9072 100644 --- a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-features/pom.xml +++ b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-features/pom.xml @@ -19,12 +19,6 @@ </dependency> <dependency> - <groupId>commons-lang</groupId> - <artifactId>commons-lang</artifactId> - <scope>compile</scope> - </dependency> - - <dependency> <groupId>org.opendaylight.mdsal</groupId> <artifactId>features-mdsal</artifactId> <classifier>features</classifier> @@ -39,13 +33,6 @@ <type>zip</type> </dependency> -<!-- <dependency> --> -<!-- Required for launching the feature tests --> -<!-- <groupId>org.opendaylight.yangtools</groupId> --> -<!-- <artifactId>features-test</artifactId> --> -<!-- <scope>test</scope> --> -<!-- </dependency> --> - <dependency> <groupId>org.opendaylight.yangtools</groupId> <artifactId>features-yangtools</artifactId> diff --git a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-features/src/main/resources/features.xml b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-features/src/main/resources/features.xml index 5ca8f8ebd..40fcce680 100644 --- a/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-features/src/main/resources/features.xml +++ b/appc-adapters/appc-iaas-adapter/appc-iaas-adapter-features/src/main/resources/features.xml @@ -27,14 +27,16 @@ <!-- <repository>mvn:org.opendaylight.mdsal/features-mdsal/${odl.mdsal.version}/xml/features</repository> --> <repository>mvn:org.opendaylight.mdsal/features-mdsal/${odl.mdsal.features.version}/xml/features</repository> +<!-- <repository>mvn:org.ops4j.pax.web/pax-web-features/6.0.3/xml/features</repository> --> <feature name='appc-iaas-adapter' description="appc-iaas-adapter" version='${project.version}'> <!-- Most applications will have a dependency on the ODL MD-SAL Broker --> -<!-- <feature version="${broker-mdsal.version}">odl-mdsal-broker</feature> --> +<!-- <feature>pax-jetty</feature> --> <feature version="${broker-mdsal.version}">odl-mdsal-broker</feature> <feature>sdnc-sli</feature> <bundle>mvn:org.openecomp.appc/appc-iaas-adapter-bundle/${project.version}</bundle> + </feature> </features> diff --git a/appc-adapters/appc-netconf-adapter/appc-netconf-adapter-bundle/pom.xml b/appc-adapters/appc-netconf-adapter/appc-netconf-adapter-bundle/pom.xml index 766a19314..19f9ebb72 100644 --- a/appc-adapters/appc-netconf-adapter/appc-netconf-adapter-bundle/pom.xml +++ b/appc-adapters/appc-netconf-adapter/appc-netconf-adapter-bundle/pom.xml @@ -22,11 +22,11 @@ <artifactId>appc-common</artifactId> <version>${project.version}</version> </dependency> - <dependency> - <groupId>org.openecomp.appc</groupId> - <artifactId>appc-dmaap-adapter-bundle</artifactId> - <version>${project.version}</version> - </dependency> +<!-- <dependency> --> +<!-- <groupId>org.openecomp.appc</groupId> --> +<!-- <artifactId>appc-dmaap-adapter-bundle</artifactId> --> +<!-- <version>${project.version}</version> --> +<!-- </dependency> --> <dependency> <groupId>javax</groupId> @@ -159,6 +159,11 @@ <groupId>org.json</groupId> <artifactId>json</artifactId> </dependency> + <dependency> + <groupId>com.jcraft</groupId> + <artifactId>jsch</artifactId> + <version>0.1.54</version> + </dependency> </dependencies> @@ -174,13 +179,13 @@ <Bundle-Activator>org.openecomp.appc.adapter.netconf.AppcNetconfAdapterActivator</Bundle-Activator> <Export-Package>org.openecomp.appc.adapter.netconf,org.openecomp.appc.adapter.netconf.dao,org.openecomp.appc.adapter.netconf.util,org.openecomp.appc.adapter.netconf.exception</Export-Package> <Import-Package> - org.w3c.dom.*,com.sun.org.apache.xerces.*,javax.sql.*,javax.sql.rowset.*,javax.xml.*,org.openecomp.appc.adapter.dmaap.*,javax.crypto.*,org.openecomp.appc.common.exception.*,com.mysql.*,org.openecomp.sdnc.sli.*,org.osgi.framework.*,org.slf4j.*,com.vmware.*,org.apache.xerces.*,javax.net.*,javax.net.ssl.*,org.xml.sax.*,javax.xml.bind.*,javax.naming.* + !org.slf4j.event,org.w3c.dom.*,com.sun.org.apache.xerces.*,javax.sql.*,javax.sql.rowset.*,javax.xml.*,org.openecomp.appc.adapter.messaging.*,javax.crypto.*,org.openecomp.appc.common.exception.*,com.mysql.*,org.openecomp.sdnc.sli.*,org.osgi.framework.*,org.slf4j.*,com.vmware.*,org.apache.xerces.*,javax.net.*,javax.net.ssl.*,org.xml.sax.*,javax.xml.bind.*,javax.naming.* </Import-Package> <Embed-Dependency>*;scope=compile|runtime;artifactId=!sli-common|dblib-provider|org.eclipse.osgi|slf4j-api|jcl-over-slf4j|mysql-connector-java|xml-apis|appc-dmaap-adapter-bundle</Embed-Dependency> <Embed-Transitive>true</Embed-Transitive> </instructions> - <manifestLocation>${project.basedir}/src/main/resources/META-INF</manifestLocation> +<!-- <manifestLocation>${project.basedir}/src/main/resources/META-INF</manifestLocation> --> </configuration> </plugin> </plugins> diff --git a/appc-adapters/appc-netconf-adapter/appc-netconf-adapter-bundle/src/main/java/org/openecomp/appc/adapter/netconf/util/Constants.java b/appc-adapters/appc-netconf-adapter/appc-netconf-adapter-bundle/src/main/java/org/openecomp/appc/adapter/netconf/util/Constants.java index 92141e1b7..93d27babf 100644 --- a/appc-adapters/appc-netconf-adapter/appc-netconf-adapter-bundle/src/main/java/org/openecomp/appc/adapter/netconf/util/Constants.java +++ b/appc-adapters/appc-netconf-adapter/appc-netconf-adapter-bundle/src/main/java/org/openecomp/appc/adapter/netconf/util/Constants.java @@ -59,6 +59,7 @@ public class Constants { public static final String VNF_HOST_IP_ADDRESS_FIELD_NAME = "vnf-host-ip-address"; public static final String DG_ERROR_FIELD_NAME = "org.openecomp.appc.dg.error"; public static final String RESOURCEKEY = "resourceKey"; + public static final String ATTRIBUTE_ERROR_MESSAGE = "error-message"; public static final String DG_OUTPUT_STATUS_MESSAGE = "output.status.message"; } diff --git a/appc-adapters/appc-netconf-adapter/appc-netconf-adapter-features/src/main/resources/features.xml b/appc-adapters/appc-netconf-adapter/appc-netconf-adapter-features/src/main/resources/features.xml index 3ce57da86..aefcc50d6 100644 --- a/appc-adapters/appc-netconf-adapter/appc-netconf-adapter-features/src/main/resources/features.xml +++ b/appc-adapters/appc-netconf-adapter/appc-netconf-adapter-features/src/main/resources/features.xml @@ -30,7 +30,9 @@ <feature name='appc-netconf-adapter' description="appc-netconf-adapter" version='${project.version}'> <!-- Most applications will have a dependency on the ODL MD-SAL Broker --> <feature version="${broker-mdsal.version}">odl-mdsal-broker</feature> - <bundle>mvn:org.openecomp.appc/appc-dmaap-adapter-bundle/${project.version}</bundle> +<!-- <bundle>mvn:org.openecomp.appc/appc-dmaap-adapter-bundle/${project.version}</bundle> --> + <bundle dependency="true">mvn:org.openecomp.appc/appc-common/${project.version}</bundle> + <bundle start-level="75">mvn:org.openecomp.sdnc.core/dblib-provider/${sdnctl.dblib.version}</bundle> <bundle start-level="83" start="true">mvn:org.openecomp.appc/appc-netconf-adapter-bundle/${project.version}</bundle> </feature> diff --git a/appc-adapters/appc-rest-adapter/appc-rest-adapter-bundle/pom.xml b/appc-adapters/appc-rest-adapter/appc-rest-adapter-bundle/pom.xml index b3d24f1fe..d93e34bd4 100644 --- a/appc-adapters/appc-rest-adapter/appc-rest-adapter-bundle/pom.xml +++ b/appc-adapters/appc-rest-adapter/appc-rest-adapter-bundle/pom.xml @@ -13,27 +13,15 @@ <dependencies> <dependency> - <groupId>commons-codec</groupId> - <artifactId>commons-codec</artifactId> - </dependency> - <!-- http://mvnrepository.com/artifact/commons-logging/commons-logging --> - <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.2</version> </dependency> - <!-- http://mvnrepository.com/artifact/org.apache.httpcomponents/httpcore --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpcore</artifactId> <version>4.4.4</version> </dependency> - - <dependency> - <groupId>org.apache.httpcomponents</groupId> - <artifactId>httpclient</artifactId> - <version>4.5.1</version> - </dependency> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcpkix-jdk15on</artifactId> @@ -41,18 +29,17 @@ <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> - </dependency> + </dependency> <dependency> <groupId>org.openecomp.appc</groupId> <artifactId>appc-common</artifactId> <version>${project.version}</version> - <classifier>jar-with-dependencies</classifier> - <scope>compile</scope> </dependency> - <dependency> + <dependency> <groupId>org.openecomp.appc</groupId> <artifactId>appc-common</artifactId> <version>${project.version}</version> + <classifier>jar-with-dependencies</classifier> <scope>test</scope> </dependency> <dependency> @@ -116,6 +103,7 @@ <groupId>org.glassfish.jersey.core</groupId> <artifactId>jersey-common</artifactId> <version>2.9.1</version> + <scope>test</scope> </dependency> <dependency> @@ -161,10 +149,10 @@ </exclusions> </dependency> - <dependency> - <groupId>equinoxSDK381</groupId> - <artifactId>org.eclipse.osgi</artifactId> - </dependency> +<!-- <dependency> --> +<!-- <groupId>equinoxSDK381</groupId> --> +<!-- <artifactId>org.eclipse.osgi</artifactId> --> +<!-- </dependency> --> <dependency> <groupId>org.slf4j</groupId> @@ -212,11 +200,9 @@ <Bundle-Activator>org.openecomp.appc.adapter.rest.RestActivator</Bundle-Activator> <Export-Package>org.openecomp.appc.adapter.rest</Export-Package> <Import-Package>org.openecomp.sdnc.sli.*,org.osgi.framework.*,org.slf4j.*,com.vmware.*,org.apache.xerces.*,javax.net.*,javax.net.ssl.*,org.xml.sax.*,javax.xml.bind.*,javax.naming.*</Import-Package> - <Embed-Dependency>*;scope=compile|runtime;artifactId=!sli-common|org.eclipse.osgi|slf4j-api|jcl-over-slf4j|mysql-connector-java|xml-apis</Embed-Dependency> + <Embed-Dependency>*;scope=compile|runtime;artifactId=!sli-common|org.eclipse.osgi|slf4j-api|jcl-over-slf4j|mysql-connector-java|xml-apis|jaxp-api</Embed-Dependency> <Embed-Transitive>true</Embed-Transitive> </instructions> - - <manifestLocation>${project.basedir}/src/main/resources/META-INF</manifestLocation> </configuration> </plugin> </plugins> diff --git a/appc-adapters/appc-rest-adapter/appc-rest-adapter-bundle/src/main/java/org/openecomp/appc/adapter/rest/RestActivator.java b/appc-adapters/appc-rest-adapter/appc-rest-adapter-bundle/src/main/java/org/openecomp/appc/adapter/rest/RestActivator.java index 4c1baeb01..8a382d778 100644 --- a/appc-adapters/appc-rest-adapter/appc-rest-adapter-bundle/src/main/java/org/openecomp/appc/adapter/rest/RestActivator.java +++ b/appc-adapters/appc-rest-adapter/appc-rest-adapter-bundle/src/main/java/org/openecomp/appc/adapter/rest/RestActivator.java @@ -26,12 +26,14 @@ import org.openecomp.appc.adapter.rest.impl.RestAdapterImpl; import org.openecomp.appc.configuration.Configuration; import org.openecomp.appc.configuration.ConfigurationFactory; import org.openecomp.appc.i18n.Msg; -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceRegistration; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + + /** * This activator is used to initialize and terminate the connection pool to one or more providers. * <p> diff --git a/appc-adapters/appc-rest-adapter/appc-rest-adapter-bundle/src/main/java/org/openecomp/appc/adapter/rest/RestAdapter.java b/appc-adapters/appc-rest-adapter/appc-rest-adapter-bundle/src/main/java/org/openecomp/appc/adapter/rest/RestAdapter.java index 0d4a19709..c84c81253 100644 --- a/appc-adapters/appc-rest-adapter/appc-rest-adapter-bundle/src/main/java/org/openecomp/appc/adapter/rest/RestAdapter.java +++ b/appc-adapters/appc-rest-adapter/appc-rest-adapter-bundle/src/main/java/org/openecomp/appc/adapter/rest/RestAdapter.java @@ -39,7 +39,7 @@ import org.openecomp.sdnc.sli.SvcLogicJavaPlugin; */ public interface RestAdapter extends SvcLogicJavaPlugin { - /** + /** * The type of provider to be accessed to locate and operate on a virtual machine instance. This is used to load the * correct provider support through the CDP IaaS abstraction layer and can be OpenStackProvider, BareMetalProvider, * or any other supported provider type. diff --git a/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-bundle/.gitignore b/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-bundle/.gitignore new file mode 100644 index 000000000..755cdc373 --- /dev/null +++ b/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-bundle/.gitignore @@ -0,0 +1,3 @@ +/bin/ +/target/ +/.settings/ diff --git a/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-bundle/pom.xml b/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-bundle/pom.xml new file mode 100644 index 000000000..094ca9ab6 --- /dev/null +++ b/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-bundle/pom.xml @@ -0,0 +1,223 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.openecomp.appc</groupId> + <artifactId>appc-rest-healthcheck-adapter</artifactId> + <version>1.1.0-SNAPSHOT</version> + </parent> + + <artifactId>appc-rest-healthcheck-adapter-bundle</artifactId> + <packaging>bundle</packaging> + <name>rest healthcheck Adapter - bundle</name> + + <dependencies> + <dependency> + <groupId>commons-codec</groupId> + <artifactId>commons-codec</artifactId> + </dependency> + <!-- http://mvnrepository.com/artifact/commons-logging/commons-logging --> + <dependency> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + <version>1.2</version> + </dependency> + <!-- http://mvnrepository.com/artifact/org.apache.httpcomponents/httpcore --> + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpcore</artifactId> + <version>4.4.4</version> + </dependency> + + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpclient</artifactId> + <version>4.5.1</version> + </dependency> + <dependency> + <groupId>org.bouncycastle</groupId> + <artifactId>bcpkix-jdk15on</artifactId> + <version>1.47</version> + </dependency> + <dependency> + <groupId>org.bouncycastle</groupId> + <artifactId>bcprov-jdk15on</artifactId> + <version>1.47</version> + </dependency> + <dependency> + <groupId>org.openecomp.appc</groupId> + <artifactId>appc-common</artifactId> + <version>${project.version}</version> + <classifier>jar-with-dependencies</classifier> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>org.openecomp.appc</groupId> + <artifactId>appc-common</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>javax</groupId> + <artifactId>javaee-api</artifactId> + <version>7.0</version> + </dependency> + + + <dependency> + <groupId>com.att.cdp</groupId> + <artifactId>cdp-pal-common</artifactId> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>com.att.cdp</groupId> + <artifactId>cdp-pal-openstack</artifactId> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>javax.ws.rs</groupId> + <artifactId>javax.ws.rs-api</artifactId> + </dependency> + + <!-- Jersey support needed for OpenStack connector and API version logic --> + <dependency> + <groupId>com.sun.jersey</groupId> + <artifactId>jersey-client</artifactId> + </dependency> + + <dependency> + <groupId>com.sun.jersey</groupId> + <artifactId>jersey-json</artifactId> + </dependency> + + <dependency> + <groupId>javax.xml.bind</groupId> + <artifactId>jaxb-api</artifactId> + <version>2.1</version> + </dependency> + + <dependency> + <groupId>javax.xml</groupId> + <artifactId>jaxp-api</artifactId> + <version>1.4.2</version> + </dependency> + + <!-- Needed to run test cases --> + <dependency> + <groupId>org.glassfish.jersey.core</groupId> + <artifactId>jersey-common</artifactId> + <version>2.9.1</version> + </dependency> + + <dependency> + <groupId>org.codehaus.jackson</groupId> + <artifactId>jackson-jaxrs</artifactId> + <version>1.9.12</version> + </dependency> + + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpclient</artifactId> + <version>4.5.1</version> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sli-common</artifactId> + <scope>compile</scope> + <!-- Added exclusion to prevent missing dependency issue on dblib --> + <exclusions> + <exclusion> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>dblib-provider</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sli-provider</artifactId> + <scope>compile</scope> + <!-- Added exclusion to prevent missing dependency issue on dblib --> + <exclusions> + <exclusion> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>dblib-provider</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>equinoxSDK381</groupId> + <artifactId>org.eclipse.osgi</artifactId> + </dependency> + + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + </dependency> + + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>jcl-over-slf4j</artifactId> + </dependency> + + <dependency> + <groupId>mysql</groupId> + <artifactId>mysql-connector-java</artifactId> + <version>5.1.31</version> + <type>jar</type> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>com.vmware</groupId> + <artifactId>vijava</artifactId> + <version>5.1</version> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>xerces</groupId> + <artifactId>xerces</artifactId> + <version>2.4.0</version> + <scope>provided</scope> + </dependency> + + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Bundle-SymbolicName>appc-rest-healthcheck-adapter</Bundle-SymbolicName> + <Bundle-Activator>org.openecomp.appc.adapter.restHealthcheck.RestHealthcheckActivator</Bundle-Activator> + <Export-Package>org.openecomp.appc.adapter.restHealthcheck</Export-Package> + <Import-Package> + org.openecomp.sdnctl.sli.*,org.osgi.framework.*,org.slf4j.*,com.vmware.*,org.apache.xerces.*,javax.net.*,javax.net.ssl.*,org.xml.sax.*,javax.xml.bind.*,javax.naming.*,javax.security.auth.* + </Import-Package> + <Embed-Dependency> + *;scope=compile|runtime;artifactId=!sli-common|!appc-common|org.eclipse.osgi|slf4j-api|jcl-over-slf4j|xml-apis + </Embed-Dependency> + <Embed-Transitive>true</Embed-Transitive> + </instructions> + + <manifestLocation>${project.basedir}/src/main/resources/META-INF</manifestLocation> + </configuration> + </plugin> + </plugins> + </build> +</project> diff --git a/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-bundle/src/main/java/org/openecomp/appc/adapter/restHealthcheck/RestHealthcheckActivator.java b/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-bundle/src/main/java/org/openecomp/appc/adapter/restHealthcheck/RestHealthcheckActivator.java new file mode 100644 index 000000000..a6c9c3f4e --- /dev/null +++ b/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-bundle/src/main/java/org/openecomp/appc/adapter/restHealthcheck/RestHealthcheckActivator.java @@ -0,0 +1,113 @@ + +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.openecomp.appc.adapter.restHealthcheck; + +import org.openecomp.appc.Constants; +import org.openecomp.appc.adapter.restHealthcheck.impl.RestHealthcheckAdapterImpl; +import org.openecomp.appc.configuration.Configuration; +import org.openecomp.appc.configuration.ConfigurationFactory; +import org.openecomp.appc.i18n.Msg; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; + +public class RestHealthcheckActivator implements BundleActivator { + + /** + * The bundle registration + */ + private ServiceRegistration registration = null; + + /** + * The reference to the actual implementation object that implements the services + */ + private RestHealthcheckAdapter adapter; + + private static final EELFLogger logger = EELFManager.getInstance().getLogger(RestHealthcheckActivator.class); + + /** + * The configuration object used to configure this bundle + */ + private Configuration configuration; + + /** + * Called when this bundle is started so the Framework can perform the bundle-specific activities necessary to start + * this bundle. This method can be used to register services or to allocate any resources that this bundle needs. + * <p> + * This method must complete and return to its caller in a timely manner. + * </p> + * + * @param context + * The execution context of the bundle being started. + * @throws java.lang.Exception + * If this method throws an exception, this bundle is marked as stopped and the Framework will remove + * this bundle's listeners, unregister all services registered by this bundle, and release all services + * used by this bundle. + * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext) + */ + @Override + public void start(BundleContext context) throws Exception { + logger.info("Starting bundle " + getName()); + + adapter = new RestHealthcheckAdapterImpl(); + if (registration == null) { + registration = context.registerService(RestHealthcheckAdapter.class, adapter, null); + } + + } + + /** + * Called when this bundle is stopped so the Framework can perform the bundle-specific activities necessary to stop + * the bundle. In general, this method should undo the work that the BundleActivator.start method started. There + * should be no active threads that were started by this bundle when this bundle returns. A stopped bundle must not + * call any Framework objects. + * <p> + * This method must complete and return to its caller in a timely manner. + * </p> + * + * @param context + * The execution context of the bundle being stopped. + * @throws java.lang.Exception + * If this method throws an exception, the bundle is still marked as stopped, and the Framework will + * remove the bundle's listeners, unregister all services registered by the bundle, and release all + * services used by the bundle. * + * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext) + */ + @Override + public void stop(BundleContext context) throws Exception { + logger.info("Stopping bundle " + getName()); + + if (registration != null) { + + registration.unregister(); + registration = null; + + } + } + + public String getName() { + return "APPC Rest Healthcheck adapter"; + } + +} diff --git a/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-bundle/src/main/java/org/openecomp/appc/adapter/restHealthcheck/RestHealthcheckAdapter.java b/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-bundle/src/main/java/org/openecomp/appc/adapter/restHealthcheck/RestHealthcheckAdapter.java new file mode 100644 index 000000000..87cd02e23 --- /dev/null +++ b/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-bundle/src/main/java/org/openecomp/appc/adapter/restHealthcheck/RestHealthcheckAdapter.java @@ -0,0 +1,48 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.openecomp.appc.adapter.restHealthcheck; + +import java.util.Map; + +import org.openecomp.appc.exceptions.APPCException; +import com.att.cdp.zones.model.Server; +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicJavaPlugin; + + +public interface RestHealthcheckAdapter extends SvcLogicJavaPlugin { + + + static final String PROPERTY_PROVIDER_TYPE = "org.openecomp.appc.provider.type"; + + + static final String PROPERTY_PROVIDER_NAME = "org.openecomp.appc.provider.name"; + + static final String PROPERTY_INSTANCE_URL = "org.openecomp.appc.instance.url"; + + + static final String PROPERTY_IDENTITY_URL = "org.openecomp.appc.identity.url"; + + String getAdapterName(); + + void checkHealth(Map<String, String> params, SvcLogicContext ctx) ; + +} diff --git a/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-bundle/src/main/java/org/openecomp/appc/adapter/restHealthcheck/impl/RequestContext.java b/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-bundle/src/main/java/org/openecomp/appc/adapter/restHealthcheck/impl/RequestContext.java new file mode 100644 index 000000000..975a9c334 --- /dev/null +++ b/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-bundle/src/main/java/org/openecomp/appc/adapter/restHealthcheck/impl/RequestContext.java @@ -0,0 +1,246 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + + + +package org.openecomp.appc.adapter.restHealthcheck.impl; + +import org.openecomp.appc.Constants; +import org.openecomp.appc.configuration.Configuration; +import org.openecomp.sdnc.sli.SvcLogicContext; + +public class RequestContext { + /** + * The number of seconds of wait time between successive attempts to connect to the provider. This is used to + * recover from provider outages or failures. It is not used to recover from logical errors, such as an invalid + * request, server not found, etc. + */ + private Integer retryDelay; + + /** + * The number of times we will attempt to connect to the provider. This is used to recover from provider outages or + * failures. It is not used to recover from logical errors, such as an invalid request, server not found, etc. + */ + private Integer retryLimit; + + /** + * The total time, in milliseconds, that the provider can have to process this request. If the accumulated time + * exceeds the time to live, then the request is failed with a timeout exception, regardless of the state of the + * provider. Note that the caller may supply this as a value in seconds, in which case it must be converted to + * milliseconds for the request context. + */ + private Long timeToLive; + + /** + * The accumulated time, in milliseconds, that has been used so far to process the request. This is compared to the + * time to live each time it is updated. If the accumulated time exceeds the time to live, then the request is + * failed with a timeout exception, regardless of the state of the provider. + */ + private long accumulatedTime; + + /** + * The total number of retries attempted so far + */ + private int attempt; + + /** + * The time when the stopwatch was started + */ + private long startTime = -1; + + /** + * The service logic (DG) context from the SLI + */ + private SvcLogicContext svcLogicContext; + + /** + * The configuration + */ + + + /** + * Set to true whenever the retry limit has been exceeded, reset to false when reset() is called. + */ + private boolean retryFailed; + + /** + * Creates the request context + * + * @param context + * The service logic (SLI) context associated with the current DG + */ + public RequestContext(SvcLogicContext context) { + setSvcLogicContext(context); + } + + /** + * @return The retry delay, in seconds. If zero, then no retry is to be performed + */ + public int getRetryDelay() { + if (retryDelay == null) { + int value = 10; + retryDelay = Integer.valueOf(value); + } + + return retryDelay.intValue(); + } + + /** + * This method is a helper that allows the caller to delay for the retry interval time and not have to handle the + * thread interruption, timer handling, etc. + */ + public void delay() { + long time = getRetryDelay() * 1000L; + long future = System.currentTimeMillis() + time; + if (time != 0) { + while (System.currentTimeMillis() < future && time > 0) { + try { + Thread.sleep(time); + } catch (InterruptedException e) { + /* + * This is rare, but it can happen if another thread interrupts us while we are sleeping. In that + * case, the thread is resumed before the delay time has actually expired, so re-calculate the + * amount of delay time needed and reenter the sleep until we get to the future time. + */ + time = future - System.currentTimeMillis(); + } + } + } + } + + /** + * @return The number of retries that are allowed per connection + */ + public int getRetryLimit() { + if (retryLimit == null) { + int value = 10; + retryLimit = Integer.valueOf(value); + } + + return retryLimit.intValue(); + } + + /** + * Check and count the connection attempt. + * + * @return True if the connection should be attempted. False indicates that the number of retries has been exhausted + * and it should NOT be attempted. + */ + public boolean attempt() { + if (retryFailed || attempt >= getRetryLimit()) { + retryFailed = true; + return false; + } + attempt++; + + return true; + } + + /** + * @return The number of retry attempts so far + */ + public int getAttempts() { + return attempt; + } + + /** + * @return True if the retry limit has been exceeded, false otherwise + */ + public boolean isFailed() { + return retryFailed; + } + + /** + * This method both checks the time to live to see if it has been exceeded and accumulates the total time used so + * far. + * <p> + * Each time this method is called it accumulates the total duration since the last time it was called to the total + * time accumulator. It then checks the total time to the time to live and if greater, it returns false. As long as + * the total time used is less than or equal to the time to live limit, the method returns true. It is important to + * call this method at the very beginning of the process so that all parts of the process are tracked. + * </p> + * + * @return True if the total time to live has not been exceeded. False indicates that the total time to live has + * been exceeded and no further processing should be performed. + */ + public boolean isAlive() { + long now = System.currentTimeMillis(); + if (startTime == -1) { + startTime = now; + return true; + } + accumulatedTime += (now - startTime); + startTime = now; + if (accumulatedTime > timeToLive) { + return false; + } + return true; + } + + /** + * @return The total amount of time used, in milliseconds. + */ + public long getTotalDuration() { + return accumulatedTime; + } + + /** + * This method is called to reset the retry counters. It has no effect on the time to live accumulator. + */ + public void reset() { + attempt = 0; + } + + /** + * Sets the time to live to the value, expressed in seconds + * + * @param time + * The time to live, in seconds + */ + public void setTimeToLiveSeconds(int time) { + setTimeToLiveMS(time * 1000L); + } + + /** + * Sets the time to live to the value, expressed in milliseconds + * + * @param time + * The time to live, in milliseconds + */ + public void setTimeToLiveMS(long time) { + this.timeToLive = time; + } + + /** + * @return The service logic context associated with this request + */ + public SvcLogicContext getSvcLogicContext() { + return svcLogicContext; + } + + /** + * @param svcLogicContext + * The service logic context to be associated with this request + */ + public void setSvcLogicContext(SvcLogicContext svcLogicContext) { + this.svcLogicContext = svcLogicContext; + } +} diff --git a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/openecomp/appc/adapter/chef/impl/RequestFailedException.java b/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-bundle/src/main/java/org/openecomp/appc/adapter/restHealthcheck/impl/RequestFailedException.java index 047eb8b1f..b4a6d2922 100644 --- a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/openecomp/appc/adapter/chef/impl/RequestFailedException.java +++ b/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-bundle/src/main/java/org/openecomp/appc/adapter/restHealthcheck/impl/RequestFailedException.java @@ -20,16 +20,14 @@ */ -package org.openecomp.appc.adapter.chef.impl; + +package org.openecomp.appc.adapter.restHealthcheck.impl; import org.glassfish.grizzly.http.util.HttpStatus; + import com.att.cdp.zones.model.Server; -/** - * This class is used to capture the exact cause and point of failure for the processing of a request. It is then used - * to encode the reason for the failure, status code, and anything else that needs to be captured and reported for - * diagnostic purposes. - */ + public class RequestFailedException extends Exception { /** diff --git a/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-bundle/src/main/java/org/openecomp/appc/adapter/restHealthcheck/impl/RestHealthcheckAdapterImpl.java b/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-bundle/src/main/java/org/openecomp/appc/adapter/restHealthcheck/impl/RestHealthcheckAdapterImpl.java new file mode 100644 index 000000000..13bc81ac4 --- /dev/null +++ b/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-bundle/src/main/java/org/openecomp/appc/adapter/restHealthcheck/impl/RestHealthcheckAdapterImpl.java @@ -0,0 +1,336 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.adapter.restHealthcheck.impl; + +import java.net.URI; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.regex.Pattern; + +import org.openecomp.appc.Constants; +import org.openecomp.appc.adapter.restHealthcheck.RestHealthcheckAdapter; +import org.openecomp.appc.configuration.Configuration; +import org.openecomp.appc.configuration.ConfigurationFactory; +import org.openecomp.appc.exceptions.APPCException; +import org.openecomp.appc.exceptions.UnknownProviderException; +import org.openecomp.appc.i18n.Msg; +import org.openecomp.appc.pool.Pool; +import org.openecomp.appc.pool.PoolExtensionException; +import org.openecomp.appc.util.StructuredPropertyHelper; +import org.openecomp.appc.util.StructuredPropertyHelper.Node; + + +import com.att.cdp.exceptions.ContextConnectionException; +import com.att.cdp.exceptions.ResourceNotFoundException; +import com.att.cdp.exceptions.TimeoutException; +import com.att.cdp.exceptions.ZoneException; +import com.att.cdp.pal.util.StringHelper; +import com.att.cdp.zones.ComputeService; +import com.att.cdp.zones.Context; +import com.att.cdp.zones.ImageService; +import com.att.cdp.zones.Provider; +import com.att.cdp.zones.model.Image; +import com.att.cdp.zones.model.Server; +import com.att.cdp.zones.model.Server.Status; +import com.att.cdp.zones.model.ServerBootSource; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.att.eelf.i18n.EELFResourceManager; +import org.openecomp.sdnc.sli.SvcLogicContext; + +import org.glassfish.grizzly.http.util.HttpStatus; +import org.slf4j.MDC; + +import java.net.InetAddress; +import java.util.Locale; +import java.util.UUID; +import static com.att.eelf.configuration.Configuration.*; + +import org.apache.http.*; +import org.apache.http.client.*; +import org.apache.http.client.methods.*; +import org.apache.http.impl.client.*; +import org.apache.http.util.EntityUtils; +import java.io.IOException; +import org.apache.http.entity.StringEntity; +import java.net.InetAddress; + +public class RestHealthcheckAdapterImpl implements RestHealthcheckAdapter { + + /** + * The constant used to define the adapter name in the mapped diagnostic + * context + */ + + + @SuppressWarnings("nls") + public static final String MDC_ADAPTER = "adapter"; + + /** + * The constant used to define the service name in the mapped diagnostic + * context + */ + @SuppressWarnings("nls") + public static final String MDC_SERVICE = "service"; + + /** + * The constant for the status code for a failed outcome + */ + @SuppressWarnings("nls") + public static final String OUTCOME_FAILURE = "failure"; + + /** + * The constant for the status code for a successful outcome + */ + @SuppressWarnings("nls") + public static final String OUTCOME_SUCCESS = "success"; + + /** + * A constant for the property token "provider" used in the structured + * property specifications + */ + @SuppressWarnings("nls") + public static final String PROPERTY_PROVIDER = "provider"; + + /** + * A constant for the property token "identity" used in the structured + * property specifications + */ + @SuppressWarnings("nls") + public static final String PROPERTY_PROVIDER_IDENTITY = "identity"; + + /** + * A constant for the property token "name" used in the structured property + * specifications + */ + @SuppressWarnings("nls") + public static final String PROPERTY_PROVIDER_NAME = "name"; + + /** + * A constant for the property token "tenant" used in the structured + * property specifications + */ + @SuppressWarnings("nls") + public static final String PROPERTY_PROVIDER_TENANT = "tenant"; + + /** + * A constant for the property token "tenant name" used in the structured + * property specifications + */ + @SuppressWarnings("nls") + public static final String PROPERTY_PROVIDER_TENANT_NAME = "name"; + + /** + * A constant for the property token "password" used in the structured + * property specifications + */ + @SuppressWarnings("nls") + public static final String PROPERTY_PROVIDER_TENANT_PASSWORD = "password"; // NOSONAR + + /** + * A constant for the property token "userid" used in the structured + * property specifications + */ + @SuppressWarnings("nls") + public static final String PROPERTY_PROVIDER_TENANT_USERID = "userid"; + + /** + * A constant for the property token "type" used in the structured property + * specifications + */ + @SuppressWarnings("nls") + public static final String PROPERTY_PROVIDER_TYPE = "type"; + + + @SuppressWarnings("nls") + public static final String PING_SERVICE = "pingServer"; + + /** + * The logger to be used + */ + private static final EELFLogger logger = EELFManager.getInstance().getLogger(RestHealthcheckAdapterImpl.class); + + /** + * The constant for a left parenthesis + */ + private static final char LPAREN = '('; + + /** + * The constant for a new line control code + */ + private static final char NL = '\n'; + + /** + * The constant for a single quote + */ + private static final char QUOTE = '\''; + + /** + * The constant for a right parenthesis + */ + private static final char RPAREN = ')'; + + /** + * The constant for a space + */ + private static final char SPACE = ' '; + + /** + * A reference to the adapter configuration object. + */ + private Configuration configuration; + + /** + * A cache of providers that are predefined. + */ + // private Map<String /* provider name */, ProviderCache> providerCache; + + /** + * This default constructor is used as a work around because the activator + * wasnt getting called + */ + /** + * A cache of providers that are predefined. + */ + // private Map<String /* provider name */, ProviderCache> providerCache; + + /** + * This default constructor is used as a work around because the activator + * wasnt getting called + */ + public RestHealthcheckAdapterImpl() { + initialize(); + + } + + + public RestHealthcheckAdapterImpl(boolean initialize) { + + if (initialize) { + initialize(); + + } + } + + + public RestHealthcheckAdapterImpl(Properties props) { + initialize(); + + } + + + @Override + public String getAdapterName() { + return configuration.getProperty(Constants.PROPERTY_ADAPTER_NAME); + } + + public void checkHealth(Map<String, String> params, SvcLogicContext ctx) { + logger.info("VNF rest health check"); + String uri=params.get("VNF.URI"); + String endPoint=params.get("VNF.endpoint"); + String tUrl=uri+"/"+endPoint; + RequestContext rc = new RequestContext(ctx); + rc.isAlive(); + + try { + HttpGet httpGet = new HttpGet(tUrl); + HttpClient httpClient = HttpClients.createDefault(); + HttpResponse response = null; + response = httpClient.execute(httpGet); + int responseCode=response.getStatusLine().getStatusCode(); + HttpEntity entity = response.getEntity(); + String responseOutput=EntityUtils.toString(entity); + if(responseCode==200) + { + doSuccess(rc,responseCode,responseOutput); + } + else + { + doHealthCheckFailure(rc,responseCode,responseOutput); + } + } catch (Exception ex) { + doFailure(rc, HttpStatus.INTERNAL_SERVER_ERROR_500, ex.toString()); + } + } + + + + + @SuppressWarnings("static-method") + private void doFailure(RequestContext rc, HttpStatus code, String message) { + SvcLogicContext svcLogic = rc.getSvcLogicContext(); + String msg = (message == null) ? code.getReasonPhrase() : message; + if (msg.contains("\n")) { + msg = msg.substring(msg.indexOf("\n")); + } + + String status; + try { + status = Integer.toString(code.getStatusCode()); + } catch (Exception e) { + status = "500"; + } + svcLogic.setStatus(OUTCOME_FAILURE); + svcLogic.setAttribute("healthcheck.result.code", "200"); + svcLogic.setAttribute("healthcheck.result.message", status+" "+msg); + } + + + /** + * @param rc + * The request context that manages the state and recovery of the + * request for the life of its processing. + */ + @SuppressWarnings("static-method") + private void doHealthCheckFailure(RequestContext rc, int code, String message) { + SvcLogicContext svcLogic = rc.getSvcLogicContext(); + String msg = Integer.toString(code)+" "+message; + svcLogic.setAttribute("healthcheck.result.code", "200"); + svcLogic.setAttribute("healthcheck.result.message", msg); + + } + + + @SuppressWarnings("static-method") + private void doSuccess(RequestContext rc, int code, String message) { + SvcLogicContext svcLogic = rc.getSvcLogicContext(); + String msg = Integer.toString(code)+" "+message; + svcLogic.setAttribute("healthcheck.result.code", "400"); + svcLogic.setAttribute("healthcheck.result.message", msg); + + } + + + /** + * initialize the provider adapter by building the context cache + */ + private void initialize() { + + + logger.info("init rest health check adapter!!!!!"); + } + +} diff --git a/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-bundle/src/main/resources/org/openecomp/appc/default.properties b/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-bundle/src/main/resources/org/openecomp/appc/default.properties new file mode 100644 index 000000000..d7d9e5cb1 --- /dev/null +++ b/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-bundle/src/main/resources/org/openecomp/appc/default.properties @@ -0,0 +1,76 @@ +### +# ============LICENSE_START======================================================= +# openECOMP : APP-C +# ================================================================================ +# Copyright (C) 2017 AT&T Intellectual Property. All rights +# reserved. +# ================================================================================ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============LICENSE_END========================================================= +### + +# +# Default properties for the APP-C Provider Adapter +# +# ------------------------------------------------------------------------------------------------- +# +# Define the name and path of any user-provided configuration (bootstrap) file that can be loaded +# to supply configuration options +org.openecomp.appc.bootstrap.file=appc.properties +org.openecomp.appc.bootstrap.path=/opt/openecomp/appc/data/properties,${user.home},. + +appc.application.name=APPC + +# +# Define the message resource bundle name to be loaded +org.openecomp.appc.resources=org/openecomp/appc/i18n/MessageResources +# +# The name of the adapter. +org.openecomp.appc.provider.adaptor.name=org.openecomp.appc.appc_provider_adapter +# +# Set up the logging environment +# +org.openecomp.appc.logging.file=org/openecomp/appc/logback.xml +org.openecomp.appc.logging.path=${user.home};etc;../etc +org.openecomp.appc.logger=org.openecomp.appc +org.openecomp.appc.security.logger=org.openecomp.appc.security +# +# The minimum and maximum provider/tenant context pool sizes. Min=1 means that as soon +# as the provider/tenant is referenced a Context is opened and added to the pool. Max=0 +# means that the upper bound on the pool is unbounded. +org.openecomp.appc.provider.min.pool=1 +org.openecomp.appc.provider.max.pool=0 + +# +# The following properties are used to configure the retry logic for connection to the +# IaaS provider(s). The retry delay property is the amount of time, in seconds, the +# application waits between retry attempts. The retry limit is the number of retries +# that are allowed before the request is failed. +org.openecomp.appc.provider.retry.delay = 30 +org.openecomp.appc.provider.retry.limit = 10 + +# +# The trusted hosts list for SSL access when a certificate is not provided. +# +provider.trusted.hosts=* +# +# The amount of time, in seconds, to wait for a server state change (start->stop, stop->start, etc). +# If the server does not change state to a valid state within the alloted time, the operation +# fails. +org.openecomp.appc.server.state.change.timeout=300 +# +# The amount of time to wait, in seconds, between subsequent polls to the OpenStack provider +# to refresh the status of a resource we are waiting on. +# +org.openecomp.appc.openstack.poll.interval=20 +# diff --git a/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-bundle/src/test/java/org/openecomp/appc/test/ExecutorHarness.java b/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-bundle/src/test/java/org/openecomp/appc/test/ExecutorHarness.java new file mode 100644 index 000000000..c21435d2e --- /dev/null +++ b/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-bundle/src/test/java/org/openecomp/appc/test/ExecutorHarness.java @@ -0,0 +1,180 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + + +package org.openecomp.appc.test; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.openecomp.appc.test.InterceptLogger; + +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicJavaPlugin; + +/** + * This class is used as a test harness to wrap the call to an executor node. + */ + +public class ExecutorHarness { + + /** + * The executor to be tested + */ + private SvcLogicJavaPlugin executor; + + /** + * The collection of all exec methods found on the class + */ + private Map<String, Method> methods; + + /** + * The field of the class being tested that contains the reference to the logger to be used. This is modified to + * point to our interception logger for the test. + */ + private Field contextLogger; + + /** + * The interception logger that buffers all messages logged and allows us to look at them as part of the test case. + */ + private InterceptLogger logger; + + /** + * Create the harness and initialize it + * + * @throws SecurityException + * If a security manager, s, is present and any of the following conditions is met: + * <ul> + * <li>invocation of s.checkMemberAccess(this, Member.DECLARED) denies access to the declared field</li> + * <li>the caller's class loader is not the same as or an ancestor of the class loader for the current + * class and invocation of s.checkPackageAccess() denies access to the package of this class</li> + * </ul> + * @throws NoSuchFieldException + * if a field with the specified name is not found. + * @throws IllegalAccessException + * if this Field object is enforcing Java language access control and the underlying field is either + * inaccessible or final. + * @throws IllegalArgumentException + * if the specified object is not an instance of the class or interface declaring the underlying field + * (or a subclass or implementor thereof), or if an unwrapping conversion fails. + */ + @SuppressWarnings("nls") + public ExecutorHarness() throws NoSuchFieldException, SecurityException, IllegalArgumentException, + IllegalAccessException { + methods = new HashMap<>(); + new SvcLogicContext(); + + Class<?> contextClass = SvcLogicContext.class; + contextLogger = contextClass.getDeclaredField("LOG"); + contextLogger.setAccessible(true); + logger = new InterceptLogger(); + contextLogger.set(null, logger); + } + + /** + * Convenience constructor + * + * @param executor + * The executor to be tested by the harness + * @throws SecurityException + * If a security manager, s, is present and any of the following conditions is met: + * <ul> + * <li>invocation of s.checkMemberAccess(this, Member.DECLARED) denies access to the declared field</li> + * <li>the caller's class loader is not the same as or an ancestor of the class loader for the current + * class and invocation of s.checkPackageAccess() denies access to the package of this class</li> + * </ul> + * @throws NoSuchFieldException + * if a field with the specified name is not found. + * @throws IllegalAccessException + * if this Field object is enforcing Java language access control and the underlying field is either + * inaccessible or final. + * @throws IllegalArgumentException + * if the specified object is not an instance of the class or interface declaring the underlying field + * (or a subclass or implementor thereof), or if an unwrapping conversion fails. + */ + public ExecutorHarness(SvcLogicJavaPlugin executor) throws NoSuchFieldException, SecurityException, + IllegalArgumentException, IllegalAccessException { + this(); + setExecutor(executor); + } + + /** + * @param executor + * The java plugin class to be executed + */ + public void setExecutor(SvcLogicJavaPlugin executor) { + this.executor = executor; + scanExecutor(); + } + + /** + * @return The java plugin class to be executed + */ + public SvcLogicJavaPlugin getExecutor() { + return executor; + } + + /** + * @return The set of all methods that meet the signature requirements + */ + public List<String> getExecMethodNames() { + List<String> names = new ArrayList<>(); + names.addAll(methods.keySet()); + return names; + } + + /** + * Returns an indication if the named method is a valid executor method that could be called from a DG execute node + * + * @param methodName + * The method name to be validated + * @return True if the method name meets the signature requirements, false if the method either does not exist or + * does not meet the requirements. + */ + public boolean isExecMethod(String methodName) { + return methods.containsKey(methodName); + } + + /** + * This method scans the executor class hierarchy to locate all methods that match the required signature of the + * executor and records these methods in a map. + */ + private void scanExecutor() { + methods.clear(); + Class<?> executorClass = executor.getClass(); + Method[] publicMethods = executorClass.getMethods(); + for (Method method : publicMethods) { + if (method.getReturnType().equals(Void.class)) { + Class<?>[] paramTypes = method.getParameterTypes(); + if (paramTypes.length == 2) { + if (Map.class.isAssignableFrom(paramTypes[0]) + && SvcLogicContext.class.isAssignableFrom(paramTypes[1])) { + methods.put(method.getName(), method); + } + } + } + } + } +} diff --git a/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-bundle/src/test/java/org/openecomp/appc/test/InterceptLogger.java b/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-bundle/src/test/java/org/openecomp/appc/test/InterceptLogger.java new file mode 100644 index 000000000..acb122914 --- /dev/null +++ b/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-bundle/src/test/java/org/openecomp/appc/test/InterceptLogger.java @@ -0,0 +1,452 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + + + +package org.openecomp.appc.test; + +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.List; + +import org.slf4j.Marker; + +import ch.qos.logback.classic.Level; + +/** + * This class is used as an intercept logger that can be used in testing to intercept and record all messages that are + * logged, thus allowing a junit test case to examine the log output and make assertions. + */ +public class InterceptLogger implements org.slf4j.Logger { + + /** + * This inner class represents an intercepted log event. + */ + public class LogRecord { + private Level level; + private String message; + private long timestamp; + private Throwable t; + + public LogRecord(Level level, String message) { + setLevel(level); + setTimestamp(System.currentTimeMillis()); + setMessage(message); + } + + public LogRecord(Level level, String message, Throwable t) { + this(level, message); + setThrowable(t); + } + + /** + * @return the value of level + */ + public Level getLevel() { + return level; + } + + /** + * @return the value of message + */ + public String getMessage() { + return message; + } + + /** + * @return the value of timestamp + */ + public long getTimestamp() { + return timestamp; + } + + /** + * @param level + * the value for level + */ + public void setLevel(Level level) { + this.level = level; + } + + /** + * @param message + * the value for message + */ + public void setMessage(String message) { + this.message = message; + } + + /** + * @param timestamp + * the value for timestamp + */ + public void setTimestamp(long timestamp) { + this.timestamp = timestamp; + } + + /** + * @return the value of t + */ + public Throwable getThrowable() { + return t; + } + + /** + * @param t + * the value for t + */ + public void setThrowable(Throwable t) { + this.t = t; + } + + } + + /** + * The list of all intercepted log events + */ + private List<LogRecord> events; + + /** + * Create the intercept logger + */ + public InterceptLogger() { + events = new ArrayList<LogRecord>(1000); + } + + /** + * @return Returns all intercepted log events + */ + public List<LogRecord> getLogRecords() { + return events; + } + + /** + * Clears all log events + */ + public void clear() { + events.clear(); + } + + @Override + public void debug(Marker marker, String msg) { + debug(msg); + } + + @Override + public void debug(Marker marker, String format, Object arg) { + debug(MessageFormat.format(format, arg)); + } + + @Override + public void debug(Marker marker, String format, Object... arguments) { + debug(MessageFormat.format(format, arguments)); + } + + @Override + public void debug(Marker marker, String format, Object arg1, Object arg2) { + debug(MessageFormat.format(format, arg1, arg2)); + } + + @Override + public void debug(Marker marker, String msg, Throwable t) { + debug(msg, t); + } + + @Override + public void debug(String msg) { + events.add(new LogRecord(Level.DEBUG, msg)); + } + + @Override + public void debug(String format, Object arg) { + events.add(new LogRecord(Level.DEBUG, MessageFormat.format(format, arg))); + } + + @Override + public void debug(String format, Object... arguments) { + events.add(new LogRecord(Level.DEBUG, MessageFormat.format(format, arguments))); + } + + @Override + public void debug(String format, Object arg1, Object arg2) { + events.add(new LogRecord(Level.DEBUG, MessageFormat.format(format, arg1, arg2))); + } + + @Override + public void debug(String msg, Throwable t) { + events.add(new LogRecord(Level.DEBUG, msg, t)); + } + + @Override + public void error(Marker marker, String msg) { + error(msg); + } + + @Override + public void error(Marker marker, String format, Object arg) { + error(format, arg); + } + + @Override + public void error(Marker marker, String format, Object... arguments) { + error(format, arguments); + } + + @Override + public void error(Marker marker, String format, Object arg1, Object arg2) { + error(format, arg1, arg2); + } + + @Override + public void error(Marker marker, String msg, Throwable t) { + events.add(new LogRecord(Level.ERROR, msg, t)); + } + + @Override + public void error(String msg) { + events.add(new LogRecord(Level.ERROR, msg)); + } + + @Override + public void error(String format, Object arg) { + events.add(new LogRecord(Level.ERROR, MessageFormat.format(format, arg))); + } + + @Override + public void error(String format, Object... arguments) { + events.add(new LogRecord(Level.ERROR, MessageFormat.format(format, arguments))); + } + + @Override + public void error(String format, Object arg1, Object arg2) { + events.add(new LogRecord(Level.ERROR, MessageFormat.format(format, arg1, arg2))); + } + + @Override + public void error(String msg, Throwable t) { + events.add(new LogRecord(Level.ERROR, msg, t)); + } + + @Override + public String getName() { + return null; + } + + @Override + public void info(Marker marker, String msg) { + info(msg); + } + + @Override + public void info(Marker marker, String format, Object arg) { + info(format, arg); + } + + @Override + public void info(Marker marker, String format, Object... arguments) { + info(format, arguments); + } + + @Override + public void info(Marker marker, String format, Object arg1, Object arg2) { + info(format, arg1, arg2); + } + + @Override + public void info(Marker marker, String msg, Throwable t) { + events.add(new LogRecord(Level.INFO, msg, t)); + } + + @Override + public void info(String msg) { + events.add(new LogRecord(Level.INFO, msg)); + } + + @Override + public void info(String format, Object arg) { + events.add(new LogRecord(Level.INFO, MessageFormat.format(format, arg))); + } + + @Override + public void info(String format, Object... arguments) { + events.add(new LogRecord(Level.INFO, MessageFormat.format(format, arguments))); + } + + @Override + public void info(String format, Object arg1, Object arg2) { + events.add(new LogRecord(Level.INFO, MessageFormat.format(format, arg1, arg2))); + } + + @Override + public void info(String msg, Throwable t) { + events.add(new LogRecord(Level.INFO, msg, t)); + } + + @Override + public boolean isDebugEnabled() { + return true; + } + + @Override + public boolean isDebugEnabled(Marker marker) { + return true; + } + + @Override + public boolean isErrorEnabled() { + return true; + } + + @Override + public boolean isErrorEnabled(Marker marker) { + return true; + } + + @Override + public boolean isInfoEnabled() { + return true; + } + + @Override + public boolean isInfoEnabled(Marker marker) { + return true; + } + + @Override + public boolean isTraceEnabled() { + return true; + } + + @Override + public boolean isTraceEnabled(Marker marker) { + return true; + } + + @Override + public boolean isWarnEnabled() { + return true; + } + + @Override + public boolean isWarnEnabled(Marker marker) { + return true; + } + + @Override + public void trace(Marker marker, String msg) { + trace(msg); + } + + @Override + public void trace(Marker marker, String format, Object arg) { + trace(format, arg); + } + + @Override + public void trace(Marker marker, String format, Object... argArray) { + trace(format, argArray); + } + + @Override + public void trace(Marker marker, String format, Object arg1, Object arg2) { + trace(format, arg1, arg2); + } + + @Override + public void trace(Marker marker, String msg, Throwable t) { + trace(msg, t); + } + + @Override + public void trace(String msg) { + events.add(new LogRecord(Level.TRACE, msg)); + } + + @Override + public void trace(String format, Object arg) { + events.add(new LogRecord(Level.TRACE, MessageFormat.format(format, arg))); + } + + @Override + public void trace(String format, Object... arguments) { + events.add(new LogRecord(Level.TRACE, MessageFormat.format(format, arguments))); + } + + @Override + public void trace(String format, Object arg1, Object arg2) { + events.add(new LogRecord(Level.TRACE, MessageFormat.format(format, arg1, arg2))); + } + + @Override + public void trace(String msg, Throwable t) { + events.add(new LogRecord(Level.TRACE, msg, t)); + } + + @Override + public void warn(Marker marker, String msg) { + warn(msg); + } + + @Override + public void warn(Marker marker, String format, Object arg) { + warn(format, arg); + } + + @Override + public void warn(Marker marker, String format, Object... arguments) { + warn(format, arguments); + } + + @Override + public void warn(Marker marker, String format, Object arg1, Object arg2) { + warn(format, arg1, arg2); + } + + @Override + public void warn(Marker marker, String msg, Throwable t) { + events.add(new LogRecord(Level.WARN, msg, t)); + } + + @Override + public void warn(String msg) { + events.add(new LogRecord(Level.WARN, msg)); + } + + @Override + public void warn(String format, Object arg) { + events.add(new LogRecord(Level.WARN, MessageFormat.format(format, arg))); + } + + @Override + public void warn(String format, Object... arguments) { + events.add(new LogRecord(Level.WARN, MessageFormat.format(format, arguments))); + } + + @Override + public void warn(String format, Object arg1, Object arg2) { + events.add(new LogRecord(Level.WARN, MessageFormat.format(format, arg1, arg2))); + } + + @Override + public void warn(String msg, Throwable t) { + events.add(new LogRecord(Level.WARN, msg, t)); + } +} diff --git a/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-bundle/src/test/resources/org/openecomp/appc/default.properties b/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-bundle/src/test/resources/org/openecomp/appc/default.properties new file mode 100644 index 000000000..0c56e3342 --- /dev/null +++ b/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-bundle/src/test/resources/org/openecomp/appc/default.properties @@ -0,0 +1,95 @@ +### +# ============LICENSE_START======================================================= +# openECOMP : APP-C +# ================================================================================ +# Copyright (C) 2017 AT&T Intellectual Property. All rights +# reserved. +# ================================================================================ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============LICENSE_END========================================================= +### + +# +# Default properties for the APP-C Provider Adapter +# +# ------------------------------------------------------------------------------------------------- +# +# Define the name and path of any user-provided configuration (bootstrap) file that can be loaded +# to supply configuration options +org.openecomp.appc.bootstrap.file=appc.properties +org.openecomp.appc.bootstrap.path=/opt/openecomp/appc/data/properties,${user.home},. + +appc.application.name=APPC + +# +# Define the message resource bundle name to be loaded +org.openecomp.appc.resources=/opt/openecomp/appc/i18n/MessageResources +# +# The name of the adapter. +org.openecomp.appc.provider.adaptor.name=org.openecomp.appc.appc_provider_adapter +# +# Set up the logging environment +# +org.openecomp.appc.logging.file=/opt/openecomp/appc/logback.xml +org.openecomp.appc.logging.path=${user.home};etc;../etc +org.openecomp.appc.logger=org.openecomp.appc +org.openecomp.appc.security.logger=org.openecomp.appc.security +# +# The minimum and maximum provider/tenant context pool sizes. Min=1 means that as soon +# as the provider/tenant is referenced a Context is opened and added to the pool. Max=0 +# means that the upper bound on the pool is unbounded. +org.openecomp.appc.provider.min.pool=1 +org.openecomp.appc.provider.max.pool=0 + +# +# The following properties are used to configure the retry logic for connection to the +# IaaS provider(s). The retry delay property is the amount of time, in seconds, the +# application waits between retry attempts. The retry limit is the number of retries +# that are allowed before the request is failed. +org.openecomp.appc.provider.retry.delay = 30 +org.openecomp.appc.provider.retry.limit = 10 + +# +# The trusted hosts list for SSL access when a certificate is not provided. +# +provider.trusted.hosts=* +# +# The amount of time, in seconds, to wait for a server state change (start->stop, stop->start, etc). +# If the server does not change state to a valid state within the alloted time, the operation +# fails. +org.openecomp.appc.server.state.change.timeout=300 +# +# The amount of time to wait, in seconds, between subsequent polls to the OpenStack provider +# to refresh the status of a resource we are waiting on. +# +org.openecomp.appc.openstack.poll.interval=20 +# +# The connection information to connect to the provider we are using. These properties +# are "structured" properties, in that the name is a compound name, where the nodes +# of the name can be ordered (1, 2, 3, ...). All of the properties with the same ordinal +# position are defining the same entity. For example, provider1.type and provider1.name +# are defining the same provider, whereas provider2.name and provider2.type are defining +# the values for a different provider. Any number of providers can be defined in this +# way. +# + + + +provider1.identity=http://localhost:4000/v2.0 +provider1.tenant1.name=Provider1 +provider1.tenant1.userid=test +provider1.tenant1.password=test + +# After a change to the provider make sure to recheck these values with an api call to proivider1.identity/tokens +test.expected-regions=1 +test.expected-endpoints=1 diff --git a/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-features/.gitignore b/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-features/.gitignore new file mode 100644 index 000000000..615a76bbc --- /dev/null +++ b/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-features/.gitignore @@ -0,0 +1,4 @@ +/target/ +/bin/ +/classes/ +/.settings/ diff --git a/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-features/pom.xml b/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-features/pom.xml new file mode 100644 index 000000000..20a990482 --- /dev/null +++ b/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-features/pom.xml @@ -0,0 +1,122 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <artifactId>appc-rest-healthcheck-adapter</artifactId> + <groupId>org.openecomp.appc</groupId> + <version>1.1.0-SNAPSHOT</version> + </parent> + <artifactId>appc-rest-healthcheck-adapter-features</artifactId> + <name>rest healthcheck Adaptor - Features</name> + + <packaging>jar</packaging> + + <dependencies> + <dependency> + <groupId>org.openecomp.appc</groupId> + <artifactId>appc-rest-healthcheck-adapter-bundle</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>commons-lang</groupId> + <artifactId>commons-lang</artifactId> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>org.opendaylight.mdsal</groupId> + <artifactId>features-mdsal</artifactId> + <classifier>features</classifier> + <type>xml</type> + <scope>runtime</scope> + </dependency> + + <!-- dependency for opendaylight-karaf-empty for use by testing --> + <dependency> + <groupId>org.opendaylight.controller</groupId> + <artifactId>opendaylight-karaf-empty</artifactId> + <type>zip</type> + </dependency> + +<!-- <dependency> --> +<!-- Required for launching the feature tests --> +<!-- <groupId>org.opendaylight.yangtools</groupId> --> +<!-- <artifactId>features-test</artifactId> --> +<!-- <scope>test</scope> --> +<!-- </dependency> --> + + <dependency> + <groupId>org.opendaylight.yangtools</groupId> + <artifactId>features-yangtools</artifactId> + <classifier>features</classifier> + <type>xml</type> + <scope>runtime</scope> + </dependency> + </dependencies> + + <build> + <resources> + <resource> + <filtering>true</filtering> + <directory>src/main/resources</directory> + </resource> + </resources> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-resources-plugin</artifactId> + <executions> + <execution> + <id>filter</id> + <goals> + <goal>resources</goal> + </goals> + <phase>generate-resources</phase> + </execution> + </executions> + </plugin> + <!-- launches the feature test, which validates that your karaf feature + can be installed inside of a karaf container. It doesn't validate that your + functionality works correctly, just that you have all of the dependent bundles + defined correctly. --> + <!-- <plugin> --> + <!-- <groupId>org.apache.maven.plugins</groupId> --> + <!-- <artifactId>maven-surefire-plugin</artifactId> --> + <!-- <version>2.16</version> --> + <!-- <configuration> --> + <!-- <systemPropertyVariables> --> + <!-- <karaf.distro.groupId>org.opendaylight.controller</karaf.distro.groupId> --> + <!-- <karaf.distro.artifactId>opendaylight-karaf-empty</karaf.distro.artifactId> --> + <!-- <karaf.distro.version>${odl.karaf.empty.distro.version}</karaf.distro.version> --> + <!-- </systemPropertyVariables> --> + <!-- <dependenciesToScan> --> + <!-- <dependency>org.opendaylight.yangtools:features-test</dependency> --> + <!-- </dependenciesToScan> --> + <!-- </configuration> --> + <!-- </plugin> --> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + <executions> + <execution> + <id>attach-artifacts</id> + <goals> + <goal>attach-artifact</goal> + </goals> + <phase>package</phase> + <configuration> + <artifacts> + <artifact> + <file>${project.build.directory}/classes/${features.file}</file> + <type>xml</type> + <classifier>features</classifier> + </artifact> + </artifacts> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project>
\ No newline at end of file diff --git a/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-features/src/main/resources/features.xml b/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-features/src/main/resources/features.xml new file mode 100644 index 000000000..d9cb37c49 --- /dev/null +++ b/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-features/src/main/resources/features.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============LICENSE_START======================================================= + openECOMP : APP-C + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights + reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + + +<features name="appc-rest-adapter-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0"> + + <repository>mvn:org.opendaylight.mdsal/features-mdsal/${features-mdsal.version}/xml/features</repository> + + <feature name='appc-rest-healthcheck-adapter' description="appc-rest-healthcheck-adapter" version='${project.version}'> + <!-- Most applications will have a dependency on the ODL MD-SAL Broker --> + <feature version="${broker-mdsal.version}">odl-mdsal-broker</feature> + <feature>sdnc-sli</feature> + <bundle>mvn:org.openecomp.appc/appc-rest-healthcheck-adapter-bundle/${project.version}</bundle> + </feature> + +</features> diff --git a/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-installer/.gitignore b/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-installer/.gitignore new file mode 100644 index 000000000..731eb433c --- /dev/null +++ b/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-installer/.gitignore @@ -0,0 +1,2 @@ +/target/ +/.settings/ diff --git a/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-installer/pom.xml b/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-installer/pom.xml new file mode 100644 index 000000000..4dc4a4d13 --- /dev/null +++ b/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-installer/pom.xml @@ -0,0 +1,126 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <artifactId>appc-rest-healthcheck-adapter</artifactId> + <groupId>org.openecomp.appc</groupId> + <version>1.1.0-SNAPSHOT</version> + </parent> + <artifactId>appc-rest-healthcheck-adapter-installer</artifactId> + <name>Chef Adapter - Karaf Installer</name> + <packaging>pom</packaging> + <properties> + <application.name>appc-rest-healthcheck-adapter</application.name> + <features.boot>appc-rest-healthcheck-adapter</features.boot> + <features.repositories>mvn:org.openecomp.appc/appc-rest-healthcheck-adapter-features/${project.version}/xml/features</features.repositories> + <include.transitive.dependencies>false</include.transitive.dependencies> + </properties> + <dependencies> + <dependency> + <groupId>org.openecomp.appc</groupId> + <artifactId>appc-rest-healthcheck-adapter-features</artifactId> + <classifier>features</classifier> + <type>xml</type> + <exclusions> + <exclusion> + <groupId>*</groupId> + <artifactId>*</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.openecomp.appc</groupId> + <artifactId>appc-rest-healthcheck-adapter-bundle</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> + <build> + <plugins> + <plugin> + <artifactId>maven-assembly-plugin</artifactId> + <executions> + <execution> + <id>maven-repo-zip</id> + <goals> + <goal>single</goal> + </goals> + <phase>package</phase> + <configuration> + <appendAssemblyId>false</appendAssemblyId> + <attach>false</attach> + <finalName>stage/${application.name}-${project.version}</finalName> + <descriptors> + <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor> + </descriptors> + </configuration> + </execution> + <execution> + <id>installer-zip</id> + <goals> + <goal>single</goal> + </goals> + <phase>package</phase> + <configuration> + <appendAssemblyId>false</appendAssemblyId> + <attach>true</attach> + <finalName>${application.name}-${project.version}</finalName> + <descriptors> + <descriptor>src/assembly/assemble_installer_zip.xml</descriptor> + </descriptors> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <executions> + <execution> + <id>copy-dependencies</id> + <goals> + <goal>copy-dependencies</goal> + </goals> + <phase>prepare-package</phase> + <configuration> + <transitive>false</transitive> + <outputDirectory>${project.build.directory}/assembly/system</outputDirectory> + <overWriteReleases>false</overWriteReleases> + <overWriteSnapshots>true</overWriteSnapshots> + <overWriteIfNewer>true</overWriteIfNewer> + <useRepositoryLayout>true</useRepositoryLayout> + <addParentPoms>false</addParentPoms> + <copyPom>false</copyPom> + <excludeGroupIds>org.opendaylight</excludeGroupIds> + <scope>provided</scope> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-resources-plugin</artifactId> + <executions> + <execution> + <id>copy-version</id> + <goals> + <goal>copy-resources</goal> + </goals> + <!-- here the phase you need --> + <phase>validate</phase> + <configuration> + <outputDirectory>${basedir}/target/stage</outputDirectory> + <resources> + <resource> + <directory>src/main/resources/scripts</directory> + <includes> + <include>install-feature.sh</include> + </includes> + <filtering>true</filtering> + </resource> + </resources> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project> diff --git a/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-installer/src/assembly/assemble_installer_zip.xml b/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-installer/src/assembly/assemble_installer_zip.xml new file mode 100644 index 000000000..9fbaad8c5 --- /dev/null +++ b/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-installer/src/assembly/assemble_installer_zip.xml @@ -0,0 +1,59 @@ +<!-- + ============LICENSE_START======================================================= + openECOMP : APP-C + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights + reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + +<!-- Defines how we build the .zip file which is our distribution. --> + +<assembly + xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd"> + <id>adapter</id> + <formats> + <format>zip</format> + </formats> + + <!-- we want "system" and related files right at the root level + as this file is suppose to be unzip on top of a karaf + distro. --> + <includeBaseDirectory>false</includeBaseDirectory> + + <fileSets> + <fileSet> + <directory>target/stage/</directory> + <outputDirectory>${application.name}</outputDirectory> + <fileMode>755</fileMode> + <includes> + <include>*.sh</include> + </includes> + </fileSet> + <fileSet> + <directory>target/stage/</directory> + <outputDirectory>${application.name}</outputDirectory> + <fileMode>644</fileMode> + <excludes> + <exclude>*.sh</exclude> + </excludes> + </fileSet> + </fileSets> + + + +</assembly> diff --git a/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-installer/src/assembly/assemble_mvnrepo_zip.xml b/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-installer/src/assembly/assemble_mvnrepo_zip.xml new file mode 100644 index 000000000..1ac5a82bc --- /dev/null +++ b/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-installer/src/assembly/assemble_mvnrepo_zip.xml @@ -0,0 +1,47 @@ +<!-- + ============LICENSE_START======================================================= + openECOMP : APP-C + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights + reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + +<!-- Defines how we build the .zip file which is our distribution. --> + +<assembly + xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd"> + <id>adapter</id> + <formats> + <format>zip</format> + </formats> + + <!-- we want "system" and related files right at the root level + as this file is suppose to be unzip on top of a karaf + distro. --> + <includeBaseDirectory>false</includeBaseDirectory> + + <fileSets> + <fileSet> + <directory>target/assembly/</directory> + <outputDirectory>.</outputDirectory> + <excludes> + </excludes> + </fileSet> + </fileSets> + +</assembly> diff --git a/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-installer/src/main/resources/scripts/install-feature.sh b/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-installer/src/main/resources/scripts/install-feature.sh new file mode 100644 index 000000000..1d769fada --- /dev/null +++ b/appc-adapters/appc-rest-healthcheck-adapter/appc-rest-healthcheck-adapter-installer/src/main/resources/scripts/install-feature.sh @@ -0,0 +1,40 @@ +### +# ============LICENSE_START======================================================= +# openECOMP : APP-C +# ================================================================================ +# Copyright (C) 2017 AT&T Intellectual Property. All rights +# reserved. +# ================================================================================ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============LICENSE_END========================================================= +### + +#!/bin/bash + +ODL_HOME=${ODL_HOME:-/opt/opendaylight/current} +ODL_KARAF_CLIENT=${ODL_KARAF_CLIENT:-${ODL_HOME}/bin/client} +ODL_KARAF_CLIENT_OPTS=${ODL_KARAF_CLIENT_OPTS:-"-u karaf"} +INSTALLERDIR=$(dirname $0) + +REPOZIP=${INSTALLERDIR}/${features.boot}-${project.version}.zip + +if [ -f ${REPOZIP} ] +then + unzip -n -d ${ODL_HOME} ${REPOZIP} +else + echo "ERROR : repo zip ($REPOZIP) not found" + exit 1 +fi + +${ODL_KARAF_CLIENT} ${ODL_KARAF_CLIENT_OPTS} feature:repo-add ${features.repositories} +${ODL_KARAF_CLIENT} ${ODL_KARAF_CLIENT_OPTS} feature:install ${features.boot} diff --git a/appc-adapters/appc-rest-healthcheck-adapter/pom.xml b/appc-adapters/appc-rest-healthcheck-adapter/pom.xml new file mode 100644 index 000000000..fd95c0bf6 --- /dev/null +++ b/appc-adapters/appc-rest-healthcheck-adapter/pom.xml @@ -0,0 +1,125 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.openecomp.appc</groupId> + <artifactId>appc-adapters</artifactId> + <version>1.1.0-SNAPSHOT</version> + </parent> + + <artifactId>appc-rest-healthcheck-adapter</artifactId> + <name>rest healthcheck adaptor</name> + <description>Abstraction to connect to and utilize the services of cloud providers such as OpenStack or VMWare.</description> + <packaging>pom</packaging> + + <reporting> + <plugins> + <plugin> + <artifactId>maven-javadoc-plugin</artifactId> + <configuration> + <additionalDependencies> + <additionalDependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + <version>${slf4j.version}</version> + </additionalDependency> + <additionalDependency> + <groupId>org.antlr</groupId> + <artifactId>antlr4</artifactId> + <version>${antlr.version}</version> + </additionalDependency> + <additionalDependency> + <groupId>org.antlr</groupId> + <artifactId>antlr4-runtime</artifactId> + <version>4.3</version> + </additionalDependency> + </additionalDependencies> + </configuration> + <reportSets> + <reportSet> + <reports> + <report>javadoc-no-fork</report> + <report>test-javadoc-no-fork</report> + </reports> + </reportSet> + <reportSet> + <id>aggregate</id> + <reports> + <report>aggregate</report> + <report>test-aggregate</report> + </reports> + </reportSet> + </reportSets> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jxr-plugin</artifactId> + <version>2.3</version> + <reportSets> + <reportSet> + <id>aggregate</id> + <reports> + <report>aggregate</report> + <report>test-aggregate</report> + </reports> + </reportSet> + </reportSets> + </plugin> + + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-changelog-plugin</artifactId> + <version>2.3</version> + <reportSets> + <reportSet> + <id>dual-report</id> + <configuration> + <type>range</type> + <range>30</range> + </configuration> + <reports> + <report>changelog</report> + <report>file-activity</report> + </reports> + </reportSet> + </reportSets> + </plugin> + + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>taglist-maven-plugin</artifactId> + <version>2.4</version> + </plugin> + </plugins> + </reporting> + + <dependencyManagement> + <dependencies> + <dependency> + <groupId>org.openecomp.appc</groupId> + <artifactId>appc-rest-healthcheck-adapter-features</artifactId> + <classifier>features</classifier> + <type>xml</type> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>org.openecomp.appc</groupId> + <artifactId>appc-rest-healthcheck-adapter-provider</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> + + + </dependencyManagement> + + <modules> + <module>appc-rest-healthcheck-adapter-bundle</module> + <module>appc-rest-healthcheck-adapter-features</module> + <module>appc-rest-healthcheck-adapter-installer</module> + </modules> +</project> diff --git a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-api/src/main/java/org/openecomp/appc/adapter/ssh/Constants.java b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-api/src/main/java/org/openecomp/appc/adapter/ssh/Constants.java index 7eb069f55..5443d5de9 100644 --- a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-api/src/main/java/org/openecomp/appc/adapter/ssh/Constants.java +++ b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-api/src/main/java/org/openecomp/appc/adapter/ssh/Constants.java @@ -46,14 +46,37 @@ public class Constants { // input fields names public static final String PAYLOAD = "payload"; + public static final String CONNECTION_RETRY_DELAY = "org.openecomp.appc.ssh.connection.retry.delay"; + public static final String CONNECTION_RETRY_COUNT = "org.openecomp.appc.ssh.connection.retry.count"; + public static final int DEFAULT_CONNECTION_RETRY_DELAY = 60; + public static final int DEFAULT_CONNECTION_RETRY_COUNT = 5; - public static final String PARAM_IN_connection_details = "connection-details"; + public static final int DEFAULT_SSH_COMMAND_RETRY_COUNT = 3; + + public static final int DEFAULT_CHECKACTIVE_RETRY_COUNT = 3; + public static final int DEFAULT_CHECKACTIVE_RETRY_DELAY = 30; + + public static final int DEFAULT_STOP_RETRY_COUNT = 3; + public static final int DEFAULT_STOP_RETRY_DELAY = 30; //seconds + + public static final String PARAM_IN_CONNECTION_DETAILS = "connection-details"; + public static final String PARAM_IN_NODE_NAME = "node-name"; + public static final String PARAM_IN_NODE_STATUS = "node-status"; + public static final String PARAM_IN_VM_URL = "vm-url"; public static final String SKIP_EXECUTION_INSTALLER_BIN_FILE = "Skip-execution-installer-bin-file"; public static final String SKIP_DEPLOY = "Skip-deploy"; public static final String UPGRADE_VERSION = "upgrade-version"; //command to get number of UP hosts public static final String STATE_COMMAND = "/opt/jnetx/skyfall-scp/asp-state.sh | grep -o UP | wc -l"; + //command to get each VNFC status + public static final String VNFC_STATE_COMMAND = "/opt/jnetx/skyfall-scp/asp-state.sh"; + //command to restart node + public static final String RESTART_NODE_COMMAND = "/opt/jnetx/skyfall-scp/asp-stop.sh --restart -f --nodes"; + //command to start node + public static final String START_NODE_COMMAND = "/opt/jnetx/skyfall-scp/asp-start.sh -f --nodes"; + //command to stop node + public static final String STOP_NODE_COMMAND = "/opt/jnetx/skyfall-scp/asp-stop.sh -f --nodes"; public static final int STATE_COMMAND_RESULT = 18; //commands to check FE hosts public static final String FE_STATE_TRUE_TEST_COMMAND = "ssh -t -q fe1 /opt/omni/bin/swmml -e display-platform-status | grep -o TRUE | wc -l"; @@ -62,6 +85,12 @@ public class Constants { public static final int FE_STATE_FALSE_TEST_RESULT = 2; public static final String FE_OPERATIONAL_TEST_COMMAND = "ssh -t -q fe1 /opt/omni/bin/swmml -e display-platform-status | grep -o 'NOT FULLY OPERATIONAL' | wc -l"; public static final int FE_OPERATIONAL_TEST_RESULT = 2; + + //smp commands + public static final String SMP_CHECK_ACTIVE_STATE_COMMAND = "cat skyfall-scp/runtime/SCP_SMP_*/smp/log/system.log| grep SSS | tail -1"; + public static final String SMP_STATE_ACTIVE="SMP is active"; + public static final String SMP_STATE_INACTIVE="SMP is not active"; + //rsync command public static final String RSYNC_COMMAND = "yes n | /opt/jnetx/skyfall-scp/asp-rsync.sh --check | grep -o 'is active' | wc -l"; public static final int RSYNC_COMMAND_RESULT = 9; @@ -70,17 +99,19 @@ public class Constants { public static final String PARAM_IN_FILE_URL = "source-file-url"; public static final String DOWNLOAD_COMMAND = "wget -N %s"; - // pre-define jnetx VM names + // pre-define VM names public static final String[] VM_NAMES = {"fe1", "fe2", "be1", "be2", "be3", "be4", "be5", "smp1", "smp2"}; public static final String DEFAULT_DISK_SPACE = "10240000"; public static final String DF_COMMAND_TEMPLATE = "ssh %s df | grep vda1 | grep -v grep | tr -s ' '|cut -d ' ' -f4"; public static final String DG_OUTPUT_STATUS_MESSAGE = "output.status.message"; + public static final String ATTRIBUTE_ERROR_MESSAGE = "error-message"; - // constants fo DG - public static final String CONNECTION_DETAILS_FIELD_NAME = "connection-details"; + // constants for DG + public static final String CONNECTION_DETAILS_FIELD_NAME = PARAM_IN_CONNECTION_DETAILS; public static final String VNF_HOST_IP_ADDRESS_FIELD_NAME = "vnf-host-ip-address"; - public static final String DG_ERROR_FIELD_NAME = "org.openecomp.appc.dg.error"; + public static final String VNF_HOST_IP2_ADDRESS_FIELD_NAME = "vnf-host-ip2-address"; + public static final String DG_ERROR_FIELD_NAME = "org.openecom.appc.dg.error"; } diff --git a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-api/src/main/java/org/openecomp/appc/adapter/ssh/SshConnection.java b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-api/src/main/java/org/openecomp/appc/adapter/ssh/SshConnection.java index 0b3275f5d..39faa321f 100644 --- a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-api/src/main/java/org/openecomp/appc/adapter/ssh/SshConnection.java +++ b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-api/src/main/java/org/openecomp/appc/adapter/ssh/SshConnection.java @@ -34,6 +34,11 @@ public interface SshConnection { void connect(); /** + * Connect to SSH Server using a retry mechanism + */ + void connectWithRetry(); + + /** * Disconnect from SSH server. */ void disconnect(); diff --git a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-features/src/main/resources/features.xml b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-features/src/main/resources/features.xml index 6f565dc09..2984a16cd 100644 --- a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-features/src/main/resources/features.xml +++ b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-features/src/main/resources/features.xml @@ -25,6 +25,8 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0"> <feature name='appc-ssh-adapter' description="appc-ssh-adapter" version='${project.version}'> +<!-- <feature version='${sdnctl.dblib.version}'>sdnc-dblib</feature> --> + <bundle dependency="true">mvn:org.openecomp.appc/appc-common/${project.version}</bundle> <bundle>mvn:org.openecomp.appc/appc-ssh-adapter-api/${project.version}</bundle> <bundle>mvn:org.openecomp.appc/appc-ssh-adapter-sshd/${project.version}</bundle> </feature> diff --git a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/pom.xml b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/pom.xml index 35bb0cf92..76601450e 100644 --- a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/pom.xml +++ b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/pom.xml @@ -1,62 +1,64 @@ <?xml version="1.0" encoding="UTF-8"?> -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - <modelVersion>4.0.0</modelVersion> - <parent> - <groupId>org.openecomp.appc</groupId> - <artifactId>appc-ssh-adapter</artifactId> - <version>1.1.0-SNAPSHOT</version> - </parent> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.openecomp.appc</groupId> + <artifactId>appc-ssh-adapter</artifactId> + <version>1.1.0-SNAPSHOT</version> + </parent> - <artifactId>appc-ssh-adapter-sshd</artifactId> - <packaging>bundle</packaging> + <artifactId>appc-ssh-adapter-sshd</artifactId> + <packaging>bundle</packaging> - <dependencies> - <dependency> - <groupId>org.openecomp.appc</groupId> - <artifactId>appc-ssh-adapter-api</artifactId> - <version>${project.version}</version> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>org.apache.sshd</groupId> - <artifactId>sshd-core</artifactId> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>com.att.eelf</groupId> - <artifactId>eelf-core</artifactId> - </dependency> - <dependency> - <groupId>junit</groupId> - <artifactId>junit</artifactId> - </dependency> - <dependency> - <groupId>org.openecomp.appc</groupId> - <artifactId>appc-common</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> - <groupId>org.openecomp.sdnc.core</groupId> - <artifactId>dblib-provider</artifactId> - </dependency> - </dependencies> + <dependencies> + <dependency> + <groupId>org.openecomp.appc</groupId> + <artifactId>appc-ssh-adapter-api</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.apache.sshd</groupId> + <artifactId>sshd-core</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.att.eelf</groupId> + <artifactId>eelf-core</artifactId> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.openecomp.appc</groupId> + <artifactId>appc-common</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>dblib-provider</artifactId> + </dependency> + </dependencies> - <build> - <plugins> - <plugin> - <groupId>org.apache.felix</groupId> - <artifactId>maven-bundle-plugin</artifactId> - <extensions>true</extensions> - <configuration> - <instructions> - <Export-Service>org.openecomp.appc.adapter.ssh.SshAdapter</Export-Service> - <Private-Package>org.openecomp.appc.adapter.ssh.impl.*</Private-Package> - <Import-Package>!org.apache.log,!org.apache.commons.logging,!groovy.lang,!javax.jms,!org.codehaus.commons.compiler,!org.codehaus.groovy.*,!org.codehaus.janino,!com.ibm.icu.*,!com.sun.faces.*,!org.jasypt.*,*;resolution:=optional</Import-Package> - <Embed-Dependency>!dblib-provider,appc-common,jasypt,eelf-core,logback-core,logback-classic;scope=compile|runtime;inline=false</Embed-Dependency> - <Embed-Transitive>true</Embed-Transitive> - </instructions> - </configuration> - </plugin> - </plugins> - </build> + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Export-Service>org.openecomp.appc.adapter.ssh.SshAdapter</Export-Service> + <Private-Package>org.openecomp.appc.adapter.ssh.impl.*</Private-Package> + <Import-Package>!org.apache.log,!org.apache.commons.logging,!groovy.lang,!javax.jms,!org.codehaus.commons.compiler,!org.codehaus.groovy.*,!org.codehaus.janino,!com.ibm.icu.*,!com.sun.faces.*,!org.jasypt.*,*</Import-Package> + <Embed-Dependency>!dblib-provider,jasypt,eelf-core,logback-core,logback-classic;scope=compile|runtime;inline=false</Embed-Dependency> + <Embed-Transitive>true</Embed-Transitive> + </instructions> + </configuration> + </plugin> + </plugins> + </build> </project> diff --git a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/java/org/openecomp/appc/adapter/ssh/sshd/SshConnectionSshd.java b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/java/org/openecomp/appc/adapter/ssh/sshd/SshConnectionSshd.java index 4d8b83b6f..e87bfa264 100644 --- a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/java/org/openecomp/appc/adapter/ssh/sshd/SshConnectionSshd.java +++ b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/java/org/openecomp/appc/adapter/ssh/sshd/SshConnectionSshd.java @@ -21,6 +21,12 @@ package org.openecomp.appc.adapter.ssh.sshd; +import org.openecomp.appc.adapter.ssh.Constants; +import org.openecomp.appc.adapter.ssh.SshConnection; +import org.openecomp.appc.adapter.ssh.SshException; +import org.openecomp.appc.encryption.EncryptionTool; +import org.openecomp.appc.configuration.Configuration; +import org.openecomp.appc.configuration.ConfigurationFactory; import org.apache.sshd.ClientChannel; import org.apache.sshd.ClientSession; import org.apache.sshd.SshClient; @@ -29,9 +35,7 @@ import org.apache.sshd.client.future.AuthFuture; import org.apache.sshd.client.future.OpenFuture; import org.apache.sshd.common.KeyPairProvider; import org.apache.sshd.common.keyprovider.FileKeyPairProvider; -import org.openecomp.appc.adapter.ssh.SshConnection; -import org.openecomp.appc.adapter.ssh.SshException; -import org.openecomp.appc.encryption.EncryptionTool; + import com.att.eelf.configuration.EELFLogger; import com.att.eelf.configuration.EELFManager; @@ -43,130 +47,187 @@ import java.security.KeyPair; */ class SshConnectionSshd implements SshConnection { - private static final EELFLogger logger = EELFManager.getInstance().getApplicationLogger(); - - private static final long AUTH_TIMEOUT = 60000; - private static final long EXEC_TIMEOUT = 120000; - - private String host; - private int port; - private String username; - private String password; - private long timeout = EXEC_TIMEOUT; - private String keyFile; - private SshClient sshClient; - private ClientSession clientSession; - - public SshConnectionSshd(String host, int port, String username, String password, String keyFile) { - this.host = host; - this.port = port; - this.username = username; - this.password = password; - this.keyFile = keyFile; - } - - public SshConnectionSshd(String host, int port, String username, String password) { - this(host, port, username, password, null); - } - - public SshConnectionSshd(String host, int port, String keyFile) { - this(host, port, null, null, keyFile); - } - - @Override - public void connect() { - sshClient = SshClient.setUpDefaultClient(); - sshClient.start(); - try { - clientSession = sshClient.connect(EncryptionTool.getInstance().decrypt(username), host, port).await().getSession(); - if(password != null) { - clientSession.addPasswordIdentity(EncryptionTool.getInstance().decrypt(password)); - } - if(keyFile != null) { - KeyPairProvider keyPairProvider = new FileKeyPairProvider(new String[]{keyFile}); - KeyPair keyPair = keyPairProvider.loadKeys().iterator().next(); - clientSession.addPublicKeyIdentity(keyPair); - } - AuthFuture authFuture = clientSession.auth(); - authFuture.await(AUTH_TIMEOUT); - if(!authFuture.isSuccess()) { - throw new SshException("Error establishing ssh connection to [" + username + "@" + host + ":" + port + "]. Authentication failed."); - } - } catch(RuntimeException e) { - throw e; - } catch(Exception e) { - throw new SshException("Error establishing ssh connection to [" + username + "@" + host + ":" + port + "].", e); - } - if(logger.isDebugEnabled()) { - logger.debug("SSH: connected to [" + toString() + "]"); - } - } - - @Override - public void disconnect() { - try { - if(logger.isDebugEnabled()) { - logger.debug("SSH: disconnecting from [" + toString() + "]"); - } - clientSession.close(false); - } finally { - if(sshClient != null) { - sshClient.stop(); - } - } - } - - @Override - public void setExecTimeout(long timeout) { - this.timeout = timeout; - } - - @Override - public int execCommand(String cmd, OutputStream out, OutputStream err) { - return execCommand(cmd, out, err, false); - } - - @Override - public int execCommandWithPty(String cmd, OutputStream out) { - return execCommand(cmd, out, out, true); - } - - private int execCommand(String cmd, OutputStream out, OutputStream err, boolean usePty) { - try { - if(logger.isDebugEnabled()) { - logger.debug("SSH: executing command"); - } - ChannelExec client = clientSession.createExecChannel(cmd); + private static final EELFLogger logger = EELFManager.getInstance().getApplicationLogger(); + + private static final long AUTH_TIMEOUT = 60000; + private static final long EXEC_TIMEOUT = 120000; + + private String host; + private int port; + private String username; + private String password; + private long timeout = EXEC_TIMEOUT; + private String keyFile; + private SshClient sshClient; + private ClientSession clientSession; + private static final Configuration configuration = ConfigurationFactory.getConfiguration(); + + public SshConnectionSshd(String host, int port, String username, String password, String keyFile) { + this.host = host; + this.port = port; + this.username = username; + this.password = password; + this.keyFile = keyFile; + } + + public SshConnectionSshd(String host, int port, String username, String password) { + this(host, port, username, password, null); + } + + public SshConnectionSshd(String host, int port, String keyFile) { + this(host, port, null, null, keyFile); + } + + @Override + public void connect() { + sshClient = SshClient.setUpDefaultClient(); + sshClient.start(); + try { + clientSession = + sshClient.connect(EncryptionTool.getInstance().decrypt(username), host, port).await().getSession(); + if (password != null) { + clientSession.addPasswordIdentity(EncryptionTool.getInstance().decrypt(password)); + } + if (keyFile != null) { + KeyPairProvider keyPairProvider = new FileKeyPairProvider(new String[] { + keyFile + }); + KeyPair keyPair = keyPairProvider.loadKeys().iterator().next(); + clientSession.addPublicKeyIdentity(keyPair); + } + AuthFuture authFuture = clientSession.auth(); + authFuture.await(AUTH_TIMEOUT); + if (!authFuture.isSuccess()) { + throw new SshException("Error establishing ssh connection to [" + username + "@" + host + ":" + port + + "]. Authentication failed."); + } + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new SshException("Error establishing ssh connection to [" + username + "@" + host + ":" + port + "].", + e); + } + if (logger.isDebugEnabled()) { + logger.debug("SSH: connected to [" + toString() + "]"); + } + } + + @Override + public void connectWithRetry() { + int retryCount = 0; + int retryDelay = 0; + int retriesLeft = 0; + retryCount = configuration.getIntegerProperty(Constants.CONNECTION_RETRY_COUNT, + Constants.DEFAULT_CONNECTION_RETRY_COUNT); + retryDelay = configuration.getIntegerProperty(Constants.CONNECTION_RETRY_DELAY, + Constants.DEFAULT_CONNECTION_RETRY_DELAY); + retriesLeft = retryCount + 1; + do { + try { + this.connect(); + break; + } catch (RuntimeException e) { + if (retriesLeft > 1) { + logger.debug("SSH Connection failed. Waiting for change in server's state."); + waitForConnection(retryDelay); + retriesLeft--; + logger.debug("Retrying SSH connection. Attempt [" + Integer.toString(retryCount - retriesLeft + 1) + + "] out of [" + retryCount + "]"); + } else { + throw e; + } + } catch (Exception e) { + throw e; + } + } while (retriesLeft > 0); + } + + @Override + public void disconnect() { + try { + if (logger.isDebugEnabled()) { + logger.debug("SSH: disconnecting from [" + toString() + "]"); + } + clientSession.close(false); + } finally { + if (sshClient != null) { + sshClient.stop(); + } + } + } + + @Override + public void setExecTimeout(long timeout) { + this.timeout = timeout; + } + + @Override + public int execCommand(String cmd, OutputStream out, OutputStream err) { + return execCommand(cmd, out, err, false); + } + + @Override + public int execCommandWithPty(String cmd, OutputStream out) { + return execCommand(cmd, out, out, true); + } + + private int execCommand(String cmd, OutputStream out, OutputStream err, boolean usePty) { + try { + if (logger.isDebugEnabled()) { + logger.debug("SSH: executing command"); + } + ChannelExec client = clientSession.createExecChannel(cmd); client.setUsePty(usePty); // use pseudo-tty? - client.setOut(out); - client.setErr(err); - OpenFuture openFuture = client.open(); - int exitStatus = 0; - try { - client.waitFor(ClientChannel.CLOSED, timeout); - openFuture.verify(); - Integer exitStatusI = client.getExitStatus(); - if(exitStatusI == null) { - throw new SshException("Error executing command [" + cmd + "] over SSH [" + username + "@" + host + ":" + port + "]. Operation timed out."); - } - exitStatus = exitStatusI; - } finally { - client.close(false); - } - return exitStatus; - } catch(RuntimeException e) { - throw e; - } catch(Exception t) { - throw new SshException("Error executing command [" + cmd + "] over SSH [" + username + "@" + host + ":" + port + "]", t); - } - } - - @Override - public String toString() { - String address = host; - if(username != null) { - address = username + '@' +address; - } - return address; - } + client.setOut(out); + client.setErr(err); + OpenFuture openFuture = client.open(); + int exitStatus = 0; + try { + client.waitFor(ClientChannel.CLOSED, timeout); + openFuture.verify(); + Integer exitStatusI = client.getExitStatus(); + if (exitStatusI == null) { + throw new SshException("Error executing command [" + cmd + "] over SSH [" + username + "@" + host + + ":" + port + "]. Operation timed out."); + } + exitStatus = exitStatusI; + } finally { + client.close(false); + } + return exitStatus; + } catch (RuntimeException e) { + throw e; + } catch (Exception t) { + throw new SshException( + "Error executing command [" + cmd + "] over SSH [" + username + "@" + host + ":" + port + "]", t); + } + } + + private void waitForConnection(int retryDelay) { + long time = retryDelay * 1000L; + long future = System.currentTimeMillis() + time; + if (time != 0) { + while (System.currentTimeMillis() < future && time > 0) { + try { + Thread.sleep(time); + } catch (InterruptedException e) { + /* + * This is rare, but it can happen if another thread interrupts us while we are sleeping. In that + * case, the thread is resumed before the delay time has actually expired, so re-calculate the + * amount of delay time needed and reenter the sleep until we get to the future time. + */ + time = future - System.currentTimeMillis(); + } + } + } + } + + @Override + public String toString() { + String address = host; + if (username != null) { + address = username + '@' + address; + } + return address; + } } diff --git a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/java/org/openecomp/appc/adapter/ssh/sshd/SshdDataAccessService.java b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/java/org/openecomp/appc/adapter/ssh/sshd/SshdDataAccessService.java index a12e2be93..4e7f8d2f5 100644 --- a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/java/org/openecomp/appc/adapter/ssh/sshd/SshdDataAccessService.java +++ b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/java/org/openecomp/appc/adapter/ssh/sshd/SshdDataAccessService.java @@ -27,14 +27,11 @@ import org.openecomp.appc.adapter.ssh.Constants; import org.openecomp.appc.adapter.ssh.SshConnectionDetails; import org.openecomp.appc.adapter.ssh.SshDataAccessException; import org.openecomp.appc.adapter.ssh.SshDataAccessService; -import org.openecomp.appc.exceptions.APPCException; import org.openecomp.sdnc.sli.resource.dblib.DbLibService; import java.sql.SQLException; import java.util.ArrayList; - - public class SshdDataAccessService implements SshDataAccessService { private String schema = Constants.NETCONF_SCHEMA; diff --git a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/resources/OSGI-INF/blueprint/blueprint.xml index f9d10868a..d6c0f686f 100644 --- a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/resources/OSGI-INF/blueprint/blueprint.xml +++ b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -22,17 +22,17 @@ <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd"> + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd"> - <bean id="sshdBean" class="org.openecomp.appc.adapter.ssh.sshd.SshAdapterSshd" scope="singleton"/> - <service id="sshAdapter" interface="org.openecomp.appc.adapter.ssh.SshAdapter" ref="sshdBean"/> + <bean id="sshdBean" class="org.openecomp.appc.adapter.ssh.sshd.SshAdapterSshd" scope="singleton"/> + <service id="sshAdapter" interface="org.openecomp.appc.adapter.ssh.SshAdapter" ref="sshdBean"/> - <reference id="dbLibServiceRef" availability="mandatory" activation="eager" interface="org.openecomp.sdnc.sli.resource.dblib.DbLibService" /> - <bean id="sshdDAServiceBean" class="org.openecomp.appc.adapter.ssh.sshd.SshdDataAccessService" scope="singleton"> - <property name="dbLibService" ref="dbLibServiceRef" /> - </bean> + <reference id="dbLibServiceRef" availability="mandatory" activation="eager" interface="org.openecomp.sdnc.sli.resource.dblib.DbLibService" /> + <bean id="sshdDAServiceBean" class="org.openecomp.appc.adapter.ssh.sshd.SshdDataAccessService" scope="singleton"> + <property name="dbLibService" ref="dbLibServiceRef" /> + </bean> - <service id="sshDAService" interface="org.openecomp.appc.adapter.ssh.SshDataAccessService" ref="sshdDAServiceBean"/> + <service id="sshDAService" interface="org.openecomp.appc.adapter.ssh.SshDataAccessService" ref="sshdDAServiceBean"/> </blueprint> diff --git a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/test/java/org/openecomp/appc/adapter/ssh/sshd/SshAdapterTest.java b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/test/java/org/openecomp/appc/adapter/ssh/sshd/SshAdapterTest.java index 980395476..1d7d06df2 100644 --- a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/test/java/org/openecomp/appc/adapter/ssh/sshd/SshAdapterTest.java +++ b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-sshd/src/test/java/org/openecomp/appc/adapter/ssh/sshd/SshAdapterTest.java @@ -49,7 +49,6 @@ import java.security.PublicKey; import java.util.Collections; import java.util.EnumSet; -@Ignore public class SshAdapterTest { private static final boolean START_SERVER = true; diff --git a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-tests/src/main/java/org/openecomp/appc/adapter/ssh/SshAdapterMock.java b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-tests/src/main/java/org/openecomp/appc/adapter/ssh/SshAdapterMock.java index c0ccdfaee..df50396ed 100644 --- a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-tests/src/main/java/org/openecomp/appc/adapter/ssh/SshAdapterMock.java +++ b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-tests/src/main/java/org/openecomp/appc/adapter/ssh/SshAdapterMock.java @@ -24,9 +24,6 @@ package org.openecomp.appc.adapter.ssh; import java.util.ArrayList; import java.util.List; -import org.openecomp.appc.adapter.ssh.SshAdapter; -import org.openecomp.appc.adapter.ssh.SshConnection; - public class SshAdapterMock implements SshAdapter { private List<SshConnectionMock> connectionMocks = new ArrayList<>(); diff --git a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-tests/src/main/java/org/openecomp/appc/adapter/ssh/SshConnectionMock.java b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-tests/src/main/java/org/openecomp/appc/adapter/ssh/SshConnectionMock.java index 3194edcfb..ed03a6107 100644 --- a/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-tests/src/main/java/org/openecomp/appc/adapter/ssh/SshConnectionMock.java +++ b/appc-adapters/appc-ssh-adapter/appc-ssh-adapter-tests/src/main/java/org/openecomp/appc/adapter/ssh/SshConnectionMock.java @@ -59,6 +59,11 @@ public class SshConnectionMock implements SshConnection { } @Override + public void connectWithRetry() { + connectCallCount++; + } + + @Override public void disconnect() { disconnectCallCount++; } diff --git a/appc-adapters/pom.xml b/appc-adapters/pom.xml index 216b294d2..0e4e12c33 100644 --- a/appc-adapters/pom.xml +++ b/appc-adapters/pom.xml @@ -17,5 +17,6 @@ <module>appc-dmaap-adapter</module> <module>appc-netconf-adapter</module> <module>appc-ssh-adapter</module> + <module>appc-rest-healthcheck-adapter</module> </modules> </project> |