1 use anyhow
::{bail, format_err, Result}
;
4 fs
::{self, create_dir_all}
,
9 static ANSWER_FILE
: &str = "answer.toml";
10 static ANSWER_MP
: &str = "/mnt/answer";
11 // FAT can only handle 11 characters, so shorten Automated Installer Source to AIS
12 static PARTLABEL
: &str = "proxmox-ais";
13 static SEARCH_PATH
: &str = "/dev/disk/by-label";
15 pub struct FetchFromPartition
;
17 impl FetchFromPartition
{
18 /// Returns the contents of the answer file
19 pub fn get_answer() -> Result
<String
> {
20 info
!("Checking for answer file on partition.");
22 let mut mount_path
= PathBuf
::from(mount_proxmoxinst_part()?
);
23 mount_path
.push(ANSWER_FILE
);
24 let answer
= fs
::read_to_string(mount_path
)
25 .map_err(|err
| format_err
!("failed to read answer file - {err}"))?
;
27 info
!("Found answer file on partition.");
33 /// Searches for upper and lower case existence of the partlabel in the search_path
36 /// * `partlabel_source` - Partition Label, used as upper and lower case
37 /// * `search_path` - Path where to search for the partiiton label
38 fn scan_partlabels(partlabel_source
: &str, search_path
: &str) -> Result
<PathBuf
> {
39 let partlabel
= partlabel_source
.to_uppercase();
40 let path
= Path
::new(search_path
).join(&partlabel
);
41 match path
.try_exists() {
43 info
!("Found partition with label '{partlabel}'");
46 Ok(false) => info
!("Did not detect partition with label '{partlabel}'"),
47 Err(err
) => info
!("Encountered issue, accessing '{path:?}': {err}"),
50 let partlabel
= partlabel_source
.to_lowercase();
51 let path
= Path
::new(search_path
).join(&partlabel
);
52 match path
.try_exists() {
54 info
!("Found partition with label '{partlabel}'");
57 Ok(false) => info
!("Did not detect partition with label '{partlabel}'"),
58 Err(err
) => info
!("Encountered issue, accessing '{path:?}': {err}"),
60 bail
!("Could not detect upper or lower case labels for '{partlabel_source}'");
63 /// Will search and mount a partition/FS labeled PARTLABEL (proxmox-ais) in lower or uppercase
65 fn mount_proxmoxinst_part() -> Result
<String
> {
66 if let Ok(true) = check_if_mounted(ANSWER_MP
) {
67 info
!("Skipping: '{ANSWER_MP}' is already mounted.");
68 return Ok(ANSWER_MP
.into());
70 let part_path
= scan_partlabels(PARTLABEL
, SEARCH_PATH
)?
;
71 info
!("Mounting partition at {ANSWER_MP}");
72 // create dir for mountpoint
73 create_dir_all(ANSWER_MP
)?
;
74 match Command
::new("mount")
81 if output
.status
.success() {
84 warn
!("Error mounting: {}", String
::from_utf8(output
.stderr
)?
);
88 Err(err
) => bail
!("Error mounting: {err}"),
92 fn check_if_mounted(target_path
: &str) -> Result
<bool
> {
93 let mounts
= fs
::read_to_string("/proc/mounts")?
;
94 for line
in mounts
.lines() {
95 if let Some(mp
) = line
.split(' '
).nth(1) {
96 if mp
== target_path
{