summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cds-ui/client/src/app/common/core/services/api.service.ts32
-rw-r--r--cds-ui/client/src/app/feature-modules/blueprint/modify-template/editor/editor.component.ts216
-rw-r--r--cds-ui/client/src/app/feature-modules/blueprint/modify-template/editor/editor.service.ts58
-rw-r--r--cds-ui/client/src/app/feature-modules/blueprint/modify-template/modify-template.component.html2
-rw-r--r--cds-ui/client/src/app/feature-modules/blueprint/modify-template/modify-template.module.ts3
-rw-r--r--cds-ui/server/src/controllers/blueprint-rest.controller.ts152
-rw-r--r--ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfDeviceCommunicator.kt2
-rw-r--r--ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfSessionImpl.kt76
-rw-r--r--ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfSessionImplTest.kt11
9 files changed, 323 insertions, 229 deletions
diff --git a/cds-ui/client/src/app/common/core/services/api.service.ts b/cds-ui/client/src/app/common/core/services/api.service.ts
index 20d8a9bce..463ef3827 100644
--- a/cds-ui/client/src/app/common/core/services/api.service.ts
+++ b/cds-ui/client/src/app/common/core/services/api.service.ts
@@ -31,38 +31,14 @@ export class ApiService {
constructor(private _http: HttpClient) {
}
- enrich(uri: string, body: FormData): Observable<any> {
-
- var HTTPOptions = {
- headers: new HttpHeaders({ 'Accept': 'application/zip', }),
- observe: "response" as 'body',// to display the full response & as 'body' for type cast
- 'responseType': 'blob' as 'json'
- }
- return this._http.post(LoopbackConfig.url + uri, body, HTTPOptions);
-
+ get(url: string, params?: any): Observable<any> {
+ return this._http.get(url,params);
}
- downloadCBA(uri: string, params?: any): Observable<Blob> {
- // return this._http.get<Blob>(LoopbackConfig.url+uri);
- var HTTPOptions = {
- headers: new HttpHeaders({ 'Accept': 'application/zip; charset=UTF-8', }),
- observe: "response" as 'body',// to display the full response & as 'body' for type cast
- 'responseType': 'blob' as 'json'
- }
- return this._http.get<Blob>(LoopbackConfig.url + uri, HTTPOptions);
- }
+ post(url: string, body: any | null, options?:any): Observable<any> {
- post(uri: string, body: FormData): Observable<any> {
- // to do
- const httpOptions = {
- headers: new HttpHeaders({
- 'Authorization': LoopbackConfig.authtoken,
-
- })
- };
- return this._http.post(LoopbackConfig.url + uri, body, httpOptions);
+ return this._http.post(url, body,options);
}
-
put() {
// to do
}
diff --git a/cds-ui/client/src/app/feature-modules/blueprint/modify-template/editor/editor.component.ts b/cds-ui/client/src/app/feature-modules/blueprint/modify-template/editor/editor.component.ts
index 7cbf5b0a5..73cc72cfd 100644
--- a/cds-ui/client/src/app/feature-modules/blueprint/modify-template/editor/editor.component.ts
+++ b/cds-ui/client/src/app/feature-modules/blueprint/modify-template/editor/editor.component.ts
@@ -36,7 +36,8 @@ import { Observable } from 'rxjs';
import { IBlueprintState } from 'src/app/common/core/store/models/blueprintState.model';
import { LoadBlueprintSuccess, SetBlueprintState } from '../../../../common/core/store/actions/blueprint.action'
import { ApiService } from 'src/app/common/core/services/api.service';
-
+import { IMetaData } from 'src/app/common/core/store/models/metadata.model';
+import { EditorService } from './editor.service';
interface Node {
name: string;
@@ -92,9 +93,9 @@ export class EditorComponent implements OnInit {
currentFilePath: string = '';
selectedFileObj = { name: '', type: '' };
viewTemplateMode: boolean = false;
- paramData : any = {
+ paramData: any = {
'capability-data': [],
- 'resourceAccumulatorResolvedData' : []
+ 'resourceAccumulatorResolvedData': []
};
validfile: boolean = false;
@ViewChild('fileInput') fileInput;
@@ -103,6 +104,7 @@ export class EditorComponent implements OnInit {
private tree;
private fileObject: any;
private tocsaMetadaData: any;
+ metadata: IMetaData;
private transformer = (node: Node, level: number) => {
return {
@@ -119,8 +121,10 @@ export class EditorComponent implements OnInit {
this.transformer, node => node.level, node => node.expandable, node => node.children);
dataSource = new MatTreeFlatDataSource(this.treeControl, this.treeFlattener);
+ artifactName: any;
+ artifactVersion: any;
- constructor(private store: Store<IAppState>, private apiservice: ApiService) {
+ constructor(private store: Store<IAppState>, private apiservice: EditorService) {
this.dataSource.data = TREE_DATA;
this.bpState = this.store.select('blueprint');
// this.dataSource.data = TREE_DATA;
@@ -161,8 +165,15 @@ export class EditorComponent implements OnInit {
blueprint.push(this.blueprintdata[key]);
}
}
- // this.text = JSON.stringify(this.blueprintdata, null, '\t');
- // this.editor.getEditor().getSession().setMode("ace/mode/json");
+ this.metadata=blueprintState.blueprint.metadata;
+ let metadatavalues = [];
+ for (let key in this.metadata) {
+ if (this.metadata.hasOwnProperty(key)) {
+ metadatavalues.push(this.metadata[key]);
+ }
+ }
+ this.artifactName = metadatavalues[3];
+ this.artifactVersion = metadatavalues[4];
this.editor.getEditor().getSession().setTabSize(2);
this.editor.getEditor().getSession().setUseWrapMode(true);
this.setEditorMode();
@@ -197,7 +208,7 @@ export class EditorComponent implements OnInit {
}
selectFileToView(file) {
- if(file.name.includes('.vtl')) { this.viewTemplateMode = true;} else { this.viewTemplateMode = false;}
+ if (file.name.includes('.vtl')) { this.viewTemplateMode = true; } else { this.viewTemplateMode = false; }
this.currentFilePath = '';
this.expandParents(file);
this.selectedFileObj.name = file.name;
@@ -224,70 +235,21 @@ export class EditorComponent implements OnInit {
this.apiservice.enrich("/enrich-blueprint/", formData)
.subscribe(
(response) => {
- console.log("Inside blob");
- var blob = new Blob([response.data], { type: 'application/zip' });
- const fileName = 'CBA.zip';
- saveAs(blob, fileName);
this.zipFile.files = {};
- this.zipFile.loadAsync(blob)
+ this.zipFile.loadAsync(response)
.then((zip) => {
if (zip) {
this.buildFileViewData(zip);
+ console.log("processed");
}
});
-
+ window.alert('Blueprint enriched successfully' );
});
-
});
-
- }
- async buildFileViewData(zip) {
- this.validfile = false;
- this.paths = [];
- for (var file in zip.files) {
- this.fileObject = {
- name: zip.files[file].name,
- data: ''
- };
- const value = <any>await zip.files[file].async('string');
- this.fileObject.data = value;
- this.paths.push(this.fileObject);
- }
-
- if(this.paths) {
- this.paths.forEach(path =>{
- if(path.name.includes("TOSCA.meta")) {
- this.validfile = true
- }
- });
- } else {
- alert('Please update proper file');
- }
-
- if(this.validfile) {
- this.fetchTOSACAMetadata();
- this.tree = this.arrangeTreeData(this.paths);
- } else {
- alert('Please update proper file with TOSCA metadata');
- }
}
+
- fetchTOSACAMetadata() {
- let toscaData = {};
- this.paths.forEach(file =>{
- if(file.name.includes('TOSCA.meta')) {
- let keys = file.data.split("\n");
- keys.forEach((key)=>{
- let propertyData = key.split(':');
- toscaData[propertyData[0]] = propertyData[1];
- });
- }
- });
- this.blueprintName = (((toscaData['Entry-Definitions']).split('/'))[1]).toString();;
- console.log(toscaData);
- }
-
saveToBackend() {
this.create();
this.zipFile.generateAsync({ type: "blob" })
@@ -295,7 +257,11 @@ export class EditorComponent implements OnInit {
const formData = new FormData();
formData.append("file", blob);
this.apiservice.post("/create-blueprint/", formData)
- .subscribe(data => console.log(data));
+ .subscribe(
+ data => {
+ // console.log(data);
+ window.alert('Success:' + JSON.stringify(data));
+ });
});
}
@@ -307,8 +273,11 @@ export class EditorComponent implements OnInit {
.then(blob => {
const formData = new FormData();
formData.append("file", blob);
- this.apiservice.post("/deploy-blueprint/", formData)
- .subscribe(data => console.log(data));
+ this.apiservice.deployPost("/deploy-blueprint/", formData)
+ .subscribe(data => {
+ // console.log(data);
+ window.alert('Saved Successfully:' + JSON.stringify(data));
+ });
});
}
@@ -320,7 +289,10 @@ export class EditorComponent implements OnInit {
const formData = new FormData();
formData.append("file", blob);
this.apiservice.post("/publish/", formData)
- .subscribe(data => console.log(data));
+ .subscribe(data => {
+ // console.log(data);
+ window.alert('Published:' + JSON.stringify(data));
+ });
});
@@ -333,17 +305,19 @@ export class EditorComponent implements OnInit {
}
download() {
- this.apiservice.downloadCBA("/download-blueprint/baseconfiguration/1.0.0")
- .subscribe(response => {
- console.log(response);
- var blob = new Blob([response], { type: 'application/zip' });
- const fileName = 'CBA';
- saveAs(blob, fileName);
- },
- error => {
- console.log(error);
- }
- );
+ console.log(this.artifactName);
+ status = this.apiservice.downloadCBA("/download-blueprint/" + this.artifactName + "/" + this.artifactVersion);
+ window.alert(status);
+ // .subscribe(response => {
+ // console.log(response);
+ // var blob = new Blob([response], { type: 'application/zip' });
+ // const fileName = 'CBA';
+ // saveAs(blob, fileName);
+ // },
+ // error => {
+ // console.log(error);
+ // }
+ // );
}
setEditorMode() {
switch (this.fileExtension) {
@@ -417,6 +391,52 @@ export class EditorComponent implements OnInit {
return indexForNewNode;
}
+ async buildFileViewData(zip) {
+ this.validfile = false;
+ this.paths = [];
+ for (var file in zip.files) {
+ this.fileObject = {
+ name: zip.files[file].name,
+ data: ''
+ };
+ const value = <any>await zip.files[file].async('string');
+ this.fileObject.data = value;
+ this.paths.push(this.fileObject);
+ }
+
+ if (this.paths) {
+ this.paths.forEach(path => {
+ if (path.name.includes("TOSCA.meta")) {
+ this.validfile = true
+ }
+ });
+ } else {
+ alert('Please update proper file');
+ }
+
+ if (this.validfile) {
+ this.fetchTOSACAMetadata();
+ this.tree = this.arrangeTreeData(this.paths);
+ } else {
+ alert('Please update proper file with TOSCA metadata');
+ }
+ }
+
+ fetchTOSACAMetadata() {
+ let toscaData = {};
+ this.paths.forEach(file => {
+ if (file.name.includes('TOSCA.meta')) {
+ let keys = file.data.split("\n");
+ keys.forEach((key) => {
+ let propertyData = key.split(':');
+ toscaData[propertyData[0]] = propertyData[1];
+ });
+ }
+ });
+ this.blueprintName = (((toscaData['Entry-Definitions']).split('/'))[1]).toString();;
+ console.log(toscaData);
+ }
+
arrangeTreeData(paths) {
const tree = [];
@@ -505,34 +525,34 @@ export class EditorComponent implements OnInit {
}
loadConfigParams() {
console.log(this.currentFilePath);
- console.log(this.selectedFile);
- console.log(this.selectedFileObj);
- console.log(this.selectedFolder);
- console.log(this.text);
-
- let parsedData = JSON.parse(this.text);
- this.paramData.resourceAccumulatorResolvedData = parsedData['resource-accumulator-resolved-data'];
- let i=0;
-
- this.paramData.resourceAccumulatorResolvedData.forEach(element => {
- element.id = i;
- let tempElement = element['param-value'];
- let indexLength = tempElement.length;
- tempElement = tempElement.slice(2,indexLength);
- let index = tempElement.indexOf('}');
- tempElement = this.removeItemByIndex(tempElement, index);
- element['param-value'] = tempElement;
- i++;
- });
+ console.log(this.selectedFile);
+ console.log(this.selectedFileObj);
+ console.log(this.selectedFolder);
+ console.log(this.text);
+
+ let parsedData = JSON.parse(this.text);
+ this.paramData.resourceAccumulatorResolvedData = parsedData['resource-accumulator-resolved-data'];
+ let i = 0;
+
+ this.paramData.resourceAccumulatorResolvedData.forEach(element => {
+ element.id = i;
+ let tempElement = element['param-value'];
+ let indexLength = tempElement.length;
+ tempElement = tempElement.slice(2, indexLength);
+ let index = tempElement.indexOf('}');
+ tempElement = this.removeItemByIndex(tempElement, index);
+ element['param-value'] = tempElement;
+ i++;
+ });
}
removeItemByIndex(paramValue, index) {
- if(index == 0) {
- return paramValue.slice(1)
- } else if(index > 0) {
+ if (index == 0) {
+ return paramValue.slice(1)
+ } else if (index > 0) {
let indexLength = paramValue.length;
- return paramValue.slice(0,index) + paramValue.slice(index+1, indexLength);
+ return paramValue.slice(0, index) + paramValue.slice(index + 1, indexLength);
} else {
return paramValue;
}
diff --git a/cds-ui/client/src/app/feature-modules/blueprint/modify-template/editor/editor.service.ts b/cds-ui/client/src/app/feature-modules/blueprint/modify-template/editor/editor.service.ts
new file mode 100644
index 000000000..98e43b6b1
--- /dev/null
+++ b/cds-ui/client/src/app/feature-modules/blueprint/modify-template/editor/editor.service.ts
@@ -0,0 +1,58 @@
+/*
+============LICENSE_START==========================================
+===================================================================
+Copyright (C) 2018 IBM Intellectual Property. All rights reserved.
+===================================================================
+
+Unless otherwise specified, all software contained herein is licensed
+under the Apache License, Version 2.0 (the License);
+you may not use this software 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============================================
+*/
+
+
+import { Injectable } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+import { Observable, observable } from 'rxjs';
+import { ApiService } from '../../../../common/core/services/api.service';
+import { LoopbackConfig } from '../../../../common/constants/app-constants';
+import { saveAs } from 'file-saver';
+
+@Injectable()
+export class EditorService {
+ // blueprintUrl = '../../constants/blueprint.json';
+
+ constructor(private _http: HttpClient, private api: ApiService) {
+ }
+
+ enrich(uri: string, body: FormData): Observable<any> {
+ return this.api.post(LoopbackConfig.url + uri, body, { responseType: 'blob' });
+ }
+ downloadCBA(uri: string): string {
+ this.api.get(LoopbackConfig.url + uri, { responseType: 'blob' })
+ .subscribe(response => {
+ let blob = new Blob([response], { 'type': "application/octet-stream" });
+ saveAs(blob, "CBA.zip");
+ });
+ return "Download Success";
+
+ }
+ post(uri: string, body: any | null, options?: any): Observable<any> {
+
+ return this.api.post(LoopbackConfig.url + uri, body, options);
+ }
+
+ deployPost(uri: string, body: any | null, options?: any): Observable<any> {
+
+ return this.api.post(LoopbackConfig.url + uri, body, { responseType: 'text' });
+ }
+} \ No newline at end of file
diff --git a/cds-ui/client/src/app/feature-modules/blueprint/modify-template/modify-template.component.html b/cds-ui/client/src/app/feature-modules/blueprint/modify-template/modify-template.component.html
index 1d9b5266e..b3eeeeda2 100644
--- a/cds-ui/client/src/app/feature-modules/blueprint/modify-template/modify-template.component.html
+++ b/cds-ui/client/src/app/feature-modules/blueprint/modify-template/modify-template.component.html
@@ -38,7 +38,7 @@ limitations under the License.
<button mat-menu-item (click)="saveToBlueprintProcessor()">Deploy</button>
<button mat-menu-item (click)="processBlueprint()">Test</button>
</mat-menu>
- <button [disabled]="!isEnriched" class="btn-active" (click)="publishToControllerBlueprint()">Publish</button>
+ <button class="btn-active" (click)="publishToControllerBlueprint()">Publish</button>
<button class="btn-active" (click)="saveToControllerBlueprint()">Save</button>
<button class="btn-active" (click)="getEnriched()">Enrich</button>
diff --git a/cds-ui/client/src/app/feature-modules/blueprint/modify-template/modify-template.module.ts b/cds-ui/client/src/app/feature-modules/blueprint/modify-template/modify-template.module.ts
index 7d22c569b..64ba4cdb1 100644
--- a/cds-ui/client/src/app/feature-modules/blueprint/modify-template/modify-template.module.ts
+++ b/cds-ui/client/src/app/feature-modules/blueprint/modify-template/modify-template.module.ts
@@ -31,6 +31,7 @@ import { EditorComponent } from './editor/editor.component';
import { AceEditorModule } from 'ng2-ace-editor';
import { ResourceMappingComponent } from './resource-mapping/resource-mapping.component';
import { ResourceMappingService } from './resource-mapping/resource-mapping.service';
+import { EditorService } from './editor/editor.service';
@NgModule({
declarations: [
@@ -52,6 +53,6 @@ import { ResourceMappingService } from './resource-mapping/resource-mapping.serv
AceEditorModule,
FormsModule
],
- providers: [ ResourceMappingService ]
+ providers: [ ResourceMappingService , EditorService ]
})
export class ModifyTemplateModule { }
diff --git a/cds-ui/server/src/controllers/blueprint-rest.controller.ts b/cds-ui/server/src/controllers/blueprint-rest.controller.ts
index c1f7f9640..38abad80c 100644
--- a/cds-ui/server/src/controllers/blueprint-rest.controller.ts
+++ b/cds-ui/server/src/controllers/blueprint-rest.controller.ts
@@ -51,12 +51,11 @@ import * as request_lib from 'request';
const REST_BLUEPRINT_CONTROLLER_BASE_URL = process.env.REST_BLUEPRINT_CONTROLLER_BASE_URL || "http://localhost:8080/api/v1";
const REST_BLUEPRINT_CONTROLLER_BASIC_AUTH_HEADER = process.env.REST_BLUEPRINT_CONTROLLER_BASIC_AUTH_HEADER || "Basic Y2NzZGthcHBzOmNjc2RrYXBwcw==";
-const REST_BLUEPRINT_PROCESSOR_BASE_URL= "http://localhost:8081/api/v1";
+const REST_BLUEPRINT_PROCESSOR_BASE_URL= process.env.REST_BLUEPRINT_PROCESSOR_BASE_URL ||"http://localhost:8081/api/v1";
+const MULTIPART_FORM_UPLOAD_DIR = process.env.MULTIPART_FORM_UPLOAD_DIR || "/tmp";
export class BlueprintRestController {
constructor(
- // @repository(BlueprintRepository)
- // public blueprintRepository : BlueprintRepository,
@inject('services.BlueprintService')
public bpservice: BlueprintService,
) {}
@@ -71,7 +70,6 @@ export class BlueprintRestController {
})
async getall() {
return await this.bpservice.getAllblueprints(REST_BLUEPRINT_CONTROLLER_BASIC_AUTH_HEADER);
-
}
@post('/create-blueprint')
@@ -89,12 +87,39 @@ export class BlueprintRestController {
})
request: Request,
@inject(RestBindings.Http.RESPONSE) response: Response,
- ): Promise<object> {
+ ): Promise<Response> {
return new Promise((resolve, reject) => {
this.getFileFromMultiPartForm(request).then(file=>{
- this.uploadFileToBlueprintController(file, "/blueprint-model/").then(resp=>{
- response.setHeader("X-ONAP-RequestID", resp.headers['x-onap-requestid']);
- resolve(JSON.parse(resp.body));
+ this.uploadFileToBlueprintController(file, REST_BLUEPRINT_CONTROLLER_BASE_URL+"/blueprint-model/", response).then(resp=>{
+ resolve(resp);
+ }, err=>{
+ reject(err);
+ });
+ }, err=>{
+ reject(err);
+ });
+ });
+ }
+ @post('/publish')
+ async publish(
+ @requestBody({
+ description: 'multipart/form-data value.',
+ required: true,
+ content: {
+ 'multipart/form-data': {
+ // Skip body parsing
+ 'x-parser': 'stream',
+ schema: {type: 'object'},
+ },
+ },
+ })
+ request: Request,
+ @inject(RestBindings.Http.RESPONSE) response: Response,
+ ): Promise<Response> {
+ return new Promise((resolve, reject) => {
+ this.getFileFromMultiPartForm(request).then(file=>{
+ this.uploadFileToBlueprintController(file, REST_BLUEPRINT_CONTROLLER_BASE_URL+"/blueprint-model/publish/", response).then(resp=>{
+ resolve(resp);
}, err=>{
reject(err);
});
@@ -103,7 +128,6 @@ export class BlueprintRestController {
});
});
}
-
@post('/enrich-blueprint')
async enrich(
@requestBody({
@@ -119,13 +143,11 @@ export class BlueprintRestController {
})
request: Request,
@inject(RestBindings.Http.RESPONSE) response: Response,
- ): Promise<any> {
+ ): Promise<Response> {
return new Promise((resolve, reject) => {
this.getFileFromMultiPartForm(request).then(file=>{
- this.uploadFileToBlueprintController(file, "/blueprint-model/enrich/").then(resp=>{
- response.setHeader("X-ONAP-RequestID", resp.headers['x-onap-requestid']);
- response.setHeader("Content-Disposition", resp.headers['content-disposition']);
- resolve(resp.body);
+ this.uploadFileToBlueprintController(file, REST_BLUEPRINT_CONTROLLER_BASE_URL+"/blueprint-model/enrich/", response).then(resp=>{
+ resolve(resp);
}, err=>{
reject(err);
});
@@ -139,25 +161,13 @@ export class BlueprintRestController {
async download(
@param.path.string('name') name: string,
@param.path.string('version') version:string,
- // @inject(RestBindings.Http.REQUEST) request: Request,
@inject(RestBindings.Http.RESPONSE) response: Response,
- ): Promise<any> {
- return new Promise((resolve, reject) => {
- this.downloadFileFromBlueprintController("/blueprint-model/download/by-name/"+name+"/version/"+version).then(resp=>{
- response.setHeader("X-ONAP-RequestID", resp.headers['x-onap-requestid']);
- response.setHeader("Content-Disposition", resp.headers['content-disposition']);
- resolve(resp.body);
- }, err=>{
- reject(err);
- });
- });
+ ): Promise<Response> {
+ return this.downloadFileFromBlueprintController(REST_BLUEPRINT_CONTROLLER_BASE_URL+"/blueprint-model/download/by-name/"+name+"/version/"+version, response);
}
- async getFileFromMultiPartForm(request: Request): Promise<any>{
+ async getFileFromMultiPartForm(request: Request): Promise<multiparty.File>{
return new Promise((resolve, reject) => {
- // let options = {
- // uploadDir: MULTIPART_FORM_UPLOAD_DIR
- // }
let form = new multiparty.Form();
form.parse(request, (err: any, fields: any, files: { [x: string]: any[]; }) => {
if (err) reject(err);
@@ -171,9 +181,38 @@ export class BlueprintRestController {
})
}
- async uploadFileToBlueprintController(file: any, uri: string): Promise<any>{
+ @post('/deploy-blueprint')
+ async deploy(
+ @requestBody({
+ description: 'multipart/form-data value.',
+ required: true,
+ content: {
+ 'multipart/form-data': {
+ // Skip body parsing
+ 'x-parser': 'stream',
+ schema: {type: 'object'},
+ },
+ },
+ })
+ request: Request,
+ @inject(RestBindings.Http.RESPONSE) response: Response,
+ ): Promise<Response> {
+ return new Promise((resolve, reject) => {
+ this.getFileFromMultiPartForm(request).then(file=>{
+ this.uploadFileToBlueprintController(file, REST_BLUEPRINT_PROCESSOR_BASE_URL+"/execution-service/upload/", response).then(resp=>{
+ resolve(resp);
+ }, err=>{
+ reject(err);
+ });
+ }, err=>{
+ reject(err);
+ });
+ });
+ }
+ async uploadFileToBlueprintController(file: multiparty.File, uri: string, response: Response): Promise<Response>{
let options = {
- url: REST_BLUEPRINT_CONTROLLER_BASE_URL + uri,
+ // url: REST_BLUEPRINT_CONTROLLER_BASE_URL + uri,
+ url:uri,
headers: {
Authorization: REST_BLUEPRINT_CONTROLLER_BASIC_AUTH_HEADER,
'content-type': 'multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW'
@@ -189,40 +228,43 @@ export class BlueprintRestController {
}
};
- return new Promise((resolve, reject) => {
- request_lib.post(options, (err: any, resp: any, body: any) => {
+ var removeTempFile = () => {
+ fs.unlink(file.path, (err: any) => {
if (err) {
- //delete tmp file
- fs.unlink(file.path, (err: any) => {
- if (err) {
- console.error(err);
- return
- }
- })
+ console.error(err);
+ }
+ });
+ }
+
+ return new Promise((resolve, reject) => {
+ request_lib.post(options)
+ .on("error", err => {
reject(err);
- }else{
- resolve(resp);
- }
- })
+ })
+ .pipe(response)
+ .once("finish", () => {
+ removeTempFile();
+ resolve(response);
+ });
})
}
-
- async downloadFileFromBlueprintController(uri: string): Promise<any> {
+ async downloadFileFromBlueprintController(uri: string, response: Response): Promise<Response> {
let options = {
- url: REST_BLUEPRINT_CONTROLLER_BASE_URL + uri,
+ url: uri,
+ // REST_BLUEPRINT_CONTROLLER_BASE_URL + uri,
headers: {
Authorization: REST_BLUEPRINT_CONTROLLER_BASIC_AUTH_HEADER,
}
};
-
return new Promise((resolve, reject) => {
- request_lib.get(options, (err: any, resp: any, body: any) => {
- if (err) {
+ request_lib.get(options)
+ .on("error", err => {
reject(err);
- }else{
- resolve(resp);
- }
- })
+ })
+ .pipe(response)
+ .once("finish", () => {
+ resolve(response);
+ });
})
-}
+ }
} \ No newline at end of file
diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfDeviceCommunicator.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfDeviceCommunicator.kt
index 6ef4f41fb..aa156e2a8 100644
--- a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfDeviceCommunicator.kt
+++ b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfDeviceCommunicator.kt
@@ -57,7 +57,7 @@ class NetconfDeviceCommunicator(private var inputStream: InputStream,
while (!socketClosed) {
val cInt = bufferReader.read()
if (cInt == -1) {
- log.error("$deviceInfo: Received cInt = -1")
+ log.debug("$deviceInfo: Received end of stream, closing socket.")
socketClosed = true
}
val c = cInt.toChar()
diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfSessionImpl.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfSessionImpl.kt
index 7e56e3e51..b1121b3d4 100644
--- a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfSessionImpl.kt
+++ b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfSessionImpl.kt
@@ -80,11 +80,11 @@ class NetconfSessionImpl(private val deviceInfo: DeviceInfo, private val rpcServ
RpcStatus.FAILURE, true)) {
rpcService.closeSession(true)
}
-
- session.close()
- // Closes the socket which should interrupt the streamHandler
- channel.close()
- client.close()
+ try {
+ close()
+ } catch (ioe: IOException) {
+ log.warn("$deviceInfo: Error closing session($sessionId) for host($deviceInfo)", ioe)
+ }
}
override fun reconnect() {
@@ -98,8 +98,8 @@ class NetconfSessionImpl(private val deviceInfo: DeviceInfo, private val rpcServ
checkAndReestablish()
try {
- return streamHandler.sendMessage(formattedRequest, messageId).get(replyTimeout.toLong(), TimeUnit.SECONDS)
-// replies.remove(messageId)
+ return streamHandler.getFutureFromSendMessage(streamHandler.sendMessage(formattedRequest, messageId),
+ replyTimeout.toLong(), TimeUnit.SECONDS)
} catch (e: InterruptedException) {
Thread.currentThread().interrupt()
throw NetconfException("$deviceInfo: Interrupted while waiting for reply for request: $formattedRequest", e)
@@ -109,10 +109,7 @@ class NetconfSessionImpl(private val deviceInfo: DeviceInfo, private val rpcServ
} catch (e: ExecutionException) {
log.warn("$deviceInfo: Closing session($sessionId) due to unexpected Error", e)
try {
- session.close()
- // Closes the socket which should interrupt the streamHandler
- channel.close()
- client.close()
+ close()
} catch (ioe: IOException) {
log.warn("$deviceInfo: Error closing session($sessionId) for host($deviceInfo)", ioe)
}
@@ -138,20 +135,23 @@ class NetconfSessionImpl(private val deviceInfo: DeviceInfo, private val rpcServ
override fun checkAndReestablish() {
try {
- if (client.isClosed) {
- log.info("Trying to restart the whole SSH connection with {}", deviceInfo)
- clearReplies()
- startConnection()
- } else if (session.isClosed) {
- log.info("Trying to restart the session with {}", deviceInfo)
- clearReplies()
- startSession()
- } else if (channel.isClosed) {
- log.info("Trying to reopen the channel with {}", deviceInfo)
- clearReplies()
- openChannel()
- } else {
- return
+ when {
+ client.isClosed -> {
+ log.info("Trying to restart the whole SSH connection with {}", deviceInfo)
+ clearReplies()
+ startConnection()
+ }
+ session.isClosed -> {
+ log.info("Trying to restart the session with {}", deviceInfo)
+ clearReplies()
+ startSession()
+ }
+ channel.isClosed -> {
+ log.info("Trying to reopen the channel with {}", deviceInfo)
+ clearReplies()
+ openChannel()
+ }
+ else -> return
}
} catch (e: IOException) {
log.error("Can't reopen connection for device {} error: {}", deviceInfo, e.message)
@@ -257,16 +257,8 @@ class NetconfSessionImpl(private val deviceInfo: DeviceInfo, private val rpcServ
}
val capabilityMatcher = NetconfMessageUtils.CAPABILITY_REGEX_PATTERN.matcher(serverHelloResponse)
- while (capabilityMatcher.find()) {
- deviceCapabilities.plus(capabilityMatcher.group(1))
- }
- }
-
- fun sessionstatus(state:String): Boolean{
- return when (state){
- "Close" -> channel.isClosed
- "Open" -> channel.isOpen
- else -> false
+ while (capabilityMatcher.find()) { //TODO: refactor to add unit test easily for device capability accumulation.
+ deviceCapabilities.add(capabilityMatcher.group(1))
}
}
@@ -279,7 +271,6 @@ class NetconfSessionImpl(private val deviceInfo: DeviceInfo, private val rpcServ
* Used by {@link NetconfSessionListenerImpl}
*/
internal fun addDeviceErrorReply(errReply: String) {
- println("addDeviceErrorReply (errReply: $errReply") //TODO : get rid of this.
errorReplies.add(errReply)
}
@@ -288,11 +279,21 @@ class NetconfSessionImpl(private val deviceInfo: DeviceInfo, private val rpcServ
* Used by {@link NetconfSessionListenerImpl}
*/
internal fun addDeviceReply(messageId: String, replyMsg: String) {
- println("addDeviceReply (messageId: $messageId replyMsg: $replyMsg") //TODO : get rid of this.
replies[messageId]?.complete(replyMsg)
}
/**
+ * Closes the session/channel/client
+ */
+ @Throws(IOException::class)
+ private fun close() {
+ session.close()
+ // Closes the socket which should interrupt the streamHandler
+ channel.close()
+ client.close()
+ }
+
+ /**
* Internal function for accessing replies for testing.
*/
internal fun getReplies() = replies
@@ -301,7 +302,6 @@ class NetconfSessionImpl(private val deviceInfo: DeviceInfo, private val rpcServ
* internal function for accessing errorReplies for testing.
*/
internal fun getErrorReplies() = errorReplies
-
internal fun clearErrorReplies() = errorReplies.clear()
internal fun clearReplies() = replies.clear()
internal fun setClient(client: SshClient) { this.client = client }
diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfSessionImplTest.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfSessionImplTest.kt
index 1f526f445..f5fd5410a 100644
--- a/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfSessionImplTest.kt
+++ b/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfSessionImplTest.kt
@@ -168,7 +168,6 @@ class NetconfSessionImplTest {
}
- @Ignore //TODO undo close method removal
@Test
fun `disconnect wraps exception from ssh closing error`() {
val netconfSessionSpy = spyk(netconfSession, recordPrivateCalls = true)
@@ -295,7 +294,6 @@ class NetconfSessionImplTest {
}
}
- @Ignore //TODO revert back on getFutureFromSendMessage
@Test
fun `syncRpc throws NetconfException if TimeoutException is caught`() {
val expectedExceptionMsg = "$deviceInfo: Timed out while waiting for reply for request $formattedRequest after ${deviceInfo.replyTimeout} sec."
@@ -310,23 +308,23 @@ class NetconfSessionImplTest {
}
}
- @Ignore
@Test
fun `syncRpc throws NetconfException if ExecutionException is caught`() {
val expectedExceptionMsg = "$deviceInfo: Closing session $sessionId for request $formattedRequest"
assertFailsWith(exceptionClass = NetconfException::class, message = expectedExceptionMsg) {
- val netconfSessionSpy = spyk(netconfSession)
+ val netconfSessionSpy = spyk(netconfSession, recordPrivateCalls = false)
val futureRet: CompletableFuture<String> = CompletableFuture.completedFuture(futureMsg)
every { netconfCommunicator.sendMessage(any(), any()) } returns futureRet
every { netconfCommunicator.getFutureFromSendMessage(any(), any(), any()) } throws
- ExecutionException("exec exception", Exception("nested exception")) //TODO revert getFutureFromSendMessage back
+ ExecutionException("exec exception", Exception("nested exception"))
+ every { netconfSessionSpy["close"]() as Unit } just Runs
every { netconfSessionSpy.checkAndReestablish() } just Runs
+ netconfSessionSpy.setSession(mockClientSession)
//call the method
netconfSessionSpy.syncRpc("0", "0")
}
}
- @Ignore //TODO revert back on getFutureFromSendMessage
@Test
fun `syncRpc throws NetconfException if caught ExecutionException and failed to close SSH session`() {
val expectedExceptionMsg = "$deviceInfo: Closing session $sessionId for request $formattedRequest"
@@ -525,7 +523,6 @@ class NetconfSessionImplTest {
verify { mockSshClient.close() }
}
- @Ignore
@Test
fun `disconnect wraps IOException if channel doesn't close`() { //this test is equivalent to others
every { rpcService.closeSession(false) } returns SUCCESSFUL_DEVICE_RESPONSE