Repository: dragonflyoss/Dragonfly2
Pull request #468 (2021-07-16 15:54:24)

Fix address typo
<!--- Provide a general summary of your changes in the Title above -->

## Description
fix the address (addr) typo and improvement a comment.
<!--- 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)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to change)
- [x] 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.
- [ ] I have added tests to cover my changes.
- [x] All new and existing tests passed.



Patch:
diff --git a/cdnsystem/server/server.go b/cdnsystem/server/server.go
index 34705275..7b7011f4 100644
--- a/cdnsystem/server/server.go
+++ b/cdnsystem/server/server.go
@@ -164,9 +164,7 @@ func (s *Server) register(ctx context.Context) error {
 	location := s.config.Host.Location
 	downloadPort := int32(s.config.DownloadPort)
 
-	var cdn *manager.CDN
-	var err error
-	cdn, err = s.managerClient.CreateCDN(ctx, &manager.CreateCDNRequest{
+	cdn, err := s.managerClient.UpdateCDN(ctx, &manager.UpdateCDNRequest{
 		SourceType:   manager.SourceType_CDN_SOURCE,
 		HostName:     iputils.HostName,
 		Ip:           ip,
@@ -176,22 +174,10 @@ func (s *Server) register(ctx context.Context) error {
 		DownloadPort: downloadPort,
 	})
 	if err != nil {
-		cdn, err = s.managerClient.UpdateCDN(ctx, &manager.UpdateCDNRequest{
-			SourceType:   manager.SourceType_CDN_SOURCE,
-			HostName:     iputils.HostName,
-			Ip:           ip,
-			Port:         port,
-			Idc:          idc,
-			Location:     location,
-			DownloadPort: downloadPort,
-		})
-		if err != nil {
-			logger.Errorf("update cdn to manager failed %v", err)
-			return err
-		}
-		logger.Infof("update cdn %s successfully", cdn.HostName)
+		logger.Errorf("update cdn %s to manager failed %v", cdn.HostName, err)
+		return err
 	}
-	logger.Infof("create cdn %s successfully", cdn.HostName)
+	logger.Infof("update cdn %s to manager successfully", cdn.HostName)
 
 	cdnClusterID := s.config.Manager.CDNClusterID
 	if cdnClusterID != 0 {
@@ -199,7 +185,7 @@ func (s *Server) register(ctx context.Context) error {
 			CdnId:        cdn.Id,
 			CdnClusterId: cdnClusterID,
 		}); err != nil {
-			logger.Warnf("add cdn to cdn cluster failed %v", err)
+			logger.Warnf("add cdn %s to cdn cluster %s failed %v", cdn.HostName, cdnClusterID, err)
 			return err
 		}
 		logger.Infof("add cdn %s to cdn cluster %s successfully", cdn.HostName, cdnClusterID)
diff --git a/client/config/constants.go b/client/config/constants.go
index c9a88621..651e37e3 100644
--- a/client/config/constants.go
+++ b/client/config/constants.go
@@ -69,6 +69,8 @@ const (
 	DefaultSchedulerSchema = "http"
 	DefaultSchedulerIP     = "127.0.0.1"
 	DefaultSchedulerPort   = 8002
+
+	DefaultPieceChanSize = 16
 )
 
 const (
diff --git a/client/daemon/peer/peertask_base.go b/client/daemon/peer/peertask_base.go
index 81206e0f..99c9f39d 100644
--- a/client/daemon/peer/peertask_base.go
+++ b/client/daemon/peer/peertask_base.go
@@ -117,7 +117,7 @@ type peerTask struct {
 	// requestedPieces stands all pieces requested from peers
 	requestedPieces *Bitmap
 	// lock used by piece result manage, when update readyPieces, lock first
-	lock sync.Mutex
+	lock sync.RWMutex
 	// limiter will be used when enable per peer task rate limit
 	limiter *rate.Limiter
 }
@@ -364,11 +364,12 @@ func (pt *peerTask) pullPiecesFromPeers(pti Task, cleanUnfinishedFunc func()) {
 		return
 	}
 	var (
-		num             int32
-		limit           int32
-		initialized     bool
-		pieceRequestCh  chan *DownloadPieceRequest
-		pieceBufferSize = int32(16)
+		num            int32
+		limit          int32
+		initialized    bool
+		pieceRequestCh chan *DownloadPieceRequest
+		// keep same size with pt.failedPieceCh for avoiding dead lock
+		pieceBufferSize = int32(config.DefaultPieceChanSize)
 	)
 loop:
 	for {
@@ -525,6 +526,13 @@ func (pt *peerTask) downloadPieceWorker(id int32, pti Task, requests chan *Downl
 	for {
 		select {
 		case request := <-requests:
+			pt.lock.RLock()
+			if pt.readyPieces.IsSet(request.piece.PieceNum) {
+				pt.lock.RUnlock()
+				pt.Log().Debugf("piece %d is already downloaded, skip", request.piece.PieceNum)
+				continue
+			}
+			pt.lock.RUnlock()
 			ctx, span := tracer.Start(pt.ctx, fmt.Sprintf(config.SpanDownloadPiece, request.piece.PieceNum))
 			span.SetAttributes(config.AttributePiece.Int(int(request.piece.PieceNum)))
 			span.SetAttributes(config.AttributePieceWorker.Int(int(id)))
diff --git a/client/daemon/peer/peertask_file.go b/client/daemon/peer/peertask_file.go
index 6cf63735..7f481963 100644
--- a/client/daemon/peer/peertask_file.go
+++ b/client/daemon/peer/peertask_file.go
@@ -175,7 +175,7 @@ func newFilePeerTask(ctx context.Context,
 			once:                sync.Once{},
 			readyPieces:         NewBitmap(),
 			requestedPieces:     NewBitmap(),
-			failedPieceCh:       make(chan int32, 4),
+			failedPieceCh:       make(chan int32, config.DefaultPieceChanSize),
 			failedReason:        failedReasonNotSet,
 			failedCode:          dfcodes.UnknownError,
 			contentLength:       -1,
diff --git a/client/daemon/peer/peertask_stream.go b/client/daemon/peer/peertask_stream.go
index d58b4243..216c777d 100644
--- a/client/daemon/peer/peertask_stream.go
+++ b/client/daemon/peer/peertask_stream.go
@@ -153,7 +153,7 @@ func newStreamPeerTask(ctx context.Context,
 			span:                span,
 			readyPieces:         NewBitmap(),
 			requestedPieces:     NewBitmap(),
-			failedPieceCh:       make(chan int32, 4),
+			failedPieceCh:       make(chan int32, config.DefaultPieceChanSize),
 			failedReason:        failedReasonNotSet,
 			failedCode:          dfcodes.UnknownError,
 			contentLength:       -1,
diff --git a/client/daemon/service/manager.go b/client/daemon/service/manager.go
index eea3ce9f..31f0380f 100644
--- a/client/daemon/service/manager.go
+++ b/client/daemon/service/manager.go
@@ -136,7 +136,7 @@ func (m *manager) CheckHealth(context.Context) error {
 func (m *manager) Download(ctx context.Context,
 	req *dfdaemongrpc.DownRequest, results chan<- *dfdaemongrpc.DownResult) error {
 	m.Keep()
-	// init peer task request, peer download request uses different peer id
+	// init peer task request, peer uses different peer id to generate every request
 	peerTask := &peer.FilePeerTaskRequest{
 		PeerTaskRequest: scheduler.PeerTaskRequest{
 			Url:      req.Url,
diff --git a/deploy/docker-compose/README.md b/deploy/docker-compose/README.md
new file mode 100644
index 00000000..fea7c891
--- /dev/null
+++ b/deploy/docker-compose/README.md
@@ -0,0 +1,13 @@
+# Deploying Dragonfly with Docker Compose
+
+> Currently, docker compose deploying is tested just in single host, no HA support.
+
+## Deploy
+
+The `run.sh` script will generate config and deploy all components with `docker-compose`.
+
+Just run:
+
+```shell
+./run.sh
+```
\ No newline at end of file
diff --git a/deploy/docker-compose/config/.gitignore b/deploy/docker-compose/config/.gitignore
new file mode 100644
index 00000000..fcb647e1
--- /dev/null
+++ b/deploy/docker-compose/config/.gitignore
@@ -0,0 +1,3 @@
+cdn.json
+cdn.yaml
+dfget.yaml
diff --git a/deploy/docker-compose/config/nginx.conf b/deploy/docker-compose/config/nginx.conf
new file mode 100644
index 00000000..26e672f1
--- /dev/null
+++ b/deploy/docker-compose/config/nginx.conf
@@ -0,0 +1,51 @@
+worker_rlimit_nofile        100000;
+
+events {
+    use                     epoll;
+    worker_connections      20480;
+}
+
+http {
+    include                 mime.types;
+    default_type            application/octet-stream;
+    root                    /home/admin/cai/htdocs;
+    sendfile                on;
+    tcp_nopush              on;
+
+    server_tokens           off;
+    keepalive_timeout       5;
+
+    client_header_timeout   1m;
+    send_timeout            1m;
+    client_max_body_size    3m;
+
+    index                   index.html index.htm;
+    access_log              off;
+    log_not_found           off;
+
+    gzip                    on;
+    gzip_http_version       1.0;
+    gzip_comp_level         6;
+    gzip_min_length         1024;
+    gzip_proxied            any;
+    gzip_vary               on;
+    gzip_disable            msie6;
+    gzip_buffers            96 8k;
+    gzip_types              text/xml text/plain text/css application/javascript application/x-javascript application/rss+xml application/json;
+
+    proxy_set_header        Host $host;
+    proxy_set_header        X-Real-IP $remote_addr;
+    proxy_set_header        Web-Server-Type nginx;
+    proxy_set_header        WL-Proxy-Client-IP $remote_addr;
+    proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
+    proxy_redirect          off;
+    proxy_buffers           128 8k;
+    proxy_intercept_errors  on;
+
+    server {
+        listen              8001;
+        location / {
+            root /tmp/cdn;
+        }
+    }
+}
diff --git a/deploy/docker-compose/config/scheduler.yaml b/deploy/docker-compose/config/scheduler.yaml
new file mode 100644
index 00000000..08bc1a29
--- /dev/null
+++ b/deploy/docker-compose/config/scheduler.yaml
@@ -0,0 +1,13 @@
+verbose: true
+
+server:
+  port: 8002
+
+worker:
+  workerNum: 4
+  workerJobPoolSize: 10000
+  senderNum: 10
+  senderJobPoolSize: 10000
+
+dynconfig:
+  cdnDirPath: /opt/dragonfly/scheduler-cdn
diff --git a/deploy/docker-compose/docker-compose.yaml b/deploy/docker-compose/docker-compose.yaml
new file mode 100644
index 00000000..f7050358
--- /dev/null
+++ b/deploy/docker-compose/docker-compose.yaml
@@ -0,0 +1,32 @@
+version: "3.9"
+services:
+  dfdaemon:
+    image: dragonflyoss/dfdaemon:v2.0.0-alpha
+    depends_on:
+    - scheduler
+    - cdn
+    container_name: dfdaemon
+    network_mode: host
+    volumes:
+    - /tmp/log/dragonfly:/var/log/dragonfly
+    - ./config/dfget.yaml:/etc/dragonfly/dfget.yaml
+
+  scheduler:
+    image: dragonflyoss/scheduler:v2.0.0-alpha
+    depends_on:
+    - cdn
+    container_name: scheduler
+    network_mode: host
+    volumes:
+    - /tmp/log/dragonfly:/var/log/dragonfly
+    - ./config/scheduler.yaml:/etc/dragonfly/scheduler.yaml
+    - ./config/cdn.json:/opt/dragonfly/scheduler-cdn/cdn.json
+
+  cdn:
+    image: dragonflyoss/cdn:v2.0.0-alpha
+    container_name: cdn
+    network_mode: host
+    volumes:
+    - /tmp/log/dragonfly:/var/log/dragonfly
+    - ./config/cdn.yaml:/etc/dragonfly/cdn.yaml
+    - ./config/nginx.conf:/etc/nginx/nginx.conf
diff --git a/deploy/docker-compose/run.sh b/deploy/docker-compose/run.sh
new file mode 100755
index 00000000..41d14010
--- /dev/null
+++ b/deploy/docker-compose/run.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+set -xe
+
+mkdir -p config
+
+cat template/cdn.template.json > config/cdn.json
+cat template/cdn.template.yaml > config/cdn.yaml
+cat template/dfget.template.yaml > config/dfget.yaml
+
+ip=$(hostname -i)
+hostname=$(hostname)
+
+sed -i "s,__IP__,$ip," config/cdn.json
+sed -i "s,__IP__,$ip," config/dfget.yaml
+sed -i "s,__IP__,$ip," config/cdn.yaml
+
+sed -i "s,__HOSTNAME__,$hostname," config/cdn.json
+
+docker-compose up -d
\ No newline at end of file
diff --git a/deploy/docker-compose/template/cdn.template.json b/deploy/docker-compose/template/cdn.template.json
new file mode 100644
index 00000000..b5bf7164
--- /dev/null
+++ b/deploy/docker-compose/template/cdn.template.json
@@ -0,0 +1,7 @@
+{
+    "host_name": "__HOSTNAME__",
+    "ip": "__IP__",
+    "port": 8003,
+    "download_port": 8001,
+    "status": "active"
+}
\ No newline at end of file
diff --git a/deploy/docker-compose/template/cdn.template.yaml b/deploy/docker-compose/template/cdn.template.yaml
new file mode 100644
index 00000000..67d45932
--- /dev/null
+++ b/deploy/docker-compose/template/cdn.template.yaml
@@ -0,0 +1,73 @@
+# This file is the template of cdn system configuration file.
+# You can configure your cdn system by change the parameter according your requirement.
+---
+base:
+  # listenPort is the port cdn server listens on.
+  # default: 8003
+  listenPort: 8003
+  advertiseIP: __IP__
+
+  # DownloadPort is the port for download files from cdn.
+  # And you should start a file server firstly which listens on the download port.
+  # default: 8001
+  downloadPort: 8001
+
+  # SystemReservedBandwidth is the network bandwidth reserved for system software.
+  # default: 20 MB, in format of G(B)/g/M(B)/m/K(B)/k/B, pure number will also be parsed as Byte.
+  systemReservedBandwidth: 20M
+
+  # MaxBandwidth is the network bandwidth that cdn can use.
+  # default: 200 MB, in format of G(B)/g/M(B)/m/K(B)/k/B, pure number will also be parsed as Byte.
+  maxBandwidth: 1024M
+
+  # Whether to enable profiler
+  # default: false
+  enableProfiler: false
+
+  # FailAccessInterval is the interval time after failed to access the URL.
+  # If a task failed to be downloaded from the source, it will not be retried in the time since the last failure.
+  # default: 3m
+  failAccessInterval: 3m
+
+  # GCInitialDelay is the delay time from the start to the first GC execution.
+  # default: 6s
+  gcInitialDelay: 6s
+
+  # GCMetaInterval is the interval time to execute GC meta.
+  # default: 2m0s
+  gcMetaInterval: 2m
+
+  # gcStorageInterval is the interval time to execute GC storage.
+  # default: 15s
+  gcStorageInterval: 15s
+
+  # TaskExpireTime when a task is not accessed within the taskExpireTime,
+  # and it will be treated to be expired.
+  # default: 3m0s
+  taskExpireTime: 3m
+
+  # StoragePattern is the pattern of storage policy, [disk/hybrid]
+  storagePattern: disk
+
+  # Console shows log on console
+  console: false
+
+plugins:
+  storageDriver:
+  - name: disk
+    enable: true
+    config:
+      baseDir: /tmp/cdn
+  storageManager:
+  - name: disk
+    enable: true
+    config:
+      gcInitialDelay: 5s
+      gcInterval: 15s
+      driverConfigs:
+        disk:
+          gcConfig:
+            youngGCThreshold: 100G
+            fullGCThreshold: 5G
+            cleanRatio: 1
+            intervalThreshold: 2h
diff --git a/deploy/docker-compose/template/dfget.template.yaml b/deploy/docker-compose/template/dfget.template.yaml
new file mode 100644
index 00000000..2d1c763a
--- /dev/null
+++ b/deploy/docker-compose/template/dfget.template.yaml
@@ -0,0 +1,143 @@
+# daemon alive time, when sets 0s, daemon will not auto exit
+aliveTime: 0s
+
+# daemon gc task running interval
+gcInterval: 1m0s
+
+# when daemon exit, keep peer task data or not
+# it is usefully when upgrade daemon service, all local cache will be saved
+keepStorage: true
+
+# all addresses of all schedulers
+# the schedulers of all daemons should be same in one region or zone.
+# daemon will send tasks to a fixed scheduler by hashing the task url and meta data
+# caution: only tcp is supported
+scheduler:
+  # below example is a stand address
+  netAddrs:
+  - type: tcp
+    addr: __IP__:8002
+  # schedule timeout
+  scheduleTimeout: 10s
+
+# when enable, pprof will be enabled,
+verbose: true
+console: false
+
+# current host info used for scheduler
+host:
+  # tcp service listen address
+  # port should be set by other options
+  listenIP: 0.0.0.0
+  # access ip for other peers
+  # when local ip is different with access ip, advertiseIP should be set
+  advertiseIP: __IP__
+  # geographical location and network topology
+  location: ""
+  idc: ""
+  securityDomain: ""
+  netTopology: ""
+
+# download service option
+download:
+  # download limit  per second
+  totalRateLimit: 1024Mi
+  perPeerRateLimit: 1024Mi
+  # download grpc option
+  downloadGRPC:
+    # security option
+    security:
+      insecure: true
+      cacert: ""
+      cert: ""
+      key: ""
+      tlsConfig: null
+    # download service listen address
+    # current, only support unix domain socket
+    unixListen:
+      socket: /var/run/dfdaemon.sock
+  # peer grpc option
+  # peer grpc service send pieces info to other peers
+  peerGRPC:
+    security:
+      insecure: true
+      cacert: ""
+      cert: ""
+      key: ""
+    tcpListen:
+      # listen address
+      listen: 0.0.0.0
+      # listen port, daemon will try to listen
+      # when this port is not available, daemon will try next port
+      port: 65000
+      # if want to limit upper port, please use blow format
+#     port:
+#       start: 65000
+#       end: 65009
+
+# proxy config file location or detail config
+# proxy: ""
+
+# upload service option
+upload:
+  defaultFilter: "Expires&Signature"
+  # upload limit per second
+  rateLimit: 200Mi
+  security:
+    insecure: true
+    cacert: ""
+    cert: ""
+    key: ""
+  tcpListen:
+    # listen address
+    listen: 0.0.0.0
+    # listen port, daemon will try to listen
+    # when this port is not available, daemon will try next port
+    port: 65002
+    # if want to limit upper port, please use blow format
+#   port:
+#     start: 65020
+#     end: 65029
+
+# peer task storage option
+storage:
+  # task data expire time
+  # when there is no access to a task data, this task will be gc.
+  taskExpireTime: 1m0s
+  multiplex: true
+
+# proxy service option
+proxy:
+  security:
+    insecure: true
+    cacert: ""
+    cert: ""
+    key: ""
+  tcpListen:
+    # Namespace stands the linux net namespace, like /proc/1/ns/net
+    # It's useful for running daemon in pod with ip allocated and listen in host
+    # Linux only
+    namespace: ""
+    # listen address
+    listen: 0.0.0.0
+    # listen port, daemon will try to listen
+    # when this port is not available, daemon will try next port
+    port: 65001
+    # if want to limit upper port, please use blow format
+  #   port:
+  #     start: 65020
+  #     end: 65029
+  registryMirror:
+    # url for the registry mirror
+    url: https://index.docker.io
+    # whether to ignore https certificate errors
+    insecure: true
+    # optional certificates if the remote server uses self-signed certificates
+    certs: [ ]
+    # whether to request the remote registry directly
+    direct: false
+
+  proxies:
+  # proxy all http image layer download requests with dfget
+  - regx: (blobs|manifests|config)/sha256.*
+  - regx: __IP__.* # test only
diff --git a/go.mod b/go.mod
index 034689cd..55fd99d2 100644
--- a/go.mod
+++ b/go.mod
@@ -26,6 +26,7 @@ require (
 	github.com/google/uuid v1.1.5
 	github.com/gorilla/mux v1.7.3
 	github.com/jarcoal/httpmock v1.0.8
+	github.com/klauspost/compress v1.13.1 // indirect
 	github.com/kr/text v0.2.0 // indirect
 	github.com/mattn/go-sqlite3 v2.0.1+incompatible // indirect
 	github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
@@ -55,8 +56,9 @@ require (
 	go.uber.org/atomic v1.6.0
 	go.uber.org/zap v1.16.0
 	golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e
+	golang.org/x/net v0.0.0-20210614182718-04defd469f4e // indirect
 	golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
-	golang.org/x/sys v0.0.0-20210616094352-59db8d763f22
+	golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c
 	golang.org/x/time v0.0.0-20201208040808-7e3f01d25324
 	golang.org/x/tools v0.1.4 // indirect
 	gonum.org/v1/gonum v0.9.3
diff --git a/go.sum b/go.sum
index caecb496..5b242e60 100644
--- a/go.sum
+++ b/go.sum
@@ -339,8 +339,9 @@ github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1
 github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
 github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
-github.com/klauspost/compress v1.12.2 h1:2KCfW3I9M7nSc5wOqXAlW2v2U6v+w6cbjvbfp+OykW8=
 github.com/klauspost/compress v1.12.2/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
+github.com/klauspost/compress v1.13.1 h1:wXr2uRxZTJXHLly6qhJabee5JqIhTRoLBhDOA74hDEQ=
+github.com/klauspost/compress v1.13.1/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
 github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@@ -683,8 +684,9 @@ golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwY
 golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
-golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0=
 golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
+golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q=
+golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -738,8 +740,9 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 h1:RqytpXGR1iVNX7psjB3ff8y7sNFinVFvkx1c8SjBkio=
 golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
+golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE=
 golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
diff --git a/manager/handlers/user.go b/manager/handlers/user.go
index bd3e928f..b167d12d 100644
--- a/manager/handlers/user.go
+++ b/manager/handlers/user.go
@@ -7,28 +7,28 @@ import (
 	"github.com/gin-gonic/gin"
 )
 
-// @Summary Register user
-// @Description Register user by json config
+// @Summary SignUp user
+// @Description SignUp user by json config
 // @Tags User
 // @Accept json
 // @Produce json
-// @Param User body types.RegisterRequest true "User"
+// @Param User body types.SignUpRequest true "User"
 // @Success 200 {object} model.User
 // @Failure 400 {object} HTTPError
 // @Failure 500 {object} HTTPError
-// @Router /auth/register [post]
-func (h *Handlers) Register(ctx *gin.Context) {
-	var json types.RegisterRequest
+// @Router /user/signup [post]
+func (h *Handlers) SignUp(ctx *gin.Context) {
+	var json types.SignUpRequest
 	if err := ctx.ShouldBindJSON(&json); err != nil {
 		ctx.JSON(http.StatusUnprocessableEntity, gin.H{"errors": err.Error()})
 		return
 	}
 
-	userInfo, err := h.Service.Register(json)
+	user, err := h.Service.SignUp(json)
 	if err != nil {
 		ctx.Error(err)
 		return
 	}
 
-	ctx.JSON(http.StatusOK, userInfo)
+	ctx.JSON(http.StatusOK, user)
 }
diff --git a/manager/middlewares/jwt.go b/manager/middlewares/jwt.go
index 0a83480e..e0df6bfa 100644
--- a/manager/middlewares/jwt.go
+++ b/manager/middlewares/jwt.go
@@ -1,45 +1,54 @@
 package middlewares
 
 import (
-	"net/http"
 	"time"
 
-	"d7y.io/dragonfly/v2/manager/handlers"
+	"d7y.io/dragonfly/v2/manager/service"
 	"d7y.io/dragonfly/v2/manager/types"
 	jwt "github.com/appleboy/gin-jwt/v2"
 	"github.com/gin-gonic/gin"
 )
 
-func Jwt(h *handlers.Handlers) (*jwt.GinJWTMiddleware, error) {
+type user struct {
+	ID uint
+}
+
+func Jwt(service service.REST) (*jwt.GinJWTMiddleware, error) {
+	var identityKey = "id"
 	authMiddleware, err := jwt.New(&jwt.GinJWTMiddleware{
-		Realm:      "Dragonfly Zone",
-		Key:        []byte("Dragonfly Secret Key"),
-		Timeout:    time.Hour,
-		MaxRefresh: time.Hour,
+		Realm:       "Dragonfly",
+		Key:         []byte("Secret Key"),
+		Timeout:     time.Hour,
+		MaxRefresh:  time.Hour,
+		IdentityKey: identityKey,
+
+		IdentityHandler: func(c *gin.Context) interface{} {
+			claims := jwt.ExtractClaims(c)
+			return &user{
+				ID: claims[identityKey].(uint),
+			}
+		},
+
 		Authenticator: func(c *gin.Context) (interface{}, error) {
-			var loginInfos types.LoginRequest
-			if err := c.ShouldBind(&loginInfos); err != nil {
+			var json types.SignInRequest
+			if err := c.ShouldBind(&json); err != nil {
 				return "", jwt.ErrMissingLoginValues
 			}
-			userInfo, err := h.Service.Login(loginInfos)
+
+			u, err := service.SignIn(json)
 			if err != nil {
 				return "", jwt.ErrFailedAuthentication
 			}
 
-			return map[string]interface{}{
-				"name": userInfo.Name,
+			return &user{
+				ID: u.ID,
 			}, nil
 		},
-		LoginResponse: func(c *gin.Context, code int, token string, expire time.Time) {
-			c.JSON(http.StatusOK, gin.H{
-				"token":  token,
-				"expire": expire.Format(time.RFC3339),
-			})
-		},
+
 		PayloadFunc: func(data interface{}) jwt.MapClaims {
-			if v, ok := data.(map[string]interface{}); ok {
+			if u, ok := data.(user); ok {
 				return jwt.MapClaims{
-					"name": v["name"],
+					identityKey: u.ID,
 				}
 			}
 			return jwt.MapClaims{}
@@ -50,6 +59,25 @@ func Jwt(h *handlers.Handlers) (*jwt.GinJWTMiddleware, error) {
 				"message": message,
 			})
 		},
+
+		LoginResponse: func(c *gin.Context, code int, token string, expire time.Time) {
+			c.JSON(code, gin.H{
+				"token":  token,
+				"expire": expire.Format(time.RFC3339),
+			})
+		},
+
+		LogoutResponse: func(c *gin.Context, code int) {
+			c.Status(code)
+		},
+
+		RefreshResponse: func(c *gin.Context, code int, token string, expire time.Time) {
+			c.JSON(code, gin.H{
+				"token":  token,
+				"expire": expire.Format(time.RFC3339),
+			})
+		},
+
 		TokenLookup:    "header: Authorization, query: token, cookie: jwt",
 		TokenHeadName:  "Bearer",
 		TimeFunc:       time.Now,
@@ -62,5 +90,4 @@ func Jwt(h *handlers.Handlers) (*jwt.GinJWTMiddleware, error) {
 	}
 
 	return authMiddleware, nil
-
 }
diff --git a/manager/model/user.go b/manager/model/user.go
index 632014a4..6fc39100 100644
--- a/manager/model/user.go
+++ b/manager/model/user.go
@@ -9,7 +9,7 @@ type User struct {
 	Model
 	Email             string `gorm:"column:email;size:256;uniqueIndex;not null" json:"email"`
 	Name              string `gorm:"column:name;size:256;uniqueIndex;not null" json:"name"`
-	EncryptedPassword string `gorm:"column:encrypted_password;size:1024" json:"-"`
+	EncryptedPassword string `gorm:"column:encrypted_password;not null;size:1024" json:"-"`
 	Avatar            string `gorm:"column:avatar;size:256" json:"avatar"`
 	Phone             string `gorm:"column:phone;size:256" json:"phone"`
 	PrivateToken      string `gorm:"column:private_token;size:256" json:"private_token"`
diff --git a/manager/server/router.go b/manager/server/router.go
index fb1777e8..3be46c41 100644
--- a/manager/server/router.go
+++ b/manager/server/router.go
@@ -26,7 +26,7 @@ func initRouter(verbose bool, service service.REST) (*gin.Engine, error) {
 	r.Use(gin.Recovery())
 	r.Use(middlewares.Error())
 
-	jwt, err := middlewares.Jwt(h)
+	jwt, err := middlewares.Jwt(service)
 	if err != nil {
 		return nil, err
 	}
@@ -34,6 +34,13 @@ func initRouter(verbose bool, service service.REST) (*gin.Engine, error) {
 	// Router
 	apiv1 := r.Group("/api/v1")
 
+	// User
+	ai := apiv1.Group("/users")
+	ai.POST("/signin", jwt.LoginHandler)
+	ai.POST("/signout", jwt.LogoutHandler)
+	ai.POST("/refresh_token", jwt.RefreshHandler)
+	ai.POST("/signup", h.SignUp)
+
 	// Scheduler Cluster
 	sc := apiv1.Group("/scheduler-clusters")
 	sc.POST("", h.CreateSchedulerCluster)
@@ -69,13 +76,6 @@ func initRouter(verbose bool, service service.REST) (*gin.Engine, error) {
 	ci.GET(":id", h.GetCDN)
 	ci.GET("", h.GetCDNs)
 
-	// User
-	ai := apiv1.Group("/user")
-	ai.POST("/login", jwt.LoginHandler)
-	ai.GET("/logout", jwt.LogoutHandler)
-	ai.POST("/refresh_token", jwt.RefreshHandler)
-	ai.POST("/register", h.Register)
-
 	// Security Group
 	sg := apiv1.Group("/security-groups")
 	sg.POST("", h.CreateSecurityGroup)
diff --git a/manager/server/server.go b/manager/server/server.go
index 7524f3b3..0aaea551 100644
--- a/manager/server/server.go
+++ b/manager/server/server.go
@@ -57,17 +57,10 @@ func New(cfg *config.Config) (*Server, error) {
 	searcher := searcher.New()
 
 	// Initialize REST service
-	restService := service.NewREST(
-		service.WithDatabase(db),
-		service.WithCache(cache),
-	)
+	restService := service.NewREST(db, cache)
 
 	// Initialize GRPC service
-	grpcService := service.NewGRPC(
-		service.GRPCWithDatabase(db),
-		service.GRPCWithCache(cache),
-		service.GRPCWithSearcher(searcher),
-	)
+	grpcService := service.NewGRPC(db, cache, searcher)
 
 	// Initialize router
 	router, err := initRouter(cfg.Verbose, restService)
diff --git a/manager/service/service.go b/manager/service/service.go
index 99a5f867..d7225d1d 100644
--- a/manager/service/service.go
+++ b/manager/service/service.go
@@ -54,8 +54,8 @@ type REST interface {
 	AddSchedulerClusterToSecurityGroup(uint, uint) error
 	AddCDNClusterToSecurityGroup(uint, uint) error
 
-	Login(json types.LoginRequest) (*model.User, error)
-	Register(json types.RegisterRequest) (*model.User, error)
+	SignIn(json types.SignInRequest) (*model.User, error)
+	SignUp(json types.SignUpRequest) (*model.User, error)
 }
 
 type rest struct {
@@ -64,31 +64,11 @@ type rest struct {
 	cache *cache.Cache
 }
 
-// Option is a functional option for rest
-type Option func(s *rest)
-
-// WithDatabase set the database client
-func WithDatabase(database *database.Database) Option {
-	return func(s *rest) {
-		s.db = database.DB
-		s.rdb = database.RDB
-	}
-}
-
-// WithCache set the cache client
-func WithCache(cache *cache.Cache) Option {
-	return func(s *rest) {
-		s.cache = cache
-	}
-}
-
 // NewREST returns a new REST instence
-func NewREST(options ...Option) REST {
-	s := &rest{}
-
-	for _, opt := range options {
-		opt(s)
+func NewREST(database *database.Database, cache *cache.Cache) REST {
+	return &rest{
+		db:    database.DB,
+		rdb:   database.RDB,
+		cache: cache,
 	}
-
-	return s
 }
diff --git a/manager/service/service_grpc.go b/manager/service/service_grpc.go
index f2050424..573927a6 100644
--- a/manager/service/service_grpc.go
+++ b/manager/service/service_grpc.go
@@ -2,6 +2,7 @@ package service
 
 import (
 	"context"
+	"errors"
 	"io"
 
 	logger "d7y.io/dragonfly/v2/internal/dflog"
@@ -27,40 +28,14 @@ type GRPC struct {
 	searcher searcher.Searcher
 }
 
-// Option is a functional option for rest
-type GRPCOption func(s *GRPC)
-
-// GRPCWithDatabase set the database client
-func GRPCWithDatabase(database *database.Database) GRPCOption {
-	return func(s *GRPC) {
-		s.db = database.DB
-		s.rdb = database.RDB
-	}
-}
-
-// GRPCWithCache set the cache client
-func GRPCWithCache(cache *cache.Cache) GRPCOption {
-	return func(s *GRPC) {
-		s.cache = cache
-	}
-}
-
-// GRPCWithSearcher set search client
-func GRPCWithSearcher(searcher searcher.Searcher) GRPCOption {
-	return func(s *GRPC) {
-		s.searcher = searcher
-	}
-}
-
 // NewREST returns a new REST instence
-func NewGRPC(options ...GRPCOption) *GRPC {
-	s := &GRPC{}
-
-	for _, opt := range options {
-		opt(s)
+func NewGRPC(database *database.Database, cache *cache.Cache, searcher searcher.Searcher) *GRPC {
+	return &GRPC{
+		db:       database.DB,
+		rdb:      database.RDB,
+		cache:    cache,
+		searcher: searcher,
 	}
-
-	return s
 }
 
 func (s *GRPC) GetCDN(ctx context.Context, req *manager.GetCDNRequest) (*manager.CDN, error) {
@@ -127,7 +102,7 @@ func (s *GRPC) GetCDN(ctx context.Context, req *manager.GetCDNRequest) (*manager
 	return &pbCDN, nil
 }
 
-func (s *GRPC) CreateCDN(ctx context.Context, req *manager.CreateCDNRequest) (*manager.CDN, error) {
+func (s *GRPC) createCDN(ctx context.Context, req *manager.UpdateCDNRequest) (*manager.CDN, error) {
 	if err := req.Validate(); err != nil {
 		return nil, status.Error(codes.InvalidArgument, err.Error())
 	}
@@ -142,7 +117,7 @@ func (s *GRPC) CreateCDN(ctx context.Context, req *manager.CreateCDNRequest) (*m
 	}
 
 	if err := s.db.Create(&cdn).Error; err != nil {
-		return nil, err
+		return nil, status.Error(codes.Unknown, err.Error())
 	}
 
 	return &manager.CDN{
@@ -162,14 +137,21 @@ func (s *GRPC) UpdateCDN(ctx context.Context, req *manager.UpdateCDNRequest) (*m
 	}
 
 	cdn := model.CDN{}
-	if err := s.db.First(&cdn, model.CDN{HostName: req.HostName}).Updates(model.CDN{
+	if err := s.db.First(&cdn, model.CDN{HostName: req.HostName}).Error; err != nil {
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return s.createCDN(ctx, req)
+		}
+		return nil, status.Error(codes.Unknown, err.Error())
+	}
+
+	if err := s.db.Model(&cdn).Updates(model.CDN{
 		IDC:          req.Idc,
 		Location:     req.Location,
 		IP:           req.Ip,
 		Port:         req.Port,
 		DownloadPort: req.DownloadPort,
 	}).Error; err != nil {
-		return nil, err
+		return nil, status.Error(codes.Unknown, err.Error())
 	}
 
 	if err := s.cache.Delete(
@@ -197,16 +179,16 @@ func (s *GRPC) AddCDNToCDNCluster(ctx context.Context, req *manager.AddCDNToCDNC
 
 	cdnCluster := model.CDNCluster{}
 	if err := s.db.First(&cdnCluster, req.CdnClusterId).Error; err != nil {
-		return nil, err
+		return nil, status.Error(codes.Unknown, err.Error())
 	}
 
 	cdn := model.CDN{}
 	if err := s.db.First(&cdn, req.CdnId).Error; err != nil {
-		return nil, err
+		return nil, status.Error(codes.Unknown, err.Error())
 	}
 
 	if err := s.db.Model(&cdnCluster).Association("CDNs").Append(&cdn); err != nil {
-		return nil, err
+		return nil, status.Error(codes.Unknown, err.Error())
 	}
 
 	if err := s.cache.Delete(
@@ -314,7 +296,7 @@ func (s *GRPC) GetScheduler(ctx context.Context, req *manager.GetSchedulerReques
 	return &pbScheduler, nil
 }
 
-func (s *GRPC) CreateScheduler(ctx context.Context, req *manager.CreateSchedulerRequest) (*manager.Scheduler, error) {
+func (s *GRPC) createScheduler(ctx context.Context, req *manager.UpdateSchedulerRequest) (*manager.Scheduler, error) {
 	if err := req.Validate(); err != nil {
 		return nil, status.Error(codes.InvalidArgument, err.Error())
 	}
@@ -337,7 +319,7 @@ func (s *GRPC) CreateScheduler(ctx context.Context, req *manager.CreateScheduler
 	}
 
 	if err := s.db.Create(&scheduler).Error; err != nil {
-		return nil, err
+		return nil, status.Error(codes.Unknown, err.Error())
 	}
 
 	return &manager.Scheduler{
@@ -358,6 +340,14 @@ func (s *GRPC) UpdateScheduler(ctx context.Context, req *manager.UpdateScheduler
 		return nil, status.Error(codes.InvalidArgument, err.Error())
 	}
 
+	scheduler := model.Scheduler{}
+	if err := s.db.First(&scheduler, model.Scheduler{HostName: req.HostName}).Error; err != nil {
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return s.createScheduler(ctx, req)
+		}
+		return nil, status.Error(codes.Unknown, err.Error())
+	}
+
 	var netConfig datatypes.JSONMap
 	if len(req.NetConfig) > 0 {
 		if err := netConfig.UnmarshalJSON(req.NetConfig); err != nil {
@@ -365,8 +355,7 @@ func (s *GRPC) UpdateScheduler(ctx context.Context, req *manager.UpdateScheduler
 		}
 	}
 
-	scheduler := model.Scheduler{}
-	if err := s.db.First(&scheduler, model.Scheduler{HostName: req.HostName}).Updates(model.Scheduler{
+	if err := s.db.Model(&scheduler).Updates(model.Scheduler{
 		VIPs:      req.Vips,
 		IDC:       req.Idc,
 		Location:  req.Location,
@@ -374,7 +363,7 @@ func (s *GRPC) UpdateScheduler(ctx context.Context, req *manager.UpdateScheduler
 		IP:        req.Ip,
 		Port:      req.Port,
 	}).Error; err != nil {
-		return nil, err
+		return nil, status.Error(codes.Unknown, err.Error())
 	}
 
 	if err := s.cache.Delete(
@@ -404,16 +393,16 @@ func (s *GRPC) AddSchedulerClusterToSchedulerCluster(ctx context.Context, req *m
 
 	schedulerCluster := model.SchedulerCluster{}
 	if err := s.db.First(&schedulerCluster, req.SchedulerClusterId).Error; err != nil {
-		return nil, err
+		return nil, status.Error(codes.Unknown, err.Error())
 	}
 
 	scheduler := model.Scheduler{}
 	if err := s.db.First(&scheduler, req.SchedulerId).Error; err != nil {
-		return nil, err
+		return nil, status.Error(codes.Unknown, err.Error())
 	}
 
 	if err := s.db.Model(&schedulerCluster).Association("Schedulers").Append(&scheduler); err != nil {
-		return nil, err
+		return nil, status.Error(codes.Unknown, err.Error())
 	}
 
 	if err := s.cache.Delete(
@@ -500,7 +489,7 @@ func (s *GRPC) KeepAlive(m manager.Manager_KeepAliveServer) error {
 	req, err := m.Recv()
 	if err != nil {
 		logger.Errorf("keepalive failed for the first time: %v", err)
-		return err
+		return status.Error(codes.Unknown, err.Error())
 	}
 	if err := req.Validate(); err != nil {
 		return status.Error(codes.InvalidArgument, err.Error())
@@ -518,7 +507,7 @@ func (s *GRPC) KeepAlive(m manager.Manager_KeepAliveServer) error {
 		}).Updates(model.Scheduler{
 			Status: model.SchedulerStatusActive,
 		}).Error; err != nil {
-			return err
+			return status.Error(codes.Unknown, err.Error())
 		}
 
 		if err := s.cache.Delete(
@@ -537,7 +526,7 @@ func (s *GRPC) KeepAlive(m manager.Manager_KeepAliveServer) error {
 		}).Updates(model.CDN{
 			Status: model.CDNStatusActive,
 		}).Error; err != nil {
-			return err
+			return status.Error(codes.Unknown, err.Error())
 		}
 
 		if err := s.cache.Delete(
@@ -559,7 +548,7 @@ func (s *GRPC) KeepAlive(m manager.Manager_KeepAliveServer) error {
 				}).Updates(model.Scheduler{
 					Status: model.SchedulerStatusInactive,
 				}).Error; err != nil {
-					return err
+					return status.Error(codes.Unknown, err.Error())
 				}
 
 				if err := s.cache.Delete(
@@ -578,7 +567,7 @@ func (s *GRPC) KeepAlive(m manager.Manager_KeepAliveServer) error {
 				}).Updates(model.CDN{
 					Status: model.CDNStatusInactive,
 				}).Error; err != nil {
-					return err
+					return status.Error(codes.Unknown, err.Error())
 				}
 
 				if err := s.cache.Delete(
@@ -594,7 +583,7 @@ func (s *GRPC) KeepAlive(m manager.Manager_KeepAliveServer) error {
 				return nil
 			}
 			logger.Errorf("%s keepalive failed: %v", hostName, err)
-			return err
+			return status.Error(codes.Unknown, err.Error())
 		}
 
 		logger.Debugf("%s type of %s send keepalive request", sourceType, hostName)
diff --git a/manager/service/user.go b/manager/service/user.go
index 75cfe793..87ed16c9 100644
--- a/manager/service/user.go
+++ b/manager/service/user.go
@@ -1,33 +1,33 @@
 package service
 
 import (
-	"errors"
-
 	"d7y.io/dragonfly/v2/manager/model"
 	"d7y.io/dragonfly/v2/manager/types"
 	"golang.org/x/crypto/bcrypt"
 )
 
-func (s *rest) Login(json types.LoginRequest) (*model.User, error) {
+func (s *rest) SignIn(json types.SignInRequest) (*model.User, error) {
 	user := model.User{}
-	if err := s.db.Where("name = ?", json.Name).First(&user).Error; err != nil {
+	if err := s.db.First(&user, model.User{
+		Name: json.Name,
+	}).Error; err != nil {
 		return nil, err
 	}
+
 	err := bcrypt.CompareHashAndPassword([]byte(user.EncryptedPassword), []byte(json.Password))
 	if err != nil {
-		return nil, errors.New("password mismatch")
+		return nil, err
 	}
 
 	return &user, nil
-
 }
 
-func (s *rest) Register(json types.RegisterRequest) (*model.User, error) {
-
+func (s *rest) SignUp(json types.SignUpRequest) (*model.User, error) {
 	encryptedPasswordBytes, err := bcrypt.GenerateFromPassword([]byte(json.Password), bcrypt.MinCost)
 	if err != nil {
 		return nil, err
 	}
+
 	user := model.User{
 		EncryptedPassword: string(encryptedPasswordBytes),
 		Name:              json.Name,
@@ -44,5 +44,4 @@ func (s *rest) Register(json types.RegisterRequest) (*model.User, error) {
 	}
 
 	return &user, nil
-
 }
diff --git a/manager/types/user.go b/manager/types/user.go
index 307bed31..d66a4bca 100644
--- a/manager/types/user.go
+++ b/manager/types/user.go
@@ -1,12 +1,12 @@
 package types
 
-type LoginRequest struct {
+type SignInRequest struct {
 	Name     string `form:"name" binding:"required,min=3,max=10"`
-	Password string `form:"password" binding:"required,min=12,max=20"`
+	Password string `form:"password" binding:"required,min=8,max=20"`
 }
 
-type RegisterRequest struct {
-	LoginRequest
+type SignUpRequest struct {
+	SignInRequest
 	Email    string `form:"email" binding:"required,email"`
 	Phone    string `form:"phone" binding:"omitempty"`
 	Avatar   string `form:"avatar" binding:"omitempty"`
diff --git a/pkg/rpc/cdnsystem/cdnsystem_grpc.pb.go b/pkg/rpc/cdnsystem/cdnsystem_grpc.pb.go
index d5b70a7c..f2994552 100644
--- a/pkg/rpc/cdnsystem/cdnsystem_grpc.pb.go
+++ b/pkg/rpc/cdnsystem/cdnsystem_grpc.pb.go
@@ -12,6 +12,7 @@ import (
 
 // This is a compile-time assertion to ensure that this generated file
 // is compatible with the grpc package it is being compiled against.
+// Requires gRPC-Go v1.32.0 or later.
 const _ = grpc.SupportPackageIsVersion7
 
 // SeederClient is the client API for Seeder service.
@@ -33,7 +34,7 @@ func NewSeederClient(cc grpc.ClientConnInterface) SeederClient {
 }
 
 func (c *seederClient) ObtainSeeds(ctx context.Context, in *SeedRequest, opts ...grpc.CallOption) (Seeder_ObtainSeedsClient, error) {
-	stream, err := c.cc.NewStream(ctx, &_Seeder_serviceDesc.Streams[0], "/cdnsystem.Seeder/ObtainSeeds", opts...)
+	stream, err := c.cc.NewStream(ctx, &Seeder_ServiceDesc.Streams[0], "/cdnsystem.Seeder/ObtainSeeds", opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -104,7 +105,7 @@ type UnsafeSeederServer interface {
 }
 
 func RegisterSeederServer(s grpc.ServiceRegistrar, srv SeederServer) {
-	s.RegisterService(&_Seeder_serviceDesc, srv)
+	s.RegisterService(&Seeder_ServiceDesc, srv)
 }
 
 func _Seeder_ObtainSeeds_Handler(srv interface{}, stream grpc.ServerStream) error {
@@ -146,7 +147,10 @@ func _Seeder_GetPieceTasks_Handler(srv interface{}, ctx context.Context, dec fun
 	return interceptor(ctx, in, info, handler)
 }
 
-var _Seeder_serviceDesc = grpc.ServiceDesc{
+// Seeder_ServiceDesc is the grpc.ServiceDesc for Seeder service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var Seeder_ServiceDesc = grpc.ServiceDesc{
 	ServiceName: "cdnsystem.Seeder",
 	HandlerType: (*SeederServer)(nil),
 	Methods: []grpc.MethodDesc{
diff --git a/pkg/rpc/cdnsystem/client/client.go b/pkg/rpc/cdnsystem/client/client.go
index e9d7dd44..4aca9198 100644
--- a/pkg/rpc/cdnsystem/client/client.go
+++ b/pkg/rpc/cdnsystem/client/client.go
@@ -30,12 +30,12 @@ import (
 	"google.golang.org/grpc"
 )
 
-func GetClientByAddr(adders []dfnet.NetAddr, opts ...grpc.DialOption) (CdnClient, error) {
-	if len(adders) == 0 {
+func GetClientByAddr(addrs []dfnet.NetAddr, opts ...grpc.DialOption) (CdnClient, error) {
+	if len(addrs) == 0 {
 		return nil, errors.New("address list of cdn is empty")
 	}
 	cc := &cdnClient{
-		rpc.NewConnection(context.Background(), "cdn", adders, []rpc.ConnOption{
+		rpc.NewConnection(context.Background(), "cdn", addrs, []rpc.ConnOption{
 			rpc.WithConnExpireTime(60 * time.Second),
 			rpc.WithDialOption(opts),
 		}),
@@ -46,7 +46,7 @@ func GetClientByAddr(adders []dfnet.NetAddr, opts ...grpc.DialOption) (CdnClient
 var once sync.Once
 var elasticCdnClient *cdnClient
 
-func GetElasticClientByAdders(addrs []dfnet.NetAddr, opts ...grpc.DialOption) (CdnClient, error) {
+func GetElasticClientByAddrs(addrs []dfnet.NetAddr, opts ...grpc.DialOption) (CdnClient, error) {
 	once.Do(func() {
 		elasticCdnClient = &cdnClient{
 			rpc.NewConnection(context.Background(), "cdn-elastic", make([]dfnet.NetAddr, 0), []rpc.ConnOption{
@@ -68,7 +68,7 @@ type CdnClient interface {
 
 	GetPieceTasks(ctx context.Context, addr dfnet.NetAddr, req *base.PieceTaskRequest, opts ...grpc.CallOption) (*base.PiecePacket, error)
 
-	UpdateState(adders []dfnet.NetAddr)
+	UpdateState(addrs []dfnet.NetAddr)
 
 	Close() error
 }
diff --git a/pkg/rpc/client.go b/pkg/rpc/client.go
index 58300061..070d9271 100644
--- a/pkg/rpc/client.go
+++ b/pkg/rpc/client.go
@@ -149,15 +149,15 @@ func WithDialTimeout(dialTimeout time.Duration) ConnOption {
 	})
 }
 
-func NewConnection(ctx context.Context, name string, adders []dfnet.NetAddr, connOpts []ConnOption) *Connection {
+func NewConnection(ctx context.Context, name string, addrs []dfnet.NetAddr, connOpts []ConnOption) *Connection {
 	conn := newDefaultConnection(ctx)
 	conn.name = name
-	addresses := make([]string, 0, len(adders))
-	for _, addr := range adders {
+	addresses := make([]string, 0, len(addrs))
+	for _, addr := range addrs {
 		addresses = append(addresses, addr.GetEndpoint())
 	}
 	conn.hashRing = hashring.New(addresses)
-	conn.serverNodes = adders
+	conn.serverNodes = addrs
 	for _, opt := range connOpts {
 		opt.apply(conn)
 	}
@@ -409,11 +409,11 @@ func (conn *Connection) Close() error {
 	return nil
 }
 
-func (conn *Connection) UpdateState(adders []dfnet.NetAddr) {
+func (conn *Connection) UpdateState(addrs []dfnet.NetAddr) {
 	// todo lock
-	conn.serverNodes = adders
+	conn.serverNodes = addrs
 	var addresses []string
-	for _, addr := range adders {
+	for _, addr := range addrs {
 		addresses = append(addresses, addr.GetEndpoint())
 	}
 
diff --git a/pkg/rpc/dfdaemon/client/client.go b/pkg/rpc/dfdaemon/client/client.go
index 827f1a06..beb1f8d7 100644
--- a/pkg/rpc/dfdaemon/client/client.go
+++ b/pkg/rpc/dfdaemon/client/client.go
@@ -51,7 +51,7 @@ func GetClientByAddr(addrs []dfnet.NetAddr, opts ...grpc.DialOption) (DaemonClie
 var once sync.Once
 var elasticDaemonClient *daemonClient
 
-func GetElasticClientByAdders(addrs []dfnet.NetAddr, opts ...grpc.DialOption) (DaemonClient, error) {
+func GetElasticClientByAddrs(addrs []dfnet.NetAddr, opts ...grpc.DialOption) (DaemonClient, error) {
 	once.Do(func() {
 		elasticDaemonClient = &daemonClient{
 			rpc.NewConnection(context.Background(), "daemon-elastic", make([]dfnet.NetAddr, 0), []rpc.ConnOption{
diff --git a/pkg/rpc/dfdaemon/client/peer.go b/pkg/rpc/dfdaemon/client/peer.go
index f00ec329..e117ad42 100644
--- a/pkg/rpc/dfdaemon/client/peer.go
+++ b/pkg/rpc/dfdaemon/client/peer.go
@@ -51,7 +51,7 @@ func GetPieceTasks(ctx context.Context, destPeer *scheduler.PeerPacket_DestPeer,
 
 func getClient(netAddr dfnet.NetAddr, toCdn bool) (rpc.Closer, error) {
 	if toCdn {
-		return cdnclient.GetElasticClientByAdders([]dfnet.NetAddr{netAddr})
+		return cdnclient.GetElasticClientByAddrs([]dfnet.NetAddr{netAddr})
 	}
-	return GetElasticClientByAdders([]dfnet.NetAddr{netAddr})
+	return GetElasticClientByAddrs([]dfnet.NetAddr{netAddr})
 }
diff --git a/pkg/rpc/dfdaemon/dfdaemon_grpc.pb.go b/pkg/rpc/dfdaemon/dfdaemon_grpc.pb.go
index 851f7c11..c5e63251 100644
--- a/pkg/rpc/dfdaemon/dfdaemon_grpc.pb.go
+++ b/pkg/rpc/dfdaemon/dfdaemon_grpc.pb.go
@@ -13,6 +13,7 @@ import (
 
 // This is a compile-time assertion to ensure that this generated file
 // is compatible with the grpc package it is being compiled against.
+// Requires gRPC-Go v1.32.0 or later.
 const _ = grpc.SupportPackageIsVersion7
 
 // DaemonClient is the client API for Daemon service.
@@ -36,7 +37,7 @@ func NewDaemonClient(cc grpc.ClientConnInterface) DaemonClient {
 }
 
 func (c *daemonClient) Download(ctx context.Context, in *DownRequest, opts ...grpc.CallOption) (Daemon_DownloadClient, error) {
-	stream, err := c.cc.NewStream(ctx, &_Daemon_serviceDesc.Streams[0], "/dfdaemon.Daemon/Download", opts...)
+	stream, err := c.cc.NewStream(ctx, &Daemon_ServiceDesc.Streams[0], "/dfdaemon.Daemon/Download", opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -121,7 +122,7 @@ type UnsafeDaemonServer interface {
 }
 
 func RegisterDaemonServer(s grpc.ServiceRegistrar, srv DaemonServer) {
-	s.RegisterService(&_Daemon_serviceDesc, srv)
+	s.RegisterService(&Daemon_ServiceDesc, srv)
 }
 
 func _Daemon_Download_Handler(srv interface{}, stream grpc.ServerStream) error {
@@ -181,7 +182,10 @@ func _Daemon_CheckHealth_Handler(srv interface{}, ctx context.Context, dec func(
 	return interceptor(ctx, in, info, handler)
 }
 
-var _Daemon_serviceDesc = grpc.ServiceDesc{
+// Daemon_ServiceDesc is the grpc.ServiceDesc for Daemon service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var Daemon_ServiceDesc = grpc.ServiceDesc{
 	ServiceName: "dfdaemon.Daemon",
 	HandlerType: (*DaemonServer)(nil),
 	Methods: []grpc.MethodDesc{
diff --git a/pkg/rpc/manager/manager.pb.go b/pkg/rpc/manager/manager.pb.go
index d5cfc99a..1335791a 100644
--- a/pkg/rpc/manager/manager.pb.go
+++ b/pkg/rpc/manager/manager.pb.go
@@ -410,101 +410,6 @@ func (x *GetCDNRequest) GetHostName() string {
 	return ""
 }
 
-type CreateCDNRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	SourceType   SourceType `protobuf:"varint,1,opt,name=source_type,json=sourceType,proto3,enum=manager.SourceType" json:"source_type,omitempty"`
-	HostName     string     `protobuf:"bytes,2,opt,name=host_name,json=hostName,proto3" json:"host_name,omitempty"`
-	Idc          string     `protobuf:"bytes,4,opt,name=idc,proto3" json:"idc,omitempty"`
-	Location     string     `protobuf:"bytes,5,opt,name=location,proto3" json:"location,omitempty"`
-	Ip           string     `protobuf:"bytes,6,opt,name=ip,proto3" json:"ip,omitempty"`
-	Port         int32      `protobuf:"varint,7,opt,name=port,proto3" json:"port,omitempty"`
-	DownloadPort int32      `protobuf:"varint,8,opt,name=download_port,json=downloadPort,proto3" json:"download_port,omitempty"`
-}
-
-func (x *CreateCDNRequest) Reset() {
-	*x = CreateCDNRequest{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_pkg_rpc_manager_manager_proto_msgTypes[4]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *CreateCDNRequest) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*CreateCDNRequest) ProtoMessage() {}
-
-func (x *CreateCDNRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_pkg_rpc_manager_manager_proto_msgTypes[4]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use CreateCDNRequest.ProtoReflect.Descriptor instead.
-func (*CreateCDNRequest) Descriptor() ([]byte, []int) {
-	return file_pkg_rpc_manager_manager_proto_rawDescGZIP(), []int{4}
-}
-
-func (x *CreateCDNRequest) GetSourceType() SourceType {
-	if x != nil {
-		return x.SourceType
-	}
-	return SourceType_SCHEDULER_SOURCE
-}
-
-func (x *CreateCDNRequest) GetHostName() string {
-	if x != nil {
-		return x.HostName
-	}
-	return ""
-}
-
-func (x *CreateCDNRequest) GetIdc() string {
-	if x != nil {
-		return x.Idc
-	}
-	return ""
-}
-
-func (x *CreateCDNRequest) GetLocation() string {
-	if x != nil {
-		return x.Location
-	}
-	return ""
-}
-
-func (x *CreateCDNRequest) GetIp() string {
-	if x != nil {
-		return x.Ip
-	}
-	return ""
-}
-
-func (x *CreateCDNRequest) GetPort() int32 {
-	if x != nil {
-		return x.Port
-	}
-	return 0
-}
-
-func (x *CreateCDNRequest) GetDownloadPort() int32 {
-	if x != nil {
-		return x.DownloadPort
-	}
-	return 0
-}
-
 type UpdateCDNRequest struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
@@ -522,7 +427,7 @@ type UpdateCDNRequest struct {
 func (x *UpdateCDNRequest) Reset() {
 	*x = UpdateCDNRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_pkg_rpc_manager_manager_proto_msgTypes[5]
+		mi := &file_pkg_rpc_manager_manager_proto_msgTypes[4]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -535,7 +440,7 @@ func (x *UpdateCDNRequest) String() string {
 func (*UpdateCDNRequest) ProtoMessage() {}
 
 func (x *UpdateCDNRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_pkg_rpc_manager_manager_proto_msgTypes[5]
+	mi := &file_pkg_rpc_manager_manager_proto_msgTypes[4]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -548,7 +453,7 @@ func (x *UpdateCDNRequest) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use UpdateCDNRequest.ProtoReflect.Descriptor instead.
 func (*UpdateCDNRequest) Descriptor() ([]byte, []int) {
-	return file_pkg_rpc_manager_manager_proto_rawDescGZIP(), []int{5}
+	return file_pkg_rpc_manager_manager_proto_rawDescGZIP(), []int{4}
 }
 
 func (x *UpdateCDNRequest) GetSourceType() SourceType {
@@ -613,7 +518,7 @@ type AddCDNToCDNClusterRequest struct {
 func (x *AddCDNToCDNClusterRequest) Reset() {
 	*x = AddCDNToCDNClusterRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_pkg_rpc_manager_manager_proto_msgTypes[6]
+		mi := &file_pkg_rpc_manager_manager_proto_msgTypes[5]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -626,7 +531,7 @@ func (x *AddCDNToCDNClusterRequest) String() string {
 func (*AddCDNToCDNClusterRequest) ProtoMessage() {}
 
 func (x *AddCDNToCDNClusterRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_pkg_rpc_manager_manager_proto_msgTypes[6]
+	mi := &file_pkg_rpc_manager_manager_proto_msgTypes[5]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -639,7 +544,7 @@ func (x *AddCDNToCDNClusterRequest) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use AddCDNToCDNClusterRequest.ProtoReflect.Descriptor instead.
 func (*AddCDNToCDNClusterRequest) Descriptor() ([]byte, []int) {
-	return file_pkg_rpc_manager_manager_proto_rawDescGZIP(), []int{6}
+	return file_pkg_rpc_manager_manager_proto_rawDescGZIP(), []int{5}
 }
 
 func (x *AddCDNToCDNClusterRequest) GetSourceType() SourceType {
@@ -679,7 +584,7 @@ type SchedulerCluster struct {
 func (x *SchedulerCluster) Reset() {
 	*x = SchedulerCluster{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_pkg_rpc_manager_manager_proto_msgTypes[7]
+		mi := &file_pkg_rpc_manager_manager_proto_msgTypes[6]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -692,7 +597,7 @@ func (x *SchedulerCluster) String() string {
 func (*SchedulerCluster) ProtoMessage() {}
 
 func (x *SchedulerCluster) ProtoReflect() protoreflect.Message {
-	mi := &file_pkg_rpc_manager_manager_proto_msgTypes[7]
+	mi := &file_pkg_rpc_manager_manager_proto_msgTypes[6]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -705,7 +610,7 @@ func (x *SchedulerCluster) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use SchedulerCluster.ProtoReflect.Descriptor instead.
 func (*SchedulerCluster) Descriptor() ([]byte, []int) {
-	return file_pkg_rpc_manager_manager_proto_rawDescGZIP(), []int{7}
+	return file_pkg_rpc_manager_manager_proto_rawDescGZIP(), []int{6}
 }
 
 func (x *SchedulerCluster) GetId() uint64 {
@@ -771,7 +676,7 @@ type Scheduler struct {
 func (x *Scheduler) Reset() {
 	*x = Scheduler{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_pkg_rpc_manager_manager_proto_msgTypes[8]
+		mi := &file_pkg_rpc_manager_manager_proto_msgTypes[7]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -784,7 +689,7 @@ func (x *Scheduler) String() string {
 func (*Scheduler) ProtoMessage() {}
 
 func (x *Scheduler) ProtoReflect() protoreflect.Message {
-	mi := &file_pkg_rpc_manager_manager_proto_msgTypes[8]
+	mi := &file_pkg_rpc_manager_manager_proto_msgTypes[7]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -797,7 +702,7 @@ func (x *Scheduler) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use Scheduler.ProtoReflect.Descriptor instead.
 func (*Scheduler) Descriptor() ([]byte, []int) {
-	return file_pkg_rpc_manager_manager_proto_rawDescGZIP(), []int{8}
+	return file_pkg_rpc_manager_manager_proto_rawDescGZIP(), []int{7}
 }
 
 func (x *Scheduler) GetId() uint64 {
@@ -889,7 +794,7 @@ type GetSchedulerRequest struct {
 func (x *GetSchedulerRequest) Reset() {
 	*x = GetSchedulerRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_pkg_rpc_manager_manager_proto_msgTypes[9]
+		mi := &file_pkg_rpc_manager_manager_proto_msgTypes[8]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -902,7 +807,7 @@ func (x *GetSchedulerRequest) String() string {
 func (*GetSchedulerRequest) ProtoMessage() {}
 
 func (x *GetSchedulerRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_pkg_rpc_manager_manager_proto_msgTypes[9]
+	mi := &file_pkg_rpc_manager_manager_proto_msgTypes[8]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -915,7 +820,7 @@ func (x *GetSchedulerRequest) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use GetSchedulerRequest.ProtoReflect.Descriptor instead.
 func (*GetSchedulerRequest) Descriptor() ([]byte, []int) {
-	return file_pkg_rpc_manager_manager_proto_rawDescGZIP(), []int{9}
+	return file_pkg_rpc_manager_manager_proto_rawDescGZIP(), []int{8}
 }
 
 func (x *GetSchedulerRequest) GetSourceType() SourceType {
@@ -932,109 +837,6 @@ func (x *GetSchedulerRequest) GetHostName() string {
 	return ""
 }
 
-type CreateSchedulerRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	SourceType SourceType `protobuf:"varint,1,opt,name=source_type,json=sourceType,proto3,enum=manager.SourceType" json:"source_type,omitempty"`
-	HostName   string     `protobuf:"bytes,2,opt,name=host_name,json=hostName,proto3" json:"host_name,omitempty"`
-	Vips       string     `protobuf:"bytes,4,opt,name=vips,proto3" json:"vips,omitempty"`
-	Idc        string     `protobuf:"bytes,5,opt,name=idc,proto3" json:"idc,omitempty"`
-	Location   string     `protobuf:"bytes,6,opt,name=location,proto3" json:"location,omitempty"`
-	NetConfig  []byte     `protobuf:"bytes,7,opt,name=net_config,json=netConfig,proto3" json:"net_config,omitempty"`
-	Ip         string     `protobuf:"bytes,8,opt,name=ip,proto3" json:"ip,omitempty"`
-	Port       int32      `protobuf:"varint,9,opt,name=port,proto3" json:"port,omitempty"`
-}
-
-func (x *CreateSchedulerRequest) Reset() {
-	*x = CreateSchedulerRequest{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_pkg_rpc_manager_manager_proto_msgTypes[10]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *CreateSchedulerRequest) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*CreateSchedulerRequest) ProtoMessage() {}
-
-func (x *CreateSchedulerRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_pkg_rpc_manager_manager_proto_msgTypes[10]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use CreateSchedulerRequest.ProtoReflect.Descriptor instead.
-func (*CreateSchedulerRequest) Descriptor() ([]byte, []int) {
-	return file_pkg_rpc_manager_manager_proto_rawDescGZIP(), []int{10}
-}
-
-func (x *CreateSchedulerRequest) GetSourceType() SourceType {
-	if x != nil {
-		return x.SourceType
-	}
-	return SourceType_SCHEDULER_SOURCE
-}
-
-func (x *CreateSchedulerRequest) GetHostName() string {
-	if x != nil {
-		return x.HostName
-	}
-	return ""
-}
-
-func (x *CreateSchedulerRequest) GetVips() string {
-	if x != nil {
-		return x.Vips
-	}
-	return ""
-}
-
-func (x *CreateSchedulerRequest) GetIdc() string {
-	if x != nil {
-		return x.Idc
-	}
-	return ""
-}
-
-func (x *CreateSchedulerRequest) GetLocation() string {
-	if x != nil {
-		return x.Location
-	}
-	return ""
-}
-
-func (x *CreateSchedulerRequest) GetNetConfig() []byte {
-	if x != nil {
-		return x.NetConfig
-	}
-	return nil
-}
-
-func (x *CreateSchedulerRequest) GetIp() string {
-	if x != nil {
-		return x.Ip
-	}
-	return ""
-}
-
-func (x *CreateSchedulerRequest) GetPort() int32 {
-	if x != nil {
-		return x.Port
-	}
-	return 0
-}
-
 type UpdateSchedulerRequest struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
@@ -1053,7 +855,7 @@ type UpdateSchedulerRequest struct {
 func (x *UpdateSchedulerRequest) Reset() {
 	*x = UpdateSchedulerRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_pkg_rpc_manager_manager_proto_msgTypes[11]
+		mi := &file_pkg_rpc_manager_manager_proto_msgTypes[9]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -1066,7 +868,7 @@ func (x *UpdateSchedulerRequest) String() string {
 func (*UpdateSchedulerRequest) ProtoMessage() {}
 
 func (x *UpdateSchedulerRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_pkg_rpc_manager_manager_proto_msgTypes[11]
+	mi := &file_pkg_rpc_manager_manager_proto_msgTypes[9]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1079,7 +881,7 @@ func (x *UpdateSchedulerRequest) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use UpdateSchedulerRequest.ProtoReflect.Descriptor instead.
 func (*UpdateSchedulerRequest) Descriptor() ([]byte, []int) {
-	return file_pkg_rpc_manager_manager_proto_rawDescGZIP(), []int{11}
+	return file_pkg_rpc_manager_manager_proto_rawDescGZIP(), []int{9}
 }
 
 func (x *UpdateSchedulerRequest) GetSourceType() SourceType {
@@ -1151,7 +953,7 @@ type AddSchedulerClusterToSchedulerClusterRequest struct {
 func (x *AddSchedulerClusterToSchedulerClusterRequest) Reset() {
 	*x = AddSchedulerClusterToSchedulerClusterRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_pkg_rpc_manager_manager_proto_msgTypes[12]
+		mi := &file_pkg_rpc_manager_manager_proto_msgTypes[10]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -1164,7 +966,7 @@ func (x *AddSchedulerClusterToSchedulerClusterRequest) String() string {
 func (*AddSchedulerClusterToSchedulerClusterRequest) ProtoMessage() {}
 
 func (x *AddSchedulerClusterToSchedulerClusterRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_pkg_rpc_manager_manager_proto_msgTypes[12]
+	mi := &file_pkg_rpc_manager_manager_proto_msgTypes[10]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1177,7 +979,7 @@ func (x *AddSchedulerClusterToSchedulerClusterRequest) ProtoReflect() protorefle
 
 // Deprecated: Use AddSchedulerClusterToSchedulerClusterRequest.ProtoReflect.Descriptor instead.
 func (*AddSchedulerClusterToSchedulerClusterRequest) Descriptor() ([]byte, []int) {
-	return file_pkg_rpc_manager_manager_proto_rawDescGZIP(), []int{12}
+	return file_pkg_rpc_manager_manager_proto_rawDescGZIP(), []int{10}
 }
 
 func (x *AddSchedulerClusterToSchedulerClusterRequest) GetSourceType() SourceType {
@@ -1215,7 +1017,7 @@ type ListSchedulersRequest struct {
 func (x *ListSchedulersRequest) Reset() {
 	*x = ListSchedulersRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_pkg_rpc_manager_manager_proto_msgTypes[13]
+		mi := &file_pkg_rpc_manager_manager_proto_msgTypes[11]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -1228,7 +1030,7 @@ func (x *ListSchedulersRequest) String() string {
 func (*ListSchedulersRequest) ProtoMessage() {}
 
 func (x *ListSchedulersRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_pkg_rpc_manager_manager_proto_msgTypes[13]
+	mi := &file_pkg_rpc_manager_manager_proto_msgTypes[11]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1241,7 +1043,7 @@ func (x *ListSchedulersRequest) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use ListSchedulersRequest.ProtoReflect.Descriptor instead.
 func (*ListSchedulersRequest) Descriptor() ([]byte, []int) {
-	return file_pkg_rpc_manager_manager_proto_rawDescGZIP(), []int{13}
+	return file_pkg_rpc_manager_manager_proto_rawDescGZIP(), []int{11}
 }
 
 func (x *ListSchedulersRequest) GetSourceType() SourceType {
@@ -1283,7 +1085,7 @@ type ListSchedulersResponse struct {
 func (x *ListSchedulersResponse) Reset() {
 	*x = ListSchedulersResponse{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_pkg_rpc_manager_manager_proto_msgTypes[14]
+		mi := &file_pkg_rpc_manager_manager_proto_msgTypes[12]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -1296,7 +1098,7 @@ func (x *ListSchedulersResponse) String() string {
 func (*ListSchedulersResponse) ProtoMessage() {}
 
 func (x *ListSchedulersResponse) ProtoReflect() protoreflect.Message {
-	mi := &file_pkg_rpc_manager_manager_proto_msgTypes[14]
+	mi := &file_pkg_rpc_manager_manager_proto_msgTypes[12]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1309,7 +1111,7 @@ func (x *ListSchedulersResponse) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use ListSchedulersResponse.ProtoReflect.Descriptor instead.
 func (*ListSchedulersResponse) Descriptor() ([]byte, []int) {
-	return file_pkg_rpc_manager_manager_proto_rawDescGZIP(), []int{14}
+	return file_pkg_rpc_manager_manager_proto_rawDescGZIP(), []int{12}
 }
 
 func (x *ListSchedulersResponse) GetSchedulers() []*Scheduler {
@@ -1331,7 +1133,7 @@ type KeepAliveRequest struct {
 func (x *KeepAliveRequest) Reset() {
 	*x = KeepAliveRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_pkg_rpc_manager_manager_proto_msgTypes[15]
+		mi := &file_pkg_rpc_manager_manager_proto_msgTypes[13]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -1344,7 +1146,7 @@ func (x *KeepAliveRequest) String() string {
 func (*KeepAliveRequest) ProtoMessage() {}
 
 func (x *KeepAliveRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_pkg_rpc_manager_manager_proto_msgTypes[15]
+	mi := &file_pkg_rpc_manager_manager_proto_msgTypes[13]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1357,7 +1159,7 @@ func (x *KeepAliveRequest) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use KeepAliveRequest.ProtoReflect.Descriptor instead.
 func (*KeepAliveRequest) Descriptor() ([]byte, []int) {
-	return file_pkg_rpc_manager_manager_proto_rawDescGZIP(), []int{15}
+	return file_pkg_rpc_manager_manager_proto_rawDescGZIP(), []int{13}
 }
 
 func (x *KeepAliveRequest) GetSourceType() SourceType {
@@ -1424,7 +1226,7 @@ var file_pkg_rpc_manager_manager_proto_rawDesc = []byte{
 	0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x24, 0x0a, 0x09, 0x68, 0x6f, 0x73, 0x74,
 	0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04,
 	0x72, 0x02, 0x68, 0x01, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xb0,
-	0x02, 0x0a, 0x10, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x44, 0x4e, 0x52, 0x65, 0x71, 0x75,
+	0x02, 0x0a, 0x10, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x44, 0x4e, 0x52, 0x65, 0x71, 0x75,
 	0x65, 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79,
 	0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x13, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67,
 	0x65, 0x72, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x42, 0x08, 0xfa,
@@ -1432,202 +1234,153 @@ var file_pkg_rpc_manager_manager_proto_rawDesc = []byte{
 	0x79, 0x70, 0x65, 0x12, 0x24, 0x0a, 0x09, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
 	0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x68, 0x01, 0x52,
 	0x08, 0x68, 0x6f, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x03, 0x69, 0x64, 0x63,
-	0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0d, 0xfa, 0x42, 0x0a, 0x72, 0x08, 0x10, 0x01, 0x18,
+	0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0d, 0xfa, 0x42, 0x0a, 0x72, 0x08, 0x10, 0x01, 0x18,
 	0x80, 0x08, 0xd0, 0x01, 0x01, 0x52, 0x03, 0x69, 0x64, 0x63, 0x12, 0x27, 0x0a, 0x08, 0x6c, 0x6f,
-	0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0b, 0xfa, 0x42,
+	0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0b, 0xfa, 0x42,
 	0x08, 0x72, 0x06, 0x18, 0x80, 0x08, 0xd0, 0x01, 0x01, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74,
-	0x69, 0x6f, 0x6e, 0x12, 0x17, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x42,
+	0x69, 0x6f, 0x6e, 0x12, 0x17, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42,
 	0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x70, 0x01, 0x52, 0x02, 0x69, 0x70, 0x12, 0x20, 0x0a, 0x04,
-	0x70, 0x6f, 0x72, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x42, 0x0c, 0xfa, 0x42, 0x09, 0x1a,
+	0x70, 0x6f, 0x72, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x42, 0x0c, 0xfa, 0x42, 0x09, 0x1a,
 	0x07, 0x10, 0xff, 0xff, 0x03, 0x28, 0x80, 0x08, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x31,
 	0x0a, 0x0d, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18,
-	0x08, 0x20, 0x01, 0x28, 0x05, 0x42, 0x0c, 0xfa, 0x42, 0x09, 0x1a, 0x07, 0x10, 0xff, 0xff, 0x03,
+	0x07, 0x20, 0x01, 0x28, 0x05, 0x42, 0x0c, 0xfa, 0x42, 0x09, 0x1a, 0x07, 0x10, 0xff, 0xff, 0x03,
 	0x28, 0x80, 0x08, 0x52, 0x0c, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x6f, 0x72,
-	0x74, 0x22, 0xb7, 0x02, 0x0a, 0x10, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x44, 0x4e, 0x52,
-	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
-	0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x13, 0x2e, 0x6d, 0x61,
-	0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65,
-	0x42, 0x08, 0xfa, 0x42, 0x05, 0x82, 0x01, 0x02, 0x10, 0x01, 0x52, 0x0a, 0x73, 0x6f, 0x75, 0x72,
-	0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x24, 0x0a, 0x09, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x6e,
-	0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02,
-	0x68, 0x01, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x03,
-	0x69, 0x64, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0d, 0xfa, 0x42, 0x0a, 0x72, 0x08,
-	0x10, 0x01, 0x18, 0x80, 0x08, 0xd0, 0x01, 0x01, 0x52, 0x03, 0x69, 0x64, 0x63, 0x12, 0x27, 0x0a,
-	0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42,
-	0x0b, 0xfa, 0x42, 0x08, 0x72, 0x06, 0x18, 0x80, 0x08, 0xd0, 0x01, 0x01, 0x52, 0x08, 0x6c, 0x6f,
-	0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x05, 0x20, 0x01,
-	0x28, 0x09, 0x42, 0x0a, 0xfa, 0x42, 0x07, 0x72, 0x05, 0x70, 0x01, 0xd0, 0x01, 0x01, 0x52, 0x02,
-	0x69, 0x70, 0x12, 0x22, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05,
-	0x42, 0x0e, 0xfa, 0x42, 0x0b, 0x1a, 0x09, 0x10, 0xff, 0xff, 0x03, 0x28, 0x80, 0x08, 0x40, 0x01,
-	0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x33, 0x0a, 0x0d, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f,
-	0x61, 0x64, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x42, 0x0e, 0xfa,
-	0x42, 0x0b, 0x1a, 0x09, 0x10, 0xff, 0xff, 0x03, 0x28, 0x80, 0x08, 0x40, 0x01, 0x52, 0x0c, 0x64,
-	0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x22, 0xaa, 0x01, 0x0a, 0x19,
-	0x41, 0x64, 0x64, 0x43, 0x44, 0x4e, 0x54, 0x6f, 0x43, 0x44, 0x4e, 0x43, 0x6c, 0x75, 0x73, 0x74,
-	0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x0b, 0x73, 0x6f, 0x75,
-	0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x13,
-	0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54,
-	0x79, 0x70, 0x65, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x82, 0x01, 0x02, 0x10, 0x01, 0x52, 0x0a, 0x73,
-	0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1e, 0x0a, 0x06, 0x63, 0x64, 0x6e,
-	0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x32, 0x02,
-	0x40, 0x01, 0x52, 0x05, 0x63, 0x64, 0x6e, 0x49, 0x64, 0x12, 0x2d, 0x0a, 0x0e, 0x63, 0x64, 0x6e,
-	0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28,
-	0x04, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x32, 0x02, 0x40, 0x01, 0x52, 0x0c, 0x63, 0x64, 0x6e, 0x43,
-	0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x22, 0xc4, 0x01, 0x0a, 0x10, 0x53, 0x63, 0x68,
-	0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x0e, 0x0a,
-	0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a,
-	0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d,
-	0x65, 0x12, 0x10, 0x0a, 0x03, 0x62, 0x69, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
-	0x62, 0x69, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x04, 0x20,
-	0x01, 0x28, 0x0c, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x23, 0x0a, 0x0d, 0x63,
-	0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x05, 0x20, 0x01,
-	0x28, 0x0c, 0x52, 0x0c, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
-	0x12, 0x3d, 0x0a, 0x0e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x67, 0x72, 0x6f,
-	0x75, 0x70, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67,
-	0x65, 0x72, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x47, 0x72, 0x6f, 0x75, 0x70,
-	0x52, 0x0d, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x22,
-	0xbf, 0x02, 0x0a, 0x09, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x12, 0x0e, 0x0a,
-	0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1b, 0x0a,
-	0x09, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
-	0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x76, 0x69,
-	0x70, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x76, 0x69, 0x70, 0x73, 0x12, 0x10,
-	0x0a, 0x03, 0x69, 0x64, 0x63, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x69, 0x64, 0x63,
-	0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a,
-	0x6e, 0x65, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c,
-	0x52, 0x09, 0x6e, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x0e, 0x0a, 0x02, 0x69,
-	0x70, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x70,
-	0x6f, 0x72, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12,
-	0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52,
-	0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x46, 0x0a, 0x11, 0x73, 0x63, 0x68, 0x65, 0x64,
-	0x75, 0x6c, 0x65, 0x72, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, 0x0b, 0x20, 0x01,
-	0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x53, 0x63, 0x68,
-	0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x10, 0x73,
-	0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12,
-	0x20, 0x0a, 0x04, 0x63, 0x64, 0x6e, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e,
-	0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x43, 0x44, 0x4e, 0x52, 0x04, 0x63, 0x64, 0x6e,
-	0x73, 0x22, 0x7b, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65,
+	0x74, 0x22, 0xaa, 0x01, 0x0a, 0x19, 0x41, 0x64, 0x64, 0x43, 0x44, 0x4e, 0x54, 0x6f, 0x43, 0x44,
+	0x4e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
+	0x3e, 0x0a, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01,
+	0x20, 0x01, 0x28, 0x0e, 0x32, 0x13, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x53,
+	0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x82, 0x01,
+	0x02, 0x10, 0x01, 0x52, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12,
+	0x1e, 0x0a, 0x06, 0x63, 0x64, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42,
+	0x07, 0xfa, 0x42, 0x04, 0x32, 0x02, 0x40, 0x01, 0x52, 0x05, 0x63, 0x64, 0x6e, 0x49, 0x64, 0x12,
+	0x2d, 0x0a, 0x0e, 0x63, 0x64, 0x6e, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69,
+	0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x32, 0x02, 0x40, 0x01,
+	0x52, 0x0c, 0x63, 0x64, 0x6e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x22, 0xc4,
+	0x01, 0x0a, 0x10, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x43, 0x6c, 0x75, 0x73,
+	0x74, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52,
+	0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x62, 0x69, 0x6f, 0x18, 0x03,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x62, 0x69, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6f, 0x6e,
+	0x66, 0x69, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69,
+	0x67, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66,
+	0x69, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74,
+	0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3d, 0x0a, 0x0e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69,
+	0x74, 0x79, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16,
+	0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74,
+	0x79, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x0d, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79,
+	0x47, 0x72, 0x6f, 0x75, 0x70, 0x22, 0xbf, 0x02, 0x0a, 0x09, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75,
+	0x6c, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52,
+	0x02, 0x69, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
+	0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65,
+	0x12, 0x12, 0x0a, 0x04, 0x76, 0x69, 0x70, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
+	0x76, 0x69, 0x70, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x64, 0x63, 0x18, 0x04, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x03, 0x69, 0x64, 0x63, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69,
+	0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69,
+	0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, 0x65, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+	0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x6e, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69,
+	0x67, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69,
+	0x70, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52,
+	0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18,
+	0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x46, 0x0a,
+	0x11, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74,
+	0x65, 0x72, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67,
+	0x65, 0x72, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x43, 0x6c, 0x75, 0x73,
+	0x74, 0x65, 0x72, 0x52, 0x10, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x43, 0x6c,
+	0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x20, 0x0a, 0x04, 0x63, 0x64, 0x6e, 0x73, 0x18, 0x0c, 0x20,
+	0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x43, 0x44,
+	0x4e, 0x52, 0x04, 0x63, 0x64, 0x6e, 0x73, 0x22, 0x7b, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x53, 0x63,
+	0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3e,
+	0x0a, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20,
+	0x01, 0x28, 0x0e, 0x32, 0x13, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x53, 0x6f,
+	0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x82, 0x01, 0x02,
+	0x10, 0x01, 0x52, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x24,
+	0x0a, 0x09, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x68, 0x01, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74,
+	0x4e, 0x61, 0x6d, 0x65, 0x22, 0xd0, 0x02, 0x0a, 0x16, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53,
+	0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
+	0x3e, 0x0a, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01,
+	0x20, 0x01, 0x28, 0x0e, 0x32, 0x13, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x53,
+	0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x82, 0x01,
+	0x02, 0x10, 0x01, 0x52, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12,
+	0x24, 0x0a, 0x09, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01,
+	0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x68, 0x01, 0x52, 0x08, 0x68, 0x6f, 0x73,
+	0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x04, 0x76, 0x69, 0x70, 0x73, 0x18, 0x04, 0x20,
+	0x01, 0x28, 0x09, 0x42, 0x0d, 0xfa, 0x42, 0x0a, 0x72, 0x08, 0x10, 0x01, 0x18, 0x80, 0x08, 0xd0,
+	0x01, 0x01, 0x52, 0x04, 0x76, 0x69, 0x70, 0x73, 0x12, 0x1f, 0x0a, 0x03, 0x69, 0x64, 0x63, 0x18,
+	0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0d, 0xfa, 0x42, 0x0a, 0x72, 0x08, 0x10, 0x01, 0x18, 0x80,
+	0x08, 0xd0, 0x01, 0x01, 0x52, 0x03, 0x69, 0x64, 0x63, 0x12, 0x27, 0x0a, 0x08, 0x6c, 0x6f, 0x63,
+	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0b, 0xfa, 0x42, 0x08,
+	0x72, 0x06, 0x18, 0x80, 0x08, 0xd0, 0x01, 0x01, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69,
+	0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x0a, 0x6e, 0x65, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+	0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x09, 0xfa, 0x42, 0x06, 0x7a, 0x04, 0x10, 0x01, 0x70,
+	0x01, 0x52, 0x09, 0x6e, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x17, 0x0a, 0x02,
+	0x69, 0x70, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x70,
+	0x01, 0x52, 0x02, 0x69, 0x70, 0x12, 0x20, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x09, 0x20,
+	0x01, 0x28, 0x05, 0x42, 0x0c, 0xfa, 0x42, 0x09, 0x1a, 0x07, 0x10, 0xff, 0xff, 0x03, 0x28, 0x80,
+	0x08, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x22, 0xd5, 0x01, 0x0a, 0x2c, 0x41, 0x64, 0x64, 0x53,
+	0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x54,
+	0x6f, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65,
 	0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x0b, 0x73, 0x6f, 0x75, 0x72,
 	0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x13, 0x2e,
 	0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79,
 	0x70, 0x65, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x82, 0x01, 0x02, 0x10, 0x01, 0x52, 0x0a, 0x73, 0x6f,
-	0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x24, 0x0a, 0x09, 0x68, 0x6f, 0x73, 0x74,
-	0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04,
-	0x72, 0x02, 0x68, 0x01, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xd0,
-	0x02, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c,
-	0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x0b, 0x73, 0x6f, 0x75,
+	0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x2a, 0x0a, 0x0c, 0x73, 0x63, 0x68, 0x65,
+	0x64, 0x75, 0x6c, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x07,
+	0xfa, 0x42, 0x04, 0x32, 0x02, 0x40, 0x01, 0x52, 0x0b, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c,
+	0x65, 0x72, 0x49, 0x64, 0x12, 0x39, 0x0a, 0x14, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65,
+	0x72, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01,
+	0x28, 0x04, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x32, 0x02, 0x40, 0x01, 0x52, 0x12, 0x73, 0x63, 0x68,
+	0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x22,
+	0xa8, 0x02, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65,
+	0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x0b, 0x73, 0x6f, 0x75,
 	0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x13,
 	0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54,
 	0x79, 0x70, 0x65, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x82, 0x01, 0x02, 0x10, 0x01, 0x52, 0x0a, 0x73,
 	0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x24, 0x0a, 0x09, 0x68, 0x6f, 0x73,
 	0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42,
 	0x04, 0x72, 0x02, 0x68, 0x01, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12,
-	0x21, 0x0a, 0x04, 0x76, 0x69, 0x70, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0d, 0xfa,
-	0x42, 0x0a, 0x72, 0x08, 0x10, 0x01, 0x18, 0x80, 0x08, 0xd0, 0x01, 0x01, 0x52, 0x04, 0x76, 0x69,
-	0x70, 0x73, 0x12, 0x1f, 0x0a, 0x03, 0x69, 0x64, 0x63, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42,
-	0x0d, 0xfa, 0x42, 0x0a, 0x72, 0x08, 0x10, 0x01, 0x18, 0x80, 0x08, 0xd0, 0x01, 0x01, 0x52, 0x03,
-	0x69, 0x64, 0x63, 0x12, 0x27, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18,
-	0x06, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0b, 0xfa, 0x42, 0x08, 0x72, 0x06, 0x18, 0x80, 0x08, 0xd0,
-	0x01, 0x01, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x0a,
-	0x6e, 0x65, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c,
-	0x42, 0x09, 0xfa, 0x42, 0x06, 0x7a, 0x04, 0x10, 0x01, 0x70, 0x01, 0x52, 0x09, 0x6e, 0x65, 0x74,
-	0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x17, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x08, 0x20, 0x01,
-	0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x70, 0x01, 0x52, 0x02, 0x69, 0x70, 0x12,
-	0x20, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x05, 0x42, 0x0c, 0xfa,
-	0x42, 0x09, 0x1a, 0x07, 0x10, 0xff, 0xff, 0x03, 0x28, 0x80, 0x08, 0x52, 0x04, 0x70, 0x6f, 0x72,
-	0x74, 0x22, 0xd5, 0x02, 0x0a, 0x16, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x63, 0x68, 0x65,
-	0x64, 0x75, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x0b,
+	0x17, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04,
+	0x72, 0x02, 0x70, 0x01, 0x52, 0x02, 0x69, 0x70, 0x12, 0x53, 0x0a, 0x09, 0x68, 0x6f, 0x73, 0x74,
+	0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x6d, 0x61,
+	0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75,
+	0x6c, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x48, 0x6f, 0x73, 0x74,
+	0x49, 0x6e, 0x66, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x9a, 0x01,
+	0x02, 0x30, 0x01, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x1a, 0x3b, 0x0a,
+	0x0d, 0x48, 0x6f, 0x73, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10,
+	0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79,
+	0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x4c, 0x0a, 0x16, 0x4c, 0x69,
+	0x73, 0x74, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70,
+	0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x0a, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65,
+	0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67,
+	0x65, 0x72, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x52, 0x0a, 0x73, 0x63,
+	0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x73, 0x22, 0x78, 0x0a, 0x10, 0x4b, 0x65, 0x65, 0x70,
+	0x41, 0x6c, 0x69, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x0b,
 	0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
 	0x0e, 0x32, 0x13, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x53, 0x6f, 0x75, 0x72,
 	0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x82, 0x01, 0x02, 0x10, 0x01,
 	0x52, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x24, 0x0a, 0x09,
 	0x68, 0x6f, 0x73, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42,
 	0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x68, 0x01, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x4e, 0x61,
-	0x6d, 0x65, 0x12, 0x21, 0x0a, 0x04, 0x76, 0x69, 0x70, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09,
-	0x42, 0x0d, 0xfa, 0x42, 0x0a, 0x72, 0x08, 0x10, 0x01, 0x18, 0x80, 0x08, 0xd0, 0x01, 0x01, 0x52,
-	0x04, 0x76, 0x69, 0x70, 0x73, 0x12, 0x1f, 0x0a, 0x03, 0x69, 0x64, 0x63, 0x18, 0x05, 0x20, 0x01,
-	0x28, 0x09, 0x42, 0x0d, 0xfa, 0x42, 0x0a, 0x72, 0x08, 0x10, 0x01, 0x18, 0x80, 0x08, 0xd0, 0x01,
-	0x01, 0x52, 0x03, 0x69, 0x64, 0x63, 0x12, 0x27, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69,
-	0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0b, 0xfa, 0x42, 0x08, 0x72, 0x06, 0x18,
-	0x80, 0x08, 0xd0, 0x01, 0x01, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12,
-	0x28, 0x0a, 0x0a, 0x6e, 0x65, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x07, 0x20,
-	0x01, 0x28, 0x0c, 0x42, 0x09, 0xfa, 0x42, 0x06, 0x7a, 0x04, 0x10, 0x01, 0x70, 0x01, 0x52, 0x09,
-	0x6e, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1a, 0x0a, 0x02, 0x69, 0x70, 0x18,
-	0x08, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0a, 0xfa, 0x42, 0x07, 0x72, 0x05, 0x70, 0x01, 0xd0, 0x01,
-	0x01, 0x52, 0x02, 0x69, 0x70, 0x12, 0x22, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x09, 0x20,
-	0x01, 0x28, 0x05, 0x42, 0x0e, 0xfa, 0x42, 0x0b, 0x1a, 0x09, 0x10, 0xff, 0xff, 0x03, 0x28, 0x80,
-	0x08, 0x40, 0x01, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x22, 0xd5, 0x01, 0x0a, 0x2c, 0x41, 0x64,
-	0x64, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65,
-	0x72, 0x54, 0x6f, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x43, 0x6c, 0x75, 0x73,
-	0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x0b, 0x73, 0x6f,
-	0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32,
-	0x13, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65,
-	0x54, 0x79, 0x70, 0x65, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x82, 0x01, 0x02, 0x10, 0x01, 0x52, 0x0a,
-	0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x2a, 0x0a, 0x0c, 0x73, 0x63,
-	0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04,
-	0x42, 0x07, 0xfa, 0x42, 0x04, 0x32, 0x02, 0x40, 0x01, 0x52, 0x0b, 0x73, 0x63, 0x68, 0x65, 0x64,
-	0x75, 0x6c, 0x65, 0x72, 0x49, 0x64, 0x12, 0x39, 0x0a, 0x14, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75,
-	0x6c, 0x65, 0x72, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03,
-	0x20, 0x01, 0x28, 0x04, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x32, 0x02, 0x40, 0x01, 0x52, 0x12, 0x73,
-	0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49,
-	0x64, 0x22, 0xa8, 0x02, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75,
-	0x6c, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x0b, 0x73,
-	0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e,
-	0x32, 0x13, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63,
-	0x65, 0x54, 0x79, 0x70, 0x65, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x82, 0x01, 0x02, 0x10, 0x01, 0x52,
-	0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x24, 0x0a, 0x09, 0x68,
-	0x6f, 0x73, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07,
-	0xfa, 0x42, 0x04, 0x72, 0x02, 0x68, 0x01, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x4e, 0x61, 0x6d,
-	0x65, 0x12, 0x17, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa,
-	0x42, 0x04, 0x72, 0x02, 0x70, 0x01, 0x52, 0x02, 0x69, 0x70, 0x12, 0x53, 0x0a, 0x09, 0x68, 0x6f,
-	0x73, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e,
-	0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x63, 0x68, 0x65,
-	0x64, 0x75, 0x6c, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x48, 0x6f,
-	0x73, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x42, 0x08, 0xfa, 0x42, 0x05,
-	0x9a, 0x01, 0x02, 0x30, 0x01, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x1a,
-	0x3b, 0x0a, 0x0d, 0x48, 0x6f, 0x73, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79,
-	0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b,
-	0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x4c, 0x0a, 0x16,
-	0x4c, 0x69, 0x73, 0x74, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x73, 0x52, 0x65,
-	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x0a, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75,
-	0x6c, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x61, 0x6e,
-	0x61, 0x67, 0x65, 0x72, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x52, 0x0a,
-	0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x73, 0x22, 0x78, 0x0a, 0x10, 0x4b, 0x65,
-	0x65, 0x70, 0x41, 0x6c, 0x69, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3e,
-	0x0a, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20,
-	0x01, 0x28, 0x0e, 0x32, 0x13, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x53, 0x6f,
-	0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x82, 0x01, 0x02,
-	0x10, 0x01, 0x52, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x24,
-	0x0a, 0x09, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
-	0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x68, 0x01, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74,
-	0x4e, 0x61, 0x6d, 0x65, 0x2a, 0x45, 0x0a, 0x0a, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79,
-	0x70, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f,
-	0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x43, 0x4c, 0x49, 0x45,
-	0x4e, 0x54, 0x5f, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x43,
-	0x44, 0x4e, 0x5f, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x10, 0x02, 0x32, 0xd6, 0x05, 0x0a, 0x07,
-	0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x12, 0x2e, 0x0a, 0x06, 0x47, 0x65, 0x74, 0x43, 0x44,
-	0x4e, 0x12, 0x16, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x74, 0x43,
-	0x44, 0x4e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0c, 0x2e, 0x6d, 0x61, 0x6e, 0x61,
-	0x67, 0x65, 0x72, 0x2e, 0x43, 0x44, 0x4e, 0x12, 0x34, 0x0a, 0x09, 0x43, 0x72, 0x65, 0x61, 0x74,
-	0x65, 0x43, 0x44, 0x4e, 0x12, 0x19, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x43,
-	0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x44, 0x4e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
-	0x0c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x43, 0x44, 0x4e, 0x12, 0x34, 0x0a,
-	0x09, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x44, 0x4e, 0x12, 0x19, 0x2e, 0x6d, 0x61, 0x6e,
-	0x61, 0x67, 0x65, 0x72, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x44, 0x4e, 0x52, 0x65,
-	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e,
-	0x43, 0x44, 0x4e, 0x12, 0x50, 0x0a, 0x12, 0x41, 0x64, 0x64, 0x43, 0x44, 0x4e, 0x54, 0x6f, 0x43,
-	0x44, 0x4e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x22, 0x2e, 0x6d, 0x61, 0x6e, 0x61,
-	0x67, 0x65, 0x72, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x44, 0x4e, 0x54, 0x6f, 0x43, 0x44, 0x4e, 0x43,
-	0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e,
-	0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
-	0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x40, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x53, 0x63, 0x68, 0x65,
-	0x64, 0x75, 0x6c, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e,
-	0x47, 0x65, 0x74, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75,
-	0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x53, 0x63,
-	0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x12, 0x46, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74,
-	0x65, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x12, 0x1f, 0x2e, 0x6d, 0x61, 0x6e,
-	0x61, 0x67, 0x65, 0x72, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x63, 0x68, 0x65, 0x64,
+	0x6d, 0x65, 0x2a, 0x45, 0x0a, 0x0a, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65,
+	0x12, 0x14, 0x0a, 0x10, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x53, 0x4f,
+	0x55, 0x52, 0x43, 0x45, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x43, 0x4c, 0x49, 0x45, 0x4e, 0x54,
+	0x5f, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x43, 0x44, 0x4e,
+	0x5f, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x10, 0x02, 0x32, 0xd8, 0x04, 0x0a, 0x07, 0x4d, 0x61,
+	0x6e, 0x61, 0x67, 0x65, 0x72, 0x12, 0x2e, 0x0a, 0x06, 0x47, 0x65, 0x74, 0x43, 0x44, 0x4e, 0x12,
+	0x16, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x44, 0x4e,
+	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65,
+	0x72, 0x2e, 0x43, 0x44, 0x4e, 0x12, 0x34, 0x0a, 0x09, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43,
+	0x44, 0x4e, 0x12, 0x19, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x55, 0x70, 0x64,
+	0x61, 0x74, 0x65, 0x43, 0x44, 0x4e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0c, 0x2e,
+	0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x43, 0x44, 0x4e, 0x12, 0x50, 0x0a, 0x12, 0x41,
+	0x64, 0x64, 0x43, 0x44, 0x4e, 0x54, 0x6f, 0x43, 0x44, 0x4e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65,
+	0x72, 0x12, 0x22, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x41, 0x64, 0x64, 0x43,
+	0x44, 0x4e, 0x54, 0x6f, 0x43, 0x44, 0x4e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65,
+	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
+	0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x40, 0x0a,
+	0x0c, 0x47, 0x65, 0x74, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x12, 0x1c, 0x2e,
+	0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x63, 0x68, 0x65, 0x64,
 	0x75, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x6d, 0x61,
 	0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x12,
 	0x46, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c,
@@ -1670,71 +1423,63 @@ func file_pkg_rpc_manager_manager_proto_rawDescGZIP() []byte {
 }
 
 var file_pkg_rpc_manager_manager_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
-var file_pkg_rpc_manager_manager_proto_msgTypes = make([]protoimpl.MessageInfo, 17)
+var file_pkg_rpc_manager_manager_proto_msgTypes = make([]protoimpl.MessageInfo, 15)
 var file_pkg_rpc_manager_manager_proto_goTypes = []interface{}{
 	(SourceType)(0),                                      // 0: manager.SourceType
 	(*CDNCluster)(nil),                                   // 1: manager.CDNCluster
 	(*SecurityGroup)(nil),                                // 2: manager.SecurityGroup
 	(*CDN)(nil),                                          // 3: manager.CDN
 	(*GetCDNRequest)(nil),                                // 4: manager.GetCDNRequest
-	(*CreateCDNRequest)(nil),                             // 5: manager.CreateCDNRequest
-	(*UpdateCDNRequest)(nil),                             // 6: manager.UpdateCDNRequest
-	(*AddCDNToCDNClusterRequest)(nil),                    // 7: manager.AddCDNToCDNClusterRequest
-	(*SchedulerCluster)(nil),                             // 8: manager.SchedulerCluster
-	(*Scheduler)(nil),                                    // 9: manager.Scheduler
-	(*GetSchedulerRequest)(nil),                          // 10: manager.GetSchedulerRequest
-	(*CreateSchedulerRequest)(nil),                       // 11: manager.CreateSchedulerRequest
-	(*UpdateSchedulerRequest)(nil),                       // 12: manager.UpdateSchedulerRequest
-	(*AddSchedulerClusterToSchedulerClusterRequest)(nil), // 13: manager.AddSchedulerClusterToSchedulerClusterRequest
-	(*ListSchedulersRequest)(nil),                        // 14: manager.ListSchedulersRequest
-	(*ListSchedulersResponse)(nil),                       // 15: manager.ListSchedulersResponse
-	(*KeepAliveRequest)(nil),                             // 16: manager.KeepAliveRequest
-	nil,                                                  // 17: manager.ListSchedulersRequest.HostInfoEntry
-	(*emptypb.Empty)(nil),                                // 18: google.protobuf.Empty
+	(*UpdateCDNRequest)(nil),                             // 5: manager.UpdateCDNRequest
+	(*AddCDNToCDNClusterRequest)(nil),                    // 6: manager.AddCDNToCDNClusterRequest
+	(*SchedulerCluster)(nil),                             // 7: manager.SchedulerCluster
+	(*Scheduler)(nil),                                    // 8: manager.Scheduler
+	(*GetSchedulerRequest)(nil),                          // 9: manager.GetSchedulerRequest
+	(*UpdateSchedulerRequest)(nil),                       // 10: manager.UpdateSchedulerRequest
+	(*AddSchedulerClusterToSchedulerClusterRequest)(nil), // 11: manager.AddSchedulerClusterToSchedulerClusterRequest
+	(*ListSchedulersRequest)(nil),                        // 12: manager.ListSchedulersRequest
+	(*ListSchedulersResponse)(nil),                       // 13: manager.ListSchedulersResponse
+	(*KeepAliveRequest)(nil),                             // 14: manager.KeepAliveRequest
+	nil,                                                  // 15: manager.ListSchedulersRequest.HostInfoEntry
+	(*emptypb.Empty)(nil),                                // 16: google.protobuf.Empty
 }
 var file_pkg_rpc_manager_manager_proto_depIdxs = []int32{
 	2,  // 0: manager.CDNCluster.security_group:type_name -> manager.SecurityGroup
 	1,  // 1: manager.CDN.cdn_cluster:type_name -> manager.CDNCluster
 	0,  // 2: manager.GetCDNRequest.source_type:type_name -> manager.SourceType
-	0,  // 3: manager.CreateCDNRequest.source_type:type_name -> manager.SourceType
-	0,  // 4: manager.UpdateCDNRequest.source_type:type_name -> manager.SourceType
-	0,  // 5: manager.AddCDNToCDNClusterRequest.source_type:type_name -> manager.SourceType
-	2,  // 6: manager.SchedulerCluster.security_group:type_name -> manager.SecurityGroup
-	8,  // 7: manager.Scheduler.scheduler_cluster:type_name -> manager.SchedulerCluster
-	3,  // 8: manager.Scheduler.cdns:type_name -> manager.CDN
-	0,  // 9: manager.GetSchedulerRequest.source_type:type_name -> manager.SourceType
-	0,  // 10: manager.CreateSchedulerRequest.source_type:type_name -> manager.SourceType
-	0,  // 11: manager.UpdateSchedulerRequest.source_type:type_name -> manager.SourceType
-	0,  // 12: manager.AddSchedulerClusterToSchedulerClusterRequest.source_type:type_name -> manager.SourceType
-	0,  // 13: manager.ListSchedulersRequest.source_type:type_name -> manager.SourceType
-	17, // 14: manager.ListSchedulersRequest.host_info:type_name -> manager.ListSchedulersRequest.HostInfoEntry
-	9,  // 15: manager.ListSchedulersResponse.schedulers:type_name -> manager.Scheduler
-	0,  // 16: manager.KeepAliveRequest.source_type:type_name -> manager.SourceType
-	4,  // 17: manager.Manager.GetCDN:input_type -> manager.GetCDNRequest
-	5,  // 18: manager.Manager.CreateCDN:input_type -> manager.CreateCDNRequest
-	6,  // 19: manager.Manager.UpdateCDN:input_type -> manager.UpdateCDNRequest
-	7,  // 20: manager.Manager.AddCDNToCDNCluster:input_type -> manager.AddCDNToCDNClusterRequest
-	10, // 21: manager.Manager.GetScheduler:input_type -> manager.GetSchedulerRequest
-	11, // 22: manager.Manager.CreateScheduler:input_type -> manager.CreateSchedulerRequest
-	12, // 23: manager.Manager.UpdateScheduler:input_type -> manager.UpdateSchedulerRequest
-	13, // 24: manager.Manager.AddSchedulerClusterToSchedulerCluster:input_type -> manager.AddSchedulerClusterToSchedulerClusterRequest
-	14, // 25: manager.Manager.ListSchedulers:input_type -> manager.ListSchedulersRequest
-	16, // 26: manager.Manager.KeepAlive:input_type -> manager.KeepAliveRequest
-	3,  // 27: manager.Manager.GetCDN:output_type -> manager.CDN
-	3,  // 28: manager.Manager.CreateCDN:output_type -> manager.CDN
-	3,  // 29: manager.Manager.UpdateCDN:output_type -> manager.CDN
-	18, // 30: manager.Manager.AddCDNToCDNCluster:output_type -> google.protobuf.Empty
-	9,  // 31: manager.Manager.GetScheduler:output_type -> manager.Scheduler
-	9,  // 32: manager.Manager.CreateScheduler:output_type -> manager.Scheduler
-	9,  // 33: manager.Manager.UpdateScheduler:output_type -> manager.Scheduler
-	18, // 34: manager.Manager.AddSchedulerClusterToSchedulerCluster:output_type -> google.protobuf.Empty
-	15, // 35: manager.Manager.ListSchedulers:output_type -> manager.ListSchedulersResponse
-	18, // 36: manager.Manager.KeepAlive:output_type -> google.protobuf.Empty
-	27, // [27:37] is the sub-list for method output_type
-	17, // [17:27] is the sub-list for method input_type
-	17, // [17:17] is the sub-list for extension type_name
-	17, // [17:17] is the sub-list for extension extendee
-	0,  // [0:17] is the sub-list for field type_name
+	0,  // 3: manager.UpdateCDNRequest.source_type:type_name -> manager.SourceType
+	0,  // 4: manager.AddCDNToCDNClusterRequest.source_type:type_name -> manager.SourceType
+	2,  // 5: manager.SchedulerCluster.security_group:type_name -> manager.SecurityGroup
+	7,  // 6: manager.Scheduler.scheduler_cluster:type_name -> manager.SchedulerCluster
+	3,  // 7: manager.Scheduler.cdns:type_name -> manager.CDN
+	0,  // 8: manager.GetSchedulerRequest.source_type:type_name -> manager.SourceType
+	0,  // 9: manager.UpdateSchedulerRequest.source_type:type_name -> manager.SourceType
+	0,  // 10: manager.AddSchedulerClusterToSchedulerClusterRequest.source_type:type_name -> manager.SourceType
+	0,  // 11: manager.ListSchedulersRequest.source_type:type_name -> manager.SourceType
+	15, // 12: manager.ListSchedulersRequest.host_info:type_name -> manager.ListSchedulersRequest.HostInfoEntry
+	8,  // 13: manager.ListSchedulersResponse.schedulers:type_name -> manager.Scheduler
+	0,  // 14: manager.KeepAliveRequest.source_type:type_name -> manager.SourceType
+	4,  // 15: manager.Manager.GetCDN:input_type -> manager.GetCDNRequest
+	5,  // 16: manager.Manager.UpdateCDN:input_type -> manager.UpdateCDNRequest
+	6,  // 17: manager.Manager.AddCDNToCDNCluster:input_type -> manager.AddCDNToCDNClusterRequest
+	9,  // 18: manager.Manager.GetScheduler:input_type -> manager.GetSchedulerRequest
+	10, // 19: manager.Manager.UpdateScheduler:input_type -> manager.UpdateSchedulerRequest
+	11, // 20: manager.Manager.AddSchedulerClusterToSchedulerCluster:input_type -> manager.AddSchedulerClusterToSchedulerClusterRequest
+	12, // 21: manager.Manager.ListSchedulers:input_type -> manager.ListSchedulersRequest
+	14, // 22: manager.Manager.KeepAlive:input_type -> manager.KeepAliveRequest
+	3,  // 23: manager.Manager.GetCDN:output_type -> manager.CDN
+	3,  // 24: manager.Manager.UpdateCDN:output_type -> manager.CDN
+	16, // 25: manager.Manager.AddCDNToCDNCluster:output_type -> google.protobuf.Empty
+	8,  // 26: manager.Manager.GetScheduler:output_type -> manager.Scheduler
+	8,  // 27: manager.Manager.UpdateScheduler:output_type -> manager.Scheduler
+	16, // 28: manager.Manager.AddSchedulerClusterToSchedulerCluster:output_type -> google.protobuf.Empty
+	13, // 29: manager.Manager.ListSchedulers:output_type -> manager.ListSchedulersResponse
+	16, // 30: manager.Manager.KeepAlive:output_type -> google.protobuf.Empty
+	23, // [23:31] is the sub-list for method output_type
+	15, // [15:23] is the sub-list for method input_type
+	15, // [15:15] is the sub-list for extension type_name
+	15, // [15:15] is the sub-list for extension extendee
+	0,  // [0:15] is the sub-list for field type_name
 }
 
 func init() { file_pkg_rpc_manager_manager_proto_init() }
@@ -1792,18 +1537,6 @@ func file_pkg_rpc_manager_manager_proto_init() {
 			}
 		}
 		file_pkg_rpc_manager_manager_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*CreateCDNRequest); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_pkg_rpc_manager_manager_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
 			switch v := v.(*UpdateCDNRequest); i {
 			case 0:
 				return &v.state
@@ -1815,7 +1548,7 @@ func file_pkg_rpc_manager_manager_proto_init() {
 				return nil
 			}
 		}
-		file_pkg_rpc_manager_manager_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
+		file_pkg_rpc_manager_manager_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
 			switch v := v.(*AddCDNToCDNClusterRequest); i {
 			case 0:
 				return &v.state
@@ -1827,7 +1560,7 @@ func file_pkg_rpc_manager_manager_proto_init() {
 				return nil
 			}
 		}
-		file_pkg_rpc_manager_manager_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
+		file_pkg_rpc_manager_manager_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
 			switch v := v.(*SchedulerCluster); i {
 			case 0:
 				return &v.state
@@ -1839,7 +1572,7 @@ func file_pkg_rpc_manager_manager_proto_init() {
 				return nil
 			}
 		}
-		file_pkg_rpc_manager_manager_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
+		file_pkg_rpc_manager_manager_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
 			switch v := v.(*Scheduler); i {
 			case 0:
 				return &v.state
@@ -1851,7 +1584,7 @@ func file_pkg_rpc_manager_manager_proto_init() {
 				return nil
 			}
 		}
-		file_pkg_rpc_manager_manager_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
+		file_pkg_rpc_manager_manager_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
 			switch v := v.(*GetSchedulerRequest); i {
 			case 0:
 				return &v.state
@@ -1863,19 +1596,7 @@ func file_pkg_rpc_manager_manager_proto_init() {
 				return nil
 			}
 		}
-		file_pkg_rpc_manager_manager_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*CreateSchedulerRequest); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_pkg_rpc_manager_manager_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
+		file_pkg_rpc_manager_manager_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
 			switch v := v.(*UpdateSchedulerRequest); i {
 			case 0:
 				return &v.state
@@ -1887,7 +1608,7 @@ func file_pkg_rpc_manager_manager_proto_init() {
 				return nil
 			}
 		}
-		file_pkg_rpc_manager_manager_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
+		file_pkg_rpc_manager_manager_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
 			switch v := v.(*AddSchedulerClusterToSchedulerClusterRequest); i {
 			case 0:
 				return &v.state
@@ -1899,7 +1620,7 @@ func file_pkg_rpc_manager_manager_proto_init() {
 				return nil
 			}
 		}
-		file_pkg_rpc_manager_manager_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
+		file_pkg_rpc_manager_manager_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
 			switch v := v.(*ListSchedulersRequest); i {
 			case 0:
 				return &v.state
@@ -1911,7 +1632,7 @@ func file_pkg_rpc_manager_manager_proto_init() {
 				return nil
 			}
 		}
-		file_pkg_rpc_manager_manager_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
+		file_pkg_rpc_manager_manager_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
 			switch v := v.(*ListSchedulersResponse); i {
 			case 0:
 				return &v.state
@@ -1923,7 +1644,7 @@ func file_pkg_rpc_manager_manager_proto_init() {
 				return nil
 			}
 		}
-		file_pkg_rpc_manager_manager_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
+		file_pkg_rpc_manager_manager_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
 			switch v := v.(*KeepAliveRequest); i {
 			case 0:
 				return &v.state
@@ -1942,7 +1663,7 @@ func file_pkg_rpc_manager_manager_proto_init() {
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: file_pkg_rpc_manager_manager_proto_rawDesc,
 			NumEnums:      1,
-			NumMessages:   17,
+			NumMessages:   15,
 			NumExtensions: 0,
 			NumServices:   1,
 		},
diff --git a/pkg/rpc/manager/manager.pb.validate.go b/pkg/rpc/manager/manager.pb.validate.go
index ac1cb038..60248060 100644
--- a/pkg/rpc/manager/manager.pb.validate.go
+++ b/pkg/rpc/manager/manager.pb.validate.go
@@ -390,23 +390,23 @@ var _ interface {
 	ErrorName() string
 } = GetCDNRequestValidationError{}
 
-// Validate checks the field values on CreateCDNRequest with the rules defined
+// Validate checks the field values on UpdateCDNRequest with the rules defined
 // in the proto definition for this message. If any rules are violated, an
 // error is returned.
-func (m *CreateCDNRequest) Validate() error {
+func (m *UpdateCDNRequest) Validate() error {
 	if m == nil {
 		return nil
 	}
 
 	if _, ok := SourceType_name[int32(m.GetSourceType())]; !ok {
-		return CreateCDNRequestValidationError{
+		return UpdateCDNRequestValidationError{
 			field:  "SourceType",
 			reason: "value must be one of the defined enum values",
 		}
 	}
 
 	if err := m._validateHostname(m.GetHostName()); err != nil {
-		return CreateCDNRequestValidationError{
+		return UpdateCDNRequestValidationError{
 			field:  "HostName",
 			reason: "value must be a valid hostname",
 			cause:  err,
@@ -416,7 +416,7 @@ func (m *CreateCDNRequest) Validate() error {
 	if m.GetIdc() != "" {
 
 		if l := utf8.RuneCountInString(m.GetIdc()); l < 1 || l > 1024 {
-			return CreateCDNRequestValidationError{
+			return UpdateCDNRequestValidationError{
 				field:  "Idc",
 				reason: "value length must be between 1 and 1024 runes, inclusive",
 			}
@@ -427,7 +427,7 @@ func (m *CreateCDNRequest) Validate() error {
 	if m.GetLocation() != "" {
 
 		if utf8.RuneCountInString(m.GetLocation()) > 1024 {
-			return CreateCDNRequestValidationError{
+			return UpdateCDNRequestValidationError{
 				field:  "Location",
 				reason: "value length must be at most 1024 runes",
 			}
@@ -436,21 +436,21 @@ func (m *CreateCDNRequest) Validate() error {
 	}
 
 	if ip := net.ParseIP(m.GetIp()); ip == nil {
-		return CreateCDNRequestValidationError{
+		return UpdateCDNRequestValidationError{
 			field:  "Ip",
 			reason: "value must be a valid IP address",
 		}
 	}
 
 	if val := m.GetPort(); val < 1024 || val >= 65535 {
-		return CreateCDNRequestValidationError{
+		return UpdateCDNRequestValidationError{
 			field:  "Port",
 			reason: "value must be inside range [1024, 65535)",
 		}
 	}
 
 	if val := m.GetDownloadPort(); val < 1024 || val >= 65535 {
-		return CreateCDNRequestValidationError{
+		return UpdateCDNRequestValidationError{
 			field:  "DownloadPort",
 			reason: "value must be inside range [1024, 65535)",
 		}
@@ -459,171 +459,6 @@ func (m *CreateCDNRequest) Validate() error {
 	return nil
 }
 
-func (m *CreateCDNRequest) _validateHostname(host string) error {
-	s := strings.ToLower(strings.TrimSuffix(host, "."))
-
-	if len(host) > 253 {
-		return errors.New("hostname cannot exceed 253 characters")
-	}
-
-	for _, part := range strings.Split(s, ".") {
-		if l := len(part); l == 0 || l > 63 {
-			return errors.New("hostname part must be non-empty and cannot exceed 63 characters")
-		}
-
-		if part[0] == '-' {
-			return errors.New("hostname parts cannot begin with hyphens")
-		}
-
-		if part[len(part)-1] == '-' {
-			return errors.New("hostname parts cannot end with hyphens")
-		}
-
-		for _, r := range part {
-			if (r < 'a' || r > 'z') && (r < '0' || r > '9') && r != '-' {
-				return fmt.Errorf("hostname parts can only contain alphanumeric characters or hyphens, got %q", string(r))
-			}
-		}
-	}
-
-	return nil
-}
-
-// CreateCDNRequestValidationError is the validation error returned by
-// CreateCDNRequest.Validate if the designated constraints aren't met.
-type CreateCDNRequestValidationError struct {
-	field  string
-	reason string
-	cause  error
-	key    bool
-}
-
-// Field function returns field value.
-func (e CreateCDNRequestValidationError) Field() string { return e.field }
-
-// Reason function returns reason value.
-func (e CreateCDNRequestValidationError) Reason() string { return e.reason }
-
-// Cause function returns cause value.
-func (e CreateCDNRequestValidationError) Cause() error { return e.cause }
-
-// Key function returns key value.
-func (e CreateCDNRequestValidationError) Key() bool { return e.key }
-
-// ErrorName returns error name.
-func (e CreateCDNRequestValidationError) ErrorName() string { return "CreateCDNRequestValidationError" }
-
-// Error satisfies the builtin error interface
-func (e CreateCDNRequestValidationError) Error() string {
-	cause := ""
-	if e.cause != nil {
-		cause = fmt.Sprintf(" | caused by: %v", e.cause)
-	}
-
-	key := ""
-	if e.key {
-		key = "key for "
-	}
-
-	return fmt.Sprintf(
-		"invalid %sCreateCDNRequest.%s: %s%s",
-		key,
-		e.field,
-		e.reason,
-		cause)
-}
-
-var _ error = CreateCDNRequestValidationError{}
-
-var _ interface {
-	Field() string
-	Reason() string
-	Key() bool
-	Cause() error
-	ErrorName() string
-} = CreateCDNRequestValidationError{}
-
-// Validate checks the field values on UpdateCDNRequest with the rules defined
-// in the proto definition for this message. If any rules are violated, an
-// error is returned.
-func (m *UpdateCDNRequest) Validate() error {
-	if m == nil {
-		return nil
-	}
-
-	if _, ok := SourceType_name[int32(m.GetSourceType())]; !ok {
-		return UpdateCDNRequestValidationError{
-			field:  "SourceType",
-			reason: "value must be one of the defined enum values",
-		}
-	}
-
-	if err := m._validateHostname(m.GetHostName()); err != nil {
-		return UpdateCDNRequestValidationError{
-			field:  "HostName",
-			reason: "value must be a valid hostname",
-			cause:  err,
-		}
-	}
-
-	if m.GetIdc() != "" {
-
-		if l := utf8.RuneCountInString(m.GetIdc()); l < 1 || l > 1024 {
-			return UpdateCDNRequestValidationError{
-				field:  "Idc",
-				reason: "value length must be between 1 and 1024 runes, inclusive",
-			}
-		}
-
-	}
-
-	if m.GetLocation() != "" {
-
-		if utf8.RuneCountInString(m.GetLocation()) > 1024 {
-			return UpdateCDNRequestValidationError{
-				field:  "Location",
-				reason: "value length must be at most 1024 runes",
-			}
-		}
-
-	}
-
-	if m.GetIp() != "" {
-
-		if ip := net.ParseIP(m.GetIp()); ip == nil {
-			return UpdateCDNRequestValidationError{
-				field:  "Ip",
-				reason: "value must be a valid IP address",
-			}
-		}
-
-	}
-
-	if m.GetPort() != 0 {
-
-		if val := m.GetPort(); val < 1024 || val >= 65535 {
-			return UpdateCDNRequestValidationError{
-				field:  "Port",
-				reason: "value must be inside range [1024, 65535)",
-			}
-		}
-
-	}
-
-	if m.GetDownloadPort() != 0 {
-
-		if val := m.GetDownloadPort(); val < 1024 || val >= 65535 {
-			return UpdateCDNRequestValidationError{
-				field:  "DownloadPort",
-				reason: "value must be inside range [1024, 65535)",
-			}
-		}
-
-	}
-
-	return nil
-}
-
 func (m *UpdateCDNRequest) _validateHostname(host string) error {
 	s := strings.ToLower(strings.TrimSuffix(host, "."))
 
@@ -1094,176 +929,6 @@ var _ interface {
 	ErrorName() string
 } = GetSchedulerRequestValidationError{}
 
-// Validate checks the field values on CreateSchedulerRequest with the rules
-// defined in the proto definition for this message. If any rules are
-// violated, an error is returned.
-func (m *CreateSchedulerRequest) Validate() error {
-	if m == nil {
-		return nil
-	}
-
-	if _, ok := SourceType_name[int32(m.GetSourceType())]; !ok {
-		return CreateSchedulerRequestValidationError{
-			field:  "SourceType",
-			reason: "value must be one of the defined enum values",
-		}
-	}
-
-	if err := m._validateHostname(m.GetHostName()); err != nil {
-		return CreateSchedulerRequestValidationError{
-			field:  "HostName",
-			reason: "value must be a valid hostname",
-			cause:  err,
-		}
-	}
-
-	if m.GetVips() != "" {
-
-		if l := utf8.RuneCountInString(m.GetVips()); l < 1 || l > 1024 {
-			return CreateSchedulerRequestValidationError{
-				field:  "Vips",
-				reason: "value length must be between 1 and 1024 runes, inclusive",
-			}
-		}
-
-	}
-
-	if m.GetIdc() != "" {
-
-		if l := utf8.RuneCountInString(m.GetIdc()); l < 1 || l > 1024 {
-			return CreateSchedulerRequestValidationError{
-				field:  "Idc",
-				reason: "value length must be between 1 and 1024 runes, inclusive",
-			}
-		}
-
-	}
-
-	if m.GetLocation() != "" {
-
-		if utf8.RuneCountInString(m.GetLocation()) > 1024 {
-			return CreateSchedulerRequestValidationError{
-				field:  "Location",
-				reason: "value length must be at most 1024 runes",
-			}
-		}
-
-	}
-
-	if len(m.GetNetConfig()) > 0 {
-
-		if len(m.GetNetConfig()) < 1 {
-			return CreateSchedulerRequestValidationError{
-				field:  "NetConfig",
-				reason: "value length must be at least 1 bytes",
-			}
-		}
-
-	}
-
-	if ip := net.ParseIP(m.GetIp()); ip == nil {
-		return CreateSchedulerRequestValidationError{
-			field:  "Ip",
-			reason: "value must be a valid IP address",
-		}
-	}
-
-	if val := m.GetPort(); val < 1024 || val >= 65535 {
-		return CreateSchedulerRequestValidationError{
-			field:  "Port",
-			reason: "value must be inside range [1024, 65535)",
-		}
-	}
-
-	return nil
-}
-
-func (m *CreateSchedulerRequest) _validateHostname(host string) error {
-	s := strings.ToLower(strings.TrimSuffix(host, "."))
-
-	if len(host) > 253 {
-		return errors.New("hostname cannot exceed 253 characters")
-	}
-
-	for _, part := range strings.Split(s, ".") {
-		if l := len(part); l == 0 || l > 63 {
-			return errors.New("hostname part must be non-empty and cannot exceed 63 characters")
-		}
-
-		if part[0] == '-' {
-			return errors.New("hostname parts cannot begin with hyphens")
-		}
-
-		if part[len(part)-1] == '-' {
-			return errors.New("hostname parts cannot end with hyphens")
-		}
-
-		for _, r := range part {
-			if (r < 'a' || r > 'z') && (r < '0' || r > '9') && r != '-' {
-				return fmt.Errorf("hostname parts can only contain alphanumeric characters or hyphens, got %q", string(r))
-			}
-		}
-	}
-
-	return nil
-}
-
-// CreateSchedulerRequestValidationError is the validation error returned by
-// CreateSchedulerRequest.Validate if the designated constraints aren't met.
-type CreateSchedulerRequestValidationError struct {
-	field  string
-	reason string
-	cause  error
-	key    bool
-}
-
-// Field function returns field value.
-func (e CreateSchedulerRequestValidationError) Field() string { return e.field }
-
-// Reason function returns reason value.
-func (e CreateSchedulerRequestValidationError) Reason() string { return e.reason }
-
-// Cause function returns cause value.
-func (e CreateSchedulerRequestValidationError) Cause() error { return e.cause }
-
-// Key function returns key value.
-func (e CreateSchedulerRequestValidationError) Key() bool { return e.key }
-
-// ErrorName returns error name.
-func (e CreateSchedulerRequestValidationError) ErrorName() string {
-	return "CreateSchedulerRequestValidationError"
-}
-
-// Error satisfies the builtin error interface
-func (e CreateSchedulerRequestValidationError) Error() string {
-	cause := ""
-	if e.cause != nil {
-		cause = fmt.Sprintf(" | caused by: %v", e.cause)
-	}
-
-	key := ""
-	if e.key {
-		key = "key for "
-	}
-
-	return fmt.Sprintf(
-		"invalid %sCreateSchedulerRequest.%s: %s%s",
-		key,
-		e.field,
-		e.reason,
-		cause)
-}
-
-var _ error = CreateSchedulerRequestValidationError{}
-
-var _ interface {
-	Field() string
-	Reason() string
-	Key() bool
-	Cause() error
-	ErrorName() string
-} = CreateSchedulerRequestValidationError{}
-
 // Validate checks the field values on UpdateSchedulerRequest with the rules
 // defined in the proto definition for this message. If any rules are
 // violated, an error is returned.
@@ -1331,26 +996,18 @@ func (m *UpdateSchedulerRequest) Validate() error {
 
 	}
 
-	if m.GetIp() != "" {
-
-		if ip := net.ParseIP(m.GetIp()); ip == nil {
-			return UpdateSchedulerRequestValidationError{
-				field:  "Ip",
-				reason: "value must be a valid IP address",
-			}
+	if ip := net.ParseIP(m.GetIp()); ip == nil {
+		return UpdateSchedulerRequestValidationError{
+			field:  "Ip",
+			reason: "value must be a valid IP address",
 		}
-
 	}
 
-	if m.GetPort() != 0 {
-
-		if val := m.GetPort(); val < 1024 || val >= 65535 {
-			return UpdateSchedulerRequestValidationError{
-				field:  "Port",
-				reason: "value must be inside range [1024, 65535)",
-			}
+	if val := m.GetPort(); val < 1024 || val >= 65535 {
+		return UpdateSchedulerRequestValidationError{
+			field:  "Port",
+			reason: "value must be inside range [1024, 65535)",
 		}
-
 	}
 
 	return nil
diff --git a/pkg/rpc/manager/manager.proto b/pkg/rpc/manager/manager.proto
index 490f7996..646c0889 100644
--- a/pkg/rpc/manager/manager.proto
+++ b/pkg/rpc/manager/manager.proto
@@ -62,24 +62,14 @@ message GetCDNRequest {
   string host_name = 2 [(validate.rules).string.hostname = true];
 }
 
-message CreateCDNRequest {
-  SourceType source_type = 1 [(validate.rules).enum.defined_only = true];
-  string host_name = 2 [(validate.rules).string.hostname = true];
-  string idc = 4 [(validate.rules).string = {min_len: 1, max_len: 1024, ignore_empty: true}];
-  string location = 5 [(validate.rules).string = {max_len: 1024, ignore_empty: true}];
-  string ip = 6 [(validate.rules).string.ip = true];
-  int32 port = 7 [(validate.rules).int32 = {gte: 1024, lt: 65535}];
-  int32 download_port = 8 [(validate.rules).int32 = {gte: 1024, lt: 65535}];
-}
-
 message UpdateCDNRequest {
   SourceType source_type = 1 [(validate.rules).enum.defined_only = true];
   string host_name = 2 [(validate.rules).string.hostname = true];
   string idc = 3 [(validate.rules).string = {min_len: 1, max_len: 1024, ignore_empty: true}];
   string location = 4 [(validate.rules).string = {max_len: 1024, ignore_empty: true}];
-  string ip = 5 [(validate.rules).string = {ip: true, ignore_empty: true}];
-  int32 port = 6 [(validate.rules).int32 = {gte: 1024, lt: 65535, ignore_empty: true}];
-  int32 download_port = 7 [(validate.rules).int32 = {gte: 1024, lt: 65535, ignore_empty: true}];
+  string ip = 5 [(validate.rules).string = {ip: true}];
+  int32 port = 6 [(validate.rules).int32 = {gte: 1024, lt: 65535}];
+  int32 download_port = 7 [(validate.rules).int32 = {gte: 1024, lt: 65535}];
 }
 
 message AddCDNToCDNClusterRequest {
@@ -116,17 +106,6 @@ message GetSchedulerRequest {
   string host_name = 2 [(validate.rules).string.hostname = true];
 }
 
-message CreateSchedulerRequest {
-  SourceType source_type = 1 [(validate.rules).enum.defined_only = true];
-  string host_name = 2 [(validate.rules).string.hostname = true];
-  string vips = 4 [(validate.rules).string = {min_len: 1, max_len: 1024, ignore_empty: true}];
-  string idc = 5 [(validate.rules).string = {min_len: 1, max_len: 1024, ignore_empty: true}];
-  string location = 6 [(validate.rules).string = {max_len: 1024, ignore_empty: true}];
-  bytes net_config = 7 [(validate.rules).bytes = {min_len: 1, ignore_empty: true}];
-  string ip = 8 [(validate.rules).string.ip = true];
-  int32 port = 9 [(validate.rules).int32 = {gte: 1024, lt: 65535}];
-}
-
 message UpdateSchedulerRequest {
   SourceType source_type = 1 [(validate.rules).enum.defined_only = true];
   string host_name = 2 [(validate.rules).string.hostname = true];
@@ -134,8 +113,8 @@ message UpdateSchedulerRequest {
   string idc = 5 [(validate.rules).string = {min_len: 1, max_len: 1024, ignore_empty: true}];
   string location = 6 [(validate.rules).string = {max_len: 1024, ignore_empty: true}];
   bytes net_config = 7 [(validate.rules).bytes = {min_len: 1, ignore_empty: true}];
-  string ip = 8 [(validate.rules).string = {ip: true, ignore_empty: true}];
-  int32 port = 9 [(validate.rules).int32 = {gte: 1024, lt: 65535, ignore_empty: true}];
+  string ip = 8 [(validate.rules).string = {ip: true}];
+  int32 port = 9 [(validate.rules).int32 = {gte: 1024, lt: 65535}];
 }
 
 message AddSchedulerClusterToSchedulerClusterRequest {
@@ -164,16 +143,12 @@ message KeepAliveRequest {
 service Manager {
   // Get CDN and CDN cluster configuration
   rpc GetCDN(GetCDNRequest) returns(CDN);
-  // Create CDN configuration
-  rpc CreateCDN(CreateCDNRequest) returns(CDN);
   // Update CDN configuration
   rpc UpdateCDN(UpdateCDNRequest) returns(CDN);
   // AddCDNToCDNCluster add cdn to cdn cluster
   rpc AddCDNToCDNCluster(AddCDNToCDNClusterRequest) returns(google.protobuf.Empty);
   // Get Scheduler and Scheduler cluster configuration
   rpc GetScheduler(GetSchedulerRequest)returns(Scheduler);
-  // Create scheduler configuration
-  rpc CreateScheduler(CreateSchedulerRequest) returns(Scheduler);
   // Update scheduler configuration
   rpc UpdateScheduler(UpdateSchedulerRequest) returns(Scheduler);
   // AddSchedulerClusterToSchedulerCluster add scheduler to scheduler cluster
diff --git a/pkg/rpc/manager/manager_grpc.pb.go b/pkg/rpc/manager/manager_grpc.pb.go
index 07794a3b..8400a058 100644
--- a/pkg/rpc/manager/manager_grpc.pb.go
+++ b/pkg/rpc/manager/manager_grpc.pb.go
@@ -12,6 +12,7 @@ import (
 
 // This is a compile-time assertion to ensure that this generated file
 // is compatible with the grpc package it is being compiled against.
+// Requires gRPC-Go v1.32.0 or later.
 const _ = grpc.SupportPackageIsVersion7
 
 // ManagerClient is the client API for Manager service.
@@ -20,16 +21,12 @@ const _ = grpc.SupportPackageIsVersion7
 type ManagerClient interface {
 	// Get CDN and CDN cluster configuration
 	GetCDN(ctx context.Context, in *GetCDNRequest, opts ...grpc.CallOption) (*CDN, error)
-	// Create CDN configuration
-	CreateCDN(ctx context.Context, in *CreateCDNRequest, opts ...grpc.CallOption) (*CDN, error)
 	// Update CDN configuration
 	UpdateCDN(ctx context.Context, in *UpdateCDNRequest, opts ...grpc.CallOption) (*CDN, error)
 	// AddCDNToCDNCluster add cdn to cdn cluster
 	AddCDNToCDNCluster(ctx context.Context, in *AddCDNToCDNClusterRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
 	// Get Scheduler and Scheduler cluster configuration
 	GetScheduler(ctx context.Context, in *GetSchedulerRequest, opts ...grpc.CallOption) (*Scheduler, error)
-	// Create scheduler configuration
-	CreateScheduler(ctx context.Context, in *CreateSchedulerRequest, opts ...grpc.CallOption) (*Scheduler, error)
 	// Update scheduler configuration
 	UpdateScheduler(ctx context.Context, in *UpdateSchedulerRequest, opts ...grpc.CallOption) (*Scheduler, error)
 	// AddSchedulerClusterToSchedulerCluster add scheduler to scheduler cluster
@@ -57,15 +54,6 @@ func (c *managerClient) GetCDN(ctx context.Context, in *GetCDNRequest, opts ...g
 	return out, nil
 }
 
-func (c *managerClient) CreateCDN(ctx context.Context, in *CreateCDNRequest, opts ...grpc.CallOption) (*CDN, error) {
-	out := new(CDN)
-	err := c.cc.Invoke(ctx, "/manager.Manager/CreateCDN", in, out, opts...)
-	if err != nil {
-		return nil, err
-	}
-	return out, nil
-}
-
 func (c *managerClient) UpdateCDN(ctx context.Context, in *UpdateCDNRequest, opts ...grpc.CallOption) (*CDN, error) {
 	out := new(CDN)
 	err := c.cc.Invoke(ctx, "/manager.Manager/UpdateCDN", in, out, opts...)
@@ -93,15 +81,6 @@ func (c *managerClient) GetScheduler(ctx context.Context, in *GetSchedulerReques
 	return out, nil
 }
 
-func (c *managerClient) CreateScheduler(ctx context.Context, in *CreateSchedulerRequest, opts ...grpc.CallOption) (*Scheduler, error) {
-	out := new(Scheduler)
-	err := c.cc.Invoke(ctx, "/manager.Manager/CreateScheduler", in, out, opts...)
-	if err != nil {
-		return nil, err
-	}
-	return out, nil
-}
-
 func (c *managerClient) UpdateScheduler(ctx context.Context, in *UpdateSchedulerRequest, opts ...grpc.CallOption) (*Scheduler, error) {
 	out := new(Scheduler)
 	err := c.cc.Invoke(ctx, "/manager.Manager/UpdateScheduler", in, out, opts...)
@@ -130,7 +109,7 @@ func (c *managerClient) ListSchedulers(ctx context.Context, in *ListSchedulersRe
 }
 
 func (c *managerClient) KeepAlive(ctx context.Context, opts ...grpc.CallOption) (Manager_KeepAliveClient, error) {
-	stream, err := c.cc.NewStream(ctx, &_Manager_serviceDesc.Streams[0], "/manager.Manager/KeepAlive", opts...)
+	stream, err := c.cc.NewStream(ctx, &Manager_ServiceDesc.Streams[0], "/manager.Manager/KeepAlive", opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -169,16 +148,12 @@ func (x *managerKeepAliveClient) CloseAndRecv() (*emptypb.Empty, error) {
 type ManagerServer interface {
 	// Get CDN and CDN cluster configuration
 	GetCDN(context.Context, *GetCDNRequest) (*CDN, error)
-	// Create CDN configuration
-	CreateCDN(context.Context, *CreateCDNRequest) (*CDN, error)
 	// Update CDN configuration
 	UpdateCDN(context.Context, *UpdateCDNRequest) (*CDN, error)
 	// AddCDNToCDNCluster add cdn to cdn cluster
 	AddCDNToCDNCluster(context.Context, *AddCDNToCDNClusterRequest) (*emptypb.Empty, error)
 	// Get Scheduler and Scheduler cluster configuration
 	GetScheduler(context.Context, *GetSchedulerRequest) (*Scheduler, error)
-	// Create scheduler configuration
-	CreateScheduler(context.Context, *CreateSchedulerRequest) (*Scheduler, error)
 	// Update scheduler configuration
 	UpdateScheduler(context.Context, *UpdateSchedulerRequest) (*Scheduler, error)
 	// AddSchedulerClusterToSchedulerCluster add scheduler to scheduler cluster
@@ -197,9 +172,6 @@ type UnimplementedManagerServer struct {
 func (UnimplementedManagerServer) GetCDN(context.Context, *GetCDNRequest) (*CDN, error) {
 	return nil, status.Errorf(codes.Unimplemented, "method GetCDN not implemented")
 }
-func (UnimplementedManagerServer) CreateCDN(context.Context, *CreateCDNRequest) (*CDN, error) {
-	return nil, status.Errorf(codes.Unimplemented, "method CreateCDN not implemented")
-}
 func (UnimplementedManagerServer) UpdateCDN(context.Context, *UpdateCDNRequest) (*CDN, error) {
 	return nil, status.Errorf(codes.Unimplemented, "method UpdateCDN not implemented")
 }
@@ -209,9 +181,6 @@ func (UnimplementedManagerServer) AddCDNToCDNCluster(context.Context, *AddCDNToC
 func (UnimplementedManagerServer) GetScheduler(context.Context, *GetSchedulerRequest) (*Scheduler, error) {
 	return nil, status.Errorf(codes.Unimplemented, "method GetScheduler not implemented")
 }
-func (UnimplementedManagerServer) CreateScheduler(context.Context, *CreateSchedulerRequest) (*Scheduler, error) {
-	return nil, status.Errorf(codes.Unimplemented, "method CreateScheduler not implemented")
-}
 func (UnimplementedManagerServer) UpdateScheduler(context.Context, *UpdateSchedulerRequest) (*Scheduler, error) {
 	return nil, status.Errorf(codes.Unimplemented, "method UpdateScheduler not implemented")
 }
@@ -234,7 +203,7 @@ type UnsafeManagerServer interface {
 }
 
 func RegisterManagerServer(s grpc.ServiceRegistrar, srv ManagerServer) {
-	s.RegisterService(&_Manager_serviceDesc, srv)
+	s.RegisterService(&Manager_ServiceDesc, srv)
 }
 
 func _Manager_GetCDN_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
@@ -255,24 +224,6 @@ func _Manager_GetCDN_Handler(srv interface{}, ctx context.Context, dec func(inte
 	return interceptor(ctx, in, info, handler)
 }
 
-func _Manager_CreateCDN_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
-	in := new(CreateCDNRequest)
-	if err := dec(in); err != nil {
-		return nil, err
-	}
-	if interceptor == nil {
-		return srv.(ManagerServer).CreateCDN(ctx, in)
-	}
-	info := &grpc.UnaryServerInfo{
-		Server:     srv,
-		FullMethod: "/manager.Manager/CreateCDN",
-	}
-	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
-		return srv.(ManagerServer).CreateCDN(ctx, req.(*CreateCDNRequest))
-	}
-	return interceptor(ctx, in, info, handler)
-}
-
 func _Manager_UpdateCDN_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
 	in := new(UpdateCDNRequest)
 	if err := dec(in); err != nil {
@@ -327,24 +278,6 @@ func _Manager_GetScheduler_Handler(srv interface{}, ctx context.Context, dec fun
 	return interceptor(ctx, in, info, handler)
 }
 
-func _Manager_CreateScheduler_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
-	in := new(CreateSchedulerRequest)
-	if err := dec(in); err != nil {
-		return nil, err
-	}
-	if interceptor == nil {
-		return srv.(ManagerServer).CreateScheduler(ctx, in)
-	}
-	info := &grpc.UnaryServerInfo{
-		Server:     srv,
-		FullMethod: "/manager.Manager/CreateScheduler",
-	}
-	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
-		return srv.(ManagerServer).CreateScheduler(ctx, req.(*CreateSchedulerRequest))
-	}
-	return interceptor(ctx, in, info, handler)
-}
-
 func _Manager_UpdateScheduler_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
 	in := new(UpdateSchedulerRequest)
 	if err := dec(in); err != nil {
@@ -425,7 +358,10 @@ func (x *managerKeepAliveServer) Recv() (*KeepAliveRequest, error) {
 	return m, nil
 }
 
-var _Manager_serviceDesc = grpc.ServiceDesc{
+// Manager_ServiceDesc is the grpc.ServiceDesc for Manager service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var Manager_ServiceDesc = grpc.ServiceDesc{
 	ServiceName: "manager.Manager",
 	HandlerType: (*ManagerServer)(nil),
 	Methods: []grpc.MethodDesc{
@@ -433,10 +369,6 @@ var _Manager_serviceDesc = grpc.ServiceDesc{
 			MethodName: "GetCDN",
 			Handler:    _Manager_GetCDN_Handler,
 		},
-		{
-			MethodName: "CreateCDN",
-			Handler:    _Manager_CreateCDN_Handler,
-		},
 		{
 			MethodName: "UpdateCDN",
 			Handler:    _Manager_UpdateCDN_Handler,
@@ -449,10 +381,6 @@ var _Manager_serviceDesc = grpc.ServiceDesc{
 			MethodName: "GetScheduler",
 			Handler:    _Manager_GetScheduler_Handler,
 		},
-		{
-			MethodName: "CreateScheduler",
-			Handler:    _Manager_CreateScheduler_Handler,
-		},
 		{
 			MethodName: "UpdateScheduler",
 			Handler:    _Manager_UpdateScheduler_Handler,
diff --git a/pkg/rpc/scheduler/scheduler_grpc.pb.go b/pkg/rpc/scheduler/scheduler_grpc.pb.go
index 2ac29781..a1b1c414 100644
--- a/pkg/rpc/scheduler/scheduler_grpc.pb.go
+++ b/pkg/rpc/scheduler/scheduler_grpc.pb.go
@@ -12,6 +12,7 @@ import (
 
 // This is a compile-time assertion to ensure that this generated file
 // is compatible with the grpc package it is being compiled against.
+// Requires gRPC-Go v1.32.0 or later.
 const _ = grpc.SupportPackageIsVersion7
 
 // SchedulerClient is the client API for Scheduler service.
@@ -48,7 +49,7 @@ func (c *schedulerClient) RegisterPeerTask(ctx context.Context, in *PeerTaskRequ
 }
 
 func (c *schedulerClient) ReportPieceResult(ctx context.Context, opts ...grpc.CallOption) (Scheduler_ReportPieceResultClient, error) {
-	stream, err := c.cc.NewStream(ctx, &_Scheduler_serviceDesc.Streams[0], "/scheduler.Scheduler/ReportPieceResult", opts...)
+	stream, err := c.cc.NewStream(ctx, &Scheduler_ServiceDesc.Streams[0], "/scheduler.Scheduler/ReportPieceResult", opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -139,7 +140,7 @@ type UnsafeSchedulerServer interface {
 }
 
 func RegisterSchedulerServer(s grpc.ServiceRegistrar, srv SchedulerServer) {
-	s.RegisterService(&_Scheduler_serviceDesc, srv)
+	s.RegisterService(&Scheduler_ServiceDesc, srv)
 }
 
 func _Scheduler_RegisterPeerTask_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
@@ -222,7 +223,10 @@ func _Scheduler_LeaveTask_Handler(srv interface{}, ctx context.Context, dec func
 	return interceptor(ctx, in, info, handler)
 }
 
-var _Scheduler_serviceDesc = grpc.ServiceDesc{
+// Scheduler_ServiceDesc is the grpc.ServiceDesc for Scheduler service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var Scheduler_ServiceDesc = grpc.ServiceDesc{
 	ServiceName: "scheduler.Scheduler",
 	HandlerType: (*SchedulerServer)(nil),
 	Methods: []grpc.MethodDesc{
diff --git a/scheduler/config/mocks/manager_client_mock.go b/scheduler/config/mocks/manager_client_mock.go
index e758621d..2550be5f 100644
--- a/scheduler/config/mocks/manager_client_mock.go
+++ b/scheduler/config/mocks/manager_client_mock.go
@@ -1,5 +1,5 @@
 // Code generated by MockGen. DO NOT EDIT.
-// Source: ../../internal/rpc/manager/manager_grpc.pb.go
+// Source: ../../pkg/rpc/manager/manager_grpc.pb.go
 
 // Package mocks is a generated GoMock package.
 package mocks
@@ -78,46 +78,6 @@ func (mr *MockManagerClientMockRecorder) AddSchedulerClusterToSchedulerCluster(c
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddSchedulerClusterToSchedulerCluster", reflect.TypeOf((*MockManagerClient)(nil).AddSchedulerClusterToSchedulerCluster), varargs...)
 }
 
-// CreateCDN mocks base method.
-func (m *MockManagerClient) CreateCDN(ctx context.Context, in *manager.CreateCDNRequest, opts ...grpc.CallOption) (*manager.CDN, error) {
-	m.ctrl.T.Helper()
-	varargs := []interface{}{ctx, in}
-	for _, a := range opts {
-		varargs = append(varargs, a)
-	}
-	ret := m.ctrl.Call(m, "CreateCDN", varargs...)
-	ret0, _ := ret[0].(*manager.CDN)
-	ret1, _ := ret[1].(error)
-	return ret0, ret1
-}
-
-// CreateCDN indicates an expected call of CreateCDN.
-func (mr *MockManagerClientMockRecorder) CreateCDN(ctx, in interface{}, opts ...interface{}) *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	varargs := append([]interface{}{ctx, in}, opts...)
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateCDN", reflect.TypeOf((*MockManagerClient)(nil).CreateCDN), varargs...)
-}
-
-// CreateScheduler mocks base method.
-func (m *MockManagerClient) CreateScheduler(ctx context.Context, in *manager.CreateSchedulerRequest, opts ...grpc.CallOption) (*manager.Scheduler, error) {
-	m.ctrl.T.Helper()
-	varargs := []interface{}{ctx, in}
-	for _, a := range opts {
-		varargs = append(varargs, a)
-	}
-	ret := m.ctrl.Call(m, "CreateScheduler", varargs...)
-	ret0, _ := ret[0].(*manager.Scheduler)
-	ret1, _ := ret[1].(error)
-	return ret0, ret1
-}
-
-// CreateScheduler indicates an expected call of CreateScheduler.
-func (mr *MockManagerClientMockRecorder) CreateScheduler(ctx, in interface{}, opts ...interface{}) *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	varargs := append([]interface{}{ctx, in}, opts...)
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateScheduler", reflect.TypeOf((*MockManagerClient)(nil).CreateScheduler), varargs...)
-}
-
 // GetCDN mocks base method.
 func (m *MockManagerClient) GetCDN(ctx context.Context, in *manager.GetCDNRequest, opts ...grpc.CallOption) (*manager.CDN, error) {
 	m.ctrl.T.Helper()
@@ -428,36 +388,6 @@ func (mr *MockManagerServerMockRecorder) AddSchedulerClusterToSchedulerCluster(a
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddSchedulerClusterToSchedulerCluster", reflect.TypeOf((*MockManagerServer)(nil).AddSchedulerClusterToSchedulerCluster), arg0, arg1)
 }
 
-// CreateCDN mocks base method.
-func (m *MockManagerServer) CreateCDN(arg0 context.Context, arg1 *manager.CreateCDNRequest) (*manager.CDN, error) {
-	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "CreateCDN", arg0, arg1)
-	ret0, _ := ret[0].(*manager.CDN)
-	ret1, _ := ret[1].(error)
-	return ret0, ret1
-}
-
-// CreateCDN indicates an expected call of CreateCDN.
-func (mr *MockManagerServerMockRecorder) CreateCDN(arg0, arg1 interface{}) *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateCDN", reflect.TypeOf((*MockManagerServer)(nil).CreateCDN), arg0, arg1)
-}
-
-// CreateScheduler mocks base method.
-func (m *MockManagerServer) CreateScheduler(arg0 context.Context, arg1 *manager.CreateSchedulerRequest) (*manager.Scheduler, error) {
-	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "CreateScheduler", arg0, arg1)
-	ret0, _ := ret[0].(*manager.Scheduler)
-	ret1, _ := ret[1].(error)
-	return ret0, ret1
-}
-
-// CreateScheduler indicates an expected call of CreateScheduler.
-func (mr *MockManagerServerMockRecorder) CreateScheduler(arg0, arg1 interface{}) *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateScheduler", reflect.TypeOf((*MockManagerServer)(nil).CreateScheduler), arg0, arg1)
-}
-
 // GetCDN mocks base method.
 func (m *MockManagerServer) GetCDN(arg0 context.Context, arg1 *manager.GetCDNRequest) (*manager.CDN, error) {
 	m.ctrl.T.Helper()
diff --git a/scheduler/server/server.go b/scheduler/server/server.go
index b93aee7d..3144b940 100644
--- a/scheduler/server/server.go
+++ b/scheduler/server/server.go
@@ -175,7 +175,7 @@ func (s *Server) register(ctx context.Context) error {
 
 	var scheduler *manager.Scheduler
 	var err error
-	scheduler, err = s.managerClient.CreateScheduler(ctx, &manager.CreateSchedulerRequest{
+	scheduler, err = s.managerClient.UpdateScheduler(ctx, &manager.UpdateSchedulerRequest{
 		SourceType: manager.SourceType_SCHEDULER_SOURCE,
 		HostName:   iputils.HostName,
 		Ip:         ip,
@@ -184,21 +184,10 @@ func (s *Server) register(ctx context.Context) error {
 		Location:   location,
 	})
 	if err != nil {
-		scheduler, err = s.managerClient.UpdateScheduler(ctx, &manager.UpdateSchedulerRequest{
-			SourceType: manager.SourceType_SCHEDULER_SOURCE,
-			HostName:   iputils.HostName,
-			Ip:         ip,
-			Port:       port,
-			Idc:        idc,
-			Location:   location,
-		})
-		if err != nil {
-			logger.Warnf("update scheduler to manager failed %v", err)
-			return err
-		}
-		logger.Infof("update scheduler %s successfully", scheduler.HostName)
+		logger.Warnf("update scheduler %s to manager failed %v", scheduler.HostName, err)
+		return err
 	}
-	logger.Infof("create scheduler %s successfully", scheduler.HostName)
+	logger.Infof("update scheduler %s to manager successfully", scheduler.HostName)
 
 	schedulerClusterID := s.config.Manager.SchedulerClusterID
 	if schedulerClusterID != 0 {
@@ -206,7 +195,7 @@ func (s *Server) register(ctx context.Context) error {
 			SchedulerId:        scheduler.Id,
 			SchedulerClusterId: schedulerClusterID,
 		}); err != nil {
-			logger.Warnf("add scheduler to scheduler cluster failed %v", err)
+			logger.Warnf("add scheduler %s to scheduler cluster %s failed %v", scheduler.HostName, schedulerClusterID, err)
 			return err
 		}
 		logger.Infof("add scheduler %s to scheduler cluster %s successfully", scheduler.HostName, schedulerClusterID)


Test patch:
diff --git a/hack/install-e2e-test.sh b/hack/install-e2e-test.sh
index 5c958831..36589bdf 100755
--- a/hack/install-e2e-test.sh
+++ b/hack/install-e2e-test.sh
@@ -5,8 +5,12 @@ set -o errexit
 set -o pipefail
 
 KIND_CONFIG_PATH="test/testdata/kind/config.yaml"
-NAMESPACE="dragonfly-system"
+CHARTS_CONFIG_PATH="test/testdata/charts/config.yaml"
+FILE_SERVER_CONFIG_PATH="test/testdata/k8s/file-server.yaml"
 CHARTS_PATH="deploy/charts/dragonfly"
+NAMESPACE="dragonfly-system"
+E2E_NAMESPACE="dragonfly-e2e"
+FILE_SERVER_NAME="file-server-0"
 curDir=$(cd "$(dirname "$0")" && pwd)
 cd "${curDir}/../" || return
 
@@ -29,18 +33,33 @@ install-helm() {
       curl -fsSL https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | sh
   fi
 
-  helm install --wait --timeout 10m --create-namespace --namespace ${NAMESPACE} dragonfly ${CHARTS_PATH}
+  helm install --wait --timeout 10m --create-namespace --namespace ${NAMESPACE} -f ${CHARTS_CONFIG_PATH} dragonfly ${CHARTS_PATH}
+}
+
+install-file-server() {
+  kubectl apply -f ${FILE_SERVER_CONFIG_PATH}
+  kubectl wait --namespace ${E2E_NAMESPACE} \
+  --for=condition=ready pod ${FILE_SERVER_NAME} \
+  --timeout=10m
 }
 
 install-ginkgo() {
   if which ginkgo >/dev/null ; then
       print_step_info "ginkgo has been installed"
   else
-      print_step_info "start install ginkgo"
       go get github.com/onsi/ginkgo/ginkgo
   fi
 }
 
+install-apache-bench() {
+  if which ab >/dev/null ; then
+      print_step_info "apache bench has been installed"
+  else
+      apt-get update
+      apt-get install apache2-utils
+  fi
+}
+
 install-local() {
   print_step_info "start kind create cluster"
   install-kind
@@ -54,8 +73,14 @@ install-local() {
   print_step_info "start helm install dragonfly"
   install-helm
 
-  print_step_info "start ginkgo install dragonfly"
+  print_step_info "start install file server"
+  install-file-server
+
+  print_step_info "start install ginkgo"
   install-ginkgo
+
+  print_step_info "start install apache bench"
+  install-apache-bench
 }
 
 install-actions() {
@@ -68,8 +93,14 @@ install-actions() {
   print_step_info "start helm install dragonfly"
   install-helm
 
-  print_step_info "start ginkgo install dragonfly"
+  print_step_info "start install file server"
+  install-file-server
+
+  print_step_info "start install ginkgo"
   install-ginkgo
+
+  print_step_info "start install apache bench"
+  install-apache-bench
 }
 
 print_step_info() {
diff --git a/test/e2e/concurrency_test.go b/test/e2e/concurrency_test.go
new file mode 100644
index 00000000..33c87c21
--- /dev/null
+++ b/test/e2e/concurrency_test.go
@@ -0,0 +1,70 @@
+/*
+ *     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 e2e
+
+import (
+	"fmt"
+
+	"d7y.io/dragonfly/v2/test/e2e/e2eutil"
+	. "github.com/onsi/ginkgo" //nolint
+	. "github.com/onsi/gomega" //nolint
+)
+
+const (
+	hostnameFilePath = "/etc/hostname"
+	proxy            = "localhost:65001"
+)
+
+var _ = Describe("Download concurrency", func() {
+	Context("ab", func() {
+		It("concurrent 100 should be ok", func() {
+			url := e2eutil.GetFileURL(hostnameFilePath)
+			fmt.Println("download url " + url)
+
+			out, err := e2eutil.ABCommand("-c", "100", "-n", "200", "-X", proxy, url).CombinedOutput()
+			fmt.Println(string(out))
+			Expect(err).NotTo(HaveOccurred())
+		})
+
+		It("concurrent 200 should be ok", func() {
+			url := e2eutil.GetFileURL(hostnameFilePath)
+			fmt.Println("download url " + url)
+
+			out, err := e2eutil.ABCommand("-c", "200", "-n", "400", "-X", proxy, url).CombinedOutput()
+			fmt.Println(string(out))
+			Expect(err).NotTo(HaveOccurred())
+		})
+
+		It("concurrent 500 should be ok", func() {
+			url := e2eutil.GetFileURL(hostnameFilePath)
+			fmt.Println("download url " + url)
+
+			out, err := e2eutil.ABCommand("-c", "500", "-n", "1000", "-X", proxy, url).CombinedOutput()
+			fmt.Println(string(out))
+			Expect(err).NotTo(HaveOccurred())
+		})
+
+		It("concurrent 1000 should be ok", func() {
+			url := e2eutil.GetFileURL(hostnameFilePath)
+			fmt.Println("download url " + url)
+
+			out, err := e2eutil.ABCommand("-c", "1000", "-n", "2000", "-X", proxy, url).CombinedOutput()
+			fmt.Println(string(out))
+			Expect(err).NotTo(HaveOccurred())
+		})
+	})
+})
diff --git a/test/e2e/dfget_test.go b/test/e2e/dfget_test.go
index c904043b..c1add543 100644
--- a/test/e2e/dfget_test.go
+++ b/test/e2e/dfget_test.go
@@ -26,25 +26,11 @@ import (
 )
 
 const (
-	dragonflyNamespace    = "dragonfly-system"
-	dragonflyE2ENamespace = "dragonfly-e2e"
+	dragonflyNamespace = "dragonfly-system"
 )
 
 var _ = Describe("Download with dfget", func() {
 	Context("dfget", func() {
-		It("setup file server should be ok", func() {
-			// create file server
-			out, err := e2eutil.KubeCtlCommand("apply", "-f", "../testdata/k8s/file-server.yaml").CombinedOutput()
-			Expect(err).NotTo(HaveOccurred())
-			fmt.Println(string(out))
-
-			// wait file server ready
-			out, err = e2eutil.KubeCtlCommand("-n", dragonflyE2ENamespace,
-				"wait", "--for=condition=ready", "--timeout=5m", "pod", "file-server-0").CombinedOutput()
-			Expect(err).NotTo(HaveOccurred())
-			fmt.Println(string(out))
-		})
-
 		It("dfget download should be ok", func() {
 			out, err := e2eutil.KubeCtlCommand("-n", dragonflyNamespace, "get", "pod", "-l", "component=dfdaemon",
 				"-o", "jsonpath='{range .items[*]}{.metadata.name}{end}'").CombinedOutput()
@@ -54,28 +40,12 @@ var _ = Describe("Download with dfget", func() {
 			Expect(strings.HasPrefix(podName, "dragonfly-dfdaemon-")).Should(BeTrue())
 			pod := e2eutil.NewPodExec(dragonflyNamespace, podName)
 
-			files := []string{
-				"/etc/containerd/config.toml",
-				"/etc/fstab",
-				"/etc/hostname",
-				"/usr/bin/kubectl",
-				"/usr/bin/systemctl",
-				"/usr/local/bin/containerd-shim",
-				"/usr/local/bin/clean-install",
-				"/usr/local/bin/entrypoint",
-				"/usr/local/bin/containerd-shim-runc-v2",
-				"/usr/local/bin/ctr",
-				"/usr/local/bin/containerd",
-				"/usr/local/bin/create-kubelet-cgroup-v2",
-				"/usr/local/bin/crictl",
-				"/usr/local/bin/containerd-fuse-overlayfs-grpc",
-			}
-			for i := range files {
-				url := fmt.Sprintf("http://file-server.dragonfly-e2e.svc/kind%s", files[i])
+			for _, v := range e2eutil.GetFileList() {
+				url := e2eutil.GetFileURL(v)
 				fmt.Println("download url " + url)
 
 				// get original file digest
-				out, err = e2eutil.DockerCommand("sha256sum", files[i]).CombinedOutput()
+				out, err = e2eutil.DockerCommand("sha256sum", v).CombinedOutput()
 				fmt.Println(string(out))
 				Expect(err).NotTo(HaveOccurred())
 				sha256sum1 := strings.Split(string(out), " ")[0]
diff --git a/test/e2e/e2eutil/exec.go b/test/e2e/e2eutil/exec.go
index 486dea4a..51085bca 100644
--- a/test/e2e/e2eutil/exec.go
+++ b/test/e2e/e2eutil/exec.go
@@ -1,6 +1,8 @@
 package e2eutil
 
-import "os/exec"
+import (
+	"os/exec"
+)
 
 const (
 	kindDockerContainer = "kind-control-plane"
@@ -22,6 +24,10 @@ func KubeCtlCommand(arg ...string) *exec.Cmd {
 	return exec.Command("kubectl", arg...)
 }
 
+func ABCommand(arg ...string) *exec.Cmd {
+	return exec.Command("ab", arg...)
+}
+
 type PodExec struct {
 	namespace string
 	name      string
diff --git a/test/e2e/e2eutil/file_server.go b/test/e2e/e2eutil/file_server.go
new file mode 100644
index 00000000..c5aed60e
--- /dev/null
+++ b/test/e2e/e2eutil/file_server.go
@@ -0,0 +1,26 @@
+package e2eutil
+
+import "fmt"
+
+func GetFileList() []string {
+	return []string{
+		"/etc/containerd/config.toml",
+		"/etc/fstab",
+		"/etc/hostname",
+		"/usr/bin/kubectl",
+		"/usr/bin/systemctl",
+		"/usr/local/bin/containerd-shim",
+		"/usr/local/bin/clean-install",
+		"/usr/local/bin/entrypoint",
+		"/usr/local/bin/containerd-shim-runc-v2",
+		"/usr/local/bin/ctr",
+		"/usr/local/bin/containerd",
+		"/usr/local/bin/create-kubelet-cgroup-v2",
+		"/usr/local/bin/crictl",
+	}
+}
+
+func GetFileURL(filePath string) string {
+	baseURL := "http://file-server.dragonfly-e2e.svc/kind"
+	return fmt.Sprintf("%s%s", baseURL, filePath)
+}
diff --git a/test/testdata/charts/config.yaml b/test/testdata/charts/config.yaml
new file mode 100644
index 00000000..07c0645d
--- /dev/null
+++ b/test/testdata/charts/config.yaml
@@ -0,0 +1,187 @@
+nameOverride: ""
+namespaceOverride: "dragonfly-system"
+fullnameOverride: ""
+
+# values for dragonfly installation
+installation:
+  clusterDomain: ""
+  # enable an all in one jaeger for tracing every downloading event
+  # should not use in production environment
+  jaeger: false
+
+scheduler:
+  name: scheduler
+  nameOverride: ""
+  fullnameOverride: ""
+  replicas: 3
+  image: dragonflyoss/scheduler
+  tag: v0.1.0-beta
+  pullPolicy: IfNotPresent
+  resources:
+    requests:
+      cpu: "0"
+      memory: "0"
+    limits:
+      cpu: "4"
+      memory: "8Gi"
+  priorityClassName: ""
+  nodeSelector: {}
+  terminationGracePeriodSeconds:
+  tolerations: []
+  podAnnotations: {}
+  podLabels: {}
+  serviceAnnotations: {}
+  statefulsetAnnotations: {}
+  containerPort: 8002
+  service:
+    type: ClusterIP
+    annotations: {}
+    port: 8002
+    targetPort: 8002
+  config:
+    # when there is no manager component in or out of cluster, enable staticCDN
+    # cdn will auto register in configmap, and scheduler will discover all of them dynamic.
+    staticCDN: true
+    debug: false
+    worker:
+      workerNum: 4
+      workerJobPoolSize: 10000
+      senderNum: 10
+      senderJobPoolSize: 10000
+
+cdn:
+  name: cdn
+  nameOverride: ""
+  fullnameOverride: ""
+  replicas: 3
+  image: dragonflyoss/cdn
+  tag: v0.1.0-beta
+  kubectlImage: bitnami/kubectl
+  pullPolicy: Always
+  resources:
+    requests:
+      cpu: "0"
+      memory: "0"
+    limits:
+      cpu: "4"
+      memory: "8Gi"
+  priorityClassName: ""
+  nodeSelector: {}
+  terminationGracePeriodSeconds:
+  tolerations: []
+  podAnnotations: {}
+  podLabels: {}
+  statefulsetAnnotations: {}
+  containerPort: 8003
+  nginxContiainerPort: 8001
+  config:
+    base:
+      systemReservedBandwidth: 20M
+      maxBandwidth: 200M
+      enableProfiler: false
+      failAccessInterval: 3m
+      gcInitialDelay: 6s
+      gcMetaInterval: 2m
+      gcStorageInterval: 15s
+      taskExpireTime: 3m
+      storagePattern: disk
+      console: false
+    plugins:
+      storageDriver:
+        - name: disk
+          enable: true
+          config:
+            baseDir: /tmp/cdn
+      storageManager:
+        - name: disk
+          enable: true
+          config:
+            gcInitialDelay: 5s
+            gcInterval: 15s
+            driverConfigs:
+              disk:
+                gcConfig:
+                  youngGCThreshold: 100G
+                  fullGCThreshold: 5G
+                  cleanRatio: 1
+                  intervalThreshold: 2h
+
+dfdaemon:
+  name: dfdaemon
+  nameOverride: ""
+  fullnameOverride: ""
+  image: dragonflyoss/dfdaemon
+  tag: v0.1.0-beta
+  pullPolicy: IfNotPresent
+  resources:
+    requests:
+      cpu: "0"
+      memory: "0"
+    limits:
+      cpu: "2"
+      memory: "2Gi"
+  priorityClassName: ""
+  nodeSelector: {}
+  terminationGracePeriodSeconds:
+  tolerations: []
+  podAnnotations: {}
+  podLabels: {}
+  daemonsetAnnotations: {}
+  containerPort: 65001
+  # hostPort is used when .hostNetwork == false, and .config.proxy.tcpListen.namespace is empty
+  # many network add-ons do not yet support hostPort
+  # https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/troubleshooting-kubeadm/#hostport-services-do-not-work
+  # by default, dfdaemon injects the 65001 port to host network by sharing host network namespace,
+  # if you want to use hostPort, please empty .config.proxy.tcpListen.namespace below, and keep .hostNetwork == false
+  # for performance, injecting the 65001 port to host network is better than hostPort
+  hostPort: 65001
+  # using hostNetwork when pod with host network can communicate with normal pods with cni network
+  hostNetwork: false
+  config:
+    aliveTime: 0s
+    gcInterval: 1m0s
+    keepStorage: false
+    verbose: true
+    jaeger: "" # customize jaeger like: http://localhost:14268/api/traces
+    host:
+      listenIP: 0.0.0.0
+      advertiseIP: 0.0.0.0
+    download:
+      rateLimit: 200Mi
+      downloadGRPC:
+        security:
+          insecure: true
+        unixListen:
+          socket: /tmp/dfdamon.sock
+      peerGRPC:
+        security:
+          insecure: true
+        tcpListen:
+          listen: 0.0.0.0
+          port: 65000
+    upload:
+      rateLimit: 100Mi
+      security:
+        insecure: true
+      tcpListen:
+        listen: 0.0.0.0
+        port: 65002
+    storage:
+      taskExpireTime: 3m0s
+      strategy: io.d7y.storage.v2.simple
+      multiplex: true
+    proxy:
+      defaultFilter: "Expires&Signature"
+      security:
+        insecure: true
+      tcpListen:
+        namespace: /run/dragonfly/net
+        listen: 0.0.0.0
+        # if you want to change port, please update hostPort in $.Values.dfdaemon.hostPort
+        # port in configmap is generated from $.Values.dfdaemon.hostPort
+        # port: 65001
+      registryMirror:
+        url: https://index.docker.io
+      proxies:
+        - regx: blobs/sha256.*
+        - regx: file-server
diff --git a/test/testdata/k8s/file-server.yaml b/test/testdata/k8s/file-server.yaml
index 290266a4..5b5a487e 100644
--- a/test/testdata/k8s/file-server.yaml
+++ b/test/testdata/k8s/file-server.yaml
@@ -4,7 +4,6 @@ metadata:
   name: dragonfly-e2e
 
 ---
-
 apiVersion: v1
 kind: Service
 metadata:
@@ -22,7 +21,6 @@ spec:
     targetPort: 80
 
 ---
-
 apiVersion: apps/v1
 kind: StatefulSet
 metadata:
@@ -43,7 +41,7 @@ spec:
     spec:
       containers:
       - name: nginx
-        image: nginx:1.20.1-alpine
+        image: d7y.io/library/nginx:1.21.1-alpine
         imagePullPolicy: "IfNotPresent"
         ports:
         - containerPort: 80
@@ -53,4 +51,4 @@ spec:
       volumes:
       - name: files
         hostPath:
-          path: /
\ No newline at end of file
+          path: /