Skip to content

Commit b499afd

Browse files
authored
Merge pull request #356 from akutz/feature/network-device-matching-by-order
Net devices by order, remove invalid IP addrs
2 parents a8e826a + f4d82af commit b499afd

File tree

10 files changed

+141
-71
lines changed

10 files changed

+141
-71
lines changed

config/crds/vsphereproviderconfig_v1alpha1_vspheremachineproviderconfig.yaml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -391,11 +391,6 @@ spec:
391391
items:
392392
type: string
393393
type: array
394-
uuid:
395-
description: UUID is used to relate this network spec to the
396-
network device created from this spec. This value is set
397-
at runtime and should not be assigned manually.
398-
type: string
399394
required:
400395
- networkName
401396
type: object

config/crds/vsphereproviderconfig_v1alpha1_vspheremachineproviderstatus.yaml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,7 @@ spec:
4646
networkName:
4747
description: NetworkName is the name of the network.
4848
type: string
49-
uuid:
50-
description: UUID is stored as the ExternalID field on a network device
51-
and uniquely identifies the device as one that was created from
52-
a known network spec.
53-
type: string
5449
required:
55-
- uuid
5650
- macAddr
5751
type: object
5852
type: array

pkg/apis/vsphereproviderconfig/v1alpha1/vspheremachineproviderconfig_types.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -98,12 +98,6 @@ type NetworkDeviceSpec struct {
9898
// will be connected.
9999
NetworkName string `json:"networkName"`
100100

101-
// UUID is used to relate this network spec to the network device created
102-
// from this spec. This value is set at runtime and should not be assigned
103-
// manually.
104-
// +optional
105-
UUID string `json:"uuid,omitempty"`
106-
107101
// DHCP4 is a flag that indicates whether or not to use DHCP for IPv4
108102
// on this device.
109103
// If true then IPAddrs should not contain any IPv4 addresses.

pkg/apis/vsphereproviderconfig/v1alpha1/vspheremachineproviderstatus_types.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,6 @@ type NetworkStatus struct {
4545
// connected to the VM.
4646
Connected bool `json:"connected,omitempty"`
4747

48-
// UUID is stored as the ExternalID field on a network device and uniquely
49-
// identifies the device as one that was created from a known network
50-
// spec.
51-
UUID string `json:"uuid"`
52-
5348
// IPAddrs is one or more IP addresses reported by vm-tools.
5449
// +optional
5550
IPAddrs []string `json:"ipAddrs,omitempty"`

pkg/cloud/vsphere/services/govmomi/net/net.go

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package net
1818

1919
import (
2020
"context"
21+
"net"
2122
"strings"
2223

2324
"github.com/pkg/errors"
@@ -33,11 +34,6 @@ type NetworkStatus struct {
3334
// connected to the VM.
3435
Connected bool `json:"connected,omitempty"`
3536

36-
// UUID is stored as the ExternalID field on a network device and uniquely
37-
// identifies the device as one that was created from a known network
38-
// spec.
39-
UUID string `json:"uuid"`
40-
4137
// IPAddrs is one or more IP addresses reported by vm-tools.
4238
// +optional
4339
IPAddrs []string `json:"ipAddrs,omitempty"`
@@ -80,7 +76,6 @@ func GetNetworkStatus(
8076
nic := dev.GetVirtualEthernetCard()
8177
netStatus := NetworkStatus{
8278
MACAddr: nic.MacAddress,
83-
UUID: nic.ExternalId,
8479
}
8580
if obj.Guest != nil {
8681
for _, i := range obj.Guest.Net {
@@ -97,3 +92,25 @@ func GetNetworkStatus(
9792

9893
return allNetStatus, nil
9994
}
95+
96+
// ErrOnLocalOnlyIPAddr returns an error if the provided IP address is
97+
// accessible only on the VM's guest OS.
98+
func ErrOnLocalOnlyIPAddr(addr string) error {
99+
var reason string
100+
a := net.ParseIP(addr)
101+
if a == nil {
102+
reason = "invalid"
103+
} else if a.IsUnspecified() {
104+
reason = "unspecified"
105+
} else if a.IsLinkLocalMulticast() {
106+
reason = "link-local-mutlicast"
107+
} else if a.IsLinkLocalUnicast() {
108+
reason = "link-local-unicast"
109+
} else if a.IsLoopback() {
110+
reason = "loopback"
111+
}
112+
if reason != "" {
113+
return errors.Errorf("failed to validate ip addr=%v: %s", addr, reason)
114+
}
115+
return nil
116+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
Copyright 2019 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package net_test
18+
19+
import (
20+
"testing"
21+
22+
"sigs.k8s.io/cluster-api-provider-vsphere/pkg/cloud/vsphere/services/govmomi/net"
23+
)
24+
25+
func TestErrOnLocalOnlyIPAddr(t *testing.T) {
26+
testCases := []struct {
27+
name string
28+
ipAddr string
29+
expectErr bool
30+
}{
31+
{
32+
name: "valid-ipv4",
33+
ipAddr: "192.168.2.33",
34+
expectErr: false,
35+
},
36+
{
37+
name: "valid-ipv6",
38+
ipAddr: "1200:0000:AB00:1234:0000:2552:7777:1313",
39+
expectErr: false,
40+
},
41+
{
42+
name: "localhost",
43+
ipAddr: "127.0.0.1",
44+
expectErr: true,
45+
},
46+
{
47+
name: "link-local-unicast-ipv4",
48+
ipAddr: "169.254.2.3",
49+
expectErr: true,
50+
},
51+
{
52+
name: "link-local-unicast-ipv6",
53+
ipAddr: "fe80::250:56ff:feb0:345d",
54+
expectErr: true,
55+
},
56+
{
57+
name: "link-local-multicast-ipv4",
58+
ipAddr: "224.0.0.252",
59+
expectErr: true,
60+
},
61+
{
62+
name: "link-local-multicast-ipv6",
63+
ipAddr: "FF02:0:0:0:0:0:1:3",
64+
expectErr: true,
65+
},
66+
}
67+
for _, tc := range testCases {
68+
t.Run(tc.name, func(t *testing.T) {
69+
if err := net.ErrOnLocalOnlyIPAddr(tc.ipAddr); err != nil {
70+
t.Log(err)
71+
if !tc.expectErr {
72+
t.Fatal(err)
73+
}
74+
} else if tc.expectErr {
75+
t.Fatal("expected error did not occur")
76+
}
77+
})
78+
}
79+
}

pkg/cloud/vsphere/services/govmomi/update.go

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ func Update(ctx *context.MachineContext) error {
4646
return errors.Errorf("vm is supposed to exist %q", ctx)
4747
}
4848

49-
if err := reconcileNetworkStatus(ctx, vm); err != nil {
49+
if err := reconcileNetwork(ctx, vm); err != nil {
5050
return err
5151
}
5252

@@ -94,8 +94,8 @@ func reconcileMetadata(ctx *context.MachineContext, vm *object.VirtualMachine) e
9494
return &clustererror.RequeueAfterError{RequeueAfter: constants.DefaultRequeue}
9595
}
9696

97-
// reconcileNetworkStatus updates the machine's network status from the VM
98-
func reconcileNetworkStatus(ctx *context.MachineContext, vm *object.VirtualMachine) error {
97+
// reconcileNetwork updates the machine's network spec and status
98+
func reconcileNetwork(ctx *context.MachineContext, vm *object.VirtualMachine) error {
9999

100100
// Validate the number of reported networks match the number of configured
101101
// networks.
@@ -107,20 +107,16 @@ func reconcileNetworkStatus(ctx *context.MachineContext, vm *object.VirtualMachi
107107
if expNetCount != actNetCount {
108108
return errors.Errorf("invalid network count for %q: exp=%d act=%d", ctx, expNetCount, actNetCount)
109109
}
110-
111-
// Update the machine's network status.
112-
ctx.Logger.V(4).Info("updating network status")
113110
ctx.MachineStatus.Network = allNetStatus
114111

115112
// Update the MAC addresses in the machine's network config as well. This
116113
// is required in order to generate the metadata.
117-
for _, netStatus := range allNetStatus {
118-
for i := range ctx.MachineConfig.MachineSpec.Network.Devices {
119-
dev := &ctx.MachineConfig.MachineSpec.Network.Devices[i]
120-
if netStatus.UUID == dev.UUID && netStatus.MACAddr != dev.MACAddr {
121-
ctx.Logger.V(4).Info("updating MAC address for device", "device-uuid", dev.UUID, "network-name", dev.NetworkName, "old-mac-addr", dev.MACAddr, "new-mac-addr", netStatus.MACAddr)
122-
dev.MACAddr = netStatus.MACAddr
123-
}
114+
for i := range ctx.MachineConfig.MachineSpec.Network.Devices {
115+
devSpec := &ctx.MachineConfig.MachineSpec.Network.Devices[i]
116+
oldMac, newMac := devSpec.MACAddr, allNetStatus[i].MACAddr
117+
if oldMac != newMac {
118+
devSpec.MACAddr = newMac
119+
ctx.Logger.V(6).Info("updating MAC address for device", "network-name", devSpec.NetworkName, "old-mac-addr", oldMac, "new-mac-addr", newMac)
124120
}
125121
}
126122

pkg/cloud/vsphere/services/govmomi/util.go

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -95,22 +95,32 @@ func getNetworkStatus(ctx *context.MachineContext) ([]v1alpha1.NetworkStatus, er
9595
}
9696
ctx.Logger.V(6).Info("got allNetStatus", "status", allNetStatus)
9797
apiNetStatus := []v1alpha1.NetworkStatus{}
98-
for _, netDevSpec := range ctx.MachineConfig.MachineSpec.Network.Devices {
99-
for _, netStatus := range allNetStatus {
100-
if netDevSpec.UUID == netStatus.UUID {
101-
apiNetStatus = append(apiNetStatus, v1alpha1.NetworkStatus{
102-
Connected: netStatus.Connected,
103-
UUID: netStatus.UUID,
104-
IPAddrs: netStatus.IPAddrs,
105-
MACAddr: netStatus.MACAddr,
106-
NetworkName: netStatus.NetworkName,
107-
})
108-
}
109-
}
98+
for _, s := range allNetStatus {
99+
apiNetStatus = append(apiNetStatus, v1alpha1.NetworkStatus{
100+
Connected: s.Connected,
101+
IPAddrs: sanitizeIPAddrs(ctx, s.IPAddrs),
102+
MACAddr: s.MACAddr,
103+
NetworkName: s.NetworkName,
104+
})
110105
}
111106
return apiNetStatus, nil
112107
}
113108

109+
func sanitizeIPAddrs(ctx *context.MachineContext, ipAddrs []string) []string {
110+
if len(ipAddrs) == 0 {
111+
return nil
112+
}
113+
newIPAddrs := []string{}
114+
for _, addr := range ipAddrs {
115+
if err := net.ErrOnLocalOnlyIPAddr(addr); err != nil {
116+
ctx.Logger.V(8).Info("ignoring IP address", "reason", err)
117+
} else {
118+
newIPAddrs = append(newIPAddrs, addr)
119+
}
120+
}
121+
return newIPAddrs
122+
}
123+
114124
func getExistingMetadata(ctx *context.MachineContext) (string, error) {
115125
var (
116126
obj mo.VirtualMachine

pkg/cloud/vsphere/services/govmomi/vcenter/clone.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ limitations under the License.
1717
package vcenter
1818

1919
import (
20-
"github.com/google/uuid"
2120
"github.com/pkg/errors"
2221
"github.com/vmware/govmomi/object"
2322
"github.com/vmware/govmomi/vim25/types"
@@ -187,16 +186,18 @@ func getNetworkSpecs(
187186
// "types.BaseVirtualEthernetCard" as a "types.BaseVirtualDevice".
188187
nic := dev.(types.BaseVirtualEthernetCard).GetVirtualEthernetCard()
189188

189+
if netSpec.MACAddr != "" {
190+
nic.MacAddress = netSpec.MACAddr
191+
// Please see https://www.vmware.com/support/developer/converter-sdk/conv60_apireference/vim.vm.device.VirtualEthernetCard.html#addressType
192+
// for the valid values for this field.
193+
nic.AddressType = "Manual"
194+
ctx.Logger.V(6).Info("configured manual mac address", "mac-addr", nic.MacAddress)
195+
}
196+
190197
// Assign a temporary device key to ensure that a unique one will be
191198
// generated when the device is created.
192199
nic.Key = key
193200

194-
// Create the device with a unique ID that is also stored on the machine's
195-
// network device spec. This allows deterministic lookup of MAC/Device
196-
// later in the workflow, once the VM is created.
197-
netSpec.UUID = uuid.New().String()
198-
nic.ExternalId = netSpec.UUID
199-
200201
deviceSpecs = append(deviceSpecs, &types.VirtualDeviceConfigSpec{
201202
Device: dev,
202203
Operation: types.VirtualDeviceConfigSpecOperationAdd,

scripts/e2e/bootstrap_job/spec/provider-components.template

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -841,11 +841,6 @@ spec:
841841
items:
842842
type: string
843843
type: array
844-
uuid:
845-
description: UUID is used to relate this network spec to the
846-
network device created from this spec. This value is set
847-
at runtime and should not be assigned manually.
848-
type: string
849844
required:
850845
- networkName
851846
type: object
@@ -960,13 +955,7 @@ spec:
960955
networkName:
961956
description: NetworkName is the name of the network.
962957
type: string
963-
uuid:
964-
description: UUID is stored as DeviceInfo.Label on a network device
965-
and uniquely identifies the device as one that was created from
966-
a known network spec.
967-
type: string
968958
required:
969-
- uuid
970959
- macAddr
971960
type: object
972961
type: array

0 commit comments

Comments
 (0)