github.com/jingruilea/kubeedge@v1.2.0-beta.0.0.20200410162146-4bb8902b3879/cloud/pkg/csidriver/utils.go (about) 1 /* 2 Copyright 2019 The KubeEdge Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package csidriver 18 19 import ( 20 "encoding/json" 21 "errors" 22 "fmt" 23 "net" 24 "os" 25 "strings" 26 "sync" 27 28 "github.com/container-storage-interface/spec/lib/go/csi" 29 "github.com/kubernetes-csi/csi-lib-utils/protosanitizer" 30 "golang.org/x/net/context" 31 "google.golang.org/grpc" 32 "k8s.io/klog" 33 34 "github.com/kubeedge/beehive/pkg/core/model" 35 "github.com/kubeedge/kubeedge/common/constants" 36 ) 37 38 // Constant defines csi related parameters 39 const ( 40 GroupResource = "resource" 41 DefaultNamespace = "default" 42 DefaultReceiveModuleName = "cloudhub" 43 ) 44 45 // newNonBlockingGRPCServer creates a new nonblocking server 46 func newNonBlockingGRPCServer() *nonBlockingGRPCServer { 47 return &nonBlockingGRPCServer{} 48 } 49 50 // NonBlocking server 51 type nonBlockingGRPCServer struct { 52 wg sync.WaitGroup 53 server *grpc.Server 54 } 55 56 func (s *nonBlockingGRPCServer) Start(endpoint string, ids csi.IdentityServer, cs csi.ControllerServer, ns csi.NodeServer) { 57 s.wg.Add(1) 58 go func() { 59 defer s.wg.Done() 60 err := s.serve(endpoint, ids, cs, ns) 61 if err != nil { 62 panic(err.Error()) 63 } 64 }() 65 } 66 67 func (s *nonBlockingGRPCServer) Wait() { 68 s.wg.Wait() 69 } 70 71 func (s *nonBlockingGRPCServer) Stop() { 72 s.server.GracefulStop() 73 } 74 75 func (s *nonBlockingGRPCServer) ForceStop() { 76 s.server.Stop() 77 } 78 79 func (s *nonBlockingGRPCServer) serve(endpoint string, ids csi.IdentityServer, cs csi.ControllerServer, ns csi.NodeServer) error { 80 81 proto, addr, err := parseEndpoint(endpoint) 82 if err != nil { 83 klog.Errorf(err.Error()) 84 return err 85 } 86 87 if proto == "unix" { 88 addr = "/" + addr 89 if err := os.Remove(addr); err != nil && !os.IsNotExist(err) { 90 klog.Warningf("failed to remove %s, error: %s", addr, err.Error()) 91 } 92 } 93 94 listener, err := net.Listen(proto, addr) 95 if err != nil { 96 klog.Errorf("failed to listen: %v", err) 97 return err 98 } 99 100 opts := []grpc.ServerOption{ 101 grpc.UnaryInterceptor(logGRPC), 102 } 103 server := grpc.NewServer(opts...) 104 s.server = server 105 106 if ids != nil { 107 csi.RegisterIdentityServer(server, ids) 108 } 109 if cs != nil { 110 csi.RegisterControllerServer(server, cs) 111 } 112 if ns != nil { 113 csi.RegisterNodeServer(server, ns) 114 } 115 klog.Infof("listening for connections on address: %#v", listener.Addr()) 116 return server.Serve(listener) 117 } 118 119 func parseEndpoint(ep string) (string, string, error) { 120 if strings.HasPrefix(strings.ToLower(ep), "unix://") || strings.HasPrefix(strings.ToLower(ep), "tcp://") { 121 s := strings.SplitN(ep, "://", 2) 122 if s[1] != "" { 123 return s[0], s[1], nil 124 } 125 } 126 return "", "", fmt.Errorf("invalid endpoint: %v", ep) 127 } 128 129 func logGRPC(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { 130 klog.Infof("gprc call: %s", info.FullMethod) 131 klog.Infof("gprc request: %+v", protosanitizer.StripSecrets(req)) 132 resp, err := handler(ctx, req) 133 if err != nil { 134 klog.Errorf("gprc error: %v", err) 135 } else { 136 klog.Infof("gprc response: %+v", protosanitizer.StripSecrets(resp)) 137 } 138 return resp, err 139 } 140 141 // buildResource return a string as "beehive/pkg/core/model".Message.Router.Resource 142 func buildResource(nodeID, namespace, resourceType, resourceID string) (string, error) { 143 if nodeID == "" || namespace == "" || resourceType == "" { 144 return "", fmt.Errorf("required parameter are not set (node id, namespace or resource type)") 145 } 146 resource := fmt.Sprintf("%s%s%s%s%s%s%s", "node", constants.ResourceSep, nodeID, constants.ResourceSep, namespace, constants.ResourceSep, resourceType) 147 if resourceID != "" { 148 resource += fmt.Sprintf("%s%s", constants.ResourceSep, resourceID) 149 } 150 return resource, nil 151 } 152 153 // sendToKubeEdge sends messages to KubeEdge 154 func sendToKubeEdge(context, kubeEdgeEndpoint string) (string, error) { 155 us := NewUnixDomainSocket(kubeEdgeEndpoint) 156 // connect 157 r, err := us.Connect() 158 if err != nil { 159 return "", err 160 } 161 // send 162 res, err := us.Send(r, context) 163 if err != nil { 164 return "", err 165 } 166 return res, nil 167 } 168 169 // extractMessage extracts message 170 func extractMessage(context string) (*model.Message, error) { 171 var msg *model.Message 172 if context != "" { 173 err := json.Unmarshal([]byte(context), &msg) 174 if err != nil { 175 return nil, err 176 } 177 } else { 178 err := errors.New("failed to extract message with empty context") 179 klog.Errorf("%v", err) 180 return nil, err 181 } 182 return msg, nil 183 }