diff --git a/src/__init__.py b/src/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/common/__init__.py b/src/common/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/monitoring/Dockerfile b/src/monitoring/Dockerfile index 5a8e6d1c8a6e3745522c18ee7ab490f6d1c6a546..3d6716334a41e5fc52287e27ae3cf13703cb0e9f 100644 --- a/src/monitoring/Dockerfile +++ b/src/monitoring/Dockerfile @@ -1,7 +1,9 @@ FROM python:3-slim -RUN apt-get update -qqy && \ - apt-get -qqy install wget g++ && \ - rm -rf /var/lib/apt/lists/* + +RUN apt-get --yes --quiet --quiet update && \ + apt-get --yes --quiet --quiet install wget g++ && \ + rm -rf /var/lib/apt/lists/* + # show python logs as they occur ENV PYTHONUNBUFFERED=0 @@ -11,20 +13,18 @@ RUN GRPC_HEALTH_PROBE_VERSION=v0.2.0 && \ chmod +x /bin/grpc_health_probe # get packages -WORKDIR /monitoring +WORKDIR /var/monitoring +RUN python3 -m pip install --upgrade pip setuptools wheel pip-tools COPY monitoring/requirements.in requirements.in -RUN python3 -m pip install pip-tools RUN pip-compile --output-file=requirements.txt requirements.in RUN python3 -m pip install -r requirements.txt # add files into working directory -COPY /monitoring/. . -COPY /common/logger.py . +COPY monitoring/. . +COPY common/logger.py . # set listen port -ENV PORT "7070" +ENV PORT=7070 EXPOSE 7070 ENTRYPOINT ["python", "/monitoring/monitoring_server.py"] - - diff --git a/src/monitoring/context_pb2.py b/src/monitoring/context_pb2.py index cb90ca043992be439f4ff4635401424bd10294a8..5930d483e211a51816f87595ed4bb12848ee9a44 100644 --- a/src/monitoring/context_pb2.py +++ b/src/monitoring/context_pb2.py @@ -20,7 +20,7 @@ DESCRIPTOR = _descriptor.FileDescriptor( package='context', syntax='proto3', serialized_options=None, - serialized_pb=_b('\n\rcontext.proto\x12\x07\x63ontext\"\x07\n\x05\x45mpty\"{\n\x07\x43ontext\x12%\n\tcontextId\x18\x01 \x01(\x0b\x32\x12.context.ContextId\x12\x1f\n\x04topo\x18\x02 \x01(\x0b\x32\x11.context.Topology\x12(\n\x03\x63tl\x18\x03 \x01(\x0b\x32\x1b.context.TeraFlowController\"/\n\tContextId\x12\"\n\x0b\x63ontextUuid\x18\x01 \x01(\x0b\x32\r.context.Uuid\"m\n\x08Topology\x12#\n\x06topoId\x18\x02 \x01(\x0b\x32\x13.context.TopologyId\x12\x1f\n\x06\x64\x65vice\x18\x03 \x03(\x0b\x32\x0f.context.Device\x12\x1b\n\x04link\x18\x04 \x03(\x0b\x32\r.context.Link\"1\n\x04Link\x12)\n\x0c\x65ndpointList\x18\x01 \x03(\x0b\x32\x13.context.EndPointId\"R\n\nTopologyId\x12%\n\tcontextId\x18\x01 \x01(\x0b\x32\x12.context.ContextId\x12\x1d\n\x06topoId\x18\x02 \x01(\x0b\x32\r.context.Uuid\"?\n\nConstraint\x12\x17\n\x0f\x63onstraint_type\x18\x01 \x01(\t\x12\x18\n\x10\x63onstraint_value\x18\x02 \x01(\t\"\xda\x01\n\x06\x44\x65vice\x12$\n\tdevice_id\x18\x01 \x01(\x0b\x32\x11.context.DeviceId\x12\x13\n\x0b\x64\x65vice_type\x18\x02 \x01(\t\x12,\n\rdevice_config\x18\x03 \x01(\x0b\x32\x15.context.DeviceConfig\x12>\n\x14\x64\x65vOperationalStatus\x18\x04 \x01(\x0e\x32 .context.DeviceOperationalStatus\x12\'\n\x0c\x65ndpointList\x18\x05 \x03(\x0b\x32\x11.context.EndPoint\"%\n\x0c\x44\x65viceConfig\x12\x15\n\rdevice_config\x18\x01 \x01(\t\"C\n\x08\x45ndPoint\x12$\n\x07port_id\x18\x01 \x01(\x0b\x32\x13.context.EndPointId\x12\x11\n\tport_type\x18\x02 \x01(\t\"t\n\nEndPointId\x12#\n\x06topoId\x18\x01 \x01(\x0b\x32\x13.context.TopologyId\x12!\n\x06\x64\x65v_id\x18\x02 \x01(\x0b\x32\x11.context.DeviceId\x12\x1e\n\x07port_id\x18\x03 \x01(\x0b\x32\r.context.Uuid\",\n\x08\x44\x65viceId\x12 \n\tdevice_id\x18\x01 \x01(\x0b\x32\r.context.Uuid\"\x14\n\x04Uuid\x12\x0c\n\x04uuid\x18\x01 \x01(\t\"K\n\x12TeraFlowController\x12\"\n\x06\x63tl_id\x18\x01 \x01(\x0b\x32\x12.context.ContextId\x12\x11\n\tipaddress\x18\x02 \x01(\t\"Q\n\x14\x41uthenticationResult\x12\"\n\x06\x63tl_id\x18\x01 \x01(\x0b\x32\x12.context.ContextId\x12\x15\n\rauthenticated\x18\x02 \x01(\x08*4\n\x17\x44\x65viceOperationalStatus\x12\x0c\n\x08\x44ISABLED\x10\x00\x12\x0b\n\x07\x45NABLED\x10\x01\x32\x44\n\x0e\x43ontextService\x12\x32\n\x0bGetTopology\x12\x0e.context.Empty\x1a\x11.context.Topology\"\x00\x62\x06proto3') + serialized_pb=_b('\n\rcontext.proto\x12\x07\x63ontext\"\x07\n\x05\x45mpty\"T\n\x07\x43ontext\x12\x1f\n\x04topo\x18\x01 \x01(\x0b\x32\x11.context.Topology\x12(\n\x03\x63tl\x18\x02 \x01(\x0b\x32\x1b.context.TeraFlowController\"H\n\x08Topology\x12\x1f\n\x06\x64\x65vice\x18\x01 \x03(\x0b\x32\x0f.context.Device\x12\x1b\n\x04link\x18\x02 \x03(\x0b\x32\r.context.Link\"1\n\x04Link\x12)\n\x0c\x65ndpointList\x18\x01 \x03(\x0b\x32\x13.context.EndPointId\"?\n\nConstraint\x12\x17\n\x0f\x63onstraint_type\x18\x01 \x01(\t\x12\x18\n\x10\x63onstraint_value\x18\x02 \x01(\t\"\xda\x01\n\x06\x44\x65vice\x12$\n\tdevice_id\x18\x01 \x01(\x0b\x32\x11.context.DeviceId\x12\x13\n\x0b\x64\x65vice_type\x18\x02 \x01(\t\x12,\n\rdevice_config\x18\x03 \x01(\x0b\x32\x15.context.DeviceConfig\x12>\n\x14\x64\x65vOperationalStatus\x18\x04 \x01(\x0e\x32 .context.DeviceOperationalStatus\x12\'\n\x0c\x65ndpointList\x18\x05 \x03(\x0b\x32\x11.context.EndPoint\"%\n\x0c\x44\x65viceConfig\x12\x15\n\rdevice_config\x18\x01 \x01(\t\"C\n\x08\x45ndPoint\x12$\n\x07port_id\x18\x01 \x01(\x0b\x32\x13.context.EndPointId\x12\x11\n\tport_type\x18\x02 \x01(\t\"O\n\nEndPointId\x12\x1e\n\x07port_id\x18\x01 \x01(\x0b\x32\r.context.Uuid\x12!\n\x06\x64\x65v_id\x18\x02 \x01(\x0b\x32\x11.context.DeviceId\",\n\x08\x44\x65viceId\x12 \n\tdevice_id\x18\x01 \x01(\x0b\x32\r.context.Uuid\"\x14\n\x04Uuid\x12\x0c\n\x04uuid\x18\x01 \x01(\t\"F\n\x12TeraFlowController\x12\x1d\n\x06\x63tl_id\x18\x01 \x01(\x0b\x32\r.context.Uuid\x12\x11\n\tipaddress\x18\x02 \x01(\t\"L\n\x14\x41uthenticationResult\x12\x1d\n\x06\x63tl_id\x18\x01 \x01(\x0b\x32\r.context.Uuid\x12\x15\n\rauthenticated\x18\x02 \x01(\x08*4\n\x17\x44\x65viceOperationalStatus\x12\x0c\n\x08\x44ISABLED\x10\x00\x12\x0b\n\x07\x45NABLED\x10\x01\x32\x44\n\x0e\x43ontextService\x12\x32\n\x0bGetTopology\x12\x0e.context.Empty\x1a\x11.context.Topology\"\x00\x62\x06proto3') ) _DEVICEOPERATIONALSTATUS = _descriptor.EnumDescriptor( @@ -40,8 +40,8 @@ _DEVICEOPERATIONALSTATUS = _descriptor.EnumDescriptor( ], containing_type=None, serialized_options=None, - serialized_start=1195, - serialized_end=1247, + serialized_start=939, + serialized_end=991, ) _sym_db.RegisterEnumDescriptor(_DEVICEOPERATIONALSTATUS) @@ -83,26 +83,19 @@ _CONTEXT = _descriptor.Descriptor( containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='contextId', full_name='context.Context.contextId', index=0, + name='topo', full_name='context.Context.topo', index=0, number=1, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='topo', full_name='context.Context.topo', index=1, + name='ctl', full_name='context.Context.ctl', index=1, number=2, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='ctl', full_name='context.Context.ctl', index=2, - number=3, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], @@ -116,38 +109,7 @@ _CONTEXT = _descriptor.Descriptor( oneofs=[ ], serialized_start=35, - serialized_end=158, -) - - -_CONTEXTID = _descriptor.Descriptor( - name='ContextId', - full_name='context.ContextId', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='contextUuid', full_name='context.ContextId.contextUuid', index=0, - number=1, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=160, - serialized_end=207, + serialized_end=119, ) @@ -159,22 +121,15 @@ _TOPOLOGY = _descriptor.Descriptor( containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='topoId', full_name='context.Topology.topoId', index=0, - number=2, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='device', full_name='context.Topology.device', index=1, - number=3, type=11, cpp_type=10, label=3, + name='device', full_name='context.Topology.device', index=0, + number=1, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='link', full_name='context.Topology.link', index=2, - number=4, type=11, cpp_type=10, label=3, + name='link', full_name='context.Topology.link', index=1, + number=2, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, @@ -191,8 +146,8 @@ _TOPOLOGY = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=209, - serialized_end=318, + serialized_start=121, + serialized_end=193, ) @@ -222,46 +177,8 @@ _LINK = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=320, - serialized_end=369, -) - - -_TOPOLOGYID = _descriptor.Descriptor( - name='TopologyId', - full_name='context.TopologyId', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='contextId', full_name='context.TopologyId.contextId', index=0, - number=1, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='topoId', full_name='context.TopologyId.topoId', index=1, - number=2, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=371, - serialized_end=453, + serialized_start=195, + serialized_end=244, ) @@ -298,8 +215,8 @@ _CONSTRAINT = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=455, - serialized_end=518, + serialized_start=246, + serialized_end=309, ) @@ -357,8 +274,8 @@ _DEVICE = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=521, - serialized_end=739, + serialized_start=312, + serialized_end=530, ) @@ -388,8 +305,8 @@ _DEVICECONFIG = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=741, - serialized_end=778, + serialized_start=532, + serialized_end=569, ) @@ -426,8 +343,8 @@ _ENDPOINT = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=780, - serialized_end=847, + serialized_start=571, + serialized_end=638, ) @@ -439,7 +356,7 @@ _ENDPOINTID = _descriptor.Descriptor( containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='topoId', full_name='context.EndPointId.topoId', index=0, + name='port_id', full_name='context.EndPointId.port_id', index=0, number=1, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, @@ -452,13 +369,6 @@ _ENDPOINTID = _descriptor.Descriptor( message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='port_id', full_name='context.EndPointId.port_id', index=2, - number=3, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], @@ -471,8 +381,8 @@ _ENDPOINTID = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=849, - serialized_end=965, + serialized_start=640, + serialized_end=719, ) @@ -502,8 +412,8 @@ _DEVICEID = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=967, - serialized_end=1011, + serialized_start=721, + serialized_end=765, ) @@ -533,8 +443,8 @@ _UUID = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=1013, - serialized_end=1033, + serialized_start=767, + serialized_end=787, ) @@ -571,8 +481,8 @@ _TERAFLOWCONTROLLER = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=1035, - serialized_end=1110, + serialized_start=789, + serialized_end=859, ) @@ -609,37 +519,29 @@ _AUTHENTICATIONRESULT = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=1112, - serialized_end=1193, + serialized_start=861, + serialized_end=937, ) -_CONTEXT.fields_by_name['contextId'].message_type = _CONTEXTID _CONTEXT.fields_by_name['topo'].message_type = _TOPOLOGY _CONTEXT.fields_by_name['ctl'].message_type = _TERAFLOWCONTROLLER -_CONTEXTID.fields_by_name['contextUuid'].message_type = _UUID -_TOPOLOGY.fields_by_name['topoId'].message_type = _TOPOLOGYID _TOPOLOGY.fields_by_name['device'].message_type = _DEVICE _TOPOLOGY.fields_by_name['link'].message_type = _LINK _LINK.fields_by_name['endpointList'].message_type = _ENDPOINTID -_TOPOLOGYID.fields_by_name['contextId'].message_type = _CONTEXTID -_TOPOLOGYID.fields_by_name['topoId'].message_type = _UUID _DEVICE.fields_by_name['device_id'].message_type = _DEVICEID _DEVICE.fields_by_name['device_config'].message_type = _DEVICECONFIG _DEVICE.fields_by_name['devOperationalStatus'].enum_type = _DEVICEOPERATIONALSTATUS _DEVICE.fields_by_name['endpointList'].message_type = _ENDPOINT _ENDPOINT.fields_by_name['port_id'].message_type = _ENDPOINTID -_ENDPOINTID.fields_by_name['topoId'].message_type = _TOPOLOGYID -_ENDPOINTID.fields_by_name['dev_id'].message_type = _DEVICEID _ENDPOINTID.fields_by_name['port_id'].message_type = _UUID +_ENDPOINTID.fields_by_name['dev_id'].message_type = _DEVICEID _DEVICEID.fields_by_name['device_id'].message_type = _UUID -_TERAFLOWCONTROLLER.fields_by_name['ctl_id'].message_type = _CONTEXTID -_AUTHENTICATIONRESULT.fields_by_name['ctl_id'].message_type = _CONTEXTID +_TERAFLOWCONTROLLER.fields_by_name['ctl_id'].message_type = _UUID +_AUTHENTICATIONRESULT.fields_by_name['ctl_id'].message_type = _UUID DESCRIPTOR.message_types_by_name['Empty'] = _EMPTY DESCRIPTOR.message_types_by_name['Context'] = _CONTEXT -DESCRIPTOR.message_types_by_name['ContextId'] = _CONTEXTID DESCRIPTOR.message_types_by_name['Topology'] = _TOPOLOGY DESCRIPTOR.message_types_by_name['Link'] = _LINK -DESCRIPTOR.message_types_by_name['TopologyId'] = _TOPOLOGYID DESCRIPTOR.message_types_by_name['Constraint'] = _CONSTRAINT DESCRIPTOR.message_types_by_name['Device'] = _DEVICE DESCRIPTOR.message_types_by_name['DeviceConfig'] = _DEVICECONFIG @@ -666,13 +568,6 @@ Context = _reflection.GeneratedProtocolMessageType('Context', (_message.Message, )) _sym_db.RegisterMessage(Context) -ContextId = _reflection.GeneratedProtocolMessageType('ContextId', (_message.Message,), dict( - DESCRIPTOR = _CONTEXTID, - __module__ = 'context_pb2' - # @@protoc_insertion_point(class_scope:context.ContextId) - )) -_sym_db.RegisterMessage(ContextId) - Topology = _reflection.GeneratedProtocolMessageType('Topology', (_message.Message,), dict( DESCRIPTOR = _TOPOLOGY, __module__ = 'context_pb2' @@ -687,13 +582,6 @@ Link = _reflection.GeneratedProtocolMessageType('Link', (_message.Message,), dic )) _sym_db.RegisterMessage(Link) -TopologyId = _reflection.GeneratedProtocolMessageType('TopologyId', (_message.Message,), dict( - DESCRIPTOR = _TOPOLOGYID, - __module__ = 'context_pb2' - # @@protoc_insertion_point(class_scope:context.TopologyId) - )) -_sym_db.RegisterMessage(TopologyId) - Constraint = _reflection.GeneratedProtocolMessageType('Constraint', (_message.Message,), dict( DESCRIPTOR = _CONSTRAINT, __module__ = 'context_pb2' @@ -765,8 +653,8 @@ _CONTEXTSERVICE = _descriptor.ServiceDescriptor( file=DESCRIPTOR, index=0, serialized_options=None, - serialized_start=1249, - serialized_end=1317, + serialized_start=993, + serialized_end=1061, methods=[ _descriptor.MethodDescriptor( name='GetTopology', diff --git a/src/monitoring/monitoring_client.py b/src/monitoring/monitoring_client.py index db70e6e2a5923fc14cba5de234e9e5b3a3cbff5b..905c09adaa43aece5db0f1c476a940141c11517a 100644 --- a/src/monitoring/monitoring_client.py +++ b/src/monitoring/monitoring_client.py @@ -22,13 +22,13 @@ class MonitoringClient: logger.info("IncludeKpi: {}".format(request)) response = self.server.IncludeKpi(request) logger.info("IncludeKpi result: {}".format(response)) - return context.Empty() + return context_pb2.Empty() def MonitorKpi(self, request): logger.info("MonitorKpi: {}".format(request)) response = self.server.IncludeKpi(request) logger.info("MonitorKpi result: {}".format(response)) - return context.Empty() + return context_pb2.Empty() def GetStream_kpi(self, request): logger.info("GetStream_kpi: {}".format(request)) @@ -52,13 +52,9 @@ if __name__ == "__main__": # form request kpi = monitoring.Kpi() - monitoring.KpiId.kpi_id = "KPIID0000" + kpi.kpi_id.kpi_id = "KPIID0000" kpi.kpiDescription = "KPI Desc" - # make call to server client = MonitoringClient(port) response=client.IncludeKpi(kpi) - - - diff --git a/src/monitoring/monitoring_server.py b/src/monitoring/monitoring_server.py index 66c85e2e613324cbd40c64135bf275c62e13b736..aaa0d3895d57061133f1dbe83ce937c0994f42aa 100644 --- a/src/monitoring/monitoring_server.py +++ b/src/monitoring/monitoring_server.py @@ -66,7 +66,7 @@ if __name__ == "__main__": serverGRPC = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) # ,interceptors=(tracer_interceptor,)) # add class to gRPC server - service = monitoring_pb2_grpc.MonitoringServiceServicer() + service = monitoringService() monitoring_pb2_grpc.add_MonitoringServiceServicer_to_server(service, serverGRPC) health_servicer = health.HealthServicer(experimental_non_blocking=True,experimental_thread_pool=futures.ThreadPoolExecutor(max_workers=1)) diff --git a/src/monitoring/requirements.txt b/src/monitoring/requirements.txt index 66f5f281c342c6c62864c83f721b91497f529be9..7b000b30e0b048875b2bcf56b4d9c1999c9f5e16 100644 --- a/src/monitoring/requirements.txt +++ b/src/monitoring/requirements.txt @@ -1,7 +1,4 @@ -#raise _InactiveRpcError(state) -grpc._channel._InactiveRpcError: <_InactiveRpcError of RPC that terminated with: - status = StatusCode.UNAVAILABLE - details = "DNS resolution failed for service: 7070:7070" +# # This file is autogenerated by pip-compile # To update, run: #