147 lines
5.0 KiB
Python
147 lines
5.0 KiB
Python
# 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.
|
|
#
|
|
"""Ohai Solo Data Plane Discovery Module."""
|
|
|
|
import json
|
|
import logging
|
|
|
|
import six
|
|
|
|
from satori import errors
|
|
from satori import ssh
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
if six.PY3:
|
|
def unicode(text, errors=None): # noqa
|
|
"""A hacky Python 3 version of unicode() function."""
|
|
return str(text)
|
|
|
|
|
|
def get_systeminfo(ipaddress, config, interactive=False):
|
|
"""Run data plane discovery using this module against a host.
|
|
|
|
:param ipaddress: address to the host to discover.
|
|
:param config: arguments and configuration suppplied to satori.
|
|
:keyword interactive: whether to prompt the user for information.
|
|
"""
|
|
ssh_client = ssh.connect(ipaddress, username=config.host_username,
|
|
private_key=config.host_key,
|
|
interactive=interactive)
|
|
install_remote(ssh_client)
|
|
return system_info(ssh_client)
|
|
|
|
|
|
def system_info(ssh_client):
|
|
"""Run ohai-solo on a remote system and gather the output.
|
|
|
|
:param ssh_client: :class:`ssh.SSH` instance
|
|
:returns: dict -- system information from ohai-solo
|
|
:raises: SystemInfoCommandMissing, SystemInfoCommandOld, SystemInfoNotJson
|
|
SystemInfoMissingJson
|
|
|
|
SystemInfoCommandMissing if `ohai` is not installed.
|
|
SystemInfoCommandOld if `ohai` is not the latest.
|
|
SystemInfoNotJson if `ohai` does not return valid JSON.
|
|
SystemInfoMissingJson if `ohai` does not return any JSON.
|
|
"""
|
|
output = ssh_client.remote_execute("sudo -i ohai-solo")
|
|
not_found_msgs = ["command not found", "Could not find ohai"]
|
|
if any(m in k for m in not_found_msgs
|
|
for k in list(output.values()) if isinstance(k, six.string_types)):
|
|
LOG.warning("SystemInfoCommandMissing on host: [%s]", ssh_client.host)
|
|
raise errors.SystemInfoCommandMissing("ohai-solo missing on %s",
|
|
ssh_client.host)
|
|
unicode_output = unicode(output['stdout'], errors='replace')
|
|
try:
|
|
results = json.loads(unicode_output)
|
|
except ValueError as exc:
|
|
try:
|
|
clean_output = get_json(unicode_output)
|
|
results = json.loads(clean_output)
|
|
except ValueError as exc:
|
|
raise errors.SystemInfoNotJson(exc)
|
|
return results
|
|
|
|
|
|
def is_debian(platform):
|
|
"""Return true if the platform is a debian-based distro."""
|
|
return platform['dist'].lower() in ['debian', 'ubuntu']
|
|
|
|
|
|
def is_fedora(platform):
|
|
"""Return true if the platform is a fedora-based distro."""
|
|
return platform['dist'].lower() in ['redhat', 'centos', 'fedora', 'el']
|
|
|
|
|
|
def install_remote(ssh_client):
|
|
"""Install ohai-solo on remote system."""
|
|
LOG.info("Installing (or updating) ohai-solo on device %s at %s:%d",
|
|
ssh_client.host, ssh_client.host, ssh_client.port)
|
|
# Download to host
|
|
command = "cd /tmp && sudo wget -N http://ohai.rax.io/install.sh"
|
|
ssh_client.remote_execute(command)
|
|
|
|
# Run install
|
|
command = "cd /tmp && bash install.sh"
|
|
output = ssh_client.remote_execute(command, with_exit_code=True)
|
|
|
|
# Be a good citizen and clean up your tmp data
|
|
command = "cd /tmp && rm install.sh"
|
|
ssh_client.remote_execute(command)
|
|
|
|
# Process install command output
|
|
if output['exit_code'] != 0:
|
|
raise errors.SystemInfoCommandInstallFailed(output['stderr'][:256])
|
|
else:
|
|
return output
|
|
|
|
|
|
def remove_remote(ssh_client):
|
|
"""Remove ohai-solo from specifc remote system.
|
|
|
|
Currently supports:
|
|
- ubuntu [10.x, 12.x]
|
|
- debian [6.x, 7.x]
|
|
- redhat [5.x, 6.x]
|
|
- centos [5.x, 6.x]
|
|
"""
|
|
platform_info = ssh_client.platform_info
|
|
if is_debian(platform_info):
|
|
remove = "sudo dpkg --purge ohai-solo"
|
|
elif is_fedora(platform_info):
|
|
remove = "sudo yum -y erase ohai-solo"
|
|
else:
|
|
raise errors.UnsupportedPlatform("Unknown distro: %s" %
|
|
platform_info['dist'])
|
|
command = "cd /tmp && %s" % remove
|
|
output = ssh_client.remote_execute(command)
|
|
return output
|
|
|
|
|
|
def get_json(data):
|
|
"""Find the JSON string in data and return a string.
|
|
|
|
:param data: :string:
|
|
:returns: string -- JSON string striped of non-JSON data
|
|
:raises: SystemInfoMissingJson
|
|
|
|
SystemInfoMissingJson if `ohai` does not return any JSON.
|
|
"""
|
|
try:
|
|
first = data.index('{')
|
|
last = data.rindex('}')
|
|
return data[first:last + 1]
|
|
except ValueError as e:
|
|
context = {"ValueError": "%s" % e}
|
|
raise errors.SystemInfoMissingJson(context)
|