diff --git a/api/proto/gosdnCLI.pb.go b/api/proto/gosdnCLI.pb.go
index 62d48d12717bcf3c036da4dfebc74546d248f3f4..e6b62456650a6a4ca00bb9def32281e9752180f1 100644
--- a/api/proto/gosdnCLI.pb.go
+++ b/api/proto/gosdnCLI.pb.go
@@ -1,20 +1,19 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
 // 	protoc-gen-go v1.25.0-devel
-// 	protoc        v3.12.4
+// 	protoc        v3.14.0
 // source: gosdnCLI.proto
 
 package gosdn
 
 import (
 	context "context"
-	proto "github.com/golang/protobuf/proto"
-	empty "github.com/golang/protobuf/ptypes/empty"
 	grpc "google.golang.org/grpc"
 	codes "google.golang.org/grpc/codes"
 	status "google.golang.org/grpc/status"
 	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
 	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+	emptypb "google.golang.org/protobuf/types/known/emptypb"
 	reflect "reflect"
 	sync "sync"
 )
@@ -26,10 +25,6 @@ const (
 	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
 )
 
-// This is a compile-time assertion that a sufficiently up-to-date version
-// of the legacy proto package is being used.
-const _ = proto.ProtoPackageIsVersion4
-
 // The request message containing the user's name.
 type HelloRequest struct {
 	state         protoimpl.MessageState
@@ -218,44 +213,600 @@ func (x *ShutdownReply) ProtoReflect() protoreflect.Message {
 	return mi.MessageOf(x)
 }
 
-// Deprecated: Use ShutdownReply.ProtoReflect.Descriptor instead.
-func (*ShutdownReply) Descriptor() ([]byte, []int) {
-	return file_gosdnCLI_proto_rawDescGZIP(), []int{3}
+// Deprecated: Use ShutdownReply.ProtoReflect.Descriptor instead.
+func (*ShutdownReply) Descriptor() ([]byte, []int) {
+	return file_gosdnCLI_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *ShutdownReply) GetMessage() string {
+	if x != nil {
+		return x.Message
+	}
+	return ""
+}
+
+// Request with no meaning by now
+type TAPIRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+}
+
+func (x *TAPIRequest) Reset() {
+	*x = TAPIRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_gosdnCLI_proto_msgTypes[4]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *TAPIRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*TAPIRequest) ProtoMessage() {}
+
+func (x *TAPIRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_gosdnCLI_proto_msgTypes[4]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use TAPIRequest.ProtoReflect.Descriptor instead.
+func (*TAPIRequest) Descriptor() ([]byte, []int) {
+	return file_gosdnCLI_proto_rawDescGZIP(), []int{4}
+}
+
+func (x *TAPIRequest) GetName() string {
+	if x != nil {
+		return x.Name
+	}
+	return ""
+}
+
+// The response message containing a string with no meaning by now
+type TAPIReply struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"`
+}
+
+func (x *TAPIReply) Reset() {
+	*x = TAPIReply{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_gosdnCLI_proto_msgTypes[5]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *TAPIReply) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*TAPIReply) ProtoMessage() {}
+
+func (x *TAPIReply) ProtoReflect() protoreflect.Message {
+	mi := &file_gosdnCLI_proto_msgTypes[5]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use TAPIReply.ProtoReflect.Descriptor instead.
+func (*TAPIReply) Descriptor() ([]byte, []int) {
+	return file_gosdnCLI_proto_rawDescGZIP(), []int{5}
+}
+
+func (x *TAPIReply) GetMessage() string {
+	if x != nil {
+		return x.Message
+	}
+	return ""
+}
+
+//
+type CreatePNDRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Name        string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+	Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"`
+	Sbi         string `protobuf:"bytes,3,opt,name=sbi,proto3" json:"sbi,omitempty"`
+}
+
+func (x *CreatePNDRequest) Reset() {
+	*x = CreatePNDRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_gosdnCLI_proto_msgTypes[6]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *CreatePNDRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CreatePNDRequest) ProtoMessage() {}
+
+func (x *CreatePNDRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_gosdnCLI_proto_msgTypes[6]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use CreatePNDRequest.ProtoReflect.Descriptor instead.
+func (*CreatePNDRequest) Descriptor() ([]byte, []int) {
+	return file_gosdnCLI_proto_rawDescGZIP(), []int{6}
+}
+
+func (x *CreatePNDRequest) GetName() string {
+	if x != nil {
+		return x.Name
+	}
+	return ""
+}
+
+func (x *CreatePNDRequest) GetDescription() string {
+	if x != nil {
+		return x.Description
+	}
+	return ""
+}
+
+func (x *CreatePNDRequest) GetSbi() string {
+	if x != nil {
+		return x.Sbi
+	}
+	return ""
+}
+
+type AllSBINamesReply struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	SbiNames []string `protobuf:"bytes,1,rep,name=sbiNames,proto3" json:"sbiNames,omitempty"`
+}
+
+func (x *AllSBINamesReply) Reset() {
+	*x = AllSBINamesReply{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_gosdnCLI_proto_msgTypes[7]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *AllSBINamesReply) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*AllSBINamesReply) ProtoMessage() {}
+
+func (x *AllSBINamesReply) ProtoReflect() protoreflect.Message {
+	mi := &file_gosdnCLI_proto_msgTypes[7]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use AllSBINamesReply.ProtoReflect.Descriptor instead.
+func (*AllSBINamesReply) Descriptor() ([]byte, []int) {
+	return file_gosdnCLI_proto_rawDescGZIP(), []int{7}
+}
+
+func (x *AllSBINamesReply) GetSbiNames() []string {
+	if x != nil {
+		return x.SbiNames
+	}
+	return nil
+}
+
+//
+type CreatePNDReply struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"`
+}
+
+func (x *CreatePNDReply) Reset() {
+	*x = CreatePNDReply{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_gosdnCLI_proto_msgTypes[8]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *CreatePNDReply) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CreatePNDReply) ProtoMessage() {}
+
+func (x *CreatePNDReply) ProtoReflect() protoreflect.Message {
+	mi := &file_gosdnCLI_proto_msgTypes[8]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use CreatePNDReply.ProtoReflect.Descriptor instead.
+func (*CreatePNDReply) Descriptor() ([]byte, []int) {
+	return file_gosdnCLI_proto_rawDescGZIP(), []int{8}
+}
+
+func (x *CreatePNDReply) GetMessage() string {
+	if x != nil {
+		return x.Message
+	}
+	return ""
+}
+
+//
+type AllPNDsReply struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Pnds []*PND `protobuf:"bytes,1,rep,name=pnds,proto3" json:"pnds,omitempty"`
+}
+
+func (x *AllPNDsReply) Reset() {
+	*x = AllPNDsReply{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_gosdnCLI_proto_msgTypes[9]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *AllPNDsReply) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*AllPNDsReply) ProtoMessage() {}
+
+func (x *AllPNDsReply) ProtoReflect() protoreflect.Message {
+	mi := &file_gosdnCLI_proto_msgTypes[9]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use AllPNDsReply.ProtoReflect.Descriptor instead.
+func (*AllPNDsReply) Descriptor() ([]byte, []int) {
+	return file_gosdnCLI_proto_rawDescGZIP(), []int{9}
+}
+
+func (x *AllPNDsReply) GetPnds() []*PND {
+	if x != nil {
+		return x.Pnds
+	}
+	return nil
+}
+
+type PND struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Uuid        string    `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"`
+	Name        string    `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
+	Description string    `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"`
+	Sbi         string    `protobuf:"bytes,4,opt,name=sbi,proto3" json:"sbi,omitempty"`
+	Devices     []*Device `protobuf:"bytes,5,rep,name=devices,proto3" json:"devices,omitempty"`
+}
+
+func (x *PND) Reset() {
+	*x = PND{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_gosdnCLI_proto_msgTypes[10]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *PND) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*PND) ProtoMessage() {}
+
+func (x *PND) ProtoReflect() protoreflect.Message {
+	mi := &file_gosdnCLI_proto_msgTypes[10]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use PND.ProtoReflect.Descriptor instead.
+func (*PND) Descriptor() ([]byte, []int) {
+	return file_gosdnCLI_proto_rawDescGZIP(), []int{10}
+}
+
+func (x *PND) GetUuid() string {
+	if x != nil {
+		return x.Uuid
+	}
+	return ""
+}
+
+func (x *PND) GetName() string {
+	if x != nil {
+		return x.Name
+	}
+	return ""
+}
+
+func (x *PND) GetDescription() string {
+	if x != nil {
+		return x.Description
+	}
+	return ""
+}
+
+func (x *PND) GetSbi() string {
+	if x != nil {
+		return x.Sbi
+	}
+	return ""
+}
+
+func (x *PND) GetDevices() []*Device {
+	if x != nil {
+		return x.Devices
+	}
+	return nil
+}
+
+type Device struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Uuid     string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"`
+	Address  string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"`
+	Username string `protobuf:"bytes,3,opt,name=username,proto3" json:"username,omitempty"`
+	Password string `protobuf:"bytes,4,opt,name=password,proto3" json:"password,omitempty"`
+}
+
+func (x *Device) Reset() {
+	*x = Device{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_gosdnCLI_proto_msgTypes[11]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *Device) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Device) ProtoMessage() {}
+
+func (x *Device) ProtoReflect() protoreflect.Message {
+	mi := &file_gosdnCLI_proto_msgTypes[11]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use Device.ProtoReflect.Descriptor instead.
+func (*Device) Descriptor() ([]byte, []int) {
+	return file_gosdnCLI_proto_rawDescGZIP(), []int{11}
+}
+
+func (x *Device) GetUuid() string {
+	if x != nil {
+		return x.Uuid
+	}
+	return ""
+}
+
+func (x *Device) GetAddress() string {
+	if x != nil {
+		return x.Address
+	}
+	return ""
+}
+
+func (x *Device) GetUsername() string {
+	if x != nil {
+		return x.Username
+	}
+	return ""
+}
+
+func (x *Device) GetPassword() string {
+	if x != nil {
+		return x.Password
+	}
+	return ""
+}
+
+type AddDeviceRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	UuidPND string  `protobuf:"bytes,1,opt,name=uuidPND,proto3" json:"uuidPND,omitempty"`
+	Device  *Device `protobuf:"bytes,2,opt,name=device,proto3" json:"device,omitempty"`
+}
+
+func (x *AddDeviceRequest) Reset() {
+	*x = AddDeviceRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_gosdnCLI_proto_msgTypes[12]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *AddDeviceRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*AddDeviceRequest) ProtoMessage() {}
+
+func (x *AddDeviceRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_gosdnCLI_proto_msgTypes[12]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use AddDeviceRequest.ProtoReflect.Descriptor instead.
+func (*AddDeviceRequest) Descriptor() ([]byte, []int) {
+	return file_gosdnCLI_proto_rawDescGZIP(), []int{12}
+}
+
+func (x *AddDeviceRequest) GetUuidPND() string {
+	if x != nil {
+		return x.UuidPND
+	}
+	return ""
+}
+
+func (x *AddDeviceRequest) GetDevice() *Device {
+	if x != nil {
+		return x.Device
+	}
+	return nil
+}
+
+type AddDeviceReply struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"`
+}
+
+func (x *AddDeviceReply) Reset() {
+	*x = AddDeviceReply{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_gosdnCLI_proto_msgTypes[13]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *AddDeviceReply) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*AddDeviceReply) ProtoMessage() {}
+
+func (x *AddDeviceReply) ProtoReflect() protoreflect.Message {
+	mi := &file_gosdnCLI_proto_msgTypes[13]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use AddDeviceReply.ProtoReflect.Descriptor instead.
+func (*AddDeviceReply) Descriptor() ([]byte, []int) {
+	return file_gosdnCLI_proto_rawDescGZIP(), []int{13}
 }
 
-func (x *ShutdownReply) GetMessage() string {
+func (x *AddDeviceReply) GetMessage() string {
 	if x != nil {
 		return x.Message
 	}
 	return ""
 }
 
-// Request with no meaning by now
-type TAPIRequest struct {
+type DeviceGetRequest struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+	UuidPND    string `protobuf:"bytes,1,opt,name=uuidPND,proto3" json:"uuidPND,omitempty"`
+	UuidDevice string `protobuf:"bytes,2,opt,name=uuidDevice,proto3" json:"uuidDevice,omitempty"`
+	Path       string `protobuf:"bytes,3,opt,name=path,proto3" json:"path,omitempty"`
 }
 
-func (x *TAPIRequest) Reset() {
-	*x = TAPIRequest{}
+func (x *DeviceGetRequest) Reset() {
+	*x = DeviceGetRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_gosdnCLI_proto_msgTypes[4]
+		mi := &file_gosdnCLI_proto_msgTypes[14]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
 }
 
-func (x *TAPIRequest) String() string {
+func (x *DeviceGetRequest) String() string {
 	return protoimpl.X.MessageStringOf(x)
 }
 
-func (*TAPIRequest) ProtoMessage() {}
+func (*DeviceGetRequest) ProtoMessage() {}
 
-func (x *TAPIRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_gosdnCLI_proto_msgTypes[4]
+func (x *DeviceGetRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_gosdnCLI_proto_msgTypes[14]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -266,20 +817,33 @@ func (x *TAPIRequest) ProtoReflect() protoreflect.Message {
 	return mi.MessageOf(x)
 }
 
-// Deprecated: Use TAPIRequest.ProtoReflect.Descriptor instead.
-func (*TAPIRequest) Descriptor() ([]byte, []int) {
-	return file_gosdnCLI_proto_rawDescGZIP(), []int{4}
+// Deprecated: Use DeviceGetRequest.ProtoReflect.Descriptor instead.
+func (*DeviceGetRequest) Descriptor() ([]byte, []int) {
+	return file_gosdnCLI_proto_rawDescGZIP(), []int{14}
 }
 
-func (x *TAPIRequest) GetName() string {
+func (x *DeviceGetRequest) GetUuidPND() string {
 	if x != nil {
-		return x.Name
+		return x.UuidPND
 	}
 	return ""
 }
 
-// The response message containing a string with no meaning by now
-type TAPIReply struct {
+func (x *DeviceGetRequest) GetUuidDevice() string {
+	if x != nil {
+		return x.UuidDevice
+	}
+	return ""
+}
+
+func (x *DeviceGetRequest) GetPath() string {
+	if x != nil {
+		return x.Path
+	}
+	return ""
+}
+
+type DeviceGetReply struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
@@ -287,23 +851,23 @@ type TAPIReply struct {
 	Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"`
 }
 
-func (x *TAPIReply) Reset() {
-	*x = TAPIReply{}
+func (x *DeviceGetReply) Reset() {
+	*x = DeviceGetReply{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_gosdnCLI_proto_msgTypes[5]
+		mi := &file_gosdnCLI_proto_msgTypes[15]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
 }
 
-func (x *TAPIReply) String() string {
+func (x *DeviceGetReply) String() string {
 	return protoimpl.X.MessageStringOf(x)
 }
 
-func (*TAPIReply) ProtoMessage() {}
+func (*DeviceGetReply) ProtoMessage() {}
 
-func (x *TAPIReply) ProtoReflect() protoreflect.Message {
-	mi := &file_gosdnCLI_proto_msgTypes[5]
+func (x *DeviceGetReply) ProtoReflect() protoreflect.Message {
+	mi := &file_gosdnCLI_proto_msgTypes[15]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -314,12 +878,12 @@ func (x *TAPIReply) ProtoReflect() protoreflect.Message {
 	return mi.MessageOf(x)
 }
 
-// Deprecated: Use TAPIReply.ProtoReflect.Descriptor instead.
-func (*TAPIReply) Descriptor() ([]byte, []int) {
-	return file_gosdnCLI_proto_rawDescGZIP(), []int{5}
+// Deprecated: Use DeviceGetReply.ProtoReflect.Descriptor instead.
+func (*DeviceGetReply) Descriptor() ([]byte, []int) {
+	return file_gosdnCLI_proto_rawDescGZIP(), []int{15}
 }
 
-func (x *TAPIReply) GetMessage() string {
+func (x *DeviceGetReply) GetMessage() string {
 	if x != nil {
 		return x.Message
 	}
@@ -338,7 +902,7 @@ type LogReply struct {
 func (x *LogReply) Reset() {
 	*x = LogReply{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_gosdnCLI_proto_msgTypes[6]
+		mi := &file_gosdnCLI_proto_msgTypes[16]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -351,7 +915,7 @@ func (x *LogReply) String() string {
 func (*LogReply) ProtoMessage() {}
 
 func (x *LogReply) ProtoReflect() protoreflect.Message {
-	mi := &file_gosdnCLI_proto_msgTypes[6]
+	mi := &file_gosdnCLI_proto_msgTypes[16]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -364,7 +928,7 @@ func (x *LogReply) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use LogReply.ProtoReflect.Descriptor instead.
 func (*LogReply) Descriptor() ([]byte, []int) {
-	return file_gosdnCLI_proto_rawDescGZIP(), []int{6}
+	return file_gosdnCLI_proto_rawDescGZIP(), []int{16}
 }
 
 func (x *LogReply) GetLog() string {
@@ -396,31 +960,99 @@ var file_gosdnCLI_proto_rawDesc = []byte{
 	0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e,
 	0x61, 0x6d, 0x65, 0x22, 0x25, 0x0a, 0x09, 0x54, 0x41, 0x50, 0x49, 0x52, 0x65, 0x70, 0x6c, 0x79,
 	0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x1c, 0x0a, 0x08, 0x4c, 0x6f,
-	0x67, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6c, 0x6f, 0x67, 0x18, 0x01, 0x20,
-	0x01, 0x28, 0x09, 0x52, 0x03, 0x6c, 0x6f, 0x67, 0x32, 0xe4, 0x02, 0x0a, 0x07, 0x47, 0x72, 0x70,
-	0x63, 0x43, 0x6c, 0x69, 0x12, 0x34, 0x0a, 0x08, 0x53, 0x61, 0x79, 0x48, 0x65, 0x6c, 0x6c, 0x6f,
-	0x12, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65,
-	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x48, 0x65,
-	0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x3a, 0x0a, 0x08, 0x53, 0x68,
-	0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x12, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53,
-	0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14,
-	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x52,
-	0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x3e, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65,
-	0x4c, 0x6f, 0x67, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
-	0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74,
-	0x79, 0x1a, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x70,
-	0x6c, 0x79, 0x22, 0x00, 0x30, 0x01, 0x12, 0x35, 0x0a, 0x0b, 0x54, 0x41, 0x50, 0x49, 0x47, 0x65,
-	0x74, 0x45, 0x64, 0x67, 0x65, 0x12, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x41,
-	0x50, 0x49, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-	0x6f, 0x2e, 0x54, 0x41, 0x50, 0x49, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x39, 0x0a,
-	0x0f, 0x54, 0x41, 0x50, 0x49, 0x47, 0x65, 0x74, 0x45, 0x64, 0x67, 0x65, 0x4e, 0x6f, 0x64, 0x65,
-	0x12, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x41, 0x50, 0x49, 0x52, 0x65, 0x71,
-	0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x41, 0x50,
-	0x49, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x35, 0x0a, 0x0b, 0x54, 0x41, 0x50, 0x49,
-	0x47, 0x65, 0x74, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
-	0x54, 0x41, 0x50, 0x49, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x70, 0x72,
-	0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x41, 0x50, 0x49, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x42,
+	0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x5a, 0x0a, 0x10, 0x43, 0x72,
+	0x65, 0x61, 0x74, 0x65, 0x50, 0x4e, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12,
+	0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
+	0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f,
+	0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
+	0x74, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x62, 0x69, 0x18, 0x03, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x03, 0x73, 0x62, 0x69, 0x22, 0x2e, 0x0a, 0x10, 0x41, 0x6c, 0x6c, 0x53, 0x42, 0x49,
+	0x4e, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x62,
+	0x69, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x73, 0x62,
+	0x69, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0x2a, 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65,
+	0x50, 0x4e, 0x44, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73,
+	0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61,
+	0x67, 0x65, 0x22, 0x2e, 0x0a, 0x0c, 0x41, 0x6c, 0x6c, 0x50, 0x4e, 0x44, 0x73, 0x52, 0x65, 0x70,
+	0x6c, 0x79, 0x12, 0x1e, 0x0a, 0x04, 0x70, 0x6e, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
+	0x32, 0x0a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x4e, 0x44, 0x52, 0x04, 0x70, 0x6e,
+	0x64, 0x73, 0x22, 0x8a, 0x01, 0x0a, 0x03, 0x50, 0x4e, 0x44, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75,
+	0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x12,
+	0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
+	0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f,
+	0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
+	0x74, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x62, 0x69, 0x18, 0x04, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x03, 0x73, 0x62, 0x69, 0x12, 0x27, 0x0a, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65,
+	0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
+	0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x22,
+	0x6e, 0x0a, 0x06, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69,
+	0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x18, 0x0a,
+	0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
+	0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e,
+	0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e,
+	0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18,
+	0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22,
+	0x53, 0x0a, 0x10, 0x41, 0x64, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x75, 0x75, 0x69, 0x64, 0x50, 0x4e, 0x44, 0x18, 0x01,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x75, 0x75, 0x69, 0x64, 0x50, 0x4e, 0x44, 0x12, 0x25, 0x0a,
+	0x06, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e,
+	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x06, 0x64, 0x65,
+	0x76, 0x69, 0x63, 0x65, 0x22, 0x2a, 0x0a, 0x0e, 0x41, 0x64, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63,
+	0x65, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
+	0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+	0x22, 0x60, 0x0a, 0x10, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x47, 0x65, 0x74, 0x52, 0x65, 0x71,
+	0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x75, 0x75, 0x69, 0x64, 0x50, 0x4e, 0x44, 0x18,
+	0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x75, 0x75, 0x69, 0x64, 0x50, 0x4e, 0x44, 0x12, 0x1e,
+	0x0a, 0x0a, 0x75, 0x75, 0x69, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x0a, 0x75, 0x75, 0x69, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x12,
+	0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61,
+	0x74, 0x68, 0x22, 0x2a, 0x0a, 0x0e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x47, 0x65, 0x74, 0x52,
+	0x65, 0x70, 0x6c, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18,
+	0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x1c,
+	0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6c, 0x6f,
+	0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6c, 0x6f, 0x67, 0x32, 0xb0, 0x05, 0x0a,
+	0x07, 0x47, 0x72, 0x70, 0x63, 0x43, 0x6c, 0x69, 0x12, 0x34, 0x0a, 0x08, 0x53, 0x61, 0x79, 0x48,
+	0x65, 0x6c, 0x6c, 0x6f, 0x12, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x48, 0x65, 0x6c,
+	0x6c, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+	0x6f, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x3a,
+	0x0a, 0x08, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x12, 0x16, 0x2e, 0x70, 0x72, 0x6f,
+	0x74, 0x6f, 0x2e, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x1a, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x68, 0x75, 0x74, 0x64,
+	0x6f, 0x77, 0x6e, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x3e, 0x0a, 0x0f, 0x43, 0x72,
+	0x65, 0x61, 0x74, 0x65, 0x4c, 0x6f, 0x67, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x16, 0x2e,
+	0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
+	0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4c, 0x6f,
+	0x67, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x30, 0x01, 0x12, 0x35, 0x0a, 0x0b, 0x54, 0x41,
+	0x50, 0x49, 0x47, 0x65, 0x74, 0x45, 0x64, 0x67, 0x65, 0x12, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+	0x6f, 0x2e, 0x54, 0x41, 0x50, 0x49, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e,
+	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x41, 0x50, 0x49, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22,
+	0x00, 0x12, 0x39, 0x0a, 0x0f, 0x54, 0x41, 0x50, 0x49, 0x47, 0x65, 0x74, 0x45, 0x64, 0x67, 0x65,
+	0x4e, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x41, 0x50,
+	0x49, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+	0x2e, 0x54, 0x41, 0x50, 0x49, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x35, 0x0a, 0x0b,
+	0x54, 0x41, 0x50, 0x49, 0x47, 0x65, 0x74, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x12, 0x2e, 0x70, 0x72,
+	0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x41, 0x50, 0x49, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
+	0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x41, 0x50, 0x49, 0x52, 0x65, 0x70, 0x6c,
+	0x79, 0x22, 0x00, 0x12, 0x3d, 0x0a, 0x09, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x4e, 0x44,
+	0x12, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50,
+	0x4e, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+	0x6f, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x4e, 0x44, 0x52, 0x65, 0x70, 0x6c, 0x79,
+	0x22, 0x00, 0x12, 0x3b, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x50, 0x4e, 0x44, 0x73,
+	0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
+	0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+	0x2e, 0x41, 0x6c, 0x6c, 0x50, 0x4e, 0x44, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12,
+	0x43, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x53, 0x42, 0x49, 0x4e, 0x61, 0x6d, 0x65,
+	0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+	0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+	0x6f, 0x2e, 0x41, 0x6c, 0x6c, 0x53, 0x42, 0x49, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x65, 0x70,
+	0x6c, 0x79, 0x22, 0x00, 0x12, 0x3d, 0x0a, 0x09, 0x41, 0x64, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63,
+	0x65, 0x12, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x64, 0x64, 0x44, 0x65, 0x76,
+	0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x70, 0x72, 0x6f,
+	0x74, 0x6f, 0x2e, 0x41, 0x64, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x70, 0x6c,
+	0x79, 0x22, 0x00, 0x12, 0x4a, 0x0a, 0x16, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x44, 0x65, 0x76,
+	0x69, 0x63, 0x65, 0x47, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x2e,
+	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x47, 0x65, 0x74, 0x52,
+	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44,
+	0x65, 0x76, 0x69, 0x63, 0x65, 0x47, 0x65, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x42,
 	0x50, 0x0a, 0x1e, 0x64, 0x65, 0x2e, 0x68, 0x2d, 0x64, 0x61, 0x2e, 0x66, 0x62, 0x69, 0x2e, 0x67,
 	0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x63, 0x6c, 0x69, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63,
 	0x65, 0x42, 0x0c, 0x63, 0x6c, 0x69, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x50,
@@ -441,35 +1073,58 @@ func file_gosdnCLI_proto_rawDescGZIP() []byte {
 	return file_gosdnCLI_proto_rawDescData
 }
 
-var file_gosdnCLI_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
+var file_gosdnCLI_proto_msgTypes = make([]protoimpl.MessageInfo, 17)
 var file_gosdnCLI_proto_goTypes = []interface{}{
-	(*HelloRequest)(nil),    // 0: proto.HelloRequest
-	(*HelloReply)(nil),      // 1: proto.HelloReply
-	(*ShutdownRequest)(nil), // 2: proto.ShutdownRequest
-	(*ShutdownReply)(nil),   // 3: proto.ShutdownReply
-	(*TAPIRequest)(nil),     // 4: proto.TAPIRequest
-	(*TAPIReply)(nil),       // 5: proto.TAPIReply
-	(*LogReply)(nil),        // 6: proto.LogReply
-	(*empty.Empty)(nil),     // 7: google.protobuf.Empty
+	(*HelloRequest)(nil),     // 0: proto.HelloRequest
+	(*HelloReply)(nil),       // 1: proto.HelloReply
+	(*ShutdownRequest)(nil),  // 2: proto.ShutdownRequest
+	(*ShutdownReply)(nil),    // 3: proto.ShutdownReply
+	(*TAPIRequest)(nil),      // 4: proto.TAPIRequest
+	(*TAPIReply)(nil),        // 5: proto.TAPIReply
+	(*CreatePNDRequest)(nil), // 6: proto.CreatePNDRequest
+	(*AllSBINamesReply)(nil), // 7: proto.AllSBINamesReply
+	(*CreatePNDReply)(nil),   // 8: proto.CreatePNDReply
+	(*AllPNDsReply)(nil),     // 9: proto.AllPNDsReply
+	(*PND)(nil),              // 10: proto.PND
+	(*Device)(nil),           // 11: proto.Device
+	(*AddDeviceRequest)(nil), // 12: proto.AddDeviceRequest
+	(*AddDeviceReply)(nil),   // 13: proto.AddDeviceReply
+	(*DeviceGetRequest)(nil), // 14: proto.DeviceGetRequest
+	(*DeviceGetReply)(nil),   // 15: proto.DeviceGetReply
+	(*LogReply)(nil),         // 16: proto.LogReply
+	(*emptypb.Empty)(nil),    // 17: google.protobuf.Empty
 }
 var file_gosdnCLI_proto_depIdxs = []int32{
-	0, // 0: proto.GrpcCli.SayHello:input_type -> proto.HelloRequest
-	2, // 1: proto.GrpcCli.Shutdown:input_type -> proto.ShutdownRequest
-	7, // 2: proto.GrpcCli.CreateLogStream:input_type -> google.protobuf.Empty
-	4, // 3: proto.GrpcCli.TAPIGetEdge:input_type -> proto.TAPIRequest
-	4, // 4: proto.GrpcCli.TAPIGetEdgeNode:input_type -> proto.TAPIRequest
-	4, // 5: proto.GrpcCli.TAPIGetLink:input_type -> proto.TAPIRequest
-	1, // 6: proto.GrpcCli.SayHello:output_type -> proto.HelloReply
-	3, // 7: proto.GrpcCli.Shutdown:output_type -> proto.ShutdownReply
-	6, // 8: proto.GrpcCli.CreateLogStream:output_type -> proto.LogReply
-	5, // 9: proto.GrpcCli.TAPIGetEdge:output_type -> proto.TAPIReply
-	5, // 10: proto.GrpcCli.TAPIGetEdgeNode:output_type -> proto.TAPIReply
-	5, // 11: proto.GrpcCli.TAPIGetLink:output_type -> proto.TAPIReply
-	6, // [6:12] is the sub-list for method output_type
-	0, // [0:6] is the sub-list for method input_type
-	0, // [0:0] is the sub-list for extension type_name
-	0, // [0:0] is the sub-list for extension extendee
-	0, // [0:0] is the sub-list for field type_name
+	10, // 0: proto.AllPNDsReply.pnds:type_name -> proto.PND
+	11, // 1: proto.PND.devices:type_name -> proto.Device
+	11, // 2: proto.AddDeviceRequest.device:type_name -> proto.Device
+	0,  // 3: proto.GrpcCli.SayHello:input_type -> proto.HelloRequest
+	2,  // 4: proto.GrpcCli.Shutdown:input_type -> proto.ShutdownRequest
+	17, // 5: proto.GrpcCli.CreateLogStream:input_type -> google.protobuf.Empty
+	4,  // 6: proto.GrpcCli.TAPIGetEdge:input_type -> proto.TAPIRequest
+	4,  // 7: proto.GrpcCli.TAPIGetEdgeNode:input_type -> proto.TAPIRequest
+	4,  // 8: proto.GrpcCli.TAPIGetLink:input_type -> proto.TAPIRequest
+	6,  // 9: proto.GrpcCli.CreatePND:input_type -> proto.CreatePNDRequest
+	17, // 10: proto.GrpcCli.GetAllPNDs:input_type -> google.protobuf.Empty
+	17, // 11: proto.GrpcCli.GetAllSBINames:input_type -> google.protobuf.Empty
+	12, // 12: proto.GrpcCli.AddDevice:input_type -> proto.AddDeviceRequest
+	14, // 13: proto.GrpcCli.HandleDeviceGetRequest:input_type -> proto.DeviceGetRequest
+	1,  // 14: proto.GrpcCli.SayHello:output_type -> proto.HelloReply
+	3,  // 15: proto.GrpcCli.Shutdown:output_type -> proto.ShutdownReply
+	16, // 16: proto.GrpcCli.CreateLogStream:output_type -> proto.LogReply
+	5,  // 17: proto.GrpcCli.TAPIGetEdge:output_type -> proto.TAPIReply
+	5,  // 18: proto.GrpcCli.TAPIGetEdgeNode:output_type -> proto.TAPIReply
+	5,  // 19: proto.GrpcCli.TAPIGetLink:output_type -> proto.TAPIReply
+	8,  // 20: proto.GrpcCli.CreatePND:output_type -> proto.CreatePNDReply
+	9,  // 21: proto.GrpcCli.GetAllPNDs:output_type -> proto.AllPNDsReply
+	7,  // 22: proto.GrpcCli.GetAllSBINames:output_type -> proto.AllSBINamesReply
+	13, // 23: proto.GrpcCli.AddDevice:output_type -> proto.AddDeviceReply
+	15, // 24: proto.GrpcCli.HandleDeviceGetRequest:output_type -> proto.DeviceGetReply
+	14, // [14:25] is the sub-list for method output_type
+	3,  // [3:14] is the sub-list for method input_type
+	3,  // [3:3] is the sub-list for extension type_name
+	3,  // [3:3] is the sub-list for extension extendee
+	0,  // [0:3] is the sub-list for field type_name
 }
 
 func init() { file_gosdnCLI_proto_init() }
@@ -551,6 +1206,126 @@ func file_gosdnCLI_proto_init() {
 			}
 		}
 		file_gosdnCLI_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*CreatePNDRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_gosdnCLI_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*AllSBINamesReply); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_gosdnCLI_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*CreatePNDReply); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_gosdnCLI_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*AllPNDsReply); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_gosdnCLI_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*PND); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_gosdnCLI_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*Device); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_gosdnCLI_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*AddDeviceRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_gosdnCLI_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*AddDeviceReply); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_gosdnCLI_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*DeviceGetRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_gosdnCLI_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*DeviceGetReply); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_gosdnCLI_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} {
 			switch v := v.(*LogReply); i {
 			case 0:
 				return &v.state
@@ -569,7 +1344,7 @@ func file_gosdnCLI_proto_init() {
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: file_gosdnCLI_proto_rawDesc,
 			NumEnums:      0,
-			NumMessages:   7,
+			NumMessages:   17,
 			NumExtensions: 0,
 			NumServices:   1,
 		},
@@ -600,7 +1375,7 @@ type GrpcCliClient interface {
 	// Shutdown goSDN
 	Shutdown(ctx context.Context, in *ShutdownRequest, opts ...grpc.CallOption) (*ShutdownReply, error)
 	// creates a stream to receive goSDN logs
-	CreateLogStream(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (GrpcCli_CreateLogStreamClient, error)
+	CreateLogStream(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (GrpcCli_CreateLogStreamClient, error)
 	// By now solely TAPI specific calls can be issued from the grpc-cli
 	// TAPIGetEdge
 	TAPIGetEdge(ctx context.Context, in *TAPIRequest, opts ...grpc.CallOption) (*TAPIReply, error)
@@ -608,6 +1383,16 @@ type GrpcCliClient interface {
 	TAPIGetEdgeNode(ctx context.Context, in *TAPIRequest, opts ...grpc.CallOption) (*TAPIReply, error)
 	// TAPIGetLink
 	TAPIGetLink(ctx context.Context, in *TAPIRequest, opts ...grpc.CallOption) (*TAPIReply, error)
+	// CreatePND
+	CreatePND(ctx context.Context, in *CreatePNDRequest, opts ...grpc.CallOption) (*CreatePNDReply, error)
+	// GetAllPNDs
+	GetAllPNDs(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*AllPNDsReply, error)
+	// GetAllSBIs
+	GetAllSBINames(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*AllSBINamesReply, error)
+	// AddDevice
+	AddDevice(ctx context.Context, in *AddDeviceRequest, opts ...grpc.CallOption) (*AddDeviceReply, error)
+	// HandleDeviceGetRequest
+	HandleDeviceGetRequest(ctx context.Context, in *DeviceGetRequest, opts ...grpc.CallOption) (*DeviceGetReply, error)
 }
 
 type grpcCliClient struct {
@@ -636,7 +1421,7 @@ func (c *grpcCliClient) Shutdown(ctx context.Context, in *ShutdownRequest, opts
 	return out, nil
 }
 
-func (c *grpcCliClient) CreateLogStream(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (GrpcCli_CreateLogStreamClient, error) {
+func (c *grpcCliClient) CreateLogStream(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (GrpcCli_CreateLogStreamClient, error) {
 	stream, err := c.cc.NewStream(ctx, &_GrpcCli_serviceDesc.Streams[0], "/proto.GrpcCli/CreateLogStream", opts...)
 	if err != nil {
 		return nil, err
@@ -695,6 +1480,51 @@ func (c *grpcCliClient) TAPIGetLink(ctx context.Context, in *TAPIRequest, opts .
 	return out, nil
 }
 
+func (c *grpcCliClient) CreatePND(ctx context.Context, in *CreatePNDRequest, opts ...grpc.CallOption) (*CreatePNDReply, error) {
+	out := new(CreatePNDReply)
+	err := c.cc.Invoke(ctx, "/proto.GrpcCli/CreatePND", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *grpcCliClient) GetAllPNDs(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*AllPNDsReply, error) {
+	out := new(AllPNDsReply)
+	err := c.cc.Invoke(ctx, "/proto.GrpcCli/GetAllPNDs", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *grpcCliClient) GetAllSBINames(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*AllSBINamesReply, error) {
+	out := new(AllSBINamesReply)
+	err := c.cc.Invoke(ctx, "/proto.GrpcCli/GetAllSBINames", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *grpcCliClient) AddDevice(ctx context.Context, in *AddDeviceRequest, opts ...grpc.CallOption) (*AddDeviceReply, error) {
+	out := new(AddDeviceReply)
+	err := c.cc.Invoke(ctx, "/proto.GrpcCli/AddDevice", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *grpcCliClient) HandleDeviceGetRequest(ctx context.Context, in *DeviceGetRequest, opts ...grpc.CallOption) (*DeviceGetReply, error) {
+	out := new(DeviceGetReply)
+	err := c.cc.Invoke(ctx, "/proto.GrpcCli/HandleDeviceGetRequest", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
 // GrpcCliServer is the server API for GrpcCli service.
 type GrpcCliServer interface {
 	// Sends a greeting
@@ -702,7 +1532,7 @@ type GrpcCliServer interface {
 	// Shutdown goSDN
 	Shutdown(context.Context, *ShutdownRequest) (*ShutdownReply, error)
 	// creates a stream to receive goSDN logs
-	CreateLogStream(*empty.Empty, GrpcCli_CreateLogStreamServer) error
+	CreateLogStream(*emptypb.Empty, GrpcCli_CreateLogStreamServer) error
 	// By now solely TAPI specific calls can be issued from the grpc-cli
 	// TAPIGetEdge
 	TAPIGetEdge(context.Context, *TAPIRequest) (*TAPIReply, error)
@@ -710,6 +1540,16 @@ type GrpcCliServer interface {
 	TAPIGetEdgeNode(context.Context, *TAPIRequest) (*TAPIReply, error)
 	// TAPIGetLink
 	TAPIGetLink(context.Context, *TAPIRequest) (*TAPIReply, error)
+	// CreatePND
+	CreatePND(context.Context, *CreatePNDRequest) (*CreatePNDReply, error)
+	// GetAllPNDs
+	GetAllPNDs(context.Context, *emptypb.Empty) (*AllPNDsReply, error)
+	// GetAllSBIs
+	GetAllSBINames(context.Context, *emptypb.Empty) (*AllSBINamesReply, error)
+	// AddDevice
+	AddDevice(context.Context, *AddDeviceRequest) (*AddDeviceReply, error)
+	// HandleDeviceGetRequest
+	HandleDeviceGetRequest(context.Context, *DeviceGetRequest) (*DeviceGetReply, error)
 }
 
 // UnimplementedGrpcCliServer can be embedded to have forward compatible implementations.
@@ -722,7 +1562,7 @@ func (*UnimplementedGrpcCliServer) SayHello(context.Context, *HelloRequest) (*He
 func (*UnimplementedGrpcCliServer) Shutdown(context.Context, *ShutdownRequest) (*ShutdownReply, error) {
 	return nil, status.Errorf(codes.Unimplemented, "method Shutdown not implemented")
 }
-func (*UnimplementedGrpcCliServer) CreateLogStream(*empty.Empty, GrpcCli_CreateLogStreamServer) error {
+func (*UnimplementedGrpcCliServer) CreateLogStream(*emptypb.Empty, GrpcCli_CreateLogStreamServer) error {
 	return status.Errorf(codes.Unimplemented, "method CreateLogStream not implemented")
 }
 func (*UnimplementedGrpcCliServer) TAPIGetEdge(context.Context, *TAPIRequest) (*TAPIReply, error) {
@@ -734,6 +1574,21 @@ func (*UnimplementedGrpcCliServer) TAPIGetEdgeNode(context.Context, *TAPIRequest
 func (*UnimplementedGrpcCliServer) TAPIGetLink(context.Context, *TAPIRequest) (*TAPIReply, error) {
 	return nil, status.Errorf(codes.Unimplemented, "method TAPIGetLink not implemented")
 }
+func (*UnimplementedGrpcCliServer) CreatePND(context.Context, *CreatePNDRequest) (*CreatePNDReply, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method CreatePND not implemented")
+}
+func (*UnimplementedGrpcCliServer) GetAllPNDs(context.Context, *emptypb.Empty) (*AllPNDsReply, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method GetAllPNDs not implemented")
+}
+func (*UnimplementedGrpcCliServer) GetAllSBINames(context.Context, *emptypb.Empty) (*AllSBINamesReply, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method GetAllSBINames not implemented")
+}
+func (*UnimplementedGrpcCliServer) AddDevice(context.Context, *AddDeviceRequest) (*AddDeviceReply, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method AddDevice not implemented")
+}
+func (*UnimplementedGrpcCliServer) HandleDeviceGetRequest(context.Context, *DeviceGetRequest) (*DeviceGetReply, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method HandleDeviceGetRequest not implemented")
+}
 
 func RegisterGrpcCliServer(s *grpc.Server, srv GrpcCliServer) {
 	s.RegisterService(&_GrpcCli_serviceDesc, srv)
@@ -776,7 +1631,7 @@ func _GrpcCli_Shutdown_Handler(srv interface{}, ctx context.Context, dec func(in
 }
 
 func _GrpcCli_CreateLogStream_Handler(srv interface{}, stream grpc.ServerStream) error {
-	m := new(empty.Empty)
+	m := new(emptypb.Empty)
 	if err := stream.RecvMsg(m); err != nil {
 		return err
 	}
@@ -850,6 +1705,96 @@ func _GrpcCli_TAPIGetLink_Handler(srv interface{}, ctx context.Context, dec func
 	return interceptor(ctx, in, info, handler)
 }
 
+func _GrpcCli_CreatePND_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(CreatePNDRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(GrpcCliServer).CreatePND(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/proto.GrpcCli/CreatePND",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(GrpcCliServer).CreatePND(ctx, req.(*CreatePNDRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _GrpcCli_GetAllPNDs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(emptypb.Empty)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(GrpcCliServer).GetAllPNDs(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/proto.GrpcCli/GetAllPNDs",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(GrpcCliServer).GetAllPNDs(ctx, req.(*emptypb.Empty))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _GrpcCli_GetAllSBINames_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(emptypb.Empty)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(GrpcCliServer).GetAllSBINames(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/proto.GrpcCli/GetAllSBINames",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(GrpcCliServer).GetAllSBINames(ctx, req.(*emptypb.Empty))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _GrpcCli_AddDevice_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(AddDeviceRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(GrpcCliServer).AddDevice(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/proto.GrpcCli/AddDevice",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(GrpcCliServer).AddDevice(ctx, req.(*AddDeviceRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _GrpcCli_HandleDeviceGetRequest_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(DeviceGetRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(GrpcCliServer).HandleDeviceGetRequest(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/proto.GrpcCli/HandleDeviceGetRequest",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(GrpcCliServer).HandleDeviceGetRequest(ctx, req.(*DeviceGetRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
 var _GrpcCli_serviceDesc = grpc.ServiceDesc{
 	ServiceName: "proto.GrpcCli",
 	HandlerType: (*GrpcCliServer)(nil),
@@ -874,6 +1819,26 @@ var _GrpcCli_serviceDesc = grpc.ServiceDesc{
 			MethodName: "TAPIGetLink",
 			Handler:    _GrpcCli_TAPIGetLink_Handler,
 		},
+		{
+			MethodName: "CreatePND",
+			Handler:    _GrpcCli_CreatePND_Handler,
+		},
+		{
+			MethodName: "GetAllPNDs",
+			Handler:    _GrpcCli_GetAllPNDs_Handler,
+		},
+		{
+			MethodName: "GetAllSBINames",
+			Handler:    _GrpcCli_GetAllSBINames_Handler,
+		},
+		{
+			MethodName: "AddDevice",
+			Handler:    _GrpcCli_AddDevice_Handler,
+		},
+		{
+			MethodName: "HandleDeviceGetRequest",
+			Handler:    _GrpcCli_HandleDeviceGetRequest_Handler,
+		},
 	},
 	Streams: []grpc.StreamDesc{
 		{
diff --git a/api/proto/gosdnCLI.proto b/api/proto/gosdnCLI.proto
index 0e3636675e4f584194cbad5414ddd28ba3156520..355d8e7455f009d2b35e8bc34c079ce31466bbdd 100644
--- a/api/proto/gosdnCLI.proto
+++ b/api/proto/gosdnCLI.proto
@@ -2,10 +2,6 @@ syntax = "proto3";
 import "google/protobuf/empty.proto";
 
 option go_package = "gitlab.fbi.h-da.de/cocsn/gosdn";
-option java_multiple_files = true;
-option java_package = "de.h-da.fbi.gosdn.cliInterface";
-option java_outer_classname = "cliInterface";
-
 
 package proto;
 
@@ -25,6 +21,16 @@ service GrpcCli {
   rpc TAPIGetEdgeNode (TAPIRequest) returns (TAPIReply) {}
   // TAPIGetLink
   rpc TAPIGetLink (TAPIRequest) returns (TAPIReply) {}
+  // CreatePND
+  rpc CreatePND (CreatePNDRequest) returns (CreatePNDReply) {}
+  // GetAllPNDs
+  rpc GetAllPNDs(google.protobuf.Empty) returns (AllPNDsReply) {}
+  // GetAllSBIs
+  rpc  GetAllSBINames(google.protobuf.Empty) returns (AllSBINamesReply) {}
+  // AddDevice
+  rpc AddDevice(AddDeviceRequest) returns (AddDeviceReply) {}
+  // HandleDeviceGetRequest
+  rpc HandleDeviceGetRequest(DeviceGetRequest) returns (DeviceGetReply) {}
 }
 
 // The request message containing the user's name.
@@ -58,6 +64,61 @@ message TAPIReply {
   string message = 1;
 }
 
+//
+message CreatePNDRequest {
+    string name = 1;
+    string description = 2;
+    string sbi = 3;
+}
+
+message AllSBINamesReply {
+    repeated string sbiNames = 1;
+}
+
+//
+message CreatePNDReply {
+    string message = 1;
+}
+
+//
+message AllPNDsReply {
+    repeated PND pnds = 1;
+}
+
+message PND {
+    string uuid = 1;
+    string name = 2;
+    string description = 3;
+    string sbi = 4;
+    repeated Device devices = 5;
+}
+
+message Device {
+ string uuid = 1;
+ string address = 2;
+ string username = 3;
+ string password = 4;
+}
+
+message AddDeviceRequest {
+     string uuidPND = 1;
+     Device device = 2;
+}
+
+message AddDeviceReply {
+     string message = 1;
+}
+
+message DeviceGetRequest {
+    string uuidPND = 1;
+    string uuidDevice = 2;
+    string path = 3;
+}
+
+message DeviceGetReply {
+    string message = 1;
+}
+
 // The response message containing a string with a goSDN log
 message LogReply {
   string log = 1;
diff --git a/cmd/gnmi-telemetry/telemetry.go b/cmd/gnmi-telemetry/telemetry.go
index 80a784f77da6fb869812222d3a4f4247f5c2a548..98650bd09d0fda8e12855b17387e2c346f392e43 100644
--- a/cmd/gnmi-telemetry/telemetry.go
+++ b/cmd/gnmi-telemetry/telemetry.go
@@ -3,7 +3,6 @@ package main
 import (
 	"code.fbi.h-da.de/cocsn/gosdn/forks/goarista/gnmi"
 	"code.fbi.h-da.de/cocsn/gosdn/nucleus"
-	schema "code.fbi.h-da.de/cocsn/yang-models/generated/arista"
 	"context"
 	"fmt"
 	"github.com/google/uuid"
@@ -18,33 +17,32 @@ import (
 func main() {
 	log.SetLevel(log.DebugLevel)
 	sbi := &nucleus.AristaOC{}
-	transport := &nucleus.Gnmi{
-		SetNode:  sbi.SetNode(),
-		RespChan: make(chan *gpb.SubscribeResponse),
-	}
+
 	device := nucleus.Device{
-		Device: &schema.Device{},
-		SBI:    sbi,
+		GoStruct: sbi.Schema().Root,
+		SBI:      sbi,
 		Config: nucleus.DeviceConfig{
-			Uuid:     uuid.New(),
-			Address:  "localhost:9339",
-			Username: "admin",
-			Password: "arista",
+			Uuid: uuid.New(),
 		},
-		Transport: transport,
 	}
-	pnd := nucleus.NewPND("openconfig", sbi)
-	if err := pnd.AddDevice(device); err != nil {
+	pnd := nucleus.NewPND("openconfig", "a simple openconfig PND", sbi)
+	if err := pnd.AddDevice(&device); err != nil {
 		log.Fatal(err)
 	}
 
+	transport := &nucleus.Gnmi{
+		SetNode:  sbi.SetNode(),
+		RespChan: make(chan *gpb.SubscribeResponse),
+	}
 	cfg := &gnmi.Config{
-		Addr:     device.Config.Address,
-		Password: device.Config.Password,
-		Username: device.Config.Username,
+		Addr:     "portainer.danet.fbi.h-da.de:6030",
+		Username: "admin",
+		Password: "arista",
+		Encoding: gpb.Encoding_JSON_IETF,
 	}
-	ctx := gnmi.NewContext(context.Background(), cfg)
-	ctx = context.WithValue(ctx, "config", cfg)
+	transport.SetConfig(cfg)
+
+	device.Transport = transport
 
 	paths := []string{"/interfaces/interface/name"}
 
@@ -62,7 +60,7 @@ func main() {
 	}
 	done := make(chan os.Signal, 1)
 	signal.Notify(done, syscall.SIGILL, syscall.SIGTERM)
-	ctx = context.WithValue(ctx, "opts", opts)
+	ctx := context.WithValue(context.Background(), "opts", opts)
 	go func() {
 		if err := transport.Subscribe(ctx); err != nil {
 			log.Fatal(err)
diff --git a/cmd/gnmi/gnmi.go b/cmd/gnmi/gnmi.go
index 7eb6853d82082d395e6c94bf04d49280f3c40bc6..29136c2493a64379c0c7df291a6a433eaa49a600 100644
--- a/cmd/gnmi/gnmi.go
+++ b/cmd/gnmi/gnmi.go
@@ -17,12 +17,13 @@ func main() {
 	log.SetLevel(log.DebugLevel)
 	sbi := &nucleus.AristaOC{}
 	device := &nucleus.Device{
-		SBI: sbi,
+		GoStruct: sbi.Schema().Root,
+		SBI:      sbi,
 		Config: nucleus.DeviceConfig{
 			Uuid: uuid.New(),
 		},
 	}
-	pnd := nucleus.NewPND("openconfig", sbi)
+	pnd := nucleus.NewPND("openconfig", "test description", sbi)
 	if err := pnd.AddDevice(device); err != nil {
 		log.Fatal(err)
 	}
diff --git a/nucleus/cli-handling.go b/nucleus/cli-handling.go
index 6ebe88cec126b0cb6255fb00e3363f8648ae7a7a..8a02188159b6bcc5372e45b2d84d87dc1153fb88 100644
--- a/nucleus/cli-handling.go
+++ b/nucleus/cli-handling.go
@@ -8,14 +8,18 @@ package nucleus
 
 import (
 	"context"
-	"github.com/google/uuid"
-	"github.com/spf13/viper"
+	"errors"
 	"io"
 	"net"
 	"os"
 	"sync"
 
+	"github.com/google/uuid"
+	"github.com/spf13/viper"
+
 	pb "code.fbi.h-da.de/cocsn/gosdn/api/proto"
+	"code.fbi.h-da.de/cocsn/gosdn/forks/goarista/gnmi"
+	gpb "github.com/openconfig/gnmi/proto/gnmi"
 	log "github.com/sirupsen/logrus"
 	"google.golang.org/grpc"
 	"google.golang.org/grpc/health"
@@ -152,3 +156,129 @@ func (s *server) TAPIGetLink(ctx context.Context, in *pb.TAPIRequest) (*pb.TAPIR
 	// TODO: Implement
 	return &pb.TAPIReply{Message: "Done"}, nil
 }
+
+//CreatePND creates a new PND and adds it to the principalNetworkDomain map of
+//the core
+func (s *server) CreatePND(ctx context.Context, in *pb.CreatePNDRequest) (*pb.CreatePNDReply, error) {
+	log.Info("Received: Create a PND with the name", in.GetName())
+	sbi := s.core.southboundInterfaces[in.GetSbi()]
+	id := uuid.New()
+	s.core.principalNetworkDomains[id] = NewPND(in.GetName(), in.GetDescription(), sbi)
+
+	return &pb.CreatePNDReply{Message: "Created new PND: " + id.String()}, nil
+}
+
+//GetAllPNDs is a request to get all current registered PNDs and returns a slim
+//variant of PNDs and their respective devices
+func (s *server) GetAllPNDs(ctx context.Context, in *emptypb.Empty) (*pb.AllPNDsReply, error) {
+	log.Info("Received: Get all PNDs")
+	var pnds []*pb.PND
+	for uuidPND, pnd := range s.core.principalNetworkDomains {
+		var devices []*pb.Device
+		for uuidDevice, device := range pnd.(*pndImplementation).devices {
+			tmpDevice := pb.Device{
+				Uuid:     uuidDevice.String(),
+				Address:  device.Config.Address,
+				Username: device.Config.Username,
+				Password: device.Config.Password}
+			devices = append(devices, &tmpDevice)
+		}
+		tmpPND := pb.PND{
+			Uuid:        uuidPND.String(),
+			Name:        pnd.GetName(),
+			Description: pnd.GetDescription(),
+			Sbi:         pnd.GetSBIs()["default"].SbiIdentifier(),
+			Devices:     devices,
+		}
+		pnds = append(pnds, &tmpPND)
+	}
+	return &pb.AllPNDsReply{Pnds: pnds}, nil
+}
+
+//GetAllSBINames returns all registered SBIs from core.
+func (s *server) GetAllSBINames(ctx context.Context, in *emptypb.Empty) (*pb.AllSBINamesReply, error) {
+	var sbiNames []string
+	for _, s := range s.core.southboundInterfaces {
+		sbiNames = append(sbiNames, s.SbiIdentifier())
+	}
+	return &pb.AllSBINamesReply{SbiNames: sbiNames}, nil
+}
+
+//AddDevice adds a new Device to a specific PND
+//currently this is only working with gnmi transports
+func (s *server) AddDevice(ctx context.Context, in *pb.AddDeviceRequest) (*pb.AddDeviceReply, error) {
+	log.Info("Received: AddDevice")
+	uuidPND, err := uuid.Parse(in.UuidPND)
+	if err != nil {
+		return &pb.AddDeviceReply{Message: err.Error()}, err
+	}
+	pnd, exists := s.core.principalNetworkDomains[uuidPND]
+	if exists != true {
+		log.Info(err)
+		return &pb.AddDeviceReply{Message: err.Error()}, err
+	}
+	sbi := s.core.principalNetworkDomains[uuidPND].GetSBIs()["default"]
+
+	//TODO: could the transport and the related config be created in device?
+	transport := &Gnmi{SetNode: sbi.SetNode()}
+	cfg := &gnmi.Config{
+		Addr:     in.Device.Address,
+		Username: in.Device.Username,
+		Password: in.Device.Password,
+		Encoding: gpb.Encoding_JSON_IETF,
+	}
+	transport.SetConfig(cfg)
+
+	newDevice := NewDevice(sbi, in.Device.Address, in.Device.Username,
+		in.Device.Password, transport)
+
+	err = pnd.AddDevice(newDevice)
+	if err != nil {
+		log.Info(err)
+		return &pb.AddDeviceReply{Message: err.Error()}, err
+	}
+
+	return &pb.AddDeviceReply{Message: "Added new Device: " + newDevice.Config.Uuid.String()}, err
+}
+
+//HandleDeviceGetRequest handles a GET request via pnd.Request()
+func (s *server) HandleDeviceGetRequest(ctx context.Context, in *pb.DeviceGetRequest) (*pb.DeviceGetReply, error) {
+	log.Info("Received: HandleDeviceGetRequest")
+	uuidPND, err := uuid.Parse(in.GetUuidPND())
+	if err != nil {
+		log.Info(err)
+		return &pb.DeviceGetReply{Message: err.Error()}, err
+	}
+	uuidDevice, err := uuid.Parse(in.GetUuidDevice())
+	if err != nil {
+		log.Info(err)
+		return &pb.DeviceGetReply{Message: err.Error()}, err
+	}
+	pnd, exists := s.core.principalNetworkDomains[uuidPND]
+	if exists != true {
+		err := errors.New("Couldnt find PND: UUID is wrong")
+		log.Info(err)
+		return &pb.DeviceGetReply{Message: err.Error()}, err
+	}
+	//check if the device exists
+	if !pnd.ContainsDevice(uuidDevice) {
+		err := errors.New("Couldnt find device: UUID is wrong")
+		log.Info(err)
+		return &pb.DeviceGetReply{Message: err.Error()}, err
+	}
+
+	//GET request for the provided path
+	err = pnd.Request(uuidDevice, in.GetPath())
+	if err != nil {
+		log.Info(err)
+		return &pb.DeviceGetReply{Message: err.Error()}, err
+	}
+
+	d, err := pnd.MarshalDevice(uuidDevice)
+	if err != nil {
+		log.Info(err)
+		return &pb.DeviceGetReply{Message: err.Error()}, err
+	}
+
+	return &pb.DeviceGetReply{Message: d}, nil
+}
diff --git a/nucleus/controller.go b/nucleus/controller.go
index 47c87bf0a6edf82066ee84ed43b7cfa7ff4c60c4..a02b55424f458f6977a0b93849d8741b1056e384 100644
--- a/nucleus/controller.go
+++ b/nucleus/controller.go
@@ -1,20 +1,21 @@
 package nucleus
 
 import (
-	"code.fbi.h-da.de/cocsn/gosdn/database"
 	"fmt"
+	"os"
+
+	"code.fbi.h-da.de/cocsn/gosdn/database"
 	"github.com/google/uuid"
 	log "github.com/sirupsen/logrus"
 	"github.com/spf13/viper"
-	"os"
 )
 
 // Core is the representation of the controllers core
 type Core struct {
-	southboundInterfaces   map[string]SouthboundInterface
-	prinipalNetworkDomains map[uuid.UUID]PrincipalNetworkDomain
-	database               database.Database
-	IsRunning              chan bool
+	southboundInterfaces    map[string]SouthboundInterface
+	principalNetworkDomains map[uuid.UUID]PrincipalNetworkDomain
+	database                database.Database
+	IsRunning               chan bool
 }
 
 //Initialize does start-up housekeeping like reading controller config files
@@ -32,15 +33,24 @@ func (c *Core) Initialize(IsRunningChannel chan bool) {
 		log.Fatal(fmt.Errorf("Fatal error config file: %s \n", err))
 	}
 	c.AttachDatabase()
+	c.CreateSouthboundInterfaces()
 
 	c.IsRunning = IsRunningChannel
 }
 
-// AttachDatabase connects to the database and passes the connectio to the controller core
+// AttachDatabase connects to the database and passes the connection to the controller core
 func (c *Core) AttachDatabase() {
 	c.database = database.NewDatabaseClient()
 }
 
+// CreateSouthboundInterfaces initializes the controller with his supported SBIs
+func (c *Core) CreateSouthboundInterfaces() {
+	arista := &AristaOC{}
+	c.southboundInterfaces[arista.SbiIdentifier()] = arista
+	openconfig := &OpenConfig{}
+	c.southboundInterfaces[openconfig.SbiIdentifier()] = openconfig
+}
+
 // Shutdown waits for the shutdown signal and gracefully shuts down once it arrived
 func (c *Core) Shutdown() {
 	<-c.IsRunning
diff --git a/nucleus/device.go b/nucleus/device.go
index 2539413479aa0c1ce87eae96a8c653642f397e72..dcad6b388de25a0e8be66dd852a2bdd1edc00b70 100644
--- a/nucleus/device.go
+++ b/nucleus/device.go
@@ -6,7 +6,7 @@ import (
 )
 
 type Device struct {
-	// Device inherits properies of ygot.GoStruct
+	// Device inherits properties of ygot.GoStruct
 	ygot.GoStruct
 
 	// SBI is the device's southbound interface implementation
@@ -19,6 +19,22 @@ type Device struct {
 	Transport Transport
 }
 
+//NewDevice creates a Device
+func NewDevice(sbi SouthboundInterface, addr, username, password string,
+	transport Transport) *Device {
+	return &Device{
+		GoStruct: sbi.Schema().Root,
+		SBI:      sbi,
+		Config: DeviceConfig{
+			Uuid:     uuid.New(),
+			Address:  addr,
+			Username: username,
+			Password: password,
+		},
+		Transport: transport,
+	}
+}
+
 type DeviceConfig struct {
 	Uuid     uuid.UUID
 	Address  string
diff --git a/nucleus/device_test.go b/nucleus/device_test.go
index a452c791232c5bf17f96eebb46f935261857003e..d98401ba952e4b94d4ebcc36da12905065e510fa 100644
--- a/nucleus/device_test.go
+++ b/nucleus/device_test.go
@@ -8,7 +8,7 @@ import (
 
 func TestDevice_Add(t *testing.T) {
 	type fields struct {
-		Device    ygot.GoStruct
+		ygot.GoStruct
 		SBI       SouthboundInterface
 		Config    DeviceConfig
 		Transport Transport
@@ -26,7 +26,7 @@ func TestDevice_Add(t *testing.T) {
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			d := Device{
-				Device:    tt.fields.Device,
+				GoStruct:  tt.fields.SBI.Schema().Root,
 				SBI:       tt.fields.SBI,
 				Config:    tt.fields.Config,
 				Transport: tt.fields.Transport,
diff --git a/nucleus/nucleus-core.go b/nucleus/nucleus-core.go
index 47b265b96d5a743fbe55eb4f1d74b20ea8f7a65b..ae6d78056beb1e9c7d19e9385026f0117d033a91 100644
--- a/nucleus/nucleus-core.go
+++ b/nucleus/nucleus-core.go
@@ -1,9 +1,11 @@
 package nucleus
 
 import (
+	"time"
+
 	"code.fbi.h-da.de/cocsn/gosdn/database"
+	"github.com/google/uuid"
 	log "github.com/sirupsen/logrus"
-	"time"
 )
 
 //StartAndRun is used to start the core of the controller and any auxiliary services.
@@ -13,7 +15,9 @@ func StartAndRun(IsRunningChannel chan bool) {
 
 	// Initialize the Core
 	core := Core{
-		database: database.Database{},
+		principalNetworkDomains: make(map[uuid.UUID]PrincipalNetworkDomain),
+		southboundInterfaces:    make(map[string]SouthboundInterface),
+		database:                database.Database{},
 	}
 	core.Initialize(IsRunningChannel)
 	// Start the GRCP CLI
diff --git a/nucleus/principalNetworkDomain.go b/nucleus/principalNetworkDomain.go
index 6d988fe9a88b7b8a4ba95ede08c5059a2765d912..bc3307cb580aab6b99ea8a5b425d4d03d834a40d 100644
--- a/nucleus/principalNetworkDomain.go
+++ b/nucleus/principalNetworkDomain.go
@@ -2,6 +2,8 @@ package nucleus
 
 import (
 	"context"
+
+	"encoding/json"
 	"github.com/google/uuid"
 )
 
@@ -9,49 +11,84 @@ import (
 // interface for PND implementations
 type PrincipalNetworkDomain interface {
 	Destroy() error
-	AddSbi() error
-	RemoveSbi() error
+	AddSbi(SouthboundInterface) error
+	RemoveSbi(string) error
 	AddDevice(*Device) error
 	RemoveDevice(uuid.UUID) error
 	Request(uuid.UUID, string) error
 	RequestAll(string) error
+	GetName() string
+	GetDescription() string
+	MarshalDevice(uuid.UUID) (string, error)
+	ContainsDevice(uuid.UUID) bool
+	GetSBIs() map[string]SouthboundInterface
 }
 
 type pndImplementation struct {
-	name    string
-	sbi     map[string]SouthboundInterface
-	devices map[uuid.UUID]*Device
+	name        string
+	description string
+	sbi         map[string]SouthboundInterface
+	devices     map[uuid.UUID]*Device
 }
 
 //NewPND creates a Principle Network Domain
-func NewPND(name string, sbi SouthboundInterface) PrincipalNetworkDomain {
+func NewPND(name, description string, sbi SouthboundInterface) PrincipalNetworkDomain {
 	sbic := make(map[string]SouthboundInterface)
 	sbic["default"] = sbi
 	devices := make(map[uuid.UUID]*Device)
 	return &pndImplementation{
-		name:    name,
-		sbi:     sbic,
-		devices: devices,
+		name:        name,
+		description: description,
+		sbi:         sbic,
+		devices:     devices,
 	}
 }
 
+//GetName returns the name of the PND
+func (pnd *pndImplementation) GetName() string {
+	return pnd.name
+}
+
+//HasDevice checks if the given device uuid is registered for this PND
+func (pnd *pndImplementation) ContainsDevice(uuid uuid.UUID) bool {
+	_, exists := pnd.devices[uuid]
+	return exists
+}
+
+//GetDescription returns the current description of the PND
+func (pnd *pndImplementation) GetDescription() string {
+	return pnd.description
+}
+
+//GetSBIs returns the registered SBIs
+func (pnd *pndImplementation) GetSBIs() map[string]SouthboundInterface {
+	return pnd.sbi
+}
+
 // Interface satisfaction
 func (pnd *pndImplementation) Destroy() error {
 	return destroy()
 }
 
-func (pnd *pndImplementation) AddSbi() error {
-	return addSbi()
+//AddSbi adds a SBI to the PND which will be supported
+func (pnd *pndImplementation) AddSbi(sbi SouthboundInterface) error {
+	return pnd.addSbi(sbi)
 }
 
-func (pnd *pndImplementation) RemoveSbi() error {
-	return removeSbi()
+//AddSbi removes a SBI from the PND
+//TODO: this should to recursivly through
+//devices and remove the devices using
+//this SBI
+func (pnd *pndImplementation) RemoveSbi(sbiIdentifier string) error {
+	return pnd.removeSbi(sbiIdentifier)
 }
 
+//AddDevice adds a new device to the PND
 func (pnd *pndImplementation) AddDevice(device *Device) error {
 	return pnd.addDevice(device)
 }
 
+//RemoveDevice removes a device from the PND
 func (pnd *pndImplementation) RemoveDevice(uuid uuid.UUID) error {
 	return pnd.removeDevice(uuid)
 }
@@ -62,11 +99,13 @@ func destroy() error {
 	return nil
 }
 
-func addSbi() error {
+func (pnd *pndImplementation) addSbi(sbi SouthboundInterface) error {
+	pnd.sbi[sbi.SbiIdentifier()] = sbi
 	return nil
 }
 
-func removeSbi() error {
+func (pnd *pndImplementation) removeSbi(sbiIdentifier string) error {
+	delete(pnd.sbi, sbiIdentifier)
 	return nil
 }
 
@@ -80,16 +119,32 @@ func (pnd *pndImplementation) removeDevice(uuid uuid.UUID) error {
 	return nil
 }
 
+func (pnd *pndImplementation) MarshalDevice(uuid uuid.UUID) (string, error) {
+	d := pnd.devices[uuid]
+	json, err := json.MarshalIndent(d.GoStruct, "", "\t")
+	if err != nil {
+		return "", err
+	}
+
+	return string(json), nil
+}
+
+//Request sends a request for a specific device
 func (pnd *pndImplementation) Request(uuid uuid.UUID, path string) error {
 	d := pnd.devices[uuid]
 	ctx := context.Background()
-	_, err := d.Transport.Get(ctx, path)
+	res, err := d.Transport.Get(ctx, path)
+	if err != nil {
+		return err
+	}
+	err = d.Transport.ProcessResponse(res, d.GoStruct, d.SBI.Schema())
 	if err != nil {
 		return err
 	}
 	return nil
 }
 
+//RequestAll sends a request for all registered devices
 func (pnd *pndImplementation) RequestAll(path string) error {
 	for k := range pnd.devices {
 		if err := pnd.Request(k, path); err != nil {
diff --git a/nucleus/principalNetworkDomain_test.go b/nucleus/principalNetworkDomain_test.go
index 133195a8d7e0cf2a3203c2c1bfc6aa4d74602a52..a5712e995138512966054471d1a905aeaf8c7935 100644
--- a/nucleus/principalNetworkDomain_test.go
+++ b/nucleus/principalNetworkDomain_test.go
@@ -9,6 +9,7 @@ import (
 func TestNewPND(t *testing.T) {
 	type args struct {
 		name string
+		desc string
 		sbi  SouthboundInterface
 	}
 	tests := []struct {
@@ -20,7 +21,7 @@ func TestNewPND(t *testing.T) {
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			if got := NewPND(tt.args.name, tt.args.sbi); !reflect.DeepEqual(got, tt.want) {
+			if got := NewPND(tt.args.name, tt.args.desc, tt.args.sbi); !reflect.DeepEqual(got, tt.want) {
 				t.Errorf("NewPND() = %v, want %v", got, tt.want)
 			}
 		})
@@ -28,15 +29,32 @@ func TestNewPND(t *testing.T) {
 }
 
 func Test_addSbi(t *testing.T) {
+	type fields struct {
+		name    string
+		desc    string
+		sbi     map[string]SouthboundInterface
+		devices map[uuid.UUID]*Device
+	}
+	type args struct {
+		sbi SouthboundInterface
+	}
 	tests := []struct {
 		name    string
+		fields  fields
+		args    args
 		wantErr bool
 	}{
 		// TODO: Add test cases.
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			if err := addSbi(); (err != nil) != tt.wantErr {
+			pnd := &pndImplementation{
+				name:        tt.fields.name,
+				description: tt.fields.desc,
+				sbi:         tt.fields.sbi,
+				devices:     tt.fields.devices,
+			}
+			if err := pnd.addSbi(tt.args.sbi); (err != nil) != tt.wantErr {
 				t.Errorf("addSbi() error = %v, wantErr %v", err, tt.wantErr)
 			}
 		})
@@ -62,8 +80,9 @@ func Test_destroy(t *testing.T) {
 func Test_pndImplementation_AddDevice(t *testing.T) {
 	type fields struct {
 		name    string
+		desc    string
 		sbi     map[string]SouthboundInterface
-		devices map[uuid.UUID]Device
+		devices map[uuid.UUID]*Device
 	}
 	type args struct {
 		device Device
@@ -79,11 +98,12 @@ func Test_pndImplementation_AddDevice(t *testing.T) {
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			pnd := &pndImplementation{
-				name:    tt.fields.name,
-				sbi:     tt.fields.sbi,
-				devices: tt.fields.devices,
+				name:        tt.fields.name,
+				description: tt.fields.desc,
+				sbi:         tt.fields.sbi,
+				devices:     tt.fields.devices,
 			}
-			if err := pnd.AddDevice(tt.args.device); (err != nil) != tt.wantErr {
+			if err := pnd.AddDevice(&tt.args.device); (err != nil) != tt.wantErr {
 				t.Errorf("AddDevice() error = %v, wantErr %v", err, tt.wantErr)
 			}
 		})
@@ -94,11 +114,15 @@ func Test_pndImplementation_AddSbi(t *testing.T) {
 	type fields struct {
 		name    string
 		sbi     map[string]SouthboundInterface
-		devices map[uuid.UUID]Device
+		devices map[uuid.UUID]*Device
+	}
+	type args struct {
+		sbi SouthboundInterface
 	}
 	tests := []struct {
 		name    string
 		fields  fields
+		args    args
 		wantErr bool
 	}{
 		// TODO: Add test cases.
@@ -110,7 +134,7 @@ func Test_pndImplementation_AddSbi(t *testing.T) {
 				sbi:     tt.fields.sbi,
 				devices: tt.fields.devices,
 			}
-			if err := pnd.AddSbi(); (err != nil) != tt.wantErr {
+			if err := pnd.AddSbi(tt.args.sbi); (err != nil) != tt.wantErr {
 				t.Errorf("AddSbi() error = %v, wantErr %v", err, tt.wantErr)
 			}
 		})
@@ -121,7 +145,7 @@ func Test_pndImplementation_Destroy(t *testing.T) {
 	type fields struct {
 		name    string
 		sbi     map[string]SouthboundInterface
-		devices map[uuid.UUID]Device
+		devices map[uuid.UUID]*Device
 	}
 	tests := []struct {
 		name    string
@@ -148,7 +172,7 @@ func Test_pndImplementation_RemoveDevice(t *testing.T) {
 	type fields struct {
 		name    string
 		sbi     map[string]SouthboundInterface
-		devices map[uuid.UUID]Device
+		devices map[uuid.UUID]*Device
 	}
 	type args struct {
 		uuid uuid.UUID
@@ -179,11 +203,15 @@ func Test_pndImplementation_RemoveSbi(t *testing.T) {
 	type fields struct {
 		name    string
 		sbi     map[string]SouthboundInterface
-		devices map[uuid.UUID]Device
+		devices map[uuid.UUID]*Device
+	}
+	type args struct {
+		sbi SouthboundInterface
 	}
 	tests := []struct {
 		name    string
 		fields  fields
+		args    args
 		wantErr bool
 	}{
 		// TODO: Add test cases.
@@ -195,7 +223,7 @@ func Test_pndImplementation_RemoveSbi(t *testing.T) {
 				sbi:     tt.fields.sbi,
 				devices: tt.fields.devices,
 			}
-			if err := pnd.RemoveSbi(); (err != nil) != tt.wantErr {
+			if err := pnd.RemoveSbi(tt.args.sbi.SbiIdentifier()); (err != nil) != tt.wantErr {
 				t.Errorf("RemoveSbi() error = %v, wantErr %v", err, tt.wantErr)
 			}
 		})
@@ -206,7 +234,7 @@ func Test_pndImplementation_addDevice(t *testing.T) {
 	type fields struct {
 		name    string
 		sbi     map[string]SouthboundInterface
-		devices map[uuid.UUID]Device
+		devices map[uuid.UUID]*Device
 	}
 	type args struct {
 		device Device
@@ -226,7 +254,7 @@ func Test_pndImplementation_addDevice(t *testing.T) {
 				sbi:     tt.fields.sbi,
 				devices: tt.fields.devices,
 			}
-			if err := pnd.addDevice(tt.args.device); (err != nil) != tt.wantErr {
+			if err := pnd.addDevice(&tt.args.device); (err != nil) != tt.wantErr {
 				t.Errorf("addDevice() error = %v, wantErr %v", err, tt.wantErr)
 			}
 		})
@@ -237,7 +265,7 @@ func Test_pndImplementation_removeDevice(t *testing.T) {
 	type fields struct {
 		name    string
 		sbi     map[string]SouthboundInterface
-		devices map[uuid.UUID]Device
+		devices map[uuid.UUID]*Device
 	}
 	type args struct {
 		uuid uuid.UUID
@@ -265,15 +293,31 @@ func Test_pndImplementation_removeDevice(t *testing.T) {
 }
 
 func Test_removeSbi(t *testing.T) {
+	type fields struct {
+		name    string
+		sbi     map[string]SouthboundInterface
+		devices map[uuid.UUID]*Device
+	}
+	type args struct {
+		uuid uuid.UUID
+		sbi  SouthboundInterface
+	}
 	tests := []struct {
 		name    string
+		fields  fields
+		args    args
 		wantErr bool
 	}{
 		// TODO: Add test cases.
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			if err := removeSbi(); (err != nil) != tt.wantErr {
+			pnd := &pndImplementation{
+				name:    tt.fields.name,
+				sbi:     tt.fields.sbi,
+				devices: tt.fields.devices,
+			}
+			if err := pnd.removeSbi(tt.args.sbi.SbiIdentifier()); (err != nil) != tt.wantErr {
 				t.Errorf("removeSbi() error = %v, wantErr %v", err, tt.wantErr)
 			}
 		})