blob: 12c75ad2fed01134f6d5eca95b76ad905b100712 [file] [log] [blame]
Kent Hagerman2b216042020-04-03 18:28:56 -04001/*
Joey Armstrong7a9af442024-01-03 19:26:36 -05002 * Copyright 2020-2024 Open Networking Foundation (ONF) and the ONF Contributors
Kent Hagerman2b216042020-04-03 18:28:56 -04003
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
17package adapter
18
19import (
Rohan Agrawal31f21802020-06-12 05:38:46 +000020 "context"
khenaidood948f772021-08-11 17:49:24 -040021 "errors"
nikesh.krishnan0ded28d2023-06-28 12:36:32 +053022 grpc_retry "github.com/grpc-ecosystem/go-grpc-middleware/retry"
khenaidood948f772021-08-11 17:49:24 -040023 vgrpc "github.com/opencord/voltha-lib-go/v7/pkg/grpc"
24 "github.com/opencord/voltha-lib-go/v7/pkg/log"
khenaidoo9beaaf12021-10-19 17:32:01 -040025 "github.com/opencord/voltha-protos/v5/go/adapter_service"
khenaidood948f772021-08-11 17:49:24 -040026 "github.com/opencord/voltha-protos/v5/go/voltha"
27 "google.golang.org/grpc"
nikesh.krishnan0ded28d2023-06-28 12:36:32 +053028 codes "google.golang.org/grpc/codes"
29 "sync"
30 "time"
Kent Hagerman2b216042020-04-03 18:28:56 -040031)
32
33// agent represents adapter agent
34type agent struct {
khenaidood948f772021-08-11 17:49:24 -040035 adapter *voltha.Adapter
36 lock sync.RWMutex
37 adapterAPIEndPoint string
38 vClient *vgrpc.Client
39 adapterLock sync.RWMutex
40 onAdapterRestart vgrpc.RestartedHandler
41 liveProbeInterval time.Duration
khenaidoo25057da2021-12-08 14:40:45 -050042 coreEndpoint string
nikesh.krishnan0ded28d2023-06-28 12:36:32 +053043 maxRetries uint
44 perRPCRetryTimeout time.Duration
Kent Hagerman2b216042020-04-03 18:28:56 -040045}
46
khenaidooa46458b2021-12-15 16:50:44 -050047func getAdapterServiceClientHandler(ctx context.Context, conn *grpc.ClientConn) interface{} {
48 if conn == nil {
khenaidood948f772021-08-11 17:49:24 -040049 return nil
50 }
khenaidooa46458b2021-12-15 16:50:44 -050051 return adapter_service.NewAdapterServiceClient(conn)
khenaidood948f772021-08-11 17:49:24 -040052}
53
nikesh.krishnan0ded28d2023-06-28 12:36:32 +053054func newAdapterAgent(coreEndpoint string, adapter *voltha.Adapter, onAdapterRestart vgrpc.RestartedHandler, liveProbeInterval time.Duration, maxRetries uint, perRPCRetryTimeout time.Duration) *agent {
Kent Hagerman2b216042020-04-03 18:28:56 -040055 return &agent{
khenaidood948f772021-08-11 17:49:24 -040056 adapter: adapter,
57 onAdapterRestart: onAdapterRestart,
58 adapterAPIEndPoint: adapter.Endpoint,
59 liveProbeInterval: liveProbeInterval,
khenaidoo25057da2021-12-08 14:40:45 -050060 coreEndpoint: coreEndpoint,
nikesh.krishnan0ded28d2023-06-28 12:36:32 +053061 maxRetries: maxRetries,
62 perRPCRetryTimeout: perRPCRetryTimeout,
khenaidood948f772021-08-11 17:49:24 -040063 }
64}
65
66func (aa *agent) start(ctx context.Context) error {
67 // Establish grpc connection to Core
68 var err error
khenaidoo25057da2021-12-08 14:40:45 -050069 if aa.vClient, err = vgrpc.NewClient(
70 aa.coreEndpoint,
71 aa.adapterAPIEndPoint,
khenaidooa46458b2021-12-15 16:50:44 -050072 "adapter_service.AdapterService",
khenaidoo25057da2021-12-08 14:40:45 -050073 aa.onAdapterRestart); err != nil {
khenaidood948f772021-08-11 17:49:24 -040074 return err
75 }
76
77 // Add a liveness communication update
78 aa.vClient.SubscribeForLiveness(aa.updateCommunicationTime)
nikesh.krishnan0ded28d2023-06-28 12:36:32 +053079 // the backoff function sets the wait time bw each grpc retries, if not set it will take the deafault value of 50ms which is too low, the jitter sets the rpc retry wait time to be in a range of[PerRPCRetryTimeout-0.2, PerRPCRetryTimeout+0.2]
80 backoffCtxOption := grpc_retry.WithBackoff(grpc_retry.BackoffLinearWithJitter(aa.perRPCRetryTimeout, 0.2))
81 retryCodes := []codes.Code{
82 codes.Unavailable, // server is currently unavailable
83 codes.DeadlineExceeded, // deadline for the operation was exceeded
84 }
85 grpcRetryOptions := grpc_retry.UnaryClientInterceptor(grpc_retry.WithMax(aa.maxRetries), grpc_retry.WithPerRetryTimeout(aa.perRPCRetryTimeout), grpc_retry.WithCodes(retryCodes...), backoffCtxOption)
86 logger.Debug(ctx, "Configuration values", log.Fields{"RETRY": aa.maxRetries, "TIMEOUT": aa.perRPCRetryTimeout})
87 go aa.vClient.Start(ctx, getAdapterServiceClientHandler, grpcRetryOptions)
khenaidood948f772021-08-11 17:49:24 -040088 return nil
89}
90
91func (aa *agent) stop(ctx context.Context) {
92 // Close the client
khenaidooa46458b2021-12-15 16:50:44 -050093 logger.Infow(ctx, "stopping-adapter-agent", log.Fields{"adapter": aa.adapter})
khenaidood948f772021-08-11 17:49:24 -040094 if aa.vClient != nil {
95 aa.vClient.Stop(ctx)
Kent Hagerman2b216042020-04-03 18:28:56 -040096 }
97}
98
Rohan Agrawal31f21802020-06-12 05:38:46 +000099func (aa *agent) getAdapter(ctx context.Context) *voltha.Adapter {
khenaidood948f772021-08-11 17:49:24 -0400100 aa.adapterLock.RLock()
101 defer aa.adapterLock.RUnlock()
Kent Hagerman2b216042020-04-03 18:28:56 -0400102 return aa.adapter
103}
104
khenaidoo9beaaf12021-10-19 17:32:01 -0400105func (aa *agent) getClient() (adapter_service.AdapterServiceClient, error) {
khenaidood948f772021-08-11 17:49:24 -0400106 client, err := aa.vClient.GetClient()
107 if err != nil {
108 return nil, err
109 }
Girish Gowdra11ddb232022-05-26 12:19:59 -0700110
khenaidoo9beaaf12021-10-19 17:32:01 -0400111 c, ok := client.(adapter_service.AdapterServiceClient)
khenaidood948f772021-08-11 17:49:24 -0400112 if ok {
113 return c, nil
114 }
115 return nil, errors.New("invalid client returned")
116}
117
118func (aa *agent) resetConnection(ctx context.Context) {
119 if aa.vClient != nil {
120 aa.vClient.Reset(ctx)
121 }
122}
123
Kent Hagerman2b216042020-04-03 18:28:56 -0400124// updateCommunicationTime updates the message to the specified time.
125// No attempt is made to save the time to the db, so only recent times are guaranteed to be accurate.
126func (aa *agent) updateCommunicationTime(new time.Time) {
127 // only update if new time is not in the future, and either the old time is invalid or new time > old time
David K. Bainbridge5809b5b2020-08-27 00:07:41 +0000128 aa.lock.Lock()
129 defer aa.lock.Unlock()
khenaidood948f772021-08-11 17:49:24 -0400130 timestamp := time.Unix(aa.adapter.LastCommunication, 0)
131 if !new.After(time.Now()) && new.After(timestamp) {
132 timestamp = new
133 aa.adapter.LastCommunication = timestamp.Unix()
Kent Hagerman2b216042020-04-03 18:28:56 -0400134 }
135}
khenaidood948f772021-08-11 17:49:24 -0400136
137func (aa *agent) IsConnectionUp() bool {
138 _, err := aa.getClient()
139 return err == nil
140}