Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

resolve network instance switch creation problem #593

Merged
merged 1 commit into from
Apr 30, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/edenNetwork.go
Original file line number Diff line number Diff line change
@@ -152,5 +152,5 @@ func networkInit() {
networkCmd.AddCommand(networkCreateCmd)
networkCreateCmd.Flags().StringVar(&networkType, "type", "local", "Type of network: local or switch")
networkCreateCmd.Flags().StringVarP(&networkName, "name", "n", "", "Name of network (empty for auto generation)")
networkCreateCmd.Flags().StringVarP(&uplinkAdapter, "uplink", "u", "eth0", "Name of uplink adapter")
networkCreateCmd.Flags().StringVarP(&uplinkAdapter, "uplink", "u", "eth0", "Name of uplink adapter, set to 'none' to not use uplink")
}
22 changes: 19 additions & 3 deletions cmd/edenPod.go
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ package cmd

import (
"fmt"
"strings"

"github.com/dustin/go-humanize"
"github.com/lf-edge/eden/pkg/controller/eapps"
@@ -53,6 +54,19 @@ var podCmd = &cobra.Command{
Use: "pod",
}

func processAcls(acls []string) map[string][]string {
m := map[string][]string{}
for _, el := range acls {
parsed := strings.SplitN(el, ":", 2)
if len(parsed) > 1 {
m[parsed[0]] = append(m[parsed[0]], parsed[1])
} else {
m[""] = append(m[""], parsed[0])
}
}
return m
}

//podDeployCmd is command for deploy application on EVE
var podDeployCmd = &cobra.Command{
Use: "deploy (docker|http(s)|file)://(<TAG>[:<VERSION>] | <URL for qcow2 image> | <path to qcow2 image>)",
@@ -105,9 +119,9 @@ var podDeployCmd = &cobra.Command{
opts = append(opts, expect.WithResources(appCpus, uint32(appMemoryParsed/1000)))
opts = append(opts, expect.WithImageFormat(imageFormat))
if aclOnlyHost {
opts = append(opts, expect.WithACL([]string{""}))
opts = append(opts, expect.WithACL(map[string][]string{"": {""}}))
} else {
opts = append(opts, expect.WithACL(acl))
opts = append(opts, expect.WithACL(processAcls(acl)))
}
opts = append(opts, expect.WithSFTPLoad(sftpLoad))
if !sftpLoad {
@@ -449,7 +463,9 @@ func podInit() {
podDeployCmd.Flags().BoolVar(&directLoad, "direct", true, "Use direct download for image instead of eserver")
podDeployCmd.Flags().BoolVar(&sftpLoad, "sftp", false, "Force use of sftp to load http/file image from eserver")
podDeployCmd.Flags().StringSliceVar(&disks, "disks", nil, "Additional disks to use")
podDeployCmd.Flags().StringSliceVar(&acl, "acl", nil, "Allow access only to defined hosts/ips/subnets")
podDeployCmd.Flags().StringSliceVar(&acl, "acl", nil, `Allow access only to defined hosts/ips/subnets
You can set acl for particular network in format '<network_name:acl>'
To remove acls you can set empty line '<network_name>:'`)
podCmd.AddCommand(podPsCmd)
podCmd.AddCommand(podStopCmd)
podCmd.AddCommand(podStartCmd)
47 changes: 39 additions & 8 deletions cmd/podModify.go
Original file line number Diff line number Diff line change
@@ -31,26 +31,51 @@ var podModifyCmd = &cobra.Command{
if err != nil {
log.Fatalf("getControllerAndDev: %s", err)
}
for _, el := range dev.GetApplicationInstances() {
app, err := ctrl.GetApplicationInstanceConfig(el)
for _, appID := range dev.GetApplicationInstances() {
app, err := ctrl.GetApplicationInstanceConfig(appID)
if err != nil {
log.Fatalf("no app in cloud %s: %s", el, err)
log.Fatalf("no app in cloud %s: %s", appID, err)
}
if app.Displayname == appName {
portPublishCombined := portPublish
if !cmd.Flags().Changed("publish") {
portPublishCombined = []string{}
for _, intf := range app.Interfaces {
for _, acls := range intf.Acls {
lport := ""
var appPort uint32
for _, match := range acls.Matches {
if match.Type == "lport" {
lport = match.Value
break
}
}
for _, action := range acls.Actions {
if action.Portmap {
appPort = action.AppPort
break
}
}
if lport != "" && appPort != 0 {
portPublishCombined = append(portPublishCombined, fmt.Sprintf("%s:%d", lport, appPort))
}
}
}
}
var opts []expect.ExpectationOption
if len(podNetworks) > 0 {
for i, el := range podNetworks {
if i == 0 {
//allocate ports on first network
opts = append(opts, expect.AddNetInstanceNameAndPortPublish(el, portPublish))
opts = append(opts, expect.AddNetInstanceNameAndPortPublish(el, portPublishCombined))
} else {
opts = append(opts, expect.AddNetInstanceNameAndPortPublish(el, nil))
}
}
} else {
opts = append(opts, expect.WithPortsPublish(portPublish))
opts = append(opts, expect.WithPortsPublish(portPublishCombined))
}
opts = append(opts, expect.WithACL(acl))
opts = append(opts, expect.WithACL(processAcls(acl)))
opts = append(opts, expect.WithOldApp(appName))
expectation := expect.AppExpectationFromURL(ctrl, dev, defaults.DefaultDummyExpect, appName, opts...)
appInstanceConfig := expectation.Application()
@@ -59,7 +84,11 @@ var podModifyCmd = &cobra.Command{
needPurge = true
} else {
for ind, el := range app.Interfaces {
if el.NetworkId != appInstanceConfig.Interfaces[ind].NetworkId {
equals, err := utils.CompareProtoMessages(el, appInstanceConfig.Interfaces[ind])
if err != nil {
log.Fatalf("CompareMessages: %v", err)
}
if !equals {
needPurge = true
break
}
@@ -89,5 +118,7 @@ func podModifyInit() {
podModifyCmd.Flags().StringSliceVarP(&portPublish, "publish", "p", nil, "Ports to publish in format EXTERNAL_PORT:INTERNAL_PORT")
podModifyCmd.Flags().BoolVar(&aclOnlyHost, "only-host", false, "Allow access only to host and external networks")
podModifyCmd.Flags().StringSliceVar(&podNetworks, "networks", nil, "Networks to connect to app (ports will be mapped to first network)")
podModifyCmd.Flags().StringSliceVar(&acl, "acl", nil, "Allow access only to defined hosts/ips/subnets")
podModifyCmd.Flags().StringSliceVar(&acl, "acl", nil, `Allow access only to defined hosts/ips/subnets
You can set acl for particular network in format '<network_name:acl>'
To remove acls you can set empty line '<network_name>:'`)
}
4 changes: 2 additions & 2 deletions pkg/expect/expectation.go
Original file line number Diff line number Diff line change
@@ -63,7 +63,7 @@ type AppExpectation struct {
sftpLoad bool

disks []string
acl []string
acl map[string][]string // networkInstanceName -> acls
}

//AppExpectationFromURL init AppExpectation with defined:
@@ -137,7 +137,7 @@ func AppExpectationFromURL(ctrl controller.Cloud, device *device.Ctx, appLink st
if err != nil {
log.Fatalf("Port map port %s could not be converted to Integer", qv)
}
if portNum == extPort || (portNum + defaults.DefaultPortMapOffset) == extPort {
if portNum == extPort || (portNum+defaults.DefaultPortMapOffset) == extPort {
ni.ports[extPort] = intPort
continue exit
}
51 changes: 28 additions & 23 deletions pkg/expect/networkInstance.go
Original file line number Diff line number Diff line change
@@ -7,7 +7,6 @@ import (
"time"

"github.com/docker/docker/pkg/namesgenerator"
"github.com/lf-edge/eden/pkg/models"
"github.com/lf-edge/eden/pkg/utils"
"github.com/lf-edge/eve/api/go/config"
"github.com/lf-edge/eve/api/go/evecommon"
@@ -30,7 +29,7 @@ func (exp *AppExpectation) checkNetworkInstance(netInst *config.NetworkInstanceC
if netInst == nil {
return false
}
if netInst.Ip.Subnet == instanceExpect.subnet || //if subnet defined and the same
if (netInst.Ip.Subnet != "" && netInst.Ip.Subnet == instanceExpect.subnet) || //if subnet defined and the same
(instanceExpect.name != "" && netInst.Displayname == instanceExpect.name) || //if name defined and the same
(instanceExpect.netInstType == "switch" && netInst.InstType == config.ZNetworkInstType_ZnetInstSwitch) { //only one switch for now
return true
@@ -45,9 +44,10 @@ func (exp *AppExpectation) createNetworkInstance(instanceExpect *NetInstanceExpe
if err != nil {
return nil, err
}
subentIPs := utils.GetSubnetIPs(instanceExpect.subnet)
adapter := exp.uplinkAdapter
if instanceExpect.uplinkAdapter != "" {
if instanceExpect.uplinkAdapter == "none" {
adapter = nil
} else if instanceExpect.uplinkAdapter != "" {
adapter = &config.Adapter{
Name: instanceExpect.uplinkAdapter,
Type: evecommon.PhyIoType_PhyIoNetEth,
@@ -63,25 +63,22 @@ func (exp *AppExpectation) createNetworkInstance(instanceExpect *NetInstanceExpe
Port: adapter,
Cfg: &config.NetworkInstanceOpaqueConfig{},
IpType: config.AddressType_IPV4,
Ip: &config.Ipspec{
Ip: &config.Ipspec{},
Dns: nil,
}
if instanceExpect.netInstType == "switch" {
netInst.InstType = config.ZNetworkInstType_ZnetInstSwitch
} else {
subentIPs := utils.GetSubnetIPs(instanceExpect.subnet)
netInst.Ip = &config.Ipspec{
Subnet: instanceExpect.subnet,
Gateway: subentIPs[1].String(),
Dns: []string{subentIPs[1].String()},
DhcpRange: &config.IpRange{
Start: subentIPs[2].String(),
End: subentIPs[len(subentIPs)-2].String(),
},
},
Dns: nil,
}
if instanceExpect.netInstType == "switch" {
netInst.InstType = config.ZNetworkInstType_ZnetInstSwitch
devModel, err := models.GetDevModelByName(exp.ctrl.GetVars().DevModel)
if err != nil {
log.Fatal(err)
}
netInst.Port = &config.Adapter{Name: devModel.GetFirstAdapterForSwitches()}
netInst.Ip = &config.Ipspec{}
}
if instanceExpect.name == "" {
rand.Seed(time.Now().UnixNano())
@@ -109,7 +106,7 @@ func (exp *AppExpectation) NetworkInstances() (networkInstances map[*NetInstance
}
}
if networkInstance == nil { //if networkInstance not exists, create it
if ni.name != "" && ni.subnet == "" {
if ni.name != "" && ni.netInstType == "local" && ni.subnet == "" {
log.Fatalf("not found subnet with name %s", ni.name)
}
if networkInstance, err = exp.createNetworkInstance(ni); err != nil {
@@ -150,14 +147,22 @@ func parseACE(inp string) *config.ACE {
func (exp *AppExpectation) getAcls(ni *NetInstanceExpectation) []*config.ACE {
var acls []*config.ACE
var aclID int32 = 1
if exp.acl != nil {
if exp.acl != nil && len(exp.acl[ni.name]) > 0 {
// in case of defined acl allow access only to them
for _, el := range exp.acl {
acl := parseACE(el)
if acl != nil {
acl.Id = aclID
acls = append(acls, acl)
aclID++
for netName, acl := range exp.acl {
if netName != "" && netName != ni.name {
continue
}
for _, el := range acl {
if el == "" {
continue
}
acl := parseACE(el)
if acl != nil {
acl.Id = aclID
acls = append(acls, acl)
aclID++
}
}
}
} else {
2 changes: 1 addition & 1 deletion pkg/expect/options.go
Original file line number Diff line number Diff line change
@@ -159,7 +159,7 @@ func WithVolumeType(volumesType VolumeType) ExpectationOption {
}

//WithACL sets access only for defined hosts
func WithACL(acl []string) ExpectationOption {
func WithACL(acl map[string][]string) ExpectationOption {
return func(expectation *AppExpectation) {
expectation.acl = acl
}
1 change: 0 additions & 1 deletion pkg/models/devModel.go
Original file line number Diff line number Diff line change
@@ -68,7 +68,6 @@ type DevModel interface {
SetPhysicalIOs([]*config.PhysicalIO)
AdapterForSwitches() []string
DevModelType() string
GetFirstAdapterForSwitches() string
SetWiFiParams(ssid string, psk string)
GetPortConfig(ssid string, psk string) string
DiskFormat() string
8 changes: 0 additions & 8 deletions pkg/models/gcp.go
Original file line number Diff line number Diff line change
@@ -82,14 +82,6 @@ func (ctx *DevModelGCP) DevModelType() string {
return string(devModelTypeGCP)
}

//GetFirstAdapterForSwitches return first adapter available for switch networkInstance
func (ctx *DevModelGCP) GetFirstAdapterForSwitches() string {
if len(ctx.adapterForSwitches) > 0 {
return ctx.adapterForSwitches[0]
}
return "uplink"
}

func createGCP() (DevModel, error) {
return &DevModelGCP{
physicalIOs: generatePhysicalIOs(1, 0, 0),
8 changes: 0 additions & 8 deletions pkg/models/general.go
Original file line number Diff line number Diff line change
@@ -82,14 +82,6 @@ func (ctx *DevModelGeneral) DevModelType() string {
return string(devModelTypeGeneral)
}

//GetFirstAdapterForSwitches return first adapter available for switch networkInstance
func (ctx *DevModelGeneral) GetFirstAdapterForSwitches() string {
if len(ctx.adapterForSwitches) > 0 {
return ctx.adapterForSwitches[0]
}
return "uplink"
}

func createGeneral() (DevModel, error) {
return &DevModelGeneral{
physicalIOs: generatePhysicalIOs(2, 0, 0),
5 changes: 0 additions & 5 deletions pkg/models/parallels.go
Original file line number Diff line number Diff line change
@@ -78,11 +78,6 @@ func (ctx *DevModelParallels) DevModelType() string {
return string(devModelTypeParallels)
}

//GetFirstAdapterForSwitches return first adapter available for switch networkInstance
func (ctx *DevModelParallels) GetFirstAdapterForSwitches() string {
return "uplink"
}

func createParallels() (DevModel, error) {
return &DevModelParallels{
physicalIOs: generatePhysicalIOs(2, 0, 4),
8 changes: 0 additions & 8 deletions pkg/models/qemu.go
Original file line number Diff line number Diff line change
@@ -76,14 +76,6 @@ func (ctx *DevModelQemu) DevModelType() string {
return string(devModelTypeQemu)
}

//GetFirstAdapterForSwitches return first adapter available for switch networkInstance
func (ctx *DevModelQemu) GetFirstAdapterForSwitches() string {
if len(ctx.adapterForSwitches) > 0 {
return ctx.adapterForSwitches[0]
}
return "uplink"
}

func createQemu() (DevModel, error) {
return &DevModelQemu{
physicalIOs: generatePhysicalIOs(2, 0, 4),
5 changes: 0 additions & 5 deletions pkg/models/rpi.go
Original file line number Diff line number Diff line change
@@ -146,11 +146,6 @@ func (ctx *DevModelRpi) DevModelType() string {
return string(devModelTypeRaspberry)
}

//GetFirstAdapterForSwitches return first adapter available for switch networkInstance
func (ctx *DevModelRpi) GetFirstAdapterForSwitches() string {
return "uplink"
}

func createRpi() (DevModel, error) {
return &DevModelRpi{
physicalIOs: generatePhysicalIOs(1, 1, 0),
8 changes: 0 additions & 8 deletions pkg/models/vbox.go
Original file line number Diff line number Diff line change
@@ -79,14 +79,6 @@ func (ctx *DevModelVBox) DevModelType() string {
return string(devModelTypeVBox)
}

//GetFirstAdapterForSwitches return first adapter available for switch networkInstance
func (ctx *DevModelVBox) GetFirstAdapterForSwitches() string {
if len(ctx.adapterForSwitches) > 0 {
return ctx.adapterForSwitches[0]
}
return "uplink"
}

func createVBox() (DevModel, error) {
return &DevModelVBox{
physicalIOs: generatePhysicalIOs(2, 0, 4),
21 changes: 21 additions & 0 deletions pkg/utils/proto.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package utils

import (
"bytes"
"fmt"

"google.golang.org/protobuf/proto"
)

//CompareProtoMessages returns true if messages are equal
func CompareProtoMessages(m1, m2 proto.Message) (bool, error) {
m1Data, err := proto.Marshal(m1)
if err != nil {
return false, fmt.Errorf("cannot marshal interface: %v", err)
}
m2Data, err := proto.Marshal(m2)
if err != nil {
return false, fmt.Errorf("cannot marshal interface: %v", err)
}
return bytes.Equal(m1Data, m2Data), nil
}