Skip to content
This repository has been archived by the owner on Apr 7, 2022. It is now read-only.

Commit

Permalink
Add SSHDummy for dev appliance
Browse files Browse the repository at this point in the history
  • Loading branch information
mshriver committed Jul 9, 2019
1 parent d712e53 commit 2146903
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 8 deletions.
31 changes: 23 additions & 8 deletions cfme/utils/appliance/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
from cfme.utils.path import data_path
from cfme.utils.path import patches_path
from cfme.utils.path import scripts_path
from cfme.utils.ssh import SSHDummy
from cfme.utils.ssh import SSHTail
from cfme.utils.version import get_stream
from cfme.utils.version import Version
Expand Down Expand Up @@ -337,6 +338,7 @@ class IPAppliance(object):
'ssh_port': 'ssh_port',
'project': 'project',
'version': 'version',
'root_dir': 'root_dir', # manageIQ source dir for dev appliance
}
CONFIG_NONGLOBAL = {'hostname'}
PROTOCOL_PORT_MAPPING = {'http': 80, 'https': 443}
Expand Down Expand Up @@ -374,7 +376,7 @@ def from_json(cls, json_string):
def __init__(
self, hostname, ui_protocol='https', ui_port=None, browser_steal=False, project=None,
container=None, openshift_creds=None, db_host=None, db_port=None, ssh_port=None,
is_dev=False, version=None,
is_dev=False, version=None, root_dir=None,
):
if not isinstance(hostname, six.string_types):
raise TypeError('Appliance\'s hostname must be a string!')
Expand Down Expand Up @@ -1018,6 +1020,9 @@ def ssh_client(self):
The credentials default to those found under ``ssh`` key in ``credentials.yaml``.
"""
if self.is_dev:
logger.warning('Using a Dummy SSH object for dev appliance')
return SSHDummy()
logger.debug('Waiting for SSH to %s to become connective.',
self.hostname)
self.wait_for_ssh()
Expand Down Expand Up @@ -1793,7 +1798,10 @@ def wait_for_ssh(self, timeout=600):
Args:
timeout: Number of seconds to wait until timeout (default ``600``)
"""
wait_for(func=lambda: self.is_ssh_running,
if self.is_dev:
return
wait_for(func=getattr,
func_args=[self, 'is_ssh_running'],
message='appliance.is_ssh_running',
delay=5,
num_sec=timeout)
Expand Down Expand Up @@ -1833,7 +1841,8 @@ def wait_for_embedded_ansible(self, timeout=1200):
timeout *= 2

wait_for(
func=lambda: self.is_embedded_ansible_running,
func=getattr,
func_args=[self, 'is_embedded_ansible_running'],
message='appliance.is_embedded_ansible_running',
delay=60,
num_sec=timeout
Expand All @@ -1851,7 +1860,8 @@ def get_host_address(self):

def wait_for_host_address(self):
try:
wait_for(func=lambda: self.get_host_address,
wait_for(func=getattr,
func_args=[self, 'get_host_address'],
fail_condition=None,
delay=5,
num_sec=120,
Expand All @@ -1863,6 +1873,8 @@ def wait_for_host_address(self):

@property
def is_ssh_running(self):
if self.is_dev:
return True # shortcut without blocking logic
if self.openshift_creds and 'hostname' in self.openshift_creds:
hostname = self.openshift_creds['hostname']
else:
Expand All @@ -1888,14 +1900,17 @@ def is_idle(self):
True if appliance is idling for longer or equal to idle_time seconds.
False if appliance is not idling for longer or equal to idle_time seconds.
"""
# TODO Handle is_dev
idle_time = 3600
ssh_output = self.ssh_client.run_command('if [ $((`date "+%s"` - `date -d "$(egrep -v '
ssh_output = self.ssh_client.run_command(
'if [ $((`date "+%s"` - `date -d "$(egrep -v '
r'"(Processing by Api::ApiController\#index as JSON|Started GET "/api" for '
'127.0.0.1|Completed 200 OK in)" /var/www/miq/vmdb/log/production.log | tail -1 |cut '
'-d"[" -f3 | cut -d"]" -f1 | cut -d" " -f1)\" \"+%s\"`)) -lt {} ];'
'127.0.0.1|Completed 200 OK in)" {} | tail -1 |cut '
r'-d"[" -f3 | cut -d"]" -f1 | cut -d" " -f1)\" \"+%s\"`)) -lt {} ];'
'then echo "False";'
'else echo "True";'
'fi;'.format(idle_time))
'fi;'.format('/var/www/miq/vmdb/log/production.log', idle_time)
)
return True if 'True' in ssh_output else False

@cached_property
Expand Down
29 changes: 29 additions & 0 deletions cfme/utils/ssh.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,12 @@ def failed(self):
return self.rc != 0


class SSHResultDummy(SSHResult):
""" Dummy result class to handle partial calls with extra kwargs for SSHClient methods"""
def __init__(self, command, rc, output, *args, **kwargs):
SSHResult.__init__(self, command, rc, output)


_ssh_key_file = project_path.join('.generated_ssh_key')
_ssh_pubkey_file = project_path.join('.generated_ssh_key.pub')

Expand Down Expand Up @@ -782,6 +788,29 @@ def lines_as_list(self):
return list(self)


class SSHDummy(object):
"""Dummy object that support contextmanager and just returns a logger.info bound method
This is for dev appliances that don't support ssh
Framework/tests that use appliance.ssh_client will end up just logging what they would have run
"""
def __enter__(self, *args, **kwargs):
return self

def __exit__(self, *args, **kwargs):
pass

@staticmethod
def is_appliance_downstream(self):
return False

def __getattr__(self, item):
if item in ['run_command', 'run_rails_command', 'run_rails_console', 'run_rake_command']:
logger.error('Cannot run ssh against a dev appliance, SSH function call skipped: %s',
item)
from functools import partial
return partial(SSHResultDummy, rc=1, output=None)


def keygen():
"""Generate temporary ssh keypair for appliance SSH auth
Expand Down

0 comments on commit 2146903

Please sign in to comment.