feat(region,host): qga deploy network config on attach nics (#22547)

This commit is contained in:
wanyaoqi
2025-05-30 10:29:38 +08:00
committed by GitHub
parent a9eb3872e4
commit cf71a29b67
7 changed files with 131 additions and 8 deletions
+4 -2
View File
@@ -155,8 +155,9 @@ func init() {
})
type ServerAttachNetworkOptions struct {
SERVER string `help:"ID or Name of server"`
NETDESC []string `help:"Network description"`
SERVER string `help:"ID or Name of server"`
DisableSyncConfig bool `help:"Disable sync config"`
NETDESC []string `help:"Network description"`
}
R(&ServerAttachNetworkOptions{}, "server-attach-network", "Attach a server to a virtual network", func(s *mcclient.ClientSession, args *ServerAttachNetworkOptions) error {
input := compute.AttachNetworkInput{}
@@ -167,6 +168,7 @@ func init() {
}
input.Nets = append(input.Nets, conf)
}
input.DisableSyncConfig = &args.DisableSyncConfig
params := jsonutils.Marshal(input)
srv, err := modules.Servers.PerformAction(s, args.SERVER, "attachnetwork", params)
if err != nil {
+1 -1
View File
@@ -1175,7 +1175,7 @@ type ServerQgaGetNetworkInput struct {
}
type ServerQgaTimeoutInput struct {
// qga execute timeout millisecond
// qga execute timeout second
Timeout int
}
+1 -1
View File
@@ -96,7 +96,7 @@ func (self *GuestSyncConfTask) StartRestartNetworkTask(ctx context.Context, gues
// try use qga restart network
err = func() error {
host, _ := guest.GetHost()
err = guest.GetDriver().QgaRequestGuestPing(ctx, self.GetTaskRequestHeader(), host, guest, false, &api.ServerQgaTimeoutInput{1000})
err = guest.GetDriver().QgaRequestGuestPing(ctx, self.GetTaskRequestHeader(), host, guest, false, &api.ServerQgaTimeoutInput{1})
if err != nil {
return errors.Wrap(err, "qga guest-ping")
}
+13 -1
View File
@@ -20,6 +20,7 @@ import (
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
"yunion.io/x/onecloud/pkg/hostman/guestman/desc"
deployapi "yunion.io/x/onecloud/pkg/hostman/hostdeployer/apis"
"yunion.io/x/onecloud/pkg/hostman/monitor"
"yunion.io/x/onecloud/pkg/httperrors"
@@ -107,7 +108,6 @@ func (m *SGuestManager) QgaSetNetwork(ctx context.Context, params interface{}) (
Gateway: input.Gateway,
}
//func (m *SGuestManager) QgaSetNetwork(netmod *monitor.NetworkModify, sid string, execTimeout int) (string, error) {
guest, err := m.checkAndInitGuestQga(input.Sid)
if err != nil {
return nil, err
@@ -144,3 +144,15 @@ func (m *SGuestManager) QgaGetOsInfo(sid string) (jsonutils.JSONObject, error) {
}
return jsonutils.Marshal(res), nil
}
func (guest *SKVMGuestInstance) QgaAddNicsConfigure(addNics []*desc.SGuestNetwork) error {
if guest.guestAgent == nil {
if err := guest.InitQga(); err != nil {
return errors.Wrap(err, "init qga")
}
}
if err := guest.guestAgent.GuestPing(1); err != nil {
return errors.Wrap(err, "Qga ping")
}
return guest.guestAgent.QgaDeployNics(deployapi.GuestNicsToServerNics(addNics))
}
+73 -1
View File
@@ -615,11 +615,34 @@ type SGuestNetworkSyncTask struct {
addNics []*desc.SGuestNetwork
errors []error
addNicMacs []string
addNicConfs []*monitor.NetworkModify
callback func(...error)
}
func (n *SGuestNetworkSyncTask) Start(callback func(...error)) {
n.callback = callback
if len(n.addNics) > 0 {
nics := make([]*desc.SGuestNetwork, 0)
nics = append(nics, n.guest.Desc.Nics...)
nics = append(nics, n.addNics...)
if err := n.guest.QgaAddNicsConfigure(nics); err != nil {
log.Errorf("QgaAddNicsConfigure failed %s", err)
} else {
addNicMacs := make([]string, 0)
addNicConfs := make([]*monitor.NetworkModify, 0)
for i := range n.addNics {
addNicMacs = append(addNicMacs, n.addNics[i].Mac)
addNicConfs = append(addNicConfs, &monitor.NetworkModify{
Ipmask: fmt.Sprintf("%s/%d", n.addNics[i].Ip, n.addNics[i].Masklen),
Gateway: n.addNics[i].Gateway,
})
}
n.addNicMacs = addNicMacs
n.addNicConfs = addNicConfs
}
}
n.syncNetworkConf()
}
@@ -633,10 +656,59 @@ func (n *SGuestNetworkSyncTask) syncNetworkConf() {
n.addNics = n.addNics[:len(n.addNics)-1]
n.addNic(nic)
} else {
if len(n.addNicMacs) > 0 {
// try restart added nics, wait for added nic ready
time.Sleep(3 * time.Second)
if err := n.qgaRestartAddedNics(); err != nil {
log.Errorf("failed qgaRestartAddedNics")
}
}
n.callback(n.errors...)
}
}
func (n *SGuestNetworkSyncTask) qgaRestartAddedNics() error {
err := n.qgaGetAddedNicDevs()
if err != nil {
return err
}
for i := range n.addNicConfs {
if n.addNicConfs[i].Device != "" {
err = n.guest.guestAgent.QgaRestartNetwork(n.addNicConfs[i])
if err != nil {
log.Errorf("Failed QgaRestartNetwork %s %s", n.addNicConfs[i].Device, err)
}
}
}
return nil
}
func (n *SGuestNetworkSyncTask) qgaGetAddedNicDevs() error {
data, err := n.guest.guestAgent.QgaGetNetwork()
if err != nil {
return errors.Wrap(err, "QgaGetNetwork")
}
var parsedData []api.IfnameDetail
ifnames, err := jsonutils.Parse(data)
if err != nil {
return errors.Wrapf(err, "parse qga network output %s", data)
}
err = ifnames.Unmarshal(&parsedData)
if err != nil {
return errors.Wrap(err, "unmarshal ifnames")
}
for i := range n.addNicMacs {
for j := range parsedData {
if n.addNicMacs[i] == parsedData[j].HardwareAddress {
n.addNicConfs[i].Device = parsedData[j].Name
break
}
}
}
return nil
}
func (n *SGuestNetworkSyncTask) removeNic(nic *desc.SGuestNetwork) {
callback := func(res string) {
if len(res) > 0 && !strings.Contains(res, "not found") {
@@ -794,7 +866,7 @@ func (n *SGuestNetworkSyncTask) onDeviceAdd(nic *desc.SGuestNetwork) {
func NewGuestNetworkSyncTask(
guest *SKVMGuestInstance, delNics, addNics []*desc.SGuestNetwork,
) *SGuestNetworkSyncTask {
return &SGuestNetworkSyncTask{guest, delNics, addNics, make([]error, 0), nil}
return &SGuestNetworkSyncTask{guest, delNics, addNics, make([]error, 0), nil, nil, nil}
}
/**
+37
View File
@@ -598,6 +598,11 @@ if systemctl is-active --quiet network.service; then
exit 0
fi
if command -v netplan &>/dev/null; then
netplan try --timeout 0
exit 0
fi
if command -v ip &> /dev/null; then
ip link set $DEV down && ip link set $DEV up
exit 0
@@ -653,6 +658,38 @@ func (qga *QemuGuestAgent) QgaSetNetwork(qgaNetMod *monitor.NetworkModify, guest
}
}
func (qga *QemuGuestAgent) QgaRestartNetwork(qgaNetMod *monitor.NetworkModify) error {
//Getting information about the operating system
resOsInfo, err := qga.QgaGuestGetOsInfo()
if err != nil {
return errors.Wrap(err, "get os info")
}
//Judgement based on id, currently only windows and other systems are judged
switch resOsInfo.Id {
case "mswindows":
return qga.QgaSetWindowsNetwork(qgaNetMod)
default:
return qga.QgaRestartLinuxNetwork(qgaNetMod)
}
}
func (qga *QemuGuestAgent) QgaDeployNics(guestNics []*types.SServerNic) error {
//Getting information about the operating system
resOsInfo, err := qga.QgaGuestGetOsInfo()
if err != nil {
return errors.Wrap(err, "get os info")
}
if resOsInfo.Id == "mswindows" {
return nil
}
if err := qga.qgaDeployNetworkConfigure(guestNics); err != nil {
return errors.Wrap(err, "qgaDeployNetworkConfigure")
}
return nil
}
/*
# @username: the user account whose password to change
# @password: the new password entry string, base64 encoded
+2 -2
View File
@@ -866,7 +866,7 @@ type ServerQgaCommand struct {
ServerIdOptions
COMMAND string `help:"qga command"`
Timeout int `help:"qga command execute timeout (ms)"`
Timeout int `help:"qga command execute timeout (s)"`
}
func (o *ServerQgaCommand) Params() (jsonutils.JSONObject, error) {
@@ -876,7 +876,7 @@ func (o *ServerQgaCommand) Params() (jsonutils.JSONObject, error) {
type ServerQgaPing struct {
ServerIdOptions
Timeout int `help:"qga command execute timeout (ms)"`
Timeout int `help:"qga command execute timeout (s)"`
}
func (o *ServerQgaPing) Params() (jsonutils.JSONObject, error) {