Rift.IO OSM R1 Initial Submission
[osm/UI.git] / skyquake / plugins / launchpad / src / instantiate / instantiateInputParams.jsx
diff --git a/skyquake/plugins/launchpad/src/instantiate/instantiateInputParams.jsx b/skyquake/plugins/launchpad/src/instantiate/instantiateInputParams.jsx
new file mode 100644 (file)
index 0000000..00397ed
--- /dev/null
@@ -0,0 +1,603 @@
+
+/*
+ * 
+ *   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="inputControls">
+            <TextInput label="Instance Name" type="text" pattern="^[a-zA-Z0-9_]*$" style={{textAlign:'left'}} onChange={props.updateName} value={props.name}/>
+          <label>Select VIM Account
+            <SelectOption options={constructCloudAccountOptions(props.cloudAccounts)} onChange={props.nsFn.updateSelectedCloudAccount} />
+          </label>
+          {
+            isOpenMano(props.selectedCloudAccount) ? this.dataCentersHTML(props.dataCenters[selectedCloudAccount.name], props.nsFn.updateSelectedDataCenter) : null
+          }
+        </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.name}</h4>
+                      <label>Select VIM Account
+                        <SelectOption options={constructCloudAccountOptions(props.cloudAccounts)} initial={true} onChange={props.vnfFn.updateSelectedCloudAccount.bind(v['member-vnf-index'])} defaultValue={defaultValue} />
+                      </label>
+                      {
+                        isOpenMano(defaultValue) ? dataCentersHTML(dataCenters[defaultValue.account.name], props.vnfFn.updateSelectedDataCenter(v['member-vnf-index'])) : null
+                      }
+                      {
+                        (props.configAgentAccounts && props.configAgentAccounts.length > 0) ?
+                        <label>Select 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>
+    )
+  }
+  inputParametersHTML = (props) => {
+    let inputParameters = props.inputParameters;
+    return inputParameters && inputParameters.map(function(input, i) {
+        return (
+                <div className="configure-nsd_section" key={i}>
+                  <h3 className="launchpadCard_title">Input Parameters</h3>
+                  <div className="inputControls">
+                      <TextInput label={ input.label || input.xpath } type="text" onChange={props.updateInputParam.bind(self, i)} />
+                  </div>
+                </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.placementGroupUpdate.bind(self, i, j, 'key')} placeholder="KEY" value={key} />
+                                    <TextInput type="text" onChange={props.nsFn.placementGroupUpdate.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 == 'unknown') || ((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']}</h4>
+                        <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='unknown' />
+                            Unknown
+                          </label>
+                        </div>
+                          {
+                            isUnknown ? null : isVIM ?
+                            <TextInput label="Network Name" onChange={self.props.vldFn.updateValue(i, currentType)} value={v[currentType]} /> :
+                            <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 ipProfileList = props.ipProfileList;
+    return ipProfileList &&
+      (
+      <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']}
+                    />
+                    <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.ipProfileFn.updateProfile(j,k)}
+                                  value={ipl['dns-server'][k]}
+                                  />
+                              <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="DCHP Start Address"
+                    onChange={props.ipProfileFn.updateDHCP(j, 'start-address')}
+                    value={ipl['dhcp-params'] && ipl['dhcp-params']['start-address']}
+                    />
+                  <TextInput
+                    label="DCHP 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) {
+                return (
+                  <div key={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={sshKeysList[0].name}
+                        onChange={self.props.updateSshKeyRef(i)}>
+                      </SelectOption>
+                      </div>
+                    </label>
+                    <label>
+                      <span onClick={self.props.updateSshKeyRef(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={self.props.updateSshKeyRef().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 usersList = props.usersList && props.usersList.map(function(u, i) {
+      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, 'gecos')} label="REAL NAME" value={i.gecos} />
+            <TextInput onChange={usersFn.update(i, 'passwd')} type="password" label="PASSWORD" value={i.passwd} />
+          </div>
+        </div>
+      )
+    });
+    return (
+      <div className="configure-nsd_section">
+        <h3 className="launchpadCard_title">USERS</h3>
+        {usersList}
+        <div className="inputControls inputControls-sshkeys ">
+            <span onClick={usersFn.add} className="addInput">
+              <img src={imgAdd} onClick={usersFn.add} />
+              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)
+          }
+          {
+            //NS PLACEMENTGROUPS
+            this.nsPlacementGroupsHTML(props)
+          }
+          {
+            //VNF PLACEMENTGROUPS
+            this.vnfPlacementGroupsHTML(props)
+          }
+          {
+            //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 constructCloudAccountOptions(cloudAccounts){
+  let CloudAccountOptions = cloudAccounts && cloudAccounts.map(function(ca, index) {
+    return {
+      label: ca.name,
+      value: ca
+    }
+  });
+  return CloudAccountOptions;
+}
+function dataCentersHTML(state, onChange) {
+  //Build DataCenter options
+  //Relook at this, why is it an object?
+  let dataCenters = state.dataCenters || [];
+  let DataCenterOptions = {};
+  if(dataCenters){
+    for (let d in dataCenters) {
+      DataCenterOptions[d] = dataCenters[d].map(function(dc, index) {
+        return {
+          label: dc.name,
+          value: dc.uuid
+        }
+      });
+    }
+  }
+  if (dataCenters.length > 0) {
+    return (
+      <label>Select Data Center
+        <SelectOption options={DataCenterOptions} onChange={onChange} />
+      </label>
+    )
+  }
+}
+function isOpenMano(account) {
+  if (account) {
+    let a = account;
+    if (a.constructor.name == 'String') {
+      a = JSON.parse(a);
+    }
+    if(a.hasOwnProperty('account')) {
+      a = a.account;
+    }
+    return a['account-type'] == 'openmano';
+  } else {
+    return false;
+  }
+}
+function updateNewSshKeyRefSelection(e) {
+  this.setState({
+    newRefSelection: e.target.value
+  })
+}
+function resetRef() {
+    this.setState({
+    newRefSelection: null
+  })
+}
+InstantiateInputParams.defaultProps = {
+  data: [],
+  sshKeysList: [],
+  sshKeysRef: [],
+  users: {}
+}