summaryrefslogtreecommitdiff
diff options
-rwxr-xr-xbin/disk_smart181
-rwxr-xr-xbin/fwts_test2
-rwxr-xr-xbin/memory_compare55
-rwxr-xr-xbin/network_device_info8
-rwxr-xr-xbin/network_info11
-rwxr-xr-xbin/removable_storage_test142
-rw-r--r--jobs/mediacard.txt.in2
-rwxr-xr-xmanage.py2
-rw-r--r--po/pl.po2
9 files changed, 262 insertions, 143 deletions
diff --git a/bin/disk_smart b/bin/disk_smart
index c7f58dfa..1aea483c 100755
--- a/bin/disk_smart
+++ b/bin/disk_smart
@@ -7,6 +7,7 @@ Copyright (C) 2010 Canonical Ltd.
Authors
Jeff Lane <jeffrey.lane@canonical.com>
Brendan Donegan <brendan.donegan@canonical.com>
+ Rod Smith <rod.smith@canonical.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2,
@@ -34,6 +35,11 @@ USB/eSATA/eSAS attached storage devices.
Changelog:
+v1.3: Fix detection of SMART availability & activate SMART if available
+ but deactivated. Also use smartctl return value rather than string-
+ matching to determine if a test has failed; this should be more
+ robust, as output strings vary between disks.
+v1.2: Handle multiple output formats for "smartctl -l"
v1.1: Put delay before first attempt to acces log, rather than after
v1.0: added debugger class and code to allow for verbose debug output if needed
@@ -58,8 +64,10 @@ import os
import sys
import time
import logging
+import shlex
-from subprocess import Popen, PIPE
+from subprocess import Popen, PIPE, check_call, check_output
+from subprocess import CalledProcessError
from argparse import ArgumentParser
@@ -72,27 +80,57 @@ class ListHandler(logging.StreamHandler):
msg = msg.decode()
logger = logging.getLogger(record.name)
new_record = logger.makeRecord(record.name, record.levelno,
- record.pathname, record.lineno, msg, record.args,
- record.exc_info, record.funcName)
+ record.pathname, record.lineno,
+ msg, record.args,
+ record.exc_info,
+ record.funcName)
logging.StreamHandler.emit(self, new_record)
else:
logging.StreamHandler.emit(self, record)
+def enable_smart(disk):
+ """ Enable SMART on the specified disk
+ :param disk:
+ disk device filename (e.g., /dev/sda)
+ :returns:
+ True if enabling smart was successful, False otherwise
+ """
+ logging.debug('SMART disabled; attempting to enable it.')
+ command = 'smartctl -s on %s' % disk
+ try:
+ check_call(shlex.split(command))
+ return True
+ except CalledProcessError:
+ return False
+
+
+# Returns True if SMART is enabled. If not enabled, attempt to
+# enable it and return result of that attempt.
def is_smart_enabled(disk):
# Check with smartctl to see if SMART is available and enabled on the disk
command = 'smartctl -i %s' % disk
diskinfo_bytes = (Popen(command, stdout=PIPE, shell=True)
- .communicate()[0])
+ .communicate()[0])
diskinfo = diskinfo_bytes.decode().splitlines()
logging.debug('SMART Info for disk %s', disk)
logging.debug(diskinfo)
- return (len(diskinfo) > 2
- and 'Enabled' in diskinfo[-2]
- and 'Available' in diskinfo[-3])
+ # Return True if the output (diskinfo) includes BOTH
+ # "SMART support is.*Available" AND "SMART support is.*Enabled".
+ # If SMART is available but not enabled, try to enable it.
+ if len(diskinfo) > 2:
+ if any("SMART support is" in s and "Available" in s
+ for s in diskinfo):
+ if any("SMART support is" in s and "Enabled" in s
+ for s in diskinfo):
+ return True
+ else:
+ return enable_smart(disk)
+ else:
+ return False
def run_smart_test(disk, type='short'):
@@ -110,20 +148,23 @@ def run_smart_test(disk, type='short'):
def get_smart_entries(disk, type='selftest'):
entries = []
- command = 'smartctl -l %s %s' % (type, disk)
- stdout = Popen(command, stdout=PIPE, shell=True).stdout
+ try:
+ stdout = check_output(['smartctl', '-l', type, disk],
+ universal_newlines=True)
+ returncode = 0
+ except CalledProcessError as err:
+ stdout = err.output
+ returncode = err.returncode
# Skip intro lines
- while True:
- line = stdout.readline().decode()
- if not line:
- raise Exception('Failed to parse SMART log entries')
-
- if line.startswith('SMART'):
+ stdout_lines = iter(stdout.splitlines())
+ for line in stdout_lines:
+ if (line.startswith('SMART') or
+ line.startswith('No self-tests have been logged')):
break
# Get lengths from header
- line = stdout.readline().decode()
+ line = next(stdout_lines)
if not line.startswith('Num'):
entries.append('No entries found in log yet')
return entries
@@ -135,8 +176,7 @@ def get_smart_entries(disk, type='selftest'):
# Get remaining lines
entries = []
- for line_bytes in stdout.readlines():
- line = line_bytes.decode()
+ for line in stdout_lines:
if line.startswith('#'):
entry = {}
for i, column in enumerate(columns):
@@ -144,10 +184,64 @@ def get_smart_entries(disk, type='selftest'):
# Convert some columns to integers
entry['number'] = int(entry['number'][1:])
- entry['lifetime'] = int(entry['lifetime'])
entries.append(entry)
- return entries
+ return entries, returncode
+
+
+# Returns True if an "in-progress" message is found in the smartctl
+# output, False if such a message is not found. In the former case,
+# the in-progress message entries are logged.
+def in_progress(current_entries):
+ statuses = [entry for entry in current_entries
+ if isinstance(entry, dict)
+ and 'status' in entry
+ and (entry['status'] == 'Self-test routine in progress'
+ or "Self test in progress" in entry['status'])]
+ if statuses:
+ for entry in statuses:
+ logging.debug('%s %s %s %s' % (entry['number'],
+ entry['description'],
+ entry['status'],
+ entry['remaining']))
+ return True
+ else:
+ return False
+
+
+# Wait for SMART test to complete; return status and return code.
+# Note that different disks return different types of values.
+# Some return no status reports while a test is ongoing; others
+# show a status line at the START of the list of tests, and
+# others show a status line at the END of the list of tests
+# (and then move it to the top once the tests are done).
+def poll_for_status(args, disk, previous_entries):
+ # Priming read... this is here in case our test is finished or fails
+ # immediate after it beginsAccording to.
+ logging.debug('Polling selftest.log for status')
+ keep_going = True
+
+ while keep_going:
+ # Poll every sleep seconds until test is complete$
+ time.sleep(args.sleep)
+
+ current_entries, returncode = get_smart_entries(disk)
+ if current_entries != previous_entries:
+ if not in_progress(current_entries):
+ keep_going = False
+
+ if args.timeout is not None:
+ if args.timeout <= 0:
+ logging.debug('Polling timed out')
+ return 1
+ else:
+ args.timeout -= args.sleep
+
+ if isinstance(current_entries[0], str):
+ return current_entries[0], returncode
+ else:
+ return current_entries[0]['status'], returncode
+
def main():
description = 'Tests that SMART capabilities on disks that support SMART function.'
@@ -184,7 +278,7 @@ def main():
logger.setLevel(logging.INFO)
# Make sure we're root, because smartctl doesn't work otherwise.
- if not os.geteuid()==0:
+ if not os.geteuid() == 0:
parser.error("You must be root to run this program")
# If SMART is available and enabled, we proceed. Otherwise, we exit as the
@@ -195,8 +289,8 @@ def main():
return 0
# Initiate a self test and start polling until the test is done
- previous_entries = get_smart_entries(disk)
- logging.info("Starting SMART self-test on %s" % disk)
+ previous_entries, returncode = get_smart_entries(disk)
+ logging.info("Starting SMART self-test on %s", disk)
if run_smart_test(disk) != 0:
logging.error("Error reported during smartctl test")
return 1
@@ -205,42 +299,17 @@ def main():
# Abort the previous instance
# so that polling can identify the difference
run_smart_test(disk)
- previous_entries = get_smart_entries(disk)
-
- # Priming read... this is here in case our test is finished or fails
- # immediate after it begins.
- logging.debug('Polling selftest.log for status')
-
- while True:
- # Poll every sleep seconds until test is complete$
- time.sleep(args.sleep)
-
- current_entries = get_smart_entries(disk)
- if isinstance(current_entries[0], str):
- logging.debug(current_entries[0])
- else:
- logging.debug('%s %s %s %s' % (current_entries[0]['number'],
- current_entries[0]['description'],
- current_entries[0]['status'],
- current_entries[0]['remaining']))
- if current_entries != previous_entries \
- and current_entries[0]["status"] != 'Self-test routine in progress':
- break
-
- if args.timeout is not None:
- if args.timeout <= 0:
- logging.debug('Polling timed out')
- return 1
- else:
- args.timeout -= args.sleep
+ previous_entries, returncode = get_smart_entries(disk)
- status = current_entries[0]['status']
+ status, returncode = poll_for_status(args, disk, previous_entries)
- if status != 'Completed without error':
- log = get_smart_entries(disk)
+ if returncode != 0:
+ log, returncode = get_smart_entries(disk)
logging.error("FAIL: SMART Self-Test appears to have failed for some reason. "
- "Run 'sudo smartctl -l selftest %s' to see the SMART log" % disk)
- logging.debug("Last self-test run status: %s" % status)
+ "Run 'sudo smartctl -l selftest %s' to see the SMART log",
+ disk)
+ logging.debug("Last smartctl return code: %d", returncode)
+ logging.debug("Last smartctl run status: %s", status)
return 1
else:
logging.info("PASS: SMART Self-Test completed without error")
diff --git a/bin/fwts_test b/bin/fwts_test
index 029c1ec9..127858a3 100755
--- a/bin/fwts_test
+++ b/bin/fwts_test
@@ -317,7 +317,7 @@ def main():
args.resume_time = 3
tests.extend(args.sleep)
else:
- tests.extend(TESTS)
+ tests.extend(CERT_TESTS)
# run the tests we want
if args.sleep:
diff --git a/bin/memory_compare b/bin/memory_compare
index 2c26f673..12a14ecd 100755
--- a/bin/memory_compare
+++ b/bin/memory_compare
@@ -27,6 +27,7 @@ import sys
from math import log, copysign
from subprocess import check_output, PIPE
+from checkbox_support.helpers.human_readable_bytes import HumanReadableBytes
from checkbox_support.parsers.lshwjson import LshwJsonParser
from checkbox_support.parsers.meminfo import MeminfoParser
@@ -82,51 +83,23 @@ def get_threshold(installed_memory):
return 10
-def bytes_to_human(my_bytes):
- """ Convert my_bytes to a scaled representation with a
- suffix
- """
- if my_bytes == 0:
- return "0 bytes"
-
- suffixes = ["bytes", "KiB", "MiB", "GiB", "TiB",
- "PiB", "EiB", "ZiB", "YiB"]
-
- try:
- sign = copysign(1, my_bytes)
- except OverflowError as excp:
- return "(Number too large: {})".format(excp)
- my_bytes = abs(my_bytes)
- # my_bytes' base-1024 logarithm.
- exponent = log(my_bytes, 1024)
- try:
- suffix = suffixes[int(exponent)]
- except IndexError:
- return "(Number too large)"
- scalar = my_bytes / (1024**int(exponent))
-
- return "{:.2f} {}".format(sign * scalar, suffix)
-
-
def main():
if os.geteuid() != 0:
print("This script must be run as root.", file=sys.stderr)
return 1
- installed_memory = get_installed_memory_size()
- visible_memory = get_visible_memory_size()
+ installed_memory = HumanReadableBytes(get_installed_memory_size())
+ visible_memory = HumanReadableBytes(get_visible_memory_size())
threshold = get_threshold(installed_memory)
- difference = installed_memory - visible_memory
+ difference = HumanReadableBytes(installed_memory - visible_memory)
try:
percentage = difference / installed_memory * 100
except ZeroDivisionError:
print("Results:")
- print("\t/proc/meminfo reports:\t{}".format(
- bytes_to_human(visible_memory)),
+ print("\t/proc/meminfo reports:\t{}".format(visible_memory),
file=sys.stderr)
- print("\tlshw reports:\t{}".format(
- bytes_to_human(installed_memory)),
+ print("\tlshw reports:\t{}".format(installed_memory),
file=sys.stderr)
print("\nFAIL: Either lshw or /proc/meminfo returned a memory size "
"of 0 kB", file=sys.stderr)
@@ -134,22 +107,18 @@ def main():
if percentage <= threshold:
print("Results:")
- print("\t/proc/meminfo reports:\t{}".format(
- bytes_to_human(visible_memory)))
- print("\tlshw reports:\t{}".format(bytes_to_human(installed_memory)))
+ print("\t/proc/meminfo reports:\t{}".format(visible_memory))
+ print("\tlshw reports:\t{}".format(installed_memory))
print("\nPASS: Meminfo reports %s less than lshw, a "
"difference of %.2f%%. This is less than the "
- "%d%% variance allowed." % (bytes_to_human(difference),
- percentage, threshold))
+ "%d%% variance allowed." % (difference, percentage, threshold))
return 0
else:
print("Results:", file=sys.stderr)
- print("\t/proc/meminfo reports:\t{}".format(
- bytes_to_human(visible_memory)),
- file=sys.stderr)
- print("\tlshw reports:\t{}".format(bytes_to_human(installed_memory)),
+ print("\t/proc/meminfo reports:\t{}".format(visible_memory),
file=sys.stderr)
- print("\nFAIL: Meminfo reports %d bytes less than lshw, "
+ print("\tlshw reports:\t{}".format(installed_memory), file=sys.stderr)
+ print("\nFAIL: Meminfo reports %d less than lshw, "
"a difference of %.2f%%. Only a variance of %d%% in "
"reported memory is allowed." %
(difference, percentage, threshold), file=sys.stderr)
diff --git a/bin/network_device_info b/bin/network_device_info
index b8c02675..f4b79110 100755
--- a/bin/network_device_info
+++ b/bin/network_device_info
@@ -200,8 +200,10 @@ def match_counts(nm_devices, udev_devices, devtype):
if udev.category == udevtype]
if len(nm_type_devices) != len(udev_type_devices):
print("ERROR: devices missing - udev showed %d %s devices, but "
- "NetworkManager saw %d devices in %s" % (len(udev_type_devices),
- udevtype, len(nm_type_devices), devtype), file=sys.stderr)
+ "NetworkManager saw %d devices in %s" %
+ (len(udev_type_devices), udevtype,
+ len(nm_type_devices), devtype),
+ file=sys.stderr)
return False
else:
return True
@@ -253,7 +255,7 @@ def main(args):
if not match_counts(nm_devices, udev_devices, "WiFi"):
return 1
- elif not match_counts(nm_devices, udev_devices, ("Ethernet","Modem")):
+ elif not match_counts(nm_devices, udev_devices, ("Ethernet", "Modem")):
return 1
else:
return 0
diff --git a/bin/network_info b/bin/network_info
index b9b46dde..9c20b89b 100755
--- a/bin/network_info
+++ b/bin/network_info
@@ -38,9 +38,10 @@ def get_ip_address(interface):
struct.pack('256s', interface[:15].encode())
)[20:24])
+
def get_ipv6_address(interface):
cmd = ['/sbin/ip', '-6', 'addr', 'show', 'dev', interface]
- proc = subprocess.check_output(cmd,universal_newlines=True)
+ proc = subprocess.check_output(cmd, universal_newlines=True)
ipaddr = proc.split()[8].strip()
return ipaddr
@@ -63,14 +64,14 @@ def main(args):
print("Interface: %s" % interface)
print("Connected: %s" % connected)
try:
- print("IPv4: %s" % get_ip_address(interface))
+ print("IPv4: %s" % get_ip_address(interface))
except IOError:
print("IPv4: n/a")
- try:
- print("IPv6: %s" % get_ipv6_address(interface))
+ try:
+ print("IPv6: %s" % get_ipv6_address(interface))
except IOError:
print("IPv6: n/a")
- except:
+ except:
print("IPv6: n/a")
print("MAC: %s\n" % get_mac_address(interface))
diff --git a/bin/removable_storage_test b/bin/removable_storage_test
index 9360becc..8e7732b8 100755
--- a/bin/removable_storage_test
+++ b/bin/removable_storage_test
@@ -22,6 +22,7 @@ from checkbox_support.dbus.udisks2 import is_udisks2_supported
from checkbox_support.dbus.udisks2 import lookup_udev_device
from checkbox_support.dbus.udisks2 import map_udisks1_connection_bus
from checkbox_support.heuristics.udisks2 import is_memory_card
+from checkbox_support.helpers.human_readable_bytes import HumanReadableBytes
from checkbox_support.parsers.udevadm import CARD_READER_RE
from checkbox_support.parsers.udevadm import GENERIC_RE
from checkbox_support.parsers.udevadm import FLASH_RE
@@ -252,24 +253,6 @@ class DiskTest():
else:
self.rem_disks_memory_cards_nm[dev_file] = None
self.rem_disks_nm[dev_file] = None
- # LP: #1313581
- # Compare the pci slot name of the devices using xhci and
- # the pci slot name of the disks,
- # which is usb3 disks in this case so far,
- # to make sure the usb3 disk does be on the bus using xhci
- # TODO: it will be better to extend to be all kinds of drivers.
- try:
- udev_devices_xhci = get_udev_xhci_devices(udev_client)
- for udev_device_xhci in udev_devices_xhci:
- pci_slot_name = udev_device_xhci.get_property('PCI_SLOT_NAME')
- for udev_device in udev_devices:
- devpath = udev_device.get_property('DEVPATH')
- if (self._compare_pci_slot_from_devpath(devpath,
- pci_slot_name)):
- self.rem_disks_xhci[
- udev_device.get_property('DEVNAME')] = 'xhci'
- except:
- logging.error("Failed to get driver information.")
def _probe_disks_udisks1(self, bus):
"""
@@ -320,6 +303,30 @@ class DiskTest():
self.rem_disks_nm[dev_file] = None
self.rem_disks_memory_cards_nm[dev_file] = None
+ def get_disks_xhci(self):
+ """
+ Compare
+ 1. the pci slot name of the devices using xhci
+ 2. the pci slot name of the disks,
+ which is usb3 disks in this case so far,
+ to make sure the usb3 disk does be on the controller using xhci
+ """
+ # LP: #1378724
+ udev_client = GUdev.Client()
+ # Get a collection of all udev devices corresponding to block devices
+ udev_devices = get_udev_block_devices(udev_client)
+ # Get a collection of all udev devices corresponding to xhci devices
+ udev_devices_xhci = get_udev_xhci_devices(udev_client)
+ for udev_device_xhci in udev_devices_xhci:
+ pci_slot_name = udev_device_xhci.get_property('PCI_SLOT_NAME')
+ for udev_device in udev_devices:
+ devpath = udev_device.get_property('DEVPATH')
+ if (self._compare_pci_slot_from_devpath(devpath,
+ pci_slot_name)):
+ self.rem_disks_xhci[
+ udev_device.get_property('DEVNAME')] = 'xhci'
+ return self.rem_disks_xhci
+
def mount(self):
passed_mount = {}
@@ -420,10 +427,17 @@ def main():
help='The number of random data files to generate')
parser.add_argument('-s', '--size',
action='store',
- type=int,
- default=1048576,
- help=("The size of the test data file to use "
- "in Bytes. Default is %(default)s"))
+ type=HumanReadableBytes,
+ default='1MiB',
+ help=("The size of the test data file to use. "
+ "You may use SI or IEC suffixes like: 'K', 'M',"
+ "'G', 'T', 'Ki', 'Mi', 'Gi', 'Ti', etc. Default"
+ " is %(default)s"))
+ parser.add_argument('--auto-reduce-size',
+ action='store_true',
+ default=False,
+ help=("Automatically reduce size to fit in the target"
+ "filesystem. Reducing until fits in 1MiB"))
parser.add_argument('-n', '--skip-not-mount',
action='store_true',
default=False,
@@ -516,11 +530,36 @@ def main():
if not args.min_speed or
int(test.rem_disks_speed[disk])
>= int(args.min_speed)}
+ if len(disks_eligible) == 0:
+ logging.error(
+ "No %s disks with speed higher than %s bits/s",
+ args.device, args.min_speed)
+ return 1
write_sizes = []
test_files = {}
+ disks_freespace = {}
+ for disk, path in disks_eligible.items():
+ stat = os.statvfs(path)
+ disks_freespace[disk] = stat.f_bfree * stat.f_bsize
+ smallest_freespace = min(disks_freespace.values())
+ desired_size = args.size
+ if desired_size > smallest_freespace:
+ if args.auto_reduce_size:
+ min_space = HumanReadableBytes("1MiB")
+ if smallest_freespace < min_space:
+ raise IOError("Not enough space. {} is required"
+ .format(min_space))
+ new_size = HumanReadableBytes(int(0.8 * smallest_freespace))
+ logging.warning("Automatically reducing test data size"
+ ". {} requested. Reducing to {}."
+ .format(desired_size, new_size))
+ desired_size = new_size
+ else:
+ raise IOError("Not enough space. {} is required"
+ .format(desired_size))
# Generate our data file(s)
for count in range(args.count):
- test_files[count] = RandomData(args.size)
+ test_files[count] = RandomData(desired_size)
write_sizes.append(os.path.getsize(
test_files[count].tfile.name))
total_write_size = sum(write_sizes)
@@ -610,20 +649,59 @@ def main():
"Completed %s test iterations, but there were"
" errors", args.count)
return 1
- elif len(disks_eligible) == 0:
- logging.error(
- "No %s disks with speed higher than %s bits/s",
- args.device, args.min_speed)
- return 1
-
else:
# LP: 1313581
+ # Try to figure out whether the disk
+ # is SuperSpeed USB and using xhci_hcd driver.
if (args.driver == 'xhci_hcd'):
- if(5000000000 == test.rem_disks_speed[disk] and
- 'xhci' == test.rem_disks_xhci[disk]):
+ # The speed reported by udisks is sometimes
+ # less than 5G bits/s, for example,
+ # it may be 705032705 bits/s
+ # So using
+ # 500000000
+ # = 500 M bits/s
+ # > 480 M bits/s ( USB 2.0 spec.)
+ # to make sure that it is higher USB version than 2.0
+ #
+ # int() for int(test.rem_disks_speed[disk])
+ # is necessary
+ # because the speed value of
+ # the dictionary rem_disks_speed is
+ # 1. str or int from _probe_disks_udisks2
+ # 2. int from _probe_disks_udisks1.
+ # This is really a mess. : (
+ print("\t\t--------------------------------")
+ if(500000000 < int(test.rem_disks_speed[disk])):
print("\t\tDevice Detected: SuperSpeed USB")
- print("\t\tDriver Detected: xhci_hcd")
+ # Unlike rem_disks_speed,
+ # which must has the connect speed
+ # for each disk devices,
+ # disk devices may not use xhci as
+ # controller drivers.
+ # This will raise KeyError for no
+ # associated disk device was found.
+ xhci_disks = test.get_disks_xhci()
+ # pep8 style suggest to limit the try clause
+ # to the absolute minimum amount of code necessary
+ try:
+ disk_xhci_flag = xhci_disks[disk]
+ except KeyError:
+ print("\t\tDisk does not use xhci_hci.")
+ return 1
+ else:
+ if('xhci' == disk_xhci_flag):
+ print("\t\tDriver Detected: xhci_hcd")
+ else:
+ print("\t\tDisk does not use xhci_hci.")
+ logging.debug("disk_xhci_flag is not xhci")
+ return 1
else:
+ # Give it a hint for the detection failure.
+ # LP: #1362902
+ print(("\t\tNo SuperSpeed USB using xhci_hcd "
+ "was detected correctly."))
+ print(("\t\tHint: please use dmesg to check "
+ "the system status again."))
return 1
# Pass is not assured
if (not args.pass_speed or
diff --git a/jobs/mediacard.txt.in b/jobs/mediacard.txt.in
index 262f1ffe..71fb8ab7 100644
--- a/jobs/mediacard.txt.in
+++ b/jobs/mediacard.txt.in
@@ -20,7 +20,7 @@ id: mediacard/mmc-storage
estimated_duration: 30.0
depends: mediacard/mmc-insert
user: root
-command: removable_storage_test -s 67120000 --memorycard sdio usb scsi
+command: removable_storage_test -s 67120000 --memorycard sdio usb scsi --auto-reduce-size
_description:
This test is automated and executes after the mediacard/mmc-insert
test is run. It tests reading and writing to the MMC card.
diff --git a/manage.py b/manage.py
index 2a9e2419..d97de5e6 100755
--- a/manage.py
+++ b/manage.py
@@ -4,7 +4,7 @@ from plainbox.provider_manager import N_
setup(
name='2013.com.canonical.certification:checkbox',
- version="0.13",
+ version="0.14",
description=N_("Checkbox provider"),
gettext_domain='2013.com.canonical.certification.checkbox',
strict=False, deprecated=False,
diff --git a/po/pl.po b/po/pl.po
index 6c9f850c..506b7f60 100644
--- a/po/pl.po
+++ b/po/pl.po
@@ -14,7 +14,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-09-27 05:37+0000\n"
+"X-Launchpad-Export-Date: 2014-10-15 05:42+0000\n"
"X-Generator: Launchpad (build 17196)\n"
"Language: Polish\n"