kvm2 driver: be more robust with creating of the network, don't delete the network if it is in use
parent
b35e908dec
commit
34ee59192b
|
@ -215,8 +215,17 @@ func (d *Driver) Restart() error {
|
|||
}
|
||||
|
||||
func (d *Driver) Start() 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
|
||||
log.Info("Ensuring networks are active...")
|
||||
err := d.ensureNetwork()
|
||||
err = d.ensureNetwork()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "ensuring active networks")
|
||||
}
|
||||
|
@ -358,18 +367,16 @@ func (d *Driver) Remove() error {
|
|||
}
|
||||
defer conn.Close()
|
||||
|
||||
//Tear down network and disk if they exist
|
||||
log.Debug("Checking if the network needs to be deleted")
|
||||
network, err := conn.LookupNetworkByName(d.PrivateNetwork)
|
||||
// Tear down network if it exists and is not in use by another minikube instance
|
||||
log.Debug("Trying to delete the networks (if possible)")
|
||||
err = d.deleteNetwork()
|
||||
if err != nil {
|
||||
log.Warn("Network %s does not exist, nothing to clean up...", d.PrivateNetwork)
|
||||
}
|
||||
if network != nil {
|
||||
log.Infof("Network %s exists, removing...", d.PrivateNetwork)
|
||||
network.Destroy()
|
||||
network.Undefine()
|
||||
log.Warnf("Deleting of networks failed: %s", err.Error())
|
||||
} else {
|
||||
log.Info("Successfully deleted networks")
|
||||
}
|
||||
|
||||
// Tear down the domain now
|
||||
log.Debug("Checking if the domain needs to be deleted")
|
||||
dom, err := conn.LookupDomainByName(d.MachineName)
|
||||
if err != nil {
|
||||
|
|
|
@ -19,6 +19,7 @@ package kvm
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
|
@ -141,6 +142,111 @@ func (d *Driver) createNetwork() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (d *Driver) deleteNetwork() error {
|
||||
type source struct {
|
||||
//XMLName xml.Name `xml:"source"`
|
||||
Network string `xml:"network,attr"`
|
||||
}
|
||||
type iface struct {
|
||||
//XMLName xml.Name `xml:"interface"`
|
||||
Source source `xml:"source"`
|
||||
}
|
||||
type result struct {
|
||||
//XMLName xml.Name `xml:"domain"`
|
||||
Name string `xml:"name"`
|
||||
Interfaces []iface `xml:"devices>interface"`
|
||||
}
|
||||
|
||||
conn, err := getConnection()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "getting libvirt connection")
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
// network: default
|
||||
// It is assumed that the OS manages this network
|
||||
|
||||
// network: private
|
||||
log.Debugf("Checking if network %s exists...", d.PrivateNetwork)
|
||||
network, err := conn.LookupNetworkByName(d.PrivateNetwork)
|
||||
if err != nil {
|
||||
// TODO: decide if we really wanna throw an error?
|
||||
return errors.Wrap(err, "network %s does not exist")
|
||||
}
|
||||
log.Debugf("Network %s exists", d.PrivateNetwork)
|
||||
|
||||
// iterate over every (also turned off) domains, and check if it
|
||||
// is using the private network. Do *not* delete the network if
|
||||
// that is the case
|
||||
log.Debug("Trying to list all domains...")
|
||||
doms, err := conn.ListAllDomains(0)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "list all domains")
|
||||
}
|
||||
log.Debugf("Listed all domains: total of %d domains", len(doms))
|
||||
|
||||
// fail if there are 0 domains
|
||||
if len(doms) == 0 {
|
||||
return fmt.Errorf("list of domains is 0 lenght")
|
||||
}
|
||||
|
||||
for _, dom := range doms {
|
||||
// get the name of the domain we iterate over
|
||||
log.Debug("Trying to get name of domain...")
|
||||
name, err := dom.GetName()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to get name of a domain")
|
||||
}
|
||||
log.Debugf("Got domain name: %s", name)
|
||||
|
||||
// skip the domain if it is our own machine
|
||||
if name == d.MachineName {
|
||||
log.Debug("Skipping domain as it is us...")
|
||||
continue
|
||||
}
|
||||
|
||||
// unfortunately, there is no better way to retrieve a list of all defined interfaces
|
||||
// in domains than getting it from the defined XML of all domains
|
||||
// NOTE: conn.ListAllInterfaces does not help in this case
|
||||
log.Debugf("Getting XML for domain %s...", name)
|
||||
xmlString, err := dom.GetXMLDesc(libvirt.DOMAIN_XML_INACTIVE)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to get XML of domain '%s'", name)
|
||||
}
|
||||
log.Debugf("Got XML for domain %s", name)
|
||||
|
||||
v := result{}
|
||||
err = xml.Unmarshal([]byte(xmlString), &v)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to unmarshal XML of domain '%s", name)
|
||||
}
|
||||
log.Debugf("Unmarshaled XML for domain %s: %#v", name, v)
|
||||
|
||||
// iterate over the found interfaces
|
||||
for _, i := range v.Interfaces {
|
||||
if i.Source.Network == d.PrivateNetwork {
|
||||
log.Debugf("domain %s DOES use network %s, aborting...", name, d.PrivateNetwork)
|
||||
return fmt.Errorf("network still in use at least by domain '%s',", name)
|
||||
}
|
||||
log.Debugf("domain %s does not use network %s", name, d.PrivateNetwork)
|
||||
}
|
||||
}
|
||||
|
||||
// when we reach this point, it means it is safe to delete the network
|
||||
log.Debugf("Trying to destroy network %s...", d.PrivateNetwork)
|
||||
err = network.Destroy()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "network destroy")
|
||||
}
|
||||
log.Debugf("Trying to undefine network %s...", d.PrivateNetwork)
|
||||
err = network.Undefine()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "network undefine")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Driver) lookupIP() (string, error) {
|
||||
conn, err := getConnection()
|
||||
if err != nil {
|
||||
|
@ -159,6 +265,7 @@ func (d *Driver) lookupIP() (string, error) {
|
|||
return d.lookupIPFromLeasesFile()
|
||||
}
|
||||
|
||||
// TODO: for everything > 1002006, there is direct support in the libvirt-go for handling this
|
||||
return d.lookupIPFromStatusFile(conn)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue