ANSIBLE Bootstrap changes for System Controller

This update contains the following misc. config changes to
support ansible bootstrap for system controller.

Creates deps model for dcmanager and dcorch puppet modules.
Creates a system controller postgres run time manifest which is
applied upon the creation of initial controller host or replay after
the distributed cloud role has been changed.
The patch_vault file system is created during the first controller
unlocked.
And allows the dc role to be modified during bootstrap.

Change-Id: Id7b416274b2a854c469bfdca7448bf1ddea639d7
Story: 2004766
Task: 35650
Signed-off-by: Tao Liu <tao.liu@windriver.com>
This commit is contained in:
Tao Liu 2019-07-01 22:43:34 -04:00
parent 248cdd9370
commit bbac058ade
25 changed files with 259 additions and 77 deletions

View File

@ -344,6 +344,7 @@ class openstack::keystone::endpoint::runtime {
if $::platform::params::distributed_cloud_role =='systemcontroller' {
include ::dcorch::keystone::auth
include ::dcmanager::keystone::auth
include ::dcdbsync::keystone::auth
}
include ::smapi::keystone::auth

View File

@ -61,9 +61,21 @@ class platform::dcmanager::api
class { '::dcmanager::api':
bind_host => $api_host,
sync_db => $::platform::params::init_database,
}
include ::platform::dcmanager::haproxy
}
}
class platform::dcmanager::runtime {
if $::platform::params::distributed_cloud_role == 'systemcontroller' {
include ::platform::amqp::params
include ::dcmanager
include ::dcmanager::db::postgresql
class { '::dcmanager::api':
sync_db => str2bool($::is_standalone_controller),
}
}
}

View File

@ -130,9 +130,22 @@ class platform::dcorch::api_proxy
class { '::dcorch::api_proxy':
bind_host => $api_host,
sync_db => $::platform::params::init_database,
}
include ::platform::dcorch::firewall
include ::platform::dcorch::haproxy
}
}
class platform::dcorch::runtime {
if $::platform::params::distributed_cloud_role == 'systemcontroller' {
include ::platform::amqp::params
include ::dcorch
include ::dcorch::db::postgresql
class { '::dcorch::api_proxy':
sync_db => str2bool($::is_standalone_controller),
}
}
}

View File

@ -254,7 +254,7 @@ class platform::drbd::patch_vault::params (
$service_enabled = false,
$device = '/dev/drbd6',
$lv_name = 'patch-vault-lv',
$lv_size = '1',
$lv_size = '8',
$mountpoint = '/opt/patch-vault',
$port = '7794',
$resource_name = 'drbd-patch-vault',
@ -264,7 +264,7 @@ class platform::drbd::patch_vault::params (
class platform::drbd::patch_vault (
) inherits ::platform::drbd::patch_vault::params {
if str2bool($::is_initial_config_primary) {
if str2bool($::is_standalone_controller) {
$drbd_primary = true
$drbd_initial = true
$drbd_automount = true

View File

@ -204,3 +204,32 @@ class platform::postgresql::upgrade
include ::fm::db::postgresql
}
class platform::postgresql::sc::configured {
file { '/etc/platform/.sc_database_configured':
ensure => present,
owner => 'root',
group => 'root',
mode => '0644',
}
}
class platform::postgresql::sc::runtime
inherits ::platform::postgresql::params {
class {'::postgresql::globals':
datadir => $data_dir,
confdir => $config_dir,
needs_initdb => false,
}
-> class {'::postgresql::server':
}
include ::platform::dcmanager::runtime
include ::platform::dcorch::runtime
class {'::platform::postgresql::sc::configured':
stage => post
}
}

View File

@ -99,20 +99,18 @@ class dcmanager::api (
$service_port = '5000',
$package_ensure = 'latest',
$bind_host = '0.0.0.0',
$enabled = false
$enabled = false,
$sync_db = false,
) {
include dcmanager::params
Dcmanager_config<||> ~> Service['dcmanager-api']
Dcmanager_config<||> ~> Exec['dcmanager-dbsync']
include dcmanager::deps
if $::dcmanager::params::api_package {
Package['dcmanager'] -> Dcmanager_config<||>
Package['dcmanager'] -> Service['dcmanager-api']
package { 'dcmanager':
ensure => $package_ensure,
name => $::dcmanager::params::api_package,
tag => 'dcmanager-package',
}
}
@ -194,15 +192,7 @@ class dcmanager::api (
}
Keystone_endpoint<||> -> Service['dcmanager-api']
exec { 'dcmanager-dbsync':
command => $::dcmanager::params::db_sync_command,
path => '/usr/bin',
refreshonly => true,
logoutput => 'on_failure',
require => Package['dcmanager'],
# Only do the db sync if both controllers are running the same software
# version. Avoids impacting mate controller during an upgrade.
onlyif => "test ${::controller_sw_versions_match} = true",
if $sync_db {
include ::dcmanager::db::sync
}
}

View File

@ -22,9 +22,11 @@ class dcmanager::client(
) {
include dcmanager::params
include dcmanager::deps
package { 'dcmanagerclient':
ensure => $package_ensure,
name => $::dcmanager::params::client_package,
tag => 'dcmanager-package',
}
}

View File

@ -40,6 +40,8 @@ class dcmanager::db::postgresql(
$privileges = 'ALL',
) {
include dcmanager::deps
::openstacklib::db::postgresql { 'dcmanager':
password_hash => postgresql_password($user, $password),
dbname => $dbname,
@ -48,7 +50,7 @@ class dcmanager::db::postgresql(
privileges => $privileges,
}
::Openstacklib::Db::Postgresql['dcmanager'] ~> Service <| title == 'dcmanager-api' |>
::Openstacklib::Db::Postgresql['dcmanager'] ~> Service <| title == 'dcmanager-manager' |>
::Openstacklib::Db::Postgresql['dcmanager'] ~> Exec <| title == 'dcmanager-dbsync' |>
Anchor['dcmanager::db::begin']
~> Class['dcmanager::db::postgresql']
~> Anchor['dcmanager::db::end']
}

View File

@ -10,12 +10,22 @@
class dcmanager::db::sync {
include dcmanager::params
include dcmanager::deps
exec { 'dcmanager-dbsync':
command => $::dcmanager::params::db_sync_command,
path => '/usr/bin',
refreshonly => true,
require => [File[$::dcmanager::params::dcmanager_conf], Class['dcmanager']],
logoutput => 'on_failure',
subscribe => [
Anchor['dcmanager::install::end'],
Anchor['dcmanager::config::end'],
Anchor['dcmanager::db::end'],
Anchor['dcmanager::dbsync::begin']
],
notify => Anchor['dcmanager::dbsync::end'],
# Only do the db sync if both controllers are running the same software
# version. Avoids impacting mate controller during an upgrade.
onlyif => "test ${::controller_sw_versions_match} = true",
}
}

View File

@ -0,0 +1,25 @@
# == Class: dcmanager::deps
#
# dcmanager anchors and dependency management
#
class dcmanager::deps {
anchor { 'dcmanager::install::begin': }
-> Package<| tag == 'dcmanager-package'|>
~> anchor { 'dcmanager::install::end': }
-> anchor { 'dcmanager::config::begin': }
-> Dcmanager_config<||>
~> anchor { 'dcmanager::config::end': }
-> anchor { 'dcmanager::db::begin': }
-> anchor { 'dcmanager::db::end': }
~> anchor { 'dcmanager::dbsync::begin': }
-> anchor { 'dcmanager::dbsync::end': }
~> anchor { 'dcmanager::service::begin': }
~> Service<| tag == 'dcmanager-service' |>
~> anchor { 'dcmanager::service::end': }
Oslo::Db<||> -> Anchor['dcmanager::dbsync::begin']
# Installation or config changes will always restart services.
Anchor['dcmanager::install::end'] ~> Anchor['dcmanager::service::begin']
Anchor['dcmanager::config::end'] ~> Anchor['dcmanager::service::begin']
}

View File

@ -45,8 +45,7 @@ class dcmanager (
) {
include dcmanager::params
Package['dcmanager'] -> Dcmanager_config<||>
include dcmanager::deps
# this anchor is used to simplify the graph between dcmanager components by
# allowing a resource to serve as a point where the configuration of dcmanager begins

View File

@ -14,15 +14,13 @@ class dcmanager::manager (
) {
include dcmanager::params
Dcmanager_config<||> ~> Service['dcmanager-manager']
include dcmanager::deps
if $::dcmanager::params::manager_package {
Package['dcmanager-manager'] -> Dcmanager_config<||>
Package['dcmanager-manager'] -> Service['dcmanager-manager']
package { 'dcmanager-manager':
ensure => $package_ensure,
name => $::dcmanager::params::manager_package,
tag => 'dcmanager-package',
}
}
@ -38,7 +36,6 @@ class dcmanager::manager (
enable => $enabled,
hasstatus => false,
require => Package['dcmanager'],
tag => 'dcmanager-service',
}
Exec<| title == 'dcmanager-dbsync' |> -> Service['dcmanager-manager']
}

View File

@ -99,22 +99,18 @@ class dcorch::api_proxy (
$service_port = '5000',
$package_ensure = 'latest',
$bind_host = '0.0.0.0',
$enabled = false
$enabled = false,
$sync_db = false,
) {
include dcorch::params
Dcorch_config<||> ~> Service['dcorch-api-proxy']
Dcorch_config<||> ~> Exec['dcorch-dbsync']
Dcorch_api_paste_ini<||> ~> Service['dcorch-api-proxy']
include dcorch::deps
if $::dcorch::params::api_package {
Package['dcorch'] -> Dcorch_config<||>
Package['dcorch'] -> Dcorch_api_paste_ini<||>
Package['dcorch'] -> Service['dcorch-api-proxy']
package { 'dcorch':
ensure => $package_ensure,
name => $::dcorch::params::api_proxy_package,
tag => 'dcorch-package',
}
}
@ -196,15 +192,7 @@ class dcorch::api_proxy (
}
Keystone_endpoint<||> -> Service['dcorch-api-proxy']
exec { 'dcorch-dbsync':
command => $::dcorch::params::db_sync_command,
path => '/usr/bin',
refreshonly => true,
logoutput => 'on_failure',
require => Package['dcorch'],
# Only do the db sync if both controllers are running the same software
# version. Avoids impacting mate controller during an upgrade.
onlyif => "test ${::controller_sw_versions_match} = true",
if $sync_db {
include ::dcorch::db::sync
}
}

View File

@ -23,9 +23,11 @@ class dcorch::client(
) {
include dcorch::params
include dcorch::deps
package { 'dcorchclient':
ensure => $package_ensure,
name => $::dcorch::params::client_package,
tag => 'dcorch-package',
}
}

View File

@ -40,6 +40,8 @@ class dcorch::db::postgresql(
$privileges = 'ALL',
) {
include dcorch::deps
::openstacklib::db::postgresql { 'dcorch':
password_hash => postgresql_password($user, $password),
dbname => $dbname,
@ -48,7 +50,7 @@ class dcorch::db::postgresql(
privileges => $privileges,
}
::Openstacklib::Db::Postgresql['dcorch'] ~> Service <| title == 'dcorch-api-proxy' |>
::Openstacklib::Db::Postgresql['dcorch'] ~> Service <| title == 'dcorch-engine' |>
::Openstacklib::Db::Postgresql['dcorch'] ~> Exec <| title == 'dcorch-dbsync' |>
Anchor['dcorch::db::begin']
~> Class['dcorch::db::postgresql']
~> Anchor['dcorch::db::end']
}

View File

@ -10,12 +10,22 @@
class dcorch::db::sync {
include dcorch::params
include dcorch::deps
exec { 'dcorch-dbsync':
command => $::dcorch::params::db_sync_command,
path => '/usr/bin',
refreshonly => true,
require => [File[$::dcorch::params::dcorch_conf], Class['dcorch']],
logoutput => 'on_failure',
subscribe => [
Anchor['dcorch::install::end'],
Anchor['dcorch::config::end'],
Anchor['dcorch::db::end'],
Anchor['dcorch::dbsync::begin']
],
notify => Anchor['dcorch::dbsync::end'],
# Only do the db sync if both controllers are running the same software
# version. Avoids impacting mate controller during an upgrade.
onlyif => "test ${::controller_sw_versions_match} = true",
}
}

View File

@ -0,0 +1,29 @@
# == Class: dcorch::deps
#
# dcorch anchors and dependency management
#
class dcorch::deps {
anchor { 'dcorch::install::begin': }
-> Package<| tag == 'dcorch-package'|>
~> anchor { 'dcorch::install::end': }
-> anchor { 'dcorch::config::begin': }
-> Dcorch_config<||>
~> anchor { 'dcorch::config::end': }
-> anchor { 'dcorch::db::begin': }
-> anchor { 'dcorch::db::end': }
~> anchor { 'dcorch::dbsync::begin': }
-> anchor { 'dcorch::dbsync::end': }
~> anchor { 'dcorch::service::begin': }
~> Service<| tag == 'dcorch-service' |>
~> anchor { 'dcorch::service::end': }
Anchor['dcorch::config::begin']
-> Dcorch_api_paste_ini<||>
~> Anchor['dcorch::config::end']
Oslo::Db<||> -> Anchor['dcorch::dbsync::begin']
# Installation or config changes will always restart services.
Anchor['dcorch::install::end'] ~> Anchor['dcorch::service::begin']
Anchor['dcorch::config::end'] ~> Anchor['dcorch::service::begin']
}

View File

@ -14,15 +14,13 @@ class dcorch::engine (
) {
include dcorch::params
Dcorch_config<||> ~> Service['dcorch-engine']
include dcorch::deps
if $::dcorch::params::engine_package {
Package['dcorch-engine'] -> Dcorch_config<||>
Package['dcorch-engine'] -> Service['dcorch-engine']
package { 'dcorch-engine':
ensure => $package_ensure,
name => $::dcorch::params::engine_package,
tag => 'dcorch-package',
}
}
@ -37,8 +35,7 @@ class dcorch::engine (
name => $::dcorch::params::engine_service,
enable => $enabled,
hasstatus => false,
require => Package['dcorch'],
tag => 'dcorch-service',
}
Exec<| title == 'dcorch-dbsync' |> -> Service['dcorch-engine']
}

View File

@ -60,9 +60,7 @@ class dcorch (
) {
include dcorch::params
Package['dcorch'] -> Dcorch_config<||>
Package['dcorch'] -> Dcorch_api_paste_ini<||>
include dcorch::deps
# this anchor is used to simplify the graph between dcorch components by
# allowing a resource to serve as a point where the configuration of dcorch begins
@ -72,6 +70,7 @@ class dcorch (
ensure => $package_ensure,
name => $::dcorch::params::package_name,
require => Anchor['dcorch-start'],
tag => 'dcorch-package',
}
file { $::dcorch::params::dcorch_conf:

View File

@ -16,15 +16,13 @@ class dcorch::snmp (
) {
include dcorch::params
Dcorch_config<||> ~> Service['dcorch-snmp']
include dcorch::deps
if $::dcorch::params::snmp_package {
Package['dcorch-snmp'] -> Dcorch_config<||>
Package['dcorch-snmp'] -> Service['dcorch-snmp']
package { 'dcorch-snmp':
ensure => $package_ensure,
name => $::dcorch::params::snmp_package,
tag => 'dcorch-package',
}
}
dcorch_config {
@ -43,8 +41,7 @@ class dcorch::snmp (
name => $::dcorch::params::snmp_service,
enable => $enabled,
hasstatus => false,
require => Package['dcorch'],
tag => 'dcorch-service',
}
Exec<| title == 'dcorch-dbsync' |> -> Service['dcorch-snmp']
}

View File

@ -1412,6 +1412,12 @@ class HostController(rest.RestController):
pecan.request.rpcapi.reconfigure_service_endpoints(
pecan.request.context, controller_ihost)
# if it is a system controller, config the database
if (utils.get_distributed_cloud_role() ==
constants.DISTRIBUTED_CLOUD_ROLE_SYSTEMCONTROLLER):
pecan.request.rpcapi.configure_sc_database(
pecan.request.context, controller_ihost)
return Host.convert_with_links(controller_ihost)
if ihost_dict['personality'] in (constants.CONTROLLER, constants.STORAGE):

View File

@ -191,7 +191,7 @@ class InterfaceNetworkController(rest.RestController):
ethernet_port_mac = tmp_interface['imac']
_update_host_mgmt_mac(host, ethernet_port_mac)
cutils.perform_distributed_cloud_config(pecan.request.dbapi,
interface_id)
interface_uuid)
return InterfaceNetwork.convert_with_links(result)

View File

@ -477,18 +477,26 @@ class SystemController(rest.RestController):
" as %s" % https_enabled))
if 'distributed_cloud_role' in updates:
# At this point dc role cannot be changed after config_controller
# and config_subcloud
if rpc_isystem['distributed_cloud_role'] is None and \
distributed_cloud_role in \
[constants.DISTRIBUTED_CLOUD_ROLE_SYSTEMCONTROLLER,
constants.DISTRIBUTED_CLOUD_ROLE_SUBCLOUD]:
# At this point dc role cannot be changed after initial
# configuration is complete
if (rpc_isystem['distributed_cloud_role'] is not None and
cutils.is_initial_config_complete()):
raise wsme.exc.ClientSideError(
_("distributed_cloud_role is already set "
" as %s" % rpc_isystem['distributed_cloud_role']))
# allow set the role to None before the initial config
# is complete
elif ((distributed_cloud_role in
[constants.DISTRIBUTED_CLOUD_ROLE_SYSTEMCONTROLLER,
constants.DISTRIBUTED_CLOUD_ROLE_SUBCLOUD] or
distributed_cloud_role is None) and not
cutils.is_initial_config_complete()):
change_dc_role = True
patched_system['distributed_cloud_role'] = distributed_cloud_role
else:
raise wsme.exc.ClientSideError(_("distributed_cloud_role is already set "
" as %s" % rpc_isystem['distributed_cloud_role']))
raise wsme.exc.ClientSideError(_("Unexpected value %s specified"
" for distributed_cloud_role"
% distributed_cloud_role))
if 'vswitch_type' in updates:
if vswitch_type == rpc_isystem['capabilities']['vswitch_type']:
@ -575,6 +583,16 @@ class SystemController(rest.RestController):
pecan.request.rpcapi.update_distributed_cloud_role(
pecan.request.context)
# check if we need to config the system controller database
if (change_dc_role and distributed_cloud_role ==
constants.DISTRIBUTED_CLOUD_ROLE_SYSTEMCONTROLLER):
hosts = pecan.request.dbapi.ihost_get_by_personality(
constants.CONTROLLER)
# this is a replay case after the first host has been created
if len(hosts) == 1:
pecan.request.rpcapi.configure_sc_database(
pecan.request.context, hosts[0])
if 'security_feature' in delta_handle:
LOG.info("update security_feature %s" % security_feature)
pecan.request.rpcapi.update_security_feature_config(

View File

@ -10417,3 +10417,44 @@ class ConductorManager(service.PeriodicService):
else:
LOG.error("Received a request to update management mac for host "
"%s under the wrong condition." % host.hostname)
def configure_sc_database(self, context, host):
"""Configure the system controller database upon the creation of initial
controller host and distributed_cloud_role change from 'none' to
'systemcontroller' during bootstrap playbook play and replay.
:param context: request context.
:param host: an ihost object
"""
if (os.path.isfile(constants.ANSIBLE_BOOTSTRAP_FLAG) and
host.hostname == constants.CONTROLLER_0_HOSTNAME):
inventory_completed = True
# This could be called as part of host creation, wait for
# inventory to complete
for i in range(constants.INVENTORY_WAIT_TIMEOUT_IN_SECS):
if cutils.is_inventory_config_complete(self.dbapi, host.uuid):
break
LOG.info('Inventory incomplete, will try again in 1 second.')
greenthread.sleep(1)
else:
inventory_completed = False
if inventory_completed:
personalities = [constants.CONTROLLER]
config_uuid = self._config_update_hosts(context, personalities)
config_dict = {
"personalities": personalities,
"host_uuids": [host.uuid],
"classes": ['platform::postgresql::sc::runtime']
}
self._config_apply_runtime_manifest(
context, config_uuid, config_dict, force=True)
else:
LOG.error("Unable to configure the sc database. Timed out "
"waiting for inventory to complete.")
else:
LOG.error("Received a request to configure the sc database "
"for host %s under the wrong condition." % host.hostname)

View File

@ -1815,3 +1815,16 @@ class ConductorAPI(sysinv.openstack.common.rpc.proxy.RpcProxy):
self.make_msg('mgmt_mac_set_by_ihost',
host=host,
mgmt_mac=mgmt_mac))
def configure_sc_database(self, context, host):
"""Synchronously, configure system controller database upon the
creation of initial controller host and distributed_cloud_role
change from 'none' to 'systemcontroller' during bootstrap
playbook play and replay.
:param context: request context.
:param host: an ihost object
"""
return self.call(context,
self.make_msg('configure_sc_database',
host=host))