Repository: dragonflyoss/Dragonfly2
Pull request #818 (2021-11-23 09:56:24)

feat: scheduler and cdn report fqdn to manager
Signed-off-by: Gaius <gaius.qi@gmail.com>

<!--- Provide a general summary of your changes in the Title above -->

## Description
- Scheduler and cdn report fqdn to manager.
- Generate `fqdn` with `github.com/Showmax/go-fqdn`.
- Refactor `idgen.CDN` to `idgen.CDNHostID`.
- Refactor `iputils.HostIP` to `iputils.IPv4`.
<!--- Describe your changes in detail -->

## Related Issue

<!--- This project only accepts pull requests related to open issues -->
<!--- If suggesting a new feature or change, please discuss it in an issue first -->
<!--- If fixing a bug, there should be an issue describing it with steps to reproduce -->
<!--- Please link to the issue here: -->

## Motivation and Context

<!--- Why is this change required? What problem does it solve? -->

## Screenshots (if appropriate):

## Types of changes

<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->

- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to change)
- [ ] Documentation Update (if none of the other choices apply)

## Checklist:

<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->

- [x] Code compiles correctly.
- [x] My code follows the code style of this project.
- [ ] My change requires a change to the documentation.
- [ ] I have updated the documentation accordingly.
- [x] I have read the **CONTRIBUTING** document.
- [x] I have added tests to cover my changes.
- [x] All new and existing tests passed.


codecov-commenter: # [Codecov](https://codecov.io/gh/dragonflyoss/Dragonfly2/pull/818?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=dragonflyoss) Report
> Merging [#818](https://codecov.io/gh/dragonflyoss/Dragonfly2/pull/818?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=dragonflyoss) (fa15150) into [main](https://codecov.io/gh/dragonflyoss/Dragonfly2/commit/543a4a2bf7b4e528be285ea15795e61c74dcd92b?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=dragonflyoss) (543a4a2) will **decrease** coverage by `0.12%`.
> The diff coverage is `47.05%`.

[![Impacted file tree graph](https://codecov.io/gh/dragonflyoss/Dragonfly2/pull/818/graphs/tree.svg?width=650&height=150&src=pr&token=PUICJYSAT7&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=dragonflyoss)](https://codecov.io/gh/dragonflyoss/Dragonfly2/pull/818?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=dragonflyoss)

```diff
@@            Coverage Diff             @@
##             main     #818      +/-   ##
==========================================
- Coverage   40.88%   40.75%   -0.13%     
==========================================
  Files          99      101       +2     
  Lines        8027     8003      -24     
==========================================
- Hits         3282     3262      -20     
+ Misses       4336     4333       -3     
+ Partials      409      408       -1     
```

| Flag | Coverage Δ | |
|---|---|---|
| Object-compatibility-e2etests | `?` | |
| e2etests | `?` | |
| unittests | `40.75% <47.05%> (-0.13%)` | :arrow_down: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=dragonflyoss#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Impacted Files](https://codecov.io/gh/dragonflyoss/Dragonfly2/pull/818?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=dragonflyoss) | Coverage Δ | |
|---|---|---|
| [cdn/rpcserver/rpcserver.go](https://codecov.io/gh/dragonflyoss/Dragonfly2/pull/818/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=dragonflyoss#diff-Y2RuL3JwY3NlcnZlci9ycGNzZXJ2ZXIuZ28=) | `0.00% <0.00%> (ø)` | |
| [client/config/peerhost.go](https://codecov.io/gh/dragonflyoss/Dragonfly2/pull/818/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=dragonflyoss#diff-Y2xpZW50L2NvbmZpZy9wZWVyaG9zdC5nbw==) | `35.29% <0.00%> (ø)` | |
| [internal/idgen/uuid.go](https://codecov.io/gh/dragonflyoss/Dragonfly2/pull/818/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=dragonflyoss#diff-aW50ZXJuYWwvaWRnZW4vdXVpZC5nbw==) | `100.00% <ø> (+50.00%)` | :arrow_up: |
| [scheduler/config/config.go](https://codecov.io/gh/dragonflyoss/Dragonfly2/pull/818/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=dragonflyoss#diff-c2NoZWR1bGVyL2NvbmZpZy9jb25maWcuZ28=) | `4.81% <0.00%> (ø)` | |
| [scheduler/supervisor/cdn.go](https://codecov.io/gh/dragonflyoss/Dragonfly2/pull/818/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=dragonflyoss#diff-c2NoZWR1bGVyL3N1cGVydmlzb3IvY2RuLmdv) | `73.37% <0.00%> (ø)` | |
| [pkg/util/net/iputils/ip\_utils.go](https://codecov.io/gh/dragonflyoss/Dragonfly2/pull/818/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=dragonflyoss#diff-cGtnL3V0aWwvbmV0L2lwdXRpbHMvaXBfdXRpbHMuZ28=) | `44.44% <33.33%> (-21.69%)` | :arrow_down: |
| [pkg/util/hostutils/host\_utils.go](https://codecov.io/gh/dragonflyoss/Dragonfly2/pull/818/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=dragonflyoss#diff-cGtnL3V0aWwvaG9zdHV0aWxzL2hvc3RfdXRpbHMuZ28=) | `60.00% <60.00%> (ø)` | |
| [internal/idgen/host\_id.go](https://codecov.io/gh/dragonflyoss/Dragonfly2/pull/818/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=dragonflyoss#diff-aW50ZXJuYWwvaWRnZW4vaG9zdF9pZC5nbw==) | `100.00% <100.00%> (ø)` | |
| [scheduler/config/dynconfig.go](https://codecov.io/gh/dragonflyoss/Dragonfly2/pull/818/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=dragonflyoss#diff-c2NoZWR1bGVyL2NvbmZpZy9keW5jb25maWcuZ28=) | `39.83% <100.00%> (ø)` | |
| ... and [2 more](https://codecov.io/gh/dragonflyoss/Dragonfly2/pull/818/diff?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=dragonflyoss) | |


Patch:
diff --git a/cdn/cdn.go b/cdn/cdn.go
index 21588205..a2e78a04 100644
--- a/cdn/cdn.go
+++ b/cdn/cdn.go
@@ -40,6 +40,7 @@ import (
 	"d7y.io/dragonfly/v2/pkg/rpc"
 	"d7y.io/dragonfly/v2/pkg/rpc/manager"
 	managerclient "d7y.io/dragonfly/v2/pkg/rpc/manager/client"
+	"d7y.io/dragonfly/v2/pkg/util/hostutils"
 	"d7y.io/dragonfly/v2/pkg/util/net/iputils"
 )
 
@@ -126,7 +127,7 @@ func New(cfg *config.Config) (*Server, error) {
 		// Register to manager
 		if _, err := s.managerClient.UpdateCDN(&manager.UpdateCDNRequest{
 			SourceType:   manager.SourceType_CDN_SOURCE,
-			HostName:     iputils.HostName,
+			HostName:     hostutils.FQDNHostname,
 			Ip:           s.config.AdvertiseIP,
 			Port:         int32(s.config.ListenPort),
 			DownloadPort: int32(s.config.DownloadPort),
@@ -167,7 +168,7 @@ func (s *Server) Serve() error {
 		go func() {
 			logger.Info("start keepalive to manager")
 			s.managerClient.KeepAlive(s.config.Manager.KeepAlive.Interval, &manager.KeepAliveRequest{
-				HostName:   iputils.HostName,
+				HostName:   hostutils.FQDNHostname,
 				SourceType: manager.SourceType_CDN_SOURCE,
 				ClusterId:  uint64(s.config.Manager.CDNClusterID),
 			})
@@ -175,7 +176,7 @@ func (s *Server) Serve() error {
 	}
 
 	// Generate GRPC listener
-	var listen = iputils.HostIP
+	var listen = iputils.IPv4
 	if s.config.AdvertiseIP != "" {
 		listen = s.config.AdvertiseIP
 	}
diff --git a/cdn/config/config.go b/cdn/config/config.go
index 812e8371..1ec7582a 100644
--- a/cdn/config/config.go
+++ b/cdn/config/config.go
@@ -131,7 +131,7 @@ func NewDefaultBaseProperties() *BaseProperties {
 		GCMetaInterval:          DefaultGCMetaInterval,
 		TaskExpireTime:          DefaultTaskExpireTime,
 		StorageMode:             DefaultStorageMode,
-		AdvertiseIP:             iputils.HostIP,
+		AdvertiseIP:             iputils.IPv4,
 		Manager: ManagerConfig{
 			KeepAlive: KeepAliveConfig{
 				Interval: DefaultKeepAliveInterval,
diff --git a/cdn/rpcserver/rpcserver.go b/cdn/rpcserver/rpcserver.go
index 28a026a0..bffe25eb 100644
--- a/cdn/rpcserver/rpcserver.go
+++ b/cdn/rpcserver/rpcserver.go
@@ -38,7 +38,7 @@ import (
 	"d7y.io/dragonfly/v2/pkg/rpc/cdnsystem"
 	cdnserver "d7y.io/dragonfly/v2/pkg/rpc/cdnsystem/server"
 	"d7y.io/dragonfly/v2/pkg/util/digestutils"
-	"d7y.io/dragonfly/v2/pkg/util/net/iputils"
+	"d7y.io/dragonfly/v2/pkg/util/hostutils"
 	"d7y.io/dragonfly/v2/pkg/util/net/urlutils"
 	"d7y.io/dragonfly/v2/pkg/util/stringutils"
 )
@@ -140,7 +140,7 @@ func (css *server) ObtainSeeds(ctx context.Context, req *cdnsystem.SeedRequest,
 	for piece := range pieceChan {
 		psc <- &cdnsystem.PieceSeed{
 			PeerId:   peerID,
-			HostUuid: idgen.CDN(iputils.HostName, int32(css.cfg.ListenPort)),
+			HostUuid: idgen.CDNHostID(hostutils.FQDNHostname, int32(css.cfg.ListenPort)),
 			PieceInfo: &base.PieceInfo{
 				PieceNum:    piece.PieceNum,
 				RangeStart:  piece.PieceRange.StartIndex,
@@ -165,7 +165,7 @@ func (css *server) ObtainSeeds(ctx context.Context, req *cdnsystem.SeedRequest,
 	}
 	psc <- &cdnsystem.PieceSeed{
 		PeerId:          peerID,
-		HostUuid:        idgen.CDN(iputils.HostName, int32(css.cfg.ListenPort)),
+		HostUuid:        idgen.CDNHostID(hostutils.FQDNHostname, int32(css.cfg.ListenPort)),
 		Done:            true,
 		ContentLength:   task.SourceFileLength,
 		TotalPieceCount: task.PieceTotal,
diff --git a/client/config/peerhost.go b/client/config/peerhost.go
index 8d3c599d..813957b9 100644
--- a/client/config/peerhost.go
+++ b/client/config/peerhost.go
@@ -95,7 +95,7 @@ func (p *DaemonOption) Convert() error {
 	// AdvertiseIP
 	ip := net.ParseIP(p.Host.AdvertiseIP)
 	if ip == nil || net.IPv4zero.Equal(ip) {
-		p.Host.AdvertiseIP = iputils.HostIP
+		p.Host.AdvertiseIP = iputils.IPv4
 	} else {
 		p.Host.AdvertiseIP = ip.String()
 	}
diff --git a/client/config/peerhost_darwin.go b/client/config/peerhost_darwin.go
index 58029cb2..f6f357b5 100644
--- a/client/config/peerhost_darwin.go
+++ b/client/config/peerhost_darwin.go
@@ -27,6 +27,7 @@ import (
 	"d7y.io/dragonfly/v2/client/clientutil"
 	"d7y.io/dragonfly/v2/pkg/basic"
 	"d7y.io/dragonfly/v2/pkg/basic/dfnet"
+	"d7y.io/dragonfly/v2/pkg/util/hostutils"
 	"d7y.io/dragonfly/v2/pkg/util/net/iputils"
 )
 
@@ -57,9 +58,9 @@ var peerHostConfig = DaemonOption{
 		ScheduleTimeout: clientutil.Duration{Duration: DefaultScheduleTimeout},
 	},
 	Host: HostOption{
-		Hostname:       iputils.HostName,
+		Hostname:       hostutils.Hostname,
 		ListenIP:       net.IPv4zero.String(),
-		AdvertiseIP:    iputils.HostIP,
+		AdvertiseIP:    iputils.IPv4,
 		SecurityDomain: "",
 		Location:       "",
 		IDC:            "",
diff --git a/client/config/peerhost_linux.go b/client/config/peerhost_linux.go
index be861e21..d735dc7b 100644
--- a/client/config/peerhost_linux.go
+++ b/client/config/peerhost_linux.go
@@ -27,6 +27,7 @@ import (
 	"d7y.io/dragonfly/v2/client/clientutil"
 	"d7y.io/dragonfly/v2/pkg/basic"
 	"d7y.io/dragonfly/v2/pkg/basic/dfnet"
+	"d7y.io/dragonfly/v2/pkg/util/hostutils"
 	"d7y.io/dragonfly/v2/pkg/util/net/iputils"
 )
 
@@ -57,9 +58,9 @@ var peerHostConfig = DaemonOption{
 		ScheduleTimeout: clientutil.Duration{Duration: DefaultScheduleTimeout},
 	},
 	Host: HostOption{
-		Hostname:       iputils.HostName,
+		Hostname:       hostutils.Hostname,
 		ListenIP:       "0.0.0.0",
-		AdvertiseIP:    iputils.HostIP,
+		AdvertiseIP:    iputils.IPv4,
 		SecurityDomain: "",
 		Location:       "",
 		IDC:            "",
diff --git a/cmd/dependency/dependency.go b/cmd/dependency/dependency.go
index 00dee5aa..b7dcd75c 100644
--- a/cmd/dependency/dependency.go
+++ b/cmd/dependency/dependency.go
@@ -51,6 +51,7 @@ import (
 	"d7y.io/dragonfly/v2/internal/dfpath"
 	"d7y.io/dragonfly/v2/pkg/basic/dfnet"
 	"d7y.io/dragonfly/v2/pkg/unit"
+	"d7y.io/dragonfly/v2/pkg/util/hostutils"
 	"d7y.io/dragonfly/v2/pkg/util/net/iputils"
 	"d7y.io/dragonfly/v2/version"
 )
@@ -103,7 +104,7 @@ func InitMonitor(verbose bool, pprofPort int, otelOption base.TelemetryOption) f
 				pprofPort, _ = freeport.GetFreePort()
 			}
 
-			debugAddr := fmt.Sprintf("%s:%d", iputils.HostIP, pprofPort)
+			debugAddr := fmt.Sprintf("%s:%d", iputils.IPv4, pprofPort)
 			viewer.SetConfiguration(viewer.WithAddr(debugAddr))
 
 			logger.With("pprof", fmt.Sprintf("http://%s/debug/pprof", debugAddr),
@@ -242,7 +243,7 @@ func initJaegerTracer(otelOption base.TelemetryOption) (func(), error) {
 		// Record information about this application in an Resource.
 		sdktrace.WithResource(resource.NewWithAttributes(
 			semconv.ServiceNameKey.String(otelOption.ServiceName),
-			semconv.ServiceInstanceIDKey.String(fmt.Sprintf("%s|%s", iputils.HostName, iputils.HostIP)),
+			semconv.ServiceInstanceIDKey.String(fmt.Sprintf("%s|%s", hostutils.FQDNHostname, iputils.IPv4)),
 			semconv.ServiceNamespaceKey.String("dragonfly"),
 			semconv.ServiceVersionKey.String(version.GitVersion))),
 	)
diff --git a/cmd/dfget/cmd/root.go b/cmd/dfget/cmd/root.go
index f06c741f..2976aa9d 100644
--- a/cmd/dfget/cmd/root.go
+++ b/cmd/dfget/cmd/root.go
@@ -84,7 +84,7 @@ var rootCmd = &cobra.Command{
 
 		fmt.Printf("--%s--  %s\n", start.Format("2006-01-02 15:04:05"), dfgetConfig.URL)
 		fmt.Printf("dfget version: %s\n", version.GitVersion)
-		fmt.Printf("current user: %s, default peer ip: %s\n", basic.Username, iputils.HostIP)
+		fmt.Printf("current user: %s, default peer ip: %s\n", basic.Username, iputils.IPv4)
 		fmt.Printf("output path: %s\n", dfgetConfig.Output)
 
 		//  do get file
diff --git a/go.mod b/go.mod
index bf5003af..c3a1fc2c 100644
--- a/go.mod
+++ b/go.mod
@@ -4,6 +4,7 @@ go 1.15
 
 require (
 	github.com/RichardKnop/machinery v1.10.6
+	github.com/Showmax/go-fqdn v1.0.0
 	github.com/VividCortex/mysqlerr v1.0.0
 	github.com/agiledragon/gomonkey v2.0.2+incompatible
 	github.com/aliyun/aliyun-oss-go-sdk v2.1.6+incompatible
diff --git a/go.sum b/go.sum
index 7cb2c69a..d2d082e4 100644
--- a/go.sum
+++ b/go.sum
@@ -61,6 +61,8 @@ github.com/RichardKnop/logging v0.0.0-20190827224416-1a693bdd4fae/go.mod h1:rJJ8
 github.com/RichardKnop/machinery v1.10.6 h1:wviOkVLVM9DaNFAOtXEuZsr9d+Okm4VSw7AILVLIhyc=
 github.com/RichardKnop/machinery v1.10.6/go.mod h1:qT0dXDPzsGqwHoYWO12Gb25MxA/9HfxaqdIaZp9ofWM=
 github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
+github.com/Showmax/go-fqdn v1.0.0 h1:0rG5IbmVliNT5O19Mfuvna9LL7zlHyRfsSvBPZmF9tM=
+github.com/Showmax/go-fqdn v1.0.0/go.mod h1:SfrFBzmDCtCGrnHhoDjuvFnKsWjEQX/Q9ARZvOrJAko=
 github.com/VividCortex/mysqlerr v1.0.0 h1:5pZ2TZA+YnzPgzBfiUWGqWmKDVNBdrkf9g+DNe1Tiq8=
 github.com/VividCortex/mysqlerr v1.0.0/go.mod h1:xERx8E4tBhLvpjzdUyQiSfUxeMcATEQrflDAfXsqcAE=
 github.com/agiledragon/gomonkey v2.0.2+incompatible h1:eXKi9/piiC3cjJD1658mEE2o3NjkJ5vDLgYjCQu0Xlw=
diff --git a/internal/idgen/host_id.go b/internal/idgen/host_id.go
new file mode 100644
index 00000000..894200aa
--- /dev/null
+++ b/internal/idgen/host_id.go
@@ -0,0 +1,29 @@
+/*
+ *     Copyright 2020 The Dragonfly Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package idgen
+
+import (
+	"fmt"
+)
+
+func HostID(hostname string, port int32) string {
+	return fmt.Sprintf("%s-%d", hostname, port)
+}
+
+func CDNHostID(hostname string, port int32) string {
+	return fmt.Sprintf("%s_CDN", HostID(hostname, port))
+}
diff --git a/internal/idgen/uuid.go b/internal/idgen/uuid.go
index ddc6427e..7684705e 100644
--- a/internal/idgen/uuid.go
+++ b/internal/idgen/uuid.go
@@ -17,15 +17,9 @@
 package idgen
 
 import (
-	"fmt"
-
 	"github.com/google/uuid"
 )
 
 func UUIDString() string {
 	return uuid.New().String()
 }
-
-func CDN(cdnHostname string, serverPort int32) string {
-	return fmt.Sprintf("%s-%d_CDN", cdnHostname, serverPort)
-}
diff --git a/pkg/rpc/cdnsystem/server/server.go b/pkg/rpc/cdnsystem/server/server.go
index 0d335400..4d2dfdc7 100644
--- a/pkg/rpc/cdnsystem/server/server.go
+++ b/pkg/rpc/cdnsystem/server/server.go
@@ -32,6 +32,7 @@ import (
 	"d7y.io/dragonfly/v2/pkg/rpc/base"
 	"d7y.io/dragonfly/v2/pkg/rpc/cdnsystem"
 	"d7y.io/dragonfly/v2/pkg/safe"
+	"d7y.io/dragonfly/v2/pkg/util/hostutils"
 	"d7y.io/dragonfly/v2/pkg/util/net/iputils"
 )
 
@@ -136,8 +137,8 @@ func StatSeedStart(taskID, url string) {
 	logger.StatSeedLogger.Info("Start Seed",
 		zap.String("TaskID", taskID),
 		zap.String("URL", url),
-		zap.String("SeederIp", iputils.HostIP),
-		zap.String("SeederHostName", iputils.HostName))
+		zap.String("SeederIP", iputils.IPv4),
+		zap.String("SeederHostname", hostutils.FQDNHostname))
 }
 
 func StatSeedFinish(taskID, url string, success bool, err error, startAt, finishAt time.Time, traffic, contentLength int64) {
@@ -147,8 +148,8 @@ func StatSeedFinish(taskID, url string, success bool, err error, startAt, finish
 		zap.Bool("Success", success),
 		zap.String("TaskID", taskID),
 		zap.String("URL", url),
-		zap.String("SeederIp", iputils.HostIP),
-		zap.String("SeederHostName", iputils.HostName),
+		zap.String("SeederIP", iputils.IPv4),
+		zap.String("SeederHostname", hostutils.FQDNHostname),
 		zap.Time("StartAt", startAt),
 		zap.Time("FinishAt", finishAt),
 		zap.Int64("Traffic", traffic),
diff --git a/pkg/rpc/manager/manager.pb.go b/pkg/rpc/manager/manager.pb.go
index ed84a383..a65c7f01 100644
--- a/pkg/rpc/manager/manager.pb.go
+++ b/pkg/rpc/manager/manager.pb.go
@@ -22,12 +22,13 @@
 package manager
 
 import (
+	reflect "reflect"
+	sync "sync"
+
 	_ "github.com/envoyproxy/protoc-gen-validate/validate"
 	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
 	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
 	emptypb "google.golang.org/protobuf/types/known/emptypb"
-	reflect "reflect"
-	sync "sync"
 )
 
 const (
diff --git a/pkg/rpc/scheduler/server/server.go b/pkg/rpc/scheduler/server/server.go
index 91e26c08..3b695916 100644
--- a/pkg/rpc/scheduler/server/server.go
+++ b/pkg/rpc/scheduler/server/server.go
@@ -26,6 +26,7 @@ import (
 	logger "d7y.io/dragonfly/v2/internal/dflog"
 	"d7y.io/dragonfly/v2/pkg/rpc"
 	"d7y.io/dragonfly/v2/pkg/rpc/scheduler"
+	"d7y.io/dragonfly/v2/pkg/util/hostutils"
 	"d7y.io/dragonfly/v2/pkg/util/net/iputils"
 	"d7y.io/dragonfly/v2/scheduler/metrics"
 )
@@ -67,8 +68,8 @@ func (p *proxy) RegisterPeerTask(ctx context.Context, req *scheduler.PeerTaskReq
 		zap.Bool("Success", isSuccess),
 		zap.String("URL", req.Url),
 		zap.String("TaskID", resp.TaskId),
-		zap.String("SchedulerIP", iputils.HostIP),
-		zap.String("SchedulerHostName", iputils.HostName),
+		zap.String("SchedulerIP", iputils.IPv4),
+		zap.String("SchedulerHostname", hostutils.FQDNHostname),
 		zap.Any("Peer", req.PeerHost),
 	)
 
@@ -99,8 +100,8 @@ func (p *proxy) ReportPeerResult(ctx context.Context, req *scheduler.PeerResult)
 		zap.String("PeerIP", req.SrcIp),
 		zap.String("SecurityDomain", req.SecurityDomain),
 		zap.String("IDC", req.Idc),
-		zap.String("SchedulerIP", iputils.HostIP),
-		zap.String("SchedulerHostName", iputils.HostName),
+		zap.String("SchedulerIP", iputils.IPv4),
+		zap.String("SchedulerHostname", hostutils.FQDNHostname),
 		zap.Int64("ContentLength", req.ContentLength),
 		zap.Int64("Traffic", req.Traffic),
 		zap.Uint32("Cost", req.Cost),
diff --git a/pkg/util/hostutils/host_utils.go b/pkg/util/hostutils/host_utils.go
new file mode 100644
index 00000000..0dcced1f
--- /dev/null
+++ b/pkg/util/hostutils/host_utils.go
@@ -0,0 +1,51 @@
+/*
+ *     Copyright 2020 The Dragonfly Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package hostutils
+
+import (
+	"os"
+
+	"github.com/Showmax/go-fqdn"
+)
+
+var Hostname string
+var FQDNHostname string
+
+func init() {
+	Hostname = hostname()
+	FQDNHostname = fqdnHostname()
+}
+
+// Get kernel hostname
+func hostname() string {
+	name, err := os.Hostname()
+	if err != nil {
+		panic(err)
+	}
+
+	return name
+}
+
+// Get FQDN hostname
+func fqdnHostname() string {
+	fqdn, err := fqdn.FqdnHostname()
+	if err != nil {
+		panic(err)
+	}
+
+	return fqdn
+}
diff --git a/pkg/util/net/iputils/ip_utils.go b/pkg/util/net/iputils/ip_utils.go
index 3041d8b0..98a7e9e3 100644
--- a/pkg/util/net/iputils/ip_utils.go
+++ b/pkg/util/net/iputils/ip_utils.go
@@ -24,23 +24,15 @@ import (
 	"github.com/pkg/errors"
 )
 
-var HostIP string
-var HostName string
+var IPv4 string
 
 func init() {
 	ip, err := externalIPv4()
-	if ip == "" {
+	if err != nil {
 		panic(err)
-	} else {
-		HostIP = ip
 	}
 
-	name, err := os.Hostname()
-	if name == "" {
-		panic(err)
-	} else {
-		HostName = name
-	}
+	IPv4 = ip
 }
 
 // IsIPv4 returns whether the ip is a valid IPv4 Address.
@@ -83,6 +75,7 @@ func externalIPv4() (string, error) {
 }
 
 // ipAddrs returns all the valid IPs available.
+// refer to https://github.com/dragonflyoss/Dragonfly2/pull/652
 func ipAddrs() ([]net.IP, error) {
 	// use prefer ip possible
 	var prefer []net.IP
diff --git a/scheduler/config/config.go b/scheduler/config/config.go
index 0ffdc7af..f82c8040 100644
--- a/scheduler/config/config.go
+++ b/scheduler/config/config.go
@@ -25,6 +25,7 @@ import (
 
 	"d7y.io/dragonfly/v2/cmd/dependency/base"
 	dc "d7y.io/dragonfly/v2/internal/dynconfig"
+	"d7y.io/dragonfly/v2/pkg/util/hostutils"
 	"d7y.io/dragonfly/v2/pkg/util/net/iputils"
 )
 
@@ -62,8 +63,8 @@ func New() *Config {
 			},
 		},
 		Server: &ServerConfig{
-			IP:   iputils.HostIP,
-			Host: iputils.HostName,
+			IP:   iputils.IPv4,
+			Host: hostutils.FQDNHostname,
 			Port: 8002,
 		},
 		DynConfig: &DynConfig{
diff --git a/scheduler/config/dynconfig.go b/scheduler/config/dynconfig.go
index 3ad3af81..97b80e2f 100644
--- a/scheduler/config/dynconfig.go
+++ b/scheduler/config/dynconfig.go
@@ -29,7 +29,6 @@ import (
 	"d7y.io/dragonfly/v2/manager/types"
 	"d7y.io/dragonfly/v2/pkg/rpc/manager"
 	managerclient "d7y.io/dragonfly/v2/pkg/rpc/manager/client"
-	"d7y.io/dragonfly/v2/pkg/util/net/iputils"
 )
 
 var (
@@ -322,21 +321,21 @@ func (d *dynconfig) Stop() error {
 
 type managerClient struct {
 	managerclient.Client
-	SchedulerClusterID uint
+	config *Config
 }
 
-func NewManagerClient(client managerclient.Client, schedulerClusterID uint) dc.ManagerClient {
+func NewManagerClient(client managerclient.Client, cfg *Config) dc.ManagerClient {
 	return &managerClient{
-		Client:             client,
-		SchedulerClusterID: schedulerClusterID,
+		Client: client,
+		config: cfg,
 	}
 }
 
 func (mc *managerClient) Get() (interface{}, error) {
 	scheduler, err := mc.GetScheduler(&manager.GetSchedulerRequest{
-		HostName:           iputils.HostName,
+		HostName:           mc.config.Server.Host,
 		SourceType:         manager.SourceType_SCHEDULER_SOURCE,
-		SchedulerClusterId: uint64(mc.SchedulerClusterID),
+		SchedulerClusterId: uint64(mc.config.Manager.SchedulerClusterID),
 	})
 	if err != nil {
 		return nil, err
diff --git a/scheduler/scheduler.go b/scheduler/scheduler.go
index bdaf22b7..453bdcdd 100644
--- a/scheduler/scheduler.go
+++ b/scheduler/scheduler.go
@@ -31,7 +31,6 @@ import (
 	"d7y.io/dragonfly/v2/pkg/rpc"
 	"d7y.io/dragonfly/v2/pkg/rpc/manager"
 	managerclient "d7y.io/dragonfly/v2/pkg/rpc/manager/client"
-	"d7y.io/dragonfly/v2/pkg/util/net/iputils"
 	"d7y.io/dragonfly/v2/scheduler/config"
 	"d7y.io/dragonfly/v2/scheduler/core"
 	"d7y.io/dragonfly/v2/scheduler/job"
@@ -98,7 +97,7 @@ func New(cfg *config.Config) (*Server, error) {
 	options := []dynconfig.Option{dynconfig.WithLocalConfigPath(dependency.GetConfigPath("scheduler"))}
 	if s.managerClient != nil && cfg.DynConfig.Type == dynconfig.ManagerSourceType {
 		options = append(options,
-			dynconfig.WithManagerClient(config.NewManagerClient(s.managerClient, cfg.Manager.SchedulerClusterID)),
+			dynconfig.WithManagerClient(config.NewManagerClient(s.managerClient, cfg)),
 			dynconfig.WithExpireTime(cfg.DynConfig.ExpireTime),
 		)
 	}
@@ -140,7 +139,7 @@ func New(cfg *config.Config) (*Server, error) {
 
 	// Initialize job service
 	if cfg.Job.Redis.Host != "" {
-		s.job, err = job.New(context.Background(), cfg.Job, cfg.Manager.SchedulerClusterID, iputils.HostName, s.service)
+		s.job, err = job.New(context.Background(), cfg.Job, cfg.Manager.SchedulerClusterID, cfg.Server.Host, s.service)
 		if err != nil {
 			return nil, err
 		}
diff --git a/scheduler/supervisor/cdn.go b/scheduler/supervisor/cdn.go
index 5fe350a0..ab8d35f6 100644
--- a/scheduler/supervisor/cdn.go
+++ b/scheduler/supervisor/cdn.go
@@ -317,7 +317,7 @@ func cdnsToHosts(cdns []*config.CDN) map[string]*Host {
 			}
 		}
 
-		id := idgen.CDN(cdn.HostName, cdn.Port)
+		id := idgen.CDNHostID(cdn.HostName, cdn.Port)
 		hosts[id] = NewCDNHost(id, cdn.IP, cdn.HostName, cdn.Port, cdn.DownloadPort, cdn.SecurityGroup, cdn.Location, cdn.IDC, options...)
 	}
 


Test patch:
diff --git a/internal/idgen/host_id_test.go b/internal/idgen/host_id_test.go
new file mode 100644
index 00000000..baa8c404
--- /dev/null
+++ b/internal/idgen/host_id_test.go
@@ -0,0 +1,109 @@
+/*
+ *     Copyright 2020 The Dragonfly Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package idgen
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestHostID(t *testing.T) {
+	tests := []struct {
+		name     string
+		hostname string
+		port     int32
+		expect   func(t *testing.T, d string)
+	}{
+		{
+			name:     "generate HostID",
+			hostname: "foo",
+			port:     8000,
+			expect: func(t *testing.T, d string) {
+				assert := assert.New(t)
+				assert.Len(d, 8)
+			},
+		},
+		{
+			name:     "generate HostID with empty host",
+			hostname: "",
+			port:     8000,
+			expect: func(t *testing.T, d string) {
+				assert := assert.New(t)
+				assert.Len(d, 5)
+			},
+		},
+		{
+			name:     "generate HostID with zero port",
+			hostname: "foo",
+			port:     0,
+			expect: func(t *testing.T, d string) {
+				assert := assert.New(t)
+				assert.Len(d, 5)
+			},
+		},
+	}
+
+	for _, tc := range tests {
+		t.Run(tc.name, func(t *testing.T) {
+			tc.expect(t, HostID(tc.hostname, tc.port))
+		})
+	}
+}
+
+func TestCDNHostID(t *testing.T) {
+	tests := []struct {
+		name     string
+		hostname string
+		port     int32
+		expect   func(t *testing.T, d string)
+	}{
+		{
+			name:     "generate CDNHostID with ipv4",
+			hostname: "foo",
+			port:     8000,
+			expect: func(t *testing.T, d string) {
+				assert := assert.New(t)
+				assert.Len(d, 12)
+			},
+		},
+		{
+			name:     "generate CDNHostID with empty string",
+			hostname: "",
+			port:     8000,
+			expect: func(t *testing.T, d string) {
+				assert := assert.New(t)
+				assert.Len(d, 9)
+			},
+		},
+		{
+			name:     "generate CDNHostID with zero port",
+			hostname: "foo",
+			port:     0,
+			expect: func(t *testing.T, d string) {
+				assert := assert.New(t)
+				assert.Len(d, 9)
+			},
+		},
+	}
+
+	for _, tc := range tests {
+		t.Run(tc.name, func(t *testing.T) {
+			tc.expect(t, CDNHostID(tc.hostname, tc.port))
+		})
+	}
+}
diff --git a/internal/idgen/peer_id_test.go b/internal/idgen/peer_id_test.go
index 6d6d7002..6ba937b3 100644
--- a/internal/idgen/peer_id_test.go
+++ b/internal/idgen/peer_id_test.go
@@ -69,7 +69,7 @@ func TestCDNPeerID(t *testing.T) {
 		expect func(t *testing.T, d interface{})
 	}{
 		{
-			name: "generate id with ipv4",
+			name: "generate CDNPeerID with ipv4",
 			ip:   "127.0.0.1",
 			expect: func(t *testing.T, d interface{}) {
 				assert := assert.New(t)
@@ -77,7 +77,7 @@ func TestCDNPeerID(t *testing.T) {
 			},
 		},
 		{
-			name: "generate id with ipv6",
+			name: "generate CDNPeerID with ipv6",
 			ip:   "2001:0db8:3c4d:0015:0000:0000:1a2f:1a2b",
 			expect: func(t *testing.T, d interface{}) {
 				assert := assert.New(t)
@@ -85,7 +85,7 @@ func TestCDNPeerID(t *testing.T) {
 			},
 		},
 		{
-			name: "generate id with empty string",
+			name: "generate CDNPeerID with empty string",
 			ip:   "",
 			expect: func(t *testing.T, d interface{}) {
 				assert := assert.New(t)
diff --git a/pkg/util/hostutils/host_utils_test.go b/pkg/util/hostutils/host_utils_test.go
new file mode 100644
index 00000000..503d790b
--- /dev/null
+++ b/pkg/util/hostutils/host_utils_test.go
@@ -0,0 +1,33 @@
+/*
+ *     Copyright 2020 The Dragonfly Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package hostutils
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestHostname(t *testing.T) {
+	hostname := hostname()
+	assert.NotEmpty(t, hostname)
+}
+
+func TestFQDNHostname(t *testing.T) {
+	fqdn := fqdnHostname()
+	assert.NotEmpty(t, fqdn)
+}
diff --git a/pkg/util/net/iputils/ip_utils_test.go b/pkg/util/net/iputils/ip_utils_test.go
index ca7bce83..e5d70d06 100644
--- a/pkg/util/net/iputils/ip_utils_test.go
+++ b/pkg/util/net/iputils/ip_utils_test.go
@@ -17,22 +17,13 @@
 package iputils
 
 import (
-	"fmt"
 	"testing"
 
 	"github.com/stretchr/testify/assert"
 )
 
-func TestIsIPv4(t *testing.T) {
-	assert.True(t, IsIPv4("30.225.24.222"))
-	assert.False(t, IsIPv4("30.225.24.2222"))
-}
-
 func TestExternalIPv4(t *testing.T) {
 	ip, err := externalIPv4()
 	assert.Nil(t, err)
-
-	fmt.Println(ip)
-
 	assert.NotEmpty(t, ip)
 }
diff --git a/scheduler/config/dynconfig_test.go b/scheduler/config/dynconfig_test.go
index 0718a379..5280311d 100644
--- a/scheduler/config/dynconfig_test.go
+++ b/scheduler/config/dynconfig_test.go
@@ -113,7 +113,10 @@ func TestDynconfigGet_ManagerSourceType(t *testing.T) {
 			tc.mock(mockManagerClient.EXPECT())
 
 			d, err := NewDynconfig(dc.ManagerSourceType, "", []dc.Option{
-				dc.WithManagerClient(NewManagerClient(mockManagerClient, uint(1))),
+				dc.WithManagerClient(NewManagerClient(mockManagerClient, &Config{
+					Manager: &ManagerConfig{SchedulerClusterID: uint(1)},
+					Server:  &ServerConfig{Host: "foo"},
+				})),
 				dc.WithCachePath(cachePath),
 				dc.WithExpireTime(tc.expire),
 			}...)
diff --git a/test/tools/stress/main.go b/test/tools/stress/main.go
index 358ba624..0f05d29e 100644
--- a/test/tools/stress/main.go
+++ b/test/tools/stress/main.go
@@ -129,7 +129,7 @@ loop:
 }
 
 func debug() {
-	debugAddr := fmt.Sprintf("%s:%d", iputils.HostIP, 18066)
+	debugAddr := fmt.Sprintf("%s:%d", iputils.IPv4, 18066)
 	viewer.SetConfiguration(viewer.WithAddr(debugAddr))
 	if err := statsview.New().Start(); err != nil {
 		log.Println("stat view start failed", err)