diff --git a/go.mod b/go.mod index 15681a9122..ecd81b2a1e 100644 --- a/go.mod +++ b/go.mod @@ -103,7 +103,7 @@ require ( yunion.io/x/ovsdb v0.0.0-20230306173834-f164f413a900 yunion.io/x/pkg v1.10.4-0.20250805171825-2431e10f90a9 yunion.io/x/s3cli v0.0.0-20241221171442-1c11599d28e1 - yunion.io/x/sqlchemy v1.1.3-0.20250531010554-ce98f840b833 + yunion.io/x/sqlchemy v1.1.3-0.20250806073422-e37f5197cec0 yunion.io/x/structarg v0.0.0-20231017124457-df4d5009457c ) diff --git a/go.sum b/go.sum index 587c6f89c2..da5127a93d 100644 --- a/go.sum +++ b/go.sum @@ -1427,7 +1427,7 @@ yunion.io/x/pkg v1.10.4-0.20250805171825-2431e10f90a9 h1:8NuoKUPb3sHigChE6Mz6Nf9 yunion.io/x/pkg v1.10.4-0.20250805171825-2431e10f90a9/go.mod h1:0Bwxqd9MA3ACi119/l02FprY/o9gHahmYC2bsSbnVpM= yunion.io/x/s3cli v0.0.0-20241221171442-1c11599d28e1 h1:1KJ3YYinydPHpDEQRXdr/T8SYcKZ5Er+m489H+PnaQ4= yunion.io/x/s3cli v0.0.0-20241221171442-1c11599d28e1/go.mod h1:0iFKpOs1y4lbCxeOmq3Xx/0AcQoewVPwj62eRluioEo= -yunion.io/x/sqlchemy v1.1.3-0.20250531010554-ce98f840b833 h1:XTFC1naKYkciCQDLm9izpzHXfTenmmtYsTpVKrsN5hE= -yunion.io/x/sqlchemy v1.1.3-0.20250531010554-ce98f840b833/go.mod h1:vCIZpqhZ5Jzaq3tFyrti/vv8BijQKtkzSgNT/uH4H5A= +yunion.io/x/sqlchemy v1.1.3-0.20250806073422-e37f5197cec0 h1:Eha/ywh4foMJm7VJ8ibFOi+WPHacuTWtosAGpOld5vo= +yunion.io/x/sqlchemy v1.1.3-0.20250806073422-e37f5197cec0/go.mod h1:vCIZpqhZ5Jzaq3tFyrti/vv8BijQKtkzSgNT/uH4H5A= yunion.io/x/structarg v0.0.0-20231017124457-df4d5009457c h1:QuLab2kSRECZRxo4Lo2KcYn6XjQFDGaZ1+x0pYDVVwQ= yunion.io/x/structarg v0.0.0-20231017124457-df4d5009457c/go.mod h1:EP6NSv2C0zzqBDTKumv8hPWLb3XvgMZDHQRfyuOrQng= diff --git a/pkg/apis/compute/guests.go b/pkg/apis/compute/guests.go index 9142bfbda2..471cf26894 100644 --- a/pkg/apis/compute/guests.go +++ b/pkg/apis/compute/guests.go @@ -711,6 +711,8 @@ type ServerDetachnetworkInput struct { NetId string `json:"net_id"` // 通过IP解绑网卡, 优先级高于mac IpAddr string `json:"ip_addr"` + // 通过IP6 addr解绑网卡, 优先级高于mac + Ip6Addr string `json:"ip6_addr"` // 通过Mac解绑网卡, 优先级低于ip_addr Mac string `json:"mac"` // 解绑后不立即同步配置 diff --git a/pkg/cloudcommon/options/options.go b/pkg/cloudcommon/options/options.go index 3537fe445d..ddb74843b2 100644 --- a/pkg/cloudcommon/options/options.go +++ b/pkg/cloudcommon/options/options.go @@ -418,6 +418,10 @@ func parseOptions(optStruct interface{}, args []string, configFileName string, s consts.SetTaskWorkerCount(optionsRef.TaskWorkerCount) consts.SetLocalTaskWorkerCount(optionsRef.LocalTaskWorkerCount) consts.SetTaskArchiveThresholdHours(optionsRef.TaskArchiveThresholdHours) + + if optionsRef.Address == "0.0.0.0" { + optionsRef.Address = "" + } } func (self *BaseOptions) HttpTransportProxyFunc() httputils.TransportProxyFunc { diff --git a/pkg/compute/models/guest_actions.go b/pkg/compute/models/guest_actions.go index 5fe2bc21e9..c1ac83ef62 100644 --- a/pkg/compute/models/guest_actions.go +++ b/pkg/compute/models/guest_actions.go @@ -2847,8 +2847,14 @@ func (self *SGuest) PerformDetachnetwork( if err != nil { return nil, httperrors.NewGeneralError(err) } - } else if len(input.IpAddr) > 0 { - gn, err := self.GetGuestnetworkByIp(input.IpAddr) + } else if len(input.IpAddr) > 0 || len(input.Ip6Addr) > 0 { + var gn *SGuestnetwork + var err error + if len(input.IpAddr) > 0 { + gn, err = self.GetGuestnetworkByIp(input.IpAddr) + } else if len(input.Ip6Addr) > 0 { + gn, err = self.GetGuestnetworkByIp6(input.Ip6Addr) + } if err != nil { if err == sql.ErrNoRows { return nil, httperrors.NewNotFoundError("ip %s not found", input.IpAddr) @@ -2944,7 +2950,7 @@ func (guest *SGuest) fixDefaultGatewayByNics(ctx context.Context, userCred mccli } net, _ := nics[i].GetNetwork() if net != nil { - nicList = nicList.Add(nics[i].IpAddr, nics[i].MacAddr, net.GuestGateway) + nicList = nicList.Add(nics[i].MacAddr, nics[i].IpAddr, net.GuestGateway, nics[i].Ip6Addr, net.GuestGateway6, nics[i].IsDefault) } } diff --git a/pkg/compute/models/guestnetworks.go b/pkg/compute/models/guestnetworks.go index f720285eaa..d82c0ab0cd 100644 --- a/pkg/compute/models/guestnetworks.go +++ b/pkg/compute/models/guestnetworks.go @@ -426,7 +426,7 @@ func (manager *SGuestnetworkManager) newGuestNetwork( gn.Ifname = ifname gn.TeamWith = teamWithMac - if isDefault && len(gn.IpAddr) > 0 && len(network.GuestGateway) > 0 { + if isDefault && ((len(gn.IpAddr) > 0 && len(network.GuestGateway) > 0) || (len(gn.Ip6Addr) > 0 && len(network.GuestGateway6) > 0)) { gn.IsDefault = isDefault } @@ -853,10 +853,10 @@ func (gn *SGuestnetwork) ValidateUpdateData( if err != nil { return input, errors.Wrapf(err, "GetNetwork") } - if len(net.GuestGateway) == 0 { + if len(net.GuestGateway) == 0 && len(net.GuestGateway6) == 0 { return input, errors.Wrap(httperrors.ErrInvalidStatus, "network of default gateway has no gateway") } - if len(gn.IpAddr) == 0 { + if (len(gn.IpAddr) == 0 || (len(gn.IpAddr) > 0 && len(net.GuestGateway) == 0)) && (len(gn.Ip6Addr) == 0 || (len(gn.Ip6Addr) > 0 && len(net.GuestGateway6) == 0)) { return input, errors.Wrap(httperrors.ErrInvalidStatus, "nic of default gateway has no ip") } } diff --git a/pkg/compute/models/hosts.go b/pkg/compute/models/hosts.go index 20ac75f1df..9aa6ba3ac0 100644 --- a/pkg/compute/models/hosts.go +++ b/pkg/compute/models/hosts.go @@ -5588,7 +5588,7 @@ func (h *SHost) PerformAddNetif( mac := input.Mac vlan := input.VlanId - wire := input.WireId + wireId := input.WireId if len(input.WireId) > 0 { wireObj, err := WireManager.FetchByIdOrName(ctx, userCred, input.WireId) if err != nil { @@ -5598,7 +5598,7 @@ func (h *SHost) PerformAddNetif( return nil, errors.Wrap(err, "FetchByIdOrName") } } - wire = wireObj.GetId() + wireId = wireObj.GetId() } ipAddr := input.IpAddr if len(ipAddr) > 0 && !regutils.MatchIP4Addr(ipAddr) { @@ -5630,25 +5630,25 @@ func (h *SHost) PerformAddNetif( } } - err = h.addNetif(ctx, userCred, mac, vlan, wire, ipAddr, ip6Addr, int(rate), nicType, index, isLinkUp, + err = h.addNetif(ctx, userCred, mac, vlan, wireId, ipAddr, ip6Addr, int(rate), nicType, index, isLinkUp, int16(mtu), reset, netIf, bridge, reserve, requireDesignatedIp, requireIpv6, strictIpv6) return nil, errors.Wrap(err, "addNetif") } func (h *SHost) addNetif(ctx context.Context, userCred mcclient.TokenCredential, - mac string, vlanId int, wire string, ipAddr string, ip6Addr string, + mac string, vlanId int, wireId string, ipAddr string, ip6Addr string, rate int, nicType compute.TNicType, index int, linkUp tristate.TriState, mtu int16, reset bool, strInterface *string, strBridge *string, reserve bool, requireDesignatedIp bool, requireIpv6 bool, strictIpv6 bool, ) error { var sw *SWire - if len(wire) > 0 { - iWire, err := WireManager.FetchByIdOrName(ctx, userCred, wire) + if len(wireId) > 0 { + iWire, err := WireManager.FetchById(wireId) if err != nil { if err == sql.ErrNoRows { - return httperrors.NewResourceNotFoundError2(WireManager.Keyword(), wire) + return httperrors.NewResourceNotFoundError2(WireManager.Keyword(), wireId) } else { - return httperrors.NewInternalServerError("find Wire %s error: %s", wire, err) + return httperrors.NewInternalServerError("find Wire %s error: %s", wireId, err) } } sw = iWire.(*SWire) @@ -5673,7 +5673,7 @@ func (h *SHost) addNetif(ctx context.Context, userCred mcclient.TokenCredential, var v4net, v6net *SNetwork swNets, err := sw.getNetworks(ctx, userCred, userCred, NetworkManager.AllowScope(userCred)) if err != nil { - return httperrors.NewInputParameterError("no networks on wire %s", wire) + return httperrors.NewInputParameterError("no networks on wire %s", wireId) } for i := range swNets { if v4net == nil && v4addr != nil && swNets[i].IsAddressInRange(*v4addr) { @@ -5694,7 +5694,7 @@ func (h *SHost) addNetif(ctx context.Context, userCred mcclient.TokenCredential, if len(ip6Addr) > 0 { addrs = append(addrs, ip6Addr) } - return httperrors.NewBadRequestError("IP %s not attach to wire %s", strings.Join(addrs, ","), wire) + return httperrors.NewBadRequestError("IP %s not attach to wire %s", strings.Join(addrs, ","), wireId) } if v4net != nil && v6net != nil && v4net.Id != v6net.Id { return httperrors.NewConflictError("IPv4 %s and IPv6 %s must be on the same network", ipAddr, ip6Addr) @@ -6137,7 +6137,7 @@ func (hh *SHost) attach2Network( defer lockman.ReleaseObject(ctx, net) var freeIp4, freeIp6 string - if (!opt.strictIpv6 || len(ipAddr) > 0) && (bn == nil || bn.IpAddr != ipAddr) { + if (!opt.strictIpv6 || len(ipAddr) > 0) && (bn == nil || bn.IpAddr != ipAddr) && net.HasIPv4Addr() { // allocate ipv4 address usedAddrs := net.GetUsedAddresses(ctx) if ipAddr != "" { @@ -6158,7 +6158,7 @@ func (hh *SHost) attach2Network( } freeIp4 = freeIp } - if (opt.requireIpv6 || len(ip6Addr) > 0) && (bn == nil || bn.Ip6Addr != ip6Addr) { + if (opt.requireIpv6 || len(ip6Addr) > 0) && (bn == nil || bn.Ip6Addr != ip6Addr) && net.HasIPv6Addr() { usedAddrs6 := net.GetUsedAddresses6(ctx) if ip6Addr != "" { // converted baremetal can resuse related guest network ip diff --git a/pkg/compute/models/networks.go b/pkg/compute/models/networks.go index c5f576d5cb..8124e460fc 100644 --- a/pkg/compute/models/networks.go +++ b/pkg/compute/models/networks.go @@ -3966,3 +3966,11 @@ func (net *SNetwork) StartRemoteUpdateTask(ctx context.Context, userCred mcclien net.SetStatus(ctx, userCred, apis.STATUS_UPDATE_TAGS, "StartRemoteUpdateTask") return task.ScheduleRun(nil) } + +func (net SNetwork) HasIPv4Addr() bool { + return len(net.GuestIpStart) > 0 && len(net.GuestIpEnd) > 0 +} + +func (net SNetwork) HasIPv6Addr() bool { + return len(net.GuestIp6Start) > 0 && len(net.GuestIp6End) > 0 +} diff --git a/pkg/compute/models/networks_used_addresses_query.go b/pkg/compute/models/networks_used_addresses_query.go index def6d3af6d..c1c368d52a 100644 --- a/pkg/compute/models/networks_used_addresses_query.go +++ b/pkg/compute/models/networks_used_addresses_query.go @@ -103,14 +103,18 @@ func (manager *SHostnetworkManager) usedAddressQuery(ctx context.Context, args * baseq = HostnetworkManager.Query().Equals("network_id", args.network.Id).SubQuery() retq *sqlchemy.SQuery ) + field := "ip_addr" + if args.addrType == api.AddressTypeIPv6 { + field = "ip6_addr" + } if args.addrOnly { retq = baseq.Query( - baseq.Field("ip_addr"), + baseq.Field(field), ) } else { ownerq := HostManager.FilterByOwner(ctx, HostManager.Query(), HostManager, args.userCred, args.owner, args.scope).SubQuery() retq = baseq.Query( - baseq.Field("ip_addr"), + baseq.Field(field), baseq.Field("mac_addr"), sqlchemy.NewStringField(HostManager.KeywordPlural()).Label("owner_type"), ownerq.Field("id").Label("owner_id"), diff --git a/pkg/compute/models/storagecachedimages.go b/pkg/compute/models/storagecachedimages.go index b6271d47bf..19592464ed 100644 --- a/pkg/compute/models/storagecachedimages.go +++ b/pkg/compute/models/storagecachedimages.go @@ -468,7 +468,7 @@ func (manager *SStoragecachedimageManager) Register(ctx context.Context, userCre } cachedimage.Status = status - err := manager.TableSpec().InsertOrUpdate(ctx, cachedimage) + err := manager.TableSpec().Insert(ctx, cachedimage) if err != nil { log.Errorf("insert error %s", err) diff --git a/pkg/compute/models/wires.go b/pkg/compute/models/wires.go index 003e7f1e9a..db31c3af66 100644 --- a/pkg/compute/models/wires.go +++ b/pkg/compute/models/wires.go @@ -966,7 +966,10 @@ func (swire *SWire) getNetworks(ctx context.Context, userCred mcclient.TokenCred func (swire *SWire) getGatewayNetworkQuery(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, scope rbacscope.TRbacScope) *sqlchemy.SQuery { q := swire.getNetworkQuery(ctx, userCred, ownerId, scope) - q = q.IsNotNull("guest_gateway").IsNotEmpty("guest_gateway") + q = q.Filter(sqlchemy.OR( + sqlchemy.AND(sqlchemy.IsNotNull(q.Field("guest_gateway")), sqlchemy.IsNotEmpty(q.Field("guest_gateway"))), + sqlchemy.AND(sqlchemy.IsNotNull(q.Field("guest_gateway6")), sqlchemy.IsNotEmpty(q.Field("guest_gateway6"))), + )) q = q.Equals("status", api.NETWORK_STATUS_AVAILABLE) return q } diff --git a/pkg/hostman/guestfs/core.go b/pkg/hostman/guestfs/core.go index 678292bda8..9ad049c6c5 100644 --- a/pkg/hostman/guestfs/core.go +++ b/pkg/hostman/guestfs/core.go @@ -74,12 +74,21 @@ func DoDeployGuestFs(rootfs fsdriver.IRootFsDriver, guestDesc *deployapi.GuestDe hn = guestDesc.Hostname } for _, n := range nics { - var addr netutils.IPV4Addr - if addr, err = netutils.NewIPV4Addr(n.Ip); err != nil { - return nil, fmt.Errorf("Fail to get ip addr from %#v: %s", n, err) + if len(n.Ip) > 0 { + var addr netutils.IPV4Addr + if addr, err = netutils.NewIPV4Addr(n.Ip); err != nil { + return nil, errors.Wrapf(err, "Fail to get ip addr from %#v", n) + } + if netutils.IsPrivate(addr) { + ips = append(ips, addr.String()) + } } - if netutils.IsPrivate(addr) { - ips = append(ips, n.Ip) + if len(n.Ip6) > 0 { + var addr netutils.IPV6Addr + if addr, err = netutils.NewIPV6Addr(n.Ip6); err != nil { + return nil, errors.Wrapf(err, "Fail to get ipv6 addr from %#v", n) + } + ips = append(ips, addr.String()) } } if releaseInfo != nil { diff --git a/pkg/hostman/guestfs/fsdriver/linux.go b/pkg/hostman/guestfs/fsdriver/linux.go index d66062f2ea..9aca3bf271 100644 --- a/pkg/hostman/guestfs/fsdriver/linux.go +++ b/pkg/hostman/guestfs/fsdriver/linux.go @@ -193,13 +193,7 @@ func (l *sLinuxRootFs) DeployHosts(rootFs IDiskPartition, hostname, domain strin } oldHostFile = string(oldhf) } - hf := make(fileutils2.HostsFile, 0) - hf.Parse(oldHostFile) - hf.Add("127.0.0.1", "localhost") - for _, ip := range ips { - hf.Add(ip, getHostname(hostname, domain), hostname) - } - return rootFs.FilePutContents(etcHosts, hf.String(), false, false) + return rootFs.FilePutContents(etcHosts, fileutils2.FormatHostsFile(oldHostFile, ips, hostname, getHostname(hostname, domain)), false, false) } func (l *sLinuxRootFs) GetLoginAccount(rootFs IDiskPartition, sUser string, defaultRootUser bool, windowsDefaultAdminUser bool) (string, error) { diff --git a/pkg/hostman/guestfs/fsdriver/windows.go b/pkg/hostman/guestfs/fsdriver/windows.go index aa3a2e811b..06f52d3246 100644 --- a/pkg/hostman/guestfs/fsdriver/windows.go +++ b/pkg/hostman/guestfs/fsdriver/windows.go @@ -270,13 +270,7 @@ func (w *SWindowsRootFs) DeployHosts(part IDiskPartition, hn, domain string, ips oldHf = string(oldHfBytes) } - hf := fileutils2.HostsFile{} - hf.Parse(oldHf) - hf.Add("127.0.0.1", "localhost") - for _, ip := range ips { - hf.Add(ip, getHostname(hn, domain), hn) - } - return w.rootFs.FilePutContents(ETC_HOSTS, hf.String(), false, true) + return w.rootFs.FilePutContents(ETC_HOSTS, fileutils2.FormatHostsFile(oldHf, ips, hn, getHostname(hn, domain)), false, true) } func (w *SWindowsRootFs) DeployNetworkingScripts(rootfs IDiskPartition, nics []*types.SServerNic) error { @@ -309,6 +303,21 @@ func (w *SWindowsRootFs) DeployNetworkingScripts(rootfs IDiskPartition, nics []* ` for /f "delims=,,, tokens=1,3" %%b in ("!line!") do (`, } + hasV6 := false + for _, snic := range nics { + if len(snic.Ip6) > 0 { + hasV6 = true + break + } + } + if hasV6 { + lines = append(lines, ` netsh interface teredo set state disable`) + lines = append(lines, ` netsh interface 6to4 set state state=disabled`) + lines = append(lines, ` netsh interface isatap set state state=disabled`) + lines = append(lines, ` netsh interface ipv6 set privacy disabled store=persistent`) + lines = append(lines, ` netsh interface ipv6 set global randomizeidentifiers=disabled store=persistent`) + } + for _, snic := range nics { mac := snic.Mac mac = strings.Replace(strings.ToUpper(mac), ":", "-", -1) @@ -317,12 +326,14 @@ func (w *SWindowsRootFs) DeployNetworkingScripts(rootfs IDiskPartition, nics []* lines = append(lines, fmt.Sprintf(` netsh interface ipv4 set subinterface "%%%%b" mtu=%d`, snic.Mtu)) } if snic.Manual { - netmask := netutils2.Netlen2Mask(int(snic.Masklen)) - cfg := fmt.Sprintf(` netsh interface ip set address "%%%%b" static %s %s`, snic.Ip, netmask) - if len(snic.Gateway) > 0 && snic.Ip == mainIp { - cfg += fmt.Sprintf(" %s", snic.Gateway) + if len(snic.Ip) > 0 { + netmask := netutils2.Netlen2Mask(int(snic.Masklen)) + cfg := fmt.Sprintf(` netsh interface ip set address "%%%%b" static %s %s`, snic.Ip, netmask) + if len(snic.Gateway) > 0 && snic.Ip == mainIp { + cfg += fmt.Sprintf(" %s", snic.Gateway) + } + lines = append(lines, cfg) } - lines = append(lines, cfg) if len(snic.Ip6) > 0 { cfg := fmt.Sprintf(` netsh interface ipv6 add address "%%%%b" %s/%d store=persistent`, snic.Ip6, snic.Masklen6) lines = append(lines, cfg) @@ -355,15 +366,15 @@ func (w *SWindowsRootFs) DeployNetworkingScripts(rootfs IDiskPartition, nics []* lines = append(lines, w.regAdd(TCPIP_PARAM_KEY, "SearchList", snic.Domain, "REG_SZ")) } } else { - lines = append(lines, ` netsh interface ip set address "%%b" dhcp`) - lines = append(lines, ` netsh interface ip set dns "%%b" dhcp`) + if len(snic.Ip) > 0 { + lines = append(lines, ` netsh interface ip set address "%%b" dhcp`) + lines = append(lines, ` netsh interface ip set dns "%%b" dhcp`) + } if len(snic.Ip6) > 0 { - cfg := fmt.Sprintf(` netsh interface ipv6 add address "%%%%b" %s/%d store=persistent`, snic.Ip6, snic.Masklen6) + cfg := ` netsh interface ipv6 set interface "%%b" routerdiscovery=enabled store=persistent` + lines = append(lines, cfg) + cfg = ` netsh interface ipv6 set interface "%%b" managedaddress=enabled otherstateful=enabled store=persistent` lines = append(lines, cfg) - if len(snic.Gateway) > 0 && snic.Ip == mainIp { - cfg := fmt.Sprintf(` netsh interface ipv6 add route ::/0 "%%%%b" %s`, snic.Gateway6) - lines = append(lines, cfg) - } } } lines = append(lines, ` )`) diff --git a/pkg/hostman/guestman/runtime.go b/pkg/hostman/guestman/runtime.go index ffa357cfd3..846698f84f 100644 --- a/pkg/hostman/guestman/runtime.go +++ b/pkg/hostman/guestman/runtime.go @@ -395,7 +395,7 @@ func SaveLiveDesc(s GuestRuntimeInstance, guestDesc *desc.SGuestDesc) error { if nic.IsDefault { defaultGwCnt++ } - defNics = defNics.Add(nic.Ip, nic.Mac, nic.Gateway) + defNics = defNics.Add(nic.Mac, nic.Ip, nic.Gateway, nic.Ip6, nic.Gateway6, nic.IsDefault) } // there should 1 and only 1 default gateway diff --git a/pkg/hostman/hostinfo/hostbridge/hostbridge.go b/pkg/hostman/hostinfo/hostbridge/hostbridge.go index 2309a92538..fcfa5751d3 100644 --- a/pkg/hostman/hostinfo/hostbridge/hostbridge.go +++ b/pkg/hostman/hostinfo/hostbridge/hostbridge.go @@ -68,6 +68,8 @@ type IBridgeDriver interface { OnVolatileGuestResume(nic *desc.SGuestNetwork) error Bridge() string + + IsV4Only() bool } type SBaseBridgeDriver struct { @@ -378,7 +380,7 @@ func (d *SBaseBridgeDriver) ConfirmToConfig() (bool, string, error) { return false, "", fmt.Errorf("bridge %s (%s) shoud have no ipv6 address", d.bridge, d.bridge.Addr6) } if !d.bridge.IsSecretInterface6() { - return false, "", fmt.Errorf("bridge %s(%s,%s) should have link local address in fe80::/10", d.bridge, d.bridge.Addr6, d.bridge.Addr6LinkLocal) + log.Warningf("bridge %s have no link local address in fe80::/10", d.bridge) } } infs, err := d.drv.Interfaces() @@ -716,3 +718,7 @@ func CleanDeletedPorts(bridgeDriver string) { cleanLinuxBridge() } } + +func (d *SBaseBridgeDriver) IsV4Only() bool { + return d.ip6 == "" && !d.bridge.IsSecretInterface6() +} diff --git a/pkg/hostman/hostinfo/hostdhcp/dhcpserver.go b/pkg/hostman/hostinfo/hostdhcp/dhcpserver.go index 5c7a69d266..262c685f68 100644 --- a/pkg/hostman/hostinfo/hostdhcp/dhcpserver.go +++ b/pkg/hostman/hostinfo/hostdhcp/dhcpserver.go @@ -80,7 +80,7 @@ func NewGuestDHCPServer(iface string, port int, relay *SDHCPRelayUpstream) (*SGu } func (s *SGuestDHCPServer) Start(blocking bool) { - log.Infof("SGuestDHCPServer starting ...") + log.Infof("SGuestDHCPServer %s starting (blocking: %v) ...", s.ifaceDev.String(), blocking) serve := func() { err := s.server.ListenAndServe(s) if err != nil { diff --git a/pkg/hostman/hostinfo/hostdhcp/dhcpserver6.go b/pkg/hostman/hostinfo/hostdhcp/dhcpserver6.go index d98830a9c3..1d7055f370 100644 --- a/pkg/hostman/hostinfo/hostdhcp/dhcpserver6.go +++ b/pkg/hostman/hostinfo/hostdhcp/dhcpserver6.go @@ -84,7 +84,7 @@ func NewGuestDHCP6Server(iface string, port int, relay *SDHCPRelayUpstream) (*SG } func (s *SGuestDHCP6Server) Start(blocking bool) { - log.Infof("SGuestDHCP6Server starting ...") + log.Infof("SGuestDHCP6Server %s starting (blocking: %v) ...", s.ifaceDev.String(), blocking) serve := func() { defer s.stopRAServer() diff --git a/pkg/hostman/hostinfo/hostdhcp/icmp6handlers.go b/pkg/hostman/hostinfo/hostdhcp/icmp6handlers.go index ecdc4328ff..29bc82ed1f 100644 --- a/pkg/hostman/hostinfo/hostdhcp/icmp6handlers.go +++ b/pkg/hostman/hostinfo/hostdhcp/icmp6handlers.go @@ -145,7 +145,7 @@ func (s *SGuestDHCP6Server) sendRouterAdvertisement(solicitation *icmp6.SRouterS PrefixInfo: []icmp6.SPrefixInfoOption{ { IsOnlink: true, - IsAutoconf: true, + IsAutoconf: false, Prefix: ipnet.IP, PrefixLen: conf.PrefixLen6, ValidLifetime: 4500, diff --git a/pkg/hostman/hostinfo/hostinfo.go b/pkg/hostman/hostinfo/hostinfo.go index e426a4e09c..ff223af82c 100644 --- a/pkg/hostman/hostinfo/hostinfo.go +++ b/pkg/hostman/hostinfo/hostinfo.go @@ -421,6 +421,14 @@ func (h *SHostInfo) parseConfig() error { } } + if h.MasterNic != nil { + if regutils.MatchIP4Addr(h.GetMasterIp()) { + options.HostOptions.Address = "0.0.0.0" + } else { + options.HostOptions.Address = "::" + } + } + h.IsolatedDeviceMan = isolated_device.NewManager(h) return nil @@ -1860,12 +1868,17 @@ func (h *SHostInfo) uploadNetworkInfo() error { var hostDetails *api.HostDetails for _, nic := range h.Nics { + log.Infof("host nic: %s", jsonutils.Marshal(nic).String()) if len(nic.WireId) == 0 { // nic info not uploaded yet if len(nic.Wire) == 0 { // no wire defined, find from region kwargs := jsonutils.NewDict() - kwargs.Set("ip", jsonutils.NewString(nic.Ip)) + if len(nic.Ip) > 0 { + kwargs.Set("ip", jsonutils.NewString(nic.Ip)) + } else if len(nic.Ip6) > 0 { + kwargs.Set("ip", jsonutils.NewString(nic.Ip6)) + } kwargs.Set("is_classic", jsonutils.JSONTrue) kwargs.Set("scope", jsonutils.NewString("system")) kwargs.Set("limit", jsonutils.NewInt(0)) diff --git a/pkg/hostman/hostinfo/hostinfohelper.go b/pkg/hostman/hostinfo/hostinfohelper.go index ac29945f20..fd15e54f75 100644 --- a/pkg/hostman/hostinfo/hostinfohelper.go +++ b/pkg/hostman/hostinfo/hostinfohelper.go @@ -382,9 +382,11 @@ func NewNIC(desc string) (*SNIC, error) { } } - nic.dhcpServer6, err = hostdhcp.NewGuestDHCP6Server(nic.Bridge, options.HostOptions.Dhcp6ServerPort, relayConf6) - if err != nil { - return nil, errors.Wrapf(err, "NewGuestDHCP6Server(%s, %d, %#v)", nic.Bridge, options.HostOptions.Dhcp6ServerPort, relayConf6) + if !nic.BridgeDev.IsV4Only() { + nic.dhcpServer6, err = hostdhcp.NewGuestDHCP6Server(nic.Bridge, options.HostOptions.Dhcp6ServerPort, relayConf6) + if err != nil { + return nil, errors.Wrapf(err, "NewGuestDHCP6Server(%s, %d, %#v)", nic.Bridge, options.HostOptions.Dhcp6ServerPort, relayConf6) + } } // dhcp server start after guest manager init diff --git a/pkg/util/fileutils2/fileutils.go b/pkg/util/fileutils2/fileutils.go index 5d2702d397..8a42d0630e 100644 --- a/pkg/util/fileutils2/fileutils.go +++ b/pkg/util/fileutils2/fileutils.go @@ -31,6 +31,7 @@ import ( "yunion.io/x/log" "yunion.io/x/pkg/errors" + "yunion.io/x/pkg/util/regutils" "yunion.io/x/onecloud/pkg/util/procutils" ) @@ -358,6 +359,25 @@ func (hf HostsFile) String() string { return ret } +func FormatHostsFile(content string, ips []string, hostname, hostdomain string) string { + hf := make(HostsFile, 0) + hf.Parse(content) + hf.Add("127.0.0.1", "localhost") + isV6 := false + for _, ip := range ips { + if regutils.MatchIP6Addr(ip) { + isV6 = true + } + } + if isV6 { + hf.Add("::1", "localhost", "ip6-localhost", "ip6-loopback") + } + for _, ip := range ips { + hf.Add(ip, hostdomain, hostname) + } + return hf.String() +} + func FsFormatToDiskType(fsFormat string) string { switch { case fsFormat == "swap": diff --git a/pkg/util/netutils2/defgw.go b/pkg/util/netutils2/defgw.go index 2dab246f5c..a7258844b7 100644 --- a/pkg/util/netutils2/defgw.go +++ b/pkg/util/netutils2/defgw.go @@ -22,36 +22,54 @@ import ( type SNicInfo struct { IpAddr string Gateway string + + Ip6Addr string + Gateway6 string + MacAddr string + + IsDefault bool } type SNicInfoList []SNicInfo -func (nics SNicInfoList) Add(ip, mac, gw string) SNicInfoList { +func (nics SNicInfoList) Add(mac, ip, gw, ip6, gw6 string, isDefault bool) SNicInfoList { return append(nics, SNicInfo{ IpAddr: ip, MacAddr: mac, Gateway: gw, + + Ip6Addr: ip6, + Gateway6: gw6, + + IsDefault: isDefault, }) } func (nics SNicInfoList) FindDefaultNicMac() (string, int) { - var intMac, exitMac string - var intIdx, exitIdx int + var intMac, exitMac, defMac string + var intIdx, exitIdx, defIdx int for i, nic := range nics { - if len(nic.IpAddr) == 0 { + if len(nic.IpAddr) == 0 && len(nic.Ip6Addr) == 0 { continue } - if len(nic.Gateway) == 0 { + if len(nic.IpAddr) > 0 && len(nic.Gateway) == 0 { continue } - addr, err := netutils.NewIPV4Addr(nic.IpAddr) - if err != nil { - log.Errorf("NewIPV4Addr %s fail %s", nic.IpAddr, err) + if len(nic.Ip6Addr) > 0 && len(nic.Gateway6) == 0 { continue } - if len(exitMac) == 0 || len(intMac) == 0 { - isExit := netutils.IsExitAddress(addr) + + var isExit bool + if len(nic.IpAddr) > 0 { + addr, err := netutils.NewIPV4Addr(nic.IpAddr) + if err != nil { + log.Errorf("NewIPV4Addr %s fail %s", nic.IpAddr, err) + continue + } + isExit = netutils.IsExitAddress(addr) + } + if len(exitMac) == 0 || len(intMac) == 0 || len(defMac) == 0 { if len(exitMac) == 0 && isExit { exitMac = nic.MacAddr exitIdx = i @@ -60,13 +78,20 @@ func (nics SNicInfoList) FindDefaultNicMac() (string, int) { intMac = nic.MacAddr intIdx = i } - } else if len(exitMac) > 0 && len(intMac) > 0 { + if len(defMac) == 0 && nic.IsDefault && !isExit { + defMac = nic.MacAddr + defIdx = i + } + } else if len(exitMac) > 0 && len(intMac) > 0 && len(defMac) > 0 { break } } if len(exitMac) > 0 { return exitMac, exitIdx } + if len(defMac) > 0 { + return defMac, defIdx + } if len(intMac) > 0 { return intMac, intIdx } diff --git a/pkg/util/netutils2/defgw_test.go b/pkg/util/netutils2/defgw_test.go index 47e0b325c9..f8ef342ebc 100644 --- a/pkg/util/netutils2/defgw_test.go +++ b/pkg/util/netutils2/defgw_test.go @@ -26,40 +26,64 @@ func TestFindDefaultNic(t *testing.T) { }{ { nics: [][]string{ - {"192.168.202.147", "00:22:00:00:00:01", "192.168.202.1"}, + {"192.168.202.147", "00:22:00:00:00:01", "192.168.202.1", "", "", "false"}, }, mac: "00:22:00:00:00:01", index: 0, }, { nics: [][]string{ - {"192.168.202.147", "00:22:00:00:00:01", "192.168.202.1"}, - {"192.168.203.147", "00:22:00:00:00:02", "192.168.203.1"}, + {"192.168.202.147", "00:22:00:00:00:01", "192.168.202.1", "", "", "false"}, + {"192.168.203.147", "00:22:00:00:00:02", "192.168.203.1", "", "", "false"}, }, mac: "00:22:00:00:00:01", index: 0, }, { nics: [][]string{ - {"192.168.202.147", "00:22:00:00:00:01", "192.168.202.1"}, - {"202.168.202.147", "00:22:00:00:00:02", "202.168.202.1"}, + {"192.168.202.147", "00:22:00:00:00:01", "192.168.202.1", "", "", "false"}, + {"192.168.203.147", "00:22:00:00:00:02", "192.168.203.1", "", "", "true"}, }, mac: "00:22:00:00:00:02", index: 1, }, { nics: [][]string{ - {"202.168.202.147", "00:22:00:00:00:01", "202.168.202.1"}, - {"192.168.202.147", "00:22:00:00:00:02", "192.168.202.1"}, + {"", "00:22:00:00:00:01", "", "3ffe:3200:fe::fb", "3ffe:3200:fe::1", "false"}, + {"", "00:22:00:00:00:02", "", "3ffe:3200:ff::fb", "3ffe:3200:ff::1", "true"}, + }, + mac: "00:22:00:00:00:02", + index: 1, + }, + { + nics: [][]string{ + {"", "00:22:00:00:00:01", "", "3ffe:3200:fe::fb", "3ffe:3200:fe::1", "false"}, + {"", "00:22:00:00:00:02", "", "3ffe:3200:ff::fb", "", "true"}, }, mac: "00:22:00:00:00:01", index: 0, }, { nics: [][]string{ - {"192.168.202.147", "00:22:00:00:00:01", "192.168.202.1"}, - {"", "00:22:00:00:00:02", ""}, - {"202.168.202.147", "00:22:00:00:00:03", "202.168.202.1"}, + {"192.168.202.147", "00:22:00:00:00:01", "192.168.202.1", "", "", "false"}, + {"202.168.202.147", "00:22:00:00:00:02", "202.168.202.1", "", "", "false"}, + }, + mac: "00:22:00:00:00:02", + index: 1, + }, + { + nics: [][]string{ + {"202.168.202.147", "00:22:00:00:00:01", "202.168.202.1", "", "", "false"}, + {"192.168.202.147", "00:22:00:00:00:02", "192.168.202.1", "", "", "false"}, + }, + mac: "00:22:00:00:00:01", + index: 0, + }, + { + nics: [][]string{ + {"192.168.202.147", "00:22:00:00:00:01", "192.168.202.1", "", "", "false"}, + {"", "00:22:00:00:00:02", "", "", "", "false"}, + {"202.168.202.147", "00:22:00:00:00:03", "202.168.202.1", "", "", "false"}, }, mac: "00:22:00:00:00:03", index: 2, @@ -68,7 +92,7 @@ func TestFindDefaultNic(t *testing.T) { for _, c := range cases { nics := SNicInfoList{} for _, n := range c.nics { - nics = nics.Add(n[0], n[1], n[2]) + nics = nics.Add(n[1], n[0], n[2], n[3], n[4], n[5] == "true") } gotMac, gotIdx := nics.FindDefaultNicMac() diff --git a/pkg/util/ovsutils/ovsutils.go b/pkg/util/ovsutils/ovsutils.go index 579a7a7a32..7217ae7d0b 100644 --- a/pkg/util/ovsutils/ovsutils.go +++ b/pkg/util/ovsutils/ovsutils.go @@ -125,7 +125,7 @@ func NormalizeDbHost(db string) (string, error) { if len(addrs) == 0 { return "", fmt.Errorf("dns lookup (%s) returned empty result", host) } - return "tcp:" + addrs[0] + ":" + port, nil + return "tcp:" + net.JoinHostPort(addrs[0], port), nil } } return db, nil diff --git a/pkg/vpcagent/models/models.go b/pkg/vpcagent/models/models.go index 72478dab61..cabc3a2fe5 100644 --- a/pkg/vpcagent/models/models.go +++ b/pkg/vpcagent/models/models.go @@ -158,7 +158,7 @@ func (el *Guest) FixIsDefaults() { if gn.IsDefault { defaultCnt++ } - nics = nics.Add(gn.IpAddr, gn.MacAddr, gn.Network.GuestGateway) + nics = nics.Add(gn.MacAddr, gn.IpAddr, gn.Network.GuestGateway, gn.Ip6Addr, gn.Network.GuestGateway6, gn.IsDefault) } if defaultCnt != 1 { gwMac, _ := nics.FindDefaultNicMac() diff --git a/pkg/webconsole/server/ssh_server.go b/pkg/webconsole/server/ssh_server.go index fafb2f728b..84492553e1 100644 --- a/pkg/webconsole/server/ssh_server.go +++ b/pkg/webconsole/server/ssh_server.go @@ -20,6 +20,7 @@ import ( "io" "net" "net/http" + "strconv" "time" "github.com/gorilla/websocket" @@ -102,7 +103,7 @@ func (s *WebsocketServer) initWs(w http.ResponseWriter, r *http.Request) error { } var err error - addr := fmt.Sprintf("%s:%d", s.Host, s.Port) + addr := net.JoinHostPort(s.Host, strconv.Itoa(s.Port)) s.conn, s.sshNetConn, err = NewSshClient("tcp", addr, config) if err != nil { return errors.Wrapf(err, "dial %s", addr) diff --git a/pkg/webconsole/server/websockify_server.go b/pkg/webconsole/server/websockify_server.go index 73876aaa4f..c74cfd821c 100644 --- a/pkg/webconsole/server/websockify_server.go +++ b/pkg/webconsole/server/websockify_server.go @@ -19,9 +19,11 @@ import ( "fmt" "net" "net/http" + "strconv" "github.com/gorilla/websocket" + "yunion.io/x/jsonutils" "yunion.io/x/log" "yunion.io/x/onecloud/pkg/webconsole/session" @@ -69,7 +71,7 @@ func (s *WebsockifyServer) isBase64Subprotocol(wsConn *websocket.Conn) bool { } func (s *WebsockifyServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { - targetAddr := fmt.Sprintf("%s:%d", s.TargetHost, s.TargetPort) + log.Debugf("ServeHTTP: %s, %s", r.URL.String(), jsonutils.Marshal(r.Header)) wsConn, err := upgrader.Upgrade(w, r, nil) if err != nil { log.Errorf("New websocket connection error: %v", err) @@ -77,6 +79,7 @@ func (s *WebsockifyServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { } log.Debugf("Get coordinate subprotocol: %s", wsConn.Subprotocol()) + targetAddr := net.JoinHostPort(s.TargetHost, strconv.Itoa(int(s.TargetPort))) log.Debugf("Handle websocket connect, target: %s", targetAddr) targetConn, err := net.Dial("tcp", targetAddr) if err != nil { @@ -89,6 +92,7 @@ func (s *WebsockifyServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { } func (s *WebsockifyServer) doProxy(wsConn *websocket.Conn, tcpConn net.Conn) { + log.Infof("doProxy bewteen ws: %s <--> tcp: %s", wsConn.RemoteAddr(), tcpConn.RemoteAddr()) s.Session.RegisterDuplicateHook(func() { wsConn.Close() tcpConn.Close() diff --git a/vendor/modules.txt b/vendor/modules.txt index ad9d2babb4..74be6ce2c8 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -2003,7 +2003,7 @@ yunion.io/x/pkg/utils # yunion.io/x/s3cli v0.0.0-20241221171442-1c11599d28e1 ## explicit; go 1.12 yunion.io/x/s3cli -# yunion.io/x/sqlchemy v1.1.3-0.20250531010554-ce98f840b833 +# yunion.io/x/sqlchemy v1.1.3-0.20250806073422-e37f5197cec0 ## explicit; go 1.17 yunion.io/x/sqlchemy yunion.io/x/sqlchemy/backends diff --git a/vendor/yunion.io/x/sqlchemy/backends/dameng/conditions.go b/vendor/yunion.io/x/sqlchemy/backends/dameng/conditions.go index 054f45985f..5ffc0e9d00 100644 --- a/vendor/yunion.io/x/sqlchemy/backends/dameng/conditions.go +++ b/vendor/yunion.io/x/sqlchemy/backends/dameng/conditions.go @@ -15,7 +15,6 @@ package dameng import ( - "yunion.io/x/log" "yunion.io/x/sqlchemy" ) @@ -32,7 +31,7 @@ func (t *SDamengEqualsCondition) WhereClause() string { // Equals filter conditions func (dameng *SDamengBackend) Equals(f sqlchemy.IQueryField, v interface{}) sqlchemy.ICondition { - log.Debugf("field %s isFieldText: %v %#v", f.Name(), sqlchemy.IsFieldText(f), f) + // log.Debugf("field %s isFieldText: %v %#v", f.Name(), sqlchemy.IsFieldText(f), f) if sqlchemy.IsFieldText(f) { c := SDamengEqualsCondition{sqlchemy.NewTupleCondition(f, v)} return &c diff --git a/vendor/yunion.io/x/sqlchemy/backends/dameng/dameng.go b/vendor/yunion.io/x/sqlchemy/backends/dameng/dameng.go index 3a86d474c6..6319466abd 100644 --- a/vendor/yunion.io/x/sqlchemy/backends/dameng/dameng.go +++ b/vendor/yunion.io/x/sqlchemy/backends/dameng/dameng.go @@ -21,6 +21,7 @@ import ( "reflect" "strconv" "strings" + "runtime/debug" _ "gitee.com/chunanyong/dm" @@ -95,6 +96,7 @@ func (dameng *SDamengBackend) PrepareInsertOrUpdateSQL(ts sqlchemy.ITableSpec, i for _, primary := range onPrimaryCols { colName := strings.Trim(primary, "'\"") if _, ok := colNameMap[colName]; !ok { + debug.PrintStack() log.Fatalf("primary colume %s missing from insert columes for table %s", colName, ts.Name()) } onConditions = append(onConditions, fmt.Sprintf("T1.%s=T2.%s", primary, primary))