Skip to content

Commit 0f5a2ca

Browse files
authored
Merge pull request #9641 from prezha/fix-kvm-minikube-net
Fix minikube-net network failures for KVM driver
2 parents 689b3db + 9e11413 commit 0f5a2ca

File tree

2 files changed

+104
-22
lines changed

2 files changed

+104
-22
lines changed

pkg/drivers/kvm/kvm.go

+13-8
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ func (d *Driver) PreCommandCheck() error {
110110
if err != nil {
111111
return errors.Wrap(err, "error connecting to libvirt socket. Have you added yourself to the libvirtd group?")
112112
}
113+
defer conn.Close()
114+
113115
libVersion, err := conn.GetLibVersion()
114116
if err != nil {
115117
return errors.Wrap(err, "getting libvirt version")
@@ -240,14 +242,6 @@ func (d *Driver) Restart() error {
240242

241243
// Start a host
242244
func (d *Driver) Start() (err error) {
243-
// if somebody/something deleted the network in the meantime,
244-
// we might need to recreate it. It's (nearly) a noop if the network exists.
245-
log.Info("Creating network...")
246-
err = d.createNetwork()
247-
if err != nil {
248-
return errors.Wrap(err, "creating network")
249-
}
250-
251245
// this call ensures that all networks are active
252246
log.Info("Ensuring networks are active...")
253247
err = d.ensureNetwork()
@@ -490,3 +484,14 @@ func (d *Driver) undefineDomain(conn *libvirt.Connect, dom *libvirt.Domain) erro
490484

491485
return dom.Undefine()
492486
}
487+
488+
// lvErr will return libvirt Error struct containing specific libvirt error code, domain, message and level
489+
func lvErr(err error) libvirt.Error {
490+
if err != nil {
491+
if lverr, ok := err.(libvirt.Error); ok {
492+
return lverr
493+
}
494+
return libvirt.Error{Code: libvirt.ERR_INTERNAL_ERROR, Message: "internal error"}
495+
}
496+
return libvirt.Error{Code: libvirt.ERR_OK, Message: ""}
497+
}

pkg/drivers/kvm/network.go

+91-14
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,12 @@ import (
2626
"io/ioutil"
2727
"strings"
2828
"text/template"
29+
"time"
2930

3031
"github.com/docker/machine/libmachine/log"
3132
libvirt "github.com/libvirt/libvirt-go"
3233
"github.com/pkg/errors"
34+
"k8s.io/minikube/pkg/util/retry"
3335
)
3436

3537
// Replace with hardcoded range with CIDR
@@ -53,6 +55,7 @@ func setupNetwork(conn *libvirt.Connect, name string) error {
5355
if err != nil {
5456
return errors.Wrapf(err, "checking network %s", name)
5557
}
58+
defer func() { _ = n.Free() }()
5659

5760
// always ensure autostart is set on the network
5861
autostart, err := n.GetAutostart()
@@ -75,7 +78,6 @@ func setupNetwork(conn *libvirt.Connect, name string) error {
7578
return errors.Wrapf(err, "starting network %s", name)
7679
}
7780
}
78-
7981
return nil
8082
}
8183

@@ -99,8 +101,21 @@ func (d *Driver) ensureNetwork() error {
99101

100102
// Start the private network
101103
log.Infof("Ensuring network %s is active", d.PrivateNetwork)
104+
// retry once to recreate the network, but only if is not used by another minikube instance
102105
if err := setupNetwork(conn, d.PrivateNetwork); err != nil {
103-
return err
106+
log.Debugf("Network %s is inoperable, will try to recreate it: %v", d.PrivateNetwork, err)
107+
if err := d.deleteNetwork(); err != nil {
108+
return errors.Wrapf(err, "deleting inoperable network %s", d.PrivateNetwork)
109+
}
110+
log.Debugf("Successfully deleted %s network", d.PrivateNetwork)
111+
if err := d.createNetwork(); err != nil {
112+
return errors.Wrapf(err, "recreating inoperable network %s", d.PrivateNetwork)
113+
}
114+
log.Debugf("Successfully recreated %s network", d.PrivateNetwork)
115+
if err := setupNetwork(conn, d.PrivateNetwork); err != nil {
116+
return err
117+
}
118+
log.Debugf("Successfully activated %s network", d.PrivateNetwork)
104119
}
105120

106121
return nil
@@ -120,13 +135,16 @@ func (d *Driver) createNetwork() error {
120135

121136
// network: default
122137
// It is assumed that the libvirt/kvm installation has already created this network
123-
if _, err := conn.LookupNetworkByName(d.Network); err != nil {
138+
netd, err := conn.LookupNetworkByName(d.Network)
139+
if err != nil {
124140
return errors.Wrapf(err, "network %s doesn't exist", d.Network)
125141
}
142+
defer func() { _ = netd.Free() }()
126143

127144
// network: private
128145
// Only create the private network if it does not already exist
129-
if _, err := conn.LookupNetworkByName(d.PrivateNetwork); err != nil {
146+
netp, err := conn.LookupNetworkByName(d.PrivateNetwork)
147+
if err != nil {
130148
// create the XML for the private network from our networkTmpl
131149
tmpl := template.Must(template.New("network").Parse(networkTmpl))
132150
var networkXML bytes.Buffer
@@ -141,10 +159,26 @@ func (d *Driver) createNetwork() error {
141159
}
142160

143161
// and finally create it
144-
if err := network.Create(); err != nil {
162+
log.Debugf("Trying to create network %s...", d.PrivateNetwork)
163+
create := func() error {
164+
if err := network.Create(); err != nil {
165+
return err
166+
}
167+
active, err := network.IsActive()
168+
if err == nil && active {
169+
return nil
170+
}
171+
return errors.Errorf("retrying %v", err)
172+
}
173+
if err := retry.Local(create, 10*time.Second); err != nil {
145174
return errors.Wrapf(err, "creating network %s", d.PrivateNetwork)
146175
}
147176
}
177+
defer func() {
178+
if netp != nil {
179+
_ = netp.Free()
180+
}
181+
}()
148182

149183
return nil
150184
}
@@ -163,13 +197,13 @@ func (d *Driver) deleteNetwork() error {
163197
log.Debugf("Checking if network %s exists...", d.PrivateNetwork)
164198
network, err := conn.LookupNetworkByName(d.PrivateNetwork)
165199
if err != nil {
166-
if libvirtErr, ok := err.(libvirt.Error); ok && libvirtErr.Code == libvirt.ERR_NO_NETWORK {
200+
if lvErr(err).Code == libvirt.ERR_NO_NETWORK {
167201
log.Warnf("Network %s does not exist. Skipping deletion", d.PrivateNetwork)
168202
return nil
169203
}
170-
171204
return errors.Wrapf(err, "failed looking for network %s", d.PrivateNetwork)
172205
}
206+
defer func() { _ = network.Free() }()
173207
log.Debugf("Network %s exists", d.PrivateNetwork)
174208

175209
err = d.checkDomains(conn)
@@ -178,15 +212,58 @@ func (d *Driver) deleteNetwork() error {
178212
}
179213

180214
// when we reach this point, it means it is safe to delete the network
215+
216+
// cannot destroy an inactive network - try to activate it first
217+
log.Debugf("Trying to reactivate network %s first (if needed)...", d.PrivateNetwork)
218+
activate := func() error {
219+
active, err := network.IsActive()
220+
if err == nil && active {
221+
return nil
222+
}
223+
if err != nil {
224+
return err
225+
}
226+
// inactive, try to activate
227+
if err := network.Create(); err != nil {
228+
return err
229+
}
230+
return errors.Errorf("needs confirmation") // confirm in the next cycle
231+
}
232+
if err := retry.Local(activate, 10*time.Second); err != nil {
233+
log.Debugf("Reactivating network %s failed, will continue anyway...", d.PrivateNetwork)
234+
}
235+
181236
log.Debugf("Trying to destroy network %s...", d.PrivateNetwork)
182-
err = network.Destroy()
183-
if err != nil {
184-
return errors.Wrap(err, "network destroy")
237+
destroy := func() error {
238+
if err := network.Destroy(); err != nil {
239+
return err
240+
}
241+
active, err := network.IsActive()
242+
if err == nil && !active {
243+
return nil
244+
}
245+
return errors.Errorf("retrying %v", err)
185246
}
247+
if err := retry.Local(destroy, 10*time.Second); err != nil {
248+
return errors.Wrap(err, "destroying network")
249+
}
250+
186251
log.Debugf("Trying to undefine network %s...", d.PrivateNetwork)
187-
err = network.Undefine()
188-
if err != nil {
189-
return errors.Wrap(err, "network undefine")
252+
undefine := func() error {
253+
if err := network.Undefine(); err != nil {
254+
return err
255+
}
256+
netp, err := conn.LookupNetworkByName(d.PrivateNetwork)
257+
if netp != nil {
258+
_ = netp.Free()
259+
}
260+
if lvErr(err).Code == libvirt.ERR_NO_NETWORK {
261+
return nil
262+
}
263+
return errors.Errorf("retrying %v", err)
264+
}
265+
if err := retry.Local(undefine, 10*time.Second); err != nil {
266+
return errors.Wrap(err, "undefining network")
190267
}
191268

192269
return nil
@@ -272,7 +349,6 @@ func (d *Driver) lookupIP() (string, error) {
272349
if err != nil {
273350
return "", errors.Wrap(err, "getting connection and domain")
274351
}
275-
276352
defer conn.Close()
277353

278354
libVersion, err := conn.GetLibVersion()
@@ -294,6 +370,7 @@ func (d *Driver) lookupIPFromStatusFile(conn *libvirt.Connect) (string, error) {
294370
if err != nil {
295371
return "", errors.Wrap(err, "looking up network by name")
296372
}
373+
defer func() { _ = network.Free() }()
297374

298375
bridge, err := network.GetBridgeName()
299376
if err != nil {

0 commit comments

Comments
 (0)