diff --git a/pkg/compute/models/guestnetworks.go b/pkg/compute/models/guestnetworks.go index 01dde8acaf..9799e8f09f 100644 --- a/pkg/compute/models/guestnetworks.go +++ b/pkg/compute/models/guestnetworks.go @@ -344,7 +344,8 @@ func (manager *SGuestnetworkManager) newGuestNetwork( return nil, errors.Wrap(err, "GetFreeIPv4") } if len(address) > 0 && ipAddr != address && requiredDesignatedIp { - return nil, errors.Wrapf(httperrors.ErrConflict, "candidate ip %s is occupied!", address) + usedAddr, _ := network.GetUsedAddressDetails(ctx, address) + return nil, errors.Wrapf(httperrors.ErrConflict, "candidate ip %s is occupied with %#v!", address, usedAddr) } gn.IpAddr = ipAddr } @@ -398,7 +399,8 @@ func (manager *SGuestnetworkManager) newGuestNetwork( return nil, errors.Wrap(err, "GetFreeIPv6") } if len(address6) > 0 && ip6Addr != address6 && !derived && requiredDesignatedIp { - return nil, errors.Wrapf(httperrors.ErrConflict, "candidate v6 ip %s is occupied!", address6) + usedAddr, _ := network.GetUsedAddressDetails(ctx, address6) + return nil, errors.Wrapf(httperrors.ErrConflict, "candidate v6 ip %s is occupied with %#v!", address6, usedAddr) } gn.Ip6Addr = ip6Addr } diff --git a/pkg/compute/models/networks.go b/pkg/compute/models/networks.go index 291bcbc16a..353dc4dd3f 100644 --- a/pkg/compute/models/networks.go +++ b/pkg/compute/models/networks.go @@ -3458,19 +3458,38 @@ func (network *SNetwork) GetDetailsAddresses( return output, nil } +func (network *SNetwork) GetUsedAddressDetails(ctx context.Context, addr string) (*api.SNetworkUsedAddress, error) { + address, err := network.GetAddressDetails(ctx, nil, nil, rbacscope.ScopeSystem) + if err != nil { + return nil, errors.Wrapf(err, "GetAddressDetails") + } + for i := range address { + if address[i].IpAddr == addr || address[i].Ip6Addr == addr { + return &address[i], nil + } + } + return nil, errors.Wrapf(errors.ErrNotFound, addr) +} + +func (network *SNetwork) GetAddressDetails(ctx context.Context, userCred mcclient.TokenCredential, owner mcclient.IIdentityProvider, scope rbacscope.TRbacScope) ([]api.SNetworkUsedAddress, error) { + netAddrs := make([]api.SNetworkUsedAddress, 0) + q := network.getUsedAddressQuery(ctx, userCred, owner, scope, false) + err := q.All(&netAddrs) + if err != nil { + return nil, httperrors.NewGeneralError(err) + } + sort.Sort(SNetworkUsedAddressList(netAddrs)) + return netAddrs, nil +} + func (network *SNetwork) fetchAddressDetails(ctx context.Context, userCred mcclient.TokenCredential, owner mcclient.IIdentityProvider, scope rbacscope.TRbacScope) (api.GetNetworkAddressesOutput, error) { output := api.GetNetworkAddressesOutput{} { - netAddrs := make([]api.SNetworkUsedAddress, 0) - q := network.getUsedAddressQuery(ctx, userCred, owner, scope, false) - err := q.All(&netAddrs) + var err error + output.Addresses, err = network.GetAddressDetails(ctx, userCred, owner, scope) if err != nil { - return output, httperrors.NewGeneralError(err) + return output, err } - - sort.Sort(SNetworkUsedAddressList(netAddrs)) - - output.Addresses = netAddrs } { netAddrs6 := make([]api.SNetworkUsedAddress, 0)