Add Network and Provider Network Intent API support 97/103697/10
authorEric Multanen <eric.w.multanen@intel.com>
Sat, 14 Mar 2020 00:39:40 +0000 (17:39 -0700)
committerRitu Sood <Ritu.Sood@intel.com>
Mon, 23 Mar 2020 22:40:28 +0000 (22:40 +0000)
Add API for CRUD operations to manage network
and provider-network intent resources.

Issue-ID: MULTICLOUD-1029
Signed-off-by: Eric Multanen <eric.w.multanen@intel.com>
Change-Id: If3c71691b3825db50eacdb0ea87b0d5c436ad80f

src/ncm/api/api.go
src/ncm/api/networkhandler.go [new file with mode: 0644]
src/ncm/api/providernethandler.go [new file with mode: 0644]
src/ncm/pkg/module/cluster.go
src/ncm/pkg/module/module.go
src/ncm/pkg/module/module_definitions.go [new file with mode: 0644]
src/ncm/pkg/module/network.go [new file with mode: 0644]
src/ncm/pkg/module/providernet.go [new file with mode: 0644]

index c26f54e..34b46c6 100644 (file)
@@ -25,7 +25,7 @@ import (
 
 var moduleClient *moduleLib.Client
 
-// for the given client and testClient, if the testClient is not null and
+// For the given client and testClient, if the testClient is not null and
 // implements the client manager interface corresponding to client, then
 // return the testClient, otherwise return the client.
 func setClient(client, testClient interface{}) interface{} {
@@ -37,6 +37,20 @@ func setClient(client, testClient interface{}) interface{} {
                                return c
                        }
                }
+       case *moduleLib.NetworkClient:
+               if testClient != nil && reflect.TypeOf(testClient).Implements(reflect.TypeOf((*moduleLib.NetworkManager)(nil)).Elem()) {
+                       c, ok := testClient.(moduleLib.NetworkManager)
+                       if ok {
+                               return c
+                       }
+               }
+       case *moduleLib.ProviderNetClient:
+               if testClient != nil && reflect.TypeOf(testClient).Implements(reflect.TypeOf((*moduleLib.ProviderNetManager)(nil)).Elem()) {
+                       c, ok := testClient.(moduleLib.ProviderNetManager)
+                       if ok {
+                               return c
+                       }
+               }
        default:
                fmt.Printf("unknown type %T\n", cl)
        }
@@ -49,12 +63,11 @@ func NewRouter(testClient interface{}) *mux.Router {
 
        moduleClient = moduleLib.NewClient()
 
+       router := mux.NewRouter().PathPrefix("/v2").Subrouter()
+
        clusterHandler := clusterHandler{
                client: setClient(moduleClient.Cluster, testClient).(moduleLib.ClusterManager),
        }
-
-       router := mux.NewRouter().PathPrefix("/v2").Subrouter()
-
        router.HandleFunc("/cluster-providers", clusterHandler.createClusterProviderHandler).Methods("POST")
        router.HandleFunc("/cluster-providers", clusterHandler.getClusterProviderHandler).Methods("GET")
        router.HandleFunc("/cluster-providers/{name}", clusterHandler.getClusterProviderHandler).Methods("GET")
@@ -72,5 +85,23 @@ func NewRouter(testClient interface{}) *mux.Router {
        router.HandleFunc("/cluster-providers/{provider-name}/clusters/{cluster-name}/kv-pairs/{kvpair}", clusterHandler.getClusterKvPairsHandler).Methods("GET")
        router.HandleFunc("/cluster-providers/{provider-name}/clusters/{cluster-name}/kv-pairs/{kvpair}", clusterHandler.deleteClusterKvPairsHandler).Methods("DELETE")
 
+       networkHandler := networkHandler{
+               client: setClient(moduleClient.Network, testClient).(moduleLib.NetworkManager),
+       }
+       router.HandleFunc("/cluster-providers/{provider-name}/clusters/{cluster-name}/networks", networkHandler.createNetworkHandler).Methods("POST")
+       router.HandleFunc("/cluster-providers/{provider-name}/clusters/{cluster-name}/networks", networkHandler.getNetworkHandler).Methods("GET")
+       router.HandleFunc("/cluster-providers/{provider-name}/clusters/{cluster-name}/networks/{name}", networkHandler.putNetworkHandler).Methods("PUT")
+       router.HandleFunc("/cluster-providers/{provider-name}/clusters/{cluster-name}/networks/{name}", networkHandler.getNetworkHandler).Methods("GET")
+       router.HandleFunc("/cluster-providers/{provider-name}/clusters/{cluster-name}/networks/{name}", networkHandler.deleteNetworkHandler).Methods("DELETE")
+
+       providernetHandler := providernetHandler{
+               client: setClient(moduleClient.ProviderNet, testClient).(moduleLib.ProviderNetManager),
+       }
+       router.HandleFunc("/cluster-providers/{provider-name}/clusters/{cluster-name}/provider-networks", providernetHandler.createProviderNetHandler).Methods("POST")
+       router.HandleFunc("/cluster-providers/{provider-name}/clusters/{cluster-name}/provider-networks", providernetHandler.getProviderNetHandler).Methods("GET")
+       router.HandleFunc("/cluster-providers/{provider-name}/clusters/{cluster-name}/provider-networks/{name}", providernetHandler.putProviderNetHandler).Methods("PUT")
+       router.HandleFunc("/cluster-providers/{provider-name}/clusters/{cluster-name}/provider-networks/{name}", providernetHandler.getProviderNetHandler).Methods("GET")
+       router.HandleFunc("/cluster-providers/{provider-name}/clusters/{cluster-name}/provider-networks/{name}", providernetHandler.deleteProviderNetHandler).Methods("DELETE")
+
        return router
 }
diff --git a/src/ncm/api/networkhandler.go b/src/ncm/api/networkhandler.go
new file mode 100644 (file)
index 0000000..01d077a
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2020 Intel Corporation, Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package api
+
+import (
+       "encoding/json"
+       "fmt"
+       "io"
+       "net/http"
+
+       moduleLib "github.com/onap/multicloud-k8s/src/ncm/pkg/module"
+       "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/validation"
+       pkgerrors "github.com/pkg/errors"
+
+       "github.com/gorilla/mux"
+)
+
+// Used to store backend implementations objects
+// Also simplifies mocking for unit testing purposes
+type networkHandler struct {
+       // Interface that implements Cluster operations
+       // We will set this variable with a mock interface for testing
+       client moduleLib.NetworkManager
+}
+
+// Check for valid format of input parameters
+func validateNetworkInputs(p moduleLib.Network) error {
+       // validate name
+       errs := validation.IsValidName(p.Metadata.Name)
+       if len(errs) > 0 {
+               return pkgerrors.Errorf("Invalid network name - name=[%v], errors: %v", p.Metadata.Name, errs)
+       }
+
+       // validate cni type
+       found := false
+       for _, val := range moduleLib.CNI_TYPES {
+               if p.Spec.CniType == val {
+                       found = true
+                       break
+               }
+       }
+       if !found {
+               return pkgerrors.Errorf("Invalid cni type: %v", p.Spec.CniType)
+       }
+
+       subnets := p.Spec.Ipv4Subnets
+       for _, subnet := range subnets {
+               err := moduleLib.ValidateSubnet(subnet)
+               if err != nil {
+                       return pkgerrors.Wrap(err, "invalid subnet")
+               }
+       }
+       return nil
+}
+
+// Create handles creation of the Network entry in the database
+func (h networkHandler) createNetworkHandler(w http.ResponseWriter, r *http.Request) {
+       var p moduleLib.Network
+       vars := mux.Vars(r)
+       clusterProvider := vars["provider-name"]
+       cluster := vars["cluster-name"]
+
+       err := json.NewDecoder(r.Body).Decode(&p)
+
+       switch {
+       case err == io.EOF:
+               http.Error(w, "Empty body", http.StatusBadRequest)
+               return
+       case err != nil:
+               http.Error(w, err.Error(), http.StatusUnprocessableEntity)
+               return
+       }
+
+       // Name is required.
+       if p.Metadata.Name == "" {
+               http.Error(w, "Missing name in POST request", http.StatusBadRequest)
+               return
+       }
+
+       err = validateNetworkInputs(p)
+       if err != nil {
+               http.Error(w, err.Error(), http.StatusBadRequest)
+               return
+       }
+
+       ret, err := h.client.CreateNetwork(p, clusterProvider, cluster, false)
+       if err != nil {
+               http.Error(w, err.Error(), http.StatusInternalServerError)
+               return
+       }
+
+       w.Header().Set("Content-Type", "application/json")
+       w.WriteHeader(http.StatusCreated)
+       err = json.NewEncoder(w).Encode(ret)
+       if err != nil {
+               http.Error(w, err.Error(), http.StatusInternalServerError)
+               return
+       }
+}
+
+// Put handles creation/update of the Network entry in the database
+func (h networkHandler) putNetworkHandler(w http.ResponseWriter, r *http.Request) {
+       var p moduleLib.Network
+       vars := mux.Vars(r)
+       clusterProvider := vars["provider-name"]
+       cluster := vars["cluster-name"]
+       name := vars["name"]
+
+       err := json.NewDecoder(r.Body).Decode(&p)
+
+       switch {
+       case err == io.EOF:
+               http.Error(w, "Empty body", http.StatusBadRequest)
+               return
+       case err != nil:
+               http.Error(w, err.Error(), http.StatusUnprocessableEntity)
+               return
+       }
+
+       // Name is required.
+       if p.Metadata.Name == "" {
+               http.Error(w, "Missing name in PUT request", http.StatusBadRequest)
+               return
+       }
+
+       // Name in URL should match name in body
+       if p.Metadata.Name != name {
+               fmt.Printf("bodyname = %v, name= %v\n", p.Metadata.Name, name)
+               http.Error(w, "Mismatched name in PUT request", http.StatusBadRequest)
+               return
+       }
+
+       err = validateNetworkInputs(p)
+       if err != nil {
+               http.Error(w, err.Error(), http.StatusBadRequest)
+               return
+       }
+
+       ret, err := h.client.CreateNetwork(p, clusterProvider, cluster, true)
+       if err != nil {
+               http.Error(w, err.Error(), http.StatusInternalServerError)
+               return
+       }
+
+       w.Header().Set("Content-Type", "application/json")
+       w.WriteHeader(http.StatusCreated)
+       err = json.NewEncoder(w).Encode(ret)
+       if err != nil {
+               http.Error(w, err.Error(), http.StatusInternalServerError)
+               return
+       }
+}
+
+// Get handles GET operations on a particular Network Name
+// Returns a Network
+func (h networkHandler) getNetworkHandler(w http.ResponseWriter, r *http.Request) {
+       vars := mux.Vars(r)
+       clusterProvider := vars["provider-name"]
+       cluster := vars["cluster-name"]
+       name := vars["name"]
+       var ret interface{}
+       var err error
+
+       if len(name) == 0 {
+               ret, err = h.client.GetNetworks(clusterProvider, cluster)
+               if err != nil {
+                       http.Error(w, err.Error(), http.StatusInternalServerError)
+                       return
+               }
+       } else {
+               ret, err = h.client.GetNetwork(name, clusterProvider, cluster)
+               if err != nil {
+                       http.Error(w, err.Error(), http.StatusInternalServerError)
+                       return
+               }
+       }
+
+       w.Header().Set("Content-Type", "application/json")
+       w.WriteHeader(http.StatusOK)
+       err = json.NewEncoder(w).Encode(ret)
+       if err != nil {
+               http.Error(w, err.Error(), http.StatusInternalServerError)
+               return
+       }
+}
+
+// Delete handles DELETE operations on a particular Network  Name
+func (h networkHandler) deleteNetworkHandler(w http.ResponseWriter, r *http.Request) {
+       vars := mux.Vars(r)
+       clusterProvider := vars["provider-name"]
+       cluster := vars["cluster-name"]
+       name := vars["name"]
+
+       err := h.client.DeleteNetwork(name, clusterProvider, cluster)
+       if err != nil {
+               http.Error(w, err.Error(), http.StatusInternalServerError)
+               return
+       }
+
+       w.WriteHeader(http.StatusNoContent)
+}
diff --git a/src/ncm/api/providernethandler.go b/src/ncm/api/providernethandler.go
new file mode 100644 (file)
index 0000000..b38a16c
--- /dev/null
@@ -0,0 +1,268 @@
+/*
+ * Copyright 2020 Intel Corporation, Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package api
+
+import (
+       "encoding/json"
+       "fmt"
+       "io"
+       "net/http"
+       "strings"
+
+       moduleLib "github.com/onap/multicloud-k8s/src/ncm/pkg/module"
+       "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/validation"
+       pkgerrors "github.com/pkg/errors"
+
+       "github.com/gorilla/mux"
+)
+
+// Used to store backend implementations objects
+// Also simplifies mocking for unit testing purposes
+type providernetHandler struct {
+       // Interface that implements Cluster operations
+       // We will set this variable with a mock interface for testing
+       client moduleLib.ProviderNetManager
+}
+
+// Check for valid format of input parameters
+func validateProviderNetInputs(p moduleLib.ProviderNet) error {
+       // validate name
+       errs := validation.IsValidName(p.Metadata.Name)
+       if len(errs) > 0 {
+               return pkgerrors.Errorf("Invalid provider network name=[%v], errors: %v", p.Metadata.Name, errs)
+       }
+
+       // validate cni type
+       found := false
+       for _, val := range moduleLib.CNI_TYPES {
+               if p.Spec.CniType == val {
+                       found = true
+                       break
+               }
+       }
+       if !found {
+               return pkgerrors.Errorf("Invalid cni type: %v", p.Spec.CniType)
+       }
+
+       // validate the provider network type
+       found = false
+       for _, val := range moduleLib.PROVIDER_NET_TYPES {
+               if strings.ToUpper(p.Spec.ProviderNetType) == val {
+                       found = true
+                       break
+               }
+       }
+       if !found {
+               return pkgerrors.Errorf("Invalid provider network type: %v", p.Spec.ProviderNetType)
+       }
+
+       // validate the subnets
+       subnets := p.Spec.Ipv4Subnets
+       for _, subnet := range subnets {
+               err := moduleLib.ValidateSubnet(subnet)
+               if err != nil {
+                       return pkgerrors.Wrap(err, "invalid subnet")
+               }
+       }
+
+       // validate the VLAN ID
+       errs = validation.IsValidNumber(p.Spec.Vlan.VlanId, 0, 4095)
+       if len(errs) > 0 {
+               return pkgerrors.Errorf("Invalid VlAN ID %v - error: %v", p.Spec.Vlan.VlanId, errs)
+       }
+
+       // validate the VLAN Node Selector value
+       expectLabels := false
+       found = false
+       for _, val := range moduleLib.VLAN_NODE_SELECTORS {
+               if strings.ToLower(p.Spec.Vlan.VlanNodeSelector) == val {
+                       found = true
+                       if val == moduleLib.VLAN_NODE_SPECIFIC {
+                               expectLabels = true
+                       }
+                       break
+               }
+       }
+       if !found {
+               return pkgerrors.Errorf("Invalid VlAN Node Selector %v", p.Spec.Vlan.VlanNodeSelector)
+       }
+
+       // validate the node label list
+       gotLabels := false
+       for _, label := range p.Spec.Vlan.NodeLabelList {
+               errs = validation.IsValidLabel(label)
+               if len(errs) > 0 {
+                       return pkgerrors.Errorf("Invalid Label=%v - errors: %v", label, errs)
+               }
+               gotLabels = true
+       }
+
+       // Need at least one label if node selector value was "specific"
+       // (if selector is "any" - don't care if labels were supplied or not
+       if expectLabels && !gotLabels {
+               return pkgerrors.Errorf("Node Labels required for VlAN node selector \"%v\"", moduleLib.VLAN_NODE_SPECIFIC)
+       }
+
+       return nil
+}
+
+// Create handles creation of the ProviderNet entry in the database
+func (h providernetHandler) createProviderNetHandler(w http.ResponseWriter, r *http.Request) {
+       var p moduleLib.ProviderNet
+       vars := mux.Vars(r)
+       clusterProvider := vars["provider-name"]
+       cluster := vars["cluster-name"]
+
+       err := json.NewDecoder(r.Body).Decode(&p)
+
+       switch {
+       case err == io.EOF:
+               http.Error(w, "Empty body", http.StatusBadRequest)
+               return
+       case err != nil:
+               http.Error(w, err.Error(), http.StatusUnprocessableEntity)
+               return
+       }
+
+       // Name is required.
+       if p.Metadata.Name == "" {
+               http.Error(w, "Missing name in POST request", http.StatusBadRequest)
+               return
+       }
+
+       err = validateProviderNetInputs(p)
+       if err != nil {
+               http.Error(w, err.Error(), http.StatusBadRequest)
+               return
+       }
+
+       ret, err := h.client.CreateProviderNet(p, clusterProvider, cluster, false)
+       if err != nil {
+               http.Error(w, err.Error(), http.StatusInternalServerError)
+               return
+       }
+
+       w.Header().Set("Content-Type", "application/json")
+       w.WriteHeader(http.StatusCreated)
+       err = json.NewEncoder(w).Encode(ret)
+       if err != nil {
+               http.Error(w, err.Error(), http.StatusInternalServerError)
+               return
+       }
+}
+
+// Put handles creation/update of the ProviderNet entry in the database
+func (h providernetHandler) putProviderNetHandler(w http.ResponseWriter, r *http.Request) {
+       var p moduleLib.ProviderNet
+       vars := mux.Vars(r)
+       clusterProvider := vars["provider-name"]
+       cluster := vars["cluster-name"]
+       name := vars["name"]
+
+       err := json.NewDecoder(r.Body).Decode(&p)
+
+       switch {
+       case err == io.EOF:
+               http.Error(w, "Empty body", http.StatusBadRequest)
+               return
+       case err != nil:
+               http.Error(w, err.Error(), http.StatusUnprocessableEntity)
+               return
+       }
+
+       // Name is required.
+       if p.Metadata.Name == "" {
+               http.Error(w, "Missing name in PUT request", http.StatusBadRequest)
+               return
+       }
+
+       // Name in URL should match name in body
+       if p.Metadata.Name != name {
+               fmt.Printf("bodyname = %v, name= %v\n", p.Metadata.Name, name)
+               http.Error(w, "Mismatched name in PUT request", http.StatusBadRequest)
+               return
+       }
+
+       err = validateProviderNetInputs(p)
+       if err != nil {
+               http.Error(w, err.Error(), http.StatusBadRequest)
+               return
+       }
+
+       ret, err := h.client.CreateProviderNet(p, clusterProvider, cluster, true)
+       if err != nil {
+               http.Error(w, err.Error(), http.StatusInternalServerError)
+               return
+       }
+
+       w.Header().Set("Content-Type", "application/json")
+       w.WriteHeader(http.StatusCreated)
+       err = json.NewEncoder(w).Encode(ret)
+       if err != nil {
+               http.Error(w, err.Error(), http.StatusInternalServerError)
+               return
+       }
+}
+
+// Get handles GET operations on a particular ProviderNet Name
+// Returns a ProviderNet
+func (h providernetHandler) getProviderNetHandler(w http.ResponseWriter, r *http.Request) {
+       vars := mux.Vars(r)
+       clusterProvider := vars["provider-name"]
+       cluster := vars["cluster-name"]
+       name := vars["name"]
+       var ret interface{}
+       var err error
+
+       if len(name) == 0 {
+               ret, err = h.client.GetProviderNets(clusterProvider, cluster)
+               if err != nil {
+                       http.Error(w, err.Error(), http.StatusInternalServerError)
+                       return
+               }
+       } else {
+               ret, err = h.client.GetProviderNet(name, clusterProvider, cluster)
+               if err != nil {
+                       http.Error(w, err.Error(), http.StatusInternalServerError)
+                       return
+               }
+       }
+
+       w.Header().Set("Content-Type", "application/json")
+       w.WriteHeader(http.StatusOK)
+       err = json.NewEncoder(w).Encode(ret)
+       if err != nil {
+               http.Error(w, err.Error(), http.StatusInternalServerError)
+               return
+       }
+}
+
+// Delete handles DELETE operations on a particular ProviderNet  Name
+func (h providernetHandler) deleteProviderNetHandler(w http.ResponseWriter, r *http.Request) {
+       vars := mux.Vars(r)
+       clusterProvider := vars["provider-name"]
+       cluster := vars["cluster-name"]
+       name := vars["name"]
+
+       err := h.client.DeleteProviderNet(name, clusterProvider, cluster)
+       if err != nil {
+               http.Error(w, err.Error(), http.StatusInternalServerError)
+               return
+       }
+
+       w.WriteHeader(http.StatusNoContent)
+}
index c9ddad6..e3260b7 100644 (file)
@@ -23,14 +23,6 @@ import (
 )
 
 // ClusterProvider contains the parameters needed for ClusterProviders
-// It implements the interface for managing the ClusterProviders
-type Metadata struct {
-       Name        string `json:"name"`
-       Description string `json:"description"`
-       UserData1   string `json:"userData1"`
-       UserData2   string `json:"userData2"`
-}
-
 type ClusterProvider struct {
        Metadata Metadata `json:"metadata"`
 }
@@ -105,18 +97,18 @@ type ClusterManager interface {
 // ClusterClient implements the Manager
 // It will also be used to maintain some localized state
 type ClusterClient struct {
-       storeName  string
-       tagMeta    string
-       tagContent string
+       db ClientDbInfo
 }
 
 // NewClusterClient returns an instance of the ClusterClient
 // which implements the Manager
 func NewClusterClient() *ClusterClient {
        return &ClusterClient{
-               storeName:  "cluster",
-               tagMeta:    "clustermetadata",
-               tagContent: "clustercontent",
+               db: ClientDbInfo{
+                       storeName:  "cluster",
+                       tagMeta:    "clustermetadata",
+                       tagContent: "clustercontent",
+               },
        }
 }
 
@@ -134,7 +126,7 @@ func (v *ClusterClient) CreateClusterProvider(p ClusterProvider) (ClusterProvide
                return ClusterProvider{}, pkgerrors.New("ClusterProvider already exists")
        }
 
-       err = db.DBconn.Insert(v.storeName, key, nil, v.tagMeta, p)
+       err = db.DBconn.Insert(v.db.storeName, key, nil, v.db.tagMeta, p)
        if err != nil {
                return ClusterProvider{}, pkgerrors.Wrap(err, "Creating DB Entry")
        }
@@ -150,7 +142,7 @@ func (v *ClusterClient) GetClusterProvider(name string) (ClusterProvider, error)
                ClusterProviderName: name,
        }
 
-       value, err := db.DBconn.Find(v.storeName, key, v.tagMeta)
+       value, err := db.DBconn.Find(v.db.storeName, key, v.db.tagMeta)
        if err != nil {
                return ClusterProvider{}, pkgerrors.Wrap(err, "Get ClusterProvider")
        }
@@ -160,7 +152,7 @@ func (v *ClusterClient) GetClusterProvider(name string) (ClusterProvider, error)
                cp := ClusterProvider{}
                err = db.DBconn.Unmarshal(value[0], &cp)
                if err != nil {
-                       return ClusterProvider{}, pkgerrors.Wrap(err, "Unmarshaling Value")
+                       return ClusterProvider{}, pkgerrors.Wrap(err, "Unmarshalling Value")
                }
                return cp, nil
        }
@@ -177,7 +169,7 @@ func (v *ClusterClient) GetClusterProviders() ([]ClusterProvider, error) {
        }
 
        var resp []ClusterProvider
-       values, err := db.DBconn.Find(v.storeName, key, v.tagMeta)
+       values, err := db.DBconn.Find(v.db.storeName, key, v.db.tagMeta)
        if err != nil {
                return []ClusterProvider{}, pkgerrors.Wrap(err, "Get ClusterProviders")
        }
@@ -186,7 +178,7 @@ func (v *ClusterClient) GetClusterProviders() ([]ClusterProvider, error) {
                cp := ClusterProvider{}
                err = db.DBconn.Unmarshal(value, &cp)
                if err != nil {
-                       return []ClusterProvider{}, pkgerrors.Wrap(err, "Unmarshaling Value")
+                       return []ClusterProvider{}, pkgerrors.Wrap(err, "Unmarshalling Value")
                }
                resp = append(resp, cp)
        }
@@ -202,7 +194,7 @@ func (v *ClusterClient) DeleteClusterProvider(name string) error {
                ClusterProviderName: name,
        }
 
-       err := db.DBconn.Remove(v.storeName, key)
+       err := db.DBconn.Remove(v.db.storeName, key)
        if err != nil {
                return pkgerrors.Wrap(err, "Delete ClusterProvider Entry;")
        }
@@ -231,11 +223,11 @@ func (v *ClusterClient) CreateCluster(provider string, p Cluster, q ClusterConte
                return Cluster{}, pkgerrors.New("Cluster already exists")
        }
 
-       err = db.DBconn.Insert(v.storeName, key, nil, v.tagMeta, p)
+       err = db.DBconn.Insert(v.db.storeName, key, nil, v.db.tagMeta, p)
        if err != nil {
                return Cluster{}, pkgerrors.Wrap(err, "Creating DB Entry")
        }
-       err = db.DBconn.Insert(v.storeName, key, nil, v.tagContent, q)
+       err = db.DBconn.Insert(v.db.storeName, key, nil, v.db.tagContent, q)
        if err != nil {
                return Cluster{}, pkgerrors.Wrap(err, "Creating DB Entry")
        }
@@ -251,7 +243,7 @@ func (v *ClusterClient) GetCluster(provider, name string) (Cluster, error) {
                ClusterName:         name,
        }
 
-       value, err := db.DBconn.Find(v.storeName, key, v.tagMeta)
+       value, err := db.DBconn.Find(v.db.storeName, key, v.db.tagMeta)
        if err != nil {
                return Cluster{}, pkgerrors.Wrap(err, "Get Cluster")
        }
@@ -261,7 +253,7 @@ func (v *ClusterClient) GetCluster(provider, name string) (Cluster, error) {
                cl := Cluster{}
                err = db.DBconn.Unmarshal(value[0], &cl)
                if err != nil {
-                       return Cluster{}, pkgerrors.Wrap(err, "Unmarshaling Value")
+                       return Cluster{}, pkgerrors.Wrap(err, "Unmarshalling Value")
                }
                return cl, nil
        }
@@ -277,7 +269,7 @@ func (v *ClusterClient) GetClusterContent(provider, name string) (ClusterContent
                ClusterName:         name,
        }
 
-       value, err := db.DBconn.Find(v.storeName, key, v.tagContent)
+       value, err := db.DBconn.Find(v.db.storeName, key, v.db.tagContent)
        if err != nil {
                return ClusterContent{}, pkgerrors.Wrap(err, "Get Cluster Content")
        }
@@ -287,7 +279,7 @@ func (v *ClusterClient) GetClusterContent(provider, name string) (ClusterContent
                cc := ClusterContent{}
                err = db.DBconn.Unmarshal(value[0], &cc)
                if err != nil {
-                       return ClusterContent{}, pkgerrors.Wrap(err, "Unmarshaling Value")
+                       return ClusterContent{}, pkgerrors.Wrap(err, "Unmarshalling Value")
                }
                return cc, nil
        }
@@ -303,7 +295,7 @@ func (v *ClusterClient) GetClusters(provider string) ([]Cluster, error) {
                ClusterName:         "",
        }
 
-       values, err := db.DBconn.Find(v.storeName, key, v.tagMeta)
+       values, err := db.DBconn.Find(v.db.storeName, key, v.db.tagMeta)
        if err != nil {
                return []Cluster{}, pkgerrors.Wrap(err, "Get Clusters")
        }
@@ -314,7 +306,7 @@ func (v *ClusterClient) GetClusters(provider string) ([]Cluster, error) {
                cp := Cluster{}
                err = db.DBconn.Unmarshal(value, &cp)
                if err != nil {
-                       return []Cluster{}, pkgerrors.Wrap(err, "Unmarshaling Value")
+                       return []Cluster{}, pkgerrors.Wrap(err, "Unmarshalling Value")
                }
                resp = append(resp, cp)
        }
@@ -330,7 +322,7 @@ func (v *ClusterClient) DeleteCluster(provider, name string) error {
                ClusterName:         name,
        }
 
-       err := db.DBconn.Remove(v.storeName, key)
+       err := db.DBconn.Remove(v.db.storeName, key)
        if err != nil {
                return pkgerrors.Wrap(err, "Delete Cluster Entry;")
        }
@@ -359,7 +351,7 @@ func (v *ClusterClient) CreateClusterLabel(provider string, cluster string, p Cl
                return ClusterLabel{}, pkgerrors.New("Cluster Label already exists")
        }
 
-       err = db.DBconn.Insert(v.storeName, key, nil, v.tagMeta, p)
+       err = db.DBconn.Insert(v.db.storeName, key, nil, v.db.tagMeta, p)
        if err != nil {
                return ClusterLabel{}, pkgerrors.Wrap(err, "Creating DB Entry")
        }
@@ -376,7 +368,7 @@ func (v *ClusterClient) GetClusterLabel(provider, cluster, label string) (Cluste
                ClusterLabelName:    label,
        }
 
-       value, err := db.DBconn.Find(v.storeName, key, v.tagMeta)
+       value, err := db.DBconn.Find(v.db.storeName, key, v.db.tagMeta)
        if err != nil {
                return ClusterLabel{}, pkgerrors.Wrap(err, "Get Cluster")
        }
@@ -386,7 +378,7 @@ func (v *ClusterClient) GetClusterLabel(provider, cluster, label string) (Cluste
                cl := ClusterLabel{}
                err = db.DBconn.Unmarshal(value[0], &cl)
                if err != nil {
-                       return ClusterLabel{}, pkgerrors.Wrap(err, "Unmarshaling Value")
+                       return ClusterLabel{}, pkgerrors.Wrap(err, "Unmarshalling Value")
                }
                return cl, nil
        }
@@ -403,7 +395,7 @@ func (v *ClusterClient) GetClusterLabels(provider, cluster string) ([]ClusterLab
                ClusterLabelName:    "",
        }
 
-       values, err := db.DBconn.Find(v.storeName, key, v.tagMeta)
+       values, err := db.DBconn.Find(v.db.storeName, key, v.db.tagMeta)
        if err != nil {
                return []ClusterLabel{}, pkgerrors.Wrap(err, "Get Cluster Labels")
        }
@@ -414,7 +406,7 @@ func (v *ClusterClient) GetClusterLabels(provider, cluster string) ([]ClusterLab
                cp := ClusterLabel{}
                err = db.DBconn.Unmarshal(value, &cp)
                if err != nil {
-                       return []ClusterLabel{}, pkgerrors.Wrap(err, "Unmarshaling Value")
+                       return []ClusterLabel{}, pkgerrors.Wrap(err, "Unmarshalling Value")
                }
                resp = append(resp, cp)
        }
@@ -431,7 +423,7 @@ func (v *ClusterClient) DeleteClusterLabel(provider, cluster, label string) erro
                ClusterLabelName:    label,
        }
 
-       err := db.DBconn.Remove(v.storeName, key)
+       err := db.DBconn.Remove(v.db.storeName, key)
        if err != nil {
                return pkgerrors.Wrap(err, "Delete ClusterLabel Entry;")
        }
@@ -459,7 +451,7 @@ func (v *ClusterClient) CreateClusterKvPairs(provider string, cluster string, p
                return ClusterKvPairs{}, pkgerrors.New("Cluster KV Pair already exists")
        }
 
-       err = db.DBconn.Insert(v.storeName, key, nil, v.tagMeta, p)
+       err = db.DBconn.Insert(v.db.storeName, key, nil, v.db.tagMeta, p)
        if err != nil {
                return ClusterKvPairs{}, pkgerrors.Wrap(err, "Creating DB Entry")
        }
@@ -476,7 +468,7 @@ func (v *ClusterClient) GetClusterKvPairs(provider, cluster, kvpair string) (Clu
                ClusterKvPairsName:  kvpair,
        }
 
-       value, err := db.DBconn.Find(v.storeName, key, v.tagMeta)
+       value, err := db.DBconn.Find(v.db.storeName, key, v.db.tagMeta)
        if err != nil {
                return ClusterKvPairs{}, pkgerrors.Wrap(err, "Get Cluster")
        }
@@ -486,7 +478,7 @@ func (v *ClusterClient) GetClusterKvPairs(provider, cluster, kvpair string) (Clu
                ckvp := ClusterKvPairs{}
                err = db.DBconn.Unmarshal(value[0], &ckvp)
                if err != nil {
-                       return ClusterKvPairs{}, pkgerrors.Wrap(err, "Unmarshaling Value")
+                       return ClusterKvPairs{}, pkgerrors.Wrap(err, "Unmarshalling Value")
                }
                return ckvp, nil
        }
@@ -503,7 +495,7 @@ func (v *ClusterClient) GetAllClusterKvPairs(provider, cluster string) ([]Cluste
                ClusterKvPairsName:  "",
        }
 
-       values, err := db.DBconn.Find(v.storeName, key, v.tagMeta)
+       values, err := db.DBconn.Find(v.db.storeName, key, v.db.tagMeta)
        if err != nil {
                return []ClusterKvPairs{}, pkgerrors.Wrap(err, "Get Cluster KV Pairs")
        }
@@ -514,7 +506,7 @@ func (v *ClusterClient) GetAllClusterKvPairs(provider, cluster string) ([]Cluste
                cp := ClusterKvPairs{}
                err = db.DBconn.Unmarshal(value, &cp)
                if err != nil {
-                       return []ClusterKvPairs{}, pkgerrors.Wrap(err, "Unmarshaling Value")
+                       return []ClusterKvPairs{}, pkgerrors.Wrap(err, "Unmarshalling Value")
                }
                resp = append(resp, cp)
        }
@@ -531,7 +523,7 @@ func (v *ClusterClient) DeleteClusterKvPairs(provider, cluster, kvpair string) e
                ClusterKvPairsName:  kvpair,
        }
 
-       err := db.DBconn.Remove(v.storeName, key)
+       err := db.DBconn.Remove(v.db.storeName, key)
        if err != nil {
                return pkgerrors.Wrap(err, "Delete ClusterKvPairs Entry;")
        }
index c1c2451..a995090 100644 (file)
@@ -18,7 +18,9 @@ package module
 
 // Client for using the services in the orchestrator
 type Client struct {
-       Cluster *ClusterClient
+       Cluster     *ClusterClient
+       Network     *NetworkClient
+       ProviderNet *ProviderNetClient
        // Add Clients for API's here
 }
 
@@ -26,6 +28,8 @@ type Client struct {
 func NewClient() *Client {
        c := &Client{}
        c.Cluster = NewClusterClient()
+       c.Network = NewNetworkClient()
+       c.ProviderNet = NewProviderNetClient()
        // Add Client API handlers here
        return c
 }
diff --git a/src/ncm/pkg/module/module_definitions.go b/src/ncm/pkg/module/module_definitions.go
new file mode 100644 (file)
index 0000000..1e83901
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2020 Intel Corporation, Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package module
+
+import (
+       "strings"
+
+       "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/validation"
+       pkgerrors "github.com/pkg/errors"
+)
+
+const VLAN_PROVIDER_NET_TYPE_VLAN string = "VLAN"
+const VLAN_PROVIDER_NET_TYPE_DIRECT string = "DIRECT"
+
+var PROVIDER_NET_TYPES = [...]string{VLAN_PROVIDER_NET_TYPE_VLAN, VLAN_PROVIDER_NET_TYPE_DIRECT}
+
+const CNI_TYPE_OVN4NFV string = "ovn4nfv"
+
+var CNI_TYPES = [...]string{CNI_TYPE_OVN4NFV}
+
+// It implements the interface for managing the ClusterProviders
+type Metadata struct {
+       Name        string `json:"name"`
+       Description string `json:"description"`
+       UserData1   string `json:"userData1"`
+       UserData2   string `json:"userData2"`
+}
+
+type ClientDbInfo struct {
+       storeName  string // name of the mongodb collection to use for client documents
+       tagMeta    string // attribute key name for the json data of a client document
+       tagContent string // attribute key name for the file data of a client document
+}
+
+type Ipv4Subnet struct {
+       Subnet  string `json:"subnet"` // CIDR notation, e.g. 172.16.33.0/24
+       Name    string `json:"name"`
+       Gateway string `json:"gateway"`    // IPv4 addre, e.g. 172.16.33.1/24
+       Exclude string `json:"excludeIps"` // space separated list of single IPs or ranges e.g. "172.16.33.2 172.16.33.5..172.16.33.10"
+}
+
+const VLAN_NODE_ANY = "any"
+const VLAN_NODE_SPECIFIC = "specific"
+
+var VLAN_NODE_SELECTORS = [...]string{VLAN_NODE_ANY, VLAN_NODE_SPECIFIC}
+
+type Vlan struct {
+       VlanId                int      `json:"vlanID"`
+       ProviderInterfaceName string   `json:"providerInterfaceName"`
+       LogicalInterfaceName  string   `json:"logicalInterfaceName"`
+       VlanNodeSelector      string   `json:"vlanNodeSelector"`
+       NodeLabelList         []string `json:"nodeLabelList"`
+}
+
+// Check for valid format of an Ipv4Subnet
+func ValidateSubnet(sub Ipv4Subnet) error {
+       // verify subnet is in valid cidr format
+       err := validation.IsIpv4Cidr(sub.Subnet)
+       if err != nil {
+               return pkgerrors.Wrap(err, "invalid subnet")
+       }
+
+       // just a size check on interface name - system dependent
+       errs := validation.IsValidName(sub.Name)
+       if len(errs) > 0 {
+               return pkgerrors.Errorf("Invalid subnet name=[%v], errors: %v", sub.Name, errs)
+       }
+
+       // verify gateway is in valid cidr format
+       if len(sub.Gateway) > 0 {
+               err = validation.IsIpv4Cidr(sub.Gateway)
+               if err != nil {
+                       return pkgerrors.Wrap(err, "invalid gateway")
+               }
+       }
+
+       // verify excludeIps is composed of space separated ipv4 addresses and
+       // ipv4 address ranges separated by '..'
+       for _, value := range strings.Fields(sub.Exclude) {
+               for _, ip := range strings.SplitN(value, "..", 2) {
+                       err = validation.IsIpv4(ip)
+                       if err != nil {
+                               return pkgerrors.Errorf("invalid ipv4 exclude list %v", sub.Exclude)
+                       }
+               }
+       }
+       return nil
+}
diff --git a/src/ncm/pkg/module/network.go b/src/ncm/pkg/module/network.go
new file mode 100644 (file)
index 0000000..2d4121e
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2020 Intel Corporation, Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package module
+
+import (
+       "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/db"
+
+       pkgerrors "github.com/pkg/errors"
+)
+
+// Network contains the parameters needed for dynamic networks
+type Network struct {
+       Metadata Metadata    `json:"metadata"`
+       Spec     NetworkSpec `json:"spec"`
+}
+
+type NetworkSpec struct {
+       CniType     string       `json:"cniType"`
+       Ipv4Subnets []Ipv4Subnet `json:"ipv4Subnets"`
+}
+
+// NetworkKey is the key structure that is used in the database
+type NetworkKey struct {
+       ClusterProviderName string `json:"provider"`
+       ClusterName         string `json:"cluster"`
+       NetworkName         string `json:"network"`
+}
+
+// Manager is an interface exposing the Network functionality
+type NetworkManager interface {
+       CreateNetwork(pr Network, clusterProvider, cluster string, exists bool) (Network, error)
+       GetNetwork(name, clusterProvider, cluster string) (Network, error)
+       GetNetworks(clusterProvider, cluster string) ([]Network, error)
+       DeleteNetwork(name, clusterProvider, cluster string) error
+}
+
+// NetworkClient implements the Manager
+// It will also be used to maintain some localized state
+type NetworkClient struct {
+       db ClientDbInfo
+}
+
+// NewNetworkClient returns an instance of the NetworkClient
+// which implements the Manager
+func NewNetworkClient() *NetworkClient {
+       return &NetworkClient{
+               db: ClientDbInfo{
+                       storeName: "cluster",
+                       tagMeta:   "networkmetadata",
+               },
+       }
+}
+
+// CreateNetwork - create a new Network
+func (v *NetworkClient) CreateNetwork(p Network, clusterProvider, cluster string, exists bool) (Network, error) {
+
+       //Construct key and tag to select the entry
+       key := NetworkKey{
+               ClusterProviderName: clusterProvider,
+               ClusterName:         cluster,
+               NetworkName:         p.Metadata.Name,
+       }
+
+       //Check if cluster exists
+       _, err := NewClusterClient().GetCluster(clusterProvider, cluster)
+       if err != nil {
+               return Network{}, pkgerrors.New("Unable to find the cluster")
+       }
+
+       //Check if this Network already exists
+       _, err = v.GetNetwork(p.Metadata.Name, clusterProvider, cluster)
+       if err == nil && !exists {
+               return Network{}, pkgerrors.New("Network already exists")
+       }
+
+       err = db.DBconn.Insert(v.db.storeName, key, nil, v.db.tagMeta, p)
+       if err != nil {
+               return Network{}, pkgerrors.Wrap(err, "Creating DB Entry")
+       }
+
+       return p, nil
+}
+
+// GetNetwork returns the Network for corresponding name
+func (v *NetworkClient) GetNetwork(name, clusterProvider, cluster string) (Network, error) {
+
+       //Construct key and tag to select the entry
+       key := NetworkKey{
+               ClusterProviderName: clusterProvider,
+               ClusterName:         cluster,
+               NetworkName:         name,
+       }
+
+       value, err := db.DBconn.Find(v.db.storeName, key, v.db.tagMeta)
+       if err != nil {
+               return Network{}, pkgerrors.Wrap(err, "Get Network")
+       }
+
+       //value is a byte array
+       if value != nil {
+               cp := Network{}
+               err = db.DBconn.Unmarshal(value[0], &cp)
+               if err != nil {
+                       return Network{}, pkgerrors.Wrap(err, "Unmarshalling Value")
+               }
+               return cp, nil
+       }
+
+       return Network{}, pkgerrors.New("Error getting Network")
+}
+
+// GetNetworkList returns all of the Network for corresponding name
+func (v *NetworkClient) GetNetworks(clusterProvider, cluster string) ([]Network, error) {
+
+       //Construct key and tag to select the entry
+       key := NetworkKey{
+               ClusterProviderName: clusterProvider,
+               ClusterName:         cluster,
+               NetworkName:         "",
+       }
+
+       var resp []Network
+       values, err := db.DBconn.Find(v.db.storeName, key, v.db.tagMeta)
+       if err != nil {
+               return []Network{}, pkgerrors.Wrap(err, "Get Networks")
+       }
+
+       for _, value := range values {
+               cp := Network{}
+               err = db.DBconn.Unmarshal(value, &cp)
+               if err != nil {
+                       return []Network{}, pkgerrors.Wrap(err, "Unmarshalling Value")
+               }
+               resp = append(resp, cp)
+       }
+
+       return resp, nil
+}
+
+// Delete the  Network from database
+func (v *NetworkClient) DeleteNetwork(name, clusterProvider, cluster string) error {
+
+       //Construct key and tag to select the entry
+       key := NetworkKey{
+               ClusterProviderName: clusterProvider,
+               ClusterName:         cluster,
+               NetworkName:         name,
+       }
+
+       err := db.DBconn.Remove(v.db.storeName, key)
+       if err != nil {
+               return pkgerrors.Wrap(err, "Delete Network Entry;")
+       }
+
+       return nil
+}
diff --git a/src/ncm/pkg/module/providernet.go b/src/ncm/pkg/module/providernet.go
new file mode 100644 (file)
index 0000000..5e2c034
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2020 Intel Corporation, Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package module
+
+import (
+       "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/db"
+
+       pkgerrors "github.com/pkg/errors"
+)
+
+// ProviderNet contains the parameters needed for dynamic networks
+type ProviderNet struct {
+       Metadata Metadata        `json:"metadata"`
+       Spec     ProviderNetSpec `json:"spec"`
+}
+
+type ProviderNetSpec struct {
+       CniType         string       `json:"cniType"`
+       Ipv4Subnets     []Ipv4Subnet `json:"ipv4Subnets"`
+       ProviderNetType string       `json:"providerNetType"`
+       Vlan            Vlan         `json:"vlan"`
+}
+
+// ProviderNetKey is the key structure that is used in the database
+type ProviderNetKey struct {
+       ClusterProviderName string `json:"provider"`
+       ClusterName         string `json:"cluster"`
+       ProviderNetName     string `json:"providernet"`
+}
+
+// Manager is an interface exposing the ProviderNet functionality
+type ProviderNetManager interface {
+       CreateProviderNet(pr ProviderNet, clusterProvider, cluster string, exists bool) (ProviderNet, error)
+       GetProviderNet(name, clusterProvider, cluster string) (ProviderNet, error)
+       GetProviderNets(clusterProvider, cluster string) ([]ProviderNet, error)
+       DeleteProviderNet(name, clusterProvider, cluster string) error
+}
+
+// ProviderNetClient implements the Manager
+// It will also be used to maintain some localized state
+type ProviderNetClient struct {
+       db ClientDbInfo
+}
+
+// NewProviderNetClient returns an instance of the ProviderNetClient
+// which implements the Manager
+func NewProviderNetClient() *ProviderNetClient {
+       return &ProviderNetClient{
+               db: ClientDbInfo{
+                       storeName: "cluster",
+                       tagMeta:   "networkmetadata",
+               },
+       }
+}
+
+// CreateProviderNet - create a new ProviderNet
+func (v *ProviderNetClient) CreateProviderNet(p ProviderNet, clusterProvider, cluster string, exists bool) (ProviderNet, error) {
+
+       //Construct key and tag to select the entry
+       key := ProviderNetKey{
+               ClusterProviderName: clusterProvider,
+               ClusterName:         cluster,
+               ProviderNetName:     p.Metadata.Name,
+       }
+
+       //Check if cluster exists
+       _, err := NewClusterClient().GetCluster(clusterProvider, cluster)
+       if err != nil {
+               return ProviderNet{}, pkgerrors.New("Unable to find the cluster")
+       }
+
+       //Check if this ProviderNet already exists
+       _, err = v.GetProviderNet(p.Metadata.Name, clusterProvider, cluster)
+       if err == nil && !exists {
+               return ProviderNet{}, pkgerrors.New("ProviderNet already exists")
+       }
+
+       err = db.DBconn.Insert(v.db.storeName, key, nil, v.db.tagMeta, p)
+       if err != nil {
+               return ProviderNet{}, pkgerrors.Wrap(err, "Creating DB Entry")
+       }
+
+       return p, nil
+}
+
+// GetProviderNet returns the ProviderNet for corresponding name
+func (v *ProviderNetClient) GetProviderNet(name, clusterProvider, cluster string) (ProviderNet, error) {
+
+       //Construct key and tag to select the entry
+       key := ProviderNetKey{
+               ClusterProviderName: clusterProvider,
+               ClusterName:         cluster,
+               ProviderNetName:     name,
+       }
+
+       value, err := db.DBconn.Find(v.db.storeName, key, v.db.tagMeta)
+       if err != nil {
+               return ProviderNet{}, pkgerrors.Wrap(err, "Get ProviderNet")
+       }
+
+       //value is a byte array
+       if value != nil {
+               cp := ProviderNet{}
+               err = db.DBconn.Unmarshal(value[0], &cp)
+               if err != nil {
+                       return ProviderNet{}, pkgerrors.Wrap(err, "Unmarshalling Value")
+               }
+               return cp, nil
+       }
+
+       return ProviderNet{}, pkgerrors.New("Error getting ProviderNet")
+}
+
+// GetProviderNetList returns all of the ProviderNet for corresponding name
+func (v *ProviderNetClient) GetProviderNets(clusterProvider, cluster string) ([]ProviderNet, error) {
+
+       //Construct key and tag to select the entry
+       key := ProviderNetKey{
+               ClusterProviderName: clusterProvider,
+               ClusterName:         cluster,
+               ProviderNetName:     "",
+       }
+
+       var resp []ProviderNet
+       values, err := db.DBconn.Find(v.db.storeName, key, v.db.tagMeta)
+       if err != nil {
+               return []ProviderNet{}, pkgerrors.Wrap(err, "Get ProviderNets")
+       }
+
+       for _, value := range values {
+               cp := ProviderNet{}
+               err = db.DBconn.Unmarshal(value, &cp)
+               if err != nil {
+                       return []ProviderNet{}, pkgerrors.Wrap(err, "Unmarshalling Value")
+               }
+               resp = append(resp, cp)
+       }
+
+       return resp, nil
+}
+
+// Delete the  ProviderNet from database
+func (v *ProviderNetClient) DeleteProviderNet(name, clusterProvider, cluster string) error {
+
+       //Construct key and tag to select the entry
+       key := ProviderNetKey{
+               ClusterProviderName: clusterProvider,
+               ClusterName:         cluster,
+               ProviderNetName:     name,
+       }
+
+       err := db.DBconn.Remove(v.db.storeName, key)
+       if err != nil {
+               return pkgerrors.Wrap(err, "Delete ProviderNet Entry;")
+       }
+
+       return nil
+}