Skip to content

Configure number of thread used by Netty base RESTCONF#2576

Open
Tobianas wants to merge 2 commits intoPANTHEONtech:mainfrom
Tobianas:osgi-netty
Open

Configure number of thread used by Netty base RESTCONF#2576
Tobianas wants to merge 2 commits intoPANTHEONtech:mainfrom
Tobianas:osgi-netty

Conversation

@Tobianas
Copy link
Copy Markdown
Contributor

No description provided.

@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello @Tobianas, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the Netty-based RESTCONF module by providing new configuration options for its underlying thread pool. These changes enable users to specify the number of worker threads and a group name, offering greater control over the server's performance and resource utilization. The implementation also involves a refactoring of the Netty endpoint to integrate with OSGi-managed components.

Highlights

  • Configurable Netty Thread Pool: Introduced the ability to configure the number of worker threads and the group name for the Netty-based RESTCONF server, allowing for better resource management.
  • Netty Endpoint Refactoring: The internal Netty endpoint initialization was refactored to utilize OSGiNettyEndpoint, streamlining its lifecycle management.
  • Configuration and Test Updates: Updated the RESTCONF configuration class, builder, and associated tests to support the new thread pool parameters, including default values and JSON loading.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • lighty-modules/lighty-restconf-netty-nb-community/src/main/java/io/lighty/modules/northbound/netty/restconf/community/impl/NettyRestConf.java
    • Added OSGiNettyEndpoint import.
    • Introduced groupName and workThreads fields and updated the constructor to accept them.
    • Modified initProcedure to use OSGiNettyEndpoint with configurable groupName and workThreads.
    • Removed the nettyEndpoint field and its explicit close() call in stopProcedure.
  • lighty-modules/lighty-restconf-netty-nb-community/src/main/java/io/lighty/modules/northbound/netty/restconf/community/impl/NettyRestConfBuilder.java
    • Updated the build() method to pass groupName and workThreads from the configuration to the NettyRestConf constructor.
  • lighty-modules/lighty-restconf-netty-nb-community/src/main/java/io/lighty/modules/northbound/netty/restconf/community/impl/config/NettyRestConfConfiguration.java
    • Added groupName and workThreads properties with default values.
    • Updated constructors to handle the new workThreads property.
    • Introduced getter and setter methods for groupName and workThreads.
    • Modified equals() and hashCode() methods to include workThreads.
  • lighty-modules/lighty-restconf-netty-nb-community/src/test/java/io/lighty/modules/northbound/netty/restconf/community/impl/tests/NettyRestConfConfigurationTest.java
    • Added assertions to verify the default values of workThreads and groupName.
    • Added assertions to confirm correct loading of groupName and workThreads from a configuration stream.
  • lighty-modules/lighty-restconf-netty-nb-community/src/test/resources/restconf-config.json
    • Added workThreads and groupName fields to the example RESTCONF configuration JSON.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces configurable thread management for the Netty-based RESTCONF server, allowing groupName and workThreads to be specified for performance tuning and resource management. A medium-severity vulnerability was identified where the user-configurable groupName is passed to a BootstrapFactory without sanitization, which could lead to log injection. Furthermore, critical issues related to lifecycle management and configuration consistency need to be addressed, including the improper management of OSGiNettyEndpoint and inconsistencies in NettyRestConfConfiguration's copy constructor and equals/hashCode implementations.

I am having trouble creating individual review comments. Click here to see my feedback.

lighty-modules/lighty-restconf-netty-nb-community/src/main/java/io/lighty/modules/northbound/netty/restconf/community/impl/NettyRestConf.java (58)

high

The OSGiNettyEndpoint is instantiated in initProcedure() but is not assigned to any field. To ensure proper lifecycle management and resource cleanup, especially during stopProcedure(), the OSGiNettyEndpoint instance should be stored in a private field.

    private OSGiNettyEndpoint nettyEndpoint;

lighty-modules/lighty-restconf-netty-nb-community/src/main/java/io/lighty/modules/northbound/netty/restconf/community/impl/NettyRestConf.java (103)

high

After creating the OSGiNettyEndpoint, it needs to be assigned to the newly introduced nettyEndpoint field to allow for its management and proper closing.

        this.nettyEndpoint = new OSGiNettyEndpoint(server, service, mdsalRestconfStreamRegistry, pros);

lighty-modules/lighty-restconf-netty-nb-community/src/main/java/io/lighty/modules/northbound/netty/restconf/community/impl/NettyRestConf.java (107-114)

high

This block, which was responsible for closing the SimpleNettyEndpoint, has been removed. With the transition to OSGiNettyEndpoint, it is crucial to re-introduce similar logic to properly close the new OSGiNettyEndpoint instance. Failure to do so can lead to resource leaks and improper shutdown. The OSGiNettyEndpoint should be stored in a field and closed here, similar to the following:

        if (nettyEndpoint != null) {
            try {
                nettyEndpoint.close();
            } catch (Exception e) {
                LOG.error("Failed to stop Netty endpoint!", e);
                stopSuccessful = false;
            }
        }

lighty-modules/lighty-restconf-netty-nb-community/src/main/java/io/lighty/modules/northbound/netty/restconf/community/impl/config/NettyRestConfConfiguration.java (54)

high

The copy constructor NettyRestConfConfiguration(final NettyRestConfConfiguration restConfConfiguration) copies workThreads but omits groupName. To ensure full configuration consistency, groupName should also be copied.

        this.workThreads = restConfConfiguration.getWorkThreads();
        this.groupName = restConfConfiguration.getGroupName();

lighty-modules/lighty-restconf-netty-nb-community/src/main/java/io/lighty/modules/northbound/netty/restconf/community/impl/config/NettyRestConfConfiguration.java (171)

high

The equals() method should include the groupName field in its comparison to ensure that two NettyRestConfConfiguration objects are correctly evaluated for equality. Without it, objects with different groupName values could be considered equal.

            && Objects.equals(workThreads, that.workThreads)
            && Objects.equals(groupName, that.groupName);

lighty-modules/lighty-restconf-netty-nb-community/src/main/java/io/lighty/modules/northbound/netty/restconf/community/impl/config/NettyRestConfConfiguration.java (177)

high

The hashCode() method should include the groupName field in its calculation. This is essential to maintain the contract between equals() and hashCode(), ensuring that equal objects produce the same hash code.

            domMountPointService, inetAddress, httpPort, restconfServletContextPath, workThreads, groupName);

lighty-modules/lighty-restconf-netty-nb-community/src/main/java/io/lighty/modules/northbound/netty/restconf/community/impl/NettyRestConf.java (101)

security-medium medium

The groupName variable, which can be sourced from an external JSON configuration, is passed directly to the BootstrapFactory constructor. If the BootstrapFactory implementation logs this group name without proper sanitization, this could lead to log injection vulnerabilities. An attacker could provide a malicious group name containing newlines and other characters to forge log entries, potentially obscuring other malicious activities or misleading system administrators. It is recommended to sanitize the groupName to only allow a restricted set of characters (e.g., alphanumeric and dashes) before passing it to the factory.

@Tobianas Tobianas force-pushed the osgi-netty branch 2 times, most recently from 066f3ba to ebe0d2a Compare February 25, 2026 12:36
@Tobianas
Copy link
Copy Markdown
Contributor Author

/gemini review

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request updates the Netty-based RESTCONF implementation to allow configuration of the number of worker threads. However, it introduces a significant regression in resource management: the newly introduced OSGiNettyEndpoint is neither stored nor closed, leading to a resource leak and potential Denial of Service (DoS) upon module restarts. Additionally, the workThreads parameter lacks validation, which could be exploited for resource exhaustion attacks. Beyond this, the NettyRestConfConfiguration copy constructor is incomplete as it fails to copy the groupName property, which could lead to incorrect configurations.

new BootstrapFactory("lighty-restconf-nb-worker", 0), configuration);
final var bootstrapFactory = new BootstrapFactory(groupName ,workThreads);
final var pros = OSGiNettyEndpoint.props(bootstrapFactory, configuration);
new OSGiNettyEndpoint(server, service, mdsalRestconfStreamRegistry, pros);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

security-high high

The OSGiNettyEndpoint instance created here is not stored, leading to a resource leak and potential Denial of Service (DoS) upon module restarts. As OSGiNettyEndpoint manages network resources and implements AutoCloseable, it must be explicitly stored and closed to release these resources. The current 'fire-and-forget' approach relies on implicit constructor side-effects for lifecycle management, which is less explicit and harder to maintain compared to the previous SimpleNettyEndpoint implementation. It is recommended to store the instance in a field and manage its lifecycle explicitly.

Suggested change
new OSGiNettyEndpoint(server, service, mdsalRestconfStreamRegistry, pros);
this.nettyEndpoint = new OSGiNettyEndpoint(server, service, mdsalRestconfStreamRegistry, pros);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Resolved by using SimpleNettyEndpoint in latest patch

Comment on lines 109 to 111
protected boolean stopProcedure() {
boolean stopSuccessful = true;
if (nettyEndpoint != null) {
try {
nettyEndpoint.close();
} catch (Exception e) {
LOG.error("Failed to stop Netty endpoint!", e);
stopSuccessful = false;
}
}
if (mdsalRestconfStreamRegistry != null) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

security-high high

The stopProcedure method no longer closes the Netty endpoint. This is a regression from the previous implementation and, combined with the missing reference in initProcedure, leads to a resource leak. The Netty endpoint should be stored in a field and closed here.

Suggested change
protected boolean stopProcedure() {
boolean stopSuccessful = true;
if (nettyEndpoint != null) {
try {
nettyEndpoint.close();
} catch (Exception e) {
LOG.error("Failed to stop Netty endpoint!", e);
stopSuccessful = false;
}
}
if (mdsalRestconfStreamRegistry != null) {
protected boolean stopProcedure() {
boolean stopSuccessful = true;
if (nettyEndpoint != null) {
try {
nettyEndpoint.close();
} catch (Exception e) {
LOG.error("Failed to stop Netty endpoint!", e);
stopSuccessful = false;
}
}
if (mdsalRestconfStreamRegistry != null) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Resolved by using SimpleNettyEndpoint in latest patch

Add the ability to configure groupName and workThreads using
json config.

JIRA: LIGHTY-398
Signed-off-by: tobias.pobocik <tobias.pobocik@pantheon.tech>
Add tests to verify functionality of reading BootstrapFactory from json
file and its default values if no config is provided.

JIRA: LIGHTY-398
Signed-off-by: tobias.pobocik <tobias.pobocik@pantheon.tech>
this.domMountPointService = domMountPointService;
}


Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

why empty line?

private InetAddress inetAddress = InetAddress.getLoopbackAddress();
private int httpPort = 8888;
private String restconfServletContextPath = "restconf";
private String groupName = "lighty-netty-worker"; //use as default
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

this is not Java style comment, and comments have no meaning IMO

return workThreads;
}

public void setWorkThreads(int workThreads) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

final

return groupName;
}

public void setGroupName(String groupName) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

final

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.

2 participants