|
7 | 7 | "github.com/kubeovn/gonetworkmanager/v2"
|
8 | 8 | "github.com/scylladb/go-set/strset"
|
9 | 9 | "github.com/vishvananda/netlink"
|
| 10 | + "golang.org/x/mod/semver" |
10 | 11 | "k8s.io/client-go/util/workqueue"
|
11 | 12 | "k8s.io/klog/v2"
|
12 | 13 | )
|
@@ -190,59 +191,79 @@ func (n *networkManagerSyncer) SetManaged(name string, managed bool) error {
|
190 | 191 | }
|
191 | 192 |
|
192 | 193 | if !managed {
|
193 |
| - devices, err := n.manager.GetAllDevices() |
| 194 | + links, err := netlink.LinkList() |
194 | 195 | if err != nil {
|
195 |
| - klog.Errorf("failed to get all devices from NetworkManager: %v", err) |
| 196 | + klog.Errorf("failed to list network links: %v", err) |
196 | 197 | return err
|
197 | 198 | }
|
198 | 199 |
|
199 |
| - var hasVlan bool |
200 |
| - for _, dev := range devices { |
201 |
| - managed, err := device.GetPropertyManaged() |
202 |
| - if err != nil { |
203 |
| - klog.Errorf("failed to get property managed of device %s: %v", dev.GetPath(), err) |
204 |
| - continue |
205 |
| - } |
206 |
| - if !managed { |
207 |
| - continue |
208 |
| - } |
209 |
| - |
210 |
| - devType, err := dev.GetPropertyDeviceType() |
211 |
| - if err != nil { |
212 |
| - klog.Errorf("failed to get type of device %s: %v", dev.GetPath(), err) |
213 |
| - continue |
214 |
| - } |
215 |
| - if devType != gonetworkmanager.NmDeviceTypeVlan { |
| 200 | + for _, l := range links { |
| 201 | + if l.Attrs().ParentIndex != link.Attrs().Index || l.Type() != "vlan" { |
216 | 202 | continue
|
217 | 203 | }
|
218 | 204 |
|
219 |
| - vlanName, err := dev.GetPropertyIpInterface() |
| 205 | + d, err := n.manager.GetDeviceByIpIface(l.Attrs().Name) |
220 | 206 | if err != nil {
|
221 |
| - klog.Errorf("failed to get IP interface of device %s: %v", dev.GetPath(), err) |
222 |
| - continue |
| 207 | + klog.Errorf("failed to get device by IP iface %q: %v", l.Attrs().Name, err) |
| 208 | + return err |
223 | 209 | }
|
224 |
| - |
225 |
| - vlanLink, err := netlink.LinkByName(vlanName) |
| 210 | + vlanManaged, err := d.GetPropertyManaged() |
226 | 211 | if err != nil {
|
227 |
| - klog.Errorf("failed to get link %s: %v", vlanName, err) |
| 212 | + klog.Errorf("failed to get property managed of device %s: %v", l.Attrs().Name, err) |
228 | 213 | continue
|
229 | 214 | }
|
230 |
| - if vlanLink.Type() != "vlan" { |
231 |
| - klog.Errorf("unexpected link type: %s", vlanLink.Type()) |
232 |
| - continue |
| 215 | + if vlanManaged { |
| 216 | + // After setting device managed=no, the vlan interface will be set down by NetworkManager. |
| 217 | + klog.Infof(`device %q has a vlan interface %q mannaged by NetworkManager, will not set the NetworkManager property "managed" to %v`, name, l.Attrs().Name, managed) |
| 218 | + return nil |
233 | 219 | }
|
| 220 | + } |
234 | 221 |
|
235 |
| - if vlanLink.Attrs().ParentIndex == link.Attrs().Index { |
236 |
| - klog.Infof("device %s has a vlan interface %s managed by NetworkManager", name, vlanName) |
237 |
| - hasVlan = true |
238 |
| - break |
239 |
| - } |
| 222 | + version, err := n.manager.GetPropertyVersion() |
| 223 | + if err != nil { |
| 224 | + klog.Errorf("failed to get NetworkManager version: %v", err) |
| 225 | + return err |
| 226 | + } |
| 227 | + |
| 228 | + if !strings.HasPrefix(version, "v") { |
| 229 | + version = "v" + version |
240 | 230 | }
|
241 | 231 |
|
242 |
| - if hasVlan { |
243 |
| - klog.Infof(`will not set device %s NetworkManager property "managed" to %v`, name, managed) |
| 232 | + // Retrieving DNS configuration requires NetworkManager >= v1.6.0. |
| 233 | + // Do not set device managed=no if the version is < v1.6.0. |
| 234 | + if semver.Compare(version, "v1.6.0") < 0 { |
| 235 | + klog.Infof("NetworkManager version %s is less than v1.6.0") |
244 | 236 | return nil
|
245 | 237 | }
|
| 238 | + |
| 239 | + // requires NetworkManager >= v1.6 |
| 240 | + dnsManager, err := gonetworkmanager.NewDnsManager() |
| 241 | + if err != nil { |
| 242 | + klog.Errorf("failed to initialize NetworkManager DNS manager: %v", err) |
| 243 | + return err |
| 244 | + } |
| 245 | + |
| 246 | + configurations, err := dnsManager.GetPropertyConfiguration() |
| 247 | + if err != nil { |
| 248 | + klog.Errorf("failed to get NetworkManager DNS configuration: %v", err) |
| 249 | + return err |
| 250 | + } |
| 251 | + |
| 252 | + for _, c := range configurations { |
| 253 | + if c.Interface == name { |
| 254 | + if len(c.Nameservers) != 0 { |
| 255 | + // After setting device managed=no on CentOS 7 with NetworkManager v1.18.x, |
| 256 | + // the DNS servers in /etc/resolv.conf configured on the device will be removed. |
| 257 | + // We don't want to change the host DNS configuration, so skip this operation. |
| 258 | + klog.Infof("DNS servers %s are configured on interface %s", strings.Join(c.Nameservers, ","), name) |
| 259 | + if semver.MajorMinor(version) == "v1.18" { |
| 260 | + klog.Infof("NetworkManager's version is v1.18.x") |
| 261 | + return nil |
| 262 | + } |
| 263 | + } |
| 264 | + break |
| 265 | + } |
| 266 | + } |
246 | 267 | }
|
247 | 268 |
|
248 | 269 | klog.Infof(`setting device %s NetworkManager property "managed" to %v`, name, managed)
|
|
0 commit comments