This repository has been archived by the owner on May 12, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 373
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
The types package holds all shared virtcontainers types. With the separation of the virtcontainers code into separate packages, we need a types one to not create circular dependencies. This package holds sandbox related types and structures for now. It will grow as virtcontainers code is moved into their own internal packages. Signed-off-by: Samuel Ortiz <[email protected]>
- Loading branch information
Samuel Ortiz
committed
Jan 8, 2019
1 parent
3ab7d07
commit 701afe9
Showing
1 changed file
with
275 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,275 @@ | ||
// Copyright (c) 2018 Intel Corporation | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
|
||
package types | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
) | ||
|
||
// stateString is a string representing a sandbox state. | ||
type stateString string | ||
|
||
const ( | ||
// StateReady represents a sandbox/container that's ready to be run | ||
StateReady stateString = "ready" | ||
|
||
// StateRunning represents a sandbox/container that's currently running. | ||
StateRunning stateString = "running" | ||
|
||
// StatePaused represents a sandbox/container that has been paused. | ||
StatePaused stateString = "paused" | ||
|
||
// StateStopped represents a sandbox/container that has been stopped. | ||
StateStopped stateString = "stopped" | ||
) | ||
|
||
// State is a sandbox state structure. | ||
type State struct { | ||
State stateString `json:"state"` | ||
|
||
BlockDeviceID string | ||
// Index of the block device passed to hypervisor. | ||
BlockIndex int `json:"blockIndex"` | ||
|
||
// File system of the rootfs incase it is block device | ||
Fstype string `json:"fstype"` | ||
|
||
// Pid is the process id of the sandbox container which is the first | ||
// container to be started. | ||
Pid int `json:"pid"` | ||
|
||
// GuestMemoryBlockSizeMB is the size of memory block of guestos | ||
GuestMemoryBlockSizeMB uint32 `json:"guestMemoryBlockSize"` | ||
} | ||
|
||
// valid checks that the sandbox state is valid. | ||
func (state *State) valid() bool { | ||
for _, validState := range []stateString{StateReady, StateRunning, StatePaused, StateStopped} { | ||
if state.State == validState { | ||
return true | ||
} | ||
} | ||
|
||
return false | ||
} | ||
|
||
// validTransition returns an error if we want to move to | ||
// an unreachable state. | ||
func (state *State) validTransition(oldState stateString, newState stateString) error { | ||
if state.State != oldState { | ||
return fmt.Errorf("Invalid state %s (Expecting %s)", state.State, oldState) | ||
} | ||
|
||
switch state.State { | ||
case StateReady: | ||
if newState == StateRunning || newState == StateStopped { | ||
return nil | ||
} | ||
|
||
case StateRunning: | ||
if newState == StatePaused || newState == StateStopped { | ||
return nil | ||
} | ||
|
||
case StatePaused: | ||
if newState == StateRunning || newState == StateStopped { | ||
return nil | ||
} | ||
|
||
case StateStopped: | ||
if newState == StateRunning { | ||
return nil | ||
} | ||
} | ||
|
||
return fmt.Errorf("Can not move from %s to %s", | ||
state.State, newState) | ||
} | ||
|
||
// Volume is a shared volume between the host and the VM, | ||
// defined by its mount tag and its host path. | ||
type Volume struct { | ||
// MountTag is a label used as a hint to the guest. | ||
MountTag string | ||
|
||
// HostPath is the host filesystem path for this volume. | ||
HostPath string | ||
} | ||
|
||
// Volumes is a Volume list. | ||
type Volumes []Volume | ||
|
||
// Set assigns volume values from string to a Volume. | ||
func (v *Volumes) Set(volStr string) error { | ||
if volStr == "" { | ||
return fmt.Errorf("volStr cannot be empty") | ||
} | ||
|
||
volSlice := strings.Split(volStr, " ") | ||
const expectedVolLen = 2 | ||
const volDelimiter = ":" | ||
|
||
for _, vol := range volSlice { | ||
volArgs := strings.Split(vol, volDelimiter) | ||
|
||
if len(volArgs) != expectedVolLen { | ||
return fmt.Errorf("Wrong string format: %s, expecting only %v parameters separated with %q", | ||
vol, expectedVolLen, volDelimiter) | ||
} | ||
|
||
if volArgs[0] == "" || volArgs[1] == "" { | ||
return fmt.Errorf("Volume parameters cannot be empty") | ||
} | ||
|
||
volume := Volume{ | ||
MountTag: volArgs[0], | ||
HostPath: volArgs[1], | ||
} | ||
|
||
*v = append(*v, volume) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// String converts a Volume to a string. | ||
func (v *Volumes) String() string { | ||
var volSlice []string | ||
|
||
for _, volume := range *v { | ||
volSlice = append(volSlice, fmt.Sprintf("%s:%s", volume.MountTag, volume.HostPath)) | ||
} | ||
|
||
return strings.Join(volSlice, " ") | ||
} | ||
|
||
// Socket defines a socket to communicate between | ||
// the host and any process inside the VM. | ||
type Socket struct { | ||
DeviceID string | ||
ID string | ||
HostPath string | ||
Name string | ||
} | ||
|
||
// Sockets is a Socket list. | ||
type Sockets []Socket | ||
|
||
// Set assigns socket values from string to a Socket. | ||
func (s *Sockets) Set(sockStr string) error { | ||
if sockStr == "" { | ||
return fmt.Errorf("sockStr cannot be empty") | ||
} | ||
|
||
sockSlice := strings.Split(sockStr, " ") | ||
const expectedSockCount = 4 | ||
const sockDelimiter = ":" | ||
|
||
for _, sock := range sockSlice { | ||
sockArgs := strings.Split(sock, sockDelimiter) | ||
|
||
if len(sockArgs) != expectedSockCount { | ||
return fmt.Errorf("Wrong string format: %s, expecting only %v parameters separated with %q", sock, expectedSockCount, sockDelimiter) | ||
} | ||
|
||
for _, a := range sockArgs { | ||
if a == "" { | ||
return fmt.Errorf("Socket parameters cannot be empty") | ||
} | ||
} | ||
|
||
socket := Socket{ | ||
DeviceID: sockArgs[0], | ||
ID: sockArgs[1], | ||
HostPath: sockArgs[2], | ||
Name: sockArgs[3], | ||
} | ||
|
||
*s = append(*s, socket) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// String converts a Socket to a string. | ||
func (s *Sockets) String() string { | ||
var sockSlice []string | ||
|
||
for _, sock := range *s { | ||
sockSlice = append(sockSlice, fmt.Sprintf("%s:%s:%s:%s", sock.DeviceID, sock.ID, sock.HostPath, sock.Name)) | ||
} | ||
|
||
return strings.Join(sockSlice, " ") | ||
} | ||
|
||
// EnvVar is a key/value structure representing a command | ||
// environment variable. | ||
type EnvVar struct { | ||
Var string | ||
Value string | ||
} | ||
|
||
// LinuxCapabilities specify the capabilities to keep when executing | ||
// the process inside the container. | ||
type LinuxCapabilities struct { | ||
// Bounding is the set of capabilities checked by the kernel. | ||
Bounding []string | ||
// Effective is the set of capabilities checked by the kernel. | ||
Effective []string | ||
// Inheritable is the capabilities preserved across execve. | ||
Inheritable []string | ||
// Permitted is the limiting superset for effective capabilities. | ||
Permitted []string | ||
// Ambient is the ambient set of capabilities that are kept. | ||
Ambient []string | ||
} | ||
|
||
// Cmd represents a command to execute in a running container. | ||
type Cmd struct { | ||
Args []string | ||
Envs []EnvVar | ||
SupplementaryGroups []string | ||
|
||
// Note that these fields *MUST* remain as strings. | ||
// | ||
// The reason being that we want runtimes to be able to support CLI | ||
// operations like "exec --user=". That option allows the | ||
// specification of a user (either as a string username or a numeric | ||
// UID), and may optionally also include a group (groupame or GID). | ||
// | ||
// Since this type is the interface to allow the runtime to specify | ||
// the user and group the workload can run as, these user and group | ||
// fields cannot be encoded as integer values since that would imply | ||
// the runtime itself would need to perform a UID/GID lookup on the | ||
// user-specified username/groupname. But that isn't practically | ||
// possible given that to do so would require the runtime to access | ||
// the image to allow it to interrogate the appropriate databases to | ||
// convert the username/groupnames to UID/GID values. | ||
// | ||
// Note that this argument applies solely to the _runtime_ supporting | ||
// a "--user=" option when running in a "standalone mode" - there is | ||
// no issue when the runtime is called by a container manager since | ||
// all the user and group mapping is handled by the container manager | ||
// and specified to the runtime in terms of UID/GID's in the | ||
// configuration file generated by the container manager. | ||
User string | ||
PrimaryGroup string | ||
WorkDir string | ||
Console string | ||
Capabilities LinuxCapabilities | ||
|
||
Interactive bool | ||
Detach bool | ||
NoNewPrivileges bool | ||
} | ||
|
||
// Resources describes VM resources configuration. | ||
type Resources struct { | ||
// Memory is the amount of available memory in MiB. | ||
Memory uint | ||
MemorySlots uint8 | ||
} |