From 8cea83fe65530248bc2e6ac2bd2684f122629999 Mon Sep 17 00:00:00 2001 From: Ashvin Deodhar Date: Wed, 27 Mar 2019 18:06:01 -0700 Subject: [PATCH 01/10] Add option in CNS to pre-provision hns network Add a commandline option in CNS to pre-provision hns network. The commandline option take the type of the network that needs pre-provisioning. This allows orchestrators to start CNS with this option so that the VM network blip / disconnect is avoided when calling cni add the very first time. --- cns/restserver/restserver.go | 71 ++++++++++++++++++++++++++++++++++++ cns/service/main.go | 9 +++++ common/config.go | 4 ++ 3 files changed, 84 insertions(+) diff --git a/cns/restserver/restserver.go b/cns/restserver/restserver.go index 54e024b1ad..6030ed46c1 100644 --- a/cns/restserver/restserver.go +++ b/cns/restserver/restserver.go @@ -8,6 +8,7 @@ import ( "fmt" "net" "net/http" + "strings" "sync" "time" @@ -22,6 +23,7 @@ import ( "github.com/Azure/azure-container-networking/log" "github.com/Azure/azure-container-networking/platform" "github.com/Azure/azure-container-networking/store" + "github.com/Microsoft/hcsshim" ) const ( @@ -171,10 +173,79 @@ func (service *HTTPRestService) Start(config *common.ServiceConfig) error { listener.AddHandler(cns.V2Prefix+cns.AttachContainerToNetwork, service.attachNetworkContainerToNetwork) listener.AddHandler(cns.V2Prefix+cns.DetachContainerFromNetwork, service.detachNetworkContainerFromNetwork) + if err := service.CreateExtHnsNetwork(); err != nil { + log.Printf("[Azure CNS] Failed to create ext network. Error: %v", err) + return err + } + log.Printf("[Azure CNS] Listening.") return nil } +// CreateExtHnsNetwork creates ext HNS network if not present. +func (service *HTTPRestService) CreateExtHnsNetwork() error { + // Ext Hns network is valid for windows only + if !strings.EqualFold(platform.GetOSInfo(), "windows") { + return nil + } + + // Check if the CNS option for createExtNetworkType is set + createExtNetworkType, _ := service.GetOption(acn.OptCreateExtNetworkType).(string) + + if len(strings.TrimSpace(createExtNetworkType)) == 0 { + return nil + } + + if !strings.EqualFold(createExtNetworkType, "l2bridge") && + !strings.EqualFold(createExtNetworkType, "l2tunnel") { + return fmt.Errorf("Invalid ext hns network type %s", createExtNetworkType) + } + + log.Printf("[Azure CNS] CreateExtHnsNetwork") + extHnsNetwork, err := hcsshim.GetHNSNetworkByName("ext") + + if extHnsNetwork != nil { + log.Printf("[Azure CNS] Found existing ext hns network with type: %s", extHnsNetwork.Type) + if !strings.EqualFold(createExtNetworkType, extHnsNetwork.Type) { + return fmt.Errorf("Network type mismatch with existing network: %s", extHnsNetwork.Type) + } + + return nil + } + + // create new hns network + log.Printf("[Azure CNS] Creating ext hns network with type %s", createExtNetworkType) + + hnsNetwork := &hcsshim.HNSNetwork{ + Name: "ext", + Type: createExtNetworkType, + } + + hnsSubnet := hcsshim.Subnet{ + AddressPrefix: "192.168.255.0/30", + GatewayAddress: "192.168.255.1", + } + + hnsNetwork.Subnets = append(hnsNetwork.Subnets, hnsSubnet) + + // Marshal the request. + buffer, err := json.Marshal(hnsNetwork) + if err != nil { + return err + } + hnsRequest := string(buffer) + + // Create the HNS network. + log.Printf("[Azure CNS] HNSNetworkRequest POST request:%+v", hnsRequest) + hnsResponse, err := hcsshim.HNSNetworkRequest("POST", "", hnsRequest) + log.Printf("[Azure CNS] HNSNetworkRequest POST response:%+v err:%v.", hnsResponse, err) + if err != nil { + return err + } + + return nil +} + // Stop stops the CNS. func (service *HTTPRestService) Stop() { service.Uninitialize() diff --git a/cns/service/main.go b/cns/service/main.go index 94946de48d..5866024a9d 100644 --- a/cns/service/main.go +++ b/cns/service/main.go @@ -142,6 +142,13 @@ var args = acn.ArgumentList{ Type: "string", DefaultValue: platform.K8SNetConfigPath + string(os.PathSeparator) + defaultCNINetworkConfigFileName, }, + { + Name: acn.OptCreateExtNetworkType, + Shorthand: acn.OptCreateExtNetworkTypeAlias, + Description: "Create ext hns network for windows platform with the specified type", + Type: "string", + DefaultValue: "", + }, } // Prints description and version information. @@ -169,6 +176,7 @@ func main() { stopcnm = acn.GetArg(acn.OptStopAzureVnet).(bool) vers := acn.GetArg(acn.OptVersion).(bool) // reportToHostInterval := acn.GetArg(acn.OptReportToHostInterval).(int) + createExtNetworkType := acn.GetArg(acn.OptCreateExtNetworkType).(string) if vers { printVersion() @@ -228,6 +236,7 @@ func main() { httpRestService.SetOption(acn.OptCnsURL, cnsURL) httpRestService.SetOption(acn.OptCNIPath, cniPath) httpRestService.SetOption(acn.OptCNIConfigFile, cniConfigFile) + httpRestService.SetOption(acn.OptCreateExtNetworkType, createExtNetworkType) // Start CNS. if httpRestService != nil { diff --git a/common/config.go b/common/config.go index 839c1998ff..d3598ab9f4 100644 --- a/common/config.go +++ b/common/config.go @@ -71,4 +71,8 @@ const ( // Telemetry config Location OptTelemetryConfigDir = "telemetry-config-file" OptTelemetryConfigDirAlias = "d" + + // Create ext Hns network + OptCreateExtNetworkType = "create-extnetwork-type" + OptCreateExtNetworkTypeAlias = "extnetworktype" ) From ef256d8331ffdb5b9a58789cb6dc692f13e4059b Mon Sep 17 00:00:00 2001 From: Ashvin Deodhar Date: Thu, 28 Mar 2019 11:37:15 -0700 Subject: [PATCH 02/10] Move the code to platform files --- cns/restserver/restserver.go | 62 +----------------------------------- platform/os_linux.go | 6 ++++ platform/os_windows.go | 58 +++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 61 deletions(-) diff --git a/cns/restserver/restserver.go b/cns/restserver/restserver.go index 6030ed46c1..d0bf8d4c4b 100644 --- a/cns/restserver/restserver.go +++ b/cns/restserver/restserver.go @@ -8,7 +8,6 @@ import ( "fmt" "net" "net/http" - "strings" "sync" "time" @@ -23,7 +22,6 @@ import ( "github.com/Azure/azure-container-networking/log" "github.com/Azure/azure-container-networking/platform" "github.com/Azure/azure-container-networking/store" - "github.com/Microsoft/hcsshim" ) const ( @@ -184,66 +182,8 @@ func (service *HTTPRestService) Start(config *common.ServiceConfig) error { // CreateExtHnsNetwork creates ext HNS network if not present. func (service *HTTPRestService) CreateExtHnsNetwork() error { - // Ext Hns network is valid for windows only - if !strings.EqualFold(platform.GetOSInfo(), "windows") { - return nil - } - - // Check if the CNS option for createExtNetworkType is set createExtNetworkType, _ := service.GetOption(acn.OptCreateExtNetworkType).(string) - - if len(strings.TrimSpace(createExtNetworkType)) == 0 { - return nil - } - - if !strings.EqualFold(createExtNetworkType, "l2bridge") && - !strings.EqualFold(createExtNetworkType, "l2tunnel") { - return fmt.Errorf("Invalid ext hns network type %s", createExtNetworkType) - } - - log.Printf("[Azure CNS] CreateExtHnsNetwork") - extHnsNetwork, err := hcsshim.GetHNSNetworkByName("ext") - - if extHnsNetwork != nil { - log.Printf("[Azure CNS] Found existing ext hns network with type: %s", extHnsNetwork.Type) - if !strings.EqualFold(createExtNetworkType, extHnsNetwork.Type) { - return fmt.Errorf("Network type mismatch with existing network: %s", extHnsNetwork.Type) - } - - return nil - } - - // create new hns network - log.Printf("[Azure CNS] Creating ext hns network with type %s", createExtNetworkType) - - hnsNetwork := &hcsshim.HNSNetwork{ - Name: "ext", - Type: createExtNetworkType, - } - - hnsSubnet := hcsshim.Subnet{ - AddressPrefix: "192.168.255.0/30", - GatewayAddress: "192.168.255.1", - } - - hnsNetwork.Subnets = append(hnsNetwork.Subnets, hnsSubnet) - - // Marshal the request. - buffer, err := json.Marshal(hnsNetwork) - if err != nil { - return err - } - hnsRequest := string(buffer) - - // Create the HNS network. - log.Printf("[Azure CNS] HNSNetworkRequest POST request:%+v", hnsRequest) - hnsResponse, err := hcsshim.HNSNetworkRequest("POST", "", hnsRequest) - log.Printf("[Azure CNS] HNSNetworkRequest POST response:%+v err:%v.", hnsResponse, err) - if err != nil { - return err - } - - return nil + return platform.CreateExtHnsNetwork(createExtNetworkType) } // Stop stops the CNS. diff --git a/platform/os_linux.go b/platform/os_linux.go index 9e03f24054..b80a0b5690 100644 --- a/platform/os_linux.go +++ b/platform/os_linux.go @@ -105,3 +105,9 @@ func KillProcessByName(processName string) error { _, err := ExecuteCommand(cmd) return err } + +// CreateExtHnsNetwork creates ext HNS network if not present +func CreateExtHnsNetwork(createExtNetworkType string) error { + // This feature is windows specific + return nil +} diff --git a/platform/os_windows.go b/platform/os_windows.go index 7e743ee5db..250bcadeac 100644 --- a/platform/os_windows.go +++ b/platform/os_windows.go @@ -5,12 +5,14 @@ package platform import ( "bytes" + "encoding/json" "fmt" "os/exec" "strings" "time" "github.com/Azure/azure-container-networking/log" + "github.com/Microsoft/hcsshim" ) const ( @@ -118,3 +120,59 @@ func KillProcessByName(processName string) { cmd := fmt.Sprintf("taskkill /IM %v /F", processName) ExecuteCommand(cmd) } + +// CreateExtHnsNetwork creates ext HNS network if not present. +func CreateExtHnsNetwork(createExtNetworkType string) error { + if len(strings.TrimSpace(createExtNetworkType)) == 0 { + return nil + } + + if !strings.EqualFold(createExtNetworkType, "l2bridge") && + !strings.EqualFold(createExtNetworkType, "l2tunnel") { + return fmt.Errorf("Invalid ext hns network type %s", createExtNetworkType) + } + + log.Printf("[Azure CNS] CreateExtHnsNetwork") + extHnsNetwork, err := hcsshim.GetHNSNetworkByName("ext") + + if extHnsNetwork != nil { + log.Printf("[Azure CNS] Found existing ext hns network with type: %s", extHnsNetwork.Type) + if !strings.EqualFold(createExtNetworkType, extHnsNetwork.Type) { + return fmt.Errorf("Network type mismatch with existing network: %s", extHnsNetwork.Type) + } + + return nil + } + + // create new hns network + log.Printf("[Azure CNS] Creating ext hns network with type %s", createExtNetworkType) + + hnsNetwork := &hcsshim.HNSNetwork{ + Name: "ext", + Type: createExtNetworkType, + } + + hnsSubnet := hcsshim.Subnet{ + AddressPrefix: "192.168.255.0/30", + GatewayAddress: "192.168.255.1", + } + + hnsNetwork.Subnets = append(hnsNetwork.Subnets, hnsSubnet) + + // Marshal the request. + buffer, err := json.Marshal(hnsNetwork) + if err != nil { + return err + } + hnsRequest := string(buffer) + + // Create the HNS network. + log.Printf("[Azure CNS] HNSNetworkRequest POST request:%+v", hnsRequest) + hnsResponse, err := hcsshim.HNSNetworkRequest("POST", "", hnsRequest) + log.Printf("[Azure CNS] HNSNetworkRequest POST response:%+v err:%v.", hnsResponse, err) + if err != nil { + return err + } + + return nil +} From 7915b89013253ee30525742143cb4f9ba0842ef6 Mon Sep 17 00:00:00 2001 From: Ashvin Deodhar Date: Thu, 28 Mar 2019 13:08:53 -0700 Subject: [PATCH 03/10] Address review comments --- platform/os_windows.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/platform/os_windows.go b/platform/os_windows.go index 250bcadeac..f535fd222d 100644 --- a/platform/os_windows.go +++ b/platform/os_windows.go @@ -133,7 +133,7 @@ func CreateExtHnsNetwork(createExtNetworkType string) error { } log.Printf("[Azure CNS] CreateExtHnsNetwork") - extHnsNetwork, err := hcsshim.GetHNSNetworkByName("ext") + extHnsNetwork, _ := hcsshim.GetHNSNetworkByName("ext") if extHnsNetwork != nil { log.Printf("[Azure CNS] Found existing ext hns network with type: %s", extHnsNetwork.Type) @@ -170,9 +170,6 @@ func CreateExtHnsNetwork(createExtNetworkType string) error { log.Printf("[Azure CNS] HNSNetworkRequest POST request:%+v", hnsRequest) hnsResponse, err := hcsshim.HNSNetworkRequest("POST", "", hnsRequest) log.Printf("[Azure CNS] HNSNetworkRequest POST response:%+v err:%v.", hnsResponse, err) - if err != nil { - return err - } - return nil + return err } From 6ebc46771621ea0243f5afbe671bf7b343d1cf44 Mon Sep 17 00:00:00 2001 From: Ashvin Deodhar Date: Thu, 28 Mar 2019 13:44:11 -0700 Subject: [PATCH 04/10] Address review comments 2 --- cns/restserver/restserver.go | 3 +++ platform/os_windows.go | 17 +++++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/cns/restserver/restserver.go b/cns/restserver/restserver.go index d0bf8d4c4b..5533c89bf2 100644 --- a/cns/restserver/restserver.go +++ b/cns/restserver/restserver.go @@ -171,6 +171,9 @@ func (service *HTTPRestService) Start(config *common.ServiceConfig) error { listener.AddHandler(cns.V2Prefix+cns.AttachContainerToNetwork, service.attachNetworkContainerToNetwork) listener.AddHandler(cns.V2Prefix+cns.DetachContainerFromNetwork, service.detachNetworkContainerFromNetwork) + // Create ext network on windows platform if speficied through the cns commandline options. + // This allows orchestrators to start CNS which pre-provisions the network so that the + // VM network blip / disconnect is avoided when calling cni add for the very first time. if err := service.CreateExtHnsNetwork(); err != nil { log.Printf("[Azure CNS] Failed to create ext network. Error: %v", err) return err diff --git a/platform/os_windows.go b/platform/os_windows.go index f535fd222d..6264db7c8d 100644 --- a/platform/os_windows.go +++ b/platform/os_windows.go @@ -36,6 +36,15 @@ const ( // DNCRuntimePath is the path where DNC state files are stored. DNCRuntimePath = "" + + // Name of the external hns network + ExtHnsNetworkName = "ext" + + // Address prefix for external hns network + ExtHnsNetworkAddressPrefix = "192.168.255.0/30" + + // Gateway address for external hns network + ExtHnsNetworkGwAddress = "192.168.255.1" ) // GetOSInfo returns OS version information. @@ -133,7 +142,7 @@ func CreateExtHnsNetwork(createExtNetworkType string) error { } log.Printf("[Azure CNS] CreateExtHnsNetwork") - extHnsNetwork, _ := hcsshim.GetHNSNetworkByName("ext") + extHnsNetwork, _ := hcsshim.GetHNSNetworkByName(ExtHnsNetworkName) if extHnsNetwork != nil { log.Printf("[Azure CNS] Found existing ext hns network with type: %s", extHnsNetwork.Type) @@ -148,13 +157,13 @@ func CreateExtHnsNetwork(createExtNetworkType string) error { log.Printf("[Azure CNS] Creating ext hns network with type %s", createExtNetworkType) hnsNetwork := &hcsshim.HNSNetwork{ - Name: "ext", + Name: ExtHnsNetworkName, Type: createExtNetworkType, } hnsSubnet := hcsshim.Subnet{ - AddressPrefix: "192.168.255.0/30", - GatewayAddress: "192.168.255.1", + AddressPrefix: ExtHnsNetworkAddressPrefix, + GatewayAddress: ExtHnsNetworkGwAddress, } hnsNetwork.Subnets = append(hnsNetwork.Subnets, hnsSubnet) From 254f8215a3cd95fef9aa87c0083fdceca1ee7d53 Mon Sep 17 00:00:00 2001 From: Ashvin Deodhar Date: Fri, 29 Mar 2019 10:37:33 -0700 Subject: [PATCH 05/10] address review comments --- cns/restserver/restserver.go | 15 ++++----------- cns/service/main.go | 10 +++++----- common/config.go | 4 ++-- platform/os_linux.go | 5 ++--- platform/os_windows.go | 34 +++++++++++++++++++++++----------- 5 files changed, 36 insertions(+), 32 deletions(-) diff --git a/cns/restserver/restserver.go b/cns/restserver/restserver.go index 5533c89bf2..263226b1b3 100644 --- a/cns/restserver/restserver.go +++ b/cns/restserver/restserver.go @@ -171,11 +171,10 @@ func (service *HTTPRestService) Start(config *common.ServiceConfig) error { listener.AddHandler(cns.V2Prefix+cns.AttachContainerToNetwork, service.attachNetworkContainerToNetwork) listener.AddHandler(cns.V2Prefix+cns.DetachContainerFromNetwork, service.detachNetworkContainerFromNetwork) - // Create ext network on windows platform if speficied through the cns commandline options. - // This allows orchestrators to start CNS which pre-provisions the network so that the - // VM network blip / disconnect is avoided when calling cni add for the very first time. - if err := service.CreateExtHnsNetwork(); err != nil { - log.Printf("[Azure CNS] Failed to create ext network. Error: %v", err) + createExtSwitchNetworkType, _ := service.GetOption(acn.OptCreateExtSwitchNetworkType).(string) + // Perform platform specific initialization + if err := platform.Init(createExtSwitchNetworkType); err != nil { + log.Printf("[Azure CNS] Failed with platform initialization due to error: %v", err) return err } @@ -183,12 +182,6 @@ func (service *HTTPRestService) Start(config *common.ServiceConfig) error { return nil } -// CreateExtHnsNetwork creates ext HNS network if not present. -func (service *HTTPRestService) CreateExtHnsNetwork() error { - createExtNetworkType, _ := service.GetOption(acn.OptCreateExtNetworkType).(string) - return platform.CreateExtHnsNetwork(createExtNetworkType) -} - // Stop stops the CNS. func (service *HTTPRestService) Stop() { service.Uninitialize() diff --git a/cns/service/main.go b/cns/service/main.go index 5866024a9d..205e76ff0c 100644 --- a/cns/service/main.go +++ b/cns/service/main.go @@ -143,9 +143,9 @@ var args = acn.ArgumentList{ DefaultValue: platform.K8SNetConfigPath + string(os.PathSeparator) + defaultCNINetworkConfigFileName, }, { - Name: acn.OptCreateExtNetworkType, - Shorthand: acn.OptCreateExtNetworkTypeAlias, - Description: "Create ext hns network for windows platform with the specified type", + Name: acn.OptCreateExtSwitchNetworkType, + Shorthand: acn.OptCreateExtSwitchNetworkTypeAlias, + Description: "Create ext switch network for windows platform with the specified type (l2bridge or l2tunnel)", Type: "string", DefaultValue: "", }, @@ -176,7 +176,7 @@ func main() { stopcnm = acn.GetArg(acn.OptStopAzureVnet).(bool) vers := acn.GetArg(acn.OptVersion).(bool) // reportToHostInterval := acn.GetArg(acn.OptReportToHostInterval).(int) - createExtNetworkType := acn.GetArg(acn.OptCreateExtNetworkType).(string) + createExtSwitchNetworkType := acn.GetArg(acn.OptCreateExtSwitchNetworkType).(string) if vers { printVersion() @@ -236,7 +236,7 @@ func main() { httpRestService.SetOption(acn.OptCnsURL, cnsURL) httpRestService.SetOption(acn.OptCNIPath, cniPath) httpRestService.SetOption(acn.OptCNIConfigFile, cniConfigFile) - httpRestService.SetOption(acn.OptCreateExtNetworkType, createExtNetworkType) + httpRestService.SetOption(acn.OptCreateExtSwitchNetworkType, createExtSwitchNetworkType) // Start CNS. if httpRestService != nil { diff --git a/common/config.go b/common/config.go index d3598ab9f4..37fb135311 100644 --- a/common/config.go +++ b/common/config.go @@ -73,6 +73,6 @@ const ( OptTelemetryConfigDirAlias = "d" // Create ext Hns network - OptCreateExtNetworkType = "create-extnetwork-type" - OptCreateExtNetworkTypeAlias = "extnetworktype" + OptCreateExtSwitchNetworkType = "create-extswitchnetwork-type" + OptCreateExtSwitchNetworkTypeAlias = "extswitchnetworktype" ) diff --git a/platform/os_linux.go b/platform/os_linux.go index b80a0b5690..fdadf4c0e2 100644 --- a/platform/os_linux.go +++ b/platform/os_linux.go @@ -106,8 +106,7 @@ func KillProcessByName(processName string) error { return err } -// CreateExtHnsNetwork creates ext HNS network if not present -func CreateExtHnsNetwork(createExtNetworkType string) error { - // This feature is windows specific +// Perform platform specific initialization +func Init(createExtSwitchNetworkType string) error { return nil } diff --git a/platform/os_windows.go b/platform/os_windows.go index 6264db7c8d..de1be7d421 100644 --- a/platform/os_windows.go +++ b/platform/os_windows.go @@ -45,6 +45,10 @@ const ( // Gateway address for external hns network ExtHnsNetworkGwAddress = "192.168.255.1" + + // HNS network types + hnsL2Bridge = "l2bridge" + hnsL2Tunnel = "l2tunnel" ) // GetOSInfo returns OS version information. @@ -130,23 +134,31 @@ func KillProcessByName(processName string) { ExecuteCommand(cmd) } -// CreateExtHnsNetwork creates ext HNS network if not present. -func CreateExtHnsNetwork(createExtNetworkType string) error { - if len(strings.TrimSpace(createExtNetworkType)) == 0 { +// Perform platform specific initialization +func Init(createExtSwitchNetworkType string) error { + // Create HNS network to create external switch on windows platform + // This allows orchestrators to start CNS which pre-provisions the network so that the + // VM network blip / disconnect is avoided when calling cni add for the very first time. + return createExtSwitchHnsNetwork(createExtSwitchNetworkType) +} + +// createExtSwitchHnsNetwork creates ext HNS network if not present. +func createExtSwitchHnsNetwork(createExtNetworkType string) error { + networkType := strings.ToLower(strings.TrimSpace(createExtNetworkType)) + if len(networkType) == 0 { return nil } - if !strings.EqualFold(createExtNetworkType, "l2bridge") && - !strings.EqualFold(createExtNetworkType, "l2tunnel") { - return fmt.Errorf("Invalid ext hns network type %s", createExtNetworkType) + if networkType != hnsL2Bridge && networkType != hnsL2Tunnel { + return fmt.Errorf("Invalid hns network type %s", createExtNetworkType) } - log.Printf("[Azure CNS] CreateExtHnsNetwork") + log.Printf("[Azure CNS] createExtSwitchHnsNetwork") extHnsNetwork, _ := hcsshim.GetHNSNetworkByName(ExtHnsNetworkName) if extHnsNetwork != nil { - log.Printf("[Azure CNS] Found existing ext hns network with type: %s", extHnsNetwork.Type) - if !strings.EqualFold(createExtNetworkType, extHnsNetwork.Type) { + log.Printf("[Azure CNS] Found existing external switch hns network with type: %s", extHnsNetwork.Type) + if !strings.EqualFold(networkType, extHnsNetwork.Type) { return fmt.Errorf("Network type mismatch with existing network: %s", extHnsNetwork.Type) } @@ -154,11 +166,11 @@ func CreateExtHnsNetwork(createExtNetworkType string) error { } // create new hns network - log.Printf("[Azure CNS] Creating ext hns network with type %s", createExtNetworkType) + log.Printf("[Azure CNS] Creating external switch hns network with type %s", networkType) hnsNetwork := &hcsshim.HNSNetwork{ Name: ExtHnsNetworkName, - Type: createExtNetworkType, + Type: networkType, } hnsSubnet := hcsshim.Subnet{ From 93c809fa057054be25eefac2efffd2582fa05f76 Mon Sep 17 00:00:00 2001 From: Ashvin Deodhar Date: Fri, 12 Apr 2019 16:04:17 -0700 Subject: [PATCH 06/10] CreateHnsNetwork API WIP --- cns/api.go | 49 ++++++++++++ cns/restserver/restserver.go | 116 +++++++++++++++++++++++++--- cns/service/main.go | 7 ++ platform/os_linux.go | 10 ++- platform/os_windows.go | 142 ++++++++++++++++++++++------------- 5 files changed, 260 insertions(+), 64 deletions(-) diff --git a/cns/api.go b/cns/api.go index 6c37f0cc96..dd41cdebe7 100644 --- a/cns/api.go +++ b/cns/api.go @@ -3,11 +3,15 @@ package cns +import "encoding/json" + // Container Network Service remote API Contract const ( SetEnvironmentPath = "/network/environment" CreateNetworkPath = "/network/create" + CreateHnsNetworkPath = "/network/createhns" DeleteNetworkPath = "/network/delete" + DeleteHnsNetworkPath = "/network/deletehns" ReserveIPAddressPath = "/network/ip/reserve" ReleaseIPAddressPath = "/network/ip/release" GetHostLocalIPPath = "/network/ip/hostlocal" @@ -44,6 +48,51 @@ type DeleteNetworkRequest struct { NetworkName string } +/* +// CreateHnsNetworkRequest describes request to create the HNS network. +type CreateHnsNetworkRequest struct { + NetworkName string + NetworkType string + Options map[string]interface{} +}*/ + +// CreateHnsNetworkRequest describes request to create the HNS network. +type CreateHnsNetworkRequest struct { + ID string `json:"ID,omitempty"` + Name string `json:",omitempty"` + Type string `json:",omitempty"` + NetworkAdapterName string `json:",omitempty"` + SourceMac string `json:",omitempty"` + Policies []json.RawMessage `json:",omitempty"` + MacPools []MacPool `json:",omitempty"` + Subnets []Subnet `json:",omitempty"` + DNSSuffix string `json:",omitempty"` + DNSServerList string `json:",omitempty"` + DNSServerCompartment uint32 `json:",omitempty"` + ManagementIP string `json:",omitempty"` + AutomaticDNS bool `json:",omitempty"` +} + +// Subnet is assoicated with HNS network and represents a list +// of subnets available to the network +type Subnet struct { + AddressPrefix string `json:",omitempty"` + GatewayAddress string `json:",omitempty"` + Policies []json.RawMessage `json:",omitempty"` +} + +// MacPool is assoicated with HNS network and represents a list +// of macaddresses available to the network +type MacPool struct { + StartMacAddress string `json:",omitempty"` + EndMacAddress string `json:",omitempty"` +} + +// DeleteHnsNetworkRequest describes request to delete the HNS network. +type DeleteHnsNetworkRequest struct { + NetworkName string +} + // ReserveIPAddressRequest describes request to reserve an IP Address type ReserveIPAddressRequest struct { ReservationID string diff --git a/cns/restserver/restserver.go b/cns/restserver/restserver.go index 134ec60b29..445101e80e 100644 --- a/cns/restserver/restserver.go +++ b/cns/restserver/restserver.go @@ -154,6 +154,8 @@ func (service *HTTPRestService) Start(config *common.ServiceConfig) error { listener.AddHandler(cns.GetNetworkContainerByOrchestratorContext, service.getNetworkContainerByOrchestratorContext) listener.AddHandler(cns.AttachContainerToNetwork, service.attachNetworkContainerToNetwork) listener.AddHandler(cns.DetachContainerFromNetwork, service.detachNetworkContainerFromNetwork) + listener.AddHandler(cns.CreateHnsNetworkPath, service.createHnsNetwork) + listener.AddHandler(cns.DeleteHnsNetworkPath, service.deleteHnsNetwork) // handlers for v0.2 listener.AddHandler(cns.V2Prefix+cns.SetEnvironmentPath, service.setEnvironment) @@ -172,13 +174,8 @@ func (service *HTTPRestService) Start(config *common.ServiceConfig) error { listener.AddHandler(cns.V2Prefix+cns.GetNetworkContainerByOrchestratorContext, service.getNetworkContainerByOrchestratorContext) listener.AddHandler(cns.V2Prefix+cns.AttachContainerToNetwork, service.attachNetworkContainerToNetwork) listener.AddHandler(cns.V2Prefix+cns.DetachContainerFromNetwork, service.detachNetworkContainerFromNetwork) - - createExtSwitchNetworkType, _ := service.GetOption(acn.OptCreateExtSwitchNetworkType).(string) - // Perform platform specific initialization - if err := platform.Init(createExtSwitchNetworkType); err != nil { - log.Printf("[Azure CNS] Failed with platform initialization due to error: %v", err) - return err - } + listener.AddHandler(cns.V2Prefix+cns.CreateHnsNetworkPath, service.createHnsNetwork) + listener.AddHandler(cns.V2Prefix+cns.DeleteHnsNetworkPath, service.deleteHnsNetwork) log.Printf("[Azure CNS] Listening.") return nil @@ -255,7 +252,7 @@ func (service *HTTPRestService) createNetwork(w http.ResponseWriter, r *http.Req case "Underlay": switch service.state.Location { case "Azure": - log.Printf("[Azure CNS] Goign to create network with name %v.", req.NetworkName) + log.Printf("[Azure CNS] Creating network with name %v.", req.NetworkName) err = rt.GetRoutingTable() if err != nil { @@ -351,7 +348,7 @@ func (service *HTTPRestService) deleteNetwork(w http.ResponseWriter, r *http.Req // Network does exist if err == nil { - log.Printf("[Azure CNS] Goign to delete network with name %v.", req.NetworkName) + log.Printf("[Azure CNS] Deleting network with name %v.", req.NetworkName) err := dc.DeleteNetwork(req.NetworkName) if err != nil { returnMessage = fmt.Sprintf("[Azure CNS] Error. DeleteNetwork failed %v.", err.Error()) @@ -386,6 +383,107 @@ func (service *HTTPRestService) deleteNetwork(w http.ResponseWriter, r *http.Req log.Response(service.Name, resp, resp.ReturnCode, ReturnCodeToString(resp.ReturnCode), err) } +// Handles CreateHnsNetwork requests. +func (service *HTTPRestService) createHnsNetwork(w http.ResponseWriter, r *http.Request) { + log.Printf("[Azure CNS] createHnsNetwork") + + var err error + returnCode := 0 + returnMessage := "" + + var req cns.CreateHnsNetworkRequest + err = service.Listener.Decode(w, r, &req) + log.Request(service.Name, &req, err) + + if err != nil { + returnMessage = fmt.Sprintf("[Azure CNS] Error. Unable to decode input request.") + returnCode = InvalidParameter + } else { + switch r.Method { + case "POST": + if err := platform.CreateNetwork(req); err == nil { + // Save the HnsNetwork that is created. CNS deleteHnsNetwork will only allow deleting + // these networks. + networkInfo := &networkInfo{ + NetworkName: req.NetworkName, + } + service.state.Networks[req.NetworkName] = networkInfo + returnMessage = fmt.Sprintf("[Azure CNS] Successfully created HNS network: %s", req.NetworkName) + } else { + returnMessage = fmt.Sprintf("[Azure CNS] CreateHnsNetwork failed with error %v", err.Error()) + returnCode = UnexpectedError + } + default: + returnMessage = "[Azure CNS] Error. CreateHnsNetwork did not receive a POST." + returnCode = InvalidParameter + } + } + + resp := &cns.Response{ + ReturnCode: returnCode, + Message: returnMessage, + } + + err = service.Listener.Encode(w, &resp) + + if returnCode == 0 { + service.saveState() + } + + log.Response(service.Name, resp, resp.ReturnCode, ReturnCodeToString(resp.ReturnCode), err) +} + +// Handles deleteHnsNetwork requests. +func (service *HTTPRestService) deleteHnsNetwork(w http.ResponseWriter, r *http.Request) { + log.Printf("[Azure CNS] deleteHnsNetwork") + + var err error + var req cns.DeleteHnsNetworkRequest + returnCode := 0 + returnMessage := "" + + err = service.Listener.Decode(w, r, &req) + log.Request(service.Name, &req, err) + + if err != nil { + returnMessage = fmt.Sprintf("[Azure CNS] Error. Unable to decode input request.") + returnCode = InvalidParameter + } else { + switch r.Method { + case "POST": + networkInfo, ok := service.state.Networks[req.NetworkName] + if ok && networkInfo.NetworkName == req.NetworkName { + if err = platform.DeleteNetwork(req.NetworkName); err == nil { + returnMessage = fmt.Sprintf("[Azure CNS] Successfully deleted HNS network: %s", req.NetworkName) + } else { + returnMessage = fmt.Sprintf("[Azure CNS] DeleteHnsNetwork failed with error %v", err.Error()) + returnCode = UnexpectedError + } + } else { + returnMessage = fmt.Sprintf("[Azure CNS] Invalid network name: %s", req.NetworkName) + returnCode = InvalidParameter + } + default: + returnMessage = "[Azure CNS] Error. CreateHnsNetwork did not receive a POST." + returnCode = InvalidParameter + } + } + + resp := &cns.Response{ + ReturnCode: returnCode, + Message: returnMessage, + } + + err = service.Listener.Encode(w, &resp) + + if returnCode == 0 { + delete(service.state.Networks, req.NetworkName) + service.saveState() + } + + log.Response(service.Name, resp, resp.ReturnCode, ReturnCodeToString(resp.ReturnCode), err) +} + // Handles ip reservation requests. func (service *HTTPRestService) reserveIPAddress(w http.ResponseWriter, r *http.Request) { log.Printf("[Azure CNS] reserveIPAddress") diff --git a/cns/service/main.go b/cns/service/main.go index b46c9048a7..2d7b87371c 100644 --- a/cns/service/main.go +++ b/cns/service/main.go @@ -240,6 +240,13 @@ func main() { httpRestService.SetOption(acn.OptNetPluginConfigFile, cniConfigFile) httpRestService.SetOption(acn.OptCreateExtSwitchNetworkType, createExtSwitchNetworkType) + //createExtSwitchNetworkType, _ := service.GetOption(acn.OptCreateExtSwitchNetworkType).(string) + // Perform platform specific initialization + if err := platform.CreateDefaultExtNetwork(createExtSwitchNetworkType); err != nil { + log.Printf("[Azure CNS] Failed to create %s network due to error: %v", createExtSwitchNetworkType, err) + return + } + // Start CNS. if httpRestService != nil { if telemetryEnabled { diff --git a/platform/os_linux.go b/platform/os_linux.go index 21f9777aa7..0f670a277c 100644 --- a/platform/os_linux.go +++ b/platform/os_linux.go @@ -106,12 +106,14 @@ func KillProcessByName(processName string) error { return err } -// Perform platform specific initialization -func Init(createExtSwitchNetworkType string) error { -} - // SetSdnRemoteArpMacAddress sets the regkey for SDNRemoteArpMacAddress needed for multitenancy // This operation is specific to windows OS func SetSdnRemoteArpMacAddress() error { +} + +// CreateNetwork creates network (if it doesn't exist already) +// to create external switch on windows platform. This is not needed +// in linux platoform. +func CreateNetwork(networkType string) error { return nil } diff --git a/platform/os_windows.go b/platform/os_windows.go index 7ed2afa17b..ccbc3a9820 100644 --- a/platform/os_windows.go +++ b/platform/os_windows.go @@ -155,30 +155,95 @@ func KillProcessByName(processName string) { ExecuteCommand(cmd) } -// Perform platform specific initialization -func Init(createExtSwitchNetworkType string) error { - // Create HNS network to create external switch on windows platform - // This allows orchestrators to start CNS which pre-provisions the network so that the - // VM network blip / disconnect is avoided when calling cni add for the very first time. - return createExtSwitchHnsNetwork(createExtSwitchNetworkType) +// executePowershellCommand executes powershell command +func executePowershellCommand(command string) (string, error) { + ps, err := exec.LookPath("powershell.exe") + if err != nil { + return "", fmt.Errorf("Failed to find powershell executable") + } + + cmd := exec.Command(ps, command) + var stdout bytes.Buffer + var stderr bytes.Buffer + cmd.Stdout = &stdout + cmd.Stderr = &stderr + cmd.Run() + + return strings.TrimSpace(stdout.String()), nil +} + +// SetSdnRemoteArpMacAddress sets the regkey for SDNRemoteArpMacAddress needed for multitenancy +func SetSdnRemoteArpMacAddress() error { + if sdnRemoteArpMacAddressSet == false { + result, err := executePowershellCommand(GetSdnRemoteArpMacAddressCommand) + if err != nil { + return err + } + + // Set the reg key if not already set or has incorrect value + if result != SDNRemoteArpMacAddress { + if _, err = executePowershellCommand(SetSdnRemoteArpMacAddressCommand); err != nil { + log.Printf("Failed to set SDNRemoteArpMacAddress due to error %s", err.Error()) + return err + } + + log.Printf("[Azure CNS] SDNRemoteArpMacAddress regKey set successfully. Restarting hns service.") + if _, err := executePowershellCommand(RestartHnsServiceCommand); err != nil { + log.Printf("Failed to Restart HNS Service due to error %s", err.Error()) + return err + } + } + + sdnRemoteArpMacAddressSet = true + } + + return nil +} + +// CreateNetwork creates HNS network with the provided configuration +func CreateNetwork(nwConfig cns.CreateHnsNetworkRequest) error { + log.Printf("[Azure CNS] CreateNetwork") +// Initialize HNS network. +hnsNetwork := &hcsshim.HNSNetwork{ + Name: nwInfo.networkName, + Type: nwInfo.networkType, + NetworkAdapterName: nwInfo.networkAdapterName, + DNSServerList: nwInfo.networkDnsServerList, + Policies: nwInfo.networkPolicies, +} + +// Populate subnets. +for _, subnet := range nwInfo.Subnets { + hnsSubnet := hcsshim.Subnet{ + AddressPrefix: subnet.Prefix.String(), + GatewayAddress: subnet.Gateway.String(), + } + + hnsNetwork.Subnets = append(hnsNetwork.Subnets, hnsSubnet) +} + +return createHnsNetwork(hnsNetwork) } -// createExtSwitchHnsNetwork creates ext HNS network if not present. -func createExtSwitchHnsNetwork(createExtNetworkType string) error { - networkType := strings.ToLower(strings.TrimSpace(createExtNetworkType)) +// CreateDefaultExtNetwork creates default HNS network named ext (if it doesn't exist already) +// to create external switch on windows platform. +// This allows orchestrators to start CNS which pre-provisions the network so that the +// VM network blip / disconnect is avoided when calling cni add for the very first time. +func CreateDefaultExtNetwork(networkType string) error { + networkType = strings.ToLower(strings.TrimSpace(networkType)) if len(networkType) == 0 { return nil } if networkType != hnsL2Bridge && networkType != hnsL2Tunnel { - return fmt.Errorf("Invalid hns network type %s", createExtNetworkType) + return fmt.Errorf("Invalid hns network type %s", networkType) } - log.Printf("[Azure CNS] createExtSwitchHnsNetwork") + log.Printf("[Azure CNS] CreateDefaultExtNetwork") extHnsNetwork, _ := hcsshim.GetHNSNetworkByName(ExtHnsNetworkName) if extHnsNetwork != nil { - log.Printf("[Azure CNS] Found existing external switch hns network with type: %s", extHnsNetwork.Type) + log.Printf("[Azure CNS] Found existing DefaultExtNetwork with type: %s", extHnsNetwork.Type) if !strings.EqualFold(networkType, extHnsNetwork.Type) { return fmt.Errorf("Network type mismatch with existing network: %s", extHnsNetwork.Type) } @@ -187,7 +252,7 @@ func createExtSwitchHnsNetwork(createExtNetworkType string) error { } // create new hns network - log.Printf("[Azure CNS] Creating external switch hns network with type %s", networkType) + log.Printf("[Azure CNS] Creating DefaultExtNetwork with type %s", networkType) hnsNetwork := &hcsshim.HNSNetwork{ Name: ExtHnsNetworkName, @@ -201,6 +266,11 @@ func createExtSwitchHnsNetwork(createExtNetworkType string) error { hnsNetwork.Subnets = append(hnsNetwork.Subnets, hnsSubnet) + return createHnsNetwork(hnsNetwork) +} + +// createHnsNetwork calls the hcshim to create the hns network +func createHnsNetwork(hnsNetwork *hcsshim.HNSNetwork) error { // Marshal the request. buffer, err := json.Marshal(hnsNetwork) if err != nil { @@ -214,47 +284,17 @@ func createExtSwitchHnsNetwork(createExtNetworkType string) error { log.Printf("[Azure CNS] HNSNetworkRequest POST response:%+v err:%v.", hnsResponse, err) return err -// executePowershellCommand executes powershell command -func executePowershellCommand(command string) (string, error) { - ps, err := exec.LookPath("powershell.exe") - if err != nil { - return "", fmt.Errorf("Failed to find powershell executable") - } - - cmd := exec.Command(ps, command) - var stdout bytes.Buffer - var stderr bytes.Buffer - cmd.Stdout = &stdout - cmd.Stderr = &stderr - cmd.Run() - - return strings.TrimSpace(stdout.String()), nil } -// SetSdnRemoteArpMacAddress sets the regkey for SDNRemoteArpMacAddress needed for multitenancy -func SetSdnRemoteArpMacAddress() error { - if sdnRemoteArpMacAddressSet == false { - result, err := executePowershellCommand(GetSdnRemoteArpMacAddressCommand) - if err != nil { - return err - } - // Set the reg key if not already set or has incorrect value - if result != SDNRemoteArpMacAddress { - if _, err = executePowershellCommand(SetSdnRemoteArpMacAddressCommand); err != nil { - log.Printf("Failed to set SDNRemoteArpMacAddress due to error %s", err.Error()) - return err - } - - log.Printf("[Azure CNS] SDNRemoteArpMacAddress regKey set successfully. Restarting hns service.") - if _, err := executePowershellCommand(RestartHnsServiceCommand); err != nil { - log.Printf("Failed to Restart HNS Service due to error %s", err.Error()) - return err - } - } - - sdnRemoteArpMacAddressSet = true +func DeleteNetwork(networkName string) error { + hnsNetwork, err := hcsshim.GetHNSNetworkByName(networkName) + if err == nil { + // Delete the HNS network. + log.Printf("[Azure CNS] HNSNetworkRequest DELETE id:%v", hnsNetwork.Id) + hnsResponse, err := hcsshim.HNSNetworkRequest("DELETE", hnsNetwork.Id, "") + log.Printf("[Azure CNS] HNSNetworkRequest DELETE response:%+v err:%v.", hnsResponse, err) } - return nil + return err } From 993342937b89fe37f916e1a9535cab78357f868f Mon Sep 17 00:00:00 2001 From: Ashvin Deodhar Date: Sun, 14 Apr 2019 15:40:03 -0700 Subject: [PATCH 07/10] create and delete hns network API --- cns/api.go | 22 +++----- cns/restserver/restserver.go | 8 +-- cns/service/main.go | 34 ++++++++---- common/config.go | 4 +- platform/os_linux.go | 30 +++++++++-- platform/os_windows.go | 102 ++++++++++++++++++++++------------- 6 files changed, 127 insertions(+), 73 deletions(-) diff --git a/cns/api.go b/cns/api.go index dd41cdebe7..f4fd61738c 100644 --- a/cns/api.go +++ b/cns/api.go @@ -48,24 +48,16 @@ type DeleteNetworkRequest struct { NetworkName string } -/* // CreateHnsNetworkRequest describes request to create the HNS network. type CreateHnsNetworkRequest struct { - NetworkName string - NetworkType string - Options map[string]interface{} -}*/ - -// CreateHnsNetworkRequest describes request to create the HNS network. -type CreateHnsNetworkRequest struct { - ID string `json:"ID,omitempty"` - Name string `json:",omitempty"` - Type string `json:",omitempty"` + NetworkID string `json:"ID,omitempty"` + NetworkName string `json:",omitempty"` + NetworkType string `json:",omitempty"` NetworkAdapterName string `json:",omitempty"` SourceMac string `json:",omitempty"` Policies []json.RawMessage `json:",omitempty"` MacPools []MacPool `json:",omitempty"` - Subnets []Subnet `json:",omitempty"` + Subnets []SubnetInfo `json:",omitempty"` DNSSuffix string `json:",omitempty"` DNSServerList string `json:",omitempty"` DNSServerCompartment uint32 `json:",omitempty"` @@ -73,9 +65,9 @@ type CreateHnsNetworkRequest struct { AutomaticDNS bool `json:",omitempty"` } -// Subnet is assoicated with HNS network and represents a list +// SubnetInfo is assoicated with HNS network and represents a list // of subnets available to the network -type Subnet struct { +type SubnetInfo struct { AddressPrefix string `json:",omitempty"` GatewayAddress string `json:",omitempty"` Policies []json.RawMessage `json:",omitempty"` @@ -90,7 +82,7 @@ type MacPool struct { // DeleteHnsNetworkRequest describes request to delete the HNS network. type DeleteHnsNetworkRequest struct { - NetworkName string + NetworkName string `json:"NetworkName"` } // ReserveIPAddressRequest describes request to reserve an IP Address diff --git a/cns/restserver/restserver.go b/cns/restserver/restserver.go index 445101e80e..cda0a93709 100644 --- a/cns/restserver/restserver.go +++ b/cns/restserver/restserver.go @@ -401,9 +401,9 @@ func (service *HTTPRestService) createHnsNetwork(w http.ResponseWriter, r *http. } else { switch r.Method { case "POST": - if err := platform.CreateNetwork(req); err == nil { - // Save the HnsNetwork that is created. CNS deleteHnsNetwork will only allow deleting - // these networks. + if err := platform.CreateHnsNetwork(req); err == nil { + // Save the newly created HnsNetwork name. CNS deleteHnsNetwork API + // will only allow deleting these networks. networkInfo := &networkInfo{ NetworkName: req.NetworkName, } @@ -453,7 +453,7 @@ func (service *HTTPRestService) deleteHnsNetwork(w http.ResponseWriter, r *http. case "POST": networkInfo, ok := service.state.Networks[req.NetworkName] if ok && networkInfo.NetworkName == req.NetworkName { - if err = platform.DeleteNetwork(req.NetworkName); err == nil { + if err = platform.DeleteHnsNetwork(req.NetworkName); err == nil { returnMessage = fmt.Sprintf("[Azure CNS] Successfully deleted HNS network: %s", req.NetworkName) } else { returnMessage = fmt.Sprintf("[Azure CNS] DeleteHnsNetwork failed with error %v", err.Error()) diff --git a/cns/service/main.go b/cns/service/main.go index 2d7b87371c..c72daae114 100644 --- a/cns/service/main.go +++ b/cns/service/main.go @@ -7,6 +7,7 @@ import ( "fmt" "os" "os/signal" + "strings" "syscall" "github.com/Azure/azure-container-networking/cnm/ipam" @@ -137,9 +138,9 @@ var args = acn.ArgumentList{ DefaultValue: platform.K8SNetConfigPath + string(os.PathSeparator) + defaultCNINetworkConfigFileName, }, { - Name: acn.OptCreateExtSwitchNetworkType, - Shorthand: acn.OptCreateExtSwitchNetworkTypeAlias, - Description: "Create ext switch network for windows platform with the specified type (l2bridge or l2tunnel)", + Name: acn.OptCreateDefaultExtNetworkType, + Shorthand: acn.OptCreateDefaultExtNetworkTypeAlias, + Description: "Create default external network for windows platform with the specified type (l2bridge or l2tunnel)", Type: "string", DefaultValue: "", }, @@ -176,7 +177,7 @@ func main() { ipamQueryInterval, _ := acn.GetArg(acn.OptIpamQueryInterval).(int) stopcnm = acn.GetArg(acn.OptStopAzureVnet).(bool) vers := acn.GetArg(acn.OptVersion).(bool) - createExtSwitchNetworkType := acn.GetArg(acn.OptCreateExtSwitchNetworkType).(string) + createDefaultExtNetworkType := acn.GetArg(acn.OptCreateDefaultExtNetworkType).(string) telemetryEnabled := acn.GetArg(acn.OptTelemetry).(bool) if vers { @@ -238,13 +239,16 @@ func main() { httpRestService.SetOption(acn.OptCnsURL, cnsURL) httpRestService.SetOption(acn.OptNetPluginPath, cniPath) httpRestService.SetOption(acn.OptNetPluginConfigFile, cniConfigFile) - httpRestService.SetOption(acn.OptCreateExtSwitchNetworkType, createExtSwitchNetworkType) - - //createExtSwitchNetworkType, _ := service.GetOption(acn.OptCreateExtSwitchNetworkType).(string) - // Perform platform specific initialization - if err := platform.CreateDefaultExtNetwork(createExtSwitchNetworkType); err != nil { - log.Printf("[Azure CNS] Failed to create %s network due to error: %v", createExtSwitchNetworkType, err) - return + httpRestService.SetOption(acn.OptCreateDefaultExtNetworkType, createDefaultExtNetworkType) + + // Create default ext network if commandline option is set + if len(strings.TrimSpace(createDefaultExtNetworkType)) > 0 { + if err := platform.CreateDefaultExtNetwork(createDefaultExtNetworkType); err == nil { + log.Printf("[Azure CNS] Successfully created default ext network") + } else { + log.Printf("[Azure CNS] Failed to create default ext network due to error: %v", err) + return + } } // Start CNS. @@ -324,6 +328,14 @@ func main() { log.Printf("CNS Received unhandled error %v, shutting down.", err) } + if len(strings.TrimSpace(createDefaultExtNetworkType)) > 0 { + if err := platform.DeleteDefaultExtNetwork(); err == nil { + log.Printf("[Azure CNS] Successfully deleted default ext network") + } else { + log.Printf("[Azure CNS] Failed to delete default ext network due to error: %v", err) + } + } + // Cleanup. if httpRestService != nil { httpRestService.Stop() diff --git a/common/config.go b/common/config.go index 4d4ed91573..89e86cc746 100644 --- a/common/config.go +++ b/common/config.go @@ -73,8 +73,8 @@ const ( OptTelemetryConfigDirAlias = "d" // Create ext Hns network - OptCreateExtSwitchNetworkType = "create-extswitchnetwork-type" - OptCreateExtSwitchNetworkTypeAlias = "extswitchnetworktype" + OptCreateDefaultExtNetworkType = "create-defaultextnetwork-type" + OptCreateDefaultExtNetworkTypeAlias = "defaultextnetworktype" // Disable Telemetry OptTelemetry = "telemetry" diff --git a/platform/os_linux.go b/platform/os_linux.go index 0f670a277c..3fbd9e47e0 100644 --- a/platform/os_linux.go +++ b/platform/os_linux.go @@ -10,6 +10,7 @@ import ( "os/exec" "time" + "github.com/Azure/azure-container-networking/cns" "github.com/Azure/azure-container-networking/log" ) @@ -109,11 +110,30 @@ func KillProcessByName(processName string) error { // SetSdnRemoteArpMacAddress sets the regkey for SDNRemoteArpMacAddress needed for multitenancy // This operation is specific to windows OS func SetSdnRemoteArpMacAddress() error { + return nil } -// CreateNetwork creates network (if it doesn't exist already) -// to create external switch on windows platform. This is not needed -// in linux platoform. -func CreateNetwork(networkType string) error { - return nil +// CreateDefaultExtNetwork creates the default ext network (if it doesn't exist already) +// to create external switch on windows platform. +// This is windows platform specific. +func CreateDefaultExtNetwork(networkType string) error { + return fmt.Errorf("CreateDefaultExtNetwork shouldn't be called for the platform: %s", GetOSInfo) +} + +// DeleteDefaultExtNetwork deletes the default HNS network. +// This is windows platform specific. +func DeleteDefaultExtNetwork() error { + return fmt.Errorf("DeleteDefaultExtNetwork shouldn't be called for the platform: %s", GetOSInfo) +} + +// CreateHnsNetwork creates the HNS network with the provided configuration +// This is windows platform specific. +func CreateHnsNetwork(nwConfig cns.CreateHnsNetworkRequest) error { + return fmt.Errorf("CreateHnsNetwork shouldn't be called for the platform: %s", GetOSInfo) +} + +// DeleteHnsNetwork deletes the HNS network with the provided name. +// This is windows platform specific. +func DeleteHnsNetwork(networkName string) error { + return fmt.Errorf("DeleteHnsNetwork shouldn't be called for the platform: %s", GetOSInfo) } diff --git a/platform/os_windows.go b/platform/os_windows.go index ccbc3a9820..bb44f6a1ee 100644 --- a/platform/os_windows.go +++ b/platform/os_windows.go @@ -11,6 +11,7 @@ import ( "strings" "time" + "github.com/Azure/azure-container-networking/cns" "github.com/Azure/azure-container-networking/log" "github.com/Microsoft/hcsshim" ) @@ -37,20 +38,6 @@ const ( // DNCRuntimePath is the path where DNC state files are stored. DNCRuntimePath = "" -<<<<<<< HEAD - // Name of the external hns network - ExtHnsNetworkName = "ext" - - // Address prefix for external hns network - ExtHnsNetworkAddressPrefix = "192.168.255.0/30" - - // Gateway address for external hns network - ExtHnsNetworkGwAddress = "192.168.255.1" - - // HNS network types - hnsL2Bridge = "l2bridge" - hnsL2Tunnel = "l2tunnel" -======= // SDNRemoteArpMacAddress is the registry key for the remote arp mac address. // This is set for multitenancy to get arp response from within VM // for vlan tagged arp requests @@ -66,7 +53,19 @@ const ( // Command to restart HNS service RestartHnsServiceCommand = "Restart-Service -Name hns" ->>>>>>> origin/master + + // Name of the external hns network + ExtHnsNetworkName = "ext" + + // Address prefix for external hns network + ExtHnsNetworkAddressPrefix = "192.168.255.0/30" + + // Gateway address for external hns network + ExtHnsNetworkGwAddress = "192.168.255.1" + + // HNS network types + hnsL2Bridge = "l2bridge" + hnsL2Tunnel = "l2tunnel" ) // Flag to check if sdnRemoteArpMacAddress registry key is set @@ -200,29 +199,52 @@ func SetSdnRemoteArpMacAddress() error { return nil } -// CreateNetwork creates HNS network with the provided configuration -func CreateNetwork(nwConfig cns.CreateHnsNetworkRequest) error { - log.Printf("[Azure CNS] CreateNetwork") -// Initialize HNS network. -hnsNetwork := &hcsshim.HNSNetwork{ - Name: nwInfo.networkName, - Type: nwInfo.networkType, - NetworkAdapterName: nwInfo.networkAdapterName, - DNSServerList: nwInfo.networkDnsServerList, - Policies: nwInfo.networkPolicies, -} +// CreateHnsNetwork creates the HNS network with the provided configuration +func CreateHnsNetwork(nwConfig cns.CreateHnsNetworkRequest) error { + log.Printf("[Azure CNS] CreateHnsNetwork") + // Initialize HNS network. + hnsNetwork := &hcsshim.HNSNetwork{ + Id: nwConfig.NetworkID, + Name: nwConfig.NetworkName, + Type: nwConfig.NetworkType, + NetworkAdapterName: nwConfig.NetworkAdapterName, + SourceMac: nwConfig.SourceMac, + DNSSuffix: nwConfig.DNSSuffix, + DNSServerList: nwConfig.DNSServerList, + DNSServerCompartment: nwConfig.DNSServerCompartment, + ManagementIP: nwConfig.ManagementIP, + AutomaticDNS: nwConfig.AutomaticDNS, + } -// Populate subnets. -for _, subnet := range nwInfo.Subnets { - hnsSubnet := hcsshim.Subnet{ - AddressPrefix: subnet.Prefix.String(), - GatewayAddress: subnet.Gateway.String(), + for _, policy := range nwConfig.Policies { + hnsNetwork.Policies = append(hnsNetwork.Policies, policy) } - hnsNetwork.Subnets = append(hnsNetwork.Subnets, hnsSubnet) + for _, subnet := range nwConfig.Subnets { + hnsSubnet := hcsshim.Subnet{ + AddressPrefix: subnet.AddressPrefix, + GatewayAddress: subnet.GatewayAddress, + } + + hnsNetwork.Subnets = append(hnsNetwork.Subnets, hnsSubnet) + } + + for _, macPool := range nwConfig.MacPools { + hnsMacPool := hcsshim.MacPool{ + StartMacAddress: macPool.StartMacAddress, + EndMacAddress: macPool.EndMacAddress, + } + hnsNetwork.MacPools = append(hnsNetwork.MacPools, hnsMacPool) + } + + return createHnsNetwork(hnsNetwork) } -return createHnsNetwork(hnsNetwork) +// DeleteHnsNetwork deletes the HNS network with the provided name +func DeleteHnsNetwork(networkName string) error { + log.Printf("[Azure CNS] DeleteHnsNetwork") + + return deleteHnsNetwork(networkName) } // CreateDefaultExtNetwork creates default HNS network named ext (if it doesn't exist already) @@ -269,6 +291,13 @@ func CreateDefaultExtNetwork(networkType string) error { return createHnsNetwork(hnsNetwork) } +// DeleteDefaultExtNetwork deletes the default HNS network +func DeleteDefaultExtNetwork() error { + log.Printf("[Azure CNS] DeleteDefaultExtNetwork") + + return deleteHnsNetwork(ExtHnsNetworkName) +} + // createHnsNetwork calls the hcshim to create the hns network func createHnsNetwork(hnsNetwork *hcsshim.HNSNetwork) error { // Marshal the request. @@ -286,13 +315,14 @@ func createHnsNetwork(hnsNetwork *hcsshim.HNSNetwork) error { return err } - -func DeleteNetwork(networkName string) error { +// deleteHnsNetwork calls HNS to delete the network with the provided name +func deleteHnsNetwork(networkName string) error { hnsNetwork, err := hcsshim.GetHNSNetworkByName(networkName) if err == nil { // Delete the HNS network. + var hnsResponse *hcsshim.HNSNetwork log.Printf("[Azure CNS] HNSNetworkRequest DELETE id:%v", hnsNetwork.Id) - hnsResponse, err := hcsshim.HNSNetworkRequest("DELETE", hnsNetwork.Id, "") + hnsResponse, err = hcsshim.HNSNetworkRequest("DELETE", hnsNetwork.Id, "") log.Printf("[Azure CNS] HNSNetworkRequest DELETE response:%+v err:%v.", hnsResponse, err) } From c0241bcf28ed9301860c86fdcfb612797c52cbfe Mon Sep 17 00:00:00 2001 From: Ashvin Deodhar Date: Mon, 15 Apr 2019 10:13:00 -0700 Subject: [PATCH 08/10] Address review comments --- cns/restserver/restserver.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/cns/restserver/restserver.go b/cns/restserver/restserver.go index cda0a93709..825c746ef9 100644 --- a/cns/restserver/restserver.go +++ b/cns/restserver/restserver.go @@ -407,7 +407,9 @@ func (service *HTTPRestService) createHnsNetwork(w http.ResponseWriter, r *http. networkInfo := &networkInfo{ NetworkName: req.NetworkName, } + service.lock.Lock() service.state.Networks[req.NetworkName] = networkInfo + service.lock.Unlock() returnMessage = fmt.Sprintf("[Azure CNS] Successfully created HNS network: %s", req.NetworkName) } else { returnMessage = fmt.Sprintf("[Azure CNS] CreateHnsNetwork failed with error %v", err.Error()) @@ -427,7 +429,9 @@ func (service *HTTPRestService) createHnsNetwork(w http.ResponseWriter, r *http. err = service.Listener.Encode(w, &resp) if returnCode == 0 { + service.lock.Lock() service.saveState() + service.lock.Unlock() } log.Response(service.Name, resp, resp.ReturnCode, ReturnCodeToString(resp.ReturnCode), err) @@ -451,6 +455,7 @@ func (service *HTTPRestService) deleteHnsNetwork(w http.ResponseWriter, r *http. } else { switch r.Method { case "POST": + service.lock.Lock() networkInfo, ok := service.state.Networks[req.NetworkName] if ok && networkInfo.NetworkName == req.NetworkName { if err = platform.DeleteHnsNetwork(req.NetworkName); err == nil { @@ -460,11 +465,12 @@ func (service *HTTPRestService) deleteHnsNetwork(w http.ResponseWriter, r *http. returnCode = UnexpectedError } } else { - returnMessage = fmt.Sprintf("[Azure CNS] Invalid network name: %s", req.NetworkName) + returnMessage = fmt.Sprintf("[Azure CNS] Network %s not found", req.NetworkName) returnCode = InvalidParameter } + service.lock.Unlock() default: - returnMessage = "[Azure CNS] Error. CreateHnsNetwork did not receive a POST." + returnMessage = "[Azure CNS] Error. DeleteHnsNetwork did not receive a POST." returnCode = InvalidParameter } } @@ -477,8 +483,10 @@ func (service *HTTPRestService) deleteHnsNetwork(w http.ResponseWriter, r *http. err = service.Listener.Encode(w, &resp) if returnCode == 0 { + service.lock.Lock() delete(service.state.Networks, req.NetworkName) service.saveState() + service.lock.Unlock() } log.Response(service.Name, resp, resp.ReturnCode, ReturnCodeToString(resp.ReturnCode), err) From d85f56f7f23064073dee366d9a298feb07bdef64 Mon Sep 17 00:00:00 2001 From: Ashvin Deodhar Date: Mon, 15 Apr 2019 10:21:06 -0700 Subject: [PATCH 09/10] Address review comments - id --- cns/api.go | 1 - platform/os_windows.go | 1 - 2 files changed, 2 deletions(-) diff --git a/cns/api.go b/cns/api.go index f4fd61738c..248b434892 100644 --- a/cns/api.go +++ b/cns/api.go @@ -50,7 +50,6 @@ type DeleteNetworkRequest struct { // CreateHnsNetworkRequest describes request to create the HNS network. type CreateHnsNetworkRequest struct { - NetworkID string `json:"ID,omitempty"` NetworkName string `json:",omitempty"` NetworkType string `json:",omitempty"` NetworkAdapterName string `json:",omitempty"` diff --git a/platform/os_windows.go b/platform/os_windows.go index bb44f6a1ee..79fc422911 100644 --- a/platform/os_windows.go +++ b/platform/os_windows.go @@ -204,7 +204,6 @@ func CreateHnsNetwork(nwConfig cns.CreateHnsNetworkRequest) error { log.Printf("[Azure CNS] CreateHnsNetwork") // Initialize HNS network. hnsNetwork := &hcsshim.HNSNetwork{ - Id: nwConfig.NetworkID, Name: nwConfig.NetworkName, Type: nwConfig.NetworkType, NetworkAdapterName: nwConfig.NetworkAdapterName, From b386a649b25d5e6818e36a9edefca34acd645d73 Mon Sep 17 00:00:00 2001 From: Ashvin Deodhar Date: Mon, 15 Apr 2019 12:02:40 -0700 Subject: [PATCH 10/10] address review comments --- cns/api.go | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/cns/api.go b/cns/api.go index 248b434892..09f138948e 100644 --- a/cns/api.go +++ b/cns/api.go @@ -9,9 +9,9 @@ import "encoding/json" const ( SetEnvironmentPath = "/network/environment" CreateNetworkPath = "/network/create" - CreateHnsNetworkPath = "/network/createhns" DeleteNetworkPath = "/network/delete" - DeleteHnsNetworkPath = "/network/deletehns" + CreateHnsNetworkPath = "/network/hns/create" + DeleteHnsNetworkPath = "/network/hns/delete" ReserveIPAddressPath = "/network/ip/reserve" ReleaseIPAddressPath = "/network/ip/release" GetHostLocalIPPath = "/network/ip/hostlocal" @@ -50,18 +50,18 @@ type DeleteNetworkRequest struct { // CreateHnsNetworkRequest describes request to create the HNS network. type CreateHnsNetworkRequest struct { - NetworkName string `json:",omitempty"` - NetworkType string `json:",omitempty"` + NetworkName string + NetworkType string NetworkAdapterName string `json:",omitempty"` SourceMac string `json:",omitempty"` Policies []json.RawMessage `json:",omitempty"` MacPools []MacPool `json:",omitempty"` - Subnets []SubnetInfo `json:",omitempty"` - DNSSuffix string `json:",omitempty"` - DNSServerList string `json:",omitempty"` - DNSServerCompartment uint32 `json:",omitempty"` - ManagementIP string `json:",omitempty"` - AutomaticDNS bool `json:",omitempty"` + Subnets []SubnetInfo + DNSSuffix string `json:",omitempty"` + DNSServerList string `json:",omitempty"` + DNSServerCompartment uint32 `json:",omitempty"` + ManagementIP string `json:",omitempty"` + AutomaticDNS bool `json:",omitempty"` } // SubnetInfo is assoicated with HNS network and represents a list @@ -81,7 +81,7 @@ type MacPool struct { // DeleteHnsNetworkRequest describes request to delete the HNS network. type DeleteHnsNetworkRequest struct { - NetworkName string `json:"NetworkName"` + NetworkName string } // ReserveIPAddressRequest describes request to reserve an IP Address