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