summaryrefslogtreecommitdiffstats
path: root/sdnr/wt/odlux/apps/connectApp
diff options
context:
space:
mode:
authorAijana Schumann <aijana.schumann@highstreet-technologies.com>2021-08-04 11:59:18 +0200
committerAijana Schumann <aijana.schumann@highstreet-technologies.com>2021-08-04 16:06:05 +0200
commit437f67407aece6f7aed8e989638b0d64075f0c0a (patch)
tree53e9e336cd8544edf8a06c889e33f5b9c98fe083 /sdnr/wt/odlux/apps/connectApp
parent1c4995eb199437e9c86336efff9972f2049e1532 (diff)
Update ODLUX
Add various updates and bugfixes to NetworkMap, Configuration, LinkCalculation and ConnectApp Issue-ID: CCSDK-3414 Signed-off-by: Aijana Schumann <aijana.schumann@highstreet-technologies.com> Change-Id: I6ea5c3a9d6ccbe9c450da43220654a53fd2f262b Signed-off-by: Aijana Schumann <aijana.schumann@highstreet-technologies.com>
Diffstat (limited to 'sdnr/wt/odlux/apps/connectApp')
-rw-r--r--sdnr/wt/odlux/apps/connectApp/package.json4
-rw-r--r--sdnr/wt/odlux/apps/connectApp/pom.xml4
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/actions/tlsKeyActions.ts60
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx2
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx131
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx47
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/handlers/connectAppRootHandler.ts5
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/handlers/tlsKeyHandler.ts55
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/index.html2
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnection.ts7
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/pluginConnect.tsx4
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/services/connectService.ts522
12 files changed, 568 insertions, 275 deletions
diff --git a/sdnr/wt/odlux/apps/connectApp/package.json b/sdnr/wt/odlux/apps/connectApp/package.json
index 4fae39ccb..a6b23df84 100644
--- a/sdnr/wt/odlux/apps/connectApp/package.json
+++ b/sdnr/wt/odlux/apps/connectApp/package.json
@@ -27,8 +27,8 @@
"@types/react": "17.0.3",
"@types/react-dom": "17.0.2",
"@types/react-router-dom": "5.1.7",
- "@material-ui/core": "4.11.0",
- "@material-ui/icons": "4.9.1",
+ "@material-ui/core": "4.11.4",
+ "@material-ui/icons": "4.11.2",
"@types/classnames": "2.2.6",
"@types/flux": "3.1.8",
"@types/jquery": "3.3.10",
diff --git a/sdnr/wt/odlux/apps/connectApp/pom.xml b/sdnr/wt/odlux/apps/connectApp/pom.xml
index e3ca9dd4d..117a374c4 100644
--- a/sdnr/wt/odlux/apps/connectApp/pom.xml
+++ b/sdnr/wt/odlux/apps/connectApp/pom.xml
@@ -140,8 +140,8 @@
<!-- optional: default phase is "generate-resources" -->
<phase>initialize</phase>
<configuration>
- <nodeVersion>v10.16.3</nodeVersion>
- <yarnVersion>v1.19.0</yarnVersion>
+ <nodeVersion>v12.13.0</nodeVersion>
+ <yarnVersion>v1.22.10</yarnVersion>
</configuration>
</execution>
<execution>
diff --git a/sdnr/wt/odlux/apps/connectApp/src/actions/tlsKeyActions.ts b/sdnr/wt/odlux/apps/connectApp/src/actions/tlsKeyActions.ts
new file mode 100644
index 000000000..1da16d9ad
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/actions/tlsKeyActions.ts
@@ -0,0 +1,60 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2021 highstreet technologies GmbH 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==========================================================================
+ */
+import { Action } from '../../../../framework/src/flux/action';
+import { Dispatch } from '../../../../framework/src/flux/store';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+import { TlsKeys } from '../models/networkElementConnection';
+import { connectService } from '../services/connectService';
+
+/**
+ * Represents the base action.
+ */
+export class BaseAction extends Action { }
+
+/**
+ * Represents an action causing the store to load all TLS Keys.
+ */
+export class LoadAllTlsKeyListAction extends BaseAction { }
+
+/**
+ * Represents an action causing the store to get all TLS Keys.
+ */
+export class AllTlsKeyListLoadedAction extends BaseAction {
+ /**
+ * Initialize this instance.
+ *
+ * @param gets all the tlsKey list from the database.
+ */
+ constructor(public tlsList: TlsKeys[] | null, public error?: string) {
+ super();
+ }
+}
+
+/**
+ * Represents an asynchronous thunk action to load all tlsKeys
+ */
+
+export const loadAllTlsKeyListAsync = () => async (dispatch: Dispatch) => {
+ dispatch(new LoadAllTlsKeyListAction());
+ connectService.getTlsKeys().then(TlsKeyList => {
+ dispatch(new AllTlsKeyListLoadedAction(TlsKeyList));
+ }).catch(error => {
+ dispatch(new AllTlsKeyListLoadedAction(null, error));
+ });
+};
diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx
index 7d2f96af3..5a5ebcc45 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx
+++ b/sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx
@@ -54,7 +54,7 @@ class ConnectionStatusLogComponent extends React.Component<ConnectionStatusLogCo
render(): JSX.Element {
const refreshConnectionStatusLogAction = {
- icon: Refresh, tooltip: 'Refresh Connection Status Log Table', ariaLabel:'refresh', onClick: () => {
+ icon: Refresh, tooltip: 'Refresh Connection Status Log Table',ariaLabel:'refresh', onClick: () => {
this.setState({
refreshConnectionStatusLogEditorMode: RefreshConnectionStatusLogDialogMode.RefreshConnectionStatusLogTable
});
diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx
index 97e6647cf..df265c23d 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx
+++ b/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx
@@ -24,7 +24,9 @@ import DialogActions from '@material-ui/core/DialogActions';
import DialogContent from '@material-ui/core/DialogContent';
import DialogContentText from '@material-ui/core/DialogContentText';
import DialogTitle from '@material-ui/core/DialogTitle';
-import { FormControl, InputLabel, Select, MenuItem, Typography } from '@material-ui/core';
+import { FormControl, InputLabel, Select, MenuItem, Typography, Radio, RadioGroup, Options, FormLabel, FormControlLabel } from '@material-ui/core';
+import { loadAllTlsKeyListAsync } from '../actions/tlsKeyActions';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
import { IDispatcher, connect, Connect } from '../../../../framework/src/flux/connect';
@@ -67,13 +69,13 @@ const mapDispatch = (dispatcher: IDispatcher) => ({
//make sure properties are there in case they get renamed
const idProperty = propertyOf<UpdateNetworkElement>("id");
const isRequiredProperty = propertyOf<UpdateNetworkElement>("isRequired");
-
+
if (values.length === 2 && values.includes(idProperty as string) && values.includes(isRequiredProperty as string)) {
// do not mount network element, if only isRequired is changed
await dispatcher.dispatch(editNetworkElementAsyncActionCreator(element));
- } else if(!(values.length===1 &&values.includes(idProperty as string))) { //do not edit or mount element, if only id was saved into object (no changes made!)
+ } else if (!(values.length === 1 && values.includes(idProperty as string))) { //do not edit or mount element, if only id was saved into object (no changes made!)
await dispatcher.dispatch(editNetworkElementAsyncActionCreator(element));
await dispatcher.dispatch(mountNetworkElementAsyncActionCreator(mountElement));
}
@@ -81,7 +83,8 @@ const mapDispatch = (dispatcher: IDispatcher) => ({
removeNetworkElement: async (element: UpdateNetworkElement) => {
await dispatcher.dispatch(removeNetworkElementAsyncActionCreator(element));
dispatcher.dispatch(removeWebUriAction(element.id));
- }
+ },
+ getAvailableTlsKeys: async () => await dispatcher.dispatch(loadAllTlsKeyListAsync()),
});
type DialogSettings = {
@@ -156,26 +159,62 @@ type EditNetworkElementDialogComponentProps = Connect<undefined, typeof mapDispa
mode: EditNetworkElementDialogMode;
initialNetworkElement: NetworkElementConnection;
onClose: () => void;
+ radioChecked: string
};
-type EditNetworkElementDialogComponentState = NetworkElementConnection & { isNameValid: boolean, isHostSet: boolean };
+type EditNetworkElementDialogComponentState = NetworkElementConnection & {
+ isNameValid: boolean,
+ isHostSet: boolean,
+ isPasswordSelected: boolean,
+ isTlsSelected: boolean,
+ radioSelected: string,
+ showPasswordTextField: boolean,
+ showTlsDropdown: boolean
+};
class EditNetworkElementDialogComponent extends React.Component<EditNetworkElementDialogComponentProps, EditNetworkElementDialogComponentState> {
constructor(props: EditNetworkElementDialogComponentProps) {
super(props);
-
+ this.handleRadioChange = this.handleRadioChange.bind(this);
this.state = {
nodeId: this.props.initialNetworkElement.nodeId,
isRequired: false,
host: this.props.initialNetworkElement.host,
port: this.props.initialNetworkElement.port,
isNameValid: true,
- isHostSet: true
+ isHostSet: true,
+ isPasswordSelected: true,
+ isTlsSelected: false,
+ radioSelected: '',
+ showPasswordTextField: true,
+ showTlsDropdown: false
};
}
+ public handleRadioChange = (event: any) => {
+ this.setState({
+ radioSelected: event.target.value,
+ showPasswordTextField: event.target.value === 'password',
+ showTlsDropdown: event.target.value === 'tlsKey'
+ });
+ }
render(): JSX.Element {
const setting = settings[this.props.mode];
+ let { showPasswordTextField, showTlsDropdown, radioSelected } = this.state;
+ radioSelected = this.state.radioSelected.length > 0 ? this.state.radioSelected : this.props.radioChecked;
+
+ if (radioSelected === 'password') {
+ radioSelected = 'password';
+ showPasswordTextField = true;
+ showTlsDropdown = false;
+ } else if (radioSelected === 'tlsKey') {
+ radioSelected = 'tlsKey';
+ showPasswordTextField = false;
+ showTlsDropdown = true;
+ }
+
+ let tlsKeysList = this.props.state.connect.availableTlsKeys ? this.props.state.connect.availableTlsKeys.tlsKeysList ? this.props.state.connect.availableTlsKeys.tlsKeysList : [] : []
+
return (
<Dialog open={this.props.mode !== EditNetworkElementDialogMode.None}>
<DialogTitle id="form-dialog-title" aria-label={`${setting.dialogTitle.replace(/ /g, "-").toLowerCase()}-dialog`}>{setting.dialogTitle}</DialogTitle>
@@ -187,9 +226,39 @@ class EditNetworkElementDialogComponent extends React.Component<EditNetworkEleme
{!this.state.isNameValid && <Typography variant="body1" color="error">Name cannot be empty.</Typography>}
<TextField disabled={!setting.enableMountIdEditor} spellCheck={false} margin="dense" id="ipaddress" label="IP address" aria-label="ip adress" type="text" fullWidth value={this.state.host} onChange={(event) => { this.setState({ host: event.target.value }); }} />
{!this.state.isHostSet && <Typography variant="body1" color="error">IP Adress cannot be empty.</Typography>}
+
<TextField disabled={!setting.enableMountIdEditor} spellCheck={false} margin="dense" id="netconfport" label="NetConf port" aria-label="netconf port" type="number" fullWidth value={this.state.port.toString()} onChange={(event) => { this.setState({ port: +event.target.value }); }} />
{setting.enableUsernameEditor && <TextField disabled={!setting.enableUsernameEditor} spellCheck={false} margin="dense" id="username" label="Username" aria-label="username" type="text" fullWidth value={this.state.username} onChange={(event) => { this.setState({ username: event.target.value }); }} /> || null}
- {setting.enableUsernameEditor && <TextField disabled={!setting.enableUsernameEditor} spellCheck={false} margin="dense" id="password" label="Password" aria-label="password" type="password" fullWidth value={this.state.password} onChange={(event) => { this.setState({ password: event.target.value }); }} /> || null}
+
+ {setting.enableUsernameEditor &&
+ <RadioGroup row aria-label="password-tls-key" name="password-tls-key" value={radioSelected}
+ onChange={this.handleRadioChange} >
+ <FormControlLabel value='password' control={<Radio />} label="Password" onChange={this.onRadioSelect} />
+ <FormControlLabel value='tlsKey' control={<Radio />} label="TlsKey" onChange={this.onRadioSelect} />
+ </RadioGroup> || null}
+
+ {setting.enableUsernameEditor && showPasswordTextField &&
+ <TextField disabled={!setting.enableUsernameEditor || !showPasswordTextField} spellCheck={false} margin="dense"
+ id="password" aria-label="password" type="password" fullWidth value={this.state.password}
+ onChange={(event) => { this.setState({ password: event.target.value }); }}
+ /> || null}
+
+ <FormControl fullWidth disabled={!setting.enableUsernameEditor}>
+ {setting.enableUsernameEditor && showTlsDropdown &&
+ <div>
+ <InputLabel htmlFor="pass">--Select tls-key--</InputLabel>
+ <Select disabled={!setting.enableUsernameEditor || !showTlsDropdown}
+ id="tlsKey" aria-label="tlsKey" value={this.state.tlsKey} fullWidth // displayEmpty
+ onChange={(event) => { this.setState({ tlsKey: event.target.value as any }); }}
+ inputProps={{ name: 'tlsKey', id: 'tlsKey' }} >
+ <MenuItem value={""} disabled >--Select tls-key--</MenuItem>
+ {tlsKeysList.map(tlsKey =>
+ (<MenuItem value={tlsKey.key} key={tlsKey.key} aria-label={tlsKey.key} >{tlsKey.key}</MenuItem>))}
+ </Select>
+ </div>
+ }
+ </FormControl>
+
<FormControl fullWidth disabled={!setting.enableUsernameEditor}>
<InputLabel htmlFor="active">Required</InputLabel>
<Select aria-label="required-selection" value={this.state.isRequired || false} onChange={(event) => {
@@ -212,6 +281,7 @@ class EditNetworkElementDialogComponent extends React.Component<EditNetworkEleme
port: this.state.port,
username: this.state.username,
password: this.state.password,
+ tlsKey: this.state.tlsKey
});
}
event.preventDefault();
@@ -227,14 +297,44 @@ class EditNetworkElementDialogComponent extends React.Component<EditNetworkEleme
)
}
+ public renderTlsKeys = () => {
+ try {
+ this.props.getAvailableTlsKeys();
+ } catch (err) {
+ console.log(err);
+ }
+ }
+
+ public componentDidMount() {
+ this.renderTlsKeys();
+ }
+
+ public onRadioSelect = (e: any) => {
+ if (e.target.value == 'password') {
+ this.setState({ isPasswordSelected: true, isTlsSelected: false })
+ } else if (e.target.value == 'tlsKey') {
+ this.setState({ isPasswordSelected: false, isTlsSelected: true })
+ }
+ };
+
private onApply = (element: NetworkElementConnection) => {
this.props.onClose && this.props.onClose();
let updateElement: UpdateNetworkElement = {
id: this.state.nodeId
}
+ if (this.state.isPasswordSelected) {
+ element.tlsKey = ''
+ }
+ else if (this.state.isTlsSelected) { //check here
+ element.password = ''
+ }
+
switch (this.props.mode) {
case EditNetworkElementDialogMode.AddNewNetworkElement:
element && this.props.addNewNetworkElement(element);
+ this.setState({
+ radioSelected: ''
+ });
break;
case EditNetworkElementDialogMode.MountNetworkElement:
element && this.props.mountNetworkElement(element);
@@ -247,22 +347,31 @@ class EditNetworkElementDialogComponent extends React.Component<EditNetworkEleme
updateElement.isRequired = this.state.isRequired;
if (this.props.initialNetworkElement.username !== this.state.username)
updateElement.username = this.state.username;
- if (this.props.initialNetworkElement.password !== this.state.password)
+ if (this.props.initialNetworkElement.password !== this.state.password && this.state.isPasswordSelected) {
updateElement.password = this.state.password;
+ updateElement.tlsKey = '';
+ }
+ if (this.props.initialNetworkElement.tlsKey !== this.state.tlsKey && this.state.isTlsSelected) {
+ updateElement.tlsKey = this.state.tlsKey;
+ updateElement.password = '';
+ }
element && this.props.editNetworkElement(updateElement, element);
+ this.setState({
+ radioSelected: ''
+ });
break;
case EditNetworkElementDialogMode.RemoveNetworkElement:
element && this.props.removeNetworkElement(updateElement);
break;
}
- this.setState({ password: '', username: '' });
+ this.setState({ password: '', username: '', tlsKey: '' });
this.resetRequieredFields();
};
private onCancel = () => {
this.props.onClose && this.props.onClose();
- this.setState({ password: '', username: '' });
+ this.setState({ password: '', username: '', tlsKey: '', radioSelected: '' });
this.resetRequieredFields();
}
diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx
index 73706f678..5d0757ab2 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx
+++ b/sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx
@@ -19,7 +19,7 @@ import * as React from 'react';
import { Theme, createStyles, withStyles, WithStyles } from '@material-ui/core/styles';
import AddIcon from '@material-ui/icons/Add';
-import Refresh from '@material-ui/icons/Refresh';
+import Refresh from '@material-ui/icons/Refresh';
import LinkIcon from '@material-ui/icons/Link';
import LinkOffIcon from '@material-ui/icons/LinkOff';
import RemoveIcon from '@material-ui/icons/RemoveCircleOutline';
@@ -68,18 +68,18 @@ const styles = (theme: Theme) => createStyles({
});
type GetStatelessComponentProps<T> = T extends (props: infer P & { children?: React.ReactNode }) => any ? P : any
-const MenuItemExt : React.FC<GetStatelessComponentProps<typeof MenuItem>> = (props) => {
+const MenuItemExt: React.FC<GetStatelessComponentProps<typeof MenuItem>> = (props) => {
const [disabled, setDisabled] = React.useState(true);
const onMouseDown = (ev: React.MouseEvent<HTMLElement>) => {
- if (ev.button ===1){
- setDisabled(!disabled);
- ev.preventDefault();
- }
+ if (ev.button === 1) {
+ setDisabled(!disabled);
+ ev.preventDefault();
+ }
};
return (
<div onMouseDown={onMouseDown} >
- <MenuItem {...{...props, disabled: props.disabled && disabled }} />
- </div>
+ <MenuItem {...{ ...props, disabled: props.disabled && disabled }} />
+ </div>
);
};
@@ -119,17 +119,17 @@ export class NetworkElementsListComponent extends React.Component<NetworkElement
networkElementEditorMode: EditNetworkElementDialogMode.None,
refreshNetworkElementsEditorMode: RefreshNetworkElementsDialogMode.None,
elementInfo: null,
- elementInfoFeature:null,
+ elementInfoFeature: null,
infoNetworkElementEditorMode: InfoNetworkElementDialogMode.None
};
}
-
+
getContextMenu(rowData: NetworkElementConnection): JSX.Element[] {
const mountUri = rowData.id && connectService.getNetworkElementUri(rowData.id);
const mountPolicy = mountUri && getAccessPolicyByUrl(mountUri);
- const canMount = mountPolicy && mountPolicy.POST || false;
-
- const { configuration} = this.props.applicationState as any;
+ const canMount = mountPolicy && mountPolicy.POST || false;
+
+ const { configuration } = this.props.applicationState as any;
const buttonArray = [
<MenuItemExt aria-label={"mount-button"} onClick={event => this.onOpenMountdNetworkElementsDialog(event, rowData)} disabled={!canMount} ><LinkIcon /><Typography>Mount</Typography></MenuItemExt>,
<MenuItemExt aria-label={"unmount-button"} onClick={event => this.onOpenUnmountdNetworkElementsDialog(event, rowData)} disabled={!canMount} ><LinkOffIcon /><Typography>Unmount</Typography></MenuItemExt>,
@@ -160,6 +160,12 @@ export class NetworkElementsListComponent extends React.Component<NetworkElement
render(): JSX.Element {
const { classes } = this.props;
const { networkElementToEdit } = this.state;
+ let savedRadio = "password";
+ if (this.state.networkElementToEdit.password && this.state.networkElementToEdit.password.length > 0) {
+ savedRadio = 'password'
+ } else if (this.state.networkElementToEdit.tlsKey && this.state.networkElementToEdit.tlsKey.length > 0) {
+ savedRadio = 'tlsKey'
+ }
// const mountUri = rowData.id && connectService.getNetworkElementUri(rowData.id);
// const mountPolicy = mountUri && getAccessPolicyByUrl(mountUri);
@@ -167,7 +173,7 @@ export class NetworkElementsListComponent extends React.Component<NetworkElement
const canAdd = true;
const addRequireNetworkElementAction = {
- icon: AddIcon, tooltip: 'Add', ariaLabel:"add-element", onClick: () => {
+ icon: AddIcon, tooltip: 'Add', ariaLabel: "add-element", onClick: () => {
this.setState({
networkElementEditorMode: EditNetworkElementDialogMode.AddNewNetworkElement,
networkElementToEdit: emptyRequireNetworkElement,
@@ -176,16 +182,16 @@ export class NetworkElementsListComponent extends React.Component<NetworkElement
};
const refreshNetworkElementsAction = {
- icon: Refresh, tooltip: 'Refresh Network Elements table', ariaLabel:'refresh', onClick: () => {
+ icon: Refresh, tooltip: 'Refresh Network Elements table', ariaLabel: 'refresh', onClick: () => {
this.setState({
refreshNetworkElementsEditorMode: RefreshNetworkElementsDialogMode.RefreshNetworkElementsTable
});
}
};
-
+
return (
<>
- <NetworkElementTable stickyHeader tableId="network-element-table" customActionButtons={[refreshNetworkElementsAction, ...canAdd ? [addRequireNetworkElementAction]: []]} columns={[
+ <NetworkElementTable stickyHeader tableId="network-element-table" customActionButtons={[refreshNetworkElementsAction, ...canAdd ? [addRequireNetworkElementAction] : []]} columns={[
{ property: "nodeId", title: "Node Name", type: ColumnType.text },
{ property: "isRequired", title: "Required", type: ColumnType.boolean },
{ property: "status", title: "Connection Status", type: ColumnType.text },
@@ -202,6 +208,7 @@ export class NetworkElementsListComponent extends React.Component<NetworkElement
initialNetworkElement={networkElementToEdit}
mode={this.state.networkElementEditorMode}
onClose={this.onCloseEditNetworkElementDialog}
+ radioChecked={savedRadio}
/>
<RefreshNetworkElementsDialog
mode={this.state.refreshNetworkElementsEditorMode}
@@ -240,6 +247,11 @@ export class NetworkElementsListComponent extends React.Component<NetworkElement
}
private onOpenEditNetworkElementDialog = (event: React.MouseEvent<HTMLElement>, element: NetworkElementConnection) => {
+ let radioSaved;
+ if (element.password && element.password.length > 0)
+ radioSaved = 'password'
+ else if (element.tlsKey && element.tlsKey.length > 0)
+ radioSaved = 'tlsKey'
this.setState({
networkElementToEdit: {
nodeId: element.nodeId,
@@ -248,6 +260,7 @@ export class NetworkElementsListComponent extends React.Component<NetworkElement
port: element.port,
username: element.username,
password: element.password,
+ tlsKey: element.tlsKey
},
networkElementEditorMode: EditNetworkElementDialogMode.EditNetworkElement
});
diff --git a/sdnr/wt/odlux/apps/connectApp/src/handlers/connectAppRootHandler.ts b/sdnr/wt/odlux/apps/connectApp/src/handlers/connectAppRootHandler.ts
index 81ee97a0a..dbb9b2c04 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/handlers/connectAppRootHandler.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/handlers/connectAppRootHandler.ts
@@ -25,6 +25,7 @@ import { SetPanelAction, AddWebUriList, RemoveWebUri, SetWeburiSearchBusy } from
import { PanelId } from '../models/panelId';
import { guiCutThrough } from '../models/guiCutTrough';
import { connectionStatusCountHandler, IConnectionStatusCount } from './connectionStatusCountHandler';
+import { availableTlsKeysActionHandler, IAvailableTlsKeysState } from './tlsKeyHandler';
export interface IConnectAppStoreState {
networkElements: INetworkElementsState;
@@ -34,6 +35,7 @@ export interface IConnectAppStoreState {
elementFeatureInfo: IInfoNetworkElementFeaturesState;
guiCutThrough: guiCutThroughState;
connectionStatusCount: IConnectionStatusCount;
+ availableTlsKeys: IAvailableTlsKeysState
}
const currentOpenPanelHandler: IActionHandler<PanelId> = (state = null, action) => {
@@ -92,7 +94,8 @@ const actionHandlers = {
elementInfo: infoNetworkElementsActionHandler,
elementFeatureInfo: infoNetworkElementFeaturesActionHandler,
guiCutThrough: guiCutThroughHandler,
- connectionStatusCount: connectionStatusCountHandler
+ connectionStatusCount: connectionStatusCountHandler,
+ availableTlsKeys: availableTlsKeysActionHandler
};
export const connectAppRootHandler = combineActionHandler<IConnectAppStoreState>(actionHandlers);
diff --git a/sdnr/wt/odlux/apps/connectApp/src/handlers/tlsKeyHandler.ts b/sdnr/wt/odlux/apps/connectApp/src/handlers/tlsKeyHandler.ts
new file mode 100644
index 000000000..326b3cc8e
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/handlers/tlsKeyHandler.ts
@@ -0,0 +1,55 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2021 highstreet technologies GmbH 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==========================================================================
+ */
+import { IActionHandler } from '../../../../framework/src/flux/action';
+
+import { AllTlsKeyListLoadedAction, LoadAllTlsKeyListAction } from '../actions/tlsKeyActions';
+import { TlsKeys } from '../models/networkElementConnection';
+
+export interface IAvailableTlsKeysState {
+ tlsKeysList: TlsKeys[];
+ busy: boolean;
+}
+
+const tlsKeysStateInit: IAvailableTlsKeysState = {
+ tlsKeysList: [],
+ busy: false,
+};
+
+export const availableTlsKeysActionHandler: IActionHandler<IAvailableTlsKeysState> = (state = tlsKeysStateInit, action) => {
+ if (action instanceof LoadAllTlsKeyListAction) {
+ state = {
+ ...state,
+ busy: true
+ };
+
+ } else if (action instanceof AllTlsKeyListLoadedAction) {
+ if (!action.error && action.tlsList) {
+ state = {
+ ...state,
+ tlsKeysList: action.tlsList,
+ busy: false,
+ };
+ } else {
+ state = {
+ ...state,
+ busy: false
+ };
+ }
+ }
+ return state;
+}; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/src/index.html b/sdnr/wt/odlux/apps/connectApp/src/index.html
index 6f44c25f7..35dbdf71d 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/index.html
+++ b/sdnr/wt/odlux/apps/connectApp/src/index.html
@@ -19,7 +19,7 @@
connectApp.register();
faultApp.register();
inventoryApp.register();
- app("./app.tsx").configureApplication({ authentication:"basic", enablePolicy: false,});
+ app("./app.tsx").configureApplication({ authentication:"oauth", enablePolicy: false, transportpceUrl:"http://test.de"});
app("./app.tsx").runApplication();
});
</script>
diff --git a/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnection.ts b/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnection.ts
index 71eddc808..89070ab39 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnection.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnection.ts
@@ -24,6 +24,7 @@ export type NetworkElementConnection = {
port: number;
username?: string;
password?: string;
+ tlsKey?: string;
weburi?: string;
isWebUriUnreachable?: boolean;
status?: "Connected" | "mounted" | "unmounted" | "Connecting" | "Disconnected" | "idle";
@@ -47,12 +48,18 @@ export type UpdateNetworkElement = {
isRequired?: boolean;
username?: string;
password?: string;
+ tlsKey?: string;
}
export type ConnectionStatus = {
status: string
}
+export type TlsKeys = {
+ key: string
+}
+
+
/**
* Checks if a object has a given propertyname, if yes, the name is returned as string.
* @throws at compile time if property is not available
diff --git a/sdnr/wt/odlux/apps/connectApp/src/pluginConnect.tsx b/sdnr/wt/odlux/apps/connectApp/src/pluginConnect.tsx
index 461e14023..1990cc03d 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/pluginConnect.tsx
+++ b/sdnr/wt/odlux/apps/connectApp/src/pluginConnect.tsx
@@ -88,9 +88,9 @@ export function register() {
subscribe<IFormatedMessage>(["object-creation-notification", "object-deletion-notification", "attribute-value-changed-notification"], (msg => {
const store = applicationApi.applicationStore;
if (msg && msg.type.type === "object-creation-notification" && store) {
- store.dispatch(new AddSnackbarNotification({ message: `Adding network element [${msg['node-id']}]`, options: { variant: 'info' } }));
+ store.dispatch(new AddSnackbarNotification({ message: `Adding network element [${msg.data['object-id-ref']}]`, options: { variant: 'info' } }));
} else if (msg && (msg.type.type === "object-deletion-notification" || msg.type.type === "attribute-value-changed-notification") && store) {
- store.dispatch(new AddSnackbarNotification({ message: `Updating network element [${msg['node-id']}]`, options: { variant: 'info' } }));
+ store.dispatch(new AddSnackbarNotification({ message: `Updating network element [${msg.data['object-id-ref']}]`, options: { variant: 'info' } }));
}
if (store) {
store.dispatch(updateCurrentViewAsyncAction() as any).then(() => {
diff --git a/sdnr/wt/odlux/apps/connectApp/src/services/connectService.ts b/sdnr/wt/odlux/apps/connectApp/src/services/connectService.ts
index ed8b0f67d..427acd3ec 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/services/connectService.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/services/connectService.ts
@@ -16,243 +16,289 @@
* ============LICENSE_END==========================================================================
*/
- import { requestRest } from '../../../../framework/src/services/restService';
- import { NetworkElementConnection, ConnectionStatus, UpdateNetworkElement } from '../models/networkElementConnection';
- import { convertPropertyNames, replaceUpperCase } from '../../../../framework/src/utilities/yangHelper';
- import { Result } from '../../../../framework/src/models/elasticSearch';
-
- import { FeatureTopology, Topology, TopologyNode, Module } from '../models/topologyNetconf';
- import { guiCutThrough } from '../models/guiCutTrough';
-
- /**
- * Represents a web api accessor service for all Network Elements actions.
- */
- class ConnectService {
- public getNetworkElementUri = (nodeId: string) => '/rests/data/network-topology:network-topology/topology=topology-netconf/node=' + nodeId;
- public getNetworkElementConnectDataProviderUri = (operation: "create" | "update" | "delete" ) => `/rests/operations/data-provider:${operation}-network-element-connection`;
- public getAllWebUriExtensionsForNetworkElementListUri = (nodeId: string) => this.getNetworkElementUri(nodeId) + '/yang-ext:mount/core-model:network-element';
- public getNetworkElementYangLibraryFeature = (nodeId: string) => '/rests/data/network-topology:network-topology/topology=topology-netconf/node=' + nodeId + '/yang-ext:mount/ietf-yang-library:yang-library?content=nonconfig'
-
- /**
- * Inserts a network elements.
- */
- public async createNetworkElement(element: NetworkElementConnection): Promise<NetworkElementConnection | null> {
- const path = this.getNetworkElementConnectDataProviderUri("create") ;
- const result = await requestRest<NetworkElementConnection>(path, {
- method: "POST", body: JSON.stringify(convertPropertyNames({ "data-provider:input": element }, replaceUpperCase))
- });
- return result || null;
- }
-
- /**
- * Updates a network element.
+import { requestRest } from '../../../../framework/src/services/restService';
+import { NetworkElementConnection, ConnectionStatus, UpdateNetworkElement } from '../models/networkElementConnection';
+import { TlsKeys } from '../models/networkElementConnection'
+import { convertPropertyNames, replaceUpperCase } from '../../../../framework/src/utilities/yangHelper';
+import { Result } from '../../../../framework/src/models/elasticSearch';
+
+import { FeatureTopology, Topology, TopologyNode, Module } from '../models/topologyNetconf';
+import { guiCutThrough } from '../models/guiCutTrough';
+
+/**
+* Represents a web api accessor service for all Network Elements actions.
+*/
+class ConnectService {
+ public getNetworkElementUri = (nodeId: string) => '/rests/data/network-topology:network-topology/topology=topology-netconf/node=' + nodeId;
+ public getNetworkElementConnectDataProviderUri = (operation: "create" | "update" | "delete") => `/rests/operations/data-provider:${operation}-network-element-connection`;
+ public getAllWebUriExtensionsForNetworkElementListUri = (nodeId: string) => this.getNetworkElementUri(nodeId) + '/yang-ext:mount/core-model:network-element';
+ public getNetworkElementYangLibraryFeature = (nodeId: string) => '/rests/data/network-topology:network-topology/topology=topology-netconf/node=' + nodeId + '/yang-ext:mount/ietf-yang-library:yang-library?content=nonconfig'
+
+ /**
+ * Inserts a network elements.
*/
- public async updateNetworkElement(element: UpdateNetworkElement): Promise<NetworkElementConnection | null> {
- const path = this.getNetworkElementConnectDataProviderUri("update");
- const result = await requestRest<NetworkElementConnection>(path, {
- method: "POST", body: JSON.stringify(convertPropertyNames({ "data-provider:input": element }, replaceUpperCase))
- });
- return result || null;
- }
-
- /**
- * Deletes a network element.
- */
- public async deleteNetworkElement(element: UpdateNetworkElement): Promise<NetworkElementConnection | null> {
- const query = {
- "id": element.id
- };
- const path = this.getNetworkElementConnectDataProviderUri("delete");
- const result = await requestRest<NetworkElementConnection>(path, {
- method: "POST", body: JSON.stringify(convertPropertyNames({ "data-provider:input": query }, replaceUpperCase))
- });
- return result || null;
- }
-
- /** Mounts network element. */
- public async mountNetworkElement(networkElement: NetworkElementConnection): Promise<boolean> {
- const path = this.getNetworkElementUri(networkElement.nodeId);
- const mountXml = [
- '<node xmlns="urn:TBD:params:xml:ns:yang:network-topology">',
- `<node-id>${networkElement.nodeId}</node-id>`,
- `<host xmlns="urn:opendaylight:netconf-node-topology">${networkElement.host}</host>`,
- `<port xmlns="urn:opendaylight:netconf-node-topology">${networkElement.port}</port>`,
- `<username xmlns="urn:opendaylight:netconf-node-topology">${networkElement.username}</username>`,
- `<password xmlns="urn:opendaylight:netconf-node-topology">${networkElement.password}</password>`,
- ' <tcp-only xmlns="urn:opendaylight:netconf-node-topology">false</tcp-only>',
-
- ' <!-- non-mandatory fields with default values, you can safely remove these if you do not wish to override any of these values-->',
- ' <reconnect-on-changed-schema xmlns="urn:opendaylight:netconf-node-topology">false</reconnect-on-changed-schema>',
- ' <connection-timeout-millis xmlns="urn:opendaylight:netconf-node-topology">20000</connection-timeout-millis>',
- ' <max-connection-attempts xmlns="urn:opendaylight:netconf-node-topology">100</max-connection-attempts>',
- ' <between-attempts-timeout-millis xmlns="urn:opendaylight:netconf-node-topology">2000</between-attempts-timeout-millis>',
- ' <sleep-factor xmlns="urn:opendaylight:netconf-node-topology">1.5</sleep-factor>',
-
- ' <!-- keepalive-delay set to 0 turns off keepalives-->',
- ' <keepalive-delay xmlns="urn:opendaylight:netconf-node-topology">120</keepalive-delay>',
- '</node>'].join('');
-
- try {
- const result = await requestRest<string>(path, {
- method: 'PUT',
- headers: {
- 'Content-Type': 'application/xml',
- 'Accept': 'application/xml'
- },
- body: mountXml
- });
- // expect an empty answer
- return result !== null;
- } catch {
- return false;
- }
- };
-
- /** Unmounts a network element by its id. */
- public async unmountNetworkElement(nodeId: string): Promise<boolean> {
- const path = this.getNetworkElementUri(nodeId);
-
- try {
- const result = await requestRest<string>(path, {
- method: 'DELETE',
- headers: {
- 'Content-Type': 'application/xml',
- 'Accept': 'application/xml'
- },
- });
- // expect an empty answer
- return result !== null;
-
- } catch {
- return false;
- }
- };
-
- /** Yang capabilities of the selected network elements. */
- public async infoNetworkElement(nodeId: string): Promise<TopologyNode | null> {
- const path = this.getNetworkElementUri(nodeId);
- const topologyRequestPomise = requestRest<Topology>(path, { method: "GET" });
-
- return topologyRequestPomise && topologyRequestPomise.then(result => {
- return result && result["network-topology:node"] && result["network-topology:node"][0] || null;
- });
- }
-
-
- /** Yang features of the selected network element module. */
- public async infoNetworkElementFeatures(nodeId: string): Promise<Module[] | null | undefined> {
- const path = this.getNetworkElementYangLibraryFeature(nodeId);
- const topologyRequestPomise = requestRest<FeatureTopology>(path, { method: "GET" });
-
- return topologyRequestPomise && topologyRequestPomise.then(result => {
- const resultFinal = result && result['ietf-yang-library:yang-library']
- && result["ietf-yang-library:yang-library"]["module-set"] &&
- result["ietf-yang-library:yang-library"]["module-set"][0] &&
- result["ietf-yang-library:yang-library"]["module-set"][0]['module'] || null;
- return resultFinal;
- });
- }
-
-
-
- /**
- * Get the connection state of the network element.
+ public async createNetworkElement(element: NetworkElementConnection): Promise<NetworkElementConnection | null> {
+ const path = this.getNetworkElementConnectDataProviderUri("create");
+ const result = await requestRest<NetworkElementConnection>(path, {
+ method: "POST", body: JSON.stringify(convertPropertyNames({ "data-provider:input": element }, replaceUpperCase))
+ });
+ return result || null;
+ }
+
+ /**
+ * Updates a network element.
+ */
+ public async updateNetworkElement(element: UpdateNetworkElement): Promise<NetworkElementConnection | null> {
+ const path = this.getNetworkElementConnectDataProviderUri("update");
+ const result = await requestRest<NetworkElementConnection>(path, {
+ method: "POST", body: JSON.stringify(convertPropertyNames({ "data-provider:input": element }, replaceUpperCase))
+ });
+ return result || null;
+ }
+
+ /**
+ * Deletes a network element.
*/
- public async getNetworkElementConnectionStatus(element: string): Promise<(ConnectionStatus)[] | null> {
- const path = `/rests/operations/data-provider:read-network-element-connection-list`;
- const query = {
- "data-provider:input": {
- "filter": [{
- "property": "node-id",
- "filtervalue": element
- }],
- "pagination": {
- "size": 20,
- "page": 1
- }
- }
- }
- const result = await requestRest<Result<ConnectionStatus>>(path, { method: "POST", body: JSON.stringify(query) });
- return result && result["data-provider:output"] && result["data-provider:output"].data && result["data-provider:output"].data.map(ne => ({
- status: ne.status
- })) || null;
- }
-
- public async getAllWebUriExtensionsForNetworkElementListAsync(neList: string[]): Promise<(guiCutThrough)[]> {
- const path = `/rests/operations/data-provider:read-gui-cut-through-entry`;
- let webUriList: guiCutThrough[] = []
- const query = {
- "data-provider:input": {
- "filter": [{
- "property": "id",
- "filtervalues": neList
- }],
- "pagination": {
- "size": 20,
- "page": 1
- }
- }
- }
-
- const result = await requestRest<Result<guiCutThrough>>(path, { method: "POST", body: JSON.stringify(query) });
- const resultData = result && result["data-provider:output"] && result["data-provider:output"].data;
- neList.forEach(nodeId => {
- let entryNotFound = true;
- if (resultData) {
- const BreakException = {};
- try {
- resultData.forEach(entry => {
- if (entry.id == nodeId) {
- entryNotFound = false;
- if (entry.weburi) {
- webUriList.push({ id: nodeId, weburi: entry.weburi });
- } else {
- webUriList.push({ id: nodeId, weburi: undefined });
- }
- throw BreakException;
- }
- });
- } catch (e) {}
- }
- if (entryNotFound)
- webUriList.push({ id: nodeId, weburi: undefined });
- });
- return webUriList;
- }
-
- // public async getAllWebUriExtensionsForNetworkElementListAsync(ne: string[]): Promise<(guiCutThrough)[] | null> {
-
- // let promises: any[] = [];
- // let webUris: guiCutThrough[] = []
-
- // ne.forEach(nodeId => {
- // const path = this.getAllWebUriExtensionsForNetworkElementListUri(nodeId);
-
- // // add search request to array
- // promises.push(requestRest<any>(path, { method: "GET" })
- // .then(result => {
- // if (result != null && result['core-model:network-element'] && result['core-model:network-element'].extension) {
- // const webUri = result['core-model:network-element'].extension.find((item: any) => item['value-name'] === "webUri")
- // if (webUri) {
- // webUris.push({ weburi: webUri.value, id: nodeId });
- // } else {
- // webUris.push({ weburi: undefined, id: nodeId });
- // }
- // } else {
- // webUris.push({ weburi: undefined, id: nodeId });
- // }
- // })
- // .catch(error => {
- // webUris.push({ weburi: undefined, id: nodeId });
- // }))
- // })
- // // wait until all promises are done and return weburis
- // return Promise.all(promises).then(result => { return webUris });
- // }
-
- }
-
-
-
- export const connectService = new ConnectService();
- \ No newline at end of file
+ public async deleteNetworkElement(element: UpdateNetworkElement): Promise<NetworkElementConnection | null> {
+ const query = {
+ "id": element.id
+ };
+ const path = this.getNetworkElementConnectDataProviderUri("delete");
+ const result = await requestRest<NetworkElementConnection>(path, {
+ method: "POST", body: JSON.stringify(convertPropertyNames({ "data-provider:input": query }, replaceUpperCase))
+ });
+ return result || null;
+ }
+
+ /** Mounts network element. */
+ public async mountNetworkElement(networkElement: NetworkElementConnection): Promise<boolean> {
+ const path = this.getNetworkElementUri(networkElement.nodeId);
+ const mountXml = [
+ '<node xmlns="urn:TBD:params:xml:ns:yang:network-topology">',
+ `<node-id>${networkElement.nodeId}</node-id>`,
+ `<host xmlns="urn:opendaylight:netconf-node-topology">${networkElement.host}</host>`,
+ `<port xmlns="urn:opendaylight:netconf-node-topology">${networkElement.port}</port>`,
+ `<username xmlns="urn:opendaylight:netconf-node-topology">${networkElement.username}</username>`,
+ `<password xmlns="urn:opendaylight:netconf-node-topology">${networkElement.password}</password>`,
+ ' <tcp-only xmlns="urn:opendaylight:netconf-node-topology">false</tcp-only>',
+
+ ' <!-- non-mandatory fields with default values, you can safely remove these if you do not wish to override any of these values-->',
+ ' <reconnect-on-changed-schema xmlns="urn:opendaylight:netconf-node-topology">false</reconnect-on-changed-schema>',
+ ' <connection-timeout-millis xmlns="urn:opendaylight:netconf-node-topology">20000</connection-timeout-millis>',
+ ' <max-connection-attempts xmlns="urn:opendaylight:netconf-node-topology">100</max-connection-attempts>',
+ ' <between-attempts-timeout-millis xmlns="urn:opendaylight:netconf-node-topology">2000</between-attempts-timeout-millis>',
+ ' <sleep-factor xmlns="urn:opendaylight:netconf-node-topology">1.5</sleep-factor>',
+
+ ' <!-- keepalive-delay set to 0 turns off keepalives-->',
+ ' <keepalive-delay xmlns="urn:opendaylight:netconf-node-topology">120</keepalive-delay>',
+ '</node>'].join('');
+
+ const tlsXml = [
+ '<node xmlns="urn:TBD:params:xml:ns:yang:network-topology">',
+ `<node-id>${networkElement.nodeId}</node-id>`,
+ '<key-based xmlns="urn:opendaylight:netconf-node-topology">',
+ `<key-id xmlns="urn:opendaylight:netconf-node-topology">${networkElement.tlsKey}</key-id>`,
+ `<username xmlns="urn:opendaylight:netconf-node-topology">${networkElement.username}</username>`,
+ '</key-based>',
+ `<host xmlns="urn:opendaylight:netconf-node-topology">${networkElement.host}</host>`,
+ `<port xmlns="urn:opendaylight:netconf-node-topology">${networkElement.port}</port>`,
+ '<tcp-only xmlns="urn:opendaylight:netconf-node-topology">false</tcp-only>',
+ '<protocol xmlns="urn:opendaylight:netconf-node-topology">',
+ '<name xmlns="urn:opendaylight:netconf-node-topology">TLS</name>',
+ ' </protocol>',
+ '<max-connection-attempts xmlns="urn:opendaylight:netconf-node-topology">2</max-connection-attempts>',
+ '</node>'].join('')
+ let bodyXml;
+ if (networkElement.password) {
+ bodyXml = mountXml
+ }
+ else {
+ bodyXml = tlsXml
+ }
+
+ try {
+ const result = await requestRest<string>(path, {
+ method: 'PUT',
+ headers: {
+ 'Content-Type': 'application/xml',
+ 'Accept': 'application/xml'
+ },
+ body: bodyXml
+ });
+ // expect an empty answer
+ return result !== null;
+ } catch {
+ return false;
+ }
+ };
+
+ /** Unmounts a network element by its id. */
+ public async unmountNetworkElement(nodeId: string): Promise<boolean> {
+ const path = this.getNetworkElementUri(nodeId);
+
+ try {
+ const result = await requestRest<string>(path, {
+ method: 'DELETE',
+ headers: {
+ 'Content-Type': 'application/xml',
+ 'Accept': 'application/xml'
+ },
+ });
+ // expect an empty answer
+ return result !== null;
+
+ } catch {
+ return false;
+ }
+ };
+
+ /** Yang capabilities of the selected network elements. */
+ public async infoNetworkElement(nodeId: string): Promise<TopologyNode | null> {
+ const path = this.getNetworkElementUri(nodeId);
+ const topologyRequestPomise = requestRest<Topology>(path, { method: "GET" });
+
+ return topologyRequestPomise && topologyRequestPomise.then(result => {
+ return result && result["network-topology:node"] && result["network-topology:node"][0] || null;
+ });
+ }
+
+
+ /** Yang features of the selected network element module. */
+ public async infoNetworkElementFeatures(nodeId: string): Promise<Module[] | null | undefined> {
+ const path = this.getNetworkElementYangLibraryFeature(nodeId);
+ const topologyRequestPomise = requestRest<FeatureTopology>(path, { method: "GET" });
+
+ return topologyRequestPomise && topologyRequestPomise.then(result => {
+ const resultFinal = result && result['ietf-yang-library:yang-library']
+ && result["ietf-yang-library:yang-library"]["module-set"] &&
+ result["ietf-yang-library:yang-library"]["module-set"][0] &&
+ result["ietf-yang-library:yang-library"]["module-set"][0]['module'] || null;
+ return resultFinal;
+ });
+ }
+
+
+
+ /**
+ * Get the connection state of the network element.
+ */
+ public async getNetworkElementConnectionStatus(element: string): Promise<(ConnectionStatus)[] | null> {
+ const path = `/rests/operations/data-provider:read-network-element-connection-list`;
+ const query = {
+ "data-provider:input": {
+ "filter": [{
+ "property": "node-id",
+ "filtervalue": element
+ }],
+ "pagination": {
+ "size": 20,
+ "page": 1
+ }
+ }
+ }
+ const result = await requestRest<Result<ConnectionStatus>>(path, { method: "POST", body: JSON.stringify(query) });
+ return result && result["data-provider:output"] && result["data-provider:output"].data && result["data-provider:output"].data.map(ne => ({
+ status: ne.status
+ })) || null;
+ }
+
+ /**
+ * Gets all available tlsKeys.
+ */
+
+ public async getTlsKeys(): Promise<(TlsKeys)[] | null> {
+ const path = '/rests/operations/data-provider:read-tls-key-entry';
+ const query = {
+ "data-provider:input": {
+ "filter": [],
+ "sortorder": [],
+ "pagination": {
+ "size": 20,
+ "page": 1
+ }
+ }
+ };
+
+ const result = await requestRest<Result<string>>(path, { method: "POST", body: JSON.stringify(query) });
+ return result && result["data-provider:output"] && result["data-provider:output"].data && result["data-provider:output"].data.map(ne => ({
+ key: ne
+ })) || null;
+ }
+
+ public async getAllWebUriExtensionsForNetworkElementListAsync(neList: string[]): Promise<(guiCutThrough)[]> {
+ const path = `/rests/operations/data-provider:read-gui-cut-through-entry`;
+ let webUriList: guiCutThrough[] = []
+ const query = {
+ "data-provider:input": {
+ "filter": [{
+ "property": "id",
+ "filtervalues": neList
+ }],
+ "pagination": {
+ "size": 20,
+ "page": 1
+ }
+ }
+ }
+
+ const result = await requestRest<Result<guiCutThrough>>(path, { method: "POST", body: JSON.stringify(query) });
+ const resultData = result && result["data-provider:output"] && result["data-provider:output"].data;
+ neList.forEach(nodeId => {
+ let entryNotFound = true;
+ if (resultData) {
+ const BreakException = {};
+ try {
+ resultData.forEach(entry => {
+ if (entry.id == nodeId) {
+ entryNotFound = false;
+ if (entry.weburi) {
+ webUriList.push({ id: nodeId, weburi: entry.weburi });
+ } else {
+ webUriList.push({ id: nodeId, weburi: undefined });
+ }
+ throw BreakException;
+ }
+ });
+ } catch (e) { }
+ }
+ if (entryNotFound)
+ webUriList.push({ id: nodeId, weburi: undefined });
+ });
+ return webUriList;
+ }
+
+ // public async getAllWebUriExtensionsForNetworkElementListAsync(ne: string[]): Promise<(guiCutThrough)[] | null> {
+
+ // let promises: any[] = [];
+ // let webUris: guiCutThrough[] = []
+
+ // ne.forEach(nodeId => {
+ // const path = this.getAllWebUriExtensionsForNetworkElementListUri(nodeId);
+
+ // // add search request to array
+ // promises.push(requestRest<any>(path, { method: "GET" })
+ // .then(result => {
+ // if (result != null && result['core-model:network-element'] && result['core-model:network-element'].extension) {
+ // const webUri = result['core-model:network-element'].extension.find((item: any) => item['value-name'] === "webUri")
+ // if (webUri) {
+ // webUris.push({ weburi: webUri.value, id: nodeId });
+ // } else {
+ // webUris.push({ weburi: undefined, id: nodeId });
+ // }
+ // } else {
+ // webUris.push({ weburi: undefined, id: nodeId });
+ // }
+ // })
+ // .catch(error => {
+ // webUris.push({ weburi: undefined, id: nodeId });
+ // }))
+ // })
+ // // wait until all promises are done and return weburis
+ // return Promise.all(promises).then(result => { return webUris });
+ // }
+
+}
+
+
+
+export const connectService = new ConnectService();