mongo_config_file=self.args.mongo_config)
self.db_client = None
self.environments_collection = None
+ self.scans_collection = None
+ self.scheduled_scans_collection = None
@staticmethod
def get_args():
def _fail_scan(self, scan_request: dict):
self._finalize_scan(scan_request, ScanStatus.FAILED, False)
- def _complete_scan(self, scan_request: dict):
- self._finalize_scan(scan_request, ScanStatus.COMPLETED, True)
+ def _complete_scan(self, scan_request: dict, result_message: str):
+ status = ScanStatus.COMPLETED if result_message == 'ok' \
+ else ScanStatus.COMPLETED_WITH_ERRORS
+ self._finalize_scan(scan_request, status, True)
# PyCharm type checker can't reliably check types of document
# noinspection PyTypeChecker
'scan_only_links': scheduled_scan['scan_only_links'],
'scan_only_cliques': scheduled_scan['scan_only_cliques'],
'submit_timestamp': ts,
+ 'interval': interval,
'environment': scheduled_scan['environment'],
'inventory': 'inventory'
}
time.sleep(self.interval)
else:
scan_request = results[0]
- if not self.inv.is_feature_supported(scan_request.get('environment'),
- EnvironmentFeatures.SCANNING):
+ env = scan_request.get('environment')
+ scan_feature = EnvironmentFeatures.SCANNING
+ if not self.inv.is_feature_supported(env, scan_feature):
self.log.error("Scanning is not supported for env '{}'"
.format(scan_request.get('environment')))
self._fail_scan(scan_request)
continue
# update the status and timestamps.
- self.log.info("Request '{}' has been scanned."
- .format(scan_request['_id']))
+ self.log.info("Request '{}' has been scanned. ({})"
+ .format(scan_request['_id'], message))
end_time = datetime.datetime.utcnow()
scan_request['end_timestamp'] = end_time
- self._complete_scan(scan_request)
+ self._complete_scan(scan_request, message)
finally:
self._clean_up()
from utils.logging.full_logger import FullLogger
from utils.mongo_access import MongoAccess
from utils.ssh_conn import SshConn
-from utils.ssh_connection import SshConnection
+from utils.ssh_connection import SshConnection, SshError
class MonitoringHandler(MongoAccess, CliAccess, BinaryConverter):
self.mechanism_drivers = \
self.configuration.environment['mechanism_drivers']
self.env = env
+ self.had_errors = False
self.monitoring_config = self.db.monitoring_config_templates
try:
self.env_monitoring_config = self.configuration.get('Monitoring')
if self.provision < self.provision_levels['files']:
if self.provision == self.provision_levels['db']:
self.log.info('Monitoring config applied only in DB')
- return
+ return True
self.log.info('applying monitoring setup')
hosts = {}
scripts_to_hosts = {}
self.handle_pending_host_setup_changes(host_changes, hosts,
scripts_to_hosts)
if self.provision < self.provision_levels['deploy']:
- return
+ return True
if self.fetch_ssl_files:
self.deploy_ssl_files(list(scripts_to_hosts.keys()))
for host in scripts_to_hosts.values():
self.deploy_scripts_to_host(host)
for host in hosts.values():
self.deploy_config_to_target(host)
- self.log.info('done applying monitoring setup')
+ had_errors = ', with some error(s)' if self.had_errors else ''
+ self.log.info('done applying monitoring setup{}'.format(had_errors))
+ return not self.had_errors
def handle_pending_host_setup_changes(self, host_changes, hosts,
scripts_to_hosts):
remote_path = self.PRODUCTION_CONFIG_DIR
if os.path.isfile(local_dir):
remote_path += os.path.sep + os.path.basename(local_dir)
- self.write_to_server(local_dir,
- remote_path=remote_path,
- is_container=is_container)
+ try:
+ self.write_to_server(local_dir,
+ remote_path=remote_path,
+ is_container=is_container)
+ except SshError:
+ self.had_errors = True
elif is_local_host:
# write to production configuration directory on local host
self.make_directory(self.PRODUCTION_CONFIG_DIR)
# write to remote host prepare dir - use sftp
if self.provision < self.provision_levels['deploy']:
continue
- self.write_to_remote_host(host, changes['local_path'])
+ try:
+ self.write_to_remote_host(host, changes['local_path'])
+ except SshError:
+ self.had_errors = True
def prepare_scripts(self, host, is_server):
if self.scripts_prepared_for_host.get(host, False):
self.scripts_prepared_for_host[host] = True
def deploy_ssl_files(self, hosts: list):
- monitoring_server = self.env_monitoring_config['server_ip']
- gateway_host = SshConn.get_gateway_host(hosts[0])
- temp_dir = tempfile.TemporaryDirectory()
- for file_path in self.fetch_ssl_files:
- # copy SSL files from the monitoring server
- file_name = os.path.basename(file_path)
- local_path = os.path.join(temp_dir.name, file_name)
- self.get_file(monitoring_server, file_path, local_path)
- # first copy the files to the gateway
- self.write_to_remote_host(gateway_host, local_path,
- remote_path=file_path)
- ssl_path = os.path.commonprefix(self.fetch_ssl_files)
- for host in hosts:
- self.copy_from_gateway_to_host(host, ssl_path, ssl_path)
+ try:
+ monitoring_server = self.env_monitoring_config['server_ip']
+ gateway_host = SshConn.get_gateway_host(hosts[0])
+ temp_dir = tempfile.TemporaryDirectory()
+ for file_path in self.fetch_ssl_files:
+ # copy SSL files from the monitoring server
+ file_name = os.path.basename(file_path)
+ local_path = os.path.join(temp_dir.name, file_name)
+ self.get_file(monitoring_server, file_path, local_path)
+ # first copy the files to the gateway
+ self.write_to_remote_host(gateway_host, local_path,
+ remote_path=file_path)
+ ssl_path = os.path.commonprefix(self.fetch_ssl_files)
+ for host in hosts:
+ self.copy_from_gateway_to_host(host, ssl_path, ssl_path)
+ except SshError:
+ self.had_errors = True
def deploy_scripts_to_host(self, host_details):
- host = host_details['host']
- is_server = host_details['is_server']
- self.prepare_scripts(host, is_server)
- remote_path = self.REMOTE_SCRIPTS_FOLDER
- local_path = remote_path + os.path.sep + '*.py'
- if is_server:
- return # this was done earlier
- self.copy_from_gateway_to_host(host, local_path, remote_path)
+ try:
+ host = host_details['host']
+ is_server = host_details['is_server']
+ self.prepare_scripts(host, is_server)
+ remote_path = self.REMOTE_SCRIPTS_FOLDER
+ local_path = remote_path + os.path.sep + '*.py'
+ if is_server:
+ return # this was done earlier
+ self.copy_from_gateway_to_host(host, local_path, remote_path)
+ except SshError:
+ self.had_errors = True
def restart_service(self, host: str = None,
service: str = 'sensu-client',
cmd = 'sudo /etc/init.d/{} restart'.format(service)
log_msg = msg if msg else 'deploying config to host {}'.format(host)
self.log.info(log_msg)
- if is_server:
- ssh.exec(cmd)
- else:
- self.run(cmd, ssh_to_host=host, ssh=ssh)
+ try:
+ if is_server:
+ ssh.exec(cmd)
+ else:
+ self.run(cmd, ssh_to_host=host, ssh=ssh)
+ except SshError:
+ self.had_errors = True
def deploy_config_to_target(self, host_details):
- host = host_details['host']
- is_local_host = host_details['is_local_host']
- is_container = host_details['is_container']
- is_server = host_details['is_server']
- local_dir = host_details['local_dir']
- if is_container or is_server or not is_local_host:
- local_dir = os.path.dirname(local_dir)
- if not is_server:
- self.move_setup_files_to_remote_host(host, local_dir)
- # restart the Sensu client on the remote host,
- # so it takes the new setup
- self.restart_service(host)
+ try:
+ host = host_details['host']
+ is_local_host = host_details['is_local_host']
+ is_container = host_details['is_container']
+ is_server = host_details['is_server']
+ local_dir = host_details['local_dir']
+ if is_container or is_server or not is_local_host:
+ local_dir = os.path.dirname(local_dir)
+ if not is_server:
+ self.move_setup_files_to_remote_host(host, local_dir)
+ # restart the Sensu client on the remote host,
+ # so it takes the new setup
+ self.restart_service(host)
+ except SshError:
+ self.had_errors = True
def run_cmd_locally(self, cmd):
try:
import paramiko
from utils.binary_converter import BinaryConverter
+from discover.scan_error import ScanError
+class SshError(Exception):
+ pass
class SshConnection(BinaryConverter):
connections = {}
else self.DEFAULT_PORT,
password=self.pwd, timeout=30)
else:
+ port = None
try:
port = self.port if self.port is not None else self.DEFAULT_PORT
self.ssh_client.connect(self.host,
err_lines = [l for l in err.splitlines()
if 'Loaded plugin: ' not in l]
if err_lines:
- self.log.error("CLI access: \n" +
- "Host: {}\nCommand: {}\nError: {}\n".
- format(self.host, cmd, err))
+ msg = "CLI access: \nHost: {}\nCommand: {}\nError: {}\n"
+ msg = msg.format(self.host, cmd, err)
+ self.log.error(msg)
stderr.close()
stdout.close()
- return ""
+ raise SshError(msg)
ret = self.binary2str(stdout.read())
stderr.close()
stdout.close()
try:
self.ftp.put(local_path, remote_path)
except IOError as e:
- self.log.error('SFTP copy_file failed to copy file: ' +
- 'local: ' + local_path +
- ', remote host: ' + self.host +
- ', error: ' + str(e))
- return str(e)
+ msg = 'SFTP copy_file failed to copy file: ' \
+ 'local: {}, remote host: {}, error: {}' \
+ .format(local_path, self.host, str(e))
+ self.log.error(msg)
+ raise SshError(msg)
try:
remote_file = self.ftp.file(remote_path, 'a+')
except IOError as e:
try:
self.ftp.get(remote_path, local_path)
except IOError as e:
- self.log.error('SFTP copy_file_from_remote failed to copy file: '
- 'remote host: {}, '
- 'remote_path: {}, local: {}, error: {}'
- .format(self.host, remote_path, local_path, str(e)))
- return str(e)
+ msg = 'SFTP copy_file_from_remote failed to copy file: ' \
+ 'remote host: {}, remote_path: {}, local: {}, error: {}'
+ msg = msg.format(self.host, remote_path, local_path, str(e))
+ self.log.error(msg)
+ raise SshError(msg)
self.log.info('SFTP copy_file_from_remote success: host={},{} -> {}'.
format(self.host, remote_path, local_path))
return ''