blob: 96f52ddfb4ba6f93662002ea3220eb1c8b3fb559 [file] [log] [blame]
/*
* Copyright 2017-present Open Networking Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
//package voltha
package main
/*
#include <stdlib.h>
#include "voltha-defs.h"
*/
import "C"
import (
"log"
"golang.org/x/net/context"
"google.golang.org/grpc"
"github.com/golang/protobuf/ptypes/empty"
"github.com/hashicorp/consul/api"
pb "github.com/opencord/voltha/netconf/translator/voltha"
pb_health "github.com/opencord/voltha/netconf/translator/voltha/health"
pb_device "github.com/opencord/voltha/netconf/translator/voltha/device"
pb_adapter "github.com/opencord/voltha/netconf/translator/voltha/adapter"
pb_logical_device "github.com/opencord/voltha/netconf/translator/voltha/logical_device"
pb_openflow "github.com/opencord/voltha/netconf/translator/voltha/openflow_13"
pb_any "github.com/golang/protobuf/ptypes/any"
"unsafe"
"fmt"
)
const (
default_consul_address = "10.100.198.220:8500"
default_grpc_address = "localhost:50555"
grpc_service_name = "voltha-grpc"
)
var (
GrpcConn *grpc.ClientConn = nil
VolthaGlobalClient pb.VolthaGlobalServiceClient = nil
HealthClient pb_health.HealthServiceClient = nil
ConsulClient *api.Client = nil
GrpcServiceAddress string = "localhost:50555"
)
func init() {
ConsulClient = connect_to_consul(default_consul_address)
GrpcServiceAddress = get_consul_service_address(grpc_service_name)
GrpcConn = connect_to_grpc(GrpcServiceAddress)
VolthaGlobalClient = pb.NewVolthaGlobalServiceClient(GrpcConn)
HealthClient = pb_health.NewHealthServiceClient(GrpcConn)
}
func connect_to_consul(consul_address string) *api.Client {
cfg := api.Config{Address: consul_address }
log.Printf("Connecting to consul - address: %s", consul_address)
client, err := api.NewClient(&cfg)
if err != nil {
panic(err)
}
log.Printf("Connected to consul - address: %s", consul_address)
return client
}
func get_consul_service_address(service_name string) string {
var service []*api.CatalogService
var err error
log.Printf("Getting consul service - name:%s", service_name)
if service, _, _ = ConsulClient.Catalog().Service(service_name, "", nil); err != nil {
panic(err)
}
address := fmt.Sprintf("%s:%d", service[0].ServiceAddress, service[0].ServicePort)
log.Printf("Got consul service - name:%s, address:%s", service_name, address)
return address
}
func connect_to_grpc(grpc_address string) *grpc.ClientConn {
var err error
var client *grpc.ClientConn
log.Printf("Connecting to grpc - address: %s", grpc_address)
// Set up a connection to the server.
client, err = grpc.Dial(grpc_address, grpc.WithInsecure())
if err != nil {
log.Fatalf("did not connect: %s", err.Error())
}
log.Printf("Connected to grpc - address: %s", grpc_address)
return client
}
// Utility methods
// -------------------------------------------------
// C to Protobuf conversion methods
// -------------------------------------------------
func _c_to_proto_Address(address C.isDevice_Address) *pb_device.Device {
var device *pb_device.Device
// Identify the address type to assign
switch address.Type {
case C.MAC:
device.Address = &pb_device.Device_MacAddress{
MacAddress: C.GoString(address.Value),
}
break
case C.IPV4:
device.Address = &pb_device.Device_Ipv4Address{
Ipv4Address: C.GoString(address.Value),
}
break
case C.IPV6:
device.Address = &pb_device.Device_Ipv6Address{
Ipv6Address: C.GoString(address.Value),
}
break
case C.HOST_AND_PORT:
device.Address = &pb_device.Device_HostAndPort{
HostAndPort: C.GoString(address.Value),
}
break
}
return device
}
// -------------------------------------------------
// Protobuf to C conversion methods
// -------------------------------------------------
func _proto_to_c_Adapters(instances []*pb_adapter.Adapter) C.AdapterArray {
// TODO: not implemented
var result C.AdapterArray
return result
}
func _proto_to_c_LogicalDevices(instances []*pb_logical_device.LogicalDevice) C.LogicalDeviceArray {
// TODO: not implemented
var result C.LogicalDeviceArray
return result
}
func _proto_to_c_DeviceTypes(instances []*pb_device.DeviceType) C.DeviceTypeArray {
// TODO: not implemented
var result C.DeviceTypeArray
return result
}
func _proto_to_c_AlarmFilters(instances []*pb.AlarmFilter) C.AlarmFilterArray {
// TODO: not implemented
var result C.AlarmFilterArray
return result
}
func _proto_to_c_DeviceGroups(instances []*pb.DeviceGroup) C.DeviceGroupArray {
// TODO: not implemented
var result C.DeviceGroupArray
return result
}
func _proto_to_c_ProxyAddress(proxyAddress *pb_device.Device_ProxyAddress) *C.Device_ProxyAddress {
// TODO: not implemented
var result *C.Device_ProxyAddress
defer C.free(unsafe.Pointer(result))
return result
}
func _proto_to_c_Ports(ports []*pb_device.Port) C.PortArray {
// TODO: not implemented
var result C.PortArray
return result
}
func _proto_to_c_Flows(flows *pb_openflow.Flows) *C.Flows {
// TODO: not implemented
var result *C.Flows
defer C.free(unsafe.Pointer(result))
return result
}
func _proto_to_c_FlowGroups(groups *pb_openflow.FlowGroups) *C.FlowGroups {
// TODO: not implemented
var result *C.FlowGroups
defer C.free(unsafe.Pointer(result))
return result
}
func _proto_to_c_PmConfigs(configs *pb_device.PmConfigs) *C.PmConfigs {
// TODO: not implemented
var result *C.PmConfigs
defer C.free(unsafe.Pointer(result))
return result
}
func _proto_to_c_Custom(configs *pb_any.Any) *C.Any {
// TODO: not implemented
var result *C.Any
defer C.free(unsafe.Pointer(result))
return result
}
func _proto_to_c_HealthStatus(health *pb_health.HealthStatus) C.HealthStatus {
var result C.HealthStatus
var c_string *C.char
defer C.free(unsafe.Pointer(c_string))
if c_string = C.CString(health.GetState().String()); c_string != nil {
result.State = c_string
}
return result
}
func _proto_to_c_VolthaInstances(instances []*pb.VolthaInstance) C.VolthaInstanceArray {
var result C.VolthaInstanceArray
var c_string *C.char
var c_voltha_instance C.VolthaInstance
defer C.free(unsafe.Pointer(c_string))
sizeof := unsafe.Sizeof(c_voltha_instance)
count := len(instances)
result.size = C.int(count)
c_items := C.malloc(C.size_t(result.size) * C.size_t(sizeof))
defer C.free(unsafe.Pointer(c_items))
// Array to the allocated space
c_array := (*[1<<30 - 1]C.VolthaInstance)(c_items)
for index, value := range instances {
if c_string = C.CString(value.GetInstanceId()); c_string != nil {
c_voltha_instance.InstanceId = c_string
}
if c_string = C.CString(value.GetVersion()); c_string != nil {
c_voltha_instance.Version = c_string
}
if c_string = C.CString(value.GetLogLevel().String()); c_string != nil {
c_voltha_instance.LogLevel = c_string
}
c_voltha_instance.Health = _proto_to_c_HealthStatus(value.GetHealth())
c_voltha_instance.Adapters = _proto_to_c_Adapters(value.GetAdapters())
c_voltha_instance.LogicalDevices = _proto_to_c_LogicalDevices(value.GetLogicalDevices())
c_voltha_instance.Devices = _proto_to_c_Devices(value.GetDevices())
c_voltha_instance.DeviceTypes = _proto_to_c_DeviceTypes(value.GetDeviceTypes())
c_voltha_instance.DeviceGroups = _proto_to_c_DeviceGroups(value.GetDeviceGroups())
c_voltha_instance.AlarmFilters = _proto_to_c_AlarmFilters(value.GetAlarmFilters())
c_array[index] = c_voltha_instance
}
result.items = (*C.VolthaInstance)(unsafe.Pointer(c_array))
return result
}
func _proto_to_c_Devices(instances []*pb_device.Device) C.DeviceArray {
var result C.DeviceArray
var c_string *C.char
var c_device_instance C.Device
defer C.free(unsafe.Pointer(c_string))
sizeof := unsafe.Sizeof(c_device_instance)
count := len(instances)
result.size = C.int(count)
c_items := C.malloc(C.size_t(result.size) * C.size_t(sizeof))
defer C.free(unsafe.Pointer(c_items))
c_array := (*[1<<30 - 1]C.Device)(c_items)
for index, value := range instances {
c_array[index] = _proto_to_c_Device(value)
}
result.items = (*C.Device)(unsafe.Pointer(c_array))
return result
}
func _proto_to_c_Voltha(voltha *pb.Voltha) C.Voltha {
var result C.Voltha
var c_string *C.char
defer C.free(unsafe.Pointer(c_string))
if c_string = C.CString(voltha.GetVersion()); c_string != nil {
result.Version = c_string
}
if c_string = C.CString(voltha.GetLogLevel().String()); c_string != nil {
result.LogLevel = c_string
}
result.Instances = _proto_to_c_VolthaInstances(voltha.GetInstances())
result.Adapters = _proto_to_c_Adapters(voltha.GetAdapters())
result.LogicalDevices = _proto_to_c_LogicalDevices(voltha.GetLogicalDevices())
result.Devices = _proto_to_c_Devices(voltha.GetDevices())
result.DeviceGroups = _proto_to_c_DeviceGroups(voltha.GetDeviceGroups())
return result
}
func _proto_to_c_Address(device *pb_device.Device) C.isDevice_Address {
var address C.isDevice_Address
var c_string *C.char
defer C.free(unsafe.Pointer(c_string))
switch device.GetAddress().(type) {
case *pb_device.Device_MacAddress:
address.Type = C.MAC
c_string = C.CString(device.GetMacAddress())
address.Value = c_string
case *pb_device.Device_Ipv4Address:
address.Type = C.IPV4
c_string = C.CString(device.GetIpv4Address())
address.Value = c_string
case *pb_device.Device_Ipv6Address:
address.Type = C.IPV6
c_string = C.CString(device.GetIpv6Address())
address.Value = c_string
case *pb_device.Device_HostAndPort:
address.Type = C.HOST_AND_PORT
c_string = C.CString(device.GetHostAndPort())
address.Value = c_string
}
return address
}
func _proto_to_c_Device(device *pb_device.Device) C.Device {
var result C.Device
var c_string *C.char
defer C.free(unsafe.Pointer(c_string))
if c_string = C.CString(device.GetId()); c_string != nil {
result.Id = c_string
}
if c_string = C.CString(device.GetType()); c_string != nil {
result.Type = c_string
}
if device.GetRoot() {
result.Root = C.int(1)
} else {
result.Root = C.int(0)
}
if c_string = C.CString(device.GetParentId()); c_string != nil {
result.ParentId = c_string
}
result.ParentPortNo = C.uint32_t(device.GetParentPortNo())
if c_string = C.CString(device.GetVendor()); c_string != nil {
result.Vendor = c_string
}
if c_string = C.CString(device.GetModel()); c_string != nil {
result.Model = c_string
}
if c_string = C.CString(device.GetHardwareVersion()); c_string != nil {
result.HardwareVersion = c_string
}
if c_string = C.CString(device.GetFirmwareVersion()); c_string != nil {
result.FirmwareVersion = c_string
}
if c_string = C.CString(device.GetSoftwareVersion()); c_string != nil {
result.SoftwareVersion = c_string
}
if c_string = C.CString(device.GetSerialNumber()); c_string != nil {
result.SerialNumber = c_string
}
if c_string = C.CString(device.GetAdapter()); c_string != nil {
result.Adapter = c_string
}
result.Vlan = C.uint32_t(device.GetVlan())
result.ProxyAddress = _proto_to_c_ProxyAddress(device.GetProxyAddress())
if c_string = C.CString(device.GetAdminState().String()); c_string != nil {
result.AdminState = c_string
}
if c_string = C.CString(device.GetOperStatus().String()); c_string != nil {
result.OperStatus = c_string
}
if c_string = C.CString(device.GetReason()); c_string != nil {
result.Reason = c_string
}
if c_string = C.CString(device.GetConnectStatus().String()); c_string != nil {
result.ConnectStatus = c_string
}
result.Custom = _proto_to_c_Custom(device.GetCustom())
result.Ports = _proto_to_c_Ports(device.GetPorts())
result.Flows = _proto_to_c_Flows(device.GetFlows())
result.FlowGroups = _proto_to_c_FlowGroups(device.GetFlowGroups())
result.PmConfigs = _proto_to_c_PmConfigs(device.GetPmConfigs())
result.Address = _proto_to_c_Address(device)
return result
}
// ---------------------------------------------------------
// Exported methods accessible through the shared library
// ---------------------------------------------------------
//export GetHealthStatus
func GetHealthStatus() C.HealthStatus {
var output *pb_health.HealthStatus
var err error
if output, err = HealthClient.GetHealthStatus(context.Background(), &empty.Empty{}); output == nil || err != nil {
log.Fatalf("Failed to retrieve health status: %s", err.Error())
}
return _proto_to_c_HealthStatus(output)
}
//export GetVoltha
func GetVoltha() C.Voltha {
var output *pb.Voltha
var err error
if output, err = VolthaGlobalClient.GetVoltha(context.Background(), &empty.Empty{}); output == nil || err != nil {
log.Fatalf("Failed to retrieve voltha information: %s", err.Error())
}
return _proto_to_c_Voltha(output)
}
//export ListDevices
func ListDevices() C.DeviceArray {
var output *pb_device.Devices
var err error
if output, err = VolthaGlobalClient.ListDevices(context.Background(), &empty.Empty{});
output == nil || err != nil {
log.Fatalf("Failed to retrieve voltha information: %s", err.Error())
}
return _proto_to_c_Devices(output.Items)
}
//export ListVolthaInstances
func ListVolthaInstances() *C.char {
return nil
}
//export ListLogicalDevices
func ListLogicalDevices() *C.char {
return nil
}
//export GetLogicalDevice
func GetLogicalDevice(input *C.char) *C.char {
return nil
}
//export ListLogicalDevicePorts
func ListLogicalDevicePorts(input *C.char) *C.char {
return nil
}
//export ListLogicalDeviceFlows
func ListLogicalDeviceFlows(input *C.char) *C.char {
return nil
}
//export CreateDevice
func CreateDevice(input C.Device) C.Device {
log.Printf("Incoming C Device - type:%v, address_type: %v, address_value:%s",
C.GoString(input.Type),
C.int(input.Address.Type),
C.GoString(input.Address.Value),
)
device := _c_to_proto_Address(input.Address)
device.Type = C.GoString(input.Type)
var output *pb_device.Device
var err error
if output, err = VolthaGlobalClient.CreateDevice(context.Background(), device);
output == nil || err != nil {
log.Fatalf("Failed to create device: %s", err.Error())
}
return _proto_to_c_Device(output)
}
// Debugging code
func TestSerialize() {
var object C.Device
object.Type = C.CString("simulated_olt")
object.Address.Type = 3
object.Address.Value = C.CString("172.16.1.233:123")
//xmlObject, _ := xml.Marshal(object)
//
//log.Printf("object: %+v", string(xmlObject))
CreateDevice(object)
}
func main() {
// We need the main function to make possible
// CGO compiler to compile the package as C shared library
//TestSerialize()
}