Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] fix: server change ip addr support ipv6 #19500

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions pkg/apis/compute/guests.go
Original file line number Diff line number Diff line change
Expand Up @@ -1127,6 +1127,9 @@ type ServerQgaSetNetworkInput struct {
Device string
Ipmask string
Gateway string

Ipmask6 string
Gateway6 string
}

type ServerQgaGetNetworkInput struct {
Expand Down
44 changes: 28 additions & 16 deletions pkg/compute/models/guest_actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -925,7 +925,7 @@ func (self *SGuest) PerformAttachdisk(ctx context.Context, userCred mcclient.Tok
return nil, self.GetDriver().StartGuestAttachDiskTask(ctx, userCred, self, taskData, "")
}

func (self *SGuest) StartRestartNetworkTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string, ip string, inBlockStream bool) error {
/*func (self *SGuest) StartRestartNetworkTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string, ip string, inBlockStream bool) error {
data := jsonutils.NewDict()
data.Set("ip", jsonutils.NewString(ip))
data.Set("in_block_stream", jsonutils.NewBool(inBlockStream))
Expand All @@ -936,13 +936,21 @@ func (self *SGuest) StartRestartNetworkTask(ctx context.Context, userCred mcclie
task.ScheduleRun(nil)
}
return nil
}
}*/

func (self *SGuest) StartQgaRestartNetworkTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string, device string, ipMask string, gateway string, prevIp string, inBlockStream bool) error {
func (self *SGuest) StartQgaRestartNetworkTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string, device string, ipMask, gateway, ipMask6, gateway6 string, prevIp string, inBlockStream bool) error {
data := jsonutils.NewDict()
data.Set("device", jsonutils.NewString(device))
data.Set("ip_mask", jsonutils.NewString(ipMask))
data.Set("gateway", jsonutils.NewString(gateway))
if len(gateway) > 0 {
data.Set("gateway", jsonutils.NewString(gateway))
}
if len(ipMask6) > 0 {
data.Set("ip_mask6", jsonutils.NewString(ipMask6))
if len(gateway6) > 0 {
data.Set("gateway6", jsonutils.NewString(gateway6))
}
}
data.Set("prev_ip", jsonutils.NewString(prevIp))
data.Set("in_block_stream", jsonutils.NewBool(inBlockStream))
if task, err := taskman.TaskManager.NewTask(ctx, "GuestQgaRestartNetworkTask", self, userCred, data, parentTaskId, "", nil); err != nil {
Expand Down Expand Up @@ -2453,15 +2461,7 @@ func (self *SGuest) PerformChangeIpaddr(
return nil, nil
}

//Get the detailed description of the NIC
networkJsonDesc := ngn.getJsonDesc()
newIpAddr := networkJsonDesc.Ip
newMacAddr := networkJsonDesc.Mac
newMaskLen := networkJsonDesc.Masklen
newGateway := networkJsonDesc.Gateway
ipMask := fmt.Sprintf("%s/%d", newIpAddr, newMaskLen)

notes := gn.GetShortDesc(ctx)
notes := ngn.GetShortDesc(ctx)
if gn != nil {
notes.Add(jsonutils.NewString(gn.IpAddr), "prev_ip")
}
Expand All @@ -2476,11 +2476,23 @@ func (self *SGuest) PerformChangeIpaddr(
if self.Hypervisor == api.HYPERVISOR_KVM && restartNetwork && (self.Status == api.VM_RUNNING || self.Status == api.VM_BLOCK_STREAM) {
taskData.Set("restart_network", jsonutils.JSONTrue)
taskData.Set("prev_ip", jsonutils.NewString(gn.IpAddr))
taskData.Set("prev_mac", jsonutils.NewString(newMacAddr))
taskData.Set("prev_mac", jsonutils.NewString(gn.MacAddr))
net := ngn.GetNetwork()
taskData.Set("is_vpc_network", jsonutils.NewBool(net.isOneCloudVpcNetwork()))
taskData.Set("ip_mask", jsonutils.NewString(ipMask))
taskData.Set("gateway", jsonutils.NewString(newGateway))

networkJsonDesc := ngn.getJsonDesc()

taskData.Set("ip_mask", jsonutils.NewString(fmt.Sprintf("%s/%d", networkJsonDesc.Ip, networkJsonDesc.Masklen)))
if ngn.IsDefault && len(networkJsonDesc.Gateway) > 0 {
taskData.Set("gateway", jsonutils.NewString(networkJsonDesc.Gateway))
}
if len(ngn.Ip6Addr) > 0 {
taskData.Set("ip_mask6", jsonutils.NewString(fmt.Sprintf("%s/%d", networkJsonDesc.Ip6, networkJsonDesc.Masklen6)))
if ngn.IsDefault && len(networkJsonDesc.Gateway6) > 0 {
taskData.Set("gateway6", jsonutils.NewString(networkJsonDesc.Gateway6))
}
}

if self.Status == api.VM_BLOCK_STREAM {
taskData.Set("in_block_stream", jsonutils.JSONTrue)
}
Expand Down
37 changes: 27 additions & 10 deletions pkg/compute/tasks/guest_qga_restart_network_task.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ package tasks

import (
"context"
"time"

"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"

api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
Expand All @@ -44,36 +46,51 @@ func (self *GuestQgaRestartNetworkTask) OnRestartNetwork(ctx context.Context, gu
device, _ := self.Params.GetString("device")
ipMask, _ := self.Params.GetString("ip_mask")
gateway, _ := self.Params.GetString("gateway")
ipMask6, _ := self.Params.GetString("ip_mask6")
gateway6, _ := self.Params.GetString("gateway6")
prevIp, _ := self.Params.GetString("prev_ip")
inBlockStream, _ := self.Params.Bool("in_block_stream")

_, err := self.requestSetNetwork(ctx, guest, device, ipMask, gateway)
_, err := self.requestSetNetwork(ctx, guest, device, ipMask, gateway, ipMask6, gateway6)
var errs []error
const MAX_TRIES = 3
//the first set maybe fail,if failed, try again
if err != nil {
for err != nil && len(errs) < MAX_TRIES {
errs = append(errs, err)
logclient.AddActionLogWithStartable(self, guest, logclient.ACT_RESTART_NETWORK, err, self.UserCred, false)
_, err = self.requestSetNetwork(ctx, guest, device, ipMask, gateway)
_, err = self.requestSetNetwork(ctx, guest, device, ipMask, gateway, ipMask6, gateway6)
if err != nil {
logclient.AddActionLogWithStartable(self, guest, logclient.ACT_RESTART_NETWORK, err, self.UserCred, false)
self.taskFailed(ctx, guest, prevIp, inBlockStream, err)
return
time.Sleep(time.Second)
continue
} else {
errs = nil
break
}
}

if len(errs) > 0 {
self.taskFailed(ctx, guest, prevIp, inBlockStream, errors.NewAggregate(errs))
return
}

logclient.AddActionLogWithStartable(self, guest, logclient.ACT_QGA_NETWORK_SUCCESS, "qga restart network success", self.UserCred, true)
guest.UpdateQgaStatus(api.QGA_STATUS_AVAILABLE)
guest.StartSyncstatus(ctx, self.UserCred, "")
self.SetStageComplete(ctx, nil)
}

func (self *GuestQgaRestartNetworkTask) requestSetNetwork(ctx context.Context, guest *models.SGuest, device string, ipMask string, gateway string) (jsonutils.JSONObject, error) {
func (self *GuestQgaRestartNetworkTask) requestSetNetwork(ctx context.Context, guest *models.SGuest, device string, ipMask, gateway, ipMask6, gateway6 string) (jsonutils.JSONObject, error) {
host, err := guest.GetHost()
if err != nil {
self.taskFailed(ctx, guest, "", false, err)
return nil, err
}
inputQgaNet := &api.ServerQgaSetNetworkInput{
Device: device,
Ipmask: ipMask,
Gateway: gateway,
Device: device,
Ipmask: ipMask,
Gateway: gateway,
Ipmask6: ipMask6,
Gateway6: gateway6,
}

// if success, log network related information
Expand Down
11 changes: 5 additions & 6 deletions pkg/compute/tasks/guest_sync_task.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,10 @@ func (self *GuestSyncConfTask) StartRestartNetworkTask(ctx context.Context, gues
log.Errorf("unable to get ip_mask when restart_network is true when sync guest")
return
}
gateway, err := self.Params.GetString("gateway")
if err != nil {
log.Errorf("unable to get gateway when restart_network is true when sync guest")
return
}
gateway, _ := self.Params.GetString("gateway")
ipMask6, _ := self.Params.GetString("ip_mask6")
gateway6, _ := self.Params.GetString("gateway6")

isVpcNetwork := jsonutils.QueryBoolean(self.Params, "is_vpc_network", false)

// try use qga restart network
Expand All @@ -116,7 +115,7 @@ func (self *GuestSyncConfTask) StartRestartNetworkTask(ctx context.Context, gues
time.Sleep(10 * time.Second)
}
return guest.StartQgaRestartNetworkTask(
ctx, self.UserCred, "", ifnameDevice, ipMask, gateway, prevIp, inBlockStream)
ctx, self.UserCred, "", ifnameDevice, ipMask, gateway, ipMask6, gateway6, prevIp, inBlockStream)
}()
if err != nil {
log.Errorf("guest %s failed start qga restart network task: %s", guest.GetName(), err)
Expand Down
11 changes: 5 additions & 6 deletions pkg/hostman/guestman/guesthandlers/guesthandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -932,14 +932,13 @@ func qgaSetNetwork(ctx context.Context, userCred mcclient.TokenCredential, sid s
if input.Ipmask == "" {
return nil, httperrors.NewMissingParameterError("ipmask")
}
if input.Gateway == "" {
return nil, httperrors.NewMissingParameterError("gateway")
}

qgaNetMod := &monitor.NetworkModify{
Device: input.Device,
Ipmask: input.Ipmask,
Gateway: input.Gateway,
Device: input.Device,
Ipmask: input.Ipmask,
Gateway: input.Gateway,
Ipmask6: input.Ipmask6,
Gateway6: input.Gateway6,
}
return gm.QgaSetNetwork(qgaNetMod, sid, input.Timeout)
}
Expand Down
28 changes: 25 additions & 3 deletions pkg/hostman/monitor/qga/qga.go
Original file line number Diff line number Diff line change
Expand Up @@ -421,12 +421,24 @@ func (qga *QemuGuestAgent) QgaSetWindowsNetwork(qgaNetMod *monitor.NetworkModify
if err != nil {
return err
}

var gatewayStr string
if len(qgaNetMod.Gateway) > 0 {
gatewayStr = fmt.Sprintf("gateway=%s", qgaNetMod.Gateway)
}
networkCmd := fmt.Sprintf(
"netsh interface ip set address name=\"%s\" source=static addr=%s mask=%s gateway=%s & "+
"netsh interface ip set address name=\"%s\" source=static addr=%s mask=%s %s & "+
"netsh interface ip set address name=\"%s\" dhcp",
qgaNetMod.Device, ip, subnetMask, qgaNetMod.Gateway, qgaNetMod.Device,
qgaNetMod.Device, ip, subnetMask, gatewayStr, qgaNetMod.Device,
)

if len(qgaNetMod.Ipmask6) > 0 {
networkCmd += fmt.Sprintf(" & netsh interface ipv6 set address \"%s\" %s", qgaNetMod.Device, qgaNetMod.Ipmask6)
if len(qgaNetMod.Gateway6) > 0 {
networkCmd += fmt.Sprintf(" & netsh interface ipv6 set route ::/0 \"%s\" %s", qgaNetMod.Device, qgaNetMod.Gateway6)
}
}

log.Infof("networkCmd: %s", networkCmd)
arg := []string{"/C", networkCmd}
cmdExecNet := &monitor.Command{
Expand All @@ -447,7 +459,17 @@ func (qga *QemuGuestAgent) QgaSetWindowsNetwork(qgaNetMod *monitor.NetworkModify
}

func (qga *QemuGuestAgent) QgaSetLinuxNetwork(qgaNetMod *monitor.NetworkModify) error {
args := []string{"-c", fmt.Sprintf("/sbin/dhclient -r %s && /sbin/dhclient -1 %s", qgaNetMod.Device, qgaNetMod.Device)}
cmd := fmt.Sprintf("/usr/sbin/ip addr flush dev %s && /usr/sbin/ip addr add %s dev %s", qgaNetMod.Device, qgaNetMod.Ipmask, qgaNetMod.Device)
if len(qgaNetMod.Gateway) > 0 {
cmd += fmt.Sprintf(" && /usr/sbin/ip route add default via %s dev %s", qgaNetMod.Gateway, qgaNetMod.Device)
}
if len(qgaNetMod.Ipmask6) > 0 {
cmd += fmt.Sprintf(" && /usr/sbin/ip -6 addr add %s dev %s", qgaNetMod.Ipmask6, qgaNetMod.Device)
if len(qgaNetMod.Gateway6) > 0 {
cmd += fmt.Sprintf(" && /usr/sbin/ip -6 route add default via %s dev %s", qgaNetMod.Gateway6, qgaNetMod.Device)
}
}
args := []string{"-c", "'" + cmd + "'"}
_, err := qga.GuestExecCommand("/bin/bash", args, []string{}, "", false)
return err
}
Expand Down
3 changes: 3 additions & 0 deletions pkg/hostman/monitor/qmp.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ type NetworkModify struct {
Device string `json:"device"`
Ipmask string `json:"ipmask"`
Gateway string `json:"gateway"`

Ipmask6 string `json:"ipmask6"`
Gateway6 string `json:"gateway6"`
}

type Version struct {
Expand Down
Loading