Skip to content

Commit 87541cb

Browse files
authored
Agent: Add and implement writeFile (#259)
This change adds in a new rpc that we probably should swap to for the underlying implementation of a couple rpcs we currently have. This new rpc simply writes to an existing or new file some data. This is useful for guest (and container) setup for things like /etc/hosts, /etc/resolv.conf, writing to one-off cgroup files and so on. Currently I've just implemented subtree_control toggling for the root cg in standardSetup with this new change, but in the future I'd like to swap the implementations of our /etc/hosts and /etc/resolv.conf logic with this.
1 parent 7b00f39 commit 87541cb

File tree

6 files changed

+380
-1
lines changed

6 files changed

+380
-1
lines changed

Sources/Containerization/Agent/Vminitd.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,29 @@ extension Vminitd: VirtualMachineAgent {
6464
for mount in mounts {
6565
try await self.mount(mount)
6666
}
67+
68+
// Setup root cg subtree_control.
69+
let data = "+memory +pids +io +cpu +cpuset".data(using: .utf8)!
70+
try await writeFile(
71+
path: "/sys/fs/cgroup/cgroup.subtree_control",
72+
data: data,
73+
flags: .init(),
74+
mode: 0
75+
)
76+
}
77+
78+
public func writeFile(path: String, data: Data, flags: WriteFileFlags, mode: UInt32) async throws {
79+
_ = try await client.writeFile(
80+
.with {
81+
$0.path = path
82+
$0.mode = mode
83+
$0.data = data
84+
$0.flags = .with {
85+
$0.append = flags.append
86+
$0.createIfMissing = flags.create
87+
$0.createParentDirs = flags.createParentDirectories
88+
}
89+
})
6790
}
6891

6992
/// Mount a filesystem in the sandbox's environment.

Sources/Containerization/SandboxContext/SandboxContext.grpc.swift

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@ public protocol Com_Apple_Containerization_Sandbox_V3_SandboxContextClientProtoc
7474
callOptions: CallOptions?
7575
) -> UnaryCall<Com_Apple_Containerization_Sandbox_V3_SetupEmulatorRequest, Com_Apple_Containerization_Sandbox_V3_SetupEmulatorResponse>
7676

77+
func writeFile(
78+
_ request: Com_Apple_Containerization_Sandbox_V3_WriteFileRequest,
79+
callOptions: CallOptions?
80+
) -> UnaryCall<Com_Apple_Containerization_Sandbox_V3_WriteFileRequest, Com_Apple_Containerization_Sandbox_V3_WriteFileResponse>
81+
7782
func createProcess(
7883
_ request: Com_Apple_Containerization_Sandbox_V3_CreateProcessRequest,
7984
callOptions: CallOptions?
@@ -309,6 +314,24 @@ extension Com_Apple_Containerization_Sandbox_V3_SandboxContextClientProtocol {
309314
)
310315
}
311316

317+
/// Write data to an existing or new file.
318+
///
319+
/// - Parameters:
320+
/// - request: Request to send to WriteFile.
321+
/// - callOptions: Call options.
322+
/// - Returns: A `UnaryCall` with futures for the metadata, status and response.
323+
public func writeFile(
324+
_ request: Com_Apple_Containerization_Sandbox_V3_WriteFileRequest,
325+
callOptions: CallOptions? = nil
326+
) -> UnaryCall<Com_Apple_Containerization_Sandbox_V3_WriteFileRequest, Com_Apple_Containerization_Sandbox_V3_WriteFileResponse> {
327+
return self.makeUnaryCall(
328+
path: Com_Apple_Containerization_Sandbox_V3_SandboxContextClientMetadata.Methods.writeFile.path,
329+
request: request,
330+
callOptions: callOptions ?? self.defaultCallOptions,
331+
interceptors: self.interceptors?.makeWriteFileInterceptors() ?? []
332+
)
333+
}
334+
312335
/// Create a new process inside the container.
313336
///
314337
/// - Parameters:
@@ -720,6 +743,11 @@ public protocol Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncClientP
720743
callOptions: CallOptions?
721744
) -> GRPCAsyncUnaryCall<Com_Apple_Containerization_Sandbox_V3_SetupEmulatorRequest, Com_Apple_Containerization_Sandbox_V3_SetupEmulatorResponse>
722745

746+
func makeWriteFileCall(
747+
_ request: Com_Apple_Containerization_Sandbox_V3_WriteFileRequest,
748+
callOptions: CallOptions?
749+
) -> GRPCAsyncUnaryCall<Com_Apple_Containerization_Sandbox_V3_WriteFileRequest, Com_Apple_Containerization_Sandbox_V3_WriteFileResponse>
750+
723751
func makeCreateProcessCall(
724752
_ request: Com_Apple_Containerization_Sandbox_V3_CreateProcessRequest,
725753
callOptions: CallOptions?
@@ -912,6 +940,18 @@ extension Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncClientProtoco
912940
)
913941
}
914942

943+
public func makeWriteFileCall(
944+
_ request: Com_Apple_Containerization_Sandbox_V3_WriteFileRequest,
945+
callOptions: CallOptions? = nil
946+
) -> GRPCAsyncUnaryCall<Com_Apple_Containerization_Sandbox_V3_WriteFileRequest, Com_Apple_Containerization_Sandbox_V3_WriteFileResponse> {
947+
return self.makeAsyncUnaryCall(
948+
path: Com_Apple_Containerization_Sandbox_V3_SandboxContextClientMetadata.Methods.writeFile.path,
949+
request: request,
950+
callOptions: callOptions ?? self.defaultCallOptions,
951+
interceptors: self.interceptors?.makeWriteFileInterceptors() ?? []
952+
)
953+
}
954+
915955
public func makeCreateProcessCall(
916956
_ request: Com_Apple_Containerization_Sandbox_V3_CreateProcessRequest,
917957
callOptions: CallOptions? = nil
@@ -1215,6 +1255,18 @@ extension Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncClientProtoco
12151255
)
12161256
}
12171257

1258+
public func writeFile(
1259+
_ request: Com_Apple_Containerization_Sandbox_V3_WriteFileRequest,
1260+
callOptions: CallOptions? = nil
1261+
) async throws -> Com_Apple_Containerization_Sandbox_V3_WriteFileResponse {
1262+
return try await self.performAsyncUnaryCall(
1263+
path: Com_Apple_Containerization_Sandbox_V3_SandboxContextClientMetadata.Methods.writeFile.path,
1264+
request: request,
1265+
callOptions: callOptions ?? self.defaultCallOptions,
1266+
interceptors: self.interceptors?.makeWriteFileInterceptors() ?? []
1267+
)
1268+
}
1269+
12181270
public func createProcess(
12191271
_ request: Com_Apple_Containerization_Sandbox_V3_CreateProcessRequest,
12201272
callOptions: CallOptions? = nil
@@ -1463,6 +1515,9 @@ public protocol Com_Apple_Containerization_Sandbox_V3_SandboxContextClientInterc
14631515
/// - Returns: Interceptors to use when invoking 'setupEmulator'.
14641516
func makeSetupEmulatorInterceptors() -> [ClientInterceptor<Com_Apple_Containerization_Sandbox_V3_SetupEmulatorRequest, Com_Apple_Containerization_Sandbox_V3_SetupEmulatorResponse>]
14651517

1518+
/// - Returns: Interceptors to use when invoking 'writeFile'.
1519+
func makeWriteFileInterceptors() -> [ClientInterceptor<Com_Apple_Containerization_Sandbox_V3_WriteFileRequest, Com_Apple_Containerization_Sandbox_V3_WriteFileResponse>]
1520+
14661521
/// - Returns: Interceptors to use when invoking 'createProcess'.
14671522
func makeCreateProcessInterceptors() -> [ClientInterceptor<Com_Apple_Containerization_Sandbox_V3_CreateProcessRequest, Com_Apple_Containerization_Sandbox_V3_CreateProcessResponse>]
14681523

@@ -1528,6 +1583,7 @@ public enum Com_Apple_Containerization_Sandbox_V3_SandboxContextClientMetadata {
15281583
Com_Apple_Containerization_Sandbox_V3_SandboxContextClientMetadata.Methods.sysctl,
15291584
Com_Apple_Containerization_Sandbox_V3_SandboxContextClientMetadata.Methods.setTime,
15301585
Com_Apple_Containerization_Sandbox_V3_SandboxContextClientMetadata.Methods.setupEmulator,
1586+
Com_Apple_Containerization_Sandbox_V3_SandboxContextClientMetadata.Methods.writeFile,
15311587
Com_Apple_Containerization_Sandbox_V3_SandboxContextClientMetadata.Methods.createProcess,
15321588
Com_Apple_Containerization_Sandbox_V3_SandboxContextClientMetadata.Methods.deleteProcess,
15331589
Com_Apple_Containerization_Sandbox_V3_SandboxContextClientMetadata.Methods.startProcess,
@@ -1597,6 +1653,12 @@ public enum Com_Apple_Containerization_Sandbox_V3_SandboxContextClientMetadata {
15971653
type: GRPCCallType.unary
15981654
)
15991655

1656+
public static let writeFile = GRPCMethodDescriptor(
1657+
name: "WriteFile",
1658+
path: "/com.apple.containerization.sandbox.v3.SandboxContext/WriteFile",
1659+
type: GRPCCallType.unary
1660+
)
1661+
16001662
public static let createProcess = GRPCMethodDescriptor(
16011663
name: "CreateProcess",
16021664
path: "/com.apple.containerization.sandbox.v3.SandboxContext/CreateProcess",
@@ -1731,6 +1793,9 @@ public protocol Com_Apple_Containerization_Sandbox_V3_SandboxContextProvider: Ca
17311793
/// Set up an emulator in the guest for a specific binary format.
17321794
func setupEmulator(request: Com_Apple_Containerization_Sandbox_V3_SetupEmulatorRequest, context: StatusOnlyCallContext) -> EventLoopFuture<Com_Apple_Containerization_Sandbox_V3_SetupEmulatorResponse>
17331795

1796+
/// Write data to an existing or new file.
1797+
func writeFile(request: Com_Apple_Containerization_Sandbox_V3_WriteFileRequest, context: StatusOnlyCallContext) -> EventLoopFuture<Com_Apple_Containerization_Sandbox_V3_WriteFileResponse>
1798+
17341799
/// Create a new process inside the container.
17351800
func createProcess(request: Com_Apple_Containerization_Sandbox_V3_CreateProcessRequest, context: StatusOnlyCallContext) -> EventLoopFuture<Com_Apple_Containerization_Sandbox_V3_CreateProcessResponse>
17361801

@@ -1868,6 +1933,15 @@ extension Com_Apple_Containerization_Sandbox_V3_SandboxContextProvider {
18681933
userFunction: self.setupEmulator(request:context:)
18691934
)
18701935

1936+
case "WriteFile":
1937+
return UnaryServerHandler(
1938+
context: context,
1939+
requestDeserializer: ProtobufDeserializer<Com_Apple_Containerization_Sandbox_V3_WriteFileRequest>(),
1940+
responseSerializer: ProtobufSerializer<Com_Apple_Containerization_Sandbox_V3_WriteFileResponse>(),
1941+
interceptors: self.interceptors?.makeWriteFileInterceptors() ?? [],
1942+
userFunction: self.writeFile(request:context:)
1943+
)
1944+
18711945
case "CreateProcess":
18721946
return UnaryServerHandler(
18731947
context: context,
@@ -2083,6 +2157,12 @@ public protocol Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvide
20832157
context: GRPCAsyncServerCallContext
20842158
) async throws -> Com_Apple_Containerization_Sandbox_V3_SetupEmulatorResponse
20852159

2160+
/// Write data to an existing or new file.
2161+
func writeFile(
2162+
request: Com_Apple_Containerization_Sandbox_V3_WriteFileRequest,
2163+
context: GRPCAsyncServerCallContext
2164+
) async throws -> Com_Apple_Containerization_Sandbox_V3_WriteFileResponse
2165+
20862166
/// Create a new process inside the container.
20872167
func createProcess(
20882168
request: Com_Apple_Containerization_Sandbox_V3_CreateProcessRequest,
@@ -2278,6 +2358,15 @@ extension Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvider {
22782358
wrapping: { try await self.setupEmulator(request: $0, context: $1) }
22792359
)
22802360

2361+
case "WriteFile":
2362+
return GRPCAsyncServerHandler(
2363+
context: context,
2364+
requestDeserializer: ProtobufDeserializer<Com_Apple_Containerization_Sandbox_V3_WriteFileRequest>(),
2365+
responseSerializer: ProtobufSerializer<Com_Apple_Containerization_Sandbox_V3_WriteFileResponse>(),
2366+
interceptors: self.interceptors?.makeWriteFileInterceptors() ?? [],
2367+
wrapping: { try await self.writeFile(request: $0, context: $1) }
2368+
)
2369+
22812370
case "CreateProcess":
22822371
return GRPCAsyncServerHandler(
22832372
context: context,
@@ -2471,6 +2560,10 @@ public protocol Com_Apple_Containerization_Sandbox_V3_SandboxContextServerInterc
24712560
/// Defaults to calling `self.makeInterceptors()`.
24722561
func makeSetupEmulatorInterceptors() -> [ServerInterceptor<Com_Apple_Containerization_Sandbox_V3_SetupEmulatorRequest, Com_Apple_Containerization_Sandbox_V3_SetupEmulatorResponse>]
24732562

2563+
/// - Returns: Interceptors to use when handling 'writeFile'.
2564+
/// Defaults to calling `self.makeInterceptors()`.
2565+
func makeWriteFileInterceptors() -> [ServerInterceptor<Com_Apple_Containerization_Sandbox_V3_WriteFileRequest, Com_Apple_Containerization_Sandbox_V3_WriteFileResponse>]
2566+
24742567
/// - Returns: Interceptors to use when handling 'createProcess'.
24752568
/// Defaults to calling `self.makeInterceptors()`.
24762569
func makeCreateProcessInterceptors() -> [ServerInterceptor<Com_Apple_Containerization_Sandbox_V3_CreateProcessRequest, Com_Apple_Containerization_Sandbox_V3_CreateProcessResponse>]
@@ -2553,6 +2646,7 @@ public enum Com_Apple_Containerization_Sandbox_V3_SandboxContextServerMetadata {
25532646
Com_Apple_Containerization_Sandbox_V3_SandboxContextServerMetadata.Methods.sysctl,
25542647
Com_Apple_Containerization_Sandbox_V3_SandboxContextServerMetadata.Methods.setTime,
25552648
Com_Apple_Containerization_Sandbox_V3_SandboxContextServerMetadata.Methods.setupEmulator,
2649+
Com_Apple_Containerization_Sandbox_V3_SandboxContextServerMetadata.Methods.writeFile,
25562650
Com_Apple_Containerization_Sandbox_V3_SandboxContextServerMetadata.Methods.createProcess,
25572651
Com_Apple_Containerization_Sandbox_V3_SandboxContextServerMetadata.Methods.deleteProcess,
25582652
Com_Apple_Containerization_Sandbox_V3_SandboxContextServerMetadata.Methods.startProcess,
@@ -2622,6 +2716,12 @@ public enum Com_Apple_Containerization_Sandbox_V3_SandboxContextServerMetadata {
26222716
type: GRPCCallType.unary
26232717
)
26242718

2719+
public static let writeFile = GRPCMethodDescriptor(
2720+
name: "WriteFile",
2721+
path: "/com.apple.containerization.sandbox.v3.SandboxContext/WriteFile",
2722+
type: GRPCCallType.unary
2723+
)
2724+
26252725
public static let createProcess = GRPCMethodDescriptor(
26262726
name: "CreateProcess",
26272727
path: "/com.apple.containerization.sandbox.v3.SandboxContext/CreateProcess",

0 commit comments

Comments
 (0)