Add heat_launcher module to help launch heat-all

This module contains several classes to help launch heat-all
on:

 -baremetal (requires the heat-all binary to be installed locally)

 -docker containers

These classes will be use to help drive the new Undercloud
installer with Heat.

Change-Id: I1d6e6ef34af4c4671cc32d880c04b307895604fa
Co-Authored-By: Ian Main <imain@redhat.com>
This commit is contained in:
Dan Prince 2017-01-31 21:27:59 -05:00
parent 44b94eb1cb
commit b999d83100
2 changed files with 270 additions and 0 deletions

View File

@ -0,0 +1,177 @@
# Copyright 2017 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
from __future__ import print_function
import os
import signal
import subprocess
import tempfile
class HeatBaseLauncher(object):
# The init function will need permission to touch these files
# and chown them accordingly for the heat user
def __init__(self, api_port, ks_port, container_image, user='heat'):
self.api_port = api_port
self.ks_port = ks_port
self.policy_file = os.path.join(os.path.dirname(__file__),
'noauth_policy.json')
self.install_tmp = tempfile.mkdtemp(prefix='undercloud_deploy-')
self.container_image = container_image
self.user = user
self.sql_db = os.path.join(self.install_tmp, 'heat.sqlite')
self.log_file = os.path.join(self.install_tmp, 'heat.log')
self.config_file = os.path.join(self.install_tmp, 'heat.conf')
self._write_heat_config(self.config_file,
self.sql_db,
self.log_file,
api_port,
ks_port,
self.policy_file)
uid = int(self.get_heat_uid())
gid = int(self.get_heat_gid())
os.chown(self.install_tmp, uid, gid)
os.chown(self.config_file, uid, gid)
def _write_heat_config(self, config_file, sqlite_db, log_file, api_port,
ks_port, policy_file):
heat_config = '''
[DEFAULT]
log_file = %(log_file)s
rpc_backend = fake
rpc_poll_timeout = 60
rpc_response_timeout = 600
deferred_auth_method = password
num_engine_workers=1
convergence_engine = false
default_deployment_signal_transport = HEAT_SIGNAL
max_nested_stack_depth = 6
[heat_all]
enabled_services = api,engine
[heat_api]
workers = 1
bind_host = 127.0.0.1
bind_port = %(api_port)s
[database]
connection = sqlite:///%(sqlite_db)s.db
[paste_deploy]
flavor = noauth
api_paste_config = /usr/share/heat/api-paste-dist.ini
[oslo_policy]
policy_file = %(policy_file)s
[clients_keystone]
auth_uri=http://127.0.0.1:%(ks_port)s
[keystone_authtoken]
auth_type = password
auth_url=http://127.0.0.1:%(ks_port)s
[yaql]
memory_quota=900000
limit_iterators=9000
''' % {'sqlite_db': sqlite_db, 'log_file': log_file,
'api_port': api_port, 'ks_port': ks_port,
'policy_file': policy_file}
with open(config_file, 'w') as temp_file:
temp_file.write(heat_config)
class HeatDockerLauncher(HeatBaseLauncher):
def __init__(self, api_port, ks_port, container_image, user='heat'):
super(HeatDockerLauncher, self).__init__(api_port, ks_port,
container_image, user)
def launch_heat(self):
subprocess.check_call(
['docker', 'run',
'--name', 'heat_all',
'--user', self.user,
'--net', 'host',
'--volume', '%(conf)s:/etc/heat/heat.conf' % {'conf':
self.config_file},
'--volume', '%(inst_tmp)s:%(inst_tmp)s:rw' % {'inst_tmp':
self.install_tmp},
'--volume', '%(pfile)s:%(pfile)s:ro' % {'pfile':
self.policy_file},
self.container_image, 'heat-all'])
def heat_db_sync(self):
subprocess.check_call([
'docker', 'run',
'--user', self.user,
'--volume', '%(conf)s:/etc/heat/heat.conf' % {'conf':
self.config_file},
'--volume', '%(inst_tmp)s:%(inst_tmp)s:rw' % {'inst_tmp':
self.install_tmp},
self.container_image,
'heat-manage', 'db_sync'])
def get_heat_uid(self):
p = subprocess.Popen([
'docker', 'run',
self.container_image,
'getent', 'passwd', '|', 'grep', self.user],
stdout=subprocess.PIPE)
return p.communicate()[0].rstrip().split(':')[2]
def get_heat_gid(self):
p = subprocess.Popen([
'docker', 'run',
self.container_image,
'getent', 'group', '|', 'grep', self.user],
stdout=subprocess.PIPE)
return p.communicate()[0].rstrip().split(':')[2]
def kill_heat(self, pid):
subprocess.check_call(['docker', 'rm', '-f', 'heat_all'])
class HeatNativeLauncher(HeatBaseLauncher):
def __init__(self, api_port, ks_port, container_image, user='heat'):
super(HeatNativeLauncher, self).__init__(api_port, ks_port,
container_image, user)
def launch_heat(self):
os.execvp('heat-all', ['heat-all', '--config-file', self.config_file])
def heat_db_sync(self):
subprocess.check_call(['heat-manage', '--config-file',
self.config_file, 'db_sync'])
def get_heat_uid(self):
p = subprocess.Popen(["getent", "passwd", "|", "grep", "heat"],
stdout=subprocess.PIPE)
return p.communicate()[0].rstrip().split(':')[2]
def get_heat_gid(self):
p = subprocess.Popen(["getent", "group", "|", "grep", "heat"],
stdout=subprocess.PIPE)
return p.communicate()[0].rstrip().split(':')[2]
def kill_heat(self, pid):
os.kill(pid, signal.SIGKILL)

View File

@ -0,0 +1,93 @@
{
"context_is_admin": "@",
"deny_stack_user": "@",
"deny_everybody": "@",
"cloudformation:ListStacks": "rule:deny_stack_user",
"cloudformation:CreateStack": "rule:deny_stack_user",
"cloudformation:DescribeStacks": "rule:deny_stack_user",
"cloudformation:DeleteStack": "rule:deny_stack_user",
"cloudformation:UpdateStack": "rule:deny_stack_user",
"cloudformation:CancelUpdateStack": "rule:deny_stack_user",
"cloudformation:DescribeStackEvents": "rule:deny_stack_user",
"cloudformation:ValidateTemplate": "rule:deny_stack_user",
"cloudformation:GetTemplate": "rule:deny_stack_user",
"cloudformation:EstimateTemplateCost": "rule:deny_stack_user",
"cloudformation:DescribeStackResource": "",
"cloudformation:DescribeStackResources": "rule:deny_stack_user",
"cloudformation:ListStackResources": "rule:deny_stack_user",
"cloudwatch:DeleteAlarms": "rule:deny_stack_user",
"cloudwatch:DescribeAlarmHistory": "rule:deny_stack_user",
"cloudwatch:DescribeAlarms": "rule:deny_stack_user",
"cloudwatch:DescribeAlarmsForMetric": "rule:deny_stack_user",
"cloudwatch:DisableAlarmActions": "rule:deny_stack_user",
"cloudwatch:EnableAlarmActions": "rule:deny_stack_user",
"cloudwatch:GetMetricStatistics": "rule:deny_stack_user",
"cloudwatch:ListMetrics": "rule:deny_stack_user",
"cloudwatch:PutMetricAlarm": "rule:deny_stack_user",
"cloudwatch:PutMetricData": "",
"cloudwatch:SetAlarmState": "rule:deny_stack_user",
"actions:action": "rule:deny_stack_user",
"build_info:build_info": "rule:deny_stack_user",
"events:index": "rule:deny_stack_user",
"events:show": "rule:deny_stack_user",
"resource:index": "rule:deny_stack_user",
"resource:metadata": "",
"resource:signal": "",
"resource:mark_unhealthy": "rule:deny_stack_user",
"resource:show": "rule:deny_stack_user",
"stacks:abandon": "rule:deny_stack_user",
"stacks:create": "rule:deny_stack_user",
"stacks:delete": "rule:deny_stack_user",
"stacks:detail": "rule:deny_stack_user",
"stacks:export": "rule:deny_stack_user",
"stacks:generate_template": "rule:deny_stack_user",
"stacks:global_index": "rule:deny_everybody",
"stacks:index": "rule:deny_stack_user",
"stacks:list_resource_types": "rule:deny_stack_user",
"stacks:list_template_versions": "rule:deny_stack_user",
"stacks:list_template_functions": "rule:deny_stack_user",
"stacks:lookup": "",
"stacks:preview": "rule:deny_stack_user",
"stacks:resource_schema": "rule:deny_stack_user",
"stacks:show": "rule:deny_stack_user",
"stacks:template": "rule:deny_stack_user",
"stacks:environment": "rule:deny_stack_user",
"stacks:files": "rule:deny_stack_user",
"stacks:update": "rule:deny_stack_user",
"stacks:update_patch": "rule:deny_stack_user",
"stacks:preview_update": "rule:deny_stack_user",
"stacks:preview_update_patch": "rule:deny_stack_user",
"stacks:validate_template": "rule:deny_stack_user",
"stacks:snapshot": "rule:deny_stack_user",
"stacks:show_snapshot": "rule:deny_stack_user",
"stacks:delete_snapshot": "rule:deny_stack_user",
"stacks:list_snapshots": "rule:deny_stack_user",
"stacks:restore_snapshot": "rule:deny_stack_user",
"stacks:list_outputs": "rule:deny_stack_user",
"stacks:show_output": "rule:deny_stack_user",
"software_configs:global_index": "rule:deny_everybody",
"software_configs:index": "rule:deny_stack_user",
"software_configs:create": "rule:deny_stack_user",
"software_configs:show": "rule:deny_stack_user",
"software_configs:delete": "rule:deny_stack_user",
"software_deployments:index": "rule:deny_stack_user",
"software_deployments:create": "rule:deny_stack_user",
"software_deployments:show": "rule:deny_stack_user",
"software_deployments:update": "rule:deny_stack_user",
"software_deployments:delete": "rule:deny_stack_user",
"software_deployments:metadata": "",
"service:index": "rule:context_is_admin",
"resource_types:OS::Nova::Flavor": "rule:context_is_admin",
"resource_types:OS::Cinder::EncryptedVolumeType": "rule:context_is_admin",
"resource_types:OS::Cinder::VolumeType": "rule:context_is_admin",
"resource_types:OS::Manila::ShareType": "rule:context_is_admin",
"resource_types:OS::Neutron::QoSPolicy": "rule:context_is_admin",
"resource_types:OS::Neutron::QoSBandwidthLimitRule": "rule:context_is_admin",
"resource_types:OS::Nova::HostAggregate": "rule:context_is_admin"
}