Added code to set the install directory for ohai-solo
Added options to the ohai_solo install, remove and execute methods to allow installation of ohai-solo to somewhere other than /opt. This is required because it lets us get around some change control policies. Change-Id: I72d051f78c5316e6077891978c65a60ece1dd4de
This commit is contained in:
parent
c5c9a9d88e
commit
a21e120146
|
@ -4,5 +4,5 @@ paramiko>=1.13.0 # py33 support
|
||||||
pbr>=0.5.21,<1.0
|
pbr>=0.5.21,<1.0
|
||||||
python-novaclient>=2.15.0 # py33 support
|
python-novaclient>=2.15.0 # py33 support
|
||||||
pythonwhois>=2.1.0 # py33 support
|
pythonwhois>=2.1.0 # py33 support
|
||||||
six>=1.4.0
|
six>=1.8.0
|
||||||
tldextract>=1.2
|
tldextract>=1.2
|
||||||
|
|
|
@ -6,6 +6,6 @@ paramiko>=1.12.0 # ecdsa added
|
||||||
pbr>=0.5.21,<1.0
|
pbr>=0.5.21,<1.0
|
||||||
python-novaclient>=2.6.0.1 # breaks before
|
python-novaclient>=2.6.0.1 # breaks before
|
||||||
pythonwhois>=2.4.3
|
pythonwhois>=2.4.3
|
||||||
six>=1.4.0 # urllib introduced
|
six>=1.8.0 # six.moves.shlex introduced
|
||||||
tldextract>=1.2
|
tldextract>=1.2
|
||||||
argparse
|
argparse
|
||||||
|
|
|
@ -51,10 +51,12 @@ def get_systeminfo(ipaddress, config, interactive=False):
|
||||||
return system_info(client)
|
return system_info(client)
|
||||||
|
|
||||||
|
|
||||||
def system_info(client, with_install=False):
|
def system_info(client, with_install=False, install_dir=None):
|
||||||
"""Run ohai-solo on a remote system and gather the output.
|
"""Run ohai-solo on a remote system and gather the output.
|
||||||
|
|
||||||
:param client: :class:`ssh.SSH` instance
|
:param client: :class:`ssh.SSH` instance
|
||||||
|
:param with_install Will install ohai-solo if set to True
|
||||||
|
:param install_dir string containing directory to install to
|
||||||
:returns: dict -- system information from ohai-solo
|
:returns: dict -- system information from ohai-solo
|
||||||
:raises: SystemInfoCommandMissing, SystemInfoCommandOld, SystemInfoNotJson
|
:raises: SystemInfoCommandMissing, SystemInfoCommandOld, SystemInfoNotJson
|
||||||
SystemInfoMissingJson
|
SystemInfoMissingJson
|
||||||
|
@ -65,37 +67,46 @@ def system_info(client, with_install=False):
|
||||||
SystemInfoMissingJson if `ohai` does not return any JSON.
|
SystemInfoMissingJson if `ohai` does not return any JSON.
|
||||||
"""
|
"""
|
||||||
if with_install:
|
if with_install:
|
||||||
perform_install(client)
|
perform_install(client, install_dir=install_dir)
|
||||||
|
|
||||||
if client.is_windows():
|
if client.is_windows():
|
||||||
raise errors.UnsupportedPlatform(
|
raise errors.UnsupportedPlatform(
|
||||||
"ohai-solo is a linux-only sytem info provider. "
|
"ohai-solo is a linux-only sytem info provider. "
|
||||||
"Target platform was %s", client.platform_info['dist'])
|
"Target platform was %s", client.platform_info['dist'])
|
||||||
else:
|
|
||||||
command = "unset GEM_CACHE GEM_HOME GEM_PATH && sudo ohai-solo"
|
ohai_solo_prefix = (install_dir or '/opt')
|
||||||
output = client.execute(command, escalate=True, allow_many=False)
|
ohai_solo_command = six.moves.shlex_quote("%s/ohai-solo/bin/ohai-solo"
|
||||||
not_found_msgs = ["command not found", "Could not find ohai"]
|
% ohai_solo_prefix)
|
||||||
if any(m in k for m in not_found_msgs
|
command = ("unset GEM_CACHE GEM_HOME GEM_PATH && "
|
||||||
for k in list(output.values()) if isinstance(k,
|
"sudo %s" % ohai_solo_command)
|
||||||
six.string_types)):
|
|
||||||
LOG.warning("SystemInfoCommandMissing on host: [%s]", client.host)
|
output = client.execute(command, escalate=True, allow_many=False)
|
||||||
raise errors.SystemInfoCommandMissing("ohai-solo missing on %s" %
|
not_found_msgs = ["command not found", "Could not find ohai"]
|
||||||
client.host)
|
if any(m in k for m in not_found_msgs
|
||||||
# use string formatting to handle unicode
|
for k in list(output.values()) if isinstance(k,
|
||||||
unicode_output = "%s" % output['stdout']
|
six.string_types)):
|
||||||
|
LOG.warning("SystemInfoCommandMissing on host: [%s]", client.host)
|
||||||
|
raise errors.SystemInfoCommandMissing("ohai-solo missing on %s" %
|
||||||
|
client.host)
|
||||||
|
# use string formatting to handle unicode
|
||||||
|
unicode_output = "%s" % output['stdout']
|
||||||
|
try:
|
||||||
|
results = json.loads(unicode_output)
|
||||||
|
except ValueError as exc:
|
||||||
try:
|
try:
|
||||||
results = json.loads(unicode_output)
|
clean_output = get_json(unicode_output)
|
||||||
|
results = json.loads(clean_output)
|
||||||
except ValueError as exc:
|
except ValueError as exc:
|
||||||
try:
|
raise errors.SystemInfoNotJson(exc)
|
||||||
clean_output = get_json(unicode_output)
|
return results
|
||||||
results = json.loads(clean_output)
|
|
||||||
except ValueError as exc:
|
|
||||||
raise errors.SystemInfoNotJson(exc)
|
|
||||||
return results
|
|
||||||
|
|
||||||
|
|
||||||
def perform_install(client):
|
def perform_install(client, install_dir=None):
|
||||||
"""Install ohai-solo on remote system."""
|
"""Install ohai-solo on remote system.
|
||||||
|
|
||||||
|
:param client: :class:`ssh.SSH` instance
|
||||||
|
:param install_dir string containing directory to install to
|
||||||
|
"""
|
||||||
LOG.info("Installing (or updating) ohai-solo on device %s at %s:%d",
|
LOG.info("Installing (or updating) ohai-solo on device %s at %s:%d",
|
||||||
client.host, client.host, client.port)
|
client.host, client.host, client.port)
|
||||||
|
|
||||||
|
@ -119,6 +130,10 @@ def perform_install(client):
|
||||||
|
|
||||||
# Run install
|
# Run install
|
||||||
command = "bash install.sh"
|
command = "bash install.sh"
|
||||||
|
if install_dir:
|
||||||
|
command = "%s -t -i %s" % (command,
|
||||||
|
six.moves.shlex_quote(install_dir))
|
||||||
|
|
||||||
install_output = client.execute(command, cwd='/tmp',
|
install_output = client.execute(command, cwd='/tmp',
|
||||||
with_exit_code=True,
|
with_exit_code=True,
|
||||||
escalate=True, allow_many=False)
|
escalate=True, allow_many=False)
|
||||||
|
@ -137,9 +152,10 @@ def perform_install(client):
|
||||||
return install_output
|
return install_output
|
||||||
|
|
||||||
|
|
||||||
def remove_remote(client):
|
def remove_remote(client, install_dir=None):
|
||||||
"""Remove ohai-solo from specifc remote system.
|
"""Remove ohai-solo from specifc remote system.
|
||||||
|
|
||||||
|
:param install_dir string containing directory ohai-solo was installed in
|
||||||
Currently supports:
|
Currently supports:
|
||||||
- ubuntu [10.x, 12.x]
|
- ubuntu [10.x, 12.x]
|
||||||
- debian [6.x, 7.x]
|
- debian [6.x, 7.x]
|
||||||
|
@ -152,7 +168,10 @@ def remove_remote(client):
|
||||||
"Target platform was %s", client.platform_info['dist'])
|
"Target platform was %s", client.platform_info['dist'])
|
||||||
else:
|
else:
|
||||||
platform_info = client.platform_info
|
platform_info = client.platform_info
|
||||||
if client.is_debian():
|
if install_dir is not None:
|
||||||
|
install_dir = six.moves.shlex_quote("%s/ohai-solo/" % install_dir)
|
||||||
|
remove = 'rm -rf %s' % install_dir
|
||||||
|
elif client.is_debian():
|
||||||
remove = "dpkg --purge ohai-solo"
|
remove = "dpkg --purge ohai-solo"
|
||||||
elif client.is_fedora():
|
elif client.is_fedora():
|
||||||
remove = "yum -y erase ohai-solo"
|
remove = "yum -y erase ohai-solo"
|
||||||
|
|
|
@ -68,6 +68,39 @@ class TestOhaiInstall(utils.TestCase):
|
||||||
mock.call('rm install.sh', cwd='/tmp', escalate=True,
|
mock.call('rm install.sh', cwd='/tmp', escalate=True,
|
||||||
allow_many=False)])
|
allow_many=False)])
|
||||||
|
|
||||||
|
def test_perform_install_with_install_dir(self):
|
||||||
|
response = {'exit_code': 0, 'stdout': 'installed remote'}
|
||||||
|
self.mock_remotesshclient.execute.return_value = response
|
||||||
|
result = ohai_solo.perform_install(self.mock_remotesshclient,
|
||||||
|
install_dir='/home/bob')
|
||||||
|
self.assertEqual(result, response)
|
||||||
|
self.assertEqual(self.mock_remotesshclient.execute.call_count, 3)
|
||||||
|
self.mock_remotesshclient.execute.assert_has_calls([
|
||||||
|
mock.call('wget -N http://readonly.configdiscovery.'
|
||||||
|
'rackspace.com/install.sh', cwd='/tmp',
|
||||||
|
escalate=True, allow_many=False),
|
||||||
|
mock.call('bash install.sh -t -i /home/bob', cwd='/tmp',
|
||||||
|
with_exit_code=True, escalate=True, allow_many=False),
|
||||||
|
mock.call('rm install.sh', cwd='/tmp', escalate=True,
|
||||||
|
allow_many=False)])
|
||||||
|
|
||||||
|
def test_perform_install_with_install_dir_and_spaces(self):
|
||||||
|
response = {'exit_code': 0, 'stdout': 'installed remote'}
|
||||||
|
self.mock_remotesshclient.execute.return_value = response
|
||||||
|
result = ohai_solo.perform_install(self.mock_remotesshclient,
|
||||||
|
install_dir='/srv/a diff * dir')
|
||||||
|
self.assertEqual(result, response)
|
||||||
|
self.assertEqual(self.mock_remotesshclient.execute.call_count, 3)
|
||||||
|
self.mock_remotesshclient.execute.assert_has_calls([
|
||||||
|
mock.call('wget -N http://readonly.configdiscovery.'
|
||||||
|
'rackspace.com/install.sh', cwd='/tmp',
|
||||||
|
escalate=True, allow_many=False),
|
||||||
|
mock.call('bash install.sh -t -i \'/srv/a diff * dir\'',
|
||||||
|
cwd='/tmp', with_exit_code=True, escalate=True,
|
||||||
|
allow_many=False),
|
||||||
|
mock.call('rm install.sh', cwd='/tmp', escalate=True,
|
||||||
|
allow_many=False)])
|
||||||
|
|
||||||
def test_install_linux_remote_failed(self):
|
def test_install_linux_remote_failed(self):
|
||||||
response = {'exit_code': 1, 'stdout': "", "stderr": "FAIL"}
|
response = {'exit_code': 1, 'stdout': "", "stderr": "FAIL"}
|
||||||
self.mock_remotesshclient.execute.return_value = response
|
self.mock_remotesshclient.execute.return_value = response
|
||||||
|
@ -108,6 +141,28 @@ class TestOhaiRemove(utils.TestCase):
|
||||||
self.assertRaises(errors.UnsupportedPlatform,
|
self.assertRaises(errors.UnsupportedPlatform,
|
||||||
ohai_solo.remove_remote, self.mock_remotesshclient)
|
ohai_solo.remove_remote, self.mock_remotesshclient)
|
||||||
|
|
||||||
|
def test_remove_remote_with_install_dir(self):
|
||||||
|
self.mock_remotesshclient.is_debian.return_value = True
|
||||||
|
self.mock_remotesshclient.is_fedora.return_value = False
|
||||||
|
response = {'exit_code': 0, 'foo': 'bar'}
|
||||||
|
self.mock_remotesshclient.execute.return_value = response
|
||||||
|
result = ohai_solo.remove_remote(self.mock_remotesshclient,
|
||||||
|
install_dir='/home/srv')
|
||||||
|
self.assertEqual(result, response)
|
||||||
|
self.mock_remotesshclient.execute.assert_called_once_with(
|
||||||
|
'rm -rf /home/srv/ohai-solo/', cwd='/tmp', escalate=True)
|
||||||
|
|
||||||
|
def test_remove_remote_with_install_dir_and_spaces(self):
|
||||||
|
self.mock_remotesshclient.is_debian.return_value = True
|
||||||
|
self.mock_remotesshclient.is_fedora.return_value = False
|
||||||
|
response = {'exit_code': 0, 'foo': 'bar'}
|
||||||
|
self.mock_remotesshclient.execute.return_value = response
|
||||||
|
result = ohai_solo.remove_remote(self.mock_remotesshclient,
|
||||||
|
install_dir='/srv/a dir')
|
||||||
|
self.assertEqual(result, response)
|
||||||
|
self.mock_remotesshclient.execute.assert_called_once_with(
|
||||||
|
'rm -rf \'/srv/a dir/ohai-solo/\'', cwd='/tmp', escalate=True)
|
||||||
|
|
||||||
|
|
||||||
class TestSystemInfo(utils.TestCase):
|
class TestSystemInfo(utils.TestCase):
|
||||||
|
|
||||||
|
@ -124,7 +179,34 @@ class TestSystemInfo(utils.TestCase):
|
||||||
}
|
}
|
||||||
ohai_solo.system_info(self.mock_remotesshclient)
|
ohai_solo.system_info(self.mock_remotesshclient)
|
||||||
self.mock_remotesshclient.execute.assert_called_with(
|
self.mock_remotesshclient.execute.assert_called_with(
|
||||||
"unset GEM_CACHE GEM_HOME GEM_PATH && sudo ohai-solo",
|
"unset GEM_CACHE GEM_HOME GEM_PATH && "
|
||||||
|
"sudo /opt/ohai-solo/bin/ohai-solo",
|
||||||
|
escalate=True, allow_many=False)
|
||||||
|
|
||||||
|
def test_system_info_with_install_dir(self):
|
||||||
|
self.mock_remotesshclient.execute.return_value = {
|
||||||
|
'exit_code': 0,
|
||||||
|
'stdout': "{}",
|
||||||
|
'stderr': ""
|
||||||
|
}
|
||||||
|
ohai_solo.system_info(self.mock_remotesshclient,
|
||||||
|
install_dir='/home/user')
|
||||||
|
self.mock_remotesshclient.execute.assert_called_with(
|
||||||
|
"unset GEM_CACHE GEM_HOME GEM_PATH && "
|
||||||
|
"sudo /home/user/ohai-solo/bin/ohai-solo",
|
||||||
|
escalate=True, allow_many=False)
|
||||||
|
|
||||||
|
def test_system_info_with_install_dir_with_spaces(self):
|
||||||
|
self.mock_remotesshclient.execute.return_value = {
|
||||||
|
'exit_code': 0,
|
||||||
|
'stdout': "{}",
|
||||||
|
'stderr': ""
|
||||||
|
}
|
||||||
|
ohai_solo.system_info(self.mock_remotesshclient,
|
||||||
|
install_dir='/sys/omg * " lol/')
|
||||||
|
self.mock_remotesshclient.execute.assert_called_with(
|
||||||
|
"unset GEM_CACHE GEM_HOME GEM_PATH && "
|
||||||
|
'sudo \'/sys/omg * " lol//ohai-solo/bin/ohai-solo\'',
|
||||||
escalate=True, allow_many=False)
|
escalate=True, allow_many=False)
|
||||||
|
|
||||||
def test_system_info_with_motd(self):
|
def test_system_info_with_motd(self):
|
||||||
|
@ -135,7 +217,8 @@ class TestSystemInfo(utils.TestCase):
|
||||||
}
|
}
|
||||||
ohai_solo.system_info(self.mock_remotesshclient)
|
ohai_solo.system_info(self.mock_remotesshclient)
|
||||||
self.mock_remotesshclient.execute.assert_called_with(
|
self.mock_remotesshclient.execute.assert_called_with(
|
||||||
"unset GEM_CACHE GEM_HOME GEM_PATH && sudo ohai-solo",
|
"unset GEM_CACHE GEM_HOME GEM_PATH && "
|
||||||
|
"sudo /opt/ohai-solo/bin/ohai-solo",
|
||||||
escalate=True, allow_many=False)
|
escalate=True, allow_many=False)
|
||||||
|
|
||||||
def test_system_info_bad_json(self):
|
def test_system_info_bad_json(self):
|
||||||
|
@ -174,6 +257,5 @@ class TestSystemInfo(utils.TestCase):
|
||||||
self.assertRaises(errors.SystemInfoCommandMissing,
|
self.assertRaises(errors.SystemInfoCommandMissing,
|
||||||
ohai_solo.system_info, self.mock_remotesshclient)
|
ohai_solo.system_info, self.mock_remotesshclient)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
Loading…
Reference in New Issue