From: Aaron Lauterer <a.lauterer@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH installer v4 21/30] auto-installer: fetch: add gathering of system identifiers and restructure code
Date: Thu, 4 Apr 2024 16:48:53 +0200 [thread overview]
Message-ID: <20240404144902.273800-22-a.lauterer@proxmox.com> (raw)
In-Reply-To: <20240404144902.273800-1-a.lauterer@proxmox.com>
They will be used as payload when POSTing a request for an answer file. The
idea is, that with this information, it should be possible to identify
the system and generate a matching answer file on the fly.
Many of these properties can also be found on the machine or packaging
of the machine and could therefore be scanned into a database.
Identifiers are the following properties from `dmidecode` sections 1, 2,
and 3:
* Asset Tag
* Product Name
* Serial Number
* SKU Number
* UUID
As well as a list of the MAC addresses of all the NICs and the product
type: pve, pmg, pbs.
Since we now have more than a simple utils.rs module in the fetch
plugins, it, and the additional fetch plugin utilities are placed in
their own directory.
Signed-off-by: Aaron Lauterer <a.lauterer@proxmox.com>
---
.../src/fetch_plugins/mod.rs | 2 +-
.../fetch_plugins/{utils.rs => utils/mod.rs} | 43 ++++++++--
.../src/fetch_plugins/utils/sysinfo.rs | 81 +++++++++++++++++++
3 files changed, 119 insertions(+), 7 deletions(-)
rename proxmox-auto-installer/src/fetch_plugins/{utils.rs => utils/mod.rs} (72%)
create mode 100644 proxmox-auto-installer/src/fetch_plugins/utils/sysinfo.rs
diff --git a/proxmox-auto-installer/src/fetch_plugins/mod.rs b/proxmox-auto-installer/src/fetch_plugins/mod.rs
index 11d6937..6f1e8a2 100644
--- a/proxmox-auto-installer/src/fetch_plugins/mod.rs
+++ b/proxmox-auto-installer/src/fetch_plugins/mod.rs
@@ -1,2 +1,2 @@
pub mod partition;
-mod utils;
+pub mod utils;
diff --git a/proxmox-auto-installer/src/fetch_plugins/utils.rs b/proxmox-auto-installer/src/fetch_plugins/utils/mod.rs
similarity index 72%
rename from proxmox-auto-installer/src/fetch_plugins/utils.rs
rename to proxmox-auto-installer/src/fetch_plugins/utils/mod.rs
index f2a8e74..b3e9dad 100644
--- a/proxmox-auto-installer/src/fetch_plugins/utils.rs
+++ b/proxmox-auto-installer/src/fetch_plugins/utils/mod.rs
@@ -1,5 +1,7 @@
-use anyhow::{bail, Error, Result};
+use anyhow::{Error, Result};
use log::{info, warn};
+use serde::Deserialize;
+use serde_json;
use std::{
fs::{self, create_dir_all},
path::{Path, PathBuf},
@@ -10,6 +12,8 @@ static ANSWER_MP: &str = "/mnt/answer";
static PARTLABEL: &str = "proxmoxinst";
static SEARCH_PATH: &str = "/dev/disk/by-label";
+pub mod sysinfo;
+
/// Searches for upper and lower case existence of the partlabel in the search_path
///
/// # Arguemnts
@@ -20,10 +24,10 @@ pub fn scan_partlabels(partlabel_source: &str, search_path: &str) -> Result<Path
let path = Path::new(search_path).join(&partlabel);
match path.try_exists() {
Ok(true) => {
- info!("Found partition with label '{partlabel}'");
+ info!("Found partition with label '{}'", partlabel);
return Ok(path);
}
- Ok(false) => info!("Did not detect partition with label '{partlabel}'"),
+ Ok(false) => info!("Did not detect partition with label '{}'", partlabel),
Err(err) => info!("Encountered issue, accessing '{}': {}", path.display(), err),
}
@@ -31,13 +35,15 @@ pub fn scan_partlabels(partlabel_source: &str, search_path: &str) -> Result<Path
let path = Path::new(search_path).join(&partlabel);
match path.try_exists() {
Ok(true) => {
- info!("Found partition with label '{partlabel}'");
+ info!("Found partition with label '{}'", partlabel);
return Ok(path);
}
- Ok(false) => info!("Did not detect partition with label '{partlabel}'"),
+ Ok(false) => info!("Did not detect partition with label '{}'", partlabel),
Err(err) => info!("Encountered issue, accessing '{}': {}", path.display(), err),
}
- bail!("Could not detect upper or lower case labels for '{partlabel_source}'");
+ Err(Error::msg(format!(
+ "Could not detect upper or lower case labels for '{partlabel_source}'"
+ )))
}
/// Will search and mount a partition/FS labeled proxmoxinst in lower or uppercase to ANSWER_MP;
@@ -79,3 +85,28 @@ fn check_if_mounted(target_path: &str) -> Result<bool> {
}
Ok(false)
}
+
+#[derive(Deserialize, Debug)]
+struct IpLinksUdevInfo {
+ ifname: String,
+}
+
+/// Returns vec of usable NICs
+pub fn get_nic_list() -> Result<Vec<String>> {
+ let ip_output = Command::new("/usr/sbin/ip")
+ .arg("-j")
+ .arg("link")
+ .output()?;
+ let parsed_links: Vec<IpLinksUdevInfo> =
+ serde_json::from_str(String::from_utf8(ip_output.stdout)?.as_str())?;
+ let mut links: Vec<String> = Vec::new();
+
+ for link in parsed_links {
+ if link.ifname == *"lo" {
+ continue;
+ }
+ links.push(link.ifname);
+ }
+
+ Ok(links)
+}
diff --git a/proxmox-auto-installer/src/fetch_plugins/utils/sysinfo.rs b/proxmox-auto-installer/src/fetch_plugins/utils/sysinfo.rs
new file mode 100644
index 0000000..8c57283
--- /dev/null
+++ b/proxmox-auto-installer/src/fetch_plugins/utils/sysinfo.rs
@@ -0,0 +1,81 @@
+use anyhow::{bail, Result};
+use proxmox_installer_common::setup::SetupInfo;
+use serde::Serialize;
+use std::{collections::HashMap, fs, io, path::Path};
+
+use super::get_nic_list;
+
+const DMI_PATH: &str = "/sys/devices/virtual/dmi/id";
+
+pub fn get_sysinfo(pretty: bool) -> Result<String> {
+ let system_files = vec![
+ "product_serial",
+ "product_sku",
+ "product_uuid",
+ "product_name",
+ ];
+ let baseboard_files = vec!["board_asset_tag", "board_serial", "board_name"];
+ let chassis_files = vec!["chassis_serial", "chassis_sku", "chassis_asset_tag"];
+
+ let system = get_dmi_infos(system_files)?;
+ let baseboard = get_dmi_infos(baseboard_files)?;
+ let chassis = get_dmi_infos(chassis_files)?;
+
+ let mut mac_addresses: Vec<String> = Vec::new();
+ let links = get_nic_list()?;
+ for link in links {
+ let address = fs::read_to_string(format!("/sys/class/net/{link}/address"))?;
+ let address = String::from(address.trim());
+ mac_addresses.push(address);
+ }
+
+ let iso_info = Path::new("/run/proxmox-installer/iso-info.json");
+ let mut product = String::from("Not available. Would be one of the following: pve, pmg, pbs");
+ if iso_info.exists() {
+ let file = fs::File::open("/run/proxmox-installer/iso-info.json")?;
+ let reader = io::BufReader::new(file);
+ let setup_info: SetupInfo = serde_json::from_reader(reader)?;
+ product = setup_info.config.product.to_string();
+ }
+
+ let sysinfo = SysInfo {
+ product,
+ system,
+ baseboard,
+ chassis,
+ mac_addresses,
+ };
+ if pretty {
+ return Ok(serde_json::to_string_pretty(&sysinfo)?);
+ }
+ Ok(serde_json::to_string(&sysinfo)?)
+}
+
+#[derive(Debug, Serialize)]
+struct SysInfo {
+ product: String,
+ system: HashMap<String, String>,
+ baseboard: HashMap<String, String>,
+ chassis: HashMap<String, String>,
+ mac_addresses: Vec<String>,
+}
+
+fn get_dmi_infos(files: Vec<&str>) -> Result<HashMap<String, String>> {
+ let mut res: HashMap<String, String> = HashMap::new();
+
+ for file in files {
+ let path = format!("{DMI_PATH}/{file}");
+ let content = match fs::read_to_string(&path) {
+ Err(ref err) if err.kind() == std::io::ErrorKind::NotFound => continue,
+ Err(ref err) if err.kind() == std::io::ErrorKind::PermissionDenied => {
+ bail!("Could not read data. Are you running as root or with sudo?")
+ }
+ Err(err) => bail!("Error: '{err}' on '{path}'"),
+ Ok(content) => content.trim().into(),
+ };
+ let key = file.splitn(2, '_').last().unwrap();
+ res.insert(key.into(), content);
+ }
+
+ Ok(res)
+}
--
2.39.2
next prev parent reply other threads:[~2024-04-04 14:49 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-04-04 14:48 [pve-devel] [PATCH installer v4 00/30] add automated/unattended installation Aaron Lauterer
2024-04-04 14:48 ` [pve-devel] [PATCH installer v4 01/30] tui: common: move InstallConfig struct to common crate Aaron Lauterer
2024-04-04 14:48 ` [pve-devel] [PATCH installer v4 02/30] common: make InstallZfsOption members public Aaron Lauterer
2024-04-04 14:48 ` [pve-devel] [PATCH installer v4 03/30] common: tui: use BTreeMap for predictable ordering Aaron Lauterer
2024-04-04 14:48 ` [pve-devel] [PATCH installer v4 04/30] common: utils: add deserializer for CidrAddress Aaron Lauterer
2024-04-04 14:48 ` [pve-devel] [PATCH installer v4 05/30] common: options: add Deserialize trait Aaron Lauterer
2024-04-04 14:48 ` [pve-devel] [PATCH installer v4 06/30] low-level: add dump-udev command Aaron Lauterer
2024-04-04 14:48 ` [pve-devel] [PATCH installer v4 07/30] add auto-installer crate Aaron Lauterer
2024-04-04 14:48 ` [pve-devel] [PATCH installer v4 08/30] auto-installer: add dependencies Aaron Lauterer
2024-04-04 14:48 ` [pve-devel] [PATCH installer v4 09/30] auto-installer: add answer file definition Aaron Lauterer
2024-04-04 14:48 ` [pve-devel] [PATCH installer v4 10/30] auto-installer: add struct to hold udev info Aaron Lauterer
2024-04-04 14:48 ` [pve-devel] [PATCH installer v4 11/30] auto-installer: add utils Aaron Lauterer
2024-04-04 14:48 ` [pve-devel] [PATCH installer v4 12/30] auto-installer: add simple logging Aaron Lauterer
2024-04-04 14:48 ` [pve-devel] [PATCH installer v4 13/30] auto-installer: add tests for answer file parsing Aaron Lauterer
2024-04-04 14:48 ` [pve-devel] [PATCH installer v4 14/30] auto-installer: add auto-installer binary Aaron Lauterer
2024-04-04 14:48 ` [pve-devel] [PATCH installer v4 15/30] auto-installer: add fetch answer binary Aaron Lauterer
2024-04-04 14:48 ` [pve-devel] [PATCH installer v4 16/30] unconfigured: add proxauto as option to start auto installer Aaron Lauterer
2024-04-04 14:48 ` [pve-devel] [PATCH installer v4 17/30] auto-installer: use glob crate for pattern matching Aaron Lauterer
2024-04-04 14:48 ` [pve-devel] [PATCH installer v4 18/30] auto-installer: utils: make get_udev_index functions public Aaron Lauterer
2024-04-04 14:48 ` [pve-devel] [PATCH installer v4 19/30] auto-installer: add proxmox-autoinst-helper tool Aaron Lauterer
2024-04-04 14:48 ` [pve-devel] [PATCH installer v4 20/30] common: add Display trait to ProxmoxProduct Aaron Lauterer
2024-04-04 14:48 ` Aaron Lauterer [this message]
2024-04-04 14:48 ` [pve-devel] [PATCH installer v4 22/30] auto-installer: helper: add subcommand to view indentifiers Aaron Lauterer
2024-04-04 14:48 ` [pve-devel] [PATCH installer v4 23/30] auto-installer: fetch: add http post utility module Aaron Lauterer
2024-04-04 14:48 ` [pve-devel] [PATCH installer v4 24/30] auto-installer: fetch: add http plugin to fetch answer Aaron Lauterer
2024-04-04 14:48 ` [pve-devel] [PATCH installer v4 25/30] control: update build depends for auto installer Aaron Lauterer
2024-04-04 14:48 ` [pve-devel] [PATCH installer v4 26/30] auto installer: factor out fetch-answer and autoinst-helper Aaron Lauterer
2024-04-04 14:48 ` [pve-devel] [PATCH installer v4 27/30] low-level: write low level config to /tmp Aaron Lauterer
2024-04-04 14:49 ` [pve-devel] [PATCH installer v4 28/30] common: add deserializer for FsType Aaron Lauterer
2024-04-04 14:49 ` [pve-devel] [PATCH installer v4 29/30] common: skip target_hd when deserializing InstallConfig Aaron Lauterer
2024-04-04 14:49 ` [pve-devel] [PATCH installer v4 30/30] add proxmox-chroot utility Aaron Lauterer
2024-04-05 12:38 ` [pve-devel] [PATCH installer v4 00/30] add automated/unattended installation Christoph Heiss
2024-04-05 14:25 ` [pve-devel] [PATCH v4 installer 31/30 follow-up] auto-installer: answer: deny unknown fields Aaron Lauterer
2024-04-09 9:20 ` Christoph Heiss
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240404144902.273800-22-a.lauterer@proxmox.com \
--to=a.lauterer@proxmox.com \
--cc=pve-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox