未验证 提交 0f5a2ca4 编写于 作者: M Medya Ghazizadeh 提交者: GitHub

Merge pull request #9641 from prezha/fix-kvm-minikube-net

Fix minikube-net network failures for KVM driver
...@@ -110,6 +110,8 @@ func (d *Driver) PreCommandCheck() error { ...@@ -110,6 +110,8 @@ func (d *Driver) PreCommandCheck() error {
if err != nil { if err != nil {
return errors.Wrap(err, "error connecting to libvirt socket. Have you added yourself to the libvirtd group?") return errors.Wrap(err, "error connecting to libvirt socket. Have you added yourself to the libvirtd group?")
} }
defer conn.Close()
libVersion, err := conn.GetLibVersion() libVersion, err := conn.GetLibVersion()
if err != nil { if err != nil {
return errors.Wrap(err, "getting libvirt version") return errors.Wrap(err, "getting libvirt version")
...@@ -240,14 +242,6 @@ func (d *Driver) Restart() error { ...@@ -240,14 +242,6 @@ func (d *Driver) Restart() error {
// Start a host // Start a host
func (d *Driver) Start() (err error) { func (d *Driver) Start() (err error) {
// if somebody/something deleted the network in the meantime,
// we might need to recreate it. It's (nearly) a noop if the network exists.
log.Info("Creating network...")
err = d.createNetwork()
if err != nil {
return errors.Wrap(err, "creating network")
}
// this call ensures that all networks are active // this call ensures that all networks are active
log.Info("Ensuring networks are active...") log.Info("Ensuring networks are active...")
err = d.ensureNetwork() err = d.ensureNetwork()
...@@ -490,3 +484,14 @@ func (d *Driver) undefineDomain(conn *libvirt.Connect, dom *libvirt.Domain) erro ...@@ -490,3 +484,14 @@ func (d *Driver) undefineDomain(conn *libvirt.Connect, dom *libvirt.Domain) erro
return dom.Undefine() return dom.Undefine()
} }
// lvErr will return libvirt Error struct containing specific libvirt error code, domain, message and level
func lvErr(err error) libvirt.Error {
if err != nil {
if lverr, ok := err.(libvirt.Error); ok {
return lverr
}
return libvirt.Error{Code: libvirt.ERR_INTERNAL_ERROR, Message: "internal error"}
}
return libvirt.Error{Code: libvirt.ERR_OK, Message: ""}
}
...@@ -26,10 +26,12 @@ import ( ...@@ -26,10 +26,12 @@ import (
"io/ioutil" "io/ioutil"
"strings" "strings"
"text/template" "text/template"
"time"
"github.com/docker/machine/libmachine/log" "github.com/docker/machine/libmachine/log"
libvirt "github.com/libvirt/libvirt-go" libvirt "github.com/libvirt/libvirt-go"
"github.com/pkg/errors" "github.com/pkg/errors"
"k8s.io/minikube/pkg/util/retry"
) )
// Replace with hardcoded range with CIDR // Replace with hardcoded range with CIDR
...@@ -53,6 +55,7 @@ func setupNetwork(conn *libvirt.Connect, name string) error { ...@@ -53,6 +55,7 @@ func setupNetwork(conn *libvirt.Connect, name string) error {
if err != nil { if err != nil {
return errors.Wrapf(err, "checking network %s", name) return errors.Wrapf(err, "checking network %s", name)
} }
defer func() { _ = n.Free() }()
// always ensure autostart is set on the network // always ensure autostart is set on the network
autostart, err := n.GetAutostart() autostart, err := n.GetAutostart()
...@@ -75,7 +78,6 @@ func setupNetwork(conn *libvirt.Connect, name string) error { ...@@ -75,7 +78,6 @@ func setupNetwork(conn *libvirt.Connect, name string) error {
return errors.Wrapf(err, "starting network %s", name) return errors.Wrapf(err, "starting network %s", name)
} }
} }
return nil return nil
} }
...@@ -99,8 +101,21 @@ func (d *Driver) ensureNetwork() error { ...@@ -99,8 +101,21 @@ func (d *Driver) ensureNetwork() error {
// Start the private network // Start the private network
log.Infof("Ensuring network %s is active", d.PrivateNetwork) log.Infof("Ensuring network %s is active", d.PrivateNetwork)
// retry once to recreate the network, but only if is not used by another minikube instance
if err := setupNetwork(conn, d.PrivateNetwork); err != nil { if err := setupNetwork(conn, d.PrivateNetwork); err != nil {
return err log.Debugf("Network %s is inoperable, will try to recreate it: %v", d.PrivateNetwork, err)
if err := d.deleteNetwork(); err != nil {
return errors.Wrapf(err, "deleting inoperable network %s", d.PrivateNetwork)
}
log.Debugf("Successfully deleted %s network", d.PrivateNetwork)
if err := d.createNetwork(); err != nil {
return errors.Wrapf(err, "recreating inoperable network %s", d.PrivateNetwork)
}
log.Debugf("Successfully recreated %s network", d.PrivateNetwork)
if err := setupNetwork(conn, d.PrivateNetwork); err != nil {
return err
}
log.Debugf("Successfully activated %s network", d.PrivateNetwork)
} }
return nil return nil
...@@ -120,13 +135,16 @@ func (d *Driver) createNetwork() error { ...@@ -120,13 +135,16 @@ func (d *Driver) createNetwork() error {
// network: default // network: default
// It is assumed that the libvirt/kvm installation has already created this network // It is assumed that the libvirt/kvm installation has already created this network
if _, err := conn.LookupNetworkByName(d.Network); err != nil { netd, err := conn.LookupNetworkByName(d.Network)
if err != nil {
return errors.Wrapf(err, "network %s doesn't exist", d.Network) return errors.Wrapf(err, "network %s doesn't exist", d.Network)
} }
defer func() { _ = netd.Free() }()
// network: private // network: private
// Only create the private network if it does not already exist // Only create the private network if it does not already exist
if _, err := conn.LookupNetworkByName(d.PrivateNetwork); err != nil { netp, err := conn.LookupNetworkByName(d.PrivateNetwork)
if err != nil {
// create the XML for the private network from our networkTmpl // create the XML for the private network from our networkTmpl
tmpl := template.Must(template.New("network").Parse(networkTmpl)) tmpl := template.Must(template.New("network").Parse(networkTmpl))
var networkXML bytes.Buffer var networkXML bytes.Buffer
...@@ -141,10 +159,26 @@ func (d *Driver) createNetwork() error { ...@@ -141,10 +159,26 @@ func (d *Driver) createNetwork() error {
} }
// and finally create it // and finally create it
if err := network.Create(); err != nil { log.Debugf("Trying to create network %s...", d.PrivateNetwork)
create := func() error {
if err := network.Create(); err != nil {
return err
}
active, err := network.IsActive()
if err == nil && active {
return nil
}
return errors.Errorf("retrying %v", err)
}
if err := retry.Local(create, 10*time.Second); err != nil {
return errors.Wrapf(err, "creating network %s", d.PrivateNetwork) return errors.Wrapf(err, "creating network %s", d.PrivateNetwork)
} }
} }
defer func() {
if netp != nil {
_ = netp.Free()
}
}()
return nil return nil
} }
...@@ -163,13 +197,13 @@ func (d *Driver) deleteNetwork() error { ...@@ -163,13 +197,13 @@ func (d *Driver) deleteNetwork() error {
log.Debugf("Checking if network %s exists...", d.PrivateNetwork) log.Debugf("Checking if network %s exists...", d.PrivateNetwork)
network, err := conn.LookupNetworkByName(d.PrivateNetwork) network, err := conn.LookupNetworkByName(d.PrivateNetwork)
if err != nil { if err != nil {
if libvirtErr, ok := err.(libvirt.Error); ok && libvirtErr.Code == libvirt.ERR_NO_NETWORK { if lvErr(err).Code == libvirt.ERR_NO_NETWORK {
log.Warnf("Network %s does not exist. Skipping deletion", d.PrivateNetwork) log.Warnf("Network %s does not exist. Skipping deletion", d.PrivateNetwork)
return nil return nil
} }
return errors.Wrapf(err, "failed looking for network %s", d.PrivateNetwork) return errors.Wrapf(err, "failed looking for network %s", d.PrivateNetwork)
} }
defer func() { _ = network.Free() }()
log.Debugf("Network %s exists", d.PrivateNetwork) log.Debugf("Network %s exists", d.PrivateNetwork)
err = d.checkDomains(conn) err = d.checkDomains(conn)
...@@ -178,15 +212,58 @@ func (d *Driver) deleteNetwork() error { ...@@ -178,15 +212,58 @@ func (d *Driver) deleteNetwork() error {
} }
// when we reach this point, it means it is safe to delete the network // when we reach this point, it means it is safe to delete the network
// cannot destroy an inactive network - try to activate it first
log.Debugf("Trying to reactivate network %s first (if needed)...", d.PrivateNetwork)
activate := func() error {
active, err := network.IsActive()
if err == nil && active {
return nil
}
if err != nil {
return err
}
// inactive, try to activate
if err := network.Create(); err != nil {
return err
}
return errors.Errorf("needs confirmation") // confirm in the next cycle
}
if err := retry.Local(activate, 10*time.Second); err != nil {
log.Debugf("Reactivating network %s failed, will continue anyway...", d.PrivateNetwork)
}
log.Debugf("Trying to destroy network %s...", d.PrivateNetwork) log.Debugf("Trying to destroy network %s...", d.PrivateNetwork)
err = network.Destroy() destroy := func() error {
if err != nil { if err := network.Destroy(); err != nil {
return errors.Wrap(err, "network destroy") return err
}
active, err := network.IsActive()
if err == nil && !active {
return nil
}
return errors.Errorf("retrying %v", err)
} }
if err := retry.Local(destroy, 10*time.Second); err != nil {
return errors.Wrap(err, "destroying network")
}
log.Debugf("Trying to undefine network %s...", d.PrivateNetwork) log.Debugf("Trying to undefine network %s...", d.PrivateNetwork)
err = network.Undefine() undefine := func() error {
if err != nil { if err := network.Undefine(); err != nil {
return errors.Wrap(err, "network undefine") return err
}
netp, err := conn.LookupNetworkByName(d.PrivateNetwork)
if netp != nil {
_ = netp.Free()
}
if lvErr(err).Code == libvirt.ERR_NO_NETWORK {
return nil
}
return errors.Errorf("retrying %v", err)
}
if err := retry.Local(undefine, 10*time.Second); err != nil {
return errors.Wrap(err, "undefining network")
} }
return nil return nil
...@@ -272,7 +349,6 @@ func (d *Driver) lookupIP() (string, error) { ...@@ -272,7 +349,6 @@ func (d *Driver) lookupIP() (string, error) {
if err != nil { if err != nil {
return "", errors.Wrap(err, "getting connection and domain") return "", errors.Wrap(err, "getting connection and domain")
} }
defer conn.Close() defer conn.Close()
libVersion, err := conn.GetLibVersion() libVersion, err := conn.GetLibVersion()
...@@ -294,6 +370,7 @@ func (d *Driver) lookupIPFromStatusFile(conn *libvirt.Connect) (string, error) { ...@@ -294,6 +370,7 @@ func (d *Driver) lookupIPFromStatusFile(conn *libvirt.Connect) (string, error) {
if err != nil { if err != nil {
return "", errors.Wrap(err, "looking up network by name") return "", errors.Wrap(err, "looking up network by name")
} }
defer func() { _ = network.Free() }()
bridge, err := network.GetBridgeName() bridge, err := network.GetBridgeName()
if err != nil { if err != nil {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册