mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-06-30 09:13:29 +00:00
utils: Remove code duplication
Replace the two versions of `makeRuntimeConfigFileData()` with a single `MakeRuntimeConfigFileData()` in a new `katatestutils` package and a new `katautils.GetDefaultHypervisorConfig()` to query the default hypervisor details. This isn't ideal but a new package had to be created to avoid circular dependencies. It was also required since test code cannot be exported from a package. Signed-off-by: James O. D. Hunt <james.o.hunt@intel.com>
This commit is contained in:
parent
ed248cef3b
commit
87d91710b9
@ -24,8 +24,7 @@ import (
|
|||||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
|
|
||||||
"strconv"
|
"github.com/kata-containers/runtime/pkg/katatestutils"
|
||||||
|
|
||||||
"github.com/kata-containers/runtime/pkg/katautils"
|
"github.com/kata-containers/runtime/pkg/katautils"
|
||||||
"github.com/kata-containers/runtime/virtcontainers/pkg/oci"
|
"github.com/kata-containers/runtime/virtcontainers/pkg/oci"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@ -36,12 +35,6 @@ const testShimVersion = "shim version 0.1"
|
|||||||
const testNetmonVersion = "netmon version 0.1"
|
const testNetmonVersion = "netmon version 0.1"
|
||||||
const testHypervisorVersion = "QEMU emulator version 2.7.0+git.741f430a96-6.1, Copyright (c) 2003-2016 Fabrice Bellard and the QEMU Project developers"
|
const testHypervisorVersion = "QEMU emulator version 2.7.0+git.741f430a96-6.1, Copyright (c) 2003-2016 Fabrice Bellard and the QEMU Project developers"
|
||||||
|
|
||||||
const defaultVCPUCount uint32 = 1
|
|
||||||
const defaultMaxVCPUCount uint32 = 0
|
|
||||||
const defaultMemSize uint32 = 2048 // MiB
|
|
||||||
const defaultMsize9p uint32 = 8192
|
|
||||||
const defaultGuestHookPath string = ""
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
hypervisorDebug = false
|
hypervisorDebug = false
|
||||||
proxyDebug = false
|
proxyDebug = false
|
||||||
@ -81,47 +74,6 @@ func createConfig(configPath string, fileData string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeRuntimeConfigFileData(hypervisor, hypervisorPath, kernelPath, imagePath, kernelParams, machineType, shimPath, proxyPath, netmonPath, logPath string, disableBlock bool, blockDeviceDriver string, enableIOThreads bool, hotplugVFIOOnRootBus, disableNewNetNs bool) string {
|
|
||||||
return `
|
|
||||||
# Runtime configuration file
|
|
||||||
|
|
||||||
[hypervisor.` + hypervisor + `]
|
|
||||||
path = "` + hypervisorPath + `"
|
|
||||||
kernel = "` + kernelPath + `"
|
|
||||||
block_device_driver = "` + blockDeviceDriver + `"
|
|
||||||
kernel_params = "` + kernelParams + `"
|
|
||||||
image = "` + imagePath + `"
|
|
||||||
machine_type = "` + machineType + `"
|
|
||||||
default_vcpus = ` + strconv.FormatUint(uint64(defaultVCPUCount), 10) + `
|
|
||||||
default_maxvcpus = ` + strconv.FormatUint(uint64(defaultMaxVCPUCount), 10) + `
|
|
||||||
default_memory = ` + strconv.FormatUint(uint64(defaultMemSize), 10) + `
|
|
||||||
disable_block_device_use = ` + strconv.FormatBool(disableBlock) + `
|
|
||||||
enable_iothreads = ` + strconv.FormatBool(enableIOThreads) + `
|
|
||||||
hotplug_vfio_on_root_bus = ` + strconv.FormatBool(hotplugVFIOOnRootBus) + `
|
|
||||||
msize_9p = ` + strconv.FormatUint(uint64(defaultMsize9p), 10) + `
|
|
||||||
enable_debug = ` + strconv.FormatBool(hypervisorDebug) + `
|
|
||||||
guest_hook_path = "` + defaultGuestHookPath + `"
|
|
||||||
|
|
||||||
[proxy.kata]
|
|
||||||
enable_debug = ` + strconv.FormatBool(proxyDebug) + `
|
|
||||||
path = "` + proxyPath + `"
|
|
||||||
|
|
||||||
[shim.kata]
|
|
||||||
path = "` + shimPath + `"
|
|
||||||
enable_debug = ` + strconv.FormatBool(shimDebug) + `
|
|
||||||
|
|
||||||
[agent.kata]
|
|
||||||
|
|
||||||
[netmon]
|
|
||||||
path = "` + netmonPath + `"
|
|
||||||
enable_debug = ` + strconv.FormatBool(netmonDebug) + `
|
|
||||||
|
|
||||||
[runtime]
|
|
||||||
enable_debug = ` + strconv.FormatBool(runtimeDebug) + `
|
|
||||||
enable_tracing = ` + strconv.FormatBool(runtimeTrace) + `
|
|
||||||
disable_new_netns= ` + strconv.FormatBool(disableNewNetNs)
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeRuntimeConfig(prefixDir string) (configFile string, config oci.RuntimeConfig, err error) {
|
func makeRuntimeConfig(prefixDir string) (configFile string, config oci.RuntimeConfig, err error) {
|
||||||
const logPath = "/log/path"
|
const logPath = "/log/path"
|
||||||
hypervisorPath := filepath.Join(prefixDir, "hypervisor")
|
hypervisorPath := filepath.Join(prefixDir, "hypervisor")
|
||||||
@ -172,23 +124,38 @@ func makeRuntimeConfig(prefixDir string) (configFile string, config oci.RuntimeC
|
|||||||
return "", oci.RuntimeConfig{}, err
|
return "", oci.RuntimeConfig{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
runtimeConfig := makeRuntimeConfigFileData(
|
hypConfig := katautils.GetDefaultHypervisorConfig()
|
||||||
"qemu",
|
|
||||||
hypervisorPath,
|
configFileOptions := katatestutils.RuntimeConfigOptions{
|
||||||
kernelPath,
|
Hypervisor: "qemu",
|
||||||
imagePath,
|
HypervisorPath: hypervisorPath,
|
||||||
kernelParams,
|
KernelPath: kernelPath,
|
||||||
machineType,
|
ImagePath: imagePath,
|
||||||
shimPath,
|
KernelParams: kernelParams,
|
||||||
proxyPath,
|
MachineType: machineType,
|
||||||
netmonPath,
|
ShimPath: shimPath,
|
||||||
logPath,
|
ProxyPath: proxyPath,
|
||||||
disableBlock,
|
NetmonPath: netmonPath,
|
||||||
blockStorageDriver,
|
LogPath: logPath,
|
||||||
enableIOThreads,
|
DefaultGuestHookPath: hypConfig.GuestHookPath,
|
||||||
hotplugVFIOOnRootBus,
|
DisableBlock: disableBlock,
|
||||||
disableNewNetNs,
|
BlockDeviceDriver: blockStorageDriver,
|
||||||
)
|
EnableIOThreads: enableIOThreads,
|
||||||
|
HotplugVFIOOnRootBus: hotplugVFIOOnRootBus,
|
||||||
|
DisableNewNetNs: disableNewNetNs,
|
||||||
|
DefaultVCPUCount: hypConfig.NumVCPUs,
|
||||||
|
DefaultMaxVCPUCount: hypConfig.DefaultMaxVCPUs,
|
||||||
|
DefaultMemSize: hypConfig.MemorySize,
|
||||||
|
DefaultMsize9p: hypConfig.Msize9p,
|
||||||
|
HypervisorDebug: hypervisorDebug,
|
||||||
|
RuntimeDebug: runtimeDebug,
|
||||||
|
RuntimeTrace: runtimeTrace,
|
||||||
|
ProxyDebug: proxyDebug,
|
||||||
|
ShimDebug: shimDebug,
|
||||||
|
NetmonDebug: netmonDebug,
|
||||||
|
}
|
||||||
|
|
||||||
|
runtimeConfig := katatestutils.MakeRuntimeConfigFileData(configFileOptions)
|
||||||
|
|
||||||
configFile = path.Join(prefixDir, "runtime.toml")
|
configFile = path.Join(prefixDir, "runtime.toml")
|
||||||
err = createConfig(configFile, runtimeConfig)
|
err = createConfig(configFile, runtimeConfig)
|
||||||
|
87
pkg/katatestutils/utils.go
Normal file
87
pkg/katatestutils/utils.go
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
// Copyright (c) 2018-2019 Intel Corporation
|
||||||
|
// Copyright (c) 2018 HyperHQ Inc.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
|
||||||
|
package katatestutils
|
||||||
|
|
||||||
|
import "strconv"
|
||||||
|
|
||||||
|
type RuntimeConfigOptions struct {
|
||||||
|
Hypervisor string
|
||||||
|
HypervisorPath string
|
||||||
|
DefaultVCPUCount uint32
|
||||||
|
DefaultMaxVCPUCount uint32
|
||||||
|
DefaultMemSize uint32
|
||||||
|
DefaultMsize9p uint32
|
||||||
|
DefaultGuestHookPath string
|
||||||
|
KernelPath string
|
||||||
|
ImagePath string
|
||||||
|
KernelParams string
|
||||||
|
MachineType string
|
||||||
|
ShimPath string
|
||||||
|
ProxyPath string
|
||||||
|
NetmonPath string
|
||||||
|
LogPath string
|
||||||
|
BlockDeviceDriver string
|
||||||
|
AgentTraceMode string
|
||||||
|
AgentTraceType string
|
||||||
|
DisableBlock bool
|
||||||
|
EnableIOThreads bool
|
||||||
|
HotplugVFIOOnRootBus bool
|
||||||
|
DisableNewNetNs bool
|
||||||
|
HypervisorDebug bool
|
||||||
|
RuntimeDebug bool
|
||||||
|
RuntimeTrace bool
|
||||||
|
ProxyDebug bool
|
||||||
|
ShimDebug bool
|
||||||
|
NetmonDebug bool
|
||||||
|
AgentDebug bool
|
||||||
|
AgentTrace bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeRuntimeConfigFileData(config RuntimeConfigOptions) string {
|
||||||
|
return `
|
||||||
|
# Runtime configuration file
|
||||||
|
|
||||||
|
[hypervisor.` + config.Hypervisor + `]
|
||||||
|
path = "` + config.HypervisorPath + `"
|
||||||
|
kernel = "` + config.KernelPath + `"
|
||||||
|
block_device_driver = "` + config.BlockDeviceDriver + `"
|
||||||
|
kernel_params = "` + config.KernelParams + `"
|
||||||
|
image = "` + config.ImagePath + `"
|
||||||
|
machine_type = "` + config.MachineType + `"
|
||||||
|
default_vcpus = ` + strconv.FormatUint(uint64(config.DefaultVCPUCount), 10) + `
|
||||||
|
default_maxvcpus = ` + strconv.FormatUint(uint64(config.DefaultMaxVCPUCount), 10) + `
|
||||||
|
default_memory = ` + strconv.FormatUint(uint64(config.DefaultMemSize), 10) + `
|
||||||
|
disable_block_device_use = ` + strconv.FormatBool(config.DisableBlock) + `
|
||||||
|
enable_iothreads = ` + strconv.FormatBool(config.EnableIOThreads) + `
|
||||||
|
hotplug_vfio_on_root_bus = ` + strconv.FormatBool(config.HotplugVFIOOnRootBus) + `
|
||||||
|
msize_9p = ` + strconv.FormatUint(uint64(config.DefaultMsize9p), 10) + `
|
||||||
|
enable_debug = ` + strconv.FormatBool(config.HypervisorDebug) + `
|
||||||
|
guest_hook_path = "` + config.DefaultGuestHookPath + `"
|
||||||
|
|
||||||
|
[proxy.kata]
|
||||||
|
enable_debug = ` + strconv.FormatBool(config.ProxyDebug) + `
|
||||||
|
path = "` + config.ProxyPath + `"
|
||||||
|
|
||||||
|
[shim.kata]
|
||||||
|
path = "` + config.ShimPath + `"
|
||||||
|
enable_debug = ` + strconv.FormatBool(config.ShimDebug) + `
|
||||||
|
|
||||||
|
[agent.kata]
|
||||||
|
enable_debug = ` + strconv.FormatBool(config.AgentDebug) + `
|
||||||
|
enable_tracing = ` + strconv.FormatBool(config.AgentTrace) + `
|
||||||
|
trace_mode = "` + config.AgentTraceMode + `"` + `
|
||||||
|
trace_type = "` + config.AgentTraceType + `"` + `
|
||||||
|
|
||||||
|
[netmon]
|
||||||
|
path = "` + config.NetmonPath + `"
|
||||||
|
enable_debug = ` + strconv.FormatBool(config.NetmonDebug) + `
|
||||||
|
|
||||||
|
[runtime]
|
||||||
|
enable_debug = ` + strconv.FormatBool(config.RuntimeDebug) + `
|
||||||
|
enable_tracing = ` + strconv.FormatBool(config.RuntimeTrace) + `
|
||||||
|
disable_new_netns= ` + strconv.FormatBool(config.DisableNewNetNs)
|
||||||
|
}
|
@ -752,10 +752,8 @@ func updateRuntimeConfig(configPath string, tomlConf tomlConfig, config *oci.Run
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func initConfig() (config oci.RuntimeConfig, err error) {
|
func GetDefaultHypervisorConfig() vc.HypervisorConfig {
|
||||||
var defaultAgentConfig interface{}
|
return vc.HypervisorConfig{
|
||||||
|
|
||||||
defaultHypervisorConfig := vc.HypervisorConfig{
|
|
||||||
HypervisorPath: defaultHypervisorPath,
|
HypervisorPath: defaultHypervisorPath,
|
||||||
KernelPath: defaultKernelPath,
|
KernelPath: defaultKernelPath,
|
||||||
ImagePath: defaultImagePath,
|
ImagePath: defaultImagePath,
|
||||||
@ -767,6 +765,7 @@ func initConfig() (config oci.RuntimeConfig, err error) {
|
|||||||
DefaultMaxVCPUs: defaultMaxVCPUCount,
|
DefaultMaxVCPUs: defaultMaxVCPUCount,
|
||||||
MemorySize: defaultMemSize,
|
MemorySize: defaultMemSize,
|
||||||
MemOffset: defaultMemOffset,
|
MemOffset: defaultMemOffset,
|
||||||
|
DisableBlockDeviceUse: defaultDisableBlockDeviceUse,
|
||||||
DefaultBridges: defaultBridgesCount,
|
DefaultBridges: defaultBridgesCount,
|
||||||
MemPrealloc: defaultEnableMemPrealloc,
|
MemPrealloc: defaultEnableMemPrealloc,
|
||||||
HugePages: defaultEnableHugePages,
|
HugePages: defaultEnableHugePages,
|
||||||
@ -782,6 +781,10 @@ func initConfig() (config oci.RuntimeConfig, err error) {
|
|||||||
HotplugVFIOOnRootBus: defaultHotplugVFIOOnRootBus,
|
HotplugVFIOOnRootBus: defaultHotplugVFIOOnRootBus,
|
||||||
GuestHookPath: defaultGuestHookPath,
|
GuestHookPath: defaultGuestHookPath,
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func initConfig() (config oci.RuntimeConfig, err error) {
|
||||||
|
var defaultAgentConfig interface{}
|
||||||
|
|
||||||
err = config.InterNetworkModel.SetModel(defaultInterNetworkingModel)
|
err = config.InterNetworkModel.SetModel(defaultInterNetworkingModel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -792,7 +795,7 @@ func initConfig() (config oci.RuntimeConfig, err error) {
|
|||||||
|
|
||||||
config = oci.RuntimeConfig{
|
config = oci.RuntimeConfig{
|
||||||
HypervisorType: defaultHypervisor,
|
HypervisorType: defaultHypervisor,
|
||||||
HypervisorConfig: defaultHypervisorConfig,
|
HypervisorConfig: GetDefaultHypervisorConfig(),
|
||||||
AgentType: defaultAgent,
|
AgentType: defaultAgent,
|
||||||
AgentConfig: defaultAgentConfig,
|
AgentConfig: defaultAgentConfig,
|
||||||
ProxyType: defaultProxy,
|
ProxyType: defaultProxy,
|
||||||
|
@ -15,11 +15,11 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
goruntime "runtime"
|
goruntime "runtime"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/kata-containers/runtime/pkg/katatestutils"
|
||||||
vc "github.com/kata-containers/runtime/virtcontainers"
|
vc "github.com/kata-containers/runtime/virtcontainers"
|
||||||
"github.com/kata-containers/runtime/virtcontainers/pkg/oci"
|
"github.com/kata-containers/runtime/virtcontainers/pkg/oci"
|
||||||
"github.com/kata-containers/runtime/virtcontainers/utils"
|
"github.com/kata-containers/runtime/virtcontainers/utils"
|
||||||
@ -30,6 +30,7 @@ var (
|
|||||||
hypervisorDebug = false
|
hypervisorDebug = false
|
||||||
proxyDebug = false
|
proxyDebug = false
|
||||||
runtimeDebug = false
|
runtimeDebug = false
|
||||||
|
runtimeTrace = false
|
||||||
shimDebug = false
|
shimDebug = false
|
||||||
netmonDebug = false
|
netmonDebug = false
|
||||||
)
|
)
|
||||||
@ -43,46 +44,6 @@ type testRuntimeConfig struct {
|
|||||||
LogPath string
|
LogPath string
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeRuntimeConfigFileData(hypervisor, hypervisorPath, kernelPath, imagePath, kernelParams, machineType, shimPath, proxyPath, netmonPath, logPath string, disableBlock bool, blockDeviceDriver string, enableIOThreads bool, hotplugVFIOOnRootBus, disableNewNetNs bool) string {
|
|
||||||
return `
|
|
||||||
# Runtime configuration file
|
|
||||||
|
|
||||||
[hypervisor.` + hypervisor + `]
|
|
||||||
path = "` + hypervisorPath + `"
|
|
||||||
kernel = "` + kernelPath + `"
|
|
||||||
block_device_driver = "` + blockDeviceDriver + `"
|
|
||||||
kernel_params = "` + kernelParams + `"
|
|
||||||
image = "` + imagePath + `"
|
|
||||||
machine_type = "` + machineType + `"
|
|
||||||
default_vcpus = ` + strconv.FormatUint(uint64(defaultVCPUCount), 10) + `
|
|
||||||
default_maxvcpus = ` + strconv.FormatUint(uint64(defaultMaxVCPUCount), 10) + `
|
|
||||||
default_memory = ` + strconv.FormatUint(uint64(defaultMemSize), 10) + `
|
|
||||||
disable_block_device_use = ` + strconv.FormatBool(disableBlock) + `
|
|
||||||
enable_iothreads = ` + strconv.FormatBool(enableIOThreads) + `
|
|
||||||
hotplug_vfio_on_root_bus = ` + strconv.FormatBool(hotplugVFIOOnRootBus) + `
|
|
||||||
msize_9p = ` + strconv.FormatUint(uint64(defaultMsize9p), 10) + `
|
|
||||||
enable_debug = ` + strconv.FormatBool(hypervisorDebug) + `
|
|
||||||
guest_hook_path = "` + defaultGuestHookPath + `"
|
|
||||||
|
|
||||||
[proxy.kata]
|
|
||||||
enable_debug = ` + strconv.FormatBool(proxyDebug) + `
|
|
||||||
path = "` + proxyPath + `"
|
|
||||||
|
|
||||||
[shim.kata]
|
|
||||||
path = "` + shimPath + `"
|
|
||||||
enable_debug = ` + strconv.FormatBool(shimDebug) + `
|
|
||||||
|
|
||||||
[agent.kata]
|
|
||||||
|
|
||||||
[netmon]
|
|
||||||
path = "` + netmonPath + `"
|
|
||||||
enable_debug = ` + strconv.FormatBool(netmonDebug) + `
|
|
||||||
|
|
||||||
[runtime]
|
|
||||||
enable_debug = ` + strconv.FormatBool(runtimeDebug) + `
|
|
||||||
disable_new_netns= ` + strconv.FormatBool(disableNewNetNs)
|
|
||||||
}
|
|
||||||
|
|
||||||
func createConfig(configPath string, fileData string) error {
|
func createConfig(configPath string, fileData string) error {
|
||||||
|
|
||||||
err := ioutil.WriteFile(configPath, []byte(fileData), testFileMode)
|
err := ioutil.WriteFile(configPath, []byte(fileData), testFileMode)
|
||||||
@ -121,7 +82,36 @@ func createAllRuntimeConfigFiles(dir, hypervisor string) (config testRuntimeConf
|
|||||||
hotplugVFIOOnRootBus := true
|
hotplugVFIOOnRootBus := true
|
||||||
disableNewNetNs := false
|
disableNewNetNs := false
|
||||||
|
|
||||||
runtimeConfigFileData := makeRuntimeConfigFileData(hypervisor, hypervisorPath, kernelPath, imagePath, kernelParams, machineType, shimPath, proxyPath, netmonPath, logPath, disableBlockDevice, blockDeviceDriver, enableIOThreads, hotplugVFIOOnRootBus, disableNewNetNs)
|
configFileOptions := katatestutils.RuntimeConfigOptions{
|
||||||
|
Hypervisor: "qemu",
|
||||||
|
HypervisorPath: hypervisorPath,
|
||||||
|
KernelPath: kernelPath,
|
||||||
|
ImagePath: imagePath,
|
||||||
|
KernelParams: kernelParams,
|
||||||
|
MachineType: machineType,
|
||||||
|
ShimPath: shimPath,
|
||||||
|
ProxyPath: proxyPath,
|
||||||
|
NetmonPath: netmonPath,
|
||||||
|
LogPath: logPath,
|
||||||
|
DefaultGuestHookPath: defaultGuestHookPath,
|
||||||
|
DisableBlock: disableBlockDevice,
|
||||||
|
BlockDeviceDriver: blockDeviceDriver,
|
||||||
|
EnableIOThreads: enableIOThreads,
|
||||||
|
HotplugVFIOOnRootBus: hotplugVFIOOnRootBus,
|
||||||
|
DisableNewNetNs: disableNewNetNs,
|
||||||
|
DefaultVCPUCount: defaultVCPUCount,
|
||||||
|
DefaultMaxVCPUCount: defaultMaxVCPUCount,
|
||||||
|
DefaultMemSize: defaultMemSize,
|
||||||
|
DefaultMsize9p: defaultMsize9p,
|
||||||
|
HypervisorDebug: hypervisorDebug,
|
||||||
|
RuntimeDebug: runtimeDebug,
|
||||||
|
RuntimeTrace: runtimeTrace,
|
||||||
|
ProxyDebug: proxyDebug,
|
||||||
|
ShimDebug: shimDebug,
|
||||||
|
NetmonDebug: netmonDebug,
|
||||||
|
}
|
||||||
|
|
||||||
|
runtimeConfigFileData := katatestutils.MakeRuntimeConfigFileData(configFileOptions)
|
||||||
|
|
||||||
configPath := path.Join(dir, "runtime.toml")
|
configPath := path.Join(dir, "runtime.toml")
|
||||||
err = createConfig(configPath, runtimeConfigFileData)
|
err = createConfig(configPath, runtimeConfigFileData)
|
||||||
|
Loading…
Reference in New Issue
Block a user