Skip to content
Snippets Groups Projects
Commit fcf3e848 authored by Lluis Gifre Renom's avatar Lluis Gifre Renom
Browse files

Merge branch 'feat/device-adapt-to-context-api' into 'develop'

First working version of Device with Emulated and OpenConfig drivers (except device monitoring)

See merge request teraflow-h2020/controller!38
parents 66d3943f 3143b9c2
No related branches found
No related tags found
1 merge request!54Release 2.0.0
Showing
with 245 additions and 96 deletions
*.xml
...@@ -81,10 +81,6 @@ spec: ...@@ -81,10 +81,6 @@ spec:
selector: selector:
app: contextservice app: contextservice
ports: ports:
- name: grpc
protocol: TCP
port: 1010
targetPort: 1010
- name: http - name: http
protocol: TCP protocol: TCP
port: 8080 port: 8080
......
...@@ -19,10 +19,6 @@ spec: ...@@ -19,10 +19,6 @@ spec:
ports: ports:
- containerPort: 2020 - containerPort: 2020
env: env:
- name: DB_ENGINE
value: "redis"
- name: REDIS_DATABASE_ID
value: "0"
- name: LOG_LEVEL - name: LOG_LEVEL
value: "DEBUG" value: "DEBUG"
readinessProbe: readinessProbe:
......
syntax = "proto3"; syntax = "proto3";
package context; package context;
//import "kpi_sample_types.proto";
service ContextService { service ContextService {
rpc ListContextIds (Empty ) returns ( ContextIdList ) {} rpc ListContextIds (Empty ) returns ( ContextIdList ) {}
rpc ListContexts (Empty ) returns ( ContextList ) {} rpc ListContexts (Empty ) returns ( ContextList ) {}
...@@ -241,6 +243,7 @@ message EndPointId { ...@@ -241,6 +243,7 @@ message EndPointId {
message EndPoint { message EndPoint {
EndPointId endpoint_id = 1; EndPointId endpoint_id = 1;
string endpoint_type = 2; string endpoint_type = 2;
//repeated kpi_sample_types.KpiSampleType kpi_sample_types = 3;
} }
......
...@@ -2,10 +2,19 @@ syntax = "proto3"; ...@@ -2,10 +2,19 @@ syntax = "proto3";
package device; package device;
import "context.proto"; import "context.proto";
//import "monitoring.proto";
service DeviceService { service DeviceService {
rpc AddDevice (context.Device ) returns (context.DeviceId ) {} rpc AddDevice (context.Device ) returns (context.DeviceId ) {}
rpc ConfigureDevice (context.Device ) returns (context.DeviceId ) {} rpc ConfigureDevice (context.Device ) returns (context.DeviceId ) {}
rpc DeleteDevice (context.DeviceId) returns (context.Empty ) {} rpc DeleteDevice (context.DeviceId ) returns (context.Empty ) {}
rpc GetInitialConfig(context.DeviceId) returns (context.DeviceConfig) {} rpc GetInitialConfig(context.DeviceId ) returns (context.DeviceConfig) {}
//rpc MonitorDeviceKpi(MonitoringSettings) returns (context.Empty ) {}
} }
//message MonitoringSettings {
// monitoring.KpiId kpi_id = 1;
// monitoring.KpiDescriptor kpi_descriptor = 2;
// float sampling_duration_s = 3;
// float sampling_interval_s = 4;
//}
syntax = "proto3";
//package kpi_sample_types;
//enum KpiSampleType {
// UNKNOWN = 0;
// PACKETS_TRANSMITTED = 101;
// PACKETS_RECEIVED = 102;
// BYTES_TRANSMITTED = 201;
// BYTES_RECEIVED = 202;
//}
//Example of topology
syntax = "proto3"; syntax = "proto3";
package monitoring; package monitoring;
import "context.proto"; import "context.proto";
//import "kpi_sample_types.proto";
service MonitoringService { service MonitoringService {
// Old RPCs:
rpc CreateKpi (CreateKpiRequest) returns (KpiId) {} rpc CreateKpi (CreateKpiRequest) returns (KpiId) {}
rpc IncludeKpi (IncludeKpiRequest) returns (context.Empty) {} rpc IncludeKpi (IncludeKpiRequest) returns (context.Empty) {}
rpc MonitorKpi (MonitorKpiRequest) returns (context.Empty) {} rpc MonitorKpi (MonitorKpiRequest) returns (context.Empty) {}
rpc MonitorDeviceKpi (MonitorDeviceKpiRequest) returns (context.Empty) {} rpc MonitorDeviceKpi (MonitorDeviceKpiRequest) returns (context.Empty) {}
rpc GetStreamKpi ( KpiId ) returns (stream Kpi) {} rpc GetStreamKpi ( KpiId ) returns (stream Kpi) {}
rpc GetInstantKpi ( KpiId ) returns (Kpi) {} rpc GetInstantKpi ( KpiId ) returns (Kpi) {}
// New RPCs:
//rpc CreateKpi (KpiDescriptor ) returns (KpiId ) {}
//rpc GetKpiDescriptor(KpiId ) returns (KpiDescriptor) {}
//rpc IncludeKpi (Kpi ) returns (context.Empty) {}
//rpc MonitorKpi (MonitorKpiRequest) returns (context.Empty) {}
//rpc GetStreamKpi (KpiId ) returns (stream Kpi ) {}
//rpc GetInstantKpi (KpiId ) returns (Kpi ) {}
} }
message CreateKpiRequest{ message CreateKpiRequest /*New name: KpiDescriptor*/ {
// Old fields:
string kpiDescription = 1; string kpiDescription = 1;
context.DeviceId device_id = 2; context.DeviceId device_id = 2;
KpiSampleType kpi_sample_type = 3; KpiSampleType kpi_sample_type = 3;
// context.EndpointId endpoint_id = 4; // others might be added // context.EndpointId endpoint_id = 4; // others might be added
// context.ServiceId service_id = 5; // for monitoring other // context.ServiceId service_id = 5; // for monitoring other
// context.SliceId slice_id = 6; // entities // context.SliceId slice_id = 6; // entities
// New fields:
//string kpi_description = 1;
//kpi_sample_types.KpiSampleType kpi_sample_type = 2;
//context.DeviceId device_id = 3;
//context.EndPointId endpoint_id = 4;
//context.ServiceId service_id = 5;
////context.SliceId slice_id = 6; // to be used in future features
} }
message MonitorKpiRequest{ message MonitorKpiRequest{
KpiId kpi_id = 1; KpiId kpi_id = 1;
// Old fields:
uint32 connexion_time_s = 2; uint32 connexion_time_s = 2;
uint32 sample_rate_ms = 3; uint32 sample_rate_ms = 3;
// New fields:
//float sampling_duration_s = 2;
//float sampling_interval_s = 3;
} }
// Message to be removed:
message MonitorDeviceKpiRequest{ message MonitorDeviceKpiRequest{
Kpi kpi = 1; Kpi kpi = 1;
uint32 connexion_time_s = 2; uint32 connexion_time_s = 2;
uint32 sample_rate_ms = 3; uint32 sample_rate_ms = 3;
} }
// Message to be removed:
message IncludeKpiRequest{ message IncludeKpiRequest{
KpiId kpi_id = 1;
string time_stamp = 2;
KpiValue kpi_value= 3;
}
message Kpi {
KpiId kpi_id = 1; KpiId kpi_id = 1;
string timestamp = 2; string time_stamp = 2;
string kpiDescription = 3; KpiValue kpi_value= 3;
KpiValue kpi_value = 4;
KpiSampleType kpi_sample_type = 5;
context.DeviceId device_id = 6;
// context.EndpointId endpoint_id = 7; // others might be added
// context.ServiceId service_id = 8; // for monitoring other
// context.SliceId slice_id = 9; // entities
} }
message KpiId { message KpiId {
context.Uuid kpi_id = 1; context.Uuid kpi_id = 1;
} }
message KpiDevice { message Kpi {
KpiId kpi_id = 1; KpiId kpi_id = 1;
context.DeviceId device_id = 2; string timestamp = 2;
} string kpiDescription = 3; // field to be removed
KpiValue kpi_value = 4; // field to be renumbered to 3
enum KpiSampleType { KpiSampleType kpi_sample_type = 5; // field to be removed
UNKNOWN = 0; context.DeviceId device_id = 6; // field to be removed
PACKETS_TRANSMITTED = 101; // others might be added for // context.EndpointId endpoint_id = 7; // others might be added // field to be removed
PACKETS_RECEIVED = 102; // packet, optical, radio,... // context.ServiceId service_id = 8; // for monitoring other // field to be removed
BYTES_TRANSMITTED = 201; // context.SliceId slice_id = 9; // entities // field to be removed
BYTES_RECEIVED = 202;
}
message KpiList {
repeated Kpi kpiList = 1;
} }
message KpiValue { message KpiValue {
oneof value { oneof value {
uint32 intVal = 1; uint32 intVal = 1; // field to be renamed to int_val
string stringVal = 2; float floatVal = 2; // field to be renamed to float_val
bool boolVal = 3; string stringVal = 3; // field to be renamed to str_val
bool boolVal = 4; // field to be renamed to bool_val
} }
} }
message KpiList {
repeated Kpi kpiList = 1; // to be renamed to kpi_list
}
enum KpiSampleType { // to be moved to file "kpi_sample_types.proto"
UNKNOWN = 0;
PACKETS_TRANSMITTED = 101; // others might be added for
PACKETS_RECEIVED = 102; // packet, optical, radio,...
BYTES_TRANSMITTED = 201;
BYTES_RECEIVED = 202;
}
#!/bin/bash #!/bin/bash
./report_coverage_all.sh | grep -v -E "^(cent|comp|cont|devi|moni|serv|test)" | grep --color -E -i "^common/.*$|$" ./report_coverage_all.sh | grep --color -E -i "^common/.*$|$"
#!/bin/bash #!/bin/bash
./report_coverage_all.sh | grep -v -E "^(cent|com|devi|moni|serv|test)" | grep --color -E -i "^context/.*$|$" ./report_coverage_all.sh | grep --color -E -i "^context/.*$|$"
...@@ -11,6 +11,17 @@ cat $PROJECTDIR/coverage/.coveragerc.template | sed s+~/teraflow/controller+$PRO ...@@ -11,6 +11,17 @@ cat $PROJECTDIR/coverage/.coveragerc.template | sed s+~/teraflow/controller+$PRO
# Run unitary tests and analyze coverage of code at same time # Run unitary tests and analyze coverage of code at same time
# Populate environment variables for context to use Redis in a development machine running Kubernetes
# Uncomment below lines to create a Redis instance within Context for testing purposes.
#kubectl delete namespace tf-dev
#kubectl create namespace tf-dev
#kubectl --namespace tf-dev apply -f ../manifests/contextservice.yaml
#kubectl --namespace tf-dev expose deployment contextservice --port=6379 --type=NodePort --name=redis-tests
#echo "Waiting 10 seconds for Redis to start..."
#sleep 10
export REDIS_SERVICE_HOST=$(kubectl get node kubernetes-master -o 'jsonpath={.status.addresses[?(@.type=="InternalIP")].address}')
export REDIS_SERVICE_PORT=$(kubectl get service redis-tests --namespace tf-dev -o 'jsonpath={.spec.ports[?(@.port==6379)].nodePort}')
# First destroy old coverage file # First destroy old coverage file
rm -f $COVERAGEFILE rm -f $COVERAGEFILE
...@@ -27,7 +38,7 @@ coverage run --rcfile=$RCFILE --append -m pytest --log-level=INFO --verbose \ ...@@ -27,7 +38,7 @@ coverage run --rcfile=$RCFILE --append -m pytest --log-level=INFO --verbose \
coverage run --rcfile=$RCFILE --append -m pytest --log-level=INFO --verbose \ coverage run --rcfile=$RCFILE --append -m pytest --log-level=INFO --verbose \
device/tests/test_unitary_driverapi.py \ device/tests/test_unitary_driverapi.py \
device/tests/test_unitary_service.py device/tests/test_unitary.py
coverage run --rcfile=$RCFILE --append -m pytest -s --log-level=INFO --verbose \ coverage run --rcfile=$RCFILE --append -m pytest -s --log-level=INFO --verbose \
l3_centralizedattackdetector/tests/test_unitary.py l3_centralizedattackdetector/tests/test_unitary.py
......
import logging, pytest, threading, time import logging, os, pytest, threading, time
from typing import List, Set from typing import List, Set
from common.message_broker.Factory import get_messagebroker_backend from common.message_broker.Factory import get_messagebroker_backend
from common.message_broker.Message import Message from common.message_broker.Message import Message
...@@ -9,13 +9,19 @@ from common.message_broker.backend._Backend import _Backend ...@@ -9,13 +9,19 @@ from common.message_broker.backend._Backend import _Backend
logging.basicConfig(level=logging.INFO) logging.basicConfig(level=logging.INFO)
LOGGER = logging.getLogger(__name__) LOGGER = logging.getLogger(__name__)
DEFAULT_REDIS_SERVICE_HOST = '127.0.0.1'
DEFAULT_REDIS_SERVICE_PORT = 6379
DEFAULT_REDIS_DATABASE_ID = 0
REDIS_CONFIG = {
'REDIS_SERVICE_HOST': os.environ.get('REDIS_SERVICE_HOST', DEFAULT_REDIS_SERVICE_HOST),
'REDIS_SERVICE_PORT': os.environ.get('REDIS_SERVICE_PORT', DEFAULT_REDIS_SERVICE_PORT),
'REDIS_DATABASE_ID' : os.environ.get('REDIS_DATABASE_ID', DEFAULT_REDIS_DATABASE_ID ),
}
SCENARIOS = [ SCENARIOS = [
(BackendEnum.INMEMORY, {}), ('all_inmemory', BackendEnum.INMEMORY, {} ),
(BackendEnum.REDIS, { ('all_redis', BackendEnum.REDIS, REDIS_CONFIG),
'REDIS_SERVICE_HOST': '10.1.7.194',
'REDIS_SERVICE_PORT': 30283,
'REDIS_DATABASE_ID': 0,
}),
] ]
CONSUME_TIMEOUT = 0.1 # seconds CONSUME_TIMEOUT = 0.1 # seconds
...@@ -43,11 +49,14 @@ class Consumer(threading.Thread): ...@@ -43,11 +49,14 @@ class Consumer(threading.Thread):
self._output_list.append(message) self._output_list.append(message)
LOGGER.info('{:s} terminates') LOGGER.info('{:s} terminates')
@pytest.fixture(scope='session', ids=[str(scenario[0].value) for scenario in SCENARIOS], params=SCENARIOS) @pytest.fixture(scope='session', ids=[str(scenario[0]) for scenario in SCENARIOS], params=SCENARIOS)
def message_broker(request): def message_broker(request):
backend,settings = request.param name,mb_backend,mb_settings = request.param
LOGGER.info('Running fixture with backend={:s}, settings={:s}...'.format(str(backend), str(settings))) msg = 'Running scenario {:s} mb_backend={:s}, mb_settings={:s}...'
return MessageBroker(get_messagebroker_backend(backend=backend, **settings)) LOGGER.info(msg.format(str(name), str(mb_backend.value), str(mb_settings)))
_message_broker = MessageBroker(get_messagebroker_backend(backend=mb_backend, **mb_settings))
yield _message_broker
_message_broker.terminate()
def test_messagebroker_instantiation(): def test_messagebroker_instantiation():
with pytest.raises(AttributeError) as e: with pytest.raises(AttributeError) as e:
......
import grpc import grpc
from typing import Iterable from typing import Iterable, Union
class ServiceException(Exception): class ServiceException(Exception):
def __init__(self, code : grpc.StatusCode, details : str, extra_details : Iterable[str] = []) -> None: def __init__(
self, code : grpc.StatusCode, details : str, extra_details : Union[str, Iterable[str]] = []
) -> None:
self.code = code self.code = code
if isinstance(extra_details, str): extra_details = [extra_details]
self.details = '; '.join(map(str, [details] + extra_details)) self.details = '; '.join(map(str, [details] + extra_details))
super().__init__(self.details) super().__init__(self.details)
class NotFoundException(ServiceException): class NotFoundException(ServiceException):
def __init__(self, object_name : str, object_uuid: str, extra_details : Iterable[str] = []) -> None: def __init__(
self, object_name : str, object_uuid: str, extra_details : Union[str, Iterable[str]] = []
) -> None:
details = '{:s}({:s}) not found'.format(str(object_name), str(object_uuid)) details = '{:s}({:s}) not found'.format(str(object_name), str(object_uuid))
super().__init__(grpc.StatusCode.NOT_FOUND, details, extra_details=extra_details) super().__init__(grpc.StatusCode.NOT_FOUND, details, extra_details=extra_details)
class AlreadyExistsException(ServiceException): class AlreadyExistsException(ServiceException):
def __init__(self, object_name : str, object_uuid: str, extra_details : Iterable[str] = None) -> None: def __init__(
self, object_name : str, object_uuid: str, extra_details : Union[str, Iterable[str]] = None
) -> None:
details = '{:s}({:s}) already exists'.format(str(object_name), str(object_uuid)) details = '{:s}({:s}) already exists'.format(str(object_name), str(object_uuid))
super().__init__(grpc.StatusCode.ALREADY_EXISTS, details, extra_details=extra_details) super().__init__(grpc.StatusCode.ALREADY_EXISTS, details, extra_details=extra_details)
class InvalidArgumentException(ServiceException): class InvalidArgumentException(ServiceException):
def __init__(self, argument_name : str, argument_value: str, extra_details : Iterable[str] = None) -> None: def __init__(
self, argument_name : str, argument_value: str, extra_details : Union[str, Iterable[str]] = None
) -> None:
details = '{:s}({:s}) is invalid'.format(str(argument_name), str(argument_value)) details = '{:s}({:s}) is invalid'.format(str(argument_name), str(argument_value))
super().__init__(grpc.StatusCode.INVALID_ARGUMENT, details, extra_details=extra_details) super().__init__(grpc.StatusCode.INVALID_ARGUMENT, details, extra_details=extra_details)
class OperationFailedException(ServiceException):
def __init__(
self, operation : str, extra_details : Union[str, Iterable[str]] = None
) -> None:
details = 'Operation({:s}) failed'.format(str(operation))
super().__init__(grpc.StatusCode.INTERNAL, details, extra_details=extra_details)
...@@ -24,6 +24,9 @@ rm -rf proto/__pycache__ ...@@ -24,6 +24,9 @@ rm -rf proto/__pycache__
touch proto/__init__.py touch proto/__init__.py
python -m grpc_tools.protoc -I../../proto --python_out=proto --grpc_python_out=proto context.proto python -m grpc_tools.protoc -I../../proto --python_out=proto --grpc_python_out=proto context.proto
python -m grpc_tools.protoc -I../../proto --python_out=proto --grpc_python_out=proto kpi_sample_types.proto
rm proto/kpi_sample_types_pb2_grpc.py
sed -i -E 's/(import\ .*)_pb2/from . \1_pb2/g' proto/context_pb2.py sed -i -E 's/(import\ .*)_pb2/from . \1_pb2/g' proto/context_pb2.py
sed -i -E 's/(import\ .*)_pb2/from . \1_pb2/g' proto/context_pb2_grpc.py sed -i -E 's/(import\ .*)_pb2/from . \1_pb2/g' proto/context_pb2_grpc.py
...@@ -6,7 +6,9 @@ from . import context_pb2 as context__pb2 ...@@ -6,7 +6,9 @@ from . import context_pb2 as context__pb2
class ContextServiceStub(object): class ContextServiceStub(object):
"""Missing associated documentation comment in .proto file.""" """import "kpi_sample_types.proto";
"""
def __init__(self, channel): def __init__(self, channel):
"""Constructor. """Constructor.
...@@ -167,7 +169,9 @@ class ContextServiceStub(object): ...@@ -167,7 +169,9 @@ class ContextServiceStub(object):
class ContextServiceServicer(object): class ContextServiceServicer(object):
"""Missing associated documentation comment in .proto file.""" """import "kpi_sample_types.proto";
"""
def ListContextIds(self, request, context): def ListContextIds(self, request, context):
"""Missing associated documentation comment in .proto file.""" """Missing associated documentation comment in .proto file."""
...@@ -510,7 +514,9 @@ def add_ContextServiceServicer_to_server(servicer, server): ...@@ -510,7 +514,9 @@ def add_ContextServiceServicer_to_server(servicer, server):
# This class is part of an EXPERIMENTAL API. # This class is part of an EXPERIMENTAL API.
class ContextService(object): class ContextService(object):
"""Missing associated documentation comment in .proto file.""" """import "kpi_sample_types.proto";
"""
@staticmethod @staticmethod
def ListContextIds(request, def ListContextIds(request,
......
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: kpi_sample_types.proto
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor.FileDescriptor(
name='kpi_sample_types.proto',
package='',
syntax='proto3',
serialized_options=None,
create_key=_descriptor._internal_create_key,
serialized_pb=b'\n\x16kpi_sample_types.protob\x06proto3'
)
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
# @@protoc_insertion_point(module_scope)
import functools, logging, operator import functools, logging, operator
from enum import Enum from enum import Enum
from typing import Dict, List, Tuple, Union from typing import Dict, List, Optional, Tuple, Union
from common.orm.Database import Database from common.orm.Database import Database
from common.orm.HighLevel import get_or_create_object, update_or_create_object from common.orm.HighLevel import get_object, get_or_create_object, update_or_create_object
from common.orm.backend.Tools import key_to_str from common.orm.backend.Tools import key_to_str
from common.orm.fields.EnumeratedField import EnumeratedField from common.orm.fields.EnumeratedField import EnumeratedField
from common.orm.fields.ForeignKeyField import ForeignKeyField from common.orm.fields.ForeignKeyField import ForeignKeyField
...@@ -11,7 +11,7 @@ from common.orm.fields.PrimaryKeyField import PrimaryKeyField ...@@ -11,7 +11,7 @@ from common.orm.fields.PrimaryKeyField import PrimaryKeyField
from common.orm.fields.StringField import StringField from common.orm.fields.StringField import StringField
from common.orm.model.Model import Model from common.orm.model.Model import Model
from context.proto.context_pb2 import ConfigActionEnum from context.proto.context_pb2 import ConfigActionEnum
from context.service.database.Tools import fast_hasher, grpc_to_enum, remove_dict_key from .Tools import fast_hasher, grpc_to_enum, remove_dict_key
LOGGER = logging.getLogger(__name__) LOGGER = logging.getLogger(__name__)
...@@ -50,35 +50,62 @@ class ConfigRuleModel(Model): # pylint: disable=abstract-method ...@@ -50,35 +50,62 @@ class ConfigRuleModel(Model): # pylint: disable=abstract-method
return result return result
def set_config_rule( def set_config_rule(
database : Database, db_config : ConfigModel, grpc_config_rule, position : int database : Database, db_config : ConfigModel, position : int, resource_key : str, resource_value : str
) -> Tuple[ConfigRuleModel, bool]: ) -> Tuple[ConfigRuleModel, bool]:
str_rule_key_hash = fast_hasher(grpc_config_rule.resource_key) str_rule_key_hash = fast_hasher(resource_key)
str_config_rule_key = key_to_str([db_config.pk, str_rule_key_hash], separator=':') str_config_rule_key = key_to_str([db_config.pk, str_rule_key_hash], separator=':')
result : Tuple[ConfigRuleModel, bool] = update_or_create_object(database, ConfigRuleModel, str_config_rule_key, { result : Tuple[ConfigRuleModel, bool] = update_or_create_object(database, ConfigRuleModel, str_config_rule_key, {
'config_fk': db_config, 'config_fk': db_config, 'position': position, 'action': ORM_ConfigActionEnum.SET,
'position' : position, 'key': resource_key, 'value': resource_value})
'action' : grpc_to_enum__config_action(grpc_config_rule.action),
'key' : grpc_config_rule.resource_key,
'value' : grpc_config_rule.resource_value,
})
db_config_rule, updated = result db_config_rule, updated = result
return db_config_rule, updated return db_config_rule, updated
def set_config( def delete_config_rule(
database : Database, db_parent_pk : str, config_name : str, grpc_config_rules database : Database, db_config : ConfigModel, resource_key : str
) -> None:
str_rule_key_hash = fast_hasher(resource_key)
str_config_rule_key = key_to_str([db_config.pk, str_rule_key_hash], separator=':')
db_config_rule : Optional[ConfigRuleModel] = get_object(
database, ConfigRuleModel, str_config_rule_key, raise_if_not_found=False)
if db_config_rule is None: return
db_config_rule.delete()
def delete_all_config_rules(
database : Database, db_config : ConfigModel
) -> None:
db_config_rule_pks = db_config.references(ConfigRuleModel)
for pk,_ in db_config_rule_pks: ConfigRuleModel(database, pk).delete()
def grpc_config_rules_to_raw(grpc_config_rules) -> List[Tuple[ORM_ConfigActionEnum, str, str]]:
def translate(grpc_config_rule):
action = grpc_to_enum__config_action(grpc_config_rule.action)
return action, grpc_config_rule.resource_key, grpc_config_rule.resource_value
return [translate(grpc_config_rule) for grpc_config_rule in grpc_config_rules]
def update_config(
database : Database, db_parent_pk : str, config_name : str,
raw_config_rules : List[Tuple[ORM_ConfigActionEnum, str, str]]
) -> List[Tuple[Union[ConfigModel, ConfigRuleModel], bool]]: ) -> List[Tuple[Union[ConfigModel, ConfigRuleModel], bool]]:
str_config_key = key_to_str([db_parent_pk, config_name], separator=':') str_config_key = key_to_str([db_parent_pk, config_name], separator=':')
result : Tuple[ConfigModel, bool] = get_or_create_object(database, ConfigModel, str_config_key) result : Tuple[ConfigModel, bool] = get_or_create_object(database, ConfigModel, str_config_key)
db_config, created = result db_config, created = result
db_objects = [(db_config, created)] db_objects : List[Tuple[Union[ConfigModel, ConfigRuleModel], bool]] = [(db_config, created)]
for position,grpc_config_rule in enumerate(grpc_config_rules): for position,(action, resource_key, resource_value) in enumerate(raw_config_rules):
result : Tuple[ConfigRuleModel, bool] = set_config_rule(database, db_config, grpc_config_rule, position) if action == ORM_ConfigActionEnum.SET:
db_config_rule, updated = result result : Tuple[ConfigRuleModel, bool] = set_config_rule(
db_objects.append((db_config_rule, updated)) database, db_config, position, resource_key, resource_value)
db_config_rule, updated = result
db_objects.append((db_config_rule, updated))
elif action == ORM_ConfigActionEnum.DELETE:
delete_config_rule(database, db_config, resource_key)
else:
msg = 'Unsupported action({:s}) for resource_key({:s})/resource_value({:s})'
raise AttributeError(msg.format(str(ConfigActionEnum.Name(action)), str(resource_key), str(resource_value)))
return db_objects return db_objects
...@@ -4,8 +4,8 @@ from common.orm.fields.ForeignKeyField import ForeignKeyField ...@@ -4,8 +4,8 @@ from common.orm.fields.ForeignKeyField import ForeignKeyField
from common.orm.fields.PrimaryKeyField import PrimaryKeyField from common.orm.fields.PrimaryKeyField import PrimaryKeyField
from common.orm.fields.StringField import StringField from common.orm.fields.StringField import StringField
from common.orm.model.Model import Model from common.orm.model.Model import Model
from context.service.database.DeviceModel import DeviceModel from .DeviceModel import DeviceModel
from context.service.database.TopologyModel import TopologyModel from .TopologyModel import TopologyModel
LOGGER = logging.getLogger(__name__) LOGGER = logging.getLogger(__name__)
......
...@@ -12,7 +12,7 @@ from context.proto.context_pb2 import ( ...@@ -12,7 +12,7 @@ from context.proto.context_pb2 import (
DeviceList, Empty, EventTypeEnum, Link, LinkEvent, LinkId, LinkIdList, LinkList, Service, ServiceEvent, ServiceId, DeviceList, Empty, EventTypeEnum, Link, LinkEvent, LinkId, LinkIdList, LinkList, Service, ServiceEvent, ServiceId,
ServiceIdList, ServiceList, Topology, TopologyEvent, TopologyId, TopologyIdList, TopologyList) ServiceIdList, ServiceList, Topology, TopologyEvent, TopologyId, TopologyIdList, TopologyList)
from context.proto.context_pb2_grpc import ContextServiceServicer from context.proto.context_pb2_grpc import ContextServiceServicer
from context.service.database.ConfigModel import ConfigModel, ConfigRuleModel, set_config from context.service.database.ConfigModel import ConfigModel, ConfigRuleModel, grpc_config_rules_to_raw, update_config
from context.service.database.ConstraintModel import ConstraintModel, ConstraintsModel, set_constraints from context.service.database.ConstraintModel import ConstraintModel, ConstraintsModel, set_constraints
from context.service.database.ContextModel import ContextModel from context.service.database.ContextModel import ContextModel
from context.service.database.DeviceModel import ( from context.service.database.DeviceModel import (
...@@ -236,7 +236,8 @@ class ContextServiceServicerImpl(ContextServiceServicer): ...@@ -236,7 +236,8 @@ class ContextServiceServicerImpl(ContextServiceServicer):
'request.device_endpoints[{:d}].device_id.device_uuid.uuid'.format(i), endpoint_device_uuid, 'request.device_endpoints[{:d}].device_id.device_uuid.uuid'.format(i), endpoint_device_uuid,
['should be == {:s}({:s})'.format('request.device_id.device_uuid.uuid', device_uuid)]) ['should be == {:s}({:s})'.format('request.device_id.device_uuid.uuid', device_uuid)])
running_config_result = set_config(self.database, device_uuid, 'running', request.device_config.config_rules) config_rules = grpc_config_rules_to_raw(request.device_config.config_rules)
running_config_result = update_config(self.database, device_uuid, 'running', config_rules)
db_running_config = running_config_result[0][0] db_running_config = running_config_result[0][0]
result : Tuple[DeviceModel, bool] = update_or_create_object(self.database, DeviceModel, device_uuid, { result : Tuple[DeviceModel, bool] = update_or_create_object(self.database, DeviceModel, device_uuid, {
...@@ -452,8 +453,8 @@ class ContextServiceServicerImpl(ContextServiceServicer): ...@@ -452,8 +453,8 @@ class ContextServiceServicerImpl(ContextServiceServicer):
self.database, str_service_key, 'constraints', request.service_constraints) self.database, str_service_key, 'constraints', request.service_constraints)
db_constraints = constraints_result[0][0] db_constraints = constraints_result[0][0]
running_config_result = set_config( config_rules = grpc_config_rules_to_raw(request.service_config.config_rules)
self.database, str_service_key, 'running', request.service_config.config_rules) running_config_result = update_config(self.database, str_service_key, 'running', config_rules)
db_running_config = running_config_result[0][0] db_running_config = running_config_result[0][0]
result : Tuple[ServiceModel, bool] = update_or_create_object(self.database, ServiceModel, str_service_key, { result : Tuple[ServiceModel, bool] = update_or_create_object(self.database, ServiceModel, str_service_key, {
......
...@@ -35,7 +35,7 @@ unit_test device: ...@@ -35,7 +35,7 @@ unit_test device:
- sleep 5 - sleep 5
- docker ps -a - docker ps -a
- docker logs $IMAGE_NAME - docker logs $IMAGE_NAME
- docker exec -i $IMAGE_NAME bash -c "pytest --log-level=DEBUG --verbose $IMAGE_NAME/tests/test_unitary_service.py $IMAGE_NAME/tests/test_unitary_driverapi.py" - docker exec -i $IMAGE_NAME bash -c "pytest --log-level=DEBUG --verbose $IMAGE_NAME/tests/test_unitary_driverapi.py $IMAGE_NAME/tests/test_unitary.py"
after_script: after_script:
- docker stop $IMAGE_NAME - docker stop $IMAGE_NAME
- docker rm $IMAGE_NAME - docker rm $IMAGE_NAME
......
...@@ -10,3 +10,9 @@ GRPC_GRACE_PERIOD = 60 ...@@ -10,3 +10,9 @@ GRPC_GRACE_PERIOD = 60
# Prometheus settings # Prometheus settings
METRICS_PORT = 9192 METRICS_PORT = 9192
# Dependency micro-service connection settings
CONTEXT_SERVICE_HOST = '127.0.0.1'
CONTEXT_SERVICE_PORT = 1010
MONITORING_SERVICE_HOST = '127.0.0.1'
MONITORING_SERVICE_PORT = 7070
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment