fix: ipv6-only mode compatibility fixes (#23027)

Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
This commit is contained in:
Jian Qiu
2025-08-06 22:01:55 +08:00
committed by GitHub
co-authored by Qiu Jian
parent 4e2c7bf353
commit 3893215bbd
31 changed files with 231 additions and 94 deletions
+2
View File
@@ -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"`
// 解绑后不立即同步配置
+4
View File
@@ -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 {
+9 -3
View File
@@ -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)
}
}
+3 -3
View File
@@ -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")
}
}
+12 -12
View File
@@ -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
+8
View File
@@ -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
}
@@ -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"),
+1 -1
View File
@@ -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)
+4 -1
View File
@@ -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
}
+14 -5
View File
@@ -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 {
+1 -7
View File
@@ -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) {
+30 -19
View File
@@ -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, ` )`)
+1 -1
View File
@@ -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
@@ -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()
}
+1 -1
View File
@@ -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 {
+1 -1
View File
@@ -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()
@@ -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,
+14 -1
View File
@@ -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))
+5 -3
View File
@@ -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
+20
View File
@@ -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":
+36 -11
View File
@@ -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
}
+35 -11
View File
@@ -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()
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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()
+2 -1
View File
@@ -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)
+5 -1
View File
@@ -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()