github.com/onosproject/onos-api/go@v0.10.32/onos/topo/topo.go (about)

     1  // SPDX-FileCopyrightText: 2020-present Open Networking Foundation <info@opennetworking.org>
     2  //
     3  // SPDX-License-Identifier: Apache-2.0
     4  
     5  package topo
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"github.com/gogo/protobuf/jsonpb"
    11  	"github.com/gogo/protobuf/proto"
    12  	"github.com/gogo/protobuf/types"
    13  	"google.golang.org/grpc"
    14  )
    15  
    16  // UUID represents a system-assigned unique identifier of a topology object.
    17  type UUID string
    18  
    19  // ID represents a client-assigned unique identifier.
    20  type ID string
    21  
    22  // String convert ID to string
    23  func (id ID) String() string {
    24  	return string(id)
    25  }
    26  
    27  // NullID represents a null/empty/omitted identifier; usually an indicator for system to generate one.
    28  const NullID = ""
    29  
    30  // Revision is an object revision
    31  type Revision uint64
    32  
    33  // DEPRECATED Entity and Relation Kinds
    34  const (
    35  	// Relations
    36  	CONTROLS  = "controls"
    37  	CONTAINS  = "contains"
    38  	NEIGHBORS = "neighbors"
    39  
    40  	// RAN Entities
    41  	E2NODE = "e2node"
    42  	E2CELL = "e2cell"
    43  	E2T    = "e2t"
    44  	XAPP   = "xapp"
    45  	A1T    = "a1t"
    46  
    47  	// onos-config entity
    48  	ONOS_CONFIG = "onos-config"
    49  )
    50  
    51  // TODO UPPERCASE entity kinds and relations should be replaced gradually with CamelCase ones
    52  const (
    53  	ControlsKind   = "controls"
    54  	ContainsKind   = "contains"
    55  	HasKind        = "has"
    56  	TerminatesKind = "terminates"
    57  	OriginatesKind = "originates"
    58  	NeighborsKind  = "neighbors"
    59  	ConnectionKind = "connection"
    60  
    61  	// Fabric Entity kinds
    62  	PodKind          = "pod"
    63  	RackKind         = "rack"
    64  	NetworkLayerKind = "network-layer"
    65  	SwitchKind       = "switch"
    66  	ServerKind       = "server"
    67  	IPUKind          = "ipu"
    68  	HostKind         = "host"
    69  	RouterKind       = "router"
    70  	PortKind         = "port"
    71  	InterfaceKind    = "interface"
    72  	LinkKind         = "link"
    73  	ControllerKind   = "controller"
    74  	ServiceKind      = "service"
    75  
    76  	// onos-config entity
    77  	OnosConfigKind = "onos-config"
    78  
    79  	// RAN Entitiy kinds
    80  	E2NodeKind = "e2node"
    81  	E2CellKind = "e2cell"
    82  	E2tKind    = "e2t"
    83  	XappKind   = "xapp"
    84  	A1tKind    = "a1t"
    85  )
    86  
    87  // PolicyTypeID is an identifier of A1 policy type
    88  type PolicyTypeID string
    89  
    90  // PolicyTypeName is a name of A1 policy type
    91  type PolicyTypeName string
    92  
    93  // PolicyTypeVersion is a version of A1 policy type
    94  type PolicyTypeVersion string
    95  
    96  // PolicyTypeDescription describe what this A1 policy is
    97  type PolicyTypeDescription string
    98  
    99  // TopoClientFactory : Default EntityServiceClient creation.
   100  var TopoClientFactory = func(cc *grpc.ClientConn) TopoClient {
   101  	return NewTopoClient(cc)
   102  }
   103  
   104  // CreateTopoClient creates and returns a new topo device client
   105  func CreateTopoClient(cc *grpc.ClientConn) TopoClient {
   106  	return TopoClientFactory(cc)
   107  }
   108  
   109  // RelationID creates a unique relationship ID from the specified source, kind and target IDs
   110  func RelationID(srcID ID, relationKind ID, tgtID ID) ID {
   111  	return ID(fmt.Sprintf("%s-%s-%s", srcID, relationKind, tgtID))
   112  }
   113  
   114  // MultiRelationID creates a unique relationship ID from the specified source, kind and target IDs,
   115  // and also from an additional discriminant to allow for multiples of same kinds of relations between
   116  // the same two objects.
   117  func MultiRelationID(srcID ID, relationKind ID, tgtID ID, discriminant uint8) ID {
   118  	return ID(fmt.Sprintf("%s-%s-%s-%d", srcID, relationKind, tgtID, discriminant))
   119  }
   120  
   121  // NewEntity allocates a new topology entity using the specified ID and kind.
   122  func NewEntity(id ID, kind ID, aspects ...proto.Message) *Object {
   123  	return &Object{ID: id, Type: Object_ENTITY, Obj: &Object_Entity{Entity: &Entity{KindID: kind}}}
   124  }
   125  
   126  // NewRelation allocates a new topology relation using the specified source, target, and kind.
   127  func NewRelation(source ID, target ID, kind ID, aspects ...proto.Message) *Object {
   128  	return &Object{
   129  		ID:   RelationID(source, kind, target),
   130  		Type: Object_RELATION,
   131  		Obj:  &Object_Relation{Relation: &Relation{SrcEntityID: source, TgtEntityID: target, KindID: kind}},
   132  	}
   133  }
   134  
   135  // WithAspects applies the given aspects to the object.
   136  func (obj *Object) WithAspects(aspects ...proto.Message) (*Object, error) {
   137  	for _, aspect := range aspects {
   138  		if err := obj.SetAspect(aspect); err != nil {
   139  			return obj, err
   140  		}
   141  	}
   142  	return obj, nil
   143  }
   144  
   145  // ToAny provides a convenience utility to convert an aspect message to protobuf types.Any
   146  func ToAny(value proto.Message) *types.Any {
   147  	jm := jsonpb.Marshaler{}
   148  	writer := bytes.Buffer{}
   149  	if err := jm.Marshal(&writer, value); err != nil {
   150  		return nil
   151  	}
   152  	return &types.Any{
   153  		TypeUrl: proto.MessageName(value),
   154  		Value:   writer.Bytes(),
   155  	}
   156  }
   157  
   158  // GetAspect retrieves the specified aspect value from the given object.
   159  func (obj *Object) GetAspect(destValue proto.Message) error {
   160  	if obj.Aspects == nil {
   161  		return fmt.Errorf("no aspects found on %s", obj.String())
   162  	}
   163  	aspectType := proto.MessageName(destValue)
   164  	any := obj.Aspects[aspectType]
   165  	if any == nil {
   166  		return fmt.Errorf("aspect '%s' not found in %s", aspectType, obj.String())
   167  	}
   168  	if any.TypeUrl != aspectType {
   169  		return fmt.Errorf("unexpected aspect type: %s", aspectType)
   170  	}
   171  	reader := bytes.NewReader(any.Value)
   172  	err := jsonpb.Unmarshal(reader, destValue)
   173  	if err != nil {
   174  		return fmt.Errorf("error '%s' when unmarshalling aspect %s: %v from %s",
   175  			err.Error(), aspectType, any.Value, obj.String())
   176  	}
   177  	return nil
   178  }
   179  
   180  // GetAspectBytes applies the specified aspect as raw JSON bytes to the given object.
   181  func (obj *Object) GetAspectBytes(aspectType string) ([]byte, error) {
   182  	if obj.Aspects == nil {
   183  		return nil, fmt.Errorf("no aspects found on %s", obj.String())
   184  	}
   185  	any := obj.Aspects[aspectType]
   186  	if any == nil {
   187  		return nil, fmt.Errorf("aspect '%s' not found on %s", aspectType, obj.String())
   188  	}
   189  	return any.Value, nil
   190  }
   191  
   192  // SetAspect applies the specified aspect value to the given object.
   193  func (obj *Object) SetAspect(value proto.Message) error {
   194  	jm := jsonpb.Marshaler{}
   195  	writer := bytes.Buffer{}
   196  	err := jm.Marshal(&writer, value)
   197  	if err != nil {
   198  		return fmt.Errorf("error '%s' marshaling aspect %v on to %s",
   199  			err.Error(), value, obj.String())
   200  	}
   201  	if obj.Aspects == nil {
   202  		obj.Aspects = make(map[string]*types.Any)
   203  	}
   204  	obj.Aspects[proto.MessageName(value)] = &types.Any{
   205  		TypeUrl: proto.MessageName(value),
   206  		Value:   writer.Bytes(),
   207  	}
   208  	return nil
   209  }
   210  
   211  // SetAspectBytes applies the specified aspect as raw JSON bytes to the given object.
   212  func (obj *Object) SetAspectBytes(aspectType string, jsonValue []byte) error {
   213  	any := &types.Any{
   214  		TypeUrl: aspectType,
   215  		Value:   jsonValue,
   216  	}
   217  	if obj.Aspects == nil {
   218  		obj.Aspects = make(map[string]*types.Any)
   219  	}
   220  	obj.Aspects[aspectType] = any
   221  	return nil
   222  }