From c604f64b971491f8c9b953adce54b847d7946e26 Mon Sep 17 00:00:00 2001 From: Prudence Au Date: Mon, 13 Aug 2018 17:06:59 -0400 Subject: Initial submission for validation service Change-Id: I9372430f1ae347373d5a9a0c7a427d7bd393d61e Issue-ID: LOG-427 Signed-off-by: Prudence Au (prudence.au@amdocs.com) Signed-off-by: Geora Barsky Signed-off-by: Pierre Rioux --- .../etc/rules/aai-event/common_rules.groovy | 69 +++++++++ .../aai-event/entity-availability-zone.groovy | 111 ++++++++++++++ .../etc/rules/aai-event/entity-complex.groovy | 146 ++++++++++++++++++ .../etc/rules/aai-event/entity-generic-vnf.groovy | 56 +++++++ .../etc/rules/aai-event/entity-newvce.groovy | 43 ++++++ .../etc/rules/aai-event/entity-oam-network.groovy | 81 ++++++++++ .../etc/rules/aai-event/entity-port-group.groovy | 45 ++++++ .../etc/rules/aai-event/entity-pserver.groovy | 74 +++++++++ bundleconfig/etc/rules/aai-event/entity-vce.groovy | 94 ++++++++++++ .../etc/rules/aai-event/entity-vnfc.groovy | 27 ++++ .../etc/rules/aai-event/entity-vpls-pe.groovy | 27 ++++ .../etc/rules/aai-event/entity-vserver.groovy | 151 ++++++++++++++++++ .../etc/rules/gizmo-event/common_rules.groovy | 27 ++++ .../etc/rules/gizmo-event/pserver-rules.groovy | 27 ++++ .../etc/rules/poa-event/default-rules.groovy | 168 +++++++++++++++++++++ .../etc/rules/spike-event/common_rules.groovy | 27 ++++ .../etc/rules/spike-event/pserver-rules.groovy | 27 ++++ 17 files changed, 1200 insertions(+) create mode 100644 bundleconfig/etc/rules/aai-event/common_rules.groovy create mode 100644 bundleconfig/etc/rules/aai-event/entity-availability-zone.groovy create mode 100644 bundleconfig/etc/rules/aai-event/entity-complex.groovy create mode 100644 bundleconfig/etc/rules/aai-event/entity-generic-vnf.groovy create mode 100644 bundleconfig/etc/rules/aai-event/entity-newvce.groovy create mode 100644 bundleconfig/etc/rules/aai-event/entity-oam-network.groovy create mode 100644 bundleconfig/etc/rules/aai-event/entity-port-group.groovy create mode 100644 bundleconfig/etc/rules/aai-event/entity-pserver.groovy create mode 100644 bundleconfig/etc/rules/aai-event/entity-vce.groovy create mode 100644 bundleconfig/etc/rules/aai-event/entity-vnfc.groovy create mode 100644 bundleconfig/etc/rules/aai-event/entity-vpls-pe.groovy create mode 100644 bundleconfig/etc/rules/aai-event/entity-vserver.groovy create mode 100644 bundleconfig/etc/rules/gizmo-event/common_rules.groovy create mode 100644 bundleconfig/etc/rules/gizmo-event/pserver-rules.groovy create mode 100644 bundleconfig/etc/rules/poa-event/default-rules.groovy create mode 100644 bundleconfig/etc/rules/spike-event/common_rules.groovy create mode 100644 bundleconfig/etc/rules/spike-event/pserver-rules.groovy (limited to 'bundleconfig/etc/rules') diff --git a/bundleconfig/etc/rules/aai-event/common_rules.groovy b/bundleconfig/etc/rules/aai-event/common_rules.groovy new file mode 100644 index 0000000..70980fe --- /dev/null +++ b/bundleconfig/etc/rules/aai-event/common_rules.groovy @@ -0,0 +1,69 @@ +/* + * ============LICENSE_START=================================================== + * Copyright (c) 2018 Amdocs + * ============================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END===================================================== + */ + +rule { + name 'prov-status' + category 'INVALID_VALUE' + description 'prov-status value restricted to one of PREPROV, NVTPROV, PROV, CAPPED, DECOM, RETIRED' + errorText 'Invalid prov-status value. Must be PREPROV, NVTPROV, PROV, CAPPED, DECOM, or RETIRED' + severity 'CRITICAL' + attributes 'status' + validate '''switch (status) { + case "PREPROV": + case "NVTPROV": + case "PROV": + case "CAPPED": + case "DECOM": + case "RETIRED": + return true + default: return false + }''' +} + +// The following are used by both vce and newvce + +rule { + name 'vnf-name' + category 'INVALID_NAME' + description 'Invalid naming convention' + errorText 'Invalid name - attribute does not match xxxxxnnnvbc (where x = alphanumeric and n = numeric)' + severity 'MINOR' + attributes 'name' + validate 'name != null && name.matches("[a-z,0-9]{5}[0-9]{3}vbc")' +} + +rule { + name 'vnf-type' + category 'INVALID_VALUE' + description 'Invalid value' + errorText 'Invalid value - attribute must equal esx-vce' + severity 'MINOR' + attributes 'name' + validate 'name != null && name.matches("esx-vce")' +} + +rule { + name 'heat-stack-id equals first 11 bytes of vnf-name' + category 'INVALID_VALUE' + description 'The value of heat-stack-id must equal the first 11 bytes of vnf-name' + errorText 'Invalid value - the value of heat-stack-id must equal the first 11 bytes of vnf-name' + severity 'MINOR' + attributes 'heatstackid', 'vnfname' + validate '''def firstEleven = { str -> str ? str.take(11) : null } + heatstackid.equals(firstEleven(vnfname))''' +} diff --git a/bundleconfig/etc/rules/aai-event/entity-availability-zone.groovy b/bundleconfig/etc/rules/aai-event/entity-availability-zone.groovy new file mode 100644 index 0000000..8fdec4f --- /dev/null +++ b/bundleconfig/etc/rules/aai-event/entity-availability-zone.groovy @@ -0,0 +1,111 @@ +/* + * ============LICENSE_START=================================================== + * Copyright (c) 2018 Amdocs + * ============================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END===================================================== + */ + +entity { + type 'availability-zone' + validation { + useRule { + name 'availability-zone name matches naming convention' + attributes 'availability-zone-name' + } + useRule { + name 'hypervisor-type matches naming convention' + attributes 'hypervisor-type' + } + useRule { + name 'operational-state must be operationalState' + attributes 'operational-state' + } + useRule { name 'availability zone is related to dvs-switch' } + useRule { name 'availability zone is related to a complex' } + useRule { + name 'availability-zone must be related to a service-capability and service-capability.service-type matches naming convention' + attributes 'relationship-list.relationship[*]' + } + } +} + +rule { + name 'availability-zone name matches naming convention' + category 'INVALID_NAME' + description 'Naming convention must match xxxxx-esx-aznn' + errorText 'Invalid name - attribute must match xxxxx-esx-aznn (where x = alphanumeric and n = numeric)' + severity 'MINOR' + attributes 'name' + validate 'name != null && name.matches("[a-z0-9]{5}-esx-az[0-9]{2}")' +} + +rule { + name 'hypervisor-type matches naming convention' + category 'INVALID_NAME' + description 'Naming convention must match the string esx' + errorText 'Invalid name - attribute must match the string esx' + severity 'CRITICAL' + attributes 'name' + validate 'name != null && name.matches("esx")' +} + +rule { + name 'operational-state must be operationalState' + category 'INVALID_VALUE' + description 'The value of operational-state must be operationalState' + errorText 'Invalid value - attribute must be set to operationalState' + severity 'CRITICAL' + attributes 'opvalue' + validate 'opvalue != null && opvalue.matches("operationalState")' +} + +rule { + name 'availability zone is related to dvs-switch' + category 'MISSING_REL' + description 'Validates that an availability zone is related to a dvs-switch' + errorText 'Missing relationship - availability zone is not related to a dvs-switch' + severity 'MAJOR' + attributes 'relationship-list.relationship[*].related-to' + validate 'related-to != null && related-to.contains("dvs-switch")' +} + +rule { + name 'availability zone is related to a complex' + category 'MISSING_REL' + description 'Validates that an availability zone is related to a complex' + errorText 'Missing relationship - availability zone is not related to a complex' + severity 'CRITICAL' + attributes 'relationship-list.relationship[*].related-to' + validate 'related-to != null && related-to.contains("complex")' +} + +rule { + name 'availability-zone must be related to a service-capability and service-capability.service-type matches naming convention' + category 'INVALID_NAME' + description 'Validates that an availability-zone is related to a service-capability and service-capability.service-type matches naming convention' + errorText 'Invalid name - availability-zone must be related to a service-capability and service-capability.service-type must be set to SDN-ETHERNET-INTERNET' + severity 'CRITICAL' + attributes 'relationships' + validate ''' + def getStringProperty = { jsonObject, propertyName -> jsonObject.get(propertyName)?.getAsString() } + + if (!relationships.find { getStringProperty(it, "related-to") == "service-capability" }) { return true } + + return relationships.findAll { getStringProperty(it, "related-to") == "service-capability" } + .findAll { it."related-to-property" != null } + .collect { it."relationship-data".get(0) } + .findAll { getStringProperty(it, "relationship-key") == "service-capability.service-type" } + .find { getStringProperty(it, "relationship-value") == "SDN-ETHERNET-INTERNET" } + ''' +} diff --git a/bundleconfig/etc/rules/aai-event/entity-complex.groovy b/bundleconfig/etc/rules/aai-event/entity-complex.groovy new file mode 100644 index 0000000..48d2f26 --- /dev/null +++ b/bundleconfig/etc/rules/aai-event/entity-complex.groovy @@ -0,0 +1,146 @@ +/* + * ============LICENSE_START=================================================== + * Copyright (c) 2018 Amdocs + * ============================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END===================================================== + */ + +entity { + type 'complex' + validation { + useRule { + name 'CLLI' + attributes 'physical-location-id' + } + useRule { + name 'not AAI default' + attributes 'street1' + } + useRule { + name 'not AAI default' + attributes 'city' + } + useRule { + name 'not AAI default' + attributes 'state' + } + useRule { + name 'not AAI default' + attributes 'postal-code' + } + useRule { + name 'not AAI default' + attributes 'region' + } + useRule { + name 'not AAI default' + attributes 'country' + } + useRule { + name 'critical not AAI default' + attributes 'physical-location-type' + } + useRule { + name 'length five or null' + attributes 'complex-name' + } + useRule {name 'complex is related to availability zone' } + useRule {name 'complex is related to 1 oam-network' } + useRule { + name 'if a customer is related to an oam-network then oam-network.network-name must match naming convention' + attributes 'relationship-list.relationship[*]' + } + } +} + +rule { + name 'CLLI' + category 'FIELD_LENGTH' + description 'Field must be 8 or 11 characters long' + errorText 'Invalid length - field must be 8 or 11 characters long' + severity 'CRITICAL' + attributes 'field' + validate 'field.size() == 8 || field.size() == 11' +} + +rule { + name 'not AAI default' + category 'FIELD_LENGTH' + description 'Invalid length - field must not be AAIDEFAULT or null' + errorText 'Invalid Value - must not be AAIDEFAULT or null' + severity 'MINOR' + attributes 'field' + validate 'field != null && field.size() > 0 && !field.equalsIgnoreCase("AAIDEFAULT")' +} + +rule { + name 'length five or null' + category 'FIELD_LENGTH' + description 'Field must be 5 characters long or null' + errorText 'Invalid Length - field must be 5 characters long or null' + severity 'MINOR' + attributes 'field' + validate 'field == null || field.size() == 5' +} + +rule { + name 'critical not AAI default' + category 'INVALID_VALUE' + description 'Field must not be AAIDEFAULT or null' + errorText 'Invalid Value - must not be AAIDEFAULT or null' + severity 'CRITICAL' + attributes 'field' + validate 'field != null && field.size() > 0 && !field.equalsIgnoreCase("AAIDEFAULT")' +} + +rule { + name 'complex is related to availability zone' + category 'MISSING_REL' + description 'Validates that a complex is related to an availability zone' + errorText 'Missing relationship - a complex must be related to an availability zone' + severity 'CRITICAL' + attributes 'relationship-list.relationship[*].related-to' + validate 'related-to != null && related-to.contains("availability-zone")' +} + +rule { + name 'complex is related to 1 oam-network' + category 'MISSING_REL' + description 'Validates that a complex is related to 1 oam-network (and not more than 1 oam-network)' + errorText 'Missing relationship - complex must be related to 1 oam-network' + severity 'MAJOR' + attributes 'relationship-list.relationship[*].related-to' + validate 'related-to != null && related-to.count("oam-network") == 1' +} + +rule { + name 'if a customer is related to an oam-network then oam-network.network-name must match naming convention' + category 'INVALID_NAME' + description 'validates that if a customer is related to an oam-network then oam-network.network-name must match naming convention' + errorText 'Invalid name - if a customer is related to an oam-network then network-name must start with VLAN' + severity 'MINOR' + attributes 'relationships' + validate ''' + def getStringProperty = { jsonObject, propertyName -> jsonObject.get(propertyName).getAsString() } + + relatedToOamNetwork = relationships.findAll { getStringProperty(it, "related-to") == "oam-network" } + + networkNameIsValid = relationships.findAll { getStringProperty(it, "related-to") == "oam-network" } + .collect { it."related-to-property".get(0) } + .findAll { getStringProperty(it, "property-key") == "oam-network.network-name" } + .find { getStringProperty(it, "property-value").startsWith("VLAN") } + + return !relatedToOamNetwork || networkNameIsValid + ''' +} diff --git a/bundleconfig/etc/rules/aai-event/entity-generic-vnf.groovy b/bundleconfig/etc/rules/aai-event/entity-generic-vnf.groovy new file mode 100644 index 0000000..d813eea --- /dev/null +++ b/bundleconfig/etc/rules/aai-event/entity-generic-vnf.groovy @@ -0,0 +1,56 @@ +/* + * ============LICENSE_START=================================================== + * Copyright (c) 2018 Amdocs + * ============================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END===================================================== + */ + +entity { + type 'generic-vnf' + validation { + useRule { + name 'prov-status' + attributes 'prov-status' + } + useRule { + name 'valid_ipv4_addr' + attributes 'ipv4-oam-address' + } + useRule { + name 'ipv4_addr_present' + attributes 'equipment-role', 'l-interfaces.l-interface[*].l3-interface-ipv4-address-list' + } + } +} + +rule { + name 'valid_ipv4_addr' + category 'INVALID_VALUE' + description 'Validate an IPv4 address' + errorText 'Invalid value - attribute is not a valid IPv4 address' + severity 'MINOR' + attributes 'ipaddr' + validate 'ipaddr != null && ipaddr.matches("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])")' +} + +// If generic-vnf.equipment-role="UCPE" and there is an l-interface - then there must be an IPV4 address related to the l-interface +rule { + name 'ipv4_addr_present' + category 'MISSING_REL' + description 'Validates that ICPE equipment has a related IPv4 address' + errorText 'UCPE l-interface missing the IPv4 relationship' + severity 'MINOR' + attributes 'equipment', 'ipv4' + validate 'equipment != "UCPE" || ipv4 != null' +} diff --git a/bundleconfig/etc/rules/aai-event/entity-newvce.groovy b/bundleconfig/etc/rules/aai-event/entity-newvce.groovy new file mode 100644 index 0000000..dce812a --- /dev/null +++ b/bundleconfig/etc/rules/aai-event/entity-newvce.groovy @@ -0,0 +1,43 @@ +/* + * ============LICENSE_START=================================================== + * Copyright (c) 2018 Amdocs + * ============================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END===================================================== + */ + +entity { + type 'newvce' + validation { + useRule { + name 'prov-status' + attributes 'prov-status' + } + useRule { + name 'vnf-name' + attributes 'vnf-name' + } + useRule { + name 'vnf-type' + attributes 'vnf-type' + } + useRule { + name 'valid_ipv4_addr' + attributes 'ipv4-oam-address' + } + useRule { + name 'heat-stack-id equals first 11 bytes of vnf-name' + attributes 'heat-stack-id', 'vnf-name' + } + } +} diff --git a/bundleconfig/etc/rules/aai-event/entity-oam-network.groovy b/bundleconfig/etc/rules/aai-event/entity-oam-network.groovy new file mode 100644 index 0000000..a2e634a --- /dev/null +++ b/bundleconfig/etc/rules/aai-event/entity-oam-network.groovy @@ -0,0 +1,81 @@ +/* + * ============LICENSE_START=================================================== + * Copyright (c) 2018 Amdocs + * ============================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END===================================================== + */ + +entity { + type 'oam-network' + validation { + useRule { + name 'network-name value' + attributes 'network-name' + } + useRule { + name 'cvlan-tag equals last four digits of network-name' + attributes 'cvlan-tag', 'network-name' + } + useRule { + name 'valid_ipv4_oam_gw_addr' + attributes 'ipv4-oam-gateway-address' + } + useRule { + name 'ipv4_oam_gw_addr_prefix_length' + attributes 'ipv4-oam-gateway-address-prefix-length' + } + } +} + +rule { + name 'network-name value' + category 'INVALID_VALUE' + description 'The value of network-name must be VLAN-OAM-1323 or VLAN-OAM-1321' + errorText 'Invalid value - the value of network-name must be VLAN-OAM-1323 or VLAN-OAM-1321' + severity 'MINOR' + attributes 'name' + validate 'name != null && name.matches("VLAN-OAM-1323|VLAN-OAM-1321")' +} + +rule { + name 'cvlan-tag equals last four digits of network-name' + category 'INVALID_VALUE' + description 'The value of cvlan-tag must match the last 4 digits of network-name' + errorText 'Invalid value - the value of cvlan-tag must match the last 4 digits of network-name' + severity 'MINOR' + attributes 'cvlantag', 'networkname' + validate '''def lastFour = { str -> str ? str.drop(str.size() - 4) : null } + cvlantagStr=String.valueOf(cvlantag) + cvlantagStr.equals(lastFour(networkname))''' +} + +rule { + name 'valid_ipv4_oam_gw_addr' + category 'INVALID_VALUE' + description 'Validate an IPv4 address' + errorText 'Invalid value - attribute is not a valid IPv4 address' + severity 'MAJOR' + attributes 'ipaddr' + validate 'ipaddr != null && ipaddr.matches("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])")' +} + +rule { + name 'ipv4_oam_gw_addr_prefix_length' + category 'INVALID_VALUE' + description 'Invalid value - field value must be 26' + errorText 'Invalid Value - field value must be 26' + severity 'MAJOR' + attributes 'field' + validate 'field != null && field == 26' +} diff --git a/bundleconfig/etc/rules/aai-event/entity-port-group.groovy b/bundleconfig/etc/rules/aai-event/entity-port-group.groovy new file mode 100644 index 0000000..8fdf2ce --- /dev/null +++ b/bundleconfig/etc/rules/aai-event/entity-port-group.groovy @@ -0,0 +1,45 @@ +/* + * ============LICENSE_START=================================================== + * Copyright (c) 2018 Amdocs + * ============================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END===================================================== + */ + +entity { + type 'port-group' + validation { + useRule { + name 'heat-stack-id' + } + } +} + +/* + * This rule validates the heat-stack-id attribute value based on the corresponding orchestration-status attribute value. + * If the orchestration-status is "created", then the heat-stack-id cannot be null or empty, or equal to "heat123". + * If the orchestration-status is "pending create", then the heat-stack-id must be null or empty, or equal to "heat123". + */ +rule { + name 'heat-stack-id' + category 'DEPENDENCY_ERR' + description 'Validates that the heat-stack-id value is valid for various Orchestration Status values' + errorText 'The heat-stack-id value is invalid for the current orchestration-status.' + severity 'CRITICAL' + attributes 'orchestration-status', 'heat-stack-id' + validate '''switch (orchestration-status?.toLowerCase()) { + case "created": return !(heat-stack-id in [null, "", "heat123"]) + case "pending create": return heat-stack-id in [null, "", "heat123"] + default: orchestration-status != null // true + }''' +} diff --git a/bundleconfig/etc/rules/aai-event/entity-pserver.groovy b/bundleconfig/etc/rules/aai-event/entity-pserver.groovy new file mode 100644 index 0000000..ed948d2 --- /dev/null +++ b/bundleconfig/etc/rules/aai-event/entity-pserver.groovy @@ -0,0 +1,74 @@ +/* + * ============LICENSE_START=================================================== + * Copyright (c) 2018 Amdocs + * ============================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END===================================================== + */ + +entity { + type 'pserver' + validation { + useRule { + name 'equip-type' + attributes 'equip-type' + } + useRule {name 'pserver is related to 1 complex' } + useRule { + name 'pserver inv-status attribute allowed values' + attributes 'inv-status' + } + } +} + +rule { + name 'equip-type' + category 'INVALID_VALUE' + description 'Invalid value - equip-type must not be toa or hitachi - an empty value is ok' + errorText 'Invalid value - attribute must not have a value of toa or hitachi' + severity 'MINOR' + validate ''' equip-type == null || + (!equip-type.equalsIgnoreCase("toa") && + !equip-type.equalsIgnoreCase("hitachi")) + ''' +} + +rule { + name 'pserver is related to 1 complex' + category 'MISSING_REL' + description 'Validates that a pserver is related to 1 complex' + errorText 'Missing relationship - pserver must be related to 1 complex' + severity 'MINOR' + attributes 'relationship-list.relationship[*].related-to' + validate 'related-to != null && related-to.count("complex") == 1' +} + +rule { + name 'pserver inv-status attribute allowed values' + category 'INVALID_VALUE' + description 'inv-status value restricted to one of Deployed, In Service, Not Specified, Pending Delete, Planned, Planned Modify' + errorText 'Invalid inv-status value. Must be Deployed, In Service, Not Specified, Pending Delete, Planned, Planned Modify' + severity 'CRITICAL' + attributes 'status' + validate '''switch (status) { + case null: + case "Deployed": + case "In Service": + case "Not Specified": + case "Pending Delete": + case "Planned": + case "Planned Modify": + return true + default: return false + }''' +} diff --git a/bundleconfig/etc/rules/aai-event/entity-vce.groovy b/bundleconfig/etc/rules/aai-event/entity-vce.groovy new file mode 100644 index 0000000..bc985b8 --- /dev/null +++ b/bundleconfig/etc/rules/aai-event/entity-vce.groovy @@ -0,0 +1,94 @@ +/* + * ============LICENSE_START=================================================== + * Copyright (c) 2018 Amdocs + * ============================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END===================================================== + */ + +entity { + type 'vce' + validation { + useRule { + name 'prov-status' + attributes 'prov-status' + } + useRule { + name 'uppercase_alpha' + attributes 'vnf-name2' + } + useRule { + name 'vnf-name' + attributes 'vnf-name' + } + useRule { + name 'vnf-type' + attributes 'vnf-type' + } + useRule { + name 'vce.vpe-id' + attributes 'vpe-id' + } + useRule { + name 'valid_ipv4_addr' + attributes 'ipv4-oam-address' + } + useRule { name 'heat-stack-id' } + useRule { name 'vce is related to vserver and service and complex' } + useRule { name 'vce is related to an availability zone' } + useRule { + name 'heat-stack-id equals first 11 bytes of vnf-name' + attributes 'heat-stack-id', 'vnf-name' + } + } +} + +rule { + name 'uppercase_alpha' + category 'INVALID_NAME' + description 'naming convention is UPPERCASE (alphanumeric)' + errorText 'Invalid name - the attribute must be UPPERCASE (alphanumeric)' + severity 'MINOR' + attributes 'name' + validate 'name != null && name.matches("[A-Z,0-9, ]+")' +} + +rule { + name 'vce.vpe-id' + category 'INVALID_NAME' + description 'Naming convention must start with VPESAT and end with lowercase 401me6' + errorText 'Invalid name - attribute must start with VPESAT and end with lowercase 401me6' + severity 'MINOR' + attributes 'name' + validate 'name != null && name.matches("^VPESAT\\\\.*401me6")' +} + +rule { + name 'vce is related to vserver and service and complex' + category 'MISSING_REL' + description 'Validates that a vce is related to a vserver and service-instance and complex' + errorText 'Missing relationship - vce is not related to a vserver and service-instance and complex' + severity 'MAJOR' + attributes 'relationship-list.relationship[*].related-to' + validate 'related-to != null && related-to.contains("vserver") && related-to.contains("service-instance") && related-to.contains("complex")' +} + +rule { + name 'vce is related to an availability zone' + category 'MISSING_REL' + description 'Validates that a vce is related to an availability zone' + errorText 'Missing relationship - vce is not related to an availability zone' + severity 'MAJOR' + attributes 'relationship-list.relationship[*].related-to' + validate 'related-to != null && related-to.contains("availability-zone")' +} diff --git a/bundleconfig/etc/rules/aai-event/entity-vnfc.groovy b/bundleconfig/etc/rules/aai-event/entity-vnfc.groovy new file mode 100644 index 0000000..9a4300f --- /dev/null +++ b/bundleconfig/etc/rules/aai-event/entity-vnfc.groovy @@ -0,0 +1,27 @@ +/* + * ============LICENSE_START=================================================== + * Copyright (c) 2018 Amdocs + * ============================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END===================================================== + */ + +entity { + type 'vnfc' + validation { + useRule { + name 'prov-status' + attributes 'prov-status' + } + } +} diff --git a/bundleconfig/etc/rules/aai-event/entity-vpls-pe.groovy b/bundleconfig/etc/rules/aai-event/entity-vpls-pe.groovy new file mode 100644 index 0000000..30d8c92 --- /dev/null +++ b/bundleconfig/etc/rules/aai-event/entity-vpls-pe.groovy @@ -0,0 +1,27 @@ +/* + * ============LICENSE_START=================================================== + * Copyright (c) 2018 Amdocs + * ============================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END===================================================== + */ + +entity { + type 'vpls-pe' + validation { + useRule { + name 'prov-status' + attributes 'prov-status' + } + } +} diff --git a/bundleconfig/etc/rules/aai-event/entity-vserver.groovy b/bundleconfig/etc/rules/aai-event/entity-vserver.groovy new file mode 100644 index 0000000..f6b3471 --- /dev/null +++ b/bundleconfig/etc/rules/aai-event/entity-vserver.groovy @@ -0,0 +1,151 @@ +/* + * ============LICENSE_START=================================================== + * Copyright (c) 2018 Amdocs + * ============================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END===================================================== + */ + +entity { + type 'vserver' + validation { + useRule {name 'vserver is related to 0 or 1 image' } + useRule {name 'vserver is related to 0 or 1 flavor' } + useRule {name 'vserver is related to 1 pserver' } + useRule {name 'vserver is related to vpe and vserver-name matches naming convention' } + useRule {name 'vserver is related to vce and vserver-name matches naming convention' } + useRule { + name 'vserver related to TRINITY image and generic-vnf.vnf-name matches naming convention' + attributes 'relationship-list.relationship[*]' + } + useRule { + name 'vserver is related to a TRINITY image and vserver-name matches naming convention' + attributes 'relationship-list.relationship[*]', 'vserver-name' + } + useRule { + name 'vserver is related to a vnf (vce or newvce or vpe or generic-vnf)' + attributes 'relationship-list.relationship[*].related-to' + } + } +} + +rule { + name 'vserver related to TRINITY image and generic-vnf.vnf-name matches naming convention' + category 'INVALID_NAME' + description 'Validates that if vserver is related to an image named TRINITY, then the related generic-vnf name matches naming convention' + errorText 'Invalid name - if vserver is related to an image named TRINITY, then the related generic-vnf name must match xxxxnnnnv (where x = character and n = number)' + severity 'MINOR' + attributes 'relationships' + validate ''' + def getStringProperty = { jsonObject, propertyName -> jsonObject.get(propertyName)?.getAsString() } + + vnf_name = relationships.findAll { getStringProperty(it, "related-to") == "generic-vnf" } + .findAll { it."related-to-property" != null } + .collect { it."related-to-property".get(0) } + .find { getStringProperty(it, "property-key") == "generic-vnf.vnf-name" } + .findResult { getStringProperty(it, "property-value") } + + relatedToTrinity = relationships.findAll { getStringProperty(it, "related-to") == "image" } + .findAll { it."related-to-property" != null } + .collect { it."related-to-property".get(0) } + .findAll { getStringProperty(it, "property-key") == "image.image-name" } + .find { getStringProperty(it, "property-value")?.startsWith("TRINITY") } + + // If (and only if) related to TRINITY then check the generic-vnf name + return !relatedToTrinity || vnf_name?.matches("[a-z]{4}[0-9]{4}v") + ''' +} + +rule { + name 'vserver is related to a vnf (vce or newvce or vpe or generic-vnf)' + category 'MISSING_REL' + description 'Validates that a vserver is related to a vnf (vce or newvce or vpe or generic-vnf)' + errorText 'Missing relationship - a vserver must be related to a vnf (vce or newvce or vpe or generic-vnf)' + severity 'MINOR' + attributes 'related-to' + validate 'related-to != null && (related-to.contains("vce") || related-to.contains("newvce") || related-to.contains("vpe") || related-to.contains("generic-vnf"))' +} + +rule { + name 'vserver is related to 1 pserver' + category 'MISSING_REL' + description 'Validates that a vserver is related to 1 pserver (and not more than 1 pserver)' + errorText 'Missing relationship - vserver must be related to 1 pserver' + severity 'MINOR' + attributes 'relationship-list.relationship[*].related-to' + validate 'related-to != null && related-to.count("pserver") == 1' +} + +rule { + name 'vserver is related to 0 or 1 image' + category 'MISSING_REL' + description 'Validates that a vserver is either not related to an image or related to only 1 image' + errorText 'Missing relationship - vserver must be related to 0 or 1 image' + severity 'MINOR' + attributes 'relationship-list.relationship[*].related-to' + validate 'related-to == null || related-to.count("image") <= 1' +} + +rule { + name 'vserver is related to 0 or 1 flavor' + category 'MISSING_REL' + description 'Validates that a vserver is either not related to a flavor or related to only 1 flavor' + errorText 'Missing relationship - vserver must be related to 0 or 1 flavor' + severity 'MINOR' + attributes 'relationship-list.relationship[*].related-to' + validate 'related-to == null || related-to.count("flavor") <= 1' +} + +rule { + name 'vserver is related to vpe and vserver-name matches naming convention' + category 'INVALID_NAME' + description 'Validates that if a vserver is related to a vpe then vserver-name must contain me6' + errorText 'Invalid name - if vserver is related to vpe then vserver-name must contain me6' + severity 'MINOR' + attributes 'relationship-list.relationship[*].related-to', 'vserver-name' + validate '!related-to.contains("vpe") || vserver-name =~ "me6"' +} + +rule { + name 'vserver is related to vce and vserver-name matches naming convention' + category 'INVALID_NAME' + description 'Validates that if a vserver is related to a vce then vserver-name must match naming convention' + errorText 'Invalid name - if vserver is related to vce then vserver-name must match xxxxxxxxvbcnnceb (where x = alphanumeric and n = numeric)' + severity 'MINOR' + attributes 'relationship-list.relationship[*].related-to', 'vserver-name' + validate '!related-to.contains("vce") || vserver-name =~ "[a-z0-9]{8}vbc[0-9]{2}ceb"' +} + + + +rule { + name 'vserver is related to a TRINITY image and vserver-name matches naming convention' + category 'INVALID_NAME' + description 'Validates that if vserver is related to an image named TRINITY, then the vserver name matches naming convention' + errorText 'Invalid name - if vserver is related to an image named TRINITY, then the vserver name must match xxxxnnnnvmnnn (where x = character and n = number)' + severity 'MINOR' + attributes 'relationships', 'vservername' + validate ''' + def getStringProperty = { jsonObject, propertyName -> jsonObject.get(propertyName)?.getAsString() } + + relatedToTrinity = relationships.findAll { getStringProperty(it, "related-to") == "image" } + .findAll { it."related-to-property" != null } + .collect { it."related-to-property".get(0) } + .findAll { getStringProperty(it, "property-key") == "image.image-name" } + .find { getStringProperty(it, "property-value").startsWith("TRINITY") } + + // If (and only if) related to TRINITY then check the vserver name + return !relatedToTrinity || vservername != null && vservername ==~ "[a-z]{4}[0-9]{4}vm[0-9]{3}" + ''' +} + diff --git a/bundleconfig/etc/rules/gizmo-event/common_rules.groovy b/bundleconfig/etc/rules/gizmo-event/common_rules.groovy new file mode 100644 index 0000000..b30816e --- /dev/null +++ b/bundleconfig/etc/rules/gizmo-event/common_rules.groovy @@ -0,0 +1,27 @@ +/* + * ============LICENSE_START=================================================== + * Copyright (c) 2018 Amdocs + * ============================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END===================================================== + */ + +rule { + name 'valid_ipv4_addr' + category 'INVALID_VALUE' + description 'Validate an IPv4 address' + errorText 'Invalid value - attribute is not a valid IPv4 address' + severity 'MINOR' + attributes 'ipaddr' + validate 'ipaddr != null && ipaddr.matches("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])")' +} diff --git a/bundleconfig/etc/rules/gizmo-event/pserver-rules.groovy b/bundleconfig/etc/rules/gizmo-event/pserver-rules.groovy new file mode 100644 index 0000000..79b3cc2 --- /dev/null +++ b/bundleconfig/etc/rules/gizmo-event/pserver-rules.groovy @@ -0,0 +1,27 @@ +/* + * ============LICENSE_START=================================================== + * Copyright (c) 2018 Amdocs + * ============================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END===================================================== + */ + +entity { + type 'pserver' + validation { + useRule { + name 'valid_ipv4_addr' + attributes 'vertex.properties.ipv4-oam-address' + } + } +} diff --git a/bundleconfig/etc/rules/poa-event/default-rules.groovy b/bundleconfig/etc/rules/poa-event/default-rules.groovy new file mode 100644 index 0000000..8397abd --- /dev/null +++ b/bundleconfig/etc/rules/poa-event/default-rules.groovy @@ -0,0 +1,168 @@ +/* + * ============LICENSE_START=================================================== + * Copyright (c) 2018 Amdocs + * ============================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END===================================================== + */ + +entity { + name 'POA-EVENT' + indexing { + indices 'default-rules' + } + validation { + useRule { + name 'Verify AAI nf-naming-code' + attributes 'context-list.aai.vf-list[*]' + } + useRule { + name 'port-mirroring-AAI-has-valid-vnfc' + attributes 'context-list.sdc.vf-list[*]', 'context-list.aai.vf-list[*]' + } + useRule { + name 'port-mirroring-SDC-vnfc-types-missing' + attributes 'context-list.sdc.vf-list[*]', 'context-list.aai.vf-list[*]' + } + useRule { + name 'port-mirroring-AAI-vnfc-type-exists-in-SDC-SUCCESS' + attributes 'context-list.sdc.vf-list[*]', 'context-list.aai.vf-list[*]' + } + } +} + +rule { + name 'Verify AAI nf-naming-code' + category 'INVALID_VALUE' + description 'Validate that nf-naming-code exists and is populated in AAI VNF instance' + errorText 'The nf-naming-code is not populated in AAI VNF instance' + severity 'CRITICAL' + attributes 'vfList' + validate ''' + def parsed = new groovy.json.JsonSlurper().parseText(vfList.toString()) + for (vf in parsed) { + String nfNamingCode = vf."nf-naming-code" + if (nfNamingCode == null || nfNamingCode.equals("")) { + return false + } + } + return true + ''' +} + +rule { + name 'port-mirroring-AAI-has-valid-vnfc' + category 'INVALID_VALUE' + description 'Validate that each VNFC instance in AAI conforms to a VNFC type defined in SDC model' + errorText 'AAI VNFC instance includes non-specified type in design SDC model' + severity 'ERROR' + attributes 'sdcVfList', 'aaiVfList' + validate ''' + def slurper = new groovy.json.JsonSlurper() + def parsedSdc = slurper.parseText(sdcVfList.toString()) + def parsedAai = slurper.parseText(aaiVfList.toString()) + + // gather all SDC nfc-naming-codes + List sdcNfcNamingCodeList = new ArrayList<>() + parsedSdc.each { + for(sdcVnfc in it.vnfc) { + String sdcNfcNamingCode = sdcVnfc."nfc-naming-code" + if(sdcNfcNamingCode != null) { + sdcNfcNamingCodeList.add(sdcNfcNamingCode) + } + } + } + + // check that all SDC nfc-naming-codes exist in AAI + parsedAai.each { + for(aaiVnfc in it.vnfc) { + String aaiNfcNamingCode = aaiVnfc."nfc-naming-code" + if(aaiNfcNamingCode != null) { + if(!sdcNfcNamingCodeList.contains(aaiNfcNamingCode)) { + return false + } + } + } + } + return true + ''' +} + + +rule { + name 'port-mirroring-SDC-vnfc-types-missing' + category 'INVALID_VALUE' + description 'Validate that each VNFC type specified in SDC model exists in AAI' + errorText 'Design has specified types but not all of them exist in AAI' + severity 'WARNING' + attributes 'sdcVfList', 'aaiVfList' + validate ''' + def getNfcNamingCodeSet = { parsedEntity -> + Set namingCodeSet = new HashSet<>() + parsedEntity.each { + for(vnfcItem in it."vnfc") { + println "vnfc: " + vnfcItem + String namingCode = vnfcItem."nfc-naming-code" + if(namingCode != null) { + namingCodeSet.add(namingCode) + } + } + } + return namingCodeSet + } + + // gather all unique nfc-naming-codes from AAI and SDC + def slurper = new groovy.json.JsonSlurper() + def aaiNfcNamingCodeSet = getNfcNamingCodeSet(slurper.parseText(aaiVfList.toString())) as java.util.HashSet + def sdcNfcNamingCodeSet = getNfcNamingCodeSet(slurper.parseText(sdcVfList.toString())) as java.util.HashSet + + println "AAI: " + aaiNfcNamingCodeSet + println "SDC: " + sdcNfcNamingCodeSet + + // check that all nfc-naming-codes in SDC exist in AAI + return aaiNfcNamingCodeSet.containsAll(sdcNfcNamingCodeSet) + ''' +} + + +rule { + name 'port-mirroring-AAI-vnfc-type-exists-in-SDC-SUCCESS' + category 'SUCCESS' + description 'Verify that every vnfc in sdc has been created in AAI' + errorText 'Every vnfc type specified in sdc has been created in AAI' + severity 'INFO' + attributes 'sdcVfList', 'aaiVfList' + validate ''' + def getNfcNamingCodeSet = { parsedEntity -> + Set namingCodeSet = new HashSet<>() + parsedEntity.each { + for(vnfcItem in it."vnfc") { + String namingCode = vnfcItem."nfc-naming-code" + if(namingCode != null) { + namingCodeSet.add(namingCode) + } + } + } + return namingCodeSet + } + + // gather all unique nfc-naming-codes from AAI and SDC + def slurper = new groovy.json.JsonSlurper() + def aaiNfcNamingCodeSet = getNfcNamingCodeSet(slurper.parseText(aaiVfList.toString())) as java.util.HashSet + def sdcNfcNamingCodeSet = getNfcNamingCodeSet(slurper.parseText(sdcVfList.toString())) as java.util.HashSet + + // check that all nfc-naming-codes in SDC exist in AAI + // return false if all SDC naming codes exist in AAI to trigger an INFO violation + return !aaiNfcNamingCodeSet.containsAll(sdcNfcNamingCodeSet) + ''' +} diff --git a/bundleconfig/etc/rules/spike-event/common_rules.groovy b/bundleconfig/etc/rules/spike-event/common_rules.groovy new file mode 100644 index 0000000..b30816e --- /dev/null +++ b/bundleconfig/etc/rules/spike-event/common_rules.groovy @@ -0,0 +1,27 @@ +/* + * ============LICENSE_START=================================================== + * Copyright (c) 2018 Amdocs + * ============================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END===================================================== + */ + +rule { + name 'valid_ipv4_addr' + category 'INVALID_VALUE' + description 'Validate an IPv4 address' + errorText 'Invalid value - attribute is not a valid IPv4 address' + severity 'MINOR' + attributes 'ipaddr' + validate 'ipaddr != null && ipaddr.matches("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])")' +} diff --git a/bundleconfig/etc/rules/spike-event/pserver-rules.groovy b/bundleconfig/etc/rules/spike-event/pserver-rules.groovy new file mode 100644 index 0000000..79b3cc2 --- /dev/null +++ b/bundleconfig/etc/rules/spike-event/pserver-rules.groovy @@ -0,0 +1,27 @@ +/* + * ============LICENSE_START=================================================== + * Copyright (c) 2018 Amdocs + * ============================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END===================================================== + */ + +entity { + type 'pserver' + validation { + useRule { + name 'valid_ipv4_addr' + attributes 'vertex.properties.ipv4-oam-address' + } + } +} -- cgit 1.2.3-korg