diff --git a/pkg/compute/guestdrivers/virtualization.go b/pkg/compute/guestdrivers/virtualization.go index 0deabc5590..407c6db0a6 100644 --- a/pkg/compute/guestdrivers/virtualization.go +++ b/pkg/compute/guestdrivers/virtualization.go @@ -209,6 +209,7 @@ func (self *SVirtualizedGuestDriver) Attach2RandomNetwork(guest *models.SGuest, AllocDir: api.IPAllocationDefault, RequireDesignatedIP: netConfig.RequireDesignatedIP, RequireIPv6: netConfig.RequireIPv6, + StrictIPv6: netConfig.StrictIPv6, NicConfs: nicConfs, IsDefault: netConfig.IsDefault, diff --git a/pkg/compute/models/guest_actions.go b/pkg/compute/models/guest_actions.go index cbdc9f4082..1b7724d871 100644 --- a/pkg/compute/models/guest_actions.go +++ b/pkg/compute/models/guest_actions.go @@ -2630,7 +2630,7 @@ func (self *SGuest) PerformChangeIpaddr( if err != nil { return nil, httperrors.NewInputParameterError("parseNetworkInfo fail: %s", err) } - if len(gn.IpAddr) == 0 && len(conf.Address) > 0 { + if conf.StrictIPv6 && len(conf.Address) > 0 { // strict ipv6 network, can't add ipv4 address return nil, httperrors.NewBadRequestError("guest network has no ipv4 address") } @@ -2639,7 +2639,16 @@ func (self *SGuest) PerformChangeIpaddr( // 允许IPv4地址不变,只改IPv6地址 reuseV4 = conf.Address } - err = isValidNetworkInfo(ctx, userCred, conf, reuseV4) + reuseV6 := "" + if gn.Ip6Addr != "" && conf.Address6 != "" { + inputIP := net.ParseIP(conf.Address6) + gnIP := net.ParseIP(gn.Ip6Addr) + if string(inputIP) == string(gnIP) { + conf.Address6 = gn.Ip6Addr + reuseV6 = gn.Ip6Addr + } + } + err = isValidNetworkInfo(ctx, userCred, conf, reuseV4, reuseV6) if err != nil { return nil, httperrors.NewInputParameterError("isValidNetworkInfo fail: %s", err) } @@ -2690,7 +2699,9 @@ func (self *SGuest) PerformChangeIpaddr( // reserve = true } - if len(conf.Address) == 0 || conf.Address != gn.IpAddr { + if conf.StrictIPv6 { + conf.Address = "" + } else if len(conf.Address) == 0 || conf.Address != gn.IpAddr { // need to allocate new address addr4, err := targetNetwork.GetFreeIP(ctx, userCred, nil, nil, conf.Address, api.IPAllocationDirection(targetNetwork.AllocPolicy), reserve, api.AddressTypeIPv4) if err != nil { @@ -2745,6 +2756,9 @@ func (self *SGuest) PerformChangeIpaddr( 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) + } notes := gn.GetShortDesc(ctx) if gn != nil { @@ -2978,7 +2992,7 @@ func (self *SGuest) PerformAttachnetwork( } var inicCnt, enicCnt, isolatedDevCount, defaultGwCnt int for i := range input.Nets { - err := isValidNetworkInfo(ctx, userCred, input.Nets[i], "") + err := isValidNetworkInfo(ctx, userCred, input.Nets[i], "", "") if err != nil { return nil, err } diff --git a/pkg/compute/models/guests.go b/pkg/compute/models/guests.go index 136c277b40..d36c9d9845 100644 --- a/pkg/compute/models/guests.go +++ b/pkg/compute/models/guests.go @@ -2025,7 +2025,7 @@ func (manager *SGuestManager) validateCreateData( if err != nil { return nil, httperrors.NewInputParameterError("parse network description error %s", err) } - err = isValidNetworkInfo(ctx, userCred, netConfig, "") + err = isValidNetworkInfo(ctx, userCred, netConfig, "", "") if err != nil { return nil, err } diff --git a/pkg/compute/models/networks.go b/pkg/compute/models/networks.go index d96bbe1c72..2fc19facea 100644 --- a/pkg/compute/models/networks.go +++ b/pkg/compute/models/networks.go @@ -1106,7 +1106,7 @@ func (snet *SNetwork) getFreeAddressCount() (int, error) { return snet.GetTotalAddressCount() - used, nil } -func isValidNetworkInfo(ctx context.Context, userCred mcclient.TokenCredential, netConfig *api.NetworkConfig, reuseAddr string) error { +func isValidNetworkInfo(ctx context.Context, userCred mcclient.TokenCredential, netConfig *api.NetworkConfig, reuseAddr, reuseAddr6 string) error { if len(netConfig.Network) > 0 { netObj, err := NetworkManager.FetchByIdOrName(ctx, userCred, netConfig.Network) if err != nil { @@ -1169,7 +1169,7 @@ func isValidNetworkInfo(ctx context.Context, userCred mcclient.TokenCredential, if err != nil { return httperrors.NewInternalServerError("isAddress6Used fail %s", err) } - if used { + if used && netConfig.Address6 != reuseAddr6 { return httperrors.NewInputParameterError("v6 address %s has been used", netConfig.Address6) } } @@ -1845,7 +1845,7 @@ func (manager *SNetworkManager) ValidateCreateData(ctx context.Context, userCred if vpc.Id != api.DEFAULT_VPC_ID { // require prefix - if len(input.GuestIpPrefix) == 0 { + if len(input.GuestIpPrefix) == 0 && len(input.GuestIp6Start) > 0 && len(input.GuestIp6End) > 0 { return input, errors.Wrap(httperrors.ErrInputParameter, "guest_ip_prefix is required") } if len(input.GuestIp6Prefix) == 0 && len(input.GuestIp6Start) > 0 && len(input.GuestIp6End) > 0 {