Eventlet-removal
Contents
- 1 Why Eventlet Needs to Be Removed
- 2 Potential Impacts if the Migration is Not Completed
- 3 Different Kind of Eventlet Usages
- 4 Save the Date
- 5 Migration's Milestones
- 6 Targeted Releases
- 7 Want to Discuss?
- 8 Getting Started
- 8.1 Available Alternatives to Eventlet
- 8.2 How to Analyze Your Deliverables
- 8.3 Identifying Common Pattern
- 8.3.1 1. Importing Eventlet
- 8.3.2 2. Use of `monkey_patch()`
- 8.3.3 3. Timeout and Deadline Management
- 8.3.4 4. Green Threads and GreenPool
- 8.3.5 5. Use of `eventlet.wsgi`
- 8.3.6 6. Deferred Tasks and Scheduling
- 8.3.7 7. Use in Tests with `mock`
- 8.3.8 8. Presence in Configuration Files and Dependencies
- 8.3.9 9. References in Documentation
- 8.4 Migration Plan
- 8.4.1 1. Direct Import of Eventlet
- 8.4.2 2. `monkey_patch()`
- 8.4.3 3. Timeout and Deadline Management
- 8.4.4 4. Green Threads and GreenPool
- 8.4.5 5. Use of `eventlet.wsgi`
- 8.4.6 6. Deferred Tasks and Scheduling (`spawn_after`)
- 8.4.7 7. Use in Tests with `mock`
- 8.4.8 8. Presence in Configuration Files and Dependencies
- 8.4.9 9. References in Documentation
- 8.5 Migration Plan Summary
- 8.6 Proposed Checklist for Migrating Each Deliverable
- 8.7 Roles and Responsibilities
- 9 Tracking Progress
- 10 Useful Links
- 11 FAQ
- 12 Teams efforts
- 13 Map of the Impacted Deliverables
- 14 Existing spec repos where Eventlet appear
Why Eventlet Needs to Be Removed
Eventlet, though once popular for concurrent execution using "greenthreads," now presents several limitations and issues that make it an outdated solution for modern projects like OpenStack:
1. Incompatibility with Recent Versions of Python:
Eventlet struggles to keep up with the evolution of Python, particularly with recent versions (such as Python 3.12 and beyond). Some of its internal functionalities, such as "monkey patching" standard libraries, no longer work correctly or cause unexpected behavior. This limits projects from adopting the latest improvements in Python, including critical security patches.
2. Inefficient Resource and Thread Management:
The greenthreads used by Eventlet can lead to excessive memory consumption and poor resource management, especially under heavy loads or in large-scale applications. Given that OpenStack operates in a distributed and highly parallel environment, this can become a significant bottleneck for overall performance.
3. Maintenance and Security Issues:
Eventlet suffers from a lack of active maintenance and does not receive regular updates to address security vulnerabilities and compatibility issues. This exposes OpenStack to potential security risks if flaws in Eventlet are not addressed promptly.
4. Outdated Approach to Concurrency Programming:
With the emergence of more modern solutions like `asyncio` or `concurrent.futures`, which are natively integrated into Python, using Eventlet feels outdated. These newer libraries offer better concurrency management, improved performance, and tighter integration with the current Python ecosystem.
5. Inability to Adopt New Linux Distributions:
Many modern Linux distributions, such as Ubuntu, RHEL, and others, now ship with newer versions of Python that are not supported by Eventlet. Without migrating away from Eventlet, OpenStack will face challenges in adopting these newer distributions. This will limit the ability to stay current with the latest infrastructure improvements and security enhancements provided by modern operating systems.
Potential Impacts if the Migration is Not Completed
Failure to migrate away from Eventlet could have significant consequences for OpenStack-based projects:
1. Blockage of Python Updates:
Continuing to use Eventlet may cause OpenStack to be stuck on older versions of Python. This prevents the adoption of new features, performance improvements, and —most importantly—security patches offered by newer versions of Python.
2. Security Vulnerabilities Risk:
Given Eventlet's lack of maintenance, unresolved security flaws could leave OpenStack systems vulnerable to attacks. Failing to migrate to modern solutions exposes the infrastructure to major security risks.
3. Degradation of Performance and Scalability:
OpenStack handles large workloads in distributed environments, and Eventlet’s inefficient resource management can cause slowdowns and failures. Without migration, this could limit OpenStack's ability to scale smoothly and handle increasingly larger data volumes.
4. Inability to Adopt New Linux Distributions:
If the migration from Eventlet is not completed, OpenStack will struggle to support modern Linux distributions that come with newer versions of Python. Distributions like Ubuntu and RHEL now ship with versions of Python that are incompatible with Eventlet. This will hinder the ability to upgrade to these distributions, which are critical for staying up-to-date with the latest security fixes and performance improvements.
5. Increased Maintenance Costs:
Continuing to rely on an outdated technology will increase maintenance costs as it becomes harder to find fixes or workarounds for technical issues. This will lead to a growing technical debt that will be difficult to manage in the long term.
To ensure the longevity, stability, and security of OpenStack, it is crucial to migrate to modern solutions like `asyncio` or `concurrent.futures`. This will not only overcome Eventlet's current limitations but also ensure that OpenStack remains capable of meeting performance, security, and scalability demands. Moreover, migrating is essential for supporting the latest Linux distributions like Ubuntu and RHEL, which include newer versions of Python that are not compatible with Eventlet.
The following sections aims to guide you during your migration journey.
Different Kind of Eventlet Usages
In OpenStack, there exist two kinds of deliverables based on Eventlet:
- deliverables for whom Eventlet is optional and can be disabled
- deliverables that cannot live without Eventlet
Both deliverables won't be migrated the same way.
For the first scenario - optional Eventlet - we suggest completely disabling Eventlet first, and then from there, start migrating your deliverables. This kind of deliverables often allows switching from one kind of execution model to another, e.g., Eventlet or futurist. We encourage migrating all your occurrences over the models non-based on Eventlet.
Steps to Disable Eventlet in Optional Deliverables
1. Analyze Dependencies and Usage of Eventlet
- Identify all parts of the code that depend on Eventlet. This includes direct imports, the use of greenthreads, and specific methods such as `monkey_patch()`, `Timeout`, or `eventlet.wsgi`.
- Perform a search across the codebase to locate these Eventlet elements. Use search tools like `grep`, or more specialized tools like `beagle`, to get an overview of Eventlet occurrences.
2. Selective Eventlet Deactivation
- In some cases, it’s possible to disable Eventlet via configuration settings. Check if your project or framework offers this capability.
- If configuration doesn’t explicitly allow for disabling, start by commenting out or removing the Eventlet import lines and test the execution of the code in a local or test environment.
- Use native alternatives to replace functionalities dependent on Eventlet. For instance, replace greenthreads with standard threads or asynchronous processes using `asyncio`.
3. Progressive Refactoring of Eventlet Entry Points
- Substitute `monkey_patch()` : Replace all occurrences of `eventlet.monkey_patch()` with explicitly defined alternatives (e.g., use `asyncio.sleep` for delays or standard libraries for threads and sockets).
- Timeout Management : Replace the usage of `eventlet.timeout.Timeout` with `asyncio.wait_for()` or equivalent exception handlers.
- Greenthreads and Thread Pools : Replace calls to `eventlet.spawn()` or `GreenPool()` with `asyncio.create_task()` or `concurrent.futures.ThreadPoolExecutor()` for concurrency management.
4. Unit and Functional Testing
- After disabling Eventlet and refactoring critical elements, run existing unit and functional tests to ensure the code remains stable.
- Use `mock` to simulate asynchronous behaviors in your tests (e.g., patching `asyncio` instead of Eventlet).
5. Performance and Stability Validation
- Assess the application's performance after disabling Eventlet, particularly in high-load scenarios. The goal is to ensure that using `asyncio` or standard threads provides equivalent or better performance.
- Also, monitor memory consumption and exception handling, as Eventlet’s greenthread implementation may differ from standard threads or `asyncio`.
6. Document the Changes
- Once Eventlet is successfully disabled, clearly document the changes made and the new dependency requirements (e.g., `asyncio` or `concurrent.futures`).
- Outline the new execution models so that other developers are aware of the modifications and the new behavior of the code.
7. Complete Migration Phase
- Once Eventlet is disabled and alternatives are in place, you can begin the full migration to a modern solution like `asyncio` by more extensively refactoring code that still depends on the old Eventlet-based architecture.
The sections below aims to give you a way to identify the Eventlet patterns, and aims to give refactoring guidance.
Save the Date
List of the coming events related to the Eventlet removal that could interest the reader.
Cross Project Events
1.TC/Cross-project session:
- Date: 2024 21st October (Monday) - Time: 1500 UTC - Meeting link: https://meetpad.opendev.org/oct2024-ptg-os-tc - Etherpad: https://etherpad.opendev.org/p/oct2024-ptg-os-tc
2. Eventlet Removal Open Discussion Hours:
- Date: 2024 23rd October (Wednesday) - Time: 1300-1500 UTC - Meeting link: https://meetpad.opendev.org/oct2024-ptg-eventlet-removal - Etherpad: https://etherpad.opendev.org/p/oct2024-ptg-eventlet-removal
Project-specific events
1. Glance - Eventlet Removal Session
- Date: 2024 24th October (Thursday) - Time: 16:00-16:30 UTC - Meeting link: https://meetpad.opendev.org/oct2024-ptg-glance - Etherpad: https://etherpad.opendev.org/p/oct2024-ptg-glance#L174
Migration's Milestones
- Adapting common libraries (Oslo, etc...) - e.g: introducing an Async Engine Facade to oslo.db, adapting oslo.service to not relying on Eventlet;
- Services migration - removing Eventlet usages from OpenStack services;
- Common libraries migration - common libraries depends on Eventlet because at a higher level - at the services level - Eventlet is required, we cannot remove this kind of Eventlet occurence from the common libraries while services are not fully migrated;
- Removing Eventlet from our global requirements;
- Abandoning Eventlet.
Targeted Releases
Fully removing Eventlet from OpenStack will surely take several series, we target, at least, the H or I series.
Want to Discuss?
#eventlet-removal
Follow the #eventlet-removal tag. It will be used everywhere to tag all the related things to this topic:
- gerrit patches
- mailing list threads
- OpenStack irc channel
- RedHat slack channel
- ...
If you want to discuss about the Eventlet removal then dial #eventlet-removal.
You can join one of these channels or submit a new patch with a topic set to #eventlet-removal or open a new thread with the #eventlet-removal tag.
The Pop-up team
A Pop-up team is constituted to manage this initiative, do not hesitate to contact this team to get feedback or answers.
Getting Started
Available Alternatives to Eventlet
We identified the following alternatives to replace Eventlet:
Do not hesitate to take a look to the following resources:
- alternatives officially supported by Eventlet;
- the alternatives proposed into the OpenStack community goal;
- a curated list of Python asyncio frameworks, libraries, software and resources.
How to Analyze Your Deliverables
Teams are invited to analyze their deliverables to see their kind of Eventlet usages, here is an example with Oslo:
$ pip install beagle
$ beagle search --ignore-comments -f link --repo-pattern "openstack/oslo*" 'eventlet'
The following sections aims to give you guidance to identify your usages and use cases.
Identifying Common Pattern
This section aims to help you identify the various patterns that you can find on your deliverables.
1. Importing Eventlet
Eventlet is imported in two main ways:
- Direct import:
import eventlet
- Specific import of Eventlet submodules:
from eventlet.timeout import Timeout
from eventlet import greenthread
from eventlet import hubs
2. Use of `monkey_patch()`
The use of the `eventlet.monkey_patch()` method is frequent and aims to replace some standard libraries (such as threads or sockets) with their asynchronous equivalents compatible with Eventlet's model.
- Explicit calls to `monkey_patch`:
eventlet.monkey_patch()
eventlet.monkey_patch(all=True)
eventlet.monkey_patch(time=True)
eventlet.patcher.monkey_patch(all=False, socket=True)
3. Timeout and Deadline Management
The use of `eventlet.timeout.Timeout` is common to manage waiting periods or deadlines for blocking operations.
- Use of `Timeout` in a `with` or `try-except` block:
with eventlet.Timeout(timeout, True):
# Do something
except eventlet.timeout.Timeout:
# Handle the timeout
4. Green Threads and GreenPool
Eventlet provides "greenthread" versions of classic threads as well as thread pools adapted to its asynchronous model.
- Use of GreenThread and GreenPool:
self.pool = eventlet.GreenPool(threads)
eventlet.spawn(func)
eventlet.spawn_n(func)
5. Use of `eventlet.wsgi`
Eventlet is sometimes used to handle WSGI (Web Server Gateway Interface) servers, particularly via `eventlet.wsgi`.
- Example of use with `eventlet.wsgi`:
import eventlet.wsgi
eventlet.wsgi.server(socket, application, custom_pool=self.pool)
6. Deferred Tasks and Scheduling
The use of `eventlet.spawn_after()` to execute tasks after a delay is also a recurring pattern.
- Example of `spawn_after`:
eventlet.spawn_after(3.5, update_db)
7. Use in Tests with `mock`
In tests, Eventlet is sometimes patched or mocked to simulate its behavior or to control asynchronous tests.
- Examples of use in tests:
@mock.patch.object(eventlet, 'monkey_patch')
@mock.patch('eventlet.spawn')
8. Presence in Configuration Files and Dependencies
Eventlet is explicitly mentioned in configuration files as a dependency in `requirements.txt` and `setup.cfg` files.
- Dependencies:
eventlet>=0.18.2
eventlet!=0.20.1,>=0.18.2 # MIT
9. References in Documentation
Some parts of the documentation or code comments refer to the use of Eventlet, either explaining why it is used or mentioning alternatives.
- Example in documentation:
If eventlet is used, then this engine will not block other threads
Migration Plan
Here’s a proposed migration plan to replace Eventlet with a more modern and efficient solution like asyncio or concurrent.futures, while considering each of the identified patterns. This plan should be used in addition of the official migration guide provided into the Eventlet documentation:
https://eventlet.readthedocs.io/en/latest/asyncio/asyncio.html
1. Direct Import of Eventlet
Migration:
- Replace `import eventlet` and specific Eventlet submodules with asyncio, or other libraries such as `concurrent.futures`.
Steps:
- Review the code for all occurrences of `eventlet` imports.
- Replace with equivalent asyncio or standard Python concurrency libraries.
Example:
# Before
import eventlet
# After
import asyncio
2. `monkey_patch()`
Migration:
- Monkey-patching should be avoided because it changes standard library behavior, which can cause unexpected side effects.
- Refactor the code to use explicit asyncio or threading-based code.
Steps:
- Identify all places where `eventlet.monkey_patch()` is used.
- Replace patched calls (e.g., `time.sleep()`, `threading`) with non-blocking alternatives (e.g., `asyncio.sleep()`, `concurrent.futures.ThreadPoolExecutor`).
Example:
# Before
eventlet.monkey_patch()
# After
# Use asyncio or threading where applicable without monkey-patching.
3. Timeout and Deadline Management
Migration:
- Use `asyncio.TimeoutError` or `asyncio.wait_for()` to handle timeout operations.
Steps:
- Replace `eventlet.Timeout()` with `asyncio.wait_for()`.
- Ensure that any blocking operations are handled asynchronously.
Example:
# Before
with eventlet.Timeout(timeout, True):
# Do something
# After
async def main():
try:
await asyncio.wait_for(task, timeout)
except asyncio.TimeoutError:
# Handle timeout
4. Green Threads and GreenPool
Migration:
- Replace Eventlet's green threads with `asyncio` tasks or `concurrent.futures` for multithreading or multiprocessing.
Steps:
- Replace `eventlet.GreenPool` with `asyncio.gather()` or `concurrent.futures.ThreadPoolExecutor`.
- Replace `eventlet.spawn()` and `eventlet.spawn_n()` with `asyncio.create_task()` or `executor.submit()` from concurrent.futures.
Example:
# Before
pool = eventlet.GreenPool(threads)
pool.spawn(func)
# After
async def func():
# Function implementation
asyncio.create_task(func())
5. Use of `eventlet.wsgi`
Migration:
- Replace Eventlet's WSGI handling with a modern asynchronous web framework, such as `aiohttp`, `FastAPI`, or `uvicorn` (requires all code be ported to asyncio)
- Replace Eventlet's WSGI handling with a plain wsgi framework such as `gunicorn` (does not require porting to asyncio)
zzzeek: why not a plain WSGI framework? There is no need for code that transparently uses eventlet for wsgi to explicitly use asyncio and convert all functions to use `async`; it should use standard wsgi patterns directly which can be run in a threaded container like mod_wsgi (we use mod_wsgi right now for web services). see masakari for example. gunicorn is currently present in requirements as well
Steps:
- Replace `eventlet.wsgi` server code with an asyncio-compatible web server like `uvicorn`.
- Update the application to be compatible with asynchronous HTTP handling.
zzzeek: How can the above be achieved for projects based on oslo.service? will an alternative to oslo.service be introduced or will we modify oslo.service to include traditional wsgi support not based on eventlet ?
Example:
# Before
import eventlet.wsgi
eventlet.wsgi.server(socket, application, custom_pool=self.pool)
# After
# Use an asynchronous web server like Uvicorn
import uvicorn
uvicorn.run("module_name:app", host="0.0.0.0", port=8000)
6. Deferred Tasks and Scheduling (`spawn_after`)
Migration:
- Use `asyncio.sleep()` or `asyncio.call_later()` for scheduling delayed tasks.
Steps:
- Replace `eventlet.spawn_after()` with `asyncio.create_task()` combined with `asyncio.sleep()`.
Example:
# Before
eventlet.spawn_after(3.5, update_db)
# After
async def update_db():
await asyncio.sleep(3.5)
# Perform database update
asyncio.create_task(update_db())
7. Use in Tests with `mock`
Migration:
- Ensure that tests are updated to mock the corresponding asyncio or threading features instead of Eventlet’s patched functions.
Steps:
- Replace Eventlet mock patches with mocks for asyncio or threading functions.
- Use `unittest.mock` or `pytest` to mock async tasks.
Example:
# Before
@mock.patch.object(eventlet, 'monkey_patch')
# After
@mock.patch('asyncio.sleep')
8. Presence in Configuration Files and Dependencies
Migration:
- Remove Eventlet from `requirements.txt` and `setup.cfg` files.
- Ensure that new dependencies (such as `asyncio` or `uvicorn`) are added where needed.
Steps:
- Remove all references to Eventlet in the configuration files.
- Replace them with modern asynchronous libraries.
Example:
# Before
eventlet>=0.18.2
# After
# Remove Eventlet, add necessary asyncio libraries
aiohttp>=3.7.0
9. References in Documentation
Migration:
- Update all documentation and code comments to reflect the switch from Eventlet to asyncio or other modern libraries.
Steps:
- Review the documentation for all mentions of Eventlet.
- Update examples and explanations to refer to the new concurrency model.
Example:
# Before
If eventlet is used, the engine will not block other threads
# After
If asyncio is used, tasks will run concurrently without blocking each other.
Migration Plan Summary
1. Preparation:
- Audit code for Eventlet usage.
- Identify areas where direct migration (e.g., replacing `monkey_patch()`) will be challenging.
2. Refactor Core Logic:
- Refactor blocking I/O operations with asyncio’s non-blocking equivalents or Awaitlet.
- Replace timeouts, task scheduling, and WSGI servers with modern async solutions.
3. Testing and Validation:
- Refactor test cases to mock asyncio or threading instead of Eventlet.
- Ensure comprehensive testing of the new concurrency model, especially for timeouts and green threads.
4. Documentation and Cleanup:
- Update all related documentation.
- Remove Eventlet from dependencies and configuration files.
5. Deployment and Monitoring:
- Deploy the refactored code and closely monitor for performance or concurrency issues.
This plan ensures that the migration from Eventlet to modern asynchronous libraries like `asyncio` (or other alternatives) happens incrementally, reducing risks and ensuring code stability.
You can apply this plan into your team by using the following checklist.
Proposed Checklist for Migrating Each Deliverable
1. Identification of Eventlet Occurrences:
- Objective: List all occurrences of Eventlet in the deliverable, including imports, usage of `monkey_patch()`, `Timeout`, greenthreads, etc.
- Action: Use search tools (such as `beagle`) to locate all instances of Eventlet in the source code.
2. Context of Usage:
- Objective: Document the context of each Eventlet occurrence, including the impacted components (WSGI, threads, timeout management, etc.) and the potential impact of its removal.
- Action: For each identified occurrence, add a note explaining its role and importance in the functionality of the deliverable.
3. Replacement Plan:
- Objective: Define how each occurrence of Eventlet will be replaced with a modern alternative (e.g., `asyncio`, `concurrent.futures`, `threading`).
- Action: Describe the specific steps for refactoring or replacing each component.
4. Progress Tracking:
- Objective: Implement a progress tracker for the migration of each component within the deliverable.
- Action: Create a dedicated section in the checklist to track the status of each task (in progress, completed, awaiting testing, etc.).
5. Testing and Validation:
- Objective: Ensure that the deliverable works correctly after the migration by running specific unit and functional tests.
- Action: Document test results after each phase of the migration and validate the stability of the deliverable.
6. Bug and Incident Tracking:
- Objective: Keep track of issues encountered during or after the migration and ensure they are resolved.
- Action: Log bugs or incidents related to the migration, with a resolution status for each issue.
7. Documentation of Changes:
- Objective: Update technical documentation to reflect the changes made during the migration.
- Action: Provide a summary of modifications in the deliverable and describe the new concurrency management practices (e.g., adopting `asyncio`).
Roles and Responsibilities
To help teams to manage the organisational aspects of the migration, we propose the following roles and responsibilities. OpenStack is maintained by several companies and organisations, the following structure aims to provide a minimal template for teams organisation to ensure that everyone is on the same page and have a clear understanding on how we work.
The Eventlet migration is complex, without a bit of structure your team might suffer of that migration. The future of your deliverables depends on it.
We strongly encourage teams to adopt this structure.
Technical Lead Role
The technical lead will be responsible for:
- Supervision: Monitoring the technical progress of the migration within the team.
- Support: Providing assistance to other developers and troubleshooting any technical issues related to the migration.
- Reporting: Submitting regular progress reports, listing impacted deliverables, patterns of Eventlet identified, and participating in monthly meetings with the team product manager.
- Technology Updates: Staying up-to-date on the latest technical news and updates related to the migration, and sharing this information with the team.
- Coordination: Working closely with the product manager to ensure that the team has the necessary resources to complete the migration.
- Communication: Acting as the main point of contact for questions or issues within the team regarding the migration process.
Product Manager’s Role
The product manager is responsible for coordinating and facilitating the Eventlet removal within their team. They ensure that the necessary resources and time are allocated for the transition and that progress is tracked regularly. Key Responsibilities:
- Prioritization and Planning: Ensure the migration is prioritized in the team's roadmap and schedules. Set clear objectives and deadlines for each stage of the migration.
- Support for the Team: Provide the technical lead and the team with the necessary resources and time to complete the migration. Address any organizational or logistical obstacles that might slow down progress.
- Progress Monitoring: Review and monitor progress reports submitted by the technical lead. Ensure the team meets the deadlines for audits, migrations, and report submissions.
- Coordination: Collaborate with other product managers to ensure a smooth and coordinated transition across all teams. Facilitate knowledge sharing between teams to optimize the migration process.
- Communication: Attend monthly meetings with the technical lead to discuss progress, challenges, and any resource needs. Provide regular updates to stakeholders about the state of the migration.
Responsibilities For Developers
- Task 1: Identify which Eventlet version is currently in use in your deliverables.You can simply inspect your requirements. You can also use beagle on all your deliverables, see the related sections.
- Task 2: If the version is lower than 0.36.1, prepare the Eventlet requirement upgrade.
- Task 3: Audit your code to identify all dependencies related to Eventlet within the next three weeks.
- Task 4: Prepare a progress report that includes:
- A list of impacted deliverables;
- Eventlet patterns used within these deliverables (based on the patterns defined above).
- Task 5: Join us at the PTG sessions and then lets discuss together about your use cases.
- Task 6: Start migrating identified Eventlet components to available alternatives after the audit is complete. The target is to have this migration started within the current quarter.
Responsibilities For Product Managers
- Task 1: Prioritize this migration in your team's roadmap. From easiest to most complex deliverables to migrate.
- Task 2: Within the next two weeks, identify a technical lead (preferably a senior developer or principal senior developer) who will oversee the migration.
- Task 3: Ensure that your teams have the necessary resources and time to complete the migration.
- Task 4: Attend the coming PTG sessions and monthly follow-up meetings with the technical lead to discuss progress, blockers, and next steps.
Tracking Progress
Proposed Key Performance Indicators (KPI)
These KPIs aim to provide managers (product managers) with a way to track and measure progress, both from a team-based perspective and from a global overview.
1. Eventlet Deactivation Rate in Deliverables:
- Objective: Track the progress of the number of deliverables where Eventlet has been completely disabled and replaced.
- KPI: Percentage of deliverables where Eventlet is replaced by alternative solutions (`asyncio`, `awaitlet`, `concurrent.futures`, etc.).
- Calculation: (Number of migrated deliverables / Total number of identified deliverables) x 100.
2. Reduction in the Number of `monkey_patch()` Occurrences:
- Objective: Assess the gradual removal of calls to `eventlet.monkey_patch()`, which can cause unwanted behaviors.
- KPI: Number of `monkey_patch()` occurrences still present in the code.
- Calculation: Total number of `monkey_patch()` occurrences identified before and after each migration phase.
3. Response Time and Performance Post-Migration:
- Objective: Verify whether the performance of the deliverables improves or remains stable after migrating to `asyncio` or other solutions.
- KPI: Average response time of services post-migration (in ms).
- Calculation: Measure the response time before and after migration to check if performance improves.
4. Percentage of Automated Tests Passed After Migration:
- Objective: Ensure the stability and quality of the migrated code by verifying that unit and functional tests pass successfully.
- KPI: Percentage of automated tests passed after migration.
- Calculation: (Number of tests passed post-migration / Total number of tests executed) x 100.
5. Number of Bugs or Incidents Post-Migration:
- Objective: Track the stability of the project post-migration by monitoring the number of bugs or incidents related to the migration.
- KPI: Number of bugs or incidents identified related to the Eventlet migration.
- Calculation: Total number of bugs/incidents opened during and after migration.
6. Adoption of New Python Versions:
- Objective: Verify if the teams are able to adopt new Python versions in the migrated deliverables.
- KPI: Percentage of deliverables using a recent version of Python (e.g., Python 3.12).
- Calculation: (Number of deliverables using the latest Python version / Total number of deliverables) x 100.
7. Meeting Project Migration Deadlines:
- Objective: Ensure that the migration project adheres to the initial schedule.
- KPI: Number of deadlines met compared to the migration plan.
- Calculation: (Number of deliverables migrated within the deadline / Total number of planned deliverables) x 100.
Useful Links
- Eventlet's official migration guide
- The gerrit patches related to the migration
- The Awaitlet documentation
- The related community goal (governance/TC)
- The origin of this whole story
- Getting the Eventlet maintenance under our umbrella
FAQ
Is this initiative is an official initiative?
Yes, this initiative is supported by the OpenStack TC. This initiative is an official OpenStack community goal. This goal has been accepted months ago and is now going to be a selected goal.
What will happen to eventlet once the openstack migration is complete?
Eventlet will be simply abandoned officially. No more maintenance will be given to the official Eventlet repository. The official Eventlet repository will be archived.
Why not simply maintaining Eventlet?
We have many reasons for that:
- The main reason is that, since years, to keep running Eventlet started to fork deprecated and removed versions of old CPython stdlib modules. With coming versions of Python this kind of workaround will surely have to repeat. This trend seems already coming with Python 3.13 and the threading module (see the discussion: https://github.com/eventlet/eventlet/pull/966#issuecomment-2344252826). We do not want to transform Eventlet into a poorly maintained fork of CPython. A poor full of security breaches. Moving away of that trend would almost require a complete rewrite of Eventlet.
- The second reason is more about resources. Eventlet is maintained by 1 or 2 part time core maintainers, that's not enough to keep its head above water, especially if we take account of the previous reason. We do not want to repeat the log4shell story.
- The third reason is that when the migration will be done, even though the migration was difficult given our deepest Eventlet usages, then we will be safe for a decades. We want to encourage a sustainable solution.
Teams efforts
Here is a list of documents created by teams with the goal to documents their migration. If your team own documents and if you do not see them in the list below please feel free to add it. It could help other team to manage their own removal.
The list:
Map of the Impacted Deliverables
Here is a curated list of the Openstack deliverables currently (as of 2024 Oct. 4th) using Eventlet and which must be migrated:
- https://opendev.org/openstack/aodh/
- https://opendev.org/openstack/auto-scaling-sig/
- https://opendev.org/openstack/barbican/
- https://opendev.org/openstack/blazar/
- https://opendev.org/openstack/ceilometer/
- https://opendev.org/openstack/charm-manila/
- https://opendev.org/openstack/charm-manila-ganesha/
- https://opendev.org/openstack/cinder/
- https://opendev.org/openstack/cloudkitty/
- https://opendev.org/openstack/cyborg/
- https://opendev.org/openstack/designate/
- https://opendev.org/openstack/devstack/
- https://opendev.org/openstack/election/
- https://opendev.org/openstack/etcd3gw/
- https://opendev.org/openstack/futurist/
- https://opendev.org/openstack/glance/
- https://opendev.org/openstack/glance_store/
- https://opendev.org/openstack/governance/
- https://opendev.org/openstack/hacking/
- https://opendev.org/openstack/heat/
- https://opendev.org/openstack/heat-templates/
- https://opendev.org/openstack/ironic/
- https://opendev.org/openstack/ironic-python-agent/
- https://opendev.org/openstack/keystone/
- https://opendev.org/openstack/keystonemiddleware/
- https://opendev.org/openstack/kolla/
- https://opendev.org/openstack/kolla-ansible/
- https://opendev.org/openstack/magnum/
- https://opendev.org/openstack/manila/
- https://opendev.org/openstack/masakari/
- https://opendev.org/openstack/masakari-monitors/
- https://opendev.org/openstack/mistral/
- https://opendev.org/openstack/mistral-extra/
- https://opendev.org/openstack/mistral-lib/
- https://opendev.org/openstack/monasca-agent/
- https://opendev.org/openstack/monasca-api/
- https://opendev.org/openstack/monasca-events-api/
- https://opendev.org/openstack/networking-baremetal/
- https://opendev.org/openstack/networking-generic-switch/
- https://opendev.org/openstack/networking-sfc/
- https://opendev.org/openstack/neutron/
- https://opendev.org/openstack/neutron-dynamic-routing/
- https://opendev.org/openstack/neutron-fwaas/
- https://opendev.org/openstack/neutron-lib/
- https://opendev.org/openstack/neutron-tempest-plugin/
- https://opendev.org/openstack/neutron-vpnaas/
- https://opendev.org/openstack/nova/
- https://opendev.org/openstack/octavia/
- https://opendev.org/openstack/octavia-lib/
- https://opendev.org/openstack/octavia-tempest-plugin/
- https://opendev.org/openstack/openstack-ansible-ops/
- https://opendev.org/openstack/openstack-ansible-os_neutron/
- https://opendev.org/openstack/openstack-helm/
- https://opendev.org/openstack/openstack-manuals/
- https://opendev.org/openstack/os-brick/
- https://opendev.org/openstack/os-ken/
- https://opendev.org/openstack/os-vif/
- https://opendev.org/openstack/oslo.cache/
- https://opendev.org/openstack/oslo.concurrency/
- https://opendev.org/openstack/oslo.config/
- https://opendev.org/openstack/oslo.db/
- https://opendev.org/openstack/oslo.log/
- https://opendev.org/openstack/oslo.messaging/
- https://opendev.org/openstack/oslo.privsep/
- https://opendev.org/openstack/oslo.reports/
- https://opendev.org/openstack/oslo.rootwrap/
- https://opendev.org/openstack/oslo.service/
- https://opendev.org/openstack/oslo.utils/
- https://opendev.org/openstack/oslo.versionedobjects/
- https://opendev.org/openstack/oslo.vmware/
- https://opendev.org/openstack/osops/
- https://opendev.org/openstack/ossa/
- https://opendev.org/openstack/ovn-bgp-agent/
- https://opendev.org/openstack/ovsdbapp/
- https://opendev.org/openstack/performance-docs/
- https://opendev.org/openstack/project-config/
- https://opendev.org/openstack/puppet-barbican/
- https://opendev.org/openstack/puppet-ceilometer/
- https://opendev.org/openstack/puppet-keystone/
- https://opendev.org/openstack/puppet-manila/
- https://opendev.org/openstack/puppet-neutron/
- https://opendev.org/openstack/puppet-openstacklib/
- https://opendev.org/openstack/python-cinderclient/
- https://opendev.org/openstack/python-glanceclient/
- https://opendev.org/openstack/python-ironicclient/
- https://opendev.org/openstack/python-keystoneclient/
- https://opendev.org/openstack/python-manilaclient/
- https://opendev.org/openstack/python-mistralclient/
- https://opendev.org/openstack/python-octaviaclient/
- https://opendev.org/openstack/python-swiftclient/
- https://opendev.org/openstack/python-troveclient/
- https://opendev.org/openstack/python-zaqarclient/
- https://opendev.org/openstack/rally/
- https://opendev.org/openstack/releases/
- https://opendev.org/openstack/requirements/
- https://opendev.org/openstack/rpm-packaging/
- https://opendev.org/openstack/security-doc/
- https://opendev.org/openstack/storlets/
- https://opendev.org/openstack/swift/
- https://opendev.org/openstack/swift-bench/
- https://opendev.org/openstack/tacker/
- https://opendev.org/openstack/taskflow/
- https://opendev.org/openstack/tooz/
- https://opendev.org/openstack/trove/
- https://opendev.org/openstack/upstream-institute-virtual-environment/
- https://opendev.org/openstack/venus/
- https://opendev.org/openstack/vitrage/
- https://opendev.org/openstack/watcher/
- https://opendev.org/openstack/zun/
Existing spec repos where Eventlet appear
- https://opendev.org/openstack/cinder-specs/
- https://opendev.org/openstack/cloudkitty-specs/
- https://opendev.org/openstack/designate-specs/
- https://opendev.org/openstack/glance-specs/
- https://opendev.org/openstack/heat-specs/
- https://opendev.org/openstack/ironic-inspector/
- https://opendev.org/openstack/ironic-specs/
- https://opendev.org/openstack/keystone-specs/
- https://opendev.org/openstack/neutron-specs/
- https://opendev.org/openstack/nova-specs/
- https://opendev.org/openstack/oslo-specs/
- https://opendev.org/openstack/python-ironic-inspector-client/
- https://opendev.org/openstack/telemetry-specs/