From: A H Date: Thu, 29 Oct 2015 06:18:01 +0000 (-0700) Subject: Adding nemo engine. X-Git-Tag: release/beryllium~136 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=7eee61442224fc764eab663569c41faacf0c3eff;p=nemo.git Adding nemo engine. Change-Id: I5f959c18bfaa11ff1db7f1b34b3840e836ed7cf5 Signed-off-by: A H --- diff --git a/diff.log b/diff.log new file mode 100644 index 0000000..0737906 --- /dev/null +++ b/diff.log @@ -0,0 +1,2794 @@ +diff --git a/nemo-api/src/main/yang/nemo-common.yang b/nemo-api/src/main/yang/nemo-common.yang +index cbccc32..072745f 100644 +--- a/nemo-api/src/main/yang/nemo-common.yang ++++ b/nemo-api/src/main/yang/nemo-common.yang +@@ -1,32 +1,37 @@ + /* +- * Copyright (c) 2015 Huawei Technologies Co., Ltd. and others. All rights reserved. ++ * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +-module nemo-common{ +- yang-version 1; +- namespace "urn:opendaylight:params:xml:ns:yang:nemo:common"; +- prefix "nemo-common"; +- +- revision "2015-06-29" { ++module nemo-common { ++ yang-version 1; ++ ++ namespace "urn:opendaylight:params:xml:ns:yang:nemo:common"; ++ prefix "nemo-common"; ++ ++ description ++ "Common types and definitions for NEMO models"; ++ ++ revision "2015-10-10" { + description + "Initial revision."; + } +- +- /********************** +- * Base types +- **********************/ +- typedef description { +- description "A human-readable description for a object."; ++ ++ // ********************* ++ // * Base Types ++ // ********************* ++ typedef description { ++ description ++ "A human-readable description for a object."; + type string { + length "1..4096"; + } + } +- +- typedef name { ++ ++ typedef name { + description + "A generic string name type. Must start with a letter"; + type string { +@@ -34,8 +39,8 @@ module nemo-common{ + length "1..256"; + } + } +- +- // UUID type from ietf-yang-types@2013-07-15 ++ ++ // UUID type from ietf-yang-types@2013-07-15 + typedef uuid { + type string { + pattern '[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-' +@@ -43,8 +48,8 @@ module nemo-common{ + } + description + "A Universally Unique IDentifier in the string representation +- defined in RFC 4122. The canonical representation uses +- lowercase characters. ++ defined in RFC 4122. The canonical representation uses ++ lower case characters. + + The following is an example of a UUID in string + representation: f81d4fae-7dec-11d0-a765-00a0c91e6bf6"; +@@ -54,265 +59,179 @@ module nemo-common{ + } + + typedef unique-id { ++ description ++ "A globally unique identifier."; + type uuid; +- description "A globally unique identifier"; + } +- +- /********************* +- * Unique IDs +- *********************/ +- typedef object-id { ++ ++ // ********************* ++ // * Unique IDs ++ // ********************* ++ typedef object-id { ++ description ++ "A unique ID for a parameterized object."; + type unique-id; +- description "A unique ID for a parameterized object"; + } +- +- typedef node-definition-id { +- type object-id; +- description "A unique ID for a node definition."; +- } +- typedef node-instance-id { +- type object-id; +- description "A unique ID for a node instance."; +- } +- +- typedef connection-definition-id { ++ ++ typedef node-id { ++ description ++ "A unique ID for a node."; + type object-id; +- description "A unique ID for a connection definition."; + } +- typedef connection-instance-id { +- type object-id; +- description "A unique ID for a connection instance."; +- } +- +- typedef flow-definition-id { ++ ++ typedef connection-id { ++ description ++ "A unique ID for a connection."; + type object-id; +- description "A unique ID for a flow definition."; + } +- typedef flow-instance-id { ++ ++ typedef flow-id { ++ description ++ "A unique ID for a flow."; + type object-id; +- description "A unique ID for a flow instance."; + } +- +- typedef expected-definition-id { ++ ++ typedef intent-id { ++ description ++ "A unique ID for an intent."; + type unique-id; +- description "A unique ID for an expected definition."; + } +- typedef expected-instance-id { ++ ++ typedef user-id { ++ description ++ "A unique ID for a user."; + type unique-id; +- description "A unique ID for an expected instance."; + } +- +- typedef avoid-definition-id { ++ ++ typedef operation-id { ++ description ++ "A unique ID for an operation."; + type unique-id; +- description "A unique ID for an avoid definition."; + } +- typedef avoid-instance-id { +- type unique-id; +- description "A unique ID for an avoid instance."; +- } +- +- typedef context-id { +- type unique-id; +- description "A unique ID for a context."; +- } +- +- typedef intent-id { ++ ++ typedef condition-segment-id { ++ description ++ "A unique ID for a segment of the condition in an operation."; + type unique-id; +- description "A unique ID for an intent."; + } +- +- typedef user-id { ++ ++ typedef query-condition-id { ++ description ++ "A unique ID for a condition of the advanced query."; + type unique-id; +- description "A unique ID for a user."; +- } +- +- +- +- /********************* +- * names +- *********************/ +- typedef object-name { ++ } ++ ++ // ********************* ++ // * Names ++ // ********************* ++ typedef object-name { ++ description ++ "A name for a parameterized object"; + type name; +- description "A name for a parameterized object"; + } +- +- typedef node-instance-name { ++ ++ typedef node-name { ++ description ++ "A name for a node instance."; + type object-name; +- description "A name for a node instance."; +- } +- +- typedef connection-instance-name { ++ } ++ ++ typedef connection-name { ++ description ++ "A name for a connection instance."; + type object-name; +- description "A name for a connection instance."; +- } +- +- typedef flow-instance-name { ++ } ++ ++ typedef flow-name { ++ description ++ "A name for a flow instance."; + type object-name; +- description "A name for a flow instance."; +- } +- +- typedef node-property-name { +- type name; +- description "A name for a node property."; +- } +- +- typedef connection-property-name { ++ } ++ ++ typedef match-item-name { ++ description ++ "A name for a match item."; + type name; +- description "A name for a connection property."; +- } ++ } + +- typedef match-item-name { ++ typedef property-name { ++ description ++ "A name for a property."; + type name; +- description "A name for a flow match item."; + } +- +- typedef property-name { ++ ++ typedef parameter-name { ++ description ++ "A name for a parameter."; + type name; +- description "A name for a property."; + } +- +- typedef parameter-name { ++ ++ typedef action-name { ++ description ++ "A name for an action."; + type name; +- description "A name for a parameter."; + } +- +- typedef action-definition-name { ++ ++ typedef condition-parameter-name { ++ description ++ "A name for a parameter of condition."; + type name; +- description "A name for an action definition."; +- } +- typedef action-instance-name { ++ } ++ ++ typedef user-name { ++ description ++ "A name for a user."; + type name; +- description "A name for an action instance."; +- } +- typedef condition-definition-name { ++ } ++ ++ typedef user-password { ++ description ++ "A password for a user."; + type name; +- description "A name for a condition definition."; +- } +- typedef condition-instance-name { +- type name; +- description "A name for a condition instance."; +- } +- typedef condition-parameter-name { +- type name; +- description "A name for a condition parameter."; +- } +- typedef constraint-definition-name { ++ } ++ ++ typedef operation-name { ++ description ++ "A name for an operation."; + type name; +- description "A name for a constraint definition."; +- } +- typedef constraint-instance-name { +- type name; +- description "A name for a constraint instance."; +- } +- typedef constraint-parameter-name { +- type name; +- description "A name for a constraint parameter."; +- } +- +- +- typedef data-name { +- type name; +- description "A name for an action data."; +- } +- +- typedef context-name { +- type name; +- description "A name for an context"; +- } +- +- typedef intent-name { ++ } ++ ++ typedef query-condition-name { ++ description ++ "A name for a query with condition."; + type name; +- description "A name for an intent."; + } +- typedef user-name { ++ ++ typedef user-role-name { ++ description ++ "A role name for a user."; + type name; +- description "A name for a user."; + } +- typedef expected-instance-name { ++ ++ typedef user-role-description { ++ description ++ "It describes the role characteristic and responsibility range."; ++ type string; ++ } ++ ++ // ********************* ++ // * Types ++ // ********************* ++ typedef node-type { ++ description ++ "The type for a node."; + type name; +- description "A name for an expected instance."; + } +- typedef avoid-instance-name { ++ ++ typedef connection-type { ++ description ++ "The type for a connection."; + type name; +- description "A name for an avoid instance."; +- } +- +- +- +- /********************* +- * types +- *********************/ +- typedef node-definition-type { +- type name; +- description "A type for a node."; +- } +- typedef connection-definition-type { +- type name; +- description "A type for a connection."; +- } +- typedef flow-definition-type { +- type name; +- description "A type for a flow."; +- } +- typedef node-instance-type { +- type name; +- description "A type for a node instance."; +- } +- typedef connection-instance-type { +- type name; +- description "A type for a connection instance."; +- } +- typedef flow-instance-type { +- type name; +- description "A type for a flow instance."; +- } ++ } + ++ typedef flow-type { ++ description ++ "The type for a flow."; ++ type name; ++ } + } +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +\ No newline at end of file +diff --git a/nemo-api/src/main/yang/nemo-intent.yang b/nemo-api/src/main/yang/nemo-intent.yang +index 21760a0..91876aa 100644 +--- a/nemo-api/src/main/yang/nemo-intent.yang ++++ b/nemo-api/src/main/yang/nemo-intent.yang +@@ -1,136 +1,395 @@ + /* +- * Copyright (c) 2015 Huawei Technologies Co., Ltd. and others. All rights reserved. ++ * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +- ++ + module nemo-intent { +- yang-version 1; +- namespace "urn:opendaylight:params:xml:ns:yang:nemo:intent"; +- prefix "nemo-intent"; +- +- import nemo-common {prefix nemo-common;} +- import nemo-object {prefix nemo-object;} +- import nemo-operation {prefix nemo-operation;} +- import nemo-result {prefix nemo-result;} +- +- revision "2015-06-29" { ++ yang-version 1; ++ ++ namespace "urn:opendaylight:params:xml:ns:yang:nemo:intent"; ++ prefix "nemo-intent"; ++ ++ import nemo-common {prefix nemo-common;} ++ import nemo-object {prefix nemo-object;} ++ import nemo-operation {prefix nemo-operation;} ++ import nemo-user {prefix nemo-user;} ++ ++ revision "2015-10-10" { + description + "Initial revision."; + } +- +- grouping intent-instance { +- description ""; +- leaf intent-id { +- description "A unique ID for the intent"; +- type nemo-common:intent-id; +- mandatory true; +- } +- leaf intent-name { +- description "A user-visible name for the intent"; +- type nemo-common:intent-name; +- } +- container objects { +- description ""; +- list node { +- key "node-id"; +- uses nemo-object:node-instance; +- } +- list connection { +- key "connection-id"; +- uses nemo-object:connection-instance; +- } +- list flow { +- key "flow-id"; +- uses nemo-object:flow-instance; +- } +- } +- +- container operation { +- leaf apply-on-object { +- type nemo-common:object-id; +- mandatory true; +- } +- leaf priority{ +- type int64; +- default 1; +- } +- uses nemo-operation:condition-instance; +- uses nemo-operation:action-instance; +- uses nemo-operation:constraint-instance; +- } +- +- container result{ +- leaf result-to-object { +- type nemo-common:object-id; +- mandatory true; +- } +- leaf priority{ +- type int64; +- default 1; +- } +- choice result-mode { +- mandatory true; +- case expected-case { +- uses nemo-result:expected-instance; +- } +- case avoid-case{ +- uses nemo-result:avoid-instance; +- } +- } +- } +- container contexts{ +- list context { +- key "context-id"; +- leaf context-id { +- type nemo-common:context-id; +- mandatory true; +- } +- leaf context-name{ +- type nemo-common:context-name; +- mandatory true; +- } +- } +- } +- } +- +- container users { +- description "The list of all known users"; +- list user { +- description ""; ++ ++ grouping user-intent { ++ description ++ "User intent refers to a purpose in getting an ultimate result ++ or performing some specific operation on some objects."; ++ ++ container objects { ++ description ++ "The element could be operated and managed by users. ++ It inludes resources to construct users' virtual network, ++ and the services in this network.In NEMO project, it is ++ abstracted into node, connection and flow"; ++ ++ list node { ++ key "node-id"; ++ uses nemo-object:node-instance; ++ } ++ ++ list connection { ++ key "connection-id"; ++ uses nemo-object:connection-instance; ++ } ++ ++ list flow { ++ key "flow-id"; ++ uses nemo-object:flow-instance; ++ } ++ } ++ ++ container operations { ++ description ++ "The operation is to dynamically adjust the behavior of network, ++ and it is applied on objects, that is, node, connection and flow"; ++ ++ list operation { ++ key "operation-id"; ++ uses nemo-operation:operation-instance; ++ } ++ } ++ ++ container results { ++ // TBD ++ } ++ } ++ ++ container users { ++ description ++ "The list of all known users"; ++ ++ list user { ++ description ++ "A user is an administrative domain which is ++ logically separated from other users, and each ++ intent is specified by a particular user."; ++ + key "user-id"; +- leaf user-id { +- description "A unique ID for the user"; +- type nemo-common:user-id; +- mandatory true; +- } +- leaf user-name { +- description "A user-visible name for the user"; +- type nemo-common:user-name; +- mandatory false; +- } +- list intent{ +- key "intent-id"; +- uses intent-instance; +- min-elements 1; +- } +- } +- } +- +- rpc register-node-instance { +- description ""; +- input { +- uses nemo-object:node-instance; +- } +- } +- +- rpc unregister-node-instance { +- description ""; +- input { +- uses nemo-object:node-instance; +- } +- } +- +-} +\ No newline at end of file ++ uses nemo-user:user-instance; ++ uses user-intent; ++ } ++ } ++ ++ container query-condition-definitions { ++ description ++ "Contains the definitions for all advanced query, which means ++ they are the query with conditions supported by the NEMO engine. ++ User will fetch all results which meet the condition."; ++ ++ list query-condition-definition { ++ description ++ "Define the query with condition. For example, user may ++ intent to query all connection's name whose utilization is ++ beyond 80%. That is a query with condition."; ++ ++ key "query-condition-name query-intent-type"; ++ leaf query-condition-name { ++ description ++ "A user-visible name for the query condition definition. ++ The query condition name is usually to specify the ++ attribute or property of some kind of intent. ++ For the above example, the query-condition-name is utility."; ++ type nemo-common:query-condition-name; ++ mandatory true; ++ } ++ ++ leaf query-intent-type { ++ description ++ "The target for the query, and its attributes will be checked out ++ if meet the condition. In the above example, connection is the ++ target. So, connection will be the query-intent-type here."; ++ type enumeration { ++ enum node; ++ enum connection; ++ enum flow; ++ enum operation; ++ enum result; ++ } ++ } ++ ++ leaf query-condition-value-type { ++ description ++ "The type of the target value for the query condition. ++ For the above example, the target-value is 80(%), ++ so the query-condition-value-type will be int."; ++ default string; ++ type enumeration { ++ enum string { ++ description ++ "A string-valued target value."; ++ } ++ enum int { ++ description ++ "An integer-valued target value."; ++ } ++ enum range { ++ description ++ "An integer-range target value."; ++ } ++ } ++ } ++ ++ container query-condition-match-patterns { ++ description ++ "The relationship between the value of query-condition-name ++ and query-condition-target-value. If an intent's attribute ++ or property specified by the query condition name matches ++ to the target value by the match pattern, this intent meets ++ the condition. For the above example, the condition's ++ query-condition-match-patterns could be less-than, not-less-than, ++ equal, not-equal, greater-than, not-greater-than, between."; ++ ++ leaf-list query-condition-match-pattern { ++ type enumeration { ++ enum less-than; ++ enum not-less-than; ++ enum equal; ++ enum not-equal; ++ enum greater-than; ++ enum not-greater-than; ++ enum between; ++ } ++ } ++ } ++ } ++ } ++ ++ grouping common-rpc-result { ++ description ++ "Common return result for all defined RPCs."; ++ ++ leaf result-code { ++ description ++ "Result code which is convenient for processing in a program."; ++ type enumeration { ++ enum ok { ++ description ++ "The invoked RPC was executed successfully"; ++ } ++ enum error { ++ description ++ "There's an error while executing the RPC"; ++ } ++ } ++ } ++ ++ leaf message { ++ description ++ "A human-readable message for an error or exception"; ++ type string; ++ } ++ } ++ ++ grouping query-condition-instance { ++ description ++ "A query condition instance generated according to ++ a specified query condition definition."; ++ ++ leaf query-condition-id { ++ description ++ "A unique ID for a query condition instance."; ++ type nemo-common:query-condition-id; ++ mandatory true; ++ } ++ ++ leaf query-condition-name { ++ description ++ "The name of the query condition definition."; ++ type nemo-common:query-condition-name; ++ mandatory true; ++ } ++ ++ leaf query-intent-type { ++ description ++ "The type of the intents that the user wants to query from through ++ the condition instance."; ++ type enumeration { ++ enum node; ++ enum connection; ++ enum flow; ++ enum operation; ++ enum result; ++ } ++ } ++ ++ leaf query-condition-match-pattern { ++ description ++ "The match pattern the condition instance will use."; ++ type enumeration { ++ enum less-than; ++ enum not-less-than; ++ enum equal; ++ enum not-equal; ++ enum greater-than; ++ enum not-greater-than; ++ enum between; ++ } ++ } ++ ++ container query-condition-target-value { ++ description ++ "The target value used to compare with the attribute ++ or property of the intents."; ++ ++ leaf string-value { ++ type string; ++ } ++ ++ leaf int-value { ++ type int64; ++ } ++ ++ container range-value { ++ leaf min { ++ type int64; ++ mandatory true; ++ } ++ ++ leaf max { ++ type int64; ++ mandatory true; ++ } ++ } ++ } ++ } ++ ++ rpc register-user { ++ description ++ "Register a user to the user repository."; ++ ++ input { ++ uses nemo-user:user-instance; ++ } ++ ++ output { ++ uses common-rpc-result; ++ } ++ } ++ ++ rpc begin-transaction { ++ description ++ "Begin a transaction for the user"; ++ ++ input { ++ uses nemo-user:user-instance; ++ } ++ ++ output { ++ uses common-rpc-result; ++ } ++ } ++ ++ rpc end-transaction { ++ description ++ "Commit the user's current transaction"; ++ ++ input { ++ uses nemo-user:user-instance; ++ } ++ ++ output { ++ uses common-rpc-result; ++ } ++ } ++ ++ rpc language-style-nemo-request { ++ description ++ "Create, update or delete an intent of a user through an NEMO statement"; ++ ++ input { ++ uses nemo-user:user-instance; ++ ++ leaf nemo-statement { ++ type string; ++ } ++ } ++ ++ output { ++ uses common-rpc-result; ++ } ++ } ++ ++ rpc structure-style-nemo-update { ++ description ++ "Create or update all or a part of the user's intents, ++ which are described as json or xml format."; ++ ++ input { ++ uses nemo-user:user-instance; ++ uses user-intent; ++ } ++ ++ output { ++ uses common-rpc-result; ++ } ++ } ++ ++ rpc structure-style-nemo-delete { ++ description ++ "Delete some intents of a user from the user repository"; ++ ++ input { ++ uses nemo-user:user-instance; ++ ++ container objects { ++ leaf-list node { ++ type nemo-common:node-id; ++ } ++ ++ leaf-list connection { ++ type nemo-common:connection-id; ++ } ++ ++ leaf-list flow { ++ type nemo-common:flow-id; ++ } ++ } ++ ++ container operations { ++ leaf-list operation { ++ type nemo-common:operation-id; ++ } ++ } ++ ++ container results { ++ // TBD ++ } ++ } ++ ++ output { ++ uses common-rpc-result; ++ } ++ } ++ ++ rpc advanced-nemo-query { ++ description ++ "Query some intents of a user from the user repository ++ according to several advanced query conditions."; ++ ++ input { ++ uses nemo-user:user-instance; ++ ++ list query-condition { ++ key "query-condition-id"; ++ uses query-condition-instance; ++ } ++ } ++ ++ output { ++ uses common-rpc-result; ++ uses user-intent; ++ } ++ } ++} +diff --git a/nemo-api/src/main/yang/nemo-object.yang b/nemo-api/src/main/yang/nemo-object.yang +index 30500fd..347406d 100644 +--- a/nemo-api/src/main/yang/nemo-object.yang ++++ b/nemo-api/src/main/yang/nemo-object.yang +@@ -1,331 +1,405 @@ + /* +- * Copyright (c) 2015 Huawei Technologies Co., Ltd. and others. All rights reserved. ++ * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +-module nemo-object{ +- yang-version 1; +- namespace "urn:opendaylight:params:xml:ns:yang:nemo:object"; +- prefix "nemo-object"; +- +- import nemo-common {prefix nemo-common;} +- +- revision "2015-06-29" { ++module nemo-object { ++ yang-version 1; ++ ++ namespace "urn:opendaylight:params:xml:ns:yang:nemo:object"; ++ prefix "nemo-object"; ++ ++ import nemo-common {prefix nemo-common;} ++ ++ revision "2015-10-10" { + description + "Initial revision."; + } +- +- grouping property-definition { +- list property { +- description ""; +- key "name"; +- leaf name { +- description "A user-visible name for the property"; ++ ++ grouping property-definitions { ++ list property-definition { ++ description ++ "The property definitions for the type of node or connection."; ++ ++ key "property-name"; ++ leaf property-name { ++ description ++ "A user-visible and unique name for the property."; + type nemo-common:property-name; + mandatory true; + } +- leaf value-type { +- description "The type of the property"; ++ ++ leaf property-value-type { ++ description ++ "The type of the property value."; + default string; + type enumeration { + enum string { +- description "A string-valued property"; ++ description ++ "An string-valued property."; + } + enum int { +- description "An integer-valued property"; ++ description ++ "An integer-valued property."; + } + enum range { +- description "An integer-range property"; ++ description ++ "An integer-range property."; + } + } + } ++ + leaf is-required { +- description "Specify whether the property is +- required for object."; ++ description ++ "Specify whether the property is required for the object."; + default optional; + type enumeration { + enum required { +- description "The property is required"; ++ description ++ "The property is required"; + } + enum optional { +- description "The property is optional"; ++ description ++ "The property is optional"; + } + } + } +- } +- } +- container node-definitions{ +- list node-definition{ +- description ""; +- key "id"; +- leaf id { +- description "A unique ID for a kind of node definition"; +- type nemo-common:node-definition-id; +- mandatory true; +- } +- leaf node-type{ +- description "A user-readable description"; +- type nemo-common:node-definition-type; +- mandatory true; +- } +- uses property-definition; +- } +- } +- container connection-definitions{ +- list connection-definition{ +- key "id"; +- leaf id { +- description "A unique ID for a kind of connection definition"; +- type nemo-common:connection-definition-id; +- mandatory true; +- } +- leaf connection-type{ +- description "A user-readable description"; +- type nemo-common:connection-definition-type; +- mandatory true; +- } +- uses property-definition; +- } +- } +- +- +- grouping match-item-definition{ +- +- list match-item { +- description ""; +- key "name"; +- leaf name { +- description "A user-visible name for the match-item"; ++ ++ leaf is-read-only { ++ description ++ "Specify whether the property is read-only for object."; ++ default write-read; ++ type enumeration { ++ enum write-read { ++ description ++ "The property can be read and written."; ++ } ++ enum read-only { ++ description ++ "The property is read-only."; ++ } ++ } ++ } ++ } ++ } ++ ++ container node-definitions { ++ list node-definition { ++ description ++ "Define new node model/type which can be used in other places, ++ and include node type name and its property."; ++ ++ key "node-type"; ++ leaf node-type { ++ description ++ "A user-visible and unique identifier for the node type."; ++ type nemo-common:node-type; ++ mandatory true; ++ } ++ ++ uses property-definitions; ++ } ++ } ++ ++ container connection-definitions { ++ list connection-definition { ++ description ++ "Define new connection model/type which can be used in other places, ++ and include connection type name and its property."; ++ ++ key "connection-type"; ++ leaf connection-type { ++ description ++ "A user-visible and unique identifier for the connection type."; ++ type nemo-common:connection-type; ++ mandatory true; ++ } ++ ++ uses property-definitions; ++ } ++ } ++ ++ container match-item-definitions { ++ list match-item-definition { ++ description ++ "Define the match item which uses to match the flow."; ++ ++ key "match-item-name"; ++ leaf match-item-name { ++ description ++ "A user-visible and unique name for the match item."; + type nemo-common:match-item-name; + mandatory true; + } +- leaf value-type { +- description "The type of the match item"; ++ ++ leaf match-item-value-type { ++ description ++ "The value type of the match item."; + default string; + type enumeration { + enum string { +- description "A string-valued match item"; ++ description ++ "A string-valued match item."; + } + enum int { +- description "An integer-valued match item"; ++ description ++ "An integer-valued match item."; + } + enum range { +- description "An integer-range match item"; ++ description ++ "An integer-range match item."; + } + } + } +- leaf is-required { +- description "Specify whether the match item is required +- for the flow."; +- default optional; +- type enumeration { +- enum required { +- description "The match item is required"; +- } +- enum optional { +- description "The match item is optional"; +- } ++ } ++ } ++ ++ container flow-property-definitions { ++ description ++ "Contains the property definitions for the flow."; ++ ++ uses property-definitions; ++ } ++ ++ grouping property-instance { ++ description ++ "The property instance and its associated metadata."; ++ ++ leaf property-name { ++ description ++ "The name for the property which can be seen as a unique ++ identifier of the property."; ++ type nemo-common:property-name; ++ mandatory true; ++ } ++ ++ container property-values { ++ description ++ "The value list of the property."; ++ ++ list string-value { ++ key "value order"; ++ leaf value { ++ type string; ++ } ++ ++ leaf order { ++ type uint32; + } + } +- } +- } +- container flow-definitions{ +- list flow-definition{ +- key "id"; +- leaf id { +- description "A unique ID for a kind of flow definition"; +- type nemo-common:flow-definition-id; +- mandatory true; +- } +- leaf flow-type{ +- description "A user-readable description"; +- type nemo-common:flow-definition-type; +- mandatory true; +- } +- uses match-item-definition; +- } +- } +- +- grouping node-property-instance{ +- list property { +- key "name"; +- leaf name { +- type nemo-common:node-property-name; +- mandatory true; +- } +- leaf string-value { +- type string; +- } +- leaf int-value { +- type int64; +- } +- container range-value { +- leaf min { ++ ++ list int-value { ++ key "value order"; ++ leaf value { + type int64; +- mandatory true; + } +- leaf max { +- type int64; +- mandatory true; ++ ++ leaf order { ++ type uint32; + } + } +- } +- } +- grouping node-instance{ +- description ""; +- leaf node-id { +- description "A unique ID for the node instance"; +- type nemo-common:node-instance-id; +- mandatory true; +- } +- leaf node-name { +- description +- "A user-visible name for the node definition"; +- type nemo-common:node-instance-name; +- } +- leaf node-type { +- type nemo-common:node-instance-type; +- mandatory true; +- } +- container subnodes{ +- leaf-list subnode-id{ +- type nemo-common:node-instance-id; +- } +- } +- container property{ +- uses node-property-instance; +- } +- } +- +- grouping connection-property-instance{ +- list property { +- key "name"; +- leaf name { +- type nemo-common:connection-property-name; +- mandatory true; +- } +- leaf string-value { +- type string; +- } +- leaf int-value { +- type int64; +- } ++ + container range-value { + leaf min { + type int64; + mandatory true; + } ++ + leaf max { + type int64; + mandatory true; + } + } +- } +- } +- grouping connection-instance { +- description ""; +- leaf connection-id { +- description "A unique ID for the connection instance"; +- type nemo-common:connection-instance-id; +- mandatory true; +- } +- leaf connection-name { +- description "A user-visible name for the connection instance"; +- type nemo-common:connection-instance-name; +- mandatory false; +- } +- leaf connection-type { +- type nemo-common:connection-instance-type; +- mandatory true; +- } +- container endnodes{ +- list one-end{ +- key "node-id"; +- leaf node-id{ +- type nemo-common:node-instance-id; +- } +- min-elements 1; +- } +- list the-other-end{ +- key "node-id"; +- leaf node-id{ +- type nemo-common:node-instance-id; +- } +- min-elements 1; +- } +- } +- container property{ +- uses connection-property-instance; +- } +- } +- +- grouping match-item-instance{ +- list match-item { +- key "name"; +- leaf name { +- type string; +- mandatory true; ++ } ++ } ++ ++ grouping node-instance { ++ description ++ "It represents the node instance and its metadata. ++ A node represents the functions a network node may provide in a ++ network such as network services,or a group of network elements."; ++ ++ leaf node-id { ++ description ++ "A unique ID for a node instance"; ++ type nemo-common:node-id; ++ mandatory true; ++ } ++ ++ leaf node-name { ++ description ++ "A user-visible and unique name for a node instance."; ++ type nemo-common:node-name; ++ mandatory true; ++ } ++ ++ leaf node-type { ++ description ++ "A user-visible and unique type identifier for a node instance."; ++ type nemo-common:node-type; ++ mandatory true; ++ } ++ ++ list sub-node { ++ description ++ "Represents the sub-nodes which have been included ++ by the node instance logically."; ++ ++ key "node-id"; ++ leaf node-id { ++ description ++ "A unique ID for a node instance."; ++ type nemo-common:node-id; ++ } ++ ++ leaf order { ++ description ++ "Specify the order of the node in a sequence node list."; ++ type uint32; ++ } ++ } ++ ++ list property { ++ description ++ "The property list of a node instance."; ++ ++ key "property-name"; ++ uses property-instance; ++ } ++ } ++ ++ grouping connection-instance { ++ description ++ "It represents the connection instance and its metadata. ++ The Connection describes the resource between node entities. ++ This connection is not limited to any physical link, but just ++ expresses the communication capacity between nodes."; ++ ++ leaf connection-id { ++ description ++ "A unique ID for a connection instance."; ++ type nemo-common:connection-id; ++ mandatory true; ++ } ++ ++ leaf connection-name { ++ description ++ "A user-visible and unique name for a connection instance."; ++ type nemo-common:connection-name; ++ mandatory true; ++ } ++ ++ leaf connection-type { ++ description ++ "A user-visible and unique type identifier for a connection instance."; ++ type nemo-common:connection-type; ++ mandatory true; ++ } ++ ++ list end-node { ++ description ++ "Represents the nodes which will be connected by connection. ++ At least two nodes in the list."; ++ ++ key "node-id"; ++ leaf node-id { ++ description ++ "A unique ID for a node instance."; ++ type nemo-common:node-id; ++ } ++ ++ leaf order { ++ description ++ "Specify the order of the node in a sequence node list"; ++ type uint32; + } ++ ++ min-elements 2; ++ } ++ ++ list property { ++ description ++ "The property list of a connection instance."; ++ ++ key "property-name"; ++ uses property-instance; ++ } ++ } ++ ++ grouping match-item-instance { ++ description ++ "Represents the match item and its metadata."; ++ ++ leaf match-item-name { ++ description ++ "A name for a match item."; ++ type nemo-common:match-item-name; ++ mandatory true; ++ } ++ ++ container match-item-value { ++ description ++ "The value of a match item."; ++ + leaf string-value { + type string; + } ++ + leaf int-value { + type int64; + } ++ + container range-value { + leaf min { + type int64; + mandatory true; + } ++ + leaf max { + type int64; + mandatory true; + } + } +- } +- } +- grouping has-direction { +- description "Object that have a directionality."; +- leaf direction { +- default bidirectional; +- type enumeration { +- enum in { +- description +- "Applies to flow into provider node"; +- } +- enum out { +- description +- "Applies to flow out of provider node"; +- } +- enum bidirectional { +- description +- "Applies to flow in both directions"; +- } +- } + } +- } +- grouping flow-instance{ +- leaf flow-id { +- description "A unique ID for the flow instance"; +- type nemo-common:flow-instance-id; +- mandatory true; +- } +- leaf flow-name { +- description "A user-visible name for the flow instance"; +- type nemo-common:flow-instance-name; +- mandatory false; +- } +- leaf flow-type { +- type nemo-common:flow-instance-type; +- mandatory true; +- } +- container match { +- uses has-direction; +- uses match-item-instance; +- } +- } +- ++ } ++ ++ grouping flow-instance { ++ description ++ "Represents the flow instance and its metadata. ++ The flow refers to the traffic in network which describes ++ data packets have some certain characters."; ++ ++ leaf flow-id { ++ description ++ "A unique ID for a flow instance."; ++ type nemo-common:flow-id; ++ mandatory true; ++ } ++ ++ leaf flow-name { ++ description ++ "A user-visible and unique name for a flow instance."; ++ type nemo-common:flow-name; ++ mandatory true; ++ } ++ ++ list match-item { ++ description ++ "The match item list of a flow instance."; ++ ++ key "match-item-name"; ++ uses match-item-instance; ++ } ++ ++ list property { ++ description ++ "The property list of a flow instance."; ++ ++ key "property-name"; ++ uses property-instance; ++ } ++ } + } +diff --git a/nemo-api/src/main/yang/nemo-operation.yang b/nemo-api/src/main/yang/nemo-operation.yang +index 219b192..8b4083a 100644 +--- a/nemo-api/src/main/yang/nemo-operation.yang ++++ b/nemo-api/src/main/yang/nemo-operation.yang +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2015 Huawei Technologies Co., Ltd. and others. All rights reserved. ++ * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, +@@ -7,201 +7,288 @@ + */ + + module nemo-operation { ++ yang-version 1; + +- yang-version 1; +- namespace "urn:opendaylight:params:xml:ns:yang:nemo:operation"; +- prefix "nemo-operation"; +- +- import nemo-common {prefix nemo-common;} +- +- revision "2015-06-29" { ++ namespace "urn:opendaylight:params:xml:ns:yang:nemo:operation"; ++ prefix "nemo-operation"; ++ ++ import nemo-common {prefix nemo-common;} ++ ++ revision "2015-10-10" { + description + "Initial revision."; + } +- +- grouping parameter-definition { +- leaf name { +- description "A user-visible name for parameter"; +- type nemo-common:parameter-name; +- mandatory true; +- } +- leaf type { +- description "The type of the parameter"; +- default string; +- type enumeration { +- enum string { +- description "A string-valued parameter"; +- } +- enum int { +- description "An integer-valued parameter"; +- } +- enum range { +- description "An integer-range parameter"; +- } +- } +- } +- leaf is-required { +- description "Specify whether the parameter is required "; +- default optional; +- type enumeration { +- enum required { +- description "The parameter is required"; +- } +- enum optional { +- description "The parameter is optional"; +- } +- } +- } +- } +- +- +- container action-definitions { +- list action-definition { +- key "action-name"; +- leaf action-name { +- description "A name for the action definition"; +- type nemo-common:action-definition-name; +- mandatory true; +- } +- list data { +- description +- "data for the action that can be passed in."; +- key "name"; +- uses parameter-definition; +- } +- } +- } +- grouping action-parameter-instance{ +- leaf data-name { +- type nemo-common:data-name; +- mandatory true; +- } +- leaf string-value { +- type string; +- } +- leaf int-value { +- type int64; +- } +- container range-value { +- leaf min { +- type int64; +- mandatory true; +- } +- leaf max { +- type int64; +- mandatory true; +- } +- } +- } +- grouping action-instance{ +- description " "; +- leaf action-name{ +- type nemo-common:action-instance-name; +- mandatory true; +- } +- list data { +- key "data-name"; +- uses action-parameter-instance; +- } +- } +- +- container condition-definitions { +- list condition-definition{ +- key "condition-name"; +- leaf condition-name{ +- type nemo-common:condition-definition-name; +- mandatory true; +- } +- list condition-parameter{ +- key "name"; +- uses parameter-definition; +- min-elements 1; +- } +- } +- } +- grouping conditon-parameter-instance{ +- leaf parameter-name { +- type nemo-common:condition-parameter-name; +- mandatory true; +- } +- leaf string-value { +- type string; +- } +- leaf int-value { +- type int64; +- } +- container range-value { +- leaf min { +- type int64; +- mandatory true; +- } +- leaf max { +- type int64; +- mandatory true; +- } +- } +- } +- grouping condition-instance { +- description " "; +- leaf condition-name{ +- type nemo-common:condition-instance-name; +- mandatory true; +- } +- list condition-parameter{ +- key "parameter-name"; +- uses conditon-parameter-instance; +- min-elements 1; +- } +- } +- +- +- container constraint-definitions { +- list constraint-definition{ +- key "constraint-name"; +- leaf constraint-name{ +- type nemo-common:constraint-definition-name; +- mandatory true; +- } +- list constraint-parameter{ +- key "name"; +- uses parameter-definition; +- min-elements 1; +- } +- } +- } +- grouping constraint-parameter-instance{ +- leaf parameter-name { +- type nemo-common:constraint-parameter-name; +- mandatory true; +- } +- leaf string-value { +- type string; +- } +- leaf int-value { +- type int64; +- } +- container range-value { +- leaf min { +- type int64; +- mandatory true; +- } +- leaf max { +- type int64; +- mandatory true; +- } +- } +- } +- grouping constraint-instance { +- description " "; +- leaf constraint-name{ +- type nemo-common:constraint-instance-name; +- mandatory true; +- } +- list constraint-parameter{ +- key "parameter-name"; +- uses constraint-parameter-instance; +- min-elements 1; +- } +- } +- +-} +\ No newline at end of file ++ ++ container condition-parameter-definitions { ++ list condition-parameter-definition { ++ description ++ "Defines the condition parameter with its metadata."; ++ ++ key "parameter-name"; ++ leaf parameter-name { ++ description ++ "A name for the condition parameter."; ++ type nemo-common:parameter-name; ++ mandatory true; ++ } ++ ++ leaf parameter-value-type { ++ description ++ "A type of value for the condition parameter."; ++ type enumeration { ++ enum string { ++ description ++ "A string-valued parameter."; ++ } ++ enum int { ++ description ++ "An integer-valued parameter."; ++ } ++ enum range { ++ description ++ "An integer-range parameter."; ++ } ++ } ++ } ++ ++ container parameter-match-patterns { ++ description ++ "Defines the match patterns of the condition parameter."; ++ ++ leaf-list parameter-match-pattern { ++ type enumeration { ++ enum less-than; ++ enum not-less-than; ++ enum equal; ++ enum not-equal; ++ enum greater-than; ++ enum not-greater-than; ++ enum between; ++ enum periodical; ++ } ++ } ++ } ++ } ++ } ++ ++ container action-definitions { ++ list action-definition { ++ description ++ "Defines the actions which will be supported by the NEMO project."; ++ ++ key "action-name"; ++ leaf action-name { ++ description ++ "A name for the action definition."; ++ type nemo-common:action-name; ++ mandatory true; ++ } ++ ++ leaf parameter-value-type { ++ description ++ "The type of the action parameter."; ++ default string; ++ type enumeration { ++ enum string { ++ description ++ "A string-valued parameter."; ++ } ++ enum int { ++ description ++ "An integer-valued parameter."; ++ } ++ enum range { ++ description ++ "An integer-range parameter."; ++ } ++ } ++ } ++ } ++ } ++ ++ grouping condition-instance { ++ description ++ "Specific a instance of condition whose metadata has been filled in."; ++ ++ list condition-segment { ++ description ++ "The segment entities will be composed into a whole condition entity. ++ Each segment will be a sub expression of the condition."; ++ ++ key "condition-segment-id"; ++ leaf condition-segment-id { ++ description ++ "A unique ID for a condition segment."; ++ type nemo-common:condition-segment-id; ++ mandatory true; ++ } ++ ++ leaf condition-parameter-name { ++ description ++ "A name for a conditon parameter."; ++ type nemo-common:condition-parameter-name; ++ } ++ ++ leaf condition-parameter-match-pattern { ++ description ++ "The operator for the condition parameter and it's target value."; ++ type enumeration { ++ enum less-than; ++ enum not-less-than; ++ enum equal; ++ enum not-equal; ++ enum greater-than; ++ enum not-greater-than; ++ enum between; ++ enum periodical; ++ } ++ } ++ ++ container condition-parameter-target-value { ++ description ++ "The target value of condition parameter."; ++ ++ leaf string-value { ++ type string; ++ } ++ ++ leaf int-value { ++ type int64; ++ } ++ ++ container range-value { ++ leaf min { ++ type int64; ++ mandatory true; ++ } ++ ++ leaf max { ++ type int64; ++ mandatory true; ++ } ++ } ++ } ++ ++ leaf precursor-relation-operator { ++ description ++ "The logical operator between current segment and the next segment."; ++ type enumeration { ++ enum none; ++ enum and; ++ enum or; ++ enum not; ++ } ++ } ++ ++ leaf order { ++ description ++ "The order of the segment in the whole condition entity."; ++ type uint32; ++ } ++ } ++ } ++ ++ grouping action-instance { ++ description ++ "Specific a action instance whose metadata has been filled in."; ++ ++ leaf action-name { ++ description ++ "A name for a action instance."; ++ type nemo-common:action-name; ++ mandatory true; ++ } ++ ++ container parameter-values { ++ description ++ "The parameter value list of an action."; ++ ++ list string-value { ++ key "value order"; ++ leaf value { ++ type string; ++ } ++ ++ leaf order { ++ type uint32; ++ } ++ } ++ ++ list int-value { ++ key "value order"; ++ leaf value { ++ type int64; ++ } ++ ++ leaf order { ++ type uint32; ++ } ++ } ++ ++ container range-value { ++ leaf min { ++ type int64; ++ mandatory true; ++ } ++ ++ leaf max { ++ type int64; ++ mandatory true; ++ } ++ } ++ } ++ } ++ ++ grouping operation-instance { ++ description ++ "Specific an operation instance whose metadata has been filled in. ++ Operation is a type of intent which refers to taking for some specific ++ actions to realize the purpose."; ++ ++ leaf operation-id { ++ description ++ "A unique ID for a operation instance."; ++ type nemo-common:operation-id; ++ mandatory true; ++ } ++ ++ leaf operation-name { ++ description ++ "A user-visible and unique name for a operation instance."; ++ type nemo-common:operation-name; ++ mandatory true; ++ } ++ ++ leaf priority { ++ description ++ "Defines the priority of a operation instance."; ++ type uint32; ++ default 0; ++ } ++ ++ leaf target-object { ++ description ++ "The target object which the operation instance will apply to."; ++ type nemo-common:object-id; ++ mandatory true; ++ } ++ ++ uses condition-instance; ++ ++ list action { ++ description ++ "The action list for the operation instance."; ++ ++ key "action-name"; ++ uses action-instance; ++ ++ leaf order { ++ description ++ "The order of an action instance in execution sequence."; ++ type uint32; ++ } ++ ++ min-elements 1; ++ } ++ } ++} +diff --git a/nemo-api/src/main/yang/nemo-result.yang b/nemo-api/src/main/yang/nemo-result.yang +index b350c21..6daf69b 100644 +--- a/nemo-api/src/main/yang/nemo-result.yang ++++ b/nemo-api/src/main/yang/nemo-result.yang +@@ -1,58 +1,23 @@ + /* +- * Copyright (c) 2015 Huawei Technologies Co., Ltd. and others. All rights reserved. ++ * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +-module nemo-result{ ++module nemo-result { ++ yang-version 1; + +- yang-version 1; +- namespace "urn:opendaylight:params:xml:ns:yang:nemo:result"; +- prefix "nemo-result"; +- +- import nemo-common {prefix nemo-common;} +- +- revision "2015-06-29" { ++ namespace "urn:opendaylight:params:xml:ns:yang:nemo:result"; ++ prefix "nemo-result"; ++ ++ import nemo-common {prefix nemo-common;} ++ ++ revision "2015-10-10" { + description + "Initial revision."; + } +- +- container expected-definitons{ +- +- } +- +- grouping expected-instance { +- leaf expected-id { +- type nemo-common:expected-instance-id; +- mandatory true; +- } +- leaf expected-name{ +- type nemo-common:expected-instance-name; +- mandatory false; +- } +- leaf expected-description { +- type nemo-common:description; +- } +- } +- +- container avoid-definitons{ +- +- } + +- grouping avoid-instance { +- leaf avoid-id { +- type nemo-common:avoid-instance-id; +- mandatory true; +- } +- leaf avoid-name{ +- type nemo-common:avoid-instance-name; +- mandatory false; +- } +- leaf avoid-description { +- type nemo-common:description; +- } +- } +- +-} +\ No newline at end of file ++ // TBD ++} +diff --git a/nemo-features/pom.xml b/nemo-features/pom.xml +index c678d52..e4db9ed 100644 +--- a/nemo-features/pom.xml ++++ b/nemo-features/pom.xml +@@ -26,10 +26,11 @@ and is available at http://www.eclipse.org/legal/epl-v10.html + + + +- 1.3.0-SNAPSHOT + 0.8.0-SNAPSHOT ++ 1.3.0-SNAPSHOT + 1.3.0-SNAPSHOT + 0.3.0-SNAPSHOT ++ 0.2.0-SNAPSHOT + + + +@@ -44,7 +45,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html + + org.opendaylight.controller + mdsal-artifacts +- ${controller.mdsal.version} ++ ${mdsal.version} + pom + import + +@@ -97,6 +98,22 @@ and is available at http://www.eclipse.org/legal/epl-v10.html + xml + runtime + ++ ++ ++ org.opendaylight.openflowplugin ++ features-openflowplugin ++ ${openflowplugin.version} ++ features ++ xml ++ ++ ++ org.opendaylight.openflowplugin ++ features-openflowplugin-extension ++ ${openflowplugin.version} ++ features ++ xml ++ ++ + + ${project.groupId} + nemo-api +@@ -109,6 +126,13 @@ and is available at http://www.eclipse.org/legal/epl-v10.html + + + ${project.groupId} ++ nemo-impl ++ ${project.version} ++ config ++ xml ++ ++ ++ ${project.groupId} + openflow-renderer + ${project.version} + +@@ -121,6 +145,13 @@ and is available at http://www.eclipse.org/legal/epl-v10.html + + + ${project.groupId} ++ openflow-renderer ++ ${project.version} ++ resource ++ json ++ ++ ++ ${project.groupId} + nemo-ui + ${project.version} + +diff --git a/nemo-features/src/main/features/features.xml b/nemo-features/src/main/features/features.xml +index 4cec890..f14ab7c 100644 +--- a/nemo-features/src/main/features/features.xml ++++ b/nemo-features/src/main/features/features.xml +@@ -9,28 +9,37 @@ and is available at http://www.eclipse.org/legal/epl-v10.html + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0"> + mvn:org.opendaylight.mdsal.model/features-mdsal-model/${mdsal.model.version}/xml/features +- mvn:org.opendaylight.controller/features-mdsal/${controller.mdsal.version}/xml/features ++ mvn:org.opendaylight.controller/features-mdsal/${mdsal.version}/xml/features + mvn:org.opendaylight.netconf/features-restconf/${restconf.version}/xml/features + mvn:org.opendaylight.dlux/features-dlux/${dlux.version}/xml/features ++ mvn:org.opendaylight.openflowplugin/features-openflowplugin/${openflowplugin.version}/xml/features ++ mvn:org.opendaylight.openflowplugin/features-openflowplugin-extension/${openflowplugin.version}/xml/features + + odl-mdsal-models + mvn:org.opendaylight.nemo/nemo-api/${project.version} + + +- odl-mdsal-broker ++ odl-mdsal-broker + odl-nemo-api + mvn:org.opendaylight.nemo/nemo-impl/${project.version} ++ mvn:org.opendaylight.nemo/nemo-impl/${project.version}/xml/config + + + odl-restconf +- odl-mdsal-apidocs +- odl-mdsal-xsql ++ odl-mdsal-apidocs ++ odl-mdsal-xsql + odl-nemo-engine + + +- odl-nemo-engine ++ odl-openflowplugin-flow-services ++ odl-openflowplugin-nxm-extensions ++ odl-nemo-engine-rest + mvn:org.opendaylight.nemo/openflow-renderer/${project.version} +- mvn:org.opendaylight.nemo/openflow-renderer/${project.version}/xml/config ++ mvn:org.opendaylight.nemo/openflow-renderer/${project.version}/xml/config ++ mvn:org.opendaylight.nemo/openflow-renderer/${project.version}/json/resource ++ ++ ++ odl-nemo-engine-rest + + + odl-dlux-core +diff --git a/nemo-impl/pom.xml b/nemo-impl/pom.xml +index fdb8145..c66209c 100644 +--- a/nemo-impl/pom.xml ++++ b/nemo-impl/pom.xml +@@ -10,9 +10,9 @@ and is available at http://www.eclipse.org/legal/epl-v10.html + 4.0.0 + + +- org.opendaylight.mdsal +- binding-parent +- 0.8.0-SNAPSHOT ++ org.opendaylight.controller ++ config-parent ++ 0.4.0-SNAPSHOT + + + +@@ -24,15 +24,49 @@ and is available at http://www.eclipse.org/legal/epl-v10.html + + + 0.7.2.201409121644 ++ target/code-coverage/jacoco.exec ++ target/code-coverage/jacoco-it.exec + + + + ++ org.opendaylight.mdsal.model ++ ietf-inet-types ++ ++ ++ org.opendaylight.mdsal.model ++ ietf-yang-types ++ ++ + ${project.groupId} + nemo-api + ${project.version} + + ++ net.sourceforge.collections ++ collections-generic ++ 4.01 ++ ++ ++ net.sf.jung ++ jung-api ++ 2.0.1 ++ ++ ++ net.sf.jung ++ jung-graph-impl ++ 2.0.1 ++ ++ ++ net.sf.jung ++ jung-algorithms ++ 2.0.1 ++ ++ ++ com.google.guava ++ guava ++ ++ + junit + junit + +@@ -59,26 +93,101 @@ and is available at http://www.eclipse.org/legal/epl-v10.html + + + +- org.jacoco +- jacoco-maven-plugin ++ org.opendaylight.yangtools ++ yang-maven-plugin ++ ++ ++ ++ generate-sources ++ ++ ++ src/main/yang ++ ++ ++ ++ org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl ++ ++ ++ ${salGeneratorPath} ++ ++ ++ ++ true ++ ++ ++ ++ ++ ++ org.opendaylight.mdsal ++ maven-sal-api-gen-plugin ++ ${yangtools.version} ++ jar ++ ++ ++ ++ ++ org.apache.felix ++ maven-bundle-plugin ++ true + +- +- org.opendaylight.nemo.* +- ++ ++ .,{maven-dependencies} ++ *;resolution:=optional ++ ++ collections-generic,jung-api,jung-graph-impl,jung-algorithms ++ ++ true ++ lib ++ true ++ <_failok>true ++ <_nouses>true ++ ++ ${project.build.outputDirectory}/META-INF + ++ ++ ++ org.codehaus.mojo ++ build-helper-maven-plugin ++ ++ ++ attach-artifacts ++ ++ attach-artifact ++ ++ package ++ ++ ++ ++ ${project.build.directory}/classes/etc/opendaylight/karaf/config.xml ++ xml ++ config ++ ++ ++ ++ ++ ++ ++ ++ org.jacoco ++ jacoco-maven-plugin + + +- pre-test ++ pre-unit-test + + prepare-agent + ++ ++ ${sonar.jacoco.reportPath} ++ + + +- post-test ++ post-unit-test + + report + +- test ++ ++ ${sonar.jacoco.reportPath} ++ + + + +diff --git a/nemo-impl/src/main/java/README b/nemo-impl/src/main/java/README +deleted file mode 100644 +index e69de29..0000000 +diff --git a/nemo-impl/src/test/java/README b/nemo-impl/src/test/java/README +deleted file mode 100644 +index e69de29..0000000 +diff --git a/nemo-karaf/pom.xml b/nemo-karaf/pom.xml +index 7f23a37..c5520cc 100644 +--- a/nemo-karaf/pom.xml ++++ b/nemo-karaf/pom.xml +@@ -26,12 +26,8 @@ and is available at http://www.eclipse.org/legal/epl-v10.html + + + +- 1.6.0-SNAPSHOT + 1.3.0-SNAPSHOT + 0.3.0-SNAPSHOT +- 1.3.0-SNAPSHOT +- 0.8.0-SNAPSHOT +- 0.10.0-SNAPSHOT + + + +@@ -61,14 +57,6 @@ and is available at http://www.eclipse.org/legal/epl-v10.html + runtime + + +- org.opendaylight.controller +- features-adsal +- features +- ${feature.adsal.version} +- xml +- runtime +- +- + org.opendaylight.dlux + features-dlux + ${feature.dlux.version} +diff --git a/nemo-renderers/openflow-renderer/pom.xml b/nemo-renderers/openflow-renderer/pom.xml +index a88e190..ab0b3f5 100644 +--- a/nemo-renderers/openflow-renderer/pom.xml ++++ b/nemo-renderers/openflow-renderer/pom.xml +@@ -24,9 +24,33 @@ and is available at http://www.eclipse.org/legal/epl-v10.html + + + 0.7.2.201409121644 ++ target/code-coverage/jacoco.exec ++ target/code-coverage/jacoco-it.exec ++ 0.2.0-SNAPSHOT ++ 0.10.0-SNAPSHOT + + + ++ ++ ++ org.opendaylight.mdsal.model ++ yang-ext ++ ++ ++ ++ org.opendaylight.openflowplugin ++ openflowplugin-extension-nicira ++ ${openflowplugin.version} ++ ++ ++ org.opendaylight.controller ++ liblldp ++ ${liblldp.version} ++ ++ ++ commons-net ++ commons-net ++ + + ${project.groupId} + nemo-api +@@ -38,6 +62,11 @@ and is available at http://www.eclipse.org/legal/epl-v10.html + ${project.version} + + ++ org.mockito ++ mockito-all ++ test ++ ++ + junit + junit + +@@ -47,6 +76,18 @@ and is available at http://www.eclipse.org/legal/epl-v10.html + test + + ++ com.fasterxml.jackson.core ++ jackson-core ++ ++ ++ com.fasterxml.jackson.core ++ jackson-databind ++ ++ ++ com.fasterxml.jackson.core ++ jackson-annotations ++ ++ + org.codehaus.jettison + jettison + +@@ -64,6 +105,19 @@ and is available at http://www.eclipse.org/legal/epl-v10.html + + + ++ org.apache.felix ++ maven-bundle-plugin ++ ++ ++ org.codehaus.jackson, ++ org.codehaus.jackson.*, ++ org.joda.time.*, ++ ++ * ++ ++ ++ ++ + org.opendaylight.yangtools + yang-maven-plugin + +@@ -108,6 +162,11 @@ and is available at http://www.eclipse.org/legal/epl-v10.html + package + + ++ ++ ${project.build.directory}/classes/etc/nemo/resource.json ++ json ++ resource ++ + + ${project.build.directory}/classes/etc/opendaylight/karaf/config.xml + xml +@@ -128,17 +187,22 @@ and is available at http://www.eclipse.org/legal/epl-v10.html + + + +- pre-test ++ pre-unit-test + + prepare-agent + ++ ++ ${sonar.jacoco.reportPath} ++ + + +- post-test ++ post-unit-test + + report + +- test ++ ++ ${sonar.jacoco.reportPath} ++ + + + +diff --git a/nemo-renderers/openflow-renderer/src/main/java/README b/nemo-renderers/openflow-renderer/src/main/java/README +deleted file mode 100644 +index e69de29..0000000 +diff --git a/nemo-renderers/openflow-renderer/src/main/yang/openflow-renderer-impl.yang b/nemo-renderers/openflow-renderer/src/main/yang/openflow-renderer-impl.yang +index dc8b4d9..0a1637e 100644 +--- a/nemo-renderers/openflow-renderer/src/main/yang/openflow-renderer-impl.yang ++++ b/nemo-renderers/openflow-renderer/src/main/yang/openflow-renderer-impl.yang +@@ -19,7 +19,7 @@ module openflow-renderer-impl { + "This module contains the base YANG definitions for + NEMO Openflow renderer implementation."; + +- revision "2015-07-01" { ++ revision "2015-10-10" { + description + "Initial revision."; + } +diff --git a/nemo-renderers/openflow-renderer/src/test/java/README b/nemo-renderers/openflow-renderer/src/test/java/README +deleted file mode 100644 +index e69de29..0000000 +diff --git a/nemo-renderers/pom.xml b/nemo-renderers/pom.xml +index 7066dda..1024502 100644 +--- a/nemo-renderers/pom.xml ++++ b/nemo-renderers/pom.xml +@@ -5,7 +5,8 @@ This program and the accompanying materials are made available under the + terms of the Eclipse Public License v1.0 which accompanies this distribution, + and is available at http://www.eclipse.org/legal/epl-v10.html + --> +- ++ + 4.0.0 + + +@@ -27,7 +28,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html + + scm:git:ssh://git.opendaylight.org:29418/nemo.git + scm:git:ssh://git.opendaylight.org:29418/nemo.git +- HEAD + https://wiki.opendaylight.org/view/NEMO:Main ++ HEAD + +- ++ +\ No newline at end of file +diff --git a/nemo-ui/src/main/resources/README b/nemo-ui/src/main/resources/README +deleted file mode 100644 +index e69de29..0000000 +diff --git a/pom.xml b/pom.xml +index 22b85c9..d898151 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -5,14 +5,15 @@ This program and the accompanying materials are made available under the + terms of the Eclipse Public License v1.0 which accompanies this distribution, + and is available at http://www.eclipse.org/legal/epl-v10.html + --> +- ++ + 4.0.0 + + +- org.opendaylight.controller +- releasepom +- 0.3.0-SNAPSHOT +- ++ org.opendaylight.odlparent ++ odlparent ++ 1.6.0-SNAPSHOT ++ + + + org.opendaylight.nemo +@@ -30,10 +31,10 @@ and is available at http://www.eclipse.org/legal/epl-v10.html + nemo-artifacts + nemo-api + nemo-impl ++ nemo-renderers + nemo-ui + nemo-features + nemo-karaf +- nemo-renderers + + + https://wiki.opendaylight.org/view/NEMO:Main +@@ -58,7 +59,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html + + scm:git:ssh://git.opendaylight.org:29418/nemo.git + scm:git:ssh://git.opendaylight.org:29418/nemo.git +- HEAD + https://wiki.opendaylight.org/view/NEMO:Main ++ HEAD + + diff --git a/nemo-api/src/main/yang/nemo-common.yang b/nemo-api/src/main/yang/nemo-common.yang index cbccc32..072745f 100644 --- a/nemo-api/src/main/yang/nemo-common.yang +++ b/nemo-api/src/main/yang/nemo-common.yang @@ -1,32 +1,37 @@ /* - * Copyright (c) 2015 Huawei Technologies Co., Ltd. and others. All rights reserved. + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ -module nemo-common{ - yang-version 1; - namespace "urn:opendaylight:params:xml:ns:yang:nemo:common"; - prefix "nemo-common"; - - revision "2015-06-29" { +module nemo-common { + yang-version 1; + + namespace "urn:opendaylight:params:xml:ns:yang:nemo:common"; + prefix "nemo-common"; + + description + "Common types and definitions for NEMO models"; + + revision "2015-10-10" { description "Initial revision."; } - - /********************** - * Base types - **********************/ - typedef description { - description "A human-readable description for a object."; + + // ********************* + // * Base Types + // ********************* + typedef description { + description + "A human-readable description for a object."; type string { length "1..4096"; } } - - typedef name { + + typedef name { description "A generic string name type. Must start with a letter"; type string { @@ -34,8 +39,8 @@ module nemo-common{ length "1..256"; } } - - // UUID type from ietf-yang-types@2013-07-15 + + // UUID type from ietf-yang-types@2013-07-15 typedef uuid { type string { pattern '[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-' @@ -43,8 +48,8 @@ module nemo-common{ } description "A Universally Unique IDentifier in the string representation - defined in RFC 4122. The canonical representation uses - lowercase characters. + defined in RFC 4122. The canonical representation uses + lower case characters. The following is an example of a UUID in string representation: f81d4fae-7dec-11d0-a765-00a0c91e6bf6"; @@ -54,265 +59,179 @@ module nemo-common{ } typedef unique-id { + description + "A globally unique identifier."; type uuid; - description "A globally unique identifier"; } - - /********************* - * Unique IDs - *********************/ - typedef object-id { + + // ********************* + // * Unique IDs + // ********************* + typedef object-id { + description + "A unique ID for a parameterized object."; type unique-id; - description "A unique ID for a parameterized object"; } - - typedef node-definition-id { - type object-id; - description "A unique ID for a node definition."; - } - typedef node-instance-id { - type object-id; - description "A unique ID for a node instance."; - } - - typedef connection-definition-id { + + typedef node-id { + description + "A unique ID for a node."; type object-id; - description "A unique ID for a connection definition."; } - typedef connection-instance-id { - type object-id; - description "A unique ID for a connection instance."; - } - - typedef flow-definition-id { + + typedef connection-id { + description + "A unique ID for a connection."; type object-id; - description "A unique ID for a flow definition."; } - typedef flow-instance-id { + + typedef flow-id { + description + "A unique ID for a flow."; type object-id; - description "A unique ID for a flow instance."; } - - typedef expected-definition-id { + + typedef intent-id { + description + "A unique ID for an intent."; type unique-id; - description "A unique ID for an expected definition."; } - typedef expected-instance-id { + + typedef user-id { + description + "A unique ID for a user."; type unique-id; - description "A unique ID for an expected instance."; } - - typedef avoid-definition-id { + + typedef operation-id { + description + "A unique ID for an operation."; type unique-id; - description "A unique ID for an avoid definition."; } - typedef avoid-instance-id { - type unique-id; - description "A unique ID for an avoid instance."; - } - - typedef context-id { - type unique-id; - description "A unique ID for a context."; - } - - typedef intent-id { + + typedef condition-segment-id { + description + "A unique ID for a segment of the condition in an operation."; type unique-id; - description "A unique ID for an intent."; } - - typedef user-id { + + typedef query-condition-id { + description + "A unique ID for a condition of the advanced query."; type unique-id; - description "A unique ID for a user."; - } - - - - /********************* - * names - *********************/ - typedef object-name { + } + + // ********************* + // * Names + // ********************* + typedef object-name { + description + "A name for a parameterized object"; type name; - description "A name for a parameterized object"; } - - typedef node-instance-name { + + typedef node-name { + description + "A name for a node instance."; type object-name; - description "A name for a node instance."; - } - - typedef connection-instance-name { + } + + typedef connection-name { + description + "A name for a connection instance."; type object-name; - description "A name for a connection instance."; - } - - typedef flow-instance-name { + } + + typedef flow-name { + description + "A name for a flow instance."; type object-name; - description "A name for a flow instance."; - } - - typedef node-property-name { - type name; - description "A name for a node property."; - } - - typedef connection-property-name { + } + + typedef match-item-name { + description + "A name for a match item."; type name; - description "A name for a connection property."; - } + } - typedef match-item-name { + typedef property-name { + description + "A name for a property."; type name; - description "A name for a flow match item."; } - - typedef property-name { + + typedef parameter-name { + description + "A name for a parameter."; type name; - description "A name for a property."; } - - typedef parameter-name { + + typedef action-name { + description + "A name for an action."; type name; - description "A name for a parameter."; } - - typedef action-definition-name { + + typedef condition-parameter-name { + description + "A name for a parameter of condition."; type name; - description "A name for an action definition."; - } - typedef action-instance-name { + } + + typedef user-name { + description + "A name for a user."; type name; - description "A name for an action instance."; - } - typedef condition-definition-name { + } + + typedef user-password { + description + "A password for a user."; type name; - description "A name for a condition definition."; - } - typedef condition-instance-name { - type name; - description "A name for a condition instance."; - } - typedef condition-parameter-name { - type name; - description "A name for a condition parameter."; - } - typedef constraint-definition-name { + } + + typedef operation-name { + description + "A name for an operation."; type name; - description "A name for a constraint definition."; - } - typedef constraint-instance-name { - type name; - description "A name for a constraint instance."; - } - typedef constraint-parameter-name { - type name; - description "A name for a constraint parameter."; - } - - - typedef data-name { - type name; - description "A name for an action data."; - } - - typedef context-name { - type name; - description "A name for an context"; - } - - typedef intent-name { + } + + typedef query-condition-name { + description + "A name for a query with condition."; type name; - description "A name for an intent."; } - typedef user-name { + + typedef user-role-name { + description + "A role name for a user."; type name; - description "A name for a user."; } - typedef expected-instance-name { + + typedef user-role-description { + description + "It describes the role characteristic and responsibility range."; + type string; + } + + // ********************* + // * Types + // ********************* + typedef node-type { + description + "The type for a node."; type name; - description "A name for an expected instance."; } - typedef avoid-instance-name { + + typedef connection-type { + description + "The type for a connection."; type name; - description "A name for an avoid instance."; - } - - - - /********************* - * types - *********************/ - typedef node-definition-type { - type name; - description "A type for a node."; - } - typedef connection-definition-type { - type name; - description "A type for a connection."; - } - typedef flow-definition-type { - type name; - description "A type for a flow."; - } - typedef node-instance-type { - type name; - description "A type for a node instance."; - } - typedef connection-instance-type { - type name; - description "A type for a connection instance."; - } - typedef flow-instance-type { - type name; - description "A type for a flow instance."; - } + } + typedef flow-type { + description + "The type for a flow."; + type name; + } } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/nemo-api/src/main/yang/nemo-intent.yang b/nemo-api/src/main/yang/nemo-intent.yang index 21760a0..91876aa 100644 --- a/nemo-api/src/main/yang/nemo-intent.yang +++ b/nemo-api/src/main/yang/nemo-intent.yang @@ -1,136 +1,395 @@ /* - * Copyright (c) 2015 Huawei Technologies Co., Ltd. and others. All rights reserved. + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ - + module nemo-intent { - yang-version 1; - namespace "urn:opendaylight:params:xml:ns:yang:nemo:intent"; - prefix "nemo-intent"; - - import nemo-common {prefix nemo-common;} - import nemo-object {prefix nemo-object;} - import nemo-operation {prefix nemo-operation;} - import nemo-result {prefix nemo-result;} - - revision "2015-06-29" { + yang-version 1; + + namespace "urn:opendaylight:params:xml:ns:yang:nemo:intent"; + prefix "nemo-intent"; + + import nemo-common {prefix nemo-common;} + import nemo-object {prefix nemo-object;} + import nemo-operation {prefix nemo-operation;} + import nemo-user {prefix nemo-user;} + + revision "2015-10-10" { description "Initial revision."; } - - grouping intent-instance { - description ""; - leaf intent-id { - description "A unique ID for the intent"; - type nemo-common:intent-id; - mandatory true; - } - leaf intent-name { - description "A user-visible name for the intent"; - type nemo-common:intent-name; - } - container objects { - description ""; - list node { - key "node-id"; - uses nemo-object:node-instance; - } - list connection { - key "connection-id"; - uses nemo-object:connection-instance; - } - list flow { - key "flow-id"; - uses nemo-object:flow-instance; - } - } - - container operation { - leaf apply-on-object { - type nemo-common:object-id; - mandatory true; - } - leaf priority{ - type int64; - default 1; - } - uses nemo-operation:condition-instance; - uses nemo-operation:action-instance; - uses nemo-operation:constraint-instance; - } - - container result{ - leaf result-to-object { - type nemo-common:object-id; - mandatory true; - } - leaf priority{ - type int64; - default 1; - } - choice result-mode { - mandatory true; - case expected-case { - uses nemo-result:expected-instance; - } - case avoid-case{ - uses nemo-result:avoid-instance; - } - } - } - container contexts{ - list context { - key "context-id"; - leaf context-id { - type nemo-common:context-id; - mandatory true; - } - leaf context-name{ - type nemo-common:context-name; - mandatory true; - } - } - } - } - - container users { - description "The list of all known users"; - list user { - description ""; + + grouping user-intent { + description + "User intent refers to a purpose in getting an ultimate result + or performing some specific operation on some objects."; + + container objects { + description + "The element could be operated and managed by users. + It inludes resources to construct users' virtual network, + and the services in this network.In NEMO project, it is + abstracted into node, connection and flow"; + + list node { + key "node-id"; + uses nemo-object:node-instance; + } + + list connection { + key "connection-id"; + uses nemo-object:connection-instance; + } + + list flow { + key "flow-id"; + uses nemo-object:flow-instance; + } + } + + container operations { + description + "The operation is to dynamically adjust the behavior of network, + and it is applied on objects, that is, node, connection and flow"; + + list operation { + key "operation-id"; + uses nemo-operation:operation-instance; + } + } + + container results { + // TBD + } + } + + container users { + description + "The list of all known users"; + + list user { + description + "A user is an administrative domain which is + logically separated from other users, and each + intent is specified by a particular user."; + key "user-id"; - leaf user-id { - description "A unique ID for the user"; - type nemo-common:user-id; - mandatory true; - } - leaf user-name { - description "A user-visible name for the user"; - type nemo-common:user-name; - mandatory false; - } - list intent{ - key "intent-id"; - uses intent-instance; - min-elements 1; - } - } - } - - rpc register-node-instance { - description ""; - input { - uses nemo-object:node-instance; - } - } - - rpc unregister-node-instance { - description ""; - input { - uses nemo-object:node-instance; - } - } - -} \ No newline at end of file + uses nemo-user:user-instance; + uses user-intent; + } + } + + container query-condition-definitions { + description + "Contains the definitions for all advanced query, which means + they are the query with conditions supported by the NEMO engine. + User will fetch all results which meet the condition."; + + list query-condition-definition { + description + "Define the query with condition. For example, user may + intent to query all connection's name whose utilization is + beyond 80%. That is a query with condition."; + + key "query-condition-name query-intent-type"; + leaf query-condition-name { + description + "A user-visible name for the query condition definition. + The query condition name is usually to specify the + attribute or property of some kind of intent. + For the above example, the query-condition-name is utility."; + type nemo-common:query-condition-name; + mandatory true; + } + + leaf query-intent-type { + description + "The target for the query, and its attributes will be checked out + if meet the condition. In the above example, connection is the + target. So, connection will be the query-intent-type here."; + type enumeration { + enum node; + enum connection; + enum flow; + enum operation; + enum result; + } + } + + leaf query-condition-value-type { + description + "The type of the target value for the query condition. + For the above example, the target-value is 80(%), + so the query-condition-value-type will be int."; + default string; + type enumeration { + enum string { + description + "A string-valued target value."; + } + enum int { + description + "An integer-valued target value."; + } + enum range { + description + "An integer-range target value."; + } + } + } + + container query-condition-match-patterns { + description + "The relationship between the value of query-condition-name + and query-condition-target-value. If an intent's attribute + or property specified by the query condition name matches + to the target value by the match pattern, this intent meets + the condition. For the above example, the condition's + query-condition-match-patterns could be less-than, not-less-than, + equal, not-equal, greater-than, not-greater-than, between."; + + leaf-list query-condition-match-pattern { + type enumeration { + enum less-than; + enum not-less-than; + enum equal; + enum not-equal; + enum greater-than; + enum not-greater-than; + enum between; + } + } + } + } + } + + grouping common-rpc-result { + description + "Common return result for all defined RPCs."; + + leaf result-code { + description + "Result code which is convenient for processing in a program."; + type enumeration { + enum ok { + description + "The invoked RPC was executed successfully"; + } + enum error { + description + "There's an error while executing the RPC"; + } + } + } + + leaf message { + description + "A human-readable message for an error or exception"; + type string; + } + } + + grouping query-condition-instance { + description + "A query condition instance generated according to + a specified query condition definition."; + + leaf query-condition-id { + description + "A unique ID for a query condition instance."; + type nemo-common:query-condition-id; + mandatory true; + } + + leaf query-condition-name { + description + "The name of the query condition definition."; + type nemo-common:query-condition-name; + mandatory true; + } + + leaf query-intent-type { + description + "The type of the intents that the user wants to query from through + the condition instance."; + type enumeration { + enum node; + enum connection; + enum flow; + enum operation; + enum result; + } + } + + leaf query-condition-match-pattern { + description + "The match pattern the condition instance will use."; + type enumeration { + enum less-than; + enum not-less-than; + enum equal; + enum not-equal; + enum greater-than; + enum not-greater-than; + enum between; + } + } + + container query-condition-target-value { + description + "The target value used to compare with the attribute + or property of the intents."; + + leaf string-value { + type string; + } + + leaf int-value { + type int64; + } + + container range-value { + leaf min { + type int64; + mandatory true; + } + + leaf max { + type int64; + mandatory true; + } + } + } + } + + rpc register-user { + description + "Register a user to the user repository."; + + input { + uses nemo-user:user-instance; + } + + output { + uses common-rpc-result; + } + } + + rpc begin-transaction { + description + "Begin a transaction for the user"; + + input { + uses nemo-user:user-instance; + } + + output { + uses common-rpc-result; + } + } + + rpc end-transaction { + description + "Commit the user's current transaction"; + + input { + uses nemo-user:user-instance; + } + + output { + uses common-rpc-result; + } + } + + rpc language-style-nemo-request { + description + "Create, update or delete an intent of a user through an NEMO statement"; + + input { + uses nemo-user:user-instance; + + leaf nemo-statement { + type string; + } + } + + output { + uses common-rpc-result; + } + } + + rpc structure-style-nemo-update { + description + "Create or update all or a part of the user's intents, + which are described as json or xml format."; + + input { + uses nemo-user:user-instance; + uses user-intent; + } + + output { + uses common-rpc-result; + } + } + + rpc structure-style-nemo-delete { + description + "Delete some intents of a user from the user repository"; + + input { + uses nemo-user:user-instance; + + container objects { + leaf-list node { + type nemo-common:node-id; + } + + leaf-list connection { + type nemo-common:connection-id; + } + + leaf-list flow { + type nemo-common:flow-id; + } + } + + container operations { + leaf-list operation { + type nemo-common:operation-id; + } + } + + container results { + // TBD + } + } + + output { + uses common-rpc-result; + } + } + + rpc advanced-nemo-query { + description + "Query some intents of a user from the user repository + according to several advanced query conditions."; + + input { + uses nemo-user:user-instance; + + list query-condition { + key "query-condition-id"; + uses query-condition-instance; + } + } + + output { + uses common-rpc-result; + uses user-intent; + } + } +} diff --git a/nemo-api/src/main/yang/nemo-object.yang b/nemo-api/src/main/yang/nemo-object.yang index 30500fd..347406d 100644 --- a/nemo-api/src/main/yang/nemo-object.yang +++ b/nemo-api/src/main/yang/nemo-object.yang @@ -1,331 +1,405 @@ /* - * Copyright (c) 2015 Huawei Technologies Co., Ltd. and others. All rights reserved. + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ -module nemo-object{ - yang-version 1; - namespace "urn:opendaylight:params:xml:ns:yang:nemo:object"; - prefix "nemo-object"; - - import nemo-common {prefix nemo-common;} - - revision "2015-06-29" { +module nemo-object { + yang-version 1; + + namespace "urn:opendaylight:params:xml:ns:yang:nemo:object"; + prefix "nemo-object"; + + import nemo-common {prefix nemo-common;} + + revision "2015-10-10" { description "Initial revision."; } - - grouping property-definition { - list property { - description ""; - key "name"; - leaf name { - description "A user-visible name for the property"; + + grouping property-definitions { + list property-definition { + description + "The property definitions for the type of node or connection."; + + key "property-name"; + leaf property-name { + description + "A user-visible and unique name for the property."; type nemo-common:property-name; mandatory true; } - leaf value-type { - description "The type of the property"; + + leaf property-value-type { + description + "The type of the property value."; default string; type enumeration { enum string { - description "A string-valued property"; + description + "An string-valued property."; } enum int { - description "An integer-valued property"; + description + "An integer-valued property."; } enum range { - description "An integer-range property"; + description + "An integer-range property."; } } } + leaf is-required { - description "Specify whether the property is - required for object."; + description + "Specify whether the property is required for the object."; default optional; type enumeration { enum required { - description "The property is required"; + description + "The property is required"; } enum optional { - description "The property is optional"; + description + "The property is optional"; } } } - } - } - container node-definitions{ - list node-definition{ - description ""; - key "id"; - leaf id { - description "A unique ID for a kind of node definition"; - type nemo-common:node-definition-id; - mandatory true; - } - leaf node-type{ - description "A user-readable description"; - type nemo-common:node-definition-type; - mandatory true; - } - uses property-definition; - } - } - container connection-definitions{ - list connection-definition{ - key "id"; - leaf id { - description "A unique ID for a kind of connection definition"; - type nemo-common:connection-definition-id; - mandatory true; - } - leaf connection-type{ - description "A user-readable description"; - type nemo-common:connection-definition-type; - mandatory true; - } - uses property-definition; - } - } - - - grouping match-item-definition{ - - list match-item { - description ""; - key "name"; - leaf name { - description "A user-visible name for the match-item"; + + leaf is-read-only { + description + "Specify whether the property is read-only for object."; + default write-read; + type enumeration { + enum write-read { + description + "The property can be read and written."; + } + enum read-only { + description + "The property is read-only."; + } + } + } + } + } + + container node-definitions { + list node-definition { + description + "Define new node model/type which can be used in other places, + and include node type name and its property."; + + key "node-type"; + leaf node-type { + description + "A user-visible and unique identifier for the node type."; + type nemo-common:node-type; + mandatory true; + } + + uses property-definitions; + } + } + + container connection-definitions { + list connection-definition { + description + "Define new connection model/type which can be used in other places, + and include connection type name and its property."; + + key "connection-type"; + leaf connection-type { + description + "A user-visible and unique identifier for the connection type."; + type nemo-common:connection-type; + mandatory true; + } + + uses property-definitions; + } + } + + container match-item-definitions { + list match-item-definition { + description + "Define the match item which uses to match the flow."; + + key "match-item-name"; + leaf match-item-name { + description + "A user-visible and unique name for the match item."; type nemo-common:match-item-name; mandatory true; } - leaf value-type { - description "The type of the match item"; + + leaf match-item-value-type { + description + "The value type of the match item."; default string; type enumeration { enum string { - description "A string-valued match item"; + description + "A string-valued match item."; } enum int { - description "An integer-valued match item"; + description + "An integer-valued match item."; } enum range { - description "An integer-range match item"; + description + "An integer-range match item."; } } } - leaf is-required { - description "Specify whether the match item is required - for the flow."; - default optional; - type enumeration { - enum required { - description "The match item is required"; - } - enum optional { - description "The match item is optional"; - } + } + } + + container flow-property-definitions { + description + "Contains the property definitions for the flow."; + + uses property-definitions; + } + + grouping property-instance { + description + "The property instance and its associated metadata."; + + leaf property-name { + description + "The name for the property which can be seen as a unique + identifier of the property."; + type nemo-common:property-name; + mandatory true; + } + + container property-values { + description + "The value list of the property."; + + list string-value { + key "value order"; + leaf value { + type string; + } + + leaf order { + type uint32; } } - } - } - container flow-definitions{ - list flow-definition{ - key "id"; - leaf id { - description "A unique ID for a kind of flow definition"; - type nemo-common:flow-definition-id; - mandatory true; - } - leaf flow-type{ - description "A user-readable description"; - type nemo-common:flow-definition-type; - mandatory true; - } - uses match-item-definition; - } - } - - grouping node-property-instance{ - list property { - key "name"; - leaf name { - type nemo-common:node-property-name; - mandatory true; - } - leaf string-value { - type string; - } - leaf int-value { - type int64; - } - container range-value { - leaf min { + + list int-value { + key "value order"; + leaf value { type int64; - mandatory true; } - leaf max { - type int64; - mandatory true; + + leaf order { + type uint32; } } - } - } - grouping node-instance{ - description ""; - leaf node-id { - description "A unique ID for the node instance"; - type nemo-common:node-instance-id; - mandatory true; - } - leaf node-name { - description - "A user-visible name for the node definition"; - type nemo-common:node-instance-name; - } - leaf node-type { - type nemo-common:node-instance-type; - mandatory true; - } - container subnodes{ - leaf-list subnode-id{ - type nemo-common:node-instance-id; - } - } - container property{ - uses node-property-instance; - } - } - - grouping connection-property-instance{ - list property { - key "name"; - leaf name { - type nemo-common:connection-property-name; - mandatory true; - } - leaf string-value { - type string; - } - leaf int-value { - type int64; - } + container range-value { leaf min { type int64; mandatory true; } + leaf max { type int64; mandatory true; } } - } - } - grouping connection-instance { - description ""; - leaf connection-id { - description "A unique ID for the connection instance"; - type nemo-common:connection-instance-id; - mandatory true; - } - leaf connection-name { - description "A user-visible name for the connection instance"; - type nemo-common:connection-instance-name; - mandatory false; - } - leaf connection-type { - type nemo-common:connection-instance-type; - mandatory true; - } - container endnodes{ - list one-end{ - key "node-id"; - leaf node-id{ - type nemo-common:node-instance-id; - } - min-elements 1; - } - list the-other-end{ - key "node-id"; - leaf node-id{ - type nemo-common:node-instance-id; - } - min-elements 1; - } - } - container property{ - uses connection-property-instance; - } - } - - grouping match-item-instance{ - list match-item { - key "name"; - leaf name { - type string; - mandatory true; + } + } + + grouping node-instance { + description + "It represents the node instance and its metadata. + A node represents the functions a network node may provide in a + network such as network services,or a group of network elements."; + + leaf node-id { + description + "A unique ID for a node instance"; + type nemo-common:node-id; + mandatory true; + } + + leaf node-name { + description + "A user-visible and unique name for a node instance."; + type nemo-common:node-name; + mandatory true; + } + + leaf node-type { + description + "A user-visible and unique type identifier for a node instance."; + type nemo-common:node-type; + mandatory true; + } + + list sub-node { + description + "Represents the sub-nodes which have been included + by the node instance logically."; + + key "node-id"; + leaf node-id { + description + "A unique ID for a node instance."; + type nemo-common:node-id; + } + + leaf order { + description + "Specify the order of the node in a sequence node list."; + type uint32; + } + } + + list property { + description + "The property list of a node instance."; + + key "property-name"; + uses property-instance; + } + } + + grouping connection-instance { + description + "It represents the connection instance and its metadata. + The Connection describes the resource between node entities. + This connection is not limited to any physical link, but just + expresses the communication capacity between nodes."; + + leaf connection-id { + description + "A unique ID for a connection instance."; + type nemo-common:connection-id; + mandatory true; + } + + leaf connection-name { + description + "A user-visible and unique name for a connection instance."; + type nemo-common:connection-name; + mandatory true; + } + + leaf connection-type { + description + "A user-visible and unique type identifier for a connection instance."; + type nemo-common:connection-type; + mandatory true; + } + + list end-node { + description + "Represents the nodes which will be connected by connection. + At least two nodes in the list."; + + key "node-id"; + leaf node-id { + description + "A unique ID for a node instance."; + type nemo-common:node-id; + } + + leaf order { + description + "Specify the order of the node in a sequence node list"; + type uint32; } + + min-elements 2; + } + + list property { + description + "The property list of a connection instance."; + + key "property-name"; + uses property-instance; + } + } + + grouping match-item-instance { + description + "Represents the match item and its metadata."; + + leaf match-item-name { + description + "A name for a match item."; + type nemo-common:match-item-name; + mandatory true; + } + + container match-item-value { + description + "The value of a match item."; + leaf string-value { type string; } + leaf int-value { type int64; } + container range-value { leaf min { type int64; mandatory true; } + leaf max { type int64; mandatory true; } } - } - } - grouping has-direction { - description "Object that have a directionality."; - leaf direction { - default bidirectional; - type enumeration { - enum in { - description - "Applies to flow into provider node"; - } - enum out { - description - "Applies to flow out of provider node"; - } - enum bidirectional { - description - "Applies to flow in both directions"; - } - } } - } - grouping flow-instance{ - leaf flow-id { - description "A unique ID for the flow instance"; - type nemo-common:flow-instance-id; - mandatory true; - } - leaf flow-name { - description "A user-visible name for the flow instance"; - type nemo-common:flow-instance-name; - mandatory false; - } - leaf flow-type { - type nemo-common:flow-instance-type; - mandatory true; - } - container match { - uses has-direction; - uses match-item-instance; - } - } - + } + + grouping flow-instance { + description + "Represents the flow instance and its metadata. + The flow refers to the traffic in network which describes + data packets have some certain characters."; + + leaf flow-id { + description + "A unique ID for a flow instance."; + type nemo-common:flow-id; + mandatory true; + } + + leaf flow-name { + description + "A user-visible and unique name for a flow instance."; + type nemo-common:flow-name; + mandatory true; + } + + list match-item { + description + "The match item list of a flow instance."; + + key "match-item-name"; + uses match-item-instance; + } + + list property { + description + "The property list of a flow instance."; + + key "property-name"; + uses property-instance; + } + } } diff --git a/nemo-api/src/main/yang/nemo-operation.yang b/nemo-api/src/main/yang/nemo-operation.yang index 219b192..8b4083a 100644 --- a/nemo-api/src/main/yang/nemo-operation.yang +++ b/nemo-api/src/main/yang/nemo-operation.yang @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Huawei Technologies Co., Ltd. and others. All rights reserved. + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, @@ -7,201 +7,288 @@ */ module nemo-operation { + yang-version 1; - yang-version 1; - namespace "urn:opendaylight:params:xml:ns:yang:nemo:operation"; - prefix "nemo-operation"; - - import nemo-common {prefix nemo-common;} - - revision "2015-06-29" { + namespace "urn:opendaylight:params:xml:ns:yang:nemo:operation"; + prefix "nemo-operation"; + + import nemo-common {prefix nemo-common;} + + revision "2015-10-10" { description "Initial revision."; } - - grouping parameter-definition { - leaf name { - description "A user-visible name for parameter"; - type nemo-common:parameter-name; - mandatory true; - } - leaf type { - description "The type of the parameter"; - default string; - type enumeration { - enum string { - description "A string-valued parameter"; - } - enum int { - description "An integer-valued parameter"; - } - enum range { - description "An integer-range parameter"; - } - } - } - leaf is-required { - description "Specify whether the parameter is required "; - default optional; - type enumeration { - enum required { - description "The parameter is required"; - } - enum optional { - description "The parameter is optional"; - } - } - } - } - - - container action-definitions { - list action-definition { - key "action-name"; - leaf action-name { - description "A name for the action definition"; - type nemo-common:action-definition-name; - mandatory true; - } - list data { - description - "data for the action that can be passed in."; - key "name"; - uses parameter-definition; - } - } - } - grouping action-parameter-instance{ - leaf data-name { - type nemo-common:data-name; - mandatory true; - } - leaf string-value { - type string; - } - leaf int-value { - type int64; - } - container range-value { - leaf min { - type int64; - mandatory true; - } - leaf max { - type int64; - mandatory true; - } - } - } - grouping action-instance{ - description " "; - leaf action-name{ - type nemo-common:action-instance-name; - mandatory true; - } - list data { - key "data-name"; - uses action-parameter-instance; - } - } - - container condition-definitions { - list condition-definition{ - key "condition-name"; - leaf condition-name{ - type nemo-common:condition-definition-name; - mandatory true; - } - list condition-parameter{ - key "name"; - uses parameter-definition; - min-elements 1; - } - } - } - grouping conditon-parameter-instance{ - leaf parameter-name { - type nemo-common:condition-parameter-name; - mandatory true; - } - leaf string-value { - type string; - } - leaf int-value { - type int64; - } - container range-value { - leaf min { - type int64; - mandatory true; - } - leaf max { - type int64; - mandatory true; - } - } - } - grouping condition-instance { - description " "; - leaf condition-name{ - type nemo-common:condition-instance-name; - mandatory true; - } - list condition-parameter{ - key "parameter-name"; - uses conditon-parameter-instance; - min-elements 1; - } - } - - - container constraint-definitions { - list constraint-definition{ - key "constraint-name"; - leaf constraint-name{ - type nemo-common:constraint-definition-name; - mandatory true; - } - list constraint-parameter{ - key "name"; - uses parameter-definition; - min-elements 1; - } - } - } - grouping constraint-parameter-instance{ - leaf parameter-name { - type nemo-common:constraint-parameter-name; - mandatory true; - } - leaf string-value { - type string; - } - leaf int-value { - type int64; - } - container range-value { - leaf min { - type int64; - mandatory true; - } - leaf max { - type int64; - mandatory true; - } - } - } - grouping constraint-instance { - description " "; - leaf constraint-name{ - type nemo-common:constraint-instance-name; - mandatory true; - } - list constraint-parameter{ - key "parameter-name"; - uses constraint-parameter-instance; - min-elements 1; - } - } - -} \ No newline at end of file + + container condition-parameter-definitions { + list condition-parameter-definition { + description + "Defines the condition parameter with its metadata."; + + key "parameter-name"; + leaf parameter-name { + description + "A name for the condition parameter."; + type nemo-common:parameter-name; + mandatory true; + } + + leaf parameter-value-type { + description + "A type of value for the condition parameter."; + type enumeration { + enum string { + description + "A string-valued parameter."; + } + enum int { + description + "An integer-valued parameter."; + } + enum range { + description + "An integer-range parameter."; + } + } + } + + container parameter-match-patterns { + description + "Defines the match patterns of the condition parameter."; + + leaf-list parameter-match-pattern { + type enumeration { + enum less-than; + enum not-less-than; + enum equal; + enum not-equal; + enum greater-than; + enum not-greater-than; + enum between; + enum periodical; + } + } + } + } + } + + container action-definitions { + list action-definition { + description + "Defines the actions which will be supported by the NEMO project."; + + key "action-name"; + leaf action-name { + description + "A name for the action definition."; + type nemo-common:action-name; + mandatory true; + } + + leaf parameter-value-type { + description + "The type of the action parameter."; + default string; + type enumeration { + enum string { + description + "A string-valued parameter."; + } + enum int { + description + "An integer-valued parameter."; + } + enum range { + description + "An integer-range parameter."; + } + } + } + } + } + + grouping condition-instance { + description + "Specific a instance of condition whose metadata has been filled in."; + + list condition-segment { + description + "The segment entities will be composed into a whole condition entity. + Each segment will be a sub expression of the condition."; + + key "condition-segment-id"; + leaf condition-segment-id { + description + "A unique ID for a condition segment."; + type nemo-common:condition-segment-id; + mandatory true; + } + + leaf condition-parameter-name { + description + "A name for a conditon parameter."; + type nemo-common:condition-parameter-name; + } + + leaf condition-parameter-match-pattern { + description + "The operator for the condition parameter and it's target value."; + type enumeration { + enum less-than; + enum not-less-than; + enum equal; + enum not-equal; + enum greater-than; + enum not-greater-than; + enum between; + enum periodical; + } + } + + container condition-parameter-target-value { + description + "The target value of condition parameter."; + + leaf string-value { + type string; + } + + leaf int-value { + type int64; + } + + container range-value { + leaf min { + type int64; + mandatory true; + } + + leaf max { + type int64; + mandatory true; + } + } + } + + leaf precursor-relation-operator { + description + "The logical operator between current segment and the next segment."; + type enumeration { + enum none; + enum and; + enum or; + enum not; + } + } + + leaf order { + description + "The order of the segment in the whole condition entity."; + type uint32; + } + } + } + + grouping action-instance { + description + "Specific a action instance whose metadata has been filled in."; + + leaf action-name { + description + "A name for a action instance."; + type nemo-common:action-name; + mandatory true; + } + + container parameter-values { + description + "The parameter value list of an action."; + + list string-value { + key "value order"; + leaf value { + type string; + } + + leaf order { + type uint32; + } + } + + list int-value { + key "value order"; + leaf value { + type int64; + } + + leaf order { + type uint32; + } + } + + container range-value { + leaf min { + type int64; + mandatory true; + } + + leaf max { + type int64; + mandatory true; + } + } + } + } + + grouping operation-instance { + description + "Specific an operation instance whose metadata has been filled in. + Operation is a type of intent which refers to taking for some specific + actions to realize the purpose."; + + leaf operation-id { + description + "A unique ID for a operation instance."; + type nemo-common:operation-id; + mandatory true; + } + + leaf operation-name { + description + "A user-visible and unique name for a operation instance."; + type nemo-common:operation-name; + mandatory true; + } + + leaf priority { + description + "Defines the priority of a operation instance."; + type uint32; + default 0; + } + + leaf target-object { + description + "The target object which the operation instance will apply to."; + type nemo-common:object-id; + mandatory true; + } + + uses condition-instance; + + list action { + description + "The action list for the operation instance."; + + key "action-name"; + uses action-instance; + + leaf order { + description + "The order of an action instance in execution sequence."; + type uint32; + } + + min-elements 1; + } + } +} diff --git a/nemo-api/src/main/yang/nemo-result.yang b/nemo-api/src/main/yang/nemo-result.yang index b350c21..6daf69b 100644 --- a/nemo-api/src/main/yang/nemo-result.yang +++ b/nemo-api/src/main/yang/nemo-result.yang @@ -1,58 +1,23 @@ /* - * Copyright (c) 2015 Huawei Technologies Co., Ltd. and others. All rights reserved. + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ -module nemo-result{ +module nemo-result { + yang-version 1; - yang-version 1; - namespace "urn:opendaylight:params:xml:ns:yang:nemo:result"; - prefix "nemo-result"; - - import nemo-common {prefix nemo-common;} - - revision "2015-06-29" { + namespace "urn:opendaylight:params:xml:ns:yang:nemo:result"; + prefix "nemo-result"; + + import nemo-common {prefix nemo-common;} + + revision "2015-10-10" { description "Initial revision."; } - - container expected-definitons{ - - } - - grouping expected-instance { - leaf expected-id { - type nemo-common:expected-instance-id; - mandatory true; - } - leaf expected-name{ - type nemo-common:expected-instance-name; - mandatory false; - } - leaf expected-description { - type nemo-common:description; - } - } - - container avoid-definitons{ - - } - grouping avoid-instance { - leaf avoid-id { - type nemo-common:avoid-instance-id; - mandatory true; - } - leaf avoid-name{ - type nemo-common:avoid-instance-name; - mandatory false; - } - leaf avoid-description { - type nemo-common:description; - } - } - -} \ No newline at end of file + // TBD +} diff --git a/nemo-api/src/main/yang/nemo-user.yang b/nemo-api/src/main/yang/nemo-user.yang new file mode 100644 index 0000000..a2d8928 --- /dev/null +++ b/nemo-api/src/main/yang/nemo-user.yang @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +module nemo-user { + yang-version 1; + + namespace "urn:opendaylight:params:xml:ns:yang:nemo:user"; + prefix "nemo-user"; + + import nemo-common {prefix nemo-common;} + + revision "2015-10-10" { + description + "Initial revision."; + } + + container user-roles { + list user-role { + description + "Defines the user role. Different users have different + intention manifestations, which have different granularity + or different level. It depends on users' role, knowledge + and their purpose."; + + key "role-name"; + leaf role-name { + description + "A user-visible and unique name for a kind of role."; + type nemo-common:user-role-name; + mandatory true; + } + + leaf role-description { + description + "Describes the characteristic,responsibility and purpose for a kind of role."; + type nemo-common:user-role-description; + } + + // TBD + } + } + + grouping user-instance { + description + "It represents an instance of the user."; + + leaf user-id { + description + "A unique ID for a user."; + type nemo-common:user-id; + mandatory true; + } + + leaf user-name { + description + "A user-visible and unique name for the user."; + type nemo-common:user-name; + mandatory true; + } + + leaf user-password { + description + "The password of a user."; + type nemo-common:user-password; + mandatory true; + } + + leaf user-role { + description + "The role of a user."; + type nemo-common:user-role-name; + mandatory true; + } + } +} diff --git a/nemo-features/pom.xml b/nemo-features/pom.xml index c678d52..e4db9ed 100644 --- a/nemo-features/pom.xml +++ b/nemo-features/pom.xml @@ -26,10 +26,11 @@ and is available at http://www.eclipse.org/legal/epl-v10.html - 1.3.0-SNAPSHOT 0.8.0-SNAPSHOT + 1.3.0-SNAPSHOT 1.3.0-SNAPSHOT 0.3.0-SNAPSHOT + 0.2.0-SNAPSHOT @@ -44,7 +45,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html org.opendaylight.controller mdsal-artifacts - ${controller.mdsal.version} + ${mdsal.version} pom import @@ -97,6 +98,22 @@ and is available at http://www.eclipse.org/legal/epl-v10.html xml runtime + + + org.opendaylight.openflowplugin + features-openflowplugin + ${openflowplugin.version} + features + xml + + + org.opendaylight.openflowplugin + features-openflowplugin-extension + ${openflowplugin.version} + features + xml + + ${project.groupId} nemo-api @@ -107,6 +124,13 @@ and is available at http://www.eclipse.org/legal/epl-v10.html nemo-impl ${project.version} + + ${project.groupId} + nemo-impl + ${project.version} + config + xml + ${project.groupId} openflow-renderer @@ -119,6 +143,13 @@ and is available at http://www.eclipse.org/legal/epl-v10.html config xml + + ${project.groupId} + openflow-renderer + ${project.version} + resource + json + ${project.groupId} nemo-ui diff --git a/nemo-features/src/main/features/features.xml b/nemo-features/src/main/features/features.xml index 4cec890..f14ab7c 100644 --- a/nemo-features/src/main/features/features.xml +++ b/nemo-features/src/main/features/features.xml @@ -9,28 +9,37 @@ and is available at http://www.eclipse.org/legal/epl-v10.html xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0"> mvn:org.opendaylight.mdsal.model/features-mdsal-model/${mdsal.model.version}/xml/features - mvn:org.opendaylight.controller/features-mdsal/${controller.mdsal.version}/xml/features + mvn:org.opendaylight.controller/features-mdsal/${mdsal.version}/xml/features mvn:org.opendaylight.netconf/features-restconf/${restconf.version}/xml/features mvn:org.opendaylight.dlux/features-dlux/${dlux.version}/xml/features + mvn:org.opendaylight.openflowplugin/features-openflowplugin/${openflowplugin.version}/xml/features + mvn:org.opendaylight.openflowplugin/features-openflowplugin-extension/${openflowplugin.version}/xml/features odl-mdsal-models mvn:org.opendaylight.nemo/nemo-api/${project.version} - odl-mdsal-broker + odl-mdsal-broker odl-nemo-api mvn:org.opendaylight.nemo/nemo-impl/${project.version} + mvn:org.opendaylight.nemo/nemo-impl/${project.version}/xml/config odl-restconf - odl-mdsal-apidocs - odl-mdsal-xsql + odl-mdsal-apidocs + odl-mdsal-xsql odl-nemo-engine - odl-nemo-engine + odl-openflowplugin-flow-services + odl-openflowplugin-nxm-extensions + odl-nemo-engine-rest mvn:org.opendaylight.nemo/openflow-renderer/${project.version} - mvn:org.opendaylight.nemo/openflow-renderer/${project.version}/xml/config + mvn:org.opendaylight.nemo/openflow-renderer/${project.version}/xml/config + mvn:org.opendaylight.nemo/openflow-renderer/${project.version}/json/resource + + + odl-nemo-engine-rest odl-dlux-core diff --git a/nemo-impl/pom.xml b/nemo-impl/pom.xml index fdb8145..c66209c 100644 --- a/nemo-impl/pom.xml +++ b/nemo-impl/pom.xml @@ -10,9 +10,9 @@ and is available at http://www.eclipse.org/legal/epl-v10.html 4.0.0 - org.opendaylight.mdsal - binding-parent - 0.8.0-SNAPSHOT + org.opendaylight.controller + config-parent + 0.4.0-SNAPSHOT @@ -24,14 +24,48 @@ and is available at http://www.eclipse.org/legal/epl-v10.html 0.7.2.201409121644 + target/code-coverage/jacoco.exec + target/code-coverage/jacoco-it.exec + + org.opendaylight.mdsal.model + ietf-inet-types + + + org.opendaylight.mdsal.model + ietf-yang-types + ${project.groupId} nemo-api ${project.version} + + net.sourceforge.collections + collections-generic + 4.01 + + + net.sf.jung + jung-api + 2.0.1 + + + net.sf.jung + jung-graph-impl + 2.0.1 + + + net.sf.jung + jung-algorithms + 2.0.1 + + + com.google.guava + guava + junit junit @@ -59,26 +93,101 @@ and is available at http://www.eclipse.org/legal/epl-v10.html - org.jacoco - jacoco-maven-plugin + org.opendaylight.yangtools + yang-maven-plugin + + + + generate-sources + + + src/main/yang + + + + org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl + + + ${salGeneratorPath} + + + + true + + + + + + org.opendaylight.mdsal + maven-sal-api-gen-plugin + ${yangtools.version} + jar + + + + + org.apache.felix + maven-bundle-plugin + true - - org.opendaylight.nemo.* - + + .,{maven-dependencies} + *;resolution:=optional + + collections-generic,jung-api,jung-graph-impl,jung-algorithms + + true + lib + true + <_failok>true + <_nouses>true + + ${project.build.outputDirectory}/META-INF + + + org.codehaus.mojo + build-helper-maven-plugin + + + attach-artifacts + + attach-artifact + + package + + + + ${project.build.directory}/classes/etc/opendaylight/karaf/config.xml + xml + config + + + + + + + + org.jacoco + jacoco-maven-plugin - pre-test + pre-unit-test prepare-agent + + ${sonar.jacoco.reportPath} + - post-test + post-unit-test report - test + + ${sonar.jacoco.reportPath} + diff --git a/nemo-impl/src/main/java/README b/nemo-impl/src/main/java/README deleted file mode 100644 index e69de29..0000000 diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/intent/ConnectionMapper.java b/nemo-impl/src/main/java/org/opendaylight/nemo/intent/ConnectionMapper.java new file mode 100644 index 0000000..6d94b16 --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/intent/ConnectionMapper.java @@ -0,0 +1,1403 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.nemo.intent; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.VirtualNetwork; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.links.VirtualLink; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.links.VirtualLinkBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.nodes.VirtualNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.node.instance.VirtualPort; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.node.instance.VirtualPortBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.intent.vn.mapping.results.UserIntentVnMapping; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.intent.vn.mapping.results.user.intent.vn.mapping.IntentVnMappingResult; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.intent.vn.mapping.results.user.intent.vn.mapping.IntentVnMappingResultBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.intent.vn.mapping.results.user.intent.vn.mapping.intent.vn.mapping.result.VirtualResource; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.intent.vn.mapping.results.user.intent.vn.mapping.intent.vn.mapping.result.VirtualResourceBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.*; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.common.rev151010.*; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Connection; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.users.User; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.object.rev151010.connection.instance.Property; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +/** + * Resolve the user's connection intent. Create the virtual link according + * to the connection if necessary, and then map the created virtual link + * into the physical network. Finally, store these intent mapping results + * into the data store. + * + * @author Zhigang Ji + */ +public class ConnectionMapper { + private static final Logger LOG = LoggerFactory.getLogger(ConnectionMapper.class); + + private final DataBroker dataBroker; + + /** + * The node mapper to resolve the user's node intent. + */ + private NodeMapper nodeMapper; + + public ConnectionMapper(DataBroker dataBroker, NodeMapper nodeMapper) { + super(); + + this.dataBroker = dataBroker; + this.nodeMapper = nodeMapper; + + LOG.debug("Initialized the renderer common connection mapper."); + + return; + } + + /** + * Resolve the user's connection intent, perform the intent mapping + * if necessary, and store the intent mapping results into data store. + * + * @param user The user for the connection. + * @param connection The connection to be resolved. + * @param virtualNetwork The virtual network for the user. + * @param userIntentVnMapping The intent-vn mapping for the user. + */ + protected void resolveConnection(User user, Connection connection, + VirtualNetwork virtualNetwork, + UserIntentVnMapping userIntentVnMapping) + throws IntentResolutionException { + ConnectionType connectionType = connection.getConnectionType(); + + if ( connectionType.equals(new ConnectionType("p2p")) ) { + resolveP2PConnection(user, connection, virtualNetwork, userIntentVnMapping, false, true, true); + + return; + } + + if ( connectionType.equals(new ConnectionType("p2mp")) ) { + resolveP2MPConnection(user, connection, virtualNetwork, userIntentVnMapping); + + return; + } + + if ( connectionType.equals(new ConnectionType("mesh")) ) { + resolveMeshConnection(user, connection, virtualNetwork, userIntentVnMapping); + + return; + } + + throw new IntentResolutionException("Unknown connection type."); + +// return; + } + + /** + * TODO + * + * @param user TODO + * @param connection TODO + * @param virtualNetwork TODO + * @param userIntentVnMapping TODO + * @param tempConnection TODO + * @param resolvingEndNode1 TODO + * @param resolvingEndNode2 TODO + * @return TODO + */ + private List resolveP2PConnection(User user, Connection connection, + VirtualNetwork virtualNetwork, + UserIntentVnMapping userIntentVnMapping, + boolean tempConnection, + boolean resolvingEndNode1, + boolean resolvingEndNode2) + throws IntentResolutionException { + List nodes = user.getObjects().getNode(); + NodeId nodeId = connection.getEndNode().get(0).getNodeId(); + Node endNode1 = IntentResolverUtils.getNode(nodes, nodeId); + + if ( null == endNode1 ) { + throw new IntentResolutionException("The end-node " + nodeId.getValue() + + " of the connection " + connection.getConnectionId().getValue() + + " does not exist."); + } + + nodeId = connection.getEndNode().get(1).getNodeId(); + Node endNode2 = IntentResolverUtils.getNode(nodes, nodeId); + + if ( null == endNode2 ) { + throw new IntentResolutionException("The end-node " + nodeId.getValue() + + " of the connection " + connection.getConnectionId().getValue() + + " does not exist."); + } + + NodeType hostNodeType = new NodeType("host"); + NodeType layer2GroupNodeType = new NodeType("l2-group"); + NodeType layer3GroupNodeType = new NodeType("l3-group"); + NodeType externalGroupNodeType = new NodeType("ext-group"); + NodeType serviceChainGroupNodeType = new NodeType("chain-group"); + NodeType firewallNodeType = new NodeType("fw"); + NodeType loadbalancerNodeType = new NodeType("lb"); + NodeType cacheNodeType = new NodeType("cache"); + + if ( endNode1.getNodeType().equals(hostNodeType) ) { + throw new IntentResolutionException("The end-node " + endNode1.getNodeId().getValue() + + " of the connection " + connection.getConnectionId().getValue() + + " can not be host type."); + } + + if ( endNode1.getNodeType().equals(layer2GroupNodeType) ) { + if ( endNode2.getNodeType().equals(hostNodeType) ) { + throw new IntentResolutionException("The end-node " + endNode2.getNodeId().getValue() + + " of the connection " + connection.getConnectionId().getValue() + + " can not be host type."); + } + + if ( endNode2.getNodeType().equals(layer2GroupNodeType) ) { + return resolveP2PConnectionBetweenLayer2Groups(user, connection, + endNode1, endNode2, virtualNetwork, userIntentVnMapping, + tempConnection, resolvingEndNode1, resolvingEndNode2); + } + + if ( endNode2.getNodeType().equals(layer3GroupNodeType) ) { + return resolveP2PConnectionBetweenLayer2AndLayer3Groups(user, connection, + endNode1, endNode2, virtualNetwork, userIntentVnMapping, + tempConnection, resolvingEndNode1, resolvingEndNode2); + } + + if ( endNode2.getNodeType().equals(externalGroupNodeType) ) { + if ( IntentResolverUtils.checkExternalLayer3Group(endNode2) ) { + return resolveP2PConnectionBetweenLayer2AndExternalLayer3Groups(user, connection, + endNode1, endNode2, virtualNetwork, userIntentVnMapping, + tempConnection, resolvingEndNode1, resolvingEndNode2); + } else { + return resolveP2PConnectionBetweenLayer2AndExternalLayer2Groups(user, connection, + endNode1, endNode2, virtualNetwork, userIntentVnMapping, + tempConnection, resolvingEndNode1, resolvingEndNode2); + } + } + + if ( endNode2.getNodeType().equals(serviceChainGroupNodeType) ) { + return null; + } + + if ( endNode2.getNodeType().equals(firewallNodeType) ) { + throw new IntentResolutionException("The end-node " + endNode2.getNodeId().getValue() + + " of the connection " + connection.getConnectionId().getValue() + + " can not be fw type."); + } + + if ( endNode2.getNodeType().equals(loadbalancerNodeType) ) { + throw new IntentResolutionException("The end-node " + endNode2.getNodeId().getValue() + + " of the connection " + connection.getConnectionId().getValue() + + " can not be lb type."); + } + + if ( endNode2.getNodeType().equals(cacheNodeType) ) { + throw new IntentResolutionException("The end-node " + endNode2.getNodeId().getValue() + + " of the connection " + connection.getConnectionId().getValue() + + " can not be cache type."); + } + } + + if ( endNode1.getNodeType().equals(layer3GroupNodeType) ) { + if ( endNode2.getNodeType().equals(hostNodeType) ) { + throw new IntentResolutionException("The end-node " + endNode2.getNodeId().getValue() + + " of the connection " + connection.getConnectionId().getValue() + + " can not be host type."); + } + + if ( endNode2.getNodeType().equals(layer2GroupNodeType) ) { + return resolveP2PConnectionBetweenLayer2AndLayer3Groups(user, connection, + endNode2, endNode1, virtualNetwork, userIntentVnMapping, + tempConnection, resolvingEndNode1, resolvingEndNode2); + } + + if ( endNode2.getNodeType().equals(layer3GroupNodeType) ) { + return resolveP2PConnectionBetweenLayer3Groups(user, connection, endNode1, + endNode2, virtualNetwork, userIntentVnMapping, + tempConnection, resolvingEndNode1, resolvingEndNode2); + } + + if ( endNode2.getNodeType().equals(externalGroupNodeType) ) { + if ( IntentResolverUtils.checkExternalLayer3Group(endNode2) ) { + return resolveP2PConnectionBetweenLayer3AndExternalLayer3Groups(user, connection, + endNode1, endNode2, virtualNetwork, userIntentVnMapping, + tempConnection, resolvingEndNode1, resolvingEndNode2); + } else { + return resolveP2PConnectionBetweenLayer3AndExternalLayer2Groups(user, connection, + endNode1, endNode2, virtualNetwork, userIntentVnMapping, + tempConnection, resolvingEndNode1, resolvingEndNode2); + } + } + + if ( endNode2.getNodeType().equals(serviceChainGroupNodeType) ) { + return null; + } + + if ( endNode2.getNodeType().equals(firewallNodeType) ) { + throw new IntentResolutionException("The end-node " + endNode2.getNodeId().getValue() + + " of the connection " + connection.getConnectionId().getValue() + + " can not be fw type."); + } + + if ( endNode2.getNodeType().equals(loadbalancerNodeType) ) { + throw new IntentResolutionException("The end-node " + endNode2.getNodeId().getValue() + + " of the connection " + connection.getConnectionId().getValue() + + " can not be lb type."); + } + + if ( endNode2.getNodeType().equals(cacheNodeType) ) { + throw new IntentResolutionException("The end-node " + endNode2.getNodeId().getValue() + + " of the connection " + connection.getConnectionId().getValue() + + " can not be cache type."); + } + } + + if ( endNode1.getNodeType().equals(externalGroupNodeType) ) { + if ( endNode2.getNodeType().equals(hostNodeType) ) { + throw new IntentResolutionException("The end-node " + endNode2.getNodeId().getValue() + + " of the connection " + connection.getConnectionId().getValue() + + " can not be host type."); + } + + if ( endNode2.getNodeType().equals(serviceChainGroupNodeType) ) { + return null; + } + + if ( endNode2.getNodeType().equals(firewallNodeType) ) { + throw new IntentResolutionException("The end-node " + endNode2.getNodeId().getValue() + + " of the connection " + connection.getConnectionId().getValue() + + " can not be fw type."); + } + + if ( endNode2.getNodeType().equals(loadbalancerNodeType) ) { + throw new IntentResolutionException("The end-node " + endNode2.getNodeId().getValue() + + " of the connection " + connection.getConnectionId().getValue() + + " can not be lb type."); + } + + if ( endNode2.getNodeType().equals(cacheNodeType) ) { + throw new IntentResolutionException("The end-node " + endNode2.getNodeId().getValue() + + " of the connection " + connection.getConnectionId().getValue() + + " can not be cache type."); + } + + if ( IntentResolverUtils.checkExternalLayer3Group(endNode1) ) { + if ( endNode2.getNodeType().equals(layer2GroupNodeType) ) { + return resolveP2PConnectionBetweenLayer2AndExternalLayer3Groups(user, connection, + endNode2, endNode1, virtualNetwork, userIntentVnMapping, + tempConnection, resolvingEndNode1, resolvingEndNode2); + } + + if ( endNode2.getNodeType().equals(layer3GroupNodeType) ) { + return resolveP2PConnectionBetweenLayer3AndExternalLayer3Groups(user, connection, + endNode2, endNode1, virtualNetwork, userIntentVnMapping, + tempConnection, resolvingEndNode1, resolvingEndNode2); + } + + if ( endNode2.getNodeType().equals(externalGroupNodeType) ) { + if ( IntentResolverUtils.checkExternalLayer3Group(endNode2) ) { + return resolveP2PConnectionBetweenExternalLayer3Groups(user, connection, + endNode1, endNode2, virtualNetwork, userIntentVnMapping, + tempConnection, resolvingEndNode1, resolvingEndNode2); + } else { + return resolveP2PConnectionBetweenExternalLayer2AndLayer3Groups(user, connection, + endNode2, endNode1, virtualNetwork, userIntentVnMapping, + tempConnection, resolvingEndNode1, resolvingEndNode2); + } + } + } else { + if ( endNode2.getNodeType().equals(layer2GroupNodeType) ) { + return resolveP2PConnectionBetweenLayer2AndExternalLayer2Groups(user, connection, + endNode2, endNode1, virtualNetwork, userIntentVnMapping, + tempConnection, resolvingEndNode1, resolvingEndNode2); + } + + if ( endNode2.getNodeType().equals(layer3GroupNodeType) ) { + return resolveP2PConnectionBetweenLayer3AndExternalLayer2Groups(user, connection, + endNode2, endNode1, virtualNetwork, userIntentVnMapping, + tempConnection, resolvingEndNode1, resolvingEndNode2); + } + + if ( endNode2.getNodeType().equals(externalGroupNodeType) ) { + if ( IntentResolverUtils.checkExternalLayer3Group(endNode2) ) { + return resolveP2PConnectionBetweenExternalLayer2AndLayer3Groups(user, connection, + endNode1, endNode2, virtualNetwork, userIntentVnMapping, + tempConnection, resolvingEndNode1, resolvingEndNode2); + } else { + return resolveP2PConnectionBetweenExternalLayer2Groups(user, connection, + endNode1, endNode2, virtualNetwork, userIntentVnMapping, + tempConnection, resolvingEndNode1, resolvingEndNode2); + } + } + } + } + + if ( endNode1.getNodeType().equals(serviceChainGroupNodeType) ) { + return null; + } + + if ( endNode1.getNodeType().equals(firewallNodeType) ) { + throw new IntentResolutionException("The end-node " + endNode1.getNodeId().getValue() + + " of the connection " + connection.getConnectionId().getValue() + + " can not be fw type."); + } + + if ( endNode1.getNodeType().equals(loadbalancerNodeType) ) { + throw new IntentResolutionException("The end-node " + endNode1.getNodeId().getValue() + + " of the connection " + connection.getConnectionId().getValue() + + " can not be lb type."); + } + + if ( endNode1.getNodeType().equals(cacheNodeType) ) { + throw new IntentResolutionException("The end-node " + endNode1.getNodeId().getValue() + + " of the connection " + connection.getConnectionId().getValue() + + " can not be cache type."); + } + + throw new IntentResolutionException("Unknown node type for the end-nodes of the connection " + + connection.getConnectionId().getValue() + "."); + +// return null; + } + + /** + * TODO + * + * @param user TODO + * @param connection TODO + * @param virtualNetwork TODO + * @param userIntentVnMapping TODO + */ + private void resolveP2MPConnection(User user, Connection connection, + VirtualNetwork virtualNetwork, + UserIntentVnMapping userIntentVnMapping) + throws IntentResolutionException { + // TODO: 1、注意root是external layer2 group的情况,只能映射一次。 + + return; + } + + /** + * TODO + * + * @param user TODO + * @param connection TODO + * @param virtualNetwork TODO + * @param userIntentVnMapping TODO + */ + private void resolveMeshConnection(User user, Connection connection, + VirtualNetwork virtualNetwork, + UserIntentVnMapping userIntentVnMapping) + throws IntentResolutionException { + // TODO: 1、注意各个end node是external layer2 group的情况,只能映射一次。 + + return; + } + + /** + * TODO + * + * @param user TODO + * @param connection TODO + * @param endNode1 TODO + * @param endNode2 TODO + * @param virtualNetwork TODO + * @param userIntentVnMapping TODO + * @param tempConnection TODO + * @param resolvingEndNode1 TODO + * @param resolvingEndNode2 TODO + * @return TODO + */ + private List resolveP2PConnectionBetweenLayer2Groups(User user, + Connection connection, + Node endNode1, + Node endNode2, + VirtualNetwork virtualNetwork, + UserIntentVnMapping userIntentVnMapping, + boolean tempConnection, + boolean resolvingEndNode1, + boolean resolvingEndNode2) + throws IntentResolutionException { + List intentVnMappingResults = userIntentVnMapping.getIntentVnMappingResult(); + IntentVnMappingResult intentVnMappingResult1 = IntentResolverUtils + .getIntentVnMappingResult(intentVnMappingResults, new IntentId(endNode1.getNodeId().getValue())); + + if ( null == intentVnMappingResult1 ) { + throw new IntentResolutionException("Can not get the intent-vn mapping result for " + + "the node " + endNode1.getNodeId().getValue() + "."); + } + + IntentVnMappingResult intentVnMappingResult2 = IntentResolverUtils + .getIntentVnMappingResult(intentVnMappingResults, new IntentId(endNode2.getNodeId().getValue())); + + if ( null == intentVnMappingResult2 ) { + throw new IntentResolutionException("Can not get the intent-vn mapping result for " + + "the node " + endNode2.getNodeId().getValue() + "."); + } + + List virtualNodes = virtualNetwork.getVirtualNodes().getVirtualNode(); + VirtualNodeId virtualNodeId = new VirtualNodeId(intentVnMappingResult1.getVirtualResource().get(0) + .getVirtualResourceEntityId().getValue()); + VirtualNode virtualRouter1 = IntentResolverUtils.getVirtualNode(virtualNodes, virtualNodeId); + + if ( null == virtualRouter1 ) { + throw new IntentResolutionException("Can not get the virtual node created for " + + "the node " + endNode1.getNodeId().getValue() + "."); + } + + virtualNodeId = new VirtualNodeId(intentVnMappingResult2.getVirtualResource().get(0) + .getVirtualResourceEntityId().getValue()); + VirtualNode virtualRouter2 = IntentResolverUtils.getVirtualNode(virtualNodes, virtualNodeId); + + if ( null == virtualRouter2 ) { + throw new IntentResolutionException("Can not get the virtual node created for " + + "the node " + endNode2.getNodeId().getValue() + "."); + } + + Property property = IntentResolverUtils + .getConnectionProperty(connection.getProperty(), new PropertyName("bandwidth")); + long bandwidth = 0; + + if ( null != property ) { + bandwidth = /*1024 * */property.getPropertyValues().getIntValue().get(0).getValue(); + } + + VirtualPort virtualPort1 = new VirtualPortBuilder() + .setPortId(new VirtualPortId(UUID.randomUUID().toString())) + .setPortType(VirtualPort.PortType.Internal) + .setBandwidth(bandwidth) + .build(); + virtualRouter1.getVirtualPort().add(virtualPort1); + + VirtualPort virtualPort2 = new VirtualPortBuilder() + .setPortId(new VirtualPortId(UUID.randomUUID().toString())) + .setPortType(VirtualPort.PortType.Internal) + .setBandwidth(bandwidth) + .build(); + virtualRouter2.getVirtualPort().add(virtualPort2); + + VirtualLink virtualLink1 = new VirtualLinkBuilder() + .setLinkId(new VirtualLinkId(UUID.randomUUID().toString())) + .setSrcNodeId(virtualRouter1.getNodeId()) + .setSrcPortId(virtualPort1.getPortId()) + .setDestNodeId(virtualRouter2.getNodeId()) + .setDestPortId(virtualPort2.getPortId()) + .setBandwidth(bandwidth) + .build(); + VirtualLink virtualLink2 = new VirtualLinkBuilder() + .setLinkId(new VirtualLinkId(UUID.randomUUID().toString())) + .setSrcNodeId(virtualRouter2.getNodeId()) + .setSrcPortId(virtualPort2.getPortId()) + .setDestNodeId(virtualRouter1.getNodeId()) + .setDestPortId(virtualPort1.getPortId()) + .setBandwidth(bandwidth) + .build(); + + if ( tempConnection ) { + List virtualLinks = new ArrayList(2); + + virtualLinks.add(virtualLink1); + virtualLinks.add(virtualLink2); + + return virtualLinks; + } + + List virtualLinks = virtualNetwork.getVirtualLinks().getVirtualLink(); + + virtualLinks.add(virtualLink1); + virtualLinks.add(virtualLink2); + + List virtualResources = new ArrayList(2); + + VirtualResource virtualResource = new VirtualResourceBuilder() + .setVirtualResourceId(new VirtualResourceId(UUID.randomUUID().toString())) + .setVirtualResourceType(VirtualResource.VirtualResourceType.Vlink) + .setVirtualResourceEntityId(new VirtualResourceEntityId(virtualLink1.getLinkId().getValue())) + .setOrder(0L) + .build(); + virtualResources.add(virtualResource); + + virtualResource = new VirtualResourceBuilder() + .setVirtualResourceId(new VirtualResourceId(UUID.randomUUID().toString())) + .setVirtualResourceType(VirtualResource.VirtualResourceType.Vlink) + .setVirtualResourceEntityId(new VirtualResourceEntityId(virtualLink2.getLinkId().getValue())) + .setOrder(0L) + .build(); + virtualResources.add(virtualResource); + + IntentVnMappingResult intentVnMappingResult = new IntentVnMappingResultBuilder() + .setIntentId(new IntentId(connection.getConnectionId().getValue())) + .setIntentType(IntentVnMappingResult.IntentType.Connection) + .setVirtualResource(virtualResources) + .build(); + + intentVnMappingResults.add(intentVnMappingResult); + + return null; + } + + /** + * TODO + * + * @param user TODO + * @param connection TODO + * @param endNode1 TODO + * @param endNode2 TODO + * @param virtualNetwork TODO + * @param userIntentVnMapping TODO + * @param tempConnection TODO + * @param resolvingEndNode1 TODO + * @param resolvingEndNode2 TODO + * @return TODO + */ + private List resolveP2PConnectionBetweenLayer2AndLayer3Groups(User user, + Connection connection, + Node endNode1, + Node endNode2, + VirtualNetwork virtualNetwork, + UserIntentVnMapping userIntentVnMapping, + boolean tempConnection, + boolean resolvingEndNode1, + boolean resolvingEndNode2) + throws IntentResolutionException { + // TODO: l2-group - l3-group: 创建l2-group的gw vrouter与l3-group的sub-nodes的gw/acc vrouters间的vlinks(vports)。 + + return null; + } + + /** + * TODO + * + * @param user TODO + * @param connection TODO + * @param endNode1 TODO + * @param endNode2 TODO + * @param virtualNetwork TODO + * @param userIntentVnMapping TODO + * @param tempConnection TODO + * @param resolvingEndNode1 TODO + * @param resolvingEndNode2 TODO + * @return TODO + */ + private List resolveP2PConnectionBetweenLayer2AndExternalLayer2Groups(User user, + Connection connection, + Node endNode1, + Node endNode2, + VirtualNetwork virtualNetwork, + UserIntentVnMapping userIntentVnMapping, + boolean tempConnection, + boolean resolvingEndNode1, + boolean resolvingEndNode2) + throws IntentResolutionException { + if ( resolvingEndNode2 ) { + nodeMapper.resolveExternalLayer2Group(user, endNode2, virtualNetwork, userIntentVnMapping, true); + } + + List intentVnMappingResults = userIntentVnMapping.getIntentVnMappingResult(); + IntentVnMappingResult intentVnMappingResult1 = IntentResolverUtils + .getIntentVnMappingResult(intentVnMappingResults, new IntentId(endNode1.getNodeId().getValue())); + + if ( null == intentVnMappingResult1 ) { + throw new IntentResolutionException("Can not get the intent-vn mapping result for " + + "the node " + endNode1.getNodeId().getValue() + "."); + } + + IntentVnMappingResult intentVnMappingResult2 = IntentResolverUtils + .getIntentVnMappingResult(intentVnMappingResults, new IntentId(endNode2.getNodeId().getValue())); + + if ( null == intentVnMappingResult2 ) { + throw new IntentResolutionException("Can not get the intent-vn mapping result for " + + "the node " + endNode2.getNodeId().getValue() + "."); + } + + List virtualNodes = virtualNetwork.getVirtualNodes().getVirtualNode(); + VirtualNodeId virtualNodeId = new VirtualNodeId(intentVnMappingResult1.getVirtualResource().get(0) + .getVirtualResourceEntityId().getValue()); + VirtualNode virtualRouter1 = IntentResolverUtils.getVirtualNode(virtualNodes, virtualNodeId); + + if ( null == virtualRouter1 ) { + throw new IntentResolutionException("Can not get the virtual node created for " + + "the node " + endNode1.getNodeId().getValue() + "."); + } + + virtualNodeId = new VirtualNodeId(intentVnMappingResult2.getVirtualResource().get(0) + .getParentVirtualResourceEntityId().getValue()); + VirtualNode virtualRouter2 = IntentResolverUtils.getVirtualNode(virtualNodes, virtualNodeId); + + if ( null == virtualRouter2 ) { + throw new IntentResolutionException("Can not get the virtual node created for " + + "the node " + endNode2.getNodeId().getValue() + "."); + } + + Property property = IntentResolverUtils + .getConnectionProperty(connection.getProperty(), new PropertyName("bandwidth")); + long bandwidth = 0; + + if ( null != property ) { + bandwidth = /*1024 * */property.getPropertyValues().getIntValue().get(0).getValue(); + } + + VirtualPort virtualPort1 = new VirtualPortBuilder() + .setPortId(new VirtualPortId(UUID.randomUUID().toString())) + .setPortType(VirtualPort.PortType.Internal) + .setBandwidth(bandwidth) + .build(); + virtualRouter1.getVirtualPort().add(virtualPort1); + + VirtualPort virtualPort2 = new VirtualPortBuilder() + .setPortId(new VirtualPortId(UUID.randomUUID().toString())) + .setPortType(VirtualPort.PortType.Internal) + .setBandwidth(bandwidth) + .build(); + virtualRouter2.getVirtualPort().add(virtualPort2); + + VirtualLink virtualLink1 = new VirtualLinkBuilder() + .setLinkId(new VirtualLinkId(UUID.randomUUID().toString())) + .setSrcNodeId(virtualRouter1.getNodeId()) + .setSrcPortId(virtualPort1.getPortId()) + .setDestNodeId(virtualRouter2.getNodeId()) + .setDestPortId(virtualPort2.getPortId()) + .setBandwidth(bandwidth) + .build(); + VirtualLink virtualLink2 = new VirtualLinkBuilder() + .setLinkId(new VirtualLinkId(UUID.randomUUID().toString())) + .setSrcNodeId(virtualRouter2.getNodeId()) + .setSrcPortId(virtualPort2.getPortId()) + .setDestNodeId(virtualRouter1.getNodeId()) + .setDestPortId(virtualPort1.getPortId()) + .setBandwidth(bandwidth) + .build(); + + if ( tempConnection ) { + List virtualLinks = new ArrayList(2); + + virtualLinks.add(virtualLink1); + virtualLinks.add(virtualLink2); + + return virtualLinks; + } + + List virtualLinks = virtualNetwork.getVirtualLinks().getVirtualLink(); + + virtualLinks.add(virtualLink1); + virtualLinks.add(virtualLink2); + + List virtualResources = new ArrayList(2); + + VirtualResource virtualResource = new VirtualResourceBuilder() + .setVirtualResourceId(new VirtualResourceId(UUID.randomUUID().toString())) + .setVirtualResourceType(VirtualResource.VirtualResourceType.Vlink) + .setVirtualResourceEntityId(new VirtualResourceEntityId(virtualLink1.getLinkId().getValue())) + .setOrder(0L) + .build(); + virtualResources.add(virtualResource); + + virtualResource = new VirtualResourceBuilder() + .setVirtualResourceId(new VirtualResourceId(UUID.randomUUID().toString())) + .setVirtualResourceType(VirtualResource.VirtualResourceType.Vlink) + .setVirtualResourceEntityId(new VirtualResourceEntityId(virtualLink2.getLinkId().getValue())) + .setOrder(0L) + .build(); + virtualResources.add(virtualResource); + + IntentVnMappingResult intentVnMappingResult = new IntentVnMappingResultBuilder() + .setIntentId(new IntentId(connection.getConnectionId().getValue())) + .setIntentType(IntentVnMappingResult.IntentType.Connection) + .setVirtualResource(virtualResources) + .build(); + + intentVnMappingResults.add(intentVnMappingResult); + + return null; + } + + /** + * TODO + * + * @param user TODO + * @param connection TODO + * @param endNode1 TODO + * @param endNode2 TODO + * @param virtualNetwork TODO + * @param userIntentVnMapping TODO + * @param tempConnection TODO + * @param resolvingEndNode1 TODO + * @param resolvingEndNode2 TODO + * @return TODO + */ + private List resolveP2PConnectionBetweenLayer2AndExternalLayer3Groups(User user, + Connection connection, + Node endNode1, + Node endNode2, + VirtualNetwork virtualNetwork, + UserIntentVnMapping userIntentVnMapping, + boolean tempConnection, + boolean resolvingEndNode1, + boolean resolvingEndNode2) + throws IntentResolutionException { + List intentVnMappingResults = userIntentVnMapping.getIntentVnMappingResult(); + IntentVnMappingResult intentVnMappingResult1 = IntentResolverUtils + .getIntentVnMappingResult(intentVnMappingResults, new IntentId(endNode1.getNodeId().getValue())); + + if ( null == intentVnMappingResult1 ) { + throw new IntentResolutionException("Can not get the intent-vn mapping result for " + + "the node " + endNode1.getNodeId().getValue() + "."); + } + + IntentVnMappingResult intentVnMappingResult2 = IntentResolverUtils + .getIntentVnMappingResult(intentVnMappingResults, new IntentId(endNode2.getNodeId().getValue())); + + if ( null == intentVnMappingResult2 ) { + throw new IntentResolutionException("Can not get the intent-vn mapping result for " + + "the node " + endNode2.getNodeId().getValue() + "."); + } + + List virtualNodes = virtualNetwork.getVirtualNodes().getVirtualNode(); + VirtualNodeId virtualNodeId = new VirtualNodeId(intentVnMappingResult1.getVirtualResource().get(0) + .getVirtualResourceEntityId().getValue()); + VirtualNode virtualRouter1 = IntentResolverUtils.getVirtualNode(virtualNodes, virtualNodeId); + + if ( null == virtualRouter1 ) { + throw new IntentResolutionException("Can not get the virtual node created for " + + "the node " + endNode1.getNodeId().getValue() + "."); + } + + virtualNodeId = new VirtualNodeId(intentVnMappingResult2.getVirtualResource().get(0) + .getParentVirtualResourceEntityId().getValue()); + VirtualNode virtualRouter2 = IntentResolverUtils.getVirtualNode(virtualNodes, virtualNodeId); + + if ( null == virtualRouter2 ) { + throw new IntentResolutionException("Can not get the virtual node created for " + + "the node " + endNode2.getNodeId().getValue() + "."); + } + + Property property = IntentResolverUtils + .getConnectionProperty(connection.getProperty(), new PropertyName("bandwidth")); + long bandwidth = 0; + + if ( null != property ) { + bandwidth = /*1024 * */property.getPropertyValues().getIntValue().get(0).getValue(); + } + + VirtualPort virtualPort1 = new VirtualPortBuilder() + .setPortId(new VirtualPortId(UUID.randomUUID().toString())) + .setPortType(VirtualPort.PortType.Internal) + .setBandwidth(bandwidth) + .build(); + virtualRouter1.getVirtualPort().add(virtualPort1); + + VirtualPort virtualPort2 = new VirtualPortBuilder() + .setPortId(new VirtualPortId(UUID.randomUUID().toString())) + .setPortType(VirtualPort.PortType.Internal) + .setBandwidth(bandwidth) + .build(); + virtualRouter2.getVirtualPort().add(virtualPort2); + + VirtualLink virtualLink1 = new VirtualLinkBuilder() + .setLinkId(new VirtualLinkId(UUID.randomUUID().toString())) + .setSrcNodeId(virtualRouter1.getNodeId()) + .setSrcPortId(virtualPort1.getPortId()) + .setDestNodeId(virtualRouter2.getNodeId()) + .setDestPortId(virtualPort2.getPortId()) + .setBandwidth(bandwidth) + .build(); + VirtualLink virtualLink2 = new VirtualLinkBuilder() + .setLinkId(new VirtualLinkId(UUID.randomUUID().toString())) + .setSrcNodeId(virtualRouter2.getNodeId()) + .setSrcPortId(virtualPort2.getPortId()) + .setDestNodeId(virtualRouter1.getNodeId()) + .setDestPortId(virtualPort1.getPortId()) + .setBandwidth(bandwidth) + .build(); + + if ( tempConnection ) { + List virtualLinks = new ArrayList(2); + + virtualLinks.add(virtualLink1); + virtualLinks.add(virtualLink2); + + return virtualLinks; + } + + List virtualLinks = virtualNetwork.getVirtualLinks().getVirtualLink(); + + virtualLinks.add(virtualLink1); + virtualLinks.add(virtualLink2); + + List virtualResources = new ArrayList(2); + + VirtualResource virtualResource = new VirtualResourceBuilder() + .setVirtualResourceId(new VirtualResourceId(UUID.randomUUID().toString())) + .setVirtualResourceType(VirtualResource.VirtualResourceType.Vlink) + .setVirtualResourceEntityId(new VirtualResourceEntityId(virtualLink1.getLinkId().getValue())) + .setOrder(0L) + .build(); + virtualResources.add(virtualResource); + + virtualResource = new VirtualResourceBuilder() + .setVirtualResourceId(new VirtualResourceId(UUID.randomUUID().toString())) + .setVirtualResourceType(VirtualResource.VirtualResourceType.Vlink) + .setVirtualResourceEntityId(new VirtualResourceEntityId(virtualLink2.getLinkId().getValue())) + .setOrder(0L) + .build(); + virtualResources.add(virtualResource); + + IntentVnMappingResult intentVnMappingResult = new IntentVnMappingResultBuilder() + .setIntentId(new IntentId(connection.getConnectionId().getValue())) + .setIntentType(IntentVnMappingResult.IntentType.Connection) + .setVirtualResource(virtualResources) + .build(); + + intentVnMappingResults.add(intentVnMappingResult); + + return null; + } + + /** + * TODO + * + * @param user TODO + * @param connection TODO + * @param endNode1 TODO + * @param endNode2 TODO + * @param virtualNetwork TODO + * @param userIntentVnMapping TODO + * @param tempConnection TODO + * @param resolvingEndNode1 TODO + * @param resolvingEndNode2 TODO + * @return TODO + */ + private List resolveP2PConnectionBetweenLayer3Groups(User user, + Connection connection, + Node endNode1, + Node endNode2, + VirtualNetwork virtualNetwork, + UserIntentVnMapping userIntentVnMapping, + boolean tempConnection, + boolean resolvingEndNode1, + boolean resolvingEndNode2) + throws IntentResolutionException { + // TODO: l3-group - l3-group: 创建第一l3-group的sub-nodes的gw/acc vrouters与第二l3-group的sub-nodes的gw/acc vrouters间的vlinks(vports)。 + + return null; + } + + /** + * TODO + * + * @param user TODO + * @param connection TODO + * @param endNode1 TODO + * @param endNode2 TODO + * @param virtualNetwork TODO + * @param userIntentVnMapping TODO + * @param tempConnection TODO + * @param resolvingEndNode1 TODO + * @param resolvingEndNode2 TODO + * @return TODO + */ + private List resolveP2PConnectionBetweenLayer3AndExternalLayer2Groups(User user, + Connection connection, + Node endNode1, + Node endNode2, + VirtualNetwork virtualNetwork, + UserIntentVnMapping userIntentVnMapping, + boolean tempConnection, + boolean resolvingEndNode1, + boolean resolvingEndNode2) + throws IntentResolutionException { + // TODO: l3-group - ext-group: 为ext-group创建gw vrouter(vport),创建新vrouter与l3-group的sub-nodes的gw/acc vrouters间的vlinks(vports)。 + + return null; + } + + /** + * TODO + * + * @param user TODO + * @param connection TODO + * @param endNode1 TODO + * @param endNode2 TODO + * @param virtualNetwork TODO + * @param userIntentVnMapping TODO + * @param tempConnection TODO + * @param resolvingEndNode1 TODO + * @param resolvingEndNode2 TODO + * @return TODO + */ + private List resolveP2PConnectionBetweenLayer3AndExternalLayer3Groups(User user, + Connection connection, + Node endNode1, + Node endNode2, + VirtualNetwork virtualNetwork, + UserIntentVnMapping userIntentVnMapping, + boolean tempConnection, + boolean resolvingEndNode1, + boolean resolvingEndNode2) + throws IntentResolutionException { + // TODO: l3-group - ext-group: 创建ext-group的acc vrouter与l3-group的sub-nodes的gw/acc vrouters间的vlinks(vports)。 + + return null; + } + + /** + * TODO + * + * @param user TODO + * @param connection TODO + * @param endNode1 TODO + * @param endNode2 TODO + * @param virtualNetwork TODO + * @param userIntentVnMapping TODO + * @param tempConnection TODO + * @param resolvingEndNode1 TODO + * @param resolvingEndNode2 TODO + * @return TODO + */ + private List resolveP2PConnectionBetweenExternalLayer2Groups(User user, + Connection connection, + Node endNode1, + Node endNode2, + VirtualNetwork virtualNetwork, + UserIntentVnMapping userIntentVnMapping, + boolean tempConnection, + boolean resolvingEndNode1, + boolean resolvingEndNode2) + throws IntentResolutionException { + boolean sameIpPrefix; + + sameIpPrefix = true;// TODO: for sameIpPrefix. + + if ( sameIpPrefix ) { + if ( resolvingEndNode1 ) { + nodeMapper.resolveExternalLayer2Group(user, endNode1, virtualNetwork, userIntentVnMapping, false); + } + + if ( resolvingEndNode2 ) { + nodeMapper.resolveExternalLayer2Group(user, endNode2, virtualNetwork, userIntentVnMapping, false); + } + } else { + if ( resolvingEndNode1 ) { + nodeMapper.resolveExternalLayer2Group(user, endNode1, virtualNetwork, userIntentVnMapping, true); + } + + if ( resolvingEndNode2 ) { + nodeMapper.resolveExternalLayer2Group(user, endNode2, virtualNetwork, userIntentVnMapping, true); + } + } + + List intentVnMappingResults = userIntentVnMapping.getIntentVnMappingResult(); + IntentVnMappingResult intentVnMappingResult1 = IntentResolverUtils + .getIntentVnMappingResult(intentVnMappingResults, new IntentId(endNode1.getNodeId().getValue())); + + if ( null == intentVnMappingResult1 ) { + throw new IntentResolutionException("Can not get the intent-vn mapping result for " + + "the node " + endNode1.getNodeId().getValue() + "."); + } + + IntentVnMappingResult intentVnMappingResult2 = IntentResolverUtils + .getIntentVnMappingResult(intentVnMappingResults, new IntentId(endNode2.getNodeId().getValue())); + + if ( null == intentVnMappingResult2 ) { + throw new IntentResolutionException("Can not get the intent-vn mapping result for " + + "the node " + endNode2.getNodeId().getValue() + "."); + } + + List virtualNodes = virtualNetwork.getVirtualNodes().getVirtualNode(); + VirtualNodeId virtualNodeId = new VirtualNodeId(intentVnMappingResult1.getVirtualResource().get(0) + .getParentVirtualResourceEntityId().getValue()); + VirtualNode virtualRouter1 = IntentResolverUtils.getVirtualNode(virtualNodes, virtualNodeId); + + if ( null == virtualRouter1 ) { + throw new IntentResolutionException("Can not get the virtual node created for " + + "the node " + endNode1.getNodeId().getValue() + "."); + } + + virtualNodeId = new VirtualNodeId(intentVnMappingResult2.getVirtualResource().get(0) + .getParentVirtualResourceEntityId().getValue()); + VirtualNode virtualRouter2 = IntentResolverUtils.getVirtualNode(virtualNodes, virtualNodeId); + + if ( null == virtualRouter2 ) { + throw new IntentResolutionException("Can not get the virtual node created for " + + "the node " + endNode2.getNodeId().getValue() + "."); + } + + Property property = IntentResolverUtils + .getConnectionProperty(connection.getProperty(), new PropertyName("bandwidth")); + long bandwidth = 0; + + if ( null != property ) { + bandwidth = /*1024 * */property.getPropertyValues().getIntValue().get(0).getValue(); + } + + VirtualPort virtualPort1 = new VirtualPortBuilder() + .setPortId(new VirtualPortId(UUID.randomUUID().toString())) + .setPortType(VirtualPort.PortType.Internal) + .setBandwidth(bandwidth) + .build(); + virtualRouter1.getVirtualPort().add(virtualPort1); + + VirtualPort virtualPort2 = new VirtualPortBuilder() + .setPortId(new VirtualPortId(UUID.randomUUID().toString())) + .setPortType(VirtualPort.PortType.Internal) + .setBandwidth(bandwidth) + .build(); + virtualRouter2.getVirtualPort().add(virtualPort2); + + VirtualLink virtualLink1 = new VirtualLinkBuilder() + .setLinkId(new VirtualLinkId(UUID.randomUUID().toString())) + .setSrcNodeId(virtualRouter1.getNodeId()) + .setSrcPortId(virtualPort1.getPortId()) + .setDestNodeId(virtualRouter2.getNodeId()) + .setDestPortId(virtualPort2.getPortId()) + .setBandwidth(bandwidth) + .build(); + VirtualLink virtualLink2 = new VirtualLinkBuilder() + .setLinkId(new VirtualLinkId(UUID.randomUUID().toString())) + .setSrcNodeId(virtualRouter2.getNodeId()) + .setSrcPortId(virtualPort2.getPortId()) + .setDestNodeId(virtualRouter1.getNodeId()) + .setDestPortId(virtualPort1.getPortId()) + .setBandwidth(bandwidth) + .build(); + + if ( tempConnection ) { + List virtualLinks = new ArrayList(2); + + virtualLinks.add(virtualLink1); + virtualLinks.add(virtualLink2); + + return virtualLinks; + } + + List virtualLinks = virtualNetwork.getVirtualLinks().getVirtualLink(); + + virtualLinks.add(virtualLink1); + virtualLinks.add(virtualLink2); + + List virtualResources = new ArrayList(2); + + VirtualResource virtualResource = new VirtualResourceBuilder() + .setVirtualResourceId(new VirtualResourceId(UUID.randomUUID().toString())) + .setVirtualResourceType(VirtualResource.VirtualResourceType.Vlink) + .setVirtualResourceEntityId(new VirtualResourceEntityId(virtualLink1.getLinkId().getValue())) + .setOrder(0L) + .build(); + virtualResources.add(virtualResource); + + virtualResource = new VirtualResourceBuilder() + .setVirtualResourceId(new VirtualResourceId(UUID.randomUUID().toString())) + .setVirtualResourceType(VirtualResource.VirtualResourceType.Vlink) + .setVirtualResourceEntityId(new VirtualResourceEntityId(virtualLink2.getLinkId().getValue())) + .setOrder(0L) + .build(); + virtualResources.add(virtualResource); + + IntentVnMappingResult intentVnMappingResult = new IntentVnMappingResultBuilder() + .setIntentId(new IntentId(connection.getConnectionId().getValue())) + .setIntentType(IntentVnMappingResult.IntentType.Connection) + .setVirtualResource(virtualResources) + .build(); + + intentVnMappingResults.add(intentVnMappingResult); + + return null; + } + + /** + * TODO + * + * @param user TODO + * @param connection TODO + * @param endNode1 TODO + * @param endNode2 TODO + * @param virtualNetwork TODO + * @param userIntentVnMapping TODO + * @param tempConnection TODO + * @param resolvingEndNode1 TODO + * @param resolvingEndNode2 TODO + * @return TODO + */ + private List resolveP2PConnectionBetweenExternalLayer2AndLayer3Groups(User user, + Connection connection, + Node endNode1, + Node endNode2, + VirtualNetwork virtualNetwork, + UserIntentVnMapping userIntentVnMapping, + boolean tempConnection, + boolean resolvingEndNode1, + boolean resolvingEndNode2) + throws IntentResolutionException { + if ( resolvingEndNode1 ) { + nodeMapper.resolveExternalLayer2Group(user, endNode1, virtualNetwork, userIntentVnMapping, true); + } + + List intentVnMappingResults = userIntentVnMapping.getIntentVnMappingResult(); + IntentVnMappingResult intentVnMappingResult1 = IntentResolverUtils + .getIntentVnMappingResult(intentVnMappingResults, new IntentId(endNode1.getNodeId().getValue())); + + if ( null == intentVnMappingResult1 ) { + throw new IntentResolutionException("Can not get the intent-vn mapping result for " + + "the node " + endNode1.getNodeId().getValue() + "."); + } + + IntentVnMappingResult intentVnMappingResult2 = IntentResolverUtils + .getIntentVnMappingResult(intentVnMappingResults, new IntentId(endNode2.getNodeId().getValue())); + + if ( null == intentVnMappingResult2 ) { + throw new IntentResolutionException("Can not get the intent-vn mapping result for " + + "the node " + endNode2.getNodeId().getValue() + "."); + } + + List virtualNodes = virtualNetwork.getVirtualNodes().getVirtualNode(); + VirtualNodeId virtualNodeId = new VirtualNodeId(intentVnMappingResult1.getVirtualResource().get(0) + .getParentVirtualResourceEntityId().getValue()); + VirtualNode virtualRouter1 = IntentResolverUtils.getVirtualNode(virtualNodes, virtualNodeId); + + if ( null == virtualRouter1 ) { + throw new IntentResolutionException("Can not get the virtual node created for " + + "the node " + endNode1.getNodeId().getValue() + "."); + } + + virtualNodeId = new VirtualNodeId(intentVnMappingResult2.getVirtualResource().get(0) + .getParentVirtualResourceEntityId().getValue()); + VirtualNode virtualRouter2 = IntentResolverUtils.getVirtualNode(virtualNodes, virtualNodeId); + + if ( null == virtualRouter2 ) { + throw new IntentResolutionException("Can not get the virtual node created for " + + "the node " + endNode2.getNodeId().getValue() + "."); + } + + Property property = IntentResolverUtils + .getConnectionProperty(connection.getProperty(), new PropertyName("bandwidth")); + long bandwidth = 0; + + if ( null != property ) { + bandwidth = /*1024 * */property.getPropertyValues().getIntValue().get(0).getValue(); + } + + VirtualPort virtualPort1 = new VirtualPortBuilder() + .setPortId(new VirtualPortId(UUID.randomUUID().toString())) + .setPortType(VirtualPort.PortType.Internal) + .setBandwidth(bandwidth) + .build(); + virtualRouter1.getVirtualPort().add(virtualPort1); + + VirtualPort virtualPort2 = new VirtualPortBuilder() + .setPortId(new VirtualPortId(UUID.randomUUID().toString())) + .setPortType(VirtualPort.PortType.Internal) + .setBandwidth(bandwidth) + .build(); + virtualRouter2.getVirtualPort().add(virtualPort2); + + VirtualLink virtualLink1 = new VirtualLinkBuilder() + .setLinkId(new VirtualLinkId(UUID.randomUUID().toString())) + .setSrcNodeId(virtualRouter1.getNodeId()) + .setSrcPortId(virtualPort1.getPortId()) + .setDestNodeId(virtualRouter2.getNodeId()) + .setDestPortId(virtualPort2.getPortId()) + .setBandwidth(bandwidth) + .build(); + VirtualLink virtualLink2 = new VirtualLinkBuilder() + .setLinkId(new VirtualLinkId(UUID.randomUUID().toString())) + .setSrcNodeId(virtualRouter2.getNodeId()) + .setSrcPortId(virtualPort2.getPortId()) + .setDestNodeId(virtualRouter1.getNodeId()) + .setDestPortId(virtualPort1.getPortId()) + .setBandwidth(bandwidth) + .build(); + + if ( tempConnection ) { + List virtualLinks = new ArrayList(2); + + virtualLinks.add(virtualLink1); + virtualLinks.add(virtualLink2); + + return virtualLinks; + } + + List virtualLinks = virtualNetwork.getVirtualLinks().getVirtualLink(); + + virtualLinks.add(virtualLink1); + virtualLinks.add(virtualLink2); + + List virtualResources = new ArrayList(2); + + VirtualResource virtualResource = new VirtualResourceBuilder() + .setVirtualResourceId(new VirtualResourceId(UUID.randomUUID().toString())) + .setVirtualResourceType(VirtualResource.VirtualResourceType.Vlink) + .setVirtualResourceEntityId(new VirtualResourceEntityId(virtualLink1.getLinkId().getValue())) + .setOrder(0L) + .build(); + virtualResources.add(virtualResource); + + virtualResource = new VirtualResourceBuilder() + .setVirtualResourceId(new VirtualResourceId(UUID.randomUUID().toString())) + .setVirtualResourceType(VirtualResource.VirtualResourceType.Vlink) + .setVirtualResourceEntityId(new VirtualResourceEntityId(virtualLink2.getLinkId().getValue())) + .setOrder(0L) + .build(); + virtualResources.add(virtualResource); + + IntentVnMappingResult intentVnMappingResult = new IntentVnMappingResultBuilder() + .setIntentId(new IntentId(connection.getConnectionId().getValue())) + .setIntentType(IntentVnMappingResult.IntentType.Connection) + .setVirtualResource(virtualResources) + .build(); + + intentVnMappingResults.add(intentVnMappingResult); + + return null; + } + + /** + * TODO + * + * @param user TODO + * @param connection TODO + * @param endNode1 TODO + * @param endNode2 TODO + * @param virtualNetwork TODO + * @param userIntentVnMapping TODO + * @param tempConnection TODO + * @param resolvingEndNode1 TODO + * @param resolvingEndNode2 TODO + * @return TODO + */ + private List resolveP2PConnectionBetweenExternalLayer3Groups(User user, + Connection connection, + Node endNode1, + Node endNode2, + VirtualNetwork virtualNetwork, + UserIntentVnMapping userIntentVnMapping, + boolean tempConnection, + boolean resolvingEndNode1, + boolean resolvingEndNode2) + throws IntentResolutionException { + List intentVnMappingResults = userIntentVnMapping.getIntentVnMappingResult(); + IntentVnMappingResult intentVnMappingResult1 = IntentResolverUtils + .getIntentVnMappingResult(intentVnMappingResults, new IntentId(endNode1.getNodeId().getValue())); + + if ( null == intentVnMappingResult1 ) { + throw new IntentResolutionException("Can not get the intent-vn mapping result for " + + "the node " + endNode1.getNodeId().getValue() + "."); + } + + IntentVnMappingResult intentVnMappingResult2 = IntentResolverUtils + .getIntentVnMappingResult(intentVnMappingResults, new IntentId(endNode2.getNodeId().getValue())); + + if ( null == intentVnMappingResult2 ) { + throw new IntentResolutionException("Can not get the intent-vn mapping result for " + + "the node " + endNode2.getNodeId().getValue() + "."); + } + + List virtualNodes = virtualNetwork.getVirtualNodes().getVirtualNode(); + VirtualNodeId virtualNodeId = new VirtualNodeId(intentVnMappingResult1.getVirtualResource().get(0) + .getParentVirtualResourceEntityId().getValue()); + VirtualNode virtualRouter1 = IntentResolverUtils.getVirtualNode(virtualNodes, virtualNodeId); + + if ( null == virtualRouter1 ) { + throw new IntentResolutionException("Can not get the virtual node created for " + + "the node " + endNode1.getNodeId().getValue() + "."); + } + + virtualNodeId = new VirtualNodeId(intentVnMappingResult2.getVirtualResource().get(0) + .getParentVirtualResourceEntityId().getValue()); + VirtualNode virtualRouter2 = IntentResolverUtils.getVirtualNode(virtualNodes, virtualNodeId); + + if ( null == virtualRouter2 ) { + throw new IntentResolutionException("Can not get the virtual node created for " + + "the node " + endNode2.getNodeId().getValue() + "."); + } + + Property property = IntentResolverUtils + .getConnectionProperty(connection.getProperty(), new PropertyName("bandwidth")); + long bandwidth = 0; + + if ( null != property ) { + bandwidth = /*1024 * */property.getPropertyValues().getIntValue().get(0).getValue(); + } + + VirtualPort virtualPort1 = new VirtualPortBuilder() + .setPortId(new VirtualPortId(UUID.randomUUID().toString())) + .setPortType(VirtualPort.PortType.Internal) + .setBandwidth(bandwidth) + .build(); + virtualRouter1.getVirtualPort().add(virtualPort1); + + VirtualPort virtualPort2 = new VirtualPortBuilder() + .setPortId(new VirtualPortId(UUID.randomUUID().toString())) + .setPortType(VirtualPort.PortType.Internal) + .setBandwidth(bandwidth) + .build(); + virtualRouter2.getVirtualPort().add(virtualPort2); + + VirtualLink virtualLink1 = new VirtualLinkBuilder() + .setLinkId(new VirtualLinkId(UUID.randomUUID().toString())) + .setSrcNodeId(virtualRouter1.getNodeId()) + .setSrcPortId(virtualPort1.getPortId()) + .setDestNodeId(virtualRouter2.getNodeId()) + .setDestPortId(virtualPort2.getPortId()) + .setBandwidth(bandwidth) + .build(); + VirtualLink virtualLink2 = new VirtualLinkBuilder() + .setLinkId(new VirtualLinkId(UUID.randomUUID().toString())) + .setSrcNodeId(virtualRouter2.getNodeId()) + .setSrcPortId(virtualPort2.getPortId()) + .setDestNodeId(virtualRouter1.getNodeId()) + .setDestPortId(virtualPort1.getPortId()) + .setBandwidth(bandwidth) + .build(); + + if ( tempConnection ) { + List virtualLinks = new ArrayList(2); + + virtualLinks.add(virtualLink1); + virtualLinks.add(virtualLink2); + + return virtualLinks; + } + + List virtualLinks = virtualNetwork.getVirtualLinks().getVirtualLink(); + + virtualLinks.add(virtualLink1); + virtualLinks.add(virtualLink2); + + List virtualResources = new ArrayList(2); + + VirtualResource virtualResource = new VirtualResourceBuilder() + .setVirtualResourceId(new VirtualResourceId(UUID.randomUUID().toString())) + .setVirtualResourceType(VirtualResource.VirtualResourceType.Vlink) + .setVirtualResourceEntityId(new VirtualResourceEntityId(virtualLink1.getLinkId().getValue())) + .setOrder(0L) + .build(); + virtualResources.add(virtualResource); + + virtualResource = new VirtualResourceBuilder() + .setVirtualResourceId(new VirtualResourceId(UUID.randomUUID().toString())) + .setVirtualResourceType(VirtualResource.VirtualResourceType.Vlink) + .setVirtualResourceEntityId(new VirtualResourceEntityId(virtualLink2.getLinkId().getValue())) + .setOrder(0L) + .build(); + virtualResources.add(virtualResource); + + IntentVnMappingResult intentVnMappingResult = new IntentVnMappingResultBuilder() + .setIntentId(new IntentId(connection.getConnectionId().getValue())) + .setIntentType(IntentVnMappingResult.IntentType.Connection) + .setVirtualResource(virtualResources) + .build(); + + intentVnMappingResults.add(intentVnMappingResult); + + return null; + } +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/intent/FlowManager.java b/nemo-impl/src/main/java/org/opendaylight/nemo/intent/FlowManager.java new file mode 100644 index 0000000..cf9e6d2 --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/intent/FlowManager.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.nemo.intent; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.UserId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Flow; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Maintain the information of the user's flows. For example, query + * the values of the properties of the flow, such as the path of the + * flow, and store them into the data store. + * + * @author Zhigang Ji + */ +public class FlowManager { + private static final Logger LOG = LoggerFactory.getLogger(FlowManager.class); + + private final DataBroker dataBroker; + + public FlowManager(DataBroker dataBroker) { + super(); + + this.dataBroker = dataBroker; + + LOG.debug("Initialized the renderer common flow manager."); + + return; + } + + /** + * Query the values of the properties of the flow, which are read-only + * for the user, and store them into the data store. + * + * @param userId The user id for the flow. + * @param flow The flow to be resolved. + */ + protected void resolveFlow(UserId userId, Flow flow) throws IntentResolutionException { + // TODO + + return; + } +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/intent/IntentResolutionException.java b/nemo-impl/src/main/java/org/opendaylight/nemo/intent/IntentResolutionException.java new file mode 100644 index 0000000..f23a782 --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/intent/IntentResolutionException.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.nemo.intent; + +/** + * An exception in resolving the user intent. + * + * @author Zhigang Ji + */ +public class IntentResolutionException extends Exception { + private static final long serialVersionUID = -6843701204012305270L; + + public IntentResolutionException() { + super(); + + return; + } + + public IntentResolutionException(String message) { + super(message); + + return; + } + + public IntentResolutionException(Throwable cause) { + super(cause); + + return; + } + + public IntentResolutionException(String message, Throwable cause) { + super(message, cause); + + return; + } + + public IntentResolutionException(String message, Throwable cause, + boolean enableSuppression, + boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + + return; + } +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/intent/IntentResolver.java b/nemo-impl/src/main/java/org/opendaylight/nemo/intent/IntentResolver.java new file mode 100644 index 0000000..c923a4c --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/intent/IntentResolver.java @@ -0,0 +1,410 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.nemo.intent; + +import com.google.common.base.Optional; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.nemo.intent.computation.PNComputationUnit; +import org.opendaylight.nemo.intent.computation.VNComputationUnit; +import org.opendaylight.nemo.intent.computation.VNMappingUnit; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.PhysicalNetwork; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.PhysicalPaths; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.paths.PhysicalPath; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.paths.PhysicalPathKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.VirtualNetworks; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.VirtualNetwork; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.VirtualNetworkBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.VirtualNetworkKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.*; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.arps.VirtualArp; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.links.VirtualLink; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.nodes.VirtualNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.paths.VirtualPath; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.routes.VirtualRoute; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.IntentVnMappingResults; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.VnPnMappingResults; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.intent.vn.mapping.results.UserIntentVnMapping; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.intent.vn.mapping.results.UserIntentVnMappingBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.intent.vn.mapping.results.UserIntentVnMappingKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.intent.vn.mapping.results.user.intent.vn.mapping.IntentVnMappingResult; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.vn.pn.mapping.results.UserVnPnMapping; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.vn.pn.mapping.results.UserVnPnMappingBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.vn.pn.mapping.results.UserVnPnMappingKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.vn.pn.mapping.results.user.vn.pn.mapping.VnPnMappingResult; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.NodeType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.UserId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.common.rev151010.PhysicalPathId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.common.rev151010.VirtualNetworkId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.Users; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Connection; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Flow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.operations.Operation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.users.User; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.users.UserKey; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutionException; + +/** + * Provide the user intent resolution APIs and distribute the user intents + * to corresponding handling classes. + * + * @author Zhigang Ji + */ +public class IntentResolver implements AutoCloseable { + private static final Logger LOG = LoggerFactory.getLogger(IntentResolver.class); + + private final DataBroker dataBroker; + + /** + * The node mapper to resolve the user's node intent. + */ + private NodeMapper nodeMapper; + + /** + * The connection mapper to resolve the user's connection intent. + */ + private ConnectionMapper connectionMapper; + + /** + * The flow manager to resolve the user's flow intent. + */ + private FlowManager flowManager; + + /** + * The operation resolver to resolve the user's operation intent. + */ + private OperationResolver operationResolver; + + /** + * The physical network computation unit. + */ + private PNComputationUnit pnComputationUnit; + + /** + * The virtual network computation unit for all users. + */ + private Map vnComputationUnits; + + /** + * The virtual network mapping unit. + */ + private VNMappingUnit vnMappingUnit; + + public IntentResolver(DataBroker dataBroker) { + super(); + + this.dataBroker = dataBroker; + + nodeMapper = new NodeMapper(dataBroker); + connectionMapper = new ConnectionMapper(dataBroker, nodeMapper); + flowManager = new FlowManager(dataBroker); + operationResolver = new OperationResolver(dataBroker); + + pnComputationUnit = new PNComputationUnit(dataBroker); + vnComputationUnits = new HashMap(); + vnMappingUnit = new VNMappingUnit(dataBroker, pnComputationUnit); + + LOG.debug("Initialized the renderer common intent resolver."); + + return; + } + + /** + * Resolve the user's intents to generate the virtual network, then map + * the virtual network into the underlying physical network, finally, store + * the generated intent mapping results into the data store, and various + * renderers configure the underlying networks according to these results. + * + * @param userId The user id for the intents to be resolved. + */ + public void resolveIntent(UserId userId) throws Exception { + VNComputationUnit vnComputationUnit = vnComputationUnits.get(userId); + + VirtualNetworkId virtualNetworkId = new VirtualNetworkId(userId.getValue()); + VirtualNetworkKey virtualNetworkKey = new VirtualNetworkKey(virtualNetworkId); + + InstanceIdentifier virtualNetworkIid = InstanceIdentifier + .builder(VirtualNetworks.class) + .child(VirtualNetwork.class, virtualNetworkKey) + .build(); + InstanceIdentifier userIntentVnMappingIid = InstanceIdentifier + .builder(IntentVnMappingResults.class) + .child(UserIntentVnMapping.class, new UserIntentVnMappingKey(userId)) + .build(); + InstanceIdentifier userVnPnMappingIid = InstanceIdentifier + .builder(VnPnMappingResults.class) + .child(UserVnPnMapping.class, new UserVnPnMappingKey(virtualNetworkId)) + .build(); + + if ( null != vnComputationUnit ) { + vnComputationUnit.close(); + vnComputationUnits.remove(userId); + + ReadWriteTransaction readWriteTransaction = dataBroker.newReadWriteTransaction(); + + Optional result; + + try { + result = readWriteTransaction.read(LogicalDatastoreType.CONFIGURATION, userVnPnMappingIid).get(); + } catch ( InterruptedException | ExecutionException exception ) { + throw new IntentResolutionException("Can not read the vn-pn mapping results for the user " + + userId.getValue() + "."); + } + + if ( result.isPresent() ) { + UserVnPnMapping userVnPnMapping = result.get(); + List vnPnMappingResults = userVnPnMapping.getVnPnMappingResult(); + InstanceIdentifier physicalPathIid; + PhysicalPathId physicalPathId; + + for ( VnPnMappingResult vnPnMappingResult : vnPnMappingResults ) { + if ( VnPnMappingResult.VirtualResourceType.Vlink == vnPnMappingResult.getVirtualResourceType() ) { + physicalPathId = new PhysicalPathId(vnPnMappingResult.getPhysicalResourceEntityId().getValue()); + physicalPathIid = InstanceIdentifier.builder(PhysicalNetwork.class) + .child(PhysicalPaths.class) + .child(PhysicalPath.class, new PhysicalPathKey(physicalPathId)) + .build(); + + readWriteTransaction.delete(LogicalDatastoreType.OPERATIONAL, physicalPathIid); + } + } + } + +// readWriteTransaction.delete(LogicalDatastoreType.CONFIGURATION, virtualNetworkIid); +// readWriteTransaction.delete(LogicalDatastoreType.CONFIGURATION, userIntentVnMappingIid); +// readWriteTransaction.delete(LogicalDatastoreType.CONFIGURATION, userVnPnMappingIid); + // TODO: 删除intent processing status + + readWriteTransaction.submit(); + } + + ReadWriteTransaction readWriteTransaction = dataBroker.newReadWriteTransaction(); + + InstanceIdentifier userIid = InstanceIdentifier.builder(Users.class) + .child(User.class, new UserKey(userId)) + .build(); + Optional result; + + try { + result = readWriteTransaction.read(LogicalDatastoreType.CONFIGURATION, userIid).get(); + } catch ( InterruptedException | ExecutionException exception ) { + throw new IntentResolutionException("Can not read the data of the user " + + userId.getValue() + "."); + } + + if ( !result.isPresent() ) { + throw new IntentResolutionException("The data of the user " + + userId.getValue() + " does not exist."); + } + + User user = result.get(); + + if ( null != user.getObjects() ) { + VirtualNodes virtualNodes = new VirtualNodesBuilder() + .setVirtualNode(new LinkedList()) + .build(); + VirtualLinks virtualLinks = new VirtualLinksBuilder() + .setVirtualLink(new LinkedList()) + .build(); + VirtualPaths virtualPaths = new VirtualPathsBuilder() + .setVirtualPath(new LinkedList()) + .build(); + VirtualRoutes virtualRoutes = new VirtualRoutesBuilder() + .setVirtualRoute(new LinkedList()) + .build(); + VirtualArps virtualArps = new VirtualArpsBuilder() + .setVirtualArp(new LinkedList()) + .build(); + VirtualNetwork virtualNetwork = new VirtualNetworkBuilder() + .setNetworkId(virtualNetworkId) + .setUserId(userId) + .setVirtualNodes(virtualNodes) + .setVirtualLinks(virtualLinks) + .setVirtualPaths(virtualPaths) + .setVirtualRoutes(virtualRoutes) + .setVirtualArps(virtualArps) + .build(); + + UserIntentVnMapping userIntentVnMapping = new UserIntentVnMappingBuilder() + .setUserId(userId) + .setVirtualNetworkId(virtualNetworkId) + .setIntentVnMappingResult(new LinkedList()) + .build(); + + UserVnPnMapping userVnPnMapping = new UserVnPnMappingBuilder() + .setVirtualNetworkId(virtualNetworkId) + .setUserId(userId) + .setVnPnMappingResult(new LinkedList()) + .build(); + + List physicalPaths = new LinkedList(); + + List nodes = user.getObjects().getNode(); + List hosts = new LinkedList(); + List layer2Groups = new LinkedList(); + List layer3Groups = new LinkedList(); + List externalLayer3Groups = new LinkedList(); + List serviceChainGroups = new LinkedList(); + List serviceFunctions = new LinkedList(); + + NodeType hostNodeType = new NodeType("host"); + NodeType layer2GroupNodeType = new NodeType("l2-group"); + NodeType layer3GroupNodeType = new NodeType("l3-group"); + NodeType externalGroupNodeType = new NodeType("ext-group"); + NodeType serviceChainGroupNodeType = new NodeType("chain-group"); + NodeType firewallNodeType = new NodeType("fw"); + NodeType loadbalancerNodeType = new NodeType("lb"); + NodeType cacheNodeType = new NodeType("cache"); + NodeType nodeType; + + if ( null != nodes ) { + for ( Node node : nodes ) { + nodeType = node.getNodeType(); + + if ( nodeType.equals(hostNodeType) ) { + hosts.add(node); + } + + if ( nodeType.equals(layer2GroupNodeType) ) { + layer2Groups.add(node); + } + + if ( nodeType.equals(layer3GroupNodeType) ) { + layer3Groups.add(node); + } + + if ( nodeType.equals(externalGroupNodeType) ) { + if ( IntentResolverUtils.checkExternalLayer3Group(node) ) { + externalLayer3Groups.add(node); + } + } + + if ( nodeType.equals(serviceChainGroupNodeType) ) { + serviceChainGroups.add(node); + } + + if ( nodeType.equals(firewallNodeType) + || nodeType.equals(loadbalancerNodeType) + || nodeType.equals(cacheNodeType) ) { + serviceFunctions.add(node); + } + } + + for ( Node node : hosts ) { + nodeMapper.resolveHost(user, node, virtualNetwork, userIntentVnMapping); + } + + for ( Node node : layer2Groups ) { + nodeMapper.resolveLayer2Group(user, node, virtualNetwork, userIntentVnMapping); + } + + for ( Node node : externalLayer3Groups ) { + nodeMapper.resolveExternalLayer3Group(user, node, virtualNetwork, userIntentVnMapping); + } + + for ( Node node : layer3Groups ) { + nodeMapper.resolveLayer3Group(user, node, virtualNetwork, userIntentVnMapping); + } + + for ( Node node : serviceFunctions ) { + nodeMapper.resolveServiceFunction(user, node, virtualNetwork, userIntentVnMapping); + } + + for ( Node node : serviceChainGroups ) { + nodeMapper.resolveServiceChainGroup(user, node, virtualNetwork, userIntentVnMapping); + } + } + + List connections = user.getObjects().getConnection(); + + if ( null != connections ) { + for ( Connection connection : connections ) { + connectionMapper.resolveConnection(user, connection, virtualNetwork, userIntentVnMapping); + } + } + + List flows = user.getObjects().getFlow(); + + if ( null != flows ) { + for ( Flow flow : flows ) { + flowManager.resolveFlow(userId, flow); + } + } + + if ( null != user.getOperations() ) { + List operations = user.getOperations().getOperation(); + + if ( null != operations ) { + for ( Operation operation : operations ) { + operationResolver.resolveOperation(user, operation, virtualNetwork, userIntentVnMapping); + } + } + } + + vnMappingUnit.virtualNetworkMapping(virtualNetwork, userVnPnMapping, physicalPaths); + vnComputationUnit = new VNComputationUnit(dataBroker, virtualNetwork); + vnComputationUnits.put(userId, vnComputationUnit); + + // for testing - jizhigang + System.out.println(virtualNetwork); + System.out.println(userIntentVnMapping); + System.out.println(userVnPnMapping); + System.out.println(physicalPaths); + // for testing - jizhigang + + readWriteTransaction.put(LogicalDatastoreType.CONFIGURATION, virtualNetworkIid, virtualNetwork, true); + readWriteTransaction.put(LogicalDatastoreType.CONFIGURATION, userIntentVnMappingIid, userIntentVnMapping, true); + readWriteTransaction.put(LogicalDatastoreType.CONFIGURATION, userVnPnMappingIid, userVnPnMapping, true); + + InstanceIdentifier physicalPathIid; + + for ( PhysicalPath physicalPath : physicalPaths ) { + physicalPathIid = InstanceIdentifier.builder(PhysicalNetwork.class) + .child(PhysicalPaths.class) + .child(PhysicalPath.class, new PhysicalPathKey(physicalPath.getPathId())) + .build(); + + readWriteTransaction.put(LogicalDatastoreType.OPERATIONAL, physicalPathIid, physicalPath, true); + } + + readWriteTransaction.submit(); + } + + return; + } + + @Override + public void close() throws Exception { + if ( null != pnComputationUnit ) { + pnComputationUnit.close(); + } + + for ( VNComputationUnit vnComputationUnit : vnComputationUnits.values() ) { + if ( null != vnComputationUnit ) { + vnComputationUnit.close(); + } + } + + if ( null != vnMappingUnit ) { + vnMappingUnit.close(); + } + + return; + } +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/intent/IntentResolverUtils.java b/nemo-impl/src/main/java/org/opendaylight/nemo/intent/IntentResolverUtils.java new file mode 100644 index 0000000..5b16ef6 --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/intent/IntentResolverUtils.java @@ -0,0 +1,652 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.nemo.intent; + +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.hosts.PhysicalHost; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.links.VirtualLink; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.nodes.VirtualNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.intent.vn.mapping.results.user.intent.vn.mapping.IntentVnMappingResult; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.intent.vn.mapping.results.user.intent.vn.mapping.intent.vn.mapping.result.VirtualResource; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.*; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.common.rev151010.PhysicalHostId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.common.rev151010.PhysicalNodeId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.common.rev151010.VirtualNodeId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.Objects; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Connection; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Flow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.operations.Operation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.object.rev151010.flow.instance.MatchItem; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.object.rev151010.node.instance.Property; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.object.rev151010.node.instance.SubNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.object.rev151010.property.instance.property.values.StringValue; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.operation.rev151010.operation.instance.Action; +import org.opendaylight.yangtools.yang.binding.DataObject; + +import java.util.ArrayList; +import java.util.List; + +/** + * Implement the common utilities frequently used in + * the intent resolution. + * + * @author Zhigang Ji + */ +public class IntentResolverUtils { + /** + * Check whether the node is an external layer2 group or layer3 group. + * + * @param node The node to be checked. + * @return True if the node is an external layer3 group. + */ + protected static boolean checkExternalLayer3Group(Node node) { + PropertyName propertyName = new PropertyName("ac-info-network"); + Property property = getNodeProperty(node.getProperty(), propertyName); + + if ( null != property ) { + String propertyValue = property.getPropertyValues().getStringValue().get(0).getValue(); + + if ( propertyValue.equals("layer3") ) { + return true; + } + } + + return false; + } + + /** + * TODO + * + * @param physicalHosts TODO + * @param node TODO + * @return TODO + */ + protected static PhysicalHost getPhysicalHost(List physicalHosts, Node node) { + PhysicalHostId physicalHostId = new PhysicalHostId(node.getNodeId().getValue()); + + return getPhysicalHost(physicalHosts, physicalHostId); + } + + /** + * TODO + * + * @param properties TODO + * @param propertyName TODO + * @return TODO + */ + protected static Property getNodeProperty(List properties, PropertyName propertyName) { + if ( null != properties ) { + for ( Property property : properties ) { + if ( property.getPropertyName().equals(propertyName) ) { + return property; + } + } + } + + return null; + } + + /** + * TODO + * + * @param property TODO + * @return TODO + */ + protected static PhysicalNodeId generatePhysicalNodeIdFromNodeLocationProperty(Property property) { + String propertyValue = property.getPropertyValues().getStringValue().get(0).getValue(); + + return new PhysicalNodeId(propertyValue.substring(0, propertyValue.lastIndexOf(':'))); + } + + /** + * TODO + * + * @param intentVnMappingResults TODO + * @param intentId TODO + * @return TODO + */ + protected static IntentVnMappingResult getIntentVnMappingResult( + List intentVnMappingResults, IntentId intentId) { + for ( IntentVnMappingResult intentVnMappingResult : intentVnMappingResults ) { + if ( intentVnMappingResult.getIntentId().equals(intentId) ) { + return intentVnMappingResult; + } + } + + return null; + } + + /** + * TODO + * + * @param virtualNodes TODO + * @param virtualNodeId TODO + * @return TODO + */ + protected static VirtualNode getVirtualNode(List virtualNodes, + VirtualNodeId virtualNodeId) { + for ( VirtualNode virtualNode : virtualNodes ) { + if ( virtualNode.getNodeId().equals(virtualNodeId) ) { + return virtualNode; + } + } + + return null; + } + + /** + * TODO + * + * @param nodes TODO + * @param nodeId TODO + * @return TODO + */ + protected static Node getNode(List nodes, NodeId nodeId) { + for ( Node node : nodes ) { + if ( node.getNodeId().equals(nodeId) ) { + return node; + } + } + + return null; + } + + /** + * TODO + * + * @param properties TODO + * @param propertyName TODO + * @return TODO + */ + protected static org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.object.rev151010.connection.instance.Property getConnectionProperty( + List properties, + PropertyName propertyName) { + if ( null != properties ) { + for ( org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.object.rev151010.connection.instance.Property + property : properties ) { + if ( property.getPropertyName().equals(propertyName) ) { + return property; + } + } + } + + return null; + } + + /** + * TODO + * + * @param subNodes TODO + * @return TODO + */ + protected static List sortSubNodes(List subNodes) { + if ( subNodes.isEmpty() || 1 == subNodes.size() ) { + return subNodes; + } + + List sortedSubNodes = new ArrayList(subNodes.size()); + sortedSubNodes.addAll(subNodes); + + for ( SubNode subNode : subNodes ) { + sortedSubNodes.set(subNode.getOrder().intValue(), subNode); + } + + return sortedSubNodes; + } + + /** + * TODO + * + * @param subNodes TODO + * @param nodes TODO + * @return TODO + */ + protected static boolean checkAllLayer2OperatingMode(List subNodes, List nodes) { + if ( subNodes.isEmpty() ) { + return false; + } + + Node node; + PropertyName propertyName = new PropertyName("operating-mode"); + Property property; + String propertyValue; + + for ( SubNode subNode : subNodes ) { + node = getNode(nodes, subNode.getNodeId()); + + if ( null == node ) { + return false; + } + + property = getNodeProperty(node.getProperty(), propertyName); + + if ( null == property ) { + return false; + } + + propertyValue = property.getPropertyValues().getStringValue().get(0).getValue(); + + if ( !propertyValue.equals("layer2") ) { + return false; + } + } + + return true; + } + + /** + * TODO + * + * @param subNodes TODO + * @param nodes TODO + * @return TODO + */ + protected static boolean checkAllLayer3OperatingMode(List subNodes, List nodes) { + if ( subNodes.isEmpty() ) { + return false; + } + + Node node; + PropertyName propertyName = new PropertyName("operating-mode"); + Property property; + String propertyValue; + + for ( SubNode subNode : subNodes ) { + node = getNode(nodes, subNode.getNodeId()); + + if ( null == node ) { + return false; + } + + property = getNodeProperty(node.getProperty(), propertyName); + + if ( null == property ) { + return false; + } + + propertyValue = property.getPropertyValues().getStringValue().get(0).getValue(); + + if ( !propertyValue.equals("layer3") ) { + return false; + } + } + + return true; + } + + /** + * TODO + * + * @param virtualLinks TODO + * @param srcVirtualNodeId TODO + * @param destVirtualNodeId TODO + * @return TODO + */ + protected static VirtualLink getVirtualLink(List virtualLinks, + VirtualNodeId srcVirtualNodeId, + VirtualNodeId destVirtualNodeId) { + for ( VirtualLink virtualLink : virtualLinks ) { + if ( virtualLink.getSrcNodeId().equals(srcVirtualNodeId) + && virtualLink.getDestNodeId().equals(destVirtualNodeId) ) { + return virtualLink; + } + } + + return null; + } + + /** + * TODO + * + * @param objects TODO + * @param objectId TODO + * @return TODO + */ + protected static DataObject getObject(Objects objects, ObjectId objectId) { + List nodes = objects.getNode(); + + if ( null != nodes ) { + NodeId nodeId = new NodeId(objectId.getValue()); + Node node = getNode(nodes, nodeId); + + if ( null != node ) { + return node; + } + } + + List connections = objects.getConnection(); + + if ( null != connections ) { + ConnectionId connectionId = new ConnectionId(objectId.getValue()); + Connection connection = getConnection(connections, connectionId); + + if ( null != connection ) { + return connection; + } + } + + List flows = objects.getFlow(); + + if ( null != flows ) { + FlowId flowId = new FlowId(objectId.getValue()); + Flow flow = getFlow(flows, flowId); + + if ( null != flow ) { + return flow; + } + } + + return null; + } + + /** + * TODO + * + * @param operations TODO + * @param operation TODO + * @return TODO + */ + protected static List getSameTargetObjectOperations(List operations, + Operation operation) { + // TODO + + return new ArrayList(0); + } + + /** + * TODO + * + * @param operations TODO + * @param operation TODO + * @param greaterPriorityOperations TODO + * @param equalPriorityOperations TODO + */ + protected static void getGreaterAndEqualPriorityOperations(List operations, Operation operation, + List greaterPriorityOperations, + List equalPriorityOperations) { + // TODO + + return; + } + + /** + * TODO + * + * @param operations TODO + * @param operation TODO + * @return TODO + */ + protected static Operation getConflictingOperation(List operations, + Operation operation) { + // TODO + + return null; + } + + /** + * TODO + * + * @param operations TODO + * @param operation TODO + * @return TODO + */ + protected static List getConflictingOperations(List operations, + Operation operation) { + // TODO + + return null; + } + + /** + * TODO + * + * @param actions TODO + * @param actionName TODO + * @return TODO + */ + protected static Action getAction(List actions, ActionName actionName) { + for ( Action action : actions ) { + if ( action.getActionName().equals(actionName) ) { + return action; + } + } + + return null; + } + + /** + * TODO + * + * @param virtualNodes TODO + * @param flow TODO + * @param nodes TODO + * @param intentVnMappingResults TODO + * @return TODO + */ + protected static VirtualNode getSourceVirtualRouterOfFlow(List virtualNodes, + Flow flow, List nodes, + List intentVnMappingResults) { + MatchItemName matchItemName = new MatchItemName("src-ip"); + MatchItem matchItem = getMatchItem(flow.getMatchItem(), matchItemName); + + if ( null == matchItem ) { + return null; + } + + String matchItemValue = matchItem.getMatchItemValue().getStringValue(); + VirtualNode virtualNode = getVirtualRouterWithIpPrefix(virtualNodes, + matchItemValue, nodes, intentVnMappingResults); + + return virtualNode; + } + + /** + * TODO + * + * @param virtualNodes TODO + * @param flow TODO + * @param nodes TODO + * @param intentVnMappingResults TODO + * @return TODO + */ + protected static VirtualNode getDestinationVirtualRouterOfFlow(List virtualNodes, + Flow flow, List nodes, + List intentVnMappingResults) { + MatchItemName matchItemName = new MatchItemName("dst-ip"); + MatchItem matchItem = getMatchItem(flow.getMatchItem(), matchItemName); + + if ( null == matchItem ) { + return null; + } + + String matchItemValue = matchItem.getMatchItemValue().getStringValue(); + VirtualNode virtualNode = getVirtualRouterWithIpPrefix(virtualNodes, + matchItemValue, nodes, intentVnMappingResults); + + return virtualNode; + } + + /** + * TODO + * + * @param virtualResources TODO + * @return TODO + */ + protected static List sortVirtualResources(List virtualResources) { + if ( virtualResources.isEmpty() || 1 == virtualResources.size() ) { + return virtualResources; + } + + List sortedVirtualResources = new ArrayList(virtualResources.size()); + sortedVirtualResources.addAll(virtualResources); + + for ( VirtualResource virtualResource : virtualResources ) { + sortedVirtualResources.set(virtualResource.getOrder().intValue(), virtualResource); + } + + return sortedVirtualResources; + } + + /** + * TODO + * + * @param physicalHosts TODO + * @param physicalHostId TODO + * @return TODO + */ + private static PhysicalHost getPhysicalHost(List physicalHosts, + PhysicalHostId physicalHostId) { + for ( PhysicalHost physicalHost : physicalHosts ) { + if ( physicalHost.getHostId().equals(physicalHostId) ) { + return physicalHost; + } + } + + return null; + } + + /** + * TODO + * + * @param connections TODO + * @param connectionId TODO + * @return TODO + */ + private static Connection getConnection(List connections, ConnectionId connectionId) { + for ( Connection connection : connections ) { + if ( connection.getConnectionId().equals(connectionId) ) { + return connection; + } + } + + return null; + } + + /** + * TODO + * + * @param flows TODO + * @param flowId TODO + * @return TODO + */ + private static Flow getFlow(List flows, FlowId flowId) { + for ( Flow flow : flows ) { + if ( flow.getFlowId().equals(flowId) ) { + return flow; + } + } + + return null; + } + + /** + * TODO + * + * @param matchItems TODO + * @param matchItemName TODO + * @return TODO + */ + private static MatchItem getMatchItem(List matchItems, MatchItemName matchItemName) { + if ( null != matchItems ) { + for ( MatchItem matchItem : matchItems ) { + if ( matchItem.getMatchItemName().equals(matchItemName) ) { + return matchItem; + } + } + } + + return null; + } + + /** + * TODO + * + * @param virtualNodes TODO + * @param ipPrefix TODO + * @param nodes TODO + * @param intentVnMappingResults TODO + * @return TODO + */ + private static VirtualNode getVirtualRouterWithIpPrefix(List virtualNodes, + String ipPrefix, List nodes, + List intentVnMappingResults) { + NodeType layer2GroupNodeType = new NodeType("l2-group"); + NodeType externalGroupNodeType = new NodeType("ext-group"); + PropertyName propertyName = new PropertyName("ip-prefix"); + Property property; + List propertyValues; + IntentVnMappingResult intentVnMappingResult; + VirtualResource virtualResource; + VirtualNodeId virtualNodeId; + VirtualNode virtualNode; + + for ( Node node : nodes ) { + if ( node.getNodeType().equals(layer2GroupNodeType) + || node.getNodeType().equals(externalGroupNodeType) ) { + property = getNodeProperty(node.getProperty(), propertyName); + + if ( null != property ) { + propertyValues = property.getPropertyValues().getStringValue(); + + if ( containPropertyValue(propertyValues, ipPrefix) ) { + intentVnMappingResult = getIntentVnMappingResult(intentVnMappingResults, + new IntentId(node.getNodeId().getValue())); + + if ( null == intentVnMappingResult ) { + return null; + } + + virtualResource = intentVnMappingResult.getVirtualResource().get(0); + + if ( VirtualResource.VirtualResourceType.Vport + == virtualResource.getVirtualResourceType() ) { + virtualNodeId = new VirtualNodeId( + virtualResource.getParentVirtualResourceEntityId().getValue()); + } else if ( VirtualResource.VirtualResourceType.Vnode + == virtualResource.getVirtualResourceType() ) { + virtualNodeId = new VirtualNodeId( + virtualResource.getVirtualResourceEntityId().getValue()); + } else { + return null; + } + + virtualNode = getVirtualNode(virtualNodes, virtualNodeId); + + if ( null == virtualNode ) { + return null; + } + + if ( VirtualNode.NodeType.Vrouter == virtualNode.getNodeType() ) { + return virtualNode; + } + } + } + } + } + + return null; + } + + /** + * TODO + * + * @param propertyValues TODO + * @param propertyValue TODO + * @return TODO + */ + private static boolean containPropertyValue(List propertyValues, String propertyValue) { + for ( StringValue stringValue : propertyValues ) { + if ( stringValue.getValue().equals(propertyValue) ) { + return true; + } + } + + return false; + } +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/intent/NodeMapper.java b/nemo-impl/src/main/java/org/opendaylight/nemo/intent/NodeMapper.java new file mode 100644 index 0000000..4eabfc8 --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/intent/NodeMapper.java @@ -0,0 +1,1028 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.nemo.intent; + +import com.google.common.base.Optional; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.PhysicalNetwork; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.attribute.instance.AttributeValue; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.attribute.instance.AttributeValueBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.PhysicalHosts; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.hosts.PhysicalHost; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.VirtualNetwork; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.arps.VirtualArp; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.arps.VirtualArpBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.links.VirtualLink; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.links.VirtualLinkBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.nodes.VirtualNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.nodes.VirtualNodeBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.paths.VirtualPath; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.paths.VirtualPathBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.node.instance.*; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.port.instance.*; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.port.instance.PhysicalResourceRequirement; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.port.instance.PhysicalResourceRequirementBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.intent.vn.mapping.results.UserIntentVnMapping; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.intent.vn.mapping.results.user.intent.vn.mapping.IntentVnMappingResult; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.intent.vn.mapping.results.user.intent.vn.mapping.IntentVnMappingResultBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.intent.vn.mapping.results.user.intent.vn.mapping.intent.vn.mapping.result.VirtualResource; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.intent.vn.mapping.results.user.intent.vn.mapping.intent.vn.mapping.result.VirtualResourceBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.IntentId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.NodeType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.PropertyName; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.common.rev151010.*; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.users.User; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.object.rev151010.node.instance.Property; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.object.rev151010.node.instance.SubNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.object.rev151010.property.instance.property.values.StringValue; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; +import java.util.concurrent.ExecutionException; + +/** + * Resolve the user's node intent. Create the virtual node according to + * the intent if it's needed, and then map the created virtual node into + * the physical network. Finally, store these intent mapping results + * into the data store. + * + * @author Zhigang Ji + */ +public class NodeMapper { + private static final Logger LOG = LoggerFactory.getLogger(NodeMapper.class); + + private final DataBroker dataBroker; + + public NodeMapper(DataBroker dataBroker) { + super(); + + this.dataBroker = dataBroker; + + LOG.debug("Initialized the renderer common node mapper."); + + return; + } + + /** + * Resolve the user's node intent, perform the necessary intent + * mapping, and store the intent mapping results into the data store. + * + * @param user The user for the node. + * @param node The node to be resolved. + * @param virtualNetwork The virtual network for the user. + * @param userIntentVnMapping The intent-vn mapping for the user. + */ + protected void resolveNode(User user, Node node, VirtualNetwork virtualNetwork, + UserIntentVnMapping userIntentVnMapping) + throws IntentResolutionException { + NodeType nodeType = node.getNodeType(); + + if ( nodeType.equals(new NodeType("host")) ) { + resolveHost(user, node, virtualNetwork, userIntentVnMapping); + + return; + } + + if ( nodeType.equals(new NodeType(("l2-group"))) ) { + resolveLayer2Group(user, node, virtualNetwork, userIntentVnMapping); + + return; + } + + if ( nodeType.equals(new NodeType("l3-group")) ) { + resolveLayer3Group(user, node, virtualNetwork, userIntentVnMapping); + + return; + } + + if ( nodeType.equals(new NodeType("ext-group")) ) { + if ( IntentResolverUtils.checkExternalLayer3Group(node) ) { + resolveExternalLayer3Group(user, node, virtualNetwork, userIntentVnMapping); + } + + return; + } + + if ( nodeType.equals(new NodeType("chain-group")) ) { + resolveServiceChainGroup(user, node, virtualNetwork, userIntentVnMapping); + + return; + } + + if ( nodeType.equals(new NodeType("fw")) + || nodeType.equals(new NodeType("lb")) + || nodeType.equals(new NodeType("cache")) ) { + resolveServiceFunction(user, node, virtualNetwork, userIntentVnMapping); + + return; + } + + throw new IntentResolutionException("Unknown node type."); + +// return; + } + + /** + * TODO + * + * @param user TODO + * @param node TODO + * @param virtualNetwork TODO + * @param userIntentVnMapping TODO + */ + protected void resolveHost(User user, Node node, VirtualNetwork virtualNetwork, + UserIntentVnMapping userIntentVnMapping) + throws IntentResolutionException { + ReadOnlyTransaction readOnlyTransaction = dataBroker.newReadOnlyTransaction(); + + InstanceIdentifier physicalHostsIid = InstanceIdentifier + .builder(PhysicalNetwork.class) + .child(PhysicalHosts.class) + .build(); + Optional result; + + try { + result = readOnlyTransaction.read(LogicalDatastoreType.OPERATIONAL, physicalHostsIid).get(); + } catch ( InterruptedException | ExecutionException exception ) { + throw new IntentResolutionException("Can not read the physical hosts."); + } + + if ( !result.isPresent() ) { + throw new IntentResolutionException("The physical hosts do not exist."); + } + + PhysicalHosts physicalHosts = result.get(); + List physicalHostList = physicalHosts.getPhysicalHost(); + PhysicalHost physicalHost = IntentResolverUtils.getPhysicalHost(physicalHostList, node); + + if ( null == physicalHost ) { + throw new IntentResolutionException("The physical host corresponding to the node " + + node.getNodeId().getValue() + " does not exist."); + } + + List physicalResourceRequirements = + new ArrayList(1); + AttributeValue attributeValue = new AttributeValueBuilder() + .setStringValue(physicalHost.getNodeId().getValue()) + .build(); + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.node.instance.PhysicalResourceRequirement physicalResourceRequirement = + new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.node.instance.PhysicalResourceRequirementBuilder() + .setAttributeName(new AttributeName("location")) + .setAttributeValue(attributeValue) + .setAttributeMatchPattern(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.node.instance.PhysicalResourceRequirement.AttributeMatchPattern.Equal) + .build(); + physicalResourceRequirements.add(physicalResourceRequirement); + + VirtualNode virtualNode = new VirtualNodeBuilder() + .setNodeId(new VirtualNodeId(UUID.randomUUID().toString())) + .setNodeType(VirtualNode.NodeType.Vswitch) + .setVirtualPort(new LinkedList()) + .setPhysicalResourceRequirement(physicalResourceRequirements) + .build(); + + virtualNetwork.getVirtualNodes().getVirtualNode().add(virtualNode); + + List macAddresses = new ArrayList(1); + macAddresses.add(physicalHost.getMacAddress()); + ExternalMacAddresses externalMacAddresses = new ExternalMacAddressesBuilder() + .setExternalMacAddress(macAddresses) + .build(); + + List physicalResourceRequirements1 = + new ArrayList(1); + AttributeValue attributeValue1 = new AttributeValueBuilder() + .setStringValue(physicalHost.getPortId().getValue()) + .build(); + PhysicalResourceRequirement physicalResourceRequirement1 = new PhysicalResourceRequirementBuilder() + .setAttributeName(new AttributeName("location")) + .setAttributeValue(attributeValue1) + .setAttributeMatchPattern(PhysicalResourceRequirement.AttributeMatchPattern.Equal) + .build(); + physicalResourceRequirements1.add(physicalResourceRequirement1); + + VirtualPort virtualPort = new VirtualPortBuilder() + .setPortId(new VirtualPortId(UUID.randomUUID().toString())) + .setPortType(VirtualPort.PortType.External) + .setExternalMacAddresses(externalMacAddresses) + .setPhysicalResourceRequirement(physicalResourceRequirements1) + .build(); + + virtualNode.getVirtualPort().add(virtualPort); + + List virtualArps = virtualNetwork.getVirtualArps().getVirtualArp(); + VirtualArp virtualArp; + + for ( IpAddress ipAddress : physicalHost.getIpAddresses().getIpAddress() ) { + virtualArp = new VirtualArpBuilder() + .setIpAddress(ipAddress) + .setMacAddress(physicalHost.getMacAddress()) + .setNodeId(virtualNode.getNodeId()) + .setPortId(virtualPort.getPortId()) + .build(); + virtualArps.add(virtualArp); + } + + List virtualResources = new ArrayList(1); + VirtualResource virtualResource = new VirtualResourceBuilder() + .setVirtualResourceId(new VirtualResourceId(UUID.randomUUID().toString())) + .setVirtualResourceType(VirtualResource.VirtualResourceType.Vport) + .setVirtualResourceEntityId(new VirtualResourceEntityId(virtualPort.getPortId().getValue())) + .setParentVirtualResourceEntityId(new VirtualResourceEntityId(virtualNode.getNodeId().getValue())) + .setOrder(0L) + .build(); + virtualResources.add(virtualResource); + + IntentVnMappingResult intentVnMappingResult = new IntentVnMappingResultBuilder() + .setIntentId(new IntentId(node.getNodeId().getValue())) + .setIntentType(IntentVnMappingResult.IntentType.Node) + .setVirtualResource(virtualResources) + .build(); + + userIntentVnMapping.getIntentVnMappingResult().add(intentVnMappingResult); + + return; + } + + /** + * TODO + * + * @param user TODO + * @param node TODO + * @param virtualNetwork TODO + * @param userIntentVnMapping TODO + */ + protected void resolveLayer2Group(User user, Node node, VirtualNetwork virtualNetwork, + UserIntentVnMapping userIntentVnMapping) + throws IntentResolutionException { + List nodes = user.getObjects().getNode(); + List subNodes = node.getSubNode(); + Node node1; + NodeType nodeType = new NodeType("ext-group"); + List virtualSwitches = new ArrayList(subNodes.size()); + List intentVnMappingResults = userIntentVnMapping.getIntentVnMappingResult(); + List virtualNodes = virtualNetwork.getVirtualNodes().getVirtualNode(); + IntentVnMappingResult intentVnMappingResult; + VirtualNode virtualNode; + + for ( SubNode subNode : subNodes ) { + node1 = IntentResolverUtils.getNode(nodes, subNode.getNodeId()); + + if ( null == node1 ) { + throw new IntentResolutionException("The sub-node " + subNode.getNodeId().getValue() + + " of the node " + node.getNodeId().getValue() + " does not exist."); + } + + if ( node1.getNodeType().equals(nodeType) ) { + if ( IntentResolverUtils.checkExternalLayer3Group(node1) ) { + throw new IntentResolutionException("The sub-node " + subNode.getNodeId().getValue() + + " of the node " + node.getNodeId().getValue() + " can't be layer3 group."); + } + + resolveExternalLayer2Group(user, node1, virtualNetwork, userIntentVnMapping, false); + } + + intentVnMappingResult = IntentResolverUtils.getIntentVnMappingResult(intentVnMappingResults, + new IntentId(node1.getNodeId().getValue())); + + if ( null == intentVnMappingResult ) { + throw new IntentResolutionException("Can not get the intent-vn mapping result for " + + "the node " + node1.getNodeId().getValue() + "."); + } + + virtualNode = IntentResolverUtils.getVirtualNode(virtualNodes, + new VirtualNodeId(intentVnMappingResult.getVirtualResource().get(0) + .getParentVirtualResourceEntityId().getValue())); + + if ( null == virtualNode ) { + throw new IntentResolutionException("Can not get the virtual node created for " + + "the node " + node1.getNodeId().getValue() + "."); + } + + virtualSwitches.add(virtualNode); + } + + Property locationProperty = IntentResolverUtils + .getNodeProperty(node.getProperty(), new PropertyName("location")); + List physicalResourceRequirements; + + if ( null == locationProperty ) { + physicalResourceRequirements = + new ArrayList(0); + } else { + physicalResourceRequirements = + new ArrayList(1); + AttributeValue attributeValue = new AttributeValueBuilder() + .setStringValue(locationProperty.getPropertyValues().getStringValue().get(0).getValue()) + .build(); + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.node.instance.PhysicalResourceRequirement physicalResourceRequirement = + new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.node.instance.PhysicalResourceRequirementBuilder() + .setAttributeName(new AttributeName("location")) + .setAttributeValue(attributeValue) + .setAttributeMatchPattern(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.node.instance.PhysicalResourceRequirement.AttributeMatchPattern.Equal) + .build(); + physicalResourceRequirements.add(physicalResourceRequirement); + } + + VirtualNode virtualRouter = new VirtualNodeBuilder() + .setNodeId(new VirtualNodeId(UUID.randomUUID().toString())) + .setNodeType(VirtualNode.NodeType.Vrouter) + .setVirtualPort(new LinkedList()) + .setPhysicalResourceRequirement(physicalResourceRequirements) + .build(); + + virtualNodes.add(virtualRouter); + + ExternalIpPrefixes externalIpPrefixes; + Property ipPrefixProperty = IntentResolverUtils + .getNodeProperty(node.getProperty(), new PropertyName("ip-prefix")); + + if ( null == ipPrefixProperty ) { + externalIpPrefixes = new ExternalIpPrefixesBuilder() + .setExternalIpPrefix(new ArrayList(0)) + .build(); + } else { + List ipPrefixes = new ArrayList(1); + IpPrefix ipPrefix = new IpPrefix( + new Ipv4Prefix(ipPrefixProperty.getPropertyValues().getStringValue().get(0).getValue())); + ipPrefixes.add(ipPrefix); + + externalIpPrefixes = new ExternalIpPrefixesBuilder() + .setExternalIpPrefix(ipPrefixes) + .build(); + } + + List virtualLinks = virtualNetwork.getVirtualLinks().getVirtualLink(); + Set handledVirtualSwitches = new HashSet(); + VirtualPort virtualPort; + VirtualPort virtualPort1; + VirtualLink virtualLink; + + for ( VirtualNode virtualSwitch : virtualSwitches ) { + virtualPort = new VirtualPortBuilder() + .setPortId(new VirtualPortId(UUID.randomUUID().toString())) + .setPortType(VirtualPort.PortType.Internal) + .setExternalIpPrefixes(externalIpPrefixes) + .build(); + virtualRouter.getVirtualPort().add(virtualPort); + + virtualPort1 = new VirtualPortBuilder() + .setPortId(new VirtualPortId(UUID.randomUUID().toString())) + .setPortType(VirtualPort.PortType.Internal) + .build(); + virtualSwitch.getVirtualPort().add(virtualPort1); + + virtualLink = new VirtualLinkBuilder() + .setLinkId(new VirtualLinkId(UUID.randomUUID().toString())) + .setSrcNodeId(virtualRouter.getNodeId()) + .setSrcPortId(virtualPort.getPortId()) + .setDestNodeId(virtualSwitch.getNodeId()) + .setDestPortId(virtualPort1.getPortId()) + .setBandwidth(0L) + .build(); + virtualLinks.add(virtualLink); + + virtualLink = new VirtualLinkBuilder() + .setLinkId(new VirtualLinkId(UUID.randomUUID().toString())) + .setSrcNodeId(virtualSwitch.getNodeId()) + .setSrcPortId(virtualPort1.getPortId()) + .setDestNodeId(virtualRouter.getNodeId()) + .setDestPortId(virtualPort.getPortId()) + .setBandwidth(0L) + .build(); + virtualLinks.add(virtualLink); + + for ( VirtualNode virtualSwitch1 : virtualSwitches ) { + if ( virtualSwitch1.getNodeId().equals(virtualSwitch.getNodeId()) ) { + continue; + } + + if ( handledVirtualSwitches.contains(virtualSwitch1.getNodeId()) ) { + continue; + } + + virtualPort = new VirtualPortBuilder() + .setPortId(new VirtualPortId(UUID.randomUUID().toString())) + .setPortType(VirtualPort.PortType.Internal) + .build(); + virtualSwitch.getVirtualPort().add(virtualPort); + + virtualPort1 = new VirtualPortBuilder() + .setPortId(new VirtualPortId(UUID.randomUUID().toString())) + .setPortType(VirtualPort.PortType.Internal) + .build(); + virtualSwitch1.getVirtualPort().add(virtualPort1); + + virtualLink = new VirtualLinkBuilder() + .setLinkId(new VirtualLinkId(UUID.randomUUID().toString())) + .setSrcNodeId(virtualSwitch.getNodeId()) + .setSrcPortId(virtualPort.getPortId()) + .setDestNodeId(virtualSwitch1.getNodeId()) + .setDestPortId(virtualPort1.getPortId()) + .setBandwidth(0L) + .build(); + virtualLinks.add(virtualLink); + + virtualLink = new VirtualLinkBuilder() + .setLinkId(new VirtualLinkId(UUID.randomUUID().toString())) + .setSrcNodeId(virtualSwitch1.getNodeId()) + .setSrcPortId(virtualPort1.getPortId()) + .setDestNodeId(virtualSwitch.getNodeId()) + .setDestPortId(virtualPort.getPortId()) + .setBandwidth(0L) + .build(); + virtualLinks.add(virtualLink); + } + + handledVirtualSwitches.add(virtualSwitch.getNodeId()); + } + + List virtualResources = new ArrayList(1); + VirtualResource virtualResource = new VirtualResourceBuilder() + .setVirtualResourceId(new VirtualResourceId(UUID.randomUUID().toString())) + .setVirtualResourceType(VirtualResource.VirtualResourceType.Vnode) + .setVirtualResourceEntityId(new VirtualResourceEntityId(virtualRouter.getNodeId().getValue())) + .setOrder(0L) + .build(); + virtualResources.add(virtualResource); + + intentVnMappingResult = new IntentVnMappingResultBuilder() + .setIntentId(new IntentId(node.getNodeId().getValue())) + .setIntentType(IntentVnMappingResult.IntentType.Node) + .setVirtualResource(virtualResources) + .build(); + + intentVnMappingResults.add(intentVnMappingResult); + + return; + } + + /** + * TODO + * + * @param user TODO + * @param node TODO + * @param virtualNetwork TODO + * @param userIntentVnMapping TODO + */ + protected void resolveLayer3Group(User user, Node node, VirtualNetwork virtualNetwork, + UserIntentVnMapping userIntentVnMapping) + throws IntentResolutionException { + // TODO: 1、l3-group的sub-node可能是:l2-group、ext-group(l2)、ext-group(l3)。 + // TODO: 将各个sub-node对应的gateway/access vrouter用vlinks连接(vrouter的vport)。 + // TODO: 特别注意:需为ext-group(l2)创建gateway vrouter。 + // TODO: 2、在data store中,创建vrouter、vports、vlinks。 + // TODO: 3、将intent - vn mapping result写入data store。 + // TODO: 4、将新vrouter、vlinks更新入user对应的算法实例。 + // TODO: 通过算法实例,重新计算全网路由。 + // TODO: 5、在data store中,新增 or 更新vroute。 + + return; + } + + /** + * TODO + * + * @param user TODO + * @param node TODO + * @param virtualNetwork TODO + * @param userIntentVnMapping TODO + * @param generatingVirtualRouter TODO + */ + protected void resolveExternalLayer2Group(User user, Node node, VirtualNetwork virtualNetwork, + UserIntentVnMapping userIntentVnMapping, + boolean generatingVirtualRouter) + throws IntentResolutionException { + Property property = IntentResolverUtils + .getNodeProperty(node.getProperty(), new PropertyName("location")); + + if ( null == property ) { + throw new IntentResolutionException("Can not get the location property of the node " + + node.getNodeId().getValue() + "."); + } + + PhysicalNodeId physicalNodeId = IntentResolverUtils + .generatePhysicalNodeIdFromNodeLocationProperty(property); + + List physicalResourceRequirements = + new ArrayList(1); + AttributeValue attributeValue = new AttributeValueBuilder() + .setStringValue(physicalNodeId.getValue()) + .build(); + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.node.instance.PhysicalResourceRequirement physicalResourceRequirement = + new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.node.instance.PhysicalResourceRequirementBuilder() + .setAttributeName(new AttributeName("location")) + .setAttributeValue(attributeValue) + .setAttributeMatchPattern(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.node.instance.PhysicalResourceRequirement.AttributeMatchPattern.Equal) + .build(); + physicalResourceRequirements.add(physicalResourceRequirement); + + VirtualNode virtualNode = new VirtualNodeBuilder() + .setNodeId(new VirtualNodeId(UUID.randomUUID().toString())) + .setNodeType(generatingVirtualRouter ? VirtualNode.NodeType.Vrouter : VirtualNode.NodeType.Vswitch) + .setVirtualPort(new LinkedList()) + .setPhysicalResourceRequirement(physicalResourceRequirements) + .build(); + + virtualNetwork.getVirtualNodes().getVirtualNode().add(virtualNode); + + ExternalMacAddresses externalMacAddresses = new ExternalMacAddressesBuilder() + .setExternalMacAddress(new ArrayList(0)) + .build(); + + ExternalIpPrefixes externalIpPrefixes = null; + + if ( generatingVirtualRouter ) { + Property property1 = IntentResolverUtils + .getNodeProperty(node.getProperty(), new PropertyName("ip-prefix")); + + if ( null != property1 ) { + List ipPrefixes = new ArrayList(1); + IpPrefix ipPrefix = new IpPrefix( + new Ipv4Prefix(property1.getPropertyValues().getStringValue().get(0).getValue())); + ipPrefixes.add(ipPrefix); + + externalIpPrefixes = new ExternalIpPrefixesBuilder() + .setExternalIpPrefix(ipPrefixes) + .build(); + } else { + externalIpPrefixes = new ExternalIpPrefixesBuilder() + .setExternalIpPrefix(new ArrayList(0)) + .build(); + } + } + + List physicalResourceRequirements1 = + new ArrayList(1); + AttributeValue attributeValue1 = new AttributeValueBuilder() + .setStringValue(property.getPropertyValues().getStringValue().get(0).getValue()) + .build(); + PhysicalResourceRequirement physicalResourceRequirement1 = new PhysicalResourceRequirementBuilder() + .setAttributeName(new AttributeName("location")) + .setAttributeValue(attributeValue1) + .setAttributeMatchPattern(PhysicalResourceRequirement.AttributeMatchPattern.Equal) + .build(); + physicalResourceRequirements1.add(physicalResourceRequirement1); + + VirtualPort virtualPort = new VirtualPortBuilder() + .setPortId(new VirtualPortId(UUID.randomUUID().toString())) + .setPortType(VirtualPort.PortType.External) + .setExternalMacAddresses(externalMacAddresses) + .setExternalIpPrefixes(externalIpPrefixes) + .setPhysicalResourceRequirement(physicalResourceRequirements1) + .build(); + + virtualNode.getVirtualPort().add(virtualPort); + + List virtualResources = new ArrayList(1); + VirtualResource virtualResource = new VirtualResourceBuilder() + .setVirtualResourceId(new VirtualResourceId(UUID.randomUUID().toString())) + .setVirtualResourceType(VirtualResource.VirtualResourceType.Vport) + .setVirtualResourceEntityId(new VirtualResourceEntityId(virtualPort.getPortId().getValue())) + .setParentVirtualResourceEntityId(new VirtualResourceEntityId(virtualNode.getNodeId().getValue())) + .setOrder(0L) + .build(); + virtualResources.add(virtualResource); + + IntentVnMappingResult intentVnMappingResult = new IntentVnMappingResultBuilder() + .setIntentId(new IntentId(node.getNodeId().getValue())) + .setIntentType(IntentVnMappingResult.IntentType.Node) + .setVirtualResource(virtualResources) + .build(); + + userIntentVnMapping.getIntentVnMappingResult().add(intentVnMappingResult); + + return; + } + + /** + * TODO + * + * @param user TODO + * @param node TODO + * @param virtualNetwork TODO + * @param userIntentVnMapping TODO + */ + protected void resolveExternalLayer3Group(User user, Node node, VirtualNetwork virtualNetwork, + UserIntentVnMapping userIntentVnMapping) + throws IntentResolutionException { + Property property = IntentResolverUtils + .getNodeProperty(node.getProperty(), new PropertyName("location")); + + if ( null == property ) { + throw new IntentResolutionException("Can not get the location property of the node " + + node.getNodeId().getValue() + "."); + } + + PhysicalNodeId physicalNodeId = IntentResolverUtils + .generatePhysicalNodeIdFromNodeLocationProperty(property); + + List physicalResourceRequirements = + new ArrayList(1); + AttributeValue attributeValue = new AttributeValueBuilder() + .setStringValue(physicalNodeId.getValue()) + .build(); + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.node.instance.PhysicalResourceRequirement physicalResourceRequirement = + new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.node.instance.PhysicalResourceRequirementBuilder() + .setAttributeName(new AttributeName("location")) + .setAttributeValue(attributeValue) + .setAttributeMatchPattern(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.node.instance.PhysicalResourceRequirement.AttributeMatchPattern.Equal) + .build(); + physicalResourceRequirements.add(physicalResourceRequirement); + + VirtualNode virtualNode = new VirtualNodeBuilder() + .setNodeId(new VirtualNodeId(UUID.randomUUID().toString())) + .setNodeType(VirtualNode.NodeType.Vrouter) + .setVirtualPort(new LinkedList()) + .setPhysicalResourceRequirement(physicalResourceRequirements) + .build(); + + virtualNetwork.getVirtualNodes().getVirtualNode().add(virtualNode); + + ExternalIpPrefixes externalIpPrefixes; + Property property1 = IntentResolverUtils + .getNodeProperty(node.getProperty(), new PropertyName("ip-prefix")); + + if ( null != property1 ) { + List ipPrefixes = + new ArrayList(property1.getPropertyValues().getStringValue().size()); + IpPrefix ipPrefix; + + for ( StringValue stringValue : property1.getPropertyValues().getStringValue() ) { + ipPrefix = new IpPrefix(new Ipv4Prefix(stringValue.getValue())); + ipPrefixes.add(ipPrefix); + } + + externalIpPrefixes = new ExternalIpPrefixesBuilder() + .setExternalIpPrefix(ipPrefixes) + .build(); + } else { + externalIpPrefixes = new ExternalIpPrefixesBuilder() + .setExternalIpPrefix(new ArrayList(0)) + .build(); + } + + List physicalResourceRequirements1 = + new ArrayList(1); + AttributeValue attributeValue1 = new AttributeValueBuilder() + .setStringValue(property.getPropertyValues().getStringValue().get(0).getValue()) + .build(); + PhysicalResourceRequirement physicalResourceRequirement1 = new PhysicalResourceRequirementBuilder() + .setAttributeName(new AttributeName("location")) + .setAttributeValue(attributeValue1) + .setAttributeMatchPattern(PhysicalResourceRequirement.AttributeMatchPattern.Equal) + .build(); + physicalResourceRequirements1.add(physicalResourceRequirement1); + + VirtualPort virtualPort = new VirtualPortBuilder() + .setPortId(new VirtualPortId(UUID.randomUUID().toString())) + .setPortType(VirtualPort.PortType.External) + .setExternalIpPrefixes(externalIpPrefixes) + .setPhysicalResourceRequirement(physicalResourceRequirements1) + .build(); + + virtualNode.getVirtualPort().add(virtualPort); + + List virtualResources = new ArrayList(1); + VirtualResource virtualResource = new VirtualResourceBuilder() + .setVirtualResourceId(new VirtualResourceId(UUID.randomUUID().toString())) + .setVirtualResourceType(VirtualResource.VirtualResourceType.Vport) + .setVirtualResourceEntityId(new VirtualResourceEntityId(virtualPort.getPortId().getValue())) + .setParentVirtualResourceEntityId(new VirtualResourceEntityId(virtualNode.getNodeId().getValue())) + .setOrder(0L) + .build(); + virtualResources.add(virtualResource); + + IntentVnMappingResult intentVnMappingResult = new IntentVnMappingResultBuilder() + .setIntentId(new IntentId(node.getNodeId().getValue())) + .setIntentType(IntentVnMappingResult.IntentType.Node) + .setVirtualResource(virtualResources) + .build(); + + userIntentVnMapping.getIntentVnMappingResult().add(intentVnMappingResult); + + return; + } + + /** + * TODO + * + * @param user TODO + * @param node TODO + * @param virtualNetwork TODO + * @param userIntentVnMapping TODO + */ + protected void resolveServiceChainGroup(User user, Node node, VirtualNetwork virtualNetwork, + UserIntentVnMapping userIntentVnMapping) + throws IntentResolutionException { + List subNodes = node.getSubNode(); + + if ( !subNodes.isEmpty() ) { + List intentVnMappingResults = userIntentVnMapping.getIntentVnMappingResult(); + List virtualResources = new LinkedList(); + + if ( 1 == subNodes.size() ) { + SubNode subNode = subNodes.get(0); + IntentVnMappingResult intentVnMappingResult = IntentResolverUtils + .getIntentVnMappingResult(intentVnMappingResults, new IntentId(subNode.getNodeId().getValue())); + + if ( null == intentVnMappingResult ) { + throw new IntentResolutionException("Can not get the intent-vn mapping result for " + + "the node " + subNode.getNodeId().getValue() + "."); + } + + VirtualResource virtualResource = intentVnMappingResult.getVirtualResource().get(0); + virtualResource = new VirtualResourceBuilder(virtualResource) + .setVirtualResourceId(new VirtualResourceId(UUID.randomUUID().toString())) + .setOrder(0L) + .build(); + virtualResources.add(virtualResource); + } else { + subNodes = IntentResolverUtils.sortSubNodes(subNodes); + List nodes = user.getObjects().getNode(); + Iterator iterator = subNodes.iterator(); + SubNode subNode1 = iterator.next(); + SubNode subNode2; + IntentVnMappingResult intentVnMappingResult; + VirtualResource virtualResource; + + if ( IntentResolverUtils.checkAllLayer2OperatingMode(subNodes, nodes) ) { + // TODO + } else if ( IntentResolverUtils.checkAllLayer3OperatingMode(subNodes, nodes) ) { + List virtualNodes = virtualNetwork.getVirtualNodes().getVirtualNode(); + List virtualLinks = virtualNetwork.getVirtualLinks().getVirtualLink(); + List virtualPaths = virtualNetwork.getVirtualPaths().getVirtualPath(); + VirtualNodeId virtualNodeId1; + VirtualNodeId virtualNodeId2; + VirtualNode virtualNode1 = null; + VirtualNode virtualNode2 = null; + VirtualPort virtualPort1; + VirtualPort virtualPort2; + VirtualLink virtualLink; + List virtualLinks1; + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.path.instance.VirtualLink virtualLink1; + VirtualPath virtualPath; + + intentVnMappingResult = IntentResolverUtils.getIntentVnMappingResult(intentVnMappingResults, + new IntentId(subNode1.getNodeId().getValue())); + + if ( null == intentVnMappingResult ) { + throw new IntentResolutionException("Can not get the intent-vn mapping result for " + + "the node " + subNode1.getNodeId().getValue() + "."); + } + + virtualResource = intentVnMappingResult.getVirtualResource().get(0); + virtualResource = new VirtualResourceBuilder(virtualResource) + .setVirtualResourceId(new VirtualResourceId(UUID.randomUUID().toString())) + .setOrder(0L) + .build(); + virtualResources.add(virtualResource); + + virtualNodeId1 = new VirtualNodeId(intentVnMappingResult.getVirtualResource().get(0) + .getParentVirtualResourceEntityId().getValue()); + + while ( iterator.hasNext() ) { + subNode2 = iterator.next(); + intentVnMappingResult = IntentResolverUtils.getIntentVnMappingResult(intentVnMappingResults, + new IntentId(subNode2.getNodeId().getValue())); + + if ( null == intentVnMappingResult ) { + throw new IntentResolutionException("Can not get the intent-vn mapping result " + + "for the node " + subNode2.getNodeId().getValue() + "."); + } + + virtualNodeId2 = new VirtualNodeId(intentVnMappingResult.getVirtualResource().get(0) + .getParentVirtualResourceEntityId().getValue()); + virtualLink = IntentResolverUtils.getVirtualLink(virtualLinks, virtualNodeId1, virtualNodeId2); + + if ( null == virtualLink ) { + if ( null == virtualNode1 ) { + virtualNode1 = IntentResolverUtils.getVirtualNode(virtualNodes, virtualNodeId1); + + if ( null == virtualNode1 ) { + throw new IntentResolutionException("Can not get the virtual node " + + "created for the node " + subNode1.getNodeId().getValue() + "."); + } + } + + virtualNode2 = IntentResolverUtils.getVirtualNode(virtualNodes, virtualNodeId2); + + if ( null == virtualNode2 ) { + throw new IntentResolutionException("Can not get the virtual node created " + + "for the node " + subNode2.getNodeId().getValue() + "."); + } + + virtualPort1 = new VirtualPortBuilder() + .setPortId(new VirtualPortId(UUID.randomUUID().toString())) + .setPortType(VirtualPort.PortType.Internal) + .build(); + virtualNode1.getVirtualPort().add(virtualPort1); + + virtualPort2 = new VirtualPortBuilder() + .setPortId(new VirtualPortId(UUID.randomUUID().toString())) + .setPortType(VirtualPort.PortType.Internal) + .build(); + virtualNode2.getVirtualPort().add(virtualPort2); + + virtualLink = new VirtualLinkBuilder() + .setLinkId(new VirtualLinkId(UUID.randomUUID().toString())) + .setSrcNodeId(virtualNodeId2) + .setSrcPortId(virtualPort2.getPortId()) + .setDestNodeId(virtualNodeId1) + .setDestPortId(virtualPort1.getPortId()) + .setBandwidth(0L) + .build(); + virtualLinks.add(virtualLink); + + virtualLink = new VirtualLinkBuilder() + .setLinkId(new VirtualLinkId(UUID.randomUUID().toString())) + .setSrcNodeId(virtualNodeId1) + .setSrcPortId(virtualPort1.getPortId()) + .setDestNodeId(virtualNodeId2) + .setDestPortId(virtualPort2.getPortId()) + .setBandwidth(0L) + .build(); + virtualLinks.add(virtualLink); + } + + virtualLinks1 = new ArrayList(1); + virtualLink1 = new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.path.instance.VirtualLinkBuilder() + .setLinkId(virtualLink.getLinkId()) + .setOrder(0L) + .build(); + virtualLinks1.add(virtualLink1); + + virtualPath = new VirtualPathBuilder() + .setPathId(new VirtualPathId(UUID.randomUUID().toString())) + .setVirtualLink(virtualLinks1) + .setBandwidth(0L) + .build(); + virtualPaths.add(virtualPath); + + virtualResource = new VirtualResourceBuilder() + .setVirtualResourceId(new VirtualResourceId(UUID.randomUUID().toString())) + .setVirtualResourceType(VirtualResource.VirtualResourceType.Vpath) + .setVirtualResourceEntityId(new VirtualResourceEntityId(virtualPath.getPathId().getValue())) + .setOrder((long) virtualResources.size()) + .build(); + virtualResources.add(virtualResource); + + virtualResource = intentVnMappingResult.getVirtualResource().get(0); + virtualResource = new VirtualResourceBuilder(virtualResource) + .setVirtualResourceId(new VirtualResourceId(UUID.randomUUID().toString())) + .setOrder((long) virtualResources.size()) + .build(); + virtualResources.add(virtualResource); + + subNode1 = subNode2; + virtualNodeId1 = virtualNodeId2; + virtualNode1 = virtualNode2; + virtualNode2 = null; + } + } else { + // TODO + } + } + + IntentVnMappingResult intentVnMappingResult = new IntentVnMappingResultBuilder() + .setIntentId(new IntentId(node.getNodeId().getValue())) + .setIntentType(IntentVnMappingResult.IntentType.Node) + .setVirtualResource(virtualResources) + .build(); + + intentVnMappingResults.add(intentVnMappingResult); + } + + return; + } + + /** + * TODO + * + * @param user TODO + * @param node TODO + * @param virtualNetwork TODO + * @param userIntentVnMapping TODO + */ + protected void resolveServiceFunction(User user, Node node, VirtualNetwork virtualNetwork, + UserIntentVnMapping userIntentVnMapping) + throws IntentResolutionException { + Property locationProperty = IntentResolverUtils + .getNodeProperty(node.getProperty(), new PropertyName("location")); + + if ( null == locationProperty ) { + throw new IntentResolutionException("Can not get the location property of the node " + + node.getNodeId().getValue() + "."); + } + + Property operatingModeProperty = IntentResolverUtils + .getNodeProperty(node.getProperty(), new PropertyName("operating-mode")); + + if ( null == operatingModeProperty ) { + throw new IntentResolutionException("Can not get the operating mode property of the node " + + node.getNodeId().getValue() + "."); + } + + PhysicalNodeId physicalNodeId = IntentResolverUtils + .generatePhysicalNodeIdFromNodeLocationProperty(locationProperty); + + List physicalResourceRequirements = + new ArrayList(1); + AttributeValue attributeValue = new AttributeValueBuilder() + .setStringValue(physicalNodeId.getValue()) + .build(); + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.node.instance.PhysicalResourceRequirement physicalResourceRequirement = + new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.node.instance.PhysicalResourceRequirementBuilder() + .setAttributeName(new AttributeName("location")) + .setAttributeValue(attributeValue) + .setAttributeMatchPattern(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.node.instance.PhysicalResourceRequirement.AttributeMatchPattern.Equal) + .build(); + physicalResourceRequirements.add(physicalResourceRequirement); + + String operatingModePropertyValue = + operatingModeProperty.getPropertyValues().getStringValue().get(0).getValue(); + + VirtualNode virtualNode = new VirtualNodeBuilder() + .setNodeId(new VirtualNodeId(UUID.randomUUID().toString())) + .setNodeType(operatingModePropertyValue.equals("layer3") ? + VirtualNode.NodeType.Vrouter : VirtualNode.NodeType.Vswitch) + .setVirtualPort(new LinkedList()) + .setPhysicalResourceRequirement(physicalResourceRequirements) + .build(); + + virtualNetwork.getVirtualNodes().getVirtualNode().add(virtualNode); + + ExternalMacAddresses externalMacAddresses = null; + ExternalIpPrefixes externalIpPrefixes = null; + + if ( operatingModePropertyValue.equals("layer2") ) { + externalMacAddresses = new ExternalMacAddressesBuilder() + .setExternalMacAddress(new ArrayList(0)) + .build(); + } else { + externalIpPrefixes = new ExternalIpPrefixesBuilder() + .setExternalIpPrefix(new ArrayList(0)) + .build(); + } + + List physicalResourceRequirements1 = + new ArrayList(1); + AttributeValue attributeValue1 = new AttributeValueBuilder() + .setStringValue(locationProperty.getPropertyValues().getStringValue().get(0).getValue()) + .build(); + PhysicalResourceRequirement physicalResourceRequirement1 = new PhysicalResourceRequirementBuilder() + .setAttributeName(new AttributeName("location")) + .setAttributeValue(attributeValue1) + .setAttributeMatchPattern(PhysicalResourceRequirement.AttributeMatchPattern.Equal) + .build(); + physicalResourceRequirements1.add(physicalResourceRequirement1); + + VirtualPort virtualPort = new VirtualPortBuilder() + .setPortId(new VirtualPortId(UUID.randomUUID().toString())) + .setPortType(VirtualPort.PortType.External) + .setExternalMacAddresses(externalMacAddresses) + .setExternalIpPrefixes(externalIpPrefixes) + .setPhysicalResourceRequirement(physicalResourceRequirements1) + .build(); + + virtualNode.getVirtualPort().add(virtualPort); + + if ( operatingModePropertyValue.equals("layer2") ) { + // TODO: Connect to all virtual switches in the same layer2 group. + } + + List virtualResources = new ArrayList(1); + VirtualResource virtualResource = new VirtualResourceBuilder() + .setVirtualResourceId(new VirtualResourceId(UUID.randomUUID().toString())) + .setVirtualResourceType(VirtualResource.VirtualResourceType.Vport) + .setVirtualResourceEntityId(new VirtualResourceEntityId(virtualPort.getPortId().getValue())) + .setParentVirtualResourceEntityId(new VirtualResourceEntityId(virtualNode.getNodeId().getValue())) + .setOrder(0L) + .build(); + virtualResources.add(virtualResource); + + IntentVnMappingResult intentVnMappingResult = new IntentVnMappingResultBuilder() + .setIntentId(new IntentId(node.getNodeId().getValue())) + .setIntentType(IntentVnMappingResult.IntentType.Node) + .setVirtualResource(virtualResources) + .build(); + + userIntentVnMapping.getIntentVnMappingResult().add(intentVnMappingResult); + + return; + } +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/intent/OperationResolver.java b/nemo-impl/src/main/java/org/opendaylight/nemo/intent/OperationResolver.java new file mode 100644 index 0000000..1d52689 --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/intent/OperationResolver.java @@ -0,0 +1,473 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.nemo.intent; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.VirtualNetwork; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.links.VirtualLink; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.links.VirtualLinkBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.nodes.VirtualNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.paths.VirtualPath; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.paths.VirtualPathBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.node.instance.VirtualPort; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.node.instance.VirtualPortBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.intent.vn.mapping.results.UserIntentVnMapping; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.intent.vn.mapping.results.user.intent.vn.mapping.IntentVnMappingResult; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.intent.vn.mapping.results.user.intent.vn.mapping.IntentVnMappingResultBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.intent.vn.mapping.results.user.intent.vn.mapping.intent.vn.mapping.result.VirtualResource; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.intent.vn.mapping.results.user.intent.vn.mapping.intent.vn.mapping.result.VirtualResourceBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.ActionName; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.IntentId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.NodeId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.NodeType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.common.rev151010.*; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Connection; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Flow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.operations.Operation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.users.User; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.operation.rev151010.action.instance.parameter.values.StringValue; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.operation.rev151010.condition.instance.ConditionSegment; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.operation.rev151010.operation.instance.Action; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.UUID; + +/** + * Resolve the user's operation intent that might act on the node, connection + * or flow. Perform the monitoring if the operation contains a condition which + * determines when to execute the operation. Resolve the actions included in + * the operation and decide how to implement them on the physical network. + * + * @author Zhigang Ji + */ +public class OperationResolver { + private static final Logger LOG = LoggerFactory.getLogger(OperationResolver.class); + + private final DataBroker dataBroker; + + /** + * The action resolver to resolve actions in the operation. + */ + private ActionResolver actionResolver; + + public OperationResolver(DataBroker dataBroker) { + super(); + + this.dataBroker = dataBroker; + + actionResolver = new ActionResolver(); + + LOG.debug("Initialized the renderer common operation resolver."); + + return; + } + + /** + * Resolve the user's operation intent and perform the monitoring for + * the condition that it contains. Generate the intent mapping results + * for the operation in the data store, which denote how to implement + * it on the physical network. + * + * @param user The user for the operation. + * @param operation The operation to be resolved. + * @param virtualNetwork The virtual network for the user. + * @param userIntentVnMapping The intent-vn mapping for the user. + */ + protected void resolveOperation(User user, Operation operation, VirtualNetwork virtualNetwork, + UserIntentVnMapping userIntentVnMapping) + throws IntentResolutionException { + DataObject dataObject = IntentResolverUtils + .getObject(user.getObjects(), operation.getTargetObject()); + + if ( null == dataObject ) { + throw new IntentResolutionException("The target object of the operation " + + operation.getOperationId().getValue() + " does not exist."); + } + + List operations = user.getOperations().getOperation(); + List sameTargetObjectOperations = IntentResolverUtils + .getSameTargetObjectOperations(operations, operation); + + if ( !sameTargetObjectOperations.isEmpty() ) { + List greaterPriorityOperations = new LinkedList(); + List equalPriorityOperations = new LinkedList(); + + IntentResolverUtils.getGreaterAndEqualPriorityOperations(sameTargetObjectOperations, + operation, greaterPriorityOperations, equalPriorityOperations); + + if ( greaterPriorityOperations.isEmpty() ) { + if ( !equalPriorityOperations.isEmpty() ) { + Operation conflictingOperation = IntentResolverUtils + .getConflictingOperation(equalPriorityOperations, operation); + + if ( null != conflictingOperation ) { + throw new IntentResolutionException("The operation " + + operation.getOperationId().getValue() + " conflicts with the one " + + conflictingOperation.getOperationId().getValue() + "."); + } + } + } else { + return; + } + } + + List conditionSegments = operation.getConditionSegment(); + + if ( null != conditionSegments && !conditionSegments.isEmpty() ) { + // TODO + + return; + } + + List actions = operation.getAction(); + + if ( null != actions && !actions.isEmpty() ) { + if ( dataObject instanceof Node ) { + actionResolver.resolveActions(user, operation, (Node)dataObject, + virtualNetwork, userIntentVnMapping); + } else if ( dataObject instanceof Connection ) { + actionResolver.resolveActions(user, operation, (Connection)dataObject, + virtualNetwork, userIntentVnMapping); + } else { + actionResolver.resolveActions(user, operation, (Flow)dataObject, + virtualNetwork, userIntentVnMapping); + } + } + + return; + } + + /** + * Perform the monitoring for the operation that contains a condition + * which determines when to execute the operation. + * + * @author Zhigang Ji + */ + private class ConditionMonitor { + // TODO + } + + /** + * Resolve the actions included in the operation and decide how to + * implement them on the physical network. + * + * @author Zhigang Ji + */ + private class ActionResolver { + /** + * TODO + * + * @param user TODO + * @param operation TODO + * @param node TODO + * @param virtualNetwork TODO + * @param userIntentVnMapping TODO + */ + protected void resolveActions(User user, Operation operation, Node node, + VirtualNetwork virtualNetwork, + UserIntentVnMapping userIntentVnMapping) + throws IntentResolutionException { + // TODO + + return; + } + + /** + * TODO + * + * @param user TODO + * @param operation TODO + * @param connection TODO + * @param virtualNetwork TODO + * @param userIntentVnMapping TODO + */ + protected void resolveActions(User user, Operation operation, Connection connection, + VirtualNetwork virtualNetwork, + UserIntentVnMapping userIntentVnMapping) + throws IntentResolutionException { + // TODO + + return; + } + + /** + * TODO + * + * @param user TODO + * @param operation TODO + * @param flow TODO + * @param virtualNetwork TODO + * @param userIntentVnMapping TODO + */ + protected void resolveActions(User user, Operation operation, Flow flow, + VirtualNetwork virtualNetwork, + UserIntentVnMapping userIntentVnMapping) + throws IntentResolutionException { + List actions = operation.getAction(); + + ActionName actionName = new ActionName("go-through"); + Action goThroughAction = IntentResolverUtils.getAction(actions, actionName); + + if ( null != goThroughAction ) { + resolveGoThroughAction(user, operation, flow, goThroughAction, + virtualNetwork, userIntentVnMapping); + + return; + } + + throw new IntentResolutionException("Unsupported action combination."); + +// return; + } + } + + /** + * TODO + * + * @param user TODO + * @param operation TODO + * @param flow TODO + * @param goThroughAction TODO + * @param virtualNetwork TODO + * @param userIntentVnMapping TODO + */ + private void resolveGoThroughAction(User user, Operation operation, Flow flow, + Action goThroughAction, + VirtualNetwork virtualNetwork, + UserIntentVnMapping userIntentVnMapping) + throws IntentResolutionException { + List parameterValues = goThroughAction.getParameterValues().getStringValue(); + + if ( !parameterValues.isEmpty() ) { + List nodes = user.getObjects().getNode(); + + if ( null == nodes || nodes.isEmpty() ) { + throw new IntentResolutionException("The nodes specified by the action parameters " + + "of the operation " + operation.getOperationId().getValue() + " does not exist."); + } + + NodeId nodeId = new NodeId(parameterValues.get(0).getValue()); + Node node = IntentResolverUtils.getNode(nodes, nodeId); + + if ( null == node ) { + throw new IntentResolutionException("The node " + nodeId.getValue() + " specified by the" + + " action parameter of the operation " + operation.getOperationId().getValue() + + " does not exist."); + } + + List virtualNodes = virtualNetwork.getVirtualNodes().getVirtualNode(); + List virtualLinks = virtualNetwork.getVirtualLinks().getVirtualLink(); + List virtualPaths = virtualNetwork.getVirtualPaths().getVirtualPath(); + List intentVnMappingResults = userIntentVnMapping.getIntentVnMappingResult(); + List virtualResources = null; + + if ( node.getNodeType().equals(new NodeType("chain-group")) ) { + if ( IntentResolverUtils.checkAllLayer2OperatingMode(node.getSubNode(), nodes) ) { + // TODO + } else if ( IntentResolverUtils.checkAllLayer3OperatingMode(node.getSubNode(), nodes) ) { + IntentVnMappingResult intentVnMappingResult = IntentResolverUtils.getIntentVnMappingResult( + intentVnMappingResults, new IntentId(node.getNodeId().getValue())); + + if ( null == intentVnMappingResult ) { + throw new IntentResolutionException("Can not get the intent-vn mapping result " + + "for the node " + node.getNodeId().getValue() + "."); + } + + VirtualNode sourceVirtualNode = IntentResolverUtils.getSourceVirtualRouterOfFlow( + virtualNodes, flow, nodes, intentVnMappingResults); + + if ( null == sourceVirtualNode ) { + throw new IntentResolutionException("Can not get the source virtual node " + + "of the flow " + flow.getFlowId().getValue() + "."); + } + + VirtualNode destinationVirtualNode = IntentResolverUtils.getDestinationVirtualRouterOfFlow( + virtualNodes, flow, nodes, intentVnMappingResults); + + if ( null == destinationVirtualNode ) { + throw new IntentResolutionException("Can not get the destination virtual node " + + "of the flow " + flow.getFlowId().getValue() + "."); + } + + List virtualResources1 = IntentResolverUtils + .sortVirtualResources(intentVnMappingResult.getVirtualResource()); + + VirtualNodeId virtualNodeId = new VirtualNodeId(virtualResources1.get(0) + .getParentVirtualResourceEntityId().getValue()); + VirtualNode virtualNode = IntentResolverUtils.getVirtualNode(virtualNodes, virtualNodeId); + + if ( null == virtualNode ) { + throw new IntentResolutionException("Can not get the virtual node" + + " created for the first sub-node of the node " + + intentVnMappingResult.getIntentId().getValue() + "."); + } + + virtualNodeId = new VirtualNodeId(virtualResources1.get(virtualResources1.size() - 1) + .getParentVirtualResourceEntityId().getValue()); + VirtualNode virtualNode1 = IntentResolverUtils.getVirtualNode(virtualNodes, virtualNodeId); + + if ( null == virtualNode1 ) { + throw new IntentResolutionException("Can not get the virtual node" + + " created for the last sub-node of the node " + + intentVnMappingResult.getIntentId().getValue() + "."); + } + + virtualResources = new ArrayList(virtualResources1.size() + 2); + VirtualLink virtualLink = IntentResolverUtils.getVirtualLink(virtualLinks, + sourceVirtualNode.getNodeId(), virtualNode.getNodeId()); + + if ( null == virtualLink ) { + VirtualPort virtualPort = new VirtualPortBuilder() + .setPortId(new VirtualPortId(UUID.randomUUID().toString())) + .setPortType(VirtualPort.PortType.Internal) + .build(); + sourceVirtualNode.getVirtualPort().add(virtualPort); + + VirtualPort virtualPort1 = new VirtualPortBuilder() + .setPortId(new VirtualPortId(UUID.randomUUID().toString())) + .setPortType(VirtualPort.PortType.Internal) + .build(); + virtualNode.getVirtualPort().add(virtualPort1); + + virtualLink = new VirtualLinkBuilder() + .setLinkId(new VirtualLinkId(UUID.randomUUID().toString())) + .setSrcNodeId(virtualNode.getNodeId()) + .setSrcPortId(virtualPort1.getPortId()) + .setDestNodeId(sourceVirtualNode.getNodeId()) + .setDestPortId(virtualPort.getPortId()) + .setBandwidth(0L) + .build(); + virtualLinks.add(virtualLink); + + virtualLink = new VirtualLinkBuilder() + .setLinkId(new VirtualLinkId(UUID.randomUUID().toString())) + .setSrcNodeId(sourceVirtualNode.getNodeId()) + .setSrcPortId(virtualPort.getPortId()) + .setDestNodeId(virtualNode.getNodeId()) + .setDestPortId(virtualPort1.getPortId()) + .setBandwidth(0L) + .build(); + virtualLinks.add(virtualLink); + } + + List virtualLinks1 = + new ArrayList(1); + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.path.instance.VirtualLink virtualLink1 = + new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.path.instance.VirtualLinkBuilder() + .setLinkId(virtualLink.getLinkId()) + .setOrder(0L) + .build(); + virtualLinks1.add(virtualLink1); + + VirtualPath virtualPath = new VirtualPathBuilder() + .setPathId(new VirtualPathId(UUID.randomUUID().toString())) + .setVirtualLink(virtualLinks1) + .setBandwidth(0L) + .build(); + virtualPaths.add(virtualPath); + + VirtualResource virtualResource = new VirtualResourceBuilder() + .setVirtualResourceId(new VirtualResourceId(UUID.randomUUID().toString())) + .setVirtualResourceType(VirtualResource.VirtualResourceType.Vpath) + .setVirtualResourceEntityId(new VirtualResourceEntityId(virtualPath.getPathId().getValue())) + .setOrder(0L) + .build(); + virtualResources.add(virtualResource); + + for ( VirtualResource virtualResource1 : virtualResources1 ) { + virtualResource = new VirtualResourceBuilder(virtualResource1) + .setVirtualResourceId(new VirtualResourceId(UUID.randomUUID().toString())) + .setOrder((long)virtualResources.size()) + .build(); + virtualResources.add(virtualResource); + } + + virtualLink = IntentResolverUtils.getVirtualLink(virtualLinks, + virtualNode1.getNodeId(), destinationVirtualNode.getNodeId()); + + if ( null == virtualLink ) { + VirtualPort virtualPort = new VirtualPortBuilder() + .setPortId(new VirtualPortId(UUID.randomUUID().toString())) + .setPortType(VirtualPort.PortType.Internal) + .build(); + virtualNode1.getVirtualPort().add(virtualPort); + + VirtualPort virtualPort1 = new VirtualPortBuilder() + .setPortId(new VirtualPortId(UUID.randomUUID().toString())) + .setPortType(VirtualPort.PortType.Internal) + .build(); + destinationVirtualNode.getVirtualPort().add(virtualPort1); + + virtualLink = new VirtualLinkBuilder() + .setLinkId(new VirtualLinkId(UUID.randomUUID().toString())) + .setSrcNodeId(destinationVirtualNode.getNodeId()) + .setSrcPortId(virtualPort1.getPortId()) + .setDestNodeId(virtualNode1.getNodeId()) + .setDestPortId(virtualPort.getPortId()) + .setBandwidth(0L) + .build(); + virtualLinks.add(virtualLink); + + virtualLink = new VirtualLinkBuilder() + .setLinkId(new VirtualLinkId(UUID.randomUUID().toString())) + .setSrcNodeId(virtualNode1.getNodeId()) + .setSrcPortId(virtualPort.getPortId()) + .setDestNodeId(destinationVirtualNode.getNodeId()) + .setDestPortId(virtualPort1.getPortId()) + .setBandwidth(0L) + .build(); + virtualLinks.add(virtualLink); + } + + virtualLinks1 = new ArrayList(1); + virtualLink1 = new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.path.instance.VirtualLinkBuilder() + .setLinkId(virtualLink.getLinkId()) + .setOrder(0L) + .build(); + virtualLinks1.add(virtualLink1); + + virtualPath = new VirtualPathBuilder() + .setPathId(new VirtualPathId(UUID.randomUUID().toString())) + .setVirtualLink(virtualLinks1) + .setBandwidth(0L) + .build(); + virtualPaths.add(virtualPath); + + virtualResource = new VirtualResourceBuilder() + .setVirtualResourceId(new VirtualResourceId(UUID.randomUUID().toString())) + .setVirtualResourceType(VirtualResource.VirtualResourceType.Vpath) + .setVirtualResourceEntityId(new VirtualResourceEntityId(virtualPath.getPathId().getValue())) + .setOrder((long) virtualResources.size()) + .build(); + virtualResources.add(virtualResource); + } else { + // TODO + } + } else { + // TODO + } + + IntentVnMappingResult intentVnMappingResult = new IntentVnMappingResultBuilder() + .setIntentId(new IntentId(operation.getOperationId().getValue())) + .setIntentType(IntentVnMappingResult.IntentType.Operation) + .setVirtualResource(virtualResources) + .build(); + + intentVnMappingResults.add(intentVnMappingResult); + } + + return; + } +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/intent/algorithm/Edge.java b/nemo-impl/src/main/java/org/opendaylight/nemo/intent/algorithm/Edge.java new file mode 100644 index 0000000..900264a --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/intent/algorithm/Edge.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.nemo.intent.algorithm; + +/** + * An edge in the network topology. + * + * @author Zhigang Ji + */ +public class Edge { + private String id; + private String src; + private String dest; + private long metric; + private long bandwidth; + + public Edge(String id, String src, String dest, long metric, long bandwidth) { + super(); + + this.id = id; + this.src = src; + this.dest = dest; + this.metric = metric; + this.bandwidth = bandwidth; + + return; + } + + public String getId() { + return id; + } + + public String getSrc() { + return src; + } + + public String getDest() { + return dest; + } + + public long getMetric() { + return metric; + } + + public long getBandwidth() { + return bandwidth; + } + + public void setMetric(long metric) { + this.metric = metric; + + return; + } + + public void setBandwidth(long bandwidth) { + this.bandwidth = bandwidth; + + return; + } + + @Override + public boolean equals(Object obj) { + return ((Edge)obj).getId().equals(id); + } + + @Override + public String toString() { + return "Edge{" + + "id='" + id + '\'' + + ", src='" + src + '\'' + + ", dest='" + dest + '\'' + + ", metric=" + metric + + ", bandwidth=" + bandwidth + + '}'; + } +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/intent/algorithm/RoutingAlgorithm.java b/nemo-impl/src/main/java/org/opendaylight/nemo/intent/algorithm/RoutingAlgorithm.java new file mode 100644 index 0000000..86a0299 --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/intent/algorithm/RoutingAlgorithm.java @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.nemo.intent.algorithm; + +import edu.uci.ics.jung.algorithms.filters.EdgePredicateFilter; +import edu.uci.ics.jung.algorithms.shortestpath.DijkstraShortestPath; +import edu.uci.ics.jung.graph.DirectedSparseGraph; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.EdgeType; +import org.apache.commons.collections15.Predicate; +import org.apache.commons.collections15.Transformer; + +import java.util.Collection; +import java.util.List; + +/** + * Implement the SPF and CSPF algorithms based on the Dijkstra's algorithm. + * + * @author Zhigang Ji + */ +public class RoutingAlgorithm { + /** + * The current network topology graph. + */ + private Graph graph; + + /** + * The Dijkstra shortest path algorithm instance. + */ + private DijkstraShortestPath dijkstraShortestPath; + + public RoutingAlgorithm() { + super(); + + graph = new DirectedSparseGraph(); + dijkstraShortestPath = new DijkstraShortestPath(graph, new Transformer() { + @Override + public Number transform(Edge edge) { + return edge.getMetric(); + } + }, false); + + return; + } + + /** + * Get the vertex with the given id from the network topology graph. + * + * @param vertexId The given vertex id. + * @return The vertex with the given id. + */ + public Vertex getVertex(String vertexId) { + for ( Vertex vertex : graph.getVertices() ) { + if ( vertex.getId().equals(vertexId) ) { + return vertex; + } + } + + return null; + } + + /** + * Get the edge with the given id from the network topology graph. + * + * @param edgeId The given edge id. + * @return The edge with the given id. + */ + public Edge getEdge(String edgeId) { + for ( Edge edge : graph.getEdges() ) { + if ( edge.getId().equals(edgeId) ) { + return edge; + } + } + + return null; + } + + /** + * Get all vertices from the network topology graph. + * + * @return The collection of all vertices. + */ + public Collection getVertices() { + return graph.getVertices(); + } + + /** + * Add a vertex into the network topology graph. + * + * @param vertex The vertex to be added. + */ + public void addVertex(Vertex vertex) { + graph.addVertex(vertex); + + return; + } + + /** + * Add an edge into the network topology graph. + * + * @param edge The edge to be added. + */ + public void addEdge(Edge edge) { + graph.addEdge(edge, getVertex(edge.getSrc()), getVertex(edge.getDest()), EdgeType.DIRECTED); + + return; + } + + /** + * Update an edge in the network topology graph with the new one. + * + * @param newEdge The given new edge. + */ + public void updateEdge(Edge newEdge) { + Edge edge = getEdge(newEdge.getId()); + + edge.setMetric(newEdge.getMetric()); + edge.setBandwidth(newEdge.getBandwidth()); + + return; + } + + /** + * Remove the vertex with the given id from the network topology graph. + * + * @param vertexId The given vertex id. + */ + public void removeVertex(String vertexId) { + Vertex vertex = getVertex(vertexId); + + if ( null != vertex ) { + graph.removeVertex(vertex); + } + + return; + } + + /** + * Remove the edge with the given id from the network topology graph. + * + * @param edgeId The given edge id. + */ + public void removeEdge(String edgeId) { + Edge edge = getEdge(edgeId); + + if ( null != edge ) { + graph.removeEdge(edge); + } + + return; + } + + /** + * Compute a shortest path from the given source vertex to target + * one without any constraint. + * + * @param source The given source vertex. + * @param target The given target vertex. + * @return A list of the edges on the shortest path, in order of + * their occurrence on this path. + */ + public List computePath(Vertex source, Vertex target) { + return dijkstraShortestPath.getPath(source, target); + } + + /** + * Compute a shortest path with the given bandwidth from the given + * source vertex to target one. + * + * @param source The given source vertex. + * @param target The given target vertex. + * @param bandwidth The given bandwidth for the path. + * @return A list of the edges on the shortest path, in order of + * their occurrence on this path. + */ + public List computePath(Vertex source, Vertex target, final long bandwidth) { + EdgePredicateFilter edgeEdgePredicateFilter = new EdgePredicateFilter(new Predicate() { + @Override + public boolean evaluate(Edge edge) { + return edge.getBandwidth() >= bandwidth; + } + }); + + Graph filteredGraph = edgeEdgePredicateFilter.transform(graph); + DijkstraShortestPath tempDijkstraShortestPath = new DijkstraShortestPath(filteredGraph, new Transformer() { + @Override + public Number transform(Edge edge) { + return edge.getMetric(); + } + }, false); + + return tempDijkstraShortestPath.getPath(source, target); + } + + @Override + public String toString() { + return "RoutingAlgorithm{" + + "vertices=" + graph.getVertices() + + ", edges=" + graph.getEdges() + + '}'; + } +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/intent/algorithm/Vertex.java b/nemo-impl/src/main/java/org/opendaylight/nemo/intent/algorithm/Vertex.java new file mode 100644 index 0000000..af5b9a6 --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/intent/algorithm/Vertex.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.nemo.intent.algorithm; + +/** + * A vertex in the network topology. + * + * @author Zhigang Ji + */ +public class Vertex { + private String id; + + public Vertex(String id) { + super(); + + this.id = id; + + return; + } + + public String getId() { + return id; + } + + @Override + public boolean equals(Object obj) { + return ((Vertex)obj).getId().equals(id); + } + + @Override + public String toString() { + return "Vertex{" + + "id='" + id + '\'' + + '}'; + } +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/intent/computation/PNComputationUnit.java b/nemo-impl/src/main/java/org/opendaylight/nemo/intent/computation/PNComputationUnit.java new file mode 100644 index 0000000..371f8d8 --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/intent/computation/PNComputationUnit.java @@ -0,0 +1,435 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.nemo.intent.computation; + +import com.google.common.base.Optional; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; +import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.nemo.intent.algorithm.Edge; +import org.opendaylight.nemo.intent.algorithm.RoutingAlgorithm; +import org.opendaylight.nemo.intent.algorithm.Vertex; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.PhysicalNetwork; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.PhysicalLinks; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.PhysicalNodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.PhysicalPaths; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.links.PhysicalLink; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.nodes.PhysicalNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.paths.PhysicalPath; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.paths.PhysicalPathBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.path.instance.PhysicalLinkBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.common.rev151010.PhysicalLinkId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.common.rev151010.PhysicalNodeId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.common.rev151010.PhysicalPathId; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; +import java.util.concurrent.ExecutionException; + +/** + * The physical network computation unit implements the following functions: + * (1) Maintain the underlying physical network topology information through + * subscribing from the data store. + * (2) Provide the tunnel computation with SLA constraints to the virtual + * network mapping computation unit. + * + * @author Zhigang Ji + */ +public class PNComputationUnit implements AutoCloseable { + private static final Logger LOG = LoggerFactory.getLogger(PNComputationUnit.class); + + private final DataBroker dataBroker; + + /** + * The routing algorithm instance. + */ + private RoutingAlgorithm routingAlgorithm; + + /** + * The registration for the physical node change listener. + */ + private ListenerRegistration physicalNodeChangeListenerReg; + + /** + * The registration for the physical link change listener. + */ + private ListenerRegistration physicalLinkChangeListenerReg; + + /** + * The registration for the physical path change listener. + */ + private ListenerRegistration physicalPathChangeListenerReg; + + public PNComputationUnit(DataBroker dataBroker) { + super(); + + this.dataBroker = dataBroker; + routingAlgorithm = new RoutingAlgorithm(); + + InstanceIdentifier physicalNodeIid = InstanceIdentifier + .builder(PhysicalNetwork.class) + .child(PhysicalNodes.class) + .child(PhysicalNode.class) + .build(); + InstanceIdentifier physicalLinkIid = InstanceIdentifier + .builder(PhysicalNetwork.class) + .child(PhysicalLinks.class) + .child(PhysicalLink.class) + .build(); + InstanceIdentifier physicalPathIid = InstanceIdentifier + .builder(PhysicalNetwork.class) + .child(PhysicalPaths.class) + .child(PhysicalPath.class) + .build(); + + physicalNodeChangeListenerReg = dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, + physicalNodeIid, new PhysicalNodeChangeListener(), DataChangeScope.BASE); + physicalLinkChangeListenerReg = dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, + physicalLinkIid, new PhysicalLinkChangeListener(), DataChangeScope.BASE); + physicalPathChangeListenerReg = dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, + physicalPathIid, new PhysicalPathChangeListener(), DataChangeScope.BASE); + + ReadOnlyTransaction readOnlyTransaction = dataBroker.newReadOnlyTransaction(); + + InstanceIdentifier physicalNodesIid = InstanceIdentifier + .builder(PhysicalNetwork.class) + .child(PhysicalNodes.class) + .build(); + Optional result; + + try { + result = readOnlyTransaction.read(LogicalDatastoreType.OPERATIONAL, physicalNodesIid).get(); + } catch ( InterruptedException | ExecutionException exception ) { + throw new RuntimeException("Can not read the physical nodes."); + } + + if ( result.isPresent() ) { + PhysicalNodes physicalNodes = result.get(); + Vertex vertex; + + for ( PhysicalNode physicalNode : physicalNodes.getPhysicalNode() ) { + vertex = new Vertex(physicalNode.getNodeId().getValue()); + routingAlgorithm.addVertex(vertex); + } + } + + InstanceIdentifier physicalLinksIid = InstanceIdentifier + .builder(PhysicalNetwork.class) + .child(PhysicalLinks.class) + .build(); + Optional result1; + + try { + result1 = readOnlyTransaction.read(LogicalDatastoreType.OPERATIONAL, physicalLinksIid).get(); + } catch ( InterruptedException | ExecutionException exception ) { + throw new RuntimeException("Can not read the physical links."); + } + + if ( result1.isPresent() ) { + PhysicalLinks physicalLinks = result1.get(); + Edge edge; + + for ( PhysicalLink physicalLink : physicalLinks.getPhysicalLink() ) { + edge = new Edge(physicalLink.getLinkId().getValue(), physicalLink.getSrcNodeId().getValue(), + physicalLink.getDestNodeId().getValue(), physicalLink.getMetric(), + physicalLink.getBandwidth()); + routingAlgorithm.addEdge(edge); + } + } + + LOG.debug("Initialized the physical network computation unit."); + + return; + } + + /** + * Compute a shortest physical path from the given source vertex to + * target one without any constraint. + * + * @param source The given source physical node id. + * @param target The given target physical node id. + * @return The physical path if successful,or null otherwise. + */ + protected PhysicalPath computePath(PhysicalNodeId source, PhysicalNodeId target) { + List edges = routingAlgorithm.computePath(routingAlgorithm.getVertex(source.getValue()), + routingAlgorithm.getVertex(target.getValue())); + + if ( null == edges || edges.isEmpty() ) { + return null; + } + + List physicalLinks = + new ArrayList(edges.size()); + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.path.instance.PhysicalLink physicalLink; + long metric = 0; + long delay = 0; + + for ( Edge edge : edges ) { + physicalLink = new PhysicalLinkBuilder() + .setLinkId(new PhysicalLinkId(edge.getId())) + .setOrder((long) physicalLinks.size()) + .build(); + physicalLinks.add(physicalLink); + + metric += edge.getMetric(); +// delay += edge.getDelay(); + } + + PhysicalPath physicalPath = new PhysicalPathBuilder() + .setPathId(new PhysicalPathId(UUID.randomUUID().toString())) + .setPhysicalLink(physicalLinks) + .setMetric(metric) + .setBandwidth(0L) + .setDelay(delay) + .build(); + + return physicalPath; + } + + /** + * Compute a shortest physical path with the given bandwidth from the + * given source vertex to target one. + * + * @param source The given source physical node id. + * @param target The given target physical node id. + * @param bandwidth The given bandwidth for the physical path. + * @return The physical path if successful,or null otherwise. + */ + protected PhysicalPath computePath(PhysicalNodeId source, PhysicalNodeId target, long bandwidth) { + List edges = routingAlgorithm.computePath(routingAlgorithm.getVertex(source.getValue()), + routingAlgorithm.getVertex(target.getValue()), bandwidth); + + if ( null == edges || edges.isEmpty() ) { + return null; + } + + List physicalLinks = + new ArrayList(edges.size()); + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.path.instance.PhysicalLink physicalLink; + long metric = 0; + long delay = 0; + + for ( Edge edge : edges ) { + edge.setBandwidth(edge.getBandwidth() - bandwidth); + routingAlgorithm.updateEdge(edge); + + physicalLink = new PhysicalLinkBuilder() + .setLinkId(new PhysicalLinkId(edge.getId())) + .setOrder((long) physicalLinks.size()) + .build(); + physicalLinks.add(physicalLink); + + metric += edge.getMetric(); +// delay += edge.getDelay(); + } + + PhysicalPath physicalPath = new PhysicalPathBuilder() + .setPathId(new PhysicalPathId(UUID.randomUUID().toString())) + .setPhysicalLink(physicalLinks) + .setMetric(metric) + .setBandwidth(bandwidth) + .setDelay(delay) + .build(); + + return physicalPath; + } + + @Override + public void close() throws Exception { + if ( null != physicalNodeChangeListenerReg ) { + physicalNodeChangeListenerReg.close(); + } + + if ( null != physicalLinkChangeListenerReg ) { + physicalLinkChangeListenerReg.close(); + } + + if ( null != physicalPathChangeListenerReg ) { + physicalPathChangeListenerReg.close(); + } + + return; + } + + /** + * A listener to change events related to physical nodes being + * added, removed or updated. + * + * @author Zhigang Ji + */ + private class PhysicalNodeChangeListener implements DataChangeListener { + @Override + public void onDataChanged(AsyncDataChangeEvent, DataObject> change) { + if ( null == change ) { + return; + } + + Map, DataObject> createdData = change.getCreatedData(); + + if ( null != createdData && !createdData.isEmpty() ) { + PhysicalNode physicalNode; + Vertex vertex; + + for ( DataObject dataObject : createdData.values() ) { + if ( dataObject instanceof PhysicalNode ) { + physicalNode = (PhysicalNode)dataObject; + vertex = new Vertex(physicalNode.getNodeId().getValue()); + + routingAlgorithm.addVertex(vertex); + } + } + } + + Map, DataObject> originalData = change.getOriginalData(); + Set> removedPaths = change.getRemovedPaths(); + + if ( null != removedPaths && !removedPaths.isEmpty() ) { + DataObject dataObject; + + for ( InstanceIdentifier instanceId : removedPaths ) { + dataObject = originalData.get(instanceId); + + if ( null != dataObject && dataObject instanceof PhysicalNode ) { + routingAlgorithm.removeVertex(((PhysicalNode)dataObject).getNodeId().getValue()); + } + } + } + + return; + } + } + + /** + * A listener to change events related to physical links being + * added, removed or updated. + * + * @author Zhigang Ji + */ + private class PhysicalLinkChangeListener implements DataChangeListener { + @Override + public void onDataChanged(AsyncDataChangeEvent, DataObject> change) { + if ( null == change ) { + return; + } + + Map, DataObject> createdData = change.getCreatedData(); + + if ( null != createdData && !createdData.isEmpty() ) { + PhysicalLink physicalLink; + Edge edge; + + for ( DataObject dataObject : createdData.values() ) { + if ( dataObject instanceof PhysicalLink ) { + physicalLink = (PhysicalLink)dataObject; + edge = new Edge(physicalLink.getLinkId().getValue(), physicalLink.getSrcNodeId().getValue(), + physicalLink.getDestNodeId().getValue(), physicalLink.getMetric(), + physicalLink.getBandwidth()); + + routingAlgorithm.addEdge(edge); + } + } + } + + Map, DataObject> updatedData = change.getUpdatedData(); + + if ( null != updatedData && !updatedData.isEmpty() ) { + PhysicalLink physicalLink; + Edge edge; + + for ( DataObject dataObject : updatedData.values() ) { + if ( dataObject instanceof PhysicalLink ) { + physicalLink = (PhysicalLink)dataObject; + edge = new Edge(physicalLink.getLinkId().getValue(), physicalLink.getSrcNodeId().getValue(), + physicalLink.getDestNodeId().getValue(), physicalLink.getMetric(), + physicalLink.getBandwidth()); + + routingAlgorithm.updateEdge(edge); + } + } + } + + Map, DataObject> originalData = change.getOriginalData(); + Set> removedPaths = change.getRemovedPaths(); + + if ( null != removedPaths && !removedPaths.isEmpty() ) { + DataObject dataObject; + + for ( InstanceIdentifier instanceId : removedPaths ) { + dataObject = originalData.get(instanceId); + + if ( null != dataObject && dataObject instanceof PhysicalLink ) { + routingAlgorithm.removeEdge(((PhysicalLink)dataObject).getLinkId().getValue()); + } + } + } + + return; + } + } + + /** + * A listener to change events related to physical paths being + * added, removed or updated. + * + * @author Zhigang Ji + */ + private class PhysicalPathChangeListener implements DataChangeListener { + @Override + public void onDataChanged(AsyncDataChangeEvent, DataObject> change) { + if ( null == change ) { + return; + } + + Map, DataObject> originalData = change.getOriginalData(); + Set> removedPaths = change.getRemovedPaths(); + + if ( null != removedPaths && !removedPaths.isEmpty() ) { + DataObject dataObject; + PhysicalPath physicalPath; + long bandwidth; + List physicalLinks; + Edge edge; + + for ( InstanceIdentifier instanceId : removedPaths ) { + dataObject = originalData.get(instanceId); + + if ( null != dataObject && dataObject instanceof PhysicalPath ) { + physicalPath = (PhysicalPath)dataObject; + bandwidth = physicalPath.getBandwidth(); + + if ( 0 < bandwidth ) { + physicalLinks = physicalPath.getPhysicalLink(); + + if ( null != physicalLinks && !physicalLinks.isEmpty() ) { + for ( org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.path.instance.PhysicalLink + physicalLink : physicalLinks ) { + edge = routingAlgorithm.getEdge(physicalLink.getLinkId().getValue()); + + if ( null != edge ) { + edge.setBandwidth(edge.getBandwidth() + bandwidth); + routingAlgorithm.updateEdge(edge); + } + } + } + } + } + } + } + + return; + } + } +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/intent/computation/VNComputationUnit.java b/nemo-impl/src/main/java/org/opendaylight/nemo/intent/computation/VNComputationUnit.java new file mode 100644 index 0000000..e340cf1 --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/intent/computation/VNComputationUnit.java @@ -0,0 +1,469 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.nemo.intent.computation; + +import com.google.common.base.Optional; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; +import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.nemo.intent.algorithm.Edge; +import org.opendaylight.nemo.intent.algorithm.RoutingAlgorithm; +import org.opendaylight.nemo.intent.algorithm.Vertex; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.VirtualNetworks; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.VirtualNetwork; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.VirtualNetworkKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.VirtualLinks; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.VirtualNodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.VirtualPaths; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.VirtualRoutes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.links.VirtualLink; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.nodes.VirtualNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.paths.VirtualPath; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.paths.VirtualPathBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.paths.VirtualPathKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.routes.VirtualRoute; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.routes.VirtualRouteBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.routes.VirtualRouteKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.path.instance.VirtualLinkBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.UserId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.common.rev151010.VirtualLinkId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.common.rev151010.VirtualNetworkId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.common.rev151010.VirtualNodeId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.common.rev151010.VirtualPathId; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; +import java.util.concurrent.ExecutionException; + +/** + * The virtual network computation unit implements the following functions: + * (1) Maintain a user's virtual network topology information generated in + * terms of the user's intents through subscribing from the data store. + * (2) Automatically recompute all routes of the virtual network when it + * changed, and store or update the routes into the data store. + * (3) Provide the path computation with SLA constraints to any other modules + * that need it. + * + * @author Zhigang Ji + */ +public class VNComputationUnit implements AutoCloseable { + private static final Logger LOG = LoggerFactory.getLogger(VNComputationUnit.class); + + private final DataBroker dataBroker; + + /** + * The user id for the virtual network maintained by + * this computation unit. + */ + private UserId userId; + + /** + * The routing algorithm instance. + */ + private RoutingAlgorithm routingAlgorithm; + + /** + * The virtual routers in the virtual network. + */ + private Set virtualRouters; + + /** + * The registration for the virtual node change listener. + */ + private ListenerRegistration virtualNodeChangeListenerReg; + + /** + * The registration for the virtual link change listener. + */ + private ListenerRegistration virtualLinkChangeListenerReg; + + public VNComputationUnit(DataBroker dataBroker, UserId userId) { + super(); + + this.dataBroker = dataBroker; + this.userId = userId; + routingAlgorithm = new RoutingAlgorithm(); + virtualRouters = new HashSet(); + + VirtualNetworkKey virtualNetworkKey = new VirtualNetworkKey(new VirtualNetworkId(userId.getValue())); + InstanceIdentifier virtualNodeIid = InstanceIdentifier + .builder(VirtualNetworks.class) + .child(VirtualNetwork.class, virtualNetworkKey) + .child(VirtualNodes.class) + .child(VirtualNode.class) + .build(); + InstanceIdentifier virtualLinkIid = InstanceIdentifier + .builder(VirtualNetworks.class) + .child(VirtualNetwork.class, virtualNetworkKey) + .child(VirtualLinks.class) + .child(VirtualLink.class) + .build(); + + virtualNodeChangeListenerReg = dataBroker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION, + virtualNodeIid, new VirtualNodeChangeListener(), DataChangeScope.BASE); + virtualLinkChangeListenerReg = dataBroker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION, + virtualLinkIid, new VirtualLinkChangeListener(), DataChangeScope.BASE); + + LOG.debug("Initialized the virtual network computation unit for the user {}.", userId.getValue()); + + return; + } + + public VNComputationUnit(DataBroker dataBroker, VirtualNetwork virtualNetwork) { + super(); + + this.dataBroker = dataBroker; + userId = virtualNetwork.getUserId(); + routingAlgorithm = new RoutingAlgorithm(); + virtualRouters = new HashSet(); + + List virtualNodes = virtualNetwork.getVirtualNodes().getVirtualNode(); + Vertex vertex; + + for ( VirtualNode virtualNode : virtualNodes ) { + vertex = new Vertex(virtualNode.getNodeId().getValue()); + routingAlgorithm.addVertex(vertex); + + if ( VirtualNode.NodeType.Vrouter == virtualNode.getNodeType() ) { + virtualRouters.add(virtualNode.getNodeId()); + } + } + + List virtualLinks = virtualNetwork.getVirtualLinks().getVirtualLink(); + Edge edge; + + for ( VirtualLink virtualLink : virtualLinks ) { + edge = new Edge(virtualLink.getLinkId().getValue(), virtualLink.getSrcNodeId().getValue(), + virtualLink.getDestNodeId().getValue(), virtualLink.getMetric(), + virtualLink.getBandwidth()); + routingAlgorithm.addEdge(edge); + } + +// computeRoute(virtualNetwork); + + return; + } + + /** + * Compute a shortest virtual path from the given source vertex to + * target one without any constraint. + * + * @param source The given source virtual node id. + * @param target The given target virtual node id. + * @return The virtual path if successful,or null otherwise. + */ + public VirtualPath computePath(VirtualNodeId source, VirtualNodeId target) { + List edges = routingAlgorithm.computePath(routingAlgorithm.getVertex(source.getValue()), + routingAlgorithm.getVertex(target.getValue())); + + if ( null == edges || edges.isEmpty() ) { + return null; + } + + List virtualLinks = + new ArrayList(edges.size()); + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.path.instance.VirtualLink virtualLink; + long metric = 0; + long delay = 0; + + for ( Edge edge : edges ) { + virtualLink = new VirtualLinkBuilder() + .setLinkId(new VirtualLinkId(edge.getId())) + .setOrder((long) virtualLinks.size()) + .build(); + virtualLinks.add(virtualLink); + + metric += edge.getMetric(); +// delay += edge.getDelay(); + } + + VirtualPath virtualPath = new VirtualPathBuilder() + .setPathId(new VirtualPathId(UUID.randomUUID().toString())) + .setVirtualLink(virtualLinks) + .setMetric(metric) + .setBandwidth(0L) + .setDelay(delay) + .build(); + + return virtualPath; + } + + /** + * Compute a shortest virtual path with the given bandwidth from the + * given source vertex to target one. + * + * @param source The given source virtual node id. + * @param target The given target virtual node id. + * @param bandwidth The given bandwidth for the virtual path. + * @return The virtual path if successful,or null otherwise. + */ + public VirtualPath computePath(VirtualNodeId source, VirtualNodeId target, long bandwidth) { + List edges = routingAlgorithm.computePath(routingAlgorithm.getVertex(source.getValue()), + routingAlgorithm.getVertex(target.getValue()), bandwidth); + + if ( null == edges || edges.isEmpty() ) { + return null; + } + + List virtualLinks = + new ArrayList(edges.size()); + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.path.instance.VirtualLink virtualLink; + long metric = 0; + long delay = 0; + + for ( Edge edge : edges ) { + edge.setBandwidth(edge.getBandwidth() - bandwidth); + routingAlgorithm.updateEdge(edge); + + virtualLink = new VirtualLinkBuilder() + .setLinkId(new VirtualLinkId(edge.getId())) + .setOrder((long)virtualLinks.size()) + .build(); + virtualLinks.add(virtualLink); + + metric += edge.getMetric(); +// delay += edge.getDelay(); + } + + VirtualPath virtualPath = new VirtualPathBuilder() + .setPathId(new VirtualPathId(UUID.randomUUID().toString())) + .setVirtualLink(virtualLinks) + .setMetric(metric) + .setBandwidth(bandwidth) + .setDelay(delay) + .build(); + + return virtualPath; + } + + @Override + public void close() throws Exception { + if ( null != virtualNodeChangeListenerReg ) { + virtualNodeChangeListenerReg.close(); + } + + if ( null != virtualLinkChangeListenerReg ) { + virtualLinkChangeListenerReg.close(); + } + + return; + } + + /** + * Compute the routes between all virtual routers in the virtual + * network, and store or update them into the data store. + */ + private void computeRoute() { + Map routes = new HashMap(); + VirtualPath virtualPath; + + for ( VirtualNodeId source : virtualRouters ) { + for ( VirtualNodeId target : virtualRouters ) { + if ( !source.equals(target) ) { + virtualPath = computePath(source, target); + + if ( null == virtualPath ) { + continue; + } + + routes.put(new VirtualRouteKey(source, target), virtualPath); + } + } + } + + updateRoute(routes); + + return; + } + + /** + * Compute the routes between all virtual routers in the virtual + * network, and store them into the virtual network. + * + * @param virtualNetwork The virtual network to store the routes. + */ + private void computeRoute(VirtualNetwork virtualNetwork) { + List virtualRoutes = virtualNetwork.getVirtualRoutes().getVirtualRoute(); + List virtualPaths = virtualNetwork.getVirtualPaths().getVirtualPath(); + VirtualRoute virtualRoute; + VirtualPath virtualPath; + + for ( VirtualNodeId source : virtualRouters ) { + for ( VirtualNodeId target : virtualRouters ) { + if ( !source.equals(target) ) { + virtualPath = computePath(source, target); + + if ( null == virtualPath ) { + continue; + } + + virtualRoute = new VirtualRouteBuilder().setSrcNodeId(source) + .setDestNodeId(target) + .setPathId(virtualPath.getPathId()) + .build(); + + virtualPaths.add(virtualPath); + virtualRoutes.add(virtualRoute); + } + } + } + + return; + } + + /** + * Update the given routes into the data store. If the route + * already exists, remove it's old virtual path and store the + * given new one into the data store. + * + * @param routes The given routes to be updated. + */ + private void updateRoute(Map routes) { + ReadWriteTransaction readWriteTransaction = dataBroker.newReadWriteTransaction(); + + VirtualNetworkKey virtualNetworkKey = new VirtualNetworkKey(new VirtualNetworkId(userId.getValue())); + InstanceIdentifier virtualRouteIid; + InstanceIdentifier virtualPathIid; + Optional result; + VirtualRoute virtualRoute; + + for ( Map.Entry route : routes.entrySet() ) { + virtualRouteIid = InstanceIdentifier.builder(VirtualNetworks.class) + .child(VirtualNetwork.class, virtualNetworkKey) + .child(VirtualRoutes.class) + .child(VirtualRoute.class, route.getKey()) + .build(); + + try { + result = readWriteTransaction.read(LogicalDatastoreType.CONFIGURATION, virtualRouteIid).get(); + } catch ( InterruptedException | ExecutionException exception ) { + LOG.error("Can not read the virtual route from the virtual node {} to {}.", + route.getKey().getSrcNodeId().getValue(), route.getKey().getDestNodeId().getValue()); + + continue; + } + + if ( result.isPresent() ) { + virtualRoute = result.get(); + virtualPathIid = InstanceIdentifier.builder(VirtualNetworks.class) + .child(VirtualNetwork.class, virtualNetworkKey) + .child(VirtualPaths.class) + .child(VirtualPath.class, new VirtualPathKey(virtualRoute.getPathId())) + .build(); + readWriteTransaction.delete(LogicalDatastoreType.CONFIGURATION, virtualPathIid); + } + + virtualPathIid = InstanceIdentifier.builder(VirtualNetworks.class) + .child(VirtualNetwork.class, virtualNetworkKey) + .child(VirtualPaths.class) + .child(VirtualPath.class, route.getValue().getKey()) + .build(); + readWriteTransaction.put(LogicalDatastoreType.CONFIGURATION, virtualPathIid, route.getValue(), true); + + virtualRoute = new VirtualRouteBuilder().setSrcNodeId(route.getKey().getSrcNodeId()) + .setDestNodeId(route.getKey().getDestNodeId()) + .setPathId(route.getValue().getPathId()) + .build(); + readWriteTransaction.put(LogicalDatastoreType.CONFIGURATION, virtualRouteIid, virtualRoute, true); + } + + readWriteTransaction.submit(); + + return; + } + + /** + * A listener to change events related to virtual nodes being + * added, removed or updated. + * + * @author Zhigang Ji + */ + private class VirtualNodeChangeListener implements DataChangeListener { + @Override + public void onDataChanged(AsyncDataChangeEvent, DataObject> change) { + if ( null == change ) { + return; + } + + Map, DataObject> createdData = change.getCreatedData(); + + if ( null != createdData && !createdData.isEmpty() ) { + VirtualNode virtualNode; + Vertex vertex; + + for ( DataObject dataObject : createdData.values() ) { + if ( dataObject instanceof VirtualNode ) { + virtualNode = (VirtualNode)dataObject; + vertex = new Vertex(virtualNode.getNodeId().getValue()); + + routingAlgorithm.addVertex(vertex); + + if ( VirtualNode.NodeType.Vrouter == virtualNode.getNodeType() ) { + virtualRouters.add(virtualNode.getNodeId()); + } + } + } + } + + return; + } + } + + /** + * A listener to change events related to virtual links being + * added, removed or updated. + * + * @author Zhigang Ji + */ + private class VirtualLinkChangeListener implements DataChangeListener { + @Override + public void onDataChanged(AsyncDataChangeEvent, DataObject> change) { + if ( null == change ) { + return; + } + + Map, DataObject> createdData = change.getCreatedData(); + + if ( null != createdData && !createdData.isEmpty() ) { + VirtualLink virtualLink; + Edge edge; + boolean needRerouting = false; + + for ( DataObject dataObject : createdData.values() ) { + if ( dataObject instanceof VirtualLink ) { + virtualLink = (VirtualLink)dataObject; + edge = new Edge(virtualLink.getLinkId().getValue(), virtualLink.getSrcNodeId().getValue(), + virtualLink.getDestNodeId().getValue(), virtualLink.getMetric(), + virtualLink.getBandwidth()); + + routingAlgorithm.addEdge(edge); + + if ( virtualRouters.contains(virtualLink.getSrcNodeId()) + && virtualRouters.contains(virtualLink.getDestNodeId()) ) { + needRerouting = true; + } + } + } + + if ( needRerouting ) { + computeRoute(); + } + } + + return; + } + } +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/intent/computation/VNMappingException.java b/nemo-impl/src/main/java/org/opendaylight/nemo/intent/computation/VNMappingException.java new file mode 100644 index 0000000..e887ef1 --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/intent/computation/VNMappingException.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.nemo.intent.computation; + +/** + * An exception in virtual network mapping. + * + * @author Zhigang Ji + */ +public class VNMappingException extends Exception { + private static final long serialVersionUID = -3854801203901305270L; + + public VNMappingException() { + super(); + + return; + } + + public VNMappingException(String message) { + super(message); + + return; + } + + public VNMappingException(Throwable cause) { + super(cause); + + return; + } + + public VNMappingException(String message, Throwable cause) { + super(message, cause); + + return; + } + + public VNMappingException(String message, Throwable cause, + boolean enableSuppression, + boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + + return; + } +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/intent/computation/VNMappingUnit.java b/nemo-impl/src/main/java/org/opendaylight/nemo/intent/computation/VNMappingUnit.java new file mode 100644 index 0000000..d4655bd --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/intent/computation/VNMappingUnit.java @@ -0,0 +1,1147 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.nemo.intent.computation; + +import com.google.common.base.Optional; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; +import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.PhysicalNetwork; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.PhysicalNodeAttributeDefinitions; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.PhysicalPortAttributeDefinitions; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.attribute.definition.AttributeMatchPatterns; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.attribute.instance.attribute.value.RangeValue; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.PhysicalLinks; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.PhysicalNodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.links.PhysicalLink; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.nodes.PhysicalNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.paths.PhysicalPath; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.paths.PhysicalPathBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.node.attribute.definitions.PhysicalNodeAttributeDefinition; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.node.attribute.definitions.PhysicalNodeAttributeDefinitionKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.node.instance.PhysicalPort; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.port.attribute.definitions.PhysicalPortAttributeDefinition; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.port.attribute.definitions.PhysicalPortAttributeDefinitionKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.port.instance.Attribute; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.VirtualNetwork; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.links.VirtualLink; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.links.VirtualLinkBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.nodes.VirtualNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.node.instance.VirtualPort; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.port.instance.PhysicalResourceRequirement; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.PhysicalResourceInstance; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.VirtualResourceInstance; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.vn.pn.mapping.results.UserVnPnMapping; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.vn.pn.mapping.results.user.vn.pn.mapping.VnPnMappingResult; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.vn.pn.mapping.results.user.vn.pn.mapping.VnPnMappingResultBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.common.rev151010.*; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; +import java.util.concurrent.ExecutionException; + +/** + * The virtual network mapping unit implements the following functions: + * (1) Automatically perform the virtual network mapping when the user's + * virtual network changed, which is subscribed from the data store. + * (2) Automatically perform the remapping for the virtual networks that + * are influenced by the changes of the underlying physical network + * which are also subscribed from the data store. + * + * @author Zhigang Ji + */ +public class VNMappingUnit implements AutoCloseable { + private static final Logger LOG = LoggerFactory.getLogger(VNMappingUnit.class); + + private final DataBroker dataBroker; + + /** + * The physical network computation unit. + */ + private PNComputationUnit pnComputationUnit; + + /** + * The registrations for the physical port change listeners. + */ + private Map>> physicalPortChangeListenerRegs; + + /** + * The registration for the physical node change listener. + */ + private ListenerRegistration physicalNodeChangeListenerReg; + + /** + * The registration for the physical link change listener. + */ + private ListenerRegistration physicalLinkChangeListenerReg; + + public VNMappingUnit(DataBroker dataBroker, PNComputationUnit pnComputationUnit) { + super(); + + this.dataBroker = dataBroker; + this.pnComputationUnit = pnComputationUnit; + + physicalPortChangeListenerRegs = + new HashMap>>(); + + InstanceIdentifier physicalNodeIid = InstanceIdentifier + .builder(PhysicalNetwork.class) + .child(PhysicalNodes.class) + .child(PhysicalNode.class) + .build(); + InstanceIdentifier physicalLinkIid = InstanceIdentifier + .builder(PhysicalNetwork.class) + .child(PhysicalLinks.class) + .child(PhysicalLink.class) + .build(); + + physicalNodeChangeListenerReg = dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, + physicalNodeIid, new PhysicalNodeChangeListener(), DataChangeScope.BASE); + physicalLinkChangeListenerReg = dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, + physicalLinkIid, new PhysicalLinkChangeListener(), DataChangeScope.BASE); + + LOG.debug("Initialized the virtual network mapping unit."); + + return; + } + + /** + * TODO + * + * @param virtualNetwork TODO + * @param userVnPnMapping TODO + * @param physicalPaths TODO + */ + public void virtualNetworkMapping(VirtualNetwork virtualNetwork, UserVnPnMapping userVnPnMapping, + List physicalPaths) + throws VNMappingException { + ReadOnlyTransaction readOnlyTransaction = dataBroker.newReadOnlyTransaction(); + + InstanceIdentifier physicalNodesIid = InstanceIdentifier + .builder(PhysicalNetwork.class) + .child(PhysicalNodes.class) + .build(); + Optional result; + + try { + result = readOnlyTransaction.read(LogicalDatastoreType.OPERATIONAL, physicalNodesIid).get(); + } catch ( InterruptedException | ExecutionException exception ) { + throw new VNMappingException("Can not read the physical nodes."); + } + + PhysicalNodes physicalNodes = result.get(); + List physicalNodeList = physicalNodes.getPhysicalNode(); + + List vnPnMappingResults = userVnPnMapping.getVnPnMappingResult(); + List virtualNodes = virtualNetwork.getVirtualNodes().getVirtualNode(); + List virtualPorts; + PhysicalNode physicalNode; + PhysicalPort physicalPort; + VnPnMappingResult vnPnMappingResult; + + for ( VirtualNode virtualNode : virtualNodes ) { + physicalNode = virtualNodeMapping(virtualNetwork.getNetworkId(), virtualNode, physicalNodeList); + + if ( null == physicalNode ) { + throw new VNMappingException("Failed mapping for the virtual node " + + virtualNode.getNodeId().getValue() + " in the virtual network " + + virtualNetwork.getNetworkId().getValue()); + } + + virtualPorts = virtualNode.getVirtualPort(); + + for ( VirtualPort virtualPort : virtualPorts ) { + if ( VirtualPort.PortType.External == virtualPort.getPortType() ) { + physicalPort = virtualPortMapping(virtualNetwork.getNetworkId(), + virtualNode.getNodeId(), virtualPort, physicalNode); + + if ( null == physicalPort ) { + throw new VNMappingException("Failed mapping for the virtual port " + + virtualPort.getPortId().getValue() + " of the virtual node " + + virtualNode.getNodeId().getValue() + " in the virtual network " + + virtualNetwork.getNetworkId().getValue()); + } + + vnPnMappingResult = new VnPnMappingResultBuilder() + .setVirtualResourceId(new VirtualResourceId(UUID.randomUUID().toString())) + .setVirtualResourceType(VirtualResourceInstance.VirtualResourceType.Vport) + .setVirtualResourceEntityId(new VirtualResourceEntityId(virtualPort.getPortId().getValue())) + .setParentVirtualResourceEntityId(new VirtualResourceEntityId(virtualNode.getNodeId().getValue())) + .setPhysicalResourceId(new PhysicalResourceId(UUID.randomUUID().toString())) + .setPhysicalResourceType(PhysicalResourceInstance.PhysicalResourceType.Port) + .setPhysicalResourceEntityId(new PhysicalResourceEntityId(physicalPort.getPortId().getValue())) + .setParentPhysicalResourceEntityId(new PhysicalResourceEntityId(physicalNode.getNodeId().getValue())) + .build(); + + vnPnMappingResults.add(vnPnMappingResult); + } + } + + vnPnMappingResult = new VnPnMappingResultBuilder() + .setVirtualResourceId(new VirtualResourceId(UUID.randomUUID().toString())) + .setVirtualResourceType(VirtualResourceInstance.VirtualResourceType.Vnode) + .setVirtualResourceEntityId(new VirtualResourceEntityId(virtualNode.getNodeId().getValue())) + .setPhysicalResourceId(new PhysicalResourceId(UUID.randomUUID().toString())) + .setPhysicalResourceType(PhysicalResourceInstance.PhysicalResourceType.Node) + .setPhysicalResourceEntityId(new PhysicalResourceEntityId(physicalNode.getNodeId().getValue())) + .build(); + + vnPnMappingResults.add(vnPnMappingResult); + } + + List virtualLinks = virtualNetwork.getVirtualLinks().getVirtualLink(); + List newVirtualLinks = new ArrayList(virtualLinks.size()); + PhysicalPath physicalPath; + VirtualLink newVirtualLink; + + for ( VirtualLink virtualLink : virtualLinks ) { + physicalPath = virtualLinkMapping(virtualNetwork.getNetworkId(), virtualLink, userVnPnMapping); + + if ( null == physicalPath ) { + throw new VNMappingException("Failed mapping for the virtual link " + + virtualLink.getLinkId().getValue() + " in the virtual network " + + virtualNetwork.getNetworkId().getValue()); + } + + physicalPaths.add(physicalPath); + + newVirtualLink = new VirtualLinkBuilder(virtualLink) + .setMetric(physicalPath.getMetric()) + .setDelay(physicalPath.getDelay()) + .build(); + + newVirtualLinks.add(newVirtualLink); + + vnPnMappingResult = new VnPnMappingResultBuilder() + .setVirtualResourceId(new VirtualResourceId(UUID.randomUUID().toString())) + .setVirtualResourceType(VirtualResourceInstance.VirtualResourceType.Vlink) + .setVirtualResourceEntityId(new VirtualResourceEntityId(virtualLink.getLinkId().getValue())) + .setPhysicalResourceId(new PhysicalResourceId(UUID.randomUUID().toString())) + .setPhysicalResourceType(PhysicalResourceInstance.PhysicalResourceType.Path) + .setPhysicalResourceEntityId(new PhysicalResourceEntityId(physicalPath.getPathId().getValue())) + .build(); + + vnPnMappingResults.add(vnPnMappingResult); + } + + virtualLinks.clear(); + virtualLinks.addAll(newVirtualLinks); + + return; + } + + @Override + public void close() throws Exception { + for ( Map> + physicalPortChangeListenerRegs1 : physicalPortChangeListenerRegs.values() ) { + for ( ListenerRegistration + physicalPortChangeListenerReg : physicalPortChangeListenerRegs1.values() ) { + if ( null != physicalPortChangeListenerReg ) { + physicalPortChangeListenerReg.close(); + } + } + } + + if ( null != physicalNodeChangeListenerReg ) { + physicalNodeChangeListenerReg.close(); + } + + if ( null != physicalLinkChangeListenerReg ) { + physicalLinkChangeListenerReg.close(); + } + + return; + } + + /** + * TODO + * + * @param virtualNetworkId TODO + * @param virtualNodeId TODO + * @param virtualPort TODO + * @param physicalNode TODO + * @return TODO + */ + private PhysicalPort virtualPortMapping(VirtualNetworkId virtualNetworkId, VirtualNodeId virtualNodeId, + VirtualPort virtualPort, PhysicalNode physicalNode) + throws VNMappingException { + if ( VirtualPort.PortType.Internal == virtualPort.getPortType() ) { + return null; + } + + List physicalPorts = physicalNode.getPhysicalPort(); + List physicalResourceRequirements = virtualPort.getPhysicalResourceRequirement(); + + for ( PhysicalPort physicalPort : physicalPorts ) { + if ( PhysicalPort.PortType.External == physicalPort.getPortType() + && checkPhysicalPortSatisfied(physicalPort, physicalResourceRequirements) ) { + return physicalPort; + } + } + + return null; + } + + /** + * TODO + * + * @param virtualNetworkId TODO + * @param virtualNode TODO + * @param physicalNodes TODO + * @return TODO + */ + private PhysicalNode virtualNodeMapping(VirtualNetworkId virtualNetworkId, VirtualNode virtualNode, + List physicalNodes) + throws VNMappingException { + List + physicalResourceRequirements = virtualNode.getPhysicalResourceRequirement(); + List candidates = new LinkedList(); + + switch ( virtualNode.getNodeType() ) { + case Vswitch: + for ( PhysicalNode physicalNode : physicalNodes ) { + if ( PhysicalNode.NodeType.Switch == physicalNode.getNodeType() ) { + if ( checkPhysicalNodeSatisfied(physicalNode, physicalResourceRequirements) ) { + candidates.add(physicalNode); + } + } + } + break; + + case Vrouter: + for ( PhysicalNode physicalNode : physicalNodes ) { + if ( PhysicalNode.NodeType.Router == physicalNode.getNodeType() ) { + if ( checkPhysicalNodeSatisfied(physicalNode, physicalResourceRequirements) ) { + candidates.add(physicalNode); + } + } + } + break; + + case Vfirewall: + for ( PhysicalNode physicalNode : physicalNodes ) { + if ( PhysicalNode.NodeType.Firewall == physicalNode.getNodeType() ) { + if ( checkPhysicalNodeSatisfied(physicalNode, physicalResourceRequirements) ) { + candidates.add(physicalNode); + } + } + } + break; + + case Vloadbalancer: + for ( PhysicalNode physicalNode : physicalNodes ) { + if ( PhysicalNode.NodeType.Loadbalancer == physicalNode.getNodeType() ) { + if ( checkPhysicalNodeSatisfied(physicalNode, physicalResourceRequirements) ) { + candidates.add(physicalNode); + } + } + } + break; + + default: + throw new VNMappingException("Unsupported virtual node type " + + virtualNode.getNodeType() + "."); +// break; + } + + if ( candidates.isEmpty() ) { + return null; + } + + return candidates.get(0); + } + + /** + * TODO + * + * @param virtualNetworkId TODO + * @param virtualLink TODO + * @param userVnPnMapping TODO + * @return TODO + */ + private PhysicalPath virtualLinkMapping(VirtualNetworkId virtualNetworkId, VirtualLink virtualLink, + UserVnPnMapping userVnPnMapping) + throws VNMappingException { + List vnPnMappingResults = userVnPnMapping.getVnPnMappingResult(); + VnPnMappingResult vnPnMappingResult = VNMappingUnitUtils.getVnPnMappingResult(vnPnMappingResults, + new VirtualResourceEntityId(virtualLink.getSrcNodeId().getValue())); + + if ( null == vnPnMappingResult ) { + throw new VNMappingException("Can not get the vn-pn mapping result for " + + "the virtual node " + virtualLink.getSrcNodeId().getValue()); + } + + PhysicalNodeId source = new PhysicalNodeId(vnPnMappingResult.getPhysicalResourceEntityId().getValue()); + + vnPnMappingResult = VNMappingUnitUtils.getVnPnMappingResult(vnPnMappingResults, + new VirtualResourceEntityId(virtualLink.getDestNodeId().getValue())); + + if ( null == vnPnMappingResult ) { + throw new VNMappingException("Can not get the vn-pn mapping result for " + + "the virtual node " + virtualLink.getDestNodeId().getValue()); + } + + PhysicalNodeId target = new PhysicalNodeId(vnPnMappingResult.getPhysicalResourceEntityId().getValue()); + + if ( source.equals(target) ) { + PhysicalPath physicalPath = new PhysicalPathBuilder() + .setPathId(new PhysicalPathId(UUID.randomUUID().toString())) + .setPhysicalLink(new ArrayList(0)) + .setMetric(0L) + .setBandwidth(virtualLink.getBandwidth()) + .setDelay(0L) + .build(); + + return physicalPath; + } + + PhysicalPath physicalPath; + + if ( 0 == virtualLink.getBandwidth() ) { + physicalPath = pnComputationUnit.computePath(source, target); + } else { + physicalPath = pnComputationUnit.computePath(source, target, virtualLink.getBandwidth()); + } + + return physicalPath; + } + + /** + * TODO + * + * @param physicalPort TODO + * @param physicalResourceRequirements TODO + * @return TODO + */ + private boolean checkPhysicalPortSatisfied(PhysicalPort physicalPort, + List physicalResourceRequirements) + throws VNMappingException { + List attributes = physicalPort.getAttribute(); + Attribute attribute; + + for ( PhysicalResourceRequirement physicalResourceRequirement : physicalResourceRequirements ) { + attribute = getPhysicalPortAttribute(attributes, physicalResourceRequirement.getAttributeName()); + + if ( null == attribute ) { + return false; + } + + if ( !checkPhysicalPortAttributeSatisfied(attribute, physicalResourceRequirement) ) { + return false; + } + } + + return true; + } + + /** + * TODO + * + * @param physicalNode TODO + * @param physicalResourceRequirements TODO + * @return TODO + */ + private boolean checkPhysicalNodeSatisfied(PhysicalNode physicalNode, + List + physicalResourceRequirements) + throws VNMappingException { + List + attributes = physicalNode.getAttribute(); + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.node.instance.Attribute attribute; + + for ( org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.node.instance.PhysicalResourceRequirement + physicalResourceRequirement : physicalResourceRequirements ) { + attribute = getPhysicalNodeAttribute(attributes, physicalResourceRequirement.getAttributeName()); + + if ( null == attribute ) { + return false; + } + + if ( !checkPhysicalNodeAttributeSatisfied(attribute, physicalResourceRequirement) ) { + return false; + } + } + + return true; + } + + /** + * TODO + * + * @param attributes TODO + * @param attributeName TODO + * @return TODO + */ + private Attribute getPhysicalPortAttribute(List attributes, AttributeName attributeName) { + for ( Attribute attribute : attributes ) { + if ( attribute.getAttributeName().equals(attributeName) ) { + return attribute; + } + } + + return null; + } + + /** + * TODO + * + * @param attributes TODO + * @param attributeName TODO + * @return TODO + */ + private org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.node.instance.Attribute getPhysicalNodeAttribute( + List attributes, + AttributeName attributeName) { + for ( org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.node.instance.Attribute + attribute : attributes ) { + if ( attribute.getAttributeName().equals(attributeName) ) { + return attribute; + } + } + + return null; + } + + /** + * TODO + * + * @param attribute TODO + * @param physicalResourceRequirement TODO + * @return TODO + */ + private boolean checkPhysicalPortAttributeSatisfied(Attribute attribute, + PhysicalResourceRequirement physicalResourceRequirement) + throws VNMappingException { + ReadOnlyTransaction readOnlyTransaction = dataBroker.newReadOnlyTransaction(); + + InstanceIdentifier physicalPortAttributeDefinitionIid = InstanceIdentifier + .builder(PhysicalPortAttributeDefinitions.class) + .child(PhysicalPortAttributeDefinition.class, + new PhysicalPortAttributeDefinitionKey(attribute.getAttributeName())) + .build(); + Optional result; + + try { + result = readOnlyTransaction.read(LogicalDatastoreType.CONFIGURATION, + physicalPortAttributeDefinitionIid).get(); + } catch ( InterruptedException | ExecutionException exception ) { + throw new VNMappingException("Can not read the physical port attribute definition " + + "with attribute name " + attribute.getAttributeName().getValue() + "."); + } + + if ( !result.isPresent() ) { + throw new VNMappingException("The physical port attribute definition with attribute name " + + attribute.getAttributeName().getValue() + " does not exist."); + } + + PhysicalPortAttributeDefinition physicalPortAttributeDefinition = result.get(); + List attributeMatchPatterns + = physicalPortAttributeDefinition.getAttributeMatchPatterns().getAttributeMatchPattern(); + PhysicalResourceRequirement.AttributeMatchPattern attributeMatchPattern + = physicalResourceRequirement.getAttributeMatchPattern(); + + if ( !checkAttributeMatchPatternSpecified(attributeMatchPatterns, attributeMatchPattern) ) { + throw new VNMappingException("The attribute match pattern " + attributeMatchPattern + + " is not specified in the physical port attribute definition " + + "with attribute name " + attribute.getAttributeName().getValue() + "."); + } + + switch ( physicalPortAttributeDefinition.getAttributeValueType() ) { + case String: + return checkAttributeStringValueSatisfied(attribute.getAttributeValue().getStringValue(), + physicalResourceRequirement.getAttributeValue().getStringValue(), attributeMatchPattern); + + case Int: + return checkAttributeIntegerValueSatisfied(attribute.getAttributeValue().getIntValue(), + physicalResourceRequirement.getAttributeValue().getIntValue(), attributeMatchPattern); + + case Range: + return checkAttributeRangeValueSatisfied(attribute.getAttributeValue().getIntValue(), + physicalResourceRequirement.getAttributeValue().getRangeValue(), attributeMatchPattern); + + default: + throw new VNMappingException("Unsupported physical port attribute value type " + + physicalPortAttributeDefinition.getAttributeValueType() + "."); +// break; + } + +// return false; + } + + /** + * TODO + * + * @param attribute TODO + * @param physicalResourceRequirement TODO + * @return TODO + */ + private boolean checkPhysicalNodeAttributeSatisfied( + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.node.instance.Attribute attribute, + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.node.instance.PhysicalResourceRequirement physicalResourceRequirement) + throws VNMappingException { + ReadOnlyTransaction readOnlyTransaction = dataBroker.newReadOnlyTransaction(); + + InstanceIdentifier physicalNodeAttributeDefinitionIid = InstanceIdentifier + .builder(PhysicalNodeAttributeDefinitions.class) + .child(PhysicalNodeAttributeDefinition.class, + new PhysicalNodeAttributeDefinitionKey(attribute.getAttributeName())) + .build(); + Optional result; + + try { + result = readOnlyTransaction.read(LogicalDatastoreType.CONFIGURATION, + physicalNodeAttributeDefinitionIid).get(); + } catch ( InterruptedException | ExecutionException exception ) { + throw new VNMappingException("Can not read the physical node attribute definition " + + "with attribute name " + attribute.getAttributeName().getValue() + "."); + } + + if ( !result.isPresent() ) { + throw new VNMappingException("The physical node attribute definition with attribute name " + + attribute.getAttributeName().getValue() + " does not exist."); + } + + PhysicalNodeAttributeDefinition physicalNodeAttributeDefinition = result.get(); + List attributeMatchPatterns + = physicalNodeAttributeDefinition.getAttributeMatchPatterns().getAttributeMatchPattern(); + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.node.instance.PhysicalResourceRequirement.AttributeMatchPattern + attributeMatchPattern = physicalResourceRequirement.getAttributeMatchPattern(); + + if ( !checkAttributeMatchPatternSpecified(attributeMatchPatterns, attributeMatchPattern) ) { + throw new VNMappingException("The attribute match pattern " + attributeMatchPattern + + " is not specified in the physical node attribute definition " + + "with attribute name " + attribute.getAttributeName().getValue() + "."); + } + + switch ( physicalNodeAttributeDefinition.getAttributeValueType() ) { + case String: + return checkAttributeStringValueSatisfied(attribute.getAttributeValue().getStringValue(), + physicalResourceRequirement.getAttributeValue().getStringValue(), attributeMatchPattern); + + case Int: + return checkAttributeIntegerValueSatisfied(attribute.getAttributeValue().getIntValue(), + physicalResourceRequirement.getAttributeValue().getIntValue(), attributeMatchPattern); + + case Range: + return checkAttributeRangeValueSatisfied(attribute.getAttributeValue().getIntValue(), + physicalResourceRequirement.getAttributeValue().getRangeValue(), attributeMatchPattern); + + default: + throw new VNMappingException("Unsupported physical node attribute value type " + + physicalNodeAttributeDefinition.getAttributeValueType() + "."); +// break; + } + +// return false; + } + + /** + * TODO + * + * @param attributeMatchPatterns TODO + * @param attributeMatchPattern TODO + * @return TODO + */ + private boolean checkAttributeMatchPatternSpecified(List attributeMatchPatterns, + PhysicalResourceRequirement.AttributeMatchPattern attributeMatchPattern) { + for ( AttributeMatchPatterns.AttributeMatchPattern attributeMatchPattern1 : attributeMatchPatterns ) { + if ( attributeMatchPattern1.name().equals(attributeMatchPattern.name()) ) { + return true; + } + } + + return false; + } + + /** + * TODO + * + * @param attributeMatchPatterns TODO + * @param attributeMatchPattern TODO + * @return TODO + */ + private boolean checkAttributeMatchPatternSpecified(List attributeMatchPatterns, + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.node.instance.PhysicalResourceRequirement.AttributeMatchPattern + attributeMatchPattern) { + for ( AttributeMatchPatterns.AttributeMatchPattern attributeMatchPattern1 : attributeMatchPatterns ) { + if ( attributeMatchPattern1.name().equals(attributeMatchPattern.name()) ) { + return true; + } + } + + return false; + } + + /** + * TODO + * + * @param attributeValue TODO + * @param requiredAttributeValue TODO + * @param attributeMatchPattern TODO + * @return TODO + */ + private boolean checkAttributeStringValueSatisfied(String attributeValue, String requiredAttributeValue, + PhysicalResourceRequirement.AttributeMatchPattern attributeMatchPattern) + throws VNMappingException { + int result = attributeValue.compareTo(requiredAttributeValue); + + switch ( attributeMatchPattern ) { + case LessThan: + return 0 > result; + + case NotLessThan: + return 0 <= result; + + case Equal: + return 0 == result; + + case NotEqual: + return 0 != result; + + case GreaterThan: + return 0 < result; + + case NotGreaterThan: + return 0 >= result; + + default: + throw new VNMappingException("Unsupported attribute match pattern " + + attributeMatchPattern + " for the attribute string value."); +// break; + } + +// return false; + } + + /** + * TODO + * + * @param attributeValue TODO + * @param requiredAttributeValue TODO + * @param attributeMatchPattern TODO + * @return TODO + */ + private boolean checkAttributeStringValueSatisfied(String attributeValue, String requiredAttributeValue, + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.node.instance.PhysicalResourceRequirement.AttributeMatchPattern + attributeMatchPattern) + throws VNMappingException { + int result = attributeValue.compareTo(requiredAttributeValue); + + switch ( attributeMatchPattern ) { + case LessThan: + return 0 > result; + + case NotLessThan: + return 0 <= result; + + case Equal: + return 0 == result; + + case NotEqual: + return 0 != result; + + case GreaterThan: + return 0 < result; + + case NotGreaterThan: + return 0 >= result; + + default: + throw new VNMappingException("Unsupported attribute match pattern " + + attributeMatchPattern + " for the attribute string value."); +// break; + } + +// return false; + } + + /** + * TODO + * + * @param attributeValue TODO + * @param requiredAttributeValue TODO + * @param attributeMatchPattern TODO + * @return TODO + */ + private boolean checkAttributeIntegerValueSatisfied(Long attributeValue, Long requiredAttributeValue, + PhysicalResourceRequirement.AttributeMatchPattern attributeMatchPattern) + throws VNMappingException { + int result = attributeValue.compareTo(requiredAttributeValue); + + switch ( attributeMatchPattern ) { + case LessThan: + return 0 > result; + + case NotLessThan: + return 0 <= result; + + case Equal: + return 0 == result; + + case NotEqual: + return 0 != result; + + case GreaterThan: + return 0 < result; + + case NotGreaterThan: + return 0 >= result; + + default: + throw new VNMappingException("Unsupported attribute match pattern " + + attributeMatchPattern + " for the attribute integer value."); +// break; + } + +// return false; + } + + /** + * TODO + * + * @param attributeValue TODO + * @param requiredAttributeValue TODO + * @param attributeMatchPattern TODO + * @return TODO + */ + private boolean checkAttributeIntegerValueSatisfied(Long attributeValue, Long requiredAttributeValue, + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.node.instance.PhysicalResourceRequirement.AttributeMatchPattern + attributeMatchPattern) + throws VNMappingException { + int result = attributeValue.compareTo(requiredAttributeValue); + + switch ( attributeMatchPattern ) { + case LessThan: + return 0 > result; + + case NotLessThan: + return 0 <= result; + + case Equal: + return 0 == result; + + case NotEqual: + return 0 != result; + + case GreaterThan: + return 0 < result; + + case NotGreaterThan: + return 0 >= result; + + default: + throw new VNMappingException("Unsupported attribute match pattern " + + attributeMatchPattern + " for the attribute integer value."); +// break; + } + +// return false; + } + + /** + * TODO + * + * @param attributeValue TODO + * @param requiredAttributeValue TODO + * @param attributeMatchPattern TODO + * @return TODO + */ + private boolean checkAttributeRangeValueSatisfied(Long attributeValue, RangeValue requiredAttributeValue, + PhysicalResourceRequirement.AttributeMatchPattern attributeMatchPattern) + throws VNMappingException { + switch ( attributeMatchPattern ) { + case Between: + return attributeValue > requiredAttributeValue.getMin() + && attributeValue < requiredAttributeValue.getMax(); + + default: + throw new VNMappingException("Unsupported attribute match pattern " + + attributeMatchPattern + " for the attribute range value."); +// break; + } + +// return false; + } + + /** + * TODO + * + * @param attributeValue TODO + * @param requiredAttributeValue TODO + * @param attributeMatchPattern TODO + * @return TODO + */ + private boolean checkAttributeRangeValueSatisfied(Long attributeValue, RangeValue requiredAttributeValue, + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.node.instance.PhysicalResourceRequirement.AttributeMatchPattern + attributeMatchPattern) + throws VNMappingException { + switch ( attributeMatchPattern ) { + case Between: + return attributeValue > requiredAttributeValue.getMin() + && attributeValue < requiredAttributeValue.getMax(); + + default: + throw new VNMappingException("Unsupported attribute match pattern " + + attributeMatchPattern + " for the attribute range value."); +// break; + } + +// return false; + } + +// /** +// * A listener to change events related to virtual ports being +// * added, removed or updated. +// * +// * @author Zhigang Ji +// */ +// private class VirtualPortChangeListener implements DataChangeListener { +// /** +// * The virtual network that the virtual port belongs to. +// */ +// private VirtualNetworkId virtualNetworkId; +// +// /** +// * The virtual node that the virtual port belongs to. +// */ +// private VirtualNodeId virtualNodeId; +// +// public VirtualPortChangeListener(VirtualNetworkId virtualNetworkId, VirtualNodeId virtualNodeId) { +// super(); +// +// this.virtualNetworkId = virtualNetworkId; +// this.virtualNodeId = virtualNodeId; +// +// return; +// } +// +// @Override +// public void onDataChanged(AsyncDataChangeEvent, DataObject> change) { +// if ( null == change ) { +// return; +// } +// +// Map, DataObject> createdData = change.getCreatedData(); +// +// if ( null != createdData && !createdData.isEmpty() ) { +// for ( DataObject dataObject : createdData.values() ) { +// if ( dataObject instanceof VirtualPort ) { +// // TODO: 1、执行端口映射。 +// } +// } +// } +// } +// } +// +// /** +// * A listener to change events related to virtual nodes being +// * added, removed or updated. +// * +// * @author Zhigang Ji +// */ +// private class VirtualNodeChangeListener implements DataChangeListener { +// /** +// * The virtual network that the virtual node belongs to. +// */ +// private VirtualNetworkId virtualNetworkId; +// +// public VirtualNodeChangeListener(VirtualNetworkId virtualNetworkId) { +// super(); +// +// this.virtualNetworkId = virtualNetworkId; +// +// return; +// } +// +// @Override +// public void onDataChanged(AsyncDataChangeEvent, DataObject> change) { +// if ( null == change ) { +// return; +// } +// +// Map, DataObject> createdData = change.getCreatedData(); +// +// if ( null != createdData && !createdData.isEmpty() ) { +// for ( DataObject dataObject : createdData.values() ) { +// if ( dataObject instanceof VirtualNode ) { +// // TODO: 1、执行节点映射。 +// // TODO: 2、启动vports监听(external端口),还需监听vnode中vport的增加。 +// // TODO: 3、读取已有vports,并执行端口映射(external端口)。 +// } +// } +// } +// } +// } +// +// /** +// * A listener to change events related to virtual links being +// * added, removed or updated. +// * +// * @author Zhigang Ji +// */ +// private class VirtualLinkChangeListener implements DataChangeListener { +// /** +// * The virtual network that the virtual link belongs to. +// */ +// private VirtualNetworkId virtualNetworkId; +// +// public VirtualLinkChangeListener(VirtualNetworkId virtualNetworkId) { +// super(); +// +// this.virtualNetworkId = virtualNetworkId; +// +// return; +// } +// +// @Override +// public void onDataChanged(AsyncDataChangeEvent, DataObject> change) { +// if ( null == change ) { +// return; +// } +// +// Map, DataObject> createdData = change.getCreatedData(); +// +// if ( null != createdData && !createdData.isEmpty() ) { +// for ( DataObject dataObject : createdData.values() ) { +// if ( dataObject instanceof VirtualLink ) { +// // TODO: 1、执行链路映射(两端vport映射结果可不写)。 +// } +// } +// } +// } +// } + + /** + * A listener to change events related to physical ports being + * added, removed or updated. + * + * @author Zhigang Ji + */ + private class PhysicalPortChangeListener implements DataChangeListener { + /** + * The physical node that the physical port belongs to. + */ + private PhysicalNodeId physicalNodeId; + + public PhysicalPortChangeListener(PhysicalNodeId physicalNodeId) { + super(); + + this.physicalNodeId = physicalNodeId; + + return; + } + + @Override + public void onDataChanged(AsyncDataChangeEvent, DataObject> change) { + if ( null == change ) { + return; + } + + Map, DataObject> originalData = change.getOriginalData(); + Map, DataObject> updatedData = change.getUpdatedData(); + + if ( null != updatedData && !updatedData.isEmpty() ) { + for ( DataObject dataObject : updatedData.values() ) { + // TODO + } + } + + Set> removedPaths = change.getRemovedPaths(); + + if ( null != removedPaths && !removedPaths.isEmpty() ) { + DataObject dataObject; + + for ( InstanceIdentifier instanceId : removedPaths ) { + dataObject = originalData.get(instanceId); + + // TODO + } + } + } + } + + /** + * A listener to change events related to physical nodes being + * added, removed or updated. + * + * @author Zhigang Ji + */ + private class PhysicalNodeChangeListener implements DataChangeListener { + @Override + public void onDataChanged(AsyncDataChangeEvent, DataObject> change) { + if ( null == change ) { + return; + } + + Map, DataObject> originalData = change.getOriginalData(); + Map, DataObject> updatedData = change.getUpdatedData(); + + if ( null != updatedData && !updatedData.isEmpty() ) { + for ( DataObject dataObject : updatedData.values() ) { + // TODO + } + } + + Set> removedPaths = change.getRemovedPaths(); + + if ( null != removedPaths && !removedPaths.isEmpty() ) { + DataObject dataObject; + + for ( InstanceIdentifier instanceId : removedPaths ) { + dataObject = originalData.get(instanceId); + + // TODO + } + } + } + } + + /** + * A listener to change events related to physical links being + * added, removed or updated. + * + * @author Zhigang Ji + */ + private class PhysicalLinkChangeListener implements DataChangeListener { + @Override + public void onDataChanged(AsyncDataChangeEvent, DataObject> change) { + if ( null == change ) { + return; + } + + Map, DataObject> originalData = change.getOriginalData(); + Map, DataObject> updatedData = change.getUpdatedData(); + + if ( null != updatedData && !updatedData.isEmpty() ) { + for ( DataObject dataObject : updatedData.values() ) { + // TODO + } + } + + Set> removedPaths = change.getRemovedPaths(); + + if ( null != removedPaths && !removedPaths.isEmpty() ) { + DataObject dataObject; + + for ( InstanceIdentifier instanceId : removedPaths ) { + dataObject = originalData.get(instanceId); + + // TODO + } + } + } + } +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/intent/computation/VNMappingUnitUtils.java b/nemo-impl/src/main/java/org/opendaylight/nemo/intent/computation/VNMappingUnitUtils.java new file mode 100644 index 0000000..39bcfae --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/intent/computation/VNMappingUnitUtils.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.nemo.intent.computation; + +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.vn.pn.mapping.results.user.vn.pn.mapping.VnPnMappingResult; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.common.rev151010.VirtualResourceEntityId; + +import java.util.List; + +/** + * Implement the utilities used in the virtual + * network mapping. + * + * @author Zhigang Ji + */ +public class VNMappingUnitUtils { + /** + * TODO + * + * @param vnPnMappingResults TODO + * @param virtualResourceEntityId TODO + * @return TODO + */ + protected static VnPnMappingResult getVnPnMappingResult(List vnPnMappingResults, + VirtualResourceEntityId virtualResourceEntityId) { + for ( VnPnMappingResult vnPnMappingResult : vnPnMappingResults ) { + if ( vnPnMappingResult.getVirtualResourceEntityId().equals(virtualResourceEntityId) ) { + return vnPnMappingResult; + } + } + + return null; + } +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/user/UserManager.java b/nemo-impl/src/main/java/org/opendaylight/nemo/user/UserManager.java new file mode 100644 index 0000000..5e49698 --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/user/UserManager.java @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.nemo.user; + +import com.google.common.util.concurrent.Futures; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RpcRegistration; +import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry; +import org.opendaylight.nemo.intent.IntentResolutionException; +import org.opendaylight.nemo.intent.IntentResolver; +import org.opendaylight.nemo.intent.computation.VNMappingException; +import org.opendaylight.nemo.user.advancedquery.AdvancedQuery; +import org.opendaylight.nemo.user.tenantmanager.AAA; +import org.opendaylight.nemo.user.tenantmanager.RegisterUser; +import org.opendaylight.nemo.user.tenantmanager.TenantManage; +import org.opendaylight.nemo.user.transactionmanager.TransactionBegin; +import org.opendaylight.nemo.user.transactionmanager.TransactionEnd; +import org.opendaylight.nemo.user.vnspacemanager.languagestyle.LanguageIntent; +import org.opendaylight.nemo.user.vnspacemanager.structurestyle.deleteintent.DeleteIntent; +import org.opendaylight.nemo.user.vnspacemanager.structurestyle.updateintent.UpdateIntent; +import org.opendaylight.nemo.user.vnspacemanager.VNSpaceManagement; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.*; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.common.RpcResultBuilder; + +import java.util.concurrent.Future; + +/** + * Created by z00293636 on 2015/9/7. + */ +public class UserManager implements NemoIntentService, AutoCloseable { + + private DataBroker dataBroker; + private RpcProviderRegistry rpcProviderRegistry; + + private VNSpaceManagement vnSpaceManagement; + private RegisterUser registerUser; + private UpdateIntent updateIntent; + private DeleteIntent deleteIntent; + private LanguageIntent languageIntent; + private TenantManage tenantManage; + private AAA aaa; + private TransactionBegin transactionBegin; + private TransactionEnd transactionEnd; + private AdvancedQuery advancedQuery; + private IntentResolver intentResolver; + + Boolean transaction; + Boolean informresolver; + + private RpcRegistration rpcRegistration; + + public UserManager(DataBroker dataBroker, RpcProviderRegistry rpcProviderRegistry, + IntentResolver intentResolver) + { + this.dataBroker = dataBroker; + this.rpcProviderRegistry = rpcProviderRegistry; + + this.intentResolver = intentResolver; + vnSpaceManagement = new VNSpaceManagement(dataBroker); + tenantManage = new TenantManage(dataBroker); + aaa = new AAA(tenantManage); + registerUser = new RegisterUser(tenantManage); + updateIntent = new UpdateIntent(dataBroker,tenantManage); + deleteIntent = new DeleteIntent(dataBroker, tenantManage); + languageIntent = new LanguageIntent(dataBroker); + advancedQuery = new AdvancedQuery(dataBroker, tenantManage); + + transactionBegin = new TransactionBegin(); + transactionEnd = new TransactionEnd(); + + transaction = false; + informresolver = false; + + rpcRegistration = rpcProviderRegistry.addRpcImplementation(NemoIntentService.class, this); + } + @Override + public Future> advancedNemoQuery(AdvancedNemoQueryInput input) { + RpcResult advancedNemoQueryOutputRpcResult = null; + AdvancedNemoQueryOutputBuilder advancedNemoQueryOutputBuilder = new AdvancedNemoQueryOutputBuilder(); + + String errorInfo = advancedQuery.advancedQuery(aaa, input); + if (errorInfo != null) + { + advancedNemoQueryOutputBuilder.setResultCode(CommonRpcResult.ResultCode.Error).setMessage(errorInfo); + } + else + { + advancedNemoQueryOutputBuilder.setResultCode(CommonRpcResult.ResultCode.Ok).setMessage(advancedQuery.getAdvancedQueryReuslt(input)); + } + advancedNemoQueryOutputRpcResult = RpcResultBuilder.success(advancedNemoQueryOutputBuilder.build()).build(); + + return Futures.immediateFuture(advancedNemoQueryOutputRpcResult); + } + + @Override + public Future> beginTransaction(BeginTransactionInput input) { + RpcResult beginTransactionOutputResult = null; + BeginTransactionOutputBuilder beginTransactionOutputBuilder = new BeginTransactionOutputBuilder(); + + if (transaction) + { + beginTransactionOutputBuilder.setResultCode(CommonRpcResult.ResultCode.Error).setMessage("The previous transaction has not been finished."); + } + else + { + String errorInfo = transactionBegin.transactionbegin(aaa,input); + if (errorInfo != null) + { + beginTransactionOutputBuilder.setResultCode(CommonRpcResult.ResultCode.Error).setMessage(errorInfo); + } + else + { + transaction = true; + beginTransactionOutputBuilder.setResultCode(CommonRpcResult.ResultCode.Ok).setMessage("Transaction Begin."); + } + } + beginTransactionOutputResult = RpcResultBuilder.success(beginTransactionOutputBuilder.build()).build(); + return Futures.immediateFuture(beginTransactionOutputResult); + } + + @Override + public Future> endTransaction(EndTransactionInput input) { + RpcResult endTransactionOutputResult = null; + EndTransactionOutputBuilder endTransactionOutputBuilder = new EndTransactionOutputBuilder(); + + if (!transaction) + { + endTransactionOutputBuilder.setResultCode(CommonRpcResult.ResultCode.Error).setMessage("The transaction has not started."); + } + else + { + String errorInfo = transactionEnd.transactionend(aaa,input); + if (errorInfo != null) + { + endTransactionOutputBuilder.setResultCode(CommonRpcResult.ResultCode.Error).setMessage(errorInfo); + } + else + { + transaction = false; + if (informresolver) + { + informresolver = false; + try + { + intentResolver.resolveIntent(input.getUserId()); + endTransactionOutputBuilder.setResultCode(CommonRpcResult.ResultCode.Ok).setMessage("The transaction ends."); + } + catch (IntentResolutionException | VNMappingException e) + { + e.printStackTrace(); + endTransactionOutputBuilder.setResultCode(CommonRpcResult.ResultCode.Error).setMessage(e.getMessage()); + } + catch (Exception e) + { + e.printStackTrace(); + } + } + else + { + endTransactionOutputBuilder.setResultCode(CommonRpcResult.ResultCode.Ok).setMessage("The transaction ends."); + } + + } + } + endTransactionOutputResult = RpcResultBuilder.success(endTransactionOutputBuilder.build()).build(); + return Futures.immediateFuture(endTransactionOutputResult); + } + + @Override + public Future> languageStyleNemoRequest(LanguageStyleNemoRequestInput input) { + RpcResult styleNemoRequestOutputRpcResult = null; + LanguageStyleNemoRequestOutputBuilder languageStyleNemoRequestOutputBuilder = new LanguageStyleNemoRequestOutputBuilder(); + + String errorInfo = languageIntent.LanIntentHandler(aaa,input); + + if (errorInfo != null) + { + languageStyleNemoRequestOutputBuilder.setResultCode(CommonRpcResult.ResultCode.Error).setMessage(errorInfo); + } + else + { + languageStyleNemoRequestOutputBuilder.setResultCode(CommonRpcResult.ResultCode.Ok).setMessage("The intent has been stored in this transaction."); + informresolver = true; + } + styleNemoRequestOutputRpcResult = RpcResultBuilder.success(languageStyleNemoRequestOutputBuilder.build()).build(); + + return Futures.immediateFuture(styleNemoRequestOutputRpcResult); + } + + @Override + public Future> registerUser(RegisterUserInput input) { + RpcResult registerUserOutputRpcResult = null; + RegisterUserOutputBuilder registerUserOutputBuilder = new RegisterUserOutputBuilder(); + String errorInfo = registerUser.registerUser(input); + + if (errorInfo != null) + { + registerUserOutputBuilder.setResultCode(CommonRpcResult.ResultCode.Error).setMessage(errorInfo); + } + else + { + registerUserOutputBuilder.setResultCode(CommonRpcResult.ResultCode.Ok).setMessage("Register user successfully."); + } + + registerUserOutputRpcResult = RpcResultBuilder.success(registerUserOutputBuilder.build()).build(); + + return Futures.immediateFuture(registerUserOutputRpcResult); + } + + @Override + public Future> structureStyleNemoDelete(StructureStyleNemoDeleteInput input) { + RpcResult styleNemoDeleteOutputRpcResult = null; + StructureStyleNemoDeleteOutputBuilder styleNemoDeleteOutputBuilder = new StructureStyleNemoDeleteOutputBuilder(); + + String errorInfo = deleteIntent.styleNemoDeleteOutput(aaa,input); + + if (errorInfo != null) + { + styleNemoDeleteOutputBuilder.setResultCode(CommonRpcResult.ResultCode.Error).setMessage(errorInfo); + } + else + { + styleNemoDeleteOutputBuilder.setResultCode(CommonRpcResult.ResultCode.Ok).setMessage("The intent has been handled by user manager successfully."); + informresolver = true; + } + + + styleNemoDeleteOutputRpcResult = RpcResultBuilder.success(styleNemoDeleteOutputBuilder.build()).build(); + + return Futures.immediateFuture(styleNemoDeleteOutputRpcResult); + } + + @Override + public Future> structureStyleNemoUpdate(StructureStyleNemoUpdateInput input) { + RpcResult styleNemoUpdateOutputRpcResult = null; + StructureStyleNemoUpdateOutputBuilder styleNemoUpdateOutputBuilder = new StructureStyleNemoUpdateOutputBuilder(); + + String erroInfo = updateIntent.updateIntent(aaa,input); + + if (erroInfo != null) + { + styleNemoUpdateOutputBuilder.setResultCode(CommonRpcResult.ResultCode.Error).setMessage(erroInfo); + } + else + { + styleNemoUpdateOutputBuilder.setResultCode(CommonRpcResult.ResultCode.Ok).setMessage("The intent has been handled by user manager successfully."); + informresolver = true; + } + + styleNemoUpdateOutputRpcResult = RpcResultBuilder.success(styleNemoUpdateOutputBuilder.build()).build(); + + return Futures.immediateFuture(styleNemoUpdateOutputRpcResult); + } + + @Override + public void close() throws Exception { + if ( null != rpcRegistration ) { + rpcRegistration.close(); + } + } +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/user/advancedquery/AdvancedQuery.java b/nemo-impl/src/main/java/org/opendaylight/nemo/user/advancedquery/AdvancedQuery.java new file mode 100644 index 0000000..98bc16d --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/user/advancedquery/AdvancedQuery.java @@ -0,0 +1,521 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.nemo.user.advancedquery; + +import org.opendaylight.nemo.user.tenantmanager.AAA; +import org.opendaylight.nemo.user.tenantmanager.TenantManage; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.UserId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.AdvancedNemoQueryInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.Users; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.advanced.nemo.query.input.QueryCondition; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.Objects; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.Operations; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.Results; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Connection; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Flow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.operations.Operation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.users.User; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.users.UserKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.object.rev151010.flow.instance.MatchItem; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.object.rev151010.flow.instance.Property; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.object.rev151010.property.instance.property.values.IntValue; +import com.google.common.base.Optional; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +/** + * Created by z00293636 on 2015/8/29. + */ +public class AdvancedQuery +{ + private DataBroker dataBroker; + private TenantManage tenantManage; + private QueryDefinitionCheck queryDefinitionCheck; + private Objects objects; + private Operations operations; + private List resultsList; + private static final Logger LOG = LoggerFactory.getLogger(QueryDefinitionCheck.class); + + public AdvancedQuery(DataBroker dataBroker, TenantManage tenantManage) + { + this.dataBroker = dataBroker; + this.tenantManage = tenantManage; + queryDefinitionCheck = new QueryDefinitionCheck(dataBroker); + objects = null; + operations = null; + resultsList = null; + } + + public String advancedQuery(AAA aaa, AdvancedNemoQueryInput input) + { + String errorInfo = null; + List queryConditionList = null; + + errorInfo = aaa.CheckUser(input.getUserId(),input.getUserName(),input.getUserPassword(),input.getUserRole()); + + if (errorInfo != null) + { + return errorInfo; + } + else + { + if (input.getQueryCondition() != null) + { + queryConditionList = input.getQueryCondition(); + for (QueryCondition queryCondition : queryConditionList) + { + errorInfo = queryDefinitionCheck.CheckQueryDefinition(queryCondition); + if (errorInfo != null) + { + break; + } + } + } + } + return errorInfo; + } + + public String getAdvancedQueryReuslt(AdvancedNemoQueryInput advancedNemoQueryInput) + { + UserId userId = advancedNemoQueryInput.getUserId(); + List queryConditionList = advancedNemoQueryInput.getQueryCondition(); + String queryResult = null; + + for (QueryCondition queryCondition : queryConditionList) + { + if (queryCondition.getQueryIntentType() != null) + { + if (queryCondition.getQueryIntentType().getIntValue() == 0) + { + queryResult += nodeInstanceQuery(userId, queryCondition); + } + if (queryCondition.getQueryIntentType().getIntValue() == 1) + { + queryResult += connectionInstanceQuery(userId,queryCondition); + } + if (queryCondition.getQueryIntentType().getIntValue() == 2) + { + queryResult += flowInstanceQuery(userId,queryCondition); + } + if (queryCondition.getQueryIntentType().getIntValue() == 3) + { + queryResult += operationsInstanceQuery(userId,queryCondition); + } + } + } + + return queryResult; + } + + private String nodeInstanceQuery(UserId userId, QueryCondition queryCondition) + { + String queryResult = null; + + fetchObjectsInstance(userId); + + if (objects != null) + { + if (objects.getNode() != null) + { + List nodeList = objects.getNode(); + + for (Node node : nodeList) + { + if (node.getProperty() != null) + { + for(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.object.rev151010.node.instance.Property property : node.getProperty()) + { + if (property.getPropertyName().equals(queryCondition.getQueryConditionName())) + { + int operator = queryCondition.getQueryConditionMatchPattern().getIntValue(); + List values =property.getPropertyValues().getIntValue(); + if (operator == 0 && (property.getPropertyValues().getIntValue() != null)) + { + for(IntValue value:values) + { + if (value.getValue()queryCondition.getQueryConditionTargetValue().getIntValue()) + { + queryResult += node.getNodeId().toString()+node.getNodeName().toString()+node.getNodeType().toString()+node.getSubNode().toString()+node.getProperty().toString(); + } + } + } + if (operator == 5 && (property.getPropertyValues().getIntValue() != null)) + { + for(IntValue value:values) + { + if (value.getValue()>=queryCondition.getQueryConditionTargetValue().getIntValue()) + { + queryResult += node.getNodeId().toString()+node.getNodeName().toString()+node.getNodeType().toString()+node.getSubNode().toString()+node.getProperty().toString(); + } + } + } + if (operator == 6 && (property.getPropertyValues().getIntValue() != null)) + { + //between todo + } + } + } + } + + } + } + + } + + return queryResult; + } + + private String connectionInstanceQuery(UserId userId, QueryCondition queryCondition) + { + String queryResult = null; + + fetchObjectsInstance(userId); + if (objects != null) + { + if (objects.getConnection() != null) + { + List connectionList = objects.getConnection(); + + for (Connection connection : connectionList) + { + if (connection.getProperty() != null) + { + for (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.object.rev151010.connection.instance.Property property : connection.getProperty()) + { + if (property.getPropertyName().equals(queryCondition.getQueryConditionName())) + { + int operator = queryCondition.getQueryConditionMatchPattern().getIntValue(); + List values =property.getPropertyValues().getIntValue(); + if (operator == 0 && (property.getPropertyValues().getIntValue() != null)) + { + for(IntValue value:values) + { + if (value.getValue()queryCondition.getQueryConditionTargetValue().getIntValue()) + { + queryResult += connection.getConnectionId().toString()+ connection.getConnectionName().toString()+connection.getConnectionType().toString()+connection.getEndNode().toString()+connection.getProperty().toString(); + } + } + } + if (operator == 5 && (property.getPropertyValues().getIntValue() != null)) + { + for(IntValue value:values) + { + if (value.getValue()>=queryCondition.getQueryConditionTargetValue().getIntValue()) + { + queryResult += connection.getConnectionId().toString()+ connection.getConnectionName().toString()+connection.getConnectionType().toString()+connection.getEndNode().toString()+connection.getProperty().toString(); + } + } + } + if (operator == 6 && (property.getPropertyValues().getIntValue() != null)) + { + //between todo + } + } + } + } + + } + } + } + + return queryResult; + } + + private String flowInstanceQuery(UserId userId, QueryCondition queryCondition) + { + String queryResult = null; + + fetchObjectsInstance(userId); + if (objects != null) + { + if (objects.getFlow() != null) + { + List flowList = objects.getFlow(); + + for (Flow flow: flowList) + { + if (flow.getProperty() != null) + { + for (Property property : flow.getProperty()) + { + if (property.getPropertyName().equals(queryCondition.getQueryConditionName())) + { + int operator = queryCondition.getQueryConditionMatchPattern().getIntValue(); + List values = property.getPropertyValues().getIntValue(); + if (operator == 0 && (property.getPropertyValues().getIntValue() != null)) + { + for(IntValue value:values) + { + if (value.getValue()queryCondition.getQueryConditionTargetValue().getIntValue()) + { + queryResult += flow.getFlowId().toString() + flow.getFlowName().toString() + flow.getMatchItem().toString() + flow.getProperty().toString(); + } + } + } + if (operator == 5 && (property.getPropertyValues().getIntValue() != null)) + { + for(IntValue value:values) + { + if (value.getValue()>=queryCondition.getQueryConditionTargetValue().getIntValue()) + { + queryResult += flow.getFlowId().toString() + flow.getFlowName().toString() + flow.getMatchItem().toString() + flow.getProperty().toString(); + } + } + } + if (operator == 6 && (property.getPropertyValues().getIntValue() != null)) + { + //between todo + } + } + } + } + if (flow.getMatchItem() != null) + { + for(MatchItem matchItem: flow.getMatchItem()) + { + if (matchItem.getMatchItemName().equals(queryCondition.getQueryConditionName())) + { + int operator = queryCondition.getQueryConditionMatchPattern().getIntValue(); + if (operator == 0 && matchItem.getMatchItemValue().getIntValue()queryCondition.getQueryConditionTargetValue().getIntValue()) + { + queryResult += flow.getFlowId().toString() + flow.getFlowName().toString() + flow.getMatchItem().toString() + flow.getProperty().toString(); + } + if (operator == 5 && matchItem.getMatchItemValue().getIntValue()>=queryCondition.getQueryConditionTargetValue().getIntValue()) + { + queryResult += flow.getFlowId().toString() + flow.getFlowName().toString() + flow.getMatchItem().toString() + flow.getProperty().toString(); + } + if (operator == 6 ) + { + //todo + } + } + } + } + } + } + } + + return queryResult; + } + + private String operationsInstanceQuery(UserId userId, QueryCondition queryCondition) + { + String queryResult = null; + fetchOperationsInstance(userId); + List operationList = operations.getOperation(); + + //todo + + return queryResult; + } + + + private void fetchObjectsInstance(UserId userId) + { + UserKey userKey = new UserKey(userId); + InstanceIdentifier objectsId = InstanceIdentifier.builder(Users.class).child(User.class, userKey).child(Objects.class).build(); + ListenableFuture> objectsFuture = dataBroker.newReadOnlyTransaction().read(LogicalDatastoreType.CONFIGURATION, objectsId); + Futures.addCallback(objectsFuture, new FutureCallback>() { + @Override + public void onSuccess(Optional result) + { + setObjects(result.get()); + return; + } + + @Override + public void onFailure(Throwable t) + { + LOG.error("Can not read objects instances.", t); + + return; + } + }); + } + + private void fetchOperationsInstance(UserId userId) + { + UserKey userKey = new UserKey(userId); + InstanceIdentifier operationsId = InstanceIdentifier.builder(Users.class).child(User.class, userKey).child(Operations.class).build(); + ListenableFuture> operationsFuture = dataBroker.newReadOnlyTransaction().read(LogicalDatastoreType.CONFIGURATION, operationsId); + Futures.addCallback(operationsFuture, new FutureCallback>() { + @Override + public void onSuccess(Optional result) + { + setOperations(result.get()); + return; + } + + @Override + public void onFailure(Throwable t) + { + LOG.error("Can not read operations instances.", t); + + return; + } + }); + } + + private void setObjects(Objects objects) + { + this.objects = objects; + } + private void setOperations(Operations operations) + { + this.operations = operations; + } + +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/user/advancedquery/QueryDefinitionCheck.java b/nemo-impl/src/main/java/org/opendaylight/nemo/user/advancedquery/QueryDefinitionCheck.java new file mode 100644 index 0000000..c47efbe --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/user/advancedquery/QueryDefinitionCheck.java @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.nemo.user.advancedquery; + +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.QueryConditionDefinitions; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.advanced.nemo.query.input.QueryCondition; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.query.condition.definitions.QueryConditionDefinition; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.query.condition.definitions.query.condition.definition.QueryConditionMatchPatterns; +import com.google.common.base.Optional; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +/** + * Created by z00293636 on 2015/9/16. + */ +public class QueryDefinitionCheck { + private DataBroker dataBroker; + private List queryConditionDefinitions; + private static final Logger LOG = LoggerFactory.getLogger(QueryDefinitionCheck.class); + + public QueryDefinitionCheck(DataBroker dataBroker) + { + this.dataBroker = dataBroker; + queryConditionDefinitions = null; + } + + public String CheckQueryDefinition(QueryCondition queryCondition) + { + fetchQueryConditionDefinitionList(); + Boolean conditionexist = false; + String errorInfo = null; + if (queryConditionDefinitions != null) + { + for (QueryConditionDefinition queryConditionDefinition : queryConditionDefinitions) + { + if (queryConditionDefinition.getQueryConditionName().equals(queryCondition.getQueryConditionName())) + { + conditionexist = true; + + if (queryCondition.getQueryIntentType() != null) + { + if (queryConditionDefinition.getQueryIntentType() != null) + { + if (queryCondition.getQueryIntentType().getIntValue() != queryConditionDefinition.getQueryIntentType().getIntValue()) + { + errorInfo = "The query target is not consistent with the definition."; + break; + } + } + else + { + errorInfo = "There are no query intent type defined in this query condition."; + break; + } + } + + if (queryCondition.getQueryConditionTargetValue() != null) + { + if (queryConditionDefinition.getQueryConditionValueType() != null) + { + QueryConditionDefinition.QueryConditionValueType queryConditionValueType = queryConditionDefinition.getQueryConditionValueType(); + if (queryConditionValueType.getIntValue() == 0 && !(queryCondition.getQueryConditionTargetValue().getIntValue() == null && queryCondition.getQueryConditionTargetValue().getStringValue() != null && queryCondition.getQueryConditionTargetValue().getRangeValue() == null)) + { + errorInfo = "The property value type should be string"; + break; + } + else if (queryConditionValueType.getIntValue() == 1 && !(queryCondition.getQueryConditionTargetValue().getIntValue() != null && queryCondition.getQueryConditionTargetValue().getStringValue() == null && queryCondition.getQueryConditionTargetValue().getRangeValue() == null)) + { + errorInfo = "The property value type should be integer"; + break; + } + else if (queryConditionValueType.getIntValue() == 2 && !(queryCondition.getQueryConditionTargetValue().getIntValue() == null && queryCondition.getQueryConditionTargetValue().getStringValue() == null && queryCondition.getQueryConditionTargetValue().getRangeValue() != null)) + { + errorInfo = "The property value type should be range"; + break; + } + } + else + { + errorInfo = "There are no query condition value type defined in query condition."; + break; + } + } + + if (queryCondition.getQueryConditionMatchPattern() != null) + { + if (queryConditionDefinition.getQueryConditionMatchPatterns() != null) + { + if (queryConditionDefinition.getQueryConditionMatchPatterns().getQueryConditionMatchPattern() != null) + { + List queryConditionMatchPatternList= queryConditionDefinition.getQueryConditionMatchPatterns().getQueryConditionMatchPattern(); + if (!queryConditionMatchPatternList.contains(queryCondition.getQueryConditionMatchPattern())) + { + errorInfo = "The query condition match type pattern is not included in the definitions."; + break; + } + } + else + { + errorInfo = "There are no query condition list defined in query condition."; + } + } + else + { + errorInfo = "There are no query condition match patterns defined in query condition."; + } + } + } + } + } + + if (!conditionexist) + { + errorInfo = "The condition has not been defined."; + } + return errorInfo; + } + + private void fetchQueryConditionDefinitionList() + { + InstanceIdentifier queryCondiDefInsIdentifier = InstanceIdentifier.builder(QueryConditionDefinitions.class).build(); + ListenableFuture> querydefinitionFuture = dataBroker.newReadOnlyTransaction().read(LogicalDatastoreType.CONFIGURATION, queryCondiDefInsIdentifier); + Futures.addCallback(querydefinitionFuture, new FutureCallback>() { + @Override + public void onSuccess(Optional result) + { + setQueryConditionDefinitions(result.get().getQueryConditionDefinition()); + return; + } + + @Override + public void onFailure(Throwable t) + { + LOG.error("Can not read query definition information.", t); + + return; + } + }); + return ; + } + + private void setQueryConditionDefinitions(List queryConditionDefinitions) + { + this.queryConditionDefinitions = queryConditionDefinitions; + } + } diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/user/tenantmanager/AAA.java b/nemo-impl/src/main/java/org/opendaylight/nemo/user/tenantmanager/AAA.java new file mode 100644 index 0000000..a1a4753 --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/user/tenantmanager/AAA.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.nemo.user.tenantmanager; + +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.UserId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.UserName; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.UserPassword; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.UserRoleName; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.users.User; + +import java.util.List; + +/** + * Created by z00293636 on 2015/8/29. + */ + +/* test user-name and user-password */ +public class AAA { + + private TenantManage tenantManage; + + public AAA(TenantManage tenantManage) + { + this.tenantManage = tenantManage; + } + + public String CheckUser(UserId userId, UserName userName, UserPassword userPassword, UserRoleName userRoleName) + { + tenantManage.fetchUsers(); + List userList = tenantManage.getUsersList(); + String errorInfo = null; + Boolean userexist = false; + + if (userList != null) + { + for (User user : userList) + { + if (user.getUserId().equals(userId)) + { + userexist = true; + if (!user.getUserName().equals(userName)) + { + errorInfo = "The user name is not right."; + break; + } + else if (!user.getUserPassword().equals(userPassword)) + { + errorInfo = "The password is not right."; + break; + } + else if (!user.getUserRole().equals(userRoleName)) + { + errorInfo = "The role is not right."; + break; + } + } + } + + } + + if (!userexist) + { + errorInfo = "The user is not exist."; + } + return errorInfo; + } +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/user/tenantmanager/RegisterUser.java b/nemo-impl/src/main/java/org/opendaylight/nemo/user/tenantmanager/RegisterUser.java new file mode 100644 index 0000000..d598b02 --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/user/tenantmanager/RegisterUser.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.nemo.user.tenantmanager; + +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.UserId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.UserRoleName; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.RegisterUserInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.users.User; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.user.rev151010.user.roles.UserRole; + +import java.util.List; + +/** + * Created by z00293636 on 2015/9/20. + */ +public class RegisterUser { + private TenantManage tenantManage; + private List userRoleList; + private List usersList; + + public RegisterUser(TenantManage tenantManage) + { + this.tenantManage = tenantManage; + } + + public String registerUser(RegisterUserInput input) + { + String errorInfo = null; + + tenantManage.fetchUserRoles(); + userRoleList = tenantManage.getUserRoleList(); + tenantManage.fetchUsers(); + usersList = tenantManage.getUsersList(); + + if (userRoleList == null) + { + errorInfo = "There are no roles be defined."; + } + else + { + if (IfRoleExist(input.getUserRole())) + { + if (usersList != null && IfUserHasRegistered(input.getUserId())) + { + errorInfo = "The user has been registered."; + } + else + { + tenantManage.addUser(input); + } + } + else + { + errorInfo = "The role is not defined in the data store."; + } + } + return errorInfo; + } + private boolean IfRoleExist(UserRoleName userRoleName){ + Boolean roleExist = false; + + for (UserRole userRole : userRoleList) + { + if (userRole.getRoleName().equals(userRoleName)) + { + roleExist = true; + } + } + + return roleExist; + } + + private boolean IfUserHasRegistered(UserId userId){ + Boolean userHasRegistered = false; + + for (User user : usersList) + { + if (user.getUserId().equals(userId)) + { + userHasRegistered = true; + } + } + + return userHasRegistered; + } + +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/user/tenantmanager/TenantManage.java b/nemo-impl/src/main/java/org/opendaylight/nemo/user/tenantmanager/TenantManage.java new file mode 100644 index 0000000..c20756b --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/user/tenantmanager/TenantManage.java @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.nemo.user.tenantmanager; + +import com.google.common.base.Optional; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.ListenableFuture; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.UserId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.RegisterUserInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.Users; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.users.User; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.users.UserBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.users.UserKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.user.rev151010.UserRoles; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.user.rev151010.user.roles.UserRole; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + + +/** + * Created by z00293636 on 2015/8/29. + */ + +/* maintain tenant information, including how many tenants are active, their information */ +public class TenantManage { + private static final Logger LOG = LoggerFactory.getLogger(TenantManage.class); + private DataBroker dataBroker; + private List userRoleList; + private List usersList ; + private User user; + + public TenantManage(DataBroker dataBroker) + { + this.dataBroker = dataBroker; + } + + private void setUserRoleList(List userRoleList) + { + this.userRoleList = userRoleList; + } + + private void setUserList(List userList) + { + this.usersList = userList; + } + + private void setUser(User user) + { + this.user = user; + } + + public List getUserRoleList() + { + return userRoleList; + } + + public List getUsersList() + { + return usersList; + } + + public User getUser() + { + return user; + } + + public void fetchUserRoles(){ + + InstanceIdentifier userRolesInsId = InstanceIdentifier.builder(UserRoles.class).build(); + ListenableFuture> userRolesFuture = this.dataBroker.newReadOnlyTransaction().read(LogicalDatastoreType.CONFIGURATION, userRolesInsId); + Futures.addCallback(userRolesFuture, new FutureCallback>() { + @Override + public void onSuccess(Optional result) + { + setUserRoleList(result.get().getUserRole()); + return; + } + + @Override + public void onFailure(Throwable t) + { + LOG.error("Can not read role information.", t); + + return; + } + }); + return; + } + + public void fetchUsers(){ + InstanceIdentifier usersInsId = InstanceIdentifier.builder(Users.class).build(); + ListenableFuture> usersFuture = dataBroker.newReadOnlyTransaction().read(LogicalDatastoreType.CONFIGURATION, usersInsId); + Futures.addCallback(usersFuture, new FutureCallback>() { + @Override + public void onSuccess(Optional result) + { + setUserList(result.get().getUser()); + return; + } + + @Override + public void onFailure(Throwable t) + { + LOG.error("Can not read users information.", t); + + return; + } + }); + return; + } + + public void fetchVNSpace(UserId userId) + { + fetchUsers(); + if (getUsersList() != null) + { + for (User user : getUsersList()) + { + if (user.getUserId().equals(userId)) + { + setUser(user); + break; + } + } + } + return; + } + + public void addUser(RegisterUserInput registerUserInput){ + WriteTransaction t = dataBroker.newWriteOnlyTransaction(); + if (registerUserInput.getUserId() != null) + { + User user = new UserBuilder(registerUserInput).build(); +// UserBuilder userBuilder = new UserBuilder(); +// userBuilder.setUserId(registerUserInput.getUserId()); +// userBuilder.setUserName(registerUserInput.getUserName()); +// userBuilder.setUserPassword(registerUserInput.getUserPassword()); +// userBuilder.setUserRole(registerUserInput.getUserRole()); +// +// User user = userBuilder.build(); + UserKey userKey = new UserKey(registerUserInput.getUserId()); + + InstanceIdentifier userid = InstanceIdentifier.builder(Users.class).child(User.class, userKey).build(); + + t.put(LogicalDatastoreType.CONFIGURATION, userid, user,true); + CheckedFuture f = t.submit(); + Futures.addCallback(f, new FutureCallback() { + @Override + public void onFailure(Throwable t) { + LOG.error("Could not write endpoint base container", t); + } + + @Override + public void onSuccess(Void result) { + + } + }); + } + } +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/user/transactionmanager/TransactionBegin.java b/nemo-impl/src/main/java/org/opendaylight/nemo/user/transactionmanager/TransactionBegin.java new file mode 100644 index 0000000..b0f7eb2 --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/user/transactionmanager/TransactionBegin.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.nemo.user.transactionmanager; + +import org.opendaylight.nemo.user.tenantmanager.AAA; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.BeginTransactionInput; + +/** + * Created by z00293636 on 2015/9/2. + */ +public class TransactionBegin { + + public String transactionbegin(AAA aaa,BeginTransactionInput input) + { + String errorInfo = null; + errorInfo = aaa.CheckUser(input.getUserId(),input.getUserName(),input.getUserPassword(),input.getUserRole()); + return errorInfo; + } +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/user/transactionmanager/TransactionEnd.java b/nemo-impl/src/main/java/org/opendaylight/nemo/user/transactionmanager/TransactionEnd.java new file mode 100644 index 0000000..c4f2f7b --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/user/transactionmanager/TransactionEnd.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.nemo.user.transactionmanager; + +import org.opendaylight.nemo.user.tenantmanager.AAA; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.EndTransactionInput; + +/** + * Created by z00293636 on 2015/9/2. + */ +public class TransactionEnd { + public String transactionend(AAA aaa,EndTransactionInput input) + { + String errorInfo = null; + errorInfo = aaa.CheckUser(input.getUserId(),input.getUserName(),input.getUserPassword(),input.getUserRole()); + return errorInfo; + } +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/VNSpaceManagement.java b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/VNSpaceManagement.java new file mode 100644 index 0000000..9c02260 --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/VNSpaceManagement.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.nemo.user.vnspacemanager; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.NodeId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.UserId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.object.rev151010.NodeInstance; + +/** + * Created by z00293636 on 2015/9/6. + */ +public class VNSpaceManagement { + private DataBroker dataBroker; + + public VNSpaceManagement(DataBroker dataBroker) + { + this.dataBroker = dataBroker; + } + + public NodeInstance getNodeInstance(UserId userId, NodeId nodeId) { + // TODO + + return null; + } + +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/instancecheck/ConnectionInstanceCheck.java b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/instancecheck/ConnectionInstanceCheck.java new file mode 100644 index 0000000..aec2430 --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/instancecheck/ConnectionInstanceCheck.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.nemo.user.vnspacemanager.instancecheck; + +import org.opendaylight.nemo.user.tenantmanager.TenantManage; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.UserId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Connection; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.users.User; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.object.rev151010.connection.instance.EndNode; + +import java.util.List; + +/** + * Created by z00293636 on 2015/9/10. + */ +public class ConnectionInstanceCheck { + private TenantManage tenantManage; + + public ConnectionInstanceCheck(TenantManage tenantManage) + { + this.tenantManage = tenantManage; + } + + public String checkConnInstance(UserId userId, Connection connection) + { + String errorInfo = null; + tenantManage.fetchVNSpace(userId); + User user = tenantManage.getUser(); + + if (user != null) + { + if (user.getObjects() != null) + { + if (user.getObjects().getConnection() != null) + { + List connectionList = tenantManage.getUser().getObjects().getConnection(); + + for (Connection connection1 : connectionList) + { + if (connection1.getConnectionId().equals(connection.getConnectionId())) + { + if (!connection1.getConnectionType().equals(connection.getConnectionType())) + { + errorInfo = "The connection type should not be changed."; + break; + } + if (!connection1.getConnectionName().equals(connection.getConnectionName())) + { + errorInfo = "The End node should not be changed."; + break; + } + + } + } + } + if (user.getObjects().getNode() != null) + { + List nodeList = connection.getEndNode(); + List nodeList1 = user.getObjects().getNode(); + + for (EndNode endNode : nodeList) + { + Boolean EndNodeExist = false; + for (Node node : nodeList1) + { + if (node.getNodeId().equals(endNode.getNodeId())) + { + EndNodeExist = true; + break; + } + } + if ( !EndNodeExist) + { + errorInfo = "There are no endnode" + endNode.getNodeId().toString() +" in this user vn space."; + break; + } + } + } + } + else + { + if (connection.getEndNode() != null) + { + errorInfo = "There are no nodes in user vn space."; + } + } + } + else + { + if (connection.getEndNode() != null) + { + errorInfo = "There are no nodes in user vn space."; + } + } + + return errorInfo; + } +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/instancecheck/FlowInstanceCheck.java b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/instancecheck/FlowInstanceCheck.java new file mode 100644 index 0000000..6ba1352 --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/instancecheck/FlowInstanceCheck.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.nemo.user.vnspacemanager.instancecheck; + +import org.opendaylight.nemo.user.tenantmanager.TenantManage; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.UserId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Flow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.users.User; + +import java.util.List; + +/** + * Created by z00293636 on 2015/9/10. + */ +public class FlowInstanceCheck { + private TenantManage tenantManage; + + public FlowInstanceCheck(TenantManage tenantManage) + { + this.tenantManage = tenantManage; + } + + public String checkFlowInstance(UserId userId, Flow flow) + { + String errorInfo = null; + + tenantManage.fetchVNSpace(userId); + + + User user = tenantManage.getUser(); + if (user != null) + { + if (user.getObjects() != null) + { + if (user.getObjects().getFlow() != null) + { + List flowList = tenantManage.getUser().getObjects().getFlow(); + for (Flow flow1 : flowList) + { + if (flow1.getFlowId() == flow.getFlowId()) + { + if (flow1.getFlowName() != flow.getFlowName()) + { + errorInfo = "The flow name should not be changed."; + break; + } + } + } + } + } + } + return errorInfo; + } +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/instancecheck/NodeInstanceCheck.java b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/instancecheck/NodeInstanceCheck.java new file mode 100644 index 0000000..e1f17f6 --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/instancecheck/NodeInstanceCheck.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.nemo.user.vnspacemanager.instancecheck; + +import org.opendaylight.nemo.user.tenantmanager.TenantManage; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.UserId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.Objects; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.users.User; + +import java.util.List; + +/** + * Created by z00293636 on 2015/9/10. + */ +public class NodeInstanceCheck { + + private TenantManage tenantManage; + + public NodeInstanceCheck(TenantManage tenantManage) + { + this.tenantManage = tenantManage; + } + + public String checkNodeInstance(UserId userId, Node node) + { + String errorInfo = null; + tenantManage.fetchVNSpace(userId); + User user = tenantManage.getUser(); + if (user != null) + { + Objects objects = user.getObjects(); + if (objects != null) + { + if (objects.getNode() != null) + { + List nodeList = objects.getNode(); + + for (Node node1 : nodeList) + { + if (node1.getNodeId().equals(node.getNodeId())) + { + if ( !node1.getNodeName().equals(node.getNodeName())) + { + errorInfo = "The node name should not be changed."; + break; + } + if (!node1.getNodeType().equals(node.getNodeType())) + { + errorInfo = "The node type should not be changed."; + break; + } + } + } + } + } + } + return errorInfo; + } +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/instancecheck/OperationInstanceCheck.java b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/instancecheck/OperationInstanceCheck.java new file mode 100644 index 0000000..b7603db --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/instancecheck/OperationInstanceCheck.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.nemo.user.vnspacemanager.instancecheck; + +import org.opendaylight.nemo.user.tenantmanager.TenantManage; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.UserId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.Objects; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Connection; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Flow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.operations.Operation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.users.User; + +import java.util.List; + +/** + * Created by z00293636 on 2015/9/10. + */ +public class OperationInstanceCheck { + private TenantManage tenantManage; + + public OperationInstanceCheck(TenantManage tenantManage) + { + this.tenantManage = tenantManage; + } + + public String checkOperationInstance(UserId userId, Operation operation) + { + String errorInfo = null; + + tenantManage.fetchVNSpace(userId); + + User user = tenantManage.getUser(); + if (user != null) + { + if (operation.getTargetObject() != null && user.getObjects() == null) + { + errorInfo = "There are no objects in data store."; + } + if (operation.getTargetObject() != null && user.getObjects() != null) + { + Objects objects = user.getObjects(); + Boolean targetExist = false; + + if (objects.getNode() != null ) + { + List nodeList = objects.getNode(); + for (Node node:nodeList) + { + if (node.getNodeId().getValue().equals(operation.getTargetObject().getValue())) + { + targetExist = true; + break; + } + } + } + if (objects.getConnection() != null) + { + List connectionList = objects.getConnection(); + for (Connection connection : connectionList) + { + if (connection.getConnectionId().getValue().equals(operation.getTargetObject().getValue())) + { + targetExist = true; + break; + } + } + } + if (objects.getFlow() != null) + { + List flowList = objects.getFlow(); + for (Flow flow : flowList) + { + if (flow.getFlowId().getValue().equals(operation.getTargetObject().getValue())) + { + targetExist = true; + break; + } + } + } + if (!targetExist) + { + errorInfo ="The target object is not included in vn space."; + } + } + else + { + if (user.getOperations() != null) + { + if (user.getOperations().getOperation() != null) + { + List operationList = tenantManage.getUser().getOperations().getOperation(); + for (Operation operation1 : operationList) + { + if (operation1.getOperationId().equals(operation.getOperationId())) + { + if (!operation1.getOperationName().equals(operation.getOperationName())) + { + errorInfo = "The operation name should not be changed."; + break; + } + } + } + } + } + } + } + else + { + if (operation.getTargetObject() != null) + { + errorInfo = "There are no objects in data store."; + } + } + return errorInfo; + } +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/instancecheck/ResultInstanceCheck.java b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/instancecheck/ResultInstanceCheck.java new file mode 100644 index 0000000..62dac6f --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/instancecheck/ResultInstanceCheck.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.nemo.user.vnspacemanager.instancecheck; + +import org.opendaylight.nemo.user.tenantmanager.TenantManage; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.UserId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.Results; + + +/** + * Created by z00293636 on 2015/9/10. + */ +public class ResultInstanceCheck { + private TenantManage tenantManage; + + public ResultInstanceCheck(TenantManage tenantManage) + { + this.tenantManage = tenantManage; + } + + public String checkResultInstance(UserId userId,Results results) + { + return null; + } +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/languagestyle/LanguageIntent.java b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/languagestyle/LanguageIntent.java new file mode 100644 index 0000000..670d1b5 --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/languagestyle/LanguageIntent.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.nemo.user.vnspacemanager.languagestyle; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.nemo.user.tenantmanager.AAA; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.LanguageStyleNemoRequestInput; + +/** + * Created by z00293636 on 2015/8/31. + */ +public class LanguageIntent { + + private DataBroker dataBroker; + + public LanguageIntent(DataBroker dataBroker) + { + this.dataBroker = dataBroker; + } + + public String LanIntentHandler(AAA aaa, LanguageStyleNemoRequestInput languageStyleNemoRequestInput){ + + String errorInfo = null; + + errorInfo = aaa.CheckUser(languageStyleNemoRequestInput.getUserId(),languageStyleNemoRequestInput.getUserName(),languageStyleNemoRequestInput.getUserPassword(),languageStyleNemoRequestInput.getUserRole()); + if (errorInfo !=null) + { + return errorInfo; + } + else + { + //TODO language parse + } + + return null; + } +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/structurestyle/deleteintent/DeleteConnection.java b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/structurestyle/deleteintent/DeleteConnection.java new file mode 100644 index 0000000..9e8baf5 --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/structurestyle/deleteintent/DeleteConnection.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.nemo.user.vnspacemanager.structurestyle.deleteintent; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.nemo.user.tenantmanager.TenantManage; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.ConnectionId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.UserId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.Users; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.Objects; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Connection; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.ConnectionKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.users.User; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.users.UserKey; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +/** + * Created by z00293636 on 2015/9/2. + */ +public class DeleteConnection { + + private DataBroker dataBroker; + private TenantManage tenantManage; + private static final Logger LOG = LoggerFactory.getLogger(DeleteConnection.class); + + public DeleteConnection(DataBroker dataBroker, TenantManage tenantManage) + { + this.dataBroker = dataBroker; + this.tenantManage = tenantManage; + } + + public String DeleteConnectionHandling(UserId userId, ConnectionId connectionId) + { + Boolean ConnInstanceExist = false; + String errorInfo = null; + + tenantManage.fetchVNSpace(userId); + User user = tenantManage.getUser(); + + if (user != null) + { + if (user.getObjects() != null) + { + if (user.getObjects().getConnection() != null) + { + List connectionList = tenantManage.getUser().getObjects().getConnection(); + + for (Connection connection : connectionList) + { + if (connection.getConnectionId().equals(connectionId)) + { + ConnInstanceExist = true; + break; + } + } + + if (ConnInstanceExist) + { + DeleteConnInstance(userId, connectionId); + } + else + { + errorInfo = "The connection instance"+connectionId.toString()+ "is not exit. Could not be deleted."; + } + + } + else + { + errorInfo = "There are no connection instances in data store."; + } + } + } + else + { + errorInfo = "There are no connection instances in data store."; + } + + return errorInfo; + } + + private void DeleteConnInstance(UserId userId, ConnectionId connectionId) + { + WriteTransaction t = dataBroker.newWriteOnlyTransaction(); + UserKey userKey = new UserKey(userId); + ConnectionKey connectionKey = new ConnectionKey(connectionId); + + InstanceIdentifier connectionid = InstanceIdentifier.builder(Users.class).child(User.class, userKey).child(Objects.class).child(Connection.class,connectionKey).build(); + t.delete(LogicalDatastoreType.CONFIGURATION, connectionid); + CheckedFuture f = t.submit(); + Futures.addCallback(f, new FutureCallback() { + @Override + public void onFailure(Throwable t) { + LOG.error("Could not write endpoint base container", t); + } + + @Override + public void onSuccess(Void result) { + } + }); + } +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/structurestyle/deleteintent/DeleteFlow.java b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/structurestyle/deleteintent/DeleteFlow.java new file mode 100644 index 0000000..6a45e31 --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/structurestyle/deleteintent/DeleteFlow.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.nemo.user.vnspacemanager.structurestyle.deleteintent; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.nemo.user.tenantmanager.TenantManage; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.FlowId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.UserId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.Users; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.Objects; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Flow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.FlowKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.users.User; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.users.UserKey; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +/** + * Created by z00293636 on 2015/9/2. + */ +public class DeleteFlow { + + private DataBroker dataBroker; + private TenantManage tenantManage; + private static final Logger LOG = LoggerFactory.getLogger(DeleteFlow.class); + + public DeleteFlow(DataBroker dataBroker, TenantManage tenantManage) + { + this.dataBroker = dataBroker; + this.tenantManage = tenantManage; + } + + public String DeleteFlowHandling(UserId userId, FlowId flowId) + { + Boolean FlowInsExist = false; + tenantManage.fetchVNSpace(userId); + String errorInfo = null; + User user = tenantManage.getUser(); + + if (user != null) + { + if (user.getObjects() != null) + { + if (user.getObjects().getFlow() != null) + { + List flowList = tenantManage.getUser().getObjects().getFlow(); + for (Flow flow : flowList) + { + if (flow.getFlowId().equals(flowId)) + { + FlowInsExist = true; + break; + } + } + + if (FlowInsExist) + { + DeleteFlowInstance(userId,flowId); + } + else + { + errorInfo = "The flow instance" +flowId.toString()+"is not exist. Could not be deleted."; + } + } + else + { + errorInfo = "There are no flow instances in the data store."; + } + } + } + else + { + errorInfo = "There are no user in the data store."; + } + return errorInfo; + } + + private void DeleteFlowInstance(UserId userId, FlowId flowId) + { + WriteTransaction t = dataBroker.newWriteOnlyTransaction(); + UserKey userKey = new UserKey(userId); + FlowKey flowKey = new FlowKey(flowId); + + InstanceIdentifier flowid = InstanceIdentifier.builder(Users.class).child(User.class, userKey).child(Objects.class).child(Flow.class,flowKey).build(); + t.delete(LogicalDatastoreType.CONFIGURATION, flowid); + CheckedFuture f = t.submit(); + Futures.addCallback(f, new FutureCallback() { + @Override + public void onFailure(Throwable t) { + LOG.error("Could not write endpoint base container", t); + } + + @Override + public void onSuccess(Void result) { + } + }); + } +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/structurestyle/deleteintent/DeleteIntent.java b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/structurestyle/deleteintent/DeleteIntent.java new file mode 100644 index 0000000..1eaba1b --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/structurestyle/deleteintent/DeleteIntent.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.nemo.user.vnspacemanager.structurestyle.deleteintent; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.nemo.user.tenantmanager.AAA; +import org.opendaylight.nemo.user.tenantmanager.TenantManage; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.ConnectionId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.FlowId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.NodeId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.OperationId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.StructureStyleNemoDeleteInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.structure.style.nemo.delete.input.Results; + +import java.util.List; + +/** + * Created by z00293636 on 2015/9/2. + */ +public class DeleteIntent { + + private DataBroker dataBroker; + private TenantManage tenantManage; + private DeleteNode deleteNode; + private DeleteConnection deleteConnection; + private DeleteFlow deleteFlow; + private DeleteOperation deleteOperation; + private DeleteResult deleteResult; + + public DeleteIntent(DataBroker dataBroker, TenantManage tenantManage) + { + this.dataBroker = dataBroker; + this.tenantManage = tenantManage; + deleteNode = new DeleteNode(dataBroker, tenantManage); + deleteConnection = new DeleteConnection(dataBroker,tenantManage); + deleteFlow = new DeleteFlow(dataBroker,tenantManage); + deleteOperation = new DeleteOperation(dataBroker,tenantManage); + deleteResult = new DeleteResult(); + } + + public String styleNemoDeleteOutput(AAA aaa,StructureStyleNemoDeleteInput styleNemoDeleteInput) + { + String errorInfo = null; + + errorInfo = aaa.CheckUser(styleNemoDeleteInput.getUserId(),styleNemoDeleteInput.getUserName(),styleNemoDeleteInput.getUserPassword(),styleNemoDeleteInput.getUserRole()); + + if (errorInfo != null) + { + return errorInfo; + } + + else + { + if (styleNemoDeleteInput.getObjects() != null) + { + if (styleNemoDeleteInput.getObjects().getNode() != null && errorInfo == null) + { + List nodeIdList= styleNemoDeleteInput.getObjects().getNode(); + for (NodeId nodeId : nodeIdList) + { + errorInfo = deleteNode.DeleNodeHandling(styleNemoDeleteInput.getUserId(), nodeId); + if (errorInfo != null) { + break; + } + } + return errorInfo; + } + + if (styleNemoDeleteInput.getObjects().getConnection() != null && errorInfo == null) + { + List connectionIdList = styleNemoDeleteInput.getObjects().getConnection(); + for (ConnectionId connectionId : connectionIdList) + { + errorInfo = deleteConnection.DeleteConnectionHandling(styleNemoDeleteInput.getUserId(),connectionId); + if (errorInfo != null) + { + break; + } + } + return errorInfo; + } + + if (styleNemoDeleteInput.getObjects().getFlow() != null && errorInfo == null) + { + List flowIdList = styleNemoDeleteInput.getObjects().getFlow(); + for (FlowId flowId : flowIdList ) + { + errorInfo = deleteFlow.DeleteFlowHandling(styleNemoDeleteInput.getUserId(),flowId); + if (errorInfo != null) + { + break; + } + } + return errorInfo; + } + } + if (styleNemoDeleteInput.getOperations() != null) + { + if (styleNemoDeleteInput.getOperations().getOperation() != null && errorInfo == null) + { + List operationIdList = styleNemoDeleteInput.getOperations().getOperation(); + for (OperationId operationId : operationIdList) + { + errorInfo = deleteOperation.DeleteOperationhandling(styleNemoDeleteInput.getUserId(),operationId); + if (errorInfo != null) + { + break; + } + } + return errorInfo; + } + } + + if (styleNemoDeleteInput.getResults() != null) + { + Results results = styleNemoDeleteInput.getResults(); + errorInfo = deleteResult.DeleteResultHandling(styleNemoDeleteInput.getUserId(),results); + if (errorInfo != null) + { + return errorInfo; + } + } + } + return null; + } +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/structurestyle/deleteintent/DeleteNode.java b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/structurestyle/deleteintent/DeleteNode.java new file mode 100644 index 0000000..7088f4f --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/structurestyle/deleteintent/DeleteNode.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.nemo.user.vnspacemanager.structurestyle.deleteintent; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.nemo.user.tenantmanager.TenantManage; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.NodeId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.UserId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.Users; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.Objects; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.NodeKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.users.User; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.users.UserKey; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +/** + * Created by z00293636 on 2015/9/2. + */ +public class DeleteNode { + + private DataBroker dataBroker; + private TenantManage tenantManage; + private static final Logger LOG = LoggerFactory.getLogger(DeleteNode.class); + + public DeleteNode(DataBroker dataBroker, TenantManage tenantManage) + { + this.dataBroker = dataBroker; + this.tenantManage = tenantManage; + } + + public String DeleNodeHandling(UserId userId,NodeId nodeId) + { + String errorInfo = null; + Boolean NodeInstanceExist = false; + + tenantManage.fetchVNSpace(userId); + + User user = tenantManage.getUser(); + if (user != null) + { + if (user.getObjects() != null) + { + if (user.getObjects().getNode() != null) + { + List nodeList = tenantManage.getUser().getObjects().getNode(); + + for (Node node : nodeList) + { + if (node.getNodeId().equals(nodeId)) + { + NodeInstanceExist = true; + break; + } + } + if (NodeInstanceExist) + { + DeleteNodeInstance(userId,nodeId); + } + else + { + errorInfo = "The node instance" +nodeId.toString()+"is not exist.Could not be deleted"; + } + } + else + { + errorInfo = "There are no nodes instances in data store."; + } + } + } + else + { + errorInfo = "There are no user in data store."; + } + + return errorInfo; + } + + private void DeleteNodeInstance(UserId userId,NodeId nodeId) + { + WriteTransaction t = dataBroker.newWriteOnlyTransaction(); + UserKey userKey = new UserKey(userId); + NodeKey nodeKey = new NodeKey(nodeId); + + InstanceIdentifier nodeid = InstanceIdentifier.builder(Users.class).child(User.class, userKey).child(Objects.class).child(Node.class,nodeKey).build(); + t.delete(LogicalDatastoreType.CONFIGURATION, nodeid); + CheckedFuture f = t.submit(); + Futures.addCallback(f, new FutureCallback() { + @Override + public void onFailure(Throwable t) { + LOG.error("Could not write endpoint base container", t); + } + + @Override + public void onSuccess(Void result) { + } + }); + } +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/structurestyle/deleteintent/DeleteOperation.java b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/structurestyle/deleteintent/DeleteOperation.java new file mode 100644 index 0000000..81cb365 --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/structurestyle/deleteintent/DeleteOperation.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.nemo.user.vnspacemanager.structurestyle.deleteintent; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.nemo.user.tenantmanager.TenantManage; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.OperationId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.UserId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.Users; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.Operations; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.operations.Operation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.operations.OperationKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.users.User; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.users.UserKey; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +/** + * Created by z00293636 on 2015/9/2. + */ +public class DeleteOperation { + + private DataBroker dataBroker; + private TenantManage tenantManage; + private static final Logger LOG = LoggerFactory.getLogger(DeleteOperation.class); + + public DeleteOperation(DataBroker dataBroker, TenantManage tenantManage) + { + this.dataBroker = dataBroker; + this.tenantManage = tenantManage; + } + + public String DeleteOperationhandling(UserId userId, OperationId operationId) + { + Boolean OperationExist = false; + String errorInfo = null; + tenantManage.fetchVNSpace(userId); + + User user = tenantManage.getUser(); + + if (user != null) + { + if (user.getOperations() != null) + { + if (user.getOperations().getOperation() != null) + { + List operationList = tenantManage.getUser().getOperations().getOperation(); + + for (Operation operation : operationList) + { + if (operation.getOperationId().equals(operationId)) + { + OperationExist = true; + break; + } + } + + if (OperationExist) + { + DeleteOperationInstance(userId,operationId); + } + else + { + errorInfo = "The operation instance" +operationId.toString()+"is not exist. Could not be deleted."; + } + } + else + { + errorInfo = "There are no operation instances in the data store."; + } + } + } + else + { + errorInfo = "There are no user in the data store."; + } + return errorInfo; + } + + private void DeleteOperationInstance(UserId userId, OperationId operationId) + { + WriteTransaction t = dataBroker.newWriteOnlyTransaction(); + UserKey userKey = new UserKey(userId); + OperationKey operationKey = new OperationKey(operationId); + + InstanceIdentifier operationid = InstanceIdentifier.builder(Users.class).child(User.class, userKey).child(Operations.class).child(Operation.class,operationKey).build(); + t.delete(LogicalDatastoreType.CONFIGURATION, operationid); + CheckedFuture f = t.submit(); + Futures.addCallback(f, new FutureCallback() { + @Override + public void onFailure(Throwable t) { + LOG.error("Could not write endpoint base container", t); + } + + @Override + public void onSuccess(Void result) { + } + }); + } +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/structurestyle/deleteintent/DeleteResult.java b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/structurestyle/deleteintent/DeleteResult.java new file mode 100644 index 0000000..8b73364 --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/structurestyle/deleteintent/DeleteResult.java @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.nemo.user.vnspacemanager.structurestyle.deleteintent; + +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.UserId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.structure.style.nemo.delete.input.Results; + +/** + * Created by z00293636 on 2015/9/2. + */ +public class DeleteResult { + + public String DeleteResultHandling(UserId userId, Results results) + { + return null; + } +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/structurestyle/updateintent/UpdateConnection.java b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/structurestyle/updateintent/UpdateConnection.java new file mode 100644 index 0000000..607e83b --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/structurestyle/updateintent/UpdateConnection.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.nemo.user.vnspacemanager.structurestyle.updateintent; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.nemo.user.tenantmanager.TenantManage; +import org.opendaylight.nemo.user.vnspacemanager.instancecheck.ConnectionInstanceCheck; +import org.opendaylight.nemo.user.vnspacemanager.syntaxcheck.ConnectionDefinitionCheck; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.UserId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.Users; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.Objects; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Connection; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.ConnectionBuilder; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.ConnectionKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.users.User; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.users.UserKey; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.FutureCallback; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Created by z00293636 on 2015/8/31. + */ +public class UpdateConnection { + + private DataBroker dataBroker; + private TenantManage tenantManage; + private ConnectionDefinitionCheck connectionDefinitionCheck; + private ConnectionInstanceCheck connectionInstanceCheck; + private static final Logger LOG = LoggerFactory.getLogger(UpdateConnection.class); + + public UpdateConnection(DataBroker dataBroker, TenantManage tenantManage) + { + this.dataBroker = dataBroker; + this.tenantManage = tenantManage; + connectionDefinitionCheck = new ConnectionDefinitionCheck(dataBroker); + connectionInstanceCheck = new ConnectionInstanceCheck(tenantManage); + } + + public String ConnectionHandling(UserId userId, Connection connection) + { + String errorDefinition = connectionDefinitionCheck.CheckConnectionDefinition(connection); + String errorInstance = connectionInstanceCheck.checkConnInstance(userId,connection); + if (errorDefinition != null) + { + return errorDefinition; + } + if (errorInstance != null) + { + return errorInstance; + } + else + { + WriteTransaction t = dataBroker.newWriteOnlyTransaction(); + if (userId != null && connection != null) + { +// ConnectionBuilder connectionBuilder = new ConnectionBuilder(); +// connectionBuilder.setConnectionId(connection.getConnectionId()); +// connectionBuilder.setConnectionName(connection.getConnectionName()); +// connectionBuilder.setConnectionType(connection.getConnectionType()); +// connectionBuilder.setEndNode(connection.getEndNode()); +// connectionBuilder.setProperty(connection.getProperty()); +// +// Connection connection1 = connectionBuilder.build(); + + Connection connection1 = new ConnectionBuilder(connection).build(); + ConnectionKey connectionKey = new ConnectionKey(connection.getConnectionId()); + + UserKey userKey = new UserKey(userId); + + InstanceIdentifier connectionid = InstanceIdentifier.builder(Users.class).child(User.class, userKey).child(Objects.class).child(Connection.class,connectionKey).build(); + t.put(LogicalDatastoreType.CONFIGURATION, connectionid, connection1,true); + CheckedFuture f = t.submit(); + Futures.addCallback(f, new FutureCallback() { + @Override + public void onFailure(Throwable t) { + LOG.error("Could not write endpoint base container", t); + } + + @Override + public void onSuccess(Void result) { + } + }); + } + } + return null; + } + +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/structurestyle/updateintent/UpdateFlow.java b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/structurestyle/updateintent/UpdateFlow.java new file mode 100644 index 0000000..5af2190 --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/structurestyle/updateintent/UpdateFlow.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.nemo.user.vnspacemanager.structurestyle.updateintent; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.nemo.user.tenantmanager.TenantManage; +import org.opendaylight.nemo.user.vnspacemanager.instancecheck.FlowInstanceCheck; +import org.opendaylight.nemo.user.vnspacemanager.syntaxcheck.FlowDefinitionCheck; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.UserId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.Users; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.Objects; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Flow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.FlowBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.FlowKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.users.User; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.users.UserKey; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +/** + * Created by z00293636 on 2015/8/31. + */ +public class UpdateFlow { + + private DataBroker dataBroker; + private TenantManage tenantManage; + private FlowDefinitionCheck flowDefinitionCheck; + private FlowInstanceCheck flowInstanceCheck; + private static final Logger LOG = LoggerFactory.getLogger(UpdateFlow.class); + + public UpdateFlow(DataBroker dataBroker, TenantManage tenantManage) + { + this.dataBroker = dataBroker; + this.tenantManage = tenantManage; + flowDefinitionCheck = new FlowDefinitionCheck(dataBroker); + flowInstanceCheck = new FlowInstanceCheck(tenantManage); + } + + public String FlowHandling(UserId userId, Flow flow) + { + String errorDefinition = flowDefinitionCheck.CheckDefinition(flow); + String errorInstance = flowInstanceCheck.checkFlowInstance(userId,flow); + + if (errorDefinition != null) + { + return errorDefinition; + } + if (errorInstance != null) + { + return errorInstance; + } + else + { + WriteTransaction t = dataBroker.newWriteOnlyTransaction(); + if (userId!=null && flow!=null) + { +// FlowBuilder flowBuilder = new FlowBuilder(); +// flowBuilder.setFlowId(flow.getFlowId()); +// flowBuilder.setFlowName(flow.getFlowName()); +// flowBuilder.setMatchItem(flow.getMatchItem()); +// flowBuilder.setProperty(flow.getProperty()); +// +// Flow flow1 = flowBuilder.build(); + Flow flow1 = new FlowBuilder(flow).build(); + FlowKey flowKey = new FlowKey(flow.getFlowId()); + + UserKey userKey = new UserKey(userId); + + InstanceIdentifier flowid = InstanceIdentifier.builder(Users.class).child(User.class, userKey).child(Objects.class).child(Flow.class,flowKey).build(); + t.put(LogicalDatastoreType.CONFIGURATION, flowid, flow1,true); + CheckedFuture f = t.submit(); + Futures.addCallback(f, new FutureCallback() { + @Override + public void onFailure(Throwable t) { + LOG.error("Could not write endpoint base container", t); + } + + @Override + public void onSuccess(Void result) { + } + }); + } + } + return null; + } + +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/structurestyle/updateintent/UpdateIntent.java b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/structurestyle/updateintent/UpdateIntent.java new file mode 100644 index 0000000..1a34b9b --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/structurestyle/updateintent/UpdateIntent.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.nemo.user.vnspacemanager.structurestyle.updateintent; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.nemo.user.tenantmanager.AAA; +import org.opendaylight.nemo.user.tenantmanager.TenantManage; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.StructureStyleNemoUpdateInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.Results; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Connection; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Flow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.operations.Operation; + +import java.util.List; + +/** + * Created by z00293636 on 2015/8/31. + */ +public class UpdateIntent { + + private DataBroker dataBroker; + private TenantManage tenantManage; + private UpdateNode updateNode; + private UpdateConnection updateConnection; + private UpdateFlow updateFlow; + private UpdateOperation updateOperation; + private UpdateResult updateResult; + + public UpdateIntent(DataBroker dataBroker, TenantManage tenantManage) + { + this.dataBroker = dataBroker; + this.tenantManage = tenantManage; + updateNode = new UpdateNode(dataBroker,tenantManage); + updateConnection = new UpdateConnection(dataBroker,tenantManage); + updateFlow = new UpdateFlow(dataBroker,tenantManage); + updateOperation = new UpdateOperation(dataBroker,tenantManage); + updateResult = new UpdateResult(dataBroker,tenantManage); + } + + public String updateIntent(AAA aaa,StructureStyleNemoUpdateInput structureStyleNemoUpdateInput){ + + String erroInfo = null; + + erroInfo = aaa.CheckUser(structureStyleNemoUpdateInput.getUserId(),structureStyleNemoUpdateInput.getUserName(),structureStyleNemoUpdateInput.getUserPassword(),structureStyleNemoUpdateInput.getUserRole()); + + if (erroInfo != null) + { + return erroInfo; + } + else + { + if(structureStyleNemoUpdateInput.getObjects() != null) + { + if (structureStyleNemoUpdateInput.getObjects().getNode() != null && erroInfo == null) + { + List nodeList= structureStyleNemoUpdateInput.getObjects().getNode(); + for (Node node : nodeList ) + { + erroInfo = updateNode.NodeHandling(structureStyleNemoUpdateInput.getUserId(), node); + if (erroInfo != null) + { + break; + } + } + } + if (structureStyleNemoUpdateInput.getObjects().getConnection() != null && erroInfo == null) + { + List connectionList = structureStyleNemoUpdateInput.getObjects().getConnection(); + for (Connection connection : connectionList) + { + erroInfo = updateConnection.ConnectionHandling(structureStyleNemoUpdateInput.getUserId(), connection); + if (erroInfo != null) + { + break; + } + } + } + + if (structureStyleNemoUpdateInput.getObjects().getFlow() != null && erroInfo == null) + { + List flowList = structureStyleNemoUpdateInput.getObjects().getFlow(); + for (Flow flow : flowList) + { + erroInfo = updateFlow.FlowHandling(structureStyleNemoUpdateInput.getUserId(),flow); + if (erroInfo != null) + { + break; + } + } + } + } + + if (structureStyleNemoUpdateInput.getOperations() != null) + { + if (structureStyleNemoUpdateInput.getOperations().getOperation() != null && erroInfo == null) + { + List operationList =structureStyleNemoUpdateInput.getOperations().getOperation(); + for (Operation operation : operationList) + { + erroInfo = updateOperation.OperationHandling(structureStyleNemoUpdateInput.getUserId(), operation); + if (erroInfo !=null) + { + break; + } + } + } + } + + else if (structureStyleNemoUpdateInput.getResults() != null) + { + if ( structureStyleNemoUpdateInput.getResults() != null && erroInfo == null) + { + Results results = structureStyleNemoUpdateInput.getResults(); + erroInfo = updateResult.ResultHandling(structureStyleNemoUpdateInput.getUserId(), results); + if (erroInfo != null) + { + //todo + } + } + } + } + return erroInfo; + } +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/structurestyle/updateintent/UpdateNode.java b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/structurestyle/updateintent/UpdateNode.java new file mode 100644 index 0000000..1739b5f --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/structurestyle/updateintent/UpdateNode.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.nemo.user.vnspacemanager.structurestyle.updateintent; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.nemo.user.tenantmanager.TenantManage; +import org.opendaylight.nemo.user.vnspacemanager.instancecheck.NodeInstanceCheck; +import org.opendaylight.nemo.user.vnspacemanager.syntaxcheck.NodeDefinitionCheck; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.UserId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.Users; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.Objects; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.NodeBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.NodeKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.users.User; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.users.UserKey; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Created by z00293636 on 2015/8/31. + */ +public class UpdateNode { + + private DataBroker dataBroker; + private NodeDefinitionCheck nodeCheck; + private NodeInstanceCheck nodeInstanceCheck; + private static final Logger LOG = LoggerFactory.getLogger(UpdateNode.class); + + public UpdateNode(DataBroker dataBroker,TenantManage tenantManage) + { + this.dataBroker = dataBroker; + nodeCheck = new NodeDefinitionCheck(dataBroker); + nodeInstanceCheck = new NodeInstanceCheck(tenantManage); + } + + public String NodeHandling(UserId userId,Node node) + { + String errorDefinition = nodeCheck.CheckNodeDefinition(node); + String errorInstance = nodeInstanceCheck.checkNodeInstance(userId,node); + + if (errorDefinition != null) + { + return errorDefinition; + } + if (errorInstance != null) + { + return errorInstance; + } + else + { + WriteTransaction t = dataBroker.newWriteOnlyTransaction(); + if (userId != null && node.getNodeId() !=null) + { +// NodeBuilder nodeBuilder = new NodeBuilder(); +// nodeBuilder.setNodeId(node.getNodeId()); +// nodeBuilder.setNodeId(node.getNodeId()); +// nodeBuilder.setNodeName(node.getNodeName()); +// nodeBuilder.setSubNode(node.getSubNode()); +// nodeBuilder.setProperty(node.getProperty()); +// Node node1 = nodeBuilder.build(); + + Node node1 = new NodeBuilder(node).build(); + NodeKey nodeKey = new NodeKey(node.getKey()); + + UserKey userKey = new UserKey(userId); + + InstanceIdentifier nodeid = InstanceIdentifier.builder(Users.class).child(User.class, userKey).child(Objects.class).child(Node.class,nodeKey).build(); + t.put(LogicalDatastoreType.CONFIGURATION, nodeid, node1,true); + CheckedFuture f = t.submit(); + Futures.addCallback(f, new FutureCallback() { + @Override + public void onFailure(Throwable t) { + LOG.error("Could not write endpoint base container", t); + } + + @Override + public void onSuccess(Void result) { + } + }); + } + } + return null; + } + +} + diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/structurestyle/updateintent/UpdateOperation.java b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/structurestyle/updateintent/UpdateOperation.java new file mode 100644 index 0000000..40b1e60 --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/structurestyle/updateintent/UpdateOperation.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.nemo.user.vnspacemanager.structurestyle.updateintent; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.nemo.user.tenantmanager.TenantManage; +import org.opendaylight.nemo.user.vnspacemanager.instancecheck.OperationInstanceCheck; +import org.opendaylight.nemo.user.vnspacemanager.syntaxcheck.OperationDefinitionCheck; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.UserId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.Users; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.Operations; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.operations.Operation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.operations.OperationBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.operations.OperationKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.users.User; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.users.UserKey; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Created by z00293636 on 2015/8/31. + */ +public class UpdateOperation { + + private DataBroker dataBroker; + private TenantManage tenantManage; + private OperationDefinitionCheck operationDefinitionCheck; + private OperationInstanceCheck operationInstanceCheck; + private static final Logger LOG = LoggerFactory.getLogger(UpdateOperation.class); + + public UpdateOperation(DataBroker dataBroker, TenantManage tenantManage) + { + this.dataBroker = dataBroker; + this.tenantManage = tenantManage; + operationDefinitionCheck = new OperationDefinitionCheck(dataBroker); + operationInstanceCheck = new OperationInstanceCheck(tenantManage); + } + + public String OperationHandling(UserId userId, Operation operation) + { + String errorDefinition = operationDefinitionCheck.CheckDefinition(operation); + String errorInstance = operationInstanceCheck.checkOperationInstance(userId, operation); + + if (errorDefinition != null) + { + return errorDefinition; + } + if (errorInstance != null) + { + return errorInstance; + } + else + { + WriteTransaction t = dataBroker.newWriteOnlyTransaction(); + if (userId != null && operation.getOperationId() != null) + { +// OperationBuilder operationBuilder = new OperationBuilder(); +// operationBuilder.setOperationId(operation.getOperationId()); +// operationBuilder.setOperationName(operation.getOperationName()); +// operationBuilder.setConditionSegment(operation.getConditionSegment()); +// operationBuilder.setTargetObject(operationBuilder.getTargetObject()); +// operationBuilder.setAction(operation.getAction()); +// operationBuilder.setPriority(operation.getPriority()); +// +// Operation operation1 = operationBuilder.build(); + Operation operation1 = new OperationBuilder(operation).build(); + OperationKey operationKey = new OperationKey(operation.getOperationId()); + + UserKey userKey = new UserKey(userId); + + InstanceIdentifier operationid = InstanceIdentifier.builder(Users.class).child(User.class, userKey).child(Operations.class).child(Operation.class,operationKey).build(); + t.put(LogicalDatastoreType.CONFIGURATION, operationid, operation1,true); + CheckedFuture f = t.submit(); + Futures.addCallback(f, new FutureCallback() { + @Override + public void onFailure(Throwable t) { + LOG.error("Could not write endpoint base container", t); + } + + @Override + public void onSuccess(Void result) { + + } + }); + } + } + return null; + } +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/structurestyle/updateintent/UpdateResult.java b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/structurestyle/updateintent/UpdateResult.java new file mode 100644 index 0000000..ede89b7 --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/structurestyle/updateintent/UpdateResult.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.nemo.user.vnspacemanager.structurestyle.updateintent; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.nemo.user.tenantmanager.TenantManage; +import org.opendaylight.nemo.user.vnspacemanager.instancecheck.ResultInstanceCheck; +import org.opendaylight.nemo.user.vnspacemanager.syntaxcheck.ResultDefinitionCheck; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.UserId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.Results; + +/** + * Created by z00293636 on 2015/8/31. + */ +public class UpdateResult { + + private DataBroker dataBroker; + private TenantManage tenantManage; + private ResultDefinitionCheck resultDefinitionCheck; + private ResultInstanceCheck resultInstanceCheck; + + public UpdateResult(DataBroker dataBroker, TenantManage tenantManage) + { + this.dataBroker = dataBroker; + this.tenantManage = tenantManage; + resultDefinitionCheck = new ResultDefinitionCheck(); + resultInstanceCheck = new ResultInstanceCheck(tenantManage); + } + + public String ResultHandling(UserId userId, Results results) + { + String errorDefinition = resultDefinitionCheck.CheckDefinition(results); + String errorInstance = resultInstanceCheck.checkResultInstance(userId,results); + + if (errorDefinition!= null) + { + return errorDefinition; + } + else if (errorInstance != null) + { + return errorInstance; + } + else + { + //todo + } + return null; + } +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/syntaxcheck/ConnectionDefinitionCheck.java b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/syntaxcheck/ConnectionDefinitionCheck.java new file mode 100644 index 0000000..ff457b7 --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/syntaxcheck/ConnectionDefinitionCheck.java @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.nemo.user.vnspacemanager.syntaxcheck; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.PropertyName; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Connection; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.object.rev151010.ConnectionDefinitions; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.object.rev151010.connection.definitions.ConnectionDefinition; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.object.rev151010.connection.instance.Property; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.object.rev151010.property.definitions.PropertyDefinition; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.object.rev151010.property.instance.PropertyValues; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.common.RpcResultBuilder; +import org.opendaylight.yangtools.yang.common.RpcError.ErrorType; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import com.google.common.base.Optional; +import com.google.common.base.Function; +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.util.List; + +/** + * Created by z00293636 on 2015/9/2. + */ +public class ConnectionDefinitionCheck { + + private DataBroker dataBroker; + private List connectionDefinitionList; + private static final Logger LOG = LoggerFactory.getLogger(ConnectionDefinitionCheck.class); + + public ConnectionDefinitionCheck(DataBroker dataBroker) + { + this.dataBroker = dataBroker; + connectionDefinitionList = null; + } + + public String CheckConnectionDefinition(Connection connection) + { + fetchConnectionDefinitionList(); + boolean ConnectionHasDefined = false; + String errorInfo = null; + + if (connectionDefinitionList != null) + { + for (ConnectionDefinition connectionDefinition : connectionDefinitionList) + { + if (connectionDefinition.getConnectionType().equals(connection.getConnectionType())) + { + ConnectionHasDefined = true; + List connectionProperties = connection.getProperty(); + List propertyDefinitions = connectionDefinition.getPropertyDefinition(); + + if (connectionProperties != null && propertyDefinitions ==null) + { + errorInfo = "There are no properties for this type of connection."; + break; + } + else if (connectionProperties != null && propertyDefinitions != null) + { + errorInfo = CheckProperty(connection.getProperty(), connectionDefinition.getPropertyDefinition()); + if (errorInfo != null) + { + break; + } + } + + } + } + } + + if (!ConnectionHasDefined) + { + return "This type of connection has not been defined."; + } + return errorInfo; + } + + private String CheckProperty(List connectionProperty, List propertyDefinitionList ) + { + String errorInfo = null; + for (Property property : connectionProperty) + { + Boolean properyHasDefine = false; + if (errorInfo != null) + { + break; + } + else + { + for (PropertyDefinition propertyDefinition : propertyDefinitionList) + { + if (property.getPropertyName().equals(propertyDefinition.getPropertyName())) + { + properyHasDefine = true; + PropertyValues propertyValues = property.getPropertyValues(); + PropertyDefinition.PropertyValueType propertyValueType = propertyDefinition.getPropertyValueType(); + + if (propertyValues != null && propertyValueType != null) + { + if (propertyDefinition.getIsReadOnly()!=null) + { + if (propertyDefinition.getIsRequired().getIntValue() == 1) + { + errorInfo = "The property value type of" + property.getPropertyName().toString() + "is read only."; + break; + } + } + else + { + if (propertyValueType.getIntValue() == 0 && !(propertyValues.getIntValue() == null && propertyValues.getStringValue() != null && propertyValues.getRangeValue() == null)) { + errorInfo = "The property value type of" + property.getPropertyName().toString() + " should be string."; + break; + } + if (propertyValueType.getIntValue() == 1 && !(propertyValues.getIntValue() != null && propertyValues.getStringValue() == null && propertyValues.getRangeValue() == null)) { + errorInfo = "The property value type of" + property.getPropertyName().toString() + " should be integer."; + break; + } + if (propertyValueType.getIntValue() == 2 && !(propertyValues.getIntValue() == null && propertyValues.getStringValue() == null && propertyValues.getRangeValue() != null)) { + errorInfo = "The property value type of" + property.getPropertyName().toString() + " should be range."; + break; + } + } + } + } + } + if (!properyHasDefine) { + errorInfo = "This type of property" + property.getPropertyName().toString() + " has not been defined."; + } + } + } + + if (errorInfo == null) + { + Boolean requiredProperty = false; + for (PropertyDefinition propertyDefinition : propertyDefinitionList) + { + if (propertyDefinition.getIsRequired()!=null) + { + if (propertyDefinition.getIsRequired().getIntValue() == 0) + { + for (Property property : connectionProperty) + { + if (property.getPropertyName().equals(propertyDefinition.getPropertyName())) + { + requiredProperty = true; + } + } + if (!requiredProperty) + { + errorInfo = "The required property" + propertyDefinition.getPropertyName().toString() + "is not included in the intent."; + } + } + } + } + } + return errorInfo; + } + + private void fetchConnectionDefinitionList() + { + InstanceIdentifier connectiondefinitionId = InstanceIdentifier.builder(ConnectionDefinitions.class).build(); + ListenableFuture> connectiondefinitionFuture = dataBroker.newReadOnlyTransaction().read(LogicalDatastoreType.CONFIGURATION, connectiondefinitionId); + Futures.addCallback(connectiondefinitionFuture, new FutureCallback>() { + @Override + public void onSuccess(Optional result) { + setConnectionDefinitionList(result.get().getConnectionDefinition()); + return; + } + + @Override + public void onFailure(Throwable t) { + LOG.error("Can not read connection definition information.", t); + + return; + } + }); + return; + } + + private void setConnectionDefinitionList(List connectionDefinitionList) + { + this.connectionDefinitionList = connectionDefinitionList; + } + +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/syntaxcheck/FlowDefinitionCheck.java b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/syntaxcheck/FlowDefinitionCheck.java new file mode 100644 index 0000000..0926357 --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/syntaxcheck/FlowDefinitionCheck.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.nemo.user.vnspacemanager.syntaxcheck; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Flow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.object.rev151010.FlowPropertyDefinitions; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.object.rev151010.MatchItemDefinitions; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.object.rev151010.flow.instance.MatchItem; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.object.rev151010.match.item.definitions.MatchItemDefinition; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.object.rev151010.match.item.instance.MatchItemValue; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.common.RpcResultBuilder; +import org.opendaylight.yangtools.yang.common.RpcError.ErrorType; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import com.google.common.base.Optional; +import com.google.common.base.Function; +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.util.List; + +/** + * Created by z00293636 on 2015/9/2. + */ +public class FlowDefinitionCheck { + + private DataBroker dataBroker; + private List matchItemDefinitionList; + private static final Logger LOG = LoggerFactory.getLogger(FlowDefinitionCheck.class); + + public FlowDefinitionCheck(DataBroker dataBroker) + { + this.dataBroker = dataBroker; + matchItemDefinitionList = null; + } + + public String CheckDefinition(Flow flow) + { + String errorInfo = null; + fetchMatchItemDefinitions(); + Boolean matchHasDefined = false; + if (flow.getMatchItem() != null) + { + if (matchItemDefinitionList != null ) + { + for (MatchItem matchItem : flow.getMatchItem()) + { + for (MatchItemDefinition matchItemDefinition : matchItemDefinitionList) + { + if (matchItem.getMatchItemName().equals(matchItemDefinition.getMatchItemName())) + { + matchHasDefined = true; + MatchItemValue matchItemValue = matchItem.getMatchItemValue(); + MatchItemDefinition.MatchItemValueType matchItemValueType = matchItemDefinition.getMatchItemValueType(); + + if (matchItemValue != null && matchItemValueType != null) + { + if (matchItemValueType.getIntValue()==0 && !(matchItemValue.getIntValue()==null&&matchItemValue.getStringValue()!=null&&matchItemValue.getRangeValue()==null)) + { + errorInfo = "The match item value type for" +matchItem.getMatchItemName().toString()+"should be string."; + break; + } + + if (matchItemValueType.getIntValue()==1 && !(matchItemValue.getIntValue()!=null&&matchItemValue.getStringValue()==null&&matchItemValue.getRangeValue()==null)) + { + errorInfo = "The match item value type for" + matchItem.getMatchItemName().toString()+"should be integer."; + break; + } + + if (matchItemValueType.getIntValue()==2 && !(matchItemValue.getIntValue()==null&&matchItemValue.getStringValue()==null&&matchItemValue.getRangeValue()!=null)) + { + errorInfo = "The match item value type for" + matchItem.getMatchItemName().toString()+"should be range."; + break; + } + } + } + } + } + } + if (!matchHasDefined) + { + errorInfo = "The match item has not been defined."; + } + } + return errorInfo; + } + + private void fetchMatchItemDefinitions() + { + InstanceIdentifier matchitemdefinitionId = InstanceIdentifier.builder(MatchItemDefinitions.class).build(); + ListenableFuture> matchitemdefinitionFuture = dataBroker.newReadOnlyTransaction().read(LogicalDatastoreType.CONFIGURATION, matchitemdefinitionId); + Futures.addCallback(matchitemdefinitionFuture, new FutureCallback>() { + @Override + public void onSuccess(Optional result) { + setMatchItemDefinitionList( result.get().getMatchItemDefinition()); + return; + } + + @Override + public void onFailure(Throwable t) { + LOG.error("Can not read match item definition information.", t); + + return; + } + }); + return ; + } + + private void setMatchItemDefinitionList(List matchItemDefinitionList) + { + this.matchItemDefinitionList = matchItemDefinitionList; + } +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/syntaxcheck/NodeDefinitionCheck.java b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/syntaxcheck/NodeDefinitionCheck.java new file mode 100644 index 0000000..3f6a66f --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/syntaxcheck/NodeDefinitionCheck.java @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.nemo.user.vnspacemanager.syntaxcheck; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.NodeType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.PropertyName; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.object.rev151010.NodeDefinitions; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.object.rev151010.node.definitions.NodeDefinition; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.object.rev151010.node.instance.Property; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.object.rev151010.property.definitions.PropertyDefinition; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.object.rev151010.property.instance.PropertyValues; + +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.common.RpcResultBuilder; +import org.opendaylight.yangtools.yang.common.RpcError.ErrorType; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import com.google.common.base.Optional; +import com.google.common.base.Function; +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +/** + * Created by z00293636 on 2015/9/2. + */ +public class NodeDefinitionCheck { + + private DataBroker dataBroker; + private List nodeDefinitionList; + private static final Logger LOG = LoggerFactory.getLogger(NodeDefinitionCheck.class); + + public NodeDefinitionCheck(DataBroker dataBroker) + { + this.dataBroker = dataBroker; + nodeDefinitionList = null; + } + + public String CheckNodeDefinition(Node node) + { + String errorInfo = null; + Boolean NodeHasDefined = false; + + fetchNodeDefinitions(); + if (nodeDefinitionList != null) + { + for (NodeDefinition nodeDefinition : nodeDefinitionList) + { + if (nodeDefinition.getNodeType().equals(node.getNodeType())) + { + NodeHasDefined = true; + List nodeProperties = node.getProperty(); + List nodePropertyDefinitions = nodeDefinition.getPropertyDefinition(); + + if (nodeProperties != null && nodePropertyDefinitions == null) + { + errorInfo = "This type of node has no properties."; + break; + } + else if (nodeProperties != null && nodePropertyDefinitions != null) + { + errorInfo = checkProperty(nodeProperties, nodeDefinition.getPropertyDefinition()); + if (errorInfo != null) + { + break; + } + } + } + } + } + + if (!NodeHasDefined) + { + errorInfo = "This type of Node has not been defined."; + } + return errorInfo; + } + + private String checkProperty(List nodeProperties, List nodePropertyDefinitions) + { + Boolean propertyHasDefine = false; + String errorInfo = null; + + for (Property property : nodeProperties) + { + if (errorInfo != null) + { + break; + } + else + { + for (PropertyDefinition propertydefinition : nodePropertyDefinitions) + { + if (property.getPropertyName().equals(propertydefinition.getPropertyName())) + { + propertyHasDefine = true; + PropertyValues propertyValues = property.getPropertyValues(); + PropertyDefinition.PropertyValueType propertyValueType = propertydefinition.getPropertyValueType(); + + if (propertyValues != null && propertyValueType != null) + { + if (propertydefinition.getIsReadOnly()!=null) + { + if (propertydefinition.getIsRequired().getIntValue() == 1) + { + errorInfo = "The property"+ property.getPropertyName().toString()+" is readonly, can not be written."; + break; + } + } + else if (propertyValueType.getIntValue() == 0 && !(propertyValues.getIntValue() == null && propertyValues.getStringValue() != null && propertyValues.getRangeValue() == null)) + { + errorInfo = "The property value type"+property.getPropertyName().toString()+" should be string"; + break; + } + else if (propertyValueType.getIntValue() == 1 && !(propertyValues.getIntValue() != null && propertyValues.getStringValue() == null && propertyValues.getRangeValue() == null)) + { + errorInfo = "The property value type"+property.getPropertyName().toString()+" should be integer"; + break; + } + else if (propertyValueType.getIntValue() == 2 && !(propertyValues.getIntValue() == null && propertyValues.getStringValue() == null && propertyValues.getRangeValue() != null)) + { + errorInfo = "The property value type"+property.getPropertyName().toString()+" should be range"; + break; + } + } + } + } + + if (!propertyHasDefine) + { + errorInfo = "The property"+property.getPropertyName().toString()+"has not been defined."; + } + } + } + + if (errorInfo == null) + { + Boolean requiredProperty = false; + for (PropertyDefinition propertyDefinition : nodePropertyDefinitions) + { + if (propertyDefinition.getIsRequired()!=null) + { + if (propertyDefinition.getIsRequired().getIntValue() ==0) + { + for (Property property: nodeProperties) + { + if (property.getPropertyName().equals(propertyDefinition.getPropertyName())) + { + requiredProperty = true; + } + } + if (!requiredProperty) + { + errorInfo = "The required property "+ propertyDefinition.getPropertyName().toString() + "is not included in the intent."; + break; + } + } + } + } + } + return errorInfo; + } + + private void fetchNodeDefinitions() + { + InstanceIdentifier nodedefinitionId = InstanceIdentifier.builder(NodeDefinitions.class).build(); + ListenableFuture> nodedefinitionFuture = dataBroker.newReadOnlyTransaction().read(LogicalDatastoreType.CONFIGURATION, nodedefinitionId); + Futures.addCallback(nodedefinitionFuture, new FutureCallback>() { + @Override + public void onSuccess(Optional result) + { + setNodeDefinitionList(result.get().getNodeDefinition()); + return; + } + + @Override + public void onFailure(Throwable t) + { + LOG.error("Can not read node definitions information.", t); + return; + } + }); + return ; + } + + private void setNodeDefinitionList(List nodeDefinitionsList) + { + this.nodeDefinitionList = nodeDefinitionsList; + } +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/syntaxcheck/OperationDefinitionCheck.java b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/syntaxcheck/OperationDefinitionCheck.java new file mode 100644 index 0000000..9f4417e --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/syntaxcheck/OperationDefinitionCheck.java @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.nemo.user.vnspacemanager.syntaxcheck; + +import com.google.common.base.Optional; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.ParameterName; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.operations.Operation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.operation.rev151010.ActionDefinitions; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.operation.rev151010.ConditionParameterDefinitions; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.operation.rev151010.action.definitions.ActionDefinition; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.operation.rev151010.action.instance.ParameterValues; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.operation.rev151010.condition.instance.ConditionSegment; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.operation.rev151010.condition.instance.condition.segment.ConditionParameterTargetValue; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.operation.rev151010.condition.parameter.definitions.ConditionParameterDefinition; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.operation.rev151010.condition.parameter.definitions.condition.parameter.definition.ParameterMatchPatterns; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.operation.rev151010.operation.instance.Action; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +/** + * Created by z00293636 on 2015/9/2. + */ +public class OperationDefinitionCheck { + + private DataBroker dataBroker; + private List actionDefinitionList; + private List conditionParameterDefinitionList; + private static final Logger LOG = LoggerFactory.getLogger(OperationDefinitionCheck.class); + public OperationDefinitionCheck(DataBroker dataBroker) + { + this.dataBroker = dataBroker; + actionDefinitionList = null; + conditionParameterDefinitionList = null; + } + + public String CheckDefinition(Operation operation) + { + fetchActionDefinitions(); + fetchConditionParaDefinitions(); + String errorInfo = null; + + if (operation.getAction() != null ) + { + errorInfo = checkAction(operation); + } + if (errorInfo == null && operation.getConditionSegment() != null) + { + errorInfo = checkCondition(operation); + } + return errorInfo; + } + + private String checkAction(Operation operation) + { + String errorInfo = null; + Boolean actionHasDefine = false; + + if ( actionDefinitionList == null) + { + errorInfo = "There are no actions has been defined in the data store."; + } + else { + for (Action action : operation.getAction()) { + for (ActionDefinition actionDefinition : actionDefinitionList) { + if (actionDefinition.getActionName().equals(action.getActionName())) { + actionHasDefine = true; + + ParameterValues parameterValues = action.getParameterValues(); + ActionDefinition.ParameterValueType parameterValueType = actionDefinition.getParameterValueType(); + + if (parameterValues != null && parameterValueType != null) + { + if (parameterValueType.getIntValue() == 0 && !(parameterValues.getIntValue() == null && parameterValues.getStringValue() != null && parameterValues.getRangeValue() == null)) { + errorInfo = "The value type of" + action.getActionName().toString() + "should be string."; + break; + } + if (parameterValueType.getIntValue() == 1 && !(parameterValues.getIntValue() != null && parameterValues.getStringValue() == null && parameterValues.getRangeValue() == null)) { + errorInfo = "The value type of" + action.getActionName().toString() + "should be integer."; + break; + } + if (parameterValueType.getIntValue() == 2 && !(parameterValues.getIntValue() == null && parameterValues.getStringValue() == null && parameterValues.getRangeValue() != null)) { + errorInfo = "The value type of" + action.getActionName().toString() + "should be range."; + break; + } + } + } + + } + } + if (!actionHasDefine) { + errorInfo = "The action type has not been defined."; + } + } + return errorInfo; + } + + private String checkCondition(Operation operation) + { + String errorInfo = null; + Boolean conditionHasDefined = false; + + if (conditionParameterDefinitionList != null) + { + if (operation.getConditionSegment() != null) + { + for (ConditionSegment conditionSegment :operation.getConditionSegment()) + { + for (ConditionParameterDefinition conditionParameterDefinition : conditionParameterDefinitionList) + { + if (conditionParameterDefinition.getParameterName().getValue().equals(conditionSegment.getConditionParameterName().getValue())) + { + conditionHasDefined = true; + if (conditionSegment.getConditionParameterMatchPattern() != null) + { + if (conditionParameterDefinition.getParameterMatchPatterns() != null) + { + List conditionParameterMatchPatterns = conditionParameterDefinition.getParameterMatchPatterns().getParameterMatchPattern(); + if (conditionParameterMatchPatterns != null) + { + Boolean matchpatternexist = false; + for (ParameterMatchPatterns.ParameterMatchPattern parameterMatchPattern : conditionParameterMatchPatterns) + { + if (parameterMatchPattern.getIntValue() == conditionSegment.getConditionParameterMatchPattern().getIntValue()) + { + matchpatternexist = true; + break; + } + } + if (!matchpatternexist) + { + errorInfo = "The match pattern has not defined in the condition."; + } + } + else + { + errorInfo = "There are no match pattern in match pattrn list."; + break; + } + } + else + { + errorInfo = "No match patterns have been defined in data store."; + break; + } + } + if (conditionSegment.getConditionParameterTargetValue() != null) + { + if (conditionParameterDefinition.getParameterValueType() != null) + { + ConditionParameterTargetValue conditionParameterTargetValue = conditionSegment.getConditionParameterTargetValue(); + ConditionParameterDefinition.ParameterValueType parameterValueType = conditionParameterDefinition.getParameterValueType(); + + if (parameterValueType.getIntValue() == 0 && !(conditionParameterTargetValue.getIntValue() == null && conditionParameterTargetValue.getStringValue() != null && conditionParameterTargetValue.getRangeValue() == null)) { + errorInfo = "The value type of" + conditionSegment.getConditionParameterName().toString() + "should be string."; + break; + } + if (parameterValueType.getIntValue() == 1 && !(conditionParameterTargetValue.getIntValue() != null && conditionParameterTargetValue.getStringValue() == null && conditionParameterTargetValue.getRangeValue() == null)) { + errorInfo = "The value type of" + conditionSegment.getConditionParameterName().toString() + "should be integer."; + break; + } + if (parameterValueType.getIntValue() == 2 && !(conditionParameterTargetValue.getIntValue() == null && conditionParameterTargetValue.getStringValue() == null && conditionParameterTargetValue.getRangeValue() != null)) { + errorInfo = "The value type of" + conditionSegment.getConditionParameterName().toString() + "should be range."; + break; + } + + } + } + } + } + } + } + } + + if (!conditionHasDefined) + { + errorInfo = "This condition has not been defined in data store."; + } + return errorInfo; + } + + private void fetchActionDefinitions() + { + InstanceIdentifier actiondefinitionId = InstanceIdentifier.builder(ActionDefinitions.class).build(); + ListenableFuture> actiondefinitionFuture = dataBroker.newReadOnlyTransaction().read(LogicalDatastoreType.CONFIGURATION, actiondefinitionId); + Futures.addCallback(actiondefinitionFuture, new FutureCallback>() { + @Override + public void onSuccess(Optional result) { + setActionDefinitionList( result.get().getActionDefinition()); + return; + } + + @Override + public void onFailure(Throwable t) { + LOG.error("Can not read action definition information.", t); + + return; + } + }); + return ; + } + + private void fetchConditionParaDefinitions() + { + InstanceIdentifier conditionparadefinitionId = InstanceIdentifier.builder(ConditionParameterDefinitions.class).build(); + ListenableFuture> conditionparadefinitionFuture = dataBroker.newReadOnlyTransaction().read(LogicalDatastoreType.CONFIGURATION, conditionparadefinitionId); + Futures.addCallback(conditionparadefinitionFuture, new FutureCallback>() { + @Override + public void onSuccess(Optional result) { + setConditionParameterDefinitionList( result.get().getConditionParameterDefinition()); + return; + } + + @Override + public void onFailure(Throwable t) { + LOG.error("Can not read condition parameter definition information.", t); + return; + } + }); + return ; + } + + private void setActionDefinitionList(List actionDefinitionList) + { + this.actionDefinitionList = actionDefinitionList; + } + + private void setConditionParameterDefinitionList(List conditionParameterDefinitionList) + { + this.conditionParameterDefinitionList = conditionParameterDefinitionList; + } +} diff --git a/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/syntaxcheck/ResultDefinitionCheck.java b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/syntaxcheck/ResultDefinitionCheck.java new file mode 100644 index 0000000..9249304 --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/nemo/user/vnspacemanager/syntaxcheck/ResultDefinitionCheck.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.nemo.user.vnspacemanager.syntaxcheck; + +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.Results; + +/** + * Created by z00293636 on 2015/9/2. + */ +public class ResultDefinitionCheck { + + public String CheckDefinition(Results results) + { + return null; + } +} diff --git a/nemo-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/nemo/engine/impl/rev151010/NemoEngineModule.java b/nemo-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/nemo/engine/impl/rev151010/NemoEngineModule.java new file mode 100644 index 0000000..2442f1c --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/nemo/engine/impl/rev151010/NemoEngineModule.java @@ -0,0 +1,54 @@ +package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.impl.rev151010; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry; +import org.opendaylight.nemo.intent.IntentResolver; +import org.opendaylight.nemo.user.UserManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class NemoEngineModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.impl.rev151010.AbstractNemoEngineModule { + private static final Logger LOG = LoggerFactory.getLogger(NemoEngineModule.class); + + public NemoEngineModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { + super(identifier, dependencyResolver); + } + + public NemoEngineModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, NemoEngineModule oldModule, AutoCloseable oldInstance) { + super(identifier, dependencyResolver, oldModule, oldInstance); + } + + @Override + public void customValidation() { + // add custom validation form module attributes here. + } + + @Override + public AutoCloseable createInstance() { + DataBroker dataBroker = getDataBrokerDependency(); + RpcProviderRegistry rpcProviderRegistry = getRpcRegistryDependency(); + + final IntentResolver intentResolver = new IntentResolver(dataBroker); + final UserManager userManager = new UserManager(dataBroker, rpcProviderRegistry, intentResolver); + + final class NemoEngine implements AutoCloseable { + @Override + public void close() throws Exception { + if ( null != intentResolver ) { + intentResolver.close(); + } + + if ( null != userManager ) { + userManager.close(); + } + + return; + } + } + + LOG.info("Initialized the NEMO engine."); + + return new NemoEngine(); + } + +} diff --git a/nemo-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/nemo/engine/impl/rev151010/NemoEngineModuleFactory.java b/nemo-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/nemo/engine/impl/rev151010/NemoEngineModuleFactory.java new file mode 100644 index 0000000..225c3e1 --- /dev/null +++ b/nemo-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/nemo/engine/impl/rev151010/NemoEngineModuleFactory.java @@ -0,0 +1,13 @@ +/* +* Generated file +* +* Generated from: yang module name: nemo-engine-impl yang module local name: nemo-engine-impl +* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator +* Generated at: Wed Sep 02 22:15:04 CST 2015 +* +* Do not modify this file unless it is present under src/main directory +*/ +package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.impl.rev151010; +public class NemoEngineModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.impl.rev151010.AbstractNemoEngineModuleFactory { + +} diff --git a/nemo-impl/src/main/resources/etc/opendaylight/karaf/config.xml b/nemo-impl/src/main/resources/etc/opendaylight/karaf/config.xml new file mode 100644 index 0000000..e73272c --- /dev/null +++ b/nemo-impl/src/main/resources/etc/opendaylight/karaf/config.xml @@ -0,0 +1,29 @@ + + + + + + + + prefix:nemo-engine-impl + nemo-engine-impl + + binding:binding-async-data-broker + binding-data-broker + + + binding:binding-rpc-registry + binding-rpc-broker + + + + + + + + \ No newline at end of file diff --git a/nemo-impl/src/main/resources/nemo-odl.py b/nemo-impl/src/main/resources/nemo-odl.py new file mode 100644 index 0000000..2c32cbd --- /dev/null +++ b/nemo-impl/src/main/resources/nemo-odl.py @@ -0,0 +1,384 @@ +#!/usr/bin/python +#Filename:nemo-odl.py +import requests,json +import argparse, sys +from requests.auth import HTTPBasicAuth + +USERNAME='admin' +PASSWORD='admin' + +PREDEFINE_USERROLE="http://%s:8181/restconf/config/nemo-user:user-roles/" +PREDEFINE_NODETYPE="http://%s:8181/restconf/config/nemo-object:node-definitions/" +PREDEFINE_CONNECTIONTYPE="http://%s:8181/restconf/config/nemo-object:connection-definitions/" +PREDEFINE_FLOWMATCHTYPE="http://%s:8181/restconf/config/nemo-object:match-item-definitions/" +PREDEFINE_FLOWPROPERTY="http://%s:8181/restconf/config/nemo-object:flow-property-definitions/" +PREDEFINE_OPERATIONACTION="http://%s:8181/restconf/config/nemo-operation:action-definitions/" +PREDEFINE_OPERATIONCONDITION="http://%s:8181/restconf/config/nemo-operation:condition-parameter-definitions/" +PHYSICAL_PORT_ATTRIBUTE="http://%s:8181/restconf/config/generic-physical-network:physical-port-attribute-definitions/" +PHYSICAL_NODE_ATTRIBUTE="http://%s:8181/restconf/config/generic-physical-network:physical-node-attribute-definitions/" + + + +def add_predefined_userrole(contHost): + data={ + "user-roles": { + "user-role": [ + { + "role-name": "tenant", + "role-description": "It's a non-administor user" + } + ] + } + } + put(PREDEFINE_USERROLE % contHost, data) + +def add_predefined_nodetypes(contHost): + data={ + "node-definitions": { + "node-definition": [ + { + "node-type": "host", + "property-definition": [ + { + "property-name": "name", + "property-value-type": "string" + }, + { + "property-name": "location", + "property-value-type": "string" + }, + { + #For example, one legal mac-address is 00:01:0a:90:78:02. + "property-name": "mac-address", + "property-value-type": "string" + }, + { + #For example, one legal ip-address is 10.0.2.0/24. + "property-name": "ip-address", + "property-value-type": "string" + } + ] + }, + { + "node-type": "l2-group", + "property-definition": [ + { + #For example, one legal ip-address is 10.0.2.0/24. + "property-name": "ip-prefix", + "property-value-type": "string" + }, + { + #For example, one legal gateway-ip is 10.0.2.1. + "property-name": "gateway-ip", + "property-value-type": "string" + }, + { + "property-name": "location", + "property-value-type": "string" + } + ] + }, + { + "node-type": "l3-group", + "property-definition": [ + { + #For example, one legal ip-address is 10.0.2.0/24. + "property-name": "ip-prefix", + "property-value-type": "string" + } + ] + }, + { + "node-type": "ext-group", + "property-definition": [ + { + "property-name": "location", + "property-value-type": "string", + "is-required": "required" + }, + { + "property-name": "ac-info-network", + "property-value-type": "string", + "is-required": "required" + }, + { + "property-name": "ac-info-protocol", + "property-value-type": "string", + "is-required": "required" + }, + { + "property-name": "ip-prefix", + "property-value-type": "string" + } + ] + }, + { + "node-type": "chain-group" + }, + { + "node-type": "fw", + "property-definition": [ + { + "property-name": "location", + "property-value-type": "string", + "is-required": "required" + }, + { + "property-name": "operating-mode", + "property-value-type": "string", + "is-required": "required" + } + ] + }, + { + "node-type": "lb", + "property-definition": [ + { + "property-name": "location", + "property-value-type": "string", + "is-required": "required" + }, + { + "property-name": "operating-mode", + "property-value-type": "string", + "is-required": "required" + } + ] + }, + { + "node-type": "cache", + "property-definition": [ + { + "property-name": "location", + "property-value-type": "string", + "is-required": "required" + }, + { + "property-name": "operating-mode", + "property-value-type": "string", + "is-required": "required" + } + ] + } + ] + } + } + put(PREDEFINE_NODETYPE % contHost, data) + +def add_predefined_connectiontypes(contHost): + data={ + "connection-definitions": { + "connection-definition":[ + { + "connection-type": "p2p", + "property-definition": [ + { + #the unit of bandwidth is mbps. + "property-name": "bandwidth", + "property-value-type": "int" + } + ] + }, + { + "connection-type": "p2mp", + "property-definition": [ + { + #the unit of bandwidth is mbps. + "property-name": "bandwidth", + "property-value-type": "int" + } + ] + }, + { + "connection-type": "mesh", + "property-definition": [ + { + #the unit of bandwidth is mbps. + "property-name": "bandwidth", + "property-value-type": "int" + } + ] + }, + { + "connection-type": "chain", + "property-definition": [ + { + #the unit of bandwidth is mbps. + "property-name": "bandwidth", + "property-value-type": "int" + } + ] + } + ] + } + } + put(PREDEFINE_CONNECTIONTYPE % contHost, data) + +def add_flow_matchtypes(contHost): + data={ + "match-item-definitions": { + "match-item-definition": [ + { + #For example, one legal eth-type is arp. + "match-item-name": "eth-type", + "match-item-value-type": "string" + }, + { + #For example, one legal src-mac is 00:00:0a:b7:01:90; + "match-item-name": "src-mac", + "match-item-value-type": "string" + }, + { + #For example, one legal src-mac is 00:00:0a:b7:01:90; + "match-item-name": "dst-mac", + "match-item-value-type": "string" + }, + { + #For example, one legal proto is http; + "match-item-name": "proto", + "match-item-value-type": "string" + }, + { + #For example, one legal src-ip is 10.0.2.1; + "match-item-name": "src-ip", + "match-item-value-type": "string" + }, + { + #For example, one legal dst-ip is 10.0.1.2; + "match-item-name": "dst-ip", + "match-item-value-type": "string" + }, + { + #For example, one legal src-port is 80; + "match-item-name": "src-port", + "match-item-value-type": "int" + }, + { + #For example, one legal dst-port is 22; + "match-item-name": "dst-port", + "match-item-value-type": "int" + } + ] + } + } + put(PREDEFINE_FLOWMATCHTYPE % contHost, data) + +def add_flow_properties(contHost): + data={ + "flow-property-definitions": { + "property-definition": [ + { + "property-name": "path", + "property-value-type": "string" + } + ] + } + } + put(PREDEFINE_FLOWPROPERTY % contHost, data) + +def add_operation_actions(contHost): + data={ + "action-definitions": { + "action-definition": [ + { + "action-name": "deny" + }, + { + "action-name": "allow" + }, + { + "action-name": "go-through", + "parameter-value-type": "string" + }, + { + "action-name": "qos-bandwidth", + "parameter-value-type": "int" + } + ] + } + } + put(PREDEFINE_OPERATIONACTION % contHost, data) + +def add_operation_conditions(contHost): + data={ + "condition-parameter-definitions": { + "condition-parameter-definition": [ + { + "parameter-name": "time", + "parameter-value-type": "string", + "parameter-match-patterns": { + "parameter-match-pattern": ["less-than" ,"not-less-than","equal","not-equal", + "greater-than","not-greater-than","between","periodical"] + } } + ] + } + } + put(PREDEFINE_OPERATIONCONDITION % contHost, data) + +def add_port_attributes(conHost): + data={ + "physical-port-attribute-definitions":{ + "physical-port-attribute-definition":[ + { + "attribute-name":"location", + "attribute-value-type":"string", + "attribute-match-patterns":{ + "attribute-match-pattern":["equal"] + } + } + ] + } + } + put(PHYSICAL_PORT_ATTRIBUTE % conHost, data) + +def add_node_attributes(conHost): + data={ + "physical-node-attribute-definitions":{ + "physical-node-attribute-definition":[ + { + "attribute-name":"location", + "attribute-value-type":"string", + "attribute-match-patterns":{ + "attribute-match-pattern":["equal"] + } + }, + { + "attribute-name":"capacity", + "attribute-value-type":"int", + "attribute-match-patterns":{ + "attribute-match-pattern":["equal"] + } + } + ] + } + } + put(PHYSICAL_NODE_ATTRIBUTE % conHost, data) + + + +def put(url, data): + headers = {'Content-type': 'application/yang.data+json', + 'Accept': 'application/yang.data+json'} + print "PUT %s" % url + print json.dumps(data, indent=4, sort_keys=True) + r = requests.put(url, data=json.dumps(data), headers=headers, auth=HTTPBasicAuth(USERNAME, PASSWORD)) + print r.text + r.raise_for_status() + +if __name__ == '__main__': + + parser = argparse.ArgumentParser() + parser.add_argument('--controller', default='127.0.0.1', help='controller IP') + args=parser.parse_args() + + print args.controller + + add_predefined_userrole(args.controller) + add_predefined_nodetypes(args.controller) + add_predefined_connectiontypes(args.controller) + add_flow_matchtypes(args.controller) + add_flow_properties(args.controller) + add_operation_actions(args.controller) + add_operation_conditions(args.controller) + add_port_attributes(args.controller) + add_node_attributes(args.controller) diff --git a/nemo-impl/src/main/yang/generic-physical-network.yang b/nemo-impl/src/main/yang/generic-physical-network.yang new file mode 100644 index 0000000..64d43ea --- /dev/null +++ b/nemo-impl/src/main/yang/generic-physical-network.yang @@ -0,0 +1,443 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +module generic-physical-network { + yang-version 1; + + namespace "urn:opendaylight:params:xml:ns:yang:generic:physical:network"; + prefix "generic-pn"; + + import nemo-engine-common {prefix nemo-engine-common;} + import ietf-inet-types { + prefix inet; + revision-date 2010-09-24; + } + import ietf-yang-types { + prefix yang; + revision-date 2010-09-24; + } + + description + "Represents the generic physical network information model. + Each renderer will collect detailed physical network information + and fill in this generic model."; + + revision "2015-10-10" { + description + "Initial revision."; + } + + grouping attribute-definition { + description + "Defines an attribute for a physical port or node."; + + leaf attribute-name { + description + "A name for the attribute."; + type nemo-engine-common:attribute-name; + mandatory true; + } + + leaf attribute-value-type { + description + "The value type for the attribute."; + type enumeration { + enum string; + enum int; + enum range; + } + } + + container attribute-match-patterns { + description + "Defines the match patterns of the attribute."; + + leaf-list attribute-match-pattern { + type enumeration { + enum less-than; + enum not-less-than; + enum equal; + enum not-equal; + enum greater-than; + enum not-greater-than; + enum between; + } + } + } + } + + container physical-port-attribute-definitions { + description + "Contains all attribute definitions for the physical port."; + + list physical-port-attribute-definition { + description + "An attribute definition for the physical port."; + + key "attribute-name"; + uses attribute-definition; + } + } + + container physical-node-attribute-definitions { + description + "Contains all attribute definitions for the physical node."; + + list physical-node-attribute-definition { + description + "An attribute definition for the physical node."; + + key "attribute-name"; + uses attribute-definition; + } + } + + grouping attribute-instance { + description + "Represents an attribute instance and it's metadata."; + + leaf attribute-name { + description + "A name for an attribute instance."; + type nemo-engine-common:attribute-name; + mandatory true; + } + + container attribute-value { + description + "The value of the attribute instance."; + + leaf string-value { + type string; + } + + leaf int-value { + type int64; + } + + container range-value { + leaf min { + type int64; + mandatory true; + } + + leaf max { + type int64; + mandatory true; + } + } + } + } + + grouping physical-port-instance { + description + "Represents a physical port instance and it's metadata."; + + leaf port-id { + description + "A unique ID for a physical port."; + type nemo-engine-common:physical-port-id; + mandatory true; + } + + leaf port-type { + description + "The type of a physical port."; + type enumeration { + enum external { + description + "The physical port is connected to a external host + or network device."; + } + enum internal { + description + "The physical port is connected to a physical node."; + } + } + mandatory true; + } + + leaf mac-address { + description + "The mac address of a physical port."; + type yang:mac-address; + mandatory true; + } + + leaf bandwidth { + description + "The bandwidth capacity of a physical port. + The unit is kbps."; + type uint32; + units kbps; + } + + list attribute { + description + "The list of attributes of a physical port."; + + key "attribute-name"; + uses attribute-instance; + } + } + + grouping physical-node-instance { + description + "Represents a physical node instance and it's metadata."; + + leaf node-id { + description + "A unique ID for a physical node."; + type nemo-engine-common:physical-node-id; + mandatory true; + } + + leaf node-type { + description + "The type of a physical node."; + type enumeration { + enum switch; + enum router; + enum firewall; + enum loadbalancer; + } + } + + list physical-port { + description + "The list of ports of a physical node."; + + key "port-id"; + uses physical-port-instance; + } + + list attribute { + description + "The list of attributes of a physical node."; + + key "attribute-name"; + uses attribute-instance; + } + } + + grouping physical-link-instance { + description + "Represents a physical link instance and it's metadata."; + + leaf link-id { + description + "A unique ID for a physical link."; + type nemo-engine-common:physical-link-id; + mandatory true; + } + + leaf src-node-id { + description + "Represents the ID of the source physical node."; + type nemo-engine-common:physical-node-id; + } + + leaf src-port-id { + description + "Represents the ID of the source physical port."; + type nemo-engine-common:physical-port-id; + } + + leaf dest-node-id { + description + "Represents the ID of the destination physical node."; + type nemo-engine-common:physical-node-id; + } + + leaf dest-port-id { + description + "Represents the ID of the destination physical port."; + type nemo-engine-common:physical-port-id; + } + + leaf metric { + description + "The routing metric is used by routing computation."; + type uint32; + } + + leaf bandwidth { + description + "The bandwidth capacity of a physical link. + The unit is kbps."; + type uint32; + units kbps; + } + + leaf delay { + description + "The packet transfer delay of a physical link. + The unit is millisecond."; + type uint32; + units millisecond; + } + + leaf loss-rate { + description + "The ratio of total lost packet outcomes to + total transmitted packets. The unit is percent."; + type uint8 { + range "0..100"; + } + units percent; + } + } + + grouping physical-host-instance { + description + "Represents a physical host instance and it's metadata."; + + leaf host-id { + description + "A unique ID for a physical host."; + type nemo-engine-common:physical-host-id; + mandatory true; + } + + leaf host-name { + description + "A human-readable name for a physical host."; + type nemo-engine-common:physical-host-name; + } + + leaf mac-address { + description + "The mac address of the host."; + type yang:mac-address; + mandatory true; + } + + container ip-addresses { + description + "One or more ip addresses of the host."; + + leaf-list ip-address { + type inet:ip-address; + min-elements 1; + } + } + + leaf node-id { + description + "A unique ID for the physical node that the host connects to."; + type nemo-engine-common:physical-node-id; + mandatory true; + } + + leaf port-id { + description + "A unique ID for the physical port that the host connects to."; + type nemo-engine-common:physical-port-id; + mandatory true; + } + } + + grouping physical-path-instance { + description + "Represents a physical tunnel instance and it's metadata."; + + leaf path-id { + description + "A unique ID for a physical path."; + type nemo-engine-common:physical-path-id; + mandatory true; + } + + list physical-link { + description + "A list of physical links which compose the physical path."; + + key "link-id"; + leaf link-id { + description + "A unique ID for the physical link."; + type nemo-engine-common:physical-link-id; + } + + leaf order { + description + "Specify the order of the physical link instance + in a sequence list."; + type uint32; + } + } + + leaf metric { + description + "The routing metric of a physical path."; + type uint32; + } + + leaf bandwidth { + description + "The bandwidth capacity of a physical path. + The unit is kbps."; + type uint32; + units kbps; + } + + leaf delay { + description + "The packet transfer delay of a physical path. + The unit is millisecond."; + type uint32; + units millisecond; + } + } + + container physical-network { + description + "Contains all physical nodes, links and tunnels + in the underlying network."; + + container physical-nodes { + list physical-node { + description + "The list of all physical nodes in the underlying network."; + + key "node-id"; + uses physical-node-instance; + } + } + + container physical-links { + list physical-link { + description + "The list of all physical links in the underlying network."; + + key "link-id"; + uses physical-link-instance; + } + } + + container physical-hosts { + list physical-host { + description + "The list of all physical hosts in the underlying network."; + + key "host-id"; + uses physical-host-instance; + } + } + + container physical-paths { + list physical-path { + description + "The list of all physical tunnels in the underlying network."; + + key "path-id"; + uses physical-path-instance; + } + } + } +} diff --git a/nemo-impl/src/main/yang/generic-virtual-network.yang b/nemo-impl/src/main/yang/generic-virtual-network.yang new file mode 100644 index 0000000..cda628c --- /dev/null +++ b/nemo-impl/src/main/yang/generic-virtual-network.yang @@ -0,0 +1,414 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +module generic-virtual-network { + yang-version 1; + + namespace "urn:opendaylight:params:xml:ns:yang:generic:virtual:network"; + prefix "generic-vn"; + + import nemo-engine-common {prefix nemo-engine-common;} + import generic-physical-network {prefix generic-pn;} + import nemo-common {prefix nemo-common;} + import ietf-inet-types { + prefix inet; + revision-date 2010-09-24; + } + import ietf-yang-types { + prefix yang; + revision-date 2010-09-24; + } + + revision "2015-10-10" { + description + "Initial revision."; + } + + grouping virtual-port-instance { + description + "Represents a virtual port instance and it's metadata."; + + leaf port-id { + description + "A unique ID for a virtual port."; + type nemo-engine-common:virtual-port-id; + mandatory true; + } + + leaf port-type { + description + "The type of a virtual port."; + type enumeration { + enum external { + description + "The virtual port is connected to a external host + or network device."; + } + enum internal { + description + "The virtual port is connected to a virtual node."; + } + } + mandatory true; + } + + leaf bandwidth { + description + "The bandwidth capacity of a virtual port. + The unit is kbps."; + type uint32; + units kbps; + } + + container external-mac-addresses { + description + "A list of external mac addresses in the layer2 network + that connects to the virtual port."; + + leaf-list external-mac-address { + type yang:mac-address; + } + } + + container external-ip-prefixes { + description + "A list of external ip prefixes in the layer3 network + that connects to the virtual port."; + + leaf-list external-ip-prefix { + type inet:ip-prefix; + } + } + + list physical-resource-requirement { + description + "A list of physical port attribute requirements + for selecting physical port resource."; + + key "attribute-name"; + uses generic-pn:attribute-instance; + + leaf attribute-match-pattern { + description + "The match pattern for an attribute instance. + It represents the arithmetic logic."; + type enumeration { + enum less-than; + enum not-less-than; + enum equal; + enum not-equal; + enum greater-than; + enum not-greater-than; + enum between; + } + } + } + } + + grouping virtual-node-instance { + description + "Represents a virtual node instance and it's metadata."; + + leaf node-id { + description + "A unique ID for a virtual node."; + type nemo-engine-common:virtual-node-id; + mandatory true; + } + + leaf node-type { + description + "The type of a virtual node."; + type enumeration { + enum vswitch; + enum vrouter; + enum vfirewall; + enum vloadbalancer; + } + } + + list virtual-port { + description + "A list of ports of a virtual node."; + + key "port-id"; + uses virtual-port-instance; + } + + list physical-resource-requirement { + description + "A list of physical node attribute requirements + for selecting physical node resource."; + + key "attribute-name"; + uses generic-pn:attribute-instance; + + leaf attribute-match-pattern { + description + "The match pattern for an attribute instance. + It represents the arithmetic logic."; + type enumeration { + enum less-than; + enum not-less-than; + enum equal; + enum not-equal; + enum greater-than; + enum not-greater-than; + enum between; + } + } + } + } + + grouping virtual-link-instance { + description + "Represents a virtual link instance and it's metadata."; + + leaf link-id { + description + "A unique ID for a virtual link."; + type nemo-engine-common:virtual-link-id; + mandatory true; + } + + leaf src-node-id { + description + "A unique ID for the source virtual node."; + type nemo-engine-common:virtual-node-id; + } + + leaf src-port-id { + description + "A unique ID for the source virtual port."; + type nemo-engine-common:virtual-port-id; + } + + leaf dest-node-id { + description + "A unique ID for the destination virtual node."; + type nemo-engine-common:virtual-node-id; + } + + leaf dest-port-id { + description + "A unique ID for the destination virtual port."; + type nemo-engine-common:virtual-port-id; + } + + leaf metric { + description + "The routing metric is used by routing computation."; + type uint32; + } + + leaf bandwidth { + description + "The bandwidth capacity of a virtual link. + The unit is kbps."; + type uint32; + units kbps; + } + + leaf delay { + description + "The packet transfer delay of a virtual link. + The unit is millisecond."; + type uint32; + units millisecond; + } + + leaf delay-requirement { + description + "The packet transfer delay requirement which + is specified by the user and used in the virtual + network mapping."; + type uint32; + units millisecond; + } + } + + grouping virtual-path-instance { + description + "Represents a virtual path instance and it's metadata."; + + leaf path-id { + description + "A unique ID for a virtual path."; + type nemo-engine-common:virtual-path-id; + mandatory true; + } + + list virtual-link { + description + "A list of virtual links which compose the virtual path."; + + key "link-id"; + leaf link-id { + description + "A unique ID for the virtual link."; + type nemo-engine-common:virtual-link-id; + } + + leaf order { + description + "Specify the order of the virtual link instance + in a sequence list."; + type uint32; + } + } + + leaf metric { + description + "The routing metric of a virtual path."; + type uint32; + } + + leaf bandwidth { + description + "The bandwidth capacity of a virtual path. + The unit is kbps."; + type uint32; + units kbps; + } + + leaf delay { + description + "The packet transfer delay of a virtual path. + The unit is millisecond."; + type uint32; + units millisecond; + } + } + + grouping virtual-route-instance { + description + "Represents a route instance in the virtual network."; + + leaf src-node-id { + description + "A unique ID for the source virtual node."; + type nemo-engine-common:virtual-node-id; + } + + leaf dest-node-id { + description + "A unique ID for the destination virtual node."; + type nemo-engine-common:virtual-node-id; + } + + leaf path-id { + description + "A unique ID for the virtual path."; + type nemo-engine-common:virtual-path-id; + } + } + + grouping virtual-arp-instance { + description + "Represents a arp instance in the virtual network."; + + leaf ip-address { + description + "Represents the ip address for an ARP entry."; + type inet:ip-address; + } + + leaf mac-address { + description + "Represents the mac address for an ARP entry."; + type yang:mac-address; + } + + leaf node-id { + description + "A unique ID for the virtual node that connects to + the host corresponding to the ARP entry."; + type nemo-engine-common:virtual-node-id; + } + + leaf port-id { + description + "A unique ID for the virtual port that connects to + the host corresponding to the ARP entry."; + type nemo-engine-common:virtual-port-id; + } + } + + container virtual-networks { + description + "Contains all virtual networks that the NEMO engine maintains."; + + list virtual-network { + description + "A virtual network which a user created."; + + key "network-id"; + leaf network-id { + description + "A unique ID for a virtual network."; + type nemo-engine-common:virtual-network-id; + } + + leaf user-id { + description + "The user ID for the virtual network."; + type nemo-common:user-id; + } + + container virtual-nodes { + list virtual-node { + description + "All virtual nodes in the virtual network."; + + key "node-id"; + uses virtual-node-instance; + } + } + + container virtual-links { + list virtual-link { + description + "All virtual links in the virtual network."; + + key "link-id"; + uses virtual-link-instance; + } + } + + container virtual-paths { + list virtual-path { + description + "All virtual paths in the virtual network."; + + key "path-id"; + uses virtual-path-instance; + } + } + + container virtual-routes { + list virtual-route { + description + "All virtual routes in the virtual network."; + + key "src-node-id dest-node-id"; + uses virtual-route-instance; + } + } + + container virtual-arps { + list virtual-arp { + description + "All virtual ARP entries in the virtual network."; + + key "ip-address"; + uses virtual-arp-instance; + } + } + } + } +} diff --git a/nemo-impl/src/main/yang/intent-mapping-result.yang b/nemo-impl/src/main/yang/intent-mapping-result.yang new file mode 100644 index 0000000..d9fa4b7 --- /dev/null +++ b/nemo-impl/src/main/yang/intent-mapping-result.yang @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +module intent-mapping-result { + yang-version 1; + + namespace "urn:opendaylight:params:xml:ns:yang:intent:mapping:result"; + prefix "intent-mapping-result"; + + import nemo-engine-common {prefix nemo-engine-common;} + import nemo-common {prefix nemo-common;} + + revision "2015-10-10" { + description + "Initial revision."; + } + + grouping virtual-resource-instance { + description + "Represents the abstract entity of the virtual resource, + which can be a vport, vnode, vlink or vpath."; + + leaf virtual-resource-id { + description + "A unique ID for a virtual resource."; + type nemo-engine-common:virtual-resource-id; + mandatory true; + } + + leaf virtual-resource-type { + description + "The type of the virtual resource."; + type enumeration { + enum vport; + enum vnode; + enum vlink; + enum vpath; + } + } + + leaf virtual-resource-entity-id { + description + "A unique ID for the entity corresponding to + the virtual resource."; + type nemo-engine-common:virtual-resource-entity-id; + } + + leaf parent-virtual-resource-entity-id { + description + "A unique ID for the parent entity corresponding + to the virtual resource. If the resource entity + is a virtual port, it's parent entity is the + virtual node which it belongs to."; + type nemo-engine-common:virtual-resource-entity-id; + } + } + + grouping physical-resource-instance { + description + "Represents the abstract entity of the physical resource, + which can be a port, node or path."; + + leaf physical-resource-id { + description + "A unique ID for a physical resource."; + type nemo-engine-common:physical-resource-id; + mandatory true; + } + + leaf physical-resource-type { + description + "The type of the physical resource."; + type enumeration { + enum port; + enum node; + enum path; + } + } + + leaf physical-resource-entity-id { + description + "A unique ID for the entity corresponding to + the physical resource."; + type nemo-engine-common:physical-resource-entity-id; + } + + leaf parent-physical-resource-entity-id { + description + "A unique ID for the parent entity corresponding + to the physical resource. If the resource entity + is a physical port, it's parent entity is the + physical node which it belongs to."; + type nemo-engine-common:physical-resource-entity-id; + } + } + + container intent-vn-mapping-results { + description + "Contains the intent-vn mapping results of all users."; + + list user-intent-vn-mapping { + description + "Represents the intent-vn mapping results of a user."; + + key "user-id"; + leaf user-id { + description + "The user id for the intents that are mapped to + the virtual resource."; + type nemo-common:user-id; + } + + leaf virtual-network-id { + description + "The virtual network id of the user."; + type nemo-engine-common:virtual-network-id; + } + + list intent-vn-mapping-result { + description + "Represents a intent-vn mapping result of the user."; + + key "intent-id"; + leaf intent-id { + description + "A unique ID for the user intent."; + type nemo-common:intent-id; + } + + leaf intent-type { + description + "The type of the user intent."; + type enumeration { + enum node; + enum connection; + enum operation; + } + } + + list virtual-resource { + description + "The list of virtual resource corresponding to + the user intent."; + + key "virtual-resource-id"; + uses virtual-resource-instance; + + leaf order { + description + "Specify the order of the virtual resource instance + in a sequence list."; + type uint32; + } + } + } + } + } + + container vn-pn-mapping-results { + description + "Contains the vn-pn mapping results of all users."; + + list user-vn-pn-mapping { + description + "Represents the vn-pn mapping results of a user."; + + key "virtual-network-id"; + leaf virtual-network-id { + description + "The virtual network id of the user."; + type nemo-engine-common:virtual-network-id; + } + + leaf user-id { + description + "The user id for the virtual network."; + type nemo-common:user-id; + } + + list vn-pn-mapping-result { + description + "Represents a vn-pn mapping result of the user."; + + key "virtual-resource-entity-id"; + uses virtual-resource-instance; + + uses physical-resource-instance; + } + } + } +} diff --git a/nemo-impl/src/main/yang/intent-processing-status.yang b/nemo-impl/src/main/yang/intent-processing-status.yang new file mode 100644 index 0000000..1110c5b --- /dev/null +++ b/nemo-impl/src/main/yang/intent-processing-status.yang @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +module intent-processing-status { + yang-version 1; + + namespace "urn:opendaylight:params:xml:ns:yang:intent:processing:status"; + prefix "intent-processing-status"; + + import nemo-common {prefix nemo-common;} + + revision "2015-10-10" { + description + "Initial revision."; + } + + grouping intent-status { + leaf status { + description + "Represents the current processing status of the user intent + maintained by the NEMO engine or the user's transaction."; + type enumeration { + enum processing-succeeded { + description + "The user intent has been successfully processed by the + NEMO engine and the underlying network has been configured + by some renderer if necessary, or the user's transaction + has been processed successfully."; + } + enum in-processing { + description + "The user intent is being processed by the NEMO engine, or + some intents in the user's transaction are being processed."; + } + enum processing-failed { + description + "The processing for the user intent by the NEMO engine is + failed, the reason might be syntax error, insufficient + underlying network resources, etc, and is described in + the message in detail. Or the processing for the user's + transaction is failed."; + } + } + config false; + mandatory true; + } + + leaf message { + description + "The human-readable and detailed message about the status."; + type string; + config false; + } + } + + container intent-processing-statuses { + description + "Contains the intent processing statuses of all users + maintained by the NEMO engine."; + + list user-intent-status { + description + "Represents the list of all users with their intent statuses."; + + key "user-id"; + leaf user-id { + description + "The unique ID for the user."; + type nemo-common:user-id; + } + + container transaction-status { + description + "Contains the user's transaction status information. + When all user intents in the transaction have been + successfully processed, the transaction status will + be set to processing-succeeded. If the processing for + some user intents in the transaction is failed, the + transaction status will be set to processing-failed."; + + uses intent-status; + } + + container object-statuses { + description + "Contains all object intent statuses of the user."; + + list node-status { + description + "The list of all node intent statuses of the user."; + + key "node-id"; + leaf node-id { + description + "The unique ID for the node."; + type nemo-common:node-id; + } + + uses intent-status; + config false; + } + + list connection-status { + description + "The list of all connection intent statuses of the user."; + + key "connection-id"; + leaf connection-id { + description + "The unique ID for the connection."; + type nemo-common:connection-id; + } + + uses intent-status; + config false; + } + + list flow-status { + description + "The list of all flow intent statuses of the user."; + + key "flow-id"; + leaf flow-id { + description + "The unique ID for the flow."; + type nemo-common:flow-id; + } + + uses intent-status; + config false; + } + } + + container operation-statuses { + description + "Contains all operation intent statuses of the user."; + + list operation-status { + description + "The list of all operation intent statuses of the user."; + + key "operation-id"; + leaf operation-id { + description + "The unique ID for the operation."; + type nemo-common:operation-id; + } + + uses intent-status; + config false; + } + } + + container result-statuses { + // TBD + } + } + } +} diff --git a/nemo-impl/src/main/yang/nemo-engine-common.yang b/nemo-impl/src/main/yang/nemo-engine-common.yang new file mode 100644 index 0000000..a893845 --- /dev/null +++ b/nemo-impl/src/main/yang/nemo-engine-common.yang @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +module nemo-engine-common { + yang-version 1; + + namespace "urn:opendaylight:params:xml:ns:yang:nemo:engine:common"; + prefix "nemo-engine-common"; + + revision "2015-10-10" { + description + "Initial revision."; + } + + // ********************* + // * Base Types + // ********************* + typedef name { + description + "A generic string name type. Must start with a letter"; + type string { + pattern '[a-zA-Z]([a-zA-Z0-9\-_.])*'; + length "1..256"; + } + } + + // UUID type from ietf-yang-types@2013-07-15 + typedef uuid { + type string { + pattern '[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-' + + '[0-9a-fA-F]{4}-[0-9a-fA-F]{12}'; + } + description + "A Universally Unique IDentifier in the string representation + defined in RFC 4122. The canonical representation uses + lower case characters. + + The following is an example of a UUID in string + representation: f81d4fae-7dec-11d0-a765-00a0c91e6bf6"; + reference + "RFC 4122: A Universally Unique IDentifier (UUID) URN + Namespace"; + } + + typedef unique-id { + description + "A globally unique identifier."; + type uuid; + } + + // ********************* + // * Unique IDs + // ********************* + typedef physical-port-id { + description + "A unique ID for a physical port."; + type string; + } + + typedef physical-node-id { + description + "A unique ID for a physical node."; + type string; + } + + typedef physical-link-id { + description + "A unique ID for a physical link."; + type string; + } + + typedef physical-host-id { + description + "A unique ID for a physical host."; + type unique-id; + } + + typedef physical-path-id { + description + "A unique ID for a physical path."; + type unique-id; + } + + typedef virtual-port-id { + description + "A unique ID for a virtual port."; + type unique-id; + } + + typedef virtual-node-id { + description + "A unique ID for a virtual node."; + type unique-id; + } + + typedef virtual-link-id { + description + "A unique ID for a virtual link."; + type unique-id; + } + + typedef virtual-path-id { + description + "A unique ID for a virtual path."; + type unique-id; + } + + typedef virtual-network-id { + description + "A unique ID for a virtual network."; + type unique-id; + } + + typedef virtual-resource-id { + description + "A unique ID for the virtual resource."; + type unique-id; + } + + typedef virtual-resource-entity-id { + description + "A unique ID for a virtual resource entity."; + type unique-id; + } + + typedef physical-resource-id { + description + "A unique ID for the physical resource."; + type unique-id; + } + + typedef physical-resource-entity-id { + description + "A unique ID for a physical resource entity."; + type string; + } + + // ********************* + // * Names + // ********************* + typedef attribute-name { + description + "A name for a physical port or node attribute."; + type name; + } + + typedef physical-host-name { + description + "A name for a physical host."; + type name; + } +} diff --git a/nemo-impl/src/main/yang/nemo-engine-impl.yang b/nemo-impl/src/main/yang/nemo-engine-impl.yang new file mode 100644 index 0000000..395c0f2 --- /dev/null +++ b/nemo-impl/src/main/yang/nemo-engine-impl.yang @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +module nemo-engine-impl { + yang-version 1; + + namespace "urn:opendaylight:params:xml:ns:yang:nemo:engine:impl"; + prefix "nemo-engine-impl"; + + import config { prefix config; revision-date 2013-04-05; } + import opendaylight-md-sal-binding { prefix mdsal; revision-date 2013-10-28; } + + description + "This module contains the base YANG definitions for + NEMO engine implementation."; + + revision "2015-10-10" { + description + "Initial revision."; + } + + identity nemo-engine-impl { + base config:module-type; + config:java-name-prefix NemoEngine; + } + + augment "/config:modules/config:module/config:configuration" { + case nemo-engine-impl { + when "/config:modules/config:module/config:type = 'nemo-engine-impl'"; + + container data-broker { + uses config:service-ref { + refine type { + mandatory false; + config:required-identity mdsal:binding-async-data-broker; + } + } + } + container rpc-registry { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity mdsal:binding-rpc-registry; + } + } + } + } + } +} diff --git a/nemo-impl/src/test/java/README b/nemo-impl/src/test/java/README deleted file mode 100644 index e69de29..0000000 diff --git a/nemo-impl/src/test/resources/bod-1.py b/nemo-impl/src/test/resources/bod-1.py new file mode 100644 index 0000000..0536aab --- /dev/null +++ b/nemo-impl/src/test/resources/bod-1.py @@ -0,0 +1,613 @@ +#!/usr/bin/python +#Filename:servicechain.py +import requests,json +import argparse, sys +from requests.auth import HTTPBasicAuth + +USERNAME='admin' +PASSWORD='admin' + +TRANSACTION_BEGIN="http://%s:8181/restconf/operations/nemo-intent:begin-transaction" +TRANSACTION_END="http://%s:8181/restconf/operations/nemo-intent:end-transaction" +REGISTER_USER="http://%s:8181/restconf/operations/nemo-intent:register-user" +STRUCTURE_UPDATE_USERS="http://%s:8181/restconf/operations/nemo-intent:structure-style-nemo-update" + +def register_user(contHost): + data={ + "input":{ + "user-id":"14ce424a-3e50-4a2a-ad5c-b29845158c8b", + "user-name":"user2", + "user-password":"abc", + "user-role":"tenant" + } + } + post(REGISTER_USER % contHost, data) + +def transaction_begin(contHost): + data={ + "input":{ + "user-id":"14ce424a-3e50-4a2a-ad5c-b29845158c8b", + "user-name":"user2", + "user-password":"abc", + "user-role":"tenant" + } + } + post(TRANSACTION_BEGIN % contHost, data) + +def transaction_end(contHost): + data={ + "input":{ + "user-id":"14ce424a-3e50-4a2a-ad5c-b29845158c8b", + "user-name":"user2", + "user-password":"abc", + "user-role":"tenant" + } + } + post(TRANSACTION_END % contHost, data) + +def add_server1_host(contHost): + data={ + "input":{ + "user-name": "user2", + "user-role": "tenant", + "user-password": "abc", + "user-id": "14ce424a-3e50-4a2a-ad5c-b29845158c8b", + "objects":{ + "node":[ + { + "node-name": "server1", + "node-type": "host", + "node-id":"7b796915-adf4-4356-b5ca-de005ac410c1" + } + ] + } + } + } + post(STRUCTURE_UPDATE_USERS % contHost, data) + +def add_server2_host(contHost): + data={ + "input":{ + "user-name": "user2", + "user-role": "tenant", + "user-password": "abc", + "user-id": "14ce424a-3e50-4a2a-ad5c-b29845158c8b", + "objects":{ + "node":[ + { + "node-name": "server2", + "node-type": "host", + "node-id":"22282cca-9a13-4d0c-a67e-a933ebb0b0ae" + } + ] + } + } + } + post(STRUCTURE_UPDATE_USERS % contHost, data) + +def add_vm1_host(contHost): + data={ + "input":{ + "user-name": "user2", + "user-role": "tenant", + "user-password": "abc", + "user-id": "14ce424a-3e50-4a2a-ad5c-b29845158c8b", + "objects":{ + "node":[ + { + "node-name": "vm1", + "node-type": "host", + "node-id":"1eaf9a67-a171-42a8-9282-71cf702f61dd" + } + ] + } + } + } + post(STRUCTURE_UPDATE_USERS % contHost, data) + +def add_vm2_host(contHost): + data={ + "input":{ + "user-name": "user2", + "user-role": "tenant", + "user-password": "abc", + "user-id": "14ce424a-3e50-4a2a-ad5c-b29845158c8b", + "objects":{ + "node":[ + { + "node-name": "vm2", + "node-type": "host", + "node-id":"6c787caa-156a-49ed-8546-547bdccf283c" + } + ] + } + } + } + post(STRUCTURE_UPDATE_USERS % contHost, data) + +def add_enterpise_node(contHost): + data={ + "input":{ + "user-name": "user2", + "user-role": "tenant", + "user-password": "abc", + "user-id": "14ce424a-3e50-4a2a-ad5c-b29845158c8b", + "objects":{ + "node":[ + { + "node-name": "enterprise", + "node-type": "ext-group", + "property": [ + { + "property-name": "location", + "property-values": { + "string-value": [ + { + "order": "0", + "value": "openflow:4:2" + } + ] + } + }, + { + "property-name": "ac-info-network", + "property-values": { + "string-value": [ + { + "order": "0", + "value": "layer3" + } + ] + } + }, + { + "property-name": "ac-info-protocol", + "property-values": { + "string-value": [ + { + "order": "0", + "value": "static" + } + ] + } + }, + { + "property-name": "ip-prefix", + "property-values": { + "string-value": [ + { + "order": "0", + "value": "192.168.13.0/24" + } + ] + } + } + ], + "node-id": "94a6fb90-b425-4ffd-9515-c0684aa4c37f" + } + ] + } + } + } + post(STRUCTURE_UPDATE_USERS % contHost, data) + +def add_internet_node(contHost): + data={ + "input":{ + "user-name": "user2", + "user-role": "tenant", + "user-password": "abc", + "user-id": "14ce424a-3e50-4a2a-ad5c-b29845158c8b", + "objects":{ + "node":[ + { + "node-name": "internet", + "node-type": "ext-group", + "property": [ + { + "property-name": "location", + "property-values": { + "string-value": [ + { + "order": "0", + "value": "openflow:3:4" + } + ] + } + }, + { + "property-name": "ac-info-network", + "property-values": { + "string-value": [ + { + "order": "0", + "value": "layer3" + } + ] + } + }, + { + "property-name": "ac-info-protocol", + "property-values": { + "string-value": [ + { + "order": "0", + "value": "static" + } + ] + } + }, + { + "property-name": "ip-prefix", + "property-values": { + "string-value": [ + { + "order": "0", + #wait for external network ip + "value": "172.168.1.0/24" + } + ] + } + } + ], + "node-id": "d463232f-363f-491c-a6f5-097ed0a794d3" + } + ] + } + } + } + post(STRUCTURE_UPDATE_USERS % contHost, data) + +def add_dmz_node(contHost): + data={ + "input":{ + "user-name": "user2", + "user-role": "tenant", + "user-password": "abc", + "user-id": "14ce424a-3e50-4a2a-ad5c-b29845158c8b", + "objects":{ + "node":[ + { + "node-name": "dmz", + "node-type": "l2-group", + "sub-node": [ + { + "node-id":"7b796915-adf4-4356-b5ca-de005ac410c1", + "order":"0" + } + ], + "property": [ + { + "property-name": "location", + "property-values": { + "string-value": [ + { + "order": "0", + "value": "openflow:3" + } + ] + } + }, + { + "property-name": "ip-prefix", + "property-values": { + "string-value": [ + { + "order": "0", + "value": "192.168.11.0/24" + } + ] + } + }, + { + "property-name": "gateway-ip", + "property-values": { + "string-value": [ + { + "order": "0", + "value": "192.168.11.1" + } + ] + } + } + ], + "node-id": "b46cfa7f-93a3-43f4-ac20-09307c75feca" + } + ] + } + } + } + post(STRUCTURE_UPDATE_USERS % contHost, data) + +def add_interior_node(contHost): + data={ + "input":{ + "user-name": "user2", + "user-role": "tenant", + "user-password": "abc", + "user-id": "14ce424a-3e50-4a2a-ad5c-b29845158c8b", + "objects":{ + "node":[ + { + "node-name": "interior", + "node-type": "l2-group", + "sub-node": [ + { + "node-id":"22282cca-9a13-4d0c-a67e-a933ebb0b0ae", + "order":"0" + }, + { + "node-id":"1eaf9a67-a171-42a8-9282-71cf702f61dd", + "order":"0" + }, + { + "node-id":"6c787caa-156a-49ed-8546-547bdccf283c", + "order":"0" + } + ], + "property": [ + { + "property-name": "location", + "property-values": { + "string-value": [ + { + "order": "0", + "value": "openflow:3" + } + ] + } + }, + { + "property-name": "ip-prefix", + "property-values": { + "string-value": [ + { + "order": "0", + "value": "192.168.12.0/24" + } + ] + } + }, + { + "property-name": "gateway-ip", + "property-values": { + "string-value": [ + { + "order": "0", + "value": "192.168.12.1" + } + ] + } + } + ], + "node-id": "175425f7-c9c9-474a-962c-70cb6c180d4d" + } + ] + } + } + } + post(STRUCTURE_UPDATE_USERS % contHost, data) + +def add_enterprise_interior_connection(contHost): + data={ + "input": { + "user-name": "user2", + "user-role": "tenant", + "user-password": "abc", + "user-id": "14ce424a-3e50-4a2a-ad5c-b29845158c8b", + "objects":{ + "connection": [ + { + "connection-name": "c1", + "connection-id": "30da6667-608e-4d2f-bb50-79e5cabcc523", + "end-node": [ + { + "order": "0", + "node-id": "94a6fb90-b425-4ffd-9515-c0684aa4c37f" + }, + { + "order": "0", + "node-id": "175425f7-c9c9-474a-962c-70cb6c180d4d" + } + ], + "connection-type": "p2p", + "property": [ + { + "property-name": "bandwidth", + "property-values": { + "int-value": [ + { + "order": "0", + "value": "128" + } + ] + } + } + ] + } + ] + } + } + } + post(STRUCTURE_UPDATE_USERS % contHost, data) + +def add_interior_dmz_connection(contHost): + data={ + "input": { + "user-name": "user2", + "user-role": "tenant", + "user-password": "abc", + "user-id": "14ce424a-3e50-4a2a-ad5c-b29845158c8b", + "objects":{ + "connection": [ + { + "connection-name": "c2", + "connection-id": "b49e3960-c08d-4fff-b9fc-08b65ebcde2c", + "end-node": [ + { + "order": "0", + "node-id": "175425f7-c9c9-474a-962c-70cb6c180d4d" + }, + { + "order": "0", + "node-id": "b46cfa7f-93a3-43f4-ac20-09307c75feca" + } + ], + "connection-type": "p2p" + } + ] + } + } + } + post(STRUCTURE_UPDATE_USERS % contHost, data) + +def add_dmz_internet_connection(contHost): + data={ + "input": { + "user-name": "user2", + "user-role": "tenant", + "user-password": "abc", + "user-id": "14ce424a-3e50-4a2a-ad5c-b29845158c8b", + "objects":{ + "connection": [ + { + "connection-name": "c3", + "connection-id": "e0d56fee-7235-4748-a2a1-eb5e3733d866", + "end-node": [ + { + "order": "0", + "node-id": "b46cfa7f-93a3-43f4-ac20-09307c75feca" + }, + { + "order": "0", + "node-id": "d463232f-363f-491c-a6f5-097ed0a794d3" + } + ], + "connection-type": "p2p" + } + ] + } + } + } + post(STRUCTURE_UPDATE_USERS % contHost, data) + +def update_enterprise_interior_connection(contHost): + data={ + "input": { + "user-name": "user2", + "user-role": "tenant", + "user-password": "abc", + "user-id": "14ce424a-3e50-4a2a-ad5c-b29845158c8b", + "objects":{ + "connection": [ + { + "connection-name": "c1", + "connection-id": "30da6667-608e-4d2f-bb50-79e5cabcc523", + "end-node": [ + { + "order": "0", + "node-id": "94a6fb90-b425-4ffd-9515-c0684aa4c37f" + }, + { + "order": "0", + "node-id": "175425f7-c9c9-474a-962c-70cb6c180d4d" + } + ], + "connection-type": "p2p", + "property": [ + { + "property-name": "bandwidth", + "property-values": { + "int-value": [ + { + "order": "0", + "value": "512" + } + ] + } + } + ] + } + ] + } + } + } + post(STRUCTURE_UPDATE_USERS % contHost, data) + +def post(url, data): + headers = {'Content-type': 'application/yang.data+json', + 'Accept': 'application/yang.data+json'} + print "POST %s" % url + print json.dumps(data, indent=4, sort_keys=True) + r = requests.post(url, data=json.dumps(data), headers=headers, auth=HTTPBasicAuth(USERNAME, PASSWORD)) + print r.text + r.raise_for_status() + +if __name__ == '__main__': + + parser = argparse.ArgumentParser() + parser.add_argument('--controller', default='127.0.0.1', help='controller IP') + args=parser.parse_args() + + # CREATE User; + register_user(args.controller) + + # IMPORT Node server1 Type host; + transaction_begin(args.controller) + add_server1_host(args.controller) + #transaction_end(args.controller) + + # IMPORT Node server2 Type host; + #transaction_begin(args.controller) + add_server2_host(args.controller) + #transaction_end(args.controller) + + # IMPORT Node vm1 Type host; + #transaction_begin(args.controller) + add_vm1_host(args.controller) + #transaction_end(args.controller) + + # IMPORT Node vm2 Type host; + #transaction_begin(args.controller) + add_vm2_host(args.controller) + #transaction_end(args.controller) + + # IMPORT Node enterprise Type ext-group Property location:openflow:4:2, ip-prefix:192.18.13.0/24; + #transaction_begin(args.controller) + add_enterpise_node(args.controller) + #transaction_end(args.controller) + + # CREATE Node interior Type l2-group Contain server1,vm1,vm2; + #transaction_begin(args.controller) + add_interior_node(args.controller) + #transaction_end(args.controller) + + # CREATE Node dmz Type l2-group Contain server2; + #transaction_begin(args.controller) + add_dmz_node(args.controller) + #transaction_end(args.controller) + + # IMPORT Node internet Type ext-group Property location:openflow:3:4, ip-prefix:172.168.1.0/24; + #transaction_begin(args.controller) + add_internet_node(args.controller) + #transaction_end(args.controller) + + # CREATE Connection c1 Endnodes enterprise,interior Property bandwidth:128(kbps); + #transaction_begin(args.controller) + add_enterprise_interior_connection(args.controller) + #transaction_end(args.controller) + + # CREATE Connection c2 Endnodes interior,dmz; + #transaction_begin(args.controller) + add_interior_dmz_connection(args.controller) + #transaction_end(args.controller) + + # CREATE Connection c3 Endnodes dmz,internet; + #transaction_begin(args.controller) + add_dmz_internet_connection(args.controller) + transaction_end(args.controller) + + # UPDATE Connection c1 Endnodes enterprise,interior Property bandwidth:512(kbps); + #transaction_begin(args.controller) + #update_enterprise_interior_connection(args.controller) + #transaction_end(args.controller) \ No newline at end of file diff --git a/nemo-impl/src/test/resources/bod-2.py b/nemo-impl/src/test/resources/bod-2.py new file mode 100644 index 0000000..e480016 --- /dev/null +++ b/nemo-impl/src/test/resources/bod-2.py @@ -0,0 +1,613 @@ +#!/usr/bin/python +#Filename:servicechain.py +import requests,json +import argparse, sys +from requests.auth import HTTPBasicAuth + +USERNAME='admin' +PASSWORD='admin' + +TRANSACTION_BEGIN="http://%s:8181/restconf/operations/nemo-intent:begin-transaction" +TRANSACTION_END="http://%s:8181/restconf/operations/nemo-intent:end-transaction" +REGISTER_USER="http://%s:8181/restconf/operations/nemo-intent:register-user" +STRUCTURE_UPDATE_USERS="http://%s:8181/restconf/operations/nemo-intent:structure-style-nemo-update" + +def register_user(contHost): + data={ + "input":{ + "user-id":"14ce424a-3e50-4a2a-ad5c-b29845158c8b", + "user-name":"user2", + "user-password":"abc", + "user-role":"tenant" + } + } + post(REGISTER_USER % contHost, data) + +def transaction_begin(contHost): + data={ + "input":{ + "user-id":"14ce424a-3e50-4a2a-ad5c-b29845158c8b", + "user-name":"user2", + "user-password":"abc", + "user-role":"tenant" + } + } + post(TRANSACTION_BEGIN % contHost, data) + +def transaction_end(contHost): + data={ + "input":{ + "user-id":"14ce424a-3e50-4a2a-ad5c-b29845158c8b", + "user-name":"user2", + "user-password":"abc", + "user-role":"tenant" + } + } + post(TRANSACTION_END % contHost, data) + +def add_server1_host(contHost): + data={ + "input":{ + "user-name": "user2", + "user-role": "tenant", + "user-password": "abc", + "user-id": "14ce424a-3e50-4a2a-ad5c-b29845158c8b", + "objects":{ + "node":[ + { + "node-name": "server1", + "node-type": "host", + "node-id":"7b796915-adf4-4356-b5ca-de005ac410c1" + } + ] + } + } + } + post(STRUCTURE_UPDATE_USERS % contHost, data) + +def add_server2_host(contHost): + data={ + "input":{ + "user-name": "user2", + "user-role": "tenant", + "user-password": "abc", + "user-id": "14ce424a-3e50-4a2a-ad5c-b29845158c8b", + "objects":{ + "node":[ + { + "node-name": "server2", + "node-type": "host", + "node-id":"22282cca-9a13-4d0c-a67e-a933ebb0b0ae" + } + ] + } + } + } + post(STRUCTURE_UPDATE_USERS % contHost, data) + +def add_vm1_host(contHost): + data={ + "input":{ + "user-name": "user2", + "user-role": "tenant", + "user-password": "abc", + "user-id": "14ce424a-3e50-4a2a-ad5c-b29845158c8b", + "objects":{ + "node":[ + { + "node-name": "vm1", + "node-type": "host", + "node-id":"1eaf9a67-a171-42a8-9282-71cf702f61dd" + } + ] + } + } + } + post(STRUCTURE_UPDATE_USERS % contHost, data) + +def add_vm2_host(contHost): + data={ + "input":{ + "user-name": "user2", + "user-role": "tenant", + "user-password": "abc", + "user-id": "14ce424a-3e50-4a2a-ad5c-b29845158c8b", + "objects":{ + "node":[ + { + "node-name": "vm2", + "node-type": "host", + "node-id":"6c787caa-156a-49ed-8546-547bdccf283c" + } + ] + } + } + } + post(STRUCTURE_UPDATE_USERS % contHost, data) + +def add_enterpise_node(contHost): + data={ + "input":{ + "user-name": "user2", + "user-role": "tenant", + "user-password": "abc", + "user-id": "14ce424a-3e50-4a2a-ad5c-b29845158c8b", + "objects":{ + "node":[ + { + "node-name": "enterprise", + "node-type": "ext-group", + "property": [ + { + "property-name": "location", + "property-values": { + "string-value": [ + { + "order": "0", + "value": "openflow:4:2" + } + ] + } + }, + { + "property-name": "ac-info-network", + "property-values": { + "string-value": [ + { + "order": "0", + "value": "layer3" + } + ] + } + }, + { + "property-name": "ac-info-protocol", + "property-values": { + "string-value": [ + { + "order": "0", + "value": "static" + } + ] + } + }, + { + "property-name": "ip-prefix", + "property-values": { + "string-value": [ + { + "order": "0", + "value": "192.168.13.0/24" + } + ] + } + } + ], + "node-id": "94a6fb90-b425-4ffd-9515-c0684aa4c37f" + } + ] + } + } + } + post(STRUCTURE_UPDATE_USERS % contHost, data) + +def add_internet_node(contHost): + data={ + "input":{ + "user-name": "user2", + "user-role": "tenant", + "user-password": "abc", + "user-id": "14ce424a-3e50-4a2a-ad5c-b29845158c8b", + "objects":{ + "node":[ + { + "node-name": "internet", + "node-type": "ext-group", + "property": [ + { + "property-name": "location", + "property-values": { + "string-value": [ + { + "order": "0", + "value": "openflow:3:4" + } + ] + } + }, + { + "property-name": "ac-info-network", + "property-values": { + "string-value": [ + { + "order": "0", + "value": "layer3" + } + ] + } + }, + { + "property-name": "ac-info-protocol", + "property-values": { + "string-value": [ + { + "order": "0", + "value": "static" + } + ] + } + }, + { + "property-name": "ip-prefix", + "property-values": { + "string-value": [ + { + "order": "0", + #wait for external network ip + "value": "172.168.1.0/24" + } + ] + } + } + ], + "node-id": "d463232f-363f-491c-a6f5-097ed0a794d3" + } + ] + } + } + } + post(STRUCTURE_UPDATE_USERS % contHost, data) + +def add_dmz_node(contHost): + data={ + "input":{ + "user-name": "user2", + "user-role": "tenant", + "user-password": "abc", + "user-id": "14ce424a-3e50-4a2a-ad5c-b29845158c8b", + "objects":{ + "node":[ + { + "node-name": "dmz", + "node-type": "l2-group", + "sub-node": [ + { + "node-id":"7b796915-adf4-4356-b5ca-de005ac410c1", + "order":"0" + } + ], + "property": [ + { + "property-name": "location", + "property-values": { + "string-value": [ + { + "order": "0", + "value": "openflow:3" + } + ] + } + }, + { + "property-name": "ip-prefix", + "property-values": { + "string-value": [ + { + "order": "0", + "value": "192.168.11.0/24" + } + ] + } + }, + { + "property-name": "gateway-ip", + "property-values": { + "string-value": [ + { + "order": "0", + "value": "192.168.11.1" + } + ] + } + } + ], + "node-id": "b46cfa7f-93a3-43f4-ac20-09307c75feca" + } + ] + } + } + } + post(STRUCTURE_UPDATE_USERS % contHost, data) + +def add_interior_node(contHost): + data={ + "input":{ + "user-name": "user2", + "user-role": "tenant", + "user-password": "abc", + "user-id": "14ce424a-3e50-4a2a-ad5c-b29845158c8b", + "objects":{ + "node":[ + { + "node-name": "interior", + "node-type": "l2-group", + "sub-node": [ + { + "node-id":"22282cca-9a13-4d0c-a67e-a933ebb0b0ae", + "order":"0" + }, + { + "node-id":"1eaf9a67-a171-42a8-9282-71cf702f61dd", + "order":"0" + }, + { + "node-id":"6c787caa-156a-49ed-8546-547bdccf283c", + "order":"0" + } + ], + "property": [ + { + "property-name": "location", + "property-values": { + "string-value": [ + { + "order": "0", + "value": "openflow:3" + } + ] + } + }, + { + "property-name": "ip-prefix", + "property-values": { + "string-value": [ + { + "order": "0", + "value": "192.168.12.0/24" + } + ] + } + }, + { + "property-name": "gateway-ip", + "property-values": { + "string-value": [ + { + "order": "0", + "value": "192.168.12.1" + } + ] + } + } + ], + "node-id": "175425f7-c9c9-474a-962c-70cb6c180d4d" + } + ] + } + } + } + post(STRUCTURE_UPDATE_USERS % contHost, data) + +def add_enterprise_interior_connection(contHost): + data={ + "input": { + "user-name": "user2", + "user-role": "tenant", + "user-password": "abc", + "user-id": "14ce424a-3e50-4a2a-ad5c-b29845158c8b", + "objects":{ + "connection": [ + { + "connection-name": "c1", + "connection-id": "30da6667-608e-4d2f-bb50-79e5cabcc523", + "end-node": [ + { + "order": "0", + "node-id": "94a6fb90-b425-4ffd-9515-c0684aa4c37f" + }, + { + "order": "0", + "node-id": "175425f7-c9c9-474a-962c-70cb6c180d4d" + } + ], + "connection-type": "p2p", + "property": [ + { + "property-name": "bandwidth", + "property-values": { + "int-value": [ + { + "order": "0", + "value": "128" + } + ] + } + } + ] + } + ] + } + } + } + post(STRUCTURE_UPDATE_USERS % contHost, data) + +def add_interior_dmz_connection(contHost): + data={ + "input": { + "user-name": "user2", + "user-role": "tenant", + "user-password": "abc", + "user-id": "14ce424a-3e50-4a2a-ad5c-b29845158c8b", + "objects":{ + "connection": [ + { + "connection-name": "c2", + "connection-id": "b49e3960-c08d-4fff-b9fc-08b65ebcde2c", + "end-node": [ + { + "order": "0", + "node-id": "175425f7-c9c9-474a-962c-70cb6c180d4d" + }, + { + "order": "0", + "node-id": "b46cfa7f-93a3-43f4-ac20-09307c75feca" + } + ], + "connection-type": "p2p" + } + ] + } + } + } + post(STRUCTURE_UPDATE_USERS % contHost, data) + +def add_dmz_internet_connection(contHost): + data={ + "input": { + "user-name": "user2", + "user-role": "tenant", + "user-password": "abc", + "user-id": "14ce424a-3e50-4a2a-ad5c-b29845158c8b", + "objects":{ + "connection": [ + { + "connection-name": "c3", + "connection-id": "e0d56fee-7235-4748-a2a1-eb5e3733d866", + "end-node": [ + { + "order": "0", + "node-id": "b46cfa7f-93a3-43f4-ac20-09307c75feca" + }, + { + "order": "0", + "node-id": "d463232f-363f-491c-a6f5-097ed0a794d3" + } + ], + "connection-type": "p2p" + } + ] + } + } + } + post(STRUCTURE_UPDATE_USERS % contHost, data) + +def update_enterprise_interior_connection(contHost): + data={ + "input": { + "user-name": "user2", + "user-role": "tenant", + "user-password": "abc", + "user-id": "14ce424a-3e50-4a2a-ad5c-b29845158c8b", + "objects":{ + "connection": [ + { + "connection-name": "c1", + "connection-id": "30da6667-608e-4d2f-bb50-79e5cabcc523", + "end-node": [ + { + "order": "0", + "node-id": "94a6fb90-b425-4ffd-9515-c0684aa4c37f" + }, + { + "order": "0", + "node-id": "175425f7-c9c9-474a-962c-70cb6c180d4d" + } + ], + "connection-type": "p2p", + "property": [ + { + "property-name": "bandwidth", + "property-values": { + "int-value": [ + { + "order": "0", + "value": "1024" + } + ] + } + } + ] + } + ] + } + } + } + post(STRUCTURE_UPDATE_USERS % contHost, data) + +def post(url, data): + headers = {'Content-type': 'application/yang.data+json', + 'Accept': 'application/yang.data+json'} + print "POST %s" % url + print json.dumps(data, indent=4, sort_keys=True) + r = requests.post(url, data=json.dumps(data), headers=headers, auth=HTTPBasicAuth(USERNAME, PASSWORD)) + print r.text + r.raise_for_status() + +if __name__ == '__main__': + + parser = argparse.ArgumentParser() + parser.add_argument('--controller', default='127.0.0.1', help='controller IP') + args=parser.parse_args() + + # CREATE User; + #register_user(args.controller) + + # IMPORT Node server1 Type host; + #transaction_begin(args.controller) + #add_server1_host(args.controller) + #transaction_end(args.controller) + + # IMPORT Node server2 Type host; + #transaction_begin(args.controller) + #add_server2_host(args.controller) + #transaction_end(args.controller) + + # IMPORT Node vm1 Type host; + #transaction_begin(args.controller) + #add_vm1_host(args.controller) + #transaction_end(args.controller) + + # IMPORT Node vm2 Type host; + #transaction_begin(args.controller) + #add_vm2_host(args.controller) + #transaction_end(args.controller) + + # IMPORT Node enterprise Type ext-group Property location:openflow:4:2, ip-prefix:192.18.13.0/24; + #transaction_begin(args.controller) + #add_enterpise_node(args.controller) + #transaction_end(args.controller) + + # CREATE Node interior Type l2-group Contain server1,vm1,vm2; + #transaction_begin(args.controller) + #add_interior_node(args.controller) + #transaction_end(args.controller) + + # CREATE Node dmz Type l2-group Contain server2; + #transaction_begin(args.controller) + #add_dmz_node(args.controller) + #transaction_end(args.controller) + + # IMPORT Node internet Type ext-group Property location:openflow:3:4, ip-prefix:172.168.1.0/24; + #transaction_begin(args.controller) + #add_internet_node(args.controller) + #transaction_end(args.controller) + + # CREATE Connection c1 Endnodes enterprise,interior Property bandwidth:128(kbps); + #transaction_begin(args.controller) + #add_enterprise_interior_connection(args.controller) + #transaction_end(args.controller) + + # CREATE Connection c2 Endnodes interior,dmz; + #transaction_begin(args.controller) + #add_interior_dmz_connection(args.controller) + #transaction_end(args.controller) + + # CREATE Connection c3 Endnodes dmz,internet; + #transaction_begin(args.controller) + #add_dmz_internet_connection(args.controller) + #transaction_end(args.controller) + + # UPDATE Connection c1 Endnodes enterprise,interior Property bandwidth:1024(kbps); + transaction_begin(args.controller) + update_enterprise_interior_connection(args.controller) + transaction_end(args.controller) \ No newline at end of file diff --git a/nemo-impl/src/test/resources/servicechain.py b/nemo-impl/src/test/resources/servicechain.py new file mode 100644 index 0000000..b684b37 --- /dev/null +++ b/nemo-impl/src/test/resources/servicechain.py @@ -0,0 +1,524 @@ +#!/usr/bin/python +#Filename:servicechain.py +import requests,json +import argparse, sys +from requests.auth import HTTPBasicAuth + +USERNAME='admin' +PASSWORD='admin' + +TRANSACTION_BEGIN="http://%s:8181/restconf/operations/nemo-intent:begin-transaction/" +TRANSACTION_END="http://%s:8181/restconf/operations/nemo-intent:end-transaction/" +REGISTER_USER="http://%s:8181/restconf/operations/nemo-intent:register-user/" +STRUCTURE_UPDATE_USERS="http://%s:8181/restconf/operations/nemo-intent:structure-style-nemo-update/" + +def register_user(contHost): + data={ + "input":{ + "user-id":"af4fc2be-e3f4-4388-a8ef-3aabae872f2b", + "user-name":"user1", + "user-password":"abcd", + "user-role":"tenant" + } + } + post(REGISTER_USER % contHost, data) + +def transaction_begin(contHost): + data={ + "input":{ + "user-id":"af4fc2be-e3f4-4388-a8ef-3aabae872f2b", + "user-name":"user1", + "user-password":"abcd", + "user-role":"tenant" + } + } + post(TRANSACTION_BEGIN % contHost, data) + +def transaction_end(contHost): + data={ + "input":{ + "user-id":"af4fc2be-e3f4-4388-a8ef-3aabae872f2b", + "user-name":"user1", + "user-password":"abcd", + "user-role":"tenant" + } + } + post(TRANSACTION_END % contHost, data) + + +def add_headquarter_node(contHost): + data={ + "input":{ + "user-name": "user1", + "user-role": "tenant", + "user-password": "abcd", + "user-id": "af4fc2be-e3f4-4388-a8ef-3aabae872f2b", + "objects":{ + "node":[ + { + "node-name": "headquarter", + "node-type": "ext-group", + "property": [ + { + "property-name": "location", + "property-values": { + "string-value": [ + { + "order": "0", + "value": "openflow:4:2" + } + ] + } + }, + { + "property-name": "ac-info-network", + "property-values": { + "string-value": [ + { + "order": "0", + "value": "layer3" + } + ] + } + }, + { + "property-name": "ac-info-protocol", + "property-values": { + "string-value": [ + { + "order": "0", + "value": "static" + } + ] + } + }, + { + "property-name": "ip-prefix", + "property-values": { + "string-value": [ + { + "order": "0", + "value": "192.168.11.0/24" + } + ] + } + } + ], + "node-id": "94a6fb90-b425-4ffd-9515-c0684aa4c37f" + } + ] + } + } + } + post(STRUCTURE_UPDATE_USERS % contHost, data) + +def add_site_node(contHost): + data={ + "input":{ + "user-name": "user1", + "user-role": "tenant", + "user-password": "abcd", + "user-id": "af4fc2be-e3f4-4388-a8ef-3aabae872f2b", + "objects":{ + "node":[ + { + "node-name": "branch", + "node-type": "ext-group", + "property": [ + { + "property-name": "location", + "property-values": { + "string-value": [ + { + "order": "0", + "value": "openflow:3:4" + } + ] + } + }, + { + "property-name": "ac-info-network", + "property-values": { + "string-value": [ + { + "order": "0", + "value": "layer3" + } + ] + } + }, + { + "property-name": "ac-info-protocol", + "property-values": { + "string-value": [ + { + "order": "0", + "value": "static" + } + ] + } + }, + { + "property-name": "ip-prefix", + "property-values": { + "string-value": [ + { + "order": "0", + "value": "192.168.12.0/24" + } + ] + } + } + ], + "node-id": "b46cfa7f-93a3-43f4-ac20-09307c75feca" + } + ] + } + } + } + post(STRUCTURE_UPDATE_USERS % contHost, data) + +def add_firewall_node(contHost): + data={ + "input":{ + "user-name": "user1", + "user-role": "tenant", + "user-password": "abcd", + "user-id": "af4fc2be-e3f4-4388-a8ef-3aabae872f2b", + "objects":{ + "node":[ + { + "node-name": "fw1", + "node-type": "fw", + "property": [ + { + "property-name": "location", + "property-values": { + "string-value": [ + { + "order": "0", + "value": "openflow:1:1" + } + ] + } + }, + { + "property-name": "operating-mode", + "property-values": { + "string-value": [ + { + "order": "0", + "value": "layer3" + } + ] + } + } + ], + "node-id": "c2cd9de6-ab25-4d3f-bff2-c4d785a41995" + } + ] + } + } + } + post(STRUCTURE_UPDATE_USERS % contHost, data) + +def add_cache_node(contHost): + data={ + "input":{ + "user-name": "user1", + "user-role": "tenant", + "user-password": "abcd", + "user-id": "af4fc2be-e3f4-4388-a8ef-3aabae872f2b", + "objects":{ + "node":[ + { + "node-name": "cache2", + "node-type": "cache", + "property": [ + { + "property-name": "location", + "property-values": { + "string-value": [ + { + "order": "0", + "value": "openflow:2:2" + } + ] + } + }, + { + "property-name": "operating-mode", + "property-values": { + "string-value": [ + { + "order": "0", + "value": "layer3" + } + ] + } + } + ], + "node-id": "a5a96dc7-51dd-44a5-802b-7e67a309fb36" + } + ] + } + } + } + post(STRUCTURE_UPDATE_USERS % contHost, data) + +def add_chain_node(contHost): + data={ + "input":{ + "user-name": "user1", + "user-role": "tenant", + "user-password": "abcd", + "user-id": "af4fc2be-e3f4-4388-a8ef-3aabae872f2b", + "objects":{ + "node":[ + { "sub-node": [ + { + "order": "0", + "node-id": "c2cd9de6-ab25-4d3f-bff2-c4d785a41995" + }, + { + "order": "1", + "node-id": "a5a96dc7-51dd-44a5-802b-7e67a309fb36" + } + ], + "node-name": "chain1", + "node-type": "chain-group", + "node-id": "41ee9aad-5f61-469d-99a9-e691d2a1de05" + } + ] + } + } + } + post(STRUCTURE_UPDATE_USERS % contHost, data) + +def add_head_site_connection(contHost): + data={ + "input": { + "user-name": "user1", + "user-role": "tenant", + "user-password": "abcd", + "user-id": "af4fc2be-e3f4-4388-a8ef-3aabae872f2b", + "objects":{ + "connection": [ + { + "connection-name": "c1", + "connection-id": "7175bac3-b785-2278-90ed-613480e354e8", + "end-node": [ + { + "order": "0", + "node-id": "94a6fb90-b425-4ffd-9515-c0684aa4c37f" + }, + { + "order": "0", + "node-id": "b46cfa7f-93a3-43f4-ac20-09307c75feca" + } + ], + "connection-type": "p2p" + } + ] + } + } + } + post(STRUCTURE_UPDATE_USERS % contHost, data) + +def add_head_chain_connection(contHost): + data={ + "input": { + "user-name": "user1", + "user-role": "tenant", + "user-password": "abcd", + "user-id": "af4fc2be-e3f4-4388-a8ef-3aabae872f2b", + "objects":{ + "connection": [ + { + "connection-name": "c2", + "connection-id": "9397bac3-d9a7-449a-b20f-8356a2f3760a", + "end-node": [ + { + "order": "0", + "node-id": "94a6fb90-b425-4ffd-9515-c0684aa4c37f" + }, + { + "order": "0", + "node-id": "41ee9aad-5f61-469d-99a9-e691d2a1de05" + } + ], + "connection-type": "p2p" + } + ] + } + } + } + post(STRUCTURE_UPDATE_USERS % contHost, data) + +def add_site_chain_connection(contHost): + data={ + "input": { + "user-name": "user1", + "user-role": "tenant", + "user-password": "abcd", + "user-id": "af4fc2be-e3f4-4388-a8ef-3aabae872f2b", + "objects":{ + "connection": [ + { + "connection-name": "c3", + "connection-id": "fed2b570-2e80-4914-a5af-040594b651b9", + "end-node": [ + { + "order": "0", + "node-id": "41ee9aad-5f61-469d-99a9-e691d2a1de05" + }, + { + "order": "0", + "node-id": "b46cfa7f-93a3-43f4-ac20-09307c75feca" + } + ], + "connection-type": "p2p" + } + ] + } + } + } + post(STRUCTURE_UPDATE_USERS % contHost, data) + +def add_flow(contHost): + data={ + "input": { + "user-name": "user1", + "user-role": "tenant", + "user-password": "abcd", + "user-id": "af4fc2be-e3f4-4388-a8ef-3aabae872f2b", + "objects":{ + "flow": [ + { + "match-item": [ + { + "match-item-value": { + "string-value": "192.168.12.0/24" + }, + "match-item-name": "src-ip" + }, + { + "match-item-value": { + "string-value": "192.168.11.0/24" + }, + "match-item-name": "dst-ip" + }, + ], + "flow-id": "cf48eeee-882e-435a-adf4-ea22ba88331f", + "flow-name": "f1" + } + ] + } + } + } + post(STRUCTURE_UPDATE_USERS % contHost, data) + +def add_operation(contHost): + data={ + "input": { + "user-name": "user1", + "user-role": "tenant", + "user-password": "abcd", + "user-id": "af4fc2be-e3f4-4388-a8ef-3aabae872f2b", + "operations":{ + "operation": [ + { + "operation-name": "o1", + "target-object": "cf48eeee-882e-435a-adf4-ea22ba88331f", + "priority":"0", + "operation-id": "619ee3bb-1e40-480f-b0fa-a331820a5518", + "action":[ + { + "action-name":"go-through", + "parameter-values":{ + "string-value": [ + {"value": "41ee9aad-5f61-469d-99a9-e691d2a1de05", + "order":"0"} + ] + }, + "order":"0" + } + ] + } + ] + } + } + } + post(STRUCTURE_UPDATE_USERS % contHost, data) + + +def post(url, data): + headers = {'Content-type': 'application/yang.data+json', + 'Accept': 'application/yang.data+json'} + print "POST %s" % url + print json.dumps(data, indent=4, sort_keys=True) + r = requests.post(url, data=json.dumps(data), headers=headers, auth=HTTPBasicAuth(USERNAME, PASSWORD)) + print r.text + r.raise_for_status() + + +if __name__ == '__main__': + + parser = argparse.ArgumentParser() + parser.add_argument('--controller', default='127.0.0.1', help='controller IP') + args=parser.parse_args() + + # CREATE User; + register_user(args.controller) + + # CREATE Node headquarter Type ext-group Property location:openflow:4:2, ip-prefix:192.168.11.0/24; + transaction_begin(args.controller) + add_headquarter_node(args.controller) + #transaction_end(args.controller) + + # CREATE Node headquarter Type ext-group Property location:openflow:3:4,ip-prefix:192.168.12.0/24; + #transaction_begin(args.controller) + add_site_node(args.controller) + #transaction_end(args.controller) + + # IMPORT Node fw1 Type fw Property location:openflow:1:1; + #transaction_begin(args.controller) + add_firewall_node(args.controller) + #transaction_end(args.controller) + + # IMPORT Node Cache2 Type cache Property location:openflow:2:2; + #transaction_begin(args.controller) + add_cache_node(args.controller) + #transaction_end(args.controller) + + # CREATE Node chain1 Type chain-group Contain fw1,cache2; + #transaction_begin(args.controller) + add_chain_node(args.controller) + #transaction_end(args.controller) + + # CREATE Connection c1 Type p2p Endnodes headquarter,site; + #transaction_begin(args.controller) + add_head_site_connection(args.controller) + #transaction_end(args.controller) + + # CREATE Connection c2 Type p2p Endnodes headquarter,chain1; + #transaction_begin(args.controller) + add_head_chain_connection(args.controller) + #transaction_end(args.controller) + + # CREATE Connection c3 Type p2p Endnodes site,chain1; + #transaction_begin(args.controller) + add_site_chain_connection(args.controller) + #transaction_end(args.controller) + + # CREATE Flow f1 Match src-ip:192.168.12.0/24, dst-ip:192.168.11.0/24; + #transaction_begin(args.controller) + add_flow(args.controller) + #transaction_end(args.controller) + + # CREATE Operation o1 Priority 0 Target f1 Action go-through: chain1; + #transaction_begin(args.controller) + add_operation(args.controller) + transaction_end(args.controller) + + diff --git a/nemo-karaf/pom.xml b/nemo-karaf/pom.xml index 7f23a37..c5520cc 100644 --- a/nemo-karaf/pom.xml +++ b/nemo-karaf/pom.xml @@ -26,12 +26,8 @@ and is available at http://www.eclipse.org/legal/epl-v10.html - 1.6.0-SNAPSHOT 1.3.0-SNAPSHOT 0.3.0-SNAPSHOT - 1.3.0-SNAPSHOT - 0.8.0-SNAPSHOT - 0.10.0-SNAPSHOT @@ -60,14 +56,6 @@ and is available at http://www.eclipse.org/legal/epl-v10.html xml runtime - - org.opendaylight.controller - features-adsal - features - ${feature.adsal.version} - xml - runtime - org.opendaylight.dlux features-dlux diff --git a/nemo-renderers/openflow-renderer/pom.xml b/nemo-renderers/openflow-renderer/pom.xml index a88e190..ab0b3f5 100644 --- a/nemo-renderers/openflow-renderer/pom.xml +++ b/nemo-renderers/openflow-renderer/pom.xml @@ -24,9 +24,33 @@ and is available at http://www.eclipse.org/legal/epl-v10.html 0.7.2.201409121644 + target/code-coverage/jacoco.exec + target/code-coverage/jacoco-it.exec + 0.2.0-SNAPSHOT + 0.10.0-SNAPSHOT + + + org.opendaylight.mdsal.model + yang-ext + + + + org.opendaylight.openflowplugin + openflowplugin-extension-nicira + ${openflowplugin.version} + + + org.opendaylight.controller + liblldp + ${liblldp.version} + + + commons-net + commons-net + ${project.groupId} nemo-api @@ -37,6 +61,11 @@ and is available at http://www.eclipse.org/legal/epl-v10.html nemo-impl ${project.version} + + org.mockito + mockito-all + test + junit junit @@ -46,6 +75,18 @@ and is available at http://www.eclipse.org/legal/epl-v10.html slf4j-simple test + + com.fasterxml.jackson.core + jackson-core + + + com.fasterxml.jackson.core + jackson-databind + + + com.fasterxml.jackson.core + jackson-annotations + org.codehaus.jettison jettison @@ -63,6 +104,19 @@ and is available at http://www.eclipse.org/legal/epl-v10.html + + org.apache.felix + maven-bundle-plugin + + + org.codehaus.jackson, + org.codehaus.jackson.*, + org.joda.time.*, + + * + + + org.opendaylight.yangtools yang-maven-plugin @@ -108,6 +162,11 @@ and is available at http://www.eclipse.org/legal/epl-v10.html package + + ${project.build.directory}/classes/etc/nemo/resource.json + json + resource + ${project.build.directory}/classes/etc/opendaylight/karaf/config.xml xml @@ -128,17 +187,22 @@ and is available at http://www.eclipse.org/legal/epl-v10.html - pre-test + pre-unit-test prepare-agent + + ${sonar.jacoco.reportPath} + - post-test + post-unit-test report - test + + ${sonar.jacoco.reportPath} + diff --git a/nemo-renderers/openflow-renderer/src/main/java/README b/nemo-renderers/openflow-renderer/src/main/java/README deleted file mode 100644 index e69de29..0000000 diff --git a/nemo-renderers/openflow-renderer/src/main/java/org/opendaylight/nemo/renderer/openflow/FlowTableManager.java b/nemo-renderers/openflow-renderer/src/main/java/org/opendaylight/nemo/renderer/openflow/FlowTableManager.java new file mode 100644 index 0000000..6ba4a0f --- /dev/null +++ b/nemo-renderers/openflow-renderer/src/main/java/org/opendaylight/nemo/renderer/openflow/FlowTableManager.java @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.nemo.renderer.openflow; + +import com.google.common.base.Optional; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import com.google.common.util.concurrent.CheckedFuture; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; +import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; + +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.PhysicalNetwork; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.PhysicalNodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.nodes.PhysicalNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.VirtualNetworks; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.VirtualNetwork; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.VirtualNetworkKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.IntentVnMappingResults; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.VnPnMappingResults; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.intent.vn.mapping.results.UserIntentVnMapping; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.intent.vn.mapping.results.UserIntentVnMappingKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.vn.pn.mapping.results.UserVnPnMapping; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.common.rev151010.VirtualNetworkId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.UserId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.Users; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.users.User; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.users.UserKey; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Map; +import java.util.Set; + +public class FlowTableManager implements AutoCloseable { + private static final Logger LOG = LoggerFactory.getLogger(FlowTableManager.class); + + private final DataBroker dataProvider; + + private ListenerRegistration userVnPnMappingChangeListenerReg; + + private FlowUtils flowUtils = null; + + public FlowTableManager(DataBroker dataProvider, ResourceManager resourceManager){ + + this.dataProvider = dataProvider; + LOG.info("Initialized FlowTableManager."); + flowUtils = new FlowUtils(dataProvider, resourceManager); + //register listener + registerUserVnPnMappingListener(); + } + + private void registerUserVnPnMappingListener() { + + //build userVnPnMappingIid + InstanceIdentifier userVnPnMappingIid = InstanceIdentifier + .builder(VnPnMappingResults.class) + .child(UserVnPnMapping.class) + .build(); + //register + userVnPnMappingChangeListenerReg = dataProvider.registerDataChangeListener( + LogicalDatastoreType.CONFIGURATION, userVnPnMappingIid, + new UserVnPnMappingChangeListener(), DataChangeScope.BASE); + } + + + private User getUser(UserId userId) { + + ReadOnlyTransaction readOnlyTransaction = dataProvider.newReadOnlyTransaction(); + InstanceIdentifier userIid = InstanceIdentifier.builder(Users.class) + .child(User.class, new UserKey(userId)) + .build(); + Optional result = null; + + try { + result = readOnlyTransaction.read(LogicalDatastoreType.CONFIGURATION, userIid).get(); + } catch (Exception e) { + e.printStackTrace(); + } + if (result.isPresent()){ + LOG.info("getUser OK"); + return (result.get()); + + }else{ + LOG.info("getUser ERROR"); + return null; + } + } + + + private VirtualNetwork getVirtualNetwork(UserId userId) { + + VirtualNetworkId virtualNetworkId = new VirtualNetworkId(userId.getValue()); + VirtualNetworkKey virtualNetworkKey = new VirtualNetworkKey(virtualNetworkId); + + ReadOnlyTransaction readOnlyTransaction = dataProvider.newReadOnlyTransaction(); + InstanceIdentifier virtualNetworkIid = InstanceIdentifier + .builder(VirtualNetworks.class) + .child(VirtualNetwork.class, virtualNetworkKey) + .build(); + Optional result = null; + + try { + result = readOnlyTransaction.read(LogicalDatastoreType.CONFIGURATION, virtualNetworkIid).get(); + + } catch (Exception e) { + e.printStackTrace(); + } + if (result.isPresent()) { + LOG.info("getVirtualNetwork OK"); + return (result.get()); + + }else{ + LOG.info("getVirtualNetwork ERROR"); + return null; + } + } + + private UserIntentVnMapping getUserIntentVnMapping(UserId userId) { + + ReadOnlyTransaction readOnlyTransaction = dataProvider.newReadOnlyTransaction(); + InstanceIdentifier userIntentVnMappingIid = InstanceIdentifier + .builder(IntentVnMappingResults.class) + .child(UserIntentVnMapping.class, new UserIntentVnMappingKey(userId)) + .build(); + Optional result = null; + try { + result = readOnlyTransaction.read(LogicalDatastoreType.CONFIGURATION, userIntentVnMappingIid).get(); + } catch (Exception e) { + e.printStackTrace(); + } + if (result.isPresent()) { + LOG.info("getUserIntentVnMapping OK"); + return (result.get()); + + }else{ + LOG.info("getUserIntentVnMapping ERROR"); + return null; + } + } + + private PhysicalNetwork getPhysicalNetwork() { + + ReadOnlyTransaction readOnlyTransaction = dataProvider.newReadOnlyTransaction(); + InstanceIdentifier physicalNetworkIid = InstanceIdentifier + .builder(PhysicalNetwork.class) + .build(); + Optional result = null; + try { + result = readOnlyTransaction.read(LogicalDatastoreType.OPERATIONAL, physicalNetworkIid).get(); + } catch (Exception e) { + e.printStackTrace(); + } + if (result.isPresent()) { + LOG.info("getPhysicalNetwork OK"); + return (result.get()); + + }else{ + LOG.info("getPhysicalNetwork ERROR"); + return null; + } + } + + + //A listener implementation + private class UserVnPnMappingChangeListener implements DataChangeListener { + + @Override + public void onDataChanged(AsyncDataChangeEvent, DataObject> change) { + if ( null == change ) { + return; + } + + Map, DataObject> createdData = change.getCreatedData(); + if ( null != createdData && !createdData.isEmpty() ) { + for ( DataObject dataObject : createdData.values() ) { + if ( dataObject instanceof UserVnPnMapping ) { + LOG.info("Ready to update flow table."); + UserVnPnMapping userVnPnMapping = (UserVnPnMapping)dataObject; + UserId userId = userVnPnMapping.getUserId(); + + User user = getUser(userId); + VirtualNetwork virtualNetwork = getVirtualNetwork(userId); + UserIntentVnMapping userIntentVnMapping = getUserIntentVnMapping(userId); + PhysicalNetwork physicalNetwork = getPhysicalNetwork(); + if(physicalNetwork == null) + { + LOG.debug("Physical Network data are not present."); + return; + } + PhysicalNodes physicalNodes= physicalNetwork.getPhysicalNodes(); + List physicalNodeList = physicalNodes.getPhysicalNode(); + flowUtils.init(physicalNodeList); + + flowUtils.updateFlowTable(user, virtualNetwork, userIntentVnMapping, userVnPnMapping, physicalNetwork); + LOG.info("Already call flowUtils.updateFlowTable()."); + } + } + } + + Map, DataObject> updatedData = change.getUpdatedData(); + if ( null != updatedData && !updatedData.isEmpty() ) { + for ( DataObject dataObject : updatedData.values() ) { + if ( dataObject instanceof UserVnPnMapping ) { + UserVnPnMapping userVnPnMapping = (UserVnPnMapping)dataObject; + UserId userId = userVnPnMapping.getUserId(); + + flowUtils.deleteFlowEntries(userId); + + User user = getUser(userId); + VirtualNetwork virtualNetwork = getVirtualNetwork(userId); + UserIntentVnMapping userIntentVnMapping = getUserIntentVnMapping(userId); + PhysicalNetwork physicalNetwork = getPhysicalNetwork(); + if(physicalNetwork == null) + { + LOG.debug("Physical Network data are not present."); + return; + } + + flowUtils.updateFlowTable(user, virtualNetwork, userIntentVnMapping, userVnPnMapping, physicalNetwork); + } + } + } + + Map, DataObject> originalData = change.getOriginalData(); + Set> removedPaths = change.getRemovedPaths(); + if ( null != removedPaths && !removedPaths.isEmpty() ) { + DataObject dataObject; + + for ( InstanceIdentifier instanceId : removedPaths ) { + dataObject = originalData.get(instanceId); + if ( null != dataObject && dataObject instanceof UserVnPnMapping ) { + UserVnPnMapping userVnPnMapping = (UserVnPnMapping)dataObject; + flowUtils.deleteFlowEntries(userVnPnMapping.getUserId()); + } + } + } + return; + } + } + + @Override + public void close() throws Exception { + + if ( null != userVnPnMappingChangeListenerReg ) { + userVnPnMappingChangeListenerReg.close(); + } + if ( null != flowUtils ) { + flowUtils.close(); + } + } +} diff --git a/nemo-renderers/openflow-renderer/src/main/java/org/opendaylight/nemo/renderer/openflow/FlowUtils.java b/nemo-renderers/openflow-renderer/src/main/java/org/opendaylight/nemo/renderer/openflow/FlowUtils.java new file mode 100644 index 0000000..e5d3254 --- /dev/null +++ b/nemo-renderers/openflow-renderer/src/main/java/org/opendaylight/nemo/renderer/openflow/FlowUtils.java @@ -0,0 +1,2579 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.nemo.renderer.openflow; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress; +import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.*; +import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.dec.mpls.ttl._case.DecMplsTtl; +import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.dec.mpls.ttl._case.DecMplsTtlBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.dec.nw.ttl._case.DecNwTtl; +import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.dec.nw.ttl._case.DecNwTtlBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.output.action._case.OutputAction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.output.action._case.OutputActionBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.mpls.action._case.PopMplsAction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.mpls.action._case.PopMplsActionBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.push.mpls.action._case.PushMplsAction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.push.mpls.action._case.PushMplsActionBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.field._case.SetField; +import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.field._case.SetFieldBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action; +import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.*; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActions; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.go.to.table._case.GoToTable; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.go.to.table._case.GoToTableBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.metadata._case.WriteMetadata; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.metadata._case.WriteMetadataBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.*; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.BandId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterBandType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterFlags; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.band.type.band.type.Drop; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.band.type.band.type.DropBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.MeterBandHeadersBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.meter.band.headers.MeterBandHeader; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.meter.band.headers.MeterBandHeaderBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.meter.band.headers.MeterBandHeaderKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.meter.band.headers.meter.band.header.MeterBandTypesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetDestinationBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetSourceBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetTypeBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.*; +import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match; +import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.PhysicalNetwork; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.PhysicalLinks; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.PhysicalPaths; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.links.PhysicalLink; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.nodes.PhysicalNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.paths.PhysicalPath; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.paths.PhysicalPathBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.node.instance.PhysicalPort; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.VirtualNetwork; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.arps.VirtualArp; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.arps.VirtualArpKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.links.VirtualLink; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.nodes.VirtualNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.networks.virtual.network.virtual.paths.VirtualPath; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.virtual.network.rev151010.virtual.node.instance.VirtualPort; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.intent.vn.mapping.results.UserIntentVnMapping; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.intent.vn.mapping.results.user.intent.vn.mapping.IntentVnMappingResult; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.intent.vn.mapping.results.user.intent.vn.mapping.intent.vn.mapping.result.VirtualResource; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.vn.pn.mapping.results.UserVnPnMapping; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.intent.mapping.result.rev151010.vn.pn.mapping.results.user.vn.pn.mapping.VnPnMappingResult; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.IntentId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.MatchItemName; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.UserId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.common.rev151010.*; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.operations.Operation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.users.User; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.object.rev151010.flow.instance.MatchItem; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.math.BigInteger; +import java.util.*; + +public class FlowUtils implements AutoCloseable { + private static final Logger LOG = LoggerFactory.getLogger(FlowUtils.class); + + private static final short IN_PORT_TABLE_ID = 0; + private static final short MPLS_LABEL_TABLE_ID = 1; + private static final short MAC_TABLE_ID = 2; + private static final short IP_TABLE_ID = 3; + private static final short ARP_TABLE_ID = 4; + + private static final int DEFAULT_FLOW_PRIORITY = 0; + private static final String DEFAULT_METADATA_MASK = "ffffffffffffffff"; + + private static final int ETH_TYPE_IP = 0x0800; + private static final int ETH_TYPE_MPLS = 0x8847; + private static final int ETH_TYPE_ARP = 0x0806; + + private final DataBroker dataBroker; + + private Map mplsGenerators; + private Map meterIdGenerators; + private Map> mplsLabelsOfPhysicalPaths; + private Map meterIdsOfPhysicalPaths; + private Map metadatas; + private long currentMetadata = 0; + + private PhysicalNetworkHelper physicalNetworkHelper; + private VirtualNetworkHelper virtualNetworkHelper; + + //liushixing + private Map>> flowIdsOfUsers; + private Map>> meterIdIdsOfUsers; +// private List assignedPortForInPort; + private ResourceManager resourceManager; + + private Map gatewayMacAddress; + + public FlowUtils(DataBroker dataBroker, ResourceManager resourceManager) { + super(); + + this.dataBroker = dataBroker; + this.resourceManager = resourceManager; + + mplsGenerators = new HashMap(); + meterIdGenerators = new HashMap(); + mplsLabelsOfPhysicalPaths = new HashMap>(); + meterIdsOfPhysicalPaths = new HashMap(); + metadatas = new HashMap(); + + //liushixing + flowIdsOfUsers = new HashMap>>(); + meterIdIdsOfUsers = new HashMap>>(); +// assignedPortForInPort = new ArrayList(); + + gatewayMacAddress = new HashMap(); + // Gateway of the DMZ group. + gatewayMacAddress.put(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.NodeId("b46cfa7f-93a3-43f4-ac20-09307c75feca"), + new MacAddress("00:00:0a:0b:0c:01")); + // Gateway of the interior group. + gatewayMacAddress.put(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.NodeId("175425f7-c9c9-474a-962c-70cb6c180d4d"), + new MacAddress("00:00:0a:0b:0c:02")); + } + + public void init(List physicalNodes) { + for ( PhysicalNode physicalNode : physicalNodes ) { + mplsGenerators.put(physicalNode.getNodeId(), new MplsLabelGenerator()); + meterIdGenerators.put(physicalNode.getNodeId(), new MeterIdGenerator()); + } + } + + /** + * TODO + * + * @author Shixing Liu + * @param userId TODO + * @param nodeId TODO + * @param tableId TODO + * @param flowId TODO + */ + private InstanceIdentifier generateFlowInsId(UserId userId, + NodeId nodeId, + Short tableId, + FlowId flowId){ + + + InstanceIdentifier flowInsId = createFlowPath(nodeId, tableId, flowId); + + if(flowIdsOfUsers.containsKey(userId) == false){ + List> flowInsIds = new ArrayList>(); + flowInsIds.add(flowInsId); + flowIdsOfUsers.put(userId, flowInsIds); + }else{ + List> flowInsIds = flowIdsOfUsers.get(userId); + flowInsIds.add(flowInsId); + } + LOG.info("nemo:generateFlowInsId"); + return flowInsId; + } + + /** + * TODO + * + * @author Shixing Liu + * @param userId TODO + * @param nodeKey TODO + * @param meterKey TODO + */ + private InstanceIdentifier generateMeterInsId(UserId userId, + NodeKey nodeKey, + MeterKey meterKey){ + InstanceIdentifier meterInsId = InstanceIdentifier.create(Nodes.class) + .child(Node.class,nodeKey) + .augmentation(FlowCapableNode.class).child(Meter.class, meterKey); + + if(meterIdIdsOfUsers.containsKey(userId) == false){ + List> meterInsIds = new ArrayList>(); + meterInsIds.add(meterInsId); + meterIdIdsOfUsers.put(userId, meterInsIds); + } + else{ + List> meterInsIds = meterIdIdsOfUsers.get(userId); + meterInsIds.add(meterInsId); + } + LOG.info("nemo:getMeterInsId"); + return meterInsId; + } + + public void updateFlowTable(User user, + VirtualNetwork virtualNetwork, + UserIntentVnMapping userIntentVnMapping, + UserVnPnMapping userVnPnMapping, + PhysicalNetwork physicalNetwork) { + //If new user, generate metadata; + if ( !metadatas.containsKey(user.getUserId()) ) { + metadatas.put(user.getUserId(), ++currentMetadata); + } + + physicalNetworkHelper = new PhysicalNetworkHelper(physicalNetwork); + virtualNetworkHelper = new VirtualNetworkHelper(virtualNetwork); + + updateInPortTable(user, virtualNetwork, userIntentVnMapping, userVnPnMapping, physicalNetwork); + updateMeterTable(user, virtualNetwork, userIntentVnMapping, userVnPnMapping, physicalNetwork); + updateMplsTable(user, virtualNetwork, userIntentVnMapping, userVnPnMapping, physicalNetwork); + updateIpTable(user, virtualNetwork, userIntentVnMapping, userVnPnMapping, physicalNetwork); + updateArpTable(user, virtualNetwork, userIntentVnMapping, userVnPnMapping, physicalNetwork); + } + + /** + * TODO + * + * @author Zhigang Ji + * @param userId TODO + */ + public void deleteFlowEntries(UserId userId) { + deleteFlowTableEntries(userId); + deleteMeterTableEntries(userId); + + flowIdsOfUsers.put(userId, new LinkedList>()); + meterIdIdsOfUsers.put(userId, new LinkedList>()); + + return; + } + + @Override + public void close() throws Exception { + // TODO + } + + /** + * TODO + * + * @author Shixing Liu + * @param physicalDestNodeId TODO + * @param physicalDestPortId TODO + */ + private void configInternalInPortFlowTable(UserId userId, + PhysicalNodeId physicalDestNodeId, + PhysicalPortId physicalDestPortId) { + String nodeID = physicalDestNodeId.getValue(); + String portID = physicalDestPortId.getValue(); + + WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction(); + List instructionList = new LinkedList(); + Match match = new MatchBuilder().setInPort(new NodeConnectorId(portID)).build(); + + GoToTable gotoTable = new GoToTableBuilder().setTableId(MPLS_LABEL_TABLE_ID).build(); + GoToTableCase gotoTableCase = new GoToTableCaseBuilder().setGoToTable(gotoTable).build(); + Instruction instructionGoto = new InstructionBuilder().setOrder(0).setInstruction(gotoTableCase).build(); + instructionList.add(instructionGoto); + + Instructions instructions = new InstructionsBuilder().setInstruction(instructionList).build(); + + FlowId flowId = new FlowId(UUID.randomUUID().toString()); + FlowBuilder flowBuilder = baseFlowBuilder().setId(flowId).setTableId(IN_PORT_TABLE_ID).setPriority(DEFAULT_FLOW_PRIORITY); + Flow flow = flowBuilder.setMatch(match).setInstructions(instructions).build(); + NodeId nodeId = new NodeId(nodeID); + + InstanceIdentifier flowInsId = generateFlowInsId(userId, nodeId, flow.getTableId(), flow.getId()); + + writeTransaction.put(LogicalDatastoreType.CONFIGURATION, flowInsId, flow, true); + writeTransaction.submit(); + + LOG.info("nemo:configInternalInPortFlowTable"); + return; + } + + /** + * TODO + * + * @author Shixing Liu + * @param physicalDestNodeId TODO + * @param physicalDestPortId TODO + * @param destNodeType TODO + */ + private void configExternalInPortFlowTable(UserId userId, + PhysicalNodeId physicalDestNodeId, + PhysicalPortId physicalDestPortId, + VirtualNode.NodeType destNodeType) { + String nodeID = physicalDestNodeId.getValue(); + String portID = physicalDestPortId.getValue(); + + WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction(); + List instructionList = new LinkedList(); + Match match = new MatchBuilder().setInPort(new NodeConnectorId(portID)).build(); + + WriteMetadata writeMetadata = new WriteMetadataBuilder().setMetadata(BigInteger.valueOf(metadatas.get(userId))).setMetadataMask(new BigInteger(DEFAULT_METADATA_MASK, 16)).build(); + WriteMetadataCase writeMetadataCase = new WriteMetadataCaseBuilder().setWriteMetadata(writeMetadata).build(); + Instruction instructionMeta = new InstructionBuilder().setOrder(instructionList.size()).setInstruction(writeMetadataCase).build(); + instructionList.add(instructionMeta); + + GoToTable gotoTable = new GoToTableBuilder().setTableId((destNodeType==VirtualNode.NodeType.Vswitch)? MAC_TABLE_ID : IP_TABLE_ID).build(); + GoToTableCase gotoTableCase = new GoToTableCaseBuilder().setGoToTable(gotoTable).build(); + Instruction instructionGoto = new InstructionBuilder().setOrder(instructionList.size()).setInstruction(gotoTableCase).build(); + instructionList.add(instructionGoto); + + Instructions instructions = new InstructionsBuilder().setInstruction(instructionList).build(); + + FlowId flowId = new FlowId(UUID.randomUUID().toString()); + + FlowBuilder flowBuilder = baseFlowBuilder().setId(flowId).setTableId(IN_PORT_TABLE_ID).setPriority(DEFAULT_FLOW_PRIORITY); + Flow flow = flowBuilder.setMatch(match).setInstructions(instructions).build(); + + NodeId nodeId = new NodeId(nodeID); + + InstanceIdentifier flowInsId = generateFlowInsId(userId, nodeId, flow.getTableId(), flow.getId()); + + writeTransaction.put(LogicalDatastoreType.CONFIGURATION, flowInsId, flow, true); + writeTransaction.submit(); + + LOG.info("nemo:configExternalInPortFlowTable"); + + return; + } + + /** + * TODO + * + * @author Shixing Liu + * @param user TODO + * @param virtualNetwork TODO + * @param userIntentVnMapping TODO + * @param userVnPnMapping TODO + * @param physicalNetwork TODO + */ + private void updateInPortTable(User user, + VirtualNetwork virtualNetwork, + UserIntentVnMapping userIntentVnMapping, + UserVnPnMapping userVnPnMapping, + PhysicalNetwork physicalNetwork) { + List vnPnMappingResults = userVnPnMapping.getVnPnMappingResult(); + + for(VnPnMappingResult vnPnMappingResult:vnPnMappingResults){ + LOG.info("nemo:inport for(VnPnMappingResult vnPnMappingResult:vnPnMappingResults)"); + if(VirtualResource.VirtualResourceType.Vport == vnPnMappingResult.getVirtualResourceType()) { + VirtualPortId virtualPortid = new VirtualPortId(vnPnMappingResult.getVirtualResourceEntityId().getValue()); + VirtualNodeId virtualNodeId = new VirtualNodeId(vnPnMappingResult.getParentVirtualResourceEntityId().getValue()); + + VirtualPort.PortType virtualPortType = VirtualPort.PortType.Internal; + VirtualNode.NodeType virtualNodeType = VirtualNode.NodeType.Vswitch; + + List virtualNodes = virtualNetwork.getVirtualNodes().getVirtualNode(); + for (VirtualNode virtualNode : virtualNodes) { + if (virtualNode.getNodeId().equals(virtualNodeId)){ + virtualNodeType = virtualNode.getNodeType(); + for (VirtualPort virtualPort : virtualNode.getVirtualPort()) { + if (virtualPort.getPortId().equals(virtualPortid)){ + virtualPortType = virtualPort.getPortType(); + break; + } + } + break; + } + } + + PhysicalNodeId physicalDestNodeId = + new PhysicalNodeId(vnPnMappingResult.getParentPhysicalResourceEntityId().getValue()); + + PhysicalPortId physicalDestPortId = + new PhysicalPortId(vnPnMappingResult.getPhysicalResourceEntityId().getValue()); + + if (virtualPortType == VirtualPort.PortType.External) { + configExternalInPortFlowTable(userVnPnMapping.getUserId(), physicalDestNodeId, physicalDestPortId, virtualNodeType); + } else { + configInternalInPortFlowTable(userVnPnMapping.getUserId(), physicalDestNodeId, physicalDestPortId); + } + } + } + + for(PhysicalNode physicalNode: physicalNetwork.getPhysicalNodes().getPhysicalNode()){ + PhysicalNodeId physicalDestNodeId = physicalNode.getNodeId(); + + for (PhysicalPort physicalPort: physicalNode.getPhysicalPort()){ + PhysicalPortId physicalDestPortId = physicalPort.getPortId(); + PhysicalPort.PortType physicalPortType = physicalPort.getPortType(); + + if(physicalPortType == PhysicalPort.PortType.Internal){ + configInternalInPortFlowTable(userVnPnMapping.getUserId(), physicalDestNodeId, physicalDestPortId); + } + } + } + } + + /** + * TODO + * + * @author Shixing Liu + * @param user TODO + * @param virtualNetwork TODO + * @param userIntentVnMapping TODO + * @param userVnPnMapping TODO + * @param physicalNetwork TODO + */ + private void updateMeterTable(User user, + VirtualNetwork virtualNetwork, + UserIntentVnMapping userIntentVnMapping, + UserVnPnMapping userVnPnMapping, + PhysicalNetwork physicalNetwork) { + + LOG.info("nemo:meter updateMeterTable()"); + PhysicalPaths physicalPaths = physicalNetwork.getPhysicalPaths(); + if(null == physicalPaths.getPhysicalPath()){ + LOG.info("PhysicalPath are null"); + return; + } + + List physicalPathList = physicalPaths.getPhysicalPath(); + + PhysicalLinks physicalLinks = physicalNetwork.getPhysicalLinks(); + List + physicalLinksList = physicalLinks.getPhysicalLink(); + + for(PhysicalPath physicalPath:physicalPathList) { + if(physicalPath.getBandwidth() > 0 ) { + LOG.info("nemo: meter physicalPath.getBandwidth() = {}", physicalPath.getBandwidth()); + if(meterIdsOfPhysicalPaths.containsKey(physicalPath.getPathId())== false){ + LOG.info("nemo:meter meterIdsOfPhysicalPaths.containsKey(physicalPath.getPathId())== false"); + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.path.instance.PhysicalLink + physicalLinkInPath = physicalPath.getPhysicalLink().get(0); + + LOG.info("nemo:meter physicalLinkInPath"+physicalLinkInPath.getLinkId().getValue()); + for (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.links.PhysicalLink physicalLink : physicalLinksList) { + LOG.info("nemo:meter physicalLink "+physicalLink.getLinkId().getValue()); + if (physicalLinkInPath.getLinkId().getValue().equals(physicalLink.getLinkId().getValue())) { + + LOG.info("nemo:meter find plink for ppath."); + PhysicalNodeId physicalSrcNodeId = physicalLink.getSrcNodeId(); + PhysicalPortId physicalSrcPortId = physicalLink.getSrcPortId(); + + LOG.info("nemo:meter meterIdGenerators.size() = "+ meterIdGenerators.size()); + LOG.info("nemo:meter physicalSrcNodeId =" + physicalSrcNodeId.getValue()); + + LOG.info("nemo:meter Assign meter id"); + Long meterId = (long)0; + if(meterIdGenerators.containsKey(physicalSrcNodeId) == false){ + LOG.info("meterIdGenerators.containsKey(physicalSrcNodeId) == false"); + MeterIdGenerator meterIdGenerator = new MeterIdGenerator(); + meterIdGenerators.put(physicalSrcNodeId, meterIdGenerator); + meterId = meterIdGenerators.get(physicalSrcNodeId).generateMeterId(); + meterIdsOfPhysicalPaths.put(physicalPath.getPathId(),meterId); + } + else{ + LOG.info("meterIdGenerators.containsKey(physicalSrcNodeId) == true"); + meterId = meterIdGenerators.get(physicalSrcNodeId).generateMeterId(); + meterIdsOfPhysicalPaths.put(physicalPath.getPathId(),meterId); + } + + //Generate meter flow entries + LOG.info("nemo:meter Generate meter flow entries"); + NodeKey nodeKey = new NodeKey(new NodeId(physicalSrcNodeId.getValue())); + MeterKey meterKey = new MeterKey(new MeterId(meterId)); + + InstanceIdentifier meterInsId = generateMeterInsId(userVnPnMapping.getUserId(), nodeKey, meterKey); + + /* + MeterBandHeaderBuilder meterBandHeaderBuilder = new MeterBandHeaderBuilder(); + MeterBandTypesBuilder meterBandTypesB = new MeterBandTypesBuilder(); + MeterBandType bandFlag = new MeterBandType(true, false, false); + meterBandTypesB.setFlags(bandFlag);// _ofpmbtDrop + DropBuilder drop = new DropBuilder(); + drop.setDropBurstSize(physicalPath.getBandwidth() / 2); + drop.setDropRate(physicalPath.getBandwidth()); + Drop drp = drop.build(); + meterBandHeaderBuilder.setBandType(drp); + meterBandHeaderBuilder.setMeterBandTypes(meterBandTypesB.build()); + MeterBandHeader meterBH = meterBandHeaderBuilder.build(); + MeterBuilder meterBuilder = new MeterBuilder(); + meterBuilder.setMeterBandHeaders(meterBandHeadersBuilder.setMeterBandHeader(meterBandHeaders).build()); + */ + + MeterBuilder meterBuilder = new MeterBuilder(); + MeterBandHeaderBuilder meterBandHeaderBuilder = new MeterBandHeaderBuilder(); + MeterBandHeadersBuilder meterBandHeadersBuilder = new MeterBandHeadersBuilder(); + MeterBandTypesBuilder meterBandTypesB = new MeterBandTypesBuilder(); + + meterBandHeaderBuilder.setKey(new MeterBandHeaderKey(new BandId(physicalPath.getBandwidth()))); + meterBandHeaderBuilder.setBandBurstSize((long)0); + meterBandHeaderBuilder.setBandRate(physicalPath.getBandwidth()); + + MeterBandType bandFlag = new MeterBandType(true, false, false); + meterBandTypesB.setFlags(bandFlag);// _ofpmbtDrop + DropBuilder drop = new DropBuilder(); + drop.setDropBurstSize((long)0); + drop.setDropRate(physicalPath.getBandwidth()); + Drop drp = drop.build(); + meterBandHeaderBuilder.setBandType(drp); + meterBandHeaderBuilder.setMeterBandTypes(meterBandTypesB.build()); + + MeterBandHeader meterBH = meterBandHeaderBuilder.build(); + List meterBandHeaders = new ArrayList(); + meterBandHeaders.add(0, meterBH); + + meterBuilder.setKey(new MeterKey(new MeterId(meterId))); + meterBuilder.setBarrier(false); + + meterBuilder.setFlags(new MeterFlags(false, true, false, true)); + + meterBuilder.setContainerName("container." + physicalPath.getPathId()); + meterBuilder.setMeterName("meter." + physicalPath.getPathId()); + meterBandHeadersBuilder.setMeterBandHeader(meterBandHeaders); + meterBuilder.setMeterBandHeaders(meterBandHeadersBuilder.build()); + + Meter meter = meterBuilder.build(); + + WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction(); + writeTransaction.put(LogicalDatastoreType.CONFIGURATION, meterInsId, meter); + writeTransaction.submit(); + LOG.info("nemo:meter writeTransaction.submit();"); + break; + } + } + } + } + } + } + + /** + * TODO + * + * @author Shixing Liu + * @param physicalPath TODO + * @param physicalLinksList TODO + */ + public void assignMPLSLabelForPPath(PhysicalPath physicalPath, + List physicalLinksList){ + + LOG.info("nemo: for(1)"); + List mplsLabels = new ArrayList(); + List + physicalLinksInPath = physicalPath.getPhysicalLink(); + + for (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.path.instance.PhysicalLink physicalLinkinPath : physicalLinksInPath) { + LOG.info("nemo: for(2)"); + for (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.links.PhysicalLink physicalLink : physicalLinksList) { + LOG.info("nemo: for(3)"); + if (physicalLinkinPath.getLinkId().getValue().equals(physicalLink.getLinkId().getValue())) { + LOG.info("nemo: physicalLinkinPath.getLinkId() == physicalLink.getLinkId()"); + PhysicalNodeId physicalDestNodeId = physicalLink.getDestNodeId(); + if(mplsGenerators.containsKey(physicalDestNodeId) == true){ + + mplsLabels.add(mplsGenerators.get(physicalDestNodeId).generateMplsLabel()); + + } + else{ + + MplsLabelGenerator mplsLabelGenerator = new MplsLabelGenerator(); + mplsGenerators.put(physicalDestNodeId, mplsLabelGenerator); + mplsLabels.add(mplsGenerators.get(physicalDestNodeId).generateMplsLabel()); + } + } + } + } + mplsLabelsOfPhysicalPaths.put(physicalPath.getPathId(), mplsLabels); + } + + /** + * TODO + * + * @author Shixing Liu + * @param user TODO + * @param virtualNetwork TODO + * @param userIntentVnMapping TODO + * @param userVnPnMapping TODO + * @param physicalNetwork TODO + */ + private void updateMplsTable(User user, + VirtualNetwork virtualNetwork, + UserIntentVnMapping userIntentVnMapping, + UserVnPnMapping userVnPnMapping, + PhysicalNetwork physicalNetwork) { + + LOG.info("nemo:mpls: updateMplsTable()"); + PhysicalPaths physicalPaths = physicalNetwork.getPhysicalPaths(); + + if(null == physicalPaths.getPhysicalPath()){ + LOG.info("PhysicalPaths are null"); + return; + } + + List physicalPathList = physicalPaths.getPhysicalPath(); + + PhysicalLinks physicalLinks = physicalNetwork.getPhysicalLinks(); + List + physicalLinksList = physicalLinks.getPhysicalLink(); + + Iterator mplsLabelIter = null; + + List vnPnMappingResults = userVnPnMapping.getVnPnMappingResult(); + + for(VnPnMappingResult vnPnMappingResult:vnPnMappingResults) { + if (VirtualResource.VirtualResourceType.Vlink == vnPnMappingResult.getVirtualResourceType()) { + PhysicalPathId physicalPathId = new PhysicalPathId(vnPnMappingResult.getPhysicalResourceEntityId().getValue()); + PhysicalPath physicalPath = physicalNetworkHelper.getPhysicalPath(physicalPathId); + + VirtualLinkId virtualLinkId = new VirtualLinkId(vnPnMappingResult.getVirtualResourceEntityId().getValue()); + VirtualLink virtualLink = virtualNetworkHelper.getVirtualLink(virtualLinkId); + VirtualNodeId virtualNodeId = virtualLink.getDestNodeId(); + VirtualNode.NodeType nodetype = VirtualNode.NodeType.Vswitch; + List virtualNodes = virtualNetwork.getVirtualNodes().getVirtualNode(); + for (VirtualNode virtualNode : virtualNodes) { + if (virtualNode.getNodeId().equals(virtualNodeId)) { + nodetype = virtualNode.getNodeType(); + break; + } + } + + //Assign MPLS Label and record MPLS Label + assignMPLSLabelForPPath(physicalPath,physicalLinksList); + + //Create Flow Entries for MPLS Flow Table + int counter = 0; + int inMPLSLabel = Integer.MAX_VALUE; + int outMPLSLabel = Integer.MAX_VALUE; + + List + physicalLinksInPath = physicalPath.getPhysicalLink(); + for (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.path.instance.PhysicalLink physicalLinkinPath : physicalLinksInPath) { + for (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.links.PhysicalLink physicalLink : physicalLinksList) { + if (physicalLinkinPath.getLinkId().getValue().equals(physicalLink.getLinkId().getValue())) { + PhysicalNodeId physicalDestNodeId = physicalLink.getDestNodeId(); + PhysicalNodeId physicalSrcNodeId = physicalLink.getSrcNodeId(); + PhysicalPortId physicalSrcPortId = physicalLink.getSrcPortId(); + + if (0 == counter++) { + LOG.info("nemo:mpls:0 == counter"); + mplsLabelIter = mplsLabelsOfPhysicalPaths.get(physicalPath.getPathId()).iterator(); + inMPLSLabel = mplsLabelIter.next(); + } else { + LOG.info("nemo:mpls:counter="+counter); + WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction(); + List instructionList = new LinkedList(); + List actionList = new LinkedList(); + outMPLSLabel = mplsLabelIter.next(); + + EthernetMatchBuilder ethernetMatchBuilder = new EthernetMatchBuilder().setEthernetType(new EthernetTypeBuilder().setType(new EtherType((long) ETH_TYPE_MPLS)).build()); + EthernetMatch ethernetMatch = ethernetMatchBuilder.build(); + + ProtocolMatchFieldsBuilder protocolMatchFieldsBuilder = new ProtocolMatchFieldsBuilder().setMplsLabel((long) inMPLSLabel); + ProtocolMatchFields protocolMatchFields = protocolMatchFieldsBuilder.build(); + + Match match = new MatchBuilder().setEthernetMatch(ethernetMatch).setProtocolMatchFields(protocolMatchFields).build(); + + SetField setField = new SetFieldBuilder().setProtocolMatchFields(new ProtocolMatchFieldsBuilder().setMplsLabel((long) outMPLSLabel).build()).build(); + SetFieldCase setFieldCase = new SetFieldCaseBuilder().setSetField(setField).build(); + Action actionSetField = new ActionBuilder().setOrder(0).setAction(setFieldCase).build(); + actionList.add(actionSetField); + + DecMplsTtl decMplsTtl = new DecMplsTtlBuilder().build(); + DecMplsTtlCase decMplsTtlCase = new DecMplsTtlCaseBuilder().setDecMplsTtl(decMplsTtl).build(); + Action actionDecMPLS = new ActionBuilder().setOrder(1).setAction(decMplsTtlCase).build(); + actionList.add(actionDecMPLS); + + OutputAction outputAction = new OutputActionBuilder().setOutputNodeConnector(new NodeConnectorId(physicalSrcPortId.getValue())).build(); + OutputActionCase outputActionCase = new OutputActionCaseBuilder().setOutputAction(outputAction).build(); + Action actionOutput = new ActionBuilder().setOrder(2).setAction(outputActionCase).build(); + actionList.add(actionOutput); + + ApplyActions applyActions = new ApplyActionsBuilder().setAction(actionList).build(); + ApplyActionsCase applyActionsCase = new ApplyActionsCaseBuilder().setApplyActions(applyActions).build(); + Instruction instructionApply = new InstructionBuilder().setOrder(0).setInstruction(applyActionsCase).build(); + instructionList.add(instructionApply); + + Instructions instructions = new InstructionsBuilder().setInstruction(instructionList).build(); + + FlowId flowId = new FlowId(UUID.randomUUID().toString()); + FlowBuilder flowBuilder = baseFlowBuilder().setId(flowId).setTableId(MPLS_LABEL_TABLE_ID).setPriority(DEFAULT_FLOW_PRIORITY); + Flow flow = flowBuilder.setMatch(match).setInstructions(instructions).build(); + + LOG.info("nemo:mpls"+physicalSrcNodeId.getValue()); + + NodeId nodeId = new NodeId(physicalSrcNodeId.getValue()); + + InstanceIdentifier flowInsId = generateFlowInsId(user.getUserId(), nodeId, flow.getTableId(), flow.getId()); + + writeTransaction.put(LogicalDatastoreType.CONFIGURATION, flowInsId, flow, true); + writeTransaction.submit(); + + inMPLSLabel = outMPLSLabel; + } + //The last hop + if (physicalPath.getPhysicalLink().size() == counter) { + LOG.info("nemo:mpls: last hop"); + WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction(); + List instructionList = new LinkedList(); + List actionList = new LinkedList(); + + EthernetMatchBuilder ethernetMatchBuilder = new EthernetMatchBuilder().setEthernetType(new EthernetTypeBuilder().setType(new EtherType((long) ETH_TYPE_MPLS)).build()); + EthernetMatch ethernetMatch = ethernetMatchBuilder.build(); + + ProtocolMatchFieldsBuilder protocolMatchFieldsBuilder = new ProtocolMatchFieldsBuilder().setMplsLabel((long) inMPLSLabel); + ProtocolMatchFields protocolMatchFields = protocolMatchFieldsBuilder.build(); + + Match match = new MatchBuilder().setEthernetMatch(ethernetMatch).setProtocolMatchFields(protocolMatchFields).build(); + + PopMplsAction popMplsAction = new PopMplsActionBuilder().setEthernetType(ETH_TYPE_IP).build(); + PopMplsActionCase popMplsActionCase = new PopMplsActionCaseBuilder().setPopMplsAction(popMplsAction).build(); + Action actionPopMPLS = new ActionBuilder().setOrder(0).setAction(popMplsActionCase).build(); + actionList.add(actionPopMPLS); + + ApplyActions applyActions = new ApplyActionsBuilder().setAction(actionList).build(); + ApplyActionsCase applyActionsCase = new ApplyActionsCaseBuilder().setApplyActions(applyActions).build(); + Instruction instructionApply = new InstructionBuilder().setOrder(0).setInstruction(applyActionsCase).build(); + instructionList.add(instructionApply); + + WriteMetadata writeMetadata = new WriteMetadataBuilder().setMetadata(BigInteger.valueOf(metadatas.get(user.getUserId()))).setMetadataMask(new BigInteger(DEFAULT_METADATA_MASK, 16)).build(); + WriteMetadataCase writeMetadataCase = new WriteMetadataCaseBuilder().setWriteMetadata(writeMetadata).build(); + Instruction instructionMeta = new InstructionBuilder().setOrder(1).setInstruction(writeMetadataCase).build(); + instructionList.add(instructionMeta); + + GoToTable gotoTable = new GoToTableBuilder().setTableId((nodetype == VirtualNode.NodeType.Vswitch)? MAC_TABLE_ID:IP_TABLE_ID).build(); + GoToTableCase gotoTableCase = new GoToTableCaseBuilder().setGoToTable(gotoTable).build(); + Instruction instructionGoto = new InstructionBuilder().setOrder(2).setInstruction(gotoTableCase).build(); + instructionList.add(instructionGoto); + + Instructions instructions = new InstructionsBuilder().setInstruction(instructionList).build(); + + FlowId flowId = new FlowId(UUID.randomUUID().toString()); + FlowBuilder flowBuilder = baseFlowBuilder().setId(flowId).setTableId(MPLS_LABEL_TABLE_ID).setPriority(DEFAULT_FLOW_PRIORITY); + Flow flow = flowBuilder.setMatch(match).setInstructions(instructions).build(); + + LOG.info("nemo:mpls:"+physicalDestNodeId.getValue()); + NodeId nodeId = new NodeId(physicalDestNodeId.getValue()); + InstanceIdentifier flowInsId = generateFlowInsId(user.getUserId(), nodeId, flow.getTableId(), flow.getId()); + + writeTransaction.put(LogicalDatastoreType.CONFIGURATION, flowInsId, flow, true); + writeTransaction.submit(); + } + } + } + } + } + } + } + + /** + * TODO + * + * @author Zhigang Ji + * @param user TODO + * @param virtualNetwork TODO + * @param userIntentVnMapping TODO + * @param userVnPnMapping TODO + * @param physicalNetwork TODO + */ + private void updateIpTable(User user, + VirtualNetwork virtualNetwork, + UserIntentVnMapping userIntentVnMapping, + UserVnPnMapping userVnPnMapping, + PhysicalNetwork physicalNetwork) { + List vnPnMappingResults = userVnPnMapping.getVnPnMappingResult(); + Map virtualRouters = virtualNetworkHelper.getVirtualRouters(); + Map> connectedVirtualSwitches; + Map> connectedVirtualSwitches1; + Map> connectedVirtualRouters; + Map> connectedVirtualRouters1; + VirtualPort layer2ExternalVirtualPort; + VirtualPort layer2ExternalVirtualPort1; + VirtualPort layer2ExternalVirtualPort2; + VirtualPort layer3ExternalVirtualPort; + VirtualPort layer3ExternalVirtualPort1; + VnPnMappingResult vnPnMappingResult; + PhysicalNodeId physicalNodeId; + PhysicalNodeId physicalNodeId1; + VirtualLink virtualLink; + VirtualLink virtualLink1; + PhysicalPathId physicalPathId; + PhysicalPathId physicalPathId1; + PhysicalPath physicalPath; + PhysicalPath physicalPath1; + PhysicalPortId physicalPortId; + PhysicalPort physicalPort; + List remoteIpPrefixes; + List ipPrefixes; + List macAddresses; + VirtualPort virtualPort; + VirtualArp virtualArp; + IpPrefix ipPrefix; + MacAddress gatewayMacAddress; + + for ( VirtualNodeId virtualNodeId : virtualRouters.keySet() ) { + vnPnMappingResult = getVnPnMappingResult(vnPnMappingResults, + new VirtualResourceEntityId(virtualNodeId.getValue())); + physicalNodeId = new PhysicalNodeId(vnPnMappingResult.getPhysicalResourceEntityId().getValue()); + + connectedVirtualRouters = virtualNetworkHelper.getConnectedVirtualRouters(virtualNodeId); + + if ( null != connectedVirtualRouters ) { + for ( Map.Entry> entry + : connectedVirtualRouters.entrySet() ) { + virtualLink = entry.getValue().getValue(); + vnPnMappingResult = getVnPnMappingResult(vnPnMappingResults, + new VirtualResourceEntityId(virtualLink.getLinkId().getValue())); + physicalPathId = new PhysicalPathId( + vnPnMappingResult.getPhysicalResourceEntityId().getValue()); + physicalPath = physicalNetworkHelper.getPhysicalPath(physicalPathId); + remoteIpPrefixes = new LinkedList(); + + connectedVirtualSwitches1 = virtualNetworkHelper + .getConnectedVirtualSwitches(entry.getKey()); + + if ( null != connectedVirtualSwitches1 ) { + virtualPort = connectedVirtualSwitches1.entrySet().iterator().next().getValue().getKey(); + ipPrefix = virtualPort.getExternalIpPrefixes().getExternalIpPrefix().get(0); + remoteIpPrefixes.add(ipPrefix); + } + + layer3ExternalVirtualPort1 = virtualNetworkHelper + .getLayer3ExternalVirtualPort(entry.getKey()); + + if ( null != layer3ExternalVirtualPort1 ) { + remoteIpPrefixes.addAll( + layer3ExternalVirtualPort1.getExternalIpPrefixes().getExternalIpPrefix()); + } + + layer2ExternalVirtualPort1 = virtualNetworkHelper + .getLayer2ExternalVirtualPort(entry.getKey()); + + if ( null != layer2ExternalVirtualPort1 ) { + remoteIpPrefixes.addAll( + layer2ExternalVirtualPort1.getExternalIpPrefixes().getExternalIpPrefix()); + } + + if ( !physicalPath.getPhysicalLink().isEmpty() ) { + for ( IpPrefix ipPrefix1 : remoteIpPrefixes ) { + configIpTableEntry(user.getUserId(), ipPrefix1, physicalPath, false); + } + } + } + } + + connectedVirtualSwitches = virtualNetworkHelper.getConnectedVirtualSwitches(virtualNodeId); + + if ( null != connectedVirtualSwitches ) { + virtualPort = connectedVirtualSwitches.values().iterator().next().getKey(); + ipPrefix = virtualPort.getExternalIpPrefixes().getExternalIpPrefix().get(0); + gatewayMacAddress = getGateWayMacAddress(userIntentVnMapping, virtualNodeId); + + configIpTableEntry(user.getUserId(), ipPrefix, gatewayMacAddress, physicalNodeId); + + for ( Map.Entry> entry + : connectedVirtualSwitches.entrySet() ) { + virtualLink = entry.getValue().getValue(); + vnPnMappingResult = getVnPnMappingResult(vnPnMappingResults, + new VirtualResourceEntityId(virtualLink.getLinkId().getValue())); + physicalPathId = new PhysicalPathId( + vnPnMappingResult.getPhysicalResourceEntityId().getValue()); + physicalPath = physicalNetworkHelper.getPhysicalPath(physicalPathId); + + connectedVirtualRouters1 = virtualNetworkHelper + .getConnectedVirtualRouters(entry.getKey()); + + if ( null != connectedVirtualRouters1 ) { + virtualLink1 = connectedVirtualRouters1.values().iterator().next().getValue(); + vnPnMappingResult = getVnPnMappingResult(vnPnMappingResults, + new VirtualResourceEntityId(virtualLink1.getLinkId().getValue())); + physicalPathId1 = new PhysicalPathId( + vnPnMappingResult.getPhysicalResourceEntityId().getValue()); + physicalPath1 = physicalNetworkHelper.getPhysicalPath(physicalPathId1); + + configMacTableEntry(user.getUserId(), gatewayMacAddress, physicalPath1); + } + + connectedVirtualSwitches1 = virtualNetworkHelper + .getConnectedVirtualSwitches(entry.getKey()); + + if ( null != connectedVirtualSwitches1 ) { + for ( Map.Entry> entry1 + : connectedVirtualSwitches1.entrySet() ) { + virtualLink1 = entry1.getValue().getValue(); + vnPnMappingResult = getVnPnMappingResult(vnPnMappingResults, + new VirtualResourceEntityId(virtualLink1.getLinkId().getValue())); + physicalPathId1 = new PhysicalPathId( + vnPnMappingResult.getPhysicalResourceEntityId().getValue()); + physicalPath1 = physicalNetworkHelper.getPhysicalPath(physicalPathId1); + + if ( !physicalPath1.getPhysicalLink().isEmpty() ) { + layer2ExternalVirtualPort2 = virtualNetworkHelper + .getLayer2ExternalVirtualPort(entry1.getKey()); + + if ( null != layer2ExternalVirtualPort2 ) { + macAddresses = layer2ExternalVirtualPort2 + .getExternalMacAddresses().getExternalMacAddress(); + + for ( MacAddress macAddress : macAddresses ) { + configMacTableEntry(user.getUserId(), macAddress, physicalPath1); + } + } + } + } + } + + layer2ExternalVirtualPort1 = virtualNetworkHelper + .getLayer2ExternalVirtualPort(entry.getKey()); + + if ( null != layer2ExternalVirtualPort1 ) { + vnPnMappingResult = getVnPnMappingResult(vnPnMappingResults, + new VirtualResourceEntityId(layer2ExternalVirtualPort1.getPortId().getValue())); + physicalNodeId1 = new PhysicalNodeId( + vnPnMappingResult.getParentPhysicalResourceEntityId().getValue()); + physicalPortId = new PhysicalPortId( + vnPnMappingResult.getPhysicalResourceEntityId().getValue()); + physicalPort = physicalNetworkHelper.getPhysicalPort(physicalNodeId1, physicalPortId); + + macAddresses = layer2ExternalVirtualPort1 + .getExternalMacAddresses().getExternalMacAddress(); + + for ( MacAddress macAddress : macAddresses ) { + virtualArp = virtualNetworkHelper.getVirtualArp(macAddress); + + configArpTableEntry(user.getUserId(), virtualArp, physicalPath); + configMacTableEntry(user.getUserId(), macAddress, physicalNodeId1, physicalPort); + } + } + } + } + + layer3ExternalVirtualPort = virtualNetworkHelper.getLayer3ExternalVirtualPort(virtualNodeId); + + if ( null != layer3ExternalVirtualPort ) { + vnPnMappingResult = getVnPnMappingResult(vnPnMappingResults, + new VirtualResourceEntityId(layer3ExternalVirtualPort.getPortId().getValue())); + physicalPortId = new PhysicalPortId(vnPnMappingResult.getPhysicalResourceEntityId().getValue()); + physicalPort = physicalNetworkHelper.getPhysicalPort(physicalNodeId, physicalPortId); + + ipPrefixes = layer3ExternalVirtualPort.getExternalIpPrefixes().getExternalIpPrefix(); + + for ( IpPrefix ipPrefix1 : ipPrefixes ) { + configIpTableEntry(user.getUserId(), ipPrefix1, physicalNodeId, physicalPort, false); + } + } + + layer2ExternalVirtualPort = virtualNetworkHelper.getLayer2ExternalVirtualPort(virtualNodeId); + + if ( null != layer2ExternalVirtualPort ) { + // TODO: config ip and arp tables. + } + } + + updateIpTableForOperations(user, virtualNetwork, userIntentVnMapping, userVnPnMapping, physicalNetwork); + + // for testing - jizhigang + // log format: vnode(nodetype) --> vnode(nodetype): vlink; ppath; plinks; mplslabels; meterid; + Set printedVirtualLinks = new HashSet(); + VirtualNode srcVirtualNode; + VirtualNode dstVirtualNode; + PhysicalPath physicalPath2; + + for ( VirtualLink virtualLink2 : virtualNetwork.getVirtualLinks().getVirtualLink() ) { + if ( !printedVirtualLinks.contains(virtualLink2.getLinkId()) ) { + srcVirtualNode = virtualNetworkHelper.virtualNodeMap.get(virtualLink2.getSrcNodeId()); + dstVirtualNode = virtualNetworkHelper.virtualNodeMap.get(virtualLink2.getDestNodeId()); + vnPnMappingResult = getVnPnMappingResult(vnPnMappingResults, new VirtualResourceEntityId(virtualLink2.getLinkId().getValue())); + physicalPath2 = physicalNetworkHelper.getPhysicalPath(new PhysicalPathId(vnPnMappingResult.getPhysicalResourceEntityId().getValue())); + + System.out.println(srcVirtualNode.getNodeId().getValue() + "(" + srcVirtualNode.getNodeType() + ") --> " + + dstVirtualNode.getNodeId().getValue() + "(" + dstVirtualNode.getNodeType() + "): " + virtualLink2.getLinkId().getValue() + "; " + + physicalPath2.getPathId().getValue() + "; " + physicalPath2.getPhysicalLink() + "; " + + mplsLabelsOfPhysicalPaths.get(physicalPath2.getPathId()) + "; " + + meterIdsOfPhysicalPaths.get(physicalPath2.getPathId()) + ";"); + + for ( VirtualLink virtualLink3 : virtualNetwork.getVirtualLinks().getVirtualLink() ) { + if ( virtualLink3.getSrcNodeId().equals(dstVirtualNode.getNodeId()) + && virtualLink3.getDestNodeId().equals(srcVirtualNode.getNodeId()) ) { + vnPnMappingResult = getVnPnMappingResult(vnPnMappingResults, new VirtualResourceEntityId(virtualLink3.getLinkId().getValue())); + physicalPath2 = physicalNetworkHelper.getPhysicalPath(new PhysicalPathId(vnPnMappingResult.getPhysicalResourceEntityId().getValue())); + + System.out.println(dstVirtualNode.getNodeId().getValue() + "(" + dstVirtualNode.getNodeType() + ") --> " + + srcVirtualNode.getNodeId().getValue() + "(" + srcVirtualNode.getNodeType() + "): " + virtualLink3.getLinkId().getValue() + "; " + + physicalPath2.getPathId().getValue() + "; " + physicalPath2.getPhysicalLink() + "; " + + mplsLabelsOfPhysicalPaths.get(physicalPath2.getPathId()) + "; " + + meterIdsOfPhysicalPaths.get(physicalPath2.getPathId()) + ";"); + + printedVirtualLinks.add(virtualLink3.getLinkId()); + } + } + + printedVirtualLinks.add(virtualLink2.getLinkId()); + } + } + // for testing - jizhigang + + return; + } + + /** + * TODO + * + * @author Zhigang Ji + * @param user TODO + * @param virtualNetwork TODO + * @param userIntentVnMapping TODO + * @param userVnPnMapping TODO + * @param physicalNetwork TODO + */ + private void updateArpTable(User user, + VirtualNetwork virtualNetwork, + UserIntentVnMapping userIntentVnMapping, + UserVnPnMapping userVnPnMapping, + PhysicalNetwork physicalNetwork) { + // TODO + } + + /** + * TODO + * + * @author Zhigang Ji + * @param userId TODO + */ + private void deleteFlowTableEntries(UserId userId) { + WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction(); + + for ( InstanceIdentifier flowIid : flowIdsOfUsers.get(userId) ) { + writeTransaction.delete(LogicalDatastoreType.CONFIGURATION, flowIid); + } + + writeTransaction.submit(); + + return; + } + + /** + * TODO + * + * @author Zhigang Ji + * @param userId TODO + */ + private void deleteMeterTableEntries(UserId userId) { + WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction(); + + for ( InstanceIdentifier meterIid : meterIdIdsOfUsers.get(userId) ) { + writeTransaction.delete(LogicalDatastoreType.CONFIGURATION, meterIid); + } + + writeTransaction.submit(); + + return; + } + + /** + * TODO + * + * @author Zhigang Ji + * @param user TODO + * @param virtualNetwork TODO + * @param userIntentVnMapping TODO + * @param userVnPnMapping TODO + * @param physicalNetwork TODO + */ + private void updateIpTableForOperations(User user, + VirtualNetwork virtualNetwork, + UserIntentVnMapping userIntentVnMapping, + UserVnPnMapping userVnPnMapping, + PhysicalNetwork physicalNetwork) { + if ( null == user.getOperations() ) { + return; + } + + List operations = user.getOperations().getOperation(); + + if ( null == operations || operations.isEmpty() ) { + return; + } + + Operation operation = operations.get(0); + + List nemoFlows = + user.getObjects().getFlow(); + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.FlowId nemoFlowId = + new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.FlowId(operation.getTargetObject().getValue()); + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Flow nemoFlow = + getFlow(nemoFlows, nemoFlowId); + + long priority = 1 + operation.getPriority(); + + List intentVnMappingResults = userIntentVnMapping.getIntentVnMappingResult(); + List vnPnMappingResults = userVnPnMapping.getVnPnMappingResult(); + IntentId intentId = new IntentId(operation.getOperationId().getValue()); + IntentVnMappingResult intentVnMappingResult = getIntentVnMappingResult(intentVnMappingResults, intentId); + List virtualResources = sortVirtualResources(intentVnMappingResult.getVirtualResource()); + Iterator iterator = virtualResources.iterator(); + VirtualResource virtualResource; + VirtualResource virtualResource1 = null; + VirtualPathId virtualPathId; + VirtualPath virtualPath; + VirtualLinkId virtualLinkId; + VirtualLink virtualLink; + VirtualNodeId virtualNodeId; + VnPnMappingResult vnPnMappingResult; + + Map> connectedVirtualSwitches; + VirtualPort layer2ExternalVirtualPort; + VirtualPort layer3ExternalVirtualPort; + + PhysicalPathId physicalPathId; + PhysicalPathId physicalPathId1; + PhysicalPath physicalPath; + PhysicalPath physicalPath1; + PhysicalNodeId physicalNodeId; + PhysicalNodeId physicalNodeId1; + PhysicalPortId physicalPortId; + PhysicalPortId physicalPortId1; + PhysicalLink physicalLink; + PhysicalPort physicalPort; + PhysicalPort physicalPort1; + + while ( iterator.hasNext() ) { + virtualResource = iterator.next(); + + if ( null == virtualResource1 ) { + if ( VirtualResource.VirtualResourceType.Vpath + == virtualResource.getVirtualResourceType() ) { + virtualPathId = new VirtualPathId(virtualResource.getVirtualResourceEntityId().getValue()); + virtualPath = virtualNetworkHelper.getVirtualPath(virtualPathId); + virtualLinkId = virtualPath.getVirtualLink().get(0).getLinkId(); + vnPnMappingResult = getVnPnMappingResult(vnPnMappingResults, + new VirtualResourceEntityId(virtualLinkId.getValue())); + physicalPathId = new PhysicalPathId(vnPnMappingResult.getPhysicalResourceEntityId().getValue()); + physicalPath = physicalNetworkHelper.getPhysicalPath(physicalPathId); + + if ( physicalPath.getPhysicalLink().isEmpty() ) { + continue; + } else { + virtualLink = virtualNetworkHelper.getVirtualLink(virtualLinkId); + connectedVirtualSwitches = virtualNetworkHelper + .getConnectedVirtualSwitches(virtualLink.getSrcNodeId()); + + if ( null != connectedVirtualSwitches ) { + for ( Map.Entry entry : connectedVirtualSwitches.values() ) { + vnPnMappingResult = getVnPnMappingResult(vnPnMappingResults, + new VirtualResourceEntityId(entry.getValue().getLinkId().getValue())); + physicalPathId1 = new PhysicalPathId( + vnPnMappingResult.getPhysicalResourceEntityId().getValue()); + physicalPath1 = physicalNetworkHelper.getPhysicalPath(physicalPathId1); + physicalLink = physicalNetworkHelper + .getFirstPhysicalLinkOfPhysicalPath(physicalPath1); + physicalPort = physicalNetworkHelper + .getPhysicalPort(physicalLink.getSrcNodeId(), physicalLink.getSrcPortId()); + + configIpTableEntryForOperation(user.getUserId(), nemoFlow, + physicalPort, physicalPath, (short)priority, true); + } + } + + layer3ExternalVirtualPort = virtualNetworkHelper + .getLayer3ExternalVirtualPort(virtualLink.getSrcNodeId()); + + if ( null != layer3ExternalVirtualPort ) { + vnPnMappingResult = getVnPnMappingResult(vnPnMappingResults, + new VirtualResourceEntityId(layer3ExternalVirtualPort.getPortId().getValue())); + physicalNodeId = new PhysicalNodeId( + vnPnMappingResult.getParentPhysicalResourceEntityId().getValue()); + physicalPortId = new PhysicalPortId( + vnPnMappingResult.getPhysicalResourceEntityId().getValue()); + physicalPort = physicalNetworkHelper.getPhysicalPort(physicalNodeId, physicalPortId); + + configIpTableEntryForOperation(user.getUserId(), nemoFlow, + physicalPort, physicalPath, (short)priority, true); + } + + layer2ExternalVirtualPort = virtualNetworkHelper + .getLayer2ExternalVirtualPort(virtualLink.getSrcNodeId()); + + if ( null != layer2ExternalVirtualPort ) { + vnPnMappingResult = getVnPnMappingResult(vnPnMappingResults, + new VirtualResourceEntityId(layer2ExternalVirtualPort.getPortId().getValue())); + physicalNodeId = new PhysicalNodeId( + vnPnMappingResult.getParentPhysicalResourceEntityId().getValue()); + physicalPortId = new PhysicalPortId( + vnPnMappingResult.getPhysicalResourceEntityId().getValue()); + physicalPort = physicalNetworkHelper.getPhysicalPort(physicalNodeId, physicalPortId); + + configIpTableEntryForOperation(user.getUserId(), nemoFlow, + physicalPort, physicalPath, (short)priority, true); + } + } + } else if ( VirtualResource.VirtualResourceType.Vport + == virtualResource.getVirtualResourceType() ) { + virtualNodeId = new VirtualNodeId(virtualResource.getParentVirtualResourceEntityId().getValue()); + vnPnMappingResult = getVnPnMappingResult(vnPnMappingResults, + new VirtualResourceEntityId(virtualResource.getVirtualResourceEntityId().getValue())); + physicalNodeId = new PhysicalNodeId( + vnPnMappingResult.getParentPhysicalResourceEntityId().getValue()); + physicalPortId = new PhysicalPortId(vnPnMappingResult.getPhysicalResourceEntityId().getValue()); + physicalPort = physicalNetworkHelper.getPhysicalPort(physicalNodeId, physicalPortId); + + connectedVirtualSwitches = virtualNetworkHelper.getConnectedVirtualSwitches(virtualNodeId); + + if ( null != connectedVirtualSwitches ) { + for ( Map.Entry entry : connectedVirtualSwitches.values() ) { + vnPnMappingResult = getVnPnMappingResult(vnPnMappingResults, + new VirtualResourceEntityId(entry.getValue().getLinkId().getValue())); + physicalPathId = new PhysicalPathId( + vnPnMappingResult.getPhysicalResourceEntityId().getValue()); + physicalPath = physicalNetworkHelper.getPhysicalPath(physicalPathId); + physicalLink = physicalNetworkHelper + .getFirstPhysicalLinkOfPhysicalPath(physicalPath); + physicalPort1 = physicalNetworkHelper + .getPhysicalPort(physicalLink.getSrcNodeId(), physicalLink.getSrcPortId()); + + configIpTableEntryForOperation(user.getUserId(), nemoFlow, + physicalNodeId, physicalPort1, physicalPort, (short)priority, true); + } + } + + layer3ExternalVirtualPort = virtualNetworkHelper.getLayer3ExternalVirtualPort(virtualNodeId); + + if ( null != layer3ExternalVirtualPort ) { + vnPnMappingResult = getVnPnMappingResult(vnPnMappingResults, + new VirtualResourceEntityId(layer3ExternalVirtualPort.getPortId().getValue())); + physicalNodeId1 = new PhysicalNodeId( + vnPnMappingResult.getParentPhysicalResourceEntityId().getValue()); + physicalPortId1 = new PhysicalPortId( + vnPnMappingResult.getPhysicalResourceEntityId().getValue()); + physicalPort1 = physicalNetworkHelper.getPhysicalPort(physicalNodeId1, physicalPortId1); + + configIpTableEntryForOperation(user.getUserId(), nemoFlow, + physicalNodeId1, physicalPort1, physicalPort, (short)priority, true); + } + + layer2ExternalVirtualPort = virtualNetworkHelper.getLayer2ExternalVirtualPort(virtualNodeId); + + if ( null != layer2ExternalVirtualPort ) { + vnPnMappingResult = getVnPnMappingResult(vnPnMappingResults, + new VirtualResourceEntityId(layer2ExternalVirtualPort.getPortId().getValue())); + physicalNodeId1 = new PhysicalNodeId( + vnPnMappingResult.getParentPhysicalResourceEntityId().getValue()); + physicalPortId1 = new PhysicalPortId( + vnPnMappingResult.getPhysicalResourceEntityId().getValue()); + physicalPort1 = physicalNetworkHelper.getPhysicalPort(physicalNodeId1, physicalPortId1); + + configIpTableEntryForOperation(user.getUserId(), nemoFlow, + physicalNodeId1, physicalPort1, physicalPort, (short)priority, true); + } + } + } else { + if ( VirtualResource.VirtualResourceType.Vport == virtualResource1.getVirtualResourceType() + && VirtualResource.VirtualResourceType.Vpath == virtualResource.getVirtualResourceType() ) { + virtualPathId = new VirtualPathId(virtualResource.getVirtualResourceEntityId().getValue()); + virtualPath = virtualNetworkHelper.getVirtualPath(virtualPathId); + virtualLinkId = virtualPath.getVirtualLink().get(0).getLinkId(); + vnPnMappingResult = getVnPnMappingResult(vnPnMappingResults, + new VirtualResourceEntityId(virtualLinkId.getValue())); + physicalPathId = new PhysicalPathId(vnPnMappingResult.getPhysicalResourceEntityId().getValue()); + physicalPath = physicalNetworkHelper.getPhysicalPath(physicalPathId); + + if ( physicalPath.getPhysicalLink().isEmpty() ) { + continue; + } else { + vnPnMappingResult = getVnPnMappingResult(vnPnMappingResults, + new VirtualResourceEntityId(virtualResource1.getVirtualResourceEntityId().getValue())); + physicalNodeId = new PhysicalNodeId( + vnPnMappingResult.getParentPhysicalResourceEntityId().getValue()); + physicalPortId = new PhysicalPortId( + vnPnMappingResult.getPhysicalResourceEntityId().getValue()); + physicalPort = physicalNetworkHelper.getPhysicalPort(physicalNodeId, physicalPortId); + + configIpTableEntryForOperation(user.getUserId(), nemoFlow, + physicalPort, physicalPath, (short)priority, true); + } + } else if ( VirtualResource.VirtualResourceType.Vpath == virtualResource1.getVirtualResourceType() + && VirtualResource.VirtualResourceType.Vport == virtualResource.getVirtualResourceType() ) { + virtualPathId = new VirtualPathId(virtualResource1.getVirtualResourceEntityId().getValue()); + virtualPath = virtualNetworkHelper.getVirtualPath(virtualPathId); + virtualLinkId = virtualPath.getVirtualLink().get(0).getLinkId(); + vnPnMappingResult = getVnPnMappingResult(vnPnMappingResults, + new VirtualResourceEntityId(virtualLinkId.getValue())); + physicalPathId = new PhysicalPathId(vnPnMappingResult.getPhysicalResourceEntityId().getValue()); + physicalPath = physicalNetworkHelper.getPhysicalPath(physicalPathId); + physicalLink = physicalNetworkHelper.getLastPhysicalLinkOfPhysicalPath(physicalPath); + physicalPort1 = physicalNetworkHelper + .getPhysicalPort(physicalLink.getDestNodeId(), physicalLink.getDestPortId()); + + vnPnMappingResult = getVnPnMappingResult(vnPnMappingResults, + new VirtualResourceEntityId(virtualResource.getVirtualResourceEntityId().getValue())); + physicalNodeId = new PhysicalNodeId( + vnPnMappingResult.getParentPhysicalResourceEntityId().getValue()); + physicalPortId = new PhysicalPortId( + vnPnMappingResult.getPhysicalResourceEntityId().getValue()); + physicalPort = physicalNetworkHelper.getPhysicalPort(physicalNodeId, physicalPortId); + + configIpTableEntryForOperation(user.getUserId(), nemoFlow, + physicalNodeId, physicalPort1, physicalPort, (short)priority, true); + } else if ( VirtualResource.VirtualResourceType.Vport == virtualResource1.getVirtualResourceType() + && VirtualResource.VirtualResourceType.Vport == virtualResource.getVirtualResourceType() ) { + vnPnMappingResult = getVnPnMappingResult(vnPnMappingResults, + new VirtualResourceEntityId(virtualResource1.getVirtualResourceEntityId().getValue())); + physicalNodeId1 = new PhysicalNodeId( + vnPnMappingResult.getParentPhysicalResourceEntityId().getValue()); + physicalPortId1 = new PhysicalPortId( + vnPnMappingResult.getPhysicalResourceEntityId().getValue()); + physicalPort1 = physicalNetworkHelper.getPhysicalPort(physicalNodeId1, physicalPortId1); + + vnPnMappingResult = getVnPnMappingResult(vnPnMappingResults, + new VirtualResourceEntityId(virtualResource.getVirtualResourceEntityId().getValue())); + physicalNodeId = new PhysicalNodeId( + vnPnMappingResult.getParentPhysicalResourceEntityId().getValue()); + physicalPortId = new PhysicalPortId( + vnPnMappingResult.getPhysicalResourceEntityId().getValue()); + physicalPort = physicalNetworkHelper.getPhysicalPort(physicalNodeId, physicalPortId); + + configIpTableEntryForOperation(user.getUserId(), nemoFlow, + physicalNodeId1, physicalPort1, physicalPort, (short)priority, true); + } + } + + virtualResource1 = virtualResource; + } + + return; + } + + /** + * TODO + * + * @author Zhigang Ji, Shixing Liu + * @param physicalNodeId TODO + * @param physicalPortId TODO + * @return TODO + */ + private MacAddress getMacAddressOfConnectedExternalDevice(PhysicalNodeId physicalNodeId, + PhysicalPortId physicalPortId) { + com.google.common.collect.Table externalNetworkMacTable = + this.resourceManager.getExternalNetworkMacTable(); + + MacAddress macAddress = externalNetworkMacTable.get(physicalNodeId, physicalPortId); + if(macAddress == null){ + LOG.info("nemo: cannot find external network device mac address"); + } + LOG.info("nemo: external network device mac address"); + + return macAddress; + } + + /** + * TODO + * + * @author Zhigang Ji + * @param userIntentVnMapping TODO + * @param virtualNodeId TODO + * @return TODO + */ + private MacAddress getGateWayMacAddress(UserIntentVnMapping userIntentVnMapping, + VirtualNodeId virtualNodeId) { + List intentVnMappingResults = userIntentVnMapping.getIntentVnMappingResult(); + VirtualResource virtualResource; + + for ( IntentVnMappingResult intentVnMappingResult : intentVnMappingResults ) { + virtualResource = intentVnMappingResult.getVirtualResource().get(0); + + if ( virtualResource.getVirtualResourceEntityId().getValue().equals(virtualNodeId.getValue()) ) { + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.NodeId nodeId = + new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.NodeId(intentVnMappingResult.getIntentId().getValue()); + + return gatewayMacAddress.get(nodeId); + } + } + + return null; + } + + /** + * TODO + * + * @author Zhigang Ji + * @param flows TODO + * @param flowId TODO + * @return TODO + */ + private org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Flow getFlow( + List flows, + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.common.rev151010.FlowId flowId) { + for ( org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Flow + flow : flows ) { + if ( flow.getFlowId().equals(flowId) ) { + return flow; + } + } + + return null; + } + + /** + * TODO + * + * @author Zhigang Ji + * @param matchItems TODO + * @param matchItemName TODO + * @return TODO + */ + private MatchItem getMatchItem(List matchItems, MatchItemName matchItemName) { + for ( MatchItem matchItem : matchItems ) { + if ( matchItem.getMatchItemName().equals(matchItemName) ) { + return matchItem; + } + } + + return null; + } + + /** + * TODO + * + * @author Zhigang Ji + * @param intentVnMappingResults TODO + * @param intentId TODO + * @return TODO + */ + private IntentVnMappingResult getIntentVnMappingResult( + List intentVnMappingResults, IntentId intentId) { + for ( IntentVnMappingResult intentVnMappingResult : intentVnMappingResults ) { + if ( intentVnMappingResult.getIntentId().equals(intentId) ) { + return intentVnMappingResult; + } + } + + return null; + } + + /** + * TODO + * + * @author Zhigang Ji + * @param vnPnMappingResults TODO + * @param virtualResourceEntityId TODO + * @return TODO + */ + private VnPnMappingResult getVnPnMappingResult(List vnPnMappingResults, + VirtualResourceEntityId virtualResourceEntityId) { + for ( VnPnMappingResult vnPnMappingResult : vnPnMappingResults ) { + if ( vnPnMappingResult.getVirtualResourceEntityId().equals(virtualResourceEntityId) ) { + return vnPnMappingResult; + } + } + + return null; + } + + /** + * TODO + * + * @author Zhigang Ji + * @param virtualResources TODO + * @return TODO + */ + private List sortVirtualResources(List virtualResources) { + if ( null == virtualResources || 2 > virtualResources.size() ) { + return virtualResources; + } + + List sortedVirtualResources = + new ArrayList(virtualResources.size()); + sortedVirtualResources.addAll(virtualResources); + + for ( VirtualResource virtualResource : virtualResources ) { + sortedVirtualResources.set(virtualResource.getOrder().intValue(), virtualResource); + } + + return sortedVirtualResources; + } + + /** + * TODO + * + * @author Zhigang Ji + * @param userId TODO + * @param macAddress TODO + * @param physicalNodeId TODO + * @param physicalPort TODO + */ + private void configMacTableEntry(UserId userId, MacAddress macAddress, + PhysicalNodeId physicalNodeId, PhysicalPort physicalPort) { + WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction(); + List instructionList = new LinkedList(); + List actionList = new LinkedList(); + + EthernetMatchBuilder ethernetMatchBuilder = new EthernetMatchBuilder().setEthernetDestination(new EthernetDestinationBuilder().setAddress(macAddress).build()); + EthernetMatch ethernetMatch = ethernetMatchBuilder.build(); + + MetadataBuilder metadataBuilder = new MetadataBuilder().setMetadata(BigInteger.valueOf(metadatas.get(userId))); + Metadata metadata = metadataBuilder.build(); + + Match match = new MatchBuilder().setEthernetMatch(ethernetMatch).setMetadata(metadata).build(); + + OutputAction outputAction = new OutputActionBuilder().setOutputNodeConnector(createNodeConnectorId(physicalPort.getPortId())).build(); + OutputActionCase outputActionCase = new OutputActionCaseBuilder().setOutputAction(outputAction).build(); + Action actionOutput = new ActionBuilder().setOrder(actionList.size()).setAction(outputActionCase).build(); + actionList.add(actionOutput); + + ApplyActions applyActions = new ApplyActionsBuilder().setAction(actionList).build(); + ApplyActionsCase applyActionsCase = new ApplyActionsCaseBuilder().setApplyActions(applyActions).build(); + Instruction instructionApply = new InstructionBuilder().setOrder(instructionList.size()).setInstruction(applyActionsCase).build(); + instructionList.add(instructionApply); + + Instructions instructions = new InstructionsBuilder().setInstruction(instructionList).build(); + + FlowId flowId = new FlowId(UUID.randomUUID().toString()); + FlowBuilder flowBuilder = baseFlowBuilder().setId(flowId).setTableId(MAC_TABLE_ID).setPriority(DEFAULT_FLOW_PRIORITY); + Flow flow = flowBuilder.setMatch(match).setInstructions(instructions).build(); + + NodeId nodeId = createNodeId(physicalNodeId); + InstanceIdentifier flowInsId = generateFlowInsId(userId, nodeId, flow.getTableId(), flow.getId()); + + writeTransaction.put(LogicalDatastoreType.CONFIGURATION, flowInsId, flow, true); + writeTransaction.submit(); + + return; + } + + /** + * TODO + * + * @author Zhigang Ji + * @param userId TODO + * @param macAddress TODO + * @param physicalPath TODO + */ + private void configMacTableEntry(UserId userId, MacAddress macAddress, + PhysicalPath physicalPath) { + WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction(); + List instructionList = new LinkedList(); + List actionList = new LinkedList(); + + PhysicalLink physicalLink = physicalNetworkHelper.getFirstPhysicalLinkOfPhysicalPath(physicalPath); + + EthernetMatchBuilder ethernetMatchBuilder = new EthernetMatchBuilder().setEthernetDestination(new EthernetDestinationBuilder().setAddress(macAddress).build()); + EthernetMatch ethernetMatch = ethernetMatchBuilder.build(); + + MetadataBuilder metadataBuilder = new MetadataBuilder().setMetadata(BigInteger.valueOf(metadatas.get(userId))); + Metadata metadata = metadataBuilder.build(); + + Match match = new MatchBuilder().setEthernetMatch(ethernetMatch).setMetadata(metadata).build(); + + PushMplsAction pushMplsAction = new PushMplsActionBuilder().setEthernetType(ETH_TYPE_MPLS).build(); + PushMplsActionCase pushMplsActionCase = new PushMplsActionCaseBuilder().setPushMplsAction(pushMplsAction).build(); + Action actionPushMPLS = new ActionBuilder().setOrder(actionList.size()).setAction(pushMplsActionCase).build(); + actionList.add(actionPushMPLS); + + SetField setField = new SetFieldBuilder().setProtocolMatchFields(new ProtocolMatchFieldsBuilder().setMplsLabel((long)mplsLabelsOfPhysicalPaths.get(physicalPath.getPathId()).get(0)).build()).build(); + SetFieldCase setFieldCase = new SetFieldCaseBuilder().setSetField(setField).build(); + Action actionSetField = new ActionBuilder().setOrder(actionList.size()).setAction(setFieldCase).build(); + actionList.add(actionSetField); + + OutputAction outputAction = new OutputActionBuilder().setOutputNodeConnector(createNodeConnectorId(physicalLink.getSrcPortId())).build(); + OutputActionCase outputActionCase = new OutputActionCaseBuilder().setOutputAction(outputAction).build(); + Action actionOutput = new ActionBuilder().setOrder(actionList.size()).setAction(outputActionCase).build(); + actionList.add(actionOutput); + + ApplyActions applyActions = new ApplyActionsBuilder().setAction(actionList).build(); + ApplyActionsCase applyActionsCase = new ApplyActionsCaseBuilder().setApplyActions(applyActions).build(); + Instruction instructionApply = new InstructionBuilder().setOrder(instructionList.size()).setInstruction(applyActionsCase).build(); + instructionList.add(instructionApply); + + Instructions instructions = new InstructionsBuilder().setInstruction(instructionList).build(); + + FlowId flowId = new FlowId(UUID.randomUUID().toString()); + FlowBuilder flowBuilder = baseFlowBuilder().setId(flowId).setTableId(MAC_TABLE_ID).setPriority(DEFAULT_FLOW_PRIORITY); + Flow flow = flowBuilder.setMatch(match).setInstructions(instructions).build(); + + NodeId nodeId = createNodeId(physicalLink.getSrcNodeId()); + InstanceIdentifier flowInsId = generateFlowInsId(userId, nodeId, flow.getTableId(), flow.getId()); + + writeTransaction.put(LogicalDatastoreType.CONFIGURATION, flowInsId, flow, true); + writeTransaction.submit(); + + return; + } + + /** + * TODO + * + * @author Zhigang Ji + * @param userId TODO + * @param ipPrefix TODO + * @param physicalNodeId TODO + * @param physicalPort TODO + * @param goToArpTable TODO + */ + private void configIpTableEntry(UserId userId, IpPrefix ipPrefix, PhysicalNodeId physicalNodeId, + PhysicalPort physicalPort, boolean goToArpTable) { + WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction(); + List instructionList = new LinkedList(); + List actionList = new LinkedList(); + + EthernetMatchBuilder ethernetMatchBuilder = new EthernetMatchBuilder().setEthernetType(new EthernetTypeBuilder().setType(new EtherType((long)ETH_TYPE_IP)).build()); + EthernetMatch ethernetMatch = ethernetMatchBuilder.build(); + + MetadataBuilder metadataBuilder = new MetadataBuilder().setMetadata(BigInteger.valueOf(metadatas.get(userId))); + Metadata metadata = metadataBuilder.build(); + + Ipv4MatchBuilder ipv4MatchBuilder = new Ipv4MatchBuilder().setIpv4Destination(ipPrefix.getIpv4Prefix()); + Ipv4Match ipv4Match = ipv4MatchBuilder.build(); + + Match match = new MatchBuilder().setEthernetMatch(ethernetMatch).setMetadata(metadata).setLayer3Match(ipv4Match).build(); + + DecNwTtl decNwTtl = new DecNwTtlBuilder().build(); + DecNwTtlCase decNwTtlCase = new DecNwTtlCaseBuilder().setDecNwTtl(decNwTtl).build(); + Action actionDecNW = new ActionBuilder().setOrder(actionList.size()).setAction(decNwTtlCase).build(); + actionList.add(actionDecNW); + + ethernetMatchBuilder = new EthernetMatchBuilder().setEthernetSource(new EthernetSourceBuilder().setAddress(physicalPort.getMacAddress()).build()); + ethernetMatch = ethernetMatchBuilder.build(); + + SetField setField = new SetFieldBuilder().setEthernetMatch(ethernetMatch).build(); + SetFieldCase setFieldCase = new SetFieldCaseBuilder().setSetField(setField).build(); + Action actionSetField = new ActionBuilder().setOrder(actionList.size()).setAction(setFieldCase).build(); + actionList.add(actionSetField); + + if ( goToArpTable ) + { + ApplyActions applyActions = new ApplyActionsBuilder().setAction(actionList).build(); + ApplyActionsCase applyActionsCase = new ApplyActionsCaseBuilder().setApplyActions(applyActions).build(); + Instruction instructionApply = new InstructionBuilder().setOrder(instructionList.size()).setInstruction(applyActionsCase).build(); + instructionList.add(instructionApply); + + WriteMetadata writeMetadata = new WriteMetadataBuilder().setMetadata(BigInteger.valueOf(metadatas.get(userId))).setMetadataMask(new BigInteger(DEFAULT_METADATA_MASK, 16)).build(); + WriteMetadataCase writeMetadataCase = new WriteMetadataCaseBuilder().setWriteMetadata(writeMetadata).build(); + Instruction instructionMeta = new InstructionBuilder().setOrder(instructionList.size()).setInstruction(writeMetadataCase).build(); + instructionList.add(instructionMeta); + + GoToTable gotoTable = new GoToTableBuilder().setTableId(ARP_TABLE_ID).build(); + GoToTableCase gotoTableCase = new GoToTableCaseBuilder().setGoToTable(gotoTable).build(); + Instruction instructionGoto = new InstructionBuilder().setOrder(instructionList.size()).setInstruction(gotoTableCase).build(); + instructionList.add(instructionGoto); + } + else + { + ethernetMatchBuilder = new EthernetMatchBuilder().setEthernetDestination(new EthernetDestinationBuilder().setAddress(getMacAddressOfConnectedExternalDevice(physicalNodeId, physicalPort.getPortId())).build()); + ethernetMatch = ethernetMatchBuilder.build(); + + setField = new SetFieldBuilder().setEthernetMatch(ethernetMatch).build(); + setFieldCase = new SetFieldCaseBuilder().setSetField(setField).build(); + actionSetField = new ActionBuilder().setOrder(actionList.size()).setAction(setFieldCase).build(); + actionList.add(actionSetField); + + OutputAction outputAction = new OutputActionBuilder().setOutputNodeConnector(createNodeConnectorId(physicalPort.getPortId())).build(); + OutputActionCase outputActionCase = new OutputActionCaseBuilder().setOutputAction(outputAction).build(); + Action actionOutput = new ActionBuilder().setOrder(actionList.size()).setAction(outputActionCase).build(); + actionList.add(actionOutput); + + ApplyActions applyActions = new ApplyActionsBuilder().setAction(actionList).build(); + ApplyActionsCase applyActionsCase = new ApplyActionsCaseBuilder().setApplyActions(applyActions).build(); + Instruction instructionApply = new InstructionBuilder().setOrder(instructionList.size()).setInstruction(applyActionsCase).build(); + instructionList.add(instructionApply); + } + + Instructions instructions = new InstructionsBuilder().setInstruction(instructionList).build(); + + FlowId flowId = new FlowId(UUID.randomUUID().toString()); + FlowBuilder flowBuilder = baseFlowBuilder().setId(flowId).setTableId(IP_TABLE_ID).setPriority(DEFAULT_FLOW_PRIORITY); + Flow flow = flowBuilder.setMatch(match).setInstructions(instructions).build(); + + NodeId nodeId = createNodeId(physicalNodeId); + InstanceIdentifier flowInsId = generateFlowInsId(userId, nodeId, flow.getTableId(), flow.getId()); + + writeTransaction.put(LogicalDatastoreType.CONFIGURATION, flowInsId, flow, true); + writeTransaction.submit(); + + return; + } + + /** + * TODO + * + * @author Zhigang Ji + * @param userId TODO + * @param ipPrefix TODO + * @param physicalPath TODO + * @param goToArpTable TODO + */ + private void configIpTableEntry(UserId userId, IpPrefix ipPrefix, + PhysicalPath physicalPath, boolean goToArpTable) { + WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction(); + List instructionList = new LinkedList(); + List actionList = new LinkedList(); + + PhysicalLink physicalLink = physicalNetworkHelper.getFirstPhysicalLinkOfPhysicalPath(physicalPath); + + EthernetMatchBuilder ethernetMatchBuilder = new EthernetMatchBuilder().setEthernetType(new EthernetTypeBuilder().setType(new EtherType((long)ETH_TYPE_IP)).build()); + EthernetMatch ethernetMatch = ethernetMatchBuilder.build(); + + MetadataBuilder metadataBuilder = new MetadataBuilder().setMetadata(BigInteger.valueOf(metadatas.get(userId))); + Metadata metadata = metadataBuilder.build(); + + Ipv4MatchBuilder ipv4MatchBuilder = new Ipv4MatchBuilder().setIpv4Destination(ipPrefix.getIpv4Prefix()); + Ipv4Match ipv4Match = ipv4MatchBuilder.build(); + + Match match = new MatchBuilder().setEthernetMatch(ethernetMatch).setMetadata(metadata).setLayer3Match(ipv4Match).build(); + + if ( 0 < physicalPath.getBandwidth() ) { + org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.meter._case.Meter + meter = new org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.meter._case.MeterBuilder() + .setMeterId(new MeterId(meterIdsOfPhysicalPaths.get(physicalPath.getPathId()))).build(); + MeterCase meterCase = new MeterCaseBuilder().setMeter(meter).build(); + Instruction instructionMeter = new InstructionBuilder().setOrder(instructionList.size()).setInstruction(meterCase).build(); + instructionList.add(instructionMeter); + } + + DecNwTtl decNwTtl = new DecNwTtlBuilder().build(); + DecNwTtlCase decNwTtlCase = new DecNwTtlCaseBuilder().setDecNwTtl(decNwTtl).build(); + Action actionDecNW = new ActionBuilder().setOrder(actionList.size()).setAction(decNwTtlCase).build(); + actionList.add(actionDecNW); + + if ( goToArpTable ) + { + PhysicalPort physicalPort = physicalNetworkHelper.getPhysicalPort(physicalLink.getSrcNodeId(), physicalLink.getSrcPortId()); + + ethernetMatchBuilder = new EthernetMatchBuilder().setEthernetSource(new EthernetSourceBuilder().setAddress(physicalPort.getMacAddress()).build()); + ethernetMatch = ethernetMatchBuilder.build(); + + SetField setField = new SetFieldBuilder().setEthernetMatch(ethernetMatch).build(); + SetFieldCase setFieldCase = new SetFieldCaseBuilder().setSetField(setField).build(); + Action actionSetField = new ActionBuilder().setOrder(actionList.size()).setAction(setFieldCase).build(); + actionList.add(actionSetField); + + ApplyActions applyActions = new ApplyActionsBuilder().setAction(actionList).build(); + ApplyActionsCase applyActionsCase = new ApplyActionsCaseBuilder().setApplyActions(applyActions).build(); + Instruction instructionApply = new InstructionBuilder().setOrder(instructionList.size()).setInstruction(applyActionsCase).build(); + instructionList.add(instructionApply); + + WriteMetadata writeMetadata = new WriteMetadataBuilder().setMetadata(BigInteger.valueOf(metadatas.get(userId))).setMetadataMask(new BigInteger(DEFAULT_METADATA_MASK, 16)).build(); + WriteMetadataCase writeMetadataCase = new WriteMetadataCaseBuilder().setWriteMetadata(writeMetadata).build(); + Instruction instructionMeta = new InstructionBuilder().setOrder(instructionList.size()).setInstruction(writeMetadataCase).build(); + instructionList.add(instructionMeta); + + GoToTable gotoTable = new GoToTableBuilder().setTableId(ARP_TABLE_ID).build(); + GoToTableCase gotoTableCase = new GoToTableCaseBuilder().setGoToTable(gotoTable).build(); + Instruction instructionGoto = new InstructionBuilder().setOrder(instructionList.size()).setInstruction(gotoTableCase).build(); + instructionList.add(instructionGoto); + } + else + { + PushMplsAction pushMplsAction = new PushMplsActionBuilder().setEthernetType(ETH_TYPE_MPLS).build(); + PushMplsActionCase pushMplsActionCase = new PushMplsActionCaseBuilder().setPushMplsAction(pushMplsAction).build(); + Action actionPushMPLS = new ActionBuilder().setOrder(actionList.size()).setAction(pushMplsActionCase).build(); + actionList.add(actionPushMPLS); + + SetField setField = new SetFieldBuilder().setProtocolMatchFields(new ProtocolMatchFieldsBuilder().setMplsLabel((long)mplsLabelsOfPhysicalPaths.get(physicalPath.getPathId()).get(0)).build()).build(); + SetFieldCase setFieldCase = new SetFieldCaseBuilder().setSetField(setField).build(); + Action actionSetField = new ActionBuilder().setOrder(actionList.size()).setAction(setFieldCase).build(); + actionList.add(actionSetField); + + OutputAction outputAction = new OutputActionBuilder().setOutputNodeConnector(createNodeConnectorId(physicalLink.getSrcPortId())).build(); + OutputActionCase outputActionCase = new OutputActionCaseBuilder().setOutputAction(outputAction).build(); + Action actionOutput = new ActionBuilder().setOrder(actionList.size()).setAction(outputActionCase).build(); + actionList.add(actionOutput); + + ApplyActions applyActions = new ApplyActionsBuilder().setAction(actionList).build(); + ApplyActionsCase applyActionsCase = new ApplyActionsCaseBuilder().setApplyActions(applyActions).build(); + Instruction instructionApply = new InstructionBuilder().setOrder(instructionList.size()).setInstruction(applyActionsCase).build(); + instructionList.add(instructionApply); + } + + Instructions instructions = new InstructionsBuilder().setInstruction(instructionList).build(); + + FlowId flowId = new FlowId(UUID.randomUUID().toString()); + FlowBuilder flowBuilder = baseFlowBuilder().setId(flowId).setTableId(IP_TABLE_ID).setPriority(DEFAULT_FLOW_PRIORITY); + Flow flow = flowBuilder.setMatch(match).setInstructions(instructions).build(); + + NodeId nodeId = createNodeId(physicalLink.getSrcNodeId()); + InstanceIdentifier flowInsId = generateFlowInsId(userId, nodeId, flow.getTableId(), flow.getId()); + + writeTransaction.put(LogicalDatastoreType.CONFIGURATION, flowInsId, flow, true); + writeTransaction.submit(); + + return; + } + + /** + * TODO + * + * @author Zhigang Ji + * @param userId TODO + * @param ipPrefix TODO + * @param macAddress TODO + * @param physicalNodeId TODO + */ + private void configIpTableEntry(UserId userId, IpPrefix ipPrefix, + MacAddress macAddress, PhysicalNodeId physicalNodeId) { + WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction(); + List instructionList = new LinkedList(); + List actionList = new LinkedList(); + + EthernetMatchBuilder ethernetMatchBuilder = new EthernetMatchBuilder().setEthernetType(new EthernetTypeBuilder().setType(new EtherType((long)ETH_TYPE_IP)).build()); + EthernetMatch ethernetMatch = ethernetMatchBuilder.build(); + + MetadataBuilder metadataBuilder = new MetadataBuilder().setMetadata(BigInteger.valueOf(metadatas.get(userId))); + Metadata metadata = metadataBuilder.build(); + + Ipv4MatchBuilder ipv4MatchBuilder = new Ipv4MatchBuilder().setIpv4Destination(ipPrefix.getIpv4Prefix()); + Ipv4Match ipv4Match = ipv4MatchBuilder.build(); + + Match match = new MatchBuilder().setEthernetMatch(ethernetMatch).setMetadata(metadata).setLayer3Match(ipv4Match).build(); + + DecNwTtl decNwTtl = new DecNwTtlBuilder().build(); + DecNwTtlCase decNwTtlCase = new DecNwTtlCaseBuilder().setDecNwTtl(decNwTtl).build(); + Action actionDecNW = new ActionBuilder().setOrder(actionList.size()).setAction(decNwTtlCase).build(); + actionList.add(actionDecNW); + + ethernetMatchBuilder = new EthernetMatchBuilder().setEthernetSource(new EthernetSourceBuilder().setAddress(macAddress).build()); + ethernetMatch = ethernetMatchBuilder.build(); + + SetField setField = new SetFieldBuilder().setEthernetMatch(ethernetMatch).build(); + SetFieldCase setFieldCase = new SetFieldCaseBuilder().setSetField(setField).build(); + Action actionSetField = new ActionBuilder().setOrder(actionList.size()).setAction(setFieldCase).build(); + actionList.add(actionSetField); + + ApplyActions applyActions = new ApplyActionsBuilder().setAction(actionList).build(); + ApplyActionsCase applyActionsCase = new ApplyActionsCaseBuilder().setApplyActions(applyActions).build(); + Instruction instructionApply = new InstructionBuilder().setOrder(instructionList.size()).setInstruction(applyActionsCase).build(); + instructionList.add(instructionApply); + + WriteMetadata writeMetadata = new WriteMetadataBuilder().setMetadata(BigInteger.valueOf(metadatas.get(userId))).setMetadataMask(new BigInteger(DEFAULT_METADATA_MASK, 16)).build(); + WriteMetadataCase writeMetadataCase = new WriteMetadataCaseBuilder().setWriteMetadata(writeMetadata).build(); + Instruction instructionMeta = new InstructionBuilder().setOrder(instructionList.size()).setInstruction(writeMetadataCase).build(); + instructionList.add(instructionMeta); + + GoToTable gotoTable = new GoToTableBuilder().setTableId(ARP_TABLE_ID).build(); + GoToTableCase gotoTableCase = new GoToTableCaseBuilder().setGoToTable(gotoTable).build(); + Instruction instructionGoto = new InstructionBuilder().setOrder(instructionList.size()).setInstruction(gotoTableCase).build(); + instructionList.add(instructionGoto); + + Instructions instructions = new InstructionsBuilder().setInstruction(instructionList).build(); + + FlowId flowId = new FlowId(UUID.randomUUID().toString()); + FlowBuilder flowBuilder = baseFlowBuilder().setId(flowId).setTableId(IP_TABLE_ID).setPriority(DEFAULT_FLOW_PRIORITY); + Flow flow = flowBuilder.setMatch(match).setInstructions(instructions).build(); + + NodeId nodeId = createNodeId(physicalNodeId); + InstanceIdentifier flowInsId = generateFlowInsId(userId, nodeId, flow.getTableId(), flow.getId()); + + writeTransaction.put(LogicalDatastoreType.CONFIGURATION, flowInsId, flow, true); + writeTransaction.submit(); + + return; + } + + /** + * TODO + * + * @author Zhigang Ji + * @param userId TODO + * @param virtualArp TODO + * @param physicalPath TODO + */ + private void configArpTableEntry(UserId userId, VirtualArp virtualArp, PhysicalPath physicalPath) { + WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction(); + List instructionList = new LinkedList(); + List actionList = new LinkedList(); + + PhysicalLink physicalLink = physicalNetworkHelper.getFirstPhysicalLinkOfPhysicalPath(physicalPath); + + EthernetMatchBuilder ethernetMatchBuilder = new EthernetMatchBuilder().setEthernetType(new EthernetTypeBuilder().setType(new EtherType((long)ETH_TYPE_IP)).build()); + EthernetMatch ethernetMatch = ethernetMatchBuilder.build(); + + Ipv4MatchBuilder ipv4MatchBuilder = new Ipv4MatchBuilder().setIpv4Destination(convertIpAddressToIpPrefix(virtualArp.getIpAddress()).getIpv4Prefix()); + Ipv4Match ipv4Match = ipv4MatchBuilder.build(); + + MetadataBuilder metadataBuilder = new MetadataBuilder().setMetadata(BigInteger.valueOf(metadatas.get(userId))); + Metadata metadata = metadataBuilder.build(); + + Match match = new MatchBuilder().setEthernetMatch(ethernetMatch).setLayer3Match(ipv4Match).setMetadata(metadata).build(); + + PushMplsAction pushMplsAction = new PushMplsActionBuilder().setEthernetType(ETH_TYPE_MPLS).build(); + PushMplsActionCase pushMplsActionCase = new PushMplsActionCaseBuilder().setPushMplsAction(pushMplsAction).build(); + Action actionPushMPLS = new ActionBuilder().setOrder(actionList.size()).setAction(pushMplsActionCase).build(); + actionList.add(actionPushMPLS); + + SetField setField = new SetFieldBuilder().setProtocolMatchFields(new ProtocolMatchFieldsBuilder().setMplsLabel((long)mplsLabelsOfPhysicalPaths.get(physicalPath.getPathId()).get(0)).build()).build(); + SetFieldCase setFieldCase = new SetFieldCaseBuilder().setSetField(setField).build(); + Action actionSetField = new ActionBuilder().setOrder(actionList.size()).setAction(setFieldCase).build(); + actionList.add(actionSetField); + + ethernetMatchBuilder = new EthernetMatchBuilder().setEthernetDestination(new EthernetDestinationBuilder().setAddress(virtualArp.getMacAddress()).build()); + ethernetMatch = ethernetMatchBuilder.build(); + + setField = new SetFieldBuilder().setEthernetMatch(ethernetMatch).build(); + setFieldCase = new SetFieldCaseBuilder().setSetField(setField).build(); + actionSetField = new ActionBuilder().setOrder(actionList.size()).setAction(setFieldCase).build(); + actionList.add(actionSetField); + + OutputAction outputAction = new OutputActionBuilder().setOutputNodeConnector(createNodeConnectorId(physicalLink.getSrcPortId())).build(); + OutputActionCase outputActionCase = new OutputActionCaseBuilder().setOutputAction(outputAction).build(); + Action actionOutput = new ActionBuilder().setOrder(actionList.size()).setAction(outputActionCase).build(); + actionList.add(actionOutput); + + ApplyActions applyActions = new ApplyActionsBuilder().setAction(actionList).build(); + ApplyActionsCase applyActionsCase = new ApplyActionsCaseBuilder().setApplyActions(applyActions).build(); + Instruction instructionApply = new InstructionBuilder().setOrder(instructionList.size()).setInstruction(applyActionsCase).build(); + instructionList.add(instructionApply); + + Instructions instructions = new InstructionsBuilder().setInstruction(instructionList).build(); + + FlowId flowId = new FlowId(UUID.randomUUID().toString()); + FlowBuilder flowBuilder = baseFlowBuilder().setId(flowId).setTableId(ARP_TABLE_ID).setPriority(DEFAULT_FLOW_PRIORITY); + Flow flow = flowBuilder.setMatch(match).setInstructions(instructions).build(); + + NodeId nodeId = createNodeId(physicalLink.getSrcNodeId()); + InstanceIdentifier flowInsId = generateFlowInsId(userId, nodeId, flow.getTableId(), flow.getId()); + + writeTransaction.put(LogicalDatastoreType.CONFIGURATION, flowInsId, flow, true); + writeTransaction.submit(); + + return; + } + + /** + * TODO + * + * @author Zhigang Ji + * @param userId TODO + * @param nemoFlow TODO + * @param physicalNodeId TODO + * @param inPhysicalPort TODO + * @param outPhysicalPort TODO + * @param policyPriority TODO + * @param layer3Forwarding TODO + */ + private void configIpTableEntryForOperation(UserId userId, + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Flow nemoFlow, + PhysicalNodeId physicalNodeId, + PhysicalPort inPhysicalPort, + PhysicalPort outPhysicalPort, + short policyPriority, + boolean layer3Forwarding) { + WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction(); + List instructionList = new LinkedList(); + List actionList = new LinkedList(); + + Match match = createMatch(userId, nemoFlow, inPhysicalPort); + + if ( layer3Forwarding ) + { + DecNwTtl decNwTtl = new DecNwTtlBuilder().build(); + DecNwTtlCase decNwTtlCase = new DecNwTtlCaseBuilder().setDecNwTtl(decNwTtl).build(); + Action actionDecNW = new ActionBuilder().setOrder(actionList.size()).setAction(decNwTtlCase).build(); + actionList.add(actionDecNW); + + EthernetMatchBuilder ethernetMatchBuilder = new EthernetMatchBuilder().setEthernetSource(new EthernetSourceBuilder().setAddress(outPhysicalPort.getMacAddress()).build()); + EthernetMatch ethernetMatch = ethernetMatchBuilder.build(); + + SetField setField = new SetFieldBuilder().setEthernetMatch(ethernetMatch).build(); + SetFieldCase setFieldCase = new SetFieldCaseBuilder().setSetField(setField).build(); + Action actionSetField = new ActionBuilder().setOrder(actionList.size()).setAction(setFieldCase).build(); + actionList.add(actionSetField); + } + + EthernetMatchBuilder ethernetMatchBuilder = new EthernetMatchBuilder().setEthernetDestination(new EthernetDestinationBuilder().setAddress(getMacAddressOfConnectedExternalDevice(physicalNodeId, outPhysicalPort.getPortId())).build()); + EthernetMatch ethernetMatch = ethernetMatchBuilder.build(); + + SetField setField = new SetFieldBuilder().setEthernetMatch(ethernetMatch).build(); + SetFieldCase setFieldCase = new SetFieldCaseBuilder().setSetField(setField).build(); + Action actionSetField = new ActionBuilder().setOrder(actionList.size()).setAction(setFieldCase).build(); + actionList.add(actionSetField); + + OutputAction outputAction = new OutputActionBuilder().setOutputNodeConnector(createNodeConnectorId(outPhysicalPort.getPortId())).build(); + OutputActionCase outputActionCase = new OutputActionCaseBuilder().setOutputAction(outputAction).build(); + Action actionOutput = new ActionBuilder().setOrder(actionList.size()).setAction(outputActionCase).build(); + actionList.add(actionOutput); + + ApplyActions applyActions = new ApplyActionsBuilder().setAction(actionList).build(); + ApplyActionsCase applyActionsCase = new ApplyActionsCaseBuilder().setApplyActions(applyActions).build(); + Instruction instructionApply = new InstructionBuilder().setOrder(instructionList.size()).setInstruction(applyActionsCase).build(); + instructionList.add(instructionApply); + + Instructions instructions = new InstructionsBuilder().setInstruction(instructionList).build(); + + FlowId flowId = new FlowId(UUID.randomUUID().toString()); + FlowBuilder flowBuilder = baseFlowBuilder().setId(flowId).setTableId(layer3Forwarding ? IP_TABLE_ID : MAC_TABLE_ID); + Flow flow = flowBuilder.setPriority(DEFAULT_FLOW_PRIORITY + policyPriority).setMatch(match).setInstructions(instructions).build(); + + NodeId nodeId = createNodeId(physicalNodeId); + InstanceIdentifier flowInsId = generateFlowInsId(userId, nodeId, flow.getTableId(), flow.getId()); + + writeTransaction.put(LogicalDatastoreType.CONFIGURATION, flowInsId, flow, true); + writeTransaction.submit(); + + return; + } + + /** + * TODO + * + * @author Zhigang Ji + * @param userId TODO + * @param nemoFlow TODO + * @param inPhysicalPort TODO + * @param outPhysicalPath TODO + * @param policyPriority TODO + * @param layer3Forwarding TODO + */ + private void configIpTableEntryForOperation(UserId userId, + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Flow nemoFlow, + PhysicalPort inPhysicalPort, + PhysicalPath outPhysicalPath, + short policyPriority, + boolean layer3Forwarding) { + WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction(); + PhysicalLink physicalLink = physicalNetworkHelper.getFirstPhysicalLinkOfPhysicalPath(outPhysicalPath); + List instructionList = new LinkedList(); + List actionList = new LinkedList(); + + Match match = createMatch(userId, nemoFlow, inPhysicalPort); + + if ( layer3Forwarding ) + { + DecNwTtl decNwTtl = new DecNwTtlBuilder().build(); + DecNwTtlCase decNwTtlCase = new DecNwTtlCaseBuilder().setDecNwTtl(decNwTtl).build(); + Action actionDecNW = new ActionBuilder().setOrder(actionList.size()).setAction(decNwTtlCase).build(); + actionList.add(actionDecNW); + } + + PushMplsAction pushMplsAction = new PushMplsActionBuilder().setEthernetType(ETH_TYPE_MPLS).build(); + PushMplsActionCase pushMplsActionCase = new PushMplsActionCaseBuilder().setPushMplsAction(pushMplsAction).build(); + Action actionPushMPLS = new ActionBuilder().setOrder(actionList.size()).setAction(pushMplsActionCase).build(); + actionList.add(actionPushMPLS); + + SetField setField = new SetFieldBuilder().setProtocolMatchFields(new ProtocolMatchFieldsBuilder().setMplsLabel((long)mplsLabelsOfPhysicalPaths.get(outPhysicalPath.getPathId()).get(0)).build()).build(); + SetFieldCase setFieldCase = new SetFieldCaseBuilder().setSetField(setField).build(); + Action actionSetField = new ActionBuilder().setOrder(actionList.size()).setAction(setFieldCase).build(); + actionList.add(actionSetField); + + OutputAction outputAction = new OutputActionBuilder().setOutputNodeConnector(createNodeConnectorId(physicalLink.getSrcPortId())).build(); + OutputActionCase outputActionCase = new OutputActionCaseBuilder().setOutputAction(outputAction).build(); + Action actionOutput = new ActionBuilder().setOrder(actionList.size()).setAction(outputActionCase).build(); + actionList.add(actionOutput); + + ApplyActions applyActions = new ApplyActionsBuilder().setAction(actionList).build(); + ApplyActionsCase applyActionsCase = new ApplyActionsCaseBuilder().setApplyActions(applyActions).build(); + Instruction instructionApply = new InstructionBuilder().setOrder(instructionList.size()).setInstruction(applyActionsCase).build(); + instructionList.add(instructionApply); + + Instructions instructions = new InstructionsBuilder().setInstruction(instructionList).build(); + + FlowId flowId = new FlowId(UUID.randomUUID().toString()); + FlowBuilder flowBuilder = baseFlowBuilder().setId(flowId).setTableId(layer3Forwarding ? IP_TABLE_ID : MAC_TABLE_ID); + Flow flow = flowBuilder.setPriority(DEFAULT_FLOW_PRIORITY + policyPriority).setMatch(match).setInstructions(instructions).build(); + + NodeId nodeId = createNodeId(physicalLink.getSrcNodeId()); + InstanceIdentifier flowInsId = generateFlowInsId(userId, nodeId, flow.getTableId(), flow.getId()); + + writeTransaction.put(LogicalDatastoreType.CONFIGURATION, flowInsId, flow, true); + writeTransaction.submit(); + + return; + } + + /** + * TODO + * + * @author Zhigang Ji + * @param userId TODO + * @param nemoFlow TODO + * @param physicalPort TODO + * @return TODO + */ + private Match createMatch(UserId userId, + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.intent.rev151010.user.intent.objects.Flow nemoFlow, + PhysicalPort physicalPort) { + List matchItems = nemoFlow.getMatchItem(); + MatchItem srcIpMatchItem = getMatchItem(matchItems, new MatchItemName("src-ip")); + MatchItem dstIpMatchItem = getMatchItem(matchItems, new MatchItemName("dst-ip")); + + EthernetMatchBuilder ethernetMatchBuilder = new EthernetMatchBuilder(); + Ipv4MatchBuilder ipv4MatchBuilder = new Ipv4MatchBuilder(); + MetadataBuilder metadataBuilder = null; + boolean containEthernetMatch = false; + boolean containIpv4Match = false; + + if ( null != userId ) { + metadataBuilder = new MetadataBuilder().setMetadata(BigInteger.valueOf(metadatas.get(userId))); + } + + if ( null != srcIpMatchItem || null != dstIpMatchItem ) { + ethernetMatchBuilder = ethernetMatchBuilder.setEthernetType(new EthernetTypeBuilder().setType(new EtherType((long)ETH_TYPE_IP)).build()); + containEthernetMatch = true; + } + + if ( null != srcIpMatchItem ) { + String matchItemValue = srcIpMatchItem.getMatchItemValue().getStringValue(); + ipv4MatchBuilder = ipv4MatchBuilder.setIpv4Source(new Ipv4Prefix(matchItemValue)); + containIpv4Match = true; + } + + if ( null != dstIpMatchItem ) { + String matchItemValue = dstIpMatchItem.getMatchItemValue().getStringValue(); + ipv4MatchBuilder = ipv4MatchBuilder.setIpv4Destination(new Ipv4Prefix(matchItemValue)); + containIpv4Match = true; + } + + MatchBuilder matchBuilder = new MatchBuilder(); + + if ( null != physicalPort ) { + matchBuilder = matchBuilder.setInPort(createNodeConnectorId(physicalPort.getPortId())); + } + + if ( containEthernetMatch ) { + matchBuilder = matchBuilder.setEthernetMatch(ethernetMatchBuilder.build()); + } + + if ( null != userId ) { + matchBuilder = matchBuilder.setMetadata(metadataBuilder.build()); + } + + if ( containIpv4Match ) { + matchBuilder = matchBuilder.setLayer3Match(ipv4MatchBuilder.build()); + } + + return matchBuilder.build(); + } + + /** + * TODO + * + * @author Zhigang Ji + * @return TODO + */ + private FlowBuilder baseFlowBuilder() { + return new FlowBuilder().setBarrier(false).setHardTimeout(0).setIdleTimeout(0); + } + + /** + * TODO + * + * @author Zhigang Ji + * @param physicalPortId TODO + * @return TODO + */ + private NodeConnectorId createNodeConnectorId(PhysicalPortId physicalPortId) { + return new NodeConnectorId(physicalPortId.getValue()); + } + + /** + * TODO + * + * @author Zhigang Ji + * @param nodeId TODO + * @param nodeConnectorId TODO + * @return TODO + */ + private InstanceIdentifier createNodeConnectorPath(NodeId nodeId, NodeConnectorId nodeConnectorId) { + return createNodePath(nodeId).child(NodeConnector.class, new NodeConnectorKey(nodeConnectorId)); + } + + /** + * TODO + * + * @author Zhigang Ji + * @param physicalNodeId TODO + * @param physicalPortId TODO + * @return TODO + */ + private NodeConnectorRef createNodeConnectorRef(PhysicalNodeId physicalNodeId, PhysicalPortId physicalPortId) { + return new NodeConnectorRef(createNodeConnectorPath(createNodeId(physicalNodeId), createNodeConnectorId(physicalPortId))); + } + + /** + * TODO + * + * @author Zhigang Ji + * @param physicalNodeId TODO + * @return TODO + */ + private NodeId createNodeId(PhysicalNodeId physicalNodeId) { + return new NodeId(physicalNodeId.getValue()); + } + + /** + * TODO + * + * @author Zhigang Ji + * @param nodeId TODO + * @return TODO + */ + private InstanceIdentifier createNodePath(NodeId nodeId) { + return InstanceIdentifier.builder(Nodes.class).child(Node.class, new NodeKey(nodeId)).build(); + } + + /** + * TODO + * + * @author Zhigang Ji + * @param physicalNodeId TODO + * @return TODO + */ + private NodeRef createNodeRef(PhysicalNodeId physicalNodeId) { + return new NodeRef(createNodePath(createNodeId(physicalNodeId))); + } + + /** + * TODO + * + * @author Zhigang Ji + * @param nodeId TODO + * @param tableId TODO + * @return TODO + */ + private InstanceIdentifier createTablePath(NodeId nodeId, Short tableId) { + return createNodePath(nodeId).builder().augmentation(FlowCapableNode.class).child(Table.class, new TableKey(tableId)).build(); + } + + /** + * TODO + * + * @author Zhigang Ji + * @param nodeId TODO + * @param tableId TODO + * @param flowId TODO + * @return TODO + */ + private InstanceIdentifier createFlowPath(NodeId nodeId, Short tableId, FlowId flowId) { + return createTablePath(nodeId, tableId).child(Flow.class, new FlowKey(flowId)); + } + + /** + * TODO + * + * @author Zhigang Ji + * @param ipAddress TODO + * @return TODO + */ + private IpPrefix convertIpAddressToIpPrefix(IpAddress ipAddress) { + return new IpPrefix(new Ipv4Prefix(ipAddress.getIpv4Address().getValue() + "/32")); + } + + /** + * TODO + * + * @author Zhigang Ji + */ + private class MplsLabelGenerator { + private int i = 0; + + protected int generateMplsLabel() { + return ++i; + } + } + + /** + * TODO + * + * @author Zhigang Ji + */ + private class MeterIdGenerator { + private long i = 0; + + protected long generateMeterId() { + return ++i; + } + } + + /** + * TODO + * + * @author Zhigang Ji + */ + private class PhysicalNetworkHelper { + private Map physicalNodeMap; + private Map physicalLinkMap; + private Map physicalPathMap; + private Map> physicalPortMap; + + public PhysicalNetworkHelper(PhysicalNetwork physicalNetwork) { + physicalNodeMap = new HashMap(); + physicalLinkMap = new HashMap(); + physicalPathMap = new HashMap(); + physicalPortMap = new HashMap>(); + + List physicalNodes = physicalNetwork.getPhysicalNodes().getPhysicalNode(); + Map physicalPorts; + + for ( PhysicalNode physicalNode : physicalNodes ) { + physicalNodeMap.put(physicalNode.getNodeId(), physicalNode); + + physicalPorts = new HashMap(); + physicalPortMap.put(physicalNode.getNodeId(), physicalPorts); + + for ( PhysicalPort physicalPort : physicalNode.getPhysicalPort() ) { + physicalPorts.put(physicalPort.getPortId(), physicalPort); + } + } + + List physicalLinks = physicalNetwork.getPhysicalLinks().getPhysicalLink(); + + for ( PhysicalLink physicalLink : physicalLinks ) { + physicalLinkMap.put(physicalLink.getLinkId(), physicalLink); + } + + if ( null != physicalNetwork.getPhysicalPaths() ) { + List physicalPaths = physicalNetwork.getPhysicalPaths().getPhysicalPath(); + + if ( null != physicalPaths ) { + for ( PhysicalPath physicalPath : physicalPaths ) { +// physicalPathMap.put(physicalPath.getPathId(), physicalPath); + physicalPathMap.put(physicalPath.getPathId(), + sortPhysicalLinksOfPhysicalPath(physicalPath)); + } + } + } + + return; + } + + protected PhysicalLink getPhysicalLink(PhysicalLinkId physicalLinkId) { + return physicalLinkMap.get(physicalLinkId); + } + + protected PhysicalPath getPhysicalPath(PhysicalPathId physicalPathId) { + return physicalPathMap.get(physicalPathId); + } + + protected PhysicalPort getPhysicalPort(PhysicalNodeId physicalNodeId, PhysicalPortId physicalPortId) { + return physicalPortMap.get(physicalNodeId).get(physicalPortId); + } + + protected PhysicalLink getFirstPhysicalLinkOfPhysicalPath(PhysicalPath physicalPath) { +// for ( org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.path.instance.PhysicalLink +// physicalLink : physicalPath.getPhysicalLink() ) { +// if ( 0 == physicalLink.getOrder() ) { +// return physicalLinkMap.get(physicalLink.getLinkId()); +// } +// } +// +// return null; + + if ( physicalPath.getPhysicalLink().isEmpty() ) { + return null; + } + + PhysicalLinkId physicalLinkId = physicalPath.getPhysicalLink().get(0).getLinkId(); + + return physicalLinkMap.get(physicalLinkId); + } + + protected PhysicalLink getLastPhysicalLinkOfPhysicalPath(PhysicalPath physicalPath) { +// long order = physicalPath.getPhysicalLink().size() - 1; +// +// for ( org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.path.instance.PhysicalLink +// physicalLink : physicalPath.getPhysicalLink() ) { +// if ( physicalLink.getOrder() == order ) { +// return physicalLinkMap.get(physicalLink.getLinkId()); +// } +// } +// +// return null; + + if ( physicalPath.getPhysicalLink().isEmpty() ) { + return null; + } + + PhysicalLinkId physicalLinkId = physicalPath.getPhysicalLink() + .get(physicalPath.getPhysicalLink().size() - 1).getLinkId(); + + return physicalLinkMap.get(physicalLinkId); + } + + private PhysicalPath sortPhysicalLinksOfPhysicalPath(PhysicalPath physicalPath) { + if ( physicalPath.getPhysicalLink().isEmpty() + || 1 == physicalPath.getPhysicalLink().size() ) { + return physicalPath; + } + + List sortedPhysicalLinks = + new ArrayList(physicalPath.getPhysicalLink().size()); + sortedPhysicalLinks.addAll(physicalPath.getPhysicalLink()); + + for ( org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.path.instance.PhysicalLink + physicalLink : physicalPath.getPhysicalLink() ) { + sortedPhysicalLinks.set(physicalLink.getOrder().intValue(), physicalLink); + } + + PhysicalPath physicalPath1 = new PhysicalPathBuilder(physicalPath) + .setPhysicalLink(sortedPhysicalLinks) + .build(); + + return physicalPath1; + } + } + + /** + * TODO + * + * @author Zhigang Ji + */ + private class VirtualNetworkHelper { + private Map virtualNodeMap; + private Map virtualLinkMap; + private Map virtualPathMap; + private Map virtualRouterMap; + private Map> virtualPortMap; + private Map layer2ExternalVirtualPortMap; + private Map layer3ExternalVirtualPortMap; + private Map>> virtualSwitchConnectedInternalVirtualPortMap; + private Map>> virtualRouterConnectedInternalVirtualPortMap; + private Map virtualArpMap; + private Map macAddressKeyVirtualArpMap; + + public VirtualNetworkHelper(VirtualNetwork virtualNetwork) { + virtualNodeMap = new HashMap(); + virtualLinkMap = new HashMap(); + virtualPathMap = new HashMap(); + virtualRouterMap = new HashMap(); + virtualPortMap = new HashMap>(); + layer2ExternalVirtualPortMap = new HashMap(); + layer3ExternalVirtualPortMap = new HashMap(); + virtualSwitchConnectedInternalVirtualPortMap = + new HashMap>>(); + virtualRouterConnectedInternalVirtualPortMap = + new HashMap>>(); + virtualArpMap = new HashMap(); + macAddressKeyVirtualArpMap = new HashMap(); + + List virtualNodes = virtualNetwork.getVirtualNodes().getVirtualNode(); + Map virtualPorts; + + for ( VirtualNode virtualNode : virtualNodes ) { + virtualNodeMap.put(virtualNode.getNodeId(), virtualNode); + + if ( VirtualNode.NodeType.Vrouter == virtualNode.getNodeType() ) { + virtualRouterMap.put(virtualNode.getNodeId(), virtualNode); + } + + virtualPorts = new HashMap(); + virtualPortMap.put(virtualNode.getNodeId(), virtualPorts); + + for ( VirtualPort virtualPort : virtualNode.getVirtualPort() ) { + virtualPorts.put(virtualPort.getPortId(), virtualPort); + + if ( VirtualPort.PortType.External == virtualPort.getPortType() ) { + if ( null == virtualPort.getExternalMacAddresses() ) { + layer3ExternalVirtualPortMap.put(virtualNode.getNodeId(), virtualPort); + } else { + layer2ExternalVirtualPortMap.put(virtualNode.getNodeId(), virtualPort); + } + } + } + } + + List virtualLinks = virtualNetwork.getVirtualLinks().getVirtualLink(); + Map> virtualSwitchConnectedInternalVirtualPorts; + Map> virtualRouterConnectedInternalVirtualPorts; + VirtualNode virtualNode; + VirtualPort virtualPort; + + for ( VirtualLink virtualLink : virtualLinks ) { + virtualLinkMap.put(virtualLink.getLinkId(), virtualLink); + + virtualNode = virtualNodeMap.get(virtualLink.getDestNodeId()); + virtualPort = virtualPortMap.get(virtualLink.getSrcNodeId()).get(virtualLink.getSrcPortId()); + + if ( VirtualNode.NodeType.Vswitch == virtualNode.getNodeType() ) { + virtualSwitchConnectedInternalVirtualPorts = + virtualSwitchConnectedInternalVirtualPortMap.get(virtualLink.getSrcNodeId()); + + if ( null == virtualSwitchConnectedInternalVirtualPorts ) { + virtualSwitchConnectedInternalVirtualPorts = + new HashMap>(); + virtualSwitchConnectedInternalVirtualPortMap.put( + virtualLink.getSrcNodeId(), virtualSwitchConnectedInternalVirtualPorts); + } + + virtualSwitchConnectedInternalVirtualPorts.put(virtualLink.getDestNodeId(), + new AbstractMap.SimpleEntry(virtualPort, virtualLink)); + } else if ( VirtualNode.NodeType.Vrouter == virtualNode.getNodeType() ) { + virtualRouterConnectedInternalVirtualPorts = + virtualRouterConnectedInternalVirtualPortMap.get(virtualLink.getSrcNodeId()); + + if ( null == virtualRouterConnectedInternalVirtualPorts ) { + virtualRouterConnectedInternalVirtualPorts = + new HashMap>(); + virtualRouterConnectedInternalVirtualPortMap.put( + virtualLink.getSrcNodeId(), virtualRouterConnectedInternalVirtualPorts); + } + + virtualRouterConnectedInternalVirtualPorts.put(virtualLink.getDestNodeId(), + new AbstractMap.SimpleEntry(virtualPort, virtualLink)); + } + } + + List virtualPaths = virtualNetwork.getVirtualPaths().getVirtualPath(); + + for ( VirtualPath virtualPath : virtualPaths ) { + virtualPathMap.put(virtualPath.getPathId(), virtualPath); + } + + List virtualArps = virtualNetwork.getVirtualArps().getVirtualArp(); + + for ( VirtualArp virtualArp : virtualArps ) { + virtualArpMap.put(virtualArp.getKey(), virtualArp); + macAddressKeyVirtualArpMap.put(virtualArp.getMacAddress(), virtualArp); + } + + return; + } + + protected VirtualLink getVirtualLink(VirtualLinkId virtualLinkId) { + return virtualLinkMap.get(virtualLinkId); + } + + protected VirtualPath getVirtualPath(VirtualPathId virtualPathId) { + return virtualPathMap.get(virtualPathId); + } + + protected Map getVirtualRouters() { + return virtualRouterMap; + } + + protected VirtualPort getLayer2ExternalVirtualPort(VirtualNodeId virtualNodeId) { + return layer2ExternalVirtualPortMap.get(virtualNodeId); + } + + protected VirtualPort getLayer3ExternalVirtualPort(VirtualNodeId virtualNodeId) { + return layer3ExternalVirtualPortMap.get(virtualNodeId); + } + + protected Map> getConnectedVirtualSwitches( + VirtualNodeId virtualNodeId) { + return virtualSwitchConnectedInternalVirtualPortMap.get(virtualNodeId); + } + + protected Map> getConnectedVirtualRouters( + VirtualNodeId virtualNodeId) { + return virtualRouterConnectedInternalVirtualPortMap.get(virtualNodeId); + } + + protected VirtualArp getVirtualArp(MacAddress macAddress) { + return macAddressKeyVirtualArpMap.get(macAddress); + } + } +} diff --git a/nemo-renderers/openflow-renderer/src/main/java/org/opendaylight/nemo/renderer/openflow/OpenflowRenderer.java b/nemo-renderers/openflow-renderer/src/main/java/org/opendaylight/nemo/renderer/openflow/OpenflowRenderer.java new file mode 100644 index 0000000..3181776 --- /dev/null +++ b/nemo-renderers/openflow-renderer/src/main/java/org/opendaylight/nemo/renderer/openflow/OpenflowRenderer.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.nemo.renderer.openflow; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; + +public class OpenflowRenderer implements AutoCloseable { + + private static final Logger LOG = LoggerFactory.getLogger(OpenflowRenderer.class); + + private DataBroker dataBroker; + private final ResourceManager resourceManager; + private final FlowTableManager flowTableMng; + + public OpenflowRenderer(DataBroker dataBroker) { + super(); + this.dataBroker = dataBroker; + System.out.println(); + System.out.println("Waiting for loading config file about 30s..."); + + LOG.info("New ResourceManager."); + resourceManager = new ResourceManager(dataBroker); + + LOG.info("New FlowTableManager."); + flowTableMng = new FlowTableManager(dataBroker, resourceManager); + + LOG.info("Initialized openflow renderer."); + } + + // ************* + // AutoCloseable + // ************* + + @Override + public void close() throws Exception { + if (flowTableMng != null) flowTableMng.close(); + if (resourceManager != null) resourceManager.close(); + } +} + diff --git a/nemo-renderers/openflow-renderer/src/main/java/org/opendaylight/nemo/renderer/openflow/ResourceManager.java b/nemo-renderers/openflow-renderer/src/main/java/org/opendaylight/nemo/renderer/openflow/ResourceManager.java new file mode 100644 index 0000000..5101748 --- /dev/null +++ b/nemo-renderers/openflow-renderer/src/main/java/org/opendaylight/nemo/renderer/openflow/ResourceManager.java @@ -0,0 +1 @@ +/* * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.nemo.renderer.openflow; import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.collect.HashBasedTable; import com.google.common.collect.Table; import java.util.*; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import com.google.common.util.concurrent.CheckedFuture; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.lang.*; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.PhysicalNetworkBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.PhysicalNetwork; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.PhysicalNodeInstance; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.PhysicalPortInstance; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.attribute.instance.AttributeValue; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.attribute.instance.AttributeValueBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.nodes.PhysicalNode; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.nodes.PhysicalNodeBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.nodes.PhysicalNodeKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.links.PhysicalLink; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.links.PhysicalLinkBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.links.PhysicalLinkKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.node.instance.PhysicalPort; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.node.instance.PhysicalPortBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.node.instance.PhysicalPortKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.port.instance.Attribute; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.port.instance.AttributeBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.port.instance.AttributeKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.common.rev151010.AttributeName; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.common.rev151010.PhysicalNodeId; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.common.rev151010.PhysicalPortId; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.common.rev151010.PhysicalLinkId; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.common.rev151010.PhysicalHostId; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.common.rev151010.PhysicalHostName; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.hosts.PhysicalHostBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.hosts.PhysicalHostKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.hosts.PhysicalHost; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.host.instance.IpAddresses; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.host.instance.IpAddressesBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.PhysicalNodes; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.PhysicalLinks; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.PhysicalHosts; import org.opendaylight.nemo.renderer.openflow.entity.ResourceBean; public class ResourceManager implements AutoCloseable { private static final Logger LOG = LoggerFactory.getLogger(ResourceManager.class); public final static String PROPERTY_FILE_PATH = "etc/nemo/nemo-openflow-renderer-resource.json"; final private DataBroker dataProvider; private ObjectMapper objectMapper = null; private Table externalNetworkMacTable; public ResourceManager(DataBroker dataProvider){ this.dataProvider = dataProvider; this.objectMapper = new ObjectMapper(); this.externalNetworkMacTable = HashBasedTable.create(); String resourceInfo = ReadFile(PROPERTY_FILE_PATH); buildPhysicalNetworkFromConfig(resourceInfo); LOG.info("nemo:Initialized resource manager for Openflow renderer."); } public Table getExternalNetworkMacTable(){ return this.externalNetworkMacTable; } private void buildPhysicalNetworkFromConfig(String resource) { try { PhysicalNetworkBuilder phyNetwrokBuilder= new PhysicalNetworkBuilder(); PhysicalNodeBuilder phyNodeBuilder = new PhysicalNodeBuilder(); JsonNode rootNode = objectMapper.readTree(resource); JsonNode pn = rootNode.path("physicalnetwork"); JsonNode nodes = pn.path("node"); JsonNode links = pn.path("link"); JsonNode hosts = pn.path("host"); LOG.debug("Import physical nodes into DataStore."); for(int i = 0; i< nodes.size(); i++){ LOG.debug("build physical node execution body"); //JsonNode node = nodeIt.next(); JsonNode node = nodes.get(i); JsonNode ports = node.path("port"); PhysicalNodeBuilder nodeBuilder = new PhysicalNodeBuilder(); nodeBuilder.setNodeId(new PhysicalNodeId(node.get("node-id").asText())); PhysicalNodeKey key = new PhysicalNodeKey(nodeBuilder.getNodeId()); nodeBuilder.setKey(key); String nodetype = node.get("node-type").asText(); if((!(nodetype.equals("switch"))) && (!(nodetype.equals("router")))){ continue; } if(nodetype.equals("switch")) { nodeBuilder.setNodeType(PhysicalNodeInstance.NodeType.Switch); }else if(nodetype.equals("router")){ nodeBuilder.setNodeType(PhysicalNodeInstance.NodeType.Router); } List phyPortList = new ArrayList(); //for (Iterator portIt = ports.elements(); portIt.hasNext(); ) { for(int j =0; j < ports.size(); j++){ LOG.debug("build physical port execution body"); //JsonNode port = portIt.next(); JsonNode port = ports.get(j); PhysicalPortBuilder phyPortbuilder = new PhysicalPortBuilder(); phyPortbuilder.setPortId(new PhysicalPortId(port.get("port-id").asText())); if((port.get("port-type").asText()).equals("external")) { phyPortbuilder.setPortType(PhysicalPortInstance.PortType.External); } else { phyPortbuilder.setPortType(PhysicalPortInstance.PortType.Internal); } //add mac-address for each port LOG.info("nemo:j=" + j); MacAddress mac = new MacAddress(port.get("port-mac-address").asText()); phyPortbuilder.setMacAddress(mac); phyPortbuilder.setBandwidth((long) (port.get("bandwidth").asInt())); JsonNode attrs = port.path("attribute"); List AttrList = new ArrayList(); for(int r = 0; r < attrs.size(); r++){ LOG.debug("build physical port attribute execution body."); JsonNode portattr = attrs.get(r); AttributeBuilder attrbuilder = new AttributeBuilder(); attrbuilder.setAttributeName(new AttributeName(portattr.path("name").asText())); AttributeValueBuilder avbd = new AttributeValueBuilder(); avbd.setStringValue(portattr.path("value").asText()); attrbuilder.setKey(new AttributeKey(attrbuilder.getAttributeName())); attrbuilder.setAttributeValue(avbd.build()); Attribute attr_instance = attrbuilder.build(); AttrList.add(attr_instance); } /* Iterator keys = attrs.fieldNames(); while(keys.hasNext()) { LOG.info("build physical port attribute execution body."); String fieldName = keys.next(); attrbuilder.setAttributeName(new AttributeName(fieldName)); AttributeValueBuilder avbd = new AttributeValueBuilder(); avbd.setStringValue(attrs.path(fieldName).asText()); attrbuilder.setKey(new AttributeKey(attrbuilder.getAttributeName())); attrbuilder.setAttributeValue(avbd.build()); Attribute attr_instance = attrbuilder.build(); AttrList.add(attr_instance); } */ phyPortbuilder.setAttribute(AttrList); phyPortList.add(phyPortbuilder.build()); } nodeBuilder.setPhysicalPort(phyPortList); /*node attribute list*/ JsonNode node_attrs = node.path("attribute"); List node_AttrList = new ArrayList(); for(int t = 0; t < node_attrs.size(); t++){ LOG.debug("build physical node attribute execution body."); JsonNode node_attr = node_attrs.get(t); org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.node.instance.AttributeBuilder attrbuilder = new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.node.instance.AttributeBuilder(); attrbuilder.setAttributeName(new AttributeName(node_attr.path("name").asText())); AttributeValueBuilder avbd = new AttributeValueBuilder(); avbd.setStringValue(node_attr.path("value").asText()); attrbuilder.setKey(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.node.instance.AttributeKey(attrbuilder.getAttributeName())); attrbuilder.setAttributeValue(avbd.build()); org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.node.instance.Attribute node_attr_instance = attrbuilder.build(); node_AttrList.add(node_attr_instance); } nodeBuilder.setAttribute((List) node_AttrList); PhysicalNode phyNode = nodeBuilder.build(); //phyNodeList.add(phyNode); LOG.debug("Ready to write node to data store."); try { WriteTransaction t = dataProvider.newWriteOnlyTransaction(); InstanceIdentifier phynode_iid = InstanceIdentifier .builder(PhysicalNetwork.class) .child(PhysicalNodes.class) .child(PhysicalNode.class, key) .build(); t.put(LogicalDatastoreType.OPERATIONAL, phynode_iid, phyNode, true); CheckedFuture f = t.submit(); Futures.addCallback(f, new FutureCallback() { @Override public void onFailure(Throwable t) { System.out.println("write transaction onFailure."); LOG.error("Could not write PhysicalNode", t); } @Override public void onSuccess(Void result) { //System.out.println("write transaction onSuccess."); LOG.debug("write transaction onSuccess."); } }); } catch (Exception e) { e.printStackTrace(); } } LOG.debug("Import physical links into DataStore."); for(int m = 0; m< links.size(); m++){ LOG.debug("build physical link execution body"); JsonNode link = links.get(m); String strLeftNodeId = link.get("left-node-id").asText(); String strRightNodeId = link.get("right-node-id").asText(); if(strLeftNodeId.contains("external")||strRightNodeId.contains("external")){ String strExternalNodeId = ""; PhysicalNodeId accessNodeId = null; PhysicalPortId accessPortId = null; if(strLeftNodeId.contains("external")){ strExternalNodeId = strLeftNodeId; accessNodeId = new PhysicalNodeId(link.get("right-node-id").asText()); accessPortId = new PhysicalPortId(link.get("right-port-id").asText()); }else{ strExternalNodeId = strRightNodeId; accessNodeId = new PhysicalNodeId(link.get("left-node-id").asText()); accessPortId = new PhysicalPortId(link.get("left-port-id").asText()); } for(int b = 0; b < nodes.size(); b++){ JsonNode pnode = nodes.get(b); if(strExternalNodeId.equals(pnode.get("node-id").asText())){ MacAddress macAddress = new MacAddress(pnode.get("mac-address").asText()); this.externalNetworkMacTable.put(accessNodeId, accessPortId, macAddress); break; } } continue; } PhysicalLinkBuilder linkBuilder = new PhysicalLinkBuilder(); PhysicalLinkId phylinkid = new PhysicalLinkId(link.get("link-id").asText()); linkBuilder.setLinkId(phylinkid); linkBuilder.setSrcNodeId(new PhysicalNodeId(link.get("left-node-id").asText())); linkBuilder.setSrcPortId(new PhysicalPortId(link.get("left-port-id").asText())); linkBuilder.setDestNodeId(new PhysicalNodeId(link.get("right-node-id").asText())); linkBuilder.setDestPortId(new PhysicalPortId(link.get("right-port-id").asText())); linkBuilder.setBandwidth((long) (link.get("link-bandwidth").asLong())); linkBuilder.setDelay((long) (link.get("delay").asLong())); linkBuilder.setMetric((long) (link.get("metric").asLong())); linkBuilder.setLossRate((short) (link.get("delay").asInt())); PhysicalLink phyLink = linkBuilder.build(); LOG.debug("Ready to write link to data store."); try { WriteTransaction t = dataProvider.newWriteOnlyTransaction(); InstanceIdentifier phylink_iid = InstanceIdentifier .builder(PhysicalNetwork.class) .child(PhysicalLinks.class) .child(PhysicalLink.class, new PhysicalLinkKey(linkBuilder.getLinkId())) .build(); t.put(LogicalDatastoreType.OPERATIONAL, phylink_iid, phyLink, true); CheckedFuture f = t.submit(); Futures.addCallback(f, new FutureCallback() { @Override public void onFailure(Throwable t) { System.out.println("write transaction onFailure."); LOG.error("Could not write PhysicalLink", t); } @Override public void onSuccess(Void result) { //System.out.println("write transaction onSuccess."); LOG.debug("write transaction onSuccess."); } }); } catch (Exception e) { e.printStackTrace(); } } LOG.debug("Import hosts into DataStore."); for(int n = 0; n< hosts.size(); n++){ LOG.debug("build host execution body"); JsonNode host = hosts.get(n); PhysicalHostBuilder hostBuilder = new PhysicalHostBuilder(); hostBuilder.setHostId(new PhysicalHostId(host.get("id").asText())); hostBuilder.setKey(new PhysicalHostKey(hostBuilder.getHostId())); hostBuilder.setHostName(new PhysicalHostName(host.get("name").asText())); IpAddressesBuilder IpAddrBuilder = new IpAddressesBuilder(); List ipList = new ArrayList(); JsonNode ipaddrs = host.path("ip-addresses"); for(int p = 0 ; p < ipaddrs.size(); p++){ JsonNode ipaddr = ipaddrs.get(p); IpAddress ip = new IpAddress(new Ipv4Address(ipaddr.get("ip-address").asText())); ipList.add(ip); } IpAddrBuilder.setIpAddress(ipList); hostBuilder.setIpAddresses(IpAddrBuilder.build()); MacAddress mac = new MacAddress(host.get("mac-address").asText()); hostBuilder.setMacAddress(mac); hostBuilder.setNodeId(new PhysicalNodeId(host.get("node-id").asText())); hostBuilder.setPortId(new PhysicalPortId(host.get("connector-id").asText())); PhysicalHost phyHost = hostBuilder.build(); LOG.debug("Ready to write host to data store."); try { WriteTransaction t = dataProvider.newWriteOnlyTransaction(); InstanceIdentifier phyhost_iid = InstanceIdentifier .builder(PhysicalNetwork.class) .child(PhysicalHosts.class) .child(PhysicalHost.class, new PhysicalHostKey(hostBuilder.getHostId())) .build(); t.put(LogicalDatastoreType.OPERATIONAL, phyhost_iid, phyHost, true); CheckedFuture f = t.submit(); Futures.addCallback(f, new FutureCallback() { @Override public void onFailure(Throwable t) { System.out.println("write transaction onFailure."); LOG.error("Could not write PhysicalHost", t); } @Override public void onSuccess(Void result) { //System.out.println("write transaction onSuccess."); LOG.debug("write transaction onSuccess."); } }); } catch (Exception e) { e.printStackTrace(); } } } catch (JsonProcessingException e) { e.printStackTrace(); } catch(IOException e){ e.printStackTrace(); } LOG.debug("buildPhysicalNetworkFromConfig end."); System.out.print("Loading physical network configuration has been completed."); } private String ReadFile(String Path){ BufferedReader reader = null; String laststr = ""; try{ FileInputStream fileInputStream = new FileInputStream(Path); InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "UTF-8"); reader = new BufferedReader(inputStreamReader); String tempString = null; while((tempString = reader.readLine()) != null){ laststr += tempString; } reader.close(); }catch(IOException e){ e.printStackTrace(); }finally{ if(reader != null){ try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } } return laststr; } @Override public void close() throws Exception { } } \ No newline at end of file diff --git a/nemo-renderers/openflow-renderer/src/main/java/org/opendaylight/nemo/renderer/openflow/entity/HostBean.java b/nemo-renderers/openflow-renderer/src/main/java/org/opendaylight/nemo/renderer/openflow/entity/HostBean.java new file mode 100644 index 0000000..66056fb --- /dev/null +++ b/nemo-renderers/openflow-renderer/src/main/java/org/opendaylight/nemo/renderer/openflow/entity/HostBean.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.nemo.renderer.openflow.entity; + +import java.util.List; + +public class HostBean { + + public String getHostName() { + return hostName; + } + + public void setHostName(String hostName) { + this.hostName = hostName; + } + + private String hostName; + + public List getIPAddressList() { + return this.IPAddressList; + } + + public void setStringList(List IPAddressList) { + this.IPAddressList = IPAddressList; + } + + private List IPAddressList; + + public String getMacAddress() { + return macAddress; + } + + public void setMacAddress(String macAddress) { + this.macAddress = macAddress; + } + + private String macAddress; + + public String getNodeID() { + return nodeID; + } + + public void setNodeID(String nodeID) { + this.nodeID = nodeID; + } + + private String nodeID; + + public String getConnectorID() { + return connectorID; + } + + public void setConnectorID(String connectorID) { + this.connectorID = connectorID; + } + + private String connectorID; + +} diff --git a/nemo-renderers/openflow-renderer/src/main/java/org/opendaylight/nemo/renderer/openflow/entity/LinkBean.java b/nemo-renderers/openflow-renderer/src/main/java/org/opendaylight/nemo/renderer/openflow/entity/LinkBean.java new file mode 100644 index 0000000..20196a9 --- /dev/null +++ b/nemo-renderers/openflow-renderer/src/main/java/org/opendaylight/nemo/renderer/openflow/entity/LinkBean.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.nemo.renderer.openflow.entity; + +public class LinkBean { + + private String linkID; + private String leftNodeID; + private String leftPortID; + private String rightPortID; + private String linkBandwidth; + + public String getLinkID() { + return linkID; + } + + public void setLinkID(String linkID) { + this.linkID = linkID; + } + + public String getLeftNodeID() { + return leftNodeID; + } + + public void setLeftNodeID(String leftNodeID) { + this.leftNodeID = leftNodeID; + } + + public String getLeftPortID() { + return leftPortID; + } + + public void setLeftPortID(String leftPortID) { + this.leftPortID = leftPortID; + } + + public String getRightNodeID() { + return rightNodeID; + } + + public void setRightNodeID(String rightNodeID) { + this.rightNodeID = rightNodeID; + } + + private String rightNodeID; + + public String getRightPortID() { + return rightPortID; + } + + public void setRightPortID(String rightPortID) { + this.rightPortID = rightPortID; + } + + public String getLinkBandwidth() { + return linkBandwidth; + } + + public void setLinkBandwidth(String linkBandwidth) { + this.linkBandwidth = linkBandwidth; + } + +} \ No newline at end of file diff --git a/nemo-renderers/openflow-renderer/src/main/java/org/opendaylight/nemo/renderer/openflow/entity/NodeBean.java b/nemo-renderers/openflow-renderer/src/main/java/org/opendaylight/nemo/renderer/openflow/entity/NodeBean.java new file mode 100644 index 0000000..c503726 --- /dev/null +++ b/nemo-renderers/openflow-renderer/src/main/java/org/opendaylight/nemo/renderer/openflow/entity/NodeBean.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.nemo.renderer.openflow.entity; + +import org.opendaylight.nemo.renderer.openflow.entity.PortBean; +import java.util.List; + +public class NodeBean { + + private String nodeID; + private String nodeType; + private String nodeCapacity; + private List portList; + + public String getNodeID() { + return nodeID; + } + + public void setNodeID(String nodeID) { + this.nodeID = nodeID; + } + + public String getNodeType() { + return nodeType; + } + + public void setNodeType(String nodeType) { + this.nodeType = nodeType; + } + + public String getNodeCapacity() { + return nodeCapacity; + } + + public void setNodeCapacity(String nodeCapacity) { + this.nodeCapacity = nodeCapacity; + } + + public List getPortList() { + return portList; + } + + public void setPortList(List portList) { + this.portList = portList; + } + +} + diff --git a/nemo-renderers/openflow-renderer/src/main/java/org/opendaylight/nemo/renderer/openflow/entity/PortBean.java b/nemo-renderers/openflow-renderer/src/main/java/org/opendaylight/nemo/renderer/openflow/entity/PortBean.java new file mode 100644 index 0000000..f369677 --- /dev/null +++ b/nemo-renderers/openflow-renderer/src/main/java/org/opendaylight/nemo/renderer/openflow/entity/PortBean.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.nemo.renderer.openflow.entity; + +public class PortBean { + + private String portID; + private String portIPAddress; + private String mask; + private String location; + private String bandwidth; + + public String getPortID() { + return portID; + } + + public void setPortID(String portID) { + this.portID = portID; + } + + public String getPortIPAddress() { + return portIPAddress; + } + + public void setPortIPAddress(String portIPAddress) { + this.portIPAddress = portIPAddress; + } + + public String getMask() { + return mask; + } + + public void setMask(String mask) { + this.mask = mask; + } + + public String getLocation() { + return location; + } + + public void setLocation(String location) { + this.location = location; + } + + public String getBandwidth() { + return bandwidth; + } + + public void setBandwidth(String bandwidth) { + this.bandwidth = bandwidth; + } +} diff --git a/nemo-renderers/openflow-renderer/src/main/java/org/opendaylight/nemo/renderer/openflow/entity/ResourceBean.java b/nemo-renderers/openflow-renderer/src/main/java/org/opendaylight/nemo/renderer/openflow/entity/ResourceBean.java new file mode 100644 index 0000000..d3085d9 --- /dev/null +++ b/nemo-renderers/openflow-renderer/src/main/java/org/opendaylight/nemo/renderer/openflow/entity/ResourceBean.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.nemo.renderer.openflow.entity; +import org.opendaylight.nemo.renderer.openflow.entity.NodeBean; +import org.opendaylight.nemo.renderer.openflow.entity.LinkBean; +import org.opendaylight.nemo.renderer.openflow.entity.HostBean; + +import java.util.List; + +public class ResourceBean { + public List getNodelist() { + return nodelist; + } + + public void setNodelist(List nodelist) { + this.nodelist = nodelist; + } + + private List nodelist; + + public List getLinklist() { + return linklist; + } + + public void setLinklist(List linklist) { + this.linklist = linklist; + } + + private List linklist; + + public List getHostlist() { + return hostlist; + } + + public void setHostlist(List hostlist) { + this.hostlist = hostlist; + } + + private List hostlist; + + //getter ,setter +} + diff --git a/nemo-renderers/openflow-renderer/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/nemo/openflow/renderer/impl/rev151010/OpenflowRendererModule.java b/nemo-renderers/openflow-renderer/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/nemo/openflow/renderer/impl/rev151010/OpenflowRendererModule.java new file mode 100644 index 0000000..13a67ac --- /dev/null +++ b/nemo-renderers/openflow-renderer/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/nemo/openflow/renderer/impl/rev151010/OpenflowRendererModule.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.openflow.renderer.impl.rev151010; + +import org.opendaylight.nemo.renderer.openflow.OpenflowRenderer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class OpenflowRendererModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.openflow.renderer.impl.rev151010.AbstractOpenflowRendererModule { + + private static final Logger LOG = LoggerFactory.getLogger(OpenflowRenderer.class); + + public OpenflowRendererModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { + super(identifier, dependencyResolver); + } + + public OpenflowRendererModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.openflow.renderer.impl.rev151010.OpenflowRendererModule oldModule, java.lang.AutoCloseable oldInstance) { + super(identifier, dependencyResolver, oldModule, oldInstance); + } + + @Override + public void customValidation() { + // add custom validation form module attributes here. + } + + @Override + public java.lang.AutoCloseable createInstance() { + LOG.info("Openflow Renderer createInstance()"); + final OpenflowRenderer renderer = new OpenflowRenderer(getDataBrokerDependency()); + + final class CloseResources implements AutoCloseable { + @Override + public void close() throws Exception { + if (renderer != null) { + renderer.close(); + } + LOG.info("Openflow Renderer (instance {}) tear down.", this); + } + } + return new CloseResources(); + } + +} diff --git a/nemo-renderers/openflow-renderer/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/nemo/openflow/renderer/impl/rev151010/OpenflowRendererModuleFactory.java b/nemo-renderers/openflow-renderer/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/nemo/openflow/renderer/impl/rev151010/OpenflowRendererModuleFactory.java new file mode 100644 index 0000000..7cc45a8 --- /dev/null +++ b/nemo-renderers/openflow-renderer/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/nemo/openflow/renderer/impl/rev151010/OpenflowRendererModuleFactory.java @@ -0,0 +1,13 @@ +/* +* Generated file +* +* Generated from: yang module name: openflow-renderer-impl yang module local name: openflow-renderer-impl +* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator +* Generated at: Tue Sep 22 12:00:29 CST 2015 +* +* Do not modify this file unless it is present under src/main directory +*/ +package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.openflow.renderer.impl.rev151010; +public class OpenflowRendererModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.openflow.renderer.impl.rev151010.AbstractOpenflowRendererModuleFactory { + +} diff --git a/nemo-renderers/openflow-renderer/src/main/resources/etc/nemo/resource-bod.json b/nemo-renderers/openflow-renderer/src/main/resources/etc/nemo/resource-bod.json new file mode 100644 index 0000000..8af843a --- /dev/null +++ b/nemo-renderers/openflow-renderer/src/main/resources/etc/nemo/resource-bod.json @@ -0,0 +1,435 @@ +{ + "physicalnetwork":{ + "node": [ + { + "node-id": "openflow:1", + "node-type": "switch", + "attribute":[ + { + "name":"location", + "value":"openflow:1" + }, + { + "name":"capacity", + "value":"" + } + ], + "port": [ + { + "port-id": "openflow:1:1", + "port-type":"external", + "port-ip-address": "", + "port-mac-address":"00:00:00:00:01:01", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"openflow:1:1" + } + ] + }, + { + "port-id": "openflow:1:2", + "port-type":"external", + "port-ip-address": "", + "port-mac-address":"00:00:00:00:01:02", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"openflow:1:2" + } + ] + }, + { + "port-id": "openflow:1:3", + "port-type":"internal", + "port-ip-address":"", + "port-mac-address":"00:00:00:00:01:03", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"openflow:1:3" + } + ] + } + ] + }, + { + "node-id": "openflow:2", + "node-type": "switch", + "attribute":[ + { + "name":"location", + "value":"openflow:2" + }, + { + "name":"capacity", + "value":"" + } + ], + "port": [ + { + "port-id": "openflow:2:1", + "port-type":"external", + "port-ip-address": "", + "port-mac-address":"00:00:00:00:02:01", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"openflow:2:1" + } + ] + }, + { + "port-id": "openflow:2:2", + "port-type":"external", + "port-ip-address": "", + "port-mac-address":"08:00:27:bb:8b:cf", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"openflow:2:2" + } + ] + }, + { + "port-id": "openflow:2:3", + "port-type":"internal", + "port-ip-address": "", + "port-mac-address":"00:00:00:00:02:03", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"openflow:2:3" + } + ] + } + ] + }, + { + "node-id": "openflow:3", + "node-type": "router", + "attribute":[ + { + "name":"location", + "value":"openflow:3" + }, + { + "name":"capacity", + "value":"" + } + ], + "port": [ + { + "port-id": "openflow:3:1", + "port-type":"internal", + "port-ip-address": "", + "port-mac-address":"00:00:00:00:03:01", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"openflow:3:1" + } + ] + }, + { + "port-id": "openflow:3:2", + "port-type":"internal", + "port-ip-address": "", + "port-mac-address":"00:00:00:00:03:02", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"openflow:3:2" + } + ] + }, + { + "port-id": "openflow:3:3", + "port-type":"internal", + "port-ip-address": "", + "port-mac-address":"00:00:00:00:03:03", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"openflow:3:3" + } + ] + }, + { + "port-id": "openflow:3:4", + "port-type":"external", + "port-ip-address": "", + "port-mac-address":"08:00:27:fb:d1:76", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"openflow:3:4" + } + ] + } + ] + }, + { + "node-id": "openflow:4", + "node-type": "router", + "attribute":[ + { + "name":"location", + "value":"openflow:4" + }, + { + "name":"capacity", + "value":"" + } + ], + "port": [ + { + "port-id": "openflow:4:1", + "port-type":"internal", + "port-ip-address": "", + "port-mac-address":"00:00:00:00:04:01", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"openflow:4:1" + } + ] + }, + { + "port-id": "openflow:4:2", + "port-type":"external", + "port-ip-address": "", + "port-mac-address":"08:00:27:0a:09:0b", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"openflow:4:2" + } + ] + } + ] + }, + { + "node-id": "external:internet-1", + "node-type": "ext-router", + "attribute":[ + { + "name":"location", + "value":"external:internet-1" + }, + { + "name":"capacity", + "value":"" + } + ], + "port": [], + "mac-address":"08:00:27:40:9c:10", + "protocol":"static" + }, + { + "node-id": "external:enterprise-1", + "node-type": "ext-router", + "attribute":[ + { + "name":"location", + "value":"external:enterprise-1" + }, + { + "name":"capacity", + "value":"" + } + ], + "port": [], + "mac-address":"08:00:27:0d:ef:79", + "protocol":"static" + } + ], + + + "link": [ + { + "link-id":"link_1", + "left-node-id":"openflow:1", + "left-port-id":"openflow:1:3", + "right-node-id":"openflow:3", + "right-port-id":"openflow:3:1", + "link-bandwidth":"10240", + "metric":"1", + "delay":"", + "loss-rate":"" + }, + { + "link-id":"link_2", + "left-node-id":"openflow:3", + "left-port-id":"openflow:3:1", + "right-node-id":"openflow:1", + "right-port-id":"openflow:1:3", + "link-bandwidth":"10240", + "metric":"1", + "delay":"", + "loss-rate":"" + }, + + { + "link-id":"link_3", + "left-node-id":"openflow:2", + "left-port-id":"openflow:2:3", + "right-node-id":"openflow:3", + "right-port-id":"openflow:3:2", + "link-bandwidth":"10240", + "metric":"1", + "delay":"", + "loss-rate":"" + }, + + { + "link-id":"link_4", + "left-node-id":"openflow:3", + "left-port-id":"openflow:3:2", + "right-node-id":"openflow:2", + "right-port-id":"openflow:2:3", + "link-bandwidth":"10240", + "metric":"1", + "delay":"", + "loss-rate":"" + }, + + { + "link-id":"link_5", + "left-node-id":"openflow:3", + "left-port-id":"openflow:3:3", + "right-node-id":"openflow:4", + "right-port-id":"openflow:4:1", + "link-bandwidth":"10240", + "metric":"1", + "delay":"", + "loss-rate":"" + }, + { + "link-id":"link_6", + "left-node-id":"openflow:4", + "left-port-id":"openflow:4:1", + "right-node-id":"openflow:3", + "right-port-id":"openflow:3:3", + "link-bandwidth":"10240", + "metric":"1", + "delay":"", + "loss-rate":"" + }, + + { + "link-id":"link_7", + "left-node-id":"openflow:3", + "left-port-id":"openflow:3:4", + "right-node-id":"external:internet-1", + "right-port-id":"", + "link-bandwidth":"10240", + "metric":"", + "delay":"", + "loss-rate":"" + }, + { + "link-id":"link_8", + "left-node-id":"external:internet-1", + "left-port-id":"", + "right-node-id":"openflow:3", + "right-port-id":"openflow:3:4", + "link-bandwidth":"10240", + "metric":"", + "delay":"", + "loss-rate":"" + }, + + { + "link-id":"link_9", + "left-node-id":"openflow:4", + "left-port-id":"openflow:4:2", + "right-node-id":"external:enterprise-1", + "right-port-id":"", + "link-bandwidth":"10240", + "metric":"", + "delay":"", + "loss-rate":"" + }, + { + "link-id":"link_10", + "left-node-id":"external:enterprise-1", + "left-port-id":"", + "right-node-id":"openflow:4", + "right-port-id":"openflow:4:2", + "link-bandwidth":"10240", + "metric":"", + "delay":"", + "loss-rate":"" + } + ], + + "host":[ + { + "name":"video-server1", + "id":"7b796915-adf4-4356-b5ca-de005ac410c1", + "ip-addresses":[ + {"ip-address":"192.168.11.2"} + ], + "mac-address":"00:00:00:00:00:03", + "node-id":"openflow:1", + "connector-id":"openflow:1:1" + }, + { + "name":"vm1", + "id":"1eaf9a67-a171-42a8-9282-71cf702f61dd", + "ip-addresses":[ + {"ip-address":"192.168.12.2"} + ], + "mac-address":"00:00:00:00:00:01", + "node-id":"openflow:1", + "connector-id":"openflow:1:2" + }, + { + "name":"vm2", + "id":"6c787caa-156a-49ed-8546-547bdccf283c", + "ip-addresses":[ + {"ip-address":"192.168.12.3"} + ], + "mac-address":"00:00:00:00:00:02", + "node-id":"openflow:2", + "connector-id":"openflow:2:1" + }, + { + "name":"video-server2", + "id":"22282cca-9a13-4d0c-a67e-a933ebb0b0ae", + "ip-addresses":[ + {"ip-address":"192.168.12.4"} + ], + "mac-address":"08:00:27:a0:a9:b3", + "node-id":"openflow:2", + "connector-id":"openflow:2:2" + } + ] + } + +} \ No newline at end of file diff --git a/nemo-renderers/openflow-renderer/src/main/resources/etc/nemo/resource-servicechain.json b/nemo-renderers/openflow-renderer/src/main/resources/etc/nemo/resource-servicechain.json new file mode 100644 index 0000000..d7ca7a8 --- /dev/null +++ b/nemo-renderers/openflow-renderer/src/main/resources/etc/nemo/resource-servicechain.json @@ -0,0 +1,612 @@ +{ + "physicalnetwork":{ + "node": [ + { + "node-id": "openflow:1", + "node-type": "router", + "attribute":[ + { + "name":"location", + "value":"openflow:1" + }, + { + "name":"capacity", + "value":"" + } + ], + "port": [ + { + "port-id": "openflow:1:1", + "port-type":"external", + "port-ip-address": "", + "port-mac-address":"00:00:00:00:01:01", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"openflow:1:1" + } + ] + }, + { + "port-id": "openflow:1:2", + "port-type":"external", + "port-ip-address": "", + "port-mac-address":"00:00:00:00:01:02", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"openflow:1:2" + } + ] + }, + { + "port-id": "openflow:1:3", + "port-type":"internal", + "port-ip-address": "", + "port-mac-address":"00:00:00:00:01:03", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"openflow:1:3" + } + ] + } + ] + }, + { + "node-id": "openflow:2", + "node-type": "router", + "attribute":[ + { + "name":"location", + "value":"openflow:2" + }, + { + "name":"capacity", + "value":"" + } + ], + "port": [ + { + "port-id": "openflow:2:1", + "port-type":"external", + "port-ip-address": "", + "port-mac-address":"00:00:00:00:02:01", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"openflow:2:1" + } + ] + }, + { + "port-id": "openflow:2:2", + "port-type":"external", + "port-ip-address": "", + "port-mac-address":"00:00:00:00:02:02", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"openflow:2:2" + } + ] + }, + { + "port-id": "openflow:2:3", + "port-type":"internal", + "port-ip-address": "", + "port-mac-address":"00:00:00:00:02:03", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"openflow:2:3" + } + ] + } + ] + }, + { + "node-id": "openflow:3", + "node-type": "router", + "attribute":[ + { + "name":"location", + "value":"openflow:3" + }, + { + "name":"capacity", + "value":"" + } + ], + "port": [ + { + "port-id": "openflow:3:1", + "port-type":"internal", + "port-ip-address": "", + "port-mac-address":"00:00:00:00:03:01", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"openflow:3:1" + } + ] + }, + { + "port-id": "openflow:3:2", + "port-type":"internal", + "port-ip-address": "", + "port-mac-address":"00:00:00:00:03:02", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"openflow:3:2" + } + ] + }, + { + "port-id": "openflow:3:3", + "port-type":"internal", + "port-ip-address": "", + "port-mac-address":"00:00:00:00:03:03", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"openflow:3:3" + } + ] + }, + { + "port-id": "openflow:3:4", + "port-type":"external", + "port-ip-address": "", + "port-mac-address":"00:00:00:00:03:04", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"openflow:3:4" + } + ] + } + ] + }, + { + "node-id": "openflow:4", + "node-type": "router", + "attribute":[ + { + "name":"location", + "value":"openflow:4" + }, + { + "name":"capacity", + "value":"" + } + ], + "port": [ + { + "port-id": "openflow:4:1", + "port-type":"internal", + "port-ip-address": "", + "port-mac-address":"00:00:00:00:04:01", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"openflow:4:1" + } + ] + }, + { + "port-id": "openflow:4:2", + "port-type":"external", + "port-ip-address": "", + "port-mac-address":"00:00:00:00:04:02", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"openflow:4:2" + } + ] + } + ] + }, + { + "node-id": "external:branch-1", + "node-type": "ext-router", + "attribute":[ + { + "name":"location", + "value":"external:branch-1" + }, + { + "name":"capacity", + "value":"" + } + ], + "port": [], + "mac-address":"08:00:27:6e:f2:07", + "protocol":"static" + }, + { + "node-id": "external:headquarters-1", + "node-type": "ext-router", + "attribute":[ + { + "name":"location", + "value":"external:headquarters-1" + }, + { + "name":"capacity", + "value":"" + } + ], + "port": [], + "mac-address":"08:00:27:cb:43:ca", + "protocol":"static" + }, + { + "node-id": "external:fw1", + "node-type": "ext-router", + "attribute":[ + { + "name":"location", + "value":"external:fw1" + }, + { + "name":"capacity", + "value":"1" + } + ], + "port": [ + { + "port-id": "fw1:1", + "port-type":"external", + "port-ip-address": "", + "port-mac-address":"08:00:27:65:4c:f6", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"fw1:1" + } + ] + } + ], + "mac-address":"08:00:27:65:4c:f6", + "protocol":"static" + }, + { + "node-id": "external:fw2", + "node-type": "ext-router", + "attribute":[ + { + "name":"location", + "value":"external:fw2" + }, + { + "name":"capacity", + "value":"1" + } + ], + "port": [ + { + "port-id": "fw2:1", + "port-type":"external", + "port-ip-address": "", + "port-mac-address":"00:00:00:00:00:01", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"fw2:1" + } + ] + } + ], + "mac-address":"00:00:00:00:00:01", + "protocol":"static" + }, + { + "node-id": "external:cache1", + "node-type": "ext-router", + "attribute":[ + { + "name":"location", + "value":"external:cache1" + }, + { + "name":"capacity", + "value":"" + } + ], + "port": [ + { + "port-id": "cache1:1", + "port-type":"external", + "port-ip-address": "", + "port-mac-address":"00:00:00:00:00:02", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"cache1:1" + } + ] + } + ], + "mac-address":"00:00:00:00:00:02", + "protocol":"static" + }, + { + "node-id": "external:cache2", + "node-type": "ext-router", + "attribute":[ + { + "name":"location", + "value":"external:cache2" + }, + { + "name":"capacity", + "value":"" + } + ], + "port": [ + { + "port-id": "cache2:1", + "port-type":"external", + "port-ip-address": "", + "port-mac-address":"08:00:27:90:0f:a5", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"cache2:1" + } + ] + } + ], + "mac-address":"08:00:27:90:0f:a5", + "protocol":"static" + } + ], + + "link": [ + { + "link-id":"link_1", + "left-node-id":"openflow:1", + "left-port-id":"openflow:1:3", + "right-node-id":"openflow:3", + "right-port-id":"openflow:3:1", + "link-bandwidth":"10240", + "metric":"1", + "delay":"", + "loss-rate":"" + }, + { + "link-id":"link_2", + "left-node-id":"openflow:3", + "left-port-id":"openflow:3:1", + "right-node-id":"openflow:1", + "right-port-id":"openflow:1:3", + "link-bandwidth":"10240", + "metric":"1", + "delay":"", + "loss-rate":"" + }, + + { + "link-id":"link_3", + "left-node-id":"openflow:3", + "left-port-id":"openflow:3:2", + "right-node-id":"openflow:2", + "right-port-id":"openflow:2:3", + "link-bandwidth":"10240", + "metric":"1", + "delay":"", + "loss-rate":"" + }, + { + "link-id":"link_4", + "left-node-id":"openflow:2", + "left-port-id":"openflow:2:3", + "right-node-id":"openflow:3", + "right-port-id":"openflow:3:2", + "link-bandwidth":"10240", + "metric":"1", + "delay":"", + "loss-rate":"" + }, + + { + "link-id":"link_5", + "left-node-id":"openflow:3", + "left-port-id":"openflow:3:3", + "right-node-id":"openflow:4", + "right-port-id":"openflow:4:1", + "link-bandwidth":"10240", + "metric":"1", + "delay":"", + "loss-rate":"" + }, + { + "link-id":"link_6", + "left-node-id":"openflow:4", + "left-port-id":"openflow:4:1", + "right-node-id":"openflow:3", + "right-port-id":"openflow:3:3", + "link-bandwidth":"10240", + "metric":"1", + "delay":"", + "loss-rate":"" + }, + + { + "link-id":"link_7", + "left-node-id":"openflow:3", + "left-port-id":"openflow:3:4", + "right-node-id":"external:branch-1", + "right-port-id":"", + "link-bandwidth":"10240", + "metric":"", + "delay":"", + "loss-rate":"" + }, + { + "link-id":"link_8", + "left-node-id":"external:branch-1", + "left-port-id":"", + "right-node-id":"openflow:3", + "right-port-id":"openflow:3:4", + "link-bandwidth":"10240", + "metric":"", + "delay":"", + "loss-rate":"" + }, + + { + "link-id":"link_9", + "left-node-id":"openflow:4", + "left-port-id":"openflow:4:2", + "right-node-id":"external:headquarters-1", + "right-port-id":"", + "link-bandwidth":"10240", + "metric":"", + "delay":"", + "loss-rate":"" + }, + { + "link-id":"link_10", + "left-node-id":"external:headquarters-1", + "left-port-id":"", + "right-node-id":"openflow:4", + "right-port-id":"openflow:4:2", + "link-bandwidth":"10240", + "metric":"", + "delay":"", + "loss-rate":"" + }, + + { + "link-id":"link_11", + "left-node-id":"openflow:1", + "left-port-id":"openflow:1:1", + "right-node-id":"external:fw1", + "right-port-id":"fw1:1", + "link-bandwidth":"10240", + "metric":"", + "delay":"", + "loss-rate":"" + }, + { + "link-id":"link_12", + "left-node-id":"external:fw1", + "left-port-id":"fw1:1", + "right-node-id":"openflow:1", + "right-port-id":"openflow:1:1", + "link-bandwidth":"10240", + "metric":"", + "delay":"", + "loss-rate":"" + }, + + { + "link-id":"link_13", + "left-node-id":"openflow:1", + "left-port-id":"openflow:1:2", + "right-node-id":"external:fw2", + "right-port-id":"fw2:1", + "link-bandwidth":"10240", + "metric":"", + "delay":"", + "loss-rate":"" + }, + { + "link-id":"link_14", + "left-node-id":"external:fw2", + "left-port-id":"fw2:1", + "right-node-id":"openflow:1", + "right-port-id":"openflow:1:2", + "link-bandwidth":"10240", + "metric":"", + "delay":"", + "loss-rate":"" + }, + + { + "link-id":"link_15", + "left-node-id":"openflow:2", + "left-port-id":"openflow:2:1", + "right-node-id":"external:cache1", + "right-port-id":"cache1:1", + "link-bandwidth":"10240", + "metric":"", + "delay":"", + "loss-rate":"" + }, + { + "link-id":"link_16", + "left-node-id":"external:cache1", + "left-port-id":"cache1:1", + "right-node-id":"openflow:2", + "right-port-id":"openflow:2:1", + "link-bandwidth":"10240", + "metric":"", + "delay":"", + "loss-rate":"" + }, + + { + "link-id":"link_17", + "left-node-id":"openflow:2", + "left-port-id":"openflow:2:2", + "right-node-id":"external:cache2", + "right-port-id":"cache2:1", + "link-bandwidth":"10240", + "metric":"", + "delay":"", + "loss-rate":"" + }, + { + "link-id":"link_18", + "left-node-id":"external:cache2", + "left-port-id":"cache2:1", + "right-node-id":"openflow:2", + "right-port-id":"openflow:2:2", + "link-bandwidth":"10240", + "metric":"", + "delay":"", + "loss-rate":"" + } + ], + + "host":[] + } + +} \ No newline at end of file diff --git a/nemo-renderers/openflow-renderer/src/main/resources/etc/nemo/resource.json b/nemo-renderers/openflow-renderer/src/main/resources/etc/nemo/resource.json new file mode 100644 index 0000000..d7ca7a8 --- /dev/null +++ b/nemo-renderers/openflow-renderer/src/main/resources/etc/nemo/resource.json @@ -0,0 +1,612 @@ +{ + "physicalnetwork":{ + "node": [ + { + "node-id": "openflow:1", + "node-type": "router", + "attribute":[ + { + "name":"location", + "value":"openflow:1" + }, + { + "name":"capacity", + "value":"" + } + ], + "port": [ + { + "port-id": "openflow:1:1", + "port-type":"external", + "port-ip-address": "", + "port-mac-address":"00:00:00:00:01:01", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"openflow:1:1" + } + ] + }, + { + "port-id": "openflow:1:2", + "port-type":"external", + "port-ip-address": "", + "port-mac-address":"00:00:00:00:01:02", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"openflow:1:2" + } + ] + }, + { + "port-id": "openflow:1:3", + "port-type":"internal", + "port-ip-address": "", + "port-mac-address":"00:00:00:00:01:03", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"openflow:1:3" + } + ] + } + ] + }, + { + "node-id": "openflow:2", + "node-type": "router", + "attribute":[ + { + "name":"location", + "value":"openflow:2" + }, + { + "name":"capacity", + "value":"" + } + ], + "port": [ + { + "port-id": "openflow:2:1", + "port-type":"external", + "port-ip-address": "", + "port-mac-address":"00:00:00:00:02:01", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"openflow:2:1" + } + ] + }, + { + "port-id": "openflow:2:2", + "port-type":"external", + "port-ip-address": "", + "port-mac-address":"00:00:00:00:02:02", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"openflow:2:2" + } + ] + }, + { + "port-id": "openflow:2:3", + "port-type":"internal", + "port-ip-address": "", + "port-mac-address":"00:00:00:00:02:03", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"openflow:2:3" + } + ] + } + ] + }, + { + "node-id": "openflow:3", + "node-type": "router", + "attribute":[ + { + "name":"location", + "value":"openflow:3" + }, + { + "name":"capacity", + "value":"" + } + ], + "port": [ + { + "port-id": "openflow:3:1", + "port-type":"internal", + "port-ip-address": "", + "port-mac-address":"00:00:00:00:03:01", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"openflow:3:1" + } + ] + }, + { + "port-id": "openflow:3:2", + "port-type":"internal", + "port-ip-address": "", + "port-mac-address":"00:00:00:00:03:02", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"openflow:3:2" + } + ] + }, + { + "port-id": "openflow:3:3", + "port-type":"internal", + "port-ip-address": "", + "port-mac-address":"00:00:00:00:03:03", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"openflow:3:3" + } + ] + }, + { + "port-id": "openflow:3:4", + "port-type":"external", + "port-ip-address": "", + "port-mac-address":"00:00:00:00:03:04", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"openflow:3:4" + } + ] + } + ] + }, + { + "node-id": "openflow:4", + "node-type": "router", + "attribute":[ + { + "name":"location", + "value":"openflow:4" + }, + { + "name":"capacity", + "value":"" + } + ], + "port": [ + { + "port-id": "openflow:4:1", + "port-type":"internal", + "port-ip-address": "", + "port-mac-address":"00:00:00:00:04:01", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"openflow:4:1" + } + ] + }, + { + "port-id": "openflow:4:2", + "port-type":"external", + "port-ip-address": "", + "port-mac-address":"00:00:00:00:04:02", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"openflow:4:2" + } + ] + } + ] + }, + { + "node-id": "external:branch-1", + "node-type": "ext-router", + "attribute":[ + { + "name":"location", + "value":"external:branch-1" + }, + { + "name":"capacity", + "value":"" + } + ], + "port": [], + "mac-address":"08:00:27:6e:f2:07", + "protocol":"static" + }, + { + "node-id": "external:headquarters-1", + "node-type": "ext-router", + "attribute":[ + { + "name":"location", + "value":"external:headquarters-1" + }, + { + "name":"capacity", + "value":"" + } + ], + "port": [], + "mac-address":"08:00:27:cb:43:ca", + "protocol":"static" + }, + { + "node-id": "external:fw1", + "node-type": "ext-router", + "attribute":[ + { + "name":"location", + "value":"external:fw1" + }, + { + "name":"capacity", + "value":"1" + } + ], + "port": [ + { + "port-id": "fw1:1", + "port-type":"external", + "port-ip-address": "", + "port-mac-address":"08:00:27:65:4c:f6", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"fw1:1" + } + ] + } + ], + "mac-address":"08:00:27:65:4c:f6", + "protocol":"static" + }, + { + "node-id": "external:fw2", + "node-type": "ext-router", + "attribute":[ + { + "name":"location", + "value":"external:fw2" + }, + { + "name":"capacity", + "value":"1" + } + ], + "port": [ + { + "port-id": "fw2:1", + "port-type":"external", + "port-ip-address": "", + "port-mac-address":"00:00:00:00:00:01", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"fw2:1" + } + ] + } + ], + "mac-address":"00:00:00:00:00:01", + "protocol":"static" + }, + { + "node-id": "external:cache1", + "node-type": "ext-router", + "attribute":[ + { + "name":"location", + "value":"external:cache1" + }, + { + "name":"capacity", + "value":"" + } + ], + "port": [ + { + "port-id": "cache1:1", + "port-type":"external", + "port-ip-address": "", + "port-mac-address":"00:00:00:00:00:02", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"cache1:1" + } + ] + } + ], + "mac-address":"00:00:00:00:00:02", + "protocol":"static" + }, + { + "node-id": "external:cache2", + "node-type": "ext-router", + "attribute":[ + { + "name":"location", + "value":"external:cache2" + }, + { + "name":"capacity", + "value":"" + } + ], + "port": [ + { + "port-id": "cache2:1", + "port-type":"external", + "port-ip-address": "", + "port-mac-address":"08:00:27:90:0f:a5", + "mask": "", + "bandwidth":"", + "attribute":[ + { + "name":"location", + "value":"cache2:1" + } + ] + } + ], + "mac-address":"08:00:27:90:0f:a5", + "protocol":"static" + } + ], + + "link": [ + { + "link-id":"link_1", + "left-node-id":"openflow:1", + "left-port-id":"openflow:1:3", + "right-node-id":"openflow:3", + "right-port-id":"openflow:3:1", + "link-bandwidth":"10240", + "metric":"1", + "delay":"", + "loss-rate":"" + }, + { + "link-id":"link_2", + "left-node-id":"openflow:3", + "left-port-id":"openflow:3:1", + "right-node-id":"openflow:1", + "right-port-id":"openflow:1:3", + "link-bandwidth":"10240", + "metric":"1", + "delay":"", + "loss-rate":"" + }, + + { + "link-id":"link_3", + "left-node-id":"openflow:3", + "left-port-id":"openflow:3:2", + "right-node-id":"openflow:2", + "right-port-id":"openflow:2:3", + "link-bandwidth":"10240", + "metric":"1", + "delay":"", + "loss-rate":"" + }, + { + "link-id":"link_4", + "left-node-id":"openflow:2", + "left-port-id":"openflow:2:3", + "right-node-id":"openflow:3", + "right-port-id":"openflow:3:2", + "link-bandwidth":"10240", + "metric":"1", + "delay":"", + "loss-rate":"" + }, + + { + "link-id":"link_5", + "left-node-id":"openflow:3", + "left-port-id":"openflow:3:3", + "right-node-id":"openflow:4", + "right-port-id":"openflow:4:1", + "link-bandwidth":"10240", + "metric":"1", + "delay":"", + "loss-rate":"" + }, + { + "link-id":"link_6", + "left-node-id":"openflow:4", + "left-port-id":"openflow:4:1", + "right-node-id":"openflow:3", + "right-port-id":"openflow:3:3", + "link-bandwidth":"10240", + "metric":"1", + "delay":"", + "loss-rate":"" + }, + + { + "link-id":"link_7", + "left-node-id":"openflow:3", + "left-port-id":"openflow:3:4", + "right-node-id":"external:branch-1", + "right-port-id":"", + "link-bandwidth":"10240", + "metric":"", + "delay":"", + "loss-rate":"" + }, + { + "link-id":"link_8", + "left-node-id":"external:branch-1", + "left-port-id":"", + "right-node-id":"openflow:3", + "right-port-id":"openflow:3:4", + "link-bandwidth":"10240", + "metric":"", + "delay":"", + "loss-rate":"" + }, + + { + "link-id":"link_9", + "left-node-id":"openflow:4", + "left-port-id":"openflow:4:2", + "right-node-id":"external:headquarters-1", + "right-port-id":"", + "link-bandwidth":"10240", + "metric":"", + "delay":"", + "loss-rate":"" + }, + { + "link-id":"link_10", + "left-node-id":"external:headquarters-1", + "left-port-id":"", + "right-node-id":"openflow:4", + "right-port-id":"openflow:4:2", + "link-bandwidth":"10240", + "metric":"", + "delay":"", + "loss-rate":"" + }, + + { + "link-id":"link_11", + "left-node-id":"openflow:1", + "left-port-id":"openflow:1:1", + "right-node-id":"external:fw1", + "right-port-id":"fw1:1", + "link-bandwidth":"10240", + "metric":"", + "delay":"", + "loss-rate":"" + }, + { + "link-id":"link_12", + "left-node-id":"external:fw1", + "left-port-id":"fw1:1", + "right-node-id":"openflow:1", + "right-port-id":"openflow:1:1", + "link-bandwidth":"10240", + "metric":"", + "delay":"", + "loss-rate":"" + }, + + { + "link-id":"link_13", + "left-node-id":"openflow:1", + "left-port-id":"openflow:1:2", + "right-node-id":"external:fw2", + "right-port-id":"fw2:1", + "link-bandwidth":"10240", + "metric":"", + "delay":"", + "loss-rate":"" + }, + { + "link-id":"link_14", + "left-node-id":"external:fw2", + "left-port-id":"fw2:1", + "right-node-id":"openflow:1", + "right-port-id":"openflow:1:2", + "link-bandwidth":"10240", + "metric":"", + "delay":"", + "loss-rate":"" + }, + + { + "link-id":"link_15", + "left-node-id":"openflow:2", + "left-port-id":"openflow:2:1", + "right-node-id":"external:cache1", + "right-port-id":"cache1:1", + "link-bandwidth":"10240", + "metric":"", + "delay":"", + "loss-rate":"" + }, + { + "link-id":"link_16", + "left-node-id":"external:cache1", + "left-port-id":"cache1:1", + "right-node-id":"openflow:2", + "right-port-id":"openflow:2:1", + "link-bandwidth":"10240", + "metric":"", + "delay":"", + "loss-rate":"" + }, + + { + "link-id":"link_17", + "left-node-id":"openflow:2", + "left-port-id":"openflow:2:2", + "right-node-id":"external:cache2", + "right-port-id":"cache2:1", + "link-bandwidth":"10240", + "metric":"", + "delay":"", + "loss-rate":"" + }, + { + "link-id":"link_18", + "left-node-id":"external:cache2", + "left-port-id":"cache2:1", + "right-node-id":"openflow:2", + "right-port-id":"openflow:2:2", + "link-bandwidth":"10240", + "metric":"", + "delay":"", + "loss-rate":"" + } + ], + + "host":[] + } + +} \ No newline at end of file diff --git a/nemo-renderers/openflow-renderer/src/main/yang/openflow-renderer-impl.yang b/nemo-renderers/openflow-renderer/src/main/yang/openflow-renderer-impl.yang index dc8b4d9..0a1637e 100644 --- a/nemo-renderers/openflow-renderer/src/main/yang/openflow-renderer-impl.yang +++ b/nemo-renderers/openflow-renderer/src/main/yang/openflow-renderer-impl.yang @@ -19,7 +19,7 @@ module openflow-renderer-impl { "This module contains the base YANG definitions for NEMO Openflow renderer implementation."; - revision "2015-07-01" { + revision "2015-10-10" { description "Initial revision."; } diff --git a/nemo-renderers/openflow-renderer/src/test/java/README b/nemo-renderers/openflow-renderer/src/test/java/README deleted file mode 100644 index e69de29..0000000 diff --git a/nemo-renderers/openflow-renderer/src/test/resources/network-down-bod.sh b/nemo-renderers/openflow-renderer/src/test/resources/network-down-bod.sh new file mode 100644 index 0000000..23b64a1 --- /dev/null +++ b/nemo-renderers/openflow-renderer/src/test/resources/network-down-bod.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +pkill -9 ofdatapath +pkill -9 ofprotocol + +pkill -9 fail-ofdatapath +pkill -9 fail-ofprotocol + +pkill -9 ext-ofdatapath +pkill -9 ext-ofprotocol + +ip link del sw1-eth1 +ip link del sw1-eth2 +ip link del sw1-eth3 +ip link del sw2-eth1 +ip link del sw2-eth3 +ip link del sw3-eth1 +ip link del sw3-eth2 +ip link del sw3-eth3 +ip link del sw4-eth1 + +ip link del server1-eth0 +ip netns delete server1 +ip link del vm1-eth0 +ip netns delete vm1 +ip link del vm2-eth0 +ip netns delete vm2 + +rm /tmp/sw* +rm /tmp/*.log +rm /tmp/vconn-unix.* +rm /tmp/vlogs.* + +exit 0 \ No newline at end of file diff --git a/nemo-renderers/openflow-renderer/src/test/resources/network-down-servicechain.sh b/nemo-renderers/openflow-renderer/src/test/resources/network-down-servicechain.sh new file mode 100644 index 0000000..d610141 --- /dev/null +++ b/nemo-renderers/openflow-renderer/src/test/resources/network-down-servicechain.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +pkill -9 ofdatapath +pkill -9 ofprotocol + +pkill -9 fail-ofdatapath +pkill -9 fail-ofprotocol + +pkill -9 ext-ofdatapath +pkill -9 ext-ofprotocol + +ip link del sw1-eth1 +ip link del sw1-eth2 +ip link del sw1-eth3 +ip link del sw2-eth1 +ip link del sw2-eth3 +ip link del sw3-eth1 +ip link del sw3-eth2 +ip link del sw3-eth3 +ip link del sw4-eth1 + +ip link del fw1-eth0 +ip netns delete fw1 +ip link del fw2-eth0 +ip netns delete fw2 +ip link del cache1-eth0 +ip netns delete cache1 + +rm /tmp/sw* +rm /tmp/*.log +rm /tmp/vconn-unix.* +rm /tmp/vlogs.* + +exit 0 \ No newline at end of file diff --git a/nemo-renderers/openflow-renderer/src/test/resources/network-up-bod.sh b/nemo-renderers/openflow-renderer/src/test/resources/network-up-bod.sh new file mode 100644 index 0000000..0db75c6 --- /dev/null +++ b/nemo-renderers/openflow-renderer/src/test/resources/network-up-bod.sh @@ -0,0 +1,119 @@ +#!/bin/bash + +########## sw1 ########## +ip link add name sw1-eth1 type veth peer name server1-eth0 +ip link add name sw1-eth2 type veth peer name vm1-eth0 +ip link add name sw1-eth3 type veth peer name sw3-eth1 + +########## sw2 ########## +ip link add name sw2-eth1 type veth peer name vm2-eth0 +ip link add name sw2-eth3 type veth peer name sw3-eth2 + +########## sw3 ########## +#ip link add name sw3-eth1 type veth peer name sw1-eth3 +#ip link add name sw3-eth2 type veth peer name sw2-eth3 +ip link add name sw3-eth3 type veth peer name sw4-eth1 + +########## sw4 ########## +#ip link add name sw4-eth1 type veth peer name sw3-eth3 + +########## server1 ########## +ip netns add server1 +ip link set server1-eth0 netns server1 + +########## vm1 ########## +ip netns add vm1 +ip link set vm1-eth0 netns vm1 + +########## vm2 ########## +ip netns add vm2 +ip link set vm2-eth0 netns vm2 + +########## sw1 ########## +ofdatapath -i sw1-eth1,sw1-eth2,sw1-eth3 punix:/tmp/sw1 -d 000000000001 1> /tmp/sw1-ofd.log 2> /tmp/sw1-ofd.log & +ofprotocol unix:/tmp/sw1 tcp:127.0.0.1:6633 --fail=closed --listen=ptcp:6661 1> /tmp/sw1-ofp.log 2> /tmp/sw1-ofp.log & + +########## sw2 ########## +ofdatapath -i sw2-eth1,eth1,sw2-eth3 punix:/tmp/sw2 -d 000000000002 1> /tmp/sw2-ofd.log 2> /tmp/sw2-ofd.log & +ofprotocol unix:/tmp/sw2 tcp:127.0.0.1:6633 --fail=closed --listen=ptcp:6662 1> /tmp/sw2-ofp.log 2> /tmp/sw2-ofp.log & + +########## sw3 ########## +ofdatapath -i sw3-eth1,sw3-eth2,sw3-eth3,eth2 punix:/tmp/sw3 -d 000000000003 1> /tmp/sw3-ofd.log 2> /tmp/sw3-ofd.log & +ofprotocol unix:/tmp/sw3 tcp:127.0.0.1:6633 --fail=closed --listen=ptcp:6663 1> /tmp/sw3-ofp.log 2> /tmp/sw3-ofp.log & + +########## sw4 ########## +ofdatapath -i sw4-eth1,eth3 punix:/tmp/sw4 -d 000000000004 1> /tmp/sw4-ofd.log 2> /tmp/sw4-ofd.log & +ofprotocol unix:/tmp/sw4 tcp:127.0.0.1:6633 --fail=closed --listen=ptcp:6664 1> /tmp/sw4-ofp.log 2> /tmp/sw4-ofp.log & + +sleep 5 + +########## lldp ########## +dpctl unix:/tmp/sw1 flow-mod cmd=add,table=0 eth_type=0x88cc apply:output=ctrl:0xff +dpctl unix:/tmp/sw2 flow-mod cmd=add,table=0 eth_type=0x88cc apply:output=ctrl:0xff +dpctl unix:/tmp/sw3 flow-mod cmd=add,table=0 eth_type=0x88cc apply:output=ctrl:0xff +dpctl unix:/tmp/sw4 flow-mod cmd=add,table=0 eth_type=0x88cc apply:output=ctrl:0xff + +exit 0 + + + +ip netns exec server1 bash +ifconfig server1-eth0 down +ifconfig server1-eth0 hw ether 00:00:00:00:00:03 +ifconfig server1-eth0 192.168.11.2/24 +ifconfig server1-eth0 up +ifconfig server1-eth0 +route add default gw 192.168.11.1 +route -n +arp -s 192.168.11.1 00:00:0a:0b:0c:01 +exit + +ip netns exec vm1 bash +ifconfig vm1-eth0 down +ifconfig vm1-eth0 hw ether 00:00:00:00:00:01 +ifconfig vm1-eth0 192.168.12.2/24 +ifconfig vm1-eth0 up +ifconfig vm1-eth0 +route add default gw 192.168.12.1 +route -n +arp -s 192.168.12.1 00:00:0a:0b:0c:02 +arp -s 192.168.12.3 00:00:00:00:00:02 +arp -s 192.168.12.4 08:00:27:a0:a9:b3 +exit + +ip netns exec vm2 bash +ifconfig vm2-eth0 down +ifconfig vm2-eth0 hw ether 00:00:00:00:00:02 +ifconfig vm2-eth0 192.168.12.3/24 +ifconfig vm2-eth0 up +ifconfig vm2-eth0 +route add default gw 192.168.12.1 +route -n +arp -s 192.168.12.1 00:00:0a:0b:0c:02 +arp -s 192.168.12.2 00:00:00:00:00:01 +arp -s 192.168.12.4 08:00:27:a0:a9:b3 +exit + + + +ip netns exec server1 bash +ping -c 3 192.168.12.4 +ping -c 3 192.168.13.2 +ping -c 3 172.168.1.2 +exit + +ip netns exec vm1 bash +ping -c 3 192.168.12.3 +ping -c 3 192.168.12.4 +ping -c 3 192.168.11.2 +ping -c 3 192.168.13.2 +ping -c 3 172.168.1.2 +exit + +ip netns exec vm2 bash +ping -c 3 192.168.12.2 +ping -c 3 192.168.12.4 +ping -c 3 192.168.11.2 +ping -c 3 192.168.13.2 +ping -c 3 172.168.1.2 +exit diff --git a/nemo-renderers/openflow-renderer/src/test/resources/network-up-servicechain.sh b/nemo-renderers/openflow-renderer/src/test/resources/network-up-servicechain.sh new file mode 100644 index 0000000..4b786c8 --- /dev/null +++ b/nemo-renderers/openflow-renderer/src/test/resources/network-up-servicechain.sh @@ -0,0 +1,83 @@ +#!/bin/bash + +########## sw1 ########## +ip link add name sw1-eth1 type veth peer name fw1-eth0 +ip link add name sw1-eth2 type veth peer name fw2-eth0 +ip link add name sw1-eth3 type veth peer name sw3-eth1 + +########## sw2 ########## +ip link add name sw2-eth1 type veth peer name cache1-eth0 +ip link add name sw2-eth3 type veth peer name sw3-eth2 + +########## sw3 ########## +#ip link add name sw3-eth1 type veth peer name sw1-eth3 +#ip link add name sw3-eth2 type veth peer name sw2-eth3 +ip link add name sw3-eth3 type veth peer name sw4-eth1 + +########## sw4 ########## +#ip link add name sw4-eth1 type veth peer name sw3-eth3 + +########## fw1 ########## +ip netns add fw1 +ip link set fw1-eth0 netns fw1 + +########## fw2 ########## +ip netns add fw2 +ip link set fw2-eth0 netns fw2 + +########## cache1 ########## +ip netns add cache1 +ip link set cache1-eth0 netns cache1 + +########## sw1 ########## +ofdatapath -i sw1-eth1,sw1-eth2,sw1-eth3 punix:/tmp/sw1 -d 000000000001 1> /tmp/sw1-ofd.log 2> /tmp/sw1-ofd.log & +ofprotocol unix:/tmp/sw1 tcp:127.0.0.1:6633 --fail=closed --listen=ptcp:6661 1> /tmp/sw1-ofp.log 2> /tmp/sw1-ofp.log & + +########## sw2 ########## +ofdatapath -i sw2-eth1,eth1,sw2-eth3 punix:/tmp/sw2 -d 000000000002 1> /tmp/sw2-ofd.log 2> /tmp/sw2-ofd.log & +ofprotocol unix:/tmp/sw2 tcp:127.0.0.1:6633 --fail=closed --listen=ptcp:6662 1> /tmp/sw2-ofp.log 2> /tmp/sw2-ofp.log & + +########## sw3 ########## +ofdatapath -i sw3-eth1,sw3-eth2,sw3-eth3,eth2 punix:/tmp/sw3 -d 000000000003 1> /tmp/sw3-ofd.log 2> /tmp/sw3-ofd.log & +ofprotocol unix:/tmp/sw3 tcp:127.0.0.1:6633 --fail=closed --listen=ptcp:6663 1> /tmp/sw3-ofp.log 2> /tmp/sw3-ofp.log & + +########## sw4 ########## +ofdatapath -i sw4-eth1,eth3 punix:/tmp/sw4 -d 000000000004 1> /tmp/sw4-ofd.log 2> /tmp/sw4-ofd.log & +ofprotocol unix:/tmp/sw4 tcp:127.0.0.1:6633 --fail=closed --listen=ptcp:6664 1> /tmp/sw4-ofp.log 2> /tmp/sw4-ofp.log & + +sleep 5 + +########## lldp ########## +dpctl unix:/tmp/sw1 flow-mod cmd=add,table=0 eth_type=0x88cc apply:output=ctrl:0xff +dpctl unix:/tmp/sw2 flow-mod cmd=add,table=0 eth_type=0x88cc apply:output=ctrl:0xff +dpctl unix:/tmp/sw3 flow-mod cmd=add,table=0 eth_type=0x88cc apply:output=ctrl:0xff +dpctl unix:/tmp/sw4 flow-mod cmd=add,table=0 eth_type=0x88cc apply:output=ctrl:0xff + +exit 0 + + + +ip netns exec fw2 bash +ifconfig fw2-eth0 down +ifconfig fw2-eth0 hw ether 00:00:00:00:00:01 +ifconfig fw2-eth0 up +ifconfig fw2-eth0 +exit + +ip netns exec cache1 bash +ifconfig cache1-eth0 down +ifconfig cache1-eth0 hw ether 00:00:00:00:00:02 +ifconfig cache1-eth0 up +ifconfig cache1-eth0 +exit + + + +echo 1 > /proc/sys/net/ipv4/ip_forward +cat /proc/sys/net/ipv4/ip_forward + +iptables -A FORWARD -i eth0 -j DROP +iptables -vxnL FORWARD + +iptables -D FORWARD -i eth0 -j DROP +iptables -vxnL FORWARD diff --git a/nemo-renderers/pom.xml b/nemo-renderers/pom.xml index 7066dda..1024502 100644 --- a/nemo-renderers/pom.xml +++ b/nemo-renderers/pom.xml @@ -5,7 +5,8 @@ This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html --> - + 4.0.0 @@ -27,7 +28,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html scm:git:ssh://git.opendaylight.org:29418/nemo.git scm:git:ssh://git.opendaylight.org:29418/nemo.git - HEAD https://wiki.opendaylight.org/view/NEMO:Main + HEAD - + \ No newline at end of file diff --git a/nemo-ui/src/main/resources/README b/nemo-ui/src/main/resources/README deleted file mode 100644 index e69de29..0000000 diff --git a/pom.xml b/pom.xml index 22b85c9..d898151 100644 --- a/pom.xml +++ b/pom.xml @@ -5,14 +5,15 @@ This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html --> - + 4.0.0 - org.opendaylight.controller - releasepom - 0.3.0-SNAPSHOT - + org.opendaylight.odlparent + odlparent + 1.6.0-SNAPSHOT + org.opendaylight.nemo @@ -30,10 +31,10 @@ and is available at http://www.eclipse.org/legal/epl-v10.html nemo-artifacts nemo-api nemo-impl + nemo-renderers nemo-ui nemo-features nemo-karaf - nemo-renderers https://wiki.opendaylight.org/view/NEMO:Main @@ -58,7 +59,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html scm:git:ssh://git.opendaylight.org:29418/nemo.git scm:git:ssh://git.opendaylight.org:29418/nemo.git - HEAD https://wiki.opendaylight.org/view/NEMO:Main + HEAD