Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve zeroconf discovery #710

Merged
merged 31 commits into from
Feb 20, 2024

Conversation

xuzhenbao
Copy link
Contributor

@xuzhenbao xuzhenbao commented Jan 1, 2024

Fix some issues of #690 and improve zeroconf_discovery.

1.Improve zeroconf_discovery and add hostname resolving mechanism.
2.Rename remote service bundles.
3.Add zeroconf configuration type for rsa_dfi.
4.Add remote.configs.supported property for remote_service_admin service.

@codecov-commenter
Copy link

codecov-commenter commented Jan 1, 2024

Codecov Report

Attention: 102 lines in your changes are missing coverage. Please review.

Comparison is base (70548d6) 88.85% compared to head (e48e5ed) 89.32%.
Report is 12 commits behind head on master.

Files Patch % Lines
...e_services/topology_manager/src/topology_manager.c 92.16% 34 Missing ⚠️
...iscovery_zeroconf/src/discovery_zeroconf_watcher.c 94.56% 33 Missing ⚠️
...e_service_admin_dfi/src/remote_service_admin_dfi.c 85.58% 16 Missing ⚠️
...covery_zeroconf/src/discovery_zeroconf_announcer.c 93.25% 12 Missing ⚠️
...ice_admin_dfi/src/remote_service_admin_activator.c 76.92% 3 Missing ⚠️
...n_shm_v2/rsa_shm/src/rsa_shm_import_registration.c 77.77% 2 Missing ⚠️
...te_service_admin_dfi/src/import_registration_dfi.c 80.00% 1 Missing ⚠️
...n_shm_v2/rsa_shm/src/rsa_shm_export_registration.c 90.90% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #710      +/-   ##
==========================================
+ Coverage   88.85%   89.32%   +0.47%     
==========================================
  Files         216      216              
  Lines       24293    25153     +860     
==========================================
+ Hits        21585    22469     +884     
+ Misses       2708     2684      -24     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@xuzhenbao xuzhenbao mentioned this pull request Jan 1, 2024
Copy link
Contributor

@pnoltes pnoltes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still reviewing.

bundles/remote_services/rsa_spi/include/remote_constants.h Outdated Show resolved Hide resolved
(void)snprintf(scope, sizeof(scope), "(&(%s=*)(%s=%s))", CELIX_FRAMEWORK_SERVICE_NAME,
OSGI_RSA_ENDPOINT_FRAMEWORK_UUID, fwUuid);
celix_properties_set(props, OSGI_ENDPOINT_LISTENER_SCOPE, scope);
celix_properties_set(props, "DISCOVERY", "true");//Only use to avoid the discovery calls to unnecessary endpoint listener service.Endpoint should be filtered by the scope.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure if I get this. As also stated in the comment, I expected that the OSGI_ENDPOINT_LISTENER_SCOPE was enough. Is the "DISCOVERY" property added for additional performance optimization?

OSGi EndpointListener doc:

Endpoint Listener services can express their scope with the service property ENDPOINT_LISTENER_SCOPE. This service property is a list of filters. An Endpoint Description should only be given to a Endpoint Listener when there is at least one filter that matches the Endpoint Description properties. This filter model is quite flexible. For example, a discovery bundle is only interested in locally originating Endpoint Descriptions. The following filter ensure that it only sees local endpoints.
(org.osgi.framework.uuid=72dc5fd9-5f8f-4f8f-9821-9ebb433a5b72)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the "DISCOVERY" property added for additional performance optimization?

yes, ENDPOINT_LISTENER_SCOPE is enough to ensure that the endpoint listener of discovery only sees local endpoint.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. I see this is used in discovery_common / discovery_endpointListenerAdded. I am not a fan of this approach, but IMO we can keep this for now.

@@ -532,7 +644,8 @@ static void *discoveryZeroconfAnnouncer_refreshEndpointThread(void *data) {
discoveryZeroconfAnnouncer_handleMDNSEvent(announcer);
}
} else if (result == -1 && errno != EINTR) {
celix_logHelper_error(announcer->logHelper, "Announcer: Error Selecting event, %d.", errno);
celix_logHelper_error(announcer->logHelper, "Announcer: Error Selecting event, %d.", errno);
sleep(1);//avoid busy loop
Copy link
Contributor

@PengZheng PengZheng Jan 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not familiar with this part yet, and thus will only leave my two cents here.

While errno == ENOMEM suggests a temporary failure, for which sleep(1) does make sense, errno == EBADF may imply that the bundle could not work any more, e.g. the eventFd or dsFd may be accidentally closed by some buggy code.

We can really do nothing locally to recover from this kind of error. This represents some long lasting exceptional system condition, which can luckily be modeled using Celix condition. Once some outside watchers get notified of this system exception, he/she can try to restart the bundle, which could fix the accidentally closed fd in this case.

I think generic system exception is a generally useful concept, which further extends error code and C++ exception. Combined with RSA, this means these exceptions can be watched remotely (cool). Event better, we don't need descriptors for Remote Celix conditions because they have no methods.

WDYT? @pnoltes @xuzhenbao

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Concerning the sleep(1) / retry on a error rc. I think this is fine, but currently the running is not updated in the else branch of if (result > 0) and this is an issue.

I think the running update can be moved to the end part of the while loop:

while (running) {
 ....
  celixThreadMutex_lock(&announcer->mutex);
  running = announcer->running;
  celixThreadMutex_unlock(&announcer->mutex);
}

ensuring that running is updated every loop.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can really do nothing locally to recover from this kind of error. This represents some long lasting exceptional system condition, which can luckily be modeled using Celix condition. Once some outside watchers get notified of this system exception, he/she can try to restart the bundle, which could fix the accidentally closed fd in this case.

I think generic system exception is a generally useful concept, which further extends error code and C++ exception. Combined with RSA, this means these exceptions can be watched remotely (cool). Event better, we don't need descriptors for Remote Celix conditions because they have no methods.

WDYT? @pnoltes @xuzhenbao

I think remote conditions are very useful and indeed this does not need a descriptor, because conditions are marker interfaces. remote conditions combined with a dependency management component means that components can react (start/stop) based on the presence of a condition in a different framework.

Currently I think the RSA expect to find a dfi descriptor, so maybe an extensions is needed to service exported with descriptors are handled as marker interface services.

btw of course out of scope for this PR.

if (bytes >= sizeof(filter)) {
celix_logHelper_error(logHelper,"RSA import reg: The value(%s) of %s is too long.", rsaRpcType, RSA_RPC_TYPE_KEY);
celix_logHelper_error(logHelper,"RSA import reg: The value(%s) of %s is too long.", rsaShmRpcType, RSA_RPC_TYPE_KEY);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: incorrect indentation

char *savePtr = NULL;
char *token = strtok_r(ipStrListCopy, ",", &savePtr);
while (token != NULL) {
char *ip = celix_utils_trimInPlace(token);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it mean that each time we perform an RPC, we need to do these strdup strtok_r inet_pton things? It sounds bad.

Copy link
Contributor

@PengZheng PengZheng left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IP address is leaked from the service discovery into RSA, and discovery_zero_config is leaked into RSA. All service discoveries should hide behind a uniform interface, which ideally should be service URLs. RSA should only deal with service URL and all address resolving complexity and inherent dynamism for distributed system should be dealt within service discovery. There shouldn't be any special treatment for zero_config in RSA.

And these strdup strtok_r inet_pton things seem performance nightmare.

Copy link
Contributor

@pnoltes pnoltes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO the zeroconf discovery and remote service admins are now entangled and this is not needed.

bundles/remote_services/rsa_spi/include/remote_constants.h Outdated Show resolved Hide resolved
@@ -36,6 +36,15 @@
#define RSA_DFI_CONFIGURATION_TYPE "org.amdatu.remote.admin.http"
#define RSA_DFI_ENDPOINT_URL "org.amdatu.remote.admin.http.url"

/**
* @brief RSA Configuration type for zeroconf http, it is synonymous(https://docs.osgi.org/specification/osgi.cmpn/7.0.0/service.remoteservices.html#i1698916) with RSA_DFI_CONFIGURATION_TYPE, they refer to the same endpoint.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand this different.

As I understand it, the service.exported.configs and service.imported.configs refer to remote service admin configurations and not discovery.
Different discovery mechanism should work without knowledge of the remote service admins used and vica versa.

For example

  • RSA DFI adds a "org.amdatu.remote.admin.http.url" property when creating a endpoint for an export service.
  • Discovery (Zeroconf, configured or etcd) "just" announces and discovers the endpoints.
  • RSA DFI checks the config when importing a service through a endpoint and uses the "org.amdatu.remote.admin.http.url".

It is possible to support configuration and endpoint with a "ifname", "port", "ipdresses" and "path" next to a "url" property, but IMO this is then an extension to RSA DFI and not a ZEROCONF concern.

For example (snippet):

if (strncmp(configType, RSA_DFI_CONFIGURATION_TYPE, 1024) == 0) {
    const char *url = celix_properties_get(endpoint->properties, RSA_DFI_ENDPOINT_URL, NULL);
    if (url) {
        return true; //RSA_DFI config with  endpoint url
   }
       
    const char *ip = celix_properties_get(endpoint->properties, CELIX_RSA_DFI_ZEROCONF_ENDPOINT_IPADDRESSES, NULL);//the property is set by the discovery_zeroconf
    const char *port = celix_properties_get(endpoint->properties, CELIX_RSA_DFI_ZEROCONF_ENDPOINT_PORT, NULL);
    const char *path = celix_properties_get(endpoint->properties, CELIX_RSA_DFI_ZEROCONF_ENDPOINT_PATH, NULL);
        if (ip != NULL || port != NULL || path != NULL) {
            return true; //RSA_DFI config with a endpoint ip, port and path/
        }
} 
return false;

Copy link
Contributor

@PengZheng PengZheng Jan 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here are some inconsistencies between RSA and ZEROCONF: RSA may not bind all (i.e. bind to a specific ip address) while ZEROCONF will advertise all addresses associated with a network interface. The interface between RSA and ZEROCONF should be carefully designed to address this issue. Otherwise, there will be performance penalty, e.g. try addresses that have no binder.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO the zeroconf discovery and remote service admins are now entangled and this is not needed.

Adding the host name resolution mechanism to zeroconf_discovery does cause RSA to become entangled with zeroconf_discovery.
The main reason for adding the host name resolution mechanism to zeroconf_discovery is that if RSA binds to any address (0.0.0.0), then it does not need to configure a specific IP, and zeroconf_discovery resolves IP list from the host name, then gives the IP list to the client via the " <config_type>.ipaddresses" endpoint property. It means that if we use zeroconf_discovery, the remote service will still work even if RSA does not configure an IP.

For the above issue, should we do host name resolution in zeroconf_discovery?
If we use host name in the URL of the endpoint (e.g. http://computer.local:8080/service/example) maybe that will resolve the problem as well. (Host name resolution will be done by the RSA)

If we do host name resolution in zeroconf_discovery, we should design interfaces between RSA and zeroconf_discovery for distinguishing whether host name resolution is needed or not, because we don't need to do host name resolution for an endpoint that already specifies a specific IP. In my option, we can add a specific property(e.g. <config_type>.automatically_get_ip_by_discovery) to the endpoint description, and zeroconf_discovery will do host name resolution according to this property.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It means that if we use zeroconf_discovery, the remote service will still work even if RSA does not configure an IP.

That is a nice feature and for now I cannot think of a way to this without some coupling between the RSA and discovery.

The option is what you mention is a good way to opt-in for discovery specific behaviour.
Maybe more generic and not coupled to zeroconf. e.g:

  • If a remote endpoint has property has a property "CELIX_RSA_DISCOVERY_IP_ADRESSES" then the value will be updated to discovered ip addresses.

If I look at the RSA spec (https://docs.osgi.org/specification/osgi.cmpn/7.0.0/service.remoteserviceadmin.html#org.osgi.service.remoteserviceadmin.RemoteServiceAdmin), exportService does allow to return multiple ExportRegistration and thus multiple endpoints.

Maybe this can be combined and the RSA DFI can provide mutiple ExportRegistrations. 1 for the fixed IP and 1 for a dynamic IP adresses.

I will read the spec a bit more and check whether exporting multiple ExportRegistration (with multiple paths to the same exported service) is feasible.

Copy link
Contributor

@pnoltes pnoltes Jan 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have some new thoughts about the dynamic ip assignment resolving challenges.
First off, I think is good to come to a sound conclusion, but this does not mean that this should be directly solved in this pull request.

So if we agree on a desired solution, I will make a ticket for this and we can then decide what should flow back to this PR.

My thoughts:
a) Let RSA implementations decide if they support "dynamic IP fill-in" by providing a additional service property on the registered RSA service
b) Optionally RSA export registration that support dynamic IP fill-in should also opt-int for dynamic replacement by adding a endpoint property to the export registration properties
c) Let discovery implementations decide if the they support "interface specific" endpoints by providing a additional service property on the registered endpoint listener interface.
c) Update the Topology Manager to detect RSA services what support dynamic IP fill-in and in that case create multiple endpoints for a single export registration based on the available network interfaces and an optional network selection configuration. These endpoints are then forwarded to the discovery listener services that support network specific endpoints. The discovery implementation can pick and handle or drop endpoints based on the selected network interface.

The primary idea is that most of the boiler-plating to support dynamic IP fill-in is moved to the topology manager and kept away from the RSA and discovery implementations.

For the service/endpoint property something like the following can be used:

  • RSA Dynamic IP fill-in support
    • Property name: "rsa.dynamic.ip.support"
    • Type boolean
    • Indicates whether the RSA implementation supports dynamic IP address fill-in for service exports
  • RSA Export Registration replacement opt-in
    • Property name: rsa.export.dynamic.ip.optin
    • Type boolean
    • Description: Signals if a service export opts in for dynamic IP address replacement
  • RSA Export Registration dynamic replaceable property
    • Property name: rsa.ip.address
    • Type string
    • Description: The dynamically determined IP address for the endpoint.
  • Discovery interface-specific endpoints support.
    • Property Name: "discovery.interface.specific.endpoints.support
    • Type boolean
    • Description: Indicates if the discovery implementation supports handling of interface-specific endpoints.

I understand that this is different from the current solution, but maybe a more cleaner approach.

WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your reply.

First, I agree with this solution. But I still have some issues that need to confirm with you.

Update the Topology Manager to detect RSA services what support dynamic IP fill-in and in that case create multiple endpoints for a single export registration based on the available network interfaces and an optional network selection configuration. These endpoints are then forwarded to the discovery listener services that support network specific endpoints. The discovery implementation can pick and handle or drop endpoints based on the selected network interface.

Does this mean that the endpoint descriptions for dynamic IP are generated by Topology Manager when exporting service?
Should the network interface used to publish services be specified by Topology Manager or RSA?

How about dealing with it in two cases:
In the first case, if the RSA supports dynamic IP, RSA should bind its services to ANY address (0.0.0.0). Then the Topology Manager should specify which network interfaces the services are published to, and restrict access to the corresponding services from other network interfaces (e.g.: iptables -A INPUT -i eth0 -p tcp -- dport 80 -j DROP).

In the second case, if RSA does not support dynamic IP, RSA binds its network services to a specific IP, and its exported endpoint should specify which network interface the service is published to.

In the above case, we will define a generic endpoint property rsa.ifnames (Type string list). The property is used to specify which network interfaces the service is published to.

RSA Export Registration dynamic replaceable property

  • Property name: rsa.ip.address
  • Type string

When using dynamic IP, perhaps multiple IP are obtained, should the rsa.ip.address type be a string list?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your reply.

First, I agree with this solution. But I still have some issues that need to confirm with you.

Update the Topology Manager to detect RSA services what support dynamic IP fill-in and in that case create multiple endpoints for a single export registration based on the available network interfaces and an optional network selection configuration. These endpoints are then forwarded to the discovery listener services that support network specific endpoints. The discovery implementation can pick and handle or drop endpoints based on the selected network interface.

Does this mean that the endpoint descriptions for dynamic IP are generated by Topology Manager when exporting service? Should the network interface used to publish services be specified by Topology Manager or RSA?

Good point, this should indeed be the RSA.

How about dealing with it in two cases: In the first case, if the RSA supports dynamic IP, RSA should bind its services to ANY address (0.0.0.0). Then the Topology Manager should specify which network interfaces the services are published to, and restrict access to the corresponding services from other network interfaces (e.g.: iptables -A INPUT -i eth0 -p tcp -- dport 80 -j DROP).

In the second case, if RSA does not support dynamic IP, RSA binds its network services to a specific IP, and its exported endpoint should specify which network interface the service is published to.

In the above case, we will define a generic endpoint property rsa.ifnames (Type string list). The property is used to specify which network interfaces the service is published to.

That does indeed sound better. One of my cancern was to prevent too much repeated boiler plaiting between the RSA bundles, but indeed the RSA is binding on network interface and hence it should decide and informs whether is uses a single or multiple interfaces.

RSA Export Registration dynamic replaceable property

  • Property name: rsa.ip.address
  • Type string

When using dynamic IP, perhaps multiple IP are obtained, should the rsa.ip.address type be a string list?

List of string, but this is not yet supported. I am busy with a branch that updates properties for (among others) list of strings: https://github.com/apache/celix/tree/feature/674-improve-properties

I will make a ticket for yet another improvement on remote service and let it depend on #674

For this PR this remark can now be ignored.

(void)snprintf(scope, sizeof(scope), "(&(%s=*)(%s=%s))", CELIX_FRAMEWORK_SERVICE_NAME,
OSGI_RSA_ENDPOINT_FRAMEWORK_UUID, fwUuid);
celix_properties_set(props, OSGI_ENDPOINT_LISTENER_SCOPE, scope);
celix_properties_set(props, "DISCOVERY", "true");//Only use to avoid the discovery calls to unnecessary endpoint listener service.Endpoint should be filtered by the scope.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. I see this is used in discovery_common / discovery_endpointListenerAdded. I am not a fan of this approach, but IMO we can keep this for now.

assert(announcer->endpoints != NULL);
if (endpoints == NULL) {
celix_logHelper_logTssErrors(logHelper, CELIX_LOG_LEVEL_ERROR);
celix_logHelper_fatal(logHelper, "Announcer: Failed to create endpoints map.");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the log level should be error. This is what we currently describe in the development guide:

https://github.com/apache/celix/tree/dc0e0aebb282ce05b51631dd5c53b14783b856ba/documents/development#error-handling-and-logging

error: This level should be used to report issues that need immediate attention and might prevent the system from functioning correctly. These are problems that are unexpected and affect functionality, but not so severe that the process needs to stop. Examples include runtime errors, inability to connect to a service, etc.
fatal: Use this level to report severe errors that prevent the program from continuing to run. After logging a fatal error, the program will typically terminate.

Optionally we can also update the development guideline if we think situations like ENOMEM should be reported as fatal.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, ENOMEM should not be fatal.

@@ -532,7 +644,8 @@ static void *discoveryZeroconfAnnouncer_refreshEndpointThread(void *data) {
discoveryZeroconfAnnouncer_handleMDNSEvent(announcer);
}
} else if (result == -1 && errno != EINTR) {
celix_logHelper_error(announcer->logHelper, "Announcer: Error Selecting event, %d.", errno);
celix_logHelper_error(announcer->logHelper, "Announcer: Error Selecting event, %d.", errno);
sleep(1);//avoid busy loop
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Concerning the sleep(1) / retry on a error rc. I think this is fine, but currently the running is not updated in the else branch of if (result > 0) and this is an issue.

I think the running update can be moved to the end part of the while loop:

while (running) {
 ....
  celixThreadMutex_lock(&announcer->mutex);
  running = announcer->running;
  celixThreadMutex_unlock(&announcer->mutex);
}

ensuring that running is updated every loop.

@@ -532,7 +644,8 @@ static void *discoveryZeroconfAnnouncer_refreshEndpointThread(void *data) {
discoveryZeroconfAnnouncer_handleMDNSEvent(announcer);
}
} else if (result == -1 && errno != EINTR) {
celix_logHelper_error(announcer->logHelper, "Announcer: Error Selecting event, %d.", errno);
celix_logHelper_error(announcer->logHelper, "Announcer: Error Selecting event, %d.", errno);
sleep(1);//avoid busy loop
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can really do nothing locally to recover from this kind of error. This represents some long lasting exceptional system condition, which can luckily be modeled using Celix condition. Once some outside watchers get notified of this system exception, he/she can try to restart the bundle, which could fix the accidentally closed fd in this case.

I think generic system exception is a generally useful concept, which further extends error code and C++ exception. Combined with RSA, this means these exceptions can be watched remotely (cool). Event better, we don't need descriptors for Remote Celix conditions because they have no methods.

WDYT? @pnoltes @xuzhenbao

I think remote conditions are very useful and indeed this does not need a descriptor, because conditions are marker interfaces. remote conditions combined with a dependency management component means that components can react (start/stop) based on the presence of a condition in a different framework.

Currently I think the RSA expect to find a dfi descriptor, so maybe an extensions is needed to service exported with descriptors are handled as marker interface services.

btw of course out of scope for this PR.

@xuzhenbao
Copy link
Contributor Author

@pnoltes

I have updated the PR, it includes the following changes:

1.Move the work of exporting dynamic IP endpoints to the Topology Manager, the dynamic IP endpoints contain the following specific properties.
- celix.rsa.ip.addresses
The list of dynamic IPs, the Topology Manager should set an empty celix.rsa.ip.addresses property, and DISCOVERY will fill in the dynamic IP when it detects the celix.rsa.ip.addresses property
- celix.rsa.port
The port number of the remote service, its value is filled by RSA
- celix.rsa.ifname
Network interface name, set by Topology Manager

  1. The endpoint listener service of Discovery adds the property celix.rsa.discovery.interface.specific.endpoints.support, which indicates whether DISCOVERY supports dynamic IP filling based on the network interface name.

  2. The RSA service adds the property celix.rsa.dynamic.ip.support, which indicates whether RSA supports dynamic IP. When the celix.rsa.dynamic.ip.support property is true, the Topology Manager should generate dynamic IP endpoints based on the registration exported by RSA, and notify these endpoints to the DISCOVERY implementation that supports dynamic IP.

  3. Add configuration property CELIX_RSA_INTERFACES_OF_PORT_ (e.g. CELIX_RSA_INTERFACES_OF_PORT_8080=eth0,eth1), which indicates to which network interfaces the server of the corresponding port should be bound. The Topology Manager should fill in the celix.rsa.ifname property based on these configurations when creating dynamic IP endpoints.

  4. Add the Facility of libcurl error codes, which is used to distinguish between http status code (CELIX_FACILITY_HTTP) and libcurl error codes in rsa_dfi

  5. Add CELIX_RSA prefix for constants in the rsa_spi

  6. celix.rsa.ip.addresses currently uses a comma-separated string, and it will use a string array (It depends on Type aware properties improvements #674)

  7. Topology Manager and RSA_DFI still leave some deprecated interfaces usage, and the related code is planned to be cleaned up in other PRs.

@pnoltes
Copy link
Contributor

pnoltes commented Feb 5, 2024

7. nd it will use a string array (

Thanks for the trigger, I will try to find some time to review this in the coming days.

}
bool dynamicIpSupport = celix_bundleContext_getPropertyAsBool(ctx, CELIX_RSA_DFI_DYNAMIC_IP_SUPPORT, CELIX_RSA_DFI_DYNAMIC_IP_SUPPORT_DEFAULT);
if (dynamicIpSupport) {
status = celix_properties_setBool(props, CELIX_RSA_DYNAMIC_IP_SUPPORT, true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

}

int size = celix_arrayList_size(ifNames);
for (int i = 0; i < size; ++i) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 , indeed multiple endpoints based on dynamic intf resolution

Copy link
Contributor

@pnoltes pnoltes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall LGTM. When this is merged I would like to try and remove the service_registration and service_reference usage in C RSA, but that is for later.

Copy link
Contributor

@PengZheng PengZheng left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still not familiar with this part of code base, and thus will not be able to review its overall design. Instead, I had a look at the hot path (i.e. remoteServiceAdmin_send) to see how various parts fit together.
This PR could be merged once the latest issue regarding CURL is addressed.

Copy link
Contributor

@PengZheng PengZheng left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@xuzhenbao xuzhenbao merged commit 0bca5ef into apache:master Feb 20, 2024
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants