[VOL-4687] Add transceivers to DMI, add commands to bbsimctl to manage them
Change-Id: Id1fe29eb48a7abb3c86958827edce70b75707de9
diff --git a/VERSION b/VERSION
index 89c881b..e0a6b34 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.12.4
+1.12.5
diff --git a/api/bbsim/bbsim_dmi.pb.go b/api/bbsim/bbsim_dmi.pb.go
index d2cc5f8..a296e5e 100644
--- a/api/bbsim/bbsim_dmi.pb.go
+++ b/api/bbsim/bbsim_dmi.pb.go
@@ -63,7 +63,7 @@
return ""
}
-type DmiCreateEventResponse struct {
+type DmiResponse struct {
StatusCode int32 `protobuf:"varint,1,opt,name=status_code,json=statusCode,proto3" json:"status_code,omitempty"`
Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
@@ -71,68 +71,272 @@
XXX_sizecache int32 `json:"-"`
}
-func (m *DmiCreateEventResponse) Reset() { *m = DmiCreateEventResponse{} }
-func (m *DmiCreateEventResponse) String() string { return proto.CompactTextString(m) }
-func (*DmiCreateEventResponse) ProtoMessage() {}
-func (*DmiCreateEventResponse) Descriptor() ([]byte, []int) {
+func (m *DmiResponse) Reset() { *m = DmiResponse{} }
+func (m *DmiResponse) String() string { return proto.CompactTextString(m) }
+func (*DmiResponse) ProtoMessage() {}
+func (*DmiResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_49e784b4938902cc, []int{1}
}
-func (m *DmiCreateEventResponse) XXX_Unmarshal(b []byte) error {
- return xxx_messageInfo_DmiCreateEventResponse.Unmarshal(m, b)
+func (m *DmiResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_DmiResponse.Unmarshal(m, b)
}
-func (m *DmiCreateEventResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
- return xxx_messageInfo_DmiCreateEventResponse.Marshal(b, m, deterministic)
+func (m *DmiResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_DmiResponse.Marshal(b, m, deterministic)
}
-func (m *DmiCreateEventResponse) XXX_Merge(src proto.Message) {
- xxx_messageInfo_DmiCreateEventResponse.Merge(m, src)
+func (m *DmiResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_DmiResponse.Merge(m, src)
}
-func (m *DmiCreateEventResponse) XXX_Size() int {
- return xxx_messageInfo_DmiCreateEventResponse.Size(m)
+func (m *DmiResponse) XXX_Size() int {
+ return xxx_messageInfo_DmiResponse.Size(m)
}
-func (m *DmiCreateEventResponse) XXX_DiscardUnknown() {
- xxx_messageInfo_DmiCreateEventResponse.DiscardUnknown(m)
+func (m *DmiResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_DmiResponse.DiscardUnknown(m)
}
-var xxx_messageInfo_DmiCreateEventResponse proto.InternalMessageInfo
+var xxx_messageInfo_DmiResponse proto.InternalMessageInfo
-func (m *DmiCreateEventResponse) GetStatusCode() int32 {
+func (m *DmiResponse) GetStatusCode() int32 {
if m != nil {
return m.StatusCode
}
return 0
}
-func (m *DmiCreateEventResponse) GetMessage() string {
+func (m *DmiResponse) GetMessage() string {
if m != nil {
return m.Message
}
return ""
}
+type DmiEmpty struct {
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *DmiEmpty) Reset() { *m = DmiEmpty{} }
+func (m *DmiEmpty) String() string { return proto.CompactTextString(m) }
+func (*DmiEmpty) ProtoMessage() {}
+func (*DmiEmpty) Descriptor() ([]byte, []int) {
+ return fileDescriptor_49e784b4938902cc, []int{2}
+}
+
+func (m *DmiEmpty) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_DmiEmpty.Unmarshal(m, b)
+}
+func (m *DmiEmpty) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_DmiEmpty.Marshal(b, m, deterministic)
+}
+func (m *DmiEmpty) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_DmiEmpty.Merge(m, src)
+}
+func (m *DmiEmpty) XXX_Size() int {
+ return xxx_messageInfo_DmiEmpty.Size(m)
+}
+func (m *DmiEmpty) XXX_DiscardUnknown() {
+ xxx_messageInfo_DmiEmpty.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_DmiEmpty proto.InternalMessageInfo
+
+type TransceiverRequest struct {
+ TransceiverId uint32 `protobuf:"varint,1,opt,name=TransceiverId,proto3" json:"TransceiverId,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *TransceiverRequest) Reset() { *m = TransceiverRequest{} }
+func (m *TransceiverRequest) String() string { return proto.CompactTextString(m) }
+func (*TransceiverRequest) ProtoMessage() {}
+func (*TransceiverRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_49e784b4938902cc, []int{3}
+}
+
+func (m *TransceiverRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_TransceiverRequest.Unmarshal(m, b)
+}
+func (m *TransceiverRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_TransceiverRequest.Marshal(b, m, deterministic)
+}
+func (m *TransceiverRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_TransceiverRequest.Merge(m, src)
+}
+func (m *TransceiverRequest) XXX_Size() int {
+ return xxx_messageInfo_TransceiverRequest.Size(m)
+}
+func (m *TransceiverRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_TransceiverRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_TransceiverRequest proto.InternalMessageInfo
+
+func (m *TransceiverRequest) GetTransceiverId() uint32 {
+ if m != nil {
+ return m.TransceiverId
+ }
+ return 0
+}
+
+type Transceiver struct {
+ ID uint32 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"`
+ UUID string `protobuf:"bytes,2,opt,name=UUID,proto3" json:"UUID,omitempty"`
+ Name string `protobuf:"bytes,3,opt,name=Name,proto3" json:"Name,omitempty"`
+ Technology string `protobuf:"bytes,4,opt,name=Technology,proto3" json:"Technology,omitempty"`
+ PluggedIn bool `protobuf:"varint,5,opt,name=PluggedIn,proto3" json:"PluggedIn,omitempty"`
+ PonIds []uint32 `protobuf:"varint,6,rep,packed,name=PonIds,proto3" json:"PonIds,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *Transceiver) Reset() { *m = Transceiver{} }
+func (m *Transceiver) String() string { return proto.CompactTextString(m) }
+func (*Transceiver) ProtoMessage() {}
+func (*Transceiver) Descriptor() ([]byte, []int) {
+ return fileDescriptor_49e784b4938902cc, []int{4}
+}
+
+func (m *Transceiver) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_Transceiver.Unmarshal(m, b)
+}
+func (m *Transceiver) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_Transceiver.Marshal(b, m, deterministic)
+}
+func (m *Transceiver) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Transceiver.Merge(m, src)
+}
+func (m *Transceiver) XXX_Size() int {
+ return xxx_messageInfo_Transceiver.Size(m)
+}
+func (m *Transceiver) XXX_DiscardUnknown() {
+ xxx_messageInfo_Transceiver.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Transceiver proto.InternalMessageInfo
+
+func (m *Transceiver) GetID() uint32 {
+ if m != nil {
+ return m.ID
+ }
+ return 0
+}
+
+func (m *Transceiver) GetUUID() string {
+ if m != nil {
+ return m.UUID
+ }
+ return ""
+}
+
+func (m *Transceiver) GetName() string {
+ if m != nil {
+ return m.Name
+ }
+ return ""
+}
+
+func (m *Transceiver) GetTechnology() string {
+ if m != nil {
+ return m.Technology
+ }
+ return ""
+}
+
+func (m *Transceiver) GetPluggedIn() bool {
+ if m != nil {
+ return m.PluggedIn
+ }
+ return false
+}
+
+func (m *Transceiver) GetPonIds() []uint32 {
+ if m != nil {
+ return m.PonIds
+ }
+ return nil
+}
+
+type Transceivers struct {
+ Items []*Transceiver `protobuf:"bytes,1,rep,name=Items,proto3" json:"Items,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *Transceivers) Reset() { *m = Transceivers{} }
+func (m *Transceivers) String() string { return proto.CompactTextString(m) }
+func (*Transceivers) ProtoMessage() {}
+func (*Transceivers) Descriptor() ([]byte, []int) {
+ return fileDescriptor_49e784b4938902cc, []int{5}
+}
+
+func (m *Transceivers) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_Transceivers.Unmarshal(m, b)
+}
+func (m *Transceivers) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_Transceivers.Marshal(b, m, deterministic)
+}
+func (m *Transceivers) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Transceivers.Merge(m, src)
+}
+func (m *Transceivers) XXX_Size() int {
+ return xxx_messageInfo_Transceivers.Size(m)
+}
+func (m *Transceivers) XXX_DiscardUnknown() {
+ xxx_messageInfo_Transceivers.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Transceivers proto.InternalMessageInfo
+
+func (m *Transceivers) GetItems() []*Transceiver {
+ if m != nil {
+ return m.Items
+ }
+ return nil
+}
+
func init() {
proto.RegisterType((*DmiEvent)(nil), "bbsim.DmiEvent")
- proto.RegisterType((*DmiCreateEventResponse)(nil), "bbsim.DmiCreateEventResponse")
+ proto.RegisterType((*DmiResponse)(nil), "bbsim.DmiResponse")
+ proto.RegisterType((*DmiEmpty)(nil), "bbsim.DmiEmpty")
+ proto.RegisterType((*TransceiverRequest)(nil), "bbsim.TransceiverRequest")
+ proto.RegisterType((*Transceiver)(nil), "bbsim.Transceiver")
+ proto.RegisterType((*Transceivers)(nil), "bbsim.Transceivers")
}
func init() { proto.RegisterFile("api/bbsim/bbsim_dmi.proto", fileDescriptor_49e784b4938902cc) }
var fileDescriptor_49e784b4938902cc = []byte{
- // 216 bytes of a gzipped FileDescriptorProto
- 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x90, 0x31, 0x4b, 0xc5, 0x30,
- 0x14, 0x85, 0x7d, 0xc2, 0x53, 0x7b, 0xdf, 0x20, 0x64, 0x90, 0x2a, 0x3c, 0x94, 0x8a, 0xa0, 0x4b,
- 0x0a, 0xfa, 0x03, 0x84, 0xb6, 0x6e, 0xe2, 0x50, 0x37, 0x97, 0x92, 0x34, 0x97, 0x9a, 0xe1, 0xe6,
- 0x86, 0x26, 0xf5, 0xf7, 0x8b, 0x69, 0xab, 0x0e, 0x6f, 0x09, 0xb9, 0x1f, 0x9c, 0xc3, 0xc7, 0x81,
- 0x4b, 0xe5, 0x6d, 0xa9, 0x75, 0xb0, 0x34, 0xbf, 0x9d, 0x21, 0x2b, 0xfd, 0xc8, 0x91, 0xc5, 0x36,
- 0x81, 0xe2, 0x01, 0xce, 0x1a, 0xb2, 0x2f, 0x5f, 0xe8, 0xa2, 0xd8, 0x03, 0xe0, 0xcf, 0xa7, 0x73,
- 0x8a, 0x30, 0xdf, 0xdc, 0x6c, 0xee, 0xb3, 0x36, 0x4b, 0xe4, 0x4d, 0x11, 0x16, 0xef, 0x70, 0xd1,
- 0x90, 0xad, 0x47, 0x54, 0x11, 0x53, 0xa0, 0xc5, 0xe0, 0xd9, 0x05, 0x14, 0xd7, 0xb0, 0x0b, 0x51,
- 0xc5, 0x29, 0x74, 0x3d, 0x9b, 0x39, 0xb9, 0x6d, 0x61, 0x46, 0x35, 0x1b, 0x14, 0x39, 0x9c, 0x12,
- 0x86, 0xa0, 0x06, 0xcc, 0x8f, 0x53, 0xed, 0x7a, 0x3e, 0xbe, 0x42, 0x56, 0x55, 0x8b, 0x99, 0x78,
- 0x86, 0xdd, 0xbf, 0x7a, 0x71, 0x2e, 0x93, 0xa3, 0x5c, 0x05, 0xaf, 0xf6, 0x7f, 0xe0, 0x80, 0x46,
- 0x71, 0x54, 0xdd, 0x7d, 0xdc, 0x0e, 0x36, 0x7e, 0x4e, 0x5a, 0xf6, 0x4c, 0x25, 0x7b, 0x74, 0x3d,
- 0x8f, 0x66, 0x59, 0xe0, 0x77, 0x0b, 0x7d, 0x92, 0x26, 0x78, 0xfa, 0x0e, 0x00, 0x00, 0xff, 0xff,
- 0xd2, 0x6b, 0xb3, 0x25, 0x1f, 0x01, 0x00, 0x00,
+ // 414 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x92, 0xcd, 0x6e, 0xd4, 0x30,
+ 0x10, 0xc7, 0x9b, 0xdd, 0xee, 0xd2, 0x9d, 0xb0, 0x54, 0x0c, 0x12, 0x72, 0x2b, 0x3e, 0x56, 0x06,
+ 0xa4, 0x70, 0x49, 0xa5, 0xc2, 0x01, 0x38, 0x6e, 0x53, 0x81, 0x2f, 0x50, 0x45, 0xed, 0x85, 0xcb,
+ 0x2a, 0x1f, 0xa3, 0x34, 0x52, 0x6d, 0x87, 0xd8, 0xa9, 0xd4, 0x47, 0xe0, 0x19, 0x78, 0x59, 0x14,
+ 0x3b, 0x4b, 0x53, 0x01, 0xa7, 0x5e, 0xa2, 0xf1, 0x2f, 0x33, 0xe3, 0xff, 0xf8, 0x3f, 0x70, 0x90,
+ 0x35, 0xf5, 0x51, 0x9e, 0x9b, 0x5a, 0xfa, 0xef, 0xa6, 0x94, 0x75, 0xdc, 0xb4, 0xda, 0x6a, 0x9c,
+ 0x39, 0xc0, 0xdf, 0xc2, 0x5e, 0x22, 0xeb, 0xd3, 0x6b, 0x52, 0x16, 0x9f, 0x03, 0x50, 0x1f, 0x6c,
+ 0x54, 0x26, 0x89, 0x05, 0xab, 0x20, 0x5a, 0xa4, 0x0b, 0x47, 0xbe, 0x66, 0x92, 0xf8, 0x17, 0x08,
+ 0x13, 0x59, 0xa7, 0x64, 0x1a, 0xad, 0x0c, 0xe1, 0x4b, 0x08, 0x8d, 0xcd, 0x6c, 0x67, 0x36, 0x85,
+ 0x2e, 0x7d, 0xfa, 0x2c, 0x05, 0x8f, 0x4e, 0x74, 0x49, 0xc8, 0xe0, 0x81, 0x24, 0x63, 0xb2, 0x8a,
+ 0xd8, 0xc4, 0xf5, 0xda, 0x1e, 0x39, 0xf8, 0x4b, 0x65, 0x63, 0x6f, 0xf8, 0x27, 0xc0, 0xf3, 0x36,
+ 0x53, 0xa6, 0xa0, 0xfa, 0x9a, 0xda, 0x94, 0x7e, 0x74, 0x64, 0x2c, 0xbe, 0x86, 0xe5, 0x88, 0x8a,
+ 0xd2, 0xb5, 0x5f, 0xa6, 0x77, 0x21, 0xff, 0x15, 0x40, 0x38, 0x22, 0xf8, 0x08, 0x26, 0x22, 0x19,
+ 0x52, 0x27, 0x22, 0x41, 0x84, 0xdd, 0x8b, 0x0b, 0x91, 0x0c, 0xd7, 0xbb, 0xb8, 0x67, 0xfd, 0x34,
+ 0x6c, 0xea, 0x59, 0x1f, 0xe3, 0x0b, 0x80, 0x73, 0x2a, 0x2e, 0x95, 0xbe, 0xd2, 0xd5, 0x0d, 0xdb,
+ 0x75, 0x7f, 0x46, 0x04, 0x9f, 0xc1, 0xe2, 0xec, 0xaa, 0xab, 0x2a, 0x2a, 0x85, 0x62, 0xb3, 0x55,
+ 0x10, 0xed, 0xa5, 0xb7, 0x00, 0x9f, 0xc2, 0xfc, 0x4c, 0x2b, 0x51, 0x1a, 0x36, 0x5f, 0x4d, 0xa3,
+ 0x65, 0x3a, 0x9c, 0xf8, 0x07, 0x78, 0x38, 0x12, 0x67, 0x30, 0x82, 0x99, 0xb0, 0x24, 0x0d, 0x0b,
+ 0x56, 0xd3, 0x28, 0x3c, 0xc6, 0xd8, 0x39, 0x10, 0x8f, 0xa7, 0xf7, 0x09, 0xc7, 0x3f, 0x27, 0xb0,
+ 0x58, 0xaf, 0x07, 0xbf, 0xf0, 0x3d, 0x84, 0x27, 0x2d, 0x65, 0x96, 0xbc, 0x4b, 0xfb, 0x43, 0xdd,
+ 0xd6, 0xb6, 0x43, 0xbc, 0x05, 0x5b, 0x73, 0xf8, 0x0e, 0x7e, 0x84, 0xfd, 0xcf, 0x64, 0xef, 0x08,
+ 0x18, 0x57, 0xf6, 0x6f, 0x7f, 0xf8, 0xe4, 0x6f, 0x09, 0x86, 0xef, 0xe0, 0x29, 0x60, 0x3f, 0xdd,
+ 0xb7, 0x6e, 0x5c, 0x8e, 0x07, 0xff, 0xd0, 0xeb, 0xdd, 0xfa, 0x8f, 0x82, 0x04, 0x1e, 0xf7, 0x6d,
+ 0x84, 0xba, 0x4f, 0x97, 0xf5, 0x9b, 0xef, 0xaf, 0xaa, 0xda, 0x5e, 0x76, 0x79, 0x5c, 0x68, 0x79,
+ 0xa4, 0x1b, 0x52, 0x85, 0x6e, 0xcb, 0x61, 0xa9, 0xff, 0xac, 0x77, 0x3e, 0x77, 0x5b, 0xfd, 0xee,
+ 0x77, 0x00, 0x00, 0x00, 0xff, 0xff, 0x62, 0xd2, 0xd2, 0x82, 0xf2, 0x02, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
@@ -148,7 +352,12 @@
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type BBsimDmiClient interface {
// Ask the DMI Server to create an event
- CreateEvent(ctx context.Context, in *DmiEvent, opts ...grpc.CallOption) (*DmiCreateEventResponse, error)
+ CreateEvent(ctx context.Context, in *DmiEvent, opts ...grpc.CallOption) (*DmiResponse, error)
+ GetTransceivers(ctx context.Context, in *DmiEmpty, opts ...grpc.CallOption) (*Transceivers, error)
+ // Plug out the transceiver by transceiverId
+ PlugOutTransceiver(ctx context.Context, in *TransceiverRequest, opts ...grpc.CallOption) (*DmiResponse, error)
+ // Plug in the transceiver of a PON by pon-port-ID
+ PlugInTransceiver(ctx context.Context, in *TransceiverRequest, opts ...grpc.CallOption) (*DmiResponse, error)
}
type bBsimDmiClient struct {
@@ -159,8 +368,8 @@
return &bBsimDmiClient{cc}
}
-func (c *bBsimDmiClient) CreateEvent(ctx context.Context, in *DmiEvent, opts ...grpc.CallOption) (*DmiCreateEventResponse, error) {
- out := new(DmiCreateEventResponse)
+func (c *bBsimDmiClient) CreateEvent(ctx context.Context, in *DmiEvent, opts ...grpc.CallOption) (*DmiResponse, error) {
+ out := new(DmiResponse)
err := c.cc.Invoke(ctx, "/bbsim.BBsim_dmi/CreateEvent", in, out, opts...)
if err != nil {
return nil, err
@@ -168,19 +377,60 @@
return out, nil
}
+func (c *bBsimDmiClient) GetTransceivers(ctx context.Context, in *DmiEmpty, opts ...grpc.CallOption) (*Transceivers, error) {
+ out := new(Transceivers)
+ err := c.cc.Invoke(ctx, "/bbsim.BBsim_dmi/GetTransceivers", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *bBsimDmiClient) PlugOutTransceiver(ctx context.Context, in *TransceiverRequest, opts ...grpc.CallOption) (*DmiResponse, error) {
+ out := new(DmiResponse)
+ err := c.cc.Invoke(ctx, "/bbsim.BBsim_dmi/PlugOutTransceiver", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *bBsimDmiClient) PlugInTransceiver(ctx context.Context, in *TransceiverRequest, opts ...grpc.CallOption) (*DmiResponse, error) {
+ out := new(DmiResponse)
+ err := c.cc.Invoke(ctx, "/bbsim.BBsim_dmi/PlugInTransceiver", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
// BBsimDmiServer is the server API for BBsimDmi service.
type BBsimDmiServer interface {
// Ask the DMI Server to create an event
- CreateEvent(context.Context, *DmiEvent) (*DmiCreateEventResponse, error)
+ CreateEvent(context.Context, *DmiEvent) (*DmiResponse, error)
+ GetTransceivers(context.Context, *DmiEmpty) (*Transceivers, error)
+ // Plug out the transceiver by transceiverId
+ PlugOutTransceiver(context.Context, *TransceiverRequest) (*DmiResponse, error)
+ // Plug in the transceiver of a PON by pon-port-ID
+ PlugInTransceiver(context.Context, *TransceiverRequest) (*DmiResponse, error)
}
// UnimplementedBBsimDmiServer can be embedded to have forward compatible implementations.
type UnimplementedBBsimDmiServer struct {
}
-func (*UnimplementedBBsimDmiServer) CreateEvent(ctx context.Context, req *DmiEvent) (*DmiCreateEventResponse, error) {
+func (*UnimplementedBBsimDmiServer) CreateEvent(ctx context.Context, req *DmiEvent) (*DmiResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method CreateEvent not implemented")
}
+func (*UnimplementedBBsimDmiServer) GetTransceivers(ctx context.Context, req *DmiEmpty) (*Transceivers, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method GetTransceivers not implemented")
+}
+func (*UnimplementedBBsimDmiServer) PlugOutTransceiver(ctx context.Context, req *TransceiverRequest) (*DmiResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method PlugOutTransceiver not implemented")
+}
+func (*UnimplementedBBsimDmiServer) PlugInTransceiver(ctx context.Context, req *TransceiverRequest) (*DmiResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method PlugInTransceiver not implemented")
+}
func RegisterBBsimDmiServer(s *grpc.Server, srv BBsimDmiServer) {
s.RegisterService(&_BBsimDmi_serviceDesc, srv)
@@ -204,6 +454,60 @@
return interceptor(ctx, in, info, handler)
}
+func _BBsimDmi_GetTransceivers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(DmiEmpty)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(BBsimDmiServer).GetTransceivers(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/bbsim.BBsim_dmi/GetTransceivers",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(BBsimDmiServer).GetTransceivers(ctx, req.(*DmiEmpty))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _BBsimDmi_PlugOutTransceiver_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(TransceiverRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(BBsimDmiServer).PlugOutTransceiver(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/bbsim.BBsim_dmi/PlugOutTransceiver",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(BBsimDmiServer).PlugOutTransceiver(ctx, req.(*TransceiverRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _BBsimDmi_PlugInTransceiver_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(TransceiverRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(BBsimDmiServer).PlugInTransceiver(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/bbsim.BBsim_dmi/PlugInTransceiver",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(BBsimDmiServer).PlugInTransceiver(ctx, req.(*TransceiverRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
var _BBsimDmi_serviceDesc = grpc.ServiceDesc{
ServiceName: "bbsim.BBsim_dmi",
HandlerType: (*BBsimDmiServer)(nil),
@@ -212,6 +516,18 @@
MethodName: "CreateEvent",
Handler: _BBsimDmi_CreateEvent_Handler,
},
+ {
+ MethodName: "GetTransceivers",
+ Handler: _BBsimDmi_GetTransceivers_Handler,
+ },
+ {
+ MethodName: "PlugOutTransceiver",
+ Handler: _BBsimDmi_PlugOutTransceiver_Handler,
+ },
+ {
+ MethodName: "PlugInTransceiver",
+ Handler: _BBsimDmi_PlugInTransceiver_Handler,
+ },
},
Streams: []grpc.StreamDesc{},
Metadata: "api/bbsim/bbsim_dmi.proto",
diff --git a/api/bbsim/bbsim_dmi.proto b/api/bbsim/bbsim_dmi.proto
index bc89a16..48c7da9 100644
--- a/api/bbsim/bbsim_dmi.proto
+++ b/api/bbsim/bbsim_dmi.proto
@@ -23,13 +23,44 @@
string event_name= 1;
}
-message DmiCreateEventResponse {
+message DmiResponse {
int32 status_code = 1;
string message = 2;
}
+message DmiEmpty {
+}
+
+message TransceiverRequest {
+ uint32 TransceiverId = 1;
+}
+
+message Transceiver{
+ uint32 ID = 1;
+ string UUID = 2;
+ string Name = 3;
+ string Technology = 4;
+ bool PluggedIn = 5;
+ repeated uint32 PonIds = 6;
+}
+
+message Transceivers{
+ repeated Transceiver Items = 1;
+}
+
+
service BBsim_dmi {
// Ask the DMI Server to create an event
- rpc CreateEvent (DmiEvent) returns (DmiCreateEventResponse){
+ rpc CreateEvent (DmiEvent) returns (DmiResponse){
+ }
+
+ rpc GetTransceivers (DmiEmpty) returns (Transceivers) {
+ }
+
+ // Plug out the transceiver by transceiverId
+ rpc PlugOutTransceiver (TransceiverRequest) returns (DmiResponse) {
+ }
+ // Plug in the transceiver of a PON by pon-port-ID
+ rpc PlugInTransceiver (TransceiverRequest) returns (DmiResponse) {
}
}
diff --git a/docs/source/DMI_Server_README.md b/docs/source/DMI_Server_README.md
index ac42994..14aa301 100755
--- a/docs/source/DMI_Server_README.md
+++ b/docs/source/DMI_Server_README.md
@@ -29,27 +29,41 @@
```sh
$ grpcurl -plaintext -d '{"device_uuid": {"uuid": "5295a1d5-a121-372e-b8dc-6f7eda83f0ba"}}' 172.17.0.2:50075 dmi.NativeHWManagementService.GetPhysicalInventory
{
- "status": "OK",
+ "status": "OK_STATUS",
"inventory": {
"lastChange": "1970-01-01T00:00:00Z",
"root": {
- "name": "BBSim-BBSIM_OLT_0",
+ "name": "BBSim-BBSIM_OLT_10",
"children": [
{
- "name": "sfp-plus-transceiver-cage-pon-0"
+ "name": "sfp-plus-transceiver-cage-0",
"class": "COMPONENT_TYPE_CONTAINER",
"description": "cage",
- "parent": "BBSim-BBSIM_OLT_0",
+ "parent": "BBSim-BBSIM_OLT_10",
"children": [
{
- "name": "sfp-0",
+ "name": "sfp-plus-0",
"class": "COMPONENT_TYPE_TRANSCEIVER",
- "description": "XGS-PON",
- "parent": "sfp-plus-transceiver-cage-pon-0",
+ "description": "bbsim-transceiver",
+ "parent": "sfp-plus-transceiver-cage-0",
+ "children": [
+ {
+ "name": "pon-0",
+ "class": "COMPONENT_TYPE_PORT",
+ "description": "bbsim-pon-port",
+ "parent": "sfp-plus-0",
+ "uuid": {
+ "uuid": "38c3cdcc-f428-370b-a08f-8c64a90552e3"
+ },
+ "portAttr": {
+ "protocol": "XGSPON"
+ }
+ }
+ ],
"uuid": {
- "uuid": "788ba741-507f-37b1-8e47-4a389460873b"
+ "uuid": "2d0ab069-f461-34e5-a16a-5ebb1f26b1a7"
},
- "transceiverAttr": {
+ "transceiverAttr": {
"formFactor": "SFP_PLUS",
"transType": "XGSPON",
"maxDistance": 10,
@@ -65,7 +79,7 @@
}
],
"uuid": {
- "uuid": "6bfab16e-8003-3e18-9143-8933df64aa52"
+ "uuid": "2410ab0a-1f17-3326-9708-da5b62b48d85"
}
},
{
@@ -78,7 +92,7 @@
"uuid": "2f4b639c-80a9-340f-b8d8-4ad06580b3cf"
},
"state": {
-
+
}
},
{
@@ -91,7 +105,7 @@
"uuid": "4fb1a981-5697-3813-955d-fbb2a2908b2f"
},
"state": {
-
+
}
},
{
@@ -104,7 +118,7 @@
"uuid": "b1d63346-c0b9-3a29-a4e6-e047efff9ddf"
},
"state": {
-
+
}
},
{
@@ -117,7 +131,7 @@
"uuid": "0bcbe296-9855-3218-9479-9c501073773f"
},
"state": {
-
+
}
},
{
@@ -130,7 +144,7 @@
"uuid": "78cd16fd-73d1-3aad-8f13-644ed3101c63"
},
"state": {
-
+
}
},
{
@@ -143,20 +157,33 @@
"uuid": "b9ada337-63a1-3991-96f5-95416dec1bf0"
},
"state": {
-
+
+ }
+ },
+ {
+ "name": "Thermal/PSU/SystemPSU/0",
+ "class": "COMPONENT_TYPE_POWER_SUPPLY",
+ "description": "bbsim-psu",
+ "serialNum": "bbsim-psu-serial-0",
+ "mfgName": "bbsim-psu",
+ "uuid": {
+ "uuid": "ee5fa7a2-0707-3bfb-90dd-678b2d6711c6"
+ },
+ "state": {
+
}
}
],
- "serialNum": "BBSIM_OLT_0",
+ "serialNum": "BBSIM_OLT_10",
"mfgName": "BBSim",
"uri": {
"uri": "XXX.YYY.ZZZ.AAA"
},
"uuid": {
- "uuid": "5295a1d5-a121-372e-b8dc-6f7eda83f0ba"
+ "uuid": "895f65ab-64a3-3957-a2db-568a168faa3a"
},
"state": {
-
+
}
}
}
@@ -415,13 +442,13 @@
Note : For event names, refer EventIds enum in https://github.com/opencord/device-management-interface/blob/master/protos/dmi/hw_events_mgmt_service.proto .
-$ bsimctl dmi events raise <event_name>
+$ bbsimctl dmi events raise <event_name>
### FAN FAILURE EVENT
.. code:: bash
```
-$ bsimctl dmi events create EVENT_FAN_FAILURE
+$ bbsimctl dmi events create EVENT_FAN_FAILURE
[Status: 0] DMI Event Indication Sent.
```
@@ -429,7 +456,7 @@
.. code:: bash
```
-$ bsimctl dmi events create EVENT_PSU_FAILURE
+$ bbsimctl dmi events create EVENT_PSU_FAILURE
[Status: 0] DMI Event Indication Sent.
```
@@ -437,6 +464,32 @@
.. code:: bash
```
-$ bsimctl dmi events create EVENT_HW_DEVICE_TEMPERATURE_ABOVE_CRITICAL
+$ bbsimctl dmi events create EVENT_HW_DEVICE_TEMPERATURE_ABOVE_CRITICAL
[Status: 0] DMI Event Indication Sent.
+```
+
+## Plug transceivers in or out
+
+Access ``bbsimctl``, as described in the previous section
+
+### List transceivers
+.. code:: bash
+```
+$ bbsimctl dmi transceiver list
+ID UUID NAME TECHNOLOGY PLUGGEDIN PONIDS
+0 2d0ab069-f461-34e5-a16a-5ebb1f26b1a7 sfp-plus-0 XGSPON false [0]
+```
+
+### Plug transceiver out
+.. code:: bash
+```
+$ bbsimctl dmi transceiver plug_out 0
+[Status: 0] Plugged out transceiver 0
+```
+
+### Plug transceiver in
+.. code:: bash
+```
+$ bbsimctl dmi transceiver plug_in 0
+[Status: 0] Plugged in transceiver 0
```
\ No newline at end of file
diff --git a/internal/bbsim/dmiserver/dmi_api_server.go b/internal/bbsim/dmiserver/dmi_api_server.go
index fea52a8..9ad8f94 100755
--- a/internal/bbsim/dmiserver/dmi_api_server.go
+++ b/internal/bbsim/dmiserver/dmi_api_server.go
@@ -18,9 +18,11 @@
import (
"context"
+ "fmt"
"net"
"github.com/opencord/bbsim/api/bbsim"
+ "github.com/opencord/bbsim/internal/bbsim/devices"
"github.com/opencord/bbsim/internal/common"
dmi "github.com/opencord/device-management-interface/go/dmi"
log "github.com/sirupsen/logrus"
@@ -35,19 +37,16 @@
//DmiAPIServer has the attributes for the Server handling the Device Management Interface
type DmiAPIServer struct {
- deviceSerial string
- deviceName string
- ipAddress string
- uuid string
- ponTransceiverUuids []string
- ponTransceiverCageUuids []string
- root *dmi.Component
- metricChannel chan interface{}
- eventChannel chan interface{}
- kafkaEndpoint string
- loggingEndpoint string
- loggingProtocol string
- mPublisherCancelFunc context.CancelFunc
+ ipAddress string
+ uuid *dmi.Uuid
+ root *dmi.Component
+ Transceivers []*Transceiver
+ metricChannel chan interface{}
+ eventChannel chan interface{}
+ kafkaEndpoint string
+ loggingEndpoint string
+ loggingProtocol string
+ mPublisherCancelFunc context.CancelFunc
}
var dmiServ DmiAPIServer
@@ -56,9 +55,27 @@
func StartDmiAPIServer() (*grpc.Server, error) {
dmiServ = DmiAPIServer{}
+ // Create the mapping between transceivers and PONS
+ // TODO: at the moment we create one transceiver for each PON,
+ // but in the case of COMBO PON this will not always be the case.
+ // This should be expanded to cover that scenario
+ logger.Debug("Creating transceivers from DMI")
+ dmiServ.Transceivers = []*Transceiver{}
+ for _, pon := range devices.GetOLT().Pons {
+ trans := newTransceiver(pon.ID, []*devices.PonPort{pon})
+ dmiServ.Transceivers = append(dmiServ.Transceivers, trans)
+ }
+
return dmiServ.newDmiAPIServer()
}
+func getDmiAPIServer() (*DmiAPIServer, error) {
+ if dmiServ.root == nil {
+ return nil, fmt.Errorf("Device management not started")
+ }
+ return &dmiServ, nil
+}
+
// newDmiAPIServer launches a new grpc server for the Device Manager Interface
func (dms *DmiAPIServer) newDmiAPIServer() (*grpc.Server, error) {
address := common.Config.BBSim.DmiServerAddress
diff --git a/internal/bbsim/dmiserver/dmi_event_generator.go b/internal/bbsim/dmiserver/dmi_event_generator.go
index 2a9073e..93aa28f 100644
--- a/internal/bbsim/dmiserver/dmi_event_generator.go
+++ b/internal/bbsim/dmiserver/dmi_event_generator.go
@@ -57,6 +57,14 @@
componentType: dmi.ComponentType_COMPONENT_TYPE_FAN,
genFunc: noThresholdEventGenerationFunc,
}
+ eventGenMap[dmi.EventIds_EVENT_TRANSCEIVER_PLUG_IN] = eventGenerationUtil{
+ componentType: dmi.ComponentType_COMPONENT_TYPE_TRANSCEIVER,
+ genFunc: noThresholdEventGenerationFunc,
+ }
+ eventGenMap[dmi.EventIds_EVENT_TRANSCEIVER_PLUG_OUT] = eventGenerationUtil{
+ componentType: dmi.ComponentType_COMPONENT_TYPE_TRANSCEIVER,
+ genFunc: noThresholdEventGenerationFunc,
+ }
eventGenMap[dmi.EventIds_EVENT_PSU_FAILURE] = eventGenerationUtil{
componentType: dmi.ComponentType_COMPONENT_TYPE_POWER_SUPPLY,
@@ -113,6 +121,16 @@
EventId: dmi.EventIds_EVENT_PSU_FAILURE,
IsConfigured: true,
}
+
+ // Add Transceiver Plug in and out event configuration
+ dmiEG.configuredEvents[dmi.EventIds_EVENT_TRANSCEIVER_PLUG_IN] = dmi.EventCfg{
+ EventId: dmi.EventIds_EVENT_TRANSCEIVER_PLUG_IN,
+ IsConfigured: true,
+ }
+ dmiEG.configuredEvents[dmi.EventIds_EVENT_TRANSCEIVER_PLUG_OUT] = dmi.EventCfg{
+ EventId: dmi.EventIds_EVENT_TRANSCEIVER_PLUG_OUT,
+ IsConfigured: true,
+ }
}
// get the events list
@@ -146,9 +164,7 @@
// update Event MetaData
func updateEventMetaData(c *dmi.Component, apiSrv *DmiAPIServer, evt *dmi.Event) *dmi.Event {
evt.EventMetadata = &dmi.EventMetaData{
- DeviceUuid: &dmi.Uuid{
- Uuid: apiSrv.uuid,
- },
+ DeviceUuid: apiSrv.uuid,
ComponentUuid: c.Uuid,
ComponentName: c.Name,
}
@@ -212,9 +228,9 @@
}
// CreateEvent creates and the passed event if it's valid and sends it to the msg bus
-func (dms *DmiAPIServer) CreateEvent(ctx context.Context, evt *bbsim.DmiEvent) (*bbsim.DmiCreateEventResponse, error) {
- retFunc := func(code codes.Code, msg string) (*bbsim.DmiCreateEventResponse, error) {
- res := &bbsim.DmiCreateEventResponse{}
+func (dms *DmiAPIServer) CreateEvent(ctx context.Context, evt *bbsim.DmiEvent) (*bbsim.DmiResponse, error) {
+ retFunc := func(code codes.Code, msg string) (*bbsim.DmiResponse, error) {
+ res := &bbsim.DmiResponse{}
res.StatusCode = int32(code)
res.Message = msg
return res, nil
@@ -222,7 +238,7 @@
if dmiEG.apiSrv == nil || dmiEG.apiSrv.root == nil || dmiEG.apiSrv.root.Children == nil {
// inventory might not yet be created
- return retFunc(codes.Internal, "inventory do no exist")
+ return retFunc(codes.Internal, "Inventory does not exist")
}
eventID, exists := dmi.EventIds_value[evt.EventName]
diff --git a/internal/bbsim/dmiserver/dmi_hw_mgmt.go b/internal/bbsim/dmiserver/dmi_hw_mgmt.go
index 06c078f..00e4a92 100755
--- a/internal/bbsim/dmiserver/dmi_hw_mgmt.go
+++ b/internal/bbsim/dmiserver/dmi_hw_mgmt.go
@@ -21,6 +21,7 @@
"fmt"
"github.com/Shopify/sarama"
+ log "github.com/sirupsen/logrus"
"github.com/golang/protobuf/ptypes/empty"
"github.com/golang/protobuf/ptypes/timestamp"
@@ -41,6 +42,46 @@
return guuid.NewMD5(guuid.Nil, []byte(seed)).String()
}
+func getOltName() string {
+ return fmt.Sprintf("%s-%s", common.Config.Olt.Vendor, devices.GetOLT().SerialNumber)
+}
+
+func getOltUUID() *dmi.Uuid {
+ return &dmi.Uuid{
+ Uuid: getUUID(devices.GetOLT().SerialNumber),
+ }
+}
+
+func getCageName(id uint32) string {
+ return fmt.Sprintf("sfp-plus-transceiver-cage-%d", id)
+}
+
+func getCageUUID(id uint32) *dmi.Uuid {
+ return &dmi.Uuid{
+ Uuid: getUUID(fmt.Sprintf("%s-%s", devices.GetOLT().SerialNumber, getCageName(id))),
+ }
+}
+
+func getTransceiverName(id uint32) string {
+ return fmt.Sprintf("sfp-plus-%d", id)
+}
+
+func getTransceiverUUID(id uint32) *dmi.Uuid {
+ return &dmi.Uuid{
+ Uuid: getUUID(fmt.Sprintf("%s-%s", devices.GetOLT().SerialNumber, getTransceiverName(id))),
+ }
+}
+
+func getPonName(id uint32) string {
+ return fmt.Sprintf("pon-%d", id)
+}
+
+func getPonUUID(id uint32) *dmi.Uuid {
+ return &dmi.Uuid{
+ Uuid: getUUID(fmt.Sprintf("%s-%s", devices.GetOLT().SerialNumber, getPonName(id))),
+ }
+}
+
//StartManagingDevice establishes connection with the device and does checks to ascertain if the device with passed identity can be managed
func (dms *DmiAPIServer) StartManagingDevice(req *dmi.ModifiableComponent, stream dmi.NativeHWManagementService_StartManagingDeviceServer) error {
//Get serial number and generate the UUID based on this serial number. Store this UUID in local cache
@@ -57,13 +98,9 @@
// Uri is the IP address
dms.ipAddress = req.GetUri().GetUri()
- dms.deviceSerial = olt.SerialNumber
- dms.deviceName = fmt.Sprintf("%s-%s", common.Config.Olt.Vendor, dms.deviceSerial)
- dms.uuid = getUUID(dms.deviceSerial)
-
- dms.ponTransceiverUuids = make([]string, olt.NumPon)
- dms.ponTransceiverCageUuids = make([]string, olt.NumPon)
+ deviceName := getOltName()
+ dms.uuid = getOltUUID()
// Start device metrics generator
dms.metricChannel = make(chan interface{}, kafkaChannelSize)
@@ -76,57 +113,27 @@
var components []*dmi.Component
// Create and store the component for transceivers and transceiver cages
- for i, pon := range olt.Pons {
- label := fmt.Sprintf("pon-%d", pon.ID)
- dms.ponTransceiverUuids[i] = getUUID(dms.deviceSerial + label)
- dms.ponTransceiverCageUuids[i] = getUUID(dms.deviceSerial + "cage" + label)
-
- transName := fmt.Sprintf("sfp-%d", i)
- cageName := fmt.Sprintf("sfp-plus-transceiver-cage-pon-%d", i)
-
- var transType dmi.TransceiverType
- var rxWavelength, txWavelength []uint32
- switch pon.Technology {
- case common.GPON:
- transType = dmi.TransceiverType_GPON
- rxWavelength = []uint32{1490} // nanometers
- txWavelength = []uint32{1550} // nanometers
- case common.XGSPON:
- transType = dmi.TransceiverType_XGSPON
- rxWavelength = []uint32{1270} // nanometers
- txWavelength = []uint32{1577} // nanometers
- }
-
- trans := dmi.Component{
- Name: transName,
- Class: dmi.ComponentType_COMPONENT_TYPE_TRANSCEIVER,
- Description: pon.Technology.String(),
- Uuid: &dmi.Uuid{
- Uuid: dms.ponTransceiverUuids[i],
- },
- Parent: cageName,
- Specific: &dmi.Component_TransceiverAttr{
- TransceiverAttr: &dmi.TransceiverComponentsAttributes{
- FormFactor: dmi.TransceiverComponentsAttributes_SFP_PLUS,
- TransType: transType,
- MaxDistance: 10, // kilometers (see scale below)
- MaxDistanceScale: dmi.ValueScale_VALUE_SCALE_KILO,
- RxWavelength: rxWavelength,
- TxWavelength: txWavelength,
- WavelengthScale: dmi.ValueScale_VALUE_SCALE_NANO,
- },
- },
- }
+ for _, trans := range dms.Transceivers {
+ //Make one cage for each of the transceivers
+ cageName := getCageName(trans.ID)
cage := dmi.Component{
Name: cageName,
Class: dmi.ComponentType_COMPONENT_TYPE_CONTAINER,
Description: "cage",
- Uuid: &dmi.Uuid{
- Uuid: dms.ponTransceiverCageUuids[i],
- },
- Parent: dms.deviceName,
- Children: []*dmi.Component{&trans},
+ Uuid: getCageUUID(trans.ID),
+ Parent: deviceName,
+ Children: []*dmi.Component{},
+ }
+
+ //If the transceiver is not plugged in, only the empty cage is created
+ if trans.PluggedIn {
+ transComponent, err := createTransceiverComponent(trans, cageName)
+ if err != nil {
+ logger.Error(err)
+ continue
+ }
+ cage.Children = append(cage.Children, transComponent)
}
components = append(components, &cage)
@@ -150,30 +157,26 @@
// create the root component
dms.root = &dmi.Component{
- Name: dms.deviceName,
+ Name: deviceName,
Class: 0,
Description: "",
Parent: "",
ParentRelPos: 0,
Children: components,
- SerialNum: dms.deviceSerial,
+ SerialNum: olt.SerialNumber,
MfgName: common.Config.Olt.Vendor,
IsFru: false,
Uri: &dmi.Uri{
Uri: dms.ipAddress,
},
- Uuid: &dmi.Uuid{
- Uuid: dms.uuid,
- },
+ Uuid: dms.uuid,
State: &dmi.ComponentState{},
}
- logger.Debugf("Generated UUID for the uri %s is %s", dms.ipAddress, dms.uuid)
+ logger.Debugf("Generated UUID for the uri %s is %s", dms.ipAddress, dms.uuid.Uuid)
response := &dmi.StartManagingDeviceResponse{
- Status: dmi.Status_OK_STATUS,
- DeviceUuid: &dmi.Uuid{
- Uuid: dms.uuid,
- },
+ Status: dmi.Status_OK_STATUS,
+ DeviceUuid: dms.uuid,
}
err := stream.Send(response)
@@ -185,6 +188,90 @@
return nil
}
+func createTransceiverComponent(trans *Transceiver, cageName string) (*dmi.Component, error) {
+ portName := getPonName(trans.ID)
+
+ var rxWavelength, txWavelength []uint32
+
+ if len(trans.Pons) == 0 {
+ return nil, fmt.Errorf("No pons in list for transceiver %d", trans.ID)
+ } else if len(trans.Pons) <= 1 {
+ //Assuming a transceiver with only one PON
+ //has the technology of the PON
+
+ switch trans.Pons[0].Technology {
+ case common.GPON:
+ trans.Technology = dmi.TransceiverType_GPON
+ rxWavelength = []uint32{1490} // nanometers
+ txWavelength = []uint32{1550} // nanometers
+ case common.XGSPON:
+ trans.Technology = dmi.TransceiverType_XGSPON
+ rxWavelength = []uint32{1270} // nanometers
+ txWavelength = []uint32{1577} // nanometers
+ }
+ } else {
+ //Assuming more than one PON for the transceiver
+ //is COMBO PON
+
+ trans.Technology = dmi.TransceiverType_COMBO_GPON_XGSPON
+
+ rxWavelength = []uint32{1490, 1270} // nanometers
+ txWavelength = []uint32{1550, 1577} // nanometers
+ }
+
+ //Create all ports mapped to this transceiver
+ ports := []*dmi.Component{}
+ for _, pon := range trans.Pons {
+ var portProto dmi.PortComponentAttributes_Protocol
+
+ switch pon.Technology {
+ case common.GPON:
+ portProto = dmi.PortComponentAttributes_GPON
+ case common.XGSPON:
+ portProto = dmi.PortComponentAttributes_XGSPON
+ }
+
+ p := dmi.Component{
+ Name: portName,
+ Class: dmi.ComponentType_COMPONENT_TYPE_PORT,
+ Description: "bbsim-pon-port",
+ Uuid: getPonUUID(pon.ID),
+ Parent: trans.Name,
+ Specific: &dmi.Component_PortAttr{
+ PortAttr: &dmi.PortComponentAttributes{
+ Protocol: portProto,
+ },
+ },
+ }
+
+ ports = append(ports, &p)
+ }
+
+ transComponent := dmi.Component{
+ Name: trans.Name,
+ Class: dmi.ComponentType_COMPONENT_TYPE_TRANSCEIVER,
+ Description: "bbsim-transceiver",
+ Uuid: &dmi.Uuid{
+ Uuid: trans.Uuid,
+ },
+ Parent: cageName,
+ Specific: &dmi.Component_TransceiverAttr{
+ TransceiverAttr: &dmi.TransceiverComponentsAttributes{
+ FormFactor: dmi.TransceiverComponentsAttributes_SFP_PLUS,
+ TransType: trans.Technology,
+ MaxDistance: 10, // kilometers (see scale below)
+ MaxDistanceScale: dmi.ValueScale_VALUE_SCALE_KILO,
+ RxWavelength: rxWavelength,
+ TxWavelength: txWavelength,
+ WavelengthScale: dmi.ValueScale_VALUE_SCALE_NANO,
+ },
+ },
+ Children: ports,
+ }
+
+ return &transComponent, nil
+}
+
func createFanComponent(fanIdx int) *dmi.Component {
fanName := fmt.Sprintf("Thermal/Fans/System Fan/%d", fanIdx)
fanSerial := fmt.Sprintf("bbsim-fan-serial-%d", fanIdx)
@@ -299,6 +386,115 @@
}
}
+func PlugoutTransceiverComponent(transId uint32, dms *DmiAPIServer) error {
+ if dms == nil {
+ return fmt.Errorf("Nil API server")
+ }
+
+ if dms.root == nil {
+ return fmt.Errorf("Device management not started")
+ }
+
+ trans, err := getTransceiverWithId(transId, dms)
+ if err != nil {
+ return err
+ }
+
+ if !trans.PluggedIn {
+ return fmt.Errorf("Cannot plug out transceiver with ID %d since it's not plugged in", transId)
+ }
+
+ //Find the transceiver node in the tree
+ targetUuid := getTransceiverUUID(transId)
+
+ var targetCage *dmi.Component
+ targetTransIndex := -1
+
+loop:
+ for _, rootChild := range dms.root.Children {
+ if rootChild.Uuid.Uuid == getCageUUID(transId).Uuid {
+ currentCage := rootChild
+
+ for j, cageChild := range currentCage.Children {
+ if cageChild.Uuid.Uuid == targetUuid.Uuid {
+ targetCage = currentCage
+ targetTransIndex = j
+ break loop
+ }
+ }
+ }
+ }
+
+ if targetCage == nil || targetTransIndex == -1 {
+ return fmt.Errorf("Cannot find transceiver with id %d", transId)
+ }
+
+ //Remove transceiver
+ targetCage.Children = append(targetCage.Children[:targetTransIndex], targetCage.Children[targetTransIndex+1:]...)
+ logger.WithFields(log.Fields{
+ "transId": transId,
+ "cageName": targetCage.Name,
+ "cageChildren": targetCage.Children,
+ }).Debug("Removed transceiver from DMI inventory")
+
+ //Change plugged-in state
+ trans.PluggedIn = false
+
+ return nil
+}
+
+func PluginTransceiverComponent(transId uint32, dms *DmiAPIServer) error {
+ if dms == nil {
+ return fmt.Errorf("Nil API server")
+ }
+
+ if dms.root == nil {
+ return fmt.Errorf("Device management not started")
+ }
+
+ trans, err := getTransceiverWithId(transId, dms)
+ if err != nil {
+ return err
+ }
+
+ if trans.PluggedIn {
+ return fmt.Errorf("Cannot plug in transceiver with ID %d since it's already plugged in", transId)
+ }
+
+ //Find transceiver node in the tree
+ var targetCage *dmi.Component
+
+ for _, rootChild := range dms.root.Children {
+ if rootChild.Uuid.Uuid == getCageUUID(transId).Uuid {
+ targetCage = rootChild
+ break
+ }
+ }
+
+ if targetCage == nil {
+ return fmt.Errorf("Cannot find cage for transceiver with id %d", transId)
+ }
+
+ //Add transceiver
+ transComponent, err := createTransceiverComponent(trans, targetCage.Name)
+ if err != nil {
+ return err
+ }
+
+ targetCage.Children = append(targetCage.Children, transComponent)
+
+ logger.WithFields(log.Fields{
+ "transId": transId,
+ "cageName": targetCage.Name,
+ "cageChildren": targetCage.Children,
+ }).Debug("Added transceiver to DMI inventory")
+
+ //Change plugged-in state
+ trans.PluggedIn = true
+
+ return nil
+}
+
//StopManagingDevice stops management of a device and cleans up any context and caches for that device
func (dms *DmiAPIServer) StopManagingDevice(ctx context.Context, req *dmi.StopManagingDeviceRequest) (*dmi.StopManagingDeviceResponse, error) {
logger.Debugf("StopManagingDevice API invoked")
@@ -318,16 +514,15 @@
dms.mPublisherCancelFunc()
}
- dms.deviceName = ""
dms.kafkaEndpoint = ""
dms.ipAddress = ""
- dms.deviceSerial = ""
- dms.ponTransceiverUuids = nil
- dms.ponTransceiverCageUuids = nil
- dms.uuid = ""
+ dms.uuid = nil
dms.root = nil
dms.metricChannel = nil
+ //Don't clear the Transceivers, so that they will survive
+ //new StartManagingDevice calls
+
logger.Infof("Stopped managing the device")
return &dmi.StopManagingDeviceResponse{Status: dmi.Status_OK_STATUS}, nil
}
@@ -348,8 +543,8 @@
return nil
}
- if req.DeviceUuid.Uuid != dms.uuid {
- logger.Errorf("Requested uuid =%s, uuid of existing device = %s", req.DeviceUuid.Uuid, dms.uuid)
+ if req.DeviceUuid.Uuid != dms.uuid.Uuid {
+ logger.Errorf("Requested uuid =%s, uuid of existing device = %s", req.DeviceUuid.Uuid, dms.uuid.Uuid)
// Wrong uuid, return error
errResponse := &dmi.PhysicalInventoryResponse{
Status: dmi.Status_ERROR_STATUS,
@@ -490,7 +685,7 @@
if request.LoggingProtocol == "" {
return errRetFunc(dmi.Status_ERROR_STATUS, dmi.SetRemoteEndpointResponse_LOGGING_ENDPOINT_PROTOCOL_ERROR)
}
- if request.DeviceUuid == nil || request.DeviceUuid.Uuid != dms.uuid {
+ if request.DeviceUuid == nil || request.DeviceUuid.Uuid != dms.uuid.Uuid {
return errRetFunc(dmi.Status_ERROR_STATUS, dmi.SetRemoteEndpointResponse_UNKNOWN_DEVICE)
}
@@ -511,7 +706,7 @@
Reason: dmi.GetLoggingEndpointResponse_UNKNOWN_DEVICE,
}, status.Errorf(codes.InvalidArgument, "invalid request")
}
- if request.Uuid.Uuid != dms.uuid {
+ if request.Uuid.Uuid != dms.uuid.Uuid {
return &dmi.GetLoggingEndpointResponse{
Status: dmi.Status_ERROR_STATUS,
Reason: dmi.GetLoggingEndpointResponse_UNKNOWN_DEVICE,
@@ -578,17 +773,15 @@
func (dms *DmiAPIServer) GetManagedDevices(context.Context, *empty.Empty) (*dmi.ManagedDevicesResponse, error) {
retResponse := dmi.ManagedDevicesResponse{}
//If our uuid is empty, we return empty list; else we fill details and return
- if dms.uuid != "" {
+ if dms.root != nil {
root := dmi.ManagedDeviceInfo{
Info: &dmi.ModifiableComponent{
- Name: dms.deviceName,
+ Name: getOltName(),
Uri: &dmi.Uri{
Uri: dms.ipAddress,
},
},
- DeviceUuid: &dmi.Uuid{
- Uuid: dms.uuid,
- },
+ DeviceUuid: dms.uuid,
}
retResponse.Devices = append(retResponse.Devices, &root)
@@ -601,32 +794,26 @@
//GetLogLevel Gets the configured log level for a certain entity on a certain device.
func (dms *DmiAPIServer) GetLogLevel(context.Context, *dmi.GetLogLevelRequest) (*dmi.GetLogLevelResponse, error) {
return &dmi.GetLogLevelResponse{
- Status: dmi.Status_OK_STATUS,
- DeviceUuid: &dmi.Uuid{
- Uuid: dms.uuid,
- },
- LogLevels: []*dmi.EntitiesLogLevel{},
+ Status: dmi.Status_OK_STATUS,
+ DeviceUuid: dms.uuid,
+ LogLevels: []*dmi.EntitiesLogLevel{},
}, nil
}
// SetLogLevel Sets the log level of the device, for each given entity to a certain level.
func (dms *DmiAPIServer) SetLogLevel(context.Context, *dmi.SetLogLevelRequest) (*dmi.SetLogLevelResponse, error) {
return &dmi.SetLogLevelResponse{
- Status: dmi.Status_OK_STATUS,
- DeviceUuid: &dmi.Uuid{
- Uuid: dms.uuid,
- },
+ Status: dmi.Status_OK_STATUS,
+ DeviceUuid: dms.uuid,
}, nil
}
// GetLoggableEntities Gets the entities of a device on which log can be configured.
func (dms *DmiAPIServer) GetLoggableEntities(context.Context, *dmi.GetLoggableEntitiesRequest) (*dmi.GetLogLevelResponse, error) {
return &dmi.GetLogLevelResponse{
- Status: dmi.Status_OK_STATUS,
- DeviceUuid: &dmi.Uuid{
- Uuid: dms.uuid,
- },
- LogLevels: []*dmi.EntitiesLogLevel{},
+ Status: dmi.Status_OK_STATUS,
+ DeviceUuid: dms.uuid,
+ LogLevels: []*dmi.EntitiesLogLevel{},
}, nil
}
diff --git a/internal/bbsim/dmiserver/dmi_metrics_generator.go b/internal/bbsim/dmiserver/dmi_metrics_generator.go
index fdb5bb4..c76e940 100755
--- a/internal/bbsim/dmiserver/dmi_metrics_generator.go
+++ b/internal/bbsim/dmiserver/dmi_metrics_generator.go
@@ -238,9 +238,7 @@
func updateMetricIDAndMetaData(id dmi.MetricNames, c *dmi.Component, apiSrv *DmiAPIServer, m *dmi.Metric) *dmi.Metric {
m.MetricId = id
m.MetricMetadata = &dmi.MetricMetaData{
- DeviceUuid: &dmi.Uuid{
- Uuid: apiSrv.uuid,
- },
+ DeviceUuid: apiSrv.uuid,
ComponentUuid: c.Uuid,
ComponentName: c.Name,
}
diff --git a/internal/bbsim/dmiserver/dmi_sw_mgmt.go b/internal/bbsim/dmiserver/dmi_sw_mgmt.go
index 0c89d42..934b41d 100755
--- a/internal/bbsim/dmiserver/dmi_sw_mgmt.go
+++ b/internal/bbsim/dmiserver/dmi_sw_mgmt.go
@@ -98,7 +98,7 @@
return status.Errorf(codes.InvalidArgument, "ConfigRequest is nil")
}
- if request.DeviceUuid == nil || request.DeviceUuid.Uuid != dms.uuid {
+ if request.DeviceUuid == nil || request.DeviceUuid.Uuid != dms.uuid.Uuid {
if err := stream.Send(&dmi.ConfigResponse{
Status: dmi.Status_ERROR_STATUS,
Reason: dmi.ConfigResponse_UNKNOWN_DEVICE,
@@ -129,7 +129,7 @@
return nil, status.Errorf(codes.InvalidArgument, "DeviceUuid is nil")
}
- if request.DeviceUuid.Uuid != dms.uuid {
+ if request.DeviceUuid.Uuid != dms.uuid.Uuid {
return &dmi.StartupConfigInfoResponse{
Status: dmi.Status_ERROR_STATUS,
Reason: dmi.StartupConfigInfoResponse_UNKNOWN_DEVICE,
diff --git a/internal/bbsim/dmiserver/dmi_transceiver.go b/internal/bbsim/dmiserver/dmi_transceiver.go
new file mode 100644
index 0000000..5dcc9b0
--- /dev/null
+++ b/internal/bbsim/dmiserver/dmi_transceiver.go
@@ -0,0 +1,283 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+
+ * 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 dmiserver
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/opencord/bbsim/api/bbsim"
+ "github.com/opencord/bbsim/internal/bbsim/devices"
+ dmi "github.com/opencord/device-management-interface/go/dmi"
+ log "github.com/sirupsen/logrus"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/protobuf/types/known/timestamppb"
+)
+
+const (
+ ponInterfaceType = "pon"
+ alarmStatusRaise = "on"
+ alarmStatusClear = "off"
+)
+
+type Transceiver struct {
+ ID uint32
+ Uuid string
+ Name string
+ Pons []*devices.PonPort
+ Technology dmi.TransceiverType
+ //Setting this bool will prevent the transceiver
+ //from being plugged out while already out, and
+ //plugged in while already in, but won't prevent
+ //the associated PONs from being enabled in other
+ //ways while the transceiver is plugged out
+ PluggedIn bool
+}
+
+func newTransceiver(id uint32, pons []*devices.PonPort) *Transceiver {
+ return &Transceiver{
+ ID: id,
+ Uuid: getTransceiverUUID(id).Uuid,
+ Name: getTransceiverName(id),
+ Pons: pons,
+ Technology: dmi.TransceiverType_TYPE_UNDEFINED,
+ PluggedIn: true,
+ }
+}
+
+func getTransceiverWithId(transId uint32, dms *DmiAPIServer) (*Transceiver, error) {
+ for _, t := range dms.Transceivers {
+ if t.ID == transId {
+ return t, nil
+ }
+ }
+
+ return nil, fmt.Errorf("Cannot find transceiver with ID %d", transId)
+}
+
+/////// Handler methods for grpc API
+
+func (s DmiAPIServer) GetTransceivers(ctx context.Context, req *bbsim.DmiEmpty) (*bbsim.Transceivers, error) {
+ res := &bbsim.Transceivers{
+ Items: []*bbsim.Transceiver{},
+ }
+
+ for _, t := range s.Transceivers {
+ item := bbsim.Transceiver{
+ ID: t.ID,
+ UUID: t.Uuid,
+ Name: t.Name,
+ Technology: t.Technology.String(),
+ PluggedIn: t.PluggedIn,
+ PonIds: []uint32{},
+ }
+
+ for _, pon := range t.Pons {
+ item.PonIds = append(item.PonIds, pon.ID)
+ }
+
+ res.Items = append(res.Items, &item)
+ }
+
+ return res, nil
+}
+
+// PlugOutTransceiver plugs out the transceiver by its ID
+func (s DmiAPIServer) PlugOutTransceiver(ctx context.Context, req *bbsim.TransceiverRequest) (*bbsim.DmiResponse, error) {
+ logger.WithFields(log.Fields{
+ "IntfId": req.TransceiverId,
+ }).Infof("Received request to plug out PON transceiver")
+
+ res := &bbsim.DmiResponse{}
+ olt := devices.GetOLT()
+
+ //Generate DMI event
+ dmiServ, err := getDmiAPIServer()
+ if err != nil {
+ res.StatusCode = int32(codes.Unavailable)
+ res.Message = fmt.Sprintf("Cannot get DMI server instance: %v", err)
+ return res, nil
+ }
+
+ trans, err := getTransceiverWithId(req.TransceiverId, dmiServ)
+ if err != nil {
+ res.StatusCode = int32(codes.NotFound)
+ res.Message = fmt.Sprintf("Cannot find transceiver with ID %d: %v", req.TransceiverId, err)
+ return res, nil
+ }
+
+ if !trans.PluggedIn {
+ res.StatusCode = int32(codes.Aborted)
+ res.Message = fmt.Sprintf("Cannot plug out transceiver with ID %d since it's not plugged in", req.TransceiverId)
+ return res, nil
+ }
+
+ err = PlugoutTransceiverComponent(req.TransceiverId, dmiServ)
+ if err != nil {
+ res.StatusCode = int32(codes.NotFound)
+ res.Message = fmt.Sprintf("Cannot remove transceiver with ID %d: %v", req.TransceiverId, err)
+ return res, nil
+ }
+ logger.Debug("Removed transceiver from DMI inventory")
+
+ if olt.InternalState.Is(devices.OltInternalStateEnabled) {
+ logger.Debug("Sending alarms for transceiver plug out")
+ for _, pon := range trans.Pons {
+ if pon.InternalState.Is("enabled") {
+
+ if err = olt.SetAlarm(pon.ID, ponInterfaceType, alarmStatusRaise); err != nil {
+ logger.WithFields(log.Fields{
+ "ponId": pon.ID,
+ "err": err,
+ }).Error("Cannot raise LOS alarm for PON")
+ }
+
+ if err = pon.InternalState.Event("disable"); err != nil {
+ logger.WithFields(log.Fields{
+ "ponId": pon.ID,
+ "err": err,
+ }).Error("Cannot disable PON")
+ continue
+ }
+
+ for _, onu := range pon.Onus {
+ if err := onu.SetAlarm(bbsim.AlarmType_ONU_ALARM_LOS.String(), alarmStatusRaise); err != nil {
+ logger.WithFields(log.Fields{
+ "ponId": pon.ID,
+ "onuId": onu.ID,
+ "err": err,
+ }).Error("Cannot raise LOS alarm for ONU")
+ }
+ }
+ }
+ }
+ } else {
+ logger.Debug("No operation on devices since the OLT is not enabled")
+ }
+
+ event := dmi.Event{
+ EventId: dmi.EventIds_EVENT_TRANSCEIVER_PLUG_OUT,
+ EventMetadata: &dmi.EventMetaData{
+ DeviceUuid: dmiServ.uuid,
+ ComponentUuid: &dmi.Uuid{
+ Uuid: trans.Uuid,
+ },
+ ComponentName: trans.Name,
+ },
+ RaisedTs: timestamppb.Now(),
+ }
+
+ sendOutEventOnKafka(event, dmiServ)
+ logger.Debug("Transceiver plug out event sent")
+
+ res.StatusCode = int32(codes.OK)
+ res.Message = fmt.Sprintf("Plugged out transceiver %d", req.TransceiverId)
+
+ return res, nil
+}
+
+// PlugInTransceiver plugs in the transceiver by its ID
+func (s DmiAPIServer) PlugInTransceiver(ctx context.Context, req *bbsim.TransceiverRequest) (*bbsim.DmiResponse, error) {
+ logger.WithFields(log.Fields{
+ "IntfId": req.TransceiverId,
+ }).Infof("Received request to plug in PON transceiver")
+
+ res := &bbsim.DmiResponse{}
+ olt := devices.GetOLT()
+
+ //Generate DMI event
+ dmiServ, err := getDmiAPIServer()
+ if err != nil {
+ res.StatusCode = int32(codes.Unavailable)
+ res.Message = fmt.Sprintf("Cannot get DMI server instance: %v", err)
+ return res, nil
+ }
+
+ trans, err := getTransceiverWithId(req.TransceiverId, dmiServ)
+ if err != nil {
+ res.StatusCode = int32(codes.NotFound)
+ res.Message = fmt.Sprintf("Cannot find transceiver with ID %d: %v", req.TransceiverId, err)
+ return res, nil
+ }
+
+ if trans.PluggedIn {
+ res.StatusCode = int32(codes.Aborted)
+ res.Message = fmt.Sprintf("Cannot plug in transceiver with ID %d since it's already plugged in", req.TransceiverId)
+ return res, nil
+ }
+
+ err = PluginTransceiverComponent(req.TransceiverId, dmiServ)
+ if err != nil {
+ res.StatusCode = int32(codes.NotFound)
+ res.Message = fmt.Sprintf("Cannot add transceiver with ID %d: %v", req.TransceiverId, err)
+ return res, nil
+ }
+ logger.Debug("Added transceiver to DMI inventory")
+
+ if olt.InternalState.Is(devices.OltInternalStateEnabled) {
+ logger.Debug("Sending alarms for transceiver plug in")
+ for _, pon := range trans.Pons {
+
+ if err = olt.SetAlarm(pon.ID, ponInterfaceType, alarmStatusClear); err != nil {
+ logger.WithFields(log.Fields{
+ "ponId": pon.ID,
+ "err": err,
+ }).Error("Cannot clear LOS alarm for ONU")
+ }
+
+ if err = pon.InternalState.Event("enable"); err != nil {
+ logger.WithFields(log.Fields{
+ "ponId": pon.ID,
+ "err": err,
+ }).Error("Cannot enable PON")
+ continue
+ }
+
+ for _, onu := range pon.Onus {
+ if err := onu.SetAlarm(bbsim.AlarmType_ONU_ALARM_LOS.String(), alarmStatusClear); err != nil {
+ logger.WithFields(log.Fields{
+ "ponId": pon.ID,
+ "onuId": onu.ID,
+ "err": err,
+ }).Error("Cannot clear LOS alarm for ONU")
+ }
+ }
+ }
+ } else {
+ logger.Debug("No operation on devices since the OLT is not enabled")
+ }
+
+ event := dmi.Event{
+ EventId: dmi.EventIds_EVENT_TRANSCEIVER_PLUG_IN,
+ EventMetadata: &dmi.EventMetaData{
+ DeviceUuid: dmiServ.uuid,
+ ComponentUuid: &dmi.Uuid{
+ Uuid: trans.Uuid,
+ },
+ ComponentName: trans.Name,
+ },
+ RaisedTs: timestamppb.Now(),
+ }
+
+ sendOutEventOnKafka(event, dmiServ)
+ logger.Debug("Transceiver plug in event sent")
+
+ res.StatusCode = int32(codes.OK)
+ res.Message = fmt.Sprintf("Plugged in transceiver %d", req.TransceiverId)
+
+ return res, nil
+}
diff --git a/internal/bbsimctl/commands/dmi.go b/internal/bbsimctl/commands/dmi.go
new file mode 100644
index 0000000..526cbad
--- /dev/null
+++ b/internal/bbsimctl/commands/dmi.go
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+
+ * 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 commands
+
+import (
+ "context"
+ "fmt"
+ "os"
+
+ "github.com/jessevdk/go-flags"
+ "github.com/opencord/bbsim/api/bbsim"
+ pb "github.com/opencord/bbsim/api/bbsim"
+ "github.com/opencord/bbsim/internal/bbsimctl/config"
+ "github.com/opencord/cordctl/pkg/format"
+ log "github.com/sirupsen/logrus"
+ "google.golang.org/grpc"
+)
+
+const (
+ DEFAULT_TRANSCEIVER_HEADER_FORMAT = "table{{ .ID }}\t{{ .UUID }}\t{{ .Name }}\t{{ .Technology }}\t{{ .PluggedIn }}\t{{ .PonIds }}"
+)
+
+type DMIOptions struct {
+ Events DmiEventOptions `command:"events"`
+ Transceiver DmiTransceiverOptions `command:"transceiver"`
+}
+
+type DmiEventOptions struct {
+ Create DmiEventCreate `command:"create"`
+}
+
+type DmiEventCreate struct {
+ Args struct {
+ Name string
+ } `positional-args:"yes" required:"yes"`
+}
+
+type DmiTransceiverOptions struct {
+ PlugIn DmiTransceiverPlugIn `command:"plug_in"`
+ PlugOut DmiTransceiverPlugOut `command:"plug_out"`
+ List DmiTransceiversList `command:"list"`
+}
+
+type DmiTransceiversList struct {
+}
+
+type DmiTransceiverPlugIn struct {
+ Args struct {
+ TransceiverId uint32
+ } `positional-args:"yes" required:"yes"`
+}
+
+type DmiTransceiverPlugOut struct {
+ Args struct {
+ TransceiverId uint32
+ } `positional-args:"yes" required:"yes"`
+}
+
+func RegisterDMICommands(parser *flags.Parser) {
+ _, _ = parser.AddCommand("dmi", "DMI Commands", "Commands to create events", &DMIOptions{})
+}
+
+func dmiEventGrpcClient() (bbsim.BBsimDmiClient, *grpc.ClientConn) {
+ conn, err := grpc.Dial(config.DmiConfig.Server, grpc.WithInsecure())
+ if err != nil {
+ log.Errorf("BBsimDmiClient connection failed : %v", err)
+ return nil, conn
+ }
+ return bbsim.NewBBsimDmiClient(conn), conn
+}
+
+// Execute create event
+func (o *DmiEventCreate) Execute(args []string) error {
+ client, conn := dmiEventGrpcClient()
+ defer conn.Close()
+
+ ctx, cancel := context.WithTimeout(context.Background(), config.GlobalConfig.Grpc.Timeout)
+ defer cancel()
+
+ req := bbsim.DmiEvent{EventName: o.Args.Name}
+ res, err := client.CreateEvent(ctx, &req)
+ if err != nil {
+ log.Errorf("Cannot create DMI event: %v", err)
+ return err
+ }
+
+ fmt.Println(fmt.Sprintf("[Status: %d] %s", res.StatusCode, res.Message))
+ return nil
+}
+
+//Print a list of the transceivers and their state
+func (pon *DmiTransceiversList) Execute(args []string) error {
+ client, conn := dmiEventGrpcClient()
+ defer conn.Close()
+
+ ctx, cancel := context.WithTimeout(context.Background(), config.GlobalConfig.Grpc.Timeout)
+ defer cancel()
+
+ transceivers, err := client.GetTransceivers(ctx, &pb.DmiEmpty{})
+ if err != nil {
+ log.Errorf("Cannot get transceivers list: %v", err)
+ return err
+ }
+
+ // print out
+ tableFormat := format.Format(DEFAULT_TRANSCEIVER_HEADER_FORMAT)
+
+ if err := tableFormat.Execute(os.Stdout, true, transceivers.Items); err != nil {
+ log.Fatalf("Error while formatting transceivers table: %s", err)
+ }
+
+ return nil
+}
+
+//Plug in the specified transceiver
+func (pon *DmiTransceiverPlugIn) Execute(args []string) error {
+ client, conn := dmiEventGrpcClient()
+ defer conn.Close()
+
+ ctx, cancel := context.WithTimeout(context.Background(), config.GlobalConfig.Grpc.Timeout)
+ defer cancel()
+
+ req := pb.TransceiverRequest{
+ TransceiverId: uint32(pon.Args.TransceiverId),
+ }
+
+ res, err := client.PlugInTransceiver(ctx, &req)
+ if err != nil {
+ log.Errorf("Cannot plug in PON transceiver: %v", err)
+ return err
+ }
+
+ fmt.Println(fmt.Sprintf("[Status: %d] %s", res.StatusCode, res.Message))
+ return nil
+}
+
+//Plug out the specified transceiver
+func (pon *DmiTransceiverPlugOut) Execute(args []string) error {
+ client, conn := dmiEventGrpcClient()
+ defer conn.Close()
+
+ ctx, cancel := context.WithTimeout(context.Background(), config.GlobalConfig.Grpc.Timeout)
+ defer cancel()
+
+ req := pb.TransceiverRequest{
+ TransceiverId: uint32(pon.Args.TransceiverId),
+ }
+
+ res, err := client.PlugOutTransceiver(ctx, &req)
+ if err != nil {
+ log.Errorf("Cannot plug out PON transceiver: %v", err)
+ return err
+ }
+
+ fmt.Println(fmt.Sprintf("[Status: %d] %s", res.StatusCode, res.Message))
+ return nil
+}
diff --git a/internal/bbsimctl/commands/dmi_events.go b/internal/bbsimctl/commands/dmi_events.go
deleted file mode 100644
index 1608965..0000000
--- a/internal/bbsimctl/commands/dmi_events.go
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2018-present Open Networking Foundation
-
- * 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 commands
-
-import (
- "context"
- "fmt"
-
- "github.com/jessevdk/go-flags"
- "github.com/opencord/bbsim/api/bbsim"
- "github.com/opencord/bbsim/internal/bbsimctl/config"
- log "github.com/sirupsen/logrus"
- "google.golang.org/grpc"
-)
-
-type DMIOptions struct {
- Events DmiEventOptions `command:"events"`
-}
-
-type DmiEventCreate struct {
- Args struct {
- Name string
- } `positional-args:"yes" required:"yes"`
-}
-
-type DmiEventOptions struct {
- Create DmiEventCreate `command:"create"`
-}
-
-func RegisterDMICommands(parser *flags.Parser) {
- _, _ = parser.AddCommand("dmi", "DMI Commands", "Commands to create events", &DMIOptions{})
-}
-
-func dmiEventGrpcClient() (bbsim.BBsimDmiClient, *grpc.ClientConn) {
- conn, err := grpc.Dial(config.DmiConfig.Server, grpc.WithInsecure())
- if err != nil {
- log.Errorf("BBsimDmiClient connection failed : %v", err)
- return nil, conn
- }
- return bbsim.NewBBsimDmiClient(conn), conn
-}
-
-// Execute create event
-func (o *DmiEventCreate) Execute(args []string) error {
- client, conn := dmiEventGrpcClient()
- defer conn.Close()
-
- ctx, cancel := context.WithTimeout(context.Background(), config.GlobalConfig.Grpc.Timeout)
- defer cancel()
-
- req := bbsim.DmiEvent{EventName: o.Args.Name}
- res, err := client.CreateEvent(ctx, &req)
- if err != nil {
- log.Errorf("Cannot create DMI event: %v", err)
- return err
- }
-
- fmt.Println(fmt.Sprintf("[Status: %d] %s", res.StatusCode, res.Message))
- return nil
-}