summaryrefslogtreecommitdiffstats
path: root/src/ncm/pkg/scheduler/scheduler.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/ncm/pkg/scheduler/scheduler.go')
-rw-r--r--src/ncm/pkg/scheduler/scheduler.go220
1 files changed, 220 insertions, 0 deletions
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
+}