@@ -20,6 +20,9 @@ import (
2020 "github.com/pkg/errors"
2121 "go.uber.org/zap"
2222 "golang.org/x/sys/windows"
23+ "golang.org/x/sys/windows/registry"
24+ "golang.org/x/sys/windows/svc"
25+ "golang.org/x/sys/windows/svc/mgr"
2326)
2427
2528const (
@@ -61,24 +64,12 @@ const (
6164 // for vlan tagged arp requests
6265 SDNRemoteArpMacAddress = "12-34-56-78-9a-bc"
6366
64- // Command to get SDNRemoteArpMacAddress registry key
65- GetSdnRemoteArpMacAddressCommand = "(Get-ItemProperty " +
66- "-Path HKLM:\\ SYSTEM\\ CurrentControlSet\\ Services\\ hns\\ State -Name SDNRemoteArpMacAddress).SDNRemoteArpMacAddress"
67-
68- // Command to set SDNRemoteArpMacAddress registry key
69- SetSdnRemoteArpMacAddressCommand = "Set-ItemProperty " +
70- "-Path HKLM:\\ SYSTEM\\ CurrentControlSet\\ Services\\ hns\\ State -Name SDNRemoteArpMacAddress -Value \" 12-34-56-78-9a-bc\" "
71-
72- // Command to check if system has hns state path or not
73- CheckIfHNSStatePathExistsCommand = "Test-Path " +
74- "-Path HKLM:\\ SYSTEM\\ CurrentControlSet\\ Services\\ hns\\ State"
75-
7667 // Command to fetch netadapter and pnp id
68+ // TODO can we replace this (and things in endpoint_windows) with "golang.org/x/sys/windows"
69+ // var adapterInfo windows.IpAdapterInfo
70+ // var bufferSize uint32 = uint32(unsafe.Sizeof(adapterInfo))
7771 GetMacAddressVFPPnpIDMapping = "Get-NetAdapter | Select-Object MacAddress, PnpDeviceID| Format-Table -HideTableHeaders"
7872
79- // Command to restart HNS service
80- RestartHnsServiceCommand = "Restart-Service -Name hns"
81-
8273 // Interval between successive checks for mellanox adapter's PriorityVLANTag value
8374 defaultMellanoxMonitorInterval = 30 * time .Second
8475
@@ -257,43 +248,70 @@ func (p *execClient) ExecutePowershellCommandWithContext(ctx context.Context, co
257248}
258249
259250// SetSdnRemoteArpMacAddress sets the regkey for SDNRemoteArpMacAddress needed for multitenancy if hns is enabled
260- func SetSdnRemoteArpMacAddress (execClient ExecClient ) error {
261- exists , err := execClient .ExecutePowershellCommand (CheckIfHNSStatePathExistsCommand )
251+ func SetSdnRemoteArpMacAddress () error {
252+ // open the registry key
253+ k , err := registry .OpenKey (registry .LOCAL_MACHINE , "SYSTEM\\ CurrentControlSet\\ Services\\ hns\\ State" , registry .READ | registry .SET_VALUE )
254+ if err != nil && ! errors .Is (err , registry .ErrNotExist ) {
255+ return errors .Wrap (err , "could not open registry key" )
256+ }
257+ defer k .Close ()
258+ // set the key value
259+ if err = setSDNRemoteARPMACAddress (k ); err != nil {
260+ return errors .Wrap (err , "could not set registry key" )
261+ }
262+ // connect to the service manager
263+ m , err := mgr .Connect ()
262264 if err != nil {
263- errMsg := fmt .Sprintf ("Failed to check the existent of hns state path due to error %s" , err .Error ())
264- log .Printf (errMsg )
265- return errors .Errorf (errMsg )
265+ return errors .Wrap (err , "could not connect to service manager" )
266266 }
267- if strings .EqualFold (exists , "false" ) {
268- log .Printf ("hns state path does not exist, skip setting SdnRemoteArpMacAddress" )
269- return nil
267+ defer m .Disconnect () //nolint:errcheck // ignore error
268+ // open the HNS service
269+ service , err := m .OpenService ("hns" )
270+ if err != nil {
271+ return errors .Wrap (err , "could not access service" )
270272 }
271- if sdnRemoteArpMacAddressSet == false {
272- result , err := execClient .ExecutePowershellCommand (GetSdnRemoteArpMacAddressCommand )
273- if err != nil {
274- return err
275- }
276-
277- // Set the reg key if not already set or has incorrect value
278- if result != SDNRemoteArpMacAddress {
279- if _ , err = execClient .ExecutePowershellCommand (SetSdnRemoteArpMacAddressCommand ); err != nil {
280- log .Printf ("Failed to set SDNRemoteArpMacAddress due to error %s" , err .Error ())
281- return err
282- }
273+ defer service .Close ()
274+ return errors .Wrap (restartService (service ), "could not restart service" )
275+ }
283276
284- log .Printf ("[Azure CNS] SDNRemoteArpMacAddress regKey set successfully. Restarting hns service." )
285- if _ , err := execClient .ExecutePowershellCommand (RestartHnsServiceCommand ); err != nil {
286- log .Printf ("Failed to Restart HNS Service due to error %s" , err .Error ())
287- return err
288- }
289- }
277+ type key interface {
278+ SetStringValue (name , value string ) error
279+ }
290280
291- sdnRemoteArpMacAddressSet = true
281+ func setSDNRemoteARPMACAddress (k key ) error {
282+ // Set the reg key
283+ // was "Set-ItemProperty -Path HKLM:\\SYSTEM\\CurrentControlSet\\Services\\hns\\State -Name SDNRemoteArpMacAddress -Value \"12-34-56-78-9a-bc\""
284+ if err := k .SetStringValue ("SDNRemoteArpMacAddress" , SDNRemoteArpMacAddress ); err != nil {
285+ return errors .Wrap (err , "could not set registry key" )
292286 }
293-
287+ log . Printf ( "[Azure CNS] SDNRemoteArpMacAddress regKey set successfully. Restarting hns service." )
294288 return nil
295289}
296290
291+ type serv interface {
292+ Control (code svc.Cmd ) (svc.Status , error )
293+ Query () (svc.Status , error )
294+ Start (... string ) error
295+ }
296+
297+ // straight out of chat gpt
298+ func restartService (s serv ) error {
299+ // Stop the service
300+ _ , err := s .Control (svc .Stop )
301+ if err != nil {
302+ return errors .Wrap (err , "could not stop service" )
303+ }
304+ // Wait for the service to stop
305+ for status , err := s .Query (); status .State != svc .Stopped ; status , err = s .Query () {
306+ if err != nil {
307+ return errors .Wrap (err , "could not query service status" )
308+ }
309+ time .Sleep (500 * time .Millisecond ) //nolint:gomnd // 500ms
310+ }
311+ // Start the service again
312+ return errors .Wrap (s .Start (), "could not start service" )
313+ }
314+
297315func HasMellanoxAdapter () bool {
298316 m := & mellanox.Mellanox {}
299317 return hasNetworkAdapter (m )
@@ -364,6 +382,7 @@ func GetProcessNameByID(pidstr string) (string, error) {
364382 pidstr = strings .Trim (pidstr , "\r \n " )
365383 cmd := fmt .Sprintf ("Get-Process -Id %s|Format-List" , pidstr )
366384 p := NewExecClient (nil )
385+ // TODO not riemovign this because it seems to only be called in test?
367386 out , err := p .ExecutePowershellCommand (cmd )
368387 if err != nil {
369388 log .Printf ("Process is not running. Output:%v, Error %v" , out , err )
0 commit comments