From abac8ca7ee43084fdd21d0ad6746dc730f24e40c Mon Sep 17 00:00:00 2001 From: Siva Kumar Bavanasi Date: Tue, 14 Feb 2017 13:47:53 +0530 Subject: [PATCH] Changes to support flat subnet feature in web-ui 1)Added subnet method and required changes in IPAM page 2)Added address allocation mode and required changes in network page Closes-bug: #1669406 Change-Id: I6491829632fdb7a20c6ef1084f1bc9a76ec3d9f6 --- webroot/common/api/jsonDiff.helper.js | 3 +- webroot/common/ui/css/contrail.controller.css | 8 +- webroot/common/ui/js/controller.constants.js | 1 + .../ipam/ui/js/models/ipamCfgModel.js | 242 +++++++++++++++++- .../ipam/ui/js/views/ipamCfgEditView.js | 187 ++++++++++++++ .../ipam/ui/js/views/ipamCfgFormatters.js | 193 +++++++++++++- .../ipam/ui/js/views/ipamCfgGridView.js | 22 +- .../networking/networks/api/vnconfig.api.js | 1 - .../networks/ui/js/models/vnCfgModel.js | 60 ++++- .../networks/ui/js/views/vnCfgEditView.js | 72 +++++- .../networks/ui/js/views/vnCfgFormatters.js | 200 +++++++++++++-- .../networks/ui/js/views/vnCfgGridView.js | 44 +++- 12 files changed, 971 insertions(+), 62 deletions(-) diff --git a/webroot/common/api/jsonDiff.helper.js b/webroot/common/api/jsonDiff.helper.js index c7b240b55..5cd520743 100644 --- a/webroot/common/api/jsonDiff.helper.js +++ b/webroot/common/api/jsonDiff.helper.js @@ -49,6 +49,7 @@ var configJsonModifyObj = { 'flood_unknown_unicast', 'multi_policy_service_chains_enabled', 'route_table_refs', 'provider_properties', 'ecmp_hashing_include_fields', + 'address_allocation_mode', 'qos_config_refs', 'perms2', 'pbb_evpn_enable', 'pbb_etree_enable', 'layer2_control_word', 'mac_learning_enabled', @@ -63,7 +64,7 @@ var configJsonModifyObj = { }, 'network-ipam': { 'isConfig': true, - 'optFields': ['network_ipam_mgmt', 'virtual_DNS_refs', 'perms2'], + 'optFields': ['network_ipam_mgmt', 'virtual_DNS_refs', 'perms2', 'ipam_subnets'], 'mandateFields': ['fq_name', 'uuid', 'display_name'] }, 'virtual-machine-interface': { diff --git a/webroot/common/ui/css/contrail.controller.css b/webroot/common/ui/css/contrail.controller.css index fe2546552..0710ab14c 100644 --- a/webroot/common/ui/css/contrail.controller.css +++ b/webroot/common/ui/css/contrail.controller.css @@ -275,7 +275,7 @@ div.vis-network canvas{ border-top:none;} #peer_selection .item-list table tr:first-child td{ background-color:gray;} -#bgp-grid .value th, #config-vn-list .value th, #service-instances-grid .value th, #global-bgp-options-grid th{ +#bgp-grid .value th, #config-vn-list .value th, #config-ipam-list .value th, #service-instances-grid .value th, #global-bgp-options-grid th{ font-weight:600; border-bottom:#777 solid 1px; padding-bottom:2px;} @@ -287,7 +287,7 @@ div.vis-network canvas{ #bgp-grid .value tr td{ border-bottom:#f5f5f5 solid 1px; vertical-align:top;} -#config-vn-list .value td, #service-instances-grid .value td{ +#config-vn-list .value td, #config-ipam-list .value td, #service-instances-grid .value td{ vertical-align:top;} #service-instances-grid .value td a{ color:#3182bd; @@ -311,14 +311,14 @@ div.vis-network canvas{ width:250px; padding-top:0px;} #prefix_limit{width:213px} -#bgp-grid ul.item-list .key, #config-vn-list ul.item-list .key, #service-instances-grid ul.item-list .key{ +#bgp-grid ul.item-list .key, #config-vn-list ul.item-list .key, #config-ipam-list ul.item-list .key, #service-instances-grid ul.item-list .key{ width:23.08% !important; } #bgp-grid ul.item-list .value, #service-instances-grid ul.item-list .value{ width:57.26% !important; vertical-align:top; } -#config-vn-list ul.item-list .value{ +#config-vn-list ul.item-list .value, #config-ipam-list ul.item-list .value{ width:76.26%!important; vertical-align:top;} div#peer_selection_section { diff --git a/webroot/common/ui/js/controller.constants.js b/webroot/common/ui/js/controller.constants.js index a71009df2..fc155d5d0 100644 --- a/webroot/common/ui/js/controller.constants.js +++ b/webroot/common/ui/js/controller.constants.js @@ -747,6 +747,7 @@ define([ // IPAM Config Constants this.URL_CFG_IPAM_DETAILS = '/api/tenants/config/ipam-details'; + this.USER_DEFINED_SUBNET = 'user-defined-subnet'; // FIP Config Constants this.URL_CFG_FIP_DETAILS = diff --git a/webroot/config/networking/ipam/ui/js/models/ipamCfgModel.js b/webroot/config/networking/ipam/ui/js/models/ipamCfgModel.js index 027928c8a..d82e70ce1 100644 --- a/webroot/config/networking/ipam/ui/js/models/ipamCfgModel.js +++ b/webroot/config/networking/ipam/ui/js/models/ipamCfgModel.js @@ -6,9 +6,15 @@ define([ 'underscore', 'contrail-config-model', 'config/networking/ipam/ui/js/models/ipamTenantDNSModel', - 'config/networking/ipam/ui/js/views/ipamCfgFormatters' -], function (_, ContrailConfigModel, IpamTenantDNSModel, IpamCfgFormatters) { - var formatipamCfg = new IpamCfgFormatters(); + 'config/networking/ipam/ui/js/views/ipamCfgFormatters', + 'config/networking/networks/ui/js/models/subnetModel', + 'config/networking/networks/ui/js/models/hostRouteModel', + 'config/networking/networks/ui/js/models/subnetDNSModel', + 'config/networking/networks/ui/js/views/vnCfgFormatters' +], function (_, ContrailConfigModel, IpamTenantDNSModel, IpamCfgFormatters, + SubnetModel, HostRouteModel, SubnetDNSModel, VNCfgFormatters) { + var formatipamCfg = new IpamCfgFormatters(), + formatVNCfg = new VNCfgFormatters(); var ipamCfgModel = ContrailConfigModel.extend({ @@ -35,7 +41,12 @@ define([ 'ntp_server': null, }, 'tenant_dns_server':[], - 'user_created_dns_method': 'default-dns-server' + 'user_created_dns_method': 'default-dns-server', + 'ipam_subnet_method': 'user-defined-subnet', + 'ipam_subnets':{ + 'subnets': [] + }, + 'user_created_ipam_subnets': [] }, formatModelConfig: function (modelConfig) { @@ -91,9 +102,222 @@ define([ formatipamCfg.getDhcpOptions(dhcpList, 15).trim(); //permissions this.formatRBACPermsModelConfig(modelConfig); + //subnets + this.readSubnetList(modelConfig); return modelConfig; }, + readSubnetList: function (modelConfig) { + var self = this; + var subnetModels = [], subnetList = []; + subnetList = getValueByJsonPath(modelConfig, + "ipam_subnets;subnets", []), + subnetLen = subnetList.length; + if(subnetLen > 0) { + for(var i = 0; i < subnetLen; i++) { + var subnetObj = subnetList[i], + subnetModel, allocPools, allocPoolStr = '', + cidr = subnetObj.subnet.ip_prefix + '/' + + subnetObj.subnet.ip_prefix_len; + subnetObj["user_created_cidr"] = cidr; + allocPools = getValueByJsonPath(subnetObj, + "allocation_pools", [], false); + allocPools.every(function(pool) { + allocPoolStr += pool.start + "-" + pool.end + "\n"; + return true; + }); + subnetObj['allocation_pools'] = allocPoolStr.trim(); + subnetObj['user_created_enable_gateway'] = + getValueByJsonPath(subnetObj, 'default_gateway', ""); + subnetObj['user_created_enable_gateway'] = + subnetObj['user_created_enable_gateway'].length && + subnetObj['user_created_enable_gateway'].indexOf("0.0.0.0") + == -1 ? true : false; + subnetObj['user_created_enable_dns'] = + formatVNCfg.getSubnetDNSStatus(subnetObj); + subnetObj['disable'] = true; + //below dummy entry is required to use existing subnet model + subnetObj['user_created_ipam_fqn'] = 'dummy'; + subnetModel = new SubnetModel(subnetObj); + subnetModels.push(subnetModel); + } + } else if (isVCenter()) { + var subnetModel = new SubnetModel(); + self.setSubnetChangeEvent(subnetModel); + subnetModels.push(subnetModel); + } + + modelConfig['user_created_ipam_subnets'] = + new Backbone.Collection(subnetModels); + }, + + setSubnetGateway: function (self, model, text) { + var subnets = self.model().attributes['user_created_ipam_subnets'].toJSON(); + var cid = model.cid; + subnets.every(function(subnet) { + if (subnet.disable() == true || subnet.model().cid != cid) { + return true; + } + if (subnet.user_created_enable_gateway() == true) { + var gw = genarateGateway(text, "start"); + gw != false ? subnet.default_gateway(gw) : subnet.default_gateway(''); + } else { + subnet.default_gateway('0.0.0.0'); + } + return true; + }); + }, + + toggleSubnetGateway: function (self, model, text) { + var subnets = self.model().attributes['user_created_ipam_subnets'].toJSON(); + var cid = model.cid; + subnets.every(function(subnet) { + if (subnet.disable() == true || subnet.model().cid != cid) { + return true; + } + if (text == true) { + var gw = false; + if (subnet.user_created_cidr() != null) { + gw = genarateGateway(subnet.user_created_cidr(), "start"); + } + gw != false ? subnet.default_gateway(gw) : subnet.default_gateway(''); + } else { + subnet.default_gateway('0.0.0.0'); + } + return true; + }); + }, + + setSubnetChangeEvent: function (subnetModel) { + var self = this; + subnetModel.__kb.view_model.model().on('change:user_created_cidr', + function(model, text){ + self.setSubnetGateway(self, model, text); + }); + subnetModel.__kb.view_model.model().on('change:user_created_enable_gateway', + function(model, text){ + self.toggleSubnetGateway(self, model, text); + }); + }, + + addSubnet: function() { + var self = this; + var subnet = this.model().attributes['user_created_ipam_subnets'], + subnetModel = new SubnetModel({user_created_ipam_fqn: 'dummy'}); + self.setSubnetChangeEvent(subnetModel); + subnet.add([subnetModel]); + }, + + deleteSubnet: function(data, kbSubnet) { + var subnetCollection = data.model().collection, + subnet = kbSubnet.model(); + + subnetCollection.remove(subnet); + }, + + getAllocPools: function(subnetObj) { + var allocPools = [], retAllocPool = []; + if ('allocation_pools' in subnetObj && + subnetObj.allocation_pools.length) { + allocPools = subnetObj.allocation_pools.split('\n'); + } + allocPools.every(function(pool) { + var poolObj = pool.split('-'); + if (poolObj.length == 2) { + retAllocPool.push({'start': poolObj[0].trim(), + 'end': poolObj[1].trim()}); + } + return true; + }); + return retAllocPool; + }, + + setDHCPOptionList: function(subnet, dhcpOption) { + if (typeof subnet.dhcp_option_list == "function") { + subnet.dhcp_option_list().dhcp_option = dhcpOption; + } else { + subnet['dhcp_option_list'] = {}; + subnet['dhcp_option_list']['dhcp_option'] = dhcpOption; + } + }, + + getSubnetList: function(attr) { + var subnetCollection = attr.user_created_ipam_subnets.toJSON(), + subnetArray = [], dhcpOption; + var dnsServers = []; + var hostRoutes = []; + var disabledDNS = [{'dhcp_option_name': '6', 'dhcp_option_value' : '0.0.0.0'}]; + for(var i = 0; i < subnetCollection.length; i++) { + var subnet = $.extend(true, {}, subnetCollection[i].model().attributes); + + if (dnsServers.length && subnet.user_created_enable_dns) { + this.setDHCPOptionList(subnet, dnsServers); + } else if(!dnsServers.length && subnet.user_created_enable_dns){ + this.setDHCPOptionList(subnet, []); + } else if (!(subnet.user_created_enable_dns)) { + this.setDHCPOptionList(subnet, disabledDNS); + } + if (hostRoutes.length) { + if (typeof subnet.host_routes == "function") { + subnet.host_routes().route = hostRoutes + } else { + subnet['host_routes'] = {}; + subnet['host_routes']['route'] = hostRoutes; + } + } + if (subnet.user_created_enable_gateway == false) { + subnet.default_gateway = '0.0.0.0'; + } else if (subnet.default_gateway == null) { + var defGw = genarateGateway(subnet.user_created_cidr, "start"); + //funny api + if (defGw != false) { + subnet.default_gateway = defGw; + } + } + var cidr = subnet.user_created_cidr; + if (subnet.subnet.ip_prefix == null && cidr != null && + cidr.split("/").length == 2) { + subnet.subnet.ip_prefix = cidr.split('/')[0]; + subnet.subnet.ip_prefix_len = Number(cidr.split('/')[1]); + } + if (subnet.subnet_uuid == null) { + subnet.subnet_uuid = UUIDjs.create()['hex']; + } + if (subnet.subnet_name == null) { + subnet.subnet_name = subnet.subnet_uuid; + } + + var allocPool = this.getAllocPools(subnet); + subnet.allocation_pools = allocPool; + + if (allocPool.length == 0) { + delete subnet['allocation_pools']; + } + if (hostRoutes.length == 0) { + delete subnet['host_routes']; + } + dhcpOption = getValueByJsonPath(subnet, + "dhcp_option_list;dhcp_option", []); + if(dhcpOption.length === 0) { + delete subnet['dhcp_option_list']; + } + + delete subnet['errors']; + delete subnet['locks']; + delete subnet['disable']; + delete subnet['user_created_enable_dns']; + delete subnet['user_created_enable_gateway']; + delete subnet['user_created_ipam_fqn']; + delete subnet['user_created_cidr']; + subnetArray.push(subnet); + } + if(attr.ipam_subnet_method === ctwc.USER_DEFINED_SUBNET) { + delete attr['ipam_subnets']; + } else { + attr['ipam_subnets']['subnets'] = subnetArray; + } + }, + addTenantDNS: function() { var dns = this.model().attributes['tenant_dns_server'], newDNS = new IpamTenantDNSModel({'ip_addr': ""}); @@ -163,6 +387,11 @@ define([ type: cowc.OBJECT_TYPE_COLLECTION, getValidation: 'ipamTenantDNSConfigValidations' }, + { + key: 'user_created_ipam_subnets', + type: cowc.OBJECT_TYPE_COLLECTION, + getValidation: 'subnetModelConfigValidations' + }, //permissions ctwu.getPermissionsValidation() ]; @@ -246,6 +475,9 @@ define([ ['dhcp_option_list']['dhcp_option'] = dhcpOptions; } + //subnets + this.getSubnetList(newipamCfgData); + //permissions this.updateRBACPermsAttrs(newipamCfgData); @@ -257,7 +489,7 @@ define([ delete newipamCfgData.href; delete newipamCfgData.parent_href; delete newipamCfgData.parent_uuid; - + delete newipamCfgData.user_created_ipam_subnets; postData['network-ipam'] = newipamCfgData; diff --git a/webroot/config/networking/ipam/ui/js/views/ipamCfgEditView.js b/webroot/config/networking/ipam/ui/js/views/ipamCfgEditView.js index 4d44fc62e..c9cd1e4c5 100644 --- a/webroot/config/networking/ipam/ui/js/views/ipamCfgEditView.js +++ b/webroot/config/networking/ipam/ui/js/views/ipamCfgEditView.js @@ -59,6 +59,8 @@ define([ document.getElementById(modalId)); kbValidation.bind(self, {collection: self.model.model().attributes.tenant_dns_server}); + kbValidation.bind(self, + {collection: self.model.model().attributes.user_created_ipam_subnets}); //permissions ctwu.bindPermissionsValidation(self); }, null, true); @@ -178,6 +180,27 @@ define([ } ] }, + { + columns: [ + { + elementId: 'ipam_subnet_method', + view: 'FormRadioButtonView', + viewConfig: { + path: 'ipam_subnet_method', + class: 'col-xs-12', + dataBindValue: 'ipam_subnet_method', + disabled: disableOnEdit, + label: 'Subnet Method', + elementConfig: { + dataObj: [{"label": "User Defined", + "value": "user-defined-subnet"}, + {"label": "Flat", "value": "flat-subnet"}] + } + } + } + ] + }, + getSubnetViewConfig(), { columns: [ { @@ -334,5 +357,169 @@ define([ return ipamCfgViewConfig; } + function getSubnetViewConfig () { + var subnetViewConfig = { + columns: [{ + elementId: 'ipamsubnets', + view: "AccordianView", + viewConfig: [{ + visible: 'ipam_subnet_method() == "flat-subnet"', + elementId: 'subnet_vcfg', + title: 'Subnets', + view: "SectionView", + viewConfig: { + rows: [{ + columns: [{ + elementId: 'user_created_ipam_subnets', + view: "FormEditableGridView", + viewConfig: { + path : 'user_created_ipam_subnets', + class: 'col-xs-12', + validation: + 'subnetModelConfigValidations', + collection: + 'user_created_ipam_subnets', + templateId: + cowc.TMP_EDITABLE_GRID_ACTION_VIEW, + gridActions: [{ + onClick: "function() {\ + if (!isVCenter())\ + addSubnet();\ + }", + buttonTitle: "" + }], + rowActions: [{ + onClick: "function() {\ + if (!isVCenter())\ + $root.addSubnet();\ + }", + iconClass: 'fa fa-plus' + }, { + onClick: "function() {\ + if (!isVCenter())\ + $root.deleteSubnet($data, this);\ + }", + iconClass: 'fa fa-minus' + }], + columns: [ + { + elementId: 'user_created_cidr', + name: + 'CIDR', + width:160, + view: "FormInputView", + viewConfig: + { + class: "", width: 160, + disabled: 'disable()', + placeholder: 'xxx.xxx.xxx.xxx/xx', + path: "user_created_cidr", + templateId: cowc.TMPL_EDITABLE_GRID_INPUT_VIEW, + dataBindValue: + 'user_created_cidr()', + } + }, + { + elementId: 'allocation_pools', + name: + 'Allocation Pools', + width:160, + view: "FormTextAreaView", + viewConfig: + { + class: "", width: 160, + placeHolder: 'start-end ...', + disabled: 'disable()', + templateId: cowc.TMPL_EDITABLE_GRID_TEXTAREA_VIEW, + path: "allocation_pools", + dataBindValue: + 'allocation_pools()', + } + }, + { + elementId: 'user_created_enable_gateway', + name: + '', + width:50, + view: "FormCheckboxView", + viewConfig: + { + disabled: 'disable()', + path: "user_created_enable_gateway", + width: 50, + templateId: cowc.TMPL_EDITABLE_GRID_CHECKBOX_VIEW, + label: "", + dataBindValue: + 'user_created_enable_gateway()', + elementConfig : { + isChecked:true + } + } + }, + { + elementId: 'default_gateway', + name: + 'Gateway', + width:160, + view: "FormInputView", + viewConfig: + { + class: "", width: 160, + disabled: 'disable()', + placeholder: 'xxx.xxx.xxx.xxx', + path: "default_gateway", + templateId: cowc.TMPL_EDITABLE_GRID_INPUT_VIEW, + dataBindValue: + 'default_gateway()', + } + }, + /*{ + elementId: 'user_created_enable_dns', + name: + 'DNS', + view: "FormCheckboxView", + viewConfig: + { + disabled: 'disable()', + path: "user_created_enable_dns", + width: 50, + label: "", + templateId: cowc.TMPL_EDITABLE_GRID_CHECKBOX_VIEW, + dataBindValue: + 'user_created_enable_dns()', + elementConfig : { + isChecked:true + } + } + },*/ + { + elementId: 'enable_dhcp', + name: + 'DHCP', + view: "FormCheckboxView", + viewConfig: + { + disabled: 'disable()', + path: "enable_dhcp", + width: 50, + label: "", + templateId: cowc.TMPL_EDITABLE_GRID_CHECKBOX_VIEW, + dataBindValue: + 'enable_dhcp()', + elementConfig : { + isChecked:true + } + } + }] + } + }] + }] + } + }] + }] + }; + return subnetViewConfig; + } + return ipamCfgEditView; }); diff --git a/webroot/config/networking/ipam/ui/js/views/ipamCfgFormatters.js b/webroot/config/networking/ipam/ui/js/views/ipamCfgFormatters.js index 6e2cbe06b..68adc48dc 100644 --- a/webroot/config/networking/ipam/ui/js/views/ipamCfgFormatters.js +++ b/webroot/config/networking/ipam/ui/js/views/ipamCfgFormatters.js @@ -4,8 +4,10 @@ */ define([ - 'underscore' -], function (_) { + 'underscore', + 'config/networking/networks/ui/js/views/vnCfgFormatters' +], function (_, VNCfgFormatters) { + var formatVNCfg = new VNCfgFormatters(); var ipamCfgFormatters = function() { var self = this; @@ -13,13 +15,33 @@ define([ * @IPBlockFormatter */ this.IPBlockFormatter = function(d, c, v, cd, dc) { - var vnObjs = - contrail.handleIfNull(dc.virtual_network_back_refs, []); + var vnObjs, length, count = 0, subnetCnt = 0, returnStr = '', + subnetMethod = getValueByJsonPath(dc, + 'ipam_subnet_method', ctwc.USER_DEFINED_SUBNET, false); - var length = vnObjs.length, count = 0, subnetCnt = 0, returnStr = ''; + if(subnetMethod !== ctwc.USER_DEFINED_SUBNET) { + var flatSubnets = getValueByJsonPath(dc, + 'ipam_subnets;subnets', [], false); + if(cd === -1){ + return this.subnetFormatter(d, c, v, cd, dc); + } + subnetCnt = flatSubnets.length; + _.each(flatSubnets, function(flatSubnet, idx) { + count++; + if (count > 2 && cd != -1) { + return true; + } + if(flatSubnet.subnet) { + var cidr = flatSubnet.subnet.ip_prefix + '/' + + flatSubnet.subnet.ip_prefix_len; + returnStr += cidr + '
'; + } + }); - if (!length) { - return returnStr; + } else { + vnObjs = getValueByJsonPath(dc, + 'virtual_network_back_refs', [], false); + length = vnObjs.length; } for(var i = 0; i < length; i++) { @@ -39,7 +61,7 @@ define([ break; } var subnet = getValueByJsonPath(vn, - 'attr;' + field + ';' + j, null, false), + 'attr;' + field + ';' + j + ';subnet', null, false), cidr; if(subnet && subnet.ip_prefix) { cidr = subnet.ip_prefix + '/' + @@ -58,7 +80,7 @@ define([ ' more)'; } - return returnStr; + return returnStr ? returnStr : '-'; }; /* @@ -166,7 +188,7 @@ define([ return "Error"; } - return ntpServer; + return ntpServer ? ntpServer : "-"; }; /* @@ -205,6 +227,157 @@ define([ return vDnsList; }; + /* + * @ipamSubnetMethodFormatter + */ + this.ipamSubnetMethodFormatter = function(d, c, v, cd, dc) { + var subnetType = getValueByJsonPath(dc, + "ipam_subnet_method", ctwc.USER_DEFINED_SUBNET, false), + returnString = ""; + if(subnetType === ctwc.USER_DEFINED_SUBNET){ + returnString = "User Defined"; + } else { + returnString = "Flat"; + } + + return returnString ? returnString : '-'; + }; + + /* + * @subnetFormatter + */ + this.subnetFormatter = function(d, c, v, cd, dc) { + var subnetType = getValueByJsonPath(dc, + "ipam_subnet_method", ctwc.USER_DEFINED_SUBNET, false), + returnString, subnetString = "", subnets; + if(subnetType === ctwc.USER_DEFINED_SUBNET){ + returnString = "-"; + } else { + returnString = ''; + subnets = getValueByJsonPath(dc, + 'ipam_subnets;subnets', [], false); + _.each(subnets, function(subnetObj){ + var cidr = getValueByJsonPath(subnetObj, + "subnet;ip_prefix", null, false); + var cidrlen = getValueByJsonPath(subnetObj, + "subnet;ip_prefix_len", null, false); + cidr = cidr ? cidr + '/' + cidrlen : "-"; + var gw = subnetObj.default_gateway ? + subnetObj.default_gateway: "-"; + var dhcp = subnetObj.enable_dhcp ? 'Enabled' : 'Disabled'; + var gwStatus = (gw == null || gw == "" || gw == "0.0.0.0") ? + 'Disabled' : gw; + + var allocPools = getValueByJsonPath(subnetObj, + "allocation_pools", []); + var allocPoolStr = "-"; + _.each(allocPools, function(pool, index) { + pool = pool.start + ' - ' + pool.end; + if(index === 0) { + allocPoolStr = pool; + } else { + allocPoolStr += "
" + pool; + } + }); + subnetString += ""; + subnetString += cidr + ""; + subnetString += gw + ""; + subnetString += dhcp + ""; + subnetString += allocPoolStr+ ""; + subnetString += ""; + }); + } + if(subnetString != ""){ + var subnetHeader = + "\ + \ + \ + \ + \ + "; + returnString += subnetHeader + subnetString; + returnString += "
CIDRGatewayDHCPAllocation Pools
"; + } else { + returnString += ""; + } + return returnString; + }; + + /* + * @subnetHostRouteFormatter + */ + this.subnetHostRouteFormatter = function(d, c, v, cd, dc) { + var subnetList = getValueByJsonPath(dc, + "ipam_subnets;subnets", []), + len = subnetList.length, returnArr = [], returnStr = ''; + + if (!len) { + return cd == -1 ? []: '-'; + } + + _.each(subnetList, function(subnetObj) { + var hostRoutes = getValueByJsonPath(subnetObj, + 'host_routes;route', []); + if (hostRoutes.length) { + returnArr.push(hostRoutes); + } + }); + + returnArr = _.flatten(returnArr); + returnArr = _.uniq(returnArr, function(hostRoute){ + return JSON.stringify(hostRoute) + }); + + if (cd == -1) { + return returnArr; + } + + $.each(returnArr, function (i, obj) { + returnStr += obj.prefix + ' ' + obj.next_hop + '
'; + }); + + return returnStr; + }; + + /* + * @subnetDNSFormatter + */ + this.subnetDNSFormatter = function(d, c, v, cd, dc) { + var subnetList = getValueByJsonPath(dc, + "ipam_subnets;subnets", []); + + var len = subnetList.length, count = 0, returnArr = []; + + if (!len) { + if (cd != -1 ) { + return '-'; + } else { + return []; + } + } + + _.each(subnetList, function(subnetObj){ + var dhcpOpts = getValueByJsonPath(subnetObj, + 'dhcp_option_list;dhcp_option', []); + if (dhcpOpts.length) { + returnArr.push(formatVNCfg. + getdhcpValuesByOption(dhcpOpts, 6).split(' ')); + } + }); + + returnArr = _.flatten(returnArr); + returnArr = _.uniq(returnArr, function(dnsObj){ + return JSON.stringify(dnsObj) + }); + if (returnArr.length) { + returnArr = _.without(returnArr, '0.0.0.0'); + returnArr = _.without(returnArr, ''); + } + + return returnArr.length ? + (cd == -1 ? [returnArr.join(' ')] : returnArr.join('
')): + (cd == -1 ? [] : '-'); + }; } return ipamCfgFormatters; }); diff --git a/webroot/config/networking/ipam/ui/js/views/ipamCfgGridView.js b/webroot/config/networking/ipam/ui/js/views/ipamCfgGridView.js index 7c6bea1c3..bbbf0692e 100644 --- a/webroot/config/networking/ipam/ui/js/views/ipamCfgGridView.js +++ b/webroot/config/networking/ipam/ui/js/views/ipamCfgGridView.js @@ -201,7 +201,7 @@ define([ templateGeneratorConfig: { columns: [ { - class: 'col-xs-6', + class: 'col-xs-8', rows: [ { title: ctwl.CFG_IPAM_TITLE_DETAILS, @@ -246,14 +246,22 @@ define([ formatter: 'dnsDomainFormatter' } }, + { + label: 'Subnet Method', + key: 'ipam_subnet_method', + templateGenerator: 'TextGenerator', + templateGeneratorConfig: { + formatter: 'IPAMSubnetMethodFormatter' + } + }, { label: 'IP Blocks', - key: 'virtual_network_back_refs', + key: 'uuid', templateGenerator: 'TextGenerator', templateGeneratorConfig: { formatter: 'IPBlockFormatter' } - }, + } ] }, //permissions @@ -281,9 +289,17 @@ define([ return formatipamCfg.dnsNTPFormatter(null, null, null, null, dc); } + this.IPAMSubnetMethodFormatter = function (v, dc) { + return formatipamCfg.ipamSubnetMethodFormatter(null, + null, null, -1, dc); + } this.IPBlockFormatter = function (v, dc) { return formatipamCfg.IPBlockFormatter(null, null, null, -1, dc); } + this.SubnetFormatter = function (v, dc) { + return formatipamCfg.subnetFormatter(null, + null, null, -1, dc); + }; return ipamCfgGridView; }); diff --git a/webroot/config/networking/networks/api/vnconfig.api.js b/webroot/config/networking/networks/api/vnconfig.api.js index 854596f25..19b16dc78 100644 --- a/webroot/config/networking/networks/api/vnconfig.api.js +++ b/webroot/config/networking/networks/api/vnconfig.api.js @@ -1025,7 +1025,6 @@ function updateBridgeDomains(vnId, vnPutData, appData, callback) return; } deleteBridgeDomainAsync(deleteBDObjList, function(deleteBDError, deleteBDData){ - console.log("deleteBDError:", deleteBDError); if(deleteBDError) { callback(deleteBDError, null); return; diff --git a/webroot/config/networking/networks/ui/js/models/vnCfgModel.js b/webroot/config/networking/networks/ui/js/models/vnCfgModel.js index 7ced4a549..d9908a5dc 100644 --- a/webroot/config/networking/networks/ui/js/models/vnCfgModel.js +++ b/webroot/config/networking/networks/ui/js/models/vnCfgModel.js @@ -30,6 +30,7 @@ define([ 'vxlan_network_identifier': null, //delete if it is null 'mirror_destination': false }, + 'user_created_forwarding_mode': 'default', 'external_ipam': false, // set only when vcenter is enabled 'virtual_network_network_id': 0, // never set at post / put 'network_policy_refs': [], //ordered collection attr.major,minor @@ -92,6 +93,8 @@ define([ 'qos_config_refs': [], 'user_created_vxlan_mode': false, 'disable': false, + 'address_allocation_mode': 'user-defined-subnet-only', + 'user_created_flat_subnet_ipam': [] }, formatModelConfig: function (modelConfig) { @@ -118,6 +121,11 @@ define([ modelConfig['display_name'] = ctwu.getDisplayNameOrName(modelConfig); + //populate user_created_forwarding_mode + modelConfig['user_created_forwarding_mode'] = + getValueByJsonPath(modelConfig, + 'virtual_network_properties;forwarding_mode', 'default', false) + this.readSubnetHostRoutes(modelConfig); this.readRouteTargetList(modelConfig, 'user_created_route_targets'); this.readRouteTargetList(modelConfig, 'user_created_import_route_targets'); @@ -457,6 +465,13 @@ define([ subnetModels.push(subnetModel); } + //flat subnet + var flatIPAMList = formatVNCfg.flatSubnetModelFormatter(null, + null, null, -1, modelConfig); + modelConfig["user_created_flat_subnet_ipam"] = + flatIPAMList.join(ctwc.MULTISELECT_VALUE_SEPARATOR); + + //user defined subnet modelConfig['network_ipam_refs'] = new Backbone.Collection(subnetModels); }, @@ -646,17 +661,29 @@ define([ {'ipam_subnets': ipamAssocArr[ipam]} }); } + //add flat subnet ipams + var flatIpams = attr.user_created_flat_subnet_ipam ? + attr.user_created_flat_subnet_ipam.split(ctwc.MULTISELECT_VALUE_SEPARATOR) : []; + _.each(flatIpams, function(flatIpam){ + subnetArray.push({'to': + flatIpam.split(cowc.DROPDOWN_VALUE_SEPARATOR), 'attr': {'ipam_subnets':[]}}); + }); + delete attr.user_created_flat_subnet_ipam; attr['network_ipam_refs'] = subnetArray; }, getProperties: function(attr) { var forwardingMode = getValueByJsonPath(attr, - 'virtual_network_properties;forwarding_mode', null); + 'user_created_forwarding_mode', null); if (forwardingMode == null || forwardingMode == 'default') { delete attr['virtual_network_properties']['forwarding_mode']; + } else { + attr["virtual_network_properties"]["forwarding_mode"] = + forwardingMode; } + delete attr.user_created_forwarding_mode; var vxLANId = getValueByJsonPath(attr, 'virtual_network_properties;vxlan_network_identifier', null); @@ -769,6 +796,25 @@ define([ } }, + updateModelAttrsForCurrentAllocMode: function(value) { + //update forwarding mode + if(value !== 'user-defined-subnet-only') { + this.user_created_forwarding_mode("l3"); + } else { + this.user_created_forwarding_mode("default"); + } + + //reset user defined ipam_subnets for flat subnet only case + if(value === 'flat-subnet-only') { + this.model().attributes.network_ipam_refs.reset(); + } + + //clear flat_subnets for user defined subnet only case + if(value === 'user-defined-subnet-only') { + this.user_created_flat_subnet_ipam(''); + } + }, + readSRIOV: function (modelConfig) { var segment_id = getValueByJsonPath(modelConfig, 'provider_properties;segmentation_id', null); @@ -857,6 +903,13 @@ define([ required: true, msg: 'Enter Name' }, + 'user_created_flat_subnet_ipam': + function(value, attr, finalObj) { + if(finalObj.address_allocation_mode === + 'flat-subnet-only' && !value) { + return "Select Flat Subnet IPAM(s)"; + } + }, 'virtual_network_properties.vxlan_network_identifier' : function (value, attr, finalObj) { var vxMode = @@ -1015,6 +1068,11 @@ define([ type: cowc.OBJECT_TYPE_COLLECTION, getValidation: 'routeTargetModelConfigValidations' }, + { + key: 'bridge_domains', + type: cowc.OBJECT_TYPE_COLLECTION, + getValidation: 'bridgeDomainModelConfigValidations' + }, //permissions ctwu.getPermissionsValidation() ]; diff --git a/webroot/config/networking/networks/ui/js/views/vnCfgEditView.js b/webroot/config/networking/networks/ui/js/views/vnCfgEditView.js index 6f514f9b5..686897570 100644 --- a/webroot/config/networking/networks/ui/js/views/vnCfgEditView.js +++ b/webroot/config/networking/networks/ui/js/views/vnCfgEditView.js @@ -72,6 +72,8 @@ define([ {collection: self.model.model().attributes.user_created_import_route_targets}); kbValidation.bind(self, {collection: self.model.model().attributes.user_created_export_route_targets}); + kbValidation.bind(self, + {collection: self.model.model().attributes.bridge_domains}); //permissions ctwu.bindPermissionsValidation(self); }, null, true); @@ -133,6 +135,8 @@ define([ {collection: self.model.model().attributes.user_created_dns_servers}); kbValidation.bind(self, {collection: self.model.model().attributes.user_created_route_targets}); + kbValidation.bind(self, + {collection: self.model.model().attributes.bridge_domains}); //permissions ctwu.bindPermissionsValidation(self); }, null, true); @@ -181,7 +185,10 @@ define([ }); function getVNCfgViewConfig (disableOnEdit, selectedProjId) { - var prefixId = ctwl.CFG_VN_PREFIX_ID; + var prefixId = ctwl.CFG_VN_PREFIX_ID, + ipamPostData = {}; + ipamPostData.data = []; + ipamPostData.data[0] = {'type':'network-ipams', 'fields':''}; var vnCfgViewConfig = { elementId: cowu.formatElementId([prefixId, ctwl.CFG_VN_TITLE_CREATE]), @@ -268,13 +275,58 @@ define([ view: "SectionView", active:false, viewConfig: { - rows: [ + rows: [{ + columns:[{ + elementId: 'address_allocation_mode', + view: "FormRadioButtonView", + viewConfig: { + label: 'Allocation Mode', + path: 'address_allocation_mode', + class: 'col-xs-12', + dataBindValue: 'address_allocation_mode', + templateId: cowc.TMPL_FOUR_OPTNS_RADIO_BUTTON_VIEW, + elementConfig: { + dataObj: [{ + value: 'user-defined-subnet-only', label:'User Defined'}, + {value: 'flat-subnet-only', label:'Flat'}, + {value: 'user-defined-subnet-preferred', label:'User Defined Hybrid'}, + {value: 'flat-subnet-preferred', label:'Flat Hybrid'}] + } + } + }] + }, { + columns:[{ + elementId: 'user_created_flat_subnet_ipam', + view: "FormMultiselectView", + viewConfig: { + visible: 'address_allocation_mode() !== "user-defined-subnet-only"', + label: 'Flat Subnet IPAM(s)', + path : 'user_created_flat_subnet_ipam', + class: 'col-xs-11', + dataBindValue : 'user_created_flat_subnet_ipam', + elementConfig : { + dataTextField : "text", + dataValueField : "id", + placeholder : 'Select IPAM(s)', + separator: ctwc.MULTISELECT_VALUE_SEPARATOR, + dataSource : { + type: "remote", + requestType: 'post', + url:'/api/tenants/config/get-config-details', + postData: JSON.stringify(ipamPostData), + parse: formatVNCfg.ipamFlatSubnetDropDownFormatter + } + } + } + }] + }, { columns: [ { elementId: 'network_ipam_refs', view: "FormEditableGridView", viewConfig: { + visible: 'address_allocation_mode() !== "flat-subnet-only"', path : 'network_ipam_refs', class: 'col-xs-12', validation: @@ -319,8 +371,10 @@ define([ dataValueField : "id", defaultValueId : 0, dataSource : { - type: 'remote', - url: '/api/tenants/config/ipams', + type: "remote", + requestType: 'post', + url:'/api/tenants/config/get-config-details', + postData: JSON.stringify(ipamPostData), parse: formatVNCfg.ipamDropDownFormatter } } @@ -452,6 +506,7 @@ define([ view: "AccordianView", viewConfig: [ { + visible: 'address_allocation_mode() !== "flat-subnet-only"', elementId: 'hostRoutes', title: 'Host Route(s)', view: "SectionView", @@ -687,14 +742,14 @@ define([ { columns: [ { - elementId: 'forwarding_mode', + elementId: 'user_created_forwarding_mode', view: "FormDropdownView", viewConfig: { label: 'Forwarding Mode', - path : 'virtual_network_properties.forwarding_mode', + path : 'user_created_forwarding_mode', class: 'col-xs-6', dataBindValue : - 'virtual_network_properties().forwarding_mode', + 'user_created_forwarding_mode', elementConfig : { dataTextField : "text", dataValueField : "id", @@ -757,7 +812,7 @@ define([ placeholder: 'Select Static Route(s)', dataTextField: "text", dataValueField: "id", - separator: cowc.DROPDOWN_VALUE_SEPARATOR, + separator: ctwc.DROPDOWN_VALUE_SEPARATOR, dataSource : { type: 'remote', requestType: 'POST', @@ -978,6 +1033,7 @@ define([ view: "AccordianView", viewConfig: [ { + visible: 'address_allocation_mode() !== "flat-subnet-only"', elementId: 'dnsServers', title: 'DNS Server(s)', view: "SectionView", diff --git a/webroot/config/networking/networks/ui/js/views/vnCfgFormatters.js b/webroot/config/networking/networks/ui/js/views/vnCfgFormatters.js index 4cb6565c3..7ddc6b00a 100644 --- a/webroot/config/networking/networks/ui/js/views/vnCfgFormatters.js +++ b/webroot/config/networking/networks/ui/js/views/vnCfgFormatters.js @@ -16,8 +16,8 @@ define([ var ipamObjs = contrail.handleIfNull(dc['network_ipam_refs'], []); - var len = ipamObjs.length, count = 0, subnetCnt = 0, returnStr = ''; - + var len = ipamObjs.length, count = 0, subnetCnt = 0, returnStr = '', + flatSubnetIPAMs; if (!len) { return "-"; } @@ -26,7 +26,9 @@ define([ var ipam = ipamObjs[i]; var subnetStr = '', field = 'ipam_subnets'; var subnetLen = ipam['attr'][field].length; - + if(validateFlatSubnetIPAM(ipam)){ + continue; + } subnetCnt += subnetLen; if (count > 2 && cd != -1) { @@ -44,29 +46,54 @@ define([ if(subnet) { cidr = subnet.ip_prefix + '/' + subnet.ip_prefix_len; } else { - cidr = "-"; + continue; } returnStr += cidr + '
'; } } + flatSubnetIPAMs = flatSubnetIPAMsFormatter(d, c, v, cd, dc); + if(flatSubnetIPAMs.length) { + var flatIpamsLen = flatSubnetIPAMs.length; + if(subnetCnt === 0) { + flatSubnetIPAMs = flatSubnetIPAMs.slice(0, 2); + } else if(subnetCnt === 1) { + flatSubnetIPAMs = flatSubnetIPAMs.slice(0, 1); + } else if(subnetCnt >= 2) { + flatSubnetIPAMs = []; + } + subnetCnt += flatIpamsLen; + } + _.each(flatSubnetIPAMs, function(ipam) { + returnStr += ipam + '
'; + }); if (subnetCnt > 2 && cd != -1) { returnStr += '(' + (subnetCnt - 2) + ' more)'; } - return returnStr; + return returnStr ? returnStr : '-'; + }; + + var validateFlatSubnetIPAM = function (ipam) { + var isFlatSubnetIPAM = getValueByJsonPath(ipam, + 'attr;ipam_subnets;0;subnet', null, false) ? false : true; + if(isFlatSubnetIPAM){ + return true; + } else { + return false; + } }; /* * private @getSubnetDNSStatus */ - var getSubnetDNSStatus = function(subnetObj) { + this.getSubnetDNSStatus = function(subnetObj) { var dhcpOpts = getValueByJsonPath(subnetObj, 'dhcp_option_list;dhcp_option', []); if (dhcpOpts.length) { - return getdhcpValuesByOption(dhcpOpts, 6).indexOf("0.0.0.0") + return this.getdhcpValuesByOption(dhcpOpts, 6).indexOf("0.0.0.0") == -1 ? true : false; } return true; @@ -75,7 +102,7 @@ define([ /* * private @getdhcpValueByOption */ - var getdhcpValuesByOption = function(dhcpObj, optCode) { + this.getdhcpValuesByOption = function(dhcpObj, optCode) { var dhcpValues = '', dhcpObjLen = dhcpObj.length; if (dhcpObjLen == 0 ) { @@ -248,7 +275,7 @@ define([ * @subnetTmplFormatter */ this.subnetTmplFormatter = function(d, c, v, cd, dc) { - var subnetString = ""; + var subnetString = "", flatSubnetIPAMs; var ipamObjs = getValueByJsonPath(dc,"network_ipam_refs", []); var len = ipamObjs.length, count = 0, subnetCnt = 0, returnStr = ''; @@ -266,16 +293,23 @@ define([ var field = 'ipam_subnets'; var subnet = ipam['attr'][field]; var subnetLen = ipam['attr'][field].length; + if(validateFlatSubnetIPAM(ipam)){ + continue; + } for(var j = 0; j < subnetLen; j++) { var ip_block = ipam['attr'][field][j]; var ipam_block= ipam['to']; var ipamto = ipam_block[2] + ' ( ' + ipam_block[0] + ':' +ipam_block[1] + ')'; var cidr = getValueByJsonPath(ip_block,"subnet;ip_prefix", null, false); - var cidrlen=getValueByJsonPath(ip_block,"subnet;ip_prefix_len", false); - cidr = cidr ? cidr + '/' + cidrlen : "-"; + var cidrlen = getValueByJsonPath(ip_block,"subnet;ip_prefix_len", null, false); + if(cidr){ + cidr = cidr + '/' + cidrlen ; + } else { + continue; + } var gw = ip_block.default_gateway ? ip_block.default_gateway: "-"; var dhcp = ip_block.enable_dhcp ? 'Enabled' : 'Disabled'; - var dns = getSubnetDNSStatus(ip_block) ? 'Enabled' : 'Disabled'; + var dns = this.getSubnetDNSStatus(ip_block) ? 'Enabled' : 'Disabled'; var gwStatus = (gw == null || gw == "" || gw == "0.0.0.0") ? 'Disabled' : gw; @@ -302,6 +336,18 @@ define([ subnetString += ""; } } + + //flat subnet ipams + flatSubnetIPAMs = flatSubnetIPAMsFormatter(d, c, v, -1, dc); + _.each(flatSubnetIPAMs, function(ipam) { + subnetString += ""; + subnetString += ipam + ""; + subnetString += '-' + ""; + subnetString += '-' + ""; + subnetString += '-' + ""; + subnetString += '-' + ""; + subnetString += ""; + }); var returnString = ""; if(subnetString != ""){ returnString = @@ -317,9 +363,48 @@ define([ } else { returnString += ""; } - return returnString; + return returnString ? returnString : "-"; } + var flatSubnetIPAMsFormatter = function(d, c, v, cd, dc) { + var ipamString, + ipamObjs = getValueByJsonPath(dc,"network_ipam_refs", [], false), + domain = contrail.getCookie(cowc.COOKIE_DOMAIN), + project = contrail.getCookie(cowc.COOKIE_PROJECT), + flatSubnetIpams = []; + _.each(ipamObjs, function(ipamObj) { + var isFlatSubnetIPAM = getValueByJsonPath(ipamObj, + 'attr;ipam_subnets;0;subnet', null, false) ? false : true; + if(isFlatSubnetIPAM) { + ipamFqn = ipamObj.to; + if (domain != ipamFqn[0] || + project != ipamFqn[1]) { + ipamString = ipamFqn[2] + ' (' + ipamFqn[0] + + ':' + ipamFqn[1] + ')'; + } else { + ipamString = ipamFqn[2]; + } + flatSubnetIpams.push(ipamString); + } + }); + return flatSubnetIpams; + }; + + this.flatSubnetModelFormatter = function(d, c, v, cd, dc) { + var flatIPAMList = [], ipamFqnStr, + ipamObjs = getValueByJsonPath(dc,"network_ipam_refs", []); + + _.each(ipamObjs, function(ipamObj) { + var isFlatSubnetIPAM = getValueByJsonPath(ipamObj, + 'attr;ipam_subnets;0;subnet', null, false) ? false : true; + if(isFlatSubnetIPAM) { + ipamFqnStr = ipamObj.to.join(cowc.DROPDOWN_VALUE_SEPARATOR); + flatIPAMList.push(ipamFqnStr) + } + }); + return flatIPAMList + }; + /* * @subnetModelFormatter */ @@ -341,18 +426,21 @@ define([ var ipamFQN = ipamObjs[i].to.join(cowc.DROPDOWN_VALUE_SEPARATOR); var field = 'ipam_subnets'; var subnetLen = ipam['attr'][field].length; + if(validateFlatSubnetIPAM(ipam)){ + continue; + } for(var j = 0; j < subnetLen; j++) { var subnetObj = {}; var ip_block = getValueByJsonPath(ipam, 'attr;' + field + ';' + j, null, false); - subnetObj['user_created_ipam_fqn'] = ipamFQN; if(!ip_block || !ip_block.subnet){ subnetObj['disable'] = true; returnArr.push(subnetObj); continue; } subnetObj = ip_block; + subnetObj['user_created_ipam_fqn'] = ipamFQN; var cidr = ip_block.subnet.ip_prefix + '/' + ip_block.subnet.ip_prefix_len; subnetObj['user_created_cidr'] = cidr; @@ -374,7 +462,7 @@ define([ subnetObj['user_created_enable_gateway'].length && subnetObj['user_created_enable_gateway'].indexOf("0.0.0.0") == -1 ? true : false; - subnetObj['user_created_enable_dns'] = getSubnetDNSStatus(ip_block); + subnetObj['user_created_enable_dns'] = this.getSubnetDNSStatus(ip_block); subnetObj['disable'] = true; returnArr.push(subnetObj); } @@ -383,7 +471,6 @@ define([ return returnArr; }; - /* * @subnetHostRouteFormatter */ @@ -456,7 +543,7 @@ define([ var dhcpOpts = getValueByJsonPath(ipBlock, 'dhcp_option_list;dhcp_option', []); if (dhcpOpts.length) { - returnArr.push(getdhcpValuesByOption(dhcpOpts, 6).split(' ')); + returnArr.push(this.getdhcpValuesByOption(dhcpOpts, 6).split(' ')); } } } @@ -744,15 +831,64 @@ define([ */ this.ipamDropDownFormatter = function(response) { var ipamResponse = getValueByJsonPath(response, - 'network-ipams', []); + '0;network-ipams', []); var ipamList = []; var domain = contrail.getCookie(cowc.COOKIE_DOMAIN); var project = contrail.getCookie(cowc.COOKIE_PROJECT); var vCenter = isVCenter(); - $.each(ipamResponse, function (i, obj) { - var flatName = obj.fq_name[2]; + $.each(ipamResponse, function (i, ipam) { + var obj = getValueByJsonPath(ipam, + 'network-ipam', "", false), + flatName = obj.fq_name[2]; + if(obj.ipam_subnet_method && + obj.ipam_subnet_method !== ctwc.USER_DEFINED_SUBNET) { + return true; + } + + if (domain != obj.fq_name[0] || + project != obj.fq_name[1]) { + flatName += ' (' + obj.fq_name[0] + + ':' + obj.fq_name[1] + ')'; + } + if (vCenter) { + if (domain == obj.fq_name[0] && + project == obj.fq_name[1]) { + ipamList.push({ + id: obj.fq_name.join(cowc.DROPDOWN_VALUE_SEPARATOR), + text: flatName + }); + } + } else { + ipamList.push({ + id: obj.fq_name.join(cowc.DROPDOWN_VALUE_SEPARATOR), + text: flatName + }); + } + }); + + return ipamList; + }; + + /* + * @ipamDropDownFormatter + */ + this.ipamFlatSubnetDropDownFormatter = function(response) { + var ipamResponse = getValueByJsonPath(response, + '0;network-ipams', []); + var ipamList = []; + var domain = contrail.getCookie(cowc.COOKIE_DOMAIN); + var project = contrail.getCookie(cowc.COOKIE_PROJECT); + var vCenter = isVCenter(); + $.each(ipamResponse, function (i, ipam) { + var obj = getValueByJsonPath(ipam, + 'network-ipam', "", false), + flatName = obj.fq_name[2]; + if(obj.ipam_subnet_method == null || + obj.ipam_subnet_method === ctwc.USER_DEFINED_SUBNET) { + return true; + } if (domain != obj.fq_name[0] || project != obj.fq_name[1]) { flatName += ' (' + obj.fq_name[0] + @@ -777,6 +913,30 @@ define([ return ipamList; }; + /* + * @allocationModeExpFormatter + */ + this.allocationModeExpFormatter = function(d, c, v, cd, dc) { + var allocType = getValueByJsonPath(dc, + "address_allocation_mode", 'user-defined-subnet-only', false), + returnString = ""; + switch(allocType) { + case 'user-defined-subnet-preferred' : + returnString = "User Defined Hybrid"; + break; + case 'user-defined-subnet-only' : + returnString = "User Defined"; + break; + case 'flat-subnet-preferred' : + returnString = "Flat Hybrid"; + break; + case 'flat-subnet-only' : + returnString = "Flat"; + break; + }; + return returnString ? returnString : '-'; + }; + /* * @qosDropDownFormatter */ diff --git a/webroot/config/networking/networks/ui/js/views/vnCfgGridView.js b/webroot/config/networking/networks/ui/js/views/vnCfgGridView.js index 2afb2d8f6..29b501965 100644 --- a/webroot/config/networking/networks/ui/js/views/vnCfgGridView.js +++ b/webroot/config/networking/networks/ui/js/views/vnCfgGridView.js @@ -160,6 +160,10 @@ define([ function(backBoneModel, value) { vnModel.externalRouterHandler(value); }); + vnModel.__kb.view_model.model().on('change:address_allocation_mode', + function(backBoneModel, value) { + vnModel.updateModelAttrsForCurrentAllocMode(value); + }); }; @@ -228,6 +232,31 @@ define([ ]; + function getSubnetExpandDetailsTmpl() { + return { + title: "Subnets", + templateGenerator: 'BlockListTemplateGenerator', + templateGeneratorConfig: [ + { + label: 'Allocation Mode', + key: 'uuid', + templateGenerator: 'TextGenerator', + templateGeneratorConfig: { + formatter: 'allocationModeExpFormatter' + } + }, + { + label: 'Subnet(s)', + key: 'uuid', + templateGenerator: 'TextGenerator', + templateGeneratorConfig: { + formatter: 'subnetTmplFormatter' + } + } + ] + } + }; + function getVNCfgDetailsTemplateConfig() { return { templateGenerator: 'RowSectionTemplateGenerator', @@ -241,18 +270,11 @@ define([ { class: 'col-xs-12', rows: [ - { + getSubnetExpandDetailsTmpl(), + { title: ctwl.CFG_VN_TITLE_DETAILS, templateGenerator: 'BlockListTemplateGenerator', templateGeneratorConfig: [ - { - label: 'Subnet(s)', - key: 'uuid', - templateGenerator: 'TextGenerator', - templateGeneratorConfig: { - formatter: 'subnetTmplFormatter' - } - }, { label: 'Name', key: 'name', @@ -566,6 +588,10 @@ define([ this.showName = function (r, c, v, cd, dc) { return ctwu.getDisplayNameOrName(dc); } + this.allocationModeExpFormatter = function (v, dc) { + return formatVNCfg.allocationModeExpFormatter(null, + null, null, null, dc); + } this.subnetTmplFormatter = function (v, dc) { return formatVNCfg.subnetTmplFormatter(null, null, null, null, dc);