[PATCH v3 0/3] Github #329: Kimchi must not run as root

From: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com> After reading the comments from Zhou Zheng Sheng, I simplified the work I did in version 2 to run only one cherrypy process instead of two processes, one for frontend and another for the backend. Nginx is still being used as a reverse proxy to allow kimchid to run as root, but not being exposed to the outside. As Zhou mentioned, it is to little avail to run frontend and backend separately if the exposed port is running by the reverse proxy anyway. He mentioned the RPC approach as a best long-term approach, which I agree. We can solve this issue right now and the work in a more suitable solution, such as RPC, and then ditch nginx. Daniel Henrique Barboza (3): Github #329: kimchid script changes Github #329: nginx proxy template Github #329: .gitignore, spec and readme changes .gitignore | 1 + contrib/kimchi.spec.fedora.in | 2 + contrib/kimchi.spec.suse.in | 2 + docs/README.md | 4 +- src/kimchid.in | 111 ++++++++++++++++++++++++++++++++++++++---- src/nginx.conf.in | 55 +++++++++++++++++++++ 6 files changed, 164 insertions(+), 11 deletions(-) create mode 100644 src/nginx.conf.in -- 1.8.3.1

From: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com> The kimchid script is now launching a reverse proxy (nginx) that will forward all requests made to the kimchi port to the kimchid process running as root in a different port, which can be made inacessible to the outside using firewall rules. Signed-off-by: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com> --- src/kimchid.in | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 102 insertions(+), 9 deletions(-) diff --git a/src/kimchid.in b/src/kimchid.in index 8b63b57..fd755eb 100644 --- a/src/kimchid.in +++ b/src/kimchid.in @@ -16,13 +16,18 @@ # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA import logging import os +import signal +import subprocess import sys sys.path.insert(1, '@pythondir@') +from string import Template + import kimchi.server import kimchi.config @@ -35,7 +40,63 @@ if not paths.installed: ACCESS_LOG = "kimchi-access.log" ERROR_LOG = "kimchi-error.log" + +def create_proxy_config(p_port, k_port, + p_ssl_port, k_ssl_port): + """Create nginx configuration file based on current ports config + + To allow flexibility in which port kimchi runs, we need the same + flexibility with the nginx proxy. This method creates the config + file dynamically by using 'nginx.conf.in' as a template, creating + the file 'nginx_kimchi.config' which will be used to launch the + proxy. + + Arguments: + p_port - proxy port + kimchid_port - kimchid port + p_ssl_port - proxy SSL port + kimchid_ssl_port - kimchid SSL port + """ + + # get SSL paths to be used by the proxy + config_dir = paths.conf_dir + cert = '%s/kimchi-cert.pem' % config_dir + key = '%s/kimchi-key.pem' % config_dir + + with open(os.path.join(config_dir, "nginx.conf.in")) as template: + data = template.read() + + data = Template(data) + data = data.safe_substitute(proxy_port=p_port, + kimchid_port=k_port, + proxy_ssl_port=p_ssl_port, + kimchid_ssl_port=k_ssl_port, + cert_pem=cert, cert_key=key) + + config_file = open(os.path.join(config_dir, "nginx_kimchi.conf"), "w") + config_file.write(data) + config_file.close() + + +def start_proxy(): + """Start nginx reverse proxy.""" + config_dir = paths.conf_dir + config_file = "%s/nginx_kimchi.conf" % config_dir + cmd = ['nginx', '-c', config_file] + subprocess.call(cmd) + + +def terminate_proxy(): + """Stop nginx process.""" + term_proxy_cmd = ['nginx', '-s', 'stop'] + subprocess.call(term_proxy_cmd) + + def main(options): + # Script must run as root or with sudo. + if not os.geteuid() == 0: + sys.exit("\nMust be root to run this script. Exiting ...\n") + host = config.get("server", "host") port = config.get("server", "port") ssl_port = config.get("server", "ssl_port") @@ -44,20 +105,52 @@ def main(options): logLevel = config.get("logging", "log_level") parser = OptionParser() - parser.add_option('--host', type="string", default=host, help="Hostname to listen on") - parser.add_option('--port', type="int", default=port, help="Port to listen on") - parser.add_option('--ssl-port', type="int", default=ssl_port, help="Enable a SSL server on the given port") - parser.add_option('--log-level', default=logLevel, help="Logging level") - parser.add_option('--access-log', default=os.path.join(logDir,ACCESS_LOG), help="Access log file") - parser.add_option('--error-log', default=os.path.join(logDir,ERROR_LOG), help="Error log file") - parser.add_option('--environment', default=runningEnv, help="Running environment of kimchi server") - parser.add_option('--test', action='store_true', help="Run server in mock model") + parser.add_option('--host', type="string", default=host, + help="Hostname to listen on") + parser.add_option('--port', type="int", default=port, + help="Port to listen on") + parser.add_option('--ssl-port', type="int", default=ssl_port, + help="Enable a SSL server on the given port") + parser.add_option('--log-level', default=logLevel, + help="Logging level") + parser.add_option('--access-log', + default=os.path.join(logDir, ACCESS_LOG), + help="Access log file") + parser.add_option('--error-log', + default=os.path.join(logDir, ERROR_LOG), + help="Error log file") + parser.add_option('--environment', default=runningEnv, + help="Running environment of kimchi server") + parser.add_option('--test', action='store_true', + help="Run server in mock model") (options, args) = parser.parse_args() # Add non-option arguments setattr(options, 'ssl_cert', config.get('server', 'ssl_cert')) setattr(options, 'ssl_key', config.get('server', 'ssl_key')) + # The following method is used when the process receives a + # SIGINT signal (CTRL+C). + def terminate_kimchi(signal, frame): + terminate_proxy() + sys.exit(0) + signal.signal(signal.SIGINT, terminate_kimchi) + + proxy_port = options.port + proxy_ssl_port = options.ssl_port + + # The max value between port and proxy_port + # will be used to calculate kimchid ports. + next_port = max(proxy_port, proxy_ssl_port) + 1 + options.port = next_port + next_port += 1 + options.ssl_port = next_port + + # Launch reverse proxy: create config file and start. + create_proxy_config(proxy_port, options.port, + proxy_ssl_port, options.ssl_port) + start_proxy() + kimchi.server.main(options) if __name__ == '__main__': -- 1.8.3.1

On 04/10/2014 05:44 PM, Daniel Barboza wrote:
From: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com>
The kimchid script is now launching a reverse proxy (nginx) that will forward all requests made to the kimchi port to the kimchid process running as root in a different port, which can be made inacessible to the outside using firewall rules.
Signed-off-by: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com> --- src/kimchid.in | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 102 insertions(+), 9 deletions(-)
diff --git a/src/kimchid.in b/src/kimchid.in index 8b63b57..fd755eb 100644 --- a/src/kimchid.in +++ b/src/kimchid.in @@ -16,13 +16,18 @@ # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA
You don't need to break line here. Just remove the extra space "02110-1301 USA" to achieve the 80 characters.
import logging import os +import signal +import subprocess import sys sys.path.insert(1, '@pythondir@')
+from string import Template + import kimchi.server import kimchi.config
@@ -35,7 +40,63 @@ if not paths.installed: ACCESS_LOG = "kimchi-access.log" ERROR_LOG = "kimchi-error.log"
+ +def create_proxy_config(p_port, k_port, + p_ssl_port, k_ssl_port): + """Create nginx configuration file based on current ports config + + To allow flexibility in which port kimchi runs, we need the same + flexibility with the nginx proxy. This method creates the config + file dynamically by using 'nginx.conf.in' as a template, creating + the file 'nginx_kimchi.config' which will be used to launch the + proxy. + + Arguments: + p_port - proxy port + kimchid_port - kimchid port + p_ssl_port - proxy SSL port + kimchid_ssl_port - kimchid SSL port + """ + + # get SSL paths to be used by the proxy + config_dir = paths.conf_dir + cert = '%s/kimchi-cert.pem' % config_dir + key = '%s/kimchi-key.pem' % config_dir +
+ with open(os.path.join(config_dir, "nginx.conf.in")) as template: + data = template.read()
This patch uses "nginx.conf.in" but it is not in this patch. You should merge this patch with patch 2 to have a consistent commit.
+ + data = Template(data) + data = data.safe_substitute(proxy_port=p_port, + kimchid_port=k_port, + proxy_ssl_port=p_ssl_port, + kimchid_ssl_port=k_ssl_port, + cert_pem=cert, cert_key=key) + + config_file = open(os.path.join(config_dir, "nginx_kimchi.conf"), "w") + config_file.write(data) + config_file.close() + + +def start_proxy(): + """Start nginx reverse proxy.""" + config_dir = paths.conf_dir + config_file = "%s/nginx_kimchi.conf" % config_dir + cmd = ['nginx', '-c', config_file] + subprocess.call(cmd) + + +def terminate_proxy(): + """Stop nginx process.""" + term_proxy_cmd = ['nginx', '-s', 'stop'] + subprocess.call(term_proxy_cmd) + + def main(options): + # Script must run as root or with sudo. + if not os.geteuid() == 0: + sys.exit("\nMust be root to run this script. Exiting ...\n") + host = config.get("server", "host") port = config.get("server", "port") ssl_port = config.get("server", "ssl_port") @@ -44,20 +105,52 @@ def main(options): logLevel = config.get("logging", "log_level")
parser = OptionParser() - parser.add_option('--host', type="string", default=host, help="Hostname to listen on") - parser.add_option('--port', type="int", default=port, help="Port to listen on") - parser.add_option('--ssl-port', type="int", default=ssl_port, help="Enable a SSL server on the given port") - parser.add_option('--log-level', default=logLevel, help="Logging level") - parser.add_option('--access-log', default=os.path.join(logDir,ACCESS_LOG), help="Access log file") - parser.add_option('--error-log', default=os.path.join(logDir,ERROR_LOG), help="Error log file") - parser.add_option('--environment', default=runningEnv, help="Running environment of kimchi server") - parser.add_option('--test', action='store_true', help="Run server in mock model") + parser.add_option('--host', type="string", default=host, + help="Hostname to listen on") + parser.add_option('--port', type="int", default=port, + help="Port to listen on") + parser.add_option('--ssl-port', type="int", default=ssl_port, + help="Enable a SSL server on the given port") + parser.add_option('--log-level', default=logLevel, + help="Logging level") + parser.add_option('--access-log', + default=os.path.join(logDir, ACCESS_LOG), + help="Access log file") + parser.add_option('--error-log', + default=os.path.join(logDir, ERROR_LOG), + help="Error log file") + parser.add_option('--environment', default=runningEnv, + help="Running environment of kimchi server") + parser.add_option('--test', action='store_true', + help="Run server in mock model") (options, args) = parser.parse_args()
# Add non-option arguments setattr(options, 'ssl_cert', config.get('server', 'ssl_cert')) setattr(options, 'ssl_key', config.get('server', 'ssl_key'))
+ # The following method is used when the process receives a + # SIGINT signal (CTRL+C). + def terminate_kimchi(signal, frame): + terminate_proxy() + sys.exit(0) + signal.signal(signal.SIGINT, terminate_kimchi)
I think the better way to do it is subscribe to the cherrypy exit function in server.py cherrypy.engine.subscribe('exit', <function to kill proxy>)
+ + proxy_port = options.port + proxy_ssl_port = options.ssl_port +
+ # The max value between port and proxy_port + # will be used to calculate kimchid ports. + next_port = max(proxy_port, proxy_ssl_port) + 1 + options.port = next_port + next_port += 1 + options.ssl_port = next_port +
Automatically discover the ports can be an easy point of errors. The ports can be in used by other application. I think we should add more options to set the proxy ports and set a default value for it in the kimchi.conf file So I expect: kimchid --proxy-port=XXXX --proxy-ssl-port=YYYY
+ # Launch reverse proxy: create config file and start. + create_proxy_config(proxy_port, options.port, + proxy_ssl_port, options.ssl_port) + start_proxy() + kimchi.server.main(options)
if __name__ == '__main__':

From: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com> nginx.conf.in is a template that is being used by kimchid script to generate a customized proxy configuration. Signed-off-by: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com> --- src/nginx.conf.in | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 src/nginx.conf.in diff --git a/src/nginx.conf.in b/src/nginx.conf.in new file mode 100644 index 0000000..9500b99 --- /dev/null +++ b/src/nginx.conf.in @@ -0,0 +1,55 @@ +# Project Kimchi +# +# Copyright IBM, Corp. 2014 +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301 USA + + +# This is a template file to be used to generate a nginx +# proxy config file at kimchid script. + +user nginx; +worker_processes 1; + +error_log /var/log/nginx/error.log; + +events { + worker_connections 1024; +} + + +http { + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + + server { + listen $proxy_port; + listen $proxy_ssl_port ssl; + ssl_certificate $cert_pem; + ssl_certificate_key $cert_key; + + location / { + proxy_pass http://localhost:$kimchid_port; + proxy_set_header Host $host; + } + } +} -- 1.8.3.1

As I said in previous patch, just merge it to patch 1 to have consistent patch On 04/10/2014 05:44 PM, Daniel Barboza wrote:
From: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com>
nginx.conf.in is a template that is being used by kimchid script to generate a customized proxy configuration.
Signed-off-by: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com> --- src/nginx.conf.in | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 src/nginx.conf.in
diff --git a/src/nginx.conf.in b/src/nginx.conf.in new file mode 100644 index 0000000..9500b99 --- /dev/null +++ b/src/nginx.conf.in @@ -0,0 +1,55 @@ +# Project Kimchi +# +# Copyright IBM, Corp. 2014 +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301 USA + + +# This is a template file to be used to generate a nginx +# proxy config file at kimchid script. + +user nginx; +worker_processes 1; + +error_log /var/log/nginx/error.log; + +events { + worker_connections 1024; +} + + +http { + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + + server { + listen $proxy_port; + listen $proxy_ssl_port ssl; + ssl_certificate $cert_pem; + ssl_certificate_key $cert_key; + + location / { + proxy_pass http://localhost:$kimchid_port; + proxy_set_header Host $host; + } + } +}

From: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com> Added src/nginx.config.in to Fedora and SUSE spec files and nginx as dependency. Added nginx to README.md instructions. Added src/nginx_kimchi.conf to .gitignore. This file is a product of the nginx.config.in template tha was used for the last (or current) kimchid/nginx run. As such, there is no need to put this file in version control. Signed-off-by: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com> --- .gitignore | 1 + contrib/kimchi.spec.fedora.in | 2 ++ contrib/kimchi.spec.suse.in | 2 ++ docs/README.md | 4 ++-- 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 67878e2..66d3731 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,7 @@ stamp-po kimchi-*.tar.gz src/kimchid src/kimchi.conf +src/nginx_kimchi.conf src/kimchi/config.py tests/run_tests.sh tests/test_config.py diff --git a/contrib/kimchi.spec.fedora.in b/contrib/kimchi.spec.fedora.in index bf80104..3f716dc 100644 --- a/contrib/kimchi.spec.fedora.in +++ b/contrib/kimchi.spec.fedora.in @@ -28,6 +28,7 @@ Requires: sos Requires: python-ipaddr Requires: python-lxml Requires: nfs-utils +Requires: nginx Requires: iscsi-initiator-utils BuildRequires: libxslt BuildRequires: libxml2-python @@ -175,6 +176,7 @@ rm -rf $RPM_BUILD_ROOT %{_datadir}/kimchi/ui/pages/help/*.html %{_datadir}/kimchi/ui/pages/tabs/*.html.tmpl %{_sysconfdir}/kimchi/kimchi.conf +%{_sysconfdir}/kimchi/nginx.conf.in %{_sysconfdir}/kimchi/distros.d/debian.json %{_sysconfdir}/kimchi/distros.d/fedora.json %{_sysconfdir}/kimchi/distros.d/opensuse.json diff --git a/contrib/kimchi.spec.suse.in b/contrib/kimchi.spec.suse.in index cba0899..ee88592 100644 --- a/contrib/kimchi.spec.suse.in +++ b/contrib/kimchi.spec.suse.in @@ -24,6 +24,7 @@ Requires: python-ipaddr Requires: python-lxml Requires: python-xml Requires: nfs-client +Requires: nginx Requires: open-iscsi BuildRequires: libxslt-tools BuildRequires: python-libxml2 @@ -101,6 +102,7 @@ rm -rf $RPM_BUILD_ROOT %{_datadir}/kimchi/ui/pages/help/*.html %{_datadir}/kimchi/ui/pages/tabs/*.html.tmpl %{_sysconfdir}/kimchi/kimchi.conf +%{_sysconfdir}/kimchi/nginx.conf.in %{_sysconfdir}/kimchi/distros.d/debian.json %{_sysconfdir}/kimchi/distros.d/fedora.json %{_sysconfdir}/kimchi/distros.d/opensuse.json diff --git a/docs/README.md b/docs/README.md index 8b8b181..63ac760 100644 --- a/docs/README.md +++ b/docs/README.md @@ -53,7 +53,7 @@ Install Dependencies PyPAM m2crypto python-jsonschema rpm-build \ qemu-kvm python-psutil python-ethtool sos \ python-ipaddr python-lxml nfs-utils \ - iscsi-initiator-utils libxslt pyparted + iscsi-initiator-utils libxslt pyparted nginx # If using RHEL6, install the following additional packages: $ sudo yum install python-unittest2 python-ordereddict # Restart libvirt to allow configuration changes to take effect @@ -75,7 +75,7 @@ for more information on how to configure your system to access this repository. python-pam python-m2crypto python-jsonschema \ qemu-kvm libtool python-psutil python-ethtool \ sosreport python-ipaddr python-lxml nfs-common \ - open-iscsi lvm2 xsltproc python-parted + open-iscsi lvm2 xsltproc python-parted nginx Packages version requirement: python-jsonschema >= 1.3.0 -- 1.8.3.1

On 04/10/2014 05:44 PM, Daniel Barboza wrote:
From: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com>
Added src/nginx.config.in to Fedora and SUSE spec files and nginx as dependency. Added nginx to README.md instructions. Added src/nginx_kimchi.conf to .gitignore. This file is a product of the nginx.config.in template tha was used for the last (or current) kimchid/nginx run. As such, there is no need to put this file in version control.
Signed-off-by: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com> --- .gitignore | 1 + contrib/kimchi.spec.fedora.in | 2 ++ contrib/kimchi.spec.suse.in | 2 ++ docs/README.md | 4 ++-- 4 files changed, 7 insertions(+), 2 deletions(-)
You also need to update the DEBIAN/control.in file to adjust the build for Ubuntu
diff --git a/.gitignore b/.gitignore index 67878e2..66d3731 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,7 @@ stamp-po kimchi-*.tar.gz src/kimchid src/kimchi.conf +src/nginx_kimchi.conf src/kimchi/config.py tests/run_tests.sh tests/test_config.py diff --git a/contrib/kimchi.spec.fedora.in b/contrib/kimchi.spec.fedora.in index bf80104..3f716dc 100644 --- a/contrib/kimchi.spec.fedora.in +++ b/contrib/kimchi.spec.fedora.in @@ -28,6 +28,7 @@ Requires: sos Requires: python-ipaddr Requires: python-lxml Requires: nfs-utils +Requires: nginx Requires: iscsi-initiator-utils BuildRequires: libxslt BuildRequires: libxml2-python @@ -175,6 +176,7 @@ rm -rf $RPM_BUILD_ROOT %{_datadir}/kimchi/ui/pages/help/*.html %{_datadir}/kimchi/ui/pages/tabs/*.html.tmpl %{_sysconfdir}/kimchi/kimchi.conf +%{_sysconfdir}/kimchi/nginx.conf.in %{_sysconfdir}/kimchi/distros.d/debian.json %{_sysconfdir}/kimchi/distros.d/fedora.json %{_sysconfdir}/kimchi/distros.d/opensuse.json diff --git a/contrib/kimchi.spec.suse.in b/contrib/kimchi.spec.suse.in index cba0899..ee88592 100644 --- a/contrib/kimchi.spec.suse.in +++ b/contrib/kimchi.spec.suse.in @@ -24,6 +24,7 @@ Requires: python-ipaddr Requires: python-lxml Requires: python-xml Requires: nfs-client +Requires: nginx Requires: open-iscsi BuildRequires: libxslt-tools BuildRequires: python-libxml2 @@ -101,6 +102,7 @@ rm -rf $RPM_BUILD_ROOT %{_datadir}/kimchi/ui/pages/help/*.html %{_datadir}/kimchi/ui/pages/tabs/*.html.tmpl %{_sysconfdir}/kimchi/kimchi.conf +%{_sysconfdir}/kimchi/nginx.conf.in %{_sysconfdir}/kimchi/distros.d/debian.json %{_sysconfdir}/kimchi/distros.d/fedora.json %{_sysconfdir}/kimchi/distros.d/opensuse.json diff --git a/docs/README.md b/docs/README.md index 8b8b181..63ac760 100644 --- a/docs/README.md +++ b/docs/README.md @@ -53,7 +53,7 @@ Install Dependencies PyPAM m2crypto python-jsonschema rpm-build \ qemu-kvm python-psutil python-ethtool sos \ python-ipaddr python-lxml nfs-utils \ - iscsi-initiator-utils libxslt pyparted + iscsi-initiator-utils libxslt pyparted nginx # If using RHEL6, install the following additional packages: $ sudo yum install python-unittest2 python-ordereddict # Restart libvirt to allow configuration changes to take effect @@ -75,7 +75,7 @@ for more information on how to configure your system to access this repository. python-pam python-m2crypto python-jsonschema \ qemu-kvm libtool python-psutil python-ethtool \ sosreport python-ipaddr python-lxml nfs-common \ - open-iscsi lvm2 xsltproc python-parted + open-iscsi lvm2 xsltproc python-parted nginx
Packages version requirement: python-jsonschema >= 1.3.0
participants (2)
-
Aline Manera
-
Daniel Barboza