trouble while executing make check
by Rohan Gupta
hello sir,
hope this is the right place to ask queries,
i tried to install kimchi on centos 7 and when i run make check-local, i
ran into a error.
# make check-local
contrib/check_i18n.py ./i18n.py
Checking for invalid i18n string...
Checking for invalid i18n string successfully
/bin/pep8 --version
1.4.6
/bin/pep8 --filename '*.py,*.py.in'
--exclude="*config.py,*i18n.py,*tests/test_config.py" .
./model/vms.py:1376:24: E127 continuation line over-indented for visual
indent
make: *** [check-local] Error 1
will i get a possible solution for this.
thank you
Rohan Raj Gupta
7 years, 8 months
[PATCH V2] [Kimchi 0/3] Multiple string truncation issue fixed
by rajgupta@linux.vnet.ibm.com
From: Rajat Gupta <rajat.triumph(a)gmail.com>
Rajat Gupta (3):
Fixed for Truncation occurs in edit a guest panel console row
Fixed Truncation appeared on Virtualization->add network of Japanese
language
Fixed truncation for Guest Interface GUI OVS network/interface scroll
bar
ui/css/kimchi.css | 6 +++++-
ui/css/src/modules/_edit-guests.scss | 2 +-
ui/css/src/modules/_network.scss | 8 ++++++++
ui/js/src/kimchi.guest_edit_main.js | 4 +++-
4 files changed, 17 insertions(+), 3 deletions(-)
--
2.1.0
7 years, 8 months
[PATCH] [Kimchi] Bug fix #1096 - Prevent mass detach based on source PCI address
by dhbarboza82@gmail.com
From: Daniel Henrique Barboza <danielhb(a)linux.vnet.ibm.com>
Before this commit, Kimchi was mass detaching PCI devices when
trying to detach a single dev 'hostdev0' following this criteria:
- using the source address element, see all hostdevs that share
the same PCI address (domain x bus x slot) as 'hostdev0';
- if more than one is found, 'hostdev0' is considered to be
a multifunction device an a mass detachment of all devices found
is made.
This logic is flawed when considering SR-IOV devices (CX4 cards
for example). Although all virtual functions share the same
source PCI address, each VF should be attached and detached
individually.
Following the current libvirt documentation
(https://libvirt.org/formatdomain.html), there is an attribute
called 'multifunction' that can be used:
'Also available is the multifunction attribute, which controls
turning on the multifunction bit for a particular slot/function
in the PCI control register (...) multifunction defaults to 'off',
but should be set to 'on' for function 0 of a slot that will have
multiple functions used.'
Further experimentation showed that, in multifunction devices,
the device PCI address differs only in the 'function' attribute,
while in the VFs for example they are different. This means that
the device address is a better place to look for paired devices
instead of using the source PCI address.
This patch implements these changes to fix #1096: use the multifunction
attribute to determine if a hostdev is multifuction and changed
the 'get_devices_same_addr' method to use the device address instead
of the source PCI address as comparison.
Minor simplications of vmhostdevs.py code were also made, such
as use a dict instead of an array of tuples to easily retrieve
elements by a key and moved the NotFound verification up in
the '_detach_device' method.
Unit tests included.
Signed-off-by: Daniel Henrique Barboza <danielhb(a)linux.vnet.ibm.com>
---
model/vmhostdevs.py | 112 +++++++++++++++++++++--------------
tests/test_model.py | 164 ++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 234 insertions(+), 42 deletions(-)
diff --git a/model/vmhostdevs.py b/model/vmhostdevs.py
index 9823537..45939b8 100644
--- a/model/vmhostdevs.py
+++ b/model/vmhostdevs.py
@@ -635,7 +635,7 @@ class VMHostDevModel(object):
wok_log.error('opaque must be valid')
return
- wok_log.info("Device %s removed successfuly" % alias)
+ wok_log.info("Device %s removed successfully" % alias)
# Re-attach device to host
try:
dev = conn.get().nodeDeviceLookupByName(alias)
@@ -655,8 +655,8 @@ class VMHostDevModel(object):
lock = params['lock']
with lock:
- pci_devs = [(DeviceModel.deduce_dev_name(e, self.conn), e)
- for e in hostdev if e.attrib['type'] == 'pci']
+ pci_devs = {DeviceModel.deduce_dev_name(e, self.conn): e
+ for e in hostdev if e.attrib['type'] == 'pci'}
dev_info = self.dev_model.lookup(dev_name)
is_3D_device = self.dev_model.is_device_3D_controller(dev_info)
@@ -664,9 +664,20 @@ class VMHostDevModel(object):
raise InvalidOperation('KCHVMHDEV0006E',
{'name': dev_info['name']})
+ if not pci_devs.get(dev_name):
+ msg = WokMessage('KCHVMHDEV0001E',
+ {'vmid': vmid, 'dev_name': dev_name})
+ cb(msg.get_text(), False)
+ raise NotFoundError('KCHVMHDEV0001E',
+ {'vmid': vmid, 'dev_name': dev_name})
+
+ dev_name_elem = pci_devs[dev_name]
+
# check for multifunction and detach all functions together
try:
- multi = self._unplug_multifunction_pci(dom, hostdev, dev_name)
+ multi = self.unplug_multifunction_pci(
+ dom, hostdev, dev_name_elem
+ )
except libvirt.libvirtError:
multi = False
@@ -680,54 +691,71 @@ class VMHostDevModel(object):
cb('OK', True)
return
- # detach each function individually
- for e in hostdev:
- if DeviceModel.deduce_dev_name(e, self.conn) == dev_name:
- xmlstr = etree.tostring(e)
- dom.detachDeviceFlags(
- xmlstr, get_vm_config_flag(dom, mode='all'))
- if e.attrib['type'] == 'pci':
- self._delete_affected_pci_devices(dom, dev_name,
- pci_devs)
- if is_3D_device:
- devsmodel = VMHostDevsModel(conn=self.conn)
- devsmodel.update_mmio_guest(vmid, False)
- break
- else:
- msg = WokMessage('KCHVMHDEV0001E',
- {'vmid': vmid, 'dev_name': dev_name})
- cb(msg.get_text(), False)
- raise NotFoundError('KCHVMHDEV0001E',
- {'vmid': vmid, 'dev_name': dev_name})
+ # detach individually
+ xmlstr = etree.tostring(dev_name_elem)
+ dom.detachDeviceFlags(
+ xmlstr, get_vm_config_flag(dom, mode='all'))
+ if dev_name_elem.attrib['type'] == 'pci':
+ self._delete_affected_pci_devices(dom, dev_name,
+ pci_devs)
+ if is_3D_device:
+ devsmodel = VMHostDevsModel(conn=self.conn)
+ devsmodel.update_mmio_guest(vmid, False)
if DOM_STATE_MAP[dom.info()[0]] == "shutoff":
cb('OK', True)
- def _get_devices_same_addr(self, hostdev, domain, bus, slot):
+ def get_devices_same_addr(self, hostdevs, device_elem):
+ def elem_has_valid_address(elem):
+ if elem.get('type') != 'pci' or \
+ elem.address is None or \
+ elem.address.get('domain') is None or \
+ elem.address.get('bus') is None or \
+ elem.address.get('slot') is None:
+ return False
+ return True
+
+ if not elem_has_valid_address(device_elem):
+ return []
+
devices = []
- for device in hostdev:
- if device.attrib['type'] != 'pci':
- continue
+ device_domain = device_elem.address.get('domain')
+ device_bus = device_elem.address.get('bus')
+ device_slot = device_elem.address.get('slot')
- address = device.source.address
- if int(address.attrib['domain'], 16) != domain or \
- int(address.attrib['bus'], 16) != bus or \
- int(address.attrib['slot'], 16) != slot:
+ for dev in hostdevs:
+
+ if not elem_has_valid_address(dev):
continue
- devices.append(etree.tostring(device))
+ dev_domain = dev.address.get('domain')
+ dev_bus = dev.address.get('bus')
+ dev_slot = dev.address.get('slot')
+
+ if dev_domain == device_domain and dev_bus == device_bus and \
+ dev_slot == device_slot:
+ devices.append(etree.tostring(dev))
return devices
- def _unplug_multifunction_pci(self, dom, hostdev, dev_name):
- # get all devices attached to the guest in the same domain+bus+slot
- # that the one we are going to detach because they must be detached
- # together
- domain, bus, slot, _ = dev_name.split('_')[1:]
- devices = self._get_devices_same_addr(hostdev,
- int(domain, 16),
- int(bus, 16),
- int(slot, 16))
+ def is_hostdev_multifunction(self, dev_elem):
+ if dev_elem.address is None or \
+ dev_elem.address.get('multifunction') is None or \
+ dev_elem.address.get('function') is None:
+
+ return False
+
+ is_multi = dev_elem.address.get('multifunction') == 'on' and \
+ dev_elem.address.get('function') == '0x0'
+
+ return is_multi
+
+ def unplug_multifunction_pci(self, dom, hostdevs, dev_elem):
+ if not self.is_hostdev_multifunction(dev_elem):
+ return False
+
+ devices = self.get_devices_same_addr(hostdevs, dev_elem)
+
if len(devices) <= 1:
return False
@@ -747,7 +775,7 @@ class VMHostDevModel(object):
DevicesModel(
conn=self.conn).get_list(_passthrough_affected_by=dev_name))
- for pci_name, e in pci_devs:
+ for pci_name, e in pci_devs.iteritems():
if pci_name in affected_names:
xmlstr = etree.tostring(e)
dom.detachDeviceFlags(
diff --git a/tests/test_model.py b/tests/test_model.py
index 0209e8e..a14cf56 100644
--- a/tests/test_model.py
+++ b/tests/test_model.py
@@ -34,6 +34,8 @@ import shutil
import time
import unittest
+from lxml import objectify
+
import tests.utils as utils
import wok.objectstore
@@ -1783,6 +1785,168 @@ class ModelTests(unittest.TestCase):
self.assertTrue(
inst.vmhostdevs_have_usb_controller('kimchi-vm1'))
+ def get_hostdevs_xml(self):
+ return """\
+<domain type='kvm' id='N'>
+ <name>vm_name</name>
+ <devices>
+ <emulator>/usr/bin/qemu-kvm</emulator>
+ <hostdev mode='subsystem' type='pci' managed='yes'>
+ <driver name='vfio'/>
+ <source>
+ <address domain='0x0001' bus='0x0d' slot='0x00' function='0x1'/>
+ </source>
+ <alias name='hostdev0'/>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x05' \
+function='0x1'/>
+ </hostdev>
+ <hostdev mode='subsystem' type='pci' managed='yes'>
+ <driver name='vfio'/>
+ <source>
+ <address domain='0x0001' bus='0x0d' slot='0x00' function='0x0'/>
+ </source>
+ <alias name='hostdev1'/>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x05' \
+function='0x0' multifunction='on'/>
+ </hostdev>
+ <hostdev mode='subsystem' type='pci' managed='yes'>
+ <driver name='vfio'/>
+ <source>
+ <address domain='0x0001' bus='0x0d' slot='0x00' function='0x2'/>
+ </source>
+ <alias name='hostdev2'/>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x06' \
+function='0x0'/>
+ </hostdev>
+ <hostdev mode='subsystem' type='pci' managed='yes'>
+ <driver name='vfio'/>
+ <source>
+ <address domain='0x0001' bus='0x0d' slot='0x00' function='0x4'/>
+ </source>
+ <alias name='hostdev3'/>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x07' \
+function='0x0'/>
+ </hostdev>
+ <hostdev mode='subsystem' type='pci' managed='yes'>
+ <driver name='vfio'/>
+ <source>
+ <address domain='0x0001' bus='0x0d' slot='0x00' function='0x5'/>
+ </source>
+ <alias name='hostdev4'/>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x08' \
+function='0x0'/>
+ </hostdev>
+ </devices>
+ </domain>
+"""
+
+ def get_hostdev_multifunction_xml(self):
+ return """\
+<hostdev mode='subsystem' type='pci' managed='yes'>
+ <driver name='vfio'/>
+ <source>
+ <address domain='0x0001' bus='0x0d' slot='0x00' function='0x0'/>
+ </source>
+ <alias name='hostdev1'/>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0' \
+multifunction='on'/>
+</hostdev>
+"""
+
+ def get_hostdev_nomultifunction_xml(self):
+ return """\
+<hostdev mode='subsystem' type='pci' managed='yes'>
+ <driver name='vfio'/>
+ <source>
+ <address domain='0x0001' bus='0x0d' slot='0x00' function='0x5'/>
+ </source>
+ <alias name='hostdev4'/>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/>
+</hostdev>
+"""
+
+ def test_vmhostdev_is_hostdev_multifunction(self):
+ inst = model.Model(None, objstore_loc=self.tmp_store)
+
+ hostdev_multi_elem = objectify.fromstring(
+ self.get_hostdev_multifunction_xml()
+ )
+ self.assertTrue(
+ inst.vmhostdev_is_hostdev_multifunction(hostdev_multi_elem)
+ )
+
+ hostdev_nomulti_elem = objectify.fromstring(
+ self.get_hostdev_nomultifunction_xml()
+ )
+ self.assertFalse(
+ inst.vmhostdev_is_hostdev_multifunction(hostdev_nomulti_elem)
+ )
+
+ def test_vmhostdev_get_devices_same_addr(self):
+ inst = model.Model(None, objstore_loc=self.tmp_store)
+
+ root = objectify.fromstring(self.get_hostdevs_xml())
+ hostdevs = root.devices.hostdev
+
+ hostdev_multi_elem = objectify.fromstring(
+ self.get_hostdev_multifunction_xml()
+ )
+
+ hostdev_same_addr_str = """\
+<hostdev mode="subsystem" type="pci" managed="yes"><driver name="vfio"/>\
+<source><address domain="0x0001" bus="0x0d" slot="0x00" function="0x1"/>\
+</source><alias name="hostdev0"/>\
+<address type="pci" domain="0x0000" bus="0x00" slot="0x05" function="0x1"/>\
+</hostdev>"""
+ same_addr_devices = [
+ ET.tostring(hostdev_multi_elem), hostdev_same_addr_str
+ ]
+
+ self.assertItemsEqual(
+ same_addr_devices,
+ inst.vmhostdev_get_devices_same_addr(hostdevs, hostdev_multi_elem)
+ )
+
+ nomatch_elem = objectify.fromstring(
+ self.get_hostdev_nomultifunction_xml()
+ )
+
+ self.assertEqual(
+ inst.vmhostdev_get_devices_same_addr(hostdevs, nomatch_elem),
+ [ET.tostring(nomatch_elem)]
+ )
+
+ @mock.patch('wok.plugins.kimchi.model.vmhostdevs.get_vm_config_flag')
+ def test_vmhostdev_unplug_multifunction_pci(self, mock_conf_flag):
+ class FakeDom():
+ def detachDeviceFlags(self, xml, config_flag):
+ pass
+
+ mock_conf_flag.return_value = ''
+
+ inst = model.Model(None, objstore_loc=self.tmp_store)
+
+ root = objectify.fromstring(self.get_hostdevs_xml())
+ hostdevs = root.devices.hostdev
+
+ hostdev_multi_elem = objectify.fromstring(
+ self.get_hostdev_multifunction_xml()
+ )
+
+ self.assertTrue(
+ inst.vmhostdev_unplug_multifunction_pci(FakeDom(), hostdevs,
+ hostdev_multi_elem)
+ )
+
+ nomatch_elem = objectify.fromstring(
+ self.get_hostdev_nomultifunction_xml()
+ )
+
+ self.assertFalse(
+ inst.vmhostdev_unplug_multifunction_pci(FakeDom(), hostdevs,
+ nomatch_elem)
+ )
+
class BaseModelTests(unittest.TestCase):
class FoosModel(object):
--
2.7.4
7 years, 8 months
[PATCH v2] [Kimchi] PCI detach enhancements
by dhbarboza82@gmail.com
From: Daniel Henrique Barboza <danielhb(a)linux.vnet.ibm.com>
v2:
- removed error msg redundancy
- skip the reattach process if the device was in managed mode
Daniel Henrique Barboza (1):
Bug fix #1096 - Prevent mass detach based on source PCI address
model/vmhostdevs.py | 134 ++++++++++++++++++++++++++----------------
tests/test_model.py | 164 ++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 249 insertions(+), 49 deletions(-)
--
2.7.4
7 years, 8 months
[PATCH V2] [Wok 0/2] Remove dhparams generation from build
by Lucio Correia
This patch moves dhparams.pem file generation to package post-install and
server initialization when running on development mode (i.e. running from
source)
It also fix an issue on nginx configure reloading. If nginx was not up and
running, reload command failed, causing tests to break or forcing user to
restart nginx manually.
V2:
- Review comments
- Updated copyright
Lucio Correia (2):
Generate dhparams in post-install and development mode
Make sure nginx is running before reloading its config
Makefile.am | 2 --
contrib/DEBIAN/control.in | 1 -
contrib/DEBIAN/postinst | 16 ++++++++++++++--
contrib/wok.spec.fedora.in | 8 ++++++--
contrib/wok.spec.suse.in | 8 ++++++--
src/Makefile.am | 10 ++--------
src/wok/proxy.py | 23 +++++++++++++++++------
7 files changed, 45 insertions(+), 23 deletions(-)
--
2.7.4
7 years, 8 months
[Wok][RFC] Option to specific logging levels #35
by Ramon Medeiros
Propose: support different levels of logging on wok
Bug: wok is setting logging handlers only, not cherrypy handlers.
Issues:
After my troubleshooting, just saw that we need to set cherrypy handlers:
--- a/src/wok/server.py
+++ b/src/wok/server.py
@@ -120,6 +120,7 @@ class Server(object):
delay=1)
h.setLevel(logLevel)
h.setFormatter(cherrypy._cplogging.logfmt)
+ cherrypy.log.access_log.setLevel(logLevel)
# Add access log file to cherrypy configuration
cherrypy.log.access_log.addHandler(h)
@@ -128,6 +129,7 @@ class Server(object):
h = SafeWatchedFileHandler(options.error_log, 'a', delay=1)
h.setLevel(logLevel)
h.setFormatter(cherrypy._cplogging.logfmt)
+ cherrypy.log.error_log.setLevel(logLevel)
# Add error log file to cherrypy configuration
cherrypy.log.error_log.addHandler(h)
When testing, got this output:
Running with loglevel == debug
command-line ./src/wokd: No output
access_log: lot of output, info output and commands results
error_log: debug info
------------------------
Running with loglevel == info
command-line ./src/wokd: No output
access_log: lot of output, info output
error_log: info
--------------------------------
Running with loglevel == error
command-line ./src/wokd: Info output (no expected)
access_log: just calls to the urls
error_log: only error
The last one was not expected :(
--
Ramon Nunes Medeiros
Kimchi Developer
Linux Technology Center Brazil
IBM Systems & Technology Group
Phone : +55 19 2132 7878
ramonn(a)br.ibm.com
7 years, 8 months
[PATCH v3] [Wok] Bug fix #147: Block authentication request after too many failures
by ramonn@linux.vnet.ibm.com
From: Ramon Medeiros <ramonn(a)linux.vnet.ibm.com>
To prevent brute force attack, creates a mechanism to allow 3 tries
first. After that, a timeout will start and will be added 30 seconds for
each failed try in a row.
Signed-off-by: Ramon Medeiros <ramonn(a)linux.vnet.ibm.com>
---
Changes:
v3:
Improve error handling on login page
v2:
Set timeout by user, ip and session id. This will avoid trouble with
users using the same ip, like NAT.
src/wok/i18n.py | 2 ++
src/wok/root.py | 66 ++++++++++++++++++++++++++++++++++++++++++++----
ui/js/src/wok.login.js | 21 +++++++++------
ui/pages/i18n.json.tmpl | 5 +++-
ui/pages/login.html.tmpl | 6 ++---
5 files changed, 82 insertions(+), 18 deletions(-)
diff --git a/src/wok/i18n.py b/src/wok/i18n.py
index e454e31..7d595b8 100644
--- a/src/wok/i18n.py
+++ b/src/wok/i18n.py
@@ -41,7 +41,9 @@ messages = {
"WOKAUTH0001E": _("Authentication failed for user '%(username)s'. [Error code: %(code)s]"),
"WOKAUTH0002E": _("You are not authorized to access Wok. Please, login first."),
"WOKAUTH0003E": _("Specify %(item)s to login into Wok."),
+ "WOKAUTH0004E": _("You have failed to login in too much attempts. Please, wait for %(seconds)s seconds to try again."),
"WOKAUTH0005E": _("Invalid LDAP configuration: %(item)s : %(value)s"),
+ "WOKAUTH0006E": _("The username or password you entered is incorrect. Please try again."),
"WOKLOG0001E": _("Invalid filter parameter. Filter parameters allowed: %(filters)s"),
"WOKLOG0002E": _("Creation of log file failed: %(err)s"),
diff --git a/src/wok/root.py b/src/wok/root.py
index 080b7f0..d314d25 100644
--- a/src/wok/root.py
+++ b/src/wok/root.py
@@ -1,7 +1,7 @@
#
# Project Wok
#
-# Copyright IBM Corp, 2015-2016
+# Copyright IBM Corp, 2015-2017
#
# Code derived from Project Kimchi
#
@@ -21,7 +21,9 @@
import cherrypy
import json
+import re
import os
+import time
from distutils.version import LooseVersion
from wok import auth
@@ -31,7 +33,7 @@ from wok.config import paths as wok_paths
from wok.control import sub_nodes
from wok.control.base import Resource
from wok.control.utils import parse_request
-from wok.exception import MissingParameter
+from wok.exception import MissingParameter, UnauthorizedError
from wok.reqlogger import log_request
@@ -48,7 +50,8 @@ class Root(Resource):
super(Root, self).__init__(model)
self._handled_error = ['error_page.400', 'error_page.404',
'error_page.405', 'error_page.406',
- 'error_page.415', 'error_page.500']
+ 'error_page.415', 'error_page.500',
+ 'error_page.403', 'error_page.401']
if not dev_env:
self._cp_config = dict([(key, self.error_production_handler)
@@ -146,6 +149,7 @@ class WokRoot(Root):
self.domain = 'wok'
self.messages = messages
self.extends = None
+ self.failed_logins = {}
# set user log messages and make sure all parameters are present
self.log_map = ROOT_REQUESTS
@@ -153,6 +157,13 @@ class WokRoot(Root):
@cherrypy.expose
def login(self, *args):
+ def _raise_timeout(user_id):
+ length = self.failed_logins[user_ip_sid]["count"]
+ timeout = (length - 3) * 30
+ details = e = UnauthorizedError("WOKAUTH0004E",
+ {"seconds": timeout})
+ log_request(code, params, details, method, 403)
+ raise cherrypy.HTTPError(403, e.message)
details = None
method = 'POST'
code = self.getRequestMessage(method, 'login')
@@ -161,17 +172,62 @@ class WokRoot(Root):
params = parse_request()
username = params['username']
password = params['password']
+
+ # no data passed: raise error
+ if len(username + password) == 0:
+ raise KeyError
+
except KeyError, item:
details = e = MissingParameter('WOKAUTH0003E', {'item': str(item)})
log_request(code, params, details, method, 400)
raise cherrypy.HTTPError(400, e.message)
+ # get authentication info
+ remote_ip = cherrypy.request.remote.ip
+ session_id = str(cherrypy.session.originalid)
+ user_ip_sid = re.escape(username + remote_ip + session_id)
+
+ # check for repetly
+ count = self.failed_logins.get(user_ip_sid, {"count": 0}).get("count")
+ if count >= 3:
+
+ # verify if timeout is still valid
+ last_try = self.failed_logins[user_ip_sid]["time"]
+ if time.time() < (last_try + ((count - 3) * 30)):
+ _raise_timeout(user_ip_sid)
+
try:
status = 200
user_info = auth.login(username, password)
+
+ # user logged sucessfuly: reset counters
+ if self.failed_logins.get(user_ip_sid) != None:
+ self.failed_logins.remove(user_ip_sid)
except cherrypy.HTTPError, e:
- status = e.status
- raise
+
+ # store time and prevent too much tries
+ if self.failed_logins.get(user_ip_sid) == None:
+ self.failed_logins[user_ip_sid] = {"time": time.time(),
+ "ip": remote_ip,
+ "session_id": session_id,
+ "username": username,
+ "count": 1}
+ else:
+
+ # tries take more than 30 seconds between each one: do not
+ # increase count
+ if (time.time() -
+ self.failed_logins[user_ip_sid]["time"]) < 30:
+
+ self.failed_logins[user_ip_sid]["time"] = time.time()
+ self.failed_logins[user_ip_sid]["count"] += 1
+
+ # more than 3 fails: raise error
+ if self.failed_logins[user_ip_sid]["count"] > 3:
+ _raise_timeout(user_ip_sid)
+
+ details = e = MissingParameter('WOKAUTH0006E')
+ raise cherrypy.HTTPError(401, e.message)
finally:
log_request(code, params, details, method, status)
diff --git a/ui/js/src/wok.login.js b/ui/js/src/wok.login.js
index fa2a98a..d9daacf 100644
--- a/ui/js/src/wok.login.js
+++ b/ui/js/src/wok.login.js
@@ -1,7 +1,7 @@
/*
* Project Wok
*
- * Copyright IBM Corp, 2015-2016
+ * Copyright IBM Corp, 2015-2017
*
* Code derived from Project Kimchi
*
@@ -19,6 +19,10 @@
*/
wok.login_main = function() {
"use strict";
+ var i18n;
+ wok.getI18n(function(i18nObj){
+ i18n = i18nObj;
+ }, false, "i18n.json", true);
// verify if language is available
var selectedLanguage = wok.lang.get();
@@ -50,7 +54,8 @@ wok.login_main = function() {
var query = window.location.search;
var error = /.*error=(.*?)(&|$)/g.exec(query);
if (error && error[1] === "sessionTimeout") {
- $("#messSession").show();
+ $("#errorArea").html(i18n["WOKAUT0001E"]);
+ $("#errorArea").show();
}
var userNameBox = $('#username');
@@ -82,13 +87,13 @@ wok.login_main = function() {
window.location.replace(window.location.pathname.replace(/\/+login.html/, '') + next_url);
}, function(jqXHR, textStatus, errorThrown) {
if (jqXHR.responseText == "") {
- $("#messUserPass").hide();
- $("#missServer").show();
- } else {
- $("#missServer").hide();
- $("#messUserPass").show();
+ $("#errorArea").html(i18n["WOKAUT0002E"]);
+ $("#errorArea").show();
+ } else if ((jqXHR.responseJSON != undefined) &&
+ ! (jqXHR.responseJSON["reason"] == undefined)) {
+ $("#errorArea").html(jqXHR.responseJSON["reason"]);
+ $("#errorArea").show();
}
- $("#messSession").hide();
$("#logging").hide();
$("#login").show();
});
diff --git a/ui/pages/i18n.json.tmpl b/ui/pages/i18n.json.tmpl
index ba29532..4329ad0 100644
--- a/ui/pages/i18n.json.tmpl
+++ b/ui/pages/i18n.json.tmpl
@@ -1,7 +1,7 @@
#*
* Project Wok
*
- * Copyright IBM Corp, 2014-2016
+ * Copyright IBM Corp, 2014-2017
*
* Code derived from Project Kimchi
*
@@ -39,6 +39,9 @@
"WOKHOST6001M": "$_("Max:")",
+ "WOKAUT0001E": "$_("Session timeout, please re-login.")",
+ "WOKAUT0002E": "$_("Server unreachable")",
+
"WOKSETT0001M": "$_("Application")",
"WOKSETT0002M": "$_("User")",
"WOKSETT0003M": "$_("Request")",
diff --git a/ui/pages/login.html.tmpl b/ui/pages/login.html.tmpl
index f5a4b2d..6f967cf 100644
--- a/ui/pages/login.html.tmpl
+++ b/ui/pages/login.html.tmpl
@@ -1,7 +1,7 @@
#*
* Project Wok
*
- * Copyright IBM Corp, 2014-2016
+ * Copyright IBM Corp, 2014-2017
*
* Code derived from Project Kimchi
*
@@ -104,9 +104,7 @@
<div class="container">
<div id="login-window" class="login-area row">
<div class="err-area">
- <div id="messUserPass" class="alert alert-danger" style="display: none;">$_("The username or password you entered is incorrect. Please try again.")</div>
- <div id="messSession" class="alert alert-danger" style="display: none;">$_("Session timeout, please re-login.")</div>
- <div id="missServer" class="alert alert-danger" style="display: none;">$_("Server unreachable.")</div>
+ <div id="errorArea" class="alert alert-danger" style="display: none;"></div>
</div>
<form id="form-login" class="form-horizontal" method="post">
<div class="form-group">
--
2.10.1 (Apple Git-78)
7 years, 8 months
[PATCH] [Kimchi] Fix for the kimchi #1102
by jkatta@linux.vnet.ibm.com
From: Jayavardhan Katta <jkatta(a)linux.vnet.ibm.com>
Fix given to the kimchi plugin to avoid multiple continuos error message to the log
in case of VMs created outside of WoK.
Signed-off-by: Jayavardhan Katta <jkatta(a)linux.vnet.ibm.com>
---
model/vms.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/model/vms.py b/model/vms.py
index 7729af0..895acd3 100644
--- a/model/vms.py
+++ b/model/vms.py
@@ -1300,7 +1300,7 @@ class VMModel(object):
with self.objstore as session:
try:
- extra_info = session.get('vm', dom.UUIDString())
+ extra_info = session.get('vm', dom.UUIDString(), False)
except NotFoundError:
extra_info = {}
icon = extra_info.get('icon')
--
2.7.4
7 years, 8 months
[PATCH] [Kimchi] Fix for the kimchi #1102
by jkatta@linux.vnet.ibm.com
From: Jayavardhan Katta <jkatta(a)linux.vnet.ibm.com>
Fix given to the kimchi plugin to avoid multiple continuos error message to the log
in case of VMs created outside of WoK.
Signed-off-by: Jayavardhan Katta <jkatta(a)linux.vnet.ibm.com>
---
model/vms.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/model/vms.py b/model/vms.py
index 7729af0..895acd3 100644
--- a/model/vms.py
+++ b/model/vms.py
@@ -1300,7 +1300,7 @@ class VMModel(object):
with self.objstore as session:
try:
- extra_info = session.get('vm', dom.UUIDString())
+ extra_info = session.get('vm', dom.UUIDString(), False)
except NotFoundError:
extra_info = {}
icon = extra_info.get('icon')
--
2.7.4
7 years, 8 months
[PATCH] [Wok] Fix to the WoK for the Kimchi issue #1102
by jkatta@linux.vnet.ibm.com
From: Jayavardhan Katta <jkatta(a)linux.vnet.ibm.com>
As a fix to the Kimchi issue #1102, some fix needs to be given for the WoK framework as well.
Signed-off-by: Jayavardhan Katta <jkatta(a)linux.vnet.ibm.com>
---
src/wok/objectstore.py | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/src/wok/objectstore.py b/src/wok/objectstore.py
index a571e5f..eb49056 100644
--- a/src/wok/objectstore.py
+++ b/src/wok/objectstore.py
@@ -52,7 +52,7 @@ class ObjectStoreSession(object):
objects.sort(key=lambda (_, obj): obj[sort_key])
return [ident for ident, _ in objects]
- def get(self, obj_type, ident):
+ def get(self, obj_type, ident, ignore_missing=True):
c = self.conn.cursor()
res = c.execute('SELECT json FROM objects WHERE type=? AND id=?',
(obj_type, ident))
@@ -60,7 +60,10 @@ class ObjectStoreSession(object):
jsonstr = res.fetchall()[0][0]
except IndexError:
self.conn.rollback()
- raise NotFoundError("WOKOBJST0001E", {'item': ident})
+ data = {"":""}
+ jsonstr = json.dumps(data)
+ if ignore_missing:
+ raise NotFoundError("WOKOBJST0001E", {'item': ident})
return json.loads(jsonstr)
def get_object_version(self, obj_type, ident):
--
2.7.4
7 years, 8 months