Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 6 additions & 8 deletions crates/dragonfly-actions/src/actions/image2disk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ impl Action for Image2DiskAction {
));

if let Err(e) = Command::new("partprobe")
.arg(&dest_disk)
.arg(dest_disk)
.output()
.await
.map_err(|e| ActionError::ExecutionFailed(format!("Failed to run partprobe: {}", e)))
Expand Down Expand Up @@ -330,7 +330,7 @@ async fn stream_from_url(
format!(
"Downloading {} ({})",
url,
total_size.map(|s| format_bytes(s)).unwrap_or_else(|| "unknown size".to_string())
total_size.map(format_bytes).unwrap_or_else(|| "unknown size".to_string())
),
));

Expand All @@ -344,7 +344,7 @@ async fn stream_from_url(
// Convert response body to async reader
let stream = response.bytes_stream();
let stream_reader = tokio_util::io::StreamReader::new(
stream.map(|result| result.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e)))
stream.map(|result| result.map_err(std::io::Error::other))
);
let buffered = BufReader::new(stream_reader);

Expand Down Expand Up @@ -616,7 +616,6 @@ async fn stream_tar_from_url(
reporter: &dyn crate::progress::ProgressReporter,
action_name: &str,
) -> Result<u64> {
use tokio_tar::Archive;

// Create HTTP client and start download
let client = reqwest::Client::new();
Expand All @@ -641,14 +640,14 @@ async fn stream_tar_from_url(
format!(
"Downloading tar archive {} ({})",
url,
total_size.map(|s| format_bytes(s)).unwrap_or_else(|| "unknown size".to_string())
total_size.map(format_bytes).unwrap_or_else(|| "unknown size".to_string())
),
));

// Convert response body to async reader
let stream = response.bytes_stream();
let stream_reader = tokio_util::io::StreamReader::new(
stream.map(|result| result.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e)))
stream.map(|result| result.map_err(std::io::Error::other))
);
let buffered = BufReader::new(stream_reader);

Expand Down Expand Up @@ -719,7 +718,6 @@ async fn extract_disk_from_tar<R: AsyncRead + Unpin>(
action_name: &str,
) -> Result<u64> {
use tokio_tar::Archive;
use tokio::io::AsyncReadExt;

let mut archive = Archive::new(reader);
let mut entries = archive.entries().map_err(|e| {
Expand All @@ -734,7 +732,7 @@ async fn extract_disk_from_tar<R: AsyncRead + Unpin>(

// Find the disk image entry (look for .raw, .img, or largest file)
while let Some(entry) = entries.next().await {
let mut entry = entry.map_err(|e| {
let entry = entry.map_err(|e| {
ActionError::ExecutionFailed(format!("Failed to read tar entry: {}", e))
})?;

Expand Down
39 changes: 16 additions & 23 deletions crates/dragonfly-actions/src/actions/writefile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ impl Action for WriteFileAction {
let mount_action = {
let mounted_guard = MOUNTED.lock().unwrap();
match mounted_guard.as_ref() {
Some(current) if current == &disk => {
Some(current) if current == disk => {
drop(mounted_guard);
None // Already mounted
}
Expand All @@ -123,7 +123,7 @@ impl Action for WriteFileAction {
// Different disk mounted, unmount first
do_unmount().await?;
}
do_mount(&disk).await?;
do_mount(disk).await?;
let mut guard = MOUNTED.lock().unwrap();
*guard = Some(disk.to_string());
drop(guard);
Expand Down Expand Up @@ -165,7 +165,7 @@ impl Action for WriteFileAction {

// Prepend mount point if we're writing to a mounted partition
let actual_path = if let Some(mnt) = mount_point {
Path::new(mnt).join(&dest_path.strip_prefix('/').unwrap_or(&dest_path))
Path::new(mnt).join(dest_path.strip_prefix('/').unwrap_or(dest_path))
} else {
Path::new(dest_path).to_path_buf()
};
Expand All @@ -174,9 +174,9 @@ impl Action for WriteFileAction {
let create_dirs = ctx.env("CREATE_DIRS").map(|v| v == "true").unwrap_or(true);
let path = &actual_path;

if create_dirs {
if let Some(parent) = path.parent() {
if !parent.exists() {
if create_dirs
&& let Some(parent) = path.parent()
&& !parent.exists() {
reporter.report(Progress::new(
self.name(),
30,
Expand All @@ -190,8 +190,6 @@ impl Action for WriteFileAction {
))
})?;
}
}
}

// Write the file
reporter.report(Progress::new(
Expand Down Expand Up @@ -275,44 +273,39 @@ fn detect_filesystem(device: &str) -> Option<String> {
let mut buf = [0u8; 8];

// Check for ext2/3/4: magic 0xEF53 at offset 1080 (0x438)
if file.seek(SeekFrom::Start(0x438)).is_ok() && file.read_exact(&mut buf[..2]).is_ok() {
if buf[0] == 0x53 && buf[1] == 0xEF {
if file.seek(SeekFrom::Start(0x438)).is_ok() && file.read_exact(&mut buf[..2]).is_ok()
&& buf[0] == 0x53 && buf[1] == 0xEF {
tracing::debug!("Detected ext2/3/4 filesystem on {}", device);
return Some("ext4".to_string()); // ext4 is backward compatible
}
}

// Check for XFS: magic "XFSB" at offset 0
if file.seek(SeekFrom::Start(0)).is_ok() && file.read_exact(&mut buf[..4]).is_ok() {
if &buf[..4] == b"XFSB" {
if file.seek(SeekFrom::Start(0)).is_ok() && file.read_exact(&mut buf[..4]).is_ok()
&& &buf[..4] == b"XFSB" {
tracing::debug!("Detected XFS filesystem on {}", device);
return Some("xfs".to_string());
}
}

// Check for btrfs: magic "_BHRfS_M" at offset 0x10040
if file.seek(SeekFrom::Start(0x10040)).is_ok() && file.read_exact(&mut buf).is_ok() {
if &buf == b"_BHRfS_M" {
if file.seek(SeekFrom::Start(0x10040)).is_ok() && file.read_exact(&mut buf).is_ok()
&& &buf == b"_BHRfS_M" {
tracing::debug!("Detected btrfs filesystem on {}", device);
return Some("btrfs".to_string());
}
}

// Check for FAT32: Look for FAT signature
if file.seek(SeekFrom::Start(0x52)).is_ok() && file.read_exact(&mut buf).is_ok() {
if &buf[..5] == b"FAT32" {
if file.seek(SeekFrom::Start(0x52)).is_ok() && file.read_exact(&mut buf).is_ok()
&& &buf[..5] == b"FAT32" {
tracing::debug!("Detected FAT32 filesystem on {}", device);
return Some("vfat".to_string());
}
}

// Check for FAT16/FAT12
if file.seek(SeekFrom::Start(0x36)).is_ok() && file.read_exact(&mut buf).is_ok() {
if &buf[..3] == b"FAT" {
if file.seek(SeekFrom::Start(0x36)).is_ok() && file.read_exact(&mut buf).is_ok()
&& &buf[..3] == b"FAT" {
tracing::debug!("Detected FAT filesystem on {}", device);
return Some("vfat".to_string());
}
}

tracing::warn!("Could not detect filesystem type on {}", device);
None
Expand Down
10 changes: 4 additions & 6 deletions crates/dragonfly-crd/src/hardware.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,15 +176,14 @@ impl HardwareSpec {

/// Builder method to configure DHCP on first interface
pub fn with_ip(mut self, address: impl Into<String>) -> Self {
if let Some(iface) = self.interfaces.first_mut() {
if let Some(dhcp) = &mut iface.dhcp {
if let Some(iface) = self.interfaces.first_mut()
&& let Some(dhcp) = &mut iface.dhcp {
dhcp.ip = Some(IpSpec {
address: address.into(),
gateway: None,
netmask: None,
});
}
}
self
}

Expand Down Expand Up @@ -327,11 +326,10 @@ impl DhcpSpec {
}

// Validate IP address if present
if let Some(ip) = &self.ip {
if IpAddr::from_str(&ip.address).is_err() {
if let Some(ip) = &self.ip
&& IpAddr::from_str(&ip.address).is_err() {
return Err(CrdError::InvalidIpAddress(ip.address.clone()));
}
}

Ok(())
}
Expand Down
15 changes: 1 addition & 14 deletions crates/dragonfly-crd/src/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::collections::HashMap;
use uuid::Uuid;

/// Kubernetes-style object metadata
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct ObjectMeta {
/// Resource name (required)
Expand Down Expand Up @@ -76,19 +76,6 @@ impl ObjectMeta {
}
}

impl Default for ObjectMeta {
fn default() -> Self {
Self {
name: String::new(),
namespace: None,
uid: None,
resource_version: None,
labels: HashMap::new(),
annotations: HashMap::new(),
creation_timestamp: None,
}
}
}

/// Type metadata for CRD objects
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
Expand Down
4 changes: 2 additions & 2 deletions crates/dragonfly-dhcp/src/packet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ impl DhcpRequest {
.get(OptionCode::MessageType)
.and_then(|opt| {
if let DhcpOption::MessageType(mt) = opt {
Some(mt.clone())
Some(*mt)
} else {
None
}
Expand Down Expand Up @@ -138,7 +138,7 @@ impl DhcpRequest {
.get(OptionCode::RequestedIpAddress)
.and_then(|opt| {
if let DhcpOption::RequestedIpAddress(ip) = opt {
Some(ip.clone())
Some(*ip)
} else {
None
}
Expand Down
10 changes: 4 additions & 6 deletions crates/dragonfly-dhcp/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,13 +271,12 @@ impl DhcpServer {
}
MessageType::Request => {
// Verify requested IP matches
if let Some(requested) = request.requested_ip {
if requested != offered_ip {
if let Some(requested) = request.requested_ip
&& requested != offered_ip {
// Send NAK
let response = self.build_nak(request)?;
return Ok(Some((response, None, "NAK".to_string())));
}
}
let response = self.build_ack(request, offered_ip, hardware)?;
Ok(Some((response, Some(offered_ip), "ACK".to_string())))
}
Expand Down Expand Up @@ -332,12 +331,11 @@ impl DhcpServer {
}

// If we have hardware, check if PXE is allowed
if let Some(hw) = hardware {
if !hw.allows_pxe() {
if let Some(hw) = hardware
&& !hw.allows_pxe() {
debug!(mac = %request.mac_address, "PXE not allowed for hardware");
return Ok(None);
}
}

// In auto-proxy, we respond even without hardware record
// (for discovery boot)
Expand Down
14 changes: 1 addition & 13 deletions crates/dragonfly-ipxe/src/script.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use crate::error::Result;
use dragonfly_crd::Hardware;

/// Configuration for iPXE script generation
#[derive(Debug, Clone)]
#[derive(Default, Debug, Clone)]
pub struct IpxeConfig {
/// Base URL for fetching resources (e.g., http://192.168.1.1:8080)
pub base_url: String,
Expand All @@ -45,18 +45,6 @@ pub struct IpxeConfig {
pub verbose: bool,
}

impl Default for IpxeConfig {
fn default() -> Self {
Self {
base_url: String::new(),
kernel_params: Vec::new(),
console: None,
verbose: false,
mage_kernel_url: None,
mage_initramfs_url: None,
}
}
}

impl IpxeConfig {
/// Create a new config with base URL
Expand Down
3 changes: 2 additions & 1 deletion crates/dragonfly-server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ description = "API server for Dragonfly bare metal infrastructure management"
[features]
default = []
server-binary = []
k8s = []

[dependencies]
# Web Framework
Expand Down Expand Up @@ -135,4 +136,4 @@ rust-embed = { version = "8", features = ["interpolate-folder-path"] }
mime_guess = "2"

[dev-dependencies]
tempfile = "3.8"
tempfile = "3.8"
Loading