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  }