Commit 26e604c7 authored by Mohamad Rahhal's avatar Mohamad Rahhal
Browse files

Logical-Resources- component -

- Corrected methods name- removed some methods, trying to allign with the design proposed
parent 2792d9c8
Loading
Loading
Loading
Loading
+15 −55
Original line number Diff line number Diff line
@@ -17,18 +17,12 @@ package logical_resources;

service LogicalResources {
    rpc AddResources (ConfigParameters) returns (Response) {}
    rpc GetAvailableResource (Empty) returns (ResourceList) {}
    rpc GetAvailableResources (Empty) returns (ResourceList) {}
    rpc ReserveResource (ResourceReservation) returns (Success) {}
    rpc DeleteResource (ResourceReservation) returns (Success) {}
    rpc GetAllocatedResources (Empty) returns (ResourceList) {}
    rpc ReleaseResource (ResourceReservation) returns (Success) {}
    rpc GetReservedResources (Empty) returns (ResourceList) {}
    rpc GetResourceOwner (Value) returns (FabricId) {}
    rpc GetResourcesByType (ResourceTypeQuery) returns (TypedResourceList) {}

    // old ones
    rpc AddDevice (DeviceConfig) returns (Response) {}
    rpc DeleteDevice (DeviceId) returns (Response) {}
    rpc GetDeviceConfig (DeviceId) returns (DeviceConfig) {}
    rpc GetDatabase (Empty) returns (Database) {}
}

message Empty {}
@@ -77,62 +71,28 @@ message TypedResourceList {
}

message ConfigParameters {
    string device_uuid = 1 [json_name = "device-uuid"];
    string endpoint_uuid = 2 [json_name = "endpoint-uuid"];
    string ip_address = 3 [json_name = "ip-address"];
    uint32 vlan_tag = 4 [json_name = "vlan-tag"];
    string mac_address = 5 [json_name = "mac-address"];
    uint32 asn = 6;
    string router_id = 7 [json_name = "router-id"];
    uint32 vni = 8;
    string local_address = 9 [json_name = "local.address"];
    uint32 port = 10;
    string bridge = 11;
    string interface = 12;
    string remote_address = 13 [json_name = "remote.address"];
    uint32 remote_as = 14 [json_name = "remote.as"];
    string local_role = 15 [json_name = "local.role"];
    string routing_table = 16 [json_name = "routing-table"];
    bool multihop = 17;
    string afi = 18 [json_name = "address-families"];
    string name = 19;
}

message DeviceConfig {
    string device_uuid = 1 [json_name = "device-uuid"];
    string endpoint_uuid = 2 [json_name = "endpoint-uuid"];
    string ip_address = 3 [json_name = "ip-address"];
    uint32 vlan_tag = 4 [json_name = "vlan-tag"];
    string mac_address = 5 [json_name = "mac-address"];
    string device_uuid = 1;
    string endpoint_uuid = 2;
    string ip_address = 3;
    uint32 vlan_tag = 4;
    string mac_address = 5;
    uint32 asn = 6;
    string router_id = 7 [json_name = "router-id"];
    string router_id = 7;
    uint32 vni = 8;
    string local_address = 9 [json_name = "local.address"];
    string local_address = 9;
    uint32 port = 10;
    string bridge = 11;
    string interface = 12;
    string remote_address = 13 [json_name = "remote.address"];
    uint32 remote_as = 14 [json_name = "remote.as"];
    string local_role = 15 [json_name = "local.role"];
    string routing_table = 16 [json_name = "routing-table"];
    string remote_address = 13;
    uint32 remote_as = 14;
    string local_role = 15;
    string routing_table = 16;
    bool multihop = 17;
    string afi = 18 [json_name = "address-families"];
    string afi = 18;
    string name = 19;
}

message DeviceId {
    string device_uuid = 1;
}

message Response {
    bool success = 1;
    string message = 2;
}
 No newline at end of file

message Database {
    map<string, DeviceEndpoints> devices = 1;
}

message DeviceEndpoints {
    map<string, DeviceConfig> endpoints = 1;
}
 No newline at end of file
+12 −46
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@ import grpc, logging
from common.Constants import ServiceNameEnum
from common.Settings import get_service_host, get_service_port_grpc
from common.proto.logical_resources_pb2 import (
    ConfigParameters,
    Empty,
)
from common.proto.logical_resources_pb2_grpc import LogicalResourcesStub
@@ -56,12 +55,12 @@ class LogicalResourceClient:
        return response

    @RETRY_DECORATOR
    def GetAvailableResource(self, request=None):
    def GetAvailableResources(self, request=None):
        if request is None:
            request = Empty()
        LOGGER.debug('GetAvailableResource request: {:s}'.format(grpc_message_to_json_string(request)))
        response = self.stub.GetAvailableResource(request)
        LOGGER.debug('GetAvailableResource result: {:s}'.format(grpc_message_to_json_string(response)))
        LOGGER.debug('GetAvailableResources request: {:s}'.format(grpc_message_to_json_string(request)))
        response = self.stub.GetAvailableResources(request)
        LOGGER.debug('GetAvailableResources result: {:s}'.format(grpc_message_to_json_string(response)))
        return response

    @RETRY_DECORATOR
@@ -72,19 +71,19 @@ class LogicalResourceClient:
        return response

    @RETRY_DECORATOR
    def DeleteResource(self, request):
        LOGGER.debug('DeleteResource request: {:s}'.format(grpc_message_to_json_string(request)))
        response = self.stub.DeleteResource(request)
        LOGGER.debug('DeleteResource result: {:s}'.format(grpc_message_to_json_string(response)))
    def ReleaseResource(self, request):
        LOGGER.debug('ReleaseResource request: {:s}'.format(grpc_message_to_json_string(request)))
        response = self.stub.ReleaseResource(request)
        LOGGER.debug('ReleaseResource result: {:s}'.format(grpc_message_to_json_string(response)))
        return response

    @RETRY_DECORATOR
    def GetAllocatedResources(self, request=None):
    def GetReservedResources(self, request=None):
        if request is None:
            request = Empty()
        LOGGER.debug('GetAllocatedResources request: {:s}'.format(grpc_message_to_json_string(request)))
        response = self.stub.GetAllocatedResources(request)
        LOGGER.debug('GetAllocatedResources result: {:s}'.format(grpc_message_to_json_string(response)))
        LOGGER.debug('GetReservedResources request: {:s}'.format(grpc_message_to_json_string(request)))
        response = self.stub.GetReservedResources(request)
        LOGGER.debug('GetReservedResources result: {:s}'.format(grpc_message_to_json_string(response)))
        return response

    @RETRY_DECORATOR
@@ -100,36 +99,3 @@ class LogicalResourceClient:
        response = self.stub.GetResourcesByType(request)
        LOGGER.debug('GetResourcesByType result: {:s}'.format(grpc_message_to_json_string(response)))
        return response

    @RETRY_DECORATOR
    def GetDatabase(self, request=None):
        if request is None:
            request = Empty()
        LOGGER.debug('Get database request: {:s}'.format(grpc_message_to_json_string(request)))
        response = self.stub.GetDatabase(request)
        LOGGER.debug('get database result: {:s}'.format(grpc_message_to_json_string(response)))
        return response

    @RETRY_DECORATOR
    def AddDevice(self, request):
        return self.AddResources(ConfigParameters(
            device_uuid=request.device_uuid,
            endpoint_uuid=request.endpoint_uuid,
            ip_address=request.ip_address,
            vlan_tag=request.vlan_tag,
            mac_address=request.mac_address,
            asn=request.asn,
            router_id=request.router_id,
            vni=request.vni,
            local_address=request.local_address,
            port=request.port,
            bridge=request.bridge,
            interface=request.interface,
            remote_address=request.remote_address,
            remote_as=request.remote_as,
            local_role=request.local_role,
            routing_table=request.routing_table,
            multihop=request.multihop,
            afi=request.afi,
            name=request.name,
        ))
 No newline at end of file
+5 −76
Original line number Diff line number Diff line
import json
class Database:
    def __init__(self):
        "Creating the database to store things"
@@ -46,32 +45,6 @@ class Database:
        self._track_resource('asn', str(ASN) if ASN else '')
        self._track_resource('loopback', RouterID)

    # Backward-compatible alias kept while callers migrate to add_resources.
    def add_device(self, device_uuid, endpoint_uuid, ip_address, vlan_tag, mac_address, ASN, RouterID,
                   vni=None, local_address=None, port=None, bridge=None, interface=None, remote_address=None,
                   remote_as=None, local_role=None, routing_table=None, multihop=None, afi=None, name=None):
        self.add_resources(
            device_uuid,
            endpoint_uuid,
            ip_address,
            vlan_tag,
            mac_address,
            ASN,
            RouterID,
            vni=vni,
            local_address=local_address,
            port=port,
            bridge=bridge,
            interface=interface,
            remote_address=remote_address,
            remote_as=remote_as,
            local_role=local_role,
            routing_table=routing_table,
            multihop=multihop,
            afi=afi,
            name=name,
        )

    def get_full_db(self):
        "Return ALLL"
        return self.database
@@ -92,14 +65,14 @@ class Database:
        self.resources[key] = fabric_id
        return True, 'Resource reserved'

    def delete_resource(self, resource_type, resource_value):
    def release_resource(self, resource_type, resource_value):
        key = (resource_type, resource_value)
        if key not in self.resources:
            return False, 'Resource not found'
        del self.resources[key]
        return True, 'Resource deleted'
        self.resources[key] = ''
        return True, 'Resource released'

    def get_allocated_resources(self):
    def get_reserved_resources(self):
        return [
            (resource_type, resource_value, fabric_id)
            for (resource_type, resource_value), fabric_id in self.resources.items()
@@ -118,47 +91,3 @@ class Database:
            for (rtype, value), fabric_id in self.resources.items()
            if rtype == resource_type
        ]
 No newline at end of file
    
# --- DELETE ---
    def delete_device(self, device_uuid):
        """to remove the entire device"""
        if device_uuid in self.database:
            del self.database[device_uuid]

    def delete_endpoint(self, device_uuid, endpoint_uuid):
        """to remove a specific port/interface from a device"""
        if device_uuid in self.database and endpoint_uuid in self.database[device_uuid]:
            del self.database[device_uuid][endpoint_uuid]

    def delete_field(self, device_uuid, endpoint_uuid, field_name):
        """to delete or rest a specific field (mac_address, asn, router_id)+ clears lists"""
        if device_uuid in self.database and endpoint_uuid in self.database[device_uuid]:
            target = self.database[device_uuid][endpoint_uuid]
            if field_name in ["mac_address", "asn", "router_id"]:
                target[field_name] = None  
            elif field_name in ["ip_addresses", "vlan_tags"]:
                target[field_name] = []   


if __name__ == "__main__":
    db = Database()
    
    # Add info
    db.add_device("leaf2", "sfp1", "10.0.0.3/31", 10, "08:55:31:A1", 65102, "10.255.1.2")
    db.add_device("leaf1","sfp1", "10.0.0.3/31", 10, "08:55:31:A1", 65102, "10.255.1.2")
    db.add_device("leaf3","sfp2","10.1.7.199",177,"02:BB:09:CC", 65103,"10.255.0.1")
    
    import json
    print("\n--- DATABASE CONTENT ---")
    print(json.dumps(db.get_full_db(), indent=4))

    #Delete field asn
    db.delete_field("leaf2", "sfp1", "asn")
    db.delete_field("leaf2","sfp1","router_id")
# DELETE endpoint
    db.delete_endpoint("leaf3","sfp2")
    #Delete the entire leaf1 device
    db.delete_device("leaf1")

    print("\n--- AFTER DELETIONS  ---")
    print(json.dumps(db.get_full_db(), indent=4))
 No newline at end of file
+6 −98
Original line number Diff line number Diff line
@@ -4,9 +4,6 @@ from common.proto.logical_resources_pb2 import (
    Response,
    Success,
    ConfigParameters,
    DeviceConfig,
    Database,
    DeviceEndpoints,
    ResourceList,
    ResourceEntry,
    FabricId,
@@ -51,7 +48,7 @@ class LogicalResourceServicerImpl(LogicalResourcesServicer):
        return Response(success=True, message='Resources added to Logical Database')

    @safe_and_metered_rpc_method(METRICS_POOL, LOGGER)
    def GetAvailableResource(self, request, context: grpc.ServicerContext) -> ResourceList:
    def GetAvailableResources(self, request, context: grpc.ServicerContext) -> ResourceList:
        reply = ResourceList()
        for resource_type, resource_value, fabric_id in self.db.get_available_resources():
            reply.resources.append(ResourceEntry(
@@ -72,14 +69,14 @@ class LogicalResourceServicerImpl(LogicalResourcesServicer):
        return Success(success=success, message=message)

    @safe_and_metered_rpc_method(METRICS_POOL, LOGGER)
    def DeleteResource(self, request, context: grpc.ServicerContext) -> Success:
        success, message = self.db.delete_resource(request.tuple.type, request.tuple.value)
    def ReleaseResource(self, request, context: grpc.ServicerContext) -> Success:
        success, message = self.db.release_resource(request.tuple.type, request.tuple.value)
        return Success(success=success, message=message)

    @safe_and_metered_rpc_method(METRICS_POOL, LOGGER)
    def GetAllocatedResources(self, request, context: grpc.ServicerContext) -> ResourceList:
    def GetReservedResources(self, request, context: grpc.ServicerContext) -> ResourceList:
        reply = ResourceList()
        for resource_type, resource_value, fabric_id in self.db.get_allocated_resources():
        for resource_type, resource_value, fabric_id in self.db.get_reserved_resources():
            reply.resources.append(ResourceEntry(
                type=resource_type,
                value=resource_value,
@@ -103,92 +100,3 @@ class LogicalResourceServicerImpl(LogicalResourcesServicer):
                allocated=bool(fabric_id),
            ))
        return reply
 No newline at end of file

    @safe_and_metered_rpc_method(METRICS_POOL, LOGGER)
    def AddDevice(self, request: DeviceConfig, context : grpc.ServicerContext) -> Response:
        return self.AddResources(ConfigParameters(
            device_uuid=request.device_uuid,
            endpoint_uuid=request.endpoint_uuid,
            ip_address=request.ip_address,
            vlan_tag=request.vlan_tag,
            mac_address=request.mac_address,
            asn=request.asn,
            router_id=request.router_id,
            vni=request.vni,
            local_address=request.local_address,
            port=request.port,
            bridge=request.bridge,
            interface=request.interface,
            remote_address=request.remote_address,
            remote_as=request.remote_as,
            local_role=request.local_role,
            routing_table=request.routing_table,
            multihop=request.multihop,
            afi=request.afi,
            name=request.name,
        ), context)

    @safe_and_metered_rpc_method(METRICS_POOL, LOGGER)
    def GetDatabase(self, request, context:grpc.ServicerContext) -> Database:
        raw_db = self.db.get_full_db()
        reply = Database()

        for dev_uuid, endpoints in raw_db.items():
            dev_eps = DeviceEndpoints()
            for ep_uuid, config in endpoints.items():
                dev_eps.endpoints[ep_uuid].CopyFrom(DeviceConfig(
                    device_uuid=dev_uuid,
                    endpoint_uuid=ep_uuid,
                    ip_address=config['ip_addresses'][0] if config.get('ip_addresses') and config['ip_addresses'] else "",
                    vlan_tag=config['vlan_tags'][0] if config.get('vlan_tags') and config['vlan_tags'] else 0,
                    mac_address=config.get('mac_address', "") or "",
                    asn=config.get('asn', 0) or 0,
                    router_id=config.get('router_id', "") or "",
                    vni=config.get('vni', 0) or 0,
                    local_address=config.get('local_address', "") or "",
                    port=config.get('port', 0) or 0,
                    bridge=config.get('bridge', "") or "",
                    interface=config.get('interface', "") or "",
                    remote_address=config.get('remote_address', "") or "",
                    remote_as=config.get('remote_as', 0) or 0,
                    local_role=config.get('local_role', "") or "",
                    routing_table=config.get('routing_table', "") or "",
                    multihop=config.get('multihop', False) or False,
                    afi=config.get('afi', "") or "",
                    name=config.get('name', "") or ""
                ))
            reply.devices[dev_uuid].CopyFrom(dev_eps)

        return reply


#    @safe_and_metered_rpc_method(METRICS_POOL, LOGGER)
#    def DeleteDevice(self, request, context:grpc.ServicerContext) -> Response:
#        self.db.delete_device(request.device_uuid)
#        return Response(success=True, message=f"Device {request.device_uuid} removed")
#
#    @safe_and_metered_rpc_method(METRICS_POOL, LOGGER)
#    def GetDatabase(self, request, context:grpc.ServicerContext) -> Database:
#        # Get your raw python dictionary
#        raw_db = self.db.get_full_db()
#        
#        # Build the gRPC Database message
#        reply = Database()
#        
#        for dev_uuid, endpoints in raw_db.items():
#            dev_eps = DeviceEndpoints()
#            for ep_uuid, config in endpoints.items():
#                # Note: config is your dictionary from database.py
#                # We map it to the DeviceConfig message
#                dev_eps.endpoints[ep_uuid].CopyFrom(DeviceConfig(
#                    device_uuid=dev_uuid,
#                    endpoint_uuid=ep_uuid,
#                    ip_address=config['ip_addresses'][0] if config['ip_addresses'] else "",
#                    vlan_tag=config['vlan_tags'][0] if config['vlan_tags'] else 0,
#                    mac_address=config['mac_address'],
#                    asn=config['asn'],
#                    router_id=config['router_id']
#                ))
#            reply.devices[dev_uuid].CopyFrom(dev_eps)
#        
#        return reply
 No newline at end of file
+156 −20

File changed.

Preview size limit exceeded, changes collapsed.