Skip to content

Commit b1d1a56

Browse files
api_server: restructured the Boot Source
We don't plan to add a network boot source, so we can simplify the BootSource request body: * removed the boot source id as we only support one boot source * removed the boot source type (only local image is supported) * removed the local image configuration. Now the boot source has 2 fields: kernel_image_path and boot_args. The kernel_image_path is required. Signed-off-by: Andreea Florescu <[email protected]>
1 parent fbe9fb7 commit b1d1a56

File tree

10 files changed

+39
-109
lines changed

10 files changed

+39
-109
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
### Changed
1313

14+
- The boot source is specified only with the `kernel_image_path` and
15+
the optional parameter `boot_args`. All other fields are removed.
1416
- The `path_on_host` property in the drive specification is now marked as
1517
*mandatory*.
1618
- PATCH drive only allows patching/changing the `path_on_host` property.

README.md

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -179,12 +179,8 @@ curl --unix-socket ${socket} -i \
179179
-H "accept: application/json" \
180180
-H "Content-Type: application/json" \
181181
-d "{
182-
\"boot_source_id\": \"linux_kernel\",
183-
\"source_type\": \"LocalImage\",
184-
\"local_image\":
185-
{
186-
\"kernel_image_path\": \"${kernel_path}\"
187-
}
182+
\"kernel_image_path\": \"${kernel_path}\",
183+
\"boot_args\": \"reboot=k panic=1 pci=off nomodules console=ttyS0\"
188184
}"
189185
```
190186

api_server/src/http_service.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use data_model::mmds::Mmds;
1414
use data_model::vm::{BlockDeviceConfig, MachineConfiguration};
1515
use logger::{Metric, METRICS};
1616
use request::actions::ActionBody;
17-
use request::boot_source::BootSourceBody;
17+
use request::boot_source::BootSourceConfig;
1818
use request::drive::PatchDrivePayload;
1919
use request::instance_info::InstanceInfo;
2020
use request::logger::APILoggerDescription;
@@ -154,7 +154,7 @@ fn parse_boot_source_req<'a>(
154154

155155
0 if method == Method::Put => {
156156
METRICS.put_api_requests.boot_source_count.inc();
157-
Ok(serde_json::from_slice::<BootSourceBody>(body)
157+
Ok(serde_json::from_slice::<BootSourceConfig>(body)
158158
.map_err(|e| {
159159
METRICS.put_api_requests.boot_source_fails.inc();
160160
Error::SerdeJson(e)
@@ -782,12 +782,10 @@ mod tests {
782782
fn test_parse_boot_source_req() {
783783
let path = "/foo";
784784
let path_tokens: Vec<&str> = path[1..].split_terminator('/').collect();
785-
let json = "{
786-
\"boot_source_id\": \"bar\",
787-
\"source_type\": \"LocalImage\",
788-
\"local_image\": {\"kernel_image_path\": \"/foo/bar\"},
789-
\"boot_args\": \"baz\"
790-
}";
785+
let json = r#"{
786+
"kernel_image_path": "/foo/bar",
787+
"boot_args": "baz"
788+
}"#;
791789
let body: Chunk = Chunk::from(json);
792790

793791
// GET
@@ -800,7 +798,7 @@ mod tests {
800798
// Falling back to json deserialization for constructing the "correct" request because not
801799
// all of BootSourceBody's members are accessible. Rather than making them all public just
802800
// for the purpose of unit tests, it's preferable to trust the deserialization.
803-
let res_bsb = serde_json::from_slice::<BootSourceBody>(&body);
801+
let res_bsb = serde_json::from_slice::<BootSourceConfig>(&body);
804802
match res_bsb {
805803
Ok(boot_source_body) => {
806804
match parse_boot_source_req(&path_tokens, &path, Method::Put, &body) {

api_server/src/request/boot_source.rs

Lines changed: 6 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -6,33 +6,16 @@ use hyper::{Response, StatusCode};
66
use http_service::{json_fault_message, json_response};
77
use request::{GenerateResponse, ParsedRequest, VmmAction};
88

9-
#[derive(Debug, Deserialize, PartialEq, Serialize)]
10-
pub enum BootSourceType {
11-
LocalImage,
12-
}
13-
149
#[derive(Debug, Deserialize, PartialEq, Serialize)]
1510
#[serde(deny_unknown_fields)]
16-
pub struct LocalImage {
11+
pub struct BootSourceConfig {
1712
pub kernel_image_path: String,
18-
}
19-
20-
#[derive(Debug, Deserialize, PartialEq, Serialize)]
21-
#[serde(deny_unknown_fields)]
22-
pub struct BootSourceBody {
23-
boot_source_id: String,
24-
source_type: BootSourceType,
25-
#[serde(skip_serializing_if = "Option::is_none")]
26-
pub local_image: Option<LocalImage>,
27-
// drive_boot to be added later
28-
// network_boot to be added later
2913
#[serde(skip_serializing_if = "Option::is_none")]
3014
pub boot_args: Option<String>,
3115
}
3216

3317
#[derive(Debug)]
3418
pub enum BootSourceConfigError {
35-
EmptyKernelPath,
3619
InvalidKernelPath,
3720
InvalidKernelCommandLine,
3821
UpdateNotAllowedPostBoot,
@@ -42,10 +25,6 @@ impl GenerateResponse for BootSourceConfigError {
4225
fn generate_response(&self) -> Response {
4326
use self::BootSourceConfigError::*;
4427
match *self {
45-
EmptyKernelPath => json_response(
46-
StatusCode::BadRequest,
47-
json_fault_message("No kernel path is specified."),
48-
),
4928
InvalidKernelPath => json_response(
5029
StatusCode::BadRequest,
5130
json_fault_message(
@@ -65,7 +44,7 @@ impl GenerateResponse for BootSourceConfigError {
6544
}
6645
}
6746

68-
impl BootSourceBody {
47+
impl BootSourceConfig {
6948
pub fn into_parsed_request(self) -> result::Result<ParsedRequest, String> {
7049
let (sender, receiver) = oneshot::channel();
7150
Ok(ParsedRequest::Sync(
@@ -97,20 +76,12 @@ mod tests {
9776

9877
#[test]
9978
fn test_into_parsed_request() {
100-
let body = BootSourceBody {
101-
boot_source_id: String::from("/foo/bar"),
102-
source_type: BootSourceType::LocalImage,
103-
local_image: Some(LocalImage {
104-
kernel_image_path: String::from("/foo/bar"),
105-
}),
79+
let body = BootSourceConfig {
80+
kernel_image_path: String::from("/foo/bar"),
10681
boot_args: Some(String::from("foobar")),
10782
};
108-
let same_body = BootSourceBody {
109-
boot_source_id: String::from("/foo/bar"),
110-
source_type: BootSourceType::LocalImage,
111-
local_image: Some(LocalImage {
112-
kernel_image_path: String::from("/foo/bar"),
113-
}),
83+
let same_body = BootSourceConfig {
84+
kernel_image_path: String::from("/foo/bar"),
11485
boot_args: Some(String::from("foobar")),
11586
};
11687
let (sender, receiver) = oneshot::channel();

api_server/src/request/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use hyper::{Method, StatusCode};
1616

1717
use data_model::vm::{BlockDeviceConfig, DriveError, MachineConfiguration};
1818

19-
use self::boot_source::BootSourceBody;
19+
use self::boot_source::BootSourceConfig;
2020
use self::logger::APILoggerDescription;
2121
use self::net::NetworkInterfaceBody;
2222

@@ -68,7 +68,7 @@ impl GenerateResponse for () {
6868
// This enum contains messages for the VMM which represent sync requests. They each contain various
6969
// bits of information (ids, paths, etc.), together with an OutcomeSender, which is always present.
7070
pub enum VmmAction {
71-
ConfigureBootSource(BootSourceBody, OutcomeSender),
71+
ConfigureBootSource(BootSourceConfig, OutcomeSender),
7272
ConfigureLogger(APILoggerDescription, OutcomeSender),
7373
GetMachineConfiguration(OutcomeSender),
7474
InsertBlockDevice(BlockDeviceConfig, OutcomeSender),

api_server/swagger/firecracker.yaml

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -303,20 +303,14 @@ paths:
303303
definitions:
304304
BootSource:
305305
type: object
306+
required:
307+
- kernel_image_path
306308
description:
307-
Boot source descriptor. The only supported boot source type is the Local Image.
308-
Network Boot and Drive Boot will be added in future releases.
309+
Boot source descriptor.
309310
properties:
310-
boot_source_id:
311-
type: string
312-
description: Unique identifier for the boot source
313-
source_type:
314-
type: string
315-
description: Type of boot source
316-
enum:
317-
- LocalImage
318-
local_image:
319-
$ref: "#/definitions/LocalImage"
311+
kernel_image_path:
312+
type: string
313+
description: Host level path to the kernel image used to boot the guest
320314
boot_args:
321315
type: string
322316
description: Kernel boot arguments
@@ -402,15 +396,6 @@ definitions:
402396
- Halting
403397
- Halted
404398

405-
LocalImage:
406-
type: object
407-
description:
408-
Locations for local kernel image.
409-
properties:
410-
kernel_image_path:
411-
type: string
412-
description: Host level path to the kernel image used to boot the guest
413-
414399
Logger:
415400
type: object
416401
description:

tests/framework/microvm.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -390,11 +390,7 @@ def basic_config(
390390

391391
# Add a kernel to start booting from.
392392
response = self.boot.put(
393-
boot_source_id='1',
394-
source_type='LocalImage',
395-
local_image={'kernel_image_path': self.kernel_api_path(
396-
create=True
397-
)}
393+
kernel_image_path=self.kernel_api_path(create=True)
398394
)
399395
assert self.api_session.is_good_response(response.status_code)
400396

tests/framework/resources.py

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -85,19 +85,13 @@ def get(cls):
8585

8686
@staticmethod
8787
def create_json(
88-
boot_source_id=None,
89-
source_type=None,
90-
local_image=None,
91-
boot_args=None
88+
boot_args=None,
89+
kernel_image_path=None
9290
):
9391
"""Compose the json associated to this type of API request."""
9492
datax = {}
95-
if boot_source_id is not None:
96-
datax['boot_source_id'] = boot_source_id
97-
if source_type is not None:
98-
datax['source_type'] = source_type
99-
if local_image is not None:
100-
datax['local_image'] = local_image
93+
if kernel_image_path is not None:
94+
datax['kernel_image_path'] = kernel_image_path
10195
if boot_args is not None:
10296
datax['boot_args'] = boot_args
10397
return datax

tests/integration_tests/functional/test_api.py

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -44,19 +44,15 @@ def test_api_put_update_pre_boot(test_microvm_with_api):
4444

4545
# Updates to `kernel_image_path` with an invalid path are not allowed.
4646
response = test_microvm.boot.put(
47-
boot_source_id='1',
48-
source_type='LocalImage',
49-
local_image={'kernel_image_path': 'foo.bar'}
47+
kernel_image_path='foo.bar'
5048
)
5149
assert not test_microvm.api_session.is_good_response(response.status_code)
5250
assert "The kernel file cannot be opened due to invalid kernel path or " \
5351
"invalid permissions" in response.text
5452

5553
# Updates to `kernel_image_path` with a valid path are allowed.
5654
response = test_microvm.boot.put(
57-
boot_source_id='1',
58-
source_type='LocalImage',
59-
local_image={'kernel_image_path': test_microvm.kernel_api_path()}
55+
kernel_image_path=test_microvm.kernel_api_path()
6056
)
6157
assert test_microvm.api_session.is_good_response(response.status_code)
6258

@@ -255,9 +251,7 @@ def test_api_put_update_post_boot(test_microvm_with_api):
255251

256252
# Valid updates to `kernel_image_path` are not allowed after boot.
257253
response = test_microvm.boot.put(
258-
boot_source_id='1',
259-
source_type='LocalImage',
260-
local_image={'kernel_image_path': test_microvm.kernel_api_path()}
254+
kernel_image_path=test_microvm.kernel_api_path()
261255
)
262256
assert not test_microvm.api_session.is_good_response(response.status_code)
263257
assert "The update operation is not allowed after boot" in response.text
@@ -493,8 +487,7 @@ def test_api_patch_pre_boot(test_microvm_with_api):
493487

494488
# Partial updates to the boot source are not allowed.
495489
response = test_microvm.boot.patch(
496-
boot_source_id='1',
497-
local_image={'kernel_image_path': 'otherfile'}
490+
kernel_image_path='otherfile'
498491
)
499492
assert not test_microvm.api_session.is_good_response(response.status_code)
500493
assert "Invalid request method" in response.text
@@ -561,8 +554,7 @@ def test_api_patch_post_boot(test_microvm_with_api):
561554

562555
# Partial updates to the boot source are not allowed.
563556
response = test_microvm.boot.patch(
564-
boot_source_id='1',
565-
local_image={'kernel_image_path': 'otherfile'}
557+
kernel_image_path='otherfile'
566558
)
567559
assert not test_microvm.api_session.is_good_response(response.status_code)
568560
assert "Invalid request method" in response.text

vmm/src/lib.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1361,14 +1361,10 @@ impl Vmm {
13611361

13621362
match request {
13631363
VmmAction::ConfigureBootSource(boot_source_body, sender) => {
1364-
let boxed_response = match boot_source_body.local_image {
1365-
// Check that the kernel path exists and it is valid.
1366-
Some(local_image) => Box::new(self.configure_boot_source(
1367-
local_image.kernel_image_path,
1368-
boot_source_body.boot_args,
1369-
)),
1370-
None => Box::new(Err(BootSourceConfigError::EmptyKernelPath)),
1371-
};
1364+
let boxed_response = Box::new(self.configure_boot_source(
1365+
boot_source_body.kernel_image_path,
1366+
boot_source_body.boot_args
1367+
));
13721368
Vmm::send_response(boxed_response, sender);
13731369
}
13741370
VmmAction::ConfigureLogger(logger_description, sender) => {

0 commit comments

Comments
 (0)