mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-08-17 07:27:22 +00:00
Merge fce1234d9a
into 9379a18c8a
This commit is contained in:
commit
db14cec489
@ -9,7 +9,7 @@ use std::fs::{self, File};
|
||||
use std::io::{BufRead, BufReader};
|
||||
use std::ops::Deref;
|
||||
use std::path::Path;
|
||||
|
||||
use std::process::Command;
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use kata_sys_util::mount::{get_linux_mount_info, parse_mount_options};
|
||||
use nix::mount::MsFlags;
|
||||
@ -63,6 +63,52 @@ lazy_static! {
|
||||
];
|
||||
}
|
||||
|
||||
#[instrument]
|
||||
pub async fn resize_file_system(mountpoint: &String, logger: &Logger) -> Result<()> {
|
||||
let logger = logger.new(o!("subsystem" => "resize_file_system"));
|
||||
match get_linux_mount_info(mountpoint) {
|
||||
Ok(info) => {
|
||||
info!(
|
||||
logger,
|
||||
"Resizing {} file system on device {:?}",
|
||||
info.fs_type,
|
||||
info.device
|
||||
);
|
||||
|
||||
let status = match info.fs_type.as_str() {
|
||||
"ext2" | "ext3" | "ext4" => {
|
||||
Command::new("resize2fs")
|
||||
.arg(&info.device)
|
||||
.status()
|
||||
.context("Failed to execute resize2fs")?
|
||||
}
|
||||
"xfs" => {
|
||||
Command::new("xfs_growfs")
|
||||
.arg(&info.path)
|
||||
.status()
|
||||
.context("Failed to execute xfs_growfs")?
|
||||
}
|
||||
other => {
|
||||
return Err(anyhow!(
|
||||
"Unsupported filesystem type: {} for device {}",
|
||||
other,
|
||||
info.device
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
if !status.success() {
|
||||
return Err(anyhow!(
|
||||
"Filesystem resize failed with exit code: {:?}",
|
||||
status.code()
|
||||
));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => Err(anyhow!("Error getting mount info: {:?}", e)),
|
||||
}
|
||||
}
|
||||
#[instrument]
|
||||
pub fn baremount(
|
||||
source: &Path,
|
||||
|
@ -7,7 +7,7 @@ use std::fmt;
|
||||
use std::ops::Deref;
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::anyhow;
|
||||
use anyhow::{anyhow,Context};
|
||||
|
||||
// The PCI spec reserves 5 bits (0..31) for slot number (a.k.a. device
|
||||
// number)
|
||||
@ -18,11 +18,21 @@ const SLOT_MAX: u8 = (1 << SLOT_BITS) - 1;
|
||||
const FUNCTION_BITS: u8 = 3;
|
||||
const FUNCTION_MAX: u8 = (1 << FUNCTION_BITS) - 1;
|
||||
|
||||
const PCI_RESCAN_FILE: &str = "/sys/bus/pci/rescan";
|
||||
const PCI_RESCAN_SIGNAL: &str = "1";
|
||||
// Represents a PCI function's slot (a.k.a. device) and function
|
||||
// numbers, giving its location on a single logical bus
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct SlotFn(u8);
|
||||
|
||||
pub async fn rescan_pci_meta() -> anyhow::Result<()> {
|
||||
tokio::fs::write(PCI_RESCAN_FILE, PCI_RESCAN_SIGNAL)
|
||||
.await
|
||||
.context(format!(
|
||||
"PCI rescan failed: writing '{}' to {}",
|
||||
PCI_RESCAN_SIGNAL, PCI_RESCAN_FILE
|
||||
))?;
|
||||
Ok(())
|
||||
}
|
||||
impl SlotFn {
|
||||
pub fn new<T, U>(ss: T, f: U) -> anyhow::Result<Self>
|
||||
where
|
||||
|
@ -66,7 +66,7 @@ use crate::device::network_device_handler::wait_for_pci_net_interface;
|
||||
use crate::device::{add_devices, handle_cdi_devices, update_env_pci};
|
||||
use crate::features::get_build_features;
|
||||
use crate::metrics::get_metrics;
|
||||
use crate::mount::baremount;
|
||||
use crate::mount::{baremount, resize_file_system};
|
||||
use crate::namespace::{NSTYPEIPC, NSTYPEPID, NSTYPEUTS};
|
||||
use crate::network::setup_guest_dns;
|
||||
use crate::passfd_io;
|
||||
@ -825,7 +825,17 @@ impl agent_ttrpc::AgentService for AgentService {
|
||||
|
||||
Ok(Empty::new())
|
||||
}
|
||||
|
||||
async fn resize_volume(
|
||||
&self,
|
||||
ctx: &TtrpcContext,
|
||||
req: protocols::agent::ResizeVolumeRequest,
|
||||
) -> ttrpc::Result<Empty> {
|
||||
trace_rpc_call!(ctx, "resize_volume", req);
|
||||
is_allowed(&req).await?;
|
||||
pci::rescan_pci_meta().await.map_ttrpc_err(same)?;
|
||||
resize_file_system(&req.volume_guest_path, &sl()).await.map_ttrpc_err(same)?;
|
||||
Ok(Empty::new())
|
||||
}
|
||||
async fn stats_container(
|
||||
&self,
|
||||
ctx: &TtrpcContext,
|
||||
|
@ -826,10 +826,18 @@ func (q *QMP) ExecuteBlockdevAddWithCache(ctx context.Context, blockDevice *Bloc
|
||||
"direct": direct,
|
||||
"no-flush": noFlush,
|
||||
}
|
||||
|
||||
return q.executeCommand(ctx, "blockdev-add", blockdevArgs, nil)
|
||||
}
|
||||
|
||||
func (q *QMP) ExecuteBlockdevResize(ctx context.Context, blockDeviceID string, size uint64) error {
|
||||
blockdevArgs := map[string]interface{}{
|
||||
"node-name": blockDeviceID,
|
||||
"size": size,
|
||||
}
|
||||
|
||||
return q.executeCommand(ctx, "block_resize", blockdevArgs, nil)
|
||||
}
|
||||
|
||||
// ExecuteBlockdevAddWithDriverCache has three one parameter driver
|
||||
// than ExecuteBlockdevAddWithCache.
|
||||
// Parameter driver can set the driver of block device.
|
||||
|
@ -1144,7 +1144,9 @@ func (clh *cloudHypervisor) ResizeVCPUs(ctx context.Context, reqVCPUs uint32) (c
|
||||
|
||||
return currentVCPUs, newVCPUs, nil
|
||||
}
|
||||
|
||||
func (clh *cloudHypervisor) ResizeBlock(ctx context.Context, deviceID string, size uint64) error {
|
||||
return nil
|
||||
}
|
||||
func (clh *cloudHypervisor) Cleanup(ctx context.Context) error {
|
||||
clh.Logger().WithField("function", "Cleanup").Info("Cleanup")
|
||||
return nil
|
||||
|
@ -1183,6 +1183,9 @@ func (fc *firecracker) ResizeMemory(ctx context.Context, reqMemMB uint32, memory
|
||||
func (fc *firecracker) ResizeVCPUs(ctx context.Context, reqVCPUs uint32) (currentVCPUs uint32, newVCPUs uint32, err error) {
|
||||
return 0, 0, nil
|
||||
}
|
||||
func (fc *firecracker) ResizeBlock(ctx context.Context, deviceID string, size uint64) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// This is used to apply cgroup information on the host.
|
||||
//
|
||||
|
@ -1124,6 +1124,7 @@ type Hypervisor interface {
|
||||
HotplugRemoveDevice(ctx context.Context, devInfo interface{}, devType DeviceType) (interface{}, error)
|
||||
ResizeMemory(ctx context.Context, memMB uint32, memoryBlockSizeMB uint32, probe bool) (uint32, MemoryDevice, error)
|
||||
ResizeVCPUs(ctx context.Context, vcpus uint32) (uint32, uint32, error)
|
||||
ResizeBlock(ctx context.Context, deviceID string, size uint64) error
|
||||
GetTotalMemoryMB(ctx context.Context) uint32
|
||||
GetVMConsole(ctx context.Context, sandboxID string) (string, string, error)
|
||||
Disconnect(ctx context.Context)
|
||||
|
@ -104,7 +104,9 @@ func (m *mockHypervisor) ResizeMemory(ctx context.Context, memMB uint32, memoryS
|
||||
func (m *mockHypervisor) ResizeVCPUs(ctx context.Context, cpus uint32) (uint32, uint32, error) {
|
||||
return 0, 0, nil
|
||||
}
|
||||
|
||||
func (m *mockHypervisor) ResizeBlock(ctx context.Context, deviceID string, size uint64) error {
|
||||
return nil
|
||||
}
|
||||
func (m *mockHypervisor) GetTotalMemoryMB(ctx context.Context) uint32 {
|
||||
return m.config.MemorySize
|
||||
}
|
||||
|
@ -2573,6 +2573,10 @@ func (q *qemu) ResizeMemory(ctx context.Context, reqMemMB uint32, memoryBlockSiz
|
||||
return currentMemory, addMemDevice, nil
|
||||
}
|
||||
|
||||
func (q *qemu) ResizeBlock(ctx context.Context, deviceID string, size uint64) error {
|
||||
return q.qmpMonitorCh.qmp.ExecuteBlockdevResize(ctx, deviceID, size)
|
||||
}
|
||||
|
||||
// genericAppendBridges appends to devices the given bridges
|
||||
// nolint: unused, deadcode
|
||||
func genericAppendBridges(devices []govmmQemu.Device, bridges []types.Bridge, machineType string) []govmmQemu.Device {
|
||||
|
@ -228,7 +228,9 @@ func (rh *remoteHypervisor) GetTotalMemoryMB(ctx context.Context) uint32 {
|
||||
func (rh *remoteHypervisor) ResizeVCPUs(ctx context.Context, vcpus uint32) (uint32, uint32, error) {
|
||||
return vcpus, vcpus, nil
|
||||
}
|
||||
|
||||
func (rh *remoteHypervisor) ResizeBlock(ctx context.Context, deviceID string, size uint64) error {
|
||||
return nil
|
||||
}
|
||||
func (rh *remoteHypervisor) GetVMConsole(ctx context.Context, sandboxID string) (string, string, error) {
|
||||
return "", "", notImplemented("GetVMConsole")
|
||||
}
|
||||
|
@ -2665,7 +2665,7 @@ func (s *Sandbox) SetPolicy(ctx context.Context, policy string) error {
|
||||
|
||||
// GuestVolumeStats return the filesystem stat of a given volume in the guest.
|
||||
func (s *Sandbox) GuestVolumeStats(ctx context.Context, volumePath string) ([]byte, error) {
|
||||
guestMountPath, err := s.guestMountPath(volumePath)
|
||||
_, guestMountPath, err := s.getMountDetails(volumePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -2674,30 +2674,47 @@ func (s *Sandbox) GuestVolumeStats(ctx context.Context, volumePath string) ([]by
|
||||
|
||||
// ResizeGuestVolume resizes a volume in the guest.
|
||||
func (s *Sandbox) ResizeGuestVolume(ctx context.Context, volumePath string, size uint64) error {
|
||||
// TODO: https://github.com/kata-containers/kata-containers/issues/3694.
|
||||
guestMountPath, err := s.guestMountPath(volumePath)
|
||||
|
||||
id, guestMountPath, err := s.getMountDetails(volumePath)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
device := s.devManager.GetDeviceByID(id)
|
||||
if device == nil {
|
||||
s.Logger().WithField("device", id).Error("failed to find device by id")
|
||||
return fmt.Errorf("failed to find device by id (id=%s)", id)
|
||||
}
|
||||
|
||||
d, ok := device.GetDeviceInfo().(*config.BlockDrive)
|
||||
if !ok || d == nil {
|
||||
s.Logger().WithField("device", device).Error("device is not a block drive or is nil")
|
||||
return fmt.Errorf("device is not a block drive or is nil")
|
||||
}
|
||||
if err := s.hypervisor.ResizeBlock(ctx, d.ID, size); err != nil {
|
||||
s.Logger().WithError(err).Error("Failed to resize block device in hypervisor")
|
||||
return err
|
||||
}
|
||||
|
||||
return s.agent.resizeGuestVolume(ctx, guestMountPath, size)
|
||||
}
|
||||
|
||||
func (s *Sandbox) guestMountPath(volumePath string) (string, error) {
|
||||
func (s *Sandbox) getMountDetails(volumePath string) (string, string, error) {
|
||||
// verify the device even exists
|
||||
if _, err := os.Stat(volumePath); err != nil {
|
||||
s.Logger().WithError(err).WithField("volume", volumePath).Error("Cannot get stats for volume that doesn't exist")
|
||||
return "", err
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
// verify that we have a mount in this sandbox who's source maps to this
|
||||
for _, c := range s.containers {
|
||||
for _, m := range c.mounts {
|
||||
if volumePath == m.Source {
|
||||
return m.GuestDeviceMount, nil
|
||||
return m.BlockDeviceID, m.GuestDeviceMount, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("mount %s not found in sandbox", volumePath)
|
||||
return "", "", fmt.Errorf("mount %s not found in sandbox", volumePath)
|
||||
}
|
||||
|
||||
// getSandboxCPUSet returns the union of each of the sandbox's containers' CPU sets'
|
||||
|
@ -1169,7 +1169,9 @@ func (s *stratovirt) ResizeMemory(ctx context.Context, reqMemMB uint32, memoryBl
|
||||
func (s *stratovirt) ResizeVCPUs(ctx context.Context, reqVCPUs uint32) (currentVCPUs uint32, newVCPUs uint32, err error) {
|
||||
return 0, 0, nil
|
||||
}
|
||||
|
||||
func (s *stratovirt) ResizeBlock(ctx context.Context, deviceID string, size uint64) error {
|
||||
return nil
|
||||
}
|
||||
func (s *stratovirt) GetVMConsole(ctx context.Context, id string) (string, string, error) {
|
||||
span, _ := katatrace.Trace(ctx, s.Logger(), "GetVMConsole", stratovirtTracingTags, map[string]string{"sandbox_id": s.id})
|
||||
defer span.End()
|
||||
|
@ -29,6 +29,7 @@ default ReadStreamRequest := false
|
||||
default RemoveContainerRequest := true
|
||||
default RemoveStaleVirtiofsShareMountsRequest := true
|
||||
default ReseedRandomDevRequest := false
|
||||
default ResizeVolumeRequest := false
|
||||
default ResumeContainerRequest := false
|
||||
default SetGuestDateTimeRequest := false
|
||||
default SetPolicyRequest := false
|
||||
|
Loading…
Reference in New Issue
Block a user