config

package
v0.0.0-...-3e0e934 Latest Latest
Warning

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

Go to latest
Published: Jun 28, 2026 License: Apache-2.0, BSD-2-Clause Imports: 16 Imported by: 0

Documentation

Overview

Package config provides the configuration for the cube master

Index

Constants

View Source
const DefaultCubeEgressCAPath = "/etc/cube/ca/cube-root-ca.crt"

DefaultCubeEgressCAPath is the canonical install path. Used when CubeEgressConf is unset or its CAPath is empty AND Required is true (meaning: an operator opted into the strict mode but forgot to configure the path; we'd rather try the canonical path than refuse to start).

Variables

This section is empty.

Functions

func AppendConfigWatcher

func AppendConfigWatcher(listener Watcher)

func DefaultNodeAffinitySelectorAllowedKeySet

func DefaultNodeAffinitySelectorAllowedKeySet() map[string]struct{}

func GetInstanceTypeOfClusterLabel

func GetInstanceTypeOfClusterLabel(label string) string

func GetLogConfig

func GetLogConfig() *log.Conf

func GetSchedulerInstanceTypeConfs

func GetSchedulerInstanceTypeConfs() []string

func HasEnvPrestartHook

func HasEnvPrestartHook(app string, envKey string) []*types.Hook

func HasEnvVirtiofsCacheHook

func HasEnvVirtiofsCacheHook(app string, envKey string) string

func IsAppHooks

func IsAppHooks(app string) bool

func IsInstanceTypeConfig

func IsInstanceTypeConfig(product string) bool

func IsReservedLabelKey

func IsReservedLabelKey(k string) bool

IsReservedLabelKey reports whether k is a system-reserved label key that cannot be created or deleted via the admin API. It checks the namespace prefix of the key (the part before '/'), or the whole key if no '/' is present.

Types

type AffinityConf

type AffinityConf struct {
	Enable            bool           `yaml:"enable"`
	DisableVmCgroup   bool           `yaml:"disable_vm_cgroup"`
	DisableHostCgroup bool           `yaml:"disable_host_cgroup"`
	ClusterLabels     map[string]any `yaml:"cluster_labels"`
}

type AffinityScore

type AffinityScore struct {
	Weight              float64  `yaml:"weight"`
	EnableWeightFactors []string `yaml:"enable_weight_factors"`
	Disable             bool     `yaml:"disable"`
}

type AppHookConfig

type AppHookConfig struct {
	PrestartHookByEnvKeys map[string][]*types.Hook `yaml:"prestart_hook_by_env_keys"`

	VirtiofsCacheHookByEnvKeys map[string]string `yaml:"virtiofs_cache_hook_by_env_keys"`
}

type AuthConf

type AuthConf struct {
	Enable                   bool                         `yaml:"enable"`
	SignatureExpireTimeInsec int64                        `yaml:"signature_expire_time_insec"`
	SecretKeyMap             map[string]map[string]string `yaml:"secret_key_map"`
}

type CommonConf

type CommonConf struct {
	MockUpdateAction       bool          `yaml:"mock_update_action"`
	DebugDumpHttpBody      bool          `yaml:"debug_dump_http_body"`
	MockDebug              bool          `yaml:"mock_debug"`
	MockNodeNum            int           `yaml:"mock_node_num"`
	MockCreateDirect       bool          `yaml:"mock_create_direct"`
	MockCreateDirectHandle bool          `yaml:"mock_create_direct_handle"`
	MockHttpDirect         bool          `yaml:"mock_http_direct"`
	MockCreateSleep        time.Duration `yaml:"mock_create_sleep"`
	MockPercents           []float64     `yaml:"mock_percents"`
	CubeDestroyCheckFilter bool          `yaml:"cube_destroy_check_filter"`
	Debug                  Debug         `toml:"debug"`
	HttpPort               int           `yaml:"http_port"`
	// HttpBind is the HTTP listen address. Empty means 0.0.0.0 (all
	// interfaces); set to 127.0.0.1 to keep the API loopback-only.
	HttpBind                        string            `yaml:"http_bind"`
	WriteTimeout                    int               `yaml:"http_writetimeout"`
	ReadTimeout                     int               `yaml:"http_readtimeout"`
	IdleTimeout                     int               `yaml:"http_idletimeout"`
	GraceFullStopTimeoutInSec       int               `yaml:"gracefull_stop_timeout_insec"`
	SyncMetaDataInterval            time.Duration     `yaml:"sync_meta_data_interval"`
	SyncMetricDataInterval          time.Duration     `yaml:"sync_metric_data_interval"`
	CleanSandboxCacheInterval       time.Duration     `yaml:"clean_sandbox_cache_interval"`
	EnabledListRunningSandboxCache  bool              `yaml:"enabled_list_running_sandbox_cache"`
	AsyncTaskQueueSize              int               `yaml:"async_task_queue_size"`
	AsyncTaskWorkerNum              int               `yaml:"async_task_worker_num"`
	HeadlessServiceName             string            `yaml:"headless_service_name"`
	DefaultHeadlessServiceNodesNum  int64             `yaml:"default_headless_service_nodes_num"`
	ListFilterOutLables             map[string]string `yaml:"list_filter_out_lables"`
	CollectMetricInterval           time.Duration     `yaml:"collect_metric_interval"`
	ReportLocalCreateNum            bool              `yaml:"report_local_create_num"`
	ReportStdevMetric               bool              `yaml:"report_stdev_metric"`
	GwCacheExpiredTime              time.Duration     `yaml:"gw_cache_expired_time"`
	GwCacheEnable                   bool              `yaml:"gw_cache_enable"`
	ReportGWRedisGetMetric          bool              `yaml:"report_gw_redis_get_metric"`
	EnableGetStatusFromCubelet      bool              `yaml:"enable_get_status_from_cubelet"`
	DisableHardDelete               bool              `yaml:"disable_hard_delete"`
	CollectSandboxMemoryWhitelist   []string          `yaml:"collect_sandbox_memory_whitelist"`
	EnableAllCollectSandboxMemory   bool              `yaml:"enable_all_collect_sandbox_memory"`
	FilterErrMsgErrorCode           map[int]bool      `yaml:"filter_err_msg_error_code"`
	DescribeInstancesWhiteList      map[string]bool   `yaml:"describe_instances_white_list"`
	DescribeTaskExpireTime          int               `yaml:"describe_task_expire_time"`
	EnablePrivateIpQuery            bool              `yaml:"enable_private_ip_query"`
	DbMaxRetryCount                 int               `yaml:"db_max_retry_count"`
	DbRetryInterval                 time.Duration     `yaml:"db_retry_interval"`
	EnableCheckComNetIDParam        bool              `yaml:"enable_check_com_net_id_param"`
	EnableDescribeInstanceFromRedis bool              `yaml:"enable_describe_instance_from_redis"`
	MaxNICQueue                     int               `yaml:"max_nic_queue"`
	DisableCreateImageCluster       map[string]bool   `yaml:"disable_create_image_cluster"`
	EnableAGSColdStartSwitch        bool              `yaml:"enable_ags_cold_start_switch"`
}

type Config

type Config struct {
	Common           *CommonConf           `yaml:"common"`
	AuthConf         *AuthConf             `yaml:"auth"`
	Log              *log.Conf             `yaml:"log"`
	CubeletConf      *CubeletConf          `yaml:"cubelet_conf"`
	OssDBConfig      *DBConfig             `yaml:"ossdb_config"`
	InstanceDBConfig *DBConfig             `yaml:"instance_db_config"`
	RedisConf        *RedisConf            `yaml:"redis"`
	ExtraConf        *ExtraConf            `yaml:"extra_conf"`
	Scheduler        *WrapperSchedulerConf `yaml:"scheduler"`
	ReqTemplateConf  *ReqTemplateConf      `yaml:"req_template_conf"`
	HookWhitelist    *HookWhitelist        `yaml:"hook_whitelist"`
	CubeEgressConf   *CubeEgressConf       `yaml:"cube_egress_conf"`
}

func GetConfig

func GetConfig() *Config

func Init

func Init() (*Config, error)

type CubeEgressConf

type CubeEgressConf struct {
	// CAPath is the host-side filesystem location of the CubeEgress
	// root certificate (PEM). Empty disables the bake silently —
	// preserves dev/test setups where CubeEgress isn't deployed. The
	// production deployment path drops the CA here as part of
	// up-cube-egress.sh; CubeMaster reads from the same file so the
	// data plane and the bake stay in lock-step on rotation.
	CAPath string `yaml:"ca_path"`

	// Required, when true, turns soft skips into hard errors:
	//   - missing CAPath file → fail the template build
	//   - zero bundle/anchor targets matched → fail the template build
	// Production deployments should set this to true so a misdeploy
	// where the CA file is absent fails loudly instead of producing a
	// silently-broken template.
	Required bool `yaml:"required"`
}

CubeEgressConf controls how CubeMaster bakes the CubeEgress root CA into freshly-built sandbox rootfs templates so workloads inside the sandbox trust the MITM certificates CubeEgress signs at request time. See design/cube-egress-ca-bake.md.

type CubeletConf

type CubeletConf struct {
	Grpc                    *GrpcConf            `yaml:"grpc"`
	CommonTimeoutInsec      int                  `yaml:"common_timeout_insec"`
	CreateImageTimeoutInSec int                  `yaml:"create_image_timeout_insec"`
	AsyncFlows              map[string]asyncFlow `yaml:"async_flows"`
	RetryCode               []string             `yaml:"retry_code"`
	LoopRetryCode           []string             `yaml:"loop_retry_code"`
	ReuseRetryCode          []string             `yaml:"reuse_retry_code"`
	CircuitBreakCode        []string             `yaml:"circuit_break_code"`
	ExcludeLoopRetryCode    []string             `yaml:"exclude_loop_retry_code"`
	BackoffRetryCode        []string             `yaml:"backoff_retry_code"`
	MaxRetries              int64                `yaml:"max_retries"`
	LoopMaxRetries          int64                `yaml:"loop_max_retries"`
	BufferQueueMinJob       int64                `yaml:"buffer_queue_min_job"`
	CreateConcurrentLimit   int64                `yaml:"create_concurrent_limit"`
	DestroyConcurentLimit   int64                `yaml:"destroy_concurent_limit"`
	ExposedPortList         []string             `yaml:"exposed_port_list"`
	EnableExposedPort       bool                 `yaml:"enable_exposed_port"`
	DisableRedisProxyPort   bool                 `yaml:"disable_redis_proxy_port"`
	MaxDelayInSecond        int64                `yaml:"max_delay_in_second"`
	BackoffRetryDelay       time.Duration        `yaml:"backoff_retry_delay"`
}

type DBConfig

type DBConfig struct {
	// Driver selects the dao engine ("mysql", future: "postgres", ...).
	// Empty defaults to "mysql" for backwards compatibility with v0.2.2
	// configurations that pre-date the multi-driver dao layer.
	Driver string `yaml:"driver"`

	Addr                   string `yaml:"addr"`
	User                   string `yaml:"user"`
	Pwd                    string `yaml:"pwd"`
	DBName                 string `yaml:"db_name"`
	ConnTimeout            int    `yaml:"conn_timeout"`
	ReadTimeout            int    `yaml:"read_timeout"`
	WriteTimeout           int    `yaml:"write_timeout"`
	MaxIdleConns           int    `yaml:"max_idle_conns"`
	MaxOpenConns           int    `yaml:"max_open_conns"`
	MaxConnLifeTimeSeconds int    `yaml:"max_conn_life_time_seconds"`

	// MigrationLockTimeoutSeconds bounds the cluster-wide GET_LOCK wait
	// at startup. Defaults to 60 seconds when zero.
	MigrationLockTimeoutSeconds int `yaml:"migration_lock_timeout_seconds"`
}

func GetDbConfig

func GetDbConfig() *DBConfig

func GetInstanceConfig

func GetInstanceConfig() *DBConfig

type Debug

type Debug struct {
	Address string `toml:"address"`
}

type ExtraConf

type ExtraConf struct {
	BlkQos     string            `yaml:"blk_qos"`
	BlkQosMap  map[string]string `yaml:"blk_qos_map"`
	FsQos      string            `yaml:"fs_qos"`
	FsQosMap   map[string]string `yaml:"fs_qos_map"`
	NetQosList string            `yaml:"net_qos_list"`
}

type GrpcConf

type GrpcConf struct {
	GrpcPort                     int `yaml:"grpc_port"`
	CleanConnTaskIntervalInMin   int `yaml:"clean_conn_task_interval_in_min"`
	CleanConnTaskRoutinePoolSize int `yaml:"clean_conn_task_routine_pool_size"`
	ConnExpireTimeInSec          int `yaml:"conn_expire_time_insec"`
}

type HookWhitelist

type HookWhitelist struct {
	AppsHooks map[string]*AppHookConfig `yaml:"apps_hooks"`
}

type ImageScore

type ImageScore struct {
	Weight              float64  `yaml:"weight"`
	EnableWeightFactors []string `yaml:"enable_weight_factors"`
	Disable             bool     `yaml:"disable"`
}

type InstanceTypeConf

type InstanceTypeConf struct {
	OssClusterLabels map[string]any `yaml:"oss_cluster_labels"`
}

type LargeSizeAffinityConf

type LargeSizeAffinityConf struct {
	Enable               bool           `yaml:"enable"`
	MemoryLowerWaterMark string         `yaml:"memory_lower_water_mark"`
	CpuLowerWaterMark    string         `yaml:"cpu_lower_water_mark"`
	Operator             string         `yaml:"operator"`
	ClusterLabels        map[string]any `yaml:"cluster_labels"`
}

type MultiFactorWeightedAverage

type MultiFactorWeightedAverage struct {
	ScoreInterval       time.Duration `yaml:"score_interval"`
	Weight              float64       `yaml:"weight"`
	EnableWeightFactors []string      `yaml:"enable_weight_factors"`
	Disable             bool          `yaml:"disable"`
}

type NodeMaxMemReservedConf

type NodeMaxMemReservedConf struct {
	MaxMemReservedInMB        int64   `yaml:"max_mem_reserved_in_mb"`
	MaxMemReservedInMBPercent float64 `yaml:"max_mem_reserved_in_mb_percent"`
}

type NodeMaxMvmNumConf

type NodeMaxMvmNumConf struct {
	MvmNum                  int64   `yaml:"mvm_num"`
	MvmNumReserveNumPercent float64 `yaml:"mvm_num_reserve_num_percent"`
}

type OvercommitRatioConf

type OvercommitRatioConf struct {
	CPURatio float64 `yaml:"cpu_ratio"`
	MemRatio float64 `yaml:"mem_ratio"`
}

OvercommitRatioConf describes the CPU/Mem overcommit multipliers applied to a node's reported quota when computing schedulable capacity.

type OverheadConf

type OverheadConf struct {
	VmMemoryOverheadBase        string `yaml:"vm_memory_overhead_base"`
	VmMemoryOverheadCoefficient int64  `yaml:"vm_memory_overhead_coefficient"`
	HostMemoryOverheadBase      string `yaml:"host_memory_overhead_base"`
	CubeMsgMemoryOverhead       string `yaml:"cube_msg_memory_overhead"`
	VmCpuOverhead               string `yaml:"vm_cpu_overhead"`
	HostCpuOverhead             string `yaml:"host_cpu_overhead"`
}

type PostScoreConf

type PostScoreConf struct {
	Disable              bool               `yaml:"disable"`
	ParamFactor          float64            `yaml:"param_factor"`
	ResourceWeights      map[string]float64 `yaml:"resource_weights"`
	ActiveWhiteList      []string           `yaml:"active_white_list"`
	ActiveWhiteListMap   map[string]bool    `yaml:"-"`
	NegativeWhiteList    []string           `yaml:"negative_white_list"`
	NegativeWhiteListMap map[string]bool    `yaml:"-"`
}

type RealTimeWeightedAverage

type RealTimeWeightedAverage struct {
	Weight              float64  `yaml:"weight"`
	EnableWeightFactors []string `yaml:"enable_weight_factors"`
	Disable             bool     `yaml:"disable"`
}

type RedisConf

type RedisConf struct {
	Password    string `yaml:"password"`
	MaxActive   int    `yaml:"max_active"`
	MaxIdle     int    `yaml:"max_idle"`
	IdleTimeout int    `yaml:"idle_timeout"`
	DbNo        int    `yaml:"db_no"`

	Nodes    string `yaml:"nodes"`
	MaxRetry int    `yaml:"max_retry"`

	// NodeMetricTTLSec is the safety TTL (seconds) for node-metric keys so an
	// offline node's entry auto-expires; refreshed on every heartbeat write.
	// A value <= 0 disables the TTL.
	NodeMetricTTLSec int `yaml:"node_metric_ttl_sec"`
	// SandboxProxyTTLSec is an OPTIONAL safety TTL (seconds) for sandbox proxy
	// routing keys. It defaults to 0 (disabled) because the route key has no
	// refresh path; enabling it is only safe if the TTL exceeds the maximum
	// sandbox lifetime, otherwise a live route would expire and break routing.
	// Normal teardown removes the key via DEL.
	SandboxProxyTTLSec int `yaml:"sandbox_proxy_ttl_sec"`
}

func GetRedisConfig

func GetRedisConfig() *RedisConf

type ReqTemplateConf

type ReqTemplateConf struct {
	CubeBoxReqTemplate string         `yaml:"cube_box_req_template"`
	WhitelistReqTag    map[string]any `yaml:"whitelist_req_tag"`
}

type SchedulerConf

type SchedulerConf struct {
	Overhead                       *OverheadConf                `yaml:"overhead"`
	NodeMaxMvmNum                  int64                        `yaml:"node_max_mvm_num"`
	NodeMaxMvmNumReserveNumPercent float64                      `yaml:"node_max_mvm_num_reserve_num_percent"`
	NodeMaxMemReservedInMB         int64                        `yaml:"node_max_mem_reserved_in_mb"`
	NodeMaxCpuUtil                 float64                      `yaml:"node_max_cpu_util"`
	PreSelectNum                   int                          `yaml:"pre_select_num"`
	PrioritySelectNum              int                          `yaml:"priority_select_num"`
	LeastSelectName                string                       `yaml:"least_select_name"`
	MetricUpdateTimeout            time.Duration                `yaml:"metric_update_timeout"`
	LocalMetricUpdateTimeout       time.Duration                `yaml:"local_metric_update_timeout"`
	Filter                         *SchedulerFilterConf         `yaml:"filter"`
	Score                          *SchedulerScoreConf          `yaml:"score"`
	PostScore                      *PostScoreConf               `yaml:"postscore"`
	DisableCircuitFilter           bool                         `yaml:"disable_circuit_filter"`
	InBackoffMode                  bool                         `yaml:"in_backoff_mode"`
	AffinityConf                   map[string]AffinityConf      `yaml:"affinityconf"`
	NodeMaxMvmNumConf              map[string]NodeMaxMvmNumConf `yaml:"node_max_mvm_num_conf"`
	EnableRunInstanceHostIps       bool                         `yaml:"enable_run_instance_host_ips"`
	MaxMvmCPU                      string                       `yaml:"max_mvm_cpu"`

	MaxMvmMemory string `yaml:"max_mvm_memory"`

	DiskUsageMaxPercent              float64                           `yaml:"disk_usage_max_percent"`
	LargeSizeAffinityConf            map[string]LargeSizeAffinityConf  `yaml:"large_size_affinity_conf"`
	NodeMaxMemReservedConf           map[string]NodeMaxMemReservedConf `yaml:"node_max_mem_reserved_conf"`
	DisableBackoffFilterInstanceType map[string]bool                   `yaml:"disable_backoff_filter_instance_type"`
	ThirtpartyFilterInstanceType     map[string]bool                   `yaml:"thirtparty_filter_instance_type"`
	InstanceTypeConf                 map[string]InstanceTypeConf       `yaml:"instance_type_conf"`
	NodeAffinitySelectorAllowedKeys  []string                          `yaml:"node_affinity_selector_allowed_keys"`

	// IgnoreRedisAllocation, when true, makes the scheduler ignore the
	// per-node allocated CPU/Mem usage recorded in Redis (treat allocated as
	// 0). A pointer is used so an unset value can default to false while still
	// allowing operators to explicitly enable it. Defaults to false.
	IgnoreRedisAllocation *bool `yaml:"ignore_redis_allocation"`
	// OvercommitRatio is the global CPU/Mem overcommit ratio applied to the
	// node-reported quota during scheduling. Defaults to CPU=3, Mem=2.
	OvercommitRatio *OvercommitRatioConf `yaml:"overcommit_ratio"`
	// OvercommitRatioByType overrides OvercommitRatio for specific instance
	// types and takes precedence over the global ratio.
	OvercommitRatioByType map[string]OvercommitRatioConf `yaml:"overcommit_ratio_conf"`
	// contains filtered or unexported fields
}

func (*SchedulerConf) EffectiveAllocated

func (s *SchedulerConf) EffectiveAllocated(usage int64) int64

EffectiveAllocated returns the allocated usage the scheduler should account for, which is 0 when Redis allocation records are ignored.

func (*SchedulerConf) EffectiveQuotaCpu

func (s *SchedulerConf) EffectiveQuotaCpu(instanceType string, quotaCpu int64) int64

EffectiveQuotaCpu returns the schedulable CPU capacity (milli-cores) for a node after applying the configured overcommit ratio to its reported quota.

func (*SchedulerConf) EffectiveQuotaMem

func (s *SchedulerConf) EffectiveQuotaMem(instanceType string, quotaMem int64) int64

EffectiveQuotaMem returns the schedulable memory capacity (MB) for a node after applying the configured overcommit ratio to its reported quota.

func (*SchedulerConf) GetAffinityConf

func (s *SchedulerConf) GetAffinityConf(serviceName string) AffinityConf

func (*SchedulerConf) GetEffectiveNodeMaxMemReservedInMB

func (s *SchedulerConf) GetEffectiveNodeMaxMemReservedInMB(instanceType string, quotaMemMB int64) int64

func (*SchedulerConf) GetEffectiveOvercommitRatio

func (s *SchedulerConf) GetEffectiveOvercommitRatio(instanceType string) OvercommitRatioConf

GetEffectiveOvercommitRatio returns the overcommit ratio for the given instance type, falling back to the global ratio and then to the built-in defaults (CPU=3, Mem=2).

func (*SchedulerConf) GetLargeSizeAffinityConf

func (s *SchedulerConf) GetLargeSizeAffinityConf(serviceName string) LargeSizeAffinityConf

func (*SchedulerConf) GetNodeMaxMemReservedConf

func (s *SchedulerConf) GetNodeMaxMemReservedConf(instanceType string) NodeMaxMemReservedConf

func (*SchedulerConf) GetNodeMaxMvmNumConf

func (s *SchedulerConf) GetNodeMaxMvmNumConf(instanceType string) NodeMaxMvmNumConf

func (*SchedulerConf) MaxMvmCPURes

func (s *SchedulerConf) MaxMvmCPURes() resource.Quantity

func (*SchedulerConf) MaxMvmMemoryRes

func (s *SchedulerConf) MaxMvmMemoryRes() resource.Quantity

func (*SchedulerConf) NodeAffinitySelectorAllowedKeySet

func (s *SchedulerConf) NodeAffinitySelectorAllowedKeySet() map[string]struct{}

func (*SchedulerConf) ShouldIgnoreRedisAllocation

func (s *SchedulerConf) ShouldIgnoreRedisAllocation() bool

ShouldIgnoreRedisAllocation reports whether the scheduler must ignore the allocated CPU/Mem usage recorded in Redis. Defaults to false when unset.

type SchedulerFilterConf

type SchedulerFilterConf struct {
	EnableFilters []string `yaml:"enable_filters"`
}

type SchedulerScoreConf

type SchedulerScoreConf struct {
	EnableScorers   []string           `yaml:"enable_scorers"`
	ResourceWeights map[string]float64 `yaml:"resource_weights"`
	ScorePluginConf ScorePluginConf    `yaml:"plugin_conf"`
}

type ScorePluginConf

type ScorePluginConf struct {
	MultiFactorWeightedAverage *MultiFactorWeightedAverage `yaml:"multi_factor_weighted_average"`
	RealTimeWeightedAverage    *RealTimeWeightedAverage    `yaml:"real_time_weighted_average"`
	AffinityScore              *AffinityScore              `yaml:"affinity_score"`
	ImageScore                 *ImageScore                 `yaml:"image_score"`
	TemplateScore              *TemplateScore              `yaml:"template_score"`
}

type TemplateScore

type TemplateScore struct {
	Weight              float64  `yaml:"weight"`
	EnableWeightFactors []string `yaml:"enable_weight_factors"`
	Disable             bool     `yaml:"disable"`
}

type Watcher

type Watcher interface {
	OnEvent(data *Config)
}

type WrapperSchedulerConf

type WrapperSchedulerConf struct {
	SchedulerConf `yaml:",inline"`
	// contains filtered or unexported fields
}

Jump to

Keyboard shortcuts

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