Merge master -> master_vca_intg

Signed-off-by: KIRAN KASHALKAR <kiran.kashalkar@riftio.com>
diff --git a/skyquake/framework/core/api_utils/sockets.js b/skyquake/framework/core/api_utils/sockets.js
index 6076594..5e0b25b 100644
--- a/skyquake/framework/core/api_utils/sockets.js
+++ b/skyquake/framework/core/api_utils/sockets.js
@@ -32,17 +32,9 @@
 var url = require('url');
 var sockjs = require('sockjs');
 var websocket_multiplex = require('websocket-multiplex');
+var utils = require('./utils.js');
 
 
-function getPortForProtocol (protocol) {
-  switch (protocol) {
-    case 'http':
-      return 8000;
-    case 'https':
-      return 8443;
-  }
-}
-
 var Subscriptions = function() {
   this.ID = 0;
   this.socketServers = {};
@@ -85,7 +77,7 @@
     var origin = '';
     if (req.query['api_server']) {
       var api_server_protocol = req.query['api_server'].match(protocolTest)[1];
-      var api_server_origin = req.query['api_server'] + ':' + getPortForProtocol(api_server_protocol);
+      var api_server_origin = req.query['api_server'] + ':' + utils.getPortForProtocol(api_server_protocol);
       origin = api_server_origin;
       protocol = api_server_protocol;
     } else {
diff --git a/skyquake/framework/core/api_utils/utils.js b/skyquake/framework/core/api_utils/utils.js
index 0d1990c..5b17279 100644
--- a/skyquake/framework/core/api_utils/utils.js
+++ b/skyquake/framework/core/api_utils/utils.js
@@ -217,6 +217,15 @@
 	});
 }
 
+var getPortForProtocol = function(protocol) {
+  switch (protocol) {
+    case 'http':
+      return 8000;
+    case 'https':
+      return 8443;
+  }
+}
+
 module.exports = {
 	/**
 	 * Ensure confd port is on api_server variable.
@@ -233,5 +242,7 @@
 
 	sendSuccessResponse: sendSuccessResponse,
 
-    passThroughConstructor: passThroughConstructor
+    passThroughConstructor: passThroughConstructor,
+
+    getPortForProtocol: getPortForProtocol
 };
diff --git a/skyquake/plugins/composer/api/composer.js b/skyquake/plugins/composer/api/composer.js
index 79c6650..23345f5 100644
--- a/skyquake/plugins/composer/api/composer.js
+++ b/skyquake/plugins/composer/api/composer.js
@@ -272,36 +272,36 @@
         });
     });
 };
-// Composer.update = function(req) {
-//     var api_server = req.query['api_server'];
-//     var catalogType = req.params.catalogType;
-//     var id = req.params.id;
-//     var data = req.body;
-//     console.log('Updating', catalogType, 'id', id, 'on', api_server);
-//     var jsonData = {};
-//     jsonData[catalogType] = {};
-//     jsonData[catalogType] = data;
-//     return new Promise(function(resolve, reject) {
-//         var requestHeaders = {};
-//         _.extend(requestHeaders, constants.HTTP_HEADERS.accept.data, constants.HTTP_HEADERS.content_type.data, {
-//             'Authorization': req.get('Authorization')
-//         });
-//         request({
-//             uri: utils.confdPort(api_server) + APIVersion + '/api/config/' + catalogType + '-catalog' + '/' + catalogType + '/' + id,
-//             method: 'PUT',
-//             headers: requestHeaders,
-//             forever: constants.FOREVER_ON,
-//             rejectUnauthorized: false,
-//             json: jsonData
-//         }, function(error, response, body) {
-//             if (utils.validateResponse('Composer.update', error, response, body, resolve, reject)) {
-//                 resolve({
-//                     statusCode: response.statusCode
-//                 });
-//             }
-//         });
-//     });
-//
+Composer.updateSave = function(req) {
+    var api_server = req.query['api_server'];
+    var catalogType = req.params.catalogType;
+    var id = req.params.id;
+    var data = req.body;
+    console.log('Updating', catalogType, 'id', id, 'on', api_server);
+    var jsonData = {};
+    jsonData[catalogType] = {};
+    jsonData[catalogType] = data;
+    return new Promise(function(resolve, reject) {
+        var requestHeaders = {};
+        _.extend(requestHeaders, constants.HTTP_HEADERS.accept.data, constants.HTTP_HEADERS.content_type.data, {
+            'Authorization': req.get('Authorization')
+        });
+        request({
+            uri: utils.confdPort(api_server) + APIVersion + '/api/config/' + catalogType + '-catalog' + '/' + catalogType + '/' + id,
+            method: 'PUT',
+            headers: requestHeaders,
+            forever: constants.FOREVER_ON,
+            rejectUnauthorized: false,
+            json: jsonData
+        }, function(error, response, body) {
+            if (utils.validateResponse('Composer.update', error, response, body, resolve, reject)) {
+                resolve({
+                    statusCode: response.statusCode
+                });
+            }
+        });
+    });
+}
 
 Composer.update = function(req) {
     console.log(' Updating file', req.file.originalname, 'as', req.file.filename);
@@ -312,7 +312,7 @@
     var download_host = req.query['dev_download_server'];
 
     if (!download_host) {
-        download_host = req.protocol + '://' + req.headers.host;
+        download_host = api_server + ':' + utils.getPortForProtocol(req.protocol);
     }
     var input = {
         'external-url': download_host + '/composer/update/' + req.file.filename,
@@ -368,7 +368,7 @@
     var download_host = req.query['dev_download_server'];
 
     if (!download_host) {
-        download_host = req.protocol + '://' + req.headers.host;
+        download_host = api_server + ':' + utils.getPortForProtocol(req.protocol);
     }
 
     return new Promise(function(resolve, reject) {
@@ -425,7 +425,7 @@
     var package_type = req.query['package_type'].toUpperCase();
     var package_path = req.query['package_path'];
     if (!download_host) {
-        download_host = req.protocol + '://' + req.headers.host;
+        download_host = api_server + ':' + utils.getPortForProtocol(req.protocol);
     }
 
     return new Promise(function(resolve, reject) {
@@ -612,6 +612,9 @@
                                 data: data.body
                             });
                         }
+                    }).catch(function(err) {
+                        console.log('Failed to retrieve FileManager.list')
+                        resolve(err);
                     })
                 }
             })
diff --git a/skyquake/plugins/composer/routes.js b/skyquake/plugins/composer/routes.js
index 2c78cc9..3782209 100644
--- a/skyquake/plugins/composer/routes.js
+++ b/skyquake/plugins/composer/routes.js
@@ -96,7 +96,7 @@
     });
 });
 router.put('/api/catalog/:catalogType/:id', cors(), function(req, res) {
-    Composer.update(req).then(function(data) {
+    Composer.updateSave(req).then(function(data) {
         res.send(data);
     }, function(error) {
         res.status(error.statusCode);
diff --git a/skyquake/plugins/composer/src/src/components/CanvasPanel.js b/skyquake/plugins/composer/src/src/components/CanvasPanel.js
index dda1372..df4af5b 100644
--- a/skyquake/plugins/composer/src/src/components/CanvasPanel.js
+++ b/skyquake/plugins/composer/src/src/components/CanvasPanel.js
@@ -81,9 +81,13 @@
 						<button className={isDescriptorView ? '-selected' : ''} onClick={ComposerAppActions.showDescriptor}>
 							Descriptor
 						</button>
-						<button className={!isDescriptorView ? '-selected' : ''}  onClick={ComposerAppActions.showAssets}>
-							Assets
-						</button>
+						{
+							this.props.files ?
+								<button className={!isDescriptorView ? '-selected' : ''}  onClick={ComposerAppActions.showAssets}>
+									Assets
+								</button>
+							: null
+						}
 					</div>
 				</div>
        		)
diff --git a/skyquake/plugins/composer/src/src/libraries/model/DescriptorModelFields.js b/skyquake/plugins/composer/src/src/libraries/model/DescriptorModelFields.js
index bdbf403..d8d9e58 100644
--- a/skyquake/plugins/composer/src/src/libraries/model/DescriptorModelFields.js
+++ b/skyquake/plugins/composer/src/src/libraries/model/DescriptorModelFields.js
@@ -27,7 +27,7 @@
 	nsd: common.concat(['constituent-vnfd', 'vnffgd', 'vld']),
 	vld: common.concat([]),
 	vnfd: common.concat(['vdu', 'internal-vld']),
-	'vnfd.vdu': common.concat(['image', 'external-interface', 'vm-flavor', 'cloud-init', 'filename']),
+	'vnfd.vdu': common.concat(['image', 'image-checksum', 'external-interface', 'vm-flavor', 'cloud-init', 'filename']),
     'nsd.config-parameter-map': common.concat([]),
 	// white-list valid fields to send in the meta field
 	meta: ['containerPositionMap']
diff --git a/skyquake/plugins/composer/src/src/stores/ComposerAppStore.js b/skyquake/plugins/composer/src/src/stores/ComposerAppStore.js
index 30352a5..b30193a 100644
--- a/skyquake/plugins/composer/src/src/stores/ComposerAppStore.js
+++ b/skyquake/plugins/composer/src/src/stores/ComposerAppStore.js
@@ -122,7 +122,7 @@
 		this.fullScreenMode = false;
 		this.panelTabShown = 'descriptor';
 		//File manager values
-		this.files = [];
+		this.files = false;
 		this.filesState = {};
 		this.downloadJobs = {};
 		//End File  manager values
@@ -465,18 +465,27 @@
 		let self = this;
 		let filesState = null;
         if (self.fileMonitoringSocketID) {
-			filesState = addInputState( _.cloneDeep(this.filesState),data);
-			// filesState = _.merge(self.filesState, addInputState({},data));
-			let normalizedData = normalizeTree(data);
-			this.setState({
-				files: {
-					data: _.mergeWith(normalizedData.data, self.files.data, function(obj, src) {
-						return _.uniqBy(obj? obj.concat(src) : src, 'name');
-					}),
-					id: self.files.id || normalizedData.id
-				},
-				filesState: filesState
-			});
+        	let newState = {};
+        	if(data.hasOwnProperty('contents')) {
+        		filesState = addInputState( _.cloneDeep(this.filesState),data);
+				// filesState = _.merge(self.filesState, addInputState({},data));
+				let normalizedData = normalizeTree(data);
+				newState = {
+					files: {
+						data: _.mergeWith(normalizedData.data, self.files.data, function(obj, src) {
+							return _.uniqBy(obj? obj.concat(src) : src, 'name');
+						}),
+						id: self.files.id || normalizedData.id
+					},
+					filesState: filesState
+				}
+        	} else {
+        		newState = {
+        			files: false
+        		}
+        	}
+
+			this.setState(newState);
         }
 		function normalizeTree(data) {
 			let f = {
@@ -548,7 +557,7 @@
 		let self = this;
 		let ws = window.multiplexer.channel(id);
 		let downloadJobs = _.cloneDeep(self.downloadJobs);
-		let newFiles = {};
+		let newFiles = false;
 		ws.onmessage = (socket) => {
             if (self.files && self.files.length > 0) {
                 let jobs = [];
@@ -624,7 +633,6 @@
 	openFileManagerSockets(i) {
 		let self = this;
 		let item = i || self.item;
-		this.files = {data:[]};
         // this.closeFileManagerSockets();
 		this.getInstance().openFileMonitoringSocket(item.id, item.uiState.type).then(function() {
         // 	// self.getInstance().openDownloadMonitoringSocket(item.id);
diff --git a/skyquake/plugins/launchpad/src/instantiate/instantiateParameters.jsx b/skyquake/plugins/launchpad/src/instantiate/instantiateParameters.jsx
index 0e5fa1f..5681851 100644
--- a/skyquake/plugins/launchpad/src/instantiate/instantiateParameters.jsx
+++ b/skyquake/plugins/launchpad/src/instantiate/instantiateParameters.jsx
@@ -44,52 +44,53 @@
             <PanelWrapper>
             <InstantiateDescriptorPanel descriptor={selectedNSD} />
             <Panel title="Input Parameters">
-        <InstantiateInputParams
+                <InstantiateInputParams
 
-            nsFn={this.props.nsFn()}
-            vnfFn={this.props.vnfFn()}
-            vldFn={this.props.vldFn()}
-            ipProfileFn={this.props.ipProfileFn()}
-            dnsFn={this.props.dnsFn()}
-            usersFn={this.props.usersFn()}
-            sshFn={this.props.sshFn()}
-            updateName={this.props.nameUpdated}
-            updateInputParam={this.props.updateInputParam}
+                    nsFn={this.props.nsFn()}
+                    vnfFn={this.props.vnfFn()}
+                    vldFn={this.props.vldFn()}
+                    ipProfileFn={this.props.ipProfileFn()}
+                    dnsFn={this.props.dnsFn()}
+                    usersFn={this.props.usersFn()}
+                    sshFn={this.props.sshFn()}
+                    updateName={this.props.nameUpdated}
+                    updateInputParam={this.props.updateInputParam}
 
-            nsd={selectedNSD}
-            selectedNSDid={this.props.selectedNSDid}
-            name={this.props.name}
+                    nsd={selectedNSD}
+                    selectedNSDid={this.props.selectedNSDid}
+                    name={this.props.name}
 
-            cloudAccounts={this.props.cloudAccounts}
-            selectedCloudAccount={this.props.selectedCloudAccount}
-            vnfdCloudAccounts={this.props.vnfdCloudAccounts}
-            ro={this.props.ro}
-            dataCenters={this.props.dataCenters}
-            configAgentAccounts={this.props.configAgentAccounts}
-            inputParameters={this.props['input-parameters']}
+                    cloudAccounts={this.props.cloudAccounts}
+                    selectedCloudAccount={this.props.selectedCloudAccount}
+                    vnfdCloudAccounts={this.props.vnfdCloudAccounts}
+                    ro={this.props.ro}
+                    dataCenters={this.props.dataCenters}
+                    configAgentAccounts={this.props.configAgentAccounts}
+                    inputParameters={this.props['input-parameters']}
 
-            displayPlacementGroups={this.props.displayPlacementGroups}
+                    displayPlacementGroups={this.props.displayPlacementGroups}
 
 
-            nsPlacementGroups={this.props['ns-placement-groups']}
-            vnfPlacementGroups={this.props['vnf-placement-groups']}
+                    nsPlacementGroups={this.props['ns-placement-groups']}
+                    vnfPlacementGroups={this.props['vnf-placement-groups']}
 
-            vlds={this.props.vld}
+                    vlds={this.props.vld}
 
-            ipProfileList={this.props.ipProfiles}
+                    ipProfileList={this.props.ipProfiles}
 
-            sshKeysList={this.props.sshKeysList}
-            sshKeysRef={this.props.sshKeysRef}
+                    sshKeysList={this.props.sshKeysList}
+                    sshKeysRef={this.props.sshKeysRef}
 
-            dnsServers={this.props.dnsServers}
+                    dnsServers={this.props.dnsServers}
 
-            usersList = {this.props.usersList}
-            selectedID={this.props.selectedNSDid}
-            selectedNSD={selectedNSD}
+                    usersList = {this.props.usersList}
+                    selectedID={this.props.selectedNSDid}
+                    selectedNSD={selectedNSD}
 
-            isOpenMano={this.props.isOpenMano}
+                    isOpenMano={this.props.isOpenMano}
 
-        /></Panel>
+                />
+            </Panel>
         </PanelWrapper>
     )
   }
diff --git a/skyquake/plugins/launchpad/src/instantiate/instantiateStore.js b/skyquake/plugins/launchpad/src/instantiate/instantiateStore.js
index 2e6e242..e779beb 100644
--- a/skyquake/plugins/launchpad/src/instantiate/instantiateStore.js
+++ b/skyquake/plugins/launchpad/src/instantiate/instantiateStore.js
@@ -484,6 +484,11 @@
                     let value = e.target.nodeName == "SELECT" ? JSON.parse(e.target.value) : e.target.value;
                     self.ipProfiles[i]['ip-profile-params'][key] = value;
 
+                    if (value == '') {
+                        // Don't send this key
+                        delete self.ipProfiles[i]['ip-profile-params'][key];
+                    }
+
                     self.setState({ipProfiles:self.ipProfiles});
                 }
             },
diff --git a/skyquake/plugins/launchpad/src/recordViewer/recordCard.jsx b/skyquake/plugins/launchpad/src/recordViewer/recordCard.jsx
index 4491776..88ff709 100644
--- a/skyquake/plugins/launchpad/src/recordViewer/recordCard.jsx
+++ b/skyquake/plugins/launchpad/src/recordViewer/recordCard.jsx
@@ -106,7 +106,7 @@
                         //That match the currently selected job id
                         if(v.id == cardData.id) {
                           return v.primitive.map(function(p, i) {
-                            return <JobListCard type="vnfr" job-id={job['job-id']} cardData={cardData} key={ob['job-id'] + '-' + i} {...p} />
+                            return <JobListCard type="vnfr" job-id={job['job-id']} cardData={cardData} key={job['job-id'] + '-' + i} {...p} />
                           })
                         }
                       })
@@ -208,7 +208,7 @@
                         //That match the currently selected job id
                         if(v.id == cardData.id) {
                           return v.primitive.map(function(p, i) {
-                            return <JobListCard type="vnfr" job-id={job['job-id']} cardData={cardData} key={ob['job-id'] + '-' + 'vnfr' + '-' + h} {...p} />
+                            return <JobListCard type="vnfr" job-id={job['job-id']} cardData={cardData} key={job['job-id'] + '-' + 'vnfr' + '-' + h} {...p} />
                           })
                         }
                       })