Merge "Disable all non-essential openstack services in a kubernetes config"
This commit is contained in:
commit
ed03cb905f
|
@ -1,2 +1,2 @@
|
|||
SRC_DIR="src"
|
||||
TIS_PATCH_VER=62
|
||||
TIS_PATCH_VER=63
|
||||
|
|
|
@ -25,7 +25,6 @@ neutron::agents::ml2::sriov::polling_interval: 5
|
|||
|
||||
|
||||
# nova
|
||||
nova::compute::enabled: true
|
||||
nova::compute::manage_service: false
|
||||
nova::compute::config_drive_format: 'iso9660'
|
||||
nova::compute::instance_usage_audit: true
|
||||
|
|
|
@ -310,7 +310,6 @@ ceilometer::keystone::auth::configure_endpoint: false
|
|||
|
||||
|
||||
# gnocchi
|
||||
gnocchi::api::enabled: true
|
||||
gnocchi::api::service_name: 'openstack-gnocchi-api'
|
||||
gnocchi::api::enable_proxy_headers_parsing: true
|
||||
gnocchi::metricd::enabled: false
|
||||
|
|
|
@ -10,6 +10,7 @@ class openstack::ceilometer {
|
|||
include ::platform::amqp::params
|
||||
include ::platform::params
|
||||
include ::openstack::ceilometer::params
|
||||
include ::platform::kubernetes::params
|
||||
|
||||
class { '::ceilometer':
|
||||
rabbit_use_ssl => $::platform::amqp::params::ssl_enabled,
|
||||
|
@ -21,7 +22,8 @@ class openstack::ceilometer {
|
|||
$::platform::params::init_keystone) {
|
||||
include ::ceilometer::keystone::auth
|
||||
|
||||
if $::platform::params::distributed_cloud_role != 'systemcontroller' {
|
||||
if ($::platform::params::distributed_cloud_role != 'systemcontroller' and
|
||||
$::platform::kubernetes::params::enabled != true) {
|
||||
include ::openstack::gnocchi::params
|
||||
|
||||
Keystone_endpoint["${::openstack::gnocchi::params::region_name}/gnocchi::metric"] ->
|
||||
|
@ -199,6 +201,7 @@ class openstack::ceilometer::polling (
|
|||
$volume_polling_interval = 600,
|
||||
) {
|
||||
include ::platform::params
|
||||
include ::platform::kubernetes::params
|
||||
|
||||
file { "/etc/ceilometer/polling.yaml":
|
||||
ensure => 'present',
|
||||
|
@ -215,7 +218,8 @@ class openstack::ceilometer::polling (
|
|||
$central_namespace = false
|
||||
}
|
||||
|
||||
if str2bool($::disable_compute_services) {
|
||||
if (str2bool($::disable_compute_services) or
|
||||
$::platform::kubernetes::params::enabled) {
|
||||
$agent_enable = false
|
||||
$compute_namespace = false
|
||||
|
||||
|
|
|
@ -193,7 +193,10 @@ class openstack::neutron::server {
|
|||
class openstack::neutron::agents
|
||||
inherits ::openstack::neutron::params {
|
||||
|
||||
if str2bool($::disable_compute_services) {
|
||||
include ::platform::kubernetes::params
|
||||
|
||||
if (str2bool($::disable_compute_services) or
|
||||
$::platform::kubernetes::params::enabled) {
|
||||
$pmon_ensure = absent
|
||||
|
||||
class {'::neutron::agents::l3':
|
||||
|
|
|
@ -672,8 +672,12 @@ class openstack::nova::compute::pci
|
|||
|
||||
|
||||
class openstack::nova::compute::reload {
|
||||
exec { 'pmon-restart-nova-compute':
|
||||
command => "pmon-restart nova-compute",
|
||||
include ::platform::kubernetes::params
|
||||
|
||||
if $::platform::kubernetes::params::enabled != true {
|
||||
exec { 'pmon-restart-nova-compute':
|
||||
command => "pmon-restart nova-compute",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -276,4 +276,11 @@ class platform::kubernetes::worker
|
|||
Class['::platform::kubernetes::kubeadm'] ->
|
||||
Class['::platform::kubernetes::worker::init']
|
||||
}
|
||||
|
||||
if $enabled {
|
||||
file { "/var/run/.disable_compute_services":
|
||||
ensure => file,
|
||||
replace => no,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -187,12 +187,12 @@ class platform::sm
|
|||
|
||||
# Cinder
|
||||
include ::openstack::cinder::params
|
||||
$cinder_service_enabled = $::openstack::cinder::params::service_enabled
|
||||
$cinder_region_name = $::openstack::cinder::params::region_name
|
||||
$cinder_ip_param_ip = $::openstack::cinder::params::cinder_address
|
||||
$cinder_backends = $::openstack::cinder::params::enabled_backends
|
||||
$cinder_drbd_resource = $::openstack::cinder::params::drbd_resource
|
||||
$cinder_vg_name = $::openstack::cinder::params::cinder_vg_name
|
||||
$cinder_service_enabled = $::openstack::cinder::params::service_enabled
|
||||
|
||||
# Glance
|
||||
include ::openstack::glance::params
|
||||
|
@ -201,16 +201,13 @@ class platform::sm
|
|||
|
||||
# Murano
|
||||
include ::openstack::murano::params
|
||||
$murano_configured = $::openstack::murano::params::service_enabled
|
||||
$disable_murano_agent = $::openstack::murano::params::disable_murano_agent
|
||||
|
||||
# Magnum
|
||||
include ::openstack::magnum::params
|
||||
$magnum_configured = $::openstack::magnum::params::service_enabled
|
||||
|
||||
# Ironic
|
||||
include ::openstack::ironic::params
|
||||
$ironic_configured = $::openstack::ironic::params::service_enabled
|
||||
$ironic_tftp_ip = $::openstack::ironic::params::tftp_server
|
||||
$ironic_controller_0_nic = $::openstack::ironic::params::controller_0_if
|
||||
$ironic_controller_1_nic = $::openstack::ironic::params::controller_1_if
|
||||
|
@ -222,6 +219,15 @@ class platform::sm
|
|||
$ceph_configured = $::platform::ceph::params::service_enabled
|
||||
$rgw_configured = $::platform::ceph::params::rgw_enabled
|
||||
|
||||
# Gnocchi
|
||||
include ::openstack::gnocchi::params
|
||||
|
||||
# AODH
|
||||
include ::openstack::aodh::params
|
||||
|
||||
# Panko
|
||||
include ::openstack::panko::params
|
||||
|
||||
if $system_mode == 'simplex' {
|
||||
$hostunit = '0'
|
||||
$management_my_unit_ip = $::platform::network::mgmt::params::controller0_address
|
||||
|
@ -264,6 +270,27 @@ class platform::sm
|
|||
shell => '/bin/sh'
|
||||
}
|
||||
|
||||
# Workaround for the time being to prevent SM from enabling the openstack
|
||||
# services when kubernetes is enabled to avoid making changes to individual
|
||||
# openstack manifests
|
||||
if $kubernetes_enabled {
|
||||
$heat_service_enabled = false
|
||||
$murano_configured = false
|
||||
$ironic_configured = false
|
||||
$magnum_configured = false
|
||||
$gnocchi_enabled = false
|
||||
$aodh_enabled = false
|
||||
$panko_enabled = false
|
||||
} else {
|
||||
$heat_service_enabled = $::openstack::heat::params::service_enabled
|
||||
$murano_configured = $::openstack::murano::params::service_enabled
|
||||
$ironic_configured = $::openstack::ironic::params::service_enabled
|
||||
$magnum_configured = $::openstack::magnum::params::service_enabled
|
||||
$gnocchi_enabled = $::openstack::gnocchi::params::service_enabled
|
||||
$aodh_enabled = $::openstack::aodh::params::service_enabled
|
||||
$panko_enabled = $::openstack::panko::params::service_enabled
|
||||
}
|
||||
|
||||
if $system_mode == 'simplex' {
|
||||
exec { 'Deprovision oam-ip service group member':
|
||||
command => "sm-deprovision service-group-member oam-services oam-ip",
|
||||
|
@ -488,6 +515,9 @@ class platform::sm
|
|||
}
|
||||
}
|
||||
}
|
||||
} elsif $kubernetes_enabled {
|
||||
$configure_keystone = true
|
||||
$configure_glance = false
|
||||
} else {
|
||||
$configure_keystone = true
|
||||
$configure_glance = true
|
||||
|
@ -521,6 +551,21 @@ class platform::sm
|
|||
exec { 'Provision OpenStack - Glance API (service)':
|
||||
command => "sm-provision service glance-api",
|
||||
}
|
||||
} else {
|
||||
# Deprovision Glance API and Glance Registry incase of a kubernetes config
|
||||
exec { 'Deprovision OpenStack - Glance Registry (service-group-member)':
|
||||
command => "sm-deprovision service-group-member cloud-services glance-registry",
|
||||
} ->
|
||||
exec { 'Deprovision OpenStack - Glance Registry(service)':
|
||||
command => "sm-deprovision service glance-registry",
|
||||
}
|
||||
|
||||
exec { 'Deprovision OpenStack - Glance API (service-group-member)':
|
||||
command => "sm-deprovision service-group-member cloud-services glance-api",
|
||||
} ->
|
||||
exec { 'Deprovision OpenStack - Glance API(service)':
|
||||
command => "sm-deprovision service glance-api",
|
||||
}
|
||||
}
|
||||
|
||||
if $cinder_service_enabled {
|
||||
|
@ -666,6 +711,8 @@ class platform::sm
|
|||
} else {
|
||||
$configure_neturon = true
|
||||
}
|
||||
} elsif $kubernetes_enabled {
|
||||
$configure_neturon = false
|
||||
} else {
|
||||
$configure_neturon = true
|
||||
}
|
||||
|
@ -676,35 +723,114 @@ class platform::sm
|
|||
}
|
||||
}
|
||||
|
||||
exec { 'Configure OpenStack - Nova API':
|
||||
command => "sm-configure service_instance nova-api nova-api \"config=/etc/nova/nova.conf,user=root,os_username=${os_username},os_project_name=${os_project_name},os_user_domain_name=${os_user_domain_name},os_project_domain_name=${os_project_domain_name},keystone_get_token_url=${os_auth_url}/tokens\"",
|
||||
if $kubernetes_enabled != true {
|
||||
|
||||
exec { 'Configure OpenStack - Nova API':
|
||||
command => "sm-configure service_instance nova-api nova-api \"config=/etc/nova/nova.conf,user=root,os_username=${os_username},os_project_name=${os_project_name},os_user_domain_name=${os_user_domain_name},os_project_domain_name=${os_project_domain_name},keystone_get_token_url=${os_auth_url}/tokens\"",
|
||||
}
|
||||
|
||||
exec { 'Configure OpenStack - Nova Placement API':
|
||||
command => "sm-configure service_instance nova-placement-api nova-placement-api \"config=/etc/nova/nova.conf,user=root,os_username=${os_username},os_project_name=${os_project_name},os_user_domain_name=${os_user_domain_name},os_project_domain_name=${os_project_domain_name},keystone_get_token_url=${os_auth_url}/tokens,host=${mgmt_ip_param_ip}\"",
|
||||
}
|
||||
|
||||
exec { 'Configure OpenStack - Nova Scheduler':
|
||||
command => "sm-configure service_instance nova-scheduler nova-scheduler \"config=/etc/nova/nova.conf,database_server_port=${db_server_port},amqp_server_port=${amqp_server_port}\"",
|
||||
}
|
||||
|
||||
exec { 'Configure OpenStack - Nova Conductor':
|
||||
command => "sm-configure service_instance nova-conductor nova-conductor \"config=/etc/nova/nova.conf,database_server_port=${db_server_port},amqp_server_port=${amqp_server_port}\"",
|
||||
}
|
||||
|
||||
exec { 'Configure OpenStack - Nova Console Authorization':
|
||||
command => "sm-configure service_instance nova-console-auth nova-console-auth \"config=/etc/nova/nova.conf,user=root,database_server_port=${db_server_port},amqp_server_port=${amqp_server_port}\"",
|
||||
}
|
||||
|
||||
exec { 'Configure OpenStack - Nova NoVNC':
|
||||
command => "sm-configure service_instance nova-novnc nova-novnc \"config=/etc/nova/nova.conf,user=root,console_port=${novnc_console_port}\"",
|
||||
}
|
||||
|
||||
exec { 'Configure OpenStack - Ceilometer Agent Notification':
|
||||
command => "sm-configure service_instance ceilometer-agent-notification ceilometer-agent-notification \"config=/etc/ceilometer/ceilometer.conf\"",
|
||||
}
|
||||
} else {
|
||||
# Deprovision Openstack services if Kubernetes Config is enabled
|
||||
|
||||
# Deprovision Nova Services
|
||||
exec { 'Deprovision OpenStack - Nova API (service-group-member)':
|
||||
command => "sm-deprovision service-group-member cloud-services nova-api",
|
||||
} ->
|
||||
exec { 'Deprovision OpenStack - Nova API(service)':
|
||||
command => "sm-deprovision service nova-api",
|
||||
}
|
||||
|
||||
exec { 'Deprovision OpenStack - Nova API Proxy (service-group-member)':
|
||||
command => "sm-deprovision service-group-member cloud-services nova-api-proxy",
|
||||
} ->
|
||||
exec { 'Deprovision OpenStack - Nova API Proxy(service)':
|
||||
command => "sm-deprovision service nova-api-proxy",
|
||||
}
|
||||
|
||||
exec { 'Deprovision OpenStack - Nova Placement API (service-group-member)':
|
||||
command => "sm-deprovision service-group-member cloud-services nova-placement-api",
|
||||
} ->
|
||||
exec { 'Deprovision OpenStack - Nova Placement API(service)':
|
||||
command => "sm-deprovision service nova-placement-api",
|
||||
}
|
||||
|
||||
exec { 'Deprovision OpenStack - Nova Scheduler (service-group-member)':
|
||||
command => "sm-deprovision service-group-member cloud-services nova-scheduler",
|
||||
} ->
|
||||
exec { 'Deprovision OpenStack - Nova Scheduler(service)':
|
||||
command => "sm-deprovision service nova-scheduler",
|
||||
}
|
||||
|
||||
exec { 'Deprovision OpenStack - Nova Conductor (service-group-member)':
|
||||
command => "sm-deprovision service-group-member cloud-services nova-conductor",
|
||||
} ->
|
||||
exec { 'Deprovision OpenStack - Nova Conductor(service)':
|
||||
command => "sm-deprovision service nova-conductor",
|
||||
}
|
||||
|
||||
exec { 'Deprovision OpenStack - Nova Console Auth (service-group-member)':
|
||||
command => "sm-deprovision service-group-member cloud-services nova-console-auth",
|
||||
} ->
|
||||
exec { 'Deprovision OpenStack - Nova Console Auth(service)':
|
||||
command => "sm-deprovision service nova-console-auth",
|
||||
}
|
||||
|
||||
exec { 'Deprovision OpenStack - Nova NoVNC (service-group-member)':
|
||||
command => "sm-deprovision service-group-member cloud-services nova-novnc",
|
||||
} ->
|
||||
exec { 'Deprovision OpenStack - Nova NoVNC(service)':
|
||||
command => "sm-deprovision service nova-novnc",
|
||||
}
|
||||
|
||||
# Deprovision Celiometer
|
||||
exec { 'Deprovision OpenStack - Ceilometer Agent Notification (service-group-member)':
|
||||
command => "sm-deprovision service-group-member cloud-services ceilometer-agent-notification",
|
||||
} ->
|
||||
exec { 'Deprovision OpenStack - Ceilometer Agent Notification(service)':
|
||||
command => "sm-deprovision service ceilometer-agent-notification",
|
||||
}
|
||||
|
||||
# Deprovision Neutron Server
|
||||
exec { 'Deprovision OpenStack - Neutron Server (service-group-member)':
|
||||
command => "sm-deprovision service-group-member cloud-services neutron-server",
|
||||
} ->
|
||||
exec { 'Deprovision OpenStack - Neutron Server (service)':
|
||||
command => "sm-deprovision service neutron-server",
|
||||
}
|
||||
|
||||
# Deprovision Horizon
|
||||
exec { 'Deprovision OpenStack - Horizon (service-group-member)':
|
||||
command => "sm-deprovision service-group-member web-services horizon",
|
||||
} ->
|
||||
exec { 'Deprovision OpenStack - Horizon(service)':
|
||||
command => "sm-deprovision service horizon",
|
||||
}
|
||||
}
|
||||
|
||||
exec { 'Configure OpenStack - Nova Placement API':
|
||||
command => "sm-configure service_instance nova-placement-api nova-placement-api \"config=/etc/nova/nova.conf,user=root,os_username=${os_username},os_project_name=${os_project_name},os_user_domain_name=${os_user_domain_name},os_project_domain_name=${os_project_domain_name},keystone_get_token_url=${os_auth_url}/tokens,host=${mgmt_ip_param_ip}\"",
|
||||
}
|
||||
|
||||
exec { 'Configure OpenStack - Nova Scheduler':
|
||||
command => "sm-configure service_instance nova-scheduler nova-scheduler \"config=/etc/nova/nova.conf,database_server_port=${db_server_port},amqp_server_port=${amqp_server_port}\"",
|
||||
}
|
||||
|
||||
exec { 'Configure OpenStack - Nova Conductor':
|
||||
command => "sm-configure service_instance nova-conductor nova-conductor \"config=/etc/nova/nova.conf,database_server_port=${db_server_port},amqp_server_port=${amqp_server_port}\"",
|
||||
}
|
||||
|
||||
exec { 'Configure OpenStack - Nova Console Authorization':
|
||||
command => "sm-configure service_instance nova-console-auth nova-console-auth \"config=/etc/nova/nova.conf,user=root,database_server_port=${db_server_port},amqp_server_port=${amqp_server_port}\"",
|
||||
}
|
||||
|
||||
exec { 'Configure OpenStack - Nova NoVNC':
|
||||
command => "sm-configure service_instance nova-novnc nova-novnc \"config=/etc/nova/nova.conf,user=root,console_port=${novnc_console_port}\"",
|
||||
}
|
||||
|
||||
exec { 'Configure OpenStack - Ceilometer Agent Notification':
|
||||
command => "sm-configure service_instance ceilometer-agent-notification ceilometer-agent-notification \"config=/etc/ceilometer/ceilometer.conf\"",
|
||||
}
|
||||
|
||||
if $::openstack::heat::params::service_enabled {
|
||||
if $heat_service_enabled {
|
||||
exec { 'Configure OpenStack - Heat Engine':
|
||||
command => "sm-configure service_instance heat-engine heat-engine \"config=/etc/heat/heat.conf,user=root,database_server_port=${db_server_port},amqp_server_port=${amqp_server_port}\"",
|
||||
}
|
||||
|
@ -759,7 +885,7 @@ class platform::sm
|
|||
}
|
||||
|
||||
# Gnocchi
|
||||
if $::openstack::gnocchi::params::service_enabled {
|
||||
if $gnocchi_enabled {
|
||||
|
||||
exec { 'Configure OpenStack - Gnocchi API':
|
||||
command => "sm-configure service_instance gnocchi-api gnocchi-api \"config=/etc/gnocchi/gnocchi.conf\"",
|
||||
|
@ -787,9 +913,9 @@ class platform::sm
|
|||
command => "sm-deprovision service gnocchi-metricd",
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# AODH
|
||||
if $::openstack::aodh::params::service_enabled {
|
||||
if $aodh_enabled {
|
||||
|
||||
exec { 'Configure OpenStack - AODH API':
|
||||
command => "sm-configure service_instance aodh-api aodh-api \"config=/etc/aodh/aodh.conf\"",
|
||||
|
@ -845,7 +971,7 @@ class platform::sm
|
|||
}
|
||||
|
||||
# Panko
|
||||
if $::openstack::panko::params::service_enabled {
|
||||
if $panko_enabled {
|
||||
exec { 'Configure OpenStack - Panko API':
|
||||
command => "sm-configure service_instance panko-api panko-api \"config=/etc/panko/panko.conf\"",
|
||||
}
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
SRC_DIR="sysinv"
|
||||
TIS_PATCH_VER=280
|
||||
TIS_PATCH_VER=281
|
||||
|
|
|
@ -4980,18 +4980,19 @@ class HostController(rest.RestController):
|
|||
|
||||
# Check whether a restore was properly completed
|
||||
self._semantic_check_restore_complete(ihost)
|
||||
# Disable compute unlock checks in a kubernetes config
|
||||
if not utils.is_kubernetes_config():
|
||||
# sdn configuration check
|
||||
self._semantic_check_sdn_attributes(ihost)
|
||||
|
||||
# sdn configuration check
|
||||
self._semantic_check_sdn_attributes(ihost)
|
||||
# check whether data route gateways are reachable
|
||||
self._semantic_check_data_routes(ihost)
|
||||
|
||||
# check whether data route gateways are reachable
|
||||
self._semantic_check_data_routes(ihost)
|
||||
|
||||
# check whether data interfaces have been configured
|
||||
self._semantic_check_data_interfaces(ihost)
|
||||
self._semantic_check_data_addresses(ihost)
|
||||
self._semantic_check_data_vrs_attributes(ihost)
|
||||
self._semantic_check_data_vrs_interfaces(ihost)
|
||||
# check whether data interfaces have been configured
|
||||
self._semantic_check_data_interfaces(ihost)
|
||||
self._semantic_check_data_addresses(ihost)
|
||||
self._semantic_check_data_vrs_attributes(ihost)
|
||||
self._semantic_check_data_vrs_interfaces(ihost)
|
||||
|
||||
# check if the platform reserved memory is valid
|
||||
ihost_inodes = pecan.request.dbapi.inode_get_by_ihost(ihost['uuid'])
|
||||
|
|
|
@ -566,6 +566,11 @@ class CinderPuppet(openstack.OpenstackBasePuppet):
|
|||
# Update the params for the external SANs
|
||||
config.update(self._get_service_parameter_config(is_service_enabled,
|
||||
enabled_backends))
|
||||
|
||||
# Disable cinder services if kubernetes is enabled
|
||||
if self._kubernetes_enabled():
|
||||
is_service_enabled = False
|
||||
|
||||
config.update({
|
||||
'openstack::cinder::params::service_enabled': is_service_enabled,
|
||||
'openstack::cinder::params::enabled_backends': enabled_backends,
|
||||
|
|
|
@ -37,6 +37,7 @@ class GnocchiPuppet(openstack.OpenstackBasePuppet):
|
|||
ksuser = self._get_service_user_name(self.SERVICE_NAME)
|
||||
|
||||
config = {
|
||||
'gnocchi::api::enabled': self._enable_gnocchi_api(),
|
||||
'gnocchi::keystone::auth::region':
|
||||
self._get_service_region_name(self.SERVICE_NAME),
|
||||
'gnocchi::keystone::auth::public_url': self.get_public_url(),
|
||||
|
@ -87,3 +88,9 @@ class GnocchiPuppet(openstack.OpenstackBasePuppet):
|
|||
|
||||
def get_admin_url(self):
|
||||
return self._format_private_endpoint(self.SERVICE_PORT)
|
||||
|
||||
def _enable_gnocchi_api(self):
|
||||
if self._kubernetes_enabled():
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
|
|
@ -34,7 +34,6 @@ SCHEDULER_FILTERS_COMMON = [
|
|||
'ServerGroupAntiAffinityFilter',
|
||||
'PciPassthroughFilter',
|
||||
'DiskFilter',
|
||||
# 'AggregateProviderNetworkFilter',
|
||||
]
|
||||
|
||||
SCHEDULER_FILTERS_STANDARD = [
|
||||
|
@ -419,6 +418,7 @@ class NovaPuppet(openstack.OpenstackBasePuppet):
|
|||
|
||||
def _get_compute_config(self, host):
|
||||
return {
|
||||
'nova::compute::enabled': self._enable_nova_compute(),
|
||||
'nova::compute::compute_reserved_vm_memory_2M':
|
||||
self._get_reserved_memory_2M(host),
|
||||
'nova::compute::compute_reserved_vm_memory_1G':
|
||||
|
@ -634,3 +634,9 @@ class NovaPuppet(openstack.OpenstackBasePuppet):
|
|||
ws_protocol = 'ws'
|
||||
url = "%s://%s:%s" % (ws_protocol, str(oam_addr), str(self.SERIALPROXY_PORT))
|
||||
return url
|
||||
|
||||
def _enable_nova_compute(self):
|
||||
if self._kubernetes_enabled():
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
|
Loading…
Reference in New Issue