REST API for managing OpenStack VM lifecycle operations. This is a proof-of-concept that demonstrates API design, clean separation of concerns, and a pluggable provider architecture.
The project follows a layered architecture:
- Routes — Thin HTTP handlers. Parse requests, return responses. No business logic.
- Service — Core business logic. Validates state transitions, coordinates between DB and provider.
- Provider — Abstract interface for compute operations.
MockProvidersimulates OpenStack Nova behavior with realistic delays and data. A real implementation would useopenstacksdkand plug in without changing anything above it. - Database — SQLAlchemy + SQLite. Tracks VM state, metadata, snapshots.
The main design decision here. In production, you'd have an OpenStackProvider wrapping openstacksdk calls to Nova. The mock lets us build and test the full API without needing a live cluster. The service layer just calls provider.create_server() and doesn't care what's behind it.
VMs follow strict state transitions — you can't stop an already-stopped VM, can't reboot a shut-off one, etc. Invalid transitions return 409 Conflict.
Valid transitions:
ACTIVE→ stop →SHUTOFFSHUTOFF→ start →ACTIVEACTIVE→ reboot →ACTIVEACTIVE/SHUTOFF→ resize →ACTIVEACTIVE/SHUTOFF/ERROR→ delete →DELETED
- Python 3.11+
- FastAPI
- SQLAlchemy + Alembic (migrations)
- SQLite (swap to Postgres for production)
- Pydantic v2
- pytest
git clone https://github.com/Parthhh893/openstack-vm-manager.git
cd openstack-vm-manager
python -m venv venv
source venv/bin/activate # windows: venv\Scripts\activate
pip install -r requirements.txt
# run migrations
alembic upgrade head
# start the server
uvicorn app.main:app --reload --port 8000API docs at http://localhost:8000/docs
docker compose up --buildpytest tests/ -vAll endpoints are under /api/v1.
| Method | Endpoint | Description |
|---|---|---|
| GET | /health | Health check |
| POST | /api/v1/vms | Create a VM |
| GET | /api/v1/vms | List VMs (filter: ?status=ACTIVE, pagination: ?page=1&per_page=20) |
| GET | /api/v1/vms/{id} | Get VM details |
| DELETE | /api/v1/vms/{id} | Delete VM (soft delete) |
| POST | /api/v1/vms/{id}/actions/start | Start a stopped VM |
| POST | /api/v1/vms/{id}/actions/stop | Stop a running VM |
| POST | /api/v1/vms/{id}/actions/reboot | Reboot |
| POST | /api/v1/vms/{id}/actions/resize | Resize (change flavor) |
| POST | /api/v1/vms/{id}/snapshots | Create snapshot |
| GET | /api/v1/vms/{id}/snapshots | List snapshots |
# create a vm
curl -X POST http://localhost:8000/api/v1/vms \
-H "Content-Type: application/json" \
-d '{"name": "web-server-01", "flavor": "m1.small", "image": "ubuntu-22.04"}'
# list vms
curl http://localhost:8000/api/v1/vms| Flavor | vCPUs | RAM | Disk |
|---|---|---|---|
| m1.tiny | 1 | 512 MB | 5 GB |
| m1.small | 1 | 2 GB | 20 GB |
| m1.medium | 2 | 4 GB | 40 GB |
| m1.large | 4 | 8 GB | 80 GB |
| m1.xlarge | 8 | 16 GB | 160 GB |
- Soft deletes — VMs are marked DELETED rather than removed. Preserves audit history, matches how OpenStack actually handles this.
- State machine — Enforced at the service layer. Invalid transitions → 409.
- API versioning — Everything under
/api/v1/. Breaking changes go to v2. - Pagination — List endpoints support page/per_page params.
What I'd add with more time:
- Real OpenStack provider using
openstacksdk - JWT auth with role-based access control
- Async VM provisioning with background tasks
- Network management, floating IPs, security groups
- WebSocket notifications for status changes
- CI/CD with GitHub Actions
- Rate limiting
- Structured logging with request tracing
├── alembic/ # db migrations
├── app/
│ ├── main.py
│ ├── config.py
│ ├── database.py
│ ├── models/vm.py # sqlalchemy models
│ ├── schemas/vm.py # pydantic schemas
│ ├── routes/vms.py # api endpoints
│ ├── services/vm_service.py # business logic
│ └── providers/
│ ├── base.py # abstract interface
│ └── mock_provider.py
├── tests/
├── Dockerfile
├── docker-compose.yml
└── requirements.txt