2
0
mirror of https://github.com/checkpoint-restore/criu synced 2025-08-26 11:57:52 +00:00

1777 Commits

Author SHA1 Message Date
Andrei Vagin
342019bb07 zdtm: avoid arithmetic overflow in datagen and datachk
p + FAST_SIZE > buffer + length

In this sentence p + FAST_SIZE may be bigger than (1<<32),
and we will be in trouble.

$ gdb -c coredump test/zdtm/static/write_read01

(gdb) p p
$3 = (uint8_t *) 0xffffa89e
(gdb) p buffer
$4 = (uint8_t *) 0xfff06780
(gdb) p length
$5 = 1000000

Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-10-22 06:34:53 +03:00
Pavel Emelyanov
62cc04df69 test: Scm tests no longer fail :)
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
2017-10-17 11:44:06 +03:00
Pavel Emelyanov
fd9fd56883 test: Zeroify scm buffer before filling
The CMSG_NXTHDR checks the length of the __next__ cmsg, i.e. the one
that it is about to return for filling. Thus, keeping there anything
but zeroes is unsafe.

Reported-by: Pavel Tikhomirov <snorcht@gmail.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
2017-10-17 11:41:51 +03:00
Pavel Emelyanov
49a2cbd62f zdtm: Send two descriptors in two SCMs
Only the send code is altered, as upon receiving kernel
merges all scm_rights int one. CRIU relies on this merge
and this is to catch situations if the kernel suddenly
stops doing this.

Reviewed-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-10-17 11:41:49 +03:00
Pavel Emelyanov
ff90e847ac zdtm: Send two descriptors in one message
Reviewed-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-10-17 11:41:49 +03:00
Pavel Emelyanov
c6908011bb zdtm: Send two descriptors via unix socket
Reviewed-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-10-17 11:41:49 +03:00
Pavel Emelyanov
00468aa801 zdtm: Test descriptor sent over unix and kept open
Reviewed-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-10-17 11:41:49 +03:00
Pavel Emelyanov
fb85281c3b zdtm: Test sit device C/R
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-10-17 10:48:46 +03:00
Andrei Vagin
0768d9203f zdtm: rework a synchronization scheme
Currently test_daemon() sends a signal to a parent process,
when a test completed a prepartion stage. But it doesn't work,
if a child changed uid and gid, because it doesn't have enough
permissions in this case.

This patch reworks a synchronization scheme to use a futex
instead of sending signals.

Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-10-17 10:21:45 +03:00
Cyrill Gorcunov
eff4c2acf4 test: thread_different_uid_gid -- Fixup sync points
Wait for thread to finish its creation instead of
calling sleep. Same time call for test_daemon
only when we're ready.

CC: Vitaly Ostrosablin <vostrosablin@virtuozzo.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-10-17 10:21:45 +03:00
Cyrill Gorcunov
bd56115303 test: thread_different_uid_gid -- Style nitpicking
CC: Vitaly Ostrosablin <vostrosablin@virtuozzo.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-10-17 10:21:45 +03:00
Andrei Vagin
105765830b zdtm: skip vsyscall vmas for x32 tests
It is known issue that a vsyscall vmas are not unmapped
from x32 processes.

Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-10-17 10:21:45 +03:00
Andrei Vagin
44dc01597a zdtm: don't use getpwnam and getgrnam
For us it doesn't matter what names of users and groups are used,
we want to be sure that we restore right uid-s and gid-s.

If we use these functions, we can't run tests in namespaces and
they use an external unix socket, what can be a problem too.

sk unix: 	Runaway socket: ino 0x1df1ae4 peer_ino 0x1df1ae3 family    1 type    1 state  1 name /run/dbus/system_bus_socket
Error (criu/sk-unix.c:712): sk unix: External socket is used. Consider using --ext-unix-sk option.

Cc: Vitaly Ostrosablin <vostrosablin@virtuozzo.com>
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-10-17 10:21:45 +03:00
Andrei Vagin
040c2487ea zdtm: check a reseted tcp connect
This test create a closed socket with a non-empty sent queue.

Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-10-17 08:40:44 +03:00
Alice Frosi
865f099d70 s390: Add test case for RI
- Add new test "s390x_runtime_instr" to check if the RI control block is
   correctly restored when the RI is active.

 - Add RI control block in test s390x_regs_check.c

The original test case for RI has been provided by
Martin Schwidefsky <schwidefsky@de.ibm.com>

Signed-off-by: Alice Frosi <alice@linux.vnet.ibm.com>
Reviewed-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-10-17 08:40:44 +03:00
Alice Frosi
581f731ba6 s390: Add test case for GS
- Add new test "s390x_gs_threads" for GS with broadcast command for the
s390_guarded_storage() system call.

 - Add GS control blocks in test s390x_regs_check.c

The original test case for GS has been provided by
Martin Schwidefsky <schwidefsky@de.ibm.com>

Signed-off-by: Alice Frosi <alice@linux.vnet.ibm.com>
Reviewed-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-10-17 08:40:44 +03:00
Andrei Vagin
f54acb48f9 zdtm: fix warnings from flake8
test/zdtm.py:1535:30: E711 comparison to None should be 'if cond is not None:'
test/zdtm.py:1538:31: E711 comparison to None should be 'if cond is not None:'
test/zdtm.py:1601:31: E711 comparison to None should be 'if cond is not None:'

Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-10-17 08:40:44 +03:00
Vitaly Ostrosablin
7d12ce293c zdtm: Implement different per-thread credentials testcase
As requested, implement a test with two threads that have mismatching,
non-root credentials, like Apache does.

Signed-off-by: Vitaly Ostrosablin <vostrosablin@virtuozzo.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-10-17 08:40:44 +03:00
Andrei Vagin
251b4d06a9 zdtm: report test results in the junit format
We found a good plugin for Jenkins to analize test results,
but it can handle only the junit format.

v2: work without the junit python module
v3: install junit-xml, because zdtm.py is executed
    with the --report option from jenkins scripts.

Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-10-17 08:40:44 +03:00
Andrei Vagin
7678f440ca test/zdtm: a few fixes to compile tests on Alpine
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-10-17 08:40:44 +03:00
Andrei Vagin
0a30316077 zdtm/autofs: don't include bits/signum.h
It isn't required and it is absant on alpine
autofs.c:9:25: fatal error: bits/signum.h: No such file or directory

Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-10-17 08:40:44 +03:00
Andrei Vagin
598790eb43 tcp: be ready that a size of tcp_info can be changed
(00.052683) Error (soccr/soccr.c:166): Failed to obtain TCP_INFO: No error information

We don't need a whole tcp info, so get only a part
what we are going to use.

Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-10-17 08:40:44 +03:00
Andrei Vagin
7178717bcf alpine: cast addresses to struct sockaddr *
Otherwise we get errors like this:

/usr/include/sys/socket.h:315:5: note: expected 'const struct sockaddr *' but argument is of type 'struct sockaddr_un *'
 int bind (int, const struct sockaddr *, socklen_t);

Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-10-17 08:40:44 +03:00
Andrei Vagin
c645cc937c alpine: use sys/wait.h instead of wait.h
In file included from socket_listen.c:22:0:
/usr/include/wait.h:1:2: error: #warning redirecting incorrect #include <wait.h> to <sys/wait.h> [-Werror=cpp]
 #warning redirecting incorrect #include <wait.h> to <sys/wait.h>

Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-10-17 08:40:44 +03:00
Andrei Vagin
fb67fb14f9 alpine: use uid_t instead of __uid_t
__uid_t isn't public

Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-10-17 08:40:44 +03:00
Andrei Vagin
d5d41bac19 zdtm: don't use find to get executable files
find: unrecognized: -executable
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-10-17 08:40:44 +03:00
Mike Rapoport
f7e52b8b4a jenkins: lazy-pages: split lazy-pages runs to local and remote
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-10-17 08:40:10 +03:00
Mike Rapoport
737a561703 jenkins: criu-lib: add BUILD_NUMBER to the archive filename
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-10-17 08:40:10 +03:00
Michael Holzheu
1a79b4d686 zdtm/s390x_regs_check: Fix wait() for threads
For older kernels (e.g. RHEL7 with 3.10) it seems that wait(NULL) after
ptrace(PTHREAD_ATTACH) does not work properly for threads that have
to be created via clone().

Fix this by using waitpid() with the __WALL flag.

>From the waitpid() man page:

 __WALL (since Linux 2.4)
 Wait  for  all  children, regardless of type ("clone" or "non-clone").

Reported-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-10-17 08:40:10 +03:00
Andrei Vagin
477618276b zdtm/chroot: allocate enough memory for a path
==36==ERROR: AddressSanitizer: heap-buffer-overflow on address
	0x60200000001c at pc 0x7fb26c88d5f9 bp 0x7ffc15087d40 sp 0x7ffc150874d0
WRITE of size 13 at 0x60200000001c thread T0
    #0 0x7fb26c88d5f8 in vsprintf (/lib64/libasan.so.4+0x9e5f8)
    #1 0x7fb26c88d986 in __interceptor_sprintf (/lib64/libasan.so.4+0x9e986)
    #2 0x402453 in main /root/git/main/criu/test/zdtm/static/chroot.c:68
    #3 0x7fb26c43e4d9 in __libc_start_main (/lib64/libc.so.6+0x204d9)
    #4 0x4031b9 in _start (/root/git/main/criu/test/zdtm/static/chroot+0x4031b9)

Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-10-17 08:40:10 +03:00
Michael Holzheu
7c0cedd84e zdtm/s390x_regs_check: Fix compiler warning
When running 'make zdtm' on s390x it fails on RHEL7 with:

 make[3]: Leaving directory `/tmp/criu/test/zdtm/lib'
  CC        s390x_regs_check.o
 s390x_regs_check.c: In function "util_hexdump_grp":
 s390x_regs_check.c:214:7: error: "ptr" may be used uninitialized
 in this function [-Werror=maybe-uninitialized]
    ptr += sprintf(ptr, "%02x", buf[i]);

Fix this and assign ptr from the beginning to help gcc.

Reported-by: Adrian Reber <adrian@lisas.de>
Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Acked-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-10-17 08:39:06 +03:00
Stanislav Kinsburskiy
a58330a26b tests: do not try to read more than packet in AutoFS test
The intention was to make sure, that only one packet is sent at a time.
And thus read has to return exactly the size of one packet.

But it doesnt' work as expected, because size of autofs_v5_packet_union
differs on 32 bit and 64 bit architectures.

This is a bug, but it's hidden so deeply, that no one really cares by the
following 2 aspects:

 1) Autofs pipe has O_DIRECT flag, which means excess bytes will be discarded
    upon read.
 2) No one tries to read more than one packet size at a time.

So let's fix the test instead and do not try to read more bytes, than
expected.

Signed-off-by: Stanislav Kinsburskiy <skinsbursky@virtuozzo.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-09-21 01:01:39 +03:00
Dmitry Safonov
8459a3de9d vdso/zdtm: Add iterative proxification test
Test for previously fixed bugs for vdso-trampolines insertion:
- unmapping original vvar (which went unnoticed)
- leaving rt-vvar after each C/R cycle and resulting pollution

Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-09-21 00:56:51 +03:00
Dmitry Safonov
17644ff3c8 zdtm/vdso: Add test for restoring task without vdso blob
Check that task without vvar & vdso blobs is restored without them.

Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-09-21 00:48:21 +03:00
Mike Rapoport
440a2a864a jenkins: lazy-pages: skip maps04 for remote-lazy-pages
Even with 2 parallel jobs maps04 takes too much time with
--remote-lazy-pages. Let's skip it for now.

Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-09-17 03:27:03 +03:00
Mike Rapoport
97fbb1bdc4 jenkins: lazy-pages: reduce amount of parallel runs for --remote case
Running zdtm/static/maps04 with --remote-lazy-pages in parallel with 3
other tests takes too much time on the Jenkins builder. Let's try running
with --parallel 2.

Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-09-17 03:27:03 +03:00
Dmitry Safonov
8d80012bf1 zdtm: rely on -D_GNU_SOURCE passed from Makefiles
After the commit
  02c763939c10 ("test/zdtm: unify common code")

CFLAGS with -D_GNU_SOURCE defined in the top Makefile
are being passed to tests Makefiles.
As _GNU_SOURCE is also defined by tests, that resulted in
zdtm tests build failures:

  make[2]: Entering directory `/home/criu/test/zdtm/lib'
   CC        test.o
  test.c:1:0: error: "_GNU_SOURCE" redefined [-Werror]
   #define _GNU_SOURCE
   ^
  <command-line>:0:0: note: this is the location of the previous definition
  cc1: all warnings being treated as errors
  make[2]: *** [test.o] Error 1

However, we didn't catch this in time by Travis-CI, as zdtm.py doesn't
do `make zdtm`, rather it does `make -C test/zdtm/{lib,static,transition}`.
By calling middle makefile this way, it doesn't have _GNU_SOURCE in
CFLAGS from top-Makefile.

I think the right thing to do here - is following CRIU's way:
rely on definition of _GNU_SOURCE by Makefiles.

This patch is almost fully generated with
  find test/zdtm/ -name '*.c' -type f					\
     -exec sed -i '/define _GNU_SOURCE/{n;/^$/d;}' '{}' \;		\
     -exec sed -i '/define _GNU_SOURCE/d' '{}' \;

With an exception for adding -D_GNU_SOURCE in tests Makefile.inc for
keeping the same behaviour for zdtm.py.
Also changed utsname.c to use utsname::domainname, rather private
utsname::__domainname, as now it's uncovered (from sys/utsname.h):
> struct utsname
>  {
...
> # ifdef __USE_GNU
>     char domainname[_UTSNAME_DOMAIN_LENGTH];
> # else
>     char __domainname[_UTSNAME_DOMAIN_LENGTH];
> # endif

Reported-by: Adrian Reber <areber@redhat.com>
Cc: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-09-17 03:27:02 +03:00
Mike Rapoport
1dc55aef45 test/zdtm: do not allow running with --lazy-pages on kernel without uffd
Raise an exception for kernels that do not have userfaultfd. For the
kernels that have userfaultfd but do not provide non-cooperative events
(4.3 - 4.11) just print a warning.

Fixes: #363

Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
2017-09-17 03:27:02 +03:00
Mike Rapoport
b1aca099cc test: add test that verifies proper intraction between lazy-pages and THP
Acked-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-09-16 12:30:22 +03:00
Mike Rapoport
0ebf7b81fa test/jenkins: update lazy-pages testing
* select excluded tests based on the kernel version
* test local and remote lazy-pages with and withour pre-dump

Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-09-16 12:29:57 +03:00
Mike Rapoport
77c115f3bf test: enable fork* tests for --remote-lazy-pages
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-09-16 12:29:55 +03:00
Mike Rapoport
459b833a8e zdtm: enable fork tests with --lazy-pages
They still will fail with --remote-lazy-pages, so mark them as
'noremotelazy'

Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-09-16 12:29:43 +03:00
Mike Rapoport
eb261b579d zdtm: introduce 'noremotelazy' flag
This allows skipping tests that are not yet run with --remote-lazy-pages,
but can be run with --lazy-pages

Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-09-16 12:29:43 +03:00
Mike Rapoport
a9ea60f8b3 zdtm: check lazy-pages and page-server exit status after test is gone
When running with --lazy-pages or --remote-lazy-pages, the daemons should
run in the background, rather than complete before t.stop() is called.
Many tests try to verify things are ok after test_waitsig() and that's
exactly the place where they access memory and cause page faults.

Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-09-16 12:29:43 +03:00
Mike Rapoport
8eae2ee844 test: add basic test for uffd events
The lazy-pages daemon have to properly track changes to virtual memory
layout of the restored process. The test verifies that lazy-pages daemon
properly reacts to fork(), exit(), madvise(MADV_DONTNEED) and mremap()
events.
Currently, no zdtm tests would generate UFFD_EVENT_{REMAP,REMOVE}.

Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
2017-09-16 11:47:03 +03:00
Andrei Vagin
6110ce00a1 zdtm.py: use --status-fd instead of --daemon for lazy stuff
It works faster and allows to check exit codes.

travis-ci: success for series starting with [1/2] page-server: don't return a server pid from page-server
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
2017-09-16 11:47:02 +03:00
Andrei Vagin
f75db3cdc9 test: check exit codes for criu criu lazy-pages
travis-ci: success for crtools: close a signal descriptor after passing a preparation stage (rev6)
Cc: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
2017-09-16 11:47:02 +03:00
Mike Rapoport
e5b4fcb6cd zdtm.py: postpone waiting for lazy-pages daemon
Currently we are waiting for lazy-pages daemon to finish as a part of
.restore method, which may cause filling test process memory before the
test process resumed it's execution after call to test_waitsig(). In such
case, no page faults occur, but rather all the memory is copied in
handle_remaining_pages method in uffd.c.
Let's move wait(<lazy-pages-pid>,..) after call to test.stop().

travis-ci: success for lazy-pages: add non-#PF events handling
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
2017-09-16 11:47:02 +03:00
Mike Rapoport
6de76ba0ac test/jenkins: extend lazy-pages testing
Add pre-dump and remote-lazy-pages passes to criu-lazy-pages.sh

Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
2017-09-16 11:47:02 +03:00
Mike Rapoport
c89a22a8e9 zdtm: simulate lazy migration with page server that can send pages
Lazy migration requires both dumped and restored processes to coexist at
the same time. This breaks some basic assumptions in the zdtm design.
Simulation of lazy migration with the page server allows testing most of
the involved code paths without major intervention into zdtm
infrastructure.

travis-ci: success for lazy-pages: improve testability (rev2)
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
2017-09-16 11:47:02 +03:00