blob: bd9d2f0234bab5af20b8ed0ee4d2fd66f090ec2e [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 api
18
19import (
donNewtonAlpha1d2d6812018-09-14 16:00:02 -040020 "errors"
Author Namea594e632018-08-10 11:33:58 -040021 "fmt"
donNewtonAlpha57aa2ff2018-10-01 16:45:32 -040022 "io/ioutil"
Author Namea594e632018-08-10 11:33:58 -040023 "log"
24 "net"
donNewtonAlpha57aa2ff2018-10-01 16:45:32 -040025 "net/http"
donNewtonAlphae7ab5b92018-09-27 15:09:14 -040026 "os"
Author Namea594e632018-08-10 11:33:58 -040027 "strings"
donNewtonAlphac997d642018-10-17 13:22:48 -040028 "sync"
Author Namea594e632018-08-10 11:33:58 -040029
30 "gerrit.opencord.org/abstract-olt/internal/pkg/settings"
31 "gerrit.opencord.org/abstract-olt/models"
32 "gerrit.opencord.org/abstract-olt/models/abstract"
33 "gerrit.opencord.org/abstract-olt/models/physical"
donNewtonAlphac997d642018-10-17 13:22:48 -040034 "github.com/mongodb/mongo-go-driver/bson"
35 "github.com/mongodb/mongo-go-driver/mongo"
36 "github.com/mongodb/mongo-go-driver/mongo/updateopt"
Author Namea594e632018-08-10 11:33:58 -040037 context "golang.org/x/net/context"
38)
39
40/*
41Server instance of the grpc server
42*/
43type Server struct {
44}
45
donNewtonAlphac997d642018-10-17 13:22:48 -040046var syncChan chan bool
47var isDirty bool
48
49var runOnce sync.Once
50
51func getSyncChannel() chan bool {
52 runOnce.Do(func() {
53 syncChan = make(chan bool, 1)
54 syncChan <- true
55 })
56
57 return syncChan
58}
59func done(myChan chan bool, done bool) {
60 myChan <- done
61}
62
donNewtonAlphae7ab5b92018-09-27 15:09:14 -040063/*
64Echo - Tester function which just returns same string sent to it
65*/
donNewtonAlphab3279ea2018-09-18 15:55:32 -040066func (s *Server) Echo(ctx context.Context, in *EchoMessage) (*EchoReplyMessage, error) {
donNewtonAlphac997d642018-10-17 13:22:48 -040067 myChan := getSyncChannel()
68 <-myChan
69 defer done(myChan, true)
donNewtonAlphab8f30752018-10-04 11:57:41 -040070 fmt.Println("HELLO WTF")
donNewtonAlphab3279ea2018-09-18 15:55:32 -040071 ping := in.GetPing()
72 pong := EchoReplyMessage{Pong: ping}
73 return &pong, nil
74}
75
Author Namea594e632018-08-10 11:33:58 -040076/*
77CreateChassis - allocates a new Chassis struct and stores it in chassisMap
78*/
79func (s *Server) CreateChassis(ctx context.Context, in *AddChassisMessage) (*AddChassisReturn, error) {
donNewtonAlphac997d642018-10-17 13:22:48 -040080 myChan := getSyncChannel()
81 fmt.Println("after getSyncChannel")
82 <-myChan
83 defer done(myChan, true)
donNewtonAlphae7ab5b92018-09-27 15:09:14 -040084 chassisMap := models.GetChassisMap()
Author Namea594e632018-08-10 11:33:58 -040085 clli := in.GetCLLI()
donNewtonAlpha57aa2ff2018-10-01 16:45:32 -040086
87 xosIP := net.ParseIP(in.GetXOSIP())
88 xosPort := int(in.GetXOSPort())
89 if xosIP == nil {
90 errStr := fmt.Sprintf("Invalid IP %s supplied for XOSIP", in.GetXOSIP())
91 return nil, errors.New(errStr)
92 }
93
94 xosAddress := net.TCPAddr{IP: xosIP, Port: xosPort}
95
96 xosUser := in.GetXOSUser()
97 xosPassword := in.GetXOSPassword()
98 if xosUser == "" || xosPassword == "" {
99 return nil, errors.New("Either XOSUser or XOSPassword supplied were empty")
100 }
101 loginWorked := testLogin(xosUser, xosPassword, xosIP, xosPort)
102 if !loginWorked {
103 return nil, errors.New("Unable to validate login not creating Abstract Chassis")
104 }
105 shelf := int(in.GetShelf())
106 rack := int(in.GetRack())
107
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400108 chassisHolder := (*chassisMap)[clli]
109 if chassisHolder != nil {
110 return &AddChassisReturn{DeviceID: chassisHolder.AbstractChassis.CLLI}, nil
Author Namea594e632018-08-10 11:33:58 -0400111 }
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400112
donNewtonAlpha1d2d6812018-09-14 16:00:02 -0400113 abstractChassis := abstract.GenerateChassis(clli, int(in.GetRack()), int(in.GetShelf()))
donNewtonAlphab8f30752018-10-04 11:57:41 -0400114 phyChassis := physical.Chassis{CLLI: clli, XOSUser: xosUser, XOSPassword: xosPassword, XOSAddress: xosAddress, Rack: rack, Shelf: shelf}
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400115
116 chassisHolder = &models.ChassisHolder{AbstractChassis: abstractChassis, PhysicalChassis: phyChassis}
Author Namea594e632018-08-10 11:33:58 -0400117 if settings.GetDebug() {
118 output := fmt.Sprintf("%v", abstractChassis)
119 formatted := strings.Replace(output, "{", "\n{", -1)
120 log.Printf("new chassis %s\n", formatted)
121 }
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400122 (*chassisMap)[clli] = chassisHolder
donNewtonAlphac997d642018-10-17 13:22:48 -0400123 isDirty = true
Author Namea594e632018-08-10 11:33:58 -0400124 return &AddChassisReturn{DeviceID: clli}, nil
125}
126
127/*
donNewtonAlpha57aa2ff2018-10-01 16:45:32 -0400128ChangeXOSUserPassword - allows update of xos credentials
129*/
130func (s *Server) ChangeXOSUserPassword(ctx context.Context, in *ChangeXOSUserPasswordMessage) (*ChangeXOSUserPasswordReturn, error) {
donNewtonAlphac997d642018-10-17 13:22:48 -0400131 myChan := getSyncChannel()
132 <-myChan
133 defer done(myChan, true)
donNewtonAlpha57aa2ff2018-10-01 16:45:32 -0400134 clli := in.GetCLLI()
135 xosUser := in.GetXOSUser()
136 xosPassword := in.GetXOSPassword()
137 if xosUser == "" || xosPassword == "" {
138 return nil, errors.New("Either XOSUser or XOSPassword supplied were empty")
139 }
140 chassisMap := models.GetChassisMap()
141 chassisHolder := (*chassisMap)[clli]
142 if chassisHolder == nil {
143 errString := fmt.Sprintf("There is no chassis with CLLI of %s", clli)
144 return nil, errors.New(errString)
145 }
146 xosIP := chassisHolder.PhysicalChassis.XOSAddress.IP
147 xosPort := chassisHolder.PhysicalChassis.XOSAddress.Port
148 loginWorked := testLogin(xosUser, xosPassword, xosIP, xosPort)
149 if !loginWorked {
150 return nil, errors.New("Unable to validate login when changing password")
151 }
152
153 chassisHolder.PhysicalChassis.XOSUser = xosUser
154 chassisHolder.PhysicalChassis.XOSPassword = xosPassword
donNewtonAlphac997d642018-10-17 13:22:48 -0400155 isDirty = true
donNewtonAlpha57aa2ff2018-10-01 16:45:32 -0400156 return &ChangeXOSUserPasswordReturn{Success: true}, nil
157
158}
159
160/*
donNewtonAlphab9b85eb2018-08-14 14:28:22 -0400161CreateOLTChassis adds an OLT chassis/line card to the Physical chassis
Author Namea594e632018-08-10 11:33:58 -0400162*/
163func (s *Server) CreateOLTChassis(ctx context.Context, in *AddOLTChassisMessage) (*AddOLTChassisReturn, error) {
donNewtonAlphac997d642018-10-17 13:22:48 -0400164 myChan := getSyncChannel()
165 <-myChan
166 defer done(myChan, true)
Author Namea594e632018-08-10 11:33:58 -0400167 fmt.Printf(" CreateOLTChassis %v \n", *in)
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400168 chassisMap := models.GetChassisMap()
Author Namea594e632018-08-10 11:33:58 -0400169 clli := in.GetCLLI()
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400170 chassisHolder := (*chassisMap)[clli]
171 if chassisHolder == nil {
donNewtonAlpha1d2d6812018-09-14 16:00:02 -0400172 errString := fmt.Sprintf("There is no chassis with CLLI of %s", clli)
173 return &AddOLTChassisReturn{DeviceID: "", ChassisDeviceID: ""}, errors.New(errString)
Author Namea594e632018-08-10 11:33:58 -0400174 }
175 oltType := in.GetType()
176 address := net.TCPAddr{IP: net.ParseIP(in.GetSlotIP()), Port: int(in.GetSlotPort())}
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400177 physicalChassis := &chassisHolder.PhysicalChassis
178 sOlt := physical.SimpleOLT{CLLI: clli, Hostname: in.GetHostname(), Address: address, Parent: physicalChassis}
Author Namea594e632018-08-10 11:33:58 -0400179 switch oltType {
180 case AddOLTChassisMessage_edgecore:
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400181 sOlt.CreateEdgecore()
Author Namea594e632018-08-10 11:33:58 -0400182 case AddOLTChassisMessage_adtran:
183 case AddOLTChassisMessage_tibit:
184 }
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400185 physicalChassis.AddOLTChassis(sOlt)
186 ports := sOlt.GetPorts()
187 for i := 0; i < len(ports); i++ {
188 absPort, _ := chassisHolder.AbstractChassis.NextPort()
189
190 absPort.PhysPort = &ports[i]
191 //AssignTraits(&ports[i], absPort)
Author Namea594e632018-08-10 11:33:58 -0400192 }
donNewtonAlphac997d642018-10-17 13:22:48 -0400193 isDirty = true
Author Namea594e632018-08-10 11:33:58 -0400194 return &AddOLTChassisReturn{DeviceID: in.GetHostname(), ChassisDeviceID: clli}, nil
195
196}
197
198/*
donNewtonAlpha5234b132018-08-16 14:12:28 -0400199ProvisionOnt provisions an ONT on a specific Chassis/LineCard/Port
200*/
201func (s *Server) ProvisionOnt(ctx context.Context, in *AddOntMessage) (*AddOntReturn, error) {
donNewtonAlphac997d642018-10-17 13:22:48 -0400202 myChan := getSyncChannel()
203 <-myChan
204 defer done(myChan, true)
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400205 chassisMap := models.GetChassisMap()
donNewtonAlpha5234b132018-08-16 14:12:28 -0400206 clli := in.GetCLLI()
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400207 chassisHolder := (*chassisMap)[clli]
208 if chassisHolder == nil {
donNewtonAlpha1d2d6812018-09-14 16:00:02 -0400209 errString := fmt.Sprintf("There is no chassis with CLLI of %s", clli)
210 return &AddOntReturn{Success: false}, errors.New(errString)
211 }
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400212 err := chassisHolder.AbstractChassis.ActivateONT(int(in.GetSlotNumber()), int(in.GetPortNumber()), int(in.GetOntNumber()), in.GetSerialNumber())
donNewtonAlpha5234b132018-08-16 14:12:28 -0400213
214 if err != nil {
215 return nil, err
216 }
donNewtonAlphac997d642018-10-17 13:22:48 -0400217 isDirty = true
donNewtonAlpha5234b132018-08-16 14:12:28 -0400218 return &AddOntReturn{Success: true}, nil
219}
donNewtonAlphaf7cc9992018-08-29 14:23:02 -0400220
221/*
222DeleteOnt - deletes a previously provision ont
223*/
224func (s *Server) DeleteOnt(ctx context.Context, in *DeleteOntMessage) (*DeleteOntReturn, error) {
donNewtonAlphac997d642018-10-17 13:22:48 -0400225 myChan := getSyncChannel()
226 <-myChan
227 defer done(myChan, true)
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400228 chassisMap := models.GetChassisMap()
donNewtonAlphaf7cc9992018-08-29 14:23:02 -0400229 clli := in.GetCLLI()
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400230 chassisHolder := (*chassisMap)[clli]
231 err := chassisHolder.AbstractChassis.DeleteONT(int(in.GetSlotNumber()), int(in.GetPortNumber()), int(in.GetOntNumber()), in.GetSerialNumber())
donNewtonAlphaf7cc9992018-08-29 14:23:02 -0400232 if err != nil {
233 return nil, err
234 }
donNewtonAlphac997d642018-10-17 13:22:48 -0400235 isDirty = true
donNewtonAlphaf7cc9992018-08-29 14:23:02 -0400236 return &DeleteOntReturn{Success: true}, nil
237}
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400238
239func (s *Server) Output(ctx context.Context, in *OutputMessage) (*OutputReturn, error) {
donNewtonAlphac997d642018-10-17 13:22:48 -0400240 return DoOutput()
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400241
donNewtonAlphac997d642018-10-17 13:22:48 -0400242}
243func DoOutput() (*OutputReturn, error) {
244 if isDirty {
245 myChan := getSyncChannel()
246 <-myChan
247 defer done(myChan, true)
248 chassisMap := models.GetChassisMap()
249 if settings.GetMongo() {
250 client, err := mongo.NewClient(settings.GetMongodb())
251 client.Connect(context.Background())
252 if err != nil {
253 log.Printf("client connect to mongo db @%s failed with %v\n", settings.GetMongodb(), err)
254 }
255 defer client.Disconnect(context.Background())
256 for clli, chassisHolder := range *chassisMap {
257 json, _ := (chassisHolder).Serialize()
258 collection := client.Database("AbstractOLT").Collection("backup")
259 doc := bson.NewDocument(bson.EC.String("_id", clli))
260 filter := bson.NewDocument(bson.EC.String("_id", clli))
261 doc.Append(bson.EC.Binary("body", json))
262
263 updateDoc := bson.NewDocument(bson.EC.SubDocument("$set", doc))
264 //update or insert if not existent
265 res, err := collection.UpdateOne(context.Background(), filter, updateDoc, updateopt.Upsert(true))
266 if err != nil {
267 log.Printf("collection.UpdateOne failed with %v\n", err)
268 } else {
269 id := res.UpsertedID
270 if settings.GetDebug() {
271 log.Printf("Update Succeeded with id %v\n", id)
272 }
273 }
274 }
275 } else {
276 for clli, chassisHolder := range *chassisMap {
277
278 json, _ := (chassisHolder).Serialize()
279 if settings.GetMongo() {
280
281 } else {
282 //TODO parameterize dump location
283 backupFile := fmt.Sprintf("backup/%s", clli)
284 f, _ := os.Create(backupFile)
285
286 defer f.Close()
287
288 _, _ = f.WriteString(string(json))
289 f.Sync()
290 }
291 }
292 }
293 isDirty = false
294 } else {
295 if settings.GetDebug() {
296 log.Print("Not dirty not dumping config")
297 }
298
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400299 }
300 return &OutputReturn{Success: true}, nil
301
302}
donNewtonAlpha57aa2ff2018-10-01 16:45:32 -0400303func testLogin(xosUser string, xosPassword string, xosIP net.IP, xosPort int) bool {
donNewtonAlphab1466392018-10-02 10:42:05 -0400304 if settings.GetDummy() {
305 return true
306 }
donNewtonAlpha57aa2ff2018-10-01 16:45:32 -0400307 var dummyYaml = `
308tosca_definitions_version: tosca_simple_yaml_1_0
309imports:
310 - custom_types/site.yaml
311description: anything
312topology_template:
313 node_templates:
314 mysite:
315 type: tosca.nodes.Site
316 properties:
317 must-exist: true
318 name: mysite
319`
320 client := &http.Client{}
321 requestList := fmt.Sprintf("http://%s:%d/run", xosIP, xosPort)
322 req, err := http.NewRequest("POST", requestList, strings.NewReader(dummyYaml))
323 req.Header.Add("xos-username", xosUser)
324 req.Header.Add("xos-password", xosPassword)
325 resp, err := client.Do(req)
326 log.Printf("testLogin resp:%v", resp)
327 if err != nil {
328 log.Printf("Unable to validate XOS Login Information %v", err)
329 return false
330 }
331 defer resp.Body.Close()
332
333 if resp.StatusCode == http.StatusOK {
334 bodyBytes, _ := ioutil.ReadAll(resp.Body)
335 bodyString := string(bodyBytes)
336 fmt.Println(bodyString)
337 return true
338 }
339 return false
340
341}