mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-08-17 15:38:00 +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::io::{BufRead, BufReader};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use std::process::Command;
|
||||||
use anyhow::{anyhow, Context, Result};
|
use anyhow::{anyhow, Context, Result};
|
||||||
use kata_sys_util::mount::{get_linux_mount_info, parse_mount_options};
|
use kata_sys_util::mount::{get_linux_mount_info, parse_mount_options};
|
||||||
use nix::mount::MsFlags;
|
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]
|
#[instrument]
|
||||||
pub fn baremount(
|
pub fn baremount(
|
||||||
source: &Path,
|
source: &Path,
|
||||||
|
@ -7,7 +7,7 @@ use std::fmt;
|
|||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::str::FromStr;
|
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
|
// The PCI spec reserves 5 bits (0..31) for slot number (a.k.a. device
|
||||||
// number)
|
// number)
|
||||||
@ -18,11 +18,21 @@ const SLOT_MAX: u8 = (1 << SLOT_BITS) - 1;
|
|||||||
const FUNCTION_BITS: u8 = 3;
|
const FUNCTION_BITS: u8 = 3;
|
||||||
const FUNCTION_MAX: u8 = (1 << FUNCTION_BITS) - 1;
|
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
|
// Represents a PCI function's slot (a.k.a. device) and function
|
||||||
// numbers, giving its location on a single logical bus
|
// numbers, giving its location on a single logical bus
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct SlotFn(u8);
|
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 {
|
impl SlotFn {
|
||||||
pub fn new<T, U>(ss: T, f: U) -> anyhow::Result<Self>
|
pub fn new<T, U>(ss: T, f: U) -> anyhow::Result<Self>
|
||||||
where
|
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::device::{add_devices, handle_cdi_devices, update_env_pci};
|
||||||
use crate::features::get_build_features;
|
use crate::features::get_build_features;
|
||||||
use crate::metrics::get_metrics;
|
use crate::metrics::get_metrics;
|
||||||
use crate::mount::baremount;
|
use crate::mount::{baremount, resize_file_system};
|
||||||
use crate::namespace::{NSTYPEIPC, NSTYPEPID, NSTYPEUTS};
|
use crate::namespace::{NSTYPEIPC, NSTYPEPID, NSTYPEUTS};
|
||||||
use crate::network::setup_guest_dns;
|
use crate::network::setup_guest_dns;
|
||||||
use crate::passfd_io;
|
use crate::passfd_io;
|
||||||
@ -825,7 +825,17 @@ impl agent_ttrpc::AgentService for AgentService {
|
|||||||
|
|
||||||
Ok(Empty::new())
|
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(
|
async fn stats_container(
|
||||||
&self,
|
&self,
|
||||||
ctx: &TtrpcContext,
|
ctx: &TtrpcContext,
|
||||||
|
@ -826,10 +826,18 @@ func (q *QMP) ExecuteBlockdevAddWithCache(ctx context.Context, blockDevice *Bloc
|
|||||||
"direct": direct,
|
"direct": direct,
|
||||||
"no-flush": noFlush,
|
"no-flush": noFlush,
|
||||||
}
|
}
|
||||||
|
|
||||||
return q.executeCommand(ctx, "blockdev-add", blockdevArgs, nil)
|
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
|
// ExecuteBlockdevAddWithDriverCache has three one parameter driver
|
||||||
// than ExecuteBlockdevAddWithCache.
|
// than ExecuteBlockdevAddWithCache.
|
||||||
// Parameter driver can set the driver of block device.
|
// 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
|
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 {
|
func (clh *cloudHypervisor) Cleanup(ctx context.Context) error {
|
||||||
clh.Logger().WithField("function", "Cleanup").Info("Cleanup")
|
clh.Logger().WithField("function", "Cleanup").Info("Cleanup")
|
||||||
return nil
|
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) {
|
func (fc *firecracker) ResizeVCPUs(ctx context.Context, reqVCPUs uint32) (currentVCPUs uint32, newVCPUs uint32, err error) {
|
||||||
return 0, 0, nil
|
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.
|
// 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)
|
HotplugRemoveDevice(ctx context.Context, devInfo interface{}, devType DeviceType) (interface{}, error)
|
||||||
ResizeMemory(ctx context.Context, memMB uint32, memoryBlockSizeMB uint32, probe bool) (uint32, MemoryDevice, error)
|
ResizeMemory(ctx context.Context, memMB uint32, memoryBlockSizeMB uint32, probe bool) (uint32, MemoryDevice, error)
|
||||||
ResizeVCPUs(ctx context.Context, vcpus uint32) (uint32, uint32, error)
|
ResizeVCPUs(ctx context.Context, vcpus uint32) (uint32, uint32, error)
|
||||||
|
ResizeBlock(ctx context.Context, deviceID string, size uint64) error
|
||||||
GetTotalMemoryMB(ctx context.Context) uint32
|
GetTotalMemoryMB(ctx context.Context) uint32
|
||||||
GetVMConsole(ctx context.Context, sandboxID string) (string, string, error)
|
GetVMConsole(ctx context.Context, sandboxID string) (string, string, error)
|
||||||
Disconnect(ctx context.Context)
|
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) {
|
func (m *mockHypervisor) ResizeVCPUs(ctx context.Context, cpus uint32) (uint32, uint32, error) {
|
||||||
return 0, 0, nil
|
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 {
|
func (m *mockHypervisor) GetTotalMemoryMB(ctx context.Context) uint32 {
|
||||||
return m.config.MemorySize
|
return m.config.MemorySize
|
||||||
}
|
}
|
||||||
|
@ -2573,6 +2573,10 @@ func (q *qemu) ResizeMemory(ctx context.Context, reqMemMB uint32, memoryBlockSiz
|
|||||||
return currentMemory, addMemDevice, nil
|
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
|
// genericAppendBridges appends to devices the given bridges
|
||||||
// nolint: unused, deadcode
|
// nolint: unused, deadcode
|
||||||
func genericAppendBridges(devices []govmmQemu.Device, bridges []types.Bridge, machineType string) []govmmQemu.Device {
|
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) {
|
func (rh *remoteHypervisor) ResizeVCPUs(ctx context.Context, vcpus uint32) (uint32, uint32, error) {
|
||||||
return vcpus, vcpus, nil
|
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) {
|
func (rh *remoteHypervisor) GetVMConsole(ctx context.Context, sandboxID string) (string, string, error) {
|
||||||
return "", "", notImplemented("GetVMConsole")
|
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.
|
// GuestVolumeStats return the filesystem stat of a given volume in the guest.
|
||||||
func (s *Sandbox) GuestVolumeStats(ctx context.Context, volumePath string) ([]byte, error) {
|
func (s *Sandbox) GuestVolumeStats(ctx context.Context, volumePath string) ([]byte, error) {
|
||||||
guestMountPath, err := s.guestMountPath(volumePath)
|
_, guestMountPath, err := s.getMountDetails(volumePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -2674,30 +2674,47 @@ func (s *Sandbox) GuestVolumeStats(ctx context.Context, volumePath string) ([]by
|
|||||||
|
|
||||||
// ResizeGuestVolume resizes a volume in the guest.
|
// ResizeGuestVolume resizes a volume in the guest.
|
||||||
func (s *Sandbox) ResizeGuestVolume(ctx context.Context, volumePath string, size uint64) error {
|
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 {
|
if err != nil {
|
||||||
return err
|
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)
|
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
|
// verify the device even exists
|
||||||
if _, err := os.Stat(volumePath); err != nil {
|
if _, err := os.Stat(volumePath); err != nil {
|
||||||
s.Logger().WithError(err).WithField("volume", volumePath).Error("Cannot get stats for volume that doesn't exist")
|
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
|
// verify that we have a mount in this sandbox who's source maps to this
|
||||||
for _, c := range s.containers {
|
for _, c := range s.containers {
|
||||||
for _, m := range c.mounts {
|
for _, m := range c.mounts {
|
||||||
if volumePath == m.Source {
|
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'
|
// 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) {
|
func (s *stratovirt) ResizeVCPUs(ctx context.Context, reqVCPUs uint32) (currentVCPUs uint32, newVCPUs uint32, err error) {
|
||||||
return 0, 0, nil
|
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) {
|
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})
|
span, _ := katatrace.Trace(ctx, s.Logger(), "GetVMConsole", stratovirtTracingTags, map[string]string{"sandbox_id": s.id})
|
||||||
defer span.End()
|
defer span.End()
|
||||||
|
@ -29,6 +29,7 @@ default ReadStreamRequest := false
|
|||||||
default RemoveContainerRequest := true
|
default RemoveContainerRequest := true
|
||||||
default RemoveStaleVirtiofsShareMountsRequest := true
|
default RemoveStaleVirtiofsShareMountsRequest := true
|
||||||
default ReseedRandomDevRequest := false
|
default ReseedRandomDevRequest := false
|
||||||
|
default ResizeVolumeRequest := false
|
||||||
default ResumeContainerRequest := false
|
default ResumeContainerRequest := false
|
||||||
default SetGuestDateTimeRequest := false
|
default SetGuestDateTimeRequest := false
|
||||||
default SetPolicyRequest := false
|
default SetPolicyRequest := false
|
||||||
|
Loading…
Reference in New Issue
Block a user