Bug 1303635

Summary: [ovirt-shell] sys.stdin.flush() issue on BSD, MacOS
Product: [oVirt] ovirt-engine-cli Reporter: Jiri Belka <jbelka>
Component: CoreAssignee: Juan Hernández <juan.hernandez>
Status: CLOSED CURRENTRELEASE QA Contact: Jiri Belka <jbelka>
Severity: medium Docs Contact:
Priority: unspecified    
Version: 3.6.2.0CC: bugs, jbelka, juan.hernandez, oourfali, sbonazzo
Target Milestone: ovirt-4.0.2Flags: rule-engine: ovirt-4.0.z+
rule-engine: planning_ack+
juan.hernandez: devel_ack+
pnovotny: testing_ack+
Target Release: 3.6.8.0   
Hardware: x86_64   
OS: Other   
Whiteboard:
Fixed In Version: ovirt-engine-cli-3.6.8.0 Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2016-08-12 14:31:43 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: Infra RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Jiri Belka 2016-02-01 14:19:00 UTC
Description of problem:

Makes *BSD happy, otherwise:

$ ovirt-shell  
Traceback (most recent call last):
  File "/usr/local/bin/ovirt-shell", line 9, in <module>
    load_entry_point('ovirt-shell==3.6.0.2', 'console_scripts', 'ovirt-shell')()
  File "/usr/local/lib/python2.7/site-packages/ovirtcli/main.py", line 38, in main
    shell.onecmd_loop()
  File "/usr/local/lib/python2.7/site-packages/ovirtcli/shell/engineshell.py", line 334, in onecmd_loop
    self.context._collect_connection_data()
  File "/usr/local/lib/python2.7/site-packages/cli/context.py", line 126, in _collect_connection_data
    sys.stdin.flush()
IOError: [Errno 9] Bad file descriptor

--- /usr/local/lib/python2.7/site-packages/cli/context.py.orig  Mon Feb  1 15:10:28 2016
+++ /usr/local/lib/python2.7/site-packages/cli/context.py       Mon Feb  1 15:10:45 2016
@@ -123,7 +123,10 @@ class ExecutionContext(object):
         except EOFError:
             sys.exit('')
         finally:
-            sys.stdin.flush()
+            try:
+                sys.stdin.flush()
+            except IOError:
+                pass
 
     def __option_error(self, opt):
         from cli.messages import Messages

Version-Release number of selected component (if applicable):
ovirt-engine-cli-3.6.0.2

How reproducible:
100%

Steps to Reproduce:
1. install openbsd, python2.7
2. install ovirt-engine-cli
3. ovirt-shell

Actual results:
$ ovirt-shell  
Traceback (most recent call last):
  File "/usr/local/bin/ovirt-shell", line 9, in <module>
    load_entry_point('ovirt-shell==3.6.0.2', 'console_scripts', 'ovirt-shell')()
  File "/usr/local/lib/python2.7/site-packages/ovirtcli/main.py", line 38, in main
    shell.onecmd_loop()
  File "/usr/local/lib/python2.7/site-packages/ovirtcli/shell/engineshell.py", line 334, in onecmd_loop
    self.context._collect_connection_data()
  File "/usr/local/lib/python2.7/site-packages/cli/context.py", line 126, in _collect_connection_data
    sys.stdin.flush()
IOError: [Errno 9] Bad file descriptor

Expected results:
should work

Additional info:
http://bugs.python.org/msg133871

~~~
In python 2.x, sys.stdin.flush() is more or less equivalent to C fflush(stdin).  The behavior of fflush() on streams that are open for reading only is undefined. [1]

Python 3.x io does not use C stdio library and therefore it is not surprising that the behavior is different.

[1] http://pubs.opengroup.org/onlinepubs/009695399/functions/fflush.html
~~~

Comment 1 Juan Hernández 2016-02-01 15:14:49 UTC
Actually I think that we don't need that "flush" at all, as flushing an input stream shouldn't have any effect. Jiri, I verified that just removing that line works file in Linux. Can you check if it works in your BSD/MacOS environment?

Comment 2 Jiri Belka 2016-02-01 16:20:53 UTC
Without that 'finally' block it runs too.

Comment 3 Jiri Belka 2016-06-24 10:57:13 UTC
there's no ovirt-engine-cli 4.x rpm, thus the code lives only in git/source but rpms have old code.

please move on_qa when a rpm will be ready, thx.

[root@jb-rhevm40 ~]# cat /usr/lib/python2.7/site-packages/cli/context.py | sed -n '120,130p'
                    self.settings['ovirt-shell:password'] = getpass.getpass()
        except KeyboardInterrupt:
            sys.exit('')
        except EOFError:
            sys.exit('')
        finally:
            sys.stdin.flush()

    def __option_error(self, opt):
        from cli.messages import Messages
        sys.exit('\n' + Messages.Error.NO_SUCH_OPTION % opt + '\n')
[root@jb-rhevm40 ~]# rpm -q ovirt-engine-cli
ovirt-engine-cli-3.6.7.0-1.el7ev.noarch
[root@jb-rhevm40 ~]# rpm -q ovirt-engine
ovirt-engine-4.0.0.6-0.1.el7ev.noarch

Comment 4 Jiri Belka 2016-07-29 08:33:47 UTC
ok

# rpm2cpio ovirt-engine-cli-3.6.8.1-1.el7.centos.noarch.rpm | cpio --to-stdout -i './usr/lib/python2.7/site-packages/cli/context.py' 2>/dev/null | sed -n '120,130p'
                    self.settings['ovirt-shell:password'] = getpass.getpass()
        except KeyboardInterrupt:
            sys.exit('')
        except EOFError:
            sys.exit('')

    def __option_error(self, opt):
        from cli.messages import Messages
        sys.exit('\n' + Messages.Error.NO_SUCH_OPTION % opt + '\n')

    def __is_option_specified_in_cli_args(self, optionname):