diff options
author | 2020-01-14 13:31:20 -0500 | |
---|---|---|
committer | 2020-08-19 17:51:07 -0400 | |
commit | 3d364e4ffa2bfdbffa75679ad67fbaa93ce0b8bf (patch) | |
tree | 6dfefbd3a80f38b567f06f37621cda1f524572c2 /lib | |
parent | d6a5b946f05f43a9942d3d564d66a0a3396933a5 (diff) |
DH install/uninstall improvements
Install workflow changes:
-Use inventory blueprint (BP) typeId when uploading BP to Cloudify/CFY
-Set global visibility when uploading BP to CFY for multi-tenant access
-Re-use BP if it exists in CFY rather than alawys uploading a new BP
-Do not add a new service in inventory anymore
Un-Install workflow changes:
-Retreive associated BP against the deployment
-Check if any other deployments still exist against the BP
-If no associated deployments, get the associated tenant for the BP
-Only delete BP if there are no more associated BPs
-Do not remove associated service from inventory (it won't exist)
Coverage summary
Statements : 78.01% ( 997/1278 )
Branches : 56.45% ( 302/535 )
Functions : 74.89% ( 164/219 )
Lines : 78.54% ( 988/1258 )
Issue-ID: DCAEGEN2-2022
Signed-off-by: Shadi Haidar <sh1986@att.com>
Change-Id: I9cb197edc3a0276c5ca95f9c936fc7300d849f56
Signed-off-by: Shadi Haidar <sh1986@att.com>
Signed-off-by: Shadi Haidar (sh1986) <sh1986@att.com>
Signed-off-by: Shadi Haidar <sh1986@att.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/cloudify.js | 93 | ||||
-rw-r--r-- | lib/dcae-deployments.js | 48 | ||||
-rw-r--r-- | lib/deploy.js | 54 |
3 files changed, 146 insertions, 49 deletions
diff --git a/lib/cloudify.js b/lib/cloudify.js index 77e6d72..2c7af6e 100644 --- a/lib/cloudify.js +++ b/lib/cloudify.js @@ -92,6 +92,17 @@ const getDeploymentCreationStatus = function(req, deployment_id) { return doRequest(req, reqOptions, null, CLOUDIFY); }; +// Get blueprint_id for a particular deployment +exports.getBlueprintIdFromDeployment = function(req, deployment_id) { + const reqOptions = { + method : "GET", + uri : cfyAPI + "/deployments/" + deployment_id + "?_include=blueprint_id" + }; + addAuthToOptions(reqOptions, req); + + return doRequest(req, reqOptions, null, CLOUDIFY); +}; + // Poll for the result of a workflow execution until it's done // Return a promise for the final result of a workflow execution exports.waitForWorkflowExecution = function(mainReq, execution_id) { @@ -243,7 +254,7 @@ exports.uploadBlueprint = function(req, bpid, blueprint) { // Set up the HTTP PUT request const reqOptions = { method : "PUT", - uri : cfyAPI + "/blueprints/" + bpid, + uri : cfyAPI + "/blueprints/" + bpid + "?visibility=global", headers : { "Content-Type" : "application/octet-stream", "Accept" : "*/*" @@ -255,6 +266,86 @@ exports.uploadBlueprint = function(req, bpid, blueprint) { return doRequest(req, reqOptions, zip_buffer, CLOUDIFY); }; +// Checks if a blueprint exists in cloudify +exports.checkBlueprintExits = function(req, bpid) { + + // Set up the HTTP GET request + var reqOptions = { + method : "GET", + uri : cfyAPI + "/blueprints?id=" + bpid, + headers : { + "Content-Type" : "application/json", + "Accept" : "*/*" + } + }; + addAuthToOptions(reqOptions, req); + + return doRequest(req, reqOptions, null, CLOUDIFY) + + .then (function(result) { + if (result.json.metadata.pagination.total > 0 ) { + return true; + } + else { + return false; + } + }) + .catch(function(error) { + logger.debug(req.dcaeReqId, "Error getting BP from Cloudify for deployment id: " + req.params['deploymentId'] + " and blueprint id: " + bpid ); + throw(error); + }); +}; + +// Get the tenant_name associated with a blueprint +exports.getBlueprintTenantName = function(req, bpid) { + + // Set up the HTTP GET request + var reqOptions = { + method : "GET", + uri : cfyAPI + "/blueprints?id=" + bpid + "&_include=tenant_name", + headers : { + "Content-Type" : "application/json", + "Accept" : "*/*" + } + }; + addAuthToOptions(reqOptions, req); + + return doRequest(req, reqOptions, null, CLOUDIFY); +}; + +// Checks if a blueprint should be deleted from cloudify due to no associated deployments +exports.shouldBlueprintGetDeleted = function(req, bpid) { + + // Set up the HTTP GET request + var reqOptions = { + method : "GET", + uri : cfyAPI + "/deployments?blueprint_id=" + bpid + "&_all_tenants=true&_include=id", + headers : { + "Content-Type" : "application/json", + "Accept" : "*/*" + } + }; + const tenant = req.query.cfy_tenant_name; + req.query.cfy_tenant_name = DEFAULT_TENANT; + addAuthToOptions(reqOptions, req); + req.query.cfy_tenant_name = tenant; + + return doRequest(req, reqOptions, null, CLOUDIFY) + + .then (function(result) { + if (result.json.metadata.pagination.total > 0 ) { + return false; + } + else { + return true; + } + }) + .catch(function(error) { + logger.debug(req.dcaeReqId, "Error getting deployments info from Cloudify for deployment id: " + req.params['deploymentId'] + " and blueprint id: " + bpid ); + throw(error); + }); +}; + // Creates a deployment from a blueprint exports.createDeployment = function(req, dpid, bpid, inputs) { diff --git a/lib/dcae-deployments.js b/lib/dcae-deployments.js index 193f6b9..708a949 100644 --- a/lib/dcae-deployments.js +++ b/lib/dcae-deployments.js @@ -1,5 +1,5 @@ /* -Copyright(c) 2017-2018 AT&T Intellectual Property. All rights reserved. +Copyright(c) 2017-2020 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. @@ -28,6 +28,7 @@ const deploy = require('./deploy'); const middleware = require('./middleware'); const inv = require('./inventory'); const log = require('./logging').getLogger(); +const DEFAULT_TENANT = "default_tenant"; /* Pick up config exported by main */ const config = process.mainModule.exports.config; @@ -63,7 +64,7 @@ const createLinks = function(req, deploymentId, executionId) { var baseURL = req.protocol + '://' + req.get('Host') + req.app.mountpath + '/' + deploymentId; return { self: baseURL, - status: baseURL + '/operation/' + executionId + status: baseURL + '/operation/' + executionId + '?cfy_tenant_name=' + req.query.cfy_tenant_name || DEFAULT_TENANT }; }; @@ -105,31 +106,20 @@ app.put('/:deploymentId', function(req, res, next) { throw e; } - /* Make sure the deploymentId doesn't already exist */ - inventory.verifyUniqueDeploymentId(req, req.params['deploymentId']) - - /* Get the blueprint for this service type */ - .then(function(res) { - return getBlueprint(req, req.body['serviceTypeId']); - }) - - /* Add this new service instance to inventory - * Easier to remove from inventory if deployment fails than vice versa - * Also lets client check for deployed/deploying instances if client wants to limit number of instances - */ - .then(function (blueprintInfo) { - req.dcaeBlueprint = blueprintInfo.blueprint; - return inventory.addService(req, req.params['deploymentId'], blueprintInfo.typeId, "dummyVnfId", "dummyVnfType", "dummyLocation"); - }) + return getBlueprint(req, req.body['serviceTypeId']) /* Upload blueprint, create deployment and start install workflow (but don't wait for completion */ - .then (function() { + .then (function(blueprintInfo) { + req.dcaeBlueprint = blueprintInfo.blueprint; + req.bpTypeId = blueprintInfo.typeId; req.dcaeAddedToInventory = true; - return deploy.launchBlueprint(req, req.params['deploymentId'], req.dcaeBlueprint, req.body['inputs']); + return deploy.launchBlueprint(req, req.params['deploymentId'], req.dcaeBlueprint, + "TID-" + req.bpTypeId, req.body['inputs']); }) /* Send the HTTP response indicating workflow has started */ .then(function(result) { + log.info(req.dcaeReqId, "Result from deployment creation/execution: " + JSON.stringify(result)); res.status(202).json(createResponse(req, result)); log.audit(req, 202, "Execution ID: " + result.executionId); return result; @@ -150,15 +140,6 @@ app.put('/:deploymentId', function(req, res, next) { /* If we haven't already sent a response, let the error handler send response and log the error */ if (!res.headersSent) { - - /* If we made an inventory entry, remove it */ - if (req.dcaeAddedToInventory) { - inventory.deleteService(req, req.params['deploymentId']) - .catch(function(error) { - log.error(error, req); - }); - } - next(error); } else { @@ -179,14 +160,6 @@ app.delete('/:deploymentId', function(req, res, next) { /* Launch the uninstall workflow */ deploy.launchUninstall(req, req.params['deploymentId']) - /* Delete the service from inventory */ - .then(function(result) { - return inventory.deleteService(req, req.params['deploymentId']) - .then (function() { - return result; - }); - }) - /* Send the HTTP response indicating workflow has started */ .then(function(result) { res.status(202).send(createResponse(req, result)); @@ -198,7 +171,6 @@ app.delete('/:deploymentId', function(req, res, next) { .then(function(result) { return deploy.finishUninstall(req, result.deploymentId, result.executionId); }) - /* Log completion in audit log */ .then(function(result) { log.audit(req, 200, "Undeployed id: " + req.params['deploymentId']); diff --git a/lib/deploy.js b/lib/deploy.js index cb78f6f..d4ce1d4 100644 --- a/lib/deploy.js +++ b/lib/deploy.js @@ -1,5 +1,5 @@ /* -Copyright(c) 2017-2018 AT&T Intellectual Property. All rights reserved. +Copyright(c) 2017-2020 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. @@ -130,19 +130,32 @@ var delay = function(dtime) { // Go through the Cloudify API call sequence to upload blueprint, create deployment, and launch install workflow // (but don't wait for the workflow to finish) -exports.launchBlueprint = function(req, id, blueprint, inputs) { +exports.launchBlueprint = function(req, id, blueprint, bpid, inputs) { + const log_blueprint_id = "blueprintId(" + bpid + "): "; const log_deployment_id = "deploymentId(" + id + "): "; - var step_log = log_deployment_id + "uploading blueprint"; + var step_log = log_blueprint_id + "uploading blueprint"; logger.info(req.dcaeReqId, step_log); - return cfy.uploadBlueprint(req, id, blueprint) + + return cfy.checkBlueprintExits(req, bpid) + + .then (function (result) { + logger.info(req.dcaeReqId, " checkBlueprintExits result " + result); + // Upload blueprint + if ( result === false ) { + logger.info(req.dcaeReqId, " blueprint with id: " + log_blueprint_id + " does not exist. Uploading"); + return cfy.uploadBlueprint(req, bpid, blueprint) + } + else { + logger.info(req.dcaeReqId, " blueprint with id: " + log_blueprint_id + " already exits. No need to upload"); + } + }) .then (function(result) { step_log = log_deployment_id + "creating deployment"; logger.info(req.dcaeReqId, step_log); // Create deployment - return cfy.createDeployment(req, id, id, inputs); + return cfy.createDeployment(req, id, bpid, inputs); }) - // create the deployment and keep checking, for up to 5 minutes, until creation is complete .then(function(result) { step_log = log_deployment_id + "waiting for deployment creation"; @@ -210,22 +223,43 @@ exports.launchUninstall = function(req, deploymentId) { exports.finishUninstall = function(req, deploymentId, executionId) { logger.info(req.dcaeReqId, "finishUninstall: " + deploymentId + " -- executionId: " + executionId); + var bid = ""; return cfy.waitForWorkflowExecution(req, executionId) .then (function(result){ logger.info(req.dcaeReqId, "deploymentId: " + deploymentId + " uninstall workflow successfully executed"); + logger.info(req.dcaeReqId, "deploymentId: " + deploymentId + " getting associated blueprint_id"); + return cfy.getBlueprintIdFromDeployment(req, deploymentId); + }) + .then (function(result){ + bid = result.json.blueprint_id; + logger.info(req.dcaeReqId, "deploymentId: " + deploymentId + " associated blueprint_id: " + bid); // Delete the deployment return delay(DELAY_DELETE_DEPLOYMENT).then(function() { return cfy.deleteDeployment(req, deploymentId); - }); + }); }) .then (function(result){ logger.info(req.dcaeReqId, "deploymentId: " + deploymentId + " deployment deleted"); - // Delete the blueprint - return delay(DELAY_DELETE_BLUEPRINT).then(function() { - return cfy.deleteBlueprint(req, deploymentId); + return delay(DELAY_DELETE_DEPLOYMENT).then(function() { + return cfy.shouldBlueprintGetDeleted(req, bid); }); }) + .then (function (result) { + logger.info(req.dcaeReqId, "deploymentId: " + deploymentId + " shouldBlueprintGetDeleted: " + result); + if ( result === true ) { + return cfy.getBlueprintTenantName(req, bid) + .then (function(result){ + const tenant = result.json.items[0].tenant_name; + logger.info(req.dcaeReqId, "deploymentId: " + deploymentId + " deleting bluerpint with id: " + + bid + " and tenant_name: " + tenant); + // Delete the blueprint + req.query.cfy_tenant_name = tenant; + return cfy.deleteBlueprint(req, bid); + }); + } + }) .then (function(result){ + logger.info(req.dcaeReqId, "deploymentId: " + deploymentId + " done with uninstall"); return result; }) .catch (function(err){ |