mirror of
https://hubproxy.babadafafafafa.cn/https://github.com/yunionio/cloudpods.git
synced 2026-09-20 08:03:53 +08:00
Compare commits
5 Commits
release/4.
...
v4.0.1-rc.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aed4db1454 | ||
|
|
5ba5d78344 | ||
|
|
d4840e0293 | ||
|
|
dd72ff2c4b | ||
|
|
84b0f1075a |
@@ -1202,9 +1202,11 @@ type ServerQgaGuestInfoTaskInput struct {
|
||||
|
||||
type ServerQgaSetNetworkInput struct {
|
||||
ServerQgaTimeoutInput
|
||||
Device string
|
||||
Ipmask string
|
||||
Gateway string
|
||||
Device string
|
||||
Ipmask string
|
||||
Gateway string
|
||||
Ip6mask string
|
||||
Gateway6 string
|
||||
}
|
||||
|
||||
type ServerQgaGetNetworkInput struct {
|
||||
|
||||
@@ -901,47 +901,45 @@ func (manager *SCachedimageManager) ListItemFilter(
|
||||
}
|
||||
|
||||
{
|
||||
var idFilter bool
|
||||
storagecachedImages := StoragecachedimageManager.Query("cachedimage_id").Equals("status", api.CACHED_IMAGE_STATUS_ACTIVE).SubQuery()
|
||||
storageCaches := StoragecacheManager.Query().SubQuery()
|
||||
storagecachedImages := StoragecachedimageManager.Query("cachedimage_id").Equals("status", api.CACHED_IMAGE_STATUS_ACTIVE) // .SubQuery()
|
||||
storagecachedImages = storagecachedImages.Snapshot()
|
||||
|
||||
storagesQ := StorageManager.Query()
|
||||
storagesQ := StorageManager.Query("storagecache_id")
|
||||
storagesQ = storagesQ.Snapshot()
|
||||
if query.Valid {
|
||||
idFilter = true
|
||||
storagesQ = storagesQ.In("status", []string{api.STORAGE_ENABLED, api.STORAGE_ONLINE}).IsTrue("enabled")
|
||||
}
|
||||
if len(query.CloudproviderId) > 0 {
|
||||
idFilter = true
|
||||
storagesQ = storagesQ.In("manager_id", query.CloudproviderId)
|
||||
}
|
||||
storages := storagesQ.SubQuery()
|
||||
zonesQ := ZoneManager.Query()
|
||||
if len(query.HostSchedtagId) > 0 {
|
||||
hostschedtags := HostschedtagManager.Query("host_id").Equals("schedtag_id", query.HostSchedtagId)
|
||||
hoststorages := HoststorageManager.Query("storage_id").In("host_id", hostschedtags.Distinct().SubQuery())
|
||||
storagesQ = storagesQ.In("id", hoststorages.Distinct().SubQuery())
|
||||
}
|
||||
|
||||
zonesQ := ZoneManager.Query("id")
|
||||
zonesQ = zonesQ.Snapshot()
|
||||
if len(query.ZoneId) > 0 {
|
||||
idFilter = true
|
||||
zonesQ = zonesQ.Equals("id", query.ZoneId)
|
||||
}
|
||||
if len(query.CloudregionId) > 0 {
|
||||
idFilter = true
|
||||
zonesQ = zonesQ.In("cloudregion_id", query.CloudregionId)
|
||||
}
|
||||
zones := zonesQ.SubQuery()
|
||||
|
||||
subq := storagecachedImages.Query(storagecachedImages.Field("cachedimage_id"))
|
||||
subq = subq.Join(storageCaches, sqlchemy.Equals(storagecachedImages.Field("storagecache_id"), storageCaches.Field("id")))
|
||||
subq = subq.Join(storages, sqlchemy.Equals(storageCaches.Field("id"), storages.Field("storagecache_id")))
|
||||
subq = subq.Join(zones, sqlchemy.Equals(storages.Field("zone_id"), zones.Field("id")))
|
||||
|
||||
if len(query.HostSchedtagId) > 0 {
|
||||
idFilter = true
|
||||
hoststorages := HoststorageManager.Query("host_id", "storage_id").SubQuery()
|
||||
hostschedtags := HostschedtagManager.Query().Equals("schedtag_id", query.HostSchedtagId).SubQuery()
|
||||
subq = subq.Join(hoststorages, sqlchemy.Equals(hoststorages.Field("storage_id"), storages.Field("id")))
|
||||
subq = subq.Join(hostschedtags, sqlchemy.Equals(hostschedtags.Field("host_id"), hoststorages.Field("host_id")))
|
||||
if zonesQ.IsAltered() {
|
||||
storagesQ = storagesQ.Filter(
|
||||
sqlchemy.In(storagesQ.Field("zone_id"), zonesQ.Distinct().SubQuery()),
|
||||
)
|
||||
}
|
||||
|
||||
if idFilter {
|
||||
subQ := subq.Distinct().SubQuery()
|
||||
q = q.Join(subQ, sqlchemy.Equals(q.Field("id"), subQ.Field("cachedimage_id")))
|
||||
if storagesQ.IsAltered() {
|
||||
storagecachedImages = storagecachedImages.Filter(
|
||||
sqlchemy.In(storagecachedImages.Field("storagecache_id"), storagesQ.Distinct().SubQuery()),
|
||||
)
|
||||
}
|
||||
|
||||
if storagecachedImages.IsAltered() {
|
||||
q = q.In("id", storagecachedImages.Distinct().SubQuery())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1031,13 +1031,18 @@ func (self *SGuest) StartRestartNetworkTask(ctx context.Context, userCred mcclie
|
||||
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, device, ipMask, gateway, ip6Mask, gateway6 string) error {
|
||||
data := jsonutils.NewDict()
|
||||
data.Set("device", jsonutils.NewString(device))
|
||||
data.Set("ip_mask", jsonutils.NewString(ipMask))
|
||||
data.Set("gateway", jsonutils.NewString(gateway))
|
||||
data.Set("prev_ip", jsonutils.NewString(prevIp))
|
||||
data.Set("in_block_stream", jsonutils.NewBool(inBlockStream))
|
||||
if len(ipMask) > 0 {
|
||||
data.Set("ip_mask", jsonutils.NewString(ipMask))
|
||||
data.Set("gateway", jsonutils.NewString(gateway))
|
||||
}
|
||||
if len(ip6Mask) > 0 {
|
||||
data.Set("ip6_mask", jsonutils.NewString(ip6Mask))
|
||||
data.Set("gateway6", jsonutils.NewString(gateway6))
|
||||
}
|
||||
|
||||
if task, err := taskman.TaskManager.NewTask(ctx, "GuestQgaRestartNetworkTask", self, userCred, data, parentTaskId, "", nil); err != nil {
|
||||
log.Errorln(err)
|
||||
return err
|
||||
@@ -2755,9 +2760,13 @@ func (self *SGuest) PerformChangeIpaddr(
|
||||
newMacAddr := networkJsonDesc.Mac
|
||||
newMaskLen := networkJsonDesc.Masklen
|
||||
newGateway := networkJsonDesc.Gateway
|
||||
ipMask := fmt.Sprintf("%s/%d", newIpAddr, newMaskLen)
|
||||
if conf.StrictIPv6 {
|
||||
ipMask = fmt.Sprintf("%s/%d", networkJsonDesc.Ip6, networkJsonDesc.Masklen6)
|
||||
ipMask := ""
|
||||
if networkJsonDesc.Ip != "" {
|
||||
ipMask = fmt.Sprintf("%s/%d", newIpAddr, newMaskLen)
|
||||
}
|
||||
ip6Mask := ""
|
||||
if networkJsonDesc.Ip6 != "" {
|
||||
ip6Mask = fmt.Sprintf("%s/%d", networkJsonDesc.Ip6, networkJsonDesc.Masklen6)
|
||||
}
|
||||
|
||||
notes := gn.GetShortDesc(ctx)
|
||||
@@ -2781,8 +2790,15 @@ func (self *SGuest) PerformChangeIpaddr(
|
||||
return nil, errors.Wrapf(err, "GetNetwork")
|
||||
}
|
||||
taskData.Set("is_vpc_network", jsonutils.NewBool(net.isOneCloudVpcNetwork()))
|
||||
taskData.Set("ip_mask", jsonutils.NewString(ipMask))
|
||||
taskData.Set("gateway", jsonutils.NewString(newGateway))
|
||||
if len(ipMask) > 0 {
|
||||
taskData.Set("ip_mask", jsonutils.NewString(ipMask))
|
||||
taskData.Set("gateway", jsonutils.NewString(newGateway))
|
||||
}
|
||||
if len(ip6Mask) > 0 {
|
||||
taskData.Set("ip6_mask", jsonutils.NewString(ip6Mask))
|
||||
taskData.Set("gateway6", jsonutils.NewString(networkJsonDesc.Gateway6))
|
||||
}
|
||||
|
||||
if self.Status == api.VM_BLOCK_STREAM {
|
||||
taskData.Set("in_block_stream", jsonutils.JSONTrue)
|
||||
}
|
||||
|
||||
@@ -502,11 +502,12 @@ func fetchGuestIPs(guestIds []string, virtual tristate.TriState) map[string][]st
|
||||
func fetchGuestVips(guestIds []string) map[string][]string {
|
||||
groupguests := GroupguestManager.Query().SubQuery()
|
||||
groupnetworks := GroupnetworkManager.Query().SubQuery()
|
||||
q := groupnetworks.Query(groupnetworks.Field("ip_addr"), groupguests.Field("guest_id"))
|
||||
q := groupnetworks.Query(groupnetworks.Field("ip_addr"), groupnetworks.Field("ip6_addr"), groupguests.Field("guest_id"))
|
||||
q = q.Join(groupguests, sqlchemy.Equals(q.Field("group_id"), groupguests.Field("group_id")))
|
||||
q = q.In("guest_id", guestIds)
|
||||
type sGuestVip struct {
|
||||
IpAddr string
|
||||
Ip6Addr string
|
||||
GuestId string
|
||||
}
|
||||
gvips := make([]sGuestVip, 0)
|
||||
@@ -519,7 +520,12 @@ func fetchGuestVips(guestIds []string) map[string][]string {
|
||||
if _, ok := ret[gvips[i].GuestId]; !ok {
|
||||
ret[gvips[i].GuestId] = make([]string, 0)
|
||||
}
|
||||
ret[gvips[i].GuestId] = append(ret[gvips[i].GuestId], gvips[i].IpAddr)
|
||||
if len(gvips[i].IpAddr) > 0 {
|
||||
ret[gvips[i].GuestId] = append(ret[gvips[i].GuestId], gvips[i].IpAddr)
|
||||
}
|
||||
if len(gvips[i].Ip6Addr) > 0 {
|
||||
ret[gvips[i].GuestId] = append(ret[gvips[i].GuestId], gvips[i].Ip6Addr)
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
@@ -434,6 +434,10 @@ func (manager *SGuestnetworkManager) newGuestNetwork(
|
||||
gn.IsDefault = isDefault
|
||||
}
|
||||
|
||||
if len(gn.Ip6Addr) > 0 && len(gn.IpAddr) == 0 {
|
||||
gn.NumQueues = 1
|
||||
}
|
||||
|
||||
err = manager.TableSpec().Insert(ctx, &gn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -2953,9 +2953,11 @@ func (self *SGuest) GetRealIPs() []string {
|
||||
|
||||
func (self *SGuest) IsExitOnly() bool {
|
||||
for _, ip := range self.GetRealIPs() {
|
||||
addr, _ := netutils.NewIPV4Addr(ip)
|
||||
if !netutils.IsExitAddress(addr) {
|
||||
return false
|
||||
if regutils.MatchIP4Addr(ip) {
|
||||
addr, _ := netutils.NewIPV4Addr(ip)
|
||||
if !netutils.IsExitAddress(addr) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
@@ -2970,7 +2972,12 @@ func (self *SGuest) getVirtualIPs() []string {
|
||||
continue
|
||||
}
|
||||
for _, groupnetwork := range groupnets {
|
||||
ips = append(ips, groupnetwork.IpAddr)
|
||||
if len(groupnetwork.IpAddr) > 0 {
|
||||
ips = append(ips, groupnetwork.IpAddr)
|
||||
}
|
||||
if len(groupnetwork.Ip6Addr) > 0 {
|
||||
ips = append(ips, groupnetwork.Ip6Addr)
|
||||
}
|
||||
}
|
||||
}
|
||||
return ips
|
||||
@@ -2979,13 +2986,15 @@ func (self *SGuest) getVirtualIPs() []string {
|
||||
func (self *SGuest) GetPrivateIPs() []string {
|
||||
ips := self.GetRealIPs()
|
||||
for i := len(ips) - 1; i >= 0; i-- {
|
||||
ipAddr, err := netutils.NewIPV4Addr(ips[i])
|
||||
if err != nil {
|
||||
log.Errorf("guest %s(%s) has bad ipv4 address (%s): %v", self.Name, self.Id, ips[i], err)
|
||||
continue
|
||||
}
|
||||
if !netutils.IsPrivate(ipAddr) {
|
||||
ips = append(ips[:i], ips[i+1:]...)
|
||||
if regutils.MatchIP4Addr(ips[i]) {
|
||||
ipAddr, err := netutils.NewIPV4Addr(ips[i])
|
||||
if err != nil {
|
||||
log.Errorf("guest %s(%s) has bad ipv4 address (%s): %v", self.Name, self.Id, ips[i], err)
|
||||
continue
|
||||
}
|
||||
if !netutils.IsPrivate(ipAddr) {
|
||||
ips = append(ips[:i], ips[i+1:]...)
|
||||
}
|
||||
}
|
||||
}
|
||||
return ips
|
||||
|
||||
@@ -45,26 +45,28 @@ func (self *GuestQgaRestartNetworkTask) OnRestartNetwork(ctx context.Context, gu
|
||||
device, _ := self.Params.GetString("device")
|
||||
ipMask, _ := self.Params.GetString("ip_mask")
|
||||
gateway, _ := self.Params.GetString("gateway")
|
||||
prevIp, _ := self.Params.GetString("prev_ip")
|
||||
inBlockStream, _ := self.Params.Bool("in_block_stream")
|
||||
ip6Mask, _ := self.Params.GetString("ip6_mask")
|
||||
gateway6, _ := self.Params.GetString("gateway6")
|
||||
|
||||
_, err := self.requestSetNetwork(ctx, guest, device, ipMask, gateway)
|
||||
_, err := self.requestSetNetwork(ctx, guest, device, ipMask, gateway, ip6Mask, gateway6)
|
||||
if err != nil {
|
||||
logclient.AddActionLogWithStartable(self, guest, logclient.ACT_RESTART_NETWORK, err, self.UserCred, false)
|
||||
self.taskFailed(ctx, guest, prevIp, inBlockStream, err)
|
||||
self.taskFailed(ctx, guest, err)
|
||||
}
|
||||
}
|
||||
|
||||
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, ipMask, gateway, ip6Mask, gateway6 string) (jsonutils.JSONObject, error) {
|
||||
host, err := guest.GetHost()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, guest, "", false, err)
|
||||
self.taskFailed(ctx, guest, err)
|
||||
return nil, err
|
||||
}
|
||||
inputQgaNet := &api.ServerQgaSetNetworkInput{
|
||||
Device: device,
|
||||
Ipmask: ipMask,
|
||||
Gateway: gateway,
|
||||
Device: device,
|
||||
Ipmask: ipMask,
|
||||
Gateway: gateway,
|
||||
Ip6mask: ip6Mask,
|
||||
Gateway6: gateway6,
|
||||
}
|
||||
|
||||
// if success, log network related information
|
||||
@@ -85,12 +87,10 @@ func (self *GuestQgaRestartNetworkTask) OnSetNetwork(ctx context.Context, guest
|
||||
}
|
||||
|
||||
func (self *GuestQgaRestartNetworkTask) OnSetNetworkFailed(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
|
||||
prevIp, _ := self.Params.GetString("prev_ip")
|
||||
inBlockStream, _ := self.Params.Bool("in_block_stream")
|
||||
self.taskFailed(ctx, guest, prevIp, inBlockStream, errors.Errorf(data.String()))
|
||||
self.taskFailed(ctx, guest, errors.Errorf(data.String()))
|
||||
}
|
||||
|
||||
func (self *GuestQgaRestartNetworkTask) taskFailed(ctx context.Context, guest *models.SGuest, prevIp string, inBlockStream bool, err error) {
|
||||
func (self *GuestQgaRestartNetworkTask) taskFailed(ctx context.Context, guest *models.SGuest, err error) {
|
||||
guest.SetStatus(ctx, self.GetUserCred(), api.VM_QGA_SET_NETWORK_FAILED, err.Error())
|
||||
logclient.AddActionLogWithStartable(self, guest, logclient.ACT_RESTART_NETWORK, jsonutils.NewString(err.Error()), self.UserCred, false)
|
||||
self.SetStageFailed(ctx, nil)
|
||||
|
||||
@@ -75,24 +75,20 @@ func (self *GuestSyncConfTask) OnSyncComplete(ctx context.Context, obj db.IStand
|
||||
|
||||
func (self *GuestSyncConfTask) StartRestartNetworkTask(ctx context.Context, guest *models.SGuest) {
|
||||
defer self.SetStageComplete(ctx, guest.GetShortDesc(ctx))
|
||||
prevIp, err := self.Params.GetString("prev_ip")
|
||||
if err != nil {
|
||||
log.Errorf("unable to get prev_ip when restart_network is true when sync guest")
|
||||
return
|
||||
}
|
||||
inBlockStream := jsonutils.QueryBoolean(self.Params, "in_block_stream", false)
|
||||
preMac, err := self.Params.GetString("prev_mac")
|
||||
if err != nil {
|
||||
log.Errorf("unable to get prev_mac when restart_network is true when sync guest")
|
||||
return
|
||||
}
|
||||
ipMask, err := self.Params.GetString("ip_mask")
|
||||
if err != nil {
|
||||
gateway, err := self.Params.GetString("gateway")
|
||||
ip6Mask, err := self.Params.GetString("ip6_mask")
|
||||
gateway6, err := self.Params.GetString("gateway6")
|
||||
if ipMask == "" && ip6Mask == "" {
|
||||
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 {
|
||||
if gateway == "" && gateway6 == "" {
|
||||
log.Errorf("unable to get gateway when restart_network is true when sync guest")
|
||||
return
|
||||
}
|
||||
@@ -128,8 +124,7 @@ func (self *GuestSyncConfTask) StartRestartNetworkTask(ctx context.Context, gues
|
||||
// wait for vpcagent sync network topo
|
||||
time.Sleep(10 * time.Second)
|
||||
}
|
||||
return guest.StartQgaRestartNetworkTask(
|
||||
ctx, self.UserCred, "", ifnameDevice, ipMask, gateway, prevIp, inBlockStream)
|
||||
return guest.StartQgaRestartNetworkTask(ctx, self.UserCred, "", ifnameDevice, ipMask, gateway, ip6Mask, gateway6)
|
||||
}()
|
||||
if err != nil {
|
||||
log.Errorf("guest %s failed start qga restart network task: %s", guest.GetName(), err)
|
||||
|
||||
@@ -53,7 +53,7 @@ func (self *SecurityGroupCreateTask) OnInit(ctx context.Context, obj db.IStandal
|
||||
}
|
||||
|
||||
rules := api.SSecgroupRuleResourceSet{}
|
||||
self.GetParams().Unmarshal(&rules)
|
||||
self.GetParams().Unmarshal(&rules, "rules")
|
||||
|
||||
driver := region.GetDriver()
|
||||
err = driver.RequestCreateSecurityGroup(ctx, self.GetUserCred(), secgroup, rules)
|
||||
|
||||
@@ -458,6 +458,26 @@ func (l *sLinuxRootFs) DeployNetworkingScripts(rootFs IDiskPartition, nics []*ty
|
||||
log.Errorf("rootFs.GenerateSshHostKeys fail %s", err)
|
||||
}
|
||||
}
|
||||
{
|
||||
// deploy /etc/gai.conf if both IPv4 and IPv6 are enabled
|
||||
v4Enabled := false
|
||||
v6Enabled := false
|
||||
for _, nic := range nics {
|
||||
if nic.Ip != "" {
|
||||
v4Enabled = true
|
||||
}
|
||||
if nic.Ip6 != "" {
|
||||
v6Enabled = true
|
||||
}
|
||||
if v4Enabled && v6Enabled {
|
||||
// prefer IPv4 over IPv6 by default of /etc/gai.conf not present
|
||||
if !rootFs.Exists("/etc/gai.conf", false) {
|
||||
rootFs.FilePutContents("/etc/gai.conf", "precedence ::ffff:0:0/96 100\n", false, false)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -103,9 +103,11 @@ func (m *SGuestManager) QgaGuestInfoTask(sid string) (string, error) {
|
||||
func (m *SGuestManager) QgaSetNetwork(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
|
||||
input := params.(*SQgaGuestSetNetwork)
|
||||
netmod := &monitor.NetworkModify{
|
||||
Device: input.Device,
|
||||
Ipmask: input.Ipmask,
|
||||
Gateway: input.Gateway,
|
||||
Device: input.Device,
|
||||
Ipmask: input.Ipmask,
|
||||
Gateway: input.Gateway,
|
||||
Ip6mask: input.Ip6mask,
|
||||
Gateway6: input.Gateway6,
|
||||
}
|
||||
|
||||
guest, err := m.checkAndInitGuestQga(input.Sid)
|
||||
|
||||
@@ -995,18 +995,20 @@ func qgaSetNetwork(ctx context.Context, userCred mcclient.TokenCredential, sid s
|
||||
if input.Device == "" {
|
||||
return nil, httperrors.NewMissingParameterError("device")
|
||||
}
|
||||
if input.Ipmask == "" {
|
||||
if input.Ipmask == "" && input.Ip6mask == "" {
|
||||
return nil, httperrors.NewMissingParameterError("ipmask")
|
||||
}
|
||||
if input.Gateway == "" {
|
||||
if input.Gateway == "" && input.Gateway6 == "" {
|
||||
return nil, httperrors.NewMissingParameterError("gateway")
|
||||
}
|
||||
|
||||
hostutils.DelayTask(ctx, guestman.GetGuestManager().QgaSetNetwork, &guestman.SQgaGuestSetNetwork{
|
||||
Sid: sid,
|
||||
Device: input.Device,
|
||||
Ipmask: input.Ipmask,
|
||||
Gateway: input.Gateway,
|
||||
Sid: sid,
|
||||
Device: input.Device,
|
||||
Ipmask: input.Ipmask,
|
||||
Gateway: input.Gateway,
|
||||
Ip6mask: input.Ip6mask,
|
||||
Gateway6: input.Gateway6,
|
||||
})
|
||||
|
||||
return nil, nil
|
||||
|
||||
@@ -214,11 +214,13 @@ type SQgaGuestSetPassword struct {
|
||||
}
|
||||
|
||||
type SQgaGuestSetNetwork struct {
|
||||
Timeout int
|
||||
Sid string
|
||||
Device string
|
||||
Ipmask string
|
||||
Gateway string
|
||||
Timeout int
|
||||
Sid string
|
||||
Device string
|
||||
Ipmask string
|
||||
Gateway string
|
||||
Ip6mask string
|
||||
Gateway6 string
|
||||
}
|
||||
|
||||
type CpuSetCounter struct {
|
||||
|
||||
@@ -634,10 +634,15 @@ func (n *SGuestNetworkSyncTask) Start(callback func(...error)) {
|
||||
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,
|
||||
})
|
||||
netMod := &monitor.NetworkModify{}
|
||||
if len(n.addNics[i].Ip) > 0 {
|
||||
netMod.Ipmask = fmt.Sprintf("%s/%d", n.addNics[i].Ip, n.addNics[i].Masklen)
|
||||
netMod.Gateway = n.addNics[i].Gateway
|
||||
}
|
||||
if len(n.addNics[i].Ip6) > 0 {
|
||||
netMod.Ip6mask = fmt.Sprintf("%s/%d", n.addNics[i].Ip6, n.addNics[i].Masklen6)
|
||||
}
|
||||
addNicConfs = append(addNicConfs, netMod)
|
||||
}
|
||||
n.addNicMacs = addNicMacs
|
||||
n.addNicConfs = addNicConfs
|
||||
|
||||
@@ -523,6 +523,29 @@ func ParseIPAndSubnet(input string) (string, string, error) {
|
||||
return ip, subnetMask, nil
|
||||
}
|
||||
|
||||
func ParseIP6AndSubnet(input string) (string, string, error) {
|
||||
//Converting IP/MASK format to IP and MASK
|
||||
parts := strings.Split(input, "/")
|
||||
if len(parts) != 2 {
|
||||
return "", "", fmt.Errorf("Invalid input format")
|
||||
}
|
||||
|
||||
ip := parts[0]
|
||||
subnetSizeStr := parts[1]
|
||||
|
||||
subnetSize := 0
|
||||
for _, c := range subnetSizeStr {
|
||||
if c < '0' || c > '9' {
|
||||
return "", "", fmt.Errorf("Invalid subnet size")
|
||||
}
|
||||
subnetSize = subnetSize*10 + int(c-'0')
|
||||
}
|
||||
|
||||
mask := net.CIDRMask(subnetSize, 32)
|
||||
subnetMask := net.IP(mask).To16().String()
|
||||
return ip, subnetMask, nil
|
||||
}
|
||||
|
||||
func (qga *QemuGuestAgent) QgaAddFileExec(filePath string) error {
|
||||
//Adding execution permissions to file
|
||||
shellAddAuth := "chmod +x " + filePath
|
||||
@@ -545,15 +568,35 @@ func (qga *QemuGuestAgent) QgaAddFileExec(filePath string) error {
|
||||
}
|
||||
|
||||
func (qga *QemuGuestAgent) QgaSetWindowsNetwork(qgaNetMod *monitor.NetworkModify) error {
|
||||
ip, subnetMask, err := ParseIPAndSubnet(qgaNetMod.Ipmask)
|
||||
if err != nil {
|
||||
return err
|
||||
var ip, ip6, mask, mask6 string
|
||||
var err error
|
||||
var networkCmd string
|
||||
|
||||
if len(qgaNetMod.Ipmask) > 0 {
|
||||
ip, mask, err = ParseIPAndSubnet(qgaNetMod.Ipmask)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
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\" dhcp",
|
||||
qgaNetMod.Device, ip, mask, qgaNetMod.Gateway, qgaNetMod.Device,
|
||||
)
|
||||
}
|
||||
if len(qgaNetMod.Ip6mask) > 0 {
|
||||
ip6, mask6, err = ParseIP6AndSubnet(qgaNetMod.Ip6mask)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if networkCmd != "" {
|
||||
networkCmd += " & "
|
||||
}
|
||||
networkCmd += fmt.Sprintf("netsh interface ipv6 set address interface=\"%s\" address=%s/%s & "+
|
||||
"netsh interface ipv6 add route ::/0 interface=\"%s\" %s & "+
|
||||
"netsh interface ipv6 set address interface=\"%s\" source=dhcp",
|
||||
qgaNetMod.Device, ip6, mask6, qgaNetMod.Device, qgaNetMod.Gateway6, qgaNetMod.Device,
|
||||
)
|
||||
}
|
||||
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\" dhcp",
|
||||
qgaNetMod.Device, ip, subnetMask, qgaNetMod.Gateway, qgaNetMod.Device,
|
||||
)
|
||||
|
||||
log.Infof("networkCmd: %s", networkCmd)
|
||||
arg := []string{"/C", networkCmd}
|
||||
|
||||
@@ -82,9 +82,11 @@ type Command struct {
|
||||
}
|
||||
|
||||
type NetworkModify struct {
|
||||
Device string `json:"device"`
|
||||
Ipmask string `json:"ipmask"`
|
||||
Gateway string `json:"gateway"`
|
||||
Device string `json:"device"`
|
||||
Ipmask string `json:"ipmask"`
|
||||
Gateway string `json:"gateway"`
|
||||
Ip6mask string `json:"ip6mask"`
|
||||
Gateway6 string `json:"gateway6"`
|
||||
}
|
||||
|
||||
type Version struct {
|
||||
|
||||
@@ -313,11 +313,15 @@ func optionsToBytes(opts []Option6) []byte {
|
||||
}
|
||||
|
||||
func (p Packet) GetOption6s() []Option6 {
|
||||
options := make([]Option6, 0)
|
||||
offset := 4
|
||||
if p.IsRelayMsg() {
|
||||
offset = 16*2 + 2
|
||||
}
|
||||
return decodeDHCP6Options(p, offset)
|
||||
}
|
||||
|
||||
func decodeDHCP6Options(p []byte, offset int) []Option6 {
|
||||
options := make([]Option6, 0)
|
||||
i := offset
|
||||
for i < len(p) {
|
||||
code := binary.BigEndian.Uint16(p[i : i+2])
|
||||
@@ -378,28 +382,137 @@ func makeIAAddr(ip net.IP, preferLT, validLT uint32, opts []Option6) []byte {
|
||||
return buf
|
||||
}
|
||||
|
||||
func responseIANA(buf []byte, opts []Option6) []byte {
|
||||
func decodeIAAddr(buf []byte) (net.IP, uint32, uint32, []Option6) {
|
||||
ipBuf := make([]byte, 16)
|
||||
copy(ipBuf, buf[0:16])
|
||||
ip := net.IP(ipBuf)
|
||||
preferLT := binary.BigEndian.Uint32(buf[16:20])
|
||||
validLT := binary.BigEndian.Uint32(buf[20:24])
|
||||
opts := decodeDHCP6Options(buf, 24)
|
||||
return ip, preferLT, validLT, opts
|
||||
}
|
||||
|
||||
/*
|
||||
+---------------+------+--------------------------------------------+
|
||||
| Name | Code | Description |
|
||||
+---------------+------+--------------------------------------------+
|
||||
| Success | 0 | Success. |
|
||||
| | | |
|
||||
| UnspecFail | 1 | Failure, reason unspecified; this status |
|
||||
| | | code is sent by either a client or a |
|
||||
| | | server to indicate a failure not |
|
||||
| | | explicitly specified in this document. |
|
||||
| | | |
|
||||
| NoAddrsAvail | 2 | The server has no addresses available to |
|
||||
| | | assign to the IA(s). |
|
||||
| | | |
|
||||
| NoBinding | 3 | Client record (binding) unavailable. |
|
||||
| | | |
|
||||
| NotOnLink | 4 | The prefix for the address is not |
|
||||
| | | appropriate for the link to which the |
|
||||
| | | client is attached. |
|
||||
| | | |
|
||||
| UseMulticast | 5 | Sent by a server to a client to force the |
|
||||
| | | client to send messages to the server |
|
||||
| | | using the |
|
||||
| | | All_DHCP_Relay_Agents_and_Servers |
|
||||
| | | multicast address. |
|
||||
| | | |
|
||||
| NoPrefixAvail | 6 | The server has no prefixes available to |
|
||||
| | | assign to the IA_PD(s). |
|
||||
+---------------+------+--------------------------------------------+
|
||||
*/
|
||||
type DHCP6StatusCode uint16
|
||||
|
||||
const (
|
||||
Dhcp6StatusSuccess DHCP6StatusCode = 0
|
||||
Dhcp6StatusUnspecFail DHCP6StatusCode = 1
|
||||
Dhcp6StatusNoAddrsAvail DHCP6StatusCode = 2
|
||||
Dhcp6StatusNoBinding DHCP6StatusCode = 3
|
||||
Dhcp6StatusNotOnLink DHCP6StatusCode = 4
|
||||
Dhcp6StatusUseMulticast DHCP6StatusCode = 5
|
||||
Dhcp6StatusNoPrefixAvail DHCP6StatusCode = 6
|
||||
)
|
||||
|
||||
func (code DHCP6StatusCode) Encode() []byte {
|
||||
var msg string
|
||||
switch code {
|
||||
case Dhcp6StatusSuccess:
|
||||
msg = "Success"
|
||||
case Dhcp6StatusUnspecFail:
|
||||
msg = "UnspecFail"
|
||||
case Dhcp6StatusNoAddrsAvail:
|
||||
msg = "NoAddrsAvail"
|
||||
case Dhcp6StatusNoBinding:
|
||||
msg = "NoBinding"
|
||||
case Dhcp6StatusNotOnLink:
|
||||
msg = "NotOnLink"
|
||||
case Dhcp6StatusUseMulticast:
|
||||
msg = "UseMulticast"
|
||||
case Dhcp6StatusNoPrefixAvail:
|
||||
msg = "NoPrefixAvail"
|
||||
}
|
||||
buf := make([]byte, 2)
|
||||
binary.BigEndian.PutUint16(buf, uint16(code))
|
||||
buf = append(buf, []byte(msg)...)
|
||||
return buf
|
||||
}
|
||||
|
||||
func responseIANA(buf []byte, ip net.IP, preferLT, validLT uint32) ([]byte, DHCP6StatusCode) {
|
||||
// IA_NA structure: IAID (4 bytes) + T1 (4 bytes) + T2 (4 bytes)
|
||||
// Preserve the original IAID, T1, and T2 values from the client request
|
||||
opts := make([]Option6, 0)
|
||||
status := Dhcp6StatusSuccess
|
||||
resp := make([]byte, 12)
|
||||
if len(buf) < 12 {
|
||||
copy(resp, buf)
|
||||
// If buffer is too short, pad with zeros
|
||||
padding := make([]byte, 12-len(buf))
|
||||
buf = append(buf, padding...)
|
||||
} else if len(buf) > 12 {
|
||||
// If buffer is too long, truncate to 12 bytes (IAID + T1 + T2)
|
||||
buf = buf[:12]
|
||||
}
|
||||
|
||||
// Log the IA_NA parameters for debugging
|
||||
if len(buf) >= 12 {
|
||||
// padding := make([]byte, 12-len(buf))
|
||||
// copy(resp[len(buf):], padding)
|
||||
} else {
|
||||
// Log the IA_NA parameters for debugging
|
||||
iaID := binary.BigEndian.Uint32(buf[0:4])
|
||||
t1 := binary.BigEndian.Uint32(buf[4:8])
|
||||
t2 := binary.BigEndian.Uint32(buf[8:12])
|
||||
log.Debugf("responseIANA IA_NA IAID %d t1 %d t2 %d", iaID, t1, t2)
|
||||
if len(buf) > 12 {
|
||||
iaOpts := decodeDHCP6Options(buf, 12)
|
||||
for i := range iaOpts {
|
||||
if iaOpts[i].Code == DHCPV6_OPTION_IAADDR {
|
||||
oldIp, oldPreferLT, oldValidLT, _ := decodeIAAddr(iaOpts[i].Value)
|
||||
if !oldIp.Equal(ip) {
|
||||
// send NotOnLink
|
||||
opts = append(opts, Option6{
|
||||
Code: DHCPV6_OPTION_IAADDR,
|
||||
Value: makeIAAddr(oldIp, oldPreferLT, oldValidLT, []Option6{
|
||||
{
|
||||
Code: DHCPV6_OPTION_STATUS_CODE,
|
||||
Value: Dhcp6StatusNotOnLink.Encode(),
|
||||
},
|
||||
}),
|
||||
})
|
||||
if status == Dhcp6StatusSuccess {
|
||||
status = Dhcp6StatusNotOnLink
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
copy(resp, buf[:12])
|
||||
}
|
||||
|
||||
buf = append(buf, optionsToBytes(opts)...)
|
||||
return buf
|
||||
opts = append(opts, Option6{
|
||||
Code: DHCPV6_OPTION_IAADDR,
|
||||
Value: makeIAAddr(ip, preferLT, validLT, []Option6{
|
||||
{
|
||||
Code: DHCPV6_OPTION_STATUS_CODE,
|
||||
Value: Dhcp6StatusSuccess.Encode(),
|
||||
},
|
||||
}),
|
||||
})
|
||||
|
||||
resp = append(resp, optionsToBytes(opts)...)
|
||||
return resp, status
|
||||
}
|
||||
|
||||
func makeIPv6s(ips []net.IP) []byte {
|
||||
@@ -473,19 +586,11 @@ func makeDHCPReplyPacket6(pkt Packet, conf *ResponseConfig, msgType MessageType)
|
||||
validLifetime := uint32(conf.LeaseTime.Seconds()) // Valid lifetime should be longer than preferred
|
||||
preferredLifetime := validLifetime / 2
|
||||
|
||||
ianaResp, status := responseIANA(ianaOpt.Value, conf.ClientIP6, preferredLifetime, validLifetime)
|
||||
|
||||
options = append(options, Option6{
|
||||
Code: DHCPV6_OPTION_IA_NA,
|
||||
Value: responseIANA(ianaOpt.Value, []Option6{
|
||||
{
|
||||
Code: DHCPV6_OPTION_IAADDR,
|
||||
Value: makeIAAddr(conf.ClientIP6, preferredLifetime, validLifetime, []Option6{
|
||||
{
|
||||
Code: DHCPV6_OPTION_STATUS_CODE,
|
||||
Value: []byte{0, 0, 'S', 'u', 'c', 'c', 'e', 's', 's'},
|
||||
},
|
||||
}),
|
||||
},
|
||||
}),
|
||||
Code: DHCPV6_OPTION_IA_NA,
|
||||
Value: ianaResp,
|
||||
})
|
||||
|
||||
if len(conf.DNSServers6) > 0 {
|
||||
@@ -514,6 +619,11 @@ func makeDHCPReplyPacket6(pkt Packet, conf *ResponseConfig, msgType MessageType)
|
||||
}
|
||||
}
|
||||
|
||||
options = append(options, Option6{
|
||||
Code: DHCPV6_OPTION_STATUS_CODE,
|
||||
Value: status.Encode(),
|
||||
})
|
||||
|
||||
resp := NewPacket6(msgType, tid)
|
||||
resp = append(resp, optionsToBytes(options)...)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user