Create docker filesystem on compute hosts

Create docker_lv and cgts_vg on on compute hosts, mounted as
/var/lib/docker.
Provisioned similarly to nova-local storage.  With Kubernetes enabled,
compute hosts will fail to unlock without this storage provisioned.

Story: 2002839
Task: 22778

Change-Id: I2df5e995437841c965311b23c8cc23e9207e1dc5
Signed-off-by: Jack Ding <jack.ding@windriver.com>
This commit is contained in:
Kevin Smith 2018-06-09 07:43:25 -04:00 committed by Jack Ding
parent f52a35d6bc
commit a04434af8b
8 changed files with 155 additions and 18 deletions

View File

@ -29,6 +29,8 @@ include ::platform::ceph
include ::platform::devices
include ::platform::grub
include ::platform::collectd
include ::platform::filesystem::compute
include ::platform::docker
include ::platform::kubernetes::worker
include ::openstack::client

View File

@ -8,19 +8,30 @@ define platform::filesystem (
$lv_size,
$mountpoint,
$fs_type,
$fs_options
$fs_options,
$fs_use_all = false,
) {
include ::platform::filesystem::params
$vg_name = $::platform::filesystem::params::vg_name
$device = "/dev/${vg_name}/${lv_name}"
if !$fs_use_all {
$size = "${lv_size}G"
$fs_size_is_minsize = true
}
else {
# use all available space
$size = undef
$fs_size_is_minsize = false
}
# create logical volume
logical_volume { $lv_name:
ensure => present,
volume_group => $vg_name,
size => "${lv_size}G",
size_is_minsize => true,
size => $size,
size_is_minsize => $fs_size_is_minsize,
} ->
# create filesystem
@ -52,6 +63,7 @@ define platform::filesystem (
exec { "mount $device":
unless => "mount | awk '{print \$3}' | grep -Fxq $mountpoint",
command => "mount $mountpoint",
path => "/usr/bin"
}
}
@ -133,6 +145,7 @@ class platform::filesystem::docker::params (
$devmapper = '/dev/mapper/cgts--vg-docker--lv',
$fs_type = 'xfs',
$fs_options = '-n ftype=1',
$fs_use_all = false
) { }
class platform::filesystem::docker
@ -146,7 +159,8 @@ class platform::filesystem::docker
lv_size => $lv_size,
mountpoint => $mountpoint,
fs_type => $fs_type,
fs_options => $fs_options
fs_options => $fs_options,
fs_use_all => $fs_use_all
}
}
}
@ -175,6 +189,21 @@ class platform::filesystem::img_conversions
}
class platform::filesystem::compute {
include ::platform::kubernetes::params
if $::platform::kubernetes::params::enabled {
class {'platform::filesystem::docker::params' :
fs_use_all => true
} ->
class {'platform::filesystem::docker' :
}
Class['::platform::lvm::vg::cgts_vg'] -> Class['::platform::filesystem::docker']
}
}
class platform::filesystem::controller {
include ::platform::filesystem::backup
include ::platform::filesystem::scratch

View File

@ -139,16 +139,7 @@ class platform::kubernetes::worker::params (
class platform::kubernetes::worker::init
inherits ::platform::kubernetes::worker::params {
# Start docker - will move to another manifest.
service { 'docker':
ensure => 'running',
enable => true,
} ->
# A seperate enable is required since we have modified the service resource
# to never enable services.
exec { 'enable-docker':
command => '/usr/bin/systemctl enable docker.service',
} ->
Class['::platform::docker::config'] -> Class[$name]
# Configure the worker node. Only do this once, so check whether the
# kubelet.conf file has already been created (by the join).

View File

@ -104,6 +104,11 @@ class platform::lvm::controller::runtime {
class platform::lvm::compute::vgs {
include ::platform::lvm::vg::nova_local
include ::platform::kubernetes::params
if $::platform::kubernetes::params::enabled {
include ::platform::lvm::vg::cgts_vg
}
}
class platform::lvm::compute

View File

@ -3990,6 +3990,69 @@ class HostController(rest.RestController):
"Please refer to system admin guide for more details.") %
(ihost['hostname']))
@staticmethod
def _semantic_check_cgts_storage(ihost_uuid, personality):
"""
Perform semantic checking for cgts storage on compute hosts.
CGTS VG on computes used for kubernetes docker lv only at this time.
:param ihost_uuid: uuid of host with compute functionality
:param personality: personality of host with compute functionality
"""
if personality != constants.COMPUTE:
return
# query volume groups
cgts_local_storage_lvg = None
ihost_ilvgs = pecan.request.dbapi.ilvg_get_by_ihost(ihost_uuid)
for lvg in ihost_ilvgs:
if lvg.lvm_vg_name == constants.LVG_CGTS_VG:
cgts_local_storage_lvg = lvg
break
# Prevent unlock if no CGTS vg or pv volume allocated
if cgts_local_storage_lvg:
if cgts_local_storage_lvg.vg_state == constants.LVG_DEL:
raise wsme.exc.ClientSideError(
_("With kubernetes configured, "
"a compute host requires a "
"cgts volume group prior to being enabled. It is "
"currently set to be removed on unlock. Please update "
"the storage settings for the host."))
else:
# Make sure that we have physical volumes allocated to the
# volume group
ihost_ipvs = pecan.request.dbapi.ipv_get_by_ihost(ihost_uuid)
lvg_has_pvs = False
for pv in ihost_ipvs:
if ((pv.lvm_vg_name == cgts_local_storage_lvg.lvm_vg_name) and
(pv.pv_state != constants.PV_DEL)):
lvg_has_pvs = True
break
if not lvg_has_pvs:
raise wsme.exc.ClientSideError(
_("With kubernetes configured, "
"a compute host requires a "
"cgts volume group prior to being enabled."
"The cgts volume group does not contain any "
"physical volumes in the adding or provisioned "
"state."))
else:
# This method is only called with hosts that have a compute
# subfunction and is locked or if subfunction_config action is
# being called. Without a cgts volume group, prevent
# unlocking.
msg = _('With kubernetes configured, '
'a compute host requires a cgts volume group prior to being '
'enabled. Please update the storage settings for the '
'host.')
raise wsme.exc.ClientSideError('%s' % msg)
@staticmethod
def _handle_ttys_dcd_change(ihost, ttys_dcd):
"""
@ -4110,6 +4173,11 @@ class HostController(rest.RestController):
self._semantic_check_nova_local_storage(
hostupdate.ihost_patch['uuid'],
hostupdate.ihost_patch['personality'])
if utils.is_kubernetes_config():
# CGTS Storage checks
self._semantic_check_cgts_storage(
hostupdate.ihost_patch['uuid'],
hostupdate.ihost_patch['personality'])
else:
raise wsme.exc.ClientSideError(_(
"action_check unrecognized action: %s" % action))
@ -5029,6 +5097,11 @@ class HostController(rest.RestController):
self._semantic_check_nova_local_storage(ihost['uuid'],
ihost['personality'])
# CGTS Storage checks
if utils.is_kubernetes_config():
self._semantic_check_cgts_storage(ihost['uuid'],
ihost['personality'])
@staticmethod
def check_unlock_storage(hostupdate):
"""Storage unlock semantic checks"""

View File

@ -526,7 +526,8 @@ def _check_host(lvg):
(constants.LVG_NOVA_LOCAL,
constants.COMPUTE))
elif (ihost.personality == constants.COMPUTE and
lvg['lvm_vg_name'] == constants.LVG_CGTS_VG):
lvg['lvm_vg_name'] == constants.LVG_CGTS_VG and
not utils.is_kubernetes_config()):
raise wsme.exc.ClientSideError(_("%s can not be provisioned for %s "
"hosts.") % (constants.LVG_CGTS_VG,
constants.COMPUTE))
@ -542,6 +543,13 @@ def _check_host(lvg):
ihost['ihost_action'] == constants.UNLOCK_ACTION)):
raise wsme.exc.ClientSideError(_("Host must be locked"))
if utils.is_kubernetes_config():
if (ihost.personality == constants.COMPUTE and
lvg['lvm_vg_name'] == constants.LVG_CGTS_VG and
(ihost['administrative'] != constants.ADMIN_LOCKED or
ihost['ihost_action'] == constants.UNLOCK_ACTION)):
raise wsme.exc.ClientSideError(_("Host must be locked"))
def _get_mate_ctrl_lvg(lvg):
""" Return the lvg object with same VG name of mate controller """
@ -593,7 +601,8 @@ def _check(op, lvg):
" both controllers." % {'lvm_type': constants.LVG_CINDER_PARAM_LVM_TYPE,
'vg_name': lvg['lvm_vg_name'],
'type': mate_type}))
if lvg['lvm_vg_name'] == constants.LVG_CGTS_VG:
if (lvg['lvm_vg_name'] == constants.LVG_CGTS_VG and
not utils.is_kubernetes_config()):
raise wsme.exc.ClientSideError(_("%s volume group already exists") %
constants.LVG_CGTS_VG)
elif lvg['lvm_vg_name'] == constants.LVG_CINDER_VOLUMES:

View File

@ -473,14 +473,25 @@ def _check_host(pv, ihost, op):
return
ilvg = pecan.request.dbapi.ilvg_get(ilvgid)
if (ilvg.lvm_vg_name == constants.LVG_CGTS_VG):
if utils.is_kubernetes_config():
if (ilvg.lvm_vg_name == constants.LVG_CGTS_VG):
if (ihost['personality'] != constants.CONTROLLER and
ihost['personality'] != constants.COMPUTE):
raise wsme.exc.ClientSideError(
_("Physical volume operations for %s are only "
"supported on %s and %s hosts" %
(constants.LVG_CGTS_VG,
constants.COMPUTE,
constants.CONTROLLER)))
elif (ilvg.lvm_vg_name == constants.LVG_CGTS_VG):
if ihost['personality'] != constants.CONTROLLER:
raise wsme.exc.ClientSideError(
_("Physical volume operations for %s are only supported "
"on %s hosts") % (constants.LVG_CGTS_VG,
constants.CONTROLLER))
# semantic check: host must be locked for a nova-local change on a
# semantic check: host must be locked for a nova-local change on
# a host with a compute subfunction (compute or AIO)
if (constants.COMPUTE in ihost['subfunctions'] and
ilvg.lvm_vg_name == constants.LVG_NOVA_LOCAL and
@ -488,6 +499,15 @@ def _check_host(pv, ihost, op):
ihost['ihost_action'] == constants.UNLOCK_ACTION)):
raise wsme.exc.ClientSideError(_("Host must be locked"))
# semantic check: host must be locked for a CGTS change on
# a compute host.
if utils.is_kubernetes_config():
if (ihost['personality'] == constants.COMPUTE and
ilvg.lvm_vg_name == constants.LVG_CGTS_VG and
(ihost['administrative'] != constants.ADMIN_LOCKED or
ihost['ihost_action'] == constants.UNLOCK_ACTION)):
raise wsme.exc.ClientSideError(_("Host must be locked"))
def _get_vg_size_from_pvs(lvg, filter_pv=None):
ipvs = pecan.request.dbapi.ipv_get_by_ihost(lvg['forihostid'])
@ -642,6 +662,7 @@ def _check_lvg(op, pv):
(pv['uuid'], ilvg.lvm_vg_name, ilvg.lvm_cur_lv - 1)))
_check_instances_lv_if_deleted(ilvg, pv)
# Possible Kubernetes issue, do we want to allow this on compute nodes?
if (ilvg.lvm_vg_name == constants.LVG_CGTS_VG):
raise wsme.exc.ClientSideError(
_("Physical volumes cannot be removed from the cgts-vg volume "

View File

@ -375,6 +375,13 @@ def get_distributed_cloud_role(dbapi=None):
return system.distributed_cloud_role
def is_kubernetes_config(dbapi=None):
if not dbapi:
dbapi = pecan.request.dbapi
system = dbapi.isystem_get_one()
return system.capabilities.get('kubernetes_enabled', False)
def is_aio_duplex_system():
return get_system_mode() == constants.SYSTEM_MODE_DUPLEX and \
SystemHelper.get_product_build() == constants.TIS_AIO_BUILD