blob: 624829c0b9c2d8839ea359b157b3ce2de80ca425 [file] [log] [blame]
/*
*
* Copyright 2016 RIFT.IO Inc
*
* 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.
*
*/
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import SelectOption from 'widgets/form_controls/selectOption.jsx';
import imgAdd from '../../node_modules/open-iconic/svg/plus.svg'
import imgRemove from '../../node_modules/open-iconic/svg/trash.svg'
import TextInput from 'widgets/form_controls/textInput.jsx';
import './instantiateInputParams.scss';
export default class InstantiateInputParams extends Component {
constructor(props) {
super(props);
}
nsConfigHTML = (props) => {
return (
<div className="configure-nsd_section">
<div className="noticeSubText noticeSubText_right">
* required
</div>
<div className="inputControls">
<TextInput label="Instance Name" required={true} type="text" pattern="^[a-zA-Z0-9_]*$" style={{textAlign:'left'}} onChange={props.updateName} value={props.name}/>
<label>Resource Orchestrator
<SelectOption options={constructROOptions(props.resourceOrchestrators)} onChange={props.nsFn.updateSelectedRoAccount} />
</label>
{
(props.selectedResourceOrchestrator.datacenters && props.selectedResourceOrchestrator.datacenters.datacenters) ?
(
<label>Datacenter
<SelectOption options={constructDataCenterOptions(props.selectedResourceOrchestrator.datacenters.datacenters)} onChange={props.nsFn.updateSelectedDataCenter} />
</label>
)
: <span>No datacenters configured</span>
}
</div>
</div>
)
}
vnfCloudAccountsHTML = (props) => {
let nsd = props.nsd;
let dataCenters = props.dataCenters;
return (
<div className="configure-nsd_section">
<h3 className="launchpadCard_title">NS/VNF ACCOUNT PLACEMENTS</h3>
{
//selectedNSDid
nsd['constituent-vnfd'] && nsd['constituent-vnfd'].map(function(v, i) {
let defaultValue = false;
if(props.vnfdCloudAccounts && props.vnfdCloudAccounts.hasOwnProperty(v['member-vnf-index'])) {
defaultValue = props.vnfdCloudAccounts[v['member-vnf-index']]
}
return (
<div className="inputControls" key={i}>
<h4 className="inputControls-title">VNFD: {v['vnf-name']}</h4>
{
(props.selectedResourceOrchestrator.datacenters && props.selectedResourceOrchestrator.datacenters.datacenters) ?
(
<label>Datacenter
<SelectOption options={constructDataCenterOptions(props.selectedResourceOrchestrator.datacenters.datacenters)} onChange={props.vnfFn.updateSelectedDataCenter.bind(null, v['member-vnf-index'])} initial={true} />
</label>
)
: <span>No datacenters configured</span>
}
{
(props.configAgentAccounts && props.configAgentAccounts.length > 0) ?
<label>Config Agent Account
<SelectOption options={props.configAgentAccounts && props.configAgentAccounts.map(function(c) {
return {
label: c.name,
value: c.name
}
})} initial={true} onChange={props.vnfFn.updateSelectedConfigAgent(v['member-vnf-index'])} defaultValue={false} />
</label> : null
}
</div>
)
})
}
</div>
)
}
//"vnfd-catalog/vnfd[id=../../../constituent-vnfd[0]/vnfd-id-ref]/version";
inputParametersHTML = (props) => {
let inputParameters = props.inputParameters;
const handleChange = (i, event) => props.updateInputParam(i, event.target.value);
let nsInputParamsHTML = [];
inputParameters && inputParameters.map(function(input, i) {
nsInputParamsHTML.push(
<div className="inputControls" key={i}>
<TextInput label={ input.label || input.xpath } value={input.value || input['default-value']} type="text" onChange={handleChange.bind(this, i)} />
</div>
);
});
var nsinput = (
<div className="configure-nsd_section" >
<h3 className="launchpadCard_title">NS Input Parameters</h3>
{
nsInputParamsHTML
}
</div>
);
return nsinput;
}
//"vnfd-catalog/vnfd[id=../../../constituent-vnfd[0]/vnfd-id-ref]/version";
vnfInputParametersHTML = (props) => {
let vnfInputParams = props.vnfInputParams;
const handleChange = (vnfIndex, parameterIndex, event) => props.updateVnfInputParam(vnfIndex, parameterIndex, event.target.value);
let vnfInputParamsHTML = [];
vnfInputParams && vnfInputParams.map(function(input, i) {
vnfInputParamsHTML.push(
<div className="configure-nsd_section" key={i}>
<h3 className="launchpadCard_title">{`VNF Input Parameters: ${input['name']}:${input['member-vnf-index-ref']}`}</h3>
{
input['input-parameter'].filter(function(p){
let regex = /vnfd\[(?:vnfd:)?id\s*=\s*'?"?(\S+?)'?"?\s*\]/
// if has id, then it belongs in a vnfd section
if (p.xpath.match(regex)) {
// look for matching vnfd
if ((p.xpath.match(regex)[1] == input['vnfd-id-ref'])) {
return true
} else {
return false;
}
} else {
return true;
}
}).map(function(p, j){
let param = vnfInputParams[i]['input-parameter'][j];
return (<div className="inputControls" key={j}>
<TextInput label={(p.label || p.xpath)} value={param.value || param['default-value']} type="text" onChange={handleChange.bind(this, i, j)} />
</div>)
})
}
</div>
);
})
return <div>{vnfInputParamsHTML}</div>;
}
nsPlacementGroupsHTML = (props) => {
let nsPlacementGroups = props.nsPlacementGroups;
let displayPlacementGroups = props.displayPlacementGroups;
if (nsPlacementGroups && nsPlacementGroups.length > 0 && displayPlacementGroups) {
return (
<div className="configure-nsd_section">
<h3 className="launchpadCard_title">NS Placement Groups</h3>
{
nsPlacementGroups.map(function(input, i) {
return (
<div key={i} className="configure-nsd_section-info">
<div className="placementGroup_description">
<div className="placementGroup_description-name">
<strong>{input.name}</strong> contains: {
input['member-vnfd'].map((m,i) => {
let s = m.name;
if(i>0) {
s = ', ' + m.name
};
return s;
})
}
</div>
<div><em>{input.requirement}</em></div>
<div><strong>Strategy:</strong> {input.strategy}</div>
</div>
<label>
<span> Availability Zone <span onClick={showInput} className="addInput"><img src={imgAdd} />Add</span> </span>
<div style={{display:'none'}}>
<TextInput type="text" onChange={props.nsFn.placementGroupUpdate.bind(self, i, 'availability-zone')} />
<span onClick={hideInput} className="removeInput"><img src={imgRemove} />Remove</span>
</div>
</label>
<label>
<span> Affinity/Anti-affinity Server Group<span onClick={showInput} className="addInput"><img src={imgAdd} />Add</span></span>
<div style={{display:'none'}}>
<TextInput type="text" onChange={props.nsFn.placementGroupUpdate.bind(self, i, 'server-group')} />
<span onClick={hideInput} className="removeInput"><img src={imgRemove} />Remove</span>
</div>
</label>
<div className="host-aggregate">
<label>
<span> Host Aggregates <span onClick={props.nsFn.addHostAggregate.bind(self, i)} className="addInput" ><img src={imgAdd} />Add</span></span>
{
input['host-aggregate'].length > 0 ?
input['host-aggregate'].map((h,j) => {
let key = h.key || '';
let value = h.value || '';
return (
<div className="input_group" key={j}>
<TextInput type="text" onChange={props.nsFn.hostAggregateUpdate.bind(self, i, j, 'key')} placeholder="KEY" value={key} />
<TextInput type="text" onChange={props.nsFn.hostAggregateUpdate.bind(self, i, j, 'value')} placeholder="VALUE" value={value} />
<span onClick={props.nsFn.removeHostAggregate.bind(self, i, j)} className="removeInput"><img src={imgRemove} />Remove</span>
</div>
)
}) : ''
}
</label>
</div>
</div>
);
})
}
</div>
);
}
}
vnfPlacementGroupsHTML = (props) => {
let vnfPlacementGroups = props.vnfPlacementGroups;
let displayPlacementGroups = props.displayPlacementGroups;
if (vnfPlacementGroups && vnfPlacementGroups.length > 0 && displayPlacementGroups) {
return vnfPlacementGroups.map(function(input, i) {
return (
<div className="configure-nsd_section" key={i}>
<h3 className="launchpadCard_title">{input['vnf-name']} VNF Placement Group</h3>
<div className="configure-nsd_section-info">
<div className="placementGroup_description">
<div className="placementGroup_description-name">
<strong>{input.name}</strong> contains: {
input['member-vdus'].map((m,i) => {
let s = m['member-vdu-ref'];
if(i>0) {
s = ', ' + m['member-vdu-ref']
};
return s;
})
}
</div>
<div><em>{input.requirement}</em></div>
<div><strong>Strategy</strong>: {input.strategy}</div>
</div>
<label>
<span> Availability Zone <span onClick={showInput} className="addInput"><img src={imgAdd} />Add</span></span>
<div style={{display:'none'}}>
<TextInput type="text" onChange={props.vnfFn.placementGroupUpdate.bind(self, i, 'availability-zone')} />
<span onClick={hideInput} className="removeInput"><img src={imgRemove} />Remove</span>
</div>
</label>
<label>
<span> Affinity/Anti-affinity Server Group<span onClick={showInput} className="addInput"><img src={imgAdd} />Add</span></span>
<div style={{display:'none'}}>
<TextInput type="text" onChange={props.vnfFn.placementGroupUpdate.bind(self, i, 'server-group')} />
<span onClick={hideInput} className="removeInput"><img src={imgRemove} />Remove</span>
</div>
</label>
<div className="host-aggregate">
<label>
<span> Host Aggregates <span onClick={props.vnfFn.addHostAggregate.bind(self, i)} className="addInput"><img src={imgAdd} />Add</span></span>
{
input['host-aggregate'].length > 0 ?
input['host-aggregate'].map((h,j) => {
let key = h.key || '';
let value = h.value || '';
return (
<div className="input_group" key={j}>
<TextInput type="text" onChange={props.vnfFn.hostAggregateUpdate.bind(self, i, j, 'key')} placeholder="KEY" value={key} />
<TextInput type="text" onChange={props.vnfFn.hostAggregateUpdate.bind(self, i, j, 'value')} placeholder="VALUE" value={value} />
<span onClick={props.vnfFn.removeHostAggregate.bind(self, i, j)} className="removeInput"><img src={imgRemove} />Remove</span>
</div>
)
}) : ''
}
</label>
</div>
</div>
</div>
);
});
}
}
vldsHTML = (props) => {
let self = this;
let ipProfileList = props.ipProfileList;
let vlds = props.vlds;
return vlds && (
<div className="configure-nsd_section">
<h3 className="launchpadCard_title">VLDs</h3>
{vlds && vlds.map(function(v, i) {
let currentType = v.type;
let isVIM = (currentType == 'vim-network-name');
let isUnknown = (currentType == 'none') || ((currentType != 'vim-network-name') && (currentType != 'ip-profile-ref'));
return (
<div key={self.props.nsd.id + '-' + i} className="inputControls">
<h4 className="inputControls-title">VLD: {v['short-name'] ? v['short-name'] : v['name']}</h4>
<label><span>Specify VLD Parameters</span></label>
<div className="inputControls-radioGroup">
<label className="inputControls-radio" style={{display: ipProfileList ? 'flex' : 'none'}}>
<input type="radio" name={'vld-' + i } onChange={self.props.vldFn.updateType(i)} checked={!isVIM && !isUnknown} value='ip-profile-ref' />
IP Profile
</label>
<label className="inputControls-radio">
<input type="radio" name={'vld-' + i } onChange={self.props.vldFn.updateType(i)} checked={isVIM && !isUnknown} value='vim-network-name' />
VIM Network Name
</label>
<label className="inputControls-radio">
<input type="radio" name={'vld-' + i } onChange={self.props.vldFn.updateType(i)} checked={isUnknown} value='none' />
None
</label>
</div>
{
isUnknown ? null : isVIM ?
<div>
<TextInput label="Network Name" onChange={self.props.vldFn.updateValue(i, currentType)} value={v[currentType]} />
{
v['mgmt-network'].toUpperCase() == "TRUE" ?
<TextInput label="IPV4 NAT POOL NAME" placeholder={self.props.dataCenterID} onChange={self.props.vldFn.updateValue(i, 'ipv4-nat-pool-name')} value={v['ipv4-nat-pool-name']} />
: null
}
</div>
: <div>
<SelectOption
label="IP PROFILE NAME"
options={ipProfileList && ipProfileList.map(function(ip) {
return {
label: ip.name,
value: ip.name
}
})}
initial={
v['ip-profile-ref'] ? false : true
}
defaultValue={v['ip-profile-ref']}
onChange={self.props.vldFn.updateValue(i, currentType)}>
</SelectOption>
</div>
}
</div>
)
})}
</div>
);
}
ipProfilesHTML = (props) => {
let vldHasIPprofile = false;
props.vlds && props.vlds.map(function(v){
if(v.type == 'ip-profile-ref') {
vldHasIPprofile = true;
}
})
let ipProfileList = props.ipProfileList;
return ipProfileList && vldHasIPprofile &&
(
<div className="configure-nsd_section">
<h3 className="launchpadCard_title">IP Profiles</h3>
{
//IP Config
ipProfileList && ipProfileList.map(function(ip, j) {
let ipl = ip['ip-profile-params'];
return (
<div className="inputControls" key={j}>
<div className="inputControls-title" >
{ip.name}
</div>
<div className="inputControls-radioGroup">
<label className="inputControls-radio">
<input type="radio" name={'ip-profile-' + j } onChange={props.ipProfileFn.updateVersion(j)} checked={ipl['ip-version'] == 'ipv4'} value='ipv4' />
ipv4
</label>
<label className="inputControls-radio">
<input type="radio" name={'ip-profile-' + j } onChange={props.ipProfileFn.updateVersion(j)} checked={ipl['ip-version'] == 'ipv6'} value='ipv6' />
ipv6
</label>
<label className="inputControls-radio">
<input type="radio" name={'ip-profile-' + j } onChange={props.ipProfileFn.updateVersion(j)} checked={ipl['ip-version'] == 'unknown'} value='unknown' />
unknown
</label>
</div>
<TextInput
label="subnet address"
onChange={props.ipProfileFn.updateProfile(j, 'subnet-address')}
value={ipl['subnet-address']}
/>
<TextInput
label="gateway address"
onChange={props.ipProfileFn.updateProfile(j, 'gateway-address')}
value={ipl['gateway-address']}
/>
<TextInput
label="security group"
onChange={props.ipProfileFn.updateProfile(j, 'security-group')}
value={ipl['security-group']}
/>
<TextInput
label="subnet prefix pool"
onChange={props.ipProfileFn.updateProfile(j, 'subnet-prefix-pool')}
value={ipl['subnet-prefix-pool']}
/>
<label>
<div style={{display:'flex'}}>
DNS SERVERS <span onClick={props.dnsFn.addDNS(j)} className="addInput"><img src={imgAdd} />Add</span>
</div>
{
ipl['dns-server'] && ipl['dns-server'].map(function(dns, k) {
return (
<div key={k} style={{display:'flex'}}>
<TextInput
onChange={props.dnsFn.updateDNS(j,k)}
value={ipl['dns-server'][k].address}
/>
<span onClick={props.dnsFn.removeDNS(j,k)} className="removeInput">
<img src={imgRemove} />Remove</span>
</div>
)
})
}
</label>
<div className="inputControls-radioGroup">
<label className="inputControls-radio">
DHCP ENABLED
<input type="radio"
name={'ip-profile-dhcp' + j }
onChange={props.ipProfileFn.updateDHCP(j, 'enabled')}
checked={ipl.hasOwnProperty('dhcp-params') && ipl['dhcp-params'].enabled}
value={true} />
YES
</label>
<label className="inputControls-radio">
<input type="radio"
name={'ip-profile-dhcp' + j }
onChange={props.ipProfileFn.updateDHCP(j, 'enabled')}
checked={!ipl.hasOwnProperty('dhcp-params') || !ipl['dhcp-params'].enabled}
value={false} />
NO
</label>
</div>
{
(ipl['dhcp-params'] && ipl['dhcp-params'].enabled) ? dhcpHTML(props, ipl, j) : null
}
</div>
)
})
}
</div>);
function dhcpHTML(props, ipl, j){
return (<div>
<TextInput
label="DHCP Start Address"
onChange={props.ipProfileFn.updateDHCP(j, 'start-address')}
value={ipl['dhcp-params'] && ipl['dhcp-params']['start-address']}
/>
<TextInput
label="DHCP Count"
onChange={props.ipProfileFn.updateDHCP(j, 'count')}
value={ipl['dhcp-params'] && ipl['dhcp-params']['count']}
/>
</div>
);
}
}
sshKeysHTML = (props) => {
let sshKeysList = props.sshKeysList;
let sshKeysRef = props.sshKeysRef;
if(sshKeysList && sshKeysList.length > 0) {
return (
<div className="configure-nsd_section">
<h3 className="launchpadCard_title">SSH Authorized Keys</h3>
{
sshKeysRef.map(function(ref, i) {
let keyref = JSON.stringify(ref)
return (
<div key={keyref.name + '-' + i} className="inputControls inputControls-sshkeys">
<label>
<div>
<SelectOption
label="Key Pair"
options={sshKeysList && sshKeysList.map(function(k) {
return {
label: k.name,
value: k
}
})}
ref="keyPairSelection"
initial={false}
defaultValue={keyref.name || sshKeysList[0].name}
onChange={props.sshFn.updateKeyRef(i)}>
</SelectOption>
</div>
</label>
<label>
<span onClick={props.sshFn.updateKeyRef(i, true)} className="removeInput">
<img src={imgRemove} />
Remove
</span>
</label>
</div>
)
})
}
<div className="inputControls inputControls-sshkeys ">
<label style={{display: 'flex', 'flexDirection': 'row'}}>
SSH KEY PAIR
<span onClick={props.sshFn.updateKeyRef().bind(null, {target:{value: JSON.stringify(sshKeysList[0])}})} className="addInput">
<img src={imgAdd} />
ADD
</span>
</label>
</div>
</div>
);
}
}
usersHTML = (props) => {
let usersFn = props.usersFn;
let sshKeysList = props.sshKeysList;
let usersList = props.usersList && props.usersList.map(function(u, i) {
let sshKeysRef = u['ssh-authorized-key'];
return (
<div className="input_group input_group-users" key={i}>
<div className="inputControls">
<div style={{fontWeight: 'bold', display: 'flex'}}>USER <span onClick={usersFn.remove(i)} className="removeInput"><img src={imgRemove} />Remove</span></div>
<TextInput onChange={usersFn.update(i, 'name')} label="USERNAME" value={i.name} />
<TextInput onChange={usersFn.update(i, 'user-info')} label="REAL NAME" value={i.gecos} />
{
sshKeysRef.map(function(ref, j) {
let keyref = JSON.stringify(ref)
return (
<div key={keyref.name + '-' + i + '-' + j} className="inputControls inputControls-sshkeys">
<label>
<div>
<SelectOption
label="Key Pair"
options={sshKeysList && sshKeysList.map(function(k) {
return {
label: k.name,
value: k
}
})}
ref="keyPairSelection"
initial={false}
defaultValue={ref}
onChange={usersFn.updateSSHkeyRef(i, j)}>
</SelectOption>
</div>
</label>
{
sshKeysRef.length > 0 ?
<label>
<span onClick={usersFn.updateSSHkeyRef(i, j, true)} className="removeInput">
<img src={imgRemove} />
Remove
</span>
</label>
: null
}
</div>
)
})
}
<div className="inputControls inputControls-sshkeys ">
<label style={{display: 'flex', 'flexDirection': 'row', 'alignItems': 'center'}}>
SSH KEY PAIR
<span onClick={usersFn.updateSSHkeyRef(i).bind(null, {target:{value: JSON.stringify(sshKeysList[0])}})} className="addInput">
<img src={imgAdd} />
ADD
</span>
</label>
</div>
</div>
</div>
)
});
return (
<div className="configure-nsd_section">
<h3 className="launchpadCard_title">USERS</h3>
{usersList}
<div className="inputControls inputControls-sshkeys inputControls-addUser ">
<span onClick={usersFn.add(sshKeysList)} className="addInput">
<img src={imgAdd} />
ADD USER
</span>
</div>
</div>
)
}
render() {
const props = this.props;
let html;
let self = this;
html = (
<div className="instantiateInputParams">
{
//NS NAMEA AND CLOUD
this.nsConfigHTML(props)
}
{
//VNF VIM ACCOUNTS
this.vnfCloudAccountsHTML(props)
}
{
//INPUT PARAMETERS
this.inputParametersHTML(props)
}
{
//VNF INPUT PARAMETERS
this.vnfInputParametersHTML(props)
}
{
true ?
// self.props.selectedResourceOrchestrator['ro-account-type'] == 'rift-ro' ?
//NS PLACEMENTGROUPS
this.nsPlacementGroupsHTML(props) : null
}
{
true ?
// self.props.selectedResourceOrchestrator['ro-account-type'] == 'rift-ro' ?
//VNF PLACEMENTGROUPS
this.vnfPlacementGroupsHTML(props) : null
}
{
//VLD CONFIGURATION
this.vldsHTML(props)
}
{
//IP PROFILE CONFIGURATION
this.ipProfilesHTML(props)
}
{
//SSH KEY ASSIGNMENTS
this.sshKeysHTML(props)
}
{
//USER MANAGEMENT
this.usersHTML(props)
}
</div>
)
return html;
}
}
function showInput(e){
let target = e.target;
if(target.parentElement.classList.contains("addInput")) {
target = target.parentElement;
}
target.style.display = 'none';
target.parentElement.nextElementSibling.style.display = 'flex';
// e.target.parentElement.nextElementSibling.children[1].style.display = 'initial';
}
function hideInput(e){
let target = e.target;
if(target.parentElement.classList.contains("removeInput")) {
target = target.parentElement;
}
target.parentElement.style.display = 'none';
target.parentElement.previousElementSibling.children[1].style.display = 'inline';
target.previousSibling.value = '';
}
function addDNS(){}
function removeDNS(){}
function constructROOptions(resourceOrchestrators){
let ROOptions = resourceOrchestrators && resourceOrchestrators.map(function(ro, index) {
return {
label: ro.name,
value: ro
}
});
return ROOptions;
}
function constructCloudAccountOptions(cloudAccounts){
let CloudAccountOptions = cloudAccounts && cloudAccounts.map(function(ca, index) {
return {
label: ca.name,
value: ca
}
});
return CloudAccountOptions;
}
function constructDataCenterOptions(dataCenters){
let DataCenterOptions = dataCenters && dataCenters.map(function(dc, index) {
return {
label: dc.name,
value: dc.name
}
});
return DataCenterOptions;
}
function dataCentersHTML(dataCenters, onChange, initial) {
//Build DataCenter options
//Relook at this, why is it an object?
let DataCenterOptions = [];
DataCenterOptions = dataCenters && dataCenters.map(function(dc, index) {
return {
label: dc.name,
value: dc.uuid
}
});
if (dataCenters && dataCenters.length > 0) {
return (
<label>Data Center
<SelectOption initial={!!initial} options={DataCenterOptions} onChange={onChange} />
</label>
)
}
}
function updateNewSshKeyRefSelection(e) {
this.setState({
newRefSelection: e.target.value
})
}
function resetRef() {
this.setState({
newRefSelection: null
})
}
InstantiateInputParams.defaultProps = {
data: [],
sshKeysList: [],
sshKeysRef: [],
users: {}
}