diff --git a/cli/cli_test.go b/cli/cli_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..df6c6ec4d09668c3cf7996599a03bf129441ccf4
--- /dev/null
+++ b/cli/cli_test.go
@@ -0,0 +1,259 @@
+package cli
+
+import (
+	"code.fbi.h-da.de/cocsn/gosdn/forks/google/gnmi"
+	"context"
+	gpb "github.com/openconfig/gnmi/proto/gnmi"
+	"github.com/openconfig/ygot/ygot"
+	"reflect"
+	"testing"
+)
+
+func TestCapabilities(t *testing.T) {
+	type args struct {
+		a string
+		u string
+		p string
+	}
+	tests := []struct {
+		name    string
+		args    args
+		wantErr bool
+	}{
+		// TODO: Add test cases.
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if err := Capabilities(tt.args.a, tt.args.u, tt.args.p); (err != nil) != tt.wantErr {
+				t.Errorf("Capabilities() error = %v, wantErr %v", err, tt.wantErr)
+			}
+		})
+	}
+}
+
+func TestGet(t *testing.T) {
+	type args struct {
+		a    string
+		u    string
+		p    string
+		args []string
+	}
+	tests := []struct {
+		name    string
+		args    args
+		wantErr bool
+	}{
+		// TODO: Add test cases.
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if err := Get(tt.args.a, tt.args.u, tt.args.p, tt.args.args...); (err != nil) != tt.wantErr {
+				t.Errorf("Get() error = %v, wantErr %v", err, tt.wantErr)
+			}
+		})
+	}
+}
+
+func TestHttpGet(t *testing.T) {
+	type args struct {
+		apiEndpoint string
+		f           string
+		args        []string
+	}
+	tests := []struct {
+		name    string
+		args    args
+		wantErr bool
+	}{
+		// TODO: Add test cases.
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if err := HttpGet(tt.args.apiEndpoint, tt.args.f, tt.args.args...); (err != nil) != tt.wantErr {
+				t.Errorf("HttpGet() error = %v, wantErr %v", err, tt.wantErr)
+			}
+		})
+	}
+}
+
+func TestLeafPaths(t *testing.T) {
+	tests := []struct {
+		name    string
+		wantErr bool
+	}{
+		// TODO: Add test cases.
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if err := LeafPaths(); (err != nil) != tt.wantErr {
+				t.Errorf("LeafPaths() error = %v, wantErr %v", err, tt.wantErr)
+			}
+		})
+	}
+}
+
+func TestPathTraversal(t *testing.T) {
+	tests := []struct {
+		name    string
+		wantErr bool
+	}{
+		// TODO: Add test cases.
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if err := PathTraversal(); (err != nil) != tt.wantErr {
+				t.Errorf("PathTraversal() error = %v, wantErr %v", err, tt.wantErr)
+			}
+		})
+	}
+}
+
+func TestSet(t *testing.T) {
+	type args struct {
+		a    string
+		u    string
+		p    string
+		typ  string
+		args []string
+	}
+	tests := []struct {
+		name    string
+		args    args
+		wantErr bool
+	}{
+		// TODO: Add test cases.
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if err := Set(tt.args.a, tt.args.u, tt.args.p, tt.args.typ, tt.args.args...); (err != nil) != tt.wantErr {
+				t.Errorf("Set() error = %v, wantErr %v", err, tt.wantErr)
+			}
+		})
+	}
+}
+
+func TestSubscribe(t *testing.T) {
+	type args struct {
+		a         string
+		u         string
+		p         string
+		sample    int64
+		heartbeat int64
+		args      []string
+	}
+	tests := []struct {
+		name    string
+		args    args
+		wantErr bool
+	}{
+		// TODO: Add test cases.
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if err := Subscribe(tt.args.a, tt.args.u, tt.args.p, tt.args.sample, tt.args.heartbeat, tt.args.args...); (err != nil) != tt.wantErr {
+				t.Errorf("Subscribe() error = %v, wantErr %v", err, tt.wantErr)
+			}
+		})
+	}
+}
+
+func TestTarget(t *testing.T) {
+	type args struct {
+		bindAddr string
+	}
+	tests := []struct {
+		name    string
+		args    args
+		wantErr bool
+	}{
+		// TODO: Add test cases.
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if err := Target(tt.args.bindAddr); (err != nil) != tt.wantErr {
+				t.Errorf("Target() error = %v, wantErr %v", err, tt.wantErr)
+			}
+		})
+	}
+}
+
+func Test_callback(t *testing.T) {
+	type args struct {
+		newConfig ygot.ValidatedGoStruct
+	}
+	tests := []struct {
+		name    string
+		args    args
+		wantErr bool
+	}{
+		// TODO: Add test cases.
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if err := callback(tt.args.newConfig); (err != nil) != tt.wantErr {
+				t.Errorf("callback() error = %v, wantErr %v", err, tt.wantErr)
+			}
+		})
+	}
+}
+
+func Test_newServer(t *testing.T) {
+	type args struct {
+		model  *gnmi.Model
+		config []byte
+	}
+	tests := []struct {
+		name    string
+		args    args
+		want    *server
+		wantErr bool
+	}{
+		// TODO: Add test cases.
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			got, err := newServer(tt.args.model, tt.args.config)
+			if (err != nil) != tt.wantErr {
+				t.Errorf("newServer() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("newServer() got = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func Test_server_Get(t *testing.T) {
+	type fields struct {
+		Server *gnmi.Server
+	}
+	type args struct {
+		ctx context.Context
+		req *gpb.GetRequest
+	}
+	tests := []struct {
+		name    string
+		fields  fields
+		args    args
+		want    *gpb.GetResponse
+		wantErr bool
+	}{
+		// TODO: Add test cases.
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			s := &server{
+				Server: tt.fields.Server,
+			}
+			got, err := s.Get(tt.args.ctx, tt.args.req)
+			if (err != nil) != tt.wantErr {
+				t.Errorf("Get() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("Get() got = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
diff --git a/cli/http.go b/cli/http.go
index 2554574f2657fdd9dd845f1d77cdd7546a202300..1dc35dd178006d65a8813a8e92bfb95d0d216f79 100644
--- a/cli/http.go
+++ b/cli/http.go
@@ -3,6 +3,7 @@ package cli
 import (
 	"fmt"
 	log "github.com/sirupsen/logrus"
+	"github.com/spf13/viper"
 	"io/ioutil"
 	"net/http"
 	"strings"
@@ -33,7 +34,15 @@ func HttpGet(apiEndpoint, f string, args ...string) error {
 		if err != nil {
 			return err
 		}
-		fmt.Println(string(bytes))
+		if f == "init" {
+			pnd := string(bytes[:36])
+			sbi := string(bytes[36:])
+			viper.Set("CLI_PND", pnd)
+			viper.Set("CLI_SBI", sbi)
+			return viper.WriteConfig()
+		} else {
+			fmt.Println(string(bytes))
+		}
 	case http.StatusCreated:
 		defer resp.Body.Close()
 		bytes, err := ioutil.ReadAll(resp.Body)
diff --git a/cmd/addDevice.go b/cmd/addDevice.go
index 59260a3c6e0b206183652b864ae94665efa8733a..66b68e55bc4b103ff1e823fc11fe305a0f725f84 100644
--- a/cmd/addDevice.go
+++ b/cmd/addDevice.go
@@ -48,6 +48,8 @@ var addDeviceCmd = &cobra.Command{
 			"address="+address,
 			"password="+password,
 			"username="+username,
+			"sbi="+cliSbi,
+			"pnd="+cliPnd,
 		)
 	},
 }
diff --git a/cmd/cli.go b/cmd/cli.go
index 86e2891e1d21e94b9918205deeab67c895a4111e..36ea21d806d15d8d375dad55a220f8fd1c102a16 100644
--- a/cmd/cli.go
+++ b/cmd/cli.go
@@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE.
 package cmd
 
 import (
-	"errors"
+	"code.fbi.h-da.de/cocsn/gosdn/cli"
 	"github.com/spf13/cobra"
 )
 
@@ -45,7 +45,7 @@ var cliCmd = &cobra.Command{
 	Short: "",
 	Long:  ``,
 	RunE: func(cmd *cobra.Command, args []string) error {
-		return errors.New("no subcommand provided")
+		return cli.HttpGet(apiEndpoint, "init")
 	},
 }
 
@@ -54,4 +54,5 @@ func init() {
 
 	cliCmd.PersistentFlags().StringVar(&uuid, "uuid", "", "uuid of the requested device")
 	cliCmd.PersistentFlags().StringVar(&apiEndpoint, "api-endpoint", "http://localhost:8080", "address of the target")
+
 }
diff --git a/cmd/cliSet.go b/cmd/cliSet.go
index a06cf887eb45c7aa62cf37e9607f2ec501820040..b16b4b8f5f865a4b9d129df16060e204da16fa4e 100644
--- a/cmd/cliSet.go
+++ b/cmd/cliSet.go
@@ -46,6 +46,8 @@ var cliSetCmd = &cobra.Command{
 			apiEndpoint,
 			"set",
 			"uuid="+uuid,
+			"cliSbi="+cliSbi,
+			"cliPnd="+cliPnd,
 			"path="+args[0],
 			"address="+address,
 			"value="+args[1],
diff --git a/cmd/getDevice.go b/cmd/getDevice.go
index 7cebe7e81f1e3e49d0ebbaed97d524c9edf059f9..1e36a0017be0d51917fddc557f5fb5641f60dc1d 100644
--- a/cmd/getDevice.go
+++ b/cmd/getDevice.go
@@ -42,7 +42,13 @@ var getDeviceCmd = &cobra.Command{
 	Short: "gets device information from the controller",
 	Long:  ``,
 	RunE: func(cmd *cobra.Command, args []string) error {
-		return cli.HttpGet(apiEndpoint, "getDevice", "uuid="+uuid)
+		return cli.HttpGet(
+			apiEndpoint,
+			"getDevice",
+			"uuid="+uuid,
+			"sbi="+cliSbi,
+			"pnd="+cliPnd,
+			)
 	},
 }
 
diff --git a/cmd/init.go b/cmd/init.go
new file mode 100644
index 0000000000000000000000000000000000000000..17fb0ca83c6fbc2ca0c8f2e3e0de0823edebc437
--- /dev/null
+++ b/cmd/init.go
@@ -0,0 +1,60 @@
+/*
+Copyright © 2021 da/net research group <danet.fbi.h-da.de>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+package cmd
+
+import (
+	"code.fbi.h-da.de/cocsn/gosdn/cli"
+	"github.com/spf13/cobra"
+)
+
+// initCmd represents the init command
+var initCmd = &cobra.Command{
+	Use:   "init",
+	Short: "initialise SBI and PND",
+	Long:  ``,
+	RunE: func(cmd *cobra.Command, args []string) error {
+		return cli.HttpGet(apiEndpoint, "init" )
+	},
+}
+
+func init() {
+	cliCmd.AddCommand(initCmd)
+
+	// Here you will define your flags and configuration settings.
+
+	// Cobra supports Persistent Flags which will work for this command
+	// and all subcommands, e.g.:
+	// initCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+	// Cobra supports local flags which will only run when this command
+	// is called directly, e.g.:
+	// initCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/cmd/request.go b/cmd/request.go
index 9aaa75f6dc5a087d72a5765c80a1230367b3565c..a0c81e8a2a158bdd85934806e425e2b33da8fb21 100644
--- a/cmd/request.go
+++ b/cmd/request.go
@@ -42,7 +42,14 @@ var requestCmd = &cobra.Command{
 	Short: "requests a path from a specified device on the controller",
 	Long:  ``,
 	RunE: func(cmd *cobra.Command, args []string) error {
-		return cli.HttpGet(apiEndpoint, "request", "uuid="+uuid, "path="+args[0])
+		return cli.HttpGet(
+			apiEndpoint,
+			"request",
+			"uuid="+uuid,
+			"sbi="+cliSbi,
+			"pnd="+cliPnd,
+			"path="+args[0],
+			)
 	},
 }
 
diff --git a/cmd/requestAll.go b/cmd/requestAll.go
index 54ee211d911ce138491fa90e9273fa2b86735c03..76aabb320f59b0ababc2623b22ce3efa43a4f381 100644
--- a/cmd/requestAll.go
+++ b/cmd/requestAll.go
@@ -42,7 +42,13 @@ var requestAllCmd = &cobra.Command{
 	Short: "requests specified path from all devices on the controller",
 	Long:  ``,
 	RunE: func(cmd *cobra.Command, args []string) error {
-		return cli.HttpGet(apiEndpoint, "requestAll", "path="+args[0])
+		return cli.HttpGet(
+			apiEndpoint,
+			"requestAll",
+			"sbi="+cliSbi,
+			"pnd="+cliPnd,
+			"path="+args[0],
+			)
 	},
 }
 
diff --git a/cmd/root.go b/cmd/root.go
index ca20379fa3ca69fb47da76553dd7e076567ad4bb..ca92d95ce6b98af7d52ac3e7520b7f144ca1459f 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -47,12 +47,14 @@ var password string
 var address string
 var loglevel string
 var grpcPort string
+var cliPnd string
+var cliSbi string
 
 // rootCmd represents the base command when called without any subcommands
 var rootCmd = &cobra.Command{
 	Use:   "gosdn",
 	Short: "starts the gosdn controller",
-	Long:  `Set GOSDN_DEBUG environment variable to enalbe debug logging.`,
+	Long:  `Set GOSDN_DEBUG environment variable to enable debug logging.`,
 	RunE: func(cmd *cobra.Command, args []string) error {
 		ctx, cancel := context.WithCancel(context.Background())
 		defer cancel()
@@ -105,6 +107,8 @@ func initConfig() {
 	}
 
 	viper.SetDefault("socket", ":"+grpcPort)
+	cliPnd = viper.GetString("CLI_PND")
+	cliSbi = viper.GetString("CLI_SBI")
 
 	loglevel = viper.GetString("GOSDN_LOG")
 	log.SetReportCaller(true)
diff --git a/nucleus/controller.go b/nucleus/controller.go
index df9752387ef13a4dd73ec7439b1e879ed64b4f77..9532f3ffbda4fac73445f7d02153c6bfcd56f640 100644
--- a/nucleus/controller.go
+++ b/nucleus/controller.go
@@ -20,7 +20,7 @@ type Core struct {
 var c *Core
 
 //Initialize does start-up housekeeping like reading controller config files
-func initialize(ctx context.Context) error {
+func initialize() error {
 	c = &Core{
 		database: database.Database{},
 		pndc:     pndStore{},
@@ -36,9 +36,9 @@ func initialize(ctx context.Context) error {
 	if err := createSouthboundInterfaces(); err != nil {
 		return err
 	}
-	// TODO: Start grpc listener here
 
-	if err := httpApi(ctx); err != nil {
+	// TODO: Start grpc listener here
+	if err := httpApi(); err != nil {
 		return err
 	}
 
@@ -48,14 +48,28 @@ func initialize(ctx context.Context) error {
 }
 
 // deprecated
-// AttachDatabase connects to the database and passes the connection to the controller core
+// attachDatabase connects to the database and passes the connection to the controller core
 func attachDatabase() {
 	c.database = database.NewDatabaseClient()
 }
 
-// CreateSouthboundInterfaces initializes the controller with its supported SBIs
+// createSouthboundInterfaces initializes the controller with its supported SBIs
 func createSouthboundInterfaces() error {
-	if err := c.sbic.add(&OpenConfig{id: uuid.New()}); err != nil {
+	sbi := &OpenConfig{id: uuid.New()}
+	if err := c.sbic.add(sbi); err != nil {
+		return err
+	}
+	return createPrincipalNetworkDomain(sbi)
+}
+
+// createPrincipalNetworkDomain initializes the controller with an initial PND
+func createPrincipalNetworkDomain(sbi SouthboundInterface) error{
+	pnd, err := NewPND("base", "gosdn base pnd", uuid.New(), sbi)
+	if err != nil {
+		return err
+	}
+	err = c.pndc.add(pnd)
+	if err != nil {
 		return err
 	}
 	return nil
@@ -63,7 +77,7 @@ func createSouthboundInterfaces() error {
 
 // Run calls initialize to start the controller
 func Run(ctx context.Context) error {
-	if err := initialize(ctx); err != nil {
+	if err := initialize(); err != nil {
 		log.WithFields(log.Fields{}).Error(err)
 		return err
 	}
diff --git a/nucleus/errors_test.go b/nucleus/errors_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..09d172db926b14465fb4e16f641017a4f6d430ae
--- /dev/null
+++ b/nucleus/errors_test.go
@@ -0,0 +1,196 @@
+package nucleus
+
+import "testing"
+
+func TestErrAlreadyExists_Error(t *testing.T) {
+	type fields struct {
+		item interface{}
+	}
+	tests := []struct {
+		name   string
+		fields fields
+		want   string
+	}{
+		// TODO: Add test cases.
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			e := &ErrAlreadyExists{
+				item: tt.fields.item,
+			}
+			if got := e.Error(); got != tt.want {
+				t.Errorf("Error() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestErrInvalidParameters_Error(t *testing.T) {
+	type fields struct {
+		f interface{}
+		r interface{}
+	}
+	tests := []struct {
+		name   string
+		fields fields
+		want   string
+	}{
+		// TODO: Add test cases.
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			e := ErrInvalidParameters{
+				f: tt.fields.f,
+				r: tt.fields.r,
+			}
+			if got := e.Error(); got != tt.want {
+				t.Errorf("Error() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestErrInvalidTransportOptions_Error(t *testing.T) {
+	type fields struct {
+		t interface{}
+	}
+	tests := []struct {
+		name   string
+		fields fields
+		want   string
+	}{
+		// TODO: Add test cases.
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			e := ErrInvalidTransportOptions{
+				t: tt.fields.t,
+			}
+			if got := e.Error(); got != tt.want {
+				t.Errorf("Error() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestErrInvalidTypeAssertion_Error(t *testing.T) {
+	type fields struct {
+		v interface{}
+		t interface{}
+	}
+	tests := []struct {
+		name   string
+		fields fields
+		want   string
+	}{
+		// TODO: Add test cases.
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			e := ErrInvalidTypeAssertion{
+				v: tt.fields.v,
+				t: tt.fields.t,
+			}
+			if got := e.Error(); got != tt.want {
+				t.Errorf("Error() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestErrNilClient_Error(t *testing.T) {
+	tests := []struct {
+		name string
+		want string
+	}{
+		// TODO: Add test cases.
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			e := &ErrNilClient{}
+			if got := e.Error(); got != tt.want {
+				t.Errorf("Error() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestErrNil_Error(t *testing.T) {
+	tests := []struct {
+		name string
+		want string
+	}{
+		// TODO: Add test cases.
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			e := &ErrNil{}
+			if got := e.Error(); got != tt.want {
+				t.Errorf("Error() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestErrNotFound_Error(t *testing.T) {
+	type fields struct {
+		id interface{}
+	}
+	tests := []struct {
+		name   string
+		fields fields
+		want   string
+	}{
+		// TODO: Add test cases.
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			e := &ErrNotFound{
+				id: tt.fields.id,
+			}
+			if got := e.Error(); got != tt.want {
+				t.Errorf("Error() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestErrNotYetImplemented_Error(t *testing.T) {
+	tests := []struct {
+		name string
+		want string
+	}{
+		// TODO: Add test cases.
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			e := ErrNotYetImplemented{}
+			if got := e.Error(); got != tt.want {
+				t.Errorf("Error() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestErrUnsupportedPath_Error(t *testing.T) {
+	type fields struct {
+		p interface{}
+	}
+	tests := []struct {
+		name   string
+		fields fields
+		want   string
+	}{
+		// TODO: Add test cases.
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			e := ErrUnsupportedPath{
+				p: tt.fields.p,
+			}
+			if got := e.Error(); got != tt.want {
+				t.Errorf("Error() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
diff --git a/nucleus/http.go b/nucleus/http.go
index 5d6e17763a453df3296dd274da715e8ffac5203e..7693bcabd845652c9f0cb81cae78a0dbd1edfae6 100644
--- a/nucleus/http.go
+++ b/nucleus/http.go
@@ -2,7 +2,6 @@ package nucleus
 
 import (
 	"code.fbi.h-da.de/cocsn/gosdn/forks/goarista/gnmi"
-	"context"
 	"fmt"
 	"github.com/google/uuid"
 	gpb "github.com/openconfig/gnmi/proto/gnmi"
@@ -13,124 +12,154 @@ import (
 
 const basePath = "/api"
 
-func httpApi(ctx context.Context) (err error) {
-	id := c.sbic.UUIDs()[0]
-	sbi, err := c.sbic.get(id)
+// deprecated
+func httpApi() (err error) {
+	http.HandleFunc(basePath, httpHandler)
+	http.HandleFunc("/livez", healthCheck)
+	http.HandleFunc("/readyz", healthCheck)
+
+	go func() {
+		err = http.ListenAndServe(":8080", nil)
+		if err != nil {
+			return
+		}
+	}()
+	return nil
+}
+
+func healthCheck(writer http.ResponseWriter, request *http.Request) {
+	writer.WriteHeader(http.StatusOK)
+}
+
+func httpHandler(writer http.ResponseWriter, request *http.Request) {
+	log.WithFields(log.Fields{
+		"request": request,
+	}).Debug("incoming request")
+
+	query, err := url.ParseQuery(request.URL.RawQuery)
 	if err != nil {
+		log.Error(err)
 		return
 	}
-	pnd, err := NewPND("http", "http base pnd", uuid.New(), sbi)
+
+	id, err := uuid.Parse(query.Get("uuid"))
 	if err != nil {
-		return
+		log.Error(err)
 	}
-	err = c.pndc.add(pnd)
+
+	pid, err := uuid.Parse(query.Get("pnd"))
 	if err != nil {
-		return
+		log.Error(err)
 	}
 
-	httpHandler := func(writer http.ResponseWriter, request *http.Request) {
-		log.WithFields(log.Fields{
-			"request": request,
-		}).Debug("incoming request")
+	sid, err := uuid.Parse(query.Get("sbi"))
+	if err != nil {
+		log.Error(err)
+	}
 
-		query, err := url.ParseQuery(request.URL.RawQuery)
+	var pnd PrincipalNetworkDomain
+	var sbi SouthboundInterface
+	if query.Get("q") != "init" && query.Get("q") != "getIDs" {
+		pnd, err = c.pndc.get(pid)
 		if err != nil {
 			log.Error(err)
-			return
 		}
+		sbic := pnd.GetSBIs()
+		sbi, err = sbic.(*sbiStore).get(sid)
+	}
 
-		id, err := uuid.Parse(query.Get("uuid"))
+	switch query.Get("q") {
+	case "addDevice":
+		d, err := NewDevice(sbi, &GnmiTransportOptions{
+			Config: gnmi.Config{
+				Addr:     query.Get("address"),
+				Password: query.Get("password"),
+				Username: query.Get("username"),
+				Encoding: gpb.Encoding_JSON_IETF,
+			},
+			SetNode:   sbi.SetNode(),
+			Unmarshal: sbi.(*OpenConfig).Unmarshal(),
+			RespChan:  make(chan *gpb.SubscribeResponse),
+		})
+		err = pnd.AddDevice(d)
 		if err != nil {
+			writer.WriteHeader(http.StatusBadRequest)
 			log.Error(err)
+			return
 		}
-
-		switch query.Get("q") {
-		case "addDevice":
-			d, err := NewDevice(sbi, &GnmiTransportOptions{
-				Config: gnmi.Config{
-					Addr:     query.Get("address"),
-					Password: query.Get("password"),
-					Username: query.Get("username"),
-					Encoding: gpb.Encoding_JSON_IETF,
-				},
-				SetNode:   sbi.SetNode(),
-				Unmarshal: sbi.(*OpenConfig).Unmarshal(),
-				RespChan:  make(chan *gpb.SubscribeResponse),
-			})
-			err = pnd.AddDevice(d)
-			if err != nil {
-				writer.WriteHeader(http.StatusBadRequest)
-				log.Error(err)
-				return
-			}
-			writer.WriteHeader(http.StatusCreated)
-			fmt.Fprintf(writer, "device added\n")
-			fmt.Fprintf(writer, "UUID: %v\n", d.Uuid)
-		case "request":
-			err = pnd.Request(id, query.Get("path"))
-			if err != nil {
-				switch err.(type) {
-				case *ErrNotFound:
-					writer.WriteHeader(http.StatusNotFound)
-				default:
-					writer.WriteHeader(http.StatusInternalServerError)
-				}
-				log.Error(err)
-				return
+		writer.WriteHeader(http.StatusCreated)
+		fmt.Fprintf(writer, "device added\n")
+		fmt.Fprintf(writer, "UUID: %v\n", d.Uuid)
+	case "request":
+		err = pnd.Request(id, query.Get("path"))
+		if err != nil {
+			switch err.(type) {
+			case *ErrNotFound:
+				writer.WriteHeader(http.StatusNotFound)
+			default:
+				writer.WriteHeader(http.StatusInternalServerError)
 			}
-			writer.WriteHeader(http.StatusOK)
-		case "requestAll":
-			err = pnd.RequestAll(query.Get("path"))
-			if err != nil {
-				switch err.(type) {
-				case *ErrNotFound:
-					writer.WriteHeader(http.StatusNotFound)
-				default:
-					writer.WriteHeader(http.StatusInternalServerError)
-				}
-				log.Error(err)
-				return
+			log.Error(err)
+			return
+		}
+		writer.WriteHeader(http.StatusOK)
+	case "requestAll":
+		err = pnd.RequestAll(query.Get("path"))
+		if err != nil {
+			switch err.(type) {
+			case *ErrNotFound:
+				writer.WriteHeader(http.StatusNotFound)
+			default:
+				writer.WriteHeader(http.StatusInternalServerError)
 			}
-			writer.WriteHeader(http.StatusOK)
-		case "getDevice":
-			device, err := pnd.MarshalDevice(id)
-			if err != nil {
-				switch err.(type) {
-				case *ErrNotFound:
-					writer.WriteHeader(http.StatusNotFound)
-				default:
-					writer.WriteHeader(http.StatusInternalServerError)
-				}
-				log.Error(err)
-				return
+			log.Error(err)
+			return
+		}
+		writer.WriteHeader(http.StatusOK)
+	case "getDevice":
+		device, err := pnd.MarshalDevice(id)
+		if err != nil {
+			switch err.(type) {
+			case *ErrNotFound:
+				writer.WriteHeader(http.StatusNotFound)
+			default:
+				writer.WriteHeader(http.StatusInternalServerError)
 			}
-			writer.Header().Set("Content-Type", "application/json")
-			fmt.Fprintf(writer, "%v", device)
-		case "getIDs":
-			ids := pnd.(*pndImplementation).devices.UUIDs()
+			log.Error(err)
+			return
+		}
+		writer.Header().Set("Content-Type", "application/json")
+		fmt.Fprintf(writer, "%v", device)
+	case "getIDs":
+		writeIDs := func(typ string, ids []uuid.UUID) {
+			fmt.Fprintf(writer, "%v:\n", typ)
 			for i, id := range ids {
 				fmt.Fprintf(writer, "%v: %v\n", i+1, id)
 			}
-		case "set":
-			resp, err := pnd.(*pndImplementation).Set(id, query.Get("path"), query.Get("value"))
-			if err != nil {
-				writer.WriteHeader(http.StatusInternalServerError)
-				log.Error(err)
-				return
+		}
+		writeIDs("PNDs", c.pndc.UUIDs())
+		writeIDs("SBIs", c.sbic.UUIDs())
+		if pnd != nil {
+			writeIDs("Devices", pnd.(*pndImplementation).devices.UUIDs())
+		}
+	case "init":
+		writeIDs := func(typ string, ids []uuid.UUID) {
+			for _, id := range ids {
+				fmt.Fprintf(writer, "%v", id)
 			}
-			writer.WriteHeader(http.StatusOK)
-			fmt.Fprintln(writer, resp)
-		default:
-			writer.WriteHeader(http.StatusBadRequest)
 		}
-	}
-	http.HandleFunc(basePath, httpHandler)
-
-	go func() {
-		err = http.ListenAndServe(":8080", nil)
+		writeIDs("PNDs", c.pndc.UUIDs())
+		writeIDs("SBIs", c.sbic.UUIDs())
+	case "set":
+		resp, err := pnd.(*pndImplementation).Set(id, query.Get("path"), query.Get("value"))
 		if err != nil {
+			writer.WriteHeader(http.StatusInternalServerError)
+			log.Error(err)
 			return
 		}
-	}()
-	return nil
-}
+		writer.WriteHeader(http.StatusOK)
+		fmt.Fprintln(writer, resp)
+	default:
+		writer.WriteHeader(http.StatusBadRequest)
+	}
+}
\ No newline at end of file
diff --git a/nucleus/http_test.go b/nucleus/http_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..9221ee253c7b7d4890e472d98dcf9122f59d164c
--- /dev/null
+++ b/nucleus/http_test.go
@@ -0,0 +1,26 @@
+package nucleus
+
+import (
+	"context"
+	"testing"
+)
+
+func Test_httpApi(t *testing.T) {
+	type args struct {
+		ctx context.Context
+	}
+	tests := []struct {
+		name    string
+		args    args
+		wantErr bool
+	}{
+		// TODO: Add test cases.
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if err := httpApi(tt.args.ctx); (err != nil) != tt.wantErr {
+				t.Errorf("httpApi() error = %v, wantErr %v", err, tt.wantErr)
+			}
+		})
+	}
+}