Skip to content

Conversation

@iulianbarbu
Copy link

@iulianbarbu iulianbarbu commented Nov 26, 2019

Signed-off-by: Iulian Barbu iul@amazon.com

Reason for This PR

Fixes #1125

Description of Changes

Some of Firecracker crates have dev-dependency on tempfile crate from crates.io. This crate has other dependencies on its own that are brought into Firecracker as well.

Removed tempfile crate dev-dependency and used instead vmm-sys-util tempfile module, which basically replaces tempfile crate with a simpler implementation for temporary files & temporary directories, without additional dependencies.

License Acceptance

By submitting this pull request, I confirm that my contribution is made under
the terms of the Apache 2.0 license.

PR Checklist

[Author TODO: Meet these criteria. Where there are two options, keep one.]
[Reviewer TODO: Verify that these criteria are met. Request changes if not]

  • All commits in this PR are signed (git commit -s).
  • Either this PR is linked to an issue, or, the reason for this PR is
    clearly provided.
  • The description of changes is clear and encompassing.
  • Either no docs need to be updated as part of this PR, or, the required
    doc changes are included in this PR. Docs in scope are all *.md files
    located either in the repository root, or in the docs/ directory.
  • Either no code has been touched, or, code-level documentation for touched
    code is included in this PR.
  • Either no API changes are included in this PR, or, the API changes are
    reflected in firecracker/swagger.yaml.
  • Either the changes in this PR have no user impact, or, the changes in
    this PR have user impact and have been added to the CHANGELOG.md file.
  • Either no new unsafe code has been added, or, the newly added unsafe
    code is unavoidable and properly documented.

@iulianbarbu iulianbarbu force-pushed the remove_tempfile_dependency branch from 7f77d6d to 79cde8f Compare November 26, 2019 11:23
Comment on lines 717 to 718
.read(true)
.write(true)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we add open options based on is_disk_read_only flag?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I agree. I've updated, please take a look: devices/src/virtio/block.rs:716.

@iulianbarbu iulianbarbu force-pushed the remove_tempfile_dependency branch from 79cde8f to 145621d Compare November 26, 2019 12:42
@iulianbarbu iulianbarbu force-pushed the remove_tempfile_dependency branch from 145621d to f1754fb Compare November 26, 2019 15:22
@iulianbarbu iulianbarbu force-pushed the remove_tempfile_dependency branch 4 times, most recently from 712a370 to fac9248 Compare November 28, 2019 09:31
@iulianbarbu iulianbarbu force-pushed the remove_tempfile_dependency branch 6 times, most recently from ed4ee2c to d7d365f Compare November 29, 2019 11:46
/// otherwise inside `/tmp` if non-Android system.
pub fn tempfile() -> Result<tempfile::TempFile> {
let mut in_tmp_dir = temp_dir();
in_tmp_dir.push("");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this needed ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll leave a comment with the reason above the line in the code.

The reason is that the call for temp_dir is returning a PathBuf with the content /tmp. When creating a TempFile::new(prefix), the prefix needs to be an explicit path/prefix where the temporary file name (a random string of 5 chars) will be placed/appended to.

If we would have just the path /tmp, when we will try to create a temporary file inside the /tmp directory, that will not happen because, the actual call to TempFile::new("/tmp") will create a file which will have a name similiar to this /tmpXVFGB, which is incorrect.

The call to in_tmp_dir.push("") will append a trailing /, which will result in /tmp/ and which will make successful the call to TempFile::new(in_tmp_dir).

/// * `path` - A path to a specific directory (e.g "/tmp/x" or "/tmp/x/").
pub fn tempfile_in(path: &Path) -> Result<tempfile::TempFile> {
let mut path_buf = path.canonicalize().unwrap();
path_buf.push("");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this needed ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above.

use crate::tempfile::tempfile;

#[test]
fn test_tempfile_new() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the method name seems outdated.

/// Wrapper over vmm_sys_util::tempfile::TempFile::new().
/// This creates a temporary file inside $TMPDIR if set,
/// otherwise inside `/tmp` if non-Android system.
pub fn tempfile() -> Result<tempfile::TempFile> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if this should be called simply tempfile() or if something like create_temfile() would be better.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather keep it simple. I admit that I am biased because of the API offered by tempfile crate from crates.io, which exposes the method with the same name for creating an "anonymous" temporary file.

The method is documented and commented, so its usage should be pretty clear, while its name, although does not explicitly suggest creation of a tempfile, it surely implies it, because you can see it as a short form of get_tempfile().


/// Wrapper over vmm_sys_util::tempdir::TempDir::new().
/// This creates a temporary directory inside $TMPDIR if set,
/// otherwise inside `/tmp` if non-Android system.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's with the non-Android comment?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll remove the note, because it is useless in our case. In Android systems the "/tmp" directory is "/data/local/tmp".

/// Wrapper over vmm_sys_util::tempfile::TempFile::new().
/// This creates a temporary file inside $TMPDIR if set,
/// otherwise inside `/tmp` if non-Android system.
pub fn tempfile() -> Result<tempfile::TempFile> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was picturing this more like a new Tempfile structure that extends the existing Tempfile from vmm-sys-util. I also thing that the goal should be to merge this changes in vmm-sys-util. To unblock ourselves it's okay to have these changes in Firecracker.

I quickly typed something that works as an example (it can be made nicer):

pub struct TempFile(tempfile::TempFile);

impl TempFile {
    fn new() -> Result<Self> {
        let mut in_tmp_dir = temp_dir();
        in_tmp_dir.push("");
        let temp_file = tempfile::TempFile::new(in_tmp_dir)?;
        Ok(TempFile(temp_file))
    }

    fn new_with_path(path: &Path) -> Result<Self> {
        let mut in_tmp_dir = temp_dir();
        let temp_file = tempfile::TempFile::new(in_tmp_dir)?;
        Ok(TempFile(temp_file))
    }

    fn path_ref(&self) -> &Path {
        self.0.as_path()
    }
}

The reason for which I prefer a structure is because I don't particularly like orphan functions, but this is subjective. Let me know what you think.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update: you don't need path_ref as you can implement deref for TempFile.

impl Deref for TempFile {
    type Target = tempfile::TempFile;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, this would work better, since it resembles the struct from vmm-sys-utils. I'll make it so.

@iulianbarbu iulianbarbu force-pushed the remove_tempfile_dependency branch 3 times, most recently from 94c3466 to f68b1ad Compare November 29, 2019 14:19

[dev-dependencies]
tempfile = ">=3.0.2"
utils = { path = "../utils" }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not required, already present in dependencies


[dev-dependencies]
tempfile = ">=3.0.2"
utils = { path = "../utils" }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here, not required.

use self::tempfile::NamedTempFile;
use super::*;
use log::MetadataBuilder;
extern crate utils;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not required, already declared outside of tests.


[dev-dependencies]
tempfile = ">=3.0.2"
utils = { path = "../utils" }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not required

Comment on lines 16 to 23
pub fn new() -> Result<Self> {
let mut in_tmp_dir = temp_dir();
// This `push` adds a trailing slash ("/tmp" -> "/tmp/").
// This is safe for paths with already trailing slash.
in_tmp_dir.push("");
let temp_dir = tempdir::TempDir::new(in_tmp_dir)?;
Ok(TempDir(temp_dir))
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would've liked to have this directly in vmm-sys-util and not wrap it ourselved in Firecracker. I say you open a PR there as well and not let this dangling.

Copy link
Author

@iulianbarbu iulianbarbu Dec 2, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. We should expose this functionality from vmm-sys-util. I will open a PR there soon.


[dev-dependencies]
tempfile = ">=3.0.2"
utils = { path = "../utils" }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
utils = { path = "../utils" }

extern crate tempfile;

use super::*;
extern crate utils;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
extern crate utils;

And while you're at it please also remove:

extern crate logger;
extern crate utils;

in src/vmm/src/signal_handler.rs.

#[cfg(test)]
mod tests {
extern crate tempfile;
extern crate utils;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
extern crate utils;

mod tests {
extern crate tempfile;
use self::tempfile::NamedTempFile;
extern crate utils;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
extern crate utils;

@iulianbarbu iulianbarbu force-pushed the remove_tempfile_dependency branch 2 times, most recently from 7f593e3 to 2399233 Compare December 2, 2019 15:45
@iulianbarbu
Copy link
Author

I've included the received feedback. Please, take a look at 2399233.

serban300
serban300 previously approved these changes Dec 3, 2019
@dianpopa
Copy link
Contributor

dianpopa commented Dec 5, 2019

Will continue work here only after rust-vmm/vmm-sys-util#54 has been merged.

@dianpopa dianpopa added Status: Blocked Indicates that an issue or pull request cannot currently be worked on and removed Status: Author labels Dec 5, 2019
@iulianbarbu iulianbarbu force-pushed the remove_tempfile_dependency branch 5 times, most recently from b1cee13 to 1279129 Compare December 10, 2019 06:47
serban300
serban300 previously approved these changes Dec 10, 2019
@iulianbarbu iulianbarbu force-pushed the remove_tempfile_dependency branch 2 times, most recently from 116e01e to aa9dd8f Compare December 10, 2019 14:29
rate_limiter = { path = "../rate_limiter" }
virtio_gen = { path = "../virtio_gen" }

[dev-dependencies]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your commit message contains a typo but I d go further and I d say Replace tempfile external dependency and in the description I would say that we are now using vmm-sys-util's tempfile implementation. Remove tempfile... suggests that we are no longer using temporary files in Firecracker at all which is inaccurate.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove tempfile ... is inaccurate, I agree, but Remove tempfile dependency it has something to do with the dependency, not with the tempfile. I think the commit needs a proper description, to log basically what the change has achieved. I'll add a description.


use libc;

use self::utils::tempfile::TempFile;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You do not need self:: here.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True that. Removed self::. Take a look: src/devices/src/virtio/block.rs.


[dev-dependencies]
tempfile = ">=3.0.2"
[dev-dependencies]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a no newline at end of file warning. However, why not removing the dev-dependencies section for good?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. 👍

use std::io::Write;
use std::path::PathBuf;

use self::utils::tempdir::TempDir;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for self::

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. 👍

use std::mem;
use std::path::Path;

use self::utils::tempfile::TempFile;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need for self::

Copy link
Author

@iulianbarbu iulianbarbu Dec 10, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I couldn't run the tests if I wouldn't use self::. The reason is that extern crate utils appears only inside themmap::tests module, and is not defined outside, in other file from memory_model crate, to be imported when we use super::*. Per my understanding, in this situation, utils crate is visible only within mod tests. To be used even by the module itself, the use has to be referenced with self::.

&app_info,
Box::new(log_file_temp),
Box::new(metrics_file_temp),
Box::new(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By looking at the TempFile implementation, calling the new() method will create a Path and File object for you.
However, calling OpenOptions::new will create a new File at the path previosuly returned by TempFile. In order to avoid recreating a new File, we need a way to make use of the File inside the TempFile object. For this logger specific usecase, one way would be to implement the relevant File traits on TempFile (I.e Write, Read etc).
I already opened a PR in vmm-sys-util that implements those traits since I think this is a miss of the initial implementation. So, I suggest waiting for ti to be merged.
After that, your code will just look like this:

ssert!(l
            .init(
                &app_info,
                Box::new(
                    log_file_temp
                ),
                Box::new(
                    metrics_file_temp
                ),
            )
            .is_ok());

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK. 👍

Copy link
Author

@iulianbarbu iulianbarbu Dec 10, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, because it might spread to another week, what do you think if we merge this like it is, if we get the approves? We can update with your suggestion in a subsequent PR. Thinking about it, this PR should've not been blocked at all. The updates could've been added in subsequent PRs (TempFile API changes, signal API refactoring). Please let me know what you think. I just want to not get blocked here everytime we find things that miss or need changes in rust-vmm/vmm-sys-util, because I found another thing that needs a change on rust-vmm/vmm-sys-util, and I've managed to work around it, although I would prefer pushing changes to rust-vmm/vmm-sys-util.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree

DummyBlock {
block: Block::new(f, is_disk_read_only, epoll_config, Some(rate_limiter)).unwrap(),
block: Block::new(
OpenOptions::new()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not tmp_f.as_file().try_clone().unwrap() instead of OpenOptions::new()..?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. This option will do, but we have to modify the permissions on the cloned file. Basically, we have to give write permission or not, depending on the is_disk_read_only variable. Take look: src/devices/src/virtio/block.rs.

.is_ok());

let mut f = tempfile().unwrap();
let temp_f = TempFile::new().unwrap();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When TempFile will implement Read, you can do:

let mut temp_f = ...
`.read_to_memory(1, &mut temp_f, mem::size_of::<u32>())`

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure.

@iulianbarbu iulianbarbu force-pushed the remove_tempfile_dependency branch 2 times, most recently from a48e5de to 10ded83 Compare December 10, 2019 20:00
@iulianbarbu iulianbarbu added Status: Awaiting review Indicates that a pull request is ready to be reviewed and removed Status: Blocked Indicates that an issue or pull request cannot currently be worked on labels Dec 10, 2019
@iulianbarbu iulianbarbu force-pushed the remove_tempfile_dependency branch from 10ded83 to c61203f Compare December 10, 2019 23:56
Removed `tempfile` crate dependency, from crates.io, which
was heavily using other dependencies which Firecracker does
not use. Used instead `rust-vmm/vmm-sys-util` tempfile
implementation, which provides support from temporary file
and directory creation.

Fixes firecracker-microvm#1125

Signed-off-by: Iulian Barbu <iul@amazon.com>
@iulianbarbu iulianbarbu force-pushed the remove_tempfile_dependency branch from c61203f to 3cc80f3 Compare December 10, 2019 23:58
@dianpopa dianpopa dismissed their stale review December 11, 2019 08:29

Changes look good now

@acatangiu
Copy link
Contributor

@iulianbarbu if we merge it like this, please add an issue describing the leftover improvements so we can track them.

@iulianbarbu
Copy link
Author

@iulianbarbu if we merge it like this, please add an issue describing the leftover improvements so we can track them.

I've added the following issue: #1466.

@iulianbarbu iulianbarbu merged commit f244f51 into firecracker-microvm:master Dec 11, 2019
@dianpopa dianpopa mentioned this pull request Jan 13, 2020
@iulianbarbu iulianbarbu deleted the remove_tempfile_dependency branch February 18, 2020 14:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Status: Awaiting review Indicates that a pull request is ready to be reviewed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Remove tempfile dependency

6 participants