...

Source file src/golang.conradwood.net/go-easyops/server/ipc.go

Documentation: golang.conradwood.net/go-easyops/server

     1  package server
     2  
     3  import (
     4  	"flag"
     5  	"fmt"
     6  	"golang.conradwood.net/apis/common"
     7  	"golang.conradwood.net/apis/goeasyops"
     8  	"golang.conradwood.net/go-easyops/cmdline"
     9  	"golang.conradwood.net/go-easyops/utils"
    10  	ad "golang.yacloud.eu/apis/autodeployer2"
    11  	"golang.yacloud.eu/unixipc"
    12  	"strconv"
    13  	"sync"
    14  )
    15  
    16  var (
    17  	enable_ipc   = flag.Bool("ge_enable_ipc", true, "enable the internal ipc between code and autodeployer")
    18  	ipc_fd_env   = cmdline.ENV("GE_AUTODEPLOYER_IPC_FD", "if set it is assumed to be a filedescriptor over which an IPC can be initiated with the autodeployer")
    19  	ipc_lock     sync.Mutex
    20  	ipc_started  = false
    21  	ipc_fd_found = false
    22  	ipc_ready    = false
    23  	unixipc_srv  *unixipc.IPCServer
    24  )
    25  
    26  func ipc_enabled() bool {
    27  	if *enable_ipc {
    28  		return true
    29  	}
    30  	return false
    31  }
    32  
    33  func start_ipc() {
    34  	if !ipc_enabled() {
    35  		return
    36  	}
    37  	ipc_lock.Lock()
    38  	defer ipc_lock.Unlock()
    39  	if ipc_started {
    40  		return
    41  	}
    42  	ipc_started = true
    43  	if ipc_fd_env.Value() == "" {
    44  		ipc_fd_found = false
    45  		fmt.Printf("[go-easyops] no ipc fd\n")
    46  		return
    47  	}
    48  	ipc_fd_found = true
    49  	fd, err := strconv.Atoi(ipc_fd_env.Value())
    50  	if err != nil {
    51  		panic(fmt.Sprintf("GE_AUTODEPLOYER_IPC_FD invalid value: %s", err))
    52  	}
    53  	unixipc_srv, err = unixipc.NewConnectedServer(fd)
    54  	if err != nil {
    55  		panic(fmt.Sprintf("failed to start autodeployer IPC: %s", err))
    56  	}
    57  	unixipc_srv.Name = "goeasyops"
    58  	unixipc_srv.RegisterRequestHandler(ipc_new_packet)
    59  	ipc_ready = true
    60  }
    61  
    62  // packet from server received
    63  func ipc_new_packet(req unixipc.Request) ([]byte, error) {
    64  	if req.RPCName() == "STOPREQUEST" {
    65  		stop_requested()
    66  		response := &goeasyops.StopUpdate{Stopping: true, ActiveRPCs: uint32(ActiveRPCs())}
    67  		b, err := utils.MarshalBytes(response)
    68  		if err != nil {
    69  			return nil, err
    70  		}
    71  		return b, nil
    72  	}
    73  	return nil, fmt.Errorf("[go-easyops] unipc client does not implement rpc call \"%s\"", req.RPCName())
    74  }
    75  func ipc_send_startup(sd *serverDef) error {
    76  	start_ipc()
    77  
    78  	if !ipc_ready {
    79  		fmt.Printf("[go-easyops] attempted to send ipc whilst it was not ready yet\n")
    80  		return nil
    81  	}
    82  	proto_payload := &ad.INTRPCStartup{
    83  		ServiceName: sd.name,
    84  		Port:        uint32(sd.port),
    85  		Healthz:     health,
    86  	}
    87  	payload, err := utils.MarshalBytes(proto_payload)
    88  	if err != nil {
    89  		return err
    90  	}
    91  	_, err = unixipc_srv.Send("startup", payload)
    92  	if err != nil {
    93  		return err
    94  	}
    95  	return nil
    96  }
    97  func ipc_send_new_para(sd *serverDef, name, value string) error {
    98  	start_ipc()
    99  	if !ipc_ready {
   100  		fmt.Printf("[go-easyops] no unixipc to report new flag %s=%s to\n", name, value)
   101  		return nil
   102  	}
   103  	if sd == nil {
   104  		sd = &serverDef{name: "", port: 0} // default to use if no service def set
   105  	}
   106  	proto_payload := &ad.INTRPCFlagChange{
   107  		ServiceName: sd.name,
   108  		FlagName:    name,
   109  		NewValue:    value,
   110  	}
   111  	payload, err := utils.MarshalBytes(proto_payload)
   112  	if err != nil {
   113  		return err
   114  	}
   115  	_, err = unixipc_srv.Send("flagchange", payload)
   116  	if err != nil {
   117  		return err
   118  	}
   119  	return nil
   120  }
   121  func ipc_send_health(sd *serverDef, h common.Health) error {
   122  	start_ipc()
   123  	if !ipc_ready {
   124  		fmt.Printf("[go-easyops] no unixipc to report new health %v to\n", h)
   125  		return nil
   126  	}
   127  	if sd == nil {
   128  		sd = &serverDef{name: "", port: 0} // default to use if no service def set
   129  	}
   130  	proto_payload := &ad.INTRPCHealthz{
   131  		ServiceName: sd.name,
   132  		Port:        uint32(sd.port),
   133  		Healthz:     h,
   134  	}
   135  	payload, err := utils.MarshalBytes(proto_payload)
   136  	if err != nil {
   137  		return err
   138  	}
   139  	_, err = unixipc_srv.Send("healthz", payload)
   140  	if err != nil {
   141  		return err
   142  	}
   143  	return nil
   144  }
   145  

View as plain text