Zack Williams | 41513bf | 2018-07-07 20:08:35 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2017-present Open Networking Foundation |
| 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 | */ |
Stephane Barbarie | 1408896 | 2017-06-01 16:56:55 -0400 | [diff] [blame] | 16 | //package voltha |
| 17 | package main |
| 18 | |
| 19 | /* |
| 20 | #include <stdlib.h> |
| 21 | #include "voltha-defs.h" |
| 22 | */ |
| 23 | import "C" |
| 24 | |
| 25 | import ( |
| 26 | "log" |
| 27 | "golang.org/x/net/context" |
| 28 | "google.golang.org/grpc" |
| 29 | "github.com/golang/protobuf/ptypes/empty" |
| 30 | "github.com/hashicorp/consul/api" |
| 31 | pb "github.com/opencord/voltha/netconf/translator/voltha" |
| 32 | pb_health "github.com/opencord/voltha/netconf/translator/voltha/health" |
| 33 | pb_device "github.com/opencord/voltha/netconf/translator/voltha/device" |
| 34 | pb_adapter "github.com/opencord/voltha/netconf/translator/voltha/adapter" |
| 35 | pb_logical_device "github.com/opencord/voltha/netconf/translator/voltha/logical_device" |
| 36 | pb_openflow "github.com/opencord/voltha/netconf/translator/voltha/openflow_13" |
| 37 | pb_any "github.com/golang/protobuf/ptypes/any" |
| 38 | "unsafe" |
| 39 | "fmt" |
| 40 | ) |
| 41 | |
| 42 | const ( |
| 43 | default_consul_address = "10.100.198.220:8500" |
| 44 | default_grpc_address = "localhost:50555" |
| 45 | grpc_service_name = "voltha-grpc" |
| 46 | ) |
| 47 | |
| 48 | var ( |
| 49 | GrpcConn *grpc.ClientConn = nil |
| 50 | VolthaGlobalClient pb.VolthaGlobalServiceClient = nil |
| 51 | HealthClient pb_health.HealthServiceClient = nil |
| 52 | ConsulClient *api.Client = nil |
| 53 | GrpcServiceAddress string = "localhost:50555" |
| 54 | ) |
| 55 | |
| 56 | func init() { |
| 57 | ConsulClient = connect_to_consul(default_consul_address) |
| 58 | GrpcServiceAddress = get_consul_service_address(grpc_service_name) |
| 59 | GrpcConn = connect_to_grpc(GrpcServiceAddress) |
| 60 | |
| 61 | VolthaGlobalClient = pb.NewVolthaGlobalServiceClient(GrpcConn) |
| 62 | HealthClient = pb_health.NewHealthServiceClient(GrpcConn) |
| 63 | } |
| 64 | |
| 65 | func connect_to_consul(consul_address string) *api.Client { |
| 66 | cfg := api.Config{Address: consul_address } |
| 67 | |
| 68 | log.Printf("Connecting to consul - address: %s", consul_address) |
| 69 | |
| 70 | client, err := api.NewClient(&cfg) |
| 71 | if err != nil { |
| 72 | panic(err) |
| 73 | } |
| 74 | |
| 75 | log.Printf("Connected to consul - address: %s", consul_address) |
| 76 | |
| 77 | return client |
| 78 | } |
| 79 | |
| 80 | func get_consul_service_address(service_name string) string { |
| 81 | var service []*api.CatalogService |
| 82 | var err error |
| 83 | |
| 84 | log.Printf("Getting consul service - name:%s", service_name) |
| 85 | |
| 86 | if service, _, _ = ConsulClient.Catalog().Service(service_name, "", nil); err != nil { |
| 87 | panic(err) |
| 88 | } |
| 89 | |
| 90 | address := fmt.Sprintf("%s:%d", service[0].ServiceAddress, service[0].ServicePort) |
| 91 | |
| 92 | log.Printf("Got consul service - name:%s, address:%s", service_name, address) |
| 93 | |
| 94 | return address |
| 95 | } |
| 96 | |
| 97 | func connect_to_grpc(grpc_address string) *grpc.ClientConn { |
| 98 | var err error |
| 99 | var client *grpc.ClientConn |
| 100 | |
| 101 | log.Printf("Connecting to grpc - address: %s", grpc_address) |
| 102 | |
| 103 | // Set up a connection to the server. |
| 104 | client, err = grpc.Dial(grpc_address, grpc.WithInsecure()) |
| 105 | if err != nil { |
| 106 | log.Fatalf("did not connect: %s", err.Error()) |
| 107 | } |
| 108 | |
| 109 | log.Printf("Connected to grpc - address: %s", grpc_address) |
| 110 | |
| 111 | return client |
| 112 | } |
| 113 | // Utility methods |
| 114 | |
| 115 | // ------------------------------------------------- |
| 116 | // C to Protobuf conversion methods |
| 117 | // ------------------------------------------------- |
| 118 | |
| 119 | func _c_to_proto_Address(address C.isDevice_Address) *pb_device.Device { |
| 120 | var device *pb_device.Device |
| 121 | |
| 122 | // Identify the address type to assign |
| 123 | switch address.Type { |
| 124 | case C.MAC: |
| 125 | device.Address = &pb_device.Device_MacAddress{ |
| 126 | MacAddress: C.GoString(address.Value), |
| 127 | } |
| 128 | break |
| 129 | case C.IPV4: |
| 130 | device.Address = &pb_device.Device_Ipv4Address{ |
| 131 | Ipv4Address: C.GoString(address.Value), |
| 132 | } |
| 133 | break |
| 134 | case C.IPV6: |
| 135 | device.Address = &pb_device.Device_Ipv6Address{ |
| 136 | Ipv6Address: C.GoString(address.Value), |
| 137 | } |
| 138 | break |
| 139 | case C.HOST_AND_PORT: |
| 140 | device.Address = &pb_device.Device_HostAndPort{ |
| 141 | HostAndPort: C.GoString(address.Value), |
| 142 | } |
| 143 | break |
| 144 | } |
| 145 | |
| 146 | return device |
| 147 | } |
| 148 | |
| 149 | // ------------------------------------------------- |
| 150 | // Protobuf to C conversion methods |
| 151 | // ------------------------------------------------- |
| 152 | |
| 153 | func _proto_to_c_Adapters(instances []*pb_adapter.Adapter) C.AdapterArray { |
| 154 | // TODO: not implemented |
| 155 | var result C.AdapterArray |
| 156 | return result |
| 157 | } |
| 158 | func _proto_to_c_LogicalDevices(instances []*pb_logical_device.LogicalDevice) C.LogicalDeviceArray { |
| 159 | // TODO: not implemented |
| 160 | var result C.LogicalDeviceArray |
| 161 | return result |
| 162 | } |
| 163 | func _proto_to_c_DeviceTypes(instances []*pb_device.DeviceType) C.DeviceTypeArray { |
| 164 | // TODO: not implemented |
| 165 | var result C.DeviceTypeArray |
| 166 | return result |
| 167 | } |
| 168 | func _proto_to_c_AlarmFilters(instances []*pb.AlarmFilter) C.AlarmFilterArray { |
| 169 | // TODO: not implemented |
| 170 | var result C.AlarmFilterArray |
| 171 | return result |
| 172 | } |
| 173 | func _proto_to_c_DeviceGroups(instances []*pb.DeviceGroup) C.DeviceGroupArray { |
| 174 | // TODO: not implemented |
| 175 | var result C.DeviceGroupArray |
| 176 | return result |
| 177 | } |
| 178 | func _proto_to_c_ProxyAddress(proxyAddress *pb_device.Device_ProxyAddress) *C.Device_ProxyAddress { |
| 179 | // TODO: not implemented |
| 180 | var result *C.Device_ProxyAddress |
| 181 | defer C.free(unsafe.Pointer(result)) |
| 182 | return result |
| 183 | } |
| 184 | func _proto_to_c_Ports(ports []*pb_device.Port) C.PortArray { |
| 185 | // TODO: not implemented |
| 186 | var result C.PortArray |
| 187 | return result |
| 188 | } |
| 189 | func _proto_to_c_Flows(flows *pb_openflow.Flows) *C.Flows { |
| 190 | // TODO: not implemented |
| 191 | var result *C.Flows |
| 192 | defer C.free(unsafe.Pointer(result)) |
| 193 | return result |
| 194 | } |
| 195 | func _proto_to_c_FlowGroups(groups *pb_openflow.FlowGroups) *C.FlowGroups { |
| 196 | // TODO: not implemented |
| 197 | var result *C.FlowGroups |
| 198 | defer C.free(unsafe.Pointer(result)) |
| 199 | return result |
| 200 | } |
| 201 | func _proto_to_c_PmConfigs(configs *pb_device.PmConfigs) *C.PmConfigs { |
| 202 | // TODO: not implemented |
| 203 | var result *C.PmConfigs |
| 204 | defer C.free(unsafe.Pointer(result)) |
| 205 | return result |
| 206 | } |
| 207 | func _proto_to_c_Custom(configs *pb_any.Any) *C.Any { |
| 208 | // TODO: not implemented |
| 209 | var result *C.Any |
| 210 | defer C.free(unsafe.Pointer(result)) |
| 211 | return result |
| 212 | } |
| 213 | func _proto_to_c_HealthStatus(health *pb_health.HealthStatus) C.HealthStatus { |
| 214 | var result C.HealthStatus |
| 215 | |
| 216 | var c_string *C.char |
| 217 | defer C.free(unsafe.Pointer(c_string)) |
| 218 | |
| 219 | if c_string = C.CString(health.GetState().String()); c_string != nil { |
| 220 | result.State = c_string |
| 221 | } |
| 222 | |
| 223 | return result |
| 224 | } |
| 225 | |
| 226 | func _proto_to_c_VolthaInstances(instances []*pb.VolthaInstance) C.VolthaInstanceArray { |
| 227 | var result C.VolthaInstanceArray |
| 228 | var c_string *C.char |
| 229 | var c_voltha_instance C.VolthaInstance |
| 230 | defer C.free(unsafe.Pointer(c_string)) |
| 231 | |
| 232 | sizeof := unsafe.Sizeof(c_voltha_instance) |
| 233 | count := len(instances) |
| 234 | result.size = C.int(count) |
| 235 | |
| 236 | c_items := C.malloc(C.size_t(result.size) * C.size_t(sizeof)) |
| 237 | defer C.free(unsafe.Pointer(c_items)) |
| 238 | |
| 239 | // Array to the allocated space |
| 240 | c_array := (*[1<<30 - 1]C.VolthaInstance)(c_items) |
| 241 | |
| 242 | for index, value := range instances { |
| 243 | if c_string = C.CString(value.GetInstanceId()); c_string != nil { |
| 244 | c_voltha_instance.InstanceId = c_string |
| 245 | } |
| 246 | if c_string = C.CString(value.GetVersion()); c_string != nil { |
| 247 | c_voltha_instance.Version = c_string |
| 248 | } |
| 249 | if c_string = C.CString(value.GetLogLevel().String()); c_string != nil { |
| 250 | c_voltha_instance.LogLevel = c_string |
| 251 | } |
| 252 | c_voltha_instance.Health = _proto_to_c_HealthStatus(value.GetHealth()) |
| 253 | c_voltha_instance.Adapters = _proto_to_c_Adapters(value.GetAdapters()) |
| 254 | c_voltha_instance.LogicalDevices = _proto_to_c_LogicalDevices(value.GetLogicalDevices()) |
| 255 | c_voltha_instance.Devices = _proto_to_c_Devices(value.GetDevices()) |
| 256 | c_voltha_instance.DeviceTypes = _proto_to_c_DeviceTypes(value.GetDeviceTypes()) |
| 257 | c_voltha_instance.DeviceGroups = _proto_to_c_DeviceGroups(value.GetDeviceGroups()) |
| 258 | c_voltha_instance.AlarmFilters = _proto_to_c_AlarmFilters(value.GetAlarmFilters()) |
| 259 | |
| 260 | c_array[index] = c_voltha_instance |
| 261 | } |
| 262 | |
| 263 | result.items = (*C.VolthaInstance)(unsafe.Pointer(c_array)) |
| 264 | |
| 265 | return result |
| 266 | } |
| 267 | func _proto_to_c_Devices(instances []*pb_device.Device) C.DeviceArray { |
| 268 | var result C.DeviceArray |
| 269 | var c_string *C.char |
| 270 | var c_device_instance C.Device |
| 271 | defer C.free(unsafe.Pointer(c_string)) |
| 272 | |
| 273 | sizeof := unsafe.Sizeof(c_device_instance) |
| 274 | count := len(instances) |
| 275 | result.size = C.int(count) |
| 276 | |
| 277 | c_items := C.malloc(C.size_t(result.size) * C.size_t(sizeof)) |
| 278 | defer C.free(unsafe.Pointer(c_items)) |
| 279 | |
| 280 | c_array := (*[1<<30 - 1]C.Device)(c_items) |
| 281 | |
| 282 | for index, value := range instances { |
| 283 | c_array[index] = _proto_to_c_Device(value) |
| 284 | } |
| 285 | |
| 286 | result.items = (*C.Device)(unsafe.Pointer(c_array)) |
| 287 | |
| 288 | return result |
| 289 | } |
| 290 | func _proto_to_c_Voltha(voltha *pb.Voltha) C.Voltha { |
| 291 | var result C.Voltha |
| 292 | var c_string *C.char |
| 293 | defer C.free(unsafe.Pointer(c_string)) |
| 294 | |
| 295 | if c_string = C.CString(voltha.GetVersion()); c_string != nil { |
| 296 | result.Version = c_string |
| 297 | } |
| 298 | if c_string = C.CString(voltha.GetLogLevel().String()); c_string != nil { |
| 299 | result.LogLevel = c_string |
| 300 | } |
| 301 | |
| 302 | result.Instances = _proto_to_c_VolthaInstances(voltha.GetInstances()) |
| 303 | result.Adapters = _proto_to_c_Adapters(voltha.GetAdapters()) |
| 304 | result.LogicalDevices = _proto_to_c_LogicalDevices(voltha.GetLogicalDevices()) |
| 305 | result.Devices = _proto_to_c_Devices(voltha.GetDevices()) |
| 306 | result.DeviceGroups = _proto_to_c_DeviceGroups(voltha.GetDeviceGroups()) |
| 307 | |
| 308 | return result |
| 309 | } |
| 310 | |
| 311 | func _proto_to_c_Address(device *pb_device.Device) C.isDevice_Address { |
| 312 | var address C.isDevice_Address |
| 313 | var c_string *C.char |
| 314 | defer C.free(unsafe.Pointer(c_string)) |
| 315 | |
| 316 | switch device.GetAddress().(type) { |
| 317 | case *pb_device.Device_MacAddress: |
| 318 | address.Type = C.MAC |
| 319 | c_string = C.CString(device.GetMacAddress()) |
| 320 | address.Value = c_string |
| 321 | case *pb_device.Device_Ipv4Address: |
| 322 | address.Type = C.IPV4 |
| 323 | c_string = C.CString(device.GetIpv4Address()) |
| 324 | address.Value = c_string |
| 325 | case *pb_device.Device_Ipv6Address: |
| 326 | address.Type = C.IPV6 |
| 327 | c_string = C.CString(device.GetIpv6Address()) |
| 328 | address.Value = c_string |
| 329 | case *pb_device.Device_HostAndPort: |
| 330 | address.Type = C.HOST_AND_PORT |
| 331 | c_string = C.CString(device.GetHostAndPort()) |
| 332 | address.Value = c_string |
| 333 | } |
| 334 | return address |
| 335 | } |
| 336 | |
| 337 | func _proto_to_c_Device(device *pb_device.Device) C.Device { |
| 338 | var result C.Device |
| 339 | var c_string *C.char |
| 340 | defer C.free(unsafe.Pointer(c_string)) |
| 341 | |
| 342 | if c_string = C.CString(device.GetId()); c_string != nil { |
| 343 | result.Id = c_string |
| 344 | } |
| 345 | if c_string = C.CString(device.GetType()); c_string != nil { |
| 346 | result.Type = c_string |
| 347 | } |
| 348 | if device.GetRoot() { |
| 349 | result.Root = C.int(1) |
| 350 | } else { |
| 351 | result.Root = C.int(0) |
| 352 | } |
| 353 | if c_string = C.CString(device.GetParentId()); c_string != nil { |
| 354 | result.ParentId = c_string |
| 355 | } |
| 356 | |
| 357 | result.ParentPortNo = C.uint32_t(device.GetParentPortNo()) |
| 358 | |
| 359 | if c_string = C.CString(device.GetVendor()); c_string != nil { |
| 360 | result.Vendor = c_string |
| 361 | } |
| 362 | if c_string = C.CString(device.GetModel()); c_string != nil { |
| 363 | result.Model = c_string |
| 364 | } |
| 365 | if c_string = C.CString(device.GetHardwareVersion()); c_string != nil { |
| 366 | result.HardwareVersion = c_string |
| 367 | } |
| 368 | if c_string = C.CString(device.GetFirmwareVersion()); c_string != nil { |
| 369 | result.FirmwareVersion = c_string |
| 370 | } |
| 371 | if c_string = C.CString(device.GetSoftwareVersion()); c_string != nil { |
| 372 | result.SoftwareVersion = c_string |
| 373 | } |
| 374 | if c_string = C.CString(device.GetSerialNumber()); c_string != nil { |
| 375 | result.SerialNumber = c_string |
| 376 | } |
| 377 | if c_string = C.CString(device.GetAdapter()); c_string != nil { |
| 378 | result.Adapter = c_string |
| 379 | } |
| 380 | |
| 381 | result.Vlan = C.uint32_t(device.GetVlan()) |
| 382 | result.ProxyAddress = _proto_to_c_ProxyAddress(device.GetProxyAddress()) |
| 383 | |
| 384 | if c_string = C.CString(device.GetAdminState().String()); c_string != nil { |
| 385 | result.AdminState = c_string |
| 386 | } |
| 387 | if c_string = C.CString(device.GetOperStatus().String()); c_string != nil { |
| 388 | result.OperStatus = c_string |
| 389 | } |
| 390 | if c_string = C.CString(device.GetReason()); c_string != nil { |
| 391 | result.Reason = c_string |
| 392 | } |
| 393 | if c_string = C.CString(device.GetConnectStatus().String()); c_string != nil { |
| 394 | result.ConnectStatus = c_string |
| 395 | } |
| 396 | |
| 397 | result.Custom = _proto_to_c_Custom(device.GetCustom()) |
| 398 | result.Ports = _proto_to_c_Ports(device.GetPorts()) |
| 399 | result.Flows = _proto_to_c_Flows(device.GetFlows()) |
| 400 | result.FlowGroups = _proto_to_c_FlowGroups(device.GetFlowGroups()) |
| 401 | result.PmConfigs = _proto_to_c_PmConfigs(device.GetPmConfigs()) |
| 402 | result.Address = _proto_to_c_Address(device) |
| 403 | |
| 404 | return result |
| 405 | } |
| 406 | |
| 407 | // --------------------------------------------------------- |
| 408 | // Exported methods accessible through the shared library |
| 409 | // --------------------------------------------------------- |
| 410 | |
| 411 | //export GetHealthStatus |
| 412 | func GetHealthStatus() C.HealthStatus { |
| 413 | var output *pb_health.HealthStatus |
| 414 | var err error |
| 415 | |
| 416 | if output, err = HealthClient.GetHealthStatus(context.Background(), &empty.Empty{}); output == nil || err != nil { |
| 417 | log.Fatalf("Failed to retrieve health status: %s", err.Error()) |
| 418 | } |
| 419 | |
| 420 | return _proto_to_c_HealthStatus(output) |
| 421 | } |
| 422 | |
| 423 | //export GetVoltha |
| 424 | func GetVoltha() C.Voltha { |
| 425 | var output *pb.Voltha |
| 426 | var err error |
| 427 | if output, err = VolthaGlobalClient.GetVoltha(context.Background(), &empty.Empty{}); output == nil || err != nil { |
| 428 | log.Fatalf("Failed to retrieve voltha information: %s", err.Error()) |
| 429 | } |
| 430 | |
| 431 | return _proto_to_c_Voltha(output) |
| 432 | } |
| 433 | |
| 434 | //export ListDevices |
| 435 | func ListDevices() C.DeviceArray { |
| 436 | var output *pb_device.Devices |
| 437 | var err error |
| 438 | if output, err = VolthaGlobalClient.ListDevices(context.Background(), &empty.Empty{}); |
| 439 | output == nil || err != nil { |
| 440 | log.Fatalf("Failed to retrieve voltha information: %s", err.Error()) |
| 441 | } |
| 442 | |
| 443 | return _proto_to_c_Devices(output.Items) |
| 444 | } |
| 445 | |
| 446 | //export ListVolthaInstances |
| 447 | func ListVolthaInstances() *C.char { |
| 448 | return nil |
| 449 | } |
| 450 | |
| 451 | //export ListLogicalDevices |
| 452 | func ListLogicalDevices() *C.char { |
| 453 | return nil |
| 454 | } |
| 455 | |
| 456 | //export GetLogicalDevice |
| 457 | func GetLogicalDevice(input *C.char) *C.char { |
| 458 | return nil |
| 459 | } |
| 460 | |
| 461 | //export ListLogicalDevicePorts |
| 462 | func ListLogicalDevicePorts(input *C.char) *C.char { |
| 463 | return nil |
| 464 | } |
| 465 | |
| 466 | //export ListLogicalDeviceFlows |
| 467 | func ListLogicalDeviceFlows(input *C.char) *C.char { |
| 468 | return nil |
| 469 | } |
| 470 | |
| 471 | //export CreateDevice |
| 472 | func CreateDevice(input C.Device) C.Device { |
| 473 | log.Printf("Incoming C Device - type:%v, address_type: %v, address_value:%s", |
| 474 | C.GoString(input.Type), |
| 475 | C.int(input.Address.Type), |
| 476 | C.GoString(input.Address.Value), |
| 477 | ) |
| 478 | |
| 479 | device := _c_to_proto_Address(input.Address) |
| 480 | device.Type = C.GoString(input.Type) |
| 481 | |
| 482 | var output *pb_device.Device |
| 483 | var err error |
| 484 | |
| 485 | if output, err = VolthaGlobalClient.CreateDevice(context.Background(), device); |
| 486 | output == nil || err != nil { |
| 487 | log.Fatalf("Failed to create device: %s", err.Error()) |
| 488 | } |
| 489 | |
| 490 | return _proto_to_c_Device(output) |
| 491 | } |
| 492 | |
| 493 | // Debugging code |
| 494 | func TestSerialize() { |
| 495 | var object C.Device |
| 496 | |
| 497 | object.Type = C.CString("simulated_olt") |
| 498 | object.Address.Type = 3 |
| 499 | object.Address.Value = C.CString("172.16.1.233:123") |
| 500 | |
| 501 | //xmlObject, _ := xml.Marshal(object) |
| 502 | // |
| 503 | //log.Printf("object: %+v", string(xmlObject)) |
| 504 | |
| 505 | CreateDevice(object) |
| 506 | } |
| 507 | |
| 508 | func main() { |
| 509 | // We need the main function to make possible |
| 510 | // CGO compiler to compile the package as C shared library |
| 511 | //TestSerialize() |
| 512 | } |