Skip to content

Commit d211633

Browse files
raduweissandreeaflorescu
authored andcommitted
examples: add hello_api example; it spawns a microvm via the api
Signed-off-by: Radu Weiss <[email protected]>
1 parent 225c1e1 commit d211633

File tree

1 file changed

+140
-0
lines changed

1 file changed

+140
-0
lines changed

examples/hello_api/spawn_microvm.py

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
import subprocess
2+
import time
3+
import urllib
4+
5+
import requests
6+
import requests_unixsocket
7+
requests_unixsocket.monkeypatch()
8+
9+
10+
class Firecracker:
11+
"""
12+
Toy class to showcase using the Firecracker API.
13+
A full API client can be generated from the Firecracker open-api model.
14+
"""
15+
16+
binary_name = 'firecracker'
17+
usocket_path_prefix = '/tmp/firecracker'
18+
19+
machine_config_path = '/machine-config'
20+
network_ifaces_path = '/network-interfaces'
21+
drives_path = '/drives'
22+
vsocks_path = '/vsocks'
23+
boot_source_path = '/boot-source'
24+
actions_path = '/actions'
25+
26+
def __init__(self, socket_name):
27+
self.socket_name = socket_name
28+
self.session_name = self.binary_name + socket_name
29+
30+
def spawn(self):
31+
self.usocket_name = (
32+
self.usocket_path_prefix +
33+
self.socket_name +
34+
'.socket'
35+
)
36+
37+
usocket_url = self.get_usocket_url()
38+
39+
self.machine_config_url = usocket_url + self.machine_config_path
40+
self.network_ifaces_url = usocket_url + self.network_ifaces_path
41+
self.drives_url = usocket_url + self.drives_path
42+
self.vsocks_url = usocket_url + self.vsocks_path
43+
self.boot_source_url = usocket_url + self.boot_source_path
44+
self.actions_url = usocket_url + self.actions_path
45+
46+
screen_cmd = (
47+
'screen -dmS ' + self.session_name +
48+
' ./' + self.binary_name + ' --api-sock ' + self.usocket_name)
49+
subprocess.call(screen_cmd, shell=True)
50+
51+
def get_usocket_url(self):
52+
url_encoded_prefix = urllib.parse.quote_plus(self.usocket_path_prefix)
53+
usocket_url = (
54+
'http+unix://' +
55+
url_encoded_prefix +
56+
self.socket_name +
57+
'.socket'
58+
)
59+
return usocket_url
60+
61+
# Spawn a new Firecracker Virtual Machine Manager process.
62+
firecracker = Firecracker('0001')
63+
firecracker.spawn()
64+
65+
# Give the api time to come online since we don't handle retries here.
66+
time.sleep(0.0042)
67+
68+
# Configure the microVM CPU and memory.
69+
requests.put(firecracker.machine_config_url, json={'vcpu_count': 2})
70+
requests.put(firecracker.machine_config_url, json={'mem_size_mib': 256})
71+
72+
# Add a network interface to the microVM.
73+
# Firecracker will map this host network interface into the microVM.
74+
requests.put(
75+
firecracker.network_ifaces_url + '/1',
76+
json={
77+
'iface_id': '1',
78+
'host_dev_name': 'fc0001tap1',
79+
'state': 'Attached'
80+
}
81+
)
82+
83+
# Add another network interface to the microVM.
84+
# Firecracker will map this host network interface into the microVM.
85+
requests.put(
86+
firecracker.network_ifaces_url + '/2',
87+
json={
88+
'iface_id': '2',
89+
'host_dev_name': 'fc0001tap2',
90+
'state': 'Attached'
91+
}
92+
)
93+
94+
# Add a disk (block device) to the microVM.
95+
# This one will be flagged as the root file system.
96+
requests.put(
97+
firecracker.drives_url + '/1',
98+
json={
99+
'drive_id': '1',
100+
'path_on_host': '/tmp/firecracker0001/ami-rootfs.ext4',
101+
'state': 'Attached',
102+
'is_root_device': True
103+
}
104+
)
105+
106+
# Add another disk (block device) to the microVM.
107+
# This one is empty, usable for, e.g., guest scratch space.
108+
requests.put(
109+
firecracker.drives_url + '/2',
110+
json={
111+
'drive_id': '2',
112+
'path_on_host': '/tmp/firecracker0001/scratch.ext4',
113+
'state': 'Attached',
114+
'is_root_device': False
115+
}
116+
)
117+
118+
# Add a vsocket between the host and guest OSs (requiers both to be Linux).
119+
# Requires appropriate privileges, and both host and guest kernel support.
120+
requests.put(
121+
firecracker.vsocks_url + '/1',
122+
json={'vsock_id': '1', 'guest_cid': 10001, 'state': 'Attached'}
123+
)
124+
125+
# Specify a boot source: a kernel image.
126+
# Currently, only linux kernel images are supported.
127+
requests.put(
128+
firecracker.boot_source_url,
129+
json={
130+
'boot_source_id': '1',
131+
'source_type': 'LocalImage',
132+
'local_image': {'kernel_image_path': '/tmp/vmlinux.bin'},
133+
}
134+
)
135+
136+
# Start!
137+
requests.put(
138+
firecracker.actions_url + '/1',
139+
json={'action_id': '1', 'action_type': 'InstanceStart'}
140+
)

0 commit comments

Comments
 (0)