VNFC Support for Ansible actions 73/98973/3
authorLukasz Rajewski <lukasz.rajewski@orange.com>
Fri, 29 Nov 2019 15:16:28 +0000 (16:16 +0100)
committerTakamune Cho <takamune.cho@att.com>
Mon, 9 Dec 2019 23:54:29 +0000 (23:54 +0000)
Introduced AutoNodeList parameter for
ansible request template which allows to generate
NodeList section from infromation about VMs and VNFC
in the AAI. List is being filtered by vnfc-name,vserver-id,
vnfc-type and vf-module-id parameters which can be specified
in the request-parameters of payload section.

Change-Id: I3d5b79ab6ff778116856b513612721a9637363df
Signed-off-by: Lukasz Rajewski <lukasz.rajewski@orange.com>
Issue-ID: APPC-1729

appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/onap/appc/adapter/ansible/impl/AnsibleAdapterImpl.java
appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/onap/appc/adapter/ansible/model/AnsibleMessageParser.java
appc-directed-graph/appc-dgraph/provider/src/main/resources/json/APPC/APPC_Generic_AnsibleDG.json
appc-directed-graph/appc-dgraph/provider/src/main/resources/json/APPC/APPC_ansible-adapter-1.0.json
appc-provider/appc-provider-bundle/src/main/java/org/onap/appc/provider/lcm/service/AbstractBaseService.java

index 0ef64d5..576a576 100644 (file)
@@ -8,6 +8,8 @@
  * =============================================================================
  * Modifications Copyright (C) 2019 IBM
  * =============================================================================
+ * Modifications Copyright (C) 2019 Orange
+ * =============================================================================
  * 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
 
 package org.onap.appc.adapter.ansible.impl;
 
+import java.io.*;
 import java.util.Map;
+import java.util.HashMap;
 import java.util.Properties;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.InputStream;
+
 import org.apache.commons.lang.StringUtils;
 import org.json.JSONException;
 import org.json.JSONObject;
+import org.json.JSONArray;
 import org.onap.appc.adapter.ansible.AnsibleAdapter;
 import org.onap.appc.adapter.ansible.model.AnsibleMessageParser;
 import org.onap.appc.adapter.ansible.model.AnsibleResult;
@@ -284,6 +287,7 @@ public class AnsibleAdapterImpl implements AnsibleAdapter {
             // create json object to send request
             jsonPayload = messageProcessor.reqMessage(params);
 
+            logger.info("Initial Payload  = " + jsonPayload.toString());
             agentUrl = (String) jsonPayload.remove("AgentUrl");
             user = (String) jsonPayload.remove("User");
             password = (String)jsonPayload.remove(PASSWORD);
@@ -293,6 +297,20 @@ public class AnsibleAdapterImpl implements AnsibleAdapter {
             timeout = jsonPayload.getString("Timeout");
             if (StringUtils.isBlank(timeout))
                 timeout = "600";
+
+            String autoNodeList = (String) jsonPayload.remove("AutoNodeList");
+            if (autoNodeList != null && Boolean.parseBoolean(autoNodeList)) {
+                JSONArray generatedNodeList = generateNodeList(params, ctx);
+                if (generatedNodeList.length() > 0) {
+                    jsonPayload.put("NodeList", generatedNodeList);
+                    jsonPayload.put("InventoryNames", "VM");
+                } else {
+                    doFailure(ctx, AnsibleResultCodes.INVALID_PAYLOAD.getValue(),
+                            "Auto generation of Node List Failed - no elements on the list");
+                }
+            } else
+                logger.debug("Auto Node List is DISABLED");
+
             payload = jsonPayload.toString();
             ctx.setAttribute("AnsibleTimeout", timeout);
             logger.info("Updated Payload  = " + payload + " timeout = " + timeout);
@@ -360,6 +378,110 @@ public class AnsibleAdapterImpl implements AnsibleAdapter {
         ctx.setAttribute(ID_ATTRIBUTE_NAME, id);
     }
 
+    /**
+     * Method is used to automatically generate NodeList section base on the svc context
+     *
+     * @see org.onap.appc.adapter.ansible.AnsibleAdapter#reqExecResult(java.util.Map,
+     *      org.onap.ccsdk.sli.core.sli.SvcLogicContext)
+     */
+    private JSONArray generateNodeList(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
+        String vfModuleId = params.get("vf-module-id");
+        String vnfcName = params.get("vnfc-name");
+        String vServerId = params.get("vserver-id");
+        String vnfcType = params.get("vnfc-type");
+        logger.info("GENERATING NODE LIST");
+        JSONArray result = new JSONArray();
+
+        if (vServerId != null && !vServerId.equals(""))
+            logger.debug("Auto Node List filtering parameter vserver-id " + vServerId);
+        else
+            vServerId = null;
+        if (vnfcName != null && !vnfcName.equals(""))
+            logger.debug("Auto Node List filtering parameter vnfc-name " + vnfcName);
+        else
+            vnfcName = null;
+        if (vnfcType != null && !vnfcType.equals(""))
+            logger.debug("Auto Node List filtering parameter vnfc-type " + vnfcType);
+        else
+            vnfcType = null;
+        if (vfModuleId != null && !vfModuleId.equals(""))
+            logger.debug("Auto Node List filtering parameter vf-module-id " + vfModuleId);
+        else
+            vfModuleId = null;
+
+        Map<String, JSONObject> candidates = new HashMap<String, JSONObject>();
+        for (int i = 0; ; i++) {
+            String vmKey = "tmp.vnfInfo.vm[" + Integer.toString(i) + "]";
+            logger.info("Looking for attributes of: " + vmKey);
+            if (ctx.getAttribute(vmKey + ".vnfc-name") != null) {
+                String vmVnfcName = ctx.getAttribute(vmKey + ".vnfc-name");
+                String vmVnfcIpv4Address = ctx.getAttribute(vmKey + ".vnfc-ipaddress-v4-oam-vip");
+                String vmVnfcType = ctx.getAttribute(vmKey + ".vnfc-type");
+
+                if (vmVnfcName != null && vmVnfcIpv4Address != null && vmVnfcType != null
+                    && !vmVnfcName.equals("") && !vmVnfcIpv4Address.equals("") && !vmVnfcType.equals("")) {
+                    if (vServerId != null) {
+                        String vmVserverId = ctx.getAttribute(vmKey + ".vserver-id");
+                        if (vmVserverId == null || !vmVserverId.equals(vServerId)) {
+                            logger.debug("Auto Node List candidate " + vmVnfcName + " dropped. vserver-id mismatch");
+                            continue;
+                        }
+                    }
+                    if (vfModuleId != null) {
+                        String vmVfModuleId = ctx.getAttribute(vmKey + ".vf-module-id");
+                        if (vmVfModuleId == null || !vmVfModuleId.equals(vfModuleId)) {
+                            logger.debug("Auto Node List candidate " + vmVnfcName + " dropped. vf-module-id mismatch");
+                            continue;
+                        }
+                    }
+                    if (vnfcName != null) {
+                        if (!vmVnfcName.equals(vnfcName)) {
+                            logger.debug("Auto Node List candidate " + vmVnfcName + " dropped. vnfc-name mismatch");
+                            continue;
+                        }
+                    }
+                    if (vnfcType != null) {
+                        if (!vmVnfcType.equals(vnfcType)) {
+                            logger.debug("Auto Node List candidate " + vmVnfcType + " dropped. vnfc-type mismatch");
+                            continue;
+                        }
+                    }
+
+                    logger.info("Auto Node List candidate " + vmVnfcName + " [" + vmVnfcIpv4Address + "," + vmVnfcType + "]");
+
+                    JSONObject vnfTypeCandidates = null;
+                    JSONArray vmList = null;
+                    if (!candidates.containsKey(vmVnfcType)) {
+                        vnfTypeCandidates = new JSONObject();
+                        vmList = new JSONArray();
+                        vnfTypeCandidates.put("site", "site");
+                        vnfTypeCandidates.put("vnfc-type", vmVnfcType);
+                        vnfTypeCandidates.put("vm-info", vmList);
+                        candidates.put(vmVnfcType, vnfTypeCandidates);
+                    } else {
+                        vnfTypeCandidates = candidates.get(vmVnfcType);
+                        vmList = (JSONArray) vnfTypeCandidates.get("vm-info");
+                    }
+
+                    JSONObject candidate = new JSONObject();
+                    candidate.put("ne_id", vmVnfcName);
+                    candidate.put("fixed_ip_address", vmVnfcIpv4Address);
+                    vmList.put(candidate);
+                } else {
+                    logger.warn("Incomplete information for Auto Node List candidate " + vmKey);
+                }
+            } else
+                break;
+        }
+
+        for(JSONObject vnfcCandidates : candidates.values()) {
+            result.put(vnfcCandidates);
+        }
+
+        logger.info("GENERATING NODE LIST COMPLETED");
+        return result;
+    }
+
     /**
      * Public method to query status of a specific request It blocks till the
      * Ansible Server responds or the session times out (non-Javadoc)
index 0e0b893..ba65773 100644 (file)
@@ -8,6 +8,8 @@
  * =============================================================================
  * Modifications Copyright (C) 2019 IBM
  * =============================================================================
+ * Modifications Copyright (C) 2019 Orange
+ * =============================================================================
  * 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
@@ -62,6 +64,7 @@ public class AnsibleMessageParser {
     private static final String FILE_PARAMETERS_OPT_KEY = "FileParameters";
     private static final String ENV_PARAMETERS_OPT_KEY = "EnvParameters";
     private static final String NODE_LIST_OPT_KEY = "NodeList";
+    private static final String AUTO_NODE_LIST_OPT_KEY = "AutoNodeList";
     private static final String TIMEOUT_OPT_KEY = "Timeout";
     private static final String VERSION_OPT_KEY = "Version";
     private static final String INVENTORY_NAMES_OPT_KEY = "InventoryNames";
@@ -84,7 +87,8 @@ public class AnsibleMessageParser {
     public JSONObject reqMessage(Map<String, String> params) throws APPCException {
         final String[] mandatoryTestParams = { AGENT_URL_KEY, PLAYBOOK_NAME_KEY, USER_KEY, PASS_KEY };
         final String[] optionalTestParams = { ENV_PARAMETERS_OPT_KEY, NODE_LIST_OPT_KEY, LOCAL_PARAMETERS_OPT_KEY,
-                TIMEOUT_OPT_KEY, VERSION_OPT_KEY, FILE_PARAMETERS_OPT_KEY, ACTION_OPT_KEY, INVENTORY_NAMES_OPT_KEY };
+                TIMEOUT_OPT_KEY, VERSION_OPT_KEY, FILE_PARAMETERS_OPT_KEY, ACTION_OPT_KEY, INVENTORY_NAMES_OPT_KEY,
+                AUTO_NODE_LIST_OPT_KEY };
 
         JSONObject jsonPayload = new JSONObject();
 
@@ -302,7 +306,13 @@ public class AnsibleMessageParser {
             }
             jsonPayload.put(key, payload);
             break;
-
+        case AUTO_NODE_LIST_OPT_KEY:
+            if (payload.equalsIgnoreCase("true") || payload.equalsIgnoreCase("false")) {
+                jsonPayload.put(key, payload);
+            } else {
+                throw new IllegalArgumentException(" : specified invalid boolean value of AutoNodeList = " + payload);
+            }
+            break;
         case VERSION_OPT_KEY:
         case INVENTORY_NAMES_OPT_KEY:
             jsonPayload.put(key, payload);
index e89142c..85ea58b 100644 (file)
         "id": "92d97097.efde08",\r
         "type": "execute",\r
         "name": "execute Convert payload to DG Context ",\r
-        "xml": "<execute plugin=\"org.onap.sdnc.config.generator.convert.ConvertNode\" method=\"convertJson2DGContext\">\n<parameter name=\"jsonData\" value=\"`$tmp.merge.mergedData`\" />\n<parameter name=\"isEscaped\" value=\"Y\" />\n<parameter name=\"blockKeys\" value=\"EnvParameters,PlaybookName,Timeout,NodeList,FileParameters,InventoryNames\" />\n<parameter name=\"responsePrefix\" value=\"tmp.convertnode\" />",\r
+        "xml": "<execute plugin=\"org.onap.sdnc.config.generator.convert.ConvertNode\" method=\"convertJson2DGContext\">\n<parameter name=\"jsonData\" value=\"`$tmp.merge.mergedData`\" />\n<parameter name=\"isEscaped\" value=\"Y\" />\n<parameter name=\"blockKeys\" value=\"EnvParameters,PlaybookName,Timeout,NodeList,AutoNodeList,FileParameters,InventoryNames\" />\n<parameter name=\"responsePrefix\" value=\"tmp.convertnode\" />",\r
         "comments": "",\r
         "outputs": 1,\r
         "x": 612.6145477294922,\r
         "id": "b26ef86f.518fa8",\r
         "type": "set",\r
         "name": "set Payload params ",\r
-        "xml": "<set>\n<parameter name='PlaybookName' value='`$PlaybookName`' />\n<parameter name='NodeList' value='`$NodeList`'/>\n<parameter name='vnf_id' value='`$vnf-id`' />\n<parameter name='AgentUrl' value='`$url`'/>\n <parameter name='User' value='`$user`'/>\n  <parameter name='Password' value='`$password`'/>\n  <parameter name='EnvParameters' value='`$EnvParameters`'/>\n  <parameter name='Timeout' value='`$Timeout`'/>\n  <parameter name='InventoryNames' value='`$InventoryNames`'/>\n  <parameter name='FileParameters' value='`$FileParameters`'/>\n\n\n\n",\r
+        "xml": "<set>\n<parameter name='PlaybookName' value='`$PlaybookName`' />\n<parameter name='NodeList' value='`$NodeList`'/>\n<parameter name='AutoNodeList' value='`$AutoNodeList`'/>\n<parameter name='vnf_id' value='`$vnf-id`' />\n<parameter name='AgentUrl' value='`$url`'/>\n <parameter name='User' value='`$user`'/>\n  <parameter name='Password' value='`$password`'/>\n  <parameter name='EnvParameters' value='`$EnvParameters`'/>\n  <parameter name='Timeout' value='`$Timeout`'/>\n  <parameter name='InventoryNames' value='`$InventoryNames`'/>\n  <parameter name='FileParameters' value='`$FileParameters`'/>\n\n\n\n",\r
         "comments": "",\r
         "x": 463.9220733642578,\r
         "y": 592.0113525390625,\r
         "id": "833c47f4.4e765",\r
         "type": "set",\r
         "name": "set Payload params ",\r
-        "xml": "<set>\n<parameter name='PlaybookName' value='`$block_PlaybookName`' />\n<parameter name='NodeList' value ='`$block_NodeList`'/>\n<parameter name='vnf_id' value='`$vnf-id`' />\n<parameter name='EnvParameters' value='`$block_EnvParameters`'/>\n<parameter name='Timeout' value='`$block_Timeout`'/>\n<parameter name='InventoryNames' value='`$block_InventoryNames`'/>\n<parameter name='FileParameters' value='`$block_FileParameters`'/>\n\n\n\n",\r
+        "xml": "<set>\n<parameter name='PlaybookName' value='`$block_PlaybookName`' />\n<parameter name='NodeList' value ='`$block_NodeList`'/>\n<parameter name='AutoNodeList' value ='`$block_AutoNodeList`'/>\n<parameter name='vnf_id' value='`$vnf-id`' />\n<parameter name='EnvParameters' value='`$block_EnvParameters`'/>\n<parameter name='Timeout' value='`$block_Timeout`'/>\n<parameter name='InventoryNames' value='`$block_InventoryNames`'/>\n<parameter name='FileParameters' value='`$block_FileParameters`'/>\n\n\n\n",\r
         "comments": "",\r
         "x": 612.4444732666016,\r
         "y": 189.22222900390625,\r
index 838c8c4..d66047f 100644 (file)
@@ -48,7 +48,7 @@
         "id": "16608a2e.c8019e",\r
         "type": "execute",\r
         "name": "execute",\r
-        "xml": "<execute plugin='org.onap.appc.adapter.ansible.AnsibleAdapter' method='reqExec' >\n<parameter name='AgentUrl' value='`$AgentUrl`'/>\n  <parameter name='User' value='`$User`'/>\n                        <parameter name='Password' value='`$Password`'/>\n                        <parameter name='LocalParameters' value='`$LocalParameters`'/>\n                        <parameter name='EnvParameters' value='`$EnvParameters`'/>\n                        <parameter name='FileParameters' value='`$FileParameters`'/>\n                        <parameter name='NodeList' value='`$NodeList`'/>\n                        <parameter name='Timeout' value='`$Timeout`'/>\n                        <parameter name='Version' value='`$Version`'/>\n                        <parameter name='InventoryNames' value='`$InventoryNames`'/>\n                        <parameter name='PlaybookName' value='`$PlaybookName`'/>\n                        <parameter name='Action' value='`$Action`'/>\n",\r
+        "xml": "<execute plugin='org.onap.appc.adapter.ansible.AnsibleAdapter' method='reqExec' >\n<parameter name='AgentUrl' value='`$AgentUrl`'/>\n  <parameter name='User' value='`$User`'/>\n                        <parameter name='Password' value='`$Password`'/>\n                        <parameter name='LocalParameters' value='`$LocalParameters`'/>\n                        <parameter name='EnvParameters' value='`$EnvParameters`'/>\n                        <parameter name='FileParameters' value='`$FileParameters`'/>\n                        <parameter name='AutoNodeList' value='`$AutoNodeList`'/>\n                        <parameter name='NodeList' value='`$NodeList`'/>\n                        <parameter name='Timeout' value='`$Timeout`'/>\n                        <parameter name='Version' value='`$Version`'/>\n                        <parameter name='InventoryNames' value='`$InventoryNames`'/>\n                        <parameter name='PlaybookName' value='`$PlaybookName`'/>\n                        <parameter name='Action' value='`$Action`'/>\n                        <parameter name='vnfc-name' value='`$request-parameters.vnfc-name`'/>\n                        <parameter name='vnfc-type' value='`$request-parameters.vnfc-type`'/>\n                        <parameter name='vserver-id' value='`$request-parameters.vserver-id`'/>\n                        <parameter name='vf-module-id' value='`$request-parameters.vf-module-id`'/>\n",\r
         "comments": "",\r
         "outputs": 1,\r
         "x": 569,\r
index 6657c2f..eec8097 100644 (file)
@@ -127,7 +127,7 @@ public abstract class AbstractBaseService extends AbstractBaseUtils {
             return validatedStatus;
         }
 
-        validatedStatus = validateMustHaveParamValue(actionIdentifiers.getVnfId(), "vnf-id");
+        validatedStatus = validateMustHaveParamValue(actionIdentifiers.getVnfId(), ACTID_KEYS.VNF_ID.getKeyName());
         if (validatedStatus == null) {
             validatedStatus = validateExcludedActIds(actionIdentifiers, EnumSet.of(ACTID_KEYS.VNF_ID));
         }
@@ -135,6 +135,28 @@ public abstract class AbstractBaseService extends AbstractBaseUtils {
         return validatedStatus;
     }
 
+    /**
+     * Validate input as well as VF MODULE ID in actionIdentifier
+     *
+     * @param commonHeader      of the input
+     * @param action            of the input
+     * @param actionIdentifiers of the input
+     * @return null if validation passed, otherwise, return Status with validation failure details.
+     */
+    Status validateVfModuleId(CommonHeader commonHeader, Action action, ActionIdentifiers actionIdentifiers) {
+        Status validatedStatus = validateInput(commonHeader, action, actionIdentifiers);
+        if (validatedStatus != null) {
+            return validatedStatus;
+        }
+
+        validatedStatus = validateMustHaveParamValue(actionIdentifiers.getVfModuleId(), ACTID_KEYS.VF_MODULE_ID.getKeyName());
+        if (validatedStatus == null) {
+            validatedStatus = validateExcludedActIds(actionIdentifiers, EnumSet.of(ACTID_KEYS.VF_MODULE_ID));
+        }
+
+        return validatedStatus;
+    }
+
     /**
      * Validate input as well as VSERVER ID in actionIdentifier
      *
@@ -149,7 +171,7 @@ public abstract class AbstractBaseService extends AbstractBaseUtils {
             return validatedStatus;
         }
 
-        validatedStatus = validateMustHaveParamValue(actionIdentifiers.getVserverId(), "vserver-id");
+        validatedStatus = validateMustHaveParamValue(actionIdentifiers.getVserverId(), ACTID_KEYS.VSERVER_ID.getKeyName());
         if (validatedStatus == null) {
             validatedStatus = validateExcludedActIds(actionIdentifiers, EnumSet.of(ACTID_KEYS.VSERVER_ID));
         }
@@ -157,6 +179,78 @@ public abstract class AbstractBaseService extends AbstractBaseUtils {
         return validatedStatus;
     }
 
+    /**
+     * Validate input as well as VNFC NAME in actionIdentifier
+     *
+     * @param commonHeader      of the input
+     * @param action            of the input
+     * @param actionIdentifiers of the input
+     * @return null if validation passed, otherwise, return Status with validation failure details.
+     */
+    Status validateVnfcName(CommonHeader commonHeader, Action action, ActionIdentifiers actionIdentifiers) {
+        Status validatedStatus = validateInput(commonHeader, action, actionIdentifiers);
+        if (validatedStatus != null) {
+            return validatedStatus;
+        }
+
+        validatedStatus = validateMustHaveParamValue(actionIdentifiers.getVnfcName(), ACTID_KEYS.VNFC_NAME.getKeyName());
+        if (validatedStatus == null) {
+            validatedStatus = validateExcludedActIds(actionIdentifiers, EnumSet.of(ACTID_KEYS.VNFC_NAME));
+        }
+
+        return validatedStatus;
+    }
+
+    /**
+     * Validate input as well as VNFC NAME in actionIdentifier
+     *
+     * @param commonHeader      of the input
+     * @param action            of the input
+     * @param actionIdentifiers of the input
+     * @return null if validation passed, otherwise, return Status with validation failure details.
+     */
+    Status validateAllVnfActIds(CommonHeader commonHeader, Action action, ActionIdentifiers actionIdentifiers) {
+        Status validatedStatus = validateInput(commonHeader, action, actionIdentifiers);
+        if (validatedStatus != null) {
+            return validatedStatus;
+        }
+
+        validatedStatus = validateMustHaveParamValue(actionIdentifiers.getVnfId(), ACTID_KEYS.VNF_ID.getKeyName());
+
+        if (validatedStatus != null) {
+            return validatedStatus;
+        }
+
+        Status validatedFinalStatus = null;
+
+        for (ACTID_KEYS key : ACTID_KEYS.values()) {
+            if (key.equals(ACTID_KEYS.SERVICE_INSTANCE_ID) || key.equals(ACTID_KEYS.VNF_ID)) {
+                continue;
+            }
+            validatedStatus = null;
+            switch (key) {
+                case VF_MODULE_ID:
+                    validatedStatus = validateMustHaveParamValue(actionIdentifiers.getVfModuleId(),
+                            ACTID_KEYS.VF_MODULE_ID.getKeyName());
+                    break;
+                case VSERVER_ID:
+                    validatedStatus = validateMustHaveParamValue(actionIdentifiers.getVserverId(),
+                            ACTID_KEYS.VSERVER_ID.getKeyName());
+                    break;
+                case VNFC_NAME:
+                    validatedStatus = validateMustHaveParamValue(actionIdentifiers.getVnfcName(),
+                            ACTID_KEYS.VNFC_NAME.getKeyName());
+                    break;
+            }
+            if (validatedStatus == null) {
+                validatedFinalStatus = validateExcludedActIds(actionIdentifiers, EnumSet.of(ACTID_KEYS.VNF_ID, key));
+                break;
+            }
+        }
+
+        return validatedFinalStatus;
+    }
+
     /**
      * Validate a value of the must have parameter
      * @param value   the value of the parameter