github.com/noironetworks/cilium-net@v1.6.12/cilium-health/launch/launcher.go (about) 1 // Copyright 2017-2019 Authors of Cilium 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package launch 16 17 import ( 18 "fmt" 19 "os" 20 "time" 21 22 "github.com/cilium/cilium/api/v1/models" 23 "github.com/cilium/cilium/pkg/api" 24 ciliumPkg "github.com/cilium/cilium/pkg/client" 25 "github.com/cilium/cilium/pkg/health/client" 26 "github.com/cilium/cilium/pkg/health/defaults" 27 "github.com/cilium/cilium/pkg/health/server" 28 "github.com/cilium/cilium/pkg/lock" 29 "github.com/cilium/cilium/pkg/logging" 30 "github.com/cilium/cilium/pkg/logging/logfields" 31 "github.com/cilium/cilium/pkg/option" 32 ) 33 34 // CiliumHealth launches and polls the cilium-health daemon 35 type CiliumHealth struct { 36 mutex lock.RWMutex 37 server *server.Server 38 client *client.Client 39 status *models.Status 40 } 41 42 var ( 43 log = logging.DefaultLogger.WithField(logfields.LogSubsys, "cilium-health-launcher") 44 45 serverProbeInterval = 60 * time.Second 46 serverProbeDeadline = 1 * time.Second 47 connectRetryInterval = 1 * time.Second 48 statusProbeInterval = 5 * time.Second 49 ) 50 51 // Launch starts the cilium-health server and returns a handle to obtain its status 52 func Launch() (*CiliumHealth, error) { 53 var ( 54 err error 55 ch = &CiliumHealth{} 56 ) 57 58 config := server.Config{ 59 Debug: option.Config.Opts.IsEnabled(option.Debug), 60 ProbeInterval: serverProbeInterval, 61 ProbeDeadline: serverProbeDeadline, 62 } 63 64 ch.server, err = server.NewServer(config) 65 if err != nil { 66 return nil, fmt.Errorf("failed to instantiate cilium-health server: %s", err) 67 } 68 69 ch.client, err = client.NewDefaultClient() 70 if err != nil { 71 return nil, fmt.Errorf("failed to instantiate cilium-health client: %s", err) 72 } 73 74 go ch.runServer() 75 76 return ch, nil 77 } 78 79 func (ch *CiliumHealth) runServer() { 80 // Wait until Cilium API is available 81 for { 82 cli, err := ciliumPkg.NewDefaultClient() 83 if err == nil { 84 // Making sure that we can talk with the daemon. 85 if _, err = cli.Daemon.GetHealthz(nil); err == nil { 86 break 87 } 88 } 89 log.WithError(err).Debugf("Cannot establish connection to local cilium instance") 90 time.Sleep(connectRetryInterval) 91 } 92 93 // Launch cilium-health API server 94 os.Remove(defaults.SockPath) 95 go func() { 96 defer ch.server.Shutdown() 97 if err := ch.server.Serve(); err != nil { 98 log.WithError(err).Error("Failed to serve cilium-health API") 99 } 100 }() 101 102 // When the unix socket is made available, set its permissions. 103 scopedLog := log.WithField(logfields.Path, defaults.SockPath) 104 for { 105 _, err := os.Stat(defaults.SockPath) 106 if err == nil { 107 break 108 } 109 scopedLog.WithError(err).Debugf("Cannot find socket") 110 time.Sleep(1 * time.Second) 111 } 112 if err := api.SetDefaultPermissions(defaults.SockPath); err != nil { 113 scopedLog.WithError(err).Fatal("Cannot set default permissions on socket") 114 } 115 116 // Periodically fetch status from cilium-health server 117 for { 118 status := &models.Status{ 119 State: models.StatusStateOk, 120 } 121 122 _, err := ch.client.Restapi.GetHealthz(nil) 123 if err != nil { 124 status.Msg = err.Error() 125 status.State = models.StatusStateWarning 126 } 127 128 ch.setStatus(status) 129 time.Sleep(statusProbeInterval) 130 } 131 } 132 133 // GetStatus returns the status of the cilium-health daemon. 134 func (ch *CiliumHealth) GetStatus() *models.Status { 135 ch.mutex.RLock() 136 status := ch.status 137 ch.mutex.RUnlock() 138 return status 139 } 140 141 // setStatus updates the status of the cilium-health daemon. 142 func (ch *CiliumHealth) setStatus(status *models.Status) { 143 ch.mutex.Lock() 144 ch.status = status 145 ch.mutex.Unlock() 146 }