Skip to content
Snippets Groups Projects
Commit 094ccd6c authored by Manuel Kieweg's avatar Manuel Kieweg
Browse files

mvp

parent 375f852f
No related branches found
No related tags found
1 merge request!155Northbound Interface
package cli
import (
"context"
"code.fbi.h-da.de/cocsn/gosdn/nucleus/errors"
"code.fbi.h-da.de/cocsn/gosdn/forks/goarista/gnmi"
"code.fbi.h-da.de/cocsn/gosdn/nucleus"
gpb "github.com/openconfig/gnmi/proto/gnmi"
log "github.com/sirupsen/logrus"
)
// Get sends a gNMI Get request to the specified target and prints the response to stdout
func Get(a, u, p string, args ...string) (*gpb.GetResponse, error) {
sbi := &nucleus.OpenConfig{}
opts := &nucleus.GnmiTransportOptions{
Config: gnmi.Config{
Addr: a,
Username: u,
Password: p,
Encoding: gpb.Encoding_JSON_IETF,
},
SetNode: sbi.SetNode(),
}
t, err := nucleus.NewGnmiTransport(opts)
if err != nil {
return nil, err
}
resp, err := t.Get(context.Background(), args...)
if err != nil {
return nil, err
}
log.Debug(resp)
r, ok := resp.(*gpb.GetResponse)
if !ok {
return nil, &errors.ErrInvalidTypeAssertion{}
}
return r, nil
}
package cli
import (
ppb "code.fbi.h-da.de/cocsn/api/go/gosdn/pnd"
nbi "code.fbi.h-da.de/cocsn/gosdn/northbound/client"
"context"
log "github.com/sirupsen/logrus"
"github.com/spf13/viper"
"time"
pb "code.fbi.h-da.de/cocsn/api/go/gosdn/core"
"google.golang.org/grpc"
)
// TODO: Delete once proper certs are set up
var grpcWithInsecure = grpc.WithInsecure()
func Init(addr string) error {
ctx := context.Background()
resp, err := getAllCore(ctx, addr)
if err != nil {
return err
}
if len(resp.Pnd) > 0 {
pid := resp.Pnd[0].Id
viper.Set("CLI_PND", pid)
log.Infof("PND: %v", pid)
if len(resp.Pnd[0].Sbi) != 0 {
sbi := resp.Pnd[0].Sbi[0].Id
viper.Set("CLI_SBI", sbi)
log.Infof("SBI: %v", sbi)
}
}
return nil
}
func GetIds(addr string) error {
ctx := context.Background()
resp, err := getAllCore(ctx, addr)
if err != nil {
return err
}
for i,pnd := range resp.Pnd {
log.Infof("PND %v: %v", i+1, pnd.Id)
for j,sbi := range pnd.Sbi {
log.Infof("\tSBI %v: %v", j+1, sbi.Id)
}
}
return nil
}
func getAllCore(ctx context.Context, addr string) (*pb.GetResponse, error) {
coreClient, err := nbi.CoreClient(addr, grpcWithInsecure)
if err != nil {
return nil, err
}
req := &pb.GetRequest{
Timestamp: time.Now().UnixNano(),
All: true,
}
return coreClient.Get(ctx, req)
}
func AddDevice(addr, username, password, sbi, pnd, deviceAddress string) error {
pndClient, err := nbi.PndClient(addr, grpcWithInsecure)
if err != nil {
return err
}
req := &ppb.SetRequest{
Timestamp: time.Now().UnixNano(),
Ond: []*ppb.SetOnd{
{
Address: deviceAddress,
Username: username,
Password: password,
Sbi: &ppb.SouthboundInterface{
Type: 0,
},
},
},
Pid: pnd,
}
ctx := context.Background()
resp, err := pndClient.Set(ctx, req)
if err != nil {
return err
}
log.Info(resp.String())
return nil
}
func GetDevice(addr, pid, path string, did ...string) error {
pndClient, err := nbi.PndClient(addr, grpcWithInsecure)
if err != nil {
return err
}
var all bool
if len(did) != 0 {
all = true
}
req := &ppb.GetRequest{
Timestamp: time.Now().UnixNano(),
Request: &ppb.GetRequest_Ond{
Ond: &ppb.GetOnd{
All: all,
Did: did,
},
},
Pid: pid,
}
ctx := context.Background()
resp, err := pndClient.Get(ctx, req)
if err != nil {
return err
}
log.Info(resp.String())
return nil
}
func Update(addr, did, pid, path, value string) error {
req := &ppb.ChangeRequest{
Id: did,
Path: path,
Value: value,
ApiOp: ppb.ChangeRequest_UPDATE,
}
return sendChangeRequest(addr, pid, req)
}
func Replace(addr, did, pid, path, value string) error {
req := &ppb.ChangeRequest{
Id: did,
Path: path,
Value: value,
ApiOp: ppb.ChangeRequest_REPLACE,
}
return sendChangeRequest(addr, pid, req)
}
func Delete(addr, did, pid, path string) error {
req := &ppb.ChangeRequest{
Id: did,
Path: path,
ApiOp: ppb.ChangeRequest_DELETE,
}
return sendChangeRequest(addr, pid, req)
}
func sendChangeRequest(addr, pid string, req *ppb.ChangeRequest) error {
pndClient, err := nbi.PndClient(addr, grpcWithInsecure)
if err != nil {
return err
}
ctx := context.Background()
r := &ppb.SetRequest{
Timestamp: time.Now().UnixNano(),
ChangeRequest: []*ppb.ChangeRequest{req},
Pid: pid,
}
resp, err := pndClient.Set(ctx, r)
if err != nil {
return err
}
log.Info(resp.String())
return nil
}
\ No newline at end of file
package cli
import (
model "code.fbi.h-da.de/cocsn/yang-models/generated/arista"
"github.com/openconfig/ygot/ytypes"
log "github.com/sirupsen/logrus"
)
var testSchema *ytypes.Schema
func init() {
var err error
testSchema, err = model.Schema()
if err != nil {
log.Fatal(err)
}
}
package cli
import (
"context"
"code.fbi.h-da.de/cocsn/gosdn/forks/goarista/gnmi"
"code.fbi.h-da.de/cocsn/gosdn/nucleus"
)
// Set sends a gNMI Set request to the specified target. Only one
// request per invocation supported.
func Set(a, u, p, typ string, args ...string) error {
opts := &nucleus.GnmiTransportOptions{
Config: gnmi.Config{
Addr: a,
Username: u,
Password: p,
},
}
t, err := nucleus.NewGnmiTransport(opts)
if err != nil {
return err
}
return t.Set(context.Background(), args)
}
...@@ -45,14 +45,13 @@ var addDeviceCmd = &cobra.Command{ ...@@ -45,14 +45,13 @@ var addDeviceCmd = &cobra.Command{
Device address and user credentials need to be provided Device address and user credentials need to be provided
if they diverge from the default credentials.`, if they diverge from the default credentials.`,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
return cli.HTTPGet( return cli.AddDevice(
apiEndpoint, apiEndpoint,
"addDevice",
"address="+address,
"password="+password,
"username="+username, "username="+username,
"sbi="+cliSbi, "password="+password,
"pnd="+cliPnd, "pnd="+cliPnd,
"sbi="+cliSbi,
"address="+address,
) )
}, },
} }
......
...@@ -44,14 +44,11 @@ var deleteCmd = &cobra.Command{ ...@@ -44,14 +44,11 @@ var deleteCmd = &cobra.Command{
Long: `Set a path value for a given device. Only one path and Long: `Set a path value for a given device. Only one path and
only one value supported for now`, only one value supported for now`,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
return cli.HTTPGet( return cli.Delete(
apiEndpoint, apiEndpoint,
"delete", uuid,
"uuid="+uuid, cliPnd,
"cliSbi="+cliSbi, args[0],
"cliPnd="+cliPnd,
"path="+args[0],
"address="+address,
) )
}, },
} }
......
/*
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"
)
// getCmd represents the get command
var getCmd = &cobra.Command{
Use: "gosdn get",
Short: "get request",
Long: `Sends a gNMI Get request to the specified target and
prints the response to stdout`,
RunE: func(cmd *cobra.Command, args []string) error {
_, err := cli.Get(address, username, password, args...)
return err
},
}
func init() {
rootCmd.AddCommand(getCmd)
}
...@@ -42,7 +42,7 @@ var getIdsCmd = &cobra.Command{ ...@@ -42,7 +42,7 @@ var getIdsCmd = &cobra.Command{
Short: "gets device IDs from the controller", Short: "gets device IDs from the controller",
Long: `Gets device IDs from the controller and lists them.`, Long: `Gets device IDs from the controller and lists them.`,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
return cli.HTTPGet(apiEndpoint, "getIDs") return cli.GetIds(apiEndpoint)
}, },
} }
......
...@@ -44,7 +44,7 @@ var initCmd = &cobra.Command{ ...@@ -44,7 +44,7 @@ var initCmd = &cobra.Command{
Same as invoking "gosdn cli" without any arguments`, Same as invoking "gosdn cli" without any arguments`,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
return cli.HTTPGet(apiEndpoint, "init") return cli.Init(apiEndpoint)
}, },
} }
......
...@@ -44,15 +44,12 @@ var replaceCmd = &cobra.Command{ ...@@ -44,15 +44,12 @@ var replaceCmd = &cobra.Command{
Long: `Set a path value for a given device. Only one path and Long: `Set a path value for a given device. Only one path and
only one value supported for now`, only one value supported for now`,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
return cli.HTTPGet( return cli.Replace(
apiEndpoint, apiEndpoint,
"replace", uuid,
"uuid="+uuid, cliPnd,
"cliSbi="+cliSbi, args[0],
"cliPnd="+cliPnd, args[1],
"path="+args[0],
"address="+address,
"value="+args[1],
) )
}, },
} }
......
...@@ -45,13 +45,11 @@ var requestCmd = &cobra.Command{ ...@@ -45,13 +45,11 @@ var requestCmd = &cobra.Command{
The request path is passed as positional argument.`, The request path is passed as positional argument.`,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
return cli.HTTPGet( return cli.GetDevice(
apiEndpoint, apiEndpoint,
"request", cliPnd,
"uuid="+uuid, args[0],
"sbi="+cliSbi, uuid,
"pnd="+cliPnd,
"path="+args[0],
) )
}, },
} }
......
...@@ -46,12 +46,10 @@ the controller. ...@@ -46,12 +46,10 @@ the controller.
The request path is passed as positional argument.`, The request path is passed as positional argument.`,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
return cli.HTTPGet( return cli.GetDevice(
apiEndpoint, apiEndpoint,
"requestAll", cliPnd,
"sbi="+cliSbi, args[0],
"pnd="+cliPnd,
"path="+args[0],
) )
}, },
} }
......
/*
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"
)
var typ string
// setCmd represents the set command
var setCmd = &cobra.Command{
Use: "set",
Short: "set request",
Long: `Sends a gNMI Set request to the specified target. Only one
request per invocation supported.`,
RunE: func(cmd *cobra.Command, args []string) error {
return cli.Set(address, username, password, typ, args...)
},
}
func init() {
rootCmd.AddCommand(setCmd)
setCmd.Flags().StringVarP(&typ, "type", "t", "update", "Type of the set request. "+
"Possible values: 'update', 'replace', and 'delete'")
}
...@@ -44,15 +44,12 @@ var updateCmd = &cobra.Command{ ...@@ -44,15 +44,12 @@ var updateCmd = &cobra.Command{
Long: `Update a path value for a given device. Only one path and Long: `Update a path value for a given device. Only one path and
only one value supported for now`, only one value supported for now`,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
return cli.HTTPGet( return cli.Update(
apiEndpoint, apiEndpoint,
"update", uuid,
"uuid="+uuid, cliPnd,
"cliSbi="+cliSbi, args[0],
"cliPnd="+cliPnd, args[1],
"path="+args[0],
"address="+address,
"value="+args[1],
) )
}, },
} }
......
...@@ -2,8 +2,6 @@ package gosdn ...@@ -2,8 +2,6 @@ package gosdn
import ( import (
"context" "context"
"github.com/spf13/viper"
"google.golang.org/grpc"
"net" "net"
"net/http" "net/http"
"os" "os"
...@@ -11,8 +9,11 @@ import ( ...@@ -11,8 +9,11 @@ import (
"sync" "sync"
"time" "time"
pb "code.fbi.h-da.de/cocsn/api/proto/gosdn" "github.com/spf13/viper"
ppb "code.fbi.h-da.de/cocsn/api/proto/gosdn/pnd" "google.golang.org/grpc"
pb "code.fbi.h-da.de/cocsn/api/go/gosdn/core"
ppb "code.fbi.h-da.de/cocsn/api/go/gosdn/pnd"
"code.fbi.h-da.de/cocsn/gosdn/database" "code.fbi.h-da.de/cocsn/gosdn/database"
nbi "code.fbi.h-da.de/cocsn/gosdn/northbound/server" nbi "code.fbi.h-da.de/cocsn/gosdn/northbound/server"
"code.fbi.h-da.de/cocsn/gosdn/nucleus" "code.fbi.h-da.de/cocsn/gosdn/nucleus"
...@@ -24,16 +25,15 @@ import ( ...@@ -24,16 +25,15 @@ import (
var coreLock sync.RWMutex var coreLock sync.RWMutex
var coreOnce sync.Once var coreOnce sync.Once
// Core is the representation of the controllers core // Core is the representation of the controller's core
type Core struct { type Core struct {
// deprecated // deprecated
database database.Database database database.Database
pndc *nucleus.PndStore pndc *nucleus.PndStore
sbic *nucleus.SbiStore
httpServer *http.Server httpServer *http.Server
grpcServer *grpc.Server grpcServer *grpc.Server
nbi *nbi.NorthboundInterface nbi *nbi.NorthboundInterface
stopChan chan os.Signal stopChan chan os.Signal
} }
...@@ -43,7 +43,6 @@ func init() { ...@@ -43,7 +43,6 @@ func init() {
c = &Core{ c = &Core{
database: database.Database{}, database: database.Database{},
pndc: nucleus.NewPndStore(), pndc: nucleus.NewPndStore(),
sbic: nucleus.NewSbiStore(),
stopChan: make(chan os.Signal, 1), stopChan: make(chan os.Signal, 1),
} }
...@@ -70,8 +69,8 @@ func startGrpcServer() error { ...@@ -70,8 +69,8 @@ func startGrpcServer() error {
return err return err
} }
c.grpcServer = grpc.NewServer() c.grpcServer = grpc.NewServer()
c.nbi = nbi.NewNBI(c.pndc, c.sbic) c.nbi = nbi.NewNBI(c.pndc)
pb.RegisterGosdnServer(c.grpcServer, c.nbi.Controller) pb.RegisterCoreServer(c.grpcServer, c.nbi.Core)
ppb.RegisterPndServer(c.grpcServer, c.nbi.Pnd) ppb.RegisterPndServer(c.grpcServer, c.nbi.Pnd)
go func() { go func() {
log.Fatal(c.grpcServer.Serve(lis)) log.Fatal(c.grpcServer.Serve(lis))
...@@ -82,9 +81,6 @@ func startGrpcServer() error { ...@@ -82,9 +81,6 @@ func startGrpcServer() error {
// createSouthboundInterfaces initializes the controller with its supported SBIs // createSouthboundInterfaces initializes the controller with its supported SBIs
func createSouthboundInterfaces() error { func createSouthboundInterfaces() error {
sbi := nucleus.NewSBI(types.Openconfig) sbi := nucleus.NewSBI(types.Openconfig)
if err := c.sbic.Add(sbi); err != nil {
return err
}
return createPrincipalNetworkDomain(sbi) return createPrincipalNetworkDomain(sbi)
} }
...@@ -128,5 +124,6 @@ func shutdown() error { ...@@ -128,5 +124,6 @@ func shutdown() error {
log.Info("shutting down controller") log.Info("shutting down controller")
coreLock.Lock() coreLock.Lock()
defer coreLock.Unlock() defer coreLock.Unlock()
c.grpcServer.GracefulStop()
return stopHttpServer() return stopHttpServer()
} }
...@@ -16,14 +16,15 @@ limitations under the License. ...@@ -16,14 +16,15 @@ limitations under the License.
package gnmi package gnmi
import ( import (
oc "code.fbi.h-da.de/cocsn/yang-models/generated/arista"
"errors" "errors"
"fmt" "fmt"
log "github.com/sirupsen/logrus"
"net" "net"
"reflect" "reflect"
"sort" "sort"
oc "code.fbi.h-da.de/cocsn/yang-models/generated/arista"
log "github.com/sirupsen/logrus"
"github.com/openconfig/goyang/pkg/yang" "github.com/openconfig/goyang/pkg/yang"
"github.com/openconfig/ygot/ygot" "github.com/openconfig/ygot/ygot"
"github.com/openconfig/ygot/ytypes" "github.com/openconfig/ygot/ytypes"
......
...@@ -3,9 +3,10 @@ package gosdn ...@@ -3,9 +3,10 @@ package gosdn
import ( import (
"context" "context"
"fmt" "fmt"
log "github.com/sirupsen/logrus"
"net/http" "net/http"
"time" "time"
log "github.com/sirupsen/logrus"
) )
func stopHttpServer() error { func stopHttpServer() error {
......
package client
package client
import (
pb "code.fbi.h-da.de/cocsn/api/go/gosdn/core"
"google.golang.org/grpc"
)
func CoreClient(addr string, opts ...grpc.DialOption) (pb.CoreClient, error) {
conn, err := grpc.Dial(addr, opts...)
if err != nil {
return nil, err
}
return pb.NewCoreClient(conn), nil
}
\ No newline at end of file
package client
import (
ppb "code.fbi.h-da.de/cocsn/api/go/gosdn/pnd"
"google.golang.org/grpc"
)
func PndClient(addr string, opts ...grpc.DialOption) (ppb.PndClient, error) {
conn, err := grpc.Dial(addr, opts...)
if err != nil {
return nil, err
}
return ppb.NewPndClient(conn), nil
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment