github.com/Mirantis/virtlet@v1.5.2-0.20191204181327-1659b8a48e9b/pkg/manager/grpc.go (about) 1 /* 2 Copyright 2018 Mirantis 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 manager 18 19 import ( 20 "net" 21 "os" 22 "strings" 23 "syscall" 24 25 "github.com/ghodss/yaml" 26 "github.com/golang/glog" 27 "golang.org/x/net/context" 28 "google.golang.org/grpc" 29 kubeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" 30 ) 31 32 const ( 33 criErrorLogLevel = 2 34 criRequestLogLevel = 3 35 criNoisyLogLevel = 4 36 criListLogLevel = 5 37 ) 38 39 // Server wraps a gRPC server and provides listener setup and request 40 // logging. 41 type Server struct { 42 server *grpc.Server 43 } 44 45 // NewServer creates a new Server. 46 func NewServer() *Server { 47 return &Server{ 48 server: grpc.NewServer(grpc.UnaryInterceptor(func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { 49 return intercept(ctx, req, info, handler) 50 })), 51 } 52 } 53 54 // Serve set up a listener on unix socket, than it passes that listener to 55 // main loop of grpc server which handles CRI calls. 56 func (s *Server) Serve(addr string) error { 57 if err := syscall.Unlink(addr); err != nil && !os.IsNotExist(err) { 58 return err 59 } 60 ln, err := net.Listen("unix", addr) 61 if err != nil { 62 return err 63 } 64 defer ln.Close() 65 return s.server.Serve(ln) 66 } 67 68 // Stop halts the manager. 69 func (s *Server) Stop() { 70 s.server.Stop() 71 } 72 73 // Register registers CRI Runtime and Image services 74 func (s *Server) Register(runtimeService kubeapi.RuntimeServiceServer, imageService kubeapi.ImageServiceServer) { 75 kubeapi.RegisterRuntimeServiceServer(s.server, runtimeService) 76 kubeapi.RegisterImageServiceServer(s.server, imageService) 77 } 78 79 func logLevelForMethod(fullMethod string) glog.Level { 80 idx := strings.LastIndex(fullMethod, "/") 81 if idx < 0 { 82 return criNoisyLogLevel 83 } 84 methodName := fullMethod[idx+1:] 85 switch { 86 case strings.Contains(methodName, "Status"): 87 return criNoisyLogLevel 88 case strings.Contains(methodName, "Version"): 89 return criNoisyLogLevel 90 case strings.Contains(methodName, "List"): 91 return criListLogLevel 92 case methodName == "ImageFsInfo": 93 return criListLogLevel 94 default: 95 return criRequestLogLevel 96 } 97 } 98 99 func dump(v interface{}) string { 100 out, err := yaml.Marshal(v) 101 if err != nil { 102 return "<marshalling error>" 103 } 104 return string(out) 105 } 106 107 func intercept(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { 108 logLevel := logLevelForMethod(info.FullMethod) 109 if glog.V(logLevel) { 110 glog.Infof("ENTER: %s():\n%s", info.FullMethod, dump(req)) 111 } 112 resp, err := handler(ctx, req) 113 switch { 114 case err != nil && !bool(glog.V(criErrorLogLevel)): 115 // do nothing 116 case err != nil: 117 glog.Errorf("FAIL: %s(): %v", info.FullMethod, err) 118 case bool(glog.V(logLevel)): 119 glog.Infof("LEAVE: %s()\n%s", info.FullMethod, dump(resp)) 120 } 121 return resp, err 122 }