Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Appcontext Data Format:

The following figure depicts the hierarchical data store for runtime data. The notes in the figure is additional data stored in each type of node. Rsync uses this information to schedule resources. Status is updated by Rsync.

AppContext Library

To create and work with appcontext a library is provided: github.com/onap/multicloud-k8s/src/orchestrator/pkg/appcontext

Creating AppContext Flow

The following example shows how to create an AppContext for a CompositeApp with one App. This pattern is used by controllers that are creating new AppContextID. Examples are Orchestrator, NCM(create networks), CLM(create clusters) and DCM(create logical clouds) 

...

languagecpp
titleCreating AppContext

...

Table of Contents
Appcontext Data Format

The following figure depicts the hierarchical data store for runtime data. The notes in the figure is additional data stored in each type of node. Rsync uses this information to schedule resources. Status is updated by Rsync.


AppContext Library

To create and work with appcontext a library is provided: github.com/onap/multicloud-k8s/src/orchestrator/pkg/appcontext

Creating AppContext Flow

The following example shows how to create an AppContext for a CompositeApp with one App. This pattern is used by controllers that are creating new AppContextID. Examples are Orchestrator, NCM(create networks), CLM(create clusters) and DCM(create logical clouds) 

Code Block
languagecpp
titleCreating AppContext
import "github.com/onap/multicloud-k8s/src/orchestrator/pkg/appcontext"
func createAppContextWithOneApp(appName string)	
{
	context := appcontext.AppContext{}
	ctxVal, err := context.InitAppContext()
	if err != nil {
		return nil
	}
	
    handle, err := context.CreateCompositeApp()
	if err != nil {
		return nil
	}
	// This is optional
    err = context.AddCompositeAppMeta(appcontext.CompositeAppMeta{Project: p, CompositeApp: ca, Version: v, Release: rName})
	if err != nil {
		return nil
	}
	
    appHandle, err := context.AddApp(handle, appName)
	if err != nil {
		return nil
	}
	
    // Iterate through cluster list and add all the clusters
	for _, cluster := range clusterList {
		clusterName := strings.Join([]string{cluster.ClusterProvider, "+", cluster.ClusterName}, "")
		clusterHandle, err := context.AddCluster(appHandle, clusterName)

		if err != nil {
			return nil
		}

		// Add resource
		_, err = context.AddResource(clusterHandle, nameofRes1, resYaml1)
		if err != nil {
			return nil
		}
		// Add resource
		_, err = context.AddResource(clusterHandle, nameofRes2, resYaml2)
		if err != nil {
			return nil
		}
		// Add Resource Order 
		resOrder, err := json.Marshal(map[string][]string{"resorder": []string{nameofRes1, nameofRes2}})
		if err != nil {
			return nil
		}
		_, err = context.AddInstruction(clusterHandle, "resource", "order", string(resOrder))
		if err != nil {
			return nil
	}
	
    handle, err := context.CreateCompositeApp()
	if err != nil {
		return nil
	}
	// This is optional
   
		}
	}
}

Action Controller flow

Action controllers will follow the following pattern to add and update existing resources in AppContext. AppContextId is provided to the action controllers from the orchestrator using gRpc call. Examples are ovnAction controller

Code Block
languagecpp
titleCreating AppContext
import "github.com/onap/multicloud-k8s/src/orchestrator/pkg/appcontext"
func updateAppContext(appContextId string)	
{
	var context appcontext.AppContext
	_, err = context.AddCompositeAppMeta(appcontext.CompositeAppMeta{Project: p, CompositeApp: ca, Version: v, Release: rName}.LoadAppContext(appContextId)
	if err != nil {
		return nil
	}
	
    appHandle

   // Get all clusters from the AppContext for an App
	clusters, err := context.AddApp(handle, appNameGetClusterNames("testApp")
	if err != nil {
		return nil
	}
	
    // Iterate through cluster list and add all the clusters
	for _, cluster := range clusterList {
		clusterNamefor _, c := range clusters {
		// Resources in AppContext are named is the format (ResourceName+ResourceType) "res3+Deployment"
		appContextResName := strings.Join([]string{cluster.ClusterProvider"resName", "+Deployment", cluster.ClusterName}, "+")
		clusterHandlerh, err := context.AddCluster(appHandle, clusterName)
GetResourceHandle("testApp", c, appContextResName )
		if err != nil {
			return nilerr
		}

		// Add resource
		_r, err := context.AddResource(clusterHandle, nameofRes1, resYaml1GetValue(rh)
		if err != nil {
			return nilerr
		}
		// Add resource Unmarshal resource extract the Kubernetes object definition
		_kubObj, err := context.AddResource(clusterHandle, nameofRes2, resYaml2runtime.Decode(scheme.Codecs.UniversalDeserializer(), []byte(r.(string)))
		if//Modify errresource != nil {
			return nil
		}
		// Add Resource Order 
		resOrder, err := json.Marshal(map[string][]string{"resorder": []string{nameofRes1, nameofRes2}})
		if err != nil {
			return nil
		}
		_, to add/modify existing contents
        ......
		// Put back updated resource in AppContext
		err = context.AddInstructionUpdateResourceValue(clusterHandlerh, "resource", "order", string(resOrder)updatedRes)
		if err != nil {
			return nil
		}
	}
}

Action Controller flow (Updating Resources in  AppContext)

...

Placement Controller flow 

Placement controllers will follow the following pattern to add and update existing resources in AppContextselect a cluster from group of clusters for an App. AppContextId is provided to the action placement controllers from the orchestrator using gRpc call. Examples are ovnAction controller 

Code Block
languagecpp
titleCreating AppContext
import "github.com/onap/multicloud-k8s/src/orchestrator/pkg/appcontext"
func updateAppContextplacement(appContextId string)	
{
	var context appcontext.AppContext
	_, err = context.LoadAppContext(appContextId)
	if err != nil {
		return nil
	}

 nil
	}
   // Get  AppContext for an App
  gmap, err := context.GetClusterGroupMap("testApp")
  // sample Get all clusters from the AppContext for an App
	clusters, err := context.GetClusterNames("testApp")
	for _, coutput {"1":["cluster_provider1+clusterName3","cluster_provider1+clusterName5"],"2":["cluster_provider2+clusterName4","cluster_provider2+clusterName6"]}
  for gr, cl := range gmap {
	for i, cn := range clusterscl {
		// ResourcesBased inon AppContextthe areoutput nameddecide is the format (ResourceName+ResourceType) "res3+Deployment"
		appContextResName := strings.Join([]string{"resName", "Deployment"}, "+"
		rh, err := context.GetResourceHandle("testApp", c, appContextResName )
		if err != nil {
			return err
		}
		rwhich cluster is not suitable
   		.......
        //Delete the cluster not suitable
		ch, err := contextct.GetValue(rhGetClusterHandle(an, cn)
		if err != nil {
			return err
		}
		// Unmarshal resource extract the Kubernetes object definition
		kubObj, err := runtime.Decode(scheme.Codecs.UniversalDeserializer(), []byte(r.(string)))
		//Modify resource to add/modify existing contents
        ......
		// Put back updated resource in AppContext
		err = context.UpdateResourceValue(rh, updatedRes)
		if err != nil {
			return nil
		}
}

Placement Controller flow 

Placement controllers will follow the following pattern to select a cluster from group of clusters for an App. AppContextId is provided to the placement controllers from the orchestrator using gRpc call. 

Code Block
languagecpp
titleCreating AppContext
func placement(appContextId string)	
{
	var context appcontext.AppContext
	_, err = context.LoadAppContext(appContextId)
	if err != nil {
		return nil
	}
   // Get  AppContext for an App
  gmap, err := context.GetClusterGroupMap("testApp")
  // sample output {"1":["cluster_provider1+clusterName3","cluster_provider1+clusterName5"],"2":["cluster_provider2+clusterName4","cluster_provider2+clusterName6"]}
  for gr, cl := range gmap {
	for i, cn := range cl {
		// Based on the output decide which cluster is not suitable
   		.......
        //Delete the cluster not suitable
		ch, err := ct.GetClusterHandle(an, cn)
		err = ct.DeleteCluster(ch)
	}	
  }
}

AppContext API

GoDoc: package appcontext // import "github.com/onap/multicloud-k8s/src/orchestrator/pkg/appcontext"

Code Block
languagecpp
func (ac *AppContext) CreateCompositeApp(= ct.DeleteCluster(ch)
	}	
  }
}

RPC Communication 

AppContext API

GoDoc: package appcontext // import "github.com/onap/multicloud-k8s/src/orchestrator/pkg/appcontext"


Code Block
languagecpp
func (ac *AppContext) CreateCompositeApp() (interface{}, error)
CreateCompositeApp method returns composite app handle as interface.

func (ac *AppContext) AddCompositeAppMeta(meta interface{}) error
AddCompositeAppMeta adds the meta data associated with a composite app

func (ac *AppContext) AddApp(handle interface{}, appname string) (interface{}, error)
Add app to the context under composite app

func (ac *AppContext) AddCluster(handle interface{}, clustername string) (interface{}, error)
AddCluster helps to add cluster to the context under app. It takes in the
app handle and clusterName as value.

func (ac *AppContext) AddClusterMetaGrp(ch interface{}, gn string) error
AddClusterMetaGrp adds the meta info of groupNumber to which a cluster
belongs. It takes in cluster handle and groupNumber as arguments. Used when
using AnyOf 

func (ac *AppContext) AddResource(handle interface{}, resname string, value interface{}) (interface{}, error)
Add resource under app and cluster

func (ac *AppContext) AddInstruction(handle interface{}, level string, insttype string, value interface{}) (interface{}, error)
Add instruction under given handle and type

func (ac *AppContext) AddLevelValue(handle interface{}, level string, value interface{}) (interface{}, error)
CreateCompositeAppAddLevelValue methodfor returnsholding compositea appstate handleobject asat interface.a given funclevel (ac *AppContext) AddCompositeAppMeta(meta interface{}) error
AddCompositeAppMeta adds the meta data associated with a composite app

will make a handle
with an appended "<level>/" to the key

func (ac *AppContext) AddAppAddResource(handle interface{}, appnameresname string, value interface{}) (interface{}, error)
Add appresource tounder theapp context under composite appand cluster

func (ac *AppContext) AddClusterDeleteApp(handle interface{}, clustername string) (interface{}, error)
AddCluster helps to add cluster to the context under app. It takes in the
app handle and clusterName as value.) error
Delete app from the context and everything underneth

func (ac *AppContext) DeleteCluster(handle interface{}) error
Delete cluster from the context and everything underneath

func (ac *AppContext) AddClusterMetaGrpDeleteClusterMetaGrpHandle(ch interface{}, gn string) error
AddClusterMetaGrp adds the meta info of groupNumberDeleteClusterMetaGrpHandle deletes the group number to which athe cluster
belongs., Itit takes in the cluster handle.

andfunc groupNumber as arguments. Used when
using AnyOf (ac *AppContext) DeleteCompositeApp() error
Deletes the entire context

func (ac *AppContext) AddResourceDeleteInstruction(handle interface{}, resname string, value) error
Delete instruction under given handle

func (ac *AppContext) GetAllHandles(handle interface{}) ([]interface{}, error)
Return all Addthe resourcehandles under appthe andcomposite clusterapp

func (ac *AppContext) AddInstruction(handle interface{}, level string, insttype string, value interface{}GetAppHandle(appname string) (interface{}, error)
AddReturns instructionthe underhandle givenfor handlea andgiven typeapp

func (ac *AppContext) AddLevelValueGetAppInstruction(handle interface{}, level string, value interface{}insttype string) (interface{}, error)
AddLevelValueReturns forthe holdingapp a state object atinstruction for a given level will make a handle
with an appended "<level>/" to the keyinstruction type

func (ac *AppContext) AddResourceGetClusterGroupMap(handle interface{}, resname string, value interface{}) (interface{}an string) (map[string][]string, error)
GetClusterGroupMap Addshall resourcetake underin appappName and clusterreturn a funcmap (ac *AppContext) DeleteApp(handle interface{}) error
Delete app from the context and everything undernethshowing the
grouping among the clusters. sample output of "GroupMap"
:{"1":["cluster_provider1+clusterName3","cluster_provider1+clusterName5"],"2":["cluster_provider2+clusterName4","cluster_provider2+clusterName6"]}

func (ac *AppContext) DeleteClusterGetClusterHandle(handle interface{}) error
Delete cluster from the context and everything underneath

func (ac *AppContext) DeleteClusterMetaGrpHandle(ch interface{}) error
DeleteClusterMetaGrpHandle deletes the group number to which the cluster
belongs, it takes in the cluster handle.appname string, clustername string) (interface{}, error)
Returns the handle for a given app and cluster

func (ac *AppContext) DeleteCompositeApp()GetClusterMetaHandle(app string, cluster string) (string, error)
DeletesGetClusterMetaHandle thetakes entirein contextappName and funcClusterName (ac *AppContext) DeleteInstruction(handle interface{}) error
Delete instruction under given handleas string arguments
and return the ClusterMetaHandle as string

func (ac *AppContext) GetAllHandlesGetClusterNames(handleappname interface{}string) ([]interface{}string, error)
Return
Returns a list of all theclusters handlesfor undera thegiven composite app

func (ac *AppContext) GetAppHandleGetClusterStatusHandle(appname string, clustername string) (interface{}, error)
Returns the handle
GetClusterStatusHandle returns the handle for cluster status for a given app
and cluster

func (ac *AppContext) GetAppInstructionGetCompositeAppHandle(insttype string) (interface{}, error)
Returns the app instructionhandles for a given composite instructionapp typecontext

func (ac *AppContext) GetClusterGroupMapGetCompositeAppMeta(an string) (map[string][]string, error)
GetClusterGroupMap shall take in appName and return a map showing the
grouping among the clusters. sample output of "GroupMap"
:{"1":["cluster_provider1+clusterName3","cluster_provider1+clusterName5"],"2":["cluster_provider2+clusterName4","cluster_provider2+clusterName6"]}CompositeAppMeta, error)
GetCompositeAppMeta returns the meta data associated with the compositeApp
Its return type is CompositeAppMeta

func (ac *AppContext) GetClusterHandleGetLevelHandle(appnamehandle stringinterface{}, clusternamelevel string) (interface{}, error)
Returns, error)
GetLevelHandle returns the handle for the supplied level at the given
handle. For example, to get the handle for of the 'status' level at a given
app andhandle.
cluster

func (ac *AppContext) GetClusterMetaHandle(appGetResourceHandle(appname string, clustername string, clusterresname string) (stringinterface{}, error)
GetClusterMetaHandleReturn takesthe inhandle appNamefor and ClusterName as string arguments
and return the ClusterMetaHandle as string
given app, cluster and resource name

func (ac *AppContext) GetClusterNamesGetResourceInstruction(appname string, clustername string, insttype string) ([]stringinterface{}, error)
Returns athe list of all clustersresource instruction for a given appinstruction type

func (ac *AppContext) GetClusterStatusHandleGetResourceStatusHandle(appname string, clustername string, resname string) (interface{}, error)
GetClusterStatusHandle returnsReturn the handle for cluster status for a given app, cluster and resource clustername

func (ac *AppContext) GetCompositeAppHandleGetValue(handle interface{}) (interface{}, error)
Returns the handlesvalue for a given composite app contexthandle

func (ac *AppContext) GetCompositeAppMetaInitAppContext() (CompositeAppMetainterface{}, error)
GetCompositeAppMetaInit returns the meta data associated with the compositeApp
Its return type is CompositeAppMeta

app context

func (ac *AppContext) GetLevelHandleLoadAppContext(handlecid interface{}, level string) (interface{}, error)
GetLevelHandleLoad returnsapp thecontext handlethat for the supplied level at the given
handle. For example, to get the handle of the 'status' level at a given
handle.was previously created

func (ac *AppContext) GetResourceHandleUpdateInstructionValue(appnamehandle stringinterface{}, clustername string, resname string) (value interface{},) error)
ReturnUpdate the handleinstruction usign forthe given app,handle
cluster
and resource name

func (ac *AppContext) GetResourceInstruction(appname string, clustername string, insttype string) UpdateResourceValue(handle interface{}, value interface{}) error)
ReturnsUpdate the resource instructionvalue forusing athe given instructionhandle
type

func (ac *AppContext) GetResourceStatusHandleUpdateStatusValue(appnamehandle stringinterface{}, clustername string, resname string) (value interface{},) error)
UpdateStatusValue Returnupdates the handlestatus for given app, cluster and resource namevalue with the given handle

func (ac *AppContext) GetValueUpdateValue(handle interface{}), value (interface{},) error)
UpdateValue Returnsupdates the state value forwith athe given handle

func (ac *AppContext) InitAppContext() (interface{}, error)
Init app context

func (ac *AppContext) LoadAppContext(cid interface{}) (interface{}, error)
Load app context that was previously created

func (ac *AppContext) UpdateInstructionValue(handle interface{}, value interface{}) error
Update the instruction usign the given handle

func (ac *AppContext) UpdateResourceValue(handle interface{}, value interface{}) error
Update the resource value using the given handle

func (ac *AppContext) UpdateStatusValue(handle interface{}, value interface{}) error
UpdateStatusValue updates the status value with the given handle

func (ac *AppContext) UpdateValue(handle interface{}, value interface{}) error
UpdateValue updates the state value with the given handle


RSYNC registration outside of orchestration.

There have been use cases when we need to invoke RSYNC outside of orchestrator.
For such cases, we have provided a method - NewRsyncInfo()
This method directly takes in Rsync controller name, hostname and port number.
After that , we have a method initRsyncClient() which creates the required gRPC client connection.
Use the above two methods to register a rsync controller outside of orchestrator.

The relevant portion in the code is shown below :

File to import : orchestrator/pkg/grpc/installappclient/client.go


Code Block
languagejava
themeMidnight
func NewRsyncInfo(rName, h string, pN int) RsyncInfo {
mutex.Lock()
defer mutex.Unlock()
rsyncInfo = RsyncInfo{RsyncName: rName, hostName: h, portNumber: pN}
return rsyncInfo

}


Code Block
languagejava
themeMidnight
func initRsyncClient() bool {
	if (RsyncInfo{}) == rsyncInfo {
		mutex.Lock()
		defer mutex.Unlock()
		log.Error("RsyncInfo not set. InitRsyncClient failed", log.Fields{
			"Rsyncname":  rsyncInfo.RsyncName,
			"Hostname":   rsyncInfo.hostName,
			"PortNumber": rsyncInfo.portNumber,
		})
		return false
	}
	rpc.UpdateRpcConn(rsyncInfo.RsyncName, rsyncInfo.hostName, rsyncInfo.portNumber)
	return true
}