Merge "Add health check feature to Compass" into dev/experimental

This commit is contained in:
Jenkins 2015-02-05 21:28:14 +00:00 committed by Gerrit Code Review
commit a5f72f2086
17 changed files with 655 additions and 8 deletions

View File

@ -17,6 +17,7 @@
import logging
from compass.actions import util
from compass.db.api import health_check_report as health_check_db
from compass.db.api import user as user_db
from compass.deployment.deploy_manager import DeployManager
from compass.deployment.utils import constants as const
@ -46,7 +47,7 @@ def deploy(cluster_id, hosts_id_list, username=None):
cluster_id, hosts_id_list, user)
deploy_manager = DeployManager(adapter_info, cluster_info, hosts_info)
#deploy_manager.prepare_for_deploy()
# deploy_manager.prepare_for_deploy()
logging.debug('Created deploy manager with %s %s %s'
% (adapter_info, cluster_info, hosts_info))
@ -80,7 +81,35 @@ def redeploy(cluster_id, hosts_id_list, username=None):
util.ActionHelper.update_state(cluster_id, hosts_id_list, user)
ActionHelper = util.ActionHelper
def health_check(cluster_id, report_uri, username):
with util.lock('cluster_health_check') as lock:
if not lock:
raise Exception('failed to acquire lock to check health')
user = user_db.get_user_object(username)
cluster_info = util.ActionHelper.get_cluster_info(cluster_id, user)
adapter_id = cluster_info[const.ADAPTER_ID]
adapter_info = util.ActionHelper.get_adapter_info(
adapter_id, cluster_id, user
)
deploy_manager = DeployManager(adapter_info, cluster_info, None)
try:
deploy_manager.check_cluster_health(report_uri)
except Exception as exc:
logging.error("health_check exception: ============= %s" % exc)
data = {'state': 'error', 'error_message': str(exc), 'report': {}}
reports = health_check_db.list_health_reports(user, cluster_id)
if not reports:
# Exception before executing command remotely for health check.
# No reports names sending back yet. Create a report
name = 'pre_remote_health_check'
health_check_db.add_report_record(
cluster_id, name=name, **data
)
health_check_db.update_multi_reports(cluster_id, **data)
class ServerPowerMgmt(object):

View File

@ -35,6 +35,7 @@ from compass.api import utils
from compass.db.api import adapter_holder as adapter_api
from compass.db.api import cluster as cluster_api
from compass.db.api import database
from compass.db.api import health_check_report as health_report_api
from compass.db.api import host as host_api
from compass.db.api import machine as machine_api
from compass.db.api import metadata_holder as metadata_api
@ -1506,6 +1507,8 @@ def delete_cluster_config(cluster_id):
def take_cluster_action(cluster_id):
"""take cluster action."""
data = _get_request_data()
url_root = request.url_root
update_cluster_hosts_func = _wrap_response(
functools.partial(
cluster_api.update_cluster_hosts, current_user, cluster_id
@ -1524,13 +1527,22 @@ def take_cluster_action(cluster_id):
),
202
)
check_cluster_health_func = _wrap_response(
functools.partial(
health_report_api.start_check_cluster_health,
current_user, cluster_id,
'%s/clusters/%s/healthreports' % (url_root, cluster_id)
),
202
)
return _group_data_action(
data,
add_hosts=update_cluster_hosts_func,
set_hosts=update_cluster_hosts_func,
remove_hosts=update_cluster_hosts_func,
review=review_cluster_func,
deploy=deploy_cluster_func
deploy=deploy_cluster_func,
check_health=check_cluster_health_func
)
@ -1549,6 +1561,73 @@ def get_cluster_state(cluster_id):
)
@app.route("/clusters/<int:cluster_id>/healthreports", methods=['POST'])
def create_health_reports(cluster_id):
"""Create a health check report."""
data = _get_request_data()
output = []
if 'report_list' in data:
for report in data['report_list']:
try:
output.append(
health_report_api.add_report_record(cluster_id, **report)
)
except Exception:
continue
else:
output = health_report_api.add_report_record(cluster_id, **data)
return utils.make_json_response(
200,
output
)
@app.route("/clusters/<int:cluster_id>/healthreports", methods=['PUT'])
def bulk_update_reports(cluster_id):
"""Bulk update reports."""
data = _get_request_data()
return utils.make_json_response(
200,
health_report_api.update_multi_reports(cluster_id, **data)
)
@app.route("/clusters/<int:cluster_id>/healthreports", methods=['GET'])
@log_user_action
@login_required
@update_user_token
def list_health_reports(cluster_id):
return utils.make_json_response(
200,
health_report_api.list_health_reports(current_user, cluster_id)
)
@app.route("/clusters/<int:cluster_id>/healthreports/<name>", methods=['PUT'])
def update_health_report(cluster_id, name):
data = _get_request_data()
if 'error_message' not in data:
data['error_message'] = ""
return utils.make_json_response(
200,
health_report_api.update_report(cluster_id, name, **data)
)
@app.route("/clusters/<int:cluster_id>/healthreports/<name>", methods=['GET'])
@log_user_action
@login_required
@update_user_token
def get_health_report(cluster_id, name):
return utils.make_json_response(
200,
health_report_api.get_health_report(current_user, cluster_id, name)
)
@app.route("/clusters/<int:cluster_id>/hosts", methods=['GET'])
@log_user_action
@login_required

View File

@ -98,7 +98,8 @@ def add_adapters_internal(session, exception_when_existing=True):
distributed_system=distributed_system,
os_installer=os_installer,
package_installer=package_installer,
deployable=config.get('DEPLOYABLE', False)
deployable=config.get('DEPLOYABLE', False),
health_check_cmd=config.get('HEALTH_CHECK_COMMAND', None)
)
supported_os_patterns = [
re.compile(supported_os_pattern)

View File

@ -32,7 +32,7 @@ RESP_FIELDS = [
'os_installer', 'package_installer',
'distributed_system_id',
'distributed_system_name',
'supported_oses', 'display_name'
'supported_oses', 'display_name', 'health_check_cmd'
]
RESP_OS_FIELDS = [
'id', 'os_id', 'name'

View File

@ -0,0 +1,177 @@
# Copyright 2014 Huawei Technologies Co. Ltd
#
# 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.
"""Cluster health check report."""
import logging
from compass.db.api import database
from compass.db.api import permission
from compass.db.api import user as user_api
from compass.db.api import utils
from compass.db import exception
from compass.db import models
REQUIRED_INSERT_FIELDS = ['name']
OPTIONAL_INSERT_FIELDS = [
'display_name', 'report', 'category', 'state', 'error_message'
]
UPDATE_FIELDS = ['report', 'state', 'error_message']
RESP_FIELDS = [
'cluster_id', 'name', 'display_name', 'report',
'category', 'state', 'error_message'
]
RESP_ACTION_FIELDS = ['cluster_id', 'status']
@utils.supported_filters(REQUIRED_INSERT_FIELDS, OPTIONAL_INSERT_FIELDS)
@database.run_in_session()
@utils.wrap_to_dict(RESP_FIELDS)
def add_report_record(cluster_id, name, report={},
state='verifying', session=None, **kwargs):
"""Create a health check report record."""
# Replace any white space into '-'
words = name.split()
name = '-'.join(words)
return utils.add_db_object(
session, models.HealthCheckReport, True, cluster_id, name,
report=report, state=state, **kwargs
)
@utils.supported_filters(UPDATE_FIELDS)
@database.run_in_session()
@utils.wrap_to_dict(RESP_FIELDS)
def update_report(cluster_id, name, session=None, **kwargs):
"""Update health check report."""
report = utils.get_db_object(
session, models.HealthCheckReport, cluster_id=cluster_id, name=name
)
if report.state == 'finished':
err_msg = 'Report cannot be updated if state is in "finished"'
raise exception.Forbidden(err_msg)
return utils.update_db_object(session, report, **kwargs)
@utils.supported_filters(UPDATE_FIELDS)
@database.run_in_session()
@utils.wrap_to_dict(RESP_FIELDS)
def update_multi_reports(cluster_id, session=None, **kwargs):
"""Bulk update reports."""
return set_error(cluster_id, session=session, **kwargs)
def set_error(cluster_id, report={}, session=None,
state='error', error_message=None):
with session.begin(subtransactions=True):
logging.debug(
"session %s updates all reports as %s in cluster %s",
id(session), state, cluster_id
)
session.query(
models.HealthCheckReport
).filter_by(cluster_id=cluster_id).update(
{"report": {}, 'state': 'error', 'error_message': error_message}
)
reports = session.query(
models.HealthCheckReport
).filter_by(cluster_id=cluster_id).all()
return reports
@database.run_in_session()
@user_api.check_user_permission_in_session(
permission.PERMISSION_LIST_HEALTH_REPORT
)
@utils.wrap_to_dict(RESP_FIELDS)
def list_health_reports(user, cluster_id, session=None):
"""List all reports in the specified cluster."""
return utils.list_db_objects(
session, models.HealthCheckReport, cluster_id=cluster_id
)
@database.run_in_session()
@user_api.check_user_permission_in_session(
permission.PERMISSION_GET_HEALTH_REPORT
)
@utils.wrap_to_dict(RESP_FIELDS)
def get_health_report(user, cluster_id, name, session=None):
return utils.get_db_object(
session, models.HealthCheckReport, cluster_id=cluster_id, name=name
)
@database.run_in_session()
@user_api.check_user_permission_in_session(
permission.PERMISSION_DELETE_REPORT
)
@utils.wrap_to_dict(RESP_FIELDS)
def delete_reports(user, cluster_id, name=None, session=None):
if not name:
report = utils.get_db_object(
session, models.HealthCheckReport, cluster_id=cluster_id, name=name
)
return utils.del_db_object(session, report)
return utils.del_db_objects(
session, models.HealthCheckReport, cluster_id=cluster_id
)
@utils.supported_filters(optional_support_keys=['check_health'])
@database.run_in_session()
@user_api.check_user_permission_in_session(
permission.PERMISSION_CHECK_CLUSTER_HEALTH
)
@utils.wrap_to_dict(RESP_ACTION_FIELDS)
def start_check_cluster_health(user, cluster_id, send_report_url,
session=None, check_health={}):
"""Start to check cluster health."""
cluster_state = utils.get_db_object(
session, models.Cluster, True, id=cluster_id
).state_dict()
if cluster_state['state'] != 'SUCCESSFUL':
logging.debug("state is %s" % cluster_state['state'])
err_msg = "Healthcheck starts only after cluster finished deployment!"
raise exception.Forbidden(err_msg)
reports = utils.list_db_objects(
session, models.HealthCheckReport,
cluster_id=cluster_id, state='verifying'
)
if reports:
err_msg = 'Healthcheck in progress, please wait for it to complete!'
raise exception.Forbidden(err_msg)
# Clear all preivous report
utils.del_db_objects(
session, models.HealthCheckReport, cluster_id=cluster_id
)
from compass.tasks import client as celery_client
celery_client.celery.send_task(
'compass.tasks.cluster_health',
(cluster_id, send_report_url, user.email)
)
return {
"cluster_id": cluster_id,
"status": "start to check cluster health."
}

View File

@ -208,6 +208,31 @@ PERMISSION_UPDATE_CLUSTERHOST_STATE = PermissionWrapper(
'update clusterhost state',
'update clusterhost state'
)
PERMISSION_LIST_HEALTH_REPORT = PermissionWrapper(
'list_health_reports',
'list health check report',
'list health check report'
)
PERMISSION_GET_HEALTH_REPORT = PermissionWrapper(
'get_health_report',
'get health report',
'get health report'
)
PERMISSION_CHECK_CLUSTER_HEALTH = PermissionWrapper(
'start_check_cluster_health',
'start check cluster health',
'start check cluster health'
)
PERMISSION_SET_HEALTH_CHECK_ERROR = PermissionWrapper(
'set_error_state',
'set health check into error state',
'set health check into error state'
)
PERMISSION_DELETE_REPORT = PermissionWrapper(
'delete_reports',
'delete health reports',
'delete health reports'
)
PERMISSIONS = [
PERMISSION_LIST_PERMISSIONS,
PERMISSION_LIST_SWITCHES,
@ -258,6 +283,11 @@ PERMISSIONS = [
PERMISSION_DEL_CLUSTERHOST_CONFIG,
PERMISSION_GET_CLUSTERHOST_STATE,
PERMISSION_UPDATE_CLUSTERHOST_STATE,
PERMISSION_LIST_HEALTH_REPORT,
PERMISSION_GET_HEALTH_REPORT,
PERMISSION_CHECK_CLUSTER_HEALTH,
PERMISSION_SET_HEALTH_CHECK_ERROR,
PERMISSION_DELETE_REPORT
]

View File

@ -2466,6 +2466,8 @@ class Adapter(BASE, HelperMixin):
Boolean, default=False
)
health_check_cmd = Column(String(80))
supported_oses = relationship(
AdapterOS,
passive_deletes=True, passive_updates=True,
@ -2732,3 +2734,41 @@ class Subnet(BASE, TimestampMixin, HelperMixin):
if not self.name:
dict_info['name'] = self.subnet
return dict_info
HEALTH_REPORT_STATES = ('verifying', 'success', 'finished', 'error')
class HealthCheckReport(BASE, HelperMixin):
"""Health check report table."""
__tablename__ = 'health_check_report'
cluster_id = Column(
Integer,
ForeignKey('cluster.id', onupdate='CASCADE', ondelete='CASCADE'),
primary_key=True
)
name = Column(String(80), nullable=False, primary_key=True)
display_name = Column(String(100))
report = Column(JSONEncoded, default={})
category = Column(String(80), default='')
state = Column(
Enum(*HEALTH_REPORT_STATES, name='report_state'),
ColumnDefault('verifying'),
nullable=False
)
error_message = Column(Text, default='')
def __init__(self, cluster_id, name, **kwargs):
self.cluster_id = cluster_id
self.name = name
if 'state' in kwargs and kwargs['state'] not in HEALTH_REPORT_STATES:
err_msg = 'State value %s is not accepted.' % kwargs['state']
raise exception.InvalidParameter(err_msg)
super(HealthCheckReport, self).__init__(**kwargs)
def __str__(self):
return 'HealthCheckReport[cluster_id: %s, name: %s]' % (
self.cluster_id, self.name
)

View File

@ -69,6 +69,10 @@ class DeployManager(object):
return deployed_config
def check_cluster_health(self, callback_url):
logging.info("DeployManager check_cluster_health...........")
self.pk_installer.check_cluster_health(callback_url)
def clean_progress(self):
"""Clean previous installation log and progress."""
self.clean_os_installtion_progress()

View File

@ -86,6 +86,16 @@ class BaseConfigManager(object):
def get_cluster_os_config(self):
return deepcopy(self.__get_cluster_item(const.OS_CONFIG, {}))
def get_server_credentials(self):
cluster_os_config = self.get_cluster_os_config()
if not cluster_os_config:
logging.info("cluster os_config is None!")
return ()
username = cluster_os_config[const.SERVER_CREDS][const.USERNAME]
password = cluster_os_config[const.SERVER_CREDS][const.PASSWORD]
return (username, password)
def get_cluster_package_config(self):
return deepcopy(self.__get_cluster_item(const.PK_CONFIG, {}))
@ -309,6 +319,9 @@ class BaseConfigManager(object):
def get_dist_system_name(self):
return self.__get_adapter_item(const.NAME, None)
def get_adapter_health_check_cmd(self):
return self.__get_adapter_item(const.HEALTH_CHECK_CMD)
def get_os_installer_settings(self):
installer_info = self.__get_adapter_item(const.OS_INSTALLER, {})
return installer_info.setdefault(const.INSTALLER_SETTINGS, {})

View File

@ -627,3 +627,35 @@ class ChefInstaller(PKInstaller):
settings = self.config_manager.get_pk_installer_settings()
return settings.setdefault(self.CHEFSERVER_DNS, None)
def check_cluster_health(self, callback_url):
import chef
cluster_name = self.config_manager.get_clustername()
nodes = chef.Search(
'node',
'tags:rally_node AND name:*%s' % cluster_name,
api=self.chef_api
)
if not nodes:
err_msg = "Cannot find Rally node!"
logging.info(err_msg)
raise Exception(err_msg)
rally_node_name = None
for node in nodes:
rally_node_name = node.object.name
break
rally_node = chef.Node(rally_node_name, api=self.chef_api)
rally_node_ip = rally_node['ipaddress']
command = self.config_manager.get_adapter_health_check_cmd()
option = '--url %s --clustername %s' % (callback_url, cluster_name)
command = ' '.join((command, option))
username, pwd = self.config_manager.get_server_credentials()
util.execute_cli_by_ssh(
command, rally_node_ip, username=username,
password=pwd, nowait=True
)

View File

@ -34,6 +34,7 @@ DIST_SYS_NAME = 'distributed_system_name'
FLAVOR = 'flavor'
FLAVORS = 'flavors'
FLAVOR_NAME = 'flavor_name'
HEALTH_CHECK_CMD = 'health_check_cmd'
TMPL = 'template'
INSTALLER_SETTINGS = 'settings'
METADATA = 'metadata'
@ -77,4 +78,5 @@ OS_CONFIG_GENERAL = 'general'
PK_CONFIG = 'package_config'
ROLES = 'roles'
ROLES_MAPPING = 'roles_mapping'
SERVER_CREDS = 'server_credentials'
TMPL_VARS_DICT = 'vars_dict'

View File

@ -80,6 +80,19 @@ def pollswitch(
logging.exception(error)
@celery.task(name='compass.tasks.cluster_health')
def health_check(cluster_id, send_report_url, useremail):
"""Verify the deployed cluster functionally works.
:param cluster_id: ID of the cluster
:param send_report_url: The URL which reports should send back
"""
try:
deploy.health_check(cluster_id, send_report_url, useremail)
except Exception as error:
logging.exception(error)
@celery.task(name='compass.tasks.deploy_cluster')
def deploy_cluster(deployer_email, cluster_id, clusterhost_ids):
"""Deploy the given cluster.

View File

@ -25,6 +25,7 @@ os.environ['COMPASS_IGNORE_SETTING'] = 'true'
from compass.actions import deploy
from compass.actions import util
from compass.utils import setting_wrapper as setting
reload(setting)
@ -101,7 +102,7 @@ class TestDeployAction(unittest2.TestCase):
"package_config": {}
}
}
output = deploy.ActionHelper.get_adapter_info(1, 1, None)
output = util.ActionHelper.get_adapter_info(1, 1, None)
self.maxDiff = None
self.assertDictEqual(expected_output, output)
@ -165,6 +166,6 @@ class TestDeployAction(unittest2.TestCase):
"deployed_package_config": {}
}
}
output = deploy.ActionHelper.get_hosts_info(1, [1], None)
output = util.ActionHelper.get_hosts_info(1, [1], None)
self.maxDiff = None
self.assertDictEqual(expected_output, output)

View File

@ -0,0 +1,160 @@
#!/usr/bin/python
#
# Copyright 2014 Huawei Technologies Co. Ltd
#
# 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.
"""Test health check api."""
import os
import simplejson as json
os.environ['COMPASS_IGNORE_SETTING'] = 'true'
from compass.utils import setting_wrapper as setting
reload(setting)
from compass.db.api import cluster as cluster_db
from compass.db.api import health_check_report as health_check_db
from compass.db import models
from compass.tests.api.test_api import ApiTestCase
report_sample = {
"report": {
"actions": {
"neutron.create_network": {
"duration": {
"data": [1.105, 0.973],
"summary": {
"errors": 0,
"success": "100.0%",
"min (sec)": 0.973,
"avg (sec)": 1.04,
"max (sec)": 1.105,
"total": 2
}
}
},
"neutron.delete_network": {
"duration": {
"data": [1.038, 0.842],
"summary": {
"errors": 0,
"success": "100.0%",
"min (sec)": 0.842,
"avg (sec)": 0.940,
"max (sec)": 1.038,
"total": 2
}
}
}
},
"errors_info": []
},
"raw_output": {}
}
api_resp_tpml = {
"cluster_id": 1,
"name": "sample_name",
"report": {},
"state": "verifying",
"errors_message": ""
}
class TestHealthCheckAPI(ApiTestCase):
"""Test health check api."""
def setUp(self):
super(TestHealthCheckAPI, self).setUp()
self.cluster_id = 1
self.url = '/clusters/%s/healthreports' % self.cluster_id
def tearDown(self):
super(TestHealthCheckAPI, self).tearDown()
def test_add_and_list_reports(self):
# Create multiple reports
reports_list = [
{'name': 'rp1', 'category': 'c1'},
{'name': 'rp2', 'category': 'c2'},
{'name': 'rp3', 'category': 'c3'}
]
request_data = json.dumps({"report_list": reports_list})
return_value = self.test_client.post(self.url, data=request_data)
resp = json.loads(return_value.get_data())
self.assertEqual(200, return_value.status_code)
self.assertEqual(3, len(resp))
# Create one report
request_data = json.dumps({'name': 'rp4 test'})
return_value = self.test_client.post(self.url, data=request_data)
resp = json.loads(return_value.get_data())
self.assertEqual(200, return_value.status_code)
self.assertEqual('rp4-test', resp['name'])
# Create duplicate report
return_value = self.test_client.post(self.url, data=request_data)
self.assertEqual(409, return_value.status_code)
# List all reports
return_value = self.test_client.get(self.url)
resp = json.loads(return_value.get_data())
self.assertEqual(200, return_value.status_code)
self.assertEqual(4, len(resp))
def test_update_and_get_health_report(self):
report_name = 'test-report'
health_check_db.add_report_record(self.cluster_id, name=report_name)
url = '/'.join((self.url, report_name))
request_data = json.dumps(
{"report": report_sample, "state": "finished"}
)
return_value = self.test_client.put(url, data=request_data)
resp = json.loads(return_value.get_data())
self.maxDiff = None
self.assertEqual(200, return_value.status_code)
self.assertDictEqual(report_sample, resp['report'])
return_value = self.test_client.put(url, data=request_data)
self.assertEqual(403, return_value.status_code)
# Get report
return_value = self.test_client.get(url)
self.assertEqual(200, return_value.status_code)
self.assertDictEqual(report_sample, resp['report'])
def test_action_start_check_health(self):
url = '/clusters/%s/action' % self.cluster_id
request_data = json.dumps({'check_health': None})
# Cluster's state is not 'SUCCESSFUL' yet.
return_value = self.test_client.post(url, data=request_data)
self.assertEqual(403, return_value.status_code)
# Cluster has been deployed successfully.
user = models.User.query.filter_by(email='admin@huawei.com').first()
cluster_db.update_cluster_state(
user, self.cluster_id, state='SUCCESSFUL'
)
return_value = self.test_client.post(url, data=request_data)
self.assertEqual(202, return_value.status_code)

View File

@ -46,7 +46,7 @@ class TestListPermissions(BaseTest):
def test_list_permissions(self):
permissions = permission.list_permissions(self.user_object)
self.assertIsNotNone(permissions)
self.assertEqual(49, len(permissions))
self.assertEqual(54, len(permissions))
class TestGetPermission(BaseTest):

View File

@ -258,3 +258,68 @@ def get_switch_machines_from_file(filename):
})
return (switches, switch_machines)
def execute_cli_by_ssh(cmd, host, username, password=None,
keyfile='/root/.ssh/id_rsa', nowait=False):
"""SSH to execute script on remote machine
:param host: ip of the remote machine
:param username: username to access the remote machine
:param password: password to access the remote machine
:param cmd: command to execute
"""
if not cmd:
logging.error("No command found!")
raise Exception('No command found!')
if nowait:
cmd = "nohup %s >/dev/null 2>&1 &" % cmd
stdin = None
stdout = None
stderr = None
try:
import paramiko
from paramiko import ssh_exception
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
if password:
client.connect(host, username=username, password=password)
else:
client.load_system_host_keys()
client.connect(
host, username=username,
key_filename=keyfile, look_for_keys=True
)
stdin, stdout, stderr = client.exec_command(cmd)
result = stdout.readlines()
logging.info("result of command '%s' is '%s'!" % (cmd, result))
return result
except ImportError:
err_msg = "Cannot find Paramiko package!"
logging.error(err_msg)
raise ImportError(err_msg)
except (ssh_exception.BadHostKeyException,
ssh_exception.AuthenticationException,
ssh_exception.SSHException):
err_msg = 'SSH connection error or command execution failed!'
logging.error(err_msg)
raise Exception(err_msg)
except Exception as exc:
logging.error(
'Failed to execute command "%s", exception is %s' % (cmd, exc)
)
raise Exception(exc)
finally:
for resource in [stdin, stdout, stderr]:
if resource:
resource.close()
client.close()

View File

@ -5,3 +5,4 @@ PACKAGE_INSTALLER = 'chef_installer'
OS_INSTALLER = 'cobbler'
SUPPORTED_OS_PATTERNS = ['(?i)centos.*', '(?i)ubuntu.*']
DEPLOYABLE = True
HEALTH_CHECK_COMMAND = 'python /opt/compass/health_check.py'