diff options
Diffstat (limited to 'src/ncm/pkg')
-rw-r--r-- | src/ncm/pkg/cluster/cluster.go (renamed from src/ncm/pkg/module/cluster.go) | 312 | ||||
-rw-r--r-- | src/ncm/pkg/grpc/rsyncclient.go | 41 | ||||
-rw-r--r-- | src/ncm/pkg/module/module.go | 20 | ||||
-rw-r--r-- | src/ncm/pkg/module/types/module_definitions.go | 24 | ||||
-rw-r--r-- | src/ncm/pkg/networkintents/network.go (renamed from src/ncm/pkg/module/network.go) | 32 | ||||
-rw-r--r-- | src/ncm/pkg/networkintents/providernet.go (renamed from src/ncm/pkg/module/providernet.go) | 34 | ||||
-rw-r--r-- | src/ncm/pkg/networkintents/types/types.go | 90 | ||||
-rw-r--r-- | src/ncm/pkg/scheduler/scheduler.go | 220 |
8 files changed, 418 insertions, 355 deletions
diff --git a/src/ncm/pkg/module/cluster.go b/src/ncm/pkg/cluster/cluster.go index 5d1f577f..f656688c 100644 --- a/src/ncm/pkg/module/cluster.go +++ b/src/ncm/pkg/cluster/cluster.go @@ -14,31 +14,24 @@ * limitations under the License. */ -package module +package cluster import ( - "context" - "encoding/json" - "time" - - "github.com/onap/multicloud-k8s/src/ncm/pkg/grpc" + ncmtypes "github.com/onap/multicloud-k8s/src/ncm/pkg/module/types" appcontext "github.com/onap/multicloud-k8s/src/orchestrator/pkg/appcontext" "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/db" - log "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/logutils" - "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/rpc" - installpb "github.com/onap/multicloud-k8s/src/rsync/pkg/grpc/installapp" - "gopkg.in/yaml.v2" + mtypes "github.com/onap/multicloud-k8s/src/orchestrator/pkg/module/types" pkgerrors "github.com/pkg/errors" ) // ClusterProvider contains the parameters needed for ClusterProviders type ClusterProvider struct { - Metadata Metadata `json:"metadata"` + Metadata mtypes.Metadata `json:"metadata"` } type Cluster struct { - Metadata Metadata `json:"metadata"` + Metadata mtypes.Metadata `json:"metadata"` } type ClusterContent struct { @@ -50,8 +43,8 @@ type ClusterLabel struct { } type ClusterKvPairs struct { - Metadata Metadata `json:"metadata"` - Spec ClusterKvSpec `json:"spec"` + Metadata mtypes.Metadata `json:"metadata"` + Spec ClusterKvSpec `json:"spec"` } type ClusterKvSpec struct { @@ -106,8 +99,6 @@ type ClusterManager interface { GetClusters(provider string) ([]Cluster, error) GetClustersWithLabel(provider, label string) ([]string, error) DeleteCluster(provider, name string) error - ApplyNetworkIntents(provider, name string) error - TerminateNetworkIntents(provider, name string) error CreateClusterLabel(provider, cluster string, pr ClusterLabel) (ClusterLabel, error) GetClusterLabel(provider, cluster, label string) (ClusterLabel, error) GetClusterLabels(provider, cluster string) ([]ClusterLabel, error) @@ -121,18 +112,18 @@ type ClusterManager interface { // ClusterClient implements the Manager // It will also be used to maintain some localized state type ClusterClient struct { - db ClientDbInfo + db ncmtypes.ClientDbInfo } // NewClusterClient returns an instance of the ClusterClient // which implements the Manager func NewClusterClient() *ClusterClient { return &ClusterClient{ - db: ClientDbInfo{ - storeName: "cluster", - tagMeta: "clustermetadata", - tagContent: "clustercontent", - tagContext: "clustercontext", + db: ncmtypes.ClientDbInfo{ + StoreName: "cluster", + TagMeta: "clustermetadata", + TagContent: "clustercontent", + TagContext: "clustercontext", }, } } @@ -151,7 +142,7 @@ func (v *ClusterClient) CreateClusterProvider(p ClusterProvider) (ClusterProvide return ClusterProvider{}, pkgerrors.New("ClusterProvider already exists") } - err = db.DBconn.Insert(v.db.storeName, key, nil, v.db.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") } @@ -167,7 +158,7 @@ func (v *ClusterClient) GetClusterProvider(name string) (ClusterProvider, error) ClusterProviderName: name, } - value, err := db.DBconn.Find(v.db.storeName, key, v.db.tagMeta) + value, err := db.DBconn.Find(v.db.StoreName, key, v.db.TagMeta) if err != nil { return ClusterProvider{}, pkgerrors.Wrap(err, "Get ClusterProvider") } @@ -194,7 +185,7 @@ func (v *ClusterClient) GetClusterProviders() ([]ClusterProvider, error) { } var resp []ClusterProvider - values, err := db.DBconn.Find(v.db.storeName, key, v.db.tagMeta) + values, err := db.DBconn.Find(v.db.StoreName, key, v.db.TagMeta) if err != nil { return []ClusterProvider{}, pkgerrors.Wrap(err, "Get ClusterProviders") } @@ -219,7 +210,7 @@ func (v *ClusterClient) DeleteClusterProvider(name string) error { ClusterProviderName: name, } - err := db.DBconn.Remove(v.db.storeName, key) + err := db.DBconn.Remove(v.db.StoreName, key) if err != nil { return pkgerrors.Wrap(err, "Delete ClusterProvider Entry;") } @@ -248,11 +239,11 @@ func (v *ClusterClient) CreateCluster(provider string, p Cluster, q ClusterConte return Cluster{}, pkgerrors.New("Cluster already exists") } - err = db.DBconn.Insert(v.db.storeName, key, nil, v.db.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.db.storeName, key, nil, v.db.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") } @@ -268,7 +259,7 @@ func (v *ClusterClient) GetCluster(provider, name string) (Cluster, error) { ClusterName: name, } - value, err := db.DBconn.Find(v.db.storeName, key, v.db.tagMeta) + value, err := db.DBconn.Find(v.db.StoreName, key, v.db.TagMeta) if err != nil { return Cluster{}, pkgerrors.Wrap(err, "Get Cluster") } @@ -294,7 +285,7 @@ func (v *ClusterClient) GetClusterContent(provider, name string) (ClusterContent ClusterName: name, } - value, err := db.DBconn.Find(v.db.storeName, key, v.db.tagContent) + value, err := db.DBconn.Find(v.db.StoreName, key, v.db.TagContent) if err != nil { return ClusterContent{}, pkgerrors.Wrap(err, "Get Cluster Content") } @@ -320,7 +311,7 @@ func (v *ClusterClient) GetClusterContext(provider, name string) (appcontext.App ClusterName: name, } - value, err := db.DBconn.Find(v.db.storeName, key, v.db.tagContext) + value, err := db.DBconn.Find(v.db.StoreName, key, v.db.TagContext) if err != nil { return appcontext.AppContext{}, pkgerrors.Wrap(err, "Get Cluster Context") } @@ -347,7 +338,7 @@ func (v *ClusterClient) GetClusters(provider string) ([]Cluster, error) { ClusterName: "", } - values, err := db.DBconn.Find(v.db.storeName, key, v.db.tagMeta) + values, err := db.DBconn.Find(v.db.StoreName, key, v.db.TagMeta) if err != nil { return []Cluster{}, pkgerrors.Wrap(err, "Get Clusters") } @@ -375,7 +366,7 @@ func (v *ClusterClient) GetClustersWithLabel(provider, label string) ([]string, ClusterLabelName: label, } - values, err := db.DBconn.Find(v.db.storeName, key, "cluster") + values, err := db.DBconn.Find(v.db.StoreName, key, "cluster") if err != nil { return []string{}, pkgerrors.Wrap(err, "Get Clusters by label") } @@ -401,7 +392,7 @@ func (v *ClusterClient) DeleteCluster(provider, name string) error { return pkgerrors.Errorf("Cannot delete cluster until context is deleted: %v, %v", provider, name) } - err = db.DBconn.Remove(v.db.storeName, key) + err = db.DBconn.Remove(v.db.StoreName, key) if err != nil { return pkgerrors.Wrap(err, "Delete Cluster Entry;") } @@ -409,243 +400,6 @@ func (v *ClusterClient) DeleteCluster(provider, name string) error { return nil } -// Apply Network Intents associated with a cluster -func (v *ClusterClient) ApplyNetworkIntents(provider, name string) error { - - _, err := v.GetClusterContext(provider, name) - if err == nil { - return pkgerrors.Errorf("Cluster network intents have already been applied: %v, %v", provider, name) - } - - type resource struct { - name string - value string - } - - var resources []resource - - // Find all Network Intents for this cluster - networkIntents, err := NewNetworkClient().GetNetworks(provider, name) - if err != nil { - return pkgerrors.Wrap(err, "Error finding Network Intents") - } - for _, intent := range networkIntents { - var crNetwork = CrNetwork{ - ApiVersion: NETWORK_APIVERSION, - Kind: NETWORK_KIND, - } - crNetwork.Network = intent - // Produce the yaml CR document for each intent - y, err := yaml.Marshal(&crNetwork) - if err != nil { - log.Info("Error marshalling network intent to yaml", log.Fields{ - "error": err, - "intent": intent, - }) - continue - } - resources = append(resources, resource{ - name: intent.Metadata.Name + SEPARATOR + NETWORK_KIND, - value: string(y), - }) - } - - // Find all Provider Network Intents for this cluster - providerNetworkIntents, err := NewProviderNetClient().GetProviderNets(provider, name) - if err != nil { - return pkgerrors.Wrap(err, "Error finding Provider Network Intents") - } - for _, intent := range providerNetworkIntents { - var crProviderNet = CrProviderNet{ - ApiVersion: PROVIDER_NETWORK_APIVERSION, - Kind: PROVIDER_NETWORK_KIND, - } - crProviderNet.ProviderNet = intent - // Produce the yaml CR document for each intent - y, err := yaml.Marshal(&crProviderNet) - if err != nil { - log.Info("Error marshalling provider network intent to yaml", log.Fields{ - "error": err, - "intent": intent, - }) - continue - } - resources = append(resources, resource{ - name: intent.Metadata.Name + SEPARATOR + PROVIDER_NETWORK_KIND, - value: string(y), - }) - } - - if len(resources) == 0 { - return nil - } - - // Make an app context for the network intent resources - ac := appcontext.AppContext{} - ctxVal, err := ac.InitAppContext() - if err != nil { - return pkgerrors.Wrap(err, "Error creating AppContext") - } - handle, err := ac.CreateCompositeApp() - if err != nil { - return pkgerrors.Wrap(err, "Error creating AppContext CompositeApp") - } - - // Add an app (fixed value) to the app context - apphandle, err := ac.AddApp(handle, CONTEXT_CLUSTER_APP) - if err != nil { - cleanuperr := ac.DeleteCompositeApp() - if cleanuperr != nil { - log.Warn("Error cleaning AppContext CompositeApp create failure", log.Fields{ - "cluster-provider": provider, - "cluster": name, - }) - } - return pkgerrors.Wrap(err, "Error adding App to AppContext") - } - - // Add an app order instruction - appinstr := struct { - Apporder []string `json:"apporder"` - }{ - []string{CONTEXT_CLUSTER_APP}, - } - jinstr, _ := json.Marshal(appinstr) - - appdepinstr := struct { - Appdep map[string]string `json:"appdependency"` - }{ - map[string]string{CONTEXT_CLUSTER_APP: "go"}, - } - jdep, _ := json.Marshal(appdepinstr) - - _, err = ac.AddInstruction(handle, "app", "order", string(jinstr)) - _, err = ac.AddInstruction(handle, "app", "dependency", string(jdep)) - - // Add a cluster to the app - clusterhandle, err := ac.AddCluster(apphandle, provider+SEPARATOR+name) - if err != nil { - cleanuperr := ac.DeleteCompositeApp() - if cleanuperr != nil { - log.Warn("Error cleaning AppContext after add cluster failure", log.Fields{ - "cluster-provider": provider, - "cluster": name, - }) - } - return pkgerrors.Wrap(err, "Error adding Cluster to AppContext") - } - - // add the resources to the app context - - var orderinstr struct { - Resorder []string `json:"resorder"` - } - var depinstr struct { - Resdep map[string]string `json:"resdependency"` - } - resdep := make(map[string]string) - for _, resource := range resources { - orderinstr.Resorder = append(orderinstr.Resorder, resource.name) - resdep[resource.name] = "go" - _, err = ac.AddResource(clusterhandle, resource.name, resource.value) - if err != nil { - cleanuperr := ac.DeleteCompositeApp() - if cleanuperr != nil { - log.Warn("Error cleaning AppContext after add resource failure", log.Fields{ - "cluster-provider": provider, - "cluster": name, - "resource": resource.name, - }) - } - return pkgerrors.Wrap(err, "Error adding Resource to AppContext") - } - } - jresord, _ := json.Marshal(orderinstr) - depinstr.Resdep = resdep - jresdep, _ := json.Marshal(depinstr) - _, err = ac.AddInstruction(clusterhandle, "resource", "order", string(jresord)) - _, err = ac.AddInstruction(clusterhandle, "resource", "dependency", string(jresdep)) - - // save the context in the cluster db record - key := ClusterKey{ - ClusterProviderName: provider, - ClusterName: name, - } - err = db.DBconn.Insert(v.db.storeName, key, nil, v.db.tagContext, ctxVal) - if err != nil { - cleanuperr := ac.DeleteCompositeApp() - if cleanuperr != nil { - log.Warn("Error cleaning AppContext after DB insert failure", log.Fields{ - "cluster-provider": provider, - "cluster": name, - }) - } - return pkgerrors.Wrap(err, "Error adding AppContext to DB") - } - - // call resource synchronizer to instantiate the CRs in the cluster - conn := rpc.GetRpcConn(grpc.RsyncName) - if conn == nil { - grpc.InitRsyncClient() - conn = rpc.GetRpcConn(grpc.RsyncName) - } - - var rpcClient installpb.InstallappClient - var installRes *installpb.InstallAppResponse - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - - if conn != nil { - rpcClient = installpb.NewInstallappClient(conn) - installReq := new(installpb.InstallAppRequest) - installReq.AppContext = ctxVal.(string) - installRes, err = rpcClient.InstallApp(ctx, installReq) - if err == nil { - log.Info("Response from InstappApp GRPC call", log.Fields{ - "Succeeded": installRes.AppContextInstalled, - "Message": installRes.AppContextInstallMessage, - }) - } - } else { - return pkgerrors.Errorf("InstallApp Failed - Could not get InstallAppClient: %v", grpc.RsyncName) - } - - return nil -} - -// Terminate Network Intents associated with a cluster -func (v *ClusterClient) TerminateNetworkIntents(provider, name string) error { - context, err := v.GetClusterContext(provider, name) - if err != nil { - return pkgerrors.Wrapf(err, "Error finding AppContext for cluster: %v, %v", provider, name) - } - - // TODO: call resource synchronizer to terminate the CRs in the cluster - - // remove the app context - cleanuperr := context.DeleteCompositeApp() - if cleanuperr != nil { - log.Warn("Error deleted AppContext", log.Fields{ - "cluster-provider": provider, - "cluster": name, - }) - } - - // remove the app context field from the cluster db record - key := ClusterKey{ - ClusterProviderName: provider, - ClusterName: name, - } - err = db.DBconn.RemoveTag(v.db.storeName, key, v.db.tagContext) - if err != nil { - log.Warn("Error removing AppContext from Cluster document", log.Fields{ - "cluster-provider": provider, - "cluster": name, - }) - } - return nil -} - // CreateClusterLabel - create a new Cluster Label mongo document for a cluster-provider/cluster func (v *ClusterClient) CreateClusterLabel(provider string, cluster string, p ClusterLabel) (ClusterLabel, error) { //Construct key and tag to select the entry @@ -667,7 +421,7 @@ func (v *ClusterClient) CreateClusterLabel(provider string, cluster string, p Cl return ClusterLabel{}, pkgerrors.New("Cluster Label already exists") } - err = db.DBconn.Insert(v.db.storeName, key, nil, v.db.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") } @@ -684,7 +438,7 @@ func (v *ClusterClient) GetClusterLabel(provider, cluster, label string) (Cluste ClusterLabelName: label, } - value, err := db.DBconn.Find(v.db.storeName, key, v.db.tagMeta) + value, err := db.DBconn.Find(v.db.StoreName, key, v.db.TagMeta) if err != nil { return ClusterLabel{}, pkgerrors.Wrap(err, "Get Cluster") } @@ -711,7 +465,7 @@ func (v *ClusterClient) GetClusterLabels(provider, cluster string) ([]ClusterLab ClusterLabelName: "", } - values, err := db.DBconn.Find(v.db.storeName, key, v.db.tagMeta) + values, err := db.DBconn.Find(v.db.StoreName, key, v.db.TagMeta) if err != nil { return []ClusterLabel{}, pkgerrors.Wrap(err, "Get Cluster Labels") } @@ -739,7 +493,7 @@ func (v *ClusterClient) DeleteClusterLabel(provider, cluster, label string) erro ClusterLabelName: label, } - err := db.DBconn.Remove(v.db.storeName, key) + err := db.DBconn.Remove(v.db.StoreName, key) if err != nil { return pkgerrors.Wrap(err, "Delete ClusterLabel Entry;") } @@ -767,7 +521,7 @@ func (v *ClusterClient) CreateClusterKvPairs(provider string, cluster string, p return ClusterKvPairs{}, pkgerrors.New("Cluster KV Pair already exists") } - err = db.DBconn.Insert(v.db.storeName, key, nil, v.db.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") } @@ -784,7 +538,7 @@ func (v *ClusterClient) GetClusterKvPairs(provider, cluster, kvpair string) (Clu ClusterKvPairsName: kvpair, } - value, err := db.DBconn.Find(v.db.storeName, key, v.db.tagMeta) + value, err := db.DBconn.Find(v.db.StoreName, key, v.db.TagMeta) if err != nil { return ClusterKvPairs{}, pkgerrors.Wrap(err, "Get Cluster") } @@ -811,7 +565,7 @@ func (v *ClusterClient) GetAllClusterKvPairs(provider, cluster string) ([]Cluste ClusterKvPairsName: "", } - values, err := db.DBconn.Find(v.db.storeName, key, v.db.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") } @@ -839,7 +593,7 @@ func (v *ClusterClient) DeleteClusterKvPairs(provider, cluster, kvpair string) e ClusterKvPairsName: kvpair, } - err := db.DBconn.Remove(v.db.storeName, key) + err := db.DBconn.Remove(v.db.StoreName, key) if err != nil { return pkgerrors.Wrap(err, "Delete ClusterKvPairs Entry;") } diff --git a/src/ncm/pkg/grpc/rsyncclient.go b/src/ncm/pkg/grpc/rsyncclient.go deleted file mode 100644 index 5eb870a7..00000000 --- a/src/ncm/pkg/grpc/rsyncclient.go +++ /dev/null @@ -1,41 +0,0 @@ -/* -Copyright 2020 Intel Corporation. -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 grpc - -import ( - log "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/logutils" - "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/rpc" - controller "github.com/onap/multicloud-k8s/src/orchestrator/pkg/module/controller" -) - -const RsyncName = "rsync" - -// InitRsyncClient initializes connctions to the Resource Synchronizer serivice -func InitRsyncClient() bool { - client := controller.NewControllerClient() - - vals, _ := client.GetControllers() - found := false - for _, v := range vals { - if v.Metadata.Name == RsyncName { - log.Info("Initializing RPC connection to resource synchronizer", log.Fields{ - "Controller": v.Metadata.Name, - }) - rpc.UpdateRpcConn(v.Metadata.Name, v.Spec.Host, v.Spec.Port) - found = true - break - } - } - return found -} diff --git a/src/ncm/pkg/module/module.go b/src/ncm/pkg/module/module.go index e3ebcccc..10b241f6 100644 --- a/src/ncm/pkg/module/module.go +++ b/src/ncm/pkg/module/module.go @@ -16,20 +16,28 @@ package module +import ( + "github.com/onap/multicloud-k8s/src/ncm/pkg/cluster" + "github.com/onap/multicloud-k8s/src/ncm/pkg/networkintents" + "github.com/onap/multicloud-k8s/src/ncm/pkg/scheduler" +) + // Client for using the services in the ncm type Client struct { - Cluster *ClusterClient - Network *NetworkClient - ProviderNet *ProviderNetClient + Cluster *cluster.ClusterClient + Network *networkintents.NetworkClient + ProviderNet *networkintents.ProviderNetClient + Scheduler *scheduler.SchedulerClient // Add Clients for API's here } // NewClient creates a new client for using the services func NewClient() *Client { c := &Client{} - c.Cluster = NewClusterClient() - c.Network = NewNetworkClient() - c.ProviderNet = NewProviderNetClient() + c.Cluster = cluster.NewClusterClient() + c.Network = networkintents.NewNetworkClient() + c.ProviderNet = networkintents.NewProviderNetClient() + c.Scheduler = scheduler.NewSchedulerClient() // Add Client API handlers here return c } diff --git a/src/ncm/pkg/module/types/module_definitions.go b/src/ncm/pkg/module/types/module_definitions.go new file mode 100644 index 00000000..0dd657ac --- /dev/null +++ b/src/ncm/pkg/module/types/module_definitions.go @@ -0,0 +1,24 @@ +/* + * 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 types + +// TODO - should move to common module types location - e.g. in orchestrator +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 + TagContext string // attribute key name for context object in App Context +} diff --git a/src/ncm/pkg/module/network.go b/src/ncm/pkg/networkintents/network.go index e753905e..e8480e0f 100644 --- a/src/ncm/pkg/module/network.go +++ b/src/ncm/pkg/networkintents/network.go @@ -14,23 +14,27 @@ * limitations under the License. */ -package module +package networkintents import ( + clusterPkg "github.com/onap/multicloud-k8s/src/ncm/pkg/cluster" + ncmtypes "github.com/onap/multicloud-k8s/src/ncm/pkg/module/types" + nettypes "github.com/onap/multicloud-k8s/src/ncm/pkg/networkintents/types" "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/db" + mtypes "github.com/onap/multicloud-k8s/src/orchestrator/pkg/module/types" pkgerrors "github.com/pkg/errors" ) // Network contains the parameters needed for dynamic networks type Network struct { - Metadata Metadata `json:"metadata" yaml:"metadata"` - Spec NetworkSpec `json:"spec" yaml:"spec"` + Metadata mtypes.Metadata `json:"metadata" yaml:"metadata"` + Spec NetworkSpec `json:"spec" yaml:"spec"` } type NetworkSpec struct { - CniType string `json:"cniType" yaml:"cniType"` - Ipv4Subnets []Ipv4Subnet `json:"ipv4Subnets" yaml:"ipv4Subnets"` + CniType string `json:"cniType" yaml:"cniType"` + Ipv4Subnets []nettypes.Ipv4Subnet `json:"ipv4Subnets" yaml:"ipv4Subnets"` } // NetworkKey is the key structure that is used in the database @@ -61,16 +65,16 @@ type NetworkManager interface { // NetworkClient implements the Manager // It will also be used to maintain some localized state type NetworkClient struct { - db ClientDbInfo + db ncmtypes.ClientDbInfo } // NewNetworkClient returns an instance of the NetworkClient // which implements the Manager func NewNetworkClient() *NetworkClient { return &NetworkClient{ - db: ClientDbInfo{ - storeName: "cluster", - tagMeta: "networkmetadata", + db: ncmtypes.ClientDbInfo{ + StoreName: "cluster", + TagMeta: "networkmetadata", }, } } @@ -86,7 +90,7 @@ func (v *NetworkClient) CreateNetwork(p Network, clusterProvider, cluster string } //Check if cluster exists - _, err := NewClusterClient().GetCluster(clusterProvider, cluster) + _, err := clusterPkg.NewClusterClient().GetCluster(clusterProvider, cluster) if err != nil { return Network{}, pkgerrors.New("Unable to find the cluster") } @@ -97,7 +101,7 @@ func (v *NetworkClient) CreateNetwork(p Network, clusterProvider, cluster string return Network{}, pkgerrors.New("Network already exists") } - err = db.DBconn.Insert(v.db.storeName, key, nil, v.db.tagMeta, p) + err = db.DBconn.Insert(v.db.StoreName, key, nil, v.db.TagMeta, p) if err != nil { return Network{}, pkgerrors.Wrap(err, "Creating DB Entry") } @@ -115,7 +119,7 @@ func (v *NetworkClient) GetNetwork(name, clusterProvider, cluster string) (Netwo NetworkName: name, } - value, err := db.DBconn.Find(v.db.storeName, key, v.db.tagMeta) + value, err := db.DBconn.Find(v.db.StoreName, key, v.db.TagMeta) if err != nil { return Network{}, pkgerrors.Wrap(err, "Get Network") } @@ -144,7 +148,7 @@ func (v *NetworkClient) GetNetworks(clusterProvider, cluster string) ([]Network, } var resp []Network - values, err := db.DBconn.Find(v.db.storeName, key, v.db.tagMeta) + values, err := db.DBconn.Find(v.db.StoreName, key, v.db.TagMeta) if err != nil { return []Network{}, pkgerrors.Wrap(err, "Get Networks") } @@ -171,7 +175,7 @@ func (v *NetworkClient) DeleteNetwork(name, clusterProvider, cluster string) err NetworkName: name, } - err := db.DBconn.Remove(v.db.storeName, key) + err := db.DBconn.Remove(v.db.StoreName, key) if err != nil { return pkgerrors.Wrap(err, "Delete Network Entry;") } diff --git a/src/ncm/pkg/module/providernet.go b/src/ncm/pkg/networkintents/providernet.go index a1cbe940..0eb763c1 100644 --- a/src/ncm/pkg/module/providernet.go +++ b/src/ncm/pkg/networkintents/providernet.go @@ -14,25 +14,29 @@ * limitations under the License. */ -package module +package networkintents import ( + clusterPkg "github.com/onap/multicloud-k8s/src/ncm/pkg/cluster" + ncmtypes "github.com/onap/multicloud-k8s/src/ncm/pkg/module/types" + nettypes "github.com/onap/multicloud-k8s/src/ncm/pkg/networkintents/types" "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/db" + mtypes "github.com/onap/multicloud-k8s/src/orchestrator/pkg/module/types" pkgerrors "github.com/pkg/errors" ) // ProviderNet contains the parameters needed for dynamic networks type ProviderNet struct { - Metadata Metadata `json:"metadata"` + Metadata mtypes.Metadata `json:"metadata"` Spec ProviderNetSpec `json:"spec"` } type ProviderNetSpec struct { - CniType string `json:"cniType" yaml:"cniType"` - Ipv4Subnets []Ipv4Subnet `json:"ipv4Subnets" yaml:"ipv4Subnets"` - ProviderNetType string `json:"providerNetType" yaml:"providerNetType"` - Vlan Vlan `json:"vlan" yaml:"vlan"` + CniType string `json:"cniType" yaml:"cniType"` + Ipv4Subnets []nettypes.Ipv4Subnet `json:"ipv4Subnets" yaml:"ipv4Subnets"` + ProviderNetType string `json:"providerNetType" yaml:"providerNetType"` + Vlan nettypes.Vlan `json:"vlan" yaml:"vlan"` } // structure for the Network Custom Resource @@ -63,16 +67,16 @@ type ProviderNetManager interface { // ProviderNetClient implements the Manager // It will also be used to maintain some localized state type ProviderNetClient struct { - db ClientDbInfo + db ncmtypes.ClientDbInfo } // NewProviderNetClient returns an instance of the ProviderNetClient // which implements the Manager func NewProviderNetClient() *ProviderNetClient { return &ProviderNetClient{ - db: ClientDbInfo{ - storeName: "cluster", - tagMeta: "networkmetadata", + db: ncmtypes.ClientDbInfo{ + StoreName: "cluster", + TagMeta: "networkmetadata", }, } } @@ -88,7 +92,7 @@ func (v *ProviderNetClient) CreateProviderNet(p ProviderNet, clusterProvider, cl } //Check if cluster exists - _, err := NewClusterClient().GetCluster(clusterProvider, cluster) + _, err := clusterPkg.NewClusterClient().GetCluster(clusterProvider, cluster) if err != nil { return ProviderNet{}, pkgerrors.New("Unable to find the cluster") } @@ -99,7 +103,7 @@ func (v *ProviderNetClient) CreateProviderNet(p ProviderNet, clusterProvider, cl return ProviderNet{}, pkgerrors.New("ProviderNet already exists") } - err = db.DBconn.Insert(v.db.storeName, key, nil, v.db.tagMeta, p) + err = db.DBconn.Insert(v.db.StoreName, key, nil, v.db.TagMeta, p) if err != nil { return ProviderNet{}, pkgerrors.Wrap(err, "Creating DB Entry") } @@ -117,7 +121,7 @@ func (v *ProviderNetClient) GetProviderNet(name, clusterProvider, cluster string ProviderNetName: name, } - value, err := db.DBconn.Find(v.db.storeName, key, v.db.tagMeta) + value, err := db.DBconn.Find(v.db.StoreName, key, v.db.TagMeta) if err != nil { return ProviderNet{}, pkgerrors.Wrap(err, "Get ProviderNet") } @@ -146,7 +150,7 @@ func (v *ProviderNetClient) GetProviderNets(clusterProvider, cluster string) ([] } var resp []ProviderNet - values, err := db.DBconn.Find(v.db.storeName, key, v.db.tagMeta) + values, err := db.DBconn.Find(v.db.StoreName, key, v.db.TagMeta) if err != nil { return []ProviderNet{}, pkgerrors.Wrap(err, "Get ProviderNets") } @@ -173,7 +177,7 @@ func (v *ProviderNetClient) DeleteProviderNet(name, clusterProvider, cluster str ProviderNetName: name, } - err := db.DBconn.Remove(v.db.storeName, key) + err := db.DBconn.Remove(v.db.StoreName, key) if err != nil { return pkgerrors.Wrap(err, "Delete ProviderNet Entry;") } diff --git a/src/ncm/pkg/networkintents/types/types.go b/src/ncm/pkg/networkintents/types/types.go new file mode 100644 index 00000000..e6fea72e --- /dev/null +++ b/src/ncm/pkg/networkintents/types/types.go @@ -0,0 +1,90 @@ +/* + * 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 types + +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" + +const SEPARATOR = "+" +const CONTEXT_CLUSTER_APP = "network-intents" + +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} + +type Ipv4Subnet struct { + Subnet string `json:"subnet" yaml:"subnet"` // CIDR notation, e.g. 172.16.33.0/24 + Name string `json:"name" yaml:"name"` + Gateway string `json:"gateway" yaml:"gateway"` // IPv4 addre, e.g. 172.16.33.1/24 + Exclude string `json:"excludeIps" yaml:"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 string `json:"vlanID" yaml:"vlanId"` + ProviderInterfaceName string `json:"providerInterfaceName" yaml:"providerInterfaceName"` + LogicalInterfaceName string `json:"logicalInterfaceName" yaml:"logicalInterfaceName"` + VlanNodeSelector string `json:"vlanNodeSelector" yaml:"vlanNodeSelector"` + NodeLabelList []string `json:"nodeLabelList" yaml:"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/scheduler/scheduler.go b/src/ncm/pkg/scheduler/scheduler.go new file mode 100644 index 00000000..e72085b7 --- /dev/null +++ b/src/ncm/pkg/scheduler/scheduler.go @@ -0,0 +1,220 @@ +/* + * 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 scheduler + +import ( + "context" + "encoding/json" + "time" + + "github.com/onap/multicloud-k8s/src/ncm/internal/grpc" + oc "github.com/onap/multicloud-k8s/src/ncm/internal/ovncontroller" + clusterPkg "github.com/onap/multicloud-k8s/src/ncm/pkg/cluster" + ncmtypes "github.com/onap/multicloud-k8s/src/ncm/pkg/module/types" + nettypes "github.com/onap/multicloud-k8s/src/ncm/pkg/networkintents/types" + appcontext "github.com/onap/multicloud-k8s/src/orchestrator/pkg/appcontext" + "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/db" + log "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/logutils" + "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/rpc" + installpb "github.com/onap/multicloud-k8s/src/rsync/pkg/grpc/installapp" + + pkgerrors "github.com/pkg/errors" +) + +// ClusterManager is an interface exposes the Cluster functionality +type SchedulerManager interface { + ApplyNetworkIntents(clusterProvider, cluster string) error + TerminateNetworkIntents(clusterProvider, cluster string) error +} + +// ClusterClient implements the Manager +// It will also be used to maintain some localized state +type SchedulerClient struct { + db ncmtypes.ClientDbInfo +} + +// NewSchedulerClient returns an instance of the SchedulerClient +// which implements the Manager +func NewSchedulerClient() *SchedulerClient { + return &SchedulerClient{ + db: ncmtypes.ClientDbInfo{ + StoreName: "cluster", + TagMeta: "clustermetadata", + TagContent: "clustercontent", + TagContext: "clustercontext", + }, + } +} + +// Apply Network Intents associated with a cluster +func (v *SchedulerClient) ApplyNetworkIntents(clusterProvider, cluster string) error { + + _, err := clusterPkg.NewClusterClient().GetClusterContext(clusterProvider, cluster) + if err == nil { + return pkgerrors.Errorf("Cluster network intents have already been applied: %v, %v", clusterProvider, cluster) + } + + // Make an app context for the network intent resources + ac := appcontext.AppContext{} + ctxVal, err := ac.InitAppContext() + if err != nil { + return pkgerrors.Wrap(err, "Error creating AppContext") + } + handle, err := ac.CreateCompositeApp() + if err != nil { + return pkgerrors.Wrap(err, "Error creating AppContext CompositeApp") + } + + // Add an app (fixed value) to the app context + apphandle, err := ac.AddApp(handle, nettypes.CONTEXT_CLUSTER_APP) + if err != nil { + cleanuperr := ac.DeleteCompositeApp() + if cleanuperr != nil { + log.Warn("Error cleaning AppContext CompositeApp create failure", log.Fields{ + "cluster-provider": clusterProvider, + "cluster": cluster, + }) + } + return pkgerrors.Wrap(err, "Error adding App to AppContext") + } + + // Add an app order instruction + appinstr := struct { + Apporder []string `json:"apporder"` + }{ + []string{nettypes.CONTEXT_CLUSTER_APP}, + } + jinstr, _ := json.Marshal(appinstr) + + appdepinstr := struct { + Appdep map[string]string `json:"appdependency"` + }{ + map[string]string{nettypes.CONTEXT_CLUSTER_APP: "go"}, + } + jdep, _ := json.Marshal(appdepinstr) + + _, err = ac.AddInstruction(handle, "app", "order", string(jinstr)) + _, err = ac.AddInstruction(handle, "app", "dependency", string(jdep)) + + // Add a cluster to the app + _, err = ac.AddCluster(apphandle, clusterProvider+nettypes.SEPARATOR+cluster) + if err != nil { + cleanuperr := ac.DeleteCompositeApp() + if cleanuperr != nil { + log.Warn("Error cleaning AppContext after add cluster failure", log.Fields{ + "cluster-provider": clusterProvider, + "cluster": cluster, + }) + } + return pkgerrors.Wrap(err, "Error adding Cluster to AppContext") + } + + // Pass the context to the appropriate controller (just default ovncontroller now) + // for internal controller - pass the appcontext, cluster provider and cluster names in directly + // external controllers will be given the appcontext id and wiil have to recontstruct + // their own context + err = oc.Apply(ctxVal, clusterProvider, cluster) + if err != nil { + cleanuperr := ac.DeleteCompositeApp() + if cleanuperr != nil { + log.Warn("Error cleaning AppContext after controller failure", log.Fields{ + "cluster-provider": clusterProvider, + "cluster": cluster, + }) + } + return pkgerrors.Wrap(err, "Error adding Cluster to AppContext") + } + + // save the context in the cluster db record + key := clusterPkg.ClusterKey{ + ClusterProviderName: clusterProvider, + ClusterName: cluster, + } + err = db.DBconn.Insert(v.db.StoreName, key, nil, v.db.TagContext, ctxVal) + if err != nil { + cleanuperr := ac.DeleteCompositeApp() + if cleanuperr != nil { + log.Warn("Error cleaning AppContext after DB insert failure", log.Fields{ + "cluster-provider": clusterProvider, + "cluster": cluster, + }) + } + return pkgerrors.Wrap(err, "Error adding AppContext to DB") + } + + // call resource synchronizer to instantiate the CRs in the cluster + conn := rpc.GetRpcConn(grpc.RsyncName) + if conn == nil { + grpc.InitRsyncClient() + conn = rpc.GetRpcConn(grpc.RsyncName) + } + + var rpcClient installpb.InstallappClient + var installRes *installpb.InstallAppResponse + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + + if conn != nil { + rpcClient = installpb.NewInstallappClient(conn) + installReq := new(installpb.InstallAppRequest) + installReq.AppContext = ctxVal.(string) + installRes, err = rpcClient.InstallApp(ctx, installReq) + if err == nil { + log.Info("Response from InstappApp GRPC call", log.Fields{ + "Succeeded": installRes.AppContextInstalled, + "Message": installRes.AppContextInstallMessage, + }) + } + } else { + return pkgerrors.Errorf("InstallApp Failed - Could not get InstallAppClient: %v", grpc.RsyncName) + } + + return nil +} + +// Terminate Network Intents associated with a cluster +func (v *SchedulerClient) TerminateNetworkIntents(clusterProvider, cluster string) error { + context, err := clusterPkg.NewClusterClient().GetClusterContext(clusterProvider, cluster) + if err != nil { + return pkgerrors.Wrapf(err, "Error finding AppContext for cluster: %v, %v", clusterProvider, cluster) + } + + // TODO: call resource synchronizer to terminate the CRs in the cluster + + // remove the app context + cleanuperr := context.DeleteCompositeApp() + if cleanuperr != nil { + log.Warn("Error deleted AppContext", log.Fields{ + "cluster-provider": clusterProvider, + "cluster": cluster, + }) + } + + // remove the app context field from the cluster db record + key := clusterPkg.ClusterKey{ + ClusterProviderName: clusterProvider, + ClusterName: cluster, + } + err = db.DBconn.RemoveTag(v.db.StoreName, key, v.db.TagContext) + if err != nil { + log.Warn("Error removing AppContext from Cluster document", log.Fields{ + "cluster-provider": clusterProvider, + "cluster": cluster, + }) + } + return nil +} |