diff --git a/pkg/hostman/guestman/guesttasks.go b/pkg/hostman/guestman/guesttasks.go index 3b1cc602d6..534dc99b8a 100644 --- a/pkg/hostman/guestman/guesttasks.go +++ b/pkg/hostman/guestman/guesttasks.go @@ -342,6 +342,8 @@ type SGuestNetworkSyncTask struct { addNics []jsonutils.JSONObject errors []error + changedNics [][]jsonutils.JSONObject + callback func(...error) } @@ -360,10 +362,39 @@ func (n *SGuestNetworkSyncTask) syncNetworkConf() { n.addNics = n.addNics[:len(n.addNics)-1] n.addNic(nic) } else { + if len(n.changedNics) > 0 { + for i := range n.changedNics { + n.onNicChange(n.changedNics[i][0], n.changedNics[i][1]) + } + } n.callback(n.errors...) } } +func (n *SGuestNetworkSyncTask) onNicChange(oldNic, newNic jsonutils.JSONObject) { + oldbr, _ := oldNic.GetString("bridge") + oldifname, _ := oldNic.GetString("ifname") + newbr, _ := newNic.GetString("bridge") + newifname, _ := newNic.GetString("ifname") + if oldbr != newbr { + // bridge changed + if oldifname == newifname { + output, err := procutils.NewRemoteCommandAsFarAsPossible("ovs-vsctl", "del-port", oldbr, oldifname).Output() + log.Debugf("ovs-vsctl del-port %s %s: %s", oldbr, oldifname, output) + if err != nil { + n.errors = append(n.errors, err) + } + output, err = procutils.NewRemoteCommandAsFarAsPossible("ovs-vsctl", "add-port", newbr, newifname).Output() + log.Debugf("ovs-vsctl add-port %s %s: %s", newbr, newifname, output) + if err != nil { + n.errors = append(n.errors, err) + } + } else { + log.Errorf("cannot change both bridge(%s!=%s) and ifname(%s!=%s)!!!!!", oldbr, newbr, oldifname, newifname) + } + } +} + func (n *SGuestNetworkSyncTask) removeNic(nic jsonutils.JSONObject) { ifname, _ := nic.GetString("ifname") callback := func(res string) { @@ -460,8 +491,8 @@ func (n *SGuestNetworkSyncTask) onDeviceAdd(nic jsonutils.JSONObject) { n.syncNetworkConf() } -func NewGuestNetworkSyncTask(guest *SKVMGuestInstance, delNics, addNics []jsonutils.JSONObject) *SGuestNetworkSyncTask { - return &SGuestNetworkSyncTask{guest, delNics, addNics, make([]error, 0), nil} +func NewGuestNetworkSyncTask(guest *SKVMGuestInstance, delNics, addNics []jsonutils.JSONObject, changedNics [][]jsonutils.JSONObject) *SGuestNetworkSyncTask { + return &SGuestNetworkSyncTask{guest, delNics, addNics, make([]error, 0), changedNics, nil} } /** diff --git a/pkg/hostman/guestman/qemu-kvm.go b/pkg/hostman/guestman/qemu-kvm.go index a7fa5b6ec4..bbfe0d28cb 100644 --- a/pkg/hostman/guestman/qemu-kvm.go +++ b/pkg/hostman/guestman/qemu-kvm.go @@ -1099,7 +1099,7 @@ func (s *SKVMGuestInstance) compareDescCdrom(newDesc jsonutils.JSONObject) *stri } } -func (s *SKVMGuestInstance) compareDescNetworks(newDesc jsonutils.JSONObject) ([]jsonutils.JSONObject, []jsonutils.JSONObject) { +func (s *SKVMGuestInstance) compareDescNetworks(newDesc jsonutils.JSONObject) ([]jsonutils.JSONObject, []jsonutils.JSONObject, [][]jsonutils.JSONObject) { var isValid = func(net jsonutils.JSONObject) bool { driver, _ := net.GetString("driver") return driver == "virtio" @@ -1117,9 +1117,11 @@ func (s *SKVMGuestInstance) compareDescNetworks(newDesc jsonutils.JSONObject) ([ } var delNics, addNics = []jsonutils.JSONObject{}, []jsonutils.JSONObject{} + var changedNics = [][]jsonutils.JSONObject{} nics, _ := newDesc.GetArray("nics") for _, n := range nics { if isValid(n) { + // assume all nics in new desc are new addNics = append(addNics, n) } } @@ -1129,24 +1131,31 @@ func (s *SKVMGuestInstance) compareDescNetworks(newDesc jsonutils.JSONObject) ([ if isValid(n) { idx := findNet(addNics, n) if idx >= 0 { - // remove n + // check if bridge changed + changedNics = append(changedNics, []jsonutils.JSONObject{ + n, // old + addNics[idx], // new + }) + // remove existing nic from new addNics = append(addNics[:idx], addNics[idx+1:]...) } else { + // not found, remove the nic delNics = append(delNics, n) } } } - return delNics, addNics + return delNics, addNics, changedNics } func (s *SKVMGuestInstance) SyncConfig(ctx context.Context, desc jsonutils.JSONObject, fwOnly bool) (jsonutils.JSONObject, error) { var delDisks, addDisks, delNetworks, addNetworks []jsonutils.JSONObject + var changedNetworks [][]jsonutils.JSONObject var cdrom *string if !fwOnly { delDisks, addDisks = s.compareDescDisks(desc) cdrom = s.compareDescCdrom(desc) - delNetworks, addNetworks = s.compareDescNetworks(desc) + delNetworks, addNetworks, changedNetworks = s.compareDescNetworks(desc) } if err := s.SaveDesc(desc); err != nil { return nil, err @@ -1190,7 +1199,7 @@ func (s *SKVMGuestInstance) SyncConfig(ctx context.Context, desc jsonutils.JSONO } if len(delNetworks)+len(addNetworks) > 0 { - task := NewGuestNetworkSyncTask(s, delNetworks, addNetworks) + task := NewGuestNetworkSyncTask(s, delNetworks, addNetworks, changedNetworks) runTaskNames = append(runTaskNames, jsonutils.NewString("networksync")) tasks = append(tasks, task) }