From 0d981dab3c531c2602a5067d784dba77d20553b9 Mon Sep 17 00:00:00 2001 From: John-Lin Date: Mon, 9 Jul 2018 18:57:17 +0800 Subject: [PATCH 1/2] change entity field Former-commit-id: 20121b3d4bb4cdb23b6ada1c2909cc5d33025089 [formerly 664ad3cb556402b7fb11879fe054df3058398d8f] Former-commit-id: e9797b52c8dacfc766ff02d1f57b391363a890a1 --- src/entity/network.go | 39 +++-- src/networkcontroller/network_controller.go | 133 +++++++----------- src/networkprovider/fake.go | 26 ++-- src/networkprovider/network.go | 12 +- src/networkprovider/ovs.go | 108 -------------- src/networkprovider/ovs_netdev.go | 99 +++++-------- src/networkprovider/ovs_system.go | 82 +++++++++++ .../{ovs_test.go => ovs_system_test.go} | 0 8 files changed, 226 insertions(+), 273 deletions(-) delete mode 100644 src/networkprovider/ovs.go create mode 100644 src/networkprovider/ovs_system.go rename src/networkprovider/{ovs_test.go => ovs_system_test.go} (100%) diff --git a/src/entity/network.go b/src/entity/network.go index 976fc1b9..9b32a269 100644 --- a/src/entity/network.go +++ b/src/entity/network.go @@ -18,19 +18,38 @@ const ( NetworkCollectionName string = "networks" ) +type PhyInterfaces struct { + Name string `bson:"name" json:"name"` + PCIID string `bson:"pciID" json:"pciID"` +} + +type Node struct { + Name string `bson:"name" json:"name"` + PhyInterfaces []PhyInterfaces `bson:"physicalInterface" json:"physicalInterface"` + + // Fake fields for restful testing + FakeParameter string `json:"fakeParameter"` + ShouldFail bool `json:"shoulFail"` +} + type Network struct { - ID bson.ObjectId `bson:"_id,omitempty" json:"id"` - Type NetworkType `bson:"type" json:"type"` - Name string `bson:"name" json:"name"` - Clusterwise bool `bson:"clusterwise" json:"clusterwise"` - NodeName string `bson:"nodeName,omitempty" json:"nodeName,omitempty"` - CreatedAt *time.Time `bson:"createdAt,omitempty" json:"createdAt,omitempty"` - OVS OVSNetwork `bson:"ovs,omitempty" json:"ovs"` - OVSUserspace OVSUserspaceNetwork `bson:"ovsUserspace,omitempty" json:"ovsUserspace"` - Fake FakeNetwork `json:"fake"` //FakeNetwork, for restful testing. + ID bson.ObjectId `bson:"_id,omitempty" json:"id"` + Type NetworkType `bson:"type" json:"type"` + IsDPDKPort bool `bson:"isDPDKPort" json:"isDPDKPort"` + Name string `bson:"name" json:"name"` + VLANTags []int32 `bson:"VLANTags" json:"VLANTags"` + BridgeName string `bson:"bridgeName" json:"bridgeName"` + Nodes []Node `bson:"nodes" json:"nodes"` + CreatedAt *time.Time `bson:"createdAt,omitempty" json:"createdAt,omitempty"` + + // Clusterwise bool `bson:"clusterwise" json:"clusterwise"` + // NodeName string `bson:"nodeName,omitempty" json:"nodeName,omitempty"` + // OVS OVSNetwork `bson:"ovs,omitempty" json:"ovs"` + // OVSUserspace OVSUserspaceNetwork `bson:"ovsUserspace,omitempty" json:"ovsUserspace"` + // Fake FakeNetwork `json:"fake"` //FakeNetwork, for restful testing. } -//GetCollection - get model mongo collection name. +// GetCollection - get model mongo collection name. func (m Network) GetCollection() string { return NetworkCollectionName } diff --git a/src/networkcontroller/network_controller.go b/src/networkcontroller/network_controller.go index 92d9df84..f168bd70 100644 --- a/src/networkcontroller/network_controller.go +++ b/src/networkcontroller/network_controller.go @@ -31,58 +31,44 @@ func New(serverAddress string) (*NetworkController, error) { }, nil } -func (nc *NetworkController) CreateOVSNetwork(bridgeName string, ports []entity.PhysicalPort) error { +func (nc *NetworkController) CreateOVSNetwork(datapathType string, bridgeName string, phyIface entity.PhyInterface, vlanTags []int32) error { if _, err := nc.ClientCtl.CreateBridge( nc.Context, &pb.CreateBridgeRequest{ BridgeName: bridgeName, - DatapathType: "system", + DatapathType: datapathType, }); err != nil { return err } - for _, port := range ports { - _, err := nc.ClientCtl.AddPort( - nc.Context, - &pb.AddPortRequest{ - BridgeName: bridgeName, - IfaceName: port.Name, - }) - if err != nil { - return err - } - - if len(port.VlanTags) > 0 { - _, err := nc.ClientCtl.SetPort( - nc.Context, - &pb.SetPortRequest{ - IfaceName: port.Name, - Options: &pb.PortOptions{ - VLANMode: "trunk", - Trunk: port.VlanTags, - }, - }) - if err != nil { - return err - } - } - } - return nil -} - -func (nc *NetworkController) DeleteOVSNetwork(bridgeName string) error { - _, err := nc.ClientCtl.DeleteBridge( + _, err := nc.ClientCtl.AddPort( nc.Context, - &pb.DeleteBridgeRequest{ + &pb.AddPortRequest{ BridgeName: bridgeName, + IfaceName: phyIface.Name, }) if err != nil { return err } + + if len(vlanTags) > 0 { + _, err := nc.ClientCtl.SetPort( + nc.Context, + &pb.SetPortRequest{ + IfaceName: phyIface.Name, + Options: &pb.PortOptions{ + VLANMode: "trunk", + Trunk: vlanTags, + }, + }) + if err != nil { + return err + } + } return nil } -func (nc *NetworkController) CreateOVSDPDKNetwork(bridgeName string, ports []entity.DPDKPhysicalPort) error { +func (nc *NetworkController) CreateOVSDPDKNetwork(bridgeName string, phyIface entity.PhyInterface, vlanTags []int32) error { if _, err := nc.ClientCtl.CreateBridge( nc.Context, &pb.CreateBridgeRequest{ @@ -92,71 +78,54 @@ func (nc *NetworkController) CreateOVSDPDKNetwork(bridgeName string, ports []ent return err } - for _, port := range ports { + if phyIface.IsDPDKPort == true { _, err := nc.ClientCtl.AddDPDKPort( nc.Context, &pb.AddPortRequest{ BridgeName: bridgeName, - IfaceName: port.Name, - DpdkDevargs: port.PCIID, + IfaceName: phyIface.Name, + DpdkDevargs: phyIface.PCIID, }) if err != nil { return err } - - if len(port.VlanTags) > 0 { - _, err := nc.ClientCtl.SetPort( - nc.Context, - &pb.SetPortRequest{ - IfaceName: port.Name, - Options: &pb.PortOptions{ - VLANMode: "trunk", - Trunk: port.VlanTags, - }, - }) - if err != nil { - return err - } - } - } - return nil -} - -func (nc *NetworkController) CreateOVSUserpsaceNetwork(bridgeName string, ports []entity.PhysicalPort) error { - if _, err := nc.ClientCtl.CreateBridge( - nc.Context, - &pb.CreateBridgeRequest{ - BridgeName: bridgeName, - DatapathType: "netdev", - }); err != nil { - return err - } - - for _, port := range ports { + } else { _, err := nc.ClientCtl.AddPort( nc.Context, &pb.AddPortRequest{ BridgeName: bridgeName, - IfaceName: port.Name, + IfaceName: phyIface.Name, }) if err != nil { return err } + } - if len(port.VlanTags) > 0 { - _, err := nc.ClientCtl.SetPort( - nc.Context, - &pb.SetPortRequest{ - IfaceName: port.Name, - Options: &pb.PortOptions{ - VLANMode: "trunk", - Trunk: port.VlanTags, - }, - }) - if err != nil { - return err - } + if len(vlanTags) > 0 { + _, err := nc.ClientCtl.SetPort( + nc.Context, + &pb.SetPortRequest{ + IfaceName: phyIface.Name, + Options: &pb.PortOptions{ + VLANMode: "trunk", + Trunk: vlanTags, + }, + }) + if err != nil { + return err } } return nil } + +func (nc *NetworkController) DeleteOVSNetwork(bridgeName string) error { + _, err := nc.ClientCtl.DeleteBridge( + nc.Context, + &pb.DeleteBridgeRequest{ + BridgeName: bridgeName, + }) + if err != nil { + return err + } + return nil +} diff --git a/src/networkprovider/fake.go b/src/networkprovider/fake.go index 882f5ac3..31bfd42c 100644 --- a/src/networkprovider/fake.go +++ b/src/networkprovider/fake.go @@ -8,26 +8,32 @@ import ( ) type FakeNetworkProvider struct { - entity.FakeNetwork + nodes []entity.Node } -func (fake FakeNetworkProvider) ValidateBeforeCreating(sp *serviceprovider.Container, net *entity.Network) error { - if fake.FakeParameter == "" { - return fmt.Errorf("Fail to validate but don't worry, I'm fake network") +func (fnp FakeNetworkProvider) ValidateBeforeCreating(sp *serviceprovider.Container, net *entity.Network) error { + for _, node := range fnp.nodes { + if node.FakeParameter == "" { + return fmt.Errorf("Fail to validate but don't worry, I'm fake network") + } } return nil } -func (fake FakeNetworkProvider) CreateNetwork(sp *serviceprovider.Container, net *entity.Network) error { - if fake.IWantFail { - return fmt.Errorf("Fail to create network but don't worry, I'm fake network") +func (fnp FakeNetworkProvider) CreateNetwork(sp *serviceprovider.Container, net *entity.Network) error { + for _, node := range fnp.nodes { + if node.ShouldFail { + return fmt.Errorf("Fail to validate but don't worry, I'm fake network") + } } return nil } -func (fake FakeNetworkProvider) DeleteNetwork(sp *serviceprovider.Container, net *entity.Network) error { - if fake.IWantFail { - return fmt.Errorf("Fail to delete network but don't worry, I'm fake network") +func (fnp FakeNetworkProvider) DeleteNetwork(sp *serviceprovider.Container, net *entity.Network) error { + for _, node := range fnp.nodes { + if node.ShouldFail { + return fmt.Errorf("Fail to delete network but don't worry, I'm fake network") + } } return nil } diff --git a/src/networkprovider/network.go b/src/networkprovider/network.go index 61fa296c..ee604a79 100644 --- a/src/networkprovider/network.go +++ b/src/networkprovider/network.go @@ -16,11 +16,17 @@ type NetworkProvider interface { func GetNetworkProvider(network *entity.Network) (NetworkProvider, error) { switch network.Type { case entity.OVSKernelspaceNetworkType: - return OVSNetworkProvider{network.OVS}, nil + return KernelSpaceNetworkProvider{ + network.Nodes, + }, nil case entity.OVSUserspaceNetworkType: - return OVSUserspaceNetworkProvider{network.OVSUserspace}, nil + return UserSpaceNetworkProvider{ + network.Nodes, + }, nil case entity.FakeNetworkType: - return FakeNetworkProvider{network.Fake}, nil + return FakeNetworkProvider{ + network.Nodes, + }, nil default: return nil, fmt.Errorf("Unsupported Network Type %s", network.Type) } diff --git a/src/networkprovider/ovs.go b/src/networkprovider/ovs.go deleted file mode 100644 index 087ad5c8..00000000 --- a/src/networkprovider/ovs.go +++ /dev/null @@ -1,108 +0,0 @@ -package networkprovider - -import ( - "fmt" - "net" - - "github.com/linkernetworks/vortex/src/entity" - "github.com/linkernetworks/vortex/src/networkcontroller" - "github.com/linkernetworks/vortex/src/serviceprovider" - - "gopkg.in/mgo.v2/bson" -) - -type OVSNetworkProvider struct { - entity.OVSNetwork -} - -func (ovs OVSNetworkProvider) ValidateBeforeCreating(sp *serviceprovider.Container, network *entity.Network) error { - session := sp.Mongo.NewSession() - defer session.Close() - //Check whether vlangTag is 0~4095 - for _, pp := range ovs.PhysicalPorts { - for _, vlangTag := range pp.VlanTags { - if vlangTag < 0 || vlangTag > 4095 { - return fmt.Errorf("The vlangTag %v in PhysicalPort %v should between 0 and 4095", pp.Name, vlangTag) - } - } - } - - q := bson.M{} - if network.Clusterwise { - //Only check the bridge name - q = bson.M{"ovs.bridgeName": ovs.BridgeName} - } else { - q = bson.M{"nodeName": network.NodeName, "ovs.bridgeName": ovs.BridgeName} - } - - n, err := session.Count(entity.NetworkCollectionName, q) - if n >= 1 { - return fmt.Errorf("The bridge name %s is exist, please check your cluster type and reassign another bridge name", ovs.BridgeName) - } else if err != nil { - return err - } - return nil -} - -func createOVSNetwork(nodeIP string, bridgeName string, ports []entity.PhysicalPort) error { - nodeAddr := net.JoinHostPort(nodeIP, networkcontroller.DEFAULT_CONTROLLER_PORT) - nc, err := networkcontroller.New(nodeAddr) - if err != nil { - return err - } - - return nc.CreateOVSNetwork(bridgeName, ports) -} - -func deleteOVSNetwork(nodeIP string, bridgeName string) error { - nodeAddr := net.JoinHostPort(nodeIP, networkcontroller.DEFAULT_CONTROLLER_PORT) - nc, err := networkcontroller.New(nodeAddr) - if err != nil { - return err - } - - return nc.DeleteOVSNetwork(bridgeName) -} - -func (ovs OVSNetworkProvider) CreateNetwork(sp *serviceprovider.Container, network *entity.Network) error { - if network.Clusterwise { - nodes, _ := sp.KubeCtl.GetNodes() - for _, v := range nodes { - nodeIP, err := sp.KubeCtl.GetNodeExternalIP(v.GetName()) - if err != nil { - return err - } - if err := createOVSNetwork(nodeIP, network.OVS.BridgeName, network.OVS.PhysicalPorts); err != nil { - return err - } - } - return nil - } - nodeIP, err := sp.KubeCtl.GetNodeExternalIP(network.NodeName) - if err != nil { - return err - } - return createOVSNetwork(nodeIP, network.OVS.BridgeName, network.OVS.PhysicalPorts) -} - -func (ovs OVSNetworkProvider) DeleteNetwork(sp *serviceprovider.Container, network *entity.Network) error { - if network.Clusterwise { - nodes, _ := sp.KubeCtl.GetNodes() - for _, v := range nodes { - nodeIP, err := sp.KubeCtl.GetNodeExternalIP(v.GetName()) - if err != nil { - return err - } - if err := deleteOVSNetwork(nodeIP, ovs.BridgeName); err != nil { - return err - } - } - return nil - } - - nodeIP, err := sp.KubeCtl.GetNodeExternalIP(network.NodeName) - if err != nil { - return err - } - return deleteOVSNetwork(nodeIP, ovs.BridgeName) -} diff --git a/src/networkprovider/ovs_netdev.go b/src/networkprovider/ovs_netdev.go index c98ef193..94ecac01 100644 --- a/src/networkprovider/ovs_netdev.go +++ b/src/networkprovider/ovs_netdev.go @@ -10,107 +10,86 @@ import ( "gopkg.in/mgo.v2/bson" ) -type OVSUserspaceNetworkProvider struct { - entity.OVSUserspaceNetwork +type KernelSpaceNetworkProvider struct { + nodes []entity.Node } -func (ovsu OVSUserspaceNetworkProvider) ValidateBeforeCreating(sp *serviceprovider.Container, network *entity.Network) error { +func (knp KernelSpaceNetworkProvider) ValidateBeforeCreating(sp *serviceprovider.Container, network *entity.Network) error { session := sp.Mongo.NewSession() defer session.Close() - // FIXME validate both dpdk or userspace datapath - // Check whether vlangTag is 0~4095 - for _, pp := range ovsu.DPDKPhysicalPorts { - for _, vlangTag := range pp.VlanTags { - if vlangTag < 0 || vlangTag > 4095 { - return fmt.Errorf("The vlangTag %v in PhysicalPort %v should between 0 and 4095", pp.Name, vlangTag) - } + + // Check whether VLAN Tag is 0~4095 + for _, tag := range network.VLANTags { + if tag < 0 || tag > 4095 { + return fmt.Errorf("The vlangTag %d should between 0 and 4095", tag) } } - q := bson.M{} - if network.Clusterwise { - //Only check the bridge name - q = bson.M{"ovsUserspace.bridgeName": ovsu.BridgeName} - } else { - q = bson.M{"nodeName": network.NodeName, "ovsUserspace.bridgeName": ovsu.BridgeName} + // TODO Check dpdk port + for _, node := knp.nodes { + node } + q := bson.M{ + "networks.name": network.Name, + } n, err := session.Count(entity.NetworkCollectionName, q) if n >= 1 { - return fmt.Errorf("The bridge name %s is exist, please check your cluster type and reassign another bridge name", ovsu.BridgeName) + return fmt.Errorf("The network name: %s is exist.", network.Name) } else if err != nil { return err } return nil } -func (ovsu OVSUserspaceNetworkProvider) CreateNetwork(sp *serviceprovider.Container, network *entity.Network) error { - if network.Clusterwise { - nodes, _ := sp.KubeCtl.GetNodes() - for _, v := range nodes { - nodeIP, err := sp.KubeCtl.GetNodeExternalIP(v.GetName()) - if err != nil { +func (knp KernelSpaceNetworkProvider) CreateNetwork(sp *serviceprovider.Container, network *entity.Network) error { + for _, node := range knp.nodes { + nodeIP, err := sp.KubeCtl.GetNodeExternalIP(node.Name) + if err != nil { + return err + } + if node.PhyInterface.IsDPDKPort { + if err := createOVSDPDKNetwork(nodeIP, node.Name, node.PhyInterface, network.VLANTags); err != nil { return err } - // TODO if dpdk==true - if err := createOVSDPDKNetwork(nodeIP, network.OVSUserspace.BridgeName, network.OVSUserspace.DPDKPhysicalPorts); err != nil { + } else { + if err := createOVSUserspaceNetwork(nodeIP, node.Name, node.PhyInterface, network.VLANTags); err != nil { return err } - // TODO else dpdk==false - // if err := createOVSUserspaceNetwork(nodeIP, network.OVS.BridgeName, network.OVS.PhysicalPorts); err != nil { - // return err - // } } - return nil } - nodeIP, err := sp.KubeCtl.GetNodeExternalIP(network.NodeName) - if err != nil { - return err - } - // TODO if dpdk==true - return createOVSDPDKNetwork(nodeIP, network.OVSUserspace.BridgeName, network.OVSUserspace.DPDKPhysicalPorts) - // TODO else dpdk==false - // return createOVSUserspaceNetwork(nodeIP, network.OVS.BridgeName, network.OVS.PhysicalPorts) + return nil } -func (ovsu OVSUserspaceNetworkProvider) DeleteNetwork(sp *serviceprovider.Container, network *entity.Network) error { - if network.Clusterwise { - nodes, _ := sp.KubeCtl.GetNodes() - for _, v := range nodes { - nodeIP, err := sp.KubeCtl.GetNodeExternalIP(v.GetName()) - if err != nil { - return err - } - if err := deleteOVSUserspaceNetwork(nodeIP, ovsu.BridgeName); err != nil { - return err - } +func (knp KernelSpaceNetworkProvider) DeleteNetwork(sp *serviceprovider.Container, network *entity.Network) error { + for _, node := range knp.nodes { + nodeIP, err := sp.KubeCtl.GetNodeExternalIP(node.Name) + if err != nil { + return err + } + if err := deleteOVSUserspaceNetwork(nodeIP, network.BridgeName); err != nil { + return err } - return nil - } - - nodeIP, err := sp.KubeCtl.GetNodeExternalIP(network.NodeName) - if err != nil { - return err } - return deleteOVSUserspaceNetwork(nodeIP, ovsu.BridgeName) + return nil } -func createOVSDPDKNetwork(nodeIP string, bridgeName string, ports []entity.DPDKPhysicalPort) error { +func createOVSDPDKNetwork(nodeIP string, bridgeName string, phyIface entity.PhyInterface, vlanTags []int32) error { nodeAddr := net.JoinHostPort(nodeIP, networkcontroller.DEFAULT_CONTROLLER_PORT) nc, err := networkcontroller.New(nodeAddr) if err != nil { return err } - return nc.CreateOVSDPDKNetwork(bridgeName, ports) + return nc.CreateOVSDPDKNetwork(bridgeName, phyIface, vlanTags) } -func createOVSUserspaceNetwork(nodeIP string, bridgeName string, ports []entity.PhysicalPort) error { +func createOVSUserspaceNetwork(nodeIP string, bridgeName string, phyIface entity.PhyInterface, vlanTags []int32) error { nodeAddr := net.JoinHostPort(nodeIP, networkcontroller.DEFAULT_CONTROLLER_PORT) nc, err := networkcontroller.New(nodeAddr) if err != nil { return err } - return nc.CreateOVSUserpsaceNetwork(bridgeName, ports) + return nc.CreateOVSNetwork("netdev", bridgeName, phyIface, vlanTags) } func deleteOVSUserspaceNetwork(nodeIP string, bridgeName string) error { diff --git a/src/networkprovider/ovs_system.go b/src/networkprovider/ovs_system.go new file mode 100644 index 00000000..00ed3cfd --- /dev/null +++ b/src/networkprovider/ovs_system.go @@ -0,0 +1,82 @@ +package networkprovider + +import ( + "fmt" + "net" + + "github.com/linkernetworks/vortex/src/entity" + "github.com/linkernetworks/vortex/src/networkcontroller" + "github.com/linkernetworks/vortex/src/serviceprovider" + "gopkg.in/mgo.v2/bson" +) + +type UserSpaceNetworkProvider struct { + nodes []entity.Node +} + +func (unp UserSpaceNetworkProvider) ValidateBeforeCreating(sp *serviceprovider.Container, network *entity.Network) error { + session := sp.Mongo.NewSession() + defer session.Close() + + // Check whether VLAN Tag is 0~4095 + for _, tag := range network.VLANTags { + if tag < 0 || tag > 4095 { + return fmt.Errorf("The vlangTag %d should between 0 and 4095", tag) + } + } + + q := bson.M{ + "networks.name": network.Name, + } + n, err := session.Count(entity.NetworkCollectionName, q) + if n >= 1 { + return fmt.Errorf("The network name: %s is exist.", network.Name) + } else if err != nil { + return err + } + return nil +} + +func (unp UserSpaceNetworkProvider) CreateNetwork(sp *serviceprovider.Container, network *entity.Network) error { + for _, node := range unp.nodes { + nodeIP, err := sp.KubeCtl.GetNodeExternalIP(node.Name) + if err != nil { + return err + } + if err := createOVSNetwork(nodeIP, node.Name, node.PhyInterface, network.VLANTags); err != nil { + return err + } + } + return nil +} + +func (unp UserSpaceNetworkProvider) DeleteNetwork(sp *serviceprovider.Container, network *entity.Network) error { + for _, node := range unp.nodes { + nodeIP, err := sp.KubeCtl.GetNodeExternalIP(node.Name) + if err != nil { + return err + } + if err := deleteOVSNetwork(nodeIP, network.BridgeName); err != nil { + return err + } + } + return nil +} + +func createOVSNetwork(nodeIP string, bridgeName string, phyIface entity.PhyInterface, vlanTags []int32) error { + nodeAddr := net.JoinHostPort(nodeIP, networkcontroller.DEFAULT_CONTROLLER_PORT) + nc, err := networkcontroller.New(nodeAddr) + if err != nil { + return err + } + return nc.CreateOVSNetwork("system", bridgeName, phyIface, vlanTags) +} + +func deleteOVSNetwork(nodeIP string, bridgeName string) error { + nodeAddr := net.JoinHostPort(nodeIP, networkcontroller.DEFAULT_CONTROLLER_PORT) + nc, err := networkcontroller.New(nodeAddr) + if err != nil { + return err + } + return nc.DeleteOVSNetwork(bridgeName) +} diff --git a/src/networkprovider/ovs_test.go b/src/networkprovider/ovs_system_test.go similarity index 100% rename from src/networkprovider/ovs_test.go rename to src/networkprovider/ovs_system_test.go From 19ee1f60da87127f6afd9596b4fa4c29dea24f8a Mon Sep 17 00:00:00 2001 From: John-Lin Date: Tue, 10 Jul 2018 00:27:05 +0800 Subject: [PATCH 2/2] fixed test for ovs_netdev and ovs_system Former-commit-id: 229b5b86ba3008f34b10c76869025bf11bc5cfe4 [formerly 3f0b3246fa0d3f71de44f528538aefc8d140dfb8] Former-commit-id: a3d88531fa8843fbf1377dc877815e781be1e0e6 --- src/entity/network.go | 14 +- src/networkcontroller/network_controller.go | 80 +++-- .../network_controller_test.go | 89 +++--- src/networkprovider/fake.go | 14 +- src/networkprovider/fake_test.go | 48 +-- src/networkprovider/network.go | 24 +- src/networkprovider/network_test.go | 6 +- src/networkprovider/ovs_netdev.go | 58 ++-- src/networkprovider/ovs_netdev_test.go | 287 +++++++++++------- src/networkprovider/ovs_system.go | 44 ++- src/networkprovider/ovs_system_test.go | 261 +++++++++------- src/server/handler_network.go | 15 +- src/server/handler_network_test.go | 126 +++++--- 13 files changed, 617 insertions(+), 449 deletions(-) diff --git a/src/entity/network.go b/src/entity/network.go index 9b32a269..1de02f00 100644 --- a/src/entity/network.go +++ b/src/entity/network.go @@ -18,18 +18,18 @@ const ( NetworkCollectionName string = "networks" ) -type PhyInterfaces struct { +type PhyInterface struct { Name string `bson:"name" json:"name"` PCIID string `bson:"pciID" json:"pciID"` } type Node struct { - Name string `bson:"name" json:"name"` - PhyInterfaces []PhyInterfaces `bson:"physicalInterface" json:"physicalInterface"` + Name string `bson:"name" json:"name"` + PhyInterfaces []PhyInterface `bson:"physicalInterfaces" json:"physicalInterfaces"` // Fake fields for restful testing FakeParameter string `json:"fakeParameter"` - ShouldFail bool `json:"shoulFail"` + ShouldFail bool `json:"shouldFail"` } type Network struct { @@ -41,12 +41,6 @@ type Network struct { BridgeName string `bson:"bridgeName" json:"bridgeName"` Nodes []Node `bson:"nodes" json:"nodes"` CreatedAt *time.Time `bson:"createdAt,omitempty" json:"createdAt,omitempty"` - - // Clusterwise bool `bson:"clusterwise" json:"clusterwise"` - // NodeName string `bson:"nodeName,omitempty" json:"nodeName,omitempty"` - // OVS OVSNetwork `bson:"ovs,omitempty" json:"ovs"` - // OVSUserspace OVSUserspaceNetwork `bson:"ovsUserspace,omitempty" json:"ovsUserspace"` - // Fake FakeNetwork `json:"fake"` //FakeNetwork, for restful testing. } // GetCollection - get model mongo collection name. diff --git a/src/networkcontroller/network_controller.go b/src/networkcontroller/network_controller.go index f168bd70..6118e911 100644 --- a/src/networkcontroller/network_controller.go +++ b/src/networkcontroller/network_controller.go @@ -31,7 +31,7 @@ func New(serverAddress string) (*NetworkController, error) { }, nil } -func (nc *NetworkController) CreateOVSNetwork(datapathType string, bridgeName string, phyIface entity.PhyInterface, vlanTags []int32) error { +func (nc *NetworkController) CreateOVSNetwork(datapathType string, bridgeName string, phyIfaces []entity.PhyInterface, vlanTags []int32) error { if _, err := nc.ClientCtl.CreateBridge( nc.Context, &pb.CreateBridgeRequest{ @@ -41,34 +41,36 @@ func (nc *NetworkController) CreateOVSNetwork(datapathType string, bridgeName st return err } - _, err := nc.ClientCtl.AddPort( - nc.Context, - &pb.AddPortRequest{ - BridgeName: bridgeName, - IfaceName: phyIface.Name, - }) - if err != nil { - return err - } - - if len(vlanTags) > 0 { - _, err := nc.ClientCtl.SetPort( + for _, phyIface := range phyIfaces { + _, err := nc.ClientCtl.AddPort( nc.Context, - &pb.SetPortRequest{ - IfaceName: phyIface.Name, - Options: &pb.PortOptions{ - VLANMode: "trunk", - Trunk: vlanTags, - }, + &pb.AddPortRequest{ + BridgeName: bridgeName, + IfaceName: phyIface.Name, }) if err != nil { return err } + + if len(vlanTags) > 0 { + _, err := nc.ClientCtl.SetPort( + nc.Context, + &pb.SetPortRequest{ + IfaceName: phyIface.Name, + Options: &pb.PortOptions{ + VLANMode: "trunk", + Trunk: vlanTags, + }, + }) + if err != nil { + return err + } + } } return nil } -func (nc *NetworkController) CreateOVSDPDKNetwork(bridgeName string, phyIface entity.PhyInterface, vlanTags []int32) error { +func (nc *NetworkController) CreateOVSDPDKNetwork(bridgeName string, phyIfaces []entity.PhyInterface, vlanTags []int32) error { if _, err := nc.ClientCtl.CreateBridge( nc.Context, &pb.CreateBridgeRequest{ @@ -78,7 +80,7 @@ func (nc *NetworkController) CreateOVSDPDKNetwork(bridgeName string, phyIface en return err } - if phyIface.IsDPDKPort == true { + for _, phyIface := range phyIfaces { _, err := nc.ClientCtl.AddDPDKPort( nc.Context, &pb.AddPortRequest{ @@ -89,30 +91,20 @@ func (nc *NetworkController) CreateOVSDPDKNetwork(bridgeName string, phyIface en if err != nil { return err } - } else { - _, err := nc.ClientCtl.AddPort( - nc.Context, - &pb.AddPortRequest{ - BridgeName: bridgeName, - IfaceName: phyIface.Name, - }) - if err != nil { - return err - } - } - if len(vlanTags) > 0 { - _, err := nc.ClientCtl.SetPort( - nc.Context, - &pb.SetPortRequest{ - IfaceName: phyIface.Name, - Options: &pb.PortOptions{ - VLANMode: "trunk", - Trunk: vlanTags, - }, - }) - if err != nil { - return err + if len(vlanTags) > 0 { + _, err := nc.ClientCtl.SetPort( + nc.Context, + &pb.SetPortRequest{ + IfaceName: phyIface.Name, + Options: &pb.PortOptions{ + VLANMode: "trunk", + Trunk: vlanTags, + }, + }) + if err != nil { + return err + } } } return nil diff --git a/src/networkcontroller/network_controller_test.go b/src/networkcontroller/network_controller_test.go index 9936b806..c415497e 100644 --- a/src/networkcontroller/network_controller_test.go +++ b/src/networkcontroller/network_controller_test.go @@ -100,29 +100,30 @@ func (suite *NetworkControllerTestSuite) TestNew() { } func (suite *NetworkControllerTestSuite) TestCreateNetwork() { - //Parameters - eth1 := entity.PhysicalPort{ - Name: suite.ifName, - MTU: 1500, - VlanTags: []int32{2043, 2143, 2243}, - } - tName := namesgenerator.GetRandomName(0) network := entity.Network{ - Name: tName, - OVS: entity.OVSNetwork{ - BridgeName: tName, - PhysicalPorts: []entity.PhysicalPort{eth1}, + Type: entity.OVSKernelspaceNetworkType, + Name: tName, + VLANTags: []int32{0, 2048, 4095}, + BridgeName: tName, + Nodes: []entity.Node{ + entity.Node{ + Name: suite.nodeName, + PhyInterfaces: []entity.PhyInterface{ + entity.PhyInterface{ + Name: suite.ifName, + PCIID: "", + }, + }, + }, }, - Type: "ovs", - NodeName: suite.nodeName, } nodeIP, err := suite.kubectl.GetNodeExternalIP(suite.nodeName) suite.NoError(err) nc, err := New(net.JoinHostPort(nodeIP, DEFAULT_CONTROLLER_PORT)) suite.NoError(err) - err = nc.CreateOVSNetwork(tName, network.OVSUserspace.PhysicalPorts) + err = nc.CreateOVSNetwork("system", tName, network.Nodes[0].PhyInterfaces, network.VLANTags) suite.NoError(err) //TODO we need support the list function to check the ovs is existed @@ -130,28 +131,31 @@ func (suite *NetworkControllerTestSuite) TestCreateNetwork() { } func (suite *NetworkControllerTestSuite) TestCreateOVSUserpsaceNetwork() { - eth1 := entity.PhysicalPort{ - Name: suite.ifName, - MTU: 1500, - VlanTags: []int32{2043, 2143, 2243}, - } - tName := namesgenerator.GetRandomName(0) network := entity.Network{ - Name: tName, - OVSUserspace: entity.OVSUserspaceNetwork{ - BridgeName: tName, - PhysicalPorts: []entity.PhysicalPort{eth1}, + Type: entity.OVSUserspaceNetworkType, + IsDPDKPort: false, + Name: tName, + VLANTags: []int32{0, 2048, 4095}, + BridgeName: tName, + Nodes: []entity.Node{ + entity.Node{ + Name: suite.nodeName, + PhyInterfaces: []entity.PhyInterface{ + entity.PhyInterface{ + Name: suite.ifName, + PCIID: "", + }, + }, + }, }, - Type: "netdev", - NodeName: suite.nodeName, } nodeIP, err := suite.kubectl.GetNodeExternalIP(suite.nodeName) suite.NoError(err) nc, err := New(net.JoinHostPort(nodeIP, DEFAULT_CONTROLLER_PORT)) suite.NoError(err) - err = nc.CreateOVSUserpsaceNetwork(tName, network.OVS.PhysicalPorts) + err = nc.CreateOVSNetwork("netdev", tName, network.Nodes[0].PhyInterfaces, network.VLANTags) suite.NoError(err) //TODO we need support the list function to check the ovs is existed @@ -159,29 +163,30 @@ func (suite *NetworkControllerTestSuite) TestCreateOVSUserpsaceNetwork() { } func (suite *NetworkControllerTestSuite) TestDeleteNetwork() { - //Parameters - eth1 := entity.PhysicalPort{ - Name: suite.ifName, - MTU: 1500, - VlanTags: []int32{2043, 2143, 2243}, - } - tName := namesgenerator.GetRandomName(0) network := entity.Network{ - Name: tName, - OVS: entity.OVSNetwork{ - BridgeName: tName, - PhysicalPorts: []entity.PhysicalPort{eth1}, + Type: entity.OVSKernelspaceNetworkType, + Name: tName, + VLANTags: []int32{0, 2048, 4095}, + BridgeName: tName, + Nodes: []entity.Node{ + entity.Node{ + Name: suite.nodeName, + PhyInterfaces: []entity.PhyInterface{ + entity.PhyInterface{ + Name: suite.ifName, + PCIID: "", + }, + }, + }, }, - Type: "ovs", - NodeName: suite.nodeName, } nodeIP, err := suite.kubectl.GetNodeExternalIP(suite.nodeName) suite.NoError(err) nc, err := New(net.JoinHostPort(nodeIP, DEFAULT_CONTROLLER_PORT)) suite.NoError(err) - err = nc.CreateOVSNetwork(tName, network.OVS.PhysicalPorts) + err = nc.CreateOVSNetwork("system", tName, network.Nodes[0].PhyInterfaces, network.VLANTags) suite.NoError(err) err = nc.DeleteOVSNetwork(tName) @@ -193,6 +198,6 @@ func (suite *NetworkControllerTestSuite) TestCreateNetworkWithInvalidAddress() { suite.NoError(err) tName := namesgenerator.GetRandomName(0) - err = nc.CreateOVSNetwork(tName, []entity.PhysicalPort{}) + err = nc.CreateOVSNetwork("system", tName, []entity.PhyInterface{}, []int32{}) suite.Error(err) } diff --git a/src/networkprovider/fake.go b/src/networkprovider/fake.go index 31bfd42c..18629a07 100644 --- a/src/networkprovider/fake.go +++ b/src/networkprovider/fake.go @@ -7,11 +7,15 @@ import ( "github.com/linkernetworks/vortex/src/serviceprovider" ) -type FakeNetworkProvider struct { - nodes []entity.Node +type fakeNetworkProvider struct { + networkName string + bridgeName string + vlanTags []int32 + nodes []entity.Node + isDPDKPort bool } -func (fnp FakeNetworkProvider) ValidateBeforeCreating(sp *serviceprovider.Container, net *entity.Network) error { +func (fnp fakeNetworkProvider) ValidateBeforeCreating(sp *serviceprovider.Container) error { for _, node := range fnp.nodes { if node.FakeParameter == "" { return fmt.Errorf("Fail to validate but don't worry, I'm fake network") @@ -20,7 +24,7 @@ func (fnp FakeNetworkProvider) ValidateBeforeCreating(sp *serviceprovider.Contai return nil } -func (fnp FakeNetworkProvider) CreateNetwork(sp *serviceprovider.Container, net *entity.Network) error { +func (fnp fakeNetworkProvider) CreateNetwork(sp *serviceprovider.Container) error { for _, node := range fnp.nodes { if node.ShouldFail { return fmt.Errorf("Fail to validate but don't worry, I'm fake network") @@ -29,7 +33,7 @@ func (fnp FakeNetworkProvider) CreateNetwork(sp *serviceprovider.Container, net return nil } -func (fnp FakeNetworkProvider) DeleteNetwork(sp *serviceprovider.Container, net *entity.Network) error { +func (fnp fakeNetworkProvider) DeleteNetwork(sp *serviceprovider.Container) error { for _, node := range fnp.nodes { if node.ShouldFail { return fmt.Errorf("Fail to delete network but don't worry, I'm fake network") diff --git a/src/networkprovider/fake_test.go b/src/networkprovider/fake_test.go index 65b439c7..6c39f190 100644 --- a/src/networkprovider/fake_test.go +++ b/src/networkprovider/fake_test.go @@ -11,70 +11,80 @@ import ( func TestNetworkValidateBeforeCreating(t *testing.T) { fake, err := GetNetworkProvider(&entity.Network{ Type: entity.FakeNetworkType, - Fake: entity.FakeNetwork{ - FakeParameter: "yes", + Nodes: []entity.Node{ + entity.Node{ + FakeParameter: "yes", + }, }, }) assert.NoError(t, err) - err = fake.ValidateBeforeCreating(nil, &entity.Network{}) + err = fake.ValidateBeforeCreating(nil) assert.NoError(t, err) } func TestFakeNetworkCreating(t *testing.T) { fake, err := GetNetworkProvider(&entity.Network{ Type: entity.FakeNetworkType, - Fake: entity.FakeNetwork{ - FakeParameter: "yes", - IWantFail: false, + Nodes: []entity.Node{ + entity.Node{ + FakeParameter: "yes", + ShouldFail: false, + }, }, }) assert.NoError(t, err) - err = fake.CreateNetwork(nil, &entity.Network{}) + err = fake.CreateNetwork(nil) assert.NoError(t, err) } func TestFakeNetworkValidateBeforeCreatingFail(t *testing.T) { fake, err := GetNetworkProvider(&entity.Network{ Type: entity.FakeNetworkType, - Fake: entity.FakeNetwork{ - FakeParameter: "", + Nodes: []entity.Node{ + entity.Node{ + FakeParameter: "", + }, }, }) assert.NoError(t, err) - err = fake.ValidateBeforeCreating(nil, &entity.Network{}) + err = fake.ValidateBeforeCreating(nil) assert.Error(t, err) } func TestFakeNetworkCreatingFail(t *testing.T) { fake, err := GetNetworkProvider(&entity.Network{ Type: entity.FakeNetworkType, - Fake: entity.FakeNetwork{ - IWantFail: true, + Nodes: []entity.Node{ + entity.Node{ + ShouldFail: true, + }, }, }) assert.NoError(t, err) - err = fake.CreateNetwork(nil, &entity.Network{}) + err = fake.CreateNetwork(nil) assert.Error(t, err) } func TestFakeNetworkDelete(t *testing.T) { fake, err := GetNetworkProvider(&entity.Network{ - Type: entity.FakeNetworkType, - Fake: entity.FakeNetwork{}, + Type: entity.FakeNetworkType, + Nodes: []entity.Node{}, }) assert.NoError(t, err) - err = fake.DeleteNetwork(nil, &entity.Network{}) + err = fake.DeleteNetwork(nil) assert.NoError(t, err) } func TestFakeNetworkDeleteFail(t *testing.T) { fake, err := GetNetworkProvider(&entity.Network{ Type: entity.FakeNetworkType, - Fake: entity.FakeNetwork{ - IWantFail: true, + Nodes: []entity.Node{ + entity.Node{ + ShouldFail: true, + }, }, }) assert.NoError(t, err) - err = fake.DeleteNetwork(nil, &entity.Network{}) + err = fake.DeleteNetwork(nil) assert.Error(t, err) } diff --git a/src/networkprovider/network.go b/src/networkprovider/network.go index ee604a79..9e1f3fb1 100644 --- a/src/networkprovider/network.go +++ b/src/networkprovider/network.go @@ -8,24 +8,36 @@ import ( ) type NetworkProvider interface { - ValidateBeforeCreating(sp *serviceprovider.Container, net *entity.Network) error - CreateNetwork(sp *serviceprovider.Container, net *entity.Network) error - DeleteNetwork(sp *serviceprovider.Container, net *entity.Network) error + ValidateBeforeCreating(sp *serviceprovider.Container) error + CreateNetwork(sp *serviceprovider.Container) error + DeleteNetwork(sp *serviceprovider.Container) error } func GetNetworkProvider(network *entity.Network) (NetworkProvider, error) { switch network.Type { case entity.OVSKernelspaceNetworkType: - return KernelSpaceNetworkProvider{ + return kernelspaceNetworkProvider{ + network.Name, + network.BridgeName, + network.VLANTags, network.Nodes, + network.IsDPDKPort, }, nil case entity.OVSUserspaceNetworkType: - return UserSpaceNetworkProvider{ + return userspaceNetworkProvider{ + network.Name, + network.BridgeName, + network.VLANTags, network.Nodes, + network.IsDPDKPort, }, nil case entity.FakeNetworkType: - return FakeNetworkProvider{ + return fakeNetworkProvider{ + network.Name, + network.BridgeName, + network.VLANTags, network.Nodes, + network.IsDPDKPort, }, nil default: return nil, fmt.Errorf("Unsupported Network Type %s", network.Type) diff --git a/src/networkprovider/network_test.go b/src/networkprovider/network_test.go index 9e40fdc2..1d2bf1d7 100644 --- a/src/networkprovider/network_test.go +++ b/src/networkprovider/network_test.go @@ -15,9 +15,9 @@ func TestGetNetworkProvider(t *testing.T) { netType entity.NetworkType netProviderType interface{} }{ - {"system", entity.OVSKernelspaceNetworkType, reflect.TypeOf(OVSNetworkProvider{})}, - {"netdev", entity.OVSUserspaceNetworkType, reflect.TypeOf(OVSUserspaceNetworkProvider{})}, - {"fake", entity.FakeNetworkType, reflect.TypeOf(FakeNetworkProvider{})}, + {"system", entity.OVSKernelspaceNetworkType, reflect.TypeOf(kernelspaceNetworkProvider{})}, + {"netdev", entity.OVSUserspaceNetworkType, reflect.TypeOf(userspaceNetworkProvider{})}, + {"fake", entity.FakeNetworkType, reflect.TypeOf(fakeNetworkProvider{})}, } for _, tc := range testCases { diff --git a/src/networkprovider/ovs_netdev.go b/src/networkprovider/ovs_netdev.go index 94ecac01..1f9c992b 100644 --- a/src/networkprovider/ovs_netdev.go +++ b/src/networkprovider/ovs_netdev.go @@ -10,50 +10,59 @@ import ( "gopkg.in/mgo.v2/bson" ) -type KernelSpaceNetworkProvider struct { - nodes []entity.Node +type userspaceNetworkProvider struct { + networkName string + bridgeName string + vlanTags []int32 + nodes []entity.Node + isDPDKPort bool } -func (knp KernelSpaceNetworkProvider) ValidateBeforeCreating(sp *serviceprovider.Container, network *entity.Network) error { +func (unp userspaceNetworkProvider) ValidateBeforeCreating(sp *serviceprovider.Container) error { session := sp.Mongo.NewSession() defer session.Close() // Check whether VLAN Tag is 0~4095 - for _, tag := range network.VLANTags { + for _, tag := range unp.vlanTags { if tag < 0 || tag > 4095 { return fmt.Errorf("The vlangTag %d should between 0 and 4095", tag) } } - // TODO Check dpdk port - for _, node := knp.nodes { - node - } - q := bson.M{ - "networks.name": network.Name, + "name": unp.networkName, } n, err := session.Count(entity.NetworkCollectionName, q) if n >= 1 { - return fmt.Errorf("The network name: %s is exist.", network.Name) + return fmt.Errorf("The network name: %s is exist.", unp.networkName) } else if err != nil { return err } return nil } -func (knp KernelSpaceNetworkProvider) CreateNetwork(sp *serviceprovider.Container, network *entity.Network) error { - for _, node := range knp.nodes { +func (unp userspaceNetworkProvider) CreateNetwork(sp *serviceprovider.Container) error { + for _, node := range unp.nodes { nodeIP, err := sp.KubeCtl.GetNodeExternalIP(node.Name) if err != nil { return err } - if node.PhyInterface.IsDPDKPort { - if err := createOVSDPDKNetwork(nodeIP, node.Name, node.PhyInterface, network.VLANTags); err != nil { + if unp.isDPDKPort { + if err := createOVSDPDKNetwork( + nodeIP, + unp.bridgeName, + node.PhyInterfaces, + unp.vlanTags, + ); err != nil { return err } } else { - if err := createOVSUserspaceNetwork(nodeIP, node.Name, node.PhyInterface, network.VLANTags); err != nil { + if err := createOVSUserspaceNetwork( + nodeIP, + unp.bridgeName, + node.PhyInterfaces, + unp.vlanTags, + ); err != nil { return err } } @@ -61,35 +70,38 @@ func (knp KernelSpaceNetworkProvider) CreateNetwork(sp *serviceprovider.Containe return nil } -func (knp KernelSpaceNetworkProvider) DeleteNetwork(sp *serviceprovider.Container, network *entity.Network) error { - for _, node := range knp.nodes { +func (unp userspaceNetworkProvider) DeleteNetwork(sp *serviceprovider.Container) error { + for _, node := range unp.nodes { nodeIP, err := sp.KubeCtl.GetNodeExternalIP(node.Name) if err != nil { return err } - if err := deleteOVSUserspaceNetwork(nodeIP, network.BridgeName); err != nil { + if err := deleteOVSUserspaceNetwork( + nodeIP, + unp.bridgeName, + ); err != nil { return err } } return nil } -func createOVSDPDKNetwork(nodeIP string, bridgeName string, phyIface entity.PhyInterface, vlanTags []int32) error { +func createOVSDPDKNetwork(nodeIP string, bridgeName string, phyIfaces []entity.PhyInterface, vlanTags []int32) error { nodeAddr := net.JoinHostPort(nodeIP, networkcontroller.DEFAULT_CONTROLLER_PORT) nc, err := networkcontroller.New(nodeAddr) if err != nil { return err } - return nc.CreateOVSDPDKNetwork(bridgeName, phyIface, vlanTags) + return nc.CreateOVSDPDKNetwork(bridgeName, phyIfaces, vlanTags) } -func createOVSUserspaceNetwork(nodeIP string, bridgeName string, phyIface entity.PhyInterface, vlanTags []int32) error { +func createOVSUserspaceNetwork(nodeIP string, bridgeName string, phyIfaces []entity.PhyInterface, vlanTags []int32) error { nodeAddr := net.JoinHostPort(nodeIP, networkcontroller.DEFAULT_CONTROLLER_PORT) nc, err := networkcontroller.New(nodeAddr) if err != nil { return err } - return nc.CreateOVSNetwork("netdev", bridgeName, phyIface, vlanTags) + return nc.CreateOVSNetwork("netdev", bridgeName, phyIfaces, vlanTags) } func deleteOVSUserspaceNetwork(nodeIP string, bridgeName string) error { diff --git a/src/networkprovider/ovs_netdev_test.go b/src/networkprovider/ovs_netdev_test.go index 7efa3920..1de0c3d2 100644 --- a/src/networkprovider/ovs_netdev_test.go +++ b/src/networkprovider/ovs_netdev_test.go @@ -27,28 +27,46 @@ func init() { rand.Seed(time.Now().UnixNano()) } -type DPDKNetworkTestSuite struct { +// OK +type OVSNetdevNetworkTestSuite struct { suite.Suite - sp *serviceprovider.Container - clusterNetwork entity.Network - singleNetwork entity.Network + sp *serviceprovider.Container + standaloneNetwork entity.Network + clusterwiseNetwork entity.Network } -func (suite *DPDKNetworkTestSuite) SetupSuite() { +// OK +func (suite *OVSNetdevNetworkTestSuite) SetupSuite() { cf := config.MustRead("../../config/testing.json") suite.sp = serviceprovider.NewForTesting(cf) - //init fakeclient + // init fakeclient fakeclient := fakeclientset.NewSimpleClientset() namespace := "default" suite.sp.KubeCtl = kc.New(fakeclient, namespace) - //Create a fake clinet - //Init node - nodeName := namesgenerator.GetRandomName(0) + // Create a fake clinet + // Initial nodes + nodeName1 := namesgenerator.GetRandomName(0) + nodeName2 := namesgenerator.GetRandomName(1) _, err := suite.sp.KubeCtl.Clientset.CoreV1().Nodes().Create(&corev1.Node{ ObjectMeta: metav1.ObjectMeta{ - Name: nodeName, + Name: nodeName1, + }, + Status: corev1.NodeStatus{ + Addresses: []corev1.NodeAddress{ + { + Type: "ExternalIP", + Address: DPDK_LOCAL_IP, + }, + }, + }, + }) + suite.NoError(err) + + _, err = suite.sp.KubeCtl.Clientset.CoreV1().Nodes().Create(&corev1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: nodeName2, }, Status: corev1.NodeStatus{ Addresses: []corev1.NodeAddress{ @@ -62,31 +80,38 @@ func (suite *DPDKNetworkTestSuite) SetupSuite() { suite.NoError(err) tName := namesgenerator.GetRandomName(0) - suite.singleNetwork = entity.Network{ - Name: tName, - OVSUserspace: entity.OVSUserspaceNetwork{ - BridgeName: tName, - DPDKPhysicalPorts: []entity.DPDKPhysicalPort{}, + + suite.standaloneNetwork = entity.Network{ + Type: entity.OVSUserspaceNetworkType, + IsDPDKPort: false, + Name: tName, + BridgeName: tName, + Nodes: []entity.Node{ + entity.Node{ + Name: nodeName1, + }, }, - Type: entity.OVSUserspaceNetworkType, - NodeName: nodeName, } - suite.clusterNetwork = entity.Network{ - Name: tName, - OVSUserspace: entity.OVSUserspaceNetwork{ - BridgeName: tName, - DPDKPhysicalPorts: []entity.DPDKPhysicalPort{}, + suite.clusterwiseNetwork = entity.Network{ + Type: entity.OVSUserspaceNetworkType, + IsDPDKPort: false, + Name: tName, + BridgeName: tName, + Nodes: []entity.Node{ + entity.Node{ + Name: nodeName1, + }, + entity.Node{ + Name: nodeName2, + }, }, - Type: entity.OVSUserspaceNetworkType, - NodeName: nodeName, - Clusterwise: true, } } -func (suite *DPDKNetworkTestSuite) TearDownSuite() { -} +func (suite *OVSNetdevNetworkTestSuite) TearDownSuite() {} +// OK func TestNetworkSuite(t *testing.T) { if runtime.GOOS != "linux" { fmt.Println("We only testing the ovs function on Linux Host") @@ -97,100 +122,116 @@ func TestNetworkSuite(t *testing.T) { t.SkipNow() return } - suite.Run(t, new(DPDKNetworkTestSuite)) + suite.Run(t, new(OVSNetdevNetworkTestSuite)) } -//Member funcion -func (suite *DPDKNetworkTestSuite) TestCreateOVSDPDKNetwork() { - name := namesgenerator.GetRandomName(0) - err := createOVSDPDKNetwork(DPDK_LOCAL_IP, name, []entity.DPDKPhysicalPort{}) - defer exec.Command("ovs-vsctl", "del-br", name).Run() +// OK. might fail +func (suite *OVSNetdevNetworkTestSuite) TestCreateOVSDPDKNetwork() { + brName := namesgenerator.GetRandomName(0) + err := createOVSDPDKNetwork( + DPDK_LOCAL_IP, + brName, + []entity.PhyInterface{}, + []int32{0, 2048, 4095}, + ) + defer exec.Command("ovs-vsctl", "del-br", brName).Run() suite.NoError(err) } -func (suite *DPDKNetworkTestSuite) TestCreateOVSUserspaceNetwork() { - name := namesgenerator.GetRandomName(0) - err := createOVSUserspaceNetwork(DPDK_LOCAL_IP, name, []entity.PhysicalPort{}) - defer exec.Command("ovs-vsctl", "del-br", name).Run() +// OK +func (suite *OVSNetdevNetworkTestSuite) TestCreateOVSUserspaceNetwork() { + brName := namesgenerator.GetRandomName(0) + err := createOVSUserspaceNetwork( + DPDK_LOCAL_IP, + brName, + []entity.PhyInterface{}, + []int32{0, 2048, 4095}, + ) + defer exec.Command("ovs-vsctl", "del-br", brName).Run() suite.NoError(err) } -func (suite *DPDKNetworkTestSuite) TestDeleteOVSUserspaceNetwork() { - name := namesgenerator.GetRandomName(0) +// OK +func (suite *OVSNetdevNetworkTestSuite) TestDeleteOVSUserspaceNetwork() { + brName := namesgenerator.GetRandomName(0) // ovs-vsctl add-br br0 -- set bridge br0 datapath_type=netdev - exec.Command("ovs-vsctl", "add-br", name, "--", "set", "bridge", name, "datapath_type=netdev").Run() - err := deleteOVSUserspaceNetwork(DPDK_LOCAL_IP, name) + exec.Command("ovs-vsctl", "add-br", brName, "--", "set", "bridge", brName, "datapath_type=netdev").Run() + err := deleteOVSUserspaceNetwork(DPDK_LOCAL_IP, brName) suite.NoError(err) } -func (suite *DPDKNetworkTestSuite) TestCreateNetwork() { +// OK +func (suite *OVSNetdevNetworkTestSuite) TestCreateNetwork() { testCases := []struct { caseName string network *entity.Network }{ - {"singelNetwork", &suite.singleNetwork}, - {"clusterNetwork", &suite.clusterNetwork}, + {"standaloneNetwork", &suite.standaloneNetwork}, + {"clusterwiseNetwork", &suite.clusterwiseNetwork}, } for _, tc := range testCases { suite.T().Run(tc.caseName, func(t *testing.T) { - //Parameters np, err := GetNetworkProvider(tc.network) suite.NoError(err) - np = np.(OVSUserspaceNetworkProvider) - err = np.CreateNetwork(suite.sp, tc.network) + np = np.(userspaceNetworkProvider) + err = np.CreateNetwork(suite.sp) suite.NoError(err) - defer exec.Command("ovs-vsctl", "del-br", tc.network.OVSUserspace.BridgeName).Run() + defer exec.Command("ovs-vsctl", "del-br", tc.network.BridgeName).Run() }) } } -func (suite *DPDKNetworkTestSuite) TestCreateNetworkFail() { +// OK +func (suite *OVSNetdevNetworkTestSuite) TestCreateNetworkFail() { network := entity.Network{ - Type: entity.OVSUserspaceNetworkType, + Type: entity.OVSUserspaceNetworkType, + IsDPDKPort: false, + Name: "none-exist-network", + BridgeName: "none", + Nodes: []entity.Node{ + entity.Node{ + Name: namesgenerator.GetRandomName(0), + }, + }, } - network.NodeName = "non-exist" np, err := GetNetworkProvider(&network) suite.NoError(err) - np = np.(OVSUserspaceNetworkProvider) - err = np.CreateNetwork(suite.sp, &network) + np = np.(userspaceNetworkProvider) + err = np.CreateNetwork(suite.sp) suite.Error(err) } -func (suite *DPDKNetworkTestSuite) TestValidateBeforeCreating() { - //Vlan - //multiple network - //single network - - //Prepare data - eth1 := entity.DPDKPhysicalPort{ - Name: namesgenerator.GetRandomName(0), - MTU: 1500, - PCIID: "0000:03:00.0", - VlanTags: []int32{ - 2043, - 2143, - 2243, - }, - } - +// OK +func (suite *OVSNetdevNetworkTestSuite) TestValidateBeforeCreating() { tName := namesgenerator.GetRandomName(0) - network := entity.Network{ - Name: tName, - OVSUserspace: entity.OVSUserspaceNetwork{ - BridgeName: tName, - DPDKPhysicalPorts: []entity.DPDKPhysicalPort{eth1}, + // Valid VLAN number + validVLANnetwork := entity.Network{ + Type: entity.OVSUserspaceNetworkType, + IsDPDKPort: false, + Name: tName, + VLANTags: []int32{0, 2048, 4095}, + BridgeName: "bro", + Nodes: []entity.Node{ + entity.Node{ + Name: "node-1", + PhyInterfaces: []entity.PhyInterface{ + entity.PhyInterface{ + Name: namesgenerator.GetRandomName(0), + PCIID: "", + }, + }, + }, }, - Type: entity.OVSUserspaceNetworkType, } testCases := []struct { caseName string network *entity.Network }{ - {"valid", &network}, - {"singelNetwork", &suite.singleNetwork}, - {"clusterNetwork", &suite.clusterNetwork}, + {"validVLAN", &validVLANnetwork}, + {"singelNetwork", &suite.standaloneNetwork}, + {"clusterNetwork", &suite.clusterwiseNetwork}, } for _, tc := range testCases { @@ -198,45 +239,47 @@ func (suite *DPDKNetworkTestSuite) TestValidateBeforeCreating() { //Parameters np, err := GetNetworkProvider(tc.network) suite.NoError(err) - np = np.(OVSUserspaceNetworkProvider) + np = np.(userspaceNetworkProvider) - err = np.ValidateBeforeCreating(suite.sp, tc.network) + err = np.ValidateBeforeCreating(suite.sp) suite.NoError(err) }) } } -func (suite *DPDKNetworkTestSuite) TestValidateBeforeCreatingFail() { - //Wrong Vlan - //Wrong Case for multiple - //Wrong Case for single - - //Prepare data - eth1 := entity.DPDKPhysicalPort{ - Name: namesgenerator.GetRandomName(0), - MTU: 1500, - PCIID: "0000:03:00.0", - VlanTags: []int32{2043, 2143, 22435}, - } - +// OK +func (suite *OVSNetdevNetworkTestSuite) TestValidateBeforeCreatingFail() { tName := namesgenerator.GetRandomName(0) - network := entity.Network{ - Name: tName, - OVSUserspace: entity.OVSUserspaceNetwork{ - BridgeName: tName, - DPDKPhysicalPorts: []entity.DPDKPhysicalPort{eth1}, + // Invalid VLAN number + invalidVLANnetwork := entity.Network{ + Type: entity.OVSUserspaceNetworkType, + IsDPDKPort: false, + Name: tName, + VLANTags: []int32{22435, 2143, 4096}, + BridgeName: "brx", + Nodes: []entity.Node{ + entity.Node{ + Name: "node-1", + PhyInterfaces: []entity.PhyInterface{ + entity.PhyInterface{ + Name: namesgenerator.GetRandomName(0), + PCIID: "", + }, + }, + }, }, - Type: entity.OVSUserspaceNetworkType, } + // Invalid Case for duplicated name in standalone network + // Invalid Case for duplicates name in clusterwise network testCases := []struct { caseName string network *entity.Network mongo bool }{ - {"invalidVlan", &network, false}, - {"singelNetwork", &suite.singleNetwork, true}, - {"clusterNetwork", &suite.clusterNetwork, true}, + {"invalidVLAN", &invalidVLANnetwork, false}, + {"standaloneNetwork", &suite.standaloneNetwork, true}, + {"clusterwiseNetwork", &suite.clusterwiseNetwork, true}, } for _, tc := range testCases { @@ -244,7 +287,7 @@ func (suite *DPDKNetworkTestSuite) TestValidateBeforeCreatingFail() { //Parameters np, err := GetNetworkProvider(tc.network) suite.NoError(err) - np = np.(OVSUserspaceNetworkProvider) + np = np.(userspaceNetworkProvider) if tc.mongo { //create a mongo-document to test duplicated name @@ -253,19 +296,20 @@ func (suite *DPDKNetworkTestSuite) TestValidateBeforeCreatingFail() { defer session.C(entity.NetworkCollectionName).Remove(tc.network) suite.NoError(err) } - err = np.ValidateBeforeCreating(suite.sp, tc.network) + err = np.ValidateBeforeCreating(suite.sp) suite.Error(err) }) } } -func (suite *DPDKNetworkTestSuite) TestDeleteNetwork() { +// OK +func (suite *OVSNetdevNetworkTestSuite) TestDeleteNetwork() { testCases := []struct { caseName string network *entity.Network }{ - {"singelNetwork", &suite.singleNetwork}, - {"clusterNetwork", &suite.clusterNetwork}, + {"standaloneNetwork", &suite.standaloneNetwork}, + {"clusterwiseNetwork", &suite.clusterwiseNetwork}, } for _, tc := range testCases { @@ -273,28 +317,35 @@ func (suite *DPDKNetworkTestSuite) TestDeleteNetwork() { //Parameters np, err := GetNetworkProvider(tc.network) suite.NoError(err) - np = np.(OVSUserspaceNetworkProvider) - err = np.CreateNetwork(suite.sp, tc.network) + np = np.(userspaceNetworkProvider) + err = np.CreateNetwork(suite.sp) suite.NoError(err) // ovs-vsctl add-br br0 -- set bridge br0 datapath_type=netdev - exec.Command("ovs-vsctl", "add-br", tc.network.OVSUserspace.BridgeName, "--", "set", "bridge", tc.network.OVSUserspace.BridgeName, "datapath_type=netdev").Run() + exec.Command("ovs-vsctl", "add-br", tc.network.BridgeName, "--", "set", "bridge", tc.network.BridgeName, "datapath_type=netdev").Run() //FIXME we need a function to check the bridge is exist - err = np.DeleteNetwork(suite.sp, tc.network) + err = np.DeleteNetwork(suite.sp) suite.NoError(err) }) } } -func (suite *DPDKNetworkTestSuite) TestDeleteNetworkFail() { +// OK +func (suite *OVSNetdevNetworkTestSuite) TestDeleteNetworkFail() { network := entity.Network{ - Type: entity.OVSUserspaceNetworkType, + Type: entity.OVSUserspaceNetworkType, + IsDPDKPort: false, + Name: "none-exist-network", + BridgeName: "none", + Nodes: []entity.Node{ + entity.Node{ + Name: namesgenerator.GetRandomName(0), + }, + }, } - network.NodeName = "non-exist" - np, err := GetNetworkProvider(&network) suite.NoError(err) - np = np.(OVSUserspaceNetworkProvider) - err = np.DeleteNetwork(suite.sp, &network) + np = np.(userspaceNetworkProvider) + err = np.DeleteNetwork(suite.sp) suite.Error(err) } diff --git a/src/networkprovider/ovs_system.go b/src/networkprovider/ovs_system.go index 00ed3cfd..3aef2b74 100644 --- a/src/networkprovider/ovs_system.go +++ b/src/networkprovider/ovs_system.go @@ -10,66 +10,82 @@ import ( "gopkg.in/mgo.v2/bson" ) -type UserSpaceNetworkProvider struct { - nodes []entity.Node +type kernelspaceNetworkProvider struct { + networkName string + bridgeName string + vlanTags []int32 + nodes []entity.Node + isDPDKPort bool } -func (unp UserSpaceNetworkProvider) ValidateBeforeCreating(sp *serviceprovider.Container, network *entity.Network) error { +func (knp kernelspaceNetworkProvider) ValidateBeforeCreating(sp *serviceprovider.Container) error { session := sp.Mongo.NewSession() defer session.Close() // Check whether VLAN Tag is 0~4095 - for _, tag := range network.VLANTags { + for _, tag := range knp.vlanTags { if tag < 0 || tag > 4095 { return fmt.Errorf("The vlangTag %d should between 0 and 4095", tag) } } + if knp.isDPDKPort != false { + return fmt.Errorf("unsupport dpdk in kernel space datapath") + } + q := bson.M{ - "networks.name": network.Name, + "name": knp.networkName, } n, err := session.Count(entity.NetworkCollectionName, q) if n >= 1 { - return fmt.Errorf("The network name: %s is exist.", network.Name) + return fmt.Errorf("The network name: %s is exist.", knp.networkName) } else if err != nil { return err } return nil } -func (unp UserSpaceNetworkProvider) CreateNetwork(sp *serviceprovider.Container, network *entity.Network) error { - for _, node := range unp.nodes { +func (knp kernelspaceNetworkProvider) CreateNetwork(sp *serviceprovider.Container) error { + for _, node := range knp.nodes { nodeIP, err := sp.KubeCtl.GetNodeExternalIP(node.Name) if err != nil { return err } - if err := createOVSNetwork(nodeIP, node.Name, node.PhyInterface, network.VLANTags); err != nil { + if err := createOVSNetwork( + nodeIP, + knp.bridgeName, + node.PhyInterfaces, + knp.vlanTags, + ); err != nil { return err } } return nil } -func (unp UserSpaceNetworkProvider) DeleteNetwork(sp *serviceprovider.Container, network *entity.Network) error { - for _, node := range unp.nodes { +func (knp kernelspaceNetworkProvider) DeleteNetwork(sp *serviceprovider.Container) error { + for _, node := range knp.nodes { nodeIP, err := sp.KubeCtl.GetNodeExternalIP(node.Name) if err != nil { return err } - if err := deleteOVSNetwork(nodeIP, network.BridgeName); err != nil { + if err := deleteOVSNetwork( + nodeIP, + knp.bridgeName, + ); err != nil { return err } } return nil } -func createOVSNetwork(nodeIP string, bridgeName string, phyIface entity.PhyInterface, vlanTags []int32) error { +func createOVSNetwork(nodeIP string, bridgeName string, phyIfaces []entity.PhyInterface, vlanTags []int32) error { nodeAddr := net.JoinHostPort(nodeIP, networkcontroller.DEFAULT_CONTROLLER_PORT) nc, err := networkcontroller.New(nodeAddr) if err != nil { return err } - return nc.CreateOVSNetwork("system", bridgeName, phyIface, vlanTags) + return nc.CreateOVSNetwork("system", bridgeName, phyIfaces, vlanTags) } func deleteOVSNetwork(nodeIP string, bridgeName string) error { diff --git a/src/networkprovider/ovs_system_test.go b/src/networkprovider/ovs_system_test.go index 83746624..5ee14767 100644 --- a/src/networkprovider/ovs_system_test.go +++ b/src/networkprovider/ovs_system_test.go @@ -36,28 +36,46 @@ func execute(suite *suite.Suite, cmd *exec.Cmd) { fmt.Printf("Stderr: %s\n", string(w.Bytes())) } -type NetworkTestSuite struct { +//OK +type OVSSystemNetworkTestSuite struct { suite.Suite - sp *serviceprovider.Container - clusterNetwork entity.Network - singleNetwork entity.Network + sp *serviceprovider.Container + standaloneNetwork entity.Network + clusterwiseNetwork entity.Network } -func (suite *NetworkTestSuite) SetupSuite() { +// OK +func (suite *OVSSystemNetworkTestSuite) SetupSuite() { cf := config.MustRead("../../config/testing.json") suite.sp = serviceprovider.NewForTesting(cf) - //init fakeclient + // init fakeclient fakeclient := fakeclientset.NewSimpleClientset() namespace := "default" suite.sp.KubeCtl = kc.New(fakeclient, namespace) - //Create a fake clinet - //Init node - nodeName := namesgenerator.GetRandomName(0) + // Create a fake clinet + // Initial nodes + nodeName1 := namesgenerator.GetRandomName(0) + nodeName2 := namesgenerator.GetRandomName(1) _, err := suite.sp.KubeCtl.Clientset.CoreV1().Nodes().Create(&corev1.Node{ ObjectMeta: metav1.ObjectMeta{ - Name: nodeName, + Name: nodeName1, + }, + Status: corev1.NodeStatus{ + Addresses: []corev1.NodeAddress{ + { + Type: "ExternalIP", + Address: OVS_LOCAL_IP, + }, + }, + }, + }) + suite.NoError(err) + + _, err = suite.sp.KubeCtl.Clientset.CoreV1().Nodes().Create(&corev1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: nodeName2, }, Status: corev1.NodeStatus{ Addresses: []corev1.NodeAddress{ @@ -71,32 +89,38 @@ func (suite *NetworkTestSuite) SetupSuite() { suite.NoError(err) tName := namesgenerator.GetRandomName(0) - suite.singleNetwork = entity.Network{ - Name: tName, - OVS: entity.OVSNetwork{ - BridgeName: tName, - PhysicalPorts: []entity.PhysicalPort{}, + + suite.standaloneNetwork = entity.Network{ + Type: entity.OVSKernelspaceNetworkType, + Name: tName, + BridgeName: tName, + Nodes: []entity.Node{ + entity.Node{ + Name: nodeName1, + }, }, - Type: entity.OVSKernelspaceNetworkType, - NodeName: nodeName, } - suite.clusterNetwork = entity.Network{ - Name: tName, - OVS: entity.OVSNetwork{ - BridgeName: tName, - PhysicalPorts: []entity.PhysicalPort{}, + suite.clusterwiseNetwork = entity.Network{ + Type: entity.OVSKernelspaceNetworkType, + Name: tName, + BridgeName: tName, + Nodes: []entity.Node{ + entity.Node{ + Name: nodeName1, + }, + entity.Node{ + Name: nodeName2, + }, }, - Type: entity.OVSKernelspaceNetworkType, - NodeName: nodeName, - Clusterwise: true, } -} -func (suite *NetworkTestSuite) TearDownSuite() { } -func TestOVSDPDKNetworkSuite(t *testing.T) { +func (suite *OVSSystemNetworkTestSuite) TearDownSuite() {} + +// OK +func TestOVSNetworkSuite(t *testing.T) { if runtime.GOOS != "linux" { fmt.Println("We only testing the ovs function on Linux Host") t.Skip() @@ -106,88 +130,98 @@ func TestOVSDPDKNetworkSuite(t *testing.T) { t.SkipNow() return } - suite.Run(t, new(NetworkTestSuite)) + suite.Run(t, new(OVSSystemNetworkTestSuite)) } -//Member funcion -func (suite *NetworkTestSuite) TestCreateOVSNetwork() { - name := namesgenerator.GetRandomName(0) - err := createOVSNetwork(OVS_LOCAL_IP, name, []entity.PhysicalPort{}) - defer exec.Command("ovs-vsctl", "del-br", name).Run() +// OK +func (suite *OVSSystemNetworkTestSuite) TestCreateOVSNetwork() { + brName := namesgenerator.GetRandomName(0) + err := createOVSNetwork( + OVS_LOCAL_IP, + brName, + []entity.PhyInterface{}, + []int32{0, 2048, 4095}, + ) + defer exec.Command("ovs-vsctl", "del-br", brName).Run() suite.NoError(err) } -func (suite *NetworkTestSuite) TestDeleteOVSNetwork() { - name := namesgenerator.GetRandomName(0) +// OK +func (suite *OVSSystemNetworkTestSuite) TestDeleteOVSNetwork() { + brName := namesgenerator.GetRandomName(0) // ovs-vsctl add-br br0 -- set bridge br0 datapath_type=netdev - exec.Command("ovs-vsctl", "add-br", name, "--", "set", "bridge", name, "datapath_type=netdev").Run() - err := deleteOVSNetwork(OVS_LOCAL_IP, name) + exec.Command("ovs-vsctl", "add-br", brName, "--", "set", "bridge", brName, "datapath_type=netdev").Run() + err := deleteOVSNetwork(OVS_LOCAL_IP, brName) suite.NoError(err) } -func (suite *NetworkTestSuite) TestCreateNetwork() { +func (suite *OVSSystemNetworkTestSuite) TestCreateNetwork() { testCases := []struct { caseName string network *entity.Network }{ - {"singelNetwork", &suite.singleNetwork}, - {"clusterNetwork", &suite.clusterNetwork}, + {"standaloneNetwork", &suite.standaloneNetwork}, + {"clusterwiseNetwork", &suite.clusterwiseNetwork}, } for _, tc := range testCases { suite.T().Run(tc.caseName, func(t *testing.T) { - //Parameters np, err := GetNetworkProvider(tc.network) suite.NoError(err) - np = np.(OVSNetworkProvider) - err = np.CreateNetwork(suite.sp, tc.network) + np = np.(kernelspaceNetworkProvider) + err = np.CreateNetwork(suite.sp) suite.NoError(err) - defer exec.Command("ovs-vsctl", "del-br", tc.network.OVS.BridgeName).Run() + defer exec.Command("ovs-vsctl", "del-br", tc.network.BridgeName).Run() }) } } -func (suite *NetworkTestSuite) TestCreateNetworkFail() { +func (suite *OVSSystemNetworkTestSuite) TestCreateNetworkFail() { network := entity.Network{ - Type: entity.OVSKernelspaceNetworkType, + Type: entity.OVSKernelspaceNetworkType, + Name: "none-exist-network", + BridgeName: "none", + Nodes: []entity.Node{ + entity.Node{ + Name: namesgenerator.GetRandomName(0), + }, + }, } - network.NodeName = "non-exist" np, err := GetNetworkProvider(&network) suite.NoError(err) - np = np.(OVSNetworkProvider) - err = np.CreateNetwork(suite.sp, &network) + np = np.(kernelspaceNetworkProvider) + err = np.CreateNetwork(suite.sp) suite.Error(err) } -func (suite *NetworkTestSuite) TestValidateBeforeCreating() { - //Vlan - //multiple network - //single network - - //Prepare data - eth1 := entity.PhysicalPort{ - Name: namesgenerator.GetRandomName(0), - MTU: 1500, - VlanTags: []int32{2043, 2143, 2243}, - } - +func (suite *OVSSystemNetworkTestSuite) TestValidateBeforeCreating() { tName := namesgenerator.GetRandomName(0) - network := entity.Network{ - Name: tName, - OVS: entity.OVSNetwork{ - BridgeName: tName, - PhysicalPorts: []entity.PhysicalPort{eth1}, + // Valid VLAN number + validVLANnetwork := entity.Network{ + Type: entity.OVSKernelspaceNetworkType, + Name: tName, + VLANTags: []int32{0, 2048, 4095}, + BridgeName: "bro", + Nodes: []entity.Node{ + entity.Node{ + Name: "node-1", + PhyInterfaces: []entity.PhyInterface{ + entity.PhyInterface{ + Name: namesgenerator.GetRandomName(0), + PCIID: "", + }, + }, + }, }, - Type: entity.OVSKernelspaceNetworkType, } testCases := []struct { caseName string network *entity.Network }{ - {"valid", &network}, - {"singelNetwork", &suite.singleNetwork}, - {"clusterNetwork", &suite.clusterNetwork}, + {"validVLAN", &validVLANnetwork}, + {"singelNetwork", &suite.standaloneNetwork}, + {"clusterNetwork", &suite.clusterwiseNetwork}, } for _, tc := range testCases { @@ -195,44 +229,46 @@ func (suite *NetworkTestSuite) TestValidateBeforeCreating() { //Parameters np, err := GetNetworkProvider(tc.network) suite.NoError(err) - np = np.(OVSNetworkProvider) + np = np.(kernelspaceNetworkProvider) - err = np.ValidateBeforeCreating(suite.sp, tc.network) + err = np.ValidateBeforeCreating(suite.sp) suite.NoError(err) }) } } -func (suite *NetworkTestSuite) TestValidateBeforeCreatingFail() { - //Wrong Vlan - //Wrong Case for multiple - //Wrong Case for single - - //Prepare data - eth1 := entity.PhysicalPort{ - Name: namesgenerator.GetRandomName(0), - MTU: 1500, - VlanTags: []int32{2043, 2143, 22435}, - } - +// OK +func (suite *OVSSystemNetworkTestSuite) TestValidateBeforeCreatingFail() { tName := namesgenerator.GetRandomName(0) - network := entity.Network{ - Name: tName, - OVS: entity.OVSNetwork{ - BridgeName: tName, - PhysicalPorts: []entity.PhysicalPort{eth1}, + // Invalid VLAN number + invalidVLANnetwork := entity.Network{ + Type: entity.OVSKernelspaceNetworkType, + Name: tName, + VLANTags: []int32{22435, 2143, 4096}, + BridgeName: "brx", + Nodes: []entity.Node{ + entity.Node{ + Name: "node-1", + PhyInterfaces: []entity.PhyInterface{ + entity.PhyInterface{ + Name: namesgenerator.GetRandomName(0), + PCIID: "", + }, + }, + }, }, - Type: entity.OVSKernelspaceNetworkType, } + // Invalid Case for duplicated name in standalone network + // Invalid Case for duplicates name in clusterwise network testCases := []struct { caseName string network *entity.Network mongo bool }{ - {"invalidVlan", &network, false}, - {"singelNetwork", &suite.singleNetwork, true}, - {"clusterNetwork", &suite.clusterNetwork, true}, + {"invalidVLAN", &invalidVLANnetwork, false}, + {"singelNetwork", &suite.standaloneNetwork, true}, + {"clusterNetwork", &suite.clusterwiseNetwork, true}, } for _, tc := range testCases { @@ -240,7 +276,7 @@ func (suite *NetworkTestSuite) TestValidateBeforeCreatingFail() { //Parameters np, err := GetNetworkProvider(tc.network) suite.NoError(err) - np = np.(OVSNetworkProvider) + np = np.(kernelspaceNetworkProvider) if tc.mongo { //create a mongo-document to test duplicated name @@ -249,19 +285,19 @@ func (suite *NetworkTestSuite) TestValidateBeforeCreatingFail() { defer session.C(entity.NetworkCollectionName).Remove(tc.network) suite.NoError(err) } - err = np.ValidateBeforeCreating(suite.sp, tc.network) + err = np.ValidateBeforeCreating(suite.sp) suite.Error(err) }) } } -func (suite *NetworkTestSuite) TestDeleteNetwork() { +func (suite *OVSSystemNetworkTestSuite) TestDeleteNetwork() { testCases := []struct { caseName string network *entity.Network }{ - {"singelNetwork", &suite.singleNetwork}, - {"clusterNetwork", &suite.clusterNetwork}, + {"standaloneNetwork", &suite.standaloneNetwork}, + {"clusterwiseNetwork", &suite.clusterwiseNetwork}, } for _, tc := range testCases { @@ -269,27 +305,34 @@ func (suite *NetworkTestSuite) TestDeleteNetwork() { //Parameters np, err := GetNetworkProvider(tc.network) suite.NoError(err) - np = np.(OVSNetworkProvider) - err = np.CreateNetwork(suite.sp, tc.network) + np = np.(kernelspaceNetworkProvider) + err = np.CreateNetwork(suite.sp) suite.NoError(err) - exec.Command("ovs-vsctl", "add-br", tc.network.OVS.BridgeName).Run() + // ovs-vsctl add-br br0 -- set bridge br0 datapath_type=netdev + exec.Command("ovs-vsctl", "add-br", tc.network.BridgeName, "--", "set", "bridge", tc.network.BridgeName, "datapath_type=netdev").Run() //FIXME we need a function to check the bridge is exist - err = np.DeleteNetwork(suite.sp, tc.network) + err = np.DeleteNetwork(suite.sp) suite.NoError(err) }) } } -func (suite *NetworkTestSuite) TestDeleteNetworkFail() { +// OK +func (suite *OVSSystemNetworkTestSuite) TestDeleteNetworkFail() { network := entity.Network{ - Type: entity.OVSKernelspaceNetworkType, + Type: entity.OVSKernelspaceNetworkType, + Name: "none-exist-network", + BridgeName: "none", + Nodes: []entity.Node{ + entity.Node{ + Name: namesgenerator.GetRandomName(0), + }, + }, } - network.NodeName = "non-exist" - np, err := GetNetworkProvider(&network) suite.NoError(err) - np = np.(OVSNetworkProvider) - err = np.DeleteNetwork(suite.sp, &network) + np = np.(kernelspaceNetworkProvider) + err = np.DeleteNetwork(suite.sp) suite.Error(err) } diff --git a/src/server/handler_network.go b/src/server/handler_network.go index 514f137f..75578982 100644 --- a/src/server/handler_network.go +++ b/src/server/handler_network.go @@ -26,10 +26,11 @@ func createNetworkHandler(ctx *web.Context) { session := sp.Mongo.NewSession() defer session.Close() - session.C(entity.NetworkCollectionName).EnsureIndex(mgo.Index{ - Key: []string{"name", "nodeName"}, - Unique: true, - }) + session.C(entity.NetworkCollectionName).EnsureIndex( + mgo.Index{ + Key: []string{"name"}, + Unique: true, + }) networkProvider, err := np.GetNetworkProvider(&network) if err != nil { @@ -37,12 +38,12 @@ func createNetworkHandler(ctx *web.Context) { return } - if err := networkProvider.ValidateBeforeCreating(sp, &network); err != nil { + if err := networkProvider.ValidateBeforeCreating(sp); err != nil { response.BadRequest(req.Request, resp.ResponseWriter, err) return } - if err := networkProvider.CreateNetwork(sp, &network); err != nil { + if err := networkProvider.CreateNetwork(sp); err != nil { response.InternalServerError(req.Request, resp.ResponseWriter, err) return } @@ -157,7 +158,7 @@ func deleteNetworkHandler(ctx *web.Context) { return } - if err := networkProvider.DeleteNetwork(sp, &network); err != nil { + if err := networkProvider.DeleteNetwork(sp); err != nil { response.InternalServerError(req.Request, resp.ResponseWriter, err) return } diff --git a/src/server/handler_network_test.go b/src/server/handler_network_test.go index f68806cc..d89480b2 100644 --- a/src/server/handler_network_test.go +++ b/src/server/handler_network_test.go @@ -54,11 +54,13 @@ func TestNetworkSuite(t *testing.T) { func (suite *NetworkTestSuite) TestCreateNetwork() { tName := namesgenerator.GetRandomName(0) network := entity.Network{ + Type: entity.FakeNetworkType, Name: tName, - Fake: entity.FakeNetwork{ - FakeParameter: "fake~", + Nodes: []entity.Node{ + entity.Node{ + FakeParameter: "fake", + }, }, - Type: entity.FakeNetworkType, } bodyBytes, err := json.MarshalIndent(network, "", " ") @@ -95,28 +97,40 @@ func (suite *NetworkTestSuite) TestCreateNetworkFail() { network entity.Network errorCode int }{ - {"InvalidParameter", entity.Network{ - Name: namesgenerator.GetRandomName(0), - Type: entity.FakeNetworkType, - Fake: entity.FakeNetwork{ - FakeParameter: "", - }}, + {"InvalidParameter", + entity.Network{ + Name: namesgenerator.GetRandomName(0), + Type: entity.FakeNetworkType, + Nodes: []entity.Node{ + entity.Node{ + FakeParameter: "", + }, + }, + }, http.StatusBadRequest}, - {"CreateFail", entity.Network{ - Name: namesgenerator.GetRandomName(0), - Type: entity.FakeNetworkType, - Fake: entity.FakeNetwork{ - FakeParameter: "Yo", - IWantFail: true, - }}, + {"CreateFail", + entity.Network{ + Name: namesgenerator.GetRandomName(0), + Type: entity.FakeNetworkType, + Nodes: []entity.Node{ + entity.Node{ + FakeParameter: "Yo", + ShouldFail: true, + }, + }, + }, http.StatusInternalServerError}, - {"NetworkTypeError", entity.Network{ - Name: namesgenerator.GetRandomName(0), - Type: "non-exist", - Fake: entity.FakeNetwork{ - FakeParameter: "Yo", - IWantFail: true, - }}, + {"NetworkTypeError", + entity.Network{ + Name: namesgenerator.GetRandomName(0), + Type: "non-exist", + Nodes: []entity.Node{ + entity.Node{ + FakeParameter: "Yo", + ShouldFail: true, + }, + }, + }, http.StatusBadRequest}, } @@ -143,8 +157,10 @@ func (suite *NetworkTestSuite) TestDeleteNetwork() { network := entity.Network{ ID: bson.NewObjectId(), Name: tName, - Fake: entity.FakeNetwork{}, Type: entity.FakeNetworkType, + Nodes: []entity.Node{ + entity.Node{}, + }, } //Create data into mongo manually @@ -179,19 +195,26 @@ func (suite *NetworkTestSuite) TestDeleteNetworkFail() { ID: bson.NewObjectId(), Name: namesgenerator.GetRandomName(0), Type: entity.FakeNetworkType, - Fake: entity.FakeNetwork{ - FakeParameter: "Yo", - IWantFail: true, - }}, + Nodes: []entity.Node{ + entity.Node{ + FakeParameter: "Yo", + ShouldFail: true, + }, + }, + }, http.StatusInternalServerError}, - {"NetworkTypeError", entity.Network{ - ID: bson.NewObjectId(), - Name: namesgenerator.GetRandomName(0), - Type: "non-exist", - Fake: entity.FakeNetwork{ - FakeParameter: "Yo", - IWantFail: true, - }}, + {"NetworkTypeError", + entity.Network{ + ID: bson.NewObjectId(), + Name: namesgenerator.GetRandomName(0), + Type: "none-exist", + Nodes: []entity.Node{ + entity.Node{ + FakeParameter: "Yo", + ShouldFail: true, + }, + }, + }, http.StatusBadRequest}, } @@ -215,14 +238,17 @@ func (suite *NetworkTestSuite) TestDeleteNetworkFail() { func (suite *NetworkTestSuite) TestGetNetwork() { tName := namesgenerator.GetRandomName(0) tType := entity.FakeNetworkType - network := entity.Network{ - ID: bson.NewObjectId(), - Name: tName, - Type: tType, - NodeName: namesgenerator.GetRandomName(0), + ID: bson.NewObjectId(), + Name: tName, + Type: tType, + Nodes: []entity.Node{ + entity.Node{ + Name: namesgenerator.GetRandomName(0), + FakeParameter: "fake", + }, + }, } - //Create data into mongo manually suite.session.C(entity.NetworkCollectionName).Insert(network) defer suite.session.Remove(entity.NetworkCollectionName, "name", tName) @@ -242,8 +268,7 @@ func (suite *NetworkTestSuite) TestGetNetwork() { } func (suite *NetworkTestSuite) TestGetNetworkWithInvalidID() { - - //Get data with non-exits ID + // Get data with none-exits ID httpRequest, err := http.NewRequest("GET", "http://localhost:7890/v1/networks/"+bson.NewObjectId().Hex(), nil) suite.NoError(err) @@ -258,10 +283,13 @@ func (suite *NetworkTestSuite) TestListNetwork() { count := 3 for i := 0; i < count; i++ { networks = append(networks, entity.Network{ - Name: namesgenerator.GetRandomName(0), - Fake: entity.FakeNetwork{}, - Type: entity.FakeNetworkType, - NodeName: namesgenerator.GetRandomName(0), + Name: namesgenerator.GetRandomName(0), + Type: entity.FakeNetworkType, + Nodes: []entity.Node{ + entity.Node{ + Name: namesgenerator.GetRandomName(0), + }, + }, }) } @@ -304,7 +332,7 @@ func (suite *NetworkTestSuite) TestListNetwork() { for i, v := range retNetworks { suite.Equal(networks[i].Name, v.Name) suite.Equal(networks[i].Type, v.Type) - suite.Equal(networks[i].NodeName, v.NodeName) + suite.Equal(networks[i].Nodes[0].Name, v.Nodes[0].Name) } })