hcsshim

package module
v0.7.12-dev Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 6, 2018 License: MIT Imports: 14 Imported by: 0

README

hcsshim

Build status

This package contains the Golang interface for using the Windows Host Compute Service (HCS) to launch and manage Windows Containers. It also contains other helpers and functions for managing Windows Containers such as the Golang interface for the Host Network Service (HNS).

It is primarily used in the Moby Project, but it can be freely used by other projects as well.

Contributing

This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.microsoft.com.

When you submit a pull request, a CLA-bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.

This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments.

Dependencies

This project requires Golang 1.9 or newer to build.

For system requirements to run this project, see the Microsoft docs on Windows Container requirements.

Reporting Security Issues

Security issues and bugs should be reported privately, via email, to the Microsoft Security Response Center (MSRC) at secure@microsoft.com. You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Further information, including the MSRC PGP key, can be found in the Security TechCenter.

For additional details, see Report a Computer Security Vulnerability on Technet


Copyright (c) 2018 Microsoft Corp. All rights reserved.

Documentation

Index

Constants

View Source
const (
	Add     = schema1.Add
	Remove  = schema1.Remove
	Network = schema1.Network
)

RequestType const

View Source
const (
	// Specific user-visible exit codes
	WaitErrExecFailed = 32767

	ERROR_GEN_FAILURE          = hcserror.ERROR_GEN_FAILURE
	ERROR_SHUTDOWN_IN_PROGRESS = syscall.Errno(1115)
	WSAEINVAL                  = syscall.Errno(10022)

	// Timeout on wait calls
	TimeoutInfinite = 0xFFFFFFFF
)
View Source
const (
	Nat                  = hns.Nat
	ACL                  = hns.ACL
	PA                   = hns.PA
	VLAN                 = hns.VLAN
	VSID                 = hns.VSID
	VNet                 = hns.VNet
	L2Driver             = hns.L2Driver
	Isolation            = hns.Isolation
	QOS                  = hns.QOS
	OutboundNat          = hns.OutboundNat
	ExternalLoadBalancer = hns.ExternalLoadBalancer
	Route                = hns.Route
)

RequestType const

View Source
const (
	Allow = hns.Allow
	Block = hns.Block

	In  = hns.In
	Out = hns.Out

	Host   = hns.Host
	Switch = hns.Switch
)

Variables

View Source
var (
	// ErrComputeSystemDoesNotExist is an error encountered when the container being operated on no longer exists = hcs.exist
	ErrComputeSystemDoesNotExist = hcs.ErrComputeSystemDoesNotExist

	// ErrElementNotFound is an error encountered when the object being referenced does not exist
	ErrElementNotFound = hcs.ErrElementNotFound

	// ErrElementNotFound is an error encountered when the object being referenced does not exist
	ErrNotSupported = hcs.ErrNotSupported

	// ErrInvalidData is an error encountered when the request being sent to hcs is invalid/unsupported
	// decimal -2147024883 / hex 0x8007000d
	ErrInvalidData = hcs.ErrInvalidData

	// ErrHandleClose is an error encountered when the handle generating the notification being waited on has been closed
	ErrHandleClose = hcs.ErrHandleClose

	// ErrAlreadyClosed is an error encountered when using a handle that has been closed by the Close method
	ErrAlreadyClosed = hcs.ErrAlreadyClosed

	// ErrInvalidNotificationType is an error encountered when an invalid notification type is used
	ErrInvalidNotificationType = hcs.ErrInvalidNotificationType

	// ErrInvalidProcessState is an error encountered when the process is not in a valid state for the requested operation
	ErrInvalidProcessState = hcs.ErrInvalidProcessState

	// ErrTimeout is an error encountered when waiting on a notification times out
	ErrTimeout = hcs.ErrTimeout

	// ErrUnexpectedContainerExit is the error encountered when a container exits while waiting for
	// a different expected notification
	ErrUnexpectedContainerExit = hcs.ErrUnexpectedContainerExit

	// ErrUnexpectedProcessAbort is the error encountered when communication with the compute service
	// is lost while waiting for a notification
	ErrUnexpectedProcessAbort = hcs.ErrUnexpectedProcessAbort

	// ErrUnexpectedValue is an error encountered when hcs returns an invalid value
	ErrUnexpectedValue = hcs.ErrUnexpectedValue

	// ErrVmcomputeAlreadyStopped is an error encountered when a shutdown or terminate request is made on a stopped container
	ErrVmcomputeAlreadyStopped = hcs.ErrVmcomputeAlreadyStopped

	// ErrVmcomputeOperationPending is an error encountered when the operation is being completed asynchronously
	ErrVmcomputeOperationPending = hcs.ErrVmcomputeOperationPending

	// ErrVmcomputeOperationInvalidState is an error encountered when the compute system is not in a valid state for the requested operation
	ErrVmcomputeOperationInvalidState = hcs.ErrVmcomputeOperationInvalidState

	// ErrProcNotFound is an error encountered when the the process cannot be found
	ErrProcNotFound = hcs.ErrProcNotFound

	// ErrVmcomputeOperationAccessIsDenied is an error which can be encountered when enumerating compute systems in RS1/RS2
	// builds when the underlying silo might be in the process of terminating. HCS was fixed in RS3.
	ErrVmcomputeOperationAccessIsDenied = hcs.ErrVmcomputeOperationAccessIsDenied

	// ErrVmcomputeInvalidJSON is an error encountered when the compute system does not support/understand the messages sent by management
	ErrVmcomputeInvalidJSON = hcs.ErrVmcomputeInvalidJSON

	// ErrVmcomputeUnknownMessage is an error encountered guest compute system doesn't support the message
	ErrVmcomputeUnknownMessage = hcs.ErrVmcomputeUnknownMessage

	// ErrNotSupported is an error encountered when hcs doesn't support the request
	ErrPlatformNotSupported = hcs.ErrPlatformNotSupported
)
View Source
var (
	HNSVersion1803 = hns.HNSVersion1803
)

Functions

func ActivateLayer

func ActivateLayer(info DriverInfo, id string) error

func CreateLayer

func CreateLayer(info DriverInfo, id, parent string) error

func CreateSandboxLayer

func CreateSandboxLayer(info DriverInfo, layerId, parentId string, parentLayerPaths []string) error

New clients should use CreateScratchLayer instead. Kept in to preserve API compatibility.

func CreateScratchLayer added in v0.7.0

func CreateScratchLayer(info DriverInfo, layerId, parentId string, parentLayerPaths []string) error

func DeactivateLayer

func DeactivateLayer(info DriverInfo, id string) error

func DestroyLayer

func DestroyLayer(info DriverInfo, id string) error

func ExpandSandboxSize added in v0.3.2

func ExpandSandboxSize(info DriverInfo, layerId string, size uint64) error

New clients should use ExpandScratchSize instead. Kept in to preserve API compatibility.

func ExpandScratchSize added in v0.7.0

func ExpandScratchSize(info DriverInfo, layerId string, size uint64) error

func ExportLayer

func ExportLayer(info DriverInfo, layerId string, exportFolderPath string, parentLayerPaths []string) error

func GetLayerMountPath

func GetLayerMountPath(info DriverInfo, id string) (string, error)

func GetSharedBaseImages

func GetSharedBaseImages() (imageData string, err error)

func HotAttachEndpoint added in v0.5.15

func HotAttachEndpoint(containerID string, endpointID string) error

HotAttachEndpoint makes a HCS Call to attach the endpoint to the container

func HotDetachEndpoint added in v0.5.15

func HotDetachEndpoint(containerID string, endpointID string) error

HotDetachEndpoint makes a HCS Call to detach the endpoint from the container

func ImportLayer

func ImportLayer(info DriverInfo, layerID string, importFolderPath string, parentLayerPaths []string) error

func IsAlreadyClosed added in v0.5.3

func IsAlreadyClosed(err error) bool

IsAlreadyClosed checks if an error is caused by the Container or Process having been already closed by a call to the Close() method.

func IsAlreadyStopped added in v0.4.0

func IsAlreadyStopped(err error) bool

IsAlreadyStopped returns a boolean indicating whether the error is caused by a Container or Process being already stopped. Note: Currently, ErrElementNotFound can mean that a Process has either already exited, or does not exist. Both IsAlreadyStopped and IsNotExist will currently return true when the error is ErrElementNotFound or ErrProcNotFound.

func IsNotExist added in v0.4.0

func IsNotExist(err error) bool

IsNotExist checks if an error is caused by the Container or Process not existing. Note: Currently, ErrElementNotFound can mean that a Process has either already exited, or does not exist. Both IsAlreadyStopped and IsNotExist will currently return true when the error is ErrElementNotFound or ErrProcNotFound.

func IsNotSupported added in v0.5.15

func IsNotSupported(err error) bool

IsNotSupported returns a boolean indicating whether the error is caused by unsupported platform requests Note: Currently Unsupported platform requests can be mean either ErrVmcomputeInvalidJSON, ErrInvalidData, ErrNotSupported or ErrVmcomputeUnknownMessage is thrown from the Platform

func IsPending added in v0.4.0

func IsPending(err error) bool

IsPending returns a boolean indicating whether the error is that the requested operation is being completed in the background.

func IsTimeout added in v0.4.0

func IsTimeout(err error) bool

IsTimeout returns a boolean indicating whether the error is caused by a timeout waiting for the operation to complete.

func LayerExists

func LayerExists(info DriverInfo, id string) (bool, error)

func PrepareLayer

func PrepareLayer(info DriverInfo, layerId string, parentLayerPaths []string) error

func ProcessBaseLayer

func ProcessBaseLayer(path string) error

func ProcessUtilityVMImage

func ProcessUtilityVMImage(path string) error

func UnprepareLayer

func UnprepareLayer(info DriverInfo, layerId string) error

Types

type ACLPolicy added in v0.5.27

type ACLPolicy = hns.ACLPolicy

type ActionType added in v0.5.27

type ActionType = hns.ActionType

type AssignedDevice added in v0.6.12

type AssignedDevice = schema1.AssignedDevice

AssignedDevice represents a device that has been directly assigned to a container

NOTE: Support added in RS5

type ComputeSystemQuery added in v0.5.3

type ComputeSystemQuery = schema1.ComputeSystemQuery

type Container added in v0.3.0

type Container interface {
	// Start synchronously starts the container.
	Start() error

	// Shutdown requests a container shutdown, but it may not actually be shutdown until Wait() succeeds.
	Shutdown() error

	// Terminate requests a container terminate, but it may not actually be terminated until Wait() succeeds.
	Terminate() error

	// Waits synchronously waits for the container to shutdown or terminate.
	Wait() error

	// WaitTimeout synchronously waits for the container to terminate or the duration to elapse. It
	// returns false if timeout occurs.
	WaitTimeout(time.Duration) error

	// Pause pauses the execution of a container.
	Pause() error

	// Resume resumes the execution of a container.
	Resume() error

	// HasPendingUpdates returns true if the container has updates pending to install.
	HasPendingUpdates() (bool, error)

	// Statistics returns statistics for a container.
	Statistics() (Statistics, error)

	// ProcessList returns details for the processes in a container.
	ProcessList() ([]ProcessListItem, error)

	// MappedVirtualDisks returns virtual disks mapped to a utility VM, indexed by controller
	MappedVirtualDisks() (map[int]MappedVirtualDiskController, error)

	// CreateProcess launches a new process within the container.
	CreateProcess(c *ProcessConfig) (Process, error)

	// OpenProcess gets an interface to an existing process within the container.
	OpenProcess(pid int) (Process, error)

	// Close cleans up any state associated with the container but does not terminate or wait for it.
	Close() error

	// Modify the System
	Modify(config *ResourceModificationRequestResponse) error
}

Container represents a created (but not necessarily running) container.

func CreateContainer added in v0.3.0

func CreateContainer(id string, c *ContainerConfig) (Container, error)

CreateContainer creates a new container with the given configuration but does not start it.

func OpenContainer added in v0.3.0

func OpenContainer(id string) (Container, error)

OpenContainer opens an existing container by ID.

type ContainerConfig added in v0.3.0

type ContainerConfig = schema1.ContainerConfig

ContainerConfig is used as both the input of CreateContainer and to convert the parameters to JSON for passing onto the HCS

type ContainerError added in v0.3.0

type ContainerError struct {
	Container *container
	Operation string
	ExtraInfo string
	Err       error
	Events    []hcs.ErrorEvent
}

ContainerError is an error encountered in HCS during an operation on a Container object

func (*ContainerError) Error added in v0.3.0

func (e *ContainerError) Error() string

type ContainerProperties added in v0.5.3

type ContainerProperties = schema1.ContainerProperties

ContainerProperties holds the properties for a container and the processes running in that container

func GetContainers added in v0.5.3

func GetContainers(q ComputeSystemQuery) ([]ContainerProperties, error)

GetContainers gets a list of the containers on the system that match the query

type DirectionType added in v0.5.27

type DirectionType = hns.DirectionType

type DriverInfo

type DriverInfo struct {
	Flavour int
	HomeDir string
}

type ELBPolicy added in v0.5.27

type ELBPolicy = hns.ELBPolicy

ELBPolicy is a structure defining schema for ELB LoadBalancing based Policy

type EndpointAttachDetachRequest added in v0.6.2

type EndpointAttachDetachRequest = hns.EndpointAttachDetachRequest

EndpointAttachDetachRequest is the structure used to send request to the container to modify the system Supported resource types are Network and Request Types are Add/Remove

type EndpointNotFoundError added in v0.6.7

type EndpointNotFoundError = hns.EndpointNotFoundError

type EndpointResquestResponse added in v0.6.2

type EndpointResquestResponse = hns.EndpointResquestResponse

EndpointResquestResponse is object to get the endpoint request response

type FilterLayerReader

type FilterLayerReader = wclayer.FilterLayerReader

type FilterLayerWriter

type FilterLayerWriter = wclayer.FilterLayerWriter

type GUID

type GUID [16]byte

func NameToGuid

func NameToGuid(name string) (id GUID, err error)

func NewGUID

func NewGUID(source string) *GUID

func (*GUID) ToString

func (g *GUID) ToString() string

type HNSAclFeatures added in v0.7.0

type HNSAclFeatures = hns.HNSAclFeatures

type HNSEndpoint

type HNSEndpoint = hns.HNSEndpoint

HNSEndpoint represents a network endpoint in HNS

func GetHNSEndpointByID added in v0.5.15

func GetHNSEndpointByID(endpointID string) (*HNSEndpoint, error)

GetHNSEndpointByID get the Endpoint by ID

func GetHNSEndpointByName added in v0.5.15

func GetHNSEndpointByName(endpointName string) (*HNSEndpoint, error)

GetHNSEndpointByName gets the endpoint filtered by Name

func HNSEndpointRequest

func HNSEndpointRequest(method, path, request string) (*HNSEndpoint, error)

HNSEndpointRequest makes a HNS call to modify/query a network endpoint

func HNSListEndpointRequest added in v0.5.15

func HNSListEndpointRequest() ([]HNSEndpoint, error)

HNSListEndpointRequest makes a HNS call to query the list of available endpoints

type HNSGlobals added in v0.7.0

type HNSGlobals = hns.HNSGlobals

func GetHNSGlobals added in v0.7.0

func GetHNSGlobals() (*HNSGlobals, error)

type HNSNetwork

type HNSNetwork = hns.HNSNetwork

HNSNetwork represents a network in HNS

func GetHNSNetworkByID added in v0.5.15

func GetHNSNetworkByID(networkID string) (*HNSNetwork, error)

GetHNSNetworkByID

func GetHNSNetworkByName added in v0.5.15

func GetHNSNetworkByName(networkName string) (*HNSNetwork, error)

GetHNSNetworkName filtered by Name

func HNSListNetworkRequest

func HNSListNetworkRequest(method, path, request string) ([]HNSNetwork, error)

HNSListNetworkRequest makes a HNS call to query the list of available networks

func HNSNetworkRequest

func HNSNetworkRequest(method, path, request string) (*HNSNetwork, error)

HNSNetworkRequest makes a call into HNS to update/query a single network

type HNSSupportedFeatures added in v0.7.0

type HNSSupportedFeatures = hns.HNSSupportedFeatures

func GetHNSSupportedFeatures added in v0.7.0

func GetHNSSupportedFeatures() HNSSupportedFeatures

type HNSVersion added in v0.7.0

type HNSVersion = hns.HNSVersion

type HcsError

type HcsError = hcserror.HcsError

type HvRuntime added in v0.3.0

type HvRuntime = schema1.HvRuntime

type IsolationPolicy added in v0.5.27

type IsolationPolicy = hns.IsolationPolicy

type LBPolicy added in v0.5.27

type LBPolicy = hns.LBPolicy

LBPolicy is a structure defining schema for LoadBalancing based Policy

type Layer added in v0.3.0

type Layer = schema1.Layer

type LayerReader

type LayerReader = wclayer.LayerReader

func NewLayerReader

func NewLayerReader(info DriverInfo, layerID string, parentLayerPaths []string) (LayerReader, error)

type LayerWriter

type LayerWriter = wclayer.LayerWriter

func NewLayerWriter

func NewLayerWriter(info DriverInfo, layerID string, parentLayerPaths []string) (LayerWriter, error)

type MacPool

type MacPool = hns.MacPool

MacPool is assoicated with a network and represents a list of macaddresses available to the network

type MappedDir added in v0.3.0

type MappedDir = schema1.MappedDir

type MappedPipe added in v0.5.26

type MappedPipe = schema1.MappedPipe

type MappedVirtualDisk added in v0.5.21

type MappedVirtualDisk = schema1.MappedVirtualDisk

type MappedVirtualDiskController added in v0.5.28

type MappedVirtualDiskController = schema1.MappedVirtualDiskController

MappedVirtualDiskController is the structure of an item returned by a MappedVirtualDiskList call on a container

type MemoryStats added in v0.4.0

type MemoryStats = schema1.MemoryStats

MemoryStats holds the memory statistics for a container

type Namespace added in v0.7.5

type Namespace = hns.Namespace

Namespace represents a Compartment.

type NatPolicy

type NatPolicy = hns.NatPolicy

type NetworkNotFoundError added in v0.6.7

type NetworkNotFoundError = hns.NetworkNotFoundError

type NetworkStats added in v0.4.0

type NetworkStats = schema1.NetworkStats

NetworkStats holds the network statistics for a container

type OutboundNatPolicy added in v0.5.27

type OutboundNatPolicy = hns.OutboundNatPolicy

type PaPolicy added in v0.5.2

type PaPolicy = hns.PaPolicy

type Policy added in v0.5.27

type Policy = hns.Policy

type PolicyList added in v0.5.27

type PolicyList = hns.PolicyList

PolicyList is a structure defining schema for Policy list request

func AddLoadBalancer added in v0.5.27

func AddLoadBalancer(endpoints []HNSEndpoint, isILB bool, sourceVIP, vip string, protocol uint16, internalPort uint16, externalPort uint16) (*PolicyList, error)

AddLoadBalancer policy list for the specified endpoints

func AddRoute added in v0.5.27

func AddRoute(endpoints []HNSEndpoint, destinationPrefix string, nextHop string, encapEnabled bool) (*PolicyList, error)

AddRoute adds route policy list for the specified endpoints

func GetPolicyListByID added in v0.6.2

func GetPolicyListByID(policyListID string) (*PolicyList, error)

GetPolicyListByID get the policy list by ID

func HNSListPolicyListRequest added in v0.5.27

func HNSListPolicyListRequest() ([]PolicyList, error)

HNSListPolicyListRequest gets all the policy list

func HNSPolicyListRequest added in v0.5.27

func HNSPolicyListRequest(method, path, request string) (*PolicyList, error)

HNSPolicyListRequest makes a call into HNS to update/query a single network

func PolicyListRequest added in v0.5.27

func PolicyListRequest(method, path, request string) (*PolicyList, error)

PolicyListRequest makes a HNS call to modify/query a network policy list

type PolicyType added in v0.5.27

type PolicyType = hns.PolicyType

Type of Request Support in ModifySystem

type Process added in v0.3.0

type Process interface {
	// Pid returns the process ID of the process within the container.
	Pid() int

	// Kill signals the process to terminate but does not wait for it to finish terminating.
	Kill() error

	// Wait waits for the process to exit.
	Wait() error

	// WaitTimeout waits for the process to exit or the duration to elapse. It returns
	// false if timeout occurs.
	WaitTimeout(time.Duration) error

	// ExitCode returns the exit code of the process. The process must have
	// already terminated.
	ExitCode() (int, error)

	// ResizeConsole resizes the console of the process.
	ResizeConsole(width, height uint16) error

	// Stdio returns the stdin, stdout, and stderr pipes, respectively. Closing
	// these pipes does not close the underlying pipes; it should be possible to
	// call this multiple times to get multiple interfaces.
	Stdio() (io.WriteCloser, io.ReadCloser, io.ReadCloser, error)

	// CloseStdin closes the write side of the stdin pipe so that the process is
	// notified on the read side that there is no more data in stdin.
	CloseStdin() error

	// Close cleans up any state associated with the process but does not kill
	// or wait on it.
	Close() error
}

Process represents a running or exited process.

type ProcessConfig added in v0.3.0

type ProcessConfig = schema1.ProcessConfig

ProcessConfig is used as both the input of Container.CreateProcess and to convert the parameters to JSON for passing onto the HCS

type ProcessError added in v0.3.0

type ProcessError struct {
	Process   *process
	Operation string
	ExtraInfo string
	Err       error
	Events    []hcs.ErrorEvent
}

ProcessError is an error encountered in HCS during an operation on a Process object

func (*ProcessError) Error added in v0.3.0

func (e *ProcessError) Error() string

type ProcessListItem added in v0.4.2

type ProcessListItem = schema1.ProcessListItem

ProcessList is the structure of an item returned by a ProcessList call on a container

type ProcessorStats added in v0.4.0

type ProcessorStats = schema1.ProcessorStats

ProcessorStats holds the processor statistics for a container

type QosPolicy

type QosPolicy = hns.QosPolicy

type RequestType added in v0.5.15

type RequestType = schema1.RequestType

Type of Request Support in ModifySystem

type ResourceModificationRequestResponse added in v0.5.15

type ResourceModificationRequestResponse = schema1.ResourceModificationRequestResponse

ResourceModificationRequestResponse is the structure used to send request to the container to modify the system Supported resource types are Network and Request Types are Add/Remove

type ResourceType added in v0.5.15

type ResourceType = schema1.ResourceType

Type of Resource Support in ModifySystem

type RoutePolicy added in v0.5.27

type RoutePolicy = hns.RoutePolicy

RoutePolicy is a structure defining schema for Route based Policy

type RuleType added in v0.5.27

type RuleType = hns.RuleType

type Statistics added in v0.4.0

type Statistics = schema1.Statistics

Statistics is the structure returned by a statistics call on a container

type StorageStats added in v0.4.0

type StorageStats = schema1.StorageStats

StorageStats holds the storage statistics for a container

type Subnet

type Subnet = hns.Subnet

Subnet is assoicated with a network and represents a list of subnets available to the network

type SystemType added in v0.6.2

type SystemType string

SystemType represents the type of the system on which actions are done

const (
	ContainerType      SystemType = "Container"
	VirtualMachineType SystemType = "VirtualMachine"
	HostType           SystemType = "Host"
)

SystemType const

type VlanPolicy added in v0.3.2

type VlanPolicy = hns.VlanPolicy

type VsidPolicy added in v0.3.2

type VsidPolicy = hns.VsidPolicy

type WC_LAYER_DESCRIPTOR

type WC_LAYER_DESCRIPTOR = wclayer.WC_LAYER_DESCRIPTOR

Directories

Path Synopsis
cmd
ext4
Package hcn is a shim for the Host Compute Networking (HCN) service, which manages networking for Windows Server containers and Hyper-V containers.
Package hcn is a shim for the Host Compute Networking (HCN) service, which manages networking for Windows Server containers and Hyper-V containers.
internal
appargs
Package appargs provides argument validation routines for use with github.com/urfave/cli.
Package appargs provides argument validation routines for use with github.com/urfave/cli.
cni
hcs
hns
ociwclayer
Package ociwclayer provides functions for importing and exporting Windows container layers from and to their OCI tar representation.
Package ociwclayer provides functions for importing and exporting Windows container layers from and to their OCI tar representation.
uvm
pkg

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL