5 "google.golang.org/grpc"
6 "google.golang.org/grpc/reflection"
8 pb "ovn4nfv-k8s-plugin/internal/pkg/nfnNotify/proto"
9 v1alpha1 "ovn4nfv-k8s-plugin/pkg/apis/k8s/v1alpha1"
10 logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
12 "k8s.io/apimachinery/pkg/apis/meta/v1"
13 "k8s.io/client-go/kubernetes"
14 "k8s.io/client-go/rest"
15 clientset "ovn4nfv-k8s-plugin/pkg/generated/clientset/versioned"
18 var log = logf.Log.WithName("rpc-server")
21 context *pb.SubscribeContext
22 stream pb.NfnNotify_SubscribeServer
25 type serverDB struct {
27 clientList map[string]client
30 var notifServer *serverDB
31 var stopChan chan interface{}
33 var pnClientset *clientset.Clientset
34 var kubeClientset *kubernetes.Clientset
36 func newServer() *serverDB {
37 return &serverDB{name: "nfnNotifServer", clientList: make(map[string]client)}
40 // Subscribe stores the client information & sends data
41 func (s *serverDB) Subscribe(sc *pb.SubscribeContext, ss pb.NfnNotify_SubscribeServer) error {
42 nodeName := sc.GetNodeName()
43 log.Info("Subscribe request from node", "Node Name", nodeName)
45 return fmt.Errorf("Node name can't be empty")
51 s.clientList[nodeName] = cp
53 providerNetworklist, err := pnClientset.K8sV1alpha1().ProviderNetworks("default").List(v1.ListOptions{})
55 for _, pn := range providerNetworklist.Items {
56 log.Info("Send message", "Provider Network", pn.GetName())
57 SendNotif(&pn, "create", nodeName)
60 inSyncMsg := pb.Notification{
62 Payload: &pb.Notification_InSync{
66 log.Info("Send Insync")
67 if err = cp.stream.Send(&inSyncMsg); err != nil {
68 log.Error(err, "Unable to send sync", "node name", nodeName)
70 log.Info("Subscribe Completed")
79 func (s *serverDB) GetClient(nodeName string) client {
80 if val, ok := s.clientList[nodeName]; ok {
86 func updatePnStatus(pn *v1alpha1.ProviderNetwork, status string) error {
87 pnCopy := pn.DeepCopy()
88 pnCopy.Status.State = status
89 _, err := pnClientset.K8sV1alpha1().ProviderNetworks(pn.Namespace).Update(pnCopy)
93 func createMsg(pn *v1alpha1.ProviderNetwork) pb.Notification {
94 msg := pb.Notification{
96 Payload: &pb.Notification_ProviderNwCreate{
97 ProviderNwCreate: &pb.ProviderNetworkCreate{
98 ProviderNwName: pn.Name,
100 VlanId: pn.Spec.Vlan.VlanId,
101 ProviderIntf: pn.Spec.Vlan.ProviderInterfaceName,
102 LogicalIntf: pn.Spec.Vlan.LogicalInterfaceName,
110 func deleteMsg(pn *v1alpha1.ProviderNetwork) pb.Notification {
111 msg := pb.Notification{
113 Payload: &pb.Notification_ProviderNwRemove{
114 ProviderNwRemove: &pb.ProviderNetworkRemove{
115 ProviderNwName: pn.Name,
116 VlanLogicalIntf: pn.Spec.Vlan.LogicalInterfaceName,
123 //SendNotif to client
124 func SendNotif(pn *v1alpha1.ProviderNetwork, msgType string, nodeReq string) error {
125 var msg pb.Notification
129 case pn.Spec.CniType == "ovn4nfv":
131 case pn.Spec.ProviderNetType == "VLAN":
132 if msgType == "create" {
134 } else if msgType == "delete" {
137 if strings.EqualFold(pn.Spec.Vlan.VlanNodeSelector, "SPECIFIC") {
138 for _, label := range pn.Spec.Vlan.NodeLabelList {
139 l := strings.Split(label, "=")
141 log.Error(fmt.Errorf("Syntax error label: %v", label), "NodeListIterator")
145 labels := strings.Join(pn.Spec.Vlan.NodeLabelList[:], ",")
146 err = sendMsg(msg, labels, "specific", nodeReq)
147 } else if strings.EqualFold(pn.Spec.Vlan.VlanNodeSelector, "ALL") {
148 err = sendMsg(msg, "", "all", nodeReq)
149 } else if strings.EqualFold(pn.Spec.Vlan.VlanNodeSelector, "ANY") {
150 if pn.Status.State != v1alpha1.Created {
151 err = sendMsg(msg, "", "any", nodeReq)
153 updatePnStatus(pn, v1alpha1.Created)
158 return fmt.Errorf("Unsupported Provider Network type")
161 return fmt.Errorf("Unsupported CNI type")
166 // sendMsg send notification to client
167 func sendMsg(msg pb.Notification, labels string, option string, nodeReq string) error {
169 for name, client := range notifServer.clientList {
170 if nodeReq != "" && nodeReq != name {
173 if client.stream != nil {
174 if err := client.stream.Send(&msg); err != nil {
175 log.Error(err, "Msg Send failed", "Node name", name)
180 } else if option == "any" {
181 // Always select the first
182 for _, client := range notifServer.clientList {
183 if client.stream != nil {
184 if err := client.stream.Send(&msg); err != nil {
187 // return after first successful send
193 // This is specific case
194 for name := range nodeListIterator(labels) {
195 if nodeReq != "" && nodeReq != name {
198 client := notifServer.GetClient(name)
199 if client.stream != nil {
200 if err := client.stream.Send(&msg); err != nil {
208 func nodeListIterator(labels string) <-chan string {
209 ch := make(chan string)
211 lo := v1.ListOptions{LabelSelector: labels}
212 // List the Nodes matching the Labels
213 nodes, err := kubeClientset.CoreV1().Nodes().List(lo)
215 log.Info("No Nodes found with labels", "list:", lo)
219 for _, node := range nodes.Items {
220 log.Info("Send message to", " node:", node.ObjectMeta.Name)
221 ch <- node.ObjectMeta.Name
228 //SetupNotifServer initilizes the gRpc nfn notif server
229 func SetupNotifServer(kConfig *rest.Config) {
231 log.Info("Starting Notif Server")
234 // creates the clientset
235 pnClientset, err = clientset.NewForConfig(kConfig)
237 log.Error(err, "Error building clientset")
239 kubeClientset, err = kubernetes.NewForConfig(kConfig)
241 log.Error(err, "Error building Kuberenetes clientset")
244 stopChan = make(chan interface{})
247 lis, err := net.Listen("tcp", ":50000")
249 log.Error(err, "failed to listen")
252 s := grpc.NewServer()
253 // Intialize Notify server
254 notifServer = newServer()
255 pb.RegisterNfnNotifyServer(s, notifServer)
257 reflection.Register(s)
258 log.Info("Initialization Completed")
259 if err := s.Serve(lis); err != nil {
260 log.Error(err, "failed to serve")