blob: 7761bf6fe9582479e07eeb79d788b6fe451746fb [file] [log] [blame]
Author Namea594e632018-08-10 11:33:58 -04001/*
2 Copyright 2017 the original author or 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
17package physical
18
donNewtonAlpha5234b132018-08-16 14:12:28 -040019import (
Don Newton276cd1f2019-02-06 17:14:03 -050020 "context"
21 "encoding/base64"
22 "errors"
donNewtonAlpha5234b132018-08-16 14:12:28 -040023 "fmt"
donNewtonAlphaaf229742018-09-19 13:22:00 -040024 "log"
donNewtonAlpha5234b132018-08-16 14:12:28 -040025 "net"
donNewtonAlpha1d2d6812018-09-14 16:00:02 -040026 "net/http"
27 "strings"
28
Don Newton276cd1f2019-02-06 17:14:03 -050029 "gerrit.opencord.org/abstract-olt/contrib/xos"
donNewtonAlphaaf229742018-09-19 13:22:00 -040030 "gerrit.opencord.org/abstract-olt/internal/pkg/settings"
donNewtonAlpha1d2d6812018-09-14 16:00:02 -040031 "gerrit.opencord.org/abstract-olt/models/tosca"
Don Newton276cd1f2019-02-06 17:14:03 -050032 "google.golang.org/grpc"
donNewtonAlpha5234b132018-08-16 14:12:28 -040033)
Author Namea594e632018-08-10 11:33:58 -040034
Don Newton276cd1f2019-02-06 17:14:03 -050035type basicAuth struct {
36 username string
37 password string
38}
39
40func (b basicAuth) GetRequestMetadata(ctx context.Context, in ...string) (map[string]string, error) {
41 auth := b.username + ":" + b.password
42 enc := base64.StdEncoding.EncodeToString([]byte(auth))
43 return map[string]string{
44 "authorization": "Basic " + enc,
45 }, nil
46}
47
48func (basicAuth) RequireTransportSecurity() bool {
49 return false
50}
51
Author Namea594e632018-08-10 11:33:58 -040052/*
53Chassis is a model that takes up to 16 discreet OLT chassis as if it is a 16 slot OLT chassis
54*/
55type Chassis struct {
donNewtonAlpha57aa2ff2018-10-01 16:45:32 -040056 CLLI string
57 XOSAddress net.TCPAddr
58 XOSUser string
59 XOSPassword string
60 Linecards []SimpleOLT
61 Rack int
62 Shelf int
Author Namea594e632018-08-10 11:33:58 -040063}
Don Newton276cd1f2019-02-06 17:14:03 -050064
65/*
66UnprovisionedSlotError - Error thrown when attempting to provision to a line card that hasn't been activated
67*/
donNewtonAlpha8205a4d2018-08-16 18:27:20 -040068type UnprovisionedSlotError struct {
69 CLLI string
70 SlotNumber int
71}
72
73func (e *UnprovisionedSlotError) Error() string {
74 return fmt.Sprintf("SlotNumber %d in Chassis %s is currently unprovsioned", e.SlotNumber, e.CLLI)
75}
donNewtonAlpha5234b132018-08-16 14:12:28 -040076
77/*
78AddOLTChassis - adds a reference to a new olt chassis
79*/
donNewtonAlphae7ab5b92018-09-27 15:09:14 -040080func (chassis *Chassis) AddOLTChassis(olt SimpleOLT) {
81 olt.SetNumber((len(chassis.Linecards) + 1))
donNewtonAlpha5234b132018-08-16 14:12:28 -040082 chassis.Linecards = append(chassis.Linecards, olt)
Don Newton276cd1f2019-02-06 17:14:03 -050083 if settings.GetGrpc() {
84 chassis.SendOltGRPC(olt)
85 } else {
86 chassis.SendOltTosca(olt)
87 }
Don Newtone973d342018-10-26 16:44:12 -040088}
89
90/*
Don Newton276cd1f2019-02-06 17:14:03 -050091SendOltGRPC - provisions olt using grpc interface
Don Newtone973d342018-10-26 16:44:12 -040092*/
Don Newton276cd1f2019-02-06 17:14:03 -050093func (chassis *Chassis) SendOltGRPC(olt SimpleOLT) error {
94 if settings.GetDummy() {
95 log.Println("Running in Dummy mode with GRPC in SendOltGRPC")
96 return nil
97 }
98 conn, err := grpc.Dial(chassis.XOSAddress.String(), grpc.WithInsecure(), grpc.WithPerRPCCredentials(basicAuth{
99 username: chassis.XOSUser,
100 password: chassis.XOSPassword,
101 }))
102 defer conn.Close()
103 if err != nil {
104 log.Println(err)
105 return err
106 }
107
108 xosClient := xos.NewXosClient(conn)
109 //queryElement := &xos.QueryElement{Operator: xos.QueryElement_EQUAL, Name: "volt_service_instances", Value: &xos.QueryElement_SValue{"volt"}}
110 queryElement := &xos.QueryElement{Operator: xos.QueryElement_EQUAL, Name: "name", Value: &xos.QueryElement_SValue{"volt"}}
111 queryElements := []*xos.QueryElement{queryElement}
112 query := &xos.Query{Kind: xos.Query_DEFAULT, Elements: queryElements}
113
114 voltResponse, err := xosClient.FilterVOLTService(context.Background(), query)
115 if err != nil {
116 log.Println(err)
117 return err
118 }
119 voltServices := voltResponse.GetItems()
120 if len(voltServices) == 0 {
121 return errors.New("xosClient.FilterVOLTService returned 0 entries with name \"volt\"")
122 }
123 voltService := voltServices[0]
124
125 response, err := xosClient.CreateOLTDevice(context.Background(), &xos.OLTDevice{
126 NamePresent: &xos.OLTDevice_Name{olt.Hostname},
127 DeviceTypePresent: &xos.OLTDevice_DeviceType{olt.Driver},
128 HostPresent: &xos.OLTDevice_Host{olt.GetAddress().IP.String()},
129 PortPresent: &xos.OLTDevice_Port{int32(olt.GetAddress().Port)},
130 OuterTpidPresent: &xos.OLTDevice_OuterTpid{"0x8100"},
131 UplinkPresent: &xos.OLTDevice_Uplink{"65536"},
132 NasIdPresent: &xos.OLTDevice_NasId{olt.CLLI},
133 SwitchDatapathIdPresent: &xos.OLTDevice_SwitchDatapathId{"of:0000000000000001"},
134 SwitchPortPresent: &xos.OLTDevice_SwitchPort{"1"},
135 VoltServicePresent: &xos.OLTDevice_VoltServiceId{voltService.GetId()},
136 })
137 if err != nil {
138 log.Printf("ERROR :) %v\n", err)
139 return err
140 }
141 log.Printf("Response is %v\n", response)
142 return nil
143}
144
145/*
146SendOltTosca - Provision OLT using TOSCA Interface
147*/
148func (chassis *Chassis) SendOltTosca(olt SimpleOLT) error {
donNewtonAlpha1d2d6812018-09-14 16:00:02 -0400149 ipString := olt.GetAddress().IP.String()
150 webServerPort := olt.GetAddress().Port
Don Newton5154fff2018-11-06 17:40:58 -0500151 oltStruct := tosca.NewOltProvision(chassis.CLLI, olt.GetHostname(), olt.Driver, ipString, webServerPort)
donNewtonAlpha1d2d6812018-09-14 16:00:02 -0400152 yaml, _ := oltStruct.ToYaml()
donNewtonAlphaaf229742018-09-19 13:22:00 -0400153 if settings.GetDummy() {
154 log.Printf("yaml:%s\n", yaml)
Don Newton276cd1f2019-02-06 17:14:03 -0500155 log.Println("YAML IS NOT BEING SET TO XOS or DEBUG is Set")
156 return nil
donNewtonAlphaaf229742018-09-19 13:22:00 -0400157 }
donNewtonAlpha1d2d6812018-09-14 16:00:02 -0400158
Don Newton276cd1f2019-02-06 17:14:03 -0500159 if settings.GetDebug() {
donNewtonAlphaaf229742018-09-19 13:22:00 -0400160 log.Printf("yaml:%s\n", yaml)
donNewtonAlphaaf229742018-09-19 13:22:00 -0400161 }
donNewtonAlpha1d2d6812018-09-14 16:00:02 -0400162 client := &http.Client{}
donNewtonAlpha57aa2ff2018-10-01 16:45:32 -0400163 requestList := fmt.Sprintf("http://%s:%d/run", chassis.XOSAddress.IP.String(), chassis.XOSAddress.Port)
donNewtonAlpha1d2d6812018-09-14 16:00:02 -0400164 req, err := http.NewRequest("POST", requestList, strings.NewReader(yaml))
donNewtonAlpha57aa2ff2018-10-01 16:45:32 -0400165 req.Header.Add("xos-username", chassis.XOSUser)
166 req.Header.Add("xos-password", chassis.XOSPassword)
donNewtonAlpha1d2d6812018-09-14 16:00:02 -0400167 resp, err := client.Do(req)
168 if err != nil {
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400169 log.Printf("ERROR :) %v\n", err)
Don Newton276cd1f2019-02-06 17:14:03 -0500170 return err
171 }
172 log.Printf("Server response was %v\n", resp.Body)
173 return nil
174}
175func (chassis *Chassis) provisionONT(ont Ont) {
176 //TODO - api call to provison s/c vlans and ont serial number etc
177 log.Printf("chassis.provisionONT(%s,SVlan:%d,CVlan:%d)\n", ont.SerialNumber, ont.Svlan, ont.Cvlan)
178 if settings.GetGrpc() {
179 chassis.SendOntGRPC(ont)
180 chassis.SendSubscriberGRPC(ont)
181 } else {
182 chassis.SendOntTosca(ont)
183 chassis.SendSubscriberTosca(ont)
184 }
185}
186
187/*
188SendOntGRPC - Provision ONT on XOS using GRPC interface
189*/
190func (chassis *Chassis) SendOntGRPC(ont Ont) error {
191 if settings.GetDummy() {
192 log.Println("Running in Dummy mode with GRPC in SendOntGRPC")
193 return nil
194 }
195 ponPort := ont.Parent
196 slot := ponPort.Parent
197 ip := slot.Address.IP
198 ipNum := []byte(ip[12:16]) //only handling ipv4
199 ofID := fmt.Sprintf("of:00000000%0x", ipNum)
200
201 conn, err := grpc.Dial(chassis.XOSAddress.String(), grpc.WithInsecure(), grpc.WithPerRPCCredentials(basicAuth{
202 username: chassis.XOSUser,
203 password: chassis.XOSPassword,
204 },
205 ))
206 defer conn.Close()
207 if err != nil {
208 log.Printf("ERROR :) %v\n", err)
209 return err
210 }
211 xosClient := xos.NewXosClient(conn)
212 queryElement := &xos.QueryElement{Operator: xos.QueryElement_EQUAL, Name: "name", Value: &xos.QueryElement_SValue{"att-workflow-driver"}}
213 queryElements := []*xos.QueryElement{queryElement}
214 query := &xos.Query{Kind: xos.Query_DEFAULT, Elements: queryElements}
215
216 attWorkFlowResponse, err := xosClient.FilterAttWorkflowDriverService(context.Background(), query)
217 if err != nil {
218 log.Printf("ERROR :) %v\n", err)
219 return err
220 }
221
222 attWorkFlowServices := attWorkFlowResponse.GetItems()
223 if len(attWorkFlowServices) == 0 {
224 err := "xosClient.FilterAttWorkflowDriverService return zero attWorkFlowServices with name att-workflow-driver"
225 log.Print(err)
226 return errors.New(err)
227 }
228 log.Printf("FilterAttWorkflowDriver response is %s", attWorkFlowResponse)
229 attWorkFlowService := attWorkFlowServices[0]
230
231 newQueryElement := &xos.QueryElement{Operator: xos.QueryElement_EQUAL, Name: "serial_number", Value: &xos.QueryElement_SValue{ont.SerialNumber}}
232 newQueryElements := []*xos.QueryElement{newQueryElement}
233 query = &xos.Query{Kind: xos.Query_DEFAULT, Elements: newQueryElements}
234
235 onuResponse, err := xosClient.FilterONUDevice(context.Background(), query)
236 log.Printf("FilterONU response is %s", onuResponse)
237 onus := onuResponse.GetItems()
238 if len(onus) == 0 {
239 err := fmt.Sprintf("xosClient.FilterONUDevices return zero onus with serial number %s", ont.SerialNumber)
240 log.Print(err)
241 return errors.New(err)
242 }
243 deviceID := onus[0].GetDeviceId()
244
245 offset := 1 << 29
246 ponPortNumber := offset + (ponPort.Number - 1)
247 log.Printf("Calling xosClient.CreateAttWorkflowDriverWhiteListEntry with SerialNumberPresent: %s DeviceIdPresent: %s PonPortIdPresent: %d OwnerPresent: %d", ont.SerialNumber, deviceID, ponPortNumber, attWorkFlowService.GetId())
248 response, err := xosClient.CreateAttWorkflowDriverWhiteListEntry(context.Background(), &xos.AttWorkflowDriverWhiteListEntry{
249 SerialNumberPresent: &xos.AttWorkflowDriverWhiteListEntry_SerialNumber{ont.SerialNumber},
250 //DeviceIdPresent: &xos.AttWorkflowDriverWhiteListEntry_DeviceId{deviceID},
251 DeviceIdPresent: &xos.AttWorkflowDriverWhiteListEntry_DeviceId{ofID},
252 PonPortIdPresent: &xos.AttWorkflowDriverWhiteListEntry_PonPortId{int32(ponPortNumber)},
253 OwnerPresent: &xos.AttWorkflowDriverWhiteListEntry_OwnerId{attWorkFlowService.GetId()},
254 })
255
256 if err != nil {
257 log.Printf("ERROR :) %v\n", err)
258 return err
259 }
260 log.Printf("Response is %v\n", response)
261 return nil
262}
263
264/*
265SendOntTosca - Provision ONT on XOS using Tosca interface
266*/
267func (chassis *Chassis) SendOntTosca(ont Ont) error {
268 ponPort := ont.Parent
269 slot := ponPort.Parent
270 ontStruct := tosca.NewOntProvision(ont.SerialNumber, slot.Address.IP, ponPort.Number)
271 yaml, _ := ontStruct.ToYaml()
272
273 if settings.GetDummy() {
274 log.Printf("yaml:%s\n", yaml)
275 log.Println("YAML IS NOT BEING SET TO XOS")
276 return nil
277 }
278 client := &http.Client{}
279 requestList := fmt.Sprintf("http://%s:%d/run", chassis.XOSAddress.IP.String(), chassis.XOSAddress.Port)
280 req, err := http.NewRequest("POST", requestList, strings.NewReader(yaml))
281 req.Header.Add("xos-username", chassis.XOSUser)
282 req.Header.Add("xos-password", chassis.XOSPassword)
283 resp, err := client.Do(req)
284 if err != nil {
285 log.Printf("ERROR :) %v\n", err)
286 return err
donNewtonAlpha1d2d6812018-09-14 16:00:02 -0400287 }
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400288 log.Printf("Response is %v\n", resp)
Don Newton276cd1f2019-02-06 17:14:03 -0500289 return nil
Don Newtone973d342018-10-26 16:44:12 -0400290}
Don Newton276cd1f2019-02-06 17:14:03 -0500291
292/*
293SendSubscriberGRPC - Provisons a subscriber using the GRPC Interface
294*/
295func (chassis *Chassis) SendSubscriberGRPC(ont Ont) error {
296 if settings.GetDummy() {
297 log.Println("Running in Dummy mode with GRPC in SendSubscriberGRPC")
298 return nil
299 }
300 ponPort := ont.Parent
301 slot := ponPort.Parent
302 conn, err := grpc.Dial(chassis.XOSAddress.String(), grpc.WithInsecure(), grpc.WithPerRPCCredentials(basicAuth{
303 username: chassis.XOSUser,
304 password: chassis.XOSPassword,
305 }))
306 defer conn.Close()
307 if err != nil {
308 log.Printf("ERROR :) %v\n", err)
309 return err
310 }
311
312 xosClient := xos.NewXosClient(conn)
313 rgName := fmt.Sprintf("%s_%d_%d_%d_RG", chassis.CLLI, slot.Number, ponPort.Number, ont.Number)
314 response, err := xosClient.CreateRCORDSubscriber(context.Background(), &xos.RCORDSubscriber{
315 NamePresent: &xos.RCORDSubscriber_Name{rgName},
316 CTagPresent: &xos.RCORDSubscriber_CTag{int32(ont.Cvlan)},
317 STagPresent: &xos.RCORDSubscriber_STag{int32(ont.Svlan)},
318 OnuDevicePresent: &xos.RCORDSubscriber_OnuDevice{ont.SerialNumber},
319 NasPortIdPresent: &xos.RCORDSubscriber_NasPortId{ont.NasPortID},
320 CircuitIdPresent: &xos.RCORDSubscriber_CircuitId{ont.CircuitID},
321 RemoteIdPresent: &xos.RCORDSubscriber_RemoteId{chassis.CLLI}})
322 if err != nil {
323 log.Printf("ERROR :) %v\n", err)
324 return err
325 }
326 log.Println(response)
327 return nil
328
329}
330
331/*
332SendSubscriberTosca - Provisons a subscriber using the Tosca Interface
333*/
334func (chassis *Chassis) SendSubscriberTosca(ont Ont) error {
Don Newtone973d342018-10-26 16:44:12 -0400335 ponPort := ont.Parent
336 slot := ponPort.Parent
337 requestList := fmt.Sprintf("http://%s:%d/run", chassis.XOSAddress.IP.String(), chassis.XOSAddress.Port)
donNewtonAlpha1d2d6812018-09-14 16:00:02 -0400338 rgName := fmt.Sprintf("%s_%d_%d_%d_RG", chassis.CLLI, slot.Number, ponPort.Number, ont.Number)
339 subStruct := tosca.NewSubscriberProvision(rgName, ont.Cvlan, ont.Svlan, ont.SerialNumber, ont.NasPortID, ont.CircuitID, chassis.CLLI)
Don Newtone973d342018-10-26 16:44:12 -0400340 yaml, _ := subStruct.ToYaml()
341 if settings.GetDummy() {
342 log.Printf("yaml:%s\n", yaml)
343 log.Println("YAML IS NOT BEING SET TO XOS")
Don Newton276cd1f2019-02-06 17:14:03 -0500344 return nil
donNewtonAlpha1d2d6812018-09-14 16:00:02 -0400345 }
Don Newton276cd1f2019-02-06 17:14:03 -0500346 req, err := http.NewRequest("POST", requestList, strings.NewReader(yaml))
347 req.Header.Add("xos-username", chassis.XOSUser)
348 req.Header.Add("xos-password", chassis.XOSPassword)
349 client := &http.Client{}
350 resp, err := client.Do(req)
351 if err != nil {
352 log.Printf("ERROR :) %v\n", err)
353 return err
354 }
355 log.Printf("Response is %v\n", resp)
356
357 return nil
donNewtonAlpha5234b132018-08-16 14:12:28 -0400358}
Don Newton276cd1f2019-02-06 17:14:03 -0500359
donNewtonAlphaf7cc9992018-08-29 14:23:02 -0400360func (chassis *Chassis) deleteONT(ont Ont) {
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400361 log.Printf("chassis.deleteONT(%s,SVlan:%d,CVlan:%d)\n", ont.SerialNumber, ont.Svlan, ont.Cvlan)
Don Newton276cd1f2019-02-06 17:14:03 -0500362 if settings.GetGrpc() {
363 chassis.deleteOntWhitelistGRPC(ont)
364 } else {
365 chassis.deleteOntTosca(ont)
366 }
367}
368
369/*
370deleteOntGRPC - deletes ONT using XOS GRPC Interface
371*/
372func (chassis *Chassis) deleteOntWhitelistGRPC(ont Ont) error {
373 if settings.GetDummy() {
374 log.Println("Running in Dummy mode with GRPC in SendSubscriberGRPC")
375 return nil
376 }
377 conn, err := grpc.Dial(chassis.XOSAddress.String(), grpc.WithInsecure(), grpc.WithPerRPCCredentials(basicAuth{
378 username: chassis.XOSUser,
379 password: chassis.XOSPassword,
380 }))
381 defer conn.Close()
382 if err != nil {
383 log.Printf("ERROR :) %v\n", err)
384 return err
385 }
386 xosClient := xos.NewXosClient(conn)
387 queryElement := &xos.QueryElement{Operator: xos.QueryElement_EQUAL, Name: "serial_number", Value: &xos.QueryElement_SValue{ont.SerialNumber}}
388 queryElements := []*xos.QueryElement{queryElement}
389 query := &xos.Query{Kind: xos.Query_DEFAULT, Elements: queryElements}
390 onuResponse, err := xosClient.FilterAttWorkflowDriverWhiteListEntry(context.Background(), query)
391 onus := onuResponse.GetItems()
392 if len(onus) == 0 {
393 errorMsg := fmt.Sprintf("Unable to find WhiteListEntry in XOS with SerialNumber %s", ont.SerialNumber)
394 return errors.New(errorMsg)
395 }
396 onu := onus[0]
397 log.Printf("DeleteAttWorkflowDriverWhiteListEntry ONU : %v\n", onu)
398
399 id := &xos.ID{Id: onu.GetId()}
400 log.Printf("DeleteAttWorkflowDriverWhiteListEntry XOSID:%v\n", id)
401 response, err := xosClient.DeleteAttWorkflowDriverWhiteListEntry(context.Background(), id)
402
403 if err != nil {
404 log.Printf("ERROR :) %v\n", err)
405 return err
406 }
407 log.Printf("Response is %v\n", response)
408 return nil
409}
410
411/*
412deleteOntTosca - deletes ONT using XOS Tosca Interface
413*/
414func (chassis *Chassis) deleteOntTosca(ont Ont) {
donNewtonAlphab8f30752018-10-04 11:57:41 -0400415 ponPort := ont.Parent
416 slot := ponPort.Parent
donNewtonAlphab8f30752018-10-04 11:57:41 -0400417 ontStruct := tosca.NewOntProvision(ont.SerialNumber, slot.Address.IP, ponPort.Number)
418 yaml, _ := ontStruct.ToYaml()
419 fmt.Println(yaml)
420
421 requestList := fmt.Sprintf("http://%s:%d/delete", chassis.XOSAddress.IP.String(), chassis.XOSAddress.Port)
422 client := &http.Client{}
423 if settings.GetDummy() {
424 log.Printf("yaml:%s\n", yaml)
425 log.Println("YAML IS NOT BEING SET TO XOS")
426 } else {
427
428 log.Println(requestList)
429 log.Println(yaml)
430 if settings.GetDummy() {
431 return
432 }
433 req, err := http.NewRequest("POST", requestList, strings.NewReader(yaml))
434 req.Header.Add("xos-username", chassis.XOSUser)
435 req.Header.Add("xos-password", chassis.XOSPassword)
436 resp, err := client.Do(req)
437 if err != nil {
438 log.Printf("ERROR :) %v\n", err)
439 // handle error
440 }
441 log.Printf("Response is %v\n", resp)
442 }
443 deleteOntStruct := tosca.NewOntDelete(ont.SerialNumber)
444 yaml, _ = deleteOntStruct.ToYaml()
445 fmt.Println(yaml)
446 if settings.GetDummy() {
447 log.Printf("yaml:%s\n", yaml)
448 log.Println("YAML IS NOT BEING SET TO XOS")
449 return
donNewtonAlphab8f30752018-10-04 11:57:41 -0400450 }
Don Newton276cd1f2019-02-06 17:14:03 -0500451 req, err := http.NewRequest("POST", requestList, strings.NewReader(yaml))
452 req.Header.Add("xos-username", chassis.XOSUser)
453 req.Header.Add("xos-password", chassis.XOSPassword)
454 resp, err := client.Do(req)
455 if err != nil {
456 log.Printf("ERROR :) %v\n", err)
457 // handle error
458 }
459 log.Printf("Response is %v\n", resp)
donNewtonAlpha8205a4d2018-08-16 18:27:20 -0400460}