@@ -18,6 +18,9 @@ import (
1818 "github.com/Azure/azure-container-networking/platform/windows/adapter/mellanox"
1919 "github.com/pkg/errors"
2020 "golang.org/x/sys/windows"
21+ "golang.org/x/sys/windows/registry"
22+ "golang.org/x/sys/windows/svc"
23+ "golang.org/x/sys/windows/svc/mgr"
2124)
2225
2326const (
@@ -59,17 +62,6 @@ const (
5962 // for vlan tagged arp requests
6063 SDNRemoteArpMacAddress = "12-34-56-78-9a-bc"
6164
62- // Command to get SDNRemoteArpMacAddress registry key
63- GetSdnRemoteArpMacAddressCommand = "(Get-ItemProperty " +
64- "-Path HKLM:\\ SYSTEM\\ CurrentControlSet\\ Services\\ hns\\ State -Name SDNRemoteArpMacAddress).SDNRemoteArpMacAddress"
65-
66- // Command to set SDNRemoteArpMacAddress registry key
67- SetSdnRemoteArpMacAddressCommand = "Set-ItemProperty " +
68- "-Path HKLM:\\ SYSTEM\\ CurrentControlSet\\ Services\\ hns\\ State -Name SDNRemoteArpMacAddress -Value \" 12-34-56-78-9a-bc\" "
69-
70- // Command to restart HNS service
71- RestartHnsServiceCommand = "Restart-Service -Name hns"
72-
7365 // Interval between successive checks for mellanox adapter's PriorityVLANTag value
7466 defaultMellanoxMonitorInterval = 30 * time .Second
7567
@@ -172,31 +164,74 @@ func ExecutePowershellCommand(command string) (string, error) {
172164 return strings .TrimSpace (stdout .String ()), nil
173165}
174166
175- // SetSdnRemoteArpMacAddress sets the regkey for SDNRemoteArpMacAddress needed for multitenancy
176- func SetSdnRemoteArpMacAddress () error {
177- if sdnRemoteArpMacAddressSet == false {
178- result , err := ExecutePowershellCommand (GetSdnRemoteArpMacAddressCommand )
179- if err != nil {
180- return err
167+ // SetSdnRemoteArpMacAddress sets the regkey for SDNRemoteArpMacAddress needed for multitenancy if hns is enabled
168+ func SetSdnRemoteArpMacAddress (ctx context.Context ) error {
169+ log .Printf ("Setting SDNRemoteArpMacAddress regKey" )
170+ // open the registry key
171+ k , err := registry .OpenKey (registry .LOCAL_MACHINE , `SYSTEM\CurrentControlSet\Services\hns\State` , registry .READ | registry .SET_VALUE )
172+ if err != nil {
173+ if errors .Is (err , registry .ErrNotExist ) {
174+ return nil
181175 }
176+ return errors .Wrap (err , "could not open registry key" )
177+ }
178+ defer k .Close ()
179+ // check the key value
180+ if v , _ , _ := k .GetStringValue ("SDNRemoteArpMacAddress" ); v == SDNRemoteArpMacAddress {
181+ log .Printf ("SDNRemoteArpMacAddress regKey already set" )
182+ return nil // already set
183+ }
184+ if err = k .SetStringValue ("SDNRemoteArpMacAddress" , SDNRemoteArpMacAddress ); err != nil {
185+ return errors .Wrap (err , "could not set registry key" )
186+ }
187+ log .Printf ("SDNRemoteArpMacAddress regKey set successfully" )
188+ log .Printf ("Restarting HNS service" )
189+ // connect to the service manager
190+ m , err := mgr .Connect ()
191+ if err != nil {
192+ return errors .Wrap (err , "could not connect to service manager" )
193+ }
194+ defer m .Disconnect () //nolint:errcheck // ignore error
195+ // open the HNS service
196+ service , err := m .OpenService ("hns" )
197+ if err != nil {
198+ return errors .Wrap (err , "could not access service" )
199+ }
200+ defer service .Close ()
201+ if err := restartService (ctx , service ); err != nil {
202+ return errors .Wrap (err , "could not restart service" )
203+ }
204+ log .Printf ("HNS service restarted successfully" )
205+ return nil
206+ }
182207
183- // Set the reg key if not already set or has incorrect value
184- if result != SDNRemoteArpMacAddress {
185- if _ , err = ExecutePowershellCommand (SetSdnRemoteArpMacAddressCommand ); err != nil {
186- log .Printf ("Failed to set SDNRemoteArpMacAddress due to error %s" , err .Error ())
187- return err
188- }
189-
190- log .Printf ("[Azure CNS] SDNRemoteArpMacAddress regKey set successfully. Restarting hns service." )
191- if _ , err := ExecutePowershellCommand (RestartHnsServiceCommand ); err != nil {
192- log .Printf ("Failed to Restart HNS Service due to error %s" , err .Error ())
193- return err
194- }
208+ func restartService (ctx context.Context , s * mgr.Service ) error {
209+ // Stop the service
210+ _ , err := s .Control (svc .Stop )
211+ if err != nil {
212+ return errors .Wrap (err , "could not stop service" )
213+ }
214+ // Wait for the service to stop
215+ ticker := time .NewTicker (500 * time .Millisecond ) //nolint:gomnd // 500ms
216+ defer ticker .Stop ()
217+ for { // hacky cancellable do-while
218+ status , err := s .Query ()
219+ if err != nil {
220+ return errors .Wrap (err , "could not query service status" )
221+ }
222+ if status .State == svc .Stopped {
223+ break
224+ }
225+ select {
226+ case <- ctx .Done ():
227+ return errors .New ("context cancelled" )
228+ case <- ticker .C :
195229 }
196-
197- sdnRemoteArpMacAddressSet = true
198230 }
199-
231+ // Start the service again
232+ if err := s .Start (); err != nil {
233+ return errors .Wrap (err , "could not start service" )
234+ }
200235 return nil
201236}
202237
0 commit comments