hysn-firecracker-python 1.0.3.post0__tar.gz → 1.0.4.post0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/.github/workflows/pypi-release.yml +1 -0
  2. {hysn_firecracker_python-1.0.3.post0/hysn_firecracker_python.egg-info → hysn_firecracker_python-1.0.4.post0}/PKG-INFO +5 -1
  3. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/docs/README.md +2 -1
  4. hysn_firecracker_python-1.0.4.post0/docs/cleanup.md +569 -0
  5. hysn_firecracker_python-1.0.4.post0/examples/create_vm_with_filesystem_format.py +95 -0
  6. hysn_firecracker_python-1.0.4.post0/firecracker/_version.py +24 -0
  7. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/firecracker/config.py +3 -2
  8. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/firecracker/microvm.py +77 -21
  9. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/firecracker/network.py +95 -4
  10. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/firecracker/vmm.py +51 -3
  11. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0/hysn_firecracker_python.egg-info}/PKG-INFO +5 -1
  12. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/hysn_firecracker_python.egg-info/SOURCES.txt +4 -0
  13. hysn_firecracker_python-1.0.4.post0/hysn_firecracker_python.egg-info/requires.txt +8 -0
  14. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/pyproject.toml +5 -2
  15. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/tests/README.md +25 -0
  16. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/tests/conftest.py +22 -6
  17. hysn_firecracker_python-1.0.4.post0/tests/test_cleanup.py +350 -0
  18. hysn_firecracker_python-1.0.4.post0/tests/test_rootfs_format.py +124 -0
  19. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/uv.lock +466 -4
  20. hysn_firecracker_python-1.0.3.post0/firecracker/_version.py +0 -34
  21. hysn_firecracker_python-1.0.3.post0/hysn_firecracker_python.egg-info/requires.txt +0 -4
  22. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  23. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  24. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/.gitignore +0 -0
  25. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/AGENTS.md +0 -0
  26. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/Dockerfile.test +0 -0
  27. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/FIRECRACKER_SETUP.md +0 -0
  28. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/LICENSE +0 -0
  29. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/Makefile +0 -0
  30. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/QUICKSTART.md +0 -0
  31. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/README.md +0 -0
  32. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/TODO.md +0 -0
  33. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/assets/img/firecracker.png +0 -0
  34. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/assets/rootfs/setup-firecracker-official.sh +0 -0
  35. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/cleanup_firecracker.py +0 -0
  36. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/debian/compat +0 -0
  37. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/debian/control +0 -0
  38. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/debian/copyright +0 -0
  39. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/debian/rules +0 -0
  40. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/docker-compose.test.yml +0 -0
  41. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/docs/api-reference.md +0 -0
  42. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/docs/configuration.md +0 -0
  43. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/docs/examples.md +0 -0
  44. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/docs/getting-started.md +0 -0
  45. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/docs/index.md +0 -0
  46. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/docs/network.md +0 -0
  47. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/docs/testing-in-docker.md +0 -0
  48. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/examples/Dockerfile +0 -0
  49. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/examples/configure_vm_network.py +0 -0
  50. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/examples/create_vm.py +0 -0
  51. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/examples/id_rsa +0 -0
  52. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/examples/id_rsa.pub +0 -0
  53. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/examples/init +0 -0
  54. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/examples/load_snapshot.py +0 -0
  55. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/examples/sample.py +0 -0
  56. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/examples/setup.sh +0 -0
  57. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/firecracker/__init__.py +0 -0
  58. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/firecracker/api.py +0 -0
  59. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/firecracker/exceptions.py +0 -0
  60. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/firecracker/logger.py +0 -0
  61. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/firecracker/process.py +0 -0
  62. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/firecracker/scripts.py +0 -0
  63. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/firecracker/utils.py +0 -0
  64. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/hysn_firecracker_python.egg-info/dependency_links.txt +0 -0
  65. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/hysn_firecracker_python.egg-info/entry_points.txt +0 -0
  66. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/hysn_firecracker_python.egg-info/top_level.txt +0 -0
  67. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/requirements.txt +0 -0
  68. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/scripts/cleanup_resources.py +0 -0
  69. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/scripts/run-tests-docker.sh +0 -0
  70. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/setup.cfg +0 -0
  71. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/setup.py +0 -0
  72. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/tests/test_api_client.py +0 -0
  73. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/tests/test_docker_integration.py +0 -0
  74. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/tests/test_error_handling.py +0 -0
  75. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/tests/test_logger.py +0 -0
  76. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/tests/test_microvm.py +0 -0
  77. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/tests/test_microvm_error_paths.py +0 -0
  78. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/tests/test_microvm_initialization.py +0 -0
  79. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/tests/test_network_error_paths.py +0 -0
  80. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/tests/test_networking.py +0 -0
  81. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/tests/test_port_forward.py +0 -0
  82. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/tests/test_process_manager.py +0 -0
  83. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/tests/test_scripts.py +0 -0
  84. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/tests/test_snapshots.py +0 -0
  85. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/tests/test_utils.py +0 -0
  86. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/tests/test_vm_configuration.py +0 -0
  87. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/tests/test_vmm_manager.py +0 -0
  88. {hysn_firecracker_python-1.0.3.post0 → hysn_firecracker_python-1.0.4.post0}/verify-setup.py +0 -0
@@ -17,6 +17,7 @@ jobs:
17
17
  uses: actions/checkout@v4
18
18
  with:
19
19
  fetch-depth: 0
20
+ fetch-tags: true
20
21
 
21
22
  - name: 'Set up Python 3.10'
22
23
  uses: actions/setup-python@v5
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hysn-firecracker-python
3
- Version: 1.0.3.post0
3
+ Version: 1.0.4.post0
4
4
  Summary: A Python client library to interact with Firecracker microVMs
5
5
  Author: Muhammad Yuga Nugraha
6
6
  License: MIT License
@@ -35,6 +35,10 @@ Requires-Python: >=3.8
35
35
  Description-Content-Type: text/markdown
36
36
  License-File: LICENSE
37
37
  Requires-Dist: docker==7.1.0
38
+ Requires-Dist: requests==2.32.3
39
+ Requires-Dist: requests-unixsocket==0.4.1
40
+ Requires-Dist: tenacity==9.0.0
41
+ Requires-Dist: psutil==7.0.0
38
42
  Requires-Dist: pyroute2==0.8.1
39
43
  Requires-Dist: paramiko==3.5.1
40
44
  Requires-Dist: faker==37.9.0
@@ -8,6 +8,7 @@ Welcome to the Firecracker Python SDK documentation! This documentation will hel
8
8
  - [API Reference](api-reference.md) - Detailed information about the SDK's API
9
9
  - [Configuration](configuration.md) - Configuration options for microVMs
10
10
  - [Network](network.md) - Networking capabilities and examples
11
+ - [Cleanup](cleanup.md) - Resource cleanup and orphaned resource management
11
12
  - [Examples](examples.md) - Practical examples for using the SDK
12
13
 
13
14
  ## What is Firecracker?
@@ -70,4 +71,4 @@ python3 -m venv venv
70
71
  source venv/bin/activate
71
72
  pip install -r requirements.txt
72
73
  pip install -e .
73
- ```
74
+ ```
@@ -0,0 +1,569 @@
1
+ # Firecracker Python Resource Cleanup Guide
2
+
3
+ This document describes the cleanup system for Firecracker microVM resources, including improvements for handling orphaned resources and resilient cleanup behavior.
4
+
5
+ ## Overview
6
+
7
+ The Firecracker Python SDK provides automatic resource cleanup when deleting microVMs. The cleanup system is designed to:
8
+
9
+ 1. **Clean all resources** associated with a VM when it's deleted
10
+ 2. **Detect and clean orphaned resources** from failed VMs
11
+ 3. **Continue cleanup** even if individual steps fail (resilient cleanup)
12
+
13
+ ## Resource Types Cleaned
14
+
15
+ When a microVM is deleted, the following resources are automatically cleaned:
16
+
17
+ ### Network Resources
18
+
19
+ - **TAP devices**: Virtual network interfaces (e.g., `tap_vm123`)
20
+ - **NAT rules**: Network address translation rules for internet access
21
+ - **Port forwarding rules**: Rules for forwarding host ports to VM ports
22
+ - **Masquerade rules**: Network masquerade for outbound traffic
23
+
24
+ ### Process Resources
25
+
26
+ - **Firecracker processes**: The VMM processes running the microVMs
27
+
28
+ ### File System Resources
29
+
30
+ - **VM directories**: Configuration and runtime files in `/var/lib/firecracker/{vm_id}/`
31
+
32
+ ## Orphaned Resource Detection
33
+
34
+ ### What are Orphaned Resources?
35
+
36
+ Orphaned resources are network devices and rules that remain after a VM fails during creation or is improperly deleted. These resources are not tracked because:
37
+
38
+ - Failed VMs never created a `config.json` file
39
+ - `list_vmm()` can only find VMs with `config.json`
40
+ - Resources were allocated before failure occurred
41
+
42
+ ### How Orphaned Detection Works
43
+
44
+ The SDK detects orphaned resources by:
45
+
46
+ 1. **Listing all TAP devices** on the system (those starting with `tap_`)
47
+ 2. **Extracting VM IDs** from TAP device names (e.g., `tap_vm123` → `vm123`)
48
+ 3. **Comparing with running VMs** from `list_vmm()`
49
+ 4. **Identifying orphans**: TAP devices whose IDs are not in the running VMs list
50
+
51
+ ### Cleaning Orphaned Resources
52
+
53
+ Use the `delete(all=True)` method to clean all VMs and orphaned resources:
54
+
55
+ ```python
56
+ from firecracker import MicroVM
57
+
58
+ # Delete all VMs and clean up any orphaned resources
59
+ vm = MicroVM()
60
+ result = vm.delete(all=True)
61
+ print(result) # "All VMMs and orphaned resources are deleted"
62
+ ```
63
+
64
+ Or manually clean orphaned resources:
65
+
66
+ ```python
67
+ from firecracker import MicroVM
68
+
69
+ vm = MicroVM(verbose=True)
70
+ vm._vmm.cleanup_orphaned_resources()
71
+ ```
72
+
73
+ ## Resilient Cleanup
74
+
75
+ ### How It Works
76
+
77
+ The cleanup system uses a resilient approach where each cleanup step runs independently:
78
+
79
+ ```python
80
+ # NetworkManager.cleanup() example
81
+ cleanup_errors = []
82
+
83
+ # Step 1: Delete NAT rules (best effort)
84
+ try:
85
+ self.delete_nat_rules(tap_device)
86
+ except Exception as e:
87
+ cleanup_errors.append(f"Failed to delete NAT rules: {str(e)}")
88
+ # Log but don't raise - continue to next step
89
+
90
+ # Step 2: Delete masquerade (best effort)
91
+ try:
92
+ self.delete_masquerade()
93
+ except Exception as e:
94
+ cleanup_errors.append(f"Failed to delete masquerade: {str(e)}")
95
+ # Log but don't raise - continue to next step
96
+
97
+ # Step 3: Delete port forwarding (best effort)
98
+ try:
99
+ self.delete_all_port_forward(machine_id)
100
+ except Exception as e:
101
+ cleanup_errors.append(f"Failed to delete port forwarding: {str(e)}")
102
+ # Log but don't raise - continue to next step
103
+
104
+ # Step 4: Delete TAP device (always try this)
105
+ try:
106
+ self.delete_tap(tap_device)
107
+ except Exception as e:
108
+ cleanup_errors.append(f"Failed to delete TAP device: {str(e)}")
109
+ # Log but don't raise
110
+
111
+ # Report any issues
112
+ if cleanup_errors:
113
+ self._logger.error(f"Partial cleanup: {'; '.join(cleanup_errors)}")
114
+ ```
115
+
116
+ ### Benefits of Resilient Cleanup
117
+
118
+ 1. **No dangling resources**: Even if NAT rule deletion fails, TAP device cleanup is attempted
119
+ 2. **Partial success better than total failure**: Some resources cleaned is better than none
120
+ 3. **Complete error logging**: All failures are logged for debugging
121
+ 4. **No cascade failures**: One failure doesn't prevent cleanup of other resources
122
+
123
+ ## API Reference
124
+
125
+ ### MicroVM.delete()
126
+
127
+ Deletes a specific microVM or all microVMs.
128
+
129
+ ```python
130
+ delete(id=None, all=False) -> str
131
+ ```
132
+
133
+ #### Parameters
134
+
135
+ - `id` (str, optional): ID of microVM to delete. If not provided, uses the current microVM's ID.
136
+ - `all` (bool, optional): If `True`, deletes all microVMs and orphaned resources. Defaults to `False`.
137
+
138
+ #### Returns
139
+
140
+ - `str`: Status message indicating the result of the delete operation.
141
+
142
+ #### Examples
143
+
144
+ ```python
145
+ from firecracker import MicroVM
146
+
147
+ # Delete a specific microVM
148
+ vm = MicroVM()
149
+ vm.create()
150
+ vm.delete()
151
+
152
+ # Delete all microVMs and orphaned resources
153
+ vm = MicroVM()
154
+ vm.delete(all=True)
155
+ ```
156
+
157
+ ### VMMManager.cleanup_orphaned_resources()
158
+
159
+ Cleans up resources from VMs that failed during creation.
160
+
161
+ ```python
162
+ def cleanup_orphaned_resources(self) -> None
163
+ ```
164
+
165
+ #### Description
166
+
167
+ This method:
168
+
169
+ 1. Lists all running VMs
170
+ 2. Finds TAP devices that don't belong to running VMs
171
+ 3. Cleans orphaned TAP devices and associated network rules
172
+
173
+ #### Example
174
+
175
+ ```python
176
+ from firecracker import MicroVM
177
+
178
+ vm = MicroVM(verbose=True)
179
+ vm._vmm.cleanup_orphaned_resources()
180
+ ```
181
+
182
+ ### NetworkManager.cleanup_orphaned_tap_devices()
183
+
184
+ Removes TAP devices that don't belong to running VMs.
185
+
186
+ ```python
187
+ def cleanup_orphaned_tap_devices(self, running_vm_ids: set) -> None
188
+ ```
189
+
190
+ #### Parameters
191
+
192
+ - `running_vm_ids` (set): Set of VM IDs that are currently running.
193
+
194
+ #### Example
195
+
196
+ ```python
197
+ from firecracker import MicroVM
198
+ from firecracker.network import NetworkManager
199
+
200
+ network_manager = NetworkManager()
201
+ network_manager.cleanup_orphaned_tap_devices(running_vm_ids={"vm1", "vm2"})
202
+ ```
203
+
204
+ ## Usage Examples
205
+
206
+ ### Normal VM Lifecycle
207
+
208
+ ```python
209
+ from firecracker import MicroVM
210
+
211
+ # Create a microVM
212
+ vm = MicroVM(name="web-server")
213
+ vm.create()
214
+
215
+ # VM is running with:
216
+ # - TAP device: tap_web-server
217
+ # - NAT rules for internet access
218
+ # - Firecracker process
219
+ # - VM directory: /var/lib/firecracker/web-server/
220
+
221
+ # Delete the VM (all resources cleaned automatically)
222
+ vm.delete()
223
+ ```
224
+
225
+ ### Handling Failed VMs
226
+
227
+ ```python
228
+ from firecracker import MicroVM
229
+
230
+ try:
231
+ # VM creation fails (e.g., due to resource constraints)
232
+ vm = MicroVM(name="failed-vm")
233
+ vm.create()
234
+ except Exception as e:
235
+ print(f"VM creation failed: {e}")
236
+
237
+ # VM didn't create config.json, so it's not in list_vmm()
238
+ # But TAP device tap_failed-vm still exists
239
+
240
+ # Clean up all VMs and orphaned resources
241
+ vm = MicroVM()
242
+ vm.delete(all=True)
243
+ # tap_failed-vm and its rules are now cleaned
244
+ ```
245
+
246
+ ### Managing Multiple VMs
247
+
248
+ ```python
249
+ from firecracker import MicroVM
250
+
251
+ # Create multiple VMs
252
+ vm1 = MicroVM(name="app1")
253
+ vm1.create()
254
+
255
+ vm2 = MicroVM(name="app2")
256
+ vm2.create()
257
+
258
+ vm3 = MicroVM(name="app3")
259
+ # This one fails during creation
260
+ try:
261
+ vm3.create()
262
+ except Exception:
263
+ pass
264
+
265
+ # List running VMs (only shows vm1 and vm2)
266
+ vms = MicroVM.list()
267
+ print(f"Running VMs: {len(vms)}") # 2
268
+
269
+ # Delete all VMs and clean orphaned resources
270
+ vm = MicroVM()
271
+ result = vm.delete(all=True)
272
+ # All resources from vm1, vm2, and the orphaned tap_app3 are cleaned
273
+ ```
274
+
275
+ ## Troubleshooting
276
+
277
+ ### Issue: TAP Devices Still Showing After Delete
278
+
279
+ **Cause:** Network rule deletion may have failed, but TAP device cleanup wasn't attempted (in older versions).
280
+
281
+ **Solution:** Run cleanup with verbose logging to see what's happening:
282
+
283
+ ```python
284
+ vm = MicroVM(verbose=True, level="DEBUG")
285
+ vm.delete(all=True)
286
+ ```
287
+
288
+ Check logs for:
289
+
290
+ - Which TAP devices were found
291
+ - Which cleanup steps succeeded/failed
292
+ - Any error messages
293
+
294
+ ### Issue: Permission Errors During Cleanup
295
+
296
+ **Cause:** Insufficient permissions to modify network resources or device files.
297
+
298
+ **Solution:** Ensure proper permissions:
299
+
300
+ ```bash
301
+ # Check user has access to KVM
302
+ ls -l /dev/kvm
303
+
304
+ # Add user to kvm group if needed
305
+ sudo usermod -aG kvm $USER
306
+ # Then log out and log back in
307
+
308
+ # For network operations, may need sudo
309
+ ```
310
+
311
+ ### Issue: Cleanup Partially Succeeds
312
+
313
+ **Expected behavior:** With resilient cleanup, partial success is normal and better than total failure.
314
+
315
+ **Solution:** Check logs to see which resources weren't cleaned and manually clean them:
316
+
317
+ ```bash
318
+ # Check for remaining TAP devices
319
+ ip link show | grep tap_
320
+
321
+ # Check for remaining NAT rules
322
+ sudo nft list ruleset
323
+
324
+ # Manually clean remaining resources
325
+ sudo ip link delete tap_<name>
326
+ sudo nft flush chain ip nat POSTROUTING
327
+ ```
328
+
329
+ ## Best Practices
330
+
331
+ ### 1. Use `delete(all=True)` for Complete Cleanup
332
+
333
+ When you want to ensure all resources are cleaned:
334
+
335
+ ```python
336
+ from firecracker import MicroVM
337
+
338
+ vm = MicroVM()
339
+ vm.delete(all=True) # Cleans VMs and orphaned resources
340
+ ```
341
+
342
+ ### 2. Enable Verbose Logging for Debugging
343
+
344
+ When troubleshooting cleanup issues:
345
+
346
+ ```python
347
+ from firecracker import MicroVM
348
+
349
+ vm = MicroVM(verbose=True, level="DEBUG")
350
+ vm.delete(all=True)
351
+ ```
352
+
353
+ ### 3. Clean Resources Regularly
354
+
355
+ For long-running systems, periodically clean orphaned resources:
356
+
357
+ ```python
358
+ from firecracker import MicroVM
359
+
360
+ vm = MicroVM()
361
+ vm._vmm.cleanup_orphaned_resources()
362
+ ```
363
+
364
+ ### 4. Handle Exceptions Gracefully
365
+
366
+ When working with multiple VMs, handle failures:
367
+
368
+ ```python
369
+ from firecracker import MicroVM
370
+ from firecracker.exceptions import VMMError, NetworkError
371
+
372
+ vms_to_delete = ["vm1", "vm2", "vm3"]
373
+
374
+ for vm_id in vms_to_delete:
375
+ try:
376
+ vm = MicroVM(id=vm_id)
377
+ vm.delete()
378
+ print(f"Successfully deleted {vm_id}")
379
+ except (VMMError, NetworkError) as e:
380
+ print(f"Error deleting {vm_id}: {e}")
381
+ # Continue to next VM
382
+ except Exception as e:
383
+ print(f"Unexpected error deleting {vm_id}: {e}")
384
+ # Continue to next VM
385
+
386
+ # Clean any orphaned resources
387
+ vm = MicroVM()
388
+ try:
389
+ vm.delete(all=True)
390
+ except Exception as e:
391
+ print(f"Error cleaning orphaned resources: {e}")
392
+ ```
393
+
394
+ ## What Does NOT Get Cleaned
395
+
396
+ The following resources are intentionally NOT cleaned by the automatic cleanup system:
397
+
398
+ ### Snapshots
399
+
400
+ Snapshot files in `/var/lib/firecracker/snapshots/` are preserved:
401
+
402
+ - Snapshots contain VM state and memory dumps
403
+ - They may be needed for recovery or analysis
404
+ - Manual cleanup is required if you want to delete them
405
+
406
+ ```bash
407
+ # Manually clean snapshots
408
+ sudo rm -rf /var/lib/firecracker/snapshots/*
409
+ ```
410
+
411
+ ### VM Creation Failures
412
+
413
+ Resources from VM creation failures are NOT automatically cleaned:
414
+
415
+ - VM creation process does not trigger cleanup on failure
416
+ - This is intentional to avoid cleaning resources that might be in use
417
+ - Use `delete(all=True)` to clean orphaned resources after failures
418
+
419
+ ## Design Decisions
420
+
421
+ ### 1. Best-Effort Cleanup
422
+
423
+ Each resource type is cleaned independently:
424
+
425
+ - Failures in one area don't prevent cleanup of others
426
+ - Partial success is better than total failure
427
+ - All failures are logged for debugging
428
+
429
+ ### 2. No Automatic Creation Cleanup
430
+
431
+ VM creation failures don't automatically trigger cleanup:
432
+
433
+ - Resources might be in use by other processes
434
+ - User should explicitly request cleanup
435
+ - Prevents accidental deletion of resources in use
436
+
437
+ ### 3. Orphan Detection Based on Running VMs
438
+
439
+ TAP devices are considered orphaned if:
440
+
441
+ - They don't belong to a VM listed by `list_vmm()`
442
+ - This ensures we don't delete resources from VMs that are actually running
443
+
444
+ ### 4. Preserve Snapshots
445
+
446
+ Snapshots are never cleaned automatically:
447
+
448
+ - They contain valuable state information
449
+ - Users should explicitly delete them when no longer needed
450
+ - Prevents accidental data loss
451
+
452
+ ### 5. Global Masquerade Rule
453
+
454
+ The masquerade rule is a shared resource for all VMs:
455
+
456
+ - It's not deleted when a single VM is deleted
457
+ - It's only deleted when no VMs are using it
458
+ - This prevents breaking networking for other VMs
459
+
460
+ ## Testing
461
+
462
+ The cleanup functionality is covered by comprehensive tests in `tests/test_cleanup.py`:
463
+
464
+ - Resilient cleanup tests (partial failures)
465
+ - Orphaned resource detection tests
466
+ - Delete behavior tests
467
+ - Integration scenarios
468
+
469
+ Run cleanup tests:
470
+
471
+ ```bash
472
+ # Run all cleanup tests
473
+ pytest tests/test_cleanup.py -v
474
+
475
+ # Run specific test class
476
+ pytest tests/test_cleanup.py::TestResilientCleanup -v
477
+ pytest tests/test_cleanup.py::TestOrphanedResourceCleanup -v
478
+ pytest tests/test_cleanup.py::TestDeleteWithOrphans -v
479
+ ```
480
+
481
+ ## Advanced Topics
482
+
483
+ ### Manual Resource Cleanup
484
+
485
+ For advanced scenarios, you can manually clean specific resources:
486
+
487
+ ```python
488
+ from firecracker import MicroVM
489
+ from firecracker.network import NetworkManager
490
+
491
+ vm = MicroVM()
492
+ network_manager = vm._network
493
+
494
+ # Clean a specific TAP device
495
+ network_manager.delete_tap("tap_vm123")
496
+
497
+ # Clean NAT rules for a specific TAP device
498
+ network_manager.delete_nat_rules("tap_vm123")
499
+
500
+ # Clean port forwarding for a specific VM
501
+ network_manager.delete_all_port_forward("vm123")
502
+ ```
503
+
504
+ ### Checking Resource State
505
+
506
+ Query the state of resources before cleanup:
507
+
508
+ ```python
509
+ from firecracker import MicroVM
510
+
511
+ vm = MicroVM()
512
+
513
+ # List running VMs
514
+ vms = MicroVM.list()
515
+ print(f"Running VMs: {vms}")
516
+
517
+ # List network interfaces
518
+ import os
519
+ tap_devices = [f for f in os.listdir('/sys/class/net') if f.startswith('tap_')]
520
+ print(f"TAP devices: {tap_devices}")
521
+ ```
522
+
523
+ ### Cleanup with Retry Logic
524
+
525
+ For transient failures, implement retry logic:
526
+
527
+ ```python
528
+ from firecracker import MicroVM
529
+ from firecracker.exceptions import NetworkError
530
+ from tenacity import retry, stop_after_attempt, wait_exponential
531
+
532
+ vm = MicroVM()
533
+
534
+ @retry(
535
+ stop=stop_after_attempt(3),
536
+ wait=wait_exponential(multiplier=1, min=1, max=10),
537
+ reraise=True
538
+ )
539
+ def delete_with_retry(vm_id):
540
+ try:
541
+ vm = MicroVM(id=vm_id)
542
+ vm.delete()
543
+ return True
544
+ except NetworkError as e:
545
+ print(f"Attempt failed: {e}, retrying...")
546
+ raise
547
+
548
+ # Use retry logic for deletion
549
+ delete_with_retry("vm123")
550
+ ```
551
+
552
+ ## Related Documentation
553
+
554
+ - [Getting Started](getting-started.md) - Learn how to create and manage microVMs
555
+ - [API Reference](api-reference.md) - Complete API documentation
556
+ - [Network](network.md) - Network configuration and management
557
+ - [Examples](examples.md) - Practical examples
558
+
559
+ ## Summary
560
+
561
+ The Firecracker Python SDK provides a robust cleanup system that:
562
+
563
+ 1. **Automatically cleans** all resources when VMs are deleted
564
+ 2. **Detects and cleans** orphaned resources from failed VMs
565
+ 3. **Continues cleanup** even when individual steps fail
566
+ 4. **Logs all failures** for debugging
567
+ 5. **Preserves snapshots** to prevent accidental data loss
568
+
569
+ For any issues or questions about cleanup, refer to the troubleshooting section or enable verbose logging to see detailed cleanup operations.
@@ -0,0 +1,95 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Example: Creating a MicroVM with Different Filesystem Formats
4
+
5
+ This example demonstrates how to create microVMs with different rootfs filesystem formats.
6
+ The firecracker-python library now supports ext3, ext4, and xfs filesystem formats.
7
+ """
8
+
9
+ from firecracker import MicroVM
10
+
11
+ # Example 1: Create a VM with ext4 filesystem (default)
12
+ print("Creating VM with ext4 filesystem...")
13
+ vm_ext4 = MicroVM(
14
+ name="vm-ext4",
15
+ image="alpine:latest",
16
+ base_rootfs="./rootfs_ext4.img",
17
+ rootfs_size="5G",
18
+ rootfs_format="ext4", # Explicitly specify ext4 format
19
+ kernel_file="/var/lib/firecracker/kernel/vmlinux",
20
+ vcpu=2,
21
+ memory="2G",
22
+ verbose=True,
23
+ )
24
+
25
+ # Build the rootfs with ext4 filesystem
26
+ result = vm_ext4.build()
27
+ print(f"Result: {result}")
28
+
29
+ # Example 2: Create a VM with ext3 filesystem
30
+ print("\nCreating VM with ext3 filesystem...")
31
+ vm_ext3 = MicroVM(
32
+ name="vm-ext3",
33
+ image="alpine:latest",
34
+ base_rootfs="./rootfs_ext3.img",
35
+ rootfs_size="5G",
36
+ rootfs_format="ext3", # Use ext3 format
37
+ kernel_file="/var/lib/firecracker/kernel/vmlinux",
38
+ vcpu=2,
39
+ memory="2G",
40
+ verbose=True,
41
+ )
42
+
43
+ # Build the rootfs with ext3 filesystem
44
+ result = vm_ext3.build()
45
+ print(f"Result: {result}")
46
+
47
+ # Example 3: Create a VM with xfs filesystem
48
+ print("\nCreating VM with xfs filesystem...")
49
+ vm_xfs = MicroVM(
50
+ name="vm-xfs",
51
+ image="alpine:latest",
52
+ base_rootfs="./rootfs_xfs.img",
53
+ rootfs_size="5G",
54
+ rootfs_format="xfs", # Use xfs format
55
+ kernel_file="/var/lib/firecracker/kernel/vmlinux",
56
+ vcpu=2,
57
+ memory="2G",
58
+ verbose=True,
59
+ )
60
+
61
+ # Build the rootfs with xfs filesystem
62
+ result = vm_xfs.build()
63
+ print(f"Result: {result}")
64
+
65
+ # Example 4: Create and start a VM with a specific filesystem format
66
+ print("\nCreating and starting VM with xfs filesystem...")
67
+ vm = MicroVM(
68
+ name="running-vm-xfs",
69
+ image="ubuntu:24.04",
70
+ base_rootfs="./ubuntu_rootfs_xfs.img",
71
+ rootfs_size="10G",
72
+ rootfs_format="xfs",
73
+ kernel_file="/var/lib/firecracker/kernel/vmlinux",
74
+ ip_addr="172.16.0.10",
75
+ vcpu=2,
76
+ memory="4G",
77
+ expose_ports=True,
78
+ host_port=10222,
79
+ dest_port=22,
80
+ verbose=True,
81
+ )
82
+
83
+ # Create and start the VM
84
+ result = vm.create()
85
+ print(f"Result: {result}")
86
+
87
+ # Clean up (optional)
88
+ # vm.delete()
89
+
90
+ print("\n✓ All examples completed successfully!")
91
+ print("\nNotes:")
92
+ print("- Supported formats: ext3, ext4, xfs")
93
+ print("- Default format: ext4")
94
+ print("- The filesystem format is validated during initialization")
95
+ print("- Overlayfs also respects the specified format")