pax_global_header00006660000000000000000000000064125425225300014512gustar00rootroot0000000000000052 comment=38ee94829bb57d2c5c788378dcd71bb5818375f9 kimchi-1.5.0/000077500000000000000000000000001254252253000127615ustar00rootroot00000000000000kimchi-1.5.0/.gitignore000066400000000000000000000011611254252253000147500ustar00rootroot00000000000000*.pyc *~ i18n/mo/* log data mo autom4te.cache Makefile Makefile.in aclocal.m4 build-aux/compile build-aux/config.guess build-aux/config.sub build-aux/install-sh build-aux/missing build-aux/py-compile configure config.log config.status contrib/DEBIAN/control contrib/kimchi.spec.fedora contrib/kimchi.spec.suse contrib/make-deb.sh docs/kimchid.8 *.min.css *.min.js *.gmo 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 plugins/sample/po/POTFILES plugins/sample/sample.conf po/POTFILES po/gen-pot *.orig *.rej *.pem ui/pages/help/*/*.html kimchi-1.5.0/ABOUT-NLS000066400000000000000000002671321254252253000142230ustar00rootroot000000000000001 Notes on the Free Translation Project *************************************** Free software is going international! The Free Translation Project is a way to get maintainers of free software, translators, and users all together, so that free software will gradually become able to speak many languages. A few packages already provide translations for their messages. If you found this `ABOUT-NLS' file inside a distribution, you may assume that the distributed package does use GNU `gettext' internally, itself available at your nearest GNU archive site. But you do _not_ need to install GNU `gettext' prior to configuring, installing or using this package with messages translated. Installers will find here some useful hints. These notes also explain how users should proceed for getting the programs to use the available translations. They tell how people wanting to contribute and work on translations can contact the appropriate team. 1.1 INSTALL Matters =================== Some packages are "localizable" when properly installed; the programs they contain can be made to speak your own native language. Most such packages use GNU `gettext'. Other packages have their own ways to internationalization, predating GNU `gettext'. By default, this package will be installed to allow translation of messages. It will automatically detect whether the system already provides the GNU `gettext' functions. Installers may use special options at configuration time for changing the default behaviour. The command: ./configure --disable-nls will _totally_ disable translation of messages. When you already have GNU `gettext' installed on your system and run configure without an option for your new package, `configure' will probably detect the previously built and installed `libintl' library and will decide to use it. If not, you may have to to use the `--with-libintl-prefix' option to tell `configure' where to look for it. Internationalized packages usually have many `po/LL.po' files, where LL gives an ISO 639 two-letter code identifying the language. Unless translations have been forbidden at `configure' time by using the `--disable-nls' switch, all available translations are installed together with the package. However, the environment variable `LINGUAS' may be set, prior to configuration, to limit the installed set. `LINGUAS' should then contain a space separated list of two-letter codes, stating which languages are allowed. 1.2 Using This Package ====================== As a user, if your language has been installed for this package, you only have to set the `LANG' environment variable to the appropriate `LL_CC' combination. If you happen to have the `LC_ALL' or some other `LC_xxx' environment variables set, you should unset them before setting `LANG', otherwise the setting of `LANG' will not have the desired effect. Here `LL' is an ISO 639 two-letter language code, and `CC' is an ISO 3166 two-letter country code. For example, let's suppose that you speak German and live in Germany. At the shell prompt, merely execute `setenv LANG de_DE' (in `csh'), `export LANG; LANG=de_DE' (in `sh') or `export LANG=de_DE' (in `bash'). This can be done from your `.login' or `.profile' file, once and for all. You might think that the country code specification is redundant. But in fact, some languages have dialects in different countries. For example, `de_AT' is used for Austria, and `pt_BR' for Brazil. The country code serves to distinguish the dialects. The locale naming convention of `LL_CC', with `LL' denoting the language and `CC' denoting the country, is the one use on systems based on GNU libc. On other systems, some variations of this scheme are used, such as `LL' or `LL_CC.ENCODING'. You can get the list of locales supported by your system for your language by running the command `locale -a | grep '^LL''. Not all programs have translations for all languages. By default, an English message is shown in place of a nonexistent translation. If you understand other languages, you can set up a priority list of languages. This is done through a different environment variable, called `LANGUAGE'. GNU `gettext' gives preference to `LANGUAGE' over `LANG' for the purpose of message handling, but you still need to have `LANG' set to the primary language; this is required by other parts of the system libraries. For example, some Swedish users who would rather read translations in German than English for when Swedish is not available, set `LANGUAGE' to `sv:de' while leaving `LANG' to `sv_SE'. Special advice for Norwegian users: The language code for Norwegian bokma*l changed from `no' to `nb' recently (in 2003). During the transition period, while some message catalogs for this language are installed under `nb' and some older ones under `no', it's recommended for Norwegian users to set `LANGUAGE' to `nb:no' so that both newer and older translations are used. In the `LANGUAGE' environment variable, but not in the `LANG' environment variable, `LL_CC' combinations can be abbreviated as `LL' to denote the language's main dialect. For example, `de' is equivalent to `de_DE' (German as spoken in Germany), and `pt' to `pt_PT' (Portuguese as spoken in Portugal) in this context. 1.3 Translating Teams ===================== For the Free Translation Project to be a success, we need interested people who like their own language and write it well, and who are also able to synergize with other translators speaking the same language. Each translation team has its own mailing list. The up-to-date list of teams can be found at the Free Translation Project's homepage, `http://translationproject.org/', in the "Teams" area. If you'd like to volunteer to _work_ at translating messages, you should become a member of the translating team for your own language. The subscribing address is _not_ the same as the list itself, it has `-request' appended. For example, speakers of Swedish can send a message to `sv-request@li.org', having this message body: subscribe Keep in mind that team members are expected to participate _actively_ in translations, or at solving translational difficulties, rather than merely lurking around. If your team does not exist yet and you want to start one, or if you are unsure about what to do or how to get started, please write to `coordinator@translationproject.org' to reach the coordinator for all translator teams. The English team is special. It works at improving and uniformizing the terminology in use. Proven linguistic skills are praised more than programming skills, here. 1.4 Available Packages ====================== Languages are not equally supported in all packages. The following matrix shows the current state of internationalization, as of June 2010. The matrix shows, in regard of each package, for which languages PO files have been submitted to translation coordination, with a translation percentage of at least 50%. Ready PO files af am an ar as ast az be be@latin bg bn_IN bs ca +--------------------------------------------------+ a2ps | [] [] | aegis | | ant-phone | | anubis | | aspell | [] [] | bash | | bfd | | bibshelf | [] | binutils | | bison | | bison-runtime | [] | bluez-pin | [] [] | bombono-dvd | | buzztard | | cflow | | clisp | | coreutils | [] [] | cpio | | cppi | | cpplib | [] | cryptsetup | | dfarc | | dialog | [] [] | dico | | diffutils | [] | dink | | doodle | | e2fsprogs | [] | enscript | [] | exif | | fetchmail | [] | findutils | [] | flex | [] | freedink | | gas | | gawk | [] [] | gcal | [] | gcc | | gettext-examples | [] [] [] [] | gettext-runtime | [] [] | gettext-tools | [] [] | gip | [] | gjay | | gliv | [] | glunarclock | [] [] | gnubiff | | gnucash | [] | gnuedu | | gnulib | | gnunet | | gnunet-gtk | | gnutls | | gold | | gpe-aerial | | gpe-beam | | gpe-bluetooth | | gpe-calendar | | gpe-clock | [] | gpe-conf | | gpe-contacts | | gpe-edit | | gpe-filemanager | | gpe-go | | gpe-login | | gpe-ownerinfo | [] | gpe-package | | gpe-sketchbook | | gpe-su | [] | gpe-taskmanager | [] | gpe-timesheet | [] | gpe-today | [] | gpe-todo | | gphoto2 | | gprof | [] | gpsdrive | | gramadoir | | grep | | grub | [] [] | gsasl | | gss | | gst-plugins-bad | [] | gst-plugins-base | [] | gst-plugins-good | [] | gst-plugins-ugly | [] | gstreamer | [] [] [] | gtick | | gtkam | [] | gtkorphan | [] | gtkspell | [] [] [] | gutenprint | | hello | [] | help2man | | hylafax | | idutils | | indent | [] [] | iso_15924 | | iso_3166 | [] [] [] [] [] [] [] | iso_3166_2 | | iso_4217 | | iso_639 | [] [] [] [] | iso_639_3 | | jwhois | | kbd | | keytouch | [] | keytouch-editor | | keytouch-keyboa... | [] | klavaro | [] | latrine | | ld | [] | leafpad | [] [] | libc | [] [] | libexif | () | libextractor | | libgnutls | | libgpewidget | | libgpg-error | | libgphoto2 | | libgphoto2_port | | libgsasl | | libiconv | [] | libidn | | lifelines | | liferea | [] [] | lilypond | | linkdr | [] | lordsawar | | lprng | | lynx | [] | m4 | | mailfromd | | mailutils | | make | | man-db | | man-db-manpages | | minicom | | mkisofs | | myserver | | nano | [] [] | opcodes | | parted | | pies | | popt | | psmisc | | pspp | [] | pwdutils | | radius | [] | recode | [] [] | rosegarden | | rpm | | rush | | sarg | | screem | | scrollkeeper | [] [] [] | sed | [] [] | sharutils | [] [] | shishi | | skencil | | solfege | | solfege-manual | | soundtracker | | sp | | sysstat | | tar | [] | texinfo | | tin | | unicode-han-tra... | | unicode-transla... | | util-linux-ng | [] | vice | | vmm | | vorbis-tools | | wastesedge | | wdiff | | wget | [] [] | wyslij-po | | xchat | [] [] [] [] | xdg-user-dirs | [] [] [] [] [] [] [] [] [] | xkeyboard-config | [] [] | +--------------------------------------------------+ af am an ar as ast az be be@latin bg bn_IN bs ca 6 0 1 2 3 19 1 10 3 28 3 1 38 crh cs da de el en en_GB en_ZA eo es et eu fa +-------------------------------------------------+ a2ps | [] [] [] [] [] [] [] | aegis | [] [] [] | ant-phone | [] () | anubis | [] [] | aspell | [] [] [] [] [] | bash | [] [] [] | bfd | [] | bibshelf | [] [] [] | binutils | [] | bison | [] [] | bison-runtime | [] [] [] [] | bluez-pin | [] [] [] [] [] [] | bombono-dvd | [] | buzztard | [] [] [] | cflow | [] [] | clisp | [] [] [] [] | coreutils | [] [] [] [] | cpio | | cppi | | cpplib | [] [] [] | cryptsetup | [] | dfarc | [] [] [] | dialog | [] [] [] [] [] | dico | | diffutils | [] [] [] [] [] [] | dink | [] [] [] | doodle | [] | e2fsprogs | [] [] [] | enscript | [] [] [] | exif | () [] [] | fetchmail | [] [] () [] [] [] | findutils | [] [] [] | flex | [] [] | freedink | [] [] [] | gas | [] | gawk | [] [] [] | gcal | [] | gcc | [] [] | gettext-examples | [] [] [] [] | gettext-runtime | [] [] [] [] | gettext-tools | [] [] [] | gip | [] [] [] [] | gjay | [] | gliv | [] [] [] | glunarclock | [] [] | gnubiff | () | gnucash | [] () () () () | gnuedu | [] [] | gnulib | [] [] | gnunet | | gnunet-gtk | [] | gnutls | [] [] | gold | [] | gpe-aerial | [] [] [] [] | gpe-beam | [] [] [] [] | gpe-bluetooth | [] [] | gpe-calendar | [] | gpe-clock | [] [] [] [] | gpe-conf | [] [] [] | gpe-contacts | [] [] [] | gpe-edit | [] [] | gpe-filemanager | [] [] [] | gpe-go | [] [] [] [] | gpe-login | [] [] | gpe-ownerinfo | [] [] [] [] | gpe-package | [] [] [] | gpe-sketchbook | [] [] [] [] | gpe-su | [] [] [] [] | gpe-taskmanager | [] [] [] [] | gpe-timesheet | [] [] [] [] | gpe-today | [] [] [] [] | gpe-todo | [] [] [] | gphoto2 | [] [] () [] [] [] | gprof | [] [] [] | gpsdrive | [] [] [] | gramadoir | [] [] [] | grep | [] | grub | [] [] | gsasl | [] | gss | | gst-plugins-bad | [] [] [] [] [] | gst-plugins-base | [] [] [] [] [] | gst-plugins-good | [] [] [] [] [] [] | gst-plugins-ugly | [] [] [] [] [] [] | gstreamer | [] [] [] [] [] | gtick | [] () [] | gtkam | [] [] () [] [] | gtkorphan | [] [] [] [] | gtkspell | [] [] [] [] [] [] [] | gutenprint | [] [] [] | hello | [] [] [] [] | help2man | [] | hylafax | [] [] | idutils | [] [] | indent | [] [] [] [] [] [] [] | iso_15924 | [] () [] [] | iso_3166 | [] [] [] [] () [] [] [] () | iso_3166_2 | () | iso_4217 | [] [] [] () [] [] | iso_639 | [] [] [] [] () [] [] | iso_639_3 | [] | jwhois | [] | kbd | [] [] [] [] [] | keytouch | [] [] | keytouch-editor | [] [] | keytouch-keyboa... | [] | klavaro | [] [] [] [] | latrine | [] () | ld | [] [] | leafpad | [] [] [] [] [] [] | libc | [] [] [] [] | libexif | [] [] () | libextractor | | libgnutls | [] | libgpewidget | [] [] | libgpg-error | [] [] | libgphoto2 | [] () | libgphoto2_port | [] () [] | libgsasl | | libiconv | [] [] [] [] [] | libidn | [] [] [] | lifelines | [] () | liferea | [] [] [] [] [] | lilypond | [] [] [] | linkdr | [] [] [] | lordsawar | [] | lprng | | lynx | [] [] [] [] | m4 | [] [] [] [] | mailfromd | | mailutils | [] | make | [] [] [] | man-db | | man-db-manpages | | minicom | [] [] [] [] | mkisofs | | myserver | | nano | [] [] [] | opcodes | [] [] | parted | [] [] | pies | | popt | [] [] [] [] [] | psmisc | [] [] [] | pspp | [] | pwdutils | [] | radius | [] | recode | [] [] [] [] [] [] | rosegarden | () () () | rpm | [] [] [] | rush | | sarg | | screem | | scrollkeeper | [] [] [] [] [] | sed | [] [] [] [] [] [] | sharutils | [] [] [] [] | shishi | | skencil | [] () [] | solfege | [] [] [] | solfege-manual | [] [] | soundtracker | [] [] [] | sp | [] | sysstat | [] [] [] | tar | [] [] [] [] | texinfo | [] [] [] | tin | [] [] | unicode-han-tra... | | unicode-transla... | | util-linux-ng | [] [] [] [] | vice | () () | vmm | [] | vorbis-tools | [] [] | wastesedge | [] | wdiff | [] [] | wget | [] [] [] | wyslij-po | | xchat | [] [] [] [] [] | xdg-user-dirs | [] [] [] [] [] [] [] [] [] | xkeyboard-config | [] [] [] [] [] [] | +-------------------------------------------------+ crh cs da de el en en_GB en_ZA eo es et eu fa 5 64 105 117 18 1 8 0 28 89 18 19 0 fi fr ga gl gu he hi hr hu hy id is it ja ka kn +----------------------------------------------------+ a2ps | [] [] [] [] | aegis | [] [] | ant-phone | [] [] | anubis | [] [] [] [] | aspell | [] [] [] [] | bash | [] [] [] [] | bfd | [] [] [] | bibshelf | [] [] [] [] [] | binutils | [] [] [] | bison | [] [] [] [] | bison-runtime | [] [] [] [] [] [] | bluez-pin | [] [] [] [] [] [] [] [] | bombono-dvd | [] | buzztard | [] | cflow | [] [] [] | clisp | [] | coreutils | [] [] [] [] [] | cpio | [] [] [] [] | cppi | [] [] | cpplib | [] [] [] | cryptsetup | [] [] [] | dfarc | [] [] [] | dialog | [] [] [] [] [] [] [] | dico | | diffutils | [] [] [] [] [] [] [] [] [] | dink | [] | doodle | [] [] | e2fsprogs | [] [] | enscript | [] [] [] [] | exif | [] [] [] [] [] [] | fetchmail | [] [] [] [] | findutils | [] [] [] [] [] [] | flex | [] [] [] | freedink | [] [] [] | gas | [] [] | gawk | [] [] [] [] () [] | gcal | [] | gcc | [] | gettext-examples | [] [] [] [] [] [] [] | gettext-runtime | [] [] [] [] [] [] | gettext-tools | [] [] [] [] | gip | [] [] [] [] [] [] | gjay | [] | gliv | [] () | glunarclock | [] [] [] [] | gnubiff | () [] () | gnucash | () () () () () [] | gnuedu | [] [] | gnulib | [] [] [] [] [] [] | gnunet | | gnunet-gtk | [] | gnutls | [] [] | gold | [] [] | gpe-aerial | [] [] [] | gpe-beam | [] [] [] [] | gpe-bluetooth | [] [] [] [] | gpe-calendar | [] [] | gpe-clock | [] [] [] [] [] | gpe-conf | [] [] [] [] | gpe-contacts | [] [] [] [] | gpe-edit | [] [] [] | gpe-filemanager | [] [] [] [] | gpe-go | [] [] [] [] [] | gpe-login | [] [] [] | gpe-ownerinfo | [] [] [] [] [] | gpe-package | [] [] [] | gpe-sketchbook | [] [] [] [] | gpe-su | [] [] [] [] [] [] | gpe-taskmanager | [] [] [] [] [] | gpe-timesheet | [] [] [] [] [] | gpe-today | [] [] [] [] [] [] [] | gpe-todo | [] [] [] | gphoto2 | [] [] [] [] [] [] | gprof | [] [] [] [] | gpsdrive | [] [] [] | gramadoir | [] [] [] | grep | [] [] | grub | [] [] [] [] | gsasl | [] [] [] [] [] | gss | [] [] [] [] [] | gst-plugins-bad | [] [] [] [] [] [] | gst-plugins-base | [] [] [] [] [] [] | gst-plugins-good | [] [] [] [] [] [] | gst-plugins-ugly | [] [] [] [] [] [] | gstreamer | [] [] [] [] [] | gtick | [] [] [] [] [] | gtkam | [] [] [] [] [] | gtkorphan | [] [] [] | gtkspell | [] [] [] [] [] [] [] [] [] | gutenprint | [] [] [] [] | hello | [] [] [] | help2man | [] [] | hylafax | [] | idutils | [] [] [] [] [] [] | indent | [] [] [] [] [] [] [] [] | iso_15924 | [] () [] [] | iso_3166 | [] () [] [] [] [] [] [] [] [] [] [] | iso_3166_2 | () [] [] [] | iso_4217 | [] () [] [] [] [] | iso_639 | [] () [] [] [] [] [] [] [] | iso_639_3 | () [] [] | jwhois | [] [] [] [] [] | kbd | [] [] | keytouch | [] [] [] [] [] [] | keytouch-editor | [] [] [] [] [] | keytouch-keyboa... | [] [] [] [] [] | klavaro | [] [] | latrine | [] [] [] | ld | [] [] [] [] | leafpad | [] [] [] [] [] [] [] () | libc | [] [] [] [] [] | libexif | [] | libextractor | | libgnutls | [] [] | libgpewidget | [] [] [] [] | libgpg-error | [] [] | libgphoto2 | [] [] [] | libgphoto2_port | [] [] [] | libgsasl | [] [] [] [] [] | libiconv | [] [] [] [] [] [] | libidn | [] [] [] [] | lifelines | () | liferea | [] [] [] [] | lilypond | [] [] | linkdr | [] [] [] [] [] | lordsawar | | lprng | [] | lynx | [] [] [] [] [] | m4 | [] [] [] [] [] [] | mailfromd | | mailutils | [] [] | make | [] [] [] [] [] [] [] [] [] | man-db | [] [] | man-db-manpages | [] | minicom | [] [] [] [] [] | mkisofs | [] [] [] [] | myserver | | nano | [] [] [] [] [] [] | opcodes | [] [] [] [] | parted | [] [] [] [] | pies | | popt | [] [] [] [] [] [] [] [] [] | psmisc | [] [] [] | pspp | | pwdutils | [] [] | radius | [] [] | recode | [] [] [] [] [] [] [] [] | rosegarden | () () () () () | rpm | [] [] | rush | | sarg | [] | screem | [] [] | scrollkeeper | [] [] [] [] | sed | [] [] [] [] [] [] [] [] | sharutils | [] [] [] [] [] [] [] | shishi | [] | skencil | [] | solfege | [] [] [] [] | solfege-manual | [] [] | soundtracker | [] [] | sp | [] () | sysstat | [] [] [] [] [] | tar | [] [] [] [] [] [] [] | texinfo | [] [] [] [] | tin | [] | unicode-han-tra... | | unicode-transla... | [] [] | util-linux-ng | [] [] [] [] [] [] | vice | () () () | vmm | [] | vorbis-tools | [] | wastesedge | () () | wdiff | [] | wget | [] [] [] [] [] [] [] [] | wyslij-po | [] [] [] | xchat | [] [] [] [] [] [] [] [] [] | xdg-user-dirs | [] [] [] [] [] [] [] [] [] [] [] [] [] | xkeyboard-config | [] [] [] [] [] | +----------------------------------------------------+ fi fr ga gl gu he hi hr hu hy id is it ja ka kn 105 121 53 20 4 8 3 5 53 2 120 5 84 67 0 4 ko ku ky lg lt lv mk ml mn mr ms mt nb nds ne +-----------------------------------------------+ a2ps | [] | aegis | | ant-phone | | anubis | [] [] | aspell | [] | bash | | bfd | | bibshelf | [] [] | binutils | | bison | [] | bison-runtime | [] [] [] [] [] | bluez-pin | [] [] [] [] [] | bombono-dvd | | buzztard | | cflow | | clisp | | coreutils | [] | cpio | | cppi | | cpplib | | cryptsetup | | dfarc | [] | dialog | [] [] [] [] [] | dico | | diffutils | [] [] | dink | | doodle | | e2fsprogs | | enscript | | exif | [] | fetchmail | | findutils | | flex | | freedink | [] | gas | | gawk | | gcal | | gcc | | gettext-examples | [] [] [] [] | gettext-runtime | [] | gettext-tools | [] | gip | [] [] | gjay | | gliv | | glunarclock | [] | gnubiff | | gnucash | () () () () | gnuedu | | gnulib | | gnunet | | gnunet-gtk | | gnutls | [] | gold | | gpe-aerial | [] | gpe-beam | [] | gpe-bluetooth | [] [] | gpe-calendar | [] | gpe-clock | [] [] [] [] [] | gpe-conf | [] [] | gpe-contacts | [] [] | gpe-edit | [] | gpe-filemanager | [] [] | gpe-go | [] [] [] | gpe-login | [] | gpe-ownerinfo | [] [] | gpe-package | [] [] | gpe-sketchbook | [] [] | gpe-su | [] [] [] [] [] [] | gpe-taskmanager | [] [] [] [] [] [] | gpe-timesheet | [] [] | gpe-today | [] [] [] [] | gpe-todo | [] [] | gphoto2 | | gprof | [] | gpsdrive | | gramadoir | | grep | | grub | | gsasl | | gss | | gst-plugins-bad | [] [] [] [] | gst-plugins-base | [] [] | gst-plugins-good | [] [] | gst-plugins-ugly | [] [] [] [] [] | gstreamer | | gtick | | gtkam | [] | gtkorphan | [] [] | gtkspell | [] [] [] [] [] [] [] | gutenprint | | hello | [] [] [] | help2man | | hylafax | | idutils | | indent | | iso_15924 | [] [] | iso_3166 | [] [] () [] [] [] [] [] | iso_3166_2 | | iso_4217 | [] [] | iso_639 | [] [] | iso_639_3 | [] | jwhois | [] | kbd | | keytouch | [] | keytouch-editor | [] | keytouch-keyboa... | [] | klavaro | [] | latrine | [] | ld | | leafpad | [] [] [] | libc | [] | libexif | | libextractor | | libgnutls | [] | libgpewidget | [] [] | libgpg-error | | libgphoto2 | | libgphoto2_port | | libgsasl | | libiconv | | libidn | | lifelines | | liferea | | lilypond | | linkdr | | lordsawar | | lprng | | lynx | | m4 | | mailfromd | | mailutils | | make | [] | man-db | | man-db-manpages | | minicom | [] | mkisofs | | myserver | | nano | [] [] | opcodes | | parted | | pies | | popt | [] [] [] | psmisc | | pspp | | pwdutils | | radius | | recode | | rosegarden | | rpm | | rush | | sarg | | screem | | scrollkeeper | [] [] | sed | | sharutils | | shishi | | skencil | | solfege | [] | solfege-manual | | soundtracker | | sp | | sysstat | [] | tar | [] | texinfo | [] | tin | | unicode-han-tra... | | unicode-transla... | | util-linux-ng | | vice | | vmm | | vorbis-tools | | wastesedge | | wdiff | | wget | [] | wyslij-po | | xchat | [] [] [] | xdg-user-dirs | [] [] [] [] [] [] [] [] | xkeyboard-config | [] [] [] | +-----------------------------------------------+ ko ku ky lg lt lv mk ml mn mr ms mt nb nds ne 20 5 10 1 13 48 4 2 2 4 24 10 20 3 1 nl nn or pa pl ps pt pt_BR ro ru rw sk sl sq sr +---------------------------------------------------+ a2ps | [] [] [] [] [] [] [] [] | aegis | [] [] [] | ant-phone | [] [] | anubis | [] [] [] | aspell | [] [] [] [] [] | bash | [] [] | bfd | [] | bibshelf | [] [] | binutils | [] [] | bison | [] [] [] | bison-runtime | [] [] [] [] [] [] [] | bluez-pin | [] [] [] [] [] [] [] [] | bombono-dvd | [] () | buzztard | [] [] | cflow | [] | clisp | [] [] | coreutils | [] [] [] [] [] [] | cpio | [] [] [] | cppi | [] | cpplib | [] | cryptsetup | [] | dfarc | [] | dialog | [] [] [] [] | dico | [] | diffutils | [] [] [] [] [] [] | dink | () | doodle | [] [] | e2fsprogs | [] [] | enscript | [] [] [] [] [] | exif | [] [] [] () [] | fetchmail | [] [] [] [] | findutils | [] [] [] [] [] | flex | [] [] [] [] [] | freedink | [] [] | gas | | gawk | [] [] [] [] | gcal | | gcc | [] | gettext-examples | [] [] [] [] [] [] [] [] | gettext-runtime | [] [] [] [] [] [] [] [] [] | gettext-tools | [] [] [] [] [] [] | gip | [] [] [] [] [] | gjay | | gliv | [] [] [] [] [] [] | glunarclock | [] [] [] [] [] | gnubiff | [] () | gnucash | [] () () () | gnuedu | [] | gnulib | [] [] [] [] | gnunet | | gnunet-gtk | | gnutls | [] [] | gold | | gpe-aerial | [] [] [] [] [] [] [] | gpe-beam | [] [] [] [] [] [] [] | gpe-bluetooth | [] [] | gpe-calendar | [] [] [] [] | gpe-clock | [] [] [] [] [] [] [] [] | gpe-conf | [] [] [] [] [] [] [] | gpe-contacts | [] [] [] [] [] | gpe-edit | [] [] [] | gpe-filemanager | [] [] [] | gpe-go | [] [] [] [] [] [] [] [] | gpe-login | [] [] | gpe-ownerinfo | [] [] [] [] [] [] [] [] | gpe-package | [] [] | gpe-sketchbook | [] [] [] [] [] [] [] | gpe-su | [] [] [] [] [] [] [] [] | gpe-taskmanager | [] [] [] [] [] [] [] [] | gpe-timesheet | [] [] [] [] [] [] [] [] | gpe-today | [] [] [] [] [] [] [] [] | gpe-todo | [] [] [] [] [] | gphoto2 | [] [] [] [] [] [] [] [] | gprof | [] [] [] | gpsdrive | [] [] | gramadoir | [] [] | grep | [] [] [] [] | grub | [] [] [] | gsasl | [] [] [] [] | gss | [] [] [] | gst-plugins-bad | [] [] [] [] [] [] | gst-plugins-base | [] [] [] [] [] | gst-plugins-good | [] [] [] [] [] | gst-plugins-ugly | [] [] [] [] [] [] | gstreamer | [] [] [] [] [] | gtick | [] [] [] | gtkam | [] [] [] [] [] [] | gtkorphan | [] | gtkspell | [] [] [] [] [] [] [] [] [] [] | gutenprint | [] [] | hello | [] [] [] [] | help2man | [] [] | hylafax | [] | idutils | [] [] [] [] [] | indent | [] [] [] [] [] [] [] | iso_15924 | [] [] [] [] | iso_3166 | [] [] [] [] [] () [] [] [] [] [] [] [] [] | iso_3166_2 | [] [] [] | iso_4217 | [] [] [] [] [] [] [] [] | iso_639 | [] [] [] [] [] [] [] [] [] | iso_639_3 | [] [] | jwhois | [] [] [] [] | kbd | [] [] [] | keytouch | [] [] [] | keytouch-editor | [] [] [] | keytouch-keyboa... | [] [] [] | klavaro | [] [] | latrine | [] [] | ld | | leafpad | [] [] [] [] [] [] [] [] [] | libc | [] [] [] [] | libexif | [] [] () [] | libextractor | | libgnutls | [] [] | libgpewidget | [] [] [] | libgpg-error | [] [] | libgphoto2 | [] [] | libgphoto2_port | [] [] [] [] [] | libgsasl | [] [] [] [] [] | libiconv | [] [] [] [] [] | libidn | [] [] | lifelines | [] [] | liferea | [] [] [] [] [] () () [] | lilypond | [] | linkdr | [] [] [] | lordsawar | | lprng | [] | lynx | [] [] [] | m4 | [] [] [] [] [] | mailfromd | [] | mailutils | [] | make | [] [] [] [] | man-db | [] [] [] | man-db-manpages | [] [] [] | minicom | [] [] [] [] | mkisofs | [] [] [] | myserver | | nano | [] [] [] [] | opcodes | [] [] | parted | [] [] [] [] | pies | [] | popt | [] [] [] [] | psmisc | [] [] [] | pspp | [] [] | pwdutils | [] | radius | [] [] [] | recode | [] [] [] [] [] [] [] [] | rosegarden | () () | rpm | [] [] [] | rush | [] [] | sarg | | screem | | scrollkeeper | [] [] [] [] [] [] [] [] | sed | [] [] [] [] [] [] [] [] [] | sharutils | [] [] [] [] | shishi | [] | skencil | [] [] | solfege | [] [] [] [] | solfege-manual | [] [] [] | soundtracker | [] | sp | | sysstat | [] [] [] [] | tar | [] [] [] [] | texinfo | [] [] [] [] | tin | [] | unicode-han-tra... | | unicode-transla... | | util-linux-ng | [] [] [] [] [] | vice | [] | vmm | [] | vorbis-tools | [] [] | wastesedge | [] | wdiff | [] [] | wget | [] [] [] [] [] [] [] | wyslij-po | [] [] [] | xchat | [] [] [] [] [] [] [] [] [] | xdg-user-dirs | [] [] [] [] [] [] [] [] [] [] [] [] [] [] | xkeyboard-config | [] [] [] | +---------------------------------------------------+ nl nn or pa pl ps pt pt_BR ro ru rw sk sl sq sr 135 10 4 7 105 1 29 62 47 91 3 54 46 9 37 sv sw ta te tg th tr uk vi wa zh_CN zh_HK zh_TW +---------------------------------------------------+ a2ps | [] [] [] [] [] | 27 aegis | [] | 9 ant-phone | [] [] [] [] | 9 anubis | [] [] [] [] | 15 aspell | [] [] [] | 20 bash | [] [] [] | 12 bfd | [] | 6 bibshelf | [] [] [] | 16 binutils | [] [] | 8 bison | [] [] | 12 bison-runtime | [] [] [] [] [] [] | 29 bluez-pin | [] [] [] [] [] [] [] [] | 37 bombono-dvd | [] | 4 buzztard | [] | 7 cflow | [] [] [] | 9 clisp | | 10 coreutils | [] [] [] [] | 22 cpio | [] [] [] [] [] [] | 13 cppi | [] [] | 5 cpplib | [] [] [] [] [] [] | 14 cryptsetup | [] [] | 7 dfarc | [] | 9 dialog | [] [] [] [] [] [] [] | 30 dico | [] | 2 diffutils | [] [] [] [] [] [] | 30 dink | | 4 doodle | [] [] | 7 e2fsprogs | [] [] [] | 11 enscript | [] [] [] [] | 17 exif | [] [] [] | 16 fetchmail | [] [] [] | 17 findutils | [] [] [] [] [] | 20 flex | [] [] [] [] | 15 freedink | [] | 10 gas | [] | 4 gawk | [] [] [] [] | 18 gcal | [] [] | 5 gcc | [] [] [] | 7 gettext-examples | [] [] [] [] [] [] [] | 34 gettext-runtime | [] [] [] [] [] [] [] | 29 gettext-tools | [] [] [] [] [] [] | 22 gip | [] [] [] [] | 22 gjay | [] | 3 gliv | [] [] [] | 14 glunarclock | [] [] [] [] [] | 19 gnubiff | [] [] | 4 gnucash | () [] () [] () | 10 gnuedu | [] [] | 7 gnulib | [] [] [] [] | 16 gnunet | [] | 1 gnunet-gtk | [] [] [] | 5 gnutls | [] [] [] | 10 gold | [] | 4 gpe-aerial | [] [] [] | 18 gpe-beam | [] [] [] | 19 gpe-bluetooth | [] [] [] | 13 gpe-calendar | [] [] [] [] | 12 gpe-clock | [] [] [] [] [] | 28 gpe-conf | [] [] [] [] | 20 gpe-contacts | [] [] [] | 17 gpe-edit | [] [] [] | 12 gpe-filemanager | [] [] [] [] | 16 gpe-go | [] [] [] [] [] | 25 gpe-login | [] [] [] | 11 gpe-ownerinfo | [] [] [] [] [] | 25 gpe-package | [] [] [] | 13 gpe-sketchbook | [] [] [] | 20 gpe-su | [] [] [] [] [] | 30 gpe-taskmanager | [] [] [] [] [] | 29 gpe-timesheet | [] [] [] [] [] | 25 gpe-today | [] [] [] [] [] [] | 30 gpe-todo | [] [] [] [] | 17 gphoto2 | [] [] [] [] [] | 24 gprof | [] [] [] | 15 gpsdrive | [] [] [] | 11 gramadoir | [] [] [] | 11 grep | [] [] [] | 10 grub | [] [] [] | 14 gsasl | [] [] [] [] | 14 gss | [] [] [] | 11 gst-plugins-bad | [] [] [] [] | 26 gst-plugins-base | [] [] [] [] [] | 24 gst-plugins-good | [] [] [] [] | 24 gst-plugins-ugly | [] [] [] [] [] | 29 gstreamer | [] [] [] [] | 22 gtick | [] [] [] | 13 gtkam | [] [] [] | 20 gtkorphan | [] [] [] | 14 gtkspell | [] [] [] [] [] [] [] [] [] | 45 gutenprint | [] | 10 hello | [] [] [] [] [] [] | 21 help2man | [] [] | 7 hylafax | [] | 5 idutils | [] [] [] [] | 17 indent | [] [] [] [] [] [] | 30 iso_15924 | () [] () [] [] | 16 iso_3166 | [] [] () [] [] () [] [] [] () | 53 iso_3166_2 | () [] () [] | 9 iso_4217 | [] () [] [] () [] [] | 26 iso_639 | [] [] [] () [] () [] [] [] [] | 38 iso_639_3 | [] () | 8 jwhois | [] [] [] [] [] | 16 kbd | [] [] [] [] [] | 15 keytouch | [] [] [] | 16 keytouch-editor | [] [] [] | 14 keytouch-keyboa... | [] [] [] | 14 klavaro | [] | 11 latrine | [] [] [] | 10 ld | [] [] [] [] | 11 leafpad | [] [] [] [] [] [] | 33 libc | [] [] [] [] [] | 21 libexif | [] () | 7 libextractor | [] | 1 libgnutls | [] [] [] | 9 libgpewidget | [] [] [] | 14 libgpg-error | [] [] [] | 9 libgphoto2 | [] [] | 8 libgphoto2_port | [] [] [] [] | 14 libgsasl | [] [] [] | 13 libiconv | [] [] [] [] | 21 libidn | () [] [] | 11 lifelines | [] | 4 liferea | [] [] [] | 21 lilypond | [] | 7 linkdr | [] [] [] [] [] | 17 lordsawar | | 1 lprng | [] | 3 lynx | [] [] [] [] | 17 m4 | [] [] [] [] | 19 mailfromd | [] [] | 3 mailutils | [] | 5 make | [] [] [] [] | 21 man-db | [] [] [] | 8 man-db-manpages | | 4 minicom | [] [] | 16 mkisofs | [] [] | 9 myserver | | 0 nano | [] [] [] [] | 21 opcodes | [] [] [] | 11 parted | [] [] [] [] [] | 15 pies | [] [] | 3 popt | [] [] [] [] [] [] | 27 psmisc | [] [] | 11 pspp | | 4 pwdutils | [] [] | 6 radius | [] [] | 9 recode | [] [] [] [] | 28 rosegarden | () | 0 rpm | [] [] [] | 11 rush | [] [] | 4 sarg | | 1 screem | [] | 3 scrollkeeper | [] [] [] [] [] | 27 sed | [] [] [] [] [] | 30 sharutils | [] [] [] [] [] | 22 shishi | [] | 3 skencil | [] [] | 7 solfege | [] [] [] [] | 16 solfege-manual | [] | 8 soundtracker | [] [] [] | 9 sp | [] | 3 sysstat | [] [] | 15 tar | [] [] [] [] [] [] | 23 texinfo | [] [] [] [] [] | 17 tin | | 4 unicode-han-tra... | | 0 unicode-transla... | | 2 util-linux-ng | [] [] [] [] | 20 vice | () () | 1 vmm | [] | 4 vorbis-tools | [] | 6 wastesedge | | 2 wdiff | [] [] | 7 wget | [] [] [] [] [] | 26 wyslij-po | [] [] | 8 xchat | [] [] [] [] [] [] | 36 xdg-user-dirs | [] [] [] [] [] [] [] [] [] [] | 63 xkeyboard-config | [] [] [] | 22 +---------------------------------------------------+ 85 teams sv sw ta te tg th tr uk vi wa zh_CN zh_HK zh_TW 178 domains 119 1 3 3 0 10 65 51 155 17 98 7 41 2618 Some counters in the preceding matrix are higher than the number of visible blocks let us expect. This is because a few extra PO files are used for implementing regional variants of languages, or language dialects. For a PO file in the matrix above to be effective, the package to which it applies should also have been internationalized and distributed as such by its maintainer. There might be an observable lag between the mere existence a PO file and its wide availability in a distribution. If June 2010 seems to be old, you may fetch a more recent copy of this `ABOUT-NLS' file on most GNU archive sites. The most up-to-date matrix with full percentage details can be found at `http://translationproject.org/extra/matrix.html'. 1.5 Using `gettext' in new packages =================================== If you are writing a freely available program and want to internationalize it you are welcome to use GNU `gettext' in your package. Of course you have to respect the GNU Library General Public License which covers the use of the GNU `gettext' library. This means in particular that even non-free programs can use `libintl' as a shared library, whereas only free software can use `libintl' as a static library or use modified versions of `libintl'. Once the sources are changed appropriately and the setup can handle the use of `gettext' the only thing missing are the translations. The Free Translation Project is also available for packages which are not developed inside the GNU project. Therefore the information given above applies also for every other Free Software Project. Contact `coordinator@translationproject.org' to make the `.pot' files available to the translation teams. kimchi-1.5.0/AUTHORS000066400000000000000000000024231254252253000140320ustar00rootroot00000000000000Adam King Adam Litke Adriano Botega Alexandre Tanaka Hirata Aline Manera apporc Anthony Liguori Bing Bu Cao Christy Perez Cole Robinson Crístian Viana Daniel H Barboza Eduardo Elias Ferreira Eli Qiao(Li Yong Qiao) Hongliang Wang Leonardo Garcia Lise Noble Malcolm Yu Mark Wu Mei Na Zhou Paulo Vital Pradeep K Surisetty Ramon Medeiros Rodrigo Trujilo Royce Lv ShaoHe Feng Shu Ming Toby Allsopp Tony Breeds Xin BJ Ding Yu Xin Huo Zhou Zheng Sheng kimchi-1.5.0/CONTRIBUTE.md000066400000000000000000000012151254252253000147600ustar00rootroot00000000000000How to Contribute ================= All development discussion happens on the mailing list. All development is done using the `git` SCM. Patches should be sent using the `git send-email` command to the kimchi-devel@ovirt.org mailing list. Good examples of how to send patches are included in [QEMU SubmitAPatch](http://wiki.qemu.org/Contribute/SubmitAPatch) and [Linux SubmittingPatches](https://www.kernel.org/doc/Documentation/SubmittingPatches). All documentation and READMEs are written using [Markdown](http://daringfireball.net/projects/markdown/). For a patch to be committed, it must receive at least one "Reviewed-by" on the mailing list. kimchi-1.5.0/COPYING000066400000000000000000000014711254252253000140170ustar00rootroot00000000000000Kimchi is distributed pursuant to the terms of two different licenses. The user interface (located in ui/ in this distribution) is governed by the Apache License version 2.0. imported from JQuery UI (http://jqueryui.com) The code under ui/spice-html5 is imported from spice-html5 project (http://cgit.freedesktop.org/spice/spice-html5) and the code under ui/libs which is imported from JQuery UI (http://jqueryui.com) The rest of this distribution is governed by the GNU Lesser General Public License version 3. See COPYING.LGPL and COPYING.ASL2. The name "Gentoo" and the "g" logo are trademarks of Gentoo Foundation, Inc. The content, project, site, product or any other type of item with which the "Gentoo" name is associated is not part of the Gentoo project and is not directed or managed by Gentoo Foundation, Inc. kimchi-1.5.0/COPYING.ASL2000066400000000000000000000261361254252253000145240ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. kimchi-1.5.0/COPYING.LGPL000066400000000000000000000167431254252253000145640ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. kimchi-1.5.0/ChangeLog000066400000000000000000006565541254252253000145600ustar00rootroot00000000000000CHANGELOG ========= #### [1.5.0] #### * [87bc47f] Prevent Kimchi against TLS Logjam attacks (Rodrigo Trujillo) * [aaa60fa] Issue #653: "make rpm" requests authentication with non-root (Ramon Medeiros) * [51f4dd5] Bug fix: Use a temp directory under /var to avoid permission errors (Aline Manera) * [e0db9f2] Bug fix: Detach host device prior to attach to guest (Aline Manera) * [ebd8f65] Gtihub #660 - Fixing .repo file with no repos handling (Daniel Henrique Barboza) * [dfb220f] Support xorriso ISOs detection (Ramon Medeiros) * [fc7ecea] Github #657 - fixing yum check-update parsing (Daniel Henrique Barboza) * [30ceeea] Bug fix: Allow user creates multiple templates (Aline Manera) * [c4d040b] Changing repositories and swupdate to use yumparser module (Daniel Henrique Barboza) * [4bfddd1] Unit tests for the yumparser module (Daniel Henrique Barboza) * [964d5eb] Adding yumparser module (Daniel Henrique Barboza) * [0c3a3e8] Fix bug #647: Properly set qxl as video model for Fedora 22 (Aline Manera) * [392feb9] Update po files for 1.5 release (Aline Manera) * [b19989b] Change the width of Actions button (Socorro Stoppler) * [c074f60] Fix tests, adds slot and memory hotplug tests (Rodrigo Trujillo) * [94826cf] Add maxMemory and numa configuration to guest xml (Rodrigo Trujillo) * [437e989] Add maxMemory into templates (Rodrigo Trujillo) * [86f0e13] Feature test to check support to memory devices (Rodrigo Trujillo) * [d2741fa] pep8 fixes (Daniel Henrique Barboza) * [7a4bd1b] UI-Template Edit: Enable user to change disk format (Rodrigo Trujillo) * [ee0c11d] Supress error messages while checking vm metadata (Ramon Medeiros) * [a1ad10e] Add support for Pause/Resume UI (Socorro Stoppler) * [9dea5f6] Does not list non-bootable images (Ramon Medeiros) * [577d85d] Enable storage volume upload on UI (Aline Manera) * [2d4cb23] Storage volume upload: Let the 'format' parameter be an empty string (Aline Manera) * [8a83cbe] Storage volume upload: Keep the task tracking to update the UI (Aline Manera) * [6704c66] Set 'used_by' to [] when creating some volumes (Crístian Deives) * [c384530] Replace storage volume 'ref_cnt' with 'used_by' (Crístian Deives) * [34634e9] Update test cases to reflect MAC address update changes (Jose Ricardo Ziviani) * [a1ac29f] Implement frontend code to edit MAC address of a guest (Jose Ricardo Ziviani) * [3058559] Implement backend code to edit MAC address of a guest (Jose Ricardo Ziviani) * [2ccb544] Add vfio driver as default for powerkvm systems. (Jose Ricardo Ziviani) * [82d4308] Removing the hardcoded version of kimchi and make it depend of PACKAGE_VERSION (Frédéric Bonnard) * [0ef10a1] UI: Enable virtual NIC hot plug/unplug (Aline Manera) * [16e2944] Change log message if command to run is not found (Jose Ricardo Ziviani) * [04d2953] Install service on make install (Ramon Medeiros) * [1aa919c] Fix SLES version checking in interfaces.py (Rodrigo Trujillo) * [0902323] Remove storage volume creation from file (Aline Manera) * [7f33702] Upload storage volume (Aline Manera) * [1327f49] Update controller to make update accept formdata params (Royce Lv) * [83e470f] Fix URI format of guest interfaces (Jose Ricardo Ziviani) * [872e379] Display MAC Address in guest interface tab (Jose Ricardo Ziviani) * [205a3f4] Avoid certificate validation on tests (Ramon Medeiros) * [8b5b932] Handle invalid path in 'get_disk_ref_cnt' (Crístian Deives) * [16c4b9b] fix: Use correct path when setting 'ref_cnt' to a new volume (Crístian Deives) * [b231913] Bug fix: Build default pools list according to user input (Aline Manera) * [f1a13ac] Fixed section number within the man page itself (Frederic Bonnard) * [1cc236f] Add documentation for VM suspend/resume (Crístian Deives) * [b61931d] Verify storage pool set as Template default prior to server starts up (Aline Manera) * [e0a6fb5] Verify all networks set as Template defaults prior to server start up (Aline Manera) * [e1ac636] Make Template defaults configurable (Aline Manera) * [2f0a442] snapshot: Handle non-existing snapshots in mock lookup (Crístian Deives) * [9b3fec5] Create option to auto create ISO pool or not on server start up (Aline Manera) * [bef2836] Add libvirt-daemon-config-network package as Kimchi dependency (Aline Manera) * [f6e0177] Merge common_spec with defaults value in osinfo.py (Aline Manera) * [aa36517] Remove useless variable in osinfo.py (Aline Manera) * [14e0179] Create VMs Asynchronously: UI (Aline Manera) * [8c85938] Create VMs Asynchronously: Tests (Christy Perez) * [698797a] Create VMs asynchronously: Backend (Christy Perez) * [a2c5abc] UI changes for new clone target_uri (Christy Perez) * [6aef7da] Tests for new clone target_uri (Christy Perez) * [e7eef4d] Append clone to target_uri for vm clone task (Christy Perez) * [a65075a] Do not resolve hostname to IP in using remote ISOs (Aline Manera) * [d6ec766] Improve code to retrieve the number of host CPUs (Jose Ricardo Ziviani) * [fde36c0] Move kimchi nginx config file to nginx default directory. (Jose Ricardo Ziviani) * [16a25ce] Add a warn about NM running in the system. (Jose Ricardo Ziviani) * [69af91d] Implement function to check if NM is running. (Jose Ricardo Ziviani) * [ec0a453] Host tests (Aline Manera) * [81dd7ce] issue #548: Hotplug network interfaces (Crístian Deives) * [aeb667d] Use default network model when attaching a NIC (Crístian Deives) * [838a30c] Handle missing parameter "network" when attaching a NIC (Crístian Deives) * [a00b2f7] Parse osinfo.lookup return parameters correctly (Crístian Deives) * [738165d] Remove nginx conf on suse (Ramon Medeiros) * [7fbb521] Create empty files on rpm build (Ramon Medeiros) * [b80e55c] Adds tests to check disk format information in new templates (Rodrigo Trujillo) * [85e9bac] Set qcow2 as default disk format in new templates (Rodrigo Trujillo) * [79c6105] Template: Assign 'raw' to disk format if pool is 'logical' or [i]scsi (Rodrigo Trujillo) * [61ede25] Server tests (Aline Manera) * [95cd887] Object store tests (Aline Manera) * [82e5658] Add support for VM suspend and resume (Crístian Viana) * [94533f9] Update some VM state conditions (Crístian Viana) * [a6b2ce2] Optimize VM update function (Crístian Viana) * [f393e07] Move stats-related VM functions to VMModel (Crístian Deives) * [9175b3e] Update stats when looking up one single VM (Crístian Deives) * [0cc163d] Add %Used in the header for storage (Socorro Stoppler) * [2ce0387] Security: Prevent Bar Mitzvah attacks by disabling RC4 (Aline Manera) * [1c716c6] issue #461: Add 'metalink' support for YUM repositories (Crístian Viana) * [65e10c2] Use more generic message in repo mirror list error (Crístian Viana) * [0190298] Handle empty variables when updating YUM repository (Crístian Viana) * [671fc4c] Update host number of cpus and total physical memory (Jose Ricardo Ziviani) * [61ffb22] Making urls relative (Frederic Bonnard) * [9185c35] test/test_model: Power architecture fixes (Daniel Henrique Barboza) * [6017105] Fix Network create name checking in backend (slashes and quotes) (Rodrigo Trujillo) * [0cb27b1] Move slash checking in storagepool name from UI to backend (Rodrigo Trujillo) * [acca0c3] Prohibits slashes '/' in VM name (Rodrigo Trujillo) * [8c4386c] issue #628: Set ref_cnt=1 on cloned disks (Crístian Viana) * [53779bd] Issue #623: Fix mismatch in host device details query (Royce Lv) * [a0b6ca0] Fix a ZeroDivisionError when starting kimchi service in Qemu. (Jose Ricardo Ziviani) #### [1.4.1] #### * [9123208] Update ChangeLog and VERSION file for 1.4.1 release (Aline Manera) * [5044020] Update pt_BR translations for Kimchi 1.4.1 (Aline Manera) * [4781452] Update .po files for translation (Aline Manera) * [44f0788] Kimchi tests: Power system fixes - removing hardcoded values (Daniel Henrique Barboza) * [6714909] tests/test_osinfo.py: fixes for Power architecture (Daniel Henrique Barboza) * [47d66eb] Specify user when changing VM disks permission (Crístian Viana) * [8f5c248] issue #518: Simplify template URL verification (Crístian Viana) * [923bf2d] Update ISO file's ACL before checking its permission (Crístian Viana) * [d501a6e] issue #564: Parse logical volumes to find out their actual formats (Crístian Viana) * [8eb00ed] issue #565: Allow a template's ISO to be a block device (Crístian Viana) * [f1a009b] Fix test_model.py to reset Singleton classes when initializing the tests (Aline Manera) * [0fe437f] Bug fix: Consider server is being started up on servermethod function (Aline Manera) * [fe65e09] Use the right firewall-cmd command to open Kimchi ports (Aline Manera) * [91e18b9] Fix issue #597: Get the right arch when using libvirt Test driver (Aline Manera) * [2cf3920] Fix issue #617: Base URL may be an empty string when updating YUM repo (Aline Manera) * [a6406e4] Fix issue #621: Catch libvirt exception when network does not have bridge name (Aline Manera) * [99dc469] Fix issue #620: Allow use iSCSI/SCSI volume on Template (Aline Manera) * [650655a] Add support to recognize RHEL-LE distro and version (Jose Ricardo Ziviani) * [bb9ccf7] Deregister peer information when kimchid exit (Royce Lv) * [27210d7] Update doc for federation (Royce Lv) * [70010ea] Assign HTML labels to their corresponding elements (Crístian Viana) * [d5e7800] Fix wrong usage of feature tests (Royce Lv) * [d2c3ad2] Avoid using server dependent feature tests when server not running (Royce Lv) * [30cf319] Remove slash "/" filter in template name when create VM (Rodrigo Trujillo) * [13de741] Remove unsupported Fedora ISO link (Royce Lv) * [c1553bb] Issue #587: Man page submission for kimchid (Frederic Bonnard) * [784c0bd] RHEL7: Guide user to install spice-html5 (Aline Manera) * [9a73497] Template tests (Aline Manera) * [7691b5a] bug fix: Allow adding a iSCSI/SCSI volume from a non-ASCII pool to a template (Aline Manera) * [77fe74e] Fix shallow scan test: wait until storage volume creation finished (Royce Lv) * [50b2a60] Change from using /usr/bin/python to /usr/bin/env python2 to improve portabi.. (Alan Jenkins) * [4143018] issue #595: Return correct memory value when VM is shutoff (Crístian Viana) * [37d5af1] Add function to convert data sizes (Crístian Viana) * [a338573] issue #545: Handle simultaneous authentication methods when updating VM perm.. (Crístian Viana) * [b5d1a03] Bug fix: Properly raise authenticate error when login fails (Aline Manera) * [0240f0c] Bug fix: Properly reload grid content (Aline Manera) * [2c6b1dc] Set a common message to KCHGRD6002M (Aline Manera) * [a17379a] Fix grammar for selected messages (Christy Perez) * [1a43119] Stop collecting background stats (Christy Perez) * [b529c0c] issue #512: Attach the function "showMessage" to the UI grid class (Crístian Viana) * [7fd7aed] Add Arch Linux entry to isoinfo. (Alan Jenkins) * [2aacf14] Add modern entry for Arch Linux. (Alan Jenkins) * [3cdb137] Set allocation=capacity when creating images in logical pools (Christy Perez) * [bef7afd] Disable SSL on nginx (Tulio Magno Quites Machado Filho) * [16d7e48] Fix issue #589: Add listener to remove Kimchi leftovers (Aline Manera) * [2f6a5d2] Fix issue #591: Get the right arch for MockModel (Aline Manera) * [0c41e50] Bugfix: Kimchi: Better to list storage pool paths (Wen Wang) * [eaf2349] Issue #573: Kimchi on ppc64el (Ramon Medeiros) * [a8a057e] Transient StoragePool POST request handling (Christy Perez) * [7714f22] Transient Network POST request handling (Christy Perez) * [97a47d2] Transient VM POST request handling (Christy Perez) * [464f5ee] Handle requests differently for transient objects (Christy Perez) * [640b257] On Ubuntu, current libvirt library requires XML (Aline Manera) * [686c314] Update vmtemplate.py to use get_disk_xml() while generating CDROM XML (Aline Manera) * [b94678e] Check QEMU stream DNS capability when attaching new disk to guest (Aline Manera) * [cded6a6] Get disk type according to file path on get_disk_xml() (Aline Manera) * [f2582f3] Remove ignore_src parameter from get_disk_xml() (Aline Manera) * [79930fd] Update get_disk_xml() to get the device same according to bus and index values (Aline Manera) * [8e89056] Remove 'bus' paramater from /vms//storages documentation (Aline Manera) * [f8b771f] Move vmdisks.py functions to xmlutils/disk.py (Aline Manera) * [291a778] Move _get_storage_xml() to xmlutils/disk.py (Aline Manera) * [be83d06] Number of CPUs in Host's Basic Information. (Paulo Vital) * [043db33] Remove libxml2-python as Kimchi dependency (Aline Manera) * [6a7704f] Use lxml.etree on gen-index.py script instead of libxml2 (Aline Manera) * [bd6d163] Use lxml.etree on xmlutils/utils.py instead of xml.etree and libxml2 (Aline Manera) * [d712d75] Remove pyc files on make clean (Christy Perez) * [c44aa09] AsyncTask: Improve continuous status feedback (Zhou Zheng Sheng) * [f33afdc] Translations for new cpu_info messages (Christy Perez) * [b6876d6] cpu_info tests for model and mockmodel (Christy Perez) * [c5dbd1f] Backend support for templates with sockets, cores, and threads (Christy Perez) * [1c8c539] ConfigTests: Fix novnc paths (Zhou Zheng Sheng) * [2000911] ModelTests: Improve leftover cleaning (Zhou Zheng Sheng) * [f28d16e] VMsModel: Make _update_guests_stats() robust against race condition (Zhou Zheng Sheng) * [a72d94b] LibvirtConnection: Share underlying connections between instances (Zhou Zheng Sheng) * [53b6b16] Update libvirtstoragepool.py to use lxml.builder (Aline Manera) * [4888826] add sub-makefile in src/kimchi/xmlutils (Simon Jin) * [e238fd2] Disabling screen log in production environment (Daniel Henrique Barboza) * [f14fcbf] Move networkxml.py to xmlutils module and update it to use lxml.builder (Aline Manera) * [f57a4af] Create a xmlutils module to hold all the XML manipulation (Aline Manera) * [65621fe] Update COPYING content to expose the imported code (Aline Manera) * [ac96bcb] Delete former imported spice code (Aline Manera) * [5a14498] Update Kimchi to use the installed spice-html5 (Aline Manera) * [6557b31] Add new spice-html5 code to Kimchi build process (Aline Manera) * [6083f7c] Modify spice_auto.html for Kimchi proposals (Aline Manera) * [b13f615] Import the latest spice-html5 code into Kimchi (Aline Manera) * [e62154a] Changes in sample plugin to fix and improve help (Rodrigo Trujillo) * [b5a3900] Fix problems to open plugin's help pages (Rodrigo Trujillo) * [1229515] Host device passthrough (Front-end): Add PCI Devices to VM (Yu Xin Huo) * [9cf9747] Host device passthrough: Add unit tests and documents (Zhou Zheng Sheng) * [604df1f] Host device passthrough: List VMs that are holding a host device (Zhou Zheng Sheng) * [12f650b] Host device passthrough: Directly assign and dissmis host device from VM (Zhou Zheng Sheng) * [42e642d] Host device passthrough: List eligible device to passthrough (Zhou Zheng Sheng) * [4fa2282] Host device passthrough: List all types of host devices (Zhou Zheng Sheng) * [aa6105d] Delete imported novnc code (Aline Manera) * [1774b96] Add novnc as Kimchi dependency (Aline Manera) * [afc42d0] Bugfix#414: Cannot login by clicking on the login button (Wen Wang) * [322f2f1] Enable remote libvirtd (Brent Baude) * [18deb57] Delete imported websockify code (Aline Manera) * [613650d] Add websockify as Kimchi dependency (Aline Manera) * [e41e2b8] bug fix: Redirect user to the URL accessed prior to login (Aline Manera) * [ff5b629] pep8: Use blacklist instead of whitelist (Crístian Viana) * [9d1b192] pep8: Fix errors in all files (Crístian Viana) * [0f6f05c] Display "README" with markdown style on Github (Crístian Viana) * [a660b2a] Fix: accelerate mockmodel for file upload (Royce Lv) * [1795a92] Bugfix: Cancel option not working properly in New Storage Define (Wen Wang) * [b4d48bd] Bug Fix: Correct select menu to handle empty input (Yu Xin Huo) * [65f14b2] Fix wrong config param of repository creation (Royce Lv) * [b6e00c5] Fix: retrieve right bus type in vmstorage update (Royce Lv) #### [1.3.0] #### * [57509ae] Update ChangeLog for 1.3 release (Aline Manera) * [eaa00fc] Update po files for 1.3 release (Aline Manera) * [244d933] issue #447: Check download URL prior to start Task (Aline Manera) * [cca060b] Update distros.d files to point to a valid URL (Aline Manera) * [2873011] issue #454: Properly display storage volumes in a pool with sub-directories (Aline Manera) * [ab97b92] Fix: Add rollback to update repository (Royce Lv) * [1d77625] Reject improper format for storage types (Royce Lv) * [05acc88] Fix: filter unsupported source type from volume list (Royce Lv) * [e5689c0] issue #445: Request /peers on every click (Aline Manera) * [c3c13e9] issue #462: Do not allow user to enter non-integer template disk size (Crístian Viana) * [e1623c3] build: Add README-federation.md to Kimchi package (Aline Manera) * [9754639] issue #447: Remove downloaded volume if an error occurs (Crístian Viana) * [d95faf6] issue #432: Display unique values for iSCSI targets (Aline Manera) * [c3975cc] issue #433: Fix repository tests (Crístian Viana) * [bff1039] issue #437: Only allow a bootable image file to be used on template (Aline Manera) * [705ae2a] issue #417: Validate image file path when creating a new template (Aline Manera) * [14b6ef0] Bugfix#424: Edit Template, "Disk (GB)" is changing with storage pool (Wen Wang) * [9ceea59] Update Chinese transtation to po (Wen Wang) * [e32155c] issue #435: Fix resource authorization logic (Crístian Viana) * [f1cfa3e] Bugfix#426: When no interface available, creating network popup error (Wen Wang) * [aa3b35b] help i18n: Add new languages to build process (Aline Manera) * [26283af] Bugfix#: Prevent overlap issue occurs under General tab on Edit (Wen Wang) * [812e490] Bugfix: Overlap issue occurs on the Power Off confirmation dialog (Wen Wang) * [762e7f6] Bug 431 Fix (Yu Xin Huo) * [75a00ca] issue #429: Properly set rollback function when creating vlan tagged bridged (Aline Manera) * [2426144] issue #415: Do not allow renaming a debug report to the same name (Crístian Viana) * [745c47e] Add firewall instructions to README-federation (Aline Manera) * [6152215] mock: Do not write file when downloading a volume (Crístian Viana) * [a045783] issue #447: Use required parameter in function "refresh" (Crístian Viana) * [ab9fe6f] Bug 416 Fix (Yu Xin Huo) * [71258eb] Bug 418 Fix (Yu Xin Huo) * [de32236] Issue #421: Grid Column Header Issue (Hongliang Wang) * [81b59c5] guest-storage-add: removing "Storage Name" backend support (Daniel Henrique Barboza) * [7f82708] guest-storage-add: removing "Storage Name" field (Daniel Henrique Barboza) * [6e1e469] bug fix: Probe image file only during the template creation (Aline Manera) * [e8fc599] Bug 446 Fix (Yu Xin Huo) * [2bb91e8] Bug 457 Fix (Yu Xin Huo) * [086fb80] Bugfix#420 UI: Pop up errors when log out at "Host" tab (Wen Wang) * [7964dcd] Revert "help i18n: Update Makefile to refeclt new languages." (Aline Manera) * [1937dff] help i18n: Update Simplified Chinese translation (Paulo Vital) * [072f9d6] help i18n: Update Portuguese (Brazil) translation (Paulo Vital) * [596d639] help i18n: Add Traditional Chinese translation (Paulo Vital) * [e240d51] help i18n: Add Russian translation (Paulo Vital) * [cddb664] help i18n: Add Korean translation (Paulo Vital) * [0c39477] help i18n: Add Japanese translation (Paulo Vital) * [0fe4a66] help i18n: Add Italian translation (Paulo Vital) * [e3568a3] help i18n: Add French translation (Paulo Vital) * [0cd30d5] help i18n: Add Spanish translation (Paulo Vital) * [0e016d1] help i18n: Add German translation (Paulo Vital) * [c964983] help i18n: Update Makefile to refeclt new languages. (Paulo Vital) * [340cf6d] Fix issue #430: Properly list packages update on openSUSE systems (Aline Manera) * [6e6a155] Delete useless variables assignment (Aline Manera) * [638dd40] Update openSUSE section in docs/README.md (Aline Manera) * [1ab51bf] Fix cdrom eject (Royce Lv) * [a0b280b] Disable upload option while adding a volume to a pool (Aline Manera) * [dbba218] Storage Pool Add Volume UI: Connect the Feature in Storage Tab (Hongliang Wang) * [5a92df3] Storage Pool Add Volume UI: Implement Download/Upload Volume Function (Hongliang Wang) * [0dfa0fa] Storage Pool Add Volume UI: Add i18n Strings (Hongliang Wang) * [4d0e3dd] Storage Pool Add Volume UI: Add APIs to kimchi.api.js (Hongliang Wang) * [3e2ac07] bug fix: Pass the right data format to run_command() (Aline Manera) * [7f477ea] python 2.6 compatibility: Use 'with' statement only with one context (Aline Manera) * [3114d5c] Update po files according to Transifex translations. (Aline Manera) * [975ab70] Update messages (Aline Manera) * [897a405] storagevolume: Use default value for param 'name' when appropriate (Crístian Viana) * [a6c7654] bug fix: Properly set max body size to nginx proxy (Aline Manera) * [8a8c959] Identify Kimchi variables from nginx config variables in nginx.conf.in file (Aline Manera) * [426e982] model.host: considering older libvirt versions (Daniel Henrique Barboza) * [afa9258] Increase read chunk size to 1MB while uploading file (Aline Manera) * [1e18c35] Only disable report buttons when the selected report is pending (Aline Manera) * [c635244] List pending debug reports while loading report grid (Aline Manera) * [29b926e] Add function to list all pending debug reports (Aline Manera) * [bb7881a] Add common function to track Task (Aline Manera) * [2778558] Add function to get pending tasks according to filter (Aline Manera) * [e434d3b] Fix: Use "max_request_body_size" value as int instead of string (Crístian Viana) * [cbf2bbf] UI: Template with VM Image - List (Yu Xin Huo) * [c02fcb8] UI: Template with VM Image - Edit (Yu Xin Huo) * [5faf008] UI: Template with VM Image - Create (Yu Xin Huo) * [95a05c6] Storage volume upload: Change mockmodel and test (Royce Lv) * [f041ffb] Storage volume upload: Adding progress to task message (Royce Lv) * [e4f152a] Storage volume upload: Support file based upload (Royce Lv) * [e3b79e3] Storage volume upload: Control request body size of kimchi (Royce Lv) * [22ca761] Storage volume upload: Parse params for upload formdata (Royce Lv) * [f07d4fa] Fix mockmodel reset for objectstore (Royce Lv) * [12220b7] Storage volume upload: Update API.md (Royce Lv) * [1e271aa] storagevolume: Set target URI when creating Task (Crístian Viana) * [2eae7ac] storagevolume: Add download progress to task (Crístian Viana) * [6befff6] storagevolume: Check storage pool before adding a volume (Crístian Viana) * [12d90ac] storagevolume: Download remote images to a storage pool (Crístian Viana) * [efe4d5c] Update current code to report target_uri while creating a Task (Aline Manera) * [f8f43b3] Expose target_uri on Task resource (Aline Manera) * [3ca880a] Update License Statement (Hongliang Wang) * [ff1bb81] Storage volume upload: Change storagevolumes to AsyncCollection (Royce Lv) * [9071b49] Storage volume upload: Dispatch volume create to right handler (Royce Lv) * [6f35bac] UI bug fix: Properly display storage volumes on Storage tab (Aline Manera) * [bd7b517] Guest storage: fix volume format overwrite (Royce Lv) * [535f0c0] UI: List Kimchi Peers (Yu Xin Huo) * [7749c16] Expose federation on /config/capabilities (Aline Manera) * [59e1d7e] Add documentation on how to enable federation on Kimchi (Aline Manera) * [6066971] Discover Kimchi peers using openSLP (Aline Manera) * [77b921f] Add federation option to Kimchi config file (Aline Manera) * [19d1ec3] Delete http_port from /config API as it is not in use anymore (Aline Manera) * [1b1c38f] Update kimchi.config values according to command line input (Aline Manera) * [6b06a50] Fix sample plugin configuration (Aline Manera) * [1798ae2] Guest storage: Fix attaching type judgement (Royce Lv) * [1fb4257] UI: List iSCSI Servers & Targets (Yu Xin Huo) * [e405e87] model.host: changing listDevices() to listAllDevices() (Daniel Henrique Barboza) * [6c10ea3] bug fix: Properly get the graphics expiration time (Aline Manera) * [d839a47] bug fix: Auto-generate guest console password when the passed value is an em.. (Aline Manera) * [a7d2942] i18n support: Add new languages in login page. (Paulo Vital) * [7cd3597] Allow user updates the passwd expiration time without changing the passwd (Aline Manera) * [c8bf6e2] Centralize graphics information (Aline Manera) * [e6931d7] Update iSCSI volume XML when creating a VM from an iSCSI pool (Aline Manera) * [30ca516] Fix duplicated message string in en_US.po file. (Paulo Vital) * [eaa20f5] i18n support: Add Traditional Chinese translation files. (Paulo Vital) * [ae21f41] i18n support: Add Russian translation files. (Paulo Vital) * [fa7d765] 18n support: Add Korean translation files. (Paulo Vital) * [b483d37] i18n support: Add Japanese translation files. (Paulo Vital) * [5608d41] i18n support: Add Italian translation files. (Paulo Vital) * [01aa06e] i18n support: Add French translation files. (Paulo Vital) * [4db8fce] i18n support: Add Spanish translation files. (Paulo Vital) * [1d23275] i18n support: Add German translation files. (Paulo Vital) * [0e15736] i18n support: Changed the file type of plugins/sample/po/LINGUAS (Paulo Vital) * [93a21ec] Update po files (Aline Manera) * [60c44f7] Add PowerKVM information as ISO otpion to installation. (Paulo Vital) * [3022860] Support tablet type as input device in VM's XML. (Eli Qiao) * [c456d43] Change function that verifies network interface status (Ramon Medeiros) * [1ebd9b2] Add unit tests for new vm 'persistent' property. (Christy Perez) * [f2ac85f] Add a check in the UI for the new 'persistent' flag of a VM. (Christy Perez) * [2238df2] Add persistent flag to VM info (Christy Perez) * [f1f9015] model/storagetargets: filtering used nfs paths (Daniel Henrique Barboza) * [e1fb135] Issue #405 - Fix enter hit in storage tab under guest edit window (Rodrigo Trujillo) * [2524fb4] Issue #405 - Fix cancel button in edit guest storage tab (Rodrigo Trujillo) * [e7b7a57] Allow admin user change permission settings when VM is running (Wen Wang) * [cff488a] UI: Delete Manage Media function from action list (Wen Wang) * [191c2f4] Bugfix UI: Change button text to indicate user network is generating (Wen Wang) * [0415a5f] Bugfix: Log out from Administrator tab raises popup errors (Wen Wang) * [47232dc] Fix UI: Show proper message when detaching a guest storage (Rodrigo Trujillo) * [55c053d] Refactor vmstorage name generation (Royce Lv) * [256c432] Remote ISO attachment: fix UI to accept remote ISO link for cdrom attachment (Royce Lv) * [7107956] Add unit tests for remote-backed CD ROM updates. (Christy Perez) * [aaea005] Fix verification of remote ISO (Christy Perez) * [f4006fe] Fix Key Error when editing CD ROM path (Christy Perez) * [6a4d2b3] UI: refactor guest edit code. (ShaoHe Feng) * [11f68f3] UI enhancement: Request /config/capabilities as soon as possible (Aline Manera) * [fd48ebb] Change default environment configuration to production mode. (Paulo Vital) * [28ea390] list host user names as less as possible (Simon Jin) * [945b6d5] bug fix: Properly list host partitions for Ubuntu 14.04 server (Aline Manera) * [dc8d508] Fix issue #340: Show error message when server fails to list host partitions (Aline Manera) * [50b5763] Increasing nginx proxy timeout (Daniel Henrique Barboza) * [1e2db06] repository: Remove error message prefix (Crístian Viana) * [103594e] typo: Fix "repositorie" (Crístian Viana) * [2696052] Issue #377: Validate repository URLs (Crístian Viana) * [424b436] bug fix: Allow kimchi runs in multiple platforms (Aline Manera) * [d001da8] bug fix: Add spice.css to Makefile and spec files (Aline Manera) * [ea41c72] Add tests for image based template (Royce Lv) * [cfdea72] Update mockmodel of base img vm (Royce Lv) * [169c77c] Create volume based on backing store image (Royce Lv) * [be8762e] Fix: Prevent iso links filling in osinfo.py (Royce Lv) * [9a54959] Change 'cdrom' to a optional param (Royce Lv) * [16a5810] Change doc and api specification (Royce Lv) * [4acea3b] Add image probe function (Royce Lv) * [672738d] Update testcases for bus type decision making (Royce Lv) * [dcf8f7b] Delete 'bus' selection from UI (Royce Lv) * [e4370ed] Delete 'bus' param from backend (Royce Lv) * [733a083] Update Chnagelog for 1.2.1.1 tag (Aline Manera) * [5ea98c7] Update license to LGPLv3 (Aline Manera) * [5f34ec8] Remove useless jquery files (Aline Manera) * [980b365] Remove useless image files (Aline Manera) * [2e90908] Install kimchi.mo files in the default locale dir (Aline Manera) * [d8e6e47] Add missing license headers (Aline Manera) * [e466333] Update copyright date (Aline Manera) * [1a926c1] UI bug fix: Properly display partitions when extending a logical pool (Aline Manera) * [dcc5838] Fix pep8 errors according to pep8 1.5.6 (Aline Manera) * [8188d7c] Disable vhost feature in Ubuntu and SLES (PPC64 LE) (Rodrigo Trujillo) * [3ddeefb] Change modern distro versions for PPC (Rodrigo Trujillo) * [d0984ca] PowerPC bootable ISO detection code (Daniel Henrique Barboza) * [4e65d8a] bug fix: Update genChangelog script (Aline Manera) * [228a56a] fix test case for volume filtering (Royce Lv) * [c5a90bd] Filter directory in storage volume listing (Royce Lv) * [0cf6558] Bugfix Issue #397 UI Broken when cookie is clear (Wen Wang) * [403d227] Fix pyflakes errors in make check (Royce Lv) * [52dcea3] bug fix: Avoid equals sign in VM console URL (Aline Manera) * [174a7be] Get user groups correctly (Crístian Viana) * [220d37c] Update ChangeLog and VERSION files for 1.2.1.1 release (Aline Manera) * [2136c20] Update Kimchi tag to remove 'kimchi-' prefix (Aline Manera) * [fc99a95] issue #389: Use 127.0.0.1 as VNC listener IP (Aline Manera) * [7f2963f] authorization: Update test cases based on last changes (Crístian Viana) * [f4b91ac] List "admin" as a valid system user in mockmodel (Crístian Viana) * [75a9acc] Move "fake_user" credentials to mockmodel (Crístian Viana) * [5bec021] Return some groups for every user in mockmodel (Crístian Viana) * [ba442f9] authorization: Remove authorization config from UrlSubNode (Aline Manera) * [ebb8392] authorization: Update control files to set role_key and admin_methods (Aline Manera) * [5570723] authorization: Restrict access to Resource instance (Aline Manera) * [19aa234] authorization: Restrict Collection access based on admin_methods parameter (Aline Manera) * [40f746f] authorization: Filter resources by users and groups (Aline Manera) * [e01a336] vm ticket in backend: update test case (ShaoHe Feng) * [85617c4] vm ticket in backend: update mockmodel (ShaoHe Feng) * [d6bf0bc] vm ticket in backend: update model (ShaoHe Feng) * [fabf9d8] vm ticket in backend: update controller and API.json (ShaoHe Feng) * [aff9cda] vm ticket in backend: update API.md (ShaoHe Feng) * [e47fc1e] authorization: update po files (Yu Xin Huo) * [286e8b2] authorization: add users/groups to vm (Yu Xin Huo) * [9f0933f] issue #374: Use base64 encoding to launch VM console (Aline Manera) * [0fb08af] Authorization: Remove actions based on roles (Wen Wang) * [eb5abf8] Authorization: remove [+] icon from non-root users view (Wen Wang) * [48d64cf] Authorization: remove host/template tabs for non-root users (Wen Wang) * [22eba43] Add roles into cookie (Wen Wang) * [c47c62e] add a base64 safe url encode and decode to js utils (ShaoHe Feng) * [e0a6e80] Let frontend redirect user after logging (Aline Manera) * [8bf9597] Remove special console rules from nginx configuration (Aline Manera) * [ea3db7e] Remove former login design files (Aline Manera) * [1fdda55] Update test case to reflect new login design (Aline Manera) * [14fbfe3] authorization: Get role according to tab instead of sudo rights (Aline Manera) * [a99cde0] authorization: Add "access" parameter to VM resource (Aline Manera) * [48b6a55] authorization: Add "access" elements to tabs.xml to describe user view (Aline Manera) * [1df92ad] authorization: Update /login to return user roles instead of sudo parameter (Aline Manera) * [7a62bf1] authorization: Update authorization rules per API (Aline Manera) * [582928c] Always use unicode in KimchiException message (Aline Manera) * [7c9b576] Debug Report Rename: Update Test Code (Royce Lv) * [12aa218] Debug Report: Update MockModel (Hongliang Wang) * [20aad65] Debug Report Rename UI: Enable Rename in Host Tab (Hongliang Wang) * [47bddf1] Debug Report Rename UI: Add Rename Page (Hongliang Wang) * [1aff19f] Debug Report Rename UI: Add API in kimchi.api.js (Hongliang Wang) * [bfaa81f] Debug Report: Sort Reports by Generated Time Descendingly (Hongliang Wang) * [b9c54b4] Debug Report: Use Generated Time instead of Most Changed Time (Hongliang Wang) * [7e6d766] Debug Report Rename: Implement Back-end (Hongliang Wang) * [d600011] Debug Report Rename: Update API.md (Hongliang Wang) * [7e7083e] Debug Report Rename: Update API.json (Hongliang Wang) * [1f2d758] Debug Report UI: Generate Report Doesn't Work with Mock Model (Hongliang Wang) * [377fd70] MockModel: Can't Generate Report if Name is not Given (Hongliang Wang) * [aef9d42] Add option to add/remove fonts files in rpm packages (ShaoHe Feng) * [7231a51] Remove useless fonts (Aline Manera) * [2f319d3] Change ISO stream feature test and kvm user test for PPC (Rodrigo Trujillo) * [ad655c4] Update API.md to reflect /host/users and /host/groups API (Aline Manera) * [07f037f] Translation updates for underscore in debug report (Christy Perez) * [d206f4c] UI changes to allow underscore in debug report name. (Christy Perez) * [b482880] Add SUSE's products (Dinar Valeev) #### [kimchi-1.2.1] #### * [31e0c0b] Update Changelog and po files for 1.2.1 release (Aline Manera) * [fcd407e] bugfix: Add policycoreutils-python as Kimchi dependency (Aline Manera) * [e475bfa] Add translation for vm disk attach exceptions (Royce Lv) * [593c420] Add testcase for vmstorages create (Royce Lv) * [954185e] Make sure path and volume will not be specified at same time (Royce Lv) * [a93aa45] Add mockmodel for vm disk attach (Royce Lv) * [fff58c2] issue#382: Validate form for adding guest cdrom (Royce Lv) * [e5333d7] issue#382 :Change false default value (Royce Lv) * [0599241] update case for root.get redirection (ShaoHe Feng) * [eed4f36] remove kimchisession hook and add the same logic to root.get (ShaoHe Feng) * [c13d53d] bug fix: redirect to the protected page after login (ShaoHe Feng) * [88affbe] Issue #380: Loading icon message splitted into two lines in Chinese (Wen Wang) * [5afa07f] bug fix: UI set the network persistent attribute. (ShaoHe Feng) * [4197f3a] Bugfix: Minor i18n updates(Chinese) (Wen Wang) * [9136f8d] add firewalld to debian Install Dependencies (ShaoHe Feng) * [0890b7a] bug fix: Set charset to help pages (Aline Manera) * [5ce667a] Show remote Ubuntu 14.04 x86_64 in new Template window (ShaoHe Feng) * [000149e] Update i18n package scripts(Chinese) (Wen Wang) * [e0a6643] Add missing translation entries in pt_BR (Crístian Viana) * [93784be] Add empty translation entries in English (Crístian Viana) * [45703ec] Help translation to zh_CN. (Paulo Vital) * [c29f1e2] Help translation to pt_BR. (Paulo Vital) * [b430576] Show remote Ubuntu 14.04 in new Template window (Rodrigo Trujillo) * [b5425f8] escape special characters for jQuery selector. (ShaoHe Feng) * [7b65e7b] escape < > and & in in xml for network name. (ShaoHe Feng) * [df9a017] network name support unicode. (ShaoHe Feng) * [2fabc33] bug fix: network name can be any characters except " and / (ShaoHe Feng) * [7167f31] Host info: Add support to Power. (Paulo Vital) * [4b096f2] Fix Bug: Actions Menu Disappears after Refresh in Guests Tab (Hongliang Wang) * [234c198] Bug fix: Do not require login for simple resources (Crístian Viana) * [14bc6fc] Typo: Rename function create_defautl_network (Crístian Viana) * [ba96997] Bug Fix: Fix network list layout. (Wen Wang) * [4a91e74] Issue#348: Fix UI for nfs mount (Royce Lv) * [3c6c5c5] List iSCSI targets available for initiator while creating iSCSI Pool (ShaoHe Feng) * [35050bf] List iSCSI server for initiator while creating iSCSI Pool (ShaoHe Feng) * [3f61acb] Issue #361: Bugfix disable the action button content when creating network (Hongliang Wang) * [7467feb] Fix i18n packaging scripts (Zhou Zheng Sheng) * [19b3c4a] Keep User from Generating a Report with an Existing Name (Hongliang Wang) * [a1bc654] Add progress Event Handler for Asynchronized Tasks (Hongliang Wang) * [5ea8e8f] Add License Statement in kimchi.report_add_main.js (Hongliang Wang) * [464d3d0] Add Name Existence Check for Debug Report when Create (Hongliang Wang) * [c89c2e0] Bug fix: Display the username on the header bar (Crístian Viana) * [8ce46e6] Add doc and test case for dedicate iso pool (Royce Lv) * [e3ab2ce] Store qemu user name in class attribute (Royce Lv) * [5dc4dd2] Dedicated ISO pool: create an out of box ISO pool (Royce Lv) * [ff92786] Reword 'isolated' network description (Christy Perez) * [9aeac73] Disable cache for help page (Royce Lv) * [27bd99f] Create pool UI: making 'Create' button disable when forms not filled. (Daniel Henrique Barboza) * [b7c518c] bug fix: Make rpm failed (ssdxiao) * [bd98489] update ui/pages/Makefile.am to let i18n.json.tmpl be added to the package. (ShaoHe Feng) * [578ab29] add some sample plugin generated files to .gitignore (ShaoHe Feng) * [26582d8] skip plugins test, when sample plugin is not enabled (ShaoHe Feng) * [de177c8] generate the translation files for plugins/sample (ShaoHe Feng) * [3ce13b5] add an option to toggle the sample plugin (ShaoHe Feng) * [38bee60] Issue #342: load i18n.html of the plugin (ShaoHe Feng) * [45b16d0] Add JS API for fetching i18n JSON (ShaoHe Feng) * [947bce5] Update the i18n tmpl to produce JSON (ShaoHe Feng) * [3205117] Update root.py to make Cheetah render the JSON template. (ShaoHe Feng) * [3d52774] Add Minimal UI Page for the Sample Plugin (Zhou Zheng Sheng) * [d8c2ea1] Bugfix: List inactive network interface while editing template (Wen Wang) * [cf015d4] login: update test config case (ShaoHe Feng) * [df4749b] login page prompts error when session timeout (ShaoHe Feng) * [ba0cf6e] login page prompts error when username or password is wrong (ShaoHe Feng) * [d7e828e] when login successfully, redirect to the last page. (ShaoHe Feng) * [85e3837] redirect the URL to login page when session timeout or first login (ShaoHe Feng) * [8f86568] create a new login page (ShaoHe Feng) * [a556578] Bugfix: Multiple progress indicator during debug report generating (Wen Wang) * [54e6bfa] Issue#305: Redesign bridged network UI section tempstorage (Wen Wang) * [fe23558] Add Ubuntu as modern distro to Power guests. (Paulo Vital) * [8c50cc8] Added the generating progress indicator (Wang Wen) * [250cc3d] Remove the first column of debug report grid (Wang Wen) * [c81314f] Add testcase for cdrom eject (Royce Lv) * [2768515] Update model to support cdrom eject (Royce Lv) * [3282020] Change doc and controllor to support cdrom eject (Royce Lv) * [cd67617] Adding test case for updating flags (Royce Lv) * [a48518b] Fix wrong create/update/delete flags for vmstorages (Royce Lv) * [5fee8c2] Fix Bug: Template Tab Broken in Chrome due to Code Error (Hongliang Wang) * [08a9c00] Bug Fix - Save Button Behaves Incorrectly in Guest Edit Window (Hongliang Wang) * [f2f137e] Remove Unused Files (Hongliang Wang) * [c4117ab] Adjust Guest Edit Storage Tab Styles (Hongliang Wang) * [339c1aa] show template is local or remote (ShaoHe Feng) * [7835e16] Update API.md (Hongliang Wang) * [6741700] Add Unit (MB) to Memory in Template Edit Window (Hongliang Wang) * [b558fd9] bug fix: decode volume name in IsoVolumesModel. (ShaoHe Feng) * [ef7e8e3] novnc does not work in IE (Adam King) * [8b6405f] Code Refector: Extract Variables in kimchi.login_window.js (Hongliang Wang) * [892238e] Disable metadata log output in every guest refresh (Crístian Viana) * [785920b] Repository Grid Column Resizing Issue (Hongliang Wang) * [76629f6] StoragePool Edit: Add Disk to Logical Pool (Royce Lv) * [5ee2b93] Exception: fix exception details when not specified (Royce Lv) * [7ca9ade] Remove cdrom '.iso' suffix checking from add template js (Rodrigo Trujillo) * [7e5f8b2] Remove '.iso' extension checking from json schema (Rodrigo Trujillo) * [a1e7364] model.host: avoid redundant libvirt lookupByName API invocation (Zhou Zheng Sheng) * [f7ec8f0] Rename kimchi.template to kimchi.substitute (Hongliang Wang) * [bd866e1] Remove unused listDeepScanIsos function (Rodrigo Trujillo) * [4448948] Update README with the correct FF ESR version. (Adam King) * [68d4d6c] VM template: add disk size error message (Zhou Zheng Sheng) * [0e165c4] adjust the width of host info-container (ShaoHe Feng) * [d65b8e5] UI: Fix VM Delete Confirmation Dialog Box Title (Zhou Zheng Sheng) * [96c19c6] Fix text alignment on storage pool type combo boxes (Crístian Viana) * [c5329c2] Remove button "Cancel" from modal dialog (Crístian Viana) * [0666eee] Fix Text Truncated Problem of Login Button (Hongliang Wang) * [ff7f991] bug fix: Allow changing default ports (Aline Manera) * [96f3248] bug fix: Update test cases to use HTTPS (Aline Manera) * [1d8476b] host/partitions: avoid calling disks.get_partitions_names() for each partition (Zhou Zheng Sheng) * [1d56572] Correct the ID String of Disk Size in Template Edit Window (Hongliang Wang) * [5c2a584] Issue #369: Fix config_dir assignment (Aline Manera) * [cc3b5b5] Revert "Host Tab: Add Widths for Repository Grid Columns" (Aline Manera) * [5dc3195] Fix Text Wrapping Problem in Template Edit (Hongliang Wang) * [9ececcf] Fix Text Wrapping in Tab Bar (Hongliang Wang) * [4128392] Github #368: Removing 'resend' tag from getHostStats JSON (Daniel Henrique Barboza) * [44ec020] Set IE edge mode for VNC/Spice web pages (Adam King) * [73e524c] bug fix: Properly set the listen IP to SPICE console (Aline Manera) * [58017f4] websockets: Disallow non-encrypted client connections (Aline Manera) * [381864f] UI: Redirect user to console page after logging (Aline Manera) * [be9b967] backend: Redirect 401 error to default page (Aline Manera) * [e1760d8] Enable Kimchi authentication in console pages (Aline Manera) * [74ad9b4] Make use of the mini Web server in the websockify (Aline Manera) * [9116d53] Enable encryption in vm console connection (Mark Wu) * [6ddf6a9] Revert "Enable encryption in vm VNC console connection" (Aline Manera) * [dc6c28e] vmiface update support: update test case (ShaoHe Feng) * [b813d6c] vmiface update support: update mockmodel (ShaoHe Feng) * [309aa71] vmiface update support: update model. (ShaoHe Feng) * [51820c4] vmiface update support: update API.md (ShaoHe Feng) * [c356a75] Display all disk types in storage edit view (Royce Lv) * [010aaac] UI: Support add guest disk (Royce Lv) * [b2d1217] Fix select menu data append (Royce Lv) * [3c294a5] Guest disks: Update testcase (Royce Lv) * [5df01ab] Multiple pep8 fixes (Royce Lv) * [2360f7c] Guest disk: deals with disk attachment (Royce Lv) * [1bc8aa6] Guest disks: Abstract vm disk functions (Royce Lv) * [7770a11] Guest disks: Choose proper bus for device (Royce Lv) * [4e7a17c] Guest disks: Update api definition and error reporting (Royce Lv) * [9c0e2a1] Guest disks: Update doc to support manage guest disks (Royce Lv) * [9328079] Return info from run_command on exception. (Christy Perez) * [781b331] write the template OS info to vm metadata (ShaoHe Feng) * [8566599] update test case to set/get user and group when VM is running (ShaoHe Feng) * [2617373] bug fix: get user and group when vm is living. (ShaoHe Feng) * [d7e7017] manually manage the metadata element (ShaoHe Feng) * [2c176c0] Add two function to set and get domain xml metadata (ShaoHe Feng) * [1f1dcc3] add method to test libvirt metadata api are available (ShaoHe Feng) * [d777a02] bug fix: call a method should be followed by "()" (ShaoHe Feng) * [06238f2] Enable encryption in vm VNC console connection (Mark Wu) * [6bf630c] Change the default tab to "Guests" (Crístian Viana) * [9e85e59] Define the default tab more clearly (Crístian Viana) * [976db87] Refactor code to trim file extension (Crístian Viana) * [37a1e1b] bug fix: Redirect 3xx responses through proxy (Aline Manera) * [a7f083c] Set default storage pool to autostart and make persistent (Christy Perez) * [6f5d0d9] Fix PEP8 in scan.py (Rodrigo Trujillo) * [5de2ca8] security: Prevent XSS attacks (Aline Manera) * [9d3bb9c] bug fix: Use secure cookies (Aline Manera) * [def7c67] security: Redirect all HTTP requests to HTTPS (Aline Manera) * [819cc2a] Fix Bug: Invalid URL at 404 Not Found Page (Hongliang Wang) * [7132f75] Changes to use 2048 bit public key for self-signed certificate (Mark Wu) * [6bac3ec] Display historical host statistical info on the host tab (Adam King) * [217858c] Host stats history: Update test cases (Aline Manera) * [9d2bf5c] Add API to return host stats history (Aline Manera) * [9b2eafb] repository: Remove full stop symbol from checkbox's label (Crístian Viana) * [087e739] repository: Make checkbox clickable (Crístian Viana) * [f2d6ff4] repository: Place checkbox to the left of its label (Crístian Viana) * [b4f84dd] Modify edit guest help info (Rodrigo Trujillo) * [4a8d603] User action menu overflows when actions with names longer than a few chars a.. (Adam King) * [1ef1561] Regenerate PO files (Adam King) * [82c1181] Update po/POTFILES.in (Adam King) * [3acf6c3] UI: Edit Guest Network Interface (Yu Xin Huo) * [19011c7] Github #329: .gitignore, spec, control.in and readme (Daniel Henrique Barboza) * [117cd5a] Github #329: changes in mockmodel, model/config and tests (Daniel Henrique Barboza) * [152d820] Github #329: Kimchid, config.py.in and server.py changes (Daniel Henrique Barboza) * [6883533] Github #329: Proxy module and template file (Daniel Henrique Barboza) * [775e630] New domain state pmsuspended (ShaoHe Feng) * [177a147] VM shutdown support in UI (ShaoHe Feng) * [d242e30] VM shutdown support in backend (ShaoHe Feng) * [44e545e] Fix error storage pool lookup usage in deep scan (Royce Lv) * [2271eeb] Clarify the meaning of an empty vm user or group list (Christy Perez) * [c01d983] VM Edit: CPU and memory (Adam King) * [b31a134] VM Edit CPU/Memory: (Backend) Changes mockmodel and tests (Rodrigo Trujillo) * [ac2c7de] VM Edit CPU/Memory: (Backend) Changes VM control and model (Rodrigo Trujillo) * [5ea7626] VM Edit CPU/Memory: (Backend) Changes API.md, API.json and i18n.py (Rodrigo Trujillo) * [ecaf9a8] Update test cases (Aline Manera) * [f04f67f] Remove unused code (Aline Manera) * [17fd157] Update users/groups verification based on new API (Aline Manera) * [fe2fd1d] Add API to list system users and groups (Aline Manera) * [5641e5e] Create a new common collection named SimpleCollection (Aline Manera) * [ce2bbbd] Bug fix: add PYTHONPATH for contrib/check_i18n.py (ShaoHe Feng) * [5c2013d] packaging: ship kimchi with plugins/__init__.py (Zhou Zheng Sheng) * [361cae4] Display version/build number in UI (Adam King) * [a67fe54] Host Tab: Add Widths for Repository Grid Columns (Hongliang Wang) * [88c190a] Issue#364: UI - Column Resizing Function Broken in Host Tab (Hongliang Wang) * [257d0ff] config version API support in backend. (ShaoHe Feng) * [698b101] config version API support: add a method to get kimchi version (ShaoHe Feng) * [4c7c402] Add/remove users and groups to VMs (Aline Manera) * [ca0bfd9] Return users and groups when fetching VM info (Aline Manera) * [0a38dc9] Add functions to check if a user/group exists (Aline Manera) * [021d4d1] Use proper term "user name" instead of "user id" (Aline Manera) * [0348f4a] Override only the updated "User" methods in "patch_auth" (Crístian Viana) * [548f894] Set virt_use_nfs when NFS pool is added. (Christy Perez) * [767a34e] Issue #363: Fix data/information consistence in edit template window (Rodrigo Trujillo) * [16659a5] Issue #363: Add new rest api function - getStoragePoolVolume (Rodrigo Trujillo) * [4266218] add a method to check the i18n strings are obsolete (ShaoHe Feng) * [89411f9] remove obsolete i18n strings which are no longer in use (ShaoHe Feng) * [3b11219] add a make check-local command to verify the i18n string formatting (ShaoHe Feng) * [04d2d73] Choose available address for ide disk (Royce Lv) * [5c487da] add confirmation for reset a VM (ShaoHe Feng) * [074f7c5] reset vm in UI (ShaoHe Feng) * [86f1afa] reset VM in backend. (ShaoHe Feng) * [6fe5997] reset VM: update API.md (ShaoHe Feng) * [9f626cb] Bug fix #357 - Error when creating template from ISO (Ramon Medeiros) * [d8617eb] Fix backend error when creating multiple templates (Rodrigo Trujillo) * [767e486] Fix typo while processing request data (Aline Manera) * [7c3bb7b] Fix kimchi vlan tagged bridge name (Mark Wu) * [3bf0173] error when editing repository entry with no mirrorlist. (Paulo Vital) * [de1d0f6] kimchi.disks: Ignore unsupported partition table (Zhou Zheng Sheng) * [68d86c5] Fix get_storageservers API and UI retrieval of storage servers. (Christy Perez) * [e19383c] help pages: Set default index file to /help URI (Aline Manera) * [23042dd] help pages: Update .gitignore file (Aline Manera) * [65051df] help pages: Adjust css url (Aline Manera) * [61d619e] help pages: Remove former .dita files (Aline Manera) * [a8f8abd] Update build process to generate html pages for each help subdir (Aline Manera) * [4e548cb] Replicate help pages for pt_BR and zh_CN (Aline Manera) * [aab8764] Bug fix #360: Support i686 architecture (Ramon Medeiros) * [42f7771] Fix volume not found error message (Rodrigo Trujillo) * [4a34cbf] Fix debugreports download issue (Mark Wu) * [c7e4707] objectstore: support sorting by a key in get_list() (Zhou Zheng Sheng) * [58efd8f] add confirmation for power off a VM (ShaoHe Feng) * [250565d] change the stop to power off for VM in UI (ShaoHe Feng) * [82fa8d1] change the stop to power off for VM in backend (ShaoHe Feng) * [70dc729] Try to activate physical interface when create a network on it (Mark Wu) * [6e19ac4] Software Update: Make Update Progress Area Collapsible (Hongliang Wang) * [c012f81] Issue #365: Preventing duplicate Bridged VLAN tagged network. (Paulo Vital) * [11b2c7f] improve Chinese translation (ShaoHe Feng) * [3a2ed85] Make use of the new forms handling capabilities (Adam King) * [eadacde] Extend jQuery form (Adam King) * [229710a] Extend base classes to support form processing (Adam King) * [0e555f5] Fix hardcoded storage bus assignment in vmstorage (Rodrigo Trujillo) * [58c9025] kimchi.exception: Properly Decode All Kinds of Exception Arguments (Zhou Zheng Sheng) * [25bd8e0] Sort device paths shown when creating a logical storage pool (Rodrigo Trujillo) * [02807f8] Add template clone support (Adam King) * [15b0e43] Fix pep8: add files to whitelist of Makefile.am (Rodrigo Trujillo) * [5252d7a] Fix pep8 issues in src/kimchi/objectstore.py (Rodrigo Trujillo) * [75542bd] Fix pep8 in src/kimchi/template.py (Rodrigo Trujillo) * [b81f7bc] Fix pep8 in src/kimchi/vmtemplate.py (Rodrigo Trujillo) * [f2c436b] Plugins UI: Correctly Load Plugin Tabs (Zhou Zheng Sheng) * [e057827] Fix 'disk full' issue: Fix vms/screenshot db store/delete error handling (Rodrigo Trujillo) * [42a9072] Fix 'disk full' issue: Fix storagepool and asynctasks error handling (Rodrigo Trujillo) * [fa0b991] Fix 'disk full' issue: Fix storage volume error handling (Rodrigo Trujillo) * [b787cba] Fix 'disk full' issue: Fix Templates db store/delete error handling (Rodrigo Trujillo) * [dc2174e] Fix 'disk full' issue: Change objectstore exception handling (Rodrigo Trujillo) * [e851d99] Add the command to run_command error and debug logging (Christy Perez) * [833125c] bug fix: we should pass str to cherrpy HTTPError (ShaoHe Feng) * [f5c517a] Issue #343 & #353: Improve & Correct UI Init Logic Flow (Hongliang Wang) * [bd80b70] AsyncTask: Propagate cherrypy request information to worker threads (Zhou Zheng Sheng) * [0ea1f4b] UI: change some code of storage add page (ShaoHe Feng) * [d5fd304] Fix non persistent network handling (mockmodel/tests) (Rodrigo Trujillo) * [f3f55a8] Fix non persistent network handling (frontend) (Rodrigo Trujillo) * [cc87c6a] Fix non persistent network handling (backend) (Rodrigo Trujillo) #### [kimchi-1.2.0] #### * [335ee71] Update Changelog for 1.2 release (Aline Manera) * [015ebb3] Remove LUN assignment in VM (Aline Manera) * [103e87b] Update po and pot files for 1.2 release (Aline Manera) * [002ec76] Translate pt_BR.po file (Ramon Medeiros) * [35c3000] Chinese translation for release 1.2 (ShaoHe Feng) * [1add01e] bug fix: fix the string format %(pool). (ShaoHe Feng) * [58da428] Add error handling for repo management (Adam King) * [2e4a46a] Logical Storage Pool: Detect and Enumerate Multipath Block Devices (Zhou Zheng Sheng) * [179bf14] validate the volume parameter when the pool of template is iscsi or scsi (ShaoHe Feng) * [31fa6b8] Fix swupdate listing (Royce Lv) * [9259c90] error message fix. (ShaoHe Feng) * [b056903] Fix a typo. (Leonardo Garcia) * [b31e125] bug fix: fix the string format. (ShaoHe Feng) * [429d370] Add lock in swupdate (Royce Lv) * [a144b90] fix lock for apt package manager (Royce Lv) * [1e3e121] Properly display YUM exception (Aline Manera) * [074e265] UI: template edit page support scsi lun (ShaoHe Feng) * [1060f98] create a VM from an scsi pool template (ShaoHe Feng) * [81bc75e] create a VM from an iscsi pool template. (ShaoHe Feng) * [0671de3] generate a iscsi volume disk for a guest (ShaoHe Feng) * [6ac343a] add a method to get iscsi storage pool auth information. (ShaoHe Feng) * [f4db0d6] Help for scsi fibre channel (Kersten Richter) * [e1e7baa] Fibre Channel SCSI Storage Pool UI (Yu Xin Huo) * [5f43812] Added help for repositories (Kersten Richter) * [5b14926] Repository Management - Integrate into Host Tab (Hongliang Wang) * [7999102] Repository Management - Edit Repository Support (Hongliang Wang) * [55c426b] Repository Management - Add Repository Support (Hongliang Wang) * [057f2d4] Repository Management - Add API Support (Hongliang Wang) * [66b1573] Repository Management - Add i18n Strings (Hongliang Wang) * [f18b0bc] Update grid widget to populate fields from deeply nested objects (Adam King) * [afea547] Update form.serializeObject method to handle deep object serialization (Adam King) * [0d51a2f] Adds 'in_use' info to API.md (Rodrigo Trujillo) * [622781d] Template: Check if the host supports Spice (Zhou Zheng Sheng) * [a8f9f16] but fix: show the content of combobox and filterselect in storage add page (ShaoHe Feng) * [24cfe69] Bug fix: specify the class attribute when change pool state dot. (ShaoHe Feng) * [281d35c] Optimize return code check. (Leonardo Garcia) * [ddd588d] Show error message from debug report generation async task (Rodrigo Trujillo) * [3d47c5c] bug fix: Lock YUM operations (Aline Manera) * [ace80fe] bug fix: Display update progress on real time (Aline Manera) * [413e36b] bug fix: Allow user specifies the repository name when adding a new YUM repo (Aline Manera) * [ad283ee] bug fix: Instantiate the apt-get manager when update the apt-get packages list (Aline Manera) * [e94903a] Issue#349: Software Update Grid Keeps Loading when Error Returns (Hongliang Wang) * [81c16b4] run pyflakes when make check (ShaoHe Feng) * [f4cbe91] add template_delete to rollback after create a template (ShaoHe Feng) * [2fa81bf] make pyflakes happly, remove unused availables (ShaoHe Feng) * [8b64eb1] make pyflakes happly, remove the unused import module (ShaoHe Feng) * [be5c57d] Remove debug report's file path from UI (Mark Wu) * [4fa40e1] partitions: Fix when disk does not have extended partition (Royce Lv) * [c177cae] bug fix: instantiate the Yum manager when update the yum packages list (ShaoHe Feng) * [4a43a7c] Issue#352: Debug Report Section NOT Hidden for Non-root User (Hongliang Wang) * [50a373a] bug fix: Lock yum/apt operations (Aline Manera) * [bc72f1c] Update test cases to reflect the repositories changes (Aline Manera) * [d369c91] bug fix: Do not store internal repository information (Aline Manera) * [8536141] bug fix: Let package manager tool create the repository ID (Aline Manera) * [ca77c50] bug fix: Sort repositories (Aline Manera) * [5e6300e] bug fix: Raise exception comming from backend (Aline Manera) * [384dbec] Update messages used in the repositories management feature (Aline Manera) * [340e4f5] mockmodel: Move specific repository data under 'config' (Aline Manera) * [7d5fad5] bug fix: Reorganize repository information (Aline Manera) * [81e5440] bug fix: Expose repository management tool name (Aline Manera) * [9b40f58] VLAN: Do not allow bridge to be the trunk device (Zhou Zheng Sheng) * [24c4319] Fix iso streaming functions and feature tests (Rodrigo Trujillo) * [c44b238] sudo: run sudo with a pseudo controlling terminal (Zhou Zheng Sheng) * [e609efa] Display the error code when displaying error msgs (Crístian Viana) * [f39dfe4] Apply Kimchi standard error message (Crístian Viana) * [cb1ece8] Do not show success messages (Crístian Viana) * [6a45ad0] Doc: add work around to handle NFS root squash problem (Royce Lv) * [13819ab] Fix issue 348: NFS pool creation times out (Christy Perez) * [6d6c816] Software Update: Enable "Update All" Button when Task Fails (Hongliang Wang) * [6888a72] Changes to help (Kersten Richter) * [38d8f1a] Remove bridge and vlan interface unconditionally on removing vlan network (Mark Wu) * [01c4035] Fix Bug - Text Overlapped in Template Add Window (Hongliang Wang) * [9c2b766] Fix multiple pep8 (Royce Lv) * [a37e0bd] Grid Loading Mask - Some Elements are Missing (Hongliang Wang) * [58ab016] Skip 'screendump' for vms no video device configured (Mark Wu) * [cfd29f8] Controller: Improve Kimchi Specific Exception Reporting (Zhou Zheng Sheng) * [4523b3e] Grid widget presently interprets displays null values as null strings (Adam King) * [22dc2af] mockmodel: Reset packages after updating system (Aline Manera) * [e6806e4] UI: Disable stop/undefine buttons when network is in use (Aline Manera) * [b590cd5] Do not allow user disable/delete a network used by VM or template (Aline Manera) * [31f7bbf] Software Update Support in Host Tab (Hongliang Wang) * [95bd616] Software Update - APIs in kimchi.api.js (Hongliang Wang) * [3182653] Software Update - i18n Translation Strings (Hongliang Wang) * [4f2b234] Supplement to [PATCH v6 0/3] UI: Software Update Support (Adam King) * [e9ab744] bug fix: encode the args in KimchiException when is is unicode. (ShaoHe Feng) * [8a6db10] Grid Enhancement - Show Message when Loading Data (Hongliang Wang) * [c700997] Correct the Repositories parameter name of is_mirror (Adam King) * [9a54667] Start up Kimchi even if no repo management tool was identified (Aline Manera) * [aee1318] Expose repo_mngt_tool to /config/capabilities (Aline Manera) * [0b811f6] bug fix: Identify repository management tool based on available system tools (Aline Manera) * [e3338e2] bug fix: Identify update tool based on available system tools (Aline Manera) * [96a0235] Changed xsl file to include stylesheet (Kersten Richter) * [acde6c7] Added a style sheet to make the html look pretty (Kersten Richter) * [35033c6] Commit changes to templates and storage.dita files (Kersten Richter) * [34cd66f] Added help for host and network tab. (Kersten Richter) * [681ac87] Grid Enhancement - "title" Attribute for Long Values (Hongliang Wang) * [5b921e0] ISO Scan: Use volume set id instead of volume id for some wrong images. (Mark Wu) * [e7c6426] Issue #302: let 'create' attr of networks model to create default network (ShaoHe Feng) * [42008ee] add a new function to get an available network address (ShaoHe Feng) * [39a2ba8] move _default_network_check from top model to networks model (ShaoHe Feng) * [3df47fe] Update guest action menu (Adam King) * [626081f] Pass ajaxError information on to original requester on ajaxError event (Adam King) * [b113780] Issue 292 Logical Storage Pool Returning "extended" Partitions as Possible P.. (Zhou Zheng Sheng) * [5ed36d6] bug fix: remove the hard code of disk_path (ShaoHe Feng) * [378eb45] probe iso permission: update test case (ShaoHe Feng) * [84a28fb] Don't allow templates to be created with ISOs that won't be usable. (ShaoHe Feng) * [af51f27] qemu user tests: probe the username of qemu process started by libvirt (ShaoHe Feng) * [baed491] add a method to probe the permission as qemu user (ShaoHe Feng) * [de0400b] Attach/Replace/Detach a CDROM to/in/from a VM (Hongliang Wang) * [474e774] Add/Edit CDROM Support (Hongliang Wang) * [505409f] Add i18n Variables for CDROM-related Function (Hongliang Wang) * [f392c6d] Add CDROM-related APIs (Hongliang Wang) * [9cfb638] kimchi.message - Enhancement (Hongliang Wang) * [23b5850] Adjust CSS for Window (Hongliang Wang) * [87a6eec] Issue 294 The auto logout leaves action menu on page - update JS (Adam King) * [28419d8] Issue 294 The auto logout leaves action menu on page - add classes (Adam King) * [f8ac146] Fix formatting of the requestJSON function (Adam King) * [9f91334] pep8 clean for osinfo.py (ShaoHe Feng) * [82a743b] bug fix: add an icon distros list. (ShaoHe Feng) * [8c3ce5f] Build help index page only once (Crístian Viana) * [2c7dbf8] fix: Build new DITA pages when running "make" (Crístian Viana) * [11e871c] Multiple pep8 fixes (Royce Lv) * [2ab54c1] Add volume ref_cnt: Update test (Royce Lv) * [3f0e775] Add volume ref_cnt: Add model and mockmodel implementation (Royce Lv) * [757a254] Add volume ref_cnt: Update controller and json schema (Royce Lv) * [d55e72a] Add volume ref_cnt: update api.md (Royce Lv) * [bb89241] Fix vm disk path when it does not have source element (Royce Lv) * [86a9b4d] Export list vms functionality (Royce Lv) * [dfccd65] Allocate enough space for logical volume (Royce Lv) * [a815850] Window Widget Enhancement - Allow onClose Listener (Hongliang Wang) * [834e48b] Bug fix: Kimchi could not start guest with iscsi lun assigned as disk (Rodrigo Trujillo) * [c092436] issue #200: Rebuild .mo files when running "make" (Crístian Viana) * [57f9f9f] Do not show a success msg when creating a template (Crístian Viana) * [7dc503d] Window - Correct Footer Height (Hongliang Wang) * [0c840f0] logical pool: Fix logical pool target path (Royce Lv) * [75f31dc] Fix storage volume format on logical pool for vm (Royce Lv) * [3fdbb1c] Use a pool of threads to valid all remote ISOs in parallel (Aline Manera) * [456018a] bug fix: "sudo: sorry, you must have a tty to run sudo". (Paulo Vital) * [389b13c] Update distros JSON files to always point to a valid URL (Aline Manera) * [7b69dfa] issue #301: Add a loading message while listing default remote ISOs (Aline Manera) * [db72242] issue #301: Only list remote ISOs with valid URL (Aline Manera) * [33a9257] Increase memory size for vm template on ppc platform (Mark Wu) * [5747b58] Fix issue #339: Change mock and add test to check persistent variable (Rodrigo Trujillo) * [88bb4a7] Fix issue #339: Changes UI to handle deactivation of non-persistent pools (Rodrigo Trujillo) * [596ddb1] Fix issue #339: Enable backend to handle not persistent pools (Rodrigo Trujillo) * [f11beaa] Fix rollback order (Rodrigo Trujillo) * [6d234f1] bug fix: Set default flags for virDomain.state() function (Aline Manera) * [00a60b3] Issue #222: add python-xml to suse require list (ShaoHe Feng) * [34a6073] storage volume: fix xml parsing of logical volume format type (Zhou Zheng Sheng) * [4be19f9] Support ppc64 isos in Templates: Fix test cases (Rodrigo Trujillo) * [6a81c0e] Support ppc64 isos in Templates: Filter remote isos and change UI (Rodrigo Trujillo) * [01d338b] Support ppc64 isos in Templates: Add arch and urls to distro jsons (Rodrigo Trujillo) * [0ef900c] issue #330: Make sure exception argument is a string to convert it to unicode (Aline Manera) * [e9a5071] issue #312: Check volume group exists while creating a logical pool (Aline Manera) * [186a2ad] Refreshing an inactive pool causes exception (Shu Ming) * [853908a] session expire: update test case (ShaoHe Feng) * [2907055] UI: set kimchi robot header for some request. (ShaoHe Feng) * [ad459df] auth enhancement: expire the session when the request access periodically (ShaoHe Feng) * [fa350f6] add timeout for sessions (ShaoHe Feng) * [eb37a50] Issue #333: do not encode error.html when the cherrpy version less than '3.2.. (ShaoHe Feng) * [707aee0] bug fix: setup disks to use cache=none to support live migration. (Paulo Vital) * [6779b95] While trying to extend a logical pool I got the following error message: (Aline Manera) * [008e76f] template integrity verification: update test case to verify storagepool (ShaoHe Feng) * [2ec01d5] template integrity verification: verify storagepool in backend (ShaoHe Feng) * [ae3b81b] template integrity verification: verify storagepool, update API.md (ShaoHe Feng) * [5f28f72] Github bug #307: storage pool type list - html and string changes (Daniel Henrique Barboza) * [a7ea3d2] Github bug #307: add storage pool type list - JS changes (Daniel Henrique Barboza) * [d977d18] remove unused InvalidOperation instance (ShaoHe Feng) * [7869c19] Add test case for kimchi server configuration. (Mark Wu) * [e65d00a] Add static directory configurations for plugin's ui (Mark Wu) * [668f522] UI: Grid Widget - Enable/Disable Row Selection (Hongliang Wang) * [e9f67dc] Bug Fix #282: Handle toggleNetwork error returns (Rodrigo Trujillo) * [41ac09c] Bug Fix #282: Disable Start/Stop network buttons while wait backend lag (Rodrigo Trujillo) * [ee36b1f] Clear pep8 failure in make check (Royce Lv) * [4175f76] Prevent volume create and delete for certain pool types (Royce Lv) * [20568e2] Fix vm creation storage rollback clean (Royce Lv) * [729d15b] UI: template support spice, update po (ShaoHe Feng) * [6a17215] UI: template support spice (ShaoHe Feng) * [a9d94a7] Fix debug report UI: Error handling and line selection (Rodrigo Trujillo) * [e1ed6cd] issue #66: Auto generate template name in backend when none is provided (Aline Manera) * [bd47f5a] bug fix: Only check for ISO images in active pools (Aline Manera) * [74614bd] bug fix: Do not probe ISO file while checking template integrity (Aline Manera) * [be2122d] vmtemplate: Remove useless imports (Aline Manera) * [276c13a] Fix typo on KCHAPI6005E message (Aline Manera) * [c835175] bug fix: Enable NFS path field when a NFS server is provided (Aline Manera) * [31c4398] Fix software update action into Host resource (Paulo Vital) * [793e2c6] Fix test_osinfo.py to use new modern distro version dict. (Paulo Vital) * [1a05317] Fix VM's network model template for Power systems. (Paulo Vital) * [9abfad4] kimchi.control.utils: fix request parsing in generate_action_handler() (Zhou Zheng Sheng) * [5d82241] Issue 299 Inactive storage pools are listed while editing template (Adam King) * [279a710] Can not create a VM from a template with disks['volume'] parameters. #181 (Shu Ming) * [3100c0c] Fix Kimchi vm tests according to new messages sent from backend (Rodrigo Trujillo) * [5e902bf] Delete unsed _vm_exists funtion (Rodrigo Trujillo) * [9178089] Fix VM delete error message handling (UI/Backend) (Rodrigo Trujillo) * [d58edad] Fix VM reset (UI) error messages hnadling (Rodrigo Trujillo) * [82b80e3] Fix VM stop error messages handling (backend/UI) (Rodrigo Trujillo) * [96f5457] Fix vm start UI error return message (Rodrigo Trujillo) * [f8c9c60] Fix Add Network window (Rodrigo Trujillo) * [eb8347e] Add another way to download the debugreport file in the test (Shu Ming) * [632c3ca] Have a meaningful description for the exception test #81 (Shu Ming) * [7ee1b09] bug fix: check all Red Hat distributions for yum package management (ShaoHe Feng) * [8931da1] Set default combo box style to storage pool type list (Aline Manera) * [c4c093e] issue #242: Do not allow user deactivate/delete storage pool used by a templ.. (Aline Manera) * [26631c0] bug fix: Make URI parameter is not None before encoding it (Aline Manera) * [d58f453] Authors cleanup (Paulo Vital) * [e3ea028] run_command: log error messages using higher log level when return code is n.. (Zhou Zheng Sheng) * [c6e8212] Fix screenshots and debug reports paths. (Leonardo Garcia) * [3514d3b] Fix tests: restore the monkey patch after testing Paths (Mark Wu) * [ca04f30] Issue # 303 The password of iSCSI Authentication should be masked (Adam King) * [e5cf383] issue #325: Use RamSession instead of FileSession (Aline Manera) * [e10177e] Github bug #327: NFS pool workaround: model changes (Daniel Henrique Barboza) * [5c38855] Github bug #327: NFS pool workaround: timeout adjustments (Daniel Henrique Barboza) * [5076c7d] Github bug #327: NFS pool workaround: i18n changes (Daniel Henrique Barboza) * [948445f] Packaging: removed start of kimchid from RPM and DEB files (Paulo Vital) * [d83510c] bug fix: Properly display missing parameter (Aline Manera) * [19f6fcf] Clear out the guests list properly using jQuery (Adam King) * [baff478] issue #316: Only verify if path starts with '/' (Aline Manera) * [ad1ecbc] Add help to user menu (Adam King) * [346d50d] Fix debug report naming problem (UI) (Rodrigo Trujillo) * [f1d433b] Fix debug report naming problem (backend) (Rodrigo Trujillo) * [cde51be] Github bug #326: run_command: killing all children processes (Daniel Henrique Barboza) * [0a34570] allow user to create a storagepool with name in his local language (ShaoHe Feng) * [c580e08] Issue #243: start/stop/display a VM whose name with "?" (ShaoHe Feng) * [7cb61c0] Clear unused reference in vmstorages of 'kargs' (Royce Lv) * [667a6b2] Issue #289: catch the libvirtError when failed to start a vm (ShaoHe Feng) * [c35c318] Fix Kimchi UI issues on IE11 (Adam King) * [5a044d9] Fix typo on API.json and add missing error messages (Aline Manera) * [68988c3] cdrom: update model test for media update (Royce Lv) * [cbab49f] cdrom: fix cdrom change media (Royce Lv) * [a319343] Undefined lable in template buttons. (adriano) * [30c383a] Issue #315: edit/delete templates that contains slashes in their names (ShaoHe Feng) * [243dd85] Remove tabs in ui/pages/storagepool-add.html.tmpl (Aline Manera) * [0af44e3] Change guests tab to update the VM List by DOM manipulation (Adam King) * [8e7ef05] Update the guest.html.tmpl to use the new circleGauge widget (Adam King) * [6db93c8] Create a reusable jQuery circleGauge widget (Adam King) * [b47595d] Update (mock)model to generate proper JSON (Adam King) * [3be6341] PEP8 for mockmodel.py (Adam King) * [977e772] Fix PEP8 in test files (Aline Manera) * [92d04e3] Fix ui/js/Makefile.am (Aline Manera) * [09366f0] Implement integrity verification: update test case (ShaoHe Feng) * [9988128] Implement integrity verification: verify template integrity in backend (ShaoHe Feng) * [ef8222b] add a new method to get iso info for VMTemplate class (ShaoHe Feng) * [f8bdc13] Implement integrity verification: verify template integrity, update API.md (ShaoHe Feng) * [8c0ad96] issue #324 Improve error messages of creating a storage pool named "kimchi_i.. (Mark Wu) * [2e93bbd] Use $(wildcard) to list files in Makefile (Aline Manera) * [c0ffb52] Fix duplicate dev names in host with multipath storage (Rodrigo Trujillo) * [898f3bd] Return 403 Forbidden when user does not have permission to access kimchi (Aline Manera) * [88b01a0] Removing extra word from kimchi description (Christy Perez) * [a4a64f9] add libxml2 to BuildRequires list (ShaoHe Feng) * [af31ad1] Host's repositories management: Update error exception messages. (Paulo Vital) * [1057a2f] Host's repositories management: Update test-cases. (Paulo Vital) * [c33ab87] Host's repositories management: Update Makefile (Paulo Vital) * [f27bcdb] Host's repositories management: Update backend. (Paulo Vital) * [fcb7c68] Host's repositories management: Update REST API (Paulo Vital) * [b7b2ab3] Host's repositories management: Update API.md (Paulo Vital) * [5eb9bd8] Block access for non-root users (Aline Manera) * [23df447] Add one more case to network tests (Ramon Medeiros) * [10a2ed4] Bug fix #318 Kimchi fails creating new network (Ramon Medeiros) * [4091825] bug fix: Properly check if there running vms before rebooting system (Aline Manera) * [ba7dea2] Bug fix: methods signature in storagetargets.py (Daniel Henrique Barboza) * [7e4588e] Add software update action to Host resource (Aline Manera) * [a695185] Remove unused vms reference in VMModel (Royce Lv) * [c53b3ea] Fix encode and decode in storagevolumes.py (Royce Lv) * [391befb] ui: Add tooltip when hovering long names (Crístian Viana) * [91bab78] doc: Generate index.html to join all help pages (Aline Manera) * [0b7d861] bug fix: Package doc html files into deb package (Aline Manera) * [400f3d8] Setup VM's input and output template for Power systems. (Paulo Vital) * [13d610b] Fix exception for model test (Royce Lv) * [db954e9] Implement integrity verification: don't disable network used by guest (ShaoHe Feng) * [ff94a34] Fix Software Update rebase issue. (Paulo Vital) * [f5506b9] clone template: update test case (ShaoHe Feng) * [31dff43] clone template: update model and mockmodel (ShaoHe Feng) * [a4be3c0] clone template: update controller (ShaoHe Feng) * [0f0c991] Enhance generate_action_handler to redirect a new resource (ShaoHe Feng) * [50f8272] clone template: update API.md (ShaoHe Feng) * [a823e20] Bug fix #309 - network: Unable to create vlan tagged on Ubuntu (Ramon Medeiros) * [f5502f7] doc: Ignore the generated files (Crístian Viana) * [1b3310d] doc: Export the help pages to cherrypy (Crístian Viana) * [5257e69] doc: Add help files to dist packages (Crístian Viana) * [31d9ccf] doc: Add DITA help pages (Crístian Viana) * [5c80111] Enhance UrlSubNode decorator and kimchiauth tool to check for sudo rights. (Leonardo Garcia) * [1ca8c6f] Find out user groups and sudo status during login. (Leonardo Garcia) * [cd65d8f] Code cleanup. (Leonardo Garcia) * [382105c] CDROM Management: changes in tests/test_model.py (Daniel Henrique Barboza) * [68f8784] CDROM Management: Guest vm storage devices mockmodel and rest api test cases (Rodrigo Trujillo) * [9ce2615] CDROM Management: Devices management model implementation (Rodrigo Trujillo) * [68701c2] CDROM Management: Update controller and API.json for guest storages (Rodrigo Trujillo) * [56a6d9a] CDROM Management: API.md and externalized error messages (Aline Manera) * [cbf7a89] bug fix: display kimchi icon instead of cherrypy icon (ShaoHe Feng) * [82f1b82] Setup VM's boot order. (Paulo Vital) * [c58465d] host update: Expose update tool (Aline Manera) * [dae3830] host update: Update po files (Aline Manera) * [d23ed36] Host's software update: Update test cases. (Paulo Vital) * [002cb04] Host's software update: Update Makefile (Paulo Vital) * [216db4f] Host's software update: Update backend. (Paulo Vital) * [c29a36f] Host's software update: Update REST API (Paulo Vital) * [3714aae] Host's software update: Update API.md (Paulo Vital) * [8e6fc17] bug fix: fix python syntax error (ShaoHe Feng) * [a9c80ac] bug fix: make install miss ifaces.py (ShaoHe Feng) * [bfb5608] Fix host debug report for Fedora 20 (Rodrigo Trujillo) * [c74e1db] Storagepool SCSI/FC: Modifies mockmodel and implements tests for FC pool (Rodrigo Trujillo) * [7c0fc12] Storagepool SCSI/FC: Backend implementation (Rodrigo Trujillo) * [ecb4d6c] Storagepool SCSI/FC: API.md entries related to host pci devices (Rodrigo Trujillo) * [e4d08f3] Storagepool SCSI/FC: Implement node devices API backend (Rodrigo Trujillo) * [57ece7a] Add mailing list information. (Leonardo Garcia) * [3907474] Limit README.md to 80 columns. (Leonardo Garcia) * [79abe0b] Add hypervisor information on README.md. (Leonardo Garcia) * [a3f157e] refactor exception: Update all po files (Aline Manera) * [0ee16b4] refactor exception: Update UI references (Aline Manera) * [ce3953b] refactor exception: Update gen-pot script to get messages from i18n.py (Aline Manera) * [f137c23] refactor exception: Update all exceptions (Aline Manera) * [8d19059] refator exception: Update control to raise the exception message (Aline Manera) * [715152c] refactor exception: Set error messages for jsonschema validation (Aline Manera) * [26020a5] refactor exception: Add messages to be translated on backend (Aline Manera) * [e13997a] refactor exception: Create a common Exception to translate error messages (Aline Manera) * [b94d36c] Fix path of plugins dir (Mark Wu) * [41ba026] pass params to create method of all Collections. (ShaoHe Feng) * [9644c05] Fix wrong "Failed to list guest" message (Rodrigo Trujillo) * [2f6ac7b] Add disks to LVM pool: API.json changes (Daniel Henrique Barboza) * [61945fd] Add disks to LVM pool: mockmodel changes (Daniel Henrique Barboza) * [0a54dab] Add disks to LVM pool: API.md changes (Daniel Henrique Barboza) * [b500a90] Add disks to LVM pool: control and model changes (Daniel Henrique Barboza) * [d7458e7] Fix missing report-add html page in rpm (Rodrigo Trujillo) * [db829ac] Fix controller base code: Update function is not using model_args (Rodrigo Trujillo) * [2fed3f5] change the vm name in test case (ShaoHe Feng) * [0adea83] update test case for updating vm with unicode name (ShaoHe Feng) * [60f3da3] bug fix: failed to update vm with unicode name (ShaoHe Feng) * [3f5cdd2] update test case for storage pool support unicode (ShaoHe Feng) * [4f3d489] Firewall: Adding WebSocket port in firewall rules (Paulo Vital) * [8cac63d] Storage pool support unicode correctly (ShaoHe Feng) * [cc11627] bug fix: Set full path to guest page file in guest tab (Aline Manera) * [9f33184] bug fix: Fix shallow scan broken after model refactoring (Aline Manera) * [b9c0594] Make sure ISO files have read permission while starting VM (Aline Manera) * [461452a] Remove kvmusertests.py (Aline Manera) * [0e25ad2] Add a method to fix read permission on ISO files (ShaoHe Feng) * [0368afa] Avoid useless libvirt error log produced by featuretests (apporc) * [f84b4d5] Packaging: add the basemodel.py to src/kimchi/Makefile.am (Paulo Vital) * [02d94f5] Fix get vms list function name (Rodrigo Trujillo) * [0d7d89c] Add test cases for BaseModel (Mark Wu) * [4a5ede7] Break the 'sample' plugin's monolithic model into several smaller ones (Zhou Zheng Sheng) * [78443ae] refactor model: Update makefile and specs files (Aline Manera) * [a0a4dc0] Delete former model.py and rename model_ to model (Aline Manera) * [17d1014] Update mockmodel imports (Aline Manera) * [d0ff3f9] Update tests to use the new model (Aline Manera) * [dd2b2f4] Update server to use the new model (Aline Manera) * [a87ab93] refactor model: Create a separated model for host resource (Aline Manera) * [8a93e68] refactor model: Create a separated model for vm interface resource (Aline Manera) * [5e34a52] refactor model: Create a separated model for vm resource (Aline Manera) * [41f0cc7] refactor model: Create a separated model for template resource (Aline Manera) * [977c267] refactor model: Create a separated model for storage target resource (Aline Manera) * [e67c3be] refactor model: Create a separated model for storage server resource (Aline Manera) * [b1d2c63] refactor model: Create a separated model for storage volume resource (Aline Manera) * [f7001ca] refactor model: Create a separated model for storage pool resource (Aline Manera) * [8d004e1] refactor model: Create a separated model for interface resource (Aline Manera) * [3bf22b3] refactor model: Create a separated model for network resource (Aline Manera) * [39d1b7b] refactor model: Create a separated model for config resource (Aline Manera) * [9c38e1f] refactor model: Create a separated model for debug report resource (Aline Manera) * [e79ebaa] refactor model: Create a separated model for plugins resource (Aline Manera) * [c08c091] refactor model: Create a separated model for task resource (Aline Manera) * [a22d932] Create a model to join all model resources implementation (Aline Manera) * [4b00cab] refactor model: Create a common model builder (Aline Manera) * [f96d5e5] refactor model: Move StoragePooldef from model to libvirtstoragepools.py (Aline Manera) * [e2008c5] refactor model: Separate libvirtconnection from model.py (Aline Manera) * [b77935b] Allow plugin use kimchi's ui handler (Mark Wu) * [44be0d2] Add test cases for paths generation code (Mark Wu) * [8bc4dde] Reorganize the kimchi's paths gereneration code (Mark Wu) * [fce2030] Move resource config's info fetching to model level (Mark Wu) * [2ab9785] CSS: Change all CSS files indentation to 4 spaces (Crístian Viana) * [ab999de] CSS: Do not allow lines longer than 79 characters (Crístian Viana) * [84df5f7] HTML: Make the form element's labels clickable (Crístian Viana) * [29e17e4] Update README to direct users to the oVirt mailing list (Adam King) * [9057ae1] Use Autoconf macros AC_PROG_MKDIR_P and MKDIR_P (ShaoHe Feng) * [21f099f] GET /plugins failed, fix it (ShaoHe Feng) * [b1bf105] get vms list by listAllDomains (ShaoHe Feng) * [6bcbb3f] Make guests template handling more robust like host template handling (Adam King) * [fdbd2a8] Remove the unnecessary 'exposed' (Mark Wu) * [de892cb] bug fix: Expose /storageservers (Aline Manera) * [a6a4999] bug fix: remove decode for resouce ident when use cherrypy's default dispatc.. (ShaoHe Feng) * [b67aa7b] fix: Add missing license copyright to css files (Aline Manera) * [8989283] PEP8 cleanup and bug fix for src/kimchi/utils.py (Mark Wu) * [7410a58] support create/delete VMIface: update testcase (ShaoHe Feng) * [9072f67] support create/delete VMIface: update API.json (ShaoHe Feng) * [4cf2b6e] support create/delete VMIface: update mockmodel (ShaoHe Feng) * [c66c675] support create/delete VMIface: update model (ShaoHe Feng) * [f4942a0] bug fix: guest iface does not return model if no model is found (ShaoHe Feng) * [dd5bf4a] bug fix: Use cherrypy host to run feature tests instead of localhost (Aline Manera) * [6ded2ab] VM supports interfaces: update testcase (ShaoHe Feng) * [e2e5aab] VM supports interfaces: update mockmodel (ShaoHe Feng) * [d90f38e] VM supports interfaces: update controller (ShaoHe Feng) * [5825943] VM supports interfaces: update model (ShaoHe Feng) * [398a171] VM supports interfaces: update API (ShaoHe Feng) * [304217b] Add a control.vm module (ShaoHe Feng) * [b4fe1dc] bug fix: test case can not find plugin, fix it (ShaoHe Feng) * [b0aed86] improve controller: set authentication automatically (ShaoHe Feng) * [18b68ea] improve controller: Root loads collections/resouces automatically (ShaoHe Feng) * [5b82bdf] improve controller: tag the collections/resouces of root with @UrlSubNode (ShaoHe Feng) * [c7d2856] improve controller: add a method to load root sub collections/resouces autom.. (ShaoHe Feng) * [f68a3bc] add gettext to package require list (ShaoHe Feng) * [7cff21e] Modify bug in spice UI (zhoumeina) * [2ef94b9] Add nfs server and target UI in create storage pool (zhoumeina) * [504213f] Fix libvirt nfs target probe problem (Royce Lv) * [881361f] Add showmount function and feature test for libvirt target probe (Royce Lv) * [e024dd3] storage target: Add model support (Royce Lv) * [d60c4b8] storage target: Update controller and json schema (Royce Lv) * [4be609a] storage target: Update API.md (Royce Lv) * [2e1657e] storage server: Update model and mockmodel (Royce Lv) * [e976b78] storage server: update controller.py (Royce Lv) * [545ec78] Storage server: Update API.md (Royce Lv) * [1740a25] Add testcase for GET param (Royce Lv) * [478d01d] Support params for GET method (Royce Lv) * [4750f33] Remove 'encoding=iso-8859-1' from json.dumps() (Mark Wu) * [7dfb3e4] Integrate nfs path check before create nfs pool (Royce Lv) * [f575b52] utils: Add nfs prevalication (Royce Lv) * [0a02212] storagepool: Use callback functions when deleting a pool (Crístian Viana) * [41e4c8c] storagepool: Do not assume different 'else' values in pool type (Crístian Viana) * [7606325] Issue #310: Query correct name to validate logical devices (Crístian Viana) * [7813c63] storagepool: Add missing msg when no logical device is selected (Crístian Viana) * [3a49821] Ubuntu: Add the LVM dependency package to README (Crístian Viana) * [c69fa0f] Use cherrypy's default dispatcher for subcollection (Mark Wu) * [43618b0] UI bug fix: Set vlan_id value only if 'Enable VLAN' is checked (Aline Manera) * [5e829c2] Add the iSCSI dependency packages to README (Crístian Viana) * [6ae06e9] add a synchronous function with timeout to execute command (ShaoHe Feng) * [f060c18] Add jquery widget dropDown button (zhoumeina) * [a2e7b35] Modify vnc_proxy_port to display_proxy_port (zhoumeina) * [19ae1dd] Add the front end support for SPICE (zhoumeina) * [b605432] RollbackContext: Make it complied with Python Standard (Zhou Zheng Sheng) * [1a2d326] UI: Remove Unused Label Room for Debug Report (Hongliang Wang) * [0dbfe20] host.css: Change Indent to 4 Spaces (Hongliang Wang) * [5289d02] Add a timeout tuning environment variable for debug report test (Shu Ming) * [f51dbbc] Skip the debug report test if there is no tool avaible (Shu Ming) * [88553a8] Issue #308: Use correct iSCSI package for openSUSE (Crístian Viana) * [1567cbb] spec: Open 8000 and 8001 port by default (Eli Qiao) * [31ef97f] Add support to RHEL 7 (Adriano Botega) * [342334e] Deep scan: listing 'unknown' bootable isos after deep scan (Daniel Henrique Barboza) * [c3a548e] UI: template supports networks (Xin Ding) * [7b608a0] Add graphics parameters description in API.md (apporc) * [655f03d] Update test case for graphics support (apporc) * [4951d3c] Update mockmodel for spice support (apporc) * [6c3bc68] Validate graphics parameters input by users (apporc) * [88ddc57] Add spice backend support for kimchi (apporc) * [5ab77d3] Fix break of deep scanning (Royce Lv) * [f5b4740] network improvement: update test case to support vms field (ShaoHe Feng) * [866e836] network improvement: update mockmodel to support vms field (ShaoHe Feng) * [dff73d0] network improvement: add vms field (ShaoHe Feng) * [2f54aab] UI: All user to specify a vlan ID for a virtual network. (Mark Wu) * [6b339da] Support creating vlan tagged virtual network (Mark Wu) * [69edfe9] Generate libvirt's interface XML definition for vlan tagged bridge (Mark Wu) * [b656d4d] Fix qemu-io option in featuretests (Mark Wu) * [dff7038] Add Fedora 20 and Ubuntu 13.10 to distros.d (Mark Wu) * [319a83b] Github issue #300: hardcoded server port fix (Daniel Henrique Barboza) * [e57b07e] Update the po files (Shu Ming) * [99808b2] Remove the legacy files (Shu Ming) * [641ace2] Remove the legacy files from automake and package configurations (Shu Ming) * [90b61f0] Remove jquery-ui customization in network (Yu Xin Huo) * [af8cac4] Customize jquery-ui dialog (Yu Xin Huo) * [762c522] Customize jquery-ui menu (Yu Xin Huo) * [5ba06d7] Customize jquery-ui button (Yu Xin Huo) * [9882732] Remove vnc related code in mockmodel (Mark Wu) * [f1234b1] Use one weksockify instance as all vms' vnc proxy. (Mark Wu) * [8480365] Add a configuration for vnc websocket proxy (Mark Wu) * [47e64e7] Move configuration parsing to config.py (Mark Wu) * [212dc33] Add the ISCSI translation po files (zhoumeina) * [4997624] Add UI support of iscsi (zhoumeina) * [618035a] Support VM template for Power machine (Mark Wu) * [177c2a0] Dynamically generate template parameters for different distros (Mark Wu) * [b4ca2a8] Fix: Storagepool json schema has not been tested when create new SP (Rodrigo Trujillo) * [0b507ff] pep8 cleanup for isoinfo.py (Aline Manera) * [b5d80d8] isoinfo: Move _probe_iso() to IsoImage() (Aline Manera) * [e885f0b] Move ISO path validation to IsoImage() (Aline Manera) * [ff79ea8] Move IsoFormatError() from isoinfo.py to exception.py (Aline Manera) * [1eb47bf] isoinfo: Use absolute path only for local ISO files (Aline Manera) * [e0b2d83] isoinfo: Add default value for ignore_list paramter (Aline Manera) * [6722758] template supports networks: update test case (ShaoHe Feng) * [6f7fda8] template supports networks: update mockmodel (ShaoHe Feng) * [51c1af4] template supports networks: update model (ShaoHe Feng) * [e777c77] template supports networks: update controller and json schema (ShaoHe Feng) * [7d03a1c] template supports networks: update API (ShaoHe Feng) * [601d140] template supports networks: fix test case (ShaoHe Feng) * [ee3377f] template supports networks: let template xml support more networks (ShaoHe Feng) * [1a0fd41] pep8 cleanup for exception.py (Aline Manera) * [be26ed4] pep8 cleanup for distroloader.py (Aline Manera) * [170709e] qemu user tests: probe the username of qemu process started by libvirt (ShaoHe Feng) * [8a7aca2] plugin: fix dynamic import mechanism (Zhou Zheng Sheng) * [05f999f] test_model: test creating iSCSI storage pool (Zhou Zheng Sheng) * [f163d22] storagepool: Support Creating iSCSI storagepool in model.py (Zhou Zheng Sheng) * [53e1d40] storagepool: rename and consolidate arguments of creating (front-end) (Zhou Zheng Sheng) * [265de8d] storagepool: rename and consolidate arguments of creating (back-end) (Zhou Zheng Sheng) * [ab63bba] storagepool: refactor _get_pool_xml() (Zhou Zheng Sheng) * [08ff87d] Issue #293: Resizing Issue When There Are Multiple Grids (Hongliang Wang) * [5e5a6a6] touch 4 files when move RollbackContext, fix pep8 on them (ShaoHe Feng) * [7c98d3b] move RollbackContext from tests/utils to src/kimchi/rollbackcontext (ShaoHe Feng) * [cb7c355] Move all resources related to tasks to control/tasks.py (Aline Manera) * [423e9bb] Move all resources related to plugins to control/plugins.py (Aline Manera) * [ae9cc6b] Move all resources related to host to control/host.py (Aline Manera) * [ceff362] Move all resources related to config to control/config.py (Aline Manera) * [0d44ed9] Move all resources related to networks to control/networks.py (Aline Manera) * [cd5d5bc] Move all resources related to interfaces to control/interfaces.py (Aline Manera) * [8a7a5f6] Move all resources related to storage volume to control/storagevolumes.py (Aline Manera) * [05ce4dd] Move all resources related to storage pools to control/storagepools.py (Aline Manera) * [69a241a] Move all resources related to debug reports to control/debugreports.py (Aline Manera) * [6ea6d32] Move all resources related to templates to control/templates.py (Aline Manera) * [1a23ce1] Move all resources related to vms to control/vms.py (Aline Manera) * [f824fa2] Move basic controller resources to control/base.py (Aline Manera) * [cae61e6] Move login() and logout() functions from controller.py to root.py (Aline Manera) * [9cf0c0f] Move common functions for Resource and Collection to control/utils.py (Aline Manera) * [2d6d1f5] Move generate_action_handler() function to Resource() class (Aline Manera) * [817d3ad] Simplify domain xml in featuretests.py (Aline Manera) * [b44e658] pep8 cleanup for featuretests.py (Aline Manera) * [07c25db] fix whitespace in test_mockmodel (ShaoHe Feng) * [c56582e] logical pool: list unused physical volume (Zhou Zheng Sheng) * [2553e21] logical pool fixes: only list leaf devices, and read file instead of run "cat" (Zhou Zheng Sheng) * [e467b32] Organize python imports (Rodrigo Trujillo) * [1410acd] Add support for Gentoo Linux (Crístian Viana) * [320fd13] PEP 8: Fix an alignment issue in src/kimchi/auth.py (Zhou Zheng Sheng) * [7cead00] pep8 cleanup for root.py (Aline Manera) * [de1867a] pep8 cleanup for cachebust.py (Aline Manera) * [508ada2] pep8 cleanup for auth.py (Aline Manera) * [c0b9d57] Bug fix: Kimchi will try to create directory for 'DIR' storagepool (Rodrigo Trujillo) * [f70d34f] Replace tab to 4 spaces (Aline Manera) * [8698173] Issue #290: correct the log usage (ShaoHe Feng) * [5831b4d] screenshot: fix problem on Power of truncated picture (Royce Lv) * [acbcf04] Return source information for storage pool (Royce Lv) #### [kimchi-1.1.0] #### * [88e5ec6] Update changelog and version files for 1.1 release (Aline Manera) * [bf6d929] Issue #276, logical pool: a quick fix for the device listing rules, front-end (Zhou Zheng Sheng) * [902d295] Issue #276: logical pool: a quick fix for the device listing rules, back-end (Zhou Zheng Sheng) * [b555f83] PEP 8: cleanup src/kimchi/disks.py (Zhou Zheng Sheng) * [85d16e1] Add some brazilian portuguese lang translations (Alexandre Tanaka Hirata) * [f2de42c] do Chinese translation for release 1.1 (ShaoHe Feng) * [3c7f2d7] issue #287: Confirm box will be hidden by the window dialog (Xin Ding) * [bf1d443] Use spacewalk repo to get python-ethtool on suse. (ShaoHe Feng) * [1773214] Add confirm box to create logical pool,and modify device path number (zhoumeina) * [0faa902] bug fix: Make sure to use string with os.walk (Aline Manera) * [b12167b] bug fix: Add authentication to host tab (Aline Manera) * [0e274b8] bug fix: Update openSUSE instructions in README file (Aline Manera) * [d5fe662] bug fix: Don't display vlan interfaces while creating network bridge (Aline Manera) * [a6ddab1] Issue #283: Fix memory leak caused by libvirt connection wrapper (Mark Wu) * [7c62e72] Templates: Remote ISO Image page aligning mess (Xin Ding) * [07111ae] Meaningless text "Default Settings" in the templates tab page (Xin Ding) * [8b41a3f] create template in batch don't show success detail message (Xin Ding) * [d2f4951] Bug fix:251 template edit page disk unit with no unit and make cdrom disable (zhoumeina) * [a4b412c] Incosistent pages when no guests or templates available (Xin Ding) * [3a44881] Update test_model to compare distro name using unicode (Ramon Medeiros) * [af05155] Set autostart value for logical storagepool (Shu Ming) * [3cf5330] Issue #259: vm create: fail msg need to be more specific (Hongliang Wang) * [1a97be6] Fix emulator path in feature tests (Mark Wu) * [428fce5] Issue #279: some plugins/sample files are missing in dist. (ShaoHe Feng) * [be5969d] Tests: Generate UUID and use as temp report file name (Zhou Zheng Sheng) * [1d15833] sosreport: fix name matching of the generated report file (Zhou Zheng Sheng) * [c8a760a] Support unicode on Host Basic Information page (Ramon Medeiros) * [d57226d] Issue #278: add iso_gen.py to Makefile EXTRA_DIST list (ShaoHe Feng) * [0d63a80] Issue 277, Disable 'bridged' option when no interface available (Yu Xin Huo) * [97139d8] Issue #271, add address space for bridged nework (Yu Xin Huo) * [842f72b] Issue #241: require python-psutil version (ShaoHe Feng) * [ed971d1] Issue #262: Switch tab lose default network type selection (Yu Xin Huo) * [9a22f75] bug fix: set the network ip as bridge ip instead of subnet IP (ShaoHe Feng) * [d43e538] Bug #260 fix: Makes UI show missing storage volume information (Rodrigo Trujillo) * [c8a25fd] Bug Fix: Wrong host available memory value (Rodrigo Trujillo) * [37f4d8c] Issue #273: unittest.TestCase has no attribute 'assertLessEqual' (ShaoHe Feng) * [e12b93e] bug fix #254: Reset guest statistics when vm is powered off (Aline Manera) * [1dd695d] bug fix #257: Specify the mime type for debugreports static dir (Aline Manera) * [01d72ca] bug fix: Don't use shell=True in subprocess.Popen while running qemu-io test (Aline Manera) * [175869d] Issue #263: network: bridge network shows network/prefix (ShaoHe Feng) * [89d4766] Packaging: add host.html.tmpl to ui/pages/tabs/Makefile.am (Paulo Vital) * [ce43d08] Add build in localdisk back-end (zhoumeina) * [92d81c6] Add logical pool UI support (zhoumeina) * [97a5e81] Packaging: add the disks.py to src/kimchi/Makefile.am (Zhou Zheng Sheng) * [55f5fa0] Nit fix of scan_dir_prepare (Royce Lv) * [2f4de5f] Deduplication: deduplication in shallow scan (Royce Lv) * [b44c66a] Deep scan: Adding scan ignore path (Royce Lv) * [8d55a0d] Deep scan result deduplication (Royce Lv) * [e3cf2c2] interface bug fix: only expose the unused interfaces to the front end (ShaoHe Feng) * [e9b8deb] Tests: fix test_model.ModelTests.test_debug_reports (Zhou Zheng Sheng) * [612b8e3] UI: Enhancement & Fixes for Host Monitoring (Hongliang Wang) * [1bf51f9] Issue #240: The bridge address of nat and isolated network is invalid, fix it (ShaoHe Feng) * [b1dd7b4] Interface: Fix status return (Rodrigo Trujillo) * [132bfc5] Logical StoragePool: changes in API.md (Daniel Henrique Barboza) * [59a0976] Logical StoragePool: changes in controller.py (Daniel Henrique Barboza) * [343f3d1] Logical StoragePool: changes in model and mockmodel (Daniel Henrique Barboza) * [d9a2013] Logical StoragePool: adding disks.py module (Daniel Henrique Barboza) * [2686b5f] PEP8 cleanup for server.py (Mark Wu) * [8e488ff] Add deep scan test (Royce Lv) * [6b2f43a] ISSUE #236: Fix break of deep scanning (Royce Lv) * [02192e5] Add pseudo iso_gen for deep scan test (Royce Lv) * [64c541a] Template: Enable update Disk size and CDROM path (UI) (Rodrigo Trujillo) * [d7b1be8] Add dependency of nfs client (Royce Lv) * [a7223e0] Concatenate ISO URL correctly with port number (Crístian Viana) * [ebac998] UI: Host Monitoring (Hongliang Wang) * [f684b36] Issue #235: changetoProperUnit Returns Wrong Result (Hongliang Wang) * [0164098] change the unit of host disk and net IO rate from kb/s to B/s (ShaoHe Feng) * [006f773] Fix test cases according to new Templates Schema validation (Rodrigo Trujillo) * [46e9b94] Enable template data verification against json schema (Rodrigo Trujillo) * [c57da0d] Json schema for templates (Rodrigo Trujillo) * [b9b4359] Host reboot and shutdown backend implementation (Rodrigo Trujillo) * [76f8d5d] ui: Adjust storage pool window layout (Aline Manera) * [2ad5768] po files: NFS pool (Pradeep K Surisetty) * [e62ff62] Add/delete NFS pool (Pradeep K Surisetty) * [76653ec] bug fix: remove wlans from nics. (ShaoHe Feng) * [33f487e] bug fix: assert list append successfully when get all network interfaces (ShaoHe Feng) * [f793d3a] Fix minor issue in import order (Rodrigo Trujillo) * [3ddb97d] Add Network UI Files to Makefile (Yu Xin Huo) * [f7a0fa8] network UI: update po files (Yu Xin Huo) * [dc0fc09] create/delete network (Yu Xin Huo) * [f2cf0b6] List/Start/Stop Network (Yu Xin Huo) * [e6b0afc] Center the storage pool "Actions" button (Crístian Viana) * [842e55b] Use consistent padding in storage pool details (Crístian Viana) * [4e2748a] Use jQuery to load xml to make code consistent (zhoumeina) * [8e23fef] host net-io: update test case (ShaoHe Feng) * [c4721df] host net-io: update model and mockmodel (ShaoHe Feng) * [80bcbcb] host net-io: update API.md (ShaoHe Feng) * [b0bc8ba] Authentication is required to access networks (ShaoHe Feng) * [853cdf1] network: update test case (ShaoHe Feng) * [df2b66e] network: update mockmodel (ShaoHe Feng) * [3e0d05b] network: update makefile, spec file and README (ShaoHe Feng) * [9070d60] network: update model (ShaoHe Feng) * [d30ca35] network: generate network xml and testcast for it (ShaoHe Feng) * [26ee208] network: update controller (ShaoHe Feng) * [dbe31d3] network: update API.md (ShaoHe Feng) * [e7c9ce7] Add license to scan.py file (Aline Manera) * [65f6ad3] Organize imports in all .py files (Aline Manera) * [0048f33] fix disk unit: 1K bytes is 1024 bytes instead of 1000 bytes (ShaoHe Feng) * [ad75a6f] Add test cases for plugin support (Mark Wu) * [2abc251] Add a sample kimchi plugin (Mark Wu) * [9fb6a09] Move API schema loading to the initialization of application (Mark Wu) * [f879390] Add a plugin mechanism for Kimchi server (Mark Wu) * [ce3e182] Add the missing Makefiles for plugins support (Mark Wu) * [f22dd25] Add a helper function to get kimchi python package directory (Mark Wu) * [302f186] host disk-io: update test case (ShaoHe Feng) * [f987fb5] host disk-io: update model and mockmodel (ShaoHe Feng) * [76f3f5b] host disk-io: update API.md (ShaoHe Feng) * [940742a] Fix kimchi make rpm fail error (zhoumeina) * [e293010] Authentication is required to access debugreports (Shu Ming) * [f2fce9d] Add the front-end support of tabs (zhoumeina) * [ebf366f] Add the back-end support of tabs (zhoumeina) * [b45e709] Template update UI return 'cpus' and 'memory' as numbers (Rodrigo Trujillo) * [277bd3b] UI: deep scan (Xin Ding) * [a83f2ee] Use "dropdown" CSS class on the Edit Template page (Crístian Viana) * [11f78db] Format template and storage pool details (Crístian Viana) * [7cb6c2a] deep scan: Probe iso information (Aline Manera) * [00d01a7] Add sos/sosreport package as Kimchi dependency (Aline Manera) * [af1de8e] Expose if the host has at least one system report tool (Aline Manera) * [c75d773] Fix low version libvirt bug when get cpuinfo (malcolm yu) * [df327bb] VM Edit UI (Hongliang Wang) * [81a7b87] vm-rename fix: return domain after static config change (Royce Lv) * [89b7631] Sort the storage pool list (Crístian Viana) * [09f9ee0] Update storage pool list after activate/deactivate (Crístian Viana) * [722c5a8] vm-rename: Update testcases for vm-rename (Royce Lv) * [bb895c6] vm-rename: Update mockmodel for vm edit (Royce Lv) * [b2953fc] vm-rename: Update model for vm edit (Royce Lv) * [edaa063] vm-rename: Update controller (Royce Lv) * [a0223e2] vm-rename: Update API.md for vm rename (Royce Lv) * [ceb4ca3] host memory stats: update test case (ShaoHe Feng) * [e225c83] host memory stats: update model and mockmodel (ShaoHe Feng) * [95dda58] host memory stats: update API.md (ShaoHe Feng) * [63f6f77] support recrusive probe in iso scanning (Royce Lv) * [ab7518f] Fix session locking issue (Mark Wu) * [59a8a08] amend API.md (ShaoHe Feng) * [cdb9023] host info: update test case (ShaoHe Feng) * [f0f069c] host info: update mockmodel (ShaoHe Feng) * [371dcdc] host info: update model (ShaoHe Feng) * [4843de7] host info: update controller (ShaoHe Feng) * [cd1d545] host info: update API.md (ShaoHe Feng) * [45df370] interface: update makefile, spec file and README (ShaoHe Feng) * [2036b2c] interface: update test case (ShaoHe Feng) * [6f22e4e] interface: update mockmodel (ShaoHe Feng) * [9054bf9] interface: update model (ShaoHe Feng) * [c47ba91] interface: update controller (ShaoHe Feng) * [5ced3ef] interface: update API (ShaoHe Feng) * [1bd987c] interface: some new utils to get the interface info (ShaoHe Feng) * [76515ed] Add json schema for API's request parameters (Mark Wu) * [8ceadbe] Extend the action decorator into an action handler generator (Mark Wu) * [da4f395] host cpu usage: update test case (ShaoHe Feng) * [f84e32d] host cpu usage: update mockmodel (ShaoHe Feng) * [ca7648b] host cpu usage: update model (ShaoHe Feng) * [1f558d7] host cpu usage: update controller (ShaoHe Feng) * [18b24b3] host cpu usage: update API.md (ShaoHe Feng) * [8ef7b15] Use socket.getservbyname() to get the default port of a protocol (Aline Manera) * [4c05423] Expose the number of CPUs assigned to a VM (Aline Manera) * [e40d237] Make the report tool silent in the background (Shu Ming) * [1c807b6] DebugReports: Downloading the archives (Shu Ming) * [cd74bb8] DebugReports: Implement the real backend (Shu Ming) * [b01b9f4] DebugReports: Implement the mock model (Shu Ming) * [bb59b46] DebugReports: Add collection and Resource (Shu Ming) * [b81fce3] DebugReports: Define the APIs (Shu Ming) * [31f60d7] Add testcase of template storagepool customise (Royce Lv) * [aa77a7a] pre-create validate: validate for mockmodel vm create (Royce Lv) * [94b3b65] pre-create validate: Add iso/storage/network availabilty check (Royce Lv) * [623135f] test storage pool not changed after vm customization (Royce Lv) * [24b4c23] model: aggregate vm config customization when creating (Royce Lv) * [02aa5eb] mockmodel: generate customised temporary template when create vm (Royce Lv) * [549da65] Customise template storage: Report 'storagepool' info in controller (Royce Lv) * [1a090d6] Customise template storage: Update API.md (Royce Lv) * [e2e5892] Set a custom pool for a template (Xin Ding) * [226f6f7] deep scan: add model support (Royce Lv) * [0469f1e] Deep scan: Add functions for deep scan preparation (Royce Lv) * [c359641] Deep scan: update controller (Royce Lv) * [c71a5a6] Deep scan: Update API.md (Royce Lv) * [b5e5bc2] Deep scan: Fix isoinfo.py for iso can't be reported (Royce Lv) * [0c603c5] Adding "python-psutil" package to Kimchi (Daniel Henrique Barboza) * [fe82184] Issue #227: Misunderstood labels and error messages in templates tab. (Paulo Vital) * [39dae67] Fix text wrap in template and guest (zhoumeina) * [1d30644] issue #228: Use SIGKILL to kill proc in featuretests (ShaoHe Feng) * [0e50096] close libvirt connection in featuretests (ShaoHe Feng) * [e74728c] Add gen-pot to .gitignore list (Aline Manera) * [7d86a64] Add missing ui files to spec file (Mark Wu) * [c339575] Distribute po/get-pot.in instead of po/get-pot (Mark Wu) * [0bd8245] bug fix: put distroloader.py in Makefile dist list (ShaoHe Feng) * [50a37a4] Remove 'config.py' from the distribution (Mark Wu) * [07d9a85] Bug fix:153 Drop kimchi-iso from storagepool list (zhoumeina) * [2ee72ce] bug fix: Use vm uuid to properly get vm statistics (Aline Manera) * [a276aff] bug fix: correct to use float when calculate guest net and disk IO (ShaoHe Feng) * [38bb3bd] iso streaming: Add default port for all protocols (Aline Manera) * [b4e0122] ISO streaming: Enable UI (Aline Manera) * [620618b] iso streaming: QEMU workaround (Aline Manera) * [29c7338] iso streaming: Libvirt workaround (Aline Manera) * [93d3ccc] Expose QEMU ISO streaming functionality to host capabilities (Aline Manera) * [03aa2e9] feature tests: Verify QEMU can properly work with hostname while streaming I.. (Aline Manera) * [9e1eae2] feature tests: Verify QEMU supports ISO streaming (Aline Manera) * [e14dec1] feature tests: Rename libvirt test to express what it does (Aline Manera) * [99331be] distros: update testcase in test_rest and rest_model (ShaoHe Feng) * [8a2980a] distros: add mockmodel and model implementation (ShaoHe Feng) * [d8b067a] distros: update Controller to add Distros collection and Distro resource (ShaoHe Feng) * [7e2a5ac] distros: update API document (ShaoHe Feng) * [7add3d9] distros: add a DistroLoader to load distros (ShaoHe Feng) * [185cad1] distros: add new distros files (ShaoHe Feng) * [0e3cb34] Drop IE8 support in README (zhoumeina) * [cbcbd5d] pep8 cleanup for asynctask.py (Mark Wu) * [cafab09] Enable pep8 code style checking (Mark Wu) * [ad793e0] Display error message on template delete failure (Crístian Viana) * [a138304] Choose right icon for centos iso (Royce Lv) * [949fc69] Add jquery-ui files to dist data list. (Yu Xin Huo) * [b1d5002] isoinfo: Allow the main program probe a single ISO file (remote or local) (Aline Manera) * [193ab1a] templates: Try to identify distro and version from remote ISO file (Aline Manera) * [e7f3337] isoinfo: Add support to identify distro and version from remote ISO file (Aline Manera) * [26f1688] StoragePool: Pool name error message (Pradeep K Surisetty) * [e9599d5] Add jquery-ui (Yu Xin Huo) * [00536ab] Remove redundant interface in api.js (zhoumeina) * [8f3e38c] Issue #199: Update templates list only after success of deleteTemplate (Aline Manera) * [cbafe92] vm-uuid: Update testcases (Royce Lv) * [053fa95] vm-uuid: Report uuid in controller (Royce Lv) * [d44883e] vm-uuid: make vm stats indexed in uuid (Royce Lv) * [b0bbc20] vm-uuid: store vm extra information indexed in uuid (Royce Lv) * [d022fff] vm-uuid: Use uuid in screenshot generation (Royce Lv) * [8d70b27] vm-uuid: Using uuid in vmtemplate (Royce Lv) * [51e9766] Use "font-weight: bold" in header texts (Crístian Viana) * [ec381bb] No HttpOnly is set to the cookie for session id (Xin Ding) * [18567d7] Use libvirt api to implement find_qemu_binary (apporc) * [ce12235] eliminate messages keys from all po files (ShaoHe Feng) * [1e164ca] bug fix: make gen-pot scan multi lines (ShaoHe Feng) * [765887d] Add the three translation for Chinese (zhoumeina) #### [kimchi-1.0.1] #### * [1726c5b] Update ChangeLog for the 1.0.1 release (Adam Litke) * [9d0c89c] Do not generate ChangeLog when outside a Git repo (Crístian Viana) * [c44d03b] Add VERSION file with Kimchi version (Aline Manera) * [51d365f] Get the appropriate Kimchi version from Git tag (Crístian Viana) * [d9d4cdd] Fix variable name "iptype" (Crístian Viana) * [564babe] Issue #97: "Make distclean" does not remove all the intermediate files (Paulo Vital) * [4a6edb2] Issue #180: Singular/plural noun agreement on "Templates" (Crístian Viana) #### [kimchi-1.0.0] #### * [d665854] Update ChangeLog for the 1.0.0 release (Adam Litke) * [0448a5a] opensuse: Start kimchid automatically (Adam Litke) * [5db3d20] Issue #173: set the correct mime type of Content-Type in HTTP respose header (ShaoHe Feng) * [665406d] Bugfix: Issue #182 int object has no attribute isdigit (apporc) * [0654104] Encode parameters in URL generated by the server (Xin Ding) * [f7fa1d8] Encode parameters in URL When calling REST APIs (Xin Ding) * [4fdc708] Make header text sizes equal (Crístian Viana) * [3c88c7f] build: Generate ChangeLog (Adam Litke) * [51f15c6] issue #183: Display all template information in pt_BR on Firefox (Aline Manera) * [adb065f] i18n: Update translation catalogue (Adam Litke) * [f4d7f5b] Fix typo in English translation (Aline Manera) * [65bdf9e] Issue #183: Adjust Template Tile Layout (Hongliang Wang) * [916344a] Fug fix:Chinese tooltip will wrap in storage (zhoumeina) * [045c506] change the storage arrow style, and make arrow disable when inactive (zhoumeina) * [b45b62c] i18n: Update pt_BR translations (Aline Manera) * [27cebf6] Issue #154: Prompt User When Creating VM and There is NO Template (Hongliang Wang) * [85195d6] Issue #191: Log-in Name Disappears after Restarting Browser (Hongliang Wang) * [4cf0113] Issue #190: Language Selector Value NOT Match Page Content (Hongliang Wang) * [6c85531] Bug fix: login window will have scroll bar when putted wrong password (zhoumeina) * [111494a] Drop the handle in storage,fix the position error of the navbar arrow (zhoumeina) * [917d120] The icon image for unknown os is not suitable (Xin Ding) * [aea983c] issue #166: Destroy storage when vm define fails (Royce Lv) * [3269670] The size unit of scanned ISOs is wrong (Xin Ding) * [66be273] kimchid: Fix default for 'host' parameter (Adam Litke) * [1fd2284] Add the translation of English and Chinese (zhoumeina) * [832a270] bug fix: 404 error in debugger network tab when creating new VM (Aline Manera) * [457afa8] Apply Kimchi style to login screen (Aline Manera) * [26f8b50] model: Handle libvirt connection failures (Adam Litke) * [b97428f] MockModel: fix mock_environment (Adam Litke) * [e7c976e] Issue#93 UI Not updated after deleting the last guest (fix) (Adam King) * [e515426] issue #171: Adjust template box style to avoid text overlapping (Aline Manera) * [3d4d209] Fix bug:145 Make a util to change the storage unit (zhoumeina) * [318a183] update test case after a series unit bug fixed (ShaoHe Feng) * [385a1b0] bug fix: keep the default value of storage info from libvirt (ShaoHe Feng) * [8171fcc] bug fix: set the capacity unit to MB when pass it the storagevolumes_create. (ShaoHe Feng) * [508cbdb] bug fix: mockmodel set the storage volume size to MB according to the API.md (ShaoHe Feng) * [aee9ebe] bug fix: Update API for storage volume resize (ShaoHe Feng) * [5eb9b8b] Issue: #177: iso storage volume get wrong allocation value (ShaoHe Feng) * [8976efd] Add spaces around words on "Templates" (Crístian Viana) * [4ed3db9] tests: Add tests to verify data validation when editing a template (Aline Manera) * [cf817b9] issue #75: Validate parameters when updating a Template (Aline Manera) * [71a3a88] Create default network if it does not exist (Aline Manera) * [59efe0c] bug fix: Fix log error message when kimchi can not create default pool (Aline Manera) * [c20106f] bug fix: Fix typo while logging information to cherrypy handlers (Aline Manera) * [e97498a] bug fix: Import missing modules (Aline Manera) * [6d8d739] doc: Restart libvirt after installing packages (Adam Litke) * [5387198] tests: Add assertIn and assertNotIn for python2.6 (Adam Litke) * [7498532] Update README and packaging files for release (Adam Litke) * [f8ef624] Fix typo on Storage Tab (Aline Manera) * [f6a60ff] change the login window css to make language selector in the head (zhoumeina) * [0509118] Issue #174: error page can not be translated, fix it. (ShaoHe Feng) * [de3cc14] UI Template Edit: Hide Unsupported Items (Hongliang Wang) * [87b2930] Fix bug Regex in checking url (zhoumeina) * [149f12d] Align storage header in Storage tab (Aline Manera) * [e7e8c61] Autostart storagepools created from kimchi (apporc) * [d41f4f5] UI: Enable Language Selection (Hongliang Wang) * [87049d1] Enable the template_create test with non-root account (Shu Ming) * [ba5fbc3] Streamline template creation flows - update (Xin Ding) * [0abccf7] bug fix: Recognize openSUSE 12.3 ISO file (Aline Manera) * [a8c5430] Fixed the regx pattern (Shu Ming) * [d244cb6] bug fix: Recognize Fedora 19 ISO file (Aline Manera) * [488784e] Issue #133: mv make_dirs from kimchid.in to server.py (ShaoHe Feng) * [ac1d7c2] Streamline template creation flows (Xin Ding) * [436ce3e] doc: Update images in README (Adam Litke) * [4ea86e3] Issue #167: Duplicate Requests for HTML Fragment when Switching Pages (Hongliang Wang) * [657bb3b] Issue #161: Firefox Doesn't Take Correct Favicon for Kimchi (Hongliang Wang) * [0ba88f8] bug fix: remove ordereddict from suse spec require list (ShaoHe Feng) * [768441a] Style of uneditable fileds in template edit (Xin Ding) * [26a9427] Change the ico of iso (zhoumeina) * [6f74c37] Bug fix:137 UI: When expanding an empty pool, show a message in the drawer (zhoumeina) * [827f3b2] Issue #151: No Message when User Opens http://kimchi:port/#i18n (Hongliang Wang) * [316565c] issue#149: fix relative symlink path error in iso scan (Royce Lv) * [cb7b5e5] Issue #131: Wrong Arrow Position after Error Page (Hongliang Wang) * [87fdfb8] Add test for refresh and vol number display (Royce Lv) * [0c7900a] Update model to support refresh and 'nr_volumes' info (Royce Lv) * [fa3ffc2] Change mockmodel to refresh pool volumes (Royce Lv) * [2391429] Update Controller to add 'nr_volumes' into its info (Royce Lv) * [8c4fedc] Update the description StoragePool and StorageVolume in API.md (Royce Lv) * [868db8e] Add testcase for create volume for active pool (Royce Lv) * [7657947] Prevent mockmodel from creating volumes for deactive pool (Royce Lv) * [45c6769] Activate default pool for mockmodel (Royce Lv) * [78f18e7] Create default pool and activate in model (Royce Lv) * [3a33f1c] Issue #112: Guest reboot and power buttons do not have hover text (Hongliang Wang) * [b8ad3fd] Issue #147: Storage UI NOT List Storage Automatically After Logging in (Hongliang Wang) * [d514ac6] KPI: Updates model and mockmodel tests (Aline Manera) * [c2dcfa9] KPI: Update API documentation (Aline Manera) * [8e6448e] Display disk I/O rate instead of storage usage (Aline Manera) * [f6c1daf] Display network I/O rate instead of memory usage (Aline Manera) * [dd1b604] Create new thread to collect Kimchi statistics (Aline Manera) * [9e20380] Fix Log-in Window Redrawn after 401 Returned (Hongliang Wang) * [5539156] tests: Fix auth tests (Adam Litke) * [87dc322] tests: Add authentication tests (Adam Litke) * [3d993d3] Issue #125: Switching Page Tabs Breaks Pop-up Menu Disappearing (Hongliang Wang) * [f00ee09] i18n: Correct storage pool create error message (Adam Litke) * [adf3ac3] issue #143: Add missing parameter while calling the request error handler (Aline Manera) * [a915292] Add the globalization translation in English/Chinese (zhoumeina) * [8ccaf94] Fix bug: Storage pool name will wrap when it contains - and white-space (zhoumeina) * [b27d1f4] issue #141: Fix regex responsible to check if an URL is valid or not (Aline Manera) * [e9a8723] fix issue #136 about mockmodel iso pool type (Royce Lv) * [d412d20] There will be two goto homepage button at the #tag nonexistent page (zhoumeina) * [d894fc1] Aggregate read for iso to improve scan efficiency (Royce Lv) * [6ffb568] Add a go to homepage button at the error page (zhoumeina) * [cd1b23d] capabilities: Update REST API tests (Aline Manera) * [f5089e8] capabilities: Update API.md (Aline Manera) * [8f54df9] Capabilities detection (Aline Manera) * [b0a0c73] screenshot: Expose stream test result (Aline Manera) * [99f9d9e] Update Test Code (Hongliang Wang) * [d00782c] Edit Template API: Change HTTP Code to 303 (Hongliang Wang) * [cfc30c8] UI: Update Template (Hongliang Wang) * [f12ebc0] UI:[Storage support]Add the html of Storage support (zhoumeina) * [53cad8d] UI:[Storage support]Add the js files of storage (zhoumeina) * [59f07ab] UI:[Storage support]Add the css style of the storage page (zhoumeina) * [3d9a7ff] UI:[Storage support]Add the po files of storage ui design (zhoumeina) * [e806e87] UI:[Storage support]Add the png files for storage ui design (zhoumeina) * [6d72c82] tests: Disable auth debug (Adam Litke) * [740ae82] tests: Fix unit tests after auth was merged (Adam Litke) * [c8876e3] auth: Prevent HTTBA in browser with FF Poster (Adam Litke) * [114d52e] Enable UI (Hongliang Wang) * [e13434a] Enable Cookie Manipulating in Client Side (Hongliang Wang) * [bd1367b] Enable REST API (Hongliang Wang) * [d69d14c] authentication (ShaoHe Feng) * [f2949fa] Raise exception when cdrom URl does not match any criteria (Aline Manera) * [ec0dd6a] Create sanity test to verify libvirt supports iso streaming (Aline Manera) * [2a0504d] Adjust VM xml to support iso streaming (Aline Manera) * [2d9ee88] bug fix: Use unitdir macro when creating directory for systemd units (ShaoHe Feng) * [706a277] Create templates by shallow scan, deep scan and distros (Xin Ding) * [50a5f26] shallow scan: Update testcases (Royce Lv) * [0ef2130] Shallow scan: Add mockmodel implementation (Royce Lv) * [e652eaf] shallow scan: Add model support (Royce Lv) * [451c006] shallow scan: Change controller to be compatible with virtual pool (Royce Lv) * [e2dd533] shallow scan: return unknown distro and version rather than none (Royce Lv) * [3bceeaf] shallow scan: Report path info to storage volume (Royce Lv) * [fac0794] shallow scan: extend API.md to make volume report iso information (Royce Lv) * [0453992] Create template iso path needs to check (zhoumeina) * [f1594e4] Fix bug:119 Action will be closed after refresh each 5 s (zhoumeina) * [9e7ccba] No html escape in the kimchi.template function (Xin Ding) * [a3b4891] Add browser support in README (zhoumeina) * [78ba75c] Remove the msg check in test_exception.py (Bing Bu Cao) * [d64c1fb] Catch the libvirt exceptions when accessing storage objects (Bing Bu Cao) * [0ca05c1] Return abspath for iso scanning (Royce Lv) * [7a01840] Add parentheses around dependency version in deb control file (Aline Manera) * [781ba1d] issue#110: Fix list storage volume for inactive pool (Royce Lv) * [b53bb35] Add testcase for InvalidOperation (Royce Lv) * [a21aaeb] Catch InvalidOperation in collection (Royce Lv) * [99638de] tests: Test the REST API using an SSL connection (Adam Litke) * [2f26f37] server: Support SSL connections (Adam Litke) * [a92de0d] api: Add an API to retrieve application configuration (Adam Litke) * [8aac0d1] bug fix: add two dependencies in README. (apporc) * [7dd1243] bug fix: two python souce missing in distribution (apporc) * [1e46730] build: Include extra top-level files in dist (Adam Litke) * [e8f27d8] Issue #76 - ImportError: No module named discover (Bing Bu Cao) * [270a971] adopt a single log convention (ShaoHe Feng) * [fff1bdf] IE8: The arrow indicator of dropdown menus can't be displayed (Xin Ding) * [c73d9e6] A module to check the pam authenticate (ShaoHe Feng) * [a724d98] set expires for static content caching (ShaoHe Feng) * [c89a1ed] cacheBust parameter for static content caching (ShaoHe Feng) * [ce1ad9c] add a cachebust module to generate href with cacheBust (ShaoHe Feng) * [253a894] IE8: No background style for items in the template list page (Xin Ding) * [0ea6333] IE8: No selected style for items in the main (Xin Ding) * [44202b0] Fix indent of the js files (zhoumeina) * [4d78ca5] template-update: real model support implement update method (ShaoHe Feng) * [d3f864b] template-update: add the test case for update (ShaoHe Feng) * [d3c4cb2] template-update: mock model support implement update method (ShaoHe Feng) * [7d924e6] template-update: resouce support update method (ShaoHe Feng) * [f67cf47] template-update: define an update method in API.md document (ShaoHe Feng) * [dab2688] codingstyle: Fix indent for templates.html.tmpl (Adam Litke) * [d12b474] IE8: The template list page can't be displayed (Xin Ding) * [d24d1d5] Add delete confirm message box (zhoumeina) * [40f0d9d] issues #95: Added files generated by build to .gitignore (ShaoHe Feng) * [6528b11] IE8: Very long guest names cause column misalignment (Xin Ding) * [8b6f92f] issue #82: convert from svg image to png image (ShaoHe Feng) * [41206f4] Add Portuguese (Brazil) translation (Aline Manera) * [e1eb228] Remove magic directories from config.py.in (Adam Litke) * [9bc6ba2] i18n: Stop adding location comments to po files (Adam Litke) * [c873867] Issue #39: Animate Button Clicks to Provide User Feedback (Hongliang Wang) * [692cdd6] ui: Rename tab pages (Adam Litke) * [eb1c6a3] python2.6 do not support dict key iteration (ShaoHe Feng) * [c59b7d6] Using absolute path in error page (Royce Lv) * [5f04ac0] test case for creating a vm with unicode name (ShaoHe Feng) * [1797fe8] mockmodel support a VM with ww language name (ShaoHe Feng) * [af8014d] support create a vm with unicode name (ShaoHe Feng) * [a4c99eb] sqlite3 support unicode (ShaoHe Feng) * [ae358e4] Passing the options from autogen.sh to configure (Shu Ming) * [ff869d5] remove the translation keys in i18n.thml and update the po files (ShaoHe Feng) * [afb3a77] UI: update some labels of template edit page (ShaoHe Feng) * [04395d5] All templates translate all languages no exceptions for English (ShaoHe Feng) * [49a02da] Issue #72: Make Pages Be Bookmark-able (Hongliang Wang) * [a5fceb2] fix bug:35 GUEST 'VNC' do not work which graphic type is 'spice' (zhoumeina) * [bfd91d8] ui: Keep image ratio while displaying VM icon and screenshot image (Aline Manera) * [1846daa] Exception: Add UI support (Royce Lv) * [431d554] Exception: Add testcase to test error reporting (Royce Lv) * [55d84e1] Exception: Distinguish development mode and production mode in kimchi server (Royce Lv) * [1463303] Exception: reporting error in controller.py in details (Royce Lv) * [dc8881f] Exception: Customise error page handler (Royce Lv) * [b8c6eee] Exception: move exceptions from model (Royce Lv) * [3e86f3f] ui: Disable 'Create' button on create guest without required input (Aline Manera) * [c5e3951] Update Banner image for Kimchi rename (Adam King) * [551a564] Issue #43: UI Reports Error When Pressing Enter Key in Creating VM Form (Hongliang Wang) * [75ce907] fix bug:#51 guest tab contains 404 file not find error (zhoumeina) * [2086de3] Bug fix:#67 add M for template memory (zhoumeina) * [831160b] update UI to get connect graphics (ShaoHe Feng) * [a196235] add graphics in mockmodel (ShaoHe Feng) * [091af9b] add an attribute to get graphics of vm in model and update test case (ShaoHe Feng) * [9d17820] bug fix: Add graphics of vm in API.md document (ShaoHe Feng) * [4c227f5] Add ignore_missing parameter to ObjectStoreSession.delete() method (Aline Manera) * [7c5b4d3] add automake and autoconf to dependencies (zhoumeina) * [895f18c] add i18n.html.tmpl in dist_html_DATA list (ShaoHe Feng) * [e67e479] doc: Update README.md with new build steps (Adam Litke) * [91746b7] Rename burnet to kimchi (Adam Litke) * [da6bc2c] build: Set install prefix using autoconf (Adam Litke) * [0eba7d3] build: remove old distutils build files (Adam Litke) * [818f184] build: Add support for building distro packages (Adam Litke) * [544d8bd] build: Add gettext i18n support (Adam Litke) * [b868785] build: Compile, distribute and install files (Adam Litke) * [3529c60] build: Add basic autotools infrastructure (Adam Litke) * [fff5167] screenshot: Add timeout to screenshot creation (Aline Manera) * [5bebdc2] bug fix:#49 404 in debugger network tab when opening kimchi templates tab (zhoumeina) * [30bc539] tests: Fix test_server_start (Adam Litke) * [6228dee] ui: Ensure i18n.html loads (Adam Litke) * [7e963fe] Remove obsolete data used in rendering page (Royce Lv) * [cc89b1e] add js globalization method (ShaoHe Feng) * [0c1cdcb] Asynctask: add logging to async task (Royce Lv) * [37b87ab] Remove 'path' which should not be specified when creating volume (Bing Bu Cao) * [95b7446] Use #unicode instead of #encoding in Cheetah templates (Aline Manera) * [cbd5afa] fix bug: xmlutils get node context by context attribute (ShaoHe Feng) * [80df676] issue34: add handling invalid iso file (Royce Lv) * [5380105] issue60: Avoid using default database file in test (Royce Lv) * [56b6e67] Issue #59: Make the popup menu entirely visible in browser (Hongliang Wang) * [8796558] template: add rhel to osinfo (Royce Lv) * [e05096c] bug: fix list vm name in unicode for mockmodel (Royce Lv) * [de4d8b4] bug fix: kimchi supports to show VM with Chinese name (ShaoHe Feng) * [b5fa8c2] Fix the exception caused by IE8 (Shu Ming) * [4a8fcfd] fix-bug: remove the useless mini-line (ShaoHe Feng) * [130d98b] UI:Add Template button should be disable but not hide before input the iSO (Xin Ding) * [7c4c1b5] fix-bug: issues30 UI:Add Template contains js errors (Xin Ding) * [a747f74] Hidden the VNC button when VM is stopped (Bing Bu Cao) * [f17e101] #32 template name too long make page abnarmally (zhoumeina) * [2477c0c] Fix Issue #10: Very long guest names cause column misalignment (Hongliang Wang) * [1b33ded] Remove useless text in template-add.html.tmpl (Xin Ding) * [868abd7] doc: Update README.md with more package dependencies (ShaoHe Feng) * [5cda59c] Need root privilege to run test_vm_list_sorted test (Shu Ming) * [69669a1] test: change testcase to allow running single test (Royce Lv) #### [kimchi-0.1.0] #### * [3efcaa2] Enable the usage of test:///default (Eduardo Elias Ferreira) * [96f604f] Ordered guest list (Eduardo Elias Ferreira) * [7c06d1d] Convert VM list to unicode (Eduardo Elias Ferreira) * [7212590] Cannot delete a VM that is powered on (Eduardo Elias Ferreira) * [85927b0] Check if VM exists before stopping or deleting (Eduardo Elias Ferreira) * [dcabdcb] ui: overwrite vm start and stop click event to fix multi-click bug. (ShaoHe Feng) * [03cbce4] ui: add a vm load icon for multi-click bug. (ShaoHe Feng) * [90e586e] Change test filename to a standard format (Eduardo Elias Ferreira) * [0e2801e] fix bug: UI displays abnormal follow the README (ShaoHe Feng) * [61332e7] fix bug: let i18n_files depends on po files instead of mo files. (ShaoHe Feng) * [98c0373] Bug Fix: Get correct exception info when run unittest on Python2.6 (Bing Bu Cao) * [811c10e] Raise an exception in skipUnless() to abort the test on Python2.6 (Bing Bu Cao) * [2ac7290] mockmodel: Use ps|grep to find open VNC port (Aline Manera) * [acfa9f2] Add another path for SLES11 to find the qemu binary (Bing Bu Cao) * [329a4c3] ui: Fix screenshot flicker (Royce Lv) * [9ed459c] fix: Remove extra import statement in objectstore.py (Aline Manera) * [41ab0c0] Tasks: Implement the backend (Shu Ming) * [0968b5c] Tasks: Implement mock model (Shu Ming) * [41f107e] Tasks: Splitting ObjectStore from model file (Shu Ming) * [bf3501f] Tasks: Define the APIs (Shu Ming) * [7343783] Correct License file to correctly cite ASL2 (Adam King) * [5983108] Bug 94806 screenshot can not display from design UI. JS Updates (Adam King) * [5e6ebea] Bug 94806 Screenshot live tile gets 404 on initial load. Refactor html (Adam King) * [9a23263] Update setup.py make_po task to be verbose (Adam King) * [34f1f3e] Remove unused rule .template-drop in template list CSS (Hongliang Wang) * [75a4e4f] Update the Rest and MockModel tests to account for the server no longer redi.. (Adam King) * [0cf1d00] Update controller.py to prefer InternalRedirect to HTTPRedirect (Adam King) * [4b65b20] Add RHEL6 support (Eduardo Elias Ferreira) * [f2149f4] Merge pull request #3 from crobinso/fedora-pil-fix (Adam Litke) * [163c3cd] Fix Image imports on Fedora 19 (Cole Robinson) * [6fbc8ed] ui: Display template icons (Adam Litke) * [9fc1789] templates: Scan ISO to determine os_distro and os_version (Adam Litke) * [68baf7a] Identify Operating System from ISO file (Adam Litke) * [7ee068d] osinfo: Fix osinfo to use the correct distro shortnames and versions (Adam Litke) * [8fafad1] Refactor osinfo/VMTemplate parameter handling (Adam Litke) * [365e6e5] Update design ui html template to use favorites icon (Adam) * [2becd3a] Add icon file for use as favorites icon (Adam) * [c8c0eb7] Make logging level configurable (Aline Manera) * [b59ab8a] Separate burnet logs into access log and error log (Aline Manera) * [ff5d076] tests: Screenshot is not available until vm is started (Adam Litke) * [c812468] Add improved README with screenshots (Anthony Liguori) * [59a94c8] ui: remove the mocked up username (Anthony Liguori) * [48b6efb] UI: Support Edit a Template (Hong Liang L Wang) * [e7b69fe] ui: template creation without iso scan support (xinding@cn.ibm.com) * [2783ce9] UI: Support List Templates & Delete a Template (Hong Liang L Wang) * [0f18271] new ui: Display a VM's icon when it is powered off (Aline Manera) * [47f5c52] Revert 5a9ff5d61fa03c19c71c1d22e0f841ca1377a423 This patch is part of the fu.. (Adam Litke) * [5a9ff5d] add template navigation title (zhoumeina) * [40c1eaa] change button styles according to the latest ui design (Xin BJ Ding) * [d364d02] Bug Fix: this patch fix the bug 95350 (Bing Bu Cao) * [ed4ec60] Added additional patterns to .gitignore (Adam King) * [07d906d] Add cpu_stats field to ModelTests (Aline Manera) * [0f094b1] Generate the cdrom XML based on template config. (Tony Breeds) * [fc6e2b9] Move bus_to_dev into the VMTemplate class. (Tony Breeds) * [30515ef] bug: using whitespace when probing qemu process with vnc option (Bing Bu Cao) * [c44dfaf] UI: remove red exclamation point before the vm name (ShaoHe Feng) * [70db7f4] burnet: relicense source tree (Anthony Liguori) * [0ecc1a3] Assume guest arch is the same as host, rather than x86_64. (Tony Breeds) * [1a8bc2f] Display percentage of CPU usage for each virtual machine (Aline Manera) * [d14d2d5] ui: Display a warning if the UI needs to be built (Adam Litke) * [9603514] packaging: python-polib is required (Adam Litke) * [61a170a] dev-ui: Fix vnc linkage (Adam Litke) * [1df0364] Fix screenshot stream resource leak (Royce Lv) * [d7c586b] ui: Update the build process and server configuration (Adam Litke) * [2a91a9d] ui: Import pages and i18n (Adam Litke) * [f852fa3] ui: Import javascript files (Adam Litke) * [b3502a3] ui: import modernizr (Adam Litke) * [21a2354] ui: Import jquery-1.10.0.min.js (Adam Litke) * [4ca183a] ui: Import the default theme images (Adam Litke) * [67bef51] ui: Import css files for the default theme (Adam Litke) * [df49b71] ui: Namespace the dev ui (Adam Litke) * [9789650] ui: Filter all requests for html pages through cheetah (Adam Litke) * [40e5b6b] Move noVNC files into new directory structure (Adam Litke) * [975bfa4] Reorganize UI files (Adam Litke) * [40a538f] ui: Let the UI pick the default icon for a VM (Adam Litke) * [3d414ed] i18n: Fix install paths of gettext .mo files (Adam Litke) * [ffa826c] Revert b8cfa245b868d4778c68f407fcf3180dde895673 I applied a patch to fix fli.. (Adam Litke) * [313b52d] ui: Increase screenshot refresh frequency (Adam Litke) * [4552ca5] ui: Allow scrollbars on the VNC window if necessary (Adam Litke) * [b8cfa24] Fix screenshot image flicker (Royce Lv) * [77b1177] do not translate en_US (ShaoHe Feng) * [0a83bd7] add README for i18n (ShaoHe Feng) * [096f512] check pygettext.py is available (ShaoHe Feng) * [16b259a] install the i18n files correctly (ShaoHe Feng) * [983e140] info_po command to show the summary infomation of po files (ShaoHe Feng) * [f222a31] add make_po command to generate or update po files (ShaoHe Feng) * [28b5875] give gettext another nickname ' _t' (ShaoHe Feng) * [beee18c] trim index.tmpl to make pygettext.py happy (ShaoHe Feng) * [26d56d7] translate burnet home page to Chinese (ShaoHe Feng) * [2c0af9f] initialize the language select on the URL loading (ShaoHe Feng) * [8a40004] i18n the title 'hostname' of index.tmpl (ShaoHe Feng) * [d099fb3] define a dummy _() function to defer actual translation (ShaoHe Feng) * [8a36c45] generate mo files during build time (ShaoHe Feng) * [574833a] configure the gettext of Cheetah template to support i18n (ShaoHe Feng) * [cb38be8] add po files for i18n (ShaoHe Feng) * [90ab55c] get language that the client prefers (ShaoHe Feng) * [5e04efc] ui: Add button to delete a templete (ShaoHe Feng) * [f3eb2ed] tests: Fix expected result in test_vm_info (Adam Litke) * [aa6101f] tests: Add required logfile variable to server options (Adam Litke) * [87964ad] Fix websockify.py permission after installation (Royce Lv) * [bd387ce] browser report start VM error, fix it (ShaoHe Feng) * [6ca43a6] Set default log directory according to burnet root directory (Aline Manera) * [12ea4a3] Create build process for Debian distributions (Aline Manera) * [d2e5514] Create build process for SLES-based distributions (Aline Manera) * [4d43935] Create build process for RHEL-based distributions (Aline Manera) * [674e129] Add sysvinit support (Aline Manera) * [972c689] Add upstart support (Aline Manera) * [9e191e6] Add systemd support (Aline Manera) * [c969f03] Create log file to burnet server (Aline Manera) * [d357d37] Replace argparse with optparse (Adam Litke) * [b086e2b] Import OrderedDict across multiple distros (Adam Litke) * [3f72977] fix the prefix of burnet date path (ShaoHe Feng) * [23815be] add the static files into data_files list (ShaoHe Feng) * [74d31b2] Display a VM's icon when it is powered off (Adam Litke) * [fe48e63] resize no_VNC window dynamically (ShaoHe Feng) * [3f1a915] Use ps instead of pgrep to search for VNC qemu port (Aline Manera) * [b9daead] Update vm-toolbar on each vm selection (Aline Manera) * [a0511aa] Make storage*s_create() return the name of the resource (Bing Bu Cao) * [d7e8a53] Open VNC port for MockModel only once (Aline Manera) * [77c5fca] Fix mock backend vm delete error (Royce Lv) * [7850b3b] Hide dialog-delete-confirm div in Burnet main page (Aline Manera) * [261cc99] Enable folder navigation for Templates in the UI (Aline Manera) * [2c774f9] Add bread-crumbs style to burnet template (Aline Manera) * [088ba06] Add folder field to Template Resource (Aline Manera) * [0e8c94b] screenshot: libvirt backend screenshot (Royce Lv) * [0a607da] screenshot: Nit fix of mockmodel (Royce Lv) * [a27afd2] screenshot: minor change to common screenshot class (Royce Lv) * [c08bab9] Add libvirt backend StoragePool(s) and StorageVolume(s) unitTest (Bing Bu Cao) * [dc8952d] Add libvirt backend StoragePool(s) and StorageVolume(s) support to Burnet (Bing Bu Cao) * [ed4bda5] Remove useless 'pass' in mockmodel.py added before (Bing Bu Cao) * [0dc3293] ui: Add button to delete a VM (Adam Litke) * [a1e335f] ui: Create a new VM from a Template (Adam Litke) * [1b147fc] API: Make VM name optional (Adam Litke) * [ded4a86] Provision storage when creating a VM from a Template (Adam Litke) * [e421821] objectstore: rollback transactions on error (Adam Litke) * [830d4e4] osinfo: Add osinfo for some popular operating systems (Adam Litke) * [b7562ae] Add 'vnc_port' key (Bing Bu Cao) * [40f4b45] Add screenshot directory to data/ directory (Royce Lv) * [e402a07] merge-fail: Add the file 'src/burnet/vnc.py' When taking the patch: [PATCH 0.. (Adam Litke) * [4b9a62c] Handle the 'Display' link (Aline Manera) * [7ccfed2] Restore 'Display' link state after performing power on/off (Aline Manera) * [1688f15] Enable 'Display' link only if a running virtual machine is selected (Aline Manera) * [9c3778a] Deselect virtual machines after performing power on/off (Aline Manera) * [5c9a736] Implement real backend to start VNC session (Aline Manera) * [0000eb6] Handle 'connect' action to virtual machine in MockModel (Aline Manera) * [19be36f] Open vnc port in MockModel (Aline Manera) * [ee197f6] Make static/ directory available in the web server (Aline Manera) * [5ab68de] Import noVNC files (Aline Manera) * [65e2312] Import python WebSocket library as it is (Aline Manera) * [30a4503] screenshot: Add time-based screenshot refresh testcase (Royce Lv) * [e95a007] screenshot: Change mock backend to support screenshot generation (Royce Lv) * [03682f3] screenshot: Add screenshot sub resource (Royce Lv) * [aadc37c] screenshot: Add common screenshot class (Royce Lv) * [cbcf002] screenshot: expose screenshot path (Royce Lv) * [5ebada4] doc: Add screenshot resource definition (Royce Lv) * [f30e4c2] images: Import some icons for popular operating systems (Adam Litke) * [7194621] api: Return HTTP:404 when deleting a non-existent resource (Adam Litke) * [cbb8396] add a select to setup a language cookie (ShaoHe Feng) * [24e76c3] ui: Refresh UI at a 5 second interval (Adam Litke) * [c70b03f] Make sure the data/ directory exists in the source tree (Adam Litke) * [19f8c02] Add a simple object persistence mechanism (Adam Litke) * [d335aa1] Implement the real backend using libvirt (Adam Litke) * [36ca77c] Create VM from a template (Adam Litke) * [6135a15] templates: Implement the mock model (Adam Litke) * [ff6ae73] templates: Add osinfo dictionary (Adam Litke) * [068ea78] templates: Add Collection and Resource (Adam Litke) * [90cf130] doc: Define the template APIs (Adam Litke) * [f93dde3] Add Rest API test cases (Bing Bu Cao) * [44ff829] Add the Collection and Resource (Bing Bu Cao) * [94dc894] Define the StoragePool(s) and StorageVolume(s) APIs (Bing Bu Cao) * [0fd434f] Enable power off virtual machines in UI (Aline Manera) * [8f94ee5] Enable power on virtual machines in UI (Aline Manera) * [09a75ce] Enable virtual machine selection in UI (Aline Manera) * [50b4937] Setting the code encoding of cheetah template as UTF-8 (ShaoHe Feng) * [212add9] Add screenshot field to VM Resource (Adam Litke) * [2c48de8] doc: Document the desired REST API (Adam Litke) * [25d9887] UI: Load VM information from the actual REST API (Adam Litke) * [b0e36f7] Add basic VM operations (Adam Litke) * [dbdb61a] Remove GPL license (Anthony Liguori) * [8dc800d] Add basic Virtual Machine support (agl@linux.vnet.ibm.com) * [f5f8f85] Add basic model/controller support (agl@linux.vnet.ibm.com) * [a2d2085] template: Fix the separators for json rendering (agl@linux.vnet.ibm.com) * [bee9ca0] tests: Correct test_server_start expected result (agl@linux.vnet.ibm.com) * [2ed1745] template: Don't forget to import json (agl@linux.vnet.ibm.com) * [50dbe22] ui: expose the js/css/images directory and the index template (Anthony Liguori) * [ae3d4f7] ui: add javascript, css, and template for main page (Anthony Liguori) * [7a563b4] ui: add external resources (jquery, etc.) (Anthony Liguori) * [2610749] burnet: add template module (Anthony Liguori) * [7d0c7d6] burnet: add config file (Anthony Liguori) * [980b749] setup.py: use package instead of py_modules (Anthony Liguori) * [4e982f9] docs: add CONTRIBUTE.md to the top-level (Anthony Liguori) * [d60a085] tests: Introduce basic unit testing infrastructure (v2) (agl@linux.vnet.ibm.com) * [5e9b7aa] Initial import of code base (Anthony Liguori)kimchi-1.5.0/INSTALL000066400000000000000000000365771254252253000140340ustar00rootroot00000000000000Installation Instructions ************************* Copyright (C) 1994-1996, 1999-2002, 2004-2011 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without warranty of any kind. Basic Installation ================== Briefly, the shell commands `./configure; make; make install' should configure, build, and install this package. The following more-detailed instructions are generic; see the `README' file for instructions specific to this package. Some packages provide this `INSTALL' file but do not implement all of the features documented below. The lack of an optional feature in a given package is not necessarily a bug. More recommendations for GNU packages can be found in *note Makefile Conventions: (standards)Makefile Conventions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves the results of its tests to speed up reconfiguring. Caching is disabled by default to prevent problems with accidental use of stale cache files. If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If you are using the cache, and at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.ac' (or `configure.in') is used to create `configure' by a program called `autoconf'. You need `configure.ac' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. Running `configure' might take a while. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package, generally using the just-built uninstalled binaries. 4. Type `make install' to install the programs and any data files and documentation. When installing into a prefix owned by root, it is recommended that the package be configured and built as a regular user, and only the `make install' phase executed with root privileges. 5. Optionally, type `make installcheck' to repeat any self-tests, but this time using the binaries in their final installed location. This target does not install anything. Running this target as a regular user, particularly if the prior `make install' required root privileges, verifies that the installation completed correctly. 6. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. 7. Often, you can also type `make uninstall' to remove the installed files again. In practice, not all packages have tested that uninstallation works correctly, even though it is required by the GNU Coding Standards. 8. Some packages, particularly those that use Automake, provide `make distcheck', which can by used by developers to test that all other targets like `make install' and `make uninstall' work correctly. This target is generally not run by end users. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. Run `./configure --help' for details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c99 CFLAGS=-g LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you can use GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. This is known as a "VPATH" build. With a non-GNU `make', it is safer to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. On MacOS X 10.5 and later systems, you can create libraries and executables that work on multiple system types--known as "fat" or "universal" binaries--by specifying multiple `-arch' options to the compiler but only a single `-arch' option to the preprocessor. Like this: ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CPP="gcc -E" CXXCPP="g++ -E" This is not guaranteed to produce working output in all cases, you may have to build one architecture at a time and combine the results using the `lipo' tool if you have problems. Installation Names ================== By default, `make install' installs the package's commands under `/usr/local/bin', include files under `/usr/local/include', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PREFIX', where PREFIX must be an absolute file name. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you pass the option `--exec-prefix=PREFIX' to `configure', the package uses PREFIX as the prefix for installing programs and libraries. Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=DIR' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. In general, the default for these options is expressed in terms of `${prefix}', so that specifying just `--prefix' will affect all of the other directory specifications that were not explicitly provided. The most portable way to affect installation locations is to pass the correct locations to `configure'; however, many packages provide one or both of the following shortcuts of passing variable assignments to the `make install' command line to change installation locations without having to reconfigure or recompile. The first method involves providing an override variable for each affected directory. For example, `make install prefix=/alternate/directory' will choose an alternate location for all directory configuration variables that were expressed in terms of `${prefix}'. Any directories that were specified during `configure', but not in terms of `${prefix}', must each be overridden at install time for the entire installation to be relocated. The approach of makefile variable overrides for each directory variable is required by the GNU Coding Standards, and ideally causes no recompilation. However, some platforms have known limitations with the semantics of shared libraries that end up requiring recompilation when using this method, particularly noticeable in packages that use GNU Libtool. The second method involves providing the `DESTDIR' variable. For example, `make install DESTDIR=/alternate/directory' will prepend `/alternate/directory' before all installation names. The approach of `DESTDIR' overrides is not required by the GNU Coding Standards, and does not work on platforms that have drive letters. On the other hand, it does better at avoiding recompilation issues, and works well even when some directory options were not specified in terms of `${prefix}' at `configure' time. Optional Features ================= If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Some packages offer the ability to configure how verbose the execution of `make' will be. For these packages, running `./configure --enable-silent-rules' sets the default to minimal output, which can be overridden with `make V=1'; while running `./configure --disable-silent-rules' sets the default to verbose, which can be overridden with `make V=0'. Particular systems ================== On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC is not installed, it is recommended to use the following options in order to use an ANSI C compiler: ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" and if that doesn't work, install pre-built binaries of GCC for HP-UX. HP-UX `make' updates targets which have the same time stamps as their prerequisites, which makes it generally unusable when shipped generated files such as `configure' are involved. Use GNU `make' instead. On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot parse its `' header file. The option `-nodtk' can be used as a workaround. If GNU CC is not installed, it is therefore recommended to try ./configure CC="cc" and if that doesn't work, try ./configure CC="cc -nodtk" On Solaris, don't put `/usr/ucb' early in your `PATH'. This directory contains several dysfunctional programs; working variants of these programs are available in `/usr/bin'. So, if you need `/usr/ucb' in your `PATH', put it _after_ `/usr/bin'. On Haiku, software installed for all users goes in `/boot/common', not `/usr/local'. It is recommended to use the following options: ./configure --prefix=/boot/common Specifying the System Type ========================== There may be some features `configure' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the _same_ architectures, `configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should use the option `--target=TYPE' to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will eventually be run) with `--host=TYPE'. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Defining Variables ================== Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc causes the specified `gcc' to be used as the C compiler (unless it is overridden in the site shell script). Unfortunately, this technique does not work for `CONFIG_SHELL' due to an Autoconf bug. Until the bug is fixed you can use this workaround: CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash `configure' Invocation ====================== `configure' recognizes the following options to control how it operates. `--help' `-h' Print a summary of all of the options to `configure', and exit. `--help=short' `--help=recursive' Print a summary of the options unique to this package's `configure', and exit. The `short' variant lists options used only in the top level, while the `recursive' variant lists options also present in any nested packages. `--version' `-V' Print the version of Autoconf used to generate the `configure' script, and exit. `--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally `config.cache'. FILE defaults to `/dev/null' to disable caching. `--config-cache' `-C' Alias for `--cache-file=config.cache'. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `--prefix=DIR' Use DIR as the installation prefix. *note Installation Names:: for more details, including other options available for fine-tuning the installation locations. `--no-create' `-n' Run the configure checks, but stop before creating any output files. `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. kimchi-1.5.0/Makefile.am000066400000000000000000000125411254252253000150200ustar00rootroot00000000000000# # Kimchi # # Copyright IBM Corp, 2013 # # 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 SUBDIRS = src ui docs contrib tests po config plugins man_MANS = docs/kimchid.8 AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = --install -I m4 EXTRA_DIST = \ config.rpath \ autogen.sh \ COPYING.ASL2 \ COPYING.LGPL \ CONTRIBUTE.md \ VERSION \ build-aux/pkg-version \ $(NULL) PEP8_BLACKLIST = *src/kimchi/config.py,*src/kimchi/i18n.py,*tests/test_config.py SKIP_PYFLAKES_ERR = "\./src/kimchi/websocket\.py" I18N_FILES = plugins/*/i18n.py \ src/kimchi/i18n.py \ $(NULL) check-local: PYTHONPATH=src contrib/check_i18n.py $(I18N_FILES) find . -path './.git' -prune -type f -o \ -name '*.py' -o -name '*.py.in' | xargs $(PYFLAKES) | \ grep -w -v $(SKIP_PYFLAKES_ERR) | \ while read LINE; do echo "$$LINE"; false; done $(PEP8) --version $(PEP8) --filename '*.py,*.py.in' --exclude="$(PEP8_BLACKLIST)" . # Link built mo files in the source tree to enable use of translations from # within the source tree all-local: while read L && test -n "$$L"; do \ dir=mo/$$L/LC_MESSAGES ; \ $(MKDIR_P) $$dir ; \ ln -sf ../../../po/$$L.gmo $$dir/kimchi.mo ; \ done < po/LINGUAS # # Packaging helpers # install-deb: install cp -R $(top_srcdir)/contrib/DEBIAN $(DESTDIR)/ mkdir -p $(DESTDIR)/var/lib/kimchi/debugreports mkdir -p $(DESTDIR)/var/lib/kimchi/screenshots mkdir -p $(DESTDIR)/var/lib/kimchi/vnc-tokens mkdir -p $(DESTDIR)/var/lib/kimchi/isos touch $(DESTDIR)/var/lib/kimchi/objectstore $(MKDIR_P) $(DESTDIR)/etc/init $(MKDIR_P) $(DESTDIR)/usr/lib/firewalld/services cp -R $(top_srcdir)/contrib/kimchid-upstart.conf.debian \ $(DESTDIR)/etc/init/kimchid.conf cp -R $(top_srcdir)/src/firewalld.xml \ $(DESTDIR)/usr/lib/firewalld/services/kimchid.xml deb: contrib/make-deb.sh $(top_srcdir)/contrib/make-deb.sh kimchi.spec: contrib/kimchi.spec.fedora contrib/kimchi.spec.suse @if test -e /etc/redhat-release; then \ ln -sf contrib/kimchi.spec.fedora $@ ; \ elif test -e /etc/SuSE-release; then \ ln -sf contrib/kimchi.spec.suse $@ ; \ else \ echo "Unable to select a spec file for RPM build" ; \ /bin/false ; \ fi rpm: dist kimchi.spec $(MKDIR_P) rpm/BUILD rpm/RPMS rpm/SOURCES rpm/SPECS rpm/SRPMS cp $(top_srcdir)/kimchi.spec rpm/SPECS/kimchi.spec cp $(DIST_ARCHIVES) rpm/SOURCES rpmbuild -ba --define "_topdir `pwd`/rpm" rpm/SPECS/kimchi.spec fedora-rpm: contrib/kimchi.spec.fedora ln -sf contrib/kimchi.spec.fedora kimchi.spec $(MAKE) rpm suse-rpm: contrib/kimchi.spec.suse ln -sf contrib/kimchi.spec.suse kimchi.spec $(MAKE) rpm ChangeLog: @if test -d .git; then \ $(top_srcdir)/build-aux/genChangelog --release > $@; \ fi install-data-local: @if test -d $(systemdsystemunitdir) ; then \ mkdir -p $(DESTDIR)/$(systemdsystemunitdir); \ $(INSTALL_DATA) contrib/kimchid.service.fedora $(DESTDIR)/$(systemdsystemunitdir)/kimchid.service; \ else \ mkdir -p $(DESTDIR)/etc/init.d/ \ $(INSTALL_DATA) contrib/kimchid.sysvinit $(DESTDIR)/etc/init.d/kimchid; \ chmod +x $(DESTDIR)/etc/init.d/kimchid; \ fi; \ if test -d /usr/lib/firewalld/services/; then \ mkdir -p $(DESTDIR)/usr/lib/firewalld/services/; \ $(INSTALL_DATA) src/firewalld.xml $(DESTDIR)/usr/lib/firewalld/services/kimchid.xml; \ fi; \ mkdir -p $(DESTDIR)/var/lib/kimchi/{debugreports,screenshots,vnc-tokens,isos} touch $(DESTDIR)/var/lib/kimchi/objectstore mkdir -p $(DESTDIR)/var/log/kimchi/ touch $(DESTDIR)/var/log/kimchi/kimchi-access.log touch $(DESTDIR)/var/log/kimchi/kimchi-error.log mkdir -p $(DESTDIR)/etc/kimchi/ $(INSTALL_DATA) src/dhparams.pem $(DESTDIR)/etc/kimchi/dhparams.pem touch $(DESTDIR)/etc/nginx/conf.d/kimchi.conf uninstall-local: @if test -f $(systemdsystemunitdir)/kimchid.service; then \ $(RM) $(DESTDIR)/$(systemdsystemunitdir)/kimchid.service; \ elif test -f /etc/init.d/kimchid; then \ $(RM) $(DESTDIR)/etc/init.d/kimchid; \ $(RM) $(DESTDIR)/etc/init/kimchi.conf; \ fi; \ if test -d /usr/lib/firewalld/services/; then \ $(RM) $(DESTDIR)/usr/lib/firewalld/services/kimchid.xml; \ fi; \ $(RM) -rf $(DESTDIR)/var/lib/kimchi $(RM) -rf $(DESTDIR)/var/log/kimchi $(RM) -rf $(DESTDIR)/etc/kimchi $(RM) $(DESTDIR)/etc/nginx/conf.d/kimchi.conf VERSION: @if test -d .git; then \ git describe --abbrev=0 > $@; \ fi .PHONY: deb install-deb rpm fedora-rpm suse-rpm ChangeLog VERSION clean-local: rm -rf mo rpm CLEANFILES = kimchi.spec `find "$(top_srcdir)" -type f -name "*.pyc" -print` kimchi-1.5.0/NEWS000066400000000000000000000000001254252253000134460ustar00rootroot00000000000000kimchi-1.5.0/README.md000077700000000000000000000000001254252253000164422docs/README.mdustar00rootroot00000000000000kimchi-1.5.0/VERSION000066400000000000000000000000061254252253000140250ustar00rootroot000000000000001.5.0 kimchi-1.5.0/autogen.sh000077500000000000000000000007231254252253000147640ustar00rootroot00000000000000#!/bin/bash aclocal automake --add-missing autoreconf if [ ! -f "configure" ]; then echo "Failed to generate configure script. Check to make sure autoconf, " echo "automake, and other build dependencies are properly installed." exit 1 fi if [ "x$1" == "x--system" ]; then ./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var else if [ $# -gt 0 ]; then ./configure $@ else ./configure --prefix=/usr/local fi fi kimchi-1.5.0/build-aux/000077500000000000000000000000001254252253000146535ustar00rootroot00000000000000kimchi-1.5.0/build-aux/config.rpath000066400000000000000000000440121254252253000171610ustar00rootroot00000000000000#! /bin/sh # Output a system dependent set of variables, describing how to set the # run time search path of shared libraries in an executable. # # Copyright 1996-2010 Free Software Foundation, Inc. # Taken from GNU libtool, 2001 # Originally by Gordon Matzigkeit , 1996 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # # The first argument passed to this file is the canonical host specification, # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # The environment variables CC, GCC, LDFLAGS, LD, with_gnu_ld # should be set by the caller. # # The set of defined variables is at the end of this script. # Known limitations: # - On IRIX 6.5 with CC="cc", the run time search patch must not be longer # than 256 bytes, otherwise the compiler driver will dump core. The only # known workaround is to choose shorter directory names for the build # directory and/or the installation directory. # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a shrext=.so host="$1" host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` # Code taken from libtool.m4's _LT_CC_BASENAME. for cc_temp in $CC""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`echo "$cc_temp" | sed -e 's%^.*/%%'` # Code taken from libtool.m4's _LT_COMPILER_PIC. wl= if test "$GCC" = yes; then wl='-Wl,' else case "$host_os" in aix*) wl='-Wl,' ;; darwin*) case $cc_basename in xlc*) wl='-Wl,' ;; esac ;; mingw* | cygwin* | pw32* | os2* | cegcc*) ;; hpux9* | hpux10* | hpux11*) wl='-Wl,' ;; irix5* | irix6* | nonstopux*) wl='-Wl,' ;; newsos6) ;; linux* | k*bsd*-gnu) case $cc_basename in ecc*) wl='-Wl,' ;; icc* | ifort*) wl='-Wl,' ;; lf95*) wl='-Wl,' ;; pgcc | pgf77 | pgf90) wl='-Wl,' ;; ccc*) wl='-Wl,' ;; como) wl='-lopt=' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) wl='-Wl,' ;; esac ;; esac ;; osf3* | osf4* | osf5*) wl='-Wl,' ;; rdos*) ;; solaris*) wl='-Wl,' ;; sunos4*) wl='-Qoption ld ' ;; sysv4 | sysv4.2uw2* | sysv4.3*) wl='-Wl,' ;; sysv4*MP*) ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) wl='-Wl,' ;; unicos*) wl='-Wl,' ;; uts4*) ;; esac fi # Code taken from libtool.m4's _LT_LINKER_SHLIBS. hardcode_libdir_flag_spec= hardcode_libdir_separator= hardcode_direct=no hardcode_minus_L=no case "$host_os" in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; esac ld_shlibs=yes if test "$with_gnu_ld" = yes; then # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. # Unlike libtool, we use -rpath here, not --rpath, since the documented # option of GNU ld is called -rpath, not --rpath. hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' case "$host_os" in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs=no fi ;; amigaos*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # Samuel A. Falvo II reports # that the semantics of dynamic libraries on AmigaOS, at least up # to version 4, is to share data among multiple programs linked # with the same dynamic library. Since this doesn't match the # behavior of shared libraries on other platforms, we cannot use # them. ld_shlibs=no ;; beos*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then : else ld_shlibs=no fi ;; interix[3-9]*) hardcode_direct=no hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; gnu* | linux* | k*bsd*-gnu) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; netbsd*) ;; solaris*) if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then ld_shlibs=no elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs=no ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' else ld_shlibs=no fi ;; esac ;; sunos4*) hardcode_direct=yes ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; esac if test "$ld_shlibs" = no; then hardcode_libdir_flag_spec= fi else case "$host_os" in aix3*) # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test "$GCC" = yes; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix[4-9]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac fi hardcode_direct=yes hardcode_libdir_separator=':' if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct=unsupported hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi ;; esac fi # Begin _LT_AC_SYS_LIBPATH_AIX. echo 'int main () { return 0; }' > conftest.c ${CC} ${LDFLAGS} conftest.c -o conftest aix_libpath=`dump -H conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` fi if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib" fi rm -f conftest.c conftest # End _LT_AC_SYS_LIBPATH_AIX. if test "$aix_use_runtimelinking" = yes; then hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' else hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" fi fi ;; amigaos*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # see comment about different semantics on the GNU ld section ld_shlibs=no ;; bsdi[45]*) ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec=' ' libext=lib ;; darwin* | rhapsody*) hardcode_direct=no if test "$GCC" = yes ; then : else case $cc_basename in xlc*) ;; *) ld_shlibs=no ;; esac fi ;; dgux*) hardcode_libdir_flag_spec='-L$libdir' ;; freebsd1*) ld_shlibs=no ;; freebsd2.2*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; freebsd2*) hardcode_direct=yes hardcode_minus_L=yes ;; freebsd* | dragonfly*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; hpux9*) hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; hpux10*) if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes fi ;; hpux11*) if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: case $host_cpu in hppa*64*|ia64*) hardcode_direct=no ;; *) hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; netbsd*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; newsos6) hardcode_direct=yes hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; openbsd*) if test -f /usr/libexec/ld.so; then hardcode_direct=yes if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then hardcode_libdir_flag_spec='${wl}-rpath,$libdir' else case "$host_os" in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) hardcode_libdir_flag_spec='-R$libdir' ;; *) hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; esac fi else ld_shlibs=no fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; osf3*) hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) if test "$GCC" = yes; then hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else # Both cc and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi hardcode_libdir_separator=: ;; solaris*) hardcode_libdir_flag_spec='-R$libdir' ;; sunos4*) hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes ;; sysv4) case $host_vendor in sni) hardcode_direct=yes # is this really true??? ;; siemens) hardcode_direct=no ;; motorola) hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac ;; sysv4.3*) ;; sysv4*MP*) if test -d /usr/nec; then ld_shlibs=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) ;; sysv5* | sco3.2v5* | sco5v6*) hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' hardcode_libdir_separator=':' ;; uts4*) hardcode_libdir_flag_spec='-L$libdir' ;; *) ld_shlibs=no ;; esac fi # Check dynamic linker characteristics # Code taken from libtool.m4's _LT_SYS_DYNAMIC_LINKER. # Unlike libtool.m4, here we don't care about _all_ names of the library, but # only about the one the linker finds when passed -lNAME. This is the last # element of library_names_spec in libtool.m4, or possibly two of them if the # linker has special search rules. library_names_spec= # the last element of library_names_spec in libtool.m4 libname_spec='lib$name' case "$host_os" in aix3*) library_names_spec='$libname.a' ;; aix[4-9]*) library_names_spec='$libname$shrext' ;; amigaos*) library_names_spec='$libname.a' ;; beos*) library_names_spec='$libname$shrext' ;; bsdi[45]*) library_names_spec='$libname$shrext' ;; cygwin* | mingw* | pw32* | cegcc*) shrext=.dll library_names_spec='$libname.dll.a $libname.lib' ;; darwin* | rhapsody*) shrext=.dylib library_names_spec='$libname$shrext' ;; dgux*) library_names_spec='$libname$shrext' ;; freebsd1*) ;; freebsd* | dragonfly*) case "$host_os" in freebsd[123]*) library_names_spec='$libname$shrext$versuffix' ;; *) library_names_spec='$libname$shrext' ;; esac ;; gnu*) library_names_spec='$libname$shrext' ;; hpux9* | hpux10* | hpux11*) case $host_cpu in ia64*) shrext=.so ;; hppa*64*) shrext=.sl ;; *) shrext=.sl ;; esac library_names_spec='$libname$shrext' ;; interix[3-9]*) library_names_spec='$libname$shrext' ;; irix5* | irix6* | nonstopux*) library_names_spec='$libname$shrext' case "$host_os" in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= ;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 ;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 ;; *) libsuff= shlibsuff= ;; esac ;; esac ;; linux*oldld* | linux*aout* | linux*coff*) ;; linux* | k*bsd*-gnu) library_names_spec='$libname$shrext' ;; knetbsd*-gnu) library_names_spec='$libname$shrext' ;; netbsd*) library_names_spec='$libname$shrext' ;; newsos6) library_names_spec='$libname$shrext' ;; nto-qnx*) library_names_spec='$libname$shrext' ;; openbsd*) library_names_spec='$libname$shrext$versuffix' ;; os2*) libname_spec='$name' shrext=.dll library_names_spec='$libname.a' ;; osf3* | osf4* | osf5*) library_names_spec='$libname$shrext' ;; rdos*) ;; solaris*) library_names_spec='$libname$shrext' ;; sunos4*) library_names_spec='$libname$shrext$versuffix' ;; sysv4 | sysv4.3*) library_names_spec='$libname$shrext' ;; sysv4*MP*) library_names_spec='$libname$shrext' ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) library_names_spec='$libname$shrext' ;; uts4*) library_names_spec='$libname$shrext' ;; esac sed_quote_subst='s/\(["`$\\]\)/\\\1/g' escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"` shlibext=`echo "$shrext" | sed -e 's,^\.,,'` escaped_libname_spec=`echo "X$libname_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` escaped_library_names_spec=`echo "X$library_names_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` LC_ALL=C sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' < 4.9.0 (upstream clean) # - 4.9.0-1 => 4.9.0 (downstream clean) # - 4.9.0-2-g34e62f => 4.9.0 (upstream dirty) # - 4.9.0-1-2-g34e62f => 4.9.0 (downstream dirty) AWK_VERSION=' BEGIN { FS="-" } /^[0-9]/ { print $1 }' # tags and output releases: # - 4.9.0 => 0 (upstream clean) # - 4.9.0-1 => 1 (downstream clean) # - 4.9.0-2-g34e62f1 => 2.git34e62f1 (upstream dirty) # - 4.9.0-1-2-g34e62f1 => 1.2.git34e62f1 (downstream dirty) AWK_RELEASE=' BEGIN { FS="-"; OFS="." } /^[0-9]/ { if (NF == 1) print 0 else if (NF == 2) print $2 else if (NF == 3) print $2, "git" substr($3, 2) else if (NF == 4) print $2, $3, "git" substr($4, 2) }' if [ ! -d .git ]; then PKG_VERSION=`cat VERSION` else PKG_VERSION=`git describe --tags --match "[0-9]*" || cat VERSION` fi if test "x$1" = "x--full"; then echo $PKG_VERSION | tr -d '[:space:]' elif test "x$1" = "x--version"; then echo $PKG_VERSION | awk "$AWK_VERSION" | tr -cd '[:alnum:].' elif test "x$1" = "x--release"; then echo $PKG_VERSION | awk "$AWK_RELEASE" | tr -cd '[:alnum:].' else echo "usage: $0 [--full|--version|--release]" exit 1 fi kimchi-1.5.0/config.rpath000066400000000000000000000440121254252253000152670ustar00rootroot00000000000000#! /bin/sh # Output a system dependent set of variables, describing how to set the # run time search path of shared libraries in an executable. # # Copyright 1996-2010 Free Software Foundation, Inc. # Taken from GNU libtool, 2001 # Originally by Gordon Matzigkeit , 1996 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # # The first argument passed to this file is the canonical host specification, # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # The environment variables CC, GCC, LDFLAGS, LD, with_gnu_ld # should be set by the caller. # # The set of defined variables is at the end of this script. # Known limitations: # - On IRIX 6.5 with CC="cc", the run time search patch must not be longer # than 256 bytes, otherwise the compiler driver will dump core. The only # known workaround is to choose shorter directory names for the build # directory and/or the installation directory. # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a shrext=.so host="$1" host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` # Code taken from libtool.m4's _LT_CC_BASENAME. for cc_temp in $CC""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`echo "$cc_temp" | sed -e 's%^.*/%%'` # Code taken from libtool.m4's _LT_COMPILER_PIC. wl= if test "$GCC" = yes; then wl='-Wl,' else case "$host_os" in aix*) wl='-Wl,' ;; darwin*) case $cc_basename in xlc*) wl='-Wl,' ;; esac ;; mingw* | cygwin* | pw32* | os2* | cegcc*) ;; hpux9* | hpux10* | hpux11*) wl='-Wl,' ;; irix5* | irix6* | nonstopux*) wl='-Wl,' ;; newsos6) ;; linux* | k*bsd*-gnu) case $cc_basename in ecc*) wl='-Wl,' ;; icc* | ifort*) wl='-Wl,' ;; lf95*) wl='-Wl,' ;; pgcc | pgf77 | pgf90) wl='-Wl,' ;; ccc*) wl='-Wl,' ;; como) wl='-lopt=' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) wl='-Wl,' ;; esac ;; esac ;; osf3* | osf4* | osf5*) wl='-Wl,' ;; rdos*) ;; solaris*) wl='-Wl,' ;; sunos4*) wl='-Qoption ld ' ;; sysv4 | sysv4.2uw2* | sysv4.3*) wl='-Wl,' ;; sysv4*MP*) ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) wl='-Wl,' ;; unicos*) wl='-Wl,' ;; uts4*) ;; esac fi # Code taken from libtool.m4's _LT_LINKER_SHLIBS. hardcode_libdir_flag_spec= hardcode_libdir_separator= hardcode_direct=no hardcode_minus_L=no case "$host_os" in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; esac ld_shlibs=yes if test "$with_gnu_ld" = yes; then # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. # Unlike libtool, we use -rpath here, not --rpath, since the documented # option of GNU ld is called -rpath, not --rpath. hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' case "$host_os" in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs=no fi ;; amigaos*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # Samuel A. Falvo II reports # that the semantics of dynamic libraries on AmigaOS, at least up # to version 4, is to share data among multiple programs linked # with the same dynamic library. Since this doesn't match the # behavior of shared libraries on other platforms, we cannot use # them. ld_shlibs=no ;; beos*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then : else ld_shlibs=no fi ;; interix[3-9]*) hardcode_direct=no hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; gnu* | linux* | k*bsd*-gnu) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; netbsd*) ;; solaris*) if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then ld_shlibs=no elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs=no ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' else ld_shlibs=no fi ;; esac ;; sunos4*) hardcode_direct=yes ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; esac if test "$ld_shlibs" = no; then hardcode_libdir_flag_spec= fi else case "$host_os" in aix3*) # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test "$GCC" = yes; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix[4-9]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac fi hardcode_direct=yes hardcode_libdir_separator=':' if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct=unsupported hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi ;; esac fi # Begin _LT_AC_SYS_LIBPATH_AIX. echo 'int main () { return 0; }' > conftest.c ${CC} ${LDFLAGS} conftest.c -o conftest aix_libpath=`dump -H conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` fi if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib" fi rm -f conftest.c conftest # End _LT_AC_SYS_LIBPATH_AIX. if test "$aix_use_runtimelinking" = yes; then hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' else hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" fi fi ;; amigaos*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # see comment about different semantics on the GNU ld section ld_shlibs=no ;; bsdi[45]*) ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec=' ' libext=lib ;; darwin* | rhapsody*) hardcode_direct=no if test "$GCC" = yes ; then : else case $cc_basename in xlc*) ;; *) ld_shlibs=no ;; esac fi ;; dgux*) hardcode_libdir_flag_spec='-L$libdir' ;; freebsd1*) ld_shlibs=no ;; freebsd2.2*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; freebsd2*) hardcode_direct=yes hardcode_minus_L=yes ;; freebsd* | dragonfly*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; hpux9*) hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; hpux10*) if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes fi ;; hpux11*) if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: case $host_cpu in hppa*64*|ia64*) hardcode_direct=no ;; *) hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; netbsd*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; newsos6) hardcode_direct=yes hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; openbsd*) if test -f /usr/libexec/ld.so; then hardcode_direct=yes if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then hardcode_libdir_flag_spec='${wl}-rpath,$libdir' else case "$host_os" in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) hardcode_libdir_flag_spec='-R$libdir' ;; *) hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; esac fi else ld_shlibs=no fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; osf3*) hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) if test "$GCC" = yes; then hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else # Both cc and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi hardcode_libdir_separator=: ;; solaris*) hardcode_libdir_flag_spec='-R$libdir' ;; sunos4*) hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes ;; sysv4) case $host_vendor in sni) hardcode_direct=yes # is this really true??? ;; siemens) hardcode_direct=no ;; motorola) hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac ;; sysv4.3*) ;; sysv4*MP*) if test -d /usr/nec; then ld_shlibs=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) ;; sysv5* | sco3.2v5* | sco5v6*) hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' hardcode_libdir_separator=':' ;; uts4*) hardcode_libdir_flag_spec='-L$libdir' ;; *) ld_shlibs=no ;; esac fi # Check dynamic linker characteristics # Code taken from libtool.m4's _LT_SYS_DYNAMIC_LINKER. # Unlike libtool.m4, here we don't care about _all_ names of the library, but # only about the one the linker finds when passed -lNAME. This is the last # element of library_names_spec in libtool.m4, or possibly two of them if the # linker has special search rules. library_names_spec= # the last element of library_names_spec in libtool.m4 libname_spec='lib$name' case "$host_os" in aix3*) library_names_spec='$libname.a' ;; aix[4-9]*) library_names_spec='$libname$shrext' ;; amigaos*) library_names_spec='$libname.a' ;; beos*) library_names_spec='$libname$shrext' ;; bsdi[45]*) library_names_spec='$libname$shrext' ;; cygwin* | mingw* | pw32* | cegcc*) shrext=.dll library_names_spec='$libname.dll.a $libname.lib' ;; darwin* | rhapsody*) shrext=.dylib library_names_spec='$libname$shrext' ;; dgux*) library_names_spec='$libname$shrext' ;; freebsd1*) ;; freebsd* | dragonfly*) case "$host_os" in freebsd[123]*) library_names_spec='$libname$shrext$versuffix' ;; *) library_names_spec='$libname$shrext' ;; esac ;; gnu*) library_names_spec='$libname$shrext' ;; hpux9* | hpux10* | hpux11*) case $host_cpu in ia64*) shrext=.so ;; hppa*64*) shrext=.sl ;; *) shrext=.sl ;; esac library_names_spec='$libname$shrext' ;; interix[3-9]*) library_names_spec='$libname$shrext' ;; irix5* | irix6* | nonstopux*) library_names_spec='$libname$shrext' case "$host_os" in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= ;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 ;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 ;; *) libsuff= shlibsuff= ;; esac ;; esac ;; linux*oldld* | linux*aout* | linux*coff*) ;; linux* | k*bsd*-gnu) library_names_spec='$libname$shrext' ;; knetbsd*-gnu) library_names_spec='$libname$shrext' ;; netbsd*) library_names_spec='$libname$shrext' ;; newsos6) library_names_spec='$libname$shrext' ;; nto-qnx*) library_names_spec='$libname$shrext' ;; openbsd*) library_names_spec='$libname$shrext$versuffix' ;; os2*) libname_spec='$name' shrext=.dll library_names_spec='$libname.a' ;; osf3* | osf4* | osf5*) library_names_spec='$libname$shrext' ;; rdos*) ;; solaris*) library_names_spec='$libname$shrext' ;; sunos4*) library_names_spec='$libname$shrext$versuffix' ;; sysv4 | sysv4.3*) library_names_spec='$libname$shrext' ;; sysv4*MP*) library_names_spec='$libname$shrext' ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) library_names_spec='$libname$shrext' ;; uts4*) library_names_spec='$libname$shrext' ;; esac sed_quote_subst='s/\(["`$\\]\)/\\\1/g' escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"` shlibext=`echo "$shrext" | sed -e 's,^\.,,'` escaped_libname_spec=`echo "X$libname_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` escaped_library_names_spec=`echo "X$library_names_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` LC_ALL=C sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' < Host tabs/host.html Guests tabs/guests.html Templates tabs/templates.html Storage tabs/storage.html Network tabs/network.html kimchi-1.5.0/configure.ac000066400000000000000000000103021254252253000152430ustar00rootroot00000000000000# # Kimchi # # Copyright IBM Corp, 2013-2015 # # 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 AC_INIT([kimchi], [m4_esyscmd([./build-aux/pkg-version --version])]) AC_SUBST([PACKAGE_VERSION], [m4_esyscmd([./build-aux/pkg-version --version])]) AC_SUBST([PACKAGE_RELEASE], [m4_esyscmd([./build-aux/pkg-version --release])]) # Testing for version and release AS_IF([test "x$PACKAGE_VERSION" = x], AC_MSG_ERROR([package version not defined])) AS_IF([test "x$PACKAGE_RELEASE" = x], AC_MSG_ERROR([package release not defined])) AC_CONFIG_AUX_DIR([build-aux]) AM_INIT_AUTOMAKE([-Wno-portability]) AM_PATH_PYTHON([2.6]) AC_PATH_PROG([PEP8], [pep8], [/usr/bin/pep8]) AC_PYTHON_MODULE([unittest]) AC_SUBST([HAVE_PYMOD_UNITTEST]) AC_SUBST([PYTHON_VERSION]) AM_GNU_GETTEXT([external]) AM_GNU_GETTEXT_VERSION([0.10]) AC_PATH_PROG([CHEETAH], [cheetah], [/usr/bin/cheetah]) # Checking for pyflakes AC_PATH_PROG([PYFLAKES], [pyflakes]) if test "x$PYFLAKES" = "x"; then AC_MSG_WARN([pyflakes not found]) fi AC_ARG_ENABLE( [sample], [AS_HELP_STRING( [--enable-sample], [enable sample plugin @<:@default=no@:>@] )], , [enable_sample="no"] ) if test "${enable_sample}" = "yes"; then AC_SUBST([ENABLE_SAMPLE], [True]) else AC_SUBST([ENABLE_SAMPLE], [False]) fi # check for systemd PKG_PROG_PKG_CONFIG AC_ARG_WITH([systemdsystemunitdir], AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]), [], [with_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)]) if test "x$with_systemdsystemunitdir" != xno; then AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir]) fi AC_ARG_WITH( [spice-html5], [AS_HELP_STRING([--with-spice-html5], [Build Kimchi with spice-html5 @<:@default=no@:>@])], , [with_spice_html5="no"] ) AM_CONDITIONAL([WITH_SPICE], [test "x$with_spice_html5" = xyes]) AC_CONFIG_FILES([ po/Makefile.in po/gen-pot Makefile docs/Makefile docs/kimchid.8 src/Makefile src/distros.d/Makefile src/nginx/Makefile src/kimchi/Makefile src/kimchi/control/Makefile src/kimchi/control/vm/Makefile src/kimchi/model/Makefile src/kimchi/xmlutils/Makefile plugins/Makefile plugins/sample/Makefile plugins/sample/po/Makefile.in plugins/sample/sample.conf plugins/sample/ui/Makefile plugins/sample/ui/config/Makefile plugins/sample/ui/js/Makefile plugins/sample/ui/pages/Makefile ui/Makefile ui/css/Makefile ui/images/Makefile ui/images/theme-default/Makefile ui/js/Makefile ui/spice-html5/Makefile ui/spice-html5/css/Makefile ui/spice-html5/pages/Makefile ui/spice-html5/thirdparty/Makefile ui/libs/Makefile ui/libs/themes/Makefile ui/libs/themes/base/Makefile ui/libs/themes/base/images/Makefile ui/pages/Makefile ui/pages/help/Makefile ui/pages/help/en_US/Makefile ui/pages/help/de_DE/Makefile ui/pages/help/es_ES/Makefile ui/pages/help/fr_FR/Makefile ui/pages/help/it_IT/Makefile ui/pages/help/ja_JP/Makefile ui/pages/help/ko_KR/Makefile ui/pages/help/pt_BR/Makefile ui/pages/help/ru_RU/Makefile ui/pages/help/zh_CN/Makefile ui/pages/help/zh_TW/Makefile ui/pages/tabs/Makefile ui/pages/websockify/Makefile contrib/Makefile contrib/DEBIAN/Makefile contrib/DEBIAN/control contrib/kimchi.spec.fedora contrib/kimchi.spec.suse tests/Makefile config/Makefile config/ui/Makefile ],[ chmod +x po/gen-pot ]) AC_OUTPUT kimchi-1.5.0/contrib/000077500000000000000000000000001254252253000144215ustar00rootroot00000000000000kimchi-1.5.0/contrib/DEBIAN/000077500000000000000000000000001254252253000153435ustar00rootroot00000000000000kimchi-1.5.0/contrib/DEBIAN/Makefile.am000066400000000000000000000014131254252253000173760ustar00rootroot00000000000000# Copyright IBM Corp, 2013 # # 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 CLEANFILES = control kimchi-1.5.0/contrib/DEBIAN/control.in000066400000000000000000000015571254252253000173630ustar00rootroot00000000000000Package: @PACKAGE_NAME@ Version: @PACKAGE_VERSION@ Section: base Priority: optional Architecture: all Depends: python-cherrypy3 (>= 3.2.0), python-cheetah, python-imaging, python-configobj, websockify, novnc, python-jsonschema (>= 1.3.0), python-libvirt, gettext, libvirt-bin, nfs-common, python-m2crypto, qemu-kvm, python-pam, python-parted, python-psutil (>= 0.6.0), python-ethtool, sosreport, python-ipaddr, python-lxml, open-iscsi, nginx, python-guestfs, python-ldap, libguestfs-tools, spice-html5 Build-Depends: libxslt, openssl, python-lxml Maintainer: Aline Manera Description: Kimchi web server kimchi-1.5.0/contrib/DEBIAN/postrm000077500000000000000000000017111254252253000166150ustar00rootroot00000000000000#!/bin/sh -e # # Project Kimchi # # Copyright IBM, Corp. 2013 # # 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 case "$1" in remove) rm -rf /var/log/kimchi /var/run/kimchi.pid ;; purge) rm -rf /var/log/kimchi /var/run/kimchi.pid /usr/share/kimchi/ ;; esac kimchi-1.5.0/contrib/Makefile.am000066400000000000000000000024711254252253000164610ustar00rootroot00000000000000# Copyright IBM Corp, 2013 # # 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 SUBDIRS = DEBIAN EXTRA_DIST = \ check_i18n.py \ kimchid.sysvinit \ kimchid.service.fedora \ kimchi.spec.fedora.in \ kimchid-upstart.conf.debian \ kimchid-upstart.conf.fedora \ make-deb.sh.in \ $(NULL) make-deb.sh: make-deb.sh.in $(top_builddir)/config.status $(AM_V_GEN)sed \ -e 's|[@]PACKAGE_VERSION[@]|$(PACKAGE_VERSION)|g' \ -e 's|[@]PACKAGE_RELEASE[@]|$(PACKAGE_RELEASE)|g' \ < $< > $@-t && \ chmod a+x $@-t && \ mv $@-t $@ BUILT_SOURCES = make-deb.sh CLEANFILES = kimchi.spec.fedora kimchi.spec.suse kimchi.spec make-deb.sh kimchi-1.5.0/contrib/check_i18n.py000077500000000000000000000054131254252253000167150ustar00rootroot00000000000000#!/usr/bin/env python2 # # Project Kimchi # # Copyright IBM, Corp. 2014-2015 # # 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 import imp import os import re import sys # Match all conversion specifier with mapping key PATTERN = re.compile(r'''%\([^)]+\) # Mapping key [#0\-+]? # Conversion flags (optional) (\d+|\*)? # Minimum field width (optional) (\.(\d+|\*))? # Precision (optional) [lLh]? # Length modifier (optional) [cdeEfFgGioursxX%] # Conversion type''', re.VERBOSE) BAD_PATTERN = re.compile(r"%\([^)]*?\)") def load_i18n_module(i18nfile): path = os.path.dirname(i18nfile) mname = i18nfile.replace("/", "_").rstrip(".py") mobj = imp.find_module("i18n", [path]) return imp.load_module(mname, *mobj) def check_string_formatting(messages): for k, v in messages.iteritems(): if BAD_PATTERN.findall(PATTERN.sub(" ", v)): print "bad i18n string formatting:" print " %s: %s" % (k, v) exit(1) def check_obsolete_messages(path, messages): def find_message_key(path, k): for root, dirs, files in os.walk(path): for f in files: fname = os.path.join(root, f) if (not fname.endswith("i18n.py") and fname.endswith(".py") or fname.endswith(".json")): with open(fname) as f: string = "".join(f.readlines()) if k in string: return True return False for k in messages.iterkeys(): if not find_message_key(path, k): print " %s is obsolete, it is no longer in use" % k exit(1) def main(): print "Checking for invalid i18n string..." for f in sys.argv[1:]: messages = load_i18n_module(f).messages check_string_formatting(messages) check_obsolete_messages(os.path.dirname(f), messages) print "Checking for invalid i18n string successfully" if __name__ == '__main__': main() kimchi-1.5.0/contrib/kimchi.spec.fedora.in000066400000000000000000000105271254252253000204120ustar00rootroot00000000000000Name: kimchi Version: @PACKAGE_VERSION@ Release: @PACKAGE_RELEASE@%{?dist} Summary: Kimchi server application BuildRoot: %{_topdir}/BUILD/%{name}-%{version}-%{release} BuildArch: noarch Group: System Environment/Base License: LGPL/ASL2 Source0: %{name}-%{version}.tar.gz Requires: qemu-kvm Requires: gettext-devel Requires: libvirt Requires: libvirt-python Requires: libvirt-daemon-config-network Requires: python-cherrypy >= 3.2.0 Requires: python-cheetah Requires: python-websockify Requires: python-configobj Requires: novnc Requires: m2crypto Requires: python-imaging Requires: PyPAM Requires: pyparted Requires: python-psutil >= 0.6.0 Requires: python-jsonschema >= 1.3.0 Requires: python-ethtool Requires: sos Requires: python-ipaddr Requires: python-lxml Requires: nfs-utils Requires: nginx Requires: iscsi-initiator-utils Requires: python-ldap Requires: python-libguestfs Requires: libguestfs-tools BuildRequires: libxslt BuildRequires: openssl BuildRequires: python-lxml %if 0%{?rhel} >= 6 || 0%{?fedora} >= 19 Requires: spice-html5 %endif %if 0%{?fedora} >= 15 || 0%{?rhel} >= 7 %global with_systemd 1 %endif %if 0%{?rhel} == 6 Requires: python-ordereddict Requires: python-imaging BuildRequires: python-unittest2 %endif %if 0%{?with_systemd} Requires: systemd Requires: firewalld Requires(post): systemd Requires(preun): systemd Requires(postun): systemd %endif %if 0%{?with_systemd} BuildRequires: systemd-units %endif %description Web server application to manage KVM/Qemu virtual machines %prep %setup %build %if 0%{?rhel} >= 6 || 0%{?fedora} >= 19 %configure %else %configure --with-spice-html5 %endif make %install rm -rf %{buildroot} make DESTDIR=%{buildroot} install %if 0%{?with_systemd} %endif %if 0%{?rhel} == 6 # Install the upstart script install -Dm 0755 contrib/kimchid-upstart.conf.fedora %{buildroot}/etc/init/kimchid.conf %endif %if 0%{?rhel} == 5 # Install the SysV init scripts install -Dm 0755 contrib/kimchid.sysvinit %{buildroot}%{_initrddir}/kimchid %endif %post if [ $1 -eq 1 ] ; then /bin/systemctl enable kimchid.service >/dev/null 2>&1 || : # Initial installation /bin/systemctl daemon-reload >/dev/null 2>&1 || : fi %preun if [ $1 -eq 0 ] ; then # Package removal, not upgrade /bin/systemctl --no-reload disable kimchid.service > /dev/null 2>&1 || : /bin/systemctl stop kimchid.service > /dev/null 2>&1 || : fi exit 0 %postun if [ "$1" -ge 1 ] ; then /bin/systemctl try-restart kimchid.service >/dev/null 2>&1 || : fi exit 0 %clean rm -rf $RPM_BUILD_ROOT %files %attr(-,root,root) %{_bindir}/kimchid %{python_sitelib}/kimchi/*.py* %{python_sitelib}/kimchi/control/*.py* %{python_sitelib}/kimchi/control/vm/*.py* %{python_sitelib}/kimchi/model/*.py* %{python_sitelib}/kimchi/xmlutils/*.py* %{python_sitelib}/kimchi/API.json %{python_sitelib}/kimchi/plugins/*.py* %{python_sitelib}/kimchi/ %{_datadir}/kimchi/doc/API.md %{_datadir}/kimchi/doc/README.md %{_datadir}/kimchi/doc/README-federation.md %{_datadir}/kimchi/doc/kimchi-guest.png %{_datadir}/kimchi/doc/kimchi-templates.png %{_prefix}/share/locale/*/LC_MESSAGES/kimchi.mo %{_datadir}/kimchi/config/ui/*.xml %{_datadir}/kimchi/ui/ %{_datadir}/kimchi %{_sysconfdir}/nginx/conf.d/kimchi.conf.in %{_sysconfdir}/nginx/conf.d/kimchi.conf %{_sysconfdir}/kimchi/kimchi.conf %{_sysconfdir}/kimchi/template.conf %{_sysconfdir}/kimchi/distros.d/debian.json %{_sysconfdir}/kimchi/distros.d/fedora.json %{_sysconfdir}/kimchi/distros.d/opensuse.json %{_sysconfdir}/kimchi/distros.d/ubuntu.json %{_sysconfdir}/kimchi/distros.d/gentoo.json %{_sysconfdir}/kimchi/ %{_sharedstatedir}/kimchi/debugreports/ %{_sharedstatedir}/kimchi/screenshots/ %{_sharedstatedir}/kimchi/vnc-tokens/ %{_sharedstatedir}/kimchi/isos/ %{_sharedstatedir}/kimchi/ %{_localstatedir}/log/kimchi/* %{_localstatedir}/log/kimchi/ %{_mandir}/man8/kimchid.8.gz %if 0%{?with_systemd} %{_unitdir}/kimchid.service %{_prefix}/lib/firewalld/services/kimchid.xml %endif %if 0%{?rhel} == 6 /etc/init/kimchid.conf %endif %if 0%{?rhel} == 5 %{_initrddir}/kimchid %endif %changelog * Thu Feb 26 2015 Frédéric Bonnard 1.4.0 - Add man page for kimchid * Tue Feb 11 2014 Crístian Viana 1.1.0 - Add help pages and XSLT dependency * Tue Jul 16 2013 Adam Litke 0.1.0-1 - Adapted for autotools build * Thu Apr 04 2013 Aline Manera 0.0-1 - First build kimchi-1.5.0/contrib/kimchi.spec.suse.in000066400000000000000000000060071254252253000201270ustar00rootroot00000000000000Name: kimchi Version: @PACKAGE_VERSION@ Release: @PACKAGE_RELEASE@%{?dist} Summary: Kimchi server application BuildRoot: %{_topdir}/BUILD/%{name}-%{version}-%{release} BuildArch: noarch Group: System Environment/Base License: LGPL/ASL2 Source0: %{name}-%{version}.tar.gz Requires: kvm Requires: gettext-tools Requires: libvirt Requires: libvirt-python Requires: libvirt-daemon-config-network Requires: python-CherryPy >= 3.2.0 Requires: python-Cheetah Requires: python-websockify Requires: python-configobj Requires: novnc Requires: python-imaging Requires: python-M2Crypto Requires: python-pam Requires: python-parted Requires: python-psutil >= 0.6.0 Requires: python-jsonschema >= 1.3.0 Requires: python-ethtool Requires: python-ipaddr Requires: python-ldap Requires: python-lxml Requires: python-xml Requires: nfs-client Requires: nginx Requires: open-iscsi Requires: python-libguestfs Requires: guestfs-tools BuildRequires: libxslt-tools BuildRequires: openssl BuildRequires: python-lxml %if 0%{?sles_version} == 11 Requires: python-ordereddict %endif %description Web server application to manage KVM/Qemu virtual machines %prep %setup %build %configure --with-spice-html5 make %install rm -rf %{buildroot} make DESTDIR=%{buildroot} install %post chkconfig kimchid on %preun service kimchid stop %clean rm -rf $RPM_BUILD_ROOT %files %attr(-,root,root) %{_bindir}/kimchid %{python_sitelib}/kimchi/*.py* %{python_sitelib}/kimchi/control/*.py* %{python_sitelib}/kimchi/control/vm/*.py* %{python_sitelib}/kimchi/model/*.py* %{python_sitelib}/kimchi/xmlutils/*.py* %{python_sitelib}/kimchi/API.json %{python_sitelib}/kimchi/plugins/*.py* %{python_sitelib}/kimchi/ %{_datadir}/kimchi/doc/API.md %{_datadir}/kimchi/doc/README.md %{_datadir}/kimchi/doc/README-federation.md %{_datadir}/kimchi/doc/kimchi-guest.png %{_datadir}/kimchi/doc/kimchi-templates.png %{_prefix}/share/locale/*/LC_MESSAGES/kimchi.mo %{_datadir}/kimchi/config/ui/*.xml %{_datadir}/kimchi/ui/ %{_datadir}/kimchi %{_sysconfdir}/nginx/conf.d/kimchi.conf.in %{_sysconfdir}/nginx/conf.d/kimchi.conf %{_sysconfdir}/kimchi/kimchi.conf %{_sysconfdir}/kimchi/template.conf %{_sysconfdir}/kimchi/distros.d/debian.json %{_sysconfdir}/kimchi/distros.d/fedora.json %{_sysconfdir}/kimchi/distros.d/opensuse.json %{_sysconfdir}/kimchi/distros.d/ubuntu.json %{_sysconfdir}/kimchi/distros.d/gentoo.json %{_sysconfdir}/kimchi %{_initrddir}/kimchid %{_sysconfdir}/kimchi/ %{_var}/lib/kimchi/debugreports/ %{_var}/lib/kimchi/screenshots/ %{_var}/lib/kimchi/vnc-tokens/ %{_var}/lib/kimchi/isos/ %{_var}/lib/kimchi/ %{_localstatedir}/log/kimchi/* %{_localstatedir}/log/kimchi/ %{_mandir}/man8/kimchid.8.gz %changelog * Thu Feb 26 2015 Frédéric Bonnard 1.4.0 - Add man page for kimchid * Tue Feb 11 2014 Crístian Viana 1.1.0 - Add help pages and XSLT dependency * Thu Jul 18 2013 Adam Litke 0.1.0-1 - Adapted for autotools build - Split Suse and Fedora spec files * Thu Apr 04 2013 Aline Manera 0.0-1 - First build kimchi-1.5.0/contrib/kimchid-upstart.conf.debian000066400000000000000000000020401254252253000216150ustar00rootroot00000000000000# # kimchid - Kimchi Web Server # # Copyright IBM, Corp. 2013 # # 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 # description "Kimchi Web Server" start on started libvirt-bin stop on stopped libvirt-bin respawn respawn limit 5 30 pre-start script status libvirt-bin | grep -q "start/running" && exit 0 start libvirt-bin || exit 1 end script exec /usr/bin/kimchid kimchi-1.5.0/contrib/kimchid-upstart.conf.fedora000066400000000000000000000020251254252253000216360ustar00rootroot00000000000000# # kimchid - Kimchi Web Server # # Copyright IBM, Corp. 2013 # # 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 # description "Kimchi Web Server" start on stopped rc RUNLEVEL=[2345] respawn respawn limit 5 30 pre-start script service libvirtd status | grep -q "start/running" && exit 0 service libvirtd start || exit 1 end script exec /usr/bin/kimchid kimchi-1.5.0/contrib/kimchid.service.fedora000066400000000000000000000003641254252253000206550ustar00rootroot00000000000000[Unit] Description=Kimchi server Requires=libvirtd.service After=libvirtd.service [Service] Type=simple ExecStart=/usr/bin/kimchid ExecStop=/bin/kill -TERM $MAINPID EnvironmentFile=/etc/kimchi/kimchi.conf [Install] WantedBy=multi-user.target kimchi-1.5.0/contrib/kimchid.sysvinit000066400000000000000000000060401254252253000176430ustar00rootroot00000000000000#! /bin/sh # # kimchid Kimchi Web Server # # Copyright IBM, Corp. 2013 # # Author: Aline Manera # # 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 # ### BEGIN INIT INFO # Provides: kimchid # Required-Start: libvirtd # Required-Stop: # Default-Start: 3 5 # Default-Stop: 0 1 2 6 # Description: Start the kimchid daemon ### END INIT INFO . /etc/rc.status # Shell functions sourced from /etc/rc.status: # rc_check check and set local and overall rc status # rc_status check and set local and overall rc status # rc_status -v ditto but be verbose in local rc status # rc_status -v -r ditto and clear the local rc status # rc_failed set local and overall rc status to failed # rc_reset clear local rc status (overall remains) # rc_exit exit appropriate to overall rc status # First reset status of this service rc_reset case "$1" in start) echo -n "Starting kimchid daemon" ## Start daemon with startproc(8). If this fails ## the echo return value is set appropriate. startproc -f /usr/bin/kimchid > /dev/null 2>&1 # Remember status and be verbose rc_status -v ;; stop) echo -n "Shutting down kimchid daemon" ## Stop daemon with killproc(8) and if this fails ## set echo the echo return value. killproc -TERM /usr/bin/kimchid # Remember status and be verbose rc_status -v ;; try-restart) ## Stop the service and if this succeeds (i.e. the ## service was running before), start it again. $0 status >/dev/null && $0 restart # Remember status and be quiet rc_status ;; restart) ## Stop the service and regardless of whether it was ## running or not, start it again. $0 stop $0 start # Remember status and be quiet rc_status ;; status) echo -n "Checking for service kimchid " ## Check status with checkproc(8), if process is running ## checkproc will return with exit status 0. # Status has a slightly different for the status command: # 0 - service running # 1 - service dead, but /var/run/ pid file exists # 2 - service dead, but /var/lock/ lock file exists # 3 - service not running checkproc /usr/bin/kimchid rc_status -v ;; *) echo "Usage: $0 {start|stop|status|try-restart|restart}" exit 1 ;; esac rc_exit kimchi-1.5.0/contrib/make-deb.sh.in000066400000000000000000000004641254252253000170330ustar00rootroot00000000000000#!/bin/bash VERSION="@PACKAGE_VERSION@" RELEASE="@PACKAGE_RELEASE@" if [ ! -f configure ]; then echo "Please run this script from the top of the package tree" exit 1 fi TMPDIR=`mktemp -d` make DESTDIR=$TMPDIR install-deb dpkg-deb -b $TMPDIR kimchi-${VERSION}-${RELEASE}.noarch.deb rm -rf $TMPDIR kimchi-1.5.0/docs/000077500000000000000000000000001254252253000137115ustar00rootroot00000000000000kimchi-1.5.0/docs/API.md000066400000000000000000001316361254252253000146560ustar00rootroot00000000000000## Project Kimchi REST API Specification The Kimchi API provides all functionality to the application and may be used directly by external tools. In the following sections you will find the specification of all Collections and Resource types that are supported and the URIs where they can be accessed. In order to use the API effectively, please the following general conventions: * The **Content Type** of the API is JSON. When making HTTP requests to this API you should specify the following headers: * Accept: application/json * Content-type: application/json * A **Collection** is a group of Resources of a given type. * A **GET** request retrieves a list of summarized Resource representations This summary *may* include all or some of the Resource properties but *must* include a link to the full Resource representation. * A **POST** request will create a new Resource in the Collection. The set of Resource properties *must* be specified as a JSON object in the request body. * No other HTTP methods are supported for Collections * A **Resource** is a representation of a singular object in the API (eg. Virtual Machine). * A **GET** request retrieves the full Resource representation. * A **DELETE** request will delete the Resource. This request *may* contain a JSON object which specifies optional parameters. * A **PUT** request is used to modify the properties of a Resource (eg. Change the name of a Virtual Machine). This kind of request *must not* alter the live state of the Resource. Only *actions* may alter live state. * A **POST** request commits an *action* upon a Resource (eg. Start a Virtual Machine). This request is made to a URI relative to the Resource URI. Available *actions* are described within the *actions* property of a Resource representation. The request body *must* contain a JSON object which specifies parameters. * URIs begin with a '/' to indicate the root of the API. * Variable segments in the URI begin with a ':' and should replaced with the appropriate resource identifier. ### Collection: Virtual Machines **URI:** /vms **Methods:** * **GET**: Retrieve a summarized list of all defined Virtual Machines * **POST**: Create a new Virtual Machine * name *(optional)*: The name of the VM. Used to identify the VM in this API. If omitted, a name will be chosen based on the template used. * persistent: If 'true', vm will persist after a Power Off or host reboot. All virtual machines created by Kimchi are persistent. * template: The URI of a Template to use when building the VM * storagepool *(optional)*: Assign a specific Storage Pool to the new VM * graphics *(optional)*: Specify the graphics paramenter for this vm * type: The type of graphics. It can be VNC or spice or None. * vnc: Graphical display using the Virtual Network Computing protocol * spice: Graphical display using the Simple Protocol for Independent Computing Environments * null: Graphics is disabled or type not supported * listen: The network which the vnc/spice server listens on. ### Resource: Virtual Machine **URI:** /vms/*:name* **Methods:** * **GET**: Retrieve the full description of a Virtual Machine * name: The name of the VM. Used to identify the VM in this API * state: Indicates the current state in the VM lifecycle * running: The VM is powered on * paused: The VMs virtual CPUs are paused * shutoff: The VM is powered off * stats: Virtual machine statistics: * cpu_utilization: A number between 0 and 100 which indicates the percentage of CPU utilization. * net_throughput: Expresses total network throughput for reads and writes across all virtual interfaces (kb/s). * net_throughput_peak: The highest recent value of 'net_throughput'. * io_throughput: Expresses the total IO throughput for reads and writes across all virtual disks (kb/s). * io_throughput_peak: The highest recent value of 'io_throughput'. * uuid: UUID of the VM. * memory: The amount of memory assigned to the VM (in MB) * cpus: The number of CPUs assigned to the VM * screenshot: A link to a recent capture of the screen in PNG format * icon: A link to an icon that represents the VM * graphics: A dict to show detail of VM graphics. * type: The type of graphics. It can be VNC or spice or None. * vnc: Graphical display using the Virtual Network Computing protocol * spice: Graphical display using the Simple Protocol for Independent Computing Environments * null: Graphics is disabled or type not supported * listen: The network which the vnc/spice server listens on. * port: The real port number of the graphics, vnc or spice. Users can use this port to connect to the vm with general vnc/spice clients. * passwd: console password * passwdValidTo: lifetime for the console password. * users: A list of system users who have permission to access the VM. Default is: empty (i.e. only root-users may access). * groups: A list of system groups whose users have permission to access the VM. Default is: empty (i.e. no groups given access). * **DELETE**: Remove the Virtual Machine * **PUT**: update the parameters of existed VM * name: New name for this VM (only applied for shutoff VM) * users: New list of system users. * groups: New list of system groups. * cpus: New number of virtual cpus for this VM (if VM is running, new value will take effect in next reboot) * memory: New amount of memory (MB) for this VM (if VM is running, new value will take effect in next reboot) * graphics: A dict to show detail of VM graphics. * passwd *(optional)*: console password. When omitted a random password willbe generated. * passwdValidTo *(optional)*: lifetime for the console password. When omitted the password will be valid just for 30 seconds. * **POST**: *See Virtual Machine Actions* **Actions (POST):** * start: Power on a VM * poweroff: Power off a VM forcefully. Note this action may produce undesirable results, for example unflushed disk cache in the guest. * shutdown: Shut down a VM graceful. This action issue shutdown request to guest. And the guest will react this request. Note the guest OS may ignore the request. * reset: Reset a VM immediately without the guest OS shutdown. It emulates the power reset button on a machine. Note that there is a risk of data loss caused by reset without the guest OS shutdown. * connect: Prepare the connection for spice or vnc * clone: Create a new VM identical to this VM. The new VM's name, UUID and network MAC addresses will be generated automatically. Each existing disks will be copied to a new volume in the same storage pool. If there is no available space on that storage pool to hold the new volume, it will be created on the pool 'default'. This action returns a Task. * suspend: Suspend an active domain. The process is frozen without further access to CPU resources and I/O but the memory used by the domain at the hypervisor level will stay allocated. * resume: Resume a suspended domain. The process is restarted from the state where it was frozen by calling "suspend". ### Sub-resource: Virtual Machine Screenshot **URI:** /vms/*:name*/screenshot Represents a snapshot of the Virtual Machine's primary monitor. **Methods:** * **GET**: Redirect to the latest screenshot of a Virtual Machine in PNG format ### Sub-collection: Virtual Machine storages **URI:** /vms/*:name*/storages * **GET**: Retrieve a summarized list of all storages of specified guest * **POST**: Attach a new storage or virtual drive to specified virtual machine. * type: The type of the storage (currently support 'cdrom' and 'disk'). * path: Path of cdrom iso. * pool: Storage pool which disk image file locate in. * vol: Storage volume name of disk image. ### Sub-resource: storage **URI:** /vms/*:name*/storages/*:dev* * **GET**: Retrieve storage information * dev: The name of the storage in the vm. * type: The type of the storage (currently support 'cdrom' and 'disk'). * path: Path of cdrom iso or disk image file. * bus: Bus type of disk attached. * **PUT**: Update storage information * path: Path of cdrom iso. Can not be blank. Now just support cdrom type. * **DELETE**: Remove the storage. **Actions (POST):** ### Sub-collection: Virtual Machine Passthrough Devices **URI:** /vms/*:name*/hostdevs * **GET**: Retrieve a summarized list of all directly assigned host device of specified guest. * **POST**: Directly assign a host device to guest. * name: The name of the host device to be assigned to vm. ### Sub-resource: Device **URI:** /vms/*:name*/hostdevs/*:dev* * **GET**: Retrieve assigned device information * name: The name of the assigned device. * type: The type of the assigned device. * **DELETE**: Detach the host device from VM. ### Sub-collection: Virtual Machine Snapshots **URI:** /vms/*:name*/snapshots * **POST**: Create a new snapshot on a VM. * name: The snapshot name (optional, defaults to a value based on the current time). * **GET**: Retrieve a list of snapshots on a VM. ### Sub-resource: Snapshot **URI:** /vms/*:name*/snapshots/*:snapshot* * **GET**: Retrieve snapshot information. * created: The time when the snapshot was created (in seconds, since the epoch). * name: The snapshot name. * parent: The name of the parent snapshot, or an empty string if there is no parent. * state: The corresponding domain's state when the snapshot was created. * **DELETE**: Delete snapshot. If the snapshot has any children, they will be merged automatically with the snapshot's parent. * **POST**: See "Snapshot actions (POST)" **Snapshot Actions (POST):** * revert: Revert the domain to the given snapshot. ### Sub-resource: Current snapshot **URI:** /vms/*:name*/snapshots/current * **GET**: Retrieve current snapshot information for the virtual machine. ### Collection: Templates **URI:** /templates **Methods:** * **GET**: Retrieve a summarized list of all defined Templates * **POST**: Create a new Template * name: The name of the Template. Used to identify the Template in this API * os_distro *(optional)*: The operating system distribution * os_version *(optional)*: The version of the operating system distribution * cpus *(optional)*: The number of CPUs assigned to the VM. Default is 1, unlees specifying a cpu topology. In that case, cpus will default to a product of the topology values (see cpu_info). * memory *(optional)*: The amount of memory assigned to the VM. Default is 1024M. * cdrom *(optional)*: A volume name or URI to an ISO image. * storagepool *(optional)*: URI of the storagepool. Default is '/storagepools/default' * networks *(optional)*: list of networks will be assigned to the new VM. Default is '[default]' * disks *(optional)*: An array of requested disks with the following optional fields (either *size* or *volume* must be specified): * index: The device index * size: The device size in GB * base: Base image of this disk * graphics *(optional)*: The graphics paramenters of this template * type: The type of graphics. It can be VNC or spice or None. * vnc: Graphical display using the Virtual Network Computing protocol * spice: Graphical display using the Simple Protocol for Independent Computing Environments * null: Graphics is disabled or type not supported * listen: The network which the vnc/spice server listens on. * cpu_info *(optional)*: CPU-specific information. * topology: Specify sockets, threads, and cores to run the virtual CPU threads on. All three are required in order to specify cpu topology. * sockets - The number of sockets to use. * cores - The number of cores per socket. * threads - The number of threads per core. If specifying both cpus and CPU topology, make sure cpus is equal to the product of sockets, cores, and threads. ### Sub-Collection: Virtual Machine Network Interfaces **URI:** /vms/*:name*/ifaces Represents all network interfaces attached to a Virtual Machine. **Methods:** * **GET**: Retrieve a summarized list of all network interfaces attached to a Virtual Machine. * **POST**: attach a network interface to VM * model *(optional)*: model of emulated network interface card. It can be one of these models: ne2k_pci, i82551, i82557b, i82559er, rtl8139, e1000, pcnet and virtio. When model is missing, libvirt will set 'rtl8139' as default value. * network *(optional)*: the name of resource network, it is required when the interface type is network. * type: The type of VM network interface that libvirt supports. Now kimchi just supports 'network' type. ### Sub-Resource: Virtual Machine Network Interface **URI:** /vms/*:name*/ifaces/*:mac* A interface represents available network interface on VM. **Methods:** * **GET**: Retrieve the full description of the VM network interface * bridge *(optional)*: the name of resource bridge, only be available when the interface type is bridge. * mac: Media Access Control Address of the VM interface. * model *(optional)*: model of emulated network interface card. It will be one of these models: ne2k_pci, i82551, i82557b, i82559er, rtl8139, e1000, pcnet and virtio. * network *(optional)*: the name of resource network, only be available when the interface type is network. * type: The type of VM network interface that libvirt supports. It will be one of these types: 'network', 'bridge', 'user','ethernet', 'direct', 'hostdev', 'mcast', 'server' and 'client'. * **DELETE**: detach the network interface from VM * **PUT**: update the parameters of existing VM interface. * model *(optional)*: model of emulated network interface card. It will be one of these models: ne2k_pci, i82551, i82557b, i82559er, rtl8139, e1000, pcnet and virtio. This change is only on the persisted VM configuration. * network *(optional)*: the name of resource network, only be available when the interface type is network. This change is on the active VM instance and persisted VM configuration. **Actions (POST):** *No actions defined* ### Resource: Template **URI:** /templates/*:name* **Methods:** * **GET**: Retrieve the full description of a Template * name: A name for this template * folder: A virtual path which can be used to organize Templates in a user interface. The format is an array of path components. * icon: A URI to a PNG image representing this template * os_distro: The operating system distribution * os_version: The version of the operating system distribution * cpus: The number of CPUs assigned to the VM * memory: The amount of memory assigned to the VM in the unit of MB * cdrom: A volume name or URI to an ISO image * storagepool: URI of the storagepool where template allocates vm storage. * networks *(optional)*: list of networks will be assigned to the new VM. * disks: An array of requested disks with the following optional fields (either *size* or *volume* must be specified): * index: The device index * size: The device size in GB * volume: A volume name that contains the initial disk contents * format: Format of the image. Valid formats: bochs, cloop, cow, dmg, qcow, qcow2, qed, raw, vmdk, vpc. * graphics: A dict of graphics paramenters of this template * type: The type of graphics. It can be VNC or spice or None. * vnc: Graphical display using the Virtual Network Computing protocol * spice: Graphical display using the Simple Protocol for Independent Computing Environments * null: Graphics is disabled or type not supported * listen: The network which the vnc/spice server listens on. * invalid: A dict indicates which paramenters of this template are invalid. * networks *(optional)*: An array of invalid network names. * cdrom *(optional)*: An array of invalid cdrom names. * disks *(optional)*: An array of invalid volume names. * storagepools *(optional)*: An array of invalid storagepool names. * **DELETE**: Remove the Template * **POST**: *See Template Actions* * **PUT**: update the parameters of existed template * name: A name for this template * folder: A virtual path which can be used to organize Templates in the user interface. The format is an array of path components. * icon: A URI to a PNG image representing this template * os_distro: The operating system distribution * os_version: The version of the operating system distribution * cpus: The number of CPUs assigned to the VM * memory: The amount of memory assigned to the VM * cdrom: A volume name or URI to an ISO image * storagepool: URI of the storagepool where template allocates vm storage. * networks *(optional)*: list of networks will be assigned to the new VM. * disks: An array of requested disks with the following optional fields (either *size* or *volume* must be specified): * index: The device index * size: The device size in GB * volume: A volume name that contains the initial disk contents * format: Format of the image. Valid formats: bochs, cloop, cow, dmg, qcow, qcow2, qed, raw, vmdk, vpc. * graphics *(optional)*: A dict of graphics paramenters of this template * type: The type of graphics. It can be VNC or spice or None. * vnc: Graphical display using the Virtual Network Computing protocol * spice: Graphical display using the Simple Protocol for Independent Computing Environments * null: Graphics is disabled or type not supported * listen: The network which the vnc/spice server listens on. **Actions (POST):** * clone: clone a template from an existing template with different name. It will provide a reasonable default name with "-cloneN" as suffix for the new clone template. The "N" means the number of clone times. ### Collection: Storage Pools **URI:** /storagepools **Methods:** * **GET**: Retrieve a summarized list of all defined Storage Pools * **POST**: Create a new Storage Pool * name: The name of the Storage Pool. * type: The type of the defined Storage Pool. Supported types: 'dir', 'kimchi-iso', 'netfs', 'logical', 'iscsi', 'scsi' * path: The path of the defined Storage Pool. For 'kimchi-iso' pool refers to targeted deep scan path. Pool types: 'dir', 'kimchi-iso'. * source: Dictionary containing source information of the pool. * host: IP or hostname of server for a pool backed from a remote host. Pool types: 'netfs', 'iscsi'. * path: Export path on NFS server for NFS pool. Pool types: 'netfs'. * devices: Array of devices to be used in the Storage Pool Pool types: 'logical'. * target: Target IQN of an iSCSI pool. Pool types: 'iscsi'. * port *(optional)*: Listening port of a remote storage server. Pool types: 'iscsi'. * auth *(optional)*: Storage back-end authentication information. Pool types: 'iscsi'. * username: Login username of the iSCSI target. * password: Login password of the iSCSI target. * adapter_name: SCSI host name. ### Resource: Storage Pool **URI:** /storagepools/*:name* **Methods:** * **GET**: Retrieve the full description of a Storage Pool * name: The name of the Storage Pool Used to identify the Storage Pool in this API 'kimchi_isos' is a reserved storage pool which aggregates all ISO images across all active storage pools into a single view. * state: Indicates the current state of the Storage Pool * active: The Storage Pool is ready for use * inactive: The Storage Pool is not available * path: The path of the defined Storage Pool * type: The type of the Storage Pool * capacity: The total space which can be used to store volumes The unit is Bytes * allocated: The amount of space which is being used to store volumes The unit is Bytes * available: Free space available for creating new volumes in the pool * nr_volumes: The number of storage volumes for active pools, 0 for inactive pools * autostart: Whether the storage pool will be enabled automatically when the system boots * persistent: True, when pool persist after a system reboot or be stopped. All storage pools created by Kimchi are persistent. * source: Source of the storage pool, * addr: mount address of this storage pool(for 'netfs' pool) * path: export path of this storage pool(for 'netfs' pool) * **PUT**: Set whether the Storage Pool should be enabled automatically when the system boots * autostart: Toggle the autostart flag of the VM. This flag sets whether the Storage Pool should be enabled automatically when the system boots * disks: Adds one or more disks to the pool (for 'logical' pool only) * **DELETE**: Remove the Storage Pool * **POST**: *See Storage Pool Actions* **Actions (POST):** * activate: Activate an inactive Storage Pool * deactivate: Deactivate an active Storage Pool ### Collection: Storage Volumes **URI:** /storagepools/*:poolname*/storagevolumes **Methods:** * **GET**: Retrieve a summarized list of all defined Storage Volumes in the defined Storage Pool * **POST**: Create a new Storage Volume in the Storage Pool The return resource is a task resource * See Resource: Task * Only one of 'capacity', 'url' can be specified. * name: The name of the Storage Volume * capacity: The total space which can be used to store volumes The unit is bytes * format: The format of the defined Storage Volume. Only used when creating a storage volume with 'capacity'. * upload: True to start an upload process. False, otherwise. Only used when creating a storage volume 'capacity' parameter. * file: File to be uploaded, passed through form data ### Resource: Storage Volume **URI:** /storagepools/*:poolname*/storagevolumes/*:name* **Methods:** * **GET**: Retrieve the full description of a Storage Volume * name: The name of the Storage Volume Used to identify the Storage Volume in this API * type: The type of the Storage Volume * capacity: The total space which can be used to store data The unit is Bytes * allocation: The amount of space which is being used to store data The unit is Bytes * format: The format of the file or volume * path: Full path of the volume on the host filesystem. * os_distro *(optional)*: os distribution of the volume, for iso volume only. * os_version *(optional)*: os version of the volume, for iso volume only. * bootable *(optional)*: True if iso image is bootable and not corrupted. * used_by: Name of vms which use this volume. * **DELETE**: Remove the Storage Volume * **POST**: *See Storage Volume Actions* * **PUT**: Upload storage volume chunk * chunk_size: Chunk size of the slice in Bytes. * chunk: Actual data of uploaded file **Actions (POST):** * resize: Resize a Storage Volume * size: resize the total space which can be used to store data The unit is bytes * wipe: Wipe a Storage Volume * clone: Clone a Storage Volume. * pool: The name of the destination pool (optional). * name: The new storage volume name (optional). ### Collection: Interfaces **URI:** /interfaces **Methods:** * **GET**: Retrieve a summarized list of current Interfaces ### Resource: Interface **URI:** /interfaces/*:name* A interface represents available interface on host. **Methods:** * **GET**: Retrieve the full description of the Interface * name: The name of the interface. * status: The current status of the Interface. * active: The interface is active. * inactive: The interface is inactive. * ipaddr: The ip address assigned to this interface in subnet. * netmask: Is used to divide an IP address into subnets and specify the networks available hosts * type: The net device type of the interface. * nic: Network interface controller that connects a computer to a computer network * vlan: A logical interface that represents a VLAN in all Layer 3 activities the unit may participate in * bonding: The combination of network interfaces on one host for redundancy and/or increased throughput. * bridge: A network device that connects multiple network segments. * **POST**: *See Interface Actions* **Actions (POST):** *No actions defined* ### Collection: Networks **URI:** /networks **Methods:** * **GET**: Retrieve a summarized list of all defined Networks * **POST**: Create a new Network * name: The name of the Network * connection: Specifies how this network should be connected to the other networks visible to this host. * isolated: Create a private, isolated virtual network. * nat: Outgoing traffic will be routed through the host. * bridge: All traffic on this network will be bridged through the indicated interface. * subnet *(optional)*: Network segment in slash-separated format with ip address and prefix or netmask used to create nat network. * interface *(optional)*: The name of a network interface on the host. For bridge network, the interface can be a bridge or nic/bonding device. * vlan_id *(optional)*: VLAN tagging ID for the bridge network. ### Resource: Network **URI:** /networks/*:name* **Methods:** * **GET**: Retrieve the full description of a Network * name: The name of the Network Used to identify the Network in this API * state: Indicates the current state of the Network * active: The Network is ready for use * inactive: The Network is not available * autostart: Network autostart onboot * in_use: Indicates ('true') if some guest is attached to this network and 'false' otherwise. * vms: all vms attached to this network * subnet: Network segment in slash-separated format with ip address and prefix * dhcp: DHCP services on the virtual network is enabled. * start: start boundary of a pool of addresses to be provided to DHCP clients. * end: end boundary of a pool of addresses to be provided to DHCP clients. * connection: Specifies how this network should be connected to the other networks visible to this host. * isolated: A private, isolated virtual network. The VMs attached to it can not be reached by the systems outside of this network and vice versa. * nat: Outgoing traffic will be routed through the host. The VM attached to it will have internet access via the host but other computers will not be able to connect to the VM. * bridge: Aggregated Public Network. The VM that joines this network is seen as a peer on this network and it may offer network services such as HTTP or SSH. * interface: The name of a bridge network interface on the host. All traffic on this network will be bridged through the indicated interface. The interface is a bridge or ethernet/bonding device. * persistent: If 'true', network will persist after a system reboot or be stopped. All networks created by Kimchi are persistent. * **DELETE**: Remove the Network * **POST**: *See Network Actions* **Actions (POST):** * activate: Activate an inactive Network * deactivate: Deactivate an active Network ### Collection: Tasks **URI:** /tasks **Methods:** * **GET**: Retrieve a summarized list of current Tasks ### Resource: Task **URI:** /tasks/*:id* A task represents an asynchronous operation that is being performed by the server. **Methods:** * **GET**: Retrieve the full description of the Task * id: The Task ID is used to identify this Task in the API. * status: The current status of the Task * running: The task is running * finished: The task has finished successfully * failed: The task failed * message: Human-readable details about the Task status * target_uri: Resource URI related to the Task * **POST**: *See Task Actions* **Actions (POST):** *No actions defined* ### Resource: Configuration **URI:** /config Contains information about the application environment and configuration. **Methods:** * **GET**: Retrieve configuration information * display_proxy_port: Port for vnc and spice's websocket proxy to listen on * version: The version of the kimchi service * **POST**: *See Configuration Actions* **Actions (POST):** *No actions defined* ### Resource: Capabilities **URI:** /config/capabilities Contains information about the host capabilities: iso streaming, screenshot creation. **Methods:** * **GET**: Retrieve capabilities information * libvirt_stream_protocols: list of which network protocols are accepted for iso streaming by libvirt * qemu_spice: True, if QEMU supports Spice; False, otherwise * qemu_stream: True, if QEMU supports ISO streaming; False, otherwise * screenshot: True, if libvirt stream functionality can create screenshot file without problems; False, otherwise or None if the functionality was not tested yet * system_report_tool: True if the is some debug report tool installed on the system; False, otherwise. * update_tool: True if there is a compatible package manager for the system; False, otherwise * repo_mngt_tool: 'deb', 'yum' or None - when the repository management tool is not identified * federation: 'on' if federation feature is enabled, 'off' otherwise. * auth: authentication type, 'pam' and 'ldap' are supported. * **POST**: *See Configuration Actions* **Actions (POST):** *No actions defined* ### Collection: Storage Servers **URI:** /storageservers **Methods:** * **GET**: Retrieve a summarized list of used storage servers. * Parameters: * _target_type: Filter server list with given type, currently support 'netfs' and 'iscsi'. ### Resource: Storage Server **URI:** /storageservers/*:host* **Methods:** * **GET**: Retrieve description of a Storage Server * host: IP or host name of storage server * port: port of storage server, only for "iscsi" ### Collection: Storage Targets **URI:** /storageservers/*:name*/storagetargets **Methods:** * **GET**: Retrieve a list of available storage targets. * Parameters: * _target_type: Filter target list with given type, currently support 'netfs' and 'iscsi'. * _server_port: Filter target list with given server port, currently support 'iscsi'. * Response: A list with storage targets information. * host: IP or host name of storage server of this target. * target_type: Type of storage target, supported: 'nfs'. * target: Storage target path. ### Collection: Distros **URI:** /config/distros **Methods:** * **GET**: Retrieve a summarized list of all Distros ### Resource: Distro **URI:** /config/distros/*:name* Contains information about the OS distribution. **Methods:** * **GET**: Retrieve a OS distribution information. * name: The name of the Distro. * os_distro: The operating system distribution. * os_version: The version of the operating system distribution. * path: A URI to an ISO image. **Actions (POST):** *No actions defined* #### Collection: Debug Reports **URI:** /debugreports **Methods:** * **GET**: Retrieve a summarized list of all available Debug Reports * **POST**: Create a new Debug Report. This POST method is different from the other ones. The return resource is a task resource which is identified by the url below * task resource. * See Resource: Task * ### Resource: Debug Report **URI:** /debugreports/*:name* A Debug Report is an archive of logs and other information about the host that is used to diagnose and debug problems. The exact format and contents are specific to the low level collection tool being used. **Methods:** * **GET**: Retrieve the full description of Debug Report * name: The debug report name used to identify the report * uri: The URI path to download a debug report * time: The time when the debug report is created * **PUT**: rename an existed debug report * name: The new name for this debug report * **DELETE**: Remove the Debug Report * name: The debug report name used to identify the report * **POST**: *See Debug Report Actions* **Actions (POST):** *No actions defined* ### Sub-resource: Debug Report content **URI:** /debugreports/*:name*/content It is the sub-resource of Debug Report and the client use it to get the real content of the Debug Report file from the server * **GET**: Retrieve the content of a Debug Report file **Actions (POST):** *No actions defined* ### Resource: Host **URI:** /host Contains information of host. **Methods:** * **GET**: Retrieve host static information * memory: Total size of host physical memory The unit is Bytes * cpu_model: The model name of host CPU * cpus: The number of online CPUs available on host * os_distro: The OS distribution that runs on host * os_version: The version of OS distribution * os_codename: The code name of OS distribution * **POST**: *See Host Actions* **Actions (POST):** * reboot: Restart the host machine. Only allowed if there is not vm running. * shutdown: Power off the host machine. Only allowed if there is not vm running. * swupdate: Start the update of packages in background and return a Task resource * task resource. * See Resource: Task * ### Resource: Users **URI:** /users List of available users. **Methods:** * **GET**: Retrieve list of available users. * Parameters: * _user_id: Validate whether user exists. Essential for 'ldap' authentication. ### Resource: Groups **URI:** /groups List of available groups. **Methods:** * **GET**: Retrieve list of available groups, only support 'pam' authentication. ### Resource: HostStats **URI:** /host/stats Contains the host sample data. **Methods:** * **GET**: Retrieve host sample data * cpu_utilization: A number between 0 and 100 which indicates the percentage of CPU utilization. * memory: memory statistics of host * total: Total amount of memory. The unit is Bytes. * free: The amount of memory left unused by the system. The unit is Bytes. * buffers: The amount of memory used for file buffers. The unit is Bytes. * cached: The amount of memory used as cache memory. The unit is Bytes. * avail: The total amount of buffer, cache and free memory. The unit is Bytes. * disk_read_rate: Expresses the total IO throughput for reads across all disks (B/s). * disk_write_rate: Expresses the total IO throughput for writes across all disks (B/s). * net_sent_rate: Expresses the total network throughput for writes across all interfaces (B/s). * net_recv_rate: Expresses the total network throughput for reads across all interfaces (B/s). * **POST**: *See HostStats Actions* **Actions (POST):** *No actions defined* ### Resource: HostStats **URI:** /host/cpuinfo The cores and sockets of a hosts's CPU. Useful when sizing VMs to take advantages of the perforamance benefits of SMT (Power) or Hyper-Threading (Intel). **Methods:** * **GET**: Retreives the sockets, cores, and threads values. * threading_enabled: Whether CPU topology is supported on this system. * sockets: The number of total sockets on a system. * cores: The total number of cores per socket. * threads_per_core: The threads per core. **Actions (PUT):** *No actions defined* **Actions (POST):** *No actions defined* ### Resource: HostStatsHistory **URI:** /host/stats/history It is the sub-resource of Host Stats and the client uses it to get the host stats history **Methods:** * **GET**: Retrieve host sample data history * cpu_utilization: CPU utilization history * memory: Memory statistics history * total: Total amount of memory. The unit is Bytes. * free: The amount of memory left unused by the system. The unit is Bytes. * buffers: The amount of memory used for file buffers. The unit is Bytes. * cached: The amount of memory used as cache memory. The unit is Bytes. * avail: The total amount of buffer, cache and free memory. The unit is Bytes. * disk_read_rate: IO throughput for reads history * disk_write_rate: IO throughput for writes history * net_sent_rate: Network throughput for writes history * net_recv_rate: Network throughput for reads history * **POST**: *See HostStatsHistory Actions* **Actions (POST):** *No actions defined* ### Collection: Plugins **URI:** /plugins **Methods:** * **GET**: Retrieve a summarized list names of all UI Plugins ### Collection: Partitions **URI:** /host/partitions **Methods:** * **GET**: Retrieves a detailed list of all partitions of the host. ### Resource: Partition **URI:** /host/partitions/*:name* **Methods:** * **GET**: Retrieve the description of a single Partition: * name: The name of the partition. Used to identify it in this API * path: The device path of this partition. * type: The type of the partition: * part: a standard partition * lvm: a partition that belongs to a lvm * fstype: The file system type of the partition * size: The total size of the partition, in bytes * mountpoint: If the partition is mounted, represents the mountpoint. Otherwise blank. * available: false, if the partition is in use by system; true, otherwise. ### Collection: Devices **URI:** /host/devices **Methods:** * **GET**: Retrieves list of host devices (Node Devices). * Parameters: * _cap: Filter node device list with given node device capability. To list Fibre Channel SCSI Host devices, use "_cap=fc_host". Other available values are "fc_host", "net", "pci", "scsi", "storage", "system", "usb" and "usb_device". * _passthrough: Filter devices eligible to be assigned to guest directly. Possible values are "ture" and "false". * _passthrough_affected_by: Filter the affected devices in the same group of a certain directly assigned device. The value should be the name of a device. ### Resource: Device **URI:** /host/devices/*:name* **Methods:** * **GET**: Retrieve information of a single host device. * device_type: Type of the device, supported types are "net", "pci", "scsi", "storage", "system", "usb" and "usb_device". * name: The name of the device. * path: Path of device in sysfs. * parent: The name of the parent parent device. * adapter: Host adapter information of a "scsi_host" or "fc_host" device. * type: The capability type of the scsi_host device (fc_host, vport_ops). * wwnn: The HBA Word Wide Node Name. Empty if pci device is not fc_host. * wwpn: The HBA Word Wide Port Name. Empty if pci device is not fc_host. * domain: Domain number of a "pci" device. * bus: Bus number of a "pci" device. * slot: Slot number of a "pci" device. * function: Function number of a "pci" device. * vendor: Vendor information of a "pci" device. * id: Vendor id of a "pci" device. * description: Vendor description of a "pci" device. * product: Product information of a "pci" device. * id: Product id of a "pci" device. * description: Product description of a "pci" device. * iommuGroup: IOMMU group number of a "pci" device. Would be None/null if host does not enable IOMMU support. ### Sub-collection: VMs with the device assigned. **URI:** /host/devices/*:name*/vmholders * **GET**: Retrieve a summarized list of all VMs holding the device. ### Sub-resource: VM holder **URI:** /host/devices/*:name*/vmholders/*:vm* * **GET**: Retrieve information of the VM which is holding the device * name: The name of the VM. * state: The power state of the VM. Could be "running" and "shutdown". ### Collection: Host Packages Update **URI:** /host/packagesupdate Contains the information and action of packages update in the host. **Methods:** * **GET**: Retrieves a list of all packages to be updated in the host: ### Resource: Host Package Update **URI:** /host/packagesupdate/*:name* Contains the information for a specific package to be updated. **Methods:** * **GET**: Retrieves a full description of a package: * package_name: The name of the package to be updated * arch: The architecture of the package * version: The new version of the package * repository: The repository name from where package will be downloaded ### Collection: Host Repositories **URI:** /host/repositories **Methods:** * **GET**: Retrieve a summarized list of all repositories available * **POST**: Add a new repository * baseurl: URL to the repodata directory when "is_mirror" is false. Otherwise, it can be URL to the mirror system for YUM. Can be an http://, ftp:// or file:// URL. * repo_id *(optional)*: Unique YUM repository ID * config: A dictionary that contains specific data according to repository type. * repo_name *(optional)*: YUM Repository name * mirrorlist *(optional)*: Specifies a URL to a file containing a list of baseurls for YUM repository * dist: Distribution to DEB repository * comps *(optional)*: List of components to DEB repository ### Resource: Repository **URI:** /host/repositories/*:repo-id* **Methods:** * **GET**: Retrieve the full description of a Repository * repo_id: Unique repository name for each repository, one word. * baseurl: URL to the repodata directory when "is_mirror" is false. Otherwise, it can be URL to the mirror system for YUM. Can be an http://, ftp:// or file:// URL. * enabled: True, when repository is enabled; False, otherwise * config: A dictionary that contains specific data according to repository type. * repo_name: Human-readable string describing the YUM repository. * mirrorlist: Specifies a URL to a file containing a list of baseurls for YUM repository * gpgcheck: True, to enable GPG signature verification; False, otherwise. * gpgkey: URL pointing to the ASCII-armored GPG key file for the YUM repository. * dist: Distribution to DEB repository * comps: List of components to DEB repository * **DELETE**: Remove the Repository * **POST**: *See Repository Actions* * **PUT**: update the parameters of existing Repository * repo_id: Unique repository name for each repository, one word. * baseurl: URL to the repodata directory when "is_mirror" is false. Otherwise, it can be URL to the mirror system for YUM. Can be an http://, ftp:// or file:// URL. * config: A dictionary that contains specific data according to repository type. * repo_name: Human-readable string describing the YUM repository. * mirrorlist: Specifies a URL to a file containing a list of baseurls for YUM repository * gpgcheck: True, to enable GPG signature verification; False, otherwise. * gpgkey: URL pointing to the ASCII-armored GPG key file for the YUM repository. * dist: Distribution to DEB repository * comps: List of components to DEB repository **Actions (POST):** * enable: Enable the Repository as package source * disable: Disable the Repository as package source ### Collection: Peers **URI:** /peers **Methods:** * **GET**: Return the list of Kimchi peers in the same network (It uses openSLP for discovering) kimchi-1.5.0/docs/Makefile.am000066400000000000000000000016761254252253000157570ustar00rootroot00000000000000# # Kimchi # # Copyright IBM Corp, 2013 # # 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 docdir = $(datadir)/kimchi/doc dist_doc_DATA = \ API.md \ README.md \ README-federation.md \ kimchi-guest.png \ kimchi-templates.png \ kimchid.8 \ $(NULL) CLEANFILES = kimchid.8 kimchi-1.5.0/docs/README-federation.md000066400000000000000000000037471254252253000173210ustar00rootroot00000000000000Kimchi Project - Federation Feature =================================== Federation feature is a mechanism to discover Kimchi peers in the same network. It uses openSLP tool (http://www.openslp.org/) to register and find the Kimchi servers. By default this feature is disabled on Kimchi as it is not critical for KVM virtualization and requires additional software installation. To enable it, do the following: 1. Install openslp and openslp-server rpm packages, or install slpd and slptool deb packages. 2. openSLP uses port 427 (UDP) and port 427 (TCP) so make sure to open those ports in your firewall configuration For system using firewalld, do: sudo firewall-cmd --permanent --add-port=427/udp sudo firewall-cmd --permanent --add-port=427/tcp sudo firewall-cmd --reload For openSUSE systems, do: sudo /sbin/SuSEfirewall2 open EXT TCP 427 sudo /sbin/SuSEfirewall2 open EXT UDP 427 For system using iptables, do: sudo iptables -A INPUT -p tcp --dport 427 -j ACCEPT sudo iptables -A INPUT -p udp --dport 427 -j ACCEPT 3. In addition to the openSLP ports, you also need to allow multicast in the firewall configuration For system using firewalld, do: sudo firewall-cmd --direct --add-rule ipv4 filter INPUT 0 -s -j ACCEPT For openSUSE systems, do: Add the subnet to the trusted networks listed on FW_TRUSTED_NETS in /etc/sysconfig/SuSEfirewall2 file. Make sure to restart /sbin/SuSEfirewall2 after modifying /etc/sysconfig/SuSEfirewall2 For system using iptables, do: sudo iptables -A INPUT -s -j ACCEPT 4. Start slpd service and make sure it is up while running Kimchi sudo service slpd start 5. Enable federation on Kimchi by editing the /etc/kimchi/kimchi.conf file: federation = on 6. Then start Kimchi service sudo service kimchid start The Kimchi server will be registered on openSLP on server starting up and will be found by other Kimchi peers (with federation feature enabled) in the same network. Enjoy! kimchi-1.5.0/docs/README.md000066400000000000000000000207231254252253000151740ustar00rootroot00000000000000Kimchi Project ============== Kimchi is an HTML5 based management tool for KVM. It is designed to make it as easy as possible to get started with KVM and create your first guest. Kimchi runs as a daemon on the hypervisor host. It manages KVM guests through libvirt. The management interface is accessed over the web using a browser that supports HTML5. Browser Support =============== Desktop Browser Support: ----------------------- * **Internet Explorer:** IE9+ * **Chrome:** Current-1 version * **Firefox:** Current-1 version Firefox 24ESR * **Safari:** Current-1 version * **Opera:** Current-1 version Mobile Browser Support: ----------------------- * **Safari iOS:** Current-1 version * **Android Browser** Current-1 version Current-1 version denotes that we support the current stable version of the browser and the version that preceded it. For example, if the current version of a browser is 24.x, we support the 24.x and 23.x versions.This does not mean that kimchi cannot be used in other browsers, however, functionality and appearance may be diminished and we may not be able to provide support for any problems you find. Hypervisor Distro Support ========================= Kimchi daemon might run on any GNU/Linux distribution that meets the conditions described on the 'Getting Started' section below. The Kimchi community makes an effort to test with the latest versions of Fedora, RHEL, OpenSuSe, and Ubuntu. Getting Started =============== Install Dependencies -------------------- **For fedora and RHEL:** $ sudo yum install gcc make autoconf automake gettext-devel git \ python-cherrypy python-cheetah libvirt-python \ libvirt libvirt-daemon-config-network python-imaging \ PyPAM m2crypto python-jsonschema rpm-build \ qemu-kvm python-psutil python-ethtool sos \ python-ipaddr python-ldap python-lxml nfs-utils \ iscsi-initiator-utils libxslt pyparted nginx \ python-libguestfs libguestfs-tools python-websockify \ novnc spice-html5 python-configobj # If using RHEL, install the following additional packages: $ sudo yum install python-unittest2 python-ordereddict # Restart libvirt to allow configuration changes to take effect $ sudo service libvirtd restart Packages version requirement: python-psutil >= 0.6.0 # These dependencies are only required if you want to run the tests: $ sudo yum install pyflakes python-pep8 python-requests *Note for RHEL users*: Some of the above packages are located in the Red Hat EPEL repositories. See [this FAQ](http://fedoraproject.org/wiki/EPEL#How_can_I_use_these_extra_packages.3F) for more information on how to configure your system to access this repository. And for RHEL7 systems, you also need to subscribe to the "RHEL Server Optional" channel at RHN Classic or Red Hat Satellite. **For debian:** $ sudo apt-get install gcc make autoconf automake gettext git \ python-cherrypy3 python-cheetah python-libvirt \ libvirt-bin python-imaging python-configobj \ python-pam python-m2crypto python-jsonschema \ qemu-kvm libtool python-psutil python-ethtool \ sosreport python-ipaddr python-ldap \ python-lxml nfs-common open-iscsi lvm2 xsltproc \ python-parted nginx python-guestfs libguestfs-tools \ websockify novnc spice-html5 Packages version requirement: python-jsonschema >= 1.3.0 python-psutil >= 0.6.0 # These dependencies are only required if you want to run the tests: $ sudo apt-get install pep8 pyflakes python-requests **For openSUSE:** $ sudo zypper install gcc make autoconf automake gettext-tools git \ python-CherryPy python-Cheetah libvirt-python \ libvirt libvirt-daemon-config-network python-pam \ python-imaging python-M2Crypto python-jsonschema \ rpm-build kvm python-psutil python-ethtool \ python-ipaddr python-ldap python-lxml nfs-client \ open-iscsi libxslt-tools python-xml python-parted \ nginx python-libguestfs python-configobj \ guestfs-tools python-websockify novnc Packages version requirement: python-psutil >= 0.6.0 # These dependencies are only required if you want to run the tests: $ sudo zypper install python-pyflakes python-pep8 python-requests *Note for openSUSE users*: Some of the above packages are located in different openSUSE repositories. See [this FAQ](http://download.opensuse.org/repositories/home:GRNET:synnefo/) for python-parted; and [this FAQ](http://download.opensuse.org/repositories/systemsmanagement:/spacewalk/) for python-ethtool to get the correct repository based on your openSUSE version. And [this FAQ](http://en.opensuse.org/SDB:Add_package_repositories) for more information on how configure your system to access this repository. Build and Install ----------------- For openSUSE 13.1: $ ./autogen.sh --with-spice-html5 Otherwise: $ ./autogen.sh --system $ make $ sudo make install # Optional if running from the source tree Run --- $ sudo kimchid --host=0.0.0.0 If you cannot access Kimchi, take a look at these 2 points: 1. Firewall Kimchi uses by default the ports 8000, 8001 and 64667. To allow incoming connections: For system using firewalld, do: sudo firewall-cmd --add-port=8000/tcp --permanent sudo firewall-cmd --add-port=8001/tcp --permanent sudo firewall-cmd --add-port=64667/tcp --permanent sudo firewall-cmd --reload For openSUSE systems, do: sudo /sbin/SuSEfirewall2 open EXT TCP 8000 sudo /sbin/SuSEfirewall2 open EXT TCP 8001 sudo /sbin/SuSEfirewall2 open EXT TCP 64667 For system using iptables, do: sudo iptables -A INPUT -p tcp --dport 8000 -j ACCEPT sudo iptables -A INPUT -p tcp --dport 8001 -j ACCEPT sudo iptables -A INPUT -p tcp --dport 64667 -j ACCEPT Don't forget to correctly save the rules. 2. SELinux Allow httpd_t context for Kimchi web server: semanage permissive -a httpd_t Test ---- $ make check-local # check for i18n and formatting errors $ sudo make check After all tests are executed, a summary will be displayed containing any errors/failures which might have occurred. Usage ----- Connect your browser to https://localhost:8001. You should see a screen like: ![Kimchi Login Screen](/docs/kimchi-login.png) Kimchi uses PAM to authenticate users so you can log in with the same username and password that you would use to log in to the machine itself. Once logged in you will see a screen like: ![Kimchi Guest View](/docs/kimchi-guest.png) This shows you the list of running guests including a live screenshot of the guest session. You can use the action buttons to shutdown the guests or connect to the display in a new window. To create a new guest, click on the "+" button in the upper right corner. In Kimchi, all guest creation is done through templates. You can view or modify templates by clicking on the Templates link in the top navigation bar. The template screen looks like: ![Kimchi Template View](/docs/kimchi-templates.png) From this view, you can change the parameters of a template or create a new template using the "+" button in the upper right corner. To create a template, you need an ISO on your host or using remote one. If you are willing to use your own ISO, please copy it to out of box storage pool (default path is: /var/lib/kimchi/isos). Known Issues ------------ 1. When you are using NFS as storage pool, check the nfs export path permission is configured as: (1) export path need to be squashed as kvm gid and libvirt uid: /my_export_path *(all_squash,anongid=, anonuid=,rw,sync) So that root user can create volume with right user/group. (2) Chown of export path as libvirt user, group as kvm group, In order to make sure all mapped user can get into the mount point. Participating ------------- All patches are sent through our mailing list hosted by oVirt. More information can be found at: https://github.com/kimchi-project/kimchi/wiki/Communications Patches should be sent using git-send-email to kimchi-devel@ovirt.org. kimchi-1.5.0/docs/kimchi-guest.png000066400000000000000000005674311254252253000170300ustar00rootroot00000000000000‰PNG  IHDR3«ÅéÓ,bKGDÿÿÿ ½§“ pHYs  šœtIMEÝ 5§ÈtEXtCommentCreated with GIMPW IDATxÚìÝwœTÕÝÇñϹeÊÎêÒ‘& "¢ 6°+Ɖ˜Ä£I|¬‰ILò¤hš&j’'‰1Å$úDb4ÆØ v¤«¨€Hï,ËöÝ™¹íœçÙv—–…(âïýz%2;÷ÞsçÎìÎùÞÓÔòåËçy455QQQïûA€Ö!„B!„ø¨)¥°m›¢¢"’É$Éd’X,†“N§I§Ó455‘J¥8ûì³åj !„B!öIÏ<ó J)¢(B͘1ÃxžÇرc)--% CŒ1r•„B!„ûœL&ìY³°***‚€d2Id„B!„û¬D"RŠššœ0Hsúé“ÉdÒØ¶-WGñÉ –R`4z/ÞÃQ–…2ÝΡ=·o\‹Ü%јüùÒö±ÁhÃÞ|mËéäQP–BìÃ×X!ÄÞ1iÒ$þñà„‘,Ë’V!Äþ“U,×u±LHÖ…ãºØ–Úgëº,þ` îñŒ˜Bïq¢Q˜°–E³ß¢¾ÛPÆ4€˜Ý¢¢M#‹_ŸOUª/‡FqLí~ ¶CÌqƒ‰|üÐ4ÿËÛ«7t"Gu[ÍÓÿ|‚¢óG0~PŠ(ÚÿJ¡ƒZæ>ók>C†õõTá9K×3û±y§ïñ <””»»‡7l]<“i3Þ&mlúŽ¿s/#26 Káî—6‚NqüE0ªk|÷Z›ضÏâž`Z˧ÊÇ2¼‡Ïû¯>Çë~WÎéw8ƒºdYôÒ3ÌvPs‹žœçëœÝûp–YÛµª(ÅÎNÐÀü—ÿÉ´y[HõéË ¡e:&·“|³ !ÄþÍi™l„byMlY¿†5]FiŸEÓåÙ×ÞÅ?àSÜtöá”F‡rë±çc"ßö¼@c0lÇÁ¶UóM¢üs!½ùÒ/îA„Q'þ悦Z6­_G½¶i43Ùrè9ô´ë˜÷ÜÖUZ¯”tí~70cð¼$g}çvÎQ†( Bƒe;ضBc XNîqîµêŽ· MSÅ:ÖVX¸…0c¡Ê&ë§8û»wp®2Da@µmMÑ>8ùÛ{¯ý4Õë7‘îz<7Ýp]UˆH»ŒBì¿òËÈ8r)„û-¥°ŒÇêÙÿæá§ß#6ò4¾~ù)”iVÎ~–ûzŽä9?à{“zðîsÿâïÏÌ¢hü™ô];…UEuÎÉÎâái ñʆsîe—rlÿ""¯Ž÷f¾Àó¯¿É¦F[ÔŸ)W]Îá]L®Lo ¯ýã7Ì\¸xßCøÌES8¬w÷~óg¼Û÷8®»ì”XY±$õU°l}†2f0£Â"Qìñ Àø¬]8gž{Õu>ÊíÁá'žÁÇN|ýCüð7s0 ¥#´Qôv W^u:³~3/ÖºœvÅw8gxÛ(eZ]WÛÎ2㯿åÙåPÌðñ§pék?L…NOÎûÂqˆ’BP‰‚J¿í^jHð©+¾Í™6òðoãu¿„òñÝØ¿É÷ÎéÊâןçé—çSébÅý˜xÖ§9éÐ^úݼ^_L±=“Ÿ|s:}Æ}‰k?ÝÏ=É‹³Þ£:°)î1Œ“Î9‡ ÃËx繿ðÀ´õ•ùôÀ:þñ‡»y'<‚kÿûs N* ABÑQñÛßþ–I“&1räÈݾIçû>3gÎdРA 2„L&Ã믿ÎðáÃ4hP‡'ÝÌ„û%cåàÖÍç_Oe(=ôT.ºðdJµOXŽK²¨ˆ¢˜…ÖÛSTRLfùú2Þ‚™,|æ~V:šSN=Žy3gñìóïsä—cÍ‚y⥹XÃNâ¢q«ëèÏõPÊ¢aù ŸÀÙ½»ñâ‹Kxí½•ŒìYN"UDQ"Ž¥Øîo®²Ü|,¢vZ‹šƒŠˆ ™Èë¦ñÁoá¯_DèÏ£=Þx9ƒA‘®x‹Gyž†G3å¬áÔ/δibwïÁ§‡Ç®E-3Ÿ›Îš†,}†B‰±d’¤çknYjQrë~^Æ #EïCOæ³Çu'A– óžå¹y/ðZÏœwL_T‹ñ*ù]-ÝÀ»og­» ÊrI¯x”?=¶ Ç5ÉÃùÒ—N¤ÔD-Z ò'©Q±>yü@î}nk¢4]›ÂA‰3ÃJQ¿æm6dË8á¨ñŒ=ìÒå‹ßšÊ’¥›9wôáŒ:¬'ïOœÊ†:йˆ NNL×ïàü̶kÔòyåb›˜ùìLš‚ˆÈk±™êJÓ·U2Ía&ÍŠwßàýPƒc3þ­·kÞMuaÌñgpÌ)t˜åçß§A9°øu[fáeê°2u,X“eÜ!Qž|‚Åv9E™_ÉÓ›6àE½8ñÌã[âÃÆÕ¬ßº˜…‹¶rÜ)ý9ëì‰,¿ï%Þzße䱟æˆþÅ„2a€b?2sçÎ¥ººz»çºuëÆ‘GÙ¡ ¢”bõêÕ¬]»¥=zô`ÕªU¬_¿Çq8öØc;h’É$'to¼ñË–-ömN<ñDúöíKíºû·„!Ä~MÀDD]䨢÷˜óÁlþùl7.ýÔXŠ]³­Û”!7þ£¹Âž(‹KY@¥ Càir3’´64F9Ø&" 7w€*TÆã©8èˆHçÆˆC«AímÃŒ1yÔ××çŒɭù¥[ `7èmu}ʇÇû>VdûsþÄ^DoèB Š1£¶1„AH¨Á²F´Ù¸xO¿0‡¦þgñ‹'– ˆÜÖ-/­JÖ¹s)ÜÏSfÃ4î}b.±Þƒ9ñÌS(]û­ºy,Mëï”üžÐ)çü/^ÉI‡”åÞ£ ƒÖ·xÓ¶]'˱‰'‚ÀÇhh"í0ààCXÃ`ÐADiï~Є&7Ív„„QÔ|þ6vQ!¾j“›:ÛÔˆ‡ÂBãeñ#£ä{P±Ÿ~'jmÛ8Îö#L,ËÚ­ñó-·+))Ùî¹Ý=NQQ™LËÊõNˆ¢¨Ý¤†!„Øÿä*À¡UÎW]Oò¯âÕY3UY|îSG`ïèï¤ÎíkZµHlû윽{¦Ø™ÇËÓfSzôÂÚZŠDßø¶€Äî Á|R_ÆÏnßvMõèü1OuëÃaÇŒÁÕG2"¡y¯P[פM÷qÞ^¸ˆAŵKç±ÎK1úàÞ˜ªwyò_ϲÑÂù'd˲åX‰2úö·¹z;9AºßXôê6ˆû—²òÍ ªyö¶¶ûš7ÛTO}ƒjþ¡E,Ör+C»;*‹ný†SÊ 2±^ŒÕ‚&Ö/]K×2—ÖS·T¼˜>=û·ßgúëï’¦ygõzšL&ŽèFT³‚§§½‰ëÏá61ÁL4„ã‡u•ÙÏ„û¥0 9úè£ ¡mÐillìP€ÐZ3lØ0FŽ À+¯¼ÂÈ‘#éÕ«õõõ:Nþœ/^LCCÆ £©©‰%K–ЧOŸÝ3£µ.Ì „û†dÓM¤Ý Ù Œ“.¼”è¡ûy鵇ù¿Ú-uxé4VóÌbQè“I7‘ 5Fk|/K:íF­C²Ù4é( Âa蘓˜TïóÊì§øý› 'Þ› þk}b^º‰´çiƒ6¹Ç?@á§Ód²‘ÖhÝú½ÎÖQ—Ýî¶Ó¶ü`}²é4¾¡Æz1G«L&CdH7QH²ÇXÎ;§Š§_|¿.~ì2Fx“Fö¥qþ?y«R“*ZÓ÷þ Cn€Ë¯8™ ›!qð£Üº “&íÇ ´Æ ñ3i2v– pÏ©#ÖòÂ;Ïóçª5 ë‘ijÂó›[•òß)JaMM“Ng ÂæYÐL.lt®œŒÁonõò3iÒQ&W®ÎMÕ\>ì8Î>­‘ç§?À/^‹á¢HõÁgFE«?ÓDÚ ÐÚY F} >¯Nÿ¿yÙ%Õu Ï?cº61ç‰'™·:àÄÿº€³Ô‘Ýð;ž~ø)ʯû<[D’h„û¡†††>ßÑðÉdÈd2cH¥Rø¾O]]ÝnGkM"‘`äÈ‘ôîÝÏópšgÍìHKQþ{Fýýï7çŸ>¾ïË»,„Ø(•[ ƒŽrÝ®¬üJó”²Áh0šH”ea)•뚦›·U £¨Å¾ÛkÛÕCs™Æi½íŒ&2´>ŸN½$ ËR…snõœecåϰ,›Ö7ÇråÒ¼]Û/0­5–m箎І<6Í_2 ËV¹ÎwÍ­BŠ\—½ö Ýv,½Ý:2;*Wëh[žS ËÊ•×ê5Î¥Åû“ß^Y­¯ÉmR–ÂRªù\Á¶÷ì}BˆOª’’²ÙÜM®Îp§Ð¨¢”Âq¢(êP#K,ãÑGÅÉ÷m“13BˆýŠ1ÍUóª‹QsE?',T’`¨ð؆­÷ Û«eE;ÿsòeª\%Ú´~Üê|:õ’Br‡P´=„ ¢ÇŽ¢°õßõæ×I´Ûò ”"Ì5o›œ?fëdž(ØÖ¡,÷“öÏ-WlPmŸÞy9ÛÞÏH·½ã—/Ëm®­1D´÷M«k{ö¾!Ä'U]]Ýýíl‚Œ1»Õ¸’Ï/2€âkÌNCÙÉã¶ûîèX­nÚ,(¹ý€ÿ=|E;\°Òìø‰¶:cö蘜ۮΣ£×zg×agûìêøò=(„{ù;öC(WÂŒB!„âc¢,¹B!„Bˆ£OÌÔÌù®Ùlß÷;´û˲p]—D"QX8Š"|ßÇó¼Üx’=h¡ÍÜ‹ÅbÄãñv§B!„0Ó‰ ETUUQRRÒî¢ABìÏÂ07…o2™¤_¿~8ŽCmm-ëÖ­+œ= QEžç1pà@ºté"ª…B!afo¨®®fݺuuÔQ”––6O»*-ñÉ¡µ&“É0gÎlÛ¦{÷î,_¾œÞ½{Ó½{wlÛÞ+©²²’eË–1fÌbÛVDB!„0ÓÆ6nÜÈðáÃ)--•EBÅ'V"‘`Ô¨QÌ;×uÑZ“J¥Èf³{­Œ’’***Èd2f„B±¯†…íØ˜0¤£±@Yvnq²($ÔÞìiÆÒé4ݺuk5V&6oÞDYY A@Ÿ>}¨©©¡©©‰!C†²jÕ*ÊËË)..–O‹øØ‹¢ˆ®]»ÒÔÔD:.´Æìj¬ŒmåÖóІvDlõ{^X»# .„Bˆ}!Ì(Üd’„maÈ­B­3kyâoÏ3`òEœ Ùu61l]>ƒÇžžƒ3þ"®8¶Qôác AVˆÇãüë_ÿ$‹3fÌÖ¯_Gcc#ee]X¿~=›7ofРÁ¼ûî;¤ÓM|æ3S:0ÎFá&Ø¡G6ì|˲q/›ms]-E t6/ K¢“âñ8a†a‡‚ Àì¥Õ,\YËØ»rÄ.»\%½£«÷ !„Bü‡ÃŒ"ËòÜ­ßá¯o­Ç‹4aÆâ´›of´ãÐÑQ':¨ç¥Gž 9î œpp—]ÞÝm¯A« ’ã8Ø–ç{»Ü?‚Vë騶Í믿ÆÝwÿ‘ 8ð”Rh­7îÈÂLO\0…Ûoÿa¶S ˆ§ŠPÙ&²(;FQÂE5Lûõ,:ò2¾:¶'AgZŸ”EÓ¦9üú‹¹àÚËèãD…ŸÇÍü抟Òç–»™Ü3Àײ6è|¸×Z~'vhð×71åä‘ÜûÂ{ŒZ¶Ó–eI˜B!ľf@)Mݺ5ô¾êî>!ES`P¢CÀrB?ÀX E(ËÆul Òe9¸®Mè5P]g9|(½Kcá!Æ(lÇűQ`,ÇRj…ãØ¾Çï~ÿN?mÆG)…1†—^y‘%KñµëoÄóvhòÓÎæ+müêW¿ÙåXl6Ë×¾öß…ŠXÄãÕüúìS©üîóÜ:ÎaËü?ñ™o¿Ì…ÿû&we=е¦S³ÜC¦©¬¬&Ð-îšM¦8êÓçQ\töøBÂŒ1„aX˜®¼#2¾Æ #ªüÝÀØöû"„Bñ‡™<;'Y@ð>ß¿øŽ»÷ÏlýɼÔeý,C'žÃ‰=×ð»û^bk6DÇûsÑ _"þø]<¿d%so¿ƒú¯_Ë€¹ä÷¯l¥I™Ä·¿:‰eÿ9ÿò&ò³ÿšÀ‚¿ÿ”§ÒÇñÝ/ŸJÒvtÀ ^|éŒQ 2”9sg±xñ{Œ>ô°­Óv T*Åå—{⦅tºi‡ûÅãqn»í§\}õµ$‰|¼Ãv\\+bÕ«ÿÇ·ÿ¼˜/üþ>> bí²2Ê¡WËÊ›£ 5>}†¦¯µ™wÞ_Ýý@ŽÕ˜K5±ò½E¬ÞšÁ)íÃa‡€¥3¬Y¼€•õMô4ŠCè‚16]z•·åƒ+öL†h­· ù…ßmX½%Mmc.¼(4›·6zsÞßJiº•ÆÜ»«Í¬€ù©Ð…B!þÓìÉ“'ßrðÁï¤ò¡pœÅ/<ÃË ³hΫ<7k#ÃíÅû/-`À™gâÏz–•Ã/å—ßü<ãûÖrçÍ1òÆÛ¹íš‹9&6ŸŸ>e¸êÆÏ]²”s¾÷+ΰžâÛ¿\ÎÕwÝÅ_p[ü1OºgrÝgeõ¿ÿÆSË—òÞÅ|åú‹è“0(eѿ߶nÝ¢ÅïQU]żÏèCÇpì1vy8Š"–-[ÆATè*¦µ¦ÿþôìÙs§ûcèÙ³'Ý»÷hجpœ,óþï„> l寓³‡Ä t–—÷Kž-ÃqÉÅ|çkwRÕµ?NÕ\î»ï%6g³ «yá¯÷S9âSÝæÝû3îxe+=Êl*77Ò÷ÀÁyëø÷ß§‘.í‰Ûø>ÿ~p:Ý9…K+øÍWn¢êÔ‹[ÉoÑ™;ŽÃܹséÕ«Ùl–nݺm÷;PÕàñ¿O®bsƒbEE–=ŠYSÑ@Ï. ¯O³x]šç­å„ѽˆ¹­×¦QJ±yófÊËË)))‘ .„Bˆ½bl›¥K—v´eÆ`"Mù±çrñá Ò¦”žÉlṈ£F÷Ce²d«×±6³Ž…?ºŠ'¼JÖ&Š©ó"Š4~Þð5=æàn†ŒéÅ„cºóÔÂMø“ÇqÅe#ùÔWáŒ[å.¯yB¤T*Å“Îâ±ÇaõêUtÐHŽL‡×ŠÉ™i©£ *ÕÎv*â­'žãâ~ÆÄ!Åø‘Ʊv,FÌR€M—Á#9ëü)ZVMzö4üm>r9ãÒ¯së˸zp¿¦/þþ{œÔÍÂ"°šê ÕogMžÂ!]&WÑîr—Ÿò üÅÝ|ph_œl^߉\0Ö&ô=¢ÈÇz>Ÿr3¸û~Æ–mbÚ†C¹üš¼zß,:…_}m"¯þæø¿¾ÁŸOÒÚVI²m‹ÓO=c·×°h[á É'Âî§µfôèÃÚ]½ÇA“øÊÀjnøÙÏIßø.=º´m•qû‡jÛ«Û†zOòêÒz¾|xwÒ5µ„±äö»KPìeù13; E ‡ï^2Û²P ÎýÞËôêYFM]š7î:‡ Ô„‘!ë…í~Gq” .„Bˆ½.‹ñøãïÞÔÌWíÝ)ö<˯øþË9õÔÓY¸ðm¶n­äÒK/ãµ×¦³dÉb¾ÿý[øñoᜳÏÅuÝ–'žhY}Ã-<Ž‘ëf‹mëšfÇâÛö¶ã-¦WÎíë¶:»6ûºqòÜx\>½bÏî`4‡öMÐÖÿ\r8?øâXÂPãÑ.ßÚk B!„ØÛ>1a¦í˜­5ýúõç‡?ü A0aÂD”²Èf3\vÙ娶CSS#wÞù+|ßïT×6!öUù0ÓÑÀáÑ.CLÛß9!„B 3{©âÖ^‰¢¨0“YËç³ÙláßMMMò)ûåïDËÏùâ‚!„Bü§Yûû TJQSSC<ïðº2BìÏ´Ö 0€7RZZú)£´´´y*s!„Bˆÿ'_áß¼yóN×[ù8«¬¬d̘1ÒÊ"¹ú'NdöìÙ¸®Ë¦M›ööJJJ¨­­%“ÉÈB!D‡t´ |*•bÈ!ÛÂŒã8¼õ曬]³f¯WjÚNºe€®ö¸£E0÷°»J¾EfÖoȧDc°, Çq¨©ªú#]Í„B×uñ}¥d:Ú™ƒGŒ k·n»Ü¶åúN¾²ÿþÒ¥,\¸pϲKsXÉWbtV«Ïe…mYÍS«í*=ùíZnR…u.P «y?©" !„Bˆ}>È8¯¾ú*guµµµ;¾yÿ çû>#Fޤoß¾»Ü6‹òB¡›ÙŽÉw&Uåÿ×rúW…ÊÝ vlÛÎ¥ ÍI-§‰m)|¬6!H’­B!„ø8¨­«CƒR‡ÝI˜‰Úd|cG>7´Çioã= 2QEabBCTáUh”kQ:´»ÔnwûB+Ne+”ã`Ù6vósùP³§ç*„B!„Ø7e²YÖ¬YKMM ݺucàÀ$‰]‡™=éãž&a†!&0„k5ñš"z…½°)B'}üâj"+lµ­Æ`5e±ë°2>‰(Ç&L$Š“ÝJqšO7j¤?¾B!„Ø—µ\¸]k-7ãw e½>Š"V®\EuM –e±¥²’ qðA­ÆË´ 3{Zx¾«X¾•ÅD–*º5”3”áôfIª×5°ùÀw¨d]a[PÄ–¯¥¤ºŽž‘E¹‰Ñ‹¸Ò4âQeU±¡4AåðP’jÕÕLB!„ûO˜ ‚ d 7줦¶?Hî(ÌìI«L~ßBw1 Κå ½åFïp Š8„”©8É—+™ IDATaY9[ÖæNÎI¾õ>ýBÍhJ8”8ýTœb,†:²±¦‰·®dÖ1£ðb6V‹ #F!„Bìë•t©³î:O@n¢/­u«5"µÖíÎpÜ*Ìt¶é«U1«Þ¢WEÆ'Žæ€h(†z²h ]OrX_\‡j°°BŸä{KjNNöâX1Ý•MÊ b \ .ÃU’C²¤Â8/ÛÛO0 MvB!„bÓ¶›™,â¾ëз;œ½q ü,dÆ †ÒŠ2FÅG3Â9B›­ÔP:.‰:¸†Õ¥K©Ý²Dz‰­ÛÈHãpô„ãiêÝ“—ŠX–¢g£ÇÈM °à=TÚ• Žb!‡•÷åu»ŽÀósÝÙ¤uF!„Bìç•v¹.»3{£›™Á`‡ý2ý™<„.aªÂ:J?cÑÀ·Y_µŽt]š0Œp£ˆnµYâgœÂ“)'¦Ñ¤Ñ‘ÆÄ"ÜA1N1‰Oÿí9âÙJ "ê=ˆ·õD­«/´Ä|æk»&B!„øøTÒ÷ÆD[f:f:Ó]«í›ã„.}èK¹Û »)çø¼ÑûUê¶Öáy™L†0Š ¶ûèÃYž´°tD൙¦Yk¦6ֳ욳˜°j+N ™?²?o¬þ?ëáùAtúƒáyét×uI&“…™¢(Âó<²Ù,ŽãL&QJáyZk‰Žã|hÝÚ|ß§¶¶–¾}ûâû>Ƙífqhù^ø¾ïû8ŽC<—¦L!„Bˆt3Û½LÑé0ÓÙTÔ*Ìp­=¬ž$£"2}2¼uàûlJKK™?>Ë—/§¨¨ˆSN9…9sæÉd>”b~1Óðì³Ïò§?ý‰|p‡ïQ†444pÔQGáy«W¯–±DB!„ó û'åÚtF§»™µ«Òr_S¤œ"T½¢æ”-¬kZM6“kéÈf³Í+ŸÛBg³…c„aX4…ãj–¢! ±•"Ê?Ÿ/K©B¨ØJ»RЦ¦&¾ÿýï³eË–,YBUU™L†††¾úÕ¯rÝu×1oÞ<Þxã Â0䦛nâÜsÏåþûïçÏþóGòAÔZã8N¡EªíkèÞ½;÷Üs«W¯æê«¯&›ÍÊ/B!Ä>RI—zÙ>fZ øod”"Løxv@i6ZGýš"?×u+ßU+BÂ0lu¼|3\á<|«©–˜ßˆkCä¸dcEøNin‘MË.´ÎìNKI¾‰OkM†Ø¶MÔÕÕ1~üx®»î:***øÑ~DE”””ðÒK/1pà@.\ˆëºAð¡¿±;'”¿±XŒ—^z‰%K–®‰üÒ!„B|4öF7³öêƒûc˜Ùãnf9@>tä[QòûX–…eYxÚgKŸÍD•>[š*ñ²&2APØ>ß­¬m¹mçáVnŒXϾôPƒÝ ÝÂ*Â*ªƒjÖš®TšR" vs0Ù7·í*£555óË_þ’šš¾ùÍoEQ¡KÙ¬Y³xíµ×())Á¶m|ß'“É µ&‹µ«’J¥ -(™Lß÷±m›¢¢"‰D«q¾U*“ÉžeY$ ŠŠŠZ½±ZkÒé4µµµ„aH<'™LâºnášÖÔÔðõ¯ÒÒR\×-E!„BñÑTÒ;Sa×ZSVVÆÅ_ÌE]Tøù¯ýkž{î9ö«ñ7{­efg mÑZÓ9x!”Æ!eLhX:tÇ.=Çsˆ¢mßšÓÞÉ·lyPJåÞGšõ*Ýû0~ÐpF‹¨Ž`ÅÖZæUe˜—€D8¶½[©µå¶¸®Ë_þòzôèÁ~ô£B·³(ŠH§Ó¤R)®¾új.\Èœ9sÈf³ >œ‰'r×]w1jÔ(&L˜€ÖšÇ{ŒÍ›7£”b„ Œ7Ïó˜1c«W¯&‘H`Ûv!œTTT0räH&L˜@Ïž=1ÆðÁ°dÉjkk çéyarÎ9ç0dÈ–-[ÆôéÓñùd¡ë["‘àÝwßå«_ýjaÌQQQ—\r ¾ï³téÒÂÏ…B!ć¯m7³Ž5j'Nl÷¹ãŽ;ŽSN9…iÓ¦íp–ÛÿÈk }´rpì½ß"´×f3ë(…a ½H K¼|i/dMírúºoâjŸyfãúEQmŠZ]³Ç/JµÕÕüöƒÁülp‚ž‰€áýºPìn¦ÊMóÊZK™NMdp饗ròÉ'3{ölxàb±Xaœ{î¹xžÇèÑ£8p |ð±X,7ëZ‹‰ Z¬–Ç¿ûî»YµjQ1uêT.ºè"ÊÊʸóÎ;Y·nZk,XÀ#<Â…^H×®]Y¿~=#FŒ`Ê”)¬X±‚[n¹¥0Û@SS@«0ò /ðÏþ³°îÍí·ßÎI'Ä1ÇÃ>ˆçyíÎ2'cf„B!>º`Ò¶Ù‘}vÕŠ³³õŽ‚Û±ˆÂ£l\×ÁR £€0Ô@Y6Ž“ûyóžè0$ˆreo{Þ ýA']ÌI+—ñÌ«‹ð¬±¸ÃÞŠ4íI´ÛÝ̶=o°)HvGÙ.Æ(RÉ$%QŒú:ƒ6¹™ÂòkÇ´ A}ƈ4³6L,Ò”' ÊqRÖȰ®Õuè°Ðj²£²Z¶²8ŽÃ«¯¾Ê’%Køîw¿Ë 7ÜÀM7ÝÔj-™¶×¥í±ß~ûm|ßÇówÆtK¬˜õ<5ƒ­Y›!Ÿ½™‹q)p)·8›°~&wüä_Ô:±½h:›:ÝáM)EÌÖD¨/ D‡¹E1ƒ ØÎT¨[N8P¨œc¨¨k¢²)B(RqCŸ"Ûq:ÔÔÖ2œlÞ¼™Ç{Œ'Ÿ|’§Ÿ~šñãÇsÚi§íVðʇ¶¶-[m[GZNE­”¢¼¼€Õ«Wwèµ 7m§^nÛª&­2B!„û†Ý­“­[·Ž{î¹§Ýçî½÷^Þ}÷ÝÎff—ôæÈ3®á÷¿ºˆpÞ£L}rõic¾ÊÔß‹ƒ¥¼6k5_v¿úÙUôS>&ô(Ÿðmî»ýK”V¾ÍŒ7+9ækÿËOþû|º¹†­sŸ`æzŸKÞà‘‡àŸÏ§ÉÚ{-3åä+Á»=ÖE«‰õQˆƒA)Hû–'›Í¢Ûi‰ÙÝ7qÛº3cZLáìû¤}6`ŽeSÏe‰tØ¡ä›?VE466bY·ß~;'Näúë¯gÆŒTVVb·™%­½¬µ‚쬫WË_IIIaúæöÂÜî–µ³Ÿ !„Bˆ&Ätt)c =zô`æÌ™Lž<™ÿøÇ 0€ÊÊJn¾ùf6mÚDyy9µµµÛ×y›ëÌv^ùÎ÷øãÕÙÏëÂÕß¿Œ`î¹ñ–GÈÆÏάäÑÇ¿Â)G>Â__sÑÿœÏ²'nàæÿ}•ÐQÌ\”æáßÇèG_áõﱪÚgàæ¼µ`>¾•CN‹×—H$H&“íÖ=óÃ$ÒéôëýÚ:3J)Œ²èj*©Ð>‘6XJÑYl »E!Am÷v÷/´ÌXÊ(0 P8J£ŒF)”±mÛ²ˆhÝšÉwƒËd2üô§?åç?ÿ9?üá¹òÊ+Û z; í½†ö¶u‡Å‹†!dzg, kLjيô¦ÌË|Ž=ºÀŠ 0;jJ)&NœÈüã¾¾_þò—<üðÃ{u„³³ÊøÎX– -aQp 2Úaƒè/Âê[uÚÝy°[VÄ-Ë"L¥qK0ÆÐäã&²Ä‚*TâÅãl±;T‰ÏŸOÛ²”RLŸ>iÓ¦1iÒ$.¿ürî¾ûîVcW- ; 8mÿíº.óçÏgݺuœ~úé\wÝuÜzë­¤ÓiŒ1”••Ñ£GcG‹î쎀B!„øpÃLGëÛétš[n¹… /¼°°Ý7¾ñ Ž8âÇÁ÷}N=õÔB½õ _ø àú믧¨¨¨E9@5?0Æ`´Ée‘æÆcJ¡½:lsvi1[pË:t{7ÖŸyæjjj¸ë®»Zm¯”â[ßú/¾øâ‡„ìµuf:J)Eø”W<Ï–ƒXŸ-&³XQ×…Òn‡KÏ Œ¶½Ø¶bwÂŒ‰ lƒÞ ^…¢>pxÎŒ'ÙES ˜Qߟ·×lÁèˆ0 w9è½í4v–eµŸó—¿ü… &pÅW0}út–,YRØ>È,Ëj5 rÞŽŽÛrzçüÔΙL†oûÛÜsÏ=\uÕUœ{î¹,Y²Çq:t(7Þx#Ë—//3ÿßükk{N-Ö²l 3B!„û~˜ñ}Ÿc=v»úÝÉ'Ÿ¼]=<ï„NÀ÷}’Éäöejƒ6…Âj\Ê««à‚I'Qúï‡È(…Ûï¾ï&ØÕ✩TŠ 6PUUÕêZ–Å{ï½Çý÷ßÏäÉ“¹øâ‹¹í¶Û°m›ÚÚÚÂøšX,Fd³ÙV¡!•JQQQA"‘hUžëºA@CCCáü,ËbÕªUœwÞy\rÉ%œx≌=šêêj¦M›F¸®K<ž‡”ÉdZ]¿ÒÒR¶nÝZx –e‘L&Éf³¤ÓéN…B!„ÿ™0³«13-× ì¨|@hÛÍ̲l ¹EF)\·’¿ÿLþÓóÛÛÊy~yŒI—šWîâ…¹•86ÜÿÃyðöÿáÖpó¶öàÜ+¦ðÎ#·ðöª:Œ±Yûæ ùô9\°>Neõ ¦¿ºˆ¬e·š@)Å’%Køâ¿È_þò¾ùÍo2þü™üµé 5uêTó¹Ï}Žë¯¿ž9sæt¸+X¾e"7÷´bÐà¨évë¢ÞTû.5•«pkÑ%»ŽR•!y(:>–#¢(BYвÃC†œQóÜÔW4‹Åro’£ua:ä  c`vvlÛ¶ñœ:å³1 +ÔÏæ·w>Ak±NMëó*...¬¸+Ùl–ï|ç;qÄd²YæÎ›ãlkw ÃñãÆ’L&‰ÇãôêÕ‹Ç{l÷×™É'®–Áu]Ö®]GlS‹ËèN—t²!7}r` ‰+Ÿºv•¾òÛj­Q–Â7i¬xD¿á]©ÝXß\q ¡¢å;ò:¢(ÂqœB8ØÑ¸“ü‚Dù£çy…mò¡#?+C>ä8ŽƒÖºÐjÓòºå»—í¨¼|ÀiÙQ)…ã8…E1[>×ö5(¥°m»ΤUF!„â£Ó²¥eWC!âñ8øÃv»ŒD"Ñê¸~ÅbîûÍ{Ønnêd¯Ú.Õ‹_à®w§a (ËÂqbØh´”býÜÇøåìGsãi, ÛqQäföë7ðÄoçqc@Ù¸® Fo;~õõõn(ùP»™å+ÍmƒC&“¥ªºz§ã4ÚjµFŠR…Ö›|81Úà9DÉFb‰ºöa5·B„aXm§)îÈkèÌs»Ú®3ÇíøB¥{V¾B!„øpµ]4sWÝÌZ¶Ft¦Œ…íØ¹Áÿm7VŽcµ,´õ6–M˧Û>o·8?cvÝ5¬£uÓÎv3Û®efwÒS>д 5ZëÜ Ž%ÐŽ‹ã{ú­.BÛ䥔"t]”18aH”o•‰4V̦±¸‚žåIâ%.Vm®åAë¨UëB!„â“e»–™ÎÞÙ/„ c¨O”P/%J×!½«°›ê1ÍAÇ4§¼|÷©:Û!í¸ C²-ZdpõE[(îP>´;±„ƉŠQ¨Vç+aF!„Bì‹v§›Ù'Ù‡>5s{'`Œ&rlíÖgØ(bý“‰BV¬ù€~kßǭ܈ <,cÀv‡-ªm‡ñå½i\¹,×ãÚ¤&âUõ‡~㺑êëà&\·XäòÝѤk•B!„ØåÃKËå:Dû×iÆÌìiPÊ"Œ'°†&5ñ tמ¨l†l¿A¬éR޽ü=RÕ›pü A¤i´¦¨ˆáHìÝwP–…JY¬V+1eÝÑwt]Nb%Céál^S‡²”$[!„B!>᜶‰¨3i±„Œ¡DAãÈú Äл[Ob£ÀïÞ“úŠuÐP aŠSØ»;G,_ÊÒl'æ²*¾œà€,½G•Ðcpвž1bqKA°¢5[Ö¦ÎÏà%-3B!„b_Ôv™Ý]Gæ“x:fÚÎ.Öʲ ÓÈÈUo±eÜDÖ8q"£sÝÏb (ï ]º@˜%¡Žq4ý—,dýÆ 8ŽK:Èôò)™PDjh‚DÒA)…Gk'²qN¿yqÌüú-Ò:#„B!>.•t¹ ÿ 3{dš×PÁ²É¾=›>UvæÞï5”¶"­Àv $–`0bk%ÕsæR]_Ÿ[FG8Ú¥¸w) å[é^ÇÓ!i¥=›†çK©Ü¸ Ïóð}¿ÃëÉ!„B±/TÒ¥îºóë´ÇëÌìé $¥rcYÂ("³q-ïýCz–sxÿH'R$Œ&奩X»š aH†xžG&“ÉMñFºùp*õF»‘>a_Æl>…õÏl¤ªr™l–L&C6›% Ci•B!„›0#ÝÌ:v:föF7³ü,aæ~‹±¥²’ªê*ÛÉuC3”" C|ß/´´c°\‹ìºz~í‚izy}X¹d5u5Ud=L:M6›Ý¶ ¦$[!„Bñ1ª¤Kýõ?f”‚ KMM ¥ /Ô„ÚPwhðBKw,²!©¸ƒ1†t )M8d‚m Åq‡†lHܵ‰;éÐÐ¥(–Eh,ÊŠ\2A.€$Euc FS—ö)I8h£ÈfÒ83³„3jb[ˆ¹Šª† ¶ ñ²Yê3)×"ã‡Dº¹\/ĵ-b¶¢>RwÐÆi>Ç´ŠÙÔgCâ®…c)²!¥ ?2øanÛF/IJI7·m‘k¡”¢É )I:xAëkãÚŠ˜½íÚ´,7ãGh Å1'W®cáØ¹rKadðBMiÒù\ !„Bì•tÛÀ޲èl–íÈEiï:e3˜(ìd˜ ²4wëîù3Ÿº{>ëËqC»rÁŸßâ¥+Æ0wM÷ÍÙÀs׌㺇Sšpøá™Ã8í®y|ë´!ô-Kð•Þ奫Çñð[›yåƒ*ýÊ|þ¾…Ö¯„+À¤ßÍç7Œ h¾ûä̽îH~ùò*VUe¸ï’C9û 8ot9gŒèÉyz“©—Æ’ŠF~÷ÚZæ^;Žo<ú> ¸ýÓqÚ]ó¸þ„8¨<Å¥{‡™ÿ5–gWòä»[xòª±\vÿ; íQÄ ' âô»æñ»s‡ãÚ7þ{ 3®=’?ÎXÇ»øûãü{Þ䔃ºó™1½9ë÷ó™zñ¡¬¯Érû‹+yóºñüàée4z!¿2’I¿›ÇÇôgÜÀ2>û×·yõˇóúŠþ1#Ï\3ŽÿúÇ"ÊKb|wÒPN»k¿q2æ÷çÀ‰ƒKHg³Ì7ÇÙÖŠ†!ãÇ%™LÇéÕ«=öXË ©¤›«ô·¨S§Û6I%· XŠ9¹pQ³Zlëþí4oëÚùÿƒT¼å±¶më6oëØ€»«r­•‹ ñöÊMì¨ÜöÎqûr;rmâ¼6Ž ^Iœ_<ÿvÜÁ²dEX!„BñÉcYŠÎÔ„e:…˜c)f¯¬Â±å­B!„BÂÌÇHÖ ÿŸ½ïŽ—³(÷ÿÎ[öÝrÒC’ !„JCE@ŠˆTEåÞk¹Š^½êO¹–«^¯¨×¢b¥ƒ…Þ{½&”@I ¤×S¶¼eæ÷ÇžgóÝÉž“sN*É|ùœ'{vgçyæ™ïSæ<øõ#Q«$n0úæ{f¸D§M‹(`ÿÞ¨º‚fÛ$4VÜ·)2ã ™M43øÀ”ígîP‡mµC\šÙfF–fø÷Ãw‚Iœ1ãààààààààààŒ™·Šù{Ÿs'ŠÅÐ †ƒƒƒƒƒƒƒƒƒÃ@wiã¦G¹–âÖ/½ eWÀÁÁÁÁÁÁÁÁaÅ@ÍÀ6dœA³©¡ðú²N@)7öΚé<âÔ›ùÐÇ_3ù\àÃÁÁÁÁÁÁÁÁÁa@ÆŒÃfAµš`Ö߇j9vƒáààààààààààŒ™·‚œ³.} ~ä"36fL÷ò»ýºý7Óâ?û³ÜFO¿÷¥íVŸµ_kõÞVŸ]ß¶[õ¹¯mÛ¯)(tÅi#Ío m÷6Æ}ëÙvO2Ò—1ÞÛÞ\²ÝSÛZ¶×§íÞ>³¡×Í– Û[óºq{ÂæÛú2nOp²½¹ö„Í-ÛnOØ6ÖMôu€ûò·¾~v mt¯ïg7FÛüZ'øÇgAá¬À”rn{cÍcŸÛ6±6|Þ†n{cöÛÉöF“íMÑö–*#[CÛý•_·n6l¿-ö'ÛN¶7’l»=aë]7­°eä6ÀŒj ‘÷ ºª V”S$¨Â—1À¡yäËU,N¶œzQ>Į߹ ¹ xÏŒÂÈ!†õÀ›6J)(qš`áêÙ~ŽA#Gà§ŽÃ/®š§ºzžƒÁCò(V«Xo£9Žžíå0(T0Ú RK°¤3E®”Ã0bAU»ZocÆh¨AÃñµ÷ï„©ù +ª”§€¸†k›‡;ç×P‰5¼œœª¿¿„‘ža IDAT@’dÈ´ à…>r`ŒA-ÑÝu¦TàÁÄ>úéCqä wã”éAÁ‡Ê2$Y·µäyˆBo“ÉZšá¿ßÿyÅÓ¬¢Yb±ßx5*Båðž]á…Y+°¨f°`ñRüôŽ·PU ð<„¡‡@-Π=dº>–9¾ŒòËyðd©FR·ÖŒ[ cPŽuÃHJÓ ©Œ­ï# j5…Ó?q0N»ó>ûŒ†Ÿ÷zõ¹2ÚJÁ}„ 0Ú –vÏ¡RðáÛÜúI2ǵ¾9ÉÃÜÕ) <˜êJ|ëo`·÷OÆOÛgã »Úœ‡¼ĉ†n%Û©î^; A¨¥Ýã×-둯º—–®¯(¨@ÁdèžGÓ²mgÌôÏ’A5Íáógì¬z§]» kð}ŒAÅ)j¦€oüû.˜sãó¸f5à·Æÿu~}Å+x1 ñ¾£&ã«ûATnÇ7¾Šk–¦(”Jøü±»àôò0qÿ¸w&nÆâc%ƒ‘'€;íÄOo| ÇOÄOØc|ƒ¯ÏçoZŒµ‰£6Úà FÙ†»d&§\}ï,üÝÅáCqá™;â·7¾ˆi+2‡ ÃÿüûÁ8b»óf½‰oßú&^KrøðG¦à Ù‹0¨Õø¿¿ÍÄ[»íóŽU³çà³7-ÄJx˜zè$œ©jXµÃpì]Rxá¹9øñóíÖ´zxÏ‘“ñµ)ƒ1ÌË0íÉYøö+0vÊNø·Á ïxßþ¸ý 2~çlÜøðo'MÆY»‘,_†ï_3 t) 5?:~':,@µc5λý5ܽèm|±¨ÑÈ¢øæQCqË/ÄÏÞ2ó¶kó‘Š3v‚ {àÖ]<ñü,|ï±N?~W|q¯AЫWãÜgã®)†ŽÏí?& °çvyL»ïT÷Þ‡W«à²{^Å¥¯V(…_:ûä*øÛ˱ãä¸v6^Mr8å¸Ýñå½ÁëX…Ÿ_÷*n]©ºƒƒƒƒƒƒÃÛÖ˜1›áÂLc€Á#ñ© .:w!æU=Dž‚Î2,\Q† ‡ÇFÙ¯ ”—ÔJ…÷œ¼~;j)ŽÿÝL”w|nÿØnxýüÑ6e'X[ŒS»iTÀmoΗ½½ë|ø… :Ïœ6?:ÿ1\יþãB¤ØôcåöÓ{åà úÝJ) <O)„¹¾÷ñ½=ü<Þû|Ç0¿;5ÃÉW,ŨÑÃðá±Uœô§'péûàÖÿw0nyèœú›ùøîöÃïö\†=—¡4¨ gÖ†ýd:¾ç Æ_>¹>»øyüµ   †B¥}ξp&æCqÁöÅùíÓðÙ§çã²£vÄ >‡“fdP™‡3?}Îîš…ã¹#¦î…Û?·+?w>rÔŽHžGÍèÂð!䵩ËèÛv©) Ò‰GV†øäûvÆË÷-Â# ÊX¶ZC›×ÎZ…=ºæà¤:­ð¾“÷ÃÏF-Ã1¼Œâ^“põÇ&á´ßÌÄò ‡c…«/~ÿ6§Š¶ÁìûÒ\|ð–vÇÃ…'OÆ[+žÅm+ øÉ'ö@í®'ñž_üÔA8¹m)þ+¼ÿ#àÜÂ|¼÷‚¡v›„»?½+æþì%¼®¦žƒƒƒƒƒƒÃfÁyž×ÔÂ&þ1ƹƒU‚Ee è3|íPÌúÞ{ð»w@®Áðu÷©æB>·k€Ë§­@´] CÛWc†á¬–vÔP1Çï2Kó—Ua ëdº-–¤Š×:<¶çh¼{\Ë—–Q6jA­ãÙïƒZ¹¶q¾Ã@@§(Œc xhq†ÉÛç±ð巀ѣ0¹¨áùÀ÷ÍÂÓí ž|~VåbüñÞ%XݵÍJ°÷Î Óðേçâþ²ÚWá¯ó2|rJ&Ó#]Ê$x~æJÃÛ°W[×=WÃn»tV¯ea e0C¶Ã×'¥¸è±Õ5¶ýÆB<9h{ü˨ o¬J0aÂH?q†«K:âîÃbo× òËøÖyÓð÷røÜI{ãÑoŽN‹íU†Ìt˵ÑÈòEœ±“‡Ÿßø&^K2Ìxn>ÐCñ¯ÛyH`°löRÜöVÆh´¯.cÆ’;n߆1ºÏ-W˜0<@nô8,ÇoŸiG–và‚ç£ÝLi(¾¼+pÑÃ+0ht K—ã‘Ü(|jeoçñu?îÇý¸÷ã~ÜÏÛþgÖLÐ%Ñõüú5Æê»)e}ƬñH¯ÕVw~? °º/ëIx×XWÏÔÐo½†#~úŽ>rœ(@ktŸåÐ ™VTýE`|ìðŽá8&QÈ)ƒYOÎÃ++3¼ðúlœSãv‰#ö„êsñµ;WÔ#=Yý¼A®k >~aŠ3öƒ†”ñµK_Á3±{§ZL9âNܱØÃW…k/}…=&ཅ.|fiŠp¨éŽ~ÕçfâØá(-]„ÿ¹þ ˜¡cpíþcàˆ½…§sïÄ™»†øá‹ß;°^ ´/ÇU‹>Yè—ÿ9]Èa—]†¢Ö™Áo¹ÿôG¶7кi)ÛfmÙF YXgÛÔ?ùw«uÓJzlÛ:hÇmkM}4Íc…>´Ýj\×j[¯{<ÐÓºéA¶7ȺÑë¿nZ·-ã:à¶Í¦•í>ì —í>î ý’í>¬›Êö€ÖMd{ ßÖ%Ûëݶi=þdݸ=aÓî fÛÙZ¶×ßÈLùjñð"¬ÚXB`ZÞ˜µÆjÛ^}øI½jüâÇâ§Ã¨¸Š{žšƒN[‚ÌÏpÅß_Â¥ŸxfWÆ}Ϯīµ<"/Æ•—?‰Ü©ûàés§`¨I0ëõ7ñ™KWÁ?Ÿz ÆG +-Æ·¯šÅ^†›®Ÿÿ8ë(TŽ_3ÿ¶§3 WŒ‹à%UÜpÇóøG)C§ú6&€51üüôšš^#|I%Æ‹?8¹_†¨µn¿§¶Y¤¿Ô¶¼7Íê Zºº ÿ}Ù+øùGÇÒÏ„¨vtàª{gâç–¡3]7º#tq–­y´,C¬ë¯û¾Áó,Çû?õ^\¾=pç=Óñã×kÈ +!É ŒRH–ÌÅ/^Škþ÷X¬Xµ·ÏîD¹hó3ÜzãkøÜYG |l'¾tÑÓ8÷7@t?ÌýÕÈÅ5<óâëøô?;0yï]pÝF`˜oðú«óð…k£¢ë%¦{–µÆÈ`³È¶Ý¶‰kH‡ïŒ‹¿¶&ð›‡q÷ËKh|T‹°ÚëKhÑ~ëÏfi†´;B( ð„>|e`´F\ë¶Ö¤@PÀ §¨³pž‡ €,E‹wÀƒŠ|ä'µnÙöºßç+h­‘$a΃§T}mÄÙšö”‚‘®Õe Q˜pôá¸ö€å8þ‚YXxˆãtM=ßGùð×)Û¦c×Óø`ƒËöÆo½¼Oõ!%b]ílŒ¶7Ÿlož¶±Ž1ì«ÞîloÜ=aóÈvOsÑ—¶lo~ÙîOÛR¶Ýž°qd{k_7=Ëv-Îð»î‚#w‚rµŠ'ž| A°&î’¦)Ü* …¢(ÂèÑ£qýõ×sdF¯9_Ñã—ëjÖ1Èò»g½·ù3¾øQÐüzwŸ¢È_Ó´oºÏÒQàa Ë5Ýg1ü|ÐÜo­ Tý’ÊFß#Ïò’™¢zxÕëóô5‡Yë “¶+áþ—²îÇhÕv«É7èË™ Êy O×KzŸ6×ä¾’(Æû@ši„¡A¡D>"B›0õïéž³(ô×–S­ës™÷×ôUÞr4ryU-¬zeÉŸýÿþlÌ=åºd»¯móº1Ýòê5·ß}N&jÈ÷œ„ê—똆 {0u£»{< ¢œ¿Ö3™ÁÎûíï좒y=Äà÷×ÍÁ2„Fw·Í^$ÝGÙ6è_~~_×Mÿe»çMiý×Mï²ÑJþÖõ¼½mž«mî«uÓÛw÷W¶7ôž`¿ÎïíKÛ}]ï}Õ›nOØø²úÚ›ü™·™loŽ=¡ï|‡÷„ž¿sc®› )Ûf˶Û6ͺY—lo¦=Á¬ï™c¬\µÞ¯e `¯eýhÛô³mÓ6² Ðv¿³ç÷šZŠŸ|h*.¼ã% ¤Öñ=èc_ÍžgÝmðÐ-OáT“"§Liªß¦ó³!Ûîl´m³×MÖäy}ÆKøÚl¾jµËËiÝ~1›F¶Þö¦—íu~cÊöæ\7f¯›õ—í ¿'lˆýfs¬lÁëfKm¼MdÛláëÆí [çžÐŸ1Þ„ëÆ¬O53¥`ŒàÁ‡#ÌûØù«ÿ@XÞã_­TQíãsؼˆ«U,¨ºqpppppppx@gXÿÈŒÖë_ÑÍ¡_Hj)þú¹cpú/îD.ºqppppppppØö0ÀÛã­33Ú¹Û7ƒšÏukTûn<¶Ac&Ac3™ÈMŒ\Îÿ¼¹Èwãïàààààààà°mbýÓÌtw#VžÙºªó­ë}ëªv×[û}¨öf CŠ ´}OÆz¶½ÎÊ~ëj»§÷aÍkq%Ƽ¿œ…í?ù'ä䞙ުÝõ£í~UÐëKÛf€ïío_úÛvomnʶׅþÈÑF^7ë-Ûëª@»®¶7…loȶû+ÛjÝl‰²½…ï [ôºé¯ümŽuãö·'lˆ=aK”m·'lù{†¯ffMfOÿ^×ûúSˆÁþ÷: %dÚóß;q2î~y1ny­Ïó6HÛë,&aÝÑÕ²]Oís5ºøÑõOÖËäJd¦¯…-ÌzŒeŠšôµmô³í¾ÂÐXwiòÞÚ\ß~÷§môSÖ7ÓºÙ ²Ý[Ûªmo Ù6›Q¶±Ëö¼'ô»íþÊö¦ØL?æiKÝú"ÛnOغ÷„-Q¶Ýž°åï zC¤™µŠÌl¡È ÐV]„«þëØ÷ñ¾Cº°úü«ñàÒ<µ‰þôu{ù¬ƒ'_]Oñ]W‡-F¶Ý|:ÙÞææ`c®'ÛnÝl­{‚ƒ«&c¦ÿ[»ÀÛd®‡è.\yö‰Øs§±¨Ô䣮ýî'pÜ׃§»†m:ƒf}²r ÿßGœô -ﲃƒƒƒƒƒƒƒÃ6hÌ­wšYwdFmÉ‘c† Îû蘺ûÔâ¤ñ×®jŒÛöŸ8ýœ‹ðð"Ïßò«ƒyûœ}üBð¶1&6,Í_¯ªÛ˜Ù²Ét …!Ù*üúcïÁñ‡î‡ÎJó€J•Z‚ Ïþ¾ðÛp×Ü¾Ú²ÓæÒ$ÅiNÂþ¶~.p‚ìàààààààà°í![Ï33Ƙ-¸4p…AñJüó›ÂÞ;_ËaóyüáK§á_þïbL[žG¨¶`#-Ið‰£§à—Þ ºK¶A 0C©aÌ„`² Q.@¦5´6}I–ÁS ¾ç!NR¡ M3ärÒ4ƒ>’4…§’$ƒçuMš"ô}iVoše0¦>6q’Â÷a,þã´£qìŒ+¿õ¯ð‹ƒ'iŸ®£«Š~òŸ¸kÚSxyQ'~ôÅ3qÚýgr$öÚy|üœ?à?þ<î{ê%\wÿ“¸òÇ_ÁWνãG ÃÙgž€¾üs|÷Ó§ Tˆpöù—ã¦ó¿„Kn~ϼ2üŸÿÀ§Îù-ßg7œqÌA8ù¿~ß|ýß°te;~zéM¸ù—_ÅO.º+:ºð³/ g|ý<œyü¡8x¯IøèÿüWþà³xâÅ×pÅíÓðŸýÞyæ×1¤­è¬r‡mµ8Åðœé÷©uùå—›“O>«W·£”ÑY©!|]•Jù©Öˆ“m…•Z @!…èªT…!ÓŸÃûRÅL>ÃQšõ2f¶NØÆLSÌ´ÖÐÆ6€ Œ60Z÷«¢™mȬÜ™‡mÀYïï-b“¦)t¦í@g)Òlír¨ŸSÙÖ•f¶^gf\š™ƒƒƒƒƒƒƒƒƒÃÖNkeDðû*• V®è‚NìÛcŒ6èêLaÌšrÎi­†Eo,C§®4½ÛS jÃࡌiŽÚ؇ÿû[Y­GcÆÁÁÁÁÁÁÁÁÁÁaëBO˜V¨Tº0wÙ˜߆L…àò0VC¡nìTâ»ñÈâÇÐ\FÀPPËÚ0iûáítºÖwÛge6H—fæààààààààà°õ4¶ÑÐêîc4´éBŒeÈL¸îvQElª­ÿ–Õ#”jŠi­›ŠdYÖÔ§þÞ7㌇­Ü˜iõ»ýž Pˆ<èZ‚Ì>£Õ±ÑÈ(êÒÔžŠa”×òû[!Ø ifΘqpppppppppØz`—Uî­²ï=üPì0AÔô7­5ÊååXÚõʈa8“†¿y•µˆô0¦m,²4A’$׳,C’$HÓ´ñ³>p‘‡­v$Du§}µäýÊÃÐÒQ9ôXAДò•¦)–,~Ï•ŸB—©AÁC>?S'|ƒÓΖ¥™µVHâÚZif½U3pš™ƒƒƒƒƒƒƒƒƒƒÃÖmØ´úݲh&i[†‰F’hJ2SPÐP­&½VE¶¿—/ÍÜ ´Öý¶†¶l#¦¿—dòû%šƒžî¦É2è³íŠV÷ݬ!Ód̬ÛJsppppppppppx;3k ý¸_RÞoûúS©¯% í43WšÙÁÁÁÁÁÁÁÁÁÁ¡_ÆÌl}£õÓ3ΘiüÞ[5³u¶aºSÇÌÚëK{|èߎÈô'RÔÒ˜‘ÆÜ™‡­× ˆ1£”B±"ì,#®T±®Á@õ«=6bz¬ª6c¦Õå5[!ÓÛkëB”ýv¸r‚ž7AVFµF‰ééÍ3[Ÿ1³¾† Tã¤|ãÃ8ëêsŠ˜1iš"IdYÖ0hÖ'3ÌÝ3ãààààààààà°•C †õ7h€,Ëô9­5Ò4]Ë aƒkÀÆLK´98888888888lùFŒ1aƒ,ËÇ1Ò4ݤYYòݵZ Õjq#I’µÒÍlÌ88888888888l]0ÆÀ÷}Œ9ÕjƘ†1±)Zë†!Ç1jµ²,CEëi¦XlîÌŒ Þs+ IDATƒƒƒƒƒƒƒƒƒÃÖ¥FމeË–aÈ!¨T*(—ËHÓt“U’f&)fI’`òäɨT*H’¾ï̘‘/pÆŒƒƒƒƒƒƒƒƒƒÃÖ‡|>8ŽÑÙÙÙH÷ªT*›$:Óªs†Øyç1nÜ8¬\¹q£P( ܘá/rppppppppppØz ”B†ð}¥R £FÚl}1Æ —Ë¡X,bÕªUëeT¹ÈŒƒƒƒƒƒƒƒƒƒÃVáùRÕ, CDQÏó6¹  ”Bš¦èèèh2ë]ÍÌÁÁÁÁÁÁÁÁÁÁaëGš¦X½zõfïÇúÜ/³–1ÓÙÙ‰U«V­eÁmˆ/ÙÔVgO}~;>φ‹méù×õ¬Ûš,lkóëdÚÍݶ(Óo§±í©¯[ïØÖåØñ''ýÖù|aöߘÑZc„ H’¹\Y–A)… e<Ï$IÏóšêA{ž¥´Öð<A4J½yž‡0 Ç1Àó¼ÆçåsR..I’†…Æ—úpâ8FPJÁ÷}¤iÚ(ó&9€J)ÔjµÆû”R‹}Â0D’$H’a6>EQ£šƒ|Fú•eY£.¶´/¡± c“¦i£OR‰AÚ‘Ïj­›žOÞ'mñ-¨òÌÒ†Œ±Öºñ9~.nG^¢qÃ÷ýÆóÔjµúĪÕjãÙù»dŽD´Öñ”yâjž”¿Ë¼I{iš6Í…äIj­ó`Ï»çyȲ iš"—Ë5žWžEdAdIæJú’ËåÏ*s$ý–6eþe>ùùe¼eŽkµZã°ËX–eÈçóH’¤IV¥Mþ~n“+zH›"ã²¶¢(j,nžw#gî›ôKÆOž‰û&r&mÊ3§iŠ(ŠZ¾OúÌ ‡•²ÌŸÈ¹Èƒ]7žçB^—öå9%§Wd…¿Gô ¯YcLÓš–gç>Ëó‰ìgYÖ~Ë€ü¿Z­6dLÚfY¹”g ‚ Ñé÷AÖ¢ü[æM^—gæ±d9ä¹”ïç‰ã¸IïÈÜp A†ÐZ7ô²¬E鋽îY¯H>3Ë´ô×ó¼¦õÏû†Ì«ÈtÇþ‹^RJ5Æ\ž¹P(4ɇŒ•Œ/§'Øé²§±œÛóÍSEÞä™ä3ò<Ò‡Þt´ìŸ¢c‚ hè‘!‘)™«\.×ey¯<§<Ÿü.}‰ã¸¡?dnYïñ~Æ{/ë Ù;XGI©TÖ;<6ü»ô¿#T*•FûÒù=IäóùF%£V¼CúÞŠwÈÜ0ïÊHÌ;DYOÉçzâÒGiÛæ²þûÊ;DXGɾ±1y‡ô ¼ƒ?/ãÅûš<«´#{¨ðiÇ÷}T«ÕÆØ×jµµx‡-Ó¬dZñ‘EÑM‚wˆn]%s 1Ç6ïuÙïñáù½ÒÞÁã }ï¹¶yßó’ËåÖâ®­x‡ð|Ñ9¾ï7Æ£¿¼CtŸôµZ­6Öf¿Œc FŽÙ(é>é çyˆ¢µZ­1¡B.óù|ÓdJg„hñF’Ïç›>/B"í‹Å¦ Zú$$§R©4„4‚Æd3ÙfR:;;1xðà&²Íäž•´([ ÈÄT*•ÆäÉÄÊÆ'ÊW¾Ãó<”Ëå¦:Ú²8…´Šà²âgcEÆMAžK6i³T*5Æ+MS <¸Ñ—jµŠ#F4‘ &v"h¼I‰–J¥Æ÷q_„x²â’ÏŠ’ãR{22Vlø¶"†L Dù1áã±aƒJ6™r¹Üxž\.×dsÿeóå -I”J¥¡e‚(Ƣ̵̣,Ly.!f¾ï7ªˆäóyÔjµ¦ƒxRo}РA ™‚ЪT¡õJ¥‚!C†4©Rûr,ÙÜí±y•ç—u$ã$sV­V2"s( Q6 .ï(ë[”·ÃW4aã†Û•µÉDYÆ@ú.:H {Þ¸XIJJ)‹Å†ç×EV¤ i¯\.7ú)ó,¤Ld]úa“Ñ%¼! !â¿ }!óɲÎHtŠèhyyuºèpÑ­òìl DQÔÐmBÀEEŽåŽ€(Šš6+Ñ™2öaNÑÓòÜ2^Bîeï0Æ`èСñ—ñd¹·DLšeležD¦Ù`aã]äMäŸÉôß÷ýF_x®eÏb2.ÿ£QÆEȳ쫲öDÇ1Øh9–÷±L³<är¹±yeù’þˆldY†r¹Ü_Y‡L6d¾¥Ÿ¶S€ Ò_Ož3ÑÅB”Dȸ3‘=ʼC)ÕЛ6¨A eÞD—ˆ~^ UÖ›ô#ŽcdY†B¡ÐøœÍ;´ÖýDÆUö¾ÞxGWWWcËX‰L±Ó ï™á½Zd›#þ½ñΘ*‹M<®¯¼C¢÷ØØ³ú,ƒòüâxcÞ!Ç^dý¼µ`ÁZò9nìØÆw¶µµaæÌ™kŒÙPE‰ ³7[7dy`^Ì­þÏäÓNY“‡ã¾ {xxã¼(iö"1Áâð({!xÓge/Ê”S3äoLjy1Ûi²y<íÔ&ଈÙÅ©y"²éJûò>YòÛÄ€Ói9Ê-ú•™?6@X÷r šŒ {ìlo/GÙ;mo\%‚mONùdYa]-Ÿå´vòé•geýĄм>9µÆv"pŠ˜mHËÂFGŠøØY%}eãõƒÌ§Œ¹~ni‡.^ã¶Ã@* ‰w_ä£<޼ÆåwNëùãg].sÇû§ÓÙé…’"ƒòlhqœ¶Æi3Ì;¤-ч6ïñ·uD+Þ!òd§3ï°÷#›wØ)O=ñ&‚"ì0㈩Æ/z\äKd–y§º±C³_˜wÈíwØïayf#VžÓ9B*÷Iö6þZ=ñ;ZÒï`ÔN“q™ä”¼V¼ƒâ”ÏÊ{8r(ãÁú©•L‹!Öï°÷ÐV)ü¬sØ0cÇ?¼ÿpzq+Þ!?6ïu!2¹!xÏ•Í;ÄAÑÕÕÕocÆã³<0¬Ü9”-!]Ù ì?/ ;´ÄÊH„Z”–­tòù|“'™=¹µZ­)„&ß)ƒ(ʘۓÏq¤ƒ£ó-½œî DLt…Ì{Øy3/R¡Ph´É‘鋬sÖBj9}‚s€e,dcãµÉí‹r•yï’ÆÆ‘@^ëvj§DØaxQÄ|Ž‚7úV©ò ö¹ þ¬@ô;“X?ˆagGtX±ÓN•f{Í9Pt¯<£è ‘ÓJ¥Ò8{ÁÞaÛ{ÇžCŽi­‘1Wv<É…o­öÙt9rÆÎ*&óL–9EKæ•×°ŒD¦%š_«ÕºÉNŸ±ÏšˆÜ²Žæ´5Ö»Ætuu5éSû\ƒ†\.׈Èúã´(Ö ¶|‹Žæ”2vb‰ ò˜p$^äMÖG«´k>¯#rÏ}³Ÿ[t–Œ·ðv¬0yc9h=ãóâDàtOáü:§×Ù¼CæŒyA+ç£ð6$Ù&)ô̧l#Uæ9šèS6È¥¶£QÖ*Gž„‹‰nâý„õJ+-ú—Ó—l½nïÁ|L ï1•ygR/é«¢‡ÙaÉ2-ã!º˜9VO¼ƒŽ>ˆ,Ø©g2²þ™w°1Ê*Ÿ-Þag1õÆ;d]ò߄ǰ^ô¦•ÑïÈçóMû€¬}vH2ï>õÄ;xmÙ¼ƒÏj²cNtá@ЈÌQµðr*oÔœß'ï“\l{9Å‹½S|¦‚s{íô!è|•½’÷ËÖ+GTØãÁ„Ùó͇5åwÎïä\sQVvˆsn9?°P(4{s$õAÚæ´É…dòf0¢¤ …BÃ{ÂÞn(Éæˆ{_xÌe.d¬¥_|6IæErÍ[å°²ÌHª„ß8/ÃÄDkÝH “š½2÷|þÈ6Ø€æBN—Òf‡½ÅkÎF•(H6(dS`GƒDìC¼¬D9×\ˆ¨lèLeŒmÂ(‘xæe 9gù’þ‹lŠ¢äÔVŽj°cBÖ$§®±Q*ßÅiœ^(D‰=þÙä4VN¥`ò!yͼ³÷#+¬'„ðÉ܈^=a§§ÉÚ’¾³£„×4ë›Ìs¤]œlàËx³çN<ùBŠìM‘×GC„˜Ëë]]]M›-Gª˜XÈ\°îå” >¯ÄE'dì9M‚õ/{geóæèk!åBØËÈé!2¿¢£ùü{Ì9•ZÈ {…ØrJ§[ÊÊó2™±#BlDHú”ì òâ ã4/‘5ŽdËá}–i.ÀiE¶Ã„½ùÒŽ|/Ÿ¹ ð)­›É©È?Ö_ï™Bj;l£q]¼CÞǤRx¯GŽŽŠNeRÊcÁýleÜòyVy>;ÂÏ$N…çTžb±Ø+ïµÍ¼Cô>Ë1èý"¼ƒvæ2ï`¼fÏNõV¼ƒ³)DGH¾ïàâ#½ñI5ätcÞß8œy‡¬eÎö`ÞaGŸÙ±ÁNP»ˆ s áìjÅ;ØqÀ<Ãæ!œMЊwpºó;²ÉÑçÞxG÷˜wp4Ðæ2—ííí çw¿ÓÌ8„Äé <É­*ñ┋2³óVYQpå3&ávöÂsŽ0‡ ™ôÊq^9.æ'{ ÙSÊÑöÞ±7€Ç„½3²P¸ê§qøÙöüóáPû §É´ªLây^#ZH‚xù¼G¾ø9ù‡7…`ñ¡löt‰ƒ+ÌT«Õ¦Ìyçœë)Q'Û±«ñwÛùõò¬ö&h{0ÙKÃri‡§¥¢€¥j­BÈ|˜S$G8ÙËÉÞ–iþŸ•£™¢(™(‰’±‚nS&™vª{ž9½ƒs»y>8ý¨U “‘i‘C‘INõ`ÙãKª—¬mަð!i!âœ>ÅÏÌ)3ì™ç44öFK¯Ì…xìy®ÙñÁ‘1´8mÖöªó&Ϻ–õ‰}FŒ j68`§UÙª¬/qþØ2mW>â³c,óvDÁN‘`/µ1…B¡¡9mAÈ •V‘d.*ÁÞ?ž_ûºífg€È‰è v2p‘&)²Çð9>—Æqްž·=£ò¬¬_˜ðˆƒÑ>§Æc { {ŸÙ€•yã´-!‰í³ Zæê}võ3»Â!G&ìóBUæè§gñ^kó–C>;Å{Áºx‡È¼®=ñ®ÐÅg€Ø°á½ZÞ/û!;2ìêvìfÞa§Çµ:‡ÉcÂY, vJ;šì3ˆ}áv$Ÿ÷:Žþq¥P›wÈ3ö…wˆí‰wˆÜÙ¼Cg­"tÌ;ÄñÈÎ\1¼XG³žcýÁ†bO¼ƒõ;ÚX°Ì3ï½€Ïr?[ñù.I½³+òq›Kóï|^ˆp6ï°ÏUõ—w´âÒÌi:;;ûmÌxìU©T*MVž-´¶B‘¿±‡­K{S³óùä§5»"‘]–˜½0œ‚Æ‹G„…7Cöú³¥*›<Ÿ=áR™\åÍ…Kí* \Í„C€l¹ó†Îç*ìr½vžÛàaì™HÓ´©˜Ÿ7à͂ɟKáû¼±±gšS …BÓ¸Úùöœó-¤Š¿ÏNCcЉSSø0ž¼§V«5dš*“V(œóÉžŽÔpµ&Çöæ,DP•Ë3ñÙÞ(¸ºŸ{àò\Ñž/Vêâefo?“|ž+Ê3rÊ)o:BîíÔT&Zò\vA . ٪ī^%Ä“#,²®E†8¢e+F6†y£æ°l@sÙINµäB LÆØø“×å™ùìÏ!G¨9B'“RŽKj§lÚœRÊÞHÞôeìù°©Ç©Zb¤².äóO¬£mcÉ–KÖ ’n^NAáó‚<~";òÜÒ&WíÊçaxßàÊmœŸÏûÏ‹Æb'°‹ðuÞx¹ ëyvN‰Œñù"®ŽÆ?ÜŽ‰ÌqJ³mØóß8¹©’~‰áÅÄÏ1Yâ¹ ·ÓÉåó¢£yÞÙ8·óü™wÈz‘Ï˸r‰rÙ£zãòÇî™ÇH_eqá NkgÞaJaÏiéÌ©D‡‰,ô‡w0µy‡}æÎ–ǾòŽ&H›¬ß8½šy;í¹µy‡È4;½øÌïï¬{E/1kåhäv¥Sv¤ØçE·¯‹wÄqÜÄ;xMqš4ž«q*,§qÑ‘1ŽôËIjž¤°1—¶ys›«Û¼ƒ÷Iv䯋wp¤œ>æÌ­ìsCýN3ãƒYl•Úá)®ÚÅéT|çA²WEþͱìúô­¿1áФxû˜HrʈM Ùxà4-öèpítŽ,°']¬B^¨ü<,|.†­VNÃ`EÌ%[ÝYcOv«Ò²¬8åYÅêç’ÏݰáÀå¡9…ÆŽt‰×¯R©4Ór®¬]Á‚Ó.ØûÏJÄ®¿ÏºEY¹ÈüÉfÍálVX¼¹ñ†Í©Cr¨›7U&þ\r–=p¶GåÖ>¨Ê¥³í@.ÌŒIží”ø쵱I²üߎqª•¬Ž °óÃNq‘¹àÈ ëN-µ«µònÙw@°âä(—ÞlåÁµï¸±š²Sî.Æ9×<× I[’>°‚fOš(|û>Qâ\X€SX¾™xØQTNe="óÃíIÎ:{|¹È‹<§l˜|ÖÂ>$lëg^ûrîÐ6\%=ˆI(§>Ù÷IÚ_«õeŸ›°£ vÅE;_›#\]OÖ 9§2ÊøðXðy!6ìEgÃÁŽs¥,Ž.H¤Ï>sÃë‚×ïYLš„à‰QÌàì³Hìã, 68%…çžS¶ìy~Jœ¼nëhް1É%Ó™w°gS±Ùp’çä*;E̾?ÉæLüDØ)ªvq€VE`d­±aÈsXø¹zâv„Ô®†Å%·{ã­8Ÿ¥´‹>õÄ;˜À ï`ËNmv¨2ï`'¸ìÞÁŽk»È]9‹dœÐŠwðyòV¼ƒ|’­íÊ–=ñ9ÄV¼Ã.ü‘ö>ÁûWÊå»xàhWo¼CRGí´c›wØ\š£€ò¾öööW3ãð;hfÁ…NQ­Ô`ü¾RÐI•X*  áé°óíY¡çr¹†ÇÎ3±‘ˇÁ؛ΡDQ.| C6.®rd[“vXÌ>¨Æµú9œË‹Cr’SÊéY|Ž€=j|¾Ç¿Kª†}×—˜–+•Ÿì|z» § ñ¦ÇÞ 3ŽVÉ‚’d¿WÎHÉbá´%>óÀQ5!†’N"-°/?cE#ýéêêj*$`o.Q`ï©l ¬H£(j]’ƒÊœWZ¿FµÜ…,ÓÈ´A’iè´Šr¹Ò½¤€ò“"cÄËÐqí]Èd)4mìm‘ ÈìÔ'Î1gå4 N×ã 39eLªzÙwaȺæƒ~vJƒ¬e;íŠËó ytv´#I2xad)ªÕ.d*D©¸f”üû ðQ«Và‡âZµ©Ð÷Û¾7€ ˆðƘe¹PaåÊvD…"ŒÎš¼×x@’jD…"|σïyèììD¦ ŒÉàÁ R­¡«\A˜Ë#K“µR›Ä³ÊÌyÓ`™f’V×M)¨UëѨ4Ë ¼µ8F1ŸC­RE ¾‡&ƒÏS@µRF5U(ä›urˆrÊHµ‡( ‘¥tREbBD¡‡¸VAgG'Ò,C’jä¢`]tÊ^X&å옰£¶SIÖ“ýj_ÆÊé«ìlÓÚÀSµj]•QB<ƒŽŽN¨ BxMÎ.~Á©J)è,E¥ÖKb¤q ±ö`Ò Ê•ÚA³Å©šLÔ¹$*ï Äž ç el9bËçìh+_’)ëMÖ¸mLrõ%ûž{;‹SäZ\U‹+òå„ìáªx=ñþîy‡ÎP«U‘iø>t–®UÜP€Ñð”-W($3‚`ôZ逽ñûî[§óz³y{ô[ñÛ(iÅ;$¿S¸G³ä|);’ù¨‚}©µì¡­.ܵËT `ÞÅկ作†,ѾÜT:õõ*ÎŽ$ôÄ;øÌ#;ødíòÝJ|5D_y‡è&ÎLêw°S„|Y¯í˜¶/íd= ²Ã†*;zâ|¿d+ÞÁ(>Åw*j­ÑÑÑ1pc†€‰N#=ÁxH—ܯ~æ{¸oUÞuÀd,è{øâŸ_ÄžûíуrÈç#£atÏ÷aà!ú0F!|xJž‡(ìö,øÝ¹¹¾ß÷×jȺ-P¶øåßúEf?’Á·ÌŠ–Ãnò§ÙFñÎs3‡Ùæó1liŠpqî§‹E>¤m—f´o0fO+$NAãMʮŠTn×–…È7oóyk&"P=E‘D¸E ñ{9mÐ3Û!yö4³Âç´^¨LrùÿœžÇ!T>@Ç^6 ‹KŸ9"ÅaeÙÜùB<£ VÌ|WüåO¸ò†»ðÀ÷â¹ïÀ®ùGð¯ÿ<õ8¼ýF<<7Å^»çqÉ9çàÊgÛðÞcvÃò[~‹oŸÿOx‡¼SFD yfÃOä‹ÏKŸì²œ£nŸ àˆŸoô?6Heœø|oÆR{ž½4|¶©qJ¥xþ΋ðýïÿ3‡îcwqÿ?½2Gï5 ù¨À ð=xžB˜Ó˜~Ï ¸îé °#BcåA'1Œ  L m€b± ÚÔ7vOi’ 3 QÔ]æÛ ¡\¯|ãèÅÞ#Êå `¦‚0BÇ·àË_ú ¢]߉wŒˆ¬ž‹+.¹cö;Ï݈‹ÿü\}Ûݸ箇ñZ{ˆ‰»íŒ‚IàÑz°=¼"¿œF'^C9³°Æµ ì|ÿ}Ö9¸yÚ£¸ÿž;p÷“¯#¹#& ]ŽKÎÿîY¶Þ=e/@øÈ²a¶ýÉwñç¶Ç)‡íå)䣈¢üôuüö[çàò§ 8êè]ù)¦ÿá;ø{r0º·]öüåê;ñðƒ÷bÚó 1bçÝ1"ß|S6G'Ù¹#相L)—ß—Üy¾£ˆ#’v!Éç”X> ïy‚l!.ùñ÷ñçÞ{Ü(x¼ö'pþþŠy¥ý1ub`4’$C.Ê#ÊuGCƒra­3„¥2Ì|øfÜøx‚}§îˆ6³·_ñ{\1cr¾òý»0qê!;,£5߯Ë'˜á7ŸEáƒÿìá´uWsï³]j\Ö7ß4Ï$”£]2~­® µ÷Ôn IDATàÉEŸØ¥|ÙಣžM´/Óä|;kÓDßÈÞ$ϸð Ÿ?dcO.Ó´óýÙbï¸ D]x“I–Ï,Ë€/ãüþþú·ûàM=ï É4¢|¹\¥€\˜CRy WýéFÄ#wƤ±C±êµ›ð£_߇ѻ5U¢<dZCyr¡ {í„Lx|! x 0-÷Q›wð9%>S,¼ƒ‹<ôÄ;숸])ÕŽ¶ÚÑžo>§,¼Cúmóv4sVó¾yÞ¾oHH¹nŽ’2ï`§;O˜wpJ­ÙaG^8jÊÑ®ŒÇÜ‚ÏmڕʤÏ|–d]¼ƒå#ÿœr,Æ>Gæ¸ÐŽ|ŸTö«V«¹},zù™‘›wpægBؼCxÃ@"3Mù\ ž«»4HlCÛà?û šÿ^ìëEh+Ã2Üû÷[ñÒâ.x…a˜z쉘º}‹_½wLÏ0Î_Š7ÊELÙ V¿ô(æ%ãñ‡‘]oaÚ}wáé9+0lçƒpÜÑctM¡V)·j—<CKÈç=K¸‹ïm`Áäó1²±ð%q¶——…™«Dp ½¡ˆ·ˆË2²²eÒ,F—,<{QqN¶]£_Ò©øP&‡Y¹‹gØöFJZR¥RiJiaOœ*´|‡Œ·>§úÈF*›Ž((þ.ñnÉk=ãœ`™K6P8<Ï÷pJ§³±7‡s†ù3­.5d/‡ß‹Å"ÚÛÛ›Œè8ÉPL_Åß.û'^Ág¾~ FèUXÚ1 i:Á ‰øÐg>kÓpÞ¯ÃÓSG#,”PŠ"xðry”ŠEøY‚,Ng¦¡\¸:]87`Vж!jßćmï"|9 þœ?Î&%Å UôA)…8Iæò<49·þOxraÅ(@x˜÷ĸë‰ÙˆÛvÄ»Þ"Æ­z ÷Ü3 ³k3ñûŽg°Ï”©Xöò3˜xòÇ1aÙ¸~FüÀ8åý» _(¢”wÎÆõ߆¶ÃOÁ“†A ¹BÅb0 ¹Úx1n|1¿}þÿaRn%î¾ú\xùCøáÙÇ`¨ïÁXåöeÍò™ENOàH§¬c.ÃÑ`›‰’ï»àô…4M„!¼ @T(¢èuçÚ'tæ¡P*¬˜‰«ÿü v:átì3ÂÃ×\ˆ7ƉSÞËfÜ›zÕÂ8|ü0Y½‚ûî|3ÚãOOc¯ÃN@¾XD1S0È¡T, È…¨Î}×Üú–™!xç1'ã ñy(?XëVp»Ü¨è!cœÖÌ›¼}û¶]N—ÛáKbíÒ×âÍåêxö=H|+:ß$.û¿bN÷å vòpTѾ„³ øüe›wðùLûrZûþ¾~AúQ­V1hÐ tvv69 „8q4ÂæMçl”Ás_År5“G.Âôû_Äw› è ¯Mí÷?‡·:C|ÊûP¹õïxdúB¼ºj1ž;ð£øø”JÅü0@mÞ¸îþ§±$)aw€÷ì> gÞ‰Ûž.cÇR^[‘a÷ƒNÀÑû ÂówÞŠ‡_^„,‚ý9SÆB@„•£õ­xWêJ’¤1><ÏÂ8½\~Øè–9–³²ÿØœ‰‰-ß7%cÏWKÈ~Âeé[ñNÁåÊ¡­xGŠØÂ¥…ûÃ;ìj«ö¹+›wð¹EvÛ¼ƒ/ýµÏ”ñqy¾'¬'ÞÁÕÆXçòUløÈó®#.Ò"}â‚%ìð¶ÏÞñÚæôW;Õ–áÌ¥û •%߃a{öÃ0€ÑYa4öàŽ>Ž4Æ P)‚“pàa‡`ÌÇe¸KSƒÎ¥sðäwà•ªÁÒ§ïÃe—ýs—-ÃôG¯Åßx Ï?p9®éáð#Fí±+qõO! ÂÆá^¾ý™óüù~ É+”ê&¼iÈ„ð8ÎçzÿöEbìàœZ.cÇŸZÝÎyµ\¹X,6Ââ­Ž]5ƒsJ¥Ê‡AòÌö…qò¼\…B65>Ì÷‹ØãÁiR‡œ/‘b‚ʇ.í\ôZ­†b±Øø©öÂùÎmáEÍÞ Î+¶£R²ñ]$<7\'Ÿ+€‰õ/©œ“Ír&ÙÍ¥^í[§ó…<ºæÍÄÜÎ Žøö7#FOÀ”=¶C!ða æB˜Î¨ø!&ø.ìñŽñ˜tð˜,{u&:RSOI£CÚ\äÁ.ÅʇRÙ nè¯é. …ñ;íãO:jÅ2,xc1–.Y„…Ë;ðÒ=Ç+f{tÀÞn:ÐQË µ‚o–㦠~‰zìõŽáhxšÊ¦¡á{ µyÓ±`ôAØ#׉y¯ÎB~ÏCpà®;bû »a¯=ö€™õ¥JÝ“È>g"äU<Áœ¯ÏU焱LK*žx_í›×9 Û¸”OÀ ”‡@¢Y-X„*¬^ö4nzf jspÿ}³Q( Emîõ8÷/wÛt0vªMÇ%ç]Œ7ò£0nÌ0xá(ì¹ï¾˜¸ÕËcáòrË®–Mù¿ºoÝSÇÔpã¯g;=„Þšg’<ŸÏ7U)bbÎ%±Ù™ÆF8uƒQ5R9-¥X,®u¿‡V‘ÄSÎcÊÆ–])TÒ™åïœÅ9ñ¶£¨Õ=c¼Ú×!“”!!v|é¬èíVÕ%Û.±kŒA©Tj""ÏÌ;šn1G†93G´ÿ{qâ;‡cÕ¬ðZ¬ïz ¿üõ•x|žÁÎ;ÇòöãvÛ‘Êaû÷Àž£Ò± –´C/¿ùÃßðÄ¢F+pã¯.À½ ËÈ:ÞÀÓw߇ÙŽÁ ŸÄ­wÜŽW¦?„+o|Å)‡ã ÝÇ «HÓfÞÁ‘ ™N¿â¨Y+ÞÁ‰x`Þ!{¸ì“Q5Úá;·øL¢òiÅ;$ŠÆÎE^|žŠyöhÅ;˜Ë^Y*•ùæè§e÷…wpDÞì¢6—nÅ;ÄA`óvbDQÔTV]ø'ŸbÞÁÞØ1ÀEl™£¢³úÃ;8]˜­xË/§¾ñ™ÒðìËm8¬ËÂZ.W †FSß{†¼q3n|µ†\à¡Z©aùË÷àªË®À}/ÎGmé\¬öóÈù@:r_|ðŒÁ1;h”ÆLÆ?q*vÌùXòú›X0g* žÁU—]Yi µÕ('uAò+Ê—ZJŸØËÎÕd¸ —oäêg¢Ü8tf{¸9D´( ^œOÈ%Ù[Á)¤rE;O•Kññy ¹ìɧ.‹ÍMžß® ÎÏ̆Žr\ns®»ººýïäƒt\þU6;ËsKß …Bc“‘ψ’ã’|C¶xì8dÍ „=™\‰‹•2+T³Ûè¤Bê–Î †\òáïZ­OÕɕ鞋|>4Iëi úM\ñËÿÃù×¾†ö=S÷y|ÀdðáAke ”òšî áÈ”ôƒ«ˆÅ·ŒG­äsÒ¶™â¡²“³Âf’̷ȧ r….‰Ût'…$z$ŽýðAhòŸ˜¾ÔÀó,}ö)¬ª´ã±[®Áƒ =”r‹±Ìƒí‡— ÛvÃa‡Œ&ŒÇ„¡#ðÆ3ðú1F^Ÿþ$«vØÞ`Áì7°ã‰§àÔ÷ŸŽcö¦ÏYŒÌ(˜°„=;:é`ŒÎ)˜ò2<úàÃØþôÏáÌýFÁI/ÂЇAš¤0éR¼öBã÷v¦ô»£¾9¿N¨}JÕ#Åbè²gPŒaöÚsDöŒ6äF™ÖðŒÝžT/Bq»í°òÕgðÀ/!ñ 4¼0Bí¹+pÏŠñ8åÃ'`ûRfZ#ˆrõÔ_dºŠWŸYˆq쌭L’j÷Òs9¨nBÃD“#P|^„u?3ßUÄ:eS¬8®8ÝŒ+8c À¬q8äÂî4®¶QØgâ$ÌäÌ™= o Û {ì6ËŸ}Ë«e<çÕ¸wNŒRnÞ¬Åø1áóãpÐa‡`—íh@u§³øÀª™/aIœaÑS7á†G_‡®Ä+KS_ëB”Ù¡#ÏQ,—arš«MùŒ¡]õÏ>ì-λ®®®ÆXHå;®ÔÄúÚí ]ù|~­’¬¢Å{Ë]¾‡Š½¬veJ>wÀ÷Oqꥌ]¹\^‹“pÁ¾«I*´q)_Û€ä3šr…€<£œO²yGlùˆ»ÞÄ Ïv`l˜!œ0Yç|Ìx±+_x ª‡~ê 8õ”SqÒ^1ù}QÐ!&L9‡ï>Y’AyË_š…] ¦žùIüë©ïÁ˜¡ ðøì*ŒÎÜï?î$ø¬îXZn8F 0ãîÛðÌ›e” E‹…µ÷³š«t±ãÕæ\ð‚Ï02ï(—ËME"dïæKÅ…@KJ)WcãjdLÈ%¢ÃóÁ¼ƒ­x—f'1—ÝçbE’=N2ax¯æèao¼ƒàÛ¼ƒÓë™w°Q$¼ƒ×;lzâœ^Êç¨DdÍHºåáè*WÚãób\ ZvÛESXçsu4>Ÿ'Ù,ì´fÝ.œÐ>×Ê)j}E`—®“Á’pÜï´Jj`tŒ=gø~~ï| Ýu<º¦ß‰Û¦/Æáÿñ¿˜òÖõøó K‘$1B£áçŒÖPžBàç…ÝÕn År;/œq0ÌÊEèÀ xµ®¦CbœJÀÂ$,¡1¾Þ>ÌÄ—er™a»D¨(6Y"t¼ÉØg*X˜(røQ‚M¸ùbF.­hß ÌJ™;,Z78Ë 9¿.}*•J ƒLÎíðwqµÙ(d‘‹Å¦ÍGr&%T/Š_¼‚ö½\)©\.£íÿ³÷æa–ÕÕÙè»Ç3Õ©©««ç‰††nºAº TDPˆhLŒšÄÄïû’'ùnrïMî½~™L¢Ñɨ1ÄO5ˆ¢èn†ºnzêL{¾T­ÝïùÕ©ªS§†®a¯ç©‡¦ûÔ>{ÿöox×ZïzWSS•t!GÿÔ(÷;‘…%Q>h™ ÆT*y>ážs‡qµoòj”¦õP塯ÔÍ€¾f 6ä„}~ ­y–8Ößµ ž¾ 7ýÊ/aÛê¥h[ÚŽ´Öå9 {{^À ‡6ãä‘Ó¨h˰"Áóüª¨;œçb>¦ˆqt’9·j'h^ò=â c¹\Ž/ÞàX!L6P•¶ÇÜ£(‚Ž‘”t"³ùÝxÛÚ]øÆóe,[o#ÝÞ -•Á;>òkØÖ\@×ÉÖuØjÐ*]8ÝÓÕíØ¼¾÷ÿl'vu¬Ã›/éÀ“< #s9.Z›Ãé´þ£'ðÚ¡"óк9Ó¨šŽLsQˆáB~+‡õk–à律Ïù(®Þ˜ÇP¡ݰGîPƒa¦¡õïÆ^çüêRÀ67c­õ3øé÷±gùÐ_þ!^ö€×]pòFðãÔkßdŽsPBÀ+ÅïÑ0Fî!ÀPïq¼º¯»ï}QÛyX»º/E i8÷õ7âöæã8¹ïG¸çßþvçïÀ@cå%XìÇíÆ97\Œ&ÍCF0¢XD•.<Ó“Æë¯jf§°î¼Mpï{ ¾°çšÝØûì>X›o@GPFaȇ¦¨Dr5†â³\¯ìA,TÁjÞ£´ËXqƒgÉ †ÍÐMƒæôâЫ¯ åXšñ¡i@€¶^²­ýßþ¾‡Uç¼Ëš€JGt½Œ7à7qå Gvãœe^ŠÝéÇ©Ó=Èä5hˆ é& CCéÖfh^€ 7þn]GÁÒsš é! ªd!¯%¦AsÝ7OæuÉ}}ä÷8‹ kWÖ#ÓV¸Yààà` Žø\äè>7œäZU½”é\r ·^œO¦}qÀL‚}œiâ<ªä±Z+ÊN²ü‹ïp`“£ã\g$ï§X,Vi• A¤aàÀƒx)ÊbùÇqß! ËÓÙ¿Á–vè£ÏíÅ1£Nj)VYôÐC÷iô•;`š:i°òya€Sû_ÂÁŽ4°.¯Ã ¶‰( Pv#hQ´œ›Þ+;Š=?½_*åð'w¼9Û¬Â;„eõ.99ëÀg­Jñ¬wpý²Š;¸®‹±B.—‹A¯]Õ@¤Ü«5eNËgÇÂâ´…;¸u‡àΤðžÌû™Ü/ã®íQq;ÀÊ`*îõ(÷)ï]jáxoU[–Èœ%5ž/ì°È}¨XA¥¦³pïgŒ;O1FhÄ™Ñ9ÝÏ“J¸¶L_<”‹%”Ë:¶¼ëF\€! ÊÈœw).îаëÛ_ÁöC¡TfÛÜ Šå†e£R,¢X,¡âTP)•Pñuì¸æ=XsêgøÛÏÿp×½xþøòYÑ„A9Ke‹ÅQEO\àÌ…§jšK&57 ダ‹ÉT@Ï.rR «9 ÇŠ%\,ÆQmÙ¤9j©Êó©51j†#zªŒ Ô>Èâg¥#É„©zù¼°ìʽȽ±w®Ò×Ä›óp™ÊN…lªò+Éä†e •ßg¥1Ž.pÁ›ª¡/ _“Œ§lœâÜÊÆW*•Î4ÆóxésñÞŽ‹3ûñÕÏýþò _ÁO_)‘‡BÉG¾m)–´æ`ø.,Áµ·ßˆó¬ýø»Ïü)îÙçà·Ü„óSšìx±ü(«¼0åRUKaÀ)ëéOªt#Ï+ÂP£M,·¬:TªÄg•šŽh‘‡b©„ Èaû;¯C{¥…bKßðKøÅMþëŸ?‹ÏÝùÜ÷øA„VlZ«ûgø›¿ú<~vTÇúÍËá Å@j3.]ea ¿áºmXÞÒ‰·½ã:¤Ÿú:>ûùÀž`+®ý&è¡‹R±„ŠÄß_rul½æ6¼gÅQ|åóŸÃýû‹°m¶mÁq+(Jð¢û‰Ç\p9:5QË%øå_{?Ö=Š¿ÿìŸá ÷¼ŒmïúeÜô¦0¢ê1"#ÊÅò,ɬ6UeÖáÏû¨ õb÷ƒÿ_øâ—ñ”··}ävœ×¢T,¢TvpøéøÏ{wâÑ}=hßx.Xª¡T@¹õr|øöw¢ÿ'‡/ýð%xQ×õ €S.¡äø@¡½V;ÎmÍ T qÁ•ïÅ{^Üsç_á³_ü*^µ.Á‡o¾ ¹áDN•²#!îy ‡÷¸â?sÖ›©‡Ü4’Uå˜FÌ”Úá=JGè{ð*.Š'Š;?ûY|öÏïăO£R,¢âHoº[›†ðÂQk/ÙŽ\à#ÉÍxïÅÍxø®Ïá¯ÿöK¸ï±ƒpõÖ­YަÒ.Üù—… ye”*.BßA±P„¹ñmøà5›qø;_ÀŸÿÕq÷÷bÀñ`zU&ž{Ép$]Àg¿ùÜ“1’Ïɹ"Κ2uLí_ÁôdÖXd‡£¨èRùð,E«*“rÍF-ùsv>DURöOÉÉÞ5w f¯3Þ¿¹ÞGÖ×hÊ5 …Bü jU)õLÝD]ÀÓß{ÖêKð¡_ÿm|ìW>Š›¯ÌâÉ'w¡kÉU¸ýšóqèÞ¿ÅgþìNüø•^ÀZ×mpñàÝ_À?>rˆ<‹%˜ç¾·¾}3^»çóøó¯þM;Þ÷niA¥RA±T4WF±âÂë} ß¿÷;ØùÀÏñZ± —ž¿ –1Z ]m ÀY.•yÁxD-®¯w𸫸ƒß¹ZëÅÙ1éõ¿Œ;¸Y.›ש¸ƒÕøTy}qHw¨ê|¬lÇtJwp‹ VIqÇ™}»w°W wp­›ˆ`Èu2™LÕ>P wðšf eÏfº¼`ãaµP³ªöŽ)£jC`µµ†lX©îçJí©ªTNÖ´»îº+ºñÆãh·D†d°ô£ç¹Ð4ñºG {tiLsØKg2ð\¾«ëø> Ë‘6ta˜Öˆr †4]‡eZ£’›F©OžÜR´. •›Ÿ©]Ô™ ¦gI1KjU^’¨<™YzSV>ãT:ü œ×u‘ËåP,«j32™Lìղğw޶qQ,w÷OŸ£ùCCCñæ“Ïçãw,ég¹ÇZ{eÒ‹E477WE†xÑ0P‘{Å4‰Hš˜¹åà^ *ƒ…XuMúgär¹ø]qdkƒxA ¯—ÒR©TÕ5{-°CÌýzX¿¿ªÈ~„T*•a˜#ÊGºÓ´~u_ Ã@±TB:q ÏÐ…£Î”DV‘b•æœË³q/)vRyÈ\º¢Ìq9%b&ó†~µo‰\W2é•Úˆ\.‡À÷á¸,Û‘4ÕD €®iˆŒG`øïQSà9¦…0ŒËeày> ÓB¹TTD@lhà8˜¦;•‚¡ë(•Šp]ùæf¸•2‚0‚eS°†×ŸÀ€mâ›ÿçŸ!úµ?ÁMBÝDøÃ÷+jdQ„€Ô¡Ô^MªóÌk‡Á¤¼ç3€Ä€çúð‰œÈdÒ|Ý0aÃ2Κ¦A7 ¸Ž]×Í€e(—K0L™´d ~?pêÙŸ`ç‘>òž«¹•álF@ÓFÖŽ¦Aq(0H@„Ï Žr2uŒœIà`I­ѬºÃYI+¾/`FIŒ Á4t¾Ý–̵Fæo*e4º« ¹¹®çލÙùÐuAÂ2 T¶e ‘Œˆ ˲ãϹž Œ8û–eahh¨J¾TövÉ.°* ¹ŠÅbUF•³Sg ÀGÖ—>".Qö@Uí’…)x=3ð”õÏHµÞA‚'¾ÔžOò~d?‘=šÕÚdnÈ÷Uã/ÞOøÞÙYäîój –üŸƒÕkˬÚÇ9{Ƹ#ð=@3`Z&œJ†¬-Û‚'u ‚|žçg@M+–w£áú´á{F;M¹,ŠÅa©÷L:( `Ú©™ø3™KM×á-[ ëUÜÁÏT©TËåFõª…;„†%û¥œÝÜNo-Ü!N³Ü/÷dª…;älð³Ùa–û‘ó­P( ¹¹¹êüQqã>Áœ}”,1gÌÕ^>ò|ÌaÜÁ…û‚;$ë#óHƉì8°8ÅX¸CÖ¼ovB¹¹&·QéòRï"ÏÉNãbu˜Édâ@-Ü¡ö\Rq‡Ìù3×𨸃³‰ÙlŽã »»¥R åJOìz²ªÞ÷}\v鎘2¸lÙ2ÜsÏ=g¤™YúV["(⚦UÅUèªXš#BÍÐõ3¼oPQž1òRÃ0"ÙȨ*í).BâM˜£þªt#{ðL âˆs9‚Ì…Ý2ÙÑãÉÏl.~U£”\´Ê…ŠÍæì×$¨Ý¦EyBíÈ,ô¹_nd()›ÍVEÒdÒË8©Ô+¦ˆ ¯QÞ7SX¦“)}| q”ˆc^ j³:U5D³Ó(©u¦K¨M#ÅY“g0ÅRœ¼1¥®¡fEÔh¨ÜÏð'›™$¿§ 9sv¦GŽQÕ+µýŹà,×”1µ‘3®œÕcÀÍQ:µRœc¦¬ì¢Öc±Ä¦Dy|0•È4M¸žMð$2mìg¨&©øð‰¢aG#®á‰"¤Ré‘ߡƵ#¡JTûF @’u7¼géÃŽTL¥2E!4­ Û®¹›3.ÜHƒ>2g8 ¢Óº©%ÎÜaÎ(r°„×€Œ'lÃûÉ™ ]:†K¶Y¡gøwƒx~›æ™Üá´Ôð÷µ¬>W\¸ƒa oÙ´*®àýW‡€j•®(ÏÄŸ3ìUÅ/µN¢÷<§YyÏó|X–]åÙŸG¢Š#Ï‘¡>YÕmBi|–Àï"‚cšðÍYtþN~–‰åzT™K|¦ÊÜæ=„÷ZuV#Ê ^9x¨âV0%=ƒd¡‡Ÿ{$x#™R"•š[]£Éñ –eÂŒë-ô3Y³XÂ7ŒKjµ"38C/û ׯ0î±:ìw@—¹?î}E„w¨øŒ©WcÕ¼Jö†¤Z¸C¥²²—ª¢ä»o8 IDAT§6cæîƒ2YÜÁ}ÌÆÂœ!Sq 茅;ÔzeV)åÌŠŒQ6›­šûŒ;˜Ñ$ÏËÏ-ŒXîg¯…;XÙMe%É™_,ï3Ã<<öry‘p$‘9‹LiR»¸rŠXÕ­g¾07ÔR7O)Ô–€ª}ØÓ”«ŠðDdo–3¬0Áœ[.\æ4Ú5]íT­6yd5^H¬9Î…Œ\Ó zÖœNTy–<825VêX<}¾îÔªFáÕž:é8«¦®kÉA à“qb0ÀT ž+œ!┵ÚèŠA";Z\ó#›k¸Ç™Ví’÷Ä›5œª¢8¤–eUõgað«jÎ 0•hŽÚôëŒd£çìGÞøXáH®W+»Ä‘pÞÌåº,6 ˜žW\ô)÷!‡óœÙñg™H53¨Rä^¹ß7JdÀÁ URó ¡†E€©ÈIJӡéJ¤‹ÌʳªàK.‹ø„º_òºáž³™²vUyhhè†'j(¿s¾GÞ§%B+ßÃ4D¦¹2p&×VégìÈÓhxïà9ÉôOî Áç׈°Óý4T@ǽTg”3õÌ'gñ ¨©½Áxc‡@-œåsŠ&«z|k5Õä9¬=ž/jñ¾ìGjãC®ßSNª{Y“,еÆL¾ëô˜®*À5Š;äž%², ŽU°T§œ©‘¬Œ¦5øLeP(Ï£â5sËó‚×*×wÖšÓ’ U߯3–ßç,ØX¸ƒÏsÎØ±ìX¸ƒ3w¬ÀÆcÄ­+Ôuøƒ3tãáfÄŒ…;„1À¸ƒÏ¥±p‡mLwp¸zp7"eÜÁ{žªü&™< †³*d-ÜÁ옙À´bÜQ*•&íÌèìõIaŸxQ’6féY™âÉËdà¦GìX¨Q–í,•J1‹»ºÊïJQ¼z)(”ÍPÒÇ<à¢Þ T.–f¹i¦ºÈ"f^/gYdÀEžNJñsIô@®-ß#›¤äøå3¯˜›qog®#âMKu¸¸ó6j’:•…£Jó58sÅïÁ)Ób0½OþNµVƒ#Ъd'¦Ü„QÆO2Âã©,ynÊÆ@M¨}ì ²S©n¤âl±ãW©Tbµy—ò9y×L¹‘ v&8*$ï†)yì<©‡üHmgÙXÛž>Yã2Õñ– Cæw°ÐÈÎÏiV:Q»¡3åfbjÍ×pD‘ŸKÒÿ쀱ֽÐ$¸ 2Ó›ø³|Xp°„ ™ªÊÀƒùÕì1¥Š#R0à9-÷'µYâüòÜb®5ÿY=4XˆÁ-çL߀b±Ÿ ,nÂkD"“BGå.5BÉE¡¢öÅY¦¥pdVÖ‰ÚK‹ûD17ÁòLœÕ–ûçq{çyÄ”eh4;jÃOµ’)*Üœ’פÐ[˜mÀivLXÔƒ£ÏìŒÈïÊ>ÄN¨Ú[£¬ªFQY‚Wo¼wË=e2™¸–Åu]”J¥xäµ){+ÿ1íˆËÉò:fÜÁY ¡I…;äšB;—w®âv°äýÈž^îš%®Keç‹ËËårU0‡÷¦Zrû5¯ž×쨲:Óô8H$eµNN üðü`ŒÂÒ¿ªã¢6æfÅC^Oü»Œ;8¨öcbÜ¡®ovnøL wÈß³ƒ&t:=.îµU«o×q6®¹QHÙAr§êl`6‘ü®àsY?‚;8øÂŽ‘dÖd_`çKiaÜÁ”wwðþ!1S‹‚:КŒÅ™¡ƒÈ„–4¹L6ÖÊ–€yñ’9òÆ‚…^ÅS»¨2ÀeÐÈݳ%(Þ&œ.ä…Ë’},£Ìé~y^‘䨯lâ½Ë}s–ƒ½aµS®8[ ˆØ;e~&×9Páh¢ªò"›’mÛ1õƒåŽÕ‘#)²€˜_+‚ËÅŸ,¢Àï‹»Æs´GÝÕâS.d—ÈP å{82¤‚¥J¥Säú Æ%M.÷Ê@”…j®27”R¦´É¸«Ý̹ã4SŠXuÁG!dÃ…¦¾ñ§ Êæ*ã.×b•:Vµa/Gâ ¨¬VÅ™ÜÓi›Âçh3§­Õ+<¹\.ÞpYÑPÍÌrQ¨læ²ðFÏ}¥TzËTrÓ&¸«:7ü“à ×ÙñXó~%ã¡6xUùÁÂcçh›ìYœuQ³èÜ ¥Pe?ä¶ÌG• Ò !çy­¶Ü/÷'qæ¸qgÌXý‡Ÿƒ³¥ò™î+Á ÌèåZ<¦@0àW#ºqŸ¨Š3«{rPIÖ•ì9êšçñQ–Ü{SSSX൬6¹åb\¦ïÕ’ie§^¨T¡çH=¿[9 YUé åÕ¬ªGeg’Ï7®+U³ %—ñ•sBÖ†ÔÀªÊ'‹;Äd}ñüT©Mœ)UëYyÍqIðÏwgÆ4X`å79ßTÜ!ãÌï\­Kⳓ÷Z¸ƒkõêÁò|rÖpv@ͨYL˲âº-~'*eÇ^m‘ÁÁ_5k%{¬ÚÃq‡PÞøžT‘&õ×2ÝŒ£Ñ¼v¸ß×]ò9U/îPkVpÉù§€sí;ÁLCVÆLSâŸõàöLw-²–üp-ÜÁ*`r±Šèdq÷bÀ*ë‹kÃTÜÁÁcfk°0 gÜx_áúíñp‡Ô«"$ì« `UÜÁÆ|ŽsüD¸ƒ÷Yw<·jÑæ„5!λºoñº‘ïSq‡dX°€ƒìвÓ\ w¨´6¾Î,©5¬roƒƒƒÓ̤A‘,:‰ìsa/:Þ…_ªò¬™KÉ‘+îé”yAB)àÆHœMá*{ÍrOBàÃEÕÒçÍ’õüU¹eN3Àd|ŽB2Ý„y×¼P˜ŸÉ4Z\wŽúÈx±3ÄΗxî숲ܩZL(›G˜bÆj"Éa Å`@€D Yá‡߯4L“ÈÏ-™ä̰ÀÙ ¡uqÓ/¹¯Zج>¢*µp6Œ7_µ£5S‰8¥/×’g—[‚ (yžÉ\—èGgeM mÈrÚž –ݬY•¹©:ò{ª£¥ØYá9Èó— Ž(ªŸç5Í7÷gâwÆTOÕep ûkÚËß—lÓ&ùýÈ|“¢MÕAR‹L¹  ¨O±* þUGE¥9±Z•*¦Át7î.¯Ò¦Ô9ÇõFâøðaʽK˜É`Š#mLË䬋Ðvð¨¯qÎ3ÀTk¾xüyobG­¹bî?Gå¹X ‹÷dÎ0²ð7Õ‰ày©fm$ØÂ…½|ƨ=š8Å‚ÎX2 Buå,§<‹Ì)Á=åȺÚpO([òÝjŒ ¨TÉmÙçÇü¯Õƒ;xÜy-0îPAŒ;˜Ò%ÏÈYÆ3r-Æìäð|VTµÆ÷U8‚Ù+õâÞ‡TÜ¡^«ÍlÕ: ÎVOwÈ\dÜÁÙ/Æ£e®3³‡“ŵ¨g,Ý,s“ç_Ã43NãÉM²7V‹.$ŽzPpÁ#Ó dÑËf¦RŸs0jjã4N{rQœZ,(@›ÊçCŠ‹“eá -‰kXª”‹ˆï)“U]  Ö9u­FmTA>8¢Èà’yÓªt&Új1«„0§W€÷áan´Ll.TS£j¬4ÇQZ5‚ÏNù2…ˆ£°ªzGíjÕ´°â7nâ´9FrøÔÒãWõÙe~ÉF.‹_ÆK¦`0·;¼ÉsÇ‹£ªjKQ³^½ºÉ¨ ?Õl †#5µ²1*˜³NLâµÅ*A*ŇÁ‡ì?ªâ ï¼Ñ³¢!ÏÞŒÙ!‘y/ÎJ§ejgS9’©¾O•O/ÿ¦ªÔñzVëÝÔýŒ÷–eíûþ¨ú ´¨5~\/Äk‚^ËüþÔH.g©8º«6…ã¨,S…„Æÿ/sZ­oãÚuâkª 7™ŠÊàK-6GK­kâˆv­¨4^èÊü9ÓM^¯Ê©gy·\÷Á9®]äfÒ*0–±qá:;™|)\¤ÌÙ ™O²6Y@楚ég n¦êðY*ïUÖ½8Vjý„|FÀ˜.ÜÁs^Å L]V¥éÙÑbY­š ®õäy$s@è§ÌvPic° wðù/™÷ru_W)XcÍiv„'ÂjtŸƒìrÖ_ÅŒ3'‹;¸WŒ¬'Ù+ùûw¨"L Wqï§µpŸe,h¡â¦(ªüÞ¹¡¼dÞw¨BŒ‹T§žihŒ;Ô²–ç3‘q‡¼#f0óƒ_-½à³DÖäÐÐPüÞêÍ̘jA¨<¤P4$ÂÊ_Ùå›aGƒG´˜®%×N¡*ÛÆÎËÀ©í<`¬¯nx²ÉÊ2 #Ög™H™<ÜAW‘{I³NÙ|ø;Xò¹VÊO&–D YF ¹èsfƒk&x\¸pŸ£0•J¥ªØ7©Iážü j„ç,àBœp¡WÕ[TiL)êU‹ödsçB?åþ¤ðXíQé].`ù]N¡«‘]µá—ý©•îgñ NÑË÷säK•bd‡DUq’Cˆ77Ž"±ì#ƒv<9«È뉋@%j#Å‹™LCCC£êE˜ò©ÖÉ|dfù^ŽR10e¾ùÙyÏQ9ý¼·É¼“H·\›¥âålš[UÔA•·åH®¼w™ü}jF™ƒ|œ9 wp¶Bîg<ÜÁµgŒ;T…<¹wOPÕ 9ú^*•b µ8ã^‡2¶*îà.íÜ ‚k_8z/ïGM^‡‚è…;Tê¿?™Ó’yef‹Ü—”ÕOÞ;ãÎzÈ'{8ã¹W^bÜÁ™­Z¸ƒ<Ó*w°Xô€ášYÎîðúç:8Æ2*îP•oká5«W wÈY­߯Âjqùaæÿ»¼wÙceÙsy pÐWÅ"Ã̸ƒ×aC™Ž€³çËÊ îYR•–ŸåîÖ\kÂ<[¡qæGxòyŽPq/U9K¥U05„á «œV¹&g—øZràóÏ©s\rmùwŽ 0Ý‘×(GuYZ”é3 vøYY9ˆ%–™ÒÀ©vÖŸWÓÔ<§eýȘ3¥Sö¹W(ó˜0 NÖ/g5¸Ñ­|Vd€Õž% |¸n‹ÿŽAŒ‰eðÏjC\DÍ lkÕuðÜ¥'U ?ÏJZ²V¸ÆBœ%µH•÷¦°‰ÃÆtA™Ÿì4ðúP öÕNó|fˆñó ½N>¯FŽÕs„›Ë‰SÀ½ÍjÑ™ÃuCLQ³¦²²8 ×Qp›ý ¢fxQÇŒU×ÄI`z©ì—Ùl¶*C#ãÀ²àügÞ·dM©™PvÒ9ÉY1~VÂL‘e5nÊ~Pk½ËX±$»¬Ù²×òý7Š;8CÌŸmÌ«â¦30'€ç yv¤T! éå¥â`¨…;¸/‰Z[Âó î‚  wðÞÇÁìñp‡*û˸C~dŸâŒ; öÕ.$að=ÜÁÔ&wȞǸƒÏAÁœµ—õ&cÉg'× q›$²rv˜ç´Š;/³ÈÕX¸CeÔÂj}(g¯UåM.§àÚ=µ}‡Š;¸_“Ü3ãV{e¬$krhhhÒ53U™5µ¥v°g·«« Åbq½GMŸWÈ­N Z¼K¾†ª¢ÁàD펪ò ùžT‰`µÿµ? {ªü¼jaÓÔ{QïO=™[Èà˜ÓȵƼVC(Nsºšù±jŠ’Çž³ j·n•6À^\ˆ®nzLÙáïR)P*€éê30ÇS­ÃQŸ›¿§õi®Ãá´«ú÷ª"÷J`É÷ÇsRmòÊTþ;~7µî[¥à¨k±ÖœfŠª DcÍI•G[ëþÕµÅN‘ºñ¿×GuÝóïª×ªµ¯ÔúwuNªó\­aR÷ îç£î `Ô¢wU*_mT[k=¨÷¤®Mõýªê]ü9uN« ƒküªîë!‹žÈBµ€×N­qWÅaêÙ£™.£ª<©ÑOõlSiÄ|ýêÞFÕs‡¿_­§¬ur–A­Pç…Jã9­ž“jJMRŸQíyѱös>¯k½+~ÎZûÔdp‡:7TÜÁ޼Ú/¨ÖÙ[ë}Lwð³×‹;Tv²¸ƒ)€áµf¯Ü¡þ®Ú‹I ÆL7îP¿·îP{ñ»ešâlâvæ™î;¸CÅ¡à|É™ŸËåÐÚÚZµ.„ À=¹&c& SC¸v†#¶•JGŽA>ŸÇÊ•+ãÈ@­ÉMŸÍôÏÕw8ç–¦ièííEEX²dɸ÷?Þó-´u¥>aسg.¹ä’†7°ù8‡&s?†aàÅ_ÄÆGqCEñôéÓ8çœs&3õ.gsžÍ¥9½ÐÏÓ4±gÏ\tÑE³:·Ü‘Ìé…ôìâP‹EœN|µšë.Ä÷¢6pœoÀ•› ŽõNÅ‘ñ<AàèÑ£8|ø0\×µ÷jš&:;;±eËäóù1?'ŽŒÜk?8€B¡0k%MÓÐÔÔ„M›6aíÚµÉ&¶ˆÏ6ÙÄ™ihîË<σmÛ‚ ªÛ²iš {J‰%–Xb‰%–Ø*7Ó{øïª“É´"Áòß…R3Áï5Š"ìß¿ét×_}Üp|6,¼òÊ+Ø»w/¶oߎ\.7aˆS§NáôéÓ¸ì²ËÐÖÖ6«ãÖÕÕ…}ûö¡R©àüóÏO6‰El•J%Þ'§ä̈ã"ÿR3ÙÎÜêÆÔhDâlu`­G¹$QªJ,±ÄKl²@×ór¹¶mÛ†çŸhmmMpÕ"4ñ7ê­÷šÐ™î¤aU…Z¢l6‘É&Í|MÓ4ašæ¤n.Š"¸® Ã0fµ3¸,°0 ã{çïçTrEñ†œXb‰%–ØÙ”sõ¾äÌpa²,455UÚ •ù Òé\×E©TŠÕQmÛŽ3ó½\è2GÅ5×\Ss fò»eŽ•Ëe477ã•W^Á¥—^ZÓI–ÿ¯T*Èçó±#3Ó÷*× ‚®ë¢\.Ãq¤Ói ´¶¶.8§>±úL‚:žç5”©ê3,ËŠ=v˲ª™‰Túúz18Ð0:“>Îe³hnï@6Uè×4 •Jý}½0­4Ú—´AŸ¥¾\.£¿¯Åb 𮡽})ZÛ[¡,ÂJ¥‚¡ÁA”JEøAÛN¡­½M¹lBÃK¬æÆlÊÉ8%c4óÆ5 seœ$#áºnÌxhnnžUÚÑ\x/üßL&ƒt:r¹ŒB¡ÏóN§«dYçÛ¬å°Is¶æ#;3Åb1þóXÎ>ggÔÂÿ™¾_ù^ÏóP.—Q*•P©Tb›ìu‹ïl“¬­$S±*ÉJ躎T*;$2ÉÆó˜5MƒW8~ý Ø;ІeùôpTÊñpέŸÆÇ¶w ªŒJé’ŒHè;ø¾üðô)lh±¯XMC±Ç×çE1?7Š"hˆÐõâýøÖ_Âà`JÚ:üö_ÿ1.N({ûqjÿøáO¢×7ÏCÛÆËqû­×aE>ÌÊÄK,±ÄªÇqÍfã&Ô‰ã©!›Í¶môõõ¡T*!“É ’9îÐ4âü̆“ óÍó<8Ž×¨Îþd¶™ÌΈ3Ãٙᙦ‰T*…R©Ô0Û©JšÙ4Mض ×u¡ëzLõª7å£iL#ƒ‹n¼wìX Y šÁP±„ŠãÁ04˜†tʆiˆ4A P,"#¤, AàÁÐud2)èšß÷Q(–F€¡–e"“JAÓ ¸ž‡R© ÝÐ0‚fÈ¥S}ÅŠ‡( ¡0M™” M7Õph4MC:“Áš ®À/4ï€ÿʽø÷'R0uÚ0¯Ø{ ìü)ro¼ ~ã&”N¾„ÿüúÝøúÛð»7lF&Ñ„ÄK,±ÅlÖGfbÓÞÞŽîîn 455R=[Hs¢ç í°žßåL‹85“uF&Û@S‚ÃIA‹z××ÎAÐó•ØÂ0×uáy^Ce)UÎŒ¦ip]ét¥R).ʳm;.T¬k1ˆB@׆¹oÑȆåTJèèGÏþ‡qߞĩ‚%ç^Ž[?x6-±P(0ÐsÏ=x/~òÌQ e.½xtCCø*£Ð{{Ú‰‡ž9ŠÀÈcÛ[oÀû¯½ )-BÿÉøî¿ïÄyo܆W}ÏÚqËG[SÏã»÷þûDÉ·±jËñ¡߈µ ATkqêh[¹¶Vp²;…¨*ò¡R8ŽCå¸cÇVt¶eЯmÀ¶s—ã›?}½7\ˆ6H–_bêÁ”Xb‰-€æ8LÓD&“I€Ù¦ë::::pòäI”Ëå¸x¡ôaà^¯3áû> …|߇ešhÊçaÛö¸×ï`§f2÷¨Þo½ó|ph/=÷<<×ÅmCGG¢ ~_½OùIÎËÅk†aÀ÷}¤Óé©ÑÌ¢(Šif–eÁó¼¸v†ù”ã-Ê(™¤0xü5ìÛW„nè°3­Èå3Ø÷=|åÞã¸òæã}+"<ýƒ»ñÕ‰ð‰_½fq¯>ò ì<´øµßAnà|ÿ?~€#Ævø¾¡b7žú¯oà¡ÞspÛ'Þ«k¾s÷]ø·T3îxóÆáÏy ÷Üߌòâ£Ël„zΫ}0Ö\޼uôÊi]BQà¡RÑP.Wi´î»FiM IDAT—q–X€ŸZ‰M2—ŒS2NdŒæÇ\’ȸã8‚íííÉ{«#èÓÚÚŠîîî˜ffYÖœËÎŒW33Õw,NL©TBo_?Ž?‰b©„t*…µ«WbÙ²NdÒ)èº1å{Ÿ®ùèG!NíûÈÿáW¡»> ï¿ùü=Ø)»á}Ž×Qb‹gÏÖ4 ©T •J¹\nj™ÏóÉd ë:²Ùl\˜çºnh0ͧ^x O! C8Ö:\{ÝFì¾/6\û[x÷UçÃ+9h¹éƒèýçoaÿá\Ð|O=5„·}øÓ¸ê¢¥(WÀ:‰£;}A¯xÏÐñþßþ ®<·Åâ2¸½Çñ¯<¡7ž C/«ï¸oÚØ P,á-}=Þ༄W^;€‚¡mýzàé'ð\÷õØj–áú€‘¢ÄTjܬŠe™h_º+­Ÿàç»÷¡ý²pûŽá•#Çáz6*> Ù@’šI,±Ä[¼³ïûp]7>”gfbK¥R°, ŽãTI6Ïçh½JÙ/ûP.—±ç¹}øùÓÏâÙ—^EÏ` ~B×5´æ²¸ð¼uxËÛñú×m…e§ª®ÅYŽÉd‚¦êð8• Ü=/#¯[hΤ½t FïÂåmРëðODiKÖÍâ hˆ@¥RE;¬Û™‰¢(¦”é_‘“Ôuétº®MEú6]w ~ù²uÃÎŒ xß)è(?ñMüÅ3Â(Búè>>€Îr‘y½z—/o¢ï"Ó´mé#t„¥. eÛÑÞ’Að¼Í-È•¡Çš!4Z°:o ð}øA€R¥ŒSý;¾ñà ¬¿ìr¬lNÁñS0"GƒQÞ/ýÓOPD„ÐËã]Ÿø\¶ªÑ‹P×u´-?7Üø|õ[wãÎ]ÍÐCMv v&‹\JC²öK,±Ä¯##…ÍQ!N'€¬NÑ¡¡¡!ø¾Û¶Üܨå$ø¾¦\C…¾ÿÐøùî}ÐtaÁº× pz×sxâÙýxû¶ãWn½Ù\n”ðQ½NÈx÷§:5ª:DÈZ6PLÃ@‹f!0­a° è†Ðu…Ñ„Ž^b‹Û‘ñufÀu\ø¾Çqáz.‚0 z*ÍuP*”à4Ù(WÊð]¡™EJ©Õ©*˜ô°?ø¤¯ú]|ü½kpºk»ðóŸ¡iÈ-݆÷ܲ^hZ +–æ‚aE7Y!4B4ÝÂú׿ÿ÷ë®Ã±c§Q6l =ù]ÜlÀjýdb&–Xb‰-vgFz¤%`­~K¥R€çy‚ ÎÎÌçù0V" C8ŽƒcÇŽáÁGwáƒ7߈_|ëðÌþ×P(•±ù¼õX³¼=ýƒxnÿA¸ž‹Šçã{=Áb ÿãc·Á¶S£h¨: ª´y-ÚWqp/ýéW=ò<Ú~ï6¬¹áªað B4RëJEø—{áŸîæ݄–Ë&—d$ÁŒ©öÜ2y‚q÷M]×áû>|ßG*•Š‹òÆ®™‰ÀI3RË@¦ý|ì87…Ç^x¥Í—#Ÿ®;n"eê0–œóÚïÃKO?‡mmçÁ-öãÔ‘—ÑUim[ÈužµÆƒxꩽhÛ¾Q¹¯¼zÚ9WcYJG4hÌïÒ4¤ìay·ÐDoß *Ån¼ºë Æðgí6lÚÒF©Ú•Šƒþ> +(V|Daˆþ®ÓlI!“Ë \*¢·§ ^hÀ°,½‡ðÄKDZã†[øÉ¢L¬Æ¦}6#c\salÎö8Íõ1šësi®ŽÑÙ'a4d³Ù„÷?Y0bš±x‚ïû «Íö¬wÞq£Êã'Oâ±'ŸÁ~Ǻ°}ûv¼ùÊËði7ÄyVcãºU‚º¦¡°€ùöðýƒïûxd÷>l~àQ¼ûÚ«…ß_×þÚhý]E¨8^úÌ—Ñô÷;‘µlØŸ¸{·ÁHKMƒ†°Ò6^ù›o ûÇwÁ‚îG÷#õõ?BfIkÝß9YƒÄæ?Nšû ;3ñ<º®Wm$õNþ¦lZàÀ ªü ¤RmxÓíw çîûðõ/ïC.gA‹­yÞ{Ó»°¦uÞúÞkq÷w€oôìEÞŠPî`i"MCË’ xÇû®ÆÝßÛ‰{1tPBÙXŽÛ>r)2†7“Bä¹ðGÒ)ºعU¸æúËñµûþ_ë9ͺ‹ŠÞ‰tù<è†ëqª5Dß‘ÝøÞΧQ,Cy(ÂÎýG<´äR|ò—߆”ൽ?ă»»`X<Xöº÷â–KV ÂÄ‘IlVAÞXÐ&êÅŸ;[ÈgûûÔƒœ÷¶‰îO½×…¨º3V‡ðzÆèlÏ¥¹4†ÆÎã{‚°DÊø±T÷«a×3/àѧŸÇ¡ã]¤,O>÷"®¸äB¼ý;!J¥ÊȺÒ)¿ù¡›°zYþþë÷ÂÜ÷àã¸ìâ ±lé’QËTÆ®Ö5"SÇËw}¹/ýíÙ&´º@®i¡„ˆ†¹1Ðu¡48&+‡¦túï ëþKÿþ U7_ï~“õ³¸,èºÛ¶áy^CάɓGUõÒu=–I«gbåÚWã½ÿ yYU¼†¹¥[qëÇÖ¡·oŽB3,d›ZÐÚœ‚…X±åZ|lå%è/:ˆŒ4Zšsx_ÑA[Þ„¶_OsJ Yȵ-A[SQ yù¹øÐû42ÍGîÓÐL¬»òfüöùÝ,ûЬ–td0tý raìø°Y–µç_†[:¶¦ ]¢0€¯çÑdÐÍ\ú¶÷ãÜKË" fº K–´ÁÖ£¤ÇLbgœ×úQù^ë’qe9Ä…FùÙƒ ˆ×;FÀ™ô7ÿ,ÙXuŒ¸7OäÌð\’1[ÈŽßD@U@«ßt]¯’ê]ÎY•@àï·wþ ™l–iÂІçÉî}PvœQ…óÃ*±!\/Â/¾ýMxò™ñèÞðêáã8z²»Ê™©§ÕëÌ€n8üòAX{Zu­M×ÿÚï£?—|Š\û! ÇÇŠ?úzØÜ€/—Á’ÿÜ…Ò{Gê†7!r½šÁ’D–9 dH$>Kvf,˪:ðE1£^ pM·ÐÚ¹2þÕŒT+š•ÅÊ/#×Ö‰¦vúž¦€‘…¥hjïDSû™ƒÁ3…öeË`š…æŽh¡{ϬÌÆTÐHåÚ°š¿äÌ"‚†tS;Väy,ÂÄ‘IlÖÁ§¨}ÈÁ_O·éZÁ Ù8€ñF2_Vb`^Ké§VDPujØ¡‘±ço!púǧ±Æ¨ž¹¤H‹Í©Ilê`ZÍ¢Î7ãà@E°S)|ú£·ã¯}+þäίáÄéî˜%Ö7PÀéî>,ëh“ÊfÞzéxò…—Qò=<ùì ¸äÂójÖ»4Ú0Sýs€å‡vÃ>5€f3­èÂúÿ>ŒðÚíúûGžQ‹R°V´Ãþòï!¸õ/0‚Fðîy á»ÞŒ|KlñšZcØÈ|ˆ×ucž*O.˲N§GMòF7ózy¥Óù»,ìä°Jlºæé>äÙQŽ çTDIã0 pîÚ¸hÓ:>q YËD6“ÆÀàžyé\×Ñ>ª»C†B.—ÃÆ ëÑœI¡R®àØ©îIáõëÛb¹c÷AäB ©06.‡~ËÕð=º¡#B- H‡„Ð ˆ"´_º=oÙŒ¶> :ìçŽ@#„à(Þ{[\ÁÃ0`šfU°°!gÆ¶íª $KM&–XbõÛt·±º%Ëaq_ŽãÕ@HåM£S3óÕ'y^ùkŒÔqR³0j&Cx¾* m®;×|ÿ<^¦iV‘PÇ#žK ¾Ôïb ÚBÏÒ$ge2~µÀ¹¬ƒ<|Qai{>õá›ðØî}p~þ¾ïãþ‡EÏ@W\¼ZPqÜQA—©8êY£iœŠƒðXÒ0 …¢óV!hJ# Cض¥ï}+¢‡^†Ö5ý¦7Bko†ðu rþ ?z&@†#m9Fg€å~“Z™ÅiŽãÄŽŒïûS«™‘4f±Æ;„Ó˜Xb³k¼ÑAw—¬@&“©¹69 ”ªQvÙæ"XW›Òñ‰Ô|­nâŽg¬ØaR¯?WU˜x|Ø!Îf³£FAÏÝZõI‰%¶šZ’̦aÂÙ·‹¥2Î]» [6n¨éÈH0¥µµwï|>¾ÏCFX¶´=®¬UC9Õq¢"~ÃY˜È2j#ÔR¹·l‡ñ_Ó ­^ /qT8–_™º>œqª‘Jhf‰Ù¶ Çq ¡†™UÎLH¥Rq!Žê1'–Xb³w ËÏNŒ\/Nò¬»oÎd°ó4×@h­1'Ʋ¬x?›)ãì…ÈJJôu®pýÇsô4MC6›m(¥?™¹Ä7ÉfÍ¥1Jxb³±OÉü°S6–-mƒöòaœ8݃¡Bí6 ]³>míŠehʦÑÓ?hÃÍ*O÷ôáÅ/cÝêU°m{ÚjPø÷MÓ„µ¬ºvÐ4„'z €Tküù`Y+BMCÀ \ÎÁãü0u …I½LbµÍ÷ý*ºÙ”23¦iVÑäL¼Ä›y€Ã ]~¢(‚išU=ŸfØ’ÅÑ¿©‚ЩF昦 c$NW:Uû7Ó&{%?ÛtŽS£c$Ž 0\ )øÙ#>¤8S3Z}¶AëBQäšMãz™¹ˆ7í33J!L×qþ†ÕøÑÏÁ¶¯÷‡øÔ‡n—úÚÑÞŠŽöVôGö O?¿»öîÃ-¿p5~ùæwY 3™>3êgÓé *[Ö"º÷)ÀÐa¾x}?‡æ÷\…hDÉlÔ÷èyù0´Ÿ¿Ã4ׇ¶z)DÌi"g&Á™‹#I@ͶíšÔ庰 _Ð÷ý˜ƒ¯ë:*•J•““Xb‰ÍüaÉàSR®ététú¬pйnf.최½0 aYVL½;÷©:~gs¼XõŽ4MC:Ž™³1Fê\ZhgKrV&6V0Bö÷×mÝŒÕKÛ`š~úÄ^|ÿ'Q8ŠæE ]GKsëWvBÉÞ ‹XÚÞŠ_½õF\wÕ +{Þt¨™EQÜ«·"•Ë ÓÄüúÇŸÞ3—åŒÂ4ÐÓÓžÿ÷«È„©éˆ\Æ-W!ÒµqÂበ4ÌmèjTÄqø¾˲ª4ó~sb‰Íü¡'ëP(9ÉdbªÎÙ´ZªhgÓ‘a§/NÏ8­¬Çïl84ìÈÈ\’ÚqöæÒ\JŠ~[ˆûùxÙŽö6¼ùÒm@øA€»¾÷üë·îé“'áºÃ¬T*âå—_Æ£ï‚eYØ´~5<ׇ¸í]×âsø[xÿ/¼kVtÆpº×QèûXqÉ…xþ†s‘r„†ŽìÉä?ú9<{×wPt+pÃnà£ì»xå‘'qúCÿ éG^D[*£PvÙè7^ÐñÆtž[Ü&BcÒ¦‘s¼Šf nZ#ÜoÏóÍfg&±Äfáäâl‰¢Ï¥|µÄfko¨åðˆiesÉxLfsï¬U##{¹döæê%Íó[ÈŽ*~ñþë߆—œÄî}P*Wp÷·ñó=/`ãªdR e/<†¡²‹|¾Wì¸ïÿ/ÿ‡Ÿ|劋C'ºñÚÉnDa4Ü`RÎÜ|óþ‡ñûŸü%üև߇0ŒP*—ÇýžñêPêyŽQÿ®iHíá}â‹0 –m¡ÅL!õüi÷…†ÐL)ËB^7`—|è+Û`|ñ7áoY ¯Tnè^[ë]| ß÷aÛöÔúÌgøÌªÄ¸p4±Ä›~ðÆ”)MÓæej¶{=Ž ÓËÄ‘™ëï—öl€­±™d%–ØÜqÔƒ‘½á7é}¸ú²KðÀc»±ë™ÐÕÛß`[&:Ú[qù%âÚ+wÀ0 8Ž‹h‚륈6™µ5ê³Q}U´þoˆ¾´øÒNýEä2)dìÜÈGBèe:èï¼ ú|þ¶õpKåšõ<‰Ó’˜ÌM×uQ,§$Ücr”@@KÎÆ!œXb‹ÙØ‘0ç¨eõlF3½O¨ÎL*•šQyêé¾wµ÷ÊLÏ%©u<[…þš(õ-„3§ð8]Œz({êýMå»§ãZ gL”e’¿Û¶i¶ž·…w`°P‚ïû0MmÍy47e‡×ö8Ô›Z3§z¿ª~mIúÿ¼ÆmoEô¹{ Ýÿ4ôa…5¤mhoØóÓ7o½ŽçÁ¯Tjf^j5ÖMlq;4–eÅI“)ÕÌp×WÉÎH”O¢Ä•3±Ä½0ëYŒêf.Mç“#£‚°™Ø¸Á£È8ÎG†Ÿa&%µYXæÒ|Êî©sg¡giƹܠv2ûˆÌ³‰ö£±jøsõˆþ¨À¹Öµæj³Ý™rNUê’Ï´æshkn‚†a‰ãÉPÇ£9Ö«t6ѽÆuë:a~ñס;>ôJt ȦáF!¼r¹ª­G½k Á—‹7™¦‰J¥Ò¢™É“ÔË0° ‚ž7¬BÑ××—L¶Ä›Àt]Gkkk]ü뺫ηC^2»“)4U´‰>nˆ9ÇH@Ýd"§¬ˆ6Ñ\b§Ï4ͳ&Q=s©Ñhí\©™o-0Ød‘Éà‰ÓkFìTŒ Õž6¼N¤_ƒª¬Ç±9!Lñw× ¬¨ëQí#×’=A®SOf.6TœÈ¨Gnx25o2ø,‹Ö5Ö}×Û‡&þ]߇ãû€†3?P,ãPky¾¨sp¼{MlášÔÌH½ŒôšiØ™×u‘N§á82™ ÇeY±\ÚŠ+’I–XbuDJ¥Ò¤Átqž&ÎØLЄ8,…‚óqNˆ“1ÝY,5»'ô²ù¼WËU©TP.—áºnÒ”=±8p3Zj•4³mÛð}†a d³Y8Ž“81‰%6_å63%c¾?¯’Óåàpt^2Äó}ŒÔºÄé*Mi¾;32FuQ^æ 5e¢µïû>šššÉdP(ªæµaØ¿?š››ã÷É€Y±•J'Nœˆ•ù»²Ù,òù<Ç®ëpgBgûĉèè舻r³ôr¹ŒŒ;×¢(Š#ðB{œ P™3ÕAÐ4 ¶mcpp¦iÂq‹ET*•ÉvÈ|’ÌŒã8q¯À‰Ä?äýzž°Ëå2J¥RÌž‰±”ï’¹¡ó¬¹8±ÒT} ³ÖA"àA&šxL‰S“XbS5µhA ¡àY²õÖx¨r­½ˆú\î'3Y°>Ùqš¨7„ìÛ`æû8MfŒjÇÙZë“)´6M---õïýýýèíí…mÛ1µRUÄÇbhhÝÝÝ£¾/ C,[¶ žçÅÊz:Å÷öö¢¯¯/–>gú¨\ãàÁƒwߊ¢¨ŠJ$ï´^Ç|.ÎãñžUlÕªUØ»w/¶oßKΪÂtªÖ©t6qj׬Y3j\Uç+“ÉàСC(‹qvghhŽãLIYj¼{e:›ÌÇ\.‡¦¦¦º×Ob #qÀ¦Q§ßd/%DmÛŽ»q.„¨qb‰ÍUGg®÷J™¬C3N«3-zÙX@}"›ŒšÕBÈʨÿ|–jž(’/”®“'OŽ:À=ÏCOOÚÚÚ`Ûö(5<ÎÌôõõ¡P(Œz÷¶m#›ÍÆßWo ’ã8èîîF[[[ìÐHÍW(•Jxíµ×êš›,p°A*gÌ6lØ€<þøãX¹reLda:ëåÔ=@àmÛ¶ 5MC.—ÃÊ•+±k×.¬^½š¦Å5-¬(5Ý÷Ë¡+• Ö­[‡ÖÖVø¾ŸÍ©™¦g§Ôg†="‰¨LU³<±Äÿð©Õ5z¾u¦ÄLeïà±ZHc¤*KMGO.è]HsIi IªYQ=ª™únûûûQ.—‘N§GÕÍpt»–c!³L&S¼&#wzìØ1¬Zµ ™L&¦wJ]ÅéÓ§ë8á`„:O²éºŽ;vàØ±c8pà@M„™2Ã0°råJlÙ²%îÛ1uíÚµhkkþ}ûfU±V×u¤R)ìØ±K—.­©n–Øâ0 xAÐpŸ=“7X‰ìÉF)h’™I,±é³LZˆÓT"êjw¡˦]ÏsMFÎu¡Í%vöÇ‹0ÏEðSO}…eYH§ÓhkkåÌ@¡P@©TBSS‚ €a±0‚œÑèéé5t]G>Ÿ›ËŠÜu½ÎV¥RÁ©S§ÏçcEµ à8ºººfTíj.½×Éf”Øé^³f 6nÜxVö.¡M™î|>7½éMgëI KË'¶øœ–—ŸRf& C¤ÓéªNä2ÑX«>ñšKlr`l,GF€ÚB[S"A<˜¨f†¶Éö°™/›·išq&«)Õ‰:i/ÄF““íÏs¶kf&zEÁgÉ’%8qâĨÌI¥RÁÀÀ@L¿º×®°´sÕÁnšUÎÌD޳:wt]ÇéÓ§±råʸ+ C ôööNªÁédz¬ÌÅš™Éô_QŸ¥Þ ÅLíÃõªÐ ˜ä^C³=Æ hñšP1ÅiÄLÙŒD CÝ |ß_€+±Äζ“s¶ŽÙؘd™ »Çhº(7j£Â…8N ñ¹DIJDr¹úûû«ž5 Ctuuaùòåqäš ñű¨eétÍÍͰm;¦‰7Žªºž¦iB___\wúûû188Xu-iç°Ð1ÂdƒòYUen¶÷˜ÉîGgã=&NÌâ6Ã0Ífã MÙ)°•‚Ó4Q.—cÎåB*¾M,±¹t8N·ý>„a †¦#m4ÃЛ(ø=Ã"lÍFÆì@¤¢e¿Mæ@3gäù=ÕÈQòû†šŒÑ]Ï"Â̰ª”õT¯3ãóJÁ üpz!eä`mgxŒæ££6ÍLp¡š-Y²}}}UÏ©izzzª¨fìÌô÷÷×”ZÖ4 ­­­H¥R±€ÏDkPê¸& Cœ:u K–,‰im‡ªr0å÷&S³˜l¾u´OœŠÄÎÆœÓu®ë²,ø¾?µ>3L{0M³JAe"múÄKlb £lÓ @ øùÀN×çp]…mÛH§Ó(‹cŽÅdäªçÚ{M¤‚Klæ=˪Òét¬…nYVœåfFÉ‚N,1LRÆ; §›®AÃPTƼú\mvàm›¾‡—ŸÅ#‡íésñ¼½)çܲå|öÐ'10p?rùkñȱÏàã+¹ˆ¦7¡ö”˜¨Ôª¡™ ¡AC¼ù€ IDAToÐïüUܘ½Û7þ%vþ?>ú´g¶bMç'bf* ··ŽÅׯ5frov5àž#¿‹ôàOñ©uŸÇ öJ<|ðWðíƒÇ[÷`:0¢© Ï…š™z߇œ­¦i"“É ³³G­Z7𦡻»kÖ¬‰U~Â0D©TBoooÍF™ÍÍÍH§ÓU=jX¸Ö\IßææftwwŸyﮋ'N@Ó´¸>‡Ìl6‹T*5æóNvÏS?3WÕÄKlƒe#˲ày^C×Ð9ÂR.—ã¨T*qV&I!'–Øô:;ÓY `h^(ïÃr¹ô&tä߈ËÛ?ˆ0Pz×·¼Åìëð§»—£µðVv~ÿxôñ{:Ún†¦™Ð4}Fž³Ñgä¾ 3™14ûJÏ 3ðÑš»í¹í¸¬ý8Nù9h¡;£àh:(T3=F4œôN"ç¦[XÖ~3.lù6ôúÝ@ùE@Ógt½,Äš vfD@U¤Ó4 årýýýp]7îWR(FÕ®(hii‰ϘˆúfÛ6òù<ÒétÕgpêÔ) …ªï³,+˜L?¤…¤šŒó“üDg=ÐØÜ7Î OIÍ,Š"d2‹EضT*ÇqÉdEq_b‰ÍöÁ8]àLƒŽ‚? 4 ¤ô4<aXD^3ñmÝrXBÖÈâ'}÷Cï½ [Ïù:>÷â[`xGqiþm¸bí_£¨Y¢95N3z}hòûaˆ4´x좠 Á¬=çTöØ™' NP†µŒ4,Í„¯iÃs%„m^ŒÓ\ÜDÕ¬©© MMM¬úLèííEGÇ0å1 Cœ>}®ëVQ¾ä 9e¡™Õ³×ˆ3cr¹\µ\šhrmWEÈçóÈf³‹¢wÌd ^:{Á—Äæçœ,¼Ð\vfDE “ÉĪfâȈ´cb‰%6½ l:6õV¦Öá0Â2 hèñû‘-ˆô,œ`†fàPå xícø?Öÿ¾Ü/®JoDó†ÂÏlÅÅÍ×@o¿aäMÛ3ÎeGfxìB¬NoÀ£!`CHi6zü>ä" ²:i3'~2]™) Ÿ¹ñŠÐjµ£¬°À@ÁL!…ð£°V#B4#îL=53 Á™‘³·¹¹CCC£0z{{Q*•â퇮y&«³zçgˆÚÚÚ000P%u§ê:º®£££©Tª!Yñ¹´Lûž’H OøNj¶5±©Í é§5%gFRÒ®ëÆÅ©ŽãÄ¢Iš0±Ä&ÄTnºÚ/c:ÖS8×>aóå80ô~üÚoã‰òn,×sšÞŒ@Ï!Џ‘øS|¨í&DÍï€6ð#Q'p`k€¡§àÏЯ§Ff¬±›É='ˆ|lJmB”ß‚]½ß@IoÆO‡~Œõ–åMoDkæêujtm¯w Ùy™éqŠ¡CoCºù:x§îÄ=¯~}æR„îa\Þ| "{º3ªüV/0>[g¯ëÉÞƒ8©T ---8yòä(j·ëºèîî†aèêê••†)f¢bÆÅÿõÌMÓbg¦¥¥™L¦ª‘§*JÐÙÙ‰L&Û¶§†®Ö×Ì5¼1ÞýÈz¬$5ƒIxlg†ßqâÔ,nœœ)uñ±†iˆ%T±X¬ò”K,±é<Ó‘‘>~gã7ñï¯ýë¹ -F×­þ Ö,ûÊ#ô WJOÃ,>‰uçüoxÞÖùq|óÕ; ïÛ[;?ŽTË»àL“*ÕX"Sü3ÔMÍħ6~ ß~í×ñh×?`™ÙŠw®ýÚÛn‚3:&³á«²½³™µð#_ýø=‡gOÿ²pñÎŽáŠ5ƒÁÈ…6ƒŽÌ| í4zvE¦¹­­ étºÊ‘ó¹··Ùl§N’¥ð?›Í²¬88©Î™‰îEèiííí(‹5Ÿ‹ïSjÎÔœK@w"gPœù9|ø0Ž9’¨ÁÖ0Û¶±råJœ{î¹ ÷Ilá˜ìg’MnÄç¨jš™Édâ? àJ¥R±ÂYb‰%6} vºê¼Ñ‚Ož÷ŸÐ4Qx‘‹RX‰“͹˰uËSpƒ€kÓçã÷·>h€ú KÓFšŽŽÞÍ4 é´Wã·.ø1 iˆ"À 8‘3kó`ªã¬ªÇÍŒãçã¶ÕŸ¾öχÝç0ÀPXœqGfªc4œ ¡šår9´¶¶bhhhÔœ/‹èêêŠéf*Œ SÌê;â­\¹'Ož¬j¤-–ËåËåâï™I ù±W3I@:Æõ×_?JÔ!±á:¬^xÏ=÷.¾øâ8ƒ˜àÌÅiR3 ׎'%?®3ÃÑb‰"v¶$RKl!/Ô±þ:×S„¨Æß›yðÃøïƒÈG™þŸ?;]d,ŠK=4³ñþº-@€²?8ëNíXÒËõΕÙîÜí%¨š3ù­*È™/4³ÉÞ‹8º®cÅŠ8zôè¨ßõ<}}}qO¶T*…¦¦¦8+£¶SŸ±Ît™CBy*ÙáÇGÕÊ477#“ÉŒ¢²µfëU´ª%Ë<_zÍȽ꺎Ç#NcÇŽUÿ¾Ø©T2FA ClÚ´ Ï>û,<ˆ .¸ š'sñÍ )ü·,«á&ÐU532É$:#*f¶mWqoK,±ú7ïñþ}!6Oï}!ŽSEqgözÆh¼1®þBä竵õ€à¹°˜ìýˆ3cYr¹–,Y‚Ó§OêÕ4e)—ËUQÌÔ€B½÷""Xºté¨ìL-ŠÙd‰Ör-‡f®ÓÌø^u]ÇñãÇñö·¿}Ô¿7R°Ð, Cø¾ÿŸ½÷޶ô¨îU_:éæÎIju«¥Vjµ QF $IHÂ` „ Æ<ÃóxfžmÏa8€×Ç3x°Á,¬GX€E”%!$¡h…êœo8ñKUóǹûÓ>Õç¦sowßP{­^}Óù®]{ÿv¬z½ŽF£¥K—â™gžÁyçgY Dãç{{{[’žrà‹“Ëå2¥†!‚ °Ml–,ͰAœï¥3áíôýJs*ÎÌB•%ža˜ÏïIïJÍòåË'½([A6^YJÙÑÄD> ¿¿K—.ÍFFwuua`` sfhÊ©mÞnå_E™£g'¯³’$ÉÎJª×ëˆã8“YK —\×Ͳ  Hã›0I;7Ý’¥4væT³ù8ÀéDo´ktŸ<’RN+¹Pd‰¡‰äe®¿«çyYv¦«««mïŒIžç¡»»;ëaéÔÁ  eg´Öظqcvp6=_.—Ë'üÀÖ9¼¶íÊ:Qf&Š"4 DQ”­1ï“´´°\)%¢(Ê* :ÍL¥dq£P( R©Àu]4–æ5a°d©³Í:û‰GWÆŠLNÔ3Ãy4ÕSÃdÞq2<˜O|"‡êì'# ³¥g†d¿“븮‹\.×öÌ™vïK‡WòC2ÛõŒÕ‹b~OÕ¹\.Ë¥iÚ’µ!\@Îødöød×n¶õÌLfMfïZì„–ý‘¦)â8ž÷zÌÒäõ}’$—™µš)¥DÇ-ÑÊÎXá²di挟yšö|Ѝ{ž—éŒÉöƒŒgøæcv†œ~.Åx¼ëýMð7ŸxD šÏd†$̦}>g†¯Žy¬ÁX÷åÿh²ecèZ”¹‘Rf‡Æ“9~͉š±œŸ¹0šy¼ÏtêØÎG2\æÔ*˧…“H÷u<š™.’ËåP¯×á8Ò4E>ŸGÇÙK–,Í\‚û|éxÎÄ3óG–-[†F£‘É4­_±Xl{€çTuä\$Ó WJ-èa ã·´°‰DÈ騙¡wª…m7ÅÌ  %KSWÞãýží¹¾·|ßÏ@:¥‰Ê§&Ë'ŠÏu !ZJÌ&kØg¢Ÿf.í›B¡Ð£vg«´½³¥gfºÙ6ÏóÖ®]‹eË–eMøˆÉ‰‚ ;(s<‡œ™þþ~lÚ´)›" kêÏårÇ9Dã•¥Ñ5ƒ À¹çž‹Z­–EUéçSz6ϵ›ÌÔÀ©ž¡³mâXü˜Í½R–N¬L^›Î—+» $ ’$i©‡í´!Ç’%K ùB¾ïÒ§bà&âÕ|àE© ˜ÎTÖÁì+šË<" >‘C<ÛïLé:¸’&†¹®‹|>ßâÐñr4Þ/Ó.‹BY*åcÒyGt©€ Â4†˜äšäÐó¼ìù¦š™áÎÁ©ÌfLDZšìa¡ ¸Ž7$Ãòha¯Vèô<¦g&Š"DQÔ¢Ô”RcNœ°dÉÒÌ(ø¹^~@€…Й4LfÝþ\¥|>ߑ÷d)ŸÏgï2WË̦û¼ä P¾™Áã½-¼Çe"ǃœß÷[ÊžxcÿTä‡#žq$¤çš¬#³Ð€,çÕDüá뮵F½Þ„@!çÂö$YšÛDãºiðÈ´23Zë ˜J%{0–%K'€ø¾¢àÁ\|‡\.—•MT4ÍÕ̃ÖÅbBˆ,ó}"ù4We‰Î:㥊 Q'p'ƒOô›ÌÞO6ø9r\§Ýg€ÌÄ5Ç{¿S­Ÿ§³÷Û9äÕj#•:úzJèÊûˆµ@—…ÖZ£R©@KýÅb-¤u¼ü£ocÇÙ·âÝç÷"NuÇïw2Kàl¶ÊÒXzŸ0Ä´Í$ψ‹ʤˆ ?Á Ÿ%KSSÜ“ý[ŠŠÎ%§µF©TÊÆºPŸJ¿ÐT )E“皢r›4M³RÞ©ôÊLå}©th®9}äÈø4Ãv*R»s£fòYÚeܦÓ_ÒîZ\g¼ëNõší@î\9gf,q,HÓCå vÿôŸñ±ïmÅuû,>pAaÒü]Eˆã8s‡GŽâñýG<~þ‡ðç׬‚ç¹i‚z* ¥@܈†!då}TUCN*ߤqçfÓTÛ &šTgž5YþYœ¹0q Óéôd— &jÄùÐxkÉÒlßÐüôÛ¹°ß´ÖYƒ/EÒ§2¡«ðD<šK™:€g®Ndé/sÉ¡Éçó-vh²™™ÙÖ3s¢€ø‰(Û<™`¿S3W{fÌ 0ÿ|†ˆjñèÏ`(Äî¼ïÞ| DXÇÐБ& ü @¡PDµZÁÑý»±½ÿÊå^Ô1]ö6¼kIÃå>„j¥ —ËañâÅ€ýû÷ZCŽ–w÷ô »« CCCAÃÀÀŠÅ”Þï‰'žÀÞ½{;+†¹E‹áÌ3ÏD__ßqkj'šY2÷ ýëÿ´”™Qs*yIæÌyK–,âû‹zOf»¢÷}ù|>é“Í6ÌPŸíù|>+/㙫“qojªœíAË{P³¥ùJZkTªUÔw=†_Y‰ý¯×ãßþö[øåž°9_ÇáÃû°ýßÁ=½„šú×áo¾Oï:„}û¾„??€o¸Åïÿ5þýêÏàs×ä1øÊ¯ð»~€FîþM|è–+0¸÷1|áÿ½ý›^‡øØ¸þCÅë–Ä_ü<ÜÁÁ™·áÿþï7 $˜ì®«Õjø³?û3Ôjµã"éJ)A€;Sř±di¬=A%Æ&š²3C†„_ˆqì ¶–,¼MM©ÿ‰Nþ>•ä8 …B‹#Ói­ëT:e(ƒ<›šB¡×uOXŸÌxŽ1e±\×Í‚S³Õ). ™u’Ý›­ Ks›—Ó½??c†²Lq£<|¿~ì)ˆó®ÂY+ÏÃyË¾ŽŸÝÿÎ|Óé¨|ßùñ^Üþ}o]_BýØ>l¬!·aj¯ÿ$>wëìÝû"~toEO"j â—ßýŽœ÷üóG®ÅÁÇîÆ_üå¿â§[.À~Ï[„7ÝñG¸t™Æ£ßø Ü}ßÃxÝ;BÜuÿÞÿ…ÏàÝçö ®Dp•‚šÂ¾»üòËqçwâŽ;îhÑÁ@ùú׿ŽóÏ?•Jå8ûÆ34–,ñá#êþÌ™¡èR*›¢Â " ¢uj,Yš˜:-ñáežçe5ϳMñ”J¥Loð^™©ùNõ ý=/‰m ¬T*eY¶éde:M»_iôîlÌvÐ9)œGS=4íDõ©tÊok'ç';ÕS¦|Öëu Ù‡'ŸÛ-·®†L]œuñ¸óчpìò3|EçaóéET*e$Ny1„(UPÒ¨ŽF˜@kB@$5ìR¸ò²3!ke$ÅeØ0 ðü¡.ê“(.[Šå‹J¨×ÂéY ™VQX÷Nüɇ^Á—þêwñ•¨×¾ÿñ¿¼ýÊÐPjz¶84RJ‹Å¶ŽÌ© ÊbQ†h¶èò P,3Y[ci¼àΩºÿL:gišbx¤ŒÚ±—°cû<üé?Ä€R1†Õ:¼2XêUHwaë¶Ý8=PB:H…D\>†‘r?”J!Q(õ 7'ðâK»°¯+F}äÊ¡À²ž\æœ(¥ •‚ “ÕrŠ oû=ü€ÃÏþþôƒ³¯ø*®ïM¦“×åQ¡P(`ëÖ­¸è¢‹ µÆöíÛáyÆqvgdlÅ%¾Ç¤”Ù𱎰 7Àtá8Ž¡”B’$™´©sK–N>P'‚œ‡SI¹\.‹¢›ŽÌ©0JtOë¤ OedÞó< H)ÛfdNö³¤ÒÅÙàS•6“,ÍÕ3eN$^ˆ f>¾×«ÿ€ 8ü«¢øÖÿ†»ÿô(¤!ʃ{q×ß~ wýüüí»ß…×ÿä¸óó_Æ…ëû‘s<¬½úflØx¾þ³{pw÷yXsæÙðEŠH t ¬Âu×]Œ¿ûöWq×Ás‘| û]Š÷½ÎÞTAºŠâT 9ü(¾üï¿Fßât%‡Ð·þ\¬*yÐè,sì8¾ùÍoB)ß÷³IicñÂîK&ñ)fÓê™QJ¡Ñhd¢(3ÀžçYgÆ’¥S`É Ðp 4œ¬ýHyù|¾e´p§“ËN$hô(9'Sgq€ Å‰9Õ|âN?„ñd†¬µÎ†FPO˜9¹l.~>ˆ%ËK¾÷hÿK)Ð×Ûs®þ06®» E!ISä»–à¦þN;Ú‡RÏÜñ_?gžxGë)¼îå8½¿ˆþ[?Œ?9íiì¯;(pñoÿV.éC¢\œsí{ñ‰5Ocë®Aèµgáͯ}-V÷øh8çã½ï_„Ó yä°öüëðþ¥N_[ÀÕ—.G€{:þè†×á‚\‚F¨:.>묳 „ÈpäX×™©1à–æÏ^'ÉÛZ:vf<σçyY#Þ?ck-Yšš’Ÿî~!ÇÏ ’œ“A…Bá8€Nt:àÓ4òÓá/] ìƒëºÃð„ë+ ö”J¥,Ò®´l&ø4Ýç¤çSJe‡”QÐêd¬®®®Gj¦²V3)K3±ßÇ:$ÑÒäù7[z'ÌLÂDç¤Læo…°î’7B(|5ƒQ\¹W®–Ðq ·¸ ¯yýòfO ÖHUŒÔ_Œ ¯¼I @C­ºKDq¥=¬8{ VŸëŒö(¤I'èÃy›ˆ‘¦…þµØ´¨‰ç6_öÆlÈ“V 0ê8cK=“Ý«“YK gßÏ„Ñrh¦ã8Èçó-ŽÌÉšÀcÉ’¥±7;Å´7yöt¦'M˜âwbf[ý $(›DŽß‰àMt3Ü­™>Y‰ô}ÐZge!3ù¼4:—Ë!—ËAkñ‡Ë’hdÉ”Ó Ÿ/NRµû;¾”Âq-“DøjwÝ–kh„ÝãdëqÓÙ·{ßÐäC6ˆNîØ™áTÅq )%¢(²çÌX²4KˆG°©¤Š1ÞT9ÙýJK'M“£DÍëü?Øj¶ûIc‰yP†±©òh–±qQ–œJóú³5d‚‰ñõœ,Ÿè]¹,èŒΟùÖÃÁ¸¥é$æÛ;ÙlCû5¶<±”9#¬7xZ=3ôa2ÄTÓìyž8K–fXç¥gÚ9P%Ðhž´Lá !àºnÖCÁ#¢J)„aØr¹tb3e²8XçïÉ' µs>ˆœGÔ³D<âÙ “Gs!Úh‚,~&çy™˜ÿ8ŸHޏ“G<âö„;0\>ç#?lĹsÝÆ¨óÉ9´8êxÝcKD¼,»ý隢düy#­.X²4u¥}¢Œ"D2þ*)*Λhù×ü™Hi´®'Ò‰9gƒP„‡&(A0)qãKÓÒ¸Ãx"€;Ñ“øpšG¥u7¿v|j'Kœf–j!b¥2»vglXŸh`ÇtÍlk–Тì K¦ýá´ŽÇqàû>êõzVãL3Ãg[³¯%K–Ž7–'P5ø¬ÏWãÛ.ƒ`òg"™ŸŸ¯|âÎ_;‹O …Gca×uQ¯×Ñh4²:–&–»Z­–e–çCŸîlÊÎ6'f.•-[:yÇ1\×^™Yš¦FOOOKã£ÑÈF³Z²diî€v¢ñ@Á©2&³áTïÙΣÙ&G–O“sh¨Ïjddù|Þ*¥IPE¨V«Ùt@ÞŸ6—÷?`ødž6[™8ŽEQËË–,µ ¢uìÌйtA†( YÏ oœµdÉÒÔ@áB†v†ÍTd–G³ÿùf#ŸfË93äì¹®‹ P.—Q.—ÑÕÕeíæ<;xð`V â8ά‘·©œ3ÓΑ‰ãFq/è *9¢Fafý‡f”Å™ O6hzj¡PèØáo™fF~T©TÀž3cÉ’%K–,M˜K)¢(‘#G²@¡¥ö@æðáÃFæÌtz øl ß÷Q.—á8Â0D­VC½^·Î Ë̃7××ÚÒÌÉM$_¤cg†Oa¡ó+ȑᓑ,Y²dÉ’%Kíš&˜ËåÇ1:„¥K—"ŸÏÛ²ƒ>ŒC‡¡»»…B!sfæ"Þ ¶bÅ <õÔSؼy3¢(B¥RA­VË‚Ä Ù™1Ëîà´ÓN³ûÂr¹’$”²£äI‹3CgÊÄqœ (•JVÐ,Y²dÉ’¥IZrh¨l»\.cçÎX¶lúúúü'âÑŽ;P­VQ*•P*•<Ï›³ÍÿØW®\‰ááa<òÈ#X¾|yV^EgwÑß.4g†þ×Zg$vuuáœsÎiqnlÐÂ#r`øTÍŽ™4MÑh4ù|>“V©TP*•ZÑ’%K“Sàv¿ŒoÜN4ŸTš IRÀñà»Ð)¢8…ຄJ( h = ´¤ãÂu$XÄqÇó Å©áÓ‰•#8Š àÀ÷]h¤IŒ$Վג8†Ò…<ÏgGGH…ßóR–¦Öi@.—˪öíÛ‡ááa dg-”ŠZ“$IP©T°oß>@WWW[Gf6öˆMF¶h­Ï?ÿ|8p;vìÈp•­niÝ#ëׯdž  ”ÊL´ãš&B MS¸®Ûr¶eGÎ à,„@EÐZ#{J«%K–æ$IGaÛ¿Š/þàa¸›ÿ >ùUØúÀ¿áKwýîš ñ·ßŒøÞÆW~µ pó(x)ª‰‡Õç\‚›ny+Ö¥%¢á§ñùÏþ^ÿþã‚98Rf ^«I:—¯@Zß…¯|â“x´ûz|ò£7Â?ü¾õµ¯á©Ãy\úŽßÆ›O?†/þíÿ‡íª ]EIT‡7°×¾ó¸âôh-à»CøÖß|Û/ù(þðº¥ÐJ€Ì†Ö iÒt ŒìöPÉ697µZ »wïÎÊÐ\×Íʪæ+ˆ£j0 Ñh4$ ‚ @±XD>ŸGsº¼¬Ýû&I‚åË—cíÚµs:Ût")MS$I‚$I² Ö‘Y˜Ž-ï§êô\Ë–23jÀ!A#eL‡YY²dÉÒœ•ž|¡ÇKðÜ}ßÀß} =¯½·ÝðœÑ¯ð+/@>ŸÇ¢M·ã·Þ”Ç}w~n}>s9Ö]Þ ­”_zñ’8}y#/ÿ?{j;ë)Ü\+ξWž×5§‰ _ûQì IDAT@©”GåÅûqÏ=÷á•hnùÛpÙú~T !ÈyðúÞ€ÿôž QÞþ¾ý­ãû½—q¤vì}ÏÖWãí—,C|l}äì8\…ºWlÄ•[ÎF)XX¾Ü¡!g†ìi†¨V«YÁ|Íâò²;!|ßGWWWæÀø¾ß2Šy¾~gJ©y÷n3Í'ꥱY™…K”¡IÓ:4“ʤL EªÕª=gÆ’¥)pK³Ê£A}ë×pç³1m¹ï½áuè Ð,/¥êþgñˇR¼8Tƒã­Ä9z  eÏ=² Ü„Úãøû¯Ýƒ£z).ؼñ—ðË'6àÊMÀ\žT$HÞÑ_à_¾™"‘KðŽ÷[Vå ‰G¬îÂã%(ïÞŠa=€‹Î[ ©4„cçÓ/#\} 6jxòwã;÷cã¥ç¡;>†—ž çŸwæ‚sf¸C#¥Ìª|ßÏŽ= gŽ*ŸOŽ wh\×mùÇÈœoz“†­3Óžì8fK$ù|¾ãIf-ÎŒR žçµD‰¨Q‹"KVà,Yš¼³ûe|åe´¿‡Òh^V@§1B¿çl\‹¢' ”†Pj´ôI 1ø2ž¨I¤‰Š%8Q…<ıgð«C\~Á ˆh'^K×`ÍE—âÆþ.¤arÂùt"åH«f¿tŠ0JPÚ¸WÀ(44 $œøž}ê( b¸Å<¼$Aª/<†§w bÝeë$ ’4F"=tõôcÝÊóñú•KQ Üö³éœ™ñ‚¡§æçñNBŸëzƒÞ™xr\ø?ògëFœ3CD.Ö‘™ØXZ¸2 ¥Ì²3qO¯ÌŒªŠãžçeŠ6›þ³d©CnéT/iËîâMX¯žÇ=_½õwÜŠë¶œO¢°â²ßÇ»m%^øæßáïô"~úÇqö‡®AùñG0ÜÎPˆõkpûÍ!~öÜnìxü~Üû]pÖ\üÞõÐ Ô\æ“VP…Ó°yiO>ýmü“SÇoÞt–åG0L#DËߊÿã£o@º÷I|ùóŸÃƒßü!¶\ô;XzdvUºqÍšRéáüKnBÃy »_ù5î}ô‡ØSîÇ»?ô[¸pyiAëÜÇ9(Ï÷w'Zˆý#?Y²46I)3ÇŸšÛ‘3CgÌäóyh­†!ŠÅ"Â0̯%K–,Í=$‘"X¶ï¾z#ðÅoâ§wÿO ÞŒÛÞ~6ä(šÙñsüðž"výzZ+ˆ\ >‚{Ÿ8‚å—¾}B!z¼\ÇŠugcmtÃGcÏŽ—0˜J,r€¹Ýá®+qÍ;_ƒ3øîºÿø—zˆßºã­è€–äð ¸ïÇ1âc¯`ÿˆ‚Êw!€Â¡}».^‡y:°{çËH ËqΦÓpè…ì|èW(a¡[‘v‹ùn[mpÇ’%Kã:"® ÏóP¯×³r³Ž™(ŠÏçQ¯×³fÅ8Ž[<&K–,YšS~Œn6—ŠT¡¸bîø/ýã×ðÌ}_…Ò7â¬T#Mw<ˆÛ©¡Dkο7½ã5{Â3å~\¿©*Q®‹äðsøá#‡ÐH·´W½ç6¬óâ9Ý2­¡Òiš@y}Øüæ÷@НâÛþŸþû2Þó®s!4 ÊÏãûß{ÅÅà½ï|3©ì܆g¼9WZ@ăxâþûp,T€ôqöÕoÁ–5ý°á0 ö-Y²dɤ(Š²Ã†§]fF}1Bär¹¬iM)…\.—Ž´K–&†ºí×–ÆæÑ‰àS𬻿½ø«·þ†hÔ" ÷üî'>@šÄHÅ\ñžWÁ¤ÀèÙ4*ÆÞ—öA®Ù‚ $UÐþé¸ùwÿï”B4Ÿ9‰#$‰:©üšá+CæÖàýŸú,>¨4Âyl¾ñ?áu·8:A¥8ÿSŸ†ýªC¢GGiÖaÿ!ë.\©5\¬»øøèïΪüT#ŽÓÞ3s"eÉ’ÕSV¶,Y:1{LkZ­ yÎå´¦™ñQÌÔ#C}3v4³%K–æ"©$B#ažŠVˆF±Õ|Hãã?' P<ó2Üvv/ülP€B…ˆç—5ê­Ž`µð%5~O\’n¯½þ&ô.-¾zµ4F˜ÆVø,Y²dÉÒÄH©ìœKi>U’übžçe£™)#“™­iŒL³dÉ’¥¹D]‹–ae_Ç›KÂ)`Ūe(¸––,Y²diêDgMq£cg&—Ë¡R©dÍÿ¾ï£\.C)e6¶Ù’%K–T×Ú:2“å“eƒ%K–,Yš"ÑÁ²Q!MÓéO3SJ¡«« õz¾ï#Žc‹E$I¥ŠÅ"*• z{{mÉ™%K€»WÁ°Ý+ãñÈòiò²dÉÊ’%+[–,Í'J’Žã Iø¾ŸU‡M•²ÌLEÐZÃó¼ìkî%õ÷÷#Žc„ah§¯X²dÉ’%K–,Y²diê·”¨Õjp]…B®ÛÌ­tz®eæÌÐéÄZk¸®‹ àº.’$ÖŽã`íÚµAEÖ¡±dÉ’%K–,Y²dÉÒ”™‘‘4 ¬Y³AdŽŒ”rz£™…Ù¬ç4M[¼#J¯æóy,_¾„çyÈår™dÉ’%´DlYÂØDÓ9¿,µ—%â—¥ñe‰Ë”%K3%[Ô+lõ¹%KÓ·gI’ Z­Âu]¬]»6;Ï2—Ëeý3ÓÍLÑZ#$I’^#„€ëºÐZcÑ¢EèééA¹\Î<+^ãÆ¿¦25úžfJ)q¡µny ú9]‡>OÏÉïIßÓ×üúüoÈëãO÷LÓ4û½”J©lKúšÿžO€#Ç~>–Wj>ñŸÞ•(¿݃xÁïÿ§w¡ïù³rÞrн8¸ä¼H’¤em8ïé{óœ7üÝ©F’ßßäÝ—ó¯Ý«LÏžx¦éqïÚî™è¦<ó5ãÏKÏ@%™J)ŒŒŒ@r¹œ]×ìàצÿù³'I×u3¹4ß‹¯a;B´•iþžægÛñ×”év÷4eš>G|çëL_¿ð èîîF¹\náýžž~N2È÷B;ùi·öI’´\ŸxÃ÷ —SOŒ'Ó¦ì›{£Ýš3yo¾ÏÈÈÇA¥Riù;Ò«\¦M½ÈŸ‰Ë´ù5ñˆOrbêb¾†\>¸Näò`î#ZSº¾É«ñd’Û“OµZ Adüâ²a® ×céhóø³›Ž&]Ç”#.¿üýø5HiíÚñ›ó•Ëçe;7–h§wÌwå×4õ®)¯¦qÛaÚnëÌk¹®›Á÷®¹/øçÆÂ¤'fwŒŒŒ ‚l@Òx¸ƒW¸t‚;ø{¿9¿Úá~Ý©à~oŽ?¦ƒ;̵ w˜ºÂÄt?n—Myåò0Ó¸ƒ?ËLá’…;Ìêtq‡‰·ÇÂíìa;ÜA{Ò÷}¬Zµ*+-k4¨×ëð<a"ŸÏw4l¬e ¦ëº¨×ëYy½$M3k4™¡ïééAð}ÿ8`@/Ç1|ßÏ6x7ψãù|qg‚â8†ëºÙç(CÄ77âÜȘáy^ËbðH9ÝÇTXRJ4  …©”‚ïûBdŒ'ÞPšž„8‚LXÓ4E.—C’$Ù;AÐø Ö¹Ûæß‘€Ñ½ù{Ð{yž—ݓ֗øMÏFü¦ÏµyÔGE‚¦)\×EE™“k:.ØŽã´¼C­VËÖŸøln\º&•4A!FƧB¡€8޳÷äÏc*tß÷Q¯×³ç¤ëŸùš¯hКrâëËe”ƒaÚÌ&¸¢Er¹\¶_Hƈ¿a¢P(´È4É$¿]Ÿ+n\h!­™çyÙ}hmhϯ(‚ÂלóÕ<Š t}â=•«Oèçt@/É‚FQ”=ñƒÆÇ“ìpPDû–ô ×-¤×èˆ\÷Ðß“Ð5èóqgkLkHòH×á{ÛŒj§iš½;­ƒëºÙ3qY$=GòÆ{7é>œ/ÄÚ‡d ©TképÓáàƒi®Gè™èçăF£Ñ²çißïInM>ÐïùµÈ.’]¡½•$ r¹\V[N{Ú”iþìd³ˆ¯ªÌ@]‹ìéÏó²f\î,à2Mú™d3—Ë¡1zŽ=Éí »®‹Z­†R©”íIZ[ß÷†a ¡gà€n<ÜAÏhâ²ÅcáZ+ÚÛ˜r°Krëºn‹Ü ðûLwîåû@J™­7}n"ÜA¼o‡;´ÖÙ÷\‡¶ÃÔ”ÍõÇ´w¸£ÊyÄqý#¬Fûš~Ïu,Ç$3¤·ésÜA›,î =g:‡¿Ð~¦ÃäFö·íp}mwiŸr,E¶€Û’Év¸ƒï%î¸seA9Š¢ls8¢=£6ÌÓ>¢É€\Fh L 0V4Ÿ”F£ÑhÐôÎôìPóAèõzý8 LÊØqœLé^\ÞHAñÈ9‰¤h]8ÐæÆ…7øYlòlA†Ù;Ñžä†Þ™jºG†ÏÍÒYº'Ý‹ødF®ˆÏô¬DðÈ=2ÌÁ#?ÄC†yT”GöÍH1FОð}F#sÊÚí{z’iû¾ïg¼áïÇA É4ñ‡÷R¿é÷<fF8¹¾'0Ãd&äkLkÉe›ì ý.MSÔëõl_s#L{d”Þ…žŸ ;V‘$pAïæº.ªÕj&[´_¸£GãEio™ûŒë îlÈç²KòÄm?ÄšøÂïq% e8H㺗þ†ž•~ND¶ƒô$Šà%ë\yàŽpú¼©ß¸ž3¯Å1 Dwp=Z«ÕZÞŸt·«wÐ>13íª*Hwއ;8àã‚Û’SŽ;Â0l ¢ñ,wH¸¬ðLbƒL{¾V«·¯MðL{a"܆a¦ÛI.Mü@Ú[wV0^w>§ýgâ x’Ý wкò*ßÔÃÁq6›¸ƒ>ËmŒ‰;Ȇq{À“&îˆã8ÛÈ \Áu#ñ”ó˜óÅĤ[Í,1ß÷wæŽí/â'É­Ñx¸ƒWl‘Seúår9“¡½ûö—_¹bEƧR©„­[·¾êÌ3 0P? 2)}Î\ÍçŠÔ,ÍâQž¢£kðô®<èï)ÚDQ23eI-½,×ôüÄPú}†èêêÊ‘ +ݗ߃G€ œb­×ë-Ê+BƒÄk2Fx“ƒ%®€àsåC‚60)=Áà`…Ö‰ W,dHòù|‹£ÈÓÓôn¹\.»/_3JÊ×…èÿvέ9ý£w奶<ÒMkó¾dßè½H·ñL™!}ÀyÂè КÕëõ,ËJûØÌ°ñ`íCræé&îàס½H× îàrË«* š¸ÃÌBsÜÁ#ßøsÜA×"ÜÁF$wðŠ’±pç É ‡Í~Î~(!É\årÃõñ|"܆a¦;9î =Fº…ž‘dŠëŽ;xp“—¼r=M{‘ ÈÆÑZŽ…;¸] =Hû€Ö‹Ëwžy€†ö+­ÍX¸ƒg IÞ)Âq/}#=afÌ,Ž;øÚóŒ2Ç$W$sãárHI~HV(h“Ëå2Y¢ç¢¥R©ÅNq4qÏÖ–¨T*YeÊÎŒ™4K$8ˆä‚J‚Ë#.üèº<}Ä÷êÌž3uÅ£Áœñ´àÜ(ñ¬m$2´“pqPÌSïjµZ‹­m‡;ÚõÒкórX^rÆKv¹]¦ìsWWW‹#GòA<¤}L¸Ã¬Ì wpÙ环ã8( --fY7éAn£'ƒ;xewž C’ýâÔ±pÙfÞ.ÀKQ9.o‡;xð’ó…¿ÏJ›Xº]_§¸ƒ÷EQ„Z­–+;rf8à‘I%¥$eÌA=œ¹‰ÌWf´±Í6q2x\ù·k`â÷2ËãxäÒL=òúU<ÉãäJ‡G*ø¦å…+~ÎO³’;6 r@K÷$'‡†Gß)2ozö<dö¸pÌÏÔðr5úŸ+Z¶ˆ'ÜÛç%¤<Û5vˆ 5æéilxĈ×3óh?m\rlIòrß÷Q­V³H/§á›ÌŒöpÅÂ=—mž]àÀ“þȤßscÆ×§90àuîdx37ÐÜòÒž5"€Æ•/1fÊÙ\³îŸ;ß|?òˆWúZ7Úß\æ(bMˆŒ9°¤óHx;m–›pÐÉKpxÊoÍ,9À,5â6€—jqÞóò2Þ¿I×! `FÞÉ s]Ç37횎y).$<3m–×™NÏ ‘­áYn—¸!ç}=fÿï½!}döeÑßð’EÓFò*ÓI%Àj–„s`B^2Å{Ìzžu2#¿Ô d1 w˜Íæ<«cö5‡;8XmWîÇy@2Í{ꦂ;ø3ÑÏ wp'‘ŒxÖ“ 蚸ƒGÎ'‹;Ì!O\GÓ=yð¡îà:“g[ÆÃœ|ÏNwО渃ìß¿¼‚f,ÜÑ®L²î0›ÖÍ&ïgå×3+x@ð#Ý‹•#gøÚñ 9Ljf’W+L„;Ìà‹ùÎwpÝÃõ$ï½åû|,Üaö!rÜaöF !P©T:wfÈÛ嵃¼ñô: ’gÏËÌÈW:ÜÀqÃÀSétMå¦MBÆ“Rtô=oå ¯£¤è%E„M§‰¢\ðy9õó9¦h>wTxT“ Oxi}Ö÷ýìy(M¬µF±Xlá%ï™à ƒp3keŽ5å —fô˜G'LÅmÖòvsÊ%<Åßn¢Ÿ˜GetA \.g f /-2ùÀû„rÃ@Ñn`xÓÏšý¼†—œñìN;§”œ/^ÇK6ÏóA–3§zïÉàñ,í zFnÍú[ŠÔqE÷¥5£†FÞ°O{–ÞݬýçÎ$ÿ ¡ç ½JûÃŒqÆKW¸ræÖ\v©gœ.cöšQZ®ôIŸP¶?ñÌ0ÖT,ÒCô´Æõz=ûŸGÍ)6|h@»é]<óÂË4¹¤½E%o|Oò옙­&Ù¥=À+ÉièhÝ(ËJ<*cä<äŸ!]NzÑÌÒðg ýÆõÏòÞŸÏœG^6ÊydfÌ oô? ¼Ï€Ë;&¸=â%y¼\Ë ¤ña%í¦ÍñÞ4Z^Í5ð@ÏÈð’TªxÄÙ̆s§ŽgŠè÷<ÈÊß‹×úØä2i®‰‰;ÌÒOúžd•ö•YâjâÚ»¤_ÇôHñkÏ(øÊƒ¦f%Ædq/±ã¸ƒÞ¹X,¶d;ø ˜šúŠWkðçä™s€É Ç|-¹Î7{Fͬ"Ãq‡9÷óî @( à\^vÇÛ38îà2M:š˜ÆÂô3Z/ŽÏͶñpo%àƒ{xàŸl/cæAlnGy鵉;¸Ãm:â\ÇñJâÇÈÈHçÎ Ý8‚lªŸ2Ã=DÓÓçŸG~|HâÌàÆ…÷Ÿð†%3zʤˆÙ< KÞ9oJ5?oA˜’aç)_¾ÁÍñ±Ð‚WV˜¸ƒ;§ôì<êÍ{8xÔ˜OVä¾ßøïéóíÆÊóþd>èÆ,_5Gœ›ãpy€Ö|?Ò!ôyÊ ãcâ^¢7îà¶g¬ã8î0ÇsùãFŽ;Ì>&ÏÍLØdp—iÜMÜÁmÉ’ïû™¼šý°|›‹\.—]c"Üaž‘Åí:¯¢Rsw˜#ÆM¹3³_¦4q­!ñ‘쟙¹áÁ<Ž;ø0 ŽÏL™æ¸”WG Oy€Ë£Ô<µÊež’£­ç†’§Q¹³Á˸Ì(œ9¦Ï<[c¬Ñ¿f‰ßü÷æ"¶›ïÎÇÍ™QO3íÎ=O³ÜÆl2ç áº.ÛÎEo7œ+Msj¾NæTæÈ9¨å%\|=ÍRÞ4KBlΤçãHyäÍœ]Λ“ÍÒ ³•;o˜™g9˜ßó5ä‘AÒ¹qä|3ÏâòÌ=®@Ú×`Îtë 4™¥Gæææ5§Ü!6£‘Üa0Œ0ß;d™YGÓÙ73< ÆËY¹¡ãÀׯ›`™Gšâ8ÆÈÈHË;p‡Ñlâç²Íûlx›—K˜ ‘æ9HfÅ<Ë‚÷V™×x*íö—ž æ%Y\¿Ñuød9þÜf¶Œß—÷K¶ãa»Þ/¾WL™æ{†;<“iÌ!Ü)2Ïëi'¯¼”`®£ù>àkÜî< nŸÌ5árjê,sä9×Ѽ4š—ò51u˜i ÛõIsef M§—Ì™ ¥]p‡óÖܧ|L¼YKòÍps¢Ç |T´)fF‰Û)¾&ƒ;ÚMlmw6Ðáǧ„;ÌlÞLàž±æåªÜ¹âÎ7çåx¸ÃÄ cᾞSÅ|(ÅD¸ƒ—ÔšåoôyʶÓwðj”éâ³”œË&_׉p‡9¥]O×#fÃ?_sIJé4p…c2S˜×çÕ íEíp‡Y*oârâK¥Òq£Âù^î„ZœsR¥%yz7Š"ìÚµ ¹\ÝÝÝÇÕµ[²´Ð‰" Z¡ ß€ IDATkôööÚS£Ç )%¶nÝŠ7vtHÖBáÑŽ;°zõêŽNE^(EŽ=Š+VØýfiFÉqlݺTÁbÉ’¥ÎˆŽ'Ù·oòù<–.]z\_s»òì)93TÉK?¨n›GèvíÚ…+Vdã-Y²t<5l<®¥±>^je©=\×ÍÆëZù.FFF²qß–,Í´ž¢»–,YêœJ¥–,Y‚Ý»wc×®]X½zuË5³ì}²”YÇ8޳q’¼†R‰J)ìÞ½K—.Eww·]K–,Y²dÉ’%K–,Mš´ÖX½z5r¹>Ür0ïÉëșᇊñt YË^.—!¥D__ŸNX²dÉ’%K–,Y²d©#‡fåÊ•Ãð¸sq:ñ1\þ oâá£ôâ8Æ‘#G²zdëÌX²4>™ ³–Ææ‘åÓääÈòhbã8Ó²ÔIí¶¥S»þ³EOìý:]Y=™Ïk÷•%¢R©„Z­–(Í)934m€ÎQ 9Ýt¦ÍË·Õ’%K–,Íg@ËGõZšDS¢:m ži‡úT83æô³É<ï© ”ð e–.‘¯aÆÝ±3C3¬ù¡r4ÖŽR´Ó<,Y²dÉÒ|%¥FFF²“¨mov“ã8ÈçóèîîF©Tê ͤÜnýÉp øØß‰œóYO–Scžrožeiá!x ‚ýíØ™Íìæóºù iK–,Y²di>Sš¦ÄöíÛqèÐ!ŒŒŒØ Þ)"~®ÈX€—†­\¹6lȦÿL€ÌÏ#£s£:mdž‰gá¼ëoø³¨<™Ïhðhš…­sé|!~(rGÎ )k:ØŠvC‡½ÙºmK–¦nà,MÍ[²²t*ùÇ1†††°gÏ|ðƒlz¤ÎEðÅÐt]a¶9È÷}”Ëeär9ÄqŒ×¿þõxá…pôèÑ–Ã89(ÖZÁqšSWi:ÒL‚ó‰ð5.ÇqœeòöíÛ‡;wf‡gŸ¬õ]¶lÎ9çäóù1ÿŽŠ‚—Ëe¼øâ‹™ã~2d[®®.œ}öÙX¹r¥ÕoVggýN+3C‡Öxž‡Z­)%<ÏË”4K–,Y²4i&Á•\;v F—\r1ž~+â8ÂûÞ÷>9r[·¾€¶¾€Q<ÖSÑÇø9ýîd9Eë֭Ƕm/cåªUX³f 6œy& Å>ó™ÏbÜW™¡ûO°ˆ€Ö¸ô²ËðžÛoÇ>ðÀŠ+ðÒK/¢V«áÚë®Ãk.ºwßýÑ`«À+»vá¼s.À°xñbDQ”eO& £’-ضmÂ0ĵ×^‹ NÚsÄqŒ­[·âñÇÇ–-[ÚÞ›?«R GŶmÛ°yóf,Y²ä¤òmÿþýxæ™gEÖ®]kqæÖß®ëN«¬e€ã8ˆ¢(v!<ϳ)ö¸€suóNôìsùÝ,Y²´°I)…4‰â<¹sq°"Ðøæ~‰(‰!¥±ôL@“;"š`]Œ–Î …pJ€VÐÐ:š_AJZZAë.´’¾´ÇÒBºÐÒT(@8Z5-·²y%šŽ@AÃl¨ÍŸúPÛ ±öbìMöHñËÏ“.ÄúKš×‹S ç©‚Šb!GBh@ ‘Zh NŽwPF#¬"sLTó¥[ÿV79AŸÆuî}b'~¹õgîþéS¨¥=ËÎÃýÏìÆCÏC§p]9ÏGµp:{¥†\0€¡CùjOÆÉ°Af¿ÉÁƒE®¸âŠ“îL¥iŠõë×ã…^ÀK/½„ .¸à8üÆŸ7 C´¬Á‘yè0†’„L!½<é@„)„T„HsH¢àAjBåWB@Ak!hÑ|&)šÏ'¯é8xtšB¸°¤Œ$PŽ/PQ ×s¤IÓý)§E 7‰‡È !¥†,C$ tœ@8£ÎŠVMgm8 •*–¯:3¢i@ U •Æ£›Ôºé‰æïzCº"Qv{DpS:9†X/‡ã)$”B:%@Ðð{yBE¢tJdPJ‰W^yW]uÕq²y"AºÖq# CÔëu àÉ'ŸÄ¦M›Ú:u„Uêõ:º»»3Gæd -H’Q¡^¯#Š"‹E £««ËBhðÈuÝi•8¶ôÌ !² !P¯×[}\¢;ŽcÔë ärߟV–®•Ï𽱯EFFFÅ1ò¹zzº-&}o­5Êå2â4Å@o7 OÎä–4MQ®TP«ÖªÅB}½½À¨³¢”BµZEµVƒ­Y.ò(ŠmI ²,MF¯X²<šˆxOÃtùÔèüÐ ©¡”€p$$e” e3c"T 8ýîr{‘Æ5È  . J…ÑŒE´J.†#ûû€§‡¡UiBö " Ôb/‚ŒCù€#åÔá T*P~7Tm? õè3J@)9ê†7­hª¡øÑçþñe¿‡w_yf3c|ÞÜH¦‡¦ÇøLåÐËøêîÂÅÿùc¸jm_ëg…€>úþæ/ˆ?þßñº>)»Lœ$Úùxbo~ÏXêjd‰ïq2-œ'ô»(Žqìå_àg¼ýŽ·c‘L³kq§±^¯ãØžçñßûw¼x,„ß} þë_½ýIüjF~œ÷WJC!“_ø¾®ß‹/üéP£‡œŽ÷¼ñ»Ý=[®'Ü‹ûïþ>žÛ±Tpá{¾öB¸¨7(Þ'‚ïÿô9­+x]«ð–ÛnÇ5節Рo“Z²diS¢ÏRŽój&F: €l:2 J€»"†ÐyÀËA‹fM䦎™V‘æÁÓTÜíÕ!ŠDßRàè!(7…Hž@3£¤G³;BBÂN(µÂ_ ©c$õÝ£™—"„P:EÔ^Ö‚tª#ü¦s}"Ÿ…JÌ¢(B†h4ÝïdÎÓ;à­Z‚zµÕ´ˆâ®#>Ò$A#N! ø>r¾×Tˆhf=asÊ#›½<ùÀUxA.@\¯£RõáH|.€”. 5œžUxÛo܈3JÅŠ43 0Bcx{d'6¿ã:,íö!Po„hD1„h2:ð=xŽ%$â(B½ŽòMÀ÷<ôÓGCá+ÿç_Á•ݸìm·bÓÚ^¤ŸÆ½÷þ;×P\¾o½õ\¸ÌÇÑráЋxð‡÷ã×{G ¼"VŸ})Þ¸e÷ýü9|éS!zqýïÃågùéIìüî?àÏ "‡ð¹¿{—}¼ªÕ£»ðäÏÀ#¿Þ‡4ׇÍ×¼7n9q¢0R©¢¶ûIüäÞ‡°}XyÁÅ8=Õ€D:ÆH¥ŠÆÞ'qïü/n kÙ™¸îÖ›±eEqšb׃wâ»[{píÅ~úã‡Q9ã7ñÇï>{Ÿ»üìiìªÁ),Á%×]«/Z·íòjˆâZ\sý9¸÷?ÿ#æb¡+xá™H׿ïºtTœ@\y5Îyäsøùƒ/âÒß<¿ÙȺP`›oÉÒßÄ£ÓÆ”7èÍFx! 4z œ@º Z @È^hGB¨*´§ "@i$pó9Äõ:àHÀI!µ„Ö5HQ‚ŽF”€´ˆY†,öC»â¸=TƒM‡Aóžz4S"²\ ´Ppu#=ÖrNê G†P¾ˆ<œ0‚‚FZ h>»è‚tZEz¸·gªW@Ž4}†ÑLŠ$޵ÆRBC@§:f ´†”£ £Ù—tÔ²èæŒöÏZAHÑ|€®A§{¡åêÑޚâJ@È"DÒd'x$Û”~€ædþ>IÔëõ¬¬X,N8:›;"äÐtâhñ’ŸÉ|®Vk`ûöíˆãg®Û€ž¾Ò„Ÿç<áSÕ¬½\Øä8N&ÈB†Y£(jf F›ÿùltºð„›²™wG­\F-¯ðäw¿ŒGô¥øƒë·ÚƒÁ{€3P*@8¸?x›Þp5®{ë™xì‡wãÛ_Ù ; W¼é&DÛ~†{¾ü-¬=ý÷±¶ QÜŸ|ý«øU}ÞyËíXŒÃxúùÔt3ŠãËcøáWïÅE׿ o;w?~ò½oೋNÇ^½*ª`ß$ Zi(V–ï_‰‹/Þ„gïÞ‹ßøƒ`­£QO€ôÀøügîEéÒ›pó›aÛwáŸþŸÏàýüX¥Žà¾þ2žYôFÜþ¾Mp뇰}ëaÄýãÊמ…çïÁmÿåÃX#4r¥.@7ï)„€çxXwÝûp]ð¯x4ÚŒ÷ßx9|7Àðáí¸ïwâáúz¼ëÖÛ!÷?Ž»¿ü¨ÿ7¯Ë¡qàI|õÞ…¡µ×ãÝo^‰_?ð<°½ y–@£¢¾ûøÂï>÷í¸õ7—à×?þ>ÿן†úëálO!­ a϶§ð}ÿMxχÿE‘‡+êåa,9çr¼vI Gw<†{ïü ]¿Ë×÷·-ùÓºÙÜŸ¤iËXR­5©Q5d)f9]˜8È{ÀÑýÛPÁù(i…o±µ¿–O3ѵ<:y²Ôr ÕìQ €;ú¿ã*…€ åRwA;€H÷C‹"´‚Ë u]@N²o %Ðàj Ü|i: íwA,> Øó24ªÐz2> è·ÙG¢RÄa8:gxÚ÷›!G³Déh‰–l: Bj4ý•óàE tA­]=Ò€8< Ç邪ÇP½tˆÊ ´@†5Èžôð0t±Œ„€W€Ž8AIwqlÚiºKH›uv"×U ’:à )$Í{S¢9`Ô^P£gÚI ¤dŸuÓáQé¨?) ”€Nê€Þ é­†j$Т ˆn(=ˆ+YYÝLŸj?^ÏÌL܃šâ«Õ*öí?€j­†\ÃêU+Ð××—UÍLäLôì3Å¥€G_úWÜ·í£HtˆMÑí¸ù¢ÏÀóÝŽõœµ WoSFf²•`c:3J)AM¢¢F`ò'ÃêQÅU?º?øxÊ»ÿÛïÝŒE2¡QP<::Ò‹7]†;n{ ¼Z]ú0>÷¥ðÛy;¶,ÏáÈê<^yùŸðÄþ ÖœæáÐöçðì‘åøãO}ë ÍçÚ´hÔëØ'T¤qÎ{>‚ߺx*ÕaÈýÛð¥_¼€ú›N£Á”HãåJˆxôа|>ÇñP(ä!¤E‹1 b:¶}÷>Ôμ }ßµpª5¬ZþA¤ÿø÷xôÑ]8ã’{‡R¬¹f3V/@©ë lzm€J¹Œ½ùõ£_Å(Wë®D€‚ 9dÀëêGwÎ…ïtañ’%ˆ‡âåíÏᙃøðŸÜ†õúºåwã wýoúã×c÷sÏaw>ùŸoD¯ÎXâààžÏa§ÒPº†—~ Çúߌ¿ûÈ (h`ÝŠ<?õi|ïß_ÀÙïZ Wh¹7|è7pVA#‰Œ”ËXyÞP:rÃÕ¥¥pîÊÝxtû~l9­ zJ5£C…B®ãŒ}¢‚ ý8cU/|âx|×Xᦨì{/¹¥ $v·%K–æI¤Ð®h&;¤€z´^à z¡£nHå@»C€ò ÝÅ€Ó,SºÇí†É‘W „(Tã àvCT#hìj:E @ªbá6½þœ¦Ðµ”댿 8šB¸Ð2mNZ FË‘kÄ5@–`Ç®S@¦BATb¸Ý¥¦Ýw%¤/P# \¸i ÝßÔëH«#i"× = cƒÐb4ÙR肎C8¥~ |IRƒã¸pPÐŽ„NGÂQÍÒ7­À¸Ði2ê{ÉQ'¦éÔ(¥!¥RháÂqb¤éÀÍCÈú€Ó-RÀ)ÏšÄÌTzfÛ_y¿zêY<üäó8p´Œ(MáH‰Å=%l¹à,¼áÒ×bÝÚÓÇÊ:nªO£ÑÀÎ#~]`P=Žzz®^>i¾X§Å’Ö:›zK§åÌÐÝ0 ›À4Ž›l61 ¸N|÷ë¨ ¼ÿø­Xî*4ÂãVÃÁ¢žÅÈ LbH§€ÞåK1sÅ ”pÊõR¸: qÆ9Xæ)¤É«™Šâ(§g/É!MĉF1çÁÊ©>MctlÛ}øî¯@o ÞüÞ·déJi(¡€Æ¼<(ý"¾ñO;‘¤Íç®%ðŽìƒÛw ®Ûëðíÿ>ýó^,]¾\r.\ß—éQ¥€Ti¨‘­¸û;£šjH”pé7`u¡™ÐZ!M›)á‘á£h¨ øÆWðhN6SƒÇîzGÒ+184„Ò9—¡[+ÄqŠØ[„³ú=l ’:öÖзé<Dq„P.Áy«||ïvTôz Vã´ Ò0ÄÈÐa<ß¿áWû/]GÇ8t¬‚Z5Dª4¾x/~üó=p¹ÜZÜôЯbŒ•ÀöÜ"6½å\vàKøÒ?|Våpìh=‹=ÄNWHíæµdÉÒÜ G5õµÄh=!]· ¨küÿì½y°eÙUæ÷[kŸsîøæœ³²†¬yPMªÒŒ$-$È€˜¨™ì€6&°›ðí°Ãv·Ûv;pÛ†¦mZt£7`54H¢%PH€fQRI*I%U©*³*Ç7ßᜳ÷^þãÜsëæ«œóeUfÖ]ï½|ïžsî¾{XÓ÷}$=ŒZ.Ü  „”è<®™|终õ‰â¨ˆºŽŒ€ñÈìl¹vH“è}Åþ¨·]Ñj¡ÖEÊMBÑMˆ„ª#ޣшIÕZVU Z$š'ZmEðŽEb# ¹G%…ÍÒÉPï±^vœW¢8¿Ž´ÛP´°"‡|.!YØ_>kt+ Šï­Bkž¤oD?À¢p™UKšHu6*$VÕ+5,ô æUÆbÅpFÕégeÀ¢GÕƒ¡¶N´€Ù,ס½¿ª€Å•Nƒô"…I !ÐnµØØØä÷ÿÇùØg¾„ªG-XªJoPðijÃ_}ê ¼ã;_Ç;ßú¤Yãyía—ÈœëY+Œ„hB–)f\¢´g!kB³™Œ±.NST>äg¬ºL™©Õ±G%€[I” ‡ÃKÇÌÄÉ󜙙™qÉ3MSʲßôìB‰`2ÇCo¸‡ÏÿÕçøÓ¿x€Ÿú®;+zÅçí0Uù»nU:­Vò¨½6MS\’Cò¢$MdÔ«Œ1†55ç)W±‰ I–±sßmÜÿÀ’(¢ ´ʊòÚt!Ë$fÌÞx7¯¼oÂWíuòÊW³¸û‰WîøÎæ?Å'Žæï>þþàw¾ÌÚÏý*wi•3³±3·—{î½A4„K3MƒS>È4KI“„t~÷?ø­T«Sâuo›c·Oº|Iˆ‘rôÙĘÞ%)ê~Ð#Ä’"/(‹ Išh=êÆÃ¢‘o<É'¿2à;~æyðºË'žá³xšO#Ë2ö\w;÷?°£ÊÔ%K4Xk˜ V÷»VáéâíüÀÏý*¯?z„ÃËCÚó_ÿ½ßâ»n¥ /‰³iïïÔ¦vd ‰DbEùëbðÕ9—ÎKA: ¨kb~ƒ‡8™'ZAÌ $zâì]0<Ã5ðmÔ cyTÊ‹¶qé,Âp½ªT¨«â“ÄU;f4di”öѤ‹&)e¾Vµ™…iZ;*#ï¿j ŽÔéˆ B¾ALæ‰Îp¾îÛªÄÃ' Ρ…#ªÇº»e/zøþä:¡ÑEʈ5’Glsšó„~]œ#ö Òî>Ê•'Ь‰Ù|…yn>Ç0æL ÁB‰¸,Cü ĵGÌmŠŠH ª+ÕŠÄÀ ‰FpŠ£1×Å6¿¦m‚v®˜Sfk‹èÖ€Á—%GåŸýo{ó·óú‡îçÓ>ÎFoÀ-7ìgß®¬¬mðÕ'žÆ,²¼Ñç½ÿþÜXYç?ýñÿ¤Ò.:Í=.&H˜¤6ßÜÔ?þâ3ÿ'Ïlü ¯»íW¸ó†×¡c¬¨TdÃç_ü}úÅq^{ï1;3Ö`fÔL  ×ë133C§Óaeeå⃙#eY’¦)yž£ª§ô°Ḭ́»üA~ù¶ÿÈ?ûÿÿ®ùÓ|ÏÃ7ŒˆO‰T&ðc}˜QÉÜFF€$mpÝuiýÕ'øäã÷qÿÎ6†Ñjup‰1¶lÉ,0qC{.Øê쾓×î¾sü(yQÐK3Ô†œ\Yf_7%½Žûolñþ'NÐ}Û}tG=½i–Òh¶Ù\[f0(p‰£½°Ÿ×¾íïqè~/Oɹ·™!qÀÉåvµ”´±‹—¿zï)¸£••Á)Ïš¦û®»‰æG?CœÝÉí*+#ÐîÌâ\äúëö2øè—yòÄíÌI¤XyšÇŽ—èuÐì,rËüõ§?ÎÞ¸‡¥è±þ׸䓯Žï¾›£ÛL] Ç¡è÷6é¯äèÓ‡ñó‚ª2³ç.^·ï¹-†’^¯ÏæÆ›½ÞŒ¢¿ÉÆú:v 67Ö sÒî"Ú†â||u–ïÓ=$ÑS¼6­+çpö¤ƒ\qãu¥ÓtŒ®Þ1ÚVÌ %Œ„!¢:…ñ‚3Å´ ±OðD;˜­ 6D°§ 7J—a²‚†Ñ ³XÅ"¸à kÏ"Î!š@ˆÕN=š¦Èü¡ïÑn 2‡mn 2ƒ Pö+GÔ{@+É/_u!XêP-–$9€Ò;‰Û5‹­['6q=’Í'„A¨ Îñ«‡½!Úì"Ã>ÁM³ŠØ µ“X®Jòz IDATÁL ëG4ø|fö{ËÄÁ \cIf‰qˆXNÔªH’Î`:ç¡ R"Ù,æ7*I…^©¦u³Ql!"è"É.¬4(O0ùñ¿˜™³iÐLþ\–%++«|úï¾Àû?ò·<ñÌ2·ßqo}Ó·±‘{î¼ùî¼åb¬XéN®®ñëÿæùè'ÿãƒóYn9x=oþ¶W]Ôº8טœî™½÷üÙ'þ7>wò“5áCßú,{ç!M3lÄé¼'‘&þì¯ó±gÿ!ÎÁ3Ÿù0?ñm¿Gš4/hœ/&3?µ«×_*Ë’f³ÉÆÆÝn÷¢Öì)ÔÌI’Œ«0ªJš¦çdј| v«D;ïýA~á'”ñÿ¾•áwÍ“âÉMhw:4ÄSŽZŽ’$¥ÕL >T…|ZÍ µ€·ê÷îyo~í7ùÓß}/_9xóiÎòð:~ð'ßB·Õ@B¨õËHÓŒv¥¸$¡ÝJ±0Ò|Ù²Pœ:vÜp 7íúöûÿßÚ¿ƒ;z-¯þñwóÄoþ>¿ý뇹qÿJòÜsËk~„×x’õÛDvïf¡“Qž|‚ãûîåGØÅÎÍ;¸añóüÉûþ˜Ç÷íàþ×¼–›wÍœ2NFF–e?Ž‹”ëîzo{í7ù“ßý×|þú=Ì4Àožd}ñmüヌÛ^ùm¼ê±÷òÞ÷ý¯ºs'‡¿ÉÀ÷)ƒâhrÿ›ßÂWÿÿê7—;o˜eõÉÇü~î-×áü€Vb”¥Õ ¤‰caÏÝ<°ûã|ìCdóÖ¬~Œ'7‡B<åÙÅÖùì‡?ÄS›9Òc³ÿ×üщ/³ãö·òö× =úeÞûo>…tš$åO/y臉ïÜ eùÒȾ¼ÐNÞÙ²igz¶­šR×z5ir,ê÷~¦C}kº›—BÅí|çÒKfŒœ‚  ÁƒÛUU<Ðìû†ú LœÌaÉB â&’Í`ýi(ΰ0À$·O¡ŠÆ8Ñ';™V„6Š!ÎA«E±: ,IAAÈh«ƒ„¼ræGœž†ŽXE¥†Ü•ªåL*  9±.ÍW #™Mð'ÖˆekÍ`}õhÚ$%i7ÅC¬0$Ií£­x‰¹‚lâBi.t•èûhHpÝÄ|-•F‚Ð!¦³0Üf1NàÒ½D€tL1‹¨:Ì&Š:A£T¬p"ˆw˜öfmH³+rM™EQpôØ1¾ø•¯ó—Ÿø>~¨’báó_þ/¿çv~à-o „HY>Çú9?Ûå¿ù?ÅïìûsÞ÷'ÿ‘<÷¼ÿ/>ÎýwÜÊŽ¥…Ó&Ð.68m`fÊß>ò~>¿üOèÌ9š]C¬GÒ°qwT­—fÊñòS´;ÐðçŸÿoyûƒÿ ¨?ïÊÌ”šù¥eµÈl–e}Žœ̈ι±ë…Pó;¯ç»Þõ.fwÏ 7¼üíüâüAžè7™™[âUoÿQü޽t[mî~˻ٕ݄ Mvßxïú¡ƒìj;T¡9³‹7|ïRîY hc‰7¼ó=Ü|ÿã:¾I„vßÄ®f‚쾑·þð1¿«] iÆÞ—¿™Ÿ>ÐdFÙw'ïüñ9®ë¸1“Ùs‹;ïâÇÞó3|ý©c BJ·™-ÜËOþÒnÿÚ“œÜ,ÀeÌîØË×ÏÓJîæ‡~´É‘å †eÄÝõ o»õ.®Ÿ ”ûyÏÏtxüÐI±A+KOY˜"B³ÙâÖ‡ßA»¬0CH6Çkßñ“Ütï7yúØ*¥)Îûo<ˆ†H2{xÏÆc_ýËCØóÚ·óúW<Ä·¸ˆ¤‹wñã?ÿ‹|íëO²Ü d¾[(\ÂÞ‡¿—Ÿ>Ðbƪ#ODhÏìá­ïùy¾þµo±ž»^ýý¼úÛœdgE–yš ¦Ýžåàmw°à#<ø Ä"!²¥.N…Îî{yûww8¾‘cI“7¸•;,à·ðÞOmû«?“•Óó©ÌÔ«õú¿Ö›­ÌdÖ/„3k"Ô Äz,¶þ»ÖœöÉùs¦LîÙæÒÖ±¹¦æRX ˆ¹ŠnÙç àfÐ0‡É :”nÑ.”h)VnV*õÅ‹‘o±Òg *zå0)(ihšbÍX†â«Ö¯£Ë¸FJÚj‹ ˜ë×6À$I0"ˆÃB%ji£¦¢pŽÔ=A±ðȱ5XšA£aËBÕþ•o Y´åC´ aÇ È‘eÄ ’UíÒ^ºöõ§Ìˈ1Ĥƒê&”ë£Dbˆ7ÆõºuuD:»¸û¡Ý¿ÛÇ. –•c&í]ÜùÀäï=…Ǿ»xå~Á|9®¼ˆÍÙ}Ü÷Šý§<ßþ³80&mîxø•§Ý|ÌHf9xσÜ<ñûi syÏÉÖÏ­m §ïF23Ös(ã‘0=ÓqòâZpD'ÇàLãt¶ŠÃäøÖcR;ëõ÷“ÁÎÕ>—jMŠÓÕéÇÈ¡â0J*b3,n.]íŽJEÖÀPTÁVј`Ì@ªX!øìâ2˜¹úÏ¢yé±8aˆIRUP‚]…ýpÞ@ÄÆ:Åf†$™YÀ¯¯“d‚tæIÊuÌ)å ¢.!Ø&ÒHq¹`Ý6q½W WZMVUht„ 2âô´Q7€JÕºul™¨:¢Aµ6˜‡›È°[˜…Ò°Á—h!•µk <{¼ªõK=RšÍá} 1Gµ‰Ù&ÒØQµí…§eÕ¢G «@¬$û`;æ"qý̹‘(§!aÔ] €¯tÖA’=Pl‚•\) [“Y#ãï¿ëûyõC/çŸÿÎpre}Ü^byË«,-Ì1 ÉÒ”ï|ÅÝ<úͧ(û%ŸûÒ×xÙ7?/hº˜ æŒmh¦<~ô#ôíI:3Ž€çUû~™»w¼‡ÕÕͪåoŒ¨H&ö.ÜËwÝôüõúU‹')øÚêû¸mßëÏX•™LöNí¥gι1Fÿb5‡ÆÁL ô/ŠbL•VOì²,ŸwÀqQlk2 çÌš>PÙY¯u¶,áóþÖìâ¬sŠHmùû:8ÃãŸCoÇÎIÚu¶¬ðY^ÅÙ߯Y~Æg:×5/ô™.§9 ¶3ˆÙ*86yÕÕÕšDµRxäüOϘkÌá4ãm7ÿk̾‘ÒÇkcÒaŸtà/wÕärôµŸnœ¶-5díˆ×ïwkÐS'zêñß:N—ó¾ø«ó™Kõ{ªç‘snü¾­Œc½/ðò½ÿ€ýóÔÇ'+4“óè…pT¶+;=þ* ŠÃâ1tˆ,!’¢&ø¸ŽÚ<–X”%¬|¢`Y‚õã×å8‡˜i%i‘ˆÄáF´ÆˆCG‰>i/‡C\Ò¿õ@æ—ˆ½UÄ^¤®×í%>y¨í/Í!ËȨÒoÑÅ|D“ª"#¤#&ÍÑ{1cgÒÀÌã\Bð%²ºJlwÐCëKBœe9ê;¸aA©9S|qI¬\_àó¢jÉ3ˆÅ \Òu˜Bqœàvãt‹«Dk I³·ûe„£!eŠ›Ùßá‰bõ|qD-jU5K@ØÄt|V½ÿ-øv¬óÑ™9û}„V#ã•÷ÞÁ«î½ƒ÷äoh¸ Ue³×ãË?Éë_q[/Q3™·ßrsí&Å0ç[Ï}k|çðÅŒI¿?àhÿ3¤Í€Ë"ít÷íùYB°QP!±Q õ-wßð&¾òÈ9n‰Šãxþ žÓO˜Üg§öÒñ“¼÷§tD\f¦¢§ã¨^@"B–eÓˆyjS»@Û®53™H¨ëúûÚÙL’dÄlÝ D”A~'PÄ Š2"G,œÑùŸÌ¶_éëÿLªÒ“Á‡snaN_Æ1ÿ—Uõläžé9'÷Ýi2ô¥ë+ÕAÍÅØ8˜)Š‚f³9ͬàù¶˜MmjS»|ÎgÄÔŽ¢ªÒh4ÆÕ…³e»aPžem!ÒNvV-Ž½Ñ“Îk}¿3½¯4gaku þ9MÓñ6ùì³aNV½¶6“íUWËM­Y–ÀœmŒ|Ì+ñÇ3Ügr.m *¯º6Æ0ˆH‹+¨sD·Å%ÄU,YÀ$ÅY ³q»±òq4ÛX‰ds˜&Äb³jG³ c€ê(»Ñjµj‚ N`í\³C®cå&ÂÒh#RVZ4‰axºÇÔX’Î,Pl®R-Dõmè(€ÇªoGUœú«iõÛsRÉž@IÒl“Œ0ÌÖ›'&©áR!®Ð2œ^A²€õ×Fín•ȘÅâÚHÖA­‚²BH’U$Î@l`›'ˆi 눛E$!ø 4[C¤7q{°<å* É. àJØXŒõ4F}…EQòêûïæ5Üà ÏO»æœSPÇïý‡³ø±O³Þ«´{v,ÎÒʶõ̸Խ¢z^#ÊMª¹‘jÌUíÊ ÷_ÿNöí¼(=öt^ Q+²ñ-,¸*˜Ù’<Ú®çÚµc!„qGØÅœ úÜ‚q”eyJæ®®È\J´4µ©Míâ•Úé,Ëï=Þû1P®Ýn“eÙy&”¾?ñܵfºT9SgpÚ“$cç&«AÛµl‡#;èm#U¥ÛíÒl6O©Älg&É9WU·F]çC_ÿb21Æñø”e9øÚí6ívû‚’V"'éù0£ªa}HM¶ì]gJ2¢ý醙AðˈÛq“ ›¨K1}Ŧéõ…X.†‘ÌÍã’.2b03ŒüXŽ Z$†ÑüQÞ ÌJb2‡¦mbbýc˜KPqâšhÒB}•ŒX nqXú‰Þ„+À¶Åêž1ŒÚÀh±ª4ÀGÔѣ߹Ù±•U‘fJtÄRGÌ„Ù&rl_ +£ (Vš7U)ŠX®ca€÷9V¤»DèîícÁ£nÂ*g &Äò£@¨À˜¯‚Åä&¬8Itb‚°@Ö¹ÒT3·V<²¬Á®¥9T•ÃGNÐ qNé´š§Å’ˆ(ì§ÝÊxöÄ*eˆ8§lôúzæðx-o—nËä5’$¡Û܉j•¤éÏ—»Z±·õFM|ð£=¹d¥÷4>Ž*´1Ž’gL5f¦vZ«ýºâ"¶êÊ&³:¨ !ཧÑhœ6Ë0µ©Míü³rúºÚ­3ÛªJ«ÕW.äÚƒòÄsíÕÍdiäTÚ9Ñ­Žçv°Ï\*ff«“>‰×h6›cm¬b¿ª›ÉJÖv1ô\ ffòµuŽv|’$¡Ñh\\[ÇHÇËb&?_«Çhë³mÇ8mAoÛº h­0'*®zÿáš*"rœH ñC³ó+КDžf9!É{àÚ]p†9¸ŠjX¢UÌc„Quð!®ÂÚû‰I)£ní§hÏ 1z=’™ELw}¯jµ²&q~ÙX#„rT}Ñç2±"qZáL±ªâHE""îÆ@æ:„˜x¬YâÒap¼ªÅYH»¸áI·…䄵“èH¤Yb-"]µ*Yéq9D6ÜDÔ]B*¦·¢‡ÐBD±°îRž݉Ú:–$Ÿ­ZçôiT÷c†ÅcP¦Û¶ŸïuÎ5ïNÇvóõûøÈg¾„KøÁ¿âïÿÀwŸžœhôú‹s,-̳ºQiÔ%>õÈc|î‹ñŽ7½†w¿ó­g¥U?_™­Ûl6Ùѽ“g6ÿ„åäðQ¯<ÊÍ;¿}$†þüûÅh_>Äá¿Å-)‘@']aµâ9ƒ™©ŸùÒó“ês»>K/©2S̼÷ãW92›S›ÚÔN¿°kÇ|2ɲŒv»=ÖG¹0GOé—Ç©›Lœ@¦]ηcȽ€ÚKu*ê1ªtç­Vë¼µ±.G@³NõvA“™º}¸ÙlŽŽ‹±@Q¿é ?p&æÑ•0—Î)hÕne£ê¢Äàˆá$âŽ@Ú©µ´Ìß„KRÄ)âû %Ñí¬ÆÊ ú>’vq¢H £`¢&ŸÐ1u2N ¸ ÁBs&‘2m E‰¨GT)6W!uXÖEðX,2ÂÜ"Nk…öª#Œ­ª.¸ªÅÍ0¢ÔBÕ†¨!bX·‰’Ì5‘fŠ&à7 ’c%4kC)6@ºä½> Ö*à¿DDGû‡«ÔáM7³ V,ÃÖ×'Qi-™…¸ŽÅ5 …d*}Ì5¡ÜÄ5Úà2œîE]Ñ#UûáŠÝ×'×äƒ/»‹½K diŸôS|쓟Cåù뺅uanŽë÷ì¯þ0g¶ÛæÛ^ù/¿ï²4{^‚èbŸoòµI"ìm½fÚC>úÍijǟ Û"„Y9¥ŽÞf?úOȤ‰R¸}Ç!hÕ^9 T¦v–„`y‘ì·Z_(„À`0 ,ËS˜jª´©Mmj/L ³ÓÐjµÆbRkƒòÄ(”1šéì[ÌζÙlѼ‡ÒdÕj²ÚÐh4h6›/:¾ïJ§I§©ŸÉÊ^Ýòuñ×(¯ç1IPÿ|Å:8!bÁˆ!VˆÑ£+Ö²rƒè7Ð$ƒrX‰@Z‰Å’”{@‰£ƒ³.ªBÌxÍÖC¥í9½™‘+Œ[Œˆ ¶~¤bKÛhðèR[Ü…¥à±¢¢újtQ_{˰ÑCæf‰ÑF”ü5™aÑWÿ‚'ú²j«ÛˈDŸ#i‹ÄÚ(%±ÛDºM,ä„¡ûñ9.™E|¿ªF­—a¡Ä‚a>T¸ «ª¦®±“˜ ¾ÿä}¬,¡ÑÀ†3ø¼À4Áü€¯`QÀv`&(+˜)æ$³b+׉^AR yÅìåg«:ìÙ½“WÝw¼(øí?üÿþƒÅêÊ210£È‡:ô4_xôK4·Ý¸Ÿ¢,æo~ÝÃü÷¿ü3üò{~ˆûï¼…b$v¾Ý¬>”ÜzÝ«h®½q±„~ú(øæOð©/~Ÿ ”_ÀãO<Ê~úçybóéÌ$x<»Ú7sÇÒ»ð¡WrÏ·R4µ—†Õ„cuåb,©'S³ÙgêÃ¥>ô¦S›Ú ï¤ãjÌ%9ØÀ T˜ÑJ.ÉY~6N^°1Úê¤×{Wš¦WÌg¹u<^ȪöéZËêö·K©ÆlQãv¨m§ú̹â:Òð®*3T•­* "ŠÙz…+I+ö²Ø"FE¡ªZ‰ÉŽªºB‰“MvÂð(®½@È×0Q7ºŒQÓq;Ÿ&†+Xjˆ¤ÐËW"BEñœxÔIÝn¼é`©á{›hêpÍ~£Â“(Z1›© ½Á˜ ŽZÐ ÅÊ TZKáä K°Š) ÝÄm¬ÑǵoÀžf 4»ˆ(‡ãö2¢¡3{‰ý€Ù šíAbÓÒS4 XØ„²f@ƒ]Oš:Šr•æô$¤s¸æmÄ•O!Á¡ÚÄÛq’¤‰4o$øÀ®È½}ÒaW~ä{ÿ_þæ!ž8ô,«ë›üË?úýô¸íú]´›ýœ/~ý)Vû9ÿã/uyÍËïã³_ù&?ðÖ7rçÁ 1Œ+¯Û…C9ýëK~ð¿Æ¿ü»O"ͧpš°é¾Ì_ÿ>ùÔÃì龊DÛø2Ï>Bpt—„´ À[nþ-”E>ïWEuvj—Ýê¸cR梂¨p2FcÜjV_xü? §6µ ?Î÷oë¶©ú5­Vk[²ÖEèó]7ý&oºñÿ ÷+”±OˆÅ¶9î‹ ºÐqšÄÕ¯IÓôEi+»Üãs)sikEFDhµZÛæ4ܲð}•vÑ6Ï¡K«IªímÅÌø’ØJÐhÝNªÐÀ*ìGÙH!Πä¤&ecçÛUÅF„)Éæðƒ§qÙÑ—ÐèÂ`«ÙÌ̪„ŠEF$‚­¯"ó;°~ˆ±&e…_)e8ŠÍ,âë„èAnfò $k e‰…€èHX³ÆëŒÀÜõgàÌQ4wC?G:"®aHh}?ÈdÉšhaX'~‰4ffHÞÃÄA{‰8(‘°¾$Ñ KÛàûà†DJ$é`æÀ6Aö#Êb€J—H){ÄÁç˜b^ òiº›PÐ_’ZÈõÌÎùö®ÁÉ{lM<-Àh6üÓøóü×ÿëoñø·ã}ä+Oæ+O®‚M³ªEø·þQ~å§ßÅ?úÅŸÄ Š²8ë}žc‰çôãÎôzÃH“&ïºçøÓoþ0›áI’D‘®§§ãK½B5½³Y¥Û\Ó¸6o¹ñרÓ~ ƒa?uêg¾4}¥º£áb;ÁtëaPŸ/¿f½©3 S›ÚÔ.OÀ3é|ÖÕ†íËR e`i¸yºÙþ«rœ&i~kÇ+©"s®Mú…£z>Õ™í´h%ÁŠm}î+Ö‚Œ¿$‚÷˜ ¦‚Å’Áp„Ks  Å(*½Sð‘B?G,Ãòe‚Í¢Ã5gª¯z4,ÆÑµ+m•j¯üÚñ [âCd~'¤)!‚ækX1ÀÑ$Iæñ'Ÿ%äI3,Í*³P½§8º‡ÄªÅÍF-NFÅB† qp‰UîS\Ä’Œ°´†Jƈ氰T4>ÇlÉvA{7=(׉–¢É.BRŠ>‡Hæ mB9b22E¬$úMDDZíÞ{'¯¼ÿnD”¢xNØ|ëu϶Ž.uÿ‰YlÝÎÛoù·Ü:ÿƒ˜ Q<­a~§cq·c~—МH#°§ûo»åÿæöÅe˜÷/ Ï3µkßêÖã<Ï/º唿iïý˜)É9GQcV )ÀÔ¦vùÐ:¹<­›ÐvwaÔÉË}HMb‰Ò4½dÑ ùùž~ËvÝk#S3–]M‡Úåð¨TÙq ³`:t$VˆDP 4E³¬ÂÊØ 28„šÇdˆ…’î†bdMv¡Í]Pn`j„Ø i;¬¿‚ D q2n3«õhÔ š¢e²6±ÙÀ‹G\ÅH&I“Pl ®…º6e¹TÌd2²†tºÄAŸè­Òz©‘ R‘…0¢h®¸*2€˜Ÿ$4›¸fíˆ_ÁÊË´ -›ÛDO‹Xl@»³HnR,Gu/Òâp§ ˜ÛÄ’4¯Cz_ÅHׄ¸ŠºEb\E×W$ ›ŠfEbÀ!$µJÇÄ Â2êv¸²¨™ÏU…¨o~Ýüîå÷räÄ2+ë›xïIÓ„¥¹Yvï\¤ÕÈFgÄ郂­‚Á—Úfvºì¸%sÙ­|û_ãž?ÅçýsžÚø0ÞFDQ {Ú/ãÁ½¿ÀÁ…·ãB—Á`ø<Ö³3‰öNí¥k“¬¤‹›9%˜É²Œr$K’d|(Ö}lÓI7µ©ŸCv>äé1¯ô¶©Ó½‡Ëí„Nxµ“~µ2“ï¡ú.à}«ƒPéYdWÞq2ivÅT…ŠªJ¢†˜BQ¢Î!‰b>TÕÍÐdap‹)¢Kø´HHÕyBq¬íTD¾‰ÑCB)‡ø¡I+zˆS¬¬*?RqÚVme¢H0$k‰Ø°…Ë€ÃOAk¡bó‚5:øþ ZnB¶ÒˆĤŀk6ÐÁÂHàP+ j3¤n¬Mce º #å}Ìå0f\ IDAT’vˆ«C|Ü`I1IJMèo ¾A´!I+ÁŠuYÔ2‚Û‹6:Ä|\ÂÎì?†XŠˆ‡Á1"‘‡¸ÇD1]C’.u”…ád'f‡¢û4%Š}M º&2?O²r˜ \³¼ÂÉઊ‰ & Òh³Eâ`™, „|ë8ð$¾…4º„|lˆ¤‹D-‘à‰€–`Q I³jË ® ØF´Æ2ÖŸDkz€Jh“bO„™Y\hM¤XEÜ I ¡ì â‘bsÑË„lÕN¢dHžcYV 2œ„Ì`pSELÀV =ÏO 1EÓæŸa$Gÿœ(¨XýÁº3~–— œ k²uÿ»X\à¥&2¶®3íÏÄ(v>{ Ī£ÏšL2Èõ)â¬É¼ÉäÝÖg½ªu§¶­ €·±mÙɤVgëROýõ„»ùæ›§“ljS;,C¯×;ïC¨^S5ÇÕø~k§»Þ/¶s£ÛªH}± Á/öÕAßvØÏW —«2à›´ÉsçE=hc$†ˆºÝ›Ú}H¨ZÈè‚ÍW˜–p ÀŽÊ=s ˘%Z9Ì6\E“ˆbdÐç¼YCÒ¡8‰FÙRF«D'›sˆÎ`ƒ>=a°‚¶:„¢ˆC,¡ìÂb$Ɉ©¡1ƒP"V »(¢â–ÓVD$ À b‘ˆTx #Æ6©(¤n@pÝPIØÇÓ@\À¬@ƒ¢¥BÜ7N`æQ×!”Øì^,?Œ– F—8üVE~ ‚ÅŠ&ÚÂ2’î@œÇò#Ôˆø K$•hgåìE_ç§ 2êšËeeYaijœóù¬›ÚiÜZÑ©‰h.—…(Š‚¢(Æã²µÂ?µ—–%IB–ec,ìE3"Bžç8çh6›c6³<ÏOéMŸ¶™Mmjçw k1N õ¾š)ÐëjÀdp³]NúdïJüŸÏ8mw ÕÖÌìÕ†“9Ó\ºZÍD#Îí†)ârÄU‚Ž’t±¸‹à‡˜®áÜ,B—(F!®lƒ,£ÌÅcÚÉ0¿¦ 8±”@8Að °!®5GÌ¡n±u¢J¥k“vA:ªk˜v‘Æ"^‡h mòpŒDg+‚€Ì¡EÕä²6Á ßÛ m´‰¡EŠk)AØÜÔ¤ôômjœaȈa Q4ô(ògiÎì!ækÄáI4]$ZR „¸¹‚S¡Œ}Ä„´±DY.£ÖF9žeB4þiÄFÉ QAÄUx‹òhÅôfUK«ŠQ¨Qˆ#6­ƒ–y²5rrÝ…(Ë’ápHY–—Ū÷Èú>õ½ÎÐl¥D¯¯S–%yž“çùe#}ªÏ»úYë€fêW¾´mòŒŸÔ »à`¦Æ)m õ¡2µ©MíÂ7îs9 u&ýj¬6œî=mwF½¾V]•¹Ú÷¢º:³]ã´µ*S‹_íó¨~//n?½a~‰˜8LJTûX\Â4bÌ‘„&‘e,®!²‹`œ…5pJ”2{~ãIDÓü®Qd²Vô ÁáJmbš‡'$#–¾R¼=4™7”%!.“¤s˜t‰lâ‚'xe×Z"”+ˆë`¥@éq!f-$4qyNäH™ iABéÐF‹0èDÔB,Á¥¢†®>ká$¾‡ß<éæ õ}T#&-¬bRDª ÈíÂbD‡Äþ—)ÄóÏ"#ÒJÿˆ‰Õ·&£Š‹€‚hh¬È ž |_œýaR6MÓqe~8Òï÷‡—%@˜lÑ)ŠbÌÔÏq&«×–ªâ½Ç{OY– ƒ±xúåª$yï)Šb8Mî‰ç:7§vmZ]­k·Û ƒ‹š{Éä!ÛjµÆÎUY–t:qÙqò™ÚÔ¦vñÍÖ²~}^ík+„0>ÎÅ®~ò­Ì7u0s-ì?õg~¾AïÙöÞ­Õ«Ú¹æR¼^Þ`»03u0)Âàd Q‡EPÁ¬‡D“˜‡hD¿‚è cUñ(rœ6|‰¹Ë#´ÛhÚ„þ’1*¢!ôÐqZQ<mƒ.Àp•HAêæ‰1—£EIuÈÎ9â±e\g+"”9ârtf'Áç°9€¢ ¡À\(¾ÑÔ!Ú iEB´b4­p+qDƒ+R‚0 ÀU±Ö+æ³t)"Ñ/ƒ5±¤YálJCu )— å:êºÕóº.6ÌgÑ ]³X5†Œp<‚`¡j'3?ÂôŒôWÃų£çØ^™­ëmÏž=<úè£Ü}÷ÝEÁææ&ý~ÿ²T ¶Rû—e9†ìÝ»÷ŒÏ^ûy­V‹§žzŠ^¯7f666ÆAÆå8ë¶»:€èt:´Ûí)…óKØGB]@I¶²išŽ¿ÖA̵5žÚÔ®´\/â<­dXj&ÄK±­ÎȵP•™ÜgëL乯éBXñTõšÙ«'™ë^¼$š€¬Tíª-¬ô#€þ:Z˜ß%³_Ahƒlc‚S%‚´ˆåÓ#hœÁÒ6:X&ö@Ò&æWÀ-"^‰AÝfŽ˜T@|u À*Ñ ‰Ðh‚õ°A€¬‹º’@‰†€f‚š„$Á¼‡XA}u-bps]¤=‹8„fm$iB<±"@v®ÒÑqÑ”=Å¢ ñë ZkÚ+ˆ’C, zÔíÁŠeŒu4ÙGÔÕ±ï!-/D‹hU–hØX$tT¹Vj>‚*@Q0  QFbž‘s{˜l׺å–[øìg?Ë#<ÂŽ;ˆ1’ç9EQ\¼ÜÖõRï-/{ÙËÎX ª[â:KKK<òÈ#ìÝ»—ã¸ÂSãf¶»%¶Þ1ÉÔÞ½{YXX?ï4yiY­‡V4cÉäÅʲ|Þ!Rch¦“kjSÛÞçþw-% &«—‚yØÚ>u-Ñ$CÙvŽÑ %ÎùBӥΥK fŠHLgP)±ÂÀÍ l¢ú2‚>…ùœH›Øß$kÎÜtÎm‚AaX:Àì(x‡%}¤¬±.B…5ÁƒÙ1M!Í_ Ò!öO’t±tñsD¿ ¥àŠé˜gˆ+­ëR–C¤8ŽKˆ¤Äg"QAË>AHß¡­ˆ%åà( â¦`6€8²±,Ñæ ¸ „dED´Š0DbE&VlPæO£y(K9.ÝG(Obåqˆ++ƒ|ˆ48Ÿ, Å1Ä)!8UÌâ¸ÝÌBEÀàG,<"ϵ暌3u€s¸)I’ððÃóôÓOóøãÓï÷_°¹›¦)û÷ïçž{î¡ÕjSÇED¸ùæ›YXXà±Çceeå’QâÀÎÏÏsß}÷±ÿþSD£¯jö©½`s¡®Êl‹hf§ÓÁ{O£Ñ`ccã”¶³)nfjSÛ>'m²âp­ÙÖ6ª‹ øêï/x%[Ý’w>Dç;^×Z}²ât6ër9=†Aâ5Ì“ |‚ ŒÄ„>’Íý*"»±æ aó–uÁ $®V`vW±GÖѤÙ$ ³”ù:ŽÜFçh‚/J¤Û ²ªFÌš9èõˆæ‘æ )šÎ Vm`e‹¨›!ØçÚh`ÖÝÀ|‚:%zƒÐEÓMdó+HÒ%–+˜ï£âÀ(D‰¨1ªÐXÅ^f#ŠheD â TƒyùæÂ…ˆÝnÊ}1ö— }Þ£çL¢£S{éXM\SËÀ\ÀdT>ɉ~-:S›Ú•Ð\ëkk»œÐkµÅu;‡ÉªÌtŒ.Ç”` p-4=@,!QÁ‡êV©JŠ$®b‘Ò“¨Ìàm¥Â¾„ªª Á—ˆ«ä,DpŠÅ‰IŠø“¦ ®Ëz˜WëH\Àe@ u$± ÒÆeMŠþQ$䕨¦yL*V/A01$*ˆ¬ ÉBè£ñ1Ì£I ÓªŠ{ö[ˆ4 XÁÜ.œôðy@tPµ•m,íA 8%*àaéÚX@úË8Ͱ¤Ò¯qi€ hÈÑV· m Íg I )ŽATó7H*ŠëQEÆüˆ @bÄL"&#'XÁ¼U,hW˜3\ï}/e;‹©Mí…²IQÙIò‰‹ fêÞý˜Y þ¹(ŠéŸÚÔ¶é`»jÇÇÿþÕ·àzŸ¤93¯Ýù3¼âÀÿÀ·bÎï~í,–ÏI‹;øÛX÷Õ|qóoøÌ¿ÀÏÞþ~ÊìÀ¶)4lÍJ^h@3y ¾0N¬ðèÆÇù‹oý2ø™À[öþ—ܾ÷¿¢Ôöeu&©¬/vŒ.G`¬’òïýw>þx¿‚D¸gö•¼íÆß ¶îæƒ'ßÇ—ý*±8BŒp}ëzÞyãÿ…›yFØö5s¶yp¹Î&,ލ´Â*6øCýèï) á82¢x#”Ͱ¸êZчŠlÔR¥I…ÇbÌ@:‹èñ¯³+g!«Àú1I°~‚k¤(9¡·††!Œ&%F"~D«ˆÎʪ*4\±-!²Hb«ø¢¤†yÁ4"®ùÿ³÷îQ¶eWyßoε÷yVÕ­ûì÷Cj ¤–dB`a $$âCÄ#æaØ€M<0±±3†ð@b°Fâ‘ǃ@ F‘Ø (H-¬G·ú}ßU·êÔyí½Öœùc}tnõ½Ý÷Qu_}æ5ºnŸSçì³ÎÚkÍoÍù}_¾†ª„úi¬¼•¼ªAVpÙBå â&5¢:¡la;gƒw¢£^U´he¯š* Ö¨Áâ¯Ghj‘ÒB )bâQÌ€4P³\,ÙŒðñ À­F‹³,áL´=K©àe,ãÚäFN‡íímZ­ÖÕUf꺞·—5™ét::KÎÌ2–±w›á^r!¹·u?¯>òטêï}êüáéÁÝ—ó‡Ú¦~‚¿ýÇù¹/ü0ç6ÞÃJÿ5üáSÿ„ïºãÇHåÝྦྷB@»[,.æ#s¡Ç/Ô"± «°“vøå‡¿“7„u¾üÿßÛþ ¿ýô?e¥u/·ù>ö«ƒ»[¹ØíÀý£„q@{¼ìŽH§ýBþèÜoñÑ3¿ÌÊ£?Ä›^úGÜÝ~÷ßýé·ñ©óá§š£þþÓ¿ð¶-î0ÞÝ?)c´Wœ%`0„p Ãâ&Î*ªT6³=Ž›e²?††ÈŒÐîY:xæRïÉ¡,gž)’ýTÒY( ÃÓød;[Ûø<€·± èÁûaóaÜ·UÜÆ9¿÷˜šyÎÐ^ÁÆ[¨ &† wÂp=†ð¸Ó)´Ž€)ɦJ°AÖ³sH±6Æt1° ìÃô,VN“¤é6Únƒ &Õ©Ñ/A<š+RÖÅeŠó8AÛ™ó¢ž_Û* ­¬ VÍínM¥¦¢ÌÔβ4´{ÓpÂþ‘eþ³ŒeìÓq¢UUB¸b†9˜iµZçiú7„œ½vô^Æ2–ñÅxO€N¾å¾ÿŽB»ôC—_<ýÏ92}óŠ7¬ïêü,ÿÃ'_Fåö¿—_8þN^‚q÷Ñd*Ñk’Mö´:s5*d‹@h?«3A?Éút“{nÿV^pðm|m÷ËøŸO¾›ÁðãÜ~ø»@Zût÷¢…j_ÆÈ#o¸íG(´ƒJÁgÓ6œýUÔ³ÏÇKû¯æ³ÚãøöÙ}‚ÃRðUwü#¯÷Ôƒ}qŒ.ö÷o~8Ô+c¦rH×)^ pl„Sƒ¬nCj€KB¤ÀêˆC½À|FNw•li3H5“NŽ0@ô'„Rð”°¨™{£c♇)$÷᲎§MTF¸iFk%•†ŒÏâÚ‚`x]g€·Q­‘Ö¨;NIÜj$mcåáìu“"Tg ‚è*’¦˜8²½ƒø6I»‡hhê`Ój'¡.°4BŠ)n‚LÚx«>Š,˜ÀY 䊊涱Ü&Vá´=ŒW#Dàñi˜=.1ógš¯ãaËc¸ŸëõåVO—q-ï×eÜÌs"¥D«Õºb€bñ”°ñs‘¹yæt:“s–±Œeìm’¶g‹ RbnüƉÿ‘;w>ĽýWqÿ±¿Á€À;^ñçŒÓ6ý°ÊÇFqêÄÏòÝ/úMÞù™o Œ?É×þ>^v×O1âÆêíÞïOP6ëStL;N?ô™žÎ!÷ Ì\M¢t-ÆI¥Ä<ñääs€øÔ5Ö9‚Æ (N‰Ä-Ôú¹­tÜÇ}œÚʈ†¤(xØ@«õ|ä"£¬`V ”¹’"–€\ ad«7ÑbTÐò^¬z Á0·¼Ú ™ãiÖ(ˆäßëúÈ\ã×eÜô`¦Ûí2™L®˜zžšYQEA]×TU5çÑ,}f–±Œ=NgUÐ=S³BÚß;ñNŽŸú^ø;ùêûÿÛ^#^“¼¢zœMÛü|ÿðÞŸã=Û¿ËëŠCô^üox÷C_ÃO¯|²þVÜë½¹¦=ðšÙïuÇ1޵îâ#ÁFØNºÅa\öÏh¯*3{=—pœ>¹õ~籿Åk[÷ðÖ—‚Öý`cj«øþÛ ¿óÇøð¹ßçŸÿNþ—‡¿›ÿêUC¶™9¸ïÑ]‹yp±{Šê$É GA$rL°Ï‘c´âÉúås£Ðaq/¢ñ$R'<¹#¨dæË¤3 fJJ;„[Ð\€¸‰ÉLjdÚ‡°Ih±¼ «7 :ÄŠ$¤: YýRÒÙÏÚ}ˆwa~ñ)žtVÅ€T ­§@iœ ;]²Ìršœ@Ú·#ÚƒXâœñwƒóÙ*0Àê¶Z€ˆÔ`޵"!A<‡•çðé ƒ/ ¸8Ú_ª"fˆ – Ð"°âhü,n5p Ñs@•+Z!àTà+h(±ú 6c-]ïX”C^›gD4RÕËœrM4Üü†ær%÷L±{¢5&KqÍî›qyc.c——ˆ=_d/’.á}äûûì=ˆ¶àßÿ'<Ð{5‡W¿†èFÄøÀ‰wò¶•WÓ9üvFþmzºF7&µM²8Ó50œ{.Ÿ™Kyl/"yIçA~½{ÿñÜ¿¡Ýy ¿¿ýAîQ8ÔõÌGdŸø:»6óKñPÙ „žmž]@’ÿöä;yèéŸâ˜”\y ¸ñ^Öt…—ù~þŸÓïb%mÒmÝÃÓãO!i‹;Ê£ävß7U©çš{Å™É@W€ ÐGl!àÒÁÍHv—€†bV ©¸†*$S„!Ö¡ÚAÂm=GJ;¸–y_EPP€œÌ‹{uù È& °x—s¨(V•Ÿä–«ÔCJ‡:$1ÅÏ=†2* T¸ôp"A"©6h÷ºŽ[Ý‚hda°¬æ&0:·ÖqéC‘pIEÛ’Ö ôqA}ÑÃHèdÿ™$°ýT¾Q¼à6‚¤YÊZfü" ¥ ±Õn¹çì ³L§BHxêÏZõ*0ËŸ»(ð4AôžÎe,#çÏ…½ZC.åuv™åAð…ÁÌõ’¬^Æ™'5àv<³ººzE¯S4“¬®kB´Z­9ér<SÅ\]`9ñ–±Œ½Kâ÷2jœ‡6~‡— <<ú4Þåm?±Õ×1>7üSÆç~‹W¼ðרÜyýÑà_?ú}ȧÞÍÛ;+ëßÄö>Ten´ö©ÝßGGÛüÍÞËo=úC<ñøßg5´øOîùŽü*ö·ÿr®sñù‹ëñ~Œ‘‰ð™­ЊÛRñ'~«¼òèßd; øÈ‰FaCxÕêëxó½ÿŒÇ=«Ê\ÿûÖÁ;$£âˆVˆ•„Ð"Vo h»ŸPÄø(æšÕ¹<âÒ}!Z<Š¥)æ½YûÄ< æ˜{–vÁ-"¡À,mB ·c¶¶‰I@¥C²³„bC»í¬è5©ÐîÔõYŠ(¸ÔˆÀÂ0MšÃ$;޶zÀA, JDà-Aâ¹ûÎѽ0¥Þ$tÖ>ŒXÓ¨¨¬bÅ&"-ÔdÅ1;ƒÛmP†´‰[BË„·Ÿ"E+ó‰ t¦´\!ÚCK…èA°°)â ÓÜ1âõ8€´R61•HD8€ù&Žª'¾ˆföy-¿ØiÍñãÇyì±ÇæBJËøb´Z-î¾ûn^øÂÞ’ÆÑ˸¼!àî”eyÅ2æEs6 %¥47Ì\YYÁÝç|še,cWª:w\n* WµÉâ”îüËצg(o%¯™zÞL_Òÿ |Ù'‰6œ÷^Éß{ùgp”ä5[>ݳDt/8 ‹ Šû jîフ¿û²À,™‹^Qí°{.0sµãÔ$P{)Ïì6å'¾ô÷9Oj6Û¶lÈ[ïøü•;rž8‘Ú¦ìu›O3®+¸€müN°3¸wQXU !aÞÅ'[H8A‚¬LÚxÚA¤…0ú!ܧ&¨ÎÚ¨:ˆOÑPœÆ‡ŸEÊU¨K¤´¸?‹‰JÐÏ>¬arê Äqæó[A4óiÔqsT 306ð°†T[„¢Û¹hOƒÞ†pÈ^m ~RÁâã¨Ü‰¥S q#$Å‚A1ïâ^!*xšb…B&x ÞïƒNЪ…Ë5%H£m\¹-Í{H+POO‚i®Àh®Ä8@]Ḭ̈ÖpmáŒÖ¡s ßù,^ì ÖâÞAµÀl ·¡pˆÌz`Û`ã,Zà •>„Ì_jŒIo Äý¹Z$ŸoafÄ©ªŠñxLUUó5«Ù7–ãôü‹æÐ*ÆxÅ<â9˜©ëšv»=/õ5­"!„%j^Æ2ö ÔÜjÑœ¬ìn1Ûh_Š<õnNÉ­²5ª-Íï#¾^ŽTó­z4jלsÅEKð1ngp’b2DM$xá C”öL™zœe…µCªG¨¬€MIõH@,·ÔH™Š™°µ¡nY H\иHuÌ}AÉÝl~Ñ£3·•uÜÛ(ÕÜN#z¬Âm‹d#TB<2ÈÜžñ®õÛ2ð±´ ;'ð0Å­E ¯yš0Îèƒõq­ñéqÄ ÀPK¸h¾®d™ç¢aÖþfxª Ž >NòŠ E£ EÒQëáVaÑC¢z7æ1ÃY#è„äL>C¬g‚Š+Y?öê[&èÏ”ÊN)]±Ûû2n½¹1¯*/*v££étJY–”e9Gл'ã2–±Œ«ÛÄv÷ùßJ‡¼â¥žL>[/ú­h<×€3›¾ç4Ï5F·b¤ª„¨ëúnÛ ³ £÷16ƈk–(ØìÞ%KAÏ”Ïøž"B¨ââ‰lO£Ùœ’”[á| ~ Ç èbZãi‡TUh» éi$܇Pã2Æ}”µêtä§²‹rêSˆì€­ :ÂýÁ,Ô"Î&¡èᾂ„ÕÓÙdÔfÉ©6RÓORô€uó 2PAEçRƤlmïž!Rºàæù9â5Z¬‘dˆˆ2ÝÀ©²¢š1é#ö¢GÀÂ!,EõÅHz u0¶ñtĈž$Ђb^áÉq•ÎQÜ>“Á”'Ä=K+ç>·üY¥‹¥¢ªmÜ·0‹ˆkE²*]Ì6AV0¡z„è#ÄÇ™rÕÊ,!!B‰ËiDnÃLú`%Bg^™¹ÖÃ%gæ™ã±]˸µò ÆæjT9‹Å ¶áÊ4eŸ ©-'à2–qi‰å³mb»Ÿs+´R•e9'µ7mf—¹TYâ[Á)ZDæ‡Æ8õRAͳq‹n5ùv»=ÿ\—2F»+T{‘t™Ä/žÛ˜d…”6q½•,#,Ãi£­K'Á²d3ð4È~/Tgdx±Ü’…Íæ´!îd ¹ËÌ SÍF•άõL0wTÃi*rŽ„ÃXrBaDõ³“ˆ®³*5.%n[ ë¨ ¼«ŽƒDví"é b`eD½F¬—‚Ä£…¦‡3phpt,Ãl`3xá ÊómÐU$m")‘´&x$`~ dŒx•£¸ ?‹ºbâY ÍÁB®`d Î z{GÁÁ« Ù{¹îg»«ì—ÛJû|4ÛŸ«¥v·f®Ôt”eÉx<¾bo¦9˜iÜ7˲¤®kBL&BÕ÷_Æ2–ñ܉úå$¦7s,ž¤7 è•&KVovÐB (Šy)ýr€ÌŪ/‹¼¢[AªYDæ>3{Nï‰}ý¬)¡¶‚¡3‰à‚TGBAD¬ ¤ÄÕI o%(Ö´…Ç^pǦ Z%êž„P̲‹ª"A2lF›q϶“f3å³[¹”ˆËQ¬Šhy€TA''€„Õ†Ê-àõY OzmßGªÇ=áq ÇÐ^oŠ„ôîÀ¶?†„#YŠº~rv "–Õ×Ì·—Aa¶ûVEˆcžvÚ"’vp¦8-ÔÚgF¸‡™¨ã’0ÏF™*ŽK…VO)Z“ܶç m¿˜”ßóµü¹x{—Ê‹ÜËyz³Þç»E.Çol·n®cœcÅù}9¡Í6œÃáp¾´Z­óˆ¼ËXÆ2öüܬѴ¤.VöòsÝ*kP¯×;ì]êgºÔÅýf#w§Óé\VUf_£èàºD¼‚Š¢ÊÆŠn)JDG™¯"]¤8€ê&xEQ´P‚ZCÒÂ:1e(ƒ¨b1‹™ðt^e@f¢jž«BÓÇe ³# !:Aºh±)EQ‚ô Õ˜öÁ‡)ƒˆ±ø9Dº¨in m0ƒàx˜ ¬bÕY|òAºˆ ÀžF0ÝQÉ"1Ä"=Tï"Ö[hˆ },´ókÙ¡\ARÄe a—VVMÓ)Ê1Ï\‘™i© *Í¿ûL4!GP)Ð`H? ¾ÃKE·æÚÞ(?F£›º"»Ì)—±xÈ—Ršö]±@#§ÚdÆç‰É­î*½Œe\ïXÔÙ¿7§æ$}¿€ÌâÂv3ŸHv»]DdÞ†·×ßõbõêfm=+Šb®†×ü\Ço µ~&•3ÉŠ\uÁO1« d‚ºC±†(Û¸Mq _¼þ\e9Iÿ2ÎÄø¸I†™gu³&O sCfÂiÆ‹É,ɀà Š…›¸Àã ·0o¡Ò²ræÙX’£à+h:‰yWUæê„£Hcæ¸D„€3B¥ ~×5¼Ú©QÔÀ$å* –92èa,AeBª a háœEDHq Asû›‚w pÝÌb*™ôãÉ`6ŸÓ¬B"8"+ÑjT;X]ýtA`Öž«=ˆÙ]±Ç GcVú=ú6&zÑ¿F8ÂZ¯¡L¦CN~êãlß÷Õ¼öž’ùM±>WefÏߨ,K&“ÉüÀïŠÀLS™éõz„怦,˹yæâd\Æ2–qéà¥ø…¸û3ÜÎo–$½Y7êº>/s9­A—ú™oV2mY–s¯E0s©^2—óyI”7Ó8‰È¼_º§ËmWÜKÎŒ»c¡FÜûY¡«hg ÙKÅ*\+ðU„aLAƒƒgNŒ!ˆ¬†è¦-B:ƒÉ É7Q<ج£3^ d7û€Ì*8É h! ð³™ïªc$ô1H-HYAÍ¥ë£á f_ÀmZÌÚ§Fˆ'œ æ5"†—wféçø$Ëïcg©²GŽ;6£óˆ NBhã²é êYÎZ|e¦:}6ƒ#o£ÒÁ9^"ÒË*o¾17ÅÈ;%ÎlXœü>²>ã÷´!;޵@Jã9”ÙÆå¬i»¹4‹›ç¶<ù‘ßäÿú£'øÚ|ßô@‡*åçÕu=ç0«*[[gùó÷¿—G¾ôÛøë¯½v§dó¡?æÃáU¼î~aZÕsÚ¢(æBN‹ÜÅ&aÌ"iÞÓä|—{pݨ2>Ûxìn½”ñ[æ™Ï¯Xlãl””¯Xͬ)í×u=/fFUUó“²¥Dá2–qyÞå,ÊÍÂ3%¡zY“¤7›çåVf.ç¹ÍÝLU,U¥ÓéœÇÙÏÖ©æµo&Á„fjøD‹â{9.^AàÅÅE F5˜à^æV(ïC(ÁF¨¶Ájœ Œœ[€°†KVø2Ä{ùõÒ”¢XÃd{ÆQ á®™'"à³@—;ª´áÖÎá®ù&S4¹Ü§8çf f-§ô!¶fÞ9d~BŠDÏàv  S\ÎâV`âx:ƒPϼnl6)ûÉàkát€íÌsá,bÇ@Áâ.N¡²†YMO%æC܆)²Æ9¨ÏTÚGx#ˆ`DDB-™·c WÀ"âÓ¸çjfW#~´È5Þ½L§S¦ã3|âƒÀG¿pœã¿òÿò–ŸþF¬³=pîÜ6¢B·Û¡×i3žìðô§>ʇÂø¾¯<Ìh0澿ò¼æÈ[à gΜa2­(ƒÒívX_[£Š‰S§NS”:ãX[¡Ýj³±¹Åp<¦Ut;®¯‚——UÓúô§?ÍÆÆÆE«§GŽáÎ;ïduuõ‚KвŒÅûáj)-ç 4ÉÉ¢‚ˆPUÕrÒ-c×(šþÑýž+Š‚^¯7OЛ5äZ\wúnt@ÓTýüË­6\í{7séFV«E·Û=¯½ìú·uë8Á={¹Pggz !æ^#â‰$-”—UðMÌJ@Ê5ÉþèB¸`7BŒ‘w¿ûݼêU¯º†˸£áÉ4{ÖU™Ýü˜¦ç:¥4—É\Æ2–±‰gs6¥ÿÝîÈ7R¨*ý~^QZl/ÛïqjÞ³Yônd@Óéth·Ûçµàí÷õ6s©i7»ÑMY–¬¬¬ÌçQøn„„GÊJT Š„VØ)DP¢Ô¤:AXCu—ƒ`çpïg¹dmcZ :E]‘…I ‚&$´f&gó*¹ÅJ‚#RdŽŒ¬"²zqEXÁ¢gÒ¿¶qmãqˆëJ~'ÎY´8šýrŠÜhSIDK Bt£‡ZB¡¡Æj•D3ò‘b%·‡Ù©™ÒÙ-ºˆX#¦Ym-Ìaœ¢º å±Z–I–5@5ûÉHÈ„wÜ#È:ª}ÌN¡EAJ:‹Fh÷À¦ 1KXß@À¥¹›Ãá#ƒí þØ'˜¾èu¼òÅ_Æ£ëïãCÿþSÜ÷ºÛùS~ý=åæ7ø«_~ˆÑ©/ð™mgí÷!é¿ç—ßv7ÇŽü‡’N¦“M>ò¾‡þVÞûï¿3ô¯ø¯ÿ›_â?¼ô§x lG-þâ÷¾ƒoxAɽûð[ïû/ù¦þåû6ù‘ÿý7ùö/é°yjH»ñ¹ÄÏö–·¼…w½ë]üøÿø333~þçž×¿þõ ƒùXìö™¹Õ$å—q屸§_±@³¡@®Ð,z!,ž".Ë‚ËXÆ¥%“WJTo6¼ælª7R„XYYɤÜËä€\ìdîJÆ©¹–qSz½­Vk>>M¢~¹ŸõJ娛õº(жÚ×jµèõzój̥̕ }æ½H@œVáV¢:›g¶sE"9ø˜¨žÄÒV6{”•Üj*’ÞX ñ)¢†¸‚,‚¦—@æÜœ\ rWB‘ÛÚÌO§Ñ2eÎx| ¢ ¡CŠC´õ"ÜŸ€¸…è ð8ØÁ|Í! úB,~<á±ûY‚¶ðÙ^¯åñ fV‘Yx ™@”99Hø ·gœÓ9Œù9¨wаŠ3y)Zo’üi„OC̹â3HrÏòÔ ·Cö©'øÊ·~%=^þ5òÞ?þ6^ýW™>ýQv޽†7¼âÃáÔ9Â'™ÄDš ±zÂhRg‘€Ô;|îTÍ_þžWÓïÀáø²czÌK(k÷ÞÇw­3Ú9Iyì^Чôî ?ø¶?ç·ÿñò[­#¼ñ;ÿßõµ+Ù›õ£ª*Þüæ7óK¿ôK¼õ­oåèÑ£œ–* Ä}•uLÎâ6%H‰ûùªe«³×;“¹?Ù‘·KA£Í A$"Å`¶¡L¸ÜWf\¥ìoãe±Ôb²—bf{b~ž „[ÛÛ 7æóþyÿü?àwƒ’☭°ÃSí[8¼zˆzû>y‚»¤¢Õî *ÔitŽÁàÐ|- t{+ôZðäÇ9¾V3œca½Wf@Ÿ½ÜY=°B+@BX=roøš—òÎ_{/wÇëéŸø>§ò÷¿ô(½,ÝôZ˜+Ó§?Ì{>|–^x´dåÀ!V:-`rÙ "ÂáÇyÏ{ÞCJ‰Ûo¿étzÁ=a÷X,cMUfÑ_报™›Ó»E£Ìà¨*EQ,G|˸Ʊ¸Ø/zo\Ëd¯YhîDžڮ禴¸)†æm]×ãš{#u¿›Kt½’ôÝ ¯Yã¯5ðswʲ¤ÓéÌ+Ž‹óé†2y„0EB!劋æ*…z&Ú»A[-„3¨uf—³ê†n¢¢àS’öѲžÆì!#ÙÐRÔHq#?–q®ì33Ê™Â!R‚"H7+¨yDeŠ»p{×f«„4ŵŸM$k#h‰i@¼„ÔÊ"Rä.'qñU‚lƒK(ž? . ’,µ‹[;W­Âm¸M¡=ó‚Ixx ü0ÉbÜ7q©¢˜°ƒÅŠÌª?šÁŒ B¡@|Š‘)í!>Ê­v…bp½å¤-\»ër-oæµjàð¡>n{oÿËßÌѶPWƒÇîçÛ¿çûyߣÂÊ‘—ð#?õøÝ÷ýß|ôŸ¢wÛ—ò–¯^çåßýC|ß¿þü½?à•_÷Í<øæ·a÷¯âÒæ5ßöCüä±÷óï>ñ§¤þ=üØ?ú<Úg'¼ˆ¯{cÍѶÓÓ÷¼ø+y“Ü{÷î*?ǧ?ö8Þ>È÷þô;ø‹«‰ÉįhŸ^ûÚ×¢ªL&“ó¤vÁ^T»–qëå:M;ô¢MÅ™v»=?[ìù_T(Z¶›-c—-œ.\íý²è‚ÞÜìÍ}z-¢ÓéÐétæÞ‹§èW³&ì–¯¾šqZ<é[lN§×$I)Šb^1³y»Ôb‚~µ-x{ÁiD]šS°UUí;ðkÞ»ßïÓjµæûÊâÏnð~5ó`/}fDò„ØNOˆÔ8JÐfÛ¸«`’(C‹d„ywFâ/Θ AJ`[ÕÄH¶JæÈÌ. 3 dϯ-*4$‰ n¦ˆŒ ;xz|‚J|ˆQ‚ƒ¥‚ [xR„%ªC°‹S¤tÜO)ÿ-ë¸F´@,e%{͘æ”Aj´X=œÉ^33®Š”-<²Œ ‘4Ƹ¬¢:Äl2+9õÑ ˆg-n³×O5¢§D´3ÍßA‘Àñ‘Çq›€vr«‹rf{µ¾\Êz¾øøÅŒ23 éóUßõÓñd>ï¿âüà+…:FºG^Ê·ýÀ+(Š€»QW±õßü×ÿo Š¥Hòïæ¥ž˜LkÌ{¼ìëÿs^ù–‚l3©êšöê=|ã7¿·šƒ÷|%o}bßòöSaþüɤºâVØ‹­·—ÓF¶ô™yþFUUçñ_¯džW™iH¢À"fÙf¶Œe\Þæ·—¯efó{´,KZ­Ö\›}?¢á34 ¦ªªgTcn¤ §ÙcŒójr¯×#ÆHUUûòžMKYY–óïgÄÜh„ûÅ 0¯¸5‰È~€šFšºÛíÎß{±³ênû:Æf`c<.mD¦xêc² ©ÌÉ:7C­CÂ!cV“Äs¸&ð èaŒ@ײɣɕ dÆOiüh²K$¤™ÚXS©Aðd¹eL×°¤`Û@hXAƒw@»`5–¦¨÷1/1›P„€O?‰ygˆYc IDAT†ægz—ƒ¸mdà”Á4 „•ަ;ÌNã¢mHCRlgóJài„Çxt´H¸W`]Ð Î6AÂ:fSœ ñÖÁ}Œ°Šã$‹hèâõT+,h s¦(%hD£dÐ%7ÖZþL`ãÔÓ »kH)ÖŒãùÿÞ“tñC¬ºšRWÏÓiZ|Qÿy Î{žu,–œ™e@.¦L&“y®sUjfM @Ó_ݼ`Œq~š¶Œe,ãú%¢ €hN×›Dt/8MKi”ÎÇb+ТÊÔºé,^_ý~þ9®„-êà·ÛmZ­Ö@í£¯eêü¹´xª:÷xÙ‹jRsÖjµhµZs@¼ûçF£/~éŠ.$Ct‚Ç>¢ÙÐÐ,$ÌÌ»¨N)&-4tQ)H>@BB \Αª1«ž1ká’Ü2gEr+›4íW^,’lö˜b®ˆîXÃ)Aø*îãì#=ÊrD’6Ô¢;HˆxrBhãskœ–ˆLpmá~Š ÷f™i !@Y2`‚ŬbÓÊ-p&7Ãåv8óÜ6¦¡åV3Àµ“ù/b:CУˆœÍêi’péR°²N@´I¾^ƒB‹#¹¥Îj\j”“™PscÝkË®– ÇõnQ^ÆMu^DæW fTu®&ðÅr¨žg ¹Œe,ãÆÙPÓÅ b1¡^¼›„¼IÊ›*FãGÒ´"UUu^Â{£'èJÖǨ§Å1Úýû…ƨY›×hÆlD6¯±øž7Ë\Z€ªJ»Ýžÿ¿ Só·‹ãt¡1Zlh¤6w½›bOI¹Zâ–é“îè„b ·!ÂìÞó„‹#6lfùà8ðª\12²Y'S ‡3@¼‹ë ]Dй¬²¶nƒ4ÂC…ûf6·ì܆œ™Œ/ÙÆœ!L#2&¥'P*D %ÎIHÊ.˜ð UpMÛˆvÀ¦¸¯ èâ5¸Œd³L'{ß„!©–ü%ÖˆWà=°>YŽgmgºêyq…PÏ÷üi÷Zy¡ñXŽÓóó¶9j ¯Ì4§nM_~§Óa2™ÌO6—z˸üäj¿7†&©\LFOË›Çw'¥»7“ݧðû½ù^«1Zü iÖ³ÅñºØ-¾ÆnçêEw³o¾ÍüY»çÓâ‰ÙÅæÒů馣Xã¡‹§&‚èJVþJC,h(HÑ«³ç‰; Ä p0‚(É ‹5A²:˜¹ÏÄ—m€Žå-OHn£Ò<ÎIWÀš2ïFD1ÙFüž·)ë"2ƒ(æn‚KB|€È¦ oAŠD-¢xª±$à%ª šHl#uGÀÎfN‹Ï— ‰ˆØ9ÌWp’R–#ð³ Üäq4 F…˜¢šˆæ„ຈ܇P—Y$a:†VЇ4 yEhi5 p-0!Tzˆô27(Ëêk{´ÖìZÆ3ã.Ôf¶«çªŠn·;?¨½b0Ólðu]Ï75U%Æ8—]Æ2–qã‚'_tÐ^HÌ›ß7Šæß—¢¾s«ÌÅþÜ %çË1âqÞ¦Ø;3BØ À»c<˜:ÆD¸d7 둺Àb|žUóA‚'ÂÚÜI1n ‚1¼káÌÓX› aöóY:®‡ñÞÕòóì.ò$IŠÖõ/µn½x¤Ë¾ôlYX89¸©çXèNI•ðUTÑÂú‹¹_^Ê{õ¥µ†xœ IÁØ| ã&!˜À0.#Ãa|>ìÒàpi€ÌË1¸¬‰w#ØpÃÞ¸þ°C—M€ëæML€u)ÖçÃE½ qÆPÃ; A\ kÆqÙ Þ5ò.jœïAæŸS™–™](I7Èn·[4Á8^ñ“ð®ßïÓétæð¤ü™ gÔï÷™zN󰙸©mÊAœªÄ¬¢Š^~¹âQETH!Œ°&Ã3ñb|ÒÁšc¦À,ÂÛ œocò!0xj˜p)>݆ "°‹°¾…·AQýdƒ¼¼ÌGã˜Ô’GX[GšLE#8çñY%8k°6ã±.?³’·>Nƒõ Ä1> ñ2Ó%01øOã& Ì›*ÛÛ€ ¶yVˆ&_¶ƒ b"{".Ûé~¼¯al‹bŒÛ‰ –à|‚E`¦°2(ÓX²,Ÿïd”%z9ÓçÁ†@îâ?8Œ 0ǘ6Y6Áú>ÄË0Ù†§óŽ~0¬Ó÷L g¦pf1ØoâÍAÜñŒ/nÄ? CÚí6Þ{ºÝ.ív›n·[…G<¥;öû}ºÝ`ßX@ÎéMËþ°,lRG®K»´Š*ª¨¢Š*:.ÈpÞ[¼ï[Xê8—bÌ(ÆõÁ ñ ì*Áû.¸½y7/kq™ÁØQ¬kæ­Žñxøq¬« ÅG`%]® Y k!ók–œÛ“gGÈ?ƒìµ£x×!4uœŸÍ—ÏÆ[‚ !sM,Ÿ¥x;h7M ŒbÝOêg0¾Ÿ72À š‚-4Á1…eÞ÷q~”Àtq>Á8•&_wƒèúà\‘ CÈZ@oƃb0‹1ž€Yœoä¾KÒÁû”Ð&xBp1Þ¦xSÇÑÃ0‘óÞÖqÔÁµóá¤f’À¾Hâ’—R­ZµŠûî»3Î8ƒ~¿O«Õ¢Õj‘¦éqŸ™‘&,ÒÖ>Š"V¯^]·ŽsŸ# Ã#>§›™ž ཧV«='š+ª¨¢Š*ªèXthŠÔ>2Œ… À»&.ņc8À95!ž6Æ[\ÚcpY„ F0Y+ÿ½Å[˺8ç BpéSä' ÆFdÌbL„I'ó¬G<¾7Șx7÷ ‚ Îeû°A 㛹sE‚±1ø&Þ÷çgÈ×d`6\~ãû0Ö *ÄRpuŒ™ÁÓÅÓÀ°çÛ„Äxãñ¾1g²<‹5è1íœÇ%?'d|^~æ¼Éùg,¸<“…üÓ: m0 ¬k“Ž8®iûùÐQïðÁ(Îuð¤ßÂ0‚w1Î4óL/nY¯sŽ 6pß}÷qÏ=÷°lÙ2²,£×ëíÊå³Ç›3£yÎ9jµguÖœ’³Ê±9þH|¶|TefÆz½Fƒn·Ëèè(ív›Z­FEÕðÌŠ*Z0þy~ç̼œŒÛóÍ'ckÀg¤™c ƒÆ¥)†ÖNཌâÉÈÂQ|Ö%À“ÑÆØLä HðAÀ/&c‚ñBéY—£‘-dçœs;wîä±Ç+JÎ*z†jµ't§žz*AŽ^Õlêø$™—×jµ9¢kÎL†E7³(Šè÷ûA@¯×;f¦ZWTÑK ¨Wôâ‘ ~í“Üðµ[ÏûmÞÿË'±óö›ø›O|—dñzÞòž÷PûÁGùÄmO ­#µ£lºàjÞúæW²2r8oIfâû.}ÏopÞÚZ©ÁƒãØ~݆¬³•þøO¹uüZÞÿ»×3ÖyŠ/ßxß´Ë™×ÿ*o?³É þžÌF©Å—yÆO8—7¿ýMœ½b!Šš|åÏÞϽgÿ6¿ýZ²Ôë ;F™äÓâpphÞ‚w¦2F ŒÁ¸6Ž\Žâ\‚ œ3f ÒÆÆSÇeOÂex3Šái )`‚ã<$-Œ| k ˺ã|› pILêê¤ù!xq3Ǹ&™Y„éus§ÉcÈ\>„Óx.€p)Y²C:1Þµò¡ž<=¼ëƒoä%pId¹ód˜` >} Ÿqµ<3âM¾œÃƒÌÈ1Γù,_¥sy©œÍ3YÆ;¼7d.o$à3Oâ§À/”Úy<+1n³øÌbŒÃ¸¼Õuæ¦ 'I÷ƒ©Cv€»›™œ‹Y¿~=›7o.‚ÁÕÙ㹪²,+š$TÝÍŽo™¿£<¸úˆœ™4M‹²2™/#ƒ3+«¨¢ŠŽI‡&Œ¨×ë‘cëmÿÂGoü>ÑÉ—ð o{+œà¹õÇ1õz%§^ÏÏ^q󗾯·‰¯o8‡÷\:Žw–æOo¡½l3ÖŒÒÞõ<¹“VÏaã:ËÖŸÉÆŠY"Ç(—ˆë FFjôwÞÃþå‹Ü¶{”«é}\wþZš;ï#Ž#ÂñWðî·œÁìOoçë_¿™¿ug½û¬¼¤j÷}Ü9³’×\¾Žlv/?ü»¦»@ÈȲõœ±ùÑ1æ¬ÍÁwhpø¼’*Œ0®O0£ø¾#ˆ,Îå¹xŒ7DQ$uÔ°¾ ¡Å¥!ÖÔÀMcl+‡ÝA@`,d`ØEuÃAv%ƒÁMç:ñRŒqdiLî¬8ï°A€3†€6Ä2|fð>ÁÚÁásÛ3†a† J±¾†—çåmQ™ÁÚ çCŒò¶ÔÆ`!£Ž5.Ûƒ5ž‚ËÖ¦¸¬“;e|æ°¡…Ôg Æ æì`°Öäƒ:ÿÎçí !Ú`ǰ`;Ƭg ¬ÃgYÞPÀŒã|JÖò.xI€3©ùït:ôûý#îÐôr'ÉÆˆcSaÍãס‘RÃ#MœÌ93#í˜%Uš$É@ŸÛŠÛU´@ªŒÖK FtÿŸxh?ñ–«yçϽ† ‹,I’1Ü´s€ÉÝ0ÝO ã5œtÂÞ¬íðÈOgɦ«Y™<ȇ?óY~:;¦-«HömåGO.âÌÿñ |?;†0ÑôÝ|æÆûÚã¼á]ïåªÓ–á­n1Òûöîefÿ}»„-'-ÉÏCXÇö{¦µúΙèrÿ·¿Ä?~c;kÏÜÄX2Íöûv³jíjNX| 6’1~ph?/ƒpÈäÜGŠëOa‚ž€ ï#œi€Ÿç‡í³kÆIÓ>d3.Åe¸Þ #ãú}¬íáÅúÃ.ÎÛûi2?4€YÚÃ2›gbŒÉ;ŠyCFŠÉL°”,mæ…wà|øÏ¸i¼·˜(Æa1.ÍÛ)÷“|ÆKš—}ã’>&ŒÈÒk<ØïŒIqÎ`éã,˜ÔálL†ËzØ ÈËò’l™cÃ<ƒ³4AîÖ >ç›70&ŸçC3wVÒ.˜|nŽõYÑ6Ûg6Jjã³CÖ{Iuql*›0?ˆÕ¼ªèøÆLÒD㨜éï,gc¤Ô,Žã"EZ¨¨¢…+èj¿šGÏ'ŸòëæhÝuö3¯àÚË/dÍX@š9“G‰Á0³í‡Ü´ ðfñ&×m­žyŸl9ÿ­°í°{¦C0v2§žs×¾…åã5²^ú‚ÈÒóyÁ$³ìK2ÆÏx—Ÿ¹›¤ùÔu|îì´æ_y¼'­/fÙx ï<6âîÇö±þ×1’ö™™ÙG›16l:-'¬cͪ¥Äöù{†çcÎÌ3V6ÌN±x“ù¼•öÃûÜg!Î8l4ŠÉðQ>h‡eVI N€i$¾µd]°=FÉ+³"ÞÆ˜h%¤I.±Þ?'sKŽfÎÌ¡òVT•dW¤œ‘0$I’#Þ+V •Ž)ge¤•^EUTѱi1Áĉ¬ ÷ðÏŸþnyršŒRÇ ¯ú]þê¯ÿo~íª dà[7ý„n±ÿž³wülÎ^ éÒ‹xÇë.`Ym7ß¿éFþ¿÷ÿÿùã?¤eCŽ}¨âqUœ°lÓ÷þûü­L§ƒ)ïYŸÞÚ7ó'þÿðçÝœ6º›o~ê+ìò–dÿ¶N7¸ôä12Ûଋ~†KN­ñпɧ?ôÿòÿó‡ypoç˜â†µ6Iàòó>Æg \.ïð™9¼ëâ}“\zãg±6Àš GšËŸ X‘; ¦A–íÆøÆ&ƒ™/Þ÷É2ƒË¦q—aLˆ–â© †OöÁŒÏðƒR.gÀcÈÁû.íã’Y¼_„ó>Í0ADâ¬IÜ(žŸYðÝÁ÷C²¬‹K¶a2Ÿ?w·‡÷=¼ƒÌ¥yÛ1)Þ´Á9¬5¤ÞbìF°yÓçFÉLœGXÃ%iQ–ú‰¼Z~¾?Oùü~“7Bò98ÎåCHq“x×Ç9ËfÈ’)\–Kržb\ß²ó¬$æ\U*G¦¢yøišq73«#A˜,ËŠÿWC*ª¨¢c§§Ô7^Í{ÞõF6Ùí|îŸâ«·oÇ…ñ@Z;ïç–ŸÜΣ“ùAo ¡Ÿâ¶[w±â¢W°Ü:\s»‚“xÝ®åú×_Î +ǘºï6v&vQ?–y”‘Žláïy;¯>c9ïó|êK?ဠyùSkwÞv;w?øSfûƒî^xöìxŠÖ’MlðYÂt;aËE¯æÚë®åòsÖÐßµ­û›ÇŒÃg­¥Ñh°jÕªü‹ñëÁX‹5—9l~RC€ ÎwÁ„xà}†3ažíð9p·6Ř¼¥³'wv¼O ÂCkc Í[2SÃgIÞ-.Ý´ÀÄy‰–5ø`|pÎݘãG±Þ“·ŽÎ0f4o¿l2ã]‚!À›ƒ jq~Çà€ ?sÓ?€Ïúï0¶µãg°nÖ°AþÜX‚ÀbüvHÛØ Æ„ã#ŒÉ;›`Ã:ÞŒ`=~?èÌl¤)Cä¼5°ùPL@`º6Ó'¬ Áu!kš4/5#ºÆÕ\¼Š*:¦(MSœsXkxL¨=£F£Qt—s2r~¦J“VTQEǹ4¡Ûéö3–m¾‚_zoÈ ü'¾õÙ¿§ÙüY6öºÝ»î¿‰>½,`Ý©—ñÆë.&Ú};wíçU®€ÔcéðÓÛ¿É×v q-⢷ü'Ç)î˜=2cÀ;úí¨C6º×¾í©ÇŸæ¦›ÿ‰¿Ú±—w¾ùd²$!¼•?yY–/>™7ÿÂëYå{ܱõ1VüZêAîÜÌîz¯|ëšYÞükÃ+^Íë–p¬Äaƒ `Ñ¢ElÞ¼šßƹ\6¨NÈk†Ä¤ÏÌK1 ºœõ€y»­(oœN ÆŸƒA—¹äŒ×!³50u\gL˜_3HÀ×r'† ÿN–A˜g‹°Ž, òÐpíüu°1˜>ôkɦÁ®‡l8á(ø™w`k`A: >ȶù>Î7­¨i73ÖAÚÊŸË‘÷Túùý½ÏîÛÏÌœq08a Y|@f=¸ZÞJÙä÷ÈûE»ÁwÌ܆dž< tÀŽç¼Ì¦óý³‚:øHºÄ##t»U5IE3Vh0fdd„4M¼›™1†4Mét:sœIûè3Uj°¢ŠNåó šGÏŸ²Ô°éšwóþ×ÿ"xG¯“R_{¿ùÇ— ð—Ãs6—þÏZÞ8vÜü•pÖ$YНmâí¿ñ»h=ë]†K3Ü È¯ç˜KØúþÍŸ}€_&ŸK¹âí¿Å•ïÈç<[þô¯J™•üçYwÛ¶¦œü3k ð8"¶\þ~ÿ•sÛW;çŸ÷33Ï•,c# CúÜ‚1DQHFá ¤ð ÆÖÜyœ÷;†Ãú¨¿cæ¹ù3~×öLfÏ8ì:þ0xÁx;÷»ÖjqÆHƒn7}NÏÌ<ßzª¢ŠŽw,`­ett”4M ÃðˆöY(“Ã72k¦Ûíæ‘çª2³Š*ªèØT”Α•Ax–ÍóÙP@ë7\ÄÛOZIÝÉpHsÙË‘KÏdæá›Ï²á`ÔÆœ}Í›X¹a|Žó’Ãl’ó2ab­%‚b‚µ¶êîù’–ägÊä«YUtldfâ8>ºÌŒ8-µZ­¨U‹¢¨¨a“•b¨¨¢ŠŽ Pä-KO8™åx2Wé½ù £±ù´%8—ñr22DUÇÕé—úÞõÅì’ê]UTÑKŸœscŠ9—GB…3c­% ÃbØ“83¢Øef•¥©¨¢ŠŽ Pô¬¬NEÚ,{ùrI—[¡­è…gUi|EŽLÇsF•3E½^¯è`Öëõæül||œv»ÍÄÄD¥*ªèÆTÕŠæçQŧ…ËRE/Ž,ÉÐC‰Vtüì›JOUTÑóKiš%¼¢køÌŒxGµZN§C†EíZ£Ñ ßï³téR{ì1QU›º¢Š*ª¨¢ãW6¯¢Š*ªè¹!cLáoH³(ŠŠ¦c‡KÅ7Ä#)jNÃ0,JËjµëÖ­czzúˆèTTQEUTQEUTQEÇ'YkiµZ´ÛmV®\‰÷cÌœ±0‡KEf& CŒ1t»Ýâ £LãLÓ”z½ÎÄÄÆvìØA­V£Ñhß«¨¢Šž‰8Èl¦joÌÏ#ýïŠOóóiØaôŠžmËrUQEÏ¥®ªd«¢ŠŽŽœs$IB³ÙÄZËúõë‰ã¸èÙétˆãøè†f:çh6›4 ‚  ÕjÍ©ak6›DQD£ÑàÔSOeß¾}ÌÎÎÒï÷çÜX6¼xZó‘ü^zLK7ƒaŸ+_·¬Xô½Ê¥û^ùó)±#¹¾þ¿þNùšåïÉÏÊßY(4’ëêÌ·†ù~?ßóÊ÷æ»Ç°ZÈòwöÜ Yç|r¡ÿoŒ)ä­|ý…®q>Ù.¯±Ýnô3óÉåÁx²~ÛO Ù3 ùÙ0™^È{*Ëçää$q³oê•Y IDAT{÷îCÊYyþÕÁÞ۵ëw¾½2lÎ'oG"Óóé…ò¾œœÄZ[ÈÑÁd|Øš¦Û†ñnØw²·¦«¯a6¡ü¹ƒÉôää$A099yØ2}°wx0™^ˆÝÓò;lÈs ,/”§‡«£"Ó‡âÕBÞýáÚ‘ò>ö÷¡lõs…;öìÙƒ1†Ý»wî˜oï wì³G‹;ÊÿžwÌ÷œ ÁÓ3Ç;î¶öç w,„ß/$îÐ÷ ‚€F£Á† ¨×ëôz=€¢L’#G’)†föû}FGGç¤z¤»@§Ó)º›É.]º”eË–Aáð8çŠÏeYFE_~9<)3múý>A¦)µZ,ˊÕò@²ùŽ÷¾h­3BÚ¨È5äwÒ¡MÚL CåšÝn·X‹îâ&Y)=[ ×ëüªÕjA0§egÇE7Yg¯×+Ö/÷ϲlÎÚt[lÉŠ‰Â­Õjôû}Œ1DQD’$ÏzFñxeݲ®(Šèv»ÅïÄQ•žüAÌY³¼yV˜Û®[ä@îíœ+x(?×¼›¯4QäFdEî%ÝõšÍ&až{š¦sÖ*ï;ºÝî>ÊDYá{¿ß/6L«Õ¢^¯ëÒëÕ›Ò9G½^§Ûí›LwôٞȻ–ÚOé€$ï_žQö@’$Å5Ež´|è.JÆ‚ (ÞOYQˆît:Ôjµ"»Úï÷‹Cve€Õn·‹Ï4gÉNÇÅÜ)ÙwÂKY›¬AdÇZKÇ….qÎÍ‘(ŠhµZ49<‘çëÉsŠœé‚²fùðNöŽðG˖Ȱ|OGöE¶EŽeŸŠâ.wt”ÏÌål¡~Wâ˜Ôjµâ3ÂCýÝ,ˈã¸hÀ"2)ò(ëJ’¤ø¿<ŸÈ“ìq­£„äÊûžkÙ}Øn·©×ë…¼K ²v0垲ײ,+ž¿,Óiš¼–÷Ìy—ÂY_š¦…,i%{¸¬z½^q}±/².¹¦¶%òû2ÏD oe›|NtFÇÅ»™³oå=Ëû“=)üÖëŸÏq–µŠ¼ „¿iš×-w]“w›$Éû!×’÷©y0Ì¡ ŸMÞÈë°lk¹!Šv"d¶ì5‘F£A·Û-žCäI丌;Död whÙY(îкk˜*¿†;D–D¶E–™.îÞ‹ÞÓ¸Cäj>Ü!ïLžE_C쇬Iã-ÓòÎD§É^»'óCôþÒúSóLt¥µ¶º‡Â²'wˆ¾×¸C‚ù‡‹;Dw_å™Äæ‰Î’g[(î^‰¼‰>ȲŒ$IŠ{”q‡ÆøÚQïÈu4Ž;î(Wh½$™Ù×¢säúÂã,Ë ÜÑëõ¨×ëÅï´¥zðÖ·¾õ?œzê©s^ª÷žZ­Vl\í¤h°# ¶¬üDH„!„D z½^!ðÂ|ù½lq2¢(šó€ºäBñ$IH’„Z­VlbÐn·K½^/”¾6âÚ8Ë:Ä è™Zht)‘|NO.!ᥖÌïÑ|’?"ÜQÍBËZájÁ”ké5ËZÅa&¤²^Y³Q–¢ÜdËûÓ W6ðU{îò´q— °0¦³~yF=? ÌgQ‚Ýnwè•ë6BžµS+íåÚکП×ï@>/Ï(?ÓÆAdAÉv»M£Ñ˜$І_;="ßòs‘sqPåyåÞò ÊE)‹ì‰A×F{˜©ß¡€Õ2'YäEÞ«¼#1t:ò"<¬Õj$IRtNÙ—ûèÞó²'´<`ÕXx/k“ß‹ü‹Ìh'EdO7Ä`ˆîÓNæ¡èýŒ¢·Ò4-ö®î¡¯«ð_öµèHm¬Ä ŠŒ‹\ˆž.wÙ’çN’do†E¤å{²gôýEw— ðE;"÷"Óz¿ˆtÎξÖâP×ëõB>¤ÜYþ/üÖàMôŽèíÍ=7°Œ;„/Ú®è}$¼,ZÑozH©ݲ&ÍG­ûæÃÃ:öz=²,+x­q‡ì£2îмԺH@·ÆbDO”q‡ðHÖ]æswˆŒKÀ®Œ;$·Ü!xG>¯eUìŽþŽðEôœàpÕ%ó„òá¥È‡nz½^aÇçâCuÀK„×qûÇC«Õ*ì×Ó;vÌ Î8çX·vm¡+ÆÆÆx衇ži ='y’dã—²ÎÈ AרÑhFAgI„‰ä¡ä:âåêM&¤°¼@ÎF£Q™€ aŒl­ÄtTVêöd­"@ÝnwŽ¡–{È P*÷Ñ<•uŽe㉰GQT<»¿Ü_þ¯ÓpryOìäYDyËæ+ þå]ŠKdK\18e¡•¼lzHñÌõ5E¸ÅÁÅSŽŠ—K„4@c"JNœ­Ê‘i‘i‘I½É´3&2$IaTÅЈ i×­ % !Ñb‘/‰¢ ÿEþD‘èì ÎÈ鈱¼ß  c/Ï$ו½« »Y‡¼ÏZ­F³Ùdtt´¸†Tý\";"‡…ÒÊ´^¯EQ¡œôžÃ-@S¢3"òNËYyfíHêh¿ŽB å÷:3"²¦#žZéŠLkã/@¼Õj|-*õz½5ù}Ù‰××—Æ+N§xF¹§¼»²³¦³±""+²ä}ˆ±Ñm÷õž.GÒµüéÌ©vx5`Ö÷Ôœ²qÔkÏé  èqŽdOŠM’ˆ¥v³,£ÓéN‹è±0 ™™™add¤Ø4u IÞ‰€|Ù›"ãÒáSôOÇsl•üNdºV«Ñjµ ¾‰Þy#ïX¢ÐåH»Ž¤Ê³Ê;Ð=›A‚yAÐétŠký$v³Óér§uŸÈ´ÑaNËÖíòÞêõú}#{´Ýn?KOi}#ïV?ŸÆÂc]*ã}­ô:‡áY—€7¹—ÎÎhÜ¡+8茀|VÀò0Ü!ú]JI˸£ÝnrÔh4æʸC¿ y?@‚;ôž“#’Ðb± ":ë#r^vtÊUz/–q‡ÖM¢WEçJ°H?«v6Z­VMtæGWhÔëõ9¶@žMÏZ,ã¨O’¤p^Z­Ö³-k"Ó ëûiPgZË™¬F£QÈ^ÙÙѸC²4:€¤í}9ø¨u´È´È¾vH5îìÝ0Ü!Ï%ûVp”àÁ…‚¤Jc¾ÌðaefĠꈙD,è¨s¹E{z¢XtJV+d)Ò§\K ‘V˜( øÐ›A6¬¬A§Ó4 ×N‹l]BR.ùÐÊL;{àëûŠ’ÿ—ëGµÊÆÀ,ŸÅ'H\H¢:EQ¡¸uêPR•Zq—Kdͺݶ<›(_á±ÈƒîeCTŽ€èzH ÈäžeW.¯Ðé}íPé´¼ Aú¾.uþi°*‡ÍD¦µó«£òí.ïQ§ÙeÝòl:z¦÷ŽÎ h§¿'Š@ ÄPê}%¼Ñ¥bXuúY®«÷ÎÂÉ{‘=R«ÕæÜGó]G÷Êζ–wy¹¶(øröMöÞèèèã©#zFƒ^¯Wvm8tɈ–‘QýÜÖÚBçéH›ŽÚ—Ëltd_ë]Æ"£"³eÜ¡«34î9‘½ ïH%å µÈ½æµà»²31 w”åqîÐY—…àÙr}Yƒè5-ówhÛZÆúzÂWÙëzêà¶ðYJåZ ÁšOz¿hû%2-üÓ¸Ccp±—eÜ¡÷¶¶¥²÷ÊALmÛuI±¾†ìï2î(Û_í`jÜáœcvv¶°% ÍÌÎŒv$t´LG4äâÚ8kÆéšCa´V`å:tJÔÑs­„ÊõÖº<ª|X¨¬ˆåZq›KâÒJ_„H ‹|N„JoÒ²c£kSËŠT²òfGDo ]^&‚® °ŽTéûH郎¨ëšGÍ_]÷ªËÏt”GGõty…~&ùœ~ÌéÔhù™ŽTèç–™++—Þéú[íiE%÷,§tEùëw, PŒ¯@Ú0”¤.Р·¬,µ‘V3¯÷B92¬å_§µLë=¤åAï¡ò™MZáëìL9ë •­D…€HTM¿_ º.YäPË‘ð¦ÝnÏqд2å&|ÓïY¿ Ð%Úˆëúx]Ÿ¯yT>¯§ ¶è8‘/ÈÑû_;(ZgiÐY<}.BäOó^G℟:R¦u£>[ †Dä^gh´Ò|™Ð:£,Gåó åçÓDÉÆè ‰|¦\_Îrɾ)"-—@•fíjÝ­)]¯eE3MåRLmäe_‰Ž–¬…6þr=Y.?$´ã!ë)-´Í”w¡ƒHš?Ú™×Rî§ÿagc´ƒ\bêÒV-LJÂ:Ã"û^__Û¬¢SË¥¥Ãp‡¶ÇZ.Ë:sîÐ6­Œ;Äžk§gîÐgàäçÚ™†;Ê tvDã2ÔAíähªŸIŸq+g9†áÉÂi¼¥m»Ø(qʸCŸeÑA5]:|8¸ã`çµ´ ÐöuîÖQRË´èQíØé`»ÆšÇúyµþÕ%Ãwè ©ÎjÜ¡íww”ƒÛeÜQÆUÃz_ wè÷¥õìè†cGUf¦Ç cË%òQ°:‹¢=9½AE¸åºD£|xY—W•ÁiÙÀ—ÏU舞N»éú] ¢µR$ŒÕ½(S)å[>¡ÿÖ™ò) zjµZ!$ú£þžVìòyЦ£†úð³>+¡Ë™ÊÎN¹”Lo0õÒO§ÏËgc´±Õ@ÊäÊ9-y¿º¼E—’éͪ¾”èlŒ.{Óo˜3QÎ$öûý9åOº¤QEí)8­uMºðSÎÓõøú:åH¬®I•ÌF¹‹ˆŽ°i#ZŽøÈ=‡•Šˆ²•õˆb*ïÇaÙ>mÈËYMñÔ˜€Y]¥ßO¹¼DÊ2´R‘Ÿéó0é#]RTΚh>iíA 6¢¯tÆI‚(²>­£d½(k®KKtàDJHË£²Ã%|×%ºv_‰® ŸµîÐí ˆNÔ‘J-ÓúŒ›6ÐúÞå :K­Áªiã+ëÑ¥6åÃ÷¢‡tôS;ýfеݒ̮{ºÙ‚ŽLë2‰¾j §K”åYeˆœ\_ô±ÖѺÁÈŽÈ–nð RXÓ×Ô{Kƒt}--§²Oõ¡bY‡”Fél€¶µ:»&º¹‚”lj hÞ‹üH†@x.¸Cx«m´T3hÛX.Û›whÇ|îÐ Fô÷‡áY)w^Ê}4èÓö´ÜL@ãÑçr5~(wŸ’€¤èh;Ê΀¬EÛV©††;ôþ™Ðg45NÔåܺ”¬Œ;´>†;t9xw”eZã ”謹ƺÜðP¸Cc2|†;´³£÷“`0Ȇ;„ÏeÜ¡eZ;‚Âc ÓAƒòY¡CáŽaÝ˸CËŠ>{«eº\jªÏðq™™6îºËŒÞ$ú$=¥Óø’JÓÝttGY]*¥£2ú3ånKZZ—Ô ;0]îò¤3):-+µ›Ò‰¦ Dt©„Þ|ò’E!ˆ‚ÑkÓ‡›eãËïE‰k¥¤ÏI$ZJbdØPù¥ëïie¨3búp£W Ô$²¢¼]W­zi…§×!÷×ΜºÌKŸyk胵2!V&ÆÊõt—Ù4úЩŽénbå³Z´ÒŠ~XæAG5õaÀaÝAt©…Ž®iÀÞï÷™ÃO]f¥#E娳,訔fH†DgÊÙ ³²Fi+—aêCâòYm\éÌvBD–D›ÍæœC¿Ú‰Ò‹®–(˜ìÑF£Qèy>m(t@ö»¤è5 -wÔr=¬†ºĨ×ës‘\O×Ì×ëõ¢$MGFuÊ]î%20¬ÌD—hiX[R²+:ZÒÿZžÊÑ6mx‡e”äÚº$®\z+Ï*ï«Ù/Ët9У)O¹”k—3?ºÔF-ÓºI‹ ­£´Ú×aªµcV«Õ¨ÕjÅù]"ïG—w•õ¾èZ¹·>·§Ëûô;Ð]4õaù²íÓù„Ÿeª3Î:)²ªŸY—7zï™ÓDïY pç;Ç©³"zZ¦µœiÜ¡Kj5;îоCáð< :è`¸Cÿlîèt:îÐ%øeÜ¡YŸØ'ÑݺŒGŸ§](:Cp‡Î‚ë ªØ{Ñ«ÒFtQ9¸£q‡ÎlêsP¢ïu©ÎR w¶*w^Ô26 w”"S·ò9bÙw²×s ú©¶êòo;´,ãÝÕPãŽrÇÔ2î(w…Óú©Œ;tFVã]²­oå§v*u©¥Ö1ºÑ•à ìè=©B;DþEÖ'3c>ñ‰Oø7¿ùÍEÝ®D†ô:½‘e1ÍfsN}¹‰lJÝê®<×C®/*þ*×vë² ÝÆ¸ìéɡҲ‚.7 dµÑ›E¯QןkMƒŠò%UÔÞõ°6®º„@;~’nÖµázÍÚ(k… £ÂÚêÎÂK>ÔÑ.½Ù´€ŠA“š®'Õ¥%º>¸Ü‘¤œ+×€–ù'¬D¤¬DuTL”¦d4pÔÀI-‹Úy(—Öhž—›’èë”ËaôÞÔíUç+]ÔúRËeù=Ë!Rá¡æY¹¼H"4¸-g¸Ëå6â8éÌn® 3•Ë•tM·Þce£yU~¿å9EÚ•Ï‘”õ¤~‡e]£våÎWb+eïj %™ÌÑ™_}FI—”è€Î~•Ïד¦Ìu¹œ^OùŒeyæ…™š—åŽKZÿj¹Ó½wÊ?±)ºülX©nùœ ðQÀØ0Ü¡3ïú¼BÙ±+Ÿ)Óm¨uU‚ÈŠv`5†)ã­?Ê­„5î(·$Ÿwèjý¾wè7} k™ÓeîÒãtƒí jÛZnþ¤ù¯uÜBp‡.?Ó{¯|Í#Áå‘ ÅÚ6j^úUÛØÐºb>Ü¡¹º%¿®jѸCº—  ®JÐÙ­r#}-Í+=;îÐr+Áâò<yÆ]»vÑn·ét»Ürëms*hÒ4å’‹.¤ÑhP«ÕXµj_øÂæ:3¢TtyŠƒ’ýصkW¡@ôM*ª¨¢œ$Ó066V1c2ưuëVN<ñÄ#ê+¼ðhçά\¹òˆ‰/”$ ÓÓÓ¬X±âˆË*ªhYkÙºu+6l¨d«¢ŠŽ‚$8Ùn·cåÊ•s‚1â4ONNæÙ õjµZ1S@Gë´÷»mÛ6V¬XÁÄÄÄoº¢Š*bNÐ9ÇòåË+f„¶oß^ñè´ÿ~V¬X1çÜIEsIÚY¯X±¢bFEÏ‹žªd«¢ŠŽÞ™‘lòŽ;ضm'žxâœÒÔrÆfÁ˜Kþ!å4úP°vTœsìܹ“¥K—²téÒg¥-+ª¨¢goÚjoÌOåsEŽf¿U|ª¨ÚƒUôÒßOa²qãFž|òI&''Y±bųÎR.Íéf&'t?hñ¢dèO•Ư¨¢Š*ª¨¢Š*ª¨¢ŠŽ„¼÷lܸ‘™™™9ƒt´ÒkN™™NÌé ¾cÇÖ¬YSE›+ªh‘‡*š·0>US>Ø8ß;¥-£zUtü8 /Õu‰Óï÷IÓt^@ÿrväĉë÷ûEç¢8Ž‰ã˜ ªß%²ÖòøãsÙe— åÃó¥Ä­ÛíÒëõX½z5÷Üs§Ÿ~ú¼‘nï=ív›E‹NÄ ÑÞÜSì‡N§C’$Œ355ÅèèhUÙpœâA9Òr¤Á°,ØAÇq¡xÃ0,ð`ÒÃôô õ‘cõ™Ÿ»Ð™™Y¢zE#–Ô=w›"Iš­FƒÑÒ}ÁïÛŒZó¬ß§iJ·×g¤Q#°G³’$¡×O©a8ºk½ÜG«Õ¦Óíâ\F£QgÉÄÎ{¼¼³f‹4˰Æ`­¡Q¯Q«Õ06Â÷>ÍV—,ËS”ÖêõZ lð‚?_5—àåF_j °¢ù÷ÜKmÎŒXdc™Óhçxx/@+FÁ”W¯× çî¥ìÔjJ0­Ýn¥e/ľ•{¤iJ¯×£Õj‘¦)ív{^ý*Â,Ë ¾¿PûGö…83N‡~¿_”èUöàøtf·­ø¼ÎLÇDQD³Ù$Š"œsÄq\DB3“óÑ>Ëy¿ò{¼zÓ²¹›-mñÕÿö'$—½_¸bósõeÏìz„ÜðE.ùõßãÊ—<ëséä=üéû¿Åõô¿sá¢Wr@l½‹¯?ØâÕ?ûz–þˆW–$)û¿…¯>ê¹æm¯c1YåÐ \ïàžï}ƒŸÜõ Oíšeýeoâß½÷zYGš¥´v?¾ó=î~øIô £Ë7ñ¦w¿“WoY %a÷d»oã3ÿô]ßµ‡nbY¶‘«þÝ\{þ:^è—P ï«™ŠŽoYÀ–$ N‡8Ž?î³ÅÒ55 Câ8æÀEY»8=Çš£w°¦/T¡Îþu:z½ÞÝK¯÷ùZ«8QI’ÎW·Û­”×q¬³­µGÝÎ<Ô ÞZ[œ›‘H‰j[È `ƒc,Þ9Ú.a‡aTãÄs_Y³˜^§ƒóŽÐ’$ÃZC-ŽqÞÑïçåmqQ‹#0¹b˲Œ^¯Oš¥ØAš¾^‹1€Á„–^§K³ÙÂZC½ÖbˆÇVrá—°ªæ@xð,Y–Ñí÷iïy’ï~ë§l~Ý+Y2a‚€~?¡ßOòuqù÷ólN/÷&8ŠÀ^¿O{÷#üë7§8ë W°¨a1AH™uÎ9z½išž(ÊŸÕÚ€4ËrEÎû9ÏSðb9³ÆE!qal0ˆÎô K–¹býõZŒ±Aqï$M1ãQ¯×0@»›-ªEž¼=w’fŒ6jx ½^Ÿ~’`È…¯V‹‰Âˆl`´ûýðC œàgok-c€~fYuÚ+X5z3»0cG-Žðû÷0­ã ¿øF–׺Ü÷Ý/ó‰¿øñŸüŸ¼j…%uÏ05Š#ÆuÖ÷^yâ:b7Ë7ÿ _þ›ÿJôGÂOŒH³ 0WTQE/Œq–­Ýn·rdæqjêõ:‹/fÿþýEdVÿ9ÞìÃ9­'qjÊeï ¹Ö‘82â|:ïá0׫Ïé³Wtì“4˱|Dׇm™1Óï÷ ÃpáCLî+diÂÌì,Ýæ^ü@ù IDATñ÷صôR^uÆ"úýŒØ¥4Û³<ñý›˜ÝÂ’t;÷>¾‡ÑU›¹ìŠK;pÿzóÝÌ0ƹW¾ŽËN;ï2ff[ô›»xä®;¸ÿÉI²¨Áú3.窋OÁÎ\kßûç{xl_ªÍñ¦«/ ôŽV§K–fxçž®ÓÙIî¾ëœíñå>Ä÷âqνòjNY=JºïQnýÉÝ<=Õetå)\yÍÕlY23Û¤;½•»~tOìiB4ÂÚ“Ïã¼SǸíž'±AÊ—>üA¾.âÊë¯çœ KŠ»JÄæÌž~ðVnx©i°éü˸êâ3ˆ¼cjß.îºù‡,>i#{~€'§Vžt×]s ãQ@³Ù¢ÛÜÃã÷ÜÎ=íÂÅãœvékxÍÙHÓ”½?½‡ܾ‹ .YÃ}7ßÊŽvÈÆs_ÅõWžF¯Ó¥5³‹Çï¾{ÝEß„,Z¹‰+¯¹’xz;÷þän6½æZ6¯¥ßï±ýžpÛî•üÜugÓšÚË®'îæö»Ÿ ™BcÑ.}ík9qIæì4SÛîå–»e¦oXuÊù\}Õ%,k<;g 0²ŽëÞùo™:°{>w OgZ°CÖ¾âZþý«òN,Ý^š‰>OkW:ž¸ç#<öØ œ´È^ƒ]QEÎŒ”üc«ÀÙ<|ª×ë,]º”={öÌévö\Ÿ­}±Û…6Q’ÏöÁRk-õz}ÎÌ¿ƒ}Oþè’­Ãq`wG'é³cçÒ4å„Ö3Vo p ^«ü©ìåñM²çåìýa;Deà%B,u”r(g˜°~O»Ù¤ÕžâÞ¯~‚¯>Yã³6`Ò[ï½GvL“¹ŒOÞÅW¿øeîÞ[ç”-ëÙs×—ùü↯=ÄøÉg±Ììá>òyž˜êæ©Ó©m|ç³ŸäÆ›w³îì‹9ÿ´5ìyì)f=à!²Óüë?|…]£'sêÆÅÜ÷ñ‘?µ†´µ—;~t;“½ Ôz­µÔ'–±iÓBƹô×ó†k®bÍ¢:ÙÞ[ùø>Íýíåœ}á¹OüõGy`ÆàÒýüð“ã»ÛBιô .8c=ÉΟÒ[Çi'­Æ°˜Ë¯{×¾á*N\1Žan]ëÌÌ OÞú9>þõ‡Xºù|¶¬‹¸ùÓÇgð }çI“»þÿÌÍÄ缞Ÿ{ã+iÝwù…{è¦ í™]ÜòåÏð™ìdÝÙsÊJøú ÿ/<|€À@v/Þýun¸ñ.V]vW·Š[¿ð!>yï,Æwyì_å¿»µç¼‚Ë.>‹ñî>v¶3\ÒâÑ»ïa×tiÉhMþ”ŸÜýÝ$aï“wòù/þ˜xÃ9\vé…œ0æØµ÷3Í&{ù&ÿéï’®8sÎ<‘?ú,ùâÍ433\^\FÒïÑë'd.—ÐïÒ4OCÏÌÌПÝO33,]16çs_“ûöíg÷änöMnãÁï—m~5ž¿Túò…ø3,@Pý©øt4|ªøplÈ’É^¯G’$LLLA¬ê= çW­VcÑ¢E´ÛíAÅBú’â×Beëh³2RzÕj5Ù¾ýi}ìq¶mÛF«Õ,lÞ‘Þãp•¯×;v}î_é¼ñé]óìý¡Ÿ&Gìðl½ÕŸ—·î–óï’¥;’ÊEfF¾,¥eâÈ$IRD½ À¹Œ~s7÷ñ&¾¶w ¿õ»¿Ä†Z®yHÞJ{F‹Î¸ˆwÿÒÛht[¬j4ù»æÿÓorÙºQön_Ξ§oà¶MVoˆØóÄ}ÜþÓ~ëÿúŸ9sQ^ºõª×A§Óa§1Ðï±þgßǯ¾j#3³û›ÙÁ'¿û0ÝË×b0kÈÒ”f³O?MåUu‚¨ÁÒ¥‹±Á NÙÌɦÏäþÜú™¯0¹ü5üï{õN‡SO^ÿ›¿åG·nç­Ìð莧¼÷õ\tÆQí<®|mL³Ùâé%ãë9qó&Ö»„V§Ëôt ÈÏ%9çI{;¹ãû?å•?ÿ¿òÎ+7Òj^ÈDÐæãß¼«/8 k ¤pÊuoáÚ O¡ßëñ†×_ÎûØW¸ûÕ›Yòô#Üò@Ê»~ç—8oENo3ã­I>þÙóÚ?|=¡5¸~Ä¿ò>^»1dÿÔ"®¾ó>÷­‡xÇ[ؽ{ã\Ë«ÎÝL\¯sñe¯&éõØþ¤Ì0sÒm¹,tfwÓ[}:W\x&+&Œ\|Y’°k÷£Üú•±þU¿ÂÛ¯;‹¬ÓaÍ’ˆOÝx O^u>'Ž›bŽQ½^Úû~¸rwÌÎÎÒžÝÅß¹Ùå×ðös¸!íûŒ±Äa“›þëóÃfŒKFyݯÿ6—.MŸ³†ÏgIAEUt쓜Øh4Q¯(×—Fƒ™™z½Þœ.o/‡¬ÌBJ·úý>»'÷p÷ýðý[ïæ©ÝSô’” °¬Y¶ˆ+/<›+/»˜•Ë—Á2¼Ãq®âT,äûÝn—Ö¿ÞA}ç4ãØoßÝ=…_½ô°«jTû_:K娺™‰âèt:…–nf W*† èpÇ?Êdt!øÇÿ–M G¯WŠpØÕKÖ2B/ˈ⠖¬[Çš±:i–A3Ò˜j%ìß;ù\N1ۧgR÷žÌ.ç‚õãdiJæ,‹FëÝt±ƒóâyûÂÛïäÇ÷ì&ˆµœÿê  òxçÉŒ‡ÞØå¨mL¸ý_¥Ÿ:œ÷¤u˜ÜN´ô|®¼ôd¾üùðÁ;6r↜vÖ¹lX5¢ŒZÆû3[¹ùGÒuž(ã” .¢ÑÞÁ¿„ 7¬ïpγdʼn,kÝÎd7càì§­œÀ;‡wžú²å,Š÷óÐdÊ93»h†5¶ßùCö…çÁõS’m÷±+}#5i¸šÓ—¸4Ã21ÂÎP_Æù]Àƒ7ý3óÔÖ¯_Ï–ÓÎäŒSÖ`˜G€<Äõ'n¹€ ·|Žß°›uëOà”SNåÔ-'ãZOñèå3Ûùþ·v‘¦®7…ëìáé™+ÚOpóíÛ1q@-^Éeo¸’¥6{¦ƒ¼A—fYF³Õ¦ÕÜÏc7•ï^¯ü/?ÇrŸ‘ Q~ÖFF×ð¶?ø3®iÍòÐ-_áËü ¢ßüCÞzÞR²´R˜UTÑóo”“$!Ë2êõzÔHùÌN‡Z­Vt|{9 Õ& Î9jqÌL¯ÇGÿé&¾ý“{‹7Þ{ŒµìŸnqßãOóÕÜÆ»Þ| W]v1ª˜æ Mn¾kxïñÅ‘µ8ç =,71#`ó3ÅÞ{L`‹KÒg£©™Šžå9 Úu[k¸«¡Õ&Íä0ŽÜDÿûà cl<} ãݧ¹ãŽÇè;÷¬ʼì*?`3ˆäùM©ñ”Ï1n$­]J’¦…3“§¢L­õϸKù&òÏ\,ŒjŒ5¢<ó§ÓMñÆͱ¼÷ùú0À`cSx‹Q²îâ7óÚ‹O"ô .}ûûøõó6.Þ²šÉ¾Ã‡>|·íö„Ö·¶6`l$&°fFËp6ÀïYÚ'Kó’—ecŸ)I´.”ÃþY’àÉ•DXl`¬Í×XâµòÎw^Í“óÄÝ!r/’]Ãû~í½üÌçPomåsŸü_¼ïQh ¾9çI’4ï<6xgKN8‹wýÚ¯òs?s9«j-¾û¥Opã‚ÁºÃÐXKEģ˹ü×sÆÚ%Œxî=n‚³ù‹–l ¬Ñ{W(øf³M»s€'¾óY¾vo›~å—9oi@êü³†¹J4ÔyC}b K–­á´ËßÈ«šÆÍ÷ïçÚkLj£û¦ö33cè¶gÙ35M?[›·PœmbƒQÖn<…¥+×°´Öçóí ºü6/Ni6ÖpÑe§@š†ÑÑqÂØù¼ùmç<‡Œv·K«Ý¦Ýn“9È’íV‹ÑzH¯ßg¶¹G¿þI¾pgŸ7þÆ¿çŒÅÍf‹Z-&MS¦gšŒ4Œ6jt:]Z.¡Íß}?q˜tOM[â±%„¼8 3òt°yPÇJÔ²âSÅ££Œ/–3“¦i••9Š¢¨Téê‹—úœOîæ;w“eÍf“»î½Ÿ/|ë‡<²u7¾îÞví5ÌvSN;ygz2ƒ÷°{ï~þöSŸç¶{¢—¤|ößgýºÕ\yÉC™…8R‡sþÆ9‡ÃóÐßžè?|’8õdß¾éoý‚Z\„¨3—Õ"ùøM¿ûw<ÛþNù›ß?è{\ß*zyÄ™¶Öq £pfÂ0¤^¯ãœ#z½^1àj!†Ë{¨×kx‚0bÃ¥ïá×û7ðÁO}ŠÑ_~第ž>†F£Al=ÎË@­F=Ι"JZè`£˜“ι„+?p]|:+¢OMNpÝ»^ÏH½FÀ3ÙÌ0ЍGïóò¹F-ÆàéÛ<+ã¥eA°ü„õ¬\ôC¾ú¥eæ¤ålØr6W½ç¸ÿ/þ‘¿þÀ$çoYI´9°w«/x¯Üðûß¿ÇâÍ›X³¨N÷é»xjìÞ~Ö*V¶NdÙÈ|埿;Ë8匳X½¸ñÌKÆÌk¯;“ís¤Sç±Òì᎟<Á+ßþïXR³ì‚¨A÷®oðiö³i¼Ã½·ÝÂ’«•s…¤›/à5ÞÍ?|äcœwÞi,ξ­<é¯äzïÙ4âP•myâZL-ðdÞ¸Y~ð•Ïðdgœu«—RëîæÎÝ=Îÿ™õ,^púÙ«ø—o~‡¥æBÌþG¹ï‘môã3±¶ßû/|ýŽ6N^ÇDÐá‘»ã„K.eéâ\ó®køÛ~–8M«FH[ûyjj‚·¾ãZÖND…ŒH9ŸK;ð¿}³~ïÃüúipû?~‚ïˆX»luÛaÛý÷³ü4~égf)ÉË\”á¢]úsÇK&IóƒñHG)5oŽ>•AÑÿÏÞ›ÇIZV÷âßw«ª«zžéž}ef˜`DA‚0àF¢‰ÆÜ$W%7Á\ÍrÕOnqIòó&&Ѹ"\“kÜÀ뎊‚€ ˆ000³ö¾Ôöî¿?zÎé·«º««»º«ªŸïç3Ÿ™é®z—óœç¤SmÐý<²Ù ®‚uû®ÇÍWìBB‹îÝŽ½;záŽc<çVvîÝ‹Íý]ÐÕ¸²zˆ¡cÇ08Y@ªw3Öõ¶#ôŠÈkkqÑŽŠ¬ö•èM†pýðÜaà l߆ëÚ`j@ w`ëÎÝX—1ÐÞÓ‰„âÃó|DZ .¼·¼é6œ— á-rEQDŠ`"‘X¥“·»ä³¡JS2£i]‚E™æ],…TÓ4œ9s+W®¬ËaƯÉS9øß|*v¹^ñ¹ ‹E£ááatttÔíž•x‰hQŽ—8½*ñÒb6hoo_R¥•fË$“ɪH¼¸§ÆÆÆ ªjIÊûRCÓ4œ={½½½3Ê)’1GŽÁöíÛKäMEp_øò}øø=÷⹓ƒÐTÚ¹šdÇõpí/çÓ ‘©{*ؽm#}⌌Obht—\°½Ýâ>¾ï£X,ŠNzÙl»ví*k,ÐsåóyA€ÞÞÞi{šÖdxtïü{´ŸG¯fÃ(xH¾÷Mp¯¹¹{DêW' Cº3Ð^w%Ô0¾òtF4Ó„ùèsÈ^½ ‰¾"“†Ò1‹Å¢xæÞÞ^´··KÃf™Ú“!E&&&Dg³“§N•È0 ±º¿_ ßmkkÃÁƒ_ŒÌ(ŠÓ4Å/œIWã¥ÓSÝØÿš(€„€bá¼+nÂN%‚„h¿ê&(Q„ ±îò[°Q‰à"EA[ϼæ†mSƒÃŠÑŽ‹¯¾ jÀ#(ˆèØuÅõ¸àÊ©‹ÂA"LõàŠo˜ú05È2}Þ~¼n§2UŒÞ¾×ݼQ0õùé§Š•;.í»¯˜"V \ ½/»aó¹LÕ¹° ;/}%viê¹’õaÀóD‘‚þ=Wâuiâç~P枪…{¯Æ–}ô.!߃E0t*"D‰~\~ÃKð²s÷ƒP< ¦°ußÕØþR^ç2u/sÅVÜpËyç>?U/Óµï5xƒ ø~€ÞMâÕ[÷¾èᔢ&»qÉ«nÃ¥çj\ÂbýÚz6áå7lÑ#·sÝxÍÆ½çÒɦê~ü ‚‡MMáÂknÀ>-vXEÏaŽ–ñçrÊßÇ4×¦ïÆ n›ÙË^®,ÿ›¦¸2CÞ"ªôw³Óˆó -ÕxMãÞ3âò®·òÄjé)1w”S¨›è߆iâ5¯¼ }ýkð…¯~kÊznoœÁðè:2m´µ¥ðªý»ñü©3(æ xüàsعuô(s-´«ä¸Qt #÷ÿ ‰ƒ§Ña& e]¨o{Ô÷¼Q!;5(ìþžÌu—àì_¾Ê{îAd¨°ó.ü»ïG´w'"Ï/ûœÜx’XžûÞ4Í…©™!¬i<σišÈçóÈd2¢Uó¬¡ß(‚ºüð=¢‘.ää‡%c £(€ëÓ¾¿¾†ðËÜÚsݘNìà øïg">‚ÀŸ¦X‡¾çû!Ê>0ÕQÍ÷gð½éï¢(*2é6Xú9o‹ç•BE´(w›i´"߃ó"ë "9¢h-K˜n:–¥á ïø!*<„;˵\§ôYÜ h¸MºPr¹ ÿ7ÿŒ¦i«IJ&?ðâʽçy%Ê:ÿÎb. ©¸”3`âJ:š4˜º5Òûr¥”®ãû~ M8êyÏGA©æšDÎSü3œFüýgŠâ}8KQYêš™ù¦ù,gÄùþß( îl53å ˜¸¢ÞßÛuý½xáÄ)|åûÂÐ4a„|¡ˆgŽÃ¥î*[CBògç¶ÍÈ$Ïqpøø©²†L5û~¦ÏòŸç‹EhB"ìPú» ßq3|圌ô½©~(870¡ï£÷u×aä?AúáçU…õà!(Q(*y+E¼¥C`yî{>ÏÒ÷ýš®SbÌÐÄbª1 Ùl©TJR|‘ ª íýøÍ÷ˆB¸ž/‰"½%‡{¹©Éº®‹?3Tñ)¦”nEJ)WHëaÔ,´ÂYnpa\©TÏuÚ£Ö³¶Ç[Ò“RÁ×”uŠt5ú¡Áÿðt:â%2òxKþJ‘ú›ÞÛ4ÍŠ©i‹m 7šÂ+±|5Ί¢`|l‡½€( ÑÓÛƒ›®ÙoÜÿž?~ /Ù½cÚ5|ßÇ|†abÃÚ>çZ¿Næò5ò¬FF@¡X@xô ’P¡…¢k¬˜rp¦‰Ìž-ˆî{ȹж¯Ò™† À·tä.X‡ÔC‡ ©4?@„eMõ8$šþ¹ùµ:0Jº™Ñ!ïyžH/3 C†þ]N–ò ¤¿ãu´_ãójI/ EŸ”Ò¸±ÔÈ)UqÅë:(J¥iZ‰±QËá©(ЍƒàQ ª1$¥½Ñy‰ÓˆžŒýìRÇóðÂ?} É_„©kˆ h¿v)¦Íh`<îû>\×…ã85ñ²à.J™àyßdàÔ:‘SBB¢6C†§Y–˲–\ØÄÿK!âÅë™1 ‰DbÉ.Pà^)ýŽš»,õü“Fá% ‰zïÁJÖ¬îþ›…òÅþឯã‡=Š\. œ®í{ΞÅá#GaÛ¶®ï‡ë(8.رø¶7àCò\}ÙÅpÎu ­Õ‘R)š¸Ú/¿§.YÝ à›:V=xÙwýxáçOÂQ@S¨ %ÂÙã'qìÿóÓßE‡„Vpu« ¾þå]¿l*œÌø‘Ð4Mè=ñÆ;բĴ.‹H$¢³Y&“A±X¬ùâs;Lâé@‰D¢¡ö_\Q_̺žZÆSðLÓ¬¹hp1h´|OS$C¦‘"ìñ™Fóå%Y«Òzh…5å)BñÒTÜþÚëðäsÇ102†ÓÃøØ]_Åù›×bÛº•HØ&²y?s£¹"þâ]¿‰Ë.ÞƒŸ<ö ^{í¸hç6˜Æ”ÚuÝ«™)÷}KÕÐù‘;0ö²;Ж‹CGçžÁÈ/?„Ãû7C¹x+Ó€÷ìq¨ß{ÆÉQôD:Ú" ð÷ûºÚ©º™*žSÖÌ,?c†ÆÁÔê”ÆŒëºH&“ÈçóÐu–eÁu]Ñ¥GZе ÕàJ›• IDAT~–GdˆMÝÈ{®ÖC§Öš™x}Œa0 £ai´P‡ò\h¯# êc‘NÜ©õù©fFæü/,›©f&®„ÅëC^ü9ÐÑžÆGþìøý÷ãã9üê9<ò«çD§3(EÅ=÷Ýw¼ùþÇ»š¢Âci£ñg¨T‡2[$¤Ò÷£ €µ¢áÝï‡û¦¿‚‘wa©*zÆX_{ Ù/?? `k*LUG‡j"©PƒÚÑu{áŠe ÿËÞOîŸe×uE­>uSž+ÄÎ#Ϧªª°,KJs‘¨ß!ÉS‚¨ˆ]Ö©M7ö¸¢NÞœFîÅŒ\Å;à‘QÜÈîVëj&!QÓ!‚møç¿ücüÚ+÷cUotC‡çp=~À0L¬é_‰U+WP!\Ï›ÕAT‡M íâ­P?÷_îÝ„LÇG—b¢ßHb™Æj5‰>_G[!„Ú× íƒoþó (:Ž4N$f=ŠÅ"Â0¬9ƒ@Dfèà³m{Z{æZ r$$$fßÄñAƒ–e5UjçbtóúŠ7Ëó[=éÄy‰RËšÁPˆ{µ[å¼™í=âÝäæ=‹¿Òõ2JWîZ2M¨T¾WŠ6„4EÁ[o½7¼â2 CGoW'6oèÇŠŽv¬CÞLËxG¸ZŸ·Ü³*QåÒíP>õGP¾÷8¢OÊÏA/:PDšeK´7^åÖ+àoZ ×qžÓ'ã‘Þ½NòÊr7ìC¡óQS³1C)žçA×u‘v–Ëå¦)- wÐqo:M_o6e­ž-~ùM J="Sî"ªZ^jÆè­m½hÔH† ¯ÿ*gÐ~ªÖå5wåŒrÍJ9²ûUÛÄ¢RêR-תD¯å± £¡ «=—^°cš1  bÛærû¾533ÞÃõ ´'ݲú«÷AÍAõ  ©@W~&/ ä 5yË 4Øšdÿ¼æÌX–…\.Ã0à8lÛF6›CÏ4MÃSO=%©.!1 4Múuëª:x´öa³)qd„͵F(~¨ÍtýøÐÐzNõ¦Q\ñ›‹4/ñoªªŠ5i6^¢:ÍùN1_*çÄl¸rN Úÿ¼Ó ‘›í`_§Üµølª¸ÑË jîï(ÌåZ3ѰQjfª­5¡µ¨EÆU2&ªýN%~š‰/+£ÕÈ, žLì—œâŒkÆy&n|UŠø¸·}¡èÄi¤ªjÓó—f-ž-MÇ÷}´··Ã¶m‹Åi æ3Ï<ƒ /¼°Ä˜(WûÇÁéÓ§§2ÀT´·§§ÅâTê{n¸b%åÖ÷}œ>}]]]e‡›’‚îº.:T¶1‡ã8p§é5Õ4D]×á8ŽX›|>/þ_€0šÈ@˜éL¡gåòšŒâB¡€B¡ÏóêVÿH÷*‹pÎu:‹G%–xêx­µù%î*þÏ(à‡¥´ %$榔Uú9O j…æñèÌL–ÙæÌÄS(*Ó Å¢sÉ‹ŸËlˆ0 …ªÙy)‘;=—zƒF¨™©f½È¨Íd2ÈçóÓ¹ÁÁAŒ‹èW–¹Rèyr¹§Ý/ Côõõ‰$nÌÌTÏ344„±±1†Q’æÆÓ™N:…ÁÁÁ£Œdøðt¢Ù"M 5üq1å9§§¢(èééÁÓO?-[¶Àu]är9äóùºD x¤"+”ÎJѸrÏNŽkÛ¶qòäIäóyÝ™œœ„ëºu‹$‘~I¼ER©‰DU5g­§'A˲ÄÈ…y·fÖu¾ïöí’üËZ r$$$f?›©{Y5B‰Ú­d ñ¨L«È ’µ<¥w&:TCw*œo•(:§ft¢ÍVóC :;;1888m¿¸®‹ÁÁA¤Ói˜¦9MF}|ßÇØØÆÇǧñŠ®ëhooŸæ˜ ù|CCCÈd2°,KS|TáC‡ªâMÿÜpÇx²\·f_ï­[·âÑG¤R)xž'¢ ­¨—ëŠG{fÏž=£¿dT¶µµ!•JáàÁƒèééïûp…B¡¤Ü`¡Ï=âCMÓàyV¬XÎÎNé4_¦à)™|ŸŸö£(  àkK†Œïûxá…„áÇïL&aÛ¶(ä¯VAˆ¢§NB__Ÿø>3¾ïcxxU¯a5™­¤¼Ú¶}ûöáøñã8tèòùü¢ÔSôº¯¯;vì@WWWYC’CÓ4lÛ¶ gÏžÅÑ£G166&"Hõž‡¥( :::°cǬ_¿ªªŠ{Ë9EË ÔÅŒlyu3#EDQ ±1æÚï^BB¢zE´ ÙN•rh[Mþ,$¸—³÷H5¬f3†a ‘H ½½}š1“““( hkk+Ûí' C œ9sfšK^w˲Jf8Tû|“““F[[›ˆ¶R ÈÀÀüYæž,WnÛ6¶oߎ]»v-ª“§erCf¦µWýýýX»v­ˆ€/†¼åÏ:—ç•h=†!7µ:7J"3AÀ4M¡d©ª Çq¦¥|HHHT¯Œ•S>¹1Ój{ŠGgfª˜‰Nñ¢öZ\£Â÷}Ñul¦ú¢™j0âCòZm¨1oõ[Žoæ²çëyùºÌjÔ`š&º»»qöìÙiß) ˜˜˜@{{»ˆÎÄk$Ž=ZÖ0Ö4 étºÄ˜™«AxúôiôööŠâÜ0 ‘Ëå0<<<'×RóÔHéF3 8ÍÉàyÞ’8cæ:D“ê¡â¾Å|^Y›½|õ$ÏóJjejqÌ•ÔÌТâ,²’Zµ¥¢„ÄR*<¤Ô´øÐ¾F¸N#óÁB½[«Êh>·¤™œÙÖ‚jf Ã@{{;’É$&''§µUFoo¯˜ùF¿§Ù2eïeÛvIÍËl u¼6IUULLL`ll ‰DBÜsbbããã¥JŦA­®€Î…¹!7ÈÓ˜©öyùì«¥T*˜å Š^Rݼ"3¼à’Ú(º® Ã0„Å.!!±pŠìB2 ª ("~è"Œ\(L5(Â(‚„P¡BWpÏý¿j!”ÐÅ0ø¨çh§ž£ƒ(òMQŸ¯°XF±¡XPÔ©Ži~ä#‹PœFjèhšÃ0J¥ÐÙÙ‰‰‰‰’÷TذaƒH÷¢Hn+iëÌ¿—N§‘H$DG²ÙÀ31žça``"Ííøñãð}_ð Ú, R°Ï°?åóJHT–‡TÇÇÌYO‡”aˆœEjËG«sÖ%$–ʈ©Ç´c Ü“ø»ƒ×â¯~ªà?làÈÉ÷#‰¹ÈÅß<} þæ§ îy|ô¯óãco…î<¨ïZk½ÝR¨Ç ñ‘_½ýSÿôH §ÏüL„uç‡ùШœ‚\?cOzøô±?À_þTÅGRðð¡×!Lu4gø^i¦3¨RÊTœ·5Mƒ®ëX¹reYƒÔó< ÁqQðO-xGFFD£ž¸aÒÓÓ# ™jR6¨Æ†?ƒ¢(ÂÄÄòù€¿=tÛçñò¾÷âÇ…ÇñÕ“…”Ö´v¨?ÀŸ\x<ö.Œ ~mk?„þ0^Ûûvæ ŠÌ ‰×:Ì4G¦Üïùÿgkq»´+„EüãspA0=«ÿߟü.¾üÂ{ðF½]¯¯›ICžö™ ¸J53å ãzÊfU1ð‰ãï@8ø\Õ}+Î+ñý³ÿÏÀµç}‘W“†{誥ÑRÏ™©¶ý.u4Óu©T ]]]œfP  ¿¿_ Q¡P(`dddZLEhkkC2™Æ 7ËшöªišhkkÃØØ˜ø¼ã88sæ V­Z…#GŽL«©°m–eUÜãs1ZÊÍéi–93µƒœ4|xæœÏ(îÍ1 ®ëŠaF$L]ו›XB¢NFÎ|¡)ž)>‹DîWX—~.éÿS¼jÝßãl|—$/À„¹_xîõHäŽîŽëñµ¡Ï¢×=ŽÍ+§¡ª‰ÎÌ7=ˆ;Oêé‘×  OÁÎÃ®Ž›qqß»ñʵÁ1Ê>%rëvïÙ†ΕÖõ‚gý!ÙCÓL\µöørÍ_#2×â‰Üc@ñ9@ÑêºOf¢S3g ðÚ™rÑEQËå0>>.f¿Ñ Ʊ±±²´èèè€iš¢ð¿‡€ªª0M™LF ^¥ïŒŒŒ`pp£££%ϧë:ÒéôŒ‘™zʽÅF­fù'’51³î-]×…ýQ t.˜¨¿3]4™LŠÆ2ÍLBba•´…ªsP bÀ=‰Œ„ª…@QЮecØhôáÝ»GÁFZË๠‹_>÷&üÉæ/âïŸÿuh¹Gpmï;°iÕ(DÎò¢PqÖ=´øZ ^ä£]Ë  ð‡¡D> ˜‹"ÌçsÐ×W>+˜ôÇ`EÐÓH* ŠŠ.Eü3P°yQhÓJó'¨èU×uI¥RÈår%Ÿó<###èêêFððð0Ç™6[&‘H “É”5ff{:çS©TI‘?5àQ šÚžJ¥–ÄÓÈr]ÎHYZç‹DóÁ÷}a{ÔZÖRÒÍ,•J ËHÓ4äóùšZ:JHHÌnÈ,”P¢ÃèA€ºP£ù Ô ˜0Õ$,³ .B|úÙ›pgßÅäÂÅ‘ cÃ'ð¹g¯Ç’»¡d®A-Ì ‰ù¶õ/þ¢ÓXb¨a*€|ƒ @ÑÚ)Z]ù`!"3 ÉK•¨”ÐÚ(王 G3aFáT4OëB„¨.ifõ¨/k4ƒ†²"’É$Òéô4cFQŒŒŒˆ"û0 qìØ±²4¡ÂÓ4ç¤"aš&:::099)Rü¨%sü:==="ÅL*§¥<+£³Ÿ ’g$–eAQ1¿j^ÝÌ‚ @±X,a4˲Ġ. ‰Ú±z#ˆì°wànsFòOàÈÈ—ð£üX¥‰ójés*i„oœý߸ÖèA÷ªwcðÈïbŸ¹í‰]€¬7ʼÓÍ*Õ5TS$Ìÿ½Î °3±ÿnfpròè»?žøV«@*y!"˜ Ï?uŸ,Ž«ô•píó á™Äa£¦?ˆÕÖÀÞDÁ’Ѥë*æòLdHØ¶ŽŽ Ns R¾ªªC6›v.«ªZ1Ål6:Å[E ”t(‹_§½½mmm0MsVgg­Š}#͘™íyâ³h¸£B*í噥l]-ÑXð<®ë–È£š¨ÄT”ÏM­šç#”$$¤ASúÿj‹„«U6-hxë¦{ðÍãÿw~T׬x vöÞ/šúÌá“þ4nÙði䣗wÿ:¾ñÂÀè—ñšökÐÞþL„°Õ3唨™ƒ™  zÊœÚÔ~}ÓçñÝcïÂ3Ï¿€ëWÝÕ¯‡7õ u¹w\`W[=.سÂÇ×~÷BÅçNüOØ paúR\·îcÈB(J³„{j©Ï¨ZîËÏXÃ0„1ou†!†††`Û6N:U–wÚÚÚ„A]Ìø ÕÙFâIÏQ©Ý²ªª"*cš&\×]˜s™fÍÔ€ª€³gÏâĉ%JšÄLÓD?Ö®]Ûpë,±øûŠš•ø¾_³ /1f<Ï¡iîm‘›QBba•X:ô*ê"ĶÔEغãÇBùVSSf¦þ¿)±w<*»Ò/Ãù;ûê‚2t½ùÖ€,V€ö¤_ŽÝ»+¡‡:·;^€NmD§zOî¢×X‰ßÚô`cD7‡µ®Qþ~ÕÎÍz?jÑœN§‘N§‘Ïç§½W6›ÅÐвÙì´ßQá?¥˜QGÒ¹<=ƒ¢(X½zõ´:âUª•¡ûÈ4ôé¹ãÇctt—^z)ÚÚÚä¡£S6›ÅOÍD«xýNww÷´Ï«ªŠL&ƒd2Y’Î6—}ÝL]®ªy®øÅÈÈ®¾új¤Óé’t³åü‡ïgÛ¶qÉ%—`||§NªºQ…D난)ôg®(ù†çybú&Í— ÃPXJ2ÍLBbîÊL­¿oVð¨ W¤*) ³ÑR^[7(B7“l­4g¦Yúz쥙R7›iÎL”n–ÉdÉd0>>>-]3ŸÏ—½n"‘@*•Æþ—{¦™æ:‘Q½½½ÓêwLÓD{{;lÛ3!fâÏZæÌ4’‘SŽv3íQUUqøðaìß¿YÈú¹ž ä/‹p]›6mÂÁƒ±aÆ=SbyéI4sKÓ4ø¾_S”Nå ¥˜QúKE²›™„ÄoÜz‚l„C‹çêWóùj~Öj ;Ÿ¨ ¯qlEPªT«;Óâmšûûû«ŽB)Š‚L&Û¶KŒ™8TKoœÝÝÝ®®.ÑÀ0 d2tuu•Ü«•÷ê\ßMQ ‘ZÆ:ò웢…çy(‹˜œœ„çy( B÷”X¾¼AI©Ë\¡Ç=40+aÔpŒ„„ÄüGžbÔŠ\âÇknqzµÈ U+ÈÓÙʼÄS˜Z]!$CB×ud2¤R©²µ3ÓñsŸŸël™™Œ*Ó4EvïÞb±(²6,ËB"‘€eYÐ4M̦“(/ÃÊEÁ–3(ÓÇu] …’æ<š(±üø‚äëº59çJZ3[–Ã0Ïç…@sGFf$$êdÔ´"t]Ÿ1Ŭ’á§O«þÜi4ßhC+óð5Kä©Ön…ä s×¶md2äóùYï—J¥ÐÖÖ6-*Sî™f2<ø3Ðuèy‚ OIO ½a.ûº=•Ꙥ‚þ"¨ŒÁ÷}Ù\JB²ä„©Õ9"Œº5 f³,«Ä{(7¥„Äü±V÷Ô†1kÑq553<ÚÐJu3Q‰zDúSkÍL+ó)ÓÔˆ¦RºN£µfŽ·è­ö»Ä뚦Á²,´··—9Æ!zzzDD§Ü…rô™‰fdÐÐ2\hMÊuÛŒn3¥6Ê{/„¢FÆŒeYؽ{7 …Ççy‚W¨1䛦)Œär´ (˪U«pÍ5× —ËÁó<Á‰D¶mO3‚ã<€ÑM¯ÀuÛ»a'5<þåÁwöý)>t]Ù¢'ä.7.iÿеÈ@¦ÑT¯0׈7ŽgZËøþ­&UO8ËÔ˜„º*Ï˘!¦v]W¤Œð‚Y3#!1wÅf.ŠXâph†}Fi‰DB(és©•©…Nädi¦COQ‘^ÆiDòu¡•u>M¹™†MR±8ѨÚtÅFœ3#•²ùÑ¯ÙæÌ”[ëº. ÅQ<ùͯàó¿8‚Gr{°ï½W Ì;Èf³ŸÌBÓ4$m ÛD±8‰g¿÷%|kl^½½nÞÃößx7ö¯èÄDÞÁÈÈ(χiL}§-•DÑõ1<2 Ó4€PTíétMÃÈØ$òŽ ÛÔ‘°mt¤" s¡öáÇ‘ËåÊÎARèêêB"‘(+ïçSƒ$ÑZûžxH×u‹ÅgkÍjÌPèÙq¤ÓixžÏó`š¦ÈÏ”¨?¨#X£ï9MÓJ¥„0š«'}>¢ÆÍ ¬Û¶ MÓJ"Wõ~nrN/5:¸QLt’i(­bœÅ‘Ëàž}?<Ò†·¾ëV|÷³wãñÑ—aKTÄÀÀYŒ~Ÿÿäñøé2›öã ·^ŠûŸ=£O¼7ýG.¿í?aÃÏ?Žï¾ìÃøè+˜:„þí3øÂ÷ž†ß¶o¸ãÝxÝ¥[pæùñ>÷+zqìÐ3(¶íÁ;ÿäNl0‡ðôW>ŽõQŒzVîÿ|öonCÒ÷«6h<ˆ;ITªìïs¹>ùÉOâ¥/}©4R$f„¢(ÈçóH§ÓH§Ó¯Ý˜!…Ä0 8Ž#B‘©‘¨ïf¦}HŠh#+¡Š¢ˆCl.ée q_žJ ¡ ˲`Û¶ Ïb2ÄKD£F7h4MC[[›0dƒF‹mÐпƒ ÀäÄ(Žÿâ1L¬yö_pN&ÞƒýèYô¿¤¹á'ñ…ù¸äOïÆ'®XÉOãé¼…ö þ÷^ù·øì58}ú9|ó§Â(B±8Ž_|鳸ϻÿöàç1òƒOà½óqlXÿôé*ÆOpÍ;ÿ ¾=‰>ùGøÊ—~ˆw^?Šýû Þu×·qó§^˜„IÑ’*ßíÆoÄøø8>øÁNK Ãï{ßûpÍ5×`rr²„<ýL7¤CضÉÉIqÔlÌС•)Êc+·9%$$fV&kÙ3´ÿøÌ–FÙsdH¨ªŠT*%¢ Qß0×w$aGµ!”ÞHò‰æl}¸Á7ך¡Zß‹f~sªÑxI×õiѽùDe–JAЧaËsrá ‚F~–ÙêÞ8o ŒŸÆ#Oû€‘_ IDATÁž«o‚‰4v]º ÷=ô\{Á-pNü#½Wà×ö¯F>Ÿ:Öa…wOû‚b¡WD¾è¾ht¸ãxò…nýÃkÐíå]³ûVÞ‹OäðÆ´ŠŽÍ[±{ÓJsg‘\³ú/F‘X}^³ÿgøÆÇþt­Â对¯ì÷áÏÖ®ëâmo{lÛÆwÞ‰ÎÎNÀðð0>úÑâöÛoG6›-›n7[«u¹–—®dš&TUƒ’çU3CíUU9kñ"AÉ`Õxó©}‰¢¾ï—Ì$i„½GŠq:s©<Ï›wJP­4"ƒ†Ïmi$“I˜¦9oCf>ëNßõ}_øRe#ð’ahkkü^+/5Zá¿ÄüiÉÿ,e3”j ÔjçÌ„aˆ‰‰IäFâÙ_>‹Gÿ~q—7?‚3PpæM7 ÍJÀ+ŒãìÙa„a¦iAQ/R'EJP5Øv†Œ áì@€Bva¨À6tD¢suha„0ðàñ¦?ø#¼prÇžúþùƒÄ§þWd¸Aõ©‰‰ 8pëÖ­Ãk_ûZÀW¿úU\vÙe˜œœœ&“ãôœ¯SK¢5ö:žçÕ™Æ ¸–e +É0 ø¾/HHH,®ÂGûÐó¼%ô¤|S© aÈÌWrƒ†Ò¸–©Tª¬!S æ+wI$çñÒRöm$“IÑ8b©yI8’^õÚƒ<¥* CD ‡ïGtÙïàSöd"cƒGð…þ/|ûÐ0þ`ßlüÂûp÷<€×ï_ -;€âªÝXÙ݆á_=ƒkº¡ëLM™žµ¸üµøèg¾Œï¼©ãâ‰ÜZܹ­æ€ ¢)™L˜Tä^x?xÚÇž«±ë¼u0#ðu Šˆ¢pNkæ8öìÙƒO|âð}ûöíC6›-«ÆSÍ$$€©¬0×uŹ9¯ÈŒiš¢èŸ˜Ž+R0KH,þÁNéS–eÁó¼%QöEiš%Êg<h);Hqƒ†æ¸,ÅóPÊ=C¼Nf©»lA f‰/-6TU…mÛb¢=Ð*†ŒtüIVæ =ÝíÄ ·¾{ÒðéÌ.¼é¶ñÏO "}ÃËpçÿ|/>÷‰/âo\@Ûº‹ñ–?¸ WüÖÛñÌ?|öç?ÀUoø}lßsÎïM@ÕSxùoþ!ôô§ñoÿð÷2ëñÛøc\Ô—Á¤ºÛ¶mF›$õú×nÆy[u¬^Ù~é.üË·ÇÚ=xõûþ¯ì P(ÔžÚyýõ׋̞J†Œ4ø%Êíõ¸ƒ­¾Æ yî¨`4Š"xž'R]dkf ‰¹ÄóÍŸç3UÂ0õkŠ] ˜¦ Û¶Eä£\¤¡Ö4±… ! C!¯hè¢ëº‹b(躎D"!ò})ÊPkjÙLtšÏsÒ¡AzÖÅ2j‰,Ë*1öâ4šoZÝRÖÌ”{y^Ö¶†¤ðV;;¨\ U¹šMkǯýÙG¡G ¹‚Øk_ñ|èZ àøh_¿ïþàU0 Qà£X(ÀMîÅÿk? ]…ç:ðñ~ìä‹BµWþÆ{pÝo›PÁu]‰îóð;wìï¹ð|`åy¯Â;÷hp½wü÷K`:Tž[D±àÎë\) 5­o9Y'÷ÍòÚó¤_ÌÇ¡%Œ×u‘L&Kúûû¾/½Lu:ü檠QKbÓ4ŽãÔ’힆a ™L–86êiX(Ñ¿ih\"‘µõXcj„@F o†Ÿ%ÓHŠ"ç%˲DªÈL<ç˲H$ÄÜ×uKh4_ükf¤BV»Á6¹Ô53óå³éŽàÅ\vÚç<§ÏyñÿY×™æËNº%×,²ïó9ó¹ißÉåX\è"ë“ÎWœöÙÅ”A•öÄòoè3×AÁÓŒÃ0àºnIÑ¿mÛÐ3/$$Zý ç‘UUÅ\×uĸP†aˆº9Þ¥l®ƒ —Z( ÀišB^ñT)>­›Ó¨‘S¦è™ù,rd¹®;ïõ¥ƒÈ²,X–%ºòÅÿ4Ëœ ZÞ]b~N‰V•Û e¨Ï§ÁRñšY7#ÁÏnJi¯˜!o&áÉ$eƲ,Ii ‰8©fÔ’˜kÚ¯ñ”ø”yîõ /¥Q:)H\I¯ebýR+ëôÌô~¼Nƒ+qoa9ñVõ4`8] û5ÃÍ N'ª‹âïTÉ›Jt¢?d/ÑEÆv³Ñh>tþÕ.ßâ|%ÑZë—µªªÂ²,qŽÌ+2ã8Ž˜‰@w]Š¢Èš ‰9*3q^ºQgêÓ>Óý©e4ÿ7ím®lò×£¡Üìz(EôD#R¶g¢W¢âJE/Ê)çõ¨“¨wíô>$ïÉ0©”†W49¨~‰Ó¦ž¼§×RÖÌð³“æçHTG?ªäÊL£Ño®Ï#»wU¦G¥½*õÌåiäRŸ²j6f¢(B¡PåÍ“²$!!Ñ (øš%%€çœR¤µœ—“jlÛFWW—ÜRn–̘™w73ÊeÔužçÁ0 8Ž#fZHHHHHHHÌ|(ëº.jP'''qòäIôööŠ9>˪ªâìÙ³B2™D*•‚eY¢ƒj33TܾqãF<ñÄ€d2 ÏóDCˆVl®R-m€»òf"»wï.1ô¤®¹<áyÞ¼œÓ†fR#ýM=ó¹u-!!1³B#÷ËܺzÑI5LXºŽ((¢è†PT–e@AÏqé&L§´D|ž@<‘¢Â² ø®‹ \ü‰Ùu?à¦mC<†]Wz\_i[PÁêœB®ë#Ï¥@·l衃¢. eÏ‘¢f†¨—Éf³8~ü8:::ÐÑÑQsûÑf—‹a"ŸÏãÌ™3( H$hkkC"‘ŠL#9OçÊ[Ôýu÷îÝ8uê:„B¡ ÄhdÛ6Ö®]‹mÛ¶!‘Hˆ!ÍòÌ\žü ëºj=/cFQ±mžç #Æ0Œiƒø$$$ª;%–ŽFªâ¹o}w}çQh{Þ÷ÿÖŒ?õ]üõg¾‹œÑŽW¿åíȸõZlÌXSÆYÄ÷?ò><ºù÷ñî›úá»Ë[q£š>ò ŸÏctt£££"AÝ»Zù|¥2…BÙl…B†a “É ™L²,X–%º˜5;¨ÖxÓ¦Mؾ}»Ò+u¨Zâ j @S¥Á·‹Šº˜Ic¦²Kmše«æå{FSU2™D±X¬É¨Õ9S% ‘ÓèyR©”d. ‰p‰FYî ßÇ]‡"ß}n{ÝM¸ Ï€ëzâ#šÕ†ŽNIC…f¬@o‡(R ª.?|íëߌ•Ê1üß{îÁã'}¬X݉pbÅÕ¯Ç{Þ²4³-@ƒž_¿ûQ<{VÇ•nÇ«_²BÒÐ-t&¤Û «i¬êN ¨Î<ù4ƺöâânÏ>ø üÛ}OÁî_ ÛÏaëñæß¸«Ûe'HA§¡p”éL&§ÍÛh¥šø0Zþþº®‹¿©sY«2qƒ† Þ嬾Êt"ZI]SêM¾ïש.iSF=žÃ0„eY%aÎx3 h¹_ª£Q=é4u]Š ì0N½¸áºk°s… ×  ÂsÚüÈÁ{ñ¯O…ÀêÚ€5+lD! :Ïâ§Gl»n3ô‰ðôÉ1è{péË_‚µ+{¶ð]ˆêÏKuU(já žÏèÜq+^µ L×E"@ÕaŒÿ ÷|îQDQˆÀZõ«Û¡†!”hO<3€¾—¾é €ÇNÁ°ßŽë.Þm«W¢«³I³~¼}Ò:)󤸆!jRËÕ ´¢1CCñè7`HÑoÄ÷Ž™syF¡‘®Ùωå˪ª"‘Hƒ¦”Ì™¡¾è´iEmÛ˺¥ „„D³#„’\…ç ¾þ¿†îß¾ Û{’x17,š+ÿ þè@/žøâÇð©â;_{ó ¸?§¬í¸­_C \Œ›/=ˆ/=r_¿ûIsE¬¸äMxÇë÷ 4·„Œ™hWòæëøâ7Ó¸íÛ`)çÞ*táôÀ_ÿ—+à{w}æóøöÝßÂÞ÷½=c§qxÄÀ¥[3;.¼¿:ò]Âçã–›× …çsºiAo=*Á´1º™°Ù‹j¶]æ{ B¨ØrÅõX½¾ýÅïj,ÍÌ'!!!!1+„ð)÷*P ªÙ… .^ ð! ‰Z`YÆÇÇaÛöüZ3S/tj!I³f¨ GÓ4A ëg$$$– €œG=»ASk+M ‰e~Ά!TUE±XtçeÌX–%úÁÓÅ©•d°m…Bmmm2B#!1“z'çÌTM#I§êyIBò’„ä- ‰VÕÊ€®ë"l®ci=σã8b+YFô³ÞÞ^är9ÑíLBBBBBBBBBBBb.Pžç!Š"¤R)X–…0 KZ××dÌ„aX2°†ØÐMÛÚÚÐÛÛ‹±±1qC ‰j ™b±ˆññqôõõ‰²–(ŠDG³¹¢¤¥˜AÃ0àû>EA†ð}+W®„iš8uêlÛF"‘€®ëÒ°‘ˆmTÊû¬ÅÃ°Ü iTœ¤œ-ÞÊSÎm‘¨oÑ”ifµ# Cxž‡l6 ذaLÓrÛó<Fm0u:\×…¦›pÎJ¢èL"‘†N*•¶mÛ022‚ÑÑQ¸®+Ú8WRìªå>Wég$dAií9*}†~>Óïëñžñƒ¾Þt¬výõåÖi.<=>>^3ŸÏçjù~µ<·P<}úôi(Š‚^xaAxz¦{Wû>sÝÓõâ½ø=â|´ûe¶ÿÏÄ•xf><] MO:EQpòäÉ“£³}·žgÑBÊé¹Òs1xºÎæ™xšÿŸóV³ès9ÏZYïX Ý õŽZåq½õMÓH$Ð××'fZ†a(æÌ†1£=1«1CCkh'ý§ÓiaI‘1C©g™L===0MSDs¨ Y`|Žïûâ»t-ú¬ªªâsÔA¬5úžïûâzÀT÷5jT@×¥zz~¾iȳ©( ÇeY%ÝÚ‚ × Ã°ä]ƒ Þ8TU…çyâçQ4ÕÙÇ4MDQ$ ›è>t-Jç£ûÑ»ð OïIF&ýNUU $ äóyض-Þ‘¬Z×uEþ!ßÄ;mx4Ž>ø¾/ŒZº†¦ip¶m‹ŸMèýˆtbÒB¡ LÐsÒýùºp:ѺÐZm©1}VQÁ;´v´¡èúQÁu](Š"èÅ;0ñÏX–%:÷EQ]×…QO«ª ×uEH”Þ‡ßÛ0 A¢-§)Ñ“xÁ÷}ñ3Ã0Ä3po3”’'š¾Ã׎öшîO¼Ç÷+çaвRW‘xGCÚ–eÁu]†!îÍ›…hš&èÍå _ÿø5é]ˆ·é=ø:‘|"/Ä×uÅûÓ³ÑÚòµ$ÚØ¶=M¾ÐºOñ÷3MSìK¢+¯%$~RUU¬1É ZGz.ȉèºÄÄËtMúœã8¢û ÉD¥ ÿÛçfÄÐ:Óþ¡¿©øÒq!{¹Ì§=MÁÏ/â ’ñ³+.¸Ì­¤woÓ¿é¹9i]¹žÉéN¼AçD­Ð8ðóÎ;O0mz)Z RŽiãÓáÄnZHb´Yâ‡AœÑ‰ …BA0 Wé»ô}úãhGëMkLŸçg7½=ßœ¸áA2=î5§÷å|G× ¾"E‹†+.üL¤FBôYú?W–¸Ó…tz7¢-íë™ôzÆøõË餤s½ƒäß't¾‡fÒ;â†-7rè=âzGü ¡µ"½ƒËz–¹è´·*éôÎ¤ØÆõºwPs|6½ƒþMtâëË ú|\ï ß‘ÞÆ÷wbT«wÄ•u~&rgW5zG†pgV½ƒœ=sÑ;èûñ @9½ƒJDCÒ;òù¼Xwâ£rÎ…¸ÞAû”Ÿå„ÞAû…uü¹8Iï k˜¦)h\ö*Š‚ÉÉIñ'O*Ùwabu? À®ëhkkÃÁƒ_lÀ½Z|#’2M ¥iZ‰ÇŒNZxRéz$€u]/ñdÑBÒæˆ¢‰ÄÔjòÌò…¥çrGP~ ÐÆ¤ÍÊs§éçd€qÅ3 ½3_hî5ˆ[Ñô~´Ixd‚+YÜ*å5yÊLÓžîå‰2¤SÄ‚Œ$ÜHPÒ!ÊkžhÃq/(y°¸"Á?H(zGÆypùÎ=Iå SúWD©“ža°,KÐ’ ÜÃÅ=h$€È NÞ'î¢MÆN‚–”º/ÑˆÖø„<+¦i ºÐšñG[LÓÏIžJú= wânPÄ €¸ñD‚{6¸äÑĸœïW×u‘L&Å¡lÛvÉýiÒ‰{-iÏé=ãžGîMã‡/ Å|>_"´‰ÿãÍIøï}߯ñ<њˮè’Ì¢÷±,K¬‘¦i(‹B ä )ñ=Z|_ÅÏóP,E]!‹ü@"šÐ~±m[ðMÚȦi "eŠÞ‹Þ§P(!K‡1Ï­$áM QÜsÈ=ÃÄ{<ˆ<™ô>\yã‹þO<Í â#ú¿ã8Bi%ZÐϹÒŠ<­„xžèd2)އׯéºÛ¶Et”{ïIÀÐ{ÑZpž€|>/)ÆÀ IDAT$øÁH{”ö â;úÃ^ÞÜ8åi”ŽÀ•g:ÔȉA{ŒÒMèã^Èd2 "õGx”ˆ.ÅbQ<Ee¸âA´°m[(oq¥šî«išØ³ôŽ´W’Éd‰’™J¥/ض-äwpmËEÁ¸ƒ„èÇ W:ôTUE"‘(Iåƒé°ãrœG…¸‘@ïF{„Þ…+ŸÜóËo®è¯Òz’bH{‘u:<ùÁÊÓe-ˆfü,šœœ,áKî@áé$ƒÈ¸$åŒxž ;îé§wlâEâ¢/žóó‡+ñ‚r¢#ñÄ fZA"¤w#ÞŠ+^$ÿy´†d)Büœ¥s/•J•D‰Óé´ ísâú ñ6—™ÜéB<@z}ŸË7Z3ί¢)¯ˆ§ÓÐAšH$ÄAÇ=§ä="žæ†e\Àñ(§O«Šóßsñ´~@SŠ{¦‰yÎ7Ý‹ó ÏߥÃ×upãé$€âÑ þ‡+sÄ_ÄÜ¡ÁS6xн?÷òóîŠ\Q¦gæ)a< ÃsÃé0漯sãòŒd czâcZkRjx )™ÜSÉe]åò(^ƒÁ½˜\¤Hçiž®ÄiS.…‹®CÏWDˆÖôžÒǽŽô.´öñšA^óÄåxò”29?‘7˜Ëf2 ¹¢H´à)°œæüŒ#ù@|Êë…â×à%zžúÉå*× âÑÇrµET'Çeß3\‰ã÷!úñt0ÎODWÒ;¸×;(âÆÓÿâéÓ•ônhs½ƒ§sóº1®ð(éÜ ãzBÑ™BïÎ÷9ˆI§à†]%½ƒËþ\¼îޤÃÑ3òsGäH¦$“É’ýHzÉ}àµKü|ŒëÜ™Nú = 7&Êéü/§wðt=î #ŜҜßh_‘³„ê–fÓ;¸Á–H$„#€§U‘C%®wpÝ—ËnœV«wÄ3f¸Ã-žöËõ?·¼Ü ®wð,¦ÙôŽl6+Öïÿgï½Ã$¹ªóá·bW§éž<³9j¥]íJ»ZA$dB Ûl2Œñ‡±Ë€I†Ÿ¶,@d”PλJhs³“;Wþþ˜9¥Ó5=3Ý==³îû<ól˜îª[·î=÷¼'꺆|ndÑ(V,[†D"ÈY 3 È g‹<æ*\ r—·xóøc~`Ñ‚#eˆobëô=âDÉXܺ[,AÏ_"YZø=ùAÈ®(Òµb±XY2%·”ð\îNçac4/ô"¹RÉç3‹Îc+ÅÛsÖέx´iITŠWæq¶tøñ< ~pÓüÓÍcÌù† 1ˉ. +1<ÔŠB÷xÂ3-nžÄÃõ¸p C–¯O~àñõȽ#<´’ s.„Æ#"arÅßO æÂ˜:aK%)Æ• „Aòbðd^Nþ9 —N'ë 'ç|nù礙+«ü=ñuÂ=WDÎù^ç Wªø¼p 7&~pð0)zG$ôx8ÉZ#<Þž+kÜ»ÌÉw‡‡ÃVyB:?ô8á¡gç䞬€ôCÏÉ÷$½&¥ƒ[›y¸ÇåÊ4Í;œxÎ/ÒÂC ø:ãŸ' \ø„çjÐåÑpE‚[¶Ãù‰$Çø¾àäÏ%Ïâa'\!ákŠ{"øYÆe-=ãV?®hðkðñ‡ãö¹Ò΋LÕ4ºÁC…x¾$)dÉæ…OÈÐB{‰+5œówÎâVt’C¤ s„[ÍÃ9gôθ±ïUžKDŸ§1ñb\Îñó•ç÷q9Æ×gåû—ër%‹{N+yØèz4oaÅ›W"â2( Cû7œ§Â —=¼˜ _Ïa TÒ;èÝ„õnPà2”¿ßÉô®ls}ŸÓ\—©¤wÐZëÜ;Æ RáõÌ=2|ÝÓºOïàÉù4¤wðܰÞA: ûÜàJžÎJÅbž4îñàz‹ö'¿Dæ¹ÞÁç‡îljîDz?ó¸g€Öxzâz×±¸Q˜îÕv¾ö8¡æ^J© ÷:‘Þ®ÂÈCz¹á“]þ¼¼`¿n%#&7ÆUÒ¥i ‘\­Vïàžî°ÞÁe$­2²‘~Cë)ŸÏk™ÞI4jŒÑÓ9™‘n¾ùfÿòË//³Lò¨üßÄœxr&/éW©,!/¥Éÿ<½\¾°ÃU$ø¡Ä­"ÜâÄC5h|á\h„-9áðÚ@\Hñjj|Qs¯?ÃÕPÂlšÂ¿¨Ú¯òÀ)鳤8pWe¥²‹áŠ9¼<'œxEZÿ´ÞÃVP¾ÿ¡lá8_îñà;R (.;œcF˼&<\‚ˆ,óå¡IáýÍ•®0sÏ1'Zü=Ñ»âJS¸<,/êÁó{*Yò¹gà×ã¡‘$+ÂeNÃ¥òÃ%Qé  {¥y¨%÷dñ0!žlÌCb¹BBr‘W‚"ÙnªÈ­½áðk^ÓTöžÖS>Ÿ/óÂò*ua#[È ÆKso­[î1æ‘᳟1¤ÐÃ%£¹'’Œ…B¡L±¡wÅ÷׸q¯%Š¿‘¯…ðØy®/6~~„ šžÞAò'ŸÏ—…Äq¯m¥Êœ•ôŽp ×Ox)y~~†£oÈ@Â÷<íR©4©ÞÁϪÖÇÃWÃ.ǽ4t=®£WÒ;Ân¹>Ê÷÷àÍ”ÞQ)M‚ë•®ëâĉe:ñxˆD"èììÄm·Ý•»–¸«6‘ÇqÇQ(Ðßß$NÖm™ ¾l6‹¹†F6FïZƒƒƒ3Þ`l*Ôjùn#åMÖD"QÖº.2CU¢ÑhPÆ”×ô§.µñx¼¬ª€€Àì;$Ä<‰9ZÈs$æIàdîA^î{¦v^©•tºZÆz2ÉŒ 5 TÑ­R³æšÉ ÕϧҴ¨Œ"• äåGÞ—c&«Ÿñhšj/{>“¤†“ÞD\`aBQd2$‰²¾‚u‘A³ª§Í8o.& PNdxÁ¤™¥ 7ÿž¨`å(PŽp£Ì™+¯ [-˜Ÿà M+5°¯‰Ìð I ;ï+H€À䂚 þ§&<\&ž1Gs{-U ýáÿžï—÷Æà²q®õʘLÿá ©©ëàà Ž?^ÖÉ|ºÏUUÑÚÚŠåË——5“xÙ¶4>räòùü´¿¾‰–-[†––õ³€å5­Gj3%2Ã;‚SPbìõ2%…®L T@`æ ³<ü(Š4_9®¸ò¨ù^DžªþzäÈ;v ›6mB<Ÿ1c‡eYØ»w/¶mÛ†-[¶ó<žòèy²Ù,žyæ¬[·ëÖ­›‘wBcèééÁc=†M›6¡««Kš UU¡iZÝ‘`e}fÈÝŒ¸þ¨)&¹LjW4ÉPHmH™œéüŠ™&2¤OЪªPŠ¢äf.“þþ|ßG&“ÁÁƒq饗Îè<ÏC$ÁƱmÛ6œþùhjjšÑùr]K—.EKK ¶mÛ†T*…H$"Æ…eYw¦žžje.EQw* Zú¿j„ /é\éw$Ô‰îKg¢g ÍÞZﵪg#¾Ï­€±\©¤t¾PD4ELSáøå¿wùB Éd º$—ýžžÛ´lD ²$ÛÂÀÇe;ˆE#€š®e–J(Z.ZÒ1H>àúµ ²b±ËÚšãð\¿â½ÇA¡P„ãzP•‘Ã4fŒXBÆ«çyÈd²p} ŒAS´àÝ Œ¿.ç‚¢%”ѹ5?bŽ&Þs³)GM’¤2OŒišð<†a ‰”ç3È£ë:¢Ñh@êŠÅ"òù<4Mƒa·f6šÉö ýr¹ÒéôŒî["Œ¦i"ŸÏÃu]äóùqe,Ëqœ@‰œ©ýCß², ‹EضèâO\÷øÒ÷‹c…ñ¯[*™ÈåðÀMŸÃþþ+¸ûù¬¨:R¥b.PAdæZâ Ö…B’$!N½Üں瑑HMMMhjj‚iš#†¸Ñ“¹8'ãuŸÜK7?ŽãD1›Í–ETLTx¢Ò{šî±’§®T*!ŸÏ£T* áµ€AÞZ’”{V T~1ª~ARøV¥$²q$8¬’9b¹÷}K¥À³£ëš»—ÀK0Í|σ~ hílEîÐc¸ïñ£xÿGÞŽÍEaø(ÿíOqçngn= )g=ð,–®ê|@•³xøö_¡cÍ)h²{ñëÝCò‡ñÖ3Û`ÀÏo½oØp&¶j:¼Ñge#ŠX4ø2ZººÑ,)plöàqÛÿ½©uØ´ª {¼ =uö—oBÜÀ¶Û~€{‡;qöæUPÌ!ì||R¯%†ÀEKw7Z AõœðZûŽcbßC·ãÞn¼è¥çbmGª$Á‡ Å=Š;þ÷×h[ºΑGq÷O óOàœ´kèyÜþýŸb¿¾ [Nmá'~‰ûÛ¿øÀ;ЉQOL ˜Ê…£ãd±ç±ˆvžCw}¿ÚÓ-½¯|Ík°umû˜÷jš&Šù<}ÿýð¶\Œ/Êb—7ò~}ˆð©Z,Ub®k \ˆó"BçÆZ"ºeY°, ÍÍÍAjʈÅb°, Ùl6ÈÓ¥¨ŠÙHLj]sÕž/Š0qâÄ  EF‹º»'àL ðWFVí8ªÝ?®ïãØoÄà¿ýnÉ‚ó'bч®‚*ÉUïÑñôJ!ïˆg¬œr53îq]Åb1°œT· F­ Ö0öüú6ܺ«õ‘wá””ÇrÒ¨ÕEUdDWœ†+ßöV$,žïnüþn\ùÉã¥ËSè;¸ ·ÜøŠ]ͯÀ«_û"ìúÃOðÝ› ¿ï=8½ó…’ˆ#rÈßÇ¥ðºWŸ)óˆðÊÔ¡L ,ˆŒÀÂYK<ÌÇ0Œº­Œ íÅãñ wBUÕ <}®¯9®”Oô9Û¶‘ÉdðÜó;p÷ÃOâÀñ”,ª"cq{3^~öxñÙg!‘H”FÃ÷™ˆÔBÖªù|©TBî ¶m?’¾ù'BºúøÍU݇ÿ¯Ì†뺬”eyjžZT…BªªÂ0 ”J¥ §£ºÅ&A–M<ý³p°¸ü§`c“Ó,ßôH²ŠEíËÑ—af$Dã­h^TÂÊ–ÔÙ1âHÆeôf-HÑß{ 抳pZ³m®Ü†³×¶üKÖÑžŽCÚÓäÑÈ+ ®ë`°g?ö‚ª«H$:°xÍH”ÓâTóK'ðÔ‰ ÝÜõŽ[.\ÏC{§ŠCÇB{Ùl^ÛŒ;~|¾¿÷tœ¶jV,_dB+#v®ë¡˜éÁ®Ý‡aû€a$±xõª‘ßKVvu!ªIðƒên.\m5^¼Ö€kYðÕ4–¶Èxz¸Ž«ãóH¬X‚ÜîçÐo¹pt,‰âÀ](`ÉHž »˜ÁÞÏ!SrÑ ´-Z¨&C‘€ä’Sñ–w¼KË»ÒÈ~嫨¾óÖw Ù÷F ¢b¾Ûî¾ ­›®B‹n!cÙðáÁ±-x® @ðJ}d ÃD¦JPųR©TØšëJn¥êa•>£( Š¥n¸å6üîÁmð^ÐHI‘ž<òÌl¸ç!üÙ›^‡ëO” L×X!Ið%@­Ö'Û.ÚA\Ràû#äÓc-"ü ÉJcûDÈNÛ¶aFU!™’êÎK"CŒ)Xœ,:IY†‘jGÂõÐ{ð0œõ]ðCùFr\$IQâ}Y–‰-lD9W¾ïBR}xž ote›AV€àßô}/¸|¨zÚà!<½}$M°¯]·2 ;#$K‚&$X½ÏáñÇ ŸDjÙ‚3×¶C‘Rxõ»?€E=‰ûáîŸÝ‡lb-®üÓ·"Í^‚¢hHjì|öd]®Źm‹°X|I†<:æ2–§j|öè}}@•2ÜþxüñC#cò}HñÍ8gÅb(þ ½cbšg÷ýûúJð}+ÏL`ëÆ6´'€˜ÖŒT0ó&,[A[·ŽÃù"\Ïü‘w/«:ôìã¸ëé –Oàö£Â6‘÷òx⎟@Ž_‰W­n“g#ðÂ^Xx |å PÌŒD"Èår°m;hØ=ßrgx²çy¡#DZvõJtv´’Û²ÐÖ’F*™@±TBOß dYÂÓ{Žàsÿq3þâÊ×àâWœ_Và§!©uþ' £3m Çï~ Îî#h~Í‹_Ò E–¡@‚ÿ…BE¾‡žmÏÃϗбuØF˜…À ,Üý‹ÅÏçË¢Áê"3Žã ‰”åÈ0©6gÆ÷<8^[.»íûnüÖwàýÕ_àÅ«F~:# IDATZB —u7Iÿãûeù éÚ;Cºÿ)ìè9§4©p| ÉDt,à{>ù½?B–:Ö]Œw®ri„L¹ž‹c²ɳP,æáFd©EXÓìã˜q .¿êÅPL ®ïÃ0¢ˆh2²Ã(JkÎ|1–­·pÞðó¸åß¾‡w¾¯ÑÀ³P(á¨>”Ôix˵ë‚ûùúz £Ã­7ê{Áó¼pFš:±ºUÁK+ðÚ«.„nYp<‘ˆxTÇ`¶<³íÀ«Þð6¸þhcLYíºXuæüæÁ#ØdÝr¾—Çàqí[( °M­é"ª‚ô¢-xÓÕ]pe ¶í Óoc¯¢©mÚ†ˆi­á;ÙVÁÙN´Ä<‰9jä¬yâå˜I2²zèºx¶¨ïÄlš¿É”ýñò>*y=ŠÅþøü.Ü~÷ƒxz×!|ñº÷ámo¸™¢•K»qÆ©k k*ÇÅáã½øÞO~…çvíG&_Âÿ÷´·µà¬ëGŒ˜8·®’¤ÚиàÚ’„]?þ¼OÞ-[Bî'ÀûÉg PEYHp}š®b÷Oï€óÑÿæÛ_…5Ÿ{/|×wLÕÌ›ÀüÖ“ˆk¨ªZ[ѱJd†wÞ¤òhôwªn6ñ" |(‘&¬¿è]¸Öû¸é»?Dêý×byD‡ª®$!bD )# ïÀˆ‹9у0)I’ k*TE†)IPU «Ï8›݆ï|ã{xå›Ñ©e±û€ŠW¾éB½,éLQUD4$(ŠŒˆ®A–GŸOR ¨l¢$-]H÷á÷¿þÚ6t,Y‰ ßþ:<ñÅÿÃ×nèÃù§/‚beÑsä0Rþ/Y¶ßþÎ#èÞ´K[¢(î”®X×ö|7bêøýコ‹–/G:Vž¢i4eÄ;ŒYQÑTõÖ$ ‘ˆ]ù»¦4áeo~-ýüñ¥ÿ›—Awóè?²ÞÒ7â5/iCD“‚jf²¢”{¥dKλ gùïÁñ~<ùðýxì™ýðÚ7`Ó©-H´®ÃK6w!»ïi³Hy¢?]×…ëºeÍnÃ?¶mŸ£ïR£ªùøNé¹èùPE*jZ;ˆ ÓΗç¡Û²ð£ŸþŸúòwñÓ?<‰B©EQ jÙöì ûnôùùwUUÅ{¯¾]m­€gvíÃáã½ã&þ7‚ÌPÄÌp>‹âg¾‡dÎD§A$g#uÍ%Z“ð팚’çC¶]´^r>Z$i¨ˆG£hýì­èÛµ%«•Æ*ö‹0dÄb± L=ëWºùæ›ýË/¿<¨BîŠû¥ôÜsÏáôÓOŸPÈH’ MSυ匄riš €ë8U’ïÁv\Èš>l{dà’¬@Sx®×ÙDº¦¾ ÛñF¼ UãÝí}8Ž €¦ŽôK±G=²ªC•GîëA‚¦*ð]¶[iüMƒÔ£$+P•r"72>„Æ6N”_ËsaQþ%¨ºlû…®Ç’¢AS$¸Ž¸]Í“ M;&Çõ‚gvl;(?=æIGç9¶çŸ¬ŒzÏØý_x· 4Mçy‡X6›…eYhii™6Å“wÌå½–:>.)D¬)WŽ~Gÿž 躎'Ÿ|›6mª«ão5Š%Ÿ—jþ°‡Ï៩x~MÓ°sçN,_¾|ZÞ _3•æ«ÒZªä…áýAhœ3™óàû>>ŒeË–4ÙDM2ÑÖÖ†h4*„aïpß¾}ÐuÉd±XlVä麎íÛ·cÆ õŸ€¬Ø#ž‡;Oýë¢Odßu<µc|âYÜõÐã(–Ì`4§’øÆ?~Éx¬¢tÄHÁ~òsÜðÓ;Q*ñÞkÞˆ+.~y°wK¥2™ †††P(pìØ1¼å-o)36ÐxÉ(ÑÛÛ Ó4±~ýúÀ8Á倬©Øyû]ÿòßÑn+Hȯ;ú÷>ާ„Þ~·>üuK¡þïßÃínƱü6–~ùw°5p\ä>øZ¤>ûN dye¹\ÃÃÃÆÐÐ6n܈eË–ÍkãšÀXd2™ Œ½ªª°m===(•J“~7‰ ³³·Ýv[yifróÒbⵟù¦_¹0M—ÿ,Ó|áßLañLNp`ºå]`MþÝÑë[fe¥Ç )C®mÂ-û½3‘…c•gTB`¼¯7•¯ºŸz6ð fè‹Î˜y²1Þ­ÃÏ\ñÎæ9ø¾cŽû¼¾ïÀ4±óê8 y­°²&3´É0ÁK~ :”é° +íôù™PFypñ›{cÂI’‚9¢°á"'aO'{$§;¼j:úÌ„›äUòªÐgE ~8á­Ôhæ;¼Žf2ídç…÷—@íĺ’L›-ã/y}¢$ü䲂3O[ƒÍë×±Müâ@•ØŽƒB±„Ýcˆucî1²–|ØŽƒ3N]ƒ¦ß=Dzðüžƒ#aùîUMŸ™jòЦ ù¡ˆº>b€Ö&¨×]5BR,Žm–N’w¤ˆgYèxÏ›0t×ÄŸ:(2ô{Ÿ‡äy‘u<¹&új-Ì}Oç?gjE™)•JA«D"|>?Ú%^©»ö³€€ÀÔÀ½-áúUUƒŸ‰@B‚xÞW*|í°Çf¶’¼JŠ$ÿ¡ßSwaªÎ8Ù…=!¤hqO ßêÃqgÇZâó^K·ŸG,«ëæC=ýiš&4MƒmÛÂÒ$ p’vR ¹J{•šÌMå ë{˜ ð°¡ÙªTpO ·ìÒø9Ñ›ÊqWÖiŽf³âöX…Éž¢(eÉ—õÎÍ7¿ýIäXÄÈ Ì¤¡c6Û2¯0$8® Ïó¡) ÞqÅ¥ø“‹/ÀÀÐ0\Ï«ØÁmÏ¡ãøù]·aËi«P4Møâ±èho¼Æ™ð÷×”)@ÃèùÒ’„¯«ð<š¬ óƒWÃÓPNd ¼ïr8Q¾eÓ³9G•¡d™U«Æê<ñJž²î’’Då%)wF@@`æA® ÓßÉ»¶ˆ7<üЇ}Ñi”e½×[ù¸G@–eD"‘2ÙÈ“{ø=§Ë“5Õyâä…{—*ya¹–èL ÏS#×ÁlSÂÅy9u™0ßæ’+ìzDGsSŠ"ãÈñ^ %4Å£hŠGbVôN_·¿øÃ#¸ëÑg i*d𦠓F:•‚ç¡¡a¨$ëEÖ”€i$’l8¿dÂ×GzäIºõoß H2lÇ…gZ#5=fÿ0×…®¨#)¡*m‘˜©Tæ&¨èX½Ž“²>3¥R©,韔nQ L@ ö¬¥ˆÊ¼rå3ŠçtïE:ÌHÀȬÍT•Œj:NWó}ÞqYaœÈð°)Y–F'-€0sÄã~gƒ—€W‡2 cÖ­%¡¸ÌWY^éÇó<¬\¶›NY†rY|íû?ÅÓÏ=³T ßÂH´Ìàà ŽŸ8Ã0°fù"¸ž‡’iaqg®yëqÓ?‰+.~9J–5%cÓxy,že#ú²3‘9½ŠíÁލXúËgpüï¾þƒGaË€'Kð$Àò= õ`Ï7o…öåÛЉB± = ùª àÙθ¥ñ… XØà¹•õ:PÆäÌH’„m…s6Ôz˜ï‡WÒéÏH$2«ö_%B3“½D€ý)lJUUD"‘YgÍçãdxµ9)æÆ(Ã0‚ܧٶ–hÜS™/A0ÿ0Þi¥}MSñÖ×½ Ïî9ŒL.ÝŽâK7þ/¶¬_ƒ5K;hÈL<½s?ú³yüÝ»¯Á9gžŽ»}Î?kÚšS£ýeÌ‘|”ƒJD#að ïDîâëuuø ·>Œž'÷ ÿ§CÞ¸’ªÁÞwîOBÙ¾­Ž„&I…dæ ýó_Ã]Ú¯P¬šÄˆœ™…µÇ‰s(Šœëu“²C"bC¡È™¨ï`¨ö³¼<²çy³Nùlä¡SoÎL¸„4™ð5çúüLe-UJôF£³VAà¤x*UÔNv¬½è3Óøyœk93•z¸Çýÿ¢Îv\ÿ‰÷â]Ÿú"<ÏÃP¶ˆ;ÞŽ»‘Ÿ¾ë²Œ[~q7Þù–Ëðùÿ =ß÷‚&´çÇ»WxìÕ<_‚®ªð¼“ ù>ÔWl†|Çàu5® Ã:< ‹}Kž·Áó<ºŽëÞý6ì>pÛþ¸=}°]Cw[+Îܰ+—tÁu\¸ãÈJÞŽ©ŽwÌ;õ}H¯;ò†åðÿçඇ€=G¡›ÎHoEº[ _´òÛ.„{þi°J&ÜQ9­‹‰¼2 ¥R)ˆ›RΌ뺋‡*Rxc5±ð{Ðq5/œ+wxŸ.ùnäI92sIQåM§£’Wx-éº>ë½{•ÖÒx ò\%(ý®ÒgêéS4ÙõøßÇKç÷­æþák„ Y­ ð&û|ɵ•Kº°bq<ß| Œ±,»&Ò423Þ»ð}~Ñ„¿¤ þ‡®€ò–  €lÙ#ãU «îò” . -«t}ÞººæÂé>ôg=ÈL¸‹85RãñSO=%f]@`(Š‚U«VU¥ÐPh"‘ÈœâŽã”5G¬õМì{ᦡTk.Í* ¿×¢\T“¯È«à‘eKÓ´9·–ˆ¬Nµ¯ÎÉ4NLFXùçxþ—TñWÇ«†è‡¯Eß§³<¬ðVú,Ýw¢{ó°ØJ{¸–k774ΓMhªÍ5 ïíZ»Ü©ë£êJ²áÆÁ“õ™ »–êb¾ãÀàt¥`v¥*}(:®×p#ßðØDÎÌÂïk‹Å`šæÔÈŒ¦iA9fEQ`YVPY@–e¸®‹7 ¶, 0 $IB.—«YšKaSáç¥0¡©X«QnÈè2çÈuݺM-sD׋¤˜že¾—m¦÷444„l6[ÖõZ’$¨ªŠööö çÛxD€"Ó4100ôâÜc±Òé4Ÿ “òÊ躎t:!bVFÇeYèïï‡mÛ¯¥ª*Òé4âñxÁ™Œ4ÌuÙ_éM¥³y5ëÉqœ1̓kïLÕóFŠðpXAhˆoÔ+ 2ã84M YZ#‘H`…ª; ª‰Wç–)jX;—…îFVðâó4Wr@ÆÉÒF‡Qpk§¦is’ðñg¡ƒùJf\×ÅÁƒñÄOT\Ï—\r ’Édð»ñB/H1ìééÁý÷ß_VáŠ~¿qãFlذpüøqÜ}÷ÝãÊ]×±uëV,^¼º®éDÖÇqpäÈÜÿýã¾#UUqöÙgcÙ²eUËŹL`ÂÏGÍjMÓ Hæt¬%ß÷aÛ6ŠÅ"J¥RÐHx²½Ãe5'¨–eM›®Gk¿T*¡T*Á4ͺKñ Ì/P™z«™••f¦Ð2Ó4åĶí9k1˜Í wçÏe"ß§ÑÞ>OÔ=~®ÏWMúÈ">ÖÒt¾ÙòlŽã ¹¹†aü,Þ±c6mÚY–ƒü°ðÚ'baYŽ;ÇqÆMÓÐÕÕ…b±Y–aYÖ„¤Âq=zétz ‘¡ñ;ŽÛ¶±{÷î1yNaeÙ4M˜¦ Y–늅Ÿ+䇿”¼aD(LÓ HÆt4çdƲ¬€ÌLÔIÞ+/ºAÄ‹¢é$3¦i¢T*Ä©Ú0Dù ’#$Ÿ¦ä™Ñ4 žçÁí$Kî]×Ë\?Â3# PÛA3‘òI (ÏW›Ë‰ªZ3ÑÜL4OᙾïÏɉÈL-Å&ZKÜ+CDf>¬%UUƒ5TË윙jö>Y!›ššpâĉ1IúÇÇòåËÇ„zqL h.—É'ÆX4=ÏCGGGཡ^ͧïûèííÅðð04M $ŸˆÈôôôàøñã*¤OX–]×˼’“½¿Ù”33Ù¤ßѳ577c÷îÝX²d LÓD.—C±Xã5kä˜h-X–DÙ´´´L(s©Ê±cÇP,aYŠÅ"²Ùl NǾ&/mÛÇ*é&tÍ…£'Qˆk¡P€®ëS3£¦5’$¡P(VÖù h ÌV¢3—*NMöL¤PMÕ .áY)v®‚rgÝP“¬Âó<ür>†7˲ UUÑÜÜŒ¾¾¾1ÏgYúúúH$ iÚo ÆÐÐÐK¼,Ëhnn.#„ÕìË|>þþ~$“É L<íGòíØ±£ªçä}êæ³ÁIæÚµkñøãófY …BAh¤çšö —Žã`Ë–-V €D"UU±ÿ~¤R)ض„€‘§o:r ÃÞût:¬Ua4_x ®Ar®î03 'K$õ…’qt]Ÿ6–. °I ꤨϢΫRMåЛsÄ­¸˜#Rf*…"ÍuBC‡Û\ 7o¼¼ÊWKK "‘J¥Ò˜g@gg'"‘Ș<("&öÊø¾x<$ò×ÒçÈ÷}=z0 š¦dÆq `hh¨&RZ‹‡m®#™LâÌ3ÏÄÁƒ144xe8‘œ®.MÓÐÑÑÕ«W£««kB"I!©§žz*<ˆýû÷#ŸÏÃ4Í1„é¯$IH¥RXºt)V¯^äl‹&º W7"93¥¦™<ÌL’$†”@Õu}^’³eóÎ'CX(5òZóMþ42|f¾yøÂÏ5ßZÏš¦!‹!•J!3¾ï#›Í¢X,"=ƒh.ÈKbš&>†pòf»åL4Oü»¤¨Í§y¢œ‰É L”ƒn<7ßÖ=÷*Lö|';g†{2EŽÎÖÖÖVœ8qb̸ …2™ ššš`F™·“zS8p bÇlEQÐÔÔxu(\¯–g9vìÚÛÛƒ\Ïó‚´Z{%Õšó4ûÌÔZØ„ÞñÉ0Æg¥š?’¼ÐLÎ9‘Ë|¡g.,äóy´´´æº=3´ ¢Ñh44„B¡PñÉd±X,Hà¯f©ªT;£ÄõÞÞ^¤ÓéÀxäÈض¬7ªB“˜›U¹D¿“Î1ê-Ó-sKõàÉ hŒ’Ï•šF!ïfñ­]oÆ¿>ÇwkDZã_A\ÒáHþ}çøç‡$üä©ÐÌý€}ÅøúS§CµöÀo°JÊìZŸódÈš^û(¾þü%¸þ‘nzb úþ Iöõ.¹;[ÖRÅÃBÒðÃ#ŸÁkÆ×‰ãé}‰$|ø3°gæ¡©2¡¡|UUÑÕÕ5æùèLîïïJîRÒ¿eY¨XîWQ´µµD¦¢+Ë2‰Ä˜ѽ½½Aiáááá1ù9š¦!NXn¹Ú¹X˜ â"¥R©îÐÒ²¦™Ô0“ú9¡áqÝBèÔ§t†-u ‘ â_w¿ ‹²÷á¬Ö·áÑâvüøàÇðvÙÀ]’kðÿðéÏâ‹?Šžo ¾äó¸·çëxUúr¸ÚrÀ÷¦”ò¡ãɉrfxÎA#›KŽÇwñÕ]WbyñY¼¨íÏp_ö.üdÿ{p•C"ý:xÓ¤®“±h"Ù:^ÎÌt®¥Š…Á·~ ¥ã_Å)ÉsQÛq{ï ðì£8{ÍmÈùæ´xh¸¥¸Ú9:Ù}fªµÈóB‰D©T ƒƒƒcÈGOOº»»ƒÜUÏóP*•0000&Æ÷}$“IÄãñ ñŸ‡pTš#Þç!#“Éû®X,âøñãèèèÀÁƒÇTM3 #è Qi×BZ*õé™Mú†0ê LŸŽ¤(J Oê‰4¹5'‰”ÅxRÜ{µÖÚIÎT¡H v›{á߇S›^‰W¯ø6.[}+Ž{ÀóÃwà})òj wÿ7D¬}Hƶྡ_CÉ=„ Ý‚ª4A–# UÙ§{Í•óé´È+’‚¥p3ÛqnëÕxåò¯áâU7cŸmãhöH¾5­ÊQ#<Óç.AB¯;ˆÜð/ (:Þ´êxõêBÑ—âÞÌÝ­}€¤Lû>ïçj‘UU¡ë:º»»+zgr¹†‡‡ƒ&f«½ IDATƒ¶m#ŸÏchh¨¢‡®¹¹9È•©6wM–e躎T*U–æyúúú000€¾¾¾2=€Bä ÃXÝÛ炇y!{ó²,Ãqø¾b±XWŸº²8 ˲·5UUƒÆŠÌs¡àˆ¹màÈQ¸ðÑ®¶ Àwú°É8éuw¡hÄ•íŽ^µw=w®[þM|ïðg€Âc¸ ý/±¨õZ”üRßu6~2*íE« ØJLßB»ÚŠœHö H¾HÚŒ­‰“5ϓљ!»1߃ ZIICNR’À: I_6­sÃÃñæ‹BDdFQ” a?‹¡X,–}Ʋ, ¢¹¹98—Q,Çô–1 MMMÉÌDóFžI’‹ÅÍfƒÿ'ï /Çìû>¢Ñ(‰DM{ùd%˜Ÿ,¥](ï3o|˜› &³S.à8 Ã@,+ ñð}?¸‰€€ÀÔAåf%Ô}øˆ«M°Àw Á…å™ÐHrTtkc $YÇgŸ5ÞÛú6üÖ܃åæNÈÄï}>Y3q>|ßiÈs6âÙ¦Û#ìÃGBMÁ ù$ø°¼T’‡é»£6ÕÒÙ*?«Ãdù>\)£†•“‚XH?•æc¶í_“ò ;ŽSWC^€yfˆÈ¸®ÄÌÒ¿I( kƒ€ÀÔä°oÄ~òá#!xÊðÈÁ`ïÎKQtœß|)Îh,_†‡Ì8pâëx÷Ò¯ ëËØš~î;öOðóâåñ³ÐÚt2ž 48á}²“šé”9>|4+)\¶ü[xèÐßâéç/BÁ+ámWayó›àúÒ´Õë +šÕ&G‡ÿo&”U.[òüáЇñï{ß]VÆÖá²%×#/€oÁ?É{j*Šs£‰Lµcà¡fä¡Â;e¤ÛuÑÛÛ ]×qäÈ‘1„Ç÷}Äãq$“É€`„“ÿ«é}C¦¦¦qË-˲4ÓÔu½bEµFÍßl#ª‡”uŠlBOOOÃæg¾€¼€mmmèêê„FèH`*‘™1M3pOSbªªªð}_ô™h HÁh¤÷Áõœ—º§Ÿ¶ž›‡"Ɉ)Íp•üÑ2ú¼uõ­pÕ.HðqVêœß É3Wš‘S[Ш~3SíFÏ%N·—Ƈ—¶¼ [’ÀóŠP$qµîhøÔt®NÚê½õ™Î<×w°.º‹WßÇ‚ìû0”$Tµ î4I u0QÎælônU;&z>"3MMMH$‰D6›EYµ1~t:h4ZFdj/5ò€Å‹£¯¯o̼û¾X,†D"¦zK©Î7…ŒËª#GŽ §§›6mB,‡^hž …vìØB¡€µk×Ö'!0? ªj²Zo~¾ZéÐp§¬Ó°VèÓ…¤Ú¨íLQA0hRš¶(PÏIEZ[üÞÃì ×™©þ"2d$µÎ1$gºÞ©®…™¨øÆ×R\IJjÆÖL5s4[• ZÆEUÍTUEww7z{{ǼSÓ4Çí-£i’ÉdYˆYðŽX˜x5¡fŠ¢ ‘H ¹¹}}}eãe¹¬!'}¾Ev¾ËóL&ƒÃ‡ãÒK/‡]…yò<‘Hçœsî¹ç¤ÓitttÕ¬\×E©T òö¦Ôg†âÕ¨$3Ý€Üࢹ•€@í»ÖСù€°We²0³‰ròæ³ÄåêxsPMèÒBËÕ¬¥¹ÖgfÃy(Þ|VtxÏMÓ°hÑ"ìØ±c̺¯ôü’$!™L çxõÑZ÷5ñ”emmmH¥RÈd2Á}‰ZZZ‚{Í÷¨zž-ŸÏ#N/CC­dƶm”J%äóyxž‡|>„EŠ W/âFÐ)yfEA¡PòdÈêBql9ybû|TÔeY†,ËSŠƒw¶ŸosD9 ZQÏ<‰™O½WÆ#3óüÓ³™I¥RˆF£(•JU%îSoR ëÍŸ¢u©( âñ8N?ýt‹E8ŽY–aF/C=èDúøF˜ðº]èºyfLÓD±X„eYcBŠ…¾¹ð@rOQ”©{fǦi°m‘H$¨,`YÖ”“yʼù|°‘A¤ÚçÏÚ<ßç¨ Î|ö`‘b=×A­ã  ž3ãUã÷‰ÅbA¾ µX¨4–ÉÖBÍèïÑh4Ð(QW×GJ–×Ó©»Qs6ßãDß:ÊÂjmÛ†eY¢ïŒ|߇išcδºÈŒëºÛ˜þN,lI¨ÿ0œïœªªA…-ú™l*ÅÛs¡6ŸÂY¨1ê¼ÿÂxó4ÙïçãZ"ešr9'Ë+šhžfRQã [­ß'BCý^*Uãð<­­­cˆÌx¹“åÌðy§p3MÓ‚±¡ ‡M–WMÌlÍ™©fmMöL¢ˆRù\ÐO¸§ˆè=³0!IRæR·ÞþÛ¶¡( òù|°ù ó- ÐÀÚóå £ ¨÷PšÏ?Y¾9Ñ›Ê<ÍWÏ å~,#' º®#N#‰ X,Ž«Æb1477e’Ã2éºÜë2Ñš¤ïÓŸä)ârŠ_c¢k’<¨4¦¹ôNEˆ„‚^]1…îá­W^”‘JÄÒu–eÁ¶íÀ‚(\€ÓsPÎ'C$™ÐÓ°Ðçˆ+éÓ1Oó )°"8H§ÓˆÇã( ?ëyº»»‹Å‚–ñÖõ#ÎEâ¿çÄg¼а§f<Ï õ®™Ë„fª2Q™±ó!¢|*ÉŠ©x0ÇT3ËçóÁB3 #°Ø4Viá}>ô¤¸PoªFTBä ç‹2Dù2áŽáXKóaލM5!f³ùê…v†Í›7£P( T*Á¶íà°§P´H$ô|™ˆ4PQ€îîn\|ñÅÈçó°,+ ÑhÑhtÌ5&˱Q†aà /D>ŸG©T *ëw͹¶ëýül œÍdFä |r]®ë–å“ÖEf(¼Œ’ý(\„J5 6- PŸàž h6€wðL­õ çÐÌÂWmÅ·jzţµdF0?“ygÂ9³¥ÏL½Ä”¼$‘H$8è©(ïCHJÈŸˆ0ðÏSO íàĨZâÁ Ð5‰Ñõ5M ÆFŸ©(»'óNîXm…áR‡Jè™ s]p¯ ï_U™¡‹R• UUaYVP.M„™ Lßfžëû‹”ôpRûtÌÓ\=èÈÛÍemµÏRr9&P«Wf6=÷T EC)ÏyZÈè8Qn ­ ²xRSLRx9æ‰BÕ*]—H)!4Æð5«)=ߨj¼ÕVm ζíÀƒ9—öûDe«„ p ÔMfø—IcjdùEÊÕ\VÔÉŠL®âF7?›/sD^ú™Îõ4ç‰,ýÕx÷æ»L @$¤’"L?Õ® MÓ*æ¸TZV‰Ìp}¡RU´ÙF4g©˲`šfàÁšhŽ(|>—ÍfáØ6RÍ-Ð5uNÍE=Æù n¼’$©®³1Ø´°ˆ¼0¥ð3±è¦Gi¡½5 ¾ïC×uhšÇqÔHyÁ•ó¹è¡° r'ª¥OµÞÊY˜‹F(RÖêYK³aM4º˜C£òU«%='ûºóIχ>ògó<CCÃ8ºg;z†]œzî+°2­Ãe¥èy2ôÐÐz÷í–nÂú®$¢q÷þÓ'ðóóþÿyy7ò¦S–[HÅÂ"ŸœLpRÚÈw?^QF&Yäå­Gî•eÅb1èA4+Õ®˜ü`®E##B£½Óù|ªª"ù ôSML=óÄ+1ÍY$Ib±”ÍQ5﹞Y®ÔÌ¥µDùá9š®µ4]D†÷F¨oþæZŸ™J¿ï»’$Á¶mJÃØñËïáËw=­ï¸ßzßf8E…B™l²"#ÑaD4K<ùƒ¯â—[ÿ·\³NÉÃéñ÷8»£ù’¡aX¶M•3"ˆE£°,ƒÃ™‘߃$ËhJÄ È2†2yL M‰ •ŒÂõdÔ2ÛLJeY&’$!™L"‘H VÇ{Ï“ý¿Àüß÷d|£ÐÙ)7ͤ—bëSid# Pý¡IV‰¹`U—eñx¼LIŸîÐ:èhŽæÂ¡W)¼lºÇMÞ psÃÙ UU‹ÅÊH±Pj渧b¼¼ß÷Q(a÷=‹»wh¸æ=¯Ãƒ?ÿž½öEXfgÑÓsÙÃânúl;’Gjõyxãk7ã¾ý}8ºóÓxËo[qÎå×båó?ÄÃçý=>uNÃýûðøÏnÆ÷÷,¼ôJ\ý7Ä%ãÈî‡ð‹Û~9Ù„ý»wÂm> ïþð{Ð)õcßヌÿwÛðU,:ÿ½øæ?¼Q×­šÐ<ù䓸Ìg>ƒ¦¦¦Š!¹\_ùÊWpöÙg×lXX ¾t¶m#‰T•c7.™‘$ hnn. -ËçóˆF£b¶fàäɳ³™ÐH’„x<^4J:Í¥šÍ¤¦iˆF£ÁMGÞdsDŸÍ¤8™LDf¦Ö’€Àt£’·Áóp,¥C÷àXËËðæWŸ§h!ºh=,χïXðìLËÑßÄ“{2xó»^eª‡ô)çàE탸÷@º*£ù”Óð¢ +àÙR«ÖCÊ÷Âè\M+eÜó£›pÓÿÞ‰aM…æÚð*Œw¼Çqð‰O|×\s …BC“ÏçñÖ·¾×]wr¹Ü¤×iäÙ 07AIÿ¼qo­(+P,ƒÏT×>Ü)X,4ê”´©(¡d¥ M>[’›IùTUµÌÛ0• fõʺyhf“÷Á0Œ²„Û¶ë â‰ÿõ®Çq‚:þ³ÅÛGë;‘Hk¼^ßlË™h,˜ c™êÚ*÷Êd‘8ˆOïÁ`ÿM¸þ^…ÁãØ‘½o~4 pÙ¡a¨vª¦Càø>|«€b±8ºGÈ2"ºH€™Ë ¯_F¡P€"Ip0ZN–àù\×çùð\~r >ø©÷ãÑí;°ûùðù_?ýqḟíUoÊd2øÔ§>…eË–á£ý(àúë¯Çµ×^‹\.WÑ(1Q 0,Ìý.I ÃŒZSªfF 3 …B„IÖaá˜yUˆÃÉð\ù ™“16îÅâ9)'±X,èãÁ‰L=Þ†©zT¸5[r )ÙŸ{dlÛž‘Ìbý!°W_}5EišU•áD„MÅØVÖmɶm#±ÞÔ‰¹P(‹jòSù>ÿÑ4-¨øÁËïNçØUU…aAØ)÷ÈLźÖÈp"4žçAUUèº^æ1šî9’e‘H†a†¡°×j*á†ô÷©ú5\uÝHk™(”L$;7ãSŸ1ìR¦-aÙæÿŸ½÷³ëªî†§ß:}FiÔ%Ë*–›Ü .¸àØ7Œ0ØôÐ)„—„$$_H¾'_Þä%|@HÀ$ƒÁ6¢ŒqÇ [¶,7[²eõ)šrÛéçýãÎ:ZwëN»3#MÙëyæÑhfî9û¬³öZ¿U÷üã¹:l'ÄÿûÝK kƒåоƒ|É…_cf;Š"ض=æ=:ÔhfI³oß{ž7®ã*zf Èë—=Ï‹Œœÿ-IÒñqhDÃH‘õ0 ãLÍD~~~ õíPÐdŒž½Â?¯iZ|Ò9•>Lè LÓ4ãÈ"&2Ó0‘<">qYšh§¦šCFKäÓD>×T虑¶²6þ‰äN·sfFrrÿ¥\?JÂçÜR½6í?ý®}Ôõú\ö“lö»b®%aÿFQ„Ü€Ï6üò߸niRìÕxô½thf'Qp‹pǸF3S‰fÒ—mÛ²¾Q’¤ãlTioR[*•BZ~F ŠÜ‹‡aNõó?h}<aš&\×°^^*E Ê–M‡i\´6â uð}BËÏ([Åaž.<lH:¾ÁŸ©ö<ÕÆækåÏh¦ƒOs^H‡_— œNHf†JG¨F^UUäóy¤R)©¤%IšB†‘— ñÃiá¢@P.“2M†aÄS¯x䜮MJfª îøXSÖ™éáxÄyeFüE׮ƣé`¤¹,©ªgýÒétÅû«,q’;z"¦‹,ÕêÐHV áò$1Ç̶erHâò`YV\6.g(GeÇ©H‹Rdm*žy!IÒl4øüPDšBSϨ‘NŒ|ñþ 45„À,/]ã Sþ2&Óq LëçN(£Âÿ†¯IçÄ+ÎèÕ¢5‰l"ù^M–xŽY†aÄÉH²¤ªjüE×ã ý\–&²èXËÕhIUÕ¸ÿTÒè‰d†äh&v9½ëè ÊpçÌLvŸ¤©%š¦Å:³ÖöŠÑÌdÜ Ã8ê ™”$©6C6×å×§ìwPÄïÅH§hTÄŒO5?‘€ñXôðg£ˆèÄqÎ31|<ãUO“yøÛhJS&âúäpŸ8_Äï«ñˆú~(>M6Ž·CC<²m[ÚË1MÁªvšüñÔá“­§f£MJoN¶¾“45‰zNĽ•5;3¤L’É$‚ €ã8¨««C©Tªùâ’$I:6Æ–R>âp¸¬*wX†ŠÀÏ$#ÊK€Dp>T$p(<ÓÀ ç—£¡â¡wÑž-¶ƒø£ë:lÛ†ëºq¦TÒȲW*•â,óL¨©6ÙL:2QÕrSI³›h i±XŒËÝkvf<Ï‹Í4 #>‹@˜)IÒô2œ¬D 5Ôg†úÿd¿ãiPi ܘÔŸŽ·,UãÉT“¥©äÌðC¦ …e p†! …B d¦«C£T™&Æ3”³ý‹ãØ%Iʉš¢Zë9qǪ́^•Îi –D"Qe¼ $I’FkÐŽ ¥õÔ:=çX¬o*ðh,ÎÌTà×ñäÑd•‹M´³z)èëëáC‡H$Éd`Y ض£™©,É’%زeK<üJ«ø´³Mø ~žïûX»vmÍ}’fŽ|ض‚Æ]ffYVÅÙ üÌ Ù3#IÒè 5WàrÏŒ¬È&‡G 4Äih@à äP4 Ó€‚žc#Ô-XºÊƒÀwáz¢ø}j0ÇFÇœ7“-CŠ¢ÂL&¡GJ¶‡€a&`h BÏVÂiE×õÄëR`$’ÐB¶Î@YÛþ§ÚoK=00€b±ˆ¦¦&d³ÙY9X‡0„mÛèîîF?LÓD&“A2™„eYqðtª–3ަg&‘H`Íš5Ø·o_œ•¡ó»fs™'˲0gÎ,[¶ °m»â cI³ÐÞ×Çq`YV<Î5èº.Á˜$IãPÜrïŒÎ¸M©j€7ù1î~l ´ÕÆç7,ƒ½ë üëíc ´pᆣñ¥Øøâ~DQˆ0Œ %±âŒËð®‹VÂôDPàßÂߺ«ßý¬m·fÄ„_Ú‹»þù[x1s!þ죡A³ñøO¿…ßn>€¹|7êã¶[ïÀžÀ@FP4ÍKÖãê«ÏG{BGºéâ©ÿøgl긟¹b/œQ²4vÙScÐFÿ/ èììDOOÏQeU3¹-Š¢¸O"ŸÏ£P(@Q¤Ói¤R)$‰ Gfºë© Éd°råJ¨ª ]ׇk>ZñûvGN8“x BV멱3cšfÅUô2J…Œñö3:0°ç¼øìÏñÝÄ|üõµ'¡ ¥žzÓǪ+Û¡zò…¼  @ÕM¤’ÔYdF¨ÜŒ‚ô½mÛ°mýýýèííñàÕ™\é_]×c'ŽœÓ4¡ëú´-/«ÌK挦ÙJÔ?C‡Ïæ ³Ý‘¡ fäÔŒûÐLß÷cïˆ{ɲ¼L’¤±pISå…hp»žÇ?Ü‚X€Ë?ô~\´,ÏsãR²TÛJœ~f¹]ob³›@R Aªùسéed:n@»Ù…‡o¿¾ÚƒD}p‹0W¾þ¾ÜiQT@…áÄ£wþ'žzÍé—߈k/^- c‡'LÍÇÚ“OF.ë`×kHê ¢PÕݯ¾‚îì:œ5ØýÂøñÏžF1‘ºp³«ñ¡\‰yuú¬ÓäÄÐù3t†[:ŽœhkgšTUµâùéK×uèºGèg’Þ¤r)éÒ™©Î#’wéÈÌn¼äy^|ÆL­û¤¢g†¦˜%“ÉxÚD†°,Kö´§†] IDATÌH’4%]í{I#µ‰¿nÙ™ñlÂV½—¿ï:œ¿8Û  GÐ|׋wâß¶p‚‰ÆµX±8 „!TožÞîcчVÂê}O¼zzÓ:\zåzÌÉ&¡ ¼É¯…Ÿ¼ëêuE…:ðžéÐ|â»píå§#íÛ""@Õa~·þûS<®Þ†ÓW¶A #(J/m=€–õïAcPÀK;_ľb#.»âb,ok@"‘Asjòú Äý6ÕöРçe5âšgŠÎ³2t&9/T^ÇGóÎ$=%Ð+iè½+í¤”:kFÓ´ñfV†a X,Â÷}xžOe™ÍŠ’$M]*y3Æ»‰F$K]xè¾±¬ãZ,Jiˆ" ff"´ŸõI|ú]Mxñž[ñãçwà‘_oÆ’÷àå§°[[Ž?Xh POÁ§<‡Ÿlzø ”˜wÎMøØ»VA ˜^|b×7³HºEäw?‚ûžèÀÕg/„J™™Ðƒ7ç*|é“gÃyëyüøG÷àáŸ<ŒÓÿâZ´ôÀk] κ¬¡bâ„ÕgaÞ+౟ÿ+*’óÖáý®BG1k÷92Þi élsä°Ðó‹ŽÎL ´H°.IÒèõc&“©¹µå¨23jÈŠ¢(MY’$Iš¶zHŸpÞ·ä9ܾñ|ã›>ò±k±fŽR™¡o£è(h¨K! ;áä#Pl¼üôH¯¹ó ^IÁÒK?Š/¿ÓAßþøå/‹7»¯_º«ŒÁtÆ+‘·þ |þÚ$îúÁoñÔ/o‡®oÀe§.Šy„ÐC©dCÕÓH%4Ýȇ€v`?úK°¢ÞD*È,8 Ÿø³SQìïÅ뛃ŸÞÿ^:x>Ôµb¶CºjYˆÙt98‘Y I’$U8"ºŽR©„D"WË™ Æa Ã8+cÛvÍ 9’$I’t\ý˜ÀƒcÛð=`Åù×àFßÀ]¿x ßýf?®»é]0=¶ã`ߦ;ñí!÷”»kÏ<éþíøý>§^µZ @±_Ç]·ÞU‡¥úèæŸ|Úá´vdBx¶’Q€Ò~)>üñ:ÜsûOñàßÃáîkpéZ žçÃßÿnýÖ&x¥”Â:¬¾ðm˜§¸Ø¾÷ud—žŽ´¡‘íOÝžë‚™NÁÏu!»èD,mÊ@Z î%I’$I$*/#ª¥Lúž7dQ½¯ì™‘$iØPöÌŒ™G“Á§0P0ÿŒwâ+ß%ÕÛѱô¬Ëñ‘EëQ B˜é,R—܈ϞçÆkPT VªÍ-uèzæ~L­ÁMm¼ÀG”<×ßÜŠÂà43U·P×Ô‚läMº33yrA5çàªOkuȨ>ô–Õ¸úCsqþ@¾’B}s7|úÏáDƒ³Á)nÍPÝ^ìÚÖ%̓ TL¬<ëj´˜‡DP ‰lë³¶gF’ÔS’$IzQémµÂ1;3|œ ÕözžÓ4áû¾,5“$IÒ4S’€•mD{¶±üÿ0DMsÛÙ_¥‘n<ú³JàÂÎ,Å;¯Zˆ:ƒ£˜ Ô7·¡¾Ê}¦5©&šæ-@SߚОmŠÿ$9¯£Ê„^€y§]Œ…‹š   ÀLÕcNª^  $I’$I•Cãºî¸Z[bg†Æ¢† â‰#Tr6UOå•$I’¤‰W®ÚW­Ç|ð©÷†àT«gž?aàOïR;I’$I’t\ˆÆ´óÉ5;3aÆ3ßéËó¼Šé+äØH’$IÒL§0ð!óÑ#;4¾ïK6H’$I’¤±[Áª0ß÷㪰q•™‘Ãâº.TU­0P®ëÂ4M”J%¤Ói™¡‘$i„ÍIÿʽ2<$ŸF/K’¤,I’²%IÒL"ß÷aYLÓ„mÛ5§Y¨ÌŒN,ÉD†a ‘H ££¹\NnfI’$I’$I’$I’$ÕLtp°aˆ¢¦iÂ0ŒšÊÌTîÑŒgÏóâ¹ÏAÀu]X–…ÆÆFôõõ•§þÈq’’$I’$I’$I’$I%)Šß÷Ñ××‡æææØ÷ 禪˜fF³ži<šeYð}º®#´´´ ¿¿½½½H&“°,+®q“$IÒ`„€M”=f£ã—¤êÄåHêÙêEt]eIVHšHÙâ{PÊ–$IµS†ð}¥R žç¡££Éd¾ïÇeœµúºh8éß(Š*rhEŽJzš2Gk_:Ý‹øèºn|?ß÷¡( èX'­ƒÞÝŸ®Ccšf|?z´vÇqât?Þ¼LŸH$âgŠ¢Åb±"ÃGƒ'|߇išÊÑÖ `Û6Òét,ô\VMÓ„ëº1?©Œî«ë:ljÏM¢Í£ëzÅû¤JºñHÓ´˜T’†a,Cü`YzfÏó`YJ¥RÌsUUá8EišðK“éQôšg^I&i\nésTËJü¢0='Ý3‘HÀqœXޏ|rÞÑ{¡Ïÿé~|#êhn'ÈüÒ>§Ÿó6$Ó\ßÐ;!A{šö×ÑÄ_ú"ˆ2N:„xÈùMû„ô„a0 Åb1~ÆD"Q­äÏhÛv,¿$KÔïÊe”ì.½Ú\wÒýhÍ|‚)M"}ÁŸxmYV¼Æb±Ã0b=#Ú#Î;âñ”pFD2Ãß;—%Ò§´â·ˆ;Èž‹¸ƒ¿7â'Ç´ÇqⵟGÂ$7†aÄrV î ÏÒ>q¯àú†xOXƒ"à#ᮋI>è÷cÅO¬òعŽ$ýJû“Þ‹ˆ;h]¤‡HVx„ŸãUUašfloÂ0D©T‚išUq‡¨ûJ¥RŒ}9+î Þ¯hˆÏeSÄ$ç¤38Ž£õÒºF‹;HG‹¸ƒô ­›d¼îà{‰öùP¸ƒìÉ&É4í¯ZËÌ´ë®»îïV®\+AÑ!á—„”›^ Kþ=½"îA÷Ⲥ Ÿ‘Pðì½lÚ´ô¢¹q£5Ò}hb8ç/o0Ú|Cñg$lYV¬€ø£$h®ëÆk¤µÑÆ!°CІ6Z#mT®¼ŠÅb?è=OHYrPHBG@& à a"£O|ó¥xH€~NŸ#y¢ß‘Œñ²S±ŒŽ@ ñœô9ñªª¢X,¢É¹àSLè³"¯iR䟃5ÚGdÜHas€E2Fï‡eºÝ‹Ë’¹âüç²G2Î܉¦}Eë"=Å× ŒÄÚtâ¿(«¤w¹A÷ã<çrêy^¬“iÐÏiψ墱OuæïˆäƒÖOÿç@—Öήïy0€ï=ÒÉüÝ’Ž&=@F›?7­]tÖøþázŸ$#\Þ98äg¶p£¿+•J±Ì®ãŽ+éiúÉ×½¤Sè]ñ=OòBûS\€4Òÿy0Žöwü¹ýá{’ô6?ˆ[ €ð÷AE „ë"Z9$¼^ŒärÜÁíw”DÜÁ÷}ž;Á´vn“†ÃôÌ<(B÷ã:„óq$ÜAòÅd$7®ëƺ'É _Ç"€æ÷àï…oIos™+îà#’,Óû õqPM÷¢kDüÇí:—/rÖ8/9‡Â$ƒ<øK²3î཮Ïùýˆ÷$o¤ÿ8î k‰¸ƒßs(ÜAk$yqÇÒ<°"^¢(ªp‰÷<㘊xËí_§¨K¸þ%ì@6•Hn—‡ÌÆè:2™ ¶mÛvd€©7ŸÍ>ýŸzcšfã™®C‹Ö4 †aÄŸ éTªÂ(óB/‹®K‚.zóôÚétºÂ0Ò:(rÀ#DÄ®Px†„ #­Œ‚¦i±Ñ曄„@žañ5”ÒôR’$ñâQ4ŠžòèÏR‰Ný÷Êy”„…6< -yî<ÂN5Žô~y&GlH¨yäGûè_’§d2GùFäŒ EÇØŸ8 ¤Íó<âJ×"ãÅ#$«´ȹ ù$òõU{$ÓôÒét…cC¼¡è*O^ÞÉŸ/$“Éxã'“É ¥õ¡ã2ÌùNk¦ß“²çŽ9ñdV,?%£®ë1@ä~zÔ è ¾Rô‡d\ÌŽñ` ñ”øGÁ zçd$)ÈÁpÒõŠÅb,÷|d89h¢Ï‘Îã(1jLÙ5 Bº‡QèÚ¶mWdx6‹;%ü 1Î+ÑááÏÈõ8­“ö.[pá5Í$'ô¬”9 ûÓZ У=J€Šö:w I·¤R©X߈}î ÐÞâ¼àú†ô6ñä‘¢¦ô,$ã\7Œ‘l[–?/íOÒ—´Ÿùþá2À3h|<˜E¿ãQlÒ¢IÏÒ;$Y$@Ž}¤»K¥REfMo\éÙI_sý,:zÁ/•JGeÔxÄ•@5·ËôN¹ æzšÞ[5ÜÁOîœq=D{q,¸ƒ>G¸ƒëT.»äˆðl#8ÚGwDÜÁ> r™®†;x@€¯Û žq#ýÀõ$ÇŠ¢Ä2ÍqäðÓž&>’“!⎡úCG”ťûضï(•Jq°‹ëGî0òwÌYÒW\‡~#Üá8Nèç ›>K:šã’In¯è‹óStHxð˜ìˆ½i/ò <ÇV#áº&“©ðJŽAÅ )ÏÈRÕ€¸GxªžÄªž5â?#[G¸ƒëÚCµ”™Å™.ŒÜ[ãQ*xD€Ê·¸°ÐËäišqtV,1ãio\’`Ú¶; ¤¨hC¢!EÄAEÈ iš†d2§¹ ñ¨mzR,üåp¥N M‚㊗¢JÜAã: 7\ñòh ±tg¤¢(:ªd‰6ýžÖ'6Ð’äÑ5œÜa ÍSðÄcJý“BâàHTò¢aæATÞªª"™LV”p€È ŠpÏŸ” lÒû kðÒ+12Ë6’³|>_›Ö@ ŠGUxš™"Žäì …Ø #N‘-â _’yR¦iV8&bTšÀ Ïò’-^VÁ÷eïè=PÙßË|ÿ’±ä²XM¦é]óh"='ŸjÂTÚïôNéÙI¦yž¯‰>Gò@Ñ&.çt_ú;*〗LÑþ£½Lï‡ô wÚ ¨pÀAe´6*G¤&K<ÐÀËméo-ËŠË5yy$L. bI¯a1æ%sdìxY­•øÇƒx¸>Ñu…BÉd²BßUÓû$s<ûNkáeéd4ôy®Wxi ¢<óU­”ÑõI&S©TEu‡h'ÉNsGÁHné™x6'™LVè9±Þžg°©\ì˜%äŽ;è÷”ý&ÜA²Î÷)Ç<°Jz–;#Éd¶mÇ /sæÙCŽ;èbTž—vÒsÛ¶]›H¶Iwó Ùþ\"îà™iŠ˜óÿÓ¾K޹ãÏ÷'/ç七;˜Ü¡0M³Â©çí®ëVXy6ˆ²Õp·Ü.‹  ߨ|ž¯‡gHù$.nçÅ–^vÅ«HÞx93ß'¼D•®“Ïç+ÚB8îà™?º= án‹ˆ÷¤ Åez^Âüt/*÷ãû’gṃÌÖä?ðõ/ …˜33±3CÄ•=¬{žG„xI¯Mäž>Mռ숄–×ëÒÆåŠRQ”Ø3äÌ¡2 $bЛ֯Ӯü…â!cͳ@‘2¢h&I¼¤‚;&äh' Bž›O›Ò†âBÍSqÄkÚ´¼ ƒGSx‰ “a±ñâý3´Nn\x™ /á‘az—Ä?^þBBM§…éy4ñwHF•#žþäQ>R^<,‚õåÙ-nÀyÔ–;Ë´vRäHe2™ŠfE'— 1+E O){Ã#\™ólÔð€ï© =Ç 28ÂhïòH//©!ùä|æwäÉáàl^ÆÊ#W<:I{AŒöïxY 0z'dȨñúa±ì•——Òß¿9x¦÷IA¾^â3?Ÿ‹zžr'ãX,ã½B“—iP@‚ö)bðòº= e´)rNk#¯Üùâ%2ä4P—=®H—ðRM’!>yƧZ™ý-_®§ QÄë:žÙ㺔Œ<É4#q-¢3ÁK5(pC{Æ4Í`rPÏ3§\ޏm ÷Æ{î“|Šý©T*–u<û'–ÿr[ʃMä°ð¬ßߤ¸Íãë'ÀBüçÀŒœhzNž)çÁ2<àN-Ùvîdò½INíî`„;8¨æ½7\ò ‹ˆ;x¿=3á^~Ãqwеyo s¼ ;aüó$KwpÊ3Ç<‹Æƒ¥<ËÄqÏ̈1€Äí'éWà{Xååådªá¾‡¸ óŸq[@aîpUÃ<ÄKãéyÄOžA#Ë®ˆ¯äƒgÎ(ÊΈx¦—üñRœjCQ¸>æeœüyy–îIÀ—'ñì.ç;w6ø½ùšÅ&fQ¦y‰Ý›þåÙ6Šš‹÷á_úžuávŠ—¨ð~r6x½>/å÷5otæA^¿OàhÄAœÿb/oÊ&Ím=#íc®ªÙWrÜI·sÜAûi<¸ƒëfxÉ‘ wð’I¨ãX@ìฃÛ[ˆ2=ÜÁƒ#"îûšÅRkwðàðwðL.Çœî ëTä?9î (êÂjŽ /éårJúŽë©ápo‰ õŽ„;ˆ$sÜqãú_ ,‘nåZÒób¶”äFêÀ^2MÏCeï¼ ƒ;§\ÿð]äHñá ¼ô‹ïá±à΃áp×C|¸ƒ¨£óù|íÎ m:n4xL!á ‰G3yD‚^1€^2ös¦Š½¼ŽGPÅL )EžU£¯œ<ÆA:Ïv!àå\T*ÆS›ü÷ü†ïc>Ð…G8¹óEÏ%NŸãå"âûæ™Q®#øÄG^RÇ+*èHyP7XÓçy¿Ï:ð’8^úJ¥cÅ‹jÚÅhµX’Y­†§Á¹cM=´¨ôK;ÊùÀyÀ*ï±£û<óìÜòr ¾EÐHÏÂ3Ð<%.NÖ›ÎÅIx<ã$–v‘¬ÓHKê¿Ç[ŠQ6оñþ >e’;~©Tª¢©›ÖÄëÎy‰ñFIÓ{¥ÁôÌ|Åqîbù/¢òŒ ¼|–JÜÈñžêKªÖGÀõ]‡0(|*×Ó\–¸,’ãJ¼¦Eè›üÅá|ía’iißqÀʸy?/M3‡Äw>I‘$žáäÑm± š‚O<ƒÉ+âM>Ÿ¯a(Þ·:f'‰¾¡¹ÙÔLID‡¼yóä[$i4QuÎ’$I½”$i¶Êãxmα\¯´’€rK]]]Ü“OÙj©BÐùEéÀñŒšØ0þüбƒ’$I’k" šäÓð<GÍKz¿I>I:ÞzêxÈ¡xFÜXìÓñØ3|"œ¤ÙKt¦ùµÊcìÌðYú4>’Ò=4+ŸÍ“$I’$I’$I’T‰£ŽG¿$ >Ú aã™ÎÎNìÝ»‹/ŽËö…|ù¾½{÷¢»»k×®­š!G†¾ŠÅ"¶nÝŠ¹s碵µõ˜î…¾¾><÷ÜsX·nš››eOö,µmº®Ã0ŒqéïŠ23ÊÀ”J%ø¾Ã0bG’$I’$I’T»†a<`Ç÷ý£J|f’­åŽ •@‰_ääLçˆ<·Q¡X,âµ×^ÃW\qÌΆ♡ÖÖV¼ð طo.\X5ÈeqçÎ8ùä“ÑÜÜ|LÞ­'´´´ ­­ /½ôÎ9ç†!Æ,¤0 ãó,I'ÖìÌPªÑ²,˜¦ UUaš&<σiš£n(*Ú2Üï&js uíɼ÷dnö©¾^®$ŵV3Ê#=ø™™ò>%I’4» 5G*뉢¦i²¬¸úa&ê3zvÏóà8N\ÂNø‚‚¨3åùUUÅŽ;pæ™gÓŠrdˆÇؾ};/^ IÓ48ŽÓ4AMº vf È#E$ОçUŒJIÈrù<‰†PÜR©Ý´¶ («¾ï£X²‘HXH:(Pªü>NÂP4@Åïƒ €ëù°,š¢"~?e%‚ª(0t–eŠVÕñ ‚Å’=è¡«°L¦aJedËu]ä EX¦‰ºLA¨ÖöÂ$MGX’ä×DðfªñˆG¿ÇA0M©T ¦iΊwKNŠeYÈd2‚¶möm‹Åøl;rèŽU&£–}7Ò{¢hòÀÀ@\®5–Ï×i$9+ ‚#î V‹8“-“äÌ‹Åx’•çy÷—ÁÊÙCžçUÈà¸zfh,¥¹ S:x8‡FQôz¿øõ#8ñš›qZG}üó(Šà”ðä]w§Ü€KNYUX1Ú>Ü}ÄMÑp'~öëßá¤÷Ü‚SÚë*>†!ìC[ñ£Ÿ?‡ >þQœ˜Ñ+-×õлví÷pòyë‘UCЭGš//®Åõ<ôîÙŠ]*N?ÿ4¤`,ï„ ê?¼Oß{Ú/½ ç®h…RãË­¶~Ïóлw;v qÚù§#­„륣(‚ëØØ÷Ú&lÚôÞêÌ!Ý´7|â,4Ê%n±/?õ~ÿâ.ô•|ÉFœôöw⪳O€>(_\çò8…ƒxù±ðÄËû¡ÖwàÂk®ÇÛW4#„¿ë\>‡ýÛ7áÑG~‡üâ øË¬CèSrƒÊ>É'éÐÌNY¢ïû°mªª"›ÍB×õY7”?«ªªH¥R°, ¶mc`` nþ¥£© b‡Êp ç0ð’™ÉzïÔ³ã8J¥\×ö¾Cí“cÑ¿EN¾çy°mù|¾êà©ïf~ÐužçAÓ4„a8¾ÌŒçyH¥Rñ¡™äàˆsÁ‡°ÐwÐ}ðrny9Ž3X«Â4u(ˆà…å¨~4˜Jò}ªªÆŠŒ²Cº®W”·ñ4=PNKÑgBßA÷¡ƒ8׋ž.„uhH'œ%2­ÍÈçгg'\³ºŸÃáÒõ-˜3wPèÄžý]õæ/^†ù- ˆ¢…bÅ\wB_ΆfZhn_„ö–º2˜;×[ßÄ€¢iN–/™(PÒZpù5ïļ”V‘• Ãn)‡®®Ã#;_Ú?“F[Ç"XZ{  =(¹’uÍX²l’òùò]è>Ô…¼íC7-44·#ÑÙÓ(*âõ_@)™Â‚å+М±*^Zoïaä»!ÛqÚSp]=‡ö"ïX¸x^ùï¢n®;·v"ç„hhiÇò¥ €ÀGOçär¬XŽ”¡Á¶K8¼ÿM”Œv,î¨Ãáƒ{p°»ˆÖ¶4ºtÂT´Ì_ŒEíMp èìî\ãØ©êZÚ çöÃË,ÂòÅ­<}}ÝèìAÕhm°*¼EQ ›iœwýqÚU.öÜÿOøÚ#•ŠÓ¬›+ßÿ™ØYÉ­] £øøí{ñÁ3; „A|IÏ÷QÜó{­€Ë¿ø¸f¡†5mèßûð“»_¹Ÿ9ž]D¡XB~ï³ØÖÛ„Õ‹Cl=rC@*>I’$Mâ%?a¢¡¡A:2CP6›-W#ô÷ÇŽ ÞfŠ33–l¡8L`´‡`òÏÑ”²Z¢±¬5ˆB‹%DQˆT* crÎ×ÊYV6{‰W~öÐ×!EQ`šfE怲$4Zpt›2B©P@®àaïs¿ÂÏ7õâ´+nÄúù~wÇ·ž÷‡¸dm#vÜÿ=<ؽ',kBèæ±o÷A,?ãLù^¼}÷ —^‡Ï~ê:4jòýØþÔýx`s7Z;æ ¥”ÐÂM·\P•¶ýî·Ø•H!(öà­C%\ðÁ?Â+àtmÃw¿ó®ùÊßâ¬F‹jˆ¾ž^A ‡öíA &òj=g;ñØÏ~í… æµ&pxß[0—]„÷ßx T»;ºî °`a¯Ûo…לÞÈB÷¼…\”@b΢ g&Š"ø^OÝñmàÒ/àý/EèÛýþë—=øÓ¿ú EP;žz›› {9¼µ¯«®ø0n8cJ]»pÇÇõñœÔ–DùØûÄF|w÷9øÆß^ˆÂþWð“;Áœ×`N[#œîÝØxâÿë“>z÷! mÚ÷ ‘‰E‰z÷wÚ×á«}ù  ôá¡ïu×ü5nº Q ¦¬#xn€b±ׯ’f ò°]¾k£Ð½»,>§*¢8¤( ßCÏNŒU8gžŠÀ÷áëÍ8ii6½ð,ö‡g"Ur Ø;ñȯ6cÉU…ñämØŠh ryl7汌rÍ´¦¤¡€¤©/KaÆÍÍõõõqF]ÒÐçy(‹ñ0Sn’jµ=8ÚÁH£yޏüÊuÑÕÝ Û¶aY&æÎ™ƒd*=¬ƒ"Þc¸r¸‘Î9-ÏÃ(Â'6ãàw6·]t\}Úß4(£æÇPΞÔw³Ç‰¡-ËW¯TìÌPIyȪªÂqœŠ¥‘„+Š£R^{ûîxNÁ Ÿú Öw$Ñu`74®k€¢À4 ¨-í¸ì=ïC³RÄ«OÞ‰;~ú<®øì§qÝŠô¾õîøþOñÌþKñ޹:zw¿„‡?€K>÷9œ¿¨}8NÕPКŸCqéøÃË×Â-tãéŸ|¿þÍ6\²ò(Š3aB ”lÞà3š¦ 3Ó‚ÕkVàá—ßÂ%×oÀRÅEW7¶Ý½¿ï\ŠOÿù˜£úè9ø îý¯{ðè §àòe]xú÷»°à–/ãƒë²ˆ~_Ó‘²yº†{Ç£éA)þ)âõ»ðø¦ñæþn”†®aÁÜfœ¿þ$œ~ò:X‰ÄYŒjçe_Œµ_Æv Üõ2?ß„L¤Bët]v.¢Ö†amrµ3–dVfvé(éû~¹ e<E‰ MZ¡)b=ãÐ8VªzØöëÿ¯zæà£_þÎnÓà8G/NQutÌ_…­)x>šÛQ?'Äê…s‘´TØuhªö¹À\݇ö¢ÐqÎ\ÔCÂPEÚPàº.€¾ÒŒsOYŠLÂDÎÏ¢£µÑæC(@EyŸ”3}=‡ÑÓ_„nèÈf›‘®O£\wGN'žßÞ†ÓNE½Ó‡>ÇGdÎŪ¥¶¿µæ™Ë°lމ'ソXu+¢½µº•Kž/ ½èî>Œ R© ꛚGôT#AX‡³Ö-G}Ò€ç¦Ð±rÚˆºx›ª éD(…ðµy8gU4D€‘Á¼¦œCa+k*‡ øÄ+aˆÂÀat:ŒHQNgÑ:w.,]á9CK`Ý»nFëÛóØ·ýYÜ÷ë{q×òñ‰·/d¡ì”ÑkˆyWæeyØ@ÏË¿ÁÏv/ÂÇÿj9¼}ð£QàÂ|(ñ]’$I’ŽŸa¦~à âSÍ%ˆ öȺ®˜î ·Zb(*–JøïmÄožÜ Ï¡ÄÆXÁÖ7öâÁß¿„ÓW=‰¿ïZ,\ÐqT“4•‡ÕšÑpC]#´µ Ùè¢65 4„. !ÂPœ);²Ó%÷Éì%êC/ q’¡&BßPö…÷Ìèºÿía„NQMõsM$[‘°ûà G;2¢Hªêñ½(Ð4•Ýcpà ‚¦*|jRƒ‚axt´#Ruh´Q•±m°^š‘@°ÿ)üøžmPLQ´üËBS˜? (ÐáÃ…†W‰ïíÖâñȪގU'&¡ªm¸öóŸGëýcË à™ûz‘Y~.6l¸"¾hšl´·Ýs?úý¾›Â;nùNÈ* ëA–³|ë: µÌ ×ó*L5@ÉW…ùõ@T™H¦é@Tþy r3¬Ä<ÈæÊëšóÊM7‘ ¶âÖ?„’ ¸v×þÉ'±¾% ?:Ú¡ŠÀß‹‚tÛœ0hŸ×³ÿ¾÷ÓÇpÃ…ËÑèå±ÐŠ]7‘I¥ —zó˜áû.ìþ ·¢ÅÀ“ÏlGrñ©xëɇðºWÄœ‹HÙŽ§žNâ„u§¡ÕЦL‚FF™$IšDÎÌxŒòl4–e¡X,VŒ žÉº4 äòy ä hjl€fXðü~ ›N!‘°ày>rù"¢(À[^Ãâs·\3O]‡pÙ ‰²YÔ~pøÕðô áÌ5в)誆òh§Ú`Y`Eèk7@vÉ<º<SÒÈò§ë媟Q÷èåÌPo Ÿ„ešf|¨Ñh¢ ˆBa=.¼q°e#nýú÷ñO~ëÚ3ÂÆˆ]‡#×E—ïQ¹M3¦æ9ŸÙŽ7{ÎÅ’Œ?ÒéË,ˆ‘…#à¼\Êhš‚yë®ÇÿZYC U"ˆ¸ŽÐus±0 {ÞÅø£ŸŽÈq†€•°`òùDz+νrN/нo~ø{ððÉâºDƒÍŸZ½éT|âO×"Byª›¦è?ÝJÅ …J%ÅRw°l,Š€`Û÷tâ‚M°K%8=Ýè/eqÞÜ$´njh#_*¢TðáØyÎ;£#\ˆŽâoùÿª¦AQU òá:6=‚¡0’‚¾^ä\aÑFèFW^A£Âh;Ÿý_§ÅÏ`&ÊrR²8Ž‹ ¢(„k»ˆR|?@¡dCÓ5¨QÏ÷á¸yDa(Â0B._€aYÈX<ÜùíH»áé7úðŽ9àõ`Ç®˜+®Ä↠úÎ~¬9î€ëæQp|DJ:»± ,ó<š¢åfS1ê4Õ¦Å˵LÇI9²†|jÊ’]¤É”äÈÈw6zþ™¦—éÑDÓ©Þ33œÌU+§"r»ÞØŸÚ„M/½†¯|áSøÐ W¢/_œÖfœ²j92©$lÇÅ{àç>ŽÝûâPϾþƒøR6ƒUË—"ìÅM‰ÙHY¢¡®E *xã¡§Qøâ·¡ìƒûŽÓPÿí/@5ô#ÎYA×5ì~ôäþòVD% »Kþø&Dìø„j|©–’{göèkrf舘ZHç$eLSÌ\×­PÊÃ×…†n@E-=g_÷ièúâ¶o߉OýÉТÐ4 „Ó2¡«G²ªªÁ¤¾æ¥iZy<šn˜X¾î ¬zòÛøÿ¸W\|ÚôìÜ œ{ÕÛ`4ÆMÕ`èj9Û£ª0 ªZ®ÁU4V¢r6´6ÃÒžÀ£oµ¢ ­í¸dÃ;ðÜW„·zñ¶5íÐÜÚûR+®Âó^Ç­·oÁ‚“WcAS ¥7·âP”Ä鋚ÑTlmÆ£¿mišç¶#c%v™O©T­™‹;Ÿy §®lA]ažyüôã((+uËTðúo6â.ír¬ktðìƒÁ=ézœÙb Òçc~[ ÷þöy´_yú_Û„ç^ß‹ E…ª(åç… *ÚÒu¦Z.3T Mm-0•gñèã/B_քƶyXtÖ:ß| ?w*ΛWÂs÷Þ‹]¾‰‘¢Á|P¢®ç¢ûÀ›Ø{ð0ú»Šˆ|ÛŸNË<œ°|ö¿ŠûïÙE+МÕ0°wž||Nºù}h}ôæÞÄÿ~싾€?;»-+OǹK~‡û¾ý=(ï: ú›OâÑ=uØð©Óa8ù¼Ëqò`V©?„ßöìÆ!ã\¼çÝg#ò„a4e7êñºÇpg#ñ2…ãýò¹Ïà‹JxlãqûOÁA%ƒ¬e¹¯V~œD"ƆÔ×¥aè:êëQßP£Ê3¨Š‚º¥çâæ+×£óáákßü>žxõêV]/ÿÍÐÚó6Þy;î¾÷wx+˜ƒ¥‹Q×¼«æxåÑ{qÇm?į^UqõçþïZ¤"³üøÐœ„·~s¾úõàÙ7úâ~Ú³¦iâä‹nÁå‡ñƒÿÿŸðŸ?{'\|=NšcA7 Ô××!Û¸×ßt Ìà‡wß¾¹ïÄ_Üò6$˜uóqÝ{oÂ’Ãàßþù_ðË×t\|öéh©OÁÐM4Ôס¡! }°}'•J¡¡¡uÙ4u+.À-p ö=ðCüÛ7þ¿½ k6à³ïYƒòUüÓ76"<çøzY:‹¼pÁ3t ¥C[qß=ñØk!²–ƒ'~¾sÏ ð4­í °¸UÅŽMâþß<€ç÷„¸à‰Ï^¸QÔeS°, ŠªªÝjÃUŸú,®;xâ§wãÑ7Øð¥/â¢9*¼ ‚¢¨qSh&“ASc#ê2©ò93³4ˆ‘->–“êöéÜ(Rô/>Žs&Îrdx½ˆwô%ŽK©²²(/~Q–èg¢,g38!>N>Õˆ2¦\žfÂóЗë:¸ç—¿Æ—ÿí¿ðÃ_?‰®ÃýƒÁZO¿ð2ÂA»Jý(\G7Õgñ¹›¯Ec}ùPðÍÛvbï®!3µîÁj×+¸6þî{ÈèÇ-‰TÞEýegAmÎ"òޱ „€êh|Ó©¬™&´˜ß¨ú¼šÁ&>WtÏ4ÀVÅÇ­x'âú‰ÆTäç }O ‹,„aرc-Z4)ï…˽±™˜‚Yc‘%þ³ce ÷îÝ‹… 7pD‡öõõ¡¹¹ÉdR¢”1¾Ã7Þx¦i¢®®Éd²æô&ZOmÙ²kÖ¬©jkhP‰þC=„w¿ûÝGD<×ÅC¿ßŒ‡ŸÚŒm»vÃóŽ”Ô45Ôá[ÿy¤’‰!בJ&pëí÷à¿z v±ˆÏtþà¢sâ½kÛ6Ð×ׇb±ˆà½ï}oìqç]]]p«W¯®NÐߪºŽí<õ–A‹« k‡PÎ^…ÄÏþ‡Õö ÌùÉ3H@A´rô»þÁü&ìÿø?báÏÃ3TDžÂ—n@ý—nl7¬ù|ýýýèïïG__N:é$,\¸°"€$iæÓÀÀ@Œ•è<®}ûö¡T*øY˲0gÎlܸˆ™"pº®Ã¶íxº?~ØR³À‡ø†ÏqŽŒô#¿sGAÓß¾‹ÀÇŸ¢¨âú¢2︎À£N0\­|op='<²&ø8Ž?äy"U¯u” *žïèçúwùÜ`¨ßp^úŽƒ€ý¿ÚCágíˆà»üa"Râ;©äXÁCÑL<© ø½]ÖË5ŒôDƒÏjY2´ªªÆ_0ÅýKK†ƒþ–Àú±:цKtZ¸qäàœó‰ä“Ëœx¸wlŽ•C3™å¢ q¹¢{ѹÕd‰Ë#Éw)Cq¬Ç쯞Q^$Õ®Û¦b¶¸–žþ9M×ñη…wœ{þõ;?ÄCOo†¦jp}Å’]{ö㤕K*™&}åz>N_½?{äž‹—vìž}Ô½F³žáö NÛs >¹–"ÈZ0þþx) an¾ç¡Ü ¢Ü<"´´|ùcȽð$^?E×`>ü2ðÕ³2ÕKÒ™™]ûžìÇh‰­F£™ù$(ŠâQͶmùÛ¡þ?ÚƒÆò7£5bµþ¾–ûÕÊ«É|žñð¶V01Ö÷=e;7êDQÑØóÒ]×aYVEàa,×çQDî%™ 0:Ñï–ë'*#=>1e¬Yº†XÏ?ÈŸª$–’‰ P“[îY»Q!ÞsÙ¬æ0Î$GF‚°És¦Ãxæálœ(A¢T, ··a¡¥!‹õkWâÞGžÂó¯ìÀšKŽº†ïûxùÕ­hjlDKKZ¹¶·à(û0Ü €±Ê1P½¶ihÐÃÑšEWÌCàû0LÉÖz ˆ€Àƒ’I@©KAUhõôžµ Öö}Pu ú@ ¨TíAž’f6Ñhv«É™Q”òy-TjF£%é_˲ä¸YI’Ž£qç5Ôxš¦U¯•äÓô º”LePÁ˜jÎ90äœÕÊ#š¸$:•¼´j*ëÉ¡bÊ2qYªLpÇ…œ?’)žÕ’öDÒTsH'sωÀÝv<„Aˆ¤eás¼7]})º÷ y ææ­;ñàS/à‚õkázn¬û'Ú‘?ïù>”ÞÉ´@ mIDATL(åã#ÚZÂ0„¡êhÿâ‡àç"¨ûû ý?7#Ì$ËÓ_ÀiËÂ×U˜U'ËNÔz%Í¢>ÌñØQ„ز¬x,rb|ß—Ü–$é8Aî\P›išÐu=. ›("ÇF,Ó♌‰¢fÅ)žY2 #vb&šGš¦AÓ´£œš©˜¥KÉxFFÓ4†gô&XÐ;J–fªC#µñó—&Ï$­|ä…úL š¦aÿ¡nK6ÚšÐÖÜ€ 8º \ B Ç/I³ƒTU³3ãÍL& ÀeYÈd2ð—ÃÀ@Éd˶#BÏ÷‘JZ¸â‚³ðão|7_s×W°©Zæ&Š"D®ý“á/Ÿ%áY:Ýñ Þü§ÿA)—‡!€€ø(Šxíîû¡þÃíÈ4?2I¨ï»¡ ÙC$uÀì&êÛ§ÒçZ¨bšY:†ã8Ð4 ®ë²ʩÄZG¥I’$iôƤH7M¦iN™uVshŽåçj<¢Á%S¥Îšóãx4¼‹ŽŒX¢8UxTm´ýxYHšy g&<Ÿ¨–iâ†+.¶7ö£hÛØ²m'þù;?Ây§®ÆâŽ9H˜òE¯¾ö&ºûóøã߈ÓOZ…ûŸÜ‚3N>—w–/š a;î„9âuÂ0DscöùF˜þ7ŒÐDh˜÷õû°ï¹× \±ú²ù€®ÁÛ×…âÃÏCûÍf4Ø!êÕ”Rú?þ!¢ ,GíhÉž™Ùëü×Z}¢ó‹‹ÅxÃe³Ù¸ž‘{JRÀ$IªÍ0Œô·T6EßO%ð9™Fg,|â ìäÈPÐe*òi4çsM†,‰™d29áÃ"&Z†Æ#K“UºVëý¥œ`3zføÏ«9èC=ÏÊ¥‹ð÷ò|î+_ƒª¨Ø{è0îúí° }ð ̰œqQÜõëGqÓ»/Á?|þ£hi¨‡¦ªp\·B/Š“ ‡ZãHÏÁ{fÀ·´w¼¯~øô@OZ°TóžÜ…Þçv¢˜Ð BäùÈ=Ô+ê´ô\ ÚÇÞ åSWÁ):Äx¨ó„äš{Þ²¬¸¥¥–>׊Ârß÷ãúx .Û0R¸$IšœÌAzñ´²©L㟵”Að‰e¼GfªC>–ëy†aìÈLuMgû"ÏÉ86|ŽkêçaaÉ‚¹øþÿþNXÒ×÷á! ¶‹\¡„¢íÀ#x~ˆ½=" ¥¡ëCY£úõ@ùÚ'”ÀGRÕÐîéèÈE˜?a­b’D“¯BwCh¾Úÿ÷8J4fp*÷ÏìÚã†aÀ÷}X–O +Udf<‘ÃO—$IÒäld1REÓ¸¦ÃÚÅÁ“ (sEg1ïÞ±ˆŽ…,ñŒÌñ†0•ei¶8½c½ÞDÞ_ž#4´Žùâû!ë²ø—¿ü46¿ú:žxî%ìïìçy°Lóç´àü3ÖaÝÊ¥‚pH2QSô†û¼¢(ˆ>t)pÊ2Dßü”Ç^†Ò3€„B© µ œ¹ê‡/GtÃy(ÙüÁó «ÝCf`$Ñ™–ªªÂ÷ýŠ¡c593Ô”A|öÏóâÆ)x’$¼9Çbq¼ÁFyELÝø¿íÏNãVÆ¿ÿA,º€º©:!ÏÀ†×èëôX²áXÌìQHH]TLÇåßÅb;vpô¸7Žc;R¾ßf4LÆ×Ç÷žïžsϪ(„aThOƒy¶Ç1Ðô¡ÖjÀo¿¢òûŸ0þø¯•”_ÆÊwˆùáÂ4‡&b-µ,ﻦïÇ33ï˲àºî³3 Ìÿv"T*•$Ä£78“ŸžžrÄ )À0 ÔjµR.dd'}Ü&qaéþý8Ayÿ/ݱ^šùŽÓ8IIä~u=«[ÒVŽ›˜yIóÎQîôfUiʳý™éŸ•‚;z¹ï"Ûʺ–ÞÀU/žÞÅOV/¡W.X¾äZEŽù[$eÎÌè‘“~æ8ýœŠÂSée£°ôwLŸC)²Ë^çh ¿kУÔÆ ðiõ–E0ß5 í5}®Oÿn¯FGFþ~5›ÍòIVWqôƒµr~FŒnuu•j™”Rxxx(½@ê)Aãûm|éž­àÒw¾ §Ì*ä‹6@×]l¸ë¸ã ‰7Î=«æ¸ØøÓÛ±Ö…k‰eÃ6ž¹çV uñ̽ßÅm÷=÷¸7â®9ƒÁ©øÔE׃\7èǬ ÆÝ0 ëüˆ_ àc>Þ÷7ÿ‚žt1ç2xõ1ìܾ TG=€=§^‹Q}ënÛöj`Î ~_Ƨ„7}ì3¸–0¾ÏgÐtº®ƒ€‚1@3Z·î•f 0Šúîmغ[ƒnf4¡“`»\óñÏâÍ„!ð=øM¡ð\Àà/Œú­Ýl߉ƬKñ¾³ˆ×ó â2Ê”)SvìmGß …B™2eǬ9ØòðwðÍ[ž†µæ øÝ›^‡A¯M߆¯~ýv”®ý$>qå>qí,lX{'nùñcØë0XÕE¸äMoÁ§àž/~k'ª¨êàÏÿ^,8ç}ø·ÌÆã·ÿw?ô4x:ªsVâŠk¯ÅkV áÉÛÿ/þûŽ8ÿýÁ[–ŽãþñKxÒ? ¿ñ;¿ˆãKDm‚”)S¦,ƒA€Ïþó¸òÊ+±f͚܇t®ëâÀ²e˰|ùr4›M¬]»«V­Â²eË2¿Ÿ@ÉÌ”)SvÌcˆsü1|ëGM žúz¼óí¯Å uáÐ ¥reK¥ ºY@y Šæ‹/cÑ¥¯…óøXëbÓ² ðº×_Œu<„Ûî܈såt¼üøÝøÁ=B[yÞyÎøÆ1\håz¢aòÅ—P»ô5¸fþî¾ûYÜ÷ô&¬‹b¥Œr±`ÊœK4&×`!ˆˆµ7*Ôƒµüœ°í<ÿüÏán^q1Î:ÍÁƒ?n‚ ±ûçøî·ïÄäÒ pã›Vaâ¹{qÇß…>{Þ²êb¼çæÕÐ0†n¿/OÚX°òd h€U*¡ä˜°Ú‘%á“;u^ŒóO}-þÏųQ„WÖ݆Û×Ý…ûF—⺠‚ù*ü¥ÄSÞ‚ý 4Ì]~.Î;Ù‚U*¡ìaée…R V3@Ý«â oJs±cÃZ|ç–u˜{é ¸ñ”Yxñá[qÇ7¿ƒY oÆYoº;nùž÷Vㆷž‰¹£#xöÞ[pëƒÏbäì7ãÍ+ÖÝûSÜúßÿƒÂ‡?„×¼îz¼¼õ«xì–ïA;®Í%¸þækq| ]ä)S¦LÙÑa†a€±^2ø¾Ÿù}4MkEí ÁìÙ³Q*• ëzî÷ñ}¾ï㡇B³ÙÄÞ½{±gÏ,Z´(ü^Éë\üºÅxÓ5—àůރŸo4±æ¢·à¬ÅUøª`€2eÊŽáÌ£>ŠL¹622‚sÏ=7ÓF„‚-[¶`ëÖ­ „`Μ9ؼy3¶oßÃ0pÑEeÞДJ%\qÅxðÁñ /@×u\~ùåX¸p!‚ ]þ­63Ê”);¦2,@0ë\œ_~<ÿ0¾qÛÞýƳQ5Ù!ÙC+ÿ£í°‡ ð= hÊ,2xE«"¥ ŒÐYÏZµHèŒ*€h+G„1t$µË›Æhà`bb¢µ™a­ž_´#òõ1wùÅX¢/Ù‹qý%óü hzàÃó‚pûJY«´]¯Á Ç®Á ( ¢ÖAeÊ”£k"¥Ðu†15ÃDÓ´\ùó⿘r-ïû”Ëe4›MhZKAd)q3£L™2eÇžµ`_›‹«>ð[(ýÛ?ã§}ÿE4üâÏ‚7OÒÖkYGDâÐÄLŒ"æÏ?Uc~|Çü` ü±1”—ˆ……C$äIÁ\TNz/>ý™C_¢>QM˜Ì+# pú…gÀ¤çbu‘âéÐ[§¨w˜ßÇëŸÁ²ª‡±çÖa›SÁi'ÍÛÿ~ø­Û°Ã\Žë/_Š=/¼­8„… ½„ïO¯1 —i˜7² ',ĦŸ5AÚÕÛä×2®]ŸÀÄ$iÿG –%þ+†È #‹Va÷£iÍÃêS^ÛŸÛŠYC&:K·1B F¢ oĽkŸBe%Å“[¶£Î†qÉê_Â-wü ޵gžPÇc?€ÇO\ŽKWÎRÕÏ”)SvLšïû¸à‚  ƒ¼Ñ©Õj™6”R¬\¹kÖ¬üä'?Áš5k0oÞ<ÀÄÄD¦÷áßiÆ ˜œœÄÊ•+Q¯×ñì³Ï,X/g†RVP¦L™²cÁ¨ïÃnÔÑ0›°½!\ñöw#øúâžû¾‰ÛƒóœFZ»²Xà»h6ê°} F)\ÇF£áÂ((õaÛ 4 ¬8ã \9áâ'ÿ_þQ˜·ýÚr,°8:Ž‹€2PÖú»éz à6hÚJAiçdOíqŒÛSŽí4€ú.ìF®€8çõïÂÄG³Ù„ç5Ѩ{ð¥9gãºk÷ã–»×âß6üЇpÊåo•k¢öØ7ðó½•òËøáWþ ­7ÝüZxv¦7hÐyÍn¥` p› 4užçÁXz)^¿z+îzòNüëþ—±r$@³^‡ã¶£J|M!£ðì žß®‚ÆZ›MÚúœ&ƒÛŽz¹ÍA³õ¹´UªyîÊ‹qÍj¸óÞÿÆßÜgÁAeÎj¼õ´³AI·YGÃñ@)C qʯC­æâ§÷þ>÷c•YKqÉõ×áÂYu<òƒbÝ—ÿÚÛpÍ’qد|·|óG˜û›ïÀIU ÚÑ(S¦ì´ÉÉÉÄëY7ÍfÍfŒ1T*¸®‹ñññÜïC)E±XÄš5k0þ|8Ž£]53K¤ˆ¯3äk_û»þúëẮú••)Svì!­™` AKv¥ñNó` DE@ˆ¦A#¤%M£íKÂk§¾×¡I5Cû3C@é¡ïÀ(†ÎïÓÕ-iÐ4~çŽkš_š¦£óp¬õ¹hÿ;y£”BÓõ€2ÄüÍÚ‹ ¦“–ø®"hIö¢z/:¥LÜçRÚÏMk}^Ç=…ßEø}ø¿'Z'ÖÊm"FHû»ºÞÛï¢L™2e¯V€m·¹º1Ã0  !†a ‚LA˲ðÝï~×¶©œeÊ”SƼv!iw] ÚŽ~ËüÐI&˜ï#ÿfðýÎ×úò{‰Ž6ÿïàŸIZN4ëü»ãûtuK>ZoA ¿ó=Â{ß9¯·ïy „Àç‹Qûßò¿ù{vþÍx‡e­ÿýÝZë…› ùròçú=*ŸøñÏbð=‰-cõÔg¬<¯·ßE™2eÊ^­6>>ÞÓÜ)n‚c¹‚+|ÿ¢ (S¦ìU°¯a‰›–ð·üÚ¸÷êüïLj(95á¿Ç;ŠmXÉâ/$Fc=1`¾[Ú÷ÈÊ:‰CÒkÒÞ_­ƒÊ”)SÖç5ö0|®ÚÌ(S¦L™2eÊ”)S¦ì¨ÜDi …2eÊ”)S¦L™2eÊŽF{Õ”fæ ®¶mÃuÝLÍx”);–LÓ4˜¦‰b±v‚®ëÂqœV>IZž¸gY …BdùGeÊ”)S¦L™2µ™éb#vïÞýû÷c`` ²i2eDzù~«„o©T¢E‹`ÆÆÆ°mÛ¶pƒÓË$AÇq°téR «„jeÊ”)S¦L™ÚÌôÃ8€mÛ¶áüóÏÇàà`»ìªr´”½zŒRŠf³‰Gyº®cöìÙxñÅ1þ|Ìž=º®÷eôwï^¼ð 8ãŒ3`ꈨL™2eÊ”)S¦63Ýc ;vìÀªU«088¨š„*{ÕZ±XÄ)§œ‚G}¦i‚RŠJ¥Û¶ûöؽ{7šÍ¦ÚÌ(S¦L™2eÊfêf†@7t0ßGÖmÑôVs²À‡O_õ4ÆFFF:re<Ïî];144„ÉÉIxž‡ ààÁƒ¨×ëX¾|6oÞŒ¹sç¢Z­ªÑ¢ì¨· 0kÖ,Ôëu40“–+£k­~”!²!bÇsöîðpeÊ”)S¦LÙLØÌ˜¥Šº†VjÚÜŠüÇXrÃ;qRÉGúÞ„aß‹÷ã{·<ã¼wâæ‹æ!φ†1ÏóÂ.£P(ð­o}–UÀgœíÛ·¡V«ahhÛ·oÇ®]»°lÙñxê©'ÑhÔñÖ·Þ˜!φÀ,¡ûl¿ûÈÑ  Û–¸j(–‹ v® ,)ëÒ …|߇ïû™62ððs°~ÓÎ>aÎZ>œÚ%=k÷^eÊ”)S¦L™²iÞÌX–Û?õ1üÛÏ·Ã (ü¦†7üñã4Ã@Ö¬êMàžoÿ¥sÞƒËNN=ÝrÀ<Ïëp À®ép\'õõžçuôÓÑuk×Þ‡/}éŸày–.=„PJqÎ9熕žÞö¶ñ™Ï|¾ï 9…JĮâ[(MPï îø‡Ïâ™sß‹ß>{^7Ñ'¢¡¾óüÃÿlÀÛ~ã½X`á/»ð¹›ÿ þäK¸aÔƒKUo eÝoî)¥á3‘´¡!þgíNÜøÚ5øÊ]OãìC‰š¦©ÍŒ2eÊ”)S¦l¦lfB(Æ·½Œùø|é² êCpòqÐ žëi4@4¦¡Ã÷<”hLS‡ïLâÀ8ÚU+0У\ÏcºaÂÐ ßÓ £>|J`:<×Á¿ü9ü®ÄÊ«@c ÷üän<ûì3øÐo}Ž“¼¡áeg¹ÓV«Õðw÷¹Ô\Û¶ñ¡ýNèø …ø‡k^½¿Ÿ:ÇÀžÇþoýèñö¿ÿG\rñšS†O)ºªrË¿½{À£Â©9£ðü ÎËu¨–=xݾ¿2µ™a ¾ï‡åʳXÓ¥püû'ÝL‡žeÊ”)S¦L™²#¼™á¦[ o#þè]‚‹¿ò¯Ø÷çÁ=Ã+±Ôµ±â’kqùèËøâWïÁ>Û-,Æ;?ü>¾ÿÜùì&<ú™ÏbâwKý'|ù'¯„¢´üJ|ô·¯Ä _û+|˹Ÿþµ×àñ¯ý~Ô¸ÿ•×£¤XvÜ2Ü}Ï]`Œ`Åòxäч°aÃÓ8íÔÓ3õŒ‘{hT*ÜtÓ{ð•¯ü'zìë …þò/ÿüào X,òítÄ©ØüÓÇGÿuÞóå¯â'l}aCE¾3†M/í„4±û ‹«NÃBmžÜ¸úìpÖ)‹`Q@#ulzúlÙׄ1¸§Ÿz@£M¼¼áqlš¨cβSpòqÃ`LÇð¼¹(èjà*ëÍ|ߥtÊ&?|^(Ö= ŒÕZ›Š]û&á;Ù¸~@12XÀñó«Ð¤ª€¼º2eÊ”)S¦LÙt›~à 7üÉI'”à|† wÝŠ¯ß€gù)nhVž:ïyK®¾îC·aÓªwãoÿ8oáþú¿Ž5ù þò×ß… ­Çð?bøÀGÞ ûÙçpí'þWi?ÂGÿöE|ð _Àï¼í|ìûß?ÃÍ«ñ›o=[¾óøÑ‹Ïáéç«xÿo½ Š „hX¼h öíÛƒg6<ýöãùç7â´SÏÀE¾&õ8¼ð 8ñÄC©¥‹/ÆèèhâëcÅìÙsډ͆acÝ7¿…'}ë߇·ÿîïãšåxÔÆ¿ø·¸­z..mÀÇ>ôר?k1Œýâ«_½»l p׿ý'ö®~#.X ¬ûʧñÙŸìÜ!{wÕ°ð„ãQv¶á;_»ÁQ˜µøÎÿÞ‹Ù¾' îÆçÞÿØÿúwáì:øVÖÍ †aàÑGżyó`Û6FFF¦<û'üý7c×$ÁK»m,™SÅË»'1:\Ćí lØÖÀÝë¶â²ÓæÁ2;{ÓB°k×.Ì; ¸2eÊ”)S¦¬ÿ›]ÇsÏ=—52ÃÀй½ï:³ˆÄhɯ¨à”Ó4mضaksÖÿÿÀÀÙ‹­Å*Æ®ç¡ñÊÏqpôœ4ÂÐdóðš gãGëw½áÜüÞ5xãoW}ê»8y˜ÁiDªT*¸êÊ7á{ßÿ6¶lÙŒO\ƒóÏ»0s¯ž3#ZÖ„Dü;àç?¸ïúð§qÉò*Ü€ÂÐ tË‚¥:†_ƒ7]#N:€ÆÃ7£~ÒGñŽ×ÎÅ9µøÔ_Áß/ß:‰_þò'pň× Í@}¨,Z‰7Ýp#Nv0°õƒøù3qÅ| f±“j£¬ã93bÞŒh® aûØ?ÑÄd£õúE±`Â4tèºíûjðýŒS”ÌL™2eÊ”)Sv8,³ÌŒQŠÅ«°fu OƒM‚CM µ76¤0€jé |ðï?‰‹† 4€ïp&w´J8S }p1Š[pÀ%²llß4‰áeC0››ðù|§¿ù"¼ø¿_ÅK§}K ¬í  ¼õ†ÿƒûîÿ .¿är ãFFÌ à–eYø÷ÿ ¾ð…/£Ñh$îún¿ýVÜtÓûP(Z;FfàuülþöçqëñŸÀÕ«ç€aB5P© ¢b”0«”,ø»µ½8PZŠeƒ:?hÝmu•¥:JU¾íƒ¶ßŸ Ÿ¡LY7Æ¥`¾ïO‘`À@IÃqC ÏlÙBJ•2N_sxx=´ÀAàS\¶z“L‰êŠ99Ê”)S¦L™2e3b3ã;6\¿}Š €ÂsP¾ë£h9Úçã¦×ýÿô7_Âó§.„aOÂYx Þv¶ßu.ô×ã-Ëÿÿø¥ÿÄÙC;qÇ+§â¦_ŸƒŸ~õ³xfÅø»]‚Ÿ~îñïßxùÅóPÒ9Iº®á^Uî²Ãåû>.¹äRxžŸø:J)N;íôÈîèsN¼ï_zþô_¡ñ‘áÝ Ê.ãÔ?É¡?´‘åXáü?}n¿ræl4ŽÁ·JS_®|Be}6ž3·á( |ü—Nƒ®i xó'~Œy£C88ÞÀƒ_¸žOá ¶ãGÏ´ iÊ”)S¦L™2e‡i3Ãày^óëÇÉ p|0Šóðößûft¬úå÷ÃYT€Ç¨§á´·ý:~oÃÓØ´§ŒÌ•³ ›:ÞtÓ¯`pˆÂ§³qÃïþ!V>ùzÇá#Ÿ<' P¼pöuøØ’U0< ¯yׇ1w§ -Âê¦_Ôés½^oUKKx;BH»Rš‡b°k“¨¹À’‹ß‰Ïê>þçÆßþ$ylŸ1† ¾…rë58íÂQÔ­£ÖôàUNLJ~û|æ‹Å{˜söéøß{æÑÖkiëÃàÙuØí rv­—!sIleÊ’ž‡¸ÒÌŒ ÛŸ`Öð&ê.¼„>Jyª¤)S¦L™2eÊ”õbä¿þë¿Øu×]×uÙ›t]_ÿú×ñK¿ôK°, P*•ðÉ?ú8~õW?ˆù æƒ1ö–Ñ4 „hð}žçá_ÿåŸpóûÞ¾`ðÌ,¢•ûLá9.˜nAg>¨nÂ$®GaZ&€ÀuÀŒ `—š(˜ZøZ¿]ÆÚ²Lh:_ë9 šS<DZ 0ÔnFY—V,ñ©O} çŸ><ˆ5kÖ¤FQþú×ãÇ¿‚+Ï_‚¼ý44¹ÏÌc=†³Î: K—.UÀ•)S¦L™2e}7˲ðýï?_iæ£Õ¢NŠÇÁM7¿ÿúÿ ¯ý/`ýú'°oß^¼ûÝïÅ}÷Ý‹gŸÝ€?ú£?ÁŸýÙŸàÚkÞ Ó4Å= ŒBQtß`†[h ÒtXÖ!išn½Z/å•[¯5;¾ôZ³þ—Y(¨Ñ«¬·Œö¦=©€løKgâ“¿|6|ŸÂñ‚Ôç-*ªL™2eÊ”)SÖo{ÕlfäœJ)-ZŒ?ýÓ?‡çyxÍk.!l»‰÷¾÷&èºz½†¿þ뿃ëº]IÛ”)›©Æ73Y7ޤnbägN™2eÊ”)S¦Lmfúä¸EmF‚ +™‰×mÛÿ½^W£DÙ1ùLˆã|:Ô†F™2eÊ”)S6ݦë7HÁÁƒQ(2÷•Q¦ìX6J)–,Y‚;v`pppZ>cpp°]Ê\™2eÊ”)S¦lúÌàÿ®]»Â(!$ìyr,lföîÝ‹3Ï<ÍfSýâÊ^õV¯×qÙe—ᡇB¡PÀîÝ»§–W–Ÿ}±§SÔ¼ \'íÍÌÄÄÄ´F”)S¦L™2e¯ {1¶|r¹ŒãŽ;îÐfÆ0 <þøãؼy3`||öï]×Ã>+­O¨g †i†Q‚vwqîð0Ó²Z¤öæÂuÝÐ!bŒÁNpy)dúM­f™Lº.:V×ÑJî«b±ð¤d´ª›Ž%$÷3Æàz^xhLã/ ß*YËÚl ¡ íüÀ¸·ä IDAT4ŒC!Bày˜ÐÀÓ’Ø8lH̽s6";;‚8:Ø(„ÚZæôÀ†R ?Ã0 '°1- ÿcÆÍcÕí"ØÒQ4"Ma^×á`S,•`~öøãS¯-6í÷›òÌ­gVØÔtTC$Ëjåä´ŸQ×uÃgRk³al@×4èíqEÚã&Ìyc †a@æ#¯Ý3'œoL„ÏGm6L`S°¬ð»Bà:Ρ–Nã&×|“r´Ç Þ/‰ £ÞQ†1†¢ê–¦i0r°‘×ø6küÑÎÆ4Œ° œÌF7ŒDÿG±é£ox$Ùpæ#ÆXG:‚8WOa3~óQÊ&rï– cÄÈìÙ€eË–aÅŠ‡63ôé`S(Àæêig3k|*iKc3ek6C‡¸/l§ÿhæacšáAv&6’ÿsT±éÂo.ô¦T:t°“ìÿÌT¿™RŠ“N: +V¬!áçt$‘hšÛ¶;¾d¥R9´@È“ äXPJ;d%º®Ãâ'´íf³ Ðð3 #ܸضÝÚµÿ=Zð¿˜Ä¡F£ÑÚÙ l´lÂ{çl„AÔ ›r6â`nŨ€È¦P(¤³¢"ildg|ʸIaSë‘M3MSÙÎ|&6íI@Dz&±jl˜Àf@f#=s•jµãt(•à°êºžÊ¦0l"Ï6á3—ƒMUb3eƒ,°aŒMe#mtÒØx=°i6›3ðÌÉlJyÙ§2Çq:ªg…9™ ŸÙ÷Ŧ—uŒ‚²4‰l"6†atø~Ça¥eYáFf:ØT¢ÆàTõʦ’ƒMÔ:–ÆfÊßo61k|¯l"×±¼l$ÿÇÍéÿäa3ã|Ã6Å^Ùó‘ÌFô ÃNl¦ø†Óè7‹knäH`˲r³«rű¦ÃɦÑhÌX6‡2îÞÓÆUñÞu]ïxÿéf#;e¥R©c>êeÜ䲌›$6|è† ?t’Ùt,®ÅâŒeµŽ%±‘OP ØÂFŽèÈy=åÐI艖…M·ëX?ØäYÇze:eq>’¦~²ÉëÿôºÆ÷ÊFž«ûͦß°ßþO6IëX¤³Ýƒo˜Ææpú†QläM`¯~óáö ùþ€RÎG23×uàiŠÅbøpˆ¡UJixRE)iëùÇ £(ü:‡ä8Nkh° †ÍY(iµ˜å¡é4à¸NøYÅb¦¦&ô€Âk4€ €¡ët …á!èºâ?ÿ|¾óäP¢tþðòÄÅKÜŠ›4¸È†;MqlxØ™_w]·ãz¡Pè¸î8N+ǧ}½X,Â4Íð:fñë¥vÄFdãû~Çõ46|ð(6ñl¸ã!³‘ÇU6¢Ó”öLM~ýp²á×ù|“—MÜ|$³±,«ãút°‰›¢Øˆìò²£Q2›¨|¯läqÕ ù™ËÊ&m®>ÖØ4ÚRXΣ6Qsu›´5~&Œñ:ßÈıáÎúá`ãy^èpÎ6ýôäu¬ß°_lº]ã‡oØ/63Ñÿ™I~³ëº3C<åÑ4-ÜUg ÆI€xD&>I ;&f[s0dÌ‚Æ,xŽƒµ=ð´p?P*—a6N Eh` f@¡Cƒz¹g¢fµR*†;C§»æ¡×6ÔjµÚq²•tbÁPñß§ÉêòÊ£ø`u|°q¤¸¸Å9MŒ±ŽU¼÷#Á†ËûÁ†Ÿ(ô“ ?í–MvŽa#G%’Øð"‰MÔ g®çç÷Æõü3‘8Iöƒ ?©âß—O‚ÓÍ&î™KbÃ_Ÿ‡MSÊÙPJ;ØÄâÍ6ò¸’ÙˆìŽ66ò|t¸Ù$IÅ t&yTlÒæêédÓÍ:–— wº¢Øð(f·k¼Ìf&­ñÝú†ŠM2åÆû†|£Ã•¢ÌÌáA€J¥nDÄ0PÜîK óèºÞª Ê\ZCƒå0jb–5 Â4øhu7Hë+0EËBa¼Ž¢ïcL”…À€  @¡8ˆ€h°½ÇxÙó]ëøA8,ˆ‰ÇBˆLü[vºÄð ¿.çEÉÄ,+¾3 Cd†Ö(‡Õ²¬Ž]³˜ðÅ¥òÉxÜ®z¦±Ñ4M±é#yqå“\›B¡0å„S;O'ñz?ØpI"g#/"Ó4;ØD…ä{a#J-¢ØD±ë–|=*Ú%²áùŒ²´ìp²¯kläÎ#ÅF¾ž$ÛKŠvåaÃ72œ,Nb#F)“dwYÙLNNQ6â\Í%@ql¢Ö1™MÒ:v$ÙtãöºÆ÷Â&m;’lDiÙáðò²9’þçyh6›Ð4­£lÇfÆ0ŒŽÝßYŠZ=þ¡„)¹ ¦ivü`<ÙŸP«QÀüâÌ-Ìõ<×EPuÀ*>Ð ¦‰BÃÆ€ëcYDÅgЉÓ$ ^Ë*Â4Z?(…†B݆gØVÑAÁ:vv|’C`I§xQz~q’’Cd"ð¼lä°tÔuÑéâ»rÙ)ã'bª8IŠƒUÔ¬G±Ùml’N ãØˆ2—^ÙÈN“ü öÂF¾>läÅ•Ÿö¤±I;?ØðIRÙ‹I–YÙØ¶=… ‰IŽš²²á×ù3y,°Oéºa#ÏGýd#_çï•MÚ\Ü ›¼sµÌ&ét9Ž8WÛ¶˜’‡M–uìH³×ø´uLfÃÖ¬'ã3M/þO6i¾a6Óéÿi63Í7l6›0 #Ì›?ßÎD=œ|¢ Ocd§‰?ˆüõš­cnq.ææC t8ÔGPöAç8ð‹u4ìZKËçz¨:æÍ››ÔÑ`úæÃDi²4Ý„Ûh¢F CØ¡Ûá;rŒ:yÏ3˜e™KT¹Sq×,Or(“&1YçÈCöqúY^Œ’;ð{)·« É¡Ùé`#æé`#Þ{·lÄÐk¯lâÖÃÍ&Jê!‡¥Åëý`“¶Ñ™.6ò|4“؈!ýnÙÈ2ùôWNHOš«g:›4‡5MUÍ®6irÍ™Æ&Îñˆ“@wË&‹´,/›¤¹:‰ }·ë˜ÌFvºÒؤÍÕGšÍt¬ñÓŦßþO›ÃåÿȾa^6DzoØ/¿YÓ4ø¾FÇ#ef˜ÅˆŽxÚ"êkeÖ‡0GEàü9.&†÷£æLÂs½VˆLסïCaÁl†Ÿ(õQ®–q€ŒÎšƒã_9ÏP0À4p` Š²EB‰!“““‘úY%NÏ/†Ø’N—eÇ#*<ÇFî±Ã+–È [|Â-‹aÕ1A”_ç“¿–Ðôø<ªßlø`—OÞ³²Ñu}ʸ‘u’qløƒœ‡M×Qa#³Kb#_ï•MGï‚W9BH*›(™KYÊq4°‘‹Èlâ’s{e#Vºá÷ÆGþY|{8Ø$é²E¹D¿Ù$ÍÕ¯6²f=Ë:Ö-Þó"›^×±¨|Ƥ5>ÿÓo6Y×ø~±ÉëÿôÊF\Ç¢ØÌTÿçp³9Ú}Ã^üf¹àO©TB±XŒ—™ñõrr‰½´SBÙñ0 lEV‚æpëØ;´M§‰ÀÂ. ´iÃÁ>Às½Öа²ƒO)¶ûöŽ–1·¼¦ãbldhmb(¥áw—µ|¢Åiý(¥ð<F£Õ ¹Ý,´R©„}oøÎ”Ì|‚Ê{$éùã’ºEÇÃq”ËåP³wú[.—C.QÜåÄã$d”Î1M™'üµk{”FTf#ëg³–ôŒÓˆ¦±ü^Ù$ÉhÒØD%çö“\F7›(mq¹tc6QÚcÅ&›8=¿(‹ìësŠ×+Q³ž—Mš4- 9$M$—4ï…Mžu¬ßl²D“ØDÉ\Ž›^×±¼þÌ&jÏËF.Û-¯ñIýXÒôüY6"\çØmnU?ÙD…^ãôürB|·¹b^YVÇ`¦°‘e{qlú¥YWlŽm6Ysòêùó8ÛÓÁ&)G&M Ò-›¬¹žÓͦ—ܪ,lòäÈô›MÔ:v¸òÎúÁ&-×3K¥¿~­ñ½²I›²°ÉêÌç̓n6ý˜«ã¤gb1€éÈ>¾!ï¡£ë:jµZç&I1„Åw†r½k~ƒbùe>ØxˆŒ×Ã6M` †aÂÙçÀžoc’N ð[¾i!„ áØá{ñ>3üfyè•w›¦žÖx¾"XˆÝ¦ãz^Èõ²'''qÁ```“““¡lÍóZ9<§v&&&°oß>躎“O>«W¯ÆÞ½{ñàƒvÈXd6|وףB«bxQ r#c AЊl…l„ð"?À¹çž‹f³‰uëÖ¡^¯‡ƒYÔIÆUÒÉÒD–+DÕß?lä{—5 i×åqÅF®B”µçÅt°‰ ;‹5æ“Øhš)gè'›¨>3r zþwy>ŠbU_?ŽMÒ¸Ò4-׸ê7ù™;ÖØÈQÐ~°‰’+D±‘×1¾8‹l’¤YØD­ñÇ›¨ü!‘MT¿™Ê&­:g¯=¿Äu,/y>š l’ú¡åék•æÿäe3ÝþO6q~s¿}ÃnÙ„{†F£C–š¸[ç½fÄzØqšun<ÆoPÔ3¡á6à>šÃu8M'ÜYñ¡ÑhÀ÷ý–œÌ÷Cù‡\«ÕZÿ–QÀib@£0íIèö$ôÀAmrA„Ÿ/–gŽšãä\’ÅCdžçÁ0 ¬Y³®ëâ‰'ž¥Õjûöíþ}û°}ûöŽxüã&vgMªt#ž(DÕ “<Á'=ÈžçaË–-صk<ÏCµZíÐׯi“ãäWiÞ儯¨Á<lx²[܃ŦV«u\ÏÂF<%¯ 6r®ƒÜ×!‰MÚ¸‘¯÷Ê&ª—JÜ)b¹½ÈFîx,v§;Åãã*ª>¿x8Ð6býþ,lÄg.MTžW+›´B qºìéb“6Wça#_ÏÂ&©ÏL6òß ›¨¹c• ÏuȺŽåe#çÈÈëXR¿46iëXÙ7ŒZÇŽe6Q ï‡Ëÿ‰ëù•—MœßÜoß°[6üÞÇaßÉ?@Ó´°Ï ÿob)µ(­qi™)†À\“d³1M¿J˸tL ‘Bˆ,kÑPAAªE‘Ù˜¬ÁÒ(ÌD”Ê• ”ç‘ÈZ>®¿ãZ@.;çœs@Á“O>n´‚ ÀÄÄÖ®] Ïó:¢ –e…?¯èfš&4M +/ˆ¼|ßC~br.çÊCh\ò'jù®‡ŸùïÆßæõë×Ã4ÍðÞâ‹Åß]f#_—KìqhÜõ¨ŽÊIý@²ö.Ëæé]פW6Qã*‰MTGå$6Qšuy”õµ½öuˆ;á<ÒlÒêóËlºé]Ð+›¨qÕ/6r·é™ÄF”#Äå¥uËFžËó°áóQ6Qyi½ô¼8šÙ$üÞE6²ìNîO”‡MÜ\uïG‚MÒ:&;óQò©46rÒužu,MÚ/²‰[ã›#ãÿäéù•×ÿé•M?}C×uÃjf|Ï2e3Ãf¾Ëì¨J–¢ƒ¤”´Lèf¶Ç`êÔsàºHEƒ=î d”`¢3¼(—è‹ëþ š†&e`V–f`™åÃg5ÇCScØO \Ê@€\¹¢&ËËN=õTŒŒŒ`Æ ˜œœ C\|²dɸ®‹­[·Â0 béҥؼy3(¥X¼x1t]Ç+¯¼Çq i0oÞ@V¬X±±1<÷Üs¨V«›ƒf³îFùÎTÜ wÜqxâ‰'°oß>Ì;çw.¼ðB†G}{öìA¡PÀ…^ˆÕ«W£^¯‡-Z„Õ«W£ÙlâÁ w·\jÆÙ0ưxñbìÙ³<ð(¥X¹r%æÏŸN8O=õ!Ò²¨Zá2±TlœÜAüi•-ÒJzÊšuq`òHxòÝ͸‰{ó”ì†MÞòƒiåNûÉFt ¦›üÌM›(=±jZº$6QÏTTN^·l¢¢]iläN6Iå—ûÁ&©4uÔ¸Ê˦גæ"›¨²Ý½°‰Êó×Ü~³éw¹w™M”ž&²‰“Ñ$E“ÊvÇ•Â›uë7›¼küt³éeŸilĹ:ÊoNbU¶{ºÙ.ß0K¹÷,¾¡øý¦lf䪲f] [ó™B¡ø F´8 .LB3 (ê,fƒ1`½®íÂs;“å²è²ÅÁÂyþw:E”‰ ÍÐàû–”\ôGѰ½È¾ â½EiùV­ZƆ‡‡±hÑ¢0r¥Iu’üÙ¶möïßßQÊytt?ûÙϰsçNhš†ÉÉI¼ôÒK¸ä’KP*•B¦K–,çyX·n!aÄhõ]à›&¾ lÚ´)\œž|òIŒŒŒ`Á‚xæ™gP,;Hš¶8I—-ê)m•Õ_/çNñ|q×e§+êD#IÏÏô¤~!YõüQ¹3MÔ3'V`JÊuÙD•íî–øÝÓ4ëiläëÇ›¬zþ™È&I—'סŸlÒt×YØðS¸uL<]΢çÏ¢YÓóÇÍ7ÓÅF^§ò²‘›îÙDõRÙD9¬"YÊÚKþP6iëX/l¢šÔ&åÁfÉÙKbã YüŸ™À&Íÿé–M–\Ï#Í&É7ä9{üß‹÷­ñàM#ySHÓ4ëe …Î0‘ïÃñ ˆf€2†r¹‚j ”µN6š°;¼Á°|sûóåŠ(â®çUÏÂ0ö5)>C£ÙAÙ`˜SJåC;Ó¨*@⽉ÀkµZ¸8å”SP*•:zèDi]× jNLL@Ó4˜¦æ9Žƒ½{÷†?žeY¡£444Û¶Q(0kÖ,lݺ5ü޼J›X†Ž‡¹ïû><€9sætè ňN™‹8Ø£²’j‰GiÅ$ÊB¡¨“”ÇU”†4J{,Ž~ŠÈC³Izþ¼¹IQ…é`#¾¾X,ö¬¯í•Mœ¾V®æ’…MZyñºeY‰l²Œ›£MTâñLc“vJ˜§wS1Ÿ±[6â¸ËÂ&kÏ Q³µŽõÊ&KH›¤ù( ‘m›¸žqk|›¼92izþ^ØDù?yÙDåÐäa#÷™égÈt²É»Æga“íŠb·ÆË-’ØdYã4q®NË‘é&go&°á‰ÿr^½!þ¨š¦AÓ´)'UIz6~C‰FÂJÅL- $ÌóàM»ÑÏÊ¥ÃÓ /ÀþñfWuÁÜ! û]`A.­c ›7oF£ÑÀ¦M›p 'àøãǺuëÂJb|çÈßKÊP*@ƒçQè¦F½¯½‘Oª’¤I%ö:´zêã𪃰}Öþ¾¤#&Jë'× ç»ÚgŸ}óæÍÜ9s0gΜP:&—ft'ü›ÿ`ü½£4ë\²Æƒ ‰›8>Ø<Ï›ÂFì±#žHLNNNÑAŠï—¦ƒ”uÙ²RÖ‹l²Œ9$/—ô”u’yÊ&›~hD{e“V~P;GÉ£úÅFŒ6E±‰b§=Nc#_k¶%ž>§…ä§›xýXc“T¶ûp²‘¯GIE’ØDE-º)wš•M–²ÝyØLNNQ6I¥©e6½–¦>’l¢øŠsuTHÚ:ÖϲÝ2›´u,›,ëX6ie»³°‘shúÉæH¯ñ‡“ÍÑæÿäeÃ×1±¥‹®ëÑKMÜyñð"w¦e)HT©5×u¢Áb6Ê–Ý0AÚ}uÏwÆ”Qšu9<˜Tb¯X(‚µû)¥h6 -º í9Œ D ‹Z?9‡FÔ꺎J¥Ò‘ìß}÷AÓ4¬Y³fJˆŒ³áï/k£:¼ó,j£ÃïwÞ¼yáw›r§ŒÿÀbØ9Jæ"ëgÓœ¦,lDYž\+œ/ YÇ>7â)¡èX¤%æ)wUG}&³‘#Q ¥²²I“¹D±Ùee#_çldvil’ÂÒGy‚ï'›(Ic/l¸3ß­<êpŽù™ËÊfÊ:Öþ®YØÈ…ò”;j0':3Ø1®oyTÔÉx?Ùä«»‘ GU„• ½²Ijö™—è°klÒÖø¬ã¦[6½¬ñyÙäñ›óú?ýf3]¾!¯d&Ž Mt¶ãN‡£ôl¶mwž¬ëó¬ ø”BÓZ 3÷55hf9ì¥ÂÃDòÎS¬A¥Yç׉Öræ©é¶[ŸЬª–-p 1€mçÓ¬G­×ëØ¸q#æÎökál’ꬋlxˆŒ³åZð.F. IDAT?Yéyöïß¹sçâÄO„mÛ¨Õj˜œœ ô¨SÂ(}mÔ`–›‘öÂF¾÷4£¬-–ï]f—VŸ?ªWJ\®C/5è{e“VG½ld=›¬ã& Yæ’¤çjLx4±ÉëÌG±á6läù&/¹ˆ¨ËÎÂ&3Ÿ$ê†MÒ\œ…x½T*åîëdž¿¾[ͺÌFÖ¬§±Iër$Øð\‡¸¼´<kq>ꕜ˴ÆgYǢؤåìõ‹áíG~²£YYÙäqæ£Øˆè¼þO›8¿¹[6Yýæ¬lâúì ß0m>òá앸€D±‘Ù‰ïµ@äe•d™$’{ôÂ&j®Î3n¢Ø$-žIUˆâšÔƱ‰Ëg<läëݰ‘çê·h}fäÊ^bHTU±"Цip]õzCÕâxÖ˜1Û&ð ÖöA£€Fˆôƒqg_Α~ê0Ë £p&8ž {¢æÓð‡%ªÞµ|o–eáþûï‡ëº¡œK ¡½òÊ+زe Ç ›W®]»6\àt]Ç®]»°eË–ðõ\{üÄO„e–ÅÝu]Üu×]á¿ç'š¦aóæÍaH rηÝvÂè/Ôpï½÷B×õPÃIÁí·ßMÓ:ò{ÒJzŠõ÷£ô±b_1¼È¿['±ÐAT×`yŒêþ*>è|“'sá÷š:¡ö“¬•Ùð(h›¨Š(½°I*[™$ëñÞÓØÈã*+¹’ È&ªI[6IåNó°‰’E±‰Ó¤÷Â&­Z^T“¶$6qsµ¸ðDZï-m>:ÚØðuLœ²²‘ÇÕ±À&jc#÷¹;ØÄ­cQlä¾VYÙȽRf:îvÃF–kfe#¯ñGŠMÿDz¬®ýŸ,lºõze3ݾ¡˜_Ä›æá½R¢€‹Z=9F,?¨iê&*äʤ ßÓ1 é˜p&0 ŒÅR1²\ª|&‡µ !ˆ‡R¥€¢a©aRwìÅLX,@ræåNÙ¨ïûá)^pÏóÂò|ÒælxR’ZÕu½#ô*êùwCöA R©t°©ÕjSd2üߊ'a¢,³ˆ’žÅI98›¨ÎµüߊÍùd6”Ò)|Ú¸µÃbX:j\D•õ–¯‹r†¨SBYç°Æ¹s­¼ùbÿ[Òâw¸ÙD•íŽjŒ(›86r¥86r¹Ó£…˜wÖ+ñ¤* ›¤Åïhc—{•…|Š× y>Š+‡š•MÔuñD“*ee%ÎÊFž«g2›¨¹ºŸl¢ª’åa“¶Žn6iëX›4ÿG±éžÍLðzaõÌuËæpø†<0ÀýZ±Ñê”È ×t§UJJžå@õZ‹rÆe­<00&iʦ¡8hÂ0LX¦LŒOv8÷b‡ö¨ªò®]>%”°¨J7QåNåYW+ê>_%±‘KzæaÃe.½°‰k¾·ŽMläby+$%­cyÙäí±“VžYž«ÓØÄE£äQžçM)=¶ŽI6òŸÆF®¢˜¶Æ¿ZÙdñâ|ÃnüŸ46iëX6¡_Àf&ù†qÅCĘ¦Ñ‘3VHÉuùKñ!‚°ldÀ¨n€iú”Ojâ?Z¥R%¬íЇÊ@4‚°³H`X õz£c'šTF.©\j’B> ë–MZ®C”.;N)ë#ó‹¤úûI¥£Êæa#ëù³°IÒe÷’ëÇF¾žÄ†_ï–MTD§_zþ¨~ Ilä’ž½°¯ge#. ÓÍ&J—‡M’.;ª¾¾¼¤±‘ç£(6âÁJ¿s’4ëyÙD=s3•ì”E±Iš«u6qy°YØ$éù³²IÊóÙ$­cY؈2›¸rÒ:Ö/6i¹ÓÍFž«ûÍ&O …¨¹úp³Q¾áÌeµŽišÖñß @©TB¡P<±*ÉÒ³¨°µÂrà¨n \*‚ÑÔsÆÐW¾ó 4 !`Àd;jÁ4³ªƒ=K€Fa×Ý)'Y¢\‹¥”FêõùÎ’‡È¢røõ(-_·lβR ¹Ç5EŠ“GÉ»fY_;“ÙÈe+{a#–ÑMªæ2ÙÈ×£J3Šìİt”.;M”ÆFì$†£ØˆåP»a#_?lä<™œ_”&׌Wqºë£…M’\áhg#ÎÕq¹ݲI“r¤ÍG²”£ßl¢:q÷‹M–u¬6‡k®ÎÂF^Ç›t6½ø?Gåö —›‰s‘!†¸øâ¦ëzGR‘æ‘uüº(Ÿâ;GŸ1¸… huÕ¹ MC­^C¥1Žæþ=`…FÊ€rµ —4A0Z©`bçÎöçk ºm`%¥Ù̲ÇmÎ À fÑé’«'DTÅ5 KK‚ŒJº–DZÇü«V«‰29¼˜tJÈ»xb‘Ô» îO”+L®ñŒcÓMX:|¢‘Tƒ>9÷*kòlÒ¸‰ÓÏÆ+ÎF,Û6®âØDàH«$Ë\’؈ÅC7›,Ï\TE¸¤q“Ôƒ'®šKTwúéfõÌå7½°‘ûÌL7q>âšóé|¦’ØÈÏ\–¾Vi";z½¥°I›«ó>SQmâØÈÏ\Ô¸‘£]yÖ1yk>Ü/6Ó¹ÆÇEtºe#ÏÕiã&ïŸÄ&ËŸeêÖÿI*2‘æöêÿðC£n}Ã^ÙD­ñG‹odž?‚ ˜ÍÒÄÓu=\\äŽÇyå ”R@Ó€Ê_cîh³æ@Ÿ»{ UL”‡a—ÊhŒ¡Y˜ÔM4M sæÀÞ 154Œ:ôÙ¢(Í3Q1Ðtë ¿Ñ©ƒŒëy‘TÒ3n0'éùÓºAgb#èÓôüâ$'Ö—e0Q%ø’JÁ¦•”², Ôh«ê™k8°f[0‡uL˜ ¶Û€NШÂk´*ñ>*¢Ö' ÉÒ3Q#†Ð¢®Ë§Ëò‰F^6Qއ˜¯UÑ-Næ"ËêÄÁ(ê®Åh×9feWÚZ–;ÄÌ'±áMÚäB q!ù~³¯§±‘¯÷Â&ªˆÄáf#~÷£‘ZOX³J9ÒÆMT?46¢&½[6b5<™XI'n>JcS(z’¹L'±¬w–¹ZfÃOÅæð°‘$™o6b^ZV6yÖø¼lxˆ8ÉlâüŸ¸5þXbÓ­o˜Æ&®ÈÃáôÒØôÓ7ÌÂæhõ ó²‰òäB ü>Å !îBåÊ]IúY¹Äp¤Ö¯P@Éž„K}Ôu5Û 0¢ÅŠƒ „Ac³uÀܳ Ú$€VkÐ¥0† °í&4ø(s(À0|ø¾ÆX‡^_®®ÕÓ‚kùÄ™x]Ö€ŠZ?"ë‰t=j°Š?TTHÚ g\u©46\9]l²äÈL7ùÄ¡_läq%³IÒwÃ&ÊéJc#× ;mIcU?)ì|$Ø$öô“XÍ. ›´ù¨W6Y棬läÔ¬2—c‰œ_4lÄhTœ”c&¬c²c!³磨þDYÙ¤U%›‰lÄùHf#ÏÕ"›¬ W 9á=©çWšÿUÍNù†G§oÈ£¤â|ÓQš™¿ˆw˜çºf^ MÖ«‰õ®å>0²œ!˜Cá…õ°†fè £®nÀP­”a€¡J(F|¶l‚íº íÓJ¹§è¢Q¬£`è¨50À0 ÀvUA½V^5MN@wÍbUþƒñz×âÎw~R%'%ñ{ï…X œ_ ­Š»h9<Èw¦ü5²”C\£ä ilxB–Z=ÚÙð$+›(™K~âÄFîÍt¸ØÈ×ãØˆ'¬ilä|Ô)ž’ï–Xš±6rÉ󣙨·j:ØÄ• ¯'=s²\¡ŸløâØ/6ò3ÇF|ýt±‰’¹ˆlä¹: —r­lâ’º³°×ø~°I›«E6QÏ\›´u,‰M”ÃÚ-›¨5¾W6ióQ¯lÒü™Ítú†ýf3“}Ã#á7‹U—'&&¦6ÍäÿXÓ4BÂ0O7z¶)'U&÷ï9pEÓÀPeÅ¡a°h§QÇžñq°öwð}? qUí*,Z@­~eRÁˆ=îN ?ÜÈLLLtÝóBî]À°¤ð`­Ÿ|âUš1¯4O™¤ÞYØDÕ ÏÊ&JV7lä<™\ž0­¯ƒ\Ÿ?MT zYÊ1]l¢î=I“žÄ†¿6I'aq½›D6r怜y YÙäÑëO'›¨“ù¼l²æ:D±‰*iž‡Ü+%i>Š*—Ú+Y•‡5H+M=ÓØÈ‘À46ò\–ëÐ ›~®cilòöüŠ’¹äe“§¤ùt²éuꇖæÿȲº^|ãÍÿÉëæas´û†ýô›³ú?ü0qbb"ü^S63⎇'5ÉU?Ä/%. rèTÔò¡¦ip=ºkÃ>°„ü?öÞì[²ã:ïüâÌ'3oU¡ Á ÅšhQ²M«m˶–»m÷C·W¯¥—~è·~Óßã¿Àozê^=®nÛZ¶$[«)Û¢LQœ@‘’( †›yæÑqÎŽ8q¦î½°^ȹy+ó—±wD|ûÛ@&мènXô5’Öƒ6y ï¯=ì®^B"b”û¾'¯¾8ç¨ªÊøB´¶˜Ê¨Ç¼ÖúÑ+4[î0'!s‹c3õ…Ù׃TÆ2v%¿&øÑç·ÁfIRf[3NÉ\æØØÅlKÙPÿýK±“Éœ‹ •rÐÓ”cØØ‹Ø9ÙØÏÏÁfhŽÍTó½SÙØÏײqi‹§Øèà:&ú8±q%e¶ÅðœÌe)›%‰eÓ¶­QCs 6cRcظäQKe.¿`swÙ#!:&7c3—ÿ,=4²Ù¼ˆ¹áZ6/Znh³Y›ÿè÷Ic}`_y‡apðy~'Œk-x#ƒFžåh[ù\MºÑÖ``ÈÔîŠy² f²Ýmƒ¦•§ y–£åm·ÛJ’¼Q.#(«^æÁûÐCÖHÒ5ÝF&˳®¡¦øˆÃH¾70T-Š…~÷Þ˪BUV¸ž¨Aÿ¼(JÔuÕ}ö$Iú^ÿÙóMSËç\ ݬ`£u-˜ü¬é&…'Z5À³,ƒà`òG’Íà „£àËc’8„hÕ•^Ë‘Úg n–6ÝÀó½. Ê„àò9Øíú«U1ö•s ¤»9s±ßÀššuý0(- cÐûúp·E)ÈéòáÐ%ú>S'êõ¼å¨óž ]Qäβ)ËîyEˆ"yåA.‚m]wÏ㤿"óÀ9x»Øm‡lAžïº`àa؃Aý''ƺ—`·íŸCùá ß»Ì6›J³Ñ»ò$UÏš¦FSP6½Åž†²*ÑV„M#{6EQ€·Ír6›-˜·ŽüÿdzÑÏ×±š¦ES=›0DÇêýʉ¶ªn‡ ÑÏj6ÛÝN =׳aŒa»Ùöl8G•6ž:ÍQÏÛ³²LÆ)›,ƒàËÙ\Ͳéey6Ö¸šc#¸@•e“lj‹MÇG°’´—Oy*ÞŽ³9±ŒÀî6P¡#Ùaˆd‚M÷V±вo›$øýZϳlsŽH=–°9œ•M€$Nz6u…¶$l¢¡ÇxSŸÀÆŒñW»3²pØ/gãy6i¿V·m‹:/œ1ÞsÄøSÙl‰Å°+ÿ¹i6%esbþãbÓΰáü´Üp,ŽÍ³a8ç6B <Ü›Ï 'ØØì†l€r&7c04ƒ¼ù¹¡‹ ð_¾¡jhèŸîf¦m[Ux\ï3<Ýgð˜@ª…­ºæº½ìs­9j° •H1l·\gr·!p8dÝÏj}ìó¬ìžïåg¦Ÿïðü Ÿ .p8ìÁÔ{ó<¯{½.œ’D>÷}i£R¿¿mZäyÖ=‚ÂJõþšºFQ–Ý¿ED- ªZ];—ª¨I>c›M!w–N6@žgC6yÕý¾C–Ak¹ØHÙžÅ&;ŽçûØlâîõmÛ"Ïl6l”ME€¨kr%_6±Á¦,‹A߇}1Îf³1ÙÈ“¬5lúçBµÊÏÆæØx>6Ûž ï®­)¥z>`†¾€P<ªº’·'±áÝ‚¾Ù¤£l >ûõ±l˜‡ínŠ7ÉÆ¤›EYŒ²©k]HسÁ›d›º[cl6[k=g!T€XÎf;ÅÆ·Ø4 Š\׉,c#*!¸›M’b_6zÛ×ål6'°aØîèz´–Ô§kuƒ|À(FØDq QsˆÊfú8FÙ˜qìlÝ{¿16Ù›(2ÙT¥¼•xaØl§Ù6›œ¬Õ6›UU޲±c|’$8”-0–ÿl6}Ã;–ÿ̰qå? ØHyG–V° 6Mwk±‚M5Á&ÝÌç†ù ±áÙáH6*ÆÙLä†çÈ›inxLÞ|JnHÙœœÚy³™ÿe!oAgòf.ªZ¶dÁ”5³¼mQ–ý"iZ¥õZ?[³Þÿ£E÷³€ÛîTKJëmr5Ð<ÏáuZ?_=æsU“Cµ|žçuZ?ýœjù<Ïë´~ú9ÕÏzž×iý<‡FÔóÜݦ‡lšQ6ZÏ?ÉFÝ\¹Ø˜ÖŒw‘M5ÉÆÖAÚÚc›ç õüÌÁf¨ç÷ÝãJ |ß¿,ûy©äUl„íŒ;͆ ÇØ0õŽa“$‰<É?‚ý| ›j›8ŽžÊF±s³±çÜb6ÞÙ„Š Sl”3Œ[—íbÃFjd¦ÙtÏï,›~=Òlø 6.‹á¾Ff$ŽyìVظ:qØŒÄ1ÍÆŽñ7ÁF×:œÂfÉZ]Uå(›©?ÆÆ°§±‰ñÚXå’lÆjd–°qç†ÞÊÜð2lÎãÙI¹a;‘–ï¼¹Y–73ÍÆcjã縙ÑZ<= Øl{/pêwM½Â—v¶‹šÖ ÚÖŒÔÛv,YÒóÂÕCÇö³vùëS/ð›f3VH8ÇÆÕÐr ×`<—º«ó­í³Æƒ~¬«ïÇ•«W µf´»ú®a3UèçbcÏ9›Íî&ÙÌõ™yÑØLu·?:çæØ¸ú:¼ÈlæúM±™‹cslæâرlÆâ˜m£k;0Íű¹ž_g64ÿc³4ÿ±ÙÜvþc³9wn¸†ÍG17»G?¸ïûü@%#×<.ͺ5؉­UZ>¡5¤–~Vk…­õÓ^áJë'„ô ïôµŒ¡i[dê ξ~”›5ÒátÁE|;)ã+ØXŽÍáX6À€g±i-6þ °élr/ÁÆÒ€Î±é^¿–’ÑP6͆$óÁÆD IDATB'eSÁÕžè3'œsÉö²¡ŽpDbDÙ›@’”-bcI9²<ѬÛlts±áG°é®ümù•ƒM½’MÇC™Ë@ö­:– Ñe ÌóFk„]ë Ø¬µz’ÍÄFG@676Ø8›±Ý2#Ž]€MxF6Ùõ|” ewI6*ÆO²Y`ÜBãØ€#ÆS6›6XÈf{N6m‹Ü!¿rmtÅx›MQ,ÏlöVÛ®Ì ×²¹hnh±)^ ÜpŽÍ]Í …WI’V׆ÌL墨Â&'^š¦ðÔÈè·‘Yu ‰Ú5 ë„SO\EGê÷餉[–ž` œXìq‡Ö ÙD-Ž¢î9Õòq!›EaØ=§Z>>£ƒÔl|͆1äY†–ó®ÃºôÃö:6yQt‰Ç1£Yw±1:-e£t£l”òlØ¥ØØ'clš¥Ww… ½šÍôÕì6H}V› [ÃÆšsw‘ }.°ÙL±Qãê\l¨öølìçSl¸úì{­N’£Ùè—Ul¦ÆMU¡"ÏlHo¦“ÙP9ÙØÐ8u ›©9eÏ9›=®4~$›ô6ÖZ-7*KØè„òβ™ËTm•nux WþÃ#ù~oá…Ù$iÚõô:•}`g³qå†é¹!£sŽ*7¼¥:967™ÿÌåÍ/\n¸Q%°Œì¢#ÏóÀ˜”Ž­ÑÇÚƒÕÖ³Íé ÏYb=˜Ç´~Kl+§ìç<äײqÙìÞ¦žÿœl\½P¦ôú§Ö:Léùm6ÇhÖ—ÖÜ6SÚã¹Z‡KèùÇj·5ã‹Ìƶ­\kéyN6××׋ٛ\m6Kôü§°YÇNa³¶Öá=ÿÒZ‡›f³¤Öa*ÆÛlŽÑó¿HlîZìX­ÃÒüçEb3•.±{‘rÃ%Æ-clîDnÈä&lh>bÜÌÈ+A$Nàyñ¦–ZzêœîD§ü¬¹¡åƒÒò¥†ågné§l-—ØÌÙÈѤL¿?xŒY3R{å¹]ó)l`iÒÏæFY‹,øÎÅÆ´fœ¶œccÛ®cÓ (ò£­dײ‰ãžçkÕç,›9kÆ,Ë/ÆÆ~~ŒÍî:6±aéyNÛJ½ÀßE6ö)¡dS Ø,·ížŸS§°iÛÖÐ]_‚͘=3MÊ–²¡öÊ®86·V/e0pþ 6Ëbüélæb¼É†¡ªÊI6eY®b3—ÿ,gc üI6çÌ–²i[c‰¥ù¥rÛdcßJh6Çç? iúbçÍ7›ŽÝb2p®Ùxn™™MÓ`»ÝÀó9dŸ†,ËÁy À~Sr2ôƒYt_˜ü„òœžâ1$IÚý¬=уÀC’Ä‚ :HtÀ%PÆÊFvõíÙ„a ØèÓ_›M|"› óŽœSsl`Œš°JyTnyå.ˆ¨°ä n6ý)^Ÿl¯e³Ü~½‘Ïí9µ`ãJæM¹‚ɆJ9„ƒM…º®ºçqM°á¤Ö;×£ñZ‡cÙìGظôü ©p°1×jS:¦çTd›c؈…lö+Ùì&Ø çÔPÏ?ÅÆSlÆæ”͆Ê59ýíšÆŽcçds½xÜÈ×§'°1¥šA¬o°©ëÆŠc¡Å¦$lø ¾8ÿé×Z{­>—<ŠÍ䆞ãÇØ¸ò>“ÿðÈ Scý¯‘™ËäFg9*ç3¹!w²±×êuùÏš¼YþÌáp{ù%%!5o³Œ>3Œ1yà)€Ãa¨!=E[<§õÛn‰R¼.±‹ìb_þïfyˆLʦõü`©¬#Z­õsék/ËfkhD×ÕØm7ØÅ®â‰/1Ž«8À.öœX2lhy€€¿ý«¯áˉiÛmö ðñÊý«³±9µFÆ5ndRc£3ÆfZä²4ß!ýnœó2À<†4ðpµ¢ÖA(«ØSjÖèù]µsšõ!oñœ² ×è²a³FÏß8 8Ne³VÏI6ô÷¯eãªg¼d­ƒK—ýQb³¦ÖÁÕÐò’lhâq™:ØéZ‡¹8v ›¹?Uë°$ŽÍ±YSëªuXËfm­Ã%ó›ÍšLnx ›+7ôOf³¦Føl“ŸSða_CfÆ9„@QÊàê{l¥žm™~vTË ÞxàSQŒ¢å‚Iãñ“k|ÿiƒ¢¬QV%|O÷}+­Ÿ@QV¨Ëð=xBŸæD¨ÔUr]×¨Ë o|ùxóÃ÷ñ?à©+²V¨Ä¢iáù Œ|a—Ðó¯bs¤î:ŠÜÛÅø¥—"Ôe]šBä%>,øö{ óÚZº Ñ÷¼€ €àh›žï©ÏGË„bÎÁÔ‹Ó¬’ï¥Ñ!ày  o|ùÓøêá þ—ŸqL * !9Àó±#Úãºi‘g™<…@D|Ð/¡»žÒˆŽ¹Å¬Ñ¬ÇIŠ—_¹¯=ô‘U‡¼»·Å7ÿú9pÿ ÿèÕøv†Z0øLàpÈ _.à¶ŠMËÕµs–ƒùLºz>Ò$EÃ|¡Ul¸À9ü0DKëFOÙäYxò^:ŽNgCµÇkÙØ›À5zþ%õC—Ö]_’Í©zþ»ÄfªÖa)Úkàœzþ¹8Ö¶íIlN©‘™sÒl¦4ë—fc÷¹©ú!ל£RØ%z~{£³$ÿYS?téš¼K²9¾ÖáãÁæEÊ §ØÌű%l.‘7 .૾Uœsãw4 ð<ûëkãjÖÞýÌMô©7eŸ8ØM‹ÊºÅ«¯mð+a†ÿ÷‡^€(N‡%"O ([¼ñ™-¼÷*|;ˆÒþþ›ðƒ<ÁûÂǽ]ˆ¿õÙ18~øî3¼]¢ŸùÄÞ|¡Ê3üä§à[ÙoÄ ¯|þÓøïZ†ýì~Š Þ|l°AUøÓ]C$n›¹¡ÔÃt„;&)›cC…i™Ë’ÂbŽÇO2¼óÓQ×_}óeT?y‚V‚0Å/¿ño\xöÁ‡øÆöøPxxíSWø"<ˆWàÓaƒï¾ýo5 ÿðsÁмc³»·Å—vx ¨rä×ñó¥’Ñ´Þ‚/½r_Þ´HØOŸîñŸäH=Äçw!¶»‡ø§÷[üàíŸâ[{à3Ÿz ¿ú0Â. ðí·¯ñã’Ãó||á1>»¹x‹¿wÊÈ8QXÃæÜÃKí é-¨ðc¼ù‰Oôÿæ§×` HB-óñÕÏ>Âà Ã?L·8ìŸã_ï)^yù ¿þJ‚·xïiƒZÀóñËŸÝ?Ûcû¹-ï=Áãûð[¯]!ï¾ÿßüyŽ¢,€ Æo|î ¯o}üì™Àæ¥oýðÞÍk<|àï}á>‚¶Æß/ðNíß*›±®ÀKæÔTRfŸTÍj¿|WÆÍ)l¦96ƒs+ÙœÛFwÌžÙÅÆP‘°Ž9¶}\ÙØ6¹sÖÔkØœÛbx©­7ác1þÒùÍfiŒÿ›ŸÍm䆗j?1ÇNÊ›=†TÝÔés°™é®q<&=œ…0®N—ôuÐJé5}“ÔÁu¢QÔ-~éÃ[oe¸†«8‡@Y·ÈšeUc·½æËNÚAœàÁ6@†Í½ë^‰?ùÁ5žû1~÷˯ï\ãƒh‹7wÿæÏ߯óVàAÂPîsüL¼Œ—?Åÿó˜Ã büöëÀ¿÷ß-î%ÂÍ –ûïϱÑÝYecïÚíÁL¯íŽÇu]¡mxLç%I‚  ñæ—_Æ'÷Oð¿ÿÙ5v/ßÃï|ù ÿÇ_^ãÞý{øÊKÀ¿û«Çxk{…¿ó©-^ùà)þè;{|îõøGŸõð¯·ð|¯2Áãmü¨¾òÙø•û ¾WoàyªYóïŸá›ïåø° ð7¾òÿ,Žðý´Ä®lò§ø_ø<|êõGøÛqŽÿNƒv»Ã?þ¥{¸þöS4‰‡‡Mó ð¼r°öh6k¥Ú•Nä±El.qÐã¢m[<®Þ¸ïá,ÄÏ5ŠªÅnw…÷>Èñ©ŠãßÍñôù÷]áë<üÉ÷ƒ=|ïõŠ~ˆ÷*†4âhšúýçÌÇç0üÉw£ b|ýKðƇOñ_2¿þæC¼úü þðg>÷Æ#üêÇêW7ø¯î7øÃï=F½¹Â?ùÊ+(¿÷?oê[b³dN1Æp}}=9§èzd» ¹NÂæÄ)ã†^ÉÓ±”ÍÚ>2.»Ó16Z0ÅfìäÝ%ªëzÐ z̶û.°¡Ýé—°™s:[Êñ¢±qÆø6kíÞõœ[Âf.©ZÃFçGSlìîökÙØÉü9ÙÌ­Õe6t­ÖSØœšžš7Óµº7üY–Nű»ÀÆÎ›7ùû}ßGMn£ºšÚ ‹AÚ3oi¤¤€”Á¡åÛ›‰]µ¾V„óŒ/ŒsŽìp<!(9Ã&MÁÿó•WðÏ~åüýOúÕ&+ð}ĉlŠÄÔm‹Wâ?ÿ°¼ûxÎ"|~ëI;Ѷū[/Å ‡¼AÔYÁJ7…"Ïð¬hñðA‚OîÄA„¾»CëwÓlô`¶%h/wÐïe¶wA" ˆ8Å›ÛßýYŽ$¨Ÿe¸ŽS|þ*FxúÞ3ü¸äøùãç8´þêÝ yÛâƒ&Äö*„¯œ)>x÷ü¤lÞâ'û o¼v^o „,»Æ“§ê ÀÃXàIãþƒ‘¸Ø_ï0p?À›<üìÂDu…Ÿ#ħøeÃ$>s?Æk¶ÈŠö6bžM`&¬uU'ºo&¬¼]^ë@µ¿>kñÿü#ü‡'o¼vÿͯ}ÿᅥ+&%{r" ÏëÛ゚¡J¶È³?>ŸN|\ïh«?yVƒa³Iñáu…8 pÅ*|ïÝkÜß…@œàKi‹ï=óÑ¢Å÷ßÍph9ò²ÄîùxûýÁ&ÆÃ8Àû­/n=Tõtˆ”ͲI,=–²‘5{–ž;Ôësj;>§´¶˜Î©.€8Æ oI€ëkd\lB»Ö¡¡ÚãµbZÏï®ó˜fC×£cغìf]_«8Š$ñ(J‹ÍùjÆj`–³Ól¬õh’XÐó+ŒlšØdçbãŠc6SqÌ÷üq=ÿ6vRæJæ'kR›M6^##¬ZLÄð3²±ÆØ4u³šÍº:Ød³ ÿ™dãO×ÈØ‡Rƒ:ØØªƒ]Àf´ärC—vqn8ÃFÖ3Nç?“lì¼ù°žÌùê¦FžçÆ7dfÀGš¤`¬tJá°fTïQpŽ\[zR Ê–—·-ò¢[.à>’D>ïû}¨]w]ãÀ"|áå-Þz¿E$ ü«o>ƒ—îð;ŸðÎF’88ÀóP×мĖ]!IB¼žÊθÍ>ÇÛ…ÀþɇøwŸ»Ÿàó¼püÙ;µ4}Lv‡ok|ã­Ÿ}ãO>«[ù×Ïð^%P9xÓBÛu–žª°$Ÿb#xoëbÃ[i±ædÓ4 Š¼è´‚a¨N$8':Ȳ{Eêz‘s¢ƒT׋\Zð%QŒŠ x¾¦l°>™&RŽöA½á>Ú–¡*Jpø€ˆQHâïiW\yÖo!¸Ü,$q ß`j“˜g8||õ¸W×h‚,õ!d—tPPu4>¶ÉÁø”`¼Å{?~ÏjàÃÃs|Kìð…Wâ*ÐdüÙ;9®ÎÈ&Š¢î¹ÔˆÖÝëM{f­çoº×§iŠ ÓˆJ¢~ÜÈ y]Wâ<϶Å;?}Šw~Êìîáï~õøÛ2üQ© ù”=¡ï{ˆ“ DYƒÁCݶ(ó Ly®{LÚ¡zAˆ¯}î õ>óC4õ!ž „Aˆí&AÓʛצªpµêý÷ïïðù åóï=/P%ü“ØÔÒ©Œ ¤ÄIG³Ñ¶–€‹àœHÇÒnìæ”v0ažœ3ݯç”ÚÀz>5çm‡Š›7q#2ääJŸ+í±vCnÔ:¹Ñ1Ø=0$iª>+‘Guri’vïNñÐϹ4MºõH&yÇ&¤I<Î& 'ãl¢(FS6DîÀµ]*7.6Tî°œ\«7rmdƒ•lб1ÇMÇ丒µž="“eS’q•œ‘ ³V%9\Á¦˜dcÎ©ÓØh½þظ!løñl|%ƒéÙ´6Ä Ÿ²!1^» ®™S·Ë&g#’4Aà‘µ:χVø„MQŒ³Ñ¹aÏÆÌ(™ÿË Ö›¥q,± –ŸÝ`Säà­›ÍÅsú™Îª EYDZ²BY+ÿQVù£ù•7;b|φ:¶6IÚý|Ûö72t£éÑ»íNh£·©sïLe¢•åÙ„Ö¯í7:<ßsØö^âQ ð½Ç/¿þ_{ ­JUÛ>€$ °1î<4@œ2$M ÅÏ]ÅøÉ9þãÛÏðÖÓ ï<;CRøË¿þßÞxõ•pÔ`à"/*p/ÀËa‹ÇÏküÇw3ìý#OúY·­ì:*¸Ñ„1†Ìf³±ØdÙDá2ÌN6EQF_‡Øh’Ö{‰såAï*fëíep`Cöä1¾wh·%¾õö|÷©ÀãÈOù¨ó¦–Ÿ lºžÚ+ü€¦i¾´Åë G˜nñú£Ïö58 Ø´€ã ÷Þ{¿À7ÞÉp`ÒX!˨Z8a@#ù>~T<|ç§øÿ¾÷süèy…'•ÀÕ&†×´øOý!þò™Àƒ¶ÌGÙ˜>ëËØP ižçVÿ!SCše™å£¾±4¤ö¸Ù üùÁð…W7x%fØnRÄqˆ«(jý!ƒ¢åò$\„øÜ«)RÁ!‚¯øÞË0êA/Â(Á}‘ãßý)¾ù“mèI»Sp¼ÝDøÕWdyWØy€hkì•r ›ƒÅ&%1~†f7ɦŒ›16r­žbÍŒ›ó°‹Ø°6ö¸Z7§ÜùÏéläz4Ç&g³Uµ„MÛ±æ?vn¸Ù$«rCà ß÷N`#sJZ /ñ.6΃°b<æ†é™sÃ+74ÖbG«Ï™ÿ¤3ùO:ÑŸhØ×ÊɆõäÃ!ënÎéŸ` «Fß±tR?+öcZ?•ñZ?K_;æl‘?y‚ÿ­ÚákŸ~€ÿöÕ-p<~rÀŸ¿[i„ÿðC|æ+¯àŸ?(ðãŸíq݆`BàÉ“±{¿û/aã <ùð)þýóE´ÁßüÂ#¼v•-Ç·~ðž2†ŸÿçøÌ/=ÂÿøuŽ¿xç9î}âU|éAï¿ÿ òþshš°lâœÚbýÙÙ›ÍÂ¥“Ì’+8õü±J,„@ËywZ#åQÃÁ\ë«UÆ  !€¼(!šþÇøŸˆÿé+;ø~úø9þôZÊmÁ§’&ÆÊîTázP;xàÙ‡%>ýæ/áïï<<ýð9þý‡®÷8ä—|kÿç7®ðµ¢Â»ÇÓRZì½ÿÓ=žéþçßÝá{o?Æ7~ðøÜKøÝ_޳x~}Àx«ÆÕË/ã·?“bë ä‡ô­Ÿ#W›*ƒCÏßÃq¨EÐÖ¬ÓZ‡²,Ñ6 tÇ©Á•¼«„ŒñYÍúõµ:­àhüÿà·>¡<Ý|÷'à_¿ý< ñ³—_Â?ÿ›÷Àê ÿç÷¯ñ_Âø§¿ùäÏžâï>ÅÛY æùHÓ žà0†bÿßÙ$ø¯¿úI”U…LJa’"`þówžàë_x¿÷ð?üi‰k"|üüýþ"x€ò›ŸEÐÔøàƒñ§o™ÍF”U…¦®»Ó–ŽšïôôW¹^¤çWs gCô³dãbèg…ÀnF—½Ùlºï]Ð+ycH“¤7†.[¹ÅØ»ãñ€–rIJîÆ Ëk4½Þ8Ö£Žšï“µê»Ún·=­YW¯7tÙB€«â]ªËv²Q¯\2—™qÓ’õÆYëжÝ{ŸSÖ¸Q¿ßÖ]Øì÷`žg²éd0|¨Yךtu28ÉF'êç =ÿظ¡I”%ee*ð;ÙŒ›í¶cÅ«ÿƒÍõµdCcüظQïo¬ÖÁ÷}c­¦EÝczþnܨ„uÒ¶›HË:6Szþý¾‹©ƒo[Å:Ö›^´pÜŒÕ:u+AØh f†¡¼áU沈ÖâQÛnõÞœlÆÆÍÒZ}²éb36nÔç±Ù rÃ,ëæ¤g×8ƾýîc|3YÏh°qÈÃGcü!†lsj0nÆrCÊ†Ä±Ž Üù1n‚ k¤:Z#33§èœËòÜ7³u°ƒõÆœS[;Ž¹Æ ]²¼W{GO:§Ø¿ü—ÿRüÞïýþÅ¿øøîw¿‹¶iðí÷žã¿óµ’Ý[7›´»N3û2ÈçÛí¦Ë; -äÕ«9X[õ\îÖ<ưQºn©6k”†U½> eƒ=U#“ê²<àQ##´­´W.« ¼ªÁLpxA„@-’¾ç¡Qʸ’GÅjçÙr™¯We)K±ˆécHâœùð}y–£n8|ŸáÞKWø»¯Dø·og¨äí¨ü^GÛ 0ßÇÕ6ç’“yßg`àˆ’-¸|߃'8®÷{@¨]ºàÞÕ‚·h8дužù><&”&}œi_SÒY{•¤Äþ¹îe2ò„UŸö˜ÒÎ~0Žá‹¤N<æÆ :¹Sy—”4êï…ˆ•L&ôš¦•šwÕÑ6 个.o68W§Œê€#ð±Û¤à<.8ϯ!8Cðèþû7þø­hKóM!çó€8 ;Ëóaâ1ÏÆ@šnNË„6èXdusQ¡…sJyZÓ¯76›m±½ÞÌuÓH9„’íÄöÒÍF;4餬¿²â(BF#l䕼çùäÆ%WÚOgÃlwWãlÈZ½š „²Ògb²^™læÆÍz6y–‘ã9¡ú^õ]ȳCo÷Þ×À8ÖjµVvl˜lº†ï{HÓí8›0JÑ ´®½#l̃<§v¨BÖ‰ëQ¦>«{ÜÈqµ€Í̸qÅøÞJÖXÉÇF7ÔÔë‘6àPëMœµÚd#ÇMß÷j-æi¹”Ê IDAT«ü±oÖ­ñ¶E6§ 62a³¨»—{γˆÂHÝ¢ºØÌ›é8&“m;7<ôllw»£rCלjZ{Üü‡Ée#e}éè¸Ñ½ähkšz†Íò¯ ÖGóf²‘Yφä?ÖzH ã”ÄÁá¸1sÃÁ¸qÄxóP*6bx‘ê&HëÕZíÊ›×Ä1ÍFøÍ×⫟}ˆ8Ið¥/} ¿ÿû¿?øƒ?èof8ç¨ëQ"WžÐ¾>¥ÓECB ôµZÊ!¸L¼5u’»‚Öò55Ê¢”RÁå"'–îºìºcGqŒ8Š -_ÛTÝóx# #é?í{¨U Œ¯zn$i‚0 Whº£2t2í—mký’´»c±ŒM·ÑlK“^+i”î:ŽL6•’z¨çq¢ÙÈ>2²ð¸îj!ÆØøž4Hbr½¨4é²ÿ–¹l2YSÚbÅ&ð½îÊÝc !ò¢€¯³zŒ!I·rÃÈÔ_äÝ©¤ïK (8c<Ñ€W…’pþJ6å<›º®»çÝÕ+×lT·i˾°iÛî`jÜ€©TÁRÌ‘g|5Ž˜Ç°ÓºmŦ,s%!Ž%\ ðe=nÆ£Ûä ØlæòŸ³³Q1žóŸá¸aÃq3›ÿ¸rCÂ&MOÊ cÊf.Æ[sj6Ư`#¥c”Í‚Ü0ÝôëÑXÞ,NaòæSrÃÅlT]½žSºöª¿Ñý&o"ofGäÍ\€%‰ì“Gozuèû>ÙA9ÈÛívÓ V¨ZËØ^#* ¸PÚc»SKIœnB?@E&µ®kTúŠLë²IÑ‘ÔAÖ]ðíý°åó<ˤf­‚~.O®y÷\_­êç‡Ã~\êá°‘Ûnwl°Š.†ë¾ß—©”ãŒlÒTi‡O`“=Ûãß>h;!q6ÌdÃ/̦ÈtðëuÙR:Âf³ó†lØÈ¸9ì|S×¥õlØÀeh“nFÙÈ‚xʆϳ©*°¦ÁŸåJT(Ïs°‰!a“ëEl{Ιl8aÃG®¥Í+ûÃ~œ ¸”o½ V²¡n.QöE×`êÖ êÞ»ôç¿ 6ât6ÂÅ&YÌFkÖ{§¿à¬lòC†–·7ÇfcƱi6éëà{Rµ„ l„º5XÁf&ŽÉÏ>µV/ÁÉFp“–¹œMa±ItÍݹbüilhëkdV°)L64ÿéNÆÕ¿g³qÇ1ÿbùÏn»ëjl°™È †lV冊 îln¸ë’ñ‹ç†Mk° |Íæ2¹á&•u¬w2oVezþ9›fê‰î©Ø]m -ßP{lZ7ÚZ¿Ôö ·ê@â41mälz—öXë$£>¹r/˲¯ó' ˜çuÏó¹hnÈü»‘7Ûµç]ýrx¾Ç·žWÊãšìÚu±iü£ƒ+#>éÖ϶¦V©-¶Ø£Ñ Ë÷;ëFÆT­C–ÙÐÞyѱ ƒ°+øb ¨ÊZZ7ªçQ¨-ø,6Šmœô½ €¢(¥u£nDFÙ (‹ž¹´Ø€yêÏfÃl”å§Í†Ž‹®D}¯½F”ô‰)‹îy¯%ã¦(»ÏÞÛ*6U…ª¬:ö½ž_~Ü‚öJ±ÙèM î#ÃÔ¸!Mó¼èNŽt¹Î\ªëê;6n´ý`ßÓÂô×·ç\ ¹©9¥Š(°‰-6•9n¢0êÆ]ÇFÝwulÔÀ²Ù$IÒõm€¶ÜBé¾zPÚ–žÌó°qZz6‰ƒ 7ä³wsÊ#ã&vŒÌ)•”1]`ZöÚ;ëjõ|0nâá¸iÛ¶Ó&'ißÀÎ5nÚ º“¢k„è7l8nºQ²ÞôuÖ¸µÞts®ïMàZ‹lbsÜ”e)%DjÜ%©v`Rã¦(ºNÛ½fÝ1n4ºÞ¨º3ƒM2Þ˜Ž›.1pÍ)Ç\lô¸ª{#9nTo&ʆΩN&¬jlt]šdSR6B±ñ¼þÓšS‰¶s×Ê€Ü5n@,ÍéZí+ͺãá7C6}?Ž ]‹£¾§…1§ôZE]s?=n*ÍF5¥=v:6]ß*ÒøPÈž_zÜô5{̬Q?«Mô>ˆñ¾i±$ÿ)h ·b¼=§ìqcå?qÉ¢î‘8Ö±qŽÑ’ÿtl„²íä?j)ïjÔZ=3§Žb“8b¼Í†æ?¥•ÿıQ?ÔÅ1› €²*l|m Æ3ÿQsÊȨ̗Äxgþ3–ºò6‘7ÓÜp*ÿÑkud±Ñãf$7´Ù8c<Í›ÇrCCæ;‘:öFnØ›V•%ôkq@jê53B´Zª¡ˆ!W*x]‡å@wõU?ß÷J‘…Ëý  æUÙÛêÑ0Œ xÛy…lä°{}ž²ÐÚZXSà·¿ø*nc¼r• ,*|ÿà ÛíVºÅtRÒÝ•+›9Ï“WdJVGÝÒl\¨%Lyfêù»"KÕ)»+Ók•ÎXÀ†Xìé„3 ûçNØ(vE^ëÞི¿zíµÅcl6Û­\»ëGº+Hã#Ù(=ÇÝÕ¨Á6a£˦µØxžiO8ÇF Ù²¬/†[9n\>ëiÇF.r´wA¨Oñ=/ЀˆÌ™®¡¥úìöœ7íp°9Œ°QsÊ`ÙÛI& ¼³6jdÈz#­lÔk.×+=n‚ @¢Šõaô¼PsJ³ÑëMI$‰-G¬µÅšM1¦mWÍ)62§(] 16nt'oFÆM11nZʆ;ØÐqÑßb¶6ÜÁfjÜ0kÜ´6Ùá`²ÙŒ›Ž7Á&NäQŸ`£ÆMßg†Æ±‘qã`Cmt»8FÖ+›M¢5é®qÓJMº?ÉfÓ5ǬGº!¦’W1äÆÉ»bCæ”Qœ«nT4WÞÊÞM2ƒUlŒ9%ewšM†Ê c†^‹ua±^4›‘q3`“eà¶­÷.dÃmuÒùܺ•HÓM?§)«cçóŸº!la³tÜ„Í ÿñgy/­oU‹-÷ôÇz„©ü‡°Ò½ª7®µÚšS‹sCAb<ŸÈ £1^ç†É ùO–»ÙÌæ†]œ; 1eòüGJÙ¹¡fS°éòfuã¢Æ´¼á]žÿlÚ#rÃÃ1lä?ªÖ•7w¹aÛ³\÷ÑKP×õøfFÛ3w:lfÚjOhÃFŽÊ\º®¿ã2ª-Ãaà†\¡ÓÇ‚Àï´xE‘£UV±BôºlO4øÍ×âÁ&B­v–¿õåÏÂë'x7gFÇQZ?õþ¦¬¥NÒ²Š5$@íàJ~À†Ö„ªÖa›ÎšÑÁWøž$œ½žÿlciÙ,›MBþ=¾ŽMpf6‡K³Ùƒ °9 ؘn1slèµ³îë ¯vײ‘{6Z{¼” ŽËÙ ¬'ØhI€ÁÆ–$ZÒ±)6u]£&ë‘”¹ôlúnÐ#lò›e³;#nË\|ÿh6†\a1›ëãØˆó°™”².`SÙlH]š‹M°‚½VÛ½™æÙ˜Ï¯®®&Ùl'ظb<•ùvõŒkØÔËÙH=ÿåØìvWݦ ûó²Iˆè(6Fþ“uÒ²>ޱÑ86ìéulas¹¡8-7\:n.žf¹a» 7¬Š£òæNÊzKlŽÊ Ó‰ÜÐgJV'ÝÛèïõh@8\(=h»/Lx–ÐÐA:®ØZu¤O®u‡SýGêùé`EQ÷÷®¯C÷…ÅðýžàøµOlð™—ÒOûüÆWð¹]_£bhD»nÐòýÐ^)Lé®ét°tSlØ6Të·šMlꪰ HgT—…0½v¶Ùl&ØÀÁÆÖˆî,hÏN6Nò l›M]¯c“˜lòI6Ã;»íÖÁa㼚=‘M›¶±k(›|À†..ƒþC6ô e;ÆιSٴꔲÑRÛ>ñ¨³±¥´ûüEÙ¸Ö£96Öz¤åDz‘¨a¿V“ òÅÙàÂl<Ïd£nIõüŸc†!Â04âØê.µéÜìà,,¦l0`ƒñ8µ„ ó&ãXÏF,bÓÁ†vøÎG]û8¶– 5N˜f#,6ëóƒï›lšf– ]«“86Ø ؘ52&›ƒ“ÍqùÏÝÈ í¿‚Í‹œZlŽÉ §ØlV²憻³ä? ¦­ww3£¥(mÛ"¥sL ¸ÔÀw6rj7&¦ÝVW#Óù]JË×?lê®læÈµt§»æ­²à£R¥ŸU¯O’A‚5%~ëóðé—ï##ZBm3WÖ ¾þ+Ÿÿæ÷ñ}¦jhº/Lí\½ RÓÍ¥³ì&â:6&ýll¢I6fGåBYð1uõªœtÔµr§U¢4MU­Ô 6´íÖ¿û…d˜l¤=á26ž_Ŧè~¶gCoê )‹é©›dCkdt?ʦ¯é®­•ŰdCk”fÝ`S¨9Ò³úóóÎéÆtlÓšuÑkÖÉœëŠ Aý÷e£ü÷ãÓØ„´w¾œ´­¼,›Ä`Ó8zP6õ°oÃ(›–Ø3·g`ÃÔœZÁ&5ÙÈϾ‚Mrlø lÔ ªfÃyÛ6´ÙÄ›¢(”=3#u°cqLÕ:¨¸#T-Är6Þ8Áø—f3ŸÿŒÆ1!fb¼›ÍÀîýŒùÏMç†ã1~!›:7 ïxnx›¶má1ÖIïé¦5 EoÚÖ/Žc5±§ì9‘¹¸tR Ø5˜éy††5ã@ëG¬ói±çƒ5%þΗ^ÃKÛ9)zêì Õ.x¿?à×ÞøªºÂ[O*ìWh–~v³éw§=N=ÿr6°ë@:Ízå®uXÌ&whD©ÎÑ­»î,ö²ѤsÇõbÏFèÔ6茎›–ÚJ=ÿ9Ùºoecècàí<æÐ»Ù¤ãl@-ÍUâ1Á¦µÙ()ÇEÙ–vx Ÿµ,ˆ—²›ÝÖ`3¼íšf“&c¶•v­Œ:¸Ø”å°dŸq×V)6ÞpÎImñ8*¯‚’õ²±m+²Á›¨gS•¥£žñLlض\–—M²òüÐçȵzb÷^Ò8†ˆOḛñfØxÄbØ`ò!sî6Í&Ö±Ñ}bŒú¡ãÙl¶[xÔ*ÖɆ²I7‰¹åã1ž¶ÝêÐé¬l¨5µ#Æß8›óç?£¹!e£ŒÂ5ùÅfh¿l³±,ÏgØÜfnxö¼ÙÎn07d«sÃFÕ3:Ø@¶‘}j˜qéÑ_èyòZY¨ óI–Ð`“n:‰©PÜõ"é1©õë®äU¡ ~ú¾ò ±f¬ÔïªHÐ=/ŠmÝt§ÝÚyÂÇ×>÷í‡öØ3ꄲªúú¯|_yu«,9z›8í´ÕOÑKh÷×û®+7 ÌëGö$@Â6ú S,[ušc°!׃U¼i6ëFV_ $VWòÝ­¯V 62¯Áa¯«þì›mݧ4 ôŠ}GÙ@±á=›Ý¶ÿìݸéëÁÌqC³<ÆFq÷ómM3ÕeËŸ¯•+‡þ·¢(BôãFÊ\ên\ulˆ<Ê`“öl`³Ñ>ëèí÷û½tá” ëÇÍ~ßod„|2®:6BKI6ÆÕlvȺçuÓ–HÐ<„žSn/‘G•ªÀT?Žu#4Õ|÷ ÞrsÎÐqs­Øèq³ÛI6ĺQ³ƒØm¶‹nN r­-zg¯ì™.DäÊ7²¹Ÿþyß#l “ùª(»AE!B2§Ê¢´ÆM<¹´MÛ½—T³Q¿?»>˜Úc=§¸cÜ(m±fûçýzä7ûƒ!qÜR6tÜÀr!Àn±ñÌ9¥ ÞA6:†tŒêù•k™ïùÝë 6BôrMÞëéùÔzsmé²·„®)NØhiÚ~/ÿ-õó[ò\paHtŸù³¼å(²ÞÝÊ÷<$–³,ËîçCÊFŒ°ÑsJH PÛ6ÝgwÉ|9¥ewÜZ‹™S ëÍõµ9§´„ÈX«É¸¡l¬õ†1‹+Ž%ýZÝTtÜ åQUY¢©jã•Ì…÷ò([Ï߻١/Ê&làéõjòZªm[dY†mÚtm6‰tÑ׋uŽ«¤÷QOÓ¸{^×5ŠºSÏe‡Ó “+TU…ʯŸhÖCB´xí^‚×_{„CÖëåìa벃0Âï|íMüéŸוìx¼I8)ºÞÿ¶Ö1j·Æþ³Ï=_Á¦9MéW`¾.$ŒE’ ˜\6AÝ}»r×uÅ'É4n g Ïç}ÓÆé+Ù¤n6úùظÑãê^2Ã&q°Q'eÃqÃL6Ñ ›Ä¼vfLþnéJ–6 ›ÍvÁœ[Á¦Î°ëžØlâÁ¸2ÇM/ªê ec¿{^ZläzÔ³)Ë›¸±æ”0®äq£Ù¨+|ùÙÅôz´zÜ4#lÜë‘7A !lêºFÁ kܬdšl|_tÒ–Ñqs6œ#;ºõÆSl7ÙífâØ=2çd_+¦™fS/aö·Û²y};=n”Ž\~v±2Ž5ÝóÃáÐÏ÷°I‡ãj·"Æ'idÊdc☰©*ÔAµhÜ@5œŠc’ 7Ù9nl<Ý·ÊšSɹ؄›©üg0nÄøŽ Iö×›þùaÁZ½;%7lfrÃÁ¸ñÜãæ6yŽMÌWŽ›SÖêdyþ³€MT`ŠtÄ¥lªÙü'ÄxnäÕé©lŽŒñMÓàPgØE÷Á<†€™mŒ>3zcð™W^ƒ44¯VU=€ö˜—§ÃLI„”FTõëèOùtïí¯Cê!=£•vXyF3æ¡,‹^ë'8’$UZ?ùú,Ϻ ­‘ÑÒ²<Ï 3½Ñ©êó׿BŠåúžŒìôh£2¯+r”gó-—Z=!ÎæÓϪÏVU¥¼uPŸ½×¤Ï±‘ÏeGÓýþT_é«¿gÓë }í%®otŽ`CµÇ&›¤û]C6J#zklÔÕì l<æ©ʆ©…¾˜n›ÒÝM³QúYʦªÈœSúÙnÎÙlÌ9w:›^ÏÏ {H¹§ü’t†MœÈÞªoCY·ÈFŸ./d“Ê:‘cØè:ÍFÏšlâ8éÖjÊBöfêÙÐÛñcÙH ØqlÌq…Î…ÈÍÆ^«×±ñUˆ“¶_6Øhg®ñß÷ûXËFÇð¦ûn:ÙÞèœÛœÀ†Äølì8vY6œä7èe{«bü1lÄ0ÿa½‘A¿VO³9&7œbSªz<7<-ÿY¦¸3¹a'£åyóíæ†.6Ç册1ø~`Ü73žç¡ixž‡ëý¾Û xž‡8ŒÐ¨¿ëÓgýÇ÷}øA€ZI \î ÌóQ7fÏ jw æuÏó|?°f”þí­Ù·A-‚Zæ¢ù©Ï IDAT72nMzï¦ðüùÐF®å@ëvÒIR4-íÀnjýNeãùÓl˜×³)ŠÃÀbØds=°Ø@÷Üņ )Ïq=?… c quÏÝlÂ[c³Ùl ÀNfÓªS‰Åp²EKôœ†ëÇYØÝ{§’Äî`Â`S8Øx—gÃÛQûås±1\‚ÔIÖ<1{=ºËl<Ï“lÚy6¶óÖ%ؘ½™²Bj½OdãZ«ý ìÖê‘ ¢{îfã^«—°‰ÃãØèÛ¨Sbü"6¸$›øllÎÿ,a3ãÝlΓÿŒ³¹tn¸Ùlœ¹á±ùÏùÙ\67„·>o~ÑsCýÞâ86êe2³0 ñôéÓîEú$Œ~ˆÎ*ÍáÐÔR;Tõ¦tÇcª=îú>„¡Úù §5cÇ]1§Y·n\¨nÎ.ØÒ:EýßæzZØ^áÔbÏ~~ll‹½5lè`¾ 6Ô^pŽÑz!}w ›Du®=ÛGý6újw í¤CuÙcl¢(2ØH]öÝ`c¿~ ›ÎÖR±ÑÝ ]l‚ 0ØT¤[ôÛ*v {=rÍ)ÃÖûD6F·é6:ñø•xÜ"›¹8ö¢±¡kuEF³ÙhEȱ1þ®±1¬b•þ›%ùÏ)lÎãçØè„õ&sÃ»Âæ.ä†çÈ›õßõgïM´öÆgÝívÆúåjÝAŸ»òº±¢lôÍ’ü‡~ÿÆf¦®kì÷{A€ªªLOgfz: !”–/}.í “î9M,ú+´¸{N¯õ"h'e½meÿ…Q¿l³«/•#ãÄ +Ž¥E×ÖD´1 ô¦Ù¸‚çZ6côKØÐÏn'ã/"ººM6Z#zlzé™\µê6:)£úÙK°±‡s°±ŸÓÄâRlŒNÙ6”Ý%ÙØÏ/ͦ,ËUlhß„cØŒ%œ7ÁFÖÈœÆf¬Ös ›¹„ò®³™Z«çúÍÍ©SØH½þæ¢lNÉl6sùÏÜZ½”Í11~ŽÍ¹sÛfó¢ç†mÛvÿN†Æ-sš }n߸l6›î¹K9°ÙlºÏC?;c Qᥗ^BÛ¶ð}” ç|ð¼ÛÌhhºH'cî,ö-:Z–4Ñ+2ýÜÔAj¿ëz²F!®çöu5[’°Úƒ™Yë`^ÒãZ6®‰zWÙÌ%e§²¡'KØØãÊfc³;†>ñЯ?{<†ÍÔœ:7zšãbã:]^“ÌO±±Oײ™[>JlzmñÇ— söÉø9Ù˜zþãÖê5læ6:SqìEeC[,Ì›ÛbsLþs*:çÖ²Y“Ìë[ƒ16S1þ®³ËÖlt\l^äܰidY†'Ožàµ×^3¾›,Ë ‡]ÚöDß0köœÒìôsÚìSodš¦ébÝÄéfÞô½»6qt“fÜÌèŒçyˆ¢¨Óĺ¾0וªAÐ —ÖÏ÷ý®îE×ÿ–žˆœ÷~ÖúwqÒ›@?7,„•–Êä\:Húܾ"³¯Z?r­<ÇÆ¥ƒ ðû<†ý2¹’¿+lì«×s³±µÇslô¸cCÙÙlôDcc³»¾¾>+ºÈ¹È6¶ÌåX6™òç¿-6¶fýlŽgCçÜ©ltpÔŸÝ^«ïìÛ'ïDz™Šcç`C×#›SÖêSÙ¸j~ÁfœÍÒüçÜlÎãÇØèçÎZ‡1~MnèbóQÎ ]ln#7,Ë|ð¾øÅ/Ê&Æàyöû½ñy5ýY÷û}ocÿ_+ýßz×3s¨§ÞèpÎÁ9GUUÈó¼ÛHÙ¹¡>€· <úe2ÆŒ‚y×D§»/×Dã¾ÏLÓ4ƒ/„¾[ϯóÒ[ƒÌj¾guégé\íçBãõš}ý8wÚ3ÅÆÌtìª9'—Îq)»K°¡'6­=Ö´\a »¯ƒÍ†²»4úûõÕëR6mÛžÌÆåô7Æf£{^|DÙ½ fØØ2—s²±ŸÏ± §°¡kµ–±™“]š=®Ö°±OŸ]EÝt­v%v›cc×ÙlN‰c§²Yãm6.3€+;Æ_šÍ©ùÏZ6kbü9rC»îÌîùuS¹¡‹Í©ùÏ›5¹á±y³>ûô§?Ýmdô[÷ô<÷îÝ3þNŸû¾o<·_ïû>®®®ŒçEQt‚»Ý®û»–ÞëM—+7ÔFeúg73ºafÓ4B ®µÖOÿ×õ¢Þ]Q­Ÿ¾–Ò×Dú¹ëúÑhîç¸bs%eT'i_ê š­¯¥W§B§”ƒ>÷}ò¹¾–¾$×&ð6t Œm4\llv56z!c£¡ \çØÐ[ƒ»ÀÆ~îºÒ§'eKØŒé²o‹Í˜ÔÃ^«ÏÍÆµ ´å kÙØV°Ç²±Ÿ_‚ =]Ëfɸqű9yÔm°“ /ñSlhÂz6vÝÙM°9%ÿYÂfIþ3';&ÿ¹ ¹¡ÍfÐÜx!—<üܹá]Í›éû£Ï5—1¹¦mdÀ9GÓpy`VÂŒ™jÚ-9Ïóî³¹ê‡ôáEÓ4,O¿_ÍF¯¿aF ]Ÿ½óÓÀhÒ¦Ocl úË×ÁO?§@õõ¡}õê’z¸´~ôêÕ¥ƒ{N¯õ‰uwpY !œÉ¼í<ábcë ?Šl\'KÙØW«w6.ç­5lôFå6ØÐkkzåNOÂ^6ö•½~½ÍîÒl\‰‡K®àbCOñ\lhð[ÂÆžs§²¡'¨§²sú£lìMe£ƒã/ØÜ}6öó›dC×£cØÌűÛ`£Ÿ±95ÿË aCew.6:¹=5ŽÑ ò%sûš7§iÚÕ yž×}6×áÁÝÿæùþÇx²ÏóÅ÷ñÒÕg±µnTæê‡ô&®®kCzf³¡bôfÓ°f¦N=c‰‡}=h_-‘rØþüzçèê#C ¶Æü®m-ŸK©ŸÛV±¶u®pÙèºv¦6sö„¶5ã6®¢îs²qN±±û“–L±™+x§ltAÜ’+yû4æ6ØØ¶•§°Ñ·a¶ÝéÇ…Íœ“ΛµR=ç–°qõ.8–WWW“ll]{­žc³Vt—ØØ2˜s³¡kõ©lìÓß±86Ææ”86ÇÆã§Ü©æØèZ‡%qìEd3ç$8—ÿ,ecKY—ä?çdóqÌ mûe-[ÃF¨¾`>û&žãÖ2xíCð ¿Kl\šõµllè¹ØŒ9¢,­‘YÂæRµǰ¡ÏOe³V³~éZ[ìÒ/eãòß³ ÖlNÑó»dw—b3VsWÙØ‰‡+a]«ç_ÃfÍœr±±×£SØÌ%ekÙ¸4ëkÙ¬‰ckØŒ¬œÂæ’u°v‡«ÎciŒ?•ÍÚÿ"±qÅø1{æÛÊÎÉæ£œ.Í›]}f8ç]ý}Î9ïžï6;õzõÙõzF{Wê×k75[y ?‹ µ—¦ŸÛÓo`Ì[ÿp]×£šv½³Ô§=újV_¡é‰lëkm‡ºûÒ…Ë®Æ?TCJe,«Ö=Q z°Qy=)PÛƒþ®±±OŸ×°ÑI›«Qê9ØØ½ æØÐÁìòç§lì]»ÍÆ>ѰÙèÄÃņ^ɻظ6ÿSãÊfc³³ÙØãêlì^)kÙ¸´Ç”«xvŒ·ÅÆîð~N6®õæ.²±å”­Ë^ÂÆ^«—°±õü·Í†®Gsl´#Ü›©8æ’­aãŠckÙLű96®86ÇfiŒcC看͚?Åæ1þEbó¢å?vnø 6Ëòæ5ýÐf{3y>6U uì)æzðØ–èúßwÉ=)CfÖ¶m÷&}ß7€ŒiÖm?l[?ëò×?F#J¯Èl¨ë Í®u°O¦œµ¦®ÀÖèù—²™ÓAÞ:ØÏ]ëpSl¦´ÅKÙ¸š´MÕÐù4Uë°– m0·T?ë²ü¼ 6vR¶†Nª\=/~ÁF]Æï×ó)=¿½­ec¯Õ§²™‹ckõúkÖê%lìÛ&[ÏÿQfc×:,e³$ÆÛµžslîRþ³–ÍÚügŽÍ‹œž›Í‹7Û²¾±8檦‡™¾ç#IUȆà9éá£×Z?d×ìù¾ßñÐ…þÔÈ@³ÑŽjMÓ7›†ÌL!ôŠÎ¾ZÕ»£¥Z?—”cÌbo©ÖÏÖ=·¯ìm ‘ëú‘^ÁÍ5ÛZ"å°õü.WŽs±qé²ÏÅÆ¾ž\k?¸D³~n6sšõ964@Ü6›µ¶•vs¾µzþs²™²­\ÒˆÕfC¯Oac_ÉŸÊÆ•X\š MöçØèFct­^jÛ}¬žŒf3µ­e³VÊ1Çf©”uŒÍ±ql-WR¶ÆšzNæòQf3×4Ò¶4?¦ÖÁfCçÜTSÇcò»ÍÀ›µùÏ›5¹¡K}›¹á¹ÙLåÍKrÃs²‹cú¿Ñ;B\__w·Yú÷ëÿ¯ew†ÌxKÖÁ‘e9„z=íÁ£›b!ÕƒginHÒuÉ£_–¶‰Ó]2™1GzÚCóÚ„u©ÖÏöAw?zåîÒ9j¤Þíé Çê‡\׋s»v×F¯Ï¡Y_ÃfLJÙLÕŒ±qɦ¬§Øèf[çЬŸ{ÜÜ6kõüS ›7ôõ—f3—Ì/‘G[?tظn»Æݤm ›©µziýÐØœ;•KzvWظ’¦5l¦â˜+NÍÅ1»àý6®dþœlN‰ñö¸Yã§òŸµlì„uM­Ã’>0kÖêsä?ksõ½/rn¸äFÇ•7›ŽÕzR6úg\ììqCkd\546À-Û£Ò2ZÏ8ÕÜØµAÖ¿Ž)ÚYëÑ<Ïsêªm½šmOH¯‘´–ÚÌÑ«Yj#W×5v»ÝàŠöupYèÙÉ¼ë Œ^‘¹¬õç¥:Æ9kFíw}6u]c»Ý®ô)»4MGÙ¸®]Éü½k³­tiÖOaCÇUÓ4HÓt`OHÙÙãf ûêÕfÃ9œH¬±ô<…MÛ¶ˆ¢hÐÓ‚Î9{ÜŒ±›sSlš¦éšU3n\l\=xÆØØÖ‹´gÅܸ9•ÍÜzC;*Ÿ›~?Slì;6W/”¥lš¦Áf³™7SkõR6cr{½™ëÁs ›©õ&I’‹Å±96mÛv§Ãk¤”ÍœÌ×ÅFÿì›KÇø¦i°Ýnzþ%1~Jæâ’Ù1ž²±“í¹qs‰¿Äžù\lôë笩—Ʊ5l\1þ˜9ulnxjŒ?…Í%Ö›51ÞµÞLÅ1{#DcxYÖhjŽ¢È(6qŒ²nÁº>3ŒÅȯsøC’†Èö%À€¦nд â8€a87”½ÞüëÏ£?»~Mš¦£fF×ÉèV×»—ÖÏ¥gsÙVŽiýôsÝ!ÔÖúYðÍÙÚ'¨s׃ö•üœˆ­ec7ÃÚív“lÆtÇØºØØ®”ÍœÌe-»áŒ.6sãælìçcãFOôs²qi톗—bsuuµÊÖòœllw©1™Ë¹ØØëÑÚõæœlìõF7N\#:eÜl6›Éµz¬Öáv¨úoÌÙËU€z û„“®Å§Ä±SÙØsÎŽcsò¨)6K¤côùT£ÔK°¡'ÇÄø)6cÆ-cëÍÿÏÞ›-Éu^׺3Ûʦ²:4$A‚½dmÛ’-}´ßD/áð“Ø¡;=ľ<ÇÇÛ–-6¢@‚Ø GuÙçZë\TÄ—£þìª@IˆP„€deeÎõÿ³cL‡GÍ›ð^Vþ³,ÆÏãy\–m|*±µ*zUÛxŒ_77¼¨mZ¶Nn˜àXÇ6ëú›—ã[­ÖÌ÷™w§²,Þàn|øûÈ£rznJÑl¶"N¯Q–b8FD)Šâ0&ÿ;FÕFD?¢TÒÄå$ÿ©ÿ>Þßû0êµÙïî‚<µZmzVű30³<Ï#Ïó3¸ëf}tlU¬ŸGdŽ9_†õd}]ŽÌ"\ö2®Ãyl³*d•±sÊ6‹ðú—i›Ëà:¸lå2<ÿeÛ†¯ktºªí.“ë° fݱǗi›e<˶Í"<Jšú¢¶Yʱ®mÖõG)¸Ãy¹WçwÛ,’_>mÖáÈ\¶mæA9VÅó¯#M²ÍEâØEm³(™_f›f}]Û¼¬¿Ì6ëò`_Fþ³èÜ\uþ³×ó<¶Y&…Õ¶¹úÏ=7L½®ÿ¹<óññaä1Œ<†Q”FÑhU§ÏŠAt{]ئfyúú8ëG·0ýo£\ŠF£9}ùý]´}^ß§ï.TÕ ÌLçdœ4΂±ƒÊîsJÒÓ·xR­`^RÆñ ‰?.“Ëæjz©±3_—≾e+]Fn]ÛøøqUÛ® ëØ†ã»E¶IÉ^•mR£Yï.{ñu³ å W±M &3Ošz„h™m\šzžmæÁ.b§^¶m<×± á ç± ÏÕUÛ†¯_µm@h›ep…E¶ñホmè«_…m\F×}õeØf^{l3oJzÛ,‹ñWe›UâXÊ6‹àœ¯³mRþè*m³,7LM_§Üð"¶yÝrÃUmCuMù¿y{ðjÕJÃ"J•ˆV³yžE”^ئ\ª˜Ü{6Èôûƒ(•K‘yÔªÕhBž™ÒÕj¬ˆæâ0bò‡ÊårdY6Ó¬«ê ŽF£ÍgÂ`æÈæaùT=-ãyðõEªó³ï¼X´l;=¿{Ê ‹l#ä<Û,ˆ®j‡Ñ,Z(µHKÜm³Êvúe¶Y4Z½lÛ¤”».Ë6)(ÇeÚ&åà_¦m¼ó~¶ñ.^j“ö˰Í*þÈa2‹l³ˆd¹®mm¿ ÛøN‹«¶Í¢%µ² }õ_m3ß6‹¦ëÚÆýÑ˰CAÖ± “®e1>ZdÈxÕ¶9Oþ³ªmæ)ý¥l³JKA=ÿyÕ¶¹hnx•¶yóæ^¯73Íç^)66ê»±Wù86Z›QŠ8)d&Y ²AÔ꓎¿¼ÑØhDµè´>Œ˜Œb˜ £ÙzÁ©oÔ£ZíD)ŠèõûSÛeYÕjujS}v?WúîŠ#l¸UùPY9 v6oì\©T¦?Ã¥$AêuÊäRïZ¯§$ôXEÏãÈ+˜ÂAÎÓ'æ<saG!¥®À¥EóFò‹lCÛ¹mtçÙÆmGÐ2Û­b›yyUl“Ò ?mD‚|U¶ñ±ó_ms~ÛÌÛyqÛpQ˜H’—i›uüÑ2Û¨Ju Ïc‡kj$Y¶™'i~¾ú¢¶IÁ\þj›ù¶I¡&^†m.;ÆÏ³ »Ï‹b|jûª¶ag|žmþœóŸ”mæå?i¶qxø*¹áëfW=Ó}rÛT«{ñöλQ:-”Š<^¿íVÃá0ŽóýmdQD©ÔŠNãçQêEqŠÔ«Íð‹JÑïuÏpdÊåòôžõûýéçq ½>™Lf µ2´–Ðë· ÏÏ‹¾*žß YŽõ›‡c<~6% ºrÝË䯂ëp•¶áû§„®Ú6ëÊVþXl“" ^¦mI3^Ô6þú2Û\”#³Lî]°»uðüËlsYÉ/_&d™l庘õ‹ð@ÜW_µmÖÁóŸgwÓ_Šm.ƒë°Žm–ÅøË¶Í:1~™m&“É…w~]$ÿYf›E|ÆËÈ–ÙfÙÎ/Æ1·ÍEsÃWm›u÷Z]47¼ª¼9õÝϾ¾y^Džå1Oâðð(ò¬ˆ<+"ŠˆæÔ•"ËOöÌäYy–G)JQ«Õ#ËòȲ*˲fæ"ÛèÎU*•›Ì33x9býVÍ’ÔíNç‘,×¹,#«¹Ä°pL8õÙS» øzj7 FŽƒ”m8ÖväEm#|íyl“ÒQ•¶™¹ˆmÖ¥é/Ë6ÄמÇ6«ºWÕ ?m¨A¿Ê;Ùî*lÃ;'Û{µ(ñxY¶á¹ZÕ6~®ÖµMÊWŸ×6Ë`.ËD^µmè^'Ûø^‡«¶Í*¾ú¢¶Y5)KA€RqlÛ(¡tÛÐ]µmV)tVÍÎc›E1~™m.#Æ/Ë e›‹æ†—m›—‘ÿ¸m^—ÜpÙrÛL&“©mDÀŸg›G£a”âÄ6£á0J¥fÅjðpî;ë÷û3úì²§ e•J%²,‹V«5û«Ò‘–J¥(—Ë1Ï×” ¾Ô"¬ƒU±~ëâù)#§JÙ‚•çEñüëØ†ØãUlã:ë?&ÛÔjµ3 I윫Ãù:ÚFŽ µmzÞE÷ͶŽçwÛ¤K^Ûh;ýe؆j0ëpR¶Q§j™mVá:œÇ6Òï?¯mæ-i»LÛÌã:¼ Û8×Ámã 3×µ ýÑEmCÌú*qì²y ‹l#¨È"Ûxç}‘mªÕêŒmÖÁó_…m«Ë¶M*ŽýXm£×ױͺ1>ÅYÅ6Í _nnx¶ñ=3>ÑqìÜ?™œ.Ì^\6Ò¿dÛ\×áUÛfÕEdWÉuð‹º »È6n»UlÃÄâ"xþ”ãªl3?{™¶ñ¤ë"¶uèØ2<ÿ:¶Yv§–ÙfdÛ8žÿ¢¶Iá²×µß¹Ë²Í<%Á‹Øfžÿ¢\çq¬k¾~QÛ¬‹ç¿j®Ã2Ûx2¾n[MK‰\Ä6/“ë°î¹Y7Æ_Ô6Í _nnxÙ¶YDK ìîŒm²¡äͳ&.?ÛÌs’‹:U´ãkÿj›…Øã?'Û¤|õ<‰á˶Í2_}Õ¶IÉž×6‹`.ËlCÒõUÙæ¢1þªlÃîï¼8¶®mRwޝÿ9Ùæ²óŸË¶ÍUæ†/Û6W‘7¯šª!'{¦v7-ÚϨü§R©Åfó×±·»f3"*Q‰É™=1‹¸ž²MQ1£\.G¯×›±!ÒÕjuz®¦!Nf¸a”#°UäS¸l|¡kÞŸp†uF³ËÔÖ•­dõÇØ«°ÍæææBÛ¸ßUÛÆ¥/Ó6ˈ€‹l# éeÙfÙ²ÑUl³®¤gªsY¶YvnݹUl“JæWµÍh4š±ÍªÒÔ«ÚÆÒWm›ePŽ?Û¤ F«—×±Íy ¯«mÜ­c›UäÞ/b›eql‘mdÛ—i›T2¿ŽmxçR;/þœlsÙùÏ:¶¹ÊÜpe¯E¶yÝsÃe¶Iå?ä­“zþS«nE³¾å¼å¼Ã~/†+JšsÏLžçÓ3»Lè ÏóŸ5ÙɲlF½ažmU\ö<<¿kħbõRX>á õ:±€Ë°~) >Žnç©7ÌÃú‰€z˜õ‹m1Zf›uñü\×±Í2|캶áÏ_µm–%¬Ël³ˆë°èUÙ&5íZ”x¬k›yØãóØf¶x]Û¸T,ƒëº¶õ²l“Ú籎møzÊ6”;Mù#—(¾LÛ¤’ù‹ØÆÉ³ëøêeçfUÛ¤HÝ—e›U¹«ì¹ˆmV‰cëØfY¡ã¶YÇÖ±ÍEcüUØfQþ3o¹ñëš^Ô6É Ïc›y\ÏË´ 9y„–)jò!hYQ1™Lf^W˜eÙÔ.*”ò<ŸY6ZÅtÚ¥×%¥÷ç´K1^¶q ÏÏ gFc %ÄòQJ-…õãèufÝG`©džãÁU¡:Œ2x ë§"X;}Ï–8HÁR#ý˰ GhζñÑ쪶a—ð2lC'´Ì6J(_•mRܪ×Ù6üî¿ζ™7’_Õ6)ÒõeØfl1m·ÌW_¥mØý•m®IÛq÷m3Ͻ Ûxç]r©ËâX æ²HîÔ}µïe`²ýºÙ†0™Wa›eqìUØæ"ùC ×‰ñ¯›m^§Üp]Û,‹ñ/Ó6Ê ¯Ê6µZm¦PÇg`wÓÏC_­áG½^Ÿ¾Îw2™Lk í†a¡BÌd2™Šw°¹ "‰¶©×ëÓ⋇ªw‡Ëår”Ë夯ü*;-˧×WÙów—N—A€æu/k¯ÃË´^Ÿgö˲«Ëþ%Øfèªl“Ò˜ÿ±Ù† Nxϳ+e™þ~ ³ªmR## Ý3 IDATûóÚÆ ñζIÁ`ÁêR;xV±wÏ»×á¼¶Yõέc&«@€VUˆœÇÖµÍ2_ý:Ùf•8öc²ÍEóŸ—i›Wã_†må†çÙ÷ºæ?år9¶··§vÇ3ç²\.GµZNR^">Å$tL¯w»Ý3¶ÑÏ ÇI_«ÕšBÉ-+—ËÓ=3”Æ.;_f]ä*cçu±|©‹pëbÖ/“낹\¥m¨%¾Ší.j›u¤—A€Ö•f|Õ¶ñ-æëHSŸÇ6ë@9Ü6N\÷N]¦m–%e«ØfÙJ_š’¦vÛø¹ºˆmá²ÿÜlãúþ/Û6ëÀ\V‘{_Ç6)´Î¹II¯ÃuX‡Ï¸ Èm³(޽LÛœ‡ë°.×óÏÉ6‹|õ2®Ãyl³NnH®Ãë–^†mÖåÁ¾nùO­V‹ñxyžÇáááô;ŽÇã¨V«S?Òï÷ãððp:ÑS¡×{½Þ´„L²ÑhÇÇÇÑëõfŠÅ,Ëb<Çd2‰£££FSèÙ7æ"´gF“«$̬R©Ä`0˜ù0¾Ü†•)ñl‹dä8 g$öæÁäĨ„áp]8Ç”Œ1é)¨Gj¼è—àó¥IëØÆGm–Á«–­S¶a7HÉü*¶q|íe؆ð©—m9ÁulãR±n‡r¸m|ÖymS©T¦??Ï6.Ýx•¶Q¡m–äÙÆ¿ûÉ6¾¤í*mÃÄ`]Û(á¼lÛÌ›’2)›ÇÜ6©ÆË"(GjùÞË´Í2Èâëj›”?ºˆm.ãÏc›µl³,ƿζa"ºjnè¶¹Hn¸Ì6òÕ/Û6órËäÍ/+7We¦8¨×ëÓïã ÁµdV÷ÄwS á¥×i½·îš«0–J¥ØÝÝííí˜L&ÓçFÛè\U*•™b±Ê*U{f›Íæ\Œ¨ëa;~Öæ]tßy1OKÜ«æe{åpÌú<¸Âeí´¸lÛÌKæÿ\l㯻r…w—¹Gf™mR0—TÕ5æÙ&zÕ¶YGŸÿUÚæ"úûç±Í*» æíRIÁ\ÜÁ/²ß¹Wa›ÜaÛÌóÕç±Ã5_Û¤|õ<%¿Úf±m˜t-³Í²_nßkµÌ6ËâØ«°Í²üçu±ÍUä?WiŸ¨ü57\-7”¿©T*Ó"Hþж‘8‚l£×e ¤lS«Õ¦"B)ÛÔjµ™ïÞh4¦…Œä™i»Z­63šÞ }¨~¿?}!˲¹‡ñ¼X¿EÑËÆóKK|]x«æ—‰ƒ\f›ËÄó¿lÛ\”rQÛ\6žßmñóes.Ó6çÁ¬_Ä6óFò—Åu¸(¶øuà:\•mVÅó¯j›e˜õu¹çµw8ì¶Iáù_¦mÎ˹,Û\„¶¡?Jq.¹LÛœ'ÿ¹ˆmÅø«ä¬ÊÉ{]sÃWÁ‘yY¹¡&ú|šÈˆäÏ™çJmÃ;W*•¦¯Ë±ÙX.—§¯ ®)Ø›`u)ÛT*•8:::»4So.g©\×Áã*8È”¬%q>~¤Ì%ömM‘º%͸:vH _{•¶ñ××±’²‹Øf]IÏ˲^¿,Û¤šÖµÍºxþË´M§Óy©¶ñ‰Î<Âû¼¤ì¢¶Y´{`ÌúElãþhQ—Ðm“"ç®k›uñü¯«mR 5¯Ò6©8v^Û\F»jÛ,ÃóÿXl£„uÛÐW§`uËbüeÚæèèè¥ÚfQþ“‚Ý]fþócÎ S‚??fÛðušŠ¨ðªT*S¥cÙÆ'Y–M}Lj‚<™L¦uEªñ‚{ÙîJ¥2cÏÎŒ¸âÍÌëòC§ðüT4H=PnpNaÒ)Eé{|8Hi}×jµéë)ƒ ˜Â€Öëõ(—ËÓ×SDÿ>ï,³ )¡¥»tzNìpŠ8™‚–Év„z(áÔø\^þHÏÕñúg_“mx®¸ÄÌ}©cÖý¹ËŸé¾äy>U-Ó÷USŠÁSïO(‡lÃ×üô»…H‘gõÜeýnB9tNôÜõºž;}¹ÛVq„’ŸŒcν’m‘=q¯”8è³¼«ß§×åOdŠ8P‡wNŸ-ÕÁt¤Ä@1ºR©L_×ûÓßT*•$DÈa{ºs„Á°@å9Óçó‚¶Ñ{Ñ׺º”sÔ9—/U ÇÓ÷£¯Õâ¾Æ1úZnHgþC©XŸ¾ûë¾ÛIù‰ßIÞ)æGœ¸èýt'ù:ýNîBÑs‡ÓÁw¥øá.”Ô$Ïó—jµGGG3ù ï´¾»Ÿ[ÙQ¾”çB¤oÝaŸ¸ð\èNé¹1¿©T*S_ìwJ¶U3_ÏŠ¯ki£Î•ÃË+•Ê4†Ë¶<7ºSº3’Nå?ÊatçXˆè½‘–m˜;ú¹ÐÏ3N1ÿáÂn‡–±‰-ÉeåGú¾ÞäW“þŠwRß]ß_¾Üý óbå¬EQį~õ«øçþçøÝï~÷bÏŒ~éd2™VaÒ‘æraë§—ƒ¤&}È£££©ãÈó<¶¶¶Î$ãTt`!¢„Y ˲éeÑ8::š°J¥2“Ôé@ªÓ ,àx<ž‘¢k·Û1™L¢^¯Ÿy ¼ º<ƒÁ`æï¼ÈJ,T­ÊÁ+xh<(ÛE1µ õ´õyôº‚¹’uÚ^‰‡øx<ž^Þ©“̲lz©du$ôœµ¼¨ÕjÍ,E’#ë÷ûS 9šápÍfsšx©ˆcâ!Çä˜òR©4=7LÖ™8Ï8fÙ†‡]ç–ª 䆑¨Íϧ‹¬ŸÑf\—$”QÝz½Y–MƒQ'“ÉÔÉÉGµZÞ3>W+)‰”J¥ØÜÜœ)êúýþ̬­­­™;¡;ëçVŸïàà`j×TœeÙº£"Wg\…Œìá /G£ÑôNðN‘'¢ïæ$H%Lä¯t掎f ~ív{»|||<ÓÌèt:Ó¤ŽþJ¶Q¡£÷èv»SÛ1ébbóL(9gÙ–KØô:Ÿ«ÞGg¸×ëMÇüJ<ôZµZ~6&ózŸ]¯ïììL*ú#=ùbýO¶ÓY“oÐ9Õ”­un…¹Ög–¿Ñw×¹¢ºšV,™D¥ `uÇø\ü¼¸WœQp–ä§l¥;§³!˜ŠÎI¯×›ñõ‚rèwM¿»l«s£÷÷×½9 {¨†!‰*~äKå{§dS&ŒznÝnwºK‰É*põûƒå«ôºÎ a,º7‡‡‡S¡œ k¯×›v¬)£«² “.v—õù4éóN— §œêöÈy«[ÃÉï„îŒ=}w%ö,D”Ø)!&>—Ýa%eì¬ëçe;v³õû9ÍÒsgr©‘’W¦íRx~+v¢T$ò\P_Ÿ ¥:ÚŽ÷e]ô'tæj ÈŸè»éÙð÷Ëw(qðî±>;“y}F*H*8ð\8Ü@Xa=7+&„Læ}ÒÆi¹Î¼Tu.d[5ÚF¾–Ec§Ó™™Úªñ#ÿÉ¢‡ßÝ© \þ¼îœ>›/zîôG‚ð¦“gÚÉ³Ž `°ä„7µ³‚ !ùA„z06è»ëßÔ\s’eÙÔŸ(I§È„’.uunYêuŠs²‡/ú7ñ8”)qàså”RþB¶>88˜9ÇŠÑ:{ôµ*TôÞãñxZ„rÊÉé¸lÇXÄ™sÉð’#£ ´ü¥ü›V„Gé½)9ˉ })m“çylooÏÄ`Èú>, q"Û3î*α`2Ï¯ä“ +;㩾žè\ûDEE ËÁû$ÓoÝ9N˜•O)Î1w,O>@…”~^ï/[òÜèun¯'TKù ›šôéùº0‹bЦEúîò7šPÈîl 6§sK»ÓßpJ*;³X/ÝÜÜœÞ/5CùG^=¯ƒƒƒéVSMïÅÆü†Ë?3¿i4Ó;)›Pè€5Cê\)+ä™gó@ïKn“^×ï;SÌè°SFŽ ©^'üŠšÏËFîrG`çœê ¬ºõ¡5"c¢ã•¥¸*CG-÷QUʱ4±|úürð„ŽÑ¸| ¡[*dؽ%Ôƒ*?;3ñ`g\]H}ÏZ­6³ÓÂá ®EN£B—’%ùK‡•]@’ÝTaë³t»Ý™‘½º|ºÜ:ú·” ®«~x!Ax;œúîtàì$Ç㸃œ˜ÎM #êÝc:A’$|ÀT +ø¤`.:#*Põ^š é»êÁ §Ãå{rø„GQ§Ý»1JŠè$u'\ÒS…޾;§Mä:°ˆKq!4•S—Š"“]‡¦é9jš¥ç,;néœ=MhY$¦”·ôÙÅ ÓeOçÎ'q,d¸»€PTÙF…„¾¯Ã|™8è»±ñ½„g±K­KâÙSbÁà&;ùnÚFÏJwF$ú«TñÏ;)Û«K¯à¨;¡„TöйãÏ$Ûéûë³*B¨ªïm ¯te.‡M&“™æƒËvs¯‚ß)·-'JìUäñ»æ¢;K˜Œ^—gÓI¶Ñsf+¡ÿ–\ÞN,ÎåKÙl¤¯åN újvÃSh½—ïÒ¹q!Æ!æ/´íãM'æ?Ìç˜ÿø¤M÷ŒŸÝÅ?<± N˜/áãœbÊÊŸ¤v31Fϓ٥¿qXáSLæÙ e(;¤ aš†±1ÃÜOb= çqbÄ—´6ÁtæÕpx9_'ÄYH¥T‘G$¾ûx<žk²ÈKA[ED dæÕòóš.¢I#›:ƒ‚Õ‘²Ñjµ¦qÀ9,šÒíÒײ&YÔÏéý•Ç¥ü]ª‰úSMᦉÕcçˆsŸ:¨Jm(eÕÌ„“<vºG w‚ɸœ(!Btð>âÒë48»ÃÄë»é¢*!%6XãCý Y„Õq$ŸZ¦Å„V—ØbÉÓP€`§)uQYÈÌ;lºÈ².",)±`Ò³HŸ_¤ypâkÙ‘ “e‚ÊbÀ‹8%…L,T§:ã²/ §QJø˜P²s®"‹DÏ}^ËàšeYlooÏ3MAùÝõóÕjuÚmÑÏóóyRÆn“}NØe!6Ø90a©àGÈŸ¦¤:,ªR¨EÜ(úo8'OwŽþ‰“6NYÙxaðäûëN‘?Ĥx|—‚%¯Éº„ËèêÎ9lŽSú 5ô»äËnÉd_?¯» _LÛë9ë\°ÑÃ3O™]ÝG‰”TñNêu÷ò]‚OÑW*‰Ñ¹a’ä;-ÈÉÜÒ§œLÖS‰»Ålœ¨ûÌ©nÞ°c‘'_îM#JÉ*ácÃx~òÆØ8I5”8°Û*¡ÄFx~}~N¯É[se/Å-MòôûX ²ùàü!~wçÉrJªï–‚?±¸ç¤NßMÆ):œ¬1áÔwãg—müÜê¾¥\þвQK1BUçÉvú΄•²­ä{!ãþ€ 5¾®ÏÊÎ9)ž¬>Î\‘erˆé/™kRBXÏÞ—B:_QÏ<÷Õä3z#ïL,‹4~wò§£™ß¨‘K%.ñäÈøww3§IÜI_Ì8¤"’w†Í"™8ÅÕ¹GF>Âmã¾VßÜqæÌ‹ ‘Ö¢âc¸Î5sú2Fâ´ä(‹‚™¿ÎêMœ£’&N|øó<Ÿ(^l_ФËı1ÇÊLÊxØØÑ$üI '«n@8]¢TÇÊSL£~Ž…•°’Hœ2‰€¼,$YªH$_AïåÁ™Á“Éü¼n ɧ$´3aÕeÒè“Xd9=k%lž”éœΠ‘:?«ÄXär(¼¾Þƒ_ÝkN|àô}$Ü?!@<§„‘ó¡çÆ$‡Ó(NâXÈx÷—#{Ž•I¦ít:3EžšKÓ6ܨÌd^¶äsõ„•SŸr*@ès(ÁVqÉÀž:Óšɦlœÿã{d7M³øÝ\£žÄg%& P‡‡‡Óg]«Õf`0T“áFi~~ uP S¡‚’uÁ¦óeÂGî€'¤Îß9>>>Cˆ'—¤q:J2WàB4ýŒü‘üyT²Î: LB)Á©„UwPÁ“]86V(A(§×ünÎõtÑ'Ϫ!¦³âb²>¯â˜OlX³`ÓGöa ö„UP Ÿ³¹ ¿®šqú3—bžÞ»‰‡‡‡3Ír³Äu ò@Cò +–¯—½9%e“ÿd!EÔ;ëT%#×ÄG³JÌYu“D)#ªcÁÎ|j™‹,&Ï„±PN2;çì*ð³(ìt:3Á‘S’ý]bOïïK•ôóŽÿ­V«g:a)8»$´ÓÉ©ðÓØ™NFÁ‚ð(voõ]y.xnR‰ÇÊê<CJ¢!§ LºôÜÅ… Ú•^W"Iò¯'$u‹œJ'èß]NPφÝ]tb‹©à”ZF1uñØudbÀ£"ÎØ»,Ûë½ÔY×s`÷YŽ×Õ©è0ÇdñNÂ:ÕâD4äs&^^þˆ… «ÙI<ÄGòS7[ÁQ‰ Ï:œœØ_äû‡^Åd‹E/;]œè°ñB8ÏKvrd¯¦“7­<=á “J9>±a×ÑùE:w’E%”–0b%Ð>='>ž’¸ôGŒCò=¾×Á§¤úyÆ5%´Ü†Í—Ü,úŠD°H#)\Äd¿>]ç8ç‚”jJ æKxc8“l6z &ç…gšç&…ª §N¾T…›¼s„‡žå$ÂúˆÇפ/%°ápMÃuQ}7 ^P<‡M+ý~ l0'߈ÏS Ïoæ©¶ÒW;ÌWŸŸçJqÌÏ+w¹ê™ò5"ÈáDDçNɰâe ʪBÄy®ú}:jVŠ“GÒ·þ¿šV>]ç¹Ò¹V³—Í¡}˜ø””WÞ)*s±Bî7QDû©ä{b”ë ÛËðÎ1çtžœ<åväì© NÿI ç¦sš¥Íéºà˜lLp¢ãÊ£œ®3?bþàËBy¦]-o¦˜‘Ã#i;õ@ñqéF%&LÎ]^Ř;ãºhãñxš8轉Ÿ%—X@Æx˜‰IW!@hÇÞ ~T!ãâC:Iòti”Ôp ‘ÂcÊdÄå”s,!erç}wÇAÒÉ)ñídÍ*Ps¥ªYŽ€S—žæh”¤Jçÿøayü¼Ä×R.TwÂaw)yB' R%ˆI‘üù\eJnöæÒŠ)b² ì^³ûãÛ¢9¶v^›K/ú¹ÓD†JzÎ+#DÈ¥`õ:ŸV&U„_±Så’Ÿœb2¡Ôwc7š¶a«sÃâ_ž]<ŸõÙ õ Œ† B=xçÈÍò)¨ŠðN¤±Ê6 Üò­ún:ST¿RBŸZÚHÒ5¹U*d|o?»ÇT’dBM…$ç9F˜p&®–'È"¡œØúRG‰œ6Q"˜ÓtNÈ/òàÌ8E.c}­CÇrH9UrdØÀ¢?йc3À;¨ÎGä´Ç—BÎ[ʨ3ªsÁ‰ ϼ ý¼Ãîè«}çá锊夓ç‚bGñ ŸrÆ1Â1 ëSRÈé·ûbv·u–¹>Â90¾ïƒËB)ÛÍçÎßÏs¥3¯÷§„° ·ð\êÿëÜ®ÉßïÅ¿wWÎR#™E'&lV’CL8&›0¼Sl’;ay/'6žûù*¾²QëòÌ.•Ï;•ZöÉF²¸ü¡mä¨N<¯øW!B¾¡nDMP¤EþŠŠ¶Ìm]Ö›\QÏ=õ\y§w5)~8£f¦ÊÐ/2áS±"”eÙT ÖUÉ=£SdRD’% ;Y®1OU2ÂÆ[Ì}L,Rò„~ùØ—%‰sg98Äx²PQG\ vT¹ƒ*JWó¢ó"úvz]dH’Ý| N9\—ìd·E{`˜\ 2èNÌ÷ÀpšE/ªËRµƒÐ6&qz6.oÈàKE7OM ¸¯Ã±ÃLðä}JŠ{Å} ®¯ïÝar³8bw5<ž‚–QÝÊ“ùÉÒqÙ®dC®§„3ï<×ßç4Jw!Å¡4£ÎÊÁÁÁŒm -Óᦠ.;e$çRÅGþ„jv”ûÔÿW¢ONw0)òî¯'Œêª©%á“<ù+ÝqÂT”˜pJªà3O¸…ÏF‰…ãùçm§§R¡ c¾,T]<%ËžTy7§>Îwp‡ E"xÒv„ðP®Ý9{œ~ó\‘ëÀ;¥;HÕ1ò@˜t¤|11íüý.yÎi”ïuð.éiÙ‰`ÝiòyîØ´"Œ…qwŠ»æ8 LÁX8MbRæd|6x.扰;¬8¤;Y­V§fßçv‡SÓ¨”( QlØÑ¿©³N8)Ÿ; ç1a¤Îe ©[gšEùÓ)4ŽÎUJ}ŠqPßwÑ|ÒGÿã¾>µ»IɺŠ4 Å0†m£&·î§~>ÕàÞ)¢m¨®Iä€R)®'¡óŒál&j *í…ù.>BD²>4ªÊ"LßS>N£«óý‹òåçö½UôWŒC.«M(¬s˧y·xÑ'`÷·T*ÅñÑaLÆãȲyÿ<‹¢ˆ3<î^*ŠˆÃã™æƒK¢3)ó½Wr’år9¢È#›dQ«oÌ$*—˥ˆ¢ˆj­þ‚C8™D¯?ˆ,›DÄ BpsΤŒß›r§œ:ðŒ»@F»ÝŠS¨££ãˆR)Š"lrb;WÁXÊ¥RôúƒiB;ÛX‰È²IdÙ‹…™y6‰IvŠÛβÈóìôÙ5Î@Ï\QŽüJ2®¶§àêÒÔä¼Q@ƒ&Mäzæ(ò<Ì£ÑØˆ(•gø?䑹”ýáá‹87…ªNÆ1M¢(ò8::Ä'“_ IDAT޼ˆ30cNëR ±¾î»»ÜÝDYZWßdãC¿›‰í«aQ¥B€ÝcªßÌøÞÔÎ/&aÞðcœ 3wRS¢6|ñ!›.!,ŽáQ<Tçäž#î*aŽÓ$Š“¤x"<7Ùdy^D »LôþzƒAÿô\žòPŠèY¥ž®CÙ¤bœõ)¦P$Ä“ Á˜ _ì2!;В… ¹Î_æ=NØÐ#‘Ð1æGJæ‰Ö¡mÉÙã$Òã:šÚpaÎDóp9wŒ#¼Ï®®É@ωd'Äûwwk¹\žÆ)/!ü›w‚SNç½iÍ€s«\dK…‹@GûHu•òËä] ±Â"Ñ׎¸àóZG¤èN²pò_e'SÀ+SrŠ¢ˆ^åìiüçÿóyd;oÄÿõ«_F~ðiüÛ{ñÑßþcìÖDÆ/¢\*Åf»E³2nQ®T¢RfGâ$ Ÿt²ŠÈóY ¾Ôn¯Î¸Š£]ÁFƒÁtw$;¨ÞåS'ŒNSBÃØía€ƒ×çßÛÛ›&:œV‘èG2¾Ëè:ÞŸ²š.1LU4BA\âØ í¼<ÜÑ#¬?»9\ÞDR¶ëã“TÍn³l«.€«q¹ sdü¢³Õwg€¢¼Š1á¾)K'¥ÄBxwâg9:Õ¹ê<ŠoïÝ‹GÇ“Øl7£¶óaüâ½Iüû¿}ýRDLkñáGoGöø~|׿¿þõQ:xÿïÿ÷itþîÆßìnD^Äô\qgU‰|$Ï" ’·ÆsK%Ab‹]í…Ý%,œ\ÎÔ•v²,‹(•b|ü]|þùÃh}ø‹øÅ»»qøÝïãß´â—s;6ªÕ¨NGêE”Ë¥è>ÿ!þx¿~øfÔKEE)Ú­V”+Õ(Ey–Çq·Õj%ò<¢\.ÅÎÎÎé‰È‹"†½^T«•ˆR9êñ<þðÙѸýñw·›§çê8JåJäED%{Ÿü×÷±ùîÏâgï_‹Aï0îþþ?¢úÞ?Ä^þ8¾ûöA J(ò<Ú{·âÖÛ7¢6E æ4Œ²&¬LX©tb»VTŠƒøÏû,zåjLÆýñÆÛïÆ»o4bÿÁ·ñUåÝøùGÛQ-½½,G¿þ$ÄÎî$šõÈ Ë‡ñýÏâYþvü߿ގÈãàî⿇oÄ/ooÄwÿ?<D«Õˆ¼ÔŠ·?ú0nlÖ£ŽŒ/}T÷š|D.€”İK¢§sãû@êJèYDD‘â›Ïÿ3þøp#~ý¿~RÄV³ˆ/>û4&»?¿{3SþQ%ªíjÑÛ,&§M›a÷IÜ{0‰¿ýÅO¢RÎcÿÁ×ñÕ~'>¾¾ÿç?Ä?ýE|ôV+Ú­ÍÈó,*§¾V\ ÙckkkO¯8D0Ñh4U„c×Þ¹œ.M-ÛøbB"èËõß*Î0Ñp9T2$;FçúÚµkg ‰úîÁ¦¨ W,P™”\P‡c²! Æ÷ÚÆÏîÊ\œÎÏ“óA|÷ÇßÇãA3Þþ‡ÿÿãúF †£ÆQ.¿PY»y£_~òyT®¿·o¶âèéÝøôóG±ûîÏâ½›ÍhMùA¥˜LN äZíŹh5›1ɲ¨œ~Gîµâ¤@±€\P~_ÁÇUàºæÄÜéEÔ!FÊG\Z:"b{{{n©›0^9Ÿvia&sr·Y$Ÿ‘ðs.¥tÙn³<Æí¾Ø×–Ðv„=qL8'·ïÜrÂ"#TˆÔ"AA}— §š˜ÚE8'·±rÈf%“.úr&œÎ³ãïÜâD5Ôeó¥Õ乪aÂɦåàÃS{©È“`³’ I΃ìÎ'z6ãÁQ K;±Ó.âù÷Ï¢¿sãÑßo¿½q)n¾÷~ôö"z_Ä£'{ñÑ“\©V¯D£4Œû_Ý¸ÖiDiü,¾¸{v#ò(¢±óNܾوçß_ÿð$ò¨ÄæÞÍxç½™f% dç‹ :™Nþ³iBšR9äŠWeM)‹zÏ€ºÏ„[:ÇF>Žù“+Ò2?q s;oŒ0÷#¼ŠBjÔRñ–qŒ¹ã _'-€q’S‡ÞSùËi fáR¾ËÜM¹‹L*ýqõ¡¬ô7„sÁ®|-÷Z1?"4Ÿ”ý<ùŒ„cú””¢YjŒËÉFË4ÇNíàHœN2pY–E{s+:íNì?xY”¢ÛëžLTjÍØ»q#n]kÄw_Þ‹î8Ⱥñíݯãi·ÃgqÿÎçq”Õ¢»ÿmÜ}4Žã§wâ¿¿~;7nFõð~|ýÕwQÔ6fHž©íô²Š%–ŸÛéuÛíöŒùÈݛ±·QŠrevÚ•M&‘åY Ÿ?ެ}#¶Ë“G9×Þˆ½ÍVT[h•"ÆÏbX¼€9TÂ…(ÁÑétΓ£\vg'Þ¼u=vÛõèõc8FœÅÃ/ßMâÚëÑ*å±ÑjG¹R‰ˆQ<úÓ'ñŃ^lmoF%NîÍfû´1s W;zö(zåÍØÝ(Çðè06®¿»[h4Û±µ³ãg¢;žD~Úûïxx4ˆêSÜîk¼yg¸ð’Ku.ÔyfaAYì”|òááá̹b!¤b€ÜªÔr?ï.³AçÊ£Îp²?}¹+›R)PÐ*%늑Œs*4˜TéÜ©sMÃÖÖÖL'šùâ§KärN²I”‡Ç‘u®Åí7¶"ºâÛý~”ÇûñÅwâûg“¸vóF”Š"›­¨F)²¼{Ûí¨”&1Œ¢^ÉâîW_Å÷ûE4êyÜÿôñíA?ЬOžÆ Túè0~¸÷e<Ü߯¾ºyk7nìlF£ZŽ:lONIÝÌotÞô\¨LJ³èÜÈ6òG”Ž&ºgkkkÚÆIaulj :E A¯È8H•DŠHèL«!§sÃ¥Ž¾ÞU[)AL()mçÊZŒsôõ¾QïIþ§¨z–.D^›š,Ò™T“›|=ç^±AO~5ófå¶Ê{õwî'Rœ¢mS`ŠÈGËš#µFù ón>·2 J¥ñ0GDÌß­N'Š(E{÷ZlæãÓoŸE¥TŠ"È{Oãé£Gñí£ƒ˜Œ1˜dqtÔ¨µãÍÛÇ»;•Øì\‹wòaì5ë18îÆ£ûßE6>ŽûwïÆ~¾íV9Ù ˜ ÉÁÄr,Î}‚Oé"»<3¡`©ñ"—j’ìÆî3GŸ¬S… G­ûêý8>$Uï/‰œ‘„ôž”[¥º”&& Žéë0pß;¤”_Öÿ\X(ð¢ùŽr¡$[)l¼ ý ‰Ï² bä)Íèªf:7$Œ˱3ñ³ÜšË;A8ƒ.*E$8 ;»é:¢ÝnE@óÿøè(Š(¢TŒãá7ŸÅWQoîÄ·v£Ýã“×c*-Ýžá:pÚ%ÛqÒ'(ˆ>ƒ’>òâX@ëÙÍ`¡£nþ[ªüHH •ntngÈúQÖn+bÿëxÔ(—#¢?Œa^ÄáÃûñýþ0ý'q8¬G{³QiÆû~{F´›Åw÷ŸG£³½§£›E¼ýî^ôŸ=úÍ7ãí·ß‹Qub0:i†\»ýóøðÝ›±µqò|}óEä×ß‹÷on¾À¤gyyDv:-+òQ<ÔÝ[×¢5幜r«Æ£ˆ8ýîì|Ë[åpBMõlŽO ë§Ð”f«} Ñ-¢È‹èõ¢ÖhE1ìÆƒ‡OcãÚͨ—òÈ‹RÄÑýøô»^¼ó³¿‰k­êó.NHä'wjp<ˆZ»õòɹ+ò<Šüt'Ç ¥)ߎ^N¹Á|>ßùåð)ª0²»+ÂEª,düØAm·7£TŠ©­ºÝnD©›[×b²•¼Ï‹zì\Û‰Éþóxrx½'÷ãþ“nT*ÃÈ*ØÜjG©¼»7nF=ïÇôÊœúêI¯ýñ$ÆûßÇg_|Y9nV:#ÜâwNI8õPw™ÝcÊSSî]ß ;ªS êÁ&§EÞ]ÖÞ+_€çþxN|Ô]¦ñ ð”ÚgçÞááôGT¢Â’âå“ óe3qÂ,å£È#!éZ½­N-ž>ìÅF¥•ÖFôŽŸÄ“§ƒ÷Ž£7Åí_ý:>xçV¼}}7¶®mÅðø8꽸¹ÛŠJ©íÍvŒ»Ýèö±õþ‡q}{;ö:“xr<Žj¥Í­½¸öÆíxûÍûqÐÅF£GOųî8Z­(£xp®'§qê¼SYÕ‹‡Édz+ÛðuŸ (F³ V~¢ß'yfçÜ1÷$ W¹'ŠOá¹àBN6ätçÆ "FÍL;å}„G±áGŶ”ïay2à”‚ùE ôÇ$"Æi„!»Zž¦œŒÃ®lÊÅÏ„®©‰ˆ“õå«)páù‘ ŒcÊ›uçÈofÞL~©¦¨ú}’{Oª™±”R“Á[­V”ŠÓŽmµ»­R|ûu/ÊÍÈ{ÏâàxÍ÷ïUÇ'Ÿ=Œ^¯Ír)¢Q«V£ÓnGqTŽr%b<™Do2ŒZ«QoÆG?}?v›•MJÑ©—#;%K;Œ†d^òHô‘<•½æ%û„ÁÈI£ÃÎÑ.õûÉ5`Õ=oŸ‡+mëPjÄKxSJcž{çH"¡/eŽ 'y ¼è„ŠøxÑ÷B( î’Éåvzêëó»ó»QšZΚø]—ÁuIQ]d—üt&J3rÒÅi˜cÖ§êÎØ~ú<¾{ò]<Ø.EmÒãA%vZQªÅ»?ù»xûúVÔQ/Oâ`4Œ÷âÙÁQT{½¨4v£]+E^‘ÙÆc’®å¤|× —ÔrŽìIwÙ–]K*¢«àÃì¶8~–B:Y–GžÑïw£¼ùA¼·ó(¾xÜíwÚ±Ñ,EƒØyç§q­6ˆãÃn´š¥w+ÑÚ¨D¯ßJs#ZÍfŒïÞòZÜü`7º÷îF½y+v6"µj ãÉÓ<Ž{yT+ըתÑjµ£TŽ(—J14F=ÿ!žìíÆß¼³“Éi÷*?y}«\Ž|ð,žå{ñ·×[‘OFÑÙ¨Æ÷ßݪףÚûÃqlÞ~36kÕ3Pu I@UÂÆé8÷ ¸è)){<ˆÑ Ï<Žq©vÝíEYÔ:oÅÇîEir÷ï~ÃÚÿŒÈ£—Õc·9Œ÷¿‹ÝÞŽÝÍSié89WÝ^7Êåëq8ÅÖöÍØêlÇñ`;ªâÁ“gq\Åó#koEg£­vóŒ´4ïÏŸ;ñ‡ØõÎF%Z›[qsóA|}ïIT7c«1x>ŽR±õöOãý½Jã"ÍR£Rä“QDgãv\©D«µEqåZ-òÉ8&›ïÆßØŒáq/êÛhóNÞ•¹%!„ÝcBE t.4åô<Õ<Дý8='WAös/èr7¡a,|Z­Ö D’¾Ôw©pŸˆ`2úýòõ¾·Ê—Z;ÙŸêULø\æ_¢2De0©âÒé)l®ÙŠèÞ‹ÇãrÔFGñÅW½Ø¨–bðôAŒw:ÑÙlGÿùÓèÖ1ÎJQÉûQ.•" b”å±ÛnGQD¹V‹"/âé?Äõ½"úƒX̱2—¨æÂç.‡+Ì:ƒ«ï>ð êrún¾›©\¯Ç­÷?ˆâÞ7ñùïÿ=Š"¢¾÷al5O”³j­h6êQyöãÚ­[±ßý2î~úI´ÛؽýaìTc¦Èóe¤Lˆ ‘ôýA P¾oƒEw+1wÛ±âKf©°äØcîJ9yÿRôzÝF‘eå¸öî»q½ûM ²,ª»ïÅ7ïÄ?ÿ?ñC¥åÚv||íFìííÅÃÇ÷âÎgŸÆµþ1Þ,eQ*Ñ+½×77"ߨĠµZ5ª×ߎÊþŸ?Í£ˆf¼ûÓ·c§=ޝ&ã(åqê$û‘ey´vÞ‰w*ßǽû_ÅWV¼·[‹ÑhÙðD‘.Ëò(÷Ž£róv´ËyDm+Þ¸õV}q'þôɃˆ(Åõw~½-¢8)œgvR;œ"e;žÿÄvyÔ+¥˜ŒÇçñÅçÏ#j›qû£÷c§:Œg£QdåRLŽÆ£ÇY”båæõ¸Þ.Åþ÷‡1®ÜŒ>¾_~úEÜ{؉v«ÓB®ß=ŽI¶“Ñ0Æã"v;›‘e“hîÜŽÛ7ûñÅŸ>‰<òˆj'>þé{±ÓnÌœ —§?Ò¹Pâ˜s‘ÐÎ WßÄÝ”[Ͳ,6”” ŸÆÏ£{<ˆkomÇd’Å$èìÝŒGOâë'G±óñ›ƒn”·ÞŽßÄ7ß~_t¢RÛŽ÷nD«ÞˆòèOqçÓ§±ûÁÏãF%¢Z«GÄÉ$j\ÙŒ{[qtÿËøäi5êõÍøøú›göø¾OÆé˽óì<Ê~s ¡ ÜåâwŽ\¢å ÇÇ!ÖŠIœ´‘#Ce-Æ9*œüë÷y;o'†Ÿçq«jçÁ©„ï3cÓ¨T*E³ÕŠJ¥ˆ‡÷ƤҊ[·ßÍR£GŸÄÜÃúÇñþ;ã¸sï‹ø¯Õ¨nÝŒŸ¼³{Ûåøæñ×ñÍV'6oL"›L"¯mÆÍë[qðÍøÃãr4:ïÄßßÚ‹|pÙ$‹ÁpÕ^/²ÎX0çÊ?®j6LäÍ©=yl|ŒÇã¨ÕjÑëõf”K}šKž³q¢Ú9y¾³Ë… –ñ§Ý¶œÄMóÌßþö·Åo~ó›ø×ý׸sçÎ ±y*é ¼Û‹_zw(•ËQ˜Ö¸>¤Æ‹„¹äyq"·zú¡O?FT*åh·[‘çdäúQ.¿à™Ÿ+챌&¢ œ6/ƒs”l3yÖDF?!<.!LÎ*›{j<Ù'¥ïG ÊjºÖ¸.º¡1áv¹SNútnØmQ¢Àθ_dB=Ø]vEÙ&ϳèv_p%¢t¢¼Å¢O|ïííí™éØÁÁÁÌôË¥¯|›ÚÁÃsÅι½F(mCigÂ\\ÑÄB`˜ðRíåTŠ¢8…årÃ-âEÄ Ôµ("Ë&Q.W¦Òú}Íf3â”sS/‚«îœøãSéÝÉdyv⛪ÕZ4›§çâÔǽ°mD­±ÿõÝè¾õ7ññv-ÃQdÙ$ò¼xQolD vç9rÑ!• â ¤±(N“ªÊLBúæ±µÕ™™Rhád’׈ˆò Kw®(¢\©Ædð,?Å[|­jÌ4¦w®Õ:-ê²™ô7ìîR¹‹þ€Äd6uØÑr_˺|S]ÿ(Š#˜æy­­“sqzÚ‡&“IÔªÕh4›'Aù«ÃÃ(iyqµíf3&YÕj9"Nž]¹TŠÉ©}ŵP2EFAeG%]ì\3ŽpÁ®+¾é½…"PçZ¿[ -1ë¾A]qLÿæ;vôþòiT‡âr?ÆIrd4qyûkO•¬4ÑÑg焙ʪú;!Ðó„Y§|±!IÙÜÇõ„ѱ!窆•J¥È³ìTžùDpâ…$zùDÎ]°»¢ˆSu÷èözQ*Š©JÙì´,¢ßïJ¦Ÿ&û‘!ÙO˜ßÝ÷ðqa790ŠÑò:w‚ )÷“ý¸\ɼþNŽ ¡÷äyèÌë ^%{oooÏ,µV¢çÝl6§É¶#R;xÈçô©† p“Ôô›{hØc2Îü‡p)5‚É£e¾Â5jNø„–1^ùïܼ}j„kÊ6¤ êË;%DΓøE\Î;¾ˆ0rËi;}æÍ*™‡ëNs…Q:—úó«_ý*þéŸþ)~÷»ßLfØ%d¨È„óéú´Ótôº§K7¾P+EåèAz±^aëÅr¯¬_eF½ /\þ'¥*k©òåÖ_vº¼!Ô‹U­‚/ù´ŠÐ0N%xØ)ç,Û¤¶×~ÅÊ•Éùááá ]É|jž¦\dÆ&¹LªèÔzb¥"[Šì¦d™Ÿ]¯ó»1`äð)—^¤íSÊ[”T²¢àç*C ž:SúŸ«ZFB<;¨ràä÷ôûƒ§ÉsEî»=Ü¥ B&Eæ—m]¶›ç’K!}¯¥ýÙi´«‰ÃHö§’ 'qzce°üìì“€Ê]&$ÔW«µij¾®³&î·ˆ³{4v§çî…‚ÓY©ÙRll4ãÍÿñQ)1Žf’y.÷ó íŽç§¤'y¼cj¼Ð—êá{±‚l¤5 IDAT¶··f:é\Þǵ\ŽYÎß©\õöµÛ±w³|Ò=>½“²íôÜ¢ø`s@’¯©1#)ÙÕ14ä¯üαóîð,—¡˜]êh»•„×çòÑ.šBÕj5š’ˆ,×>“¿Sè Š@år9r@UÕl“OàT‡u*×~Ú\ ß‘¶£;﮼E»sÂ쉇ï/â‚ríJÖ¹ Ô!Є ûšîS¢'_KõM}wB¨]Sw†:1ß-à‹w8>Ôô†<—9˜íîVgÆÎì«{~pppfû¼2.¤@\¤DÉ‘¼'E$³Qb8%/H‚)«Ç”Ñe÷ƒ…N¥R™‘Líà”#¥êÁñbŠH˜ÂQºÔ+/ñµúBj|úl'ÛøE¤mtnØuKéïÓ6.MÍÄ€:êJæ-Ó¹cÒE¦ pšFijJ#V§¤ÊwZ¤ôõ -£Ãt̺Fê$IV¢–0NDÈ"U†ƒ!,Æ ž×$ÄG…E$œäHXó‹HÊöE`$AÒWR”˜u&]äìÑñýy.)§J(,': ¾éÛ ª©%nìò¹¿QJ5;Éà²Ó3ô½U,òô~$€R²SŸ…¼6Æ!6•Xʟж¾ó‹Ó,OB5Rä\Jôl.øBKßÝäR²¼Sä3’XìBÂ5u®ôo”ªwø·7Vüý}'™ü‘7•¸ØÐ dÑQA¯ç®î/F6>\b˜M%_ÜLQçNŠlܵâð)Ý?î±s8%“BN%‘æ®Bœ™ì;!]oJ©¸¡/vq.M­˜æ¤júZîèámž+6zÙ<`Ó[9/¾á=•ÛyíÓsN\8ýõ™¨ çÜQ\$µ—Šyo*·äëäÉr÷%Ó‡ˆÖá¹aßç†M'ò§™S¸"ó6Á$ÛÑW¦Œsº„Ž¥&y„wSÍÒié3f¸SÌë}€à{hˆTHª™ º¥*vkkk¦Ê–ÁõFÂóë •°¦>4q˜J 4±a€ÐÏç¨ßÇ„•ð(Ê^Êྼïì&íæLG’ѱ|| ŽÛfbÃJ¸7×R"ØU9øy¨l¡ªOïÀ’«ÀÊÕ§Q>mbUžRí ŒE‰‡'LJŽ-Ög§ü ¸STÎ!¾–“<ýœ€Ê w8ùºÎ —6zpt9SN@XÈ(ió%²üìÔ÷¤‹û‡æy.MÍI90Í’Äs©©§Q  öófê\êA¸¡ezß"N¨‡C u.èäŽŽŽ¦¶Ç…E#qÓ.[.—§°¢:ÀôÕäÀð>qºÍ…šÞ%þ>µ“‚ðvHg:<<œIî Ÿ*Šb sá^+ž çy(©ò%µÄ¬S:VÍ5U¸?ˆ´î# TòÒ|Ã: íôõaRT*•¦qÌ“m}^qÜ_éY‘¯HžážôÅ‚‚xRǤLgŠ\ÊÙ{CÏ7û®7Nê<Žù.=OuçH`wh½C =й"òAßËáëç¹Ò$Wùò1ù>ùiúbrâ8 —“ ,Ù´ìÎyÎfòÎ…àò7|¶ÕûÓ_± î¶¥ò©/Zõ]qäÉRÑUÏ]þ(%øCUSÞ—¨êê Ãõß‹CìÃú³¿¿?39tž«hÜ3â“ð*NAõóšÜRL€¸ºslœÐ»45üÞTò¼‚ñòïÊù)ÛíÍLN×NÅo:éNMóf×ËfÒD‚*;óÄ)²Ã_*¼›¾>0v“ôš“uYÕeàa¦²—B¦pÞ!u¿ËYòlsVGì±lÇßGb2%ˆ©¸ÂâB‡U %aut¢ìæ“^«ÕfFÕNxçĆŠ'*2‰!ç4I‡U6ex âXÙ«vvwtX©EÎ9:/ÔôbF^PÏŽ°:â [cb¢©2OÊ/³c¡b‚Ý]:pN-8qQ'ŒNŠE#yg~‘•8“£B†²•.—šêæÏ$”Ó.â®5Ò÷‰o\ö±3mC¨› Þ]f×OPùrdxn-#&PvæüÎ’ÜëR´)¥B„b€à$…ÃØ £À§¤l|Ô­ç®;¥ïÆâ€SNÙŽËK çdðsõ*‡OQ¼„ß]à“B‰H%ßÑø£ßã°9ï:/ŒÈÐ’WæêQ¾‚Ívõ=Ù§o§/– ‹8.…$ü›¢5ú>Ξ/)Ïìÿá²toV:ÏsáJ:7šŒù”SþÆ':̯ȩ“¯åÂNrASw†¢Ü!èh_‘À8†›l­ïî‚=lV²±Â‰lÇ)$ùÑäÍ;rÀ¥£u¼™É)(÷;òýõ‡qŒ°*/%;ß:PÓÉÊ“]D'„©[#)'7/¸é"Ò ¾GÆuÒ]]E‘ºx½ ?Ë £; ¦’"t±sîݪÕðïâ:gÉÎ{jÃ:É· n®æÂ‰Œ½Ñßé੺A¸1¨;;;ÓâVÝa]DÁúøÇáO„_Ê¡¿SM&%"Á¤#}bÒÉbS‰*I>6ž§s>+I3É8ɵú.œBêý½ÓŤ˥­IêæÄÇ ë©ÄB0‹ Áawäj*ÍÛ#£©!@qNŸs`t'5aP"t‹j”ú±yH‡åÕjµØßßOBÝßø^,ÞiN\ÙÔ#*NiªÀâ^M)%Ó”åv²>wÉÍ,3Çïâ¹Òžr™4áMÅ!®—ðé´þ­CYo’ù}©#Ç^rõ†Pj4¥lã‚>Dî°ˆ“¿ T‹œ<ù#·ï:á¹u(,'m.èCè>~Œ›l¤úÂp6Á aôÎlÌxÓ‡¯+ΑcƧÓ.ÏL: ½¼CDÛÌ£-°Éä(./]Š?9™Ñ‡¢rU<|LÄFr®C„¼}+°;^ÕS¡Š2R=l—;õA™IV9—­ôdœ‡½Z­Æþþþ Õ1¤Ä9—-[P†Nï/§¤‹ +Ǘܤí»dª9É® @§nŽã¹íYÏUI©œ œr éÛ Sï¯ççÒÓ ¾ä¡„.™]vŸ9vf7ˆ -GòÄ—²sÎi•“s{¥ÀOî„: ²¿Ÿ+v¾‰e‘ÉdDÁŸXÐS5“ I¤45‹Ý)ý¼€ˆº*„Tsšä £/:%ÁTþƒÏÕU„¸»Éý“yÙ]‰‹¥õÙÓž"m³ƒêü .„ àÁ"ÑqÙ.!ì$L.Еt´/.t²¿Ëvsêyxx8S ë\êuBY G`÷™±€.a4ìBrJÊàÇÎ8'*Tr៨(Á“m嫼¡Fò,áš„,Ê_èçý»;ÁTÁ•Í þ>m)w!% Þê.»,;ó¾{‰þB 1Ù€´«? öF^w½é»1y—¯–¿áò?íc7š0ß,˦j þPÆuVÒ¼<£¬åE`j‡Ž+²¹Èæó6^˜OÈéu2:Læe;¾?›„ÁpH©|•›››ÓïKN!¿;ã”/…Ô–Ebjù1÷R9¡ÝE$ÈJñŸ gqï»àdù‰%é¸í½ÈÔ•j|„ ã z©Âè*ˆ,ˆêP!C¬Š.çlè³Ë³¤¿ ÿˆqQ” ˆynÄ!Nínš'–ÄÜŽb,pe;G&¤&:Crn“ «à ®lÃ?Ü¡ãp¹\ŽN§3s'”W{^ì¾–”©hL}·A*ùŒ#}ªK9¦Œ¸mßM0ÏÚ]Kœ•)7²ÄRN€ÒLðÅé»O„ðèÜèuB•ºü!1íì ²HäćÍ_úÈI™+ý‘CCl®«CÑé1!ä—XP+!e/%¯L¹xÇ»Šyä#¨aÂÊÊœà’@¨ˆÃtYD¸\©ïJ¡/öà¨"Í &U,¤ü¹ê¹«Hã¤ÏÔ±«Iä“>‡žQL@þŒÍ€Ô´Œ$j½ÎÀîŠm.*Ã$Ž0—ó¥¸U|°>%P²-› êë3»„qJ 6µïƒPý>þ¼>q¾WŠP _¡À¤-»sÔ…8<¥Q‘¨f$§¤òg²½û«ŸgŒÖU2ïûÐ<Ž‘Ôí4Q~ç(*Ã]n,œÜ6,€•ìsªê»Z¦{fÀíò½Y”,§?ÑÙàSœ“mtguæ}R¨‚îŒ&œ¢z²L¥BNˆ8¡e!ÆZ å|C·¡gl<;š¿ß—^³aGõNr·¨¾ÉI!ÉþTêó;.Bn¸üe»)š•âbòN’v@Â;Ïü‰N>%%MƒbÂêèÈu$ꃰ&ûT²‘b—¦rÇŽÀ)²1í*„øÙ =ó"Í•»4–ž'³Kh™.¦'E.2Á‹Ì)¦—O)ÙÙ×ánÇœ:&n»1ŽŸå#A”û…t†Ùé¢<3§QôŽ¿%‡…„xžv¦c!ÌEM upÕùu²¾ò-ívûÌŽ6'\ò“œ;*,ùv{Çû“×–ÚnOÑ!×ÈI”>U ƒw}}ß3Cø¡z/â²uî «óѪ:Y„Gq¤ÎÑ«þ]tŠ pŠA»„N†ã9=7:JfÙ­aâÀ¤‹$L/ò[<<<œI ¨‚¨©Aj‘ؼ×ÉÝJéÿKšš ±lëøZvƒ¼¹@]_’Æ%fÎÙc¡Â„”Å»« *P~¹V«Íto]Ô¹²-ÉþúyOhð.;èÜȇp‹8'6 ¾L8®ÀÄAX~ô}º3zÖ¾›ÉI×,p½øW1@(-·ˆâ£{O^ž+u9bR¦³Gùe+_NL_McLƹ_ˆ»™Ôð_Ä´»ür*1`Ô¿+¦$Œ©üÅÎ9!לPyË—>ªdƒKþˆ‹}ˆC„Èeàg÷])Œñò)dŒ&\Ó¹žÜ¤¿ëN1î±y × u%7ËE$ÉÊÐù$” ®ž©À€Ü>ÏØJCYnB×øÇÏmÇ^.=íɼ>c ŽIØïo¥R9³èÔ‹4®îð\”G&|ж#ü’¹a–e±µµ5ÃW¤?c3“H'—Âg.šR»Ó9—¿!r€ùÅŽ\DËa¾ò¥„ù³©”Ú#£f¥^'dÐ÷9RÉÅd{ž+ý¼b¯ I¥"–0á©]´íd× gÇ•Iœ$¹ž8ðSCÿæÄfŽFÙ=¦<²™»Ã”x‘ˆG œŒåÀÂó;¡Ý¥}ïƒ*Gßã…»ËÄë2 ‡ÃH€ÃhTê³°ûK'é[w9Í"™Ì«n®¸CGgƒÁ•øX½ÇÁÁÁÔ‘x¬Ñ)/.%A¹ëEÀƒ«P™TÏïS™üìNX')Û»ËEQL±Åì.3ñðI¡R;9^Žü…Y'ùV£ÛDIA€<&MÞIã¢/r(ÃKȌޛ²—$³úDÅwV(1áÎ âý_K’&¼ÞïððpæÙq»<¥dùó©CãSPv@é¯Ôä¤8Ê/û$Ž YÈè»szµµµ5;‘/å$¤ˆ#JÁ*©’/'ÿ‰ÝÓÔÆeð¹È•PUž .VfÜð鸾ørzÄ„Q]B&ŒCœ‚¦¦˜lìœËn³^gSŠ|vŸ YÔÿ£Q÷XÏŽqLE-Ï Ï¼`乊ï ÷:ÏO_ɤŠM¿]˜…wf<O§mž)©’¨§]AN)Æéýi;ž;¢68ÅäÕņx'I'¡/å;oŒ0Æ“¯8§±Öè:„š“º$ÌŒ «ãg™˜8隇™„0:IrR\9pÁѳîòÌ.߬‹ÈàÊ11w¤˜«¢yð’£ÐãS_Jž‡T»#W‰ƒKzcê#yâõ¹õ7¥xâÂ).§U¾K…ÞµÂîÀ„•Øb&M)2>ƒ·sXs¤îd~-­ÕjgàU$«Πï§× å`‡’*î‘qYK_²FøÐï÷*0qQbBܵOòHL%ëzŽ)9TÝ)âª?Ë"Íw7qbãÒÓJHõwNx•4) ñå|©<œV9qÙ÷¸xë˜tî¢RŽ>‹Ë'Ëvä¥Ñ6|ÿñx<³Mš.BÓRurx}q"á˜lpÚÄ"Lç"Åÿqž'yº'Ü;åEžîTj ­ìE9yué›áÄ…V*Ýp‚Â)$1穦¡cº¾×Ê‹/]zÚ»þ$³)Ås¡ßE_N™]qhŸò½UŒÎeðIa5Ù˜Æë‹ ½;¬âœR³¾?ˆÍH¿$msRçÊ\„ûôÜ!‰„{rºÎ„Ýb’¢ÉOâB$]ÀƒÂÞXq2>ó*ù±ñÁsÇ}fÜÀî|EBt˜oðuAËø‡’è^œËëçÙLôdqLvrÑr§$ôĉ’Î ›>Ìíõ@_êE ï™ñÝJ”õvÞšÇ!žòhSßÍ W¼e#˜ßé¹e>Ø IDATEÞÑ6ƒÁ`šû~!®X jB9ÚwFArtÃÙŒ¤/–?#Ï•œ@/òˆ$pU4N1ýÎÈåÅÜ3)Àê‰zÜ JÚTͳ#!l1fz€ÐT‚ɶ:Ur|”Øs}þÔa¤Ü)Gòܕ¥j¾ı~ÄIBÄB\¦dtõ~¾¤ÍqL,d?:I>P*éPuŒU/!BrBê\qjà âo™Ì3á$æ\߇ӦÉdrFž0µ£‡É>Õ¥Ø%u’¤ž%!u®FW¯×gT‚ØýeRÅå|r’$a2)sü­:ãΠt# auóv7’È©„/×S7EçŽ[Äå€ùÝé µ¤VNPÉ2‹{—[g+ì0›„ªêuvÂ\òsú,©æÂÄ…ÁÕåày.脉vU2N{”PêuN«¹lÔN ®@hGªEhå—u®<]*Öá äB³îÛ ¹÷þÓUÉØÁäÔ€{­<átU°yKdy§œWÆ;é2·: ^䥤b)Œðÿ³÷î±Ú®ù]×ï~ë|š=£³™2ƒC­¢-XJJ Фֶ%¡´ÑhL°šXI4‚šHš` Äÿ˜$„”ª Ú@R±Z,¤)–ÀÔlR'Zv§‡ý®µÞw­õœýc­Ï½>÷w]ë=Ó)#û½ïd’y÷³žÃ}Ý×áwøÒ÷!ýÐnJõÚJ¯Rû:¤Ç9$-ÿ!;a›¯h(i«8àÂJJáƒi7¤99ƒ õ°ŸPËE»2nl{v˜-á‹auìÕæBcÙo'ÀNPS8… Öݨív[WWWý¹gÞZôz/v×’5Gíý¨åÝ”„uÖïOTF*º‘ÞK™$ºÉsu÷ÈE!{\åO®çééiÿ:ñEò<,Qì® ¹>ã}6x¿Kãh'yiNì.¦ƒýV¡Ö ´ã«„†9˜¦¨Ä31?ÚȆܯàíTUŸŸ?A].u~~>XS>ÇZ´w-j É÷>›Í Öœa²‘0j‚ØÏq1óư=ß‹Ï)ÛKPTÆ&ÀBQ)à"µsŠD&Rèâ€ß“d†õ9‘qÛÚA›«GÆú¥Ò‰LºÃº­åM'¥d-“›¦‘-ªƒñ”tVŸ] ãõ oJ˜Ëååå ÒÔpo|>ïOœ$cc˜ŒO¨¡báö¡¥­mª”ì¯3ÔÌj±Åf®òM§Ó~2ó{Mc#1×! îŒûæó]IÙLol(©ú‘~ >¼L¢L߇V…ÓP2æ cŸvÌY*W©–ç`Ýccâ´1­Ì+X+¦°&´,!H&Qº­l¯ îô%‡€/ɯlÂàå3Af,Ùäp:ðHéi?÷ÜDÓmšïwå<Ϭtñùî,˜dH¡€Â]ƒìðf°NÔ‰‡ä:PZ„ÂûI NZRøV˜dÍx[Δý&e½í…b «¥¢B Í}bÞ¸úëyàDÅ{¹4ŒÏwÐäÕçêÂKΛµ±¸‰ùŽ-%cÒÝ]7áÎë‘¢(œ' Æü:°†å™çš@¸Ìé„[òÜ¿ôò^‹…Bò@ ]ãïÍbM³÷qï†G^åNŸ¡g ŸJ‡vÇÌi>ƒ5—I]“ªt¹ûpOw%R™”D†ÄÈpÒì–µ ½VŸò~bDIúȸ«à3Ó‰NópdZÅFæûôµ4Ìf?qlȽq΂íâ«=¹,6ª®FäïD¨em ·¤÷Ö’ æ;X3[ŸÁ–®vÑÈ ‚4Z5Òq·S†L­cƒaöÐM­±3r E"ÒÌÓ"[îäeÜí6=“‡j”‰i-YÞò®4Üó‰ÏŒ/WLR~¹29÷9Rv I‹ŒÃÕ›`KBÏØe›måiADzõÊáä*\nk»bab±•lŒ]Î×3ض´µï€Šº †g16&úee½µÍyΈ,]Ä <,ßìǰ;’0“éÌ3ñdO—q·•â“›˜90†åñl[•2s§¦ÒNÂ%ž+XþÙ­a0®§K¹yi™üûY¤b[š»3`s>Ë¡ò·ª\áLº„3¤ôt*¾ù`vcPVÞ]¸p`ᎊáœikO¯¬ç~á°Í‡ÝUHÏ (S*Ÿà8ç•UËÒ©ÛÊ^)Ûí3ÔD{7y?Jª ç¢ìOd¼¾‹æiX‚Ø<^'˜·C»‘9ï˜W›t·Oe¯„,zͧ‚û‡×TÂxéBfžÕaCa9à hÙoLÖOÏ.w›Z…X']¼&R˜Å*aŽR¼$• bxlHÝå°ì¶Õ3[&²æ­1ÏÓ+ÎF¯¯›æûŒ&Fàòû™†Kz¯O -‘ò:ijZ¦·SkÞ’èØÎ ®ï;T;º(•¾T–g6ÿˆÿo~QKJß0cÆ®Å/JÉr+ŸÚ8Õ\Ο1e½S¬ÈçÜs¼³g¥™½P[R&€'s¶ K‰=ÃP¬›°n‹jÿXš1M­¬å÷·¼T%œÁJ\Ïɺ’ådÀžv!g¡sïî¸ǘîô†3¤D±qÕÆÇØ_^^º[ €Ý¥Œ³ô–:Uý¼‰™HȼH²~â$M&3 Æâ_íO”äÚÔAÎ %ÇžßjŒi@ªÜºM;W—]±04«9t)½¦Zk.»æf¥C;"W8TÛ˽û0ƒñ ãÂXP­±ZKVP=O îà.hά65¯ h˜$i8‡÷w¬¤ç=2¿ÉNßvÚ6”Õ]Lwl€Íq?Ù5hÍ«Ü3r¿1×!å•“ÇÑJ -sàà5‘rï–ФÉg~PB-"‘êšö}pÎF­Ù5°®1ééwæ6ýÐü~.Ìɳ¼²«Ã‰ç·\jËïÌÁºåPøƒ±­e¼]A5TÃÄeŸû0\ÓŇ–Ln3»Xé€ÓŒŸÊ7 ¬¹žNâ «sñ ÏøŠöbAbØ~ÏÙ°ßXM.!Î1Î…óóó'ÈÃz<0‡ØJ…þ):¹ Æx8Icïíí x¬.h›”æÄŽ_ˆŸåîµùE†ºê•¹”íN5¼L€ 94ç.ý…\4²L¸UÇ’ðî°=Ù‹3 dÞ¤ä9cïs dç zÎ ¯9ÖLrl\X±‰-û¥÷«®ZÌÈBP¬ü˜×Î#žpfHdLÔIÕ² æ˜du™…ΛCC…Ó¸kË ›””Pí¿ä*X‚/!B’ CÊ&’R®Æ¶ª„> ¬öb9Boæ™ çó¥ÏßâJ$‘Ð8®–¸rE'¿®à€194é3Ó‚#˜ËÕWPÝ’7ÿÇDI¿ß‡«qÕlÞ¤Ü5`Î¥qa*¹Â&ÊgloϦ`)Ø”nlñÜVnÁ5=¯ ïò:=<<ì+0& :`ÍJϺå"žžÜ›‰|lLÞÄX3îFµJÃÌU@òÜÕxi– 6DˆD‹ß„uîý‡®„!‹†r¸ãBGÃP.+8Ú‡Æ"® y?IwúÖ~“…‹H$ÜÓA™1ï`“¯hu«4©õýY(!Í‹]5ìÎݦì~VçDÅYÛX35 í²¿õòòr)bÞ&lH¢;} 9̱1²€€•yË^N`Á˜8X÷ÁmËsÆÍp`P§2—ÁdÎËËËTÍk8§a3N23h[¯×=g€ÓÝ&ðú>çœäQã»Zê -³"œy¦>gžóaìÒd–#ƒ›ëÝPÕä»ÛÕ‚s:)lñ=vœá沺Ðãs  ÷OòïsÆ@£*’Wf1"w\X¨®zM&_1=z’”ÅŽ­»×l HW«Õæ‹€­2rÞ:æ{3Õk*e¯‰ÍÒ³Ëcïyg¾"ó*m¼æ¬Üe“Ù„‡;X7<œŸ{ÎâãcÛ‡\S>'Œ¶ÉDÃ^Ð<žæ¡zMÒQº¸¸xìx/öîDÅç\ª»Ã›¾VtÿÓÚçØ“dƇŸ90ilh<ÊÐùðo¹¿Â'HiFªÏ -³)¤´–Ëå@Ñ$ƒùt¯ÏÀ€ê,l1Ÿ JÖ™0®"¸£ãÊ{¾Î½§´#|TrËÞ‰ Á>ãg cc‹9¼\-²ïƒ“¼ô¸Ió=ã“Üë 91¢-·éT¯²šVJ‚¦¡Tf:h´aTšF¦ZžMMšvbA`ò\¥*½™›t¯71Úó”MŒçCЕQ¯IÖ—!@­n˜áU ÷L=/Ò˜²•ÏU²Þ;[½Iê6R Å™ó^i˜­áœNÀ[²ßé½Ä9suu5€P¯ÊB°»ÿ ϲ|³UYø´:*nq±¯å ndArüÜmKeÝñ„õàpê¢Qr«P×´@‡ùÓ6…dÞ9ÆÈ®„ ä,"὚DÂ|ièíX/-œhøœ³91ûAK #å•[k&ãjwm Iô~dëKcloEcCö‡õz=ð…J8fBç)œÞiAöJ#§(°fçÂH(«w&×Ó]]ÓYfÎþZøY·ÀL‚44«ÃÆ]›ë`Ž„GYîÔ-¶ôBa“³„1iÊb&ÄÈ™« £-ò¬'“ßo_ÃòLÖc lθkÒɸæö¤JëŒÛvVnéÆTÊar™<Û2uLBXš¬Ù=>³êÖF„vCIÌa±¬7c—¬d™{e™]ãù½“Ëà Íªgy@äáçMÖ›˜ç {z^˜Pž­Soà$ZùÜ3è2nÚ-yó|ØÛ U†L¶¬džIÎ5”$ycæÙ¤«ux»’Õ’No%)Ké–¾÷£–7“[ò&´'^ßI§TQöÀÉJ™±Ã8³«Ð‚¾yÞøq¢â/óÒÝuã²YSž·†­™Wæî9˜a.žWöm1,Ï*=-!…TÒ±šÉ»-©{CŒ|Ž!œÒâzMÙÑ JîS]Nˆ‘;¼N€­¢è ïgÞrNš”=&}gá„ñ ÂjwzóóŒO …ìb:˜¶ï”ƒmC]A]pïæ;:X§:œïG µ"\*¾¹úËXº{Î~ã¿÷¼ÃcÇ‰Š¥©}޹›•2»Ï­©<§ÎIá$y®)…Ÿ²äfùÞ’ ꎽV áIÒvK¶Ûû‰Ý -³ÏLò@|†3/8§l½aØ?ç …øÒÑqlheÒì ³&™'NtZö.èÙ·Ê…Ö'¯Õ¥MÞ˜}¥ÌåtòoZCrî“ Mü^•ªIˆ7¡¾U%ôå…ž•´ôàI¥›Öšós3GÆ8ÖDVCRVÒ•%shÀ¬{ý'/ÍÒ‹ÆóóÞ’WöØââ5ïMŽâ¹KBÌSÖŒ‹6RŒ9÷¼hù̘@j9÷,œø9®@³Õò÷šò<{Ž“gìpf:‘áp¤«@P.ÚpÎ,*ÙóÂ{­… cs·ÉÐ2s¯Ò·ÊpKïG‘àÙ:‰3¦ÝE5ŸcYÈê/{ïuP—Ɔö½2ÙÞ‰]+ö:ûÑq1§ÎÁ<8t '@Ïœ@Óés‚›ròîg'Ðâ  ð9åê0ç˜yžì7-©XÖëÌAOò@Ø/œÈ˜KÙu]߉˱÷ØyÞ™[•É»‹N–d7ŸÑA—ãŸvñ¼I³NCÐf|c¹wsæZ6Ƀµ½„÷r'Ð&¼»#cˆáTiÜlõNÆ>͇ý{Œº`͸›eµJË/·º˜‹Å¢ïZ¸éNšáåŽ?̇4”Õ1B®Iö›¯Œ5gø(IV"²˜Ùâ‰$ÿ§UävÇņ–îžç9å"³aüŽ_ìAè5ãyãs&)³Ù¬‡s¶|ôCd·+!ØNÓ,Ýç˜ãcù‰«îÞà!ð£ò1ÁÈ®²Ef8¯e{Ðúü&-ìqâ$ÐZ ÚšÁ¸ ^·'¯»}Hk” ›^+l$Æ[§R†X~Ðj/& &&€ê­«»>|hº:lÈ 1¢-(°7oN„8œ ›s@lü.“9 ª,6*ai8å¬>yž·&ÌCËV÷lø÷îß>Þð'o‚ÌEC€WºxòÖ 'uW¾6l’$Ï&}›|kRvËñ˜*¡7dû2pð“ÄÕH™ç<½|8³îÎÎÎ8í¬.;Ø~® j/û–ÉÍn•;}ö'²ÇƯÅÙs‡Äûƒ¡­ »ky~ùàâpl½Ì…0¨å™áŽŽaN€™Ÿ^SÆS9‹±±é4¿‹ý€½!Ek‹æØ·ýˆý/w³ØÏø·m •å÷ª(!žuÚ½vÙGÜM¢òΜÎ.f þ˜+À¼ñ;;;ð” ËKø“ל-ü÷¼Ü«ÇÎ|GCŒÜí"Éä\lyÅXñÍ^ïÕöµjì\Psá£ÅÕÌD„ñãuÆŽs¬E˜waʼn”×û!ÿýÈ7Æø¸8âlÕÓD¸èDÂ< æÅw›|†·ŠÔ.J¹ g±///ûûÆëyæ‚…¡çN¬9~Oš'jÃ…•\s†—»›•BN.äZ|„ýȆá6èuìç÷{ÿáu¯y7 Ì—4Ò)÷bü:†ñ^ü¤3c¯ÿ(²âTXb@SºÑÕžÄ÷¦ŒO·ì­Ážªe~`À\,ù鎌q×ɳ°z”Ét©dž†á–Á5>ÖYµ]ÎÍHˆ¾ &ăŸe²çEªÉP KRºÏ{²ZMƦŽÞ€åMÎ0kȳÝžLùAK†ºJèÅ“ò„& 2¶Æî¢ˆbXŸÛõV‹ÉDÇÕc‚á–ü`Ô™;•!ÝÅÅÅ€ÌÛRíðBwKE7ó<Ÿº¤¬w»Q»:íÀÂ0^{Tdçßœ:“wªJÛûQú:dÇÇNÛ†WùÞík•¸ìçd¹“¯hwíœÓ¤ïJ°hDò@Êø{ŸÑt ]„‹kÒÜ-wêZ•uÃ9-mm9xCqŸ“¢M_Š•.x¹ š–kwu×焃kWîóÞÍñeîÚ¨5¥îyÝg°ŸÍjµê…[,]mþk‰a arñ€çf °•M[òÎ §´Ò¨“´–iµÄS"ØûUúåëîÂÛs‡:å™ Ës×Á•‰ˆÿmÃoÆÆofìÉÅœ·¿‘­= »3§ÏRü;Û ™b }€o%tÞâô’Ûdž¹æÜ]'Qá¹›'›ÜsdžæØ$“sÆ<™3 `fé ž7me­ °o„  lb©¼eC©¼©$ ¶d+ML& tåÉη† 1,[™.è¾T‡é ¤±¥"Ú´(«ÃÆÏ29Ò»€*V¶ÔŸ3„âý–+%Y­V³-sdÜ~´1bJðqøZ^07ÁT‡ò&çö¡7!6É x©À§gƒ.'qÌÛ”0& ÍjOzWðÂô¼2ÌÅpY-ⱡkV”ËM(¥©[ð(ãc­ö’k*¾%Ç…ùaÉs\“_[’Ÿ..¤’לG¨”¹PÂwÓ‰0„)ý‹òÞùíN`Ó›À÷få­<œ h9à¼ßX2”!…Άø¤ä§¡i.¬ÎPYætª™ûå. ÏÖ” #.n˜´mè™×{{ËH5…U\”"`uq MÚ¬éÃÊk&•x8Y0‘9 }ø¶¸žNpB˜uö#¯wÜRÂ]Nw%t1ï,-Íþî$М=¾Í‘ 2ÄÚkŽä‚3ØÐµýýý†ßƒïͲÛ>CÍÝJwzó²“æÂ†¡$Ì»äܥŃ!BÞr¿á¾¬²èDÆó8}bw–ÉM•E'÷-®¦•þÌal؇S•ÕcçB¯‹Fæ†d’g…IÃî]JDI>²n¸¦;õ6ed^8qr°Î~×êr2^.ð[‘ÍbëÜ»ùEžWÄÅÌIw\!ë“Ø¥ÐS‹ëé5eÂj¾†¾ózúVçØÑ9ƒaÆŽ--í$‹5c^•ÇÎEtCËŸ•fæ‹“´m©40¢|P+suVíŽÛÖn‘‘} ²{<7Ídᦻ7©äqXö’ IOgÆ×ºGè ,UÍÜ‚ku-Pý°©&$ÍBÙ’ j “qma‡-àîVò@€G˜°‰š,çÅå®BÊúu6e6iîÙª! gHGc+[Øñ˜*›•µ²«`âpÂ\Œ«N (óÆ0Kn\ïÄç&‡¦ŸrÅÃó*8XîV¹šã g°>}‹ÅÝÃFRUµ«ƒýƒÚ¬WµZ.k:}HòvUÛÝÃázxTëÕ2ç]U=Ϋ›W/ ÷Ÿ¿Ùlª«®ºÉýἸ»«ÉäÊ1™L«j×W!w·ýïyyý²¦³é£ÔlV‹»ÛꪫÕz]‹Å]uݤVËû@lÕU= øk»½/¼tõСÝß{¸·EÔ» º··WëÕ²6ënà¥RÕU×Ý0«å¢¶›mM¦“ºº|1è Õr±¨ív3ÀWuµÛmëôô¬înnªºzâ¨|_X9ªÕr¡ysý°ù?w·{ζnooúÏﺪ½ùìaìvϯívW³Ù´¦“Iÿúý¹¨É¤«®›Ü?IW»í&8{U“É}àÃssÐSÕÕj¹¨ýýƒÚm7µ\­ª:ºM÷÷}ÌÕâŽÄª«››WO¦ËÅ]Fîßßu]íÍguw{38§î÷ªª®»Ooo^ÉpóÕýoÝîj6¿_37¯^>Ž6uw÷øþÙlZ]Íêîö¶v»­îÕ±YmÖ«Ú¬ï×Ñ]ßµ¸6óùüþõÕª6ÛÍó㣣ûçºÚݯ’»‡ù}¿ÇTÞ¿~?åëæöæ~~ݨÃZÜÝ1ìÍÍýëÕ=(Úíí×Ýí#|cq·¨]íÉÀã¼ÙÔÍÍmÿ=¶Óé´înoÎøû±™ÏgU»mݼº‡\ݼzU«Õr N²tu»ZUוàSœ¾ífSËí¶j·«»Å]mÖ›ê&“Únï;ÌËÅx´÷ëçþÙïêðð ··µ«Ý ìÞ¯9öŸÛ»»‡ýd´¹(¸e7 IDATka>¤å™ùíN°ÏÏÏdüôfJe/߬'Ì׆›N$Z2¹ÄKœbH¸e*g¹ó–öÈ/3/(›I ×!UÉ|Æ›–ÞM!Žq1ÓÝ.Wœ€§òñp?*2Np-F䮯ôz3Ïc:ƒ{ó/-´àn•‹R¬IIsÆÆüVCÓlÝ1¼(²˜¢4 R˜ÅEi'y†ñZØÅṳ̂w“…c8g˜·îH¹!áø†dÇE¬A2ÓrÊ&H¹Tó¯ŸÕáĤó~'+L(c‹[uiÞ÷:ý~2[ß,Õ_¨“6ï²e杖1å-ÒR:”fEÃ!&cúX^Bº—©.›dièYó† ºÚÃÆ”ªd–žf#°â’ßoŒ§+ï6À3¬Ï÷æê²ÉwTÇÝ~L‰bcÞ]Åg!›¸kgk·…™w>¼ l%iI Æ(MfM6ò9Lºñü)]m¥áW–¶öØDÜÜÜ `%óù¼v›umjRïÎÞªÝ~ÝηU{\Ö\c:Ø ý¦¶«Úl7µ™l„ûÉdRÝì~Ó[Õªv‡»AµÉ›æb»¨î¬T@ßI³ÐÓª] +Ä}¥¯ÕͻԭÕú–‹euÇÃÏw`³Ú_ Ⱦü¾^¼¡»ïÖ®j2 *å»Ý®VÕÝCÀ1 ‰íÉv€~§ëª›?’‡ëèZ¶7ß#þë÷:­'Ähs„ºÓnÀMóØ.—ËÚï÷~ÿþûˆy¹\Öät2(80Y׺j¯ˆçõú`=8œ™ãÝüáõãõ #ļáÞ·GÛûø³«AÕßûñc 0ŸÍ«ºti»“n ì@f¹\Vwöøœ\©ªZmWÕwO:î wG]?ï\<`l'g÷ÞMj6Ÿ 8ën]ÝA7(@xM­ÖOºeõȬ7ëÚ?ŽÍ|6¯n2”S­ã69/ê¨ïíËå²¶ÇÛÁë|wu÷k’{|þìá¬Ù.ªÛëú¿÷šéÍR¡½ù^?Ž»Ý®V»UMçÏøív[ën]“îáõédÀ±Y¯×µ9Ú#±Ÿy´žWæàx=Ò!a`H¤¡÷Œm†;±HAs„Ÿ+ôfƒÀªd.ä&ß‘"¶“R'à¶5In–ׄ¡ó ÃÌÈI4ü¡&Ô»ë`¸B’ÙØ°R b³uÎy T ÏMãó@Œ¿%±ò–½PRÂÏ—”ÉMƒº”WNþ2Õok…gÀi!‚ Æ´™–“”ü4?ñú龚\WH-iÂzn­¦g÷nLº»žŒÖ ÏŽ‹ÇÎd|*[öóp5ÆŸÏ&È\&T;xÌ›”ÁmÉ#¦P‚]]­IîTžÖYçubš«&j™Àºjf_‡åry¿^7ëz·;©ÿóø7Õçw§uµÙ«ÝÞä>*é(nîjU[4¤]/¾îõƒPÙÅÿyòúnøï/ùõ‡ÿ~X_âëÏÝ[ŒÏÑkî}ÿuc¯å°Ö®ê°5v|÷î™{ï^3¶ñ%‡Ý{¿÷'Ÿÿº±yóbÿW2oºÆs{¯cSOŸÛ“y±»ÿ}¯›/zÞ|9^/sz÷…×Ìþ¯ÆšëìzvG¿‚±ÙÝØìª;ÜÖi·¨·6ïÖ§~éoW÷òÝ:<>éáy<(JY>ÞÐy­(FúuÀéHP”²g†ã‹”Ù5„ÜÁ:PV‚ùô­"¾rÆç”¹­IÒw#v—bæBXµÌ0]ó‹Ÿd—Ò<Ž$ûBd kYoÃæ¬®k bÆÖ… £iðb±ïU*‹ÚÍq¯å“81'ÐEnKákn¹yªÉNuM{31W@ó0öæÄ¥l·ç…=[fŸ.D§ß™‹HÄžV578¨ùÍ)o: ó†"«“´$3,;°‡i¬“Ñ™­ žlV%³Ü©‘”à³Îº±Á†GÙÇ!e+i [òÓp+·È€ùñùh­ÜÃdOx”IçÆì§‰Ž•!Z.âÖmêßbµ•ôiqÉï=??oNÖl­ZÛóƒÉn­pgñLFðÒYq0a¹a¼=I¢‰á­ŽŒ=xÌ}²Ú‹åÁ·ºûcŒ¨«1lø–¥´ ŒÕì ãóh½º’fÅÆÞÅWÙ<¯Ì¡Êá$Îîô&m[¼^¯ëª;©¿ýÖï®ëí~ýÁßúñú®¯ûh½}±_“†Ìáx×x×?)×n·«Ï½»¨¿øwÞ©ïÿ±Ÿ«»“Õ¯û‡?P•g'VQ$`5" vŸC”X9ŒÏvüC|ãJu]”²L.g"íìÿhSd"¥êua•EŸá.°â¬ásA2y&Ì;±Ù(©“,£e;6g>cz¥X Ÿ3Ü…\#Jˆ]ÏØÏ¨bKÛO`ø7÷FÜla«¶š6ÀØYôŦ‘t‹\¼5Ëó*Í>ÝH¯8¾ÿòòr ¸‘q±;"†¦esÜ<rèxM!BZÇ´ 'Ðî¸dêÙñëÀ4Ó<‚.mÆI&¡Ý (€]Ì™ì^ˆIöwµÄdÌÌš­JfiiWS€ù²ç…“4ÀÙÙÙ ­ìÌÒгtÆuÅÜʺݮýÀL4v{Ò›œ ¦æexN-oË¡² ‚uÅ" ç†á™°~ÖÝªÔ '¢Ú’NÜnºÒ•Y9ÏÆms+¾yÞ˜`šnÑ ›3NÚÆ„l‚$>l|èƒ÷›+ñœLn:¸3¶^®xXº1±Ç)ƒK5Ç]No‚Õ”m­·»ú‰ó¡öOÎë~ÿgê¾ú¼ë]m³ò:^ã5^ãõOÜÕÕg>|Tÿù·}º¾ãk¾ªþõ¿ôêsŸüÖZÿ䟩ÃýGx« óyX’³Õ9“ýÍWtüª"•j¦Ä°»œS>GRõÌð)Ü ñIÏ-ô¬äe.CBëW«U¡6ÄÈÅQàSÙµ Î0:¥¯áqX¼Ã*yŽÙgÏF§ü>‚éäðRð´Ê¡ýÎ|FÛ ÊÁ¸9ÂÜŸcÇ”åfÞðÛ_ÑE!X'‰IøTJ¦¶GÇÆþ†©H›°¹D2åœO³QžyÊüS¨µ·9ÆÄÝVa³Be«ˆn1Û¢˜ÿÍzt·ËÅèªÓLRƒs}ÓªHdRb/e1 £±oÅííí€gbv²~>ËÊöJ1YΉ@j¸›”mÓ$þ–Š…7k}+hŒ©au”< 'Hð1±ÁI¦ [ªW‘±?g™ËÄd¶aíG`y&æùÞRþÐ.åN"½A[, ƒqøAÆQºÓgÙï$ZÅܧÔ*§ãÂ&`®„ ïnÍZÞÙÆ¨žW)/è9ÏfaÙJŒP»Õj50bµô4“94ÆM“ˆøðô&˜ô<÷”õ¦`u«Úlêí}¢®÷?TÿÑïüD}ÝÛgu»ÚމÌx×x½o®ínW·«m}ýÛgõG~ç'êêà#õê«~C­înúý¸ÂcUõ~ >Í¡qÀêÀççPòíðnIrïå©Þ™0«¦: $2ÿ8!Òé^ï$Í9óýàd06Y9§cClg±$´ü¶ôá3òÀRútt¬@ ¯Ì´„4•&ö¡Xè"¹¡cŽýì­”„xw\˜ü†4‰MÿPˆu±ÓÁ:ü¢ä¹f$q±Ç†ùÍý Ô„‰­ÌN£yrÆÎBSÄ/7;¶ Nz3y^X-Ï«À:®Ï"¹•’ûd† ë/u ÍÐ2Ëò£øP;ó SaÉÒ&Ä›kaˆ ÝÁ±1žÆêefšY·«-LÜa=Yðš'âª;B6#Ø&¡ËwëÔªe††9ÙpËš×Í#Á-šû±|!‰Œƒs=cc¨˜1¤iîG°Oâ”Âîf±‰qï¨n;œ^'–_¦«`©Ü›››y`v ýÛ©H8I´,·çUV$ø|wl’j蘡o¹‰ñœìëÀ\1¯,=rLæO9U6pކsrxõón»ªŸ=øt½}Rõ»>óÁÚŒIÌx×x½O¯ÍnW¿ë3oÕ'Ž«^|äëêîæe¿S³T’õÙkLûœæB±0=¿à¹úœ1„x9ïân‘ «­LÚ62b§» -ã·Û/¸ÏÃßà·ÿdA®åÝDüc¡ƒç¼TxÝÁº9ÂüVCóÓ»‰Árð†Göç÷A `B=Å}b Åæ¥H„½Rxî.ÔšÐN<à{7dB.Ü*':îþà1Èý¤‘¼½¡Ì¡áÞ$ÑbUU#^ì#cÕ1ß;qnzG2¯z1 ‡DÅ ª_·ç–¹WO:3ü8Ks¬Îàʺ pHøÑ,6‚ýl­ºEEëŒÞjØ› ïü>g~ö>`qáµâ ãöaVÆYGÝmiWc¬>åÊ:¿ßfYÀÊx 6²ÚŠ„ól ãi®­QÆ–{çnK§N;› +îØ˜lg³Ðt€g´»¬ 3Ý­r×efš,—Ï%‰€æ:ù»ÓóÉNÏyû…°Q¸úv™Ã *›ºŸ´ù<;.§4¤…|Àš„h¡w1g³Y_áÙXtµZÕ«—×u=;¯Óýi½}±_c.3^ã5^ï×k·«zûâ N÷ºº9ø`mà`œ!.ˆÁõtÇ%‹•†@Sã,0—“}Þp&öjÎ"RàRyÎðù~“¶Q塘ə†X‘!G‰L XçH1¾w‚{b?39óìŸE0l/û‰T="Rœ$z–I¦ÖNTˆ=ñr7 þ}f ·— 6.Üq¯V”ó뜵~ö 2¬Àø‡$Žø'͇Z6œ¼E¶Ü}rJ2`¼E²ˆ«M{°ç—;önò³AL‰ñ6’ˆŽs 7(ì³G‘Û÷îø™mûļoÑ>dO©ÌådÁ-´ÌÎh3‘=%Þ`ßÙŒN ÙÐ5/Ü4÷3|É8HÚµÆr¯æZÆgñù~Ý“Ñð*“áLJ²êî×2sŒ½õ­neÂ;›"Á®ƒm›CÚj;#‘ÇÆgãÁÄϲÐÝáñغ“Çç¥|¡ñ³æV¥Î»±Å$Eî†YgÜÆ‚öëH¡„Ôï'‘É šÅvrr2ÈøSg³Qc›³eo¼okl™§æ16 î‚Z(Á ,›`ªžÙˆuµ\Öº¦5íªæÓ®nWcÀ3^ã5^ïßkoÚÕtÒÕz7­õfÝ8¯¯¯{(A[ò­Àdå-û¤ý„=ë\y· {9E)öuwD’ËɹdØg"N‘âøèÅ‹}åÜðqÞo?3Û øû ¦¼²auÀ¿S(±µÁ™nk‚}þÖÒÓŽ/|æ[mŽ$.iSBر¯ï­jÈ“åµxŽ!œDûqï¼t*¹W3i¤i$@ÆÆ ®)$2öañëÜ»…¥ˆí<66ÈtÜ=›Ízþ5ßgp"™(“?€Â"ù'wÌœpN¸Y)0F²õ¤3ãÉLÐdó¾ æ]“»»»üˆš–™óÃnIѺZÒ{ÈgÆ„1ËÞ §Œ1¦ö%p0Îd²b¤$‚u;q§Y–]Ì­ˆ’†—|×ááá¢DÀÊo·ªI 79’@ÆÆ:é$˜& ¦ü2Á4Â] ›6¾ÎÔ‘¤²ßDD*b‰ŸeÃ4OĪf9/XøV=cl\Ù‚P—ÒŽ ›³ü!‡¿ß¾–qáýI‚ô&gl0 Ñ×ÕßŃLt çtµÃd9àöÈ¡ã)ñÔñ¯ñ¯÷wwFÿ½Z c-Sí$}ƒ÷çì°{1ÉDô€Îûœ²r—!B>§ÒhÕÁ<çŸayfJWÖ9g8w!ó›Kꞃù|"N8§|†ûý$*Éõ´h üjºŽýÜѱ⭃uó$|¾;*ÄŽÜ—Ñ4æ‰ „H„‹Ø†‡-:o¡h üv{ òº…HTœèX-Øb†W¶gµ<ºYîÄ9ÁuÜL‘Ù‰:û26lAëí丙DÈ1?P7â#~‹!‰tdœHYúÚ"WŸÝæêp’º= &UGéLÍ•s°zV¹à†Œ£Lx“´“(dæø7Ô²rVo0!ëÑ ûn°PÓ¸'5èš–Ê[î(y²™’ÈõZÅË÷Þ‚Õyì‘|îÞ‘v´Û¼ÝYÉÚ™L–VÌö¢+Ynù9Q’øY]3w› {óB¶Fw†–{ªzðþ|àO:uîNYÉf:ömgæ¥1¦T ø[¾ŸÄÁŠ*6Ô´Ù•[îyy“# ócye …†Õ¥RŸ¹O³Ù¬.//ûM£¥—Çk¼Æë ½6›û½Øp2]tþ}†›xlãAÇ'ìϦùlÎ)Ç7œî¸T %€W«ÕZÆû­zFüBrc0g4ñ‚}ò(tY}3¹œÀ£Ò&À~Ù‘qF Ñ Y@ÀjþU{'‰-‰a¨†óßlÝ‘÷î¼¥­ÝÉØÐ²Ûîø¤× ´ÛÛÛAñÕx°<7^f¢A|` fP|7÷ÆoKÿ! XˆðlÌáuÜmn»;u|>óŠ$“9m‘*C*ý{x=;q:àY;¾±È¿Íüç–ZoŸÌômš‡@Í” ‹×©Œ; %h3Ùß¡NdȪ=àT­3«~®«`¨Yú8Q‚äÖ*Á¸!JæN¸£c?6w«œäyìX,t{ÜÌç󾂒] -o“õ Æ]íñF@’ÇØy£Àg¦å…Âäµâ㇇‡M}^'àwÅÃîö¼Îdä÷$хμK²>sÈ•*c8½ QQ°«+Qi&ê›çî±1¾Ö>›•ZÎhσn˜ï2Ñq[Ù‡#œ'QNpYn±û`¯ñ¯ñz“®Õj]±Îʼ(Ù‹]!fŸ·àE4sŒšHè¼å—}†û„½Œ%ˆí»gŸ˜ÉdÒŸSœs/_¾ìƒ¸ž†o¿˜ëÉïsb–!C„’c3ôt§7Ú¦å¡Ã½9ø%þáýN³HM°N,ÅØúý××ןÙxÝœfb?+ÒÙÜÝhŸÓVdsG†Tˆy"ñÝÕ`¬2~±X€“DbbKî“ØÎcÃ-‰ÛíÁcE\ÖŒ 8=ö<›„,‚aM9¾qlh%d¯9~?1"è—g“™TîJyBOv·ÈÈ®^reö¥»L>/½Pìnj»ÔÁzâ˜V¿ßÒ‹nòÛRFΦ‘n_26& OâÍf³A딬ÖS¿—"‰|d±,äô¸I"_nRNŒHd’eü®;<éCÃdujŒ*ckGeã$©öÐrOÿ¡Ä º¢a^— 'ØöÍ¢âaâ¡5ÞÍã²Ø¿ÝN¥£ršiy$‰s5ˆyÏßÃÍb!û°ZŒÇv»YŒÍx×x½‘[¿]̳»Þ‚ñRŒÌêrëuЖ饫aèY&êÂ̈8·(èqFcpa)„ÈZfüÄ9æØ/;6†Æ»ÈíB®Õ«H¹wCËì¡ãsŒøÍ±c3­:æb¥cEC¿Òð»ªí1è`;Éü~ƒhq|ãnñ±a†ó¼XUÌ ¹Œtò½›ób¤%s\rl2®æBˆÁÐùŒ‹[†™Ä–ŒÏÚƒŽ]‰…¹©§XÀ ™q{ÐY5‹Á{n!c±² Ç-.Ãd"ä…œz^X–©cÀ )rÛØ„.cLÝ¥0–ïu§m™ìÈÈy2g7‹…î{·¼1¯ꊄ“2z¶ýùüÿ”?´s-›V.ô–ü²auN"ݲ׋_g±ãÉëIôKyf:}96)ëí`Ýmb«–Q‘p{Ò°>«å9Id‘¬x¡Zf ­g'y~Œm’$-­Èwsoîbú`lId|¸ºZüX¯×µ¸šñ¯ñz3/Ãx !ÆK…ø£¥®iÄFÆÖ[Ê¢† »Xi/8w%ì;°Å‚ù’î"¤Ÿ!<Ü!&²yæ¹r®šßì3žï³…Ü”&H™^îÝI—í+ ï&pl˜çdžÑ6w|ÄØ9>rlÈXµü… Ÿ–çyÁë¶Xȸ˜gÚ'i -ydæ­‘Eiˆùܼ øK¢aÕU•ý‹2.N0Õêlî½Å+³­Ir§,ÀØ:11¯ûÕc? ¼Rr!:`M2Z£L¾g²¥¸[\Nd.//òÉÀ£xÿÕÕUß‚Z¯×uvv6h'¶²bWî>e¬ŸÉj³¼Ÿ¶ê’"åŽ ›ŠáO`@IòÈè ËsÛ8·­ ›ãoÙ„½‰›ã; ãóºdÂ:‰ÊdÎy0GÆÁ¼ÛÎüŽ–Ï d6c<¹2z'y/^¼t› s%Ì•(“÷i­r?´^ˆY<ÀÐ0ó‹ž“ôrÀ`éiÃêL åÀK8ÍB-â`~Oµ˜Çk¼Æë nÍpNpN.MGƪª‹Å¢yöööú*ºýÒ̑ɢ”c* fìïFÀ%X4ÇÆ>}¾P.M‰aŸCiŒh‚{*›ZÊñEnC¼Ap&; åŒoy’¼ xëb£¡gÐ8G­*VUOâ8¾7ùx=Ç6ÍJI r'5;#BˆAˆY\¨µˆ• ìîÎpÆó{œ ©Äë\>ÛÐ2ó§ IÄzÃI&÷F\mʯó}V”u!_g¬1©eíðÿÝqr²Å/âÙ;Á57ÜÍÏŒ«Ïý“o¹W&³ñl³)hâ8–ôûàu]×'*\vOM­pˆ[^6îAbØT–ø#à5Ž ¼ >ä(:6®Ì;˜÷&B×Ád~›…æoc¡yò9+_­Vuð³®æ\__÷²x­€å¬ª^ºÑ“9³rÃê芸õËw÷îóߟ²ßÖç·i¤7`·äéx¸ä‚y“®½ÙÉs¢ãyïySU}"“ø\XæeJ?²&¬AOl¸dVƒ€ÚMÚÕpÛ$Åöf2,-au]×Õr±xÏ*f»Ý®ºâ_¡Jj•~؈×x×—~Íâw-ÌEHå.›BrÖdA޽Òê™6}¤ƒNìcx¹¡e¤Çð4(D¥RÚW\\\ ÒXázÚ‚€•sÍçœýÐ(à%Äš®‡y6VÞJÔDú¡!ª3›Íz蘓H äÄÄV¦ø·AÚ† ×CÅò¡ÚÂý[HÁ®¾ÆÏr!/è±£íl2›EZF¨Æ]ûð{ùòåàõ\èÌ›ûßÿÅõ4f]Õ¬«ýùôI+×Øì®¶5TÍ&U“Ú a³«ImkZ»Úm7Uµ«i·«Y÷ú¤jïá7̧ƒåý{wµÛé³»¯$n¼Æk¼þÿ¹³OWÃ7Ÿcv)÷^l*pmörÃÁ‰?ˆ R~Ù³|Ý~k6Ät1ÕêUœñœ1.$»XÉgsÆÛÒïçu£"H q6|б³‡Ž94¾7{¡O%¼ è4 Çx^çóØ,&`S¢T—" ãÆ­£Îb¡Œ@ª–Ù½þêêjðº'„1¢¨b¸r´5\$‚}»&¼;ItÀÊÿ<6l’Æp¶_\LFë¨36™ä‘ÀbÖE•À‹Å8Êç°Çjà€à»RÕÌböò¼ružqsµ$+<æ•.Ï…ïf“3ÍØa !¸[æDÊ ‹xÞ06öà1vÙSW—XSVtmâŸ]{Q=«/k·ÛU7ÙÕgÿÖ/Ö¿òç¹þÆçvõë¿öõ{Ëi}t±¨¿øWÞ©é®êù´î~þUý[á—ê‡þÑ®æ<¬oþ‡õÃÿã/Ö·žVMêüp>¨b}a HÕt>©:šVݾ¬ïù‘Mý†¯½¨ßü©YÕåmýÑ?óùúÑÍ^íOÆÍx×xÕ`Ï÷^ÚÚ‹3˜7LØÕr¿è=ÁíÉÉÉ ûîøÆªhŽ1ÜÅæœ"y"öÊ`Ú«ãR Ç6~öëÄ/h ½÷î`š‚ðr DéÑc®ƒcGD“ZÈ‹ Ùl”ß›B~n*p"åNœ;6V}%^$þ!v´*ñç*±ežñÄ‚"þ±i¥Ñ:ÄŽÜ¿Ñ<îˆ$R$¶êû¹ØÉou‘œ‹{gî™ÌOüc…7K;â~œ38§pCÄæW§?É?ªh$¸nA6a€S眬Ü”ìˆx6”/eÀ¬^ež •÷Sõ÷åD"áS9Ùy¿Ú[~!&„åo3þÔÒŒ&úñùƺ½hx”M-íÈ&hu¸l‚ÓÙ¶v—Ɖ–ñµŠ'3“ 2œ[îà$ùüĺ=hU2wlȺiº¢ÁBäu:2ü[>R?øo~²¾ÿ»?VìwœÖñ~Wÿïßû…ú/fW?þÓ7õ“W»ªIÕøî_Wÿí¿ñkꇿç­úàrøy_<çeWµÝ¯?þoÿÚú³¿ÿ#õGÛI}hÖU­n꯾3©ýÙdŒÞÆk¼ÆkpqÆ›KaA^c/·œN“õí'’föjâ¡£££AGèÕ«Wýë†%tÍÐ{^§#âÊ>/¦1³í7l M!Ö\*ëÐ\9CÀJlh‰%ЉHT ë>eŸ<^7Ù°:s|)r§Ç… oâÙ¤Œ½â J5;¸áFMXTª&GÇIž9†W¹ØiQ+«ÙÙçÅ-'fN¥!&ó6E°œ™?m=û9uÜî–B­‹ôÌæÑÝÝ]?ï̽¢hkJEnÇÝ/vjKèñA^¨\-âq« DÖÊ€#óÆskÕ¤&&´!@n­ò›h/&0ùžÌ|þt:p- ËÌy'*HO§Ù§+Ùv¶jÇÙÙÙ~dxð&ã,áJð}pdØY LH;×›sÄY»;&<óTíXˆˆmÃK2î$„¹=˜øS6!·-ó˜úý–®¦›äÊ›;yŒ­»YWWWƒn—;&Èfš–ηžWÜ?ÿÎ…Ê&ÈïI‘ ûó´’sð«®zc!3Xüûâââ±óå+qֿŢþeWµ›ÔoÿÔa½}¸­Ùd[¿ùûõö~UMvõwÿáª>w³©›]UÕAýË_»_»u}øÇõ­»úý Ý®ê­“ú¶M«Ûm뫎&u<½Or^ÞUucgf¼Æk¼¢cÔ;ÎÇ>.˜9 ÌsÌ]ŠRœ)¸“êSœCœmœ3}†±—'G˜`3ÝíyÝô¬ÞÉo0´Ýð(~»}fè68¾q¢‘BTñ‰½\Ð3 Ôg®¡ïUüj{Úø¿þÏ8qm¨ ZÇòË$Ð ¬8˼ ‘J³òŒk!´ó{ŽŽª¯NÂ,ô”Üt~ÃÙÙÙ ÛļriÎ/ŸOìq†)æfy^Ñ©"YI³O«g'Î *k†ç@˜±!o1# øVç­g&“Ùd9먻fuž²baS"þgu)6'NÖÓ6ƒÆQ'a~¿oØ\ ‚yCÝ ]³@*s™ðe#.÷Lh·3OWSZòÌöF¡uÉFçÀ†—κô]]] ”4Lx:Æÿ'É3vÑ] jš#c¹EcLYè,|°Ç¾7ÿÖ4„²¡¿Ý•Ü$] ñs7¤€×²ÛÄo7Þ5ÏŽÖI·|3Ý®t\v%ÌKW4HÜl4æ.ª79w:¼Ép¸~IùÃnÛìï¿ j6ŸÔìÞ¦^.׵ݬkºÛÖr³­åßÍfµ·é:BÛº¼[Õn¾©év]/Ö_†èd6­YÝÏ«IøáŒêfã5^ã5Ø.ÄS% w™iãù­°” ”¼ì;$ yNYpÇç Á¶Eh0µæ÷rsVRô2üÊÊ£–¦+á û C€ø>:>-û ÃîÜ•0,3Ú¨ˆ–úg¨“8b;ó@lvÎç'6{òŒw àŽŒ}dH8|Æ;ÑI完 ­jK,gÙn>Ã|Ð,i/ÁKžˆ¡cŒ­‹æNÒ(ð{^&¿ˆØééäž›77=90.®&ÒÉÐ~Ï þ®„sºî.eªÕy<É 9ƒuZXóù¼ÏŽÒùÖÁ¾Ý]©HX‚`~½^Ú‹–àsféÉÍ€¹âÁ÷*™Û“Ü ]î•…î€ÖÄ6«/ؘßnu©VÇÅŠp†®™Çaœ£«9îv¹uš°<·Í³ ›”¦9Mæ7aŠ„ç‰K Ó•Èn”±ÁI’´ˆ„»]lðî¹­í{÷&•ÕÃîܵ?Q@ùo)dà‚ÀÝ*ÆŽ¶q¶…½É¥÷RVù€åµ¤©™Æ‹®™Õ˜¾ö¥øÄtU?ÿ ¯ê¯ýä¶Žv›l7­¯ÿôa}Ç[Ûú¯¹«ÿåÇß­¿üö®¾áp]?ø“¯ês«ªZÍêÛÿ¹ãúŸÝ«³éM½[Ëúþ¿ö õ™ß:¯Ÿûì‹ú¡W]U÷+ìíª)Ó<^ã5^ãõ´™;½¡Ài¼¿y®†@Û^ÇDy†;>rÁ.»y†'Ĉ`ÚÐxNÓ~DÁ5öIùm-ô¡q‘Ú -h—áá6}$F0DÚg¼ zœñ†ý™ ʹÌN!Úˆ+‰×œè6ççnž¬‹¥~nYŒtüã¿-HpÝmrÜK—× ­çÙ96ÌNŸ… ,’•²ÜW3v\.—ƒ„ÝEtâ£ô/r¢c›…R¤NÙobK^w¡!“87Wܱ1¨ç´9`MCj¬ùlB:`¼¾U5ø¡ÖYGkœÁ>å Rßo²™¯št@5ÙÍ\‹… ž ŠT9À³±az ü<ÔQỀY‚ßÅdvµ†Éγ ãâMÒI¨']þž`Û­X'(Êy!»gŒ'-w l{´Ú‹1”†üYÑßê…n¢Ÿ\“ݨ41O­ÈfÃJ«½:Æa “íí#ãJ‘œîBÚ Ô ª«)VOÉÂ:t™c“Éä‰k¯‹æà¼Wiæû1ç»ú©ÿ몾÷g¯úÎǫŬþÔðÉúÿµ×üÉŸ¯Ÿù¹—õ‡þümOvuùjSëWÛúmßõéú÷>ÞÕv~Vßü¿]×~~[?ö7?_ßú]]ÞtõὪ›…²’'9TW“gº+¿-²®ñ¯ñ¯×Tfö Ä8çœÈÀ£’hÜ~Ý6$Bi¡]+wYjŸ³„øÈ|I.£2ÌáÌ#÷Ùâ`Ü ´Ô£ŒŠà3²IAx øg•M§-]ÍïØ¯…ªZÆÙ <ª%¯Ì³±Zg4ߟI ÍÎÓ´4Ž àŽý -£ãa…4ó—ùmî`Öæ¸ÛF«)mM,I\M¢Î÷û²RKÕ µ^æ± üba’´T»s"ã$ÌóÊñ‹=zl?á„Ô÷ÎØJo索P3sû‡c2š±8lÚhG*,q#扠§-6&OUõZã,üÓÓÓ^çÝ“=¡e–WLø¿Å2r–ÑåßdåÆ ’Õ3YŒ“Lå+ãæ p,D Et|¦i;3¹ìïv»zñâÅžˆ¡k, ÷î€Ú„w“ÕœŒX™‚J“…¬ÈæMÔð©ÔÇw!WÒgÆ^+p¯ÜZå¾;oænY•ÃØcË3³™7æØ¸Òf8Ï•…l1ËzR­±[ú6ac“rûßfŒe)-Éù^‘W]UMfÓ:=˜ÔÙÁ´Žç“šv“št“št]MºIͦóúЯ}«~ô?ýd}ï×ÖYWµØvõñ_s^â|mý¯ßrPë›E-öêÏý»¯?üÏÔÙ¤«½Ó£úÓßû‘úŽÃ{ÎÌÞ|RÓêžvXºªn2©“‡ßp²7©î!‘™Ï§UÓª}þ[Wóù¤N&uz8­Ãé—Ö„¯ñ¯÷sgf;(*´¹cbT‰«¿ãtP¾2a=áQ´t&¬ìÉïDÇèÉd2€!µÏë`ÝAWê]9wgsÈ<«½¹ F×Á°3Älˆi®ƒ½ÈLæwÁxæêêjpnaàb%c"†3›Br*s1–ëõº/fzoÔð)Þc³O`›jSè嵌-[16Ķ>ß³Xiø”94F ØC0å—»®ë=xÌ¡aŽYÍŽx“޼âslsX°(!“ø/ZHÁÜ+óέôçn–Í>­ˆF‚ÍØ­Óô™±'Ù•}ì•â…ã˜HËÇ%uªªÏ Y@Îê­gÍ€¥ÄžÛÂÈÈYià Ñ\ó\<ˆVö2|ŠÏ·â›±€tD 24ÌõÙ–f"P­Én’M<6–Øãý¾&«%†ù>ã qb¬R™ |,4·n]í1üÉîõT{x?I”ùEÞ¬ôâÂôÌ[%W {s§Îªnå¦tµ«æÐxlxÅêjÎjµê7}*Y®µü‰Xg&fÑUK3²Ø(¼)¼7Ÿ™ÝvW«¾Uïü‰TMç®u<þÍrU×wë:ùÀAýÉ?øÕõ§fóÇîÈrU/oïjµÙT·]×ßùü®þÕß÷ñúÏ>¸WÓõº~êïÿB}ß‹®ª›Ô×h¯ö¦Uµy ![]œÔý'¨šß,7/µXW}ÃïùêÚ}ç^UMêîfUwË]}êŸy«þî7~´ª›W-Wuy»£·ñ¯ñ! M CÇØ{3èb¿Oû¯ ñ–©u2Ä-{੺G|Ä~ŸÉ‚ÅŒº®«³³³AáÙ…dâÇG)vdÕWCÏ\ÌlÑ ,¿ìØ÷¹ëïæ½‚Í•>2$f)väøˆb©ÑCö™1¿ˆ±5e.’â#Ƕˆðû]èu·ËÐ6b?Û’Ø3Ðüèì¸Íç|7÷›û}ùòåÀóÐH§”žvׄçÁšð¼Kþ‘»]Žß(‚;‘i©ýò^S2œºkŠ„.| ¬¾`ùÁÔöû¼7 *çt™cã4©ÉêRî¤jˆ[r܋ГD„³× W,gw{ã$Ÿ¥ZãMŠÉš\'yvW5ü)ÇÆÐ3·f­øfœ¤’•·ÐA'Ae“²— ³7±ÛÛÛ~.X^±±!”«-æ‰p‘óÛÍ1‡†Õæ‚1¦-µgõ>`Ì2TÍcg²¾Ç†{ÿÚ"ˆzƒO1‹<8‘AÒ<áš6Œ ‰ç%U>'´(ÙpY5„Mf}³|ï'ÿv[/®—Uµ|M¥óþû_\/ªë–ÍצÛú³õóõë®>}>­ƒÚÖOÿß‹úüv[ÿÔ[õ=¿é¤öwËZ¶Z)»]½ûrY]·|æòn]«Åfð]›õ®^\.ªj(ü1^ã5^ãå‹Á¦¹×sÆ“ä˜ëi\‚6CÙÝ=g/6tøÆ2þ.È%rÀ;CË8-l³sÎ1ŸCöz£Øh±Í<éö8ѱ!¸Ï)Î]Ë;r|Õ ÖIJ(r[ ÚEèV0ox“-’M0n2>ÏÝÅJóDHâ8£“#cùeæUŠ™Œ,7ñˆ¹ç )âZ ÉÅÌçÔò¬Œšaâ^‹ ä¼pr:–ÕflˆOl‰B’eÚ‚•„S¶ÛóÂFó†ýµd¹T9öšµº æax¡z²¢C듉j‘!>ž\`ýXx†žšÆCvæHPGU› Ð˜ÕÌ,÷÷÷ûÄŒöØ<cýZ› 2¸6=J/2—“4¤­"v~~>¨¼»¢`B"[«)]må +šdµÅ‹…gOÇņ˜t \qhhY 'ÙrÃW«UÆs™#cX%ˆý)V&7± nÎB.±že½án¥â[Bû™rb5ßår9ðbÎ9IK¡#J;›ƒ»ùa¥¿Kèý“ÎŒIÙÎŽHy`^(LŽÌšKGæÇ‚p{o·ÛõÁ|’º]™·J‰$6«ŽòcŠ“¨+Tc\ñà÷{!ÓÒ3. ï^¨n/zò€¯%›=??l¼lr|“ÙY·ÛÜ̃¯åþœdZ~0 3¹÷tuÖž +ž0Á“ðî€D†÷so6 µÑiò{8 <­6Ó‚Ždì|¯i’æ¶1•.“éüÛ[-Ù_íkµÔ·ýî×w~ûÛU³YÝCÑvU›mÝÞ-j±Ø|E~×x×x½Y—Õ±Ê'â펋ƒ6öb+o9pÁ, ëÄ+úЇúsÆÅJŠ©­‚›y$îÈ#8Þâ3ßÒ<óüö–{š:r?Œ+ï–vWÀ<ŸS†é6çØÌÁxò4¸à›Ÿaâ+?«³³³4Ìü¥ù|Þÿ>>ß^)†ÝY~ÙEnxQØ'¸ Ç%Ñ@.vš›… ƒuǖ溫õŸÿÖ[oõ÷f²?I0óÆ"[NÈÍ+K8¦as·í“Ð2âfó‡Zþ‹rr×ÒjyÌ wþÉ “Ç2¼]6e´‚í;C|Ú,ÕÆßpò]-yeÎS¾ÐX?“ÊÔy!¿bì¥ÂÇBf“# âc?¸¾7C€<Ñ™ŒTz¿‡Eb‰`o& º-MGŤosX,dàÀ$:SÜ¿+éC[¹Õ¶¶{+ÏÁ†šÌ :>nZ ÕBI¶·*Hêßçw§¼2ÏÝ•9;ß²I’¨XžÐB îylSÕÌGû%tû³4#‰ ¡ZDA¯['Bù:ßÿ•è]¬ÖÛzñr¥pâ=^ã5^ãõ«}ùœ!¨‚èíîz*TrNÙ†À~giÀ9åàÝg<¯[ÍÊj¼VølàOÞ;Ósè $¼Û«Å•w«Wª0ÕBƉñ9ckûüvn;örì×C•å‘GƼÛôz3%"ùÏ’S\¥#dĉጪ°ª«ŸÏhŠÅŒùÏîv¹ë@lÒŸÑáÏHÌjÙnr&$Ñp,¸QÄ/.‚{Þ;Ícij~cÁ‰Ÿ¸Ü0äÐ9i-^>cm³t'IGßç zÒÝþøøx0!ðZÙÂ<*ádoڜȀ%4 Û<ƒáXY9weÂVª–œ®V«‰ƒu«OÙYÖkÈçd§õÊFi,aâ[²RÝ•h%iÆ*¬»Ult»ÓÛ,”ד?äD*qŽ `#`!zæ™Éi3Q›iµä Ýrç~™ì­DÇF¬üÛd4„<‹EÿyÌWªxDƒ 7æ¼ÅìÝÄb|/ó†×ONNI¢óÚ;ºY$e†¼²¯\âàîÆk¼Æk¼þq]†XÛóÂRü)¿œ6ðDì·82|Ÿáá)aüœ ¯Õ«Ò4Òj‚q‘-`ÕÖ”ÑmYm¡''JîH™vÇÅñ‘ƒy„ ËKÅ\âb £ì#ãb£‹™Ž?Öù|b?CLjÒCÇþІkùÞ ¯2·Ü¶ .²3¶Ì% ‹V>µ(ƒ“D ÷üz[Ö™`;¶u›ÛÛÛA,KGÅóÆ"V}¢DÜm¡ó³Í‘®âbûÙˆžyã.¥•Œ ûŸ8‘1|Ì2²U‰‡s¦ç2×Á¤mWÂÍÁ3ÃzÈòy-¼œ[·üvz:¼§—Jê¬óùVWpç`= ¨!mŒ©5áy Îjͱ+°ùIlŠl‚†oQ} É$Õb&²gû °Išc´ÅÍ&ÆwYö~‘îƒD­…ä”yÃwËs~N¿ß Ù:ìWWWáW,´À‚sœI>‘ &Ù­…-öàÄ 5uØ9 ØÜm4Æû-= ¾ÖÈãëcò0^ã5^oæÅyáD$Ú]0Ë®DÕ=t,ŸCPŒLx8g*ðrÎÃÇS™«êQ†—³ƒsÐÝw‚yŸ›¶AHyeâê”¶Y(ñ‡»þìù|^WWWýû'à³Ç8m·Ûº¸¸@Œà‘pVæo±üØžëVH¡SBW¿µWãïDè|ËÐÒjwNd,fD!—Xùúúº;¤¥­°vyy9(Ÿ :kæÙÈ|,ÇÉ@Ç¿9.NCL^'Ùòï¾ÎwÙ$–B­¹[ö/t¡6­5L™°WJž»ù?Ȱ<[sTÌŒ€˜…Ê z¡± Æí0šÊÎ Ëòo‹øý-Ô¼•«««Aâå¬Êº«1–ÈódvûÓ̤jÞo,_n2Tñ ¶­èfyÁÇÆ› ÛÎ$Vt#Yà9Ø …Mž]wdL†£š’°<ËýѺ¥‚C7ËÕîÏfœI@{𩾠-sÅdÇ›Ìv»íÆü+ÿÍÐ0ªå‘ÝšÝÛÛëߟ>3N¤;¸c†¦«ïjµê¿!Z§Œ)wê˜7,ì„õ¹Šg!¿ßøh-9^ã5^of2Sƒ¢\û@5Xp‡B§(êÒ÷^›2¶pdPêJùe¤ÄæVpÆÛïÌ @ïC˜+‰Ä°}høn›Jš#c¬Ï\Ãî £¨MG‡˜Éö6Ää󮯯ûXÒBOÄæ'“Iï¥Â9OlHÀN°î±qÑÝ÷NlÚâQd&6l™‰ºØ˜"‰š°ÈƒùA0!Þ‰Œl«˜Ù0s6›õbF3–àË¥ãbœe¶Vù~gÕ-ç[O6*ï6u´WŠ“2Ë#§:“5å !œ9˜w·ÉíÎ?È Ùd|æÔçYYGn“áQîFeVn (ã‘Ä´ì I´ò°;æ½érhnãc~e·é6y“õ¼¡«äçnÇdÏ+6ÔýýýÁ&ì¶²a{I e£qqÀF¬žV5Ko«‚¸ŠÈº}–ÇýïííÍx×x½‘×v» *¼spNYÕÕÐùÜ«9‡Ìq êæÀüÉÐ0CŽ€ñrθsN™'kH’¶ý:ç ¨Ÿñ\éç®… zޝ\èõ9eø·Ñ6æqX"8-è–90?øx‹?mþµùC 7äа¼ŒP-³‡ dÍ;n6,ϱ'±ßïXÝEpó²ÁàÂ…\“ùÍ¡anðl9>ñØÚcÐtwÂ,T`JóÎâ'¸NZ¬Šæ"ÀÌ‹Þ0Ûœ]ùGÑb³ž6ƒïʶƒq&·«Ë¼nL’ÕLè"3·Ã:¯c™Š$ÙV¶òVJ?»E¶Ùlúމ+,¿Î÷[gD¨åÃF•ªe™DòûP»Ýȳ¡šï¶3›´+QÖÝmb“4¬Î$Ä ¦ÈT¥Ä^k2æ½™|<*•+¸wÞïDÌM›æbr¢dCÐä1§S•ƒMбgì²%îÃÍÕBÑÖæ9XƒÞÅÜÒÞKI4\b6›Õzs7F4ã5^ãõÆvfš\‰N¯7RΠaé—¢5&e·80.øe@Ê™m±#¿Ÿóب›^'‡×†–.¸ÄyeäùÏÓ&¬;~¢ë`?³ôCËDÇòË–®v!–±7j‚ûµ„vÎLË+›k±ŸÁÄ7NP¬Ãq1Õðp µ†Ž›¹àN˜!‹îZçu£m²˜É÷Ù¾‚±áo[ööá³Ç sÓÐ3æ;.žæÿ;ZX‰×“mE6S*l¤:›Í±Ÿ!)=í$÷‰ÏŒ37´¾‡ÕݽþáÎf³¾”íA·V¬sãþQξ¬ÞÀL)6w%Vùý ¤;*dp¼¶ÙlúÉL›ËûuðÝžÌæ°àÚkÍzª5™õ2^øÌ+hžÉååå K7QÐY{BÓ,ýȽÈeŃßk+–¸šâ–{’ Á92VŸ×b±¨ãããû ÐH¸¯ñ¯7ôêºGcCÃïP•·!¸ƒªôŠ£#â`ß0c‚²äûó]u"Ä9æbäññqŸÔØ>";*œá†Æ£žih»Ûmc€4ÅN3ôV°ž>|x”å‘[sŽQ-㿜œô>HãŽ9,Mˆ‚}Ç~¾w£…(fšpN"ÃßÛ'Ø*½âl÷`hºý™ }÷‹ø‰q¶áeÂˉ Í·jq… ±.r»Aáyî"1ˆš,;6²Ò_Ê~'ZÇEdrÇ/β”ŒVÇföØŠÝ>!³ÙPÉhV†pÀ—¤,D¶,ÏÌ¢ž…³7CËÀúûÝ^ä¦Ã©}rŒ5,ÎíI¥lÿy²²‰po®Ü³I¥ŽùEÜ›K¼8È\½Ñ8 4ÇõwIRUÓ™Åhå-K3’•·àQ,{ð˜Ÿ" ü¶ì&¥¾¾ÉvæÀd×ý|wIœºÒża“d˜{•EÆ4É/r¼c/x²64˜DŽ ->eÅ7æÁ¸QÄüÏ÷nT†cý\¸×„—[UÕ„憻°›q·‘TæNñ6Ô\¯×}14ë‚øÌü¢”,wlØ‚îó}¶æ cc ¿Ë“tžøÊk&­3ž$3Î í7bieÚTÜ ¢„Ñxr¦¡¥•»L–³|²y -,Ÿ4Uˬg W©M!=à@|è<­×ëX€¥S/!HÖxwl÷ÖÜ$ílk㜛\Ëð’MŒV²­èF“¬ì0IÞjµ¼NVí¶5ÄöСcÓ’f´c²«A<'2Ü›•-L£’Æ÷y·€1¯–­$A¶È‰Öl6ëßï–¼½ ^‡¯54ŒMŸ5Ã\3É‘$Ê™ÔYgÎ3>l‚Hò:ÊårQUÝ â3^ã5^ãõþíÆ<ìq]ÕdÒ ÎhC|Œ; 6—މÝãÍ&¾!ž±ª+›¡ï®ÜÕÁå3œ³Ã‚;Ž,-í3Þ·V@iˆu/›'kiiŸÁŽÕ\w·‰ËBP¼ßˆ/yF;Iã³­ÌÅû“mÓêD¤^E°îøÄbEYb˜ßjX1€}Yrl /w°nÙoîÝc—bHŽýR­×ñ‘ÉþÑy½U¨uŒaè>q/ŸO¢g±'Ö”Ñ: ½]—²;ÚÄ•yeã ™1FÔR³v¯Ï ÌZã–Wv°ï Ì£«×®Œ» âÌ®‡%†Ý²— •ûÄAZ/•)ì0 iÛð*¸ ™gggƒ62cÃCAzš€˜±á3 ¯" íŠTɸ¿tgÍ…JG& ¥¬èæ¬ÙBTý]‰²_vL|$~–{³TbrdHÒø­$‰\t-x?Á¾«1Þà­³NËŸ…ã–<ãŽ:ãcÍ/JgZÔZ|ø˜ã’› ÛÒ$2¼—{OìqÊ~»úAµ†g™óÞä:vµëºÚîª^½|Y¯›1Ú¯ñ¯÷o7f=­{{­É`/†k¼>g4ç¢!ÔÀ€ÝAÉ®Bzɹ颅ÚTïä÷rž» g¾Q!œœM†ÞWÕ€'B|ã¢u†ÚØ4÷ŽD0E_[,#ø3„ˆ®„c;+­zf>ž…æyÝ=îÝññ“¿Ûüiûì‘hø·÷¶ç iŽo’5NÝ&Ɔ¢¶¹ëÄ~~¿ÇÆjÀîzð:Enwdˆ›¹âê”õ64Þq³;mkÙG86cÃ='–LZè&<;Öœí+úN›ƒ6+MXÙ‹w«‰<>ØX¿õzÝ·¸¸Œ“ìºnðþªG Œ(çìÍÆ† 8ð(OfWæ©h0YÓ¬ÓOWÆ]ñBsØÎµÜ›/'yé`ZUþ‘ÜùoÖ¨OÅ68>V*3ׂD.…Œƒ¤;bÕ2\ª1®D1/Òñ8±Å<÷”'ÌÚ÷:€G=Œ mn>ß­ZZ§ÜE.“áòó 9 ‰¢eCQæ&°|¾ÍD“ÄèyåjObDÝ–nLíü2Ïöêêj°é² ò7t9w»mUWµëPÀY p¿ã5^ã5^ï›Df2©ƒÉ~íº é炽Ú甋Fð 㽺ºêÏ,Î1¡ÒG†½ØA›¡óy&Ö^s–ÚwÐçøÆÐ3r9Ë\ݶ̿»æ"Á˹¼É^pÐ*O"ä€Ôc—ÒÔĆ.¶x~væ+?Y]Ô]‹ôZqübè<D>§2vŽm#B"ij±=„¥©[7€Î[ÒØÐzîÝü¢‚}S.Ì2å‚BoÎ+ÛšXbܱ¡Éú|–c~ÁÍñu1À:©Xëø‰ÿvuu5‹gƉL‹ãbãÁœlîÏÎΞ(0YÒ8å-‘g, å›]­0|*evS/BJà(íðîv™ÍB-?hõtX÷FàjL¶¥½ë{?;;,®HÄŒ»ccü-I–:2<îÝmvo‚†íQ°#²%„í±cüª»nºd³.wþ’ÃBWƒÿfHb×uuzz:€Hì»mí ÞÕ'y†Õ¹R•Ð3·•slr¡ÛˆjM*áxC'Aöáè“Àš@šü#æØýf8­Éäþ·“Áߎ×x×x½_®û÷¼&“iÕÃþí}ž¬;6¶XHã@ïóU5¨¼s[ìÈ‚;$:-±$CWÞ‰̯Zoø¸;HIx·‰‘œVÃ+Î\MºoØ‹™œü6b*Wõ­¾ÉYHåÞ…†{9¾ìŸÖyÆsÙ½>- Ÿ²ò–)†ŽQ êg<ÉMr«,ŸÌscŽ9Q1<Ý…eshx?Ÿeþur«Hâ膹nJ†ÏA×@=Y¶;}ôŒXq7ˆ¥»³ÊYÆ?i?Á¼hJ3ó@ c±Nº+ﮄ[G=½VŒ³´€!Bƒ6ÑCû/IÙö±:ƒ [NTLÈb!ã›ò^8†®¥Ÿ÷î÷~å`½Õžlù;¯“ØóB')ÿ“†Oöè12Ý[}ïÀ§žƒåÁòÄIüís] ® Öy±4ÿÈc“IœW¶ì3ã€Ó -e-½S(M*‰~îd¶xc^È)`Ã(Ã9=ïœl8yÏ5—ñvDîÕþö÷«º®ºéƒ0ÃfäÌŒ×x×û÷šÏgÕM'UÕ ðú–ÚÏs.a4¼n^†¡]-Ô†!2¶mèÔRO =èDÆ÷æö“$ˆ+`DÝ"c"e°íŠ -8' nÒÍjçÌt±X ”-Ö-]m¢¡ƒytÜCX77*e)ýÛS Ü8G*QÜŒ=6ôÌ Í÷nL§Í@Ýr÷&êÃÎjuÞà¹|ø±‘ð~º×¤×¾ÛuË\˜2š'¹U&t$•‘Fþm.às?$¸Üëùùù“‚/'2ƒÎŒ]Ä]¹æG{M–#`uåÛ󭊱ƒygý{{{ý·OLJµ‘èðþ„e‹Í“5[¯ö‰'˜-2îÝ!º&®Œ[:ÑíCw£øw¶[»þ‚£´‚'Ûb±´ŠÝúL|,‰ ã˜mm›m‘ȰyólX˜Ì‹‡Æò͹A;xO5OÖäÐØ,‹ ŽÉnž,do$$Ȇ,âñC5„$× Ë³ür&Èn½šW–Ü+'}; UÐH¥¿ìÔÙw9òcÆk¼Æë îÒøLåœVDw=Fâ"C¤9‡8Ã(Z{p˜CÜ’Wv2?g<ŸÏë®Cžƒæzßø÷%|?4~›EmÒO$Õ©l¡`Ç‚û­"5cŸµ»6äû\èuÇÆ±a¾ß ¬ÇÞ^qi_A¢cn‰ÿ­Eöw°ï"8ݦL4ܱq|¼âwÚ?ÑBNŽk-„þŠ.Äš{•'Zóù¼‡Ò½Îž‚$1+.ÛŸÈcÇýg—ÔUbFÌXèàI2cR_Ú‚žÐz2{#pëÕ$g†,^Z`^È Ÿbñù$ÎÒ¶•/ØsëÕï÷d³Œ7!WsÈ s²Z½ÁZà­…jL©áOÞ$múÈ÷y“K×_ãÝѱÄ0Ê[l’Æsï–(6aÝmi*V7‰¶<³7©Ä˜¦þ¾‰Œ­[î><™—N—ý„h8Æ4ã5^ãõ&6itFSȤ˜„ü²]Æ;~©ª'ð)>ç’œ†˜i\˜òÉ.&lP9`®‚!8.¸™oŸ#¬Ävær>Ç•p¢`è¿ 5­üE|cŸ=£&%„ñu’i‰b3[,uáÔ>~"”`"!ð'~;ï·k¯»/_¾´n½‰Ù§Æ†NiÆÅ88+O!w-¼ÉÒÉsÛ™ïsµÅ®¿­ ÚÏ•ÿæ$Íü" w›ªªç‘ÌYL~Q¶Ü9¶5å )6ø¯ñ¯ñz“ r†©SÐ2iÛ¦‘œÁö™±c»½Tyàs( ï¼îsĈa5.6šë`ÓEw\Áï´©#¿ZAËC0ý>8G uÏ"¶½æ,-bIÝ)¿œˆ‚y+op;X§˜G1‘×]Œ4ÇÐ1.Ü ^pžß~}}=ˆNOOEôëëëªÃÁü|>¯ËËËAÇ&!V]Íb¨=z¸G#èV‘â";EpâVÆ•÷[D‚$ÑE`~ËÙÙÙ€äØÎüjKš»³ç4çáž|ÿŸ²#~„+ïîx1xèp“ggg}ÀgžGEƒA¶z”q˜–/´ Y¹[¯ÎÖŒ/—ËY?U?œµ[UÌPß-²¾3M¤©yÿÕÕÕ@î™$Åî$Î&Ésø]ºUÖ˜G^ÙËC´á¦“µ²­le.'Yl8l2V<±Ï <õzÝ·(mʼr• !î71¨-CM»þÂíb^™§bþÿgà…l1ÈrlB$yÜ»±Ä$çÖ˜÷Î1Ç> ˆoq’fžÄ~˜ŠZu5!Ò–7vÁ̱£‹‰¶`HyåL¤ªªç¥"œ‹‘Éb\ÜuãüvG†B­ƒùår9(fš¨ :y$&ÙÑ¡«ÀxZY!)Ç;‘p×ÂÅÌ„$¶($Fª¢[Å4mÀ°:â [w0'¿¹Û•JÄN²¬új {¦H– Á|¦½-«ªç–g'¯/â{Ñó¬`àÊv¶‰2`õd³´ÛsX¾4Ç©ªŽzbýÖYÚKÅïÏš³nºI­Ž[³À¯²=ÈÄÏ{·<3­U“ -sÆÃL"ïgƒ5Y…hëø|y"[ë^¨t%üÛ_Á±1ù-e+-¡Çû­æ’†RLæBp[Ù•(s¯;oð@ÇÒ_h6› ¤­Ý–6¿ÈŒUÏ{WñH0 7`óv•ÎÕË-ûðäÞÝ2ÉÒÉ;kÂòÏ&Yòúx×x×›x™˜OáÇв܋mZM0ì®ÅááaþûŒ·!§9,z ( ÿÎøùåÈB.ï·çdbÚ«Ž3ž3ß´ÚJð’†ÞV…Mh~û»¥×ñ‹ ëód]Èõû-*…u¿Å<ØV¡—ŽLò<Ò“±³Ç cãçä`Ÿ9½Rž¡p‚œ±!ß‘òÌÌKâ'bS|ÍÓ…cCQÿ¡´5á¿1¶i´J±4 Á )4$Ø’{A¾ÙóÆÞ’tŒ\dv‘úI2c¼¾[nn6›>ódr¦T¬ƒ*»·¦Ìoê]·ˆÑldžÖêf²äd$ $ ³Ö÷ÁÁAôÉ -4¾Ï†—¸ò¶$ˆyøv0µWŠ¥§½‰fVM2`"ŸÛÊt(\áßÙ–vÇÄÁ¼õó­õí…hŸ+¦¹K`tÚ{­®Ãsmkž÷bH"ð)/d愹UŒ-~ =6võMyA¾ÛвĈ&ÙŸ5ádÈa¾ž†Q–¦ÎyáDÈ´G'ZÜ;co,4DßiSË|¼Æk¼ÆëMKf²iˆ´!F®¬{/v1ÔAVBËžSFe¯æ»Ý5àßó.”RlL1€,¨ñÛQÂ9ás(ÏpÛ8Q1¡ýuÆ…FEØÞg’¶-!ÌøX¨ ø|/»BN¾w'‰LzN°ý?ÈÝ*'iŒÅŽ\¬ôn[«ïZ Ø] 'y 3mÁBQ$i–å6ÚIœýƒœ §*™¡iæylÝ­š¿\.ëäädàÃgKC}ïVæ³<³×œçs¿>hÆøîh€´V9ð)²f H‰‡31ˆ‡ÃëTŽITÜña²‚ÿ´2™£Dé¤!Á8RÁ2¼æ‰Ð™`²¹íœÐ1ã(]Y§}èÉjÅ76’¬xde”Åa1’o’Œmv\¬Üe2¾Û|ïü&‰E -ìMÒ“Ù69žóÊŠoÆE>§³îN[¹I£ç–ç”­ÓäÿðºݼI1¶Œ¸jÖsžÍÃ’ç®ö°É’ ûpå¹Ìçó'DC^g£¶~¿çÝx×x×›z‘,˜_HЖç"x~ÎJàá,±XpQ ®…+ëÜø¥ñæyБqá×ñ‰í%x¯Es° p¢ãBu;uae­Íf3à˜ç‘~iœU†ÆÛO„‰dÀªd.4sNYÑ–{EÑ–dŠ´ . ­§ÛEGaPH%¶â÷˜ÃB°ÏwW=p1’øÅqq&2 ›KCpbI Ü/óÆóÊ'qî†9öeN{l Iä³Òðûèèh€¤">â9ŸŸ÷ÏÝ"XŒ-üjâ;ṵ̂¦Ìöë4OŒþ!ÉKîVß™IFê]£õ ×ÁÐ0OÿÈëëëÁhá$ìPÒÖjeý†GYžø“IK-, »MÏy©xb@S•ÌøÙĈ"”:êü°€|ÞÅÅE¿¡‚Ï5‰Ê­Ý$ù…g ©y/l°™ˆx2{ô&ÃBv¢àV'ïeüM¢$1ÑÏζÛ&¥ë/-÷lK“„]f1ÑÒGqÏÆÄ˜¦OzìZf}}/$W{Z†˜|ÞÏ¥[´»¤<Ë/^ N"-ÍèNcºíŽ×x×x½IWWž`†G¹ûêš&&ÛŒý›3š"^(‰l0ÞßAbBŒPmu0ok ~ÅÌ9žoÃpâ›VLJ³ÍÈ£q<6¶Òhùÿæ©26œÑœá† Ù Ž ˜±5-Á±%-¨ bÎfÖöq7‹ßGÜÉX§é#Û–˜kåºÃúœÈ$4̶%îvq¿ðD(˜¾|ùr ÍØ¦E ¬-Rz:U_Ý)4å‚äDˆ+yo~ÝÞŽŽÍ_ÊNãbrîÍhžétúÄl½‡™ùC¬œÄ';2®ä;s#ë&ø5ÒOZÖÂAòùV΂À½¿¿ß“ºÍ‘ñdó ’•º"áʵƒ?ß•"j:Øö€vGEÅ„.&›ƒyžÃÿÇÞþjžæw}¿Î©sª»k9Õ=c{÷ò»~×ﺾËg1k.`íaR'ÝŽ‹:%qSš±¹ÕL«Mª¹«Z4[¯v£Zìnð–×o/ž“4ñ³óÚTsé·— z) ýꫯîùéÔº’h§oBË”¾nÝôz-q\[îm2’8åûßò¬¶xà(M­€F„ü»p‡q‡q/Ó°#P <Ù3\{ ‹HÓôÚêó,Vê5§Œnç\gt·‚õ)ƒ«?œñ¦õô›òÈ&:ä æ=§¦:gs3•E=Ƕ„˜ìné¡ó,®ç$óÏØ±kM£¢kh‹ØÚKÿرZ¦WŠBέ‰ÐìˆÈ3š_|ÔuÛòÞMÿÅÉ‘1ñ46 IDAT.6 3ùA[&¸[ mIŠu›“““½Ø°k³#4ãjuÓô’´ÈÜÜïŠt“ŒWò™Ûå0vzP§ò—™¢ð%Û—š&õƒf"Ô„—YºX[lâá¶ô°%·'/(Hå q’š&ÉRG]ˆOíÁsд*íVÞ'¡« 8iǺ.¶n{ öm+o9×Nij«SÈ`â ßzë­½‡¡ÅÚ}–ÿÓܶÙO aay-6[§j{ÔêO§]Œh‹u‹DY‚-FTéÄ-¡=ržõ «Ã®°¸ª5VÕz]^ؔն«X•oF¹Ñ´îÔÏï^M·ê¹näµÙi—}ð™9ŒÃ8Œ—²3s¼/Ÿ<‹NÓgÆ"R¨ ¥`'׳½Øbè”HZoÐjÂsHG>3Å%Bý^9Ä'''; `ºãÆ73{]øUIžò̾^1sB¤fGF±"•K fõ™^']»I`‰Lg°ãxf?§ò¼èÈ¡©ÖÍõ†ÌÊü”RÛ ÊT_0¨kAJ†«uªŒÕÜ„LÒäïˆõóAR¤^vøWuؓѵ}8¸™Lôù¾ßn˜bª²µÉõ]µÔ§knIQ‹¥û&Ѯ֥÷y VgK^µ•Ö…s+#œeß­M!71!‡mfÂî‚W)+®4c‡ˆ®¹b§§Ú]Õ˜®_5–)âàënrÞWUÅ‚†µ O#Ö4ê[ÓÞ»\e¿'ì®DÎ*¡‡çaÆaÆK™Ð ‹…Î)"r!„?5„Cô^9Æu}æûÛ‹;ç§²WÝù:3"#R-³Ðk!VeÏ©šzzzú”L®¦#½–-°×&O$Pç–1Dñ×›o¾¹ N~hž1‘¢"JãQë…Rüe1òÝwßÝóZ‘#\‘Ù$MBú7v>0 …Åñ§{O‰R±¨H£’H99Æ® cãfÍÚ™°˜©á¦ÒÕQ:f-$±ßl®„qÒ=„å)=Ýû¥PL‰ì)à ç¬HÝë™k >eRÛ‡L™[·ní]¤x|Ý[›d9.Ó¥sB|ÊÎüÑï¼óÎ^¦<ñvºÓÛq™‰‹i몚ٚuBæb™Iž:ëò@T³šS;6'''{7\x?bL…‹ 1*˜W¾Yœd‹Y/åøJ¬©L±• >+˜o±¹ØÅ9·¡$Q¥1ß_'jrl\Wqd¦Žzóè !”†RS,`VƒzÿTc)–ó2 +å¹I©Ï¯ŠšÓW+,³øÐ&iË¿ŠÆAà0ã0^ÖQ¡lžñî¥)Â\:§=z´«F¬+ØS±²ý¹½¾Ê¹4v9ü‘[¥èUÐøâ;2ÅÍ&VÆÕu-&t^þѤl„Ú˜ö[ŠpAÃü}É…ÖOÈ¡¶'v=§¢ÛãÇ÷¬>&/MÿÆgy;ÙPØó™)€Ï& fªKl7ä™ô oɺØ%þX9o±i¨)W¡×mqêZ Xûí:•¹Zˆ-;.Ââ&´MÒM³®F‹Iy ¬>ˆãý¦áe‹yÊj*~Ö$K2\„ôþmÎí Ö'~v«íÜ<(Íèbnµ˜{­¶°É‡†OA'vXh™²š¶ÛÞóꫯî™NÊ/JÚºuåºqœøY«+vKºO®±ÅV 5*3VÖ²ïëPÎù0ã0ãeMd<£Ý‹UHš94Å:",¨M®§‚<&‡Ø®~ ‘7f±±€trEõ;ÓóO¡ƒÎI äSA•Qí¨8JdzÐwQ«Zo¨¼¥ÐÓ<£'<\è|g|s#êB‹…¿cXäöŒïý!Rœ[Ì ÿÞuѽ-6’ÝZk] ½W±MžlëNùe‘Nú'ß”«›þ>+UÖ g[BRrûv…Ÿš;¹ã6ôOô™Š;%¿y>SO%3’ÕT‚èA®*pïÞ½=ìŸ0Ú¾ØÖ¨ÕeIIâ6Ã*pzzºÎÏÏ÷4â­8Ì í&Ì`]hW-03Á)¿,a½®FYd•uƒóéÐn[:B—™®Êá­ÔØ,+žÁx¯wí‹&ÏC•dþ™îq™‰¯uS³c£OL×V%Ë®…Áum톉J×ßÆÔƒ.LloÕ¨¾[n–Øâ’m}Z¼ï&yqlúí*×G¸ººÚS²éýÝ×óóó|aïq³­Ý: —-ٮ߮ýä¥U<˜Õ˜£ëƒÏÌaÆa¼œc úÞ™ì^¯êjAÔ›o¾¹wvÌÊ¹ÅÆ™Mð¯f Y±±3ÐîÇÅÅÅîŒ6‘˜2ºÓï£øàââb«›ñÉôóè,*¶ël««`0¯j™IØTt úUü`Çej¦NZ!YBz£DFÅXã…JTôJQµ,ùc¡Z¡"úþÎpiÆÎboܸ±ƒÝ5—*—/©T¢b1Ön•‚@!‘Š×´æˆÿS’Xl5“´­"õôáëÞG©h¾´Ÿ0¹ïóUë5‘é™zøðáGX%dcË`q t”ȹŸJf Æ ºz­‡A~ÀìJs™î¯¶‰ ÆãZ؆’§bÀº¥N% NB|<ŒiÕÍí»ô° 0>|¸ ‚åq´(ä$¯lÇŶµòÍôúÌH†³311 Í°;7ÉZéÓTÉÅ<ƒáºQ=HSºZ£sëâ½wïÞî!L>Ð,¿ua·ªÁÖl t¶fM"§ü`Y»šöÏ2k^'ÙÿY•ª6I[™šm­µö6A[^ü îµøXe+û µû½ggg{I§-wá ]“$Êàï¿sˆhã0ã¥[†ÝeÚ ¨ÖëÏü&V‹„Î)“>[SÈ’ )3…D)e«êXÁ|г:.³ê?92}®bCzè* •_d¡Vä´ƒ~ïäyLAŸæ¦÷è7b¡×¹™Ðy-,bOÕ±ìjx­ÓÌSxxg°bEžÑÅÆ‚óÆW3¾i>L„ºw&Åžª¢ Ï2îzÖÜf¡T2ÿ”Wnnú­­y ɧ<³IŸpÊ7n¬û÷ïïþ~òÊ„s6J”äå+±.ÚçÄn‹Kå [\m.f3ÇÚ‡vd^{íµ=ýoõ¶wzÚ[= qN”‰›Ê¬*T¹v#ñZ öå4És#PY¢Åf0?ÛÎVk”g6 ôAœÐ¶6áM䑨êáƒîÍv©Ä_×®¡’Ê“nG¨ÿ­ÿДW6ÉSS×aÛÎý›:êVºúí bHëj˜$– ë›Ü¬)¿lK½ûÞwµ®e:6½ L°U4QQŶ69‹&q=S=µŽÕÏÏgFÅaÆaÆËÖ™ÑDk{§E­Î)%’õ‰)àµ[?EiÚ‹ÛïåÉÎø¨€S.gïï7/>S&×ø¥D§3³sPeÑÉuèœò 7¶›1@¿íüü|O~YÁ!ß[¯ODŠ´±aÐ|y"^.jCå® †“çjügìØµY8 vW<6ÝçUÃëý®»~»±£¦ÖÆGÆ7rhL>úüæ^Ÿ‰H)vÜz]èØ–u‡°¼)]Ý\Ôq±£Òuõ~ÍÌß~ûí½$N5»™ükä*%CÈü4?™¾x5yâÝÄJJ²ÖV¡ 5ض£"Ï÷÷ Û50 3Ôg¦Ê»òͶÿš!FºÇû Ί„Á¾ZáÊÿÉuP•¤…¿å#Î1²ZóQ¢ÓbUë[xÔ4Ója×U˜-w?ßÅ5y&J/*`Û¹M)ŽŽ‹ÑuUǤÏjݘuízìÌj²ÝjÈO‘‡´îu×Ö¥ôt<9)š¨ÉOjî&ìNÕ+e­™ÖE›hëºÏšJ[×îë“Èçæ~‡q‡ñ2Ó“Ó½3¹Êv×T :¦Íä+œ =ëß”.èœÐëDÑerå°hÌ|¸‡Âr±ÖÚ£lu?íèLSlàì u&"r»fÞ5jGf­õG7~ôôœq·ÖÂ3{ÿ:PÂß·¥f§„‰P×ÞóºišY@ê ©»/ ïÿ,b³dÿâYÑèó»¡&:¶Z)c(‘×wOœ¤•ù*"ò{Ú„¦L®\'LxU¯›Ø„¯m1M ¾Zl3`-˜OÏ[.Fc]Ìv³¦´cD:M”¥ìÚzfët ÃY"S0~qq±ÓaoÁ«örqq±×õhÝh0U·«×ç&Ø÷·nêø´fúü)[©ˆÄìvõ~7pͶLt\A [³UÒú>Ūö4·&°}ß³Ètn$ŽmÂmXS2}:çîLb!ÍaÆa¼¤c‹‹14ã{ë­·vrÁºÆÐ<؃ÆÏbçTïÌSLûˆþvšf[™WB¸³HãçÎ@ã› vý½•q+뻋¥JŠ!B˜~#Ê+[IðàÁîZBÔH"WF7 ÿ^ãgÅBO4·Â¸™ ZWì×g›`v¦*T`¢aWÁ3·$°®Ls—HÃýû÷÷ëâÍØ;Ÿ…õÙU鵊¥Žîm1‡´‰_UìGÝïI•uò§ÝZC³“W\ªƒþ‡æ ÍeÅ­5ìô=|øp·æfÎ!Åu#t­œc×™)èkáèÀ>ñüâ§§E0±~§zPuùœRå•èÓp©`]M¨²…ªd.f­¬ÏMf’º§¡“¤$_Ÿ:éÓCgJìµéÕv–ãb‹mBËÜäRý0i²Ú³ÖÚ%Av“Z˜‰Œ„õ6Iƒg¯mBmýšàJ°o1ÛZunõ±ªDIÜ”õvnìV9wݧæ^ò™Åiôµ%Ë=[«=èÝ[«taH{¯›ŒÀ|fâõ|ª¯ÑÏJ×ãÇ÷Š ‡q‡q/ëj› Oç¤ððΉǡ*¦ß™îò:Vü3Ïðâmâyôº0ááMu-:+:ÃKNª¼‹Úèý¹ÇïšVÄWvþ·â›IHŸ\Îâ-áãv\ ˜_yå•§|ò¦×[±ðZkÌsNyf¡ióTÌ-FÅâÜöùÍm ¨"­‹~o]æZ~P±ÅÊàQ½Ç¸Ö3Ü"öŒ_&ȹi]m%ÐÅŽsÝMH¡ñ i&2[Šk XØÝš¼|!ƒ d˜´¦}fÊIžé3S`m¢¡ßÇlõƒ:a.êm1*èš§K•Œ-¬•N1¢Œf†V$”6ØO^ÙÖ¯Y¸™§„-ÛÎfñº¯ªX2¡_Í·<47É-ô- éÅÅÅîÚ¦{½íC•:qý›²•]»rÈ.ö‚õ¥yí&¸v|l¹{í-vƒýôø7*œiÖo·ºñÎ;ïìæ¦5©Fý–ü`Ÿ?¨ßuqq±s<¶šÒC©‰Z£jŽïU8»aóð«µÜ3'þvëé³÷6ÁÓ›ÓÌÃ8ŒÃxi™i˜i:¡a³k *BQ›âŸ ^íųã¢àð)áã’ùõ’3ØV}SˆŽbG[\ÏIX7¸‘Ò0þšÊ^[´+ãÓï,˜³†àr\´X˜ühã9&Š*ÈŸžÐø®­$q*¾™$v­ò§§)öåååžD±Ê]*ÖO(--?¼Q\Ý\«ÊZ\Ѻ1AÞ²‘ÿS’bÄu1;u¹CY• mW xBï§™ºqµÝ0ï]ñ—H£ûõLÿhtZñ@šÃ^2Ó›l?†ƒt1JüÙ’bóAî¦ ñ©bQ‹KžG‰Ž™Û|­|kzÔb5SÃ91¢ó’°k 7árZÍ‹•õ-¬Ÿ„woXÞJ¨b¢*šCd~;>>¨Ó¬$lª†5ŸÒKT Ö ÆÅ˜Îj÷9Ls÷ðáÃ=¸ÖäàÈšªe)¶™ÔºI¬«ú!Ïj‰BólÛÜ(#©P›˜‡™Ý*ÕæªþÙI ’h«WÈ¢ÒÕóýÝëÚÊšqMEqÝòÊÞïå!¢9ŒÃ8Œ—rteaPñÌ¢Ó$û§@Ù9U2²• ˆ,0ˆ´ë¡àO½â„ŽuÎmùäùº×Öl0/—¡sJ/»[dc„ÉQ~øðá^À¼J¬ŸW!·øÅø¨øÇ³ˆ‘ÎÀÎ5Q;?5ü ·Îx‹ÅÊÎøÎÎé%§Únÿ–üi¡cÅ/ýÍÙÙÙ^ò!‡Xžk1‡~TK€å?£µ[7¾ß8¶kW~Ùg ûÚßH ˆ_Ýÿž²ßk}È=onm0wOĉߧ*ZÏ\¿¿DG•Ù§’ƒªnÐýû÷Ÿ’‚UùB?-uª)±§3m‹uJM‘7D‰½Ijž U%Yš yýaÏ (56 :æÜݹsg¯e7³vå{ÝD,~Q£ÖkßÕç?‹ohVlU_žGI\÷ÎûV’gµ¥­ÄN#Ô6’pB%–ÀÆ¡Ñ?¨$o:Ûª¼¡´cÈéééSmg‰rµFû®~Û¼vÍ=g%Ì$±DB ó ËóÚZW&u>sÓÛÉj„ž°»ìà­™ó'W‡ˆæ0ã0^ê„F‰ÇÆVÒ º 8…ÁX$›ÅLyº+ëöh ]²cü2áQ¢" æ+ôöÛ·ïË´ò4æ9c𯱴«òÎÆ'Šý”޶Xò 8óÉ“'OAï…hk‘pqq±C¬xo,äfÖÙm°\°-\¡ý‰ºž’<ùÍ&:­+96źÏ*Fvm3ö ñÒ}÷õ ‹¶W7Kè}Ÿí@X^¯Ë±õ¾ÎDh*ÂY¨•¿c‘Ü$M)ì Mó™› xïWôÂ÷ïùÌL‰½Éó0ëÇX"ÓEHöoBåÐLø•Ð4¹½¿Å:!Bv|ü­µ^mÝN‰¾þÖ mq›htír3ìj¸íZ4O›Â9*tàƒj¢%lMN8GÛÆÂöäõº­]åmÝöù*_Øþ³¢¡,÷l+O >•~Ë\W]{›rß_RÓ¿åêÛ&e·kŠ@´nÄ.›¨L“×Ö]‡Š-ÿ®ÍaÇeÊ3Û²Ÿ²Ý=ès“›üÔoÝMÙîþ-îÍÑdv‡q/é( 6h¯NJD‰çðòÎEEeÚ‹Cm‘ž·Þ?Πó[ óóó½DBå×yʶc3¹žÊèvÎÍØ­×¶Ô5-Ê1öÓëmJoñ‹,䊺+ÇEE7㟊3‰³sQüäû7ªl’噾*A50þ1q’p/·ªûÚç—XÍDEè™qµbG[ÒÖò£MM¦§š^‰È„å©(gGGyeçn>SOu)åÐè!(GX…œžêÌØn´ò.4Ì€ujjÌ#ÆTxT-²é#cëöY‰J“&?gê¤O¿²nß”ûKPŸ³ê6Ð^÷·GfSΰMj+hnú¼ =“Ò¿Õv¶Ú㦭‘Øéé鞌Eóçûk;+T ZËùùùî¡J‘Lþ‘í~ l‰‹=B &yk­=1€7nì4æÛX¬ÒÕòwS”ƒ£,¥ÒÔ["­Ûiˆ)‘pú Õ±9H3ÆaÆËÚ™i/~ôèÑ‘[<1Bç·\ÎöââŸöãŠZu5:ã+Žt÷ÈóâÓ‡š0vR,¡]¯8Âέ«««Ý-ÂD¥3¾?zz;‡åk^ân·Ke/“‹’ÉàSz𜞞îZN3ôÙU(þé¿UËŠlÁÅCk­½¹)¶ë^û©rV `‚+CŠh®{BïK :¦"›Ð{):-àOééÐ:­i\ï«Eðb‹’ÌæÅB¯ñ¢Z÷îÝÛ#ûÏÏ-ecvú¼—RJäõ›6“™)1,ŽÒ íG*0½PfÉŪŽz¢2W!¡eº×ûÝmu‹fÇDŸ˜’2K[\v›äÙ­’ø'×Áöà”7ìÚ•wn1—X©x2ÛÚ³Egµ§M«\÷JHº¼ Éd%2¶V%d¹»þtÐU-³úeEen$vdn‚º —ˆLH£›\F&ÐS¾0‘‰à’‚æmVºNNNvkMØ[º~@n}†Ð/uÐíVùLØÒßrÆõðöwrr²§z6«A¬´ÆaÆa¼ŒÉLÉ‚á¼à&ÏCU3«áòT 8;KT˜™ ×C˜Œ\…­bgŵÖ‚Ëâ§®­b¡5±UˆµÐ[V‘Üø'îxÿ&<«Z¡hš’@Ŧ=EEîã;6ýv‹¢uZ7vDì2?+µ®6P®Ž´ »K”DëØ¥´›å½±Ãcüb‘Ûgî)Ÿ[`Uâ쪻Üœ´þ^ÍçIJêýn =ÈS~Њ…<“nˆíÅé._û±®„‹SUå »¯m&JsÓÐIéi“@'Æd!Ç”fT¦.œc¿ej…Ë)Øn1*mݛθz´«™‹eJ_Oe®-‰=ý‰z}ËŸÈ`¾Ïz÷Ýw÷61ÛÊš…nqhª(cSÓ¤µVë¶ûh§®uáa×Ü »ëu5Þ›oÛÆVsLRÛÚäº×m]»k¾¶sÏ”p‡Y½8ŒÃ8ŒÃx©ÆõûFenƒÎ[“ã"fú™µW[ˆµØØYê9¼ª³"žGÿ-ü)ø”g¼bAŒfå½Ï*>òu çë9+&´¥¾)Dë ÉÆŽÆOSÅÓ½~+>²%Æ3¾ëõõ iÓ+NºB Æn~¾ñ±Ý#šü æ¦Ø+ÔHs198rˆMTL⌯´Ÿ0n–?=í+ŒŸ2 o®KÏÏÏ×Í›7÷ g^{ׯhEìâØ¹.êb–LÊ…j¿ñ£Ê)DÛX$ßëÌxm‘M<¾ÄäÙ¬²ne_Òö$»µX„Ž=S}JÏqež=ˆ©'LCÌÞoÅA¯•iúØâ›•÷n˜Á¸ê ݰ>_Â{-gU¼æÜ¹IvÃTñ²µ*~ÖÖ¨†‰Ê–²„ZÞ¾¿Äbš…Vm1É4K¯ÚÒüiæÃÐ|ÎØWùæÎ×g"3±Ã½n§¯¹S–²ß­¬e×ÿúë¯ïÁø>—¼³ë²µ©tµ‡§"Ê+?yòd•S±Mÿ!…TúKò³®ä+7_9HÆaÆK9Î/Î׫•f1´êqÞðœ*è梼rçÞ¯OÞ4ìVŒ¨sÆ€0Žo‰ÈT•b@iW@ë !B vÓ4{KâØ€V¬güäÛm2éÑ´qòŸ-B›$ÊqQbxúìÿåJH¡ø)XÝôÙSÈ1•½z]CMUÖ*b—$Vh ES"S\-¡=~Qñb ›ëªø§ß—äx1„IœÒÒÝw¯íæÍ›»u‡Gië™Ä9w³£c¯á¥É}>2ýþâ›-¢:2B7“%‚M6l¡ùzò7vêIÁ§ ºÅóõ7MZ ©>%‡ffÝV²§tbÁ´ÒŠ]—ÒÒ“2oèä*˜ÙÚ²“ôÝdf¦=ÌuƒÌL%|¹˜û|»[†Q]ÛTæêóÂxöÛ·!…ÔaŸ²ÝÊö>ÈÓrÊv·X;Hz©`f? IDAT‚މ35ÁnnÚ$|­éælEÃêLªj0}ïZïÃêZÓú5š[d7x×MØå)mÝûƒž t“ëu7õ×^{mÏ|¬àÉ“'ï¼ë p‡q/ç0à™ÅL!Î":ë|=>¤Þ/Âp„W´’wÑ9ÕÙ3 vòd vå먼YeR!ÌS&FÆGò8&´¾ï›;r'„h:ÀËå Z6ùÓ&B¢qªì[¬ ^eì¥jë–L×2×´PÐzù›Ê£zøÌ¹³#szzºŸÒç¯ó^XžŠqÅ3Í_×.­  B¯1úC­c¡wz+õÆ–Í éÑ3¹ë<ØñÎäg»n|¦„¶®-‚7× ˜ …{ÉŒò‚Úí$4¡.¨‚²k7!<£®Ãìø´¸m¡…å3ûÚ’ö†¨|Uæhðn°/ǦÅ;M!%«uÃMdôØéý¹lÿM3­ÚÎ’Ù&R ú³d7“6µÂ§„žÐ.¥¥»%ÓìJ~P›Øl;Ïn”›¬’}vê¦>¿øYå›»—3ÉÛ·.æÜ•èx(P¢°%ÛÝüJr”¬oËÞ¸M²ßîÜÍ*ßéééSÓi¦åû=...vJƒÊz@´Áž?>øÌÆaÆË9ŽöáU“§2©ðòVã›-ë„m™BZpêë,º/*£ÏY0!Ö¼Š×¦Þ„Gé#c»³+DŠ~Bõ-rwÎy†ÿ\\\ìÅnòæ.òÀ¤KŸ½ ìyñ]·s'´½y5þ™´¯ÝÄGžF…`;Hþ¤l·BOò§]Û _:ßµÅ6¾±c£ý„Ý0 µÝ³bKR:êRN “™ükÞº0>š¼2sŽ’¼™€7fü¤=Å.™1£ŒüüÎ;ïìZTSoÛÌ0LÁ¸UÉ&)IeŠZ«VæmQuÃú­Úk½Î®Ñn¨]3Ï:>ºÇ:¡[ªdâ•È3ŸøÙ“““=üª²ÁôÔ ×GÆùââbOËŽÌ?¨`ûY°;³î™HèÁc§ÍjO›˜f£¶n{=HԔ힆PrdfÛ·$ðsÉzO#1¥¥U5³c3[êÂ<œ„#H’œš¿·DÊDÈ÷+O¨šKØá$E奙ÀÎä«U~‡q‡ñR£¡@"J”õ-XV4¦ÓøC.CÁi‰Œûü,–ˆtNߘ¨XŒ,èŒï,˜ª«³+Ñ9VPÙë&ŠM‹Eg&¬NãõÖ©{‹ ѵLlw†7×JOûÛ…o›PN/”øEÏŠÏœ;c‹Ü~ž^ÍÒõÁë³E”è8½â”.‰›"Xàm&؉“ã+?Hè™jÀuåMZCëbÅ›@—„´®§ýDkzBËôѳӶ%äÔºÑÛi®›ž)㱃­‚õ²öþM)4ñþ%:eG&YNSFT™a7X‡õôÚimB³m¬‘áÇw‹K‰<D pUR¾P­q;.œûf¦}ÖìH¸*IS•¤$¯µÍŽˆY²²‹²Ø³³³½DGxU‰R‹iê°›Ë?r±NþÐìfMCÌ6yÕì”ô¶›Öƒ>U9º^uÖûm³“f%ÊjK °Æ­›ÖF²–}ŸÆ©v7I’ꨛ€÷Ù­[åUÃSÒÓnSÏ‘I`÷ZIóß6ÆÇ¤™ã0ã¥BÛ; ¤DMHö×x¸`Þ‚\E]}øÚ‹U-àš•s-¦!x#±[ñÉTuí, ZVLrvv¶gO!ÏDÕ³®·ÏWJUV+çÅ8S´f&:ñ"ê˜4WuläÉ6 ÆUÏ;Ó'ïÑ£GOùä+Þ¿wÝBË„¦9ì6iKÒ9¾Åc56¬ð¨¢[÷mÆ7qËí¨xí“?d‚jì¨eŠ£DÅn”Ÿ¿ºÑºéùi]-sdOQÇGÛã›bs…¢äå ×왲[Ô{ŸJfìZ˜MÚ‚SK|zbôº™­z‹yÊ7Û^ÜÊ,ugÕKefÍ-æ[`¶­`xÃgE¢ª€ä¼ ! ?ë‚éûõØi“›Æ‡ÞÐ)O†´ï3‰›„-Ä®ïîÝ»O !Tk¿ö¡Ý-³ê’¼¹ v­>¨® [æ=è%q­‹i÷ƹSÚQH`Õ¢6F 5M€5yµº“HDcr¯„67VkÚD«š<|øpO}ïììl×=3ÉëÀ,Ÿmk1¬“DÙÆXñ`&2 ì’N³ÐÃ8ŒÃ8Œ—ª1 æwÞÙ †’_VÝsJákŒ(ñyJŪŒZÀª@ç ÅÌ ½Wfw’ñ-&VŒÔÛÄ3ØD¥Ïð^Àk¼i¼k÷õ‹‹‹õöÛoïsò‡*Ø/(³[ÐùÎ;ïìÔ¼,ØI+c+O$Ÿ=“8‹Ö¢*:Cƒb÷Ý%Cû]3‰Tºº÷Ÿ4?R¨²–†˜*â¿t†× rX]ü£âZ…Ðá&Z§ua\‹R¡j™ „Öá–ÿ’çWWWëÁƒ{Æ?ª¾v 6(*tÏØÏÃ^2SÀ¨1ê—aúÀL—Nù=ˆÊÄIøR‚o«òÞ UI«ŽÎlÝÚ¢ë³zПŅÐCü¬ÝªÉuèayT¡i“T…Ç$o«Z#4͹¾¤4´»I-Fs‰ÐÔ˜cÚÃ1}h¶”)ÄOSÇyôùÁk/Nè™6iÕQ·Û¥j˜‡M²›XóÖÜ;T)RŽYŶ I ãéáV'®×%No¦6¹ 笲çºÝR„SIð0ã0ãeÊðÚ ÈT{ëœÑ﬽tœJw†»——ÈtNÉõœ¢YÌœhQ B˜Œ¯LÜ*&öß îqUa¡w ú„êÐyr@%U'Ó£°øG®§Ð}ϱâ#… „`w_ j… ΠDI¾PÁxóc|£WÜ ö‹YfÜ+/>7ªkFZÜù«IšO¬é#Óº)ö3‘š–.Ò ´5Ùó™iÁø «ƒ>´¹ØÂ1:a’Ž”à+slÁõ Y©'yrr²×>4 ´…%6Ï®@]‰Y‘è†(`¢Ôƒ(¤ ôæÍ›{×cµÆ€Õ¬¹Ï7  8qbH›û gFIÖW9bëó›»þ6e‹ù Š)8ȉ-n£H½¢`{šºM`ÝàKTÚ¸&lNØØ`=zLp§ì¥²×ݪÉpb­æX ³%ÔaË'¦aKÞâA˜é¡#Bì¯UÀ’\[±‡q‡q/Ûè™ëzÁs/×ìüü|wNt¦”ðéu¢»6ÓÆ7íåžñ°´Ÿ˜\‡ =k#¬°Î€ÔDÇsÌbãZkÏв€´k«ªiõk¯½¶^yå•]¼)üi+þ1Xkí¹Ï× +ö¼ººZ÷îÝÛ;£ëFõ™Æ?ÂîŠw´¯PµlúÈôyš•Fö–ç9­*«Ê¥&aB¿äW'¤09Äñ‡¶â›yßU%› €âöîcÐ2Ñ8®‹~Ÿ±cеÐ"SC1‘VÅ~³8`’¨ÈU×n½ÖZÇ[µ­Ê|ˈUg(ë3•%$óÏÌQœdãì ÔÂò¿#Ãu«Ú„Ùþ+Ø·=UÀk@ºÐö÷A߬xôþª9 Í´J’¶T9š‹¾ZâÁŸüm‘Ýú~çæèèh=xðà)h˜sýàÁƒ½Ê•¿½Ävb›¨Ávj NiÁˆbD[«Í«Á¼j-¹˜íÔmê·‡¼¼¼ÜKûL…¦G­×YéjÌ(Œh›|ÕžæKo&]‰ëØL%¡zìtxzím"Ó£§¹¸}ûöÁgæ0ã0^Ê!ĹýÔÊ»ðïinÜ^-"¥bbç`û±bEù3o¯ÖFÀ€²ø¢{ôèÑ^"<\ n&:sÆKrd®®®v…ââ¾_Pv}=^.mÀŽJÿ»ø¦3¸Ø¯F3щHþÝï™ü£®ÍøEˆá,äÎ3ÚDFñœYW®Ï Ó½xòäÉžCÓûµÞ0‘éZKåVÍÖBìô/R$KZB÷J4ΉHHaË£gš­õ¼ôûÌŒ-§B…^'ºv;}vê{µÿ̶ÂÖêšî®A„¬.Û>ŒÄSGC ½gy‰tSì*”ÙÌÛ5hÅ6á’ž XU§²kÑ$Mí?ó”_VBOùåtRmívi6ªNûÖbŸjkÕÖ©‹µ€þáÇ{œš §úí“ wïÞ½§pŽnºn’Ó1¹]éF=z:@Ú´õ'j“ ´-p!{A¿äVi¬cÔƒTÀ¯«®’œ­Mñ­bHMRUÇ«%?5ðãø„=6öÚ·ÌHíÈ(oX¥K³ª‹æf=9øÌÆaÆË9,R¥òØYW@j¢½XޤqÏšöâØ*óî;Çz¿½)¿2@Ò¸Ö*T#l#‹i&êbŠÖÄaÑ'FX²ÒÕZwLŽŒg¼Šš½^ì–hÊ_Æ~Âǧ¡ð¢iO!l®áoï n®äØØ 3Áµ[lèëN±‹ØZwŸ¶W°.šGDKqs1p ²H§ºE­Ëâê~«‰F…Z¯Ýyš¡·®ŒoìrêÍ´µî¤|/Mû ååO—À6·B÷’!FM˜x}¥ÒNNNö\Æ• VIx‹ÁºòƒMbÕg%òJ ú N®ƒî±.ÆnÈô "$´L–d:±¶S¦wê¤O÷¼TZL%*[:ê*¢õßâc[¬v-¦!eŠíG[âúÄè•Ò&.¾u.&98{îô*ž¨h¢rÌlN²¿d·î»Òv³&÷êôôt×­Rõ£k³Ô&ØÜ‰ñl m©¢Ùvî„+ô Š!ÃZbå&&ôLØÝT[<? ¦ÍýÑÑÑzòø ev‡q/ç#H²ý+ÒÓ¢DýXÌthŸîöC³{nǨ½Ü®ÀØ’wÚ¯áx¯¿?ÙQ‘§a¥~Z(ÌØÐ3^ b»Yv D¤üµÖÚ· 3å?«>79Àúèmùä=ËÂa+¶““ô´s_lWâU·J{Š©v纒X¢ñ¹ä“«åGO{ ãr ³"J¦LErÿÛ˜¾¹‘Ž2Ñ8Ó~BÅÛ’& „«³9"¤QºÊ¦ÏL#hÎá«ÅøøñãÝ ‚’™æZTB¿$Ó©gÝëM~2oBÁ¦ níǯ®½-áYÓÊ/o¬-æ~‹f¡½®Þõ”àkîZ œm’º¹ë.¯Nzß-™mò4ê&•5 ¿’È8çÆ¹Ÿü¡-­ðIx·ã>v.vÅÏÊe*Ië·m­‰€B S\ëóæºk£°uªs­Î³%BËêRê±£·€åMd4ì4I³šcÛºûèágµÆ¨MNÙÊžãÙŽý<•GQÕaÆo á…êÌ0V„+i±«b¢Ó97½àäÀØQq/.ï»å¹Î€rKuuBǽ™^p}¾•¼Xâ2LõÌ nšW¬ì,ÕÍÝ$M~µEî­`ÜØ±ÎB‰„ü %ˆóÑëÌ;99ÙÁ^›08áQÁ»››ì'æµw-ñƒŒìÄY(6¨¨+G¸3^SJ××ÞX]÷Q}ÿ®ÝÖi­×æ^!;}]¯ÕšwÞyg=~üx¯ò'ÉÒDÆn”ëFÅ’-%›ÏkèquµŽÞ}w­wß]ë }‡ñâŽããµnÝZׯ¾úþÿ~†ÁxÉH…¤Î ö³(õꫯî*ƈ:“ížO¦Î±:=}÷T-Ø+Ø·˜Y ÐYpÿþý=^²‰ÐÉÉÉŽÛ¸{÷î^AËBkñ™‰Ïä:lq9E(d@Z7¨×{oçX±—ñEÅÊ~ݤ£åJܹsg¶ü[²÷U½þ¦¹ÑƒÇøG¬ðp!ƒñg™FNe»%ÃO3u½äLP'·{­67®³ 7}½5íº‘’!¤0X…`óiÊ' ™´°sÁ§ˆÖTì™Ú|Îýä*çJÍÊéA×4Òê²ÙÙT`šbÊÌÍŽËVæÙ÷ÎD§ŽŠBâ'‡e CúÖ[oínæ$ª%^k¶ÅV%¿d`Ëg& íìèØ5(X׌JbßムþÕ`|n=¨’ÙäïԕЋ¥ï3 L颠؎²–UsLT&ìOgZ»b,K%Yv½UKú{e-«h˜È ëu7 á———;ÉràÔ^Ÿª[ÒŒ[Š'%ÿv9 pÝvíu|: &ÁTYï'Ož¬ë«ëÏ«ÀÑ[o­ÿ쟭Ÿþô:œô0ã0^°†Ì믯˯ùšuù•_¹®!L?ÿ¤¹Æ ™n©šPë(/B1$Õ§„Ÿ -ë³²-¤s¨³C.C…àº'ž¡B˜?Ì9w•óâ¹8Àr„$Up³Uü¤LçØ4B$loòHzÝBmŸï9¢Å`]TGß«²V¿Wè»<ÚÎ}¯ÝØNÀéu"N²¿ïŸ¦Ý©ºÖ•í#j£n’” 9ÂÍýD‰8iÝ(«m@žºa®SýŸ%ë­ á::r£¶NB ŠE¡LÈb÷VÞÐ.™Q ­ÃDdÞð-%±~¶¸z¿ÄN ä½O x”„÷`6MÀ$Ã)/è„Ø"s#ðÚ»Év=&¼j¼á ·ZhbL›áO[Ý.MäÐÌ`~Šhe°.90&ÓC§u!H^}÷Ý¸ÚØ¯¹ü"ã£yßO|ػȪÝ|«.)»m@Ú⟄®³³³=·ù&t‹ÐôL…¦ä·tÖgå¼ ±¬²Öµº˜m +dÐõUMB4Õ£&¡Ë9ˆ hò‡ÜZªŠ¬[ѰµÚ‚0qyøðá^@4LþOsSg@Å7M#åÕn¯"²…“ŒŒÖµ¸É4ïfÝëÂòJ^’¥ìß‚$6w®‹©!~~¾k[÷°˜Èô~Ç„ÕM zÉr]{´f¡SÒ|’Ù¶°ÅSä¡ ²o‹éš6Iü¼ûÌœŸ¯ã_ø…uùÝß½.>ö±õ3?÷3ë—~ù—ÖÕõrv‡ñ¼ãã“õE_ð…ëÿÄ:ùÉŸ\§?øƒk¿8 ‰u¸…åtÎu>MTG1BI{qбöÚ‚í ›Ûíå[^pœr„GÄöýÅrŠ„†MuñQçC¤AÏY+ï*ÖNA¯·9,˜6 œ‰ŽŠ´JW -³J?M±-b÷Û§„°îðûŠ\õ›ì˜ìwn7·ò`MP_Ldºorl¦HÖ4µ.þQ5ÕB¹¸¼¼\ggg»ëÎ'ƘàììlïÚU|“»5E¸Z‡Åž®{cÙîm($㣺IJuG7q]ô{…kÎg¦œ¡bï^gÆ Nb¸ fe¶ 5ÕŸòÓ[η¾$»éC#Gƶq‹Ý.GÉ„Õë:Ó¸§®ƒ%ezu n±Z9·š³µØß~ûí§ºYmÚmRºZ>PЯ’©û÷ï?%¡g`[{°k+É4ضËaû±¶¹Âsî’ón1Ì[‰²Ó×õ)"!~ÖM²‡®kk.äÈl½ÿøøxÝ¿|ÿúë¯ï8¾­µÇ½êÞù}[j1S^yÂfÛZõ-ŽL×R۹öu×;¹Uwnßùü÷@®¯×ñÑÑú™ŸýÌzxÿþúÒ/øøºñ‚`îã0^æqyuµ~éWþåZ××ë+^@! ©r5änóí¯ªGÅuú¥è^)ôª¼k/Ñ™üèÑ£=IâŠRÚCx¦Þ½{wwN¶÷w†Ïs¬Ï Z¦8A¢9ý÷¼ö‰Ê0~ B4+ëÅGÍMç´ÅÌ‚y-‚¾÷7%*&i%P7nÜØ+VvFo%y}†±aÅL¥©;ãƒooY4˜<„æQ-O!…b»ºi™­kÆÞ¹n’hÜl§oŠDl]{#!©îñËÉÉÉí@-ßo^¡Wе(Å/Æ¡†Oéë:*ù5wÍE…ÞÖ­ˆ¯y¯33½R¦›?ªìjJµIF¾Š†åmN宂} -m*¬©£7Ä,Þd` ^eû1œ£‰Z¯rlLB0`_%éGƒY7%ƒ}¯ÍÅ>¥»¯màS¹Ë¹D#±þ¶kSõ£M´EÕº©k ^ëBe.±É¶…$ª¦R‹¼ueÂ*!^ÇbÙš7€>¯$®µµµÉµmOU?$œJæ—d麚òƒÓ›À*ØìfÙ ´ÒÕ&yyñîsT¯_øÅ_X¿ï«~ïº3º`‡q‡ñüŽÛgw×?þþÉú_ðñò÷[=6æ4ÅŽ*VcLu«‚®Î¦P#ŠÞM+hÓo£ädÚKt÷or:Ã;ʦ_Ú,Oްœb»Ù‘1 lž¦—œ %qáñƒƒ–¥NeW¢D§¹)v´@®PÔÛo¿½Wì¬XØü×µè÷ZÈ5®íó,6vï,ÜN»B S™kÆ~zEUHx7X?==݉!)‚eR¥GaŸ-¢¥uUlZ\UØF„³kL¯ÿጧôuÒÕŠ7M וqu±aÏd±” ý‡ºw{ÉÌ$&‹÷WÓYÕÚ H· >“Cã„wsïÝ»÷”³­•ó*}žª’–ì¨LcžIv³]i×# áùCbù4&4ØöuΉõ ™2WskGf*šôû\\bLmN ãÄ4U¥H"`›œIÞ4û,KW^yB5í¡L‘¤jIò„Óìsb“mÝÚ¶¶Ê–V¹ˆ* ­]e¹§¢›ü#1¤n’>ˆSCÞµn’eØaqÑB•ä´ Úº5AÝ’õn¾|NŠ££µ.¯.×Ùݳu|²_U9ŒÃ8Œ_{`þ›=ÎÎî­Ë«Ëv΄ÎWTòœQ=J?‘Éñµàfá³½Ú3ÔàõÞ½{{2ã'Ïà µj–ÈtæÚM’Oi±QžH¯{öX¬ =¹ B²-RKê®c1Ï©™ µzKÂäy¬Ï$Lhš=x4B5X/ë™™„óÎèæµÅBªÁôŒo‚ŽYD/>:??_·oßÞS³3..>)&•#ã}•;åë[ñ‘Ðû÷Þ{oשÓÐrr«LlôÐÑÑ"·Eêé18awš¡·îŒ‹+²S§Þ|}ÆÕ{>3eH³ujV®ŽºXµ 3$•¹ÂhZattuuµÎÎÎö]©np[7(œŸIzêóûþM‹½°¶³^.-d5èÛdÎÏÏwsÑÜt籡„r%€Û¸Â9JHÞdÛ¹Ö¨°½×_}Ou,Œ¨‰ŒCu1¦[øß‰M•cj‰·´X»mnênàq`ÚPgkµ ^E“ºYÊöž®­ ]nVƒÚÎÝ+¡µžVt«õÚßLùe+"’,Å‘š¨¸‘LIsÛùòÖ\ÓBKdÚTÎÎÎvœëçÄâúƒ¹8}åæ|à0ã0žßqtt´nbŽ÷"&2ÓaÝ`9TÆ„ÖO.§Ê¡*)UÌT9T‹†×_}·o—èLÓF÷ú‚y+çýoÕ©,Ôv?õ÷A¬í¨Ÿ #×SÒxªd³ÓKN?4}ôôzÓ}^õMy ëv ŠÝ:;§‡àT|+¶¬¸\ `lª˜ˆ”IKèúû~¥¹+ÐnyìLAžîS÷½ûPÛØQpIb1ЮÉ#Yk_èéúúz½ñÆ›üjÝäÔNDKŸßýR±¶ØÐä"%d`;…Bç‹­[Ó dLþÎä™à+Ÿô›1ÎÖ«Ê\ºŒ«y®;½•ûn¶ªbMª92m6ggg{‹Ù «×lwãÆ]W£Å„ÈdÁ‡ÃMLùC+ïš.M³PÛ„?©ZVVÛƒ$¾v¶&uW5ØîAô¾M"`8É~:êmbVòK"ÛümÍ–úpª\Qk¶{m×–¼®¾S>Yùf×EEDø*aâaçƒhÇ¥MÐu&ä°d@ˆc¯Û–¶²f"ÒçºQúzBÏ< RÓS–²¶|×¢¤yI”úúÏ2õ€¹~΂‹ç!™9t†ÝŠ5¹ø|<³/ê°ê_ R‘Ñî|{±ö!3¬Ìkʨ„±ñMÉBÓ~Bxwóë.„Ù3Ú÷ß¹sg¯@hAO²¿ÝʺÐ4e|ÙQ™4¼‰—È‹àÍÁºçTI ëJx’ð§Ö_±Ðø¾ËØL¯ƒûàå½?䂉É]øEñ_f Ð-mÁ ¹?[ « IDAT76Üò'R¤j E•PjöiÜë0I3¾™¯oqËw±£1†¼‘NS¾Y~wkfR.&\SÃðnÍMsgb|2 ñüAŒÄû›ÈÔê¢Ê<›ôô²/]Êk#yMèX7tfí=PËM¸‹>_Å’‚ÀÚƒø?“Ë`kVx•]‰cŸŸ˜€\‚U«üJ;Êj.¬úÛ^ÔX± u›J„ä)Ä tLžII©mã-HbªÀL½ïu%f‚Ü|¨–§4õ”µTñÄn”s' ÒuádµG¡‚æNU“““Ý&(ÆÔuc"2«|òÒ4„š]PÕdzæ< Ä*˽u@\]>?]£u´'~‡qHLŸÿÄíèèh½àRêÅ7íßÅî¥ÂÃU¨,þøÕÎA‹¸žýoUËŒoŒ_ ÛËõNQjB¤ HK4DeÔUÑ'Æ€tZoè·ÿtÆ«hë-‡FBÒÿLø”ðpM‹=§¼ò„žõÙÆvÝ “Õì+2~™>4³›5=t„ž?57ÓÂÁ„ѹ©PªP‚Ü+׉Î\WúèYÄÖÏØPí'Š_Š¥¼öÏ¥ÚºW Yœñ“ÏŒ¾¸åo÷’™&ôYÄy$v TPÒDù@ØÝŒãy4aýz½œ8Ë6¸2DzêÔµØÅxÎjJ7Dyb'¼W›‚¤¤)£ëƒÜo‘ì6ƒí“““õèÑ£½Š…\ˆÚÆ’×z}Ê+w?„½õþ¹ )d ÐÂôJé¾k”*NÑDÄÖ¨ ®ð¨Zö¶'Ïà \|mïŸ] ۓΰ½®¯jÎüü®ÉD¦MÒJ–ÒŠªµÔÍŠìoÛÙn”B ʶf§ÇŽ’årlúmn¨® e-Ÿ7 䣃¿ÌaÆ •¸½èϬêšÃB”Ü‹´‡°êoüi[¥ÐyŽ™ÈÌÊ{ ˆ“´mGÆa¬S `rû[¡eÓÏDÆ®ƒ•ó ±“ðÞïɤâß<Ç”_®µeúh:;2ÏŠ çûKD |§iõ4uq"ÏChûì¸ØUÐCǸ¸û:i Ó±®Ãééé­@È¡„Š:ÔQ™‰Nó%|+j€ÅE‘Ùi,QñÞ8wSéO;.ÓCP³sQSÉ/k+¢pÓ‘؃™™\(#W°û,ÃË´•hôŵ>»È&Ôö•seÞtŸ7`uq M+¨óá™S!>µGMâ\Ìv£¦;«]…™U«z!i[þÎõõõÞµ÷ ¥l1µÂÅaª“ÞgåÅâÜ -kAÍÅXµ¡‡m*¢•«Zä}oh¦U<‰~u¦Ú¤ìè¸w_û¬ø0Vªô™‘L—êFs¥ª"³bÑgØ–nÝz@´‰µÖ;`wVù¦â[‡g¿5ìoŸ¥w€¸mÛÆFù =WÕëuðÉ<ŒC—æ…Ø·“¥œñ$uë°OB®Bg¤‰Œ½”µ„vÍsL¸S¨ŠF‰R¿3žIŸ'üÉ÷ÿ(y<¡©8k7*±¤‚çÎiÑ8ÍOIŒ‚=yÅÿhxi!Ö$¬D"h–‚±7nÜØ‹‚?ù}ö¦q÷FSêbÃÎð Ñbl8ý‰D´Í—›eg|ŠDÛ¼õÖ[»uY’X¼Q2à+¯<ý·`{rpâ%#nÜnlªð”BSªši–^œi·«$ÑæÅì¸È¯Ö(~z:ö’™ª e_S/»bšІ„÷n˜Ælõ£t¦m¡ö «"âbí¢|½€·“+ÑëSÙÂÅêïSzºŠ†Ê\J7ÎkïA(X_Z Qyeë$³uCͺèßäȯ’ø(†Ój‘¦LÎMÉ@‰æ®µ¢l¥ÒÖ’«¨x¬{ÞÜLwû~§f ’05þÒhµ]ùæé-P’'/¬ï«š#L°¹r üòTE›mq?ßjŒ r‰€Ý×IbëÆn˜UÀ]ùœE‡€ó0ãÈüf qõS^ÙÊz—éÐ>¡eíÅU¶…m?Ͻ¼¿­ãÒßÊa™ÅHep;Ÿåtv(Z£˜Q3áY·¼~ýBâØ(”°Å©˜©"œ´ƒÎ©æÎ@¯¸^«ò.É[DÉ4­µ!Oµ¹Ùò‚+vÝâÐ4ŸÆŽ“c¬tµ„øîÍä^‰æQ2US‹»k hT/ŸÈûfì6mMš?ã“I'¹¾¾^÷îÝ{*¾Ò'fÎmüie¿‹o„õßm¡¼ŠJU}-êyµ#£ÏÞ¦€íAyS'½×·L·p’ëeµrº¹>È&“´´Õb«£Re¡ï¶gå|ýº¶’¸2ÃŒ §ómIÞ|‹yJä‰sì÷¶‰U¡P™ÂjI‹Ñ¬¸`z*º)”`G¥MÊDG2Þl*íèÜ”´Ö>”4ƒu íÉö Ö^TÖRX>2mr̓¿½$,è™midÀ&>Vù‚If Ö÷É/ÚzP§>¿¦ÅÖ•÷Én•sï&VåæââbWųµ;aw—ïœ?G1ÑóÓ):$T¿u†³Ã}ýÿ~nŸ§çö×{ ÓGFwzýÐ ^5…Ô¦`Â| Æ ºŠ1ä‰}×"Až‡‰Œg°Äc§âÀõ÷œ+I‰ìââbÏ/Dè}…\¡õ“4•I…gé#S¼#¼JþôLt4Ô÷Î`=äÂLPE.»EK˜ v«&ªB‹¹UÍbE“c“…‚ñ‘ÒÖZ0tmvZ—š•OŽŒ<ÙÉ=RXìi÷ʾ•­D¨gBá‡h JšË±qnf\Þܶ†ÝDû(%úF19wÉŒ]+ãÛMhUúZ«ÓЩ…­çE-0+~~­S‡Y·ð, 3ÍÌ”,¨”`Vf+GFå '¥Q²¿]“090SG½ß+—¡ÏW%,¯•bevóèé»zÝ®E‹YéGx«fWÊ/«|å&›i£øX[ò>è“Óo/I°âÐÃþµß#wÊJV•¢º]¯Š%âkåðØJF¬­» }Bׄ¾• ÛZ;ò‡¦ÎºpáVº5OINŸ)»MÎíôvzõÕW÷”è0ã0^ÆgUˆö îT‰Çï/qÊ+Ëw Þw”i0%ŠÛÛgü5‘Ó'OxTñšg¸ªjSÕ,Ï– ÅÆYÄžn¬§»½^)ò‹&­Àà¾ø¦¿7Ø/‘ÙR]’ÖÉÑUÑMèXß×}-F¸wïÞîZ[w[s3“<å•ý}Ííä®77v›Š›åôÿ˜(Uè-I›Ý(»UrhBÛ7›ÄUˆmî¦e‹Ü¨ øÂØ,’ïufZØâ §ÞtARêTnfÍañ&V¯ êAïGÞ¹sgMc8H96‘ºçç—¼<|øp¯…&†tV,4ª%=•¹$ÔwC{¯Á¾¦-ö¤¡mßÙ˜:鬒åšÿìÛ÷îÝ{JbØD'Ø]ªduú ¯½öÚ «Å8æFfÁºsÓ&6•·"IΊƒ°9ÀÒa·ƒb[WNcó÷îÝÛK*g¼»STÂM®‡uË Z }f:Üz¦tõU¶»MÊg,nTk<ì°¿mnbâe{¦žG¸Ê!‘9ŒÃxšô±'cå¹=ºÊùT„v÷êÙUˆçQ ×!ž¯Ê¡kmË/[Iw/_kíAã Ö;å:L­ˆa:[Ý*ÏxáÝÚ×Z{ÅÌi–^!UO‹ØÅnƽ^<3Ù,è?ÿL½™È¼þúë{z¥§…íÿ< š¦„pq¡g|»Ťrlûmñr|EßøÛZ7ÆŠñ£û?»Uú'ö™ÆÍùɕ҇¦$¯X6è}ñ®ÂI¹¨¡!ÒI蘈áÆ±­y µ $›mŒ³3+Q‘ðÞw1÷àtAfGVΫH“Cl·È¸XSÉéÏh·ås§-‰†ßÆGŠ<Ì$Qh}sÛ}˜ö&y=oBû…k yœãL0•ýV­Î8/™y–2×” ®M¤²–< 1¨³V°®±¡~ -Ö’# ñëÓô±Å½%'ÃÖj•í BVÖU4™Á¼í¸-~mg¹Éôú` oJ5·S~ÐddK¹Â€vέØàih)D `7š‰“´£1ÝYÅI»³åî¦#þV5< /ÝàUÃS ÀïW¥ÌJ–8–yØmšØãž }`Ôï÷ûíÄ]\\ìÖIšúü%iÓLK£ÔÖU¿O!ç¶÷¯ç(8=ZG»ˆès ÇGGë—Þ|wý…¿ø×ÇÞ¸³þ£ïþÓëµ»÷>xãÍõ—ÿ¿¾¾úwœ­?ñ'ÿãõ„ô0‰Áaüÿ“ܾ¨œƒù'Ožìξ۷oïu×+úuŽvŽ…Íw¯Vj¶auY™ž§™htÎôynÙ1ñŒï<)> uaÀ´ïÓzCõÌΉ)¯Ü9fÀiG§slBó§C»1Àt·764î,þ™ñ‹×¦´t×'”mš:Ê1v|–ÙùôŠ;??ßû“ÿ,w¼¸×ØmÂò<Ãõgl-i;¢ˆDCDЉÎDœè?$¥Bh™ ì–!xÉ}¿M0UËLD¤TÄ~eÃ.¨ñM÷Bþu´‚b©îûž4sYõtÙ”ýÖ[oíý¨IZÒ=^?‘‰÷—^¢ÄžX@o©]t•oÆnvÁº×£ µÁ´IšÒÙZü¢©—=½N|°95ì%§)OlOŒ¨ò†u%f×Àöã$»ETËÖn‰J‰Ž…ªXèu"!]£°þ>dIkå•g%Ë¡leÒÖÊ€W푬&$Ñ{+†4eŽ©Úak´×Sý³[5ùEmÀê¤÷Ìô MjëFîTseq@E57ç^Ÿ™ç®+ókš½ŸÐܹu{]\¬ûôß__ÿ-ß¹.¯.?ØTOÖ'/Ž×ñÑñZ|îååÕººº¤Úu´Ž?m8~ÿï”ù>¹qcïßžªîÞ¸±Ž>¸Ïú›Ã8$c¿¥çôW4ÛJDô;3ؾsçÎnï팷 W|³u†Pv6v†w–zf7}BÏ,ØYèíŒy0•E…O™ xÆPZy—$b$$‹Øýv9À '͹}øðáSªªÔ‹ g1´ß÷ðáÃ=ÇøàWÝ_¡ñ*s5?ÓвøÇbåô)ÁU(¡øÄXÊDÆŽJÉÄ4KŸf¡B/..Öo¼±·näN{ÝW-¯xAèý4b-AžŠmÓ_HÿFÕ|øêóy˜Eê®Ý"·¯ûL•§øLíufZ%$%µßªÈ!R‚o4}ðÁ.Önˆ&Eggg»ÅÙ:&P˜<‘7ß|sOÍ¡d ›ª)dX@7&Û‡û-*•¿T4±+!GÆn•¯U±˜Šm&qrd ¦…ù0Ôv–§QhkÕ¤Ò¬WB—ª"¶ô„OM ?Ä©xbV?J%9ªªa5G2ܬ8(Ý}/l#ðïÏÎÎö eI36W%Jý¦î{÷îݽ.‰ïOšzÊV¶1ÔͲÓgåÈ$°ÃG‚iIÞ”¥TqDî•Â~»Šm>èÏ[pw´Ž~ÕßÔ<Þ¹õÊú²/ÿ]ëï~ú­¯ýÚ{½rï£ëúúˆâñ:¿<^óï|ßúéŸþ‰õî;ï¬Ó“ãõµ_õ;×7|ã·¬£“Óuãh­øÑŸZ?þ¿wýžß÷o­ú‘Yß~k}åW|b}êSß±~âç?»¾ïïþõöÃÏ®ßý_²þÈú£ëèæÍµ>x†ÿÕý·Öÿõ½ß·~ñç>³®®/ÖW|â‹Ö§¾å[×Ý{]×Ï1ðæ ðu‡äðâ[ç`Õã⋪Ë ¼•"m0Þª¹ßôJ&©{òH‚Pû÷Ïòé,˜öÏ:Ãa*f *`ö*gžžîu8 –›«b¿b“<Viûîb? r^›×Þïoî”W¶Pk°/HTIÃ$ÎëŸ>3µa¡ØyžÒÕ½ÞÿÖ#ÇB¬ü bñ\ƒûû÷ïï)ìOŽŒEì­º¢dMh˜h+"FD”øÌˆö)Ik]Ô‘)6›ü!÷¡)Mý̬¬¾/ÝR¶(3U"¸­pÉM­×~˜Æ†§smßg°Þ&ä‚i1^\\ì騫w]0«¼`™gÃA„¦D_Ý_«æL¬`òƒšZÑúU[ÙùWˆ 6 •fÔX¨ë}–Y¨†Oý·<æNÕy¾l§Ü594¶äÃ/Ï–û\.æ®§DÇjU;qvú¦ÌlKw_?~¼‡Ýì¾öùŠ\¼úê«ëÖ­[»ëÔæåº³-mGG-;:Sgݹق3ÌJÓñññzåµçÅgæ}‰×suu¹>ùÕ¿{ýÌ/ý«õ7¿ço¬?õ§þôzr¹ßÁ9¿¸Z'Ççë;¾å›Ö­;w×g¼µ¾÷ûp½÷Þ__ßñ‡¾k]¯µn¯_ùìƒõ ?û“ë;¿ý[×»ï]­ïù¾ï]oýŸs_¬ïüÔ7¯ÇÇë¯ÿ_{Ýû¿µ¾åþ‰uyy±>ûðÉúóÿËÿ¼¾êK¿p}ÓŸøcëêèdýȧÿÉú+ÿû_]ÿþ¿÷§Ö+·î‚ÐÃx 2šf¦yòä)®ç¤ßt† ?/`UÖz¬&Âò*’w¾zŽIÖ×{ʱ g|ep²aª–um3É›Ð{ Á»J wý3Ÿìä¿LCLE´‚Žé¿(ÿº¸Uè™ r÷µUÈ`…Ø~›f¢="J´Ÿ(Q1vÕ–¤ØðYjÀÚ¢´FãÝÛ@¯£ØQë®Xí™™dèÄڹئS‹u«õjE¢ä¡]ôIvÓøÇÅ܃ØB²ë –OUŽ)·EJÒ¸ÐÖå ¦Pqbýä*´Xg{±ùšî®Jø¬wƒ… õû­HHkcªJ‹Õj‹‰Œ8G½N¦4cß­<³íE¥¥…víÓ'Ƶ ÂuYkWùæ“““½–~¿_ó-¥6!×ùô¡QnŠDÈmÒMZ¸‚Ê|²¸µ‰ix9e+MPåàØÑ±*'ô¬æúñ{ÏODô¯d_¯µnž^¯oùæO­ÿõ/ý¹õS?þO×'þß·÷·^YëßýCx­£÷çôK~ÇZ×7î®þþ¿ºÞ{÷íuúÚû ÇÙíW×7Ãׯ³|l]_¯õËŸ}¸þáßÿ[ëÏü§ÿÅ:¹ugžœ¬ú“ŸY?öãŸ^Ÿúö˵nœ®¿ó÷¾w½ñÊÅú£ô»Ö:z½þ¶ßþë¿ÿŸþÇõ¯þå/¯é#=$6‡ñèlüVèÎLµ¹ vÇåÀh )סçË lò`g°n1Qžˆ] ý@#ÚReÍÐ{r`:7•_¶ V¼6ùÑ9 OŒ°ºIKðó…îß½{÷)®§âA3>šöJ[[hÕÃÇXVdÃD㨼e!Wx•bC’ý…üµVB¬¨æ+"eKöÛ3ÜøG‰bÑ<ÆSJ$¸Ž¦l·±YñÍL"‹_*BÛóOÅâîb‘LÆ?Í…°=%Ñ[WÊ3ëA8ãò~Eâñlé¥"¡«QûO—ñg9”N­ñ©)mfª„Ÿxº gv- X[l}¾Y³!B>e{ÑÖj¿M ©„,¡eúÈl=¨UÚmKÛvž×nÀª Ý4Œšø\qS1%å y-V“|Ð{P]Ìm‚’áOOOwŸŠm-V‰‚ÓC'BW×F jîôàQ–{>È=<Êš Oh[›DCû}VñB’h·jbHí¬M" Ã6±- é„#X<0p½uëÖûÑçFà×]^^­¯ü²/\_ø%¿{ýƒýôúâ/ùê½Ï<¹q²~øÿ‹õþþ®·ßz°Kš>rv{½÷Þ“uúA÷äöí[ëÖ­`šGëôäÆúȽÛëÆÍWÖÕååº:>^·nÝ^O>Øì¯ÖÑú—¿üsëñ£‹õ_ÿ7ÿí ìÝÇï¬÷ž<>Dº‡ñrÀÌ®_Ü„¸€tN…HÊ ÒB|áéÓ†@މÊ¢c¢S1P¿‘)“«`Šl”#‹ý<ãEtmþöàSÌAÃô´øØÜvÖÉÁQâ8(`ã-X^¹s§4wIê$û÷{nݺµûÉZ?•bƒõâ½Z¦ÄŒo&šGnúœ;#ý´„-ië©vçÜ:7Å7ò›§aæD"m AõÙ“[Þµ¹î‚$ö×Et8N|@·:.AËTÂ2ó+è2 Tž0ôâ æŸålÛâ<::Zo¼ñÆdIR¹\†Þ/é;ÑÄúÌëÞª<³ 0þÐLòú­v‹&´¬Å6»[Ɖ}Fjß©Þv°½ÉQ²nꨟòÞMU³¾_ z³öîCÐB¥¯U¶ˆL§"œX^¥£m¹ÛQ±C3µÆ5Ûj“nžNNNvP 5{ôàQdB€›6Ÿ ’@!‹_;çF®“Õš:iVùf'O^˜B×¥Õ˜­S°ãÄtH]]¬ïüÔ·­?÷çÿ»õ™ÏüćŸqt´þÁýøú¾ïùkë[¿þ÷¯O|éï\7_¹¹~úç®þÁ¿±ÿYplÞÿî÷EŽŽ×ÑÂ{¿éèh­uuu½>þÛn¯ïú®ÿ`=†è¹®¯×Û·Ãxi`f/ê8>:ÞÛ« È&D¼çÎùùù4lvö•Šu/wœíup¶üB”ñ«)ŽÞs(d‚„wy(ÊäJxïÌ®ro±®s*þŒp¦Ì[yï 6–œ ž±Ö»7ñýþbGƒ}9;Š)myɉö1˜7>2XŸÐ0 ëžUì¨E‚ñMI H§YÌ4–³7…šÿ µûÆGÆåÆ/~Ÿ`¹Uª¾ªÀûäÉ“]÷O¡„™ ‹(Q$"4OÜ£ÖUÉ·Â%*ýVR½¶gų́°dÖ=!FATXê¢Ê®ZàVÎ XMlÌ U—êßä"¤La5Âö¡zÖbD§Äð4-!ƒk<‰n¨-²¾¿$o.V1˜ÓlËS `•¿lÿyoÂÇv/îÞ½»w¯¶ÈnSy«ÎÔÔY¯â±…¯UÚÚj­Ý0¦àmrÝk[—]›ºÄÜÞ_K~Vz X Ò¸åóR‚«W4õ_ öþh—ðíàf}ýÕõo~Õï_ÿðGÿẺüÐÏé'êÇ×Ç^e}Ý7~ëný|ÿ?úëÆÐ¡ïƒw‡åÆïò;Öúø'¾lýâO|zÝ<¾^g¿ý·ïsÏ/.ž+ÙëÃ8ŒÏWñáy7NnìÁd‚¯T¬T™Tû‰óóó=ÄIñÑv*¿u†[>%!½€¸3¸€prx‹oô‰‘ßÓm"#rÀx¡DH¿9À[ç|_...vçœêzÞ$ô$¼»y6ØïÜô›‰†Ð±~›°¼i?QüÖo·ˆ­õF1@±£Ÿol8»Yú¯Z6ÅDe¨\j!wƵ6 ¶¸SúÿÌ"´ªd;…Ý 9”vÐgh_Qì(´Lx×T ¶ˆÝº*1ïõ­Ž±]Ϥ‰N±´b›œ™-¿ +•‘Ûj†œ„/+£*gÍ×ÍL ¶3ögéb™„u‘drp1¦ÛSšZ¬ž‹M¥+;.[°¹Ù š&´m‹_ÔëmbÓùV-pÛj›wÓõBi±ôàŠsœ¸:ý½„ôÉ’ãÒ 5uÖU®˜dþ®³ØÏÏŸ—-×iAÒäV5w]£;ÓL ùÞo%J}ýÖ…›`€Þmà³8àa9ÛÚ3 œ®¿òÆž›Dæ×$Í|ôaò±Û3®×'ïW­¿ú×~|-*2û‚/ZŸþÌ?_?ü÷¾}ä ¾xýØ?ÿ‰õ‹ŸùÉuˆß‡žÙ}9Úuxzéý|æh]^^¬ïøÆ¯_ÿÃÏüôú é/¯O~ò“ëÕ[gë³÷ï¯Ïüô¯O}ó7­7>ú±C0z¿©ãóbjzýbûÌ#Øq¿}ûöž o¨ˆÎ…`2V¶E9}·Xi‡Fž­gø ·*óžc³h%‡FĉòÊ[\‡Î¡>[±¢ŠØ}~g¸±Á¸^*[´€:&3ØîógìheÞ¹íÜŸfë"F&2¡Ê¿Ðƒic¿Þ/¿HÔ„ð§Îøì%&ôÝXÍnQªª[Ö­Ã-Ââ`à¾o"J¦‡Ž ¨"[ `LYîÞ_ò/¯k"J&,ÎŽMs£t´ëêsÅÍÓ_È€ ú®ÈmëSè•íSÿ»®€Á¼„°T;ÄöyQµ^mýŠ—SFn&NêT$±r/tM‡Ó­€ÕjK>m}ÐÜë ˜¨(/˜ªFótyy¹îÝ»÷–Ðß^ ­ùëýÍí|Ð}˜NNNž’Æ–hcÃ6 IDAT'bkTUËËË]Â!!«Ž‹>,š&µô]-Æy_묩ºquuµçÁs||¼ÎÎÎöû£GöZ·%ØÊRºN”^,‘Ñÿh’ýKtš›º½_¡„æ®M\"b‰„T‰ÊÐ Ôd¶•­âÅÿñ™{óÍ7Ÿ: 6ŸÙç«-óúóì£ëã¿ãK>ÌrÖZßúï|íú=_óuë{~èGÖ_ú+y½¶Þ^ßþ|½wþÞ¿þO9úð•ëëëuûµë?ù¿{½ñE_¶þö÷ýÀú+í[ÿ÷þÈúÄ~lݾ{vˆ¬ãåèÌ¿Ø>3£tX÷Œ´’Ÿ±} sJÓkÏhaÀÑr1;Ãû¼Îð)“« {»2½[ªgr€uŸ:ïùß9U×azÁMŸ!Ë‚õ;“ƒ2ýÐT]ëC˜â€û÷ïïyâÜ»woèíܨ(7»]¢2Šº?Bß‹{º*ºU@7¾Ð¾$*•Q9¼³Aàë“cã:PJŠ>OÁ'ͽ”E(ºFã/U]EõY/?zšê¿h‘Úkó™›Ü&¹åþv×¥¼¯µžæWŸl=øbH×Ú'E ¯êߦκ¤>¨&Ç(´,Œi¨ßfk´‹¶}˜Dð–<¡íÉ-Íth73m3èsåÐì©GáâƒÎQq £Ìª­8L ¾vÉ€Õž evl̺mV1™²•fõbH5µš£þ¾‹Yl®]‡i„Úõ*Oغq1Ÿí潎ƒY{s¯¢†R¶¥»×aH­&µ.„®Ù œˆ­_lÅúnõûí´MÈbß]Ryuuµ>|¸»᪭ŒYñ899ynâ_‹ÇÌûÕõúò/>[æ¿ü¯ÖÅÅ庾þ zs}¹þäwþÁµ¾ó;Þ_cçï­£u´þȧ¾qý‘oû¦ŠÈëêòbý®ÿì?ÿÀ,ïj}ý×|éú†O~Å:?¿øà/®×øº¯]àë>ùþšúàyøcßúuë}ë×­s`¯½v²þøþ¶µþð·íýÆ‹ËËÌì0^Ž.Û ¼Ì Ü âŠo Ò 8§*«ªdúàY°“ãRÐ8 /%ûORvg•¾Lt„¦Å¡™ ŠÉ)¾QBÙ"ZnꚉNø”ðl ½œô¦Ž]Ïð7nì¼â:Ç*bk8.Jcò§‹ §"\¯ÏjîJØŠ‚õ¥'|ªØpjšÄÕ þm§ÏBÍM:Í—ïŸH*ÍÒ‹!ŒËCmtmAû,‘NÆÕÍÓ–­IseA5^E´Š E™Ä…tjÞ*Ðka§m3™ë·!Ú"5UqPÚ€Ò µõjeÜ­žµ<‘^WG]¯UÍ„W=+‘Q‚x.ƉaíZ’?ìï:ˆ(ØÍ-ëë'Dh¶­öô{{­8ˆst£˜‰ÈÄ1*/8ñµò@|ýYz]Ÿ<UÏê:(hÆ/7Ë{ã\ØI›­Õd¡h=h}žj0}ÿÑÎþiø^ŸIšpƒ>_²~mk[þÓ,Ë–¿ïïZ§¢I ²ÁVëU2œ›X‡ßÎ £Ó)(»¾^{8ä]qñ!Äìø9æ‹Ë˧Þï{/¯®×ººø½vôÔç<õžgüŽÃ8Œ—6‰zA[357.Q‘ BåÖ^ouÙ¢“]U[˜«bÅ/”’ù×úÇ!!½‚]±›ðñ©êªBùcy°·nÝÚ´`˜9m¦z•ÅÃα]—ûƒ®…<÷õ)Z3-DIgÜäÿL@ƒñöy¿_èÙ„×2~ >þ,4Är€]w&*ò{*äš— Æµm]TÖ[ޱ܍Y¤žü!Ñ6rϧ¿Ð4 Õ?h"ZêÈs›²ß“?]qÀ3ß5[\þõf2£²„ª[^'aý„rÙB3¨r1L*!, ÇïÛòJ±£c{´€´L¹`^BºÒ‹‘®å8ºváQÝЮÍÖå½{÷ö”¸t_M‚¸k?99ÙƒžYq˜] +"r! ÖͪgÛY hSíîO¢Ÿdƒõ:.3Á­­ì¡‘„žíÃ)˽%»½uß·:}}¾Èêô-!“Ì©Ïo‚ܺhÝÌÖª˜Ð0ñ¯*š k´ÒäøðáÞº—­<¡®ÁV[êø¸]¾óäyŠˆ>ÕåÃ8ŒÃøõ?·G/v‡&¾£çLg >3¦;ez­¼ µ+2S a°>;.UÆ+Ø©[ütrr²ƒ@u®Vl”ß`0>{"e a®²n!¶ß®DpIš‰Œ^ráòD‚ÎÇ[ z¯Mçš´€ÉÅ0þ1ÉS„ªbe$ó^‘2ƒñþ¶b¦Ðvy\Û3‰SèàYñ‹RÓ¢&fWB4 ðä_;—vââV͸¹¸pv5âËŸÖt;Ë–Ö¥ëÊø§¹šF©v£Œ¦*š÷µØèââb­Ï&¤øÈn×S>3¶ÿªl‹÷W>0Œ¨Áµ­Ñ²^y#÷îÝÛó ¹ÿþ^Ö=¿êi«¾`°? ©Ä:6!úÈÌ€U/ÔíÎlmbVêˆÌjLŸ!‡æèèh=xð`Oêñõ×_ªãÒBÖ¾à\ø•ݨ6Ž6 eð †]0mlJðé•"²MRe.!‡Ên»."»©Q¯„°›T‹]Lhв²òGíIú)6puuõTV?!AL€­Ê 9ÔÕ·v±jvyum>#³â œ¡.攥tö o l$[iU°¹·87——*s‡q/Ýèœ×ÏLĆ<‰H¢ìß{ÎÈglïhej¢ê}gAu2¼Bß Æ‹1Jtìî[¬ìŒ®ã"¢ÅB¯g¶‰FIœIžgxd!Òj+ôjžþàÁƒÝ=)˜—/½åScò š§{7•»D‰ÈñÕÔ1l±bH ú4OÙ’¼]¾Ü‹Tt3Q)‘ÑÛuR|Ôï“[5Œ‹[‡Á¯ºv98qdŒM£„7Ìø§ŽÎ4Sßêb*Õûã·¦‹»õÀ)U)°ä^¡¨³³³=.lïûfgF/’^¿Ù×tgU™¢ \„‰ç×IWcD!B ;>ªS)£«!fÐ6ÝéõB‘+‘êY“é|Ûƒ¬üó XMT¬æ”èøàÛž[k=õ –u—\Ty7ÑÑiÂêT|snlÍöY¯¼òÊ.«on«X”•—5×I«šc¥ËÖ¯­ý©ê±U1„Y0îÜ»+ÉkS¶#492’ÝZ«ï¾ûîžÔä–ô£Õ!=¤[›”âô²8[ö¶ôÅeoUSLÒšg»”u%YNéé÷®žŸrêóU9$T¿µÖÃ8Œ­ÑeÁOBy¢.vL:§(ÌäÐ7QÇÅʼÕêx´Væ-¾*4'Êôv6ŠÚž¥±¦Ø:Ä×ñ õpóæÍ½XÎø¡ØLøS…P»ºÝ?xðà) Â=z´§„zûöí½ÄLCpáçÈo½õÖSsS¼fÇf‹RñäÉ“=Zà Ƌ¦g¼œ—¸Y͇Üó;NÚ…Øb 㛩X+7|r«\WýcG9¾Î}Ü*ÍèU¼õ»ŠolNÈ“»4ᚉ…Î ½Ÿ ®cO%3ò\f–-f  ¶ af‚SYÂDBH¼Ð´i\èƒØ&$´¬`^=ë ¯zï½÷ÖéééŽ Q‹Í¶±ªV$Üäô‘Ñ/dª/¸©5wVö þËê«øºd5½Tì&‰Sl±ËéÙâÈL}ý6ey]›¤»¥«Ÿ%ß,yM#Ö6Ñ©¨â:RGÝJZ¶Þ_'®n”Ñ~Ký‹äÐô~וóʺIÎ×gÛºCÀ¹ûn‡Åj‰ˆÏÜ4©®0“´'Ož<—èC2q‡uõâ$Š/*gæÆñ~ÁÍBÕì:è³×9ÙLe/ ïr!f1³÷‹\ð”#ª¢3|šRPÎ3Ü ±sÌßf|cסø¦3Ä€Õ`}Æ?ºÉ«üU!Ö`S´Žëì tŠÆé“Ìoì7{z½D¤B­g|ÅH½ä¦ž±ÛôR @ºsc×ÁÄAn•š`kô®×|}òƒJ€å_Oµ;¹[úäMþtEî^?==ÝSò:Ö½)ö›qq£u3 ÉgN¡ÿP¿å™™¤ÎZÀbÅë· ‚–õE^NS3O+çÞ0Én-fñsSy« íuMðnˆ•™¤4¸“¶b Àä¸X±ë ó­8Éé#c[[þªjJKä3«îß‚YQiq¸X öS±0Ø®" ÃpÕH\b@•4ÑQ-fjЗõ`ÊÙš×E‰Œ2™V¢ª¤õ[º~×M%õùå^Ù–VÍÎDeò¾ì"z8†µe.YÎÃmzœœœìA [WªÉ¨¿o·ë¹ªZ83‡q/frø‚>²×ëÃD%X–ñÉ—³½¶sDްç˜(‰û÷ïïΕÎÏÅ”G @ƒgÙ·`7RM' æ§±aÁ¶‚=ÚOlYg„(é·É…˜°:‹™CúÐÌ`>ZÐúº[bÅ_ª˜éQX\¾¶]…ròŒtn'Y_4MÁ¸é¿(4Ì"ss1ÕìDÛxß‹M›«bùOžñ³Ð+?(‹¨Ž­¹™Šn}^ ¬ÏLk<5]ý‹ KšåOùåµÖSsEÛ‘~Ë´ŸÐcp—ÌX·}(äÇ`=™8GíÁ&t«µjۨכ”¸ }züJõ !@fÕ[¤nõÄ%´Ý’»Ðƒb5ÆÖhX½‰Ct1»¸Ú( àk+Ov禹ÞÒ¶g[¹ïo±}ªýx~~¾ëVÙ±)¡ÓPjv£Ú§˜‡µÖÎQ2~×wvv¶×jMšÚÅ>O¬`x@ôû¦G›¶-}ùE­‡îm•;U ¦ôt×ûÞ{ïíI3>K±DØœBkÚŠÇä¥5mrrfôðñ™±ãs||üBûCÆaº1‡ñ«Ÿ¼¨˜©(ž_蚇,0H³{}}½îß¿¿ Ý‹+˜ !šßañMcºÏOlñO› ÉÍjuÂ§Š½¼V‹™ÆG[ü:.ÆKÆ/­»­øeR:ÖZ»DGoo‹›URÕ:D5aÑ>Èëf™ —\ÇŠÛ¥Úœëfš¡÷[gr? 9­µÖ½{÷v±ïßìÌḬ̀`» 73ì‚»h degfýªGÉEèA®ÕbÛáý? »™uÔl#‘´4àÃ8ZÑè†týSõLãÃ:’¬§;«^&6×bvc0QÚbm«£"U~Rø×®½¹ÙÒQ7ÉëÞE¼²mÝ‚íõ-ŒéT®0_ZK}mØÝ×ÖˆF§]¯Y¹ÒSºº,?ü«ªê3*¶yíÊföYVs¦¬e•²¡c=¸J/NéD[§þv˜é?T±¤\![³k­uzrú\ùÌÆ!Ø?Œß@§áóÔi}QŸÝ‹Ë‹=ÔCÁ¼È]ÌåZ¶—¶·VÈÕ}Þb¢\Î ŠÂÃ;ç,jÉIF·s·sªx`Bã;à NŸu†÷{äÛ)¿<ƒùΙ-+ç“ßÓ÷mã&q!ªö?u>xð`wì™R Ÿ*>ÑCÐø¦Ïlîœ[¡ñ*ºÅŸ³Il›«Ø)’iÆÅš}j±0‹]ˆ” ø&¸[BPƆ&2Ož<ÙÁˆÔo-ÉÛ¢%ô›ë =3®× \®©†§5FïZoÌﺚc—Ìèia¥!S‰Š¸Ç)C'‡f&2´¾n0oÖl×@R¶X¿YÝp;*ývIM*oÒOäîÝ»{(Ò¾_è™Ê^få %ôY³õªáT‹_il…æ&dEÁMŽL—æzv\4-r1÷  ŠçáÜo2+7ØW /²óc5hB;lùo)_høä&®g¶V[W®ÉɱQC~K_ß®aݨ†-ÿ-#1×UÏL]I“¸™@ÏnUŸ!îz&J7nÜXǯ<>3ÏCp}ðkø¿Õïëoöõ½èâ A³ ç9Tux¯¦:•ˆ9.“ã;•Mõ™éߦ©¤…Ø – Ú® Pg´Uÿég×¢ø§³G.gs#ôK™)Ÿ,b¤¡R1€Â Í<ÏU‹Øvô‚+^(X÷³ëV?X¤66,×~âÝwß]?ÞøÖƒÆ ƒ“ÓÜ;voZ+ÆÍú/Ê¡™ëÆ3^£ÕØÆäÀTäÞZÅŽJŠ÷Û]w!²±àîµ×i³k¨dyëBJÇLt¦š¯s3½›\o'³k`¢bösyy¹ÎÎÎö³<HýÒ©‡m&êbﯱ¢ØÄ2Ï2GÛÂaa –Õö[ÔgÕVîájÂå¸ØÊœzÎMò„=X“(ÖO9AM‘ì:ôû•àkÁÜ˱qîfGÅMÐNÔÔ×gF2Zê$»µ&¼¯³}8õûm½ÎDÅÖ«®¾ÊZ6שÕyX ™¦‘]{„1Ýi«t=‹Ú ÉRxãÄϪ:6Üél{}}½^ýõ$o®ùI0m]ÚMšD@ÛÎ)®œŸ¿sHbã0ã7ô̾ÿÿ_ÀÄæú˜Z‹_´`ˆ ¡²©2¥òŸÂû«¼5¹ž•îí"¬¼ËÝ"m«<Û Jbx”v«îܹ³×ŠÓ(þ™<¾î˜ÒÕ3ʇϮF/ì®ë²2¿%eW"e®ýî×V1ñâââ)Cð µÅ<ÅŽóÆvªÑ57®‹©Ì%£ù°›U‘¾¸nªÂNÕ×™èTÖÌ|BÇJÒºž~‹:“¨-oIec»9wÍ*!«—÷}3çØô™)à,`4èš2¸Êä*ÛE»[p÷îÝÛÝp?¿êzb-°©ÎÐ ± æ&+ß`º¿vÃzo7[Ift”4ä}ÐêZ´à¦F½ü ü@‚q¥!?y Î]ïo¾ôѹvbT æ§tµÕœ©¼¥ÏNÁ´<‘)OX"`µDwVuÊí¸´«h¨%®ŠÇÄÏö »‰:W÷îÝÛ[¶ôS„ö7!‹¶ì'$ ö§Ši®;ÕZ$AÚ¶îõ`k&mòΪHx­zx@tàµ.œòÛ·oïU1ÉÌaÆa¼lÏîÑñѮ꤀U‡ö`aô•ékm¯ïܳ §ñagA‰NgãÄûÌ:4¾³$hYÿ¡]u©Î±'ºÏ—àIÚq²Õqé~ˆã$¿ ãgîg×G?òÑu}~ñÂýöY™ïŒkÿ¯2owÜDÅ`ºs¬ó{«« ôÝB° ϡ#Lޱ<× ¿ê÷ÅóèýÆGÊ'«îiÀÙ^áÕB©bF½_Jg´I–]‹97V'Y¿"³É€Ðúî‹üç`wr»¥-#¨xÛ˜ð«^×zCéê+‹Enܸ±‘ƒk0/©¸ÚuØÜ f§PŸç·nÝÚ“TîóÉê>Lh¼Šp'''»YÊFIM릹Ù*‚›@·n&*=SSäªëîó§øž€3Ãiìã&!Oef†÷ŸR±¶D[Ì‘¾'™ÍY‰Šj&aË`ÛÇjIäu\ZœfôIðM¢ ]‡gyì´yLßIjêÚ"»5wU“¦*G‹Q i¯û ÎjŠ›dK-s[êSšÑ`]Çã‚é¾Ë-̦mç~ŸÎ¶Š4Lž‰Õœ6àæÎ¹™ñjÐ »{–b›-ñ¼ˆT ë^*KYË|ÊNšä)Y•nJ–·ÆL"gK_쳕ª6he+[·»MöóŸÉ¬«««õ‰býü/üüú™Ÿù™dêaÆa<߉â­[·Ö'¾øëê'~b½`šYtªãžº¦Þmžñ&2žCVÚ§òh­Õc ïB ;çg"srr²Þ{ï½=²¿šÎŽJ½ÜthYP|dK4ŽÈ€®Õ3xªkû™È8WCù´ñ[~hý6…œ:wõJQYËøÇ`^ÔH±£÷M4MʤÆ?Æ¡ Û“¿m|S’ÔgØñÑŸQJEëHYîcÇŠÐZ5Ì,Qðû»öæ}zäW÷þé¯hÜ­¢šÜ©âçvBë}ff\îç÷þbín–T…½dF ©A—¯O䄞uQ-`áSJή‡«bóm<¶ÛìJX97rB HÛH$miÈ›èñ‘d-ô¬¶´]…0¢= q-LòÄã¶Ø:ÕPªÅZ+wz­¸XÏÏÏ÷`u“l¦A‹ÙDEý}€)´Ðç» eª$Æ´÷w-.öÖ‰ÕÖFa5húĘ [É*Áµu<7±ˆðÆ’,;Ü4tšð’ÝZ7þv¿ˆÖsIb‰ˆ¯·©Yí±¨šž›úÎñøó[]×wî¬õÁšúò/ûò=Ó¬Ã8ŒÃx¾ÇÅùùzïü|]߸±®nß^ ¾Ãó>4}´¨çE; ï—¦û|ç˜ÝpÚ:´ èœõì0 5þñ’ª˜Ò–Ù§9ùПȚð'c¿£££õàÁƒMXœÆˆýöÉs=>>^<س-˜Bâ'?hÏfàƒÏ;==ÝÏÍOçøä‰ˆH :U|ÏTx¸Â]›Í^+væ’Þ²‡ˆ¶ 7ÜŒ4/>*/F)î´,šhú/ZÄ–=»aŠM¡…)d°ÖzŠìoq ø¨ug"£¼r1v²Ýåœ;‹ìS¤bç3ã„+#פxÔàë¿§^õíÛ·÷”œð&EYä^·EÖ Ÿ†™Þ0«Ó¶ÿÌ,%„UQÔ=•·¼ö­®F¯Û"3Ø·­l""iÜDeª†LÞIšrV‚¸Åzûöí]‡KE”º$&yš&ì»!·Áö[º/ͯ8IE ÔÏ÷ZÛäú·<ÕvöÁžbJ;¶YéRžYyÂä•åÐÈ‘)’ ZEb‘¶i•$*o¨Ìµ:ëz¨xâ[¢RbõðáýÄiJ‚ºÉ-ëÞœŸŸïªŒ×WŸßÈõ;ëâ¾a½úgÿì:þ•_yÿ·\º2‡q/Ê8=:Z7×ZWûغøöo_×Ãgî¹OÆ>ˆ5Th²`§ñ¡\Ïx•GãÀL®§{}gàVü¢W…\M±-ðyV¨^å9Ögën<©€tš.v«)FäëSˆÉXÏ3XCÌþ;ÁþÍøEŽŒééAX¡4è}¢9&:AȚÔª­%Aã“窴µ jkjÉ»öþ¦$Îu1=tL¸ã–Ûm+éÔýPHArEl¹çzõû‹=…ÞñsÝÌBî”_~–˜cfN#y&Ð6OÈлi¯3c"3 éÁplcõ£'iZ<›{f†âÕ ¯5*üJ2¿•ó¾Ë¬»$ìæÍ›»NAÁ´7sJà™•Où@!HÝЧª!z©hjdµÅŠC­d+&Vg5¦‡M~ø[å•Ã6¦\Ñõ4w“GbÛ×¶²FbJ3º.Ú\àΖ|‹SC&ùEÓ'ÆNŸÜ*ÛÚ&yÍ»üý…š;Imb%Àu«zƒ#¸‰žžn:*»n4šæ33¡mâ®MÎýíº=w›û¾³jMIkøØ‹‹‹uãäÆçµ3s}÷îºüä'×Õ—~éZÀ@ã0ã7o®ë7Þx¡’™‚U»VŸ‹ä‰L‹…­sl“U.-fÐ^Bø“¶3 ´{$);u¯Ë#ùðöÜÜëz ÿÂ#ÃsHˆ³ÒÕ _Ÿîó"Z¤àN/º`uóKÓ^G‰JñÓ<ã·ÎðâÝí剺6áéÒú|“BX‹Ôrd¦éõìÔ+¶$wª5müÔºé^ß´Î'?Ú@ñÏôØÑ³&Z†œ6¦¼³Ý®’sÕëš;/Ó~Âæ‰Ïœ]LÇSœ[l-6‰7J±méa÷£·Ìoêzl{Ã’‘Õ!յŠi{’ÕzÐR\P/»ï¶B0Ö5»ë§2—–-,ŸÆ‰“G²¬÷`©¨ÒbU5¦Å[@ÛÜÕvÝ2Mjƒîa*É:áKͯ÷ÛK„$û·ØÛ«t¹.¦ÄžÁý æ§WJs×ýœÁ¾‰†ÈÿËÞ»>ÙvÖw~¿}ëÓ}NߎŽt$ !Á€Ã``4X¶ãûe;¶Çs‰')WªR)¿É¿“ª¤*•I2•‰ÇŽ=Œœ ñØÆ€ „B çôåÜz÷î½óâœÏÖg}ûi lu»×š¢Æ:«÷Þk=ëYÏó»|/l®&!dÀÂ…ô4׿ŠDn~H3ZYfkk«ó÷NtÜqáþööö–shŸ5ÿ‡±°ŒbêóÛ»ÀD?¾o4ÕX՘צ¬;©ùƒV]¹ÒƒýÑgý îýïŒó£yÇ3Œý–‚`ÑðïôÁs"äxȪ®¶p°XÿmSì´p¢bxxŠÖxw¢ae-›2š“ûj5Ç/H­lš±ׯ5àÓG‚`è¾a{™Ä3ô>©E|eZc›bHŽýìC™ð½›ÇAürRÊ’ IDAT <Ê]†ô_tüÔòš³ê™ùIFÛ0v|¿‰äV!A %ðÿ–È„çß slL+pìf1£DqµøÕ ­Oè½ýìM™Etb¬L %3\´õ± º ñ1ÜÊð¨Ô¤¶“‰É~¹ÚRæŽJ{ÐÕi¶¦ –YËè:n™YYuÃ>0LPÎl}òÍu°CiªWñ²X‚˜ÉîÙ‰’ £h—ƒÿ¥ÚcyÁLIv,ÍhÉ»$òze²¿“¶'ÝÍJ¤Û•®h0¯<-AìŠId«šcC¨LýRÐV¶OŒ94æ¹ÒÄ&¼ñ"il¯e+‹Emmmuª/´V¹>0¤Ü[êó{7$À÷7Ý¿Ý@ýÑýqN“¯:Öqi¹Œ[Óx}öâ#Öoû°Ï±G³OY½Êï¤a{À=«ª†LÛ±…á4"Vg[v)·_ˆõ²­Ø”XDë¤Û Å¡V‹‹€”ÏÍ2O9W,|m樘(Èr"Ãdö½ñáߌ¯Ífµ··×i}ûecÊ÷ô"ßï¬Úb88èìp`Œª “Ó‚Á1¼*å—Ó†À·–™¨92öSãÞÌ)NÕ1 ɹ)Vä"¹ùÑt\ð3,΃@±¹ww“lŒž²Ú– vlh³Qó“æ=6©F—²Þîb¤—ŠÕìÌ-÷Ø™{žaõÍ1ô¾Å?òyÇ'6 7˜ycŵìÈ´ÄÜiKû Ç'¾67?7;12\óX2“x8û‰˜ÜO ,+ÛîØ0XVö²§Á'<{x8˜7†”kc@3³s"Ãï¹­ëÙ"¿xdÅV-sõÅÀTΙè)O˜ íA®7+"6ÌdüLö§ÚBÞ≘7‘Šm$:&êû ¾ÖòÊ|×x<îà óE¶Ú;6;+OÐi³è Io Ùm?Ì"IGî,¸S¼hÜ[KµÌ‹ _dæIíÖÖVgQrµÅ°8¾?G²Ké—J›}hZ&j®XÇäÝpë¢_¯ÖýÑç²3£ŽÌþþ~]¼xqwßpÞÕc¥øÎO§Ó¥²–÷UÖ\«­JPæ`žuÞ~Ä?Ä?ì#ÞÇÒ¯Ã{´÷‰T]BtÄáû‰ŸHwwwy¥˜dë ‚|W‹#ã{çßÍ16|2¾c/óŸ)rsm$qìÛ.2û¹ºî…-(R; Lh¾M!ŽŽj{{»C©pÇÄ]«ùºÙJ‰…mK’q¯‹ÐNTmC êB-ñ±GBýÎL&“ÚÛÛëÄG ‘Ò¿ÑbZFiVGq€9êÛÝǪû03pgg§5³f´ƒ:&ŒÍmÜ:e ,?˜\ˆT–`ÂBd"(õM1YMún)Žˆ8Q³ºÜ-/c@-„ÀCw"„| Û‰»»»öd¾,ÉÁ1¾‘_6'Zöz!‘!à5|‹*¾]M†s¢CvO7Ê2,’Ü«½NZ†—^ăÁ’0ÆýZ~™…ˆï&kOÅ8/®TYÚ‘cƒÈEyä–ˆ„“ó“:2Ù1±l¶“4BùÞ{æ©Çžñr[Ú 7¸Ldl¤ Æ”{°™è6×g2ýÑýqÎÀ‰okÐÚÝ ‚6Öoó-1lˆ’‘F6°¹»î½†B¯áa––& ¥£bø“ n$Bü {  rFãpò›;;;Ž}úæóyÇGÆ^q\¯a{+++Ëëc_$>£I¡š±µ¨Ž»Œ]Ò l:é{'~HÅ5îÓŠlF*eÈžÎs§£SUµ½½½,.{^ðŒdž.V’¬8ÖtÜüh:y$+tôH´ß8¶rR@‘Ù V3%îåú€S26ðîy6¼S$?ĵæØÌf³Î;ã"¶ã/¥c>3ÖâfÀè€8hâ‹IT8p %»c2ZaÉð(W¯ù~óD’+aZ³ü–+ë,& ¥ú‚ éó~QyѼPh‘(jiÆäن·[lJp"‘z<*üðªVë•{3¦r}}ýX°î$ÍÒ\©–0Ñ©ٌˊlTk\‘`²[^9Ÿ»ŸUVºü² öb¨ç™7&óûó,&æ¥jçÝ–¶Wˆå•_H¸±±ÑÑiw%Í‚§qцžñ·‰Ûv¥+ 5«§ÌôGôÇ9=(zý4Œ×öŽOrNÂ{úy˜Çj¯C¬]ygÏãóì#† »¨eÄŠ‹•@ó-zã=ÕÁ,û˜!FÞcS×çI6²˜—“˜†=–Ûßß_BÂmNŒF‘:ùÙìaÙÍÊøÈcáÂ…Ž‚cöI›¥%*Ãðos^ ·á8ãg>ã– ¶©µQƒÁ`)øÃ½WƒÖq¡—ykØc˽óy’@Ï+ŠÄø. ÓE4D=ãf'™30v¦pd"DN`ÅZdž¶%I~³;6ˆL¾ôV%³–¸F‚.2?w\L¦£K;ÉÐ1¿ˆÎjÝ"c¡€Po2ƒè®ƒN:Y¦×î˜M!ýâZÂÏ™)ãeÃIK/2Ù:¥JdRº!cK²`Ž‹uÖ ÆóóY‘`‘Ã42 1Ý­J£µÀ™ì†Í¥´tBÇ2Ø·92n+ƒ•N§Ëçν[–ÛþFîôѹÂC'ñ³æÐ8fÞ°(PQà^LrL8&/zJ/¦ê™+at1rèNßE’È8Aä³w“±Ç áYM&“>Ÿéþèsy¸£AŒÀžäµÚžæ;¦àŽ‹FÞLjo¬.E×€µÚ{8ÅHwß°ÚF€=ø8ÅAâïÑŽ¯,ßl®§¹ŒƒI߆8[Å̆›æ2°79 ˜&ŽdæÚÍsµi#çÙçØ·‰ˆIÌñµ|²‹™N”Ì6¼Šû§#cŽc9':óæZd2·ÜÊ¢É2­€˜#yÜTó…[eޝãZCËP-˸ۆÞ.¨;>bÞ¤:ÏÜ”Ç?N<WûóNdø|6/àÐ0îŽoì”GÇ4Ó2p66L®/³#ËÄå¶TÉŒs¤:/]»ÚBø2!«_r•sssy­”&¼g¢ÔR‡2ìÎ2½®ÌÓÉh)Âùzx \³³^CçŒu7ʓ͓1awÖ7YÍ‹Ä[U£ª::ìœ?I.ÇÆÉ‚»YIèâ+ºñ7†ÆyƒI7+ù?¼è&œqíVÕðæÇ¼In”•lxg©ßoÈbª~$‘…XÞÚÚZÇÈÕ²•nÎçóåw»âI”«9©ϼdžxl2&‘¤šÃØZ–ÛóÆÕ$wQ]éb1¹ÏIfôGôÇy<ˆÙïAm,!­Åì“;;;Ëuó–õ% uõ˜ïbŸcÏBF×û{¸‹R†ØÿPÌs¢dø¸Õ©l‘]Ð-YÈ…6à®CZkûY¢Øû+ …U_mìLŒÁçS™Ä)qÝ• ØçÞ¬ºê±u'Í{°‹;Ý©óØ9míѹ‚ïƒuGÆ–îèø¿]à'öä^¼ÇsoÙµàÙ‘ˆ&åÂüp›¥'"%ÍFÝ`p\Ì3ò¼°Ð‚i.äÚ_ˆØ–wÊ×Ç}˜·æDÊ ²ŸÍ˜/¡kÀÿè¨ðèŽä¦Žº'›ÏgkÕ­S«šÁU zmÒ’;:8œk­¦6] ®Ý| &ã§²–Éü¾·Ä1ºâÀØY‡ÝÕl;ëÙÕœétº¬ìgVïÏÌæØ9©£Û•mk&›Û¾Æ-Ñg']sdHTZf ;Æ l±ƒuc@‘¦Î±³T%É„ùCn›CIŽNŸ[Ÿn[{l½¨9IòØfÒ ¶±ÌN"9o6wòRºšw&¹YéO”¸ÒþèþèótPAgí$ 5‰›}Š¿7〨{ƒc)††y-¶»=*L>Ÿ«º"Ì^@ÀH|C!×|gÜ(†ÚÁÝäÈX~9QV•uWÀs„Ù׉í€OÙf1P&&ó=ƒg’ÅÀ«ZîöæÈXõÕð,‘4ônqdRy4 ÇMöOÓGb“ñy6Çx²\{&Ȉµ ¹$ †ž9öžî{Gö›ye‘¬Tû5eÂh!7܉#ötÂÍs7÷*%ͤe\Kìçæ‡ãü¡+î­Ö)“¹éÀnRv’åxù,Á8¹¶¶vÌ¡ÝbLV?0K9{2‚´Vy Þ”X?Of·y`îBGi k¹P0¹Lèj%‰ÖY€“ä9Xg!a‘J‰a’¼$´ó\m¸é¶4‹¬³d+w!kiâ ¡ež7¼œ,$æfy²ò¢:¥Z•CÇèÔylÒG†dcmm­cˆÉ‹l8A’ýí±Ãµó™4 ã¼7?›a¥+ó†½Eö·L¦7ýxn6”2”³?ú£?úã<FÐÕp€j®„×b>kãå,F²±O™§A°îDÃ>3T¾ÍUpG²;2öÙ#¾°_ÛíÛ·}¿áÚö¡!àõ>gB<ñ‘!ÒVŸ"Ék¼ìS†þß0®b]„Æ´‘ø:×NÁ{³G!^+/^ìxì$?;­9l˜™¦‘Œ}‹–Àw¸ÓâÅF¦-ÿE‹3™ðN¡6»Eö‰q"c~;}ô Û³‡Ï5»QæÖg‘-ó³ÍÁIyg-ºUæ–;¶óyÆÎEhÇnÇL3É,ù!ãé¸(&®!J–HvåÍ.ÜX@^T&³ñ¬L6‚6°vî˜øó¢ñ}`íŒc$¸F/)c÷ÀAr?þ}Z§nW²HZHÁ/ª•»lÄyOf&+cçÖ*/‚+G–fVç./ÏéæÍ›,—öŸÉl^䬨†DŸÛÖµ»ãâDÉo -ÓH/b&ÓùE2ö˜<[â-’$Ý&Ï;·Ì‹E‡Cc|,ÏÂ;ÌK·‰sÞææhÉrw«¼ùºÛåyEÕ‚¤ˆä¾WgîþèóšÌðÿß¾}»ÄzvüÃa<¿¹œöô¢°š‰’y Ä7ær8aÃO…`×Á¼ƒiö)ÃØ !ò½±Oìííu¸¡–Émñ\766–û~iâÜŸcWîýûìÛ©ÎiþR‹'¼‰±1Ýãn/»Ã'<)ao›ÿÙݨýýýOÄcgyåažDÇâKþþÙlÖîÉ”…^Ë/»`Å7sÏ™óI+°2q+æç™‘ 3ÇÜÅd^Ûg¯ª–Šl<‹4ÌLŽŒ›ŽýRɹgû óš:ÉŒ £À£Yw=¥Ô¸(>ãŽa4düX-@·ÀYµÕÈ<¬“ù%†”‡à¬9U9H²H¦´Ð¸ÉüN4¸OøCé`êD¦åðž!)gí)Sç±1?)ÇÆb nK[(EÙþAžL;W¸ ¯Êɘ²ÜæØpžyÅsOå¥K—:p0ë »Z㶸;6ö‘[ÅoÓmÊŠƒŸ[r—|¯6beÞ´ÈlN„Üz_ëE4eÁý,SŽ%Ï …ãúHŽÓÍú´À>ú£?úãlÎâµß¾}{ ³–šàž{¸ÍûÌó`ßg-'°JÄŠáçÚ‘â"9ö8ŠRTÖ\'Ã<ó,ø+ÎúÞLh7¼*m|o$*É¡q1øÅccH÷êêê²pͽ³o:Ïø2v%y¶Å’z†ì"3ñÝííÿc†y¨ÉblÝå°"›c’1wø~º„,Z—ØÜ°:æµQn¸SGJÌɼ¤SäÕq±‹ÒæžR˜9ßïøÆbJĵ.B;.ö¼Icž ÂEãkMôc\½¦`è׿Q»{»g:8êþ8/Ç`0¨í­íº¼}ùÌ#Œ:pPæµÖð©ä¸X}*‹‰ 0—Ó1€eø &þ!Ø7²e-÷,1ìŽ A¨÷¹“Š‘Þ ÿNQúû¥»`'}‹CcX‰†cŠ‘­B-{èI<Š‘N,€_Ꭰ‰ ãí=Úðr¡=¯7›cCücX¿-Z±# S6\ÄNè½ÅŒÒ~‚ß7tÍŸ÷½g‘ÛŠlöÐ!vô>Ïœç7ÈÒG/“´ä•1WÜÜ ‰3 pù¡†PUê/7퀷%¿ìž/*A#ä ÍÊ ÉUHPÕ+êPhs[Éê€Å‘ÄIbä€/½R\·2÷kãB·3³´<™²9,$a–_e³OªþNTàÿX"˜ö «)¼8ào-aìE’ö Ÿ{ÂæÒ,”‰fl1ÿ³Ð‚ /Mäc\“ÌO‚kiiCÇ ës­ÌYË ’F£ÚÝÝ=fvåÍÊR cIôó;bIO ­ªféêÖBàyC¢”:ìT©œ¼'ÁÔ$Êù|^+“•Sá33 ꥗_ª¯¼øåÚX[¯á°ïÐôGœêD¦ªŽæózþ‹ÏÕÑÑQ]}ðj-ÎhÕª^…ìTw]är¢ã É§,Ô¨0²{­6隢±!@¶P°×‰Ýâáçm{bÏE}*ö-Î; e²P” ‚ìcÄŽÞ-dÐÚDzã’ü +¥œ½LìÓöhÝiKû â'æIÆ?‰(i%qæÈÐ çØÐj¿é?dþ±å—Ýq!¶4 Îݪ4Zfu¹ÍÍÍÎ<³sžkËŽLBóÝ‘!ös|’C¥fÜLÇ&‘Hæ?Kf8Ádæ‹ÀY&q™A +QUÇC„Øò¢²¢áv›•·H4œ)&a.1¡c9™s¡àÞ“g⊃[·(¢ðòKh-q+0po¼ÌöÍ·±Ù/º;&®–`¦å¬Üî¬&ë36Ö¨‡âk÷sGGݲ”–VäóÞ4£º¾¾^‡‡‡寬yQ6¬îÂ… Ëj mêóÓz¶Ú]+ÑãiòÒÑ@\fQ:68Óœ`šd éiÇ?†D'‡Æðñ4>\,µ»»ÛAÀØ~ˆí,œÈ•A¼eU2:BŒ-ˆÇ.ØqïFãXÌf³ŽÏž9¼.’3N$B¶X0G8mK€–Yš"ºá[N¬Ì“H¹i¡ÇÄÔiá84ÍD­æK’èN¥aoÌyæ ²Ÿ:ÈØÒÜr'JiýáyÁ¸ƒt2,hš“DŽ%3mœÌìÈ»Œ;SNž‡ù6„b!p‹ ˜L:˜Z†7uÔ§Ói­¬¬,ƒy/:L6…€•Aµ2—µÀyhéÈðß¾7ÙÒŽn?Zº‘ÿ¦…fwVOfA'76M²b ‰€+ æ‘UóÛ$Yd¶†/¥>¾“D“­¬“Þ‚–±ˆ¹[E—b:ÖÍ›7;™$³¹íÌË—j0à,9Ò 4Í´<6N„x1­AÏBÁ8Y•ÌøT/ðæ°˜wfyå”ndŽÍf³ÚÛÛ[Vö w -M•0•=o¬x2ë`zëÔÀU¦³i]}øáŽÇÕ§2ýÑg#Xyø‘úÌþòÌ^?]›íݺu«S`LcÅ“8Ĭçt=X«áJ¸úìB¥í/lOA±Ò{âl6ëÍupeœë÷oCn'Q.¨µxó¿¸`æ Ãò¸FÆ6;2)”`ˆÑI¦ÙæÁ²Ç§"\zºÛ…ò(ÿ¶¾¾¾ŒZ{48îÇF«I¹à¼Ÿ1×› ®…ž\¬$.öï;A¶)s´s"c1$'È$Å$<{æ|zOZõÕ8æ•‘Pn˜Î’ïœUYÓšƒó¶l!ö=æ3c-q²âl‘ùGݳWJ&"´ÀÒð)³j·N ¶Y( ò±©eÛÜ~$«æoYd¬Šf‡x%¿èYQ0Ž’Eˆdå ûÎê ÆOQÍA>Ùç[íC·­ÁQ'ùjÒÓ†¶±HðœÜ1i%BNd^mlŒ=¶ÙUNF'À-ÙÊä^‹ËEÌüãUó¼7ô‰!‘Ê–¾«x$:Ní3ã–}r«Lðô½[Z~]NCÏœàšWæwÊSæôt:­ÅüôÀBƒAÆã>Bìþø6ƒó¿Îc<™Ôp0<“ãEQÌ‰ŠƒmUI˜wÀéŽ ñ môØÇÒÐÒ¡,'‡ØÊ¦éCãŽy‰Ú0G‡k±²×ccÂ,fš”M"“\ö©“¬9à¸Ð­rWZ‚cGwl|ïVç´b-)džî¨X!͉Œ…¢¼µ‘F§æÛƒ0!Ç~)¿œóÆÅJË''RÈóŽØÓ”â#îÝd{w8,¢Å¼KE7'&iDïB.±¡'àž7 -óØXÉ.ÇÆÞOÎ9Žuff©.»™d¹ Öí¾šQJsh<˜ƒ6C¿ …[uæŒvgµ fI~Þ{v[õç™ÌnÙz–2qÆz2›œgE7ó@xÓ½Õ„tã$íŽÊ‹•®¿ jɺ­ÌB`éko|ÞíEæI¤ñµÞ ÒÓØb^®“Z«ü¶7‹øEgîYzšÖ§Õâœó"ºÕjyB^d'ÈÙ‘1ln6›Ã&“ä%ÑЉPKGÝDÃTƒñµù¹Û; êîÁÝSƒr§šä íµ¼–þèü³œÿµ'3£³[€p÷…}Ò>fiìLG&•µpf"âóÀ€ôÍs¥˜˜ÆÎ-ÜÃÃÃc\ä‘gg"ã=z6›-¡eiàÁP3‚}ÎSÌ$®påÜ^r콆Í9b§˜ÈìŽѨ b7ó؃øÃç‰OÅdº>ÖçÝöu{ÐNoŠÜ;/ÃææfGëÛ>5NtÌ­²F=„•+¬³nt«ÉØ’k7ÑËj/pqì 뎌H/rü6ó‰úú™ØÚÚZÎcCù ŸçYìíí-6œdz±…¯ÏVCÏì ýÚ IDAT7Às7\ÍÌܪÓŒõ‰Dô‰éÙIÜg\¬ÃÂFloo+äZUÌû”¥`³²îB/¿ç‘=ÍÅF›Z[]*-­ø‡Ï§=lÒ˜ÐÖ†øÌ@К3¼»»[“ÉdÉeÙØØèx¿¶G1Öñ˜‹•†¾zÇõM&“oÆécgöDŠÔì¹-è<Ÿ7¤{u²0ŸÏkww÷˜¼²‹ê & »3?ÚIš»ÜwzìHÌ36ÀÁˆ›¹wÇÝÄ͆¦™÷NÇÄ´~Ã-÷sg%¶t¢”q±ç¼4CDzÈîæˆ#d,M ÓtŒ´Lœƒy ãnØ8IW‹hŒƒù»wï.ÛH¼Èêòý üÊ7쎋+VE³I×é\›„t2K«zØëÄ‹\HÜͲÏ'›•ÁxÑ =c‘´™–ï=ÉR0–`ÙвÔ9÷ßsoÌ…Ô¨wËÞª$i ™-yKø1ïZÒŒt²Òe ib‹ù¼[þn­ò"óß;à Zmåô‰±·‹ç´qÑæ…Ã=QÒq‚oÕà†+œŠ óþÿëþ賓(gû½eŸ#s1’½“`ž"!%…Xïcv`Ï‚Á8û˜%Ž-Ìâ½ ÜÙã]ìL1¤Dm°'šTí`ÛûXîáɱa¦}™íøÅÁ¸‹†‡»Xi.(¿o!)öèWƒíÁ¿±÷ÎÚJ„,Ïœ^&.ž"òÀõ¸›'Q-/bÄxîæGg'ÐòÊ$عÇ[¶›äÙcÇ3¤šþ‡‰8qM·*E´Ü©cž´àš~gÜüàû(gsĪf-ÄŠ‘NÇ|f oJwúœŒæi˜pÅ€›«:è°¼! ˆ90®|Ûí­pCÇ`¶àS^(ü"ÛÕ/+¿méiW4·$ûçȽ٠%˜L-~‰JòDœùÞxÌá!‰³tuNY¢Ø^&©z–Ü)&+““DÆ!ª5ö²*ccŸ+ž%>Öõ^¦»;&Ã¥l¥au$y<j2L¦#9weË$FËRòÜ-ûM‚ËB“P’´„Õùó‹îäß-÷ápX³ÓÁYTõyLô]š³u‹ÅâÌ¿»‡‡‡Œ¾M%Ù+Z\NÖZ“¶YËÙ'¼Ç³›Ï袩áçþþ´§ð>–çÿ8qqe‚œ!Aöû°áer€̳ºã½ÙoÍBOÞÇ,[%,92öÙ£câ=Üö$aNTØ'é`Œ·|òÜ‘±rª… ÌqÇÆü ¾Û×ð(w{¬*¶¾¾ÞÑ7´ÌÒ‰L®=uÔÓ•—±ÀLÔbi8åDÆøÜlKzF5‹‘Éî¶v*W¸ã±#©5¶˜ó©F—øZ·qà2/ܦEž™DË­S+Õ´î=‘çóùRºš…‹yÇw°¤7:'y¼wV`aƒ¶g"¡«))¹¹ìrögôGœÃwÕ2þV·²z” |ö]ö>šçS™ËòËÖ ÆÿØ‚ÁÁ¶EgN*ÔÚ"Á`’.Ë'{s0î} Áóp8ѵ`Ï'‰CÔ)Ü!´ì‡ÄücÇØ¦±ïÝñ cg÷zâ)!fTËkbK:gÛÛÛx¹áã©ׂ®™'⮄!ž9ï—wÚ8R$Ëpt}­N² 4¢„Ã…^ÆÚ×oîñ‘ã-'2@Ë€,’ˆñÛ!cAà ™ÇîÎXäÊã?ô‚…Ÿ7èÊ»ՃdžÉoãC`6tw ¯:)óÌÌ’—Ì^N¿hLV~oo¯ó€IdZ ÚdÔphÜ®tûѪéðÎõ¡LAPnÒ‹öIS$Wcœ±“•;©sÇ%%ô[û‘X§öcG¢äÖ«=t,]Í„„LgÕ3ý¥K—–‹Ï•…  ]ÆšŠ…lÆÎ/º+vgæEµH„Éì&Áql"ôõ™Ó!x^Xž|m*¢¤,8÷Îõ/å£eOèÝøbËRº’tj£ôÝ™þè³–Ð Ï.Ì,…WR~ÙŠO)¥O±”îzJé!bÏ€4‹NìS66d¯°OŠ•¿œh¸›D×cccc™0` MRdx¿cuNâ'°Ä?Œ1{£ Å­ÞÉ=°±·;p]ìa–ñµX] ïcFeUáçºD&HHŠ=CMâA|òì?äxËümÄÜ=sŒ@ìie½]$w‚LœHü。8ñKBÏ|-†:f7G†kF˾‹àÌqb?Ãî ­®™” «˜çäߘWVãsáÁòÍðöy?:Hò§3CåßFŒ‰ç'«oi'i)eè “I‰=°¬†W È€Ð^$ ³ º[dën™‘ ðoÎLirŽ—…Ç„uîÍbŒ%†Q5¾Ömk¿h&ÎYú:+V„s¢`΋ÛÒ,¢‰ñä%òdwk׊'¾wÚ‹ö‘±²E:ÛMcœ¼À[ššëwµˆ¹b|­ßhéûZ »C(Á•% w!Mìó‹h‘‰”¦Ný{¾ÏÞJö`|Í+ƒwfWàïŒg‰" «=Nt3†Þ>åÂmš^ŸäNÏý›Ìo÷WÆ“”m+ühw Œ< þ!q±5‡¥«PãEgk´ŸHÚ€!ØN²˜I°žÊ£†¾{Ý0m ãÃËÙcIT|ž¹b1×cÓkCÓW0ÿÈÐ| ×kAÇ?üVªù’Dñ¬m¶ÉØzÞ¤P“e¿y§ ­÷÷“乓—=¦³€dj¡¸’mîÖ1ŸwThñ™xìÉjˆÝYÝBJø’Û‡´ÿxøÀdÒ™Ö¿Ѐ^ÕÒ³ö"Ƶ2YÝ¢²Œ[`<4“ÑŽŽŽ:­M·ÇãñòEf¬Òƒ‡ÌÒŠm^0÷÷÷;•!øAL^ëé±CµÆ]ó‹¬xÂõ{왌©¬åŽ8Jª?®Æd"cþNjÈ›äÈõÚ£†n’[™~Qó¼1žl †,ŽÇãåÀ<°¢IBÓ¬ÚÁÂèjŠ¡c–Wöõ[ìEŽëá<Ð1“õ-;iH@D®Àý2§N—?ÄàÞÿú€óäc2×ð~@ÓýqšÞÛ³xŒ†£N"AuÚE%ïcö‚3ÙßE%Cëé<°/X•Œµ<ý@œ¨˜ƒËîk¥ãÂ^eX[¢"¬NÅKÇÅAaëtó-vduP‹¥¢[vLK@°‡{s7ÊbEŒÖFÜElÆþšÐ3öpwÞLKàûÍJÃJʳ«ì/ µiöin•;6±"ÁõØzÞeǘÏf³NG·ÈÖŒ×JÜÍõMãþÓÓ‰’‘HÌEûÐX,É"¯–ˆ˜Ÿ”"ä ©èækã™ëÌX†×/‹ÒXÑʼLˆø¬¹âàç¢ÈðòÙë„`ß*éµÂ"åÝ\ZhI–3)*(¿Âéo­pwT¬ú•ò„$³Ùl â¿=Ýp—Á~J7ºúa÷z`wü=Ý*/š´^©°¸kàJóÂÊ©nÙJî=_dþ–*X*²9Ø÷‹R1îEÎ<`‹ =3,»]Öç'‰teŒ{7¿É‰+a$ÈÜKvâ,½è*ž… I`ƒpÔ¿Óä3sš*ç§1¡GõÁ?üh½ð¹Õ¯ýêU‡‹ùkÚå83±vŸÿï¦þÿNfÆ£Îß¹s§£&–|FÇÀ`Œº°}]•4f6*‚¹ ½ÉÃ`/0™‚›Ù5a1#[k°þçß¼¥ ®¹æ“äßg¶WŒùEŽl ZÆÝ’<’?{z6T+“À­­­cÒÓ†ÁÙ>±ãi=â+3_™6a¡”¶Ñ;1Ž‘H¬¬tŠØNñòo‘À2§-Põ å"­3Zñ ÒÖ¯ìI÷|ú|톾»ˆÎ÷ÅåD'»$JŽ›ó2wÊŠ´¦At’‚Ô„¹¤ò—_–” 6¼*1¢påÞ™¥+çéÓBGÇ/žÛUµìjðý,Æ :‹wEÄX“ä[ð¬lÝ:Qq5‡Ý0¿èphrìZîô–¦æ^³+Ádr0oÝuCÏxÑÓ4ÉÒÓ†OYKœN€µÄSB˜j’á`V%ƒGc}úô‘áEOÅW{L6³h„7ë¨{!ÈN ÇÂQ>ßrL6äЕ,æ /öúúúò~,ùiÙnwA­Ú‘$Kwl8O‹ä© о‰Xy8Ôç_Ø­ö?ÿ·µ½¹YÃѽ ÑåÍ‹õþ÷¾·ýªþ¦°¯q.Ñ'g6Õ'4ßúœ¾uëV'f±L®-Øç^îø&92ülßàb¦UÏl#`[˜i`w÷äCZæ{ã>¼±Ï¿X,–ÆÒYð#€&ö£ccëó§SÚê]ÛÜÃmc@Ü ¨Ÿ¥i&ãqïîvq-t«\ôv|“^(ÞãÝQ2g'y$†î›’A@1ÔÒÛi¨™F«Ž‹³ÈíEÆ¥@ÃàÝX¨ÀErÆÆòÉÜ»é&N"IþˆXºú$´ó”g—B Žeݱ1ôÌϳ“Ì8‘1‹L ªf'á7Y™Ë0Ëè’µ[}*uÖÕs -3;C°l½2à@è,?H7©…åû“+á{w×áðð°&“É1éÆtýM¤3W*ˆ 0[{À«¸84þ}gáÙZõB`Å8/𞦹wTÉ’Gb£±Cý"šÅàÖ0ZŸÆ«ú¹Û1Ù‹¤[öö>J£V+ùyÞÚd–ya¥? d°ZI‡*„½™róô‹Ì¼¥e8'›£¹eÃáðô„!ß$Ìl0Ôh8¬­ÍKõc?ôt=ðÐcu÷îAýÉŸ}º~烿[¿öµV7·ïwðî}iË*»j‡³YÕbQÃáàþ9`”‹šÍ«jQ++j:=¬ÅýÎÈ…••:Z,jvÿ=†5OºÝÆû]Ö –ßµ¬ä 5YY¹×=j0ÖÁôà•遲Z,z„>;]÷·X,Î4ÌŒ{888XVu“ËÉ>•îõÞgÒk…uÛÈ„¥€UWÍÕ„çA|de.¤Yù¶¡¦<+Þ£0šÃb‰aâÎ; u±ÒÃƽ³§qÞ„vïˆOZçÓ ÅI¢y©ð`-!lwyŠ‘ü½UÍØãÍqiÉ'[¬ÇÏïglì£ÇغHm4ãb+w9‘1ôÌj½É!æ¿mýaåSóT^vàøÈ²Þ™3,Gìȳô¼²¢¯çß9Çݼ3NòLwY&3œàaS°º+ëd†™9ò¢ð°©Ø'æððp©*Æ¿¥2–!Bþ~Š)·´L†£cC mu*wT–-i YÑÂ5-@C| òy²£iéE&›[—&¼»£ÝšDBËf£Xb• ®ÝD@’s`r2»ÚcdKÞ×­^ËZf‚Û‚–™¨·¶¶V«««Ë…‹=R:Æ÷ÓV&ا­ Ì‘N]Ê~»#”†šNêZCÆÉÝ$6'¼¨[ )XšÚ$ÉVòO'„Ѱ8c-ï|ª`f5øeË âpXloÕÕ¬E-j1Z©¿|ö³uk÷zŽ/ÖìÃõâ—¿T³Ùa]}`«ž~ï{jûÊÕûÏtX/|ååúÈG?Rû{7j4Öc]ö§Ÿ¨ÙôN=öð•z柩Éê¥VÕW¯ß©ßûà?«Ÿù¡ª?úä§ëË/<_?õô÷×ëßúÎúÌ矯~ôÃ5;¼[ïüî·Õ`ñ ¦ûÛ©†÷¤øþøN%OgÝ0s:v¬ŸŽo°²Žy­?‰B@HÑ dA&*‰ °ò•íwF@éwÚ\NïÑúüýܸ>’8’ †@¨ÌU ëÀÞsxx¸¼6âsxs`\¥w Ày8Û“Éd?Sqïü={4×K!ÖðnÃÁ] wW‚çn¯9dž–W¶-‰M­8±Ï ó†óVëeNRÈM²¿‹ÌŒ-²Û|Þ…Z«Ý1öÉO²c—Ðz“û¹7ÆÂÄžNt\'þ¡Èl¤ãïøÈ9×nË’ÈšÃA=kÂ:?ÊE‘]‘ôX™"» l††Y1Í«–¹ÕiR¸ýDH.p²ýBÌ‘!û³;Ñ”Wvf |Êð0®5•ÁN2>ôó"FÅ‚ 5Ø­[·:DCŸ·×‰»MæÀ¸}Gkµ%„çÁwºk`Œ*/r>[`«’1¯xÑÝq±4dfíðDr°?5ã!ó;¥¢AèEÌÜ)ZêTðí±cü,÷ÂØZmÎþAŒ-s–$΀4œ24Îï ¥§Ù x6$°ö™ñX¬¯¯ŸšPiæo%¸^,è°.êî݃:šMk¼²R/}}¿^úÊsõö·¾©Þý®¿]7§ƒúßç·kçzUU}í»õÛ¿û¯jó ž~Ï{êíoG]ßݯ££iݺ}Pÿâ¿[££Ûõw~àÝõŽw|ÝžÕÝ;·kãÒJ½t}¯¾þò×j8Ô­Û³zñ…çê/>÷™ªÙQͫꥯ½\G‹ªÑ¸5¨ßÿð¿«ÿçC¬7\{°ÞùÎw×W¾q«þûÿá¿«ÅÁí 5›ÍkoïVýÖÿùÁzüÊÅú¹ŸúɺüðëêsϽX¿ý/«¿º]ï}÷{ês/|­>õg¯ÁwJä9Ñýq^af³¨–éµ­á]웨K±×`ÜÌúÚ‚@›ë^)6}4×¢›Nb¾ƒ}"•KÙ³èÈ8˜§àgùee­êJ"åDLjîŸÂ0Á¼mˆËˆoŒsž}Ö~!ÄV¶øHSÈ–-ˆáÜiJlh4c]ø×;éˆ æn™ã9‚y`KÝé#næÞ) [D«¥†ç5$‰¿a^p½Ž_ŒÖq|DRCüã¿7?‰Â1¾»Yö™1¥ÃïAŠdD{à~ÉLGql•"_˜/„‰Í A¢=IÆ”ê´$gíeÆT:ë>ÅdFÃä Øå{]YÏŠJ€œÐ2ºVl󀦖8ª )ßL•‚ Gåž`<'{â ¯å»ñºa¼jÒ·‰„ÖAÏ$ÍÕIJ£â–¼«L6þÍÊà(Ÿµtµa{¹ &ãN E$¬ŠfhWÊ:a4$¬>‰t¶õø@Íêî­½š ¨—^þz½í©7U µ³w«þìÏÿ´~ö‡ÿN½å{ ªæõÔÞ\ÿãÿòOëßü›ß«ÿé_¬ܻƷ¾ñÑú÷½ÿÞû½Ô?ÿàoÖûÞþ]õþþ±ªÁ°ž|êoÕ¿øÔtÿK}ôܧçží„˜À‰ Ì\OÇ.vYÀ>NGÇ"ãùøóVµú¦9¾V]Mè™/ü¾÷!›js=NTÜU0´Ìms€_Yð§Å#q7ËêUÉŸvAèVÊ/»Ûå±á·(¡ØçDÅ +ñOÆÜ/ü '2æ°$OÖb†Ÿ·îÝŠo©zæ"?›{¸“@îygÊ…Ñ.ö0´ˆ„ãV¾øÃйF6n‰Ð9Ån¤?P>wóê ç´øEò”4' r¢CƒÀrÔÇ’Þq`ÏŠn¿Ä\ã(ý@œØÁ=IM([û%ø r°ox•yÉñ‹dÕŽ20Ð:ìt²Ü¶¦5ê$®Eê¶2—]¿uEÃÔ\¥ç˜S®†ß7aÌ“Ùîó¼Héˆì`õTW.TÕ >þ©O×—¾ø\ÍîϹé[µ¿·[Uƒº¼µQà Ûõ[øWõÈÃ×c=ZO>ñT Ç㺸:©­Ë×êü×õøµÇêÚµGëÉ'^_+«kUƒª7>ùT}å¹×|^õ©Ïüy½ù©ÇêË×êË_z¶®½i»^zé‹õô÷þðýêçÝšܨ‡}¢ï ö•ÍÕÚºrµ¾ðåçª÷ñÜ‹y½íMo©éá¬óyM‡uãë/ÔÕï}-ƒšÏjí¤¸r¥¾ºÿÂw*Ôýñm¼¼gv±Ö¦KчµÖ^p-áâ“ôü2_Ò…”_NT… jöÑË=ØÁ¸žÊ»,æòQùçZOòÈáZíCüB"’\K[¿šh û”Ŭèf›Ãêxn®éjðlÿÐá³Þ'ùÎ,Ð>Õâ™ÿcUVæ ÷îDÅ…Vw(Ø£‰{ͽrkn–Õ~9O Ÿ;–®6d1Ucýû>ÜñHèóÊ…X¿S zü\=§­è–ñ cc~sÞï”sb˦ÏLKF—J¬Ÿ³æl¯ï‹¶¼ ­È£££ŽûjbHÝu"déY¿Èž¬öûðd÷ùVficEóƒœ%â$C'C„LƧ£cwúøCÆUÒ϶1É ­U^,Λgâ ‡µÂ³ÚbŽŽ2CÃ_Ï=÷\}òÏ¿6/þAýý_ø¥ºxi£~ù?ùÙúü³Ï׳_x¶>õ¡?¬µ•?¨_øÙŸ«­®«W¶ëO>v½nÝšÖË/}©~î}?YwÆ7êSŸûxm?öÝua0«Í­í{ïb-j<ÜsI×}­¬¬Öí9‰ñ°ª5ž¬Ôà>ÌnQU5?ªñx´ä% Uãñ+ÊA¯ÐýñmÃÁ°#¨Ce” ÅHUìaYp3‰Ùªdt\,¸cdÀh4êtà*¤Œ¿ ¼P·:2®l³.r}FÓøóþ~{ÅŠp·ÉçmøíB«á_TÖ /2²À>2¨’eübÁŸ$룘檾¡a†ž¥PÐ1£Üqq’hYnLJK˜W ŽiHNLbÞ•!‡.Äl!~Sd7OÖpHwM# S—Fª-E ó.j;¶t§ŽÏØÈÕpK«ó].ö2§'ç n0ØXÔt¿s~ÏŽqf¨¾sA-UÚ\&.›CcõwÈ,¢wíö¢1žt‹ø7nŠÿYfŽÉÈ߃ÚÚÚêHâ9Q²º×”ê n’I[^9o§Óé²òÎÃgÜXļÚ‰§Evs"C@Ë‹¼··×! nmmu&·•4Ì´Ò‹(ãÏBÁ³6N$A½ßlæåa</¯?_d`®ÇøW:®ÖÐR·Ï‹}k\ér§Ð™¶˜ÿ16Œ/I¦‰„<[ c–ovÛÜI²ÔT\x–Né†îhÅCI„œÀܽ{v}f/’ÚWª­ãúø'þ¸Þõöïª÷ÿݬ7¿ùÍõä러ÁhRƒZ,»?ë/Ô»¾ï{ê—~þïÕ?ùÕÿ¢‡õÙ¿øx G£º¸ºRßûÝßU¿ð÷~ºþË_ûµZݺVŸù‹OÞ{w6׫Fë³ùl­ëÁ«Ô_ÿd½øõ½ú³ÏÕc]­‹—îAVVWVj:ÕÁ] —U³£ª½—ëKUÃQ+Ÿ«ÉxP+k›µ¿«Ðc>šWݼ¹÷Š‚TôG3û¶ŽÑxÔé P9mT{¸»óv¡:ÌžF±’ï³z¨8"¶P`Ÿ4´‹}Ä\Kö1‚k|`øûäŠ^¿~}òZº··wÌ+%mBd´ ˆîø‹nÅFÆÍhsˆI²2 dÿ³b›QŽÝöÍc¨ wÓÒcÇÄHSsmé/DŒàc1(b; eNZ¨qM‘7‹‘Ärݱiñ£‰5ˆ{¸kb~Š‹àp„P 3÷Üߟ±«ã3Ÿ'î# D ÀI‰»Uø=/(rŸè3c9W+W$„ÌÓ²…1=<<\>›q¦ËyÓ)?˜Ê&t¥ƒ©=p¸6+:ÙÝ\cHÝÅ0©ÉôÉó°{,c³¶¶¶L”P~£jŽŒ+ëü©áSV sVž/º³n)2vVE³#²á&ññúÞ;æÍiêÌ|³î¶HìƒAÕ…µKõò7nÔõo|£ŽjPŸ}ö‹õâ—¿Poyäm5 êÆÎÍzùåëÁ+WjeåBÝØ»]³ÙA­®­Õ­Û‡õÜsŸ©‡ºZ.¬Öþ탚Ô… ÷ñÍõºöÈëê#ÿîßÖµ‡¶jpáR=võR V6êO>ñ‘ú¾·½±VVVëh±¨Ë[ëõøão®û‘×ÓO?S“Õ‹õéϺnï¼\?õ“?rï®AÈ j2ªzû÷¼³þô/>Q?òX]ÚØ®/¾øµzé«/Öªþ¾?úãTtSÏxvÍZNœ¨Œ„_y­7DdÅJKí»{N"c™]Ç7ìS¹G·Œ¡ÓÇŽ=Ö{þÝ»w—@ŠÙk@]ä>åDÌB#£. O7k w-@„–gd‚cWö)‚S$vc|w;þà™: ÎŽ‹“ =¥Ç 92j3>J,×c4ã êb2™,!‹Ù0¼ÜH(æ…i nv—öŽíób@Ç?ü~v³ÜÉKÙnð=¶'qÇ Y$ɳ"n*Þ®é"î8;.ù"š¬f >~´…w#quB•5¥ÝLŒáW-Õ2«;yCêŽá6~ù®–;½+&Iä3ÄŠo¼”È+síðƒ<=ygf‚¹õ:™L:U}C¿R ÜI¢PWÒʓݭáÄ¿òÜŒÃ1aÝjvv®5¡Ý÷–®& lág »3DJ“Éln‘»íÌØðù”åvEÃ÷Êõ1nÌ+oX'µìYÄ\ Á5dÑø\Þ9Wc\}IékÃ=Ýò?Uñ·p)÷ÔËî.½^ºÇ¬~â‡~¤>ô¡ß«çþ·ß¨ &õºk×êÚ£¯[®c·îÔ}ôcu4åÝ:ª·<ùºzêÍo¯ý;Óúÿý'ëèàþB¿8ª'®=\oùžï¿·¾LFµ¶¾^7övë'žþ¾š/µvaPë—®ë_úL=zõ¡Z U‹E­^×>ót}èþ°~ã·ÿe ‡£š õcÏ<]¯{ãÛêèhVóùý™ËE-ê=ïx[ýßû7ê·>ðÔÊʤ{äáº|ùrí|íúkÖ ëSžW¼¦™gØgÆ\öDi8ÏZJÌ“æ|$"ÄGUæa°Ì› ÁZž1€÷`K; LûŠäà¸àæ}4•A oíc.Vº˜iž¬%†]Ð3µ¥Hë}ÌŸOû žß· NÕ+<¾Ÿ`;ã>ãBqòDL;àû,èã=ÞBQÌ ú˜ã’bEŽXpïYäv!7)Ĉd9 7GÆIÏ*Ý,]ügæ•E'ì³g°ŒH$ÓGÏÜsÇvæÀðo©6g~3Åc>3Î`ÁAºrž„t*熱˜<ŸÊ\”9.Æ|Ò:%1ØÜÜìLfV>chZŠCêdÄ [NÙ†ÌÖã‘®½V–HÃLŒ}˜ žŒ,2é\ën“¡ápX»»»% ·6}ï'yìøE·b ß— …ǦEø2QаºÄ[bزÔN€Ñlé¤[¾˜—E`<×ÎÎN§z~–¿¡mÌýµäM”w¢Äï“@ÒÒw•.o¯¥¢ã¶³»MNd gÌŽŒ/ÆE3/ÜYëÀòNapñÍ$2O^Û¨_ÿ¯½Æ£ñ±n±XÔ^wµžøG¿R ½/‹Åâ^̵XÔcÄïÁ!ñ@´ÆE-C– ½g/qÇÆ…^+oÙ'ÐsÈ]’8Ç?)lB>¨ ö" 9ÁMjy™p}öŠ³Ù§Ï›çš±ã>Ÿ±_š­{ßL1ûô‡ïÍÚÚÚ2‘±¡¦ –FM˜[¹«ÅÆäV7ÛѾ1 ¹îþãCã±÷Ød¡–¸ÚI¤9?Ć|_¢u8ïns:‹I¹ ¹aïHÏù–˜Øc03^t·VÝ>$ˆ´ =pÀ1 ìΉ× NÒ×ÃËÀ÷ïïïƒZŒx”MŒ»4¬ÎÊŒ‹¹N–DMÏI ÷ÎÁÏ ‘ó$ÈÙ©3äаdæ…UH,7Á «|l nÙ³ÁXÒ“Äí}®¥@“,9ç¶2ŸOØù7T O•ÏÌ·´MÆ“Wý›ñhT5øùñ ç–¸ïWùîÑpX#Í¡åï} oXœ @>œDé_û¨½?NWuV}fÔH>#•u?Õ FH轋‘†@ÑÂ{{8±•+÷޶··;{¨ãïáÉÁa´WÜb±¨ÝÝÝÎ>fžIUƒO¥¿oyhûä16ìÿöCv—¦ˆîJX¨ÀÈ[,°÷¹ ç=–ÄˈP†K™ƒlž‰;>†~¾²²Ò1·"-û°mI|ït˵,\85t x•¥ˆ“×eE“ùy–bcpî“;‡téñy®±۹˂乻MîØXµ 8§ß)«ýR<°@F«;=v;ÍÆ‡®¬ó"Ì»Íc˜»LF¿)ìÍ7iȉ’IE®(øE$“µá¦yy6¤ô"–8GÈlöB1ÿÇI }^2^D( ?|·SU#}dr2’ x‘zµ¶³'„'³ØV0Î8zsEƒï‚#“øYi;*sí®”ÙÝ•×ε´ì Yô"×J€_K™úû$ìNîm›²–|¿Mf+$Ó óŽ…„Í•{3n›Š†?ï ÂUD~ÿâÅ‹5¿3;u0³¾ãÐýq¦2™3,Hñ š€Ó.ä&¬sÞ£V1Ó] C|ܱÌžjyc¥HŽÒ¯,áO.˜¹òí`Ý1®Ý] ùŽí¼:ϵÛ±YÆ7áåþ¼;:îf™ÐN1“êgFxl J*÷F>$tÌH‡,VN§Ó¤ÉÁ>ÅL®ŽcÃô2ôÍ¿oøqdv“@¬¸“g¼ÇÕÇÍ$Ä ‰æ±j«9Æø¼8Á6‡†¸ÛI"óÎpM«¸y^á½dh~ÚS$G˜±q<»Lfh¿qÑéuB°m^DrÜ‘æâLÖ«Õ§²ãâ¿OÒ“ãÀ›¬S^>bžFBÇlè”P«rð@ðûà~Qãß8o¬ŸÛ,‚$6À£ìànˆmg®Émkw ,ßü \fÑi?š?DµÅ²Ùœ7tÌB ™h8IÓ#Xw%ìüêÙme“Ù¬5žçmDæyÇ}ó¢yÂ;«·â÷À"cŒ¨¥´môêÍ-auŒMò‡¼È¥¿!‡nyûüIÒŽðÊlNÅ|÷´I3¿†p™þèþøÖŽ×„£ó¼þZtº ì¥N$’¯huMsQe­µá¥ µ >ø<ÅF ³XÊêž6½æœÕ5½±’ÆÑÈ‚›ý>¸wïc)øC0LÌD:}ö û?éÞòÞÝu ¸h´Ža}샖 v‘;¡õV[z“È´š$α1çÍNž ñ“4Ï«ùrh/KSÏçó%å‰DÂËÓGÆïl±ºÆØ;.vÜêøÈ(-ÆÝd}’@'à­BnÅ›7æwº‰ç<±ŸÅŒ”·^~Zd®œ'üi:.'°UË î˜÷Afi‰<Õœu‡ÃÚÙÙiº³2ÁL†c!2$É­Ó„oqÞ]&cK!*VÝmGiþ» žŒœ£š“:è|Þmeîˆ gκV—ªdé;Bׂ…xɉzÆ›ÌoX™ý‰ŒƒäóÆxÚðÉζü­=nH}lnnvd|ÞݬtDn©~Z–Ò,b<;“4­fçN^k‘sµ§%Ëm<ª9k|ÞÕ{ì°úp‚;úD¦O¦ú€»?Îå{Âzœ¤hŠhæ‰PÈr¡6 ïöôÊ`Ü2º8­"æb¤ma`Hñû.k=HŒ­­­Na˜Ž‹Zï»ÙÑ1m€@ÒÁT³OLr=ÍepÜîòì©N¤ïÝÝÝŽŠãÖÖVÇ{Ž=Ú¢8¾vshðšs0¿»»{¬k‘ãDEp•áøÈÞE;î-Õx™|7ßE°Î½rïÌ_£uàÀ0ÿp=ÄG–õvÜ»¾¾ÞQJu<…¢ ˳!¨“NøQVdNÛ0“"9Ϻ†›'éohZ€ýuf4^ŵ*]*)#çUV²£â`š`ÛHÙÎ÷öö:•z²rþ~oo¯“È NåÝ÷›#!:2NÌI?ãìC“2rþÿ³…Ƹ3™}mðrïüßà= ŒqÞcϽ;@†gÂâáÏ»"BK4¥¬»ÛÅB`ÙK“$ý¹Zãn¿mLgV¨8pfò{~‘™NêÀx’L9Q±ªŸq‚Íõ¹eŸ‹ ;y(ž´ÔòÜÍò›bl î踋ÉüœN§uûÖíSã3Ó›@öGœÑ¤àŒ¾»îüStcoµEq…áQ 7ò€Bi ú°V³Ç:>1?'EiR&׍Р8Ùç¶··;&“>ïbhU- rNd\ðc´º&1±í-y@¢Ãx[zÚîðYv"âÕ‰ƒ]Ò]§K~ön±½Dë¼ÅR6<kÝí²¤¹›æ[ÊŠ¶ÌCÓ ·ëØÝ5áQ®H¤±ÛD~ÑÝ~ä29\Ñ ‚LPf ©‹ «ç®G:Ó¦¼ +5n?º²)ÉÄÁ4“-9cùxÑÉFý2{ó‹åöŸ1¢Œ„.WR™ÂYªM#½Pxì­ßíÉØ’f´âØbõhÛ·Ý&96O“,;žÛÊÖïoU,– èb~š"¢¾+Ò}'álf3gzN€&a°× û »"æB ¸èD|ãøÈ]„ô‰É‚œã›”ÉeNãA=³GØÓÈ„ä[ðÇ¢2æG³™ÐnuÎ Xù<×B|D‡{÷†g™?ÄØ›çáøžkª’Q@4<ŠØÐ´âVbÇŽ¶P°ŒcOëlø±£ï"?I’;$Ù $nµjãìø…ÃpÉìØ&Æc—h'°Äf-hYJš3¶æ{^åØóS,§HmïJ(ŽqÇ™È8ókq øR0 ³Ù¬&“É1/²^‚6»¯¦»+Êž¬d–\,­Ug¶¾>·/y n›¦ô"I/"‹_DªŒ_¸p¡“9šË8F:6¼X–žvEÁ¿o èx<îx©´aLFë´[ùÂcG’éN+´Nù{ë¨'GÆò‚ni»m̪dé”óÆŠméä8ò…þþRð¸ë>éó<7(–Q¬$10ÄÙR°É…`oò>FÁÍÅÎìä>fŽ0{<ÿ·ev¹^Š™Lso©,JŒâDÉð){¡P3aÝñ÷x|—‹™†‡{ì ÛŸN§4M*Þ26Ü7ÅB­VtKÃJC”¸':ü!O‘sˆ)FòÝæ‰ØìsÂÜ*~{{{9§ñ¡ñ‹jè‹(ãÆù\dÝñáEOž–¤'‰Nv³øû4ó¤"a3Pov$q,âûûûË"€fÖûýñí¯?謾»ó£yÇ𛀕=Ì1BHæ_̧r–#샬ÕF&xßsÀ 4Þ•pöAöpó<(ŠBí}ˆø‰äÍ] ö¡,ÈÙØÐ…^ö>£H’Øéj0¶¦ÝmâÚ¶··;ˆ íü›i.§GErhü>6)†ä=ܨ ä—‰)ŒêMã":†™+™?ˆ˜›uëÖ­Ž';6Ž­ø{îy()œ:ï+Žý[£:ì³Ç¼r¼äظÚ]#ˆéT¥ý 2Gú ÙßÇsšçʵ‘gøÞ:ov©@àŠ‰€O6* i dÇSKüÐòÝ®xXbØŒD%qŒ|’²oݺÕáq'É‹ÌwsÞQ“éHòê¨à1ÃÄ0¿È†J–nLU1ó$R¹+ÛÂ$BƾäDÉÕ& 8ã‰]©Jè™UÓXØø}W,Ì1†” Âmc9Ú¼tVƒq'ŽïbK#1«ÍðܘG™ºÛä–½9æ$nÑ~6^ˆØ ÜÍ¢ÒeùB·ì] 2쮪«¤c›ušäÍÓfžÌ»K—.º0¤®û£?úwç¯ã8š¿4±Ç»fœØ§¬ðd€ªêÈäZlˆN{83ËìgÀ˜^n`_„#ã}„`Ø7ö9‚B<O’(&ž³ÇNš‰ÚÝÞ ¾w{¢¹mihö%[(d’Èç“'µf"ÄçM°'XÏï7­À$sˆSˆÁÁ|ÂËá•ÛÚþ4×¢…wÊÏ))îˆ#ëqmžÓ©“Îw ”²ÜN”˜»öà!Qá=­“@ÇOÜ;ïÅswAݼpAždˆÏÚ²¥Kf뇟HVÖ™¬ ƒ11ÇXACŒÜf"‘ἃõ–:ƒý<ÜZ5ËZå~0ºÛcÓ"KG›ôÍJiiZ«‰%LÅc<ݵHžGþ¾!DŒÑòˆL6„Ü­rÖì$ÎÁ¶ÝYÄÑ–6 ’EÔøXKìÙÇ“­rË;»=H’×â'YÞ°Õѱ#²7/’ž7œOì±…œhÜ»óÈØÙ$Í/š=xœ„%ì.92¼SÆ›€šŽÆ‘ òhiÈeñàÎAˆõAá¹éVôÏõ¯flƒAÕâì^¿áSô–A¤ä>D|Cõ¸µ‡£$qÙ‰„‘ \SKUÕ]…–*«¹£N$Zfçæ*ØG†½Ñ2¾ -Kkö©Tß´2hò‡œ¸ÞMÇ$i.J[Íȃ„ûÚLo%¨é^ϬsÐq1Åd~:n6ô+½Þ÷ÒÍrŒà¢²¡ïtLZðqЧ.à3¯mé`\ž»?ŸKOÛðÒü›¥3vÎ <¯ =sǽÉdik7Gˆý\$ïH3Ÿ¤d©B»³ÚðÉY³³pÚH šÑÖÓ&£EKÜ­Õ” 64Í)ƒâЉƒyOf{»ä"E«‘EÊ/šaw“ɤÓ"›N§uñâÅÎØ¹k†OdÍ& “èðßTœ1-Z¿©犉ƒûĸ£BÖ tÌ …_4Cïü¢¿šÑ)mÞ:`²¦ c™Ü*KZÜ*WkÜzå·ÜµàYûE#ÑKH¢d/4V££ílB&]L'QNÒZÞ®Ž¸e^UK~çP‚Ôa‡c“œ¡þèþèó–ôSAvòbÈŒIÕéÇáê1û…ÜÜgpŽmLîSØO8æHèÚÖÖVG<‰TÆË&¼»›ä‚™y TͤT9çZ3‰cçÚŸXž™ÃŠjÜ» ¼www—ññ“»MöÁ#`6bÅ<Žô¡1üÉ<`r‰oˆe³ÀŸ"UJHn ®mKœT±Çs½ÿXŠÀ¢Ü›U˲[eÃð„¯3o™7©Zæ$ŽŽ ±±ŸÇÖ†âæµ ¹ZªªÚÙÙé(°·2æVÅu¬3c’U;ÜÕ°„0™¥Vn‚D$eâì ÃY>ÐíC¿È)1ìœý@œøzÆdeKÃ(“š8Ïq5† ”$ÏD=+oµª)~1[P/šhÔ»µé “±‚Ü{¶…ý,L–KRU&ót:í\?Ð4Ofë–[FšÑÕ;,Ÿœð*c'–½4ÿü+ãåEÎc“=Ï2ÑÙÜÜìBѰç;˜—àbí#C"äÖ¨;tËœôúA, •pl"ën—Í:M0å;,9î±Fu¨gòZWH/]ºTû7÷kc}ãTUóûãoNÀÝ?×ïà¸Ö jPµ·¿wo>ƒ­ŠnF&xŸ±}A™çP*,¥ØÄe‹Ú°NF£¥_ˆÏÓ­­­ÎÚŽ={ºm€XÛd’ ˜Ä,‹Ú'¸c“ÅH‹%Ñ1!Ñ!6´z¦ tRyÔ†ã$yÄPX(ßqo¶æ Öij JB=ð+ög-¾ßÝ,ó§]7tX]ªººdTF‹ðnâæäW· [Ì;û&YßñO&‰NˆÉ,´À÷søÞ ŵ¹ÛEÜl!(ÃâHù-{ÔÇtbCMÔìr]Ç’·ØlüCVï€5%ŠíâéÉY½uÊ™¦ƒ©[³–‰sWÃɂۗÀ£@ëi·üB,£K·ÉíCºUžÌÀ§LèJ?Ð| κ}íæI0ÜvnIèúEGÅøW+s¥Ø€›BÚ#Ç÷nœdz©¸ÛåŽS,1ìjÍ<’hO'°UuÌñØ“Ýç }3$‘Öª5îÓcÇ/²¡e ›#Aæz9o’¥e/­Ïϼc±M¸çIÅ/’v4¶’ Þ=§"Y,õøc׳Ï>[<ð@gCîþèÓyÌæuýÆõzâuOœ*1‘oöp|AÁB™Å²Ý=÷ZM°nd‚MtÙËu™`›uÏÝuû‰Ø>‹™®¼Ã!1À#ÐÂF]¿x7„š=ÜÐ4¬p,4àBmú$êd¬%‚©Üûï}qïŽ «³;Vm5ÙŸyÁnx×ÆØ¦Xñ‹ Éæq½îØðù“($‘F÷òÇŽtTÌ+q7ªª:…àl86L1H'îÝÐ4c?‹!™rÁo'œÓjÀ,¤`1±¡ßéfg&'#ÊþRëëë€$ÛHtd<™Ýäû-㛇 (Mz²:–“ÈDÎþh­2@€–ÕkMf«’ñðü"Ú˜±£bá¶µ«=®X$á«Å‘aäEõØ{弫MžŒ,B^d™ŒîÄ‘¨ !ÏožtíM#Uë ßjG¾ˆ$^DÓ‡†ŠF ¶çjNó9/˜6(+Ù€ŸMùåôpëÔøØ”¥LÇcs¯Àßr/Nþ-ééN%‹P cjüîüèt ‹Å¢ÖV×êÚ£×jz8í+èýÑg! ëÚµk5Mj¾˜ŸIØ™Iù@kZ~i.VZ5•‚š÷!ÃŒùþô‰a-¶a¦!@†¼±ÇG$™ß‚yCëM¨àø0{¼÷X£q(¨%G؈ÇOì¡.ØùÞÌ›G뀴%v”6®ÌÛÇïçÚy®Œs ¸ÐjwzÆÊBMæ™RíE7«ËùûÙã »šFñ3=t€g%O„ï£ÍßÄ¥¿ãã±izÛ°ÒÇ?N¢ˆOèr¶ÄŒìGé¸X]Â5=o|~¿“ðòÎ%?h™Ì˜¸ ¤ÊY1m wd\¹Nå sdÌó°ZƒÛ‹“ɤvww—74›Íjkkk9™³ãCÐiU2gå¼,æ8QáEwk±e ÙÂÇ’$9àt0MgÉÞ4³âÞ=vö™1—‚{7v±7ÿÈ Šo©ÃîJ×Êy/Ú®Ö¨0/òEµÐ;mŒµU5æÝ66¤ŒUÀvvv:›­SÆ+[«‰Ãô¼s[™J–ÕôØà,BÁ¼6öØ‰Ž•þŒ5Ùë]__ï@ÏÌ¡1¤ÑÞJÆË:‰£cì1óŽ÷ |í`885 %s°?ú£?Nÿ±X,jQ‹3›ÈØ”™ Œ  ޝ+÷ìc$2¬ÅæjŽÇãeÐå u?ý>Ø+XÇ)ø9 Zf±¼ Ø/RõÕ†àœÉådÏ&˜OD ¿E¢Ab`虃m¾Ÿ}ÈEn7­JÆØ»hmå­ñxÜ‘(fl™“p·,y"¦¸ÛDügU2L±“ìo‹3Ó½Þ5:"tÝö¼HØœy ð‡8ïøˆyi.»ý‹ŽŽŽjoooù¬y¶Fûß³9îµÇ qº…˜ZbIÜk±’ÜÛ{ÒdbG…c;’{ÓK2îítfĬ|E‹ÉšN;Ê7B"ÄßÛØÐX@‚u0¢|RKìù¦ü¢R‘ðdv¢ôl2™Ôt:í`ýH” Cc²»Ä€ó°S~Ù„ñ΋”' _«yÜ»!E¾7’…lͺeG[›±qE£õ2ðì¯ä˜;Eȳd2ÚåÖ©+],rù"³ÀÐrwõ†{£»ö˜ßKl² /é†YuíÙtNžŠe»¹w’@¿OëÕ°8W[lÄêjÇÖzû¼Èn “Y’“ ¢ßÒéGýÑýÑÕ>b  IDAT»!Jö12 ùŒ üyâö+o¥è „vdžžáç"XÂÃ]È%0T-¹œÞçìgb›€D´p¿îØPöw¥òiª²¾í}É„xøCüÖh4êÄ?æðßÄOÄg&ĺFnn•»Qüñ’´‹?ØcÇ÷š´Û’8Á¶ PÚK˜ïDüdÙo’qÇýÄÄîÈØŸ[©:¶$&§ÃHüä˜wÊxǹ‘°l6ï™á–Ç’™”ù%k梬ÁDpEƒ6‡+nù˜«`†Ô-6·ÿ¬ÚÁyËØ&×Á†SnÑžKR“`5UÏHg³YçE% Mh™ƒo+QYouTxÑü@MÈb²„¯»Q\;“íÎ;Ë– <žµÍ°Üeò§qvlœu[Í%}d’0æŠóÌò6UòäösO¤`®‡Eοï*+i-Å7o&YÒv¶ƒ7æ•ᘜg<¼yf§ÎpƸÍFím0^»ØG4ýÑýq.›Z³V³6gå=•½@¸ûž2ÿŽÜp±0 vls=þÙ¿ŸÐ3ëÌ1ή„ãb;‚T r.¤+áQh_¼´@°…‚…¤ÜqqÇ„€=Ü]‘•••N±Ò]›>qB¡ððð°VWW;‰ çm±`ø¹Ñ>iíA±1¡õŒ]Þ›»YNpyÎŽ ]„÷ïqíP*ˆ»Id˜7”[1Îó‚B¬çiæedž{!n6G˜„‹ÕÉ»ç±_xJ·ÈŒ“´<¡V«’9±àELž/ªIÛžìv—ç}SyÖÆf2ríTÆMæO|,“É~^„Œu°M0n3­œ¬®8˜çAÒf³NZl~)¡çEÊîô~\mq’gžÈ«iÈ;¥âÀycHq¶54Ÿ»]×××;‰JÊ^Ò6¶ÚŠý‡¬8⬗)ç•;u†$Bð$±W c Ñà ,­×|í@œ†™ ó‹Lµ„w Ùoo¾)혆™–üLïÁÃýƒ>¢éþès{TUáB¬!ÊFUP¨uõ؈àU†Q=fHT†ýÖbṵ̂;`u¡ ¸/ë°ùˆÉI¯öéíííN1®§a4Ž!,ßlåÒ´X À¶±´90Ü ´ó›ÖíÃDÚ^*®ú»«Àg©¼óßœ·ØçØÃ-–”¦ÖîÈ,¸Ðjè÷žÐ|#%[r|d³Q£ ¯²u‰¨ ¾‹{wìäXÊH%wúœ$æ¼q¼ãB/ ¸ÉûÑrdžcsss9§-dD›È:~JŽ0±/ï‡i $q R¦­ ×r’š;q¾×¥˜‘8467=–Ì Àd™_dxÝåKøRã$íµbõ –yyI$PK๽èÖ«ƒq¾Ÿ'Q1N2½XÌãpëÕÒŒÜ{Fé“ÍY{>0ß»ñµÎšý÷îfY^ÐcãDÔբĀ2¹WŸöÆØäyKº½èŽHëÞ-Ý芆[ŸÙºe.¤¿MbÖ2t")YYYéàg[ü¡ÔwÅ‚•¤ÖÜ*>Ÿ™ü~6@{WíŽùC~§¬úa±D³íœ‹Ðl6«;wïTŸÎôGôǹLf†¯øàÝb}6"Å•w¯µ'ùxŸó>䮂}ôlèmµƒqï±®¹vC¨ oAë¹G¿áåìCœ'ö# à4iÛa’@÷L É#iàÚ¬“¨8v´)¤áëæ “¤tï)=mëŒB°âEnîÍaˆ“ÉdR7oÞ\þ-þ„Ÿ»kk Î'4Íа¤d$­À” …Ä6ô¦@ïØÎfŸŒcCãᆧگ•õÌ­">rÜœÜ+óòixlÒ0Ó1¿¡[™é3c™8·LŒ64Í?/ilÈÃIv^t&:“™—Å™¡ c y Æòqopdü@= -ÃJ^–<ÐfY8ßfÀÊù¥9]ƒ]±HÃMèH%ăP6=âp0N0lx“Íó"オȵä Q$ö‡†½ïÅíÃTƒqµÇ‰sέU«µ¸é— ÂK+ú¼å—“Ìæ–½ß0Z5AÔóÎ÷NkYð$óïïïwðµ ‡ð¼JE·½û£?ú£?Îã¤4ð)CÇ2¾IA‚QÏ• Ìñ {‘92‰z`-·1"û×HÀÈ÷%¡>Em¼Û/­ª–û/HŠ‹/vâ'ö±ÜÃÙ3Í“õù´ŸpìgEŠÐM2tŸX«°²¥Y)I$xkd¹ãÓê*˜ÇAìè=ÜÅÃK—.uÆîæÍ›ÇæìÑŽoÛ´hà<È$‹%9†pÑÛq·ã'ÀÄ^æ¦Ó¥£9A·‰¸˜.¦QZ6‚¥eE77?,]͵¸8`o'ÆŽnñ‘PF: zN.}fnÞ¼Ù êÜ"# ubÞŸÝÝÝíã©5ž›t¶5ÞßíEΆšv¾L&ËÑØØ”Wæe†Ãçå¬Ù§&:¿Åµ3ጇÃ4ùGÆÏ2x ö±0ƒáS-å//bLvž•ÏÛL”—ß•&0ž0©ˆ’B@Ã<™ ›£íÌysdüyÃîœ4®¯¯w’ *]ŒѬdeWÙ“ĨÖp?6"Ë.%B®âYßžEÊ-y·¼[ÒŠ†¦1v–v®Àç/_¾ÜyVöøô1MôGœÓƒŽýIaZ±Ÿðn“j ʬç wGÄð(d~[Þ9Úí=gˆ6—t§g­·»Ýé-?ì=œÎ¿?k%-ø?Ž ù­ª:_rlG|dšûÝ'Ç?YÌL?5º]†³ÛðkfÚTÒφyá"¶ùÑécD ÷–†à$˜\{0ñYBËø~âàã†$¦‡ ý‡ŒÆ!ötâcZÂd29ш5wEø7æ/hx4“ÉdÉ‘1—Û(­l^S0öÐ r^9G 6d.îîîv:…Ka- ñqûâ®@få']”%öÜB³JBˆ,#ÇËÍã…4ŽÒ2½d{´ÈP­H =XjÌ»=™ê ÆhV—8ÊÔ OéFäùwTìµÂ³1ÃÄ)ßl‰bZ³†ý¥² ‹[«Y­±„0•.O®Ü X@-Ζ»P/2$BÆó\ñ´ Éææf§ÕìDÅ>ÆÓÔ¬H0vV-3vÚÒÔ$2$:P$YßïÌIü"CÇ\ ²ç=Iò/‚&(öGôGœ§c~4_®µôIÕU':Ä6…lq ñqÇÅ—V¿•añ#Ë+S¬t–Ê»aÆN”輤)¤!>>O|傜ãw |oY°3š&‘FóyàB-{æp8<æ3ã"·‘$…Yä¶àcGbˆäW»ëÀØpЕ°Ñj*“r>;yþnîÍÜrÇvŽ-í¿HÛóœÇ?ð] õ¼¢ˆí” ½Ø–H¥?Ðy®ÕFõ(ÚÚÜ’æž7†Z´ÊïŒ)Ä[Î RÈàX2ã`ÜÌR¶¬ÎÕgc@ÝÕðE[µÌÁ¸_4™ev J¯àQ*pànU”žæEõ‹lè÷îÌ’J¶h²ØI2º~@$*ž,Y¹7¬ÎY¹94výM„Ýq½Öaw"Ãõsoöàñ" ™Ÿ„ÓÕž”vt¢cøÖI8Iª1žWÆ»’eæIúÔX±-¡c‰¦Sgs+K+?kK–{̽'tŒ \*–ðûéÚëÎï”áš^à‡âVõGôGœ§ãh~Ô æÙk(˜9@LÝäyX¸…øÈ•{ÓÆMhg_¢câ®ýÈ²ØØòJa¦ãâø(¡ñ(‹&‡†Ä U[sþÔ X)f>îb%cÛŠÍQNÿÈÑm"‘q‘Û‰ˆÍ@Íc5"…ÃÝ*Ç–Ö[š_íó.ôš[•…\’@þÆŠ¸Ì+ž‘Hü^Kš:¥§ù>'°@³ZÐz{ šnB|”°;#,ËͽÛ(e½3g°@†QVÉ?2Ý„yßLf蘤V¸J&ƒ!B–™#Q 5jé7ó©*F°ož ~Ó­S¾ÀÕ3ÏÃêQÎìf³Yg2´*^¤Ì#±< )“/Zh®H¸½è$‘Ä„±ç~ý2¤j‡!N)¡çÉÌÂÃd%i²š‹E ÌÃ`Q°4cvêxŽÙ–NØ\Âö|ï´ô9ܶæù¸Zü2®ò$2>/²Ù¨X07,€A7 io:.>œ@SÉrkµ%ÛÍât£“2æ“4W(,Iîn˜%Ay?é8Mo÷MôGœëÃ†Üæ©Ûï# µ†¹˜ÏØêž{­nu\Øw“ça±#ûÈÐ1!X&~bóÞi®ƒí! nb’èð}ìá[,0~‰Haϱ¥¸iÚ îbX9Ô]‹LtZBQ’r¢Âõ¤Z¯‹Ü†ÅÙÂEp8¾)MMŒ,Žƒ{ãY[ºÚf ­Ø“Ø ÔIœ)FŒ {ÛCNž­5œÜ»ฒ±Ëø„˜ÞÜ+'ãŽùͲª«û.ßË~»›åxèDÆÊd%03tl6›ÕÎÎNÇЉ Œ›0”Öª>¹ºÌáŽLvtœ‘ùYÞ®„ZU»d¡–l™í2_R¶_tcL“§Á"ÈõúE^,µ½½ÝÉÊÍ?bdÜévùCDÇhœ'Ê^™ùºÚÁË@× “&¶•µH†ìó’f[l Ü7‰ˆ5áMæg%É0·ÊmiËtsÞ²ÞvåÙ²øûúÜÍ¢šaÙNžM&B$:æØÐ‘a!H|­ŸCz3ÙGf4ud- ãóžw™ü¿ÛýÑýq^‚PÖU{ű±ñ¿äy¤_^o¬·Égt12 µ²–»xjõ©ôг©¶á[ì™öJ!¾r°|Êò͆¥Ç勉¬œÅjø¿iB;÷fŸ'ü>{¸¡gìé©<ꂟ¡ó˜ª[ZÈŸã»ÕÕÕN2àÑÅLƽÅbœ9o{ ?7öh':"p±2“HÆ7 3S(Ê÷fœìè‰ÅgÆ;I²Ð“¹çÄ?.ÀWs¿æ3çùmsÇ9l/1ŸÏkss³_¹Ëi‰fgƾnaYUƒ Í°W<ü@Lüq6f2›[düþÍ›7;°;´ŸÔ4„÷WªÎÚ-ñ—{–‰ó‹ìî×ÎCv°lB¼%„ÝÝ²Ž¹ïݤosdŒÍ¬>Uɘ̖ÈFf¯þÖÒŽîxy2›Gâ–¼;æ¨Ø÷%M ²isÇI˜ÇÎÝ0ιhH£…ZfZ\«Ï{žƒïÝ;U¯¸; Dþ™œ…ÀþCîZ¦leff%Ê]NWù\Åó±¶¶ÖQéþèþ8‡•¡¼$¼œ@ŽB+ë« ¥îüÓù°zæIƆ.ÈÙKΦì=.z¥Ož!Ôùyº$BzÍqåh¾¡gµ!Ø'¾BQû$þqðÍLÌáBª ± 1JZ‚÷xó<€Å±G'4Í\Rwl̳5ôÌñM ~N²ÁóNXáãVÞ²5÷Ï~œ] î݆šÄW-â^ž;ÿ3Ú÷æÏ§*kÆF:ÑÑ™L&Ǥ©SñÖÜrTËlk’H%ºŒ”rŽÑBq964JìX2“šÏþÑ䑘ób²“Ù-7g~´v]q¢‘Zß–à#ˆd@ý¢&”dk7„‡`Ýê ü–Ïó²Ø]ÕZáøÔ¸ûD×Â< w`ìœK°Ïj÷y 1Ø­>y žîFùE7†ÓÊL6·u“°4 LÊ3§á¥?oYn*]Ö"È`>¥¯-2‘Ü+Ï ’4òGð¯<KW§(×îÝIše'Sí%1žiÆ¢éóÌÛtkö¼1‘/±ÅIÔóyo¾}¦?ú£?ÎãÁOÀI¡ÎR¯pÞçLÚNÕ3ïá> b; BDŒàj5E/öp' ìñ'r‰ÝÌãð>e±# <)¯L‚y(Ÿvk“]šôd×^ã(³õjxÕáááòe"Ùb‘3|‹V+‰ˆ'+ßÏy·¥Y¹·TlIb“‰ “ ˜I ùE´•ÍcšØbc}ÞI^J3òû†ùå"çNblF³Ù¬Óž¤â•,Ãò,?Øê6Y¤‚çÎX¬¯¯w“åª^‘üä÷÷öö:°9cDIâ\pHn•¥M²ä÷ÛþèþèóxþE#öAÜØŸ°ÁBÇÄÉ€¡iþ~Öb;À§1bîñ$2ÊVç$à´…BBï“pÎ>Ê>ä`poooÿ€<°ï‹94 aNŸ<¾?í-,Çœ°;CÏÛ“ ÿæOBî¼…,dàŽŠã#‹\Aægew°í=÷öíÛ~cK€OüþžüiïñÄ †á¹XjÊ…»Qîrz–ü!shœs?Ĵ޽œDÿð[Nd˜óV`K[Þ âqdžîVñl t0W2ù7?iìD#q”Üà`0¨©È%“Ý`cc£ch.ç]ɧõjcW@R‚ØÕg?w%̃â¬ØfŸ擬f™Æ‰L¶¶¶:/*“‘—‰€5¥©Ä™DnCLKOÛ0ÊíAÆ.}b¿è´Nݵ -Iè®…;eT$Z„t~3•¹œó¢ú@•Œyˆë‡{eµóRÖ××aTÝeÉ–;‰ ϶E´)‹W[,Â`1^Fw«Òì“$ßöÁýZÎmãô†bsà›õ¼™þèþ8§Ç uIö1WÖ]óÍaÂ;^)†Oíìì4¡cNŒ„ þ1OÄE0ηl¸~yé¥âB¯ù#ìqÞÃéˆØÝÞ±œ!@Œ“¾ýýýc´wxÌÁ±j+{c날㺄¹`ç®…¡sîø¤»½ááÙ‘1íÀаôŠc<)2$îjxìÖ××;ÂTi¦NüâyçÄ þßÇØs˜ûnÙî,‚“äQ'vó¼qŸÂ{"•˜¿¶TÉœ 0¸W':\»‹Þp¯ø·­­­Žºpò:œ+_8;²afB|rÑ)k=lõ<Àl‚tkÔ¤%AlŒ)„vë¸;3¥¢áŠ“=!B$:®¬;Øw"ãjŒÿžÏ{²±+çécÃ'Ô(¬5nž†Wl˜™I å—íë±7~Ö8I‘T® ZÀؘ+eèXk‘vgU‹LØ,Ë:ëä ˆ=š ŽuŸµ6¡aVMŸs1-!쮄¹œð88ÏOQ0-̱a7„=œøÇ{¼÷I‚uûXž™=ÜPøVçßbIƆGÙO$ ±æ'yŸ³O‹ÃKuŸóÜ»c„“”MíÑãØÏ±!ü ómOaÙn?÷,r[žÙÜqwT(2›@Üʼs7+mK¬&ì$Í”D¤ä¼¤›åøÅhbCŸÅe±#wÒˆy®Fa9‰–gè¼e·Ó;1sæX2ã ŒöZJ©¥ yúÄj.„ V2CWý[ cù¬wí·NúÚÚÚ²Ãdh— àØGƪ®ú§ˆƒ_/Ÿ+ ©³žŠl,ãkMÆ'ɳ¸ [Iø2”EÒ/²•)H̬AŸd~·äÝ-rÅÀªdîÈXú1%ú˜˜ià¼=vì_Äóc!¡ï$Î>1–ífQô½[¶Ûcã{OyBû ‘À²8-Khšù?p¯X„Zcë6tºöÂK³Ø÷iäòÞ‡úˆ¦?ú£?Îg2£à™¢Í‰ wP•x~Ã`Z^) :ø>,8g˜ ×å®Á´¥i ½·13û˜¡õ¤†ÖŸ$Ès|ʈºUÄÀÇÍCÉ$ѼVsˆ]ȵ’ÿÞªc96öÇËØqD'y"ÙqiÙŽ˜cc/:ßhóL,ú@·Êüi+“fü“ж£uΞŸŸo’‘â£]è‰4jò‹¢c²PúYí#¦ÆFZ\€?@Ú¸^]]­<§¥˜ 5}‡tl“²$[H×±°Õ¦ôÍš‰L´ê¼XßäD†Â7±ql± èõþƒžs5S[.v•Â¥0Ã<ã «ø” /@”R.‰ÝЧ3‘£é€K2ˆ›Ý[µgž€Rëéî«×]ؽ®s†."i! ”Ôàȃ,#1}Öu„«|8;"«¯±ì¬…ð.7—i¯<Ÿët»+£a5Ì…ª¿¿&Àý»{WìÖFÒëEÿ–üÕ YvÖµ# ïenBº™ÌJ^xU¶Þßœn“›kÊJ]c'ÝÓÒìt|»uëÖßøe¹î?=XÿðƒGë`Ï}Û_ûë…×ÁZëðàj­ut°ÖñÑÕº}m­Û×®Ö­kWëÆÉZ—Woÿ·ÏW|è+@׺G•0S€nõª ÆÎ)÷ZÁ»ýF¦àÝ k­ :›2 ` 3ïžËR¤g ¾±âc àÔùTJô)'é(t ¿ˆmOa­gÑm0bÕA‰c7m÷þ‰:&6´OJc£,!0/u«ªCItõÐa/%á‘ÌŽÔÕvF‹!ìñsÿþý­Þ*ⱡ’æd´»]¶Þ=»ŽÉæéÙ7/§>º §$±¸8ÙA¸6YBãÙsµâb°¯Q“1ƒ¸{â+3[ÖÌ–È < d^e}Ï>..TEGrgÅeèì|›Í® ùEö̽À;È´Ù-³ß€«uØÕÕMÌ{Ì[†ž Ý…ZùQ í&¤¨ªòÞ³Ucc¶G0/-°@§çjÙ¸Š^≅®f-3[ÚZ–‰’_ÛØ4÷¦=…"4 IDAT¡Á€ÊÔõº™®iË­ „›\ã­%yp›Ü4в¼Ï·¬\ !½@Z\‡£óhr@åÏ >^u¯;¯¤6 Ü_€ößz¼~õ¾Æî³¿ö×þÚy­uxm­ëÇWëöµ«õñ÷®ÖÇݹ\÷rýè¹\Ÿú çëÓ>ñbýˆ×/×éÅÁ:=_{ö9„ï$Ý+·Ü=M™²¹qøE½¢™sµœŠ¦Õ¡ªU°ÅBgÇÄöRñŒ×¹SÇ.ê—6¸:“Ú'O£ÏÁªQýo»¬§=Ç:çìÁö1HôU“£ãš™Àút¬µ¡g|Žn“Z¯s—U Ïø]ôò+žñ‚ùIíšúYbÏI6L2O£'ƒ8µç"™ý'Rg#Uqóteí™ölf¢¾K]ZøGý³Õ¨©KÓàËÿÔÍ»¦ž fú³ù¥Q's¦¨Ù``ºŽÉY5Ð1ªW¥à|—»TŸµ«ˆ“uZ7™Ûf7tWP¢ö¤ð˜½)[ó"Žè¼Ï†N Ê›¬‚õƦ Å®Æòg«7SÈgŸ_—;¬×wc«Q‚÷¢-åôY·ã±ckCGõ?³ëpbþŸÈdÍØXìj¤j¶f.ä\;ìc¦ÊMìââbS1yÑB¶OŒ¼êþ·É-–î`3Ñ]½ p§~©ïS?Ô¼z™Î­kk­×ö kí¯žëòj­'gëÉéÁú¾Gk}ÝÕ;T©£µî^¿Zwo^­Où˜‹õ~ÚéúœO{¶ÖZÏÎöA çSÿ÷éÓ§›ýÑ>yžá‚õ]¬Œõ;“þ]€ =i67Nc¬áE:ÏûìyÎe£6‹Zæ-}*l×ëÑŸ¬86Q]24Šš™ó]ç¤çT•éÚÚØ…^Ô~Â{ŸÍ@ ²fšð“újçEØ#W²ùúlˆ¹IØèH=sìæØNgRïÍyåPz¹ýÕ–ûܦ¤¢yÕwÏ¿¯Ï=³‘”ÁªQ®!±_øÉ Œ”Âh}³º,­ÙLý¹`¦…¬ËÇ.Ý]“YЦcÓlª4ËL³»ÎÓµl.t'{ y”òK} f[ìNŸè)^ý@ÜĤ–6 ÃnýV%K§‚u³CMÖu–-Ëæ4Ù‹ª¯]»¶¹_Áøùùùºyóæ&Èl“вŒ„“yö¡1óðáÃ-ñÚäQVuè÷ZV6HÜUòo!·8ã¨Z²/2Hžn.n‚VTû]ºµØÇÅ n—ɃAœlÖ‰ýûîÝ»[kBÊàÅÅÅzã76Ÿ}pp°¡žõ÷:®I3ºéµ¦_*7³kGWëÚñZ§ç{ µ¿ö׿PY“ÿ{uõ6eóþÓƒõ?x¸¾ôOÖ[·Ö¿ÿ3ž­ÿðg=]oܺڻrÉZßH¹±O^¯k=;­dMvêL*˜ŸaÍd&Hï²¢Ó¹bÂN0oe6µîœ+ë®2™ØïÕzZl¶ÖÛìš<§ö·{N‰ Õ_§ß(ük¯ì9—öרx†L”èí÷Èô{gõEŠùѵ-QGâ˜÷ý&ôÃGögœŒó°±•–gPª‘T´»^•¡‘A®nvV›NOO7Á‹ú¡™ÈÁ½ºùYü¨òõæ›on‚×îÝ$yïo¬îÞ½» k­!¿sçÎfNH›Û3ýqmæf ÌìïËUQÈOÛ…\ ”fÀÈuöZÑþ0×dŒËcÌÕLAX¿w:s¥¡‘Â3›.ZZ}‘»B÷cÆÄ<Šá\¸Ú̹Éõßk¯½¶E ªÚU–Àòc¥U›@IËs2W:-`+jrÌîösìzî3ªöj! ZÙl æuœ›:éUÚZ6¯´®žn1³sncŸ{†N‡ˆ›ÌìŒk Ó¼±¬<¹Å»8¢Í3õб-:„ïwS490ÏóóóMòáìüü¥ÉÒ^­µ®¯uóäjžï¡ÖþÚ_ÿÒ®£µ>=X_ðWn¬/üòë7ÿ¬§ës>õt}Ú'^¬Ãƒµ.._Ý¡9==Ýê]'ÍEëìN?¥öÍêNdtÎXmWï}]Ç(¡(àáÓ¹ÔªD:Y'eæ;ãwþLwMG§½r±™ ,u6 =~üx‹Êÿ"}uŸ7©ùÒ§vaC±©c£FØj—Žo2‘^$©0‰­qóbb?©a“>.Ø7 ðÛzÃC ìÆÎfè¶ÞH»%6•ºf¢î½g“ÙQß5ûÈì*èö+5l­µÁ½]³¸ñ¢öRó§$à ÑÄå[•™&›Æt›3ߺ+49ŒŠŠtg˜ÎM6KlŠ®²Ðk#HÔ-…Hp µ"£½`KX‚ßÙÝÞ÷›1ØUmš^Þn^Ål-Ä~›´9MãSôøñã-±¿˜I¯2*—;<»î žíêÛ­ó„b3õA½.÷×l‹Ï}Þ›B?³%‰(­VÉaMÔ³”*÷زwAžó-ÞÉ-6f bÉ^kÆJþíL¸¦¦ÁÅ µå–{¼i8uíåê3s÷ÆÕzãÖÕºÿdÌì¯ýõ/½zs²ÖÓ³µþÛ¿|cýɯº¾~é?]¿ãç>]?êëÉÙ«·æ.Î/¶’HU4ÚÛ=çJØu®L‡ô+«ßýÿ»úäˆØ[SÛKܸqcs¶Ì†ß»Î1µ ʳÉõu;´—™ŸÔ2›*:ž3]³é£h¥À²çX€ZC50S6 FìÖg©ŸÖzzjh:s¥Ö‡¥Þk†Ô/þ‘6>ë·èXé›`_JbmI JÂÅ6o—>žFØyU{!¨Wò‹:ÖØuïöÐãûÜÅ7Î{ƒ¸Y¥l^Ífë¨V⺷’ÐÞû& rbUÆ‘cꀗ¹—æd—s3÷eÅ땹ÛB• uåÈf7Ч˜­¨UA™ô$™nzÚûz€WË`³ì¢†Æ¦H•àŒ,-¡ÙÃG÷©&€U69K½ºnUWNu²–]ˆ·oßÞæµÞµVô¹:9*­J,àëu©bZ+®õvçZ]4œÌ-äéz6E˜}ž—ÆWG;ÛšižeòÐû;¼ òl¢ÖBM°6þtc‘V§åç,½zoU1gÿ¢þv:¶ÍMTyËÊsMõ·ëøèåRÚ¿~ój}àÖå^©¼¿ö×ePsm­>:Xìÿ¹¾~Þ¾³þ—¯º¾®½‚¦2lÿàYÐÙÑÝ^,ó@üÓ2FfCÍ@£º\é[íÕÙ/ Ú¬žá‚ùµÖs`:6M÷&> ÛiA¬½²ýÖ:§NDF:]›bOw)›B¦ƒ€¶@"G¶žW‰ÚþvêƒÔðv†voáÍŒÔÈL0ÞûmŠmÅÆ. [‚ß÷ëlê½Û§O*|ŸoŸ=çfJa“äbÍŠªä•(.ˆ ¿Èô\ ¢v5üžÖÑj€{¿­9Â?UuÔ7of=m» t,®W(Ùx.˜988X÷îÝÛ]•'ׯIOR‹áY†êô@gv9½K‹Õ.æ.Äi1ìBê4XaÖÙA}Šùãò)fsÓòYþ›b¹þ7…‚RMFÅr•gÓ¤¹ Z•˜Á¬¨ÌÉ*¿Õ†Lm‚N–µÖ–Nà ¾÷Ä-6ráF-ë=y9§yÚ7Ë£l^:6»:ÛHL·–Z›dsÚÂJÞ<üœÓV\=z´ÎÏÏ7δ¶ž}fÚdÍP8o¤#ØlKþlŸoøÚµkëe#οqër}ôí}$³¿öׇëúž‡ë7þ‰Ûë7üé[ëÙùz¥´4Û`¼sñÍ7ßÜmâ›Î)tá—pÆÃ‡7{ññññæýý}I)­ú'uÞ&•BöÑ›Z?[Á»Ÿg/·À´`PüaSÉ~:û…t†*úž÷^BT@Û÷Û/DÀl®×c¤„'eãtÖ)ˆï{m±0]UÓ‘"vÛ…›îÍ Aøgö™é¹G¿J÷=ᦑ‚:iý¿{ Ÿ•ä¶ÒXÃî®Ø:áæ44½ß>3Þ»ÍÒ öea)7éïïß¿¿[ª¿îõ¨÷óû{MFËZ£ÏLÀÝÈrW…ÅEs.#ü›–‹HÛå³® kR€tîêu3»Êƒf4,}Zþk“š€S°\ÆbW‡öÉÕBØ ð­·ÞÚ¢$Y~Ì  ršö„Þ»¶y¾¿MpZW›)ª"Ów«Ë°âv“Ù•©*p*ˆs^änYºqnì&µl6Er#°kðõë×7ÍäÏjKYŦKëkãuÞeÑs³+°´™æ»‡“kjrLMôÜ¥íMn±´»œpfÙº÷_»vím-ÙKV™yíÚZŸôË·AÆgî¯ýõáõ××ú3ëúúúï>^ÿí/{¼>ã“Î×å«°ß©î{nMÓ˜iF£Ä̹ŽKZ—`oŒWÞØfýOOO7!Ó!)ÖÒ³f›ÙÏCwNÏ…þ·Ù½>üÒ½¶wé4Ä?2R÷jE_t†K­wì D¤GI«Ok/•°[ø¨÷‹ „Žꇻɚ0j{ÚrK9¬K ›ú ®^÷YNýPbÿÙ0SzúÔ¾[ñ™mOtË *éŸh†4µYaC+<ê£ `¥ÎO}óœWögÿØcg'ͬ/m1ô€ Tœ ½ÞB×ݪ/ÝP\ó–µ™s@ãúX]¿~}KPŸkGÜ÷ï*aéÎ ` pÆ!í÷«uPÔ­ÅŸ¶Ì»AÞ®Ìyß­3…F ½n/{ä¨Ùe߬3…%uEª4Û&4ƒ@Vcc3«2"v¾mÂÏ…6ÉVè×íû­¸´IV’¯ h®cIH›Xt»[ÖnƒßÕcGjš /ýQ`›dcéûûü~ë´,ŸUÊ)KÎò¦Û¢¦+Û¸g§/¶¸¸Zë3~Äùºv¼eö×þúp]Wk­u²Ö7|çÑúwþøkëK¾þdÝ<¹zß'ŽÞí)¨²ª`íœÑ v&uxÒL  #@<Åþ%ëýÛDn߯NöÆ ý)°Þë&ì?~¼Õô[-§:)ÔV‡fÓëÆÆŠŠŸÙƒgöЙg¼ߨe:­êZþ™=r:×oܸ±I¦j¿ì=ûÌ”¬Çf­µ5vaSÁ¾ÉÄ‚@Y³Ñ»•ÂÙ_hÐáê°e¸Øï¶WKó&|¡Y€Ô³0ºï/‘["[ì85ÄáÐÙdvJ>l¨iÅg6;ï›L$]ϦcÛsÁL—¢¨é5.¥‰èžöË ‡ŒüüÁ¾®óD›€Y~Ý| ‚ùJ¯ççç[öË•ï P52öZ™Î]½nd(=ªMÌî²N悉¾¿ª‚úu"Ó¹"ú”‚®‚ÌJâÓÄAyýñË»Ðfž6 ³7Í‹]‚°iO¨[^¼"Ë‚r‘æ]“¹’¼[~í T´gv#H¼Ùs5H«dÞ:(ˆ³ââáw÷îÝ­f¢výY@+:Š–Ü{]1ÞÌtuÿeª&áéÓ§/`¹¸\ë§}òùº¾oš¹¿öׇÿ:\ë¬_óE¯­?ú•7Öíkïïp¦pÍDm{oô*_—Ò<µ /ÒÉš¬”Ï?f Êf¢·ddÁŒm¦õ³ô©vö‘9ÐoI#£Îc¶Pè<_kÛy«@Js€0B¿×Ìù¬Z”¹olgÃð°eøÊf¡bÃ* S0?©õ67Hë Uò£$°^ûõÕj`–áÔÚ¿¨û™½X¬ÈtN7Vö_œ˜WÃ*V]JÐÛgF“ %V«œ%Z TÔøvïΫËËË uL·:þ>ÜjØ™~Z7âÖ›´ºÙ„V&’1ÇÎ`&/ñé“nùÐúÚk¯mÿlv‹ÖªèÖûÑe¯¬jhZè º½T¬S0¦n##ƒi“ÛgËcl2jTßu ß;Pvï6´ZÕbi-íZÖÖ;Ç6­§{ø- aFÝ^e$ï6ÓêÞ¦Oº=m dø÷îÝÛâÏäͦIýwÿþý-‡º&{›‡%s±~ƒšYñQ„i3.ÌÙ¨U›Hr“qCž´9`9žmZ–N»Ïð6׌½²®–6f¦KÝY¦6x×Ù‹—ẼZëÇ~ìÅúÄ{{€ýµ¿>rô«µ~ëßZàËn®Ã÷±ˆFfÀÄíÛëÍ7ßÜÒ¨Dïl ¨v¯üøñV£Çh01JÔv–L¨‡sh1,5L°ß.«Â̸ ;g3PÏ™Î1iþU›:ël/±ÖZwïÞÝ:“íµ‰³gÆõë×7Á„î }¿4™é^ÆB׳Þßdµ¢âdU+aù0z”Ô6{Hc5éSS¥ ïùùùFHØ&4­í>Ÿ¤ç`ÕBëj­mvóæÍ-¯óÆÎL‘\_}Ð+ݺIJÛ ¬kÓÝBŽâT€ÛgXu˜A¤Ùš&´Î3Èknè@W RùÙj˜öÍ“{<;ç¶Ihhé¼™üY{ ”5'(ZÍ’ÿ꼑#ÚšjÖ¿×—ÒAK\]]­Ë—°ÁÄéÅZ¿ñg>[kß8óÕ¼.×ZÏÖ>˜ýH_Gký¾¿psý™¯¾ö¾hÙ“æë9i‚OêWÁdf{½‰ÚöeY±*dM\»vmæKÔxK¨Yù·ÍÀl˜ÙëóŒŸýм:à v¼—„žô)xâ—ÎøÎÿ“““FOfêë¥ÒYª3WØq6Ô™kê— ¥åu[­²½EgpB|ÔeµHgÓ~o&¬ëúj¦JŸp¸7|´Ëèɱéÿß…‹gÕ" Œ‰Üð†UÀï=pl*YTÅa1é–=wM´ ¼wÇfÊUÂ?V«L<϶(‡~˜_*ÍeоË^—qæ³î`ÊcŒ&|òäÉ–°Y ›¾[ Ñô9ׂ¯ «@E›\Åórùt¯2ØPÐe/”ªÒ£&`UŒ¯ÆMÊ j ²ä˜¶-++:ŒçhiUÚž®RËôY7ð˜s§ÎÉX ¦6j–ôçdTl¿K©ÆMnºÍ¹Á{oM ÙLÖùùù–íe÷æï›þü>7=ê[Èfš·ö6ж»5×½D3ãaY9Ý—•¸Ævfs.//×õ×_:÷¢gçëWú³uxmh?âAÅãõá */×Zûtýùßòh}Þëûçÿ_‹gk}þŸ»µ¾ü[Ž×ñáûïþtýªjaÅ% vÿ63.µ^ Lÿÿ|=ü#e[ê}îUQ2¢P—ÌôŠþ-P';ïÇÇÇÏÑ›:Ô²(ì³7±ŸÔ°IÚe–þSëiŧ„[÷ÖëöÿhèÓ½Ëö ߘ olj¶®þ9ì(õ~ö㵇¬¬0˜:Ù0Àl¯6<Œ`5Îq3I­}s zŸMH÷ÓØ¨Lmxójya±VúíVX¤SjÏÜïV­jζ&Zs&fï¦Öas~&¡­X=×gf6÷‹Fcöw -²”ª ¬¿1ú+ЙZ3ãEÅÒ•ôH/âמ°ßÞä«3­KZV¦Ÿv6q•ñÊHXú-ª¬§«YŸa(Á¾™ûi‘×&¨ÏzFNf³9nbiP´Ñnlf³­9v†jpÚd›7½¿¿›œ<É\ÚÛ[jAÚy× ~:Í‹ž{Ù˜x˜-TÝl ³ä,à´Ú4]ËºÊÆtïjdœ7–ü]èekZÈq“›#mšT4<¢ÌÇ>Yßþß\_øS/?|Ïáj­uýrýŒy¾>ñxÌ|įƒµ?;XŸûÇî¬>:xßUhÄ/Sã+˜š©ŽâÜ~ê^[{«Î¢öá›ÉÌ~Ÿ™õαΡØ0ö:yøðá¦ûmÇÇÇ[ç4Â&jwÑ£+†‡ =×|ÿ¤XÛa—ÑAøÇ3^æ-;b¤hŠÓ/õÜ^o%bÃZ÷îÝÛÂCÓ¬(YŠAZco¿éèÖï¶]¿§±1Pó÷NW´Ù¬´±Q?Ýœœæ5¨¨'hÎ7nݺµÅ„ê¹ìj$ßû :j?áë¶tYëmJb÷Ò³ óÀöyêÊÂ<=ÛÇôMv3}£7)ZµÃ©¯OŒ_ÓF×î¯:v‡UÔm‰L0oÆAð¾ËËÛlŒ½T|½+úT‹L/ñÉ=>>ÞÒ˜óóŽ^5+ÔY>´š¥Î£àAG·i¿Ü&Ùdò×ß&rta™±˜^âNÞ{÷î=·ØHÕ±U;%¿¶g!­¯ßßbjÏf\ÚÚ03‘b´Á)]9 ‚ @Û¦ÓÍÌd5/LXv¶wIAí¤–¥½23ÖÓýÙ¨MR›üÜÙqùe»Î.Öú­?ûÙ;ñûë#u\}èÊÝÕZë‚ÿ®^ùzÿ~µi}û­õÆo}ýÁï[ëàïøçù®ýõCМ­õ9ÿãõì|½/)g&Z§ Þsª³eW"×½>>¿V²R¬¼Ë,ȽRVG{µ­)¬¸Øg%ü#`µŸš`=И†ØÌ¹T2ƒ¼Î©ÎP«Ya“™êƒl3`(›¦sªÀ¬Ì¿£'½JüÖØ†Ã? X‰ë ´Y¹}fìÃg#x+q‚q©gRïû›lî­@J«½Z&=+l9q±ØO·¼]ޏRç­ÔÙ t⛉L«ešÍÒ{î:âZ ¹sçÎV_¾zSöoñ‹ó®ûSŸ­kkÿ9öÇ–¡&àÜ5™ú!"•NP3çs2j¡§ «’^uvv¶q¦Khi¶b O¯rmvÝd &ÌúûºÂÓËÛMª{wl´Wž“Q±~ú$5:M3ù¨;YµOÎÑÄçzrr²ÏeiÌæô[ÕÿØË¥ÍÙj’ÎZ¸–>åhdúÜÛD 4æBuÞÍ ^׎敂wûÈ´ÐäÇ ö}¿å [ѺÑ@Êy£cÓ÷¢5§¥¹Ú¨Æ¦{× ÀÞK~'''[|ä—.cºÖúáo\¬_ñ“N×Õµ}Pó²>¤k—ë—~úéúô\®ƒÓÃõÿÚú+ßv¸.Þ d>ùGž­_þãÎ×ëoýÉú¶×Ï×/yýhý7_v¼žîøÌ7ÎÖïù©ë¯þëo>\ëäãN×òiWëÏÍñú”º~⽫õw“ì“Å _×äAmxÅ‹ÆFܽ³2¶©¤%²Ç\¨Ó+<±›Èìl[Å¥‡­ÅÞì•ýI@©ðzö‰é5(QˆtWPöÚk¯mÀ~Ë›ÑêäQÚÊ MzT ÝŠÉÔB¸ëòWÛ)f»uëÖrÒ§Ôÿœœœl,ø¬f¹ôùqŒ{õI¾ß*D -\¶ÝÍ5M"ªÒ4/ÚDÝh²ž¶tê¼h^µéäÜD¶xnß¾½™wsƒOcc†ÁlIˆ)FS»ÕB÷pþüÍ›I9tÍxÀôÜgðo»i’öôÙË›-=^ë—ÿ„ÓuûÖ>ÿR^Çë ~˃õöéúÀáÁúèñlý©ßôpý®Ÿx±jô)?öéú3¿éÑú¼»\ç—ë×}ö[ë}Þãõ»Æùºqù‚*γõÿܧë3n½ýï“9]¿ï?^ÿó¯x²~ÜÁáú»ßu¸~ÒÏ|´¾è>[³r?¬×ýíë뫾íè}?vþ÷ÿ{h¯<›özFç¢ "iïyöìÙ¬gè3ÅüR3¨Ø\ ÉLñQgEÔ2ÛSXôèÑVŸ­¥eϳ)¤´ºÙìS«Œ›V˶ÑdÁjÕ¤‡O o÷Ö9àÕK|¥­v=qf 3\çEg¼Î_»Æ¶g;µSj«Â½p7›$W;5Ýìì5W’Û±S!þP;Uà6ü³õ†•ºôIa)mÁu»ST»UµÓèÉ`æXúÐñññzóÍ7·z·DsQX<»xʃ´é¬ÈHñ™ô)#GxQ>wXÔ.3r@du¯–F¥Oéo}ïÞ½Í:::Ú|~ãSg\3}·™w}äõïJ-ëÞ´n2ÛÇÆ ¶ ºÿÿììì9mSå»&ˆòm;ÓNëjy–———ÏY?|øpË÷<ˆeçÈ´8vQÇì\Û¼ª’eÔ^ ã¼«×÷φ•–VgƠ׎ÇQ¿Ôf™‘plÞèŽç&¦}ÿöÞåëjÖ,›d€l£Uè²5gçg/-[çêj­Ÿ÷cÎÖOûäóõW¿éd$_¦ët­OûÜGë7¾v¸~ÝÞ]öŸ®µo®¿øKï¯/þ¬gëû‡·Ö?<»\¿â>YW_ykýÜ/¹¾ž\®uü±§ë/þ{o­ó†óöùåÚt ¿ºZk]¬/ýê›ë÷~ÅÑZGk}å÷¯õå¿îtýØ/¿¶>øûÒ̇ëzôø`}Á—Ý\üW=z_ô‚2 õøñã P ßh‰,½jj1ŽŽÇM.Ú IDAT6ÄíÝ⣕٬÷V5è7v†‡ T¤eW2s£ÄÄkôñ]= d:Wß|óÍ­~h¯¿þúEH°½Ö»Zˆ0Û£G¶Ë2 :'­†©oNÿ>Q#:?{Ú´:ìÕùïîs³j ½JŒ×–;ˆ=s¢OMü¦˜í!úýJ.¼w }’ ÌŠŠL ɇĨ¶-±Yç‹’à³µÆ4zR6ptt´îß¿ÿµlö4&È £÷‹JT«Íjl¤kÚ—æ¹ÊÌÅÅÅzøðá–Û•€Uç u ³ y“%°ncC;¬Nw«€~ÝZ ¹¿•âcæÜÈÑ IúÔŒýåC©emù¬Ø'½Ê^)Ó/[Ÿõ²·nÝÚj$$ý*ëF3óÒ¿óf´+6›2;OH›h‹Jç¬[>t¡¶I56}TLg¶ÆÀÈ÷;¶mbfƒ´Wnޖ͉–×Q€Ø}i4Ðbè™Mb52˜ðZ5ÎjÕ p«&õ¬[3}ÇÌHèDלȦ-x•'í Ûè¤$¾¬×µ£µþ³ëɺum_y¹Pàåú5ÿúåúGßy}}Éw®·µ.ký¯½±¾éãÏÖO¼}µŽ¯_¬_ô‰‡ëO~ÓÉzzõö‰rþÝ'ë/~ðð_8€~òô`ýp´ùžGo­oY—ë®ïçŇ·”±Ö_þ{'ëÿúOÖÉÑû#˜éU E°Íÿ¤â^/ÙiÏ Ý°ªîÚÌn«·l¯·ªEH-ƒf9wõÛJè™(–:°â2Á|­â-+6ÇÇÇëîÝ»[cYû‰éd»ªYV„¢HwfËæ©Š²Kßoíý+:ÑfðûîþS#³Kv 5lF˜Œ®«CR Õ_Om•L'ƒÆæM‚y_´-SfX ¤Øß9ßoŸ »eût¿22Vúü©á½yóæ–Mzº4«ia½ì»W©ijÏwö™1û,X/úë¦u$î²Ñ-)2´ûÍ›7·´ EŽ–6¯]»¶ùüèQýMQ{>#×›7o>×^ªà½Š™réYJ'£ÝY«Í Nž¥<È6 +.ÚÆÞ;“–7õEMÒö¤Žuo%Lkë²å@Åt³Q˜Ô13ŠÝâ›1±lkɾ<ƒÔ0­­§vj.ÔÀ¼ŽpÙZN[ni{3@®4kéµ p2Šù­ø¨;³Q—Ö›"HpÔF5o:ü<ë/4»IÛüëe½Î.ÖúŒO:_Ÿÿ™O×zºÇ’/ ¼ZÿʵN®§ÄÃÏÖ÷^^®:Yëàèjý°ƒƒõðôàÝàåj­ï||ð/Ì\]¬§˜\¼ÍH;Úe>ü×õµþ£ÿýöº¸|ïË•Ìê›6¡ÖÝÞëÖ­MÅÆ3¶sF½£ŒA›©÷c»jlt% KÕø¹3>ú’l˜ ƒì…"Hæ€ý<:‡Ír‹ÍLkÓÛ×9dy—~zÒò¦,Aüâ¯QÂÔYÍ2Y)>²i¤øFì9éSþìÒOï²VÌoVW€ëØÏd¥= tÄO»ú/ª Ÿ®¯Vd €­ÔI_ŸNÃaƒ2µéV“fqb6‚ß…•t-k^ˆŸ*ž(“0HTnò\eÆ2ÑöÌòe`YA»€S-BZˆ_ UA»Rµ • ü}MÖC<Å)ÚnЦEžÔ¯Éõ³ü83ëÒÀz€rØ×FN1¿›˜ µÉ/ORkj­ŸçØ0Î>0ÒâÚ$¥žMWލg~¾‚¯žÍ¬ZØe¾ò_ÈìÞªH²®¿r8ù© ÂÜà dZ˜»Ù,éëê1=æ›óͱ€ªrù÷;–s”ÒXÅÅŒ†s¾±+èÜeaYÏL™þønRþëK8Þ:=XŸÿsž®Ÿó©g{«æ—åº:\ßüÖZ7Þ¸Xzòݹ~µ>ñàpýÓÓµ®.×?¹¸\¸qµ6Kûðjý¨×®þÿ͹}àò’²k}ðÁÁúÃýúºù¯˜º+ê–¦,=< ‘î°¬û»Î¢·(u&RÕBH±Ñµ5@9Ïà@ætT›½älÊxxx¸57’´AM(Ëlö^±üO²ÉnypºŽµë>ÑokB=|øð¹fVê‹úínr>Ü L›*õ}Ò£4ZÐ;kH³5þ½n-U%ÌæØÃÆ*]NãS ó¡|Ö[ˆÒ |îÀnR=Ë8 OtL=æµ’.ÈsÞjÍ8ƒ@´?´Ò77Iug'''ëøè½A|?îÆÕºvtµ>úG­_ô1—û¸ä½~®õßåõ擃uð~˜RŒÜkÓ‰ÈÚPãkBÎÄ€u·Ho7áV"wRŒ¤Oz”:“Ì:{uYV`ìÀn?µÎÜ0BgÅÝ»w·ŒfÂW}Fg|”7©ñ6Ä ´šŒ4ÐQc4rb€i†¤¡Ž=ø:ÃcãHK;ë?ƒ°ÙC§DpÏa&rÕàDéR’a þ™‚w«]“ñRÀ@I{eeU-LŒ>zôh€G½×ˆÉŠHÏuÚ#ûÕWÛ~ÂyÓ8ÙPÓöþ;Ý™í%Ä–¸U” Ž Àm’¾R;ÊÛÁTá±e¤@®vh׆nv@•r3í—{ 6µ º#بï1£`Ã'ƒ4K\ õ¬Ùa=±þì¡ãFdF£Èr:oéê‘Vh ÊÕ‰H²RÐFÄ€s—PP! ôÔïØ03g ]=,/öýjdÚh¼ßJîŠÝf£Õ~öÉ w=‡^—“·¶÷ï²Wîµf5©ùß½¹Éܹsg+°²J9³1———›¤C¥Œ„¼ê)æ7û´K;ÕFгўy­µNŸ=zÏþÆåú¯~É“õ›¿øö:ÝWh> ø«uûÆÕúìÏ|´¾ä'¾ Z¯¬ÿáÏßZ毽¶þóþh}þ¯}°>ûŸ­Ã{ëSo®ßþg¯¯o²ÖåÁáúâ¿tk}æ¯}²þïÿàtýÝ8XuýjýÀåÁººzGØÿ¢ï½vµNÞù¾ƒÃ·ÿmØ}p°ÖÍkWëx}Ä®ï{x°þ¯»¶~åO>]gïáiŽU~ûcý@Â?&+Ë·ÿªUðR'â^àìlRÔ-~ñœÓ´F+ZuÒ¿;wLVª…è {ÉT˜m:Ǻ_µƒâ-??z“ØoÒ§ÔbL‹âZ,ø~¹ Ó·sµ3ÞD¯Œ˜ª]öB‘MÓØ‰ŸL&†¿]&WÒ«zîJGGG[¸¸ß&®ÞeË­ÙQAžÖÔ¶þP²±Ë×jJÁ»%½_ëhñEõFÊMfÞØ»&ÂÅöбÿ¢¶ßJ6l_ñ\Ÿ?´ŒƒÎ,ZFÒâwöi1õÀvÑ£Œ[z•#*Í͈¿Ì¼Q®ƳƒéŒLåÏÊ×3Ò”š6›}¶˜šÌ§§§[õ:–4YÚ¬O›]¹æ½k<>h–'[»ÇµÏ±ßzô·nB³š¤Wy×Üä²nì~fÆÀòbÑœ]ÊHØ”¬²qãÑ&æ¼”¶W âB/Àllfè)œïßuïV›:lôiož{ø@\uoé{^Ètïnbýv]TÞYÔµ>÷ÓN×÷<8\ÿ韻¹NöEšJ*Ѻ}ý»ôd\miSŽÖ×ÿàÁ:¸:X_ð'ï¬/ýäóõI·¯ÖÁùÁú‡ß}¼¾áûÖÕ;Óê;¿íúúõäxýä¿X7Ö7}ÇáúŸûhýœ›‡ëáåîŒÿú¾ëóþ§k묵ŽÖzöí7׿ýEWë«¿K5{ëÖïþ·×·}ÿ>šùH]OÏÖ—}óñúÜO;]G‡ïÑiþð1sÞ™Ò~-F0)Ôþë^^ !`5P±ò?Á´Î[žƒê@¦©Œ ;-Òæ:_=§ÔYÁ‘y «B{h52JÑÒ£’L-E¸Ò@Ê3:ü#}\3“‘[›qJ˳âbòQG8i{ÞÛ|¿tq«Ru]ÕhÊ‚3ÁßsŸ¯[š þ0@xlj€ë«jÞÍjÔì¿X 云2{ô„ |¤ýÏöS¬ß¼m.LíxnëÏ$º¯‹mŽç999ÙUOÀ«—xQ·VÎ-ÔÞ»Kp.`´Z£{B¯§ãh2G ›^à-¬ÙgFW6 }Õ§D a)ZlB–§Y€€Õ±s²õ@Ìê»Ð›lNF¦½²“íââbC{slª h¯<Áü´®6ÐqìZˆE•<³I]j«›Àz”;ç@!]Éæaµ© `=vì$í­±³â?vúï›Í)È,0u,€7HÌÍÎy;E’­í­6¯Zs¾®©^ßÌ‹'Oß3A¿ó·þì§ëþ“ƒõ_ÿ…k]߃ʲ`æÙÑúK_ÿϰ¬º8X_ó-'ëkf@Båû¾÷hýåï}çs>út}Á'\¬¯ýÒ£wkÎï}r´þüß?Ú|ÖÅÃãõ%߸ýggÏ×W|ãáþ9}„¯¿õOÖ?yóp}ÒG]¾'g‚îž ÅÚFã9£¬«þÖ†—eë'zâ#!ûuHñ13®˜ßsJÀi{ŠÙ¸Ðû>Þ9¤–A]Å3Ù©KšÎX6Sè76žcyÚ[Q)QÛo9>>Þ2ä1PQG;ÝêdaÙô±çþéYˆ¯ÂJ*¢¦Å"*“ArïÞ½Í{§‚lšƒ¸ÙÌÓFïñãaCim¡â½_^^n¨aáêlÍ›l·{]këæÕl˜)“i2f€<+.àl #¾±YèsÁLå¼o%Çéþ`d8; êªÑBPØ,7µÚ‚(ªÕk\¯ð™õŸ}Ò*È¥kj`¢øtå‡]ÕáÑ£G[=:^´ÌÓbXŸ€UG¸(DUÃóEåfcš`i!lô¥þFG]7¬†éÝݽ ÖÝ´ òZ0ñ$ûû,†û‚‹é†×b4È›ô-ÅnNæî½j•:äYѱgÍ 铚8¬µÝÓŒBïÉ’Ó»ƒ®`zØ8ÙÃÇÒl‡«TÏÆ¹`EÆ@Dzt¿}è¼ÇÈÙÅZ¿÷=YŸ¬?òå×÷Âð—øúWÌÓõ>ël}Ë?>^ßsq¹~Á§­ÿäÆú7þöÑZû†—ïù€÷[¿ûp}ë÷¿wƒÏÉGma5´4ÐÉbXPÙ91ñv¯C¤Uè `EG¼e a²2ü þi/W‹  bþ^—nî>µQ¨=wMvvïVl½¡}²ã£Q‚¡n²aó1Nt>ÝÕ,tê4ÂŽ]`{W/ {lf}ªÏwlµ®nü²¶ÛM«`¼ª„öË6½ŽV×ß<[ ÒÕì­·ÞÚ`€éô[¢V*»úé«««uÿþý­À_¦’FRÝûíÛ··æ©¶Ûغ–9ÏÅ?&Ág%ÏŠŒA Õ*1æVŸ™É”¦ÍÜl|hi¶É!M¦ÉjùsÚÚ½5Ñô‹,†g‰M×1Ýì\;í—g¿ûu4Ù›™‘¨â3mrw=0)BS'¢ýr“ÅÉZuÁ~!‚ñ8žnre4̦4™?”M7:M1¿Õ®HéøÖo°é¤ŸoÅFÇ8Áªv¯³ã²}dšs'''›`'·YV6Ñéfj¯ PmFêoŸZ " vo%ªr:oì¬%ú˜ö·ñ®Õµ={öl]\^¼'©Z§kýŸýxýÎÏÚû5¿Ì×?ùΓõÇþÞñ:=¹Z{ã`ýÕ¯¼µ~úwkýƒ½æé}Ðüo=yOÓ=K†zÎÉê8??ߪJ¸×†o:Çt§Tí¢`ÈtN†¯JfƤһ{½Dñ´ö öŒ/‘ÛÙ1©õŠ®›Æc:sÈ2§Îæ۳WŠøi—;§lŸÄîV£¤§766ÜÕ"!ŠÒdUèfçûmä©c­¸x²*ÔzÌö:sIï²Ò§=³úi©maÇž³ÖÖ»´U²}t\“Ñ¢«Ø´OžújƒÀî½9]oÊž±v¸·yÓû5Šêý2Nì=©dØ¢+ü³Ñ¦7hr8ÕBØ´HûAZhéšlZ K¯ò†‹Ì´¬´Ú MzUQy «ÈÓÈÒ@¦@C Œ`;ÀÙæ1k£"f +.³¢ò¢Ì¹¢o«Yꃚ :7xï=Üéo ³«Y–›`“uöÈqSlG›“Ÿ[ 37ø]b´‚´è`RÇ p›“““õÖ[omþ¶J›Ü´_.ˆì¹Ï{wÞ5v>»6™¾C7Ý^ª$Mê˜óBZAhÁuçE U§-1¥cN[Ë·Þzë]íÕ{ØŠèèp­ßõóž¬þúåú-ÿë­·Ó/{æÑKu=}x´þÜ_¿¹þÜÕ»àw®}5íýr­õ¥ßt²~Ï/xòÞ|¦dì;÷í°n RÒIã­òg"·sÆ F›+ÿZüNAûÌœwäM䦅°"3;¨ïÒJHÏz󠪇ÄLRë¼Uû ÅþÓA°o‹«Iö2‘á!íÎ@F-iÏцáË6S???ß$©§«Y¿¿ŠŒžþ^m•rÉJ½›„ß(æW’vT”¾9¼ì@üãoŸ­9’døþ‰ýv1RlñÐsÖÜ™Ú)«U½¿± ½È,@Ý™®¬bÇX^éêemUfûvu±¹ö@ µð túQ:(XUh25ñZHjdÔÀ¬õ6…§Ï?::Z<Ør¯Ò;j™÷&ÏQ›¹~Ÿ“=iÙ‘ªö 1j6ãNúS€ÕÉb§«F µì‚Ò~Ûƒžë¥"•K¡Ÿk§Eðì#Ó÷ͨ]AÙt=³crÏ¢²xóF¥öƒ6ˬ@6oŸÇo¸nŠ0 »Y’ŸöËUgÆ¡û³ô*VÊ¥ccÿ¡…tV£ d&÷¸ ÔFam‚Íi6Ù–÷(Žººz[“ñ«ʳõ7çƒõÃîím›_ÆÌý:z'5vüÎÿ¿dÞ?×áZ_ûŽÖÓó÷æC={g_t?쌃ˆLf–*È);FAW2 s:ã=ƒ¥–w™YŸ Ãûmiˆ»Ò:ìb„_^¤öË3Ñ<;›™/2kl4JȨÀ„`_ºµ=hìÑ3ÛÔ¸èÔKEV†W:ÙÎå,‚gk5ÆUš¤š ›öûe¼8¯¦-wçuذ9åO=²¸¸Ï>g^‡/š'S;¥¬àE­3¤â‹ •Tô~]aëñ3Ž¥@Nɇ½‘lˆYEf&z €3Ào=̤•0ظÿþ&ó,õ¬*ŒÙãú}º¦h»¨½ŒC>g 'ÛliDÏQ»ÂÊ{M+œ-ލöÉwïÞÝjtÿþý-ލÓÓÓÓÍd·ôÛä”¶UµØE«,­h|Z…|V“ fŸ7ÑÙôh ¥GéúÑé@ÌæÌf¤ý¿_ ?c.ôÄp-ðœ½ti‘T¦·™hU‰ÄþfKjfiµ¶çd¥®Mj ޵b~m-›[U|_}Öu{icpì\SÍ}³|³JÚÜj”Ñè³§#Û{õººZëÇ}ÜÅúòßö`}Ö¿v¶NŽÖÛíá÷×þÚ_žÖZ_÷]Gëø=¸•xîLzÓƒvfµ@@ëÎ)½Ý꽆>E¶Ÿðu3ë&¥¼hH/šŒ“t¬Ã¤åZÖwKŸšýÌÄO6ð °ÚÝÞ1ö÷YíꌚZÎ]öÌj€«è˜`oÜÃ?a€Î¹ÎáÀ|gxøÇd¨.dÒ—j¡àç«Ñ‰’¨Sé믿¾õo)‰bCñOc#E Iî‚ådë„¥ÊH‘7Ø]¯ÛŸ1³qwtÉfûÌ„]µ,·Ò'­Ï V—55Ä7nÜØ¢Ö‡½u¡}.˜©êÐÄñ´‘Âê§OŸn]-¾YÍV~ìGë§mdÙwm¸þ<|'zb:Ë“šÖB.Œ·Xnݺµe§¨ Þ׋D T*ÛTòôôtk2[ÖV_¤Ž£Å4;ßNûÁÆnºr” r¡76U z]牙miì&ÇS'0Ëé¼¥°¨Ûîö ú¬;of5Ë…>-Š¥W•Qxµ¬…Ð%%À†”ýÿ½ß…n©‘Êúw¼ë)’´”Ûë LÍô¸Ñ<{ölË5-Ž©UP§#Ê{ýº¸\ëãï^­?õk­?ðËÞZŸú‰k=[ûJÍþÚ_†êÌ×}×Ñ{ÖžYüÒ9¤)ÍÄ/V%f¯ºÞ/_ß>ze—¥ݾ}{ËÙTl Mg¯ézõ¬Ï«¢3u°¶)˜öÎþöI«3ˆ‹u¡Æ¥Drô3ï6~®â"-OüãëÝ»²†]¿=³õCÝ{ØËj—ÚìÎx›±ÛOý‘}ö¦†7ü0eilzVÎ+éS}VÚ+56Í»db„L´ú~©iÚ7;ï&=K3‚D´Ožä T4x°¢’Bzv¬Ñ¼Òd«ø'°¥AèÔOZÊÑ=aöR™`<ˆbýYr¡é£^‡RéU•NËHØg¦…^–úñãÇëììl³°ò hõúžý>úûµÖV§³Dû‘èÚ±K_”ëFˆB?3ö‰ÙÕÔqZðU½˜>êòsõ*·"c6ÈÒ®Î}ïÝ®¾f²l¤¹gì½E»ë¹(MZ] YýÌ[o½µåœwûöí­’¼ÎÙÙÙ¦b2³%³YV¿·…^¦Dj™bý]Ú¬^—_«ëGb¶æ´MV»÷^w¡7¥Ý5§Õ½_®ó˵N×úÕŸqº¾ø×?Z¿ïsž¬“ãµÖ^l¾¿ö×i0óµßy¼Žß{û‰íú¯sЄ™e“Êðˆ`&ä:ce=–?TÝš4µ PJ]KK!#E§,©a“SË  ^°XwlÄO&Ôó:¾…te²ƒ¾¿±±Gá£G¶šsÞ¾}{KŸýjj€û>u°Rç­6éä¥ã›lOÕÈXíjl&þql¦ý²®¯SçZ€ÚwÙCPÙÔ¯IY ­µ6Õ(eö‘ѵ5ײ°Œb}õCRÅ^­))ŒUËšç½^¢WƒŒæÍ®þŒid îg¶U™éGOPÖu0˜b8Á¸7,G´Ï—z5}Ô‹ì $æ©Ä¥ø>úSŸÆE±Ý|àÒ±äÇÊl±µPʵ6˜ˆCk #E¨ÉØ÷Í@&ÁºÍBÕÿ´Ð{wîÜÙ¬³ââd¶×{éq‘6§ý³Kên¢:fƒfWߌ^4oâ6¦ÑãÞ½7ÏÔ°ô™Í =äåpÚ_H플¥Vˆž­Î\É*Õz8i”-µÕ¨*umò>÷Èu“6øïj#x?…4WïTi>öÎåúŸùt}ëï{sýÆóé:>Zë`¯ÕØ_ûë‡$˜ùæn5V}¯\Rt¦q‹V÷7Rç¥ùî¢ Æí¥Ò9hs?52&Å>ÜÚËMÔî2©*Ñjh¤uöÅ0Xÿiè#­®sH@:u²ê‡ók6ì½½þ‘®d%­±™Ê.üÒgäºêØÙ"AGZ{ðt¦‡-ṵ̂£Ž¹:‡Û+¥y3›¥æ Dמ“óÆJ]sÖ¶$ÊúšWÍÁî݆ÜSW5?Ü-öÔÚzŽm”B“­Žlœ~kŽºt{;9o f¶ºôÀäâi¥ÖB.²œ7­¨)‹a£nûÈT¦¬«uh2Z¥˜B=yŽk­­ŒE“Ýß¿§zˆåÁù~-Š Ú½uWiu“Q~gìšø•µw9¾9™µ†”SéBWˆ×¥¾È¨Ø±-[aŸ™®t šnÍ £ªÚ^îj ©Q‚.#ÓùK~£ö{è4¯šK‚}©aÍã©ÈäE7ï¦Û›ðt%3`Öõ£ÝÃMîp¼k›D¹ V‘éÀ3yP ¢ÎK¡ úš÷ëuq¹ÖkׯÖúå×ïüùO×ýÊëë¯}óÉú–ï;Zßÿ`וּ¿ö׿¤ëû¼'“‚û§OŸnõ‡Ó^9j}ø&°®gÒ”KJuŽLjýdeÔRÖ†ç†öÊ3!gÅDÀª‰Ôx­§»¿©A¶—Jg¼ç`U‰ÎJ)HŽM!=ÇÔåzVbz6vîõéX«àÝ Ì$sÉÐþ­¾§÷h†¤Žcš!™6ñ¬µô´(nì |ç÷Kë“B¥,ÁJ]Úó’5¯¤ÉÍöÊd5·L2«¶¢c`ö ·¾öÚk› OЦ]&¤†5ö/r.¦n9é â'g·‚™èW/ê²YT-µlW÷Vu ŠçëN»·š}¶bbéWpnf^ á²ýÓ'ÝMʆOaRǦ¸AÜlLhT]ÐróæÍçø³–FwÝ»™À¶‹2üêD´è› }:–´97öŽíìѳk²5öò$­ÔI2S•ÒØÏ/êžÖŒsl§mw÷fÅÆ Okëþÿ9ö³â¢Ç»›œÙ]UJ7)õ?³ŠÙo´WÖ³ÜõÛçš›N³Ykòý|]]­õÖéÁúèÛWë÷ÿâ'ë·½õt}Íw¯¯ùŽ£õw¿ãx}Õ·¯oÿîwŠÐ9mU“>Ø:ûký3¯ƒ0öxr IDATµî?9|O3 ggg[@hê ¬µ—h/>>>~N«YõÜêø4;2y:¼Ús&<²Ë¹Tl¶ÖÚªØH_™P“Ö¯QÁì‘£½r— +Õjªe°½D`\­¨Á†ç˜ sXúy߯éBøHjš—Fq]ÏfU`º²†OÂÅê‹l$o¼>ëEØq6Älì&þ #„iÔVÅÖq^E¿77fÀ]Ôw+}i/ÒFÀtïêâ5±ê~›7=wX]ËúíáâÆc6’w^n‚™]w$½/m§ëXŒUEGz‰+Èj§®Ô²£££õæ›onûüü|«Ãz€ÕV‚¬~CQs“F\÷;¬ë:6Ý4+ÐHÀŒ‚öÃM&í™]ˆ³´:K¬&IsáUVv!»p“Í>6êDú}Úäö¬t›Ù˜²)Œ6BuÞXMš‘j³º·#çE‹1Z^™¥É=îpìgÿ£æhIŸ¯+GsόɮM°bò¦åÇÚ?È’¾Y.-Ã푳+[3K±ïçëòj­Ç§ëÆÉZ?ý“Ï×Oû¤óõôìt=9[러¯û®ãõ ß}´¾á{ŽÖ7ïázôì`ýà“Ãõìéz[s³jö×þzAÆ`­^¬Ã÷heFšŠÌ¬®—]¿qãÆfÞ¥…Ðy´½¶ &±¿=1Ú·íÒ^ÿþý­s£sf6Ÿ€µ³1Àع8]S;£Õ¢ê%=Jg¬Þo¯·©™Ô3+.žsþ¶©6(›Œl³³³-‹á0€²ön¹ñNƊد³rÒ¯û]“äyÓ,IëjHÄ͆–ilÄÕb˨a/ÒÉN{åpµ8Y#‚^ï™DêZ– –ôw±dÅyѸ¨LÜ<µá5K½Ÿ`m*3ꌎ\è=L]ÇÎÎΞë÷1R`^‹aËserýp>xð`31///×믿¾EE“GY0Ñ&‘½²š›{÷îm•0S#£Fx­µi;ÒÜHVÐïsÞäÊÞÉ–[j™‰Ú*6}ÖÔkVoîHÇ´¿b•¾@ëzw,PïÖM¤<É]e¢(FöÔèËÚDt Plà5ÛlU"0?Åúýöªýμ¾º¤ÙÄi¡§FF׎ùÀ¤WéÚÑØÔëD ÒŒLm˜) ÍH­JæÕ5y'uÌÉ¢þÇÅb•#Ú]‹ÅM® Ü*‹&~¾eëK‘A^eç³³³çJòVlôa×ÄÁç8»W1™òìuªSV°‹±¢©Žô¬î½„[›4<ѧ¤_I?99Ùz½Ì{ØÂîñÚy†—¹×Hªß)µ¾³Ù$¹ô©~¯Î¦ZKk†~9==Ýj¡0{ð—´×õL}µ :§5õ”lhA,=]Ö†¸Tëj¥ê£Å†bGØùÛ]º²º¦¬¸LÌdBii. Ì9ß3 ——·b¶ fÛ‚&}Я_¿¾˜ãj¬FFÁ•ÂÒ`lîg‰­ŸÎ=,Kh.4)G6}T”mÕ¢ßâ€û@tŸŠBÔBUæ½O ZÇ®û˜eg­¥ÿY:‘îõCMJ¿Õòac/­®¨ß Ê Š¥Í5ÙôŸ"È]Ï6¹96–^µèsìå&ÏØ J{ä6!¯²)Óž¹û±£ñÌdÈTMq!·‰µZs“sƒ÷±óíÅÅÅ&Se·èè\\\¬‹«}#–ýµ¿ö×+ZQz“h%+õj­w5³zÞÙ6zÙàÎs¬÷÷zI¶Ùô:À:™]jA tú¼r•²&Ô¨”Ôš¬Ši:c?3;°;6]»zôˆŸbô[Õuoèhä”}ò‹42Z˺ñbžÉ¦™&Ui“ÞÔ¼°m‰`¼D¬ÚªÙ½Þþ@:sÅ ûiëÝ5[0¨[öþ]fÍ9+}Ï@¨Jäì-ÙØH³5‡ô¤$J9ìó âL.8o”³ˆ]ð p`¾A®y_ƒ4££2FåŠù]B©eq)BÓ"X‡¤Kôª>ÃÒ¬™wï~¾éSýF¡ÜMD1›:+.‚åÙÐi.D'£b6£æÆÞ²²c#ÒMQ¥^à6m²kùR·—&»:3R+›NmU¯Oûemµ[h»Ž'=§û÷ïo•…³žî‹RØXÞ»woëó dÌöØuxÎ 3Yfšº³|Š('­ÎlJ‡_s´9©Fײà»wïnùùï¯ýµ¿ö׫xEóè*6)@±&ÂÚ+'螊…{qøÇs(Ü]®e្¨“>ef¼Kz”ZÐÎ:ÏðÙgÏDn÷k‹…(@â+õÈÓ~Ùdc:Y[0(H¶ß9yuuµ%(aî ì{/ɼývÁ¼”ÁÎÿðL¢Ù_1lçç÷ëfº–iËm=5¼*ê—MÔ†_›ix»¿(‹ÝÏœw#¤?2‰nÏÂé,ãD'cµWÝ›c'nnÍI«‹r'ö«¸ášR8“ÐkÑg¦ŠDVj ߦཿ™Àqåî)h6ylXÙW“bC©i#×W·a?‘󊜊ê?”ý³ƒ¨ «ÈÔ¦AóÍ®»VTÂͲ³ϺÝNõRྌ€‚x³M6³*£Qv ¯ûKˆØFX¯•&|®›´<ÊÙ=Ö¦IFý-†î³ m £ÉDÙËȳìܽÏþD-’‡nþ½ÖzÎH¡yÑXÞ½{wóýi«f×`K§ðÙÞ{c£ÉLجø”ɲQé|nÒ9Û¤z=ËÍœÓÓÓµgö×þÚ_¯â%(ú¹{yÉÖ {vÖöâ™”šÎ¢iLJa–9°ÖÚʼè„E tLHÍ>yáŸ>CQwçœAœ:’~¿@U% dÄ aCõFú46a ]_MFj˜ÓùXö^ìcÕ¢×ïÞ½»¥yyôèÑVŸ˜×_}K/]Ŧ38°o/+~ÿ¤íM°>Ó~Ù`YVE!ƒ<]Ífßßæ¼èwÔÑ9­>º Ql8{èh(Tÿ"±Ÿúd)šh‰Û[S}— 7[“ag«e£sªïÖ`ì¹`ÆèKûeKt•ØtgðGY&²)dÀÊŒG…?º‚è,¡à}—=a“õáÇ[ý8Ô‰”ÑhšÌÒµðëׯoE ê-;«ÚõºÕ mz¬}¿#ò ̳ZÕý–»·9ÙÓ%$ŸÖŽz…Ë žcÓx˜ ‚[õEò[wé‡ÌvèŠX·,œpÌ °±œÔ3)‹U íÔsmÌmeI¿g©@ï·¢c€|ýúõÍá¨å§Ú,9 UA7³ÇNßÕáa5ËnËV»œw———{…ÈþÚ_û땾J*IiÒ¸¥„]ËÆˆSØÜÙ;˜¤Hk†Ôû=7|ý[ng|{ù<‡ „”Ò¯Ò2t†ª‘©j˜/qØïRÔ=éW•ÛE* 0aiÃðIÝÛÙ=þ­·ÞÚÐò¤‡Oç®>¯ ­¿1ì¹Ú'/|$¶œøFjšFÓÞ¹^,³-‰IùÜîÔè˜ä–~e¸ª„\›7ýWf 9î¶ÂS%ÐyeKm»íŸ(åQl'~šº²æ¥Ô3“ôö‘ÑÞY'Aiu6i=¶4©`Kz” jVpyŽNæ"µùºZ‡¨g“FÓç7Y ™Ng­>CQõ}V\š¬qHå9:™Œª'?¶×uÕhâI›ëóÚ¤[9ž•§½å<]=,}6ùœÌòkûMmÐý{FÕ–?-½ªÿq!*ÖÓè`ŽM“QŽªóB}ÐûOJcÑëëE.˜o¬-¹ï*K—ISPoÉÝLV•ºæ¤½úìî}®)jâÔ^i„  Dc¯»D‘ceçM6geö×þÚ_¯èÕY.ˆqâ9¦éL`Z+XrS#¬"{åIî»<ÃÕ:ìê…Ò{¬â??ŠÉÈ‚,ñOb}/{¹ØøP ŒÉBû¡)æ/Ñ)pïý]ÒŸrM5‰m/¸ÙCP­ÉÆIQ2 µ_Žj&±w%„oz]nŸÝï‡ýz&Ê â<Ãed„o¤W©–É4M²Â‡S²Q5Iü4{ì4޳évófV15¨‰l&"ºùNêØÄ?²´´,Ÿ=wVfšLýhµ,­6¹¬¨¸P§èzв›ˆ>°^ßå>e £B‹¾&H¥Ñ¾ÃZY¹‰mÕ¡@frù-duÚ*6k2wï=Ô~›ô&ËY;ªóÐ ±ò  ³/~þ „;9®•ÛØŠÚíNïØ¶Øì0««†‹ÕF©6Ôl웬e!æ¼ñ» Ìti21³A»ôA÷îÝÛZ 6Œr1à7v³VÁŠ\i…~ÐSÌeÑ`—A†MØrÊ1y ]áîÝ»›÷G7ØTò÷hfí¯ýõJ^žSöC›4˜ÎŠªßÒ|Ã3‘k¯ÏxñM¢Ì¹çZˆ@›=o¢ŽuÎGî÷ö ƪ XMRâ9ÕýÙÐѪF‚v“‘RË?~¼åÌe5IÁ{Ñ߃¶bšèõœë\»{÷îÕ½3¼±Uc<%_Á2ÛKˆ_L¢[ñéY«Ÿ.I¾)ÙX@Y`9Åd ·îj¯~H&Sc~Û­µ6”E±éœ7âì©Ý dNj½Žm³™è dÂoQï“]LÙ€hq‡Ï¥57µÀÇþ#À)Ȥþhý¢-ÓڳŠL«¨…ÜïÒ2Ì…Ø ¶Ðéê¡Å°6q–3§˜Nç­(BSÐUÔÚ„v“S0&OÒ^!6ÓR¯S ¤Å°›b%q'³×®^*.¦ì‘åϺiÏ’û£G6¯·Ø î,/jhùOg-Q¢ž%¢´·Q—:Jó´9i%Ð ¿ …i üýàgà³ÓvR‹ 1µW\êàšÑ@Ãö͵qU[e£²i¿Üœ•;<“ 7nÞØÓÌö×þÚ_¯ä¥{ÔL*ÙÁ]föË®ð‡4`¹þV<ǤÊ+löõyÆw.¤U˜Î¢öJÑ‘­Ì¸î þ}ýD|ÝsTú¹ç˜íîÅÖaÃXþ×w™õÙP0+*‚éÎ>Á´c£V´ß®6ªï:¦+ZUŽðÇⵂ8ÛKtn‡ÿ¦^ÿ®Úåëö2Rw®¶©geV"5¼0ïMmzÿ›’Š‚À>ÛJ]¿Çd¨Œ-ËÅíR'ÛG––óÊyi,Ó5 ð9Ú|u+˜±çEo´¼ht%T¶Š ÍHØRñš¥Ïs>í‘+Uåž ÇtÚ/‰UO!_oíbFŠLŸoé3Ó„«åAmxm¦eçÜ&”mÍLêšTc+/)Ø%Öïó§…pßg¥ „ö…þöÙÔèÆ›Ò­”CõC:• ë3ƒ½¨»ý,;«]’{\n[fiú¨Ë›ŽßÚ†'ÇSÊb¿Mî±´<…€Z¢ꔣã‰BÁ]ÖÓ–…7‡ßÓ³=¢Ù_ûk½’×ÁÚNf¶—Oc•ÚOè.5í‘mènÏ/Ï)“™³ÏžZÉÙO,Ðf5)FK¿Y-ÄlÌlwzµêDì“g‡÷ù~ûðÙkEê½gxckûCµ¯Þ=Yš ¨–ñ˜îR_´«OŒ}îdã¨KѨ*¦ÒÔGO{gçUØ/ZšT£‡ÅšWq=§æ…zžðŽp‹{ð̱뷆éÃB1™¢¾ëæ« „øhW[qµ1ì¾ÈšZj™Œ©iá¯-kfØìYaé3 ˜ÖžÙ2ÐZk‹+èûuõpa|ÔG}Ôs½P¦Ö¡Ðd ­{éýFŽ æõQ/P*r,™U "íÎ"mïôôt½ñÆ[ïìKËëþg÷zÅönzähMmi¸±ÐšÑ ®÷¶ è46ZS·Í®¾–OOO×;w¶*$i§öZWnì—Ͷè7çBAïÝ@Ë ~ Íâ ·±Ìj“N~š<$ÈÌ ¯*até–Óº±Ï—WhVïÆo—º÷ÖÌûkí¯WôºZW[m:ã:ïÕ#vnˆf22ë.­gž®|àÏáŸþ6›\ééºK™ùöœõl°ñá DtSëëB3£¹öìœ1‰­uu ÕØ˜ø¼wïÞÖ¯QÁ¬f5vö:™ú%ñŒ²“ZWK o͆”bÃz¸EëÒä!ÜÙ¼9;;ÛÒ56b©’•móÆ ¯{[ên7]Ϥ<žm(‰b?›MŠov‰ýÕWÏ@E·:{'…ý&íß±éýÝg‰Ú~{•6+yÒî4ŠÚ`cA²`8P saEjñö¡•Û*Qõº:3ïýÐ7Þxc+ŠÐf3§zÒ~SÂSG2Kt»J¯•N­ X“fWÞÙ¹¶ßn3ÐYllzà‡‡‡›{×BOúx’M8 ½§ÏocŠG9Á¼¿O*šöƒê‹¶2û˜ؾŒÃ|®Be,z@èá®-wó&ªÏ½êŸ‚0ßß\èÞÚ8ÜDÓÐÈÜ ´ÒÀxàY6W_Ôo”Û«Q‚Õ¢î·lЏMÍrséï MôþµÖÆšQ~òþÚ_ûk½jWû±¦6&•´ÉÕ _­ç¤³ûü®3:|òÆol%ZeШeö)¡u~~¾y½{о¹sp¸íh/‘óh˜È9ѧbwN©-2hcÃ[·nmÁ3™¨¾'L3ÛCØë¤@Eª»Øîøøx£!îêõ.«iõ ìü–Ñ"ío6ôÞKOpø&|ÓÈdã¬6íJÐKƒÓìÈJ\ów2&ÉÃ/â©{÷îí tškšh…ë­ ¦½j*+¨Ð½ÚgÏjÕìáÓ<ìõá“zo3O«”Ý‹½!7éVãUªA¶D¦}rÑU;³úÚäJS÷aCK)@.T¿/GŸa LŠQ“­÷7Y=z´ÉÆ(ê¶y¡ÿY–Ö‡]êYQ}‘­Î»šQõÀu\³¬Ü3r­j` ãä–Z&­Î`@ªÛ òt9™‹Êµà«*¡ØmFíRs阢а×Ú©3QK5³-.tßßxOëiÝ\ 4 fCL9 “:&5ÍŠQ¿G§œ²A:¶ NÚžÖÕS„ØßÎfž³wÒ¾ÏÌþÚ_ûëU¾”º:×Õz×0|Ò|ÍÌkŸÜ?³ÏfÞ ²ÜëgU¡ªƒM(¤šå¨5©õþvf†fUÂdggÌ„ðQŸi¯”Îxis&ìLöé¬ÕßH ì›ä¿”Hï žÉÈî}Z{o¶h°*QâZü$½Êö:—ê'}«û)@¶eãlèâfñ‡Aœ&Ua?5.៻÷n%/lèsŸøg—d£ÏOW6èî7lþ’’hÅGý³Úq›·f쿸3˜‘iyqWC(}Ò»f÷yˆZ‰Ù9w"ÝälÜÓBÖ~°ÉZy°ÉßëS«ÐÆÖBVÌ&=êæÍ›ëÆ&£îSÑ«´¶l] ήÀF‘qÝ¥Wu÷ûÜä´àëßSG"íÎî¬6lÚe¿lyPzÔãÇ7÷c R&KýÑÛÊV³»¸Åý^5$Í›Ù5X±œc3K³“«öJí”Ô5K—Rú79¦vƒ–v·+.RÆB^µÕž‚Ü8¤}þÙÙÙ–#‰AžA¤™§9ïö×þÚ_û땺®Ö–¨; ×^Û^ýäÉ“-ûå@WâÑ£G[Ô3ÛGtƪ9ñõÎ kçP• ͆:Ç:4 ì›ëœõÜ,¿ˆ D:§²wö ïŒVë -oö’“‚Ý97›¡«–UaÄdæÉÉÉlÏjR˜a²"ºwƒ+<S[ö›Œížña™ªA=ãÎx+}¾Ú&çØ°×d¥´¹©½šà]nu»ðÔ³‚8ûÀ4Ç D4ÐKË8 W÷ìLØzCã¤]ºûÉxÙH4]½T&P·KhÚäÎ>2½' `mææ€›i/q@âåòÙa}WãÃi7éQfÆ¥–U¡r“êÞäp*Z²4*XWð.ŨlQ²ô)_ïo,ÍÚÓ²·› U…2QeZZ,ir»&pQ³¥Õ‚DõEÚr'î ŒïÒÈÈ]61í—Ao5¼ìÙ­kÏ\é³uÞ´ [¥ìÞ4¡èÙZqñðë÷Yv6ˆÓãÝ…®Ø¿’¼UÅžû4R˜‡«•¼«½^fí¯ýõ*_ïb€Î>+›pk/ïÑXÅD®I¥Î™]ý@fÃKñÍt%3þúë¯oíÝF3ó2d¬hKäöûJØI­‘Ö{+P)ëL ßÌ>wö‘‘¾=“ÜS á9vrr²y]£ûâ… t`¿$·cësúÔoŸg|¯+Ö7 ÞswÞÈL·`µUá›i-=+6âܨóýÛJ›ŒƒñŽ®«U˦FxŠý›£³NcãØÍâÈ.'ddé˜Ñ-Å?>Üf¼lÖ;ÚƒÀ¼LÀy–ë.¬h.š ˜9×~ÙòaŸ1-‚í\{yy¹îÞ½»5AÒR4H½Þ ô@,ý꺡ó–<¾Dê³jàBª|8'K÷³k²Zb3œî [^á6|’‡é&w÷îÝçì—¬º?ØýµMµ¨Zꛓeå(‰V\ `uÖrö9Ïy5õ=ýžJ—U•~ðp³±D»“+˜/?[ŧßtûöí-c«UÀf£6 iX/J«›¶Þf,zN°Uú¤åI—\ë]ùy¸ZÅ”‡½¿ö×þÚ_¯da†3¨s]±~I'Ûˆ|]wO+ÿVÚ«û÷dMÜ»woël¸ÿþ~QGÛ^ßÞ~qq±¥‡ìœ “äJæÞþ*£m›ƒX!ý~«ZJÛ¦ êG¬ˆi”0u¬6ÿ´]øF<¢F¦Öý{—>úÁƒ[¹QïcëˆMý~isš/Éh™ØðÆëæÍ›ëôôtÓ²ªFsÊ3Øxqâ‡æRý{½{³ ´Ô0µWS’aC±¾´=%ÒÛµ¦6š•ÄÉöÑ ¹{ŸMd¥éwo=‹Y Ó7Öá×鱓zvwÝÕ0sÚJ³)3ïҽʊ‹™wƒƒÉƒÔµcú]OÑv^áFÚ3²TìVéTHï/£¡¨ªÆŒ<µožÝçu iÔ¾Yw£rrÿVŒ/½j–´>ì]ŽrÓ‚Ø(Þ²reçî% eçJ¯»8¢öà1f%8—úÕokaîÊD¹IÍŠN¼›¤Aœ µy!5ljpr=ëY[šÝåÏßB7°rŽîZSm`:õz¯Swæ&stt´®ß~mßgfí¯ýõJ^çÒÏuPêšVûíµ&­¤Kóµª!Ÿ¿@fj€ D¦Îužá+Òb¸3|—ÖA°/`íýºeMW³©ƒíœ,Rðn3Ñid³ÑÙcÇf£jŒ'¾éÞ<Ãe•D€‹¤ÝY-ëo³îR–`2r¶ŸPCÓ³‹þd5Kl¾q^L Œä­ˆX 0ù)u,6Nÿcg•C MóF\=¹}cuºRKäžžžniÓ]3%™VIuE7[r^¨_ÛÒÌD ›¥Õ@Ýéwù°ûþþ>À8;Zµ3®!}Ôõˆ/¢¶ÄeT=ý®¥WÉ£´b#Oײɵ»ªÖ¾®ØÌ…®«YöËS 7_%X6ÖbX ½im­G½ÝYÛÄzÖMF7¡K 4ÔE-s·|¨¿~Ͻ@gnbÍ+3SšLôù Þ«èLmV iv®uƒVLWÛëä³·’¥WûÀÈŸµââ&7¿™¥sÞi{9¹Í=GçU€âÿ]´¹‹ó'{D³¿ö×þz%¯ƒõî^.+B-§{­fGb€]Œ[0HÍ—&l "뢪…ôóI½ŸUƒè˜h¢jÏè‚4ÍÄ'ž3"ßtÎÄ8‘¾í9)³ F‰º +&줾[Ý’:†0ÐñŒ—Z/¾š½àz–öš½RÄ7V vI2¦±ÉF“ÜÑ]úh©ùâ›Ø@Í­ÙUí•ÍF+*h!>š¸:\ü"ücpï¼Ò¨Apú#5ÂScç…ý]3:µ¦6–æMˆ©ep¡Uæ üf˜s…f“*ÅHW³¨a2–Ø,ÚaTž¥b¶nz6r@4 °óm‘§¢"Ý£ðîG à&£6tö‰É]Ê(\Œ6¼ý>£òiïœþÈ2ò¬†EŸ²iãœe¥ØbèólˆÙï¹víÚfÓO(ؽ§‘éÙL}QóÊ@¦ï.Ñ9oú¬{ïj³ZxrTí?4K»Fým ¸Í³³³Íç»Ð{6qH{ö6ò lsz—Ϻٗ(‡m¦=ÿÜ IDATXŠõ5àhžT’ï÷d{ÙØ?|øpè76–¥÷×þÚ_ûëU»ê3ã[²Îöýÿ Ö=ÇJ8ªWì ÞÕ/­ïŠþ¤N%üÔÞ¬s–Ô°Î-Á¸Ôû~:ŒÎñ‚–^ïóÏÏÏ7¿½³Ç„œŒ u:—ëØwuïýo&±£G©…Hëþ’YÐØùû;Çæç‹Ÿ¤gäi´°ÖÚ°qz6úöÞ96‚õùÙݬ¸4UÃ¥õài=ÃudÓÎ^sõá«â#¦çܼnNk"ÑØ…»-0Ø¶Ä O[ïæìLR[)T¬o ,5›N}óÔå‹¥¦uºè«,ªZlZðάÿ,JêFö¨qiÐ-ægãBPŸ?FU¾»ÿþÖ™å?Kt9W˜±ŸÇtéã“ÕÑ9SÅÇFÖË4­‘8ŸöÉáŸ‰Ý¦Žµsùõ×_ß2ð™_õÕöbéó;çÌ&Õ'ë#°Ý9£¥3Þ„b›ÆMj™²¾_3€ÎÿðQ}îœi| `'°ßaIìž}Ú©îo6Í5çýþ°Ÿ ÃMRwNá£ð”‰ÚÖSc!n¶IíÔŽ$ÚzÃ;öVê²Qý&~éÿ±3ne¤²ö“ë§ûU`|W ÌŠÍçF`¶Ú…,=jv¯Ÿ%.KhfXŒªw•^{¿åâXûÈæ &^äˆ2]ź—lvû}Vf&²ß[ á&¥CœüXK¯ú¤ÄY•8==Ý ò&ÏÑþCr‹Õ™Ñh²[ñ)£ }Êj—åÅÆCj™åE³Óc^ @•>7ðÙˆÕ2»Ù"{윟Ÿoe$z]KÏæM›¾"ÉI=kìª|Åí}‘P°±‡“MÐìqsyy¹ž>ÛÇ3ûkí¯Wò::<Úê—µÈÌ»=Çp%ì¦vVlv™Úì¢wOk€ØäæÔ2 ¨q¯Ãy\»vmË À^rÒËíå¦ÅpÔ±µÞ¦iv¤Ô$wçý4Š  ÞÓ¸H¿RV`"Ø R3$Yi`z´¼IŸº~ýúF¿”ÜE¿’*§ ©3n¢ûkí¯ýõª]WëÝ@¦„\Zƒ Íd]ôú.гM«èt®Ø¼¸½<¬ÔÞ™kÓlG˪LOúS C{™(œßXu0;u°úH}/A¦†Fì7͎“җr /ÈÆQ– }\}’‰ÖîÝ@¨ бÛŠ¿Cï³—ÜÄnÍiuÒæó:sI럶ݞñ:ÈïjÈ=qsó4IF2`çÝÄ?=Wƒû¨÷VŒÄü%‘Õ_7/ì±c ³« ¶ÞÊU’h0f@ƒ‹M0#XŸ‡5ÈXu¨´*¨ÒWúUô¨iÏlɬ@¨ÍÁŒE‘³M#û¨èÞ`cÃ^P*èš5.-´"Kf:™]˜<ØÊ®¼þúë[š•\ǴГ>½J0Þs›®“¶—³„AgcÓfÓdl¡û·Uâz6 ºì\ÛýÙL´À²uϵ±Ì~PG·î%nr÷zzzºÞxã-ª™óªMÒ£lNÏ^·—=ê ”;ùÉ»l¹g3¬]ÏhoÍ• »Û(¬ZÎà­·ÞÚâ¤V’ïYSâ+©ûj:§f?u*“9ðäÉ“M2p¿Í†“áežCSÌý{&bmBmµÖF'R0н‡õ¢OÙ0<¼RUBÇ®†›öT²¡¦Á‰F»Ø85­ª`{6Ô´=„ΤŒ÷Ÿ”ĵÖ÷lfÿ¡{÷îmaAµSk­-êXc×ïfJsì û¬àÆ>ü×ýV °¥&b;“ÓdËynîó_$gy®2c•`FW6œœ¤ò_oºz('W€æBžåG-ôª*8™ÏÏÏ·ü´»õþ²1Ó¢¯ïö$ÙÞMΪ‚Ž'³{¼: YZO7¾ê@ d¬¸¨ã°ê ­ÏMsZ7öº ­ü¾~ ;ßèØÀJ·»t þ6˃–ÜÛ$ HÍDM7;ý÷½â{À˜ý™Î^»X›…F˳tj ¤ã‰<ËÖnrj« ¢;;&OÇ“]Ý¢>|¸õ,œ7Ò®®®ÖÁáÞ˜yí¯ýõj^šåtnK’~^ à9Ö>?«ßíµR»L&öyé;‡:ƒe maÏÍ;wîlÎéQ&r½w©ñ&rmz-þéLí «Ù/¤×MtJî¬Ò'ŒÐ{/..žkúX cf?0«F¦ïëuÏA©ežÁ¶XÐÕµVzÕZïÊbbTÑ鳤Η$7`;ZÑ™”ÁîGê»AœIn Ró›Wb„IÛëþ¬‚ˆ‹ÅgÚS‡…’£Ø›ÉÀlé¢+™½—š :÷ݽÞoŸ¶ÞÝg×áÌ^”YoayxuÞêG»pu¯PöVtüQ½?À©(É@DŽg€SjYÑa Ý>.j%ZüêL¦ ¯M‘ÒJ˜Ñ¨ô) ÔÁvìÊô[]ˆþ6Ÿ÷6JMþìì…2úÅÅŵ ±M= –e,ÒØè\‘«Ù®M²ˆ^7™ª-”æœ ›,¥f)©­¶Ö‹Ò)T,¶´:i{öèÉ$¢ÅÙØ¨‘±¢Ó&·‹®ÙQ ¸]A§k¦MÒ=Ò äÏJË›ôûpfí¯ýõ*^žÁ³Ìì‰!˜—µ1][§…ñlüÜ~oŸ™Àüu]á—~o`ß^páæ®Îpωéꪙ‘mÒØT½éÞ¤h§õŒN#3ñ³ECøgê¯=sg{‰´a?ÍLb;vâñ‰ÉH«Y}VØPçÑÞ†¬ò+£s¸jc§¬ÁF«Ý»Iäæ…ØR}Oó®{‘‘"Øï½%j ¼ÂŽâ—ÆB\µL¦T™ ½¿ß¦~»ßö+ø‘±¢+™rXѶ'Í©mºÑí¬Ì”µW\àëCŠŠgϲø½>ùpf$š¸6¿é&£¦õysÀìãbÕ ]Ìtåp2ÍÆ†ñh?ÓúY ŸVÁfX•ÿ´L£“ó„®ec¼÷Ù~vW•Þ4Á¶c'˜oqj0«rƒåI6±ËTàNú”‚ö2Yól”:9¢³tê&¥ý²S³7³,>52V5l8µ«Ze%¯`´)¸A÷]mð½ÇMÆ ¼¿ŸQ+2nðvõÝ56m²½Þ\éð+Ⱦyóæ:ëÙÑì¯ýµ¿^ÉË^-“>å9Zú”U1‚g| ¬(F}g¬ ©má•*6ý­ZÎþF÷(Á¶ÉPm¯_¿¾I¸©¥ÔÌH@Ø9æoÛeÈ>é>wábÃúè‰gÔGGA²ÂR¯•þFú¸c3“è= zi³ö˳ٹøÇ^)bÇÎðÆg*%+'µ~ŽÝ‹Ì¤õEËÏȺw‹g|]6Pî4Ѳ‡Ol¢ðPA\\W²¾»à_—bþ‰kgûˆYÜ–×¼1¦ØÅt2|®ÏŒ‘ÛlˆÙB6 TÅ-Ë.߭ϓϯ Ìï·Äàl¹‘èU÷}EŽ‚@«OŸ>ݲ—¶¢ÒÃÖC>­ƒ‚sg ¹ñq“k£ÐåcV£´Öµ#J‘Qwc/×Õ£…^à¤s†å]­ tvù¨¿¨g#UûÌè:¦`ÞɪϹ¿«‡Ï‹ôK–vÛ *É÷››7òk-£ÛÐiŠá¦}eã6lˆãããçšÌJ«3+ÈLc¶¥ŠfÁ¿Ùœì™ æ¥cžŸŸo,ÉM>˜ŒØ_ûkí¯WíR =Û~+ê´½w²&Öz»E‚ûjçX˜Á~!êH:¦wÒ³tßôŒŸ 9{ÅHM«šT’ÍÆ‹Ù/— Ÿôð*"ÝŸ‚wí=£Õü>xð` +özŸ‘~¨{Ÿô)'%¹ úJØ©±Š¡v&‚cv4޶Ÿ˜Œ’*êR „º¿ Bö‰)@.xH’ѼÛe’UBÝ3Ü@Ê 1ZÞ4Sj^hbQ¥Ñg] ö‹²¨¶jâæÆ¹÷ØíêO¤ szöÛÙGÆçÞ¼,o쟫Ì0…=MœèIÓ°‘À¥ÜÊ{ñ Õ‘Ìòž6pŠÝš€•NÍ8L­…¢m3óQ|´à“â£`ÞŒ‚473ï:’˜ñ˜Q¹‚/ßß&×äßÅüZ=æ'×0ž¤ú!mzíþÚmOw¬™±ÐK\ž¤Ï­¨Ù²²Žg³ûkU‹ªFvTÖTb–…»M¤™´Ù,«ìRóÆy1;çÎFdfìœÛæÑØXÒoì+ë¶n´µž‡žÛt”›üÙîUƒŽ.ß½›ÙþÚ_ûëU½:Û»Ë,«ã°b“N$öAYÿ› ¹eUì¢8wΩIÌ›p“&¬F¦sN]«Vlz]zUçœ& {¬Z„½ìÑ#«Ã$sc¥†Æ3¾ä¬cc cæ¹7Ý«ÂGžáà]A ´=ƒÀôC ô}=ê¼­/&#e6jØ«A û•äŽVo:)ƒêúÛ´S%†ÓvM|e@®¶\C µÎkí™§ÉWïi^¨M?íj˜ž3Ði^̱3p »…]ì£çš1¡°¥™Ñ`–ÐŒr@»r™S§Ñ€Èç·ˆ mºŠ¸£iS7´@F‡ 0kÆ ¢m#KK£FåFžfÞý|#Çi¡gÆC0ß›Í<\Ÿ¤?|øp³øvMVo÷®þ¨,ŽÔ4¹ÁZ7ÊUÐ>K³=W)‰ÓžY[ÊÞ?E–Šù'Gs:ºÕHµË®¿Ý›b;çEÏZ1ßéééVÃÍzèxÀÈ­Ò§#œê´ýV,×¼qS“ßjÉ^º§Ž#Ò6ÖÔ{L³¿ö×þz/Zôsu°ÄÎ9{½M¬çRéá&¾Ä/íÅ‚á©ußhTæÜ6ó4«T³£(Da·I¯2ÅÈ„™`>|SRyj„eӔ赢Sf¾ `º¶¨ˆOl[ ëböÁ+Pé9Ȫè¹køcëŽðUðÉ.ÚÞì¿è½ËæqÞM±~AuÎ¥6Ô _yoóýšd5–»´UÊ Â–â“9v³‰ÜæUÎ]®­&ØÅ~½ÞøX h^IU{®2S‰KÀ©ƒÀÉÉÉ»V¯ïü¨ºÏÏ.ä9):y‘û#pkÿ›¢Åìâ*¨¬›qh¡—ù¶³mD0^”­NÄ>0»hwRÏš\a_ãXù¯{ÑÄj×Üä¦c››rÝ[§ãIß-=*0Ýç)8×zºkŽ®`Λég¥nú÷;)³½ì3»^¿ººÚì¯ýµ¿^Ù«½ÐþswîÜÙÚ«Û‹íЮŽ6ê|W™s­h;·ÄfægcCÛ X½ïko—>eÃK·LØ©u˜ýÆbÛøþ’žñ²„ëÎèŒ>ÕýHZë]Sš~¯wjˆ=çvÞ‚+i9¥Cí³«´õ{¬ÄUm÷F‹+¹«ÝLÔ®û÷ïoQÛÕÌ3~¶%‘Ó\,ˆ+9ùèÑ£ ¶Yë]ûe1Ša“Í‹Áš‘úeÿ¡æ¼¸WÜís·e‹•:±¤öËÑêÔ¢¿°ÏŒºŠ¹Pãã»PµF³Cé®É í‡T:åC]ÑÌfû£u®hÙÙ¶ «ï£(XßÕ¹vN›Bîâ·¾hœ`\ Ô±Ù‡F ‘ [°¯³Wÿn£ˆ¾4ÛäAÆÖÕcRÃä9V‰’v7Åþ“V›{›>¶¦>H»BéSŠ0-? Ö{6¯½öÚVo5iºÙu$6+@ž–.䯦yc#T)‡ò¢-¹´¹PõïïÞ£ 6w M¸Æf“¶­`gö×þÚ_¯à¥¥½€vö1q:E×f¶KZ‰G¦N6ásßñðáÃ-Ɖ{yŸxõœ3ÑëÞï9ö¢ª„}hdŒhjS°à™iB-l&ÅÚ„\÷¦®v×½9ÖRË:§´ž6Q«©MÏæÞ½{\ZÕ@-FlœÆÎîöîäJ6»Ó‹lÔöÎ3^«ÆFšÜÝ»w·´è÷ïßß â—ËËËMÿ"-¿¯ye³QÓ«ošc#6´‘½In“às^IS{%£D\k™æ…8WoŒkÆyQ ´³2ãdR‡!…§ŠÈ.ÏçyêØ$…Ǫ‚6rrVg¯”&TG`¾ NjYÙzÅ÷iºfiµòŸîR–fgæÝlŠöÉ-<3M6¾¬j(V³üXyQ!`\jZeëþVëê‚8ï]{e«»,öZÍ y”³Ù–]}ÛÄ ˆ›Þ›:-: ZÑî¬Þºuk«ùéäÏ$J»›}dªf9¯Ú9×±¶Üò¤u‹ÑIG[K7¹Åò_Õ) 4À69°ÖZ‡ûÊÌþÚ_û땼DË2&+ Ôyhuêê·ïjøÝmÐùôéÓ-‹áôÓóÞûêlm¡0©câ›]­?Â8ö’S?d"5|¶‹IdÛç¶›FV!ÔV5vâôI»‹ú߈ý®_¿¾™wySÒa !~¿ß P¹IÏ:6LxqöTVP¢xêwŒ ­&Ïì…“U£ ÊÒh¬¬‚¢¦&Cï—‹×ãbPT]¶_P8›]ŸŸ?×/dò+ͪÑc¾…\ÐVé³×§µâì3£Y€egËÊÝ{Qó,ºÐ¤ÓYKz”Qs¿GA{c77±i£ôw±xoqê‡4:Ìk_(Ø×¿ßÒ³³OAâtÆÐY¬y§‰D›Ìì- {÷æsQ?4)ÚZèdL ¿þ´^tl{ÿ® °¬˜›œú¢iàÁ­‰ÃÑÑÑ:ݬ÷×þÚ_ûëU¹ÌþÚ¼/+ÚÑ€KföºLûqô*¥V«÷&j¥‡YáÑL`Rççç«‘Yk»^÷fÃpéW/J¸™8îTeÞg Ò½šy/³i¤÷¦ÆŠÐ »×°Ÿ: ±£‰Zub³0†g|g¬Ôzû 9o¢'öú¤ÎMú¸c#5¬±’z?±¥óB6Ø}n–v'þ™ŽµR£ýOëjñÏ.m¹ÅŠ©»¿sçÎVL!µLûfñϻ濽‘Ä‹[ÁÌZïjÔJho¬ëÆ®›€³ò €ÔÈT@Úl¡ë\ÖþqãÆVi5.d—KdR€Z¨U“ÊÆÔ'ÆLUf¹‚S#£€|öJÑ•¬²tv…NFÇÆlàÍD:.¾Þb(pk2Z¾³Ù•ÖŒ½>'›ÏA#ç…½Rœt½¿M-ÛnûuM}ÐÔ' KÛk“³£óûÚufdиš­‰Cêoó€˜N8»z XÕt^E‹ó^t—ÌŒÜq£‘ùù™O޵«Í‰9¤£³÷ž1çã?þ—ßå¹ÔýIä xh¹šr| X»V¡`ÛbigÚo¿ývüð׫úæJ_¬ûùò§UþR¢¹g‰#l¥‘ðñ•µ(6RÕÌøCóòõ‰©T±Q(˜B­®¿£EôƦ$SÚüð>³J)dÐvdš7è+B÷“¼mÇŸÒÒ}Þš‘›îØ7›Ì¿|ùòjøûÝß%~j‚é ÛBóR"/b²?j°.Ù­®ŸH‹Aœåwß}wIb h%-qh”™Sõc³j«ú½0!>¶…µu¬ú›9öï[ ûf’AÇ6Il#‰PÖBÕCGül›\“± ×`[SÈ&¥m鯷±UÇ»JÐJìù¬&ª’5>&À ‹ë€P|¥©…&Oظ4ö=¯8K“ݬ­„YíÙM®báŠDØbw)uÓRò\8Bs­D¦÷öððpéМaDÝ„–,×&ù믿ŸoŒ™Ûu»n×|IØF#TËʹÐ.Ïp fÅ7;Y,t®j^¬ºæ*—® îB°ÛËÏ|ô„øxÖˆÊ(³†“¢6Š6Ñ0q‘§!ÿ§ûtwwwId3S7‘©k¡´u<UYû½¥ ìýË.Iô÷JX áÎxØbÇtauÉåøZÈ•R1ÓXÔ÷8Ž¿plâž÷ìŠoÎ!‘P­ö%ÀË=·£S2TÜi—R¤‘>ãâ5µ3g!÷Ó§OÇÃÃÃÕþé§Ÿ®r»YéÌÈ5Xø”X@ƒ*âÊä.!«c³n¥Ö$´lÛÊ쪤aÀm@ÚB÷Ù‚)Q\‹l+v%¼÷5>l"È…0+·ÛTC)_°f¦Jô5 hãÈ,>W¢ :îÛZu2 ¯ÚMÈÖ¦ ]Gå&›]„Þ‹Ý(¯¾¯Q»–zc)¤°çYï½¶s›Ð×_}Õ)¬õú¶ùÝ»w‘Õ\1€³nV׊xx=k(€á&×¼]£­Æ¬äùÍ4óvÝ®Ûõ¥^í©,h©nÙ^º0m–ëÐ÷û®ÊZ#vh,Äê‚^@ùË/¿\Á¦åBë÷Ýë…ál°o¡×ŽÊ³gÏ®|bäÉvŽÙqÙ{ßøf jþ{»UëgŒ ÇFe-Ç.ŽpŸ¯>2ZƒˆºÐ¢áÌ~¢¹Ó¸v†ŸÅ†Zo(Ò`lèØ¬-‰Ý®b;áèúé¡#ÇW±£•¶–#Ǧb©àºw6„4jn\-—©yÕý;/;½)-"·8/lžøo®’™ªÇK,B´„we –7X÷ûŒ-!G-å HíÞØzíÍøÏ|^$HIèJBÏÄ¢ŠCß:¦^v‹Y ¼²v7IÛÒÛñ)«nò©Ø¶må‚uñ¯AË\¨’ùåy,R|mï©É¸ÒÖGí?y"+1¼8J œt¶-I³ÒÕFR‚P[|[êÏ tUÉ” w“«-Ýß3Qj¡•,¸Ijh¹¸j7pÕV¢< L€M…DöžÜ¬¶ØIT,à×_ý£;s»n×íº]_f2£g˜RQŠÖØù÷Òð[ÁQž{ò\• ®P[!Wãåu\äÁz†«ÈÖnPü»sª3|Ú=Ç”(Þ®„÷^ü"¼JhšÖ™û[›È߈Ò8ó‘‘ß;TBØøFâ£Æ¶÷^¼·h ï[„.•gk"cüc `Áq›’'ÿ¶‰TF‹ÜŠ<.t̸VYo Å&¥®˜Qq±›è*rËK˜´æ(V-¸¸ÞœA “DyÃWÉŒzÖÁŽ6èÆ"î,ï¡Äò©neåÛŠE“Á…lV­q`{Õ øj)o¢#޲—\×A‘’Âoß¾½ ðû÷‡ËÕvãÍÊ[,¶F[,m¼·fY’Ý4#m¡ièÑMXÝ’ û~-wÚr£œ%2m$Kèr!7ä‰XéêÓ·šc{Ѷ°þ>¿Ð1ç•bNv|LTl½.þÖä¼w¯šK÷këTIr7á—[é¿«‘ª•¨ìƶ9-ô¦fv»n×íú/ƒq¹áÚGt†¶kϵ³)ˆÅJ!:ó*—nŒÑ¹g@+jâþþþ¯òœ{öìÙå?Gºî\©Èl’VÕo÷®_¼xq¥Âj"³¶$Q.Îâ!‹Åu %ÈQŽû\|£Üøůlw±cÖ5âé1XlؽVD&loä=YløúõëK¼¯"[ë(éébÜòOþÉåoŸ©ýn|$ôÞɾêSbý”¸‹ç!dIS¤M[¯BÇŽã¸â:=Sbx¹ ÊÌIÚn2§¦QEc92ŠØbS @ŒeA™gÕøW¯^]‘À X HW/»ÿlÇERw›Z›¨üÛ—þþÂúJ¼z6uÔ[œ*kUÑË´:ëñ Æ·uªlw…ÄßV©Ò,ÔŽŽ-ù:2oß¾½ê ÕÝÖjóN’¤•´æ•I¢‰Ìû÷ï¯Ô^¬”™dž©ÿ¤Ôò IDATÙµI‡o5±Òåá¸<á®­X±è€©2óáÇ‹7Ô§OŸn™Ûu»n×{½ÿþ Ž®úTÅPƒiƒm û÷/_¾¼êBTì´k!Á Ë‚]EÀ·oß÷÷÷—¬¨‰ g&^ÏŸ?¿žyÐ9·¨ 㓪/¢&Šw„ýëeâØì-ÏUC¡ñÝ{B ‹ò̪–¬ûí·W÷Ûý•|£t¾‡RÕuUUzÅŽuÍTT+XWì¨B¯IañQ1Cc[|æ{Õƒ°±ûé§Ÿ®$‘å^—;öq·„ö«Jæý7¶úi–.·ª±.©Ò_ ªòËz+Õñé>Kp‹‡‡‡+uá’8­;„ù©wÕ™Z@jæjnëÕ…*aLøÔº4×ɸG–AXÀyU;Î2ϳ€s¥—°Õd®òÞ ÞdÇ籊™OŒYv“]ÕÛƒëêkûOeIž›¤8Êí¸lÙFª™è>»„øºäûºYm¶¥u6«6«¿òB™¬[‘‡ª+ËÁš…®¾~Bç•­ÓífYÍi#úæ›o®:…}ÞßúöÛo/ÑÝš7JÝ`ÏøC‹«îo7w}ïžÜU!_åÏn™Ûu»n×yŒzF¯ýÄÂÓ;ƒ;ã…Õñ‘"Ù_ÄŠ½Î`;:Ú,ªÂB«ñ‘]û::rl*ôÊõl<*f.2@E[?7 ´r¿~gÆ?KK(©ÐBÁ±éïÛU÷ ÞBsÅHí%T&•¶ ìÎ`¾ï[h–?m·kQ©¾ö[B WHj!‰ýíâ›þžÐ0ÅŒ]…–-Ç·nU|cÃ84ÂÞä®ïØ«–·†áÅD½Ó3ޝ¶!%vlvlLÎå~?jšÙ&,Þ­ V›iIMfýÝ„<[`°ö²œÌóbÅL&gµÂ̲{WË»Àج¹…ñòåË«Êú™ü²/Lwú•/\×^å×l´¿'}z<ýú«[Ds»n×íú"/¥îã:¸—®yßrhª>wN¶·ÿ¬{»¤m+ãš:v?B ;ÇÖ/äï~ ’§Ú9µ~fž3ò`+^¾yóæªÊ¼êŒkWb‹ØrAVwfÞÙ+<\Á«þÆ~òX%¤ÛÉÚ÷nlWüÓÏ"Á÷¬ür¡g]ÿ} ÅåG‹(‘_m|”HDIë™ÿЙXQq±óªØM²¾…SØŠÐ&¨­)UUûl•WíWÈ¡fŸ;6&Èòê5Í|b‡EœäýýýãéÓ§—Ò„Ð¥ûª/”½Ô­1b/Ĭ_÷²z!@]U44+ãÁâú~-®ZmÇñ't¬”´í½Ú¶w¡Š1m±4ðU<̪ûû½¤&L“ÆŠI‰L_3ÐÆµŠ„" rLêÊ4vNÛ æÛ”âV5/_¾¼dà}n‚ìß¼±­,‡¦Å¢ × ³‰lÖßw"ú¹ë’Äîw]}·J÷Ýwß]6A?½ Ü—7æ¯÷€ÅïÝÖé“'O®tÖ­ö´&Ïà Îû6øÛu»n×íúR“™…¹Hڶع•w÷NRϹ%´{Îvîh‘еÝw vâåz*ˆ#×!xÔªc#t†o鵿³5oÞ¼¹Rßô;ŽãÌ€q6‘2žšf|svÆ«ˆ"ÃØ°b¦ã*ª"4N¿FÖß"ôò‹ ’‹kûׯ__ î¼xñâÊ`ûõë×—Øäîîîxxx¸ò0\Õ|+vŠ€YU2¡mR>„4ZÌTH¡±ë÷ìR; ]_3týƒ¤%TH-QiìåØÄ²9’%‹É¿kv¹ç©º.Òé’̘ŒÛ“°n0Þ ™¹ÚõP{'«Ù–-¸0¢þ½U¶ð÷ O¤g©}èF &|Aƒæ&×€Õj²-Ù߀Véêûûûã‡~¸R«GùáÇ« ÉjEþ’Y»ªgjæazÿþýG&²W¯|L£R— çÂ[ùÁwïÞ]ÆI£07x¥£?~üxñØi#-XïsM•J°Ï6Á•o^ÿ€P•®æ‡ ò™ó퇮“…mšàº õ,U<Ú¤zv7)!y;9/äÐüüóÏWºðPOîžÜ"šÛu»n×yÝwWð¡öjùŠÊÐvÆëùUõ¸ó3>ÀBÓŠA,†þío»òj ÆÓ>}õ¹ð«Î`‰Bô[ùì)øS‘Sè™Ö ±ö\Z¶ŠngbFÝ{q‚çXÉ„±›ñËýýý%àíû*“.üª€W ‡ Š%{ò«KvJŠý:SûlÍÔ×>¢ìMh—ϪPT!‹Ÿ›åÁcÜ,'Ù¸¹¸×„¼¸ÙÀÅÆ¾ß±R‘¸¹“ĺ]ý–I BËovÞ˜Ü7/\³û{xx¸’¦ÎŸ±xM±ãf&éÈŠ€¤m±|¾yÎàOâÝ–GòìÙ³«_™c¿¯Nº5â•j +¸­×î¥ÌnUÍÄ.ÆÓnR/ÌÉîX-¼ÊމI\϶Á¼ÕµÂû\œb›”ÊJ_›ä5¶ËZwûUÖj2K8_Œ¨y"%V£ËÔÆAŒ¨ª-¬¸U’í}ïµ—Ìß8 -+9·RöË/¿\)Ò-lnq«H¬ü²‰Š\*½›úýÖˆF_¶vý÷g|Ï¡9¶J€>~¸E4·ëvÝ®/òêLYõËÐìÖøÙDǘ ½z /%¬k˜ùã?^qx5Äl¯Þø§s¤D&ÈT7ýB4Í^xÕóçÏ/<[å™ÏÔ9‹oì*Q²PzƯ6ÐÀÛø¥"óžcÅsò­ú›•;àVöU+s\ã­9qÛº-Ønaõl=o“ÙÌÏÖíwß}w%øêÕ««ÄäÌøp%ŒÛo›Èè#Ó³îØ4¡zö:.ý=]Ï&sÇÆ xS kUÉ„žŒË_jlm/žÁŸ‚0n’泫Ãn’f7ª¤$§MΊƒ>.uꂆ­¢IÿÖ…¨†Dľ߼Yì±¼2}dú½/^\qt„†½ÿþ2oû÷vIWZ»$п¼´ ‰òÓÜ®Ûu»¾ÄÎÌ“ë½ØJ¶ÝqRyí¥ôìÞËWTâxN ½]!F„G«Ì¼ª"›âÎð• Þ`[Õ×Αå2ŸxŽ#t)Ô9Ù¿; ½±íjÈ.~)à-‘)örlVÕµª¾æ™uì:_xÆ#ôÞíl1²B«ñˆüž84R&{ óÎ; ïv„š7ÆÔ"FT%©ÔU"R,k|Ô{3vL̨¤øçŸ¾ŒãY7ÊNžc[lçšë÷‡ÖŒ½5×ø.·ÊœÀÎÌÛ:ÁXúG—Q=¡?ræ##ÇÅêóB€tÆë×CÛ5h¡»P èïýúë¯R¸Ý¤ž¥ï[m1” !ÇÅ`ßg_ z[Ÿ?~<®<¬ ñ&* !´ ý*Ù¨Ûc5F aÇ®g ^fÕ_µ³âí¨”u/¿§Etwww™7b‡­Î$]mVïd5ÉT^pÝíûÜ`}¡o%r­ö kN*ÙÝ{ñpS6»÷nG¥ ¸¿Ÿ}zÅ#i//˜ÎoÍß—çê9%¶¿g×¢ µ`¾j½gäò`þùç+Õ²U’ƒ»Á¼cS<&¬N›€þ^¢7ûëç9ØØ)-í9¥:§üiÅD”tŽ‹„¨ºÅÊ::¢uìFKÛ$®@Iœ±›I`Ð29:WêyJ[¨Õ4Ò`ÝÏ‹ ×G¯y»…Þ-bË ×ï¥9\‘[± ¡ˆbK»]Å?±}Ïj‹‘ZsýýÑRH!~’–0¢ÀVÕõâ3£ú“ÙÓnòDìR„×ׇ¦L¶êy¨ ¬ÏÅ9öBÅþ‡UÔGFˆ‘­Ñ&£Ð1?_¡±z>›„1ñ­-¤M„L²LTTíØŠ„8ÇÔ²ÚÄúÛÊ#·YÌ[±Ð7gå—×½^dà­tiU%JN‹Ê^¶…öŽë´xÄx®<¡ïÆÏ—[U5Æïwo*ÂÙͲ ¢j™bUºÚ Åþv)‚àç}G¢Ÿ‡c‹¹ÃsçMÿ~]}=VÖRÉNùA—$ïÓÜ®Ûu»¾ÄÎ ÉörM©‹oÚ7M4L”sޏܹ]ÑI¯cy°u\<ãóÔ(yñœ“ëPGÇbeçÔªWuî*/\¢ ºUg¸ðïÎSå•;·´P¿Æ†Væí:Èóðó=EœìØw¿ñZ47Xoë:è/ä³äA¨|²òËŽMó¦wfG§yQ±Ñ¸¸ßÓ?qçMЯbm ö½;çUcWǦ¸û8Ž XnUÍ€ŠØŽþ="Jüœ“ÚOˆx±xàï/‡¦¿¯º°(°>?•f.“¸#χXÕmïÙ5g)´L gm[+æN¦[Ÿ’’šLò*„ðT‘XSGïÕÚšB®„ߺÚh¸IZ©ïÙ×ìJÓH1¯š‰UÕ£{_Ÿš‚u92ªn$;y–žmÝ([ò íø4¡[µÂ{·Û’cºúû&iºú†¿]ÙKawV”¾Nº±ß×wý‡”µ\^™•¦3î•kb!‡®¹írªqo‚Úáf\3ò³g7Ÿ™Ûu»n×—y‰°¨2ï™ne[Â{g°Ðzep—k ©céßã2Ôqés ¿„– q.>éŒ?ƒP‹ÚøøñãUǤ®ƒ óÒDY¤ë9W ÑØ(Ë«ªlBÆŽ¤c"BäqÿlìØ9ª‡NŸ/âÂ|Ð-c€5½ñ±…Þ c}GØjygªi› F™Pm®¸Ú¶ûñ½šˆ¬¢ÛÂ)õ‘Ñg&ÄŠþD&¸u£6±nÇeùIÛ¥…¥â¬üžZSÍ+WÉL‹><ÿY0ßF`6äB3{˨²—Ý_ˆ>3òs¶£¢ß‡Á¶zÔý~:éj‰×*µÅUp¼:þý%¼ë|ëbÙD¦¤ÂM¬ /<Ê…,ìî±®‚8É6¡p”Çq\¹þîdÿ#”le)MtT%“çab¬® [X]Õ˜3e‹î©$°÷«Q˜Á¼É†IžP=t–™ê†€‰ŒþA.ÄåÉ*w¡JæñâÅUkTï¥ÆÖjŠ(&‰V[lé{8W\¨õûìÙ³ãÉñìÑÜ®Ûu»¾ÈKXoç\1ÀÜ„H· Z¾@‚A½,Èŵ쬳k p‹d{ ßJËñ:f’&óÕ«WWpò”?»÷P5%:“)‡šäu¦*¿,¿HµN}nŠÏŠ… XåÀôûkû-ãÇÎnWI^ù@"JŠTÊzxx¸ê.-OUþs´9½ÆGÇq\>/ž Zÿ÷ü‰DËh Ùïˆ(in37o–vPlÙgÅ/Æ‘©{¯r£‚Sž¡qì¸ôΛžÍØQĈ°ºbùâ^%óåÐü%™É³bNáM¶N•¡kRøÐâ,íèØ†JjMx”$tR'«d·Xyáø9vtÌL3mt`Þ¼ysNõy‹ÌW›bŸ÷Jä•YöŸ…ÉÕðû›µÛ‘YÕ³T7l_Ê)Xò·Áúc‡ˆ‚+dà†þððpi¹þüùø‡ø‡+\fcÓFÓ{oAÔ *™Nœd‹OyÂÚÒÐJ°S±QQ®ŽËºK6óð³-ÜF ,Õ]3Î+!‰%Ê/Û±ÑMºÏ­d)i¾Ò¹6¥0Çïßÿz‹hn×íº]_l2³.äy^Xœ\1£ðúýo¥<Ç,ž*ÃÛY ’š]‡ X;§>%ÊÄà¶D@U²å¹ß,Dg¡ñk^·¦×žƒ¯_¿¾:çâØ˜(yFk|˜MI¥>|Þ¿öÐjZ‚T·Ì8Vxöýýý•ÙgÅN9ÅŠÇŸf šfÛÉ“lz?ïVç¯íˆ†àÂî,fÖP‘V¡„3!¨’o ð&"&2*{ïÝëÆŽ«vW‚¬±ª>2Ë?2®©¤¿‘pÌ»ï‡mPš…ËQq!¯CûBË̾”?îóÔ›Ôy·µkëµßR™«ÊµX¿Zlvº¯Zhf†Ý»êË ¨]‡þ­›”BЪŽ}øðá/ÒŠÛ–Võ,ØÝYÛÚŽÌBËj[·(ñ·®ÀU,Ô1/XÞ$G¦Ž‡-y 4••”ÿSò#ƳMN¿íÅM…Ž9vg<*{í¼?ÛØ¤Šf·ÊDa…lVIR¨àì€Î`Ë] ¥ÛKŠm¹ »ëÝ3û|cÌÜ®Ûu»¾Ð«³Â`ûÍ›7XÏqWÁ²bEBÇ„d¯r¨ß·`×9gÇÇ`\øÔºÛw&JºnO_ˆ‘hšÎðÎÌ5+·2olæ9¸Ã´Aà ¶•_zßÙXüdÀZ|²…X¥¡+ä66ÅO!RJh”±Nù³˜`=vTm-6µc£‡`cc’¼D»MÅgg|gørϵ5I–ÛïÛ ØDf¹ágöò¯7ÆŽÝ›öò‹Íc‘|»”&Jÿ˜¤å+M7¼øJ8åUgÆ…¨ª†„/áOË¡Ù?j&,ü)xTWÁtƒØ€õ€z©Ô[ø“÷¼Êß÷å.Æ´D§£Œœ/ÌÊ·ÿ]øÒ¾%ûÛQQ¢øâÿHžÕQW"XŒ§Ýªm ‹“ìÝV­)i2‘is°ý(¿¨¬ÜDç1eCýü*B…͵Á·°Zˆ}n»Š%ýmÇf7)åëF (‰ë^U²YIO94b‹­(XíQMOyi»¤”v“·$¹•¦2¸]·ëvÝ®/ñR2ŽŒ°daºëîµëÁÏ%´·W }¬ºœ½ÄúÜ­Ožgl‰X~iãA„<ç’Oöœ^n|UWCr½ñ‘ϾŠl*«ÊuÐKÅ$Qî]3О=ˆtßU ©ÏWQv ±"N”0NVÅ7Eú\ÂzÁ·°»b݉XA\ië÷X!ÖnXÅÊþ^"Ë2¾Y‘94‰\Ù©3>RH!´‹bIAûûÒQ42ÕãÇÏ×G¦DÇB°BBË4‰=è&m¡ÕbkQvSòj‘Y6ëî¦ f“.¶EÖMkª¸gÁ´Y¬¦Fúu4ù‚øhlØD<Žã"/ØbQ \õ©m½ð*O¸Š%ͶN7Ñq²jJT"ã&©aÔ³gÏ®þó¯¿þz•(Ùº¬£Üßv’ìݵQØVvl~øá‡ËÖb±k L²ßªŽŒ77”¦v,Ñq/ÁíÝ)O¸ªd¶Fw¡+h媹yQK}ÛνG+aÉr«.³Ü*¥]Ƚ‹æUݬ ‹A;+"Š0”ü»æn×íº]·ëK¿~ýõ׫Ž÷Ë—/¯Š§r- ÚVy«3,B»-ì¾WèâÜoô·4 ß‚\§¨ ÏØ µžCžñÁêì"ølÇq\`wÝ_ððǸ¤sÍuŸY3Ñ‚qau=w»þ}‹yýîr%Œíz>U[ý\5»ÇØí¸ÜÝÝ?ýôÓUl§ÐSükï)´Nß1®>B°H¾ „•ÊNjw-—ÀŠ’2Q1¶ëÞ¤ ôÞKj5±_YîD¶„Þ÷l]Î;}dú½(¾»’÷â£Í+-aþ’Ìì€×—©qb:íâ(ß¾}{¥&aöT`µ8J«ËküÓ éeY1XB˜ ¡ NÊÊ*·Ð3±|BËôÄYŸ™Kð‹/þ®4£Ð4¥…GÉó°µÚ³«ì ómŸ™hTé·Uõ¨£Ò„ŠX²±ŽÇ&y&=»Êí0½|ùòJ%M {Ý_›¬AËê)ØÜèï™*=ݦ§ÙhI”É€ï 4÷ä)±ÞKÎ;y«£.ÇfUÉl;w¿*šìỪ=Ÿ?Ý€f·ëvÝ®/óê,x÷îÝœþáááÊ– `^ä€ñ‹Â.Uîå–t-ÇFîÎá ™! æ­ìwðõyñ‡089ÂÅ&Nv‹„õKx7€}õêÕ©ªª¿ßyÝ9h0¼ǦB²ñr¯„Wé^¿”‹’›7ÅÅË­òû3íØôžKû¼q-ÖÙR~´IØBǶS×XUhNÛ­²9Ò;¯HîçúðÉ­£šžÁ+Ÿ™nPÂÖê¬[qP΀Óì©Ì{9.«“×¢D&÷Z\œâåêØH–‚TÇFá‚3cÁ­œ«`r†õSbOˆdÝY Øýöýž]hÙê¬Û^lq+1lµ¦MvÝU]ÈU[ú¼ª¿“%iEƒñ>3‘p!›ˆ,ÿèûï¿¿$UÍ+(~?7دµZ¥JE7¡]¶¥Ýãø‹Zž-UÇv^4ö«ñ^˾Jò¶Výý‰hÓµíìØHuÛ½]~ÿ¦Ë|»n×íú‚/¹#+*S±³}¸sÐ.„gÁ™Ì"¾ùæ›Ë¹Ü9¦˜Qu™…\mêÈèÀ¾Ê¤z×øY‡vEh”ÑÕ'Fˆ„vyÜäÕE16ì ×~"ø’‰’u£:—Mâ$¼Û™ëëÜÖÈÝøh%‚=G5Ju^4oŒ·DÛ(&`7j)r`ÖbAÿGã«åWË7...±[5½•g®Ð*¥¢±Y†-‚¯¼h›-íB*fT¡VþÑ6?ûõÑ»ę̂=®ª˜~¡jN‹ƒô¦ HlB|zà‚Ã÷ïß_á$åÈTÝèû’Õ–ì&_Áʹ™í*Ø^l1YùVBÙ….¡\2¾8Ê…Ýõò}bÌš• n¡ŠŸ5_U3“´`qÝW––>¦Wµ¦îóMæHMv]|Ïd»mW:™WÄ¡$nͰœW½wù?Êz¯¿P>2u£4Jr6Ye¹Uvòä')gXÅAn•-~UÓ¬¶¸æÖÕ·ïõÕWWB u›®¸K·xævÝ®Ûõ…&2[”²:¼\ +ïUÖ HW,À$Pû¶E§ã8®àS[ŒT]ÊøG.Ä·ß~{Õ•èœZCðâ •»Žã¸ŠÝ־®„IžçTÊ\ãÊr%÷BXRw϶Á¸>-WçœEæMD´þ(>‘CÓ½t†Ëñµk`·I™•(vÉAV1·çõ½‰¦1n6®\Ÿ=ãÖXÅÁªH]¼±ü¢ŸþùÊh¹U¯_¿¾Ì‘ðE*-%ÃÎÞv1ó \4ŽJ~]&‰5/LÞ/cÜ‚±§ S0_vT@Ü$Q/{3Ï%´«ŽP·åýû÷— ­Éhæ§Ì7ß|sQ˜ê¡4­ì…¬±«­´Àûßú¼ Ûç}ÿ‡~¸ h#}o{Ñö¤ªdIWÛõ°›ufˆÙäŠÕïe(Õo}ûí·1œR&{'ÛÛ·o¯*ÿmàII¾zõêÒaX‰¾ûûû ‡¦÷Uµ§I޲y%~7Œ©òÍÝ_ï²ÂM®ÿî±f¡&:Íuõ•ùôéÓ 4¬â±øÙ!﵊D›Cbò—ìvID´5Û\xýúõå·7‘Ùû¯ÚÒwmÉ_LhŸ<½E4·ëvÝ®/öê\¬àÕ^¬_H©3½ð‚ªÒnLÐò@äÀÔuY-o[«*sUÙî?[Y')A*èY¿g@*ÎÑÌ´MK®ÂÊ/›(Y¡ÐçeeâÖcÇɶfZ’ýûü›o¾¹’Økl•g¶õÚï+/(¬®\‰CŸ÷^«vØþSйjZâg†Qªz,a½±+A=ó™Q?¿J‘QÛʶ^•TžPÅ7»M*¢¨˜&þV i‡Î´g‘5õ÷û=ZI˜ÀVé¶¶IœŠ'k"[Ü{múí·ßŽ»'7Ùíº]·ëËíÊÔÝh¯>ãj* ÏAUÏ ñûy3áá+vD¨½\¡=焎=æÝØàO IDATWÁ«`PPç®Åú¥IH/¾êœëò _yæ ©*‡šÄ5vëçǡ>yÑòp{ö.Ç®Bìš2Ê!^ëåa(f´ñF¨[Àׇ¯wܳÙM2™nì÷Xüã³Ëÿé^•ÝÖ–Äg+î.‘Ш¾ß·P\|bƒá̶dÇvÞ5óÔ»r›>»”Ö”J­Wjfâ8Íš—be¿ »]oZs*eæ¶âÐd5SÓ=^Í’ÝVg½äEÒu}¶f…7é\»ÊëÐÞK]B¼~![ÑXöMTÌJ×”±$-,nd6yºêº ö›A¿tg•Sk¶¿ÿòåË+ØÊg„±®ª)áT›ì-vƒñz›úΡ%ë»I5VªÕÙú´kFTE™æ|ßwl–C#\¡K!…TÕšg*¶I$ÜM®¢nÓâ®-L(/úîÝ»›šÙíº]·ë‹¼¬Ú×]¯ˆ·òÉšbÿío»Û]áùÛ÷=ã…?mücÀg¢RÁÌøD„ê—VÆ RãrZY7žYÕÖ³øg¿ïZ4ߘ¤€Ôb¤Ÿ /z—Gÿ§ØOŽnIœüiQ>|¸œÑ+tÐØˆ(IbØb¤ï¦øÆK±"y®+e’'÷jâ‹M{¾x°ÅGQ.JNÖq“¼ä‘»·BÐ'oi 6´PÙ¸yeóC¨™”é(6­ÓßßA¼³õ™yb6øT™Ú’¢¼éM úzùÝ´›ÀbH t%Eõ{q zß¾}{éÈH–sÀ „ x­œ¯*G µ{×OÄßï¿Çeh2Æ9#|•¹ö,KzRAE8;f¹©~ô¹Ý&i#×»\ˆJK¼¿yóæªXûÏDÈn—›äq»0¦ÝC›´“Ux•Bgf\uíô©–§ÒŒ\‡W‰âß›Óng•®®xeݫܪ~ßVnóÆÏ›£?~¼Òa×1ÙDι°Š)&2ú÷7Ÿ™Ûu»n×—|yî” Äm(‘Ñü¯Ï³PˆÇ¡„qgiç¬çp1AÁzûqÝy×ÜØ1輑þ®\ˆ³g;ãÀ(†Ô9Và¿…\ƒ}ÏQ…žäB|øðá’ ôb˜ýþšb/é»b´bK öØhlŠV™K²¾|åâÀ,dáãëCSÌ­¡³ºD'^”<¡evãLë–7[ì\DIóªH#Õì”·,'MÝ¥r‹àËñío[èÙÖÈ.góÚÂðLBËäÂÿ¥3³–OŸ>zfôŸ Ú¸ðüql¬> *‘QÕÃÖ¬]œ¤òÉ*Š˜™®Ìn“E‰º&«NÁ餋µe·~¶N—.²$­Ìt•-‚†µÏä™m½Ú~´½'ô¬¬Ú®†ïÕÖgÆZþP—›œúúnðÂòäÐH\÷×Õ°¯ã³™Õo"Ô³mûRA UÉZH%9"»[qP_nTW²“+Mí¼9“/´³h’·j0Ï£¬÷vt.]Ì›–Ùíº]·ë ¾Š? Äîïï/·-vŠHéBÔ^o ñ´¡«N¯|sñ“ðrmTp=SÀªÏb@Ù9gq3ÆÆ?Vî%eÛ±9³æèuá¬}…îòëŒ ×º#d›ü\¡¨™žoí)ê¸ì½™È¨‹Ü½ÛL{~ǾÏb9.+]í¼zß¼0v¬›SR\'б‘Va…¢ŠÇTœ}Ì ÔB®“gÏž]¬7zžÆFÿE;@ðéÔØo'¯÷´Eî‹ÏŒUzŸ­2…8É~TùA‰9‹ñt²Ú‚Z©Yeæô©˧Ãi­Û3^µ¾ÏHÝmRË1˜·e]×`áW«~Ç|ª…lV-~¶ŽŠ\¥º -¬x ÝK µ6oÐ41¨ºÅ§L±íÁ³$±ÏW¥ þbÊHRh'¬ÎjL‹k+*–´ ­t£„3áU-4[ú%B&¨&Uu£ôÿYèš Í±•à¹úür·ú®ÇW¶^mÍêM`ÜßФÍn•ÒŸ?>n–™·ëvÝ®/öú|-Ï,Ä98Y3‹zbXp“crÆeèûk¾öztŽuƯª«>xúÌ¿(L`e^Õ2Ï)Qúè©\ÚxÙUP¨ÉøkcC¹Æzä >ÕØ ó¯ÀÞõD1"9-B×ú¾Ý«¥È“Ý$1hÙÊ+ 9 ªxÇe^ÄmÕZ£±1X/¾é÷‹×¶DŽ…\¿/‡F´Žáânã/!‰ í_Ãð*Ò®·Ózð(t°¶%5V¨á fÖCˆ<#¼+\k­,{j‚(?øáÇ q¹›.sܪýòDš<¬|rhâJ´QM«‚P M-qÈV+¾0uηk±øZ¹eÏq%Jò”ØÓìs „v‰oU+¼gs!¯4µI^šžOþQ°:7=7‚Þ»óÆjŠ•,±Åj—Ÿ™>öï×4ò›o¾¹"Ã)±B%ª€…mq•ÄÙWgý±±oaÙÒ_iéÞ7©îO»˜ºA7g3™-Ám“ÑPÓ±ùúë¯o½™Ûu»n×y‰ê"T Ð9Ô™Ö9hå½`?èÊ*Š,u¡¡xç˜ç„Ðûï¿ÿþRøâl|¢[¥6BÁ₊,0~>þäÉ“+4ÎBÃì6ia±3®©Iž$õí6± Ð;ã…ÖÛ]èÞ»ŸåÉš~üøñxxx¸;9Âý*“.GX4ŽÐ6ãŸæ’]ƒŠ±&yÅÍqdT[­::]=»>/Û@ˆ¿ÊÊDFšMT{¡gBë›W 9”¯í¼T)P¢µ5):“,—?]q 5ý—df[l ‚Y¹x¸õ´ƒ¹(!,Ὤ»…½ ¹ŽGŸ—ˆ¨¬e× R¶¦Nμ@ïáááªíûÓO?]°°Ož<9~øá‡+ˆÐO?ýtµM&ÔyWÂï/?¨¬¿±Û¬XéH…¬Æ4áÌšKMLô™±õêb°m-ѯÏÝôÔQ?Žã‚£4°íí÷{w*{ÙÒW~9H¡Y¹®À¶V•Õ6I«µŠ#}gý‡4*[K›œxó*¸‚ªgŸ>}ºZè»IŠ-^jÿ[H¿Qq …Ü|mÍ4'Ú$JK%Þ®Ûu»n×—t¥æh|³çœÆÐ}.´Þê²¼’ºëïß¿¿t-,‚U¹ï÷+¨Yp«ˆVüS0o7HxTçjüžºJcÆOª•ÉÝsæŒËà³’‹º<ïOyæµÞÐ:£g)ÑQmNB½ü¢‰b·MÒ ÖM`Mê<ãõŠk,’Ý6~j4öŠì¬ˆDﮘÃyãâbÔcc!WŽl]ÆU»³#RrmºbE±+´6~‰p•Ä+«]¡yyeBKdúßL€·c¿ÈB¯ŠtÑ}×]iæûûûËdVf·LI¬ßß“ZëƒWµË< +ïß¿¿ÀŸú\蘕s7žd87+"ÜȪœ!Öï—_~¹@žLÒš`a m?š\¤ˆ’éÕ™*Úr`Zèeå¶µ…Ý56Ê3—õ¬+c'á«`_yfÇÒ¬:œcÿ¾…l»ÑÖo_)ÊÕAw^}ýõ×—±*×ý¬·X4J•#ãØq¯VÖ{![ìšU5ïzîæ•I¡–ž}[îªóù}¹WpÍ*rdÎd»íØ4ß’6úôéñþÝ­/s»n×íú2/ácžS¯^½º‚æînP¦Ãîå -[‹†¸ÏŸ?¿t* Ê ¦»—¼T–ðþìÙ³KL4_» gîô a–'"OcÒ ±k#Pì$¼©˜§®Dç‘›…î =³® Oð*­9Œ_DUl°®Dq±›I^…^áKÆvgþAým'Ûrp¢l”\øû=ªh"¡JWñ«WÒVul!‘Âæú\ŠÅ&Ðrˆ›7ýöÒÛ>—?­ýDëQYnýmû ×,6¼ò™©óàB•ôÔB-À]õ¬¯¡¥Rj¶VÅIÚâ*ó[Ò¶$"[Tý}3½²neê|!„& ¶¡[ˆf†Âîú\žI—‰HgoÐ’ÃåBèÁÓ÷#¬·)Tq°­l‡£±[~I˜Õ•†Ôyƒý­ÖTÉÚDƶª•ªªã¾>2J[GôkÓNµ£¹fK¾¶±•#²ØäÆËZÅ¡­Â‰×íÙWc^ÈAãhÛùL?¿DÆ ~¡c„­¡Ýûû÷ï/söæ3s»n×íú¢;3@˜4‘ôŒïœ[‘çâjåZÄöœ³(&¶DEÎ r">ì¨Üµ•÷¾o­‚îöÆ+°¦Øë݃°¹;Z¡e-|Š8‘ŸTr¢tµ‰Š<ŽåŒ+< ½…ñ‰ðu)òX+R¯Eƒç®ÅL¡cÆÍ„öÆuÉú>{1€ªª¿(¯ìçzÍÇû9v*ñ- «¸ZŸ´™â-cË}öÖä®™>²è{•–°¼²ãfV—b_¸YwÁ¼•sýRjº%A÷ÂíÈØ ëW¦V¢ÔbÞÅ’³­¤z›ØBÛ߯cãßßÌÕ¬ÙÚoÖZ ‚´BbÕY7I<ËŠKò\ˆýíp¼’õm­v?Ââž>}z¼|ùòòY“}M„¢I$ÜDI»Õ$“ʪ=òʆ–ýÛæ¤Õ˜êJjÚVÒ˜D¾‘3éé³J–ŸÛ²·賨ڡê‡-ûÆ¡H×`7ÁÖ“6I–ŽÎéÝào·ëvÝ®/ñ’«ÐYQUÜd@ÃLƒ*'ã›b¦:&UŸ‹ X-vÊs­#R|$™_ye+ïJ ¯1¡¡Î) ±>|8^¿~}•LT,ÕRŽŒÐ4­‚õÞŠlÄl…ÎÛIH·²¯Š%õlÑ»w“ ½z¡ôÞ¶k¡©¶>{Ë7^*~’§k¬Xעئ"yïBÅx2Å‹Æ:֜ԫ¥n“H#M¹¹UB .ÉD ®ßûýýýE,Inz÷GF«UmÝ}èžMµáæÍBËÌ)NM3ìųI\F£9Ž<‰;Ûu(à²úÜ"0`µ+`¢"²D¢Áh£©‚¡˜Àâc{¶/^\¾+–¯L÷åË—"õqWòÌjÌ÷Ü*®m7Ë®D㺊'n¢¶NÛÛÄÊjýÜjÍ™V·²ÚM6e)Å€Úu[Ü–$iÇfáv“´ûæ¼[å.±®ëþZ0¯ª‡ŽÅB[|-$¹[&¬vòªH(=ݼQžÙnÖ·ß~{™Ç«1ßá¨É¬j/U{l½n[Z“Z»¤Íù:7Ÿ™Ûu»n×}}¾†Éȡ윲##,ǽܽØýv}ú·g{µçTñÁ°P¯Š•ªk}¯(—SèXö&J"p^¾|yÅ* íŒÿþû﯆t`/W}jÜ•g.É+>ë · ×8õì*{Y<´¯B[½ ~Û+«½üèx°&Rž«Ú’cëh¶ÞØH;PìÈÏíZ8oÖgOCï ûÆMþíÆÆøÅ$2~´Ü.}òÖ£°DH„ŒH'awv»L¨ë®YªÍ“Þ˳gÏ®„œ¼îý£;Y[ÈNf«Ëf¦V$º!Ý]—ÔÝd6kw€W&×Ö©¤îLMÊU?ÔêÞÖ©¿oÀjû°É¨dr/¬WÙËÖ«“µÊݬºQú‘Ë«#cp[VÞäi캄ž9¶‡Ï¾•îÝ®„­×‚qX7[ò-DÍJmz(½}jÔ«†w&?è&YÅCØšœµÜmK×ÑéÐQvÛgWÈàLÃÞÖ«Ü%!ªv¬Žz…ý¾íš°ÙÒ¿]·ëvÝ®/3—ù|—w6ÔUX¼àŠJŒ+Ÿ,ϵ «$H^EÂ,koá9g×AõÎ…_uÿ¾òd»Î Ã=§„ŽUöœùæ›o®Š³ò@ìØè“glçï«êZü³\Ÿ­s¬síLzZEÛÎø’•‚a}øjÒË­`ùŒ]«ؒˆ•ÆsÇÎ"¶bGÅ/g>2ÍÃx°%'Í;oº_Õ|‹{;c?)Í áÆ~‚ûL´MüæbÃÞeϦ7“ÒÆ>It9Àþ}ä×»IÈ¢ˆ—Kg¦oPöRu©~Ô¤GÃKa2‹£TïZe¬•š­£¢{½'›i/Té¾/~Ö®ÃVÂú™ˆl—±¡dþûb/,œ£ ÒîݤKxÕ‡®¾¯†|÷òòåË«¶sд¾´¬ »Š…ж…Õ]2_ä“Wb;uvlÔQoÞ˜ˆéëóˆ~n2ºâÖvî?76¶¥Å×zmNXíéãìO9eå ƒõ9Å]«„ó˜ÑØ>V2¿Š&JGëÝÔßÛëØ|þüùøôñÓ-¢¹]·ëv}™ÉÌk÷ê _S&" òm7‰ë¹¢3}_±¢Š‘ûëN/DZSÆÎÁW¯^]~Û"h[çdE1•I5>ì~ H5ól\zþFå™·#´…âÎhEk6`-ÑéûjÜéyÏè…Õy†o"c‘[U2ƒýÎÜ5¼\¡‚’H‹™¢m,r‹˜ÙB«ñÅòƒäÙÆQ(J/¡aÎ+“ÄåW/wªç8S„Ó'ϹõT’fE"ŠY*b÷{v£|ö:Å7ŃÚÁÛÙ½»Jf HÅm:àNmEÂÌTuy Ý´‰Œ¶†—qÚô d…AŸ™»»»+Å’ÚƒV,¶u[À¹V'ëÿ´1ÙuPƒ¾ç“P®;«Ib¿+ÙMþÞ(ÂâÂAöâÀhbd{ðÉ“'~Q¿÷âÅ‹K—ã1Ee+׳`þŒìör?—l¶Ü++M)sµÑ-32‡FïM5¼æù³gÏ. ¹Ä+YîõØé~øá‡«îV­×ÞÝ?þøÃ'“V[«:&«ô·ÞN}Õýyló »ÛDç8Žãù7Ïo>3·ëvÝ®/ò ÆÞÞ-„ºÆÊ{…K‘¬쬜—Ä¡)([‰`ù9Äú\!&¡ñáVªì±P+¬NîÅ‚…H?yò䟱" DäA眫™­Ü/ªÂBo†ßÂîÎLGr—ï+¾ilB]¬=„El… ŒŽã¸Bm,<|sƒÊÙYÄŒðøÓùj»qÇ¥˜Ùÿ&t¾Ï’’£» òÂ)ãÀˆD’ì_Üm¢¢*YŠ¶Æ¢úä™™@[Tˆqf˜Ù³ÛÑi^Héð~¯’™0jkÊd°o’ce=UíÈø2%) Î¸™k/úL}¡ÝÌQUŽ&@ Õ.T yÚû7š>êÅ"ÆÕ±é…Ø‚SxevívÙÍj²»Á¶ú®£Z«ë¾jÅ¢jO¶:é¶Â>Úr—c#tÛ‹¯•—¢´c ¹y×Bn.u@ô[©½´ÉÚÕ0nCí·­ÙÂ^eawVÆL`×Íwß}w¹÷:ugck2Ò8?{öìøî»ï®à ½×>oMåÁ£ªÇš}Ö%í@þꫯŽÏŸ~»E4·ëvÝ®/ò²­M€xüξªÓ«þ)1Y®†êQA„T&m¯V,@ø•ê˜KW,©bb±JF‘ i|hâ#OÄ€6Ðcð©É-fžIKpì%¼G8×~Â$pc¿»Krpë6Y„>ì1øŽR!GFô‘fèÊ3÷7M¤ŒŸŠ¹L•ý.¦RÍÎ{oì#û'2e,¶BKÂî*ðÛÕÐV¤0½Md‰dì'÷êŒcÜØnÜ,í þõÒêȬH„ëFñ®ûí¨tƒVη}X"S ¬Ö«•õ…ŸR»öbY¹›ˆXÀ~_7z+×þ~ I­q±|g‰Hn"¤žµí=ñ¯&"œµ¥Ƕ`ºM.ü­Ð1Mƒ„~oê½ô>ÛUÖÒÌJB˜ä·/^üE¾PþOco5F2~¥Zß+m½²Þ}Þ³ïçk ©â›Øâæ¥ÒÔv³Ú„$׫ÈfÇÆHc1ÇÞ±QßßÖªÏ^’ik6’eï².¨’ŸMÞ[­Ñ_H¼©j/­™OŸ>ûíî¢fvwëÑÜ®Ûu»þ±'0ìs»×[L¬ˆf|c°½¢3íûz^tÎ÷ûí·ß.êRÆGÏÆ/§:— ø¬|kH.7rykül±²®ƒ “ÆO]ÆOÅ?>{ÆÖsL™]=tü|Q¢–V*Ã$ÐÄf“8“Ä3ýg‹‘½cC}bìF• w†[èµ#QlX ±óNÔÆŽí3}/š‘Ö <³51¾Qª5R§Ñ„¸±©`j¢ÒØ÷*г­"­ˆ½•®Ž²Qؼv%ÍlÀ*tIGzb¬Ä°î®ÊÖN+3LûóçÏÇÃÃÃ%ó\,a Õ`=èY‹SÕ²²æåÐh´zÚÛÑz¶­SùAÂæúÛK¬"ÑïõìVŠ”~ûöíåÙ«X˜+×쟳­Ýª:2Mà`y}‡fUA–(¨éS“ß{óÂNíÁ5Þk“Ö±°3¦š]¼Fªrdj¹ûžÛä$AZ Sß$² ŠŠm%àÍQ1¦V,ú·-t«‚k”ê¼*Éëïé-°f g²Ø%È0ò“î?<>}>ŽŸn"Í·ëvÝ®Ü×ûŸŽOŸãéññ/žB õ;+™8‹„¾ŒwF÷ÝíŽwŽ%•ß9×Au¨îå8Ž¿@„,˜­ª™ÅL»*­L®…b}ðú=!@‰ Ù*°0½µ`w¹· W­BЭºûìÍrl„–-DNç¬V"‘,r÷÷„66Æk~¾÷®`OïÍnÕÏ?ÿ|•(¬‡8ÑžÂDeÍÒCœ_iKb²`lØØôÍRBLâz;FííÔ¹¦J ³il\ªý–Ä©†·–)WÉL“IÕe•½ H­œÔI¶3 m@Z”eübí¨¨ âdµâ‡¦Íæõë×WX¾x$½@Ú’ý 8v Δ3Äu ïêÕ˶}¾Vx•Ý&«1m’VšµÄ5•ì߇“ì³$ø¬¶(P’'±ÐŽQ™õº»V½h“ko^”´6Y»ß¡6†ÚÊý{å›ÌÂÚÄû61}bZHVªz¶°Çm<]ïPìòbÛÄäuMœ½¼3ý‚+¸&|ÏqdK°ûÛûãÛ¯·ûtü‹W¿7q³Ûu»n×?Ú®ÌÝqüW¯ÿv¼ýÛ§ã›ßþá¸ÿêëKðY…¸½ô8®aȆëg¡·¢[gä K$ÖÃÆ3\.CÕg‹ƒùàé.o£ÏÛë+†zÎ),£ßZ\ ýJ„æk±EìÆÆn—bÇq\x´*²U¹7 ,‘¾I^< 9)WݦW¯^]!B*Vv†Ë.6ÔZ#ÔDI\‚?Æ7-‚¯!¸„w“8}Š+M¢Ö4rk»ÏU´[u–äm·ªÿ‹\¼*¤B²(ã;>Å{&‰Å0ÍK}ö‚ÎoNQ’ØšQñ¶"¸kø*™)ëÕ¥<)XÛ*…5 ó…VÑ(c¯²Þ õy.¬ÍYö’¡^˜zV£•à{Lbo?/¡s²ö¿IzRªÌÓ€õùóçW]Ÿ÷·jÍÖá (éû v§ÙVcc5EåŠÆçÍ›7WRiÈÌ×Òë½+}m5FþP­äm/:öÍ‹6 ;>Ê3¯¡æ’ÝìV•Ñ÷ù:"Ûi³ã±ªc>¹(\h?~¼$:ÛÉ+A+÷€rì„í­ÇO ¶m][úý }jlÉÛº­¢!nûýû÷ÇûOÇñoý×ÿ·ãŸ¿ýtü§ÿù?OnÙÌíº]·ëéõäîîøgÿ¯8þÅÏŸïÿÅÿñ¸{ú§dýªoVôÒïlm6ѱ«ê™‰ÎÆ?úVæƒH3¼yóæJx`y" äøÚqé\Ô°»s,Q›>xx¸ü½Š‘vdŠýT.íoo0¿ß—ýõ×__ÜÞ¿1Ì,Ž4n,XW‘ö,˜ï¬ûï×§Å"wÅNÇZDJŸ[¤~óæÍ%¶,>²˜™â[ñ¶#¡uŠAúÜD&øY…y;Å?éÆÌuÒT6-A•³÷ÊŽ‹Â r§,[D÷]Yè=Ž?/­7uµ-©£ãØ)°a æš3þ±qrñ™Y©WÛ<ºÓ¯‚’ß·}'Þ­`‰Ë½”TÁ4îÑ´È€´ßj¡¯„°Á²ð+“°ÅÏ6 V „~Uïo »V·ð©^¸ÔÕIo!:Ùtý_»ªh*¶,O£MPþ““µ±©¢dB¸‡ÚÒ-1¢KãÙ¥ÿ‰L„÷³nÓ™t£d5ØÖ'f½X”v\CMß$Ñn•š¶ÉY齫衴£ÄÌ®4ŸZUÇö«¯¾ºTé„#øî.måg_?þ«ÿìø¯þ­ÿáñïÿ³'Çïßþîøïÿ;/Žw>Ÿ>ß`g·ëvÝ®IÌógOŽÿó?sü/ÿÓ~Üÿü/OÿÏv<~-¹¯ê˜>w©[uŽi0™§Eûsg¼<×5_?´å2T°ÓaÝB©Ár•o«×/·`v–„)¯W³Áø¨Ž‹†Þu³<çŠA„Õû /¾é^ƒ‡ûy÷R"áØï³o·k•Måõìí•îœ\ް±¬>/ÂîÁê~;ãWr|=£åŽ÷ß#û{†ë1h?´N÷ÿGJÆ&À}¿çóæÍU‘Úø)¡9Ä%¡iä9ç‘–P!V‘+sýMâº?E²ê´9//Ì!II¶ÊÈ…VLoФs­ÊNư“”uZdfŽ.H¼\“±ß,Ñ he}!>ªO¹Ë†KdÊ ¿þúëË mÀým¥£ÍšŒmŽ]“Ýg[xS­OÛ‡ýguÖåЈ§}xx¸’gnì æ»—uDfW!Ã'94&°šB ;k!–äE– ²–ÐÂ&¸&2uÊCÚµJ|΋•oÞN›>1U ªÖ˜¬¨Ò&§d§mkHˆæ•ÅU,QÄ!nÕVšl»ªÿäÉÓãÅ·OŽÿÎÿç?9þïOþ/ñ IDAT§Çÿä?ø¿ÿóÿÑ¿{üÏþÿöñßüñùñäÖ¨¹]·ëvýÿñõéóqü—ÿðîøßüŸþ¿Çÿêÿ/ŽÏß/þÿáñõ“㊄\PUÐÔÙ½žñUBh„¹PnÀ©—ÊÒ;•ö —ó[ÀX÷'x•¤~»DɳAŸ=!Îc­úËUZvæ1h·©ï  Z–Ђ±¡öñ¡úí¼ÜzÖ?/_¾¼ŠåΤ­=³—¶°ÐýÎÑžIŸÅäÛrè¾ó&¤“ zà(=Ýï›É“2X¬ÏLsàþþþ*Fb‚®ÐAqwÿýíÛ·W‰QIž÷o‚\·D|1šk®€…œz øø+_ufš’¾ òú£“•È‹ØS5[e-«ÃM^‰Ë-DÛF&:z™4ÀfÕ¬nmê¸ûýÕaïû‹aTÛ/œ°»uÆ5‰‹#Ó¥³m÷n–Û&x&¯ìØhéXDæoò†mÌ—µû.õèÙɺ†›JC¶qU-ÒGƶõv%ìØhT¦*™I–Õ £„ Šý]H¡0=ÝJ•ر3‘)ÉkœÝ$Åà¶èu<.Ù1Ék#Ü.¦Ï.¤°dUA;qJG?¼ý—Ç÷ÿýÿù¿ó?>þ½ÿÝ»ãñ¿ý/Ž7u³Ûu»n×?‚ëéñùøúîãñíûŸŽÿ³ÿèxòÓy<ûîû+Ŭ B%5Ü„–Ù5Ð'Ïs¬½ù×_½TÞû;ÊÅnWa!:’²õ’[.B—^s;å>Ä…ðë¨ gò W4!y&ëÀ®!æBÛ æ5 ïŒ3ÑéŒ×pRh{‰ÔvT’Oö½mW!¸ñX4OÁ~ï+‹Åô vW ´” }TûÍ"A¯»’¼Îð’cùÑg;& >kï½Ê"uIšñIbq±y€ˆ;…Æõ~.­@´ ²\­Æ¶.h ß*¶Énì‚:5Íl2ŸÉÌmÇ¥—»2qb7Ñ1(³5*YÎZÁY"ãFÑÄÑØgerWFWŽ’ÈbD{¡¶Kû\½ëîW?U—Ú› a-”Æa+jq÷l«6·d´î½E¢_ïÝ{kï]»‰:YMD¬X˜ä56bH—_T’¦ÖJ—Á¼ïݬ} ñ&¤&"ò‹l©[%hlLÀMP7Ñ‘,·ó¦±Ý Ü–¾pÎÆ¦±lM96ªš ‹«Úâ&÷Í7ß\ÖÇWÏ¿9¾ù¯ÿ‹ã¿õ¯þ×Ç›þÛÇ›¯þÇû'_?ý1–Ÿ>ŸÏÇï:Οã¸;îžü.rúûÿT5ð÷ÿåîîîPMàóçÏÇÁß¾k£ùÜÿ›Ïïžww—ÏÚŸ?tïè_ÁJž<9>?òyß¿;ÎÿêþþøÂçÏ|~wwá]?ûwtw\}þç³ÏØp }þ|…GžíîÏÏïžüþËw¿ÿ§OŸŽ?ý¸ÚÄïyöÓçû^ËÆö8»?ÆæóçÏ—g¼›ã¸Ì›ß«æ¿Ï­?†í÷gzdÞ|þ.t5¯ÎÆæŽgûË÷ÿøüûûüéóeì³ÿ›Æî‚Z˜g;€n|üôé`•ü9v̇«yuÜOžü)•~½¦~ì»ÓyõçØÜÝÝqïól;6ólO+zìçñHøü÷5ñùò¯?¨dÒ58[“Çß[sÜßõ¼9.ûÍq26ŸÏ!üºæîŽÏÇWÇûã»_ÿåñäŸÿ_Ž'ŸÞÏ_¼¼Ä“*PÊc5([.ƒ|DaÆúȸ·Þ×M󳎎2¸"q²È ·àæßS-CNýÙzZZ@1F¨ թ䑢꫱£ÁžƒÚ‚È2 ÕcPkŒ`uÂÇ×̼`Ú"¹¼9Æën¯qgxñM~ǾøÈbæR6óÐÑŸHHacg’ØZÓ£FØÝÊzËm×KRÃL)~~æO´†šñ§¥lÈŸɤ¢­±Ö®‰•¦¶›uê3“‚€šÕ„®ÅeåÜ”~ U, (]è¶ÿTÕ0ósrÔq9ÓÃ6 Ý®‚Æ?+-í s!ﳇ¯-àu¡ö¹‰”-°^¶\3KµÀ[x¯_¿¾ Æ×ƒg_èÂöl™—,H$\|­Ð°35:•ÇpŽg¦F¾Ò_Û&×ÂHÅÖ©IÙÃÃÃå®t£­S[ò&È’0—ÄØ`¥Ë$M5—æiŸ+ò`[W ¨‡ß^g²Üš}6vwµæÚwÍÇq<{þíñüî·ãøWÿãÅçOÇû÷;>~üt|øðyõÓçKõÕW_ý¸<¹;>}úýp¾# ¸¿úG¼ý‡3ïÇĶŸ»;ˆŠÇq|üôñÀë¸MOž>9žÜ=9>ý1¶õ·OŸŽ§÷÷ÇÓ§O.ÁÌïÝÀ‡Ÿ/{ÑÝÁþûŽÏüÇqÏîï»'wijwÇÇ.ü ­„©$xõ9AÞåÙÿ´Å5ëllÛ½g9ŽãøÔô÷*æÓK÷éÓÇãÇW î“'áwwWÝÔ»ã8žÞßÿžL0ïT8º¿ŒÝŸ>«Áý~Qå‡÷ﯸSÏž=;žÜÝŸH°/ícã%‘¶ßW’üC¼±ã÷yñ'Dù÷`üO¹õßÿÌS ÌŸ>~<>òl ÿ»ßÜßçͧÛû«êòïcó{2©pÈq|>Þ¿ÿpõUvòÙ ®Ÿ"õîïÿþýOdzg_1¯Ž?Îë‚¡Dçcwép¿ÿûÈ£„x6ïŽã3³…—ýâóçãɃÆBÈIû«UþÎ0פ{çelþH„å ár^”`îï_>?›þÍŸóîóñéÓç«û¿H(ß?;î¿y~{öì Ï_@è^úÛo¿]žq<ÏöêoºÏ‚]cmv¯7þéoôûª¦5Vªkz*M-W´¥û‰'«iµ±_Á¶1BcS|#|Ü"¸ü¢_z~Ïàíf#…¶QQî 1ÒXË’Û÷ƒ—7'ÏÄŒJ>‚WÉa1‘XžG#Ò–#cì¸óÊ@Øœg~‰HÿÝWyå¥ ìØ,tÌ$±wc"#J«g•ìšN©¡x÷®ƒ”ï¿ÿþ ºvÕ™é¡í txI¸Rg] ©g8IÉü„Jð.ס˜ž‡‡‡« …ÁAË|Áµ^%ìËÙ9#„¹Ðƒ¾5™;×Õ׎Œ _u$›%¤K^“ãrÇ…ã¢b‰­:ë÷÷÷ÇO?ýtùÏ>|¸â=yòäxýúõÕ»¬Úã„òs8M;+B½®‡?]}Ûh"AÚ²÷ |ùòåUwª¶°-y?÷÷hAh&êF" ³…¨ÒM‹7ÈbóºySQÇfºHëDH¡ju: »ÐUÒs¡û}e+=í¶yµIUåùå—_ޝ¿ý³Òê&U"ö Œ °$Ibÿ»°¹UdIíÏ*`@Á´É}¸c‘çTyW¶Ñ ´ ë~2Ü_ÜÀ÷Ùû}ƒ*«€Ä.·Ÿz@z¿uÁ ÝŸ[3%€BYƒº “ù†{o?ûLé^ká¢5ýõ·î&ï¾EÈÅlóâkΫϭ­ <”‚½$ZI°Í¡:Ø­„•œÍ‹B‘oõF° æ³)•ï÷}ïÞ½;¾á=Eýfž}9y¾‹Mœ×¥ü}¥þMÒ„÷ü;o>~üxµ×›À®M€çœsÞýA<}cóœ„W/¶ží9ûóÆß_¦îU{€ŠÅª®6nž^¡eëÀ^°m"¤÷ÇŽÜd¿½:ÈM¡þÆË—/¯`5zÉÌ»?Y°+>ê~ ÖU’§ B Š©<¥˜€ÁzïEuÍí6ñ`»×ž½qˆÇa1S‹=åÈø÷êF5¯…¶ýío»ê*4o¶«aÌ`×D2~{ek«3ÖÏ;‡*ÞÖi³§ «¨ E¶:Û•W>Žã2/Œoz2î­Ky†TjžIÙ软ùÞëBÊ¿TSzÇ&¨Š\-÷\Xœ±ð•@“UR·òƒ=tƒßÆá¡)QíGƒ”äŸuX÷ņm“ùôéÓEBXSH3a\P“ßÏÏ*ë«§í&úîÝ»K¢£ê™‹ÁjÔJOÇ‘1ëmŒK²ªH(W"ÏMS¯“»»»+õÈr±Jò¥…Ž5i4Ô þäd7‘YŽ­Ý‚yƒíp’}®žò=¯c±ÀÛµ°š²Õ–æóì矾ª¶ø¹Øc«š“¾zõꪃ¤ì·mçm )4XÝ–úŠD˜(º4¯Td—¬>ö/¿ür)4o[ŸÝ»AýöÛeã6à5Á/X)à4ÉKªsM 8UþkMY™ÖMÚ½¡ ÇßSí¥€ï±gkl 2•ª÷Ù„¢š½{÷îò¼í¥&*ïÞ½»ÌÕ3—òß~ûí²Î„$¬› ¬ŒŸ·WËî°ûUU:ŸM"uccº l÷®?€Áö¯¿þzU̱º¼_q@ 5&¡½Û38g‰‚hǦs®±Ù¢TÄb÷·UHrÍè2n‡ZMkÎsȹàuMžq:ÇïŬ Z‹„Î1?7`ëû‘wÍýöÛoWc½æÉ]¿ç¼jlÜßE=4/LzCíkÝó³gÏ.Ýûu1÷½÷^Z3 2e!VUV vò8L@EŒ,$ãg%„ŸZî¸Üs Æ~Íëö2÷»öa}hôŸI–{ÕxÝ‹E´46þ’̈“Ϧz•YwíÇ•Rkl2®Ä^‰šªD½0¡_ëÀ.\k ›„OÙB+YxŒ”¤ “Ñ h«5JOl»¬œVñ$uÛ k²mWÃ.DÁ¾„*«³o!lëR¼ð)[|¬NæÅ×.cåÏæ•mß…¶Ì÷ìBW¾°ê„²Ü+Û})T~ÐÖ«d5ÕòLÒzv;. ·l^´Ð÷û+mÅCXŸme_yg«úÑš[iÅáÆÐË «±«æš4‘1 4°(Ñ(é.mÓ­BÚ:[×ߪ¯ýogøY=•ë0÷L®)¡ VKÈú7ÁL„õy ¼{÷î*©ÕQ¹ïwàº&…‚ôù‹ÛÜ+æ,T¶C̱qÍõìíAîGbÊ]Ó&‰¾×Æx…[z¯J~ çZ¢Tli²P‚¢’Ì-*)Eߨ uõëÓ“«5ç¼p¿iìZOv¿íR*dÓØ›„‰6°kÐçV”wMµæäCÊu8[Sí¥í&»&*6¶wƒQyHpIœ‰…ºv†®º¦‰Šj^Î çÝc…“_ýõjM¹_85;Çšç’²û¾g´ˆcˆ‚.etÝ‹MÞåÈ8ïúý•WöŒ_9.óvâ°˜$z†›0ÿì9d í@.fû¡ökÁ 㱂\ñÓΛžK‰âMþMTD]ôìqzÜË{öµPhNwFë³ç±¡c³dÿÇαÆFØÞžá®ÇN¨«Ðý]“ÆGžC›(å_Cï…–Éa)öó]Ê?ês‹‘v×õàV'ÌwÕðVšZu^×Û•ÏŒ8K5£Ý$u—?SíˆvTÙFZ =•'p»›u{ø¬Ë±2´]ƒyáBšÌM†`0fÅŽKêÞ@ùÁOŸ>]:&Ê7¬wÐY­qS“rVQ(aÛ¬`®ÄÞcU¼&s­W»Q’ÕêVUÉúꫯþ‚ýU5ÃMl¿•µ´­¼²–&uÍ…ìð86uâs7®m’&¸Uƒ¬æxH¢\½™ú-½ l¹7v½wá ‰rLnOí¥ûûþûï/k°¶³Úïgƒ¢&Ø­™*Ê&%wëˆlE©ñÖ$¶±1Aðó ”sïÞ}6lï]5» ÆUßÖ·Ïnе!mÐÁ— ”„[ãh®Úêpó@6ph? ²¼µÖ¬Ï¾Å·oß^ÞUnÒ«’Ø{ J²R°&K ­ãRð²žîMzZ˜ht6•d5~­çtÇ©s¨Š±Á¼çŒ¿/Tµgï7ÛoVÎÔ»gW½Êu¶~"u9åä™Ü¶¦ô¼rhâiA®$ÑD¤sÎ@èðbÞ›W݇dúÆÞîÙâùùå—«"–\Ðæ­ݳ®†E<ì‚Â¾ßØ4¯ 8ûíPžCæR!×3ÚXèûrhŠoï/¤Q±Á¾c0¾B­©­ì¯€…àÆn nr=ýìVu޹¦–ÐÞØ-GæãÇÇ‹/.ûä¢*œ¹vdÚ«…ª#9ÜDGc³0àSjÏÑGÏ‚™0dÏÈ:.6$û+=½BP%AÇzÖ`yyÍ 9´ÃbزEîþ­·ö“åVùì+ Q’'Ç¥sþýû÷Ç·ß~û—bäwÊsLïË}6yõéÌ”étx´¸«”5á„­q™~÷õë×—Œ[õ†ZtJ+?¨©’gZã „Á¼Î¹m.ªO aRGÞIõ(!JB)„­™hÏÚß^R·Áy‰Ž­S7¹ò]úȬŠÏ®b‰mï&kÕ1¤:+!œj‡Xô]ÈBö½6/Ä`Öí²«Ð½è#T—Üׯ__v-u±Ì›(Õaèo´Q4?üðÃÕ»š¶•÷6¹ˆûûû‹òªÉ¸fºŸ„,¬H„¼ «™ŽMÿ÷ððpyž›öìÍßý¯ÿõÕ<µÚ.ÛÄ+¨FãS"´G½Ü´›weªv\[a %-J¢{oV²”Å6àìûE½\“­9“‡ÆÞ.e÷µ*‹&݇j2UVî¬"êO¤¬U:¡§­9׌Í%YÊûjÞyÐŒ÷žüñÇ+ܴݬÇö–Ö”]%Ó•<÷Ù–Ÿdç^ˆžó¢÷fbPÁk» ÍÁÝç_¼xq)TXáì÷~üñÇ¿ðƒzÎ'Ož— çîîîxýúõU1b zoÞ¼¹2 Ïß»ûöíÕ÷ÛïJº|7_ýõ‚äý ÷¬ŠYÇ¢ Þ±)Xnl{_œvÏ+RYݾԽ+ãß³ýôÓOxÒÇüñ ÆÒ9Öæ^ê~i—³¢R]Î5÷Ó+®}Å}XdÞ’]È>ÕßX{NTŒ”Kj·ª÷.WéåË——øË5+”U‡#¹B¨{V•E;ǫ̷.-KöoüÏÔ3Uöò²í^i!×­ۂ}iÅ?­›x®§péþ~kTÕVï¯õ¹ª®ú«Lj§NE7‹ÄqË‹Íä–;§…ÕÙQé½ßßß_hía­I Áv-×£°±qlÏ ñ¢6ì¸÷œ2Ñ1î}þüùE<¡¸y¡í[Ê*<³±‘/z¿ª,ÏŸ?¿â¨la…´€ùLõlÛ9’®·ý¸zÕ.ÔþMkÿ›A[ƈvI¼m» ‹«ösÅ„¶59–dYÐ%¹T,°êUkš´„t»ÛZíoWm±µ*ŒOþ^)ንt±ØÚ=äW]¶ÛÕ&oëÕBJŸwßË¡éðt“4àk^¹)-,O}!‡V$”Ô‡æãÇWA¡Fªši­<¡‡gßoã‘©af‰kÂMrIׯzv«¯’${7z+uï͕֜²š%"V„áéO¤‡ð+I¸*¦´æ l[œ¨òf[Ú–{op‹¾«2“pŸîÝâ•å6ù¹UHýœW/J¢Jþ æ…#¸Ÿ­d¨œ>Æn’¸î«y¿j2ýïBÄÌ—€6wvWG¦±{óæÍU¸‰Œc'¿¨ß÷p5ò,‘¬.lϽ¶ç^Ï «·”_ýõ%(ëY,*Ùµðà6ñhlš³®Ù’Dm ª2.׳sðûï¿¿T5í¢ 7/" 5Y˜Œöªsö¼Á«ZÓAeW˜ÅN—êSÂx (ÏøˆîG½§öZd+ïí'vAT.µ#¤ðÊr!VÁҽ½XTFÏÞšíù-6ëouÆëwæ{öœ*¾°ë 2×¢2κ˜’ý뎷O¿ÿþŠ#,<Üøh¹¤îGB¤…ôÌûo7ËåÖÙú¶²Þz5–í9c—Ó±ò½Çq)v¶¿ÙUùK®§Ý.“DùCBa-È-P_Ãð3‰a23´t¯© i·»5¥*š¼ÕŠ™>›{¿qµ{qÏ ¬vayËŸ>³æ(xþüùeM)èrÆgô,iî4ç-Jÿ%™¯ïíd®Ê×XÒ3b° õŒ\ëÂrVbX2]ƒgÛx9.g<’ÅQ.R yáS¶^ RÄAÚbó0«ê!Éq––Ð~F–b´j1VÒÍŠP^ЀQ£S7py ºþºQ¤ú!ÃM®ŽŒ²—Fnr¶­Û’<`ƒ ñ³Ê^®Ìcd:ƒ¦m½.¿Ç…æo¼pÇV8CC‡£ò˪-¡Ý.D¼>_CÍU»sl HU0ÒŒ«5iEÕê²mé= åJ5 kw4 \ì²L¹½?eÁ«Àiðk%ÊâÁʆë&Ý~#qyƒ}¡VmàÍógÏž]:uí!î‡B…r3Ù`|Õbïß8Y\߇­pšä-.ÛÀB¸Árúä:x¸µ> Ú„Ý8/„²öÞìÉÓDMˆeŸ‹Ë®°k®½|åÞ“’5(tM9/,úX ^Ξ˜ôÇÄLdV}Ó‚Z¦v²ìž°.W³÷æ^¯úfÐ2!D>›•u%„ ¿ÁB%œZ%´ÒƼU¼ªIºA»É-HyQ»”nЋ=öóî#(†‰ÉcÉÿ›p‡æ=%Ë•üVA©î¶žÊüªôwæÐî^["bW¢Ã1•¼ >=ÿ¤mêF Õî°~Ëgg]Xƒ2×ÔVTR–Ú3ú±êosALú™@E‹Jk¡ Ò§g¸{©ÚMþ›·š°Z˜µÑ•ëia¦õWPåù®…Bˆ!ÎŽýúÜÙ½Þ5ÖxfϹâã£ý|¿¯J«ÆÐ"”‹·˜©Ø€â!š¡7§UeÕÔÑ$K®¤‚=g†˜g~!λö‹õÑð÷88žñ»æìZøùBe}vÏóÑslú·+|²‚;©J‰±b‡VÚ@¿¿º¿_¡³S4Mq³ßzfaÅ"ûR*vç9e"$×óL ì¬Ké{-^˜ð™Êb{íòÎN;3fvµy¬ö¬±Ï’–ÄÞ½zõêJÁ¤ÉØÆX¢£!”7U`¡ªK8J!U=:|…ž)ÙiV^¥k 3õ0Xo“è÷¬VôýõYyfŸM˜KØá­Öôß›ì.ä!%‚­˜¾xñâê03/æ½@Ì kµÈWµ£¶öª­©£d7çšU<7©®H’ú¸Ø•Øn–òƒ&yŽýBˆLêØô¿µQ$ÇiG¦€UÈ£|«€Í9ç†äÕõ¬“n§NÑ™Àª–­÷’‡›¤í’ÌM ¾MåfYüØ «ƒ]ÖÖ]‡…ÁlÐjŒŽÂ=›Ð±‚ýö‘[3Ž­’ç pôo:`„G ™Ü®…óÎÃU(«Dùë©¡¤ùªW 9\8¦B⊠šô6ž ŒVnVÁ{iû•Ï*—ÂÊ»&n&•í‡vûM…!7¯‚Ú»[!„åôw2ÑY…È¥‘—¦Ô¼‰ÊÇ~øá*1Ò€®sN.¨0Uˆ,¸™`klèï+É.ÔCSë’À]S[™7 5pØÂJcc±p÷Òír.'ϳÀ5·œ?!Â9=§¾þúë ÿÀâ‚1ÌVîM U¯Û$Nñý> R×G¯{S´Æ5ѳõ¹òÊk?¡¢aï]¿Î;>ò`- w¯´ÐÛ^nq ®`PVä’M«Uµ°²°¶ /’¸w/µEôžuí'„Õů)á9é^½Ýw»Ä­Çž¿$xáãJ k®Ù¨kJ‘+ŸÝοk‘P%Àv¯~úé§+¾—g¼c#ÄYc?ãf“ a¾í7ΫîEÆ~s»Ý*Mj›Ó™ž&3VºìÈ,ÞßÖm™•‹„NÉ©B„Út4ö1 ]Ùʇ2º hƒ¨ÖøšÙÚµ+±ÒÓmrMŠU¯’D*„¨gSõÃD&‰¤&+Qv¶%/ln%C—xlâÔd­Ò©òÖš¸ùûgr¨}¿l1㹿šàJÚZE·íÔ©\ñ÷àO«Ð¤—ÉYWBⱓÀžMÉâmK»ÐMtîïï/<[AUßÖi°¾þÖ¶µ×lT(‡’çVÞMÖU²±zkÒ5ÕáhO嬕µ´Ê§wÕ畾¶¸°•0=»Æm*º¨ IDATÆ÷t&1¼Æ†+£{¦¿¿’åâíÏ‚2\@–Àö¸ï[¼Ð—Á±±K²0˜3ø•Ï&ÖN`„‰Àט2Ñ[Ýõ½JPµÈU᤽}}±ìº­ŒvŠ´×ë}%¤Pܹ¼´Ö\ûM…¡ ŽkÅUN¹R±*ëÝþ!Ýj·{eð)ù?’gó´Xñ£Î`{맦°‹RÏø3‰a»vâzv+ÛÛ©kÞõv·=g ªJ Mµl0ÁíÙäK®Tí*ƒõìíå«LºûͬëJ ÊäÉŸtN ”ÇÚšq^¸×zÌ‹„P©oáãý¼¼Â‰pK¡i%‹<#£¤¹f¢+FtÆÍªèc’–T£ý¤ßÔ´ºgj·Ižˆ•·äf9¯-¬œâÝo´ñ¢áö*Ò:¯|v‹RäVÑÍBmﵿ·Fª*æ.Äzi ìfé§&ܳ½Ö8Õ=Á¸Ù5k‘Z‘ÏpÈüýÓdF¬]í=1í¤«Êat[ú¶$tž™UXt8[·­¼Á¾/ÄÀAÓ£°Ëê¤o[¹¿µ-y™*×¶2Z&G&„U‹±ú,îÚÀ¤ÍɬXS#1¢g:éjw˜ØZ]õ*UŽ›ˆô^{×UºÌÛ­ÒÛ@ â5àái«×…h’g5H|¬8¹Ug]‹íFy´Ð„ш•ç!ÿHˆà”&n:+Mm¢±’ U Ö×ñŒË°$È•V.ÑMhɳÂ?k°žAosa‹u‹TæR.ÙŽÍÞ»¤ï… mõ 2°Ï~Öµ¶·¼³õZV•.xÔvx9.B€Ü‹u÷=9¯>|øp™v- 0•½Ü$ͱõþßyeáı‘”½¾ Bƒñ.dñLö²ßSRÝ$Ó½zetwÞ5¯ Ê<\ØxÌ|¸ýAîÕ•z/&úN‰9wMemo{óæÍÕœ_îÔ %8/J„T»´»®\ª]ߥÁ¸ÒÕ´ìYÓB¡g_>cx}“ÈXß 9=CÛË—ÜÛúdÌý¦ye×b•O5•”˜ÜÞnå»DDå¯5½–³×³÷÷ÝëÚ …¦l7o*ºõ^ ºÖ Nh™kòLÙ˽Xî–2Þk¬lñ¡5%ô]éjUW‹I6‘ñŒ®ðRŒê¢go¿0v\Õ2- ê*Ô‰ZoafÏx}–VÔf;…‹X9ãVY$·ý˜‚Ý:<'*|(ÔгO¸fVÕl'•–{µ¼3Å뢚/´y!LX²¿E';2ÂÃ¥›œù/nNñË/¿\u˜]3u1å0·_tïq=O¥™ÍŠÏ ¬ÆØ%PæÖ¶rGeàÄó‹ŸUBÔÉ$^Î"W!IÐ5ÜìP½ª®ÅÚ»UˬdY½íó‚¶zAÍ™·PŽå56z,Gf[Ÿ]?ýôÓ_ÚνÏ×å¡8vU4¶²O¤n—ŽÊëâ$·=h…³Ž‡²Ý&¸‹›n2[‰ZRwLÿ=|m¿—ûâoÛã­ œU»MÜÀAu*ñúë2z-mK^L Uˆúú\s+gÚ¼Q °9a'¯ï “©’%4M"âš´íѺê0\yå3‘ ‹]­½ì÷¹ïu%É5Êںћ`÷³5…\ž‡¼{לj0+¿låÜY©…«„Š{œ¹I,l¢"9Ö*asE\¶D¹ rþ$}7¶ÞÏÃÃÃeŸÐg +ݯób +u ¶£#Ôc«»ú0hìÜ~ œ³`ûÌ)[òmë0Ò÷î7ëyò@š[=6ˆ;#u+5ë9$”µõæ~cò\AÎÀ@bsÁþVÖ-½xñâ*a7X7 k<~úé§Ë; -Òy³;‹<nÙØùîåÙ®¾ÆŠT´ïÚ)´Û^Û¥ò–>v&‘»W[4 >Õ=´×.1Úêµg°Áz©pÎUuuMW<Ð+e“D!ÒšbûìvŸÛÛôÑ[Ók ï ~è;µÞNgÆŠòõ¢óÙ[SÂÇ…ëç^[b€.”µ`[“ÚÖ§ “*²Éå4¹· &Tµ9öäÉ“+Ñ›…ÎëϸH©b906äg›<9\þ¶H¦Ö½ AÇ„¾Ë;SdbyÜÜOÎŒâ}÷÷Vø{!Ûu³º¬WŠˆRM·£²ÎÅ´K²tÀ¬`FUbOh™¤%MüýÅU÷[¶n[H Ñ  …,®ÚnË]%å [ä¾0KŽU~JÉp®òl;/Âß—”-¶x«9*S”•ë]°2»bÈõØé€QAe/ì’ë›ý»D9M^]SgäXaëiauwï]¸æVsä¹I®úÔJÁún„3„˶šcÔMP’c%HiÇæý¾WçôâõWI°DEºPye ñiÍ”È|øð᪋ùX¢Ó}={öìJ(Á€T¸„Ýs¥«WšZh™ :8“î7-AT!_Mf——æš‚ô˜ä§É€jzz̈!wNZE\´»PU×ÌôZÁ´BÚ{ß$m=/^µäZ¶åØXp[rîò<ì:Èw,è“о°=%„U-ð;CXtòÙÚ‹S“k¯´ø üò )«[÷zÖÖ‰*‹ge|›7®ÉªÏœÞ«…Ð_Ö/äŒç*‡E¿´¹:*Å?*íÙÉóÒ ÅäÕ«‚y¯Wœ ´¤mùŽë£w&$¥’|C9Ã+^"Ü1uß]¯¸õlÞÊv¯îûžÑgƒíMíåŠ%%8!—S/–åž›ÐÊõìZZÁ&vM7A]¹÷b¿ ¿—ò¡riçX±©ÞKý-לÖÆÕ UísÍØ›ÖÜ¿TöûK2³xþ3M-2»ëno Ð \b–¸|FV³uj@ªJ<îǶ¯ß_’ãn{ð¯ò–íA³n«„ªEuÓ’ wXDáWò{$ÄŸümb¶Nçè&¤üòY{0‚©Øb=vš7Þ+ѧ9ŸžK†+hS±då›òhå\ܵ—ÁסÃSëíV­¯CßW½gklÞ¿UéZYo«9—vÞIZ¬å¾\¡a*wYaµå.?i»QV‹ X…k0ÉK³ÊWP³dþ%¬{,ÔÃÃO.ƒ»ÂÞ,¬t?®O‰ÁV¢VoaÃyµ~híÅ[qÍ6o„¢z¦šÀ*V´ ’gêJy´«P¹~hrŸ æ×ïL²¾°º³¢QsÚgïŒ?3u´ª¿rîÆJø «;“¶Ž#¼Ï¾¿&°Ñ¨ ju+Ba‘º±Wšzù×fäY~ôrúL¶µiìwÂ9«›ã»×ÛÍóŸÑ3Z %ÇFµºõä:S¤UíîÝ»w—bçÚGœÅ–gеŠdY8éÙ–Ó'ôÌs¦¿ÿŸe+[¨ûÛß.‹¡…juÚDÅ ú•Š]˜YUêRBQ?»NÝ«zvf쳆™KÊî…Zýöe.ÄÀB»‰Nð§6xÕXj©[I·ò-Gf ¤o­Y}n„ÁØÂ[×Þ>orYIÛjŽnÚ*ÝXe´“'A×]ƒ.¹Ok¾§çÅÊö{ú­dçäq¡Ç\Ê…²¬ùžU¶3‚ér«–8l°nuEÜôê¬[‰Ò[ÉÏ_¾|yÅ¡£”ìjà/¬¯ysæ'âoM®ÃzÀ*Z\ØÚŠH8¯Üš7Ýë«W¯®º˜L{ïnÚº5ßßß_àšPÂê„3XY·Š¸þV0·«°¼39{rD¬Œ »–²&µ+s+ÜRhšk®ÃJzöìz(½/Œ&Ùn¿¿&³AŸì~ !²Š·&°Ý«°ºuX_>â1¹€5È–*Aªšµ7þÓúO¯Î©ö!Jz3•Èx¬;½óÜŽ<ל Aî]Uî+ uƪzf·Ê¢ÑÙ~µ‰ÐmA˺¥«U l-Þ_ä€rï¹B"Û»¿-FjŒXl—Òî·pL- LD$´+ç.×ól¯^Žpsqd“¼3•Å…Ñ-ë,®%ü©BnÉÇr5…}ž%"ë£×š*æño÷ì&}‚ñÊFëØ¸×Û9 vwæf"´°»bysäÞ½°»-¸æ,JÙ©³Ù9£"cï} z«ŽÙï¥y¦x»rï­“ß,¬X|0a·ÒHUÖå3.·ª8q}döœÒËmUY·heÚxG¾â©ÏÌJ›=Ymð•}<“VTí¥Já¤&2ák­…»n¾}ûö*S6 ]¸‚01éë°ÞïoÛZW`%ò–Ô½P94vŸ\ˆD,[íY>€Õè:èóÇ|‚Ù4~z+X¶½¸R°*é„ËÞÀC'lƒu1¨¶Ô…‚8/œGâ[WBøÓ§O—y£þþr&©RÃ)ͶĮsíBÏ„í™üo7kÉp&ˆk&·ÊNœ„tƒ6pÍM€Å¤ gð@1‘//Î=BIRÕf„ ­«VqÒÛr/Q²ØßUª÷±&kq£ jWò³`ß±“xÇæ,þðáÃÕ~$©{å¡{¶ª€µìŤûnë>›$ÚñØÃÕÂ…þAkÚ¡/ìÎî¹U>ùG%ÐŒò@LR÷Ù â„G­ìÂA;‹ä;ê¯a"£_Ècè < HKá–’w»wÏ!yiË[SÞ.g{¹Å‹`gpÍÇl TÞÚê³|Å3ðÂXTQt¯ÜDGþ¢|F!:Ûñ@|︕ÚOš1A^î–Â+íµªK —#cUãQ¹ VÖK,|lÐåÚ³ï½^*òd+.XŒ0>936Ôà·BòB˺ß÷bâöZ÷ÓSWBŽðÂæÖ˜Ù½Pµ`¯åzÊñZ¶Ð±¿Û3 "½<—3è¾E)‘DòÒvÞch*’hU-Zíšh^™@»×j´êÝçkÝ!rAcçÖÜò`µlYãþ>GTÜÓ3\E2.ìà?-|Ü¢Ï)gÆbûÑŠfuÌåySyŒHè¦(‡Æ ^}~qÙ’šÌºÏÔÎ0¤*¢Hö/¹©ë`÷˜_HP^ÞÂê$ß>feå\XÜ@¶äu`÷÷=`\è¶Š·£#ÆÔ®ƒÐ²…?ÌžÉÚíòûKäÓpÊ ÊMrý@6¶¥î¼Z æ•p-[þ[±XÃLT[r·RöZÿ!qÓëÔ}Ö–¶¥/‰ò kÒ¨>¾ï}a,Kô3èjN÷l+yîØˆÛÞý¢n•cïçÎ+Õ©4ï3™·í\å{×”˜õ5BUùk+QË3YÞ˜ß?sD–¬ßØm‡Ø J®ÃJ¢·f "é[E¸uê.97[…H ¤í…¶ûí^|fNl—Rn•r§VÎÛ BA Xì·¦’“wͬa¦Ši[y3®ÜéîGg²ß{ÎÈõ\ÐÊ/o’v–Ü/|êŒ(Ùß`Þ5a`/×sƒùªË&¼®¹^¡ žá&Î Ïa0½P8m„’ȹSPG3P+ç’ý×KåÌókUW»æŠçXkâlÍmáÅ`ÚêñŽmŸ÷÷ôn²P¼óÂDÆyW³ø¥5³~h+%¬+]m!w?_n”Џ ½/V«Ó·Ý¨-ú°®lwÿY~gø&¸½·Ôð–#|Ÿ,|jãáåã3ï¼i?9ëj¡`’©½çÔʽ+Q¬º¦H%}ì¶—ól/ェš&X´ŽÝñ³ýH5ÞÉjͽÿþŠËi)RÉdþRDµ+sƒq£°M´<‘^˜V[§ÊìÚ¦Z.ƒ¥‡Ÿ|IÓv” Æ%6‹Ïµš³Õš‚6±ÁV²Wž9¥PµÀÅÇöýÅAÚ*]%=`Vbo•rzöªtVΗXl¢ÔÙ&Ù&ØB*ɲÊßÐßÓ‡æ —-FÔDÆ JˆÎºˆ/6ÙMð15+®Î+ᛵ ðc•*Ͱ ´4b]ü­‡_kj“D«Ç’ù•’]ééªí&ŽÞLgøÛ5+•Çqfl¸‰Ì h¨öâØ­l¥Ižôm‚â²W>»ÞòÚD5‰ï¿Mn­N¯ÏŒ;+â༰ðQ""ŒÖýă_žˆ{©žÛ±Î)gÏî¸÷W«Ï&6&ÈB€¬"þ=IÏ5^O­­€VÉ+¨sž¤§…44àUB؃ßn¶{írp¶Ó·r©Væ‰X‰`n×»¸5™-‰³CÑ9Õß’³ç~"\ÒsÖŠçœþG…{.¼I^›Æ‡Ë“už Ÿ2 ¢dÌ D.¨…7žÑuú‰, Fˆ´rígJ‚®ÄõôZU´ÝïÜëëäylë/Ô^keÞ‹„uÇf½™L8Ï ¿· &_т޳gÏþâ‹eìx&'/a½ŽŒ0½Eû¬OÞ´ßöså—ýÛŠ%œ76+]3+tp#è3Sl¹…“•Dß‹±cñE+9Ä ·ˆTI¥b\…Z94k^¬¸Èóçϯ 7¿üòË%ÑY?´¥\´q®8Ðxh¡Ð¿üh9ÆWê— ÀD—úæÍ›«¬;¼~Æ´—¬DÞjÈWQ0ó¬…&ÄÇÀÁ ìVHÍ,×ÜÏ*_%+*–X…3ÑY—o'«³VªVòÓv^’žÝßëׯ¯ôöMtlŠ™wò¯Óöz”­»©ªlÝKøÚ%¬«³®š“d7;q=¿øÙ61•ol™GÎuÞH†;;÷ð´:,?Iý~•òÎà ж>%"º Z¡ôØya°~f\håÜN^¿‘·Sï&‰áþÞšû©#7ËM¼EÕ´æš¾íVÙ‘QÀ¢9¿Sû¾p%¥XMþ Ú<@ÚÚƒ²šöÎ*>¸á+‡jaÆw#œ¢û“w¦P‚²ÝÍ›õ.00Øß®€~’o·ÕX¹‹Y¦Ûï)ßßûé§Ÿ®:6V}vyq&‘ÛÉ+èr^­x‰I E)å•%Ÿ¹Ó·_È=¨›$)ÜýG9ÓîÝ¢’ï½ýÌ$O¼óÖZkòìÙ7+j³dÍõÎÔ£¶›T¢cPµßÏë­ç7fÑɽ÷õë×!}›Ð.¯L)|çMcg§oÍwMiÀkQJ‘ О[žEÁ¶‰‚IâEUÈW´#Ò~ï¬ûéŒï¿wÆ £ñ[.„ÒÒKÚîœÖLYB¿êVÂQ-¬X©£â¹§èm²ÞXï%/y°;6ËÝnÖžSÆ–ý^ó®qq^©‚¨‚ç™éõv9 ¶…KêÑcl¸¾Sz~bµ h<:‡–›%ÜRÊFЍ¼þD¿µß8“í¶+U²þ¡ª‚h1R²šõK{ýúõU'o÷›ì+Naf’ž`IÑbí4QS±DžˆÉ@&±Xù24½VÄÏÚ•XIÏ3RSÉF$˺1Ê A’ôí&`àaGÂ*›8ÄuOÛ½‹ ¶;&GF‹]‘3!“Õ`TÒq¡¬¿}ûö ûØ¡ü`ÿ^yª»V{VšÑ`>˜ŒY¸øUqÛâg­`v¬÷€0˜íä­ ¹Ü*7¹ ,ìØè¨¼Þ¶ô:¶cçB¶º{æ¤A\ób%‚Ý|”®.pP^uqÙòÖL°ûÜ€õL VlrÁº$Ë3»kÎuc‚,y×g_A]›¸UM¾Â¯Ü/Ö/d<ìHoK^U2X5…”ëP%K(Ç„z¬Ñª r‡Ï&Ú>»r¥Ál·0"i|…_±§RüBEVDÂNàîÅ;/RÞZZXUÂ4^Ê}6ð0Ñêáý”ÈKÀ7^è™0_÷zymÂ\v/·Óך½&µvt1o,+J9gš5…´Ÿ<²kÆ3ül¿rÍ1òÝëY©Z“\•½zÏTEmTQÜ®„Ïn©õ¬¼Pz“¬’L‘úÀì9%¡½õn!×3x%„7¾Zß$„Ϻ¨–˹jyí»’ºÛÿ½w#Íóô:/BΠ‚ùµ¦–{µç\…ÚÔ ]…í­'Xñ“>yýŸêœv˜í¼ eu¿hÏ·ƒ+Y_¤€Â,룗XÒr³”Gv^•ä{ 9”${)Kí0› {ÆÛ ÓôÚøÉ{ ¹6GœÓŠü%™±º¼íGÐm¹Ÿ¾ <ä",¾öÿGؽ-Éu$W›(©OÐ6ïÿŠ#€¤† ¤æj•}ùÓj3™‰LVUîØ~XGê%tí…;>Ô„²âÅ2Ö¶aWLz¥«•¶F£˜@‹À훽káU*2—úf90&ËW,¯ïçåìÉóðwÊ©ÂRï©íá”NÏë%gÓIÄJÅ #¶iÕµ±‰d÷ZÔÇ X›BBUõ'’3VŽË¸œæG•²·x6ÞiÐx´ïÖµµjñoSG.„_ŸýB”T @NŽÍ‰ÝÑŠ T|Ä"T âíù=»ª­…²Úˆ•ÓR¡(㑨‰ý>ïÈ)Õî:QiÃ홿be¹·/Ì{åbj¡ š¯˜Æ³}Þ3åï·R6[^~&›Ú¤¶¦893Jv w0±p¼éÅ,æÝEË·º‡XÛƒËqñ K:ª¡S“ªmlGê²4ˆ ¸‘û^Òô´¤ìŠ™ÿé§ŸºÏÂ`ª³nR&ÙÍNºÇŽKÚ^GfãM7³À ¥3mý…V×LëÂ+Ÿ\~Q¥÷ójomì¨2$öØ‘ù‚Ü&bÂKˆï¤n…|KÖ—„¬£ ‘O̦õ.0)[ÒäåèÈÜÄÂd½Ýc îI–¹*’øÞUX²»½ßå4ª“8ñúMš.l±\ˆý½_ýõ .±µ¹ ‰’[•Ævmœä©¦'A}ûfçHP 1KÂôr-öxI•6ÉþKÖ…ÕO/ÔËO‰ýÿïß¿ÿ.iºpÓ’s×\Xºð,'2N×·vb—¯©ÆÕ”$¡ÝxäTâ2ĬQêö] X%È7»§œèÔÓ©Â`wmbÎMÖåv 3^îÚXmÏàÚY઒¨¨ŽÍƒ%ãS”Ò÷IžëeR«¬·ÊYî›Åò­ýÖfwnáäq¨ç™ô]íç[ ×èÕî²Ø=ÿ&ÄÕS× ,nñdÞJN„¾×XPõ)y²mƒº¯œÀ¶çÓ„wïÖxc¡¢ñ²Íƒ"J,dêÝd²í¯Ù¹f§UKXEÏLy´SR94{oÒLæå̸/ª¬Õ{nû¢÷˜HzŠ%ÉóÐgæÙØü©ðr¹á—?£ðpE>|øð]~UÅÛàrÛU¬ÝºîÙŒµËOœ~_†ß66ÊÕªj¡c»{JdÏâ‰÷œŠ¸mÈB-ÿÙ{ªñæ­˜©ôaÕ©–¬+÷7£±}iõù{AüðÃï>|øð©\R“ðªn\r¨—»ý4±]p•Ájì³ ( Jb±#W‰ÃJø:z^P3¬aÖJ09Nr›]Œép”;è•O.4ìÂëKØê´kk³¤lɸÉþ¢Ë°i»õI;˜“ÁÕq}úý{öÁüýJwÐ÷ëR¾µ{Ö Z Ù¥d³äZ»Ë»\$uK<îÄfæöXGæKºL0ý2PX ë}°Ÿ¯¬¤È޵—pªrT‡÷N„œîr†Êpà IDATTåGIÏ˸ü 'uÆ“í›]€BÏ„†)Ùi!Ó w™¸íR1¥¢­Oaâ¶ •­†â#;“z/ÉKÐI{—ˆPÕÅÒ}÷â²%çnOà___ßȵ&û^ÆÂŸ~üñÇ7‰ü# «9¸W–»„ö5,`wín–7è™Â;S;“v§ýÛvHë æ%^Èáž­“ý>98¿ÿþû»OŸ>=Àâ”8b-ßÑ ÊºÃ‹…J _Rfg]ãÄ­ÍÞ¥EZáÝÏ8{¯ä¥Õ”zÜ+¡`mŒ¯ÖØYŽ ¿±ÜgßY)ìn™í™ªž9Ý=V ^9yN=…äÙ8iq¯ŒüÃÚKÇ|}}}ËÜw5Õ6¾iÄ*4ÍI¢(%–7A.Odk뤮 ©¦vömlÈÆ»õ7}}}0 W–{±}g¥§ÍÝÌ_”¾s¥Ex×,—4îxMpùCk¬¸o”žßßÞ»Pxe…Òšì¥ìL!ýüùóÉñ5žÉ½r€ }Ć dí¿ŒäõàÙ¤ÏÆÆeîrMjs3=°‰PèÉxá½²æ‚ü!aum><øÌì—:ò_4é²ÓS‰_1šê¤;²ÛfÞƒî ×-z—[Ç‹âkÅ´›tVeh œSušöûÛéòr½œ´Å_¤î* ZöîÝ»wÿçÿüŸ‡‰I ¢Âî|öðz^øó^~Bˆz9zÙ¯Û£€pˆvÂÄÃVű³]ºýoA¬ŽÈ&=MÖwðº/L –Pz˜¾~ýúÀ±ƒºç¾)è’w¶[#ÁT'ízTV[!e)WÄ]^%»Ü¶§Å¤/Q¶ø‚޽¼¼¼ý~»9—ô¢Ýa§²+T<7ûýëT©BäS¡„Â1 Um!4Xœ—Wå“·¶—wÀ?üðîÓ§O'·ª>1{•½væ…Þš84áT ¤xÿBe·ïäû(NbNSR§6^ö.mœh>\Yïý¾Ê;‹)WL ñN\}\›žYaÄ‹ò@ölJŽVÎôrÚ^q#¿G<¿ñæÏ|­æÝT¨Ç5铯¸è—5ü\¨¬ûVYï%Ü+JíŒïÙ·Wä:ˆŠpÊ*ùÞóîÄ¥P֭ϦçÆ åÞ3ïÞ½{÷éÓ§·Y?´)Ãó«ìµ»EuªòƒœZX°«¬µ ±ÆÏ{õZ1!5ÿ1ÞX$ºoÊKó²É´†…–“A'È:­²ît¼Â,šÐz&mJÉVò¼›åf¢&䉨(ݳ;~Ïç¼}¥(Ec¹±V/‹‰ÊÅï–[¾¼¼<@ËÜ7ñÙlº-–5™7–š.Þ,FÙPSL@.h ¿/èÙÎÑ?ÿùÏ{ s„ùbU$kïi±\ wÏl¹žæ–6‚÷ó" ÆÍrlãäŠGÛ7HÔ×JõMfæÒÅL5¡Å&wAMæ½ :6–HX㓦bÞ/u“í’8¸X‘‹ÛV‚OŒ¨„úûòƒ\ÐB€ìè6Ý©„‰G•·66ö… !²Sf‘V™ýϱóF§zô”~)áØ­ê¤N¥œ‹'²ŽG!<ò{T«òr«GÝ¢uI|慠9Z½|Êê³·3î¾+œ¡øXqÛÏd)+¿¬F¼„õKBXˆ<’­“8/ˆò‡ÄWYË}£³î°.á{ïâg'—ZIÐN,„TÂREQsaw^–ƒLj‚[YË?k¼˜´™gF+—Aì±SJ; úÐüöÛook[uªò%QÖ³¢PU}ž5V* ±¹Ääþü…9rh²­H4êiáçršt—­D±Ó²BE:ieâ`Òæ¾ñ²6)’ÏxqAëc,–”í„w‰Ó ÊB¨…éÊ©ºT%ÍŸ‰H”sWdÁåV™ôÔÕæB#šZË/º¸SÂæ4µ– ºÄ¿ Iõ:zvy^Ø0+$Q®¨gF¨jåÞ…@ïôÞVׯÉöÕÎA½•l´–;%¤ÏVŽõ‹ì_ÎÞî9¡aBÓäÉví”ém¼Ø9¨Ð‚÷”|Æ‹¼"mÿ+ÇET…9€±¸ügQ®}!‡Š“Øl´1"?ȼU~‘ÿ{–ì{OÙѹ¼ æ”-GFÕ¥d[èçßWÝÊæ¸ÖN—b\ÊíÛ‰ZÕ-TÒÑ.Çk´êØÙgÕ¹öÙ³·*wj2îåz¹öJÓñØnæí¶¸Y—ô(my%Œ®*7«ûÂßç³m´j÷Ä„tø[ ìíËK¶[¥M%•–VÑͩ¾[‰~Å„ãiBi—ï?þxøîÂ|vas&Œë¶ÈMx¦hâ¾_»µ-ùVµ=' òLWxæ±£¹ŸEàÖª†™åVmšd¼¨ŸÇ:–ƒ’Ú=öÙ:å´“µËgrQ»ſxþË¡ÝÙÂJ1€’¶JTèÀ÷Z9wãEÕžÝgët¼>2Š•¨2$n[ÙK×Òît§"vé ãÝúîÙ÷ÙŸISëVü{fÆó0^¨ìU®gɹž™JÝ×-wÁ¦Qa4ªÙ°sú]Ø ½*(íâßwµTÀbÍa²BU «sí°ë¿{lIIãÕΜÓë}.Ô¶6à¸î¹zr=ó­Ú³™5VJÊV­©^oÚUIÜÏ,^í| U5žìœ¦»üFÒvÅIÌAL8Û(VíNÕ1'5wÚ¼"í*P/¾aÍ‹/È¢ ©¨ŠÁæl|È;«‚½§œ²vŠZpUk̼µRARD‰ Ž6V*Ó¯×[å›8Í67ôLíÌnÊi3³§ßN+…¯õ†ñHq'‘»ÿm²•'»F@QôÑÂ`ÿ<¨ik†¢¬„–YSØÈ­Ú°½Ÿ±Çðýóp×jÐWîÔä^¿%ûv|¡»\ LKˆÅû8©×wqÙ…­Ã¿Ÿm²_cÃzøù6«S/ˆô*¶y|¶zlänG¤zB9äqtív9ìÕk¥•ÂìH˜xì «|£·À’u÷‰I—°:‹ÅTMÛÈÞ}#Þ_e/«úª½øýÖå[B&LƤã2«¬v!…Êf{y-É©¬dyaJOÿðÃïþã?þãÁ@êâ­9²ûlwÙ.¤.GîJ w$¿‹Ã÷°¤¬]¾ vöëd¡Sµ—%¤•Š]²"AÔ +t­p±Î+d,Ô„Ù,^ÖXH‚\‹4 2 p4™Ö(õò¤¸›È¨lj¡â=Ú‰L§ç…íÌ^w|'yªÑU•Õ¸6Yž9E$öÞ½ëýä³™C,áF¸X깨Âä%'_ bIÛ¾Ws9§œÐŠÚÐ?hki¡#WT?2í#lb×{ißW>c92Ò [ämß쯨ü#ᘋ6óTQtßUèɦRóŸÊv{‡×ZcMð­cEê#Ó)éòâÊü«†·ÏÍ,d|wr9…Ýy&÷ÿûÞ÷ß\’æN˜ÍíT¤­¹ñÓb¦\…K±d º‹^ÕÊèvDfâ!¶XH«êj_Faªµ˜8utZGd/ý7Ö%\ ë'Þ¿ôø®mÉøJrþAyBñüW€ÞÔE¥ eI”…W õ°ãà{Z ³.g¸mƒìÞã0ï{N»tvîíêÙQpeBéåjÇ`¤êê¤WzqAn1œòT»|Én¬<’uéìò ¿2±°êåYž‡ä8ƒŒjÐ/qi,ɱ˜p½Rì®6€7©ªâ›)ƒ˜ÞK5¨ŽàTÒ ©Äp±ÇB"·Gzf›³Èv'/m—_“í}þòòòWè{Ý?+ð¡\»Ýáz^ôLÊéÙµ]Lpò&”V§°6^„Õ-™V\¤—[¹ë Úz\ iŸ½ÒÓ&9ÿûßàm¬85Pæ_¾ãåkUÉÏ*H¶)eÃÌBÇBDÉüJš+ŽR>€ÅýT{šàÉgÜ="¬¯wÂ[ý|¥bå̵{«7“s ¤J¹ª”ã… 4L˜ŠE^•·¼lõR‘ º}x©G95pêá¾ÒXp—c§çN1Åó_²Ú*ù+-ò¼‡ Šê™²šV)Ù½»ºŒïù.¹S^cµ"9×}aR¤JX'u{¶KR\hØþ92Æbs“ï*ÂÕ©Ûdßo„?3u¼Ô¥žMÇmÈ)*S…£ÿJÁ– q ¯8‘ùöíۃİgfÏ:x•ñFX±ÓªMx{&- :ØXcDuL'ÈrÊ;+‡ÅBÄ{AZM#y¬åÈ8µZæTÈ¢wüb±ûÖ|jñªÈ€í~ØÐk¥pËúÄ‘în¼‘çZÄ=ëž½<Ö­m¹ç£\è³g³¡H'-'-¬nÿwMê4·ñaîWa¥¥¥¢¸äÀ¼{÷îÝ—/_¾Ëí|ïJÝÿñÇï>~üø€p)÷j¿ÿ­˜YBk·x‰…r¤v,$ ^d}“uÇÖ³Šiï—Þvj±‡ÔñYR^»€«ê§p$vwÁ Ýß«s®\ªä\É·~nÕ\¨F1¤-ˆY !lOå Þ._/K~ÙŠÿr¶Ý†“Àé$Oü­ÓËShXɳvÅßJpµÐ‘0VÒ¶ ñån/SX^ÅÔæ¿ @^žMÊžùHݙқÀiÖžMü«P¶qlv&ìXì »6r¯Š¿ulm÷YÈŸÐ65èå™ ×@×ËÓ ¯Ó(ƒœñ¢ÀÅm×—j]ÂíÅ/_¾¼%‰û~ªV>Yr®P‘A1TŒ+œTÎ % ; º”ï=J0­•P«…[*¤P b/ ymžÉ&]…3_¨‡Â,—øˆÐ;Iß¾Çâ²åÈ3©ÂB¥±áÖæ€þ>»Ó*'Äí Zä «3)óL-í»Wủ^(‹uû&]•7Ö«mûzñD²¿wøö›PÆò&´///o =÷ÕÎ߅ʨÐ3¥î÷û-Òô )ÿÏ"Ýwî+ ™BMH%Ä ]£xÐyã™wx!‹Nßí¦ÛùVÞ¹²Üòc:¥4V‰<°iUh½°ºN³Ü7³ÞðÞ´qRÙ6, 3Þ{·\³b`ðr d÷…¾U™_åR‹D§A \TÙÔ{ÌF®`››zÅ]<“ò!w‡Ké°qª±sacEhY)ŠH(°±3»3³=½µY|vJiSÉÆ‡>Nl–#ø.Óòå»ÉŒ¤¦z©\ð'7w é—»˜u;ã-„.ÙË„Gµ“Uu)Ç‹ƒÅ­ª_ÒѪ»úü*mU(áêDUˆÀÿ^ i1ž5>¬»½0–*£ëâÏ;²ßf´ ôL#R1¨#˜®È‚äXÛÎy ¨BêõÛY#êA«‘#ùâ²·oÄÇ^ÒŒ®ÍÞuáSâ¤l¸Ã9ÖBǶð¨Á«žJÂ|yyy€/õç õƲï+ÔÃdßæ@;a+Ë]o&ÇÖúȈßÕ3ãâÜu߸¯ å¯†ç7ž9)°qÙi—j1kT\¤’¡û[uX¯ì÷%Mí4Iܶľ{Göú´ØÝï0q( æÏ !ùCM8%ûëÛ) Æ3[¹÷s i¬z•Ó*cÏ\Ö3Wõꜗw&æ‚z¨vçÏ q_ 뫤¹Ï.¾~±\Êý.}:Ývêá„æ"U×a}÷{½™ «Ò_å•kR»ÆÉΉ~gz3]°:!‹;CBˆf¾gÓªI߯a.µŸ(¶Ðùò”¶µyàÚ,ÑS¸pO¹žr9…KîTÞ¹/7Ê}åÄEßßûòŠÀ&ë…+8±{[<ÿ.W‡kâãZ+ÝX?âgÕçß^‘##±XXžkc Ÿ¾ ¾'ÂôuB¤ú”…ŒðªúÀ1’ð.<«„y%;åàÔdvç} ¥Å÷öÝ&Q&}—Ъd{6¡õ‘ùúõë´LYïÆÒòHTs©œ»U‹/qâ¢EU/)|Ÿ½½JžÊ꾪g…Óíâ²Ëw4—äĤÒÔv];÷ÅåwfCmʼnj§ï%뻯l:é‡V…$'uëêBmòì™qbSµ;ïA%BÓÊ¥J»sli-qÙ}Sÿ¡ l”ð~‘¶…Ž‰ÐØ=Öθ*…Þá¢*ÊÙʺŸ1ÿÑcg1ñ™ÏÌÎ]%„m:‰Ê¨Çj6œ èÍ´{n2¸5RUæ¶Ð3Ï”C!>…¦-9wêp©¾6ÙacdûÜB¡„‹GËבãÚ(_¹vM§Ës]<17–§ºü¨SNãÍb¹îöÒVˆøý-—[î̉ꨘ€yqcu½™¨žÈ‹—¶3knhþ#,¯PÖzSî=U, SR)ÊŽ»ßÖÍîLqŒ>|øŽ+±/½Îy‰€Û¨ ŽÕMXí”9ñ±8r0%œ¦’w GPBx]: ¨»@öïÙê¡ÏŒ®¿äŸþù ®³¤ll‡©J9U;s‹.×ÁÀ£éeÍDëÁ³î¤îMÂöù.Wñ±B€ŠIïDÅ ÀÄÃË´˜ôK–RÊɰ¯vXíˆèM BÓ’®%-^¾ŽFu/Ft‡û§Ÿ~zHˆwPÛ¯ïת’ç^…sºVØ»ÀLX«dG£—ç‚ û¼†š+¢×]¶ëµD¾ªd;³&Uïß¿x¶Â væé×½~I—ñÆ„X9T?/,ðêN;Ŭ_ˆÝm‹@/ß25bý3¡‚Iã9%˜Ê²•Š“Øtrm$ ÿÜ7š/éñçK˜·y`b¡L¾Þ »<÷¬KH×0ð¼nY_+MÚöyZ-d”{_|“\;ÜöŠT9:ûžEmì"nO« i¼µAè´L®§ïJÁÚ½•Ã2>c'2ŠÖXhøÞWÊ~»v~®±…¿¯ M%_²ÝNˆÕv‡‹õ±Qé¤Nº%‡ƒµU>YXJ¡e‹ÅÊ/ IܯT¾ñHä€|ï'ÆòP4ÅV€Ã3·ç³ÐÚ¾üÉIàÖRÄÉõÞÇ'Üzª j¡³6륢¤¹w´â#5±u¬¤¹|ì±–[¥`ÏâÍþ¾Mîå~—ùp"ýùB ¥z¥,›dka¡£Ñ«_þÒËËËÛÄeyu'2bE4Ž…žùŠlûî-€¯fær¡}÷åõl'/ y¹éòhGÇÕƒPéü‡)¨Ê^å‰\2¹ÂhœÈÔ+E¥žâá$‰“Ó.1ÈŽÅuAw½.ª +W •-„‚T*Wh˜Äåüñí…TŸ_HÄ”¡vgÕ¿é‚™u—K²´SæØùr!¯{½ß}IÕн#É»NöÝ–(í(!L‡‰Œ¸ìiÔ›Ôèccb!ŽÒW˜ÌÖFÞu,^__¿SË—]¥›iUåhqßn‹EäÚ½wGüÔjØ_D@/×¶_̺Дv{èë° gÒ&Ôcg¶ÞM6­óTDá˜Ûg ¶¶Ü`ïZcD6¼<•êöÌÚ¶ÎúþyŸMo¦íÝë·6;ï{îÂ%MöÅ›H SîÚØ‘ÝÚ®Q#÷J‰áB9ÖÅÓëÄxS•E§¤×$pŸ/[]<¿0y"6¼|kììå\Ñ™gdÿ}'‹ûÆr»ÃÛWóCsíl‚U‰ðâÐ\*Œ’oåVÒμÞLÛ—ò:lZäUyT嬚ÖóBx”œ¼úZ*»3ç„ÉFçb±¦‘û|ßO^ÜÎT¹žò‰ Æf¤Ýa…Ú¬¬xˆ?o¼0¹×/¤ãÞc— ­gn°¾ò<,’v÷wº®!¦ïÕ了ÞE¼Èål2=¯óU_wæ6Qy÷îÝ»OŸ>=À)ËíòÙ•›×ž¢ 9'2‹åK²!j¼2ÿQíμÕ{Â3gîÖ}åÚÙ\0¹ÿüùóC.êÚ•ç:n–oïð­Si õØ6g~e1!ÇfÜò "m)ä°|Â…[öýOÖ»š ‹7þïAšù™|¡£×u$ ‚#¬{ø¹IÑuùÙ%T#~¤lñþêû‹Ÿ+¸‹ªÆ†Ï`.ò@Z¹ªãèT7èb4/.„°<TƒäÖîÒw<(ȱ´ü Keè"ÚQüÇ?þñ€m^E­UŒ7]ÿ!áÂ\–ô8ù+´¬j.‘å*,)ÚUc~ÿÖFii1šrh®ÄÁ±ö’®:¸Ó¾ ¦~#{/îK¹’K²¼ŒP%¬÷çMº.L»²’õ¬Ð„Mÿ"›B=œF9’·à¬‡Î.ˆËõ×}åÄf¿Ë3wMxë²Îx1ëò<à[ì g®Ó,;È&ë[»‹¢‚^)+°ëë 0Ëþ[÷…œ= Üú¬ø·1ÖÖ`®J€>»ûª>2+òêke¨Gq×õ’ë º”÷T… ¶vªg6^]råqÔïì™w“ûB¼½Éº˜t%Óõôòž+ú’‚ÕÜØî­œ=ùEµ:R/9ïàr5—Œ¯˜^º}óïÿþïŠp"vëÁ³‰Íî®ëL¹/Œ'’¾¯x´AˆbùŒ*c9uØßypÁæ3—Ђ<åØõ‘‘€êå¸iÃÎ{IÙr¯*|Múô¬[¬òÖ. ùC* ^“6§¨íp*¼R†0´ä IDATs>•·Ë]}dœFYÜ/é*\a«ð¦q¯L,.‡õzzÙ<0±°Ð¹ŒXëë â›ü"¹6V6ýÞïê$O¥V6iÒó¢ÍDU½&wê=×x$÷JèXe½wWøìž9å›+=íD¦ mJ-QÚ{› É’.›•%´[0V}ªÒÕN1·ç-d¼Ç¼Ã;åè\дg’æmZ5á:æ؉ʒù= c%r€-rÚÙÞÄÄÎøa¶@DhçÌŸom#·dÿšV_æÆ{ïûû6j·6ÚW”[eÃLO®gM§=›ù ”õÙ«¤ùDûy‹ÀÒ ¼çl.ØxQÖ[…IUåÀŠŠPЧʣ6ÔäG—#|5„º6˜ÃKÙÐVÄ;Ü3hÓÈg¯R`yûƬ‡b¦šÏŽF+WÃÞnpy —èAŸƒéuи¸™7QYÜ‹—|ë‚.HÚÝ­4´òþóO?ýô 1ºñß.³Iìíûní wpd¾IÂÁ6ªÐ³š&Ù}6PƒªkïF«U{ñXX]‰~VÅ[Ûñ8 ’Å&Ô*Ñ‘ýàS• ­ yZ±×v’–pîBòb×YŶv¶‡M j,h·¦ð)åýgI× Rbõ.6#tmÐ홊tô+ž?oSõ(ÝÄ{æ,²VH­3»„T(Ygž>»Éø/¿üòvÆ¿}ûö&BQýýû^®õu°À×IÛi–Ýg9,7 ˜Té󌋰 B‚ùÖÆ÷ªÔ«M¥%´*®ÐÙû‘ä¾QeñR¬T­þC%6;ùù¶2ÿ…r˜Ôtâbü¹Œ™…GzOíLIÒörv'×AØñåÛ`³cEê u&N®R¯B ¯xÏ7nOù†r5‹I’£L®ÍJ÷¥k©ä¹´jwô«pÏò@,äLÀ%¤/éR²\˜Û’*‹¤E-$:11érí¶§…Æïç¿|ùò°v d æâ„Øg_é$@Ô…“ÂÂî¼ã×EWuUÕ²ËBÁ{Ìdy{¶ ;s³Ûú̬é´ßÿùóçžH×Nyçñ%˱©"\Í…¥8uy°IžùÓ,ÕêöûJ©ÐvÄü£Â)ûþóŠ3–ï](m­…Bm.Q›Ë§fÉþ¥lÚ;^x÷¥<*äP~vE²ðêpÂBDSjã…Ó)Ïœñd9˜¹ŸgÎüÊ}l<ÛÞ8}f–àê¥"|ÊêêçŸ~;´ X?eäÚ!-BŒè¥ÎP‰áJ¯2ñXPmFÅe«œUyBqÕ Àõ©b[qÓ ðj…KŽ³ã †ôR=Sg]ìqG»WGbAL¼ÿª^=n*‘'F& r¥`=ÕI7YïXú¿:‘ÙÚT-oï®ÃO§ŽâTA×_A½TJ 6‘¨§E/vGæú=ó³¾ÄhkÒŒ&B½<é/¡•”ì¤Oe/ÏÅö7“H‹ýgjx&Er\›’kåíû|üøñ!À¯@–Ô±´œºî×fð'…–ЪfWuªž);”rZ Pˆàê RM¨‡ûbÝg¥¥}6'2…ªjú¸ïççÿ›T¾g²xþJáKPµ!¶ÄBxÓÎÛš …+´1²„gœ=›Üooªzæô}ßç*}ïÆ3åÚËõ\ÒU̺wÍȵÞs^ä·ØÐ¤¶Â,6.*‡ºæ€>/…G]þBU-óûWDâºÃ÷7åÐüõ¯}‹õîD„GumÄóÛ¹vâân¼h¡QùeåÜ}vãŸÐ1§ç[[¹6ÅT»3áÕ+åoûÛ»ÿ÷ð‰©Œîâþeº‰Å¿¨MúTÇ,GÆ3'²@ž­¾WæOÞñ&ëÌW8çžÑ„VØž¼µÅ;k+ ®¼²Ð}9ymtæ="tl{aMrs3‘ 6É„—Ö>Â)éxªBQ#ÒZék{!ZDØhòj£WE¸«ÙpA-„.ߨ‹– ò@®f­;¾›ÌX…ÛÑÐTq—gáOÑm6áA«¬š—XÏRuL‰áÊ™šxÔ·Á̋ߑ½›Ù #u…Œ¸m“õ>›…P90quõu³µΰµ+°øØ¹ý~%ò.ŒkcÒÔµU³ANÙîvz9jÞç4Ê}±çiÂXhÙ.Gå—ÅTΡ½æ~B¿Š/¼J¨ˆØ`‹Àv/ܵ0•É*Ù襲g×ãFø“Ýšr¯Úéº\ÄÅUË[sß\îövÊì>ËͲӵ$·Ý ÷•r™xÿþýw˜s õ&Û•ü¬'†ƒ¬>1ë€*„àH¾nÒ“¦öLÖ^¥@ãÕÞ«òfûþÂÓ7±uÑXì´ËBÇ)⊠a.6Œg6F îÓÆÊîp¹SËêg¶¿Ý©B¹SB×½ãE¤Øüï¬öUmÝ÷S)ÐF®Ø :q!jì¬Èƒ¶R÷mËÚ¾ršT(ª°:ù„Þ3Æ+›òd·/--DäึªÉÙà×hU­ÓøzôXÈh>lþc‘å=ÖaéBœ«ç—ñ¦”ŒÂˆ«Šfá™öž3ïU®±|kg‘è¾8af“­Ï?øÓ^Ȱ—g;eVª;ˆ[DåÛAm—Ï )Y¿øÕvÙìŒ[¡ï…ìsMÄ´ïàyP…]#uƒœ£S½[ü|ÏV‚© £„±‘sÅ%7¡ìA¶¬„°òûyåŒÅšT-Aüé§Ÿ0ï[÷M/Ï’ášÐjŠ´ËoXê‰vv9.H˜Là%®«¤Í¥ $~Ö„÷â -«#ôOŸ>=8_×½þ2õœnßUj±Ùå(i»°:‹w;Ï BJžÛ,\aëT—pÏÜŠ²I/V£ÞnŽgÆIß:M'±³¶ Y£S§IK,F¶_P¶È"äåׯÊøû÷ïßà°½ „Ù([Y¸å“ωJÓª¸hyk&œ[;%óï=­©ep{~ð¨Õíéz¡8ÍÄG¥@¥ø•Â/ñÙB¥*BÂ!ŒÅúŽ©R B ½K¶¯,dÚ„×VÒ·&µ×™s_tß ›“« W‰­SP'°N9¯ ­òÍBg…’h"»˜èÏÛ°3!µÙéž—w¶}wIüîûÚTºÞ»ð*ï1'ÿN³„?­Y¹óRQl£W¿ŽÅ¡n"D”(M-äÑ„²&³6¼*…ßBB¹w s7¡¬Ú,w^AïŠz­(GocyÍF¥·w&mäVIP‘› ª’ 5Ñd¼\Pyc—avÚdÓzÈ›å?+]¯_½Vö¹y÷•ÌÛ€ZVnú8Äæ?—Ùy926#m¸}øðá»{¨JÅJ¤¯¦ðLØ4×ëMË—z$nÏìÝZôç3cÒ%ÎÒ@P¬àŸiØ/ñX"eW cmeäê+‰r‡¯Äßòoê½  ÊÛ0’s5MÚ†ýòåËÃâ Ï/ß £P‘úB4á­›ôeª$,®0¹û|ÅË­¾~÷]ŽÄG¢´R ¼ûf…”—…R+q\iH…ölvs£1HÛmqßH¨³“µº’›UòsµÀab¡Yh=/ö¼ãVU$¤¬d9¡!&6¯¯¯ok±j&º@±µYdvEڂނ侯D‡­…AhŠqÄ‹N ÅÀ[@ÿñÇï~þùç‡ÂæÿøÇƒ¦½òU@WõìR„Ûº¯Ð©yŸ1eÿ^O‹NTªôW¿“&'ÄÛ{7úÉ¡©Cû|'\ûoß¾=HÁV.U_‡Žô•®¾„$¼Kεø×LtñÌé¸Å{÷MeµëGfSkëµX¾ï%\s÷È’ˆñ‡¶§…ù×½Ÿ÷Ì+zc<Þ+f}¢:âõõÅRÜCYMjµ0PBX_«}w›rLX=Ó"%„ÕÙ³ax9´Ë‘¹ 3÷nöü+’¯æÂÞ­IUs*^¢aæbÈî)¥£-´P¸L#å Z/§oûnE«þA&ó hÔ^v!Ö»Ã×xPEq «Å¹ ý3örúvÊÓx&¦¤©íÖËkn“Âk ZÈ¢“ºK ð™Ï^•M…‡yv•4ׇfgvù‘ùˆÅ»EZEiôø1c½3«4¸ðnÑ>6üjÍ!GDAïøª0µ!ªCx·wüî±Å:¡c‹GÆ/§¨æüûï?þü à¶xcîh¬4oÞ=æZšCÔ¾â}‰=[p/g7£ä\G`âÙ¼÷EËuìÁX¦x¢r—θbýtL¶ëai‡µŠlWR¤–xÛ.OŠm+Ïš*í Jf³ (<«ð«×××ï’åÐׄx—È%¯¬†»¸î&åNÕBä*ò4+&`7ér¯ßȾ¾ Âòœ²¸¶B5: 4Ywš%®ºž*åïoÒ#ô¬Ý¢%*$ G¸Ô¥Vˆˆç/O¤ð)¥•_¶3_~‘˜t}fZ@_“@›ÅÛíSî„Ö èž]<º|c«äWÞšœ¾zTIÇ)©‰ƒñ¦’Ÿvº†i/÷Ê$ªê;SúÄHXíÄæâÕ…¼R±%mû¹Ô5”ÉUZ™]92Ú%¼WÞY.„¾Æâ€}va*G ÈãV³X,¡NÚNŒäM*V˜Ì¦eú®†©B´î­ áî)}f*y®¢ ‘KÆMšš–#£l¶œ½r¯ºöÊäzæ Û3™//M³Ð)w ‰t º©†ÉºëzÅyæ<³>u¿üÐ\›*¾•ðîT¡èK Ïi— i=¿¶ï4]\u*c¹Â-rd¡°Ð¨)¤pªí Ýí+Ï|MA/Ž‹h9Â[gm•,7VW,`÷Ü’ýBïUÌñ±}eÍxc“Ú}×VIs÷]Ûv¦ö®¤¸oDœ–W ìÚlí¦’X~´jv…Ë‘‘ëtÜ;^(kÍ‹FÙ´’ââyÃzz]þD§ÏLÖU`^»Ä^Äž:i+[¹$D÷ú*(51PËÏípêˆlÒµà[‡vͲÄ{¶Ï_=ì=»Æe5QSHÁƒ¶`dÇÂg·3^3P»)b‹/<¿ä0ÕbTÒ¹ü<êM ü`»€Ž /6¥=Èša©.%qÙ V¿Ž’åVœ«öbgÉÄ`ÒÒvÝ„¹TžÙ¤KL»p'»%…Ýírt2Ø©€có%ûB9‹Y—Ë R¡û]=“N‹ìºíLè‰a‘¨"[ ¦ƒw5H¶K'ö×3Qn–pNerY_­sý‡ê]`\žˆC;”õµz¦Äp»Ã;ó^–âñkö¹µ&sÁxíÒIÊ.Ôæ±ZX^}«$& ËÓ…¼˜s |KÚ6tºÞÄÃiU'…ÂM›n¶!·"Í)‹÷ÅÖÝ|Ü*;˜å>]NÜZ líY¬Œ÷”÷ŒêVB€lZy¦Ê3içûëׯß5µj3 »}›õ¥*ÞßBÆ"mûXa–¡&,šLÊÏ„,nßÊ£]ÒåÚ”_t‰TèÀ}c‘¦©µer—ëk¥§—<Õúx¦Jö/ŒØ{È{Nµw¼BN2®M t×qÒxí›*ž¹Þám6–‡¢äx…WJXÊZH¡…ŠÅ~ÉúÝ7ÊrëÁã³›ì{GT¬åµæè³{Úàï=T)üË'Æï¾ÿ .b¥Ü-Ï\E öÏ•Ê7Ë+eãò¡‘“÷TšùÛ·oïþõ¯=Œ3k^£™V»¿’é®êÏ©—«7Û¥T2¾ #aÝOôBË”´P29÷çüñLJ±sJí8x\¤î”‹-öâDh‡Ú„ÔªÚîí3äF£vªÄ´+­Xÿ¡JÍvü§ÄŸÉýäP-d”,¶*¯íÈÉ•fôÙ4œ*1YU2‹Dy ®ßmɸЋ_ýõáŒr¨'†£W94Ýw•ì,÷ªøY;ë&MÕïïåX6‹ïíyÇÈr`ÄÓ÷Ì41ؾZâ!Ð `PU¡U/OåN…¦Ù9Wha£%‰jnm„ùrx%ËìzÔ„v{^¬ð”µl¼©«¼µµ”_4Þ›IXßM§ &5ØZv™:z¦œÔý™ç—ÏÞB¦2¹Å´/”Ñ5±Øž”ÏX8¨P6fœäyu¬Á¯Ð2ï–Yò\w¡c—wÒ’õ6Ì,X—0.yÐÓëê ÛS*¿|€òd«ÌåôܤD RmTÑMÎÝÌ¿~ýúнº¾=ì=´÷~‡•ݶ ¼ i¹Sî['<&”k.Ôø¹™ËDÖ)¥†â’¶m u,¤ÐdÚ|¤û¦þBõ;ŠZŸ½?þøãݧOŸä´kCP™^›¢&œjø.›Û¾1™·¡öÌ”ñòº Ð…kzf¼}V92ŠÔ&@þQygEU”FþSÐM\ÖWíîâ‚QÒÆË«+¥ ìyT¬¯Þ KùÕ6jg[R{ ãßàãОY›Šz:™tL¹âªƒ÷ :š]7§Øc;ïò<4̴б”xìTÁ©C;ã—§…Î-âtHc/ϽP'.K,$t b÷h0cºGŒœ3®°5¡o“ÐSÖQe ;¬•/ֳ±q [ /x9ÚÉ’[åÏkĪVøÖ¦Òzøè™á4ʪ^õ©]ŽUls¬\'î?ƒ+èB^O ‹8»x^Žb@«>%ÓBDÂü3¥å¡Û)“xh'ΉÍöÐ1»ËûÛN³Jnõb¶PQIG>Ðü:B¡ØžT®½ÄçIƒ`½Äk7¨žpÒÅ“ý>§avX•‚­úTR¹PN§Mz$ûw‚ëôÛxÓBC¿÷Eõý…ªN†·*CõqÂìÚêùuuÊT—²3/K;(?ܼنݚ.Z¸¯„c^¨†N)ë3£ÀuUq‰týóŸÿ|àì-ïÝZØœ°ÐñL~ç3£é’¦¾»Ã3i4·Zñlb@ëÞ:,öGšV®‚˜ëý¼õ¥Bt©µòSÇ\¢r5à= »€¼ LÊÄÏJÈòrS¦Î©ÁFîëhìò°*W:{Af ier»™;í2.Áo¿ü…ž]0Ôà ¸Ä@œ¤¼¡ ß¾};Gê&S§¯¯Y–™K~pA ˜u»p‰UÉß_ij9.Êr^`•⪕ü´È+÷ª0;óuÚ®tã¾ë¤­/¸ƒ‰‡ïµA²AH(ë…=¶v¸rð…UýJ8+ë½3ùÌ©»ÞªÅ–çç•åv_ØÅSÒS<½É¾ûÆé·Ÿ³î´ªÓ®ÅU…r¨µ}YoƒkmŒµ‹gþ¼Ò×&óv0›t]È&G>›ê˜›à.Þ»³ˆt_-±ñÌêº;­0%ˆw7Õ)»ñJB»~UúóÌ8vâóL!ér`/wê‚sZ&LØ{ÎI J6Zè¨0¹äw±¾Špû]Èèä¿>yBœ›pjhYcÂ} ~¯dÜλ±¶þD…ÖWs?oŽ"4kcó@E7Õ1o*Û½ß'g®É´gR â«I}M€kˆÙ}S{ŠñÒO„S*Ü2~ÐU$ækSªê®}áá—Ü»kS^Z‘L7òZV¤‹åï8Í*Wˆ³Èƒ Ž©zg…Uüî]Úžˆ4#Ú"r÷Ìe±PcçqÀ-òêQè¾ùn2Ó©B1éõJYÅ}‘(ûª%.¶ØŽƒnÑûùu¢ bn690KHMæ›pz¨uaÄš8=ž%!^˜Ð±NTÂÙA¼6«S‡­WÛöÝ÷ïZÄ [¹Ô}WÇÊ®½R³WçÛÄÄÿ)¡·ÃX÷úý-;mû{‘ÉèúølNy;zõâ×èk£Q¥•f¬äf5æ%}›ÔøìÄB9$€î¸dÜu}¶¯v¦œfIê®Tì΄åJG$¬†üåÁc‘h'[ÙK§”•Ùµ€¿ ê c¹Ì´vyÊ]2ir’·÷¦çEÈvyŠi÷ï× »BÆ‹z?Yzù›Z JxWEQN^ vŤwR'Äîð3_+98BYëòm²/ÏD%ÏL“õ*0yfºo„–8ñqš´Ëuk#·Ê¤ª2ºvÎuÒ¾<+„ ¯Y¸3·}còìDEñ‘}¿?žjxNÇËõìÙ„¶æÅrdLæ7ÅTýÉ3µ=©T¾xüÂ\$ó—DZ}¹gÛ®…BygBÓäÙ˜qêXÈ¡ñb"9|Å6ôqiÃN Md÷ݼçl˜Õ´QpÕ…–;U´âkª¡ßÇîÁúÌȹ‘Pï„WØ¡wp“i§ã›rzÏ”e¬VT¦÷ ùQ¡kÝwÛ÷Þñ—E‚E–ªcþ}+òÒ**£'X¥©-âj*?Ú}ç$n9€÷ÂÄžùÀ8ÜxyyyÈ›÷óÆn'5½VQ®|H›FžáæGÞN”Dn<3•:ó…©ê±n„ˆø^Mݬl›tí…ì²±2ܳÿßÊRh–r„?]°aÒ÷û¾|ùò¤ÒÕu<ÞA®"Ü5>\â1^(*(-aµH,Dìq;MuÚîåUœäðøƒÍ‰-!~ùe浩‚¢$K7bÕìär´‹·k/“&»ÃBwÄß®£±DKïÊ™.±°PºMf•Vܾô2Ýå¹µö×i;ûî+“¶í»É/_Ô6ä¼I‚t”7¦7AñþH÷û‡»’èZ‹¿­wÓö¥|“õ +éYÅ6‹]5"[´Äd㉬q ðåô=ƒ,Jhbtí›ýŽñL„Sˆ»Jµîñâí&ÀšÔV=j—ó’–Pk0gÑ5§ÛÂ3å)e¯gÆbÁøGª2×} »xf¼vUéïõõõ!ñX3iê%úJw«zfÂ(qxë(×Aˆ³gÀd¾ð)cõ%¯,LWyf‹@;¤•åÖÜÏÄB5»"ôÜZ2oq^/÷eMËQAò‚}ùòåÁôñÇk •wïÞ½ûôéÓC¼{nÿεµ3¯Œîî…Þcõ©ÇÎÌÎà X§I"ì|[÷ž²ø/Ö;yPÖÝkV.¶ºïvæl~îÙU¬­,øþÛÅbzJ–ïÝ:ö|Ûèu jþ`#؆ÚâÞ&-`ùå—ȵgF咽¹‘­½Ð³+ß_‘¦“{›Økf.o´q"VDˆÛµõÈðñŽ7"}Yº(ß¼†ÏnÞ].§œ¼¢&œèxÆÏb¦Zâ—Tš¦Jâå^__ß°ÇV–à ·;íˆÍÎ»ê ¢»<ªl±d~X^‡]Â-˜/¨¸ìºÓw$/VP|í’PuÚ_^^ð¹U4QÙ«#ÿ*8){©ô£~! ’K&s) ³p„’ñ÷ý{M<$]ÛñÐkELûð±&Ûv(‹£¬‘˜ ­ïýRdÙ"Ð}g§l—ãþ]¾îY±ÁN-zùê½"\sSƒâ®…ÁÈÙDÆ¢TrnùIB×^^^¾#QÊªšž‰…g¦>-ÊèZ(ØUháÙ4Ëgï°w» f{sɼûê2ÿ»’yá[>ß³.áÖÎé>W`ÃB©j0‹7• wßo_‰òÝ7•Ã+‡ª‚äâù½W=½i´±2r²²˜•ÑuÊiÓJ$ñðå2ˆA¿8{ú•¹/l¨Iö·osÂ}á™ÔØyï}E³¸o¡kNQ½§œøhŽWu)>‹»ÃN)M–MLüg hï‘‹{UÉóB|._+§a-µXu!1y“ÆK  ¢6•å6Ð;I‡w ív¶m¬¨zyì¨d(ÁÏ5nn±`w¹†™ÂòŒG&ã‹Õ"Nlعoœ¢ö»W²|ñÊÆJy®v¾[ÄÙô.‡Ehš\ÏQJ06ÿQÙ«F­UïTœã­@ÿŸò‡öÝj;bh~¢_šÍ„Šd y”³çtÞ¦Ô36<³2Á3k¼Ù¾ÑZC©èÐÞá[ó‰5Í®pÊžÛaûlB N9åÍ«w‡Ûø)·Ü@#úÁ=¿ó™YÇ©:è-dJL.ÜÀbA‰½½¯_¿>à¦5Y»¸Á½Íûª ¢ÎºÉpGhNäØxy5)+Fó½gQ ùòƒ”èû3ôuÖ½<«ˆRöýþ÷–éfßﯪGá[5IÛ:{9IT, R iý‡Ä Vzºü"ñúõR)DÈd}ë±±µ]>'oõ™ÑD­²“NLLŠ)÷Lt_x9^¸êò8êë°î¯I“ŽËå~ Ï&S¸Á%A,ÜÁ¤LŠb‹õû@j²îäÐxsq!Ô /Æâ^úí›òƒŒ7›˜(q)Æ •ÓNS•÷™fB5ì„_ž_&uWâ!¿àò첃ºË½ž®íÿÆ…°ÆR%åV]‰Çni÷Ö¦Îö|JgÞKrhÚ©oU90Þ3z‹\Ð-ŸýÿøÇThÚbŒR²rò …U…HE¤9!—U—º¸ WÃÎ"ï:;%Ä{Ð¦Ô »Ãå´9 ×óºç,¢ê5ç”ÔfeUÍŒ7G+dœä]÷˜¼4wfw-)s_ËÉk¬­¬wÏTÖg¾_×™ IDAT¾ò‡úlN“Ìý̼ÇêåV²¾ùÞk_Èq©ÁîÄIœèÈ!îž÷^Y³Ò ñ%¯\Å7‹À­…Ðw'åÁÖgoÿ½ks þìÌx¯Z„nߘ÷Šª0oÝDÄi•ðo= Ííš7·YYU4‹²ú¡-Þ˜¿U±­5Å3!§7ÌŸäGŸjf{¹û! Ö½.©ÛÄË©wI’ÕúV]Ê‘ö.±ÅÂTg>Vr«¸ïºú~üøñáYkøTŒ©£[ÇÞK/½lÇÊ}¡ëàî…\ÒËìSˆ¸èŽNÅꊃ¬¢É~~‰EùCBŒ £YÀ/Y®0=vÜWK,šl»ï$ßú^ÝÌ&MxŸýßþíßÞýúë¯k»gŸzJ÷MayÊ/«B$$ ‰ƒ J&U…ÝIÊ^€v¢ÓÏdö÷j0·ËMõ¦ú½¼¼¼ï¼–”yl,­2W v…ª:¥ÔcÇnL}­:5PE˜Š…ŠÉ¶ë&ëå Ï¿=½xcÂY¸¦ª‡òLj»µvâÈþÒ߯”¬#÷gNÚ+ø¶/Œo>ÛehÙ¤LXÝ%pá{´™T½„ÐIrîçå­³î>\,–O`|±Ë§GÏb˜žv/IO¹ z7mÅëw* Ü5Uè¾RX yeu¯¯’ŸA=„ÙÈÍÚ¾˜hÂé¾)áý2à2.Üù[¡a- ø?ÿó?šN¿KVççNζ/ªººx$ßQ˜‹I™l›R•‹_³qgÞæ€§³¸|ýúõm/8áµ3î¤Í;^žHÕ9å¹ ñQR‹†M‹[B[.‚°àB¨-dʪY© ’»m¨•Ìo²}ñ8ÚxiþR)|E VH8íºÌÒûóåW»¶î+sGù–æ7r=«’Xe®5ð-â.>£ökÙ¨Ý;Rqûf÷ýµ»¿¥>^ÿE4.ºŠf'Dªñ•×V¥ã5U]<;afâ²U—-Át›No órTÆð0¬‹·Ï7"3Ù÷çŸ]üåaì% Áq³ê°î…±¤kßOŶêï¿ÿþÍgFò®ãAá~¿U¯vw/ƒ:•·õØ»XÂf2섥ƅ…#˜V^yPßE9._¾|y(œ†Ÿ­¼³—bâ§NcGÄwSý}7»˜u»|»@ÄA—XlBi¡R"_åN ðŽZ?}úôPT>Ûw{÷úHhw*" f H4>¸æ•˜Ì+¥pË’o×U[·fßM/•H‡UñÍNÖš. ¸/õð1±éTbñæÛ·oo §PŽÁ* ±ó¦,¥pÍ=›p5T ¬[´…Ì ½«Êä~þüù Ò¤Í3¹‘}áSبò–Í›J;a®*o«d!5Nêj«Tþ —uƒ6\¶Òáªåô)I¼d{ïÓ3g¼ûà×_}ØN /E8“q»ˆÏD l|TaigJ(«pÌíù&ŠÚx-Yï™+$qïrkW‘‰Å¯MpåRÈÙÔAÉöÅíšÌÚyߺ*2Qˆ³ÍÊš66_‘'$¨Ðxy®‹'Kðô/rÊé¿ÏCªŒÓ|µ+hÚ]Þ{Y±³wm<²Ú™¹ÌD7±©!w¡ªBYmvzÆ–ß”Cì=&dQhý¦¤k|l’·µXãÅ}'²@þ[ 3ml IyभÜ)­5v—‰ÆYîf{¹]}òäF ÏVµµÂ+6;åÀ8w8Ió"„x[ÄU„bñFï&aÿVdÕ;IhØÞ‘y÷î`'o{v6ÁlÄ ×ÜïûøñãƒBq)ªg%f.ò;eÂ`V¨”ìæèT¢bGlbÒ%ÄëŽZžÊ ¤}áUŽuP·åˆÌ.žÉ›yH ¾p7ç‚Øþ]}jVÈ{¼ `R2¿Éúån¿ÊsäÖÎd]ø”P §ì^{AT~Ù„Ñ‰Š—§Øãâ¶÷ì*$Yïû­›4|í`bI§+b."‹Ä%´J_«À4"¡Añ³:×.È8fv& F8¥ï}äZ;ïë„í ›W•ã’ ]òY±Ïì C;÷ãJ(»YxU»ÃU·2h§¬&iUd“<ëDg{z. ë[;»ˆØ# îy…j8öö«÷bÂäÎÍ’ %ž‰àéÇRÓFÍ>;‘–·nºØb»€È*gÙ]žç—PÏí+»€*é,9nºs´X,ÈÂdÑö­¸ì »ö{l|T·™ñÊì»çÛ%45±º¦òOcµ²Ý•Ñýí·ßº B|”žö̹ç6]ßey7mO»v‹1‹Öå8%U @þ‚;õvªÚÞî¹}'§ÛU!ª"œSÒ¡6ôã±@Þ¾³ù`jmþa·Öï¾Xo^°æ„±Ø$pk·XÃðÈ6ôvW·¨2˜‚>*Â92©úÚ¦ÔŠHN ÜÞ Ÿ27Û{ñÒÏ Ir`ûhw|‹ c¹ù—ùœ½}>ZÂÞ«w¼ˆcñìö^ÌG4™µQëï·™ ±Å¿E`%†åÜéaè]±¼´}×Þ%r9mh: XŽ3Q#UP‹Í+-²«¾ùÏþó¡ieÃl…ˆˆŸm¹]!ÒõôLÚ(.Rø¹ûæ;Ÿ7‹›Ñ’«0<[ƒ˜òÌ&UÅ Ϫtã¤d;bs»‰C“"qÛ«öìN»TŸZ7ÆÏÅœW"رõåÍÔ©cåj/C)•¿.ùfåL-€+í¸}±½²}·õrí*ëíÚVÚÑnŽÍr¯ll8u°{íH¸(ƒ¤PW¥j/e-ã‘\»Måä îÐ3µ=Ü©„‰Ç…Y_ÒÔ÷êtÚ÷nâÑ«EX!‹rŠËVºÙx´„Sbq•r*=}Éìníëe¢ªû¦pÏ•½Ö0k,–{å=²x´çÙ³o¹vÆ«ËÈWÈåÀnW^߆y…ŽÉ +ŸÑµ½ää+=mí²ÝÏ|Š ðs;œmJÕËD}`êS>âǼ¼T*³«Tìž}ñßX©ò—ñª*Šû[‹ÅN„…$úyÏl%É…žíûÚØÐ Î}%vÓ*ï‘r5å™x¦\[÷ùг§ûy-,ºÌo ºr;‹0?_þ£JãÎŒÐ3§˜B¸Ì‹¡j,ü¼„÷k*qM9Åj²ñ"t^Ñ™ò 9\,Ö÷ª†ßûÜ;Xî•?o¼ÒÖ¤PWQµö(×sk¿Ÿ©*lUYË?êDEn–`ášõS«œûu¦¾ƒ™IS~PB—„ô]N5Ä´"ÞA·)!k0+;»=b‡µ ö…)õÚ YÂú3yf?·Ë·dFYÌuPk ¤sížo “¢}^9ÔÊ ï¿ (aËÑ«U­Ó¡V+[?ÊgŠ&vš.·é­º™…;HhïÚØý¨jF'q»”Wvg2n¡²½fG@þОńõ‡~xë«ê!„ÑgU„쬋Ÿ5á\‘§áåžMÉÏuù¶o¤ºo¶¶KZfn;ˆOɱ=“v¦ô¼»%æ}KÌúÞW§œ:N³œÂ§4Ì”$¹µ©aå. u±®æ€¤n“²JGï»/àNÒ¼pM»€^¶z/í³ûë™ÝÏïb6gçßw½xR—t}fö»7r§lØeºuÁ9%¤«èf¬5Þ úµâÄIÞ88Ö­@îDf‚ñF‡uãY; 6Nô¤0!m<*—aEZ?ãy¯Üéâ…kçt[¨¬E ²:u?‹Åè0oâ°w¿}W˜Kerõ•3iqb¢º¦I2ü‹6_^^Þ ÎT a pÅJl†Šzæ[?!Fåzo³õ袬àŽû¦æÅzׯ÷*<ÊÜçÏŸ„ ä'U¾ùÛ·oßI¢_Ó.“ûÞáËoäzn-fx陳©òÖr#áÝqh3²Ü's¿ßÿý;hý èùJO{Ç˃Ýû}&°&¢S‰¾»=Ÿk§Í26­žå~6´,Tê½t5ôÜÏ{f4¡ÝÄVëó/‹D!UÝ=cÀ¼[ÃÚ4–W–û;˜™¤¦«»lÕnàQ‰§þ*c8þ³Ãj¡cU½ËUœ¤PŒág…±©®Ð±î¾Û̓”ÌF`Kn×I¶$™N¸Â‚ºêXƒ;ì0»Y×Þ _'Ì._ñ³‘«‘ ú—¿üåÝçÏŸ bz™ä*ϼVžðÇ|‚ÃQj”($q£UÃ6»y¡eªS©A¯ì¶åë”Ý‘¼jsëhÔØÐ}¤»’ä&uv£ëûPM‹È]ŽKF%.ï ;%Q"XváQN{–ÜÊis¤¿ýæXwgfS}×OŸ>=èÏŸ??tsöÞ·ï…Å)ëíXYž›Ð²â¶íN+ aWÓ"wû®å’Ryivж?5È&"é{PÓ½§v ‡ßçب¸ˆ‰ƒ m•-j陽&î)UË Û[L“ØÛ¹fžƒ¦•G"1xë¡’_—çùÕâ_HD;ó›Ðȵ\¼•,\Yî¹%då ·hû¶ K»gö߃©ÿP}*«½"¯~!•>|xhüØ<DZˆ¤`b¡aB«Bd²3µµvŠYu) !eÃMæ…Ù:éÛ{Ý-H^špÌŠh~l1PÑšrúì>k^lÒ¨‚¥Í %–U]Õƒ¯ïÅ"nk;%XïD‹¬ÿB|vÇ.¶@®yq…Y܃šoA~5z@]¦‘>Éþ&Ämˆ‘WQÅÚʱW Ã¦Ô~¿0½¹rÇw[(m:ï¾uíl’;%Ý™]ÌiÐi˜ü¡ E²þLñú\¨ªÓò5+÷ûç¿hþ£êYQ½§lÔêS³fŒPWó7Qûo÷sƒÊù¿÷Ö ’Âܬ~ÞZQ.·èbÞ•ÑUfWÕŽ ñ­ / K*žˆ›¶û[Ë‚²>/BÃ,DÄ cQa…[¡i…»»àSºkŠTX]¥\uoö&äÏ"M<ýN»Çûy•4±À5qq&tíõõõ!±Ø¾XºυzHÚÞå"îZ#2“Y¥M,ÜWílï ;…C#”CÏŠJÅÊCió`äÚuη/FxŸ'†Ó¨k*!îúòB)bû®’æK`zÞ÷÷ Š&ãBÐ'¦0%9M¦ù—££gÅÖÆ‘|‰‚vs¶/önÖtÑ N÷ý¼Y…Ç9 hGúŸŒ'ÂðÄ]k0W7ha2r§„Žù^‹yog}ñJ)XÕd*ß„ÔIà §ïž)ã•xy› bÒå2´afòîÏ—?Ô†Ü>/Ch®gÆÄÂXìtÜ33˜°Á6䄞U±Í{°Äᚺ¯$.«"ä¾P°çä)i{¿_‹“ya{¾Û5°*÷^•E MºTǬô´“ÀŠ8è%×3SÃË*6¿¢Séé ^.)܆œ~(ûÿwÏ q^¼Y<n©zÕ:ßNò<3•{WÖ»ðpy Û§%ë²=%W³SÎÊvïÞÞïßÚY+Ã[©|ÅŒÜK´Uú[<]²-êÂIÛeQ£x…©V$ÖÓKï&)Bó}oNIêÖËnk¿V‘‹*ÞV€cù‘gJ)|‘ Š{V×3SX^Í@÷®Í-m´š–vÐXkîWŽïrèF¬1‘páUHªŽz%= b«[¨ø¥‡«–[Ü´ "ŽÀj(¥*™Äe»+½\«\Ñ*Ì¥Þ&&®:ê:eWʵO1ëâ—L”Ë '†˜öBÏ “Q9 BC)!‡&¬v ä™xlîç5Q«F½F©åˆIÿÇ?þñ@v+FTHáû÷ï&*Êÿ g¸¤­/±€ÜÙÅs澱˧ì¥ûÒ©òÍ•'\ç[IðqZ@Û.¿§êQíl_kc÷Ù±õömÇÖ&]5»2é³ðšG“iI’&ûv)—P® V·) …Nå“…\úû;‹Ÿù¬û»ï½}Ñ/CN]½™œ6™4éC#æü’ô¼ ei&¼N¯Udslrì{ßÚÉYQæ¶½_¿~}èÎÖA]8¦Ó²KºZYîN .œñÆL~ûí·‡„õâìU~ÙÏ×y®Nc¹ûÆ&Ò  ži‹68äy˜ì_˜s d›R›pk¼,©»ž^ƒ•·À•ÃbÂX¬ñb÷\áœN<äôž^Ò·ì…{Ö4òJæÛÌQRÈž]ÔÀî©×××·Fì3ãæ%Û[/!@k6VvÛ;³Ð±JëŽ Ïr²W1-”õv2àdÒxeç¾|R>ãžMˆQ=¿Œåž9憃 /¼ c0â\Ãp×ZŽÒ‡ÆÙÝᙫçWïxŸMk Õåêõ6¤OýÎÌ»7kv–{Õ{®„æž±òÒê[%Õâ_U2Ï”÷M§Mk´¨JâwÒÌ[˜uH5Url-Ä©…]:%„•Û[¡£ßF“ñb½@tO-„ÇĤNÛ’Â šUݨŠT§U5˜«‰‡P •vá¶Ù„j SgZ•µ\›ËðòÒ/n{ÃrWÄ]?“µt­ íÆ\ܪ]þbª–çå¸.…Œ k;{öí•©n¸¯šÐj¤Z‰`/ ñ»Û{J¯[tuí ºMìâmíì®Þ÷Ùåicb*AÅ=ëyQþNáú6¨·±³#}a,vñ–¸ìÙ„Š¬+«ú”ÞM*®hl¸3'ÂËSÞÙ~÷ηñ¨¼2 e/•’ݳùó&[›½×Ÿ~úéÆk².‡f?#ôÌiÔöº†™uPwª°¦‘¼%YÖ»@!„MhK®:Tášw~øðáÁŸÌÄâþçÞýë_ÿzÀq;ê¾ÜAXßî ï’š°™°öL úí·ßÞ.W¡BAÞìžÛ߯ ®¾òÈð¿/SŽM=xönEÈ/²ƒ*'Ï$Î;¾Ó¨Å£âùöØÝuÒW/¹r1…’n¯ù^ë/TáÊÂ\T€”¯4HââEa¾6­šÿ˜Ø|°³¾üÁBg÷éÞÅÕTªÌ­J’—¢2WóŸ®ûJ?MjõÅ’Ýx´®^›VÞC6z›ÿŒ¿iñÞd¾&µ~÷ŃIÙ¯!°XzY$Ë…žy§ i´,·\1­&*’µ¼Ù\ÕÜQ¸åZ»s×°ºÌ@¯X=,ïäüjkòûï¿¿åGî»Ý­ãV ÷VÍWˆô`¨—Zž›àk¬ÔŸh¹f'6–83{Ž­wÁUO{Ab:ß.(™”­êÖ¨LÅ“-\]}G¤÷òZ ]€_¢ÒÄÁ„Ö Â‘»Ïj!´"!~ãÁ}ϪɨXbU¿µi¡#Ü`‰É³êSŽç ÀÂ=. <‹6%A‹s\¡"±odOGò5ÓZâ5Í~¦^*N-”'” j—Ði–J6ªÑ- ´Q´ce1¦[ûz´ÔœïâÀ,ˆ*„° ¶}gÐ\-?iÝc#'vsö»“±SäTC|ì>åN·v#ú:–Þ™s­Äönm„?(½¸}³==>÷Å?üðÆíÒ,´^*^0ÊVªÏoº}pjÚXÙ¾q¤ïï–?d¡d!â™X¼êÚ„V.—pÐ6vÖœ°pë™–Ç¢,wMÚ,„Üwë.»o4”3QÅÅ¢}? ™ßÿý´­/–ÅÆ›Ë›ÉÄ¡ž^óÅÒàN¾R=3T"\b¥'Æžc—¹u§…ü ‘Þïöâ׸°±z{a\Ðí…%¬5ÿÛûÑïl͇JWÛhÙÚ{‡×æ”° væûì*—>›OÃ$Îf§0áM”µÉtyk&¬Æ¿M˜å‚î]lÊÚîp- ­—"ŒyB …Å™™XœÿñÇï~úé§7î€ùO 7-"u«ß³mŸk#09w½VläÊùÛ;×ÂÁI ñr{FÆ#º¶Í½voˆšX^Z^š¾4åN¹ïj°;ZÃâ½=S§äSnß[`krkŽðÌŸqñFŸ=i Ë›åO›»-ïÞpB˜œ{RØÿuOýñÇo¾VÆbó)ýmfVDˆÞÞÕäàUçôŽßÄf¿OuÎÝWßMf.Ÿ˜Ž‰4ª\©øY¡_ÛüÛÌNŠƒÔÊ„UIOÇLqÕ”±$G+C¡JÁštiâ¹d{IQ}b䙸lƒzì Y9Uå‘Gnª»«ã?•-LÈ„®-p^Ê^–»ì8XØ\Ð1;œUšP‚Ü*»»ü–PÚŸ:Õ.ÒA„ö·LÖu nGC¨Ç%?hÒc·Ø)ã38‚É÷¸UK,”Ñ[}]ÆõØñ‚°@Þ$N8¨ÒÒ—¤h¥«°šxxy^ÒŒõ}Ro&=0ê&]˜‹ûj˜t'&¼•CÕe¼:+„ uÒ(gÏ.¡±P¥ã‰G»ÇŠØô‘?¤ÝžÇi™‰¸½§:iË;“b¼*BL»J:5-ôÌgßÏ»/š”91ñÌhh)ŒWŸ—«»¼xS){aw;ÓKT ësÊ©øH¡®•íV¾y±|gÒBG(ˆw¨Ê^6Ùç&„NlzùÞ½‡–˜ÔÏÌÖæðªÅW9:åj–[UTE¹¢~®êÙÞ³ü¡íy R¥ú6UlHèYe·MÚVÈÔf`w¼0ßÉ}_¹Syõ’“_d¼))»Ï&äϤmñxŽ9†“Âgž_å*«]á”ý·rd„O•ç¡‘ b•(–[~“wx!‡æ~&ón^ZBKNþ-œª YôŽ®åÅ=¿8wÞcפ¯\ÕòäÈ,?j~³}åÚ¨rhQÖ{LÈâΔMw |71êw¿L«÷}üýr«®üGÈbùˆ+`]Û÷’L}Ùä/‘«{“q»)ŽÐ¼\ÛyßhÖñ£Ýáu†ÙÝøp]3/š9bSÅǪXø“°%ö.<ÿŠ´ýn/·vcì8TŸÝW7‡qÕbÖ«pTXÝ•tÎ ÏÃÑmý@œÄ•¼ëAܰ)–„s‹Hƒ¨˜tM$Ïú%f}nÏi’ýÛ ³«¯Äð¥£^Õ0!F•õ.ѯÄgGî+:åÀiv·¿ïæXÙzEœk'îzp§M¹rhä^ï/·Ê N|¹UÊ~/1Øß²1²â^îÔEHßå8r­0GòÏ ÷\ˆ =kñ¯¬·ž­­Œ´“B§˜B9œ4®éå¼"Î3%'O¿‹¬_ÙË&¬‹7ºE_R´B]íÖn ú *ëåWñÖ=ÏöM ‘vñÊK“sç=¤×É֮ɸâ#Öß/h ¯ñJ¯“ÊÁ7Ö¯¹ÐxTh™ïúrÒg—æÁr!vf,MNµXè”Ñ„ÔÄDˆáÅrJQ±€Åb•ÃäȬs¾kϜꠕ¦VHASGj¥1Þzï4ÈiÕŠõí«B»LÖmô*uïÚì\O oRHÁ†œâ"&û+º„SôÕjcd“}׺ÓK˜ÕPŸ÷M¹œÿçº *m]KóŸò8*䤒®¹_Mf—ûÙÈm³Òi´”‹ÅÅE6ÝV.ÞF¯ÏþíÛ·75»Ý¹Ê/—w&×Ó¼¼Þ‰r=×s@p‰âü‘##,ï;˜™p ƒ Êu`¯jY'6 b›Ô¸§˜s«je%í„é.Žr/x^*^0êmï…Ù­qªáÈ]©Y+k§’ž–¬ïe‰ÉÒQ¨nÑ®ö·×yßz6©Ü ÄäJèí=Vñ­^)•¾®¯ƒ ­—çęô^á v åÀxyçìÅ_L¹P åPMÖ—pîç7:Ý÷¹œ° ð $v…y¹J4„Å©Æ.€%FÝ7H0]V‚©É¸SR]Â5™rXKõó•Dßåm¡Ss?÷EžŠ+®mÜ+À±µÖZ#³Ä-a´s.¼ª\¡®íž×‰M~pEX‘©Dºû²Ê\v8·6UË«¼òö”ɾx|¾­û„.sâÊäêU²ŸWlà—_~yÛ—ƒÉ(•_b²Í…Á€EØ\·æt¾2¹B -d„¨TUl 7“íÐ…¢Ê÷3–ïyvf„Á1œ¼ò~~ñÈ"Ò¿'æ}kkgÝ ³r§v÷ÿoíÚ|âbñ¾"ÇÆËþ[c­jy%´»ç•G®¯Â=ÿ/¿üòÐ$òç5™Ý^>UQœÁþ”ùÞyßýå„xu›‘òÆä®‘»d~w¬o¡¢Ûª×-–ï¿1Ö:¦(„þGröõ‘QL©¢5ÛGZN +¯¼Xm|¾þ¬¼Â£ŠhQ(ACK ëšKØï¨P ïrîº/4j^ŽP!(eÃ˯‚í™é¤Úwô¥,j3So#E¤OÖHÞô}÷ï>·#¼}Yn¹ÿ¼3õ í£U'u»+Ê‘Qár¼3mK:±yÊ™©C»\ÊZÖi»ãKÍv4öò ïKmsMân—ï:˜vc–tí’i·G|«]D=t$mî‚Ø –ð5¬¡#0¿Av/Mq!BÊèvä¯IÛþÖ6¬ßu]¹Ò½3 1ï&×%líÙ ’v@öì[ï­\ “²%mr¯Jv«sî~Þ‘ÿ¾“2ÂÅm¯{ìÚ)Dàè´&°&r jx=x\›š…ê#Qðõõõ ó®¬÷~V¯•&¬»XwAèÝdq½÷äU̹…çU§lÕ^¼\vÁ;åâ…´ùòB©H„ûÊ}¡:ÍÆÎþ|»|ŽüävM¦•[µ;«»üâÕÕÅS Ç.ÂÂHï“ù=ûÎÌžGˆ<ŽªÁõÐi»0˜KJñjÝgcy•¹œlì½­XPLºï]<ÿ%ò`ìåY…%/gn—z•Ó±r)vf…;,éóL©Nåw«bܦô~.æ’Ä_U åY îžÚïØ¾Ñ÷Ê{ïÇð$IÝ3øuß F¤Ý¯F IDAT#„È{¬xÿÞSK<œ‚š°­qÒ33hŒ…‰Dcµ“8s”q£ê·Ÿ7kgfñb1ÂX¿â÷êîøKúzÏ® S‹Š“ìn³û<®ƒE˜ðòË^BH³÷„¢3‹O_¾|ù®Ùi¾¥ì¶pL•²ê öúúúv¦únœþkÑ jcÏ3ˆµÜªñò,€˜xg¯È«ÿa=pôÜòž3ÖN$B®”PÕí;§œûýû—S¡Å³ª…Õu¢c“|вÊ++ŸlÓÆXf‘Wëau‘¢À†gÎ}c³±9‚´„r«ŒWË‹ÍA&Ì¢‡Z÷Äû+±q"SL» 7S±Éú>T+\¢ßºÞë(›Y¥Ýa,UWPÈ x}µÂ{žù6,Hv3îïÉ…#ºMexMÊÚÍ)Dèr£Þfµ›b7¨#ù ÝL5¬Üf¤Ï©^³P%öš4)/èfUùjûâåååíså— rŽ¥Ũ¼`¡"…ž)}í¤Ð ÄBÉ"OxÔ¥vWˆòô©‘”½ËQ‚låN‹iïèugn¿ßi”DÂ탑·^Â⪊¦,¥Š&aØNVÇÖ-´ª1¯ì¥gÆ‘½"Ø\S /úúTÚºXÅAjxY£çÝÆ&4L8MÊä¸Ô³KL»ñFßMb…ùêàÞx§À…«¾à¤»\÷ï.)|“2•lô¼°ÃYÄDë­$¤O®fc¹Ü©Å;þ¶61Âþ.U²ËGfÏQ/:×FN^'Äú•w¯ì·t–݃O}f¬Ú¤®Ø‚”æyÙbÎ… Ô1ù˜¯_øÔ’®mà?s‹.n{AXX•ß‚ÐEXß‚›ô,q((¬Í"y×¥d} ñü |ƒÅ9r¯ÃzÇÏd-MÚª Ö.žI—_ÃL‰ÅBë„^-¡Ô¸PŽ—Qy ;¨ªÝ=s—ß¾Qí©I™0qÝû¿/_¾¼uùûn$.«VS¨‡E§&l rz¡˜ôØýN° Ð f—m]ÿB9Zü/©Ø¾Ú×£GBºsPM,*¤ Q™¤nϤòàNÊKk2ýÌ› Ød ÈíKý3º6òÊôè)ÄdÝ‘ºOÿ~'Ìú:èùu)Ù˜Œ7!u¢ã™ÙÅüg±Ö}£û¼»vNDÖXñ÷þ¤»½"âªý|E« ç>w}Á£„r(驤¹‰‰ÝÝÂ|;)«‡N ËÙßš2–;•C5!uÒ·§ƒ{Õ¥ C®Úk³}¼˜b¼xeªÜ»9€{|ïݤI˜qhäyØÛ¾lwØ©D›U£“{Õ"Ñ}[®§÷Ôön-$6¯9`ãCq¡‹ç*wK¹wåØÃ^Qv{ç©êœ{ÞÊðnmm.\Çú}8Q¶iµµÙ9Z¡3ȯ^oåZ*ç^ï$ß»¹Ö …ž‰Åê———7ZÁÞ³û®&³6r+߬‚"XUˆôLêùµx²;\¿3!‡6:’QkŽÅ ‰MÚ´¯Ø¿FEÕ|åìi½±ß/ÇWÞÚeˆ©œ¼ñÆx±â¼ÈU5å–/oßšCký·ß©™íÈeXåfÏ‘üª·ááöU—òòs$¿Íîå+‰r…Èeڸϋ-Þˆ«ð§½d“:ñ½*4Õ3£IU]} <&NÚåk§J¸ƒ¼P*JrVêÕ¤Ë"nE¦Ÿ8äRŸ2±þ´Í:B»d¹%óÅó[DŠÍ­ÈÄ¥%÷iR°+Èw¹V­În‹S†ý¼k£¾ÿÇFðKö÷þä cÁ¾ƒ.$Ñ$q‰E}dšì›”¹oå$¯"ëzê¥&ÿf¿¿F«ØÉE0!µp1V‹çW•Lï×îò†B-Dzïó—_~yH2—¸ì¿Ù]£ˆ„k£êÙö•2µ5Øî]œÈ{ÖÿûÿïF^ùd%„ á±P ý‡ä¥íL-ÞínnóA¸è –ÍÜ—&ëÅNòzž‹šP•l¿_‰`áQB ÷ßÊÚßÿùçŸ Û&¬ÛwÊûýlÌì÷K¨×KN^™ÍïÑ<‹GÏL/‹%Åÿçþ绵ùôéÓƒ¼»•í;‹}!‰NêN¯a6†X±©dcCþ·Þ« ®‘jQrAå›»-έHóÌHö//mŸ—v É;¾<ÚK˜Å‰ÉîxùFò£/µ;›Vî_ùÓåÌ<˜fþío{ûRŽv÷.IÐBM¼@–L^&m rKd½\½ØM’ê= ©i‡ÁJu/Tˆßm—ç3<U;öûß¿ÿ¶àvHu\Ö¼o½EžS ýy섹®&ÏúeÔ)[s½ý÷ÅÏz9•G²ÄEŒ¨’ƒ?•´­¤·%¤u!× n¿¿p‡%ó‚*4ulkGC2¾kSôkd¿½§g†x|ÇÂûÝëTm SxUõõ·6;+Â4Œ²{k!SÅ ¥êbn÷Vë.ñ}7¹WvD윛•ÿ£ñ«ÒŽÃ¬»oöùº1Ϥb…;lW©¡Å»·u/¯Ë}³ d{ÍB¥^'N«/¾d²íTdçÝ‘'2É+†²îoI’ÊèÊù3éSÚ5¬T211a´9pâ-¶ÎmŒ\M¡šï¿Xé4ê’(6ñXL0édqk£1¢Ô hìÌõ½;©Ûß^l÷ž¸øŒ"4^6) !¬îš‹,Êá=vJÊ¥:AêÄf{PÕ°%x:¸ =3ÞØ ˜»IOåÞ-˜½Ã]{Þ7›ýýï+bV„ËuŸßÏ+Ó+ªB˜Íò—M·¶vÞU|³»,ßÑÆ‰“EiŠ(ÙÏ(¡œ<š^›3ØXñLÕ±ûÆæG¡®’¶õ*CXž›:Âö›,˵ìÔaÿWAßk9wõ¡)Œ×üèõõõ!]PNŸñªS‹6+W„/ãe›‚^|Ä~w›—aæeØí¾Q™Ôxd¡ÓxdÃME7÷õî…T5&l}“f^RtAE”½|&¯¼/uA=ä2({©œŸ£ÕV_U=[uJ8oexÉÀùìºþnìÜBF2~e)ÅÄÿöÛof¡Õ¯Ÿ\ˆ½ªÊѪ]åÕ¡J¾ÕcGÒuIá+$„–É㨄ž…È&*…+˜ˆµ]‡tɯ°;§Yýù‹{5µ»ÊàÖx°Ãv ä:ÔçExÔ: –”= qû\8C»Ç&•Éù¶’èN|Vüo=å¨ö"nÚ©p5â+¿,iÛ n÷—cÙÖp_4ÞØ8qÂë´JLúÖN_+ƒ:.—Ðn3 ¸kU|¶öN{¦Ö…+™ß}%lN)XÏ»;mœ˜Œ‹UÃ+f]Ì%{¹¤Ë$iûJ•"/rÖòL8-4LŠLºœ h s¸.äâíMjî'4«ñĵ©BcùŒ>›êVÂt/Ï‹z¥Øxéô½^p•‹óL°GANcq÷M-ÚAm<)Œ·“­­¼7*½çŠ£EÚÞŸyy90‹7×™s,?Û¹¾Vï tûÅ×Ú-Õ Äª×ƒl¡¢Lœ£ÙB¿TÑæROŒMô°¨Üª„U»ä>_¨—ßׯ_ߺǗÁœ›Ý b›E̺ºÞ[»øÊJnº6///ü¡âoí$9³;㳩<áøtØFÉpŽä%´ ´l¿«‰‡ï]ãÂgð)'u?þøãÛ³× {ûÖI];]ŤÛ}Þ÷uªÐ.a‹È%>56ô°P)éÚ.Þº-NÕW¢Ñ]fª†•8ì³=óàY³…P!•U©G"a92*ÒÙéj¼Q¶R‘…̾›Í»j{¶%U¾÷ÅáRÊ^þñÇï>}úôà:Ö"R£³âù•¥´È{&„ ÜÒg¿R/ Ê+˹“ã"4Ì‹\ܵIÙÖS•ÄJÙom\KùA’o÷ì®]“®]`×4Ëd¨RùÞc£ôCSNT^Y§œBG?þü]¼ðL4irm.¸¦qm$¼ÛˆYÒfWÖ}z‰MÊãPr¼ªS¡[BQÛٮ̿œÀ¿JÍzG öž²P⬂’ñÆ„¹†šíþj"[½zÔLÔâ¾~hrll`}üøñ4üÞùþ׿þõ«&iC œ¼gøòŠ{&¼ò¬€5S^Y˜ï%!ÔÕXlc¥ž\¢ql6.¿1Ÿ)´~k§Eƒ|#ïè½óÏ„Ó,s˜¢qÖ`\<2×µÙ)´¾ÚšÈÖ'ï²Þ(?è²æ0-žXËKS€CʆE¢H§Š(ª#ŒWÚÀöÒÓ—™¹>yÆ›BIýß{_^ èªP°/­‰ÛºžUk1ö ïK‰£TæMÐ5vÞ :bÒ¥êÙb|¹:u+=½nÞNìT êÄÅnÎpÉnåUHÒW¡ð¨«Sµg•(X.„}¿¤íJÉîpo3×){ï× ·ÄdÅÉ  ZhR¦§…Øc §”õ‚XÒô0ãJ[ø,aÝó¨Ï¯ÏÌöæÇ‚r^%‚Û¬·Á³}kÐÖ˜p—HÉrÕ×W_Á‹ŠíÕ c±Ï&D§< lT–»EayrtœJØy_±R%“ÕJS›°$åДR™Ü­o¡ú.8©Û»^².$qïrÅ‚I–ö’ºBתÜÕ¤ËXm§ê*d*ÀaBØBÀäÞ[•µüçñÂö}ô.?¨‰‡Ÿo_(Y~Ií[è,n«÷úúú³yàDfûfûv“HŸ½~cÆF“aýƒ,t*I.þ~òÉ>{m<3ÃóW _8ç΃±ÜBF߆N 7éÛï¯ÒŸÏ®OŒ<ûÜy¾Uí¬»ï*Û}õåË—8ºÜªg"í¬»¶ž©C·)%GFΞ&­‹'…UbxñâCº ª{¯ƒ÷½¼¼¼ûøñãC3tŸ ³!÷åË—‡¢´¢5:¸7Þôž]Žá®ÐÂe˜éÚùù‘®©c¹œÂæÊªÜ»èÍdgÞBf{þò'Zl3èÔbï½0…oä'U”Æ ŒûjI—÷LUÇL¦mN(%Ûx°=öõë×7ú)2aþᙫj«™Ë&ÀéúÖ¾ Ý7û‹…ú™mZ¶œª\ílF¶Pº¸KÖ•ù7zf®«j*¢ek³=4è½ùO!Dîq!Ê’ù-„œy°çí^îÔ¦¤klt:>^YygJ 95á=%ìÎ}£\|áWËzÇoÏëµÒâþ™l·¼2›ZæÅN\Ü7¾Wy®mêÏØ†\ïI¥æõŠDìL×ôÚ‰Žœ´÷/¶²Ô<¯*Bªâc;â*þÕÑh»Ï¿ÿþûÛhv‡E â6]¤%dÙý5ˆ©A¿¿UÓ¢ê ?#9ŠÜ‚¯3îÄÆ¼Ñë6«Š(%×ÚÅÛË7™®Ìnå…ª”C#îZB™xþ¹ý~5â½Üª¿oÂ)O£õuùŠ»n‡ÔŽ¢Sá&œ&˜JÍV­eV/í ¥`…žÛ»é’ºõ&(T¢:ê.[ˆM'.’ý/XÞΔ ƒœSP÷½EÛE5È911ñhs¡…ŠÜ'ÿ¶Ež %Ï·¯•ìܳﲸpÙƒ†i"ë¾,¼IØœ0šªÑ]’ …Á(÷.œArì3·¹Ðx!\@NÝÄ5Nêi!L·Šp…:a^,WʵI›~!ú.8á]¼1^Ø03^˜Œ[@ëO¤g…T“”¾÷žÉu …ùŠ<и¹þCª^êk:oSjgR¨†Óo!BíþZÀšpnmT:fÜ/hñBÌzåàíÒ«ZV/8å—·–ûûò8,êj,}ùulâ#q¸„tãiÎÅjù=…²Ú¬4?šº„ùÉÁàÄ&oCªÊaRe—rÜ“u/ÏAÇTžñ…8:µX0h˜¬ãbB+¦]߇­M§UÃ&ïß•+¡›tÕ¥T“v§²„jwºúº6&-{¶]®õ¨YëÅox:ŽF˽e'{pˆMQäBì÷_Äen% ’}·Â§v±.ÈxyéÚë¾Ñ„ÍIÜŠ*1íKh›X8æýøñãÛïßÚz&„¡øó{—õ7²{¼]X AR:›À h ¯ ìš 𗺔þÂû× ¥¾V{6ÐÂ,òäà(B!éÛï'.{]B÷¼EâÖFe0Ò­»°òÊŒ•â¶÷]L¶}¯J¹^I•M)…Xõ׿þõ-Þ]œ= Òý¼‰A½—–Té»e¼¯ÌU¤ÕÜØ„Q諼7¥b+N¢0‹\ˆ%”*Ò©¥¸ˆ÷Øš ¾÷I‹0×yɼ9‚"ñø:òh=3Bˆ”sß¿æƒ|E•¿ŒÕ[»­£9JÍûö®m˜-oP¸ÅBÃFmáQÛóõ’SýÚ7KÊþò—¿¼û׿þõöÝw&mNÔóë*+†´|aèvî5̬ˆ„pÌ}'IÝ&”5à]Bº²g÷ó½—ÆúÝS½ã…ÁíÙWæŠ{ïûo,¤œÎ«úÚüǦ“ ³‹{%é­1ŸØ{is¡Â,û߇ÞÎÜâ…*“6ä¦o;MêôÞ}#·ËÙæÃrÇ pØ[Ãmy£÷àî𭳆ákêlm _<²Yú3Ó„Iìt1ç*ž8•(Y®nÐU5ëçy «P ;gâ +/0[µ—ç!´¬R²ªO=sâV¥nÓNY舟­›ôªîΕ­ôýè³@ §fÂ’wM¶56”¬&G§Š) Ðâý~—r—¦’*u´t)¦H޵:V•ŸqbÚÅ×:ò·Û³µ¹ü…êc£½ïFtÿÿ¿ýÛ¿=ðLJ4ô ïóÁõä­-[â±=ÝÖ¤ËdyßW®Ce+=3‹—w‰ˆx…ê^o·h¬ˆ„POÆ-Z'ͤkë1‰¥>ã)Y¾ÏŸÉr_ñhxþ]àìïL4^ç¡À‡“€Ë¡]¿šBþío{›¨wº®7rî—AÝâÑÔhÊa鄸ýû÷ï>}úôÐi·qRiê9§$ó¹Hã‹'võbѼÏwïÕdßsgW_¥+“áKÍ®Ü&;œ5à­ÈƒkSÿ¢={‰Írþ.ÓH!DòÒ46ôîèYÞ5öüCØ5žo¯*Xɹ•ÂßÔ@žš<‹7ò*Ï|Áò´P­nñN³eïð×××7x•\N6ÊK“Ã2Á$;×6ìlœhJ]?³«Ý¡õ'RðÇ;^¯94æG&÷ø3Ùpe|åcª i¼igþ2½–·áD¥Öåø¶ ^~´9@ùI{v¡ez3Éå¬i¤gêZ»Åáí+­5v¦V$êÙeó¡~haËŸôb“Ë© bmGü›õÔG¯ªc -Ôí‚wßUÕµF«6#Í‹-@…á^Mr¾Îb¦²“›:x¹ö [•ïòTRÔkIMv4¬šWŽPh™Š'<:\fWŽ;;²/ñx.¥b÷lúBTöRL»U»Ý’J W°›ãXº0—aV­Â!$ÔËE¨l¥k«»Øi»|Ê+O'Ý„¶#}¡ UhR$B"z=x„©HÄkR³µö^ÙK;ÿ…Õ+E ¨$ËúÈ +_JÒùðþ•4/d±„Ó2¡mžÙ&ûMjô™)ODÕåÚ« dRfi7§2»Nòä*\ü!ßúùà ;Ãeï]·yÐËÓ„®J;â¨xÊÝ2éR¶Rø„^\µgfçWXžÓ*§ç¶)!¬4µ¼´BŒ ®]VZá–Æb¥§U£²Hl¼rRgãÄ},Gfü ýýžÏ|¥©-ò.øÕº»Ê½Ûù¾T†„4^ëîy/þN\Löõ~&¼"s÷îλ°e!H›Ô9és_É;ÛÚlmU ÖWùf;¨B¬ë\»5NìÌïw¯º¿S ŸÍ‰‹±^¼¿¼°úÈ,VzfWÌHöæ fþSü¡Â¿È”Ëà´© ³åGr\œž7ÙÖgÆ;º0ßgÏfg½dþÅ=v„Hš¦”~mõûï¿¿­MUYŸÝSÆR%ÓŸùÀ”“'­A¥¾æGZ½ãÍ$ãQbÓ¨ðêË–d…Œù“ßOU1%Í·,€…Æ7©Ñüâ©*ˆ -¸6ŠLTLɵßçÂÍ-óÌ5/6ž÷ÇÚ{²fÿÙ¼ü/;]^®%æhÎ'öx‹Ti1ž_¾|y é T|n=/êYQéEZ}Lþ…[,±0HV ÀN”!ñøÛøA» ì{K Ð*c ’å:Ô—A¡$Û`[/!51ºV‘‡¶m¸mxº®¾N³ ¢û÷…~Ub‰Ã&Ï%}ý¼°¹ßÿý ê±ïëÚ^0™gž5F\Ñ ¼µÑOÄ3±}¥F».ãíî^ApI×ö•Äæ>ÈÍòÙwÉoßî½w_ Z1S¥}·‰H¨6#'Ob±úõ’ñ E «Ám¹ åMδ˜vãÉ’õ196›ª8Ò/6ù’›w_O„,n]Vð9‰SÑLÈ¢Â)âù-ÒÊ/ªËøÎËN/»I8„Íg‡R'ïá®­ßoŸïLM)ÐX.\Áxµ=- Fq’qiVèØõ×ÄMÅ6 %Õ¥Ü'?~|üµˆ\²®âdVå—;ªûü•ðþ×ý׃°K…ÖýÝ{6Vnjm»;rï¾æÃ>|8“®Â1}v§òdüñÇï gNtŠÊ°rº.Þò¦¨U]µÜ'£¢3&U¨+w&í¼/ ´“^Žï‡ ‹À­½¿µÖø³ IDATgv{ukë¾®òi!Ô×>_¥ð½ãÖ\(YÕ)=tä—“·ï÷ñãÇ·çøöíÛƒp‹ý‘ä_ 4>Ëå3cí³[— ZÄÈöÍÅm’7æsûªBõ캄WDMèÅâ$Ðüé2±ÕWK轜Âp íwÊéqÒÁ5¶iÔóºXj¡4ièú+Zô>øÌ8"SžÙîôåŒ+µîö’o­ºí.±v4z9ˆ>SWXeÅÀ³#ÿâñU5&s©zÔ¤­¦ÊÌ oÚ!Ðݵвú:lƒ¯È«ªØþÝð³ ò%*Ê¡ÙAu%T£Zâ­ª^%¨cm ¦J~^¦IŠDÈÏQ¹Âq¿ŸfI”r.8Bq×å‰4©ž_üë~“q1¤•v¼”½jd&œÃ"ÐgÙ幎´AP£ŽËõuðàoâR a› ’*-ò*I¾.ŸI×ö]¸å•]ÅÛwúN‰]~}}ýNצÅZ'²BM½Ü »+”µbÕ×Wî}±cü¥­«Äý>½vföÝœjH0•Œ¼IžÅŒP‘%5ÛsUìôºÐ1Uõ‰Ñ³Káñüz3)Å/gî·ß~{€sýõ¯}è† -Û÷šæÚ"]Å7¡ Uç,Œf÷X‘&œ ýªÍeR»†Þžc°: ^erwyKæ^%÷ª<zî;;¬ %ع÷Lè%gg{b›&´õ–8ó¿5+Müœì;]Úº «sªPß+ùˆ…[/DUxÏ}øðáí^2`ë¢<³9Hy¬»’îßyWÙwšµ‚TޝƒÂ¿5yuO?C˜=û|ñ§>1Â5k´*sSέ½Ð±½Çg`‹<:T5s éT£°9úæ/Êv_Šn[›èfY@ÿøãûfêŸ;ŸU6•ï¸w%<]ÿ¢ÆjvBU¹’ÎQ>‹»÷V~#»mƒ™Xì…­ÐY .á ÓùöÂûïò5 ¯c1j1ç2);²Ww؃*Ir‰ / r%m‹^µï¾µÛ´Ë‘¾P/ÇÿÏØ½.ÉuU[»¶ l Öýß"’|,™µ½O6õô·AP®¬œcŽÑG?´ÃÂXTùYx”Uü’ÕÖ€®Ê÷ºcßµéµ »•,ï^ùý÷ß_½{÷îAÉÏî¯BÛ=Þx©P‚ƒ”ü¼ÃMz,òš¨\ý>„ª¶¶N£\«k_¹ïœðêðÞ] z•±¶˜¨1³ûÆf¤d÷•w| Š—HÄž)¥§°øÞ—{%üûꜷ/VºÚé‘;½ïâ•9ˆ9u5f„Kp‚[¼ZïÓ¿í{[èך}Š®)÷ëL«w:^é¾Y%„×HÑ™r¸mNh?a½8~M¿WuLE¶åȘÛÙ0óç­•ñHTFk/­À;¾}óþýû‡ÆñÊÅ[y¦ÖŸ±¿çÄEJF{Jˆ´Üñмg^oåüÝ¿ýöÛøõë×/ª©æ'æ7+çþà3c7'ܯêNÊêÎ*ÔbMÔÄâ™XíÏß"Yš˜ˆaÆr%e+‹ÙfWÎô¡}Íÿ ¨ªþË_þòò;++¾öº·ãRƒ;×r1¦ŽÌWJVGîjЋ–„ÙA­ÃZ¡ºr®&ö:Ä‹!•جV‰‡ü!3b0Õ9×ïÃïbbaïû·öW'k%×} øéË_+ÙM(Ê’º3ËZ#/§e^~÷KÚ{íùþþ«jöîÝ»nÆ3<¿Eê¥N%~ÖËÚnJÒÓbÚÝúÌØÁ´±âXÚ éžÖ·J¹ÓâIëܾèw>}úô¯.s?½UÞ¿ÿ:³%–]Žrz©Tõ¬ïÓÅ’xÉ¥i—ÐÆ‹šõy‘Çq­¶/,€‹Õ}F±¼çíްü! |ÝW+ܲJ9ª[=SÚ¹:ãíi -dl*©$¹Ë³wçt{ïÁßÿýe_ô÷¯BÈd\ˆ³Í‡°øÁêä#êÓ¾j\â± M»–\5‡è’ªÞ›Ó&6Z§ïÛXÙXžÄðNlzÎÖF°ûV—ñž÷ò’sÚåUo¦âMÙ윋)Ù·¸7–¯ÈƒùOû¢=W~T\´ùÐ{¶ª8‰±ZéÚ•oßO2yÑ äKT‘͆ުšc¶6z+ ãÛü¤ü¨½«—Êò֮ܲµ í#aÞB«ß÷.ùúõëC¬_Úr¿8V¿Ës:nq®ÕÆeÀkž*GxùGÊv÷ŸÎÔ¿» U ”üâ5±µÐ“_d£;”WëZî=­HD{Zݳí ÅÌ`fUD‹»ÞÜvÞÕöCã?Õ fB·cá:UvêUXòçvº bbH×Qy 3MH{éb“WÕc ïò‡ì *d°r¨þcÂz)šÀÜ·Ž—úÏ?ÿü §¨ÚËzè({L·3o7g‰É+±¾v U—ÚÄb}f„É8(¡-àÈ‘iïÄVžð‘¨ÀuJ²ûrÕ«’’5ˆ+Šañ2ÛÚiÔŽV…jØÉòÝl·H• ڞפJ\µÝšÅ_kÓÏãJ\pÏ ›þGëÁ£"J³Xb´}¯&Ó&a›¬×T=Êxå{µ“uÅ£õ­’çaRvI‚J\¶3/\´}Ql~U-”ÃDÅm·vNþôy­c³‰„'yúÙ”²»’žNß…º.dQo'÷¥ÝeE$Ö¬sEk¼ÇìþÚ421"´ÒÒëéeQ—ß™0Ÿ½µʺ÷SJ§Yªšyæ„D*Æ¡¯Cñja,6Ö«ÄfáúÌ”TYVË9 K0¿<ï©G+çÚ³«Ž©¹ñZ,\’æ­ë+¡Ý©Â3žÆÞÁ&ëNÃJXÅN»Ögϵsm…4Ö¨•'"âÄ}Q!¤S¹aïÁæk·ªfòl m,.Þ¬8ˆ¹ßú™ékµ*‹»¯ä+šû ¾Ð<ªo·ìÑüÔ"²d^Ãm}cTÃ[ÈáòÖVl {nE²víÌ«7‹ ‘ã»Eá æÍz3í¾^3Q%Ím‚/ìNÊ„EÜ7ÅŒð¨K‚X¥Õ@ ÄÇηp¿@fÉhmæÆN^0 êâ—Èhç|}dV•C¼RïƒKBX®ƒ‰Å%³kÅo‡r%†cÚæ6©²‹ØañâvtªTlÿ}… Ö}u X×fcB°jöÙ$ßêîº.æb—UÂYƒ9 dÍ´v4j÷v%? æN„#,·jáUBd ˆ^Khß"°g[u/y$¯_¿~qýU$Â@ F˜ÍEÔs¤ngü‚z(€±¾SŠDˆŸ5H Ë““'>¶·õªy°ì:m_ð޵÷XyæõR1¡ý#Ÿ!B^®+tà³µl_­SvïA_9.ÀíÕ캜Ĵï¾(žxYÙ…3Þ8é³Ñ²þB—wgØ}eÓh1ç—Ìâ¦õ}¸äನ̀kkøÿçö¶ê™›ÌïTÀî³ ±d}Ï„ÝÏÎÌ%×¾òË6¬+” Á®ÏnR¶ K&ˆºx{]û¦g÷[2¿±v%Œ%.¯‰ìuOm!´wìÂ|/Ø]0®kJi¸GÕð„8kÔj<éÙmu¦ž)¶­‰ìÚ«÷çÞc—ña±ö™GÏBÏšF85XÉtÅ<Ž¹Ð±ô)¤Ô™t­„ãuŸÚ(ÖcǦ¹á…ñ¶q²^(í›gÐxcõÚ’l¼ðóÌm¹þEëÃçâ™Ü»ÞNY$“g®º÷&ì®x³Ü«µÖXUÖµã{ÉÁ[>H3û®ÎxAÎ ÄÒ´cç•ÿs´ê˜èßÿþ÷ÃgëÀ^à\SH½P< IÕÙeôrµH—¹\ %Ýz¶…Êš´Ù±“îØØŽDp;KWâàY©Y»=%…ÑT9L\ÂÏ cYÅ%öeZà*ñk7ÆÎ“ŸÔ`¼|3Ò7É»ü‹z/­¼+!“â®KZ–%/M%ßKkížÖdÍnŒ[éê.‹ÊüãcíOŸ>=üï.ß.ÈÏŸ??\XŽä;óŽÅWx ¨I =»UÃ.!ƒÎœ*d’õÅ”÷Ýþþ÷¿?|÷âMÏ.‰²ËÛf…¸kÕòZ¯¦e›Ì7É Òº(ƒë$Ñ‘»IIçEƒ_ ñ+%ë¾øðáÃÃä­Ä¡V¼Pª¾=#îºËÔBèÙ¾36¿}ûö—f¼Y8ƒÍ§"O»Çuk¾È賊'%­BM l2~Å£ï¿ÿþÕ§OŸîÅ·oß>$y©þFr§NˆõRY~Q…޲ÜôÊì6%µyP±Y<)6&¶Ò¾º +í\wÏôY¾w9{âñ¯ß¾s¼6àlJéý´ Oª‡ö]œ wæ.U³•¾Ô©2ðŽ~fð»\‰ÿû¿ÿ{¹g:— µo\+ãQPT¥ø…XwOR¹´{פ/hYß_ÈbÐ0á¨!.T£sbRñ»ÆÎBMmðXÈhXÙçwÏh°¸(~^LTl X,·TÈaa=¿Ö'o‘:&ëoÞ¼ùF­÷Ç|ám3P!§ÖÞ&óø*In³Ñfƒ’äÂ9Í«ÍlôÚ/¶÷ýD¼ôýk¼ô÷j¼Km¢·'åÛ¨-ÎKûÿYþÐ 3³ ¹¸ë•g¾¤b7i»Fh´ª:eä®$¨J7Ÿ?~ȳ*××Á¤êâà\ÛXÔ S-¦ Y‡rÞ•áõrI¹ÂËPÉŽNM·»ìÅ.\kÇÎᶃpõû‹-^¹SáM½+‘UæZ9U‹ÀF¿šB:ò7h YçÙJ$”£âáð½‹9ÿ#~Ý'•vTý !&]n•$ÊNƒ¤Ü«u§/0¶ïÖ Û.]?7¡\¨S÷½j/±öE\=)ÚCî»p>ÛÊìþ\sšºÄWúQØž[¨ˆ*Dv’¼@L†åékå„Çx’ îzôlkB›ï‚k×Îæ€“…yyn‘dw¸3»j2^Ž— —£üI L_¼½Í}ô‘‘¼«±kÏ&”U¸¥Få—u›jr™‰Š».áq"Òw³;­èÍò@V=Óx²6îã…•°j¬¸Ósyer«ZÛõn*)ª;ìÄfe»mè-±X½R°5ÌLL ²Šnâý/…¥õä2u7å{eg^˜Œ±|y²J_ï»]9y'…" ÚÊH,iZ•CóŸ dÕ£V•UÑ -D´ôý~ú駇{Ù{Nñr9V1V«'Dh¹Þá /¿:ë€óëÙ¥Xˆ^rßÿýK!T3¸}S¬Ö(Õ3!,Ð3©E±V?µ•(–Ô=ØóVö:skàkÚ÷Ì)eñÒÖkÍæƒ¨ óæ…ùº¯,€õ¶S¨Ê}ÓdÑxT< IqÙˆæYh›?_ †…á¡v‚»—³˜éò+)´c¡ ø*0-ñø‚_meêå(œAܵd|É»^¾m}ºa]:{ ‚«Qg\ŒžÍñ R²vk.ï•nÄ¿^#÷ ã¹Zàrhü¹y jÈ_îôKøŠç±£ÏgŸPÂx½Täy(ùiú̃g%Š=È:ëö,lP• gž&œ*áüÑ{—§áäLn”°8§œâ®ëÒÉ­òPïUÜõJ¯‰¬PU%»škºS¹Ï#Ëqq$o÷W¾@ká¾ñÙ…K˜|Û SEh§¬ª½üŸaÒ=“6^,ÂÖ×ÊËm¹6F®xâÏ#·J^ÚîËË×a%;%_&kž ‹÷¹ 6–{e<ºjÅr1ïËóÐC¸fI®F¨ËÑE\äÀòHôB±»ì™Š&¤Ñ)äB°×·¡3¥ €žòX}¯+JSRå´i…W6±XÅ·öªkg×a¼ q¾¦Ûú]2»%ë+d`¸Ȁ…wÛŒ\ÒôJÉšP ¿’¯Í€œ<§{­ŸˆawÆj÷k[a%¦"óÙÚXÀjZí³o!²ÁN“–³œ¿Ëcp%Ó7!Ý"°ü¨)‘¨÷Õå•R›BOýí¼—ÚWæ½®ûNÈck¿bFÂ|¥=¼ä½&z,œ¡Í*†ÓQérh”ÜÜÑjA´‹SR¹ ޹;è%.%©‘øýMºÄë÷,2½LÇê>{Ý_¨ •PºÊ&œVͽ„wïÞ=@-4&\U:YBœèÔqXB˜°™øKúVQΠ{‰¬ °µ‚ÂnVI×I \94½waq‹Û.µ‰UÊ ’è¾³c! F|­A´w»ð§ÐRRø’ÅúìŸì ù[Gß½ï»ÒŒþ¼‘½0¼•¥”ëÐÔÄ©dlϵ²›^Â:—ë%²Éüv@íæô^\;½>~üxv·ê3”®6aÝÄÁ , °x·²ÞWç^¥™Þ«“› à2B|*T”#í»Ê­ê3W)°¤jyc»v!답˜w ªpŰkÞ×ô[‚©Ó¦”„é®ZŽŠ¼¾GÝá '“"½<“~wU˺¼MÊ,•åî]ªZ&×Ssã’Žß~ûí>µ²ÞMEÚ+¯l‡tÍ…kØ )7iÒ0Óg³ˆÛ;>Èázø´ö˜;±1™ïû%©Ñ¢3×]E6æõÑG¦ï&iúôyæ VilÕ#ç‚+À¡Å‚“¾M8-x;ó¢*„x ZØB Z(TtÖÌÛ†W߯dºwo‘V<±Y$±µ>4æGñDlN‚4*ŽäÚ÷n.þtÍrú­‘jw¼ùKû¦œc“ýî±mÈÙˆU}3rï²3·Ú>½TäЫã3ºï.dpRUÓ„‡®M€ñ`½÷N9zð\6¿üòËCÞýÃ?|yô÷•‹×Ÿè)ÌLœäÕa$6Ùn²Aj‰„úÓŸ^}øðá¡ÃaS/ûò>P‡Ý‘þº+{·Š) M+È­„žP“2“6au%ÛËeØiUÿ¾Ê&¤Â§~þùç—©B0Ret/£1®t£ÒÓ¾«U§2Jøêò& f½N„Ø´¡ Ðvª¼ „jš$äиËõ:È& =ó [x)K¹ÅUöR±DéÆô‹DÙ¥lR¶ìNÚ,h%œ÷lÏÌ®üùJrŠmîXXOŒº&+ Ú¾ oï”URnûè©;©3)Y6ß«‰Ó¨Ul j§¬çN*Ö®£ûr½T)2¡µ¤OÍÝë]›âÍš:]Èá…§ï\Žƃqö—ÝÞxÿþýC¬ìÙä/©’(n[¸ƒÅý¼ËÓw»J‚6^.>cjm”¡ÕˆYL·¿åm¨É±©ñRq¤L®^)ý;úÈôn¼ìõmP=Óé»Ýr'MË4…´ˆr¨¯ƒw`gõ2÷3©r:nba!.±8ˆÐr¯ÜgÞñ+Q×Á;Üî²pÌÖsùŠB›Z”D:ÉÓ~b÷•wàe"«Šü@!…Bx¶@öÙ÷ç%¸î[›J—:§¢mZ]ðòâ°2NTÖ—!ç剴AÚ¬þ\ij9,«ü|}bZ“}'6 -3ÙµK÷¬ûk!²ÒŠ›ìë^/YÍ"q%нœqPAiG÷—cÝ[¥`/™\%ˆ•½lÏ® ïBA$Ë­*šÊ[ÊàJr´+_Ž‹…—xû‚ x}ÎÀP.Õ¿ï”ÔϿܨåÈØ´K'œaÄzÇ+çnç\Žp.¾Å‚r£:Ö{ÜžõÌÙz~^ ¥ù‘ðRmZ;ïI›•J÷;Êè^ðóàš‹Ö鎖ð®Šrë3£Ôþ*{-‡f¹U;!^%@ ëN€ÝWò\ÿ>^lSIeR§5Z/›Ø×4«µéó—[.jC«m¨]‚<Ø®|'㉜?ù×y6r7Þ\|ÇåÕo#WNßÒQV„b§ï)ýÞŠ™Ë¸PiE5æuoc*æ¼±õ&´v–€êåªRÿNe] §&ŒàŸ9°¯·ÁBÃ<ˆ‹!Õùvƒ˜Ñ._¡×¯_?TÝ+1l²îàåÔAÕÜÏ.΂˜Uõ¿þõ¯̬]<; +¯ì´©µo3ª¦ÓõåÛàèÔÎ÷âùÕ2·#)ö¹Ë[Ì.‰r‰Ã%óàº1]=»R÷Õâo;ˆJoñß;‹Hh‘w®«?B´ÒÒ×ÄÇ ZwÛ„Ó½¦PTMYå2¬Ü©ôbÚ Rv[/Ÿ!:ÿý÷/â 6'—½ü"92»6]~uùÄœ/‡FîÔ5¥¬ÐéyלO(ëׯ_¦Â§L(å)±ž&Û­MÍv¹o…†ˆËwídì¯@qív‚¼|Æ«Py&!¬üòN„àÄõ4lj°˜t!>ëà¾k»Óõ5?^O ï1ý‰Öœx §ßyÅê7oÞ¼4•s_acyŽÆÆ«î¡Î± åÅiòß*ÍJ¼ IDAT/^ôy 欑éN˜mœlӪɤjy"k&ºÅ»|ÄmV®ƒŠkæÂdËÌG»hÅAÖbÁIÛ6Z×½ÿÄÙ=w!JÚ£6Ö¸pI×6©ÍúïñL.ZÁ¥r(ü¼{te½¯d¾éQ…†k×vùŠË¡©H[ó£5n¾$ɯd{)þóŸàOæÍ—5‡\ÎδдàœN=Bîn~£´¶Šm"™–_Ì×iÓZȇܦh›öñh‘H+…ßïËéóÙ„á–·¿@W!É ã‚®ºxüÕÃ~óæÍƒÄÞ~);ç-p#2“6«±­Ú'©†üêóÛ‘Pu쑹 âªuýŽ Vðš*tÐ?}úôÀy‘_ä³+gêøÐîñbL•c½Uú~*g-.Û÷^ÂÙ÷+)ÛÍ&îÙƒ$G¥¥ð|Áâóçϰ”÷ïß#áÿ¶%ìn;¤vöK°ìþj†µcçõ¹:YKL¶ûëaò¼òÌ›”]D@ÿišä³ÙùZ™ÝÆÎB%Ø?éÛÍéb’`QinÏŒ~!מÔãFÿ 1á‹Iå¾°àUîT|­0™•(vív*áâÏUA’wâ™r_u¦®xdbáwµËV¼¸ ‘…Wõî:®Í…~¿g Z¶?þ}íì Æâ»ÿ£X½E` eëªÀÂîúÿ„8oä:x*‹*P.V?4”l´È?zóæÍ |Jh™*`Úгa§,·ÈÎÌòDŽ)oÌ)§2ÿ%]X&1Ü¿ÓÚ R< æ‚EÜz7mwÙ}kg½BO(¬•’}ã‰Síþ^ ¹år:omvßt&*=³B…–™ŒË¥öµ’êrä^ËåkÊå\ÎÞN¿ü;]_¡„õì=+Ờ<›%Ä5<3òÒâü©XÛ=Õ»m_9!¶¨”ö°À¥ô·Ü0qݪɨƧ¤gk»ªfuÃÂË+dà$®¤Í3³.ävéT¯R¤bñú[È(V²œpÙ ¿’|+÷jß$´×}VÅ­I` ë5Mò¼Ûi—üz‰‹ˆ—Ï Å I9R÷Åzìô;;!6Vo<ór ²}Ö,tÕL¢„=S ”ßcçºúR-“ËpÉà^ÅBü!M'À »zÖýâ=©S·‰ÇÂ|UùQ´Æ„´=½jwÛL\Yn…TvmT\ë»;µõS™Ôd]néuæVêÞ©¬gNŸ˜P~Y…%…_µQüãâ#.סµ>Õ=¤Ð¥.µÞKéÖví!„øx¦ûý¦y«@©WJ±~áTMëLµ×Êlú¬zUqn¡a×=´œ¿…GÅÙ[è½°;ÿYø”²Ý—B¥ÓªÄoK’{T¢ª™S ¡¨ªÕ)ÜR³Íóîô]°ÐùmÈ 9TùÔÁ3Wë®,x°¼r§åôiÝaþã»1Ï ,§O±£…²k—óç”R·‡bFÜ÷BÇL®u–u4êÈÜd^쯦ŒŽÿ”™³ú*á4!´sîXY™]ÇkJôYÈtÉØÉÒYU.ÄBAV>pexøØ5ÜÄÃ.^?_8Âúq¸ä:¨NµÉø>»¾ >»S‡u ÒÚ¯Dž…ŒòÌËR}ʵ»d½Å°^Äa…+Û‰sîXÙyñüvwuñ{Nˆ… /?HÔ†\‰m‚_ÉüòÒl›k:¡:TÿâyOí=´ùËB½ÇTß,žl2¿~gË6V_F«ŠÞ\¼µb—±Ü"îâ–»¶Æ¿ì)¶ˆ[O1=x^.¬%Ë/¤“Ð0ï+¿Ö+Ûí¾ñž~(fÔ|v̳x8«VµÆ•Ðë°$í¨ª†#²-tÖðIiGÇŸz±˜Œ‹¯•˜Ü!—P©$§}I’b4ý}á *O´9„ÝÉÁ11éo “¹ $v4Tžh]ëþn3yлZw…+—8Ôu´i'[S#=zÖÈg³ƒº>4ëµ²\;^~bî½Ü·Ûát_9jîð?ÿó?/ûÖ}c€·Ko»š+½(ž?¨‡I”NØ;±¹íª½ä¯¿™$Põ´0À¯F]À¢»çå:”äÜ©Œ%ÌÅwáŽÌU[ñ̺–?´"ò¶ñ¬N…§5}ŒË°˜u1íYÛ¶’ºgNè×^íñâ‘ûÆ}wI›¤9ƒ³½ŠDXàv¦¶ÐñÌ,¡\Ìú¡š­œû6>Öd6KsUWj}d\;Ml}w«ò£tÿ ,'O_‡•,_蘼µm|twíw·1²?oߨ)O]j§” bT"^`üŠêÔc‘òd×Ö"OžìŠxÇ –;u™}ö}¶À-V?óšóŽ.ÞÈmøé§ŸŠÊõÉ[1$›®aÍÆ³J¡g«Š7ŠÊ¸¯ô‰^µ|ÆÞmXy ¼í MÍåµYµÓ‘—çrd <éÖ¾ŽJIvkW2k÷¸Î÷2½‡ð·Ÿ·ûÛßþö0)\O‰.×þ¾R»€zf¨"´žòL ’žQE*,幈¡·ÛDF}ú.Ï•‚õÌYè8þï³/ˆ¡ˆ@*Ù¿d¼wÓ"äÐBEó@‰„;‘éÌlg^éÈURÖÛÄÃ.œ''>ÂæúO{Ê=½\….™šJ;]79Wšº}å”BÙËï¾ûîÕ‡^ÞëÕìL¯idpBa0qò¶iÕó•tin,b¡¬ÛTê½*Ý:iŒh¡¢0‚|ùEÏ&6Ï/íý—%Ûý ¹âŠdÿõm(õyºÓ·']X/”…é½Ô½†™Â¡JX{Vy®qò,xß½{÷=“ükⳞdíã8@N)½ Vgó ½g2®ÃÛ·o|«¼ãƒÅ™´Ó- ®ñ²½&ãÝÇÂËJhn3S‰c-œø/…köý½i],òº§ÖmM¯·ÑÛ÷]ÕÖÞ[wa~ ݱò\û}§æŽíKa¸åWæ NxžÁ§ºÃVdbƒœÔÉ‘±Ñi£Ø&sgN‘‰5à-?ŠP¡%’©}l,ÖL]Žß§µm¿Ë­S~cã&Z…æðk{W:‹Ð8}_§1Ûô‘?m¼ðÎlíÊâO¯¤ywÓÞcÒÌŽàÂu›š˜le¸…„¬Ÿ~úé¡8Xß7{X=§‘¶uDöð­gÆò܉Mš¦ âñ/g\ùMÁ’ “2]Æå‰Û®êX·Ï2^’åÊääžq]ü*ßÄRf÷ÙÚJž]!‡õR±ƒº¸m 'ÅÀv&/ƒ:Í´42óò[µ;§q1¥õÀéy‹G§abW²óÍ›7/d~ãIg¶xá™3©¤sqº¼—`ª_HF¡^ô 2Þ‹S ÀލÂí+Õ蜮×ý6Zæ™UN^e.»„òÖì°¶ÎBåäÉuP ÐâZî”P×bŸ-¿ãÕºŒ_…c^µdùEzoRQôÙ*"ç®3ó—¿üå¥!as¡=i3ÀX¸*‰Ýc{æ.X1}Õ1ÝN}v'uý¾PÙ¼Rú.òÎּφÜ&¬BלȮÜêî‹M8·ÐQkyoKÊÞ{ÊX¼ÞMË#imäfyfŸÁîöÙ„ƒî¹X¾ë… /…’ÙxYÞš2¸+“k!ÒßöÌöÞ…ÞËiÏ{GûÞËíú¹±Úx¦Êázèk—[µEž¹áú…wŸy‡¯*« ¸¾÷õJQARx”ÍÊ«‰m¼pN ¦ß6äVyÔÆ«ñÆxÕók¼üìjÚÜR£Wá˜>ûÊ/÷û¡°¼ã×#ÐxQ~³ëòZYéi'ub[a0rúVÒ˳D]µ¾âŒ²ÝKÚîrµÈÚ ?g®OYïK<äß°µûðáÃ7±Þ}”£ ‰P‘•wv*ÑÙP9k÷Í‹]›M+NJ¦…/ÙäiÏwKÖÛ+5”¶_¬n½Ö‚A‰a§Þ£­…&³íCUËTÇ´9 †rEžM#á‘9;ÏvÆå*xOµï’_¾ÞûJÅ:Åtê ÿÇ}·‚@½»ÑÞCë?´“Àö„r¹W›¬Wè|ùòåÅŸ¨F¯]+Æ«åÁ®$¹¢4Á€m˜?ÙŒ”­<üÊr«ºêÄF¯H'ª+…_s`9Äò@,d‚Í9ýÖ´Ñ;\°ü!×Jžˆ´×Vk-ƒ[šì¯Áe¼¬ÌN£ônRš{ýÊR¸žM¯ü¡•ª7·4Vw‡»¶Ê|_Fó§ÏÌ¥ƒng]ª8Dzð†¾T8d_ÒÍ(qy'2«ˆ²P%=•'¬ca—P2\/OŽÉ:ÓZµ/f×f!@Ž¡{!]þ§?ýéÕû÷61íý¼Bh]åzX85žT)Çña@›ÑË×b‰…X^MÚÏ/H‹˜Î.ÇžÇ}ÌEò¬ÀÊ^GÓ~¹Œ[èè¸,¶xý@$=—XØ1ØBHÈ¢‰D—Ÿ\Ü Ü¾_pKáQ&¨BÃÖ4R!‰PqßuºäàX•°ÝWu¯©‚cg94ëbÝ{míÞ¿ÿÀ ªI[Þµ5Y7á¶À-ží™òÝÛ²^ýþ’q¡uW²r äöÌhhi!$ŒFnÔï¿ÿþ‰­>2q«„kæáãÔ‚:hÙr·Ä¤‡Ç¶ƒzuùú÷Ö}Þ.Ÿ±ë27ÞËÑé—±ÚËq `›=[—ÎøvÞ=³B„¼üM,, ½çl*]h,Jx;ë²s ^¥^÷½-tLžUÏ/½ŸzïÞ½{™Ò\â%}~Ï;-$qy°5¥‚Wmg¼3)·jãÑ \¸§åV“ßÓ4¡]©ØÖ£æ€÷¼^tJá‹ ±ón]¬•a®d3²¢ðD;çî;ÏÜ&Ëkðë™Ú„4®CŸï”Q~Pß]}öz¿Å³Š|x@qˆ<èŽ×hááJ–?µ‘;½h à¾ÿB¤}ï¢2ú]¡g;Üé¤w“6ÆÏŒÜ5~>}fìÎ^ÞŽu%_AhñövÎüÒkè¤ÚKtqß«1¿ k‰MãZ¡&bý,tL< ’V¶*Oˆ[¶+·óKº–0ß´jñµDñ·_¿~}ð 1À_PºÇušì8¬ôôEL"$!\¸D?_yBŸm1¤«1q`®Žƒ ç%Ù¹^ è2+³+äqúr„ðgˆ¸Fdô ’& ÑöqfXíM¡eòÆœrn÷Xb±›5»  ®I•’žîË…ÝUèÔ]^ /Ïš­Ï^®]>ÊJz&mlxtZ,„YwŸ: ô~U<êÙì Ú S¶RŸ}^µr§´+ç®Ê»ñf/+&Û+ÄÇ$Í"Ï„³.`Ÿ\ÁX˜ðòÊÖÜx%ÏåBl¬VÙFÇÆÒΤrî+“»F©þ½Å6Vôè1¡v‚Û¾®s.æ}9{ë#Ó™ÒHü»Ó®öÅ&óýá’ò…å] ­;çiímïøõ;+V[<¿êûõY+ ±~ ž˜öž[ŒÏnQ¥:çªÕ-"D.èNdV^ùÊ®Ÿ¯|³9ÂÆ§]:MYÕAi-—³·ðªšBí¥…ž)û­âZ?/^¨X«¨ÅÿüÏÿ<è»G” ¶Q¼ÞLkê(Ÿ1ÃÍÞõzì,-¡3uÝñÒ D"­dùJ_o0ºˆ«8R¶»¼Ên ¢Š)få¬Ôtìm'¼ Ôߺ¼4å“/Þš…Êqá²U{±Àë™»$ÍfÄÅw&WÎtU í¤o!²°…Ð&MËÙ31è?Kµ¨8÷<_þBíq=r‚ÕyQÿúë¯ɾŽÈ­ÍzZôYËqÙ B%‹<'¾[-GFО)›^r¼'>%¬¯"Íd×xf¼Øxu¹×+*ãô¼ÏÛ3é=¤«‰Iï±MhMŠ«Hl $ĹBF÷zùˆ™rä;ÚywŠiç\uK½V\%ÇrÊIIùSþÐ6F– êdO~³a Á×SëjĶ^ë%'/­f£J~6œøl{f6GØæ€&´ÏöÕ6v߬êÙBëË‹»gZ›õvZaï÷íe2«ï®}ûj=½:gNx;sƹ Ë«—ÏØç«jVî'R`kóæ§jfrX¼ÜÌŽ‰?|øðÛóŽôrèLkU˜ÊN­‰›ä¼zAhGòŸLšqµ¡¶Q~Y1€u“–Ë`¬»ª˜öåRô÷^ª ¿Hø’B •#7ZR¶p£ B‹-^œ-Òv3ªHÈN»ØbIÝ{A$“®îó’ülß©„ã¤Î JÈaÉö:›8€TJ$T±Mž… `E ÄcŸíãÇ/0€/_¾¼úðáÃCÇA³¬ÞØcyiþ}ñÁ«R¤ìïŠD”x4ÚVÉϱt<qÝ+¼I™üy"ÜÄVî]¹v; ýûaûÏBAÚW…’"»„ÿõlDï&}ü앦—½{Úx°ž+9žþþš2’­t$_¼[ˆPkßÚuÁ/6¹ ¬¦ÓÂXZ›’/J“¢ ` ãkÎç³›­*™’úZµ7Pm„‰[¥Ü³pËõ½rÒ·<‘’IÛ;ijÐ÷Ón÷wUF)ùT¢B’:ÏLØœØ(l¢,·¾V6–ÿsÉj› ¶6_¿~}õæÍ›‡ßßf£“@ýØœJ(¡ˆÓûî÷Š™ÖÍ)k÷˜Årg¦w%ªÂüʼn‹Ö›?%IÞÏËŸ”º7ÖË“µs.÷jQkîÝ ÚF™E¤Ç\‘ ‰/_«5m\þÏ«jÖ¨‚(wªõ,Ö 7/–—Ö]°“ ùÑkà«\»÷\¨„bvOUœ¤¾Yü®'7éòGlïU šÓ›;^<ÙÎ×òîÍ-ÍíäSuíÝ?úˆµå,s+ÏÅ»%wª¤¨AÉË5œ¤ ©<•»¼\í¬Uè”0èëÆvG`Ž>íÌ Ä"¬Ï\\´Þ;Òÿïÿû@êNã~¥dUAëò]‘ïfåV][צ ¤w‰R¸Ù3¤Ë ¨8ÒDF¬o<Öj½ ‚bDÅ»¯$¼¿ò;·ïTÂ٤τµÄcå•5ÓšÖX<e ŽÝ~_¢ŸR°KðìßW&·3#GFþ‘ð©öŠ…ÎA»9vÒ 2:´oqa2%œŽì·{¼^— nÍß»Étg¦3á¾X¸e—ïÅ•(ðoº0õ6¸ vŸ%ßîÚ ¯2®Ð Î`æ¾qz­ò—E/~%Ñ;Ë®­¸í« n[á9s‹_©|ymšÀ)_¬ŠPSÐÞEyáì  ãݤK¿ •÷r5áüôéÓ+~P/ïNÇô-—ÁË~1çØBÓ”,רº½!OGNž~ekü¼Ð0…Uóng^ž‡M¥¾»^&&ÿïß¿¹W/!…ÎÔò‡$Ì 3ô\¸¶}†æ~»¯._+áU{OU€n§]Ñ ¼wl„Ö<è÷ÐêÓ·jÀÂ|½§ÚWr|þùç—fHñ¤}Z,VŒHäÀ6'äÑ®Ç`¼³•4_9x}ô„énÃn}dÖµ}§’éZsØ>93:mÛ-1A¼”v¢ã”Ã.œ›Ý˱߷cpuíœ[9ªÞdßÙrÞ¼yó WA&IÝvXûÞmæÅ]{V+ü"=ÉG²ó½{äJ<”ØS²Ss>Ÿ½‹XdǼUÅ‹Ë^OŒž·çÂ!zi×”Qéë%³)Mm¿äN½ $1ZäI/ ­yŸð§+áìr´ómq¯·‰õÒ0Ê$Fw=xº¼ „–©1¿…Êzìx¹&ÙÞØ=¿„>2[Èl'jŸÝîíšiUt9‘îi÷Ù3gB»p;aN LH—x,µ}ÑóRÈ@H¢»ž™%×öÿy¦äÀˆ-6 ï¹}#GÇ Äæ‚¬Ißų3WÃ)tlawâõó‰±^'ÄIÍ®yñ^>ó‘±»kÒåÔà$±}uMd¶á¶r¨5•ô YBº<嵯.O ¡]Ýy¿=SBŒ„íÉg”'k'ÝÏw⣢ÛÊÁË]•ï¸ðš…zÙøÐlÓ†™°3ÝçW}Ÿ½X¼®¿¿Äc!Bë¥b,Wò‚)à™t|I +:Óô¼3Uñ¿<ØU%³å$®É¿(å“—“§ýĪSÙpsâ²-ž™å+vÉ1^!§õ Üx³M)eþWÑ-ø“M} P§I+ ¾ ”63ÑâÔaUWEEƒ´7ô rwùZ]Å24÷Z&?Ègr(?Zx¥k·yñ—/_^½{÷î!?2^Év_¹¶ß3+ùÙx°ÿ*û½Òöýš°©øf¡aÂ*goÍ…/'íu·{[‚oç;̺>1Å:¡BCÜ7%mÞ î 5uX§¸pϺŒJš¯ƒ»P¿þõ¯/E  «“¹U%5›œ¼]Bë·Ð¯U4qqB+go}±„HO¼Ô§Z»’õ·3¾†˜­‹&´Æ®bÖ³ñ²~f+€±k³M%ãcù%ÌbÃÎî³¼›‘)+kl(´LHbùÑ' qRÖZ* Ñ»QdB€þéžZÎß&ëîײxb²ïì™ZeÓ-€ƒk®ï†‹Æ1Þ¨Èfܤs Áã¸Øô2OŽ#,,Ïïê„Wo&¹¢½›rðE6lsaáë:Åò…*†Ôg÷¿¯õÙ4ÊBFèûªoº/äÀlͱM©…®­ç×kV7»0'.vBØÑh3ºH%6â×5xIÛ‹Y·x°¦ã²z×nV“ºÅˆ^Š%ÏW» ê  ³ñ šXtyZ<ä2Þe¼ü¡K}JhXkçX|•½./U9ÙïøÐ f罄OC)G›â {Wz^hâÖÚ­¹Ÿ¦“X·+½‰EÒvâ ’—S÷Êì¤d™x8ú¼üB®}#·ª}ÔA¾ŒÄZ¡î‹Î¤ çªÉØ©Ÿ«\ª0œ-ò¹¯?Q0/×…ZøsMÎéž·Cjq/·*{~§Kl^ b‹8 |%µïÚ{Þ¼MÊVéo'Äv¾í> W°S¦ÁÕ\°è\Äqª œk!‰­Í6VúŽ&>î›…ù®œ{çMr®|Æ äåìy™ c)aõÌé"È„Ô)Ç*ªpyIW›Ð*ynÓi÷¥ÅÉ*P ©´©ÐьԵéžQžy›ÝÑí'ûB=Ú[ò{vªà”³ŒGJš;-[Q¡g©6+…ùz¦”g®±bÃN¸¶Ýãò¹ž*®ÚÓs›‘°š^ËSíœÄw\qáWþ¾öæ?*{«Mæ77A6ÿ±q#d•µ¼Cô­`w¼ 7ï¡kí;Zžˆûf᜞™r;ÏMŸµ÷˜`×Î}çùêZÞk!#7I$“\O‹DáSíù>ËiSwbÞËï.XXžñ®&¹Ï^¼rº¾Šo5jB8E´Ø6^©@¹fŸž©•_6V›×Ë]Ûò#¥©ÏÉŒdY/§Âh ’vñþÈe\s>ªÎ¶ëç¡¶AΗýLúÑŸW,Z(‡ãE;"k’¶ÆA‹åSYB¢^ÏîÍ"mµÀM ì o2iª;æ4Ky@¡i×xq UÊq¬-”£÷æaðrÜ"qM%—í{ÛZ˜‹îš…ö·vm–ã²£WÉþ “ÙÄC(‡ÑŽ…PÎÄòDœf­"›ciÏ”"íi}`z¶öÝŽÜ/ße½W¿?¥œÅëÛ‘Y?º=ë­´ MrìꔽÐ4¹W˹s$/$Ñæ‚Ð2ãÑòÊ.©<á )'yúÈ“¹`0íYÉþNt/IõKüÉÐî«%Q®ìŠ<\êS*á˜Xؼè÷UÚÆˆÉüî›õ&ÐáÝæÉ¶gNƒßmlØpS€CxÄ6äÖ‡F±›JîùU|ëûš¬·çå:(€aqIÛ3–¯ä2ذk­TITzZ¯M+Ï”®Ê\&ÈÞ3¾· ÎË­ò¸ ·ÎìJÅ. F˜ÊÊìng~½âÖCÇøbqn#u}­”å¾’u ) zF-dÑ;zy kB{yÁ umÒhcå2Ä\ …WÌ÷ª’Éñõï{‡{Ç_ûÆ„Uèý6¹UËÝ{rùŒ—§—“:×F°‹¸ÖÆ3#DÚ¢p9} e݉ŠpÍÝ7‹w_®u‡…J±Ò"¯¼{ýд10ßP%QkXˆ´ÖÝ7N›.)ü½ÃËž3VOBˆv³;U°Jcêå*~V)II–Ûï…YȈç_èØÊ¸©žðæÍ›—¦›í’vªàA&#´lñü~ÿ­l+×ýíÀÀ—‹°tbÖ+D<È’Ùþüç??@€ÔY·ã°ÞVÝ)s­:•d6!?ÛYÙJ92îG§v4Ä–Œ›X¤h’’ÝbMÚœB^Ƈ­Ó ‹u/y „+ìTÂyÞ]»ºkšš”Õ­¹4äŸy4ÉÓU]ÏÔêóo‡´±r04§udóvj/îTBÉrer…r\ñDXœ´*á Šè–l¡²œ½u“ÞÚ‰»VA©ßß3·Ê¤ÉËq94Ÿ>}zp÷®ÐñL oئ’k·FÉþËwìï•vžYa•åô­Üi÷„*@ƻΜ>2k…º ƒY§í¤«Ý7Å+¡´b®ŸÁ!ZrñúBQ,4V àâ2´Î&U[¤í4(kã=§$ºF¨&  ·”ð^óB(˜EžÂ,òÊì.Û[f—Å{æ*⼇NѳkE"„•}úôéa˹[x”\N l÷•ˆ§U6¶±"á\R¸ÏÞî™Øæ€™åÔ©rØ÷iB[씫`Ó¨X\~c,¶ ´›ËŸè™{½>Ò ôn’¯xÝcú©YÜ·¯T5\CK94zr]gn•·fi/ûÝl:­jÙNŠÅªª‹-È/eR¹å6jXÃï-þõG´q²üéKæ¿3•$ºB—åKñråæÍ6?Z¡¨…Úz×gyI+ªÚ㇪*Và\މ…c¨…®õ÷$ó«úQ§l1éKú¶ò ?»—>ËdÛÍI²Ü÷ØåÙx[ø”ɼß]5<9r!T·º”÷Löó`,¡[N³ìœÛI2¡\ß…`0WñÞ™µÛf½ÿh2kÓ©$R¹÷.0¡"+íÚ®’ ‰ÇeFº¡ Á£‚Á¬oC÷Ä‹÷Ö…®Rà&”N!.NŸ÷’±:9Ô5÷+ëçý»r«ärnwصiJ["d!¤r–x|aq›4Ù€[¨G÷Ô6Zß…Žé¢¿‘ûÖø´Ó0!HÞc"/uѳ-$±¹µë™l·ïÉiÒzÅ–оÉþ6;[ûåVirëZxíš^[ Ë+[n•0æ…ŽÙ<0–¯ gJyãΕömßM{‰î|bl”|øðá!¶~úôéeOÅw´¸¸ D&÷ í_åSá]"œ÷÷»?D˘ìÛ2/u’ç„Ø{ĦS{Tÿ¡ä™mØ— ú,?SÕ¬û¤X»ÒÕ6+û¹ùъΈÚèy, ¥dhØ)Ñ=ýßÿþ÷ÁLÝBC!ïp¹WnƒœÄ »{Ö$‰°‹h", E, ˜r‰ƒÊ¼-´ì{•˜4åç¡‹ißÅNW‰…IUI›˜v;󛬯«¯ò›LïhuÝç%|y9º!ìö4U¨S%¨ ¨žöbHWÂ/‰>MÚê"êûàfSë_2\…†õ½ôè±Ãº¦Gb“ôTBØËk‹ä]y í+á[+MžÝ§…W-<êRPêB _+b;¨Åœ [ a/ `%~•Nlß|þüù¿ÕoV†WžÇºÛ¯RJLºkÓ„U™ì”ý}“§=ëM ¤ùvHUPÚIœ—Öª$ê\Aaã•|€Ë©[]Ö& ªSåAÓ% €Éº ævÂ~ùå—Bµ†•K¶×MÚ3h¼‘°ng~ùEvÂê*Äè:S sqÒg¬¢Ðùwâa2~¹×›, ó•Gò ¼I‘?W®]hZ…„>2Þש[®èòÖÖ0SEÍõ¼âÜ™ë\£VaÄk ës8zo !x‡·÷Öï#8¦M£%]ï=(w*8¨ 9eƒmoÊVÊb xãž—+%tlM©…Sö÷·iÔ=U²¬¬¶îª(.dIÛ+¼²ªgœÓa‹@ášÊô¶o֭κ4‚’õ=vÎ{6%ÍׂÁ)¦ÖüñA½Oþɺð¬m’›û¹¶k–îß/–kkÖmCO¾£QÅb§Sr--þm$/§o¹š›W¯ÜûòÚž‰l)ñåË—S`Ãf¦v±ò²%IæüâÛ@Û;~æ•×sï襫Xd>ÀÌêÜ*Ù¹OUŒÔ wAzèUÂYPŽ%AÊuX¿¸pG‘uKäÈ4éq$_ÐQIÇñâ&eâ¶U_ð»?óR¹ŠÀM(åqth»¼ ucêN(]m·æ’´[£ì¥dº:QÂæ.¡q&óVåú]†–j…»Y%Ï>s¶U_ßBh/·U41ÈYˆˆMîï?Óç¿x í+ èÅm/ÓζfW­$¥^å^u¡ÙÝ-Ø8Ò×[`å™?Û™r,­ŽûÊ‹yGöBALh-²×mÑä\ÞØ³¾$JñµBŤ›0Dƒr˜Ì/îZ®CïÝIÜž ‹åä©€T<’d¹ÂTVÖ[‚êNpŤ u­s¾S….~ýBVît9}«MšŠW¼Zƒ9ýÈ„O9‘Q¼c§ï+=}qd–{¥—JïSïåÙÕåÚÚù^9pu‡×ÓKÎJû¢sÔ³õ;«–'ò@âò&ó;Aöû)eï] ‘ª—mF*q53m¡vZUcDCÜ…P ù+ …]¯8ï1-®BgÏäæ?KxÿòåËÃ$Ï °?}_ãðp‹ÄryTï´¹¡¤ù’ùu·WÂxÏ”SO‹{•½ä28e°ø_4Î:į,wwxwƒ|E¡õN³VÕl!…«Úêôü‡~x¥òž©€µé¼Ð´ýùrË-k¼4©ZnV÷œñNŒÎ\ë|ÝC[ˆ,dÑ)¨SÊ…4ÆñÌØøhBëùmßh?áäÏüÂi–ímÛ Û¼Ù¾üSÀ?ºêUþÇÖAA¬ÆV¿ßª»î°ØbͲ:èK:rä^|óæÍË‚,²Ÿ‡åÓ{À„²ñ †—&ÏýþJ3ÚauLülbãf5QÙi•Ïîå¸ce1¦r‚r”Ð]ζ¾R,¥`å¬èˆlU7gñµ&ë‰a¡cr°sè•®n³«¬e!s™6:vVáLÈ¡NØý-±Ãíy!Œ+˽r¦b‹][¥­-òœV9µY1aÕ NhŠ Lh¯„T ¹U&ã­ïM#Îu{¶9°ÒŠ»ï<ÓÛù¶SoÐxc㥋ÔyÅEì´Y,f½)¦ØcáMŒbÖ6õOû¦ßc—Ïø±&´J¦_rªòTÈ㢌®PI×AT®ƒM¥…K@õòòrmmüýÖ¦dÅIü£ž?©XßËxÚbýªÕÙœi¬:¶i›NÛ¨ 'çnÛÖ{©BÅXìÔÀÚÄ@ŽþEBåì­Œî6#µÂ€é•¢Å‚?·éc2¬XÀ’ýÛ75V Cµ±\¾ä*² “QAIžHw§Ü,ÍFŽï¾ë½jÚ>Vi*DŠÍ<Ö×BAĉwøª–y¹¯zöK©oe½-òZ[áS›pŠxYÅZMdWTŽðúZ­êªåôY¨,÷iayª¶ï‚O­@‡îõþcl r@.–gz)ª ®Ø‘^pþÜü¦¼Ù†šÈaÿB{^ùÑAãÍ‚Z$jõa#¶µ­³1Ó÷/èù˯TˆT$Ç&·¹ÅgF úðp¬Õçï" ©[‡v7³„°Å›”iB·f[ÊVö¿Kª$´;•ØBƤG'm=r„Ý9ÑY¹ÒW¯^½úÇ?þñð¿×ÛÀ[…ÔBÛ.ªcmµÍ­Êë J¦Ó¼ï"ú·õZå /·þ¾—ožr§ÒYןHˆÐEúní¶Óe!S`ðª@n²hGc½ èï۵ߎÀ¾·./‹B¥Ÿ—¸¼:èX sã¾Xiê•~ÜѬ¸r‰„vžSXêLɱ©€.1ÚnÍN«”^,@ Y,X¼ûìa‹;W6FÒ ^°r©Y=1–Hè$Ò¤Ímq .b—ÃJÕ¯d§þC’®—˜\ñ¾Ê\r LšZ{¥1+tìËéûøñãCBl‘Øå½j2~ž¸ëž_¥cu?w­ù ê”šÈö÷å ç¬0¼Í#be§6ÝÖcÇi–§ë+…ß™Ú&d÷•öFkÓç óžX¥@‘N:Úl±féÒÌíú}Ï”`EmÖ‡Æ)«±xUÏÖÀwáš*¶õyß½+Mµ…_h~N×m,ï=·>{0³5¯Ñ!Þ‰Írž‘ŠV£^ü­ÒŒò8ÔÓî`wU[Y‰aGl;UUÌʰïªrWÙÄÂ¥„.“:;ùâ%ïª1¿¾²–nVGŸ+±W€ï÷ƒGù·\;ǃv$„34~ì‚1iÒhuÍFM ü¼5”ò éÁãÄeuÒÅ.K:_Ÿ˜ª¼0ׯ}§ÿApU„ìD­Ä%/è9ÓõwÍýìâI¢\(‡Rá[>[¾âù•îÙÖ|Ï.œk³ûæ’C]hš»9‹ÏU×îÏ6.L{ÈU聾úlâ¢ÝWK<–#c_>£ûÆ©ƒÞKB€Ö_È® 37NTÜW˹ëy”’õLŠ ØgïóåÀkEû[¤•g^¾ÀB|.2¿\P9w—šÉzR¬­]÷Œ¼³å:I\/¸½7^y¦þz¶ å,Ocý…„åXÜë/¤PÂBÃl ™p.×Óxd¼RZZ.¨šµ‡X b¥«m,TU•3½P„@+çnîhÓi‹4s€õ’“—ÖßÖºc¥ì£øû ¾ò'÷¸|ǦßËùóÌÈK[ÁQ6[U•]®§gj90Ëÿ‘ûä”Ò¦²ÝÊz+û½²Ú×ç/wʼøâ§&l“[Ù¡“\vø±ÿ¼6ñö‚ѽUÌ¥`°¦’n€uƵ Wå¹€zÙVŽyV¬Nÿßúyè„­b[O‚©°º.ÅAªè¦jÙþ\³,ƒd¤óÅAšX¨päféXYcA‡.×ßvw¹£Ñºl %ø¾|ùò0ZŠqaH¯w#GGܵŀSa,ú…”pY`¯b›ð'”<èÂì`*,„h“&‹}²xÿ•¥¬#±P÷Å %8I´Ôø°I¡^*;Q)À·6ª’­@’çBxZ&Yo§¦òB„Í-GÆ"пŸ¤­û"8„ÝëËÛ@_ªËÐR¡‚ÎÜ%õj—Î=}Ðõ÷jôìÅ£ö»wïŠù ‡­’èB9ü¹PU ìK À3ÕÔ 3å¾³ƒ¹S‰5ïëwu‹nm·H³¦Î/šìË­ê9… ¯œªrðB…•°J¾5–;å\ÝKAIÏ‹’yÏÜ’¶ÀöÝ$m¯GŽþA¿ýöÛ«><@ }v-.ŽŒ—å#®zÕ %l‘·¼³’]cí¯¿þúÒ]nmœF™l;©3)òYVÒ|›‘ÛHzºb}vÞs}¾S§ã6ì¶9 gONŸo=¤D´¬)ãš _EÚ%È#ôšR®ŒZ!Î= ¹…8ËÃÝFð !ØXQU¬µûòåËâd…WÖtZ?3%«’¸EœgN¾¡„»/¯¿ßÏ-˜›ž;‘q_]ža{ǯÀŠI9°±â”s6¼œà®˜Ñå!x2™Þsœ@÷¼0Þåf]JƒBã­)„“j?ñM1S2Ž0®ƒ]AÇ<—æt#4=/”±“,·zØë´]'KÒ¶›U• «^T"°]ºˆÍ4 휻ټ<7á ›l‡CÂÙ*,é6­OÌú:-3ÈUÌè`‘TìyZÖA¬Ð±€½Š0Éh]n"1ë*å¬wûF¨ˆä] ™ RXâQÒd2o'«Zg݃Ò——eRæWÖÑ B¿ûêç›´é©q dÈKsìmBª)¥pøi!‡ëRn·gMj-’×Á}MØl.xöçÐ%e&ÿÊ'/?H\öŽ{wþ\>€wƒ®S ep…Ïl¬¬ˆ„ØbÕ¥¶ÃéwóòÛé·ªaAÝ:6n,Ø%÷jB»‰‡‰Éʆ¯¤§0“:;¨—¤¹˜õ’uψ÷ƒMXå'Ù™6)[ÙMÖåf-ôÌÎúvÆ·ó.œóšžÛálª±t«.µÉ¾2·N£T›[ž‡Íƒ½ç¶ÈÛ}%¼JŒ¾’ýŸ©b±r÷»^%eNšØXøIôÕR±€å(ܲ÷˜{~}§]~£ò¨¿¿ªertöž´ó^‚þóÏ??Ü£ý}'::ëàÞúØS™ËF¯¼´…nu&l2-4Ì÷¾Ðxy*Z$,4­ßïy…÷ûÛyoî„Y…J›&ëN)·‰ µõâ IDATìTB¾ãÅËٹY³t¡õš}Zä)â=\ÓBFsƒ&óM¿»Ã¸,GXdÁr«4©]%@‹@·ÝÁú̈¨‘«§—kµ‘ àÖϦ“PWc½(ÓgFgY1ëŽV}aŽ¥õePšqR±€Ë±±òÜ.à%ßlWN“6]Æíh¨®`!áÅïhUHQ÷VõŽí|;Þkª"Á~y —¬åš‚å-LÆnŽP M“”àëRªáève+Uþrm"$Ò‹}/þžArNצ ¦l÷º Ù}WR¥—Àr”wöÙ×LtÉp+¤`!qM1¯}#‘OÅ“5ÃZ¸¦ Jv¿}ïú}¸¶Â«œÈä/d¬H~æì{—ÔíÚl·e“ígj/ʹËíû+vx¹ ÊèîÈ^È¢ïÕµûë_ÿúê/ùËËz8%õØiÕî;/W»Ë&¼%6+ùiW°¤ÊIc{zÕðLªÖÐRU³•K}Æ;“›%gïŠÅN»\Ûí>›\+ÙÙÚ·v{y-¯¬ŸÛ­v_ÔP³ø&³2¹yrî^¥¾÷¨›Î”RûÔÃ)ëÊ//Ìå’ɵ jbcañÂf¥Í‡’.yòLöÙ]›…—[ªLZBzÁ|%&/üi¡²;µ^ewz'.Ë’d¬µùÐTX5;IÙ‡Ø}Õ™±yqÀB=S«Ü¥Yè&¤žw›4{f™XÉòg°ºÍýT jšWœj£z©¬Ÿˆg¦ÜÏæÁÂxkÈ9y·€ní¯3)-ÁXªpÁšÐ.*cáå5fÌ›ÛÓ}¾Mê‹’an¸œ;y¸kÜì$ïòWÔØÙµ¹¸ JK «[Z@±gk‚kmŠWkye:KgQ¬h÷Ýé3ãå¹ð)!@m“*ILª”V‘Ä TGÁÄÁçe¢&_@ÈJj !ž$öx»»vºVâO$±Ëûì‹»vŒ½F`×ÚØ%T ü‡~xõç?ÿùküçØØ±²תyñ³]ÎÁ•í^8Â&œ%u{XZ' \=/.ôõ‘qª° !Bšw:²W¹k!>­M •úìpŠA]—òM¶WÁIŵ:Ó›púù‹¿¤ˆ„I‘2»ý¼Ë3ìðN–Ça2ñ@ Ûõ«Ãª"›cf/¸]F“* ÜÖfáQ×å'^_’¥™Š{ @¡_+å*ÏÃËϤK.ƒð,9:ò<”(¶@61X™BØ‹}Êöµ0`•·.¡a+¯l,5–+.²Ê]A Ř—°*—*Tu͉…,–(¿*îz/XÝ%:³ÞMýŽk›Äpk§äùJï¾)^yÏ ÅØŸ«é™u⢂Sñצ“"šÀ*`¡p‹dþÒgü"aw6 70ù]™…Ý9ýv‚¼þDí%j®÷Øz¥´ÎBç—çzù‰\Me»mœ(a~ät[?³½ãõìZÕðl_k·ڔ²s^st%„õØY³Ñ‹°¾\O%Ïå^-ïÌÆˆÖ}—öU“@'Z,¨8é™ ëÚ,ÌØÀIÛ"•Œå e]îÔejÝÚgÙÄ6ïUgááMŠjr/÷{ášæ+æ¦ù+/¶±"¼\x¸†Þ ×L™QÞ¾ñȾó ˜T]ºÆÚBT@R,`e3û¹J?ÉÀêû`ÇAU¯…G5îDGb±$ÌU$¹üD‘éêkÕþ B´ NbÒ—(¸î²v<„zô<—ÐUµÉ²Aªßw*°w&¤­í§OŸœfR°êÞªºàÒaëýZµ/Gg%WUõ÷ ©”Óån\©ØŠ,“åÒMhíë«låz+é;£Â’²—jÜëK£ùÞ^vØ7™·c«¤§ŠkvùZ¯ɯ‘˜uÝ  ’®®…Î&¤bÚ»øV@CÉòËÀW¿õ&pÚ¶Ü*‹k§i—´©’ÑbHó>O\³\ˆ¾OÐ/Ïûî»ý¹gæýû÷/±â•qpE&ÖdÖÄdšTZ~P ië£wSë.ü«gëûè5Ò™³(3ß.^k×gÙÔr_µ–]Îd#°b&&vÞû{ŠÎ¬Œ®Üžý_ÿú×K|WbXH¢ð*›BòÎVtfÏ”Ÿþ?+66n1™W©¯Xß»sb¤oVg^u)ãu1Å­ÝiU½\c±~c{‡÷.Œµ­öû­í;k?¡´uk£ç†rí}¿ÖG8¦Í•É>fcÆ"m;ëv΋7åI*‹.×@¹Ùr=KhûG?=vúþMTÜ—N€kÈõ~„žÅ;[#×b{Mn﹚å7Nˆ½‡:}ŸàS­eý§F°ð'zqòÌO¼'KöÛwÿüç?þýì%ŒÅò!ÍíœJ”³Ø®ÙßX8¦hÕì*¾W£õ“Ôžv"â™j}å¿~ýúem½‡lj+m]ãFß;‹ÀrÓõ'Ò`'ÐZƒœ¦™ºÓ_R°›”yAÉ3±šSrƒœ?W>P%žíõB·ómÒS0Xìñš&Yˆ¬|àê÷[¨\òÊêó›Tù÷V"Ï‘¼~r9Z;!nú±¬ô¢U³y"­«Ë„t½T XÈ¥ÊÑ¥©äòDìªÜ¥꞉]^³Ð`wNdäOutÁ•ìo§Ë Â@`µBÄ ŽIU—Ÿ—噑ýïÞ½{ø> d\²Þ]0‘$Kª„z,—AE7 ¥•ÙÕGNÌ«„µ9uXÌù…×oÚuá¶í”y&ûîz?<“KPu,^2îH¿„ÔΞêXvºì¼×q¢âôzy ^žŒe×na, •¯o!R¡#\áRZ‘ ›Jíɺó~¿ŠaÀÆ:;ç&ê—gWñ¤¢Qø‘ÿÂæúå…-v›R÷&>½œ:|ýúõï(äÑÆKC‹¼âÝz3Ù°sÚ¤¸ˆI›É¼“¸õ¸±9ÐßûøñãC'_á–Ö^ø¸Ü(§ç½?ÖÖ¦‚{Õ7U·ÒóK#V‹´’y›BÝ Š¾˜´vKx_óca2ÂhlÈ !ÊÄ{Ä©‚ñª"LÑš…Ñt¦MÀbÔÚ­¤ygbáWN9KÔ…ðô=Ü7rꌵ6VÜWM4ŶqRCL/ºÎ¤Sù†_¿~}‘‹_E¸-ò,-p·¸—+º>+6WqVþ´òÈæ’ªg¾zõêÕ§OŸT“{_aå›E*Å2žÙx¶·üj9} ½7o6÷s_•ƒj÷÷*dúìõNêÙÛ›{G/Çe½+·Q»CùE¢:„Poãæô™ÑtQ ©ZÜ%ÒNML¦‹·Éú^~$¡wÜ%˜×Pse+I]ÆvÒ„±HuÁ—ãr̵™» ”nã+%«]Ÿàâ2È…ÐlsͲ\»îXºŸ;Íê=©:æAZÌúâ$U=s¤¿PŽ…_m“;¥Í3ñú뙡ê‡2·&œbÚÝ7Ï:YJ½*1¼pËëÙ–+q^ rûû^ A›J´ïLŠÖMú‚SŠ÷¿ºÃ^†‹×/ž´‹'À6.ìÂÄ4F\‡õ…knãcyJŶ6]@¹ÖÃ"qq׺A·¶Ê'«¦·PÕþ¿KU¬}#ùV˜Ë `Øù^o›rä^© ¹C!H&”J~v7,7Kòmð*Õ ì²õ÷M4V¥Èx³——Ó&y$ Wèٖ˰rï*í«…å¹oäô9­ZÉt!ƒËóP.¾d]^Ù %¬ ÿ¸çK¶Ý§­ýЛµo|ïN£\›Þõ¢*4µÖ³BÎÍùA>»°>¿» ãePs¡¤ñâ+^ûÊ©ƒ0ÀrˆÊ‹¬ï=¦»ýò@„š?•°*×®4µRú ×\B»¿oCîR%SÝêR—2w³‘|ÅÚg< ëÅb}±Œå×T•Ã^õ!÷j¡²NÊZ‹½Í_þGÞL ,¢Dh™ü 5ìÜ{ðjR{æv_Olj-'Ï}#Ô‰Žî¥llŽ Z°üé í²&¶|Æ•±Èó÷—‹ùÍdæ’‘[%œ­~7ÓÊ+‹õ[å‰Ìù6_O ƒF eÉíòÄÏ^ŽÊvsöç›Jèz–¬dÅëKØêrPŸåLûn^Ž™pŽJµ6M6·®½nFe-?+ìn !UAVºÚ+ 9´½Z90 »[®ƒ…NßM|jûæ¼NvR÷Ûo¿½úÇ?þñrˆâ‘¬”¬ï )È­2é²H´±3n—®ƒþË/¿¼®íÒ Ë3é’ !×Á±±„òÇ’ι„va(v8 ¢ý÷Š{÷UŒjßÄã"¬¯dçÂ9WDbõ÷Åû¯7SϦ4µ²•êç÷]‚Õ-®z9}%.)sÉWÔ<Ô ¢3#§Æ˜°ž`ªÕ)ƒÛžÞX+$ñÍ›7ßðÊ$m 'XÏ ¡_{&ìhªØ&”t§çv@¯î²—£ï26t*°Äf§U—z¦²²6•œtf;sªðØÑ´ypñÒš2ö7Bê¤í=§i¤êQÆzÿ¾ÓoÏ\ûEÏvÎ×gf!‡&ûJ­¾yóæAWŠÖõòž‘c³"r·ŒwB7V÷÷›²®Â£ŸoSÊÝF¯ªlq!TÇ\ž…‘ΜÓñ…W™0º¶M¿%i¿{÷î Ó³É#q­šBj¨é¾òó/{‰?:S­¯°œ;#Zs,ßPÕÔëL Eu‚Ñ”Ó@1ó'­=Ö}Þb@œö¼ü¡•s—¾Ü_ýõÛº†ÞŠ‹¬Qüz/Õ8éîZ¤’ -Ú'å5Ô=³BaÝ·ŠÔôùk± Lù*tDN¬,·EšÈo83 ŸÒüƤkGöz'X™ŠËVƒ^22ºoÞ¼y ]÷²ÖmLÆK8…_©æ²ž»Y+÷;¥b…ž‰q_¨ˆŸR;´%ë.¿PФ&R«á~é˜ïØX\u[¸”Ézð'a3á$Wßߎ…ANþ‘p…5¬êp÷ýÛq…¼¸7aM‚°Ž†]<ÿöú*löÝwß=@1LÚÚÃþþŸþô§W?~|PÇ{÷îÝËEÖçû,‰A=TÛ“Ë!ÌE¢KÊN—…†­dùzt–UZRµ¼µÓRbÑ™.@·/ü}!‰}ç ?«´´SΊ•-€{V•»ÖPsy$}7ÇýÛáôrô½OÂ+¿}ûö›•DðÆÒž÷óçÏM$ ¤}?!ëùÕ³U¯êX°» r;ï;…üë_ÿúp:)[éé’¢õRîà™zÖTZ³ûÊxå] 7‚“C‡5ÿ+æ©“ëPrg2ïä_p±¸ÄÅ ¯Ü«K•¬wݾéy¯xe7ئÕï¿ÿþ²¶2B&¬Ú¨Ž•4µ¡ÎöŒ0͉×ìSÁŸårÚYײà2(9]ï©î*ùGkî÷Ýwß½úûßÿþPÔ]ïfcõ­7ÞÊår «Kºœ¼+™_A ß‹ÍïµöIߺÏ·kn¬r—¾{6þûßÿ¾ØOZá›uÞ½Ã×ÓÌXí$ЩAVó£•{ßfá d¬`Ü(§œ5&ŠÅÛ>î™ð_~P±ùš0 ±ÎhÕBÆf¥œî±ÖÖµë¼{Ri´ÒßgUSËkEQ$$í@ñ¡GNA‹Õ®u…’H)(îËÑ2– ã~˜Ì¬_ÈâÙ»ÜHþÂÇÖÍYS¤d1% ±qĶz “‘D¸¦Gêó;R7™^™5û”‡aU¾>2ÊÐya(5«Ö¸Äê6›Ežã?»d{Ðën@UÛ‰Iƒí¶\IÕ](¹K•£ À.¥Øâ’&•3V¾pMÚÄÄ÷šV8ѱ¢wª¡þ½…‚InÐ 9T½J¼E诿þú0AR OXÝúy¸/v_·ÓµÞN;ºóúõë<¿Ýi§§ÖÝ~É·&³¡:¨N,÷b_|më»ÅBþDŽì—(¨ô´pU†ì°®ÇÎ:¼ï™j² K:m_îõ^2º&Éܺ/vߘä ×\n•ØcÅEœ¾…Û–+Ñ…%^ÍD°€v_4%UŠÖ3+”Õdýr‹öÌô}7iêr•ƒ³r§N´…W­ÀÊ;ûû½W 3Ÿu`X¥¿å^­Ïv¾/ž‡¤ï%̯Œ £wôëׯx":´+÷î´}+qy?_ˆ´gfï©•ñ­{¼ ”’íMþâì½ñ¦¤«ï¶ÞJ˲ÈÛ†š ”6Š‚õí¾^wf¬.¡SüDHbñÄî´ˆ’‹·¦!÷’ªÞmBÛ¿ÓDf“u!οÍo¶§0‹Sžåšž¯ü²ÍÁîbï¡°BWLÈB¤sº9rú–?}AÇT&5ËC1W]eS¡¶6ìúþ™?ÿùÏß Ê«í££²h à¥d<ãjÊS­‘»^oÞcz+­7S ?Em„P/Lø¶ Kv@¬êWÒÓBƤJ˜‹x¸åyˆ-–$©t¢€¿¿…£Û¸X($Å îèפJ5—UHÚ w%&FFÕî²AÐQ£ãÁ bb·›sÁ«$»™T9}Ò¨T»0˜þBÏÔ¼êX‹Ÿ]‘90[à.ÔÃñÊô ñéÙ/ï/Ÿ5H S;UÛm)é;qé°ïÅ¿úýBõn’Ç~VîUžA„ä­œ©\ˆ•Ù]6¥©u`×'á‚õÙL°{{AUÿȃGiFñür·v'œÀ„sÙ„ª:­šæåX€¯ÐùòåË‹@†ÏîH_yf…íÏ/9x‹û ÊîtüÙ¾)~nÓHÞ™ÒbÓ/¿ürz©\R´ÆÚUÊqšÔ%]‘æ³wæ”z5)3^­,÷ÞSž™åÔu^…²öóÞå®rïâõ'Q\d÷åJšïï_•ÿ.þÑÞS&¬:Åy§"Ë­Ò] ñôNú”[÷÷Mмƒ×çFu*(õë#³<ÞãvŸ×/MXàò<äÈ„€/G¸¶{w v—DZˆ“Uˆ´ÈÛ3ùlß(…ï¾+Ö:eìoûn•õ^NßòÎÀØügÅŒôôrm6ÛÔ©Ðiª ß1øÔæ/Úf9} Ë»’õK9kňŒ7­*‰[È<ƒÂ ÛB£Ïïž©9`A)Ñ3eãÄÂA?´‹_$G¸üéY¼g.‘-ó-ùCú¥-ÇØXíï7üp@ÐÏWþa2ãÿé˜É„u½R ‚ sQYb_Ø&UmÖÅ]·ò<.Ìú^0%9¢úôéLº2”UÝ"»pb—º¶B M ìÛMR=jÝWw´*æ{qŽv²Åó+õª½›]ØÜú>41±0ùøñãCG@Wàªê „J~Úa]ùA!F[„m‘·í*¤Uè¬ÁÜ:";ñ ă(Æü:È+ÃëA5ÀǽÜ*ayZ”T5ñÔƒGÅ6 œ5uÖ×@N‘‡UtÛN•"^±ÇÁ)5sòfç¼ÄGì«°º-¯î±É´—gEŽòË%ãB€l|ì´ÉU¨i¿\¡wãÈ=•C_¿>ü~ûÎ)ª0K–¼¼.B»±X%?Pû÷…u&WÊUèXM'!‰Lƒ(/Þþò´°Ëg‘¹¥õ…u×ìSrínŠ×_9xã‘<ïñúBx„­ˆ»±M!™p_.—A¸g÷¤IãMçB9ù¨(õª¸2º½»¿Iá»Îy[ˆx¦Ö'æË—//¿³bÉ'Ë?òL-׳æg¶ÿ-ô¬¼¤ÆËz¡,‡¸=S‘l¬d{§ß%Ó6:SžY§C—šEš¼±MÆ/Yo¿{÷œpòΤM%c·kÓ¾õ·!WsßiÚ¾Q$ÁøPþÓ^5–oÖÏf¥…C¿o,U"¸;ÚÞI~ ;!Ð~¾Í†Ï”üŠwæ†Nþ…+9n#V[¹Wíé±H[ †åžwÇ÷»¿ÿþû«¿ÿýï/ˆ‘m¬´oµˆÖpñ³õ T4G>TÓíâ†ÈsCÿy€™)ºð©’Ékê "ŠÉøN%ÂØæ‚ìA/!«*__ÉpKí€tÐê’ˆÕ &<¡Ÿ·iVZz±~Ñu®2 üJ‰>Á*šØ}^iF½ ¯•˜#ÑJ‹Èd+zfqðùóçà¥h"·á"¯"œ‰G‰‹ü"á õ(i o-~üøðûí+¥ô…ɤ ©Úžç)ˆÄg90+õj!³¼3’ZW“6‹o› BMz*€-•4ZÖÚÛ1ý§?ýéÕ?ÿùχ¤ÉXî”Ô{®÷–_ˆ‰ÇŠLìÚ,lN³Pau‹ªX~?c±xc±ñÄÜ„¸3gÒ¨?‰ÍÌ•’­ùѽj1Ùg yŒÏ¨P’gNåÑmV I4ÿQh¥Bç4¬YR¸PV¥§ÍoäýD¨æ@w_g¶¦ÀBÃ6‡h_h3 á¦Í½öMñb 'ÌËÒ/­Ï ú.ÏÕ†š…ŽÐ¯þ¿¼æä™¬ü","7GpJ*ZhÜN%z^E:“RÖDÖ"²ßJ]¡Ò]ø÷¿ÿý‹b6Áó­Z#W›Ü M3ZV µ¡Xƒ` 3Š™’ýÅò9Æî ¯zƒ};ò7wl-qYÈÀ¾Ð•ü”ðµN×vë._U±<’Oݘ °‰I„¬ÅA¶Ø;~¼üB,¼<•µ\ß DÇÚäÅóK(ï‚)è{¶.ù’»9¸ªÓØU_Ø\߯ ²µµˆ³»,ŒÆBÇw#¾ÖÎýN³>%´¬"iUÑœ¨ØÕ“«P2-áR¼ cýÄL,&cÂ)Ä}£¼¡Ýe®Ï¶¡ÞËÊ+Kž­@n=×,K¼¾ÿå[¥J¢ALã´5RÝNV°:=vT`‘#cpn_Èõp«Ù5éóçòLš„õ^5Y[ÉO9,ûsøúÐè=àÚŠIî œÁ‘¾Ó¬…Á¯ZÞÙeÚÚÚA꺿†”+1Üß¨ÐØX®9±k£ÃûNÇkœtfVîTx”²Þ&ãB»§\; ΛZôû«F׳ïÅn“h ó*ÖØhí7¯äÀ8vµñjy´MI{O6ì„w/$Ñ;ðŠÕÆ›±È»¤¥]»õK3Ù¿LfýîËgtbS#Öi—ˆ”…ʪ^ê{S–Ö;^ãg++“ë{Rj¾ö¼gV^Z…ήÍzô˜SËËcÇxã{ßf¨æÅž¹ÞÃþóŸã•ö6¥4y•¯Ødÿ™X’•KÌh' %8É3·“{U»Ã=3o䙌o3Sµí5_¯—2³>3íiMË/.n•°5ïÉÿûßùUÏî´j•¹ld¬þÊjÛtÚ"Qá–5t_-SŸبᶾSòÍÝlb¯Ü»”‹}ïí‹åôÕÈðL(Iî?‰]†ß—mÉÒlØYäy­È–!ÒÏîpãwôƒ4ó*s)ÍVëàõÄh³î ±ÛªbÉN\’ìt‚Ò貃öñãLJ‘VHßýŸÿüçKBÕˆM±€íH¬¤g ®‘™¦‘'è¬\ªÝËs»9šëÕ ±Ù"OøSòN³>}úôDß¾}ûÍåìËGR ríü›| _R¶Ûi×úF-T]Êd{Å$³u°„À꽭Ѐϼ©wøåË—ß%ˆû>^ž)žXðî帿/﬎„Þäº!v·u 6¡:¶ß›.äƒ+MŠÚ7vÝ’¥¼üB$YšxØ,P `;¨—‚²Ü^ M!%Qþå/yP!2)kj`]#1á–á³Kæ¬T¬¿/”6˜Ëv…?9™K¶Û­ÿ,7«3SLòr•`Zb)”¢Ää¥sE¬nm—˜l²Þåäž^ž†*cíùÖS(HP¿kwA/NŸ±z}#,êôuX¿3'yí«7zü×Ó‰«q l¼N©ls÷TÏ«´´NÚzø¬Tþz^8Aîû5ùhÖݧr–1¡ïÔUùe7ÚWPGŒÞËå­d¬v+ƒÄ'„Cg^EF%ËËœ®; \èZk³¥…štå×QsÀIbùMH‰~.bd%ëÒÏ]»ö–J€ò‡„ï=g<òž²¹p)¶]\ÑUt+)Öd/!t^Þ•†Þ6¢šBË IDATFJv:XÀÚàÂ=rzö7oÞ¼Èr÷Ý?|øð úà³ÛX¹/’ýÛ»òDü¹Št«ökSIDÌRô¥Z£w•þ,Ò„ºÆg\U2fÞCÝ¡ªŠY@Û,ôLÊÝrÚµÍÌ ©þwïÎçë¨Ö«Ñ¼Ðynk&ú ̬Í(Lf;¨v4"Ø[µ_2r:ë:zÝ‘{›Áñá’ª×tñ¯ýë«/_¾¼|†ã½%¼_ÄW'L•­\…b¬´ãBŒÖ¼¯¤Ö²\‡Åˆ:•P©¦.ãšaIâ^r¬úø]@‹WJQ•d¹uÒ®:Y¡kBªÞÅ­ÚÄ¢µ[úöUcå>¯}³’A¢VH³Ñ –'æ\ï¥~§ ©SϚúæ¤ñDLˆ-.„©-®Îúò‹t~Ö!-HiÄ*Ò vI’¯¾þN»\;E&Lšv¤/ÌeñøÂ· Œ9¡e^ÆËópšå;,±›¬JbçÙ‹¿I_—Šð&•»®x³IÓ«W¯^p×6œfÉ©ëóÛÓÅÚbK#w•t4¥l_®À†˜íÎT0‘:¤ x8ÉoJÙßÚåD¥ Ñ"P¿y"Âüøý÷ß0ëJzö;ýþÆR•Ûw%¦6f”Ê_NŸü¢ÕÊr;‹7í5÷´¾jJÙüðŽ^_ªÿþ÷¿/|€~¿3-B‰ágê}v®ìþzÏ­:T~Úì4É„ò÷ßõñãLJNºž]KÖ_¼}I™ ¶Rú 1F#»Øc,­Q²{nUUªjBYÌ×sk娷ëïKP>.Äg½›´PPœ`<ŒgåŠ' •ÄpûæË—/ߨ(óÚ§Jå·vz‹(ØS~bÑf&Gwצ}å$ÐIâú]f ÂAÍ14 ÕkÎd=YirÝñí…ŠÈÖÖ¦“Ç…ù®)vÿĹ+—î»w·ˆXÉr߯E_ϾÜö µa bÅæÂ6ôþþM1Só „w ¤Ú‹I“Õ•²–býĬ÷ï:Öö…IÔ³j:vë´Ùz Ï:Â46+1X<~]€¢Äv.l±"»®­°½ K4­ »ü£‚œË±¸µ‘l/î[S%‡£ÝöÅ&MBˆâ¬s­<5}ô‚wÞïÛ™÷"–ðiû’í¾Ä䉈_µÐ0!½bxïÊËm¹W_¿~}àJdKK/?Èn޾Âl6ˆ i´ÛÓ9Ï®â‰Ì5ì¹»\%û¯‘ê*šôì6z6§)Ë+[}}Ýé…õé?pqXšV-ÉRrí3îÕNQ/!ÏÔ3™å‰,@¹SãI—ßÖÝwË;&,$QÞ™²ÖVxëvÞ×ÜØKFÿ åN]ÛURêº"ÎÄA¨‡™&2Æ€…ùï¶ù /Mõ)÷ÅÆ#§ïÂ\ê` õèL)­Q¡ÆˆÛL¬9°˜uaÀbÖ•kvç=æ„×xÕ³Û\0Þ˜xe• ª ­¼3“Ýοf óë§ ïMøÔò!=s+õº~f T(vd|5•D»s_ ©ôÙu§×À}ᙑ·ÖÚ­µ†‚;+F´êQË‘YþQ±x%€ÔÙPÛxe¿å+ }_¯¸šƒN-V޽}çTÁ¦“ªg[Ȭ‘û )\œ¼Ë~b¹Wž9%†…í¹ï® ±°¾1ÝSþ\A½™œükà2Á†œÖ{æTUÝX*RÉÜR«SN•þZÏ•ÿá‡^îž ­ãïËÃ}ð™qÂÑUA¸ÅÂX$]« äØÙî°›ùR§ ©z×-°#y_˜ÉxUõ¡bR%m»ÙÛ^^vÖ%Ú¥S V‚hÏ p;Û µ€Þå(–Ðî‹Ïþõë×oFúu[$*áÙ³'õë´É¿ª£Wñü^Žx¶å÷áQ±DYʤÓ.©q/˜…r8Ú\±€’¶ ŽY×`]н ì´y9 Q…+8‚ÏîÔAYoe+/iGÏÄíœ;µXh™<«ï¿Øä&6‹ÇWUl ƒh?—è$R’cØàå]Äc¹]žùÖf}¥lŒ smâ‰Ø54ÀÚtºLÆ»|„–Jð”XÜ{®ñÒÿ—¼òÅX©Wþ.[1áäôÉqª DÑév ¹kWSª)ž—§ »gì6q,²L ÚÇ?ýôÓ ÄªxduÅrï±-°…±t¹ËKÙ¦—ûB8ç ³¨@¹ð¨þýP½[EgVž¹3±›}ïŶ…(/¤†œM£b¹gº=­w“ȉUEªZ<´¦«ÊêDÇ\D½›F‘ÓWÃÍüÉÏvg~#ò@è«ñÈ}Ñ»”ï¨ÈÄÒ 6ÖvfôÙ“—Ö¾p*"ŒW~†™½—îAj½÷èÍ»ÃF9% :f£WIõå3*.²"Jª¯©äªñ3D”4ÝÖ—*h}ß=–˜mäv&–C|‰UÜóu_DÉØßo½ÿþå³äü­žÜrï|ï Å,t*º.[yï«®yúÌT½yøKÛ [R·xý•‘{æˆ,©i7‹d}_¨ãÀ¹[èüþûï<I–:"{ÙéyÑå¬WÊÊVÚíYuªuªQôÙ…v­ÚÌ%±§Ì®„¤k'<=»“-”V*ÖªÚ˳„Ó1¹5…´ãѳ©šfÕ.¾Vå.7óåR·'wzMØ$»­b›…H¯÷®WŠÎÝŽ^wl- æ*òº…I¶ë‚ð õ0ñX}ýkä¯ç…&k^^êÝûó-DìT)!,¿Èg¿øAb‹WbxqÝËKSÙKÉN;óŠL¬Á¯PX“–•^(‡*áo ÐJjî¤nenMª¼^¿~ýêÇ|Iûí·o$?Ýó‹Yo¢#œsݦÛ#—BgnU„ÖI»s¥‚£\ !Ì[ _nÐÊ'{YþôÓOÏ»r©®|Ç•¦Þ†ÜN UþrÝÚ5±‘_dÒµ“¶õePÅçâiÄÿqJâž—[%ÌÅf‚6Ë{[¾@¿¯Bgòé3w{Q®kûÊ{@Å6c±w¨|ÅË_¨grT³ÓI Ýßàš‹×ßbÁxg~#·*ä€k×=¤èÍo”OV­NåP§ï ±±!·¨ Å”6ΩWÜ¥@·JÕ×…`¯¤¹ù‹ÞKí;ïJ–'Àáùÿ5múÿÚ»·ÝºŽ+ Ã’,Ê‹r® ?’ŸÔ'A‡v”«Ÿý­¡Ú ºÒyó°w­ªYó0òÄ<3Á—N ;i+öטñÌØÌæÛ™4'ií:Ç›­QüN³Ì›×MTÅ6 rÏ{¯¬ ñDèür5®)—ԢЦ–ü"• ®Ûdßµ©@^ˆ´ÓûK1S€DÎPnÀI'ÝŽUébñVžPÜõÊð.ÌÅÑ«PI’mˆ=¨VámV1éý-'&Jè©ZæˆM#4½VVöò”Š´[ãX[ygå íl[„-FÔÍ"©[~‘Ó¦“„ž]<5âOæ|+ÝØah³n‡S‘8È%˜ºvâ_ Jv—]%9{æ[Ä©Vgw× ÍI¶ÒŽ©˜süIƒÞ $䪒‰ç×óbáv,Zç: “•Å,¡7­±¤Ý“íUÞúôlÅCÖcG(›ð)?›˜tá'ßÕ§L¨%çšÌ¯<²ÝgÌâÕÂêöç#'Ïd~á %Á7v$oÂ[€—swÂe¯lwk'$q×FþÑ:ÛA¦»’é%KÐlÚµ0`¿¶€–€Z2Ý>–#³¸j›F‹ç·HëLÝ’õBÄi‘„w•½Ö+E©Xÿ¾ ¨â$ú:ó=MêL\¼ø’h³QÔ„°ºö`ûBOŒô$'¿2·k°Äå&ÄŠÈl!"omM#=—ÍÖ¨}©Ø€ïm=xºãË–³g<:‰Ö®×[Ûu8ß)£œ>c¥dÕ1WÆw¹Wk_á=§ò–¨Œå•O<3kzm À†ñä¤\*„È}¥µ†ìÙÀµ•¸Ê£«wz¿ÞL )kÛú)ÈcÑsÊý*ñŽ^o¦U„[îù‰ã™TÄÁµ•gf³RÚhötθª°?¼c[ÛîØÝW;üðk_ÙP&üÖê´ƒ–yžÝ7£˜õíòy¹ sY¸…CÞ%bUŽm˜Fò+½˜ªO£Óu_í˪d6»m‰€º¼ –$Y9Iè‰]!ñún†:,fÜ€ïÏïå©*‡Ézß»T¥©ªáˆ¯ì´¬Ž‚AjÕ\êÈ,¡½ýçÚIæ¿P 1 Ê•:’/Ш¤cìóÔQpí쵯ڛbP%œ‹-Vb;ÛÂ5=ÈyØ…Û}%¼É‘zIHR®ºËK$.ȵwÂ&{y®Q˜Hgj½›¶K¨B“xUuú^¥ùAÁ¦*MòTå1Þ¤Ï¯à…—g#w‹&×¶µ[(¬'94'•D'À›´i)L§/ñ¸ÄJ£ÔM8‹G]®k«‚T‰Aß³Éx¯ë å´Êæ€nÒ[Z¨,Ü`‰Å5ær*Ò$;M[©X¥¿-påqKל¯}qšÜwæƒjXȈ1_µ:ùG 2Þ¨¬uŠ7›{G÷,Vè@XÝvÎß¾}{IÆ=sËg´È[/”m˜) œ2eÓþöB€Ö·òòO|F‹<§ër)Dè°<Êfãú¡ÉZÑ™Þ{9‚w´\÷…Y}¯Z¯Rચi˜¹¼´%û·¯šŠô^V°Gçͦððõɳ)ºx¶<owºž}Ä-õÌåáªÚê=å™ÜüJ!©m´ZÄYüËR½;¾ß/Òi=r\›öÂÞCæA㋃ÙX°ªb¸û&î¹9Cù‹ŠnN¿åï´o•cå¥Üûú™­œ{±þ–§W±Za– gÆÊÔ¢r˜îöšÛœ: âu¯PèMTÈH‚ôC¯†¼ªaûÀ–€ZÔ éÔ`%þÄAöPÖUØ„VÇe×Çd¾ªºéAT  ëˆÛ@±ä܇u®•ð.¶Øª¹äEe/ǃ%/ëG"vYÏŒÿIúUZ'^_X´Î~wûHˆÎIC>ŒgŸÍçþÍ7ß\àÂòz?ýþž[ûRŽ>1¯RtSñD}}GîÂ1M”äf‰ù®á噹_Ÿµ¤jU†ôvÚ‘½‰ §"rä64¥ìÌI´À60 §0ñ ¢ÒžñÆiÛ êÚžkÏ÷zÅ‘ÏíóçÏlðëׯ_=<<\¨Å«¾–$aÞ"oÕìäB˜ˆtyöùU{1Ùœh­å:H¢t'\Á"Q¾_‰…ñDHckQó@ØSÍõf:y8³KØ]à„Wø“’åþþÞ¿M)%=ðkîg¬“CÓžÑëÄæ‚܇âAÿ­XÞÏŸ$ËÎiì|xx¸@7NÂ0íkåPv§6Ý^¾bŸ}Õ©$´ûÜJ’ãÏ/œfÛÝ•G¢M€ ´ÇÇÇK·w 3k¼¬(޹ 66ûU¢î¤¯¤Íæ‚PØ ì~ŸÓ$ ëN;1¹EH/ý 6g~S¬_?›VN×å#.X{Œ-´¼KD¬(²jyúÌè#s‚HwG×ðܿݾ‰G²‚:'¾ár«þ½gî$üÒs3±Qmѹ¹§ÓùT{o;I´¹„÷λy¦Í‹óže9º½o{6JÝ·vkcP~«‡àŠHøþår©*tÌ ±¹¡Eð ˆ­Ñû‘3³ªJ/ªc·{/O7o1$DíT ‹Ô¤Mb³?Xœ:èKD”xe ÿêå¾ò‡J½Š¯ h[ik«ö.“ì¥&m›p$õYe,æ’sMö…+´¶%eIÒ5QæâÚHèÚNÖzðt0]q×z8Z­Kh‡vÕ\  õ¨{¼Å¾Ç"Q|í‰'ÒÚ-Hî“ÓÅ]Û=¾%¿¬bÜ:Ä÷lú<z᢫˜²cé…$*驺TûB’µ…Л7o^Ýßß_ΤpÌwˤPÏ 'NJÉÚÍåT µӀ®3W<Û)¤" ’o“.—A5»Ó™³±Òb¨ßH°‘…²Ši·Ëg<ònq‚­¤§ïu“}^&M}þȰ9 ¥ÿöÃ?\`sÉþ[g&®fñ¦©êŠDœ<€V £DŹS…Êå•mÃNu¨â•Ãå°ÜRP2–šH,Oã„÷WEÍkw…áON»N°;a:ª–ȹNl\[M­U„Û„o;çòhÛWÞSoß¾½ì+=Áœž/¯Í=ï¬?’jzËc n ¦µµ@¶)¤Czù‘ªgƺâîB¿lFZ¼÷wWXe÷ÕÓÓÓÅäÖ¾[®ƒŠ•¼ƒO±Üµs(üÜ)cÓä3Š Y 7±Q$Bµ]ÏŒ¼³E,¿yïØåWŸ6;R5Ò†œ’çîKãª(¶o:´Í‰Ž<Ô“*ë¸ÞsÝ‹ÝñN]…ƒÖx‘o¸ùQ¾VrE’º¯NЏ 5UsHkX¾ã¥˜Ù™ ºÞ:ˆ–8¬ü P@—ðÂhìöxAwX™]ÿ-©ûd$¶Qƒ¬æ{VŽºÏ/Ô¢%u(Ïn (¸•éâ ýìëÑc'k 5Åß ÏRG}½t«6a¼åã"†S¸ÃJ7®ˆü • -ȼ{÷îy/-Þ~%?•¢]î–y ¨{A, sÇÎ[ÀŠ!½“Y·5ç[XÞ­©ÂÂ$m÷ºø\ÿ~ŽU ¨ëí¤$úBõ™QÂØÎ·Éò’0w¤~K à ×g·øoŸ Ç\8@‰‡#û’6S\Ûu€?ùIö_µ:•»\›QÅ[!M§.ž—›ÞJ}6/ˆå§êÒYl/Ìw!‰q³„©€´Í…“´ô^nikÚXíÔà„›_b¿ñH˜Çb–x­D±S‹[ܪýìKêVdbã‰Ók“ya6òDØØ‰ÑÉìÓ†ÛJݯŒï=¸¦fŸÚ5]äÀvoÞƒ[H8}¿U /tlýÎ,âÖ;©3#2@¾£Ó,9ÂÝ™ž) ïŠÎ,SŒ¦Öò4¼Gl9Á-¡¢hzep-4¼g×Oídˆ¹&³+u’{·ˆëŽUò\xwwÙÅZU_Wùj!΢ül&ÓÊËa±qáTAye9y»¶òH–Û=²|ƽ§lÔš[ªk¬m/9Ñ9ùðÉG\Õ×[ÚÍ«o© Šâ ‚,åB1¹éÂáWÍ×"ìĹ“ëéÚ]&3 GXÃ'»1U†r%ÜŒɘ¨LÑ"Ø¡;,ÄG¨Ù‡.ñþJŠ®Â’pˆU¦PÉÆ.^…– ÛÁ\þÐ:úôò[cB?»£Õd1íþšXìTbGîš8nUîfÖja'Gc90[¨¬b›AÐ.£•µs}tk>‘gO1¦â,]kŸ»¾ ®­Ýa8^¾&Fý>½™N I]žB5Ä&Kv;ÖW*ø“…ŒE ^(òHú}ºà&;,meâÄÈJU¶0Qk®\÷W;Y*áØq(ñïsÇqP=J’ã>p»¿N³Jú¼%mÀÇÇÇKâ޲€.Ѱñ¤Ý$e)·[³B ë/$¢‹ÕÑq`'q*Ùì´K¦ûj1ï%þ>/דó’}½Rü·0–V,è£üàɨUÞÕI~ÙŽDß³~ áS넽Äe»|‰'øT#õÖ²dÞµï<É;[¿’µAÔ©†‰EÏ®3×Z,tl‰ËvHÉÛáT`à f}\LÆ{%ó¾n¼²€¶+Tà kßå|jNó<kn\‡TÒ÷NdL,‚í´éä °ÞÁvÜž–ßÓÏ·6Ý#%ûbÞ]KÕ¥TÓ[h›NÞÂîN!;˜*¶vÆ;/þ“ic{NˆÎrî–<ÛZùz6B„ÚW½ÇÇÇçg%¼ªõØ}%¤qï9 3…ø8éÛî±;ÅZã‘ÝZwÖËÍ=oCpã„ø’y‹À5 •§b²ïô¼{²x¥:•Éþ*‹)x#l]Aeúm¬Ø°êÌ9±•ƒ"·Jï&QÂê"}»Öú}þüùyíú«–· ”=;ÿ‹X–×Sg¾óPÞ(÷)XÞ6mVšZ.¦{Ú;ØdÚd|}ôL€è获¸X¿5÷•ð­òÇu¦:§«<ê™[ÁõCk_É¥Ü&´jv U]n¸BTíy¬›ÿ¨ži¾#ϵb£;[qï©È_¡„“9±PÑrhãÊ[»±v{ÔçWVR\¹NÝëR.dZ90›IF[d¦B*09®T,À ¦Ñ¸úú+%{‚_YµŸ`0‹ÕÏDyØ*AA« «Ö¢ªÆÂÖMzñü>·íT™4õþ„r¬©£R²Ž-Z…Ьû«| ê r«³ŽÉ­ý^žíNÔÖ|OééÕaw´êů"ÜrXN0™[˜s~›B=„vµ6u;¾†YWdB¸§nÔ«öb§]è—ûÂ)©Ïj}!ôyQµLH£¢UöêL>==]x }ËÖ$£„TxÔž9)ë˜,|k Xã‘EØ’®MÆ7}öÖNÈከ^ÕrÒ·úýkÒ&1ùe•´±zMÆwÊj¼òr³Ë'äp}¥ÚÓ5Tæ‘·æ4Ky枥^() ª@YÓi•»Ü7M UpÒÒ=*¤ñ$!¼SÔOD®‚Â,zèô\:3¨=WÏì&eN›è(…¿2ºÂ³T—²qÊi¬vߘ¬V¨œºÃ«üµÓo;ùë×±ÞKN9·PÑݾóÜë­½?/|ª °Äbµ|Érž ¬+¿ìï=S²l¡´"6™Vf×Xhs¢÷ØžŠìNúœ{&—'b¼q_™:]wâã¾vJê™[宯Z»¿3¹ šHžTUÄ\éé…+çžY¨•Dg´þØ×Í ÷L)ØsZ›þ¿w¨Ó÷å~·GÍÍæÛ[®åzÁ­‘|gRî˜h¹ë¢y„,v¦”¾^Cñ —ÉŒ—«^tÒÅ9zXÄI:¶¶³-ôÌÊ2˜‹2½J‚®2Öâ¾O¦´`a&¼Ê3·Hë³p;*ê¬Ä*¤JŠJhõ é"wmJÚôX¨ˆco§]vS• m‹TmR¦ÒΑš&iîçèÔdüÝ»w_$«öâ帄—gÝ]…–D¦]¥½Öî”t9žÔ¨ÌiÚŽä·i]4ysµv0M\K¯X€ÞI‹Üö|‰Øû÷ï/SÔȹÉ¥>õôôt¶éia‡T(I U{ÑÄv!‘q^ v w’§t£j0žw}©»2ù>Øi?ák%=é&½S…Å .`Ýë%ng¾duk…¹yñ+¿l²,ÔÑ»r¨+ù),ϱóiüè…`Bi2®÷€RÙJüÕ%\µÝ¢W–û$”`‡ÓÉÚþð‡/øG&ˆâk—$¾Õ.Ê9 öòüý÷ß_Ýßßá¥âåèèU‘ Éü'bsçÄ©Á‰d2ïå(¤Ð ¹D>e´–'<Ê®{õ‡~x~î'ž‡“¾.w“,a. )Øý–_ ÆUÈb“:÷ÕºŒŸ vÅuïÚ¹6'³Ï?þñ—÷.¿}ágr¸²”ž™ÓÚ±B +ìë'̉²æÂkúøúõë/ø†*áXüwå-`c}¿ß¢OIQ%CXO å—GÛ´’Œ¿gJ¾ Å´“®øA¾…VxE)Ù7íá|zŸ?~¼À"–ó×Úéá4ß=ßç[I¡Q‹^9ù̬!æ©3¾ºý79wÆêîÍàá%àq%Ê!œ/ϵdÜ}cްbÿlÒ'¡½¤ÍéxpN½•v¢¢o•±z}§”,—[ås÷kmNÞL26/Ëoäz¶>Uç|ùŒ A9UX¯·Í BjÍÑ×ýýýå³öÞ{KxWqm‹¼,,ºÖg&ZAïÏ;¾xµ¹X6ðmr;õµá™pÚ¤Q¼ˆ‘òfùÓr9—“g¬Ž’qzïZg´÷:sŠpµÎúÌØÐ³Y°"æGÅÃU>UzZ­F5h–`‘ç4ªç–Á¯´÷Öf¦²…AP̺I“ «j+â[%¹™³.¾ÖÍèès/GU=Nrª''n‚ä^0”*K‰Ö^€ %(#§ôã:m×éªq|(áKÓ"õÿ=¸d§a¶âcÒ&¼j1óë´-œÁμ\‡‡{a,¾?•±º@|Îë3Ó! ÓÄ¢çÞ³ª{«Žº~FY¡këbÄB¥Ø÷^_Ïö…?ßTÇÑlk×åj¯@PÚÎúšÀžàñ‚ T¯¿p…Îdû$ùå`,+ùé™ް‰‡NÜ‹-vmKÚš\ê[¥¯ûƤKˆûnqÑ+¹i'ªÏcÒ%¿ÿ&lÎd]¿Éì„¶ÝÝÝ=ÃnÈNxU“ѧÆÄB®âBË*зó-,w=tVÁ¦RE 0ãIûîîîîÕÓÓÓ«»»»gB½qß§©† ïÂ-ækPÂûròJZTúSÍn'*bΕÕ^?›\ɹË#ñ¹} >µÄäb»ÝËg4ßü±›½~hž_¹Wvw‹—­k¦¬Kh—ëЙ®P)Ö‹…—/)Ü}š¯•^-ÂKí¯ä¹÷T »mJí™±hZyåbµM§Ueµñ*çÎæü“a¦÷÷ÕBã×»i;óë1Ø~Pèd/á{oÏ _ê÷hÏ`(ö$.ât½ÜV”FŽÌ"NÐ4'ÀÅ”]{¹SæÝc50…²V­b›y¨ÓáÛ}OŸ­½%jc‹÷ö|H h›r9OE¢C•ÆNpÍö¼ðð`ÀñÖ4bÕz¹œB]·‘ûE1Ó¢9b[u«îÆâí:èëb²íæÒmzU†TŽp¤¾ò‚^ ë^¿Zᑞnañüy1éëiáhtaw&e‹»¶ê_RÓ-Œ¨øÛ­z8N2»^­Ý*k‰£ìµ…í5­r³­ß‡ð+U=”ÜκR²ŠHX•»Ñ÷8M\”µôu;M‹éwym'ÄÇ &¶ØIß:mïhÖi˜†™J?@…3ØÍYöõuØdÛ ),Ï¢p90'ì±6ä•©ŠæëN£\‹¸Åó«ò£þ¾ÄÛžýŽ¥WEÑ ±gJ£V/¿5 ‹8,OÃÆŒˆ*Gâ²…’8uXèØâ®W`ã¤j&æ\µ=›FÂNñþrŸ–C㵉*Œ·D&ô¥ Þ´áQÛxY©Ø]»åÙc,ïï;=_¾¢EàÚXèôóvhí&/CØ[—¿]I“ù…w×ÕsË׆)©ò¹zfœ¢lsÀ‰Ž>3B¿­‘¤`ÎÞÑ®¡#kL(™ÿ䥲s'§;Þ¦•s ¿[gÖu§_h~k»§G~vã‘þE6ŒKˆ?ñT7(ÿñžY~Q¯/$±» æCpMý‹üyïøž±Ø†\Åßr§4G×ÄÕÏÞÏ™Ÿèíäoü“S·¾W&Ó‰Ê[ÞZ 5%Ñ7?ê½È;³)c±mnÙ{?Y(§\ ã‰òÉ*ÖŠÖ±áµ`B]=sËåÜœßÆ‹0`!…B OgJ5½òyò_ìå)yÖ *½ $»)¥f2¾r§^&¼;ÂZ¥G³;þ[Âû»”ô”\ëågBé¬Ã`'Ëd\å-²Ïõ©;|Jºè{]2~ÁRC)¡e&Ûi[\ 8^ª¼á`[€÷âv3/ÁsG«ð>oÜ,IšN tõÕû`MJäL¶…<ž0åÛÑ/äD,6)[n•——Ýaw®x|ׯ}Sb±ûæä÷qZ»>{g`;a+=­š‹ûf»I+„ ɱ7U2§x·º€BˆÖ{Éç¾ñÆ$h]Æé?===Od*Vüì“ON×[ÈxØý=I/©ûÔø ª§ÅÖ×åÛ"l1çž™ÅU«ujH<¶Ði_)*ã”v t—Àºî+UÉôNÊëD¢¯—£|Ã…±œ¤©…H “1!]ñ‘ºÃ+'o,—´mãÂ"OdÏB”@…ˆ¯Ùø’ØÏœ Ð+£ë|’’•Wv’O¶ˆ³~AË„ƒÊɳ3DQ› ÜõJ1öï=&ÌʼnËú¹6æ·ü>Úw&eq€µ§pß(!ÜשƒF­{æ½1a]e-¹¡6¡"­ßGûÃF°gªI›pM}dêºPÒµ¸»»»LxO±~a{Âæ„G)a¬x’ð'ãÝ úÿrʨk·Ó¨ •…Þ«JG¦s´²Üò¢\Øh°qrË3lÙü~ÕDóØ5!R©ÏÞ¿5‰íwŸxeÅ}ð–ïhó`=½çä2o¾H3÷;Kx×ô±Í¼pƒ‹r¥uæÅ×:–^}ÿÅ9št­r—ÂÔ5¼åîj °¥Ãº#ý@$¬¯B’D¼ªn§•[›íÆ|MŸ?ˆÏN»Ä £9©W9-[“¶%Óåû°²œJO åÐe¼×W¨ ‹ê·ß~{&תFç(ѱòî Z‹Dƒ\B 'Õb$Qö^*tú^/ˆ¡Ó¦ºI«Õ¿5‰õ ®9_…ÃJKÚvl,\aý‹”™¬lí?~üx¹ Úwš´)ù©¢\ÈN vâ£wÉ~û&¹EÏ”­ŸÞ&ªŽy¬ÿP²Ü}}üøñù¹†Ëv+Aÿ¢žÍÂ5‹7ŠƒHö(Ä}cⲜ>šFî´É¤HNœÜ­.%Ó}¯=×.»½ü,”l^HÚ оsâb+·ëcqß8qQ °¿¯Ú]ïM(‹ £ža=Û…3È7,!õ¹‹…rhKФïdC Dhez‹y6nB-×Añ‘>_‰ƒ*Bñ@Š'Åò !§úÓŸž×®iωWÖgéÌô~v_Üßß_ V'Àë%×û³q"|¸™ÅbášîÛîAã‘Mð$ÍÍ}}]´¨ §˜ÅS'.ÅRs€å3ºgœà*lÃìÇ—÷ÚsíúðáÃŽ­šoj×Þµq_vï /×gf- z½f¥²ˆ ©âMëe\#ÔÈ0 ¡¾ÀÌTΰ£!QP‹NÖªŠé0ºNÙVÝëëàH|‰„vÎÖ—!|¬÷Vªë*,„¨EqB´²˜*ñ,ÂŽÆúÀ¨„#ö·x’ä´sîx±‡hg¼µ‘¢2VÐuX—°µ Jë¨,bÕ§ì :±²¨l¬íèÕ®¿ü ª‚v ]ëe×~XUs?k·Yo_·+p"YÊ‘Qµl;¨ßÿýEÁÅ}£ê‡céf½b`½ ,½™”Ú{÷ z¦>þüìÍäÚ uê°ûBÈ¢ŸÍIŸ|ƒØžYÚ;oÂÿ ¯Ò3¦—³Øã“R §Ð²“ˆƒpN òþóŸŸ÷ôbÖ=sB"šæ…'LW¸Ãz,ÜsauwwwˆÄ“ÜûÂ`Œ7îi!ÈùŠ&Q&¤­ ¯œ;¡¬­µ˜vý‰œ ëgf÷yep…,Ú”²ë¹B 5¼,ÒV××ýìa΋I{&ýù¼P<+tðÝwß='BKX¿å±ãû¤qbgnÉ·IMÇÅûûœÚ¿í=¹z^Øù¶È;Iá;½WS˜ËJ/üüd± TV5¾Um](¬Ó*R×NBüšÐšw’Ðn‘§a÷BÄ£«ÔWcÄi~÷÷˜DaÄ5”)ïŽ×FA©mU_mr«r¸¨ “]Ÿ› +¡õò¯½Ã—-<Ü&³! /;Sr×ãP^Éž¹f1VïDgaÈN×׌tå—=¯rÇW­×)kÍ…µXß+ÏŒß~w‡B ­…Q¹§þ‹*ùyO–#ˆÜòÿw¦lÌ,·Ê/ïïö·~SAx‰Ç’šN#4Gúëh¬¶vªg+ÍhåêfV>yƒÐ’Žìò)?h+iS"Ø„ÑÊQè™ Ï#Cå ½L,¼w<¸ä\;¬Â|x+Ÿ¼†–{ÐjP]Ê„ô¶y1¢N\¶›ãÈ~µÄ—{%Œf%ˆo.dp!@'ƒ; ¦Â`Ö˜PŒè‰ŽzÛWÉjÛ%TBX" &d· ‘6jmîîî.÷TyñòEMËQbÓêRÌ$…킞¸ëë ü²Øã•­ôõß~ûíY²sGúJÛ‰:M-ÖÀnÇÆ·’ñ.·ªÆåм{÷î90ù·ë€Úm]éjáMÊŠçWe/˜¦]}¶U`ª*?­­°¼’Éþ%&ÂfÚ̪GÙ=֔у¼äÙ-ò³®ªÉ²—£]ù @&ŒÚÅ«°t*dN:ë:çöÈìè´¤èd¤Z+ér"ãÅn Ú^qd~’±=9¸Ûù’DÙ¾XLºkiR¦"JÏÂ˱ ÀæìNxwí Rí›.×Ö}ù=yP%vfRXkªÐ¾­s.ÔÃ÷º&³uýý+[ibbc¤ µֈLå-+v@€OÖ$mùˆÂêvß8}Þî°2¸mÍöÜË3dsà–Y§Ü¨ºs‹ç?yN(ù)Ìe%=ÛWÂ`|έ ã•ü"!‡ëy±~ !s¿ 7›Å#;˜Åb§MK\¶ˆ[Hâ‰ÇºžòåœýÚévŸEÂ|“:‘ßÿýeÊ ¼Ü3¹±Úfç&mØÛpSðg‹¼å Q6);qxWäN¯EÝJšËÕTìh=Áʼ'‹GBãMxWØE1#÷<Ž5V%±)§âªYšOäÈûlúxÇ—_mÃní+ÌŸ:SÂ=#:5+õ'ê½»OæÅÁ¥4Å\)üÖf›Ü›ß˜k—Ó·ˆ§šBûy›ÒË¡QMX4øŠÚ¬\ÐUú[¯÷œž^Å •‰+Òüì~/œRºË…3cÕëèp•»œ*lå¸ò€.¸x ©GµK[¼ÿL÷  g0á•оS =4t7)kƒj,xÂAÚñ\¶¸nqÓVÝbOøÚMºô&†·ü!•µÙ«¬¡l`k£D`›_Õ A; ò<ÜÌ&뼞»˜ñåùœÛÌ=»OŸ>=zzvNZ{‹B˜™pš¥<³6Ý6aµ”`ºfWòÖ–´íÄe/Oß»€Ð´öUÄÎLÏz§¤­]ïA|­2¹Å ‰ÍšÔŠç·û»Š%r£zOý¼F¨ŠL¨ø&¤GnUû®gÑÚÔŽ#ž¿3ÓÏÈÉÛb`¥«ïîîžÏT±BÉs±ÇN€½ Lœ4ïSÒ¼ï]µ? }`äX ¯g×ýýý¥CÚ¾ r²0_ÚÅëÛTšfQØûN!§ÏyMKX‹Ó½ÞþQUÞZïMa•M,ŠGЇ,Wt90Ûؤl!ØÅr!B6fVxEL}û˵éýënß{­aמ¶û¬A¯Å»¹ rŸääY(ü‡ä<Ê݃zn¬i¤É¼pïAR¸Ó.;ç?•GÊj‘'ÿÈ;Xø¸wøš÷ú6#7áüôéÓ¥•Óg‘xjvºoWr+4vš%ªbåàÛ‡N9mäZ ï„W)gÅ=Œ5••oÞ¼yuQ |xx¸À'ã‰ÈÝZE¿‹<'*š© óµ1S¬./,ÙÖLT[“z‹<'6æ°§)çÉA˜ÞÃÃÃóP–Û¦”û.N¿s?»‚C­Ðþ¯ )(²e¬µ æÜÝ"|²;º½T¼pO{Æž'3ÿûß_ýøã— v%I;møML :JÍJÒtl¾x''/;éÙ“¹ŸøÙ‚àzµx˜ö‚`Úû³Û-!lÌvmV/»¤M#ñµU¾vöMH×óÂ"­ËÛΖ˜sÅìÌ«2"ɲÄGÇx;U;µç¹U}S˜z‡Qø”Ý;BvÒœZ´çÔi® DGsqÛ†ƒà º¶FeËÍò³¯ªlz𜚶ãaÂzÚ7çÝwB^NºŸdÁUXÚµq*á™smöLZ@¯´£É…O.Äâ‡ÛÊC»öšJÜ£ò*¾M(ˆ›V@Ãi•Ü(•t\;á&¼rp¶Hî´Ê‰Œk×ûÝŸ÷Ì­Ãû 7.¦=˜Íbêm¦ZE*4ìÌ S±ÛXîÚÔp³ å¾ñž2–»Vò‡J,4rtÂ,\T['HëYæ]±SÔö†È;¤~v½VÜ7+ï,”´©‡Eã_þò—W?ýôÓZgpò’»Õ™×»Éx%_r'‰ÞckäªL°¼@ï)vNXõvZ%AcÂ+šV«0¹ù‹kcÁ-É3uJæõksm-k¬¸oŒo>[ï¹…‡Ç—d²oƒMxøé³ûzù‹ñå” +>ÁÏ-¬„ ËwÜX¿>{«¦×÷ט‘·¦(Κ‘îÕÏî”r=~Œ•æ7Ëg´q¼y³ûj=¹°SÔ²*ìbÞ¬q´BRå7½ß‘¯_¿~õã?þ×ï‡þùçËâù冸߾þ¯üÝÿn¯ÿþlÿê}ñŸ¼oþ»ûêeß½|ö—µy¹§^öÕËÚü_>SÿÉk÷rfþg¯[ì¾ýõ×__ýòË/ÇõòõòõòõòõòõòõòõòõòõòõòõòõïöÕäê­ßÈú 2˜IEND®B`‚kimchi-1.5.0/docs/kimchi-templates.png000066400000000000000000012037161254252253000176710ustar00rootroot00000000000000‰PNG  IHDR3«ÅéÓ,bKGDÿÿÿ ½§“ pHYs  šœtIMEÝ 9¹¥—htEXtCommentCreated with GIMPW IDATxÚìÝwœÜU½ÿñ×ù–)[³ÙôNY -H- õ*HÅ‹×öЫ \½ê¸¢(R® ¢\Dz¡‡– )¤‘Þ6›lŸòmçüþ˜ÉÌf“ì&cø<agæ[æ;3»ç=çœÏQK—.5žç‘J¥¨¯¯Ç÷}‚ @kB!„Bü³)¥°m›²²2’É$Éd’X,†“N§I§Ó¤R)ÊËË9ãŒ3äj !„B!öHÏ>û,J)¢(B½ñÆÆó<&NœHUUabŒ‘«$„B!„Øãd2Þzë-¬úúz‚ ™L!„B!Ä+‘H ”¢©© ' Òœ|ò9d2ilÛ–«#„øtP K)0½¿ÃQ–…2ÝÅCÛ»oϸ$¹K¢1ùó¥óÏ£ »ót>ÎNîe)À|…BìS¦LáÀ # 0X–%½2Bˆ½'«X6®ëb™¬ Çu±- ´Ï¦Õ±`ñJÜ‘‡qè°rô.'… ›™ÿöû´öÅ¡û %f5´igÁë³Ø\>ˆ cGSS=?‚ísÀ`"?4·Çˆ»¹ßåçõøw¹Â²|–ÏžÍjÏbXÝgY°äY¬Õ FÖÌÐ*ŸÅoÍd½UÉ~uÒ·¬gçïÄ8ª4Ei–Í|վ͈º‰ ­¶Ø™?E^ó:.ZN›’¨΄ƒöÁ•B6B±×ÒZcŒÁ0ÆHBìURë?ä…§Ÿg]ùQ\ù…‰”ëvÞyêïücÅb#ŽeRï<ó·');{,‡('Švñw Rè ™wŸ}œ•ûŸÅ£ãZªpŸ¥[yûñ¿òÁ cºÏ(ÊÝžîÞ°iÁ žã¤Í Ã.`êÁÕDƦíÃGøÝôu Ë9æÂóWïYo“ÛöYð“<ßärj¿‰Œéã³ð•çxݯaêàƒÑ+ËüéÏò¶3”Šaãè[fwóï†Âv÷«,ŒWE:Œz> Ì´pÏw~ÁÜAGqí¥ç1´ÒÚù§KÒºy1KÖd¨æ Þ¨·HT8d<0>«æ¼Ê³Ï½ÆŠåöáàcOá”c&¾æAn¼íLÂEém}FÁ—¿r2oÿ¿ñb³ËIW|Ÿ©c:G)Sr]m;Ëü _ÚŽ1Œ9ìΜr8}b]‡©ÐéËY—\ÍgÇV‚J4ðÄÏofz[‚S¯ø§íÛÎC7þœ×ýJÆŽƺ¹³±'‡N­aÁëÓxæ¥Y4x†XÅ`&Ÿþ9Ž_ÉôÛoæõÖ *ìüô;¯2ðÐ+ùÚçj™ýÜS¼øÖ<›Š>£9nêTŽSÍÏýÿ{~“®ú&ŸÖÂwþŽÂCøÚ|ž}’JBBtCEüæ7¿aÊ”)ÔÕÕõøK:ß÷™1c#FŒ`äÈ‘d2^ýuÆŒÈ#º½?f&„Ø+(·e?¡jü‰\xÁñTiŸ°—dYe1 ­ ¶§¬²‚ÌÒ• >æx¼Ù3˜óìŸY6âpN8ñ(fÎx‹¿O[Èg¾4•³_äÉéïb>Ž JØØB¯xn®‡RmK?¢ý˜£9c@o^|ñC^›·Œº¾ýH”—Q–ˆc)¶ú«,7?‹¨‹Þ¢Ž ¢b#'³ïêçY¼ø}ü5ó C8ä@7_Ê`P¤ëßç±G¦Ñ6ìpÎ?} ­‹^åùçîíÃçÆÅ%WŒÅ¢™ϽÊʶ,G@¥±d’¤çëèY*:ré8/cБbÀøãù·£jIeíÌ¿óÜÌx­ï0Î:bªh¾J~SK·1÷Ígؼ0Xôù; F,™¤,L³AE<™$–‰HœtÁE$ûT±nÁë<úÌLúsç«aéÛÏòüCR3è 9ýÖ=ó4‹ƒ±œsîÁôëÛ›_}†gßüÞÏäÌQŠ™¯¾Â³ÿ÷ño\ÇÑ'œÍÊU÷2ë™Ç±†§Y˜ÊÙWLeŸ$;1ßH!þ58ŽƒRª‹¿—†0 »½˲r½öJQ[[K2™Ä¶íï' CÂ0ä­·Þ"“ÉÐÐÐÀÆò Nûl‚'ÖÌeU}+§žÆgÝ…|4ÿ=67m&ígY»n9í~Î>ëd&õq‰´&ÒeÀ˜wÄÁœrìÑ”gkùàÕhiÍnsV: P–Kú£Ç¸ûñå8®!HÌ•WK•‰Šz ò'©Q±|æ˜aÜóÜó¬ŒÒÔu>û%å (Eëʰ6[Íg'ÆÄ ÃI÷‹Xðþ_øpÑÎ<ð`ÆMèËÂWŸ ¡­…².伯ӭÛ8?³å߯\ì`=3þ>ƒTy)K‘il 0ƒpKÂé3i>šû& C VŒ±ìÏaô)}\Çfª¬s Gì[޳|0m!mʯóø /Ó‚•iaöÊ,‡°ý’O²ÀîÇ~ãÆQí7ðÌúµxQŽ=í&Vú°nk6-`ÎüMuÂN?c2KïÎû ]êŽü‡ © ”‚Bˆ½8ȼûî»466nu_ïÞ½ùÌg>Ó­ ¢”bÅŠ¬Zµ ¥}úôaùòå¬Y³Çq8òÈ#»h’É$Çwo¾ù&K–,Á¶mŽ=öX Díxø·„!Ä^MÀDD5ŸaRÙ<ÞYü6û{o.>u"®Ù2lÊ›ÿÑÑ`OTÇ ¥, Œª„!ð4¹Šd­ Q¶‰ÈÕP…Æx¼<:"Ò¹9"ÆP2©½s˜1Æ #ÖÖÖ\˜1¹5¿tÉvƒÞÒÖ§ßÈ£jßËGÙ!œ=¹?Ñ›ºÐƒbŒÆ(…m aj°,…Ñ­CÖ-xƒg^x‡ÔÓùþEËDniÏKÉ‘uî\ ßç)³öyîyò]böáØÓN jÕÓÜÿZcÇ\šÒ¿)ù9<¡Ó³/û2ÇP{‚ ~ØZô¢m¹N–cO:ÑÐDÚaèþ0¬"†Á ƒˆª1ü …&Wf; BÂ(ê8; ‚¨_µÉ•€Î¦ÚñPXh¼l;~¤q”üB쥵ƶmgë&–eõhþ|ñã*++·º¯§û)++#“É`Y¹Ñ QuÙƒ´Ý0#„{Ÿ\8´úqÊW¾NòwóÊ[OðeñùSÁÞÖïIÛÖ”ôHlùŬœìC…3“—ž›ªÃ‡67S6b?Å·$z2?ò)ßÿR~qÓ–“Hµ¶£·ó˼¼÷@&q®þ cšy…Öº¦|ø tŸàsæ3¢" yÑLV{å¸ÿÌæ¹<õðßYçŽäìc‡±qÉR¬D5ƒÅ;]½íœ¿‚ ݆o,ú÷Á¾CªXö^ÕQ½­ó¶¦èâfS­´¶©Ž-b±âGºÜPYô<†*Þ ëÏØqƒ!H±fÑ*jª]JK·T¼‚}·òêës)­ù`ÅR¦“Çö&júˆgž/6„ƒ÷M1kö fï7’cF×Hõ3!Ä^) C?üðB`ètÚÛÛ» ´ÖŒ=šºº:^~ùeêêêèß¿?­­­ÝÚOþœ,X@[[£G&•Jñá‡0pàÀžÍ™ÑZ*!ÄÞ@‡!ÙtŠ´›!TsÜ=øg¦¿öjÞȤáà¥ÓX•Å¢Ð'“N‘ 5Fk|/K:íF­C²Ù4é( ÂaÔAÇ1¥Õçå·ŸæŽ÷N|ç]=’±/"íùDÚ Mî猠‰ðÓi2YHk´.ýe¯³-´d·úÚiK~°@‡>Ùtß‹ÐN%‡žx‡«L&CdH§‚($Ùg"gMÝÌ3/¾Î¼v5ãŽ=)uƒhŸõ7ÞoД—­ä©{îÆ+pùÇd3¤3~”û†.ȤIûq­1hüLšŒ%œaÇpâØU¼ðÁ4~¿y%£{GdR)<¿£W)ÿ7E),£ ²iÒé,AØQÍä¦A玓1ø½^~&M:Ê䎫s¥šû>Š3NjgÚ«ÿÇÿ¼ÃEQÞg,ç8­"üLŠ´ µ!²Œ;üÚÛ}^yõ>n{É¥¼f“Ï>‹#jR¼óäSÌ\pìÕçqÆÐ²ko癇ž¦ßµ_`ÿ ‹Hb/ÔÖÖ¶Ýû»2™ ™Lc åååø¾OKKK÷£µ&‘HPWWÇ€ð<§£jfwzŠògÔý÷ßoÎ>ûl|ß—WY±÷P*·@&å†]Yù•æ1(eƒÑ`4‘6(ËÂR*74Mw;õ”,,Kιä>ËÆÊŸ/`Y6¥_ŽåŽKÇã:ÿÓZcÙvîúèmØÆÏ¦ãŒÂ²Unð]G¯"7d¯«H·ìKoµŽÌ¶Ž«u´%Ï)…eåŽWòœ çRôú䯬Òk`rs›”¥°”ê8W°í]{]„âÓª²²’l6÷%×Îp§Ð©¢”Âq¢(êV'K,ã±ÇÃÉm“93Bˆ½Š1UǪ‹QGC?',4’`¨ð³! K· ;﫸¡¿ü1U®mJ.9ŸzJ!¹](:ï„QѾ£(,ý½Þñ<‰‚.{”R„ù?FÍÿœßgéφ(Ø2 ,wK×ç–;lPïÞþq¶¼ž‘îü_þX†0ètm!¢«×thJ®UìÚë"„ŸV---»ô»³8czÔ¹’Ï/R@ñ)È5f»¡ÇlççÎÛnk_¥·›N Jn=áŸÑ6¬4Û¾c»½Ƙ]º¦ç¶£óèîµÞÞuØÞ6;Ú¿üBˆÝü7ö8®„!„B!Ä¿dˆ²äR!„B!þ}jJ3ç'¸f³Y|ßïÖb±/ÁÎô>)‹Ôúwøõ 8ïk—2Љ ·Ç ÜvÅ3ðǿ㜾¾–µÄ·{­uá3±½@£€^_ÏùÇ×qÏ ó˜8ªz»_DX–%aF!„{J˜¥4-«W2à+ÿËï>[N*0( ÑñœÀ0–BGʲq›0ˆ´AY®kzm4¶êÆŒb@U £#ü Ä…í¸8¶" ŒåàX £CB­p›À÷¸ýŽÛ8ù¤)Œ5¥Æ¦¿ü"~8Ÿë¾þMãD~0Ÿê°qÖÝœû½—¸àWw2ù¨ã¨îSF¨5;UåÖ¢0MCC#.úÖÜh‚°œIŸ;‹Š²€`g÷/$ÌC†…råÝ‘ñ5^±¹ÍïÖ[>/B!„ÿä0“gÇâÄãq" rýE?æ¨{~ϦŸ~“é½F3ÌÏ2jòTŽí»’ÛïΦlˆŽáÂo\Iü‰ß2íÃe¼{ÓÍ´~ëk }÷.îxy-(Mrä¾÷ïSXrÿÿãao2¿¸úhfßÿß<>Š|éD’¶Ãˆá#xqú £5rï¼û ÌãÀñºµfLç54ÊË˹üòK¸çž?“N§¶¹]<çç?ÿo®¹æk$‰|¼Ãv\\+bù+â{¿_À%wÜËöU¬ZRMuÂ!ôšYöÑzÂ(C}“ÏÀ12ÈÚÀ ×`×îË!ãÓ`©ËæÍgŦ NÕ@&ŒßKgX¹`6ËZSô1ކ÷›^ýû·å+vM†h­· ù…Ï‹6¬Ø˜¦¹=^š ›Ú=wn"Œ4½«âì3 «SUÀ|)t!„Bˆ›}Î9çüxÿý÷ßNãCá8! ^x–—æ,`þ;¯ðÜ[ë=¾? §Ïfèi§á¿õw–¹˜_~ç 6¨™[~ô uß¼‰Ÿõ"ŽˆÍ⿟6|å›ç’ýpSx+§XOó½_.åšßþ–ÿ8o›þúžrOãÚsdzâÑûxzé"æ-®àª¯_ÈÀ„A)‹!ƒ‡²iÓFæ/˜ÇæÆÍ,^¼ÇÄ‘G½Ão€£(bÉ’%ì·ß~…¡bZk† Bß¾}·»½1†¾}ûR[Û§cb³Âq²Ì|èa>}æÌÞÄßúgŒŒè,/ÝþKþ^qG%ðýënasÍœÍïrï½ÓÙÍ‚nä…?þ™†±§rø˜yÏ/¸ùåMô©¶iØÐΠ}÷¡Ì[Í£÷?Oºª/nûBýë«ÔqûVÕsÛUßeó‰1±2"’/¾ÅÎ|ƒá8¼ûî»ôïߟl6KïÞ½·ú lnóøÕSËÙЦø¨>ËÐ>¬¬o£o¯ Ö¤Y°:Í‹3WñÙûsKצQJ±aÃúõëGee¥\p!„BìþcÛ,Z´¨»=3iúy&œ mªè›Ìî‹(g܃Q™,ÙÆÕ¬Ê¬fÎ}…§¼V%*hñö#Š4~^û>M}gÿÞ†ŒéÏÑGÔòôœõøçÊ—Öqê¿?Â)?{Œz¼Ž‚Håååœ2åtâV¬XÎ~ûÕ1é°#º½VL~ÎL±î.¨TSï?ù}ãLYi[aÇbÄ,ØôÚ§ŽÓÏ>Ÿñդ߾‚Ôþßã Ç÷ãÐôëü쥵\³O=w<ÛÆewüãz[øA–CªÊæôsÎç€^•«®áýùM7ÀÂM$pHŽ»"?g¦xÞL1ßHgC6·fhKç>„a¤IÄ]\ÇÆ¶Ölj' #Œq¶ú@†™ !„â“ÐíafFk*‡Œ¡nléÀÂaYQƒZau¯¤"y×üêŽìåéˆ0ŒðÚÖåJ8k]5„Dë }Eu,ËšemôQ›YÆoîœÍ„3dé_ï壯a¨b:HñxœsÏù7^{ãeŽ|,t3ÈÏ È7°b±úÓ=üö·wN§·›úž{îY.¿üJâñx.Ø Æá„k¾ÄòG~óûüÓÆöÁ` 0¡ÊË«(VqzU%°kÊ1‘"Y#¬÷ˆÚhLcD•MF¹ç“ß¶¢šò¸Bk›d…K˜ Ñû×EÇbg䇂…a¸ÕL€Ê¤ÅðjÃüëPÊ,/cBݾÌx{V䅚ώíKÜU[õêÏÉB!„Ø#ÂLèeñÃŽoq1€&ð<4ú>&×Ðî5ËOx™»þçw,?'Û†7h2çM´ }(ò±GÍçFþˆ;÷g&V¯çùµã¹ü«}xåÞ›™?ê|n½n2¯ÜöŸüéooòÍÏFÒÚÒH²m‹“O<¥ÇkXtnp…aÈäÉÇáv·ÓZsàº\½Ï~S¸jX#ßøÅÿ#ýÍïsñáU›Œ[ÿ¨¶ü`õÉ(ï)^YÔÊ—®%ÝÔLKn½¹´ Ån–Ÿ3³­ÀQ–pøÁĶ,”‚3øýûVÓÔ’æÍßN%5adÈza—oÏUHB!„ø„ÂŒ!býÕpÀ 8^hÀh"úsÁ·¯£&n3沫ðÇ ŒAž÷U¾½`Ë6¦ wŽ®ÁvmN¿üKTUkB]Ë9ßúOF°„¦`8ß¼aûWj–L<‹ïƒX}Ñ7è·ÞÇê¢=´3‹ñuõís*•ÊUKÛÎî”R•ÒŠû¡ Ùö6Ú}zÔ…Ül[üà§ß ñßo`pà‘ Æ„¤ÓYòÊOµãuŽÒ~ŠöL@P>ëþ}27Ýþ=.16níþãÛ—Ð_ç¶Õ¹ƒdSd;*ÈeÛÛñ Ý.‰-Äö>Û*Íl ¤³aá3 €š^•(­)Ÿ`;ë(õ¤JšB!Ä®PùË_ÌYg…ïû{í“ô}Ÿ|/~ñ‹Äb1’É$7\ÿ¾üåk0pƘÂÚ2–e¡”EAÀïÿ÷.®¸òªÂ¶`=ã&ÈÍ}Öž±cØ&DÛ.®ÒøÆ¹( ò=ŒDZÀD¾v‰»VaÛ°£Œu,æb•nxh+†kCàù¨XGÒŒØI‰D‚ŸýìgLš4‰¦¦&êêêvØ‹rË_çðÒìµL™4”o^p ‘Þþ:3³fÍâCaذarÁ…B±ÛÅb1žx≞•fþWÕÕ7ÅžçqùWòû?Üʼn'žÌœ9ÿ`Ó¦.¾øR^{íU>üp×_ÿc~ò“3õŒ3q]·8âÄÅÍ7ÜÂÏ1rÒlb±-CÓìX|ËÖv¼¨¼rn[·äì:mëÆÉÿäÆãòî»ö FGhß^€Îþó‹sÃe CD;ü¼uÕ*„B±»}jÂLç93ZkÂ7þ” 8úèÉ(e‘Íf¸ôÒ˱m‡Tª[n¹ß÷wjh›{ª|˜énàð‚h‡!¦ógN!„BÂÌnj¸uF¢(*T2+¾?›Íþ?•JÉ»D앟‰â÷ùÇñ‚!„B|ܬ½ý *¥hjj"w{]!öfZk†ʺu먪ªúXŽQUUÕQÊ\!„âãã@nÂîÚµk ½–eíU ÿ††:è ée¢ãó=yòdÞ~ûm\×eýúõ»û*++inn&“ÉÈB!Ä.ËÏõ(//gÔ¨Q[ÂL~AJß÷QJ±|ùr.X°{MGy×b&wðm>¾K;1t%ÿ<ÞzóMy'a –eá8M›7Œ‡‘¡fB!DgŽãJIiÚž´åGÍÈQ£0Æà8N¡áä“Î!CÐZ“H$X¾|93Þ|Çuw[ƒ¦¸rR.«¨BUôbšâFPQc(ÿ‚+ËÊ…"¥ ë_HsI!„BìélÛfÖ¬Y}ÔQ¹ChvHï¾û.¿ÿÃ;v,¶mEan 3ù@cY¶m£µÆ‚] ù“¯œ”ÿÀ¶llÇÆ¶íŽu]T!ìt>…'Ó€ŠƒPqÐB!„bO¥µ¦µµ•¨£­-mØîimk+ôê|Íœâ `ŒÁ÷ýBÒÙ]A& Ã\‰4Q«Æ[a TíS†ÓÇ.¼¸ùÇGQ„Î÷ÊD´Ka¹66–²JŽ!„B!öî ˜L&QJ•ÌÉ-„™|OG>ÔtµÐdOÃL†¹ÿ¢ÂÕwsœ!A?bT¬öˆªZ cÙBè à ¨¬‡ÝÔŠñH„ʲq‚ò$aŸjŒãâ°¥·FÆæ !„Bˆ=Yñ|t­µ|ß ÅÅ#ÉòkH–ôÌ8Žƒmç†~íJ8(éeѹ•Àͨj¬a$û2˜QÄTÍ›ÒlHȆزÜãµËÂ]¾–ò›èZô7.}±Hb“Q>ª™µk¨9Ý·¦0ß&„B!„ØI[u篙mÛ…@Óe˜É/‹ÇãDQ´— iX IDATÓ•ˆ:Oø×Æ`¯q©i¬eœs C¢‘8¦Œ4š€8}«P¯–åÒj›·”íÆQÁ Sq*±ˆa`h5õmY>˜¿’‡&i­*+陑7‰B!„ØSæÒfÝ9A‹Åð}ŸL&ƒmÛ¥aÆuÝB×Í®†™â^•Vô^_Ë¡‰Iì«Çb"›V2DFS~°EóvXÊ@bñrÆ´§8>ÞŸ ‰*ú)‡Š0Dµg*†Á0Z%¨ ¡&kñDß8AǶ®Š!„B±§„™¼|»[tO</LIq§0¦d˜™mÛA€ëº»Ü3“/­\ÖXÎXëÆ»ˆg“l2Í”×%°Æ·±ºvšÖ`Ù6‰ÍMŒhNqÔ¡GÃÐA¼Ö«…¢&ë3¶>Íȹ‹pZ@•C1ÍA5}x±Ì¥Ýó ]Mf„B!Äžf¤ÝÚ3¾ïQ‘L& E a& CÊÊÊJÂÈ®†¥-úfú16q}éCsÐNùñ.K›Ï²ÆedÚÒxY×qH.YCïŽczÿjpšt®—ÇŽP GŒ>Š{f½Ö®,tU’yûíCÔ²®01èÓ°H_ñD1ù!„Bük†iÇõL"‘ ™LâyÙl¶p{!ÌäWÒÌW!ÛÙ`Ÿ+`i›¾ºÝ8©úà&>8ì]Öm^‡—õÈd2„QD¸a‡IJþU˜(ÀÒÑVëÓ<“jgÙ99ac›ÚXpð(^©_I:.$µf©T ˲(+++™`”¿`–e‘H$p¯£'(ãºî'V‰" CøàæÏŸmÛœ~úé¼÷Þ{455á8ÎÇþ*¥ ×äÅ_dúôéÜ|óÍxž×åã£(¢¹¹™8€¾}û2wî\)(„BñO3]±c¶mã8ííí¸®[¸Ýé|qó)§óïÎ Óyxšr‰xk£Mú´vfॽBß÷sÛ¹6élÕ±®‚Œ1”Ê%2¥ˆŒ! C( 1ÅÿõD&“ák_ûûì³ ,`õêÕxžGss3'Ÿ|2¿þõ¯ùè£x÷Ýw1Æp饗òÕ¯~•™3grÝu×zµ> ùŽãàûþVë埿֚|¦¦&®»î:Ö¬Y³Kk !„BˆÝfzÒÖ[¾Øï|ݜⴓo‰î¼([…ŽüÏÍ¢õãVÓ´¢ ä†nå‡jÖ‡ ÃíîÐG¥Z‰e[q-q]²nß­&2 l»cÑÏžÕ’òÕ¢(¢¥¥…šš~ùË_ÒÞÞÎõ×_O{{;åååÌœ9“9sæ0mÚ4ÊÊÊ Ãò>î7W€mÝPSSã>JE´µµÉ‡F!„âŸfvu˜Yq[îÓ2âF)…ïûø¾OYYYIçK!Ì䫘1ÛQ÷x=™â¡^–RX¶MDÄÆÚË<6¤6àyYˆA”€âÞ‚®jocP¶ƒÛ»?5V Ã]Ñ&ÒaM~#«L5õ¦†0²wj^HññµÖ´¶¶†!úÓŸˆ¢ˆŸüä'´´´NçŠ,X°€K/½”ŠŠ b±AÉd‚ P6.?T­¬¬ŒX,F†…Þ(¥eee$‰­Î7 C²Ùln^GØK$%Åò×Äó<6mÚT¨»L&‰Åb…€E7Þx#$‰’×H!„B|òa¦«`Óí‰gu×^{máöû￟‡zˆM›6íÕóoŒ1Äãq’É$AtÝ3cŒÁ²¬Âä÷îîxKѤ#›L (A¥m ‚UýWÐT¾™XÖ%Œ"T¤¶ZǦ«ž…â e¹ž‹@ÖGQu?ê†ælg)m¡ÇòÍ­¼¿y=o¥‡ÐæilÛÚ*ÍíèM•ÿ7›Í¿ùÍo3f wÜqóæÍ+„ ÏóPJqõÕWÓÒÒÂ#œ)S¦0dÈÇaÑ¢E|ôÑGlذâð™N§9þøã7nk֬ᥗ^"“ÉL&‰¢ˆ††n¸á.\È›o¾)sf„B!ö€0ÓÓö˜mÛ\tÑE\vÙe%·_tÑELœ8‘«¯¾z¯nç©¢9õù"[…™ü$öü¯âªdÛ’ŒÑí:Î’ö^˜D*ckg€ÝJÊkããg0nÅì*ßó Af{ûïüb+¥ra ØÜØÄÿ¥ô9d$'V,`X¿ZökjbÈÚuüuã¾dÒé’'¹½ã†¹uð}Ÿë®»Ž“O>™‡zˆ§Ÿ~ºÐë’¯ôÖ§O®¹æ/^ÌÃ?L†Œ1‚«¯¾Û¶9÷ÜsilldäÈ‘|ùË_æóŸÿ\rÉ%Ü}÷Ý…0äyëׯçë_ÿ:W]u555444àû>_úÒ—øñL}}}á\]×å¾ûº˲¨­­åŠ+®àª«®¢­­­PåáÒK/å•W^á½÷Þ#“ÉÈœ!„Bˆb£¼;íÓÎzõêÅÅ_Üå}ûï¿?—_~9·ß~;ñxü“ f¡O`lbî'S-7?z,ß^ß*Ìä„Õ1ï¤G/ †ú¨7îЃIª#Y|´i%Cï R̉ޣ|H9Õéêõú’ Ò“îµâǦÛÛøãâ*öSÆ>± ûô¯¤Ê­§5ÑΣK“Xj˼›í§óí“&Mâ²Ë.cñâÅÜ~ûíØ¶]2$.ªòaÌq‚ (\³/}éKüð‡?dæÌ™|ðÁ\ýõÜ}÷Ý$“In¸áæÍ›GïÞ½ùÃþÀ¿øE^{í5hnnæòË/ç;ßùëׯçÛßþ6õõõ…4žL&KÚ©§žÊc=Æ]wÝE\rÉ%…Â?ùÉOp]·äñR–Y!„â_S~ôÔ¶L˜00 ?±0cˆŸ½’“zÏã¡ÇgâÙeßBµdÇ!ì˜k_fÂ0,i¨wg_¡H€ÑPÖ—²G¡úŒÂΦ±’µ¸ÞÔæE`lfÔ¿†ŠÔ–ÞœôÌt6Š«tcX¾j%/öïË%±¥$Ü}zWs¦ZÁœÌ‘¬X׈Rtë8ùcضÍUW]…Öš1cÆPWWÇÛo¿M"‘(9ööBÖ“O>É?þñÂ0äå—_æ¼óÎãÐCå–[náý÷ßDz,V¬XÁ¯~õ+~øÃ2xð`6lØ@ïÞ½¹ð iiiáßø---%ëýÿ 0gÎî»ï¾ÂZ8÷ÜsçœsÇ<7ÝtÓVE ve!T!„B±ëŠ lõtÎÌöø¾¿íýC`Y¡Â‰Å°Q®8°eá¸vqïQ†PÊÆq,a&Eõg¾ÀyûÞÏßî™L¬ŒXÜåãžµãºna¤Q~ŽSœø¢(ÂuÝBC¸;! fœx’°¬/¶Ã&OÒ;ž ±Á Éo‹t„Žt×ÕÊz˜Ì´ÖXZóöZŸ“’šå—å‡ X±ÁÁ¢´¼sWŠ{m”R¬X±‚‡~˜Ÿþô§üà?ફ®bãÆ…zÖ÷ÕyÿK—.%•Jáy7n¤¥¥€?ü(Š |Λ7€Ñ£G3{ölFŽI]]÷Ýw›6m*Œ ,>Ïâ×cÍš5d2Òé4a²dɒ¡C‡²lÙ²­>,Ý:(„B!>;;̬­­Y³fq衇vyÿ#<‚ã8]îÓJôæ´Ë/ ùszÄqÚ/dÚ_oç…l">êx.¿à$F÷sÙ´øm½ÿ1gbÄm…ö³TÖÊÅçÃÐ^Šõs_åáŸeEÚaà)×ñõ#âT”MáÆ_ÅÒó¸åúûX‡ý±š|»XkM</T4+ÏqœÂФüÊšÝ}Q”²ˆ[šÐ((Ìq‰0O¤£BÙã(Üzý˜ž˜âžŒ¡¡%ņ¶Pwô®¸#+Ú±l·ÛCæòçEüãyùå—ùóŸÿÌàÁƒ¹òÊ+{t®ù’3?_¶¬ç“O–•••¬\¹²°ÎNW縭 U|œüpÁž$z!„B±gJ§ÓÜu×]´··oußÃ?ÌôéÓK’,i«»eìì¥ÜzóW¨]>?ÿíÕ§0£.äO÷ÞÄI}7ðÆ«P;åÛÜù§çd ‚ î¸k¸ÿo`‚õ¯ÍXÂÈÏÿ„ßüúŒŒ4쪮 K³¤6Îåñîç/{ƒ&,>Îòù©Ûfæû>®ë*!ô¨ë EbsvümYp++Èf²eBLq•²žÈ‡ƒâ¨À'åGDlÀR.½â¶ã`EaÉ6Û 2ÅA¡¥¥˲¸í¶Û8餓˜:u*Ó¦McöìÙ]†¼Îû.9¿.îëê¹ç‡÷TVVÊ7wu ¶w¬®nßÞmB!„â“Ó¹ÝÙv™ÖšÚÚZV¬XÁ\Àõ×_O]]mmmÜrË-Ì;—~ýúFunCm°\˜}÷¯¸ý©Y(~6É9w\Áð¿ç¤kKsÜæoÓVñÀë·rù¹÷ðõÿmä’\A|îÍ\ûŸ÷“‰+žzµžGŸÿSý¿yf!‹6øxåkø`ÖLZbq,¥€\ûrCÂ*++·ÙU¼bw(¥ Ë‘(¥ð<¯4ÌX–UHtK'oï0Ê¢Ú4P®²ø¾Æ¶!°4ÕWÒ+>™ž¾ðùóÒV(”Q€ÂQ¥# £Êض‹mY˜¨çø|ÏmÛ|ûÛßæ/ù ßýîw¹ôÒKñ<¯Ë7á¶‚Ãö޼ŷ+¥hhh ©©‰É“'æÂä+Ìå¯ÙöÍìꜶ÷B!„Ÿ|˜éI»¬½½)S¦ðË_þÈõÂ\|ñÅ…5O:é$¦OŸÀ믿η¾õ­­ Øz3³W7b)…AÅ0id9+|Žz'I¹£ õM™§ø·ýÇ/[ÅÑ#l–üâ%šeŽÂ4½Æ³+~Ìè#pYo¡’ïŽéüÜöÝw_î¼óNb±X—Ïíá‡æÖ[o-éeÙQ˜±,‹l6[2©¤ô@~áÌâ^î°,¿­‘qz3Â!$ǶYÔÖ— Uýaãj:Få= 4Å tK9ø•M$Ûúêv« »¢7q¿ÛŒ•b™]‡­V²ã0Ó9$Xºt)wÜq×^{-_ûÚ×øÑ~D<ßîq{¡¥«°‘¿ëׯgöìÙœxâ‰Üxã|ë[ß*,€äº.Ç/™ÔßÕ~v”ü%Ì!„Bük„™üßýîw ·wÞy 0­5A0yòäÂ}“'Oæø—\rIé3c ·LO £ÿÄ›pb Æ(Œ¡P<ËtÜÊ·s÷£è¸¯ðàÂÔÎÏdîܹ\vÙeÜyçTUU•´{o¹åxànM Éߟ/r_83?%Ã)~`q7Pç!M;>ˆ‚åÓ;n,d“t,u«ÝèkÀ÷²%O¢§óe “Øýˆ^+ O³ÿoÜzë­Œ=š©S§rä‘G2þ|2™ ‡~8?úÑxõÕW ½5ùDšßgçs*ÞwçÇ !„Bˆ=;Ì„aÈøñã·ºýè£Þæ6ãÇ'Š¢’Ñ=[Ž‘Ÿ¦a°²k™±´§žF¿;E“eãWŸÈùã4kŸ™G¦}3¯|råi'QóÀŸHY úžÊÃ[x~éGxB?B9.&ŠˆlÝ1̬ԢE‹¸ð yúé§ màÿú¯ÿâ©§ž*iŸvçšåç÷{žWÒ¶/ 3ùÿŠÞÝ 3J)ü¶&êêÀðy7–aâe,i†W6–¾fÚKc©ÒÑcOþ7Ú³ÊIŽÛˆÓÔ‹È3,XÝÈ/š+)OÄhͬ"ô=|ß' ÃB Ùžd2ɦM›H&“]ö˜Üwß}\uÕU\{íµÌŸ?×uY·n›6m¶íB÷Y~¬b^"‘ ¥¥…7ö›Âæ8Ùl¶ðøüP³ /¼ .¸€“N:‰ºº:ÚÛÛyê©§hnn.ŒL§Ó´¶¶–Ìmª¨¨`Æ %¦²²’öövš››{<J!„Bì^=)ÍÜUA§ž@P¶]fÀqZyòæ»øÂ}ßåÞ»Êy`F3G^t%}?Ê,%V¦øëïàü?|;þ§–§çN¼ür‚·~ϯ®E¹†µ3ÿAÅi'rÉÅkùhó^{ñ}Ú:PJ±víZN9åüqî½÷^žxâ‰O9-Ó`ò0ù}¨¿üå/æÌ3ÏIJ,’É$J)þøÇ?rÛm·m³*BWaƲ,ÇÁ¶,† @vÀá¬Ó%Ù¼y-jó<ªÓ+¨V)‘‡Ât{øSç0S½ŒA'mļ7ž†Eib±XîÅV £uI äÎë­lëü}ß'‹Çñ}¿¤Yñг|%…ü¤üÏÆ¢("™LE¹^!˲ U‰DÉ~ó/JYYYIfÛ¶‰¢¨pM‹‹äãyeee…ÛòovÏóˆÇ㸮[¨–ÖÕc…B!Ä'ϲ,æÎË™gžÉâÅ‹·»fL:•ºººn·ßâñxañôŽV4V¼†ã.8Ÿö7æåM[BŽŸÁ1™Ïî8FõuÙüÑ,žüÛS,Íĉ۠ƒ,•ûÄ¿M=ŠÁÕP¿àMlkƒ®e0TpÄy_䨱ƒ( çò›Ÿý•zrëÐtD*++ñ<¯°¶eO,\¸|O<±ØÂ0äÉ'ŸÌõÌä«äK3÷dM’âoüó=4k×oÄmx–¡UÕÔRÆH'F:‘"2<ŠÂz3Åae[O¬¸$³RYZPvD¿Ñe4,N—¬‹“¯š–/oÜÝÞÇq0ÆÉdº¬6¦”* ùuyòÇ.ž””NQÞ¤÷›jVüøâó/|çû”R%ªø¾|}ñl6»ÝÇ !„BˆO^ç¥4¶×Öv‡§žzŠÇ¼Ûc ±X¬têHf3Ïýá·`—.ˆ‰'Xõ÷Ü:#×{cYض‹«4ZvŒÖÅ/qÇM/ææÓXŽæã~ZyýÿnãUm0ÊÂuº0O¾óónkkÛéªÆJ©BܳuifcLa Z2™,šîËš  ¡$ 457wkÎJ熼R¹ÊdÖ—‰4N™C6±™dY Õ1Çu¼ 0¤¬ó6»ceÕî^‡óöÙN‹B!Äž£xØö¾ÈÏ·ã,ËêñP³®Ú–ít}Ÿ²°‹-ýC¹ÉÿÅ÷;ŽU¼ó’‰þ–í`Ù]ß·³mêí…4×uÉf³%ó‚ sf¢(²¬MüßV )™°o4¸ "7†àgKžhçФ”"r\Œ7Ð=Zk,Û¦½|úÆ)«N`µ+Ç&ð‚’^!„B!ÄÞ#?ê)?½$?¥¢¤@YYYáÝf¶½Ô©£ˆL¼œÆx5A²Wú¶7ooÆD¦0%WÿÍqR–ÍfÇa Îf1Z£µA9íÉFÜþiì7€D¥Ái)GQ:¹]ÂŒB!„Øõd˜™(½fù)3J!Ìä»mâñx«™u•œ´ÖD¶CS¯~„£êˆ Û_)V¬]ÁÀóIÔ¯FyY, ʲ ‡&-‹C%³øCŒÖ(Û&ˆgi‹mÆ2ü^TˆcÇl2N.Z%„B!öD—AÙ™ª^Ÿ6Å#ÀŒ1ø¾_(–Uf”R$ ²ÙìnI‰J)´ÃŒCùäSP†aù Åšš~¨EP±i ®×NjÚm…NÄ>f_Ê–,&cYXI›ÕÖ*üÊ6ª%p`5µ”«PØ~/ÚÖt,Ü#AF!„Bˆ½V¾Rp,ëzÑÌ  ¦ó$úž¦§¼„2ô0˜Ôà‘Ø±8°«{¯;¯WoÚ6¬‚–M¤!gpÿ¾V¿šå™4ʶؘÜHû€VŒ¯¤ÏÈ2júÇI”¹DÆÃÞ¸«ÚÐ:WQ,_ULB!„Øu.R%íÖî‹Åb%•‚· 3ùÅ{ZÒx[”R¨ `øÊy´úSXOâcrëÀ81èÓ** ÊbiÃ’6£?Z@êUض6¿—GÅ Êê$*\,e‘1Í ¥ùí*Z›—ÇÜ•&„B!Ä'fº 6bÇŠ3Šïû…Ûâµ··S^^N,Û¥ œ_—Ųm¼>¤æÎê¹,1žÕ6´)ƒeCyYœá¶âÀÖVšgÌ µ¥¿£ÛÈ66å½*Ù0°]‘Ä7š”Jq'½0Œ5‹—àžçJ2Ë$*!„B!afïcY®ëÍVaÆ÷}âñxn®ËnèåÈOÔ‰´Æß¼‘U½›þUÕŒ1ŠtY%Ž‚J?CãÚÕ¬Ïf£Üb™L¦ã$5#FÑÛ¯ÅXôú0¡áX𧥍_³ˆl6K:. 3B!„BìÉaF†™íœ(Šð}˲°m»t˜Y¡€ã†ánf–D…•>‰ÑÔÚJë¼98¶²m6@m99ß÷ñ<¯cM sŠ‘3FÖ¦¯îÃÆ¥Í4n¨'ëå‚L6›-Y(S!„Bˆ=9ÌtlÄŽ)¥ˆÅb¤R©Â¼™B˜1Æàºna½Ò!&Û†‰b;÷BuT™³”"°,´e96Žmc;Nn5S¥0&zÂ($ B¢($Š4ƒmÙèÈ£aöbs“¬u1ʆYÏÃËf ÂEh-o!„B±‡‡Ë" ì(›kkÛŽ\”nЙvˆr‹d&“I<Ï+ 3ù´“H$ȦS¸Î våþ¸¶µÛN""Š­ëi›ŽE3ì¢Û!ŠÔ6’­Xòú !„BˆcµfëÓEŵ’h¦hé›]Ùwñ¶Åû.Þ_O÷ÝÕ¶ÝÝwçûvfß]í«øœ;ÿÿ¶öÝÕ¹îèz|œûîê¾®Þ#{â¾»óÞîêõ“ÏM÷ßÛ»ósóI¿·w´oyoË{[þ&ìÙïí…ÏͶÞ#ÿ¬ÏÍÇýÞþWþ› íéo‚‚(Šð}§Óv…0ãû>eeeè0Àvlrå̶¼«“ØÞ}Û»½;ÛwwßÛÛvgöÝÝm»ºW¶ý8ö½£Û>Î}¡Æ²-lÕó÷HOÏûÓ°oùÜüknä½-ïíOûß„Oã{{wï{WÞû»ûs³§½·÷¤Ï¼·?ž¿ Æ\×%‘HuÚ¬¤4sGß Fÿ˘ŽC¿ÿÏÞ›‡k–Wõ½ß½÷;œ©æ€nzº™gh‰<*‚h 5ˆñL jbÔ'*ÞkŒIˆÞD Q“ë(èÅ8 "¸ N(26Ý`Ó ô@OÕcÍç¼Óîç|w}ÞUûœ:U=TWñ[ÏSOóž÷ÝïÞ¿aý¾k­ïZke åÞºM6ž–:°:Ó¸~è¾beÇP;fSíŸ4ç|K•¥¡Î_*”5RÝ4R–)—Ô4•îx`¬YöPŽ@£&_Ò[ø¹ºá·>¤ÿ~O¦"ëz—´¼<Ô®rª»¾æ s¤²\ûv ´k+kM¦¥î9:“=íëI÷­•Jå8’$I’$I’$_ò’I³ÙL“éTy±ÞFæ„jfu]k:Jg²afÓ¨îЛ^ñD}ížF¬•jòLMUécŸù¢~í3«—µÔ/´­CâѤVoX¨/iVV*«õˆ’z¹†Åzk:«Tׯ¹TgzÕkŸ§¸ö#zÑßL•/äê5¦åtÌr ùñ„¢³XjåzÚ/Ð럲S½&×óž~f·ß«ëÕšNŽè'~ç&U.å¹zý\ýLšÍ*•Y&ÕµÔdÊú¹úŸ,W¿Ÿ«È6Ö•y¼T IDATLµaš4ë†ð 5@+M7l⪬4³çôs•3éů|–Þ|˧tõ_Œ” ×çk6«TmÌUÞ/4Ø =NfõF]¾LÙÆÜžÍRV™ž÷eOÔ[ž³¤»ŽÌ4mr-6Gõoÿ×-*Ÿt‘~ùI¥þÁïݦq“k¡ŸiVVªªøüÆÓýÚdÊû¹²òøø©È5ìmq›FãY%5™TdRÕ¨?,Ô“4í¼v’$I’$I’$É£D)Ë3õ{=•u£ÙlÖþ©5fúý¾Š¢P9(ÏÎ ŒŸ–…¾áµOÕìØ¯¯{Ǻe­RçÚ»cA{Š™&Õ@ßóOQï×ê­÷HÙÂý÷ü½íí×ëoÆ…®~á•ú?_tžöÖcýΟ~^¿üùU5Å@¯}éÓô¦§îР™éo>r£~ú¶E½þÂ.}ésôžgOôοü¼þ¿zŸþã×^¤'3¼{¿¾ïn×ψA®Z¾ö6}èšFY>ЛÏÛ¡cv½~Ô_Ñ¿ø–«õM—uèÎýzó;oÖ5“ž¾æëž¦WÜó€Ž<ç2½re¬_|çõúàîKôK/Œz÷ì×÷ÿáuë´Ñ%W-O×ôö÷^¿yóHê/釾á Ú{t¬Ë/ß­[?p>tù“ô¯žº¢åf¦÷þõçôÓ?¢¦ª…Ýú©o¿R_»»ÔüÕ}ºäÙ+úõß¼^÷ô•_þýè öhÇlM¿þÞÏém·M”Ì™$I’$I’$É£ Óæ¹š¦Ñt:UQmÁ²Ö˜)ËREQh8ªªª3Ð4³Q½¸Sßþ¤¾~ëmwè†ÕFÃ|=:pàðšHª›]zñNõú’šFúzÆ¥+ÚQKO¹úIú/¾ë×?¦÷ê7^w¥n½ï:}t÷åzÓåSýÓÿöaÝ‘/êiçKo¿_ï¸c¤7\§W|t"-íÕ»¿ÿqzÏÛ>®o¿7ÓUu¨Tp8Û%S¦^ž­W”+SÝ õ/¿û…zé>­WüìA=í%ÏÕo¿QzѾU;öìÔžß×·þÒ'ô¶‹/×ÿ/Òë>ý9½á—>¡×~ã³ôÖçÞ¯¯ûëcê/,èÕ_}¾~âç?©8×›^õ4ýð3Æú±ë¦ë$©V¦~}LoyûMºf¶¤ŸüžçéwÖŽêe< ÿõÅczÜí×멨3}Íkž¯_Øw¾ö¯×øòËõ¾7\¥[~özí}ÖåzÎÚ~½úîQµ¸¨‹—ëg8{gD“‘þö>éG¾î‰úÛâ.ýÕíÇtßá™”IïûØzùRßñ'wép)=í…OÐ/<¯§ïúµéÎ=èíßüTÝý[×éý‡zzÞ3ÎÓÑ÷_«ö«_PUôõ¼¥{ôOþòzÜqžþŸ7>K?pèÃú7ú‘ï®^pÝ'õ•¿±¦×~óóõCWÌôŽRzîW?M¿zÕHßô+Õû£ßÿæ«tÓ/F¹V«Hz3I’$I’$Iò(¦‘ò,Wo0”&ÓîÒÌ.w–ù­ydÿ5Ôϵ³¨t×j-5•ªÝè·ÿù—éš7¿Dü¶Kµ£*[ÃgÝÒZ§…5½žþÁwèCŸ: É®%]Ú›ê£Gzú–Ç÷54ê/éåOÞ§gìÍôÅýk*]«Íˆ»œêæÃµžû” õ²KUëHyÆàaýççÑz¸dßãô¦‹FúÝ¿[Óå-éð ·ë¦½ÓË÷6R‘éïþüFýïûgºéæCº·ëÞ»_wGz÷ÍÇtÑãÕ¯e…t×µwéýgÊf½÷¦ÃzÑ—5„ Xd•>}Ý}:ºcYÏÚSéO®YÓ•ÏØ­~]©n6Ö]]«ZÜ¡7]Yèmz@ ¬hçáƒúë|¯ÞøxéÞ£í8o·¾îÊݺ|©Ö÷Uåó1,¦ú¯¿úýÓë*}ãKŸ¢üð—ëϾõ2]5hT6ëk³njÕy®_¶CÿûCwèšÕJûï¸O¿ÿÅF_ÿØ¡ê¦Öê«úÀ h­j4›MuíÍGµû‚]9\Ó{o(õ¤K¤}è;÷Ö¿ùÓ4nÆúÍ÷Þ¡{•Iƒ½þ‰‹úã> fß²[­éÃã%}çãs•usŽ­ÿô/ýKÿÒ¿ô/ýKÿÎîR9›ªßïk0´X³ÌdY¦¦iTÎÊ–cÿà\ß¼}þžemÞÉïk¤Õ5}vÜ×K/íéïž({`¿þÑ[ïÐcžþ<ýößË•×ÚÊü‰:So㣅 ]øØ]zépY½¬Ñä¶{ôλg:²ÿV½é]#½êª=ú¶§_¦ÇïÒw¿ãÎõa©×¯3˜Ò¾ýz½ú™ç뫞}‰~`_£·þþ zÿÁrÃÚ˺ŸgÛdœ¦ãÍq/ý¶¯ÝõúV×Öüwäuk¸æ½žóžžþ„}º ×SÑ4zÏûoÖµééY£ÑZ#eëFc=›éX-eM£¬n”åRÖlÌAÓ¨ªk5µTUŠ"SÖ7šÊ|E?ú-OÕÔVKeôUg¹zM½^+oc”gê5¹.¹t¯¾¦Ì5ÈÝð··êƃµ®½õóú©ñ…úšËÎ×W=E«_¼UÿæÏï×Z–d¬4?&ëït×öƒ½v£¬éݼ^ïþ@#-íÖû×/Ò[Ÿs§¾ó`³aä5ÊÔ¨È2ÊzcÌkͪZƒ|ýk«ªV9[ïòÞóô“¯ºTÕ½‡õÀ¤Ò…{s5‡Ök±÷šJ“ªV–çjÊJ“fBY¨Ðc/Ú­—ínÔÏÝÿÙ;õÑûJåM-ÕÙY²¶Žkg§©ç6û[³ÉxõwföÍ©œ §{íÓYçÚNûæÑ±oígÂ)ì›´¶ÓÚþR<šZMÓ´öJgÎŒ#3½~_õhjyfíÅ;$þ-ËpW˪›¹«Ãû7ª”Gô–÷Ü£½þúñé5úùëŽè˜zzÊãµ\U¯ëS }Ï“¤Žê /¼@Wô¥z6Ñ_ÝyTßxi©wþÞ ºy5Ó…—îÖÊÑ™VöìÖ¾Cwëç~ï­<û¹úô.ÐãÞq«M3¿/—ŽM4Ý»S_µ«Ô|ðýîânýê÷?GÏ\Éô¾ò “¹É}o9|oû7ŒÉ)_»îþ>ŽëÜàõõPˆ²¬Q}÷ízÇ—hÏêýúá¿8 -,éi—/ë®Q­gªQ¦z.ú•m,¢ ­ÓüÊFyÖÅú濼]¿|G®W=ã<}î¦4Ùˆì5u%-ìÑ·=¥Ð÷üð§õÁµE½á{/U¯i”ÕµŽÌ2·¯'›H³ƒúÝ»k}ßòHÿê·oÓ¡º§+ž´Gõ‘Jß·Co¾]oùèLO}ÉÕúµçìÖŽ?¿GkMÖ1&YØ5Ö_˜ŽU¡p˵½Ùµë­×†”½%}ÛÕ»tó÷éÃ÷L4ܹ¤'-eºçðLãªÑÒŽB³ñTÓºÖ'ïZÓ[¿ìBýÚ§èîÝ{õ/ïë÷?6RÞ ×—’j©®µ¼{Ÿž3<¢×¾óÓº§Ø£Ÿý‘˵CêûîÖ»§OÔ¾pYßökúÚx±ŸWª'kzß]#ý‡Sý«?ü‚øòÝ®T¨î8#:ÆêѲ¶OçÚñþÚïËý=É\nzmÞ_vüN¸¶ÿvš×~Pk»>ñ ~ÖöCy&œRâXuÍÙi¯¿‡sm?JÏ„½o0'õ¾ñïzßœ©3a³µÝ<òk[]׮ς}sŽ®ít&l¾¶·:šZ³éDÒzžÿzJLs¢1S×µfÓézifZF]7è/÷ÄðõhU5¸Ù¦ã:¦$™î½öÓzö‘Kõóßð|Ýôí ÔS}ì3·ë÷&6zço}J¯ü§_¦Ï]=ÖŸ]wD7kM©¿þàõú‰—>Uôo_©‹zµîºs¿þÅÛÿNGwîÕÏ}ÇóôÔ•\£CõŸ~ã}Z™>÷þ›uÛw¿HG¿b¦ŸyÏ´ü„Kõÿ~ï ë™þæÃŸÕß5Yœº9qÁl5&›Æ$¾÷x°íŽÍR7'\»ªUM¦Võ“¿ô1ýä·>Wwã’4ZÓ?þy½éó‡UUfM³~ºÑ¬ª7šIª*M«ujXž7ºášƒzÆ«¾\÷]6Ôõ×|Nßõ‰TkIUÕ¨V&¾]ßûÁ ôKÿ×ËuàÀaýÉ­»¤Q‘Wú›?¿E7þ“çëð/4ú?ù¸þå¯DÅkŸ­kþó³´«™és7ݦ7¾í†¿XÿãU/ÔEÃLì¿[?úÛ_Ð]•TamYYÖ›Œ‘+´Å¿mº¶;æl«µ} ×nf3­.ìÕO¿éizúŽB“ÑHïyÿGõýŸžj¼tŸþôêgéóÿéJÝö™kôâ_ÿ¬~zç3õÿñïki2Ò¯½ëÓúƒÛÇÊ•U½Qn;׷ߢw­>OïóKõÀÑCúðçŽiœeZÔQýؽVÿó»¿\‡^3Õoýé=úÂl·Šf¦÷¾ëZ­üý§ëƒoùº ¯tÛmwê{Þvƒn›>ȵÝ<”û¦cL;Öv·"ÝØcÍkÂâù‹óØum®‘®kG/Y½ÉéJÌÛêÚ]kìt×vÜ7ÑÚÞôOãL˜¿¶6ßÛëú{¯ÝõÞ‡bß´k{»ûF›¯íÍôíC²o´½õwJûæLž Í6¯}Šk»«Â£}m?j΄GÁÚ~´ž ñÜzØÏڙЬ1yž¯»ÜëZÙÆu³ßüÍßl¾þë¿^½^O šŒÖô_þì&ýèï_«A/ï òmñ÷M¬¿¹÷w¶®*ͦÇKñªÈ•÷sõóuãi2ÞHú)2©l”/õ5P³^‚y¶aÍå¹òaO½ºÒt²ñþ,—…†Åú˜L6¼Ïýb=¤-ë\hÐÏ:ôÅÖ÷}ò1ézßV×ÖI~ßîµËd\Jýž†Åº;TÛz9ëÁ ×lRª)zZè­/¢ñ¸V±ÐS/kT—•fU®Á0וÏx‚þïË&zÍ;oÑhÖHE¡þ Pž5ëß3èk!o4–ªKIy&åTç.sP®— îö3M¦¥TnÜOž«7Ì¥ªR9=^6;äÙIB×ÚbL¶šÇÍæå¡¸öüû§³J׫ÖÇ`Ð?ÞsFU#= ‡™¦ÓJM¹a¤ z¹²¦ÖdR)ö4ØPF“i¹LË6Æ:+4ìe*=ÍŽ¬i6n´ã…/Ðg^[é+ê:ÝÙ+TÎ|íõ}S ×çúÔ÷»ÎÀÚ>ÕkoF)8¥v3ºÄfï9•koõÙI¨ [­¿­^{x×öC}&œùkŸ kûô΄‡wm?”×>Sk{«k©­í³aßh×JgÂÙx&LËZ?óMÏÕýý§©,KF#IÒ»Þõ®ùjf«««ZYYQÖ–¢j¶øò®AîúÿT&aýµ<“†Ã¢Ã’]ssë­¿¾n“dRÑ?~=s† =|ÿñ\€¹ë¹ÔßÊÐh½^ÂÉÆ$ëxo×Äu¶Ÿí|çÖã*IÃAÑz2eÇ÷ûëFƒþúkŽò ‡ñIyži˜¯çåE®åA¡åA¡º8ÎiTÓl\·VS7ê÷ ÄáMhçàxèrØ+ÖçT 乊…|þ™OX›]›b;c’mãoŵuÂZùúºãõ7(zÃ~!õý¬Ò —I½^Ø ãÜØ“S¯.ÞiYj×UOÖ[¿|Y£™táÞ¾~ùŸÔmÊÔošk‡}ÓœÎÚÞjltkx;ór:ûF§¼o¶¾vסݜⵛ-îût¯}&ÖöÃq&¬¯ínºõ—Ÿd-Ô'Ý«§wí³ãLØÞµÌÚ~8öM¶÷?RgƒÃ;›¯…“é½3¹oê3á¡^Û§s&3 *§•³™ÔT®Ê›$I’$I’$I’$I’$gFêJµ/:6W`4©Wäôû!g&I’$I’$I’$I’$I΀4µ2I½¢P–Ç'3½^OEQ¨W䚌Ç륊YäE:y•»øúv+µ=×>™l§ZÝv¯½çÚεOåžNvÛ­Ølã^6«f8÷÷FUš©X/ð^ûÖÈéT|<›×ö©^ûL­í3µoÊõ÷p^{;sþp®íÓ©°™Î„G÷™ GùÚ>“g—ÒÚ~´ž Þé*v.­í3u&<×vS©ªJ•'Ë™éõzëVO/?ž3ÃÔ:yùp¾¾Uá„øû©à8ÙµOjámãµí^{;ÏuªEš6óÍ*-vÝÓÉJyo·°ÅI榪3]¾0Ò~Í“ô+u‹®=ÔW‘5ɵOyœîµÏÖµ}º…kéµ½kogmŸê¾9õ÷í›m™y$Öö©ÜËù¶Ó™pNœ ÛZOgòLh¢}s6¬íGë™°ývªgBöŸ ÍØ7_Êx§^o‘幦£±z½žê6sÕÌêºV¹ÑŒ¶Ìlwc$yø¤ysð0Ï׬Éõ¸ên½ã_¿NO¸ø½øÙOÖkþÝ;ô…ê<õ³úìç$g÷4i-¤µÎ„´Ò¾ù’™ƒæaœÏt&œy©«õÞëY¦º®UUÇK‚÷Ž<µúý¾ò"jª´‘“l½®šLé~}à-ß©•š֯SíÙ¹¢?û™7ê«~è¿é–ú¼ãš$I’$I’$I’$INË«TוʪÒòò²f³™Ê²œ7fŠ¢P–ešL&*ËÙÍ,Kƒ—¤Ó¤oé²¥™~ã{_£K 'T–x×O¾A¯û™ßÓõ‡û륾“$I’$I’$I’$9-èY·T3I-ÅlΘ±!³´¸¨~¯'UÕ<§.I’ )›L— WõËo|…®¼ä±šÌÊÞ³wçŠ~åM¯Ô?yëëïŽ ÔË›éK’$I’$I’$IrêRUÊó\ýÁ@eUk0´ÍZcf:j8j2™h6›JM­&Ï$AfM®ÇÕ÷éÞü]ºpßîNCF’ʪ֥=_¿ûcÿH¯ü±_ÑMÕÞ³/‡&I’$I’$I’$É™—f=*3™LT7êΙ ëÝ4§•zE.U¥”¸ˆºK¨i“×¶óz×ï,ï¶Õ5ºÞ{º×î4¼w;Ïq²g<Õko5æÛyïvî!Ûæç6~¯éñý#zï[¾[»V–Tb!mfЬ,-êÏîûôÕ?ø ºi²¢BÛX#ñ}o{ý=œ×ÞjÍlö¼Í#°¶-ûædc¡‡hè‘ß7gôÚ¶µÎ„sêL8ç×övÆ÷‘ZÛçò™ð`õ÷¹¶¶Ó™Ðý{]©ijy®ºZ/Pż1c §(zºh¡Ò‹/˜©×K¡™$Çe!oôï¥öî\QUo?Ê’e™~çÇ^¯ÿï¿§Õ2“²Ä_L’$I’$I’$I²=)ËR_nÔ UO§Êó¼Íמ«f6Õ4¾á«ž§W\ý”4rINñ´£+¯¼RçŸ~Kßz¤¤išÖþhšF‡Ò®]»65hüÞ¢(º›fæy®ÉdÒ^ ÑÌ’$I’$I’$I’$9·¤i8p@×\s^ö²—iiiIyž·¥Ž³,{Äl€º^/³<™L4NuôèQíÚµ«óûg³™F£‘vîÜÙBsÆL]×Çë5ob%I’$I’$I’$I’ä앺®µÿ~=ó™ÏÔòòrkÈE¡<Ïç’ëNɲLu]«®k5M£²,5™LæÊ.Ó ‡šÍfÝ¥™›¦QžçFªª*ÑÌ’$I’$I’$I’$9™ÕÕU]vÙe’tZÆLÓ4šN§­MU×zE¡••e½ã½ROÕ¨™N§-K¬,Ë9Ú›sfš¦Ñl6Óp8Ôx<ž7fRʲLeY&c&I’$I’$I’$I’sL˜LO#&Ïóöï'3>š¦Ñ‘#‡õÅ;ÿX÷Lî×p0о󞢫.~¥–ózÛv„ßW׵ʲÔh4jsb\iš¦½ÏñxçhfY–iaaAý~®~s’$I’$I’$I’$IÎ c&þ~*ŒãQ”úÄÌ6#,Ñøñÿ[UN‰FFm+™¹ÈL¯×Ól6KÕÌ’$I’$I’$I’$ù1f‰¯of€TUüÛza€².OˆÌ°jr¼NŒÈtX®f6NU…4›Í晢(T–ekØt=T’$I’$I’$I’$IÎ~c&æ©ÐxȲL“ÉDU5Í»Ç4M£µµ‰šº8þZ]éþÛî“êUÕx¦LËËËÚ³wQM>OOÛ,_¦ë5(£Í2gÌHÒââ¢Ê²Ôt:M3$I’$I’$I’$É9lÐÄŸ)“ÉLwßÿ{ú»ñ¯h–-ˆ!ŽFÔHµ)׺ASÕ7êã÷¼LyGúv¿´÷ðéOúååøxý³- 0åÅå ý{gif÷–aI´$I’$I’$I’$I’œ[†LŒÆ4´°õÊd#M›û4Óâ6®\jÖÜ·Ù—jÜL¥,WC„X Ëàê÷ûm±²áp¨ñx!Ò#­,_¥z6Ñl6k™º®ÛâceY®ÿmc«®kÇceY¦^¯wbiæ^¯§,Ë4•çy2f’$I’$I’$I’$9™øo³ªe‹ Ïѳ—Ÿ«þ`0W¬®*ÝÿÀ½úìê't°9¢L™òâ=ãò¯ÇU‡;ûÌ4M¦r²6G3#µ,ÒߺúÌôû}M§SM&“ö=>Ød2™kB“$I’$I’$I’$I’sß°ÙLªJªFÓ>7›VR“ãÕLu-MÆ3Ͷ°%6«Z¶•Qe)ËRÃáPÓé´}okÌdY¦Á`0g)åyžf9I’$I’$I’$I’sDbO—í<ü?˲ã9.±js#U›4¿ìêcÓÕW¦ËÀªëºí‰ÿÖ;nu­[Pý~ÓÊI’$I’$I’$I’$9»…†Åv""]FHÓHêLµé6”6{m3šY|ÿl6kó{L7;Á˜ ê÷ûÉI’$I’$I’$I’ä”S‰Êlu uØ2ÍC|ŸÑ臚ÍfÝÕÌŠ¢P¯×SY–[T5H’$I’$I’$I’$ÉÙnÌ´e’Oøi6Â2Ù 4³S»^¤¼m™q4Æ•—;ifu]k2™¨,Ë8mI’$I’$I’$I’$97Œ™­ ‡íH–e‡ZN49:Q.©ÒHM–©Ñ©]o³^3QʲÔt:UžçsËæhf ­µÃrhI’$I’$I’$I’$97Œ™h4œ#k8\ÔýE]~Y¡á` iQÃú˜&U}J‘ÿsgbifÓÌ|íÙl6oÌôzë?E‘úÌ$I’$I’$I’$IrŽ3]†Íé`ÿ"»HEU¨˜’¤i}TU½}c¦ªª6±?FfâϤ—Çãöo­1“繦ÓikÌ$I’$I’$I’$I’äÜ“ñ8ÕŠfÑ 9©ëZeYj6›Í4›`EQ¨ªª6èâg˜3füfW H4³$I’$IAsPZ IDAT’$I’$IÎiš¦ed92R–åi3§{UUi:j<k:ÎU)뢙•e9×gƶKkÌ”e©<Ï5ÛL’$I’$I’$I’$ɹ#Y–iÏž=­!3™L4™LN;ÂrºÆŒ£26hªªjû]vÑÔܬ³,K-,,t÷™±µ“J3'I’$I’$I’$IrnÊž={täÈíÙ³G£ÑH«««mBý#eÌÔu=*ËRW\qEkäÄœ™ªªTEûwKÖÎ`0h­œdÌ$I’$I’$I’$IrîI¿ß—$=z´¥{­­­="Ñ™Xº®kõz=]tÑEºâŠ+´¶¶Ö&øw½w8¶ešçŒ™<ÏU×µ¦Ói¡I’$I’$I’$I’$ɹ'½^OyžkiiIûöí;c¹òÎáY^^n£DѨr€Ùl¦¢(柃oòbh'I’$I’$I’$I’$ç–´Áz=-,,¨(ŠGÜȲLUUiuuU£Ñ¨3:ä{*Š¢Í›9Á˜)ŠB½^OeY>¢ @I’$I’$I’$I’$93RU•Ž;¦£G>* «Í¤®kåy®Á` ÉdrbÓL×k.ŠBkkk:xð ²,;ëÊ3³îô©üí\”ø¼_JϲgýR[ _jó›Ötš»/Å5}6íf÷z6®´¦îH¸ãá—º®uá…JZo˜Ù™‘¤étª~¿¯Ç<æ1Úµk—úý~ÛœF’f³Y›[ÃÏ.•–ç¹z½ž¦Óiû{¿ßotò_ÇŸu½l?Ÿßçky\}Ï#q]×íçø\¼Ž_‡m#T?Ïd2YŸø^Oãñ¸}v~—çh6›i0´‰YY–µóD¾"›™¢è÷»ôç¢išöºž‡8ïyž«ª*•e©Á`Ð>¯ŸÅkÁk)6R²Õîû³xŽƒA;ÿžO>¿ÇÛs<™LÔ4úýþÜ«ªJ šÍfskÕ×ä÷óšNb+˲½¦×¸÷Öp8l70çÝcäqæ½ù¾<~~&Þ›cy<óC;|¢(4Û±ŸL&'àŽ¸¦©<]¸ÃkѺé¡ÀÖÖUžIíGÜá}¹îðøpþ­W¶ƒ;8¾ÇÓÁžëˆ;¬£=F»váã|뜢(Úñ8UÜaÝÇ}Ó…;ªªÒÎ;ÛkùºsÆŒo®i-,,heeeðùÝ‹f2™´jp¹°°07™VZïEâë.--ÍЃœÑhÔ>x¯×k'›`› ¤×ë騱cÚ¹sçØ&¸§’¶rˆJÀ3ÚÉóØùà³òõwäy®µµ5 ‡ÃvbX5n8¶ —ŠŸÆŠÇÍ ÁÏåƒÀ×\^^nÇ«,Kíܹ³½—ñx¬}ûöÍ »Ø È‹µi-//·ßÇ{1ð¤âòg­ä˜¬EÙ›“ë C‚+?>Ž *2kkkíó ƒ9#˜÷ï×Úl6Óòòr h m,z®=Þ˜~.³¢(Úšè šL&íwE¡étªÉd¢;v´kÚ¡3Ùmc“F#íÚµ«U¤¥Þs¾gîql½^ýüÞG'ÏÙx4-No<+7&Á8‡øââb;>˜ Zx`yR ô¨üüŒôJ{ž½¬T½Nì±ã³q^-¾½¾gÖëÄמL&íwy®mXz¬ü·µá!BÏÃp8œÛXTr<Øéù¦²ô˜åyÞ¦\ûas³ÙL‹‹‹íZ°Á=d=^>`•ñ³XxŒèAô£‘é}OO²Çž‡‚•1?=ë<|"˜çÏŒ Ð Fƒ’JÔ¿F£9ãÈ΂C¿‡=Á^ž_½ ¯Ã®h ÁoWäƒïñ=z<Û¹¤Þ48÷½ì|ú^¨ë¼^ƒA«cô»å'o<£Þ#wƒ1ô2šÁ=îû$°~°Þ3 ¥±Eą̀2ÇÝkÒç†Çˆ`„±}/1"C¸çg0´Æ.íÖkˆñòëÞ¯õ“„u‰yzœ¹^[[kׂ ŽA¿ß×êêj;žµŒêø¼bT’`–:sàçåzéêàíëù9ˆ; \ý;âïqîÂOwø^#èõyoýq‡×ëÂÂ Β“á²!Ì÷÷xøyÆDG0£948È€áX3 b,@¾î`NÁ¤¹­p‡Ïrë1—q< —SÁÖM‘åÀ3œØŠÑb϶ˆ;xn1jO<æ×©£¹Ÿ½®}}ãMÏ‹ÏhÞ³ÇÊkŠNƒ.Üá5óÚk›ÿ­pSKKKs8n»¸Ãë={Ñ¡Ï5èç·ã¸ƒÁ.ÜÁ>3¿o¼ñ¸1ãÕÊÈ Þl+nd?07s×ÿŸ‘²æ‡cHßC~{à­¤éE"Àbx”^úTöV¦¤føoµÜÌ‘ö-É.ê'†Š˜ž(Ró¼8<Á¾¾ßç àç±EÏEh€âŸéicÔ+‚”è•áXÙ#ÀµÀÃÎ÷âEj…Í @‹ãm…•=ôÂù{*ö=ÓP‰Þ42¾‡Ø86*ûèÙóÆâ:òsò3žËH0ˆ¦·Þ€ z¾éAåz°ÇÆÊÇ€ˆŠÜë.‚]*î\ƒ\¤žÒ«èy00åAÌyñuèH0$P¤.ʲ¬õJ’ªâ9w„„ÑîCFKH'‰Ïà”FsŒHZûw{Ÿ#0 –QnëWÿž ê^RÐ<.ôØEoo,ìyíþŸQrì½Æø Öåž;ž¤ÓEza]×-eÙ=ë/ï^ƒ´5Òfˆ;|-ëÈ;<þQGtᯧH&îˆçQÄ‘ò´î ôš (cÄ”QMÏ)×—×,q©nt¨wĪT]¸£«rUttðHk$•÷ä³?Ó¡µîˆÑ’­p ÐHó¸xM’’×…;è °sПõ{9ôxP?u­ib›áŽx†vQø©sh˜ÑñGã‡çéÅ]¸Ãÿ"î`d™wp®"î Ü wpŽýïÆoTÎ\ •;CÙéú0ˆ!~nŒZ¢2ò¢¶ÒŠJgaaaΓLOîd2™ ¡ù;=ˆVƼž?ÇH£<´X½ñlÐ;LEÌCÎÊo:ÎåsPA³Rœ=¦%ÙãN/44Ž=C¿Þ€Tj6ÔhìÙcÀû"÷Ò ÚóN%0ç"lìÑpµ¢£"!—ž¨ØùÕ5®…H¹ñ<š.Àéq¢KÚÚp8l½¸<4¸¡âæ#¢—^6ðVÚ¤°ìØ(²7Ô ƒÒS Iëá!˽çïó¸zoÒDzŽïÙŸáaÍœ*ë Ï=ìØ¸7y}+WÏ£½K‘ÆÆH ÷z¤Æ‘Ãðv´0‚}õÃÏó2øY‹õIÔ6ìbD‡zŒ^ÌH•°N‹^sÒ ­{ýŒÖ^§.¯éýE Gï=‡ŒÕuÝFÆ<®t¿Ï\ì8‰¤xÑ;Åœ r{#=Äɨô˜÷Kë•z×4‹V&ôæû:þ^æÜöûý9Z7Á©×ÇŸÉú'Ã^3¤Ñ©Æ“á¿ Ò¸ƒû‘ÑѶ39@)Ç‚÷ÙeÜ2ŸÕÏ#üŒ ‘ O*ÏÒÒÒ–¸Ã{›¸ÃzŸë˜:¬_Œ;hЙKÜA|¤ÙÓ©Þ…;Ȧ°Žp¾ w°øÈV¸ÃTCÒy¾‘NÜá½L¶qGŒ>Ó±A'h,bClaÜAPî ã€8#â² ºpérÄ1²ÉèóV¸ƒÑ=âF#î Řù{1jc{ÅúsŽfÆé œä®JEÜœþÝÊ,òV©(˜ìC+@Ð OŽ0Ã…½ž òÊ™\Ì'=Ðô”2ZCï½zg¼QXõ‚"†Ÿ£çŸÉ¡1‡‡4™®Ê$yž·\hƒ{™oÀÈŸ“y o`1)›ž.{0Çs˜¼sr=uІH¬ÄïŽüz6yå&ŠLzi¸.cxÚ÷hìª!4.ºBÈLæ´‚d„“^Nz¸¦ùsä…úpµ¢$P²’ðX G`J©ô<“ÞAn7çƒô£. Á״ס×$©\{üÝT/ïmFS˜$m NúŸ™”zæIC£7Ú<^Ï…=öœk:>y°¡EÚlôªó§®¥>‰9b4¨i0iUÑ@õþ²ó'®éXùˆ¹c\ó1¢)ôR7M£ÅÅÅV'’¶`0h°ÒIfQ zÿ8¿1=z†é ð:±® “ER|Æ0φyiôˆ3j@==£~VêØ1Ocೆ^L°ž7Ò¶ í‹€ŒIˬÞ«ŸÅ ‡ŒLÄ|!F•ý =‹gmÄ\‡ÌâYp2Üá5oÃu3ÜÁ ]Ì¢aóÚï÷yHGF¬nGZ9qG¤ÇuåarLÈzàZˆ” :šbâvpGŒäó¬cô•B#îð3nwX‡n†;¼î"î°ã¬+BGÜaÇ#¹6¼¨£©ç¨?h(n†;¨¿èh£>àš'îðYÀÜ@Þgîðw™z+2 biþÌ|!:á"îˆyU§Š;º°4 `F¶Yì…´cê Ö˜yò“ŸäYåQ®¸¦µ`”Öãâ9ñ³Úxq%r×=nô„à 3ƒãOO/“}89’ Zz cî’çR±r_ìå@j ùÈ׎ùE<ûâz渳x -°Dm¤mÑH!•z’4 H1áüG£’E9æ£"…€!:#@i8sýEÍÈb,GKÓ ²î áqF‘ å÷pÄt°DÜK wáŽñ ]³+‰Zêfë*ÄSÁ17-–@f$5®Ç­pGÌ·àsrò,%¥Š”¹¨;‰éT‰ÔÁX¦š9“Œluá: ºp‡õWÄtÆž î !˜ŠÔeâëK:MˆGyfØyÁH6£Ó¬ÀÇ{g9YwtÝóvpGܧ¤ûmw0‡š9Ø,¿=™abVIœDVí"нȃ¤W…‹”¥àèi£ÑÁÚUŽu¿is‚Ø*Èç¥2'Ÿ’›‹^z…ø<Œ\1/†V+iœx–<ìêY“ĺJËòðñ³Úê§aEÁÍÃòÐ\Ç2º.çjïN ’++XР÷ŸÉϱþ>º½i@zþ¬ÌÎ&x$`b‚ ©CNêæÂ’å<é‹u®Û˜¨ÊÒÙ‘ÈòÈ,vÀÊ7Ñ3èd\zmb¹qQôÌÐà½Â)%‘ââ¹ ’£þ µ4V7êònÅŸŒò°ôf—7ö¸‰‰¦tÄêbä\s®»úsùØ¿†Nš±‡Á 0„Îõí»ËH$=–zÄóÃ뙳N狼ø9 ò™k“„£~æÞwÞaìMbzõφXÊ\F“bÂ2ÁOŒ6ÄŠ‹‘¯Á’Ÿ×û„cN*#烀:œ¹ 1ùž•#·œÆfí'öÔà™E€É’¦¤°ÚA0hO6Yt¤ÈrîIÙêR¦Í±”zÔÑ46èáeÉtâ:VèôósÒ°Ž±Ø?)âR‚¬"E5è*ã½ÆBtjEÇ+Ï©.ÜÙX +¾›áŽ.L@‡O,ú´î 3˸ƒ:–Ì}#îˆ ß1ÍÎfã™èôe¸ƒÔa²ºp Õ.ÜA§û'E}+[n†;œĈG_ùˆÏ žG¬”KÇ ÏF»¶Â¦ŽFÚqÄK3 HŒqG¤¯1š8gÌ0üNïn¼lÂæcbd,¹ì ã$º'°ñ†e2½¶´v­\Ø„Šâƒ‹UŽ¢W‰e ‹ÅD5Öêg8—›!9sJIÏb£MÌï‰áwS5b¯–˜ö†µ·2òéc%Ò…¸`èa¤ÕÍ|ß3 J¿×9RÞ,¤-1çTCÓI¼Y´ 6?ciZ&[Ñø~VWWç ÄÃ…kÚ “(ép8l óލÌècôàñ‹¼÷è¡òšvÂ|ô&²ò @‚?iŒ°°a&)c®ê{ax_Ǩ,) ~¦H»¢—iqqq®w½¬¾LÎÍ2…Ò¿S7Ñ¡B@È"ÔYô„²¬(+eÙËÅò©ô¾±BK`’šà¨3ÌyhpM¤Y7ÑÉäç\[[k)-%\Ó4V¨“}?4JiDsoÅh7 æ”Ó1Á¨B¬ÀÅR¿,&á1ÍXé§³ÑæYPz<¼vXü‚T ^‡”?6fn鼎×K¢òLัi™î¹f£ëÊsÂèXLôg^½ò½^¯Í7ôز:(óbž›dz¿yGc’Õ—bŸŽ}¤cEÏn4&XU‹• É·§s„ô”Íp¿{»¸Ã‘«XÎ6:˜ÿPvy¼‰;bï—¨Ó¹ß"î ½¯ wD£¤ wØ3Ïï´Nâ9çüR:’cÔ›M­}†v5Üeª#ˆ»XJÝï% Ù¬ 67µC‡U½_í,aÎÝf¸ƒ9tðyï²·[ClwX7± õV¸ƒNµˆ;¨/bng¬Æë¹íÂt2l†;Ø_² w°ßs È6ð™Lú"…º€#¥sÆ ŽKì…½!¬ÆË G>,Ar&•Ñâ÷ï U2NãÇy ±Z;Ùͯ‘+=ŒöÎógÿZÛѬnb×Y/ƒE†{ciÆØÁ˜ž *$*XR±:¨»k{#²ó6%Çš`ÂÈfQ$/n+!¾—”‰Ø‘»‹Ö@ÅɨYôÞŲØüŸÕDül1ŽàÍ¡lß3Ág}¸ ƲۑêǪ"Œìùõ3¸Â“Òiøy}‘òGª)él1'€æ7¸Š! Ró³xÇfW‚^QÂÂýÓU¥ˆ4±˜ômo`¤¶Dºt©ó"Pöß–––Zo缫#wôðzý’Vk¯¡§.ÊÁz¬’ÆóXŽvqqQÇŽ›;@" +Fµ­GÙX9R]H›ñx8’ŽQbÒcD221œ´)Ò;¸ÿ™ûimÔc6.c/0ÏïòòòUŽÆCì{Æ„m‚”x?LüçzŽºÕí}Ž¥ÆIKd¢9u}ìÕÒÕ&€É­Ob)ßH“Œû†}•x^q¼"k{ÝkÔg“Ç5b :9}8‘ïOCˆÎ£È@0P'~1îàúŒ¥¦yÎwØõ¹1™Læp‹sÄ9ß wÐËÍóçhÄÌS¢{ii©Å,ò°îˆñX)5F[c4‚óÍ—xNGÜA§'<‹H[ÌŽyáyAüËÊxĤE)ß™ ±îàz`äŸT?ã :‚Xh§ wx®¬í ÷wxH•ã¹Gæ™wÄVÆ^ǬFJ=5gÌDï š•~º’Ï"ýÀJŠêeËËËmÇO+GZÜôˆ“æw‚9æ´DÚ«GtQÈUŒžR†Ò#—¹ üŒ“`¿‡=ÓÈÆþÙô¸Ñ{äÏÑ+NeçEÈp/7«½µ Ñû)3±Oi%±"ù öðÄ Íyç†÷cÈ››Ÿk2zñ莕¯ÚŽT>‚ö˜;¶´´Ôö`™à¸æèЇ%甆Ÿiof+G bŽFW?ŒØŠ<`®iî9Rº¼fÚ瞈”2dF y_Tì4Šbò/“¶éÉ$—›ž|¦¤=òàˆ¥+ Œ=o±ŸT¬èF0ïª31ÊéºÔ#qMGºKäÓ‹J„%~©£cU5ælÄè³--ö éJÒ%ùi”°_gŽK¢Æjx¤Ñ0zl$ ÅX.<æl1É4$á9 VÜŒ}¯"UºÊà0êŒhp±ygì%ÂkÓ@ˆ /æ/ƤZ6G´áüÄji±÷C¬¤ÉÜC¤³)D¤a1_.æ¿Fç×tÜ‘&Ës†ådíˆZ^^nõ Jë§ÍpŸƒp{ÛIcckRÕãàqc?/>GĤ EÜiZ4üéd x'î ~ˆåð=FqÎ˲l8Ïð¹XÂ:ö»#Ul+ÜÁÏF*{îàyÌ}Æü>F7Ã4Ô"M‹8c)£K‘‰s­èä§î#Ñ·Íp‡ê’ùbšZy IDATŸ3:œ­3ü: ]¸ƒÑC¦t߈tHLºp×I<ß:sfÈ}gÂWLZö&‰Oã‡^%zʹ m1³,1»n{`Øsƒ•g¢™–²!ƒ3<ôÊÑv^ó˜„F  ó4øYR~ÈÅfµ®ƒ“`€^.ö’ð¸Qq3iÚÞ®ååå9ËóD Çæ–ö,ùþY{œyP1‘€þÌrëH¡‡‘ :Vx¢ÑJO 9¶ {Çf°>°ÙÀ´²È?eÂ*;#…Þ;îÄ"ÌÑb÷d†Åy˜²º¹Ì1‡‹•ØèÌWW®ALÂT 4ž{öéa¿z•bÎiw륥¥¨;LPõ8ùP"…Èk 6.õxpŸ˜ŽÀ²œŒp^cÑz—ü¬4ÔýìÍÂCžÑ!*dv ŽÆ4½ØQRg{°!“ûÙ¨ŽŽ–XuFflÞû€°Áb`t,R‚èô³ŽöµI±ó>2=Ã??Gä¶3‘Ÿ´·˜ßI`ç×IQbϸÙ™Q-ØÛ†ëÙ÷Å©4 Þ t%F#ùa$•½AºJôsÏ2‰@TkF}‰;ü]]¸ƒ43é˜O±]ÜÑU=Õ°¹ˆ¹^ïâĬÆ}è{gÅ<ž![á– æ}3ò¢"Ì[9llhÎrÁžgb®ÍpGLÒçqG\[, q£A›áŽÈš‰Í©»pGtF2i>æH‘ò›^ÒH¦.bŠU,Ðdc”ÑÜ.ÜûéQ3òÉ5Eü‹pÐÀáÈ€ƒKl3JÈs>¶¶àsø挙®ªST:ôÒB$%ƒŠ?rüèñöÚeÔø{IÓ —‡9u<´¨< c÷먌¼€Ù€Œ‡4.&3ÒÃ1w%ñ˜Œé+±BK¾F0À 5´p©˜\—T¾µâóXÄ Åa':z~cÔ`ÇøXý‚À¬k}Å*.ì‘ ªA/¡½i]e¬£W Î-“çb·Çƒ´1&éº<4|Ö~atF ˜o©B±´f,9JW¡hÅSrSiŽÇã9^8ùÊl És§aË9´Ë=³?–÷ƒÓ†ø,Q™RÏy,\6‚Í®&¨ŒhÐûêè9$õQÈØ»)þsÏÎÎäÄó#íÏÞBz##¥ŽûŠVo‹Õ H1á^§‘ÃüU4HX"9–³g”/Rn*É ^ä9‚}Ñ8%å.‚_^ÓÏD‘|tž6xÒÐf¯ ?˱cÇNðvóÜò^gŽ ÁW4TbÛ¿ï/VcŒã»ÆŸU8‰+Ø—m+ÜA¯ùf¸ƒÕµ"îàº=î`>VÔc'Ã1bä{eþqupÌùˆ‘l:.»JC3ÏéTp™/]¸ƒ³#ª¤ uáFTˆ;˜'q‡¼n†;hLwеî`ô`z3Ü+äEÜÁèwÄ‘ÙÃ(-©W¾o²cذ’Qãb”.¼À³"âŽØÿ¨ wl$cãTpGìI\ìuFÜáqžë3CN>¹¡ä»ÑëÇ0=idægØòf¥,—ãf·„bÃ:ÖUˆèŽ•3¢R"Ï‹ƒ–2iôx392z—¬`È•%mÇ÷MO “ܺ(9© ËÓ#ÊÊ,L²ŽÔZLT÷aJcLãAÁç!&Ûqó1ß*&-G1v¡R¢ÙK€à Ö%¥3í‹üNV£!=ˆÏÊê&Pű`´/– '?Ý ‰‘±§ˆÇƒÍ¶b$…ï'H!Ž|ޮư±D"×ãh4j)R¤cEî< [°ñ0‰!þXª«—CÝ6”Y “•|bIÙè!§±# Lž¥·ƒÕÝ”T®.ºS¤¡±‡Š÷(©‘Ô%<0éuã½ xÎl¸Ä®ô̵ˆvVõ‰d<ì¼æh|\Ñ‘ÀˆõDl@0õ˜AMt\ÄÄÓX&Vì¡1Ò•GÁç¦2ê+êh‚'À®¾ ÌõЉÿ¦ùÐÛó¨§é 0X‹efcD–•ý؆Àš<ö®†Ç¤’"l€FÃ/âï>+#,Äü &ˆo…;b7óØÛ„緦΋”Zæ¼DÜÁhD¤ Å>^^Glà«vr ˆ;by똜ÏRãŒnw4S?q­’öIš!s•Øc.%½þ1"ʈT,¹O£q+ÜÁó%örЏƒø2gŠ¸ÃŽˆ;"]Œ‘ŒH#c´Ê{€µ.Ü‹ºÄ5ȵMç:ï›%ä™›Ï~ö êÂ|?q«táŽØ/ŠÅ˜wBŸv?f®h´À¢c>@ô^ÒÛJo…¯cN§‚žJ*¹œL"c¨Š5ï}ÿìäìßFåáï­pnG/|ðsâéaäAA0ëmz€=Ȥ¹ÙKÌ*UL§²Žt¢XruuuµUbΧ±õÌè†=XìNOÈââb«È#p¦Ç§×뵊Ÿ”6Ó¥b9_zp蹈¥3 ÂXyjmmm®*”û)ÐÛ»žsùšþ\ì9A@LðÀŠhŒÐoo ˴Ĉ3çÀÊ‹%XÞЇy ³)¡ÇÞÞ’Ø43FäØ8’%0Is ®`™ÛÏMŠœ•©=jL¦!Àj%,ÎÜÓ§èpðÿ6hÈKæ>&àaõ-Öÿç{I™a v?æð0`µ?'æ!sXÌ¢«ƒ÷ý8É֛؀>z– þè™`mFbÕ%{( FYâ1z;bÍy6¯¢×˜¥œ¹vc„Á{ÐÉöè¬òã}FÚÁ¹×.iŸTÊž+üLòçz _Ü÷K£‘ÏC¥söšý¥b‚zìÌLÚ%s¶èt`…=®C×þžvôHòuV·Š,¹~Yp Ò¼v|?vø˜RÁõÁg"Ý"‚hÀ±„8£›&¤Wø¾XF9Ò}b#`Ç,lÁuBNpc£Ø`2æ°wûðkL殤aȹô}ÓH: ÷ÁgW3½H¡f¯×4CÑ Š†7ivüÎèp¡ò¾%bÑV<Ü˜¼î û`‘v×…Cb²=½Î¤Çâ'Ã]…'"u—4RžÁ¤¥wx,l<±Âh¬Žhãàd¸Ããá1ˆ¸#â3:´b[æ wpGÜAã’‘Z–ø'vˆ%™c9–¸ß.î q½î`®qÄ426ÃÌ…î*Ù©ýKKKskŸ¸ƒXâŽX=Ðq;¸ÃÏÞ…;¸b%?FÆ;b§x~œPš™üY†Û¹IŠu˜Ü/‘ëË|+0Á ß—ë„Iɤ\År®1QÙ ‚åO7+±Í<ˆ˜·Dªdäì2Å{‹½¢Ñõ§/—pfžéH_ìwAjQÔ—1/…F<{&ÅÒÒѳ»w%]ò£Ae‡A9=ôÔý^s­ö ÇR¸ìKÓ•dÁ!ó?èÞPVQë¢ù.“PYq.&¾“ªÇ橬¸;¨sŒ¼žiÐøe4F­Ë½¶»€oWSM®áô¸^8ç¾–ér¤ŠÐyNÒcϪkÜO‘Eº*óõ"E.Ò¸ îð=;¡Ý Žy(Ñ(ÕœÈ,‰4³¨·©"î e”“¯wĦÊ4¦Xžž\Òd©·éê±xï™ÏÓ…;XJÜºŠŽnîSæ°‘’å}«¨n†;6snDG“S¸¾b.mÄŽt=ÜAæÍvpÓ)ˆ;¨óbšˆ#»v†Ç¼Äˆ;H‡|8pVÛÅ]:å„Ò̬rDÞ.ë¡3tÌ('!Vè¡cn k¦Ó;ÉN¤ å³öµ½c¼,AÈRrÑÇF¹XÉ‹Œ¿”ŠèUa¯«º“`,­H0LÏbl@Ê$aòU™“ÁÒ‡40R$P§…L¹y 2Û 1–ðdŽó2¨ã!9ßX]Ñ/Wb’žÇ)®1Î;A°×ßGÃ7Rºš„¬Æ1'ÿÝ¡txR¤9ñ<1îàüwáæ¶Eª—é¤<;©ºp mÒ… »"wÌsbÞW—“¯ÓÂ9‰ Éé¼£NŽ•p»Šéð\¢ã‰‘%j¢CšgW<#î`.#ï<_H´`-½®ÞÊèRıaj¤wÒù̼ â; igd—ÎLj;xöÇꮎ8ë‡n†;b…ÞétzBC¯1Fµý|¬RqGÌ‘*ËrÞ˜a“DÒ#È lºªÒhm­õrxBÖÖÖ6¾4×p8˜ ‰Ñâ&…Ä d(yÇúænfèÁ][[Óh2Q‘çô{ªªúúAôV6TUö®­ÿ+7Ñ[;BǤS6vªëZå¬ÔêÚHÃá@y.Íf¥Ž=¦µµ‘¦³éð(Õ‡Çn4km4Òl:Õh4jk­×¦²llˆ˜XƎDZ:yý^8ŒxÁÒ£3 tìØê`êiÐïi4ž¨njõ{=•³™zßgeÈ„9®Ñxý™²LjêZ å YÑ&zè™0ÉRÖLXF ËJÓSçõEcÕe«é±ŽÕ¶b™Ê˜‡Aeaž3£‘¼6)sì—@àË›²ÚïË÷IzP¤rF@I9>ó¹ÈÖ` î6Õ¹¹tf y_w᎘³JÀÅ>$Ô·±’"éßl¹@ƒT=Ò”èàùH »î ³g;¸ƒÏK¶Ç"zŠUÝ f~á©âŽØ`‘½Äè4ã¾rƒm:YlQ¢XŒ¹˜±ŸZ¤áwõ¤ƒ5Òø7ÃtwðgÙû“áŽXž…s"î ÁÏ.½Å}ÃJoÄ,è+ñzíÄ\ÙÍpG¤µñ~X´€ë®kMÇÒïŒrßxãê1¿auuµ}£+eY¦,Ïuýßþµ®ùÜMjVZk7“z;®Ôk^÷ÕÚYWsaqö!±bŽ}[ìíbµ–dçan¼,Ë4žŽuãþ@×éë /ø }峞¨¦šÎYáh>xŸîºífMê¡ö^þ=á¼Å¹÷Xé“rÀŸJ!=/®ckkº÷Ú÷ëãû ]õì¯ÐS.]Ö½7}F7Ýv‡îਦU­þÒn]ùŒçé¹O»Lý,Ó¡wëÚ½_·‘ é‹Þ@;Ï»DWÅ‹tÅžE•P‚ôĆJl˜è0 ½eöì0dí99rôˆî¼þ£úägoV6¼@/~Í«µ|ðNÝxÓZرO—<ùéºppœvH^jîºYùð_épö$½êu_¥]M­ ‡—•¯=ãñ¸­4ÅD>(zMÉ-'—5Ò x˜{Áj4TÀ¬CË]¬¾žsèaaÙgJ®3+'Ff"Ý,æ9Ìf³¶§êØó„žÕHá‹NVP3Ø`…Ê…áߘ H~5 …Ø‹†Ì®êZì¾EŠ xìœÔËJs<¨=¾~é ‘z#§‘ŠÅýèòÌ“ÉD‹‹‹íB/pì¨Íª@¦2²w—<Þ#B¬VH'Aì ;Í3q5–AeÅ'ö `5<Ò¸‡˜?Ä$ÔèÁeT˜¥š ^ ÀIicºØé…ÅNbÞ#$ÜG4JaŒ…?ü¤>òðÅBº*Â1† ™9ìa]bI Á¾bèt±"{MN †0±—•°¢aÌÏ‘ºâç^[[k_'p4ÀX(Ú¡ñFÜaZ÷¦ÇÛ«¢z\¼þØ7Ìk‘V;¬ê7RôØ@›=Eü÷ˆ;Ø–åЉ=X„%23lHTC"ÆýgA:?Ó…;˜ï²¼Ä*1ǃ´;ë5‚Zö·bºÃh4šKØ·. s‚û>:‰¢aéäxG\|Í.ÜÁ>.Ä£>O|[ája?¼ÈÂaô7ž7thñüô9cœ Vÿ£N"îð¹Èï©âꮸOc¾Zþ—ïÒu·Óåÿè'ô}{zªë¬-ókeHή•xÓ4m4Ê÷êdÁ<ÏUÕ&‡nÐûÞ÷}±Ø«'|õ7)ÏêŽþ¾Þ}ÓHålª&+Ô õÉO|Zû¿é;ô¯~‚šjª»>÷)]³?SÞL5-¥¢××`ðI}üSwé_¼ùÛõ˜f¦|cãûÙ|˜PùY»ÉægÊó\GmÿîCerà.}úSŸÐjóX]úòWèñû?­ÿýžiÔ õ’ïúq}ý•‹íæå|Zùù`XÙ½SãûïÖG>s&W7i&^ÏTʬ$Øô'V?á5é¹!ayOzÁ˜SÂ&Ì[ˆ^UV^Œ…;¬g¨3xˆ>ic…øLðA{'ÑSDo‹xܼŒ:'F›<î4L˜{Ajfì¦n_UUZYY™óv’FCz.£¬ ä=@ªËËz®™ŸÀqŠýŒH¥S…Ñv´^^^nA¶'6p6¨ö>óšf[Fï#Sü­ÃØ,æc±Üwlì 1”rÌh4Gê7£Š¼oë*ÌË¢Ñ@çõûeYÖb¨Xª×Φ °pK]So0:Ë;¶ÄŒÖ1ª;Õ3?ö‰!îð~eTµ wÖ³¤ko°AļwV|dÄ›…¯ºŒ5:õXâ» wxŒ;è`~i¤kFãÅ¥™íZ¯±ïÒœ1+bØ{a@àŸŒÇzúW¿T}þ‹4­êï>ö§úè§nQ™=^oø‘oÕåXkÕPÍ}wé¶µ5Uu­ápQKËËÚ»w¯ÊÙTÇŽÓ¡÷«èUôzšŒÖ”=-¯ìTžKãÕ£OfZ\^Ñ^¨Å^OGÕÁûïÓxVj8\PÝT*§ë4§óοP+ËK’š6z”5ÖF#ݯÑh¢zcA,¯¬hïÞ}ÊÔhuõ˜Ž9¢ñd¦él¦£÷Ý¡ýûGZÙ}žš’ŒÇŽÖh¼ˆ—´oßùÚ»g—Ž9¢c«ÇtìèQÇë×ï÷ûÚ±c§ö¾TWš•íÿä'tû¤ÔÞ+þž^pù‚ú“%íXÚ¥g|í7éÕ/y¶êýŸÐoÿê;tÓê½úà‡?«?ãñ*g¥2eR5Ñ®¯ø}ïWìÔGÞ÷‡ú«koÕê½Ö_Üô-ú¶+s8|X‡> Ñh¬Fë†ÔÊŽÚµk—ýõÚçÜŸV×Ö6N®;wé¼óÏWÖÔ:rø8 å»tþ…j:êÈáƒZ]éü .To8ØØ”¹2I£ÃuäÈ1Mg3M«F÷Ýy«î\Ù©å]û´zð€î1ˆÑ IDATŽ>¼~˜Öë‡ý®Ý{´ï¼óÖ×ÖŽ ô¬§^¦Oܼ_7¾ûÝÚÿeߥ½ã5)ËçBÙìì͆¦Ldí{G+¸ñÚeÃC—½f=VóêJ dRdW¸ßц¼iL0)=–bdÙÇXʼnetc Fƒ3z>cc,và¥'ȇ½û[,..êèÑ£'ä‹ÄÚû±Ô©s˜|lI.*²¢‘œj¿‡Éäz%¤úç£G¶sFà6ÛtlBƤ_GŠ„x¿ÑóÅñ4HŠ¥ã r˜_A.µŸ›y€,{Îù7˜÷wÚ0gŸ Wœ{FìÃCzŸÏ6~s$É œ:R¸‡Iíê¢Ʋž4ô˜ëP×µVVVZ+Ò«IãÅ€…åmü±Œ1£nt0°‡ƒ÷1½¡«««s(s÷XmËzƒeb™wa0Á.ô¼†×ΡC‡´´´Ô–Ñ5õ؇óÃü 3ƒÏ#läôS·±° ;{³T¼AsnIbA‡®ªÌõ𦣇 ÊÑ“Ë5ÈÈ)`±¤´÷_,ËÈ×)HæÒxbÿµuÉî¢(Z*×A/÷¡Çvaa¡í×âõLCŽwÌ`"?‹…À|4ï­HëaivëΛ¤Û)ÅV âãñ¸„yÞ}®[ŸûŸuœu¸Á;#h^Ó±j -ë;°¬‹"îðçb•µµµµ¹ü]F5ˆˆ;꺞È;båÛ.Üi§]¸Ãg5ƒ]% I[£ð¿ÑhtBy|æYÇZÇ ‡ÃölŠEISå;~ îؤ™ìR­{ÆKõ;¯:O¹|V;n¸JŸùÁ=Rn™Ž?i¹6Þq¯¦Û±î\ýÚ¯=_«‡¨¡/e²mÿáçôÙnV­ÙR·ÝQº4¦Ïxª^ò‚‹µ¼PÕ—ÿïßêŽîr æ´íkÓ;¿ÔКg¿^o}ÎYªn»K?½þzÝz÷ƒÚ[k)•Ññ²^øâKtDQÚ»ã!Ýøíku˽µ¯‘RZ)†Öè…ð]´*£fy‡îØ0¡N»«•çYQ+5 5Ç®g>÷¹:ë„UÚ¿g›îøÞÕúá-÷iW¹!u¥ìàrûâßÐ žt¼¦&ÖW?þ1Ý2±L¯ý_® –gtï×éŠþŽö6§·}â•ëv{T·êöŸéò/~[åü°ÒšÑ Ÿý3}czFÿýê×WìÒß¼F7ݵA{gºJKÊ—VéY¿õßô‚“—©Ýìhùqk5’»U»Êwê'÷•õ¼rJgr½Ö¸7)œ›q%­T*õɃr€=*õxÑ“úBßèjÛð†>@ÝŠæp©pTHa·Z­öÄ6¨ÃMI;‹¼vFN®»…q€›4ÒX•òaa@ïk£áT ø¢WUx¼O& z¤•°*È #«R¤¦oùºêõzï@!`à%HòΣšSô߈³It'f§Ê‡¤ß+¯q6‹êh4&—™‡ÝÕ#Õ/v¥  üNXI5jg‘rÈá~ÒÞHap2Áʾß)CyQ•‰iBL" ÜÙé'Í‹æmNR9lLµ!v§ T9i€å5í6£|¿ß Í £\³Å$˜û{¼¦K¥Rïw‘îÉÙª‘ÈÎ= %bý;Yµá²Ÿ ‹¦^Q0È1‡â\Käç<?Íöb·:I:‹³{ÍÄ’€–ô?Ç?®[w¥ ½ü¼]AöYdpé}ýi|¾&[ǬH¢:'­)*ÄûsBÀÄ´!îS‚üN¢¥Ÿ‡Ï}=Tg‹É^œ™…†™™™¾$Õç¾ãg—Ø=âzdlc2 “lCüŒ" Úÿ¯é8_îwÆNwô"˜ˆƒá²¥"îpÑ€æ™þï¼vcŒ;ba‚¬29øÜŒ;HÃõwÓ|š…ŠÃÁq_²sãX㻑Iƹ}™ÈmgÛ*!éô\²åáÊ”¤®Miÿþݺó»×èÚ›7ª¸ú4½ôyg(³ï^}÷Ú›ôÕ+;{£ŽL)[ÔÐPV›×Oè)^¢Ñû¾¯[7<¬ï_½A…cž¡ /§Ò²Çéüœ§ÕKòjÖ§uÿ×èÆ¿¥¯­=E¿õô£ôŒ_{…f~ð=mÜQÓêg¾E¿wJQí‘UÒÌ.ýë¿\¥nîêÔs/ÑsÓÄC7é?ü®>ÝY¦?xÍ“5¹åvÝ|ÇF <ñRýöV¶S×®›UÌÎn´Úä.í©L©ÓÒI§ŽJêªÝî¨Ó™r“û§Uß÷€î¸gJÝnN'ž~¬JùŒövº³4•R{z·¶oiiË–mª7Zj6ÇtâqKÔ¨mÔ]ß½Fß¼}»–s†^öÂuêNÜ­ï~ãf]ù•´–¾éÕZ²ÿNýàú»U?æt½âeOÖò|Gå‰íª-™Í¢Ó™¬òƒ*‹ÈfÕjÕ•Éä400¨RvP™n÷ÀÐŽÒZ~ÜuÉsîו?¼Gn^OzÅÛõ¤UeV-Õ¾{¾¥ŸÜò ²g\¬7Ÿ{¼ jjbóåŠsŽ»])=´ZG–²Ú6ÑÒöû·ª{Êñj·Ú=Z-V3ì–̪}ôœàÁ©¬E#.ŸÅj“7V1£Ê›ˆr¦ˆ‡€7|¹\îãHs Ù……8´+s>`˜PP!ªà8àìdFŠU|’¼qhF妸¼ýϾ>Îé1‰ bÁ…Í >=OCÃ4z¬x ñZÜåŠb$‘¾Ú¢b”×-¶h Kú9ؤ©°£ÇßÍÙº#ûpdÕ˜ŠHLD\e4öuº³ÇµÆ¡oàÅa{&ZÞ?(¬€ógØ%‰3(<0©Øæ}ëØ@àk“Ã(eÌŽY4m& ”IJ\LÐx@31ã,(%ä©Â¿—¾+¾wv¦ PSHᢻ9+·\¤ÕÒö Š|(S±Ó`ŒJTò"íÃ÷áïç ~œmc¼f׆꧌›¤?Æ$!*÷EZq4ÙsRì‹D^o<_ün\…vÄϘ”\ÿ»4Lþ ™ÀºhäØ@‘Ø ~¤ôrv¢Ñhô(ŠN¶¼_|Ü뤰²èk`òÇ9³¨LFkïŸóLfPDºçI[b眂,ÛTÛcBOÕ.J}ßîQ^™2ù<ç×£!+×! 3æ<+†;œ G°güø>­x0ÜAŠ#çÐW’pG(ÆÅ™*Ò˜w°ã“„;¢d{íyMÍëÌÄMCò'ɯ'5¡—DT·ë®M{¤lFíÚ^Ýsë¿*Õ®ª›É¨5¹]oÝ¡5'Õ•Ôi¶uì³_ ^p¢î-m×=üD•™ãô¦7ýšÆvޮݥ}[¦µqÇŒ2cI)uÕU¾4¦g¼ð=~ ª¡é[uûåwjëCÛ4Uƒ1Y»¥}“S*÷+[¸{ŸÊ3M•›ir-mxpR¢ÕÇŸ¤¥?½N:m•Ž>]gœµDSÓ3Úy÷uúÙÖºò…Aíßö€nÝ·Q­Ú´²Yí¿ã&mO]¨áâ 2é¬ÊÞ¥[ U­^½F§<ùB¿*§v«¥F¥¦f}F]­Ðêa©Q¯«Õ™}û§¦UÞó€®»ò*Ý6ÑÖòcÏÒKžuŽÒÍYºœ¤T¶ òÍ_Ô_ß–R»ÕP=½J—üöïê©ËÚÚýÐFݱiR©\FÍònÝuËMR«"e2jìÞ¤-{Ë:fÙR¥;i5÷ìÐÏn»CG±RkO8Mçž¼V9RO”š›{R⼇ԕ”R~h¹Ö»FÙëïU£›Ñª“ÎÒNȨZ­kóð°Ò©Œj×ë–Á–V¯Z¥“ÎxŠÖ=n‰Ré´òùœ”ÔòbZÚÝT}ÿnÍtOT)›ž7ˆH HÔÖ'‰òŒ4ä¡E:@Rg rñeÂÄî yÍQš›­]ï/ ª÷¸ŠGÙhRŒ¢ %݈ôv¼¨nâßã!\òâ¬ÆøÐ®V«}31ÑwÀÔ'iʦGÙM&uу#Ï6›Í˜àÂ9¶Õ™Ì²ez‡B)µl€©tî ø}°ÒË€[ä¾Gl<#M†ÌLDزŽße4—ä!È$ŸT5椶‘ÉäÒÂ,DCK*{ù{éÓÁØ?Å8Ï„Ý_·¹ûþ.ε|f³³´[ƒ©Hñ5@D³[?Mþr­2¹âý0Ig×”{ h`MZ˜4ãX4&ŒI.38ëéê*»«\¯(Òˆ‘û•ÉhÒÐ8‡™©Üt(Üg)còíŽC’ZÕ)iL:O™žãe1ÄßaÚ_’Ÿ“ >®cÀ¼Ž ,½F9LN¥F™‡††úÀ#ýù\¸`G#J1›ú­$¨.J’ïÇâ ü;±ÅR˜´ÂICUÿßw’ˆ翨rÉ9jR¦ün9Çç£açÏwP /*tEÜÁä‘q‚Ø!v¦ÈLàyã Õé=èõèÒ:…;h9àßGÜAA1&%ŽOîЙšÇwìnº;Ä<—{Ï„Õ7ý5P)¡Ë¶äl7Dê¶gTëÌ %6+šœ˜ÐÄdU¹ÑQ-𕿣.uº­QJÝÙù™nG‘#µrp6qIÍìv««NìÔ€ŠÙ®ÊÓ¥†•ïJí™Í4$3VKµéMúÞg?¡Ë¾öݾþ!mÙºUÓm¥S)µgZjÎÉXtïÎL©¦”Rê¨VÞ¯½šª¶TZ¶\cKóju³:þñé³ÓÒlEÞy‹¾ó/_ÑŸàê37lR&“š{™}2ʤ¥Ü܋޳gvmº[ß½òŸtÓæi =^¯yÛ›uòÈ\µµÓ½I©Ü  J§¥TmJ;wíQ;•RºUW­ÓVJR«QÑäÄMì«)¿lTË—–¤TG…±sôŠž©±|G;¾[7|÷ëúÔÇþRyÅõÚ[k¨ÓîH))¥ŽÚ­–ºÝŽÚŽº ½ë—ºêv;’°:-©ÓQ«ÕÔÊãÏӥ矬Ñl]ß{›®ûÆUúË?ýˆ>ù½4Ó˜Q³Ùš½IÏ=aS‰æ€˜Á¬öDÃ7o ÏJ[ÕØ}¡.½`ôº!G—‰dô!Á΂7ºÁé1n岪éK<$òù|e®X,öö£±“‹*$©ÏÙäÕ|92¶r}í¬SÁ2”F>¨Ù²æ¼ò£ «[úæ~Sò8úM¹BHGuŠ,˜ÞâwU­Vû*ÞN¹è)«k¬ G¿Š(ƒ.+ã>P8ÈNÑæÓ3„À˹̦8Eië˜lSaˆ÷A¥)+ÜäŽeœañsô÷ÆÙ•(ýZ(4444o6Æ ˆ‰i©TšW±'ÉCïjtÉ&Ð&†2°”-uÂì5åÿ^*•ú€jœIàZõ{óü‘U¢§ߟ·ã’é–qÞÿn…Qα+Iv±#Ë‚Éd, 8éã,‚ç1ÈÒ0ˆ0h‰Ý¬jÉ+ ¡¸ Ašq㻟'ï•ݤØÝ2ð2Hr\ˆÝTúñ>èÅCªòàà`o@ÙkÛÏÝ{%y›x‘þäŸ2öQö˜¢C¤(™ægÇuMJdLÞ¢?ã–×XµZ'¿‹}ÞÏLD½¿GOêõz¯+Ì3Š¿#*¶Q9Œ´^菱8Ñ0¥Í E¼®$Üq‹IѸ” g‡"–fbâŸrò,8r¾‰ôYã* wÏDÜÁz©TêÍr9)÷s¡Á¥gb†;xI¸ƒñ*âv£YfŒ&{€‚Jó:3T¸á§²…\.§J¥›¤âÒq-Ëå´C-­\÷\ýîooXߺüÓúçÝ­[¿ò5¾æýzöšÕZ–Éh"%õ„éM/=K¹NS­ú”&÷Õµdl…ê•Ý*žú<½íÜŒ&víÖÖ~¬¯ýfÝ{ëzM>ó‰*)—–R™mÜ´S§ÙÕÄž]ªµR½çß=W)•Î(“ž{EíŽ*{'ÔËjÛž²Ž¿à×uúÅ íÚ¹SÞñC}ÿú»ôãoߥW_x¢šMµší¯v¤tFùá1e5ë7³L «Ü>`™P »ÏÎN”¼rV-ɧÂ74¹®N8X­]È””•bÇSM„ô1V#¨bF DVœŒø0n6›=jP”Áä,;­µZM¥RižÞ<ùÍþ³XMõáàù–¨LdN¶½¡X}ã°"y¼TFŒ4¶ŸÍig5œt–(ÍUÃüè¯âêÇ¢âZtmê«æ`ª\.÷%„”™åúeráçH¥“¤ŠcbÉnåÛãü„ß_tÁŽRÃÑ|Ò×}’è'C áÿÆû¡Ê¹ì•J¥7DM@ãwG>{t®6ðàµQÎt!ï;'ò.:`úŒŒô€A«·~®^Ó4—s²Eyc‚\ 3°JOðOðÁ®+Ø\ÿIó%‘ÆB ç’¨œ¡ñ³1sL£)!q»`Ñ?(:˜ûþäÆIÿ<“R¹w˜Ç/ŸUÜ£,ˆp&“TRäÜÍ-DÀ¹vriÍÙP+ó±xãïç,L§Óé ¨ç÷ä?‹T,‹æx6ˆ”ã@¿7Ò—¨b˜§gX$s&É0’VREÍ  tpô”aGš4+ûÓþ)~îÞ³|?TÝsÒáïcÜf±.÷è)E;†Gw°“Ij,;ôœ!¤Ø;­T3eâíäÙÔo¸ï‰;<×ÃBAî !°“yÒÌÑŒÏUQËÅyšL:Ý£!¥$–ÿÝó¹´ùÖ+õÑ7j8×Q£^ÕîJIÏ{Õtú‘Ê¥fÿN·;Û±Èf3³ßCS)ƒ«n§÷ýRJ™)ýäÊ¿ÓýK‹*ïÞ£N*¯uëNÓŠ%Ú>÷WÒÙ¬FX«eëµgf¯n»þëÚú£úÙ“ÊæÜOkd騆KCRº®Ý?ú¢þ×=#ú•‹Ÿ¯óNª.yêõúûïlÖ·¾ò)ÝùýQåº3ª•'´9už>øÎ‹5¹ù§úò?ß®e#*²ªí›T³ÙÐÒÇ­V1›Ucl…––F´ur¿îpŸ~õœau5£?ø†îÜ:£\>«ve“¾õùOÎvE†N×ßx‰ò™´2©Ù{í¶fÔÍ¡³Î¿@wܵIë÷Vuó7¯Õ¹o{…^pñÉúÈe7éÁŸ|I¹é*eÚjÔ+ÚQÓ«ó :&ó.ÿÄפËTÈ«]Û§f·­Á±-Ti`…Ž{ƒòcK5PÈifjBÍfS#G¯T)—ÑL½®ÆÔvm)·•ɦ4~±ÊuÚªÎ/$&¤Û$$9¦sÓyó³jíJ‡CI/1ðaÇ„A!Ê9SÂÔßS*•ú± ¢J”fÿï1~WÝ/ª¤¸ÚæïtÐð÷ø9Äv49ÿ±Ò©ƒ7ªï›ó:.s^/çPH_¢úŸc”^fñËûÜk¸ž9WEZ$):=.P°cÈnÎ>°CÄu¿NìØÒ2ªïD3Az6Pà‚‰”‹LÙ¥ãnœÏŠÆžT‚bWÙ@ÏÏÊï›´#&pNüçLiÈ“߸˜Ä˜²M ÂøžØ1òºöúåÞ]1R©lÏ3Ùµc"ĵIÑ }Òæ"ý5>/wIceœbAƒß Tû"-Í °ß5×(Ÿ åt™0hSq/ú“*JY}+Æ‚GìÞ0áfŒ&}ÕU|ŸÏQ ÷äXFAšNz­Óº€ï›sl à’ŠzœáŠÔ-¯wR«|­”Ä®T*½"DôЏƒs'‡ƒ;\¼{$¸ƒ‚ Ꭸ‚æXK?#ªƒ.„;˜TÆN#%™Yðˆ¸Ãk—¸Ãßw`ª`‰›ÛÕ\ÿ·F£Ñ§”P«ÕTÈç4:TP·ÝV§=ËJ*ä :î‚×ëÞñ*=~Í€ön¾_÷?´YûšzÂÓÏ×ikG522¢áL[­Ö,¥)›ËiåØˆÔj«Ý™}QKGŠÌÍI¦Q9UWÃÇèÙ/uÒY —4œëªÝn©«ŒR’J+OÓËŸy¼ÚíŽvm¼S7ÿl·Ö<ýµú£?x¹NÏi÷¦ôÀÃ[5ÕÖ“žñ4xİFÇÕé'Ž«1¹]ÝŸÞ2©¥'_ ß{ý ´z$¯‘¥ãºàE¯Ó¹ÖÌÄVM¦VëÂgœ¯å™†Úí®òy-+æ•ê´Õ™m¢häÈsõú«å¹–öïÞ¬{ïÙ J¦ •«Öê¸#ŠšÚµYÞŸ¶î®ë¨§¾Bÿãµçª;ÓP½1£ò懴·9£|þx}jQ­Ö³f³©r¹Üã­»re^®ƒ:gH™òAë®!åÉóteÕUNªkXš8‚OVo}ÈF©PÒ°¼V}°‚200 l6Û£¦6ãß4J*“CË90ÿ>*½EÙ`v¢d4•‡¨æD è`ÈY _o±Xì݃)Á³«ÞÑ3Åïgzzº¯¢ÄØú;]ábU”žA œ~>ÄYeEº^¯÷ù89X8LFSC' qM³eÎê:ùùLâ\sË޿ݵL&Ó«ÖÑׯ©×©4~Ï5¤c¤»³gP 8}ÿƒƒƒ}~LÒ¨v×tTîò:Œ4EÞ'×´ß“*œ‘³Î•”Ç ¯o'Ó…BAÅb±·cÃk=*Aˆzö!ªjqV(*/Y„Á ž×4ÁeÜ7^¿N¸}†{~Âë‚ »ŒLp¨Êd:UµZíÑÉHó¾gÊ‚ãq.—ë[Ó¾>ÿÓ¹ „?-Æb@ÃgJ(oL•+Òd9N¥F_O&“éÍ¢Txú¢7;0.’Å3ƒ‚~ÇqœóÚæ<Ÿ1»·\?ì6û¾¼w½Ï¼¶ü|8£æ„Ð]ú¬¹P˜Édz²ý¼.vÆ8Säý`z4ÏfWˆ=™Rú<ÎM9A«Õj½}ÆN‡Î™HP4Åç¾ã¼»U4U¦L{Ä~ÿ>ƒ8ŽAÓ¹ˆ;ü~ªsÖäFÜAe0vYÂþÝô#î fbrAaèy“„;8SÊEú›».쎓 í3ÊÝEâŽyXð²Ë.ë>ÿùÏï“UdPæ ^”ŽL§3³ƒÝP‹šv - *ŸËÌ%ïtÚj6[Ê ½‰’f£!¥sÊeçZ‹33R:£\.;÷3]MLNêž«?­Ëo¸O™‘ô;ú”Å÷¶Û’RJgÒ½¡õV³¥V7¥|VIŸ™z]]IélNùlfÞŸuæè0óe:ª×J¥3ÊåsýƒG’:í–:]©Õõ‡úØ_]¡ÝÙ5zí»Þ«sÆ3R:ð4¥ë† »×ã´§²Ègz÷×l4¥tV¹l¸‚nG­ölbXàûÁLJD&›Óà@!ùZÚ-u3ÙÞµv[M5Ú>I@ÿ¾F«ƒ÷Å?j«Z««<µS7üãeºöæ:îåÒ;Ÿ½B33Í>c7ÒͼÉÊårßf!}*VTH›rrNGzªBQÉ„’Ê Ò‘ãLú+'ô>ðý8À ¨\.khh¨ÇA'͇5V@D(-Lz 9¨äo³BFçe&æ;À{¶…Úî4X¤Ò MlÙ½`bõìiögðÏn«l|Æl1GÉG)²"έ5 û IDAT÷í,àìÖ8H;X’få€L*[¬ÆÑÝ›nÎlÍs°•rÁ¬Àûg©LGÎq- º«‘ô4*jjì‘Ò‡òí @'ð\.×£˜6è?ô¸¦ ˜húJ × iÜ ü{f° L€Kÿ î=ŽäsG*ÊÀ'©r¶ÃïÂ$ÒÞ(¸ãŸcÇÌ?oÓ>¯-ð¤ðl0~ºíýâj6;$2¦Å™1lî;V_)Õ%oYÑf|ˆ¸#úQ‘~dÉî…W(DÂ.Õ ø>kµZÆÂanÏßxÏS¨€=ÎîP¨Âñ†2Ô<瘳KÂn"ã±;lT[Œj}¼&¯sRT¹îØ­ º÷EÜ=áÚpgÕÝ*¸Å÷L)ùHQ4ÖôºâÜ tîv¢;<ßwìp2Æò¹;ØUŽ&ÄÄŒG¦P³ÃÊ¢qÀ£‰;¸†Œsˆ;¬Îêsç`¸#z=±ð»Û±[;ê,(QJ< w°S™„;Øùj·ÛúêW¿ªÌ‹_üâœtÒIóO¶Aýß9¬8»@Ô·xšà¬vÚ­>nv4vjÎ…Î\É?›90Ðc•ƒ˜)Rõ¾Õ ë·¨“Y¦³/:Oc©–ZsÉS«ÝV&›éÞl6›Ê¤S}Ò€”ýëµÉš> ~¿˜|.§&$\ ÚÙC ­.ª^D-ae3ÊŒ¬Ñ1ù)MjHËÆŽÖãjÌ=Gfü¾¶¿‡Ò|ýÍF¿ªU:“™K›½ S«Õz3.¨d¸Ý—3è8øÙôxˆ©tŸs´Ré>Ù=ÿΙFCétª/‘±V­6ÛúLÍLiËŽmÊ?I/ûµ³4ИQþ*ÞTT‰âð|¤éx3r#RýˆU}|­rÀ>š÷‘FÒÓ0G5ŒRƒ<¢òKÒ`rt¿%Ïš4úÏDÇï8â ‡åY  N>«jT4ŠCÞ<Èx0P­Š@ÜïÃUmJ“M'eÒ—Øyè³ÃÂCÄKô!`…‹kËï’üyR²¢¡ãߋa@‰FŒ”'%Õ„‡žk†3Mñ°â½ÄÎiQn›ß̓+ɱž>¤Uðš(çK0Êb;ý HºÅ„Áçg4\¤©5‹dœÙdA‚ëŸ 7“rŠ]ù(úà¤ÑÉ;“Ò¨¢97ïÞIŒ‘œŸ%î Rã!ñÀB¸ƒJ£‘J•„;x¾ùþ’]†;¢à ¿ŸI¥…m¢ñ1ç÷x®Ó§óͤë’Áó#šwpЬ›tSЬ_¿þ@2ãa¯˜µ‘3Ƕ[”u‹/L)S,x`9»gû‘U\.§t*­Òªcõ¤§] óžvŽÖ,)ª=îÙÞ¦)i5QV—@‹°¯‡(%2 Z­–Ú­ŽVŸ|¦Ö|’·zD] ’ÛL§q“(×ÇCÁ„\bêêó@ôŠFYäËú0óÝRb‘ž̰ý¼8ì•ÍfÕMtº'êÌ'œ¤eÙ”ê3ÀÛÕ4ŒnÊ>$ØRõ¡ þh$Xmw€ "ÒTâ (œÛ¾äé²ó᪠»ègѼaýžHéqðg°‹àÄ”ªe…9r…¼UîEÊG²ÊT©’ã5+¡<Ø}Ÿœ}òþ`) Œ=® ’§‡H òb%³%¾fó›Ù #xä̤Àë€R¿Üzq@œ]"ï»Hù#ךɊŸ#邌Mœƒä¥}½WÙað5Gj#“ª­E:†×°i4i¥¤/…@˜¸s¦†CrÖ#HŽß¿9?ÆÃCÀTMcÂîwÁÎ…×V³½Û÷Ü]YŽ¢ì0óÝ3¾y¹ÐÅ{a…ÝÝìH£Œnåœ+¢ï–?)9”o§Å ˜ðG`˪8‡Ô-èÀ€tM~â&±Ž\~Î0`÷‰sgŒ‰;Ê8›ãŽ;OI ž!휃$õ‘Ýïˆ;øãQL˜ø9C—„;’æ¸Hñ¢+øÃœmá>ö9iv!˜4EÐÏ5ä¢);KÜCô:q|âP>×fÄ#ñ<¸ƒ]²è³Bo ž‘œ‰Š*ì¸w°ÓÈuâ®ËáàzÍpÆ…óTÆ”.ÿ÷àž ˆkšEÚØy'îðšŽæ¹N§?™±_ÜPügT3ˆª<ÔhäCMuN?`rí£[»ÝV¦PTihHË—-U6¥¾!L_«fl½RÅ‘ %ÎšÙÆó3 ùX™¢·F³ÕQ:s “ÅÄ‹:J&F7v¶ËyoQ!(V})ÁkàÈ™óX9lF^%ASä/³¢Æ#é^”¸ j4›J««T*ݧ~Å`Â!]V¸b²C:ZÜÞ^Ó>̹N8Ø ÍìAB™TÏM8cŽT‹È ¦+8‡¹ÝšŽ†‡öfÂaj*T¢? 9éFN:UÞø|©öÆJA8ç:Hí2xeUÝÏUlîçx™´31gÄ:e_™Tùz"çš*OZ~/¦WÐ,ŒôOR]ü]T‘¢¬jìŠ\ñLÚØub—$Êçsö ;`ìÄ¡còÓcÇ€ ¾“ˆ¨ÇJUzøN)¹ÊΆ׼×4ÕØHíóï5åÅñÅï5ÆÊ#xðRÂ4‚®iÇç¨ÇÙŒèÁ˜] *ò¹P­ÈÒÐd ÐMÛ …eTI¿ô~b„ɫ̜+p"S(z2Æ<‡'x^ÅY>{vø»Yõ0î ­•Ï3 wø'áÆKŸ³’ι 'Æ\ï<ÛI+*‹½µÂŽy’ªipÄAì0>;Ae“8]™Ä²@A!%¸®“pG’øßC4¡&î Œ.“>P=×åY;ß»OâÊ·³hÀ¤‹4êØ!sW×ö¤N±«AŒùHqÛHÅr,K¢BRÁ4âç3ytÜò™ç›(Ì„Œg ñYô³a÷*ÊÉsO3æ1î2ññó± El"î ;… "îˆl1®ë¾d†A‘ˆ¼B8qSGc¶è~ëÃyh»µjžµï×Õˆ¤”?HpÇ Ége`ɵ%mÃ`‘Õ–‘?ÊÅ«>lõ²»Ájõôù>"2˜ï•,Vþ(ƒK¹`ò´=˜gVŠ0ùß IÏ X‹É_¤cñ»=Sà`DzLLÚc+Ùkšíuÿ;i<¤Ùµóâù V ¨ôãgàï6 t`ñŸ“ Æ`ÉïL¤’ð)4 ©D¾p¬0»²“a*ÃD°CÿH7a< Loô­`àdíyRKL{ã¡HŠZlÍGçbRÊ"ƒIM¤R±—¤ÒÆî )v±èAcM'÷©{\¢¤•QÞ5z¬° Çï"gÚY~g4»$åƒt Rñè[ÃDÜïÒ÷kóTvªøL·iŒJ°Ï}¹?”÷tôå`G+ºÇê°žI‘Ï8‚JóÇý.©\GjgÑ (CR·'ú@±Æù߯ þ½ì¾GAÒ¹¢)7» QU‘€šÏŽž8w,DãŒÆ·Ä‘AÀDˆ¸ƒi¯"î`ìt\çuñÌÀÏÏÜT¯?ǤH¹brCçáH§‹¸ƒ4âŽX¤rq-*ëEa ²<˜@÷¨ñˆáÄ Ik8âÆjS•’¨—±«Í„”4Uâc=v±©Ìv(ÜÏJÂ#œœD&U×#îH¢úPSmr!ÜÁ¸âLz´c+„È îàEÄþýI¸ƒt½$ÜÁÎyì§p‹4dÅ5ȳŽï€ÀÝ{7 wpÝ{¦‹æó¤ê w°cMjjî ºèÁpôw0¡g,9ÜáõÔAe'&ÔI¸ƒÂTuäïŸ'À`Í‹gÇ–W< ¸!ìÞÌj"[Ð>™i›@+Ò˜Ù±Ú¥9©.ÁÛCö~°®8p“±-ÇEG +Ç È7“÷o`ÃÊ7»5Ü@¦â°ÓáïJzÜx¬ŒÄ@BðFYÙàpA:éq@ØïÓAÞÁ4&kìLì`ÝÙª÷;aÛÑ|y:ðºÍm¯¶Š¹Fé}@^7+¯Tóa2Hõ­¨¤ä@;@¬Î³¥J7ßoäD¬rŸÝEWE#p¦º÷ •W|Pñ>=”í ¹Í«’¤³ÙæáEPÌ`J53¶ý£º\¤¯p=²ë};b ˆÞIE&6Qž”ÔWV¾¨ãõä(rüý®½Ïx˜:Àûd',JѲÚÇä;vx(Ó(“t*žQ Štbš²‹áw;gÑô”T&§üž8ì•ÒHÉ¡¤§÷YŒ¬tòpæÌ@LÂãIÚŽcA>A1»,†Ån);nL Iƒ¢T{,ˆ9ÉbG@6ª²pÈ9Ê(RÀ"ƒÏdîŠËDÚ¦0‹c>Oê°$ˆó2wpÝGñ€$Üá?§ÇGL£™1ëèkÅÎ{P¦ÙB¸ƒ¢ˆ;¼f£2™×*“{šFwD kÿ΃áRžØuJÂìÆ-ÔŠqú߃;¼—#î RÖB¸ƒÆ³¤rÅXELˆUØ]LÂL<Ïæ"ãq“æˆ;8O‹òwP,‰s„”៛ýéØU¦‰1åÝc§*Æ•$Üa|A3^ÿ&kœ5¤€‡ÏÈÃÅq.iÍÌ;r’<XÙe¢9ÍËø0@øñ1ÈÆy€hxepÄùrùb7‚­Íh6õ¸ý€È6EŽTƒhŒÕ#’@‡ðÄ tYáã\Ÿu44¢|# ¢)¬+ôñXèRÆ–jo¤`ÐíœTA.44x’3íª#«æIÊY<(¢· ÕrhèÅ ©+®¢³²Mo &E”AôaÀã$ž‚~Þ: º‡– 4c…3µFÊM”ô(ÿ,]è ø©<«Ôìz°B+I”zäœG’â é qØÕ{ÅůA^v£ÂN<`ý Xx‰JF‘â%9£¬/W”öçÀ1i±2ÏØG?v„Xg|lCúÉg‘¼‡]ÅŽ`:z‚щ“wé9ÁÊœŸ)“Ø‘ÞEÞ5gžXÝ7`£ ù>kØN*°± )¡Œ5<´ãïë%MÆD‘‰D¢±CGcJïMÇ%J“}àª4=38O•~brësÆ, žMqè—à…{ƒ•{ÎÖÄ lˆÆ=ß“Ÿk’lqÄdÄbl¼ìGªÙB¸#JLGÜ;ÍŸ`uÃÖ´ˆ¸ƒt&&㤱âo HIwγqO2)à°> >¾>òS°â‘âŽè2Ÿ„;Ø!áz`gÞïœ&·Qù,ŸÏ«\.ÏëÖÇù¬hÌm¬ÅD“¸Ã×@üš„;8/Çî@vW½™@w°X©aQN9ê’pçAI ó@,ú°hFÓ^â';TŽEǃáŽy33'Ÿ|r_++r«ã0"7K "§Ÿ’p¬(Xé&©òÆÁª‡f­VS©Tš§ ”D7Yh€.ʲ-Í€=* H{ r[9ȇ­ ÄØÝ0Á`Ua-Îøw¤E)Dª{E×l‚cpš’åŠ]e9DÊJvôw‰uV=ÌÇ–¥ýȹŽIf4¶ä!N¾'»†¤W±µÍJ0À¸þéš%^í“$¿Ì$3Ê@z½¸Òý@’Œýþb²J50?K®o)SL3cÇ’³0¬²°Á@Lã;ª#E¤H9#@&íë‰"캘nèµÅù'S\iöúáÌHt+’¨€ôÚá| e©}y­S9‡£× ;Ò43}êˆÌÅý²¢z÷ÝȹÞû˜ S:“†‘ŽÍq†± ‚–¸.GÙÍà<ïµT*õQj¨êÈ¡{v ©ð;°ô5¢²¤A“×1©V±jé/Iƒï\#=¾n F‘ªkú ã'8Ÿùøþ.VÍý¼‹Åâ<Å._¿¯‰ 6zêDgwr壤0Š1°{» Ð.:GܯŸ….&¸^Ó6W>\ÜÁsÏgSÀt±gA&® ¯oÇl^kôý£b)qGÏŒq×ÉKœ§aׄb5Vÿâ,‹±0Í&ÎrºRoPï÷;33ÓëB,'áÆå(QÌ‚é^\o\§>{…;({N[ Z0n=ÜÅ&X°f—‡¸£\.'âÎѱ8ÏÄÃԳؕ?îàØC”=gdž׌wP¾9ú%áÇ"Î\öuf¸ñ |ØB‹Òq®€Ù8‡#W?›Íö€4Û_¤t‚Dðe®8j¢,,+«ü.‚Ro ¤V{ìd¥ØÕíÈYfòÄÚó#4}¢¤+gI8¸m ¹ ¢šÛç¾ïjµÚW%`RꃔF›¬ó]r08úÍpã»ËåM¯ü\yMI€—É;zÑÛ…÷µÌ-«ãѼŠ`ȳRÔŽ§‚ŒïX¡4«Nc7‡× D»FïlvÄ8¢ ÎrM9™e¥Å‡T4‰äaf¿Ò4Äs.…óBÑ8‹UmÒ´âàrt”÷,EœcaÑÀ‡rÎÑ/ Î{ñ}DÏ&þ@îr±CÂyŽH ¡jaäVóù $ñ´£|T”‰@1ŸÏ÷ž;}¦R–C7¿º—{-x†]e>C®EÇrˆx¿ì¸FzÁ¢«×”Ìæúb·‚ÊTôŒ‘R䤎RÁì°²CJJª£¼(c÷žçÉ¢„¯Ýû€Úï¢1iŠàʉ å†3™LïúÜŒ ‚]Hb&ÿ^ÓØTŠrƇÂñ,HÂLX9Ëⳟ³ ¤.*¹P“„;âžMR„JÂ,~wP*®éˆ;›‰;˜Ü%Í ²xê=@ÌãgÁùfŽˆ;"…ˆ¸# Zp½r˜¸#ÇZQ±V«õ©$ÒhJiwÄNˆcc´¯ÓUw‰;âðy¤wð™w°ØËNùÁpq©¦ÆQ.ÚëÀE âÆLïëØý!Ë#âƒáÒåhDK#ÖÓˆA"îàŸ™F á¯SvµûhfîÌpp5Ê"’ÊÄì?‰ÛζƒùtT ‰Þ(q¸8IqºålA‘B~aäÙ¼p‰”5fµìHñŠ’…Šã8ÙcE†­`—8pL :T€!g?‚†8 ÊCÔ~ô>gâÍ{æ³×ùîQ¥„íó83@ÿ=vh8HI¿ ®kRx¼&½Ï@ Ì£oKL®¼Wã¾b¢jjNäÛ;ž˜QRU4¿z‹fAÃÅ(±ÎÙVÐ}xQò+ŸÜŒ±Âæ@ÅàIî*1ùˆ­¬–1EC?Ò­(1Ë–fÜXlÆwc0ßK’–99±t='†êv±b¹âqC29p¥ŠJe¾7š™2‰r«²Š±+@…>&¬“"Uøû¢ü-«‡¸œëàf%ŽÜq 0VÔ9hKàËåT.—ûèE~n¬¾Åê·¹­<ÈH_`à•ÐQΜ|rÓb²çÆ"7ž³!>`½ß¢d2yÚì3€F×ó(wN¾=)$¤pÅ9Š8£½~©0G èd ÆÞçmœ? UËg¤ßß%å­©*Fðcãç7éÂ$‚42&sQ=‘«hÚLÜÁyLÒ_†;(%;¨T{Џƒ{”¸#zâp.)JÔSægoÄ®^S=+ wÐxMÑ, IDAT8ú|ø2ÎrVŠ….&PLà¸ßè)Âû`׉1ç`¸ƒ×í³™óh4^å»±k|ÄÎÑGÏ…$ÜÁ.|¤ñÅýM*kÜ÷z¡ú¢‹YîèržÇ1Úû›÷kŒÀû¦Tìjw°àN¹w'ãCÄ,P³ÛÌXFÜA,Ê…pG,¸ wòv(ÜÁÂV4gŸG3#¿Ÿ ³H£;)+(Þ4µZmÞC¡‚+¥ PôA!¥„mÆ8·áõí}F#½$ÓNf¸ ^T¦Gq𗇆ÖB¡Ðû»ü^º&3 19âaAž3+0®À“I]}vxx·ÛmU*•¾àK‹8pÌí¤à䟥$ŸïÕmñ8|çêAolÝ’¶A>1:;|L2J8; ƒA©$Õjµ Å¡éèBOyGò}£³¢Ògú¦ÐEœGóþ#Uуƒƒ}I •XUc5Êra9ÓÅ5åXé²ÌŽ ‘™¨úw°“IjƒA]½^W±Xì,4ñŒÞ%ŒA¤1ríp?R¤ƒ¼sVî ØÖ^ ñ~£¯¿Ÿ{"¬”‘÷Ïgí9èÎÅÊ*ÍãXÒÐkçšæ08+ó\?q°Ý—F–‘Ïâ‡Í#eÍïÛÏŸú¨ I‡wI*•J}?K_ï1Vù£¼1%ªYÍåÐ6ןä Ö˜ø ®T*=æ@µZíKâ`,ú¸vØ!d·¦z,°EFcס'ùH‰²ì¼N&³¤ wx ,„;xþî`‚EÀ;H‡ƒ;8ÄlÜå°#}. w2J#^ƹƒáŽr¹ÜÃü}Üï1Þ±ÈJŸ'ªMyo9žxù;;X(â¤ñL¥Réý{ôxYwDq‡×Y4`rž„/Ëb’IÉæ(´À3•¸Ã1ƒÅ-št&á?Sw¢Ä4Ÿƒç½Hs#g‡–…æˆ;xÇÙöˆ;|”$'îð~ŒÉ»ÚI¸Ãg£ÿÛàà`î`SÁÇ](ÒÞIyž§fÆJÛ£Q“Û`„í3R%¼yªÕê<ó0W’Ô¿b+>þñe;:VéÊAýhÄλO®pÅÆÖxTªqs•Ä™”ú±°ºÇdÐÏ£Z­ÎÓg޼M¼äò;x×jµ¾ÁB‚vº¯Gs̨¦ã@5Û ²üìXù&’•¾ØbõßeR)eI'ΰ5KŠ[ø|ó{ì›Ë §•à–ê9ìúÐD‹‡fìðPí$*oñ;üÏTú‹ô Wøb àûâ‹~1Q*;ònÉËó@|–|nÑs(¥Kê©ÆÄÙ5v/8Gå*“z¯/Љtúp#€Æ©Ñ¡Û®æ¬²hS1Í×)?äõšl0àöáÀ*?6}¸Ån*ŸM\kþý^Ó¾.šFÊž“¨æ=ÅJbÒ%M…TˆØe#}ˆU@ ²ÐĘÉJ7yèìºøÏYÐá,€¯…T _ çë8»=9ÈávBHyŒÑ‘‡NÀOêš+ӌΫœyaW(ÊU“º;쎯 w8°ðÁ&ï™Ô™¸¦£|”~¤¸ÃÏ*úM%ávë#-9î-¾kâv…£™4sŸ&á+©´2!R¾ÄTšåL”¿+z©øïòŒ[wpÝð,¦ð ±ƒïÇI»EÑ™³mI¸#ÆMZŽ$áŽhš©ƒÑä’Š¤I¸ƒEKRç¢>ÄE‡ÂTÌ£õiÌwDÉö¸¦ÙãïåèH4‰fnà‚gÐØÅ‰]ñ¾d&Ê(²‚À /ÛLœaá!ãŒÔÕR=¼¹Y©Cíê [¿Ñ¿ƒ &úø»É©æËŒ-,ÒdÐü½¬ž03u„™>+GTìbõ˜•|V^ŠÅbŸ‚3Ò¨¿Îê&ÎyÀ’oÏÀMS'VϘX±’ÍÁ¬hÐÆŠ*R4öck5*åE§p_·y~6ä}“ÄÑ&¯)š,’KµÙ½F9\êf€>=Q9†>+Q‚Üê$©M&äœ2@ð0¢,0+TQ튉«ý½Q  Ÿ*ˆ”Àd¥É±T*õU-Y‰ŒUòjYÈà=Qý+άD¿VHå¼Zø,¤oMÐHÓFVÌ#g×å9*VÙ7‰òïa‹ \4M’®÷Zf!ÂCàŒ—¤žrXž×ß1“1Vå#¿œÒý|Þ¤9EWmš@²#ÃuË`òÔó]1¸Zo?îG'¤'R>›´!|ð=pؘà‚g) o<crÅx«¯œ5ŠŠv±NO îKJÔ’ÉgÈxÆ®!ÅYœEZT”}2èg1Éâϰ€ÆõÌ 9• Ù±gg­b%;JC³›çø¸÷£wYÒŒ%¯…°$%Æ@ƒkÆ|ΑÁD›QÌÁÊmT¥g»tT]ãÜY¤ËÇŽs’oŒTÄ£ðáÈ´‰R¯(u»dÅN6Ù¥R©—4“‘@Šc_X(qŽñìL{ß°“ÉN×ãŸãñrô]d¬ó𤟱óÌ5í¿Gz!ÈP ®b××±Ôë4 wp¾TÞõë×+KnlTÆñC›˜˜ÐÞ½{û¸š\@Ñ(Iµ&šëEóÇÈ(é™ôaÖÉOJŽÏ%ûL|ø{âßMÊ„ù瑃‡½z{Öñ;££u ŒñÅëIºÎ¤wÀ ôHÞ×Bïw¡u[îñ>ãµÇï‹7IYƒ‡HT[hM'­¿¨&ÆöŒzñ]DÉϤ÷x¨çž¤Ò×´+ú+V¬èP&Ü7J9Gsà¤gfÀ700 ññq ¨R©ôc&CLêÚëvqîŒ3¼Täk6›}ó/L€I£"…ͪHZ¤3’¶™ ’‘ÞIp‹R,`rN‰ô à¢W–¿“7v…™ p½QÅ‹óUNN8¸^«Õzƒó»Ñ>‚×M«©ræûs÷˜ Ú?f)’h¶‘^ÅY_îE·iL|Ñï‹{•’×år¹Îæç\.—{‚#ì´Æê(KÏ5ÍnHô²#ÞJkÑûЉ•ï …BïÖjµÞÏsî1©I+–$U7È¢y.i1d™˜f愤P(ô јTsªºEe]ÓãÌJˆíTí"…•{?vF¼¦Y,`·ÊJ¤. Pm× ˆï™”ÏØÉô½’RKzYqxŸ3nö·úeì—ËåÞ»*•J}×ÄNU}™üq&=vÐ9_Jl‘%ˆ¡™ññq-_¾|^Epñ³øYüü×ûär9­\¹RË—/×Ã?Ü“—L¥R½!d¶’YÍçóÚ¶m›–-[¦ñññرøYüü|²Ù¬V¬X¡±±1mذA’444ÔçãDZ%q †Èwq•’÷üx¦ÊkôÐ!…ÐßEþ¾glˆÉ$‹•gÒê(TÄù‹(KËy4ÎAPàÅó¾>ÏÓE:M”²%½’]š";FG{ú_9ù`ÒDY{zGEÓkwXüNjµZŸ?}¢Ü© ÀƒA2«ïú‘NAv ý,|-¾¯A¸ß=ç1hLóêb±Ø—;éñú¤ä°Ÿ¯Ÿ'÷“Ž8ÏG s4ÿ¤ñ3iûœwµ° UÐü^9;Ì÷Õã|^›¾ìN›¤àó99ôžàl%× ÇZ»wïî™FN¾DÆM›6i||\ããã‹1cñ³øù%‹©TJG}´öîÝÛ'Ø!©—xPIAªA-mü³Vê2€ñ0¸64J:"šˆaòGU²R©ÔÃM4‘¤D®A¹“š>ÆÙÆ(kNõ6_›ÿ.¬k°-©÷œ}}îJp¶êYœ'¡t0ç-zb°MpNʱïÑ@—j~~îîZ±ÓO9þ(ãk Œ:a9c Ì(ÎÑÈàÝÊN’½ýèÝä÷ÄgÃÄÍâ"œñ#гZžeòu:ÙæšŽÝB£ EVHå£È饜#ròlÕ°hͤ—ÝVÚ Dõ3*#RöœŠ„^k´7hµZªV«=åGî_ߣ;•ìþ¥ŒèžËå´téÒE@²øYüü’‚“|>¯ÑÑQMLLô( ƒƒƒ½v¼*ü-ÆŒÅÏâç—÷cÜ055Õ7KG9öjìDsÐÞ>,¨¸‚ldš“ Ƥh$Ké] 0¼qöÉÕêjµªZ­Ö—lÑß.i^Ø@‘r¹õz½à9{B³PpS]Î`Ïô cƒRWë)ïlꔲ“&¾ƒmw£hŽlð¥ß£Ñ&)Ýå 2Íi8ék¡±µÏ* :9k4j4=u@?'y–f—ÌIA´×­/(tBUËÓl>ÎÛÒ"ƒ>ZW¸3qrÒkIv'J²`rB¹íHéôsô5:ñr‚)ÕjµOå2ZCXáŽóÆNÎ|=îŒyýQ‘ÔL^«ŸéÌÌ̼‚ƒU #î =­/™q0ÉårªT*YŒÌ‹ŸÅÏ/yB3::ª}ûöÍSls«X,*ŸÏkß¾}‹3u‹ŸÅÏbÌè%34?¤¤±}I(ßOóZƒkέXyvƒÕë8¨ŸJ¥T©Tæ™°ÈqÎÀÀÈÔ7u©¦ÄnƒJŸv € Yá&m†Õ~w28 cÙuÿ'!¦W1d IÃÃÃ*‹ªV«=)mwÒŠÅb_âI:+ü¦C±’U»H9£Eß%»5Lðü|œXE³EÎøøgŠÅbß»-•Jì{7N&i?b•C_·“JRõ¼ÞhDn?88ØKêØQsòÀµÌ$—¢ì40™¢r[³ÙTµZíuoØÙd’C[¿WS$Ù©Œ3(œ—!•Œ×Món'*LÚ£w¢Ÿƒ?KÇ‹oxOñ½S#âŽB¡ R©¤B¡ÐWLèõpÕ¹€?‹ŸÅÏ/ßÇR‰¬hÙÄŠ‡ýB²º‹ŸÅÏâç—ëCkÇ *9Áˆ&”ñ5°‰ÞQ4Ä5H3°¢R›“;ˆÓ‘@Û@ÎqW÷é-eïÓÊ’”A™YN×@_:0'B¥= pØÛχ3|¶I~5þNTœH–J¥Þl¨¢ÍýF|Tps’gàÎyËš;¹ñó¤|4gi¢2ÕÌèïõ=r<B<νX­ŽÊYœŸñz¡—™nÿ,guüœœ`Fÿ3J¼“ÊG£qzà¸óâï·,:}”<èoàïÁx›OºëEª †øniÐîÎ’mE¼&}ߤ£¹Kä¿Ëww¸ž¹§™À‘þÆ6&¾¾Vw}/µZmžÙ)×S–•¨Ä°øYü<*}‹ŸùŸÿÈýIÉÞ$óCó[cÆâg1f,Æ ¿"WZ9(LÀN4\ÛC¾Z­ö(j˜6å‰ÃÃL” n ´ ö(kýÑ Æ\±vq—RÖ4ýŽæ²ÑsŽ€/z©ù™0aˆ&œóàü%zý ¨fZÐÌÌL¸’zÇΉãyüß«)zþ˜®äwAŠ“;b6—´¹8tî‘~Lö(çëûa²GaúuymqŠ4©(­;nô Šï×뇆½^G¾'Íf³—(8©bç2ÎÇЗÉ×Âë‹Ï’òîôrŠ&µ|—~¾Qn™êhI–|§¾Øòµø½:¡D8“?&ïîšùÏ+•J/ùéKfüÌý·ÊÇ*˜YFþÏ HßÛáí·ÿˆ}çj—ÿ9ʧ.ä³3?ÿÑIÌ¿e-.ÆŒŸÿÇÁô›±Ú–;7Ž®8ûÏhÒmIZz °Óc‰e;¬ŒºKA*Œ;/†V¤êv»=pd^*•zóf§Ù$«Ø4`tçšþã¼oƒj*|ÑõÜiVë)oLð.©ÏSÇ¿“]w2Ø}ð3às¢©d”üõ<Šg ÐI‹¢'¡;F¤ ²+åêºß™1ÕÁè[B)m¿c‚FéeϹóÁç`ïzݸÛÅ$r``@õz]ÃÃêT*}$ûÑP$€øÅbQ•J¥ÏÉ?;44Ô§žÇÙ$+:aaw‹]¼8ÜÏ⣓~JW;¹¢\· &®|~þ9'ÅN8IOó;7õË×è®ÍÚMu²î5MÉh'ùÄôþŠ w}43_à#9 |ñ*—Ë}ÆA…à](422¢eË–õÉè-~»Ÿ¤¶û"°œJh|õhƒrY#WºX,jzzú}c†ƒècåÙæóù^Ì`ågñ³3cÆáœ”¤qNfhh¨ˆ3¸£`€ME*ÊääÑSÆÀÚg¿Áœ“Ïž:!0ßÀž ç~8¯Àj3;+êwBãu9444oX›f ¦ÿd³Ù>‰eW¹S©”–,Y¢r¹Ü{6=ðèçAçu‹ ØÄàÓÏ×ÏÆIµh¦êë ß‹¥q žlRÌ ­¥ºí{CÚT¹\ÖÐÐм ¾“FS‹œd8™õ=Ð#ÈÉÕ´h@ÌÁwϵP-ÎÆˆŸ©TêÍ­PÍ~*~&¦D&uì|]¤òç»(kÎyw£üŒ½¦™|ùž(láçÍîb”ÊöŸ9yd’jaJš›jç{`gˆwm¦K³Rw©¸_üŒ*•Jo¦‰ê{.ªº{;/™q†KçØÃ9 vìØ¡z½®ÑÑQ­Y³¦O]à±P©k4Ú·oŸ6oÞ¬ÑÑQ-_¾|±r÷¯®rØ.É {˜¤ú( *Ö'Ò \E‰4ˆÃy?»víRµZÕÒ¥KµzõêÇTÌ0Û¿¿¶lÙ¢¥K—öäé?ݘáÔTˆÅ˜ñ‹¦ƒ(sК1… –ÿi+ô)á¹@P¥v ¢Hc£¤/)MT§"˜eRì)RÖ|®úûû|¥R©O1Œ’´ô{q tgÉòÀÑGÄ@3ŸÏ«Z­ö€<ç5¢ßŸ¥ïÁÔ&ÊRsf‚ž;Làœ48Qñü„.*yÙÄÓCÞî¶XÁË€˜Ö\.×çãk2Èïv»ªV«ê%Uîι“äîïÓkÏž:¾Nw£8ßágëÄÖÏk‚bþw]˜@¹ûýeLÍ£|2׿×d\û^/Þ7¾GÓ²è‹ä„&ó9Ãâç _'ý圔{=RíÏ÷D©tï Ž°°‹åõïD•]IÒ1¤GÜ1/™ñ &OðPÁqÇŽj·Û:æ˜cúø£¥O6›Õøø¸–.]ª‡~XétZ£££‡Lh’‚ü¿õPüE¨‘ÓøHÿüJ8À×ívµÿ~mذ¡Oµbñs`m¯X±BÇü£ÞApÅN¿Ü=P”N§µsçNÍÌÌ<æcÆØØX/f¤R©ÿ4E…öõB1(é¿Çw¿ç‘ÄÅG;ÎSn155¥ 6¨Z­.‰ðÉd2× 'œÐÌæïbeÕ€0zV81ˆ±€@‹²¸’úâ èMa!ÕÊf®u{{˜*æÄ†UpΣ˜êB€e°Lá­SÁÌ*¼fvgèÈÎAuŠ öÓr¹Ü×asåÛì¼V÷ï§RTTËb"B¥*Vñ9ÀmJá‚mv œù\÷ßcâåçç^ü.ýn­ºæDƒ’ÚQÚ]zœð÷Ån†éM\{ôþaâÃn»/\ÓÑ·ˆ ¶Ÿ¿mwÖüg1©!5Љ1åŸÝÉòý{¯Ðïˆsc\ËþÝ4·ó>œ¢Ü2ת¯•…w®Hcd¢î=èÎ ;X–-§'•õúŠ übß03ä…¨F£¡½{÷êÔSO}ÌóËýpÖ®]«õë×kxxxÞÀ?0 º~™Š:œ•?þ£æè6ìÀÊû5—Ö‡Ûê¿èÍvîÜ©x@OzÒ“´lÙ²E$@a½^×}÷ݧ[n¹EgŸ}ö£Úá0g˜+w@ކvïÞ­SO=õ1•D/ôŒ3™ŒÖ®]«{î¹GK–,9hÌx,\/¥V}èF*«sæßóç;H001 Ä•hz)ÄïgÕøÑˆ3ìÈìÞ½[ëׯ×9眣±±±Å`ÖH£ÑÐý÷߯›o¾YgŸ}ö£Z!ßÝÀótý&Œò¼>»¼þh!aPn »N¨ªÅ"¯ÏŠ[ô¡\/wäèûÙQx€êJîtSÁ‰ßS,û®Énïív»ç#c<â™Îëø¹YáŠÝ)_»Ÿ|ÿ; hA4Môó0^ð}V«UŒŒÌë\øýš’å?75ОeNF¸N|}²çìŠ×ã½{¬bç÷à™?cߣA½ž“ÆfÊ";¾”wÂê8çwâgǤÌÏÜñ‘ªk¾v'Û."zýùšÇ)´áwäÄëƒRÑ” ´:ú3Q晳<öœ£$7Í\ý^Iit’èNøÝõ}R ÀßÔőDšYTu8TõoçÎZµjÕ¿»ëÐíJ©ÔìÿK]¥”R75—vSêª+)Õû™O>Éd´lÙ2íß¿_Ë–-[°R9Óhh烷êÞ-SJÏýÞl6«%ËÆuÜéghy¾«Ã¹åN§£©éýšxàn5ÆN×é',W·ýèVw;Ž*åýÚ¶y£víÚ£¶r:âøStÜ1«•Õì+WªªNnצ›5YmixÙ*rÚ)+æÕù¶ªÛ´i“.½ôÒE²@+›Íê”SNÑwÞ© 6褓NzÔWø¨¨r¸]™•+WÎåO:ÖØØ˜öîÝ«ñññÇdæŠÚôþ½Úµu£vî­¨“J©4<ª£Öž U£EMìÚ¦Ý[¶kÕiOÐÊá¹§¥};×kÓŽºŽyüÙZ–ijÿô´¦vnÔæí{Tov•- jÕ‘G똣Tg¦¦Ý¢¶×”NÏÆÅt:¥BaHÇö+:bùR!yݳc£¶lÙ®r­©¥£«tÒYghIº£î£3ªÕª6nܨK/½tQYoç”N§uâ‰'jýúõzðÁµnݺGmM;N|'ÉûÌ%¥„t-rìYùe'†T4' 333½"Œz¹\îÉÙrÃÀ,ºžGÉyƒ~WŒY\2ˆª[–kæ½0#=¨Ýnkhh¨gøè!hSž ™$ÐoÆÏÁÏ€‰™ï‹NóFI&ijž{ñp¾;%N"#eŠ”"ƒP߯TZ£"Í% Ö º£åóÉ€Ú2~—Ÿ éc^ë~nœý¦ç ÿŒÊhì0ùµø•¹œ¤z­JèçÇÀ±4—Ë©X,ö’RÒ0FÏl3J$û;£¡'ïÉTP k°ûÆ}J¯!îS*›VßG¥Ré½':~ß^žybQÀ÷’„;XœèS3c&w(êÀôô´V¯^ýo%l—e³³›fbï”vîÙ¯ýSUÍ4[J¥¤BNc£ÃZ9¾TC¥A©ÛU»ÓQ§ÓU*õÈÍau2³`ÐOçµïo×óÞu³NxÒyZ•ë¨Óíª0vœÞõÉÐÅËšj¶HåñÅ1#ïv¥t~F_}Ã…úàÚ«4ýµ¨µ·4>÷•´ºÝ~ã¯(#Ùwý’÷ëcïþmýËí»5¹c‡Žûõé[Ÿ~¯ÆÓ-ÕgªOÞ«/~è=ú‹¯oÕ1kÇ4±a›Ž{Ñûôù¿QcÎ/$¡‰÷½cÇ­[·.ñ@þeþ¸"äáËz½®•+WêŽ;îÐ)§œ2¯•ûóL’]Q£ñ¡>årY+W®üO5³Öív5<<¬]»vi||üë÷pö6A+vÔì¬D`å¿ÏAËV«¥}ûöêö«þTïþëoª»dµ–ZšÞ7©îß©o|â×UÞö3ýþ3^¢g\}§þèY'Ï~g*¯Î½©§\ú9½ó–®Þ¿¶¢ýw}EïyïGôã]Ã:veI3µªfrãú½_¡—=± M—ÿ†ž÷{tú“ÏÕ’L[Ý®Ôl-Ñk?ðçúÍ_=Uén§wÍ©tF›¯û^ùŽo«^ß­‰ÚQº|ï&½|©ôó¨é0f¸+s 'Ì£¶-ÎÌ(H¸Ú»|ùrÝqÇZ·nÝ£JƒvÙ´Wõ pù{ýÏšȦ…ôÐ¥>ªVÔ²ƒÈ?'¨dG†%þ^Î6øïrϺo@5<<ÜK ¾Ì‚ d±«ëö7¸ët:=u,ª@`znÅÿlé*µ& ì¬Pr™^>üoNèïçê$‘¼'¶#øç½pÖ„ կ؉ˆô>âUÒÊìKBïÇHã%Ï\°3â$(*hQÌ J{®ÄßëdÆ]biwB¨hg%8‹9ð>˜L²[åÄŒRÛ>{ rL þnÒ©Šççã$kÐ Ï{ ¶J IDATXpÊ ç\ü>Ý•¢±¦÷¼=sh¦ë=o ZîðšÈFMt pncy<2PÔU:=ûp&÷Më{?¾[×Ýx¯îy`›ÍŽ­¶Ú®Rs@¾Ëª8ÑN;V=už|Ö‰Êçs}ZàäÃöó‚ru•-¥ÁÓôÇ_þ–ž·¤ªV7¥®ÒJeªÚ3YW&›Q>—Q*ÕU>“V»“Vw®åZk´5XÈ+ŸM+Óí*?”ÑH)§®¤J¹¬Z³£|VÙLZ™´”VJ­î¬\]½ÖÒA©:# •í45Uo©Ñê*—I)“N©Ï*“J«ÝO{I§R*Œž¢·ø3zu¥¡ø¹úB&׫˜¶Ú3ºÿª¿Ñz§>|ëôÊc´åÆÿ­g]úûúýóž«/¼l¥º­ö/<:(•J¥ÄDg±ÂÚí“J¥¢V«Õ7ðó|N¤ ˜à}犌ÕCGÇŒÿlï‘ …®½Óé¨R©h¦Õííí,÷v¹¢z7£%]Õ)åriÒ)eRµ:³VµZU£ÕU¡Snîï§”R«=Û©ìf ÌtÔh§”˦5XÈ)“êªÖê¨6y§>ñÁ/éœw\¦¾þi*eÚªNMhW¥¤b&¥ý©ŒŠ#% æ2¡]= B¦¨BF’&ôOxŸ®™~­~üãèq…޵Š&÷îWaù :í¶rÃ*žøD}üÊ+tÆ@}¶Ã’J«00¨t·@iN§?罺üôw©öíß×3ß¿K¹ÔlÅåÑX£¤:.ÆŒùëÓó•J¥çùñH„;éû 1 c0ÍÆŠF®€²*oEÅ.SÃi$HŸq•ÛÖÿ̪5‡ù ö˜T²Ó¤À×èv/˜pùgIW3%Í2ÿ^'/T)3¦Ä-g†,.à¿ëë6•‡ƒîÐoðs!¥ˆƒî~Ž4¤äý‘¦ì÷ç.•UÂÜõ2(öºˆEcÎÅp3,ŽÝVÁó ».NPØyþ]þË„û¿ûyðwsÖ¦Õjõ’¿L&ÓSâ㻌ô.lQZÛÉ `Þ[þgRɬRgª£irTý“Ð3½?-ƒî‹ï‰tGRòø|ŸÞLd}?øç^v§.&”þØQ£GRš­4sá8Tóób™LZSåšþø¯þQç¿üCúq¥¾}ý]ÚºcB““šžžVµRV¥RÖÔÔ”ví™Ð†Í»ô×Þ¬7¿÷3:ÿeÔß}á;j¶Úÿf‹ÃMºf¡DWêε³iUÊÓšZµþûóÏÔ²áaÇNÑÿöGjÌm˜rµ¬¯úC=娇Wëïû’&›]©ÛU½ÛÐT¥¬û¯úCÒJ kÅé/Ð'oÚ­lZêd3úé{¯áãÞ O~äuZËièUßQ!WÑ·ÿ¿ßÕSN^­ááa q¶ÞuÙõª¶H6³#Z{Ò:°öhÓ}”¸T§¬ŸÞ|¯Êg¼Io8c•JÅ!­<ëùzéÚ–¾ñ‰¯¨¬” F8`G#´_Öÿ˜XÚòÑîvДÎÁ#ŸÏ÷¹Naá¿*ýgf¦¡éÊ´îùÊ{ô´VhxxX«Îx©þþֽʦ¥v6¥ÿŸµü”7ê£ï±Ö,R~ü4½íS?QsŽº1¹w§~ò¹wêÉ×ÐÐŽyêëtÕÝSJ§Sª7Ëú»®Ö%¯{¯Þýª'kÉÐFÖ^¤O}ÿa¥²Ye:{ôàäˆÖsŒJù´rù­>V§Ÿ´J¹”IëJ§¤lYw?TQñØ'êqK³Êdr^:¦µ'ž¤#–ç{q15GûíÙ¬² ãD)I¥ñ“tÚ©'jõèàxìXŒócF£ÑP­VS¹\ž7ûôóþ81 ±!é/w‡_¯×{ ã‹Å¾yv¢ü´•=dn¿W«ÕÀgEIZ«œù¿»p㊶A «ûœ s’f€ç¿o@hÏ'Vö"=(—Ë©T*õ”³kÂŽ‡üùLÐM ³²“¿#_}H8_â{ç\»AÞ‹V^3 uáËn«žD3™.œ âšõ{ãü¯9“ ?C΃pýx­ðL¥;ž)1 ö{›©Zžñs'§ @©TêÑÃø¾hêÊ}c‰s¿ÏY5É*Íi)yÌDÊɎ׻çŒü½žüɯ땿÷ }çú»ÔjwæŽÍŸ#•Gs4ˆæ¤®ûÊeúü¿¨/é ]}Ý*o¸F¯yÁ[õÓcÞ¢oÞ|‡¾ö×/×÷ßöl½æË[”Nw4ùƒ¿Ð%oþœN|ç?ëöÛ¿¡gíÿªþúöŽ i¦ÕÔîkÞ¥ ÞüúŽ/ë–Û~¤?8s³~ë)êS÷¶•Kw•ÍÔÚñ5ý¨órýlÿ”6|üjÕZÊ­:Cïù?ÿ¢›nù©¾ð‡éŠw¾MWܱK™GxëÙ\N™LZjUT×l°o6êj(­Ö†ëµmØ<ÖºF×á?{wÆû5Ò¼-€B)SW Yñüe}7©TJ-uµãŸß® çJýþ«tË­×é÷N^¯ß|Ò3õ¹:ʦ¥L6¯Ú¦kußïÒŽfW·}ú¥úÚ;^¨?»zƒªÍ†üò[õŠ÷Ü ôÝüÓëô['Ü­ß~å[ôãí-©ÛU.]Ó¾s£Nzë•Ú;µSýâŽÞùžhSYZ¾æ\½ð {õÑ÷ý®>ô·Ÿ×Õßø®n¹{ƒjÖa½—TZÊ–NÒË^z¦f¾þ½ü¿}T_¼êýð_oÓ¶ÉêlQg..Ö&7êÚ+.Ó¾ð]~ùåºâŸ¾©‡w×Óûe1fôw6H z´b;”°´7ª€Ù·Ê±† Î`Õ`U¡ Pù?wL±ì¯A˜«úþyq›Dj‘A¾“*ƒEVÔ©0EIZW—£w—“.Õkdîyú•T‹²€gRüßÙy1 t¢GPïßC€í÷Hë't”F÷yäk°a¥»r”ߥ*™¹ÿ{|ŽQ¨ˆI×°=_K½^ï»'Š qþƒ‰°×ãÀÀ€*•JïúYû{¨¶çó°^¯÷©~v»Ý­Œ>4N´-à.—×¹ßc4õšdB턈 '!QX€ËkÛ«É{ÍI‹ ìtùÿ}=NìèÙÄýOgÎÑÅßáØäçÀ÷LaŠÊôðIR;šC5ÿÞ*«7ð}mÓŸ|ì*ýëm*ꪛã‚wçÿü좒ªµÍ4ZZ:2¤Rq¶UU©5T-Wt×úzûŸ|^Ï¿øL½ó-—jÙÒ¡¹Äæçø%eÒ)©5¥;¯ÿ¾öç[êtÚ9eLõÖÕúÙª×ëÞx—Žè¶Ô8óOôÙ»¿¦§ÿ¿ŸÒG^úßtíåßRë¢ë+ï~ž2]ií_ü±n¼ö"ÝÞ‘2íúÂß^«¡çÿ¾ðߟ«nWZûñOëÞïž«ÏüŸïë%=_™T[¹±óõ?{¹Ö¤¤faFû¦tæYgé_¾|¥þê²jvj*¶Öë³7ïЛÎZýˆèùezÆyg(wÙ'ôGW«+ª+³ªª™Ç0x_ôê&ÑÄíÑìþ} æòFNñµdåPå¼¶ésÿ†Æ^úYýý[Ÿ­nG:öo>­»¯{º.ûÌõºäÎU&ÕÕÀ‘èÝïºXÅv[G^ô½ëE_Ч®þº^yÆéúÄŸ~[O{ßOô¡×ž£™™¦ŽùóOkýs^¢ë~úŽ{êˆR*èÉ/³Þü앪Tuב_úmÝ_Ӊǯw|þë:òï?§kþéÿÿì½yœe™=~Þª»ßÛ[:Ig#ûJBAAdS@Q@ÔŸã0ÎÈ|utFEÐqÄP‘(3ŠÀ¨ Ê’„- Y;!éôz÷¥–ß·OåÜêNÒ $pËO>†tß[UïûÖ[ç<Ïy΃>»•Øœõ‰«ñíŸRϤøL=óê _ï-Ž7évüxÁMøïÿù-®úä7±¹Çà¨s.Ä•W~¯ž\—Åz¹<öàï±!âÔkf31ýÈ×cVWcªì7Í=ã¥ÜCÌÈç…ç`4[-W¹_„kÍä33@àÃÏkmÚ‡{©è÷¤²ðšÄYñÕZu”ÒŽìá"wµÄeÝvª×,çS%VšP’¡7l¬]íUj§QeJ$:ZO¤õ%Z¯µ7¬!@&fÔÚ µ»&±Õš Ž9çU­¬yÚh’[ë4­çµR§ä“D‹$B­‰™ dCgI†´0^%ŽZb¡dA%v:$̪©Ý¸®g5á ÷Ùãù8F¼GÊ3)ÇÓ"?þ\‰¡špI´-ÇJkˆt s^µÁj¸OS¸ß“f»t’ rNwh]Ï2ÖîNG.¼ÜÝFñû??…O}ùv fóˆD |»q3°,ƒþÁ<^}Ä\\øö×ãØ#g£=“€1À`¾Š?üu ¾uÓ½¨åz±ìžG±fÝv\}Å{0mòØ›Ûíéþ,ËR3ñÑënÁYm%T]¹¡í¸åóßBõéÿÁÒ ·×ëúêDl¯TÑÝ7ˆi§@¥ZE1:'L³ð¨˜J?žë/cÆEG©¹¼? ÇÏà±M«‘÷N…ï{ˆ´ÎÅdø®ƒb©‚þ àÊ÷_Œg\ˆžý´ Κ‡ðÌ@0ØeŸˆàŸM?ø¾ ,¹ðßpëªgqÁ»Ç÷[ãp;¹Çfp×ö‰h Ææ¥ 632»§]ìý©×ÂtF±8¸Á¦ÓézMÇ~Ú3ÖñÞíµ—z°z Šoà³]FÓqü\·u?‡¢÷ZÀ÷o‹I¨¹jåÚgMEïÊ~Tú×`eØxÕèü–ï¾ç`p¨Œ õÃó[à›(Ú3í0<ÏAe”‡_ ãf½ùܱøÿ>Q@oï6ÜwãeøŸ¼ǾyÎŽF`Ìpñ/v¾è<Ç«ž¢÷øÑ©xë‡.Ç›.ú(³l|r>~Î?àËS–↻–ežyþí†[pd¼4Ì] ìH¾çu@Öðîúáì©8½¹gì¿lÕþÞ3”dh ŒöÆÐÎëAZ»Ë(.å+ŒÜja;q ÉR¸G ï ‚µ×L@ç‡A,Á˜â£B¡,‚F݇yŸJŽ´ˆf3´‰¡ZØò{ ª$J#ÕJÜ42NÂC°§µdèÕ*sSiöAá< …€Ô(‰S×9­!Ò쿟÷Npª×¯Y¼jv&1j±»YA6DI‹fJøÂ®[aƒ%­‹a³Æ°e·š(0Ë>ʰ•`h+lf uéšéQbà N±Xlø~%¼+$—žçÍRGÍÌì­†v,›ßÿò >þÅÛQ.aYf/7=n´´Kfæå9>ìD+:1¬^» >C©<ül÷»H´M@>¨ nĶÐR+£\.¡ÐÛ‹d¦-ã&c¼1XòïËð­sºP©wÄÐÑ5 µR_@FdÓ]Åbž_w‡´ãI´Ž›ŒSÏ<óoü%è®á½óZÑÚéáéM;P­Î„ãx(•+ÈnÜ„š=ÓÚj©ŒBÕA,…±bHe,t-|+þö‚‰øÔÆuÈV‡íñÁ¢Ð†.£ƒcÇqจ ÝPÿºÞÚq]Ä´ãÔkp$*væÙÛ½¤¹g4JS$‘-¢Y md©Ù "‚a©ŽZ;«³#ÊjA«@‰ÿÆú’mžN§¹LjEÝÚ½ÖÂÚD™ÙZkFŒæ|‡p Ùt”¤ƒ œVI%sj¦@ÂÇw¡fM|uÍóÚµ¡¨fX‹ÂŽõ܃*•JPc¤ ’>^' ûÕÊY•J´”Dq}ó;Õé‹s¥vË̪±·6j-‹ –åtNã:Ò^@¬]aæPׯ5Ü)"—ËšÕ½Z£JNÃÖßJ\HœøÝü^>ç¥R©A•biŒƒµ?jf|ßG÷óýøÒµ¿D±P®Ùý†é8."‘(¾ÿõãÞR·bvë¶È;¶&·E꜊¶yÇ#’Hâ‘ÇWá«×ß-ò‰–&¯/4MqDm8éôÓÐòø]¸ã±-¨™zákm¨{|¤2“pæ›^m?½w>µ®[Æö?ý ?]ë!fÄ"ópþYK°åûÿ†ïÝ÷¶lÝ„µ¿þ¾óì8¼á¼7¢,!“ÑXét ¢åmXÛ݃r%‡uÿ<ÒwÔnÜ@¹\ÄÖͱyóf –”³½Ø´þ9lï/ÂC]óþûûÿ}öy¸Õ>u7nýY7N~݉˜xØI¸ä¼ixä–[±rGvĆqËèÝÞ‹J¹îRh…ˆŒeXßç#Ûû4þë»7ជÇ3«×býÚ•xðÞûñÜÐ,œ6·-“æà„ÓæãÎïÜ€_þq9Ö>·›Ÿ¾ß¾æ>tóA¼e*P­öà®ë¿Û~ý–?½ëž[çžø5~y_ÌZˆö„Ï÷á”sذæY¬Zµ kÖ¬Á† ›0X(õZ­†¾íØ´~¶ Tðüúuè~¾U×E©˜Çê¿ü?¿ÿIT½z6kÊñß?ÿ†Üº ¨Ã¸ëgw♬;æúÀp&­ùç¥Ù7@ktž™–––¬2#uÐ""¹U© ›4‚®Ù‚EJÌÒ[ZZ)œfƒx^­Q ¨R œ„°£íi ú˜Ibµf4‚ yÝZhv Û‰›œ€ $“É’JxÆy}´ÀV‚£…üázŽ;‰²ºÍ±˜Ÿs©ÄœãÎçM³šÌêPzÆ9WyŸ.µ¿’Ö¥Óé`\X§D"¥nq Xh"L¤ø$c*S Ä™í>õ‰±på5¿Àš ÛQw5»õÓÕ©}õ3â”ãÂs]ÀXA–e0WB­æ ™Ja[?ýÝ:¸µ ¢±Zf¼ Xÿ(–Ýû8Ú[“øìGÏmp9ØÛk'âh±‹@1‹šCm+‚ygü~ø!\ö¥Ä‹UX‘ÒmãpÔ×ãÔã¦àØþ;®}î|âœ7aâä èÓ Ø’‡ˆoÜþ3|`†Ç9¸»²ïÏ—p¸Å¡*y1®]µëš…áÆ··‘ó}§/õ¨¾ ÆØuÊ?b}ø¾><߃`ŒìA¾Ï—™µß® ~o¼âû¸ºp)>û®3‘HÚ(×ZðîïüŸxc;j¹!Dl±öWÁ}äkxÏuëпcóßý |âÂ× ç~ãlùÌeøÄùoƒ±aEÓ˜¸ø-¸êˇcéÔ "•Ad‹5øÃ/¦–T Å¡<ËF&ņßߌoýçÕ¨x,·ŒZr.üÆâ¢Ù)q\ô/×¢÷ÓÇÇ.~`GZãû(nûöÇ1 œL ¬-ÀÕ7ÿ ã¡æø˜~òøÖÇÎÅä–¶›Ê~‹¼ý ¤L}ÏöjI¼ã‹ßÃU¿Q¨DÌÂŽgîÀû.ø:z+=€\qÎI¸ròÛñÛ»¿Œ9IƒÇîø4.¹çmØòÄRtÄ,lûÃÍxïeðÐßœŠc’1XkïÂï¿{â<|cœëø/éóq¨îáf/ÖžAË,D<¤¾ƒ‘p}g‡I‹õ<8)S9‘ÛÌi±4ɆÖ"0¡5Z<],2¦ÍU²ÅÂvmh  ÁáL¥RŒôóšøÍN0ËÅ"o%ÚOÇI9™åák§xˆa‡8"f´4«¡Ap%ÚKGkEøÞ ý.í¬µÑh©TB*• î×¢5*J|TnȵÂì1ç™dJëSø½œ+’¹Ñ²zÌÌðœÚHÉ5±4ÝË´çŒf°8ß|ª J𔼩ۗÖîp=kýŽÖYÑõM\CºîR©Ô9žöã!9æüqιöõ1* 7Éeæ?g p†GëÈxýj¦41½õÖ[ý³Ï>;ð&7ÆàùçŸG[[[Ðç#|ضåË—céÒ¥# ,ëqwÜý>uÕˆGDzéû¨9ÞtòQ¸ú3"©šca{_—]u]±Žã"ÓÚ ¿}&ì–ñ°|w¸ µâöu¨ö®ƒMá?¿|1Ž^:î(…ñ•J===˜>}ún®ËÀ«d‘-™övD}ÍV8(Š(WÀX°"Q$’)Ä#ÛˆSF>_‚ ÑD 1§€ŠÝжL¤nù\+!_(Ãñ+Gº%ƒ¨.Î, ![‹£½= xn0>Nµ„B¡ÏÄâIX^n4ƒÖ„=J‘«‡b6‡ŠëÁ †ëH ƵÅà;5 Tj.`YˆÆÓȤâ«ÜKùÂ¥ÍâÊ•+±dÉ’ •ÖF%Ú—È¡6a:TFÂr¹P,±eËœþù»§}9lÛÆã?Ž#Ž8"ؘ5ÂH°ÐÛÛ‹d2‰¶¶¶]~çto‹²ýab™,cÁ6rµ~ ·"WÛ|µ¾Ø&‚t¬™Øt$'¡%6žxpáû\ßAÌJ¤È÷=x¾»Gbãº.6mÚ„9sæìáÚ |§þl»`EÈ´f`{KE<üÏ‹qÑÃ`åò/#Ù×ÏD‘Ê´ Ý™®÷rýó>c!O"™ˆÁÀC5?„Z$ƒL*ßóà»5òe$ÛZZ¥„rµ §þaØÑ8Òél³ظÕŠ¥Jýû-‰T Rq ¾7œöw*¨”«¨:õ=ÏX$Ri$c6<߇[D¶ä7X3û>O· éhçÖJÈeK€Í¨¢ß$ÐÖ–† •R%7ŽöÖ$à{¨•‹È—|´u´À‚¯ZD¶PA²½qãZ#Ã=cõêÕ˜>}:&L˜pÀö /j{]6›Åàà …ÂÝ3žxâ ,^¼x„ÊC÷ Ž¥@QÒª€M¨özQ‰ŠJy´‹¸‚^m¾§`[û›háu¸o{ ©Dùýt‡¢D— ‘$…à™’µ&Ø$É ¡`T^#ò Uª£„H»Á“¨iSF0u+cgw‚q‚UZÍd)èÔg,Ò5•w)ÁÔÆ‹ºfä…$Š5 𙡠Ö«Mµ’9m ª$–sOi3JL”Äp.µ'k¼´~E ¨ö.Ó¬¥UÚXT××¼:Á)y#YR"¢F$j áû~@ÎI„ªÕ*R©TCÓR&´p_Çžs¤Ù/m|ÊñÒZ9í9£}‰8oü3]Jº¹Œ1X¶lY=3ÃÅ͇Nµ§cIã‡3¹| _ÿÞ¯øc.–©ýŸuú«‘~!c°bU7.¸ô;Ì¢µ%ƒÁ¾>Xý½HO_‚xÇT˜aPrï&øNßûÑý¸vÑô‘´±h‡ ŸL,ƒö¸ï9ðF@+ ñT‰´ñ¨Ïh-í ùI;b\6£´ãÈ´ÉÏýz£P0‰V´' |·ÑQÎŽ&ÑÖ‘’‰7èŠÃ *ÙÒŠ”]_ïÃB"Ý‚¤F=÷%4†Ý;Æ2gµZ …bÑH©dÆÚ5À¨G‚jH&ã°íú 'Ûß+3“;[¹¬Ìh53û[F¢› ZBªìLgö´gì-hò‡û<Õ¼2†*=X=ð<Õ{/6çV TË"–ŒÀ&`2><×Gµä!É`\rf´…¹m¯ÅÌöcñض;ñç­·aî¸ã05}fµ‹ÖøÄì¢Vž?zÍàØå9~ýÙ×gÛsàG‰¶×"–ööŽ ûÚt±ãÈ´ÆC€z$šnC̘zÖ¬Ò­øð|v,L<9"°áImM %–¹'pží’™8’£:°â­èH˜]>¿#ööHmãû¦š+ IDAT£Œk]>M´ ÔÉ™ïÃŽ%Ñ7€_ÿ9" ´µ'¸ ÷±§lížö öÖH¥’°ö¸gÔ Ò R³ý=0ÉLšÐC¥k’î/ÖžÁ¨,I£ßŒCáæ‰)™L¦¡Ç ¥/jãªý>P3; ÑfWZĪÌEk4ÂN©ÆHétz„+ï×¥}XH|H@XßÀÿÏ3(a;˜‘Xèwh–G¥EJúÂõHJN´×‰˜«³™º¤i- ‰ˆf…ˆ)imÌ9ázà¸jŸ-–×±á9T.¥¤Ik¤øGÉ€!Þ?ekꮦ ^9>j† ë†ãFƒÚ#µ£›V¨¿‡µ8 Pªc×.熒<Þ/%‰\'$sá6 '%j§L¹¥ø¬jÖ‹²?ò„r¹45ÕºmÜ©™,%–Ú7IƒRê$¨²Cígħèzê“Ü×#‰à›7þ/²… ¼1 £-ƒÅó§ÕÏïû(•j¸êºe(—ÊhkÍÔ|X¶ ø> [× šî€‰Ô]ÎìXV"¿”ÅŠU[ð§G×àuÇÌß­L`o¤ {ûóñÙ½}Ù¼k8XeákÎåóè^õV<µÓN~NŸ×†šÛX$É.›–gŸÀöèTœtÔ_¼àxxÃQ¾ˆù†I7µÔhÐÞZü¹«û€ðX¼ó¨vêxÕZ”‘Àý8á°¬( µ~<Ó{VôÿV÷>„JˆGð}ƒ˜•‚©X#‚ Qˇ‹ú*ëÑÛ»uߊÖÄDÄì$rÎv<Þw'þÚó3x.0=ój,žp¦·¾ 3ÛŽ]‡ÖûMȱKÆã˜yò{ñ)¯AÃæûðlî©x{˜hˆ}co¾sweûcÏ( ؼfž\ù&žø.¼iA'oäžaÛ6r¹¶¬YmnN8f1" ¹gĶLÅï?¶ï6€p}HxÏо Œž¾{ÆhÈcÏVÛYî­¬M ®^Ý“if‘¿fsÔ-K‹†9~¬Ë ab/îU<7‰³*ᨵîÿ ì´™§:¦1SCÐ¥¿£‘tFÖÝh¤|´ꔥ6ÍzÍ™ü¥fÐS©Ô¨R,ÊàÇ ¬«YïBÎï6à ~IÖôýªvÄš±Ð¨<3OÌ.±C#ùj{­kõ+”Ž1³Br˱åý1¡–ØÝ' æ|¨Ãšf¸4 ¦VØ:ß v¨‘Ú+ÁT¹ƒ*$ÄšbCSJ,u-„ç_÷­!Ó½…÷¯Ÿáøéxë9ø¼v­Yã=¦Óéà#PS%"*­d¦Šó Ù"fx(«äßuüÕ¯Ì0Òªþ>à ðà#k`cýÇq1q|;ÆkŒ`ÓóýXñÌÄ¢#eT>¿VA-ׇDçau ¼eÃŽ¥PË`([ÀÃO<‡ãŽš[wÚy™v%£ójê?ŸÂæåඟމʓ“ñ†ÿ8(VP,10˜ŒA*C:•D¹C÷Sáö¾ù8îˆÙˆù:_s6>3®žëb``…RшD<ŠÖL®çcGï¬XQ߃ ƒÖL ‰XÙ\¹B±hñXí­iŒÕ¡Ö²,lÞ¼ù|>xY„ï=“É ««kD·ç]Ë:Ô‘H_ö žö—ìÆÀ bÇðèö»ðж`kþ8Ž[7ÄðSðj;ëïü]L<Ï3,Ĭ*N§ß³a\ƒx,EãOäô«ƒX¹ã7x>¿ 'N{|øc×~;3Þý|ÛN­†f÷“—nÏÈå²xþÙ‡ñ³[oAߣãð†ï_»TE±TÂÀ`0ÉD ™T•BÛÖ>†ÛV¥ñª# -â uñiøä‰ã`û.‡†Ï—ZHÄchI§àû;úúa¢QD}.,´¤“HÆcÈæKÈæ Ã{Fm­™½Þ3º»»‘ÏçyQøÞÓé4&MšÔ°g¼ØÁ•,©-­-m†¨.Sᨮêô)[Ñ¢z~/]±®ItiÅb1hÊ©û”|ª5³F‰ÕZ™?cá7¯Sïƒß§M=µ~€ÅæZçÂs©å±I“„‹Åp¨™ mî¨D9ülxδRï÷J+f­ëÑu©ýsÚ™MЬkfHÚÔì@åFãÚ«DÍìy?áæÎ¼'ÊÌÕøA Ó9'¼6•ÿñœ*­Sé)kJH4Õ~šãn©sßÇãñ€`ª4ãN"Â,“PhïS%bÚwŠÏ?¯ÜÚ£ˆÏ¤:ñ1Ó©tÝg®wš© [qSÚGS ÎUwh$ küK,kXHû½žY»}C¥áE5¶MÓó|¤“1$b6\σmYÈå˨Vºc%ö}Àsª0–ßu눚Øh ®Üˆb¹Št2Ö$3‡È±»HãhÿV*•PxϮ݊S/zþá-øU÷;ñ¶6==}(õ­ÄÏo¸÷=Ý«c!Îû×KÑû»ÿÚçÿˆ‹þô#L9þ¼sòcøïÚpÕ{ŽBߎÍXýÀ¸éöÐçµàÄóþÿxÁéÈ ­ÅÏ>ÿ%ì8ò (/ÿ#6—ºpÑg¿„S'—°áÿ~„ÿøñ=è.øÈÌ? ßýú¥˜Ýsl¿V«áì³ÏÞe­‰çy8ï¼óð™Ï|¦!EûbŒÞé‹^#‰Úƒæ…fdŠNw®ýž+ÝRnø¥êq%ëýK´ß«ï#ÆXH'Ú0#s4þºý,ê<©hVõ>ˆ%ãß„Öx×Ù3¼ZÕæcþ’’œr¹ŒüP/Ö¯]‹£ßq>VÞñSܹñÝx×;zûQx ËþóFüzùø­óðÎËþ•{~…g6DðÁÇ—¡ó¨áýG¬ÇÏžŸ‹Ï¿ïd lß‚ üßÿÑ}Ø^M☳>€}ðoPÊoÄŸù,6¿æ à±ßc]®ïºü+8s¦ƒÍ¼×ßr76d=¤gޝ]õq,žß«}ò¬³ÎB{{û.÷ÆÓN; ßüæ7ƒÆˆ»Ë̈µNª+ÍÂP.CsÕåS¶É%ySPªÄB35š5)—ËA&€uÀ•Ä<Z*7 Û k×z~#ÊŒžó{µ€Ÿ S´Ö¥hѽ6m$1 ØS ýYh" e½f9ét:ùQ¤µ?ÜÃ9&ᦅü‚tÞ7ç€Y3%U…B™L&È‚±G-2A67“ÉsÏ‚úð<©s*• äLùê§çìÚRͨB  ¬IÉ®‚zöSa¶Œc§ÖÒül.— æŠ ½xô:H¬T2È9K$Áúà|qU-¢f\{¼g5.ЬT¥R ÞíÚ7H¥_\3šÕÀ§òH$È阙Òf¦\ëü^]ÃZ£ÅskýLD79ZÐ…Sä{Š|)™Yùì& fa™±ŽºÓÐ΂Қ˺¬l´Â\¿ÞìV49\“3õqj0–ÀÇÊU›°mÇ æÍìUÂp(6ï{¹ÊèwW»À¿g³9d·?‡u}mxçñç£ãÏ÷à®=„Sþ~)j•MøÅW®FöÜëðà­GÛWá‘þJo=[sGãÿô÷nŃ7ý ®í£T,áù•÷á¶?ùøÂbRßCøêåWáöɇá- #ðJ%$'¿ _ºì³ØtçÇpÙ×n‘_ynºm9NÿâOñ¡£;1´}‘LdÌöà®ëbúôé¸ë®»pñÅ7DÃHtN;í4|þóŸG.—1»ë3s jfm ÜCÄEç…ÔÙ)ê)®Çm«?Žmŧajñ†¦°/ô–<H$b(UŠ€AÕ-¡ìåÐffií&Q1CØ^Z¶ø¤`ÑÜ3=cOëÍ÷}dsyú×cÕ 'Ÿs!f<ó;ü÷ÍàÌy œJ7~ù¥¯`Ó›¿‰ßß|"½kðçž$œw¼ Ÿ›€ï^q1ÊýÛð§Û¾ ×óQ*•Ñ÷Üñ“ßöâ?úæ×žÀ·/û,n^6ç¿6 8e ñZ|õöËñü/?~ùzóÝ¿Áoÿ ^÷™âÖ×NA¡¯~&6ægÖu]tuuá¾ûîùçžYÍ üñ¸æškö -òšý±á÷(ð¤Îž *•J„&‘H P(4€ãT*Èи7(@W©%F$B*=QbÀšµÆÕèx¥RA&“ ö^­Qç*~¦P(Y ’’+-œæ50+nZ³Ã=6´Ÿ‚“¦~ñ uz°d›`ûqLHÏÂï)¬êÿ ,øhî/·=£Z­"›ËcÛŠ{°cÜ"̘؎#Þv2jºo¬ÞGð= ð‘KN€].¡œ> 3Z\”+U8µ ²ù r…JÐ(0è^ñG‚WMŠ¢d&á¸SĶõÏ¢ì[ˆFXòÆ×#Q„uØRLv¶ Ÿž‹ÓOšg?ýÂÕ¸ûñ¨›4ìÝž1}útüà?"à044„óÏ??úÑFì£Ë>ÂM ÚHÕ½‹²0‚/Íp(€Qý=ÿÓP ÜAž‘}þŽkæA›F2â¯nWZ¯RµÇåþ­ŽYÌ~€–Ëå âÍÏ3ëD©U©T 2ñZ“HùÞ'#ëaûa­?b¶…ã•ÏçÆ’`”@9Nr<5:`”œ`R]äØóE(ɦš)ð¿™9PéÿŸàY×*Ie8¨žFì)ãÓ9&Àç\„›Ÿª¬ŒŸSIŸÖ2ñ~Ôd‚@„Wkq´ýIMw0­•áup5ÄC³—üŽ+¯›JÎxï*…Tó%¸gµ—VÃŽK¹\n'rˆ(ƒÔF©ôP'>>Ï$~Š;”ˆk†¶!3êvúÞÛY¥â §7Ë®·wÓÈÂÎÅRoöæÃC­Z×ÁWk5Ôj;µ€õËE¹\Ed¸ÏŒmD, ®ëÀŠÄ™ºV$¸¹•Üra˜ÑúˆE#X»~;Œeà;~Sjö2'ù|N¹Ý¿Ï”·àsÏþ~-‹-½q¬XÞ3:R0^Û· b¢)ÀÄõƒ0p«Eòy8N Ãþ³H$°#6ŠÙ!ôôô ;4㹈›²áô¬ãÁ‡‡*:qæûÿKºŸÇúµOào¼Þ„+ñŽpÆX0FÉÅ1ǃeË–á„N@"‘À§>õ)|ä# ^:û«(z_ºÏ„-YlKg“}“¤ØªlÇW_ŠÁÒVDüä0½¬7®5Ãcÿ‚×g°~èaœ1ó_ðêÌYX¾ãnl+¬F_±+{ÿ :Þˆ£'žW7Ùo=hšÇÁ°w@¾P„SÝŠ¿Þ³k‡6à û#àdñ|Ÿ¿þù9̆嗰mÛ‹áGâ0<n­ŒB>ø²g”óõ=£08Ës`Ûƒúú5×­7†ªßŠÓÞó!ÌÛò<6<÷$îýÉõ¨¶]w¿zÚ˜kUIÌ-Z„»îº ¯{ÝëH$pÉ%—à²Ë.uÏx)úÌ|ˆœ‹Å( ( ¡;’F³ ù§f_õút{Êd2 ’’ Í@(8e›@N{hiaºF– ð) ×”QBÃÆáºÊH†H…B¡AnCâÇ=™ò0-TW[`u³Ò G¹\€¢Öð÷”U«Ud2™€HqL™YS¹žº’© Œ7NóÆñ×÷ ‰ ë1Â5¼ÞjµßU*vbãg¸Þ8·*ÙSÂÎ&q|µù&Éï/ŸÏ7˜F赓 pNÙgH³¥JV´ÙªZ:³Dë•x?*=T£Ív©Q ׆ÖMiö‡Vâ$Fšõa…„\ë‡Húù\œª’„σb^3íŸ53Åg"Œ;¸/Œ™yž‡|>T*ÕÐé{ì€ÄBÍq1”/Á2V=c"2ž;ñ,Ø‘¦LIö,Ôj&NWøá‹8¾ çÏ@©\…e€|±Š¡B©ö.¤&χOÂ&Ô Ü·¾ï°ê½U,ƒžþì°Œ­Id^NdÆó‚ ì½îaÁ £«« +V¬Àå—_Ž~ô£Èår£âîÏþ»;Â:vº«¨ûË ™Ûek¯ÄPe;|׆óa[\LJ±êý«E¾yø>²¥~,ëþ4’µI8u懱tü™õMÓ­`Sþ1lέÀÔÌáp}¯Ihñ#,­ò`!¶å·øsy)¾vÇwpd¼ŒlOýæ«øÉ_ÿïçà¬y·áúoÞö‹C{i ¶¶,Å„Îq¨lÝ€m½}èJÛHÄ¢0R©$fy ¿¹÷?¶ÇuöâO¿[…¹ï|?&´:ˆ ?–e#•оAu`#îê)t͘ù à™þ„²g`™º÷çXŸeîãÆÃªU«ðþ÷¿ŸûÜçv¹g„e©/Æž¡‘t-­Å Ìçó†ÖÌ$ù|¾Á@{ª„ò<ÿdŒPóü*WágK¥R: ¬Âö¶Z¤‹Å‚ƈ$jíjº@ù³ŒV“¤±f€ÝÛ™ÁàÏé,F9m"‘+‰e^”`1K¡²3%bZŒM¢¡N{š­P)£fÂÔn™ä‘€ç ¨–6°äõò3Z£©ý€øâÜj¤>—Ëh¶¨Y%VšES"Ë1"ˆg†Ndžkß©€žÙ½d2Í qM“ f³Ù`žÃÍ'5`ÈR’f퇉‰k¸ôYÐëæÚåï÷ó>µÇ]¿Såfüþ\.×P[ÆkÔ^R$Šc’)%‚$A”’qÎÕ Œ;"œD6~ÒæU»Ó¿‡7ENbµZ ‡ï×c«¾ç!’lAºs ÜxŽZ0_üб˜Ô±kIÛü™]øõÿegªÒñqËo×âÆ_¯CÄòê½üºUs-×rÿ–a"S—™ÅR¥Þ<ägýbG§šÇÞ–±çŽqq<·¶Šã.ü^X+*Å8R™ 2o}?ÖÞþ$j˜‚}û:´^{®¹ònXsqÞ'OÂkNy ÎÙx®úìe˜|Üßãâ×`áP¢Ñ(æw>U­â‡?þ.~íµà„÷^ N›S܈Y‹Gk¢ê'v†‹çcÚøVôtÿ7ÿêT­Ÿq Þ¹h\¯¶ÏÑãt:o¼ÙlvŸ\TÏÕù†_ìúòßëšßÇú¡Ç°¹òWøŽA,âöÓqL×¹˜š…ŠSÀsƒ£;þÏŸ†çÃÉXR”zª—~#>Fí}åÃ…ç7Ì+Yô»qǺøI¤­ñ0¶‹ éYxûì+áù^=4JMAsÏ84÷ À £=ŽkKxõ…ŸÀé3ÚP.Ƒʴ õ̿Ū›‡b¹øö h½îz\ûÅ{à·ÎÄ;þõwÜ)xÇÚðÝ/|­K?„<ép,Œw"`Æ’7âSÿTÄÍ?¾¨&qÌ;¯ÀÎY‚h¹3_“ªGž'Lœ†…K`Úø¬Ýþþë—w¢‚8æŸò^œÌLx~mŸ-¯1øùÏŽl6»O5tbÏP·&uU"⾡@Gkñ½Öâbu†bFC¥_Zः×ÃúIžCA+—ð°Û”ö€ÑÈ7³jP¶æ&Xf”\{èÈkãDm¤Èȵ¾:I4ª­îbJþHny?¶m74ÈTËfµDæ8“`‘pPBîï‰DP(‚u@â¦óÅkR9"â”0„×Ç\kšÒétC­ ¯/Œk5[ >ž‹$“óKSfw´f†5+jÈ@bÀ9 )PrË9çwzž‡b±Ø`C­u7a·3m§Â5̵­Ù­¯S &ïQû¶pl˜¥ã¸hÖ„ÿ¯Hu ã¸jVŠÿÏ`Œö·Ô}‚k2œ]Óµ®DÌ­·ÞêŸuÖY ¬¯§§---/yø­›·ëzèÌão?yº·õ 7Aóc#=eS`"Qä Üúé“°dV<¯y…a)‰¿ Ôïüì}èÍ–aÛÀ²QËö ·a%<·4L4ÆÀñ N{íB|ç £Ru`Éâß±c¦M›Ö&a$•ã“O>‰Ã?<èJË?:gÑd ËA±\oLX'·Q¤’1T+¸žA<™@<|•b%§þ²HÄ£ðœ J5 n¹(V†›ÆâH%°,·VA±\ëúˆ§R0µ2Ê5>l¤Óq8•L4Šx, ˸µ*J• çÀ6 e¤&—ËݼwìØw¿ûÝ ÖŸûã°m+V¬Àá‡ÞžÖÂÁR©DÄZ[[wù=O?ý4.\ØHàãþÍ×âþÿHÔÆ;f KÆ¿OöýÝÙ•ˆÛ,w&§à[€{7_ãît‹óL +†T´ U·Œ²›…åGßL=¨c°´ë ÄM5S@ÉÉÂõ\$íVÄí &Äæ`jÛbLÏ ÛŠÂóÝãÝÝÝY³fí·qmûwÏp]kÖ¬ÁôéÓÑÙÙ¹ë=#‘FÒvP(;;ãÙ¤’qÔªU8.KÄEa|•R¥š‡x"D<ß­ Tñ³}”«×E$G*¯gk”Ê8Ã{†U+£TsáÃB:“€S®ÁD¢ˆÇë{†çTQ*WP;À{†çy(—ËÈårB>Ÿ? {ÆÊ•+±hÑ¢ôh=DXfB‰–’Ê~©V aÊŸ42¬ F‹ÙQW)6æy´ »ÚçªÛÖhr‚ef« ÖIœ’ÉdpfIÆ´Àœç&(×ZDî÷*³ ËvT¢£äR-¢×F£*»R2È#žÒÞ"Z¯ Ù~—ºoi]‚gf´I¥Ú`fÚÄëQ74­¥ÐìÈh$WÉ@©T ê\¸.˜ Ò:!ÍÐéz ÑQ²^Ó$^ Ô™ã܇3j©¬uLú.Ò^1êx¦Ù3UN¨+I„º¼©ùÄh™;%e$/ÌÒ¸®8j]׾ʹþIJIÔX'GI\ÁyÒÌÍN>`y¦çyX¶lYcÍŒú²ïu4Fc¥¾?35h¹Ñ–NÀó¯Î¬¶ö±dV,ËHxu˜ÔìF®’+¹(:‘X^­Šâó«QÚ±i°X ÄžöÖTýR|æq(F`u“«ó#¬n]§Š\nç¿:¹*Š ÝÔ} 5”Š;Sèù|µ\Bµ\ádUÊç ŸξT+(͘" *"ýbœSõ°jñ©ÎIc>ŒÇ-ckþI˜˜ƒù™Óðª‰oïž»Ësw`(›C<Å#ý7ãuã/Á©Óÿe·€?lþ>"V >|LO‰·Í¹ mñIp¼*V<ˆ{7} e'ß³áG*xÍÄ ñÖYŸž9ž_޶±a™Hð]>üD¦yÚ{Føù¨–FÛ3jÈåvfS|¥ÐžQ*äQ*ì|?Uä;k•†*cØ3²ù{FéÅÝ3ö¶±êþ8¼(a"¨!°×Ȫ‚4f´Ù! †v1×(0¥Nꚥ}7´p`‘ÄEûc0ª­•0¸ÕëUg+-Tg@py½ü.•×h= ÿ°6†)Öº¨)ƒ´jš@àȱTðÊ{dðšcÎ>ƒê‚¥F * c–ˆnd$+t¦RòA®ÀŸ?çÚP‰fR®kÚ¬2ÉçÏ ’5à„ÙÀ°Œã£}o4{£À\åY”þqî¹®xs*/HL9_̤‡³i<k„˜… g›ÔÈA +x-Z3¥æ $;*× g¥´îHÍ ô™Ó9 ŸÐõ£ÎsÌšRŠF"£’Fq(á¦ÔŒ¸ƒóHÍ €À"ñéß댞SEfÊ|ÄÚ&Âs†‹ïà£%Ç•?xÕòáX8½Æ®ëcÒø´fÁÍË5líÚIdŠUÜp×J lÛ¿4ˆrÿ6øµ ™~h³v\³gLÜ¥Íoó84‰Ìþê>¾?»œ¿Ø>nÊZp -’Õ¢HnRûÒgÆóêä!Wë…ç¹XØy2²å,\†9™SpÆÂO ;»÷v_ƒßlù ¦·…ã&½«³÷¡/» étgÏýwLÍ,„ ˆ~S‘ IDAT'L}/æ¶¿7=ýdË=ð|‰é°­(\¿QØ&Úáa f¿7ÊlüØ]oªRS¶'¹ä¡¶g„÷‹‹Ðh¤\{ÆPBB=>Ÿ½ZüÒn™îc©T* CêNF)‰‰J†TöB«bfªxêÈȈ¯Ö¨«•Êd4“ÀßQÂÄ,vׂ¬ ÐÞj‹¬Ù'^³©³>#‰4íÕBRǬƒFÖ9vü:h‘´äRf¦rýX,Ö`««âyO$Vº•|*±áÏ•T©Óö«™ƒ~^ÿM 4k¨å$üoâEu$Óâx½^íR¯ÄQë;˜¥ÐL¢’KíýCRÊ™4˜`  •=jß"®®/þ¬\.<ÊÇ*•JC£Y%Ùêø§¦$ÙjöC Àßaýç˜6çá,>G .ðœ;~'ׂš^èy2ÃÉS?î}Ýì |ÏƒÈ Ù5 ¾ëÖ5ë>à– (n[ƒÒP/.yä>$b6ŒeP®Ôpú‰Kñƒ«/çû°ÁãOmÄE—~– p<ð}$c¾çÊD`†™wø¥Vÿ' æLÕ"º)/;x£¨ÍãàKµU—ntci´;ÚuXˆÙ)Àg¸ø×-cBj6JµAÌl?§ãcøõŽÏâ›oćú!¦ÅA_âç°k1!5®¿3_uK˜š…-¾7?ý·ØQ{[ O#bÅá»ûØx13`Ícïƒ{Z·ÍyÃÝ÷÷©õl¸¿H¸Ñ$A™¬´&…¶¯ÌêhSL­a€FñI(˜UÐŒ€öÇÐl û_Tñß´öFm~ùa™P"‘hˆ¬+±SÒ Ù fT4cDiŽÊßhs«Eõ–e"•åqÜI¦øßÚW&"XJÉm£•ø…›Šð²áb.— @§f.tÎH‚4£ÄïR N"©R0οʑÂ`\ÇS×8÷5 Ð~B£eêHj8nádÌr  … øŸ%Üé^%i|^HÞ5£•J¥‚Ïp½¨ükGÁøï¼N’x>$ZÆ{QÒÈL‹Ê™Ñ⸨˜ÎaT&?$•j¯¬Îwt&Ó}‚÷¨ÙK5àuÖÝʲ™2Tv·§—û¨w¤¦Ì¬|·˲áVŠzîQxNËF[&V¯™¢JåJÃ9,c‰ØÃR´¨©;¾øŒÍjßÑ#sÆX˜uXæLŸØÞÜÕµ7ƒœ„u³¯ôqÚ“3Ñþ6ÐÍ“:ð½i*9Úïc`[Qt%çcÝÐÃx´çç8aê{±´ómx`ûõx4÷CLõNÄ™³ÿÑþ$‹[áúÀ‰ÓÞôT°nÇp½l[¬UaÁñjh‹OÆùó®Æo·|+–á ù¿CÂnAÌN!n§š„æ²g„k^éã´»,÷hš©ÑX• 2ÊšN§'$­ýÐ^2$GªÁWI“J…Ô¾Y{ÆPiæˆø€@OÁšv!W‰“ÖÝð{áÖ>¼^¿@Íšh ‹Ê¡üt ¾ V)cô_3?á}‹ŸÑú$•ä…e`’Žã ¥¥¥¡!¨º©ñ˜mQÉSØéK¯QûÃh†fíx>aÃñ×sŽÖûLe‰ ôµ¾F³;*Ùâ8h6N•ª|Jå†$ðá~DšAQP®„3\Ãõ¤ëÑÖ´6 T™µW õ3|4³¨kgg£ûC]Ój¶ k$¬šÒy »×QЍ™Ïð¾̶jÛö¥f¦!µlGoßv©°,ä6?Ï©ÀX‘ FƲ̰u²Û¦ËÂð÷€“";ϲÛkp\G/‰t*Þ,—y™½ˆ›^²¦™ºIrc§ŽV{Œ9z ÛD±°ý<5ø?è­<‡_o¸ïš{5–œ‰ªWÀ‚¶Sñè¶;Qªä091À„Ôlœ5ý ÈOî…5b?0ÃÖf]éy¸hþõX3ðžì¹K&œÛD€} 3Íãå‘‘hA^JŸt/§Ì)œ¢›É›œ²kØ•ï]gš cv-ä„Ò"•ri]ç§P(4d±Âδ*“SB˵¡M=ÕM‹]›0Ì`¨µ²öÔÑ5¶"«$4»¡R^Ç ZDs½qÝë¸(áÑžKJvÔX‚Ù·|>]Ó*¥¤‘åuœ7fµžŸÙ:ž—$¼ÌPsÉô× Ø2aEâ0v>`,8•j…AË•XñZ¥w@`±¼—½Œ1ˆE#8fÉ Äc4ße‡î–ˆ4 Mc´9¼Ñè¹`º˜çæAýêh‘°±ÜϼαhàÍX1p|þfl/¬ÁñS.@‡‡¶Þ‚·ÞŒŠ)ãÔFÍ«ÖÛi mñ)» lXÆ‚ï{XØy*\ŸÎVÍM¡Iö_Y‡Æ¿dFe>áú%‚"JLèEÙ%HÚP“Ÿ)‹ Ù ÇqP*•ÐÒÒÒZÕ@IÏɈ±Ú)랦r#JÁ’É$2™LC¿ `§œŒ5*{Ò,;•ßð¾ÖŠÅbC_³+j«Yšp¤œ¤OÝÑ4ûÀLAs8;Õvmg= É'³AìDÅ:&%´”í©+›6K%ØÖy#Ñ`¿•S©›¦‚n‚yžƒs–¦©:@ezá~vê°Æ÷-Áµ:€iöP¥X¼ÖÑù‹¤Ú÷ý†ùæû”òBÍ@(A% àú!¡Òû7!•{qNãñxPkE²Á¦ª|4{¦Fº¯h‚sžÏçGÌ¥ÊuôºÕ\Iëkø$ã#23aê>Bž:±¬á¿¾e໵aaF¡>€g ̰œÌÉçù°ÌÞéÜ1˜;k^wìüºŒ­™–9äL8å«E}á¼RšºÝìOKÕÝêó®ýÂR³}™oøÀß̾™îqX>ð <“û-V>}wÝj۲ЙžŽ3&|sÚCÕ-¿ï›ÄÄBÁ4ë¨& aÇ8%êˆÇñS£6~Ž™u ÔL›Öœi6“cĹ Ë0õú96oŽŸ6 ׯbÄd&¬YÜý»ÁΞÆ “σoÛ€ïÂŽ§aE¢ðÝ|ßj@‘ˆR¶‚¹³&™ß÷10”GµVCÄŽïà2ðÁyo9ǵŽêÝ߬™9´À Dˆ½’ ×l­VC©TB¥R ¢!£E¥÷×9IÒ^ús¾ŒÇ²gŒN|êµs§M»‹ÇMÙÇÑW]˲¶ÆcvÛñ˜’Y„ª[Ãwíâ>^@6¦¹gzY‚æžá7d0ÊåòˆNïû{mV –ݨu-ÿ h4™;k5’ÉdéÐhn<‡ëº©`†€Ö·á(z˜x(y÷(RP¨2'ÞÏ©ÅÔ Ä ÕL£Ûê<¦ã öÍá> 4&Ðþ;šqѽKko”¤„m¢µ!¦‚f•9i= ‰67% dD]ÁHÊ”œhð,ü»*ñãšÑ¾$”¯iÍ‹:“‘Ì)þä;Ny*w Lk“OI®’Ríû®SÑõ[«ÕÉd‚ç„ûUxìX3¾D$áz¯:j ®ÏO¸–÷®×G"Kµ…Jå”ÐósJÈ4»D¬Y:•ªí¶6Ub£ŽtáuM™Ÿ­ˆ.n{½yÉ_|Soæ”sˆfÆÁsX‘Ò“ç!»~9"ñ¤<`*•*ZZÒø§œ!!ðøS›à{Sf…’4×·0ozÎ{ëq¨9Í~‡"‰!ãç¦@m±X \m^©vÛJfªÕ*J¥Rƒöô@Üœµ¨“$†Q©±ÈÌv˜<ßÅÄÔlt¥æÔ¯Þ@ª¾¯4IDóÞÁµÉ烽0š{F}Ïàxèžq Ÿ-•{i#@ŘÑÂvf[Øl¨7NägjµZCƒoiZ kÍ ÊÄ4ÒÎó'‰@ǯynmèÇúêýµ@œZ~Þ³v|×¾3$—üw’°E³ Fùy>ÍÀh‰à]-pµÑ&¯OŸ#‚D¼7ʈ´W kqÂ}e(¡Rb¡®`j@ÀÌû"8'1 ¨Õú“h4ôwa6&lÓM"«† tDã¼xªDP¿xn­éá \ÚZ‹¤Y$®MZ7«%r˜ ‘0ég•œ“P«¬.ã@R¯5Y*ÉäÚdà’c¢ýpt%á ›-ð¹Ôš]ÿj–0ZOKf©wp½…ÝùF²±örÞ,ú· Ú:Æ3ðâ‡!YÈ¢°cs}S1^ÕE[[ßþ÷ ³­^heÙ*U÷=¸ÑÈØí—;;R¸þË€ã6%%‡ê‹—@[[6lØ€E‹d¦P(Œˆ.¼’@£c|à¹YF"Œ?þ€žŸú]¾Œyîpçáz€ï{õLÊð4[Æj>Íc·{†eYhiiAww7Z[[ƒ=#ŸÏ¿¢÷Œp}³mÛ?~üÖ;„ÝÔåˆ`^ûŽxª”J¾(é"èd=‚:ki†'‹!›Í6ô5!‘ H'8ײ+X'™Ñ~Ñhù|¾PS"§à\‹Ÿùïš5Q ›šeSiÖ¼tª! Á·JÜ”8òIIÒ4ó¥½lôÔŽZë@Ân—¼Ž ÏM¢¡ CS©T‘#ˆ¥$M³zü}¾IùZLoŒA&“ipõRÙ•œ“ticNí ÄqÖ5nø¨½×4³¤{ÏÍçS ¯D†sʹ)•JÁ|¨59ëiøÌq\‰DÖz[•z©C`˜ óùâ|‘0‘˜r½1kÈ| (¨4ޏ†µSúü0¦ ;™¹-ƒÛP3£ìv¯7. ëÍ`ÙQ”¶!1~ìT+Œï©Õ0ïUG㨩G£’D¥æ`Ú¤œõÆWcúäqu À67ÝþÖ®ÛŠq™=ðKîÑÖ’ÁUŸ>ä¨Y+sh¾|¹§NŠÇ«V­B[[[ÐøI}Ø_i%\ÊMÔó<qÄ´v†Ñ]M«^zf†Œ±ší+›Ç^íÐÕÕ…íÛ·cÕªUhoo@j©Tjî²g0ª»xñâ:*!ÀÑÂ_áZèÎëeE­„µq^¸Ð^#ÀW$CÉd²¡ožOëQ˜Maæ„”ßÅk'™"1"¨&TÒÆ,l6¨¤Œ$N%Ka‰¿‹%f’ø3‚Ó°lKƒ`¡'RÛ\µ&Àåuq¿ç5j½JÍÂã©…áŠ+à €UB¨Ÿ×lP*•j zê §Ù¦p?Þ³ ÌÐhFŒuJ,Ô„BM"Âí9ü°Ê)\ã¥dŸïUS%€jƒÍ1Qûg°çV›b†%^ÌҨ͹ö|")d&Fk¹øü*qä³®5µ$g*U‚ÂgLדJíôYæXó9hp°U¾³§.Á£iÈ=ß $bÃ?D¾ûi´Í= Rɾþ÷ÇbzW®;ü°D†µ§’ú|ð¯kñÍ–¡£=½G"cYžç#‹ãs=ǽj&׃mÕûÑÀ¼fÍÌ!yD"yä‘èîîÆºuëÏç÷ƒAÅË# ÍuF1iÒ$,\¸¤Ã·jÆUv Í²4ø±7{Æ¡›{ÆÁ½g,]º[¶lÁúõë‘Ëå^ñ{Fx G"tuuaáÂ…˜0aÂÝ3ˆ+˜*1`dZ{X(xV`îQ®‹ Á­¶£X,"N7m. çµ(€ ]«–’Evp×l”öï+•JI#aКÊŽ”dèžK>š¼ŒùpF!\o£=_ÔYŒ×Ì>¯ 3ܬ‘’4ʤèDG‰‘fߨª¬M³Cš5 ÷ráø§ª´IÏ£D ‹¡P(4P¦¤™ Ž6 Ï»žW*• ‡íÇÕ\A3/j)¶ÐæØqýj—‚íÕÄ,š:·iÆ‹÷¡kš×Åk× ƒfÕrÌd2Ê=ãñ8ŠÅb@6™™#)SY£öFRC'Þ£>o$B¼&mvÆ£¨FpŸ"dÃìˆcß‚SB~ã Ħ,ÁÜ)˜Ñ•AÍqƒþ2®çÕõðð±m<úÔF\zňE‡ÝÐö@d|XÈdâ¸î ïŤIqÍ]k±`j“;°`Ж‰¢«=Ñ4b=D_¾Ñh³gÏÆ¼yóvYÚÌbí$úgܰ™bÛ­¾RkšÇÁµgD"Ìœ9sæÌiî»Ø7^¬=C•4»B@©Ñnlê Åè1Áo±XDKK r¹\C£Bþ.¥dZHM¯ÍIp1Kâû>ÒétPc–È|V*¤Óé"˜N§ƒz-¼d2‰b±ˆD"©kt×LB¦õ5a`Z©TH…JÑ´À^û¥„­pI\²Ùlp~•)©ä¿€«¹ƒfyd5cE­ò6Î/?ÃëW÷2•«¹®AÎW8B¯îvår¹¼g2™€$qœi#­™ B¡€pŽ+ÏÉ1 ÷>"1 [‹sý©¶ZrÀó`f‚Dk-‘HDœs¢ã­µA\ת–à5ñ™Ëd2Áü(Ye½š[ %“Ɇ–-”r-§ÓéÀV\M<8Ÿú]š9Òú$}5ƒÎkSÜÁk[;7ÕeîK¿c,$1LØŽ ›·ËÍ"(lƒW-auu>þòì|³ «¡×Lµæ §/‡_Ý÷®¹éîúÊJ.QRñxG>WüÓY˜<±ð=Ì™œÂ’™m¸þî5èh‰ãÌc§4D´›Ç¡yè&ÒœÇÑAœ‹Mžø’ç Q»&plÓž¡ÖªÍã¥Ù3XOÀ¨l-ìV[fíýÁl ñ òUÒ¥nZª§g™@”_•Êj„F© : ©õ-³$Ž]\o$EŒ:«T)ìüDb¤’(öÑF‡JDµh^›?ª5³îÇÌFhÍÇT Ú9Þ æ¹Ï“d(ð¦LŠyu€Óîóš¥â94˦ ^³`©T*xßp̵o ëh<Ï ²^šÅQ¹I»Ä“hР\.EìZèÎuF‘J¥‚qÉçóH§Ó íÌ q=sMèœé˜kóSu”SJ‰DЋ‰ãAr®}…˜ÔžJ\;JÐTf¨’MŽ[>ŸoèõÃyV™¤Ö1iVGk´¸&T>Úèl‘±ÕÌdwÄãqär¹‘d†6Çۛò RÉ^ì<<¼|<· ‹Á­0´îqü¿Ë7áäãæcæaÑÖ’Dÿ@«×mÅãO®ÃÆîHÄ£ˆÇ¢#º¼®T+bQ¯?v!Þù–£qâ±óaYÕš‹ˆm0±-Û68f^'ŒeКŠ6±æqh¾puoÎå®Çé@J Ôñ„/!ui™æq°íÜ+š{Æè㤢Ad4j®ÅØtK§Ó u üœ6) 7Ë#iÐ{ãžKuûá^$MüœÖ#¨ŒÒþ>åHÌÞ¨­³öÍ(‹ ýA´p^]Ì(µfEíƒÃc¨•5鸆 L¸‘¤ÞÓh=LÔÎZƒÜ¬úw²Ì¨e¿FØIX8w*ÇJ$}¸fox½*—äu“L©]°6o$±UDz°I×ÊéÂãÚ¯†’BZ%hÌ ñ³”¥i*œ¡ ¯?®#޹FŽ»f5ÈÈëÕžRálÇ–2Gf™MÔš.6JU)%…\ÿ”¼)ñÓߥ4M &”t«QI'çšß§ÄH³> d†„6³Ú— ìío>Ûv áúÿ¢QF\lÀô÷gqǯ7,-3ÆÀ2–eH¦áÃGÍ+°cu]ž[â¹Spê ‡ãäãaúÔN¤’±áW7p=‹g¶Á2oŸo°eæùøNÓÂóx<>jQͨqƒÖ}q\uMj?$^?ÇMëÖ $àkV„ãÂÌI¤>k­"‰aÏž'•JÙA^—:èézÐÆšúÌð`q¾ÖqLâñxC$•*ùâçr¹\ðû{Âf¨+Áž Fk ÇIýØß¾oì”@;;ÙÓòX‹¡Ã½®‹hDX Â…ÓWW5¥¼ö\.7¢æG-fÕáL.5ûúÐ^–˜II‡ž›û¤’<µV J²¢Y¿@“‚Y¬ë¹xÍ<OåUá®òÌ0ióΰ[f’Òé4*• ²Ùlƒ…6I„Î!¯'l…ÍßUI¥“€ÑñL-ªUG"@À®õAÌÚ0£Ã±¥‰3+t’ÓÚ Îï…&ü~:éñý©=‹´Q«’!%2*áÒõ¬­Ô쓺ŽqM“˜kík˜œ†íѹ†µ'’¾ÉÂÍOù,+)ÕìJØUÉ2kÒtÍ„kèt=7ô™á@ì)õ̇ºËð ¾R­aÑœ©8bÁa0Ö>¿žuñ<®çÃq9iõLÎ虡Æÿí`¥æÑ<šÇÞÜP¹‘Q ªÝL1³höP¹g’æÑ<šÇÞZB”[)Ö ×FŠ,áw¨ '\K¢6½Ú¬25}mà©’-F—µÐœõ9&ˆe]O±X ,Á •Èñºµ¡Ö,<*€c&‹EÝZ ¢îm´‡f6ãR,ƒûft{´^j;¬ 4IHnÀkß5Kà| Äb± ˆß²¬àU®AÒ mH©®o$áÚ/>óKâ?f T¶¨kB»×\«ž®?mžªD…Ÿ!!å»S{©üŒ÷&ªa#fû8×Zš¡÷ª½éTz§µNj~¡æj§Í”¼o•óq]ñžµˆŸ ;ªñ3<·Ž·ÖÁiTëx/£’Øèæ±» ª££½½½˜1cÆ`bŒãzp\÷9‰ù›1€m¿0]¾eYÂäÉ“›ÖæÑ<öâ ã £Maý¶ê¨w·gìØ±---£fuV2ÓßßßÜ3šGóØG2£ÙJmÄð¿IÔÍLÁ¨öÅP[_-8§œ‰àH3”7©äGTks>f{˜5c#••ÀxéyYãÀý’×LÇ)V“D„û¡„û¶„-™Í"PÕ‚m’%‹jD uE¸j ÷@ÉOØQJûÛ0âÎêöÚÑpÚo…ï%#j嬒=%"£}&,ÛÒ U:ÆZˆ®™$]·ªPÒì£Î5›JòÞ5+Âk 7èÔÀ!$“É@"¦dCûàp^Hum*‰U¹XØà ܆ÄD{ºðÔ’ZëØÇipÔHjòÁqàç´~ŒcAÉqçzá8ò|¾ç_¢ÑhPÄ32“Éd`Û6Gý}3,'³^ÀŸ©¤¾©Ú¶­[·"™Lîµ¹Aóh¯ôƒ_¬ª{ViÀîö ºÀôõõ†¶mcÛ¶mH&“ÍÌLóhû<Ôˆ- Á$A6qOe-$'±X¬¡?‹ö!¨ צ(è%ÀÓb÷D"h4Ú`-«ò£L&#•Í´²‡ ­i+HÓfÃu›Thßf8¸ïЊNVº¯ªtD†÷¯=?8¬Ëat›c¡.aü=¹UZT©T‚à–g+Éâ«U´ÊôXsÄ÷ˆÎ{¹\nȺ(@gƒU% j•Å*Ç" S ÏëÐbtŽÏ¡5êôËŒljÙ®+5#‰Åb#Æ:õ4›U¨‘ãE™·f¤(,‹Á3¡d]³œ'ÍÖq¾T¦F”rܵŠd^ײÔd÷œJ¥‚ú ~(Ñ#©RËpm;‚ÌèÅÅáÄ÷}Lš4 CCCÈårmc2>ìÛ¶mƒëºèêêjFX›GóØËCýíµÉ–TŽåYœ…ÀŒ U‹ÖI$(WcöB#ßü]ª³F„ U³´Ç&@ä0Û¤…ݬ‰!QägÔ8€VÔÐjÛL¯p“Q^3ÇVí¬K¥R`ÏÍÚ)ÊÛ4³¥5'”ùñûJ¥RàXF"¢†‡3U IDATšÉáçHI0¹^hvÃ#™L‰ï?mØÊ:•Uq|9>êJF¢¡™²p?•NòÿI*I̸V´1-¯/•J¡Z­=uôz“Éd U)]¸W× >Çj·žÏç¤qçpF’RÄR©ÈÓi/ÍŒçWç…Ï ç•ëTŸÿ†>3á bO/pc &Mš„¾¾¾ Jq°÷²Ø*‹aêÔ©‡Œ¼¥y4ƒØk4ˆ/xm ¥Yš±€þÉ“'£¯¯/Ðr¬{F4Å”)Sšä›Gó؇=CA¤º’i „Ê4`BOàK ®]ÐàN™ ÿ ÿX OmY2™LCo‚/˲ËåL&ƒš9î#±à\£ÐŠ¥TJ‹ÅÒDM÷-J—Hb4KÀkR hAÊè µ™$#ð$¼?žSÍX«CEl§¦šMã~ÍŒ–º£i …JU§ø‘$`ZmŠ5ÚϵÄÏi¦A3LúoZ¹a›M°œ¾Ó:a–§“κÉP&Fû¬` Jƒ  V«õÏ®©çË6‹M÷–´°Í°h”1Ñúi-,OË*´Y9Fj(+¹j;G›!Ò^T«Õ§TÌ,îÐþsftÈä Æ` Æ`hX¼%Ó¦Sîƒ1ƒ1ëâRàY cðÙ’±4È•C`åu-ŸÅFõìmEwUÊ¥’39J¶¬K ³X,öËtÔ‹OËqнڮï–"{ijΖ€mVTZc{¾(;b9 Ì6ã#0Ýl6û¥@º†"í¶üH²ùÅb±¿nVV[\}‡íé"©e½$l%°m‰TZý*ÝõÝŠE({a%›mw{eˬ¯»L&s¬Ù³ØiÜ«}T;Ó,É:rŠåÌé è\ëÞíÞY²¼úð¤UÙl_ Ûl¶V«õ?gWÛ”ÔfÐôû¶”O¢­VëXSñ¨ÒrÝöL+;©¬ X™q»g–¼¯ÏëLë{tÐ|¬šœø9wØ €Íʺ6Š¢M´r{ƒ1ƒñÍVNÓF«¬á±’œƒ1ƒ1°r* —!ˆ0¸Q¹’~fµE®¶Jc¶ åê©„F?¸·R¶ÊjHLŽ‹€¸­å·¼D-[ÊdåŽÅùp¶¸é&ž¶á¤4+olåu­“a%šu q4,çê)#!§Ð–ÓÙ QZ9-¼` ïÊhM”I°üÛ(QŽŒåÜèzÚô̳0j>Ÿ?ÆAе{¬ò©tSRí£› ÑÏ-ÃòD­ã£9XîTZ ÁöV²™?[Fe÷Øò¶lS˳½—ô«#¥Œ†Dt/VM{e•ÎÒάmä*GZçÏ®¹æn¥Ö­#bùXš»m´m¯­3jûÛ|îègf¢(âàà€ááá§ôËc0ã›=]±if‘±ØŒÁŒÁ°ÆJØZ>…þÁÁCCCÇúg¨¼Êöǰ}jÁh²ÊÖ±±QrѨV«ýH³¶¶ Èfˆôw+-+@*e0=¶¥;*Å}VGwË5¶Ñ:éìÍ0Û† ¶‘£æÛ •aÈ”ã`KŽô¹t/ÍW Y{“~/ÈÔ>h ¬’–íYc3vzßXYk•ÙõÕ>XGT«p¦ùÚ†£6ƒbË µgV@!Íñ’”´øä ª{½ø;º¦îQûlûiع§+¼cû0YQ;—´\rZ!Ί(k¤’=ë¼Y>ÊîlïëÛ ¤UÖ³e{6«b³¯VOYÇt¿U+p&3ãû>…Bá ›ß Æ` Æ7oèd#]Ö`Y"ä` Æ` †%K‹³ ÿ,@î°¥,¶Ô%›Í>ÀldY%jRÙlö˜“¢ìÊÙ©×ë}ž‡@”À–íà®ïص¢%¶ïŒJ®ÒÄd+±kÁ¤•·Î‰-€ÏúÌX2¼Í©ü«ìLÔ;-«Ÿ*¯²ÙëiU:gûÅX¼å·hÕ—¬°ø.ÖI•ƒb³r–ƒd ëÌê¾å$«¼­Ùlöœ¦Iëéþ;âÁh%Clcõƒ‘L¶æÔív©×ëýïÖzf2™¾3 3¥ýÖ|Ä1·ëPZÇ'‚¾œ²þMÏDÇ4 ét:DzU¶§“îIŽí¿#Žœ3•Ú3ÊþÙ ‚Ö_¿þl¥˜m_&{¦•ÁÉçóÇÖÔ>û*ŸL㜰Îó153ÛÜfàÐ Æ` †FºÖ9MÜ82ƒ1ƒa‡€ª §›Hª zÙcÛ×DŽƒþ/ÜbK¹l©Žø!–k“Vó²N‹•…¶…m¬©®îúL:jœî#GJó×z$K,@%_Z Ûé\×ö9±}A´Ni°(ÌÎÕÚtÙr]ß–8Y>‡dªõYÍßr–Î-†´j]jè˜v.,?GÙc[*hùMâFéséÒ&ë`ÈùQ–œ*Ë{±’ÝZ­›Îžu6-Éßfoô»V½O÷¬LQÚ¡°}ôs­³ul6Oe„6gdñ–äXØólE ÒgΖéïé²NÍÇ:Û’?×}kmuF¬z~×ʬÛl™ –¦Å ô÷t?žcjfòÀÓµlƒñÍJÙÆÈ8Ë@çóù~ïø´¾þ` lÆ`|³m†Š€‘€¥"ÈÄ@_LÃòól£D< .EÊ×÷Z™[ ”¬\­€°ƶ燕€Jg2¼lï}‘®€ ¶Žín.À«ë×j5 …Â1šîâ.à¯û¶ÀÜf¼D¸¶¥v–s"p¯2;«ÜeËÎ,ÏÂþ]ë¬ßM—& ¼kßlÇy{Nlÿeˆ¤®%V ?ý½VH!-´Ðh4Ž•`Ùò,9IÊLØì‡JólÏ‚|elt¿”k~OÛ¾0ÖIÖµÕPÒöD²,myYZˆBß/ÎPZÚ:Íã±N¶-QÔ9¶N«-³ÙJI^ËHŸw+F`û.Y%:}Ÿ}öìÚw»] …B_Á⎾3m Õ Œo6(ùË¿üËAŸÁx  ØÈ^H6Ò9pd¾™#þú¯ÿzÑŒ§†€·•iµ¥a¶ìÈ*pÉž4Šó ß—-j6›OmÃtçp[¯/¦!à%Peù=*RÙ2ܪTÌx+I-µX­…>+à, + ªï¶¤rÛÏÂKÍ_Ño+H`Ëx¬ZUºa©Í<Ù’+eBäHj¤mßÎ9Mô·%NZ/›UQô^ë­yØF˜¶/™Íæhmòù|¿Nÿf×GŽ‹mŒlÁº@w>Ÿ?¦ô¦û°=S4;7‹¥­Ã’抬[e6eeT–g+(`KÐısM÷p²%ˆr‚”%U¹›ž%ëxêÚ:grâ­ÂXEÇδœjÉHÛ&¥–;f3µV’Y{`9T¶ÇÌópÇ1gF“²©²Áøæ¥úc0€¾RŠ•W84¤ Çq6c0žrp¥&@¢Ì®­ù’ãy•J¥_Ú¤ˆ®²0[¶1¦jû-ˆ“EQŸ Ò'ÛÐQ€O Ý:E–bËÊõn·ÛÔjµc}J¬2Z½^?–UÑ}f³Ù§¤£ÕÄPs²‚õzý˜˜í†!ù|¾ÿïv=å LÚ¨½u¬]×}kŸ”°åAÖ±p·Òڛʦ¬2¦>›®²¼¥t#Nñ†”-_DJ›ZËaÉår}à¬36 ×h4h6›T«ÕþÚX‘]_2Êr¤m¯—z½N¹\îŸ X…:Ë+’T¶@¿Þ«r¼ä,ص°ý˜þu^Fÿ߯1±a{e¶ô9ÛÐÖŠ)Èi?`¤–§õÖ=Z=*|V¡Í6›Í~`CÎÖK¼6ËÒÚ= wôCïZ -²„/ŠÖ¦ÉméOÿìy¿ÿeº‡§%ã~´þËìszXcò«ìeú»>ï<üªsK_Ëþ=}oê^+j&ƒgË?~3óëØŒÁØŒÍøz X²Ü[’dKTT ä8õzýXw{Kì–ca;¹[Û$°fÉ×6¢,â¸Î—¢áöšêÏ¡k« Éö±ÄoýYÀVÙ–b±xL±L ÷Y¥_VÁÌ6V´åm6s¤`“å ©TKßgeŽUæg•¬ƒ¤3+•8«pf%¥…Ù´'Zcü´r™í·£»JóÔ_G÷–æBÙ;¶—Žæ¯5ÒþØE›]Ðõ,?ÆJ kì\u?â€X•6[Ú¨½Ñ¼l©¤äµZíX`P½m|ßïŸw­³í#…5Ù»WÚK+¡³iå¹ÅÑÞÚ~D"ãÛ’qHƒ¥s/§Åþ\÷b!ôÝvol&ÕrÜtVíyÖ¹¯îy¸ãgF›c;µ~ž¡j5ÞqPÖ×qiµÛ4[m¼£Y&ðÀù¬!Š"êqœfò¹8qžzYØE­VÇ¡TÈsôÚxîç¿ì n0~ýµj6[4[MÜ~ eïaò\žTŸÙlµñ}B.‹ãx$_r;õF“|.$ð}š­ÎÑœ96W}O«ÝéŸÁ0“!|\Ò—ïÑ<0G1­vÏ÷ ƒ€N·C³Õ!›Íñ}ž „~]õuØECDl-µ-ùø¼ûê‘ݨû™Í3¸žG«•¶™À¼þcþ¬5þ¼uÿuöä_zýçåo’Íù¼{mµZ4š-\糚ól˜Áóü/¶žG>â:þ—¶=Å¡FïÙ š­Žë 3Àq§Cß“~o%xϱm\ÏíÙŒ8éÛl&C§Û¥Ùj“ 2Að´ržUÊe‰È¶ÜI6D¥Vâa©ÔFNƒ@¢ÄàY “îÝaK”YÖçlÿÛ,ÑFÉÅq±\e¬Ê’•^Ö=Ø•¹ jm©·ü˜t™œâ¨+º- W–G߯Ÿ[`¯gD…UªÔ|-_Ī¥é9°ßiµ4oÇv¢·Ä}[‚X­VÉçóÇÎ@º=C¶lÍ6ÞT‰—ý¿´¯åÍØ,ŠþÍJ3[Ñ…´œò³LZ®½ÒYj4}!9”Ú[•aY±9¶ÜÊò·¬d±ií—=ÓúýŽ”ËÄGR3ÎR©ôTÃZëäk”!Òúhïufm¯!í¥ïP–Ífºôï–›cí„öHg»Ï½±Ħ:¿”TªUê•mV,²²S%vBÆçÎðÒåó$Í:kw¸÷`ÃVŒŸ-pòÊ;¼zº@»ÕÆq]šÍÛË<¸w—íÃù‰«|÷;qŽ¢ ¶w…æÕ¨ïðéOß§š;Å÷þÕkÍQJ…ÄÖÓYã™6Lƒñ/{i&@§]åÞ{ï±²_í­¯24µÀW_ xǵ¤ÃJ…ÝÇ7¹ûd›z<Áwÿõï0ê%DGÞ·Œt7àÞùŒØß¸Í߸ͅ7ß`,Ó`kiìä<§fOà›ÈV­Vç`í6÷¬Si'¹ WßæåSy:íî±úáN§ÃÁþ[+gÊS=Øbku›¡ù3L”ónÜâoßÝäêw¿ÍÉáÌS5©Ö(ÛVѧ¯Û´:ò2<¶þú‹xvQQ©T©WwX{påí ]2ŒÍ,ðÒÕK¸í‡kw¹{…ƒfŒæ™»ü;¼~®LûÈiµ/ûrO¯{zOl ®Ö==ß´bŒîÏžÇ4HIGmã7;Oûïßd›Ði×yðÑû<ÙÚ'Nð2 8Ék¯¾Èp<µžqS©VÙ{ò1wmQ‹Gxûos"t¾”Íèt#·ïò÷ï­³ðêëL;l=Y%Ÿaa~šÀý ¼Uku*ëw¸{ÿè½8ùÒÛ¼v¦D»}Ü–u:]¶ØZ^';9Ïäh™Úáv߆LŽ–©íÜåï~ºÂ…·ßæÜ‰±!×~Sl†u ,Å÷}jµÚ1‰_û~®V«Çí‘Í~¨ÞÞv–Oóèl}—UY’ü­mú'ü!Жn¬è8N?šV³öAü‹4'@ÿ)Cd3=i…6 úl»ŽÖY´€Üöv‘³ Xkl¹*¶Á©JÙ¬Cam¤Í¥Õåñ×5¬jœÍ‚Xnˆkоè|ØL•öÜþžUͳ}R4½7äl¦#+ùœnºi3Tºg­—JméžœS}Ÿá,?Èö|þVY¥åÞX…@«PfÇ\.G>Ÿ?–Ó¾Éq±Y@­m±X<@#.ûÔh4(—ËÇJ ­ðíÅdÏžCë|Zç,ŸÏ“v¶÷¦³¨çÒÞëS™|K¨yî ©Ó¥ÕØãÑû¿àIw˜³ç¯àW–¸wÿc‡+ .·n>¢UœâÒ•)¨lrØ€N·ÃÞî6¸11{›kln×9qõ5^œ™¢¾·K³^§ÅdÂ,Åb‘n§M½V!Š Žt:m:~D7ЍïïÑlµˆÈfó u;ìïÒî$dCˆ—¸Ó&N2a–¡¡¡£ÈÜ`üúoªžCGÚ­˜“W¯àl/±òøCþßýð»/‘TzúòQL&âÍÚ6«Ö‰ Ó¼võ*Ùn“½ (Âó| ¥2.1µÊ!ÙB™LÆçp?Éæó$qD§ÓKGÖ[;<ºw¿î2T*02TÄ’¢ÖŸÞ|B44à &H*›Tk½—àþþ.v‡(N2!žçR;Üæá{ä:ÌŽÑ©móàö]†Ý!Ä^ÙùIJ¡ÇÁÁzÏ÷‰£ˆ0—§<4D·Ý¢Z9 ÛIppHÈJd€ZµB§ÝÇ%—/P*— <÷k³ÝŠl¦Ul¤2"½ýçgr#ZÍ}ðs¶Jœ>w…l}…ÅÇ·øY+áê…<·n>¤Žsáò,^m“½Fïú{;Ûx~†\©D«V¥ÑèÙˆ “¡<4Là¹ìïÑl¶ú{’Éæ&ê´{kßé'ËÃZå€v'Âóâ(&_(‘/äi6j4j5¢8ÁÏd(–†qèR9Ø'ÉåCöpŸB©D³^£Ùl'½:üÒÐ(.ÕÊa/*Å„Ùåry`sŽ‚ Iԥ݊™¿öþî ËKóŸö:üÁᅩS= qd3‚LØ“Á­í°úhvfœW^~™mvv*tº=°S(–ñ\¨Vs%²Ù ‡û{¸^@®P$Iâ#›Ñ¥^Ýãñâ=⃘¡¡2cCE<’öŸÞ|L3‚‹W¦q«›ì×:Q—ƒý½þ~f ^ÙåÑÝ{øu7™"jôlH¾z.19fæ'Îe8<Ø£^k<ó|Vèv£¾ÍÈå‹„¹úÑÂqÉæò”ÊCdü¯Í°ÀÞ6 T­|©Têƒqë((3c>[Þjœ€±í¥a‰ïVXÀ–~ÙæiQ«Ê—îé¢H¾@™¯€¶ ”èw¬Cf,Ú ˆ²M6:o¥p­\²@¨2E6ÛcE ¤Îe[Ê™H“ÙmÉ’íÿ¢ž=ýàÀÑ}ªìÉ–Æií•1³Äz}FY ÍÏFÝu¢9¤*êLhÍ,'#íkÿ%×l³nvNõz½–,Ä–4)[ •Ýk~•# S„³ŽFÇäóù¾L³•š¶ q*AG½W¬Ô³6ÈÑ|ÒgDÙ>UPX¹g9Ÿ6“–Éd¨Õjý,Š˜Z‡l6Û?ÇÊìh¿¬}Ž,¿Kç\ްíñ¤}ÐyµÎ¼Í¬‰{wŒ#'ÃcuÑõ ?/Ú' ýÇ,Õ®ÝàÛožaó$nã?òñÖ.ñÂ$Ž›¸>.#'¯pu~˜¨U§öè&?þt—~ð=ë[t‡ý¥û|T÷˜Ëor÷Án&$j5ÈO_äütÀÒ§7YÞ‹(–iG½ÃѨ°õè÷o‡Yºí.Ó/¼Îµ…avWnóÁ­F§F Q˜š¦³¹FhÖê Ÿ¹Ê[×ΓqåfÿÒáÄ9.¼öcÕS|øãÿÎíµ;|ôxž™Æ"wná†!Q«IaæCÕ'ìv=hìsûÞ&7^*rÔ\—n½B7;ÅÕëÙºõsníNóþÂþú]~ñá!¿ó¿þ¾ÓûÖLÛ·–¨;Þî2?ÿÇ&oüáw8át‰q=öÙD2Óéõ/ŠÌ÷¢„ ݃%–ª³¯óÝo¿ÀáÖAëÿáƒÝ]ÚÝbÏfx\Çaxî2WæGIÚMš+·ø‡V¹ð‡ÌäÁ#îÜ~DÝ ¡Y';}‘×®^¤S[æg?¾M01IÁm°½×áÔK787é³rïm7Ȇ6Ì^z…‰è>?ûÅCÓ“$õº%®½ù-Æ¢e>zÿ6u¯L1áŽ_çÍŠl<ü€÷øƒ¾Ecï1?ýç®üÞ÷iÜçƒOž„%B/&œyƒW`óÉ—÷ðÃn«IùÔK¼sí  ßx«ã$ÄQ–s×ß`²¹IþŸ~ħïòÁ£º¸u'“%n7Èž8Ãh{ŽKœT¸woòKÃ,~ôUÇ%ªWi‡¼ôêeï½ËGk£üÑoPÙºÏÏ~¹Í?ú]òô*3Ø}´DÍñp×øÅ?uxý¾Í”¹.ù°g3ð‚Þ{kþ /L•©îí°ñø6÷Wöñà ÝV›¡“g ·žPw=¼ÝUî4öð¢:-Ï£»ñˆ÷w«,œóy|™pö'œU~þ£q†Ç)zM¶:œ¼ö.Ï$¬Ýÿ˜Å';d†FqšìÕJ|÷{‡Úã›ÜZ®S,dÁËpúÊïpiÆ'úšØ [*$`j•­,X²Y—tDW Ù<øÖç-Ád˱`J×yÞ*‡)Ë#€+lIÚ¶ó¹-ϵy›qQ¶; °¥YŠø › ” ØKP@™õ¶%ë0>«ß‰À¢Uý²e&l´^Θæ­*9&Ö9´å\VÜÀfˆä ø*Ro3'rNµ¶/‰åZÓêœiÎö,X`ß¾÷,WÔV$؆°VŠÛž'ÍK{o1ë[~”΄틣ë[ÇÕà­Ód«š4'[º&µ¶ÖMDY(­K»Ýîg)m¹£œñgõnJ72Õ÷ZÇÐÿ-æy<í¥lÁá×nšˆmŸ'ÉÛ|´ÚÄž‹Ÿ iÕªÔj-ÂbHÜjãOòÆ[¯0•«pëÃ÷øÉO~Äßþø]?dúÒuþàŸ 'Ƙš›Æ<.|ëû\[Y_zB¥Þîe_Úu–î?b{õ>K{]f®¼Ã+/ΡÀT·¶ÍÒò*ÝÉë|÷;ßâähÀã?a?ññ}Ï ˜¿ö-Þ|óuf‹>aàÐívˆãëkÔ:ΗŒçEZp UoR©u(d=pš{l¬-Sij?k<¹»Lvá<~Laâ o½y§›P(dp¢.q­ƒeoö^l™L€‹ƒãJªÑï‡w¯Àì¥s”“„±“/òƒ?ú.“sÝ„Lé$7Þ¼ÆDpÀ­÷ßã'?þ{þþ§÷h4XYÝ ÑîÐí´é4öYütƒ‘ ç(Æ Sç¯ñíï~—‹—N“ë&Ì]¾Á·¿û*Ïëñƒ\À™9ÇKׯ0âvØY^£YÝaisðÔ¼uã2Ã…LÏg鶪4#lqˆ™ÙY¦F²G3åkLì Þ*¯Ø:ÝçÚ Ï%i·‰\/“£S¯P«5ȳÄín~†×ߺÎ\©Î>àò#þËnÑö3Lž»Æïÿëßçd¦Ãöòvü9¾õÎwxñÂ4‡î³ºßÇÅ÷3ŒLŸå¥×np¶Ôeåñ}¶v¶x¼¾Kë(2ß©ípûæ#Ú^€ï…L_¸Êž©' IDATKWÏ“kU8<¬“u›ìV»¸™ÃcÓ\85Œ‡ƒëúd2>ÞÑþûA@®P çTØ«EøÙc“³œ›+Э²ººF­ytÆšîrŸ<|PâJÒó.Z•j›\ÆÃñšû6×–8¨wŽlFƒåûKø³§9$ä†çyó[—ñc(BܸK”@û`…‡ëíÏl†žÑL@àà8$ 8^žéKç"ahê<¿ÿ¿|é¬G‚ƒë@¦4Ç7_f:_åÎÑ{ëïþñ6V…Õµõ£ýìÐiòàö:åsg)' ã§.óÎ÷¾Ï /ž#'L™oïE×Ãs]×%ð†&¸òêUÆ‚˜¥•ž=ÚØÆ›»Áï¼yÑRHà½îô ®KX(3=3ÇÌXîke3HlùŒ2ª4G™õl±e<¼À[À¯S¹—¿š‹úÈI7ÇT¤Zs´™}¯í\¯? ÈÙÆŸ–‹#n‹m4hÍr[~…%ÃÛÏ+zn×Vª]éò'eg¬f>ëh*ã`yº«ê¦h|ÚY•£cÉæZ;e¯ä{…3î2ïßÝ"Ž×Á‰[Ôê5¢Nçÿ8½2Àu<üL@BBÇ@D·Ý3FQQ«TH S¼ðò4çZûÜùÅûl­¯Ð8¹I—àÄe^»4Š“€䉻[Ä$$q„ã@ñÊèbH>‹É‹‹l¾LÖñqèº žÓ›ŸçûxžK ì¦rê…×q—VØÙÝæÖÒ-§Ä«/LýÆ“zeˆTßn#(VmHiöçÝçùF‡ÉÄÛT¶²²´j4öjø…!èvèf'¸øÒ8g.V¸ÿþû,­2öñè€âæ†ÈfcÇ¡íÄ=›‘$¸A€ëB @¢ã1sþuâì2Û»;ܹ¹J5Ê󿵓©ëþæž•£X± h6›‹Å¾ì­Êt,Xå(¶/…lŒTÌž·ŠP° üX ðÛ(¸ÈâR|Ò|”i`¢ˆjµz¬TG€QÜ ÍIײ};¤Œe‰ÐŠrkÞr8Òü*96*óQ„_½–ä¯k+ªnbÊñ‘S ëÙ¾J“lcQEâåHH.ÙdËý²äz+¬·¥~ºX»ÿǸpGgÄ*—¥»¬ò–u ­ €•æ¶½qôîÓuð-ÏDÁl6K½^ïgQ´õzýX¦ÂòÆÄ%±gÝògô¼hmÔ@Óòrl¹›œLIsÛ,æÛjµúŽm£Ñ P(ôŸ%3ôìê,ý –œ&I©«NsiµZ …>ßíY"V1PN«upt¶Â0¤ÑhôÿœÆz~l6°ïÌX¯Zþ¹QZÇ¡<õWOnòáÚ=Þ«o“íî³Y+qñ•óŒg÷ø¯ó”†(ø]¶›1ùñ9Æ +ï½Ç¾³Çµ?þÆBŸ$Žq]by˜©éi¶î-±¸ä2â6Øj ñÊ¥F?dëþÇ„c ûQ„ÇðÔ,“ccÿÞ<7ÁííiÖï.qoÉaÄ­³Yâå«'ðèqJ2™ ¹lÏ©â8]*ûµÞ“-1ê a6èϧ”¢œƒõµG|x3ËåO‘%Áq<2É6?þûOñ††È»¶Ú ¥ÉyNÍÏpxŒÅÕÜ/t(Ƭ·çùÖõ2ålÂæÒ"Ÿ&.§æ†(åbÖÝÁkža²”!‰zg5ú8qŽG.â&1àS<1Åhq‘GïóA³DµZ'¡Œ“tÙÙX¦çŸ¥¾·Žãy8®ûµ)9’ÁRô(Mžü"e&Ï…Òä‹\;µÎû+y÷{’C6ªyÎ^¾Àt©Âû›ŸJü˜½z‡ìÈŸõ›7ù››ë\þãÿÙS'YþàßjÖÖhÏqb¨{à±µö·æ°¾ç1væ$çÏs¸ô„ÕÕEfgȶvX.ðêB†8é•\>ĉÇÇ©.±¸^gxh„¤Y£YOòEFFÆÈÝȃ 7hà¸ñÁïÄŒŽŽÒ9<äÐs(O2=5ÉÞ£G,.Å Qa½1ÁíF&|œ?ú%KÍCë]ÊçÞá[gÇx°7Ëʧ+,.yŒú-¶k9._™ÃOb Èä²!ž“à81ÕÞÍp3EFó£„÷Ÿ°x¿€»»E›Žç“Ïõl†ãû‹C”óKÛK|øa‰Ë—O‘w8²»üäG7ûï­FD~ì$§f§hž8Áþ“GÜ+ígsŠ7_9²?ø4Èpúdφl--r+‚ÙÑÞ÷âúä2>Ä1à’Ëú¸qL’x'&+—X~üïw†hTIÈâ°¿õ„Ãn–±‰Qê{«8®‡ã¹$_“žÖŠÖ XZþ‹"­VDD‘t9%[Rf,AX$eEý\ÿo4ÇJݤ¨$GÊ‚{«H(Ð$`iKÙ¬H€æ¯ìŠå Ù¹êèlÖEY*Ëû±NŒ%i7>è”ó#€® Îg$ïXæÁR l$ÝFÊmßPX›]±¥JrtäÜØ2-«ÖU*•úÀY΃U)ó §Fï˜L&Ó亖åEÅqL­Vcxxø(—C%ç@d|Û}ÞžMý޽?[ne¥µå@è[çDënK°l¦Mûj&ÇMçNgÊ MØw±U ³Ž ÝW;}^çNÙe{ìüÓÏŸÍ~ʹF?Ó³g+<4¨Õjý½·\‹/콦KÞ½óoþÍÿ}ñâÅc5•ºèóJG\7`âä“åa6¤0<ÍÅ—^æÊù/`¸\ ŸÍ’- 1}ò<¯Ü¸ÌÛ‹DFN0wjž²ŸæËLÍÏs]†Ç'ÎB’àfŠLŸœgzæóã9<×%76Ëìè(ÓÓLNO131ÌP!Äõ²ŒÏ]äÍW/wÁó²…ffOú.å‘QŠ^D+)2fšáá)¦&FÜäK |Ó†çyܼy“«W¯~næÊ÷<|×£<>Æp©ÄÐØç.¿Ê[׿¡1<6Áøpx´Ÿ%fN-03QÂÇexj–‰‘ùá1FÞüéøÜ4#ÃãÌÌ-pzz˜\.Càç™:}†‰áfæ¦(fÜ Ôûs.ÏèHŽL‚[àÄÌ(>½¬›ŸÉ36R"Ÿ ɇ™9u—_{‘¢ç1~bœ¡bð²Ãœ:s’É‘F†²dü xEææÊ‘ñœ`ˆù“£„A‘™¹ÊyÇÍ3=?ËX9‹“xŒNÏ02:L6jÐu]ß%jÔ¨…óÜxyL·A«Ý7ËäÙ¸tþ$¢ßøóç8»»»ÌÌÌôOºI–"_Ôp×uÆO.05”'̆䇧¸pùW_8Ièú=›‘Ë’-”™š;Çõ7^bÈí½äóCcÌ-œbzl‚‰‘žãS›çÚË/1^ô©¬³¼tÀôéóœ)36sš«¯\¡昞¥˜ ‡ 0Îéó L–3x~‘ÙùiJ9× ™œ›g|8KÜjÅÙ‘)^xíUf‹>Ù\r)Äw³œ8}žÉ¡!¦æfʺ´›mâÄ¥8y’+¯½ÂDÎgtlŒ‘ÒÑÙËÌ>Åx9ûT/“ß&›ññÇsåÊ•Ï=Ó¾çâ»>å‘Q†Ë%†F§8óâu¾õò)œnDydœ‰á,N’àú&Ožbvr˜‡¡ÉYNŒ ‘e4ëƒã2:5Éèè8Ó³§833B>Ÿ!ðrLž>ljáa¦ç¦)….®W`fnšR¾ÀèHž0Èâx9&¦Æ œ^¾× óŒ”ÎàS'ÏñÊë—){.£ã ÃÞ¼Â!æNŸdrl”Ñá,™ Äñ ÌžšçÄpŽÀÏàeæçÇ ýÓó3 }7ËÔÜ<ãÃ9œÄetz†Ñ±²Q“®ã¸.q»NÕŸáÆ+gÈÆ-Z­‰2qú"/\:CÖéþÆsf\×eww—ñññ¾£!0hm‡å°Øæ‚–×r¬Ã÷Q¤YÔ–:Ù°NªÙ¡í&nÕMé¶åJ”¦ù/¶ü^@RϲW¶÷̳ʺ,˜”µ}f,gÙªpY‰Ùdk—mw›!IGëӾϖ¹ÙîìZ_9*7’b¥´º›U€³ݵ¯ÊpY `Ý—JšÒ¥ÎÏj%’¾n?lÀ°ö^N’H+)Z°n÷×ÊMkΨ[¾œë”[¼mÅ*,?(-  ,Ÿ}ë{u–ì=ØR?]× -ÏÅ:ö³öZVùO-ÛGÆ´'¶_’ýÏ®kqϬ š~ß®w:SpçΜ?û³?K~øÃö=×(ŠØÚÚêwßý"â„oêç“$!êv‰L]cÚÃq|Ÿ$‰‰¢#7Ièt»$ =¾‹®'£vœ]÷¨öÙn§÷=Vj0Žz*gIAà‘$Rq¿ÿûEñSÆr0>ËÒýùŸÿ9ú§zŒ ÷¼—ôêÔ{hLÔˆâø9û“8à».Ý(::¾÷Y¿™$‰éFG²ýšbˆ¢Þï{ž‹½½>Šö:ŽCÔííÿgÝ„?;ƒ"ëõ~Ç÷ý^-»‘ïý,âÐSßÒü{q]’„náz.î‘\´ãºx®K»Ó`ùÝŸðîã=â$ÆÉŸàµï|‡ c!­VÏ;ŠBŠ8ýæ—¹®Ëââ"W¯^í—.Ø(’^žûûûDQD±Xüœžw´ßi›áíw¿V9Šè›Ñ_{SÏÄ1­v—æþ§üÇ¿ú€…oÿo_‚n‡(:’½¥W¾óÑ5"Š<Ï}z?££:ô¾‘úçÎ÷?{±ãôJ•t.ú/…£}cõ”pûóìšRƒßF›ññüÛûoû`âsm†'½wAo“„Ôù8²GŽP·Ûûœ>ó2ˆé<ÃfÄQÏ–ôöþóÿålÆgg°÷ýOï§Î–®›ucqдJJ–"pjy¶/ŠÊ–ð,0ð´œÛÇÊü*ë”æ³XBx ”Úl‹-³ ÙªBÙŒŠ$˜mÞêv»ÝWÚ’ýµ½Ql¦@øÑªUiU:f³RµSÉQZŒ@{Ud³ÙþÿÓåZÚ/ñ,Z­VÛìŠåY1{ß¶\+-em÷5Š¢¾ƒ=%·J¥r,¢{´ê}*³ÒÊ:OV!ÍfÛlÉ•öMÂZÛ^û_íX–£w¶ÖÃf=¬¬¶íå¤}±ëxêê¼Û ¦I“ÛÀ±Í3¥RéXýß7©kõ`p,ò¬?ÆÛËϯûYxžL©}aþÏ>/*+Ø®ÍøZ­]Ñú-²¶,Çr,,‰Úf $ è½€aÇ}’½ëºý)âoøYoUÊ$j¤k € T PŠloå Å]Q=¿œ[²dy8âx¤³OVùÊ–éè!P&þ޾Ï:D"W[µ®4‡A÷gyÏÖ)±œ9*í³ŸÓ}[®‡æaeŽmÉmJªß·äîl6K.—ë;ÊRhÞÚï(ŠúÙ0«Ú¦ò*9 ¶„K <Ý4Yk¤ûµŽ¨ ( 4›Í§zýhn¶©§Þurr­ XÚÉô±8cºÇn·K¥R!‚~†É -è?ëœI Os×ZëüÉ©±¥YšW†}A ëPÙr@{†´Fƒ\.wŒC£ÒAí¡uºÒeŠ6 ¨3m!ô=²yV‚[×±¢öÙ²gùXª6¥6ƒ1¿>°Këæ݇}é[F[‹ü›°î¿­e\ƒ1°_·Ñl6i4}‚¶€-›ÑÏ,@´ Æ:rl™k£Ñ8Ʊ},l‡p+nÐ'ðlU½š%ély-–Sc)• DZ aE{_énîéóÐh4ú\D+ïlKø-¿H&ËÕ±JR¶‡‹öÇÊD++d98DÚò/+“+pª,„öØ‚äz½ÞwTâ¤kÔëõ>h—Shy>¶Ad³Ù<&G,Üj£ý€k~­Vë8¶êkú]ë§…!t¦õûÊìY§FN†ø]ÖÙQÖM?OŸéV«ÕúöœÈé´ A%5my'¶çοJ+s¹\ÿ¼Øl§uªmCZ9SVÌ8æèjlY™UY³Žd»ÝîÛ›²Ï§Ö^¦4îгgË%Ÿrfltõy 3c0ã›9Õ±QÛsfà@ Æ` †–ó!›¡lˆÄV XY“geÄ P “Àžœ;•¾¨TÞðŒ,aèg^ÓÍ urdïlÉNºÿ‰Í”(ò/ hí¥miµ>¯lŽJnlçw @ëõzß­×ëOñe·Y¬ä°Ë™³œ'Ý«Ànš÷a. âµ·Êà(ãb%©m‰ uˆÞõŸ#ÐÚ* ¹Øôú»å[Š®û±%jög³igT÷b¼ä˜  Ûr2ý®ö¤Ùlöµ´â—xË#²ê^ ~Hj\މuxäÌÙ²DëTÛ~7úN•…¥»ÿvM­<´-ÔžZ‘ «š¬}UO }¿Í’$ég•¬Â íëôܦ™ª!u²Åƒ1ƒa†Ê5¬ö}Zvq0c0Ãb «nd›Ê!°ÊS¶dH`EädK¶i•YY.ƒm&(bx©T:&ü£ïNGÀÓääJ¥r,ƒ ì€²%â`Y.­VIàÝö¬i·ÛÔëõc A-ˆVtZÜÍW몲!õGSND£ÑèÏ+›Í#òÛ(¸2P6K`×RÙŸ´ª–€ªUVÓ5miœÖTë–Ïçû÷!°o- Pçóù¾S§l’@¯J¡,§B“2h×ïÊÁÐý[§ÛÊpÛf—*õ“ü´-›’SgÉé–ÓaåÀí|uïš§„!´~¶´QóU†SŽU•³gÏfÿ€§2>ûûûýž0ú¹uˆìõ,wK™?9¤–Ó§ λJC­P‚®¯5Ó¿g³Ùþ½ˆ#–Ëåúë¯ûPÖò© €þ`•8Ò̓ìH’„N»C'ŠÈ…\Ï%ŽšÍŽë Ã_«‡ËgZñ ú20¿ÆÐáétº$IϘ„™ ˜ÔYõÔe‚ è©â Ù¯µÎN§§ê£¾#A¯‘e³Ù’c²™®ëôÏIöè€7›m|ß# 3ðÝ­{Q¥QÔýLÊÑsIìÝW=¬<¢ ˆ%Φk‹ŸuN:݈l˜Á÷\¢¸÷ÂÃù—ÚŒI†œ¯Èft»]ÚIÜSÈêEƒcçUö«Û•ÔdpÝA–û™ëÜíömF8$4ZmH¬ÍðHÑm²Ù°ÿ®ñ|ì—´½—fïE˜ÍlÆÿ¨a#ŠâZd3½˜6Òo?“ÏçûÑy+ɪëÚ̌쑆œ›% WéÊcdÃÄŸ°e@V)KËIQ¦ÀÊݦ%g-ø²JM6â®ûTäZσÖGÊ)ºoûòH+û`¥m™œå°HUNÀ[€\N_¡P诣²¶7‹æi³é l€8öbÉ÷jF)áí©í+pxxØ__Ë —Cëh³T¶ìÉfQ´gZggeG¬“`;ÒËy³YB]S$vË-±¼&ý´Jš¾OY"˱ÒgU®iKÿt–­pöKk¡ @†ý=·(í¥žë”Ê)Ѻ¥¹³º®Î½•X·0eåD«á«T 3c³0âá)+Ú/ L§…åùêÐ=ý2‚nÔdéã›ì‘åܵWv:T«»l..Ò;Å‹gNâ=³Q›lIº}Pë·îRõ§¹ñú9¼v§'Ùjô©Óײ¿oSQݨÃö“»<ÙÜ'&ÃìÅËœ>Q¦ÕjS;Üaku‰Íƒ&™â.^è÷€ Žç­‰À[­^£±»ÎêÆµvL®4Îì™8Xâñ£ ºN¸ä†&8sz§³ÍÃON-púô õ½'Ü¿¿ÍøéKœ™#15Îöìô£( K‹wØmtð½2/¼õ£nD<غ¯ô,ÈÙ.ÐViEDÍçÛŒ6+·n²Ýñ8óòëŒ{]ªÕ}¶ïR+ÏòÂ…³„te›ÑmWxxûœàÆð;bÉúUlFuÙ]^äñÆQ0uöggFév;l/±ôdZ;"“/³pî3c¥~7ö8Nèvë,ݾÅúa \Òè —.Ÿ¥à@ò 9'Ï{oX§ÖÚŒj+"[eöÌi¼ê*¬Òq\²¥QNŸ9‹íòðÓxcsœ;ŠæÁ2‹‹› Ížç™I’nçómF³Æòâm¶km<·Ä¥·n0î lÆW}$ÕkÿMÑm p-9ÙFØåè ¬ëyVLDËQ'Ý»E€Ùf‚Ò²€YYf9;6:lûר>0ëzâUÈY±Ýå­Ä°œ9*V^ZrÆúwÛ^}+7œî&/Rºæ`³4Ê\¤{àÈÙ‘ –•óÕ}Øß·ï+ÆbËÿ|¸õ±N—•"¶ýF´r"䌦7[Á˳°?I½'´ç’à–ÊœìI>Ÿ*‹gw«V«ÕߣãA]÷^™]ß:6ã§}·JxÖ©±6Ï:’öY³Òàö¬¤•ÆÒN¯Î´-…´‚6›jÅ(ôœYתÜIAY/[V©Ïhï­ÚÅÍf³÷Ï2BÝÏÑuðƒ<…°Áã'ËÒÑïõÈçs%TªU*•*•J…V«Irdˆ+T*+ªÕ*N›$éu|­T«$qL˜ñˆkušQÄÎÊ*íÇqi·ê¬?¾Í­ûûÆÇimÜág/ÒˆœA¹Ì¯©Oh¶š<¹Å{ßfi³Eadˆhï÷ö!iרZÛ¤›)‘õ;¬Üù„÷î-Ñî¶Ø]_gs¯^º56Ö6ØÞoPo¶¨T«ÔjµÞCœÄ}õf«…ë@˜qh7šÔö÷Y^Þ¤äpÿùÁøòÃ*©ØL®È•Ÿg3‚ K!l±´´ÌÃ't㘸±Îý¥-j —N»g3ªÕ*­V“ŽlÆá!ÕjÕØŒj¿$Ã!!Š<ß#—Ïá$ ÕZÃÞ]h6{6£ÓéômF¥R¡R­öj©“˜Z­Îa¥zÅóHušQÌîê{õ.žày.íê.Õ(K¹°ûø>¿¼y—ÃŽ{¬Î9:t;ù¡!¼v…GwÞãç‹ÑHV IDAT-‚О£÷K³Õä`ù.ï|‹ÇkuòÃÃ$KÜÛKHºu¶×6iûyrA—µÅÛ¼wûn›½ 6¶+$~Ý:›këlíÕ©·ZT«5jµZï¥Ö·UÍæ‘ÍpéÔÔYYÚ ôš0ÆW;lßtôØòhš,±Z‘_$/|›¹Rô^eI ¸)šÍf©×ëý늠mùw"g[‚¹@²@š%>‹óÒl6ûÜ8 t-È:*²¡¶¬«^¯÷UÞ:Nÿ¾lÇJEÛõ²N‚=‘Ñ¥.&¸U’²ó’‚ʉ\-ø¶%NV(áYå~¬ÛïK«˜Y‰m9dʲȱಒÓâËØ2/ío½^ï_KŸ±’ì…B¡ßkÈ*ॳ[¶™h?ª«½íQcKŬT¶=K¶„Ló¶ÊbÚw+7® ²%Ö!Õ=[^’-Õ³ Ym&MÏY£Ñè;_ö3š»uä5 nléY³Ù<æ` …cj…é’:­‰œJ+’ƾ|ÊÓù¢¾®ëRš;ÃèÝwÙÝxÄÁèI*«k´ÂÅ‘!–>åÖ½%ªí/;Ì¥W^¦Ô¸ÏOö„áej‡‡dçOãobñîC¶Ž—åܵ×8?=ÄáÆ-~þþ:ãSeww‰r'xýí· "ÿîox.ð»?øs×Þ ·q÷Öwq<Ï÷q‰©Wöè_âôüI6OxÿÑ&Õë yßdg¾<4!j°´¾E³3¿úwÂBÐ¥Gìòø.$±ÇøÉ3ÌfZµ`q¯Iwºwx×ÁõÜ>؇Vm‹{ï½ÇêAÇs(œ|ß½>Mko™ÿÓGLÿàOxsj‚K¯ÝÀÿå?s§áànÇßW:l¤%Ý9ŸÏ÷£#ϵŽKiö4ã··Ø_{ÀÞÔyj«k4ü™‰qªË·¹u÷1‡í7SæÂµ—žðÏÿtŸâĭꙹ3„›Øm&8~Àä‹ßãÚT—õ5Vº> ç'¨o=áÁÝûlÔ»8NÈé+×¹8?Fmç.?ûùÃSÃÔ÷÷h#¼ööw˜ÊÇ<ø»¿a1™â{øf®Ü »õ€÷6¶q<×ó‚S—ÞäÔ °°O©µÅ/÷:$¸8޲E %^ºÌáîÝ}¶š ñ—6ƒ†3Q«ÂêÆµf™ßûwÿçÈvQ98äÉýžÍ=Í©RB¶þ#ní7étó88®klF8´ë;,¾÷.Ë{mÏ!?{ï¿6O§ºÎ?ý§_2úÝ?æíùQÎßxÿƒŸñiµƒø¸‘ ÑÀh|•ÃFÆ(„Õ\O‘r•‰,@ªÞ3jög›ÚH³ ›­±™áOwX¸SóA›Ý³R¼š«u†lÙ™•õYl+ý¬¹ 06 ÊårÿwÓó´Í2EÄW´Z@_åX–Ho¹úŒþÝJ[«ôJóÓÚʾk?äDÚþ/*ó±óОY0› °·Ñv›Uª×ëý̇U)Óµä`h®*G²Î²íñcK³²Ùì1Áceœ”ùh4ý²;Ý“u:ì½Xž–tŽäxÚR.9”Ê8Ú{µ\ëÀY1‰t••.¶™ie(Åq²¦Ä ¬3˜®ÆÒ3iÚj½ïÕ@SŸÑy+•JÇ•RjÎ6#dºeÇlFÇ6Õw?SÍ̦q¿HfÕu “Ÿb~*`w{‹Êþ:Ë›-²…Œeö¸}çJÌÌMv·x÷݇t<߉qFxó;ßcžU6;9æÏ^äÊ¥sÌ„8¨©C·yÀãû‹l1Ãß~‡S£ Ÿ¾û û]§×)܉ÈL^àêK ¸•]66öÉÊL:Ëù…9ò"9½îÑIãÙ\ѱQœýÇܺs›ÕÍNÜ¢sŒ8Ÿ_2Ò;4ÚÝ6ñÐ)&ƒ‡*‡½¨wB‚ëÅl>¼ÃƒÅ;¬ì'ŒLŒ’Íx½’‘ñŽ.ïxAk“¥Ý&ÅÙ³\yñçg‡ÉfBÊ#㜹xÙá|ÿA‹â#Ç vì«VÁÆ@lèó†ã€Ÿ;ÁütÈáþ{Ûë¬l5²“L*ܽû€ý¸Àôì4ùd—Þ{@Ëq \pÊ3¼þíïsÆ[c­0{ö"W^8Çɱ,Žãöc×%jUY~x—µî ^ûÛœ9áqçƒOØiö²²ž›ŒŸá¥«§É4X[Ù&S(3yê çÏž¤˜QÊ¿×Ù=Ib8zÑÔ vv¶9\¿ÏãÍ.'Ïb¤˜9.í€O“å;·¹¿¶Oœ›`¦Ñ7LêþóÊ̈#Úí&Qù$3™û‡‡T+´Žl†ãÅl?¹Çƒ{wx²34>B>ôÛ )×#èì²¼['7}†+/^âÂÜù0¤<4Æé ˜-ö¸’Ýî‘ï’GùîÿCÀWÀM„êt·{Ë9Q×qÙÛå^ŽŒUj²ÒÄÉ–¡ˆ¶l˜íQ’–Y¶ÒØVyÊö‚9žŽÀ—•›¶}Näˆär¹c%h*A’c#2½X[i`]WóWv\rÊV~×r?lWwë({%À®ìV­V;Ö4Ñ®‡ú•Ø •œGeDúV9©ö°P(ëk#nöNïtÛsFŽ‚unl‰T§ÓésnxU’eKÜ,)½¶¦öLNk©Têgvl¦ÈJV˱²Úš›årÈÑÔç­Sa9*…Ô³b®ê¼Yq 9q¶äÒrgl†Æ>CÏ’¦–3þ,^gTs×\m#Uq‡äŒØÀ‚í¹deªm9\»ÝîgKu¦ÓÌwÙ¤‘x$ÄN‘Ù™) Í&!OH’.FDùÜN–Š´[Uê†(•¢áúL.\ãõÒ&»‡]Še6›!ùL@’t¿ÀÁÈóÖ#“ÍøÜê2×O17ñ‚ IÜ#A“$x™by”ÉÓW™™ž¤}ø—„v«FµRÅM:D¸¸ŽGf쯼³º½ÃƒMÜ|Ìääb¯È¥ë×Ée*µ:£yœ„n«Þ IâW}d,mÃ4+Çik?×fœ:Mvé.ëïqÐêP¾ú#¬Ñ‰»¥1ÆG ŒŒqÎ/â9›$N†¹“g˜ž*‘w¯q9zÌÎÎ*Û+]†«yJ Jâ{ÝVd’±Ržd|œÜÃe‰CHœSSS”œ„,HâF—â™ËÌ—ŠtZ5›Mâ¤G»â¸WQ«°õäoRºðߺ| §Ý`ÿà×sÉf2´:]œ$ÇùW_gng‘_~ô€Ÿ¿·ÌÜ÷OAÒþ­vº-ÏîsmF˜%È„¸û+Ü_?ÃXÒ ’8:rXÀËd(•8qòE¦g¦‰jOpV§Nå°B&îŽë“Yà囬líñàA'ÛáÄT™„,ç_¹N>t©Ôê´;Ý>¿©ÛjA0°_õY°ÑdQµ -m)@uiédË ° ÈòÂ0ì—Ù’yËKÆ*"Ùž7¶S½/9g0Úhº•EI\ _€×ò„¬Ì­%ŸÅ*S¥9º_+¢n”©ëZ~…ì¸öBs·ÎŽ€¥>«=²%ÆrZ¤¨fA­ÖJ S%YeGl‰˜•C¶RÅ–«!'ÁžÛ0Sέ£2QéŠ#9FÏââØ’j훜C›a³N€-…³êd*wT&L¤vqÊtFí™OK"ës¶ï‹í­c³ƒº–íÛ¤¬”%ì[¡ëÔÛ’H­ƒ-‘TpB¼µt ¥uÀT¦fï/í [‡Ö;¾,îx*3£‡éË6ír]—Âð,SC›Ûâdœ—^œ¤4c§O2šÏ ^n¿Âp]—ÜÐ .ΟÀ‹7ùÙßýß¾Ã{ÿð·ül­K. ˆ#¹^áÆõ—9jмŸäF™wÙßZåî§s÷Î*Q& tb §¶Ín'dv~žÉ’ÏÁúuÇ£±ó˜ÿúïÿ’Ÿ.Òm7Ø[[å°ÙÅqÚ,/Þac¯1P£ûЇ€€Œ¢¢¥ú¿ Ûç–¸¹ò,³£ Û»ÚÝQ®]™¢X¦œËÑÝÛ¥é„Ñ!O6Zd3GÏy’ÐétilÑÊŒ°pzŽrÜ`{c2Y<ÙŒòÃ#£D«·ødñ!ë+ËÔ‡¦9QÌ’ÉxG6Ã!¼#ëámþä¿ðïÿÓYoÆÔwÖØÚÚ£í8T¶–Y|¸F;Ž9ÜxȽ‡«´‹“”ã=nݺÇ^­MÔÞã—ÿßßðÓÛ«´ïóÓ_|Ìã¥%–—wzêm££d<çs>?wèº=Rÿùù²Î?ÿ»à£Ûwxÿ'ÿ^n‘ }’ØeúÜU^{õ.œž¡$ÙNŽ{Tö7¹ûÉMîÜ^¡ëy”¦fñê;ì¶¦çæ™ 9ÜØ †Gë`•ÿþWÉ?>Ü¥Ûi²¿¶ÌA½ƒã¶Y]¼ÃêNm`3¾â!€jÚÒgt˱ I–䮨´¶¬JYÛ[Å6È’º”%›{žG.—#—Ëõ¿Sˆ€x>ÿYe€-…‘m”r˜J•li”•Í(غ®# '>ŠîM÷¯{³™‡t)žåg躶LØfÜí~ésaR,û¶^œ‡|>ì¾ä¤‰þÖQÔÞÚþ4VvW×¶gBŽ€85}õC£z¦ïÓ\´?ÊØžBö÷m «L¦µSƒGÍ_'ëõzàku.åÀj.ò鯔Zo½;­$¶íu$±+¬ GÇì%{­{Õgs¹\ß1¶Žªœ\•ÄY–7ÔÄÔ:–“eûÛ¤ËE­t·U2ÔA&C!P½ÿ„íÕotWßxƒ©âKCC4a~„ë7Þ ûñ',­¬âçOñƒoß`<ŸÁbh¨E>›e8¢wá$ÊÄâ= ˆ4çžóšý®½÷ÚkwÃÔÜâZ[_ýÁ_¨ú꫺xó¦ÍGôÒ˯è¥/õ5¾ÒVmø¡Þ»:•ê}í'?Ôã݆nmÓÖV_ý~_ÝÖ®—?Ö¨ÚÖñÒ÷ßU«¶­žV÷(Bß\¿ÊîÂŽÚŒF# ‡Ãû hT*u»[zâé/ëö›—´zôÛz¢½ÔhvJßûþ÷ôú¯ÞÔÇï¾¥Z££GžzV§O4µ}ì˜Ú­ªJ¯ÛÔø½‹zûÒRÕcçõÊw¿¯³ý=]ÚÞÖî´§V{K/¼ò]5Z¯éÃKŸ¨Ö:§ÿðÓïèÑcmíkûؾz¶Ž÷·µ}lKí^Gý^_ǶúÚZØŒñ;WtùêPíÒð¦Þúu[ýÇ—Õï6Õ;vBªuåò@óú\gÎ?©ãÛ[:Öï«¶uLÇOvu¼~UW>½£U­¥/½ü—úÞ7Ok6llÆ™g¿¥¿<¶£_½û¡n]»®fï=sþ´vmoS·Y×l6?vY©^méË?ø U^}U^¿©iý¤¾ö½oê›_ÝÒäZKµÑ ½åS©ÖÖ³?þ¡žè5µ{옎mõÕßê«×jtåcí¯Z:¾ÓÐÍßUmÕשÓÇ´Íbsýþ^ÓT#ët:Eý€£ÊvL,!ÌË{·˜—o°lùx߃Q{KÁ²0Ü·ŸÅÑmJAS!*.GÑ™±0è¥ E Ê €S¾™âTõ2e‡Åó¬ sQ­Vµ»»«^¯WDÖÙüQofÐ\ømg’²À–Ì ù÷˜ÅñßT£2ædý’Çïç±2À7P¶³å¬‚ëhò3Rát,ÓýØ,•"®—ñs¹@Eî<™%âØb6„sǾ+vTH dÆi0¬ÑÌ(Á¬¥ŸÍŸå³ÚãÀŒ¥?“cäy¡Œ:ËP¸¦Ëê¼HÝ,S¥ÓH§”Ι–ãË ¨%‹æ¼?ÿùÏW?ûÙÏÖx€W¯^-¼¡û]õzSNKµÊJƒÑº@¥ZS»ÝR³Ñ´Òb6Ódv ¤ÕJãÉTËUEívSz]l Ét®Z½®v³¦ñxªÙâ D³ÑP¥"ͦSM¦3­Vu:M­–KM¦s5š Õ«•ƒ~µšÚͺ&“©ªªÓúLƒ\«…F£ÉÚ}WËÃÈÇt®år±Q4;ŒDýýßÿ½þîïþîš"Öê µ[-Õë5I+Í&M+µZ U–K&S¤eWªTjjµ[›]Òr1×h<Ñb±R³ÙP³ÙPµRÑr1×x2Õ|¹R§ÓVe¹Ðx6W½ÞP«ùYAÚ|6=üýÅAüÉ| —^z©0ÔÔï÷uãÆ M&õz½ûghê u:mÕ«+ ‡Mg3U*Uµ;íì«´˜Ï4™.ÕhÖT)l†ÔnµÔhÔU9œ÷ñt~Ðs¤Y×d2Ót~`´[Í›1ŸÍŠßívZ‡ög¦z³¡f­¢Ñx*Ukê4y櫊ÚÍÏøçZ-5µXJíNSõš¥f—šN&šLçj¶šjT+ÏR«©Ù<ìò½\h<™®u²þS¶ÿðÿ ¿ýÛ¿-@êým†»G¯4›N5-lÆê3›qp(KªTÕjµçõÐ6Œ'š§ÍXÎ5žô¾j·Ûªi¥Ñtvx®4о?‹ùLÃÑxc3þ€6ã¹çž+ö‘š£ÖÙðŽ * ¨ ¤,JDçõ 4ÉŽ(“²ÃâtGÚ Â þ P§ƒALjŽÊP;êm ÍûSõ‹ÀÚ_gá9 Òì ±“½ÁeÊLû]IÝò¸1ð”5ĶûlêHFÇœ´;:€©>Æ^-®ñú`¡?;ÙgfÌYÖI±GŠÅiü=ÊU³”N»úÙ)ü` îç¤ÓÅñ¢³Ææ¯”|&u1eÆé8Øù¡#äûúÙLçósrî=wÞ²Çýë5ý|?Ò4©8Ç6‡å;2KfÇØû“A«äQ6š¢Çs±Xè¿øÅg™* Pïý~×l6Ñ|>]K)®s s*ÙTNk;Î5½&f¦éä3™ÁÑp®qÜG’ö÷g˜LÇùL³égŸ±?›ÜõÌ«ÕJÃù¬x¾é‘ðEº´f¦Ø´³©ögÓµEvÐ\u²6ߟý½Ðh8ÔÅžþÞx<×d2¾ëëƒýýÏæ{6Ód\ù\ϸ¹~·µ@ž³ ‹¿Ç^2óÙTû‡uO\ÃÁà¾6c8œßµÎÒfŒGóµõñ™Í˜¯ÙŒIqß™æÓÏ~0›–Žƒí\~Ý6ê³5\ù­Ëߛ͘MîbqKGÃÒy=Êf  om3¦¡¸·±ص`)dƒUf:X¸l*Õ \S@)Y1ÑÞØaa¤×ÿ¼£øvª¨dƾ1¤Ìø~“ÉDý~-ÒÍŒ@vq÷߈Î"±[;ûŽØ9È>o3¿'ÁxY¿öao;$~;F”f¦Ì÷¥³å¯1ºoñ–éK®« ¢•ŸÑ牳Jþ?ƒAt×^ð~®»`†Ñ};”tJéP•ÕA´Ó dmŠ.ªr1Kcb¯g‹('îZ¤v»]dgÒsí¯f¥(Žáçr¿:nJi¥5gÛ<®tÂÝ´–}_ü|t¢IQôçûýu ¸¦=¦ü}×À13G žU ^¯·–¶ü<Æ«¼YÞÝBùÿGýÌQ?wÔaô Ÿq¯ÏÙ\¿û!v¯ù~Ÿÿ<óý B›ë÷sQmÄÆÌ}ö:øCÚŒ{ýÌïj3Dä=îgKî÷Ù›kc3¾H{‰t:5J‹ÈYa Èf€Ù‘}>Lo5è·z–1)9ìWAu*G” à—Ë¥öhÌp°± A×p8,z—رHu4*•Ù™ò:t†Á‘ffFܽ½Ìaʈ9)P†¬‹aÇz‚oKÝ:ÃâûxœF¡XÖl6ÕívU­V ´tü,f°Lÿë÷ûk=r¢I+3xfÓK:v Ûíö÷Ø. õûýbÜLQ¢ƒâñrf«Ûí®eý.lòè÷²í9±ãkÇÒ5"¤ãùLe ˆU͸FáL˜Zé¯Óif¦ÉRȾ¿÷žßÓ:ßÏë*v=ß>«çò¸¡A)UçØ\Õïíw¶ƒÃ, ÿ©\—¸ƒ} ¼‡}Õ™®ñ7T« À8yòäæÀß\Ÿ èöF£"éÀ‡ÁÈæúâÚŒÍØ\w9’J¤ÜPv™YKòNÄ”& ³—³þÞh4Z«`Ö!\G·Y<ÏzÀ,4¦ããzƒiÖ]D»þÇÏÉÚ™ì–Îh?› )†À¾^ŽÖ»¨›ÿvD~2™M0 †³…Né=VQë÷ûÅgeÃÇlpj Íg¦–Ái·Û]Ëlø³=^v$¨0–²ÇCƒthgPX×bÚa»Ý.(Î|%í'6+µÃáÏâú2•‘Y3Îïíí­9éì÷ãñ6­}\£Óq5ØwV”ý‹XGcGßN?3&܇¤fÓëËûÀ÷ðxÚùdЀÂÎî0ÓGÇueGá×#U3òê”ÎæPúâ^³ÙL?ýéO7àts­ËRR6Òïóff6ןžÍøÉO~²©AÙ\wÙ ;I¢ -M0’FÂh½A,›^Rº¹ÕjvÊ•ÝÞQvmM‚4ƒ.aÛ:G‡%ÅàvÂÆãqAó³ÚYàû±7›PS !¥ž;Nìè4tÌú¹™Õò³3úí‚NïÍ^$lôÓ‘aæÁ?ï9Íþ0~g«œ9»A9ê˜`sËn·[¬?;¦œ{6f4˜÷3±q(:k°ò÷üÜ^çì§ÃÚí3Ë`ÇÁ_gÊY"¯*sNüîÙ†kÂøÞ÷ðœÛ¡·“ïõ7™L4 zÅèÔRÙŒýaHÃ#]b ¬-£’•Â…ãGÃÃFRÁØ\_¬‹ê÷º’ß~Ô×þÿ¾Ê¢r÷ûÞ½~§ì=–±øm¢«l²å4=m)›ë‹ëÐ:ó°ÛŒ{=ׯfÜßfP+\òüSÊ ÎN‚£±Ù{…ª«¤ˆ‘Ûo€l°Dg*U¤ϊÕ)¥Liaþ·30½^¯pP8¤~ÑY ƒÅ.ðÞCÆÎNØép= t 0›Ã†”¶áì%þ;޳Fþ|^Î+M6 ¥Áþ"ž[fRØOÄgµ<.e½z,@à¹÷•­˜¡d3³Rl>Z©T4 Yn*ÞùÞÆJìÍÃl›~†ŸÇk†u@–àüYèëÔb¬Êq¦t·×£„Ú©µóOj¨?”:ö]¢B›ßÁÙ,4®ÖëÐéÉþMTz3îà|13»&ÀÙ&¶¹îwQÓjÜ Ñzo"G¶èSD}*«ÿJõrÿž#Tå N< ÷æÌ¥2mÈý®Žpm®ÍõymFµRÑl¾Ðb1ÿ£¶|®2›±:ì…´Z-76à–RîþCIeÓ˜\³A¥%RW'“IQËAî¼çˆÊJ¤)\šÏ ëuìÈ:2N ëšrS¿ˆŸLe"@å`ãEÊⲩ¥m­)t;jÝn·¨mpA9›qÚ)Çêõzk5 ,ê÷œ±×‹Ä¤UQ)‹Á, L&u»]ííí Ót7g\üœ>Sì¸zmø¾žø2§Ÿ™ƒÅbQ¼/›‰²žÃûŽb Ì’1Ë@6??3×6 àù>®_Y.—…ÚšŸ×6‚ãèì#¥‰)xÁ:¯5RÙüÞ~n¿·ŸÓõ3'öu±£cçÁµGìÑÃÚªÕy]ókÞ{|6Öÿ°¶Í5MvZ‰;ìDN!­_g”ÂÿÆ‘Ù\rM&#]»|YÓÅJýíGtúÔ–ƒ]ݺzM‹ZS'9«ã[ Ñ´ûE.3BG®óÝ*GŸEïußét¢ÝWu{¤Z½©GÏéDï@Êr8Ü×àÎmí¦j´»:}æŒÚõªFÃ]ݺqKãÙBõFSÛ'Ïèô‰¾t¸Oö÷wµwû–*õ¾}âœV“±®_¹¬ñl¡î±Gtæ‘c ötëÊUÍku8uV;Ç{ª<ÄWJ`´Ûmíîîn6Äæºï5Žuýòú>wuëʵÃ}ò¨v¶ûÒjù{³üݵ³ÙT»7®êÖÞPÕZS;gÎjg««ù|¦á`_ƒÝÛÚNToutú‘3ê4ëvuëÆM¦sÕêMmï<¢GN“#–ûû»Ú»uC«Z_>yN•éDׯ^Ñh2U»ZgÏžÐp¸¯[W®jV©éøÎ<¹õÐÚ ‚aªI9«apojk0Øœ@È`1£Ñæ‘Ýì ÃuÑív ú¬‹Üõ·ÓÄȱqk  °íxÑ!psA*Œ„Òy±SÅH?ƒ‡n(Éw¢¤®Æ ˆÇãqQ§`i`˜…è9޹/ IDATÐÛq4ðõ\º®Ãã: 48Tô=Ù Ñã°Z­´»»»Vnš”\SéœQð{º/ƒž?6v$•‰ªpvš˜A£L4³;>ïXƒã¹¦@/Òá(šC§ÊkǴƬóš&’NK¸öíXUrОsÖGI*eÓ$Iç"í’YgáXc”A!ïk¯;RtbèLS:Ý6º w˜Æ¸æÌ0e³Ø\½œêêoÞ×Å›»ªõÓ·ü]µö/ëׯÿZû‹º¾üR_/öZšŽÆªV+ªU«j6âMgsÕj-—R­VUEÒl±P£ÞP«Y×|¾Ðx:S¥"U+5£™ò޳âw¥•êõÆAŸ‘Ùü ëz«¡ét¦•*êuÚjµj\úHÜhÿæH_ùñi<ÖÕdO»—?Ò;ï|¨éÖŽªû7õÁôý—žRm~Uï¼õ±ZÇZÚ½zSÕãgôòŸýHgZSM§3 ¯¾§×ÞüHÃÉqýÅSOik²§ŸþFï_º!µÑw~ú#u‡Wõö¯_×iUçŸiëû§Oh5<”smãçÂ|V«Ûl®Íõ`6c¦ëŸ|¨.ßT¥}Fßþ?TwpUo¿ù†î̪züÙ¶¾y¬§ép¤j¥¢Zí`ïÏç M°ï×mF]­fC‹ÅAÛŒF£®z­®él~xø~f3jõº:ÍÆÍ˜-Ôn74›Î´PEýN[ÍfM£+ëÃë{Üèñïlëäñ-M{Ú½ö±Þ}ë}{'TÜÐûמӟ}ãY5–×õΛª¹ÝÑÞµ›RG_ÿþŸë|w¡Ét®ñôÚkhrL?ýòWt¼2Ôí+õÎGW´¨ïè;õm ¯ëÝ·ÞЭÉR<ùMýøì)i2~(çš5t4 *Ù»„`жžÔfw ˆüuöÓ •ÈÉÀŸÙ.~–83!þ,ÂT¢âópÚÑ`öˆt8ƒÅ²ÆŽ~~Ö4 û½Ù«Ãªhì½B?{ûÐy$•ÇóaLJΆ璵B¤œÑé£4uц]ÞéìÒ1ã:ðØ“Våñ²“ÀȽº,nf^˜!evÔóéÏfG{fY=–ü=þŽßÉN'™þY;vk’ hEÉÌõì¿)Í,™Ÿ“G®1;Mv¼üs^'ÜðZäx9ƒÆ (e¡Œ sÊú±ÇŒtKSÛ¼§|Ï2ÜÁwÓ’›ks=@¬^µjUÕZKõÙ-}rñšNì^Õ¤ÖQSKUUÑh4ÒÞ'oéí÷?ÕþTÚ:óe½ðüãºýÁ«zûã…=1×¥zâIõÆ×õ›k{:~î9=÷Ô-n|¨wÞýH7sµ¶Îèßù†¶«3}úÞ/õÎ'3;µÒÇ—vµRE§^ø®^x¤£›Ÿ¾¡×Þ]êëßùªv_ý]é=©ï}ï›:ÿâwÔºú¾^û—_«Ñõ¨F—ÞÐ{íº–i6¼¦;ÍÇôè±…>~û-]Óqí­tõ“÷tùò%½þ«wu}r\ϼðŒãõÿþã;šVëZ-š¯ézý ½üí—ôØ™®>}û¢v'cí]¾¤úÙGuîÑSê4ªªÕj4›RµªÊaŒünË…f£±ª½cêÔ+ªÖ;j,Ú®´ªÔ5 5ÞÔõëC5;ÇôÈ™®f“;úðÕ74{äy?Þ”VKͧ6ÞK-WÇtáB_»Ÿ¾¡÷®íëØ“çÔ[­´RE«•Úu@.®£TŽ@Q~ógc3î÷ýŠVZ®¶uáɾv?yCï]hûÂ9õ–KÍKMï|¨í Ûé¹§ÏivímýË/¯iU‘æÃëºÝ8£³ÇWºüÞ;º4íéÑ~E7.½£‹Ÿ^ѯß|[W†[zæÅçÕ™]Öù§·4©Ö¤åBóá ]¯žÓ˯|C?¶¥+ï~¬;ã±ö/¢ÊéS:wîŒºšªµºÍlÆêÀf6ïœ Gªt·Ô­UU­wÕXµ7Yh©š¦“‘ÆÃ›ºq} zkKžïk6¾£_}]ÃS_Ó…“MI Íg‡ô–ÕJËå–¾ta[ƒO_×{Wî¨ÿ„m†´Òû² ;™»fÂtR‚ P\¿»½½]îN§SDù æ ª?^8"Ž"·Ûíâw šÚívñl¤‘™ž´Z­´¿¿_Qfk ¶ÌfqdÞ4%;Cõz½°¤Ä–e¸H_£ 4U£èÀб¡úiNãñ¸P\sŠQt °ÏN޹Uã†ö÷÷‹þ%v\YDÑÓžÆãñšøƒ0RŽ˜É`Qü`0X«1÷çø¾vdL©¢p§Ó)Ö%³O~?‹US没$é[~'ÏeÉ݇¨Ùlª×ëcIÚ¡Á<3bÛÛÛ…S@E;K/;Óg‡‘½k2Ó4ŠlŽ3µZ­øš3”^ãx¯xMsÞ(DUÁ²¬Tîת÷#³T³ðس¡n‘á"„šà›ksÝïZIRe%­j:õÕçU¿uY·WgôåÓM-–RµVÕüÎmMk­¦ûº~{ª“=®3…«•ÕÓúÆË_ÓÙÓ[Rí¤žyöE=y®¯åb¥É]3u/|]O_x\gŽŸPíÖ§Ú«¶T­,5Óiýø'ßÑÓO=§§?¯Þäc}pùS]½ÓÐ…sçTYTtáGÿIýçßTw1Òl6÷kqØ}¾^¯«Z«j5›h0ðôUS­rpíÞ¼¤÷^ý¥.®Nê›?üs}©¿ÔüÚzïvMÝê]½¹'Õ'zÿÕ7µ·ª«Z‘V˪v¾ú¢zƒkº19¡ §ÛZ.WÅg?¬ ¸<›†m®Íõ¹lǪ¢¯¾ ÎàšnLwtáTûÀfT«šïíjZ­Hó®ßéÄ™ó:Ûk¾’Õ“úúK/èÜ™mUjÛzêéõ¥Çi¹¬hº»§ñl¢ö“/êé çõèÉ“jܾ¬ÝJK•ÊJsíè?þŽžyúY}åñ'´µøT^þD—oVuîìj,¥ó?ø_õüå÷tl9ÒôÐfTTÑrñ™Uµ^Õj>Ñþp(­ÒêÀf íݾ¢^{U¿™mé¥þ…žÙZjvã#½wKê5ötåÚ®Võ™>xõMÝYÕU©H«¥tâé¯ëøô¦®î÷ôÄéîa¼åá¶Ù7P&ˆbßJþÚ¡0@Lõ,N7ß3pôÏ“ºãl 3®w0öa±¿AŸ£ô.XvÞÍ" ÈIó³À“Æåg%˜¦ÊƒG¤/9ãÁö¬2Ø$¥™,Ò~ø T ó¿SõÍcjJGgµZi8jkk«˜3Òš|ϤÐÙi1€eA½×ŠÇ†Â,ÒgVÌëŠ5OþygÂü¼ÎÂX Â?CÑŽ){t|˜Ab}–çÀ÷ã»øÝY_âÏ£ˆƒï1 Çž5CÕjµX‡cfR<®žGסØae6ÎùsÌFQÖÚAϱ0L³ÌšߟŽ÷p8,îã=íý⨉;H;¥¯R§á±gµ¡™m®¹jÕŠª•ŠV••¶O}I/¼tE7úÏh»ñ±xéM8qRµ×¯ªÖ:¡ _9% ®êÊä˜ÚËËRµ®Êj)U*R­ªje%U¤•ªê8¡æåš¿¡÷;Ûº½wGÓ­§´ÓªjT©HµºVÓ©&Ó‰Z'NëôöûºøÁGjöNëѳ'5|¢ßüòß´Û=§¯>}A³[×´»;Ò²"í_¿¤+ªŽõ¶´sbGßû@ï~ÔTõÆM¶ÏêT»®ñµ«zï7ucÞÑ_>£ê‹ºR9£ÞÎ9=ÿlO³Å\·é©TU«×U«Dq·Ž?©_~^'ë_ÒN÷†þBìfÍâJ6Û\›ë~Wµz@­’VÚ:qA/~ãyn~Y;k’VªÖ:qzGõùǪ6¶õäWUexU—FÇÕ©ßЪRSeµÔªR‘*u3þOgû¸Æ×›ºùé›zoë¤nݹ­Iÿ í´ªºV­Jµ†V³©&«©['õȉž>üð#Õ›ÛzáÉG5_Òoþýèfó=ýüÓZܺ®;»CÍ+Òàæ]>ÖÒv¿«Ój¼ù‘Þ»ØUëÖe·Ni§ÛÖäΧzÿõ7tmÖÔù gÕØ¿¨O«gÔ;qVÏ=ÛÔt¾ÐîÓªRQ­VW­ZÑJ+u=®¯¿ò5m/Ïét_ü Ì5 þ]HlGƒÅÀæê›Ú’T!3êm h`ÌÆ–LŽz“úc`L•ªìÕÁ‚uÛñbÝiBY£âŸa MRÍŒ¹¨Že€—ÅÖ̱^ {Ö‚v¸¬tf§„QpŠaXf½±>Ó~¿¿Ö7„T@ÖoPÎsE@ÊZf"RÐc4cç,£þ¦îyž}^Ùa6èfQðSÁ­Ùlj<ëÈs×étÖDØÜÑãMZ×ëqX\Oê YþZ¯×Óp8\+¶÷x ú9Rnš’á~wËFû™)Öá=ÇŒ˜³#¬ý¡@EŽsf÷ì¨y^¹÷|:É\ÓĬcýÒZÍ =½Íµ¹îwµZM5k-Õ[=î[zL5M÷¯I‹¥T©ª÷ØKúÉ÷æúï¿|Gÿüo«Õ=¦'_|Zýñ±j´;ÚêÖ4_,Õl÷´Õ©j±X©uêiýù÷—ú§ÿú+ýÏûXíísú«ÿôí4gºÙªk¹< `ÌçsMM=ñøŽ>þÕ%õÎ<¯³[U MéÎu]›žÐ×¶úýÏ_éµKcU++Þù¥.ýf¨¿þ?¿§¯<ÿ’æÓÕ›¿úwUÚ;úþ¿­Óý¶îÜèæ±¹~óÖkú°ÒÔ…—þBß~úI½pêIU+K}ô«ÿªkWnë™ï¼¬Ó“›ºÕ¨i¹X©Ölëѯ¾¢Óªi1ÚWe±Ôò!÷h˜î§Qo·Ûk‘¡Íµ¹îi3šMµëU-R½ÙÖÎÓ¯èÕ4îÚŒŠº¾¨?ÿ³‰þû¿¿§ùÇ÷Ôìléñ¯=¥­j]ËÅDVGÍn]óÅDÍvWÛÓš‹¥šÇ¿¤}¥úç_ê—ÿú©š[ê§ÿÛwuª% Ú -s­åÙ²¦sçwôÑÍÔ|ä=±]ÕpUWeV:z¾ßÓìÕ7ôÚÅ*ZjøÁëºrq¤ÿýÿú¾ž|úëšMþU¯¿þK©¹­o}ÿ{:w¢«ýáH7oµhÌtñ_éâ»5=úü_êG/<®¯íœW¥²Ò¥·ÿUW?½¬g¾õ²]ìiЬk9ŸªÖhiçË/넪ZN.ª²Xh¹ªØS{H×êZäœÅÃÌ8j΂b+‹¬ÌPÞ¸ÅQrsþI¡1à5À"P2@#‹Šµ<¶v®ã1àg»–€;{r±p›”*ƒ@*ôÙÑHeI{ÕØ1böì]âL5ƒf:|9gVo£Ì3üs®—!õ‰™;?–l&ÝÒÚ[[[šÍfêt:Úßß/œÒ¬»r&Ù ‚q;w¤7²ØÜN5ܨÄg‡ÎŸEš¥Þ cž'R&“ªmU1g9ïì3Ä ¥Ž½8ßlØÉõe§ÍïççdÆÎcä,××6×4Å6Øp4…6L§dÓÔ"Ž^3~ã*§U~þóŸ¯~ö³Ÿ­)0\½zµ˜ ÍõŽì¹ß ¨ÖMmõ»šM¦2yUu{5ë5 †#-–R¯×Q³ÑÐj¹Ô|>Ód¶P§ÝÐ|¶Ðx:W·ÓÔj¹ÔhºP§y°QÇÓƒƒ«ÕlHZi:™h4žH•ªú½¶ó¥nß¹£[×>ÕµßÑ»×Vúöþ[=Õh8V«ÓV÷°ˆt¾’ºí8Òs ö‡šLgj¶ZêtÚªU*šN>ÃÏÜ)µ-5ŸNµ?n´Šê†úýŽÓ¹£±*Õª¶úͦóƒ±X."ÆÝŽZͺƒÑCG˪V«ºxñ¢^yå•ÂаàÒ†ëêÕ«…Dãæú"8Zk¾¶‡ûäPIªÚŒº†Ã‘æË•zÝ®šÍCe§Ù¡Íh€±Ñd®nûà`Mj7kªJMçj6j5›ªh¥Édªñd¢Õª¢^¯­Õr©Ûwvuûú%]½øŽÞ¹<ÓËÿùÿÖs‘ö#5Ûmõ:-MÆcÍ–R§ÕD]lF³y`3ªUÍfS Gc-–+õºâ ]­–šÏ¦ ]PQ­^W¿ßÕj¾Ð`4:°eý޳¹†£ñáž:°ífCƒÁP“‡Ôf¼ð kÅÃŽ›f[L9WFqÙ¯¤×ëà‡NÃd2)j0êõúZÀ³¬ƒ0xcV…ÅëƒÁ`­HÜÑzRÇX/`Êþ~N;¬'`¶›@ÖãDšA5Õ%í$õ‰™ƒA×ø˜¢ç¾/ìç轇Á*ªK1óâÌ{äü3ÛeÇ" ý™)aM$;WvÂØ„‘N3;ÌÖ¬гƒ=×€3 ÎV­)gaý4¢†‡k%ŸRlïÊFªvØ8ž+RÍ( àñrÏÏJG*å©>G‡Ö{ƒt2öb²”¹tîWfI†ë6co÷mÆþØŒ]Ø V½ªj猾ùƒgõܱ¹†ûÓƒ€ÉxTz¬V+-ÂfØ>ŒÇ#M&ŸÕf6c¿(.³óÙTwÖÞ}ÿþÓ±¶ŒÒÚÑ¥ÂkhH=ËÌŒAk#\ôÌblfk(#Ëž|&‚Tv 7‰²Çlähíç1(¥Ü0UºHá÷³:í{µƒg.sO1¢oÙagTìÈQ™²Ë|î‹~¿_dÍìðQEŒµ®3ét:…–Ÿ=iœq8v옃A¡åûPÁÍγthXhN'Р–¢ž; ^/”ÑÎìå‡ýÎì…Ãú{:G,²ç\øo?»ÏÂ>@žÓ%©ççKå4ŠS0{™k:‰z¬™ý ¼ùh4*ö/í›vÒ £ãæ9vÅŒ/:¨”&½ŒYW?3¿OÜÁ=ãq®ÓSeŠnsm®½Ê\¦ÑËþ]ö{rŸüz¥RÕö™Çuê|CÕjEÃýÁÚúÍNG]eß;ê³›÷|ØE5²i— 3Ú³¹6׃ڌûí“?œÍ¨¨êœ^<{áw²¤CllÆÝ—6{$8#­Ê`Ž=CH;s]A¡Á"E‹ ¸ÜÄ@™,‚,:©þ½v»]d,Ìñ§Œ,ŸÇ ÑiGÍíh°c=3Mþ=~Ÿƒ]ÒÑüýTƒÊ¬2ÖçÖÔív GÊcE@j Ï‹Ýááñç³ ßïæH¾³[`½ß#6SôÏ2ºOçÉãâÌßÁÙ-Ku“â–À›àÝÏͺ6Óô»P"œb¾ÅLILJš³ˆt¼¸_œ9Ë,)Iír-L»ÝV§ÓÑ`0( öýž)>ÁÚ-ßÃt<®3:òHG‘Ô6fb3pÀl)ÖÌ…;Šûåbõ"ß\›ëa¹lÌF£qñÙ\¿ß‹Q•ŒÜ°׿Ú\…3µ±ð‹ùÓéT£Ñ¨ÙŽH»æ Ñh¬õ…Éæ‰”$&½Ë@§^¯¿Opl»eÀØl6‹Æ{©’e'Ë"[Y¼oYeK„³hÛ´ƒ:feR~˜Ê\éT€r†À™‹ €f­‹£Øçv»­^¯·V+a*œ ³‰=f¬ãñü°†ÁÙfÉœ…síég¦h- F£B²ØcÍùq e¦ÙŸÆ€ÚcÌ#;!¦5ú3¹a¡½³!žß;UæLr¿öhaVÊŒ¢\Ó^¿\/üº×»¶ë‰²· <Ï®WrËßg¦Òõ9•JEN§p&¼—X󲿿¿–-KçžÙj+^Ÿ^ïÆÎÄø~ì%dÜ‘u;,…YpzmaÝ\’î[/³¹¾8— u­VÓÞÞ^ñµN§³VP»¹¾Ø×ýêe6×+ÈD•'EÒ| @;˜0Pöï°^„”?N4fK ÈHYb†™*V¦ñPUÉ‘b;ThcEÿ®‹ÜÙ#†ïáBu¿§k(½Ø„ÐãCõ*Sßü¾ìMb`K0nkH{b·u;tþ9f¶§#B~G¿¯Hg«ÒAe÷zScƒøápXÐæHÇd¶Ï‚¤¾yÝQé‹2àv¬<~¤g1 ÕjµÖ²þœ”©¦úš×ŽOöÕaKöb†ÒÎ-ûÜpÌÊ({”:÷ú÷:tmŒQ¯I6£uO!;<½^oM¡.äœ%óï“bçç¤cæÚ#f꼞½F+•JáDY €rÚkÎ »{¯ów7×:‚¹Y›ù?¼|ðúÀtÄɇåf½l®ÍØ\M0rµT 3î`ÏŠì5ÃñÕjU€úV«UP¥¸îX NÊš¿Ç¦š¤lQm‘n6£ôs“>–EâI=bfƒÏÄÚ ;W¬Å`€€…î«Á`P8Ù{Æ ÓN•Á¿36¤ø8ƒÂl9έ逶ý,þΆ©þ<Î#ôžŸ-tn}Ö¹þÂÊ[Ì2ù>þ]:@{ÿmœéS¤Ehs.Ü•NŽŸÉë’52¬SñÜð~¬Á³³g*ºq}š2Çßçš `y¿‹ò³%k†²OE Ra.kh(—M9ÏßÙTB:vêØÀ“kšŽ:.¼vÖšf:2°¡™m®Íµ¹2Êj#îèO*Æl®Íµ¹6/;y“Âb›b`äè¬A‹ˆ¦ô¬£øÎ(PU©L%Í ÉŸË&|¤ÞD±‘$³$Î$P™ŠÅÊ”eN ]KiÖWÐù©RÖëõ yiƒêñx¼ö=vJg?¿*%ª)˜À=hzL "í˜Æ:Ï-;/T²"pfCÇÌܹó¼ßÑ%ÙÌÑ2Ç ®q­`ge©³.ĤÑhT<Ȭàé÷fm–Ç„k—Ï⯙êçš+;žg3¨æFª~Î,øgmŠç>ëUø¹tlé°1û䵿=â9t}2üÎÔP9®ßïÁ Óƒjµšz½^‘Acß#¿3$¼ª+TbØ\›ksm._NÓ˜ù°JzÈæÚ\›ks¨ïïï«×ëΆœk VLJ2ÿ¤,gA¸#ÞS–®!]k0NŠ 6˜dÇwSfìL`ùyÙ¼ÒËMï"X%½Èøf³©Á`°¦0åHû`0¤¢Y'¥]Ó㚣$•«ül”±õXµÛíº™¦ÿm€;×Xv =ÎdøsY—a°ê1§ãAG’òÒ~N6 µJ54®SýèÐù¾”»öp]°–ÊŽÇÜŽ£ññp8T¯×[ë×ú¾;Á,™×5UȸFœy3ÅŽ46;¶v2ƒÁ]M[½.í@z/øì¯CÅ8ϵBÖ;M&“bLXŸäñév»EMý RûF£‘FáŒSaÎâ{{{źòûÙ©K1 ÿœ¯5if.’ U`sm®ÍEÕzäÈ:Jfa€Íµ¹6×÷2´à"h*W±™"é*¦Lپر`Í…•”xe_Ь}1à¶âiaÎ6Ðpp¦×ëIR‘©0è£$1 Â¥03('¥JrCFŸI‘cƒOm´ß•=t8¦”š¶Ä‹,Φ*—?‹Žg³Ù,€½©Cv.Œ#M2=ÌN‹ì)¡lÚ•Ï;m./hEìÎPŠ›}`ìht:µÌ•Á<ž^΄Øññ|XðÀN¥A{6B¥*M:­t™•ò<$UÏëÛCg†RÏsÅì¡UÀ< œÆ IDATJR.ÝN‚ÿŸÙ7?£ß›Ù,ïM Ux|˜¥ôåò¼PHÈŽ/뜈;LI-„%ḛ̀¸Î¼qj6׿úb^>8Ì¥”(‹[©ê²±›ksml† Š ºýÿ¶)ìkg™`ÖS˜†ÂÞ#¬Ã±½IJ£Æ¬“`½@R¦øü, f‘± ʳö#»¥³Y¡ûmø ØYàm›5(¤Ì¨Sj˜´§têX“DqŽA:;óPžEèÙáÞÒÇÎÞضZ­µZŸ';?ìcfÐí÷a=ïAçƒu¬¹bJRï˜Ucv…bÖÎ9»aÉcRØì°ÙygŸ6Átÿ"ÊWS@À÷£ÓL8g¯ÜïÇë‡, û³FÅÏà,’ :õìÃrŽ9÷kÖ  Ï,•ßÍã鋬áp¸&Þýk0Õ²xFF`½ Ž?^D`7׿Ú\_ÜkooO§N*Œ£)ŽvU*õûý5žùæÚ\›ë‹yíïïë±ÇÓ`0(è,̘Þd`hÜaçÇxÿ?¨£Æ”€¥,³ßx<^“ý5wŸÑq:FTcÁ¾]öã3(ePÒâ,¯[¯× êØr¹ÔþþþZÌlHѾ—Á^Ê7›úeÍ=‹Âý¦ã9càwÍÏcðŠão0ï¬)gNg­VÄàÛãe ¡!:ÌŠù™©˜ÉL•ÌèøV—*ZR°3FIdR= ̱nÆïIÇÛNf¯×+jYXSäLe”³–&‹îý;7?›kjœ"m™J>¿—ÒÌF ïûñÙ8•{ÔtHÊ_û,ƒMá ®iJj»«3Qv¸˜ÁIÜÁ Ä]Î µÒëõº¶··uûöíeÞ\›ë z µZ-åSœEg¦ìéGÎq™–;L±K/Ç@u8‰z½^4gòs•uLfS.½ULl$è5{,=7ެP¾‘}F í÷|²‹²× ©]ïè ¹×²×¨ïï‚>jâ3ÊæÍ¨» 3râ¹gQ!ª1­Úï÷ ýúÙl¦ííí5š›ù~60ަx>Íåõðúuçhòº½(uI™eGZœ~÷º´¥|";3;ʶµµµvøøðºá!Ã.Í~?KsÏ©“O æ1ÏÞxŽ >¹êTNa7pòðý™<ÔœúöaÎ&€Lƒóct×vÉ 9¾¸OxÈð0§”Ÿ³Ûí®EC)â@0ȬðÉdR¼í;ÛþÐF;’H¥ƒ S)txoöÞ°mö½=?.ve³AGù5®m?·ŸÅ`ÚT(Û]Rj¼F¹O8o^w¶#¶Óù´ìeÂ3Å6‘ßËÙ®%*n±(—T"Ž‹e‘ýœc?›çÙ6Ú*JTò0bë}åýêywd›g=m±  ýoâ{žø9½ÖÙO……ÞÚÚfhöÈ¿o·Û…ͳM …†4)ïCªcñs=¶ž?â#‹¯ó½Wü~,êΈ¹÷q1ZfMØÇgo{¯M? T*[eF%³Z>—ÙÄ’¸ƒç×›e|‰;*•JQ§Á÷*ÃÎÄxoúëÜŸ.^g†ÇàÙvËóâ=âçãڇڲBhÖ‚wx<˜Ja ï[bŠ=ø3Øh–ôBÒålOmc;¶–µ´Ì¹çÅŠmó`0(ö©Ç׸ƒ•ÙRò|þ²7“ŸÑöÉ{Ý{’J…ÞÏ ÜÔþæoþæÿyæ™gÔjµÖŠÞºlì¨AïÛ›„gýa©AÜP/2J'²+0Õ[8g¾_*1˜‘¶‚\q6òË(½÷‹…“oÛd‘S¿ÇŽ€‘)žq¤JØÉ'Àg ÊÒz'Ðd@„µ^g>›m}&³ó6£¤ üyÍû¾ì€žQUFë3ÓÂ:Š»`Øç¹ÁmÏï#ÖÕp +¸6Ķ…ÙãÚvn¢â—ÏTù¼=?^ÓtF2Òì±å^aï:ôÄ_\«T:£ÈküÌtX<§®ïðürL¹nlm‡l ¸ÿ8×B0³’µPéÈ2»F¡:ó¶¡~~ža¶Ë¬ë1†!}3¿»q gª–%†ðïëQ^š§;õ 6{°v˘*év MCãšrPŸçë·xSÆšŽ1F',˜  ®àzJºƒ¥Ä.Ì>[Ò±ò»Çþ6lZ–µ±€ƒ7o½õÖgÎŒ7M&eFÀ˜ÚñIn¹ÉÛdf‚JÎ¥'Ÿ@¦,Ãæ@ôÒeá†eD•)@/ÀLÇ3 ˨A?£¢<È©‹Ïôf¦¶=y6VLùÚic:Í¿G… /†áp¸–!pqïň!JVæ²¹’Ÿ“©n}F )3èùòÿ{¬3êHPÃH`D:“k:ã8é@„32ŸirF¹ðœÐÁKçˆãÈè?£)Ÿ˜”FȘ%tÀÁ÷áZdæÑQ}Þ'uá¹æ 퀯MYT¯§ÌàÑ^x­pM»'M¦íù.ÜGŒœ9ÅõB)VÏ-~w.ä³—<^w¤Øú÷} ”mèùO°BŠƒƒŒÈ2cM@ÀµIGÕŸÇ5ÊŸKº‘kf’ËÎuɽ̈3yâYKÅ>>#Hãñów»ÝÂQàÁÙE¦ì.MPÊ5K 9Úv†½þ( LûA{HûIgœg•²è<›áÙγX×ö0³î¾oRH¹ò{Q‰Èçå…ÙüÎk5×|6ËKùcfýyn0 @Š%[3+ä}ÈqeH>¶c•54™ `1¨Áq ÓƳæApƒ§>kŽÂ†þùÅ™­õó2°L°IÜÁ=‘‘qžqt‚èìÓÉÈlHâf w8Ú5F‰; ÂÂ^û|FJ!{ ž‰;èð\`ý‹÷b²BŽÂ®»: wxÍ—ábiÓªhÓ©BW†;’ÞÅZ+Ú±¤`¦ãB¼Àõg,‘g5ëÙ|?;G)…ž¸ƒ>ÛÂdÞ6†¸ƒ{Ò?S83Ï>ûìZôÔNãäÁfºŽÎJ™®:A>£·ô†é­3ÊHb¾„?ƒ†ƒ‡0=:f8É”$¤di4€ H¹!I—ó¢`± ³™¡b)8f<¶¤A1£ÄÍMc˜›×Î#…¼gz2zëÅoÃfàDÅFDzã¯?àØkÑÿf„Œè\Ó9fôÜ{&˜–Åý–í’ïM:A#ÁŒ 3ÒH À€Çž QW¯ýÑh´¦,E0Ë3‚`‰ ÓARž¸† ¤h£³q"©"^ƒ|'žœ#,‚„ ¤‘š—ý2èó>I»ô“EäÁÙÈŽ™M>Þ—Ù_f(RŽÖÏÆ†x\Oe¸ƒÁRÒXòl$ 4{ƒiÖú$î cÄ¢÷t Ø ‘¶%›vf×òã2Üá5MÜA JÇN ×½›x’¾_†;x¾1h¸Ö]ëˆ`?iÐGáÖ…;t B©úþRŸ8nĤá2PêµÏÀ‰í6qÀ2ܑƒçFRŽw0ÀÀ››’½ÁL6qpd¹0àÇu˜xÏ™7®å¤w’]@g‡„ç;q‡ß•™Ç,•Èæ¸Ù×n-3C¹<‚(¼¤dêÞ1ùpŽø°s* :.–2-psûøÜŒ< Ê8Hi£3áM§…pìˆJ‰Ã4Â<ñ 8°1å"#¿’srkùL¬' gMJ7ýÌÒ0òMú£¨Ž0›;ŸÏ Avv&Œ =iH4"™B7 cf+e Å÷üq>ü5Ö@ШS ß5kê¿TÒÁ%e‘À¶ PxsDRˆ‘+F¸¨æC+©™lG@@àKÚ`ª—°Þ‚¼^Ò½F˜=¢cÉ.Ì ‚B^, ‚ @‰bÐÏ@š£eiTÑò>ö¡j)PÖÑØ{ì½ p²{63©¬ý `öøy¯$äþ Pæ>%-Ó÷ kàÍÀÖsf;í@ Ae®Á²5îù¡-à!jÚmÒÝx˜òü‡kô»¬b!.PRUÙm›`†uzt>½Î¼¿©pD°Ë}Fç˜ß÷Z )3H쟊QÞ h1“Ç !­¤71ðÆs~?*4±ã:)™M¡jÏ÷w¡}#•†T3߃àÖGw0ÐÄÆz ÐrÎî…;ÒÞ.쯓yÁìA:¡Ù»¤,S•5Gá¾í Ç€{¢ wx ™YÎlYÅ4ûmqQ‚õ2ÜAÛ@ÜaúqmŽ?ø‹›LŠTÐVwøÝxÆùóŒ;¼î`¿ w0HlÜAÊpŽÛƒâÖq1ИÌfÖ~¸ƒ¸Æø"ë~î…;üù¬ÏZsfx#Fu2Ò“j"‹ù>ðÉW¤wN=FX;ÔS¦ë'XñBešÖ›Àž,9–\Ôô(³™Á8&zªìâʃžj –‹Ï ‰i]_®‰a£Ç‹Ñ3ÓÐÀeêp±5ŸÝ‚Àò ä{$-“EÆÝYĬ±i ~nÏ·yvÙ±™Ô 6˜+‹\1‚o‡Š¼oî²û³ ^)J›ç5‹´©¸éÄ‘rD@C:2íJR]&­¥`G:jü>Y\SÌ\)lc‚crä „ËºtÓy(£XçžgSH±ìbo`ÁÀùóIñc ™‚ñ¤îÒI0å“@¿‡h—’¢ÅSŠ¥Ò–m…÷¹÷£üÌf–uC§í.£æ²Æ. ñéX’êÇñùmqGYMÏý²blÞ³ wp –üwð<£.Ãì’¸#›dúbß—2ÜAœ•µN †òPÜÁL ÅI²«½Òwp ’3˜ç1÷ýS嫌 LŠq‡±Ò½pë§ ÷šæ˜Ùn%î 3ÁÚ¥Á‡{ášÈÚaËýpëkÉVÈL3ît.½Æ4ºË™!œ)kÒÅHÉò „QÅ!yŸôòé’sŸ@ÎRvų̈Erö¼ð©ïî "·”†Ž£SŒjûç¥ad…\?:@Tçñ³’Š“DRÒ‰Ì:Ö0úHÊ›8y³eí•=R‘ãFº?¿?£¬>»Ñ‘~C*ER‘ÎI^CTÓ᳑ãie@^vp0êÏÕe_µ±¨œ?ç{Û ³Ð£I<°XxÇ:FUHa²ñäÏ’³Ì5Me8Ò2åL:)'Ibt™@†ô%}v£Îw"ÅÇk”…÷Œ\òp̓…µ%ÌPòóü^.ĤJ£Q ”dÄ”MÏmd¶›Ù|Ó¹¡mÎzÖ%GßjµŠf¨åÊh:mmŒ{zðݲÔ*Rþ=‚ Fëëõú()«—à9jj6€(zÁ}™Á1¹Å¤×f¦’íRÁ/žtšËÖ1­ ¸Ñ&eˆM'™%Ȧ~T@3À¡ÃI{:Cé¼ßw0ëp󂸃´Ngj .I§I–IÚÖãáù“Xö†µ¦Ÿwø})˜”k%±¥š3(•™ÄÄ^3e¸#÷NÚ)ãÚ¶2Üá 3³3yþd¶€:ˆ)Ðö(LfeK3x”¬ Ï'3XÄ\ß¹vËpGªSÁ6ñ‰ÇÆ‚-£Ñ¨è•DÅRg‰üüYOZ†; åÚ¼î m—õ5—5g†4.nv~hŒeÏ’ÊCVÖ kÒŒLÍ9ZC™F„“8‹ñ\£ââwê›gÁ+½Û¬ `$£ ³vQ v4¥‘M}ý,È&ßžF¸¬ØŒÆÅ¼v>v”…ªä¸2­\¯×׿…À€‚ý|ØŒ*xŽIõó³Øhѱ— ©÷bw1£!BŒ¨S)_Ê«¦ Rª1úÆî¾¬=±D²ßßãLc]V¸M0ìÏóáçß#ÉÍ˲K1#-™jN%´,†MÊ@F<(°ÁšŠlÊÆ¨%ÇÙc‘4Q?ÖÅñ°òwäžóLuŠPøPvÖÆã›*jYÛÃ> Þ³¤¥ž@ âFk×tlR%-›¥ª#d:S)gΈ…R¨ªEµ,:}Y_ãuHjA!U“ŠÌuæL=),œ{ª\1BèµÀHµ3)<ø™UÊ¢|fD¹‡³~/Fy™•b$ÞcœN’í¤eáÁuQ2U S¾ŸÀ„1Ÿ£|Îäÿ'`´Ayž)iÍ‚kÖ5²oG:<ÿSñ(OIKéqfÒØ#ĸ#ÏÖü\Úhò÷ Ž;N!&B›è :YÙ€ïAÙZ*>.—Ë" Ÿ5ºt ôr€Œ™yfµ{lwdfÑô›£p¢£pi•t¨(/ìó‡¸Ãõ† Ž•áλÏNž‘<ç¸×wPbŸg Å&ˆ;X‡L'€fëˆ;¨zö ¸ƒgžY‰;2‹JÇ€Škü±´ßŸóé=Ä >Ä e¸ÃøÒÙ.Ï¥û3AAŒÈ _½´.Ãtx˜M?ªÝÁ]Î oDÏÔ7#Ì& •N„…²ä¾±Õßc4;{WPE"=eFÙIËñÀºkþÓëÍ‚A*DP§½,ÃdÐãEhÃçÜ›)ÀŒ,dï?¿?©\Ì\QÙÄE·Œä¤%&R|œº´ !û‚à’·Íè—çp2™hkk«Ø4ôò ÄRV1¦h(<®Œ1:UVœJG™Å©Œ˜±9FØ##¥MI`u=éôpÐ8QÚœ5L­gjž\Ö1±30Ù×"e™%c‚*B£¤¬ŒsÎ2kÆbMÏa¯×»‹ŠF®:¹Ã,¤“ñk –goÍBþääò=%‡iyfø$¼po38“©}Žƒ0©jÄ¢bƒ-ÖmB‰YRZiÇY?ª (•ÙÁTHd]Lò­Sé}ƒ¨Vå×Òÿ{t˜©ÏL£yü<Î7Ï›V«µV“Eç(å®SÝŒ=( ã@›Ãu”ÃìA{á,ë²›:³_©`F»ÒëõŠ{Ó>rîYfA‚pFó \ 2¸" ¤m,Ã]l³™L:Þ)nDÜaÍú„¬y!¥É¸ƒ‚³Ä¬Eãœ<î Už8…SX LŠ*ƒ¶Ñ)¯~?Üáqg­J²*ÊpëÆw¤"Ue){Eí™A î  9 w¤ø3¹Y/’kë'q‡×í½pƒvÙ¶¢ w8ˆCŠiŠ2‘êGÜÁ[ì[•Af‰¥yVQ ‚¸ƒ¸í(ÜAe¶ÅÌÌ2ûIß~Çš3ÂcÒ²p;SFljÉÈÁPî±IX¿ß/Œ›ŸµŒ|”©&8É[6("-‡s‘óÊ+<0 *Èä}¸2¥È™ ÄÓõŒ4¤D,»«ÀæAlª ߇‘*t&µ!‹¹ t˜¾ä¦eŸˆìøË´$©TTÖaMDFH3êL:9ÐY—À1Ï®Ñ\ÛÔ6g&‚ÑÖñdí …,ˆc1Áû–¤ LFs¨Â“rÊü]‚uÓ0½©ž“ [SC߇uÒóï”yfqpFp½Vü®yJ³Ì@q-óK!gpË«hÛ’ÎCG™Ù*S˜‰*ë¹EuÄÙÈú½T!â¾¢òbÖÎØñ 0bá1és¤¶ƒèôp6…á¾gÊ9³»5Á$$¥Â™1ƒ>‰²Q3dªU’þDG6…"˜%¥ÉÂ`ÚÒ]ܹš…³lºçñw„ß«¤ËP5Tí¤xò¦sá9çÞ%-–ûŸFŠj${€µ3T€Ë,?£Óü\ÎMŠê$î (HîàÙÇì'kŠŽÂ^ól-aÜÁ³ˆkšY ~NîÙ2Ü‘mX[¿éÐÑ9JÜAº ³Ä¹—\7ÌñËæ—‰;(Xˆ~ÖWÙþPUð~¸#ë[9Ή;\*‘ùmq)ÊÙT”TXâŽ|§Ïƒ;|N&îHE`Šw¤ÈBâf&$#î`æXšô0:â챕TÕÜÓ¬õcý q›‰ÜqÔš¾‹fF/‡…i4äÙ,2û#°Î&Õoü}ÒB¼M&“5Å•Tþa‘X*kÙ2 @Àßäà1"Eã–Ê( SÑ$ù´ž ŽA!,‚Ó’×™¼vÒY¬†Å¦TJ>`IåÉ+kÒ»Ýnñ™¦’e#³ìJN~­3J>mü¨šR–ŽÍÍ”4:6ÄKÊKX×ÄC!9çL«çAD½x6c¤º‘•Ýøy^÷)KÃÌ5í(;ÕÅHåø••ópåaF* {@Lƒs}8ånFNyJ|2]–šN™[QÛ&0ËB9_6æ,ËâðYø3žK«c¸z:ÀÎ×ezøéL¹¾Y®'n¤ ’ÖÄÃRéYÁ,e¨™Uñ:IÛ’mòïÙ\Õ4ª?:K™=’¸þ²È•sÈ::g©’–u1)¥ê÷&Ń€‡û‰ š 4©N”;åó”ñê Fh‹ ÒR¢œA,fëS➪k”æ&u‘ô/¡sgà½>Ù€3E ¨TFÅ"f'Ê„X²o -sϰgV™JÑQ¸ƒ™R¾ÜÐÞsn¼F}60 SH»•¸#÷xâŽÔÙ5A!{»w0hr/Ü‘YÖc2HPf£¯¹xd IDAT3ËY†;x¾…;ò<ôg8èÁì;Ï®޵׽3êã2Üá`Ç‚™H;m>·Nl¥êq¬û|PÜÁ€ùýpÇ‚ŽV¶¡HÜ‘ Z‰;2+C<ô ¸#Ÿ· wdfÙ#ŸÄ)FmEŽÂ þø¼ðÜ­õ™a×m G8€6œTDb4Á‹Ö ˜)v*Š˜ÓžˆŒ ’žRvT* ƒ5%.ÎŒP¦AvGçç1úÁ‚_~-ëjXÈÊ‚nO°|™¨@j·§.:Çß|Æ*ÈNÝTÉèëOhhL]cʲšY|Å6Y£l7éì—BƒÈMÂ(4뮲i&Ulð؉v2™‡»ßŸcCcÅ禔7£®¤ ±ï ûD†Hð̃-õÖ™úg-»ã2™r6¤É9ήڌ~|°‰@!¦òk’Ên_3ªÍþÀ”—%˜bT­LœÄß3-Åö‡Á ý$0‹*dTŒñx1b–j ¼Þ¬ Çô=)V|®²š(¿›©[ ñœ²¡ë©"Izkü~¦(xŸÑ¾&@-‹®gá-•,yegû¤z=§ü2)º~~S­Øƒ‚Aº”+æÁLÅ5VÖ“c‘Mè²c{ÖQòºL†š|¼»ÝîZ6‘ãùŒ¸r°f€iòáY`=ë̽÷šfÖ¤• 3CKùqÖQr=SR—Î)7nyowPvÖÊŒ¤Y3£–6iˆ;lóe.Ãz)üâ{&¥4ûæPô…4úÌ®’9‘ªXyÞR,€ÏþÛâ‚íì¯Äz5âÖ-v»Ýµ5ž½¶2*ï±g–1{Ce«’ªÉó…ÔmÖaÓÑö¹ÅZ¢Ä”(æ¹KG™g[âÏ]îÈ •q›úUtO!…2Üáçfo%ÚÌbß w¤¸q‡ƒ œ âŠP胸£Ñh5Š‹Åâî>3NrcóÆ)˜ÝÂÉ‘¥êHfgRMÁìLù%l€8@ìIB#새ÆŸ‘86sb-J»Ý.8õ~wdÍÞ5ðÄPU„“›|DrU½±ý´õXø>V¿ñÂåajcÍæQT‚¡WÍÂh§Ôó ðXÐQ |4©×ë­ÉÒ€û@·ÑtÝ )MܘT˜¢t$è²NÍ6²¬—!°vÑXRn’~SÖÅΰ4$v½dôØÏèÀ &©Z”¬4-ÅŸiCCLj/7>©5Ì0:K“… Bºæâópdd“ꬭá3’CîñðŹoHñX¦(C6Òòx9µNÀæwâáå=æén·»ÖÀÀ€‘#™BSžÒk†Ù Î#\,x&í0• I"U‘¤¢Øv0ûFêCf±3“Æ>(Ì0F£»ÏqžRD€óËèqÙ¾Jš){<´]ÿ”j?yˆÓÁcPËÀÈÁÌN˜VJ ›×|f±ö“t8?7û”¥Sj[Ϻ²!H¤ä7mªí ×Rq³ÆŽŽ€ÅcMª ?”Ñ¥ VvçxÚF³žtëTe½#·¬EÉ ±×AqÏEîÈ:@ÒgŽb80[Êl"•Â|¿Ä^»Î@…; ü3ÈäÀ÷¥ÇÒdX{É€„çÆÁöߣԼ탹‰;<ƶé|§ à‘á^S ´ —኱Y GᎠ‚$î`@ÜAuâŽd Ð9çù•=_<—Ä£TÄc#LŽIJ0²»< +S=ÊÏßëõÖ2Þø<,Y»”ÄéøgóÅìm”rÃ4àÓ©.Bç/‹³à±ŒŠ—ul®­Èú7޹³¤¾ð`²Ñôýi”YJ§Ê 7Téad¿ŒÌ5zÒl¤ÝË^Ló“vÀ$8#i,gvŽQtÚf}yÈÑÉãžã³1(•]ÃI}i4ðJuÂì”m{A k:²ñ$ )PCž8Á6),Œg÷ì” æ¸¥í¥àŒç€µD™qQ>RˆÀcÅ:&ƒ,Ûbî-ÿ¿ƒkÌ.eFÃãLƒÚvÒ瘉b@$3h\3¬#Êæ‰´)\[̳ ×ãè}˨8%q À¨ÚW†;øï J%î ÚÓ½p³vt²Sä„™[Ž )Ø<7)ºà±3î Z\6Ë%î õ†Nßoƒ;Ì+äÌÜÁuåþ]¬ƒ¥}¤½¦ý¢ÓÈ,-Y6d20HSF%'î Vãù›˜…X9qàù|^É$ Þ$–.£1—‰P\Šâœgc;ÄóÙc*q©z¿+î =åþ9 w0KNÜ‘ÔÙ4s-ßψ¤;#·L:Å“›Á´=è2=ûTFwe²ö„‘v¿´7‰#¯eš‡,¥½Yˆéïó€ð!Dãž|ìŒÎ0íî1¡EƒIgÁ‡½^¿_#õÏ…t4ŠT bq#S”Ífs-:˜·eÞ¾Þt:-(SŒ,Ð!! öxÚ`’þÄ´2‹ÏY”ê(9£—ì(ËJ(¦Ôù.¬ñ¢£D°ÅzŸ²5ÍȰeBS‰$Sª©`Ÿ gœrMûsÙ`’ãÆ(Õ`X;fç€Éeª^ÙšïN9ef ˜a¥sL˜9죘N§ÅšN9Gª­Ðió»› 9{1ŠÍ=É®ãÅ$œµÊâ{ þ¤ÓMÜ‘n™æÙ6 Û?ÜÁ}ÇLŸÏUÚMõ&î`—ôèlä˜çéƒà =w$kÁÌ€£pGJê…;XäÍH{âŸá tw0ÍltâffËp‡±çÙûšà<{by¬XlÜAʬ•>w˜;ûåÌ 3ð<›²½@⎣°4ƒJf[pÎS $å§=Æ)ðypÅ®ˆ;2ˆ@‡4›.S¬QX™a¡ÿN¥ nB§ïçÄÓ»£ëJʺ±’zàÏuäÏj=þ,:#¶Í#MýT| zß3’MGT¿;í©× ×TÒó²É/ësžéÜ1Ë »m.ét|½~-Éi˜’ô‘VFâ¼’²K`æycäÌ dD‘Zò ²ÈAdø°öe‡… ‡k3=óláÈ:¶´ÉÙx•"î Ö–%øJyyF’I¥ÃHÇ”M,Ùç-3×ej¦¶ÿ¶Ñ "–ᎀ´Ñ †ðå8¦}óz56HÜ‘‚¬e¡ùýpG:GáÚÉĤ÷Ru1‡™ÅNðžÝàÉ®¡ð³ÜÄ^»¬= w¢Ë=o§ÀÁÉÄGá2#î‡;²ˆ¸#ëb™é̺ž”ï&X¿î0µÌŸ—¸ƒs}/ÜA in ºwPŠŸïÆ~g¤º‘ÁžÌà³ö…,fÃÊpßTî œ•áŽThMjäQ¸Ãs¿F33OÓ‘D7€"Å‚i3{¯äÄyÓgç^HOš#©…σÝÎβŒBxáQ‰ÇÿÎt#½Â<¸=Á,„ÍÂ_n\{Ðtü{œlÆÈ¨•¬xèø^TR*“ÌÎŒûê8Àºƒ”qäfJIÂÔœg7#Ù]‡Í™¨ÛOÚ\Š10áq ¤cÍéè1[æÿ71¯•Tÿ.{:†\÷4ÆLûy!Í~-óÁÈçHG‚Qa‚XÒ-l Ü#ÃdFç=N¾?%véúHYZ5Fn¥Ï^¤)а±.,;‹Sµ¦×ë•réü±‘))6>ðhXçÃ~  sD©hÛlvUçÞ¦3#¿¤]Ò¹`¶‚ç÷Èñ9Aq Û³T¹KÜág(ÃÙã#q…H¥¢#âýÃf±¤r²[9Ç9¥•Ë쩳iì?“â%‰;( tîÈ~#´ÙÜÇ,ð|9X@Ê/©Ø÷ÂÞó>KR`â÷‰;(¢@äs‡ª­‰;xŽqï•áÖFòl< wølû<¸ÃÙÛtꌧºÛQ¸ƒA²©rìyö'î`öÑ÷`š6ª wø9¼‡™is0Ž45еü¶¸Ãs´æÌdd‘ZÒs夰—•ˆÈ½M>´Së¬Á`4>»¤Ò;H*RFÁ¡žž6”˜Q¡áfƒ9ª`ИgS@ò”©ªÅhWªN”EK)6Àƒ*8’^ÂdÖp#ҩ˦•Œžò€'•Ð Å 2šF:¹I%)SßJ.2£B ø²‘gF%¸¦Ù$<ílv•2ÂL3û’**£û¤á²Åλ¡sžÙûƒ‘h‚Tîm:ü©vå=“ÅäÉÆàùÊ`Áw6âe†ŽçrŽ'3fÌ.Ýwäyâuìó’AŠ”á¶”õåÒf&…ë9©qÄÌ<îÈÆ¶Žúw°Ž‡”PR‚Ìœ!î`ÏÄvæŽÂWÖ@rÍr¯Ù¤@‹ë)F*~÷ÂI³£éSÌ6òs²)»×P⎤£…;Œ ³¾‹v¸£ìܱ½v£Q2jò|yÜAÜÌ5ÍZùûá:O ä‘qűþmqª©NB>"õ¡T2:@®¿ÆænÜ6ú,t¤#4 ÖŒ'ò°¨£l˜ÒzØÔÈΔº¿o'ŽF)»×r“òÀ¥DuöôñÞ“Ù™,PóB`4—Ñ¡²‚1:+ü]ªD»ì…å9u“Þ»;i8Ù‹ w\žó,Ìδ{o2‚‚<éd°ÞÄF”Ô‡\Ó\Té ¡#‰Œó d*I‘>DðŸÍÔ <f6–¥èI¡CÅ5m0äçdÔšŽ5©U”Yöø23‘ªeý•h0³ïSRï¤SðƒŸEj,#Ú>S\! ÉѧÈAŒœ’ÂFš¢ÏrÇ“Éd­pžà™ÎeYã^f}m£²æƒÿάWØKÚ$fCý‡b*óñP¢ gÖ5¼x¤šk3²"é|Þ´¿ìæNjZªX2úÊ+J³S™ÊódÐÅà ³séÔ‘¢Ìƒ=¡<Œòf?3;š>ß8öfWPZ™}AXWFdž})=%&½Ócíqd¯ Û6 x¶ù*Ã^Ó)&™ ‚X‚Oââª1Z-‹EïÄf ¾ÃfßÖ`¸#³þ)žB»Â÷OÜÁ:Уp‡ç)éDTÆ*Ãd©Pø =e÷ï…;¼’¹®ØÃÅójixÓÖ˜±BƒçìýR†;¼l¸·)0Áf¡Þ[t< Äéä—áÞØÐ2EwX£ä±¦baâ>#qû#rü=–GáÖ ò˜yæ™æuÀF®X¿î ýMŠ}âÖªr,R‚~­f&S9lxEÕF#<é©0iðl*ÄÂWʸ%]‰E°ŒP²8‹“Ê^L3…Hš å)•é= ÞlÖ˜$¿‘‘Œä“2*“ÑÄT|ËîÛYåb¡‚A=Ó¹LMfçÖÜL.î"÷xQê–ñäTf7u¦þY0íù#H'hÈôhjžSΔ›š# žkF¦Ù«À€ŠZò¹¦ \ü<¦ RGJMF¥-L‰UvëÍ}G n§ò9&~nÒˆRÿŸE…9nÙè‹Î,£dä×f°€ÅŸŒ6“¯žÅ²’÷ A#ICª=e}#·ä›³þƇ0¨1—ª\)ãIñ‚SÏ bÖ*ÅAØ ‚”8îeÚ‚²Œ‰×¹Ñþ,ª³(Tóʹb°'Ï9F`éüP°wP6ÈcMÁ6Ç€¶·¬'ƒ"Y@OÐoÍ9Î5í3…€Ñg0³qe}ÕØ Š2â “YÁº2çÇóNCâªLf3iâ;c>¿=G©×ëkm8þ¤4wP\ÉŠn‚;¨¶–¸ƒN qÉQ {ÉHHÜA'Ækkþóà?³qG‚ŽÂ bB_†;èXzü¨g’´&Ú3¯ ×óùù˜Í#¥Žç»÷+ƒ~‡ÅY¦ÀwHÜÁ,—2ÜÁ †Ç9±ŸÏ ßÒžw°4qe—‰uRÏsÌzARչffÆt›(%Šmè­q!{pøÂI?b#@Š8Ý–5'¹É²Ùû¹0ºÇ¢0F5Y Öl6 ©\ò3i¬è=’'ȎؤeÊŽÏM˜ö` ‚˜BÏbÓLEz®|€pCј™#› gÞl,ÎâƒR´ósIIƒ˜øT»ñ'™ÜbÞ3¢œãH  ›ÍeD†À™ÑÒét¤A`¦ƒuZŽÒ2œõLåfc¨4ÐkŒzžmܲãrfXüLjïëv»­ýýýb>XdÉlXYÖŠïON5µþY@JyUªç°¡ùñŽZón»5 î¢Q°Ï?—Æ›E¢äì³(’Y[r¸ :ÁôÞ £Bξë |1•Ÿ2©|V®UgG©¬C§–ë­,ãÇì,B6’c_ ªZ2SpT±zÒóÙvèÔ÷z½»öRJcó°¦@ drû ÓIdv9{ïx mÿ)¼@º$t2“µ$^‡Ž>rÝPµj­‰"eÊIûι`A;eÕ¹¦“‚Â~5) 9@Ⱥ7GËY´Î:¼”Ìf/ ž[Ä9þ)€qÏ!ŸlÈìGâŽlf]†;ˆaˆ4eЍÜg ÒëõÖö£ÛTƒeæßÁ[Ÿ÷þÿ |¤#ËÌfîðsw;%î` „â:Þe¸ƒÌí~¸ÃÇì~¸ƒ?f²Iãó÷íÜR!$ Gp½e_®{áŽtÆî…; î`B–b0X™Â&ÉzIeÒÄ XdÈcaçĸÔ[®=î§Te³#Oܱ···Æ¢!Æ? wÜåÌøx¢Ibgiòñ2åÌï3ÝÎÌ.ß>(³,‹ÿó`'@b4:#î(L}ú3™E²´(£ÑùŒÐ³×S­Ù€ˆÎƒ–E­ÈÌÏ Ó¨ÌHp¸¡©ÁÄZ ˤ°ÿJ‚pÂe3@*ÅgIç˜Ñ;q:‘|Lƒp*q]òÀçFÆw%u2}ÒÙ<‘c@š£64ZTýàÁ‘Qƒ_~&U‡Xóâ±4'—÷a””©e>'»,32š¢(¤ QF<ûxøpòANj€¯_êÏS™%×»‚3úÃÎñ”‹ÌzŒäž“C‘sgÖ0c—êyH2rKyfdHlJšu<,^§ˆ»Ý0ô1à”YT6Qõ³gq-ëíËöTÍb.› gÍ£q<| ê­$ÉZÈ™¥*{ú¤“›5:tiOG‡kÚôµÌZ`')jÙë‚Ê…lDëµÕét {7Fby×JŠÐfód € r¸TnÊh0éj|/ß%qÏ>Ö¦Œ4ñ÷ÀçÅ>oËp‡ß•T9¯i:8eu¶tìX‹’=‰è…;Y'FÉÞD‰;¼GËp³v¦˜a 1E²í7&îð~ôs¤ RîHûᎤ;SA޶ŠûˆgRʲwPðÁ÷`Ÿ—£p‡×hÊìgyF*½‘b?Ü‘©Ïƒ;xž$ýÕïÅ3—4”Ö? wä½²ÿàçÁ~—5g†J GI@f 7# )MkCI>ùÄNg­;5'6ëX/ãn¡Ýnw­K³•RH;£w˜J>Œt“jbN#C'§ `f¤„ÆÑÖNÃIÊ ~[²/嘙Q"àãïø¹Ù碡ì- –=y»Éͧña- ½˜]ð{³ŠRÂY@Jþ$׈ïÃð” ¥ƒ•ÔÑR%Ž $©Ž’}\$J©Yfo±`—nRHóòaÇ"g*¾°…éï¤tðó€(3Üì‰B™”‚¤ ±)Á0‹³ËöA}*–Ù™ÿ̨ª£¬³Ù¬P³b‘öëHÕ1ß7 žS>:»“{í¦~YïâÙ•µ{tÞXÏ•²¡#öüH'œN"v~&)§¤ M§Ó¢ed8±ÞˆõQ\¤ôq_ð|ñz 5Œ ‘” vq']# ­” •Õ¿Ç:¤lIŠé,Ù++©Ñì¿sT"Y?ã¹b6óOg‘Y&Ö`² ï–íhW“"Ê>|OÒ¹(ãqŽIOÜ‘=ݎ©Çsô~¸ÃxÅà=lj¸ƒrÔãñXÝn·X»¦áø< húûáÖèPª93’­> wPÒü~¸ƒ¶›æ£p멘%![cã¶<&~F:T ´wp>w¤𠸃T¼²š·2Ü‘TÄÅeôiÚhž—tvY3N'„™4â;¯÷Âi[Œm·=/¤“{ÜIgcàŽ´1Ö ¦j\:íÄ÷ÃÄÜlš¹V3ÃC”ÎÓùÙ“$‹ip¸ØÉÙÎF\Ù¼.µ¥SVӆɒ|ŒÈ{á°8 ݈Ef¤sA® •mr²á=v.0Ò®Êd­32èËQK*m1*Ì(MÊß±–|ÎÔêg4&› z¾X;ÃL »g3êïMă9»—û=(Íš÷ÏC”í²Þä‹òÀ*kžÇç#Mއ^%rX³Ù,Iz¤(p=2ÕMš‘‚6ªÌÙð'·Ÿ cÇú1öaá/#×ÉoOzÒ•¡Ì48³tŒd%È`¢L€t°ì%CÀÀÃEîi›x(‘¦Ãì5í#7fÑÝËÎÆHÐýÿñv¯Éqɲ®¡+A€êqh<=¢=ÍžÅZ- ·‰Òùå°§^d`÷¶#³¶–H ê»dFzDx¸ëɱƒ¡Rºõëq6Å«ö¥ÇÔI¼Ã¸ª*pàðööÀr²á»f9N¦†Ûk‹½ÖV©•ÐV]p yÅ©“:UËývŸkî¹®g=ì$«žå£\vMù¬ØÖ‰Ý8k\ªR›óO2,ö;Ã广9U:Õ5×ôÅè^³ñ¸;B•ãuNÊõuR?r~NYa©µ×p‡•q‡…ËáŽvkÅÒð£½æâŽúRÉŒñXQ ª[ÛûK¢ö½RT‡oN¸C)úÅZ‹ŽޝáŽQ ‹ì†væÈLÊyq‡ê¶>¿â•ví6ï.¦w8N îðìx;œË¬r˜E²îpçî¨0† ½>WRÇŠ;ZÔ3)™ïý¼w”ÖZÄ= -¤\‹;´]Y<ó}üõ×_—ÉLµÙ{+¶hë¼\™\%K• õ¨ i9&,ûôéÓ…ƒšÜó[iuÁÃCƒ.)fÄ‚¤0Êÿ“R¡BÒ‚ôƒ€´y‰[ôKV<¤åâº@;?T^çîg@Óàçó¶õjv-Ï݃Åëò÷53©“C鵟̹LLšÀÔÀv°×î¤JQ5ªzÉÒø¡º²WKa×tõÒ+O½ ì@ÏÝÝÝÅ€§ƒŠwww/ 5åt ²*…] !]À=¯9ŸàþäÒ[yÅvVì¬ æ’휛”žÒ Œ£ùôúmÏÛÖ¶z,ÏYª•t×£ž>vD”šµÐSð‚)á^o«TÛG‚›?½v;ª:˜k"¶õä\FÝ;´> ¤ñ¡ÿSyìÏ?ÿ¼¹¿¿¿˜}:ÉÅñÍ¥³yKqÖÃ.LTW­7`x °6¿`gËüb&'‚vßÃþ{ÉNàManïR IDATß¹ÕG+qÞVM—çn¼±+·8Ñ.‘ûnïÔŠ•ï*j¶š,îð¬´:| wØ)Ry°¸ÃçßY5O¸C{vfì‚n·|žG ¹›ßÂÆãîX¼}/îÐ×ï@qG…ZŠ;Nr¾‚]q‡·Òúª~9öƒ4àîð<èÅ w,T©f¼v)‹;ÖUüwT!®¸£*Š&w|úôé…²£¸Ã¸s¾s=*Ol…Æ& yUPum{®Ûµ}ašYC£:c·jæáí†5pm³VÚ¸ž~Oåüz=[tU «äe«"ÊoV.ÐÒjÔ5çZÍ­”©«m°X¦o Ô0Òë6ÑqøÏ€'¬@ÐÃÏJæ¾[Mrˆ›¬”ãÚj‰Ï\ Ÿ”zˆL$ŠNtIJ—¢ ­&¸Ê7ù:Í0” ÿuÊVÿ;(ê{P¾X@mwÑ*òi(¹†ŠõS8¸'F jÅÞ´íyé R‰Nœô½79÷Ò]h\UРçaQõ¸­iƒ¿¼Z |—šåšq ›Ü–Ö6~é¥Êè_$7zhnÛ&íÎk]W'“L;Ù­d7‘òÞ*ýÙn¢ßÛb“f©íTª~¤b˜  ëÛîéi/mŒ^Ü.²"Ó>ûÆF;V¬Túö„•έùoß¾=S­>V*¸´)ã´44A¿@¸ÀÎdι×Bg\¥Œ;7²ï²Qõ¬ šÌ8¬/ñÌר Š'àþÜá^¶ âÜS“~¯Çïq¦¥²»*-¾^Ãõõ9áÁº*v9Š;ìHØaëµ,nYDq¦dû¾b<ƨk¸£JzUH;ᎉs\îé×pG=ÂB5©˜ìùÜÞÞ^ˆyN¬[éùoLò|ݾum H·–Ü?í¨Š;,4ÀTNªO‡’ͯ­iωR O¸cqF[‡x[¬é OÛ%’®õî09:Íɉ©¬|gÜÓûNqGY)ŠøXz w<>>^P¨úL÷Îßp‡ëÏçVÿ¹k¸C\9Êìp‡ëÞÙÐâ»é&×Òkšz‡¥õúôéù–xÖ)Ÿ_Üá}¸öl6H5¯±ñâGqÇΉÎ{¯HÚ¿L‚Ä&ÆRT/:3ãX:dy1ˆî‚~zzºð²Ø—´£L\åfíŠì`µšºÏž^ûæböïJCVîVþŸs66©fF)/[ÊAÕ>jž$°ª*ˆw-kÛân¦…“Ü€ù¯¿þzóùóç‹{W^Öìßôööö…›¹Ýg}÷Êñ¹¹¤G|ùòåBÝmAùñññVc|ïx ‹‡“ɇ÷SޏUrå>íí/(IÚs/ßÃE#ªÎ”Tú×5]¹^©7òC;ÜÜa:9½&Áuù5xÿðÃÏûÄdÁõÝJý@õ‚¤óV¥eÝßß?d£Éhêš¶b«ŒgE4¶ö.*3ªgɈ­ZîÁëlÅ݃ƒÀà(¤È¨¾#ÿÙ„gŸñôôt¡l¤l·Õ:Ÿ—CÑ«w=[¹7iñ}yxYù•-Íeïrà_øf¥vm¾Û%0'ê±Éº’ÏÎ&n-m NÙ¥OU ASÕz-•åüÀbÎþL™Š<øù• =lßBY»×vÊv6(…kÚs¶Càv’¤mI'\Œ•®eç¤3Uµ>Ø<›E‚ÓL4Uµ“ª´­qkÅNççLR¥,W ÌbãÖŠÌ€}–`ß™WEŠ;4Jw´ £ú`“ävÚ\ß×p‡öGʳSÄ-"ˆ;4l…|kï=¸£ó_ª4¶6Q¦Î|”~ìy½{Vôâä{óîP&½çéÖÛ wì^±ÐÂóõÞßß_$Љ6p_Üapø\ÜawMaƒw‹®iq‡ñÔÄ´tt1°³*Uw8´o|w{‹;쌊;“zýÂgÆ…])Por›RNkTKw(ÿ\S+2{Øú^ÔÄǪÀÖÁâ:×ãæšôk+^§ÊEfÏ'ÿ »CH3£4àÔ›@.¥ÎÚ x*Œ +‘mFÇmý?*‹X ¥ ÎÊ•æ£Î9•~UÞk[ë "ȶkg‹×*¨AÎ${íõ}Ö@jnyÁ¥=µŠ$½cÃÂÎpýñÇ›·4šŸV]iëË¿mñk.òÒ" æ¸Î‘Ù©ðsL~õmòRdÁjªUd;0 Kì]T¼£>Æ“ú)mÏ×ÀÐ.§ƒ¦;TTÜsttö¨,©NÒjTg“Æ!«•4ãÝɘ°F›ª†ùü÷gõ§:ñæõDêŒÌ?üð dZ+Vx(–²ëýéDﺬHˆ³•gµ(²ç·ýîšl·»ccAŠ ¨‡²÷/íÈbF Ö½àw€V6ÃÞŸÞ3*/™üîw¥1 Šû¼LÂÜ>«þ­X/¶š ôUJ´ããy0Q‹12,’´XgÂ%à–u w(R²Ÿ[gПób,‰¿†;,Bù9U$| wXµµ#Þ$㽸C`{ w( à¼q©Ck'Üášm‡rï]Œs’S>ái¯'uG $~ÿ w쉊;*×ÂvÀü¬N¸Ãâ„Ô±Æý¢ö;ûî=+ ßâŽÓ\¥û®²ëÒoO#ÿ-î¨z±”ôîÖ{!`P^%ÁA¢ cu9± Ú­q¡ «ÈÅ.—ÎäJ mÌ&.Êð-ð¶‚[þ·÷ã÷— .´üìV_þÁŠÑèJYÒ'F.n;üVà’r•È­s´i×ì ì]Ϫ_¶>5@s^DçtcùÀ¹ypË½í ˆ4¯kÓÃN©XïÝÏWZR>mrpõô°­k«×@i’ÚäÐM-{e&=«Nt¢#Ô™xg+þVÓ;,èü… z÷gwO@-(ßsvY3À>£&ÕU¦ép®º•õS’U…¦Uí:‡ãûÐdïÃdEáé?ÎVì{õB’‚z2ÃlRJw÷Ú!W ‚\ß­”’êVE°]ÃJ™–g-½ÀjôÖ±Ò£VþÜ—&–ÒâJ‹VíD×q®DŠÊiû gµ¶_¤Bl¯Ø­(EÙ¢§ÈÉ‹BŠ’ DoïÉ^Á}ÆIY&çªÖÍPp£3î)ý*|×R»:£ ¸…¸£ó[:žŸp‡¸â °'ÜáY_zvqÇIDEQ„ÿil¸Žã÷â0íÊXèi¢)îXõ„;J»wxNIùµ“!î°Èå^¨ÝE—õ…)óÆŽ¹õç'Ü!Ò}±½­¯ŽÅ˜Š (p%³¡ãŠ´{<Ú™…" “-ÈÖ«Mp¿8-Ž>Í¿…;®y wXÀß8ÊÖÎÿŸ¸c÷ô¯ýëæG©îÙ¥D¬(íFcû¸íÑV¨FÑò³Öê«þºU+ù­r[ïîîž9Úk9ª@ÒA]°ôƒÇÇÇ‹!ý-¨‡‡‡‹EìÀ¶zÏi¿÷õë׋ÃXn©sw¾½½½ ­l†eŸ¿CÄÀ¢¤ª×ÑjĆ‡ì‡ž«$ÛÈMNÝ<¥xlÝLo݃ѵä)K5òš×mØï®î3ÙsŸ›¿•R“ËšPU[¼fUž•©àhÝp£ŠWVgt$î@ª’¤kKo é¤ÝYÝå·n7_³¶Ý†§§§‹™šú2¸þ6Ó°€9‰Y×îSéV¶®üFû“±õ¶DÀ˜PÉà ×ßÞÞ>wÁ¤º®å0KMÝrNC/ å.U¼ªj—•§Ñ*øw/Ê}Ú¹ÙwŒ¾sâ Œ¦ÀcEÐAËñ¬ëêlÄxa×ÖÃfÕÎ%¦Ûw§nRç›ôÙÚ¼¿¿îÀKµ¨ò™Þ7R¤¶vœ{ÛZüüùó‹Ãq‡¢üðL¶^¶¿J‡²(°{ßZ“ÖèY´w_R“éåêKóúõ×_Ÿ÷®ÕK}Mœ u¾À¿«rØÎG;ÒÒï*°ñóÏ??«,Žá0†ý¼JQ{¾{n-ZvÅýóî¨J“æªb)›+Jky w¸j.¸³çîî|Â&E‚ÃÎJ>>>^Ìüì Û3qVÍÙŠ­/i¡[Óš_WŽxï~¸Æ3VJÙ5Ü!˜µ(ãóÚÿûe@èM6Ü XŸžÎÜí9Ì'h1}ÖâMvUdÔÐuëUŠç0‰ôö]óp‡…,=a¤û‹;ì>Ÿp‡ì¨R_O]i½¶7íPw؉îØÄö©¸c âgùv~.yÙ»ýóÏ?ožžžžïaßñåË—çç\Üá,îžÿö”¸C ˆ €;?V .gÄjy{tÈ âZI)mFÐs’v(½tM»•›]àvžAébè%‰®«MŠ÷gU­Úuè]!ýF‡kí29ˆ®,e¥ V)uÞ#¥q H`¢Alg ­k¸DI¢ωj ƒxé€U¨+­D K½qª hÜ‘^Ù8b7@ÇuÕpvh„Ì»Wì€9©x‚©pUÛ^]ÂduO3å½%ð—¼[­´ë/ˆx´“açekÖ‚†Ý¦¶à½Uù±ùKøö¬¶7·§¶Ï÷s}ž{¿å4®h ¸=ºq…‹ªŒéáÓŽ½]»J5UuM»Ÿ®â+ÖVð7ÜW¥pî~œ¡;áŽ,ȸP@ ¸ÃY1Š´ÃÆ]±ÉîGÜaqÁ3Òn›ÏEÜáð»ûÁ󸸣"/Åh§ºjsµÁجƒ¸Ãæ €JHkí°¢3˜âŽ“W×Öô5Üal¹†;,ÚŠ;ªÄ'î6(î^îLÔöÆTGÅ2 Ömzxx¸À^‡cž·}§Jvc²ˆ½=!îXáÿ$h¥´üîw1Á¹—Úcˆ;Jó.î0N_ÐÌ*ŸW5‰šÅ•Ϧcl)ŽäZ©ÞM.ìïw<>>^Ò•9l@±‚g‹ZSºe¹{ø[”‚u«¤*Y ’ëêZù<¯Ab¥ÆAg+dÒaüE.]bžÞמ¿•½*Z©Ïï\Ž|^7×î¡B+ÛÛ¤= ½f«RÞŸ nqyìVml¹Z ®š†÷-=NЇDi Òn¤¬Ù0ApÒvñ*Rp:ûPnö:t'­~¤Uvœir½úŽOfºÏWÞÚ™”Î/Ø5¬þ5VÁD­Š+€a,fUêÆ’ørÖ}¾»ÊK Ò¥…©£ä«I€‡j©Váa‚›k^}ÆÒZ¬rÚ‰”V"ðò{ûl]Ïô‹Ñ¨2ûRjÉÙîO ‰ôC%æ»> `¤ùù\+9kQ¤×õZqg8vª%J;3†«X·ë]a€LÃ>Í/k¼gA¡³(UßP)¥ª´jM±½gUýZ|tý˜P{VJ+îØó9áŽí)i¥tÕ›£’Ë[T€wèÙñÜQJ«c ª¼†;Ö1(uÔ¢®*‘&ËMBL®Å%š!–¾ZÜÑ™l=v¤ô9c‘À8-u¾¸£Å”âŽÎîVù„;<³¤ñÿ'¸c÷}Âv˜*Zðîh‘Ñ™¼ Ä5ZÐ,î°P4EÍÿwô,S)Î8<ÜaÂ_ÜáP¿9„x«3fÇdf fÀÀ໊œí$ ¨vwõáu®)[>[‘–Û{jo.{³Ò[ÅŠCÀ.4ù‹’]pZUÃj¡R¦:”{Ø ÖTŲâ_9Fƒ»AZjC•½<,ÝXû¼UnT±ÚÇ4 Ys¿VŽÉé6_þ¥’¶Ê¼ ôêÙâ32qíðãªjºKïù ˜¬Bí s–£¼^Uðª¾egK 7ïic <ÖÝk·@v’v_è8¿5ggÍ ú®Ó®ÜøÜ»/eNk^U?ý 4/(«lõ®Í¼ „]šøÊówððTu’Ra2£‚ÝiøÞ8æ^R:s׺.h•zhêæ×Û™–}Ïh>ë˜:D^[@U72ÑÇõ©¬û~ßa]¥;O’éªéfEµnÒÑÞÖ8´qÐA^g’T ´sX©£ª¦Ù3kû¥ ç=ü%M¥¥XD«ˆŒÂ's9§8v’óo2çz²‹¯ÀŒg˜€ßù7½çªÃЕ‚õ{·¶¶G¶æ¬n· ï:WäÁbY»·'ܱ3Ã}çÜ”Iª›î8yé½wje ”ú§¢ÊWRÜŸÆD÷€…‰kœü½¸C†‚¦ûYc¥³Ð-w8åÜ^ Ú87dÑÑ$XÜ!–8áí®áÕºN¸c¨îXBgwßbÅ[¸cïø„;:¨ÂBªúûž5íÙ^SÛîP¢_:°ª}%ýü%Ë?üðÃËd¦í2AúýfÍÄ´: 5mþ%:µîçîïï_˜hº¡ë:Úá!g%T:ñzš¨HG°‚¾DHo”*‡•Þa¦iÅWµ•)ìfmægÿ¾ßk»M©kÁšàr äDYQÀyyºM:åH~þüù¢ºe S!«–u2X ¢tµªf¢aÇnëC0 ˆ"¶GÕ5ß$ÿÕ ªO‰ï³t]ƒ z=&ãéç÷ í€c ÅVí­ñV)&Vݬ†UÔ Pe½^²4 J;PJ »O­^é©dµsïq€q<Ýý쾯ó ûއ‡‡ÕfæÉO’®òÒî÷—_~y®ìvÕÃÍ΀²´hÕÚ]`”N©vE<Ĥ,Ö.™Ü»s¸~±¥t;A`ãz^P«N]é%­‚šÈ¨|cåÝXi‘­*{UMªÑª…4+“•€µãïìZ)¸]äì»W¤rn­,ÆXµ@7YReÈ®™^PVØOØHLd&7m'm.ñ[K;‡'_.¬Ï„Uå“@KqG©€®…ˆo?9ŸW‘€ûûûÏ¢ŠtÅC'Ü!­øZU¹¸C *UPIü×pÇÉDixcUqÇâJM^‡;ü…7ºÖßÂÊ£;kä\òÖ‹ ký§Ÿ~ºyxx¸ï¶£W±â»#×pǺU)+îPåLöÀºþâ¿ÏDÃDhÉc;oÎ6¹UeSIo ÝÛ \»lײx§gx;þ&MÎw´›×.Ü)ÞŠ­N¸ã43fAýEg¦5VÇÈ}ç6’j?nfAw|oÔÙ ïëP¿CÊ`6€Û¶¹tµÒJ3óe æLæö’kèfÖë}xج;â0” Mj”Î$U Czòj7(ȩԧY¸ƒŸªÃØ)úÒdÕ ¸ƒA)+Vm›o`ZÊÚI‚q`Á ¤ñÞÞèrmsšHìŠ ~ViÙºY5³´L“p;§nÈ© l&PÜk¥eõ^o¹ì'»¦ë± øD«vMÞ ØjýW¯1H“ù ¼ì mÈÛîÒßô ÐÃâÝ/ÅEœ?*=è$KYåE•ÒŒ‹V‚kзõïýWÕO5¯v¹Ë÷îÏíæ ¬ÊÓ6±P±Ëã«tëÒ™ì¹æŒék­¢ÒŒŸ®á“ô°þÎh®’ê³{° ¸¶¦33,ñèܦï®ïÜ÷ôððpž1KM5Yþÿ_ýõ,È!]ª—^B*5Iö9{6†’w°:®Ú§Ê_{·oá©ÔÆ:»OÒ[ji‡§…%UºÄÎÆ¼†;,ÂI…µÿßà™ ߃;ìäW‰n¸Ã5½„õ„;”wwˆqì~ w,I±pUo2•OÅs;Þ&¹d‡ÐÝ#ÒI›l=·híy¡XBqG©oÎËÊ^*îÐ3¬¸£sÔë î»†;d¼†;:gåü£çpq‡Å‘­çΞ[h›x”çà{pG©gÉŒƒ±¥ Ø…±m¯{²Y»íS%ÌáJ9VÌ]ô{‰¶X¥9Y-)Í¢ƒ°u§U  órMõ¿P¯Þ!f»[@*ù¼f¦ªÓèÝ£Œ´³­Õø¬À©ÜÖÊK:@]ÚŽ™}$UsÛzPÁg¯™ÕWÛ%É—w¾®ž2¡V\:ØØûÊÌ ¢¬Z¸ëÁ° åáeµËêhyÛ55l£<`Á…I·‡õh Œ[7VU­Ym·ÅÝÙ­•U4­$y¸:÷p’öYë2/ÿ¼³g&2'¯ŒºŠËÙõw¥#¸G+U«òŽ «‡ÍŒö|_>Wã¤açÝ&Ô±}óšärcSòt¦ï5ù³%ªä¬¨Ka³Ø`·^…´O:ðl\©à±À÷Q©uçêé!ð–ú¡À‹qßäÀ"ƒëÖ®ÎÏ8+Qcävê:ǣў{gÅRÅ*ß*U²ÒòÒŽ\³íâyNw&¡*«Ïz5­Sc·Ì™ºâ¯©ƒÞv)<3jzÂëbžÌ/Kgsž§ÃßÎ øgõ’z wXM:ïÅÎi\{ÂíZJq*…wCô& #Ëxq&X Õ w”µ`§¸£ßofï|g”âžõJÑÿxþÚíñçÅë€Ø5<á©WÞkãlàK©ßÚ,î°C} w( #ÆØ©O]»L¥îü»%MzžI1”)4\òŸàŽšu®3ó£m»eì pú8ø¼¶Òª"Õ+*c9WV îlŸ6‹ßM9 ¹Ï× ØJd9&ç9@ã!RàäAºªÓããã³ì}zÁÅ7(€£‡›`·j¶Hrz WIÜ=®,pVºp45]h;àÕ b5xÕìU5trkø§¾³AngvY)ÓËA¥™å¸ýù%P{3ÂÜzøuM«Ò´õ¶{\⫤áîEÐé¼Ãî{û«ÃVð§@bµzj+¶uõA°âj‡nï¤ÎéÎUL&ÓÄ©†ÚO>%®é]ß¾«CM¨ô¼ç,ØOߊ¾ÊU[óJL:'ŸW'îΨ}ýúõBj·b+‚ϧ§§çë—‚¶køðáÃEâ¼5wª$+u­ÚNAo•$¥ûùV¹W™UÜÀy«ÏŸ??Çw%žKû¼=Á¬BuïÖ…|@l*„¡QmÇØVe(•ðŒ]û÷Éä— ï^1YRÑÓN› }bŒÆ~‹SVÅù2¾m€|{ÕY=ã_ýõ¹+mCÚ‘ÊsgÞ%DZ8Ø9ÐØnëd…›­“vt¥•j¾?SÈBν¸c÷/î°R.·Îvní,>}î˜þb¹¸æT°ÑàtŠüñ¹¸q wXì0qw,©²öôôtÑe˜,¯Ê“&;'Ü¡€ŠÝc¢ qÇ>Ó}¼óftÄâãç¾s ×(Å{Ç]Ô¯¯rõK¶Çh!Išµ ižÕš/Ÿp‡sÌήUÉÖsË‚ØÝÝÝUÜ!†(î¢ë<ð(e³pØ9pÂ[OS‘Ôj`ÏGÊã½Å©íÓá šn¿w8‹w1«÷ÏþóÿüþûïÏ7<þy«E§áb…âíÀðä‚ìæ/<w±‘™±->==ÝÜÝݽ0Ý2ö Ó9~ Ó¶´¤ž HHm±ÜÞÞ>ó$uV-äÆªÚvúž^ú‰;(z‡¨Ã©­z{pÚf_’Ögµr÷=Þr£Ò ª²Ô¶¡Á\Ú|Ð’¬œ+D°ÊÄуP0TC¬ÊlÛÉè[yµr¶`¶À¢ZˆAPz¤‰Ù>w•i R0­Š€U êpõ€Æ@‹&§} k÷zXxVç!Z¢ï¸aÕqì^–’a· UÒàXvNÈà¬]¹ÁÓÌ_bâ<Êx»<5M­® AùÐc%uw—ŠèzÓ¹YÏ %¾ºH× OZ‰Å £kq÷º¸ÚßÙ= Ðí^{<|÷ìUܲ¸Pz–×ôÖ<ìºþñ\È`omŒNZwô½¯¾Wç>åÀï™lM/Y%oWÍØnwR%&gŒVÅ4n,Fyèï¹[­·Éžó¿ßµfap?gò»ç=š™={E,öî¬rK%­¤îÎ~;ë£(í|wH¶Óuê±kçì©Ïÿ×_}ž¿° ¤·¸C‰â*Nj{°8Q äŠ6“ IDATÔRÒ¾w8+*î°{ï5 TwÔ:áîø÷¿ÿý‚ViA»3€v‰¿~ýz;¤VwØ…w&¯Ô^)ìÒC_ÃR✿òýÛ±ZQA:ûqfF€~â7* 'µ©ÕóUG¤HGX4볓1ºÆºÕU—ä¸ Œ Tõ)ȸîšZí­®ý/P<ì;À¬¡ŸeÖ¬Œ¬ *SÔ«¢Òª&QÚÆ„AÁkÜF]¥ËáÂÊ^ïç[˜Š¸ø«¢"pfÊCòÄã¬4xgJŸ1¡±-[7zßýÞßÖ´@˵áábÂdwÂàìࢭfƒŠkQÞzåXOþ)$<à,‚TUU4çt¾i1`ÉŠ‡^±œ…2‘·]] £U5=K®É;Kqâßô-¾Èù—¦#/þ[Nž[{[úÒ´º)-°ÉR;wMÕ §Ø×$¾J?®³­éªú­Z ¿ŠèºŸÛã®…ÅÆJHK±’‚Ô5í}«V#æªUšD)l!Mªn -ªHûP®Wžº´‡«·Æ”–2å^ö|­OË®gÚŠ‘üòË/7···ÏUUi¥5ë3ÑW­Ë¢ÂüâLÊV<ezàÞ¹“žo&O uX‰­Ñ[¸C©ª©Öè-ÜÑj³¸ck}…Ì×pGç¯Äõ@ÛÑÌîQg[¶Î†;öó+4Êt°ki§¨”%éµâŽzFp‡÷-îØŸ‹;z¾:ƒ6&JñÚpÄžµj±v)߃;¬àÛ.îPêݘ곲Ðu w˜wOw¸¾wÖäˆ;| Ôˆ;d¶Hqs͉;zî_Ã&œ|îð]wXàTÂBÔs2³ÎÌ*ù*kÐõôeœ(#[;à:8ƒ¿T®¶¡ ¨òäÍËÌt´Ã¡¬ `Çä‹\%DùúQÔ¤R•º–«f–ÝÃCàäAÓAß]KEÔ6wñ™˜”NÊfK¨¶Ñ8Ÿkïߓꅋ¹ ‡×:&Q߀U‰¬‚™È/-M >KV€ªðS¥2+R'B½J jVÔ@î™ú9<ºªÍ¨™*à-w›•niWQ®¯ ÁàÙjªϪʘ¼´Û{Ò½÷BVEkâ SZ¶ÆæTF¶Ÿ«pû¬zZä8Ÿà³· ßbƒÿ8ã!¸á×RN­*oï¹åZ»Þ[X’ Z¥KgUš8ZÕó0”²aå²ÝÈ}ߪõòéífìž/(va¬ô»;ðêêû´[\±ˆÕ³°…4ãcÕ”:î銣Àœ”8Ë\PžWñ¿wñ}qÝ}§÷†~T=ß»=©¼o†}÷»ÏÅèâÏcV?/î¨ú¨^ÏpqG=xªô´w#³ Ô<×´ÅåruvSÏ«åí´Z=×ÿF*ggKšàœ„aN¸ÃÜjyc˜‘ÎëZ°1N¿…;ܧ®3i±'ܱ߽»»{wÔJCŠ\±È5Ü!µWº½Àü„;ZŒªª©¸ckIÜq¸gõÜ¡ðç΃;L@wVÚÁwTqò5ÜQ ˜oß¾]vfVµ‘C«‚ˆîïétÝ€¯ZˆefÎYŒOîç©| ¹\úJ¶y9ócõfß³ërfc d¼Ç¹¹(wXÔ¸Ìe%ˆüâµà:ô*¸,e@_ãîu&VpëX^/ב«–Uù­F–JM*ãª3·‡£&ˆM( ØÞ²«¹g¶ŸÝ³ûŸÿùŸ‹jÇÞ©šÊ[[™UþV§ß€=ùÒ¥³ZÁ³b·ax)QVôsz_8[²˜4Ýžïb„4Ê&]-Ò5¦u‡ogwkÏù“ÿvöþü3»¾•ÇÞsun×b¥K`Ð º­šUêê¼ûÓÅYE7©BVAM,åj[áÕÛÈ™ ϹöÒ ­[”ùüùóE²ÿi ت¢Îëz&é÷r2’kLí,•žJÎx˜ˆíwL\¬žnÍ-ÁPbñbs<{W;å K±’+-KA‹‘ÎGØqóüo·Ånêöæh’u_L(î°ê.ð=¸cësÏM€ºÿ^¼—¢* CÜ!x“6ë:SnØj·¸Cà,EÉ­ó_¾|¹Ø;gj˜iœ•:.Ms±z…Ûý¹¿¿=fçHÜqŠë{¦v“_ÃûwìÜÚ¾‘½ãü¬]¾uˆÊw¿¸C߯5÷ß[g×p‡þ>;ƒÄÛßΤ‹(Ö Šš…e¦õÄ1žŸ—í#ý±#î?q‡E ®-¶žpÇ©èow~Ý¥ÿýßÿ½H^Š;*€2Ü¡’…²ý÷E2£’••4+‹>„ :òîaÍ)´'µ§šŽ9äk"`–çðYú¾×LQÕ'y“V‰j8wwwwÑ’^¥Ì § áǼùã?nnooŸj5³D³U®º¬­Ôm‡÷<ª+¯ÊÙ·oßnžƒ¯ÏÆ ¡ÕH+åV+ .”‡^wÚ]×x»V¦•ÔF³:ß™æû¾µ4ÒÄvH—>æ°íîe¼ë*·Ø–vþË¥ ¡” ‡i[­–¿õ7Pë`ºÝ¿m~T“ÏOŸ>=ƒƒ­ñýwŸö™_¾|¹ùôéÓ(—¶© LÛóVæUÿQr|ùž÷¡†tòÈ÷¬–¾~ýzsÁí®á¤*¥R­"í:ªÕÇ{©JÕÞÓž¥•Ï­×¾jI§™'«âzµh.hbÞnââ„{NIÒ½#N‰¬¦‚Ò’LdUmrx»êdάHAÝ]Žöiþ¢ô¬]Ãâòâu –;³2qƒ zX”2ÉÝ>±Cf'È.Žñr⻞% R윳ÚûyxxxNÄ7ÀîóSyªJHVc];‚f+Í‹“'¡‡*ÅÕœÏs@O®};ˆ‹¹®% í ¼…;|Gšž~/î°û#Ut¸Cö‡¸cö?ÁÒëögÎ/Ò©hÇi®y³›+w>ȯ*Vòþ½¸có[Å¥þõ×_7Ÿ?~N>œÇ²øwÂb¬âŽJC{vI”ɲùÅ …œp‡ y;ïÎ<*P ‡_gO¯á™7 üüóÏÏôé“m„¸ÃD¦BKÎíûTê4Nïúv®¼wXè?ᎉ[Y8<á±ô„*îïï_tÉ4‰¾Hf*][ùA5¤wcÆfsã®ËO]t(Ì ìjûÏÃËÊ¡òœ5“¬œi ž ¤”c.¯Ú6žY³ô#Í"÷Â5¿<hÛ¥êÍ›ÄlƒkÐÕ6³-X+ÆÛŒVÙZ5í[ñ‡‚ ‰|Túª¯øN¬jÖû¡çŠ9T9ÎàÒ`ÖêšÜh¥S÷Þ â­LYÝQp ƒŒ•ŽdzˆØ%ÓQZê…Ý+"Î]yX*lPÚg)^í°¨Ú&ø-ýtëj}gjJÓ+Aõ%=•¬L{À9§fÅhÀЃÄÙ)p}*KsP5hïDóØÒ@÷NìrÈßT-É<É¥ëaäR…Ê*{àoMï³Ñ09q©:Vqíx<©¶&[í[|1Ñ-õËßëÜT½¤bT9¬²Ë­T×a[¡=#‹«V+Ðù“‚…%ú¾çzluÐJóžÏºõMŸvÞžäý[3^ªšé¹Ôäuâ:^¯»ïvgTP2nš@Ø­vûî*÷¿õ§ÂXq‡Êªû®*7J'tX¿sâ1…—±AÞ‹;|ÅÒ·ìˆOÅ®áÎy~™ÔKó;‹;<—N¸£?WÜѵ-îXì>áŽí׿5Ü!ýø„;ê{´sÏç Ú[=äÜW Sx«¥æ›\¨b(ÖÛ¹¢óÞ›]q‡ïÂÄf÷rÂílÔ7¯þ*§)fUË‚îP¬E,]Üa²~ wHÞwvHÖG»âÉLU–ä7+UgëÙÁ¾J)÷œ›•k;ÕõöB}ffrrm³)Íëïx˜ëÙѪM;#&!q%4m‘dê1€#§W`á Ѫ3r–;¿¢2›ƒ ¾k§Z5w“,:¼Y^¬Ô'Yµßkhäõ™•wvÈÚÉ@¼ïšÆÖnå>åO»±¤_ÕdÑA:ßaµÒ Xõ’±ºº µîϨ³]5²tkôéìIU™êQáÏi4«X€àËaÎíùµÓ¥EYQÕ «^R®­Ý×$@ë SS-¥Hë)±Û€ÛìÊøFMÞÊ1|{½îñV¾®¹~ËÓö ”ê%MdUO°1º’®Ø×ê~3ÉÓ h´>ã›æÂ•35ŽÔí¾@J²µãþЕfѹ–s?î ï»qvq£³S7ÒŸÇY«šN*" "ÖŠG•—×j > R}‡>ÛSŒ–naõu‰a+ÈÆßÊž§:©,zî9×>wTŸ}{ÖÄwŠ;4ÎÓBÜQºæÎÐ÷âgeN¢×pǨk®çîhÂ-î>g’tÂðR¿N¸C꨸C¡‹Î;[K½3Ù«zæpÇ®Ïb‹joáŽÎ#wôLmbZïÅyœ[3¹jñÖÙ“uÖÐrÂBóižÈ8+¦Ó½¸c‰³ç¿²çe-IÉ7ÉõüQTÃù5;¬e†ˆ¥M(^Ãí`[ ©”¸c׳øY¿/Töì/’™Fí°½[³6«&C[ø®«³ÃçêûצCk‚~+­x¨mn"bÐ]7E£L©lEu`Ì»` á¤œy«2mß8ååïÐ]E¬CµËŽuDxp=,5 ì^•N¬Ð/0ø®«Q@·`¶voÍ5œäi¼·Š¡•–ŸþùæóçÏσ¿i±ú& ÑÔÍáqMÿäÅo³ ÜOBV=”²51sލV íd4öÓ ëÀu±ç³ê±Üa» ¶—ˆ)glkõî$!]ë§Ÿ~zvzV±§ô'+^òJS2ÝuioÇÃÊp«ämÝwHRоøæAT9a)²vìn-˜6¿âîÉJ¾k½ªÜWVºg³ÒZÓ¶R ·þŸ&,ò¼×*®'ãÖŒß÷ÝRÆæ'áûSÜÄÎíÖôž×ÞŸb#ž±r:ZÌ%AÎ>Ø9µ'PT2ïK¥"U%-z¹ßLVv¶•Zb—Zpϩk¿ó"ÆieäRš*Ë^9z¥ƒ­f=ÇÄð×p‡ÑvRöw50<áé“‚ÓïÅRè·ª^/,\lîaßg’i‘±TÈdŠ;!°n—¾¸Ã„׸ng¢¢!¯á’×pGÅ5Ã>~üøÂ°y¸Cùiϳ­¿uHG3Þ{||¼ùøñãwáŽÎÍšdI¿†;|¦5ŒVÐÄc̆;L8|Æ'ÜQ“K½ÐJ_wè›¶õØYðZuü'¸Ã=øBšYe“zK˜%\Öf¶z¦„âùnzÙ½Þ¶mYZmKÝï÷Ðܦôá;·!˜PÃ{Ô¸ý£¼§@Äàê(í©´µµ¿ ‚ŠÓÁîq^ú¯xM¥"m£îû ð‚¶=ÿV~äôªð¢–ÿîMg™Ø"î¾×)Û@^ Õj°´Ey΂ïy¼N æ¬ð œ™¼›°l ×!giQ‚µÊ´žªE/àIÚA²`äPâ†Z÷jÞob‡ÉxÎõbÒ»DÝûš1šJ3*æ½üW+Bû©$íäIÛ{Ü{À[Y+ø°m^ùÔ*kÙ Q‚|Ô3•À,âtþÍ$ÄDN0ì^³]’ÐÞóج¨qxR¦VûKŸëšVánûNP»½áAìúª«õ@í€Îh™™+P"MÂdÆ=îÜÍ>ÓØ&=BÉøö:?0ªŸE=w:g00‹þ³Îƒæ¦®w“Pu÷¡ô“·Wu«†zÒΜQ2¶ëW³µ ÿ›3' ¢Å “•*Oí¦z¦»N²¯•7>wb-&¬¶ïÝ:G¿¸ck±¸£RàÎÏt°¸Ã‚‚ƒÔ®Aq‡ Ž÷¤ïN“Ò·p‡³VÅη¸®ØóÙpþ[¸ÃØ_ Œ&/~—L†×pÇâ²tÔÍfŸp‡¸kXk¸ÃÎpe²;l_uD±S=öj¶­âš&¯ Ä?>gñö0”~8Òb qGÍÎiéžîØþ±q0Üášv ®`9vQ%©¥®ÚÅ=áG&£>Û‹d¦FˆU!² Ñ ¦~úù^ZÁ‘­d©f²'*Ke–›ç¡^e‹-».ýìr%½é&hb»&>šËÉ¿÷ûä [-nXÞñ>cs&ÒTè±Zïr«Ðs‡owMåù[uêP·Àì$õª^ V^¶ÙV1±U]*‚²¡§‡#OUwg zHCÐi¸tH¥¦ü¥e•;j®,ñÞƒ4c”*m1`‰@¾I™~ 0$ýƒœIÐ<× oÅuàJ‡j÷ÙÞ«ŠO6v·¤—æâõZ(Pí§s>5„¬ƒ@ FÁž!&Ôk`ÖùµšÎ.vœ$`«hµ[НŠçiVW‘luYÀç¡)M§(Á’îéŠ?lïk>'µËCYÕÌÝcA j@Ƨ­ÍaÆýÎD•¾"€è »4¼=+öÒ8J­°»å@¯>“ÊžÅ*˜Õ·ÂÄÝ‚ˆ ªTÓv^-êTqT¥>1„’ß[·¥a*«+î(¥ØkÙ½¼†;, ^›wx w\øy/îЄ²¸ÃäÍ9+×ÌIáÎ5ùŸàïÕÊ}q‡ÅgQþ_â“{©vÅvJí>ZT9YjtÄÎC9›¤èÎ*÷¸´vc£t>qG½àZ”­ÿR•PÛÕò9œhÄú<{V€3þ›d–v­’ì w £ˆ;j:ºk˜¨Åp£jƒ¾G“›%þ'ܱ.ä¿þõ¯›+oY…“egVG®¶)•×Tºu`Í*¬Áª ]UÊ ¤'-þ»»»‹@âwÚf–Òæàš\ÿr䕎Üç $[]…e•{o3áI;K´ghð.m£ ¶˜•¢.€t˜Íê§-Ö/_¾\(¹8Lf½÷“gmxF°mÛ  W}W~»&—«PDF)’ 7nk•”V3)]eU÷Ù>Sj±U¼C R¯À×ý]pk'Á™ ×ç®§úð­Ö,V £ £>-[Ïû;%}Ý_Ÿ?¾pèö;1®A;VàìöZÜuÈÖ»§òçJ]Jar(prê’Òoä‡H{)µEZ—ó+b®§Õo]î¾ÛáÒ¨qUz×Ù®w‡®ÉÊhN­€NQi{mÏyQ}!ì8X5–ÒqšÕªÇÖáÝÝÝs5¯³~æÞ£]tyÕ‚|×ûb“ëoÕV)0_¾|yVêÞtød)I ·5mBéšÚùf§K*‡µô“ÄÅ¡‚Ic–£u¾Jav½ÖœY*•àÂάÔÚ,«óÒ5¶»¿¿qVœèpž÷ª)_^§óâiÜVž‹;ôá9áŽVͯá÷W»qI看hÒ¦¤¶¢$ÎFäŸqZÑŠ;Lèj@éš6ñÝŸïìwfÎ3£¸C wìÞÞ‹;´0fWU¬tÀÎ ¶êïù&îи½ÔBe®-®ŽúÞ.ÄâÓ w˜<í]wÔ[¥Š§Þ“¸ã“¯áŽ=÷?¾ˆq]›îsq‡bLbÅ¥­ß=÷ÎRO5V bÖ¡ßþ½¹¹¹T3³²ZéC«Î“KÛË”°ÁÜmˆxÁšÙ³Ø^ÌS9zå^ï¥íÆj¾·kÞÏzó­Æn¡ T(½,pŸá"þöíÛ3§Ù½à«ÿÄZ¶Jm–jåÁa•Vž¤`I¹w•¦‚¶&7ü;÷òµ¾­íÀ6©-ïÖŠêÖ€|}[†u+³ÓØï!ºÊ…kaüÚ™Ýtš7ù> `&‰uÞ=þüùù9PÚÉræä4À»ïòð\ÅgÏ{Å ouFív[Õv"uê†*ûY¥¯gCåíŠIؾùòåËÍýýýEe’ësªìuçI&œâ|¾&˜v\BúWX”[ pÝIQvÿ-N z[!5iUæu×`ò.ÌY0iÒÊ2»?Ü™»Ÿ›­É»´¤ÃV¶Û¢•™ùlHi[²0¹s_o—š.zßÙ} wì(¬cXAœKk‘1QjŽgEŠ;ìÊØ°³Q } wô3¥XÙÁw8G+îØÙÙmRp:lSÜѺâ÷ß ß'Üa7ÙÙ…|¶¦\&íPˆ;*™]:¯]ÇzZíÝjëÑy¿ÊB[>á1“ï~˜EÜ1j® ä’¥‡‡‡ç3}¸Ãbtv‹?õº²«#¾töô„;dƒìþN¸C)f©Ú[WªÌY°wèK)[OþüóÏ—òðTGñ ÙÃÒ˜K*A]°•äµ…¨ù• E5(} lŒ¨W¡4Pœ\D5­ëàé6{eõT€ØFßpf© «d \I£ª…2œ.W1Ip^)>«n»Ç©ŒHh%ª`¶<7ƒ¡4¥T†­ ©;XÛ¶’ུÝj ~•'&9²zÝÈMUi £j%~FE'ªbæFvˆ¿ƒ®¶qå÷ž”\*…¾äA€e |ÛwVá…Ý»k·NÖ V˜ˆZY÷ÞŒ Òߔߔz¨oŒæy¥‘`+qís²RXùæ“Ó¸êQÊa›Ð:(ïÚòÝ/÷÷÷/æ_¬º&M;ÿ3³à­ !‹ŠØi¬ÉëVšÖʳݦ=ƒª7ù~ìļv¸¾žRÁèlÅÐ=ŠÑa¨úT}ŠdVÑ8ù³tmç—3†ë.¡ÑYÜbÈÀ¡ Kg&û\«ˆfŒµBk²naž5Jµ“¬ ½ ½t7iAÌ·Ó 3¼êm*em?ËîP5®5”ºw w˜p«Vç:r>クCúµæ–ïŪVy-w.eQç„;Ü[ÃvY߃;ö§Úl®3Dõ5’Öfa¹1IqGUÜìŽú-dwXÚ¾=á‹èÎPp‡‚(žÝÎoTÈeûPÃsÏ) ÓÎã-Üa|ël¨¸Ã³Lq›k¸Ã‚’x}¶/ïtMÛU“V} w(øµµV2¥¼+N³¸ïÙõBÀ!i»2V méïAïV¹G«V÷”‰äJ}X5W^¨^*9´ŠâKqè̪»¾\£ ެH²8\å#g}×ÒE<#êëà»r½¨ˆ'c 3<Îãµ{å5ê@.`wпæ½Îó*7ªåÕãÉ΂ *7 H:sâ`lgöZŒð}íðµÓ!|ÉÍž‡×à{ÚòúëåQS‹0å|woíXzÀ6F«°£œ»k«h¾ci-u‹®wÀ5¿ %}Ší uÖÁØR2c¸…™rçNœ9“ jòìïø=ª{Ya® ¦Iî΀=Ã%£l8/¸³EƒY W'ú sÔÕwÛSéÕ]ãÖ¾TÏ •á_Œ\—RÜ¡!æ’^q‡J©'ÜQYæ×p‡î&©ÙöIEÏü“ÐŒ×VÜÑ=Qñ‚â‹5ÅÅÅCÅzÍØÙ6N,ŽZØ’‚¬ÄqY3‰‘Ö™ÞŠÑìù46¿†;êK³g¢8ˆ–â q‡b‹é&Bþùç3ÚøY¦Bq‡ï¤Ý çÏ·WNèž]'ÜñÞ5íØ†‰—EØÓÌ»¢(*´žpÇ>×ÂÔâÁ·oß.“™j¬ï4h)m§ŸƒÕþq :c·ÌdÐÏÖJ-²ª¤d¯Cð&ÓûÞUÕ7«dæúÃÃÃŽû«O”Գ͑Øá©@ˆªk«ÒIùé§Ÿžc—ê„ë0mÍíØXg¥ù»g¯K  ì¤U¨­@Z…låßÃËdd€ÈõìlÐö€òÉ\ÎÀž5œ,=C°·½¸Š»]º>\tïË40înïlO(ì²})«@°S_'+îÎá8/`‡ÀÁN¸ïxïçãÇ/´$v;Káûïu*@!ËÀ5èY¼ßÝ:q/›(0±¿ß¾½¿¿¡¾5Éd{ëØú´B¿NŸÕÀÝ—¸Cùæî轞pÇ·oßž÷îªØúçUq²¬áUÒ^Ãî¤lï›0Ùµ g窸ã4Ã$~ w”ú»î¼êwâãÚÿúë¯gÜáwšLw>E ëVhB©·p‡øRÜ! ÀegàýýýE1ŸýîÐZÁdzóâŽ%~cÛí9ÍV•sß+½k1FÜá\ºÁ×p‡çµ39'Ü¡˜Èöl­âG7,¦u~ËâùE2ã‚UrP©>³¼/_¾<nY¡YÀqH{ÁÖ håCyYÍãLT̲U@)_~× ÍÃ@Ój·¦}[p œ&d 3cZelÀÁJº­ué_r4w0ºÃ±•"•7^P\IÇU7¬¶wõáÇ‹lwƒW•ÏtÑÄÐ `g`j†¥<¢33y¹9ªFg²4 g· $ËàeשBƒÏr·ÕËWsÝjO«Jò†¼³•,]±Æ_ª—Ô=¸êgã¼+…+Ýeÿ“:eõYnôq€jnVe5c ÙÍrÎI¹ìr®¥6Éï¶:S‰Ø½%?7äê Õ@I©`}þ¶ím[l°â+øPUO¡ÍæL½ïýó FØ­ªŠÒ ö+×k²!î#Ö«†jV½M€JM0qPVÓØX/©…íÚÊßç¬3åá~2Q>It;c7àT1•Š"TÖb“ñ¦ÝHª]me_—P ŒÑŠ 8ç©j˜‡½L.œMâê»]7À3Cu¶“/“´±v"¥9Z¨9Í Jk1ñ+}F·p‡]2×Fizv-:SU‰ñkÕîJ¯´;áð½gÊp‡¢<Ž®á)~&jµ>ð½£Ýkv΋;N¾J®Õá0Å\^Sg|g£õ¾†;öwªê5€-dý'¸CEVVÅv«ç3´™pÂRìŠ;öû/ÔÌZÑw9œæÏú¥Ë°qÎO, UÎÕ ÛJ…‡ƒÉ En±•¿§Žö ÀfÂ.B«9&dJ¼z¸O9F~âãããÐ÷ÞXôeŒfR·u7 Á¦îjë«:e…ÐMd‚e÷b÷æPi)Guý",ÿwÕ‡Ú¡òðìÕ$NÁÕ. ‚•€tþª@êþb¡Þ2ÿ;STq‹)bq‡k¼Š’•ˆ>u‡¯áŽÎ-_Ãvw씞’ã6¨6+XÖIбþ½¸ÃýtÂâ»®Ù4âçWN¸ãäµUsÛuòõKRI±¦Á'Ü¡’ëÖ¶Iæ~NˆÔ{cšqÙVGNÜ+ë„îçöï²´Hi!Üuü‚f¦Ú@+M{‘[\zXÔ$k‡QÍ¡”´ê³ÖÒÀƒñfg­ŒšÉn8ÔJ¿ AºDÍk¶g°ªÜŽþçd:c`P´Åç}*§ç‚•’RÇd;ARb¦Áo0´ÒåPèþ|‰×:SR~¬˜WÅ[WG?‚rkjw33¬i•àÖ*ÉžÏÖV}ŒLÐÌøëòÛáÿÑŽVb4Ö-x88“Uidi3VOUJ³Zn×΄°÷WyÙ*{(ßjµÃß³Û°™¥‹ë…£kð~Ïç-p±u¬Œ°€Ö!sÁ¡ü‹=M·§Ÿžžž¯yðþþþ‚Ôks&Ø¢ž¾a»8D+pØÝÜs¯"ŽÔƒr»÷œ«êÔ9*%­ ‚ó@ÒÑ–˜oŒYTq]ïÞÖr·›añ£óR÷y †(‰jO^ýÀ¹JFºÌËÛý£ÂCKCR†·ŠMuˆ—Ë]S^‹ÿ·+^¥8¥a7¸¸þ×_={öX°éL†J@랸G;D,ÈÞ>{||¼`!¸†ÚI’Z¥7Ïf@¤r—}ág5FK™*îP.Ø™‚Ñ¿wì<ùÜÑDZ/)qÇ ×p‡…ŒîÐ$rÏl>ãÒöj‰`ï9ÜMf,Ð}îØþ¼†;ŠQ|Ïç£Ô]ÃR¢N¸£kQܱ½½xg‘ÈSªµ¸Cyÿ÷â»T×p‡ó´M¶†‡M¼†;d¹4IÛz(EÍâ¢ûE¯¢ÎF{žô{[D«Zn½ÂV Ú%S*ZÜѲû|Ñ™¹FOØ‹® ¸ ß–rŠ\Ì@v0²’ÄUËqóÊ•vÃ*Úϳkð•ÊàñL$¥-èD»Åc¥çì ÜV` bV÷«tÕ¡_«‹Rt÷­ûªÊr—È8obÇ¡Êr*'ÊŒÏqÜíý÷®+¶Ô¤}—]gMì®(“è}WžÕ@o…Ý*s‡ì°5ÝÁÇú´Ì EÖoB>~•DJ /îèxA²Þ,š˜,>>>^à)­í&w´[òÜ¡ˆBq‡g¥# Æí×pG}Š;\»õò«©ç{p‡Åƒ2ŒI×p‡ûstYgè•C·ˆ+8á p[óÿú׿n~¬¡* i­ú©Rć^xr¨´°6³@dYÙÌ“4¤]ŒV5ºX¶±ïïï/Ô¡Ö«¨†£Ê‹óóçÏ/ÚÏ5Šr°Œ£Iתù’—JRo1É#ô€©R+1§ÏÚû™‚`PÚ”Ccr€¥–¶cE¾C’v¬êî}<ÚÒ­©ã~nëGÓªkÆ‹V(D—êm³5.ð®¤âyGk¾ª‹²ãvïªFe{¾zñVN}~cÕ’”îTšS!]•Dn0•‚¢i×è rä=¬ÂÖ@vïiïÜ ‘æ}•?ÍÞ펾¸áA®îûn I]«ô^ý1êoõiÏÝwZÁÖÖîfÖeÒk—@Ó]ý]ÈW½àÔ.’³ssáöºW 6©6žYu5ióy»×9SºÓÄaÏϤ_ÚÒ΋‚•äštZmž^}]zø{v ¶ÏUíq¶¨ü}×)FKï«R“ ÒžÑöiùò‚hr©žR†ŒÑ¸Üÿ{î/žš<[`3ìóŒÑžëÅK>í.®9_UÜal<±Fßy wX;CbWzçÒp‡ª—Å‹ª³-á*îhŒ.°·»ëÚ—$­´³Î&ì~T tϯhZá®i«ç>û&×p‡³>owÈp’hGB{;‡e”¼…;,d¨ð¹5kâðîØgXÀ^Üî,— ß"Yq‡v-tÊ:¨á5Ü1œazkò5Ü!îWi¶³Ée µØ-îØÜ …1“æ›››KŸ™-¤ÿûÿïÍÝÝÝó¡æL‰U8•7œ“±)½ ZÔ[ ?~¼Ð–xx¸à ö€1 èÿ1.åÉðÒÅ(åD=ó}†^Õ}Tç0ÁYÀU°`/Yõ”}†’©ãi^WçÕu~âW왃©B¨‰¡Cùe•špXµpÈËv²Ôž%x¥âY)¨NºžrΧfÖNß-øœ¢Êßä·™´¶fLRäJQïßuµÀeejkÊu"LCX¹é x51ÓËÄ÷­q¤yã]›0«.ÔÙ“„®ÅùØ£i8kfÂäþó°QâyÔ' ÞvïÚYsmÙÞtu-IÅ1)óP|B¹kMe÷ USªA°3W>/+¥ûžóUPÂN§´¼}Öɽs;šK‘ª¡d¹%Œ2®ð'ÃM]«•Ô×XS>¹³2ô˜ªí~4­Û•ŠUŸ ;ŠOOO7ÿøÇ?.9gŒçKÂìx)à³W‚´2ÀSF²"içb÷# ÓDzÜr÷ºÁÛÁ;©‚UvÜ"ãªTÞ”ª§'TeÃ-(I¿¬ ³4•U÷׉ufbñSÜ1 ë9=`*•¬††;Ö©îp¾â„;쌼…;ôó²Vý‚T’öewͤ¨Ê‹‹ªÅ-A>áŽÎ£™ˆh®¨ì¿­þ#¦+j÷#]Y«}¦¸cÀö=¸£F¢=VX~;árN¸cɵŌ&;ÆéááOŸ>=Þ wX ÞújgÄ‚æÉØBÃΦ%Í'ܱ÷éü– Iq‡ŽŽø,v-»Ÿð‹?6·çy2µ`Ù [3»¯ š™mFÛv;@|«ŒœTŠLÌ¢¥œ¬U¿M¶ ¹nèr_Ýôò¤·«$bjïîîîæñññâ%m3í€ÖÝú4\©7Å6œ^8jè‚sñ*£¸…WiV5\¬ŠmÈ‚ý- %M„ÜJÊÇ´»¤™–2´>w ýMZq/rÜJ– ]J[5ìœÕ©­†+[Y¤—}Ï€˜ ѵꬆŒÉÓýýýÅàn+ªœ×Žnì;¤v@ëk3pe5­Õ+å•LÝs@Þ}+ߪ׃þ'3XiARj xòhWÑáÜU¾vïÝžóÚQpíÖ½xæ@«]®i©%; ÈJJw¨ÔY¯MJ›B5 ›ÇÍÉɽJ‡'ãµVV¨º”‰—Þ¯_¿ÞüöÛo¯ÏdL`j×Ú¡íŒvM²:S£i_‡û-@¸—ÝKvôeºFëÐûɪg½µ¬žzÖI¯,Å{ÀNéêÓ`oí :k'ðòïzVH”2Wú”.ëR†TÙ\â*•M£Ü¬ÏGÜá<ŒR¥Àk²°Å{wâŽ%OÅ{¯WIt•ô*5ù»K˜L4·6_Çkp+¥×®†g“çb»¹[g¯áŽR¤¿wœº4æh"¤·–þ.'Üaò-6u_]ÃM|ªb¶w¶ulÁiçÎÚ‰;옵³ä™q w¸gßÂÊÍﺆ;LôUܼ†;¾~ýú\ ô^®áŽÍîmÖZ1 vFwH­wX07&Wéîøûï¿ÏÒÌV²V °éðžÁÉ*«t¨ÖUoÛ×tR!‚k HËb¥y¤«¾ÖjÕ*».~—t gNj0é=œ jë–*ß_N¸ æ¤ê憒¯ìü”ò¦'K"÷ì¬pZE)—¼ê4åƒúŒ”V,ÏÙêVskæùóÏ??Ïz(ÅÙµU>pÅô-Ú3ó½ö€ôÙV&÷äAa·fºªCÁ.«ˆÚ/‡ÛCÛ*eè;=9µûs*úxØûŽ*qmUµm~eUMòOy•º<·x0 '%LÓÇv>OÇ>Ÿ¡ õä>/`Ô?¥R±î=“ns×ú’Qi2U¡«"ÏKc3ùÅò¸;/äu™P¨è|aÍ\¥Ž8Ô»öÛÛÛg˜¬vL|5UlôÚONà8ÙµhT×ê½ÆÞ]ïªÓVÍ×Ö´BŠHI´ë %lßaG×ëSá±Å¢Y“Øî_³Ý¼v$¤À©ž¥@ΨÖ5œ6fõYfaÅ&â'sb…:Ä ²›ZÜQÙfgÓ®)/Öå^õ90»%í$»¦~¯áiÉâg4ÅÞŸ³Í+˜Øœp‡³½M.TóXØ9>»Æc 8Ž î(3ädQÅÆÀ·p‡ ÏIArŸ3Óåâ;Êâ;z>— ŽœæM;ƒf êKQñ¿¥$‹;Ê·ùà÷wôÜþÜ¡ÍK‹œïÁe(M3O{&˘Ôò€t±túä5 #kåí\B·+ä¿[™0iØ!¼ ]Ÿ—jþ—òá=UO¼fM¦«"šuJòPÿßH`YS´Ê²„©åÞj  ®ƒë&¶…éó—âeõ£­#“D¡ÏJ!îð–ÔjDN;¬k`Sþ¸òÌ5uóUÖºÃîõ RÚû$J! ]ÅÊä@bïÏg¦˜FeÇ•›”J怤‡²ÛÖ±kK0³5-’ÞgÛß­ºú>ÊWÁ¤ðv^Úa´*Ö "­”•+®J— D`°ŽáÖŽ H¬-¾ËíE%0ÝWúBì9—nUÙgyç5¼Æñ6)6Î.ñ0ÁQVZ^u“ˆ}¯ÒÕuý6Y”êªZž{Ìø( ÷s\ß«*R Pë|cåØKG«Äm‹ ‚3Õí¤M˜D.ÎÕÊw¢m©¸RËìä™HI딚eeÞ³°E"ƒßç,ÅÔĬJK;Ûšì\M%}]ÓÞ§qº]S UùR A ø×p‡€õ5ÜQQ·p‡ª ÅT*îhœµ[Òb¤¸Ã™¥ÐGé1ñ>᎓a¡F–žîÅvÌO¸cëË5RÜ!Æ:áibvkÞÂʦŸp‡ÌÏeÿÛŸ} wˆß,œ™„[ähRq wlM‹;Œ»ŽîP!î=¸Cʶ Æ wÔÊÂ9=¼\Cv·Nô.”9ã~¸*ͼE»àêK[Eâ¤rP©Ð¸[•‘7êÜMåÕ¨´=>>^ ÔY1÷“këb œø¬ ¾­´8PÛ¿W!d•œmøQ‰4_²]]m“‘½ôQ­ìü¸uü(·;'áÛS;±ž.f稆ê¨ïÏên•§àµ¾:' …YÁ¤{¸nJo“Ó¿àéa(îT=(Ýn÷÷ððptMÜŒB"}ãááá¢=ëuXMtx^Õ» Þ¬Ur©k¹à×gÏw þ™2•¿ýöÛ…ÞÿÖžÕÖ¨Yñw^¤Æ€‹roÛyܳøøñãó¾Ûš°ÈÑŠ£HÊ›‰³1ÄΪ]‹vhlÏ× ºëZ•š‚)Lγìç>~üxQíµ›·CÎÃÃ}W*MB­U&"±°b…P_¤§§§]0)„»yÖ‹Çìœ*Þâ~­B˜ô KÁ€rÐ[ORm¥ÎIY<Þ÷ÝH½@ òN†£V/­šºwêƒU6Dg;KA²àc‡ êP¥vxOÒë¤ÂuæªR¿£¶X‰mÜ+sÀîVqGÿÝçì™^¡ »…K+TðÜ!îðœPÂü=¸Ãx³=Q§ø×p‡Àt÷Ú窉'ÜáyZ¥?i âŽ*5ÚI•Îì,žF˜×pÇþÙyck’b§I€] ¼˜lœ,îŽ_óØk¸CшŠd|î0vY¼\!DÅ3“}Ÿéþnï@ƒÊ}ޱ², aµá5GH*²RÜ¡`Ë0Ήb.»å½¸c÷s‘Ìx0¨|Ó ¹‹²­(5«så–’pj'·ÒÓáÚ:[¯'E Ûú¥%·Yt^u³ZleUW¹;JA´ƒèV©·±ÜÌÍd}±m‹ }F`É%#[øÎ øþìPí¹YÑu0ÖÙŸY•V¶êpJ®Æ})Û´_¾|¹ùøñã3xnÕÇ5Û!C³ɪƒmsA .Ä;Ð;š°Yå’–áç×o¢‡ƒk×.ãÇ_HlÛöïŸUb³Þ êÀ ~ìÊunN‹ õw0IHøjÖØ8±  `¹’îÒ?¤d:¨ëš¾æb®JNéç:¯¦øž[)V)ïîî.î¡ûÇácÁŽÕc;åuv=Jõqý»¯Oqú$£½¸)ÍN£>ϯ{@€¼ûš©´ßªï øº¾­^^óí)Eºs¢ÒO~*åôÛ ðg\Óp®²~`ML¥¬x¶-¦TA©¥þ¹³IžÕ@‡ÃG˜VÒZŠÞ®iÀ¦T±ÆÖ‚;|÷vIô¢¹†;,”ü7¸ÃY÷âŽv%Åîíî𾻦_ÃMî‹;ŠÉ¶—¹pÿ w,!ò¼²Xí±«°©8…g•!+Qnò'ø·¸*¥³ÖžïÁ···¸ã$r®yÏúÒ`»¦ßƒ;®Í§¾wXè‰/Þƒ;,ž˜twÔ‚¥¸C¼Po° Ÿ™Ø•kì >V?«V%DZú¶g­˜TsUßΓlqT@ým¹¹Ò²+pRo `/ÆÊªÕÖ-f[ôkßú*?~¼ùøñãÍííís;^ÀoÕÓmW¥ÉF]®ÝLô«ÈÐׯ_/’œU;4WŠ€´þ ë$íÙ­ ¿CÕÃîšXœz‡Lmð­òOŠÑÁ;9Ú•3–§j‚µ5m’o…¦jFROF…_¿~}a(^´>‡¶u•À5Q9©U ¤û.öÌå€ï€PñNwpß…`óãÇ7wwwÏzùv ݇®aÍu)juÌão€Þ{ÍÇÎK ~¥¸}f‚– ¯JIÚ³¬ÙªŸgdzÕðúM“\“ÙtžÝ¥ÈT9qßÝc÷cç{J§ëPéb°ï[™SýFäÈK16&˜$HKuí³íØéÑΕr½RkÈv{{û¼¦wP;÷³ý£XG¹õ­( bÚE©¢¤”’}¾ÞC¥ŽšÔœÌúü¾-÷þö™våÿ—Š´x¢Ï™”²º¶·S¾sÇøÚdгZÜQêÕk¸£ýBŒž­ÿ-î茕Éį—å IDATIÉé-Ü¡à€]k¸Ã¤a?sÂv¥AÖ¨Ñgy8¹\#×p‡IÎ5Ü!]·P×´3]ûÞ}¦kú5Ü!+DÕ5;ró³ø îè¬xg]¤ÂÖ ê-,]:íÞ›ïµ??-‹Z}l݉;*oݽ T¸jv}7‹Í{â)‚“h/îQQ…‹Âù?ÿùÏÿóûï¿¿l·AJXy°Ì9¤U£¯Š Xù¨G‹œóÊÓmC|ùòåæ·ß~{5R ª»ßY“><–ŒÕ‚U×·`wàÉû“·)×oURÚ¬Tkж{Wfx/Nc6“•¶L  >ÏUê¼ß‡iå+ï[ó§J‹(­v« ¿ƒFi΂¼ð6𬚷wP†zÚìYÔeÛ†‡¿ÁH³k;QG\#;¸:8Ü×t¹Ç»~åB+wºëR©JøÛÛÛ›§§§t8«Sõ\XàÚ0èÖž ‹´*ñ(½nÒb"¦i˜‡‡~#V¢[1ë¡°{Hzˆ«·ý1)G‡]Ý_{§{ž}WîÉ➨nl¨,NY±ÛšÞú–Ü5{€-×Ü µqSÉ`)­¾JÇh×¥”­JÓZ5oBo—UÅ:¹ÙrÏ—üWö^±­¶®œOóàTÊÔª¤ü~ÕñLrå‹‚fwÎîWn¹è³ÜÚm÷C:b%ÀÝ£VQ}¯?ÿüó³šïÊŠñâÿiˆ¸Îí»&÷‹>TŠÑ¸hïÅ‚ìâãTà w4Ñ{ w|ýúõæÓ§O/p‡À·¸Ã}x wXiß:pþd¸cIgtì"Jõó Ü>ªâ¤@ú{p‡â2µyð™íOrõó¸ÑÄ÷„;¤Výö„;&õlQ¬^aÎØšLzn/.K³l÷ý„;Nj‡®á_óüÜá¹ù–¶ˆfìÖ‡g>|'Üaò&%s¸cª•îu»9&ØK@†;†¹¶‡¤ç+ÑoQÑÙ£üñ%ÍÌö±§äïÁUÞ:á÷¾sIµ˜ðÝJµƒ/“fgÓIQòDY5fwXp¬\óþN‹½~Š;”ß=šLp‡3¯á‹5fÜ:_<®Ôùk¸ÃóHº°¸£fËRC-&Š;ïoá ŠÊL‰ï5Üa‘ÀBÖÖ܉ÖfŒwìlxîXQüÂs]ñŠdKëUÊóæ…4³’qmõžª„ò;ê¢+OXŃª7ßæ-7¬Ã÷Ýè'U‡z‰”’µ¬ø'Ïû¼Ö%Zn}˜¸.5B`v{{û ¥£) ý¨CÝr ÝØ¥~¬õ\ Šë Ã¶ hK**qkàò; p5£äi Y)?+#¨Jëªsòv«V¤oÇ*¶Õ×oœÖ)¹U‡U•Û´Š$°WÆ?_à3Ð À;¸n•vmôJX:˜-‡Y?¤íïJï*µkgÒ®Ìþ~ɘUBçÆ ¨¥éc°kÙÚaÑöy‡—-nX-voTUKß)VX¥.œ}út‡06à¾0ñðþõ³¨âÖŠ OOOÏ1ËçW€Q@¶.«¥0áñ>=CTbzxx¸¡ ›O”Ök «öƱҀO.¥ygßÞŸ^EÞw;4•c-» ÙÄá$UôSMÍNÄxøVî-0ª¢f’ ˆqoš#ïзïzÒì7777¿ýöÛ «ˆŸ~úéæñññ¢óQ¼Pš–³—u$½æîPŠxke†Õ'Üá^¬OOUÉï¿|ùòÜɵxª4p y¥”–ºWÜa5]ª¬^#RX‹;ìÖØÑþ;š°»vý'³tÅjVíLSýS:‹+«âîðçUðžÄŸ>}z¶%0ž÷Ìó|ìü¯¸ÃŸ?áŽR Å&×Å6 jhl}ZÓ:íœ><<\à;z«¿ÿþû2™QÖMs©ÀVõWmòåÁYÙ¨Äß^ÈhÛ´;8åĶâqªlMC] Xå­Fíõn8Ÿ’™o%ïúÂ¥xí@ÔhN2€(VÙ?yÝ$yñ«  |XÙ÷p]VŸ›Uü*Tðôôôü>wN•bC›Òpÿš…í™ìyŒ«öÌLr²{(@éÀ¡ƒæ R›‹ªÌ’p“žÏŸ?¿ØÄû¾rýµÙ!0:›ÃÀŠOèœ]ÿ“Yt+¯«|µt¼¨%Ì]ÓUZ@²r7'úV[•d¬›±\õ>Ï=¨s&HÚ¤@Éõo…»T%‡e÷¥‚št«ö#WfUtUk;Ϊþ4v-a+è“ãì”{mªa2 jæirR:ÚÝÝÝ3 «ØÃ:Ýž*i9/SÜ¡tñâÔÞ÷þ»rŮөzJcóLRÔÇob¥È„*wS³ ëš8áÏ~ñŠŒácþpG±M…r^ö..ÛwuÞMiðÝëÓÓÓ jkç²V˜Ô8öD'ý^ÜQ:ßbôžO™8×p‡‰¨ââ çò¶ß+ˆ±ç"ýý„;úÙâŽ&74¦”ibw®E Å>ºüîá礵h©Ôô[¸£Æ¾7777wwwû¹É§¸Ãggòbff7]Õ¢*‘¸0m=Õ4ǪÞiPª i7Q³Ì&9œÒì«,tJËùìâ ¯ ¤nµU¬pÃÔÇaU¬Ñí F B¥t®–XE‘µï?ßaò“¿„ é*µ•ûõžÍ´=¼=¬vO{ÿí–½6@¾kï é‚‡AhŸW>g!ˆV¥iHGÔcB`$—½•i“麣½éÚAã&Ø©øc¿Õ+gW<èìjH‹¬)£ªëØ÷ð÷ßß<>>¾ðŒÑ¸Ï ¢è­+0U6ª^~+ë>ÇÒ¹¬Ø»¦­Né“q耱réš¶ÚÝ=_þSïM•´úo8çÖm‡Êøç€°±»*MÒ¤¬úWUÎw´}iõÝ‚Î5ÓC“9éå©?J•”ÅÕ¨ q!ž4–­É»ž-P”b³ëwÎÅâÌéºJ­­©É» u‰{‹Hž»5¹¬ šë®òó‚W¯uÏH©q¼0饈 Ez 'iÑÒ"Ô:lS«[¹`y”Ö⎠%TDáD«=ᇤýœŠ|(a+–(îp=^çx=ºøÀç\ãd%›•éu¿ûl<»;WSܱõ:¦€ñ 1Eߢg¢¸C³îîpýœF LZÜsˆ×î òÒÎ?z.µx*wTmÏõ$&±÷¬Iwq‡ÅíÒ|¯áŽèÄw1kÁfÅŠk¸£#UÑw|ûöí2™YP6Èx¸«µ®Óù‚å6¤rå–Ûë€zõàmíŽì`ÍÂJwù¡Sõð:¬ÒíPpQ›¬¬Z(HuÀTÃ'7‰›kÉvãf<˜U¿ÑÂÉ®ªW~~ š¬Vø9˸•g–R¸ë²‚lU]š‘C`}—¶:åA`•Tp'p•º"xس~dAcƒŸ•âÓ¨IÊžÙ½ýÞ ´º‘5¦«9™]#e)ÕÆ·à|“ìVÒ6NŠ}zÏp¥_´úãá¦"˜ÂQC¤1 æ R* í÷;#%uaÏFú¨É¬E;õyéLÑb™Cœ¼öíß®éJ½z(JqèRz¢ Ì(;T›ÿ½L%Jd÷©vÍíïÐÚµšè ¬¼GE3ì(nohºdÞÚÂÖ´tïݧÀ¸æËúÍÔìÔ®£gDç ¶ž­ê ¢æË"ýG—tMT­°ã&HÞÚÖgïÍ{1ËØfë<<+U22yóû+DsšÉ’Þ´ï’!P¡ãCý^&¯­îé¾£îX2$Õw׺ ´Cá¬Ä |ORûâ+Ý®Ý×p‡ÝŒ·pÇb¦¸Ãý«Èà wìß÷={îÒ€ç0=áŽ=Ïk¸£¶±N¸cÝYç-ÖÑ{ wx攪%mÎù â¥X^ÃvÄN¸c‰ ó?Ò(ÿJÅ2±ô¬ØK!u®­&šî+–š¢Š?ìäwH×µã[&”¸CË…“ÏÒb¨¿ëûw8ÞqÂÛ/hfã–Ö±uª V…Æu«'€^iD¥é”i´šçad õ†Ú¨¼uð\éP} FsØA"Gr‡ë¾G“F¥p+;lvH´’'å*Á©Yr¥5­&N0@¥}K¶á=`Ûe¸¶¡Vq°âæ&YÂZµ´ÇÇÇ s¶"ëL^ΤU,+Uµó³=|÷®GyPµi¿³Y®ÇÇÇ‹uz’ïuöKÕƒ‹Õ{ÍÏÊw¶’ä;Xu¹•)‡ 7·æ³ÛÚûðáÃÍüqÑöu®G’­ïº;Û©ôÝï³”A--òdÐgU™¯Ý–­;•¨J1Û^…¿ª 59]¬°R-(ܯ…;TNæ«×ÞÛ⤹+%k\¬:ŒƒáÒ\MS°« ÜkÝî•ÊÔ Vš÷㌆ üvvf1ÊVö7¥oÇÖÂ/¿üróïÿû‚n¸ïU…qƒùúɨ:'}jïÐz•xªÄU ;ÅÎà4Fo¾ Ó¡[)]'óc»í&^£i(©î™)=Kúκî{®ƒrõ­DÛ5Ý^xzzz!øRóF‹VºÍ³éϲï/îPthïõ„;ü{ BÒ4ÅÊå—ñáLÁÖ¸Ãu$¨Ö¼¹¸c1tE éaÆ¿îX ›¸JeAZÜaáÁ5Ý9°â¯v1ßÂûÞîèšw,¾YÔ꼞3xŲ®±=^à ”ÒÔ3¦ i{×_¿~½¹»»{aã°õ®‡ÍÃÃà Š5Iõòl0ö½†;ÊŠ°°4ÿqGÏ}vªDºû½mñtçÑ5Üáúsî»O¸cV%ÿ-î&&Û>*ž5)-î¨8É5ܱXl«ëCq‡t7ÅL†½¾áŽ£‘Øï8GÙBß‹dæ´ˆ”e–+hví ëµQ—`y]¸w±¶2:òçl;œ/HѰ«Ê zF‘×Ú®üÁ‚«³årj~¶ê¡UU+\“‹ÜŸ5a¼»»{¡¥n…b’…š_ T™€ÕUWmò-Žz2´šf5 ‡G ¥žžž.ärO|jAP†›É×üpëL³µõ¥2móìÝîßð².Õ•BU=ÌM¹÷_SÙJ‘–c.7WúÀ©Bd@Yâ' ·#yMe×±ý·õìÐÞöÍÚēﶢc²n§U`à{’úi÷ÀÁ e²áwZ¡•âs€ÙMÜ:•6£ÒQi©¥‹ ŽvàZè±:î€èÞ—UOgL†G7rž§Rð&<Ê‚*=mò;å¨]‹31íL:ˆéy`åÞy“ ÷º9çI¤ïÕˆqkÚÄR¹n×’ëÀDÌbÏÞëÖtéK‚ÅvÅì:-žö ¶ÂîœÆÎª½Ï½#äFyÜu;çì—Ô3ZÊîhÏqG×ã w”–ýî°Ð"……æâŽªxz†œ˜ ÛëîC“©”Ša½wÔ¨¶4ëÅ'[Åbð—Åîí“’¤¸CÑÏÁâ»v⎞¿¥±Š;¤Ÿ–&hÃcÏí"™i6×l ´ÜïðŽCC0M• Ø>¬Ò ¬<(+|jo7[åRÞ°|VMŠv ,V;ä×ÄÆlºT@Ö͸DÄMaMå_pyþ®ÔÜÔg\ã­m:\ý RÐ5·&’V æluË3–¶¦¬i¹ô8×8á'å4…kWå,¯Oå+ß±ƒ³BV3@Ú=ô6XzÈ;3PJŒïØ.šÏ@&%V¥%Vò¼òÆ'éØR?Z…ˆZUq W"p©ÏŽôA<¥rÖ¨RŠŸÏ¯ÒÛR:$oÑê˜ÏȸIÏb\½‡¤â8Ãåó¬<¦æ»û÷V=Lœ pÆ  ±”77ñ–g»ö'Ü!­Ï¢štªïÁ]ÓÎCzt½¸ÃµÞsq¸Ã9N»EÅ>cï×ø»¢Vq‡EÒ}¦Ãú2wª¬)uýî(®z w¸/Þ¾¯“š£{ódÕÑ™/“¢4³Q¢6°ušÃØ—®ú³‡¢’ŽÊkÁˆN¾¶ ­¤ å°v€Ë ªZNeOOÿ¨DÓŠ§ÕÚòT=`jÜæï‹<!M£4tÙ¾žPƒÕp«*Vø[0Õ±®ö5=-à*-G§üvùÍ>*Š-`[6íÍ IDAT’¾ç \¤Ý·bÙB> 8°ì†4i¬O­M—î“XÁ€I}]s;ûÐ*„ϰ’;×]©®éRÞw8UpºÃ¶””zUü£óuv„T \¢lQC0T¬ÏJÑ„ÏVð£”-‰VŸûý'i[;0ÎÉXQsxw?W…ªfé¯!ðü©²"_sÓz+9¯%uÏÄM  ±¬ûSª“@^ÙßÍê•Vè÷)H伃`Þý¦ÇK©„ά|/îp.ø-ÜQеÏWYõÎfºžõ +î¨'—@¸xÌœms¶A`«¤ôýýýî°ªÿ^ÜáûwHy>áŽzýwÔ©?s w”2ÜN„T¬·pGéeý_Ãëæ‹ÍŠ¡Š;œ',•®×!îèŒ^g鯯áãIߥ÷ÛŽ¯ëÐó`ûD±çÌ‹;Z zÑ™)è oƒ€A¿ÉÛFþŠJÐZQA¦Cå¥)mÊLú„÷b0Ú}}ùòå™_.Àr™¬Ðä;_ —v?ïㆈO’ÆÞ3Yóððp¡îs2érA¸0Vµ]kSeùʽœ·´•ͺ»JÓ3Ù³ª¼j¬AXŽúÀôÝÝÝ…œh9àÛÄ›²c0j+_`]e½';U{+Í«Å*ê) ˆX—hêk¶ùËù=U« ïø†’'q[ðíì•ó &œݽGF ¦zmM»ÿøãú÷ «zM5ü'þQéözKìÏ6¬>ÐÑá\ÁÑÉÁÝclYqÂäJ× Š+á.µ Å—O’ V;Ká»]UMÉËkR´'˜8²{ÕÙÇy[£=j4hŒYB¸Ø0!€ºª×3È5­’”Ñå¶÷Ûñ¢gupëd¥OOOÏÞû9çƒN2ËÛ·‹qúYp¨‡„’ÓKv-žT¥ÎDR,߉, eÅíZ)»»Œgõd²xc§Åí\X;ŽÎUp‡”Úk&ˆ'Üa‡ï-Ü1Œ±ïRXÀ¢Q½Ó\ç'ÜñôôôŒ;¤à¿†;4·Ü5”êç~SæYÜa\Ÿ÷‹«óRQ’ݰ&’ª7ª;9áâŽbÎ⋼v]c'Üáówì¹\oßm¯s½wx6¹–Ê^8áqG“™â»2²N¸Ãç&î²íXCi¸Ë)Åx¨ʨýîÉÎ|ËŒ½lqijP꺳®ÉÌšR§kk©‘¿\kÜ øŒ2Ípm³KEÐX̃°fh¶¨¶ À4Í\Ÿ"…/°™}Ý ˜n ÕP¬n˜·ÛoÕR¤*˜} ¦ëÁáLŽA¼>ºÌ›¹0¬hY­¨7Á©‹$½ª‰Tùá¶ùO›øTQ¨b”šò&3QúµªM®-¹ý···/:ímwNª]}p6»c+´’’®é½¯ u¡ÒtYIôÀÛ¾µZ©—H郞‚‰¶áÝÓÎ,˜Ä¹¦«>RéfŸ‰3 *ÍX9t¸õÿcí^—ã<ަ]CËElìó?Í×&6"%yýJÄ57zÐþá°D3Ϧ»:«*+ÓÃz‡lç¬p Û­«‡K…/Ú rŽM5G+£Uu”þdÕ©ÂÊz+áÛÃkô ¯m÷»YƒúiøÏLk)3‘‘UÚBǃp‡²t’=¯ ŸfNkºsRéêqQya .•á•2&¥ÌY“ Fç" Ô÷=»Oã­ g'áßI¯±êLÆäéžfb¬ }?0F¸¦'&RkLF¤×JŸÑdÏX Sø5Ü1éðr÷]£þ¹•p“•dJ£_ñT%§9›SêÌoq‡Ïô„;”Î6)øw”Zæ;໦K§½†;ìäíÙyÿ£‡*¦cÇ@X >ÿÆî°âzr-wTM´ì÷pG½þ:ëSÜ!]ª‰°{lÀÞ$À5-FT,¢¸Cñš%ªŠsœp‡E3U‹-è©gáì‘1Z)îpÖOVÀgq‡L™â ¸»¿7ÒÌÛ´¶üðÊï·` \R#\¼qð¬vªˆ2®½‡@¢2’[Õ¢÷@.Ea@Ô7© ´®«­vIWè°ºU=!l KéàÝ⼫áVTµÂ×îÃøUbQ¹¦3ò«Q/µ`×% ¤mJ“5ƒjףݖJeôºà]sUÓ)•E¥!9¡Èþc'â4$n"juRùL?×P•jÜØÜ‚¬*A‰‰ÊMý¹V9¥X]tVY¬´Äúl5Ìs |‰ú®ÝÊ“ €³ •ám…UU'ÚήXaìÞvž¡³5ø=UÊ;W ’*Òy3»QÒAìÀ:Ïå3¶©1«±ì¤ZÖ  àg{ÙjÞ¨s® Ï‚9@Kñó7Ž žƒ;Zp++¤¸cXº4Ý+-(x>Ük§Íâ;‘'ÜaÑH Uy~U-û;élø‰†h¾ô†f¦"Lù†5»™2‚•S[¯?~üx•íB—.¹ ¶º{H›(¶f`dâ5`¤<êºÁIgkAúþç"±òÙšƒçåÁªJ£®z]³¥ªYE0£S°IÑþ Ý~×*wù¸ Ò<:#¿Ñ@º†êt¶;ÄiUQÕ¤­-«V=Dè šïW‰ì¶}=ˆV‘Ø÷ÚmðòòòÊU_°×xÌïÙ¡ªˆÃ©â.€ÔI¥õÙÛñÀ4©Ú30ˆt ¾3g'E ­ÕŽ‚GŽÔ*¿s1ªÿ>sñBE¤‹í¿­ûÆŠzšTL@º³!ÒÚœášl¨ô5g ¥+ š÷2I©ŠSac@D¬ÒׄÏu8z¢,ÊÝ þ/hU‹­V:„ïѽ­Øn²@JÚ¢g†Ï¡´()!“¢·ë×Á«~‹ÇRù¬z Wàñññ"›€…T»*ÊPï5EtŽL™õu}OvÙw> Œ]“V§ÛÙ1¹?u ¼&;Vv8Ü+XÐ H Ù9vçJÛAwì{ÅJïÿøñãu®Àlñ,kgö„;\Kv8N¸C&ÂG¸ÃŸÕ\|q wHM5ž¼‡;ŒAKº4›l|©Û½ïð=ܱ½½=0èI|g¿_zlq‡]ÀÒ³-¨¸v¨ß¸cÏ÷„;<,ú”ÙÈgqÇTàìà*¡é¨¸C%Êâ}¨,j}wÈVð>j®{šû3n¿‡;ÄrªRŠ;”ÿ~wìÚÞ,PtÐMŽºü\©L ›kWfmëa(•iÕ©e•¥íVƒ^.¤ U©;UÔ79Ñaº.µVÛõ˜0Á‘§_ýmŽë¿cÕÁ–± ÓàÖ¬]ß7°‰N¥€}O• V*ÓîË”Óvmµ* ¹Š›€±íØò¸¥KÉ·6S¯'…^r‚M¸¤éV뼎p•0¬jÌè–ÔUDLúl½»G¶ÎK󪿈€Äa8Ím«râ÷8Ä'pM8SoÊá.(äPC;Õ^NœjƒèIQÐ}°ù)»—Ϋyÿ‹Jcª«o Ýo1NïŽÎ; Ð>iE[‹­ H½×®S)+&¿R„kNªzœ&˜×faL–vèVŽXÃ44Kו;-­>)®{÷= ÍuRBV¡Áh¯¿p»ú"¸†ª%½Ìw°8°ÊréuŽßÿ,¦ùG*Høu[cÊšþ îT£³*[:™q£ÒÉû¹¯*Ÿ™°K3<Éi[Ú•‚â™nqõ=Ü¡YçIj¨9<Óõ#¥»¸Ã=TÜaœÝs³“¢|xg/|×—5 z`×îfŠ;*½ë™Yº›Ôj‹•Å{⎪fUѱE€k¸ÃÎØÎZ ;×p‡¶'Üq•ÒçKìx w(ÿ\ܱ8wÂ{G*©þ/¸cñR™ýâ Ö]çâŽkT\‹%[Ç›m.Ѓ;Ä8‹ß+˜¾™™qÓù©VvÊÙÜP¬ž«š˜Z5êœJ1•E­<²ÜóJ%oã*+ììî»NÊíŠìªŽÙ­4#7¦ßSGíè-òš*Z½.m¬ïg›ÂŠ@ƒ~½}4†Ô›Âog¶°÷ó^óHüæL]c±]ƒïÓwn¥rCúUÕ0°™8íÏœ=$|W•MvM[ÝÙϯcàa¹k³­<°SZƒAÁûYà³zZ©è}ÎfÅô}Rìa¹ŠT•V—ËÝC´j)ms;Û6…—³ò‹íº¬ `ñÂê©ûÃ5}¢ÜtÏ Ö§¤3DV‡œ¿Ú¡ ÄÖîo¿ývQ‘5Q“n`ï37®H+•Vº˜`GàòôôtA)4q·úêг4–­é%Åë7RµE+‘õˆÙs°@±ßµk'íÍîX²eX‚ä=yÀÛQ(€¨ºV1êã $ñÖúK¨¥DjêfG©I€ñÂN•÷Rév;:úÌØ¥õ=lí/¦nŽ©³»Î©”Npƽ%0Ót÷$}m‘pÊ ®üz {Šüx΀Hí´[WÜ1–HqÇž_ÝË6¶€ã~h!jkúîŽï ­l A •uq‡NðáŽ&M^¥Š¯Ø¢T¸ÒÊUÜ»¸†;,Üáã—쓽pG©¸÷÷÷of<“N´À ‰;NÊl©ï½Jk3ÁnѽâQ×p‡¦Ì'Ü!­ùE!™5 ÈBÒÇÐs{¸u1ZfMq‡{½¸ã$hÑÙÍ­Ñ‹dÆ¡r³u[l­†;”[¯[x`« °·%º‡°@»¬xÎÊcy–Ëë6o»^²Á¬-Ù&rûµjU3ˆ.Øh¶X÷;òå rZáö0¶•Z-yÎIñJ~·1ݬ¥ê٩ءÞçrªîváÕØÎŠ”¶Õ«Äf饃µ•¯N«Û°Ý†Ú¼—ÿÜ”ë*m£ëÉy‘V¦öÌ­Œ˜€íºíx<\û gA {¯V¹t4yy¹P¼iàèиÕ>U¢ ÖvK èUa9%ß•ïÖ€¬Úùúþ,Ù; O<äªÒØEÐe?/?\/—S,lb³}½ÿ¯·†¶Î øL¬Æo ³ÃñG¨¡›¿_©lÕ#•võ~¶fM²wvh^[EÆœå+­aÏÐÛþ]J—ñÖ®€ [š£ÊvªPVŠ×XÔ9yû[‡&מy§‚Ù’“o+¦‹#¥€”B¸Ÿ‘Ž"X«OTÍ0í°u=‹ ü Á³1ºRv™ËØ»2Ù´@ºûß3ê9ß΂ëVl¡èОÏfdJTáRÜaÁeÒÅ'ܱ]qG)ôÎôëJ{wH›3ØZwœäÎÅ$»ÆÚM)î¨Ú–¬ cÂöÜâZgk‹;ü|٠{×÷¥¸ãDq²ˆà8B½Lhv' ’“Qµ¸C/Ä÷pGeêe6w¸_|^ž]Æ= —3¨®’M »:²h>‹›_¾|yówŠk‘ bâš™´ÝT¥U¦[…§<×ve|‰ã¼úgÒ±lsîaÊá÷à0@z(,“Ü ´Â¹jÚ8×¥v´[³ÀÑ€ùŸÿüçun‡•Á^ÚDùôMT^í^ì}¸ù«-¾ ºëu¦`§¤Õ»`. ÑJb\íʼšÝÏÃ@·À$X€U¥¥î½£2¸;Àíé{}bkkÏ} g¾‡™U%MÇâÝŸÕÒª¬Hu¬´¸CŸRTƒ2‰—~±³U´ûú˜äÿ‰k =P\»åÒFà­.{¯«`­.¿}ïìééé‚>¥C½Ð}â¡&èðÐØL„ô#ç¹<èG­ fáeÏBƒP‹&§µá(@RÌ£ bzÙÁ­W€‡žÔ«)CÙÉT¬Ã÷¬Z£kÈuïìžkA J¥ëK!(…L¯ Ž›T¼´2^¥Ÿ:„W‘ËNÓf¨Nþ4>WgÚT~ÚXºIŠóPv>V„«×L©t¥®)Çß9ÕÎËØ½Ùú–6æ|œëÕ9ƒ*aÕÑÞäÒŠ»¸Ãÿíg4¢l1²t2÷¸£†¸í~–†¨Ï†€~ïPO+溌*ôõ¼Ü=ìoÇk]ápÇ5•Ðοú³Ò œïáŽ}ö:'Ú{”òí÷›Èw¢O&ê5¶ˆž—ÏGÜáýË9áŽ]¯ç«g¸l%ÍÈKŸ³w˜\w8©hqG € Ç”ÖÙëw sØ!UÀg]¼­))dUƒU ¦™Ñá~wT¶üÍÌLkZñ‘9ZƒŽÞr¿w ÚªrÈ^ŽQlçïÆïîîÞpìU¥Ðh̪Òü+LZnooo^^^^AÐ6ó~× Þ£Õ4öËiÜ5Ðì0°¢ígIMéPæ6—ÃU•&,%oQoŠºÏš,îZ[ÕRÑFþ°ÕÜiS »!7³ö•ÑTdäu(zÏÁAÔmU\ìRƶ.k¦fUÎjèíííÍóóó/[úÆîÅnÈÀÆ~ÖvþÝÝÝ›€¿{D †¾~ýúªrcuwñí£8¡@¦Õd?Û=-p4°w^À² '(Û~¼f.+Xo•ÙŠªÃ¦*Cµ’SCÉ:Ø»ìR–îV ªt`i•Egó Îí"{*'ï~°¦éô/=ö½«ÈmO×»g±xûS? ·@º>SÒöîô$YAÈ!ÏvïV—J²ê¸¬rþMŒkiqN@©Ráž›rèVs)R+µÝae+õ¥´îžá°*¿…¶ $¬‚6nޤŕ·”ö–¿¯)`› £À²fÅeY¨ìvJV;L]Üa¡QëÌìIQËõðî(w¸¶_ŪO.®×ÓÊnö w”Ý m°t;æÒõìl]Ã×o?lϵÃtÂeì¨ v-Öš<¿ö,TtnIÜáú°èd‚Vܱ54Ê¡]2ý«Ä’Ꭾw¦¤*™Ûó² v=µwTäaëø#Ü¡ÿÑ5ܱk±¸#&1;ª!íö=Ü¡yvm– Wõ=Ü¡êÜ1™©Y“‹F‡W«ž¥ƒ¬›ÅwèR®® \_ƒVŽÛús#häh¢Ró©:eÛö[eÅö¡íd7²•ßJGZÍ9™IÅ™2œ<ãú‰tÀÍv -ñý™jþ~øöÜ'(eL‹´@é'0`·ÆÃïäž½Cf€gŸáw8ßà0½üQi<ªäDðmǶºáßU­jÁkS+ª> Û°UÖ*µ¢^'UÁ›C¶{@åì”Éåhkh‡Å»|6­–Ÿ4øÕ¸_Ú{œ!\?«^¶î}Ž«ä+¯)P*ýH•½%†å•êö.°S)¨®Ó'ðVê·¦÷gR*»¦MN°W¥4±1ù–¶ê• ¥_ Œ: ?¾É‚\ü}– íbÔ¿ÂQ…ºVÞ7•ÃÜ‚ v³Löð€.UF¥vÿ¥EÔ¤ÔªüÉ`TÉc+àVeO¾VK†kfg‘Â= Š¤jtMHjx'nlŠÅEI‚²Bœ³d{oíØU·Ó¦¶‚×pG…3úžíÊœp‡2åÎø]ÃÛ vb*[\iåη{¦ØOgʤÌ<Çœ»«=€þT0oooßÌ{¾Ưáç8œC5&¼‡;ª†WÊçfø,ª˜œœpG“®â•Ôþøã×D³¸£3$;ó¥ÁwTj_IqGeêU<)’vžÚ„ÝóÒNþ w4©«—ÿïs[®…£âŽ&—K€œÑl¡ÈwþîPåNÿ¡Å”‹dF=o¿ÈÙ½|]Å ¼xr¦£´1ùi¶¤FqÞ¸|peù¤MH±Ê#0p˪÷@þdyÛ}Ùï;ÈܹmH9°^Y©©„cZ¥Hd»H5سØ5×zïÔgÚù ƒn‡¾kXç³¼”Žh[½Nàå‘—ú1ð¬!à‚ë ¥-ÝŒJR;\k7ËMfÙ5T}¤:éÕe/ —c.Þ–¹Ò‘åíKßÙ3ª̾{-Ý /Ûš—N¤ÈƒÀÐDÒÎjg—äI׸«´”Ò <ë!EÏC§3`®É½ŸÅ8߃IAçœL’]ûvŒaM|:DÜùµÑ—”5_’(õÇû²šé;^¥¬óR,íd:o4Ûh«úUˆÀw^K1ÃwMë( Ô,0ØÁxJgRe,v=w.K)y}]NžQuÕ6Vy~9ˆëïÚ7®:deÒ5ã ÐÞB6[p»í@øŽô!±²»çR»·Š;˜ì*«ZÁQ¿vFw>@lA¦¸CfFiåíêú,>Âv;O¸Ãn¡¸cëu &UâŽúB ØU@´Ka"¬TöâÏžùºtJâ·°úî0i¹†;ª¨åy¼µµõs®ë±&®RÜaì¨ØQÍ­ë#f÷ׂü©ˆXÜ¡ª®ß9öËpÇ„3–h¬ã§lþ wXàöܪ2h}z~w4!ö,·¨.Õ\O™Ûí²ª4ªpÑ w,±ëal®÷p‡ Ïxì‹d¦CÚò†ʵ•zu¼ò ßAªdÜÉM~‡‡Ã¥0¬ÅªíWÁ‡êVÍm?ïsÊA_w›_0³ïúúõëk¥pƒÛVê›RÏeV ¢M¸  L̲ü¾}ûöªÎTÿ—}Þž]«}ÒÔ“_¬á“•y¹“›)øöíÛÅ@¶Õ•v”í· ÞÚš†u=T¥ y`×s¢CÓVèUYÂ-€mõ¢€]þ½3¶ÿ574 ¶Â·çß ¡UE¤GŒ>br²ƒ]ÓÖ´þ뤩%_Ã϶íÿÓrÅ2*AY1‰¿ÿýï7ÿ÷ÿw¡Õ¶¾kRJ” qs"SnÚw«è4 ¤$¹ûoÏ£•zi¦šèI±Qbø4n¢ ¥£rÛVÅ–¸•ÚêõÕHRªa»ô•»–Ò#ÝcëÄNóÖ–3Œ5g”¯"—ç€ôÛšîR4·Øm<Øóõ^÷÷÷÷¯×»Ù3Ï´ªVQKðà>PU³úÆåœ'`cBï<ªç³3»½‹Á¥^îü]QI*¯ŠMÛ«ue_Œn\ßïlo™¤TbÖN›]«ÌgÒgËÑ®‰ç¾`\Ü!e´T*; Rj§ußá³nÙýëº*îè“nháÆîìÀðöÄ@õÎK»iÒ§?ƒ;Œ¹âÙ·ó}‰;¦^[ÜaÜ·+!î>f¡ü=Ü!}KVÍG¸C9nçëxÑ#ë£íÌÔJ;¿Üªº®m ¼‡;LÌ‚KŠÏögÃîégÞ›£&]Ò5Í ë(î0±w¬ðúíÛ·×÷³uÿòòr±Nß$3rÅËÙµRí U2³Á×øš§Ÿ¯t¦ƒÝ&ýYAÑþlÛlfz[`=l:¬¦á¡s(&5`ÚÏŽo+È’&`µIVA“ Ôçöõë× 53i+ò/ÿúë¯Wª‡Ã‰~_iJ'7îŠÜÞÞ^HÛZQªç×gûU.°™¸ïWJÊž³Úê5qÒïgüN»Puè®®Iÿ†ª|uø¸ŽÌv¨—ðÖ4Qƒ1¥Ç•Æ”žÔ!Xe¼û¹r¹k4fÂUç¥ zT‹kÕvkÀ!Å“•U«>W…,•!;'R“Û*wÕ)ÞŽ—&€_¸ëSÕBmqÇÞ¹ñãîpOxºîŠ;”Ñ=ᇊ;œ}UȦÂOâ»ðz]½‡;d7ˆ¯ÿ‹žj'ÜaâÚÄKãäî°àܳLÜQ³p;7‹š5ïlÎõ鞵;:_qG;I×p‡Åçõ³¸ãË—/¯BL] ¥Rïs–¼yþŸpÇžûƒ;ü,;œë Umsg†Ïë"™Ñ•{/uÿÞÖN¹}V^Nƒ×Õ7`–:P¥%;#û\ý”=´åµÀ²ƒÜÏ–Úä duÂO‡úª ¦ô°€˜ð4H)éA«ÑÖ®ÓLºNÅm76Y´ý¼g·$¤ÃÏòk]|}&Õüw°ÛƒI@ÛD`ÏfÖ&OhV-ÄÊÛÉÝy•i“Ï´r˜×*Îi‚.ÕŠªÕ5¤B;­º[ÓÙw"UÍäÖ½§G¹éV™Tóy–ßªê¡ £"§˜!nÕÿRåÖwþL`°ö¾‡àª¦&ÛÊìZ!W.Òj—Þ$õtלOêIùà¥$É5˜ðìl„U,ý´Úe­ØƒïÌdJÀ¨D²Uu©tåüè´£VSA}–4ŒºÛ.«Õy‹Æ[G¹¥Ã(ª`W\Š•CÝŠ`œö®É±´Q4¤^”¾ë9Y£P÷ÿpgsZõw>Afߩ緀Ã粊¬ÔTßí@Ð-Ï'cÏ:F‚Ê*œ™¬xêÏÛ­(vhÁÄ®kú„;vš:‡p*H)p£"™RåÅRàN¸£ÒÎh˜Ø†U¿kà]Ü!ˆWš÷=ÜÑ9÷ÑfMžƒì¶Š;êÅ·"\qÇI޼sͧóÑÎ^îcÜ IDATMÊ ¨ÛZ×üDõ;᎞U<Û=œ<®®áŽú!–¾iWF%îNׂ”ŸïÚ2V׿£Þ2⎮ictcÈ{¸£B5e+]Ãõ¤Ùõ½¡™m[µóƒ Ô‚E9 Èå–oñ;¸µŠ^¢Tg¨‚…U:¼O DfÎ.€ºVÆ ÂSÒ¯ÚæJÝI˲ŠcVêõ¤ÝÈk·å¿ƒîäQ7ôUä¹ vöŒ6´¼Ï—Oìá/U¨Ù9¯Ú#¸ðûWyõ°”¤,nÛ¦J+z Ó¬’ó»æm¸º(Ÿ\V—*0p Ä®NàÝäU|²B¢ZXÉtHpkûŸegÀv~]ÅMª*#Zs;gNkÔy:˜V; çõïgW*µÉ$ÊCɃºª`VÖê~,0µó¼ÏX<ÒÐЊ ]‚“m|ê¡´uê }×ôžßâ“ÕJ¤ ^º°`¬ FºÇVcÍöãÞ¹¹ULJgÜ'sãQp·7W°qÿU⸕=‡êõð±S¥Z’Å”]ë:ÿ:©¡•F´ý*X1ÁrvAcQã@ÄĶE “íU†5òþ¥#[PR¸â0Òºì›ÑÙ¾°ØQœRde­^ïÙî|/î°c´"{ä#Ü¡¼ìö‚ÝŽÎVúß‚‰ûMÓëâŽ%ñ'ñ %ÕÅ5ŪŠ;ªJç,Þ%'Ü¡ìô wHU,îX ?ù>Ļ⋠‹ùß¿ƒ;jf-Qܧ¸Ã}YÜá·*îpfËçnÒb›¸CÐîØÚòZ¥¹ŸpÇ d§"ˆ…ºÏàitÎ}„;LÂ<‡íòw(l#ÆOq‡Åܲ#ö,.’™/_¾\piwP-È-è¯*HÑøjÙCÑ¡nµê§]¿ïX+²þ?ÿùÏ ŠÑ†­¶—hX%¬ò—ÐiV§ƒe D»Fû™cY´Š¢úÜmÕ/¬xyh[)³‚µà*¨Åf†>W„¤JYï9 Æ×&ߩޠZPle×åü‡*`ò‹­†ÈÓõZ¯ù uÓ{oÊÂÖ4µæ]®­©&Ø3©‰rÿ­àËï´Jo j[H¥·Y ò@ò¾œ;1±b·{Þ½ísîïïßTØÚÅ\UÍ÷0`µ}Üá~5¸”r¡„é·oßÞøJÕT×âvW°`"­ËÁoÁ«ÀÙ ì–7 ºF»g‰z(µ³#·Ù.Ûµ5½Xúððp!…©¡Ÿ&·ûfeÓ­þYUlµWÿšÅ„çç狎Á§ùë,Vy–Ì;Hê²`ÞN“qÔBƒ³íþîÞfÂöÛo¿½‘S>gø‡‡‡‹B‚ÃóšÆæ6`Ý^ýþýûÍÝÝÝ«g3”[_û»x êw)•»„ytŸu’¶þµhgÕn‰@ª*”SŠ–1ú4­¹]š“"×@Ú’Úhï]:LßbJgPŠ;ìZ8wÑxõøøx1ß¶KÜѳyÏï=Ü!‹ ~Q%}O'ܱ½±­Ã{UTU–¼†;dyìÏÞÃ[;û'ª¢Ïõ=Ü!µ£gLQªw˜Ëy'«úÃÎ$v&¸’øÅ‹§Jkל¼]IM~·Ge»w(O^³íÅvqÇ’îîØýï:o7?¥2£EýŽV”*èÜ¢ïV³äâýj|ÇÚ5 K—5Ua¨½ÓâŽýý›™³®¶ò·¹Êã­'†CÄêŽ[™RÙe>©À]d; *-´-¨´¥™w@+:»*?¸‡¯¶þ¨*Ù‚[Eh‡»Â-†V…5#R­Çj”Ê3'Ã=e4Ý4“N) 5Ëò@ˆ9IòY]¬¦øªxvd¶4p[±TÜ@ŸizÒ’t¦vÐ^J¤÷SCªUôP ¾Æcn49ö\Vvö3¾¹·uí-ÕÃÖq‡Eí6j´f¥Åɪ`{O»nµâkfi×Óý¬é­€sƒàv¬Ìœä|= lÝWE*ßö¥•v]ÓÝSRÇšDZð«¬ÌåÄÜ UDÛçmM7qÑÌ×8¶½ãà£=Ÿ¬NK5¬×ÚM­Lµ]<çsðL-p´U“å]Ã|6ÿà0a¶åšSšZ€ìûÜïnìšö¶¦UÚwXÈŸ$›¥.K±r€·C¼[Ï=•ñÀvœêõb'Y5ºqÆ«ŸÆ]=n+ärš›’Fä Lýãv=õ—«gЉ¤@Ò¹+´äËí“Ãâéò&Ìêîj3Àgåùgp‡E«áÏ Ád•ÿÄš3Ö³o¸ÃÏw¸v¬¦k‚èžÔ §¸Ã5)­~GâeyÍÅv¢Ä-0Ûwl¯7a1öÉ0Zì*îØk7ð3¸cßc7Ú÷«Bæ~ÿgk aÕdÁ÷mwO ¤3HÎ=sÄ=Ó´')îØ™àŒÔ wè¡·„sE )c{þ½¶ž¤ø?¶®ÞÐÌ솸@U˜FRMø‹wîb?¿ƒÆn´€t?¿ªÞ*Rj»{X9¸iÇCÙÛ¶Ô¥û()+ÅKš‰IŒ‰Ÿ¦•Îý¬’©f© ðUQ¬ƒˆe•†UŠIÕL*Õ¬sÛÕ?¯2Me\pv$ä¾Z]-‡SÞ¥ ÞMÞ–¶•º6¯òWz‡ïªhÎTTÏ åª$U4ª1™Ô •E·Îz ¥tË žž{Ê1@]úQZ¨.wkf†_&¨mA 0z'¿×kåÝMˆ:^$ïÏ n»²Ù+­¢ÔR-M6›¼¹¦ú)¸ÿM6·{–v2k8*Ëõ[Ñ%wåí· ¨<´t®~o]×h·‚-UÈ:ÍøØ½u-J\œr Û‰“Vbç ¢õX±ŠízØ(E« Ÿ¿¿ûßþ¤UJ¼Uy?ËÓ˜-m³1úd¶hŒ>ÍNÿv€õkqEÐÒ„¹TÆŠa´X#ÕÕóM wr¯Ü½†ˆÎ$r|wTLã=Üᬬ úNIw•Þ*õ¯’û5w 0Ú*î°£!3 óEÆÚ­éÏâŽÒ4}Ÿ£íÀ{×ËÏâ;1ʼn֠³ïõ„;,V§©àéû<Í„4n›Ô×Ê‚¨{¶³ïJë»O?‹;ÜŸ&©ÃSøTÖWŸp‡±¦¢í¼~„;þú믷(ºÓZ ±¢§Ë»¿`X§i•]™:¢ äPzH˜p]Ëdw?Ò/äožÜ«ÆäíZMr&G a7D`k'GO +ÍÈ;ô¸ á¼D+wv_šÖ©ùôü¢óÀêæn²ª¬¥mP)8ÎdÔ(³ï´‚¥áÔœÎ@é aùÌ‚¡ñ—Õ}ß5Js0Ô‘]¥¬pÕ·][Ã6)e^ã$‚MÞvUÊŠY•Ëq^¢u’.–s,gXjÄ>ÓC³8šNÆ|&-­Æy½§9ùè¨v€ªÞ$ð€5¶ùþí–Ê=þóÏ?/ŒÑÊá®ó‰R³õî,W©DU`ª'LÕý\ÇRq¬fù-ºX1¶Ò¶59W Ý>O“ß@.V®Ë^‰t}r¤L˜À ’Ò[ j£å©×X}v¤.úÙ&ûZx¾Œ¢ã÷»æ›JÁ{—"²Xh·¹³$ëØM}Ï¢•ÖÒí2 &\Ó»i±ÊÛÉ2™l÷¥Ÿolp5Ö·Czžçž=Ò–Uc¼†;’¶ÞçVÉteõÒé™Zªsq‡âÎÖ8«1…§VÙý¼îhؽvÂ'ðy wt¾Â$º”DŸIštmMY±«¦×Nq…]…vŠ[ iÌxqšßö½wÔPݸtJ>l.ˆ;FŸ·{T ®iq‡Â'Üa"wÂÞ‡J“/°AQÜa·×B‡ì„Ý—2è )»þË/¿\&3M6ê°j_d7¡/¹Ê*R׿}òíÛ·‹*±àßáÜY•)O~^ féSêñ[qPù¶{À«­îœ‚-wÏO û½ékKY¨§Îxü{?~ü¸¹»»{S±_&mBP¥²ÓfmG­*kõVW!Þ”–Ó[­ò%UÒ€ÌJ•‰ƒôЏ¹¶¡ë/EÁ×} — }ƒç5smÂí …•–Êèê¡#½Á®ˆÊvVlí:k¦³¶©ÊK[îOuAþ•~-{Ϋ¸¸wFƒ³å¿·¼zßáüŠô´*©/µa&}Ì!g+cý¾‡ô’­íñ%ãú[©?I&K ÚgUÊù¤>Ù„ád¢Ø¤¨†–í˜,¦-F¬WîÚŽƒ” ýoœË«Û·ê‹5wuÖE:“É«ëÀyGÏçççç o˜žå[OŠê¸:TÿÏ‹5Â^¬kÜrÀøn‚]%Àî(e­s³âwqÇ~Vû•úLŒë55Üa÷¥TèâŽÆèŸÁÞ› —¸Ã³ÄÂÄα÷p‡ê«ÃÒ©MÄe œp‡g…ŒŠk¸CK ¿ë„;Ä|eu|„;,TØ “¡ð‰ÿ8‹×3I‰z;U7û îpvµïLa§%-ιç®áiûÎĵ(y wì~ÄvwÞÃõôw¬#·ÎÌÿç ÖT˜ æ*œTw\̶“N‹@N´€ZWVŒ*.|gMö`:Œ¸µ¤s ^—4±A™Õ:¤.ÛsÜàUuø·Y–ÑØf°æ!Õ@l{ß #ÏÖŒþ¤…ne_I`+«òv'\hûÛßnîîîn~ýõ×WƒAg]ö9 þÊéÙn·%ÜóÃë.äµ°U¹Y€µ…¿e“ZïÇ„OÙß*@µÝm´ë2`«Aß ß€ël”ïDå-+Ä/K­ªB‘¹ˆšbÕCJq€íaç©I©PeYYØ‚s»­HW¶­UQé$UaQuðïÿûÍÃÃë¿‚G¯Õ®f¦ëL÷êš:#áž6´2gÂÜW”zû”ºi‡Áøf¥¬³FT®»±Ï¶ÐÁXcÀ€kq¿_e3å 5u®é²×íZ>%P;S*H³T¬ú¾Š°3 î»rÙ-Ph*èÙ$EsN;~u_wý šÊNøí·ßnîïïß(gJˆÙ••ï_o¹Î[ÚTøàoûÛÍíííÈÖL¶>cb‹ V“¯áŽzwXع†;Í'ܱkèàóI|×?걿dÈ5²½&î0)w8Kàýœp‡óŽÅÁyw¸ÆMôIJ*+/Qºß¢déÌÊ[L”ÆuwwwóåË— ÜQÆHq‡1FÜa'Ë{5–”’-îØ~¨¶ø[ÓK×Jq‡±ý#Üá»)çð…fqGi„×<_õ³Ù}X”)yÏ¥Éy»­á ,®…}¿â'33ß¾}»yxx¸¨ÎÈE´zgµÓ࿌N37yx[nþûßÿ~Óv2#«BBÇš­­s#_Põå]à­ü¹™« RiE«qõgG^Ío´‰€­ki1­øš ÉÍ\™ìÞ°–^`¥¤‹Ôw²{›:…ÙýªÄvͬ¶º1Oê=ç™ ùüGÛX‡eÏw}/äëúä&ö}©ª´êØ‚‹FlR(êlk]Àà½ìs­û.”>î,˜­n«:ª,éͱ}Úªeµé—.HZíw¶Âw(UtО›²­ùu*­Ð·ke%¿ãz–#Ý°àØµ¿ÏxzzºPâØj ­HŽ*\¡t´Þ’ÖËa{ß1ÉÍ=»QìŠ9GT¡•.RH—ðî3F}p†`”VcôŸ¹ryÓÆ¡í))]];-ˆUa°”d‡›«0ægooJoÙó”†cò¤|xŽ·þÊÕh•–yòæØ;ØzÛ^›Š\þk5ÏU!ÔÁw‹z Õ ´ƒÃ¾£%=Kжž÷üîýýûßÿ¾yxx¸˜Ù¨üù©ËZܱ{–j&5·óQg›¾‡;Ú±rM‹;:üYÜ!˜, ðîP€£¸£6'*];û•Ïý,îh,+æ3°ˆáùnŒî öî(Æ(]RÁ!Õ{?ƒ;Fç• õüü|swwwщԯFÜQZÖžUq‡¶ÛÅ £ËŸâ‹ì ïEœY•\ã‰L»Î5â­÷Pq‡kïgqGçÛ¶_.hf¿þúë+ïQÅ›R¤<´Í)Çw›×ƒÔvþüñʽ¼¿¿cx©AZí+3lP°•¦¤´o¯œùªüަ´k°Rêa}r¢ä8WÓŠry˜ÕoëÎ÷f3­»²†”5KRv¹Ò¸úVÈAÝ\%ßQpYµ·R‡dOƒ©ÛdÚê5ê÷beSMx+ˆRÎ*N!§|ƪ-n¶?~ܩڌPê~{È„Ê8í¥˜è„;ìžpÇÈ–vÎRŽúI©læƒêjU¤}ã3càÍåþþþ‚sª¼îÀìo¿ýöJè a«‚­ VÑÁ¦bÃNgaŠ®@ÁÚþùډΪ˜EªÂ _y g/Î+›[|&MÆÜ€­ Û®üVòR*–™Õh·è;²T½A£Êq ¬­p:°g%ï».¼bVwm¥*óì@îÉÌj•£)÷8Sàç`ô{ð`ŸÄõÓÓÓ(ß5·ý}â–Ûf6©”ó-W^Ð-Õ°rÇÎa˜¬mMë‘0ú–&}¤¼Î“÷†A]iïhuh¿•§*·høh…¿óIõ§¹Ö!0XV_¿•þ“ƒõâW9ì V„©)e; ãP7Áõ¹/!Ù)ø’¯>Ðg¼èÜ€ŠNU›rÐV¨ÏIƒh| ná*-É¥Þó|(ºý¬jd2KíØ:œ+ªy©Uqçkt<úƾÝ®³ÁYŠ´VqwNš(ZX’*¬y®lÆÓççç×ÙÝRšÄQŸpG‡çÛÅQÀwkñà=Üa2n‚å,œ¸CåO•K«x÷õë×›§§§wq‡àµj\ÎL´‚Ýäã#Ü!ß:ô<-®;uÑ?‹;ô:áϸ2oP©‡Qq‡J|‹'ܱ}¨WqÇ(ÙÚd(fTAƒÎ¸¾ÿþŠ;êét w”º-•V„D”LÅb¹š‚šLK;C´ä™-îðù[p“©r*‚Š;ö;ÉŒÁt/o•A áʱ—~{{{qAÞ¼ i~J{Öa]U*œx“Æ¢£¨ {AòåI ­€ìºNƒ—ãDËå6ƒüúõëE%f`×fÆl«ÖCJoŠºPËŸö Uº°à¦Ê4RUjš&7ÜCÂÌ[SÌ-:« fýÍw-ís—$I·RcÏkƒurXç ûüã"ÐîÐØ®¢zð8o è*=©nßÎ<ì}ÙɨӡNéjÕUß½ mª‚‘×ßöq+{îsõýíšüøñãæþþþÂ\ÔnˆRÖãÛêÄ-HÛ³—bê+˜k"bµxqÁûÓ«£s Ò.Û³êeÕÚ=¤“·ÃÒ›Ú™›|uþ£ ûN“.%ÝkT¶$UÇúºŽ¯£´½ç!ÝÁêJ§:4¾çä\”ËQ+² Mµó@;=°¤ÿjR\«õ wN`i?wÏJÖª¨é³Ðfñv`ºJb*ëx®£v„í(h&éµ:gSóa­ÏSÀScÏ}fUŽœS¨ì¶èçç狵¶kpnu¾@RªœÇPë×µ½=|àY¡ß‘ïËd^ÜaGvk¸¸£sEž)ÅÆŠk¸ÃÏîÀúG¸C…Oïϸv’W¶;³sÀ™ï_=ç&œówhÄyÂM†>‹;,&º7T>ó÷÷®jÉáü亷Eò̶›+îÐ(¸"»ß‰×¸F&ÐñÏþó îPœÆ.¯EËÅm™D^«BTÆ?»Û+Œ-–ÕWN:—]o±ô‰±²ïÞ¾´`c«³¢M;kéûÙóß{¯€ÎÝÝÝkœ=áŽÅõ7™=h†ªX²ö ÓO®µ-½àÂês«Ð6;È}âdïaj˜X Y«OV¶¥£Ô<Òª¸Ã~VÈ\ vVÌ. ¨Âƒ2½5æ+Þïi2Õê½gé7[œ534¨6ÁS±¤ nfð¾7Íš4Ô³£að´ÓTŪ:ÆW‰ÃÊÇ@ ­ìý÷÷E©PrNÛ5°•âèt•ž”‡ì)U\cÌí ¦”%%ýÿV‰{˜) +Í®ï°Ê†˜êg#õ¤­íP]0¼V’Û³@B ¥ô÷¥IÒ+G/s IDAT*¢ÎUiÈÀ¢×ZñÕ•[E6+•¦.å„ǪØÉ¡^ŠNÛ+¬ZÑî¹~®•¶œe©*d‡L uoÏšXº?<Ô ž¾ïV|•µ¢yº.c\gKZ€oñbë¼Å»¿µp_ï,ÏEc´ÏWq€ªVê¼^%F"eâ'¸¥¬´*ªÒœ‰[%ý¥—Y<è¡¿ Ðsïrë~ ¥ÝTg_K!tMw]ùî;—ÔùÓïºÞÞÃ>¯ÏàŽ2 ìPO†YÜQÊþ w˜XYrM;Э…ƒb!×pGñÑ{¸Ã*ü wÔ Æ¸ …Î"´‰Sg(›¸‹;Œ¡õ:QÈ-P7Þ™ä*Òt wXˆS]ÑØtš5æÌçõRw¨\†€ïX¹ç­q‡ ‰±ÐxgÇÍŸ…¹k¸£ì Ÿ™Î¿X5\âb°qˆ·îÑrf×öÛBˆÜz0ln³º ÷9&«€8„½¿Ÿ÷ó_^^.Úó‚GÜtÌUž((j UàÀ—>°cë‡Ý‰³ÜÃ\Ï›-¾¹¼ª|âºZàÎÜ(;Y#8ÁЪ½˜ifÚ5c rs;ôþýû÷‹.œÉÏIªVØäÖŠr+úª† 6ýçñññ¢Ó`2.O^à´µ0ÿ+=Mw€sïskZƒ´À&»ç9åšdè÷á¬PÍ3u­Þý|ýúõ58®› ˆjnõÒêžIÇÍÍÍk7Æk«AnE)*ðãÇ‹gèarÚç‚Õ–ô…hE~€v÷/%ªI†Õ§¾9ð[Ó ªr•—4Zu7Îì-º²ºÝSòß›Hl=(ã©BO {nóP±;lRëÌȨr[“RRF/(—Ü._=ÖѼ횥J^Õ¸1Ú"ŠSßû¨¨‚M]¾Uà[‡Áù+£&Î\F—òÙ[Áüúõëkyï«C苯õRýç¤T&ð»U?j⻸6õºª†©Ö¥jiU¦,²tOu]áÕ L$·‡(—Þ¸_Ï qǪÀž‘{~ó`QñÓâÁÎó½«í=æ=Üñûï¿_Èá«væ<òÖ´†‡'ÜQêá wì]‰;TÚ,î°äj§øùùù¢iÆý¡B–~S -}„;¬òwníî¼ÿþûï¯g‹…±k¸£É“ Y×´ Ð wXŒ*ÍrgQM°÷Þª>ipÂ)ÆòîÐA£Q Ã¥¶w(S/î^’úëlžñ³êt‹M'aáŽ7>3¥ìðx|||n,åeQR ä<«-^n½™™ P½lù•~ Ÿ/Û@YÓ*˜Ô‹BsIÛù¶ùvïkç ®«‚Ⳬ{j•-<<¬n,pJ£ØÙå9UüàP>)1ÉÓ>9ÙZYðn…Ê{p“o ,pYq¯#ò’Ìh*t g‚€ùÍš*ëg5}ŒÕà­CU÷¤,X=ÓÑYÅòzooo_éjU¥Y{{`N*‚²¤þû§Üußß~v­]Õñ¤tŽAsÀ¹ÀKñ²‚"¿^ÉG}+N´› ,æ­8©Îc%¶Æ`>ïfVæ• wª±Æ"‹ÂR.äÄŸdß[A“2XÓR¿c¤ ´ÒžÝ_ HÙû°+e…xã1dUÖªd³&‡R´Vµ Yº“t†%'CL»¯{?î³ûûû74Kev[üØyðòòò:c<hìV®ŽgML’LÖ`î µ Œçcl%­4›ÀÙ‘Ç>€#.ÐÅÜ}<*¤ç‘kÚózûFÁãî wt(Ýî¼Rü>·âŽÎs”>9Üa ïÌjgøFÛ´Š^ÅPm4ÔìÙNEq‡ NÛç{?ÆaÁvmñÿÏ®ûzçíL•*'î°Zo—¢Æ±âŽ (ÙÑ5Y—ÕyHÏ ÷p‡…+qGg+}nÛŸvNó˜‚yqÇ®¥ “`ãA¥ŽG×´¹`a«žXvG+‡Åkm‡Øç·u¥º^ýƒN¸ÃÏé0ÿbôžkçØvÍ3×µ[ë¾SÑO ÿFš¹²uå<ª„$Å.-ÐÒ=ZeÌŠÒUVàhÀ”ïß¿_tЬ[ÍÙçíE°÷TŠÓ¢~ *i58kØØJO†ýOðP“)»¼SØâ·ºä`¬2¡¨Ù<Íég}‡­|Ki9ÑìþYÔÙ:ДÓî’‰÷€¬<éªNªÚäç{¤~Xí3nÔÇfò———›ûûûWï¨ú©Øöýû÷×.Îî_'xcUÏ>ç<”J6qªcÑmÏÃ}"uÆB†] †¤–[¹>yH­‘¶æ4C´u›/ºíį_¿^,¼]ÌV-¥Š°×1QîááábÈèB”÷ØAK+dÕR÷p,ïÔJ©T>+ãC+­ÜÕÒ*Ílñl^ǤÃÊì6Ùª@{‡kÝÊ«·+S:“"ÄYá÷ ±“¨Êؾßà_E*éê—b$pTgÏÄûjR-oÔ„ÀÃaPÅ%öÜ «ðí^­¼X[0“Ò²}¬Gƒ…‡=Û»»»›»»»×5W…­ÿÅ gëcK]z7’•ƒe¬ºï kë^Nf]›·1l R6ôµ€|ÊN­úKk²U®Ú‡øh,ûާ§§‹ëÛsÝB\`ÕûÂ…î ÷©"!‡YúU]b÷szÔÅ»íly—Ê{Û  ¼mÖ}_ö¬Öy½VQZ V:ÚV«Je8«åoETmy¹øä···¯f-l«³R ž£|Éó—æäúrʳÞï=??¿þ¼ÎuVTHÙáY:¤ª-& ¶ÊËP2wÁô_ÿú×pûÜŽU÷UA÷³¥í&í´TaÌγ‰ìÖüê=O}³÷s»–qõZçñññ‚æç¬Ù*¬ÎÉØµ]RdD%"ç¤% ÂwŸ/† øšÐy&-é²;*=ÜÎWý†‚&¯î ÷õ>C daÇäBŠÉóóó«°ÃžÝž÷bžr»Š2ˆ;ªXu wŽ÷L«´Úób{Õ×~W#ÐÍ[ \wŽ;¯«¨‡t®&‹m~Ï~F[Ï:‹;Ù»?Iý‹;ìÛ©ÑO¬RÕ…,X-áØ™µ3G`.îpþoàß"I×™ÆB£1X*é w(k­äºÅÎ/‹WÜÃúÙ(ʳ3ߊ²[®á)糦¸cûÁÄ}×PãoMO¸ÃDe1r¸ã?ÿùÏÍýýý‡¸ÃÙ.^ëØõ¥Ù´Ý¼ÅÕ$í‹;~ùå—Kš™<äÊʶÍi¥Ú6·W/^Îø6þ.ÌöÑùþnßSgp[–&5¶–OŠmR5ìΨòå¡áÂ×wenÍàêÁ&P¯±—ïwWWÛÊOùïÍm.šf|êªkTW™]õØkXµÃg ÚÊí>Üó]ã†E·ñõðp`ѡ섬!¦×ç¡në¹~»5RÊӬ뺊’£Ué°Jíß +ÉjÂ[E«®ƒ±ïN]ûJJŸæ‰öL7âókKÞëìì\ì:“W:/sí3MZ껲ÃXº¬åvÝãR>¬Ü9«á:,rnaáÄ·.ý¥†q<ˆº§ô”°£â¡&x–i§É8¢pÈîCAÁꀑgËÛ6ÞJ™Ø>êaÚ5Uµ+‹jVI£[ðÙ`[WÉê{ÙÒ¤üÌŠZøl;NrñÞ£ªs*¾Iq*µT5³š³;P¯2;t;'&t ÉnL)˜>“*[lÕ×d@ªÌºcŠ®t0¾çŽ{jïËîš1ÃäÞbÝßû5Ü!˜ØmSŒÂ³¾4ÉîOœÖ´´Þ%?‹;ú̯©ÍUÌæ„;\³Ò¯V8°ìïÛiÛóØwì>}PQQ”vŒx.|¥ÄR÷¥^{íÅÎ Š;¼>‹f2wÄKÅ5a¯’¦BÙ)žu®E;ïá ží²4>ƒ;®M_Ã5Ìöç4,Uüé„;öso:o ¯‡þ2§"ùU.2ûnb±vÕ‰/,Ee’“Ôh/åÜ–{Xν ÎÍl•AºÂZáê¶"aP3)ªR’ÜM5î.ŽÝ‹UG;a¥Ë´Åé¢P°AŽ¢@ÉÎŽ•Ogšêt®ìž¹F„{÷r'Pêõìбº¼~ר‡žôCiå ÔŠ¨xåpº¼ã: Œ;ÌwR–Q”ÁáLž€V{*ím@Å­­§}çŠ :´Ÿâ€]•=k~ÕoëUt~AóÜrò•(uÏtæb×(Ø”¸Öë-U°Ò™—Ó»u|Õ9ã••¿ƒºîìšÉcwÎá´¦&ˆÜ—‚°ÒZ¡…8\K>ªO<M²«ÎÓB€÷fwÑÿ®BÝžÓ>_:š{MeMJóÆ]×Z¥âÏÖ‰ë{i±Ê{±ëTeDGì ±T"ç¤\kÎÒØùñç¬l+Ñ_ŸS1¥]Iç&¬´›$‡LP G!·€÷Üq2õ;[D´ó_ÜáÞ3ɶƒ«*]çx†;Ti:yÖ¨¦§ÔÖÂpG=^zvŠ¢º±×/ª²ÀâŽv;íò›„¹ÏŠ;*:âL¦lg…”öÿopGgÐ’BûsŠK;§gŒ´»ùî¨T»ÑJ¼;CvžÍKž* ðî8Q2w†}„;ºº7d4uKÕB ‰½1°÷|T3[UÎÖª²…%}aj5€¬˜ÈÕ«Q‘óf»»yùwRz@íAUµÉMVŸ”«V˜—8xpœ€Z%Û­Á—-ðnX©&š¢UiÈÖ3n°Ý÷ÓÓÓ…Û¯€­+k/–gªá’4'Š-ÐUR*"`÷ê®.·¥ƒt_N­à¦tɣ̈́ªMÒ6tíõç xº KO9™ ®õoU½ÉÁ@ᨃ Î{_‚I«Å£qHÿ4ÀXñÝ=ÕÜËßq6Á„³ôÒÆƒ@Ÿƒ€Øç©¿@‡Ô]Ï*­y8/ì¹ÉßzzºèPîs×®–ë«ÃžK•wíòxK—ìšõ”~âLŽæÅ^ŸI^!Cv+»ë¡ ¼¨ëÃdĸ¿ï²r¬úNîÎÄÔ±ZÀaµÍ½a"§ÃùΣŠì@ÜUÃãrH"VÛlÍë4Üad«² ô¸¦€ág9l¼áËV›•@µ‚ê÷·áðë6WgÜVTë!±?“s¹¤² Þ`9iG+Ç&rA+¾;“ÊÓÜÎþùþýûk[yëééé"oÍU¾Òön+ö'…ŸÒW‰µ›±–º`¿”A« ´”ÇÒ« „Vge~–Ò&Ú6VÉMÅšíÉ ;‘¥úLVØÊœï[‘€ª[iaÒÉdl Ú¥~ÝÞÞ^Prôñ™J[•oÝê«à¾kÚ;cõ}h•[9å=Ûÿ:ô­T¯1Çä×?¬l†ÒVyØV²[ñ­Ôn;Ö®ÁÀIÐ$n`Ó®c‡šKað½«Dh7¬*S&+®ELÜ=/¤ƒÕçE¯-)tUE²b[Š”]¦Ýó$¢;ÿf7@çLƒç‰ÉšrÈ]ÓΘŒÙárat¶ÅtqÇþ[éåp‡ÝÍk¸Ãy™uvÞÃOµ VÙù|þ,î°èjgÜ$åîhGßÏ0¡°òÞν¢×p‡ŸWµ5'ý îº*˜VàeÏy¾ùÂ}ÇÿkÜQ¡úè|wÜÞÞÞ|ûöíB¤Ã}®¿Ó5Ü¡tô wˆ}RÙçwTŠ\ÃV“³ÿwصpþîðÜ8uÔ)ÙuŠÑÉŒô¶4÷ ËÒÚú—OnEÒ·j‹/¢Ò•K†4›«ì¢›Ã‡¦ëì¹m{¥ã<UGªî¼æO&':º N\7#í&*wØ¡]Û‘ë0Y‰P³Õ?e ÔK÷R:ó{Âþ¬LŽÿw8WU_» ׯìœp‡æí-*URÚî{¿S¯ ªÞ®s*¥¬¸CULg|r´ÁùX=éT)t8 øYÜ!ÅPš«¼A;*î01n¡¨Á“mI _/’™=¤½l«}R”\­c+‚)Á„TœK˜¤ž€Uº[Š ˜”Ò«ê¶^^ªÐ¤êl7»Ñ=X–™¯Åºë^RaˬÊ&•ýìП45ÁŒU1«t*Àìg¬:Ä5~ÿ‚ƒÏù¤Âµê¡ÁT\gnlVQEz„sRÒ¼ ¤¶‘KªÀ™T)ëgKï±K³µ¢ãº\O…vV¢ëx[yÇJ3¯Òd‡ÈÊ­qÏUhªÄ”yFÁ}h”–V± ¶Þ³RŒV }JE[m“Û=²Ãcæ\Ô Ê2·Š&ðVDÂꤕª¸qµÃ¤“•K僭 )§íagÒV_!+p‚èýNµô;;' ¤Ê{•úõ`qÏH·Cã\K½\ÓŠ¼”›Þêª ¢]»,PY¡[å{ëÑn\sŸ»~¤t©äSå,“ó­«Ò{çÛ[½p÷µêCvóŒOΪ < ØvOìw^3Glcrç[öŒëcŽƋ{&!ÆŸi='N>$.'Ü¡XIéUð>ƒ;J{.îðiÂWÜágˆŠ;jÐUq‡Ï·ž[Æáá÷»kPÀ,­pkR…ª®N&ªâ«ïÎ[‹ñv-Ã+bÕr¸C:¦¸C[‚vi-ºˆ;†#NbPš°€³ï¯ˆƒÝ¥­—Æ£ÆAq‡ ¸…úkïÚâš‚Iï P¨7¥P;D>Ÿp‡J–íÊ/6ªúø3¸Ãû“¾èyaà ÍLº‹**;¸õ'ØF[kMS1‡«¤I´åkFk¥bÌ!>)nU»ÚØFܯ"• ¶4ˆýO®pMŠ—éÖDÐàõøøxQq²‚)=¤Lùi%t­l.8YIRë¾þŸzVø­$ÙæUÂÙŠäK~•ÜvsìÞ¤íÙâÝ|G7…} OtK.‚¶?¯\·Õ«¹sèmU›³FjVy˧Ý~ÐÉÜ.‡íÞmv®­ÌÞs«$Mç½ô"q-Ø‘O®¬âóóóëASq‰íOik¥(X-ÔÙÞꑲÆåöZ «òÙží‚´½ BÊTòÓWA_L°¨#¥£íw»H‹1Îãí¹oM+ÁÝæTWþ¸Š…M¸¤d¸W:Lí,N¥Zå•/[¼Rþº& tØ{{¬Þ ª~æíü™è+Zò矾Â)ÁªbÞÝÝÝÍËËË« ýºX•öÎØPUp‡¬‰ÕhΕDÞy8vƒ¬;nU[Üuì:¿jO?0gH¤a;¤VJM5ÎK³Ñ ¤Bì*™ä™ ®º.ͤâ3¥OëqòððpQà Ú‘óڔĖҴg#î¨ø‰t;ùŸÁ‚Mq‡?#îh\]ŒZâ,îÐà×_½ùöíÛk nšH“Þ-ÊìÚQÜžp‡:ÿnëÊDä=ܱ÷¨àŽsžÉR±ô³ø(n©¸ÍpW;Ó“V\©†ïáéu'Üáº÷L3™uîmÅ•v¶—ÈŸpGçøÄÚ%ÔïËNšØGÜa‘êgqÇ®ÛäDÜáZ‰î=›í§ÍtW¤ikz˜é"™©R™™ƒ8»ÑfrJŸ¶ja`@aÚÕR¬¤í³ëOóøøxÁÕT‚ΠTµŒ=¤É0J?k°Ü Së]Nk(å÷šLHá±k°ÀQŠMM«ôΰJâ UyñŠv…t•·ã3þ÷™;½m”)Ô½ÙJ³]½¶cMޤ :;¡ôsd5¸kÂ`ÂR ÎVŤ*Xõ¥`é%cµJη¿#m¦mWéî‹ÇÇÇW.ù¾sÏs•Þk»/¸«ªÌ®Eà¥ï¦gR¼O©]U±jÙ!¾J+Öá¡§1¦®Ä0A­3]‚:¥JžI––2²v,1±*Ôè:{HÌËÄÄÃX¦g€Òœ&FvÚ¤tÖœ²´C÷ü‰FkÂmÏ|ɆÒÜK˜J{uOZ-Ý ÷ÝÝÝ볈­rŽ”x©AÆIg-ÛÎvÚEÒ—E0á|Ø@ˆïw –޽sÇÙ£Ýï®Çn°P3ÙXRZª£@k±|ë×N£¦‰ ˜L(FÒ™šíC…4–¨¦>-¥OµWE¦Îsmm›Ä‰;>᎗¿ÿþûÍÃÃÃ…ôµ*eRL÷Snlê]&Å­¸cïûéééÍà¹1x1Ì®‘¸cïr »&g‹çÂÄ•ß IDATÅz‚t¾Öó^°Ùsâ„;<{ÅRŠ;ví+nÍî:\©÷Žûâ=Üa|‘âgü¯¨QÏšâÏ8Ï9ß™Ë÷pÇ5ÚèÞÓ’Æk¸Ã¤ß³Äõ/Ýk±Î3}¸cøOA…­×Hç ·&ÃÎ’KW3*¼accïɽkn|ݵ}f<ôvsÒš¬<^“4>ù˜)j´´ `%IZ‚} a7tQil@´²Tå_²” yøVÎOMœÖuXµ¯/] ë5˜á;O1ÀguÄnÊ@oõ­èšPZ‘¨AE *N° ×ÕÔ× HªU9¹÷†óýZUV¶Ù56À×ßu¸Xx[¼[·z3lã¬sf×ËáÞ ´ k»þä§pm¦Å ¹*o[×»¦Y7À”¯[éÎúH«“ö1À¸µ-‡XjOA€ ›F®V—ÖApiv'¥µ¾]Ïv„ììžGop ihx’~¶³×uº+Ùz÷èìíЧϹCØS+È«ºµ+$Ý@e3ã˜*a:žÃJQõvæÈÊœ¾ÊnÚõ2I0>mÍVîSð¤÷‚Üñ½K)ƒ&ÌÒ—*[/»Àºr¦Ò-ö|—ĹŸëÇ õG Þ9!Õ}.{†*{î‹ÛsªÀÖ¤E€&ÅÖ‚ƒ?g½Ý:ã«û°òãzŒ¿ÅÛ7Îæ+,`'OjU•/î°Ps w˜ˆÛE¶óÕ3ÿîqr w쬲Ò?ÜQ êŸÁ*n™¨;[1.cŒ8£³%“wT±ÏJ1ˆîPÑLÈÏâŽ^ãI:~ëY? zb}w¸>ö|4LÞ{¯çUé_b®vüNVÆLß—ÅÅ"j2,–¶ j’kÜÚzZL:ÍœV,d‰Í:Û[Ó'ÜQÆÇ›™™UÞ×=ØæØbWVj—íúý»íwûnЊªID_„Î$jÏŸY`è ’ÃfmÏ)1¬b–™½ vR™!:œ:7 }Íá=•’4ˆÒCF…Žl)%V²Z]zcsCtPÓüù*›éè,µ¢¦d¦Õ0 åÚ¢t ô™$M~Yð$Ǹ’ÐÌ®×]—ãú“P[yñàP©¦fP§ä¦s&Vh­ –ë_p+MÎf«Ç>»¶ýõa[§zM¬äo·­l'uŸá¼ŽPðSGïÓ@ ƒŽŠ7Ô£Æ^Û7¾Ëª ®rTwu+òv v¨Õ LyeA‰3óê8¿¤ä4¤/zàÇÎ×®sÏÒŠš%;"ÎöTeËý¸çìžm¡JP)%Å–ëÇΈ×%ŬsK[Ëzt¬¡7ÒÆžéªÃKj¾j¥Ø$ÊÂ󔌪öã\³Rv+NþJÎ<íY ú䨗ÚT¼&7ÒJcMl%P ­@{Ÿ¹™7“ßÿý¢\JŽóQ**äQܱëZ¡E*Ž•mg:˜½µ»˜/p=áŽZ;¨äÕ!|%£O¸cg~ÕKÅ'Ik÷æ€ý w¨¸å¬Ñ5Üa7\Qg7¯á;y&ª-üÙi²Xy²Bðç-ˆ;Q8áMÚ?Â-‹;¤ÊÔ0^ÙÑð¬·Ø`#ÅÚ®·¸£”Çw-Ö½gFE;÷Îk6!²«U?¤RÌœW¯xËI¹o42©â'ÜaÑÃγ ª7jf¶XXnkWmqiÄŽê!H”b!—ºí77‹úô>蓱 z2¹*˜Ubs t()[ûß@Ï8ÇnŠšY%÷…,®J»8•%Ðÿ§ŠMv˜¤kyxÉCôÿ;l|2Ö´:'ˆÒ©\ W岺¶?­¢Èu(Ð0•˜µõ—øµ/ÆŠÁ~¦ÃŽn+ÂƽÝ–=à­"ïþMˆ­v ÚTЩA9¥Î^í:Ê…WÖx¾9]• 7Äh‚k…FS:ù²ëÚvÈ{ïFÇäýù@•UYg`l={MVmVÁ«™g% {¸n?Û«pˆóÒùú3*õ¸¯:\ö“ßžõ†ÚWÁ;ùTøOåfåЯÂg§Ääo×8wôuÞ&1¼õj|uÿÖ¬¯Þ?R´¤{_LV•4É•-x ë ²g¹}½„jI€ÜùVít·œÑTííñññ"NHîtM«òçõïYZ×HzG5kšç^õg•¸uàw ª´^Á©*„®M+²•*w¶Áy¼:¬«´g£^>gÕ.Å+®î}Éÿ?á“ï÷p‡T½Åâ“hß·Ÿ«ˆÔœâŽ÷úîˆ; h;/â<à”AO¸Cú°*“KÀN¸£s‘õIº†;<7ë{gÒdA±¸ÃäÄbœÅW»¿ÆÑâŽÚw½e¬ÐZI1¨ú ôÚ{6ÛiØ»W(Bz†´Ä»ÑNª&°ªÙηR£!©ª>R»ÂÛ4wwwGÇdy½­X*CX*ÚIöW3?+cR(N‰òÞIi›ªm³oG:ÝÖ½­Z+«•0-ÇákýÊ?ÞuYêð¿['rŸóÖj”íÌîú;ï#“^¨¢“I©¦¡VËLZìžtH²ôE)iRý<¼Û¡Üs8™Uî•ÞT>uï¾1ºR«zþ½ÀÚî˜ÀšñMa«C´•ìhûÇ\˜KÖüo±AÓºªÕÕŸÁnê¨+ÞC ŠWX´Ùœ¤4¦®éÍÉ”’ålTûµ8¦¯‘…Y 5N6ù ]l«/’–zɘ|º§ê_³Â¡êj;{*Á¾{Zâfñ`×°dÛB̨ªÃ$ÿ î± î¦ÙØ»®IE_ Ú¥`Ùx¶å¼ßýýý… zq‡RÑ¥/žÏOí$PRÜ1Ú“ó¹õ³‹¹wíl¤³9'ÜÑ$¡¸ÃΨ¢'ÜqªèÆjrã=hkçºRÙ‚æ]ÿžÏÞAi„írC‹[=³O{³‚žë•íšî™dq`kV<ãú¬’àÏàŽí™âŽ?~ÜÜÝÝ]œƒÎ %P*|Xý#ܱ{}33#Övsé1V¼=ð+%\E°J‰úÒmëz“­Ø+¡Z޽ܸ“Ï€û¶Æ¬²Ví4&7Z™ÛBRùFéO«ŒwÐÓg7š[‡S=$äŠ/8P¹Aߺ–kŽ´÷úûï¿ßÜÝÝ] ¶ †¬Æ:¤Xû­™ò«¶u1¹I+ãVŸªÈ£B˜³XÎ6õÏ¥lØ]QõÊ-úÎ×HMì@°¶ív8Ïm…¼A%~¥.H/*õÄÎW;”þùî½Î¼¦"gá*Ë+ÐÄIz‹¢ú¨@ghI[$:<,Ø­d{Þ·—¦j€ê;Û^+ÍÎêbçväm×sG+=LÊZi”šPZ§V®%×´‡· y"¾3d|«ÜMôíD:£R>¿ ¬ÆÎ'ªN6e·Ñ{츻?ëE&ÕפLż]¯Ïy?×Xb§Ô$ÆŠ¸óG¥GŒÇ_4Õ^,ÚÚ+]YŸ5㜸õ¼ç<€®Œ¾ÔÉâŽoqƒÔêpGãÛ‹;ìü,îPÆZZ_%­k:Zyhc›*bïá;¢ûÅÎ9,ÿYÜ!½Ø»žBâg•NâDÚ[øì}^'‘‡2i꿤Yè—/_n_g—vv¬ðáLŒ÷nQãîФ¹J‘chü·¸£‚,•'ÿ î° eáNa ÏàŽú•m-¿ñ™Ñ$ªÁÌV¢&`:Jñ2'ˆqQ9Ü´LOÅ*“üH•´ÜÌÊXî&ç!` 4x[0¸-;·ƒ³®<èpuèm»xœ;¨)Ôë@¶mì_ýõB¯|‡æÃÃÃÂîD~Uhªk¹ÕÉúrWð}*«lè:Oíì ª­HtøOÀ¾~ýzóíÛ·›»»»‹Al+"J5WNWéNWr|ïÜŽH… r&ÈÒäÉš 䬚lþl·Ó€«{mÚU:åÁ ì5»]Ì}¨<ñöÄׯ_/0ì0 ÎÛòV @± ƒÕ:’ÓÜoEL@rR.ë°Aqï®Áz‰†Ô;+uv‘¶Vµk°÷}Ölµ]ºª}ùòåæ·ß~{MH¼ÞþÓáÛJ0RiQáw÷ô¾¯•ìJwWñFÅ*+ÒR`MáÐ×G*iA§ÉÖâ¾" úŸh”·u³ukexÝ—Åýý÷Öôæ"·¿wh›$ Bh3ýSzíí#‹0R*Œ¥[ªqÝn íyÛa÷}Uj¹]'×¶^5Î…ìšS:ã¸$ÎN ®ï&5 ¶ Ð$Ê.ägp‡ò½*4Ú9whx,X71ÉôÜnB¿µ(>xw8gø³¸Ã®}ç!h÷Y de}Å¥ç}ùòåw g<<<¼® Í?Â~vñÇ>»†ÛÛÿv®á»ê&¾×pG½q,¤ld@Ãö¯_¿¾&$ž­§;žqÂ[O¥ wL°â#Ü¡ù¸kC:®¤âÏE|†;TOôöž÷¼wØ}wˆ'kw6Úaµ³|‘ÌØ~Ü,…ÙºŠJ•ÜKÜ59ÙÅ:ÜìªUt†*N&,‚N‰šßFàp8MÓ¾º°šÔUÒÒn”-jÛ¨V/6øëlGõµmîzœK‘†ÖË÷øÔ*8ôÁ÷{¥Ã,˜ ` œEP÷ÜìY^¼*]vÖüóy ¤ùòåB| •J ´D¨4ui¶ØKS”VTYà¶]}nÞV‰NÀ+€õ¿OãU±½ï¼Œm^gU:ˆ«q ×!àð ¶;'Í®‰©ëP‰Ü¶·M.݃^³\y]Ý+G¹¢™ÜÉI] h +xr¨»Âv”­ +•« &­uµ_ ¶kæ;­³²Ý]”í¬X«ëö5ª Ÿ+˜öº{=Æh©YÒ\—§®34ãË;kâ².€ß)pÞϪ¯Å*)?~~EVmu­:ˆï¥3X§ë•bÒ÷"øÞõIÏQê¹æ„Îd8åžõ¹v¨Y%)gƒ,BÞÞÞ^ˆˆ4.I2¶:3bõÝ^=ŽôC19Q€DzKq‡ÉjÕ»c¯á)Î{¸†;¤G‰;š\Ã>ϽãªàpÇID¥ªS –ü îè¾:…ÀŠ;üiÂmý=ÜaçöîðLQÑϘchE·ŠwHÑÜ~ØžðÜl'³]âÓx„¸ÃÂOq‡4²úèò{ w´ˆ!•Øø%¾’*«Rã0n×ôG¸£ ¸ÃŽäÑgƇëC]’bë­ô$låêt\)ÊX²­7Lå› $Zýô°Xg@0"íÂEPB„üÅ&OVöÜÒT*e- è@š`@ð-€.·võõ[YµRiv-˜X¥gC˜'Æ:tw#î{G‘š(]ÀÏ®@„ƒi†7!mÂìFè ²ÏßÙ.E[¼{¯¶Ìݘ•íÌ’Óª¨Ï¼Ã×Þ§ƒˆ™Ä †*Û(`”Šà:°Û¹$RÊ…•wß™•)¢jå‚×1º®Ì¥#iòirÝî³_åÕ«N¸ ÛuiaÀg¸C¹òɬ÷½' "½©‹˜&¨Ê  lyÆ«pÎ4#ÚpO”nS—wÕúê»ãAluZ:¥´<ôÎùu(¶ªVäíš».æ>g» ΔZS/©`îç)T;­¾Z5†•¶äIA;þ™ï°Rªê&áÎøNN>Jh3“ºÄK›s¹'Š;ê3Õ„_Y]”³&Ťú°ü/¸C èŸÁî)´—Jµ\w±ô1×­³©Å‚Ãk¸£û·¸ckÚ{©:¢É`q‡T­îhwŤ®I§X©&Íž‹á÷¸’Õî¡áæZxwxîVÝ­ªÁ—ÛïØùsÎĹÒp‡3JÅ¥ÂúNm¸Ç=?;†ñ3¸c˜±¸£~û®‹dFšÈ’š\MýÄ:)UµÉ–_‹ÇÁÕôÇ…¸Àg»úÇ7ÿøÇ?.í=äeÂr¹·à\ˆJ*'j•ÇVfg‡m+­§‚ÑÔ2H»YË^DÜDò¥R(¥¬ä¢‰“µÅìÀµ £ª&‚.Í<÷µ€¯‘ÀUFª!Û*ÁhÕk6³ë^eÉ5kà[{Úîæææu8v÷££¹Èf£ ¬8;ð~J4K9éšVØA@«Äk;¥¸îµ=›*e­ÂãaÑ™AãbÇb‹´©m?Èv`ÜdÉêÚ†—Ÿžž.è»–}·óVõ›°KTPd ±MßÎÃbÜöîiP³Ó8Ћ‹¥‹sJ_L|»o\+ÎD ü+EêdEï~2æV|ŸŸŸ/¤t¥¥" ¶g+øÔŒ²4·òÿ¥=YQ­d²”²Ê» ¶¡0 ­G‚îÍ=C%V½¶=;¾ËšVJ}±äñññ"‘~¢Yù÷î™rÿÒ¨´ ÅnæÞ¡kß9±ÄâØ@ñh.M,êKç?Êt øœ“øopG“ýq‡.êíàˆ;,,ì 1Éw´ð×ÑÖ\÷Åž¿¸c÷XIãîpMÛ4¦lÔ¢uÉ¥x‹ª¦Vó^ýw-Ãâ ‹ýÇóäî0Ñ;GÄR*¥KÛ-wxVl͉;6å̸Ïp&¥MB÷5QÖ'Ñ8µÏª/JzζŸp‡8SêøI˜Ëîàgq‡˜Yñ„âG5³_~ùåæîîî‚îc‹º­$«EëÞx8K¡Ð{CI8ÁRåjê×ÁꨋZÅ 9Ã;”MÄJÎÕh±ÃORv¶¸÷B[Ú?ùµ¨demŠ!•cœý²qíÇ·Ú`ï!`«nÎ?þñ‹À%DZƒu{*py¸ªŒd–¿à´CaÚ dï`&gƒ¤›H׫¢ÝæêQQI«¾Õ¾¯¹i.Líº¶¯ìV,aŸÓmÜ]«I>;V»Ž%LåµÛN·õÜ{´ªT¹ZåUBÛïlþÀ*Õ‚®ªÛRÙëöööõ°Ø÷ÕGÅArÙÖÝï¿ÿ~óÏþóM@Ü÷èv-¿¿ 8šÝmO Æ·ÿ—ŒjhÐX§Ü®ÉçÖôž³Ï×{˜ßÉ®G€ß™×êž»4»%ß& VfO´«oÍ–rfg·Še3i­l| ;Mú-(ø{5ò­ Å€ÕI@?¨“ÄxÚŠ›HUšÒRãê@ÿbôŠú–,~:—!}Æ °ûyç¦ë°’þÛ‚y÷²3™J{—Ö«9¬]A¡Ucc¨‰uw—ték$EÖïv'Z|´+ºj¾ª”Å©Ó~¡¸ÃÄÂ$¸¸cxé„;ÃÊãJéC˜¤w _´òoá­nïÛóΠÙîØÜÃpÇ~_Üá,¸£ÂM>-ölÌcqËû4ØY©X ‹«²%úñãÇë|ñp‡“xq‡jµ*Z¤^¼±½®Âžq‹tÅ\÷{ÖúÉw´[{»~©÷×pÇÞGq‡ªˆÆmq‡XU\`Ñ©¸Cú|q‡MÏ}åšßtf:hûÏlÙ€l›hÀÒÃP®eM·:S`ǧÝš€DuzU8' ·ÓQ×k+‘5s¡ÛÚÞ=Zù¨K´£ð0+a•6tG@¦°‚É–Yù*p§J²Àr®ôÂj²+CØAli+>[ èÚ Þ»’/¼`ç®ïÇö¤Jx¥79ÐjÀ–®@fÆ¥`ƒ™s®­Ó\ˆ4";7¾/»sU42Ù¬TóÉ m'(1ÙX÷ýªªÔ5`ÐU-Ëg0e&½’jé:ñ™ ö.?q·`ÏDÔ5>pºƒKÅÅVìœë*­®³"ÒE”>ÍZ}}yyy=`N4¨=ãfA“’ÌzüÔ=zËý%+V\#°{Y߃*Zµ—eÅX®´çˆÔ1©Õ>g­Œ÷ƒ@Èç.uz£²Ÿ)CäøÈ[$P¢xÉÓ‰²g¼ó.úV¨P¶}¹jznçEƒ‘w®é¨ÅÇý‚Æ‹^­öîY(NM4ÝôÌíÜ`׋I±€Ìw!°wtž÷$Âq w8¯TjµrÓÅþ¹ïKÜáõŸpÇIàÅš¸ÃYj¡‰âbЏäîpà}@Y¬á¿WÛÏSÛÙF=NN ö„;N”¬­1׆l“ÏàŽÊ-›Ø–R.îpmX@ªb¨ñægqÇ’¦â¤Òíßîh‘Êõ%îè|VqG¯IÆI\Æ"áG¸£ëPùj Ù&vο¾1ÍÔLÇæ‚1ï‚àA£:Ì×€Íy…J6ÀÀ8ü6 ¹Í¾C¦/Çæõ ¢NÆž'z­Ýóø²Òu:´*ÕÍÍÍÍÓÓÓïÙN˜Ã…Ê«áçjz7pge×g/ο÷]ÖûǪ† [{?uÂíád“‚qÒ÷ïA·`/ÒϵúÝê²Å']¢ Á…÷nt;Iòx b£ºéEÔù+7±ïßÁFt÷ì÷ÌëýÓÊŸ×t2×d `<öÜí°Z¯R’Ô%A€¼ñúÁ¸¦MÌ›„Õ°–®ê†®U}-F”Î ¯×d\Z©Ï¬÷ÞCÐ"ˆTÆÅQ+ï[_ÎÐTcßáQãÝ7÷€`¶AU—”ð¶ï”-æ¶ã¬²Ñ’?U~,î˜í`´›º{U¡­ó[Òߤ7+ªàƒ¢¥ÃmNñLÙVETSõsñ¼¨ …oLnëÜ‘æGKqq_ìl\¢!}ĵ*¥rÿ_÷ª±¯ïTª‘É–®ôwøl­TKÝ|wÔ°¯¸£"Cû⑚‹wthø»õïsvØ[;‹âŽú# Ä=;¼çutÅîØgw”¦½÷X%»%íŠYTÒ:àîXG`gMq‡>Õ ±; M4–vFÉ.è5Ü¡ª]…BjÛà9WQˆ& JœpÇÖã5Ü!kê#ܱQR;P[·žÙUt\LÑQϬ­u©•'ÓâR}§zw,†×#êH3«Ñ‘Yî^ü‚„tš UÌô—±·ƒÏ W=ï]¬AÑvŸmlƒÛ‹RÎVXj~¶`*Wýä:ëAy2aó¥ÙØØ&ûï󳂢Ԩߪ•‹ ÅÝ•óïai•l4ecuŸU绪7kKËI®ä³•o‚ô0•¢*#hðu³(1¨ùh)_¤:T¶©Þ8¾ç\Ú‘2`°p½[Ew¶cë{ÏΖu•Œz_ RRFjâhõÑnYÅ5FYPßx`ò©`Á[ƒœtŽ*z0YݱRX“Àh.®lfDÚX•N6_$`VòÑÂ…ä“Lï”wU³Æl—…Å+÷¸±To çm¤ÛÂã!* öܳªà‚É–…-Å4”¸ZÉÝ:Øuî@U6T¡;ÎÎ5þíª˜f‚P³R“œ…ëýoíÛµP"ÛÕÊfgÀ:|rC¯é 2èí:ÔhôA÷ÎEg€<¿G ´–n5€~ªÀwFêû®ICg1A)H5땞ӳ\Üa"¦J¡kÚó¦êi'ÜQçXíêìùzžXðÔ(ÚäÚ‚…ó6Å—â;aâ±âŽRÿÄB|qÇ5©w×tÅ?çv4I¶‹!uÿîÐ÷J;Z›ywH­íˆ„‰´´eg4~ùå—7¸ÃD{{Ï„ìî°k¾=sÂUÉ+îð,ufñ´ž¥tpÇ’Ëâ»TÆ´ÝÏè×βì³,@›‰eN¦¿×p‡³ùâ?ëÏÌ‚¤§¼¾mj¶&Û¦¥¨UEg‹w¿ë0•OA­™ð6¢•]ùÄ‚¯Ñ¼ÊEnW£2«•4vè­Uêq³US±•º °Erwww±1™ûÌeÔVEw¸V™¬”©H xÙÛ{Xb±Ùisrð}—•ïô—ò6êÅ©­+ó]XiUжü÷%ÆŠ®’€&ÔV©hÖ:ÞWÓjÕ®ÉuwÏnAßg.Õs”¡ÝÈRI:×&µÂkhÅN¨ ³Rç ¢ÖX`¶;¨àÃöÔ:’Ë<)1¾ IDAT­óJ°zpúÜ÷y£qèš¼dE`æœÇÖÆf*NáÜMM[y3Qµà²µ×µéa³xeÛ½ŽÖ‚nßóŒ"M2ìt&ÌcHiÖJ{Ú]‡[yaݪõϰø°ý5ZqmkJqérªSyØI9ÚS«ÃÅVg·Çœ×¥¡ª1PjFŪLYQrc`;ç­êšÌyîVT2YÐ3Q,Ep¿M÷$Ëßjs“àÒÇ- I•² fü¨Œ´œ~»v¾èünq‡RÌbYžKîçš}Z¹—BÓK+â®áâŽ:ӛį RÜážtþÂ55ÜQº`%þõ†òýô̯R™¸ÃÊî8·óöÜQo‹&Ðâq©Åúk¸Ã¤xó^'Üqš±®é°kJÜ¡êŸÉ‡±²fÓïáçÛ·Vþ§—Ëb¢`kZÜaLÛ;=y–¾k7Xì'½¶ëT•³—­µçüFšÙË*·”¯^n¬nlÁºŸáÁÝŠ³ Àá*å}û‚ÜÐka®:;ž£€¨ƒÒ ”wíàU½:<b'ýu©E]¤¾ƒmÿb•a:‹!oW>ºÀ¶Nâ;4ü¼¿þúëæñññb¨ÞCÄ„·Šx­ðù]D“Ï=‘ƒÙïò³Ë·V¥ëÃê° _OÑU_¤wUÜ@E'©?­èÖ]{I¢{Ê=áº/gŸ'Õs?_Yç¸Ò1W.uoŸ»dh¼jÊŠÛŸ[Ó«ê/¬ø•rR ƒ±±Ã³ò½¥”©ÙØ_¿#Á¥‡¾‰~ v;*5ÊNĺð­ôžyMíÔ1¾ƒ²õrh²çw@ßßml=©(¯·ìú[u·`QúŸ \:å:Ôvæwí///g–"vã·.÷>\³žëê]ãö²E3ç$WHpFË*¿ŒBNÞFU-;á“PïëSµ¬p‡ ¥{˸¥¼±ç«\;$îë{¸£ÊpÅ'ùîî(­]ï«ÆBÏ1™,ïáŽZE˜8*hQJ¿ï}Öèod¶þ¦Ê×$R·y 8Î3·%îp¬A .£EkÍ•sO¦˜úuÎKÂí´œpGçöJ+®“YóîPÈqM>‹;†³Ûê¼ógp‡IU×£ÏØ˜ô&™épž›Æ_³w[Oëfù¾¬-ܪm´"+X¶"¹ª„\_[÷{ñ‚J“œ²e—S>©i’Z•I¤Yò°6@/8o“ɽ6›WnÎîV¯v¿rK[Á±R×Û€=TíÈ—Vf²FVÛìUÛqãïð¬G€jEM6jj§™Ó[‡Ú<4ËÍÜA[ª^‡i­®Jç› ]e# ÖVoÜ_RVqwߨ×aCýÆ1µÚSý÷ríÛphQÚÀ%Õ—¬:¾¼¼\#Ý‚­†UµÄزֵ<ôÓÍi}y/>p½ÙÉðý÷à^õg-yÿÌàn%·öíÛø®ÏQ_–Hž¥Ä«žmïA}\yc´IÏÖIã–tž­iqvJ”ÏUYFÊæhR{W‹Ù&:¯t T÷{R j<)¥Óá|eCMºìl4\eÏYÌ­iW*‹7‚ šåõ9X0±ª[éáÊ1—r|’0ÝuØ­tBqi©Î¡)³\ªXý¸\“ëXì±[¤I¶g®…%V¯÷²NUs‹ž{¯ÎYÔà±*‰Î®H!Séî°»Ò.ü;›ýpG©·nTË4¾.~TmÖNmcçbZ…“¤¿‡;¤Ê;&ÝLÀj§Û®Ô wØvy.ìù_Ãú¡Y½†;öß뀵3xò¥’™ÐޤťŽt´«³kwX~|||ƒ;¤ WÀe?³ÄnY“=çÄbé1f–ìœp‡áÏàŽíy;ìŠ\H™Ûºx“Ì6|p›3xzzºh“ûRå‘ ÌÆm¬aŽ`q ®ŠUl«b×8Œ£]©£¯±2|‚‹%åpK‡1è©æå!aEN_[us*Ý=ÉïW£ÞA6ѳùÂm5îà2AÚ<6GÛmtƒÅI Á Uõ2uËUFkwÁÍV-{‡¯Õ£7nôU‹«á’J2&[VÅ÷ó­vIuP.ûááá¢ë|‹Ô¥V¦Ö¦­ÿ’•q“e2=ÄLŠ÷=þY…"4“œúàîÏYA“sÔ¹:_µuÙY¸=Ÿ“Ÿ‘ñC¾®3{þR¥öMœwÞ«óBí[å1áR~]?«]*›úg…Y½ ;gÎîwíTç¨1ÛèüñÇëᦼz‡åUÔÑ7`²ÚrÿK[° êlÒ´¸#×ø¶5'2y”.&uPJLU·‡·pÛ"‡÷®œ»rØÁÉ·ò-ºs »®ÍH[õH㳚,uhñÍ™›*îYðñ¼6.0Øz“JWCc+ [»V˜·^T;³0¸çª4»÷ É¢3 üøqóøøx‘`pÇöäèjJë*;~‚RqG¥’‡;ôA©Êaq‡…2g8,•þ^ÜQEÃvnjèiç_1Ïà•Ò,. †-¼‡;œš<ùgp‡‰Bq‡E5Å}œU1Q´+e¦²™ªzY1›„îUÙ³vÆçIàÜ]Ÿyçà”+­ˆK»¬¿þúëÍÓÓÓZñ“ܾr¨&_}Æ]÷΂ÚÑXÜ4á¨<°´Å}ŽþvöT³8$ͩϵ”µRC×=´uNK…ÂÎmvø~϶‰˜üveÁ=ª¹½3Ü¡ªÕÖî w8ŸTÜÑÏî°“/îðÌ^\øóÏ?ožžžÞtí£]ë=í0™ˆˆ;vV„;L¤ëþ^ d×§¸cûß³µÀ¸´ÃÊl ˜‹;”Lï™ïÚþYÜQË Gì¼^Ã*„šLoo5‘³;±øýòòr!VdÒj’îg×àWÜa\¥S -{ç3¬´xúîhÇ©¸cb â"ü;q‡B±DÕ~]‹'Üá¹VšYY ²ˆÚ•ö]¾™™©~¹nå׃\º‹CCULr~À‹´biEgH`Q­lMÏä–æCVÊ× oÖnð*ŸR°c5¾²¿v!ªoï÷Z™©R†S ¶0æÛÑÁo£ÏX×`•^l÷:"Þ_’ìxy˜ÊÙ_¢P~¤R—ÒPí TÌ¡ ­‰v=q¬f™xèHíáìL„Õå‚w}ÎUjõd^)Jp)И*Ý`ëv?ë ´@DðVWd+¶B¹õu‰^¥·É•ž0}ævlö {¸t­Þáï^§Æ^Îát@¿3ð qý ˆ¥mHÙi•¼¦¦;xêÓÐá{A*Bv­4àÓ‘Üg¤“²^Ò²L¾R¬’×(¶b ®v@:ÏxR2>ùZŒ*µÌN¥ëK°&EÍk¬G—UþóOª~‚ÔVw¥*-VlÍOå©~?]°86à¶õhaÎ96ÁCg_ûîjrj·Ò„£Ý’Šì¹ÎNû½>ΡŠ®i«ÇR£Gá’zÂúàÙ%Ô‡Ã3î3¸Ã"dÕ=­0¾¸ÿªÜhœwX@0¦µK$°Ýœ÷p‡3[•û.Èܺšy¬±³ÒîRÿæ[Óû©Ç_»†ÅƧ½ßÏàß­&ç;?\ÓÞÛ wØM+-µ¸ÃÊNôÎ[Ÿí>ÿ=ÜQ/Èξ^Ê÷\ÃÞ‡¸c÷ûÿ³v¯ÉqI²†!©Å @ÙFï7³Ši3)±Õç——=õ" 5#³¶–H ê»dFzxxxˆõŒ±'ÛqñêÚ%LXß‚;g='¯’=KåÛdËÕ.ìÐ9{)lD7)2ÀùðeA«ß´É¯ °jÝ4‚-õÕ2P·úY´m\ *&~¾2½ñ÷s–ú;±~ø^àÝÁˆûì²V»~mÕóÖ+½M³|ÎãPëíµ{ ˜pÔœ !dç'Y´ªç 0µîÚÚÛ‚¡ú˜ËºoMwºõÞ‹%ß1~º#iEÞÏ6XË.:–9™·àËê‘éíCÒ«¾ u6ˆž ´Ö®ÄÆ Ï$>³6YwXdœ< ´í l¥D[f¦;½^÷:¬ÕÁHvóôs^¿}µÍôý+Yº¿¿¿°ìöÉ(S]Cv­ÔerÏhmƒI|¿J²&EQ¸}ãÁ¡ƒŒd‘• “ǰ“¬ðÐVúÕCй-N£76úóJ6Ÿm:·z[[ÔUûÚu{«QFÙpû0VÉÜY¥ÜY)†óÊœoâuœ×ÞÁ2¦6ö›p n­ uV„ûìýû÷ z•ÊŒgÆØšâŽ9¬½†;LŒ´ —<õL츅ƤZ~WF-î¨Á8-ÑLÀžâ­âmy‹;Z…0a(îhìGpGûP•dJF¯ªfÂe©«VÈô{6Õ\¤¯÷ŽÞ‚;4§°JíÞ>¹ò¹G'¹qšì}ùòåªÂÕoñ—Dž8³ƒ,­Âˆ;º&ÛdRmvÍEnáî*Š;Ü'î«\Ã5¦wxýßË WÉL­÷PÆ^¨½T]voÉ@~Ò¶v˨+­ µäépJW­·ð+Ü^9Uÿ¾^ùêƒ-ÙÚ\,ÃP«ÁʶA Ž6WÚ¶Ÿßa³w²MU‰‘¬ÑAýæmʳDïëgüûßÿ¾{xx¸<÷¹Žè{®×zA¬ Òz*YUXhåeU€£0ç˜ÎåÙF´wÅc`_@sýßjæ«Ý¯U¼VHjGì„ò8õ_·Ä_sbyëøc¢^ „Í·úƤ°JÖ¤¥«}]kVeöyúàï3j/©M¬Î'à«L¬MªJAMx•®¯C}wݦL,b³ò³u×ø8po?šƒ ö2^“Ÿž»ó ¬Ì:XÒj˜¬³k²öû •±“5­Ì²Uݶþ&ýQ~r«‚Y—±Z7«P‹í< ‰7÷Ábj B¶/=Pëe¥qnu>«ÅÞ:]îúuòsL:ì‘0ùös·æûí·Ëž¶^ TÙîžl©gkí¡Wq²Ï˵ªÞ]`¾uµç]Ü¡öÞ÷ß5ýÜѵòî0¹ëZ¶'KÅšÎL{Âþϳ¤¸CÉP%XîâŽS__Ýf‹;$ヌ;$X†;jûïY Õ%Ƭâ×¶ë~kZÜáÌ+åy~þ-ÜQw1Ò~wˆW‹;$<VIqÇȈ½Ÿ¯“œ¸Ã„ø5Ü!©aB³gÓ™\oŪœZw/K˜ïyŒ|8á{S_WÉŒ_Rç$Vnsjû&{`©¾‹Cmœ™ªš}=Î÷°–‘Êhû[f¹Önuy29‘­ë<™]Ë2íJ’|˜Vde­Ví d(“=¨Ì@VÓrm¥f.NoÏI&­‹OÀ×À0 ÑavmÜÓvÚÚr5•mÒÛç«ãìü¡Ú¡.a]õF–T [7° ÿx¥b‚|‡¯é¨cò¤º,Ɉ¬ŸzR“µ×ö:é–4­C(ë6xš™³ÿ^ŸFŒÀNV²kºÎ3 Ôöë(uvŠ{OÙP¿Ój—ì·ne¾ NeïU(µ€— 21·c%Çç+Ù99Îèò^ÚCÔø³CLL?Ûw'`а ýî…“tC»LÍÚ¯U)ïØBgyh+oÑÊÖ*m­—µ•+ ¬­0¹v]c´(©äœ2{;C¢=L2‰>_Y}ÏG“0ׇÿîïh¨ã$t“ ã٪͞O•uMÚÃ(H696qѦ~hŒ«ýcñädg¹l÷{{C_Ã2ËÜÛyrƸâ‘âmq•"‰;*ï€`MBŠ©üÇXº„®Ö½­p{µ oBºdÜû•¼ªµþk¸ã¤T9á“D迃;Äxëuþ*î0öOJ4(Á]ý„;ŒµÃ¾ãîè SU"šÔè:¶sÞsJ¬]ÜÑäJê$5U‹tæŽ2°Ž·ÐÍ´¸Ã8gòéÙùî(¶(îP6,zœ3S]šÓÉíÂÃ[WmSëo®æ\ö½Y¼‘½L_@'çm¯R‡Inñy˜k(têpg—Ô!ª~æ‚W™ºFÍ6„÷$ï°Ì¬ûP'Ù—¯_¿ÞÝßß_Q­²5pqµ1ÚéÇ‚ˆš!,irózp¤Úcb¶~šÎ» }*õ/É*u€£‰GÁg‡, °wm²ÕË«W Õ~´ C—}6kªh[éïz¿^ÇD,Ûª´©MöZ;˜Íƒ`ýþþþjÏÊ^ºwM`5qÝ)ñRFçš>Í¢{¸ç×¾¶&x&“ ÛiÜP¦'©àŒû'\o-ËÉ$oÉ»J€4Qck|RÊgÃi×£€Gù\íµùXkf›ˆ•ÏöXi_‡ï FðÙJ†ÉyU)c´g×XÕS Îcý»9Êé¶µwÜ5£)…UœÆ¸Éu×ä^¹c‰•í#m™%˜”–¸$wt7³Úk³¹çƒû²»êûM:Z9pwÚxMjÓÜw'øÚ5n-‰;$5$˜d|½ö¶:tµ¸£½sÛËJº:s¯¸C'ÐŽ»X~wØ«Y¡ÎäwlOmÔ…¸ÃÛ>™%”âŽöFNõððp‘wXqlæyfµ¢¸£sÛ§{ ÷!éš^òU £¸Ãu"sÂ9h(ÁeLpŒ†•n“ÞâŽííüG“œá±k1…gU]õš¸é˜X'ÈÊ;Š ¸£Ž³b®«dÆa@j‘]`ú¼×ë¼ Ð²6ejì‰<îß'—Ó²b4Cë¡:—ËÄZÆuFIA¢¶–}A:YÈn4 œ§ê¹¯½òò¸j™; ¬s; ÖfÍ{~WS‰kšÐ¤h›Äk÷”!ZivÀ¦¼y™Ë‚7“7X;ÄÉZC ]ÛdZÔð×ÊÕ?ÓÂWM¬vŽ-SnukŸÑA¢n:g& Ð)¯•:éá·l†uÓoPÛɾkÚÀt²á6 ™“KŸ•@´“g¼µà{V⌠¯³Uûe”©-™Ÿ×5oP·i^0{šsÕá\ÚÆW"ôçŸ^æF´1Õ&x¥UƺJÅÉ TêžÚZSR½ƒÔY VBËf·¸RL³´o­x.ÉDŸéõù莶ug/F“×HL” :öwëm`mò,YXqGöî¥÷Üö¼®#aãàpÇžåö·k´‰˜¸ãþþþ*p] e­+ýr††kæ4—ijªÀÕdFLâ(ƒÙM{ÞØì} wH"wèÐ%î8ÙûnÄ;ãŠ;LDLÀnáŽ&¤Ê8+qª©Ç w(~ î8ÅAI.nቮ)PŠ;”wìþß½{w÷ôôteÑ-ùSÜ¡ÊʪRÞ=Iš’á“Eü‰È®Éĵ¸C,ë~?ΙÙLz!S]w –$ëa@{ Zfj©SöP†Ø;À=æ£ý;û<›+ó-𨫡ÝßÛÐ×¾-Ô¢OÆ!kéfY^&W{ÞS k)´‰Þî½emÚ^c ›{µ•·KÖM‡3Uõ¾ua©T±zÓÍ:ô0Ýs´·  ÕaU'‡;£Û{7•zí­” ŒJp ­xoÿøÇ?î>þ|ÕH» S¦ÈɾîeÝE¬.xP@•Œ˜4ìзšÓ྽­•³ƒÙj•ë¡R¶L½3´Út°¬Õ ¥Yd]Ë; ÁîÙÏŸ?«ZﳕÝÉRùÌöüŸžž. ír‚‘SuÉxYÛWÁ¾4ZãkÚiíeÐgŒ.ZS{AYy» kǼµc…Á&_A%‚•Ìi±l~ÿ[Ñȧs·šÄËH¯ Wyéä{Î 1Is6Sß—ýV³œVïµí÷z¬ê¶×¦³Ãö>[²yØ^À½׆½zwx†w´Q@5 áó*îp:sI ùβ׸ ùž«^ß-Üá`Iq‡ë­©í5µwX&|¸còPqÇpBñÚ\oŸñÖt%yûûý÷½âG5œL¿ÕöÍHKÜÚhÜõÜw¸×[Qî¨ìu˜Ê½'ÜÑáµ?Š;L„OÃ×pG‹ š…ìl±ªYÜ5ܱX<“1¦ñ©ê”[¸CâIÌâž³ÛáÍ/ ô´7PUßëáZÝðIöÑÒ´MŠ«’²”æØ º‘ö°d Ê¡êÊ¡ÈÀÖ†I’ò…½øÎ~‘èdb¯ u.LýùÇv,HìÊ ˜@xpŸúŸÚàA­\ Õž–3­ ¹6¬–tH•b—ÏÍû+“¶¿McâV¶Æë–ù°õ:-Ó—]éÚªJ¥ –M¦OƒäÚйëØüe‘J‰Ö ¸÷<ºUŽkÎj–_‰Þ‚ƒkGÍ«ëÒ†ñ:­oI›i|A€ÌW¥qÔ®×ûí<çÒì¹Ûؾ÷²w¥Cà`³s-pÛG°5-ãgKás_jl³ZÐäS©©Î^•ñj,PËd×|gp®S  kÔÉCÈ¡ ºTßtóštnÛA(s©ÔÇ£íŸpâ¸kzàÂ}.ˆ^Fãã’ñÛ©è[uŸ”T«)…k¥öö‚Y-á§¡‡KŠ:M‡C“’Óµî³+vðf•M$NêŽÊÈ£÷Îꂤbä-¸£Ò*cuq‡…Ü wt¢gš==&l6ðkšq w¸'”kxPÜáú)îp}w,qÑSÛ]g%('Ü¡½ý©‚§LÑÞ:׆¸£•‹×pGçúp‡òзâßa±ÂÉZüÿ w´š_Üqrj«ƒ§æJõ:z`ïç—nnâ­Æ‹;$*5ͱ`0Ü¡›¦gôk¸C³¬•‡åØ,nɲŒ…®hèBuê§ W©Ä6†®wj¼ÒîXm¯ BÙPç™ìaÙã°`bÕb‡w›%ËLßnfê"܃—Q4({Ï‚Kr-M;èHÐÜUå*V-ÛàtÛÓðNæëׯ—`;&ÕïÑ^°ìê€ôÜܺÚºucµ¦jíFÛäf¯ƒÕ0­2u«³Ü6ºŸÿÇÜÝßß”ÚÏšôéŒepîpUKþ-ù¶LÞ!šl?ë›?X€`Ù[Â2ïÖŒº\í0Ðì ™lÇ *“?² ³[ n®5››-µ—i3[v]¹\ð– t g-Z+ϳ8É™{NJ™ZYPÂå”zÿi,5V²76oñ]Óaf‹K&65K^Øc£,N6¯¦:õùû¾•´AÂÉ6÷ÎL|jb°wàz7®¯ mUÒþ÷þ®gkz.lVœ+»vª¶€¬ûÞ=¬Ÿƒ9¨ôËÊÐÖjµ÷þÎÖš“=É;G-Ô‘°dŸ.ycâ ­yAÙs]·¬ÄXí[\Ë/ " üî8ÙÁŠ;*=íš¾e+.îèpNq‡vÒrvð¯ ø­¸c±æ”8tô‚ò×V•Mž$Å‘dO¸Ãý)î0éyæù-™g…XLªñ‹¸Ã>Ï£­‘Ãp‡URûÔ$ÂÚ/$îð쓸”ÄÑ`E@qÇöñýýý‹a˜·pG{{+O·7ZÜQª=»’Ê]o†;öεLß>]¼ju¼ÅíQwHÖÝÌÆì0µu©Ò­Wµµ\(ã2váä‹ßÿ•¡;‘{ºwmvÛˆd°móöºÖ™»_§¼›]n åötˆ›Òj¶éË:M#÷PœLÇFÁýܾKY€ iƒ:ôT³é`D›¹-ïyMÕçïw•¸(KÜûÛ»¯¼E  ïZ‹I7ö¡JQöž?|øpu/‰ãÚQÖT  Ï%TyžZ-ÖZÔê›F²¡Ì È2hÊ¥c 8ÓŒëÒ3†i ˆläýýýå€AÀÓÓÓÝÇ/$„r%$:¥˜·W`ïfÈÀôöV Ns ªmVʸϕáߟ·±{×\bBù†ûÈYMÎ 8¹Â;Î*ók¡u¨€›C˜DÌîg}BZÝ*µ” s‡I@ç/i[¾uX£ cƒŒzåuV¬8JÔ‘gŒŸmQ·Žö|hæ¾µ¹„ÑÞ“?þøãîáááêÜXŸÃ$}î÷Ñk‚´}¦ ‹æ'Z*;îš®ÛÖb¶Ö¨eÃ[5ï縆 ”rÔ9Q Ÿ¤›ýe²Ü“½É´o p<==]I£¶÷ìo.æì]i—/îð\or¼u·³G ._™+g΀wè²*h"eEH“”aÆ%“´­ûOŸ>]®}—¿üòËÅhegŠn„m®V"lÏŸäÝÖþßÅ•¼î=Ö&ø4“ËA­µÁ/îXb6Ü!ì5lÇ IDATÑÖ¦öP¿…;z™˜í{ÿþýÕ,&u"ì ä·àÉ_qÇâ‹rMßÉ[pÇö†²?e–’‰Vb”ë w¼{÷î"õnek¸ckýîîîîááá‚;–'<>>^p‡¹bd{Äön¯’+#2eßNÓf &›ÊOœµ?¸6³2 jôÔí*“ªœG‹Æ/™Šnıj¿üòËåz”-X‚Û5¶4k‰Ö’±zÄORʲaHfüJ8Ìä;üI¶Ã¨RFe*m~ï\² 6~Ûtê€Teê!ýn7Œ“Ç[.–¬xl… ³sq<¼¢*8=9¬É¶í îlAñÓÓÓ›ÛiÊt^ïé9·÷ÄJ‘R–¨9~||¼ò‡ßçK4è*h"ºÃrÏ^&N¶Û$u×¹ƒP»ß:¶ÕÅE‡CÁCÙ/A‡…àÍ~в¯&~þî[{TjI)S¥Ö]¶É¸9’ÃýTÙ‘–·,&dÎÃÐôÁx¢fÜ~“¹J}ÜÓ?§ƒ¨ƒ0í§²r%R›NÏ'ÙëdX5ÀÞŪŒ2¢Õu6‚‰¬¤œ–Ñ;ŸìGkCj‡½ÖýÊöoú¬oÎØq­›øøn–é’&X¨Ú}9¬Ú^ÅÚýß’y{ÎtˆâH>¾˜¿5‚açÊ L¦µ¬ƒ'µ-iü#¸Ãêö÷p‡&’~ßÝ{’Lwlï¹¾Hf\øÊ |À–“µA-ÔI§N*»qƒJeb*c)늶kéÐGƒðiP§Y´‡Ôýýý‹rq±L¶´l­‹N›ê¡Ýƒñ L*¥i3 ²­²Ô6noÁnñ¨Çõ0mÆ¿dÎ> Zýû-™v ˜¤Vãëw r­uØ™ÉlÓÉ ñdÕ[÷×F}þ ¦Ç«íP8ËÝJBD•0¨U^G¶’š·½5¶[™J‡P;`Ný¯¯JÝ´&·‚"3)3leÐ{Û^ö`,÷9[M5ûäݯº#™Û¯â\« &<îýº=úkR«Ê+óîP>»}jü-îç½wÔé„;NƒmMH÷^öÁ¿¨ÌèìcÓ’PKcƒyµyËvj«Í=|-¹8–VhÖÛÏÙâ·Jqÿ¢1ÎR¯r¤Ê[|Ðê5<½wQtÙ¸ÕJ©;ér6“¹ ví $Êt(qÉÞèœd³â© [éV'cß:`”¬ø>]¶6Ë:×B€¤LÅ猪µ¬S'åvM«ß—õœt¢=èÜÄNVÚµXÙf‡EªCÞµÙï¦DJЦS‡S­µ..›£kÐÖ©únÁqû,l<.+ì@[¥ 6î/ ‰6IÑnR ëz¬kç˜(X¥|øp5ì¸Í°4fwЦnŠûý©Næ6ÛGë3ªLÅd®øµeßÞdt }Am¦UÖfÂÄxÒ©JfOƒ'ßtša",!d¬ÓÚdEKXIŒa \ÊÎúM|‹;\ÛÅV¾j{Ünl½…;v]¿ç:ïçØH½5³~A{8ö쌧ží¯üžp‡UÆîhA,¡áIû*ÑúÜQ‹ñb´âßqÇI2~ÚÿÚ;ÿoqÇ*q‡øó„;${ w¸îŠ;êv¦J@Ü¡¼í{¸C©¨ûF‚B2Ã=´X¾?_,wìüÒÉñîP½SÜá× Dܱkya`ŸÇ’ˆX³ì·Í0}¼Ì¹åÊö?ø3«-Z%GÎE©Ñ¡Ièö/,³\)K§AK‡v) ‘ͳÌÙrm›Êz€¨±nuCfÒDÊCdïËA[»ï1c¡Ú7à=à-fò²®'€³õqš6Û¬ÚÆ0Í!lZö0SÚd)~›Q e¶~atÔ‘û½~ŸU—1sÓç[v–Ù’)DõYɾվ°,Ø€«ªR‘€š\?¯³Ú·ädYW€ÔyQht[ªý°÷\ùŠ ©Úu÷ÁOüþÙ~Ô}ªsZZ)³qÛ¸c?–ºø:'v˜]ÍGHí±q9½.O6ç/ÑІWl£éâM=ùÜ—Û3ºÚYQqîBÙºö9 ¦ltßuŒ¼5ccDËóóóeÝm>VÉŸ¡Þ~8ÆêÊwÆê¶Sµ½gþ=ÿUÂËw~’„ÔÑöLê¢dÂ\³ZÍ%\[&L®—]ßÇ/3L$vo˜setÃöôœp‡ïþ„;L¢[µó¬PÊês­­6²â]‹;4©Ø0‘“-—^ÃöÐv¾MÇZ¼w(û;¸ÃÞ'ÜQ³¦Åû‘;¸öd½9'â«S5ßÑ@¢l¾ÕÑÁ&bN°÷Yïs‡;ì3Û8¹p~wtæÐ÷p‡Æ!·p‡cJJk“Þž&qÇ$}ÃÃG&€ÊGÓ•LO–®ä·ûü„L⯒™†ŒŽ¬¼Œ‘AÕ…Õ‰ÄÛðfœ0.£,³d²?×{ßÁzz—9\—Á¦3‘LÜ´S5¦ÓV—µke9²MnŸ‹×/sÞû6–ýñYûöíÊ®Wöv}AzŸ×ÏÝŪc‘òÁ¯ö®:Ð,Ó¶Y˵c4tk­ÎDӾͶgê?öoØ›Q­¥%÷1 u—smé–r²”Èž<ù,´ÝÔÁÄ`Òg¢Öu ²“\n5æÎn©„Î`£QF‡n•lpÍž˜¢yP )õLm«EVÿ®ÌÉý\§¼²×â]«˜$Ü£îkg79gªÃQµa­\V¶«ï\àÒ^ƒ:*Ë‘ˆq½dOò•²öÚÑ R%?´ocª{Ï5­dE=ö{:4ӃܖŽѤ`‰ ëǃӊJ“ŠíåÓÐÊlî0¼íe²§Ä g“N{µ .ÛouÛØn•¸Œ•’©}¶s"– xoPh©Ü5)¡¦» Ìj±$Ì-ÜQÙk×NvÇÛ;Se£—jk¾w¢ã˜=½â)î?“¡Ž¹(îh‚¼¸=âÎ3['Æâe‹uš­ü÷5ܱ{x||¼ªVlº†o­i•&g]óÃö”yækùn…ðÖëàfåe[?»]vÅö;úÞŒ}'Üaß¶¸£×p w¸7u1¼…;¾}ûöwì^œÍXÙôâ×ѪP‡rwlßh]¾ëzÑ3#È©?ý.d¡V¨6ó¹èÍ´ªÓ¶É·:bK­B¹®ƒS‡¯Õg̀«®¿ÍYuËPÎ1ÖÜ6u˜²²‚é²k•Âx i3»òå6ŠL›‹ÈÊì‚=9]àš¨õ”-T¶$s}r›ÚóÞ3ªUn¯uϼ¥Ë2 í—2˜h1êw ¾ÕäºVV­ª›ž ©‚‰J,‰[É0ùÜmvÌêbtr/28+ǹ5TTé@ÝŠÚL¹S-쩇ıCËÊ–û½Ýcõ¡¶¯jõ•8Œ×ïH¶ÒÛÆ^¥­ œ˜3YG™[÷t¥””xÐ4v Š•‡øóê‡e?Ûk p§C«÷àj—Õr÷³{Â*¬{Í„µåÄ@önCl¥[‹+öìújR2†±ó·jnâš>F³g‘DØû÷ïï>þ|åªØß7Ù¼Ö1ÑÄÓ=PÉ.H{–«®vˆr“;Ÿ×öàÖ Óž²‚0å°Û2Áž…§Ê¬’#GXݳϩ¸ÃçÐ’Æ-«Kû ¥}úêç»Ä:Mp‡&'íc= Ý;,îhZÜá;<ç1wèÎWÕÏp‡ç·=7·p‡$Xg(™´u˜ •û˜?‚;JÂ)庅;$Væ¦äÚjHå}öÄœpG•Qm÷°ßµÊ¨öR—ü<WÉÌ‚¿€¬úËî2ªX²7q–:¿1dw¾@™ñ1 šZ”êº @(+¨ÖqÕ«Ú•š®ÝE§Q‰u);[&Dvg‹Mxƒâ›j:!us¨c.#æ=z­«ð|øðá¢_dèÂâ@Ô6N‹*ó²Ò²îx.ðeÿOOOWÌŒ×)cZ@c€/ºï.+ár.‘¥z­ˆ; |ßµ{ÝÞXµaÆ 6êªRy^u»•d˜¸===]õ½'½@Ûþ´›ì¶B«ú€––Àm¬Ýß¹Þd·Ý>{BüÛ§îy«söCy=ZïÖr×x´k²J¹Äb‡¿–ßùñãÇ+g)+!c7C±õ¼¸ @VnpªžØca/H+)P¨§ÿ¦·F”-I"i…»Ø¹X´~ª‹³Âmƒ©ÏÇ5á{×fÖj½ïÚ?3ÙV^cììõT×í¹ã{µjôððpEžu0ñd#V”·6Y)³mrýÇÜýöÛoWÜ‹y‹3¤Veý9Ye“$ãT‡¬¶òØ—[·Æ<ˆìp‡àéX'øÓ jñc2º[&1ζi•ÝkÞŸ~Ý ¥} 6 .%ðì7ð̯E¼ òb[\¶L‰JuÙd+¤žAí‰óù‹;¬ì잊;¶ÆÄ'Ç»âè·oßîîïï/ç\™kRVú-¸c{òî(¶¹…;tÖ@wHlM‰;Ü[&L’XuNT&è¬@'ØÛ϶usÂUS´R¨ÃØÖ´ß~–äÄþ[›bm¹Osÿ4¢:áŽI·Ä%´wxÞJô´”(Vbk¢fóî¨|RÜQÒgÏ[beê‚îè0ÏÎCR®¦T°¸£È•™±@¼+q3½%6£aØ(ذ×dåJ}:0(×êáá®H¥e^›Ù¹ÔàdQ§™²C74‰óðìdSÙ0ËjTlÓuuÿû®Ÿnœ:ôÈv»È•rÙ»ôáÇK£×<ôí õùS²dòë:“©µÌ«DÇR¨ÁtÕ'KåR2ÆÓôœ>==]Ôõ;, }üøñJÞй TX­ëÞ wu¬íb‡Úøüü|a‹ë–U×+Y»“å²®=u™²±pû߉ÙêéÕÿ›„íþ»¦]«¾?íÒ• @[wÃZùD8pN‰«.2Ú­Úƒ¢“šýëׯWƒŠMÊr´§”d2Fí©Ñö|kÚ¢Àvß3@ä³Un×~ãÈ,éMìg´™ô4÷E ÈÓÓÓÝýýýU‰O+µ•UHHµ§ÐÃvqÝýe…dàÌ'¥‚²é‚aûŠÜûÆ¥Mèj SiR‡â)­ów%¬6€ZgÎöÕ5yí 'e;­,}ùòåÊò»&B#Ò¶f¥ßÃöÀ*½Uf¦Ì©¸ÃaÐ'Üáš>™)¿wèz²è>9¬*éõ )îPy w÷šüjè°ÿî~±¢þîPe£C•É’’e7O󑬯|wTŲ™Ãšìˆ;önVÙµ˜üš½w´÷lxè„;voÅ~#4Öß,îØžÙwT¶kŒ–”tÿÙ£4LfeËx\“™îXL±âßêe÷‚²Á¿‹;Ž2³1|íOèÐ:KCµo­7ºÒžN{µ¡NÿèÚúU‹ï„mƒŸ,©Õ˜j¢GY[Á2ŸdkAëCQËï6K«I”E©Eä@£ µƒÀ ¬ÕÜZò¬æ±É¨ÁÍy<6êV° ¼¶?[uK se e4«kíðHY “H­•‘Œé7£÷°ê£v]óƒe%}ê­Ç>m:o'[Qì÷vÞüÔëTâ¬ìS¶¸år]ã<ô´põ \å­ì[Ýõd¤ŒmˆõÀÖgßàï`·Kll]U'ìÞo°ßÿè÷R¤.žY)tÀäýýýå°“åRJä€9¸“†Ü겯ºm”5øÛc¢„©vÏ&‹öHé~Õ†âÆ´Ú6—ó}*ïÜ:°Jkeeމ’eöKõxfÔ™¬‰ýΰ}öUl¹žý{ “*÷j¥:M¾=;•µbè?>§“œµý&î‘­i‡ã©ÏWFY%^ÚÝ×FÞ5­êcqj–¿öTRrÂAr w„‰;œ³ò=ÜázÇTZç³6vÛQl<t¿$f­¬wtvÖßÅmH!ÐJÂ-ܡ䳒٭Íb “ó[¸Ãsèt®ÜÂ[ÛÙ·p‡ò¸G4±¹…;”ëµg¬xFÜa’¡4Tâjëõ„;¶v~w˜T7F‹;:îÂóIÜ1¯;ïßÅ’|Å&Öž1/æÌlÃê¼àÂé<•:Ûè¤,J6TÜXpå–vO Æ2›>¤•Ý&ýñPÞ „Õç½ àÑ’ µŒ'ÛXùÝw'™;a›Ûfi§×ùÂòÿ4¬£úÕ{“Wè>µMöüüüB§mÃô>S™‹ ¬@h÷?ÐçaÒ‰á–;…Ýõ§ãÆ))0ð·wľ­6Ìùó“üõs•[ Â'ò8Õ‘G·5%–2={nÎ6`êãží \Ù!›ôÛäß5]÷ê\뺑Èþ ¨Êþî;AÈ@nù÷xló¸.D{Gš=ÔÝMùVgr˜ÄhíŸ;°S©`'ÖËò«ûv œ~·óÊ¢ möÕ)p⪋޻ýu®UmFí/òàmŸ’çj×fe&µ&ãV}Ü:™@¾$Ói¢¹„F«cwË`Û746Øëª„ÑäXWIßi岪‹—Nß=oOuŽX+f&m,¶:¯©‹¶öl¶¢/9 ôG€¶ŸétyŸO?[ÜQÛ^¸É^C•Üœp‡½'ÜÑ*¯3~ç$>“þwø=® ÷q+…(Ù3¤R'½SëàîP’ùîè@tשÕÉbœ¿‹;L‹;ÄA& Úõ+y;᎓ݵ•ÍXÞ¾0nO‰Ï_ܱ÷&q­{«¶ÜN| wì$|Þ‚;LÀëN¼ÄpI’¼sÍÛó¹…¥¿‡;Ú3ö=ÜÑ^õ£5s,›ã–©-ØXþn)Üò’g’(IÚ"¹¿¿¿0å!TËaí·d '³;HÌ—¿AÆKy›Y¥Ag¬°¥n1úø7ëìa²E>ÐjÖÛF¿%kö)íÙ=??_5»­/FÙ‡ ù–©þùç»ÏŸ?_Œ3š–‡;Ì«­¼¿¿¿JäõùßsÙ³ooƒÕŸÇî©Ãö\øntÙ÷62›)ƒ’Qªþ} ÌÏúðáÃÝããã¥×bÏ|o Î@ñÓO?]œ†P¨ûÌr$®ö„ïvÂàš§"¨+XVcÜá:©éàn?wš¹•έi¥V rOOO—ø` ÖñnqCÉØ@¦žøÛ?Vsó³ñ¹â€Ïó½“1D«’mˆÜÚ3¶j”²¤ÚJ¯½t2첚ýoËü#§ÜçM€¶~_Ô«·÷È!¸'±yX²êû‚Öð˜ +ß IDATg¿W{ÍËœl½=UwªNõ.ȳÿÌ ÃiîI³g[«¾{&»§}¾ò>\þ{ëeýܪDÇ$ô?þxÑ\l‚Ófñ½³/_¾\Íz’Üi¿Z×éžöÊ|Ú¥ê@%Á´gå<-å‚2õ:‡‰;”ÝíL9Iˬ¬w¬wÕ3~qåî¨4j1zïWýÓÓÓU³ô wHˆîì“ø»¸Ã=®5pÍjN³_ìó½d+oÝ÷®_H °cr£}‡¸Cƒ†ÝcqGgÑYíšÀÓÓÓ c¢õ§4°²q w8,ýT}Pnë˜ý+“Èlµ=ÃuÞ»ìlžÅ”áŽÅDɸU»5Œ™ ƒ2É[¸cgÐægí»5›ñ'’èïàŽ°F¸…;~þùç—•§ÐjOg¶=`e¥Ãòé ìmç Ø£P§­ ²›f¬Qâ!tjd®­C”LÈl¸WªÔ²®²,“,Sjl°À¹à#`¿U…2°9­~ÁÄ`(˱ ¾MiÉS …óQ¶16 Í&e+$²6“¬¾|ùr÷Ûo¿]ž·ƒ¸d:ÙZÉŒzÍ–A 6de œºË؇QI‡MÛüeReg½—Ó¬”={ËÿVr”þÔ1É&z™«_j¡·–žì±½ýT²q¯Ri¨UÅ­ÎhãúIú£äcÏp3IÊü F)ÜõîÓíéãDZÿ¶9^_§ŸÆöc˜ècâäÀÄο±˽¯ìC7™‚#׋ ÅÒüb©€¼¬ŸU²–2ѧ9Y~¿.J*€–)Vv·}àleÆ ßY]£T¸*¹„XÙÿ[iëÐ]¯¹ÿ½ç¿g³$p ÿÔ$Û]I¶AãÙ€óÓÓÓå98§¬nfuÇ’xøóÏ?/d‰Z~ç¹÷·ïwO> c_íÕM:rußwèj¸5¡ ¶û{Ɉ@ÝøY3‰îX:[+tÞwcôk¸C ÕböÈ“KÁü¾[Üa²¸c÷T§·âÏÓîØžþîÐ^~ÒÉÎrq®ÐbÕ€òHKg’HÖú/Þ‚;Nò'ÿý$m4Áq]HäèH(~è<)Ÿ›’7žî»?~üxàK\º¾‡;JJwhØb2»ç{rë]Bd\Ý“¿IúÉBÙCs2b¥7Æ]AIÍ:Ns5éV½êlåÞ³r¥ÄhÏjûO%Áb›Úšbû*áXBñ믿^€uoÒmT"©,©„•1b÷ì¹+Ë, VR©ÄÚŸ×F·½Œ&![£ßõ™=õìîM>ÅÎ í;€nwh lïÌ wÔÄh mçÌ*‘¤cbqG›ì•Þ™ØìYšŸ!«Øœ¯ô­¸Cð_¹“gE+XÅ÷÷÷—ç¸Þ ×ÄÖ̾ã-¸c½R'Ü!¶ÒõÔ8¹gW?O ·ïð„;ª„wˆ[ê’çȆâ{b_ÃJ‹ö\;캸£=1t:SFú#¸C§7É“ÖK2óÏþó…už’eÕºeÙ¸E»ÅµCkŸ?€3K½Ú#׫¼7T+ÃÇÇÇË5ù–þºAÕÀîš)k;h¹m`ÇMÐæ^¥ÚÞ¥^uñÚ D–•"­xígVÚµoD;ÎJœÃ—äþþþr¨ËªH[VT׺ £¶Ô ç ‚›¤Y¿ößjÿ•~¨Ý­kÍžÊûölzßÚZZ*Ö¡GÐÓTeŠ~ž€gkEÙR«6Ò;˜ÒýZ'Ùõ•õ­ÀÉ´Ëjvxœ2̧§§«Ï´še ®u§ëz¶—î×CÇž¹M†n¹>¸S"§üÅukåÀÊç» l²Aï›É:(­GP¨ÜB&Ê*ˆàd¥}{­öNO^“'0v`¤²â±wZ‘???¿pƒTJØŠêÖ¡MÁêî÷ž­ZÛxš·á,!clm„x>|øp¥$ЭȹiíUètm n¹_zŽtrû’ÝV3Œ7k°õ}뤤ôi±õ¯¿þºûôéÓÕzWN·xkß‹C­MÊEC»û ölÕÿO›¿µb¬”¹ïQ’´Yö âŠ;Fnw‡'÷îX’·sb×»wh¢ÓŠR“‡îhszUM ì jRì»w­o°lÁ[©²"í»²¯¯¸£s·^Ãë£P¢é¬ñTq‡ÒÁ/Å®ñ“ Ãg¬¹MÝhÅ&^âIk¥mõßÊоCC ‡TwXeW ¾uÛyp"m¡8AÉë¾o{´¦QÊÿ$?tiuäî­ý·ö¯Tîo¯¸Ã³í5ÜQãî wŒÔЖûÅœ™g¬k˜Í£V2|ð²[ˆµ±œØˆ®&X§4%XeéÑ›5‹vÓ˜ÉËLڤîc²¬Û,6Þ<58vZ¬ÁBë¾ÚºvøÑ~nÿï%¨1 ÷þ•“ì{VR·¹lEæL7²@›T{be×O6œ~þÞeÞÚŽv"·lí‚Æ~ß]²:Ê•åÔµÎIÝ•ƒÐ]kJ) \º©˜(yèÛ.ƒãÔâ /tm<÷þ„w]µºv¾Ë’)Y¼ZÊÖa÷Ó¦{Ÿ¿Ãdv_TûRåÛ¯V!ÇB èšÐì@ ¥…¹V×2ú·f” ÈoÈÂTeø47Ð2Y)š i­1Os™:¼ôV¸nx2¥u èô°ôàëôwßn7m ?Ièvvø¾}öVÚÇhŸdGµðì0Eû¦´5 ÜsóJŠl]IÞ(UÙ>Þ=ÕvÖë–‘µ?ÄyCÆH¥,VÓöw&8;ç6«wJ¸–ÕÞÿ’e'Ê«Wê6ƒí™5S[UªÌéî°šäpÌ·àU,ø,Œ£»ÿ®ç6+ûþüF÷Lí=wë44iï×p‡ê†Ú6woáŽÓÿ~?oÒgìÖýÏ9>Ú$‹;Œ—î³í‹º îüœÙ‘ N+ØÅ¿îp`igv6Ûɵì{¸Ãê„2Òš.wXÑôLyM%b ØS.{ wtÞcqÇÖØ{1Î=ÆÑžß®‰“|s½V¯áy —£€Ž[Ë–kŨÔLÉkVŽ&KV[Q]ÔÕÊfŸ\m˜µrŒtÈ™› b²Á-—6ÀÊ|TòÓA-š v:r˜ë‚⦯fò´Qu‹ZÓh+ ²_-¿n#ubïi½¥W“!½ø«%WTý³Á¦ý¾cÁŽ’&+"[Ó¾Ó¾wˆ  ]Ó6Ü©5µ!­n›×&DúšÐØËÕò®Ï·Zê=sçí;t‡i¿’A²ÏÖúSÖ•ëiÍè{éñ¿4qk¯F'^+ïÔëd `´Â%`l¯†¬}gjYU Ÿæœ´)¾³_*Qª´Q^Oþ^õùvÞ…U ¶úý\e9íÙ‘½3ë»5ùoÃÏêP4ãRŸ¡ÂJ@šÒÜÄÎßiƒu•«–xv˜ÄZ­‘•îœ/±eA[™s’÷bq .IWd¿XgÔô]›\ÏVÅ\×í{²'¬²çÎ&9­i{HÚGdåX'R+<ݧ·×pÇiøk¸Ã!~§¹r#{þîpM‹;”Õ»OVí-î👭…­ýP5/Q¦å™[ܱÊÌθ×p‡ çKˆŠ;\ ª *;{+îè¹ØÆüî0 ’œµ7þîP¤ó›‰X 3N¸ÃýêzwhÖaÏ©g­Õ½Ópvö‚ë:üVÜaOaq‡ý£Á•¿úÌ­Š;~úé§³5ó@‡±õ0ËUíØÖº?wru_º•ežß½{w÷øøxõÐ,÷÷A["­ôÍEãÑäÀªÕ‡z¥»a¡»:B›û¢¸ ãá]#ƒ±üöñèØ%±A»}7c¼¶YÜ@º·™,hö`ò;æv.DJÚ7a_³Z¶ÆšÕ×ÁJ¹Ä>CÆÊž0Ú1Jºs¬„©/ü§OŸ.÷ääêí 7k“×6¥Nš¥Ó]%~Žàkƒ©ò8íCeeL,d„e Ž  íÛjÐélŸºžYÉt˜®MÞ;äÞ½’WíbÃ>weF^¯3\Ôü×Åiïb²'Ek™Ùáu'‡½?^Uo÷ýmî6i©äjÄŽîaÚÀ·b¥ãÒ¾S ¨.;6£+yõ°ñ ov=Î:¨î¹H¯Ù“)€¬Õ´ëÊŠ«^G/Aî¾ïééé²¶Ö»Tkl®q^¹¤ÄY¥‹³‚¯CWíeÂÛ cŒ0Á«<¹1Q¾’ß=7û*&ã1yo?œëÆÞ…;‘ä)î¨k߯(áÔª¹9qGåëÜ᜛6I–+}ö¢ wt6ÌžQqGÍÄö¤hÝ|ÂÆî¼*fØ{´t²Ûâ«S®¡·àŽõí¼wÔ¤ÆJ•Ħ3½<¿:˜Øxoµ£,ö*¶sÂ#Bß¿ÿC¸C@¾5mй·Æ,'Ü!èpåíñ­¥I©·þJXwXÑSaR5€ƒ£•¸w8çÞ“òdÝLK0žp‡qeïþEefŒÀ€ˆ m3Ôm&®QÖ›VæÒÉånàN}—Úf¶©TÖ] ½…T ^m=¸¶)ê¶%رb¬§ºe3e 2í2ÁJ¸d½´—ö€,;dV,0uê°zì©z³[:ïB´!Ò¤6Å»veyÎPiiÜ@_¸Ò‰½™®ÖÎuPZ³~¡±5u+ZeÆ$¶:yçd„Ý2­-ËÊ.Ì™Ãõ~’g¼;ðÑy J§V™Z`Üî>eõª]–Uò€ºµ¦Ûç¡LIç¾·U³š~t¾Ä$§¸Úqú.M=|< 5:Q+^YŠß¹÷ëÞÔ±I3ŽN¡6Hï0r›º Õ?¡Cþd˜]C&"í›1Ûšv°¬Iði¢»kvÏpÉÛiH\¸o$¥üÇÆî_~ùåªÚ¯ÖŠ™{i±GÀä:wŸË`úž¬² `dU­*X9/9¡ÔjÏe2î­gÁÌ­jB×KãÈâBgk™@쌷ÊdߨŸ­dÐ}ížÙsªjÍu¶ŸJ¿ê¡I°X`}:'ÜÑ æVŠ;”©šøœpÇÞuq‡ÃÀµžVÚåY»s¿¸ÃaØ5/1~lïKxZ©o{÷Ÿ±ckM’zI¦dÊ-Ü¡ÄÕ8ãœòÝG·p‡rQ;ÏÉxQܱ=¡ó„;Ü7V£N¸C™Û w(­w¸f–ôW$©oåú”@H$t¨÷Ln<UøüN¸£Š“§)ºö=3÷þwNÍXÊjòˆÛâFMâLV^ÃÒ»–ÉŒåYím—ñ³±¬>ðjEëRdµaMÀÛÄ6Þa?.ú5 ¹°Z~v3+‡¨­œ‰OýºÍõÂWª#3î‹W×ßAmíK%’-Õ×ÿ4-Z0i&.Ȳy¼r1uó1:à,0X±¡´½U–¼Ûh.­DAöÊÃXéì»,°ëd,ÆÖegÛ¬)q¬¯l•kßjœÕ³ý\³leËd܆BïYm²A®þõkˆÎ¡¨ž¾C¼Ô[Þ{oy]¹€L¡„Á­ëXóemµñ^²V=ù®ÃdÝŠ™¤HcŒòY“ªm³­ –ûÎDµB+8~¾ì¿Rª–ÑeW=`+ç³Ö¬Ë¡sÆÇ”È›<ïï'­[ÅÀÊÍÞ©½!2 ëýûní¬¹EõïN”W>)qbB«l¢½wÊ÷JkLt>'¿|ùrq¸”u6)ÕÔÂ>³íY«@îuò¬)=^r­ƒ¥• ÷k]Ü$ÃzVnס¸®)«L­²ðjQIàÞ·}s:›yfŸpGIÚ0]VyV±ºƒ•º¯œ¼®Oï§rãV¨LëNÕäî06žpG{¬”+»¦—ºê)»v®Z{~öûJ…Ó%*aº…;$7Äs“¼…;J˜œp‡=2âÔöý³‹;”‰ÖlÄäÅ#±†;”ÑŸú¯‹;LVŠ;&Á<…böî°rf媸c±Õ&¡âç;º£ý3î7ߥqå„;ì§õ,üïÿþﻫn²èÎÍ-0øiï*0Ò Ë6ȲY_ìãããUb¤fЀîbp7èN²ä†tf‡@\¶Û€¯o­îœú«õ¯F+÷ p»8·¸š™îÏ ~Ú=Xx§{‹ÂmZ­ûÕ2ì1u2sOOOwŸ>}ºú=u’u²dº&dδªT2± áa¼kñ°sÐVgx¨vp¡ÏÏÊ@ËÑ tŸ>}ºª†-‘Úg™¸î;öþe¼êØ·5½ƒAŸv%{ß¾}»¼›% uóh¯9A@ºçál„­>Á²ŸwPÜ*):šYYqZiüÖÈàaµx£þ¶úq¶I'V=x~~¾êñªE¨ÎK[¿µ¾îPѱ†Ú+w:óöú®Ã~]ì$t$™N {î/º[©DÒ bwß‹G¶Û½M¾¸÷(Û¹xâŒVzµê¯Yzì1÷²¯J-mÞÝó±ï£–×jÄ{´5~Y ²’©kÏþÿÓ§OW1ØÆpe·å&Œ&»mQ=“•M*EþóÏ?¯XÑÍ3µºa5ád4¡:Ê«MÙ{·Ú¯jD`C7Ð’VJVhÐ w´¢¢CÜál,›Ó·>¯ÀïîIéÛb¾ÓË÷]º$*å9á™f÷t«cÅ&A‹Kµö/î¨s¢¸Ã¦øÔ,v ÀŵÃï $J5âŽ=Ë[¸Ã9E{dzÄ.î°:.Y}Â&YÅUcTn*îØš’¸w´êå½wtM‹;< ?}útó­kÉoòûüü|ÕÇ$î°ÇÆg®¡—•ËÅ•[&0â¥ìÃŽ%)î¨ýôÞUqGÝB}Ç—ÊŒ ¹Ø ¡!ùw%3“A\ÙI=ô.ÒÅn#é­Æt'Ÿ*­X¹^g¥ÊY,“wÚmÁAõú|™¯÷ïß_ú„öp,sïá{]V–Æô­Y³¦ºgub¼ò­Nî]@®×ï¨u±fÏÃEe#Ý™é¾kyÛJŽúÏ]»Þø–…;í»V¶¾{3u™v}Í×k«ÔP—"âVyÖ°[ËGGŸå’aY&Mç&íÐK[Ëj™õ:ÕÖÓ¤³F”-`Þßß_ÉȬ$(Ð.Q ãíýÏŸ?_9±ØdÙh''$ŸEÝz|/ácÏšàÂêÒâH+»¿U*nÚµ.à*[‘T©ÔJùJ'™ï»÷;¤eª9[ãë‹ÓÑlqjû²5×ÄÖ·òšS3Œ/V“5F±BßÊ–óvöÙ'öÚ˜Ö5ǦÎî%Ÿúý‡‡‡«vVi%Œ¶Þ`•³¶ÁÝxÕÁ—íSKM`LÞ­F¸Ï ø÷s6 › 9¸u„j„½ãž½V|¬@¶—í´¦÷½’ö(ë+¬«Ã3mZ?U]çH¬aÃÈ«J´í+±WÆ^¢U—p˜Ø _Ã$Úêx‡ú®b3ܱçðܱç.7 Rb«¸£‰Â÷p‡ öä`h¢ÔÄIܱØäÛöàŠ;ºžÅ•Ô€é-¸£„÷k¸£nu'2­3ÛZ!^Ü¡xm¡GÖ·)ßXWܱg¾G3€âŽÞ8á笠C×¾?^õ*Y±*î0n¯ïï¿ÿ~å)î°bXIÛU2#“U÷$ÄtSQÊ$ËæÀ¡j5OSÀïn&?CP¤N±.!ÊÌÚ³£6oŸ±’«%Cõ|ú² ¢eCk‰§vZ©Ä>[6P"Ù¦=£mòm2e nf\ê€sjØw¡×±­“žís¨»˜ŽcµÛ­M³ÒŽ=?™åj­¯ŠÅg¤U°}»´H’úÜk6ñîðœ^,ªÁˆ‰@×ë-ܱçþwp‡qO¶kikøGp‡1§†8KnÙ•«¹…¥íÙ1žŒÛ'Òcï¼½£Ž™:àË—/WsÈög;·\“ª{+­È[NïSLRÜaq£Cè%mÄwww/+32â;ˆúx<˜•<Øô©ËMÖÌ[ ÑN–VŸ¬3•ì‡ îX ]5Ìèj)8``i/Èàn¹m/M02Àf?€›A/rÑþ^vƒÝRq³ù»»»«Ùn0Ëõe˜;ÝÆj”ì­ÏÆÃ{›\ù‰~é‚WKΣ2½*k¡@Òæ9U¾2’öaÉœ´áÎ^ÕËÛðfâ*+*ã(C×=0½°ÌšºkAœ ›ަ³ÝX'- œËòhºC~{D+hÍ5´/µÁrÁÆçUÐ5-°žÓ\{ŒK’®9uÔ5)õù;LÒdε$ðè|™j÷‚U%“f«­ˆùÝ»>ß§}~Õ\Wþ·½ë!mÕ©ÒLŽ´€µú]Ëw“ÿš,)_œÀR eÿ‰ZµÞZl˨.¶Ç+ÊIªóÖ=R áþ}‡å=jÕ+·]î`È>™ãNÖ–¹”a5Nµ²•G xÖ¶ú¦Z ±¯%×öbéÎßS•¯†öÍÖ:Ý5Ýž%ß½¸Ãw!h+cåÃùí·ôÙ«ÞP<Ü!Soßâ-Ü!™káº)îh%rïÆäv}<âå‹'Ü1b¸vâöë¼wH`;ïË9N·p‡²2ŸMg’د\Ü!q(‰"¡n³÷¨¡Ô-Ü!Áì:?áŽÊüOÃ)ߊ;7¬Žu˜ïRÜ1«ölJн†;Lþ£%w”ÌÖ®\ã)qÇÈ.儯3{›÷Þ®’5l2Jl ö°5Ë,k¦$§öƒÚ±š, Û¡¤åëׯ—CÄË•¢ætåð~<0;÷¡Œ7ÙpçÔ<\ ²¥JD”ç,Ø´ê£Ë—ncmþëôæ1IΖðe·Êh¹Ù µI4ÉØá«3“òÁ©AM0´û“UòÞ´(=ý¹NÚ@zOê¸ Ò6+6p[noi]9¡ïÕ5¸`¢.\­leTkÂ+SlÀ´Ì®½hµ­ì´7 “œM æêdcyÏ@pëZªü´Ì¶r ehÛÛ''ó ¯­•´V.N}B5mPî¥$¡ƒ¾Zúo?–½-J ÛLÚž+M^[›k+¡tœxÚ,*8ÖûÔï¥ÌI©V%‚5˜¦¼’D‰ªUOý4µ¸=5áÚè^ªUëQŸ¹ÏÅ Ü5e©²ýbÔ)s\Í|›'cÓTâÔŸ§!CA±7 ÚÞÌë^µké jc§2OÕ :­Ix®Çöž´jVJYs qG÷ñ[q‡$Ë[qÇÜöŠ;v¦n)·ô¼³·®é-Üa¼sN}Hî]q÷^[ì[¸cÒÎ[¸cïýôìÛï¨ÜÊªÏ w´‚ízU¢¶÷óVÜQc ›ñOýB·p‡{çîËÞÂ~Žý%VÀ4è«Q;‹ì£{ wHÒŒ,rŸëe¸C¢ù4W®ý•5~èš>É©MÔ;èZ2Òwu4¨{õÄåp’æœô÷õâ¶ô_–£PÛà·Ï¶™³MÇuJ°š¤æ»×Tïs³uí¤½î~KÉáê¢ÕÆ·ZX%é2õSãíî§RƒNžéá°DÐþ(º²ÂnȺ½¸ î/ÐÊŽ&6žV÷¿Ð ­]§–¬¼G×Q¾[K¼»¦mü:y/õ¾·ÑzßormU¡.xœV4M÷ÄÊÏÞoAc›´·–,6.:ŸÀ‡&?΄p>ò±8ºÐØŒ_’Á¾&™Yg(9ŒÌà~zç&íÝrèÀÃl]gåi³Lj”jÔ6´ A«‚~ϳ\Cœ|}k€§²[×b{|š(aªÅ°ÉæÀƒ@Ç÷¤´q®~Û‡‹µŸWvÔª³}z[Gj½uåt€\ÚØ¼5³ý\™¥1ͤ¤¤Ú’8«a6sw†šÚvŸ·±Ï>ÿNé©IZ“Ž&lbd•Sfö£wìŸÚïÊžK&ýop‡äÙÎÛÎ5+¹wÂ&Ç'Ü!¡llUÂ.Þ*îØýŠ;¬„ÙÓfB¯»™ë×þC¥Q·p‡L½dÛ[p‡Iß w˜¨wxþ{^t;—Ë5mÕ³ €ÚQ›D¨$êš6yíšîÐáSþ-Ü1 ÛiݽüÜá~é¹!îèX‹ïá“Ƕnl-™4VλëXl¼2øç?ÿyÅèìM9ônÀ‹óåÚ_!+ã<é#}Ykä®Ftî@Û´VÚ糇3§´Øá¿Í]eÁìùùùŠé¨F»‡g5œžjâ;CÁ¦AS]—LÕX;IÙì¶¥X¿á—_~¹{zzzÁ.öÐõwÑvHØ’›VeÈl0´â`Yz×¼w €Œ%Ù¬€Yx–9.Ôç3Ð »è¿ûöí2ÏÃÒgûððpaÁÖÏešþ뫊ÕÔõ'øÚý}üøñr°LÒXFÊ$ÁƒÍ»É^ÔËŠXeþõÏWâcµ­}ʰì S˯ó˜¿7]¯R¡ö¡L4\?®ƒí¿AãˆïÖªÞ)ýû5'qÏnm/áõûvœy±ûîc¶óJ›œuÒÙU[oö¿èr§QÒ*›9ulToEÀÆJw­2sVeC­hmáÞ½‰\+öÂlnïÎ2x1Á9Ž51Q:·äSI°Ú{mŒ;×Êá’Pº|9dT‚N€»ï=UÍ·þžžž®ªqö£Êô¶ŸkñEI›ïmÔÞyõáÇï_𶸶X¾ë·¯B»r«=â‰eqÇ-SqÇîËû—Œ.QZjÕì„;Tjl?(5)#ÝŒŸO â™îáŽÊ¦ëu wtü£q¡¸Ã*…²ïâŽS5¿¸£Ÿeâ>Éš¸Cù°qAûÅØÊšj}| w¬w¸½Hû®õ²Š;jg-îÐú §¸C÷É·âŽÎ Ùsw¬×e”⎵1w´§«¸ã¯¿þºô39^¥äƒ½Èb—áû‡\7&·p‡¤‘±éEeFf毿þºûôéÓÕ”MÛKR^%*¨®žR`+«u² þùçŸ/@ÒF=GìZdâ:¬L­µsj m-‹f©Ý!êß{˜«ýózÊ6ìžNšãþŸ?¾’Eur|K“Zh–ÙðùvžÎž‹fíØf±'fÏùééé²6:ëÂà·¦[ÝÏÆ‚›ØøN d²ðºlì´w°ççm_Ù€Ñ@€¬–ÁGM¨–ºÚBªÏ¶Ú¡‹ƒºÚ`×Á¶NSï!'›XÉšn&6#º•vZ!µÙ[rÄþ–Ž<>>^õ}ìs,óHw@ø=•pȸ·W¨{T-ÿÖ³Õ©É~:Ï{°Ê³¡eº®wÄ{o¿¢ÄŒ¥® ¥´­h8+ Í 6h· Ø$¦²]­öY»6 E$³Êü5vt¾I|FK4ZmµU9ž} ööÀ×dÅ}iõ¤îB­ø †FhLVÓÉØÎñÀªüI7Kݘ”¾xèk›ªeªëÑ*fÝLá®ÅIcÝÈ35û°Û¿Ë†ÛhþïÿûîáááE£õâÿÀ$Ã>ϸ¨¬ç¬rÙ%ŸûóîØúW~hŸ¡¸CÙ¹’?û!‹;*—9 Xõ¬Þ~3^œpGM`Œ—‚ÍJX‹;|g3´y|||1ÒÆí[¸ÃsZ “¸®øqë«•ðâŽÎÞ[2¸µ[2VÜaߞÒ_Þý·p‡½áWDˆã·Å•‘jJÐ` Hq‡qª¸Ãµ(î(Ù ™ä¿†;?‹;¬ÊˆUnቷ£ÌÌÌÈÁHºŒÉ<ÖV®¶¥=d:» ÒƒM/6{¬dÁÅ,hp±(›:&WLûк‚xoZÑiûê=õ%í™Ê@ØÀtjâ2È,yMð»ê Qïø–4=ÞåüêÄ­~l{ȨÁœ¨í`U%: ¬ªUuøšŒ­À@®Ôŵ²J‡’ÝY:A¸½<–a•5v(½X€­kIg*5€mí xì}jH]´\“-=+¡ìÜ Á™æzÝá§„ÌÏQö´}¹wh)¨ìú:Òé¦LI°²ëªsÞi˜£–·2?ö~h«{KV&‹jÏÀ𣻖­8ù¹ºÖTžçðÝ=Gã‚l¤Àѽ\;{AM÷´kf j-”gŒÒ¤Mݸn ¾¬h×YÄ÷¨iÏæÝöÕx¾éÒdÅÞæjã–=6‘ ;¸oñpÒTnÍ*CrÏT²(°v¶‰ýW&ɺ9?ªò¬:5I—T«k™`Û¯eb3àbÿ˜ZzqG'— Æ=Z!ëpÚÆ@Ïq‡kµû¤šý×p‡$©¸CÕBpåáµ³} î0WþYx wX})î0Qîpè×p‡†wuZJ¥|öª˜‰àîpínŸj‡îø‡Ó,Åïá+µ'ÜQ2ñ¡ëÆêæU2#sj³Î7'&Ù¬ßAq~iûf,¥›Åvãv“*ñê 5ξ¨6Si‘g%æ÷6xv`R| î[ò·„(ØÙ!×&(§[Ëží9-@ .e1dÀõX7xÉ©ÏÜÁ ¼Ú÷ T¯/(Ú=ØOáÌKûÊmÊö|~6îËàœÊÔ'Íí@¡ ©²$­4e¹“f¢o°ÙõÕæ¹VØkrï~س5±ÙuëoBmpÕQ‚a¿ÊþN™‡s}|—6Çkëû²´nõfl˜ a‡hçJ˜¼h…-S´w¨diÿ¿Š…1O39—Pp¤Vݾ&gb ”Ož`3m«wÚo÷ýµ—AwCÿ»s¦”~˜°ÕT¡MÄ$2Ö0ûÙJ¿N±F0PS f¼%¹ƒì}·2¿Ÿ3)ég“}/5¡P²ÙYKû÷~·Œ¤ç€Ö¥r5Pf¼çã5Ú‹ÒYjZÍËš€lÍ+ÝkoR+{¤znoàãÓÓÓÕÙæ³¶Zlÿ¬ÊƒÓwx¦9Wªè·pGûf*‰w8Ó­‰¡ÒXf±H“ÔÚÆ[‰ìÜŽîÐéÉÏñkæaECG/{KM¨Öqj¾¾…;œ)d²ëYô#¸ã4HYi¤Ïªgiq‡ æbôp‡$ Èb´ræÅIÝëŠ;j®¡1ˆ¸C2Ëž–[¸CLt wxÖ‰;Z`ÜÒ]Ìß3»^}/&™·µ:BuÏݾ¯éH|¾wXmê•Ýà kæMþ–Å6H˜ýªì<‘Ó@µ-Þ?þøã ] ÓðËÄTkë´o_ø4ºZÅnq×ʃß^‹eÁjù÷Y“uy¨TÓW¦ m½cg÷ÌöLç]’¬:(J]µ@}÷l@›6ýáááj– QÀ¤Â’¾oïéþþþ"_Øá#SO®5îÞ¥2?7ù~Ö5±÷l[ç Ù¹ÚÈšP Ô˜àtxæI è;X™zŽL?~¼<Çu×;ØÜš½ï¹åÈöí³Þ¿ nl“—É"šÜn=Ë’˜èî·ý¾ÄÙ9 ¨­¤Z]X–jPÚuZõ\¼Y0«Œd{x ×ýýýÝÓÓÓ£-ë{˜Nw׿¿3Ö=??_üúuhqÍì:´Ùœ[Ôö  ГÊ*·¬sX§Ê{Ðyï‘ì}n_/æitbõÙ8-ˆh¢RÚ½#Át§~ ª°ö3LâÐ9M['5XñÚ÷Üí˰ò;É­ ¢Õa÷ÐúAµb–‘T’\‹tëì‡Z¦[­ÚÚ=õp.l:é]5ÁÎŒ%*62OéL¦½S]à*Ûó‹Ñ²Ë‹[WûÝÅ(Ao ú|MdlÎבk¸ÃsSÉs߸4ÁµjU‚Åfõ1ÖÅJN_Ë)Ê—øv.FûFö¾œucB½w\Ü!‰YÜáš^üìœ}÷dcu¥Mx+r:¶éJµ˜W©Ü$¹‹[¿ÅJ(‡;”;Vâ7¼ªUºg¢Mï®i¿jî0Ü¡ü±s›v*#ôúT‚èÌê\ ·«3'Ü!†îxxx¸ôµ8sÉdý5Ü¡TÐ=} w8—ͽl_Ú-Ü19_qG‹;”ño5\%3ëmn¶_YŒÎC{@·ØwïÞÝ=>>^1/.P~‰ìžÍ¥–dÝä²å^‹@Jf«C0—\è"eóô‚´NÙÙîG°·DÍ ©DW#Á‹%R7‰¶º³Ñ‘²;÷÷÷Wefƒ™¿îPº˜Í—uØ”ÑV©†_[H¦n–úÕ£«õ–Á•e0I]"êaãæ­n؃o=&r6Ü>>>^1´®®k[u Þ›kÉ=gã¼×jƒ¿U§V»%®A'k[ÞVn¥¡ƒ NÝtœÉaÿŒ.²>ÛµA.£luDy„¸®'µñTÛmÅk Àþ’݇æV.:ˆÍëk‚`#m'Ï[©ñž¬Ô±ÉC°2ÎuW9ŽnmV÷L´v½ö'Yö?Å«§Þ¿ï@kÑÊ}j×-ëþåË—«=lõp‡±äDç¸h âžS&çÕ%uÞ‹ýcs’8K¦Us>d²µŠßöÆÎ¼ZÅ·2éçà9ãöæOTÚ£E}Ò«TS&~k–/¶*` ®ãagÉù³kÌ®d¨¸cý^*=j3| wìgŠ;”ÖV!yPÜ¡ŒHÜ1j…f÷îž™2L¡¬èî0®x]ÚîšðH¢ ˜%­6Ùë°Ò™D{÷VRêìZÜ¡Ê`øEy]MB\«žã'ÜaÅЊm‡Ï*wŒˆXeõ{¸CyüH´Zýøwˆ}1ºñ¾w´ÃY<iJ•݃îÑîPžøî8;»Jÿÿ*™Ù¢òóÅ5 Z‘°ÉS)˜–Ùœ \)Ò~OiÁn`xMµ ô¾Ä•¼üNB–Úž®b´ìÞäJYÍI ì÷{x *ë”![½ŠR‡cú»'mªåû ýúÍhMt9ñàÞóß­üÁ Ñ fsh›aë!ß¿ƒ±ßþŒE]gP“iª` Ö–ÕàQm¯ÁÜ t+irå;Ûû(PôБùÚ»³iOÀ] 8&fà¯É¿I€UŸ±g§R²ÉóIsíLÛb0›ÎZMmBAU™pãƒMÔÝ-«õ矾˜Òn ¬>Ûä½É®ÏÁDß„Ò=kr?¦YIªlÞÞÛî» èµ¼?±zgc¯ j™u‹qµ³ÃØf_+Hûßdu +X§ž §l Â$””k.¶Œ1lÃÉ’ß³¬ý)=Xýý­éZ—¼h"ºû` Ñ{\¬Öžw?7¢E÷HŸ§Õ²&µõV00,Ѻ[™•Ò,É6÷ê®YÕCOäx¾ÚÔ>#%¸ž_‚5gzÔòuf}æ»×pGå³'ÜaÂÖäß~½ûûû«Xn?À-ÜáùRrÓŠ[{Œ=vî(é»%¬uÿÄÎf{x>ù][»ÃîÉîèpØökš\˜„(•Z’3ä$Áw”¸QŠ|ÂâÙJÏná‡Fz–Ï«$±=ÜRyu&ëø('!¯QÊâ×Þïªa(œp‡eÕBßÃJË%ŸN¸cëíØ3³rÛ´l;XWb.= ír(ÇÐÊÕCBÙÓivå<‡‚}AÊ–dŽÚÔêâ®Û…e±N>_‚¥ûÄSõœ.Àv‚™ð¬’`"P×1“šjƒJáö<º8ðpšêª}è‚–IŸ½52ò26/÷}¸ù•()}³‘±ü”TÄ ÌJG&óQÇ>)€ìLû•”¨uâµÍ}`¥^ÿʸՋŸÖ´à{@¸þõ§5m°T ²w7Vr€Ö¤Òª†NÁ­ÎpÚ¼Ú‹¡IA¿_™Ò@‚F®§ÚFZ}Tx"jU®%çö¹%q{ë±/AÒƒ¯àwÂJ%$”?Z)´B!)tSüýÊ|•÷µ‡P&N«P+Û7ëµ5d?„v¥*î‡Å»Sckç§t6’òÆ%Ú[á¯\C× ‡V:ªf]lÒFëãáâ®Æ&„2׋{JDOnŒ—CVˆüŒVØ”ÎxnH(ØÇ¡Ò3ûWiN=6º»ž[!Y‚:ܱwSÜ!¡` õý~w¶Å •b¾†;Úogå¦dngkU RG±í·îP®¤ìUúî&Ñ´¥•Îʨëh'®½Òòö/™wÔª‰îk¸£.{§YqÊØO¸C•P%÷âÏ( ‹®½š=‰·¶&¿‡;œ¥¢\¬Ûü®jFã ãjILɸ–ÖÌÃóê{¸£âcäÖƒ†?&‹Æ×pÇbÙU2#ã¿­»Ô˜©ÓÄ罃…ºÁ»»» «¡–uŸõéÓ§R…2ð=”ìÓ±ßE­`›®úÿz{{ÕÚ±eS]–d±¬huÓÚxk™x ~/ÍÜf:K¼V‚NC¡Ê€ÀÆ”©'Õµ®²_~ùåîóçÏW­&nÓ|›JëœÓ¦C“ÁÎ&jó¸ÌÉ‚êžS‡†Ö}¨ìàØÙå·ª|fï±»‡ÞÝÝÝÝÃÃà õú¥›¬HØœhÐñº:‡¢ v%x”I©5£e|Y"¾²Sål²£6Úœm×ÜA lÒѾ*%ö,ƨWß÷u8ážÉl |úÜjªï CMÝNÖÞóØ,{ —ìkf Ü¡¡ZH»GְĬ²£®…Ú’[!–Y( ¨”J¨w™ÍüViLF &X­ l˜÷¢$·DU9@¯¬(Ê^Z¡°1· ¼CßNñ[Ûd¥Èó{÷W6é[/“AZµØ;ûúõ닞@«6:Šym&ÿ­–ù 7ÇB0?i”²(Š:“M[ì:Š;Ö«%îèw,®¤[‘›ôi0l D«¹&kgtÂí‰r}*‰³ e–sGZ®’F7¾“ãž p}Å'ƒÅc¡¸Ã>ϰáŽí)EÄ#PÝßâŽö˜¼wX©ªÓ¤küÔSÔþ'ŒÎúº…;*RÞw wxÝmÌowÛ/ö^6N¥N #¹‹;LÊv-§¸·pGÿìGqGûŽÄ’"‹ÉVnŽÖÌ2wuøÑZò4ÙÚÒ‘àÀ­s`êc)]¦Uöݹ$@‹™y›ã-å—MìkAéµm#úÂOSOL²[ö½¥glÌÞ•LÔ6Ù :@cŸ@…5©pñÌc} ƒ ÈE¤³ OûSÀeÀÔñÛ æÏùy'»>Y('Û6‰°éŠ¢ôMpa©ÓwÛ¾ŒÚ¼ÖZR°SS„6Án-lï &­~ʢܔ֩ìÓຕ.X¢®¾] SËþÕKïÏ\/î[-[M”¿}ûvUbÖþQ¦ÙßPÕF;,ÌfÆ[3”vèºâðÁö9Û`MÜjÛ?$ ør:u{­òÖÚ~ˆò«YFÙxv«`íËñ= zrŒ©­)Wh¢öÔ%QFŽÕþÔçT'žu噋euç¤*QÝïiÑž0«»*J¯ŒÑºPuB¸ÿ[b¼÷¸8ØÁ÷¶½gã|çU°u-Rî½ÏWæç¾‘mÅܸé?•b{®îw‡;ìð|ìù¯DK|r²i¯±LqGeÁMÚÇá<+׬գVâv]ÎóØ{R~^·µ×p‡Õ8×ÄžÇ-Üa¥XYøp‡äÔ*yû.{L­xU¢xÂ?ýôÓÝÓÓÓwH`uþV¯³¸C¬ª}²ÏfÏÔž˜îh¢| w˜`·ZSiå wÔ\Ê$ø„;ì| wèðçu‰;üûVOO²qq‡xÊÄ‹;<Ï4«¹…;ê¬bC7³Ÿ«ÅlÉNÇ)¦Ï[à²j6LÚÛQ=òÀÀÀ–'x·y_/p™[³Kõ×`‚¡#—ƒ¢.U á„Þà^—×¼Ÿ—Yÿþý•œ®ý– í{Ù ßwí½8I\ð¡NÔÒõ@½?oà˜;TgÙ”1µ\ë`ÁÙîØ,î\›1”eݶlS÷o2·r¥,u—ö(•aW²±Ä¸}_§žŠDØl¯øw1%9c³eÁe.[åªãŽÙ²11B'øî€Í%çÚ$*OT›<É€ÉÔ®_æ¤Ì•Ë1¦2}ë)pB¸2ea»¾Å+xV< ç6çIíš;…¼®Ƀßo¥y̵{Ûá“:÷hÐ!8;g+#'&O-µ Ÿ“vñ•@º¶¶—?}útÓÒVi§Ò)I`A„¶Ûí¹¬mhåÌ u/ IDATýõ×Ýo¿ýö"AlÏ•ÕñÊ}62Ã.hœøXÅݯJ±w²ØùíÛ·‹©Œò«{–Ê®±VIïwoû%E§?‚ÜUqjÓ, ݲ¸æšÑ I$Ñe¯Ô»wïî>~üxå†h5DW…Äîwr±ý~qÇiø©ëÅdYù«.~'Ü¡9ŽÉ~9“¼ïác´×¹kwØS¹ûÚÙïÙaoÌ’"“îœÜÁÃÅKÈÅÚ»w¾”rÞâÏþâŽW¯áŽöJ¹¦÷ß[ÓâŽá±Ýi¸û’âŽ:ñî=~üøñªg¨2Êη©äpqQ»k±‡ }ãm AŸ¹¸£}iVöÄ‘:¶§Xr{†ìiÜš^kÄÈ wؾàå&¾â1·Æ>WýèÊÌÔáVN ¸èÀ =¢·W’®Îu6}OOO7—=d«µßÏ 9WF]ö} u³¬G{R|ù{qŸ?¾ûðáÃÅÔFp›£ZÒ³„¨&Yã‚–Âç:¶à ­¦MӲΠÎNzž%¢/ßÌÜ~A¹ ®»V5šj_ußq¬r öSYž·÷e÷áÇ»çççKr ç½¬ü6žö}WýnÒ]«K·¦ügi* ´u)£0›É½¯ÇÇÇ»‡‡‡»ÇÇÇ«ŠQçæíïÆß~Ù~š¶t@Å’°sƈ-Qº~ùå—»ÇÇÇË{Ûu??¿˜¬.ðwlM‹;ö®Û{lÅkŸñøøx!O¸Ã8*‘)A¨ñÁ w˜@jï®1‚•*çÇpÇbô w¨Àx îp釮Ô86”ïœcéˆé^³׊Ûp‡Ø×˜,îØúw8Æb1pײ6{)‹;$™L˜% 3rwww÷øøx÷éÓ§‹-}q‡FÎ*ó¿í;t ±ÏgXÊ8(î°GÙdn±G[ìáesâ“gIÙÊᘅś+™™ZƯ%wA‚Á‹’±½ÿþîÝ»wwŸ?¾’*)•r`‘Ž[û³Ùú•Mm¿f ÀŒÞ«ƒº”­8äoÜ2J›µ,µJÑa{¸=¿ðœ\k½ƒhŸ#bßË Lyßžr$ŸÝüq¹ïÎ2¹Ö¢NH‚1ƒ¹‡”eôm\Á@Ÿ2 eÃMZkk¢]À ‹mã£Ò€»ÍIP>¦LÍ€Ú†¾%5÷÷÷/¦úz »>w;L<È:ÑYKn{ögÎBÒÌf~Ÿa{Ìt¾Sn¸dz]-×Õ†× N¯e9öUY9^ ¶ÁY)ÍÖôÊÚ Îºcu £®„í£ÚÚòùïø=Vq±b¦}í’˜4í¤w®gã²,°kÈu(·øaß—æµÝŒÄº™¸I"¶÷ò-¸cÉJ¯ÙØe¢£œuI¾¸ÃÙtxq‡ç}¥ì‹×Ž'ÜQûÎ<9JÞÂíÙüîÐdã­¸Ã1 u©Üž©©T×Óà×z­ ;8º¸£Rºî°jh"æùï{ܺ°Ê&³‡¥÷ÕôÊA% N¸£Vê’"«à­jôî0IS-¢JlÖÌ?«µÞ/ŒM¨Û⬛;ÝÜ ˆŽjy;»¤ÞãfV0º‹Sé†Ð/û¤½Þ üúõëU“|…v€¢ò»m8uémÚ²7ÅëÞË\´Ô-ÓäDßnhŸ£åB+U°º!-ð«)ߟ«Û^P·©ÕFè½Ã¨¼‚¥qËÖ 2¶NŒîì€ÓœžV=üÇJŒEiÕcÁnLÌ›ÌóÖ‡ÆJí? ©‡ÿêi}v]Ó30;¥ýéé銡ÞsnO…Ö²õKjzXU·ß¹+2¯ö«™”è’r²Â-ûå}Ÿœ·&·v+ÆuþZ“®ßeŒ«.ƒÊ[¶ö\›€Ú8껩=öÖôÜÌÊ*6¾y¨YÚ·ça{·^ý»Éb]|Dã˜NŠî¿Zî6ifR`ÉÝr¼'o`d’ž±|ÆÚÓÓÓU<Z9ê|{•\cöÕ ÇÁ‚‚2“ò“qƒkÚg%hhºV-ñÚ_c¯ËþóŸ»ççç+Iž{Àù"&Õm8¯ý±&^ûd[&3Æh³À~篎†‹!·pLJ.ë ¤R_wœLß‚;z–wì»\Óâãÿzïvm 51šì§U¨Ú‚;c´ ¸Ž¦žÏoÅö4wœ M:ÛÏë°Ë*‰ëròÉáÝÚìA<áh—HŠ;j½3¤=³?‚;ì#ÿQÜaò¹g}Âûþʲ»¦ÛSþ;¶ŸŸŸ/¿ÿ믿^á;ŸÙâY%ÒÃÒöëwx}ÅöT]*3cx vƒcd,¹ª³õÁè(Ô8.ðï¿WVÜd™V‡.³Æx³½Ö²žºPØüºïîP!ç0¼ÿþ2EØr{mP=œÕ‡ûg{>“€-ûÜçypË´Øl%[ÐÆ³I!l w#ï`+ó¸v›æááájÚµ¢KËÎì{´ÂuÖÁî«}#_¿~½ÈQöµ´U{½a|ÊQæìS)„Ótw/2Ê;\¶fêÜãA%1@:Ey ˆÚXå*Ê.Ô†jÓªæ½2>»ÌÝöÈÞ‘{kß&Î>Üýúë¯wÿú׿®JÏë3è\ uª{µåí É!<öÌ÷=îg³l­oÒ¹û­ý_²L2sö¥<<<\¾õHdàë&¦ŒQYÖþ¼3[öZUR°=¢§vð[Ç:,Ù{¥‰Âeßµ*+•êÌíù°!ïyàgñ¾6¨oôþ_6GyžÒ%÷RgD ¼Ùka”Ò–ÅËßÿý+Föyïcç fee•ˆ:‰i=\ËØ}ZõÓ°7¥tuˆ2iÐéÏž€­ñ1Ø®E«5íçTz\{úíŸÅ~Á©ÉÝîÉþ-5´ªµJ°~„ý»g‘fZß®_t1¡ý=ê¾Ýº5.þíœw˜x-ÎØè¿ÿ-É”+µ‘^©OqÇö–qÓªñz84s6Ù³2AwÔ6Ÿ½þÅ«îPŽÖÙbÃPKûUlôwW+¼J|·4˜œm×ãyÝJ’gš¸Ce¤LÊø†;¬È¨Øù¿À[»öV;²`q¾¶Ü·p‡Rfå}ëaÓ°Æ$½¸Ã¸µÄò„;ŒsbûâîšÐ*;Þ;úŸÿùŸ+Ü1°ÄUbçîðï=3–¤ˆìW9•Ìe’@ Rê[ÁQz3€ Xn?út·ô¶w€Ú¦?2JæÑ{hkv’Å^@²éW¶ã÷ß¿°£Þ³i«,mæS³hÙ´vˆ3 XpðÐæÖ¾–6gùüt¥‘ýìL¡Êálº³9ÎgßÁzÓL¶ªd’ìftró~_FÙÊ•›}F»§öTXa’åÚóÓÎtŽ'î{S‡­õÖO‘¶ñOÒMuÉý›µ­.`2ö6øn÷Ÿ>}ºÒ_ï=lÿžP~ùòåîáááêÏuA³ï«ŽJ.Zz÷  hÚ3qšW±5±Þ#½ë]SJǬèxð*áSÒbŸ‰‰A†M˜ô”)íiw'〦;êûOýxV·)²»ÿùÏîžžž^¬ge‚ïÆ¯Ñõ««œ1Z'=um\ý¾VO6À6ñÀž¤¾V¶—úé§»‡‡‡‰õ@°Ë6§ÛÐ-ÑUëó¹úXñXòTi·ßµJÞôd7*îûŒºïÕã;–Àµ;àâ4u™û™îì<óZÝ¿;¯$ê,ißm«…VKʺç:=\íÁÅ?%±‚¡á±I¤ q‡êq‡}Jж‘¼¸£tqÇÀ¶•F-;÷m¸cÊ™Zº;Ïê§]Ç'ÜáPã×pÇž»ûuïaöËÊB•{u¼†;|?źƒvºýÉÜ×p‡&T5Pö»Ø:¬²žšÅZ‰ÁîÀ–ô ¨Õ¶ûkïÂØ~ wHžp‡ÞÝõº‰;üÝ»xà âpÇ®oçµòNñÅ\æÄ;ÿMôbhf­;è«Ö•»ˆ=T7³SÓ-÷6€žt±N"­'¸ƒÙdÅœ\îSÒa¹M½]ÔÕÛ;áUéœ@FÍá~{ñêÌã`°ÐöÔr£ƒ 8jZ탰Oæ´:©Ý\g‘ZUv(à«:}È>×.×Emt¶êÐ&PßÙL+Eö¢,u÷ °œ.›éÁ¦ ¢ýcJjéªìÌï0@ëê#‹g“d“úÚÍž´·µ¢ÕNÜÞ›… @ʯlxîÌÙd­`Ò^ÙMg’¸*é±?ÇJ„c½{Œ9µˆoå§®yîÓ½;M,”K-697Æ^‹%ØüÝ¿DA <: A‹íÚ>«/ßg hÕ=«/—˜ñðQ&§Ü¥ mjÞ;ß¿×uNÐÓëUŠ¢.ßÏ9 vë|WmHç'¤ í1©´XI§ëî”N’·±œ«Rx:­\÷Î[SÚ›Pz®nWfåC™¶ïµ ß7nâãóטÆÏ/(“H€ßÂJX´–~ îp?·—À½å¹+îðu¾XI§Ïÿîè4yÝ í!³*4¬æ §ÅúV‹;:ÓH à[p‡Õ±·à‰Öâ–[¸ckþî¨dV fïZqŒ¸C5PqG{M˜Ûjõ®}ÔK´=c‰{Vò =¦ÊC¿‡;ŒS§ØÝ=¤ì®¸£ŽÀžo]·Þ¿}§þœDÍð³¦+=¯®’YúNø^ Ó‰Á’µRˆz„ﳞŸŸ/²¥9ÊŠzØn-çZZvÑÖ‘l?SËQã–Le̦í{±ñl÷«\¢3I”îŒ)ØâЭæÔ=Ö ˆƒ›N,•6‰cŠLÔE&£/3§fþ4ïG`bžÔ•ê²#ð¯«Ü ª|G\5aãd¬@öx}&ݰcM •y Dd,<¨öÝ/ä=·áM ë“Þ·2´I Í·&¶{_î×qÝ;Ö¹jƒËÀhëå©3¦\—Úl*ñy›¬y8mí;°rluûM:»CIÆöLqiÿÙ9­&×3_“«Qþëó¹ÛÀî:éDn{”÷í}¶Áµ(ël“òâäÞá¤6jÝYb‚gÎôzöþ¬lÔT&mZ+A¡¤ÁäE«cm‚G¶¹N÷<Çø©ßþuê• ÀâK¥‚Vx¬¾Û”ï¹g’°8á™dõ¯®hÎg’éà;ÑP Cî‡Þ¿©l©ºè€Áý£ÅºI¨Cœ•¶:ðW"ë„;ÚK!à«[Üaß—˜á„;$<^Ã&Æe £×p‡Ø×p‡Õ%cA œFôìºdáµÕ/îXåÂsg±w{BÜáhí™•ÚžÖœŽ¦ÅöËÞž)Å­œX©“ô“¼Ô±­¤œqHÙþbOe¤2íý­Þ¸ÿÿ‰»Ûä8¯#iÃÉ"€ocö¿oÃ"’–äù•Wß8 BòÄû*Âa‰ºŸsêdUeenowÔ×okUª¨Ô8;3+p‰µ,¾´`«yk‹¨Å}>âãjq‡xÞóiñ`?§á´¸C–Åöó› ]X.–½UÅÆQÖ§ENn¿¥Ï8tæÐ“›Õª™mM?³ÎÞšTöÒ!ÖM²ÁàÙJëh¥S~½|>«5íФ’›.ö=‹%Ÿ:;:Ña/9Ìzvøò¾æì3®^¾‡q׉ôÅUÒÔŸ¨•Æ}×ü:\÷ùóç _w¿3@Ñ ‰ jÎ/Év\¥"e mßz¿§jÐö„ L‡Ÿ¥ó9|_=«4v1 ðzZÈ×KÃâƒ3jR+6Ÿ&ÕÇn‡k¢ô%hï&‘RÆ|?J=KsU"sîÖ÷Öøè0*Öt~©”»vUîq¯rçLœFg«(§[õÀ|ÿurv/‚“=ã´¹uZ?%Y»žú-ÈE¶ãP?-+ër±ZkËõàµÛã{ñP·¸óD_&“ í¤ ÚAÞ{è;SÕÊ"Ýžé(-ÿF½¨‡”  T× E‰%xÎsŽf²êÞ³‚éZÓÛ¡3`•}ÝÏ=>>^‘jì¸9Õõ¯øäÙéïÛ¹•2*íåî°ÀXioךórÅ{Çã5–Ú1qwÜ:OÊMÅ­Z‹;”Q>á=Â*²õìùãy¢¥1Ú53ܶ{î°`¡t¾ãóyrîË«E*ÝjðÜ"Å{pG•RÛ™åWÓpNqG»%///Wþ4»—§§§W¸Ãx] ¾çš±ò-Üá<â[¸ÃÄZвÉþItå„£‹;*šQcøJL×/J)}q‡"½ë´ñ€ÅñÒZ}÷WÉŒ[«cøD [=S/Ç!)ç ¶Ø¥tš•·«@:‚kdåÅ ÓÑæ!Üø°•²3QQMÄçµào’!Ŧ]­V´ÌVMBÎÄ~lÓÙZ °[#¥È  i›e@R:Í÷b,hÀj²`+´^£¼}AœÎg«R=öyV_¥*Öý]ê`šIÙ®G íœF[ÛÒ–V²Ñ †ò¬U%ÙóíÚ3yÚþ[ŬJZ'WáS'Èֲј°Šs“a®Òa<Ô+¦!åµR²ª*y Ky‘ï}’¶Û¸{©?Œž.R-âØÁ–v" òD”ÆæÒƒE€X#Wðßv~<$êBn×y|øu#,Tý\‹ÛÛg«Šî0²ã«?‹0gQ:»´îŽ`ê$ÐQƒÓŒd‡nuÏ–ª7 ^p)ørHUªJÔ6™¨É17æ ä­À ²•ï·h²wm¢»sq šcg ”K/DÐ%—ݼ- 'ÜÑ÷wZÓ¾gãôîE¯™ À;W Ãá„;|'q,î°Ð(úœ¸C€ç}WÅU²ðkb?Üá¹Sµ<¹ÉÎ’çuøŠ;¤ÒUTŠ ß«x‡k¢E7ϹáÏm1Á wøwâ»Ñ2jŠ;Z˜yîðl-î¨ñü÷p‡ëY¯4ƒNsÞ®Å[¸Ã÷ar´{²!îðsN¸Ãy™%‚ÎE×›I,íÙVÜQÅ9ŸÃ‘fÖvž‡~ƒÙ^¼š*Q9$)pq ßEäÆð ö»¤vÈ]”j…Ö$É@)WÏ+oV+åøyhï«Úá¡ëÖ+)‡ØÄC((ö^W¹sXÝn€Fdšlê ºwgµOÞ«ƒ.j¯±Ò¶¶h­ºÛýñ0.q³êXÏ”üþrì[­ÑôÉžŠ¨4SÎéÖ» EÍxg2Êuïú(g´êA®é%…nf«3*µ93ÔŠø˜Žï&Þ?¸ø÷nöù °¤Íti‡ú@x©…[Ór˜6woرlºþçö`ÐëÄäg‰ƒ>I53P;«aW«Åç ëOã!©ùi=t»ö]£šžæúœ•3a·XUš—Ïc÷°õÒCÚ˜_>´‰„Édé9š‹:+Ó:pbG¥KA¸4d“ŠÓaj·èÔ(©é«Ô Ÿ¯ÂõgÑ0XK‹‡[OJ³›4Z€(µªF¶EÖ/ÄN·Ô)Uº¬~ÛU½Ð™,“Þî°å5®RlÂãº3ÚìÖ‰;|·ÆH×ÃÎ v•-ZøÎw®}¯Ãõe¢!>QM±¸£Ú“ÊW}™¤³™´[06É2‰?áãNcï[¸£{çîPÁlq‡ÈîpžLÜQʸÃ1‚%Gî£Æ{î-¾)pâLšo½`ö9oá™.¥ñ:Óbãá÷p‡s«ÅÆ[Ï“¬îð™Ö‹Î"÷ž¯j·{Ÿ‡Gåé/ Uztís/~_ºî†V7lkÙâ–~i9¥ØtøþãÇw÷÷÷WZÝV)¤鱡I—ƒxRªp$Æ«´÷ã?Þ}þüù•Êy:óWUBœÛ °r±ïSšQjÛÚÄ‚û™ª„ÈiäÉÃdŸ¿ƒMÁ‰I£I©` f­\Y–ŽçÆØs²’3EŒm¨U ^ye¸F *kivÖâÛ·ow///W"奫kï=/iòp¨ï­âöù)tŽÍað')m÷)§Zþ·Ò½ F«dºvþøã»ÏŸ?¿âåúϪî›7(³+âš*7¼Z÷[Î.™¸«dhUßVôo¿ývQA³"äÁçlÊd4{¨ËÉ?™ŠYIªˆÄÖ`MC-€l`ñoŸ³ýf!`kk{¶ž#«„9'¥ã½|ÿ/_¾\â¼^‚‹í«ì›ur¯{`ÙôÀeÀsê\éj‚C Cwh ²­Æ®h£’Ú¨{{_¾|¹òûiÇPêZÕ‰jäg³w*µ×®Ê€Ýí­£Uæ5ì\õ×Ä~sivž÷œöù[·û~»gú¾¨|휸Ç\O&"‚ç&¦xµïýå—_®Þ÷bÛ’Þƒ;Fq²À²÷½g(îèœÏö‡3޳wœL›Å[W[Óî¯l¥}¹ÿ}/ž¥ Š;ìŠ1fQܱ}´µ#îXB Ö w˜°-Ö×p÷„;vÆŠ;V°w4¾K™ßÚîØy\ÿ’*dúlëñòÜa¢eB'¸Ÿm€ktûÃuïښЈ_â‹ü{>6,ÀwØUÒÞ¤©¦¶Rì·oÄka—Ë9SÍi[øXܳˆ´˜ÚÑ€§§§W¸Ãœ`ñmû÷ÊgFZCz&ÛÂ{yy¹,Ê=ÀýÿÞ*Àú¥Xe)~‹‡/ÈjE9‡{@¶;½f«VùÜ´‚²mžµòä®=i’60±ÁĽ`¹ÙVÓìdÉ¥\@TFÚ!¸Ó ü^ª-ÅQ#v=V|è}V“$®zdu‡‹4ŸryOÊH>ÇÓ¡´g]Ñ}Vûs½64™²r!@P¥f`Rú™ò \wŸ?~å!d‚¬`F7ò‚¥.Ü ÄÒð¶WöN7(mÉnJ•ã¬ÔZß3vïYm/ÿ¾€:°«¹•4 Á‰•ÿ=ßúYõ¶¥p€æ¬V§¼ Ž*æL”>|øp÷ôôtuk0YÐÓATé%ué._\)tíjIësÿ.™Ð׉[Ÿ-ï[@µÃOƒRg^^^.”Q‹%&à¥Ô|ת©®Ô£>>>^€˜ó)¥úÕÁ\ɘ¥Óu¸Ø¹=Ù[Ó]û}ã´ãòÈK—-øéÀ²I±{Ï™ŒÉRH4šsÝTü¡›y:H-­ÏPgS;Òʧ è*¨+”µàf‘ÈX´ýpêÐ8OÑ=åu †Ñz[½w4iW@FÜáÞqFî„;z;ÿîðüÖïÊÑN® uïM‹…â>q‡WB ‚5k,€^²)=oûÌ¡sÅUêY³gõððpÙOü5|6AØþ¨×Og¬û¬8’¸CÏ·———WÝ»ZhÞNºó}ÅÎÐø³CðÃKT×}WR¹¸£s¥ÊI+à³÷¼Ï±p¸wÚÔv˜Ä‹½Æ­îpowìy¼w˜@½š™©Ñ£™X4ç8t™¯l¨ ß Y ¼Z§Ú‚nç8¬þª(5Üa.;‚0«> ÌûžC»?B³bº…/Äh»;ûÝÛ]X'íö3ŸDôNÀ”Q•&+–ÔÍ`ø®L4÷^­\Þßß¿ò») æL¾3çŽÜÀ*eì}yh¹y Ȭ„‡ÏÌ`h5ÈáäÖí:•?5 Z Ùa´ ;lWC ÕvlmŸö”€Õ.€šô-:óaÝ IDATL¨Ãº”ã†AÈÃÊwTš‹ñCêC»{ûsUκ¦÷Tds? Œ²Ñ×âÞ÷ÃÃÃMG WÅ0>v[IÛ!2q‹Ýƒ~¾+ßCÙäÐ$ÌbÜ& í´t_T½Mª™JbòžoÉÞ®³SJ•ƒÎôœ:z®iAæž¡IÝïí«®5¶k¯›ÏqçÍ(Î+¾y€WɧέΫ°µýnc!K@m!£EšÊGW™Îî̪àVB=?”ý]5 bzlUæºf¡K8)egxŽ-î©2'¥ÆÙ«Ø>sßÇ wè$˜ÖŒ×BäŸÅ]ÓÆ-=sì´œX'î)ˆÞƒ;žÅ&Ç'Üá>wöÑ.HEk†;J×-î¨@ˆðYñî'q‡L#g-Œâ…Höß2 T@5¡­–”ØïáŽ&;+üYÜQüRÜÑΓÃýîULÇkì-£é4+ß=eâ{¸Ã™TÏß5i_,¸Jf\°Õ@—‡·Ž*­^ãUÏÒ‚Å·pÇÎ#ýS”)®Ñã*½ÅÎÁì{ÚvØA?áŽûùË·óöœ®Œ­1Ú䬸ÃDôîX•»]2UÓøeJTV¿æÑÒÞô^±ƒÚ3M ‘û@³ìâiŽÅZ\Xä<áŽS¡ý-Ü!>èœiÕZw âŽÎ±ÜÂ[c£8+R,m—Dóf ¥î%‹ª¤­£å;r¦Ïø„;F‹uîFÚëÉH¼ìžªa~wìÞN´»£i¦Õ“}éb+RS}Ñõ[ô*’Ò„Ôñh­U÷Ã?\µ… ½éªÞTÅA o`ДO€îæð^=à«©nkÐCÓMn÷IJÎFÍò4òM|l“ÿüóÏ—Ï‘¶±€´ö³‹pŽÂ£ Ú¬ ÙL%–, JÛ·UU•¸ ÛœrRèœë0 ž¥cuSZ49ã0`úððpU­r¸Íy²Ês:<:0v’¯¬Á¢@°˜v¬ž €íx ,= \õßßY'ß½U°Ýƒ£½V¥Àµó²kÙšÛ»³½ º5¼Ï_!àëׯ¯*ÚÞ¿µÉnî ¼¿¿¿âxïpðw¦Gº– ÐGJäÖÊËËËåÏÖºWéKÙð [%— çx×6*ƒŠDõ r_9¯ã÷lol¾FÙliƒ‚†v¤Áy›¤µKZ6;–Ò@M¨Rß’héx­êÊ3?Ç .žŸŸ/´9ãq%pwvÎä@ú—¾þû~~T_eÈë®*èä›ûú•J¶=!0èW|¶~–Å ûÅÈŠkÈZ ÕóÅgW‘žý¹¢&ÌÃu_Òi!j¿³x"î^u¥Ɵp‡çÄ{qÇ:=Òµ]WâŽú{´èWܱÙÏÚa°=k ˜=‡¤ÿXm¯Ø:àvùæ]U•+å«@/îh—ÃdC -î06×ÊÀ9¦SÒ°õaÇÄnëjgs a'ܱëRpl†â÷OÅ3NìÙΛ:wøîh'JåP;uîÕ[¸cqÙ¢bEÅ¥¸šè‹;ö¹v¸WØx%Íl`5Ã6±UUOl)íYP–“ë!Q¯+ «¾X}?|Y¾Rê„ý ¬º!eSªØ²ú"ÔîÂIAByA;­â:ìe+[3N«¤•üt(PkÛ“{ŸJÝ¡lu½ÜÇ‚7Á¼•W[®˜ªáì9Ü}'“ðøìyØJÝð‡›2‚Òf”¥• ¸õí¡¶ëîš+ê¬]2;p=„ô](“wmEÞêÊ%›twÀÎ*ÍóóóåÚ¬¢Ë©®‘•òž*½ «ÖRšÁÊ7WËãU•\®lt¥z—Äl WZÜ‚¡Ý÷¼_Ôý½ñÉaXAùb†ÊS-ìTjyÕþÅHßÉÀǪv绫x¸b‘Å?o‡çÖ”'×\ç?6ÆèÅ‘ýìЭé=÷ºÝUe§×Tvî¬ï}w^m4©av_|V‚ÈÅ"=àWè0Zq­Ò–¬Y ªe×ÜY§%Ù=à·ov[[ܪ¥ôG;2ás}9o"˜l«zéðÀbIDîaã£ëT1÷_¥Y×i .õݸU‘×JqÇ@fq‡ÕèÎÕ¼w(•¼ø?Ü!žñYÖ9Ý‚› z4ò[¸Cš§]Ñ2Aná½ð”ؾ…;œ z wœfN,6º‡Kçwh&zÂvdcÖ1wïûÎ.NÚ{¸Ã¹2 ‚vHVpXì×¾Ànýö¯RñoáŽzÖÔÞÀ³ÂÐÖç’g–Â-w¬è(î°PûÜaÇé„;¤eîÞ^ÑÌN:÷õ;ØŸ;0îpHÛá+’AÁìMO½HÜ0Š*éÔu|j ffŽ>ùÿdVFÓ`5гáí¥ÝW½0œ¨Ê›Aë–¦&frnm/º8=,6tÝÞ†tQ)zàÜ€C\{¯ãŒW&ÖƒÛî‚﫟o–êcgi¿³êãÖÖžÙÔˬĔ^°ç¹õ欃 å§×,¶\÷ýœCÇ=Ä”oR}2iël—•r÷I% U:’:U/»‹ëTì©âdb)¥F*ƒ•ð½SÁQ)‘ÒOvÝ[Ïõ›1ùpŽdÏo ÏǃÉýxª”JÑô;O ª´gaì*Y‘®ƒrg <@V±²o\ø·Sm‡u](g<˜ì~8Wâ<„ƒéR)ìÒl]ÙÅw»¦å»;ãѵ[ðæ€s•«`äZ”âàÏ+®Wq§³*( ÌKë8IÒêÉrªîÛuÛ3Úyä,^ç$;p.W¾‰—û@päµ»656ݾt^ ‹MÒ›¶Ý»RuÝË­tw¨0)îèðò-Ü!ÕQܱnžÒoá“iE£âØ-ñLð\wT<§Š«âŽDTr<á»%RĨiUÞô|¯¡ô÷pÇŠGÃ5Œw8¿§½‡3aoá½ÃNÝñÓ¤¢ûŒ¤GY,ªòØ’ÞâŸS)a®OM<5¿…;7N¸ã{”á­%gV™Åª Þžß⎽'qGÍëwv???_ÖÊÞsi—vÞ–è\%3rÊ]Ôn$+ÈsŸA¸ 5vz¶Øâs€Í ‰ÕÃr¦]ü«©"¥`€äùùùêzwè Ü¥øý ˜/èy08[²kvW…È î\Cå3¥ò­;™?7@H I3w¿KR‡ïíü€Ô ·ó¡ûïÀÀʒɆïÚdÅác+o[‘;«*\}«Ð'Ã/7w]ו?Ö›Æî¥•#ß_Ͷ:›åa³ÏÑÝõä°ñd¿W°ŠéL—Å Aˆ½&šVKZU_\ÖãGUOÿ~{Ð=¥?Š`Ì„ªÉzœ¨hlÄ´ÂdµµÆ…$»/ Øí:Ùµ1‰ª±¢…" õ,¨àG¥’-BœÖ´‰“¯çççËáì r‡M¥µXIïð¶ º†|®+Ö['›c€q@Ùk²äQ:© ¼&.û~”¥\Ù©ë ¦ÏsàÆkß~ê¬b=/·'윴ø¢ºgU´ì¬9ðlráõzÞ¹Ÿ=Kü-µ°Ðƒºœ÷Ù‹;<×»†}Î-rT*Ý¢›¸ÃŸ¿…;,x¸Þ‹;tG—¹QÜ1ª¢ ƒ¸Ãy-c‹ ·täSÁÆ{©·JçwŠ;L&-¸—ÀhDÚýWª_.)PâßÑÏÜâŽa<)˜9[œ*îp§þ({ÖoáŽN:«x•ó79¬@ñÀdJÜ¡›{Ûæ@q‡ Q·pGeË׸…;|ö2“¾‡;ÄÒe6¹wN׸p¤™™ù-K„K)`R\la¯z#§YÜÊh/½*¬íÅ•w¾…¾b›_‰a«8VÎößëÀHٙܫ]wË3îl‰ÔëЀ²²ˆò •Öpí°ïÐJ5 M¸V9S~Tj2³g6Ð# ®*P,<0k¸VEÑZ•êÛÂu »~\Ó¶su¯n¥zÏÅJóè};.žÌ­msbçÚyØû–.´½Õà¦ïCtU:S^¶Å‡í#’âÊŸ»¦='‡ìIIª¬"²³£Ê›€Ü½vZÓR(¥Õ4Ò™ªvË»®œ¯ûÑ=®4l»¼òÑMR<ŒŒ§Î7)ŒÒ©àM®· Çý©×Í ilÊüJ}°ƒp‰KÆ`}4Ý;Xe¯Iç/ö¬íöï`|||¼úîúY]ò¿bÃü,œuÚ»m¿ MVÝ·¿MNݳv„&Ðј^JM=2ìFJ³³K,­PÑ••{Ž)?ÜÂÖÒ€dÍ3+»êœ’ɺ`VK©Óvß|f•B>uÝ<ó•PÞ<ˆ3TÒƒkb}Â5³5ÎÙ)*î°»¿Ñ‚åÖáÎ ÅìÀw8ÿåË—+ªÒÖÖiÖÈ.äöC•ôŠ;T±íšnG£ÎÊŠ£]lŠ;z w(Íìðzq‡‡Q÷E)î0i>) ê›¨ïWqG Ï}&â×¶÷) ß³†*îØ^Ü}w( Óäµ…ŠvGè\٠λkƒà:ÛZ×­s^[ÛKèÖmîøí·ß^áŽÎ®ï^®’yœ§6£üWåY=थ˜Ù Býo+MJ.Zµ(¥åDýXàìÁáÐQ2+WÙjG%M—(,rh®`f _ -Àíz]šåzu—µm©/HÛµ­NÊ‘hÉÚiȳó3Û„rŒå[ ¨L¶`­šŒ ‚ ÿf ê•`ð<É^ž¨(Î,TÉG§æñÞ¥ì®D;ÈÎuÖv¸‡Tr5+ÝÄ®•ÏÖ †6ÛÑÔEÉÚu`š(È=— ú×Ö‚‰ƒb'oŽ}ÿ@JÐÖ´ráÛ«:uþÆÄ²Ô» ]ó]H~ùòåêXÒÞ!öΦÔoÊLMÎ<ÌëóÒã”9MgÔÛ‡ÞãÖ¤Fd‚îÒR•Re’`R)o“üÅW%ûoIè[Yèšøîþö¬=üÌv‚}víÞ–¿]“E 2…«Øƒ{×î̆ùw/www*s;® }-F{T®·Ò·J殊=λg¥b7îSÏ%i€+²Týʳ¿4ßîp=(êcB¥ÒY» û{‹š*? wXHwœÄ^Ä&„,)©ï˜×q wì>ì¬kÄüî°[kÒPÙíÅj½îh‡»¸Ãù¿·p‡±êùùùòlÄ®“îÐßèîØºX2ðûï¿ß=??_utK=­¯Õ-ܱïtöæTôøî° y wlÖÈ¡ÝCŸ·qǸ»w)m×™1 âÏHg$››wÔ,­bAU¯Ns7¾[éh[¶ï·Nt°[°=´5¾óÆ9;þîyUd×§&¾âŽůs¤bèÖtq‡êQ®7gÍvÍ3r< 9KZÜásvÒþT^¬tŸKwìý w(øâ}lOŒ!âì×ÞÓ°“J’MÔ':˰8_ܱç<™p“îX|6–í|VÍNÜ¡úâ w¨Xh­ú•ïkÝ49uŽ»xP…_×ȨyâŽá›zµˆ;d.íþFƒ{ w8#-}P|>êäX+­»g?¿¸C–I£¸C!qGHkÀyÂõ9| wHïm‘äjff‡Û€ÁÓªL$—Nu‰Jä:ûQy?Û[—!Éß~ûíîééé²[:q7Œ'swò…±KäŒÕšm¶-jMŒì:YÉ\»LÞ§½ T‡}Çiˆ\jÁæØ AµÏÖꈺãrfW™ÔKe­l+x‡Ïä׫üùÂv¾'„œXÏ\C»÷š35ð[5y||¼ÈÊnÊ™ÝÑÈga2Þ!?+UO¥p=\LVvÈm}© ´CÅ©®ãV3öûzsŒ¶"ÐU©­Í}UFs´º­Y×Ï>o×ëwÙõ1˜nÝïóv „vÎ\Ïîa)Jdj¼'Äß³šê\‘U* øÎáé²-}Pð¶§³²TÀ7A®«¨§¡ûñê=Ðw=¼VZYú£›vXTOÒ§ÊAxñ׊„Ý«•?ÍX÷¾Úùٵ؉Ä Tº^<¸Û xyy¹ûïÿþïË~\,¯B×äÇÇÇW œt¥Rkõ[Ó÷fó`•³WaÍ®°fŽV¥,·ÐrªHŸdªµYò¿»?i0UÀ³ha—ÆÙN}ªFumw,ݳU ´‚B'ÜáZâÚpÃp‡TÍ‚& a‹;”(® ¦±ùî°peçxk¾f×últ0ÚWÚÕö”±[ÖIMqÇöÅön÷”tM÷t¡Å:eãõžÁ·p‡ÏÇ?«Ñ²¸CË“\M§oá [›Å–™ñ^?}útÁ=oáŽÅ@i‹Æ±tç*}GªÈîwTû-ÜqkÖ¸J‡§b†¸Ã=Uf’ÏskºB8£>‹35 ~%ͼj‰­ÝAing€< Ja²¢·V gf‘'éÀ¶S­N8 (½fAr`ªßh:ÉÊWg[€,ø±ÅïÁTå Í5õ¡¨qUDœù©v¼4»*Ú8£äŸ C3Î ÛîDuxUÅ™ [”vúl›[ 3XiÄfR0ðá¦õú+iº@ÙvõÖÜÉKÈJßIEÚ•Ý =+:" ÐäÐÎÍÄ%¶†X;ô*µjkZp»bƒ´šÍÕ½&o•sµ Aã’>=\VuW2´Ê8Æåj ÚuWo2áó³¥¾x²wlg£ÃÝVѨDª3`îß¶ÍOh»îË­÷e»àK…}=LÔåïïWw=K/ÑônkÓe᪳7JëK§²ã°µ`"ïá'EK‘†“©æñ%HVƒí䮨¶}§ê¢E•–|ßKXž+îoi!.æIQªˆçY©[Î])²k2Y’ã~í|™s@5lçakÚÏRñNÏ M íÚ8ßTxÏJÍ*MD4 #þ îpvÐ8¡ò•rÕÊn;ÿuÂ&`‹÷÷÷—©?Òλ@Ç0Ùp®ñ„;ìÜVõÍØmÑÂØ]Üa‡¾RÈ·pGMBO¸Ãι6‚\«S‡È9V‹OΫŠ;B8á ¢'ÜáswT±®¸CJà wÈ ² ôîØŸ)D¤¸ƒsìÆç2Ï”ã/î¨@ʼ‚6ó´wwÂ2–¤Ú–様Ë÷p‡xkçÉ¿ÿýï×jfRB–¹ïTçû'¸•â`¥À6ç6be«S®V¿\A“ )h¶ª¤zu·Õu©ÖêŒÊ)WÉÅ$¤þVO¬ØŸÌÌ\Tû êòë3ª–¾²Ð5TÒXí?þ¸’aµúãûïæsóvþ¡’°:.À\Ô‚»®ã¿Úâ6`úŒ½žVº=4w˜¨ø"׺|j¹Î)[¥ÈÀPÊA¤^«„tR C˜®e½,œ‰å¢{Tî:ƒ¶Ør®¼b„•ÊÊ©–¿-=´•DûÇV~«Ü´oïºLV´›4xmšú¼³ÝÏòî­$ûªÒM®¤™ŒH‹s JØž«"‘IQØÝUc²3U¯¬‘¬þ-ÙàX²«^åÁRýVý\ÂÐw! Ѫ¬òÚUÊ2Á±;îP¼2ü«2:ÏÑ5íù¨W…ëA ²µ¢*ÛÀ«†°­¢WÜ¡É~‡¢û\}ßõ›é<àßÁiMNí¦õÌnÒWmwUÜÑ*t]î}Þ[+'Üá¹Õgã Ko*H½…;<;K¡µ+=þ„;*Öbb^ë÷ kµsƒíµ+v wøÜÅ' ¯Ó¼E©îX¥]o0ô~)Æ)î06¾…;œ9.½·fÎïÁ&Ó¥’—rÛ.wqÇi¶ÜY¹ZnˆMʰè`|<áY8⎿찺Ÿ[üÜ{›@ŽÏ«¸cñb÷ù^ÜQ£ÖWÉŒ<âÒ¨TU²a›­C‡åŽvØY7éúÎ,p›IîÏÌ÷"*§èñª;ÊnuÎ6­ô“Jž@„T¯-Kýl ìsêU#U¨qþT¹n2«²¡éávÖöž±‚þ§§§«"aEe,d.ž;À\Ü!…qûÍ$IÜQ¥³ú²¨Xyª¿y]ûóá»øÎQì™(×þÜa2uÂÒ¦-^zïÞô[©`É °Æ’ÿ ÜQA¡b —b•]‡¹¸CZrc´Ž®ùî°Û¬=Ç wlÞ§¸Ãx$EÐý¤JY)â"hÁÒ¢Ø÷pGÅj¤¬¸CvÕp‡£!&­»fÏÓ“GMG8Ä&Òw<)öî¿} w¼’fö‚4tÖƒÄJ¼T$³¿êÏ ÔüœÎUƒ²Ý¾ûüü|5°l;P ¿ùˆÊ!ïZÊtÀ®ŠB55¸Ö¨NÐ3*ÎÇü|i v[ 5t“Sì—«¬‘V)$ã¾;ëäÆª¯‹ms4}®û]¥ƒÌ[ðèÂõÞ”ôs]¹)m]V®UX…)G¥54(v3¬T÷ÙØ‰ˆ²²ÖÊ‹üO«åjV Ïûß¿ë©$·ŠIVx6‹¢«·• ƒšUüÓ¸ŸÙÞú÷¿ÿ}÷éÓ§«ŠœîÂRˆìÞôZÛØŠ¶•ßÍ2x¿®½ËÛÆ‹ú¿ÛÔϯw‚×nòi)«i]MÚ¤%xXÖÈÔ$E…='¥ÅxÏÑž’e;WõHuÈâÏֈł ôúì¤Àmß:´¯ô½sV&dƒlÖ‡¦ê{‹ƒ&oºqëµbçS %-¢ëb÷î;ÍpûOI[ÝÔO®ëû~ߣrã¡4¼Ò¥G£ÛóÝþr¡ô!ÿ>‡v­¼¶8¨GSçYNCÜ'Ü¡%„à¦â±Éâñ֔Ɵþ½UqùüJùp‡ÔÕâŽRÄ=Ç,JŠ;ÊÅÎ:J-´èpÂî­áÏTiËc亸ë IDATÊìñž+–P wì»¶¦¾'ܱûrV¬¸ã4ˆ.î8/ßÂØšw¨\ùîpÝž¹Øæ>îPlf{pűA¿…;&‘]ÜQeÎz9wØ=«ÒšÌî¿yþéßã;ÜuüñÇw¿üòËeÍ]%3V¢ÌÊšåU}HE/AŠtfåm‡vcÕ ƒú][HíŒX]êLK]·­¦º·Ñíª´#mgâ>c¶Þ³œÇ&+V"VU¶Ë`¶ý\C=ÛÙ¶R] €> þ*¶å­ [‰\µÍ +øª|£ Ó~wÏD0iªI°íOƒª]£“toe?MläÏWNÓö~[ÈRrì(8$¹Ï·Ã±¡b‡¯½žv8Ñ)-JjAÀ%ikìT1«Ò•~3¶£·&`ìè¬$ëuá»`ÚѱÓãÌ„`² £4Õ­¯]Cgë?û;V­þ·cPgkeR­\µHÓ®“G‚òœ¥1yÐÖË@Ú™q¤Å»EÒWì´ùN¥’¸Ï«(9"0F8›¤ºeiº>«v=7ø9›Sš¦Ì·æ•¶Š*Cu$ãEUšÚp»¯=¿\ËÆ ¹ §s!&>C“3;>RÃL¬j.k…ß½ê¹âÜËi¾Jß5òî0õYUE¬àèî¨H‰t[³3kµ:áŽv¯Ng­¸C-Ae÷Dý’öÝ ±œp‡ûRܱëÙ™`òk÷¼¨ ê wHOïÌ‹ïØ˜"K£É•ßY · Ö-Üá¹*¾)¾:áŽÒ 3ò9uM×|¶¶ >¶žp‡˜¼¸Cñ%ES†;ÄŠgüÜÑÎiãR‹k'ÜqzFwhîüÊgÆ,W©JÿÜö»­ÁºO[±¸DnQMNövÑ™a›½:üéFÓ8È@½‡fv¯Ìž-¼U—Ê«WÅB•¿ßfeôTå; <Ûu0ð{Ò\LVz:\L ÐV“táµÍ(Ýɶ¥|ê-F¶U…ýë_éìp[å±jl[Ýĵ³<º%K£ðð´*èûQÔ5\n¶‡‹kÖÎÅɴ͵m2Sï‡Ã5¢•{._݃¡ÎÛØÍÎtF¥•l+4RM¼A™ Ö÷c²Ó9;+úî—rg_vu·7¹°*½5-QÀ§"ŠU®%gv¶vÈ“¶‚6-/=ev šc–þ$å©B3«Ùš Ç5m<2†îZD¤™lJEi7¾g]°­Ðyε"íù¡rО‰]ÉÎ%ZIÔǨÊÆ‚Å[ŒèŒ‘ëý¬R#×ôó³vîH³œï¼éLCµ®×Ul'z#0Ћ¨¶‹o£%Ùm¬ëQo²Äë®ûás·‹û=ÜQ!Ïk)µõƒi‡®s€5¬Ÿ³ª·wH÷÷´2wŒúÓ™e·L¶o­éâ×êiœà{¸£Ôt×c½ª¼÷ïá;ª­ù.T*\qD6ã'ÜáüÅhg^‹CìvÃoáŽÎƒî}wô]m¿V[Üáø†I[KZ/ƒAÙb‹‹ÙõžC õ‡²¨WãzãÔhbâöSÁýv w´CYßW¦™™Õr6à–«[Wx7cÕ,:D+]¡#/tºü¿U Æ—ŸgZª˜‹[>ž•Œ=pµ­«U?ÊÀ6QlgO¬ÚîVäçï°ö—xm“ÉËßçoS[m[T´ƒÙr5URÚuJ÷(z@*OXz¡Cׄ•_ŸCNUïSšŽÙ¦Þ³6éh·K®s®÷²ïµ*íóõ«yjƒÒ@œŠ0»¾še• kû~Àeû +f~–³[9Y2µõg÷B`³ÿµ2¶µ¡Ä¥R¡Vþö^l“—j¥‰í¨gú?ì™»†ë eÑñ“é¤4¥J%×,ÏCÎCÀë–R#˜Øs¹¿¿eºk5TGíV|·'‘*@è>61@¨æå?2^¯Y°Å»UÓ4»«i§`ÎN•ø­ÅÅ5 +>O¬êÝ[eŒl>~üx÷ñãÇ˳2ñ4f3ùqøØnugvTÖ$®Õº/©sF¦I•g°1DÓÓ*vJ£­¹ ÔU¥”î9OuÑÏXb¿÷àØÎçÖô_ÁLÙ3w¸÷¥‰+K/ˆsfï=¸£EÔ&óÅ*É.¾-ìÌÇ[¸ÃsjëY ‚âÍ8Uß,îKTENùå[¸ÃάÀ¿‚R¥1yÆvoU)Ôq÷°Y{·p‡3Q§ÙAÍ.oáŽvÝŠ;öÜÛ‘2ù0ØÙ+î0iúî(#Çç^‘Sê)©'רþÏÙΩÛS ïHW=áŽ]ß%™ùŸÿùŸË…ÔôLº™ÌÎNHýqÑשۀUñ“âD_”•± g}úôéÂ4èɹ[ «Ú´Ç;Ÿa‹y‹fKîè²N=CVý´EVÀ6>uA¸©[J†¶R鋸XyrîÆWçP¦(¢N½jmŸzþ”½ëÜ!Ó™³t‘û~ öã—/X™¸™@Ù%ðÀhWÌŠŸƒ ô;ØN]DŸWÇÉ­þÖš¶³ ½g(xÒ“D@³C]>|Üm»Ûs¾atXºXåÙ=,Æÿp›ü 8t–hEJO[Ái¥O ×údgáeÕàJÎ Ê·ÎìúÈ÷ï3k|•Ÿlg@Þ±IŠrâ[ß{ÏíðîYº/\oŽ÷Úð;L¯ØBåÏR \Ëv_vÏÎéIÑèP½€Í$Ôî·Ï×·Áu´NÄ tvíõ YLÛï·‹jRºxT¡ ACãpi ­tÛÉ>%ÿ¥¨ÙõQÄÂÄe{Û5½ïØŸkf(}¥V vúì ì™+.°wbð¤8jñRÜ¡šžÅ†ÅAýZJ/>ᎊ“¸®­v7F»¦G•î°Sl‡ÁþIvŒoᆷp‡‘í™Å4Ïñš¸£ÒîïÁíòZ½·â^ËŽÎm‰yÄ 縿í¼ËÐù³¸C:–÷ÜίXt"ù+>Té~±ô-ܱX²û½…;N”k×´´¯¿‚;,ÒÍwÉ¢IüðjqÇæ ¾‡;KÐ(u÷¾DLŠ™ý åè£óã?¾ö™ñ%-HiòT)Uõô»Ø<ܤU¨xSðÓÿ9èé?VÒ=p=•UÖwÁJz³çÊéÙ>>µ`MD\ å7šiûül9ZÁ©7ÙùïVJ­úoxxY…iõÛ÷;™f^%¡fía%0Õ¸‡ðTz¬>ï}thß¡8i 'Š—Õ?ÍH;ˆW +;n© J:s°@o«Ônc+¶POšú=œ·¾TÆ«¤UÛòl¥&8ðêi9Ý•Œ®ª‰•aA€ïªJvv=Tóàp/ª04º±¨T5ƒŸTI×ugîü~㢠ß9…vœ×^·¢>Ï @i£R¥ãH[06j0×j¦·V&=L·<$U‡Q¶Óëì¼`«û®iãjãLg9Ù£GIc¶3^p`²dl©áf;å‚rga*ƒ]xApý‰|WÒÉ”ö¯)©ÿΤÂ}£ZÝI’ÞÁ®Ú‰«¯WiÊ* -ñ¶ ô»ÌÊ?;Äß3ÅÂa“–­[À(îsØwîÉ}SŠî÷pGAôÉ;KܱŸ¼U.¾ó$v*T -î01æ½wø¿RÅWÅ¥dv6£ñÞký³¸Ãï·µì:.î8á¥zW£õŠ:Q`•–ÑRÜ¡2¬OŸ©1Ú5'îPr¼]pG$þ î踂ïÃ{i‡ïI9ïv®‹;dxmv{vÚÙê<û‘f6WôúT?Û@R÷í]€ªg{!'U§V‹¾mXiGVòìŽxè*騹j {0Võjg@IÝÒ~¤ÎxØÈ;>yŸøb­4íϧCÅõÛzžp‡.…HÆp_+Žá¹ÐB—Iªg˜öÛCÅîíâŽÍ&–RlòТP O퀺‡«¤¦du½¥*W¼@Üq’fn×¢4[×Äbó-ÜQዟïÁzêˆ'Š;,íçLìþ*²ûNšÅOEœ,¼êÌè[ÐaG3ñq/Ä2úôéò>}útupî&×^rs´¢¤IX]`˵tS5S߃ž¯ÉŒÐ*[ꀗ/Ø*¦Õ¼eßÏÏÏ—àp¢~"Þ‹@Æ€å`Ò€ºRAÇlY)Pƒ})fŠHØ!×D®Ãg'ÉÓn*,J«5¤³ú­„¢óª‹œ†ì*ÜÊû'=‹TKZ°­àáááòœ4ÈXAi…̓¼ÞEVQ•?¬šÞöâ(KD¦¬iV nMŒ÷þ-BÈýõ×__Ñ?¶îëc¢ü°Þ _º¦ë›³¤ÆŽçöÖ¾k1G>±åñðM:TóQ:³kµCÂ%8 À¶bìgy×*ÕëÈ´ëïìõHƒ“汃}ï°I·ôÌoß¾Ýýýᅳ PºÝ*ôi®ÑÍ÷ªÒÓþûùùùè¢do÷êï¿ÿ~éÒøÚÑ:ɉ.¾é²såóçϯh%z/”BÚ=õ·¿ýíŠf¶ç£¯ˆ€g{³órôàqŽ:Z c*=_êIçgÚ®2¨óhíöm¯{Æì³„Fñs?Ÿ|ƒ¯oᎭéâŽÅÿÇÇÇË÷Ë/¿\i:¹w´Ó(ÕÎîLJޟ親{mÎbñE#ÆâŽ*˜9¤¿øæsÞy±‚§Aæ{¶Ý®éSO³Е^àªÏ®O¶†hÕ=;f2Üâ±\ì'mKÃ_qÇÖy•0Os³%Ä¡]Ç•F>áŽu8ìH¶£õË/¿Ü½¼¼ÜÝßß_ÍS®È¡™kú-ÜaŒ®!åbþŸÅ@*&!nwMkc²÷4¦Éüq÷믿^ÅὋQ{nWÉŒjX.Užö WAµ`ÅÀP«,ÝËÿ]…È §DÍ÷<¼¿}ûvw¥,Ñ ™ «Æ‚c[Ï”V9L²C•eäÉý–¢›­òÄ]„fÜ‚³úåhi ]ð¶Ê†AªÕ°ÿú¯ÿº ’kT¥rÐæ#:Pí!ëa°Ã§UõÖ;ˆ/È> B«Vã ´<ËU–CöfðyzzzU‰Û;*MªÀbëʪ°…<@?ÇCÄê±&b¥¦XAàw¸÷4_aàÕeYÏ!÷ÚÖ‰tØMέz9¨[õ¾Vi+ÿº€¹áÂ*J²BX?!»ëÞÈÅýöíÛ îçV‘v¤Ú4Î8{åUéꪆ äu,ïwm]m¿¯Âh÷b³yõÀ8Q»¤¼¸JÛ¸uÈKï˜ø¼;9I¡J‘•*'M¦ X³Üv¤êP_yáQþ*ò  µ^#{&+Ò©xÖîl%ÒÝÿ2šT¾Ôøm§ÊÎ_}¦¶V­®¿Ô;×ú¨4ã=fð­ÈÏÖ¶ëÅ=µûß>1ž¿…;6kòÜa³„v ¸Ã{*î0~ÙYYÂïÀ¶ñÔµ¨$üÖÒÉ̸¢7 õØi·tëü-ÜáŒTÙ%íü»‡‹;<{VŒ:áÏô÷âŽÍv¹îì®Ö©^ ýgqÇb’C÷wˆÅJÅ&T?üðÃw˜¬)OÝ„…øÿw(6b×SÕ̶,øÝÂõ¿²8(ÎÏÜ;7Y7Úlj àâŽÝÓ+53Û'‰¶½õ¦­Ø˜ñÕ\ÓÖk¼ B¼fß)érÝh7Ùµ­&Ðë[9µURØæÔÛ¶«Ô*‡åõÏQ‘¢üýúñؾSÅ–gÛšÊÌÖIQc¢ .ØmØg¬Ònu§Ã¨‚gé"{ÎJNô¯6{–ô¥gµª¾@¸*™€¦3ÄåsZÅ3°[‰ö0¬R›‡½UT×ôZìo™kµjT€& k·‚\Û¾'»‚÷Kç’NÔ“‚“U#;׺t^$Æ‹zŸèÂÞ©š´ÐÕœRþ·à¤-~édÎ0 nÛº×ûÂ=´k—¾sRŒ«)]‹ªØ8S¤ÑâIÙe׸.S•ôT,ù¬á`•ÔLt-ø.,¶hÜæš¨q Ú}Ð{PJZ‰ä 范g¡UÞ©µ{†RM÷ó&JûN=H:+ØÎ¥E!ÝÔ›”·[ѹçßTÐÈÛº»¿¿%×j̵´û½…; ÞTìŒ{q‡˜ÆBIé“Åis=´šýŸà¾»»»«¤`qc‰TçûÞƒ;:j'ÕßÝZl ÿîp®P:ú®a…m³Ýæ[¸£,ÕHoᎽGVÁ±Ïâ„;üwïU…Ý·pGßKçsÜ÷wÈ8y3yÆÙå–¡á~©ïYÅŠ;|—¥ÿ_àqT½Æ<¥¿JfÖò*ïq‹¡Nöó "»Á=ÐÃ>\9<”Ô«$±IN¤ÚZwú`kTÕ o/ßß·¼ßuXu>µòê­[šÂ‘ºt+,;A‹y]ô\ܹ+ºfÝ J'õAî*À/µ•²Ý¯•·¼Ìí ¯²•ºòþþ—/_.kg?SqÁj•dÚ6÷ÙïZW…„´Z¨4òþû˜N¼Ú²{·5-5ÐzÐYÁÛ¿o=€­Ô”šf…ÓóX¼=òt]g:“[]WvÙ¢ŠÆd¼[ÞiinA¶öë¾äÞ µ2ºîÉu2¥]˜´Hi“ 9u¡ÎvxR ý?,‚H *È0VêÓî´ÝÌUõJ·sá!¦Cã´3!]ÏÎ*ÕÏ s%Þ_»·ëºIé|T‡QMJ••·nÒ³ç_• Ò¢”ˆ6©19°ºÝsaëÙa‹)‚â­Ý9½ÛµB­üÉŒS™_«´ªâÕx´Vž—‚s«ÂJÛ>??_Ñ|jö¨ ùŸÁoÏLú„;Ü[ êŸpG<«üöîp˜Ú®¢t²]ƒ¸cßßnwý뤳pÇ’ãí™ïá ÅíŸÄkn᎚›*4õÜ!vº¥2j¡ð„;:˜ß­î°HÔy¤áŽÑǺ>Š;Ê€Puì-Ü¡âbÙ"ÅMïwÔœ¶2ævKí¶8GóÜ¡Iòº‚·p‡¬$çÁ<óœWzE3Óc¤í¤—xs3êŸoLWÞ àƒè`Ÿj)U%i5O ±—¾Mª?‡ÕÞ·=8…•_d+Æ À?::Ýá§ý·–{†{1k¥K%pÑŽª·ŸÑ M㿪ÝlQHù{xx¸š³X%t``mßqÛåÊäµú¥rYU\œ0ø;&èW‰¦T×Ýžýóóóå}ïyŒ:3ŠHUúÚ Y Ñ%×6±³KÒ{êû!ßJe“ŠqŠ-$ø]Îaõ=ôÙ;¬W~øÖ2â˜Ö¬¯"«‹£r,ð*‰,À›„£Áªàj×äZª%5p-ÝÃjä‚z½œьҵgÕÞÀ>£·í­ªÏIu)·º•Ô­74 4 Üý+9Ýê³]ÈÊKisÍÔ9}¯Þ£‡J%J½Z·¬ÀÙ÷ª€Šƒ“ì´¢Ò”âRÅTô“ÚWq]ÐågŸ@Ëž—‰Ê貚6ÞYÞ:’¦i‡B0´wýüü|%\ÑB’ê\v6ü~‹i5’´òêð°—®•ªÏ©2·ky~~¾ì/Õí( lMv÷ þ,î°(c²=ÜaY™Þg‹[g;¤é›œ(B`òðî(vy~~¾JtMÖœë•ÆþîØ5Éhwìs6?ñWq‡t(U@oáŽ}×fäÞÂΨp‡ê²6ÞÂÚV7ì¨ 7w<==]æH·f—Õˆú„;,†‹µ‘-Q††IÍ whâì:Ô«jň60,Ð.FW^ý=¸Ã„d;*ËÂÒ;S~øá‡ëdF¯«HõhÙ‹u–ÏÛ@æ`¶Eå#/ºµV5äÖ;åá·E2€d6©ËñÀAw͌ݤ:Ö·âTó¤¶\­ðKY1c.ͦê1“Çt˜_myßLÛÙØ{Øg.Pó´½}v¹LH*hõÆ6¤ÄʯÜúÎ}Xið^ Ìê1±@ýüü|B­ÚÈżàÙ~^¦$b9Å‚DÛª ¤Ò£¬p/¹ÚÜZ[ü›Ùúç?ÿyU,ÐGgÁÞŠèéé®b:lܬ؛Ü/0+éÝ.“8î¯íÕQXnpÍ}oVõê53°àlž‰–ª5uÇ®T¬€ÝC΢ŽsH'cEßÑ‚½jPÆ•h·²)5ÈJßóbßâž ?‚@ΤIê¤kZ“\Áã@›B1ÿóŸÿ¼†R’ö9[Ó‹&R‚¥j2,¸©ó·ïJº¥s/RqŒµÛ—‚×Tç5Zô+½Å7ˆÒ¦í¼ 4õîòš­ðº¦+¹Ý®ûD LpU´«¥ÀÞÓÖÐׯ_/¢B?•ö|øp÷믿^u#ëß·8çz’ýÞº=á;â»§üãw?Àîïï¯*ÀrÑ[]ÐÚ¡ÌšÜh dë¬Úø T'5›S€±Âî!ÞaâfëRç¬BŒæ²kÓ…ÝÊd+¢5¶Ûçd œ¶-=šù—j¢œ¦`à¤'nÕr×8ïuÁýIT%‹M›Äíï§㽟 SíÚTÅåä`K¾îÎúŽ|WM²º0jœ¦Šš%ZkeÊ\½‡š@*gêáîg øì6Öõ×yAAgAŠòãmõ[u©¿ˆs ò¥]¾#׉ÎÑø5÷êý ø ìíü8ÿ ½«³Þ[UVì¨5©“åÜœÕ?·\Á@ß»¤ÜyŸµ‰â ÒøLlÊÍW1Ι»B[/K–ŒóVt·6ë+d÷´Ê†!Ÿ$žM4¤á:bjI×ö¬1D³¹Î[ X¬û³wç3óZËïµY}>­û®aÁƒÏØ"Ÿ ¯¦{•bV)­çÄIFÛ÷o"Sºv)JMÚœ‘bRU4¯³ó‚-$y¨þ×sIpäZó:LÞö|*uÞ½$ §ó·p‡ïø„;L줜p‡JžÎÀˆ;ÖÅÎø­ÛQÿ¼âµ`ïLmÏüš8úŽËÖØ5®“é<œfÖž'ïS~îØúw´ˆè agMô˜q Çd|,NO”ª¸cɹ¸ÒŠk§*^zðصPYNIä[¸Ã³²T~qÇIÔÄâÓ-ûáiU/;ï%m²JxÆÅ¿®$éיё{íu«Ï ¾r¨–‹j_êp˜ƒ‚õ4Ùg(›ÜêtéB«Ø>>>^ZÍVç®”^ä½ fvRÛ¬ªº¹dn`ºª­” nÚþ`LZRIê.f5Á­0O–Zn£´”QÞV)ì°›ÁÙ5²w©‚+7UzY‡aÏ{I É®ôµ}¯‡²UWŸWé$üñÇÝãããÍÃ*a9ÎL·34š‰<öuÖ%kwmöôôt÷øøxyÎ?šÜô]›Vw¿[ûJÅ–_?Aòç $>==½š ± !°]ÍĽh%Ý¥•Ljra©AÒ ¤#ØÁØáÕjÕÉîy;¯V wÈ,îZW1÷`°¨á.ȶbk—˵$sÝJuÓ‡Dߪ‡‡‡+ZÐ:…ÒN\_R;Ð///Góüü|÷éÓ§WÆ‚&¡ªS.ÎXÉÔGa˜‡úžùÃÃÃ%í$v<\û{Îh <Õ”âfü[åPÏ";v¹¬*oí9Üßß_(›?Ú5Èf°ëTß1¯ƒË[‹&³ž¾?«ÃS‚ÒçKJ¨øvj<“¥²ÓY&»}ÒXŒpÚ¹…;¶¦•y.îp.ËØãìžÅ.cå whá™Pܱõ;YèQþvÿ_¿~½œ9*hU"_£]Ï¡âét®ÝN¸£Î󊘈žp‡s¨RU÷³sRÜqêd›ÐwXm¯!éÖÈö˜¸CÕ®àjò¹ëwx9ühÒVªòöd‹ØÅµ<Õ…¸£â£ö‰ƒ¿|ùråÕ#Ëd¤¸cÏ\Šh› žCv&•“î^;A°ØcÑ×bÑbïöOÍ:Ń»&gl×™¹$3uÄ,Ø{1òÊ+/lr ®øÉS Þ.ò«_¯r…™z«6*+i‚é—ÕI*4‘ÚÆ]Ðm°ÞÏÛùY°±ÒXÊÖÀÇîi{@üáááªÚ䮦Q j;T«”R«t{ŸõÞ°ófa•«îîHªGÕõw—‚4‹;àö  ¶'voV±]‘o IDAT¼) ¥¬Éóí­1kyÕ§nƒôÂUšªÁïÞöÇöS•p:Ô½äééé õÊ«H‡FwîËúvíÐvö«t!©:­Ì•þàs”Îæ ª¢¥ :`l%P¯$ @ŠXDÑcjqJ©ÏýokÚSýŠÜ»uy·x%õÓnŠ²Òºö>•óVÀ‚_圷îU7Ó‰¼…8%ÎÝ îL¨·^^^®æ«6¨¢™ïƹ ®éíÇûûûW¦¥ LV—L¸÷Š;4,¯ßd`@êÏàŽJnìþŒµWA‹žÏwHµq îž·ç”v¯²¤]›ÑÄÞ‹;š žpÇ’ÆâŽª•éç#¸.>8ág©Êb™/UE˜*вýªMƒ šâU붤DJ®çÍ wX°X1ÅX{Â+Ö›¤Öt;öâ ¹ŽØuÓü½¸£6%-ò÷,Ùþw=;»¹wñüü|÷ððpõ®Œ7'ܱbÑ+iæe¼ lëfHèYÙ°ýlõÖzòŠp(I`6p=Uˆ-$+e•¢ÝÃqÕ¦#§½-}Õ/l3ëGS)é,~`¥ýªù,äÁ[°ZXCÐm7† ß…ÿ3(ª`åïXÍêÀš‹¸ÃŸ‚%L·Iöù*ßggkÓµXù]9ïJ§î0¶‚á†ÚV«½Sb¥> Ð:P\ß[Ðû©U;’&ÑJÕI¥MJRÜ«bÕõPCµçOÊo•CogÄlÅ}þ|çD&}®I¦{ik}ñÉJ¦JU'L¹¶‹yõn*õ¯J}v0¤+˜èûŽl¥·+T`§­³îºr \jN(ßʽ±­ÏØ¡LŸ¡ÏÆŠ«^YV/§› fø,Ž™žMãÉI´Æ…V¬÷î€K÷s¯’k‡[oŸŠ•,®=>>^’ÓRWÖá´»ÚpgDª*ç½âY¥·Ot2·nåÎÖIñ¸µ¦±•Âç9jGÌy¢âu“N\+œTÄÄŸ5¶uM…U…|ÄŠÔX‘î=™.JÙk1@ªmUþœÝy wœæˆ«q½>)þ'ܱõä=š¼,ñîý­ã¿¤F:¹žR'ÚáŸÅeÁ”Úè¾wx^‹:ÿsK!΂œ÷hÌ)îp|ëIÿqÇÎ3qG)žÅµì0™”²wÂb“ p‡Â2M¿‡;Cùîè\¼¢RV+r²wx•ÌHsÎ ¶›([e¨‚|CùåÍpœ{ùŸ'Ia7oE ¬ª :N¹žVFåGú9'éV¯ÓàÔd¨ƒ¹ë0¨¬²àÒCÃCÍÃÒÃw0»1«ÊVËݫİ”§=‹“z™•<+1*æ´‚'@TaÎgR¯ÞÕƒoE¾JQ@“X)p&¾KÀšŒ«fVo ÿ[êÉXO®}‡ß«Š& ¬@S` éV Ó¼ï-Wn¶«ŸºH{À˜@ij+ÙYµøýl÷•«—öÎö)®a…ËÛy»“ᦳ\v:ÏàŸYámaåD7Ý5WzT™\A˜ÃÓÆL ýZ‰í Tïoûª‰kºà¸ÃÝž•K/ï¹­gÖ¸"•¦ÔŒ®É®iŸ»ç„¾3§E ‰yÍiMv¯»?*Ïv\GQ3‰.Àõ™Uºòµ~ú¡2ÿŸ*5ëšö\4yW(ÇN”ûÇ‹vÏMÐN ’g°3ÀïÁî½v¤‹;NEÚ3£½& R¡O¸£ÔÔ[¸Cºi½ò{Ð5¹iðtે“vòpèLš••ªf¡¶{hs±Öd®:÷ûìeíÛ¼uúm¸ªõ_‡äJ+ózv-±:¤êÜŠIW@­6yVå©võs°Í+uGµ¬´“‡MÏQöTϲZ$/Ü.Á:3 K0½®ÝÃÖ´¦XUN)uÅÀ}à†wQꤕÓ*Q5QñÀtMøÒ L(¤¤‡XE²RÖÄÃ÷ë|ŒókUïQ\¤ Î]I)òyTH óç:T\#U)ý~ŸeAi¦U RYpkk`RŸ†*?Ú𘘇?¯çŽ"vjGÐÏFWl+sIŸ:°R,¬Œ¶Kã<ÏÐØî^»bu”?U~÷ô8pèÖ$fŽ \ö>4"u­˜˜Ú絯¨ÑÉ#Í9HiÛ呯»cáÀ³³´SŸ™CÅe6Ç1©ÿ–ƒéÛ»S½TùȽáPø ¡ª4M8æ„;ÅûþâçD¥?•"îp=ŸpG;¿ tüÿÀzÑTôÆçíyÖÙ‘áÕüœËépþÃÃÃUQÄ¢Ê wX¼w˜‰;¤,wX$9á»™ßÃí¾XP¥Oÿ=ÜaÑß5m÷këa³R‹WK0oáÅíÚŸp‡ q‡xD›ˆ÷â (½ïÈì)b"-M©áŽ*Õ©fvE3“/\žw)V>¨]Ð$×43ØôçЧàt  Ö53”wí M«Ý%¹8<¸6lùÉc4 ÜèÏíŸ×U^yMϼ6— ®*Áüùóç« c<µä<ØÇ=V嫆[¾_­¼T¹]4+áåUJÁZõʪùîÝaÅ%p@°ó gݨjúŸh\'…ÐõëãP§fjÎÅ”Fã5¶sb è\ÍÔÙ¤ö”ºU m(gÚøôÝî;êUïß}“Jï¹RÖ®Åí1)ëê—FSc‡×Èz}®ã­ÿXH±ªè,ŲÎ54VžªõÎX%~xx¸Š!;¨wíÆ0ÍíZ‘­ìmcdïW°SGmÏ£­eל Üûî̜ݨÒÐn™UÖ¶Á™™­™¿‚;¦‚$ˆ+Dåâoá©+È`PµIa—ý̳²¸Ãç]©_»è•¤óœ¾Ó¯Ug…­ÞKí-î°€,=Éó ¢§)îè|Ñ÷p‡Øã?ÅeRœ¼áüýÅ$eš‹;d¼…;¤N{.––öîpîêî( bëwñ}÷³?3Ù³{Rß)œ'Üѹ=×ø whÚ¬‡¶Ø3ºøÌ—ùK ›!— RZP‡ ïîî.-IéRRÔ‰—V¤Ü£í®———«àºîÀ­¬-0ôFëP›ÞÍ9É9yó*^µæAVÓ@Õ›|RZ¶ñ$¥™í{V °:4a¨]ßËËË¥â«|çÑŒ  îþö·¿]ª/VÎõ«zª™Õ•Ýs /= ¥iYÒètˆU§zN(€aÑÎR[ä­®ŽbÒä̉ßóÒV<ô˜\—=üNUõR«<Üt‹î¡[C¶%—v»W%¬Ô@—ÉI¥CïV›÷Ü~ûí· ÐÜZRaÌ„¡ÔOM]ã“%Ô‰§´X×dEÜ “WöÜy~~¾*œI‘Ñ`Ô5½D¤U»ùß¾}»{||¼ê$[U=ÉtK¬PMíÜï&䯸QÏd»€ÎÍÙ5t°wïå4Oj"£× wØ9ÔðTÃlé_ß¾}»$Y‹ý£*w¬ &åI »ÁRäŠ;:W³èîЛkI›É¾RàUç”ûîÐOù Jž}õÏ髚»‡ÍÌÎ[o«Ô£×ÕN…T$¸íùªüµçâp|•|칦¯*?&Ÿz0ªÔµwfâ5 ^«VS½}“‡øiäe·Å˜SŠØhY]s•Üôz44S‰ÑÁSˆÅ&4A¦J:rñK%sFG ¹ê—Ô˜Òá*}Þ– œ 9&[Òò£+~‡½Ô©ZïzW©lgÓ é|Æœ\–º(Ð󟔉wo»žšŒù³‹s®™J¬Kõ”ºåu·íÿkŠ«Ù]r[>c©ŸUž3nKU«}A©%·K1SØB@(l1ѹ¥a÷Ü4Eí¹T `§¶ƒ½Å‚ŒÅK*Š;,ÖœpG)éâŽ}§ÅqÇŠDúôˆ‰† ö\öMì¶w”Þ\ñ ×¼ÛJòï‹;ÜþüIáÔóEé })[;û:ï%À?ý¹I¬æîXÉX&ÅËn^M¨-º*¬PeÀ­e•O~4wOþ¯q‡¬‹éîyYR¿·¦U.ÖÚ¤*™óß3–xÝoá×*»¼ÎëIõJšÙ ÌŒßç"ô`¯|¡ü×:1KC0øøû§¡ÿƒÖ— TšÂù0ì$ìïºlÿù;{#_õ¤î#…¤`E€Y±ß²RÛëy•k^‡ëÒ[”ñjN¶Š>-•5ȫʱ{ò3Lþt;nÒkW®Žã&·.øŸ&ƒŠ¨ÀS7feªkpeÕf¦RvÌ.ö϶7l­zߪ¿/èTY!hoýX1®Ò‰„ÊîVëÞ½ßÁϺYO¡È}‡WÂ#V߬žºÎ]ÓvNòð¶Ë­(•¤ÊÍÞ÷öÜŒÿä`ÏU]ž²ûÓC½kÚçe5tëcëRêÀ-ã:×À:HD¬r[©”ß\Q„pT/ñʵDe×k j‘E¬Î:uXzsþîÞóÏ?ÿ|5Ü®Ø-O ‹tÝŸ5wóy­û´áúuÂGÙpî»W•6Ko4fK…³»ê~Ýó—¾Rc÷¯óKVe+¸cB©_Q»Ë}‡Räjà·D@ñgc¥W—ÞW;†?‹;A{Ù˜©ü©éýšpï–ú¦\î íBØ5’B!¿ÞAçš&nž@Ã>+Ê«öyH.™W¾J?«|ïû+O¥Üu”vàt”˜Šoèc±eqjþdAüu:ì©®UЉÞ:ÐÛ.žq|{ËgØîÔ¨E&ÈízŸ>c{ÍNH=]ìhM„KCôYÙÝ0!uÞ¦¸cs rû»ŸÝ+÷Š®x~îïF#ÜÚ;áŽÅï¹~úôéÕÀqÇ’IÏyýg:Èïόձ3ì-ÜaB¾¸tÂîA;XwXŒ‘Õ££×iA´@¿þ„ÿ î0).î°ÃZ¹ý[¸Ã½ê³Ž(îPIÑ¢ö-Üa‚$;æDmWñÌ„cß!UkkuÉ¿3Ke«t^§ëa×tÂq0®/>|øp÷üü|¥HøîØ~w.þ•š™Už/[UÜE~üøñÒê7ójàh&é«‚¶Ÿ€U•h¢e€leÃ*™ü6Û€¥™¼”]‡3-UgwÀ8ï°“®*KÕã/5ÂL\¶|ù%„‚‹=£UÅO॔{9«IÏ­Ùƒv°”û󚟞ž®øÇÊW’{•ÇòB âšÍIÅjÅÅ `NùE¥¯ë´«·GizûÌmÖ=¯q×.ýQ¹X–šö­f:p'eIIê4•Í<¼ëúë!¤š¡ó‚yÁ•]·£b¥ÅúÍÀ`§§ÐîÛ.„”ĉ]h0»÷ÑY”µÒÖv-¢ïвÀw׿nˆ]ÅÍ×41(®LøÀMßÏրݎ´ûfœýÜ£xµZê;®¼k² %?}Ÿ-f€Åg¯Â¥£ô D ;Î\Y¡” ÑjøIº[9Û:ÐW-È΂”1‡¡£ÐäØ˜ÓË}ÿ‰R+­c H5 ºÌË÷ù¹'+k,˜QôÅDÎŽ¾1[ÆLý¨t…ßý:GdregÂŽº ±‰}=îÄRYUÉ*•ª]Ëí;1ƒÒÅ*%I­í|°–]»³…âŽÑ˜ö¼ôQi!§¸ÃJ¹¸£J_îÏ“”ï w˜¸H)¬wH[÷z•a¯¤p $}wv\\OoáŽv°ìZ‹;žŸŸ¯pÌæ½7'ꡈïá»}·p‡j©¥nXÞï+ÅÒõ¬ØCqG=…´‘>ÖyXÏ#;b·p‡³ñ·pǾ¯]ÓZ ,ѯÝ[¸£ì WÉŒee ëj<¥‡x LV¶jf7€âf®Á•pjv¬~ ¬ uÁîåÇlu¥s.'_AçªþUqP•ÍÜR[ª„&˜¯{ø‰ÆV£¬J:Èm[C$[Ô.:„°?™iUEÄÖtÛÂ*¡¨=/¨×¤±rŽ•lÜz 9^3§JŸÌÝÔjÓϨMe)¥a5oSBN®AYÏ}ÎÀ—«QΟYp1Ú©^ì0±‘ŽSú‚®*yªÅ8$°ÊÓyÁšîÚVµîlUçᜋ0¦Û1 ^7­û´Nµ!yïþN}}Ô§¹Ë‚M©‚G“}“;硎êyR/O1Ún³ÉÎ;tÖÂDÀç õÔî£óRí¢TÝÎ÷';aϤ ²3µrŽr¢åœ¨|ÆšâŽRöÞÂVܥɕªSƒfך å-ÜaqWº’÷WÖˆ¾<ÅdHŠ;jQŠ“¸£ó{Î"Š;¼Ö÷⎓é­qÃ8¸gêù+®º…;ìÚp‡TØâŽZì~v N¸Cï¤zyŽyΜpGïû$!¯a´ÍiÓv·ü™ÒÓÅ¥ÔÝœû3¸£&ãÂ’z•Ì|øðá’!JïÙC–ª1-ô?*U9@j W‘JoåÍ&·VEì •^$r0•™Þ¦µU^¥ò ­žÙf—Ra«Zñ„-¦µ7¼*>°Zƒ(=ƒo‡\ÒV1Ú×Á\Nû1_µýM ›uWæSž§‰™Üçj”÷`r@m•צÉÓ‡î~ýõ×Ëuï}yyyåÄ+¿_NU +ÒNÒ(yÚV° ²«æSÍ~çÐäæ*iÒ:Þ~MƒÁ}•ø Pkà¶Ït¨º†›v³ HRV à&·ôÆXЪ³p)–;ô÷竞º—}Þõ8ØÏ»¿j4«`g ×â ×j𺠛µ2ù¨@ˆ´’]ÓºõÍP8a\ûù5ÁÙý®û5¦Æ{p‡Cé_ÒÀߊ!T=jkkç‘kZÁ•ÍjmÏ)(à¿ß‹ 6JÍ¿ìlÓÇkÅ=U]O¸Ã®í÷pGAí-Ü¡P‡ôÜîØšΟw­yíÊZ¿…;ôœÙ»0.V ¾Åv…¥‘w˜ì w8ûkQl¶PeE¼w8³®‘°Ò¢M~N¸c‰Ö w´óù=ÜÑnÖ-ÜaaÙ¹›æ'U6ŸÕU2Ó!m¬ÛƒÓÄ¢ÕOùlòP§r°ÛJ©òq¶VmC n«‡]Ó:«ÐJnž”jÌÜõƱû1áÛªÒæ¨\—ÈüöÛo—jK Ð>r IDAT ½äCïÀlÝÍ)`«~¾­{«ªŸ?¾:9èïj£;øiåÏÊ‚”½”¦,Þßßß}þüùJJÓÝ… öï<·Ú&€´eZ«Î&ì™´ÛÖœt=+ã 5q« «•Ýýýø»‚Þ©g `GORU©ä¤÷_Ç`ß½-õJåÖ`ö矾’+ ,˜Jͨ4¥@%w Xû™ÎÒùn~úé§»þóŸWûѪº¼i׈±eûðË—/:Bý^.ë×¹8«”nÊôÝí9ÙVO0eu­t)&o5g]ܱ³[9y+fVlth•P7ú‡‹} "8ë´g¥,°2Ý&¯U³X%maI¿ƒù[Óv~5üí¾"Áb´®ðrÏ«ªçp³ ž3Uv»Ûå«Ìì@ÝÄ@J‘Ûï—®#Ð7cï°f‚S2á’‚¸¿¯ìý~{J_÷€’³Æ;²Î7T­Ô˜öî¨/Ñ-ܱ¸s wøïîñQäШXwÂ~ÿ wØ]Öº¾,v,w.Š;ŒÑRÙv¯ïÅÛO2Z•íRT}ö„;fÙ°ç#®IcMb‹;ìp‡3ŠâŽ]ã wxÞŒ=aÑBսݧxðÏàgýÓ”w/¿wØ™êœzqÇÉFÄYZß‹;*umìsß}Ú•wHƒ¯Áìp‡¸{†Ñž§¯’gý÷ú›tÑ¿sÐ w¥KG+ýεÕÉšx*ÅYI79ší&l¹0O^/ 4Ýè{©5ò4 ÉUÔ¯£Cõ•=v¨ïDËÚ箪%uHo«>*…HÉØf•¾P¶}åôjf©ë‹²Ò±MhUÌaU+qÎ%ÔðσWîn“/Ñ”S•¨•ÅÊýÚÚ,è“ߨ“nUé|šÎÙFÜg âôËšé{-€«Îy€J‡Ø¦PBÔ ï{R½T¥&k‚| ä{žäkœ%-ÉÀ±g%mÎuP‰G“ÂE~«T¾}Çž¡ÕÛËb¥{µRØÁe©€î?Áv¹ë­&9#ἂ@\ ª ŽÝ“B»„¥œªF¥ŠZå+M,b, Ø5š<t;¸¤Š´sj»\ÑŒ­/פÜq©ë¢Ôíú$ bá¥"R̤٭«pJtv(MºÖM²`"°ûðáÃ…ŠaEßdz´'››Ì ÞOêI‚ùÊ«÷óT‰ò~jòg<4®z¨Z¤¾:ûjWÓܽÒÂb‹5]TÀe?»NjgMÖ îLŸgÕÖÎÖ`Ï.‹FqpMYìpþÊ÷{ w´®º“`ÐgÑîÍ[¸C|¡²XÆgj<0\"ZÜá(î°Ët½ÏOïã-Ü!îš®hÈ wt­¿w8˹g¥”o㺴>»£žvl•˜6ÛÔtÓõìœÚìhW±³Á%{ÞƒåΙ´ˆß9$Ï…²PvþwTxà=¸CÓwçF¥.W]Våãa7ýÙÄ( Umïî8Í@‰;ê…ó*™ÙÍîà)÷Ôìl/MŠ„³«‚<È×b[ «œ­•Ûõrÿ: ,·N@ºë1°J੟þoƒ*¤9X* Àëµã €R^º—­Hƒ°ƒ-ñzvHÉêÆœw•AÄded›î÷ –Ö±Àµõ°ÌÚ…l%ÃÊk¥åìK›ªy U¦%P;ŒWý]ÕÇaëmÊ)nUÕ[n0ugŸ%§´³¶ïU•’O.Ð,?[ ÖÛ¾Êa5õ=¥oŒ œ¹ê…¿v…L4íü¸&­Ô´â*Ài‚¼˜!=`Å—E›Œ½¼¼\Ö†•:)- ¤™Ö,rЪ>?_¾|¹Ú×Uò¬sã<×É7k1PYN}ÁIµÕí6õÿàÛú²J鯆1kó'rÓë4`1™ÙͪY°ñ Ðý]e.=ªlT5¦v°¬˜Wykk¶ô ã·‚ ÎrYÈ3ÆH7ÔЊ¨IE‘J4/TNX@ã¬Ïö» {ûoÏ?×ô:W-èl?m?úg5/Üýp®òm·Ò¤OˆÅèî°ÒïL£²Îâg@T·ôÜÝçxmÅK\öÝâ;\-ö™íïv·p‡ ÛEg‚Äv;oáŽi￞'Ù½…;6?RŠª¸c õÎSUCO¸ÃóÚ÷!îX×§ß'°w&¯ûVµÁªxŠ;,P-¹R¸‚/·p‡û^À¿5äy&Sé=¸Ã"Šq{V-h‰;¤TÚ{ w,8s+¯?—çÑÎwg„Foßóq^Ý"ü+5³-ªýò‹U‡eÕrÖ:¼ÂÌÕ¡Èñu÷Â÷¬†ìa|ùòåîïÿûÕÚ0»ý€°ÔiDò”MšÚªÓÕzÜa‰¿}ûv÷øøxuuÁ8T×*ÿ·€ÄM¾{³r´Jƒ½ÊÝ"Ì;OâA((³…éû[ pتÐ6U‹møý÷xç5­hÄÔ9r;DUpkgKS»mú&^u¢wB Œ ¹] = ”ÂÞ¾¿³ (õ/°’µj{‡ nU´’^ ìŸ˜5Œ´‹SÅ´1¬ä¼I’ÊFïÝll_/À>==]˜%qM›”*‰­‚ÖîuÁÓùŠ*#ÖÄ.ã$\@6Úw9´]`iU&˜]Ó{6Ÿ>}ºláŽkĪ2Ti·ºçuw0tCá&ÆR8§æ¶u2IèIV7±“6Xß ÿ®>"RæLö7\îœÁ‰:3ÑEC礲J›+…Kz”s÷÷÷3¸É »ß7WyšOè4¹Ø½ÿüóÏ—3Ùµ¢úXç¤Ú™Ñ|R¦A ´­\—:j“\þ¶Ë°{Ýœš¸cßmR îÐPÖ™5™%¾eŠ¿÷3pÛÏ{òÿûß/±mÃéRGßÂ[“'Éjã¶ûnqÝ™&ÕY£sÅKú÷ N¸ÃkÞ;.îØ»•.»³³ ÎT8÷^Ü¡–›ççç«n•Þ0‚b m‹;úÜ!1A­u€¸C—÷àg:ñH³Shé„;쨼wLôF:–B,&¨&ÍÒê}6&ÍRjÅ->wøŒ,TwœÔ\e_y?[Ó¯:3ò+K1™ê“³êjÛ ³­'À2¹X4‘tPȤ£×f`P}¨•¥í r˜u—¦/„ê8­ÚK pWC²Îü”SZçfÁfè}&‡Ôº¼×GÏÕ‚|'Viì°IQØ&·U»Àççû;þÙèîÃC}ATA««õté&²’¦¸üüš¶ÕY¹ÏÒ ¤øl\W»ÇÊ’Z-®?…Ý5Q°§A¡Åƒ‚VŸ™³/»&ý<¬´u°oÁ³ÆVå#oKáh¢P`¨¬õ‰´õëÀ ‡@eB+Œ`wñÔJ`[}–ï}k€Þù&×t<¶V ,äl=[ĸ彰Ù%ÜåVW¾½””Î<”%`uíÚÞ.ýCÿ¿kû¬Éq%AüuÖÇ¿«H€Ã»vàVé•3ÞŽ—sr‚o±Ïõ¶ï­|ªç¦ÆÐÎF©†¤Llã½`v±ÜÎÙ>³~GínIS´rŠ¥ÛX½¯m‚kÖ¨ïVÀì^U>|±]¸cIßÞo¥p­¾+ý{ÂÕ+¢¨”X 'î¨HÑ[¸Ã‚×tÂv·-Fl ïß¾/‹;bŸp“.‹°~Oq‡F¿Î®T>4Þ뤱x"îîí:whrÚ© ™h6-îp€]UßÂ:ÓÖyqGgèj½`lPǵ\6Ã-Ü1ÜPö“R£¸£´dYU⎽_ס# & vÛµ^Ÿ‚⎠-½R3sMJ3Yy‰U¡Ž`kÝVûh~+§Û »ée±“;tÚÌÔ `Õ}›GU¢Ê º‰UwZXÐ!pqƒ xÐïºmIº(4&\`wÍMÜʪ‹]ŠO(UìU‘Äû5(ë{`¥Â¶²êߘ[ƒðâ»VßÃÒÒŒ·Š%ô~k:ÜaÿîPÐæÏàçO¸Ã®ÏIPEiV-hv¾Ð¢À-Ü¡Ÿ—sž‹OKNM,dZ)Nóî(#bx`Ï®çÆÉØxפ®JÆÄW335<³*¨6·œ/ÖæªÐ'Píð%y ú·Ak*årÑ-`ì€,Ǿ®£•t±kJä§œÕ 6;øj°’Â$0qáxO« ×åüìb©ð¢<ž‚io5p3I)ØZY°ÿ÷¿ÿ}÷òòršÜÈÒ545TCþ4meÖj¿?×YÝÈ=,÷{kYÊůÎ6¸f˜£4(U'Þ5]ƒ¨Ýó¯¿þzeª:Ú„ Ì*HMT…®[UŒz8j ñ} üŽ.×VPl2 `ÓsIšÂI ÜuQY×ýΨ;yÁÎ´š© …‰»~[»;”Äl¼A¹d»V£ËØ•«”´öé>>_ר>ÛÅb^çDNf¬‹W;àGj\õ³!ˆÙ3[<˜ßV]ÝwˆZÓƒJ°Wð"ÓõPãQý%ÚFw+0«®]ª­[ßÿèju+·£}’HÐè·ÔÁZg,5–vM듳nÆžßÎJcåÀÞºŽíDo ®ªXºßWaS:¯ÂU“kåºNð«ÚÊÏ7á®ÿ™]1ßÃÞU•‹;œ‰°&¾ý«”2©­®S׋ÀØn´1ÉaiAbqGŸ«óv¡*¢³sÚâ“t  î,W¨Gj_é´b”n¥¿fÎqÚͰS]—íe»çzÙ¹^÷¸…;LàŸS¡L¯q‡kç„;LôF+7ÆŠ!náŽÅ›*¼YP¸/lNlŸ}þüù•)íhg®å[Ñ'ܱÐ1†î‘Óµr w´áñJš¹þ¶«Û²-­z-ÈrÐå0/øøñã…'iuè-y̪Ö4¨ûçm¥Öp ¼ê7Õ/Ó=ùøb~úé§»§§§WNÐnÜð•»>޾Ê>Ù¶Âé<ŠÔ‰µë=8LL¼&¹¸Ê(ZÙ”­“õ>cÙ}qM¶ªÔÓ$ÂÊœÁ£NÀí®X •ZÓº•Ò5 `­PÙö­Á¥•­çªÒ8‹ä€¨U Á›s0¾#«w >g6ªÎæZ»pU—úüùó+U+×)¿£îí=¤FÝ`s Òà àó0XðЕvéRí6úŽÒð@19rvjÀIˆkÃûÚÏ8P-½³‡€ÕjšNÜ5ª+(Óж ÀŸw/JñÙûX24À|õ¬¥äÙíÚÌ”°*n.& Üíg- 8£åšv_ øJ¸ë ¥qÕýÅäÎ7mÎÌÙÇÎùI“Ú|RªÂv]°WvÈ*ï- s¯X¬³Àå{µ h5\Pê öÉ‘¼ÒëÎ…TeUÓzaH îØYmœî¾®,wÙRk=ÏO¸Ãë\qÍç)=Gú”k×¥¸ãùùùÕ¬™ÀüV\Œ±ëâ;¥uîÔÙ¸:}&;Ò‚=Ó,ÆT‘Óy·vÚ-wÔç¬ô2Y7vŽC>á‹'Å®ç“ܸ‰—_ÏüîçÕÅË¿‡;Š“dTHáÖìý„;,Ꚅە»…;\çÒ䤩‰;|W⎽³«dfFjifžv6¸n¦fõCÿ9œÒ§NC¨VO> ¢ò3å•ÛýQ%ÇÖ«ƒ'Ÿç̈·yOЧêË <à5 t1Ÿ¸·J®u>Õ¶”›u±˜8Ƀu¨ïÕç³…}RÙQ;¼‚ û39­“]ïI[] Ãv¿«H d¬ø•[ï»u XÖjœÛ’Vb+Þ®PÝ”­Ì{ Û¬`…•‡v½^ÕÿNþÒLÖmçÒïÝ>1ñðiesÁ¼à§ò‰Uì¬Mi^* YÀ3á­7Ä‚¹‰C¿ý.yßÒ=]ËÞ‡÷fÂ5¿k”$߇ÏÖœÏOZf=­t®?Í_yèYl’š! ËÈŠciÒÕŒov¨k¬‡||‹a*>ZMÜZ`DZ„ªs5Y@™%;#±ÄPåº~øáîáááj»TÒ!¤y¨à4 ®òФgó+óØßíÏ”tsí¿pªrãìÏ€[ÍÞ¶?äK¯ÒXóJÿg ê·†^ª6u9ö½6({`X݃írì=ŒöåZ,§æZòs»–ô,vX©4_‚¦·KÁx[ò›žd~ýA»f*tP™q“3Ûùùp†M©Ïrù+gê ñâŽëJÊ’RÑÆ ;R»^çŒrÉ+'.¥Õ"€´;c´àE…Åhço).y0+„P)÷ÒSªÔcGs¿·97Ï4c´ Ï,Å@¤ îÏ\Ó}F;|kÄ(õgçÒâõÖò’ñš4[}÷óœ³Úµè‡¤¹¬JS•n–2»µ/}ܸ,ÝÄB”ÏÂîºÕé_ýõö{›µ¾°¸¸؂ˮ˂œûĈ­µ§§§+ê¬Ý*•½,þœp‡Â&nÒ,|؉é™ë¼b Rí–ßVUwH“uX‘¦S7¨‚6Å£j¶‹*îØ»–mã™úîðŸâŽ[,P­¨êÞ/EQå°Îæu`ÞdÄdÚóUÜáÙûüü|é¼[<±«Y_,c˜ó}ÅvN”Èÿã?®fK/}\j›O`Z1ÉVó¯àŽzÌw,9,î¨aîâ÷+Ÿ™‡‡‡«AXÕl?7§\¸mÞ7¹°ÆÁž‡‚›´”5AŠ˜†jji+,X©C¹`Ò¡¿Îs8ª6Vå3Ó“³¬´Ÿ¥¾/ª§™Õþ/k÷šç‘$mRK"Y ÞÙÆì7³ ¨Ó÷çó²«ndTÏ´™Lj¨z™‘îV +wl¥Ý   „r¥&÷üEä¿îzwˆTQgçÆµ²&}Á —ݹ}·ôŸ½;°›e÷UÓÕ>\ƒ`éjnîýŒÉ‘ŠQ+V-•X 4Hû9L+£¶«¥`¤:ЪÉZׇ`]ß!Ïþ“N5ÚÀeg¶ÞÝ>çŠaTJ¸2Âîë­Y%¸+áÝÀ¼}í°ei¥1TÿÞ8´CÂŽžÀq>!ÆçJì¬ `¬üZpêV…´Ê"¯ çÁ¾ v¡=´š y`°{f¥rU3ùýõØ9‰ÀTÆ|ûf|û}ïüqÓY(‡ºׯœƒ¶À°}Z?©RðT³zZ%!@g œßqXþñññUÅÒ’ëÒ*¸ëû4Cr:ÿº&Œ+R«v¿ŠQ¸¾¤ã·9Âi«Û¥°{¢B‹•;«Uâ(Á›m6éa_Õ‡ì:LiEÁ…hGƀ頼:ã&,R5TÀ0™«y¡Æ›õã1©9É.Ömy/\ùP©>3Á¥:øÀ­)œ‹¶ý¶×äT¼©,è®i ZJƒƒJi{H”t¶£!Õ`kÚj­,‡Ðö{õ0rý[5qX¾œtŸ¹ïÓ5ÝN› ªÒ×[÷òomïÚ1, ­–¹¦«ïÀ¢q¨û¸ƒ×QŸSK½©:¯ÖgÒußÿum«üV7Á‹n߃‰k‹÷ó- ´;ÐDúdîëóQ:VpÞïŒzи¦íl:\+•Ëù¢V©ÈÎÐtƱÂvߌû&µ&!&ÆK,g{ðiÎ×Y ÿYÜlõ»’ËvÝ”D7ö[ÍÔXw×jR"€°#ë·ëd¥ÚøßÕêÊ=÷ P†×9*;«íðØa[Œî»tÞÒb1Ën‡TfÏÜS&î0Ö4±©@¸ckËk®:ä[¸Ãn½qDŒQÜ!Èï<ãé}½…;|ž7yo±¸Ã·ëÎî¢kþ„;¤95ɯ¬ý[¸£kÚ¤»¸ÃÄß„Gê±+qGcÏ?ÅMþІ;6T/•î°hãûø'¸C†I;-–ßÃ-F¼…;jGàs×Fd¿7,öîÂÜfE‹¤<úÌüüóÏ7N¼}P5Ú’ÑAGˆrÇuua×ËÂj„-ærçÆc´š¹v_•;ÔÅw¨Ûvi3jÉÓÓÓ|@Dp¼*v+oRE4º4ÀÀ–ñwáTVÏÀ«°AÍ÷Ýû¶º­6[‘ÙÁ3n²34¶÷{róY¥PÔ|{6‚³Ûµêž "n¼ççç›Ùùí‚äªýX•ó05!°‚ZÓÖ­éR;ìúû5t5È´²9JˆÒÊn«päá½w% TâÒC°~¾‹’º‚R[äÞ‹•:Ÿ›„•þu„”h5>¸o§¨êk®ò£»7]+m+UGyX¯ÉxT•*Aj&»'OjPÚuû­“; IDAT¢~@+‚8xßaqŸU½rNNâúv¹~ìj8ðßad!Aœkª…«ÿž1JÅn_—jºÕ3¥ƒ´ëºîì®[ì’æãçLÂÚO¥`bö?Ñx<Ærgb¬¸ªnV56ŸÜseÏ[2†Xn…Þ*¹3U«´K賬.656©'U‡“Úä}b\ÜáçwH=ëÿ üŒú]´“rw¸víÒ¿îáŽýOÙÜzp¹Ç_• wíêõ!Þµîl®@NÅgIJYîáUOíx‰;,:l­OV\iìý[–GqGϦ{¸CêœÝ ƒH],îmUÜ¡Šß÷àÿîŸâ1¡”^Ïõ­éîÐ õ-ÜQEO»{ÛÆŽº‡;,Äwhœk§¯¸£ã•4sU ^^^®\Öš?nhÉÊ\+=ìÚ–kà‘ `U®Þm~Ÿ/V߃´ôƒ:Ñ/­²ÃȬ%oV•«–áA׎@½@Ú¾ôpÝg—.ÓAJŸ_¥cË_46éˆïÏå:¯ÂWå¤V †|þvèVÉQž´4ÄmÖ}—ˠ4ÅR@˜¶k¢š“Ô:+‚l¿¯ëLåš½S%¯¶v+‡8jŠœfˆª]¦'9ã}§Ý\A¼Â €zØV}ÊJ¤ØDD“>ãR¦‹~ýúõ¦Ê~¢ð(áÞ|cÖÍ÷ÕbÌ’”%8'@Å Ú•~å\c´r¾GÿÔZ½mòS…½Æß©3õ^ZÑC@ ½ÒgY9{“RU»ö Š¥cì{œSlÅ~•Ã* •«o²×ê¦Þ>Ò¶T;[¶.¬ž–3n§¥Rä•HÞSéf©džëîýýÎÞ_ç0êu¢pF»±>ƒÑ e`HÑ–Ônª¸c³»â -Oò®Ò®ÿ®])ÒU“²ÃvwàzÆV"ZUÏ“ä¾ó[߃;v?5kRžóÅ0UÛN¸ÃuÚ.½¸£ŒìÄLí"S[p¬Üs±t»{'ÜÑâ¥{@ÜQÿ5…~|îþÿ)wVå¬sp¯:3V±VIÛø€tVc\0PE ¹Ç5Í“ÚR•¯vvš¡Õp«2‘Õµv&¥ÀQçXüev++£Ç˜±ë2ßCm Äù–¢¥"è!ŸÓ Z.£üB«‡r¥K Û}5cÄYÑ:¹¿Ö›ÈÄÅAÐêÈosôyuÅ„Ô`í°˜À´îß>×}§ +{¯Vñûî™ ×ÌPúôÿWàÁ5mµÜ"Ó’Ú“*ÖèU£Pužo1Ïî|é¼Îåì{ì :Ð{:?ÏÙ9ëµjÝ"މkZžÎxª¨v‹'ÜQá˜Å˜_~ùåJÏCI=+îØ^þøñãï¿þz=, ë1c#Ø,îØ÷Œ5 ã·p‡]“&ÁOOO7ôFÏ`ߣô¢íU÷½kOqqǰƒë¬ó.ÆÓv|÷Þ<[:g¶Ÿ`]šdçTÅ[Ç÷p‡LŒí‰§§§ëŸW`ä„;ôúúôéÓ5¾zöKstc¾BÛÓ››wl¾‡;æ)¸ý<ùd IM‚öŽO¸ÃÃ=©bd l‹IÃpר»ÎŒ­D_àÓÓÓ•çlKåz«¡úƒ |Wˆ-(yÕu·ÃQ¯kêß¶­®w¾ÇE¨œ•Ÿ:ÿêA¡£s–õŠœDd.…ÎÀ¥ö÷ž‡´ ; ø8&?¥8xoEÀê«Ï²W7«§©]ƒÀ´´«ÍÜë„(À`×­†£ÛnVÕÀ{øzÏKõ¶°jn1ÀƒdÁL­Ÿ2ÝUUð¬Åmò9}{—Ψ޲*‰™ªŽ Zì&•BUÁ ûN‚U¦ð¨Ñ¢TÛâÆžJš+;låÈ{«7’«vQ\Ó¥…*§,¿ÝJ²)5+ë{gýŸ×\î²ÃÚr¦?~üx¶ãâ÷·ÜCJn£5©Ø‹‰¸¾‚)]vi×—ìiî(¯z`¾ÔÒ&5&|av_J' àîIx×iqrŸ×dÞ˜oçkg™?»‡Ò‚”*µKPQBo-0™ð¹ö«ö¤!³Õr;„Kn¬ÐWRx{¤áäÞ]j¦3ŸÙùé§Ÿ®¸CÚqq×´â "HÃ| w8çiwô=ܱµaqJÚŽà=Üa£'÷²Nózp‰;”Þëün…‹<ëIJ(öy=÷=â?wñV6ÊIÞ¾f¡ÿîØ3×»nç[qG;;¾KoßÂÎ,Šûv-{O{× ØÁ*;ggqG+,†UÙkkª¸ÃX0…ÓâŽíËår¥õpÇׯ_¸Cœ àE»3=Z’$îºmX|æ}¿š™©™üv¢“>(ÛÑå‹–¦e Y'UiÊIöà¨\¨Ê:•‚U"·@[¥7[ˆ*Âxpûòª7^ºL¹¨M.êWaex`ÚJNyÈV‰¤²Ø¶õy¢/´º"¶¥þAÓ9É4 ¬åX¶Ò.Ã,Þ¶x5åU‰s6ÀV¥Ábµ V51«$VýT 2 ÕôP¶ƒ@ùV:+‚ÛÎõ#jÇO ]9LéÒAN2wxLìØ Б#¿?;%© œr ÌÒÇJ¿3Ñð~í,K±sý:¯$Ç¿âþ|+•V•·V\_MȬ–™D©úd¬ìãhÝ?&ªý”–iÜìÀ»DãR+ŸîQgZrÍ·p³ÿ¿ªíi€Øn‘´Ÿ‚þÊžJa*¥ÈÄG/•Ó3dûhÅŽV™ë/³¢„TãÅe =ë-!•JA é2Æd *RdŒªðY<迃ȣKcñ™µhS‰VÏ—îGú˜ ~¶{¥tÀâŽâÊ9 žþ)îè,Æ[¸ÃXYܱä¦3yõÌwl™ ¸N=ïái¹Þ£… ÝÇ'ÜápoM¿…;¼7qÇIøÃ®éž‘3ÖâM¤:fP™a÷»ÏÆâ•q¿sVÿwl=ìï;÷á¹d‘ÙùO •Ïn±QÚ^©ÉÎowì^ïá»åŽ èOµï'ËòiW¸"Åõ¨,îx53sâÛZ¯©U9‡¿¤»˜Hxcõ£Y;Pΰ݃mç+|øVûú+)8ŠæÄr•GðŸÎk¸ .¶’¯ö~W©ZŠt³€½ÜþΞaÕÅ<;äXS¶š"Õ™Û§™• F­Ãì'߉J]·•_ó,«9Ò8¦Bæð×"ßÚƒIîúÞOùѹY¥«é¯Õ²Ñå%O½¼ó]ƒSém1¶V"ùßÁ—ËåŠ;ÚqRµã böïÁ{ÏÃòUió]ù\w˜ùÎoffÖŽÝ‹Ø m:œý×_]5ö­L×9µñ½¼ççç›!Ï[Îñ6Š|¹ßä.îA???ß$-»ÖÍ/ Tz‡XÛ­­nô`þûï¿.—ËÃãããÊt¡eåã'·Ã *–²Å{Ns´wnÄ6î¾Ï]óÆq­ªªˆµg²gº¶â·oßžŸŸo#Ý ] ¶¶>}útå_ äF;i3y4^+µUÃýÞ*í .ž\T«uMÛfµ‚¾5¹¦K¥R·¦kfLê—Üí›S¢³{ÝÚ³–w¿õÞª£*åW÷ßÿïÿý¿ë»_Z5¢ýìfâ”în›Øê²—Ëå¦ræ`þhz£òõ„Ù÷ù­*¬w(íš_^^žŸŸ_©äXQÞþ‘ʶ¹‹q™Ì.ÝöÔé–ÂæŒÀcûŸ/xšïŠ`f‡¾seUñ*(°K'àyy¹QVëœaôÀ¶0¢ƒ³ù­»———kÌ2&í^}§ÏÏϯx÷5Ý}®C%Å×ÎøüÇ\÷ÎfÂv¸/a{xxx¸\.7ÕF;ÆÒ½§ÅÏÅ7U¾¿œk÷lïj6Þ{¿ÎžÖGfÏmçób½ÝÖÒœö3‹‘›ݾT¦W*¨‰×ÖgÍ =£J/ݨrÙ€óÞŸ¸c÷°5ß¹^q‡ôJÍJ‡;d]øÿ»¦ÅÎr–þ´ÿÿË/¿<<==ÝÈ›ï½nžÐ3[ú²ÃÒÅU•FµÏÞ옸c’Á{7â)šÎ{XÄݹµçañB•RôÅÛ;®i ¨»&“dé§ÅÅ<߃;桸})cd÷ç¾ÒWʱê—5OwèÃ7ìh¡Þ÷§d»É‘ûÞ³Ô‚†¸£]Båé+Y--ܳF•Ãaæççç*÷ò€©wl”C‘‹*8Ú˜°h0¬ð믿q‡&¯voff&:°!÷Q5ÒNª–£ò˜\ÕJ/ëôªÜ2±½à-Šý÷§OŸ^µ÷³> .ª#ÍÄTÏØ‹PÅ­l:R°»& V燰Åk;°CÇV‡š±ÛÞn€³Êÿüü|“ ïžUŠpø«^"{é³`µÓ–~Ý›mÁK¥s°ÒAl+¹vD¤/T±¬ŽÁ{Ï>÷ÉoVq¥Ô€®¶Ã•q• éLGå‹UŒZÕLúÉÖ´@ãª=¯Ëåòj ]*Å>g M“0÷G+û¬ÎìÚ:û\ì¬l¯/ètOÎu»ƒuƒÞsúí·ß®kzrv8·Ïõ(ÒB‰c˜‰eÛØÒÊ*aµâš$VMG%&çÖsoLÖ»ÏMžÝÒtY¯ç‰±yŸgAµ,œ½»ËårC ±sQÊ€Õû‡‡‡‡———7ꭷѸTi’Þ°‚šñW0aÅTU(i^*÷mM® £JŽª:Û[• vxvŸ!,(ÕÏCÞkvþ³I›â7^û«|õ*†ÕèºÀÆá8ó&ÓPŠ]S¼Å—%ƒ¾[%W÷œ?~üxL'Üag_æÂ¤î‹/îØÚ,+3»u*îXlmAKoÅø€a»ë‹§šânïÚ¥°›\Üa¼îpöK@½ëµÓPaˆaÏ…Å^©ÊÆ' bþùç5Ù| wX¤wxž{o'ÜQœÑn»¸cX@ܱ™qV V:b»çÅ{ßÎÜœp‡3{RßìÞxoâ×ãâø±ì¤Ò›¼ O(^±w±ý¹ÿ–¢{Âν¼¼Ü¬Ñ#ÆHÏúvÌößÃv¨ü;M^_ÑÌ4B“lU¥žR›ÊŸ´ûЪ™ñà(`nhÁV}*ݫɑ#¹hÅUÉV5×9÷ÇÚäG°[cJ´Ò¾äõ ôN’†uÔ.§±Îí»O;`V|äTûÙ‚îr;¥[µ:«ãõøä{÷.~y²¶¸M`¬z:¤[3¾*aùžä—µ5®i˜ÀG)@g+ºùäK91yÖ ð¤Ìe%Æý×Í\µ!¯×À¥ºÑ&©L]Ó¾·zÕk“vU¿Ö½c¬0±1¸KÍ9­§šlVºTÅ+y·wú!xR­"R*\‹{Ζtu6bkbÏ~À»)½ÎÙ.»“^Ëö÷@–´C§Î&8g£²’1å±WXúÞÉ}¼AuF?ÍCZ¸ªøˆ*J&hvã¥ß¸ßJH)§Ü…=ÏÑšæVJúµ¿k¼q_jfZjŒûÜjñº![Ó ˜¸zOûžHpø»'> }º'UŸƒ÷Q”uˆ¶žV5þøñãµZ׃NÁi [ÓKìïJ2¨­ÂëAl Ü»2øY‰sh-‰]Ç‚‹{M)o[ðú”’&8Ü¿õtèÿLØì5™óP4^Hc±l¥_ª™ûN>t;AG×±¿ãl…¡uRL¤LbuXWô@‹RÓºØ=;\o"¥«{Ï9žUÂ+}ßuYñf÷üñwçN¿$·ê;ê¾C»oÆ<Å3: .]Xi×zv؉­º Ï$hÿ^2è³s®Åâx¡Jç, ºV¶»ÇáŽÆ>q‡¿ß*¸]]q‡4×Å"q‡B''›·pG‹^Åõ÷°«›úp‡j{õöiw½1Çí{—^}‹³Î(¯:^Ü¡€Ínå{+ô#îP]VÜ!ãÀN‹¸C/’{¸cqilqÕ=Ü!~41ñÚ¹U;iNq¥m]Óvˆ;ä¹wo'¹jI5â¼+¹Ý¹3«ô i\*gµc-ðZ|°óâЧ…0«‚tí†9À.Åê¢Ê6&gN÷p‹‚ÿ®i=-d˜äI÷rø^ÇoÝÖ-üTý¯Rw}OOO¯:1õ5YÒ$€¨Û,KŸL2O²¿‘¥¸éQ6ºw»2¤*.ý«d¥Äÿ26ÚpöÀm‡ûwOÃ@Š .ž·xcG÷„;Ú5jGܱk½‡;Z TCÜ!æ¨rÙ÷àŽî%÷Ž]¬%Z³žÕ[Ô<£¤ÂJ<áã±g¥sËMÖÅu‹;œÕî³wœºJEKmtÿ·È¬àƒ3»#úÜ1ܬ‰w-œý^Ü!Vڸȉ‰1ÜÑe´ciŠoáŽWjfãæŸø“í¨X¬†yˆWñ¥îí[ VͽÐ:W“Úî‡wYÝ)ƒö:ÿ•í­ySl X5ˆ¬„U\)På–ïúföåÞƒXè÷·m¯ô¯]˜.B+²v ¼UãYö¾CQA4UÖL.¦¥[©¶äákh‡éçÏŸ¯ïsÒÊ„Æe嬺æoõ²íhgTTE’æ~T+è`P©[p¥'{ ûû~§Ã¸Š>Ì<„•‘ö òsJ•ñ”VæÜJÓMˆ,zX?áçÝÞ•ÞÃvj¿w¸¦ÅŸ>}ºŠ§ìý,y9ai; £hí>dH _¬NWMLz˜kÅn²üJŽ÷,(î(þ>Ù[(²ñOq‡…9•*í¢6®;3ÝŒ*g š;$kðŒìÀÛ0 ƒÜ  ­|Û6s°Iú—¼{i£•si¥×{rØÐF‡Ã”ëTšÎ@pòÑ ¤ÆQõÊhåÒ`±)1H¶kd%öDÁQÛÊuäF®ÿÌ‚•ÀÖ!æ* 8n´I3[r¸Ô ÂÉÃÁÇnÛ’ºÉNˆ¡•‘J‘Z‘”«¾¤Ó–»ÉcM¤\O¥fuÓ{°®Ë`fr¾ÀËC¼ó-¶§}–Ò!ÊI5˜¸†ÝϧCÀNÙþ­@À©Ø±n‡•çzMIÇñ êìYÍhûTÃÑÛ¤Ær&žYj$êÞ^GR³ÒæL êm =ÇN•{a x{gŸÓˆúc™ì÷뻥¼­Ý;H»¿¦J ê:¤´k¤Ägÿzð ¬k+à\šñZÞùAÆ©:½X¢›ÊJ-T v­¾'©P5;î­ôS*PµK&`“jâ ók:Y¨¸h%YöE)Mû>º‰‘ɺV55-e¨T“úÌ †Š;TéwH_÷:·¦‹;Ú¥þí·ß.—ËÍ»¬oÓ¾K!q‡ ÔI­\Óâ»''PÚ®¸Ã8(SÚà w¸Ÿ²š^QPúOp‡¦ÌM"OÊ…§5GV8 IDAT‚ñ{¸CévqGçñ¤iÞÃâ±f :ÃXjÜ[¸cëWܡϢÒÜRí\õ Ûgî‰t¢çm]Øm{wÈ\² f’ç<Ñ’™Š”H]ئy|||e޵ \¼‹t€|_ñI Kaò´B¾Eg•«fbˈ×ùÙ]+ÓA•Bdß!=Îç”v_:V&Y§žûo_¶àÀjÁ*Sûï#Û°r¸·éwÐnQH”ó¿ÄÔr2+^[ü pJ)¾¼¼\9ÂRP6·#åLPºêºœZ‡ÓWu®Ñªr™Ûl>s6ŽuP·â§Ó¹ËuYö<>>Þ´”­ìîY-ø«j2µ½É:n:Ð.]fëÁö±@΄Ðï’&j‘ckz÷vòaZWÑ]£R®Û#VþL¶·vø*ù\ÀþôôôÊ|v*@&VÚ}?Òr¦Š´}ccÏÛ™­Åõª‘ÕÄMà½5½µhMª]•Áœ‘BeÅ{×?‰Õ=ã———‡ËåríxÐW͸«@Â>ÏDhñ@~»ï`J;)^^^®×W±R‡Ä}¾J; ü–x×çàëׯ×δ1kïÅ„ô=}–ô]ÒÌrg¢Å/eSwÍÌï:T>Û:,õGÊöö¿g‚àØâÑÿ÷߬ÃÎk(I­?R»Ò8¯kÐêÙ:Ü!¨×æA¶Á=Üa'·¸£s‚£,*ñ\¡§àTܡҙEÙîçÊë+é{wè[µÿ.î¨Õ@;9Ú@ì|QÖÝ”`Sª£jUÛgÃJ ßê¼ÞÃ;+ö>O¸cñÁÊÿb’Ø%s¸iwìì(îpæc×b’xêÈ{>wXHñë\ªjGl¸cÏS»ów‹;ô·w,> w,Þ³µ0ÐmÅŒÉsŸp‡…çŸJ[[ìè<û4si ¾•*PJOiUuªö³åÊåsQÔ ¯<î¶ê¬l3TAÈEáà›•;õÎËÅU®t/Gß3ã/_¾Ü :ìÀYuǵfž[”vD¼¶ý]é4qƒæ=×Ú¶y•íÈê[²ÿoEÛ§¶·ˆWÕê š­xE!Hp]~ûöíáóçϯè9û¹qœ½Ÿ­)ùâÕmRƒ¬„ÎÕ_d׸ÄX9G“Ž=¦]™ª,ÙIØ¿«„â,³/kekTÙÃÎÃîûùùù•¶»ôÐ%¶³O’”vp,í Ðí0Ýú·ZŠËö ¸dé€}~úZ->,hzØõ) ÉAÍýž®v,œ1‘ªT¯ã©÷n§`‡ðæþÿÿ|—ĵ"[E?+zvš*è°ßY‡­RÕÞçŠKí4LaÈJxUž¬üž(¾ÇíÇÝçãããÍÚ²»>нÂÀ†O£¤Æè £‡Ï®}Ïר*Ù9±k]²ªa¡àÁŽÃ֣ɴ²ãvBìY-–†åþY‘ÀNH»kÎ.­€Õù<÷v=>/‹hÎ¥.áö (ÈSªßnÎb|qG÷šÞqL}6ââ°ÿ Ü!û¢¸Ã¤tó:b3gSþùç+îXLØþ3F«ô¨XIé[®»+2w,†}7IqGåÛÅ O]¸râ&9ìîÐŒØäÚ‚ð÷à×@U™"Ãýõ×Uö¾¸CeÞâ»L÷p‡Éç=ñ”­ Ïî0y_Œ1U滸£¬g—l6ìÿÿõ×_OOO7ERñèš ¯<¬}‘õ°zjfjw£mu™ž*‡-j«B27³]&ÝÙ–= Í0Úæ\µ¼ê8céÔÛ!åm>3ñ:ïÅXÑØLÒ6á6Ÿ•-«eˆª¬$øÚõ¹qoœÎpU†µúúu–^Яúœ©vVíFmm:h^u3yêV9×hÂ,-H)Òíi¿Þ95£³:,ÕD¡2ç|G£"í@±‚o¡J ‹\é­Å%ã[Ÿ*VY½¯§”A¡ï[0SóíÓúÍT€B¡íeçÐ4Rì™"-qÊeMrbì„Hótí-ù^UO‡úõ©”lc³Éà€k¬5Ò?ê±3%±ú2 Ô)ÒFª6Y­—~Ö®dm *Ü#Ø”Jºw+ètv€º¸c1º “c£´®í5q‡´÷š!‡U‘ÞP…¯¢Câãí=ÜÑ9U/UJ«®±Òçîì™´{>Uäû^ܡܹ1ºñÒA Îs8?¥˜Ì wœ”.O¸C,f¼½‡;Z²Óþ=¸£Ôë_V ¼¸r߻ޱ›&ø-H[-îhçrøÓÂyc„´âŽíÛRXõûá‡^K3ïá pTã[•¥êg×(MÞh‡å#´Vª;ðg`‡Ä¥UÚ*ÉtØ»Y³*&ªïTîYÚ„4#ñZøÒ*ÃÚ&†—è ¬´©9nE²9‡p ~áµ8Ó±{~zzº¦®XƒàÃÿµš¾.•¶B›(È™¶äµD*ºÛ{n lSòª¬o×¶@°­O?Ó粃Þûë0¦ £ïJ»úùnxƒc3”Ý¿ëÿÔD΄kÏÌýXGyÿÜäQ#ÓÊÿÚå°a¢á{ØþÐkJ'r˜¥x`x`Ô[Â@-ÜÙ&gíÜÌíØ•°r_ŠLïAp¡ƒ÷$J tª0©%ÚÃbûQ®ùo¿ýv¥Á´]c1¥L«±_%4«³¶Ó§®¤4ï}ÃëÔËöÃfôœO¨qè©úÜÃN5³½Çvê^½¹eo'Xù\­dn½ÙÝ[¬Ðï£d“²qô£=_¤eZ©UÊ¢Á’U;­¤ZiT‘K ”¼oÁìþùöíÛM%¼>+Û?ž’Æv‡õT[¨×huõ<1!ô¬øðáÃÃóóóÍîŠ0{þ*¡9°-ø³ópwtòî3wlMu®ÊŽ`qGÅL¶ Ùù¶(¦ÐÞá{q‡kÎΑü⎭oqÇÞ¹]††;ì˜LŸí®¸oìbZØq¾…/Y.®%;»¶”/—žkBpÂJ‹;ìÔW>ØNn …ÃõÚ32fµ;4¼&ƒhïR# JJª×û°kÚYG;Ê5ïõüè é÷â“m“7Ïì*ÑJ%>áY RÝ3{OÃÿñǯÕÌ<\NòÂÀË: [è[ôfïÌr9÷P nÖ6®$U'2)Z—¤YeÕ‹¤˜ `ÚåPƒ}r š8Õ$ÓäÉÏP"TÇd­”5lWÁࡊƒó ¶þ5 •^Rƒ5ïßÃÍ5]5.Û´ÛJ¡ÛÊÞúw¶«õºzoêË2° É›tɺA;Ðk!A T«¦rfK¡4Θ4\I9)E´>Vbí˜*ïa]«ü•Ån"㠸ɺƒ˜;ì¬Ì·¢ía‡W¯}ÕdçÆ|?;LWhQBÓ ·‡…íþÎ:«>cwFŠÉâžÏJÀ¨\«ÕÃÅ.ùòÎX¹!î×b}­6°,BŠóp±êhÅkoWB7uÝ—7° Q:”×vz,X–·ßs׳Þx&•äÔ±ªÙá†z,6ù²ãágYÀhoÏÃ.ݦP,¤ufË®ïpÇâÂÖ™k¤>Qv®Å œ7üN;•Ã{¦z™p‡*g[óªáYà°“U,-îØÙ±ó½³¹ßƒ;†W,0I«^B¾Ø%î% ¢*€ŠI“Ý~«D´ÃaY]å=@«¶ãÍû°¬‚ép]¯[×RœŠ­>ËãÝÆV ÉCYU*Õ‚ ½úÝŽ©}ñfÍÕüwرT5+‡š í±½:P®Šštç :¼ç[å9[å‚[án®ù×IÚäÁ÷/’–è0g¥€ÕõÞwQ! “µ ÅÖ©Þ*—]»¾çº„;ð[÷o9ÅvÚüÜoLœ™°ZdWÒVóÖ‹B U1qýHË©S°kMªI½C¬¸ü¦ž¯º_çòœqè ïɽ³µ¶À,Pª\q¹È½öú hâ¦ø‰ó5Ò» ðšÏ X¥‡8[P"““%ˆòñ&û ÉÞçÉë󔥬YýôéÓ«!õrò[},à³l¥SzRá€Þ:­Ô*Ærr¿ögMq‡–îžm¢¡ðAeÓwžŸp‡³hZPüÜ¡ ¸kAƒJq‡Ä*jžp‡ÅÚ&[vP¼6ÏW‹$;|NzƒÕŸ¨C¯ffZu¶-nÅÜÌNÐ(½ÅCKùÛúTeb¿#§ZÚÑh^#–›×ÌÏa0¥V­²Ú)ð0ó`-eE aV RÞ¯«‚=ÍJu`¼n¬ä>ÍRT5n•“Æ:¯ï»ýùò´OÒ•v58í`wàTðQsºz ¶ÀÆhÝ=è¥ÇX•µ…lµgkb@Q`WZ^+¤»¶V€ÿüóÏk§ÒÄUiP+“5+kò×NhÕ«Ú¡ÚTóIU¾¬|™Ê퀲Õj+cîr%, êvpì„ ìKƒPv·3^VIËwö€pniûW°÷ÚÄRš®ý“‹±òœ«Æê’-eÍêWcs‡0­Bº6š´+ ìÀ| ãìTrß59Ï]¿J6>,>œ(«®icÍiØÔ5­J`;]šð[v®¢³&­ž¨ŸJ×UÜçW!ŒÒ•M¸¼.¥£w߯W‡Ó?~üx#Yßaé=‹Å&‹i- ìwOŽæ®Õýë_OOOWõ¨ýùÉ ö-Ü!(wXȪʘ€GœÑÿ/îp>â{pGç©Zì9Q4ánÑò„; 9á‹*&<Ä‚l;Ñ÷p‡ï^ÜQÚ`qG‰ïÅv¥îáŽÅ¥’‹Õª2ZܱgÂ&°î‹&_Ú',îëOø¿ÁJAßÕ{výœp‡Ý ­½©M¶Ëzw”9áì L›âï©~R'Ü!þy wgfä>äÌþ×FÕÛöì²® °+çg%În‹ª?ëÅ,ÛEa€­Ã´‡ö®ÝàÖŠª¾ ëÖTöÂÍ,=È ÚT*OÙ—á°¢I—ß'w{x¨ÊmzÐêÕ`…Zúj8ÎìúUACúfÕK¡ñ¤D»†ˆrÂŒ¶`í&œ¸ûVt„Ö—äÇ_¾|¹ê¥ïûÔ»ïû–vÕwmÕÌ–©\])hû»R­Ì–†a%©"Ò.ÚõÚ~ZW£2ì;ô”¤'ìg@uæÅµm·¤•¯ò™[±Y»Ùj{°ƒ©ªvY”YÀ5‘Qô¡&‘¼6FÔ»~Û¦í¹K÷wõ­¨È€Þz7¹§êQ xˆsgíÜÖfz4‡?;D­I­ÉÛbø©ºoRZ0ìç×]Ú¤²2æ»çʲZ˜sVHHcÉ>{ç–3*Œämïî÷w. 6c±9²*Ú)7¦Hc¤¬²*€³ÓnR{¢ ò;¬låX°4¹VÁníìZM.¸“bY'yi©&‹]*Õpº¸Cpuw8wc!c>:'Ü¡]À=Ü!µ´~<'Ü!Ö™ §ë¤J ïáŽRëTi¥É„¸còîX7Îgrw,V)þaÌ´£~ÂûsM =ö³+ õÞŠ;d]”!b¬0Žø÷úð™ˆ*\òáÇkR¿w=€î09òlñ]wlž»Í…ÉT‹Á\{ÎJ¾…;N³äÅvó·´]8áÓ¾wر|%ÍlûÔFß \†·ƒÙŠ›V«èƪf)µê¦ˆí!84-¿VÉ>5ßuà®yÒ‚÷Úá&j{)êá«‚³Í,ÅÆjÉ6£•*ï_`mõO‡tß…sûüõÏŸ?ßÈóªÎR«LnNŸŸ*}¶VOŽò.:Æ KUóðòYjèj"8>üÓÓÓµ*h°³SéØÊGË5m5ÑäÊÊÀžs‡Ó[Q[pÚ:qŽÃdC™×œ.è(ÿ*¥Ò¶¸UÂͶtŽÄà*wØ|ßRœÛ[ÏÏÏ74GÛÜþÏJ] i!òx·/—Ë«DÁKé›õD±kà~= ,ž$•= í[3o«Ãt¹þU’ ê>”R²g ô»É•´V¯¿kóK›*Ëøè,‹`¨f‘Ò"MÂI)ÝѤs÷5@îŒ_Í-;È>°jòé`ÿΩÑ{¶Vâ­º:Ka!Fµ·ÄWÖëÙ}m]­ ¶}¤©gœÅ’hÏã´k\PãšÞ5V*½\t+Øõ”x·"^J´~#{~J{kÌ]¡šÒ¶«æ´ï^üò|=uŒZ˜(î97Û¸ïºwHÑ2Q¶+p»'…–|ßûœ©—w½;ÄK5f¶Û-½j××x=M,@ÙAÓ0ò¯¿þºÁU…sx†»‹;–4ÕÿêŸâç›ÞÂâ4Öí(-Éw|üøñáùùù*¾àY|wT}k×­Áñ[¸Ã$ëî°“Öbž¸Ãòvïw>o­žsM`v6ƒÄÒÙ4>Ý^‘RÜ¡¹ª]Ó]×M2#½Å6«Õ£ªûÔ¼ÒƒF0½ ´ÆVÈ,‡¿ÿͺ+õ·4Ü2Ép#{hZÕ[5¸šÕù7as¶»õH0ƒo"SùÂVŠNó.j²WùËÇkYàªS« ËÀfÕ¥2«j‰WaKþç©ÕÖÊ™v˜ßà2 ½àßéüìòx•¶¶’d•Ü |çW\P¹FÚyt(Ó.\ÚηCjKµrƶǦ¬1©É³ëË÷äp¢‹UÁ«²­‚E¿Â®i,ç,¬·óâµïZVý\ÅË ¡àÈê <ú*‚E‹(•¿gÚjr;Ìv=÷Ü×±ÛØ=Ò¹7¹ØuøvöGO E!*-êžñ°“n£¸€E×P}cŒ¡úZ9[U9äzžÙ_Ðk¢tc€Ý÷QAŸƒðõž06Ÿ8åÝ?ΘxXÌ0æ×Lºß{:ÏìNºWÖ©·£áýXpÏjêj×ɸ£*q]E¸ ;«åØ¢ÛCXåÌCG7Zµ¾«‰miÀ±âÓX@8ZOéf㻞ò7ÍþÛnÔ7B?‰CPz™ påƒV6ÑT¾óZŠ&0 3HÓ¸«›óï*bÎÀX!÷Ùu# Ž“8Ùú]8;!VêžàFIH=*Ak²²…&˜¾—äSàh•Â5o‡£Á½F¶XOÞ-å©:^š×ï|L‡¼;ÐJœþ%VE¬˜Öptß!8­a¦¿[0*O·3¥L´rogxûÑÃȘ!W¹s)&«•ÄÕ©ÜÃÒ9™¾·Vóó&¹v³ ²+A»ÏÚA»ß³óÓ®I|“*¯Õxë{k!I~¾ïÐ5×nš{kë­f¥ d=ê7Ñ!ZÕ®t\WÙË.dgGÛytívpÛC]•8דЇûgÕOA©ûL%=¼k[q“S’‚rW–—Ž~’ŠÝÞRÊzb;OŒ¡îEyâŽ=çP¥¬8;¤hDqñFqGÙïáŽ&¨ÅîñšzÚÙcœŒÉUÅÛsÛsíõw´‹ÂÆdcÄ=Ü!£Äõ£O‰€]:£„'Üá3èÌPg3}f‹ìæˆ; ÂïágTŽ[‚f|-ÍKj¦Ø¤ssžYb采‡k±ÎDø„;NIe¶{¸£L€ÒíìÄɪ*{â-Üѽ#Mu¸cxNªg žU½Ifäî‡VÝùé§Ÿ®ÕË™7›TÕd¥2± lKªâ³ÙÑ~ÿ×_½ÉÎ4s€j™¡’r hq¨Ë`Ó–f¥Z4\ÅÀ…°A«r˜mÝŸ’²VƒÍÎ=lÇÕäð¯¿þºn ¿J/ò¾}F;dk8å`ÜîŪ÷‰Z£L_•Äöž:ãá¡}JnvmËYùÛæPIltž~øá:úíÛ·‡Ëår„rÉ·N6¤%i–jeI_«Í£¨:´ïy||¼i›JÇQÞ|C%»MÊñÔUÄî‚×f²heµEàñªëïb%Wаƒ°©ù[mýí€z||¼Æ˜UÎz˜˜P šÎžŸŸ_ùïlýèá0cŸƒÂV™5õš#õÝjwÖ¤d\u}“63·u'-ȘkE·FeVÑL–õ(i÷h±ÏêßÎŽvHF¡³SèAf7jT0¥c¥ñšà¶›ÝDgÏ·J? º,!4‘ªêf%†Û909ñ™ú¾+; Æâ¦²¹{Î ÔÓeæ¯&)—ËåjrììÕΤÿ ¬|Îο °I½ ·Û°3p×¶.‰ÒS\“ëRŒÖ#s`ZÜá{ñï³¥mI•·¸µ½³Lðúûï¿¿Âî3;pª–y*á{Â&&$Å쬙ˆßÃû·‰]…bì`x;ËzÂ&;[wFI½ôY˜’Á2ZðÎo ,*íóÛñs¼…;ìHž¤ð-Xxxw(F#ø-Üaìzwì,“]ð½¸Ãó÷óçÏ7¸Ã½¸g6ï5ý ítwX´ÐsÂmX¼W8¨I¾gû+©EÎ:(/Ø™[^>l›XT‹։Ô*ÂA]rOÔ–:‡Ú•OÙŽ’/¾Šf¬90{/vhªäТc÷üüüðøøx®‰ûó]ÿží4ôCv£¬ÈËþý÷ß>þ|Sm´Ý_Ê¡·*®8p_®êÖÔø¶Uݺ§Âåà˜UM í9eзŠlò&`ñtm:ÇÔÊ_«ÙrcG‰°mß¡[y¼{*#Y‰‘Regi£¾›SUÑQ`VE'G û¬ØmžÄ*•óe; Jô½M¹KÀç|€ïÒj©&;»f;#¶ÀKÅ“æ pÅöÝ›ô ì:$/ø­ºïºœ%ÙûØ÷î===]«±Rm ¥Úý¬g‡ô8-ùëQ¬¬O,ÅýPáψ%ëí Ú%¶ê:1ˆR2ãM€/Û°‚U‡yÝÏ‹Êv_.—+Ý··o&41-ÝLZ_¨Ý{}=<7< «¦dÖ®˜¦•KRZýô¬[Áä°Rß;¤õ â— IkU*Ö¢„²Ìܯ”¹"²%îá©~&šÒvnœ‹îØõÚ±­éŸ¸Ã÷õOp‡q§´¢½ÛR5×U{ïèåååáóçÏWàú;d_´€³úöÏîMºü wtÀÞxU ×ßï¿ÿþðøøxƒ3ØÎ4ùŒ[ŒÕòCÍÒ¼¶ÿí¬Z0;ᎲDÞÂ2 *¯¼ç½DáŒ]ã΋W{Õôt{½C)å⎮é*7/î°€±¢„qØ=×gƃA…ÛÍãöRèáT!«¯ÞXⶉ¼ÙmÀ¶À 4Û*VÈ}7pú ì.ís¶IARêé`àðû¬P{À—“éAcUѶ<^«8=«#Ò¨(“ÿ¿J’A¼òŽfÖ‚ÌSbZp©ÎÁNò®â±bw IDATåÅúìkpè ¥A²¾>yà5Êzzzzå±dI…‡€k²NôÊn¿¨žUÿšg¹†U~iÕ¸ )‰Ògät׫ÉÁ=iy§‡à;¨¨SÅ ??ßE«iV⤥XíÛïÖÿAÙÞ*{ã.š1ïwvHŽF`@¶]Ó1‡Âê×PÞ½r‰óNä о£ªOø›D–n¢¢T‡ÇU Ú:®‹y» õ*YUËÊd¿¥*|°Ïßçm­«Š´{)ØîP¹3§„Ùö¸‰oç¦*ðH£s]ž¤Í­øvÞÌ5^Cºú(Y¬ ò8ì'5–u vŸÏÏÏ7{Üçk¢Y9sƒt»À{gº ïÏv­•€U ª3ZÛ£Mzl;¸©=»½?;gV}¤PTb|Z+Þ>«7• U à4Pì½´ú´ûö`5qß¡{¹\®ûÛJe½*zˆè¼½umçjë³Â~· pû|x·?U¯RuÉnE‡·W‰uÆB Ó ¸<óÓÌa+ºÎ¥(û­÷A B··÷Ík¾EwÚûÕSDÀWÊŒ{Ûøfuëmût÷lõ·Îàš; Þýh¢VÿŒÅ'´Î^”§ÇSÎf8‡·ÄÃuÙXçùáz³àzwØ]»‡;Ü¿]sÞã[kº4GåvÍ‘m!î­ÏBÇ[¸c´¦·p‡Ýe‘Hv}ÚÛúXÒwÂR¯KùÚ>p^ì-ÜÑîê=Ü!•Ôu\6‡ÉžI¿Þg‹?ÅÎqUHBÜÑ®Ò=Üa2[ÜÑ=[ ùŠYíš5ë~å3³‹±oÛIúOå—OB'™\éHi<[ÀÊÄnIÕ•)Eþp»,•é«òš••r ö<–, hX)Àøøñã+“¸RXœØõ-+V*ÏS*Ò…]Ï®Ùa‡wm@ ,Ø–©mgé{^—CÔ“K‡Mˆ5V´5oâfeµs_&ƒ~Ÿ•yA–ŸÑù¬®•ÊîùHÙsõž=v_;P|>R-œc[²¹Î@×wV€`ÁÀ®ƒ‰µ4£ÍÉ!CÕEôqÏ+«¸jw‡¥wv¡ƒ©v€”úuÐTð1ÊŠ_‚=¿W:A²*»)½¢ê,Uh,MÍj®û*E6°¿¼¼¼ÚO3k2ìóª\&Õ± …«nM«fÔ!bgzT.*ÕÓÏp ×9Ç’údïK½sï©ìØÎ‘T˜*3ªXW‰òšJe²›¼5SõªHížå×k1àš±ƒ§p‚â'¹i烶?{]‹Ñ®ÃÆ …zzþ8;c§Ýs_šx)vâŽRLÞëƯ&Ž…Å{¾ÅûÝ¥½óe*²í:MŒŒ!ï'ÿ¢âUÃlRÜq’vî°È!#ÀîËþ½ëð¿‹;L4<ƒF쵟(°;*‰¿ûè¶s©0FqG½ˆœo| wÈ@PØ=hAJœ¬TµgÖ¿‹;Q¨¿Yq‡‰¬8´¸Ã£ (~S#ú^gc‰ñTž,‚îh!_5³ûBNNÓJ¼Êl…­4¥Vx¥™©Ïnv¼jêÜÎÐ>W bUO¾é†¾j,´€¶jUe鬀Xݱեš„ Þn‰T´Ýë>cYòæœp˜Ú*š” ÛÛáªé™¼ÿ-p«€Å€\Ô///7³55qHMê’êC[Osàýúõë ÍÈJÉ6Ç:h'x«¶¥ÃX­²Ò¶?3Yw8 j™×wzMØàáÖÝžÍèr&$UÛýîÀš'A«tR{\ë‚@uÿyª™¸\cª0É‹µÚfµÎ„B¯§FçêsaWÔn¬r¾ãp¾@ª’´‘©˜•~RÀ©d°³MVœw a,HÏ•¹¾6‹/u‹$ l]ÓV}Ö*¬ÕÝ[ðYŸŠ½k•’ìÈØÕÙ0KÑ1foÆd1ÐäEjZýŠJŲ¡Bd XVÈ¥9g9†UÛUl%íиk¥ÔN¿§È‡êR²8ÿ®Z¯‡oß¾=¼¼¼Üðäí‹×Ægç”öìþøãZ±ëOùäý³ë0á8ùj¤‡5K´˜'È6q–ê÷=¸C_ºÅ%e’;[Áï5®´ sÂVTqMŸpÇö”ʨƅ™ã:a÷¡¸ÃYq‡ï ³7Rdv‘,ŠØÅ{ wØ=ÝùïÜÞîçåååÊ1>JåkÑSŠ÷©0'îøí·ßn$ÀM$¤ÒÖ\ykòTÜõy*mŒ>yC‰;¶ÿ×é[½‡;öýZ*zŸ§_Ÿ †Å¦%ƒÝ#vq—¬ž¼o:C´{Uz»ÒóUw˜/Øñxx¸™Q²ÍÃÚ*Ã6ææTÝr±˜Ëóýñǯâ5H[ *¸ÜM|ýúõš€¨e¢¥þ6ë2×HS—yyy¹Êä¹ 4DRï^ÙE³Xyàû¬Ñ>ôK…ÁjŸ­³“¿†> AÎHWX¦{ûk àùùù ÄU‡¸ê\•Áà­…ÅVÍ•èÝóë0³tÅ8OOO×j«J„ûÒ öLw-vzG©°„³î½í[¥Áë,®pÅf¦öΖ4¼ÛAØùdAjÉl;Æug?9r× ÃófÏg÷(Ôì®s#‹£òî·æ¥<•Âlå¸2º&>®ÉËårÃîè9¹sÚD¯JM‹Û&~KŒsOR,Àê%bÒí”ÕLwqUÜ!Ðn¥3UÅ&#›aÐý]@yÂÊÒWê½Ö£j¹6Wdbe¢x¢nÖwpkس\uP€=ï²e¤šw˜`šP¨ú&xß™au{u{àîð|¨¼…ˆÐ÷Ü6Ë}‘éqÏ𵊄âr}©Ü'õ‚ûé§Ÿ¾|ùrÓMw´‹mAp¸Ã³hÏ~±PÆ‚¸c˜ßµNûÒ.š ²ëå^ßîÃŽÕ¨¾Îg6¶¾’fVªØ*îu¥ˆl5~`S‡m¸ãnܺ-/3ôáŒÃ8ÐQ¾¢´ª¾­Û@-)(P1÷rpz@do÷=R”L9å)*¿¶T>¥·¹vx©V"•Á*p™ëÕ#¿Tã(ƒ¬T;;-V |‡rK•Z´Ê·àµoïD0cÕ×î–¸U[“e[Ù«TL-Kï¤&¹íJ ôyx •¹ÕQꀽ ¥Î, µ@àü[¥«]Óußõ9›P˜ÈKí±êdpöÐ4Q©d{[Ê>ÓU‹W1Ú:ªÓ±ÄU/”¦Uß¹É%T™’* /ek²ëÛ+˜¥ßhJfc·Ò#¶¦/—˵r¾kkåµ4€­§% îtí”ê7F+ºÒŽOéU¯ÁÙH;;+=mgÏXêì¤]{FvVZw Îuîû0õvN]Gž å0YSº[ú¢y‹-DK‘†Xz‡”O»îïÅϼ ÉøüfK¢wŸvÊ-–Y<0©ÝÙn’éÞ\Ò³}c‚õîT«êf´èRÜ¡©éîy¸ãdr*}T *õT0çŒaiŠž÷ÒÅ'c[çröœí2‰;ìÌ´PÐ’ççâk•ËÄÛÿ[;ž 'Üá*-Jܱ5 Òi㎸ÃBԾݸâ֞oq‡5‹âìŠ;LRÿÄb1ÓxU:«½A;gÛ3›1rŸ§‹;¤k¿…;ŒÍŽHˆ;,–íýÛ-*î(]·É”‚WËî·áöro¤Uœ©šC˜Ÿ›ÒA<œЛ‹3‚e+ÙìC(Ÿ²\Wÿ®r…Jó)ÐNEƒ¥Ð ³…`·kèÀä6¦×â³CA½(-Es#Û¶t¼—Èœd’ëo¡“³[tMî°8r’æo’öî°8&€wØÉw·;TQ,îpDa!×dÝêMdN2ÉèÆí÷pG}—Œ¿…;œ›:_×´ÿT†îØú¶[ª‰¯ Š”içoÖ 5¾TÊ88öÃpÊr©_îá‚;|oá㊮ÅÒ컦]{æ7ÉŒþVîT…Q¾·©^*•nÜØK¶ÚïCíì€<>+¨íÄ8ÜÔVr®U êá#¸’Î5ª˜­MÿÞ®U‡û$¾4å} ¦rsвÆkÎV´à&WÉLàfÅEÿƒ•ÔµŽË¸5vÚ÷~±jº¤¦IÒ™öç:àúþK2p m]Œö.­fɵzTGïäRLz°Ö+@ÉÇ: {í¾=¼E•N˜Ëuö½9¸k²gÒaWÃ5ãÀÅ äD{í&V¢¥º?Tœ³Â¨±c«L¶\î÷­h»Ÿºg9òz²ôk±¢+7]Šœ{DŸˆux”“îÌ–IºïH`.uw•}Öb©Õ=i’VÇ­|Z%U^³’¬ °Ú|ð]ëáàð¿kÚµ%K IŠjƒž7z•Ùáj S0Á.¾aÏ›RWPuëmd…ÓäKi×&'žw¾o;£Æ͉ë]Óªµ Ü •Iu-ÙÔÃF©p‹Uõ°¨$µ3;}¥,þSÜ¡Je™oáŽ& 2jr-˜söÁxÕ¢AqÇiøÿ{p‡4=ß·€ÚëpOtîHúv¢úç˜ôœŠ$뎗.ƒ¢žK:Í¿‡;, H?w”ú]Ü¡{#O¸Cö´pY7γ Øïá‹ZîÑúï½…;\³U| K;Ûèš.î°søOpGÕRÝ÷&¨ÅÛÛ⎓ÐPE3w-×dæ?ÿó?o:(&º{0­j$BiÃ=XážUÛ(•ăÀ,Ó*–¡›XÞ¿­3«‚÷©¤0~k“ŽUï•VÆÕ«†y‡ÍPÕSÿóÏ?o†HÍzž‚2¹XPذ•©*—4œmr‡±0U’Фµ<ت©WßD­ƒ†.kó>??_Û¬‚ ‡‡g|)ÕdœY+ V¥ëY2àÜ™!š^^^®íÚÍ9¨^cERõ-×´~'Wq;;ë"ä‰;Øé`¯ë¼Á~´¤V«Mäô £/…‰õfö|Gýêý)[é3(µKu4ã†-t•Éì–ú^½f+°Î2Ù¶%®ç“àõxé\нó#ÛëëbŒvášn•í·ß~»®t>­j>—Ëå&YÛµù|L¥ @üüóÏWa„ÓŒ™HŸ­Ý3»7>)Q+(yÈ9s°¹¤Ó vŸ³})@©yž;z3¸¶¦3®=쬆»Ç&væk…±Ê¡°:Àmb%5¥Å³½[}×…ÎÎæH+Y‡ÔóHÉõ­¥/_¾Ü¬½v5·õ»ÔwìÞGLˆ?~üxý¼·p‡ÊðwtO›˜ûÎOê¢UÔ¤²×[‹& RÞ‹;T;Ü™ôîpžSJig•v ÷p‡“jåÚO¶â÷„žV*_¾…;ª$k¢¥Ï÷âéë;»NŠwŠ}Ý® ;šBI‰«‹¸{Ä$}L€¸¿ÜN€]•¤JjvMKEÙåɨT%%ºUûñݺ¦]kÛûKÈL ¬®Iw°r(MJÀÒƒS _-Á¸ÿ¶µ}Ÿ‚A’mÁ‚J8v=¼Û'šŠ¹÷¶¶ïRš‚õ¨rÍØµÛ_J\å—ï­/ÅPZ¬ÙœBMåÒ×¥êV¥;l˜°ÔµÝÙ;¿ëL«Ú£`ÊÞëÖ¯®Õ•˜µà'mƘo'HÔõ&Ÿ?~UíWaÓêrÕ´ìì9(Ͷ ÈN¢jJ|·( 4¬tÕ¢<‹kÔù=¸ãD9| wX(| w,™sÝÚ+î¨ôú=Üáópo‰;Ll¸O¸£J„>ËÑsKW4ÉóŸ{¸£ TÅ&a÷¨‹ªÍž(›{®Ÿ?¾&Úÿw”R(^ìµ[ü«XQq‡¼ª¿pÇèf&!®G±*y&ÑZØ1Z¢*ËØPz¢jÅ 6ÌïÙSiï2z-Çéìµñã=ÜáŒýÉœóè3ÓÍæ¡àв7[¬jä÷s<œêV¯7‹-=õIrÔ¡$T ­Ô›ù{0KݲãcÅÈCT°]u’N÷¥ER`Bbà/½ÂMRÕ+·u.5A~¸ŸÝ_úŠ+cMàœ Y²ç}×㤞ER5lÁÚÆÞŸ«bãý7!óÝíÏ:”m@”VçïWõÌI)Z‡5ë§b@—†e€³B®¡ß²ÝO«aU]±«%À®—ŠÉZYƒ©Ý9“(åge¨š™À߆¼Y+ÃÆ'»xšØÙ¨B¼f•%ìØx ¶“[éÜ*35iˆö9)i¯@€ýäö\×û*÷¹V*Þqø®™¡GªI°±}¡_„ ¦ûÚŽŽ×æZ±ÃSogQ\Ó‚>€tÅŠßH©;uL¤X•ZR¿$‡–õ­9ͬ)oç–”ÅÎÿìó£¼ãgéGï¬f‡°•ÕŸEª4GEÊ£?áé·VV)w´Ûà;ô™nvfk÷=Ü!eê„;üÞRì;Gé½wH/ôsÅ2WN¸C:”Z“bé¹£Œ{'Ü¡gÌ÷⎓PY8Æ|q‡Ïº¾&'ÜaQ°¸C†‰¸£òùÎvÛ)5±Ú±BÜ w´ƒj§aØ×}(l’!ú„;ì¼wx–¿…;,’*:ó¿Ášj¾…;<×ÛT°ËiÒ3Ÿ™›™™¶õl;yÀªü¢ŒŸšÜòìËy%Å™¶æ‚+KVÅÖFÞCWCÛCh‹ÒCѾ\[³K™|]^™”Úô]5a‡Áèz^ímÏZùÛ`Z}tLDæ§3ʆÁÚà]rÖ/“+´îƯù©Ïl zíJE¬2ég]iRë ª<œ­/¨J5é[Ûÿ«P Œ+ÚЊu“&ðí j ØÎ ;„l'L5®“4v“Í}þD ¬àÉ}ìc«©*¦p( ë0çîÏêáîaï È);;`UÇù¥S¤œíJl šŒ‹^gEF™YåÙ˜&˜ÙºÍÁBSùUŸ‘N°„Ý•»*#lì_’'Íäÿ´¦›9§ ÍÖ®ˆòšî¯ÒͶf¤>· <+)+õؘ,°PžW¹oi"“º×dR “}çG*¹¿{XQiR½ž[ õü¬ú’’®RÅ,0W<³,RôüLåöµs¶g±j±©1pñ£æ¬®'ç%-ؾ;áŽß~ûíÆñ„;Ã-@¼‡;¶¿O¸cø§]TÖ´¯(î0Qêœá‰²s2‰< óï³ô ZwÅAÿâ“òïÁúö w¸fN¸Ãäÿî¨Vq‡þRÅÍòÙp‡Ñ&h®m÷ygMK]<õš¥ïéÉäzVJÜ‘‚M&hdÁüîèìII÷;[ÃvTm@¸Çí®ù|O¸£Š¡âŽzÚµ“£ï¢ø}¸ã&™)¸ë.¼þf‡êX[ V+LÕêß… Lâ v¥-(_.—'Ü:³Z¡ Øì¶ÊYr:«‚¶ )­¤’¸§Y‘…çç盄®'õ…ÙõÈ¿”ï»¶ /—Ë ·ÓöÔ#ùûÎ[xïíì8”êÛþnëfÿ–:Õf•ÏŸu0´>s«`n(é:ÒmL”ü;ãNb®i©HÐn&Aþ¼U_“%©?~¼ªÀè÷.ç… åªÕîI¼U­úl?šDUNÓêüãããuŸuNªFv&‚X«sãa;÷5=¯(«LÒEê-`ç¢F”R;Í»x*Õ}â®Ï”´5+|Éy(Ûå¨W=ösÆ=;·ÈPùí4/€9PêW•à]C饣+øž«Ð8@¤9g¥¥9VøN4cs={\{K¶öloFi1®x¡`‡40»C&ÉšcZÙt/©bV[Ï4÷‘ßy:ø»¼OŸ_ª `Y_xœ7["Q5Lž]”ùz%I§ôçö³2¿wìû‹;&‰[¦·pG;¦HýóÅ0תó´Åû=-$T„øIK˜°ëf·DFÕ³v+W*îð\^ŒýøñãÃóóóÍŒS…xzþ{'Üá³mñA50`©ÿ—¸ãÔ•.øî0¾×§å„;ö¼MV ÒФ鴦ņ;œ zw,pÇî{þ2‹Û&ßâŽ*vžæõ¤÷m;ß}»ΛdFpxR (g´ªQ!0ïA”+\Õ«v[ P8î³TëK•ÓÜ<“‘íB³ÐrhåÈß{ÛxËlmýÉaí¢–¯JJU€ªväÏ[!Q¡n×°÷¡ËµxiÒ%|V•.ÖeZ ‰nÜdÉq=X?ÉüDR*V±ÐPë$©X¹‚AØÀ§>¥=I¨rÙ8ÊVüßÀ³ÃïmÕî»ô_¨Ä£U»Ê5¶;d7Fž~Õ·ü×UuÀtIr+kíŒH}Òÿ¨J)-ZœºOŸª×®ßª^뫦’‘ñKÉçv?|øðð?ÿó?7²ê3Ò#¼~÷g«Ïÿý÷Õ³ræNcWç< zßšíü‰ñ}‡R×—T¾RõÞãB¯©¬¸´ŠSÕÏáèRv:Ç$EÐNÏþ×Ù;{ÛC[_&h&Ûî¯Ó¸îó{'‹a*M®ˆ·-Psÿs:gT*™b%ú`XtœèHg)×+…Ej>E IDATm§Á.§{}Å ÞšÅR;XVa›øžÖ´Ô!‹™Æ¹÷p‡g¬‚7RÅÆr;qõгÀѳ´VÿwXH1a–ab1ÍäNóC:ëieõ¼rÈâñš¸Có]zíL¼‡;ì6T>~/#h±A·zg$ÿîYgÁë!dâ>|ᙥlôöæöï¿‹;4ˆwØq1Ø=wˆ9‹;,ô™Ô‰{Š;J§lQPŒpÂõ¢3Ù3®‹;“Fw“ÌÌY½­ÜªA¨¤ȱtqÚÂmEQjÝè5ä+ßÙCÜß]ëÔÁ)Õ¾L¶:ø)5ÅaWwìš5VÁ¥ÏÎn—ò³5ŒÚçšPÚŠ­tªÓ{iÂ熵C"ØŠWe­èL"=´T®¤ìg÷yë²UWܵӖù†•·€M:§àÁ³{UÞÔÏp.Åõb7Q>¾”K»1ÒX ˆ¥p¨V0¤ÈÀÞ­.óºIïšÖ‘Øa‹Ýªš ‹ íLî½ú\;0ïa¼µ(uB­þEM®†ëk30SGf¯S`iu© a{&œ•µ[d̓¯TÁV¾å2×4Жª‰îñ¥¥°”'\ý®”©.XcO‡¼å< ¶[¨2UÁ޽+ëJïýûû&[[Oªe ` ž¤xYQÕI¦ÎtIq0±ÜüæÖn+£Š,hjwWÏ‘>çóFÙšÿ”]¥‡Ri:ï5š“»P'ç,$mM›ìÎ+$Ðêyï«kº„ ¨xyRƒ2F÷\³;V VýÒ4~µÓÑçÈ wl-ŠYSA©Z⎚]êë²Ï?áŽÁ'ZÓ=Ü¡z§]O±Â÷öÉp‡ª©;ÅÏ'O»t;¿´ªŠwTnX€[ܨǒXË÷(îè|¸E‚Î݈;šDw®°¸cÔ ¿ÔÆÂçYÜaR]o½îPüÂB§‰à[¸côä 'Ü¡WØ wØIqÞYJŸ±UÜQ!±ÀîO*ô«ÎŒ4‘Ûòí”è ¼lÛ ®ØÎᨮ+±í~xÿÌ ‘‡ŠAÓ…­Êƒºú»^Sùå—_žžž^Ô^ÏîsÙ¸jM ‚š:¨éâWrºU ¿«æP5 Ý»$œTpö3:ÂJG³ D²­f9T§Ë»mÊ IØ-ÚµÍØ©U딵¡”¦óº[tÃ;¬:Ú‰sOÒ‹|¿û>iuV[:‹&¨®*škÈ¿_€ôñó9Nj l÷ÿððððôôtt-HWØçÞõbërëÑý¨¤¯\àoß¾=<>>ÞÐ<¤#îð03Q)eU™S)1ú?UzX…$A±—{†Æª&K®uÁ×@é¨"®Ý­•­)רÕš3ZáÖ“§žÊÒún>• n1Ê„Ò!ßúœæ±Tsîd׸]);­ÊKcð,pèü§Ÿ~º>ë%IR÷¬ÐºÖœÓÔaÛ.Âö‹…´u²õ®Øl€Ý%ñ]«‹uÛSUmÛgœÔ$'Ï]ÕLçŒÃúé‡ÒΨƒ»®ƒ9ý²Ta2ÁÒüÒÿ^ ”öìž(ý»¸C;‡·pÇh»®Q„–;wYš¡IH±Ì{¸C?“·p‡XAsÅÝÏæoÎqˆì”J¥t¾Jê”t~=;:ÞŽƒêaD;Ìn,š´ÕƒG¿- 3Å{G+ôúóî§ïáé£âŽ]˧OŸnÞ‡ç…&R01w,Ér¿IßÚýZ”w,Ö,>wø\Š;Nʘ޻Ï^ (åÎy<úÛ wxæýðÃOOO¯Î¦š³‹;LŽ;k'¶8ª™msìâ÷¢åæW]IYB’ý]‡ÄìšØvsá;Ï  ™ó);ÔTS2n ÏÉV>ÞÜ%p?ýôÓÃår¹iYK-Ó(S™O“’UhË·t°zïHpd0v¸ÍE·…¯ÌŸC»UÙòy613áÐãäÂJ|;RåXKEpÞ@‰Ãq)ë´¼ O•N¬¾+ßk¦4§mF'y»Ò…pˆR¬TXù09·ë3Ї]ËÊ7n]VUMõ8)Jv§ä.¯»¿`ÚàùÜ´ û¹ 04©Pnß?ÊŒ¼íJ‰Ú=0W>׃f…A²óirÍO³,J_ dvè8S¢O ) v–ÔTÑÈbUMÀb·GúÞ(uî IšÒî`*}Õ¤ÁNÔÖñÖ¡ürc{«}ªÔH)‘ÂeõS5¸­Ÿ)KíÌY—F¹†¶›iÜ9£É’ ÅÕßÿýáñññúš ›´ŸÔçL ^Øàþ¸èRZ¥W;¡Á«´ÎΕ®3c‡Ì5{RU¤x»³»TÃj‚£Ã¸×·ø%EtkfrÄ[v‚—|Ö[h4»½«SVäk¸§Á wTv}…Êš, í×TÖx/ÝzT]LšXé»UÄÛ{“.5Ü!Èss:+:ˆÉjdxw´›*uÛ.P1Õ wÔ Ø>Ù;¾qG)«RíÊÜÃvD[ȵcm1`kNÚWqǰ^Í?çc§[ʻŻFeä,Žu&º]>)š'ÜÑâ_q‡lgLGû³ëåü·^AvM–+Ì3M+óˆ=Ã}æår¹&AËŠ‡XØ0g¸IfJ×)ÿY7hõòè•ZžŒ‹Sá6w«uà3 T¹Gnm+ïíÓ¹M±…Z…ª=¼VÛ*`‹¸4š^‡tµš•Tú’ ¢²‘RDl+V ²òŽúpTÑI —ɬ­B©ƒkŠjäÛÝPð‚§ÑJÇg;M;K)è†Ïnɬ ò$¯¼599B‡Ÿ¥ãQXF…èZÕ^wb†h¤²Èw}(Ðçàûìž±‚ìàù@ƒÉ‚úö•}oâ-µ®ÎÂnÆVC*ï½³ÒÞÃÖô=šS¥cŽ&âv+4"çzñPO/[ã¼ï]´u³dI`(…n{µ–z(ÔõÜýc󙚼š„È÷_ŒЄPOîŸîËÒ:—dBVƒæ“ƾ» ²™“ïYg&œy8Ø=2‰/°©T¼]ÙúºX@5‘]œ*µ"àº÷(•:îyTÉüâ¯ý„;LrŒÙï/vž×î¢{ÿ$Ã+†é<¤j÷pÇÖë wÔ€òî°ãuÂ>×îp0\*´É„Éï w˜ÀÝÃÓžž9§Ù> ²2d]w,qª©³³Þ¥„-îp‡’W†;LíßÃÒë†Ûu?)‰à+ÈÔ"Âé¼µ^Ü!Å͘±ÜßÑ#ȳÁï9®*mXFOq‡¬c— ÐI®¿jµ¯’™>Ø Üœepè¯31­€T©A)ÛªüÔX« ®r¿uZ·•éaÐY“}žô¢™ýièЀ\ PyŽØd ª<È}¾Rç*±;ðä³SŠZzØ:pkp‘È_‚¢‚šjéjÒà[=÷[¬;¼ûî-ÜQƇ] =X|§>WUÿÄäþÜÑÙq‡?÷~½‘,¾õ>-þœLQ½&ȳÖwïŸâ­¤VžpGés÷p‡´ª·p‡Éyª{L)‡ùIJzº·MÌ[jçû´¦-Ò7ž® G•ëê„;ù:yæ}îhQ¼¸cCqG;)Å-ø)ðRÜa²÷üJšÙ9M¡ZÕ´úà÷À7ë³ IœV/·s¾‚¦ñ'+'m{_¥.3c+Œ¶´<ô€Zñ赺¬>Êe.ÿ´ ÜÕÞIM5ÿkÀ¨K³íb«´{8yÞ*oÙ‘öTõ+Ûó5Ú*W³4¬Jh 6mùî_»]*È@ê*);$$­`VE¤ÒÁ5+3ÀÚQÙ„€ ÷f6e°J®òÔj¶ÜJÒî}º:Ñ™ÁÑjÖ*\‡[<í±šª¬x×´ó,‚[e,­Žîû”•î¨Â’¯Îðxp­ëÒÁr%Ê++Yå6Ûî‚DA¶ó§n”ŠNû·Â«4â!9@n &ÂU¯«úÚ®qrׯèÎ÷µó«G…r¿ÔûÇCÌ„uÏa±dÕR=tœqsMûœ½¶šY*êâ°¸]YdL¨JEµs§À‰¿´8»yUeÚþY§éÔá÷Œ žÄd,$ºÞ•˜ÝyiLòœV€@]±‹»§%i©­ •™œð¬ô›Ì ïá;qJdŠ;ê—ôî0±ýÜa¢sÂÎÀÖEÜÑAî“dvºÒþöíÛÍšwÈPm¯¸GSÙ FTÑm'c‘q¾É„Ý«­éâŽÍžp‡Jˆîÿ⎪•)fd 6~®¬òÛp‡s/â©Þ]v¯‹;\'ŠùH%_ÂPÜἋ3׸¸Ãóö-ܱçì\–…E){ž÷p‡…gf‹;š‹Ø½ÜõÞ$3fµ«ZìB0‚Þf—«šY…4Àx0ÄŠUȪä²j.V"T[Ó&Iõ2°½M^ÊÐÉ$Ìà<þ§É†„ÇÇÇ«‘škz‡ü÷…úý£ éÏ"ÝË΀B5Îr[Ù29m€®ÜqòžÅ¸§Ò7åõZÁõlâµ½ }H R•3ÁÙ¾OÅž¶µ]×=À[D yè:ÔkÜ ¬ßÓ5]•ŸËårSQµC±ÄB‰qïÝ=ÓjkƒM›Ò,¸T)n`n‰†‰Â*’!力ˆHϪR“¾vÁœí©£ô©ߎþþÜ{ê ªóãƒÿøãOOO7ªVMÊ|šÒ&£M¶*‹nìnŒ´K»©§‘ KÛƒú‘UÎݘ"½¨&  Ù½­°r*žìJ/²Þ¡Þ‚™vÉ•V×ÿþûï«Qs«¨‹Á3Ö}xx¸žÇÛw›ê ™ÏÖkÚ>j|Âv pèœGq‡Ý¬ïÅ2Üûw˜)“ïù^ÜQz÷ w˜ lV©þ1úÍ<>>^GgŒÅ¥Üµî ð¾Ï¢„ç›´r‹q÷p‡8§3‰eA•Ye¼Úû^Á[o¤î0nÔÓîååå]ÜQ3Ô6>n’<¬îÂ\f¿ÞˆÔY•ºèö)`»¸*×矗 °ÍìA%W²ƒ¿•ŽÜßY)5JºÇ€ïîy‹ÒÊŒÝ.j9ãVŽë|Ûö»C´ããúž¾|ùrå0Ž¿(ZÚž™µÔµ.U’»7¯`uw§ ÑnßSgl)*V­À ØËa·[×aÒ&R­Vu˜×€Úî[):­ÖÌUµ+ŸÒ&¤”8G`÷Êß¶É5žU‚³÷ì@¯É¸ÉèÉáÜ °4¬Êw–âÚYÊU[_g¡•^?Ë*z=P¤"ê"• Â¾G+E[¯û¹Ê·rh7¢Îëv˜*¯ìµ–C/½¡³WvÉ„Æ×z4)“zҸ߸zÛŒ6bœu¦ÄÊÜÔq¬pÖñ•b Ú…è£XÜacaš?·h=ܱ{Ý3ß÷Y}Õ™9ÿ[3¯7™¹W2ÔjžÕy^ëòZ Μґ5*…h¼ÎJ¿VP@p¶ÅQ=p_ˆàXUá;$õÒÞÕÁ`éisÍvFÃJÂç’TåU¡P·C€& vÁ»@Sœ%­Öï^UWs°ò_ÿú×õ=YÝô»šÉ©´"_·ó’Z52Y’–²Ï\.—³³cS<+J&dRJV‘Q] à½YEQ§½TšòP«Ôcå•6ÕÖÚátM{øù?DÁí®gï~-ûž ˜*ŠaE}Ý(J=©Sv=Eš»ÆL$¶ç ”{5QU\ÁƒÑ꺢ê;„¿}TÑÁ‹ÅéxÅúå}{pÕçËn€2˜RkKàXòÙ¸·NžLú>”#/emkÛÂTÍE¥]–æÚùŸú¾ÔïÂï4v,áÿòåËçOŸnT÷î·†\Ï–w.Åkp°¹ÒôRãªf¥,vc´þ‚K«»ÒñvvØÝS²×dÉ¢¥s VøU;rckSÿ¢íéŸ'±€Æø&Ý&IÅ}>÷p‡&Åí¸-†w/l­[ìwXÔN+Ëá­ýïö±Š}Ògïá»zRje"œæ¨ÞÃ&;»V‹˜*Úî ­¯êmKHÛ±-îð 2F{ÿ²qMžpG»iïáïÓ÷þ=¸Ãù1¯ËÑq‡³îhWg‰‹´=csg¤]jJ¿³T ÷Þš®‡ÔM2³E¹‡¢*L5Ø¥ÔµÔ1e ­( ¤•~¶ÚºÍ04[û{ÙÊ?îßÓœ÷`5‹«rÎîm\GµÇ}ñÓ~¯H ©rÁ*žt@ÐJ¸þ3òMê.—Ë 2Û×]E{ÕO¶ •Ì^%G­tg`êæ­Lìo¿ýv= ·8¿~ýzC]ÙµZÑÑ<ÐJóÖâ@«Y™i—¸”#> °À㜉I…U»4í®¨lRðºõéÓ§éÍzr(»¹ç´ûZ uàs ªÀgÏ|‡IŸï‚áóóó+÷îQnö™&ŽVfíÔ¼K ¡ÒŒÁrÕ"=–˜{ïÊTï÷œÜ¡ZzQ““ëÒþê…±kÚêè=ÛÅ£]Ó>gï[qŤYmEꎅ‡ý½²ð&Ƭ%+Ê[½tM?<<\c›ë¾ó&òÔ·*‡iò¡,§*IÊK?8ù1¹½OeîutW B!‡pÎ7íY(»Zz«|ÿ‚>ÿÎý/pMþüù&ÖÕÃeñµtÍÆÛíOA›²°[ƒvZÖ¨oïhgÀÖôÖûxçV§ý»í­üÙu_”X•røñãLJ§§§¯«ÅØÍæîüع‡;¤þÕõÜY ­ ¤3-¦(€ îpŸ«¾º÷¿X¡·Ë®E¯÷‡3¬ÚwNߪý{¸£¾B‚Ýî°+[Ü¡òf×eqGž­MkO¸£]$Aù{¸£¹Ã{Ÿ{vRЋ;”‰VN~¸c±}gÀÎc›™îÐCæ-ÜÑY½î°ðøîPÚ~çÏiŽP›‘ÝßÞ~~oá•jUpô¼ÛÚŸ¢jqÇ0Oç+Ú#î°“ÓÐW¦™×O“"näÖê-âB0TÎÍVm¹ë‡BýÞOŸ>Ý´©[=Ù5›XÕ½³Jd ¨OZÝ{N´»¶ÚWý4°äR?9¢Ú¬ñ”Ýžù|8§¢³­]%ÁàÚâ¥6 tIM°2k5uÕv©A[0¾ƒF e+q¶T•¯Þ`t“5+BV{íh(›+Ë.ŽI†Ue“T¹©&­:ï÷uúYAÝ5z¿¼¼\ç‚ä.[}®ŠˆÁQ@ÐÃÏ áºl:v5 .#ZAT­úU‘‘r¬+Í.ß×ÏÝA7ðUó\!ßõ97á~µÒë0u©²òôM&wÆ‹í»Ã¦J¬4¶¨àœX%ŠO*w^:oæz­HÆÖ½”ùß*WÂt… I-úìÙ ìL|ºGõ1±Ã¦Œ¨]åňÊàVÑKJNÅ+ìl8¯ÖŽh×”RÒÆú­cïAaÏW“†N:ÄýÃ?<|ùòåU绾Ngí\[‹9eìZ·Ÿ¤<Ú‘‘*µ½aצŠu»Ï âÁ¼ NÏ’“Íòë&Á9”7l .7Giáö„;Zß¾ò]œ¤¸Unr¶ÁóY?«â“[ Áß‹;¤¯¸vÂƽz|½‡;ê:_ܱûÖÈw?ûüü|£†öݒÅä‰öýÒ7kLYÜáZB®ˆÉöÅŠvœ¡µ)ÓÉbŸÅ¼šVÙTuM;­Å®U)½âŽÍºÝÃõrô\‘©á@g´õÚu8V"î8&3[ØV§< Vp¬š-à”m@(}c7¸ETï “{“/‡µöl•ß=ÍþÔ¼ÎÖ ‡º*QÎÉÉí`󀋇¡ÿ–½î“6P³3ũ­ԫ‰‡€OJ@%UUò2båÉa84“IõËmµû®jÂe»y:¹bç´’:#p´p£šÉˆžßÛ3)%ÆN•fšŠAT¥ì¤2$ݬ]<Ÿ•k\×zã–nߥ[vÀÜ÷#ŸÛ!ãŠK½°Ö5­ A‹7>Ë&’«´ f¥ƒTÁ¯JIU³óç|^ÞÓi¦¬óš'·ùuûZí¬p‚q«ã&u®aÏÏ+×í©àäÛ±³ÒêšÞú}wÔ'¯"8M,-šU%Mܱ䬪ToáŽÚ?øí¤ ”Å>'ÕM˜+RQܱ.u±ßÃ몽…;*ÔÒbc‹¾> Ïß‹gþâXãšLqGgK‹;Œ!väl9áã›>m~—³XªÇÖ“Ç„´¸ÃîšRíRâ}æ}®@Åç)î°3÷Op‡…œâ tâ)² IœpÇöšÔg»žÆ¦ÿú¯ÿzøQgØe*œìn`“ò±L¯´o¢òζ÷R§ØS)ÈŠœ¼èoZôꆗ(Üäe/ZΨR€ò·¬öIuÓˆsÊ-&¾¤><<>>Þ, =ŸçççWôÁ†¼CÆÝãTB”aÔl—º²çÑJˆrÀ¶ ÷¾¥ü©ÞdEÕwéZt ¯æQ¶ÿÝXkÏ·Ôʼú‹U~tBWƵmFêÑÖÌTI¬2”ÿén+A[#£óYÕ®j‘I…üwe[·öë‡a ^ŽÿbƒkÊ{6qïøãÇ7 ÃË—ËåÕ¼ÇþÿœÔ«ûo€öUxdÜn«Ïvy>ÞœI{ë@Úý?qò˜‚ª©tIc=ñßK]YPŠ•*qVÏÁU”§Šö÷ß߈È87¸ûh7Ô™+Ò{RÏs|/;eÜÃÜ¿ÿþû (ÚïX¼PrÞ™!clçj\ï)Œ7±TuK *oá«ÎÊÝÛ 8áŽ%:âŽÎ®Ø|wüòË/Ÿ?¾Ò£¼Ê|+•©sw|øðᆚåÚQ.û„;¶nTBÜ;è<âðË~þÇ×®•Ç­•{¸C µsoïwët{}kú„;¶¯–¤š¸×Fã矾ÁeØé°(#mq£ó‡®ÁšjжFFµãå¼^•ØœU²Ø£ô³Åáâ qÅ \4†><<Üšfž¤õzñ¶¸D5Ë´M¯ Ê0õç,<¥R¨Uþ悚ÀÖŠ‡Ã[;Uh+[$—ÐËƒß  •·m’ñý•N¼O•9¶ Õ4·Óµ À×ʇ‹·T…ñ\6wèÞä¬L‡Ý:¨^SM»e.PøžFGêÚ꜌þ;ò9UÞÜ̘L>±óõöÑ•¶ÆgV¼U²QodkË*š•%OU±@à2™ÐwHªƒçI¢¸‰ó7¥¢µ½íuü¤Ô—å§Ÿ~ºr¥v¨‚U:Û©ã"‡Ýî«­h×åÖ¤žêó×´TGó®1V¼ ¤Ý³à(5_“@çž\ÒÚ3õ3ñ Ø~ûôéÓÍïWi3‚ÅT«Ô'@o§Äaq`‡Ø¯¿þz¥5 ÔM€MV¿QIN°TJÚÞõbh+ÂÒKöÒ–´pcwuk¾]+=5Vœ;1F{ˆ ú«ri§bç“¿Î5¨¬¤zØbíbôɬRúÑÉH²•W;Xªˆ™`êù¥O\}«ÅÆÑÍ€¹ŒÑÆ}qÇÓa‚âcô𓙿þ{3%]ç=*hÐ!ì¹%ARRO¸Ã9‘îXB«ÂÕ{¸cqnñ¿ ‹â•ëk´õ'îKÜáŒðΈâãŸgµï[ë[9á‡ÿßÃÒQMD^Øš–½°õ Ê›ÌâŽï¿w,á×EãUg¥ÿÞÃΓµÀvÂ'ыډtÑâyq‡EÆ“7WÕÚöçGÓÌVó­þ„œë˜î!\ IDATxA·Ù²2šú™©º)TLsÑËÅS9Äjq«›¶×ËA¬Þé&&NÎæX±ªô¤Ô}lÇ­z Ç†•ìÎÁ˜ÙJõpÃç!Ü&-©Ñ’êEmÏ–g½€¸ µ*ðÞÓÀ[Ußêž¾` yi5à’—/+5IªËÞ‘Õœ:ÎJu©ò††„ ®b±5¸ªœ ÁÙ›®™H;‹£ì§ TUå;)…8g`Å[Ū“ZLEjh ò{ ¶®é×b[×UTH@¹Ÿ;U!Yóm•±fsrìýüªy)cëÌÙÀÊÖ’ÒãVíIy’zqò6XeÑ¢ˆâ"U3*G\º…Ô,åIMÞ>~üxãya…l×°dzI¥‡µ±Õku?îY9*hu6§ÝV‹…///פÌçk¬­´¶ Ýž™ÞîA)Mžu{{¿vZØ—òã™Õx]…ªó:Ôë9PSe+¨®•Z5ßß/~)4ÑkUr\ŹíÓ5[á]ؤÍw±3öî° ]rqG=Wª ¥!©üÿ·p‡óÒ<ÇÊ °#Ý5-î(µ¬‰T»‚MM‹5¸‡;vöŸp‡]4»`zrÇ`qÇÿ×ÞÝ-×yG¦$+"*ס«ñ‘/Ñ9óQî&×$aýä¨w=ûÅÚ)'©8ET©L“ÀÆ÷³Ö¬žžžŸÇçà¥wžo¯á×þ—àŽö{Öú9ö¦ùîŠ;%s?wøœ+5~ wüþûïÜa±AÇËî0±Úûé~hß­ýÞ&¶}¬új¿·ïU×Ðâ{”×ÝÂ[ÛSƒ½yóæ¹5³ìšŽ2'›ÖÎè¬Ål›– {ù N.æ“fS}¿`Gok›þtTò ·Ì_W å`ÊÎÊjÀeÎÚ€¯¬®2¾Þw”zÇÓíµðÀh »Äò½Ÿ#Û¼ÃËA£:8GÆGɃAF€$c±Ÿ•í`4°ÙeÃï̦L¿Ó¤ìº Éžïß;KDfûãÇ™†eRg(µ_¢–…mÔºÒCÙ¤o,õØ5+P6lz,÷¬¬Æš( 0•¨ØCç:—A3ú»”_zØUs]‚A Ü*—̶I’ûJGUAÕ"[YÙš®”ІÈ%â6Þ·Jžœ†êÞÛ#b›:}«âí]ÒÙP²b=ZÆc«6•*Ñ”T÷ÝöÀh:ÑʺëÎ$vCKòèpÖJd“îŠ5aW>YIåiøhå1®Y¥+ÆZ•Ùsó¶WÏwc³l+-~Ÿ ‰òk«'ºâ©`(#l\ªü£½>ßëöî΂“-øöv-Öui2éÙ;w(cn?Œó£>wèD'îh•v¿{&@^{«3Æ eS‚öSŒwtXm+KuùÛ߉;*élŸ^ QT¢w8óGìtÂÛ¿Uw ›Ô±Ô÷sÂ,éh‘öw›ÌÕE¯¸Cì+Ö*îp?Ú§S Þ!žý¯áç :ú„;<+Ãõ|} w“†;t£4ÎÇN¸Ã¢Á w¨Ò2‘V­õ,™ñÅ—y šùµj¢ôÄf e‡–ÀÃÃÃUm9¹`×daŸë$f4uíu²êÜŽÖê¾m\2hÉR¸ v*ÉÒ©vvûì-ÞV›ö_7È‚ÃÞÛd#|uÙ襻»»g“t÷^Ü|6ÌíÏ6î vö (ö} ¢»ÞºËló,8;û¤3ÖG"ð鬓ZoÍh¹¯Zçš —]ßûô¹îç¦-vÃvÿÈäÙ@§ÃÕ˜‹‹Éå”Sʺ»ït,1I·÷À¡‚K›g÷ìëF(÷«µæÞíÀhçŽÈú9¹ykºƒ •ÐYñ1QÛš.££$H†T¹Ø4Âɳk³´ß¿$ÒffYó Lêi£¨Sëæ(ȘKïµ&*M0%|v­{ŽÎ9±¢©tÕ©Æn“¯ÝG¥Bmàn–Ö¼VdÛ Ý™/Æh™mã{WNMÉíõì첺ÎÁÌ]™“ÿßapPÊÞ’^Z/®§Åª‹@{÷8EđĆ`Å¢äVÑ·.ýcrº†s“Û“$½ƒø\Ü ZÎwêyÖ‰Våpjw´šY)²>¾ˆ;<Ç5]ªJb—=·»»»«¿_Š;¬²¾†;4Õè0èβ:º™uÐΉ•³gAyEËŽu+Y  jн»»»<›$-yËúyø ”ûí·K†ª“Œ¶ƒaeTÍhë°¶ÃÈòy­ª#Œtˆ•î!‚ÅVv,ï~ïïï/3WÖoáô_Y2eq–¼ÿý÷7?ÿüóUð˜üÀûßûÜûz|||æžuU†÷—d85ZöAiÚãããU@¶¡· á7Ð}CõÔh LtÅéðBæ§®kÝÞî×ý´Æá±M J³mÜš¶Quf&¯uns€•º%Q•¿íï[ÖvVŒ®-J‡ö=²]2¶'XUë¼&J+»¿ýöÛ›ÇÇǫĤVÕ%É'«7æ“pÙ;¹»»»XìÊtÎòÔ~l% kF–±Ô2Sg·’Fj¤{({öË9›k%{{tâÄ:…ÚõWIЮ¯ÃèLXw]{†µ)ÇÞýö±•ÚšVŒ˜Z5ئnl6y0n?ï÷é°¶ÏT¾aY¬¨£åz¶Îì?Z¼|zzº9{VêæûšH,Öí9(;ªkšÏoó’3 ©aUÛ|›îëXä:œÚó`5rϧ3·dÀMˆ?wÔP‰¹Ã 'ÑxÏBÜ¡t´Cm•Z‰;”Å<>>^>Ï>Oå—â˜}ÆiqG]°&¥ªÝ·#$ÆÄW·pÇðB“`]@·_N¸ã›o¾¹àŽõlTZÍVƒ>w,F,ìyí¼¯âÅGqGݸ>wXerüG[ Ú+³k[U\ÜQBÄá‘â"ÏÛ~øáˆ;FðÞÂëóº…;F î¿÷ïß_—·pGñ² X­§_µI7þY•Tes•Ì8ÌÈIܵ3´ÙIýªÃ¶Úˆ¦6ЮÁT¦M=wKó²kºD´¿Äá@p[„6oé¬â‚¶‰[·Küfâ ¦JWvýÑ–ñ*¿kã]'/ipQXÕ± Uù“Ô–±·ˆ•ßÔÚód©«\clÕ€x©ÚâºúÈ.yZrì,å4½>2Ÿ›vÍ–Êí )Ø©÷»»vŠJÂdydïä§æZ¦Ù÷eÏ”Œ’X V§æFuÍÚ+õ«Ý¥Ã%÷t‡³D\ãÌölÍnMëàÓJƒrmÒÝãgçG¸>lü}ÉÎÕdÏ^`íAgÒz²¤WîÒ9:5“(ã/«Ø>+5'pŸ[aQèðľ{oYÏ7Ÿ`@™—IŠLd7­eÑßc‚j’h“õdgkHvr}5ö:ZÉ"ÏEo@kÏbÉiYbתò ŸwïÞ]í¥'gJN|ÿVKïž3{Æþ¯ý3µY¾…;\»¯á“sq‡qo•Ò’_âŽ:þUö­¬ª¸£.˜Ÿ‹;´ko?žµdª} Ÿƒ;jìSÙ©ûtD¦óÚHï{%pÄþ^M†Õ¶O¸£NrVt¬œ~ î¨ÚÃó÷Kp‡çM×è whþ <^Yêp‡Ä˜1ÙDO÷NŸä‡kº¸£DHãþk¸CÒª¸ÃÈ};Œ\ÜaŒ’,³÷ªvÙWÖÌÛ`Û0.@mskÕöY±CϬ,TdŒ·é—½\TûšF°sC,Óv>F}ì—êÀäîtד¾½S§í‹hì™(¹ùî»ï.v¥–eUöÜ”Ød)#(³§;e~™ÝÊ6¶˜6ÄnïG;åU ÜÐËœmp`mc><<\±4&¬®Ae‚;%K.\kh]_VM«ë›ÌŠï@VAࢠJ»Å‚Áýì€ÈXóMówÊ6éÚþñp¶wÀõúáÇ«ž0}ó=µîµk< Q`™\'1+6s¿jųsImâ”,˜,§²-+¬2mM˜$i¶Ç÷ÿý».2¡Ú÷Öwß¿óg2$[î~°ºžÍ±Q&e%Bö®ÕYÚÎ…h2Ù¦yØ:a|ëvÙª-‚ ã¢&0ÊÛgWâLÀ^ «À‚}תäÛ×ÑD«Óê5Šøõ×_/ìïžÃÝÝÝCê:\2ºûq>ÙöØž¥£ìs´mmzÞ ˆVµcÜË[3J2u j“³,#±e] ëuŠ}=çw–ùl‡;š°VŠ-Ž‘œwÝYÕsžb´×äºÐ)³MþÚtÛ“.h?‹Î~%>ÄÒžYâŽUÌŒgž-"œp‡û©ýËö’ÕüÊšy ²ß¸2íÀ³®+» ™UãOMÆê>·IZñÙÃØi Ð êñññRs"¶ £¥@%Ä–]ê°TKZg´´iÙç¡Öó4‘u‚®Hzw{í²ÓZò!ÐDØœ¦Dz²³a OOOoîïï¯æTl¶‚=&+azKJ'1Í_BÒᇇª£žì§rL¥DÕŽoɘ٠kUiëo‰½ò¤ZTïýïž¶¾ .»P?õÚ…ïÝL?l¯Ì®×^™@eIï[/>sgtÚtÃÞ‘§Y^Y¡Î xm†ˆ¶¥V3v/{ÎÊN•Ù«kŠLÿd&cïß¿¿~Vó´h×n³l«1R¦}ïB7Ç}¶=­æ peT•GlLª¡¥¦±¡Ÿ¾;ºV%íÁÛþhã°ñu‡¸I™UËßÿýÍþç^*eKMô{·“û¼ÇÇÇ«sB}+:öÝ”0Úší$tAüîÝ8%3i»÷k²fò¬±‹¶µ®›Îl3ñòü[¯ÊȽņõ¨ªRÐr{÷9;`«YÛ?ÊÆŒQ&V¦,Ëu¶>)Œ2!qÇöøÖß~¸ÃsV÷«6Æ¿†;¶gœ»QÜ!)èsßž{xxxóã?^>¯óí:Ï£î›íåØ3·FÜarh¬·ðÔk¥EÜ!hÏi6ŠÅÎÙ1¹6y9á•:{‰;&_³5`ï{f ªL6¯ÅÄx8Ñæû&&£âÕ,ÅΔ¨< i^’¯õîh…äîP67œ\÷ýî—p‡ÄÚd}žuÎ3FJžö,%QN¸c몸Ã=^ÜaKËEföÓO?]•òÛ±ËOOO¶y P=e%K{ö88¸MF£c‡Ùé>–_‹OÝL:黓¤Íe ÝxïÞ½»µ+UšbYrß3k½N¿ 8@ÏæÂJ‚:=öOúÓn\›k7”Á}v[|²¾²·6ÖvR­ ¯CiL§èÖmK–cëÆÐýn=ô;„mn޳ݲofŒU]:zh½hãá ±'·!Y›ßöyûÌ]·®qÊ6øíé©k”¶”"ÔýdžsçB´¿Æ=6=yF%3&®ïÚ®v>Àh×WÍu§=»–¸ê¸e¥•6œ˜ %“<˜Ü<<<<"¸g´Q"Â^#‡ƒ ‚¦ÔE#™^lì¦3Ûºù1uTk¿…–Ï:»-1Ûg[1Ñé¼ eÝÝ£³äzQg­d¦¶ù‚»6¦Ë¬ lYÇ“͹Ê¼ÚømMÝ~œ'âüeVÚ o]úlµÞ¾°"ú믿¾yÿþýåí[m½no›Ø× @âÁêâ>KùyãÈöFMk$5OÉW+[c&öâŽÇ,îØ™¿äm€±cÖãããÕ9Z‰Pgªé¾wÂ[ÿ:¡Ý®gêôl¶WcäI¢ÊHk-Ð× ¥¸ck½hð9¸Ã{—Lh_› úîðœÒ<Ã9lî±ñÿî(^ðK,¹DWÇ[qGŸ¡ÕÚâï9îŒÙ¯¼KœqþîûÙ÷LAcœ«Ü¾²5zÑ´Èob- ™îè÷QqÇÈe{>wq‡›Å&ÑW=3Õ˨v¤‹À‡Ûùê·ë[­öV&Ìþ€Ðqx¤×jéKp`ã¿Î‚ çøBvÀȦi½Ÿ˜l1ÞšÃàæv ¦Ï·6µ« Œ¥œ ÔØˆß’>×-›š ¸c'M𴛞ËX-gÓÿÞQoÜhVñ K†½¼“}èÀ‡€Ée°¼…‡Ž=6¶hIZ©‘6 ¨ìàd3Ûýer«ƒÑ€ûU•ºŠ(ƒ+©P7ÝoöüL8Ý74:[uB°ƒìlì«G}¥ Zq6¶§Í˜â𶫆Mp:¬ Óùaù{‰‹•˜œSrÑ$¦=6VÜÿ½­¨ù=•ju(ª‡«}(XnÅkë@Y”@߃°‡—²TÁÙ­çЃ:PY1oòbE¦2• žIVÇ]×˳™¹î?V3ìùò=Ù—¥E¸ÕÏ]ƒVØ{µ'C@PëdYŸôðîçŮݟg˜ì¬=ºJò´/ïspÇi~Ô wœæËY-îØþ×yÐ~Çâ¬ß£•½gŒncö—TÑR—'ÁõžÙÀùk¸Còõ%ÜÑx4òAuNÝþ¾w,¹Ry!jŒÔvŸ;¢¦3Ëì²ZéÐÊâeMñmôwì{vJøÄMíW9áŽqˆ—í¯š¡rȼwÍ餩1ŽsÕþ(î,wh&a_•ØÞqmmüó]éövt3³¯-cbÕSzÀéþâÒ)¬Æ¼¿«m¡?³ öîÝ»g%:+ƒS}ã}Á#_¤]wˆ–³-yVî¦[?Òþ}¬‹e\ŽÚ_¯ŸÂ£Õ’2!Nus©Kš½n^«M&%~¹`óYµljS^WýΨí¤ÊÍÆ²=Ë­iuÅ•£©©=äa‘ý}eµ±{²J]ƒÊØk°``Ò6ÔdÉCS¥ûÐ5&£X à¡Xy¢Öçd³ý§…¦6”ÚD ˜­BÖ…­¶écc• ì~dÑ•1M^὚ Ÿæ9Ô JÉŠzúº/š¼µyÜd¡³Ut3ë,6º†z¸yÐî?³}ö@iÝÿViéÚqýÖáOÓÁ[›l‚ç1(ôKûh¥µöµ¾‡¢¿Ïçæó? &Øë©žg€×Ü8`œ5µ²j¿—ý;¯Î23N¹>Ú³×Ùf®ieOKB/LôöŒN¢}H“êÌØŸÙ¾s`µ ÊaÔVª¶ÖMt•ªyŸ&༅;”÷w·º¦Ý‡}¦{_‚;:åâ«–V¼:¨WÜ!1éðä—pdžZµhkƒ=Ü!Øõl.îhc¼UB+È•~î°?¯„“¤éÞ¡ý­%•|wVÕ¬–‰;j ¡ü˽WÜ!ÙÊu-´—w´2TRÙªr{í‹;úg%°ß}÷Ýs73KYÚØÉœ,kýðáÃEÿ­‹ÄÜ.v–ŒÕcë ;Q›Rß¾}{ioc¯Ö{eÔwÈ Æ;õ·Œx‡©\¶]“ƒi3;`É e†n%£Låܺ`()QÇî3ë±÷!;d“¥ Uv@ÆÉ_‰….7ßá®u$eD êöwdÛ`[cu¥“¡nCÚ§ì¥ö¿ed¶Ö·¦µu}üøãW¶Ž9 ëª9† U²&Çö*Èpfö¨½¯4õúsô²iPÆO¹†üÓÙ{oun©Œª§’™ãšº¥í½iFa%U79›P•„ö Qj!£æ`µ2VktV4¹|zzº¬K%œ5ŠPüîÝ»ËÚs_zH k°bñ ¿ƒàJ,Ðïwj«%óîk R›Ð2Æ„¹÷d̹jÊÌÏu§s»:ˬ‰“n‘Jk¸áu)§ô}·ù½תüGÇ/+ÖáÜßO¯¯,ÎtVµœ$ ²:-$s-²‡ÍóU3„1Ô# ì ´²Ýž'Ùæ%±û,ºgði†Šý<‹¯KÞŠ;Ü—Å&Ð:Êb×r×D÷îØg=<<\%ÐÅu°RÞvÂVTeÌmh·O¡ ¯áÏšÏÅV÷úÌnáŽÎNîð|³'µ„ƒUŠžâÕÆ$qGûa÷,Ū'º¦¨uz›õûk¸£ª†}F½N¸cïpÒÉK“øîùþë¿þ뫸ÊñþNÌÞ¥ÇÇÇ î¨ó™½Câ4|çaKŸp‡ë:Z9ýÜaU«Æ[φfªUÖåg‡“ Ã@§ Å:/Ò&¹“³R‡äY®Û´dßçïêt]›£ë±€ÙCO l™³Ö{Ú:×#Ü2· ê‚öJK,A¶ÉpÉ“Î0c •¡XÂÓ·½Ÿ»û©u¥:×.\ƒ’~îN-6@ÉT-0 ¾ÕpÒwÈœú<Ô¶.0¬ŸÀžT¬4Ú³3 ¢¼Ñ!“ï4;›¸e¤•¯ì³w½bËæåd§r*›Ew/ ´ÙÛ Ìö¯ÔXÀ¸ÐÁ^ïaM«w÷„ÁÖR»²¾ÊÍŒ6jz°Ô5M¦GËbåme•è»nIŠý]{ít×ë,˜%þl›­-ëk᫳šëhN2ê™dÜÞ2W““;Ën?T¶eí îئÁƒ’>}Hª¸¦M‚7ž•Q)M>IMt T µŸ[‚²siÕéÎg+ãÞéáVOdÄmÆ7*ö]µê©jBÀï5i‘Åî4o­R'Ý,“íyd ÒÁm}·ž'öÐ8Iݽaeû5ÜÑ*Õk¸CÓŽ½_¿¯¸ÃÁ­éÅeg·p‡ókœå>{ w¸6[•®ËÛ-Ü1 ®ò6Ööì$;nᎺŠ÷ö¹{÷%Š;ÚçZÁ^¯ÓªcqGct{ŽìÇ)î(–Ñ~±©¸cŸç˜=GqÇ’®Z4·µb÷aX÷»b&ÒÆÝºWÞžñÊø5ý8áŽÝK+e#žâߣkº¸CiÞ³dfŒ€}–w-ÝÛ<>FeÍuÒPµÞ.gÎö©¤p×[Ü!Á+hÞ>P–¹}¿súááá™lºÓŠß—àÏ%Ð*”¬à›èÖpæî‰%ù#î0 Õ’ß^!“ôÅà?^0š¸ÃØ\Üa?Ü\ѼÿâŽÅ¾Æ–“úÆYaÅâfÝÚüÊiM%öoÏ’5¸69é\—•NRn%Æ—½‡mâb&»±¹–ùwû}‚-Y{õ‰Ûh[Tßÿý›ÇÇÇËܽ“Áë#¸ñå\wN7 é0Glj˜ ¹–·[ЖAu59Ép”¨s/0Ü"u|ÊÒ<==½ùñÇ/×4iDyêo¿„CP½^K‰Ú˜º‘ÝPuï°wekPG”2$Pa›e `ïß¿¿ê ["tËšxö‰ÊŒ¶žµUµœªäÆFz8V IDAT×ÍÖÈû÷ï¯*V[û“Äì^Õ­jmì»ÐÉ´9 «&M¼µîÀÐòÝzßöJo:4N‡<'YWF(¸ßç,p«ÃÞû×-gÕl;§ÄCªÞ÷4{¦î%F«X8WC6n€SÙ†?Û†îVÉ­Í’x‡Ïšr•tí°ó`uí*­XŒöž–Ð(ÃXR^[î»»»gͯ;CL¤µ( (¸SžæÁîìˆd÷ž•hmm8Ãeïtd„磦­V¹noÄ©3¥ná+ôb‡@‹;*],|f ‹¢«¬¨ ~-³Ë\ªïÞ"ØÅX®“™”…’ >¹E vl€“\N"¯S‡›Ë&8à-ÐU‹)°ßýZ.´Ñ³ºd™Jzûd¬û"½Kʵþô«úpÝNy{×;¸O Y’Ô:,µ¹ÕrÝ÷]G Á›Â[j)×ß«SÈ 8KV\2ækëÄ9 šU™een|¯ËY“ Ýßß_=ŸK‡š\ïó”­°´™ßµ­ÆöýùΖtjnÅT¯ye& [®é²SæxbãìMPÆæò¤%”öÔbÕÐJ¶ç=Œ†[îwíÛäj<«kY"•£,qTf³w#€(! y°ëX"b’UòC¼Îhu²2ÁÿöÛo¯*º»—ûûûgó˜u{—ŠúöíÛËgÔÏY}’(DïS××-ܱϰú|•̬—DæÁä ´*ÿڃҚІçr<==½¹»»»V¨ ßF´ùrÚ½lS˜%  ÜÈ+e•QÒÎ Òû6“Þ÷.©©g½Í[Kr–U{¨Ê.ûì:ØI²ºH¸d_ö{mÎ]£åÀ‡l½Í³Î°Øßk‘hâëu5ð”ýîDð={ t•Sòál€­!Á™({Yܬ»o“”νñ>tµSúÓ!Pcâ>ì185õ­²·ÞŒýÛØ7›_—¬,XÙ„¹g9m¸"ËN9  ®4þ¹eÞº;ÉH}úôéêpS ì÷éè?G-§Ë8*3‘yÝ>²Aüþþþòùöѩ׷:Rýt#Ú8íu¾®™lH²œê¼¤lσ¿UQ)erê¾#mÂíA¢¼a Ôõ¯Åþ¨ÍS½uâ½Å~Ÿ»ó†¶¦•ÖÔRõdÇ*ã_KòÆhcã·“Lç¨L‚¡ýk]µ®®dÇ÷fóì &Œùî+3Óº¾½7&U­{F{Öè¹ëÐÆ½Ž&Y&ðí©´{ w4F×HaÏL&‰ +ÂÅ,×±}:KŠ7ìñññ‚;vþ¯*¾s·ƒs•МpG“®ÊœŠ;4±¹…;öï_Š;ö¾O3¯öîv‹Kž‹Åû™ ÜzÝ»¾èÄ{qGçlÝÂI:5Š;œ'ãèí·ª*ªdPl±=u®חp‡¤ÄÖJ][]Ƈ§§§‹üÌ›/áŽõ·83Êž¥%+mUa¢Ä²¸ÃsÄ>Zey'Üa¯fc‹$çpdz93µÿ­5jÝX:ƒa¡Õ“ÃPËÚ&@Qe ºL¸˜Djߺ'³+0)À6Ù’q¬ž¯ZGŠšt¨²ÿd€~/Ó­ó6 pÎU°”ùøøøÌ®Ðl»ÓÉwÍu’RVP`à•ýP:¨ì@¿ô‚¡1z29Îëñýï½ De^ 2 D'€mSò6|'@+aОڠ`eë$ ¾º®ÚHmÒ+ûøí·ß^ú ‚U«‚îQt&Êò*ÑqŽ,T]Ö¶¦„¸`Óy&/mÜ;H¨žÖ¸TÉ•µï©qMIÜž“6“VëNU™…ý=@7î§Ž&ÍVa<€+ÛZò}v˜¡ v;”âGjƒj¢àaTû`Ÿýô½;cÄžÓ†2ë²'¯Õ»ýA•?x8šX]òžuÔªEµ ©@»ó4vø·JcoYe\ëG4K¾ô;ŒÏsÀг{J@U#ã²ãÊa$ƒ–X±Ú:ó×µÍÞEß‘îw‹Ñ6óª­¯n^UAÏA«ñ•ƒw´\X{öŒ_5µëHó‚½3I§îX¨ý±‰AÏpÉ”©¸Ã)êóu wìyŠ;Z½ìàZI`½­óîèXK_­ºw¨¦i¯Œ}ÔâŽb_¥Ìâ+…ºÎÕù±ñù„;$.%±LΊ;ÚkW‡B *V1ßWmµ¤ÊÊ ïô„;êjf¿Ëk¸Ãƒ&P«Ò„ÿY2Ó!g:MìÏ¢•% ¶ôV6bù³,°‹»‡gôVœ¼½¿·iv¾ëfPohƒ`Ý5|¤.]`lЭ&Ñg²ƒ^†rìÊîÃê™}&mžTkiBböëÁ'+î :µ©R§f|­wt6¸ºùdÛu¿2ñRÐ!ž‚¿ÏÍìÁ¾M¶û´™Ï¤Amÿ@˜‡£÷m TÛªz“yŸ‹@Ei‡ìAwÌV£ˆ•¡vy-eæ=D'¹Èè¹N Ê6Þ+Ck®6]Wù¡•ËÝ]AnA•²Sõ½}çeî5±"huÇê=x«FuκØHØ´~û±ó–´»ÜÁÔ¸UsƒN‰¶J¤Ôe?oÏÒ‰1“q«„ªÎj’QVzì¿ÚZT‚¶u©C–Õsû‘:“¡fz2þPJb¼5‰XuFbÅ=(p4þ™´™Þ^96->öÌkOšÍÈ1dðë°—»nÙnYmíŠ;çÃjÎPð+³ïBbÇ”¼ÄÌ@\7ÊÀué{ w´gqûº’A­›µÚ=áå– QÜáš[¸£3­ní÷»Æ>wÌyR²Åý(°lƒ¿Òû:šY%óy¾†;š`é8æyç:´ŠP2Á3M)S.·pG«€/á ‰â+§'Ü¡TP‰æk¸Ãʧ®×p‡v÷Ó*;*UÿGpÇpûIÒo¬Vú÷,™1ˆk÷Û„ÄÍ${acžŒåï6Z¦“ÉÞb—µŸ\G ¹±mPkÌÅ0ÀcªC— ÌÆã5@º°Ô{*w蜖ÎÝ0»ìœ"dƒµµ/ÄáLÚ4hwýú²ßßß_I£t¬:5©oã™8”}n3· ‹¾eD6bïÙµñÌwkE-æž•,úïÚ…ªnØÖ4€áaææò¹,1Ó_†b–Ю[7¸ÚýZ‡ ã»»»gÕ…VdQ9eH—¬V×­ÔóÏCV[=¬`ÚySµYu-jÛíð9ãI«¼Þ®½ö ¸·ŽÞ½{wÙGÆ; ÊòiÛiÝÎSpÊx{z쨤Á~ÁÎTh“t?}ï‹Msa¥b š,îÖ´ƒ•9ÙßàÚ·Ÿ¥MûšjÔTÂóâîîîYF]‰*w®TEòjlàÞ•ÃödÑ}ïV+¶F·1’5VÜdmTÕÕǹZƒ¥-m‡~üøñªâ5°ñÀõÔÁ›’"5ýéÿz&ÒuXÒ4`ëO“’U—D,áQri/¨¸C|Rv]© ‰¹VÍûý&¹öaZUv=u6Jå=ªLø»þ“u±ÕGcŽ1öÇWïmÏÀTÜ!ù 8þ#¸Ãï“ 0ÙwŽˆVö’VN&b,“¡âŽŽ´p®’Vq‡¸Ô½uÂ*¼³z$–ï®ÃCO¸C ܪ[ƒ'ÜaÅí„;–Lk\sYïâûî(q)éëy/î°§JÒ·HÅöõáÇ+s/ûì*Ë”¤wˆ#Ž=3kº5°nž…Ù¼ìtŠ“D@&Kç§Z³úâëÝwwwyÁcÓR¸–µD®y‡†µ¡²ýJb,Ië€aöº/Kw§f˺¯Ù—Ñ>µf ÝÄMw¨6¾oóÖ>µv€m6´és2i¶Y}¯»Ž]§MÓ²x&MÛl²Z³½îÏšð·)d=Œ– Ù.3iù¼®#õ´Üv(ªÏ×&üí¯¹éM>¨.¸“¼O’7¹Á^9”ƒ-SÕdUÕÁd2y&© 쩳5­ ê4=¼³“Ú°µÒ¦ìêŠR÷9åJd}¯&æRoï‡Ì²ày¶¨ÿRÉ̜匫ÛîÍ6&d6C*1`:hQ@?§†¼I³ýJVìûQ~T»þ9f-ñÒÖß$ÄçobЙ7Vey•ÉH·™ö4?Éê„2 påŸ"°û¤×V ÇV œ'IðÞ…ƒÛ¯©JÁ½­±‰ÕAüØT'q"ˆ9Ň}ßb§Ç’{΋2N)ái¯1m¸C·9ÙéU0ÄÚôžpGg"ù¼]ÓžS#¨ö Oƒ‚{.Ý‹GV _ÕâÖí´ö÷^K‡¾„;ŒËPuM/æýð×5äšSõИ~ wˆ‰¿PÒY {û×_Y'Ë%ƒV.O¸cëÙ= î0Y]ìH ¯¯¸cs´^Â:Y:£¸£vçKTkÔ¦~1ZKõ““°­ÅöE6†[yw´²ïšüÜÑsà*™1ÓRÖ´:Vx¾eÅÚ'vð–¼®5]tBêK­ËÙñ6ñî~œÝ!VÛD‚e5 p6¬YµÔÝÆ[+L>ºú8l´Í¿ ÜÚkO:`.°°üî¢sQYW3Zfû”y·Y–ÊéÚ–ÇžT‚cÂÒ€aö¯vV‹l¥.üÚz øVAÜp¨•DÝt'›Z5ä=•1T¶(H«å³,™}8–¯]Ó6æê‚&sg3§‰ü®Eô±-}·àä|32ÃNI…N[o[·K€ ü뇘äG)N‡×Y¶wM \'w™=Cm~u]<±Ö>¿FŸ¬Æ¬zà»Qî´Ÿ–ɵ@IŽ=2ÎzÙšV¢cïÌ­fLÁ&û]¹U6Í$± »:5îç<5ЙÌÃMÃíó«)/s¨TF‚Áäbàß)ô-ÔÙÆu¯² ™Ú7iµO錎j‹O&Ú¤ÖÈ8¥û“=Mh;ûÅóЄdI´ÊÎÈ©…쉘ٟ+a6iîèl¢&-âñ‚fuÁÛš–Iî^¼i‚4¼=&°n?šˆ¼„;ìÑO׿î“êNu wÈÂ;l|$‹#Vbì‡ñÌýÜÑy†’ލ­²²@¥cŧ^ âã®ï«²z“-q‡½ßVΊI¬Ž wŒhúRÜÑÞÍ[¸ÃäËdÃgY"Óª³}HV;÷½3o{nˆ;$÷NößK¸ã–ãž:‹sÏ’]9 eMÆ(ª­v±p¶‘Æh \¸ ëPàF›·š$#߉ò‚í–,MÀdcÔ"Û„W'£`²V}õq7@;m›qS\m‚ªUÞ $¬Tß 4F°nö3lèéV“hâ3—×òÖ†âöeŒµ{§ñ‚Éï¤j»ž:ÆÈä91]!}Ê ì>Ó g‹è^#+dEpŠß~ûíÒ¨¶ŸipªeíÞ§ ©Ã­:Ϧ̶Ҩ•æ•2øL×Þay>K©6aËVº-Qoý)OÒöôd›ki]rC9Uö™X´—CINŠ÷ݷsEs“˘d“tZ315ùÚ¾¿¿¿0}•HY­ê„äéÌg·©Ejë;oc¨jö{+Ã5©Ø=˜lìŒ)·Š®]zII©&Ù äÇ?›¼´â¾ßm"çš÷~Ê)P4¸f%Ydæ÷y•í,1îy†Yhuúy=ïTrdŸ‘ÄÒÎçÿt®l®Õ£EÞ½®éüááár¾×œÃʽã LuÇtŸË&w(4.ÖÙÒõ*1ºûPÂ*îТ½¸Ã3øî0Ñ㘄Zr­H0(¶§ÍÄWÜ¡,XÜa‡Iíp‡äiq‡çÆþmò»Úd¿†;:;Ðw©LÒÁ˜Jªub³¢Q‚ü5Ü!1´ß1UÒÎ.ûÅ+µ;%û™Ù&i'ÜaŸ“N{[“=‰;¶>náŽ=q‡?wÂí-”´ù7…‹ÄÉöø wl]öls½¶·Fܱk½Jf¶©>|øp5™ÓÄf¾ V‚G€fÉÊu–¡ÙìãU›où_IÙ¯nšÊf¹jøwè ¤˜ Ž)Ô•ÉEËèÛdв­ÎR±"5Íx]‡”(éòðîìžöÎìŒ ˜dÏdA ZÃŒrCà¼ÍeÝöó6J› ä¶@·€ ?q‡ÄŠ–Õ>ó«dFïi¨Mç[tÖ‡U0ñý÷ß¿yxx¸*ž,%µ dÓ:Ø­C”Ô,î!ÉæxÊZ¬wÃ.û/èT'+S±`¶F]µÃöɬÈ" 2JÌ,‘:Í~ ÆÀŸlådÓ–}g‚óUå…mÖTãÚ$Rö¢¿»2˜“.³î3&,uÿ8ˆ6÷¹ñ/÷Ðiâ§¹2–wۜق,Y7·ºTå>]cœv]cvvO'™Å©qÓá³KˆªÙöûN½o´ñ¡úØJW&_uorf6’uL;¹¯(O(èÁïU¹¦ÏP6¬šzÿ®úcßY'Pwrw-6wØVFWg%å8ëj/Eu÷§Y§wØ¡†Ê(ÜW>_NŠö|•u˜Ìmr¹Ï´ñH©‚϶÷³w¸õ·5íù¤T³ÍÕ“a¯Ðiˆt‡˜mÝ4´¢çíÞ{9a]@ÉCÍ#¬|÷œ5n£f*ß¿˜iBà+îP¶+ÙP[æ—p‡äÄ wX9wÄLº§uGtV›ñRâUÜQð]Ü¡äÈß¹Ø%î¨%qq‡½"5B1ÎÞ§ÑÊÚ†;ö^5GP6íY¡œÏ÷_;ÍŒcbQ+k’ Ú#‹1YOzd ÔFû\wð Øj7h¯H]/d,õ÷¨:!×CÝ÷é¿ëtåÁÖ†F7¥:g7Hû°ê¢¢þ¿ÛÊ·”y¨þøñã…u³'@—«&\&çuÙñí¬ ×ú*&÷ƒZs«“왕aÞZÞZmoñÎð޺׶‡vî=YX¬S‘Ay:k ˆVÿlÌïìƒÝÃzÜ”nŽ‘òpÞïÒñEiçÓÓÓe?Z1ÕÆW¹–N]§ùVÝ?Jì_ÑnvLó Ù^×ÖöŸÞþ®­[‡bAbÓª5MÆdëLÊ­Æ{°”y÷w)yÝïZ¿€}¾sõV!¬€ZåÌæïÙ×ê4&»¾÷¿ç£Ú$ø´¦Çì;™Z¯yŠ÷çsÞÙj•E÷®0%šï³?~üxŒÑaux5Ùõ<71² jÒ$pþœ„¤npOOO—ûÑzXòÀjÿÉP¡Òrc« Ø{Sª'îÐÅQ‡H{Ú^ÂNùœ\ÞVIDATÈ¿…;z/âŽÅÒUóÅVGì7º…;Vihßñ©×߽̄®q‰Fö.›, wô:áϱ[Ï“ûi›àÅbªVJ$á*9ÓŽÝDzÏÆ÷qÂs‘,ÁSÜqk0ç-Ü!ÁRS€öª‰QuÝÚq-éDz°é¬©½ßýŽ:ðu†—ÉèÖ¦8¨}rö®wXq´ŸÚ5ô¬gf?ðöíÛKæ<à ì¢S‡ÕËnÁZ!Ù*SVdY¹6¨2n½‰„†3ªãP›£;ÝtR‹º•W¢5#õ0lTÓ Ó6²-A;IL°ZÂwxåI»@;€ä<™²;ÓCÚüæû5£×ß¾,Ò›.üê ![s–Ie³LBedve°V•Úúë X¥C2¢&È•:©K¯´ÐàЄñíÛ·W–„em6ž/ˆøNkÇÜá›mÝõ¸nWª·Iw¿g?»½¤]­‰’þûúøûLeû;wJ9¡Xµì–íOM’ÊÙ:É~ÁRKÌ•Óe 룵lçœt&‹útEv½ïjïM&«¹—%v¯|ûí·—ÙAš²ÜšÐiì•ql­Ž=SÞ0¬Ü¶npöï9Ä5m_ÍöŸÒ™ÎþqŸ×=ÈûVQ0‰æicß«¬´öüZ/át¿Ø{ÓŠfþ­+ëV‹Ë–ï©üÔ³IÙžîŸû¹I«Rû¼{‰&mŸ5&Bû³ç‹}º‘÷ô­LÚ$½Ø#îXB_s‘ŒØ mekÏϾ›µO΂ÿ/Åž³_‚;jq½ ÍΫîð\§¸CBsg”3ïo±Ï­,Î%îÐÐÆ{ ¤îè;×§N£'Üq ²½é3´:«<^‚C€î¾´Rsj#ð}ßÂÃ’nÊ5O¸Cù¡’ÏÏÁaGj¯ü¥¸£Vè¯á1í®gU˜}ßÞµ.y·pGMÀTlþÇüÇ›oþú׿þþç?ÿùŠáóáÙ,¨ËŒL©,k~­è–÷-ÙÜZÛg½Œž€¶–-‡hüY©½%GJ‚ÜDJ•:Á¶S¶bdÏÉÉ1Mù“zEYˆÚºdNNn"ÚkZÎÞæZ³`ªk NV ™bòûúnzÊ’ø;Ç:ªE/Y»?¤q(-%Ÿ|ü]»§ ·uQf²eâêX–_–Õ&Z"%¢þ‚õÙM,Ú[Ö9J†*ý¨ª÷Pw)“ð¾sÝ·d¦duö¼-WkÐà Ízèïçï&«ÊÏü{¤x¿ç´'eåíëÚáÖ!iŒî!‡PºVµþìš.3Û÷i¢xb+= j/ÜîJ†”ã èÚ‹fL×NÍëíñ—d³:Þg]‹ÒÎYjÑáŽ]Ó6–[Etß•m-¨ž5ì€ÈžŸ åΛprºö¿•tÊПz3}žK8Ü]ÓZ¼ŽiW.tªd3;üPÜ!=í;¯ýKpG%f®1åO_‚;N±÷t¶YIýÜÑÙ+¯áã®ïø%ÜÑ‘ âŽîžýKK ÷üþÜѹ:¯áûc‹;Ä/á{Â>wˆYëXø9¸£2{ûÿ;qG÷û ‹Hª} îÐZ^õÇÅ*“\óÿþïÿþæ›û·ûý/ùËUEàÖ— ùK¿þ‘Ÿýÿòõé|éµÔ½äsöóžÿÈïúßú™¯_ÿÖôÿõõùõ½ÿóÇè?zÿ“×ÿßñÙÿÛ{àŸuÿü\ÓÿhŒþŸø=ÿLkÚ¾ž¯g›+)äßþö·7úôéÓ›¿ýío_Îׯ¯__¿¾~}ýúúõõëë×ׯ¯__¿þiÿOŸ>½ù/W¶Úñ×^^]IEND®B`‚kimchi-1.5.0/docs/kimchid.8.in000066400000000000000000000140641254252253000160240ustar00rootroot00000000000000.TH KIMCHI 8 "February 05, 2015" "Version @PACKAGE_VERSION@" "Kimchi Manual" .SH NAME Kimchi \- HTML5 based management tool for KVM .SH SYNOPSIS .B kimchid [\fB-h\fP|\fB--help\fP] [\fB--host\fP \fIhost\fP] [\fB--port\fP \fIport\fP] [\fB--ssl-port\fP \fIssl_port\fP] [\fB--cherrypy_port\fP \fIcherrypy_port\fP] [\fB--log-level\fP \fIlog_level\fP] [\fB--access-log\fP \fIaccess_log\fP] [\fB--error-log\fP \fIerror_log\fP] [\fB--environment\fP \fIenvironment\fP] [\fB--federation\fP \fIfederation\fP] [\fB--test\fP] .SH DESCRIPTION \fBKimchi\fP is an HTML5 based management tool for KVM. It is designed to make it as easy as possible to get started with KVM and create your first guest. \fBkimchid\fP launches the daemon on the hypervisor host which manages KVM guests through libvirt. The management interface is accessed over the web using a browser that supports HTML5. .SH OPTIONS The following options are supported: .TP \fB-h\fP , \fB--help\fP Show this help message and exit. .TP \fB--host\fP \fIhost\fP Specify the hostname or IP to listen on. .TP \fB--port\fP \fIport\fP Specify the HTTP port (default \fI8000\fP). .TP \fB--ssl-port\fP \fIssl_port\fP Specify the HTTPS port (default \fI8001\fP). .TP \fB--cherrypy_port\fP \fIcherrypy_port\fP Specify the Cherrypy server port (default \fI8010\fP). .TP \fB--log-level\fP [\fIdebug\fP | \fIinfo\fP | \fIwarning\fP | \fIerror\fP | \fIcritical\fP] Specify the log level (default \fIdebug\fP). .TP \fB--access-log\fP \fIaccess_log\fP Specify the access log location where kimchi should create the access log file. .TP \fB--environment\fP [\fIdevelopment\fP | \fIproduction\fP] Specify the running environment of kimchi server. Check cherrypy documentation for more details (default \fIproduction\fP). .TP \fB--federation\fP [\fIon\fP | \fIoff\fP] Register and discover Kimchi peers in the same network using OpenSLP. Check below the \fBFEDERATION\fP section for more details (default \fIoff\fP). .TP \fB--test\fP Run kimchi on a mock version that does not affect the system. For testing proposals. .SH FEDERATION Federation feature is a mechanism to discover Kimchi peers in the same network. It uses OpenSLP tool (http://www.openslp.org/) to register and find the Kimchi servers. By default this feature is disabled on Kimchi as it is not critical for KVM virtualization and requires additional software installation. To enable it, do the following: 1. Install OpenSLP server package 2. OpenSLP uses port 427 (UDP) and port 427 (TCP) so make sure to open those ports in your firewall configuration For system using firewalld, do: sudo firewall-cmd --permanent --add-port=427/udp sudo firewall-cmd --permanent --add-port=427/tcp sudo firewall-cmd --reload For openSUSE systems, do: sudo /sbin/SuSEfirewall2 open EXT TCP 427 sudo /sbin/SuSEfirewall2 open EXT UDP 427 For system using iptables, do: sudo iptables -A INPUT -p tcp --dport 427 -j ACCEPT sudo iptables -A INPUT -p udp --dport 427 -j ACCEPT 3. In addition to the OpenSLP ports, you also need to allow multicast in the firewall configuration For system using firewalld, do: sudo firewall-cmd --direct --add-rule ipv4 filter INPUT 0 -s -j ACCEPT For openSUSE systems, do: Add the subnet to the trusted networks listed on FW_TRUSTED_NETS in /etc/sysconfig/SuSEfirewall2 file. Make sure to restart /sbin/SuSEfirewall2 after modifying /etc/sysconfig/SuSEfirewall2 For system using iptables, do: sudo iptables -A INPUT -s -j ACCEPT 4. Start slpd service and make sure it is up while running Kimchi sudo service slpd start 5. Enable federation on Kimchi by editing the /etc/kimchi/kimchi.conf file: federation = on 6. Then start Kimchi service sudo service kimchid start The Kimchi server will be registered on OpenSLP on server starting up and will be found by other Kimchi peers (with federation feature enabled) in the same network. .SH LICENCE .br Kimchi is distributed pursuant to the terms of two different licenses. The user interface (located in ui/ in this distribution) is governed by the Apache License version 2.0. The code under ui/spice-html5 is imported from spice-html5 project (http://cgit.freedesktop.org/spice/spice-html5) and the code under ui/libs which is imported from JQuery UI (http://jqueryui.com) The rest of this distribution is governed by the GNU Lesser General Public License version 3. See COPYING.LGPL and COPYING.ASL2. .SH BUGS Current bugs can be found here : https://github.com/kimchi-project/kimchi/issues .br If you find any, please open an issue : https://github.com/kimchi-project/kimchi/issues/new .SH AUTHOR \fBAdam King\fP , \fBAdam Litke\fP , \fBAdriano Botega\fP , \fBAlexandre Tanaka Hirata\fP , \fBAline Manera\fP , \fBapporc\fP , \fBAnthony Liguori\fP , \fBBing Bu Cao\fP , \fBChristy Perez\fP , \fBCole Robinson\fP , \fBCrístian Viana\fP , \fBDaniel H Barboza\fP , \fBEduardo Elias Ferreira\fP , \fBEli Qiao(Li Yong Qiao)\fP , \fBHongliang Wang\fP , \fBLeonardo Garcia\fP , \fBLise Noble\fP , \fBMalcolm Yu\fP , \fBMark Wu\fP , \fBMei Na Zhou\fP , \fBPaulo Vital\fP , \fBPradeep K Surisetty\fP , \fBRamon Medeiros\fP , \fBRodrigo Trujilo\fP , \fBRoyce Lv\fP , \fBShaoHe Feng\fP , \fBShu Ming\fP , \fBToby Allsopp\fP , \fBTony Breeds\fP , \fBXin BJ Ding\fP , \fBYu Xin Huo\fP , \fBZhou Zheng Sheng\fP , .SH SEE ALSO kimchi-1.5.0/m4/000077500000000000000000000000001254252253000133015ustar00rootroot00000000000000kimchi-1.5.0/m4/ac_python_module.m4000066400000000000000000000012071254252253000170740ustar00rootroot00000000000000dnl @synopsis AC_PYTHON_MODULE(modname[, fatal]) dnl dnl Checks for Python module. dnl dnl If fatal is non-empty then absence of a module will trigger an dnl error. dnl dnl @category InstalledPackages dnl @author Andrew Collier . dnl @version 2004-07-14 dnl @license AllPermissive AC_DEFUN([AC_PYTHON_MODULE],[ AC_MSG_CHECKING(python module: $1) python -c "import $1" 2>/dev/null if test $? -eq 0; then AC_MSG_RESULT(yes) eval AS_TR_CPP(HAVE_PYMOD_$1)=yes else AC_MSG_RESULT(no) eval AS_TR_CPP(HAVE_PYMOD_$1)=no # if test -n "$2" then AC_MSG_ERROR(failed to find required module $1) exit 1 fi fi ]) kimchi-1.5.0/m4/gettext.m4000066400000000000000000000351321254252253000152330ustar00rootroot00000000000000# gettext.m4 serial 63 (gettext-0.18) dnl Copyright (C) 1995-2010 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl dnl This file can can be used in projects which are not available under dnl the GNU General Public License or the GNU Library General Public dnl License but which still want to provide support for the GNU gettext dnl functionality. dnl Please note that the actual code of the GNU gettext library is covered dnl by the GNU Library General Public License, and the rest of the GNU dnl gettext package package is covered by the GNU General Public License. dnl They are *not* in the public domain. dnl Authors: dnl Ulrich Drepper , 1995-2000. dnl Bruno Haible , 2000-2006, 2008-2010. dnl Macro to add for using GNU gettext. dnl Usage: AM_GNU_GETTEXT([INTLSYMBOL], [NEEDSYMBOL], [INTLDIR]). dnl INTLSYMBOL can be one of 'external', 'no-libtool', 'use-libtool'. The dnl default (if it is not specified or empty) is 'no-libtool'. dnl INTLSYMBOL should be 'external' for packages with no intl directory, dnl and 'no-libtool' or 'use-libtool' for packages with an intl directory. dnl If INTLSYMBOL is 'use-libtool', then a libtool library dnl $(top_builddir)/intl/libintl.la will be created (shared and/or static, dnl depending on --{enable,disable}-{shared,static} and on the presence of dnl AM-DISABLE-SHARED). If INTLSYMBOL is 'no-libtool', a static library dnl $(top_builddir)/intl/libintl.a will be created. dnl If NEEDSYMBOL is specified and is 'need-ngettext', then GNU gettext dnl implementations (in libc or libintl) without the ngettext() function dnl will be ignored. If NEEDSYMBOL is specified and is dnl 'need-formatstring-macros', then GNU gettext implementations that don't dnl support the ISO C 99 formatstring macros will be ignored. dnl INTLDIR is used to find the intl libraries. If empty, dnl the value `$(top_builddir)/intl/' is used. dnl dnl The result of the configuration is one of three cases: dnl 1) GNU gettext, as included in the intl subdirectory, will be compiled dnl and used. dnl Catalog format: GNU --> install in $(datadir) dnl Catalog extension: .mo after installation, .gmo in source tree dnl 2) GNU gettext has been found in the system's C library. dnl Catalog format: GNU --> install in $(datadir) dnl Catalog extension: .mo after installation, .gmo in source tree dnl 3) No internationalization, always use English msgid. dnl Catalog format: none dnl Catalog extension: none dnl If INTLSYMBOL is 'external', only cases 2 and 3 can occur. dnl The use of .gmo is historical (it was needed to avoid overwriting the dnl GNU format catalogs when building on a platform with an X/Open gettext), dnl but we keep it in order not to force irrelevant filename changes on the dnl maintainers. dnl AC_DEFUN([AM_GNU_GETTEXT], [ dnl Argument checking. ifelse([$1], [], , [ifelse([$1], [external], , [ifelse([$1], [no-libtool], , [ifelse([$1], [use-libtool], , [errprint([ERROR: invalid first argument to AM_GNU_GETTEXT ])])])])]) ifelse(ifelse([$1], [], [old])[]ifelse([$1], [no-libtool], [old]), [old], [AC_DIAGNOSE([obsolete], [Use of AM_GNU_GETTEXT without [external] argument is deprecated.])]) ifelse([$2], [], , [ifelse([$2], [need-ngettext], , [ifelse([$2], [need-formatstring-macros], , [errprint([ERROR: invalid second argument to AM_GNU_GETTEXT ])])])]) define([gt_included_intl], ifelse([$1], [external], ifdef([AM_GNU_GETTEXT_][INTL_SUBDIR], [yes], [no]), [yes])) define([gt_libtool_suffix_prefix], ifelse([$1], [use-libtool], [l], [])) gt_NEEDS_INIT AM_GNU_GETTEXT_NEED([$2]) AC_REQUIRE([AM_PO_SUBDIRS])dnl ifelse(gt_included_intl, yes, [ AC_REQUIRE([AM_INTL_SUBDIR])dnl ]) dnl Prerequisites of AC_LIB_LINKFLAGS_BODY. AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) AC_REQUIRE([AC_LIB_RPATH]) dnl Sometimes libintl requires libiconv, so first search for libiconv. dnl Ideally we would do this search only after the dnl if test "$USE_NLS" = "yes"; then dnl if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then dnl tests. But if configure.in invokes AM_ICONV after AM_GNU_GETTEXT dnl the configure script would need to contain the same shell code dnl again, outside any 'if'. There are two solutions: dnl - Invoke AM_ICONV_LINKFLAGS_BODY here, outside any 'if'. dnl - Control the expansions in more detail using AC_PROVIDE_IFELSE. dnl Since AC_PROVIDE_IFELSE is only in autoconf >= 2.52 and not dnl documented, we avoid it. ifelse(gt_included_intl, yes, , [ AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY]) ]) dnl Sometimes, on MacOS X, libintl requires linking with CoreFoundation. gt_INTL_MACOSX dnl Set USE_NLS. AC_REQUIRE([AM_NLS]) ifelse(gt_included_intl, yes, [ BUILD_INCLUDED_LIBINTL=no USE_INCLUDED_LIBINTL=no ]) LIBINTL= LTLIBINTL= POSUB= dnl Add a version number to the cache macros. case " $gt_needs " in *" need-formatstring-macros "*) gt_api_version=3 ;; *" need-ngettext "*) gt_api_version=2 ;; *) gt_api_version=1 ;; esac gt_func_gnugettext_libc="gt_cv_func_gnugettext${gt_api_version}_libc" gt_func_gnugettext_libintl="gt_cv_func_gnugettext${gt_api_version}_libintl" dnl If we use NLS figure out what method if test "$USE_NLS" = "yes"; then gt_use_preinstalled_gnugettext=no ifelse(gt_included_intl, yes, [ AC_MSG_CHECKING([whether included gettext is requested]) AC_ARG_WITH([included-gettext], [ --with-included-gettext use the GNU gettext library included here], nls_cv_force_use_gnu_gettext=$withval, nls_cv_force_use_gnu_gettext=no) AC_MSG_RESULT([$nls_cv_force_use_gnu_gettext]) nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext" if test "$nls_cv_force_use_gnu_gettext" != "yes"; then ]) dnl User does not insist on using GNU NLS library. Figure out what dnl to use. If GNU gettext is available we use this. Else we have dnl to fall back to GNU NLS library. if test $gt_api_version -ge 3; then gt_revision_test_code=' #ifndef __GNU_GETTEXT_SUPPORTED_REVISION #define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1) #endif changequote(,)dnl typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1]; changequote([,])dnl ' else gt_revision_test_code= fi if test $gt_api_version -ge 2; then gt_expression_test_code=' + * ngettext ("", "", 0)' else gt_expression_test_code= fi AC_CACHE_CHECK([for GNU gettext in libc], [$gt_func_gnugettext_libc], [AC_TRY_LINK([#include $gt_revision_test_code extern int _nl_msg_cat_cntr; extern int *_nl_domain_bindings;], [bindtextdomain ("", ""); return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_domain_bindings], [eval "$gt_func_gnugettext_libc=yes"], [eval "$gt_func_gnugettext_libc=no"])]) if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then dnl Sometimes libintl requires libiconv, so first search for libiconv. ifelse(gt_included_intl, yes, , [ AM_ICONV_LINK ]) dnl Search for libintl and define LIBINTL, LTLIBINTL and INCINTL dnl accordingly. Don't use AC_LIB_LINKFLAGS_BODY([intl],[iconv]) dnl because that would add "-liconv" to LIBINTL and LTLIBINTL dnl even if libiconv doesn't exist. AC_LIB_LINKFLAGS_BODY([intl]) AC_CACHE_CHECK([for GNU gettext in libintl], [$gt_func_gnugettext_libintl], [gt_save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $INCINTL" gt_save_LIBS="$LIBS" LIBS="$LIBS $LIBINTL" dnl Now see whether libintl exists and does not depend on libiconv. AC_TRY_LINK([#include $gt_revision_test_code extern int _nl_msg_cat_cntr; extern #ifdef __cplusplus "C" #endif const char *_nl_expand_alias (const char *);], [bindtextdomain ("", ""); return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("")], [eval "$gt_func_gnugettext_libintl=yes"], [eval "$gt_func_gnugettext_libintl=no"]) dnl Now see whether libintl exists and depends on libiconv. if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" != yes; } && test -n "$LIBICONV"; then LIBS="$LIBS $LIBICONV" AC_TRY_LINK([#include $gt_revision_test_code extern int _nl_msg_cat_cntr; extern #ifdef __cplusplus "C" #endif const char *_nl_expand_alias (const char *);], [bindtextdomain ("", ""); return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("")], [LIBINTL="$LIBINTL $LIBICONV" LTLIBINTL="$LTLIBINTL $LTLIBICONV" eval "$gt_func_gnugettext_libintl=yes" ]) fi CPPFLAGS="$gt_save_CPPFLAGS" LIBS="$gt_save_LIBS"]) fi dnl If an already present or preinstalled GNU gettext() is found, dnl use it. But if this macro is used in GNU gettext, and GNU dnl gettext is already preinstalled in libintl, we update this dnl libintl. (Cf. the install rule in intl/Makefile.in.) if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" = "yes"; } \ || { { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; } \ && test "$PACKAGE" != gettext-runtime \ && test "$PACKAGE" != gettext-tools; }; then gt_use_preinstalled_gnugettext=yes else dnl Reset the values set by searching for libintl. LIBINTL= LTLIBINTL= INCINTL= fi ifelse(gt_included_intl, yes, [ if test "$gt_use_preinstalled_gnugettext" != "yes"; then dnl GNU gettext is not found in the C library. dnl Fall back on included GNU gettext library. nls_cv_use_gnu_gettext=yes fi fi if test "$nls_cv_use_gnu_gettext" = "yes"; then dnl Mark actions used to generate GNU NLS library. BUILD_INCLUDED_LIBINTL=yes USE_INCLUDED_LIBINTL=yes LIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LIBICONV $LIBTHREAD" LTLIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LTLIBICONV $LTLIBTHREAD" LIBS=`echo " $LIBS " | sed -e 's/ -lintl / /' -e 's/^ //' -e 's/ $//'` fi CATOBJEXT= if test "$gt_use_preinstalled_gnugettext" = "yes" \ || test "$nls_cv_use_gnu_gettext" = "yes"; then dnl Mark actions to use GNU gettext tools. CATOBJEXT=.gmo fi ]) if test -n "$INTL_MACOSX_LIBS"; then if test "$gt_use_preinstalled_gnugettext" = "yes" \ || test "$nls_cv_use_gnu_gettext" = "yes"; then dnl Some extra flags are needed during linking. LIBINTL="$LIBINTL $INTL_MACOSX_LIBS" LTLIBINTL="$LTLIBINTL $INTL_MACOSX_LIBS" fi fi if test "$gt_use_preinstalled_gnugettext" = "yes" \ || test "$nls_cv_use_gnu_gettext" = "yes"; then AC_DEFINE([ENABLE_NLS], [1], [Define to 1 if translation of program messages to the user's native language is requested.]) else USE_NLS=no fi fi AC_MSG_CHECKING([whether to use NLS]) AC_MSG_RESULT([$USE_NLS]) if test "$USE_NLS" = "yes"; then AC_MSG_CHECKING([where the gettext function comes from]) if test "$gt_use_preinstalled_gnugettext" = "yes"; then if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then gt_source="external libintl" else gt_source="libc" fi else gt_source="included intl directory" fi AC_MSG_RESULT([$gt_source]) fi if test "$USE_NLS" = "yes"; then if test "$gt_use_preinstalled_gnugettext" = "yes"; then if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then AC_MSG_CHECKING([how to link with libintl]) AC_MSG_RESULT([$LIBINTL]) AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCINTL]) fi dnl For backward compatibility. Some packages may be using this. AC_DEFINE([HAVE_GETTEXT], [1], [Define if the GNU gettext() function is already present or preinstalled.]) AC_DEFINE([HAVE_DCGETTEXT], [1], [Define if the GNU dcgettext() function is already present or preinstalled.]) fi dnl We need to process the po/ directory. POSUB=po fi ifelse(gt_included_intl, yes, [ dnl If this is used in GNU gettext we have to set BUILD_INCLUDED_LIBINTL dnl to 'yes' because some of the testsuite requires it. if test "$PACKAGE" = gettext-runtime || test "$PACKAGE" = gettext-tools; then BUILD_INCLUDED_LIBINTL=yes fi dnl Make all variables we use known to autoconf. AC_SUBST([BUILD_INCLUDED_LIBINTL]) AC_SUBST([USE_INCLUDED_LIBINTL]) AC_SUBST([CATOBJEXT]) dnl For backward compatibility. Some configure.ins may be using this. nls_cv_header_intl= nls_cv_header_libgt= dnl For backward compatibility. Some Makefiles may be using this. DATADIRNAME=share AC_SUBST([DATADIRNAME]) dnl For backward compatibility. Some Makefiles may be using this. INSTOBJEXT=.mo AC_SUBST([INSTOBJEXT]) dnl For backward compatibility. Some Makefiles may be using this. GENCAT=gencat AC_SUBST([GENCAT]) dnl For backward compatibility. Some Makefiles may be using this. INTLOBJS= if test "$USE_INCLUDED_LIBINTL" = yes; then INTLOBJS="\$(GETTOBJS)" fi AC_SUBST([INTLOBJS]) dnl Enable libtool support if the surrounding package wishes it. INTL_LIBTOOL_SUFFIX_PREFIX=gt_libtool_suffix_prefix AC_SUBST([INTL_LIBTOOL_SUFFIX_PREFIX]) ]) dnl For backward compatibility. Some Makefiles may be using this. INTLLIBS="$LIBINTL" AC_SUBST([INTLLIBS]) dnl Make all documented variables known to autoconf. AC_SUBST([LIBINTL]) AC_SUBST([LTLIBINTL]) AC_SUBST([POSUB]) ]) dnl gt_NEEDS_INIT ensures that the gt_needs variable is initialized. m4_define([gt_NEEDS_INIT], [ m4_divert_text([DEFAULTS], [gt_needs=]) m4_define([gt_NEEDS_INIT], []) ]) dnl Usage: AM_GNU_GETTEXT_NEED([NEEDSYMBOL]) AC_DEFUN([AM_GNU_GETTEXT_NEED], [ m4_divert_text([INIT_PREPARE], [gt_needs="$gt_needs $1"]) ]) dnl Usage: AM_GNU_GETTEXT_VERSION([gettext-version]) AC_DEFUN([AM_GNU_GETTEXT_VERSION], []) kimchi-1.5.0/m4/iconv.m4000066400000000000000000000165371254252253000146750ustar00rootroot00000000000000# iconv.m4 serial 11 (gettext-0.18.1) dnl Copyright (C) 2000-2002, 2007-2010 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. AC_DEFUN([AM_ICONV_LINKFLAGS_BODY], [ dnl Prerequisites of AC_LIB_LINKFLAGS_BODY. AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) AC_REQUIRE([AC_LIB_RPATH]) dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV dnl accordingly. AC_LIB_LINKFLAGS_BODY([iconv]) ]) AC_DEFUN([AM_ICONV_LINK], [ dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and dnl those with the standalone portable GNU libiconv installed). AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV dnl accordingly. AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY]) dnl Add $INCICONV to CPPFLAGS before performing the following checks, dnl because if the user has installed libiconv and not disabled its use dnl via --without-libiconv-prefix, he wants to use it. The first dnl AC_TRY_LINK will then fail, the second AC_TRY_LINK will succeed. am_save_CPPFLAGS="$CPPFLAGS" AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCICONV]) AC_CACHE_CHECK([for iconv], [am_cv_func_iconv], [ am_cv_func_iconv="no, consider installing GNU libiconv" am_cv_lib_iconv=no AC_TRY_LINK([#include #include ], [iconv_t cd = iconv_open("",""); iconv(cd,NULL,NULL,NULL,NULL); iconv_close(cd);], [am_cv_func_iconv=yes]) if test "$am_cv_func_iconv" != yes; then am_save_LIBS="$LIBS" LIBS="$LIBS $LIBICONV" AC_TRY_LINK([#include #include ], [iconv_t cd = iconv_open("",""); iconv(cd,NULL,NULL,NULL,NULL); iconv_close(cd);], [am_cv_lib_iconv=yes] [am_cv_func_iconv=yes]) LIBS="$am_save_LIBS" fi ]) if test "$am_cv_func_iconv" = yes; then AC_CACHE_CHECK([for working iconv], [am_cv_func_iconv_works], [ dnl This tests against bugs in AIX 5.1, HP-UX 11.11, Solaris 10. am_save_LIBS="$LIBS" if test $am_cv_lib_iconv = yes; then LIBS="$LIBS $LIBICONV" fi AC_TRY_RUN([ #include #include int main () { /* Test against AIX 5.1 bug: Failures are not distinguishable from successful returns. */ { iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8"); if (cd_utf8_to_88591 != (iconv_t)(-1)) { static const char input[] = "\342\202\254"; /* EURO SIGN */ char buf[10]; const char *inptr = input; size_t inbytesleft = strlen (input); char *outptr = buf; size_t outbytesleft = sizeof (buf); size_t res = iconv (cd_utf8_to_88591, (char **) &inptr, &inbytesleft, &outptr, &outbytesleft); if (res == 0) return 1; } } /* Test against Solaris 10 bug: Failures are not distinguishable from successful returns. */ { iconv_t cd_ascii_to_88591 = iconv_open ("ISO8859-1", "646"); if (cd_ascii_to_88591 != (iconv_t)(-1)) { static const char input[] = "\263"; char buf[10]; const char *inptr = input; size_t inbytesleft = strlen (input); char *outptr = buf; size_t outbytesleft = sizeof (buf); size_t res = iconv (cd_ascii_to_88591, (char **) &inptr, &inbytesleft, &outptr, &outbytesleft); if (res == 0) return 1; } } #if 0 /* This bug could be worked around by the caller. */ /* Test against HP-UX 11.11 bug: Positive return value instead of 0. */ { iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591"); if (cd_88591_to_utf8 != (iconv_t)(-1)) { static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337"; char buf[50]; const char *inptr = input; size_t inbytesleft = strlen (input); char *outptr = buf; size_t outbytesleft = sizeof (buf); size_t res = iconv (cd_88591_to_utf8, (char **) &inptr, &inbytesleft, &outptr, &outbytesleft); if ((int)res > 0) return 1; } } #endif /* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is provided. */ if (/* Try standardized names. */ iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1) /* Try IRIX, OSF/1 names. */ && iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1) /* Try AIX names. */ && iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1) /* Try HP-UX names. */ && iconv_open ("utf8", "eucJP") == (iconv_t)(-1)) return 1; return 0; }], [am_cv_func_iconv_works=yes], [am_cv_func_iconv_works=no], [case "$host_os" in aix* | hpux*) am_cv_func_iconv_works="guessing no" ;; *) am_cv_func_iconv_works="guessing yes" ;; esac]) LIBS="$am_save_LIBS" ]) case "$am_cv_func_iconv_works" in *no) am_func_iconv=no am_cv_lib_iconv=no ;; *) am_func_iconv=yes ;; esac else am_func_iconv=no am_cv_lib_iconv=no fi if test "$am_func_iconv" = yes; then AC_DEFINE([HAVE_ICONV], [1], [Define if you have the iconv() function and it works.]) fi if test "$am_cv_lib_iconv" = yes; then AC_MSG_CHECKING([how to link with libiconv]) AC_MSG_RESULT([$LIBICONV]) else dnl If $LIBICONV didn't lead to a usable library, we don't need $INCICONV dnl either. CPPFLAGS="$am_save_CPPFLAGS" LIBICONV= LTLIBICONV= fi AC_SUBST([LIBICONV]) AC_SUBST([LTLIBICONV]) ]) dnl Define AM_ICONV using AC_DEFUN_ONCE for Autoconf >= 2.64, in order to dnl avoid warnings like dnl "warning: AC_REQUIRE: `AM_ICONV' was expanded before it was required". dnl This is tricky because of the way 'aclocal' is implemented: dnl - It requires defining an auxiliary macro whose name ends in AC_DEFUN. dnl Otherwise aclocal's initial scan pass would miss the macro definition. dnl - It requires a line break inside the AC_DEFUN_ONCE and AC_DEFUN expansions. dnl Otherwise aclocal would emit many "Use of uninitialized value $1" dnl warnings. m4_define([gl_iconv_AC_DEFUN], m4_version_prereq([2.64], [[AC_DEFUN_ONCE( [$1], [$2])]], [[AC_DEFUN( [$1], [$2])]])) gl_iconv_AC_DEFUN([AM_ICONV], [ AM_ICONV_LINK if test "$am_cv_func_iconv" = yes; then AC_MSG_CHECKING([for iconv declaration]) AC_CACHE_VAL([am_cv_proto_iconv], [ AC_TRY_COMPILE([ #include #include extern #ifdef __cplusplus "C" #endif #if defined(__STDC__) || defined(__cplusplus) size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft); #else size_t iconv(); #endif ], [], [am_cv_proto_iconv_arg1=""], [am_cv_proto_iconv_arg1="const"]) am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"]) am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'` AC_MSG_RESULT([ $am_cv_proto_iconv]) AC_DEFINE_UNQUOTED([ICONV_CONST], [$am_cv_proto_iconv_arg1], [Define as const if the declaration of iconv() needs const.]) fi ]) kimchi-1.5.0/m4/intlmacosx.m4000066400000000000000000000045751254252253000157370ustar00rootroot00000000000000# intlmacosx.m4 serial 3 (gettext-0.18) dnl Copyright (C) 2004-2010 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl dnl This file can can be used in projects which are not available under dnl the GNU General Public License or the GNU Library General Public dnl License but which still want to provide support for the GNU gettext dnl functionality. dnl Please note that the actual code of the GNU gettext library is covered dnl by the GNU Library General Public License, and the rest of the GNU dnl gettext package package is covered by the GNU General Public License. dnl They are *not* in the public domain. dnl Checks for special options needed on MacOS X. dnl Defines INTL_MACOSX_LIBS. AC_DEFUN([gt_INTL_MACOSX], [ dnl Check for API introduced in MacOS X 10.2. AC_CACHE_CHECK([for CFPreferencesCopyAppValue], [gt_cv_func_CFPreferencesCopyAppValue], [gt_save_LIBS="$LIBS" LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" AC_TRY_LINK([#include ], [CFPreferencesCopyAppValue(NULL, NULL)], [gt_cv_func_CFPreferencesCopyAppValue=yes], [gt_cv_func_CFPreferencesCopyAppValue=no]) LIBS="$gt_save_LIBS"]) if test $gt_cv_func_CFPreferencesCopyAppValue = yes; then AC_DEFINE([HAVE_CFPREFERENCESCOPYAPPVALUE], [1], [Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in the CoreFoundation framework.]) fi dnl Check for API introduced in MacOS X 10.3. AC_CACHE_CHECK([for CFLocaleCopyCurrent], [gt_cv_func_CFLocaleCopyCurrent], [gt_save_LIBS="$LIBS" LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" AC_TRY_LINK([#include ], [CFLocaleCopyCurrent();], [gt_cv_func_CFLocaleCopyCurrent=yes], [gt_cv_func_CFLocaleCopyCurrent=no]) LIBS="$gt_save_LIBS"]) if test $gt_cv_func_CFLocaleCopyCurrent = yes; then AC_DEFINE([HAVE_CFLOCALECOPYCURRENT], [1], [Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the CoreFoundation framework.]) fi INTL_MACOSX_LIBS= if test $gt_cv_func_CFPreferencesCopyAppValue = yes || test $gt_cv_func_CFLocaleCopyCurrent = yes; then INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation" fi AC_SUBST([INTL_MACOSX_LIBS]) ]) kimchi-1.5.0/m4/lib-ld.m4000066400000000000000000000066031254252253000147130ustar00rootroot00000000000000# lib-ld.m4 serial 4 (gettext-0.18) dnl Copyright (C) 1996-2003, 2009-2010 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl Subroutines of libtool.m4, dnl with replacements s/AC_/AC_LIB/ and s/lt_cv/acl_cv/ to avoid collision dnl with libtool.m4. dnl From libtool-1.4. Sets the variable with_gnu_ld to yes or no. AC_DEFUN([AC_LIB_PROG_LD_GNU], [AC_CACHE_CHECK([if the linker ($LD) is GNU ld], [acl_cv_prog_gnu_ld], [# I'd rather use --version here, but apparently some GNU ld's only accept -v. case `$LD -v 2>&1 conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by GCC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]* | [A-Za-z]:[\\/]*)] [re_direlt='/[^/][^/]*/\.\./'] # Canonicalize the path of ld ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL([acl_cv_path_LD], [if test -z "$LD"; then IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" for ac_dir in $PATH; do test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then acl_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some GNU ld's only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$acl_cv_path_LD" -v 2>&1 < /dev/null` in *GNU* | *'with BFD'*) test "$with_gnu_ld" != no && break ;; *) test "$with_gnu_ld" != yes && break ;; esac fi done IFS="$ac_save_ifs" else acl_cv_path_LD="$LD" # Let the user override the test with a path. fi]) LD="$acl_cv_path_LD" if test -n "$LD"; then AC_MSG_RESULT([$LD]) else AC_MSG_RESULT([no]) fi test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH]) AC_LIB_PROG_LD_GNU ]) kimchi-1.5.0/m4/lib-link.m4000066400000000000000000001002021254252253000152370ustar00rootroot00000000000000# lib-link.m4 serial 21 (gettext-0.18) dnl Copyright (C) 2001-2010 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. AC_PREREQ([2.54]) dnl AC_LIB_LINKFLAGS(name [, dependencies]) searches for libname and dnl the libraries corresponding to explicit and implicit dependencies. dnl Sets and AC_SUBSTs the LIB${NAME} and LTLIB${NAME} variables and dnl augments the CPPFLAGS variable. dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem. AC_DEFUN([AC_LIB_LINKFLAGS], [ AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) AC_REQUIRE([AC_LIB_RPATH]) pushdef([Name],[translit([$1],[./-], [___])]) pushdef([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) AC_CACHE_CHECK([how to link with lib[]$1], [ac_cv_lib[]Name[]_libs], [ AC_LIB_LINKFLAGS_BODY([$1], [$2]) ac_cv_lib[]Name[]_libs="$LIB[]NAME" ac_cv_lib[]Name[]_ltlibs="$LTLIB[]NAME" ac_cv_lib[]Name[]_cppflags="$INC[]NAME" ac_cv_lib[]Name[]_prefix="$LIB[]NAME[]_PREFIX" ]) LIB[]NAME="$ac_cv_lib[]Name[]_libs" LTLIB[]NAME="$ac_cv_lib[]Name[]_ltlibs" INC[]NAME="$ac_cv_lib[]Name[]_cppflags" LIB[]NAME[]_PREFIX="$ac_cv_lib[]Name[]_prefix" AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME) AC_SUBST([LIB]NAME) AC_SUBST([LTLIB]NAME) AC_SUBST([LIB]NAME[_PREFIX]) dnl Also set HAVE_LIB[]NAME so that AC_LIB_HAVE_LINKFLAGS can reuse the dnl results of this search when this library appears as a dependency. HAVE_LIB[]NAME=yes popdef([NAME]) popdef([Name]) ]) dnl AC_LIB_HAVE_LINKFLAGS(name, dependencies, includes, testcode, [missing-message]) dnl searches for libname and the libraries corresponding to explicit and dnl implicit dependencies, together with the specified include files and dnl the ability to compile and link the specified testcode. The missing-message dnl defaults to 'no' and may contain additional hints for the user. dnl If found, it sets and AC_SUBSTs HAVE_LIB${NAME}=yes and the LIB${NAME} dnl and LTLIB${NAME} variables and augments the CPPFLAGS variable, and dnl #defines HAVE_LIB${NAME} to 1. Otherwise, it sets and AC_SUBSTs dnl HAVE_LIB${NAME}=no and LIB${NAME} and LTLIB${NAME} to empty. dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem. AC_DEFUN([AC_LIB_HAVE_LINKFLAGS], [ AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) AC_REQUIRE([AC_LIB_RPATH]) pushdef([Name],[translit([$1],[./-], [___])]) pushdef([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) dnl Search for lib[]Name and define LIB[]NAME, LTLIB[]NAME and INC[]NAME dnl accordingly. AC_LIB_LINKFLAGS_BODY([$1], [$2]) dnl Add $INC[]NAME to CPPFLAGS before performing the following checks, dnl because if the user has installed lib[]Name and not disabled its use dnl via --without-lib[]Name-prefix, he wants to use it. ac_save_CPPFLAGS="$CPPFLAGS" AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME) AC_CACHE_CHECK([for lib[]$1], [ac_cv_lib[]Name], [ ac_save_LIBS="$LIBS" dnl If $LIB[]NAME contains some -l options, add it to the end of LIBS, dnl because these -l options might require -L options that are present in dnl LIBS. -l options benefit only from the -L options listed before it. dnl Otherwise, add it to the front of LIBS, because it may be a static dnl library that depends on another static library that is present in LIBS. dnl Static libraries benefit only from the static libraries listed after dnl it. case " $LIB[]NAME" in *" -l"*) LIBS="$LIBS $LIB[]NAME" ;; *) LIBS="$LIB[]NAME $LIBS" ;; esac AC_TRY_LINK([$3], [$4], [ac_cv_lib[]Name=yes], [ac_cv_lib[]Name='m4_if([$5], [], [no], [[$5]])']) LIBS="$ac_save_LIBS" ]) if test "$ac_cv_lib[]Name" = yes; then HAVE_LIB[]NAME=yes AC_DEFINE([HAVE_LIB]NAME, 1, [Define if you have the lib][$1 library.]) AC_MSG_CHECKING([how to link with lib[]$1]) AC_MSG_RESULT([$LIB[]NAME]) else HAVE_LIB[]NAME=no dnl If $LIB[]NAME didn't lead to a usable library, we don't need dnl $INC[]NAME either. CPPFLAGS="$ac_save_CPPFLAGS" LIB[]NAME= LTLIB[]NAME= LIB[]NAME[]_PREFIX= fi AC_SUBST([HAVE_LIB]NAME) AC_SUBST([LIB]NAME) AC_SUBST([LTLIB]NAME) AC_SUBST([LIB]NAME[_PREFIX]) popdef([NAME]) popdef([Name]) ]) dnl Determine the platform dependent parameters needed to use rpath: dnl acl_libext, dnl acl_shlibext, dnl acl_hardcode_libdir_flag_spec, dnl acl_hardcode_libdir_separator, dnl acl_hardcode_direct, dnl acl_hardcode_minus_L. AC_DEFUN([AC_LIB_RPATH], [ dnl Tell automake >= 1.10 to complain if config.rpath is missing. m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([config.rpath])]) AC_REQUIRE([AC_PROG_CC]) dnl we use $CC, $GCC, $LDFLAGS AC_REQUIRE([AC_LIB_PROG_LD]) dnl we use $LD, $with_gnu_ld AC_REQUIRE([AC_CANONICAL_HOST]) dnl we use $host AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir AC_CACHE_CHECK([for shared library run path origin], [acl_cv_rpath], [ CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \ ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh . ./conftest.sh rm -f ./conftest.sh acl_cv_rpath=done ]) wl="$acl_cv_wl" acl_libext="$acl_cv_libext" acl_shlibext="$acl_cv_shlibext" acl_libname_spec="$acl_cv_libname_spec" acl_library_names_spec="$acl_cv_library_names_spec" acl_hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec" acl_hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" acl_hardcode_direct="$acl_cv_hardcode_direct" acl_hardcode_minus_L="$acl_cv_hardcode_minus_L" dnl Determine whether the user wants rpath handling at all. AC_ARG_ENABLE([rpath], [ --disable-rpath do not hardcode runtime library paths], :, enable_rpath=yes) ]) dnl AC_LIB_FROMPACKAGE(name, package) dnl declares that libname comes from the given package. The configure file dnl will then not have a --with-libname-prefix option but a dnl --with-package-prefix option. Several libraries can come from the same dnl package. This declaration must occur before an AC_LIB_LINKFLAGS or similar dnl macro call that searches for libname. AC_DEFUN([AC_LIB_FROMPACKAGE], [ pushdef([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) define([acl_frompackage_]NAME, [$2]) popdef([NAME]) pushdef([PACK],[$2]) pushdef([PACKUP],[translit(PACK,[abcdefghijklmnopqrstuvwxyz./-], [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) define([acl_libsinpackage_]PACKUP, m4_ifdef([acl_libsinpackage_]PACKUP, [acl_libsinpackage_]PACKUP[[, ]],)[lib$1]) popdef([PACKUP]) popdef([PACK]) ]) dnl AC_LIB_LINKFLAGS_BODY(name [, dependencies]) searches for libname and dnl the libraries corresponding to explicit and implicit dependencies. dnl Sets the LIB${NAME}, LTLIB${NAME} and INC${NAME} variables. dnl Also, sets the LIB${NAME}_PREFIX variable to nonempty if libname was found dnl in ${LIB${NAME}_PREFIX}/$acl_libdirstem. AC_DEFUN([AC_LIB_LINKFLAGS_BODY], [ AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) pushdef([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) pushdef([PACK],[m4_ifdef([acl_frompackage_]NAME, [acl_frompackage_]NAME, lib[$1])]) pushdef([PACKUP],[translit(PACK,[abcdefghijklmnopqrstuvwxyz./-], [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) pushdef([PACKLIBS],[m4_ifdef([acl_frompackage_]NAME, [acl_libsinpackage_]PACKUP, lib[$1])]) dnl Autoconf >= 2.61 supports dots in --with options. pushdef([P_A_C_K],[m4_if(m4_version_compare(m4_defn([m4_PACKAGE_VERSION]),[2.61]),[-1],[translit(PACK,[.],[_])],PACK)]) dnl By default, look in $includedir and $libdir. use_additional=yes AC_LIB_WITH_FINAL_PREFIX([ eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" ]) AC_ARG_WITH(P_A_C_K[-prefix], [[ --with-]]P_A_C_K[[-prefix[=DIR] search for ]PACKLIBS[ in DIR/include and DIR/lib --without-]]P_A_C_K[[-prefix don't search for ]PACKLIBS[ in includedir and libdir]], [ if test "X$withval" = "Xno"; then use_additional=no else if test "X$withval" = "X"; then AC_LIB_WITH_FINAL_PREFIX([ eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" ]) else additional_includedir="$withval/include" additional_libdir="$withval/$acl_libdirstem" if test "$acl_libdirstem2" != "$acl_libdirstem" \ && ! test -d "$withval/$acl_libdirstem"; then additional_libdir="$withval/$acl_libdirstem2" fi fi fi ]) dnl Search the library and its dependencies in $additional_libdir and dnl $LDFLAGS. Using breadth-first-seach. LIB[]NAME= LTLIB[]NAME= INC[]NAME= LIB[]NAME[]_PREFIX= dnl HAVE_LIB${NAME} is an indicator that LIB${NAME}, LTLIB${NAME} have been dnl computed. So it has to be reset here. HAVE_LIB[]NAME= rpathdirs= ltrpathdirs= names_already_handled= names_next_round='$1 $2' while test -n "$names_next_round"; do names_this_round="$names_next_round" names_next_round= for name in $names_this_round; do already_handled= for n in $names_already_handled; do if test "$n" = "$name"; then already_handled=yes break fi done if test -z "$already_handled"; then names_already_handled="$names_already_handled $name" dnl See if it was already located by an earlier AC_LIB_LINKFLAGS dnl or AC_LIB_HAVE_LINKFLAGS call. uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` eval value=\"\$HAVE_LIB$uppername\" if test -n "$value"; then if test "$value" = yes; then eval value=\"\$LIB$uppername\" test -z "$value" || LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$value" eval value=\"\$LTLIB$uppername\" test -z "$value" || LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$value" else dnl An earlier call to AC_LIB_HAVE_LINKFLAGS has determined dnl that this library doesn't exist. So just drop it. : fi else dnl Search the library lib$name in $additional_libdir and $LDFLAGS dnl and the already constructed $LIBNAME/$LTLIBNAME. found_dir= found_la= found_so= found_a= eval libname=\"$acl_libname_spec\" # typically: libname=lib$name if test -n "$acl_shlibext"; then shrext=".$acl_shlibext" # typically: shrext=.so else shrext= fi if test $use_additional = yes; then dir="$additional_libdir" dnl The same code as in the loop below: dnl First look for a shared library. if test -n "$acl_shlibext"; then if test -f "$dir/$libname$shrext"; then found_dir="$dir" found_so="$dir/$libname$shrext" else if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then ver=`(cd "$dir" && \ for f in "$libname$shrext".*; do echo "$f"; done \ | sed -e "s,^$libname$shrext\\\\.,," \ | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ | sed 1q ) 2>/dev/null` if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then found_dir="$dir" found_so="$dir/$libname$shrext.$ver" fi else eval library_names=\"$acl_library_names_spec\" for f in $library_names; do if test -f "$dir/$f"; then found_dir="$dir" found_so="$dir/$f" break fi done fi fi fi dnl Then look for a static library. if test "X$found_dir" = "X"; then if test -f "$dir/$libname.$acl_libext"; then found_dir="$dir" found_a="$dir/$libname.$acl_libext" fi fi if test "X$found_dir" != "X"; then if test -f "$dir/$libname.la"; then found_la="$dir/$libname.la" fi fi fi if test "X$found_dir" = "X"; then for x in $LDFLAGS $LTLIB[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) case "$x" in -L*) dir=`echo "X$x" | sed -e 's/^X-L//'` dnl First look for a shared library. if test -n "$acl_shlibext"; then if test -f "$dir/$libname$shrext"; then found_dir="$dir" found_so="$dir/$libname$shrext" else if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then ver=`(cd "$dir" && \ for f in "$libname$shrext".*; do echo "$f"; done \ | sed -e "s,^$libname$shrext\\\\.,," \ | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ | sed 1q ) 2>/dev/null` if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then found_dir="$dir" found_so="$dir/$libname$shrext.$ver" fi else eval library_names=\"$acl_library_names_spec\" for f in $library_names; do if test -f "$dir/$f"; then found_dir="$dir" found_so="$dir/$f" break fi done fi fi fi dnl Then look for a static library. if test "X$found_dir" = "X"; then if test -f "$dir/$libname.$acl_libext"; then found_dir="$dir" found_a="$dir/$libname.$acl_libext" fi fi if test "X$found_dir" != "X"; then if test -f "$dir/$libname.la"; then found_la="$dir/$libname.la" fi fi ;; esac if test "X$found_dir" != "X"; then break fi done fi if test "X$found_dir" != "X"; then dnl Found the library. LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$found_dir -l$name" if test "X$found_so" != "X"; then dnl Linking with a shared library. We attempt to hardcode its dnl directory into the executable's runpath, unless it's the dnl standard /usr/lib. if test "$enable_rpath" = no \ || test "X$found_dir" = "X/usr/$acl_libdirstem" \ || test "X$found_dir" = "X/usr/$acl_libdirstem2"; then dnl No hardcoding is needed. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" else dnl Use an explicit option to hardcode DIR into the resulting dnl binary. dnl Potentially add DIR to ltrpathdirs. dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. haveit= for x in $ltrpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $found_dir" fi dnl The hardcoding into $LIBNAME is system dependent. if test "$acl_hardcode_direct" = yes; then dnl Using DIR/libNAME.so during linking hardcodes DIR into the dnl resulting binary. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" else if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then dnl Use an explicit option to hardcode DIR into the resulting dnl binary. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" dnl Potentially add DIR to rpathdirs. dnl The rpathdirs will be appended to $LIBNAME at the end. haveit= for x in $rpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $found_dir" fi else dnl Rely on "-L$found_dir". dnl But don't add it if it's already contained in the LDFLAGS dnl or the already constructed $LIBNAME haveit= for x in $LDFLAGS $LIB[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-L$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir" fi if test "$acl_hardcode_minus_L" != no; then dnl FIXME: Not sure whether we should use dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" dnl here. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" else dnl We cannot use $acl_hardcode_runpath_var and LD_RUN_PATH dnl here, because this doesn't fit in flags passed to the dnl compiler. So give up. No hardcoding. This affects only dnl very old systems. dnl FIXME: Not sure whether we should use dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" dnl here. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" fi fi fi fi else if test "X$found_a" != "X"; then dnl Linking with a static library. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_a" else dnl We shouldn't come here, but anyway it's good to have a dnl fallback. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir -l$name" fi fi dnl Assume the include files are nearby. additional_includedir= case "$found_dir" in */$acl_libdirstem | */$acl_libdirstem/) basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` if test "$name" = '$1'; then LIB[]NAME[]_PREFIX="$basedir" fi additional_includedir="$basedir/include" ;; */$acl_libdirstem2 | */$acl_libdirstem2/) basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem2/"'*$,,'` if test "$name" = '$1'; then LIB[]NAME[]_PREFIX="$basedir" fi additional_includedir="$basedir/include" ;; esac if test "X$additional_includedir" != "X"; then dnl Potentially add $additional_includedir to $INCNAME. dnl But don't add it dnl 1. if it's the standard /usr/include, dnl 2. if it's /usr/local/include and we are using GCC on Linux, dnl 3. if it's already present in $CPPFLAGS or the already dnl constructed $INCNAME, dnl 4. if it doesn't exist as a directory. if test "X$additional_includedir" != "X/usr/include"; then haveit= if test "X$additional_includedir" = "X/usr/local/include"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then for x in $CPPFLAGS $INC[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-I$additional_includedir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_includedir"; then dnl Really add $additional_includedir to $INCNAME. INC[]NAME="${INC[]NAME}${INC[]NAME:+ }-I$additional_includedir" fi fi fi fi fi dnl Look for dependencies. if test -n "$found_la"; then dnl Read the .la file. It defines the variables dnl dlname, library_names, old_library, dependency_libs, current, dnl age, revision, installed, dlopen, dlpreopen, libdir. save_libdir="$libdir" case "$found_la" in */* | *\\*) . "$found_la" ;; *) . "./$found_la" ;; esac libdir="$save_libdir" dnl We use only dependency_libs. for dep in $dependency_libs; do case "$dep" in -L*) additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` dnl Potentially add $additional_libdir to $LIBNAME and $LTLIBNAME. dnl But don't add it dnl 1. if it's the standard /usr/lib, dnl 2. if it's /usr/local/lib and we are using GCC on Linux, dnl 3. if it's already present in $LDFLAGS or the already dnl constructed $LIBNAME, dnl 4. if it doesn't exist as a directory. if test "X$additional_libdir" != "X/usr/$acl_libdirstem" \ && test "X$additional_libdir" != "X/usr/$acl_libdirstem2"; then haveit= if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem" \ || test "X$additional_libdir" = "X/usr/local/$acl_libdirstem2"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then haveit= for x in $LDFLAGS $LIB[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then dnl Really add $additional_libdir to $LIBNAME. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$additional_libdir" fi fi haveit= for x in $LDFLAGS $LTLIB[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then dnl Really add $additional_libdir to $LTLIBNAME. LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$additional_libdir" fi fi fi fi ;; -R*) dir=`echo "X$dep" | sed -e 's/^X-R//'` if test "$enable_rpath" != no; then dnl Potentially add DIR to rpathdirs. dnl The rpathdirs will be appended to $LIBNAME at the end. haveit= for x in $rpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $dir" fi dnl Potentially add DIR to ltrpathdirs. dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. haveit= for x in $ltrpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $dir" fi fi ;; -l*) dnl Handle this in the next round. names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` ;; *.la) dnl Handle this in the next round. Throw away the .la's dnl directory; it is already contained in a preceding -L dnl option. names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` ;; *) dnl Most likely an immediate library name. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$dep" LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$dep" ;; esac done fi else dnl Didn't find the library; assume it is in the system directories dnl known to the linker and runtime loader. (All the system dnl directories known to the linker should also be known to the dnl runtime loader, otherwise the system is severely misconfigured.) LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-l$name" fi fi fi done done if test "X$rpathdirs" != "X"; then if test -n "$acl_hardcode_libdir_separator"; then dnl Weird platform: only the last -rpath option counts, the user must dnl pass all path elements in one option. We can arrange that for a dnl single library, but not when more than one $LIBNAMEs are used. alldirs= for found_dir in $rpathdirs; do alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" done dnl Note: acl_hardcode_libdir_flag_spec uses $libdir and $wl. acl_save_libdir="$libdir" libdir="$alldirs" eval flag=\"$acl_hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" else dnl The -rpath options are cumulative. for found_dir in $rpathdirs; do acl_save_libdir="$libdir" libdir="$found_dir" eval flag=\"$acl_hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" done fi fi if test "X$ltrpathdirs" != "X"; then dnl When using libtool, the option that works for both libraries and dnl executables is -R. The -R options are cumulative. for found_dir in $ltrpathdirs; do LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-R$found_dir" done fi popdef([P_A_C_K]) popdef([PACKLIBS]) popdef([PACKUP]) popdef([PACK]) popdef([NAME]) ]) dnl AC_LIB_APPENDTOVAR(VAR, CONTENTS) appends the elements of CONTENTS to VAR, dnl unless already present in VAR. dnl Works only for CPPFLAGS, not for LIB* variables because that sometimes dnl contains two or three consecutive elements that belong together. AC_DEFUN([AC_LIB_APPENDTOVAR], [ for element in [$2]; do haveit= for x in $[$1]; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X$element"; then haveit=yes break fi done if test -z "$haveit"; then [$1]="${[$1]}${[$1]:+ }$element" fi done ]) dnl For those cases where a variable contains several -L and -l options dnl referring to unknown libraries and directories, this macro determines the dnl necessary additional linker options for the runtime path. dnl AC_LIB_LINKFLAGS_FROM_LIBS([LDADDVAR], [LIBSVALUE], [USE-LIBTOOL]) dnl sets LDADDVAR to linker options needed together with LIBSVALUE. dnl If USE-LIBTOOL evaluates to non-empty, linking with libtool is assumed, dnl otherwise linking without libtool is assumed. AC_DEFUN([AC_LIB_LINKFLAGS_FROM_LIBS], [ AC_REQUIRE([AC_LIB_RPATH]) AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) $1= if test "$enable_rpath" != no; then if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then dnl Use an explicit option to hardcode directories into the resulting dnl binary. rpathdirs= next= for opt in $2; do if test -n "$next"; then dir="$next" dnl No need to hardcode the standard /usr/lib. if test "X$dir" != "X/usr/$acl_libdirstem" \ && test "X$dir" != "X/usr/$acl_libdirstem2"; then rpathdirs="$rpathdirs $dir" fi next= else case $opt in -L) next=yes ;; -L*) dir=`echo "X$opt" | sed -e 's,^X-L,,'` dnl No need to hardcode the standard /usr/lib. if test "X$dir" != "X/usr/$acl_libdirstem" \ && test "X$dir" != "X/usr/$acl_libdirstem2"; then rpathdirs="$rpathdirs $dir" fi next= ;; *) next= ;; esac fi done if test "X$rpathdirs" != "X"; then if test -n ""$3""; then dnl libtool is used for linking. Use -R options. for dir in $rpathdirs; do $1="${$1}${$1:+ }-R$dir" done else dnl The linker is used for linking directly. if test -n "$acl_hardcode_libdir_separator"; then dnl Weird platform: only the last -rpath option counts, the user dnl must pass all path elements in one option. alldirs= for dir in $rpathdirs; do alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$dir" done acl_save_libdir="$libdir" libdir="$alldirs" eval flag=\"$acl_hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" $1="$flag" else dnl The -rpath options are cumulative. for dir in $rpathdirs; do acl_save_libdir="$libdir" libdir="$dir" eval flag=\"$acl_hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" $1="${$1}${$1:+ }$flag" done fi fi fi fi fi AC_SUBST([$1]) ]) kimchi-1.5.0/m4/lib-prefix.m4000066400000000000000000000204221254252253000156040ustar00rootroot00000000000000# lib-prefix.m4 serial 7 (gettext-0.18) dnl Copyright (C) 2001-2005, 2008-2010 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. dnl AC_LIB_ARG_WITH is synonymous to AC_ARG_WITH in autoconf-2.13, and dnl similar to AC_ARG_WITH in autoconf 2.52...2.57 except that is doesn't dnl require excessive bracketing. ifdef([AC_HELP_STRING], [AC_DEFUN([AC_LIB_ARG_WITH], [AC_ARG_WITH([$1],[[$2]],[$3],[$4])])], [AC_DEFUN([AC_][LIB_ARG_WITH], [AC_ARG_WITH([$1],[$2],[$3],[$4])])]) dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed dnl to access previously installed libraries. The basic assumption is that dnl a user will want packages to use other packages he previously installed dnl with the same --prefix option. dnl This macro is not needed if only AC_LIB_LINKFLAGS is used to locate dnl libraries, but is otherwise very convenient. AC_DEFUN([AC_LIB_PREFIX], [ AC_BEFORE([$0], [AC_LIB_LINKFLAGS]) AC_REQUIRE([AC_PROG_CC]) AC_REQUIRE([AC_CANONICAL_HOST]) AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) dnl By default, look in $includedir and $libdir. use_additional=yes AC_LIB_WITH_FINAL_PREFIX([ eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" ]) AC_LIB_ARG_WITH([lib-prefix], [ --with-lib-prefix[=DIR] search for libraries in DIR/include and DIR/lib --without-lib-prefix don't search for libraries in includedir and libdir], [ if test "X$withval" = "Xno"; then use_additional=no else if test "X$withval" = "X"; then AC_LIB_WITH_FINAL_PREFIX([ eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" ]) else additional_includedir="$withval/include" additional_libdir="$withval/$acl_libdirstem" fi fi ]) if test $use_additional = yes; then dnl Potentially add $additional_includedir to $CPPFLAGS. dnl But don't add it dnl 1. if it's the standard /usr/include, dnl 2. if it's already present in $CPPFLAGS, dnl 3. if it's /usr/local/include and we are using GCC on Linux, dnl 4. if it doesn't exist as a directory. if test "X$additional_includedir" != "X/usr/include"; then haveit= for x in $CPPFLAGS; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-I$additional_includedir"; then haveit=yes break fi done if test -z "$haveit"; then if test "X$additional_includedir" = "X/usr/local/include"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then if test -d "$additional_includedir"; then dnl Really add $additional_includedir to $CPPFLAGS. CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-I$additional_includedir" fi fi fi fi dnl Potentially add $additional_libdir to $LDFLAGS. dnl But don't add it dnl 1. if it's the standard /usr/lib, dnl 2. if it's already present in $LDFLAGS, dnl 3. if it's /usr/local/lib and we are using GCC on Linux, dnl 4. if it doesn't exist as a directory. if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then haveit= for x in $LDFLAGS; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then if test -n "$GCC"; then case $host_os in linux*) haveit=yes;; esac fi fi if test -z "$haveit"; then if test -d "$additional_libdir"; then dnl Really add $additional_libdir to $LDFLAGS. LDFLAGS="${LDFLAGS}${LDFLAGS:+ }-L$additional_libdir" fi fi fi fi fi ]) dnl AC_LIB_PREPARE_PREFIX creates variables acl_final_prefix, dnl acl_final_exec_prefix, containing the values to which $prefix and dnl $exec_prefix will expand at the end of the configure script. AC_DEFUN([AC_LIB_PREPARE_PREFIX], [ dnl Unfortunately, prefix and exec_prefix get only finally determined dnl at the end of configure. if test "X$prefix" = "XNONE"; then acl_final_prefix="$ac_default_prefix" else acl_final_prefix="$prefix" fi if test "X$exec_prefix" = "XNONE"; then acl_final_exec_prefix='${prefix}' else acl_final_exec_prefix="$exec_prefix" fi acl_save_prefix="$prefix" prefix="$acl_final_prefix" eval acl_final_exec_prefix=\"$acl_final_exec_prefix\" prefix="$acl_save_prefix" ]) dnl AC_LIB_WITH_FINAL_PREFIX([statement]) evaluates statement, with the dnl variables prefix and exec_prefix bound to the values they will have dnl at the end of the configure script. AC_DEFUN([AC_LIB_WITH_FINAL_PREFIX], [ acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" $1 exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" ]) dnl AC_LIB_PREPARE_MULTILIB creates dnl - a variable acl_libdirstem, containing the basename of the libdir, either dnl "lib" or "lib64" or "lib/64", dnl - a variable acl_libdirstem2, as a secondary possible value for dnl acl_libdirstem, either the same as acl_libdirstem or "lib/sparcv9" or dnl "lib/amd64". AC_DEFUN([AC_LIB_PREPARE_MULTILIB], [ dnl There is no formal standard regarding lib and lib64. dnl On glibc systems, the current practice is that on a system supporting dnl 32-bit and 64-bit instruction sets or ABIs, 64-bit libraries go under dnl $prefix/lib64 and 32-bit libraries go under $prefix/lib. We determine dnl the compiler's default mode by looking at the compiler's library search dnl path. If at least one of its elements ends in /lib64 or points to a dnl directory whose absolute pathname ends in /lib64, we assume a 64-bit ABI. dnl Otherwise we use the default, namely "lib". dnl On Solaris systems, the current practice is that on a system supporting dnl 32-bit and 64-bit instruction sets or ABIs, 64-bit libraries go under dnl $prefix/lib/64 (which is a symlink to either $prefix/lib/sparcv9 or dnl $prefix/lib/amd64) and 32-bit libraries go under $prefix/lib. AC_REQUIRE([AC_CANONICAL_HOST]) acl_libdirstem=lib acl_libdirstem2= case "$host_os" in solaris*) dnl See Solaris 10 Software Developer Collection > Solaris 64-bit Developer's Guide > The Development Environment dnl . dnl "Portable Makefiles should refer to any library directories using the 64 symbolic link." dnl But we want to recognize the sparcv9 or amd64 subdirectory also if the dnl symlink is missing, so we set acl_libdirstem2 too. AC_CACHE_CHECK([for 64-bit host], [gl_cv_solaris_64bit], [AC_EGREP_CPP([sixtyfour bits], [ #ifdef _LP64 sixtyfour bits #endif ], [gl_cv_solaris_64bit=yes], [gl_cv_solaris_64bit=no]) ]) if test $gl_cv_solaris_64bit = yes; then acl_libdirstem=lib/64 case "$host_cpu" in sparc*) acl_libdirstem2=lib/sparcv9 ;; i*86 | x86_64) acl_libdirstem2=lib/amd64 ;; esac fi ;; *) searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'` if test -n "$searchpath"; then acl_save_IFS="${IFS= }"; IFS=":" for searchdir in $searchpath; do if test -d "$searchdir"; then case "$searchdir" in */lib64/ | */lib64 ) acl_libdirstem=lib64 ;; */../ | */.. ) # Better ignore directories of this form. They are misleading. ;; *) searchdir=`cd "$searchdir" && pwd` case "$searchdir" in */lib64 ) acl_libdirstem=lib64 ;; esac ;; esac fi done IFS="$acl_save_IFS" fi ;; esac test -n "$acl_libdirstem2" || acl_libdirstem2="$acl_libdirstem" ]) kimchi-1.5.0/m4/nls.m4000066400000000000000000000023151254252253000143400ustar00rootroot00000000000000# nls.m4 serial 5 (gettext-0.18) dnl Copyright (C) 1995-2003, 2005-2006, 2008-2010 Free Software Foundation, dnl Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl dnl This file can can be used in projects which are not available under dnl the GNU General Public License or the GNU Library General Public dnl License but which still want to provide support for the GNU gettext dnl functionality. dnl Please note that the actual code of the GNU gettext library is covered dnl by the GNU Library General Public License, and the rest of the GNU dnl gettext package package is covered by the GNU General Public License. dnl They are *not* in the public domain. dnl Authors: dnl Ulrich Drepper , 1995-2000. dnl Bruno Haible , 2000-2003. AC_PREREQ([2.50]) AC_DEFUN([AM_NLS], [ AC_MSG_CHECKING([whether NLS is requested]) dnl Default is enabled NLS AC_ARG_ENABLE([nls], [ --disable-nls do not use Native Language Support], USE_NLS=$enableval, USE_NLS=yes) AC_MSG_RESULT([$USE_NLS]) AC_SUBST([USE_NLS]) ]) kimchi-1.5.0/m4/po.m4000066400000000000000000000446161254252253000141740ustar00rootroot00000000000000# po.m4 serial 17 (gettext-0.18) dnl Copyright (C) 1995-2010 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl dnl This file can can be used in projects which are not available under dnl the GNU General Public License or the GNU Library General Public dnl License but which still want to provide support for the GNU gettext dnl functionality. dnl Please note that the actual code of the GNU gettext library is covered dnl by the GNU Library General Public License, and the rest of the GNU dnl gettext package package is covered by the GNU General Public License. dnl They are *not* in the public domain. dnl Authors: dnl Ulrich Drepper , 1995-2000. dnl Bruno Haible , 2000-2003. AC_PREREQ([2.50]) dnl Checks for all prerequisites of the po subdirectory. AC_DEFUN([AM_PO_SUBDIRS], [ AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl defined by autoconf AC_REQUIRE([AM_NLS])dnl dnl Release version of the gettext macros. This is used to ensure that dnl the gettext macros and po/Makefile.in.in are in sync. AC_SUBST([GETTEXT_MACRO_VERSION], [0.18]) dnl Perform the following tests also if --disable-nls has been given, dnl because they are needed for "make dist" to work. dnl Search for GNU msgfmt in the PATH. dnl The first test excludes Solaris msgfmt and early GNU msgfmt versions. dnl The second test excludes FreeBSD msgfmt. AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt, [$ac_dir/$ac_word --statistics /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1 && (if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)], :) AC_PATH_PROG([GMSGFMT], [gmsgfmt], [$MSGFMT]) dnl Test whether it is GNU msgfmt >= 0.15. changequote(,)dnl case `$MSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) MSGFMT_015=: ;; *) MSGFMT_015=$MSGFMT ;; esac changequote([,])dnl AC_SUBST([MSGFMT_015]) changequote(,)dnl case `$GMSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) GMSGFMT_015=: ;; *) GMSGFMT_015=$GMSGFMT ;; esac changequote([,])dnl AC_SUBST([GMSGFMT_015]) dnl Search for GNU xgettext 0.12 or newer in the PATH. dnl The first test excludes Solaris xgettext and early GNU xgettext versions. dnl The second test excludes FreeBSD xgettext. AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, [$ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1 && (if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)], :) dnl Remove leftover from FreeBSD xgettext call. rm -f messages.po dnl Test whether it is GNU xgettext >= 0.15. changequote(,)dnl case `$XGETTEXT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) XGETTEXT_015=: ;; *) XGETTEXT_015=$XGETTEXT ;; esac changequote([,])dnl AC_SUBST([XGETTEXT_015]) dnl Search for GNU msgmerge 0.11 or newer in the PATH. AM_PATH_PROG_WITH_TEST(MSGMERGE, msgmerge, [$ac_dir/$ac_word --update -q /dev/null /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1], :) dnl Installation directories. dnl Autoconf >= 2.60 defines localedir. For older versions of autoconf, we dnl have to define it here, so that it can be used in po/Makefile. test -n "$localedir" || localedir='${datadir}/locale' AC_SUBST([localedir]) dnl Support for AM_XGETTEXT_OPTION. test -n "${XGETTEXT_EXTRA_OPTIONS+set}" || XGETTEXT_EXTRA_OPTIONS= AC_SUBST([XGETTEXT_EXTRA_OPTIONS]) AC_CONFIG_COMMANDS([po-directories], [[ for ac_file in $CONFIG_FILES; do # Support "outfile[:infile[:infile...]]" case "$ac_file" in *:*) ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; esac # PO directories have a Makefile.in generated from Makefile.in.in. case "$ac_file" in */Makefile.in) # Adjust a relative srcdir. ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`" ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` # In autoconf-2.13 it is called $ac_given_srcdir. # In autoconf-2.50 it is called $srcdir. test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" case "$ac_given_srcdir" in .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; /*) top_srcdir="$ac_given_srcdir" ;; *) top_srcdir="$ac_dots$ac_given_srcdir" ;; esac # Treat a directory as a PO directory if and only if it has a # POTFILES.in file. This allows packages to have multiple PO # directories under different names or in different locations. if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then rm -f "$ac_dir/POTFILES" test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES" cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ ]*\$/d" -e "s,.*, $top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES" POMAKEFILEDEPS="POTFILES.in" # ALL_LINGUAS, POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES depend # on $ac_dir but don't depend on user-specified configuration # parameters. if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then # The LINGUAS file contains the set of available languages. if test -n "$OBSOLETE_ALL_LINGUAS"; then test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete" fi ALL_LINGUAS_=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"` # Hide the ALL_LINGUAS assigment from automake < 1.5. eval 'ALL_LINGUAS''=$ALL_LINGUAS_' POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS" else # The set of available languages was given in configure.in. # Hide the ALL_LINGUAS assigment from automake < 1.5. eval 'ALL_LINGUAS''=$OBSOLETE_ALL_LINGUAS' fi # Compute POFILES # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po) # Compute UPDATEPOFILES # as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update) # Compute DUMMYPOFILES # as $(foreach lang, $(ALL_LINGUAS), $(lang).nop) # Compute GMOFILES # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo) case "$ac_given_srcdir" in .) srcdirpre= ;; *) srcdirpre='$(srcdir)/' ;; esac POFILES= UPDATEPOFILES= DUMMYPOFILES= GMOFILES= for lang in $ALL_LINGUAS; do POFILES="$POFILES $srcdirpre$lang.po" UPDATEPOFILES="$UPDATEPOFILES $lang.po-update" DUMMYPOFILES="$DUMMYPOFILES $lang.nop" GMOFILES="$GMOFILES $srcdirpre$lang.gmo" done # CATALOGS depends on both $ac_dir and the user's LINGUAS # environment variable. INST_LINGUAS= if test -n "$ALL_LINGUAS"; then for presentlang in $ALL_LINGUAS; do useit=no if test "%UNSET%" != "$LINGUAS"; then desiredlanguages="$LINGUAS" else desiredlanguages="$ALL_LINGUAS" fi for desiredlang in $desiredlanguages; do # Use the presentlang catalog if desiredlang is # a. equal to presentlang, or # b. a variant of presentlang (because in this case, # presentlang can be used as a fallback for messages # which are not translated in the desiredlang catalog). case "$desiredlang" in "$presentlang"*) useit=yes;; esac done if test $useit = yes; then INST_LINGUAS="$INST_LINGUAS $presentlang" fi done fi CATALOGS= if test -n "$INST_LINGUAS"; then for lang in $INST_LINGUAS; do CATALOGS="$CATALOGS $lang.gmo" done fi test -n "$as_me" && echo "$as_me: creating $ac_dir/Makefile" || echo "creating $ac_dir/Makefile" sed -e "/^POTFILES =/r $ac_dir/POTFILES" -e "/^# Makevars/r $ac_given_srcdir/$ac_dir/Makevars" -e "s|@POFILES@|$POFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@POMAKEFILEDEPS@|$POMAKEFILEDEPS|g" "$ac_dir/Makefile.in" > "$ac_dir/Makefile" for f in "$ac_given_srcdir/$ac_dir"/Rules-*; do if test -f "$f"; then case "$f" in *.orig | *.bak | *~) ;; *) cat "$f" >> "$ac_dir/Makefile" ;; esac fi done fi ;; esac done]], [# Capture the value of obsolete ALL_LINGUAS because we need it to compute # POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES, CATALOGS. But hide it # from automake < 1.5. eval 'OBSOLETE_ALL_LINGUAS''="$ALL_LINGUAS"' # Capture the value of LINGUAS because we need it to compute CATALOGS. LINGUAS="${LINGUAS-%UNSET%}" ]) ]) dnl Postprocesses a Makefile in a directory containing PO files. AC_DEFUN([AM_POSTPROCESS_PO_MAKEFILE], [ # When this code is run, in config.status, two variables have already been # set: # - OBSOLETE_ALL_LINGUAS is the value of LINGUAS set in configure.in, # - LINGUAS is the value of the environment variable LINGUAS at configure # time. changequote(,)dnl # Adjust a relative srcdir. ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`" ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` # In autoconf-2.13 it is called $ac_given_srcdir. # In autoconf-2.50 it is called $srcdir. test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" case "$ac_given_srcdir" in .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; /*) top_srcdir="$ac_given_srcdir" ;; *) top_srcdir="$ac_dots$ac_given_srcdir" ;; esac # Find a way to echo strings without interpreting backslash. if test "X`(echo '\t') 2>/dev/null`" = 'X\t'; then gt_echo='echo' else if test "X`(printf '%s\n' '\t') 2>/dev/null`" = 'X\t'; then gt_echo='printf %s\n' else echo_func () { cat < "$ac_file.tmp" if grep -l '@TCLCATALOGS@' "$ac_file" > /dev/null; then # Add dependencies that cannot be formulated as a simple suffix rule. for lang in $ALL_LINGUAS; do frobbedlang=`echo $lang | sed -e 's/\..*$//' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'` cat >> "$ac_file.tmp" < /dev/null; then # Add dependencies that cannot be formulated as a simple suffix rule. for lang in $ALL_LINGUAS; do frobbedlang=`echo $lang | sed -e 's/_/-/g' -e 's/^sr-CS/sr-SP/' -e 's/@latin$/-Latn/' -e 's/@cyrillic$/-Cyrl/' -e 's/^sr-SP$/sr-SP-Latn/' -e 's/^uz-UZ$/uz-UZ-Latn/'` cat >> "$ac_file.tmp" <> "$ac_file.tmp" <, 1996. AC_PREREQ([2.50]) # Search path for a program which passes the given test. dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR, dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]]) AC_DEFUN([AM_PATH_PROG_WITH_TEST], [ # Prepare PATH_SEPARATOR. # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi # Find out how to test for executable files. Don't use a zero-byte file, # as systems may use methods other than mode bits to determine executability. cat >conf$$.file <<_ASEOF #! /bin/sh exit 0 _ASEOF chmod +x conf$$.file if test -x conf$$.file >/dev/null 2>&1; then ac_executable_p="test -x" else ac_executable_p="test -f" fi rm -f conf$$.file # Extract the first word of "$2", so it can be a program name with args. set dummy $2; ac_word=[$]2 AC_MSG_CHECKING([for $ac_word]) AC_CACHE_VAL([ac_cv_path_$1], [case "[$]$1" in [[\\/]]* | ?:[[\\/]]*) ac_cv_path_$1="[$]$1" # Let the user override the test with a path. ;; *) ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in ifelse([$5], , $PATH, [$5]); do IFS="$ac_save_IFS" test -z "$ac_dir" && ac_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then echo "$as_me: trying $ac_dir/$ac_word..." >&AS_MESSAGE_LOG_FD if [$3]; then ac_cv_path_$1="$ac_dir/$ac_word$ac_exec_ext" break 2 fi fi done done IFS="$ac_save_IFS" dnl If no 4th arg is given, leave the cache variable unset, dnl so AC_PATH_PROGS will keep looking. ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4" ])dnl ;; esac])dnl $1="$ac_cv_path_$1" if test ifelse([$4], , [-n "[$]$1"], ["[$]$1" != "$4"]); then AC_MSG_RESULT([$][$1]) else AC_MSG_RESULT([no]) fi AC_SUBST([$1])dnl ]) kimchi-1.5.0/plugins/000077500000000000000000000000001254252253000144425ustar00rootroot00000000000000kimchi-1.5.0/plugins/Makefile.am000066400000000000000000000015371254252253000165040ustar00rootroot00000000000000# # Kimchi # # Copyright IBM Corp, 2013 # # 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 SUBDIRS = sample plugins_PYTHON = \ __init__.py pluginsdir = $(pythondir)/kimchi/plugins kimchi-1.5.0/plugins/__init__.py000066400000000000000000000014161254252253000165550ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-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 kimchi-1.5.0/plugins/sample/000077500000000000000000000000001254252253000157235ustar00rootroot00000000000000kimchi-1.5.0/plugins/sample/API.json000066400000000000000000000033421254252253000172310ustar00rootroot00000000000000{ "$schema": "http://json-schema.org/draft-03/schema#", "title": "Plugin Sample API", "description": "Json schema for Kimchi's Sample Plugin API", "type": "object", "error": "SPAPI0001E", "properties": { "rectangles_create": { "type": "object", "error": "SPRET0003E", "properties": { "name": { "description": "The name of the new rectangle instance", "type": "string", "required": true, "error": "SPRET0004E" }, "length": { "$ref": "#/definitions/positiveNumber", "required": true, "error": "SPRET0005E" }, "width": { "$ref": "#/definitions/positiveNumber", "required": true, "error": "SPRET0006E" } } }, "circles_create": { "type": "object", "error": "SPCIRC0003E", "properties": { "name": { "description": "The name of the new circle instance", "type": "string", "required": true, "error": "SPCIRC0004E" }, "radius": { "$ref": "#/definitions/positiveNumber", "required": true, "error": "SPCIRC0005E" } } } }, "definitions": { "positiveNumber": { "error": "SPAPI0002E", "type": "number", "minimum": 0, "exclusiveMinimum": true } } } kimchi-1.5.0/plugins/sample/Makefile.am000066400000000000000000000021121254252253000177530ustar00rootroot00000000000000# # Kimchi # # Copyright IBM Corp, 2013 # # 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 SUBDIRS = ui po EXTRA_DIST = API.json sample.conf.in $(wildcard *.py) config.status all-local: while read L && test -n "$$L"; do \ dir=mo/$$L/LC_MESSAGES ; \ $(MKDIR_P) $$dir ; \ ln -sf ../../../po/$$L.gmo $$dir/sample.mo ; \ done < po/LINGUAS kimchi-1.5.0/plugins/sample/__init__.py000066400000000000000000000052551254252253000200430ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-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 import json import os from cherrypy import expose from kimchi.config import PluginPaths from kimchi.control.base import Collection, Resource from kimchi.root import Root from plugins.sample.i18n import messages from plugins.sample.model import Model model = Model() class Drawings(Root): def __init__(self): Resource.__init__(self, model) self.description = Description(model) self.rectangles = Rectangles(model) self.circles = Circles(model) self.paths = PluginPaths('sample') self.domain = 'sample' self.messages = messages self.api_schema = json.load(open(os.path.join(os.path.dirname( os.path.abspath(__file__)), 'API.json'))) @expose def index(self): return 'This is a sample plugin for Kimchi' class Description(Resource): def __init__(self, model): super(Description, self).__init__(model) @property def data(self): return {'name': 'sample', 'version': '0.1'} class Circles(Collection): def __init__(self, model): super(Circles, self).__init__(model) self.resource = Circle self.admin_methods = ['POST', 'PUT'] class Rectangles(Collection): def __init__(self, model): super(Rectangles, self).__init__(model) self.resource = Rectangle self.admin_methods = ['POST', 'PUT'] class Circle(Resource): def __init__(self, model, ident): super(Circle, self).__init__(model, ident) self.update_params = ['radius'] @property def data(self): ret = {'name': self.ident} ret.update(self.info) return ret class Rectangle(Resource): def __init__(self, model, ident): super(Rectangle, self).__init__(model, ident) self.update_params = ['length', 'width'] @property def data(self): self.info.update({'name': self.ident}) return self.info kimchi-1.5.0/plugins/sample/config.status000077700000000000000000000000001254252253000235702../../config.statusustar00rootroot00000000000000kimchi-1.5.0/plugins/sample/i18n.py000066400000000000000000000030771254252253000170630ustar00rootroot00000000000000# # 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 import gettext _ = gettext.gettext messages = { "SPAPI0001E": _("Unkown parameter specified %(value)s"), "SPAPI0002E": _("The specified value %(value)s is not a positive number"), "SPCIRC0002E": _("Circle %(name)s does not exist"), "SPCIRC0003E": _("Specify name and radius to create a Circle"), "SPCIRC0004E": _("Circle name must be a string"), "SPCIRC0005E": _("Circle radius must be a positive number"), "SPRET0001E": _("Rectangle %(name)s already exists"), "SPRET0002E": _("Rectangle %(name)s does not exist"), "SPRET0003E": _("Specify name, length and width to create a Rectangle"), "SPRET0004E": _("Rectangle name must be a string"), "SPRET0005E": _("Rectangle length must be a positive number"), "SPRET0006E": _("Rectangle width must be a positive number"), } kimchi-1.5.0/plugins/sample/model.py000066400000000000000000000073371254252253000174070ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-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 from kimchi.exception import InvalidOperation, NotFoundError from kimchi.basemodel import BaseModel class CirclesModel(object): def __init__(self): self._circles = {} def create(self, params): name = params['name'] if name in self._circles: raise InvalidOperation("SPCIRCLE0001E", {'name': name}) self._circles[name] = Circle(params['radius']) return name def get_list(self): return sorted(self._circles) class CircleModel(object): def __init__(self, parent_model): # Circel and Circles models are friends, it's OK to share _circles. self._circles = parent_model._circles def lookup(self, name): try: circle = self._circles[name] except KeyError: raise NotFoundError("SPCIRC0002E", {'name': name}) return {'radius': circle.radius} def update(self, name, params): if name not in self._circles: raise NotFoundError("SPCIRC0002E", {'name': name}) self._circles[name].radius = params['radius'] return name def delete(self, name): try: del self._circles[name] except KeyError: pass class RectanglesModel(object): def __init__(self): self._rectangles = {} def create(self, params): name = params['name'] if name in self._rectangles: raise InvalidOperation("SPRET0001E", {'name': name}) self._rectangles[name] = Rectangle(params['length'], params['width']) return name def get_list(self): return sorted(self._rectangles) class RectangleModel(object): def __init__(self, parent_model): self._rectangles = parent_model._rectangles def lookup(self, name): try: rectangle = self._rectangles[name] except KeyError: raise NotFoundError("SPRET0002E", {'name': name}) return {'length': rectangle.length, 'width': rectangle.width} def update(self, name, params): if name not in self._rectangles: raise NotFoundError("SPRET0002E", {'name': name}) try: self._rectangles[name].length = params['length'] except KeyError: pass try: self._rectangles[name].width = params['width'] except KeyError: pass return name def delete(self, name): try: del self._rectangles[name] except KeyError: pass class Model(BaseModel): def __init__(self): circles = CirclesModel() circle = CircleModel(circles) rectangles = RectanglesModel() rectangle = RectangleModel(rectangles) return super(Model, self).__init__( [circle, circles, rectangle, rectangles]) class Rectangle(object): def __init__(self, length, width): self.length = length self.width = width class Circle(object): def __init__(self, radius): self.radius = radius kimchi-1.5.0/plugins/sample/po/000077500000000000000000000000001254252253000163415ustar00rootroot00000000000000kimchi-1.5.0/plugins/sample/po/LINGUAS000066400000000000000000000000221254252253000173600ustar00rootroot00000000000000en_US pt_BR zh_CN kimchi-1.5.0/plugins/sample/po/Makefile.in.in000066400000000000000000000332071254252253000210200ustar00rootroot00000000000000# Makefile for PO directory in any package using GNU gettext. # Copyright (C) 1995-1997, 2000-2007, 2009-2010 by Ulrich Drepper # # This file can be copied and used freely without restrictions. It can # be used in projects which are not available under the GNU General Public # License but which still want to provide support for the GNU gettext # functionality. # Please note that the actual code of GNU gettext is covered by the GNU # General Public License and is *not* in the public domain. # # Origin: gettext-0.18 GETTEXT_MACRO_VERSION = 0.18 PACKAGE = @PACKAGE@ VERSION = @VERSION@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ SHELL = /bin/sh @SET_MAKE@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ datarootdir = @datarootdir@ datadir = @datadir@ localedir = @prefix@/share/locale gettextsrcdir = $(datadir)/gettext/po INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ # We use $(MKDIR_P). # This macro uses the 'mkdir -p' command if possible. Otherwise, it falls back # on invoking install-sh with the -d option, so your package should contain # install-sh as described under AC_PROG_INSTALL. mkinstalldirs = $(SHELL) @install_sh@ -d install_sh = $(SHELL) @install_sh@ MKDIR_P = @MKDIR_P@ MKDIR_P = @MKDIR_P@ GMSGFMT_ = @GMSGFMT@ GMSGFMT_no = @GMSGFMT@ GMSGFMT_yes = @GMSGFMT_015@ GMSGFMT = $(GMSGFMT_$(USE_MSGCTXT)) MSGFMT_ = @MSGFMT@ MSGFMT_no = @MSGFMT@ MSGFMT_yes = @MSGFMT_015@ MSGFMT = $(MSGFMT_$(USE_MSGCTXT)) XGETTEXT_ = @XGETTEXT@ XGETTEXT_no = @XGETTEXT@ XGETTEXT_yes = @XGETTEXT_015@ XGETTEXT = $(XGETTEXT_$(USE_MSGCTXT)) MSGMERGE = msgmerge MSGMERGE_UPDATE = @MSGMERGE@ --update MSGINIT = msginit MSGCONV = msgconv MSGFILTER = msgfilter POFILES = @POFILES@ GMOFILES = @GMOFILES@ UPDATEPOFILES = @UPDATEPOFILES@ DUMMYPOFILES = @DUMMYPOFILES@ DISTFILES.common = Makefile.in.in \ $(DISTFILES.common.extra1) $(DISTFILES.common.extra2) $(DISTFILES.common.extra3) DISTFILES = $(DISTFILES.common) Makevars POTFILES.in gen-pot \ $(POFILES) $(GMOFILES) \ $(DISTFILES.extra1) $(DISTFILES.extra2) $(DISTFILES.extra3) POTFILES = \ CATALOGS = @CATALOGS@ # Makevars gets inserted here. (Don't remove this line!) .SUFFIXES: .SUFFIXES: .po .gmo .mo .sed .sin .nop .po-create .po-update .po.mo: @echo "$(MSGFMT) -c -o $@ $<"; \ $(MSGFMT) -c -o t-$@ $< && mv t-$@ $@ .po.gmo: @lang=`echo $* | sed -e 's,.*/,,'`; \ test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ echo "$${cdcmd}rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics --verbose -o $${lang}.gmo $${lang}.po"; \ cd $(srcdir) && rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics --verbose -o t-$${lang}.gmo $${lang}.po && mv t-$${lang}.gmo $${lang}.gmo .sin.sed: sed -e '/^#/d' $< > t-$@ mv t-$@ $@ all: check-macro-version update-gmo all-@USE_NLS@ all-yes: stamp-po all-no: # Ensure that the gettext macros and this Makefile.in.in are in sync. check-macro-version: @test "$(GETTEXT_MACRO_VERSION)" = "@GETTEXT_MACRO_VERSION@" \ || { echo "*** error: gettext infrastructure mismatch: using a Makefile.in.in from gettext version $(GETTEXT_MACRO_VERSION) but the autoconf macros are from gettext version @GETTEXT_MACRO_VERSION@" 1>&2; \ exit 1; \ } # $(srcdir)/$(DOMAIN).pot is only created when needed. When xgettext finds no # internationalized messages, no $(srcdir)/$(DOMAIN).pot is created (because # we don't want to bother translators with empty POT files). We assume that # LINGUAS is empty in this case, i.e. $(POFILES) and $(GMOFILES) are empty. # In this case, stamp-po is a nop (i.e. a phony target). # stamp-po is a timestamp denoting the last time at which the CATALOGS have # been loosely updated. Its purpose is that when a developer or translator # checks out the package via CVS, and the $(DOMAIN).pot file is not in CVS, # "make" will update the $(DOMAIN).pot and the $(CATALOGS), but subsequent # invocations of "make" will do nothing. This timestamp would not be necessary # if updating the $(CATALOGS) would always touch them; however, the rule for # $(POFILES) has been designed to not touch files that don't need to be # changed. stamp-po: $(srcdir)/$(DOMAIN).pot test ! -f $(srcdir)/$(DOMAIN).pot || \ test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES) @test ! -f $(srcdir)/$(DOMAIN).pot || { \ echo "touch stamp-po" && \ echo timestamp > stamp-poT && \ mv stamp-poT stamp-po; \ } # Note: Target 'all' must not depend on target '$(DOMAIN).pot-update', # otherwise packages like GCC can not be built if only parts of the source # have been downloaded. $(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in $(srcdir)/gen-pot $(POTFILES) # This rule has no dependencies: we don't need to update $(DOMAIN).pot at # every "make" invocation, only create it when it is missing. # Only "make $(DOMAIN).pot-update" or "make dist" will force an update. $(srcdir)/$(DOMAIN).pot: $(MAKE) $(DOMAIN).pot-update # This target rebuilds a PO file if $(DOMAIN).pot has changed. # Note that a PO file is not touched if it doesn't need to be changed. $(POFILES): $(srcdir)/$(DOMAIN).pot @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \ if test -f "$(srcdir)/$${lang}.po"; then \ test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ echo "$${cdcmd}$(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --lang=$${lang} $${lang}.po $(DOMAIN).pot"; \ cd $(srcdir) \ && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ '' | 0.[0-9] | 0.[0-9].* | 0.1[0-7] | 0.1[0-7].*) \ $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \ *) \ $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --lang=$${lang} $${lang}.po $(DOMAIN).pot;; \ esac; \ }; \ else \ $(MAKE) $${lang}.po-create; \ fi install: install-exec: install-data: install-data-@USE_NLS@ if test "$(PACKAGE)" = "gettext-tools"; then \ $(MKDIR_P) $(DESTDIR)$(gettextsrcdir); \ for file in $(DISTFILES.common) Makevars.template; do \ $(INSTALL_DATA) $(srcdir)/$$file \ $(DESTDIR)$(gettextsrcdir)/$$file; \ done; \ for file in Makevars; do \ rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ done; \ else \ : ; \ fi install-data-no: all install-data-yes: all @catalogs='$(CATALOGS)'; \ for cat in $$catalogs; do \ cat=`basename $$cat`; \ lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ dir=$(localedir)/$$lang/LC_MESSAGES; \ $(MKDIR_P) $(DESTDIR)$$dir; \ if test -r $$cat; then realcat=$$cat; else realcat=$(srcdir)/$$cat; fi; \ $(INSTALL_DATA) $$realcat $(DESTDIR)$$dir/$(DOMAIN).mo; \ echo "installing $$realcat as $(DESTDIR)$$dir/$(DOMAIN).mo"; \ for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \ if test -n "$$lc"; then \ if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \ link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \ mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ (cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \ for file in *; do \ if test -f $$file; then \ ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \ fi; \ done); \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ else \ if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \ :; \ else \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \ mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ fi; \ fi; \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ ln -s ../LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \ ln $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \ cp -p $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ echo "installing $$realcat link as $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo"; \ fi; \ done; \ done install-strip: install installdirs: installdirs-exec installdirs-data installdirs-exec: installdirs-data: installdirs-data-@USE_NLS@ if test "$(PACKAGE)" = "gettext-tools"; then \ $(MKDIR_P) $(DESTDIR)$(gettextsrcdir); \ else \ : ; \ fi installdirs-data-no: installdirs-data-yes: @catalogs='$(CATALOGS)'; \ for cat in $$catalogs; do \ cat=`basename $$cat`; \ lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ dir=$(localedir)/$$lang/LC_MESSAGES; \ $(MKDIR_P) $(DESTDIR)$$dir; \ for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \ if test -n "$$lc"; then \ if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \ link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \ mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ (cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \ for file in *; do \ if test -f $$file; then \ ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \ fi; \ done); \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ else \ if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \ :; \ else \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \ mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ fi; \ fi; \ fi; \ done; \ done # Define this as empty until I found a useful application. installcheck: uninstall: uninstall-exec: uninstall-data: uninstall-data-@USE_NLS@ if test "$(PACKAGE)" = "gettext-tools"; then \ for file in $(DISTFILES.common) Makevars.template; do \ rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ done; \ else \ : ; \ fi uninstall-data-no: uninstall-data-yes: catalogs='$(CATALOGS)'; \ for cat in $$catalogs; do \ cat=`basename $$cat`; \ lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ for lc in LC_MESSAGES $(EXTRA_LOCALE_CATEGORIES); do \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ done; \ done check: all info dvi ps pdf html tags TAGS ctags CTAGS ID: mostlyclean: rm -f remove-potcdate.sed rm -f stamp-poT rm -f core core.* $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po rm -fr *.o clean: mostlyclean distclean: clean rm -f Makefile Makefile.in POTFILES *.mo maintainer-clean: distclean @echo "This command is intended for maintainers to use;" @echo "it deletes files that may require special tools to rebuild." rm -f stamp-po $(GMOFILES) distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) dist distdir: $(MAKE) update-po @$(MAKE) dist2 # This is a separate target because 'update-po' must be executed before. dist2: stamp-po $(DISTFILES) dists="$(DISTFILES)"; \ if test "$(PACKAGE)" = "gettext-tools"; then \ dists="$$dists Makevars.template"; \ fi; \ if test -f $(srcdir)/$(DOMAIN).pot; then \ dists="$$dists $(DOMAIN).pot stamp-po"; \ fi; \ if test -f $(srcdir)/ChangeLog; then \ dists="$$dists ChangeLog"; \ fi; \ for i in 0 1 2 3 4 5 6 7 8 9; do \ if test -f $(srcdir)/ChangeLog.$$i; then \ dists="$$dists ChangeLog.$$i"; \ fi; \ done; \ if test -f $(srcdir)/LINGUAS; then dists="$$dists LINGUAS"; fi; \ for file in $$dists; do \ if test -f $$file; then \ cp -p $$file $(distdir) || exit 1; \ else \ cp -p $(srcdir)/$$file $(distdir) || exit 1; \ fi; \ done update-po: Makefile $(MAKE) $(DOMAIN).pot-update test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES) $(MAKE) update-gmo # General rule for creating PO files. .nop.po-create: @lang=`echo $@ | sed -e 's/\.po-create$$//'`; \ echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \ exit 1 # General rule for updating PO files. .nop.po-update: @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \ if test "$(PACKAGE)" = "gettext-tools"; then PATH=`pwd`/../src:$$PATH; fi; \ tmpdir=`pwd`; \ echo "$$lang:"; \ test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ echo "$${cdcmd}$(MSGMERGE) $(MSGMERGE_OPTIONS) --lang=$$lang $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \ cd $(srcdir); \ if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ '' | 0.[0-9] | 0.[0-9].* | 0.1[0-7] | 0.1[0-7].*) \ $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \ *) \ $(MSGMERGE) $(MSGMERGE_OPTIONS) --lang=$$lang -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \ esac; \ }; then \ if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ rm -f $$tmpdir/$$lang.new.po; \ else \ if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ :; \ else \ echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ exit 1; \ fi; \ fi; \ else \ echo "msgmerge for $$lang.po failed!" 1>&2; \ rm -f $$tmpdir/$$lang.new.po; \ fi $(DUMMYPOFILES): update-gmo: Makefile $(GMOFILES) @: # Recreate Makefile by invoking config.status. Explicitly invoke the shell, # because execution permission bits may not work on the current file system. # Use @SHELL@, which is the shell determined by autoconf for the use by its # scripts, not $(SHELL) which is hardwired to /bin/sh and may be deficient. Makefile: Makefile.in.in Makevars $(top_builddir)/config.status @POMAKEFILEDEPS@ cd $(top_builddir) \ && @SHELL@ ./config.status $(subdir)/$@.in po-directories force: # Tell versions [3.59,3.63) of GNU make not to export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: kimchi-1.5.0/plugins/sample/po/Makevars000066400000000000000000000034021254252253000200340ustar00rootroot00000000000000# Makefile variables for PO directory in any package using GNU gettext. # Usually the message domain is the same as the package name. DOMAIN = sample # These two variables depend on the location of this directory. subdir = po top_builddir = .. # These options get passed to xgettext. XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ # This is the copyright holder that gets inserted into the header of the # $(DOMAIN).pot file. Set this to the copyright holder of the surrounding # package. (Note that the msgstr strings, extracted from the package's # sources, belong to the copyright holder of the package.) Translators are # expected to transfer the copyright for their translations to this person # or entity, or to disclaim their copyright. The empty string stands for # the public domain; in this case the translators are expected to disclaim # their copyright. COPYRIGHT_HOLDER = # This is the email address or URL to which the translators shall report # bugs in the untranslated strings: # - Strings which are not entire sentences, see the maintainer guidelines # in the GNU gettext documentation, section 'Preparing Strings'. # - Strings which use unclear terms or require additional context to be # understood. # - Strings which make invalid assumptions about notation of date, time or # money. # - Pluralisation problems. # - Incorrect English spelling. # - Incorrect formatting. # It can be your email address, or a mailing list address where translators # can write to without being subscribed, or the URL of a web page through # which the translators can contact you. MSGID_BUGS_ADDRESS = kimchi-devel@ovirt.org # This is the list of locale categories, beyond LC_MESSAGES, for which the # message catalogs shall be used. It is usually empty. EXTRA_LOCALE_CATEGORIES = kimchi-1.5.0/plugins/sample/po/POTFILES.in000066400000000000000000000001321254252253000201120ustar00rootroot00000000000000# List of source files which contain translatable strings. plugins/sample/ui/pages/*.tmpl kimchi-1.5.0/plugins/sample/po/en_US.po000066400000000000000000000012331254252253000177110ustar00rootroot00000000000000# English translations for kimchi package. # Copyright (C) 2014 THE kimchi'S COPYRIGHT HOLDER # This file is distributed under the same license as the kimchi package. # shhfeng , 2014. # msgid "" msgstr "" "Project-Id-Version: kimchi 1.2.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-06-24 09:39-0300\n" "PO-Revision-Date: 2014-05-17 02:08+0800\n" "Last-Translator: shhfeng \n" "Language-Team: English\n" "Language: en_US\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=ASCII\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: pygettext.py 1.5\n" msgid "SampleTab" msgstr "SampleTab" kimchi-1.5.0/plugins/sample/po/gen-pot000077500000000000000000000003021254252253000176330ustar00rootroot00000000000000#!/bin/bash for src in $@; do if [ ${src: -3} == ".py" ]; then cat $src else cat $src | cheetah compile - fi done | xgettext --no-location -o sample.pot -L Python - kimchi-1.5.0/plugins/sample/po/pt_BR.po000066400000000000000000000014441254252253000177120ustar00rootroot00000000000000# Portuguese translations for kimchi package # Copyright (C) 2014 THE kimchi'S COPYRIGHT HOLDER # This file is distributed under the same license as the kimchi package. # shhfeng , 2014. # msgid "" msgstr "" "Project-Id-Version: kimchi 1.2.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-06-24 09:39-0300\n" "PO-Revision-Date: 2014-05-17 02:09+0800\n" "Last-Translator: Crístian Viana \n" "Language-Team: Aline Manera \n" "Language: pt_BR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: pygettext.py 1.5\n" "X-Poedit-Country: Brazil\n" "X-Poedit-Language: Portuguese\n" "X-Poedit-SourceCharset: utf-8\n" msgid "SampleTab" msgstr "Tab de exemplo" kimchi-1.5.0/plugins/sample/po/sample.pot000066400000000000000000000011431254252253000203450ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-06-24 09:39-0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" msgid "SampleTab" msgstr "" kimchi-1.5.0/plugins/sample/po/zh_CN.po000066400000000000000000000014071254252253000177040ustar00rootroot00000000000000# Chinese translations for kimchi package # Copyright (C) 2014 THE kimchi'S COPYRIGHT HOLDER # This file is distributed under the same license as the kimchi package. # shhfeng , 2014. # msgid "" msgstr "" "Project-Id-Version: kimchi 1.2.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-06-24 09:39-0300\n" "PO-Revision-Date: 2014-05-17 02:10+0800\n" "Last-Translator: shhfeng \n" "Language-Team: Chinese (simplified)\n" "Language: zh_CN\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: pygettext.py 1.5\n" "X-Poedit-Country: CHINA\n" "X-Poedit-Language: Chinese\n" "X-Poedit-SourceCharset: utf-8\n" msgid "SampleTab" msgstr "示例标签" kimchi-1.5.0/plugins/sample/sample.conf.in000066400000000000000000000010701254252253000204560ustar00rootroot00000000000000[kimchi] enable = @ENABLE_SAMPLE@ plugin_class = "Drawings" uri = "/plugins/sample" [/] tools.nocache.on = True tools.trailing_slash.on = False tools.sessions.on = True tools.sessions.name = 'kimchi' tools.sessions.httponly = True tools.sessions.locking = 'explicit' tools.sessions.storage_type = 'ram' [/description] tools.kimchiauth.on = True [/rectangles] tools.kimchiauth.on = True [/circles] tools.kimchiauth.on = True [/help] tools.staticdir.on = True tools.nocache.on = True tools.staticdir.dir = kimchi.config.PluginPaths('sample').ui_dir + '/pages/help' kimchi-1.5.0/plugins/sample/ui/000077500000000000000000000000001254252253000163405ustar00rootroot00000000000000kimchi-1.5.0/plugins/sample/ui/Makefile.am000066400000000000000000000014371254252253000204010ustar00rootroot00000000000000# # Kimchi # # Copyright IBM Corp, 2013 # # 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 SUBDIRS = config js pages kimchi-1.5.0/plugins/sample/ui/config/000077500000000000000000000000001254252253000176055ustar00rootroot00000000000000kimchi-1.5.0/plugins/sample/ui/config/Makefile.am000066400000000000000000000014351254252253000216440ustar00rootroot00000000000000# # Kimchi # # Copyright IBM Corp, 2013 # # 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 EXTRA_DIST = tab-ext.xml kimchi-1.5.0/plugins/sample/ui/config/tab-ext.xml000066400000000000000000000007061254252253000216760ustar00rootroot00000000000000 SampleTab 1 plugins/sample/sample-tab1.html SampleTab 2 plugins/sample/sample-tab2.html kimchi-1.5.0/plugins/sample/ui/css/000077500000000000000000000000001254252253000171305ustar00rootroot00000000000000kimchi-1.5.0/plugins/sample/ui/css/.gitignore000066400000000000000000000000001254252253000211060ustar00rootroot00000000000000kimchi-1.5.0/plugins/sample/ui/images/000077500000000000000000000000001254252253000176055ustar00rootroot00000000000000kimchi-1.5.0/plugins/sample/ui/images/.gitignore000066400000000000000000000000001254252253000215630ustar00rootroot00000000000000kimchi-1.5.0/plugins/sample/ui/js/000077500000000000000000000000001254252253000167545ustar00rootroot00000000000000kimchi-1.5.0/plugins/sample/ui/js/.gitignore000066400000000000000000000000001254252253000207320ustar00rootroot00000000000000kimchi-1.5.0/plugins/sample/ui/js/Makefile.am000066400000000000000000000014301254252253000210060ustar00rootroot00000000000000# # 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 EXTRA_DIST = util.js kimchi-1.5.0/plugins/sample/ui/js/util.js000066400000000000000000000017631254252253000202760ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ sample = {}; sample.description = function(suc, err){ kimchi.requestJSON({ url : kimchi.url + 'plugins/sample/description', type : 'GET', contentType : 'application/json', dataType : 'json', resend : true, success : suc, error : err || function(data) { kimchi.message.error(data.responseJSON.reason); } }); }; kimchi-1.5.0/plugins/sample/ui/libs/000077500000000000000000000000001254252253000172715ustar00rootroot00000000000000kimchi-1.5.0/plugins/sample/ui/libs/.gitignore000066400000000000000000000000001254252253000212470ustar00rootroot00000000000000kimchi-1.5.0/plugins/sample/ui/pages/000077500000000000000000000000001254252253000174375ustar00rootroot00000000000000kimchi-1.5.0/plugins/sample/ui/pages/Makefile.am000066400000000000000000000015131254252253000214730ustar00rootroot00000000000000# # 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 EXTRA_DIST = i18n.json.tmpl sample-tab1.html.tmpl sample-tab2.html.tmpl kimchi-1.5.0/plugins/sample/ui/pages/help/000077500000000000000000000000001254252253000203675ustar00rootroot00000000000000kimchi-1.5.0/plugins/sample/ui/pages/help/en_US/000077500000000000000000000000001254252253000214005ustar00rootroot00000000000000kimchi-1.5.0/plugins/sample/ui/pages/help/en_US/sample-tab1.html000066400000000000000000000000571254252253000243760ustar00rootroot00000000000000Help page for TAB 1 of Kimchi's Sample plugin. kimchi-1.5.0/plugins/sample/ui/pages/help/en_US/sample-tab2.html000066400000000000000000000000571254252253000243770ustar00rootroot00000000000000Help page for TAB 2 of Kimchi's Sample plugin. kimchi-1.5.0/plugins/sample/ui/pages/i18n.json.tmpl000066400000000000000000000015121254252253000220630ustar00rootroot00000000000000#* * Kimchi * * Copyright IBM, Corp. 2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *# #unicode UTF-8 #import gettext #from kimchi.cachebust import href #silent t = gettext.translation($lang.domain, $lang.localedir, languages=$lang.lang) #silent _ = t.gettext #silent _t = t.gettext { "SampleTab": "$_("SampleTab")" } kimchi-1.5.0/plugins/sample/ui/pages/sample-tab1.html.tmpl000066400000000000000000000016251254252253000234120ustar00rootroot00000000000000#* * Project Kimchi * * Copyright IBM, Corp. 2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *# #unicode UTF-8
kimchi-1.5.0/plugins/sample/ui/pages/sample-tab2.html.tmpl000066400000000000000000000016251254252253000234130ustar00rootroot00000000000000#* * Project Kimchi * * Copyright IBM, Corp. 2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *# #unicode UTF-8
kimchi-1.5.0/po/000077500000000000000000000000001254252253000133775ustar00rootroot00000000000000kimchi-1.5.0/po/LINGUAS000066400000000000000000000001021254252253000144150ustar00rootroot00000000000000en_US pt_BR zh_CN de_DE es_ES fr_FR it_IT ja_JP ko_KR ru_RU zh_TW kimchi-1.5.0/po/Makefile.in.in000066400000000000000000000333001254252253000160500ustar00rootroot00000000000000# Makefile for PO directory in any package using GNU gettext. # Copyright (C) 1995-1997, 2000-2007, 2009-2010 by Ulrich Drepper # # This file can be copied and used freely without restrictions. It can # be used in projects which are not available under the GNU General Public # License but which still want to provide support for the GNU gettext # functionality. # Please note that the actual code of GNU gettext is covered by the GNU # General Public License and is *not* in the public domain. # # Origin: gettext-0.18 GETTEXT_MACRO_VERSION = 0.18 PACKAGE = @PACKAGE@ VERSION = @VERSION@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ SHELL = /bin/sh @SET_MAKE@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ datarootdir = @datarootdir@ datadir = @datadir@ localedir = @prefix@/share/locale gettextsrcdir = $(datadir)/gettext/po INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ # We use $(MKDIR_P). # This macro uses the 'mkdir -p' command if possible. Otherwise, it falls back # on invoking install-sh with the -d option, so your package should contain # install-sh as described under AC_PROG_INSTALL. mkinstalldirs = $(SHELL) @install_sh@ -d install_sh = $(SHELL) @install_sh@ MKDIR_P = @MKDIR_P@ MKDIR_P = @MKDIR_P@ GMSGFMT_ = @GMSGFMT@ GMSGFMT_no = @GMSGFMT@ GMSGFMT_yes = @GMSGFMT_015@ GMSGFMT = $(GMSGFMT_$(USE_MSGCTXT)) MSGFMT_ = @MSGFMT@ MSGFMT_no = @MSGFMT@ MSGFMT_yes = @MSGFMT_015@ MSGFMT = $(MSGFMT_$(USE_MSGCTXT)) XGETTEXT_ = @XGETTEXT@ XGETTEXT_no = @XGETTEXT@ XGETTEXT_yes = @XGETTEXT_015@ XGETTEXT = $(XGETTEXT_$(USE_MSGCTXT)) MSGMERGE = msgmerge MSGMERGE_UPDATE = @MSGMERGE@ --update MSGINIT = msginit MSGCONV = msgconv MSGFILTER = msgfilter POFILES = @POFILES@ GMOFILES = @GMOFILES@ UPDATEPOFILES = @UPDATEPOFILES@ DUMMYPOFILES = @DUMMYPOFILES@ DISTFILES.common = Makefile.in.in \ $(DISTFILES.common.extra1) $(DISTFILES.common.extra2) $(DISTFILES.common.extra3) DISTFILES = $(DISTFILES.common) Makevars POTFILES.in gen-pot.in \ $(POFILES) $(GMOFILES) \ $(DISTFILES.extra1) $(DISTFILES.extra2) $(DISTFILES.extra3) POTFILES = \ CATALOGS = @CATALOGS@ # Makevars gets inserted here. (Don't remove this line!) .SUFFIXES: .SUFFIXES: .po .gmo .mo .sed .sin .nop .po-create .po-update .po.mo: @echo "$(MSGFMT) -c -o $@ $<"; \ $(MSGFMT) -c -o t-$@ $< && mv t-$@ $@ .po.gmo: @lang=`echo $* | sed -e 's,.*/,,'`; \ test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ echo "$${cdcmd}rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics --verbose -o $${lang}.gmo $${lang}.po"; \ cd $(srcdir) && rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics --verbose -o t-$${lang}.gmo $${lang}.po && mv t-$${lang}.gmo $${lang}.gmo .sin.sed: sed -e '/^#/d' $< > t-$@ mv t-$@ $@ all: check-macro-version update-gmo all-@USE_NLS@ all-yes: stamp-po all-no: # Ensure that the gettext macros and this Makefile.in.in are in sync. check-macro-version: @test "$(GETTEXT_MACRO_VERSION)" = "@GETTEXT_MACRO_VERSION@" \ || { echo "*** error: gettext infrastructure mismatch: using a Makefile.in.in from gettext version $(GETTEXT_MACRO_VERSION) but the autoconf macros are from gettext version @GETTEXT_MACRO_VERSION@" 1>&2; \ exit 1; \ } # $(srcdir)/$(DOMAIN).pot is only created when needed. When xgettext finds no # internationalized messages, no $(srcdir)/$(DOMAIN).pot is created (because # we don't want to bother translators with empty POT files). We assume that # LINGUAS is empty in this case, i.e. $(POFILES) and $(GMOFILES) are empty. # In this case, stamp-po is a nop (i.e. a phony target). # stamp-po is a timestamp denoting the last time at which the CATALOGS have # been loosely updated. Its purpose is that when a developer or translator # checks out the package via CVS, and the $(DOMAIN).pot file is not in CVS, # "make" will update the $(DOMAIN).pot and the $(CATALOGS), but subsequent # invocations of "make" will do nothing. This timestamp would not be necessary # if updating the $(CATALOGS) would always touch them; however, the rule for # $(POFILES) has been designed to not touch files that don't need to be # changed. stamp-po: $(srcdir)/$(DOMAIN).pot test ! -f $(srcdir)/$(DOMAIN).pot || \ test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES) @test ! -f $(srcdir)/$(DOMAIN).pot || { \ echo "touch stamp-po" && \ echo timestamp > stamp-poT && \ mv stamp-poT stamp-po; \ } # Note: Target 'all' must not depend on target '$(DOMAIN).pot-update', # otherwise packages like GCC can not be built if only parts of the source # have been downloaded. $(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in $(srcdir)/gen-pot $(POTFILES) # This rule has no dependencies: we don't need to update $(DOMAIN).pot at # every "make" invocation, only create it when it is missing. # Only "make $(DOMAIN).pot-update" or "make dist" will force an update. $(srcdir)/$(DOMAIN).pot: $(MAKE) $(DOMAIN).pot-update # This target rebuilds a PO file if $(DOMAIN).pot has changed. # Note that a PO file is not touched if it doesn't need to be changed. $(POFILES): $(srcdir)/$(DOMAIN).pot @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \ if test -f "$(srcdir)/$${lang}.po"; then \ test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ echo "$${cdcmd}$(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --lang=$${lang} $${lang}.po $(DOMAIN).pot"; \ cd $(srcdir) \ && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ '' | 0.[0-9] | 0.[0-9].* | 0.1[0-7] | 0.1[0-7].*) \ $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \ *) \ $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --lang=$${lang} $${lang}.po $(DOMAIN).pot;; \ esac; \ }; \ else \ $(MAKE) $${lang}.po-create; \ fi install: install-exec install-data install-exec: install-data: install-data-@USE_NLS@ if test "$(PACKAGE)" = "gettext-tools"; then \ $(MKDIR_P) $(DESTDIR)$(gettextsrcdir); \ for file in $(DISTFILES.common) Makevars.template; do \ $(INSTALL_DATA) $(srcdir)/$$file \ $(DESTDIR)$(gettextsrcdir)/$$file; \ done; \ for file in Makevars; do \ rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ done; \ else \ : ; \ fi install-data-no: all install-data-yes: all @catalogs='$(CATALOGS)'; \ for cat in $$catalogs; do \ cat=`basename $$cat`; \ lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ dir=$(localedir)/$$lang/LC_MESSAGES; \ $(MKDIR_P) $(DESTDIR)$$dir; \ if test -r $$cat; then realcat=$$cat; else realcat=$(srcdir)/$$cat; fi; \ $(INSTALL_DATA) $$realcat $(DESTDIR)$$dir/$(DOMAIN).mo; \ echo "installing $$realcat as $(DESTDIR)$$dir/$(DOMAIN).mo"; \ for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \ if test -n "$$lc"; then \ if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \ link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \ mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ (cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \ for file in *; do \ if test -f $$file; then \ ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \ fi; \ done); \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ else \ if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \ :; \ else \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \ mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ fi; \ fi; \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ ln -s ../LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \ ln $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \ cp -p $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ echo "installing $$realcat link as $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo"; \ fi; \ done; \ done install-strip: install installdirs: installdirs-exec installdirs-data installdirs-exec: installdirs-data: installdirs-data-@USE_NLS@ if test "$(PACKAGE)" = "gettext-tools"; then \ $(MKDIR_P) $(DESTDIR)$(gettextsrcdir); \ else \ : ; \ fi installdirs-data-no: installdirs-data-yes: @catalogs='$(CATALOGS)'; \ for cat in $$catalogs; do \ cat=`basename $$cat`; \ lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ dir=$(localedir)/$$lang/LC_MESSAGES; \ $(MKDIR_P) $(DESTDIR)$$dir; \ for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \ if test -n "$$lc"; then \ if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \ link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \ mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ (cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \ for file in *; do \ if test -f $$file; then \ ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \ fi; \ done); \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ else \ if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \ :; \ else \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \ mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ fi; \ fi; \ fi; \ done; \ done # Define this as empty until I found a useful application. installcheck: uninstall: uninstall-exec uninstall-data uninstall-exec: uninstall-data: uninstall-data-@USE_NLS@ if test "$(PACKAGE)" = "gettext-tools"; then \ for file in $(DISTFILES.common) Makevars.template; do \ rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ done; \ else \ : ; \ fi uninstall-data-no: uninstall-data-yes: catalogs='$(CATALOGS)'; \ for cat in $$catalogs; do \ cat=`basename $$cat`; \ lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ for lc in LC_MESSAGES $(EXTRA_LOCALE_CATEGORIES); do \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ done; \ done check: all info dvi ps pdf html tags TAGS ctags CTAGS ID: mostlyclean: rm -f remove-potcdate.sed rm -f stamp-poT rm -f core core.* $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po rm -fr *.o clean: mostlyclean distclean: clean rm -f Makefile Makefile.in POTFILES *.mo maintainer-clean: distclean @echo "This command is intended for maintainers to use;" @echo "it deletes files that may require special tools to rebuild." rm -f stamp-po $(GMOFILES) distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) dist distdir: $(MAKE) update-po @$(MAKE) dist2 # This is a separate target because 'update-po' must be executed before. dist2: stamp-po $(DISTFILES) dists="$(DISTFILES)"; \ if test "$(PACKAGE)" = "gettext-tools"; then \ dists="$$dists Makevars.template"; \ fi; \ if test -f $(srcdir)/$(DOMAIN).pot; then \ dists="$$dists $(DOMAIN).pot stamp-po"; \ fi; \ if test -f $(srcdir)/ChangeLog; then \ dists="$$dists ChangeLog"; \ fi; \ for i in 0 1 2 3 4 5 6 7 8 9; do \ if test -f $(srcdir)/ChangeLog.$$i; then \ dists="$$dists ChangeLog.$$i"; \ fi; \ done; \ if test -f $(srcdir)/LINGUAS; then dists="$$dists LINGUAS"; fi; \ for file in $$dists; do \ if test -f $$file; then \ cp -p $$file $(distdir) || exit 1; \ else \ cp -p $(srcdir)/$$file $(distdir) || exit 1; \ fi; \ done update-po: Makefile $(MAKE) $(DOMAIN).pot-update test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES) $(MAKE) update-gmo # General rule for creating PO files. .nop.po-create: @lang=`echo $@ | sed -e 's/\.po-create$$//'`; \ echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \ exit 1 # General rule for updating PO files. .nop.po-update: @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \ if test "$(PACKAGE)" = "gettext-tools"; then PATH=`pwd`/../src:$$PATH; fi; \ tmpdir=`pwd`; \ echo "$$lang:"; \ test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ echo "$${cdcmd}$(MSGMERGE) $(MSGMERGE_OPTIONS) --lang=$$lang $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \ cd $(srcdir); \ if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ '' | 0.[0-9] | 0.[0-9].* | 0.1[0-7] | 0.1[0-7].*) \ $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \ *) \ $(MSGMERGE) $(MSGMERGE_OPTIONS) --lang=$$lang -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \ esac; \ }; then \ if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ rm -f $$tmpdir/$$lang.new.po; \ else \ if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ :; \ else \ echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ exit 1; \ fi; \ fi; \ else \ echo "msgmerge for $$lang.po failed!" 1>&2; \ rm -f $$tmpdir/$$lang.new.po; \ fi $(DUMMYPOFILES): update-gmo: Makefile $(GMOFILES) @: # Recreate Makefile by invoking config.status. Explicitly invoke the shell, # because execution permission bits may not work on the current file system. # Use @SHELL@, which is the shell determined by autoconf for the use by its # scripts, not $(SHELL) which is hardwired to /bin/sh and may be deficient. Makefile: Makefile.in.in Makevars $(top_builddir)/config.status @POMAKEFILEDEPS@ cd $(top_builddir) \ && @SHELL@ ./config.status $(subdir)/$@.in po-directories force: # Tell versions [3.59,3.63) of GNU make not to export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: kimchi-1.5.0/po/Makevars000066400000000000000000000034131254252253000150740ustar00rootroot00000000000000# Makefile variables for PO directory in any package using GNU gettext. # Usually the message domain is the same as the package name. DOMAIN = kimchi # These two variables depend on the location of this directory. subdir = po top_builddir = .. # These options get passed to xgettext. XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ # This is the copyright holder that gets inserted into the header of the # $(DOMAIN).pot file. Set this to the copyright holder of the surrounding # package. (Note that the msgstr strings, extracted from the package's # sources, belong to the copyright holder of the package.) Translators are # expected to transfer the copyright for their translations to this person # or entity, or to disclaim their copyright. The empty string stands for # the public domain; in this case the translators are expected to disclaim # their copyright. COPYRIGHT_HOLDER = # This is the email address or URL to which the translators shall report # bugs in the untranslated strings: # - Strings which are not entire sentences, see the maintainer guidelines # in the GNU gettext documentation, section 'Preparing Strings'. # - Strings which use unclear terms or require additional context to be # understood. # - Strings which make invalid assumptions about notation of date, time or # money. # - Pluralisation problems. # - Incorrect English spelling. # - Incorrect formatting. # It can be your email address, or a mailing list address where translators # can write to without being subscribed, or the URL of a web page through # which the translators can contact you. MSGID_BUGS_ADDRESS = project-kimchi@googlegroups.com # This is the list of locale categories, beyond LC_MESSAGES, for which the # message catalogs shall be used. It is usually empty. EXTRA_LOCALE_CATEGORIES = kimchi-1.5.0/po/POTFILES.in000066400000000000000000000001631254252253000151540ustar00rootroot00000000000000# List of source files which contain translatable strings. src/kimchi/i18n.py ui/pages/*.tmpl ui/pages/tabs/*.tmpl kimchi-1.5.0/po/de_DE.po000066400000000000000000001656701254252253000147160ustar00rootroot00000000000000# English translations for kimchi package. # Copyright (C) 2013 ORGANIZATION # msgid "" msgstr "" "Project-Id-Version: kimchi 0.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-06-24 09:39-0300\n" "PO-Revision-Date: 2013-07-11 17:32-0400\n" "Last-Translator: Crístian Viana \n" "Language-Team: English\n" "Language: de_DE\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: pygettext.py 1.5\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #, python-format msgid "Unknown parameter %(value)s" msgstr "" #, python-format msgid "Delete is not allowed for %(resource)s" msgstr "Löschen ist nicht zulässig für %(resource)s" #, python-format msgid "%(resource)s does not implement update method" msgstr "%(resource)s implementiert keine Aktualisierungsmethode" #, python-format msgid "Create is not allowed for %(resource)s" msgstr "Erstellen ist nicht zulässig für %(resource)s" msgid "Unable to parse JSON request" msgstr "JSON-Anfrage konnte nicht analysiert werden" msgid "This API only supports JSON" msgstr "Diese API unterstützt nur JSON" #, python-format msgid "Parameters does not match requirement in schema: %(err)s" msgstr "" msgid "You don't have permission to perform this operation." msgstr "" msgid "Datastore is not initiated in the model object." msgstr "Datenspeicher wird nicht im Modellobjekt initialisiert." #, python-format msgid "Unable to start task due error: %(err)s" msgstr "" "Task kann aufgrund des folgenden Fehlers nicht gestartet werden: %(err)s" #, python-format msgid "Timeout of %(seconds)s seconds expired while running task '%(task)s." msgstr "" #, python-format msgid "Authentication failed for user '%(username)s'. [Error code: %(code)s]" msgstr "" "Authentifizierung für Benutzer '%(username)s' fehlgeschlagen. [Fehlercode: " "%(code)s]" msgid "You are not authorized to access Kimchi" msgstr "Sie sind nicht berechtigt, auf Kimchi zuzugreifen" #, python-format msgid "Specify %(item)s to login into Kimchi" msgstr "Geben Sie %(item)s an, um sich bei Kimchi anzumelden" #, python-format msgid "User %(user_id)s not found with given LDAP settings." msgstr "" #, python-format msgid "Invalid LDAP configuration: %(item)s : %(value)s" msgstr "" msgid "Unknown \"_cap\" specified" msgstr "" msgid "\"_passthrough\" should be \"true\" or \"false\"" msgstr "" msgid "\"_passthrough_affected_by\" should be a device name string" msgstr "" #, python-format msgid "Error while getting block devices. Details: %(err)s" msgstr "Fehler beim Abrufen von Blockeinheiten. Details: %(err)s" #, python-format msgid "Error while getting block device information for %(device)s." msgstr "Fehler beim Abrufen von Blockeinheitinformationen für %(device)s." #, python-format msgid "Unable to find distro file: %(filename)s" msgstr "Distro-Datei konnte nicht gefunden werden: %(filename)s" #, python-format msgid "" "Unable to parse distro file: %(filename)s. Make sure, it is a JSON file." msgstr "" "Distro-Datei konnte nicht analysiert werden: %(filename)s. Stellen Sie " "sicher, dass es sich um eine JSON-Datei handelt." #, python-format msgid "Unable to login to iSCSI host target %(portal)s. Details: %(err)s" msgstr "Fehler beim Anmelden bei iSCSI-Hostziel %(portal)s. Details: %(err)s" #, python-format msgid "Unable to login to iSCSI host %(host)s target %(target)s" msgstr "Anmeldung bei iSCSI-Host %(host)s Ziel %(target)s nicht möglich" #, python-format msgid "Unable to find ISO file %(filename)s" msgstr "" #, python-format msgid "The ISO file %(filename)s is not bootable" msgstr "Die ISO-Datei %(filename)s ist nicht bootfähig" #, python-format msgid "The ISO file %(filename)s does not have a valid El Torito boot record" msgstr "Die ISO-Datei %(filename)s hat keinen gültigen El Torito-Bootsatz" #, python-format msgid "Invalid El Torito validation entry in ISO %(filename)s" msgstr "Ungültiger El Torito-Prüfeintrag in ISO-Datei %(filename)s" #, python-format msgid "Invalid El Torito boot indicator in ISO %(filename)s" msgstr "Ungültiger El Torito-Boot-Indikator in ISO-Datei %(filename)s" #, python-format msgid "Unexpected volume type for primary volume in ISO %(filename)s" msgstr "" "Unerwarteter Datenträgertyp für Primärdatenträger in ISO-Datei %(filename)s" #, python-format msgid "Bad format while reading volume descriptor in ISO %(filename)s" msgstr "" "Ungültiges Format beim Lesen des Datenträgerdeskriptors in ISO-Datei " "%(filename)s" #, python-format msgid "" "The hypervisor doesn't have permission to use this ISO %(filename)s. " "Consider moving it under /var/lib/libvirt, or set the search permission to " "file access control lists for '%(user)s' user if possible, or add the " "'%(user)s' to the ISO path group, or (not recommended) 'chmod -R o+x " "'path_to_iso'.Details: %(err)s" msgstr "" "Der Hypervisor hat nicht die Berechtigung, die ISO-Datei %(filename)s zu " "verwenden. Verschieben Sie sie entweder nach /var/lib/libvirt oder setzen " "Sie, sofern möglich, die Suchberechtigung auf Dateizugriffssteuerungslisten " "für den Benutzer '%(user)s' oder fügen Sie '%(user)s' der ISO-Pfadgruppe " "hinzu oder (nicht empfohlen) 'chmod -R o+x 'path_to_iso'. Details: %(err)s" msgid "An error occurred when probing image OS information." msgstr "" msgid "No OS information found in given image." msgstr "" #, python-format msgid "Unable to read image file %(filename)s" msgstr "" #, python-format msgid "" "Image file must be an existing file on system. %(filename)s is not a valid " "input." msgstr "" #, python-format msgid "Virtual machine %(name)s already exists" msgstr "Virtuelle Maschine %(name)s ist bereits vorhanden" #, python-format msgid "Virtual machine %(name)s does not exist" msgstr "Virtuelle Maschine %(name)s ist nicht vorhanden" #, python-format msgid "" "Unable to rename virtual machine %(name)s. The name %(new_name)s is already " "in use or the virtual machine is not powered off." msgstr "" #, python-format msgid "Unable to retrieve screenshot for stopped virtual machine %(name)s" msgstr "" "Screenshot für gestoppte virtuelle Maschine %(name)s konnte nicht abgerufen " "werden" msgid "Remote ISO image is not supported by this server." msgstr "Fernes ISO-Image wird von diesem Server nicht unterstützt." #, python-format msgid "Screenshot is not supported on virtual machine %(name)s" msgstr "" #, python-format msgid "Unable to create virtual machine %(name)s. Details: %(err)s" msgstr "" "Virtuelle Maschine %(name)s konnte nicht erstellt werden. Details: %(err)s" #, python-format msgid "Unable to update virtual machine %(name)s. Details: %(err)s" msgstr "" "Virtuelle Maschine %(name)s konnte nicht erstellt werden. Details: %(err)s" #, python-format msgid "Unable to retrieve virtual machine %(name)s. Details: %(err)s" msgstr "" "Virtuelle Maschine %(name)s konnte nicht abgerufen werden. Details: %(err)s" #, python-format msgid "Unable to connect to powered off virtual machine %(name)s." msgstr "" "Verbindung zur abgeschalteten Maschine %(name)s konnte nicht hergestellt " "werden." msgid "Virtual machine name must be a string without slashes (/)" msgstr "" #, python-format msgid "Invalid template URI %(value)s specified for virtual machine" msgstr "" #, python-format msgid "Invalid storage pool URI %(value)s specified for virtual machine" msgstr "" msgid "Supported virtual machine graphics are Spice or VNC" msgstr "" msgid "Graphics address to listen on must be IPv4 or IPv6" msgstr "Zu überwachende Grafikadresse muss IPv4 oder IPv6 sein" msgid "Specify a template to create a virtual machine from" msgstr "Vorlage angeben, aus der eine virtuelle Maschine erstellt werden soll" #, python-format msgid "Unable to start virtual machine %(name)s. Details: %(err)s" msgstr "" "Virtuelle Maschine %(name)s konnte nicht gestartet werden. Details: %(err)s" #, python-format msgid "Unable to power off virtual machine %(name)s. Details: %(err)s" msgstr "" "Virtuelle Maschine %(name)s konnte nicht gestoppt werden. Details: %(err)s" #, python-format msgid "Unable to delete virtual machine %(name)s. Details: %(err)s" msgstr "" "Virtuelle Maschine %(name)s konnte nicht gelöscht werden. Details: %(err)s" #, python-format msgid "Unable to reset virtual machine %(name)s. Details: %(err)s" msgstr "" "Virtuelle Maschine %(name)s konnte nicht umbenannt werden. Details: %(err)s" msgid "User name list must be an array" msgstr "" msgid "User name must be a string" msgstr "Netzname muss eine Zeichenfolge sein" msgid "Group name list must be an array" msgstr "" msgid "Group name must be a string" msgstr "Netzname muss eine Zeichenfolge sein" #, python-format msgid "User(s) '%(users)s' do not exist" msgstr "Benutzer '%(users)s' ist nicht vorhanden." #, python-format msgid "Group(s) '%(groups)s' do not exist" msgstr "Benutzer '%(groups)s' ist nicht vorhanden." #, python-format msgid "Unable to shutdown virtual machine %(name)s. Details: %(err)s" msgstr "" "Virtuelle Maschine %(name)s konnte nicht gestoppt werden. Details: %(err)s" #, python-format msgid "" "Unable to get access metadata of virtual machine %(name)s. Details: %(err)s" msgstr "" "Virtuelle Maschine %(name)s konnte nicht gestartet werden. Details: %(err)s" msgid "The guest console password must be a string." msgstr "" msgid "The life time for the guest console password must be a number." msgstr "" #, python-format msgid "Virtual machine '%(name)s' must be stopped before cloning it." msgstr "" #, python-format msgid "Insufficient disk space to clone virtual machine '%(name)s'" msgstr "" #, python-format msgid "Unable to clone VM '%(name)s'. Details: %(err)s" msgstr "" #, python-format msgid "Invalid operation for non-persistent virtual machine %(name)s" msgstr "" #, python-format msgid "Cannot suspend VM '%(name)s' because it is not running." msgstr "" #, python-format msgid "Unable to suspend VM '%(name)s'. Details: %(err)s" msgstr "" #, python-format msgid "Cannot resume VM '%(name)s' because it is not paused." msgstr "" #, python-format msgid "Unable to resume VM '%(name)s'. Details: %(err)s" msgstr "" msgid "Memory assigned is higher then the maximum allowed in the host." msgstr "" #, python-format msgid "" "VM '%(name)s' does not support live memory update. Update the memory with " "the machine offline to enable this feature." msgstr "" msgid "Only increase memory is allowed in active VMs" msgstr "" msgid "" "For live memory update, new memory value must be equal old memory value plus " "multiples of 1024 Mib" msgstr "" msgid "There are not enough free slots of 1024 Mib in the guest." msgstr "" msgid "" "Host's libvirt version does not support memory devices. Libvirt must be >= " "1.2.14" msgstr "" #, python-format msgid "Error attaching memory device. Details: %(error)s" msgstr "" #, python-format msgid "" "VM %(vmid)s does not contain directly assigned host device %(dev_name)s." msgstr "" #, python-format msgid "The host device %(dev_name)s is not allowed to directly assign to VM." msgstr "" msgid "" "No IOMMU groups found. Host PCI pass through needs IOMMU group to function " "correctly. Please enable Intel VT-d or AMD IOMMU in your BIOS, then verify " "the Kernel is compiled with IOMMU support. For Intel CPU, add intel_iommu=on " "to your Kernel parameter in /boot/grub2/grub.conf. For AMD CPU, add iommu=pt " "iommu=1." msgstr "" msgid "\"name\" should be a device name string" msgstr "" #, python-format msgid "" "The device %(name)s is probably in use by the host. Unable to attach it to " "the guest." msgstr "" #, python-format msgid "Interface %(iface)s does not exist in virtual machine %(name)s" msgstr "" "Schnittstelle %(iface)s ist in virtueller Maschine %(name)s nicht vorhanden" #, python-format msgid "" "Network %(network)s specified for virtual machine %(name)s does not exist" msgstr "" "Das für die virtuelle Maschine %(name)s angegebene Netz %(network)s ist " "nicht vorhanden" msgid "Supported virtual machine interfaces type is only network" msgstr "Unterstützter Schnittstellentyp einer virtuellen Maschine ist nur Netz" msgid "Network name for virtual machine interface must be a string" msgstr "" "Netzname für Schnittstelle einer virtuellen Maschine muss eine Zeichenfolge " "sein" msgid "Invalid network model card specified for virtual machine interface" msgstr "" "Ungültige Netzmodellkarte für Schnittstelle einer virtuellen Maschine " "angegeben" msgid "Specify type and network to add a new virtual machine interface" msgstr "" "Geben Sie Typ und Netz an, um eine neue Schnittstelle für eine virtuelle " "Maschine hinzuzufügen" msgid "MAC Address must respect this format FF:FF:FF:FF:FF:FF" msgstr "" #, python-format msgid "MAC Address %(mac)s already exists in virtual machine %(name)s" msgstr "" msgid "Invalid MAC Address" msgstr "" msgid "Cannot change MAC address of a running virtual machine" msgstr "" #, python-format msgid "Template %(name)s already exists" msgstr "Vorlage %(name)s ist bereits vorhanden" #, python-format msgid "" "Network '%(network)s' specified for template %(template)s does not exist" msgstr "" "Das für Vorlage %(template)s angegebene Netz '%(network)s' ist nicht " "vorhanden" #, python-format msgid "" "Storage pool %(pool)s specified for template %(template)s does not exist" msgstr "" "Der für Vorlage %(template)s angegebene Speicherpool '%(pool)s' ist nicht " "vorhanden" #, python-format msgid "Storage pool %(pool)s specified for template %(template)s is not active" msgstr "" "Der für Vorlage %(template)s angegebene Speicherpool '%(pool)s' ist nicht " "aktiv" #, python-format msgid "Invalid parameter '%(param)s' specified for CDROM." msgstr "Ungültiger Parameter '%(param)s' für CD-ROM angegeben." #, python-format msgid "Network %(network)s specified for template %(template)s is not active" msgstr "" "Das für Vorlage %(template)s angegebene Netz %(network)s ist nicht aktiv" msgid "Template name must be a string" msgstr "Vorlagenname muss eine Zeichenfolge sein" msgid "Template icon must be a path to the image" msgstr "Vorlagensymbol muss ein Pfad zum Image sein" msgid "Template distribution must be a string" msgstr "Vorlagenverteilung muss eine Zeichenfolge sein" msgid "Template distribution version must be a string" msgstr "Vorlagenverteilungsversion muss eine Zeichenfolge sein" msgid "The number of CPUs must be an integer greater than 0" msgstr "Die Anzahl der CPUs muss eine Ganzzahl sein" msgid "Amount of memory (MB) must be an integer greater than 512" msgstr "Speicherkapazität (MB) muss eine Ganzzahl größer als 512 sein" msgid "Template CDROM must be a local or remote ISO file" msgstr "Vorlagen-CD-ROM muss eine lokale oder ferne ISO-Datei sein" #, python-format msgid "Invalid storage pool URI %(value)s specified for template" msgstr "Ungültiger Speicherpool-URI %(value)s für Vorlage angegeben" msgid "Specify an ISO image as CDROM or a base image to create a template" msgstr "Geben Sie ein ISO-Image als CD-ROM an, um eine Vorlage zu erstellen" msgid "All networks for the template must be specified in a list." msgstr "Alle Netze für die Vorlage müssen in einer Liste angegeben werden." msgid "Specify a volume to a template when storage pool is iSCSI or SCSI" msgstr "" #, python-format msgid "The volume %(volume)s is not in storage pool %(pool)s" msgstr "" #, python-format msgid "Unable to create template due error: %(err)s" msgstr "" "Vorlage kann aufgrund des folgenden Fehlers nicht erstellt werden: %(err)s" #, python-format msgid "Unable to delete template due error: %(err)s" msgstr "" "Vorlage kann aufgrund des folgenden Fehlers nicht gelöscht werden: %(err)s" msgid "Disk size must be an integer greater than 1GB." msgstr "" msgid "Template base image must be a valid local image file" msgstr "Vorlagen-CD-ROM muss eine lokale oder ferne ISO-Datei sein" #, python-format msgid "Cannot identify base image %(path)s format" msgstr "" msgid "" "When specifying CPU topology, VCPUs must be a product of sockets, cores, and " "threads." msgstr "" msgid "" "When specifying CPU topology, each element must be an integer greater than " "zero." msgstr "" msgid "" "Invalid disk image format. Valid formats: bochs, cloop, cow, dmg, qcow, " "qcow2, qed, raw, vmdk, vpc." msgstr "" #, python-format msgid "Storage pool %(name)s already exists" msgstr "Speicherpool %(name)s ist bereits vorhanden" #, python-format msgid "Storage pool %(name)s does not exist" msgstr "Speicherpool %(name)s ist nicht vorhanden" #, python-format msgid "Specify %(item)s in order to create the storage pool %(name)s" msgstr "Geben Sie %(item)s an, um den Speicherpool %(name)s zu erstellen" #, python-format msgid "Unable to delete active storage pool %(name)s" msgstr "Aktiver Speicherpool %(name)s konnte nicht gelöscht werden" #, python-format msgid "Unable to list storage pools. Details: %(err)s" msgstr "Speicherpools konnten nicht aufgelistet werden. Details: %(err)s" #, python-format msgid "Unable to create storage pool %(name)s. Details: %(err)s" msgstr "Speicherpool %(name)s konnte nicht erstellt werden. Details: %(err)s" #, python-format msgid "" "Unable to get number of storage volumes in storage pool %(name)s. Details: " "%(err)s" msgstr "" "Anzahl der Speicherdatenträger im Speicherpool %(name)s konnte nicht " "abgerufen werden. Details: %(err)s" #, python-format msgid "Unable to activate storage pool %(name)s. Details: %(err)s" msgstr "Speicherpool %(name)s konnte nicht aktiviert werden. Details: %(err)s" #, python-format msgid "Unable to deactivate storage pool %(name)s. Details: %(err)s" msgstr "" "Speicherpool %(name)s konnte nicht inaktiviert werden. Details: %(err)s" #, python-format msgid "Unable to delete storage pool %(name)s. Details: %(err)s" msgstr "Speicherpool %(name)s konnte nicht gelöscht werden. Details: %(err)s" #, python-format msgid "" "Unable to create NFS Pool as export path %(path)s may block during mount" msgstr "" "NFS-Pool konnte nicht erstellt werden, weil Exportpfad %(path)s beim Mounten " "blockieren kann" #, python-format msgid "Unable to create NFS Pool as export path %(path)s mount failed" msgstr "" "NFS-Pool konnte nicht erstellt werden, weil das Mounten des Exportpfads" "%(path)s fehlgeschlagen ist" #, python-format msgid "Unsupported storage pool type: %(type)s" msgstr "Nicht unterstützter Speicherpooltyp: %(type)s" #, python-format msgid "Error while retrieving storage pool XML to %(pool)s" msgstr "" msgid "Storage pool name must be a string without slashes (/)" msgstr "" msgid "" "Supported storage pool types are dir, netfs, logical, iscsi, isci and kimchi-" "iso" msgstr "" msgid "Storage pool path must be a string" msgstr "Speicherpoolpfad muss eine Zeichenfolge sein" msgid "Storage pool host must be a IP or hostname" msgstr "Speicherpoolhost muss eine IP oder ein Hostname sein" msgid "Storage pool device must be the absolute path to the block device" msgstr "" msgid "Storage pool devices parameter must be a list" msgstr "Einheitenparameter des Speicherpools muss eine Liste sein" msgid "Target IQN of an iSCSI pool must be a string" msgstr "Ziel-IQN eines iSCSI-Pools muss eine Zeichenfolge sein" msgid "Port of a remote storage server must be an integer between 1 and 65535" msgstr "" "Port eines fernen Speicherservers muss eine Ganzzahl zwischen 1 und 65535 " "sein" msgid "iSCSI target username must be a string" msgstr "" msgid "iSCSI target password must be a string" msgstr "" msgid "Specify name and type to create a storage pool" msgstr "Geben Sie Name und Typ an, um einen Speicherpool zu erstellen" #, python-format msgid "" "%(disk)s is not a valid disk/partition. Could not add it to the pool " "%(pool)s." msgstr "" "%(disk)s ist keine gültige Platte/Partition. Sie konnte nicht hinzugefügt " "werden zum Pool %(pool)s." #, python-format msgid "Unable to extend logical pool %(pool)s. Details: %(err)s" msgstr "" msgid "The parameter disks only can be updated for logical storage pool." msgstr "" "Die Parameterplatten können nur für den logischen Speicherpool aktualisiert " "werden." msgid "The SCSI host adapter name must be a string." msgstr "Der Name des SCSI-Hostadapters muss eine Zeichenfolge sein." msgid "The storage pool kimchi_isos is reserved for internal use" msgstr "Der Speicherpool kimchi_isos ist für die interne Verwendung reserviert" #, python-format msgid "" "Unable to activate NFS storage pool %(name)s. NFS server %(server)s is " "unreachable." msgstr "" "Der NFS-Speicherpool %(name)s konnte nicht aktiviert werden. NFS-Server " "%(server)s ist nicht erreichbar." #, python-format msgid "" "Unable to deactivate NFS storage pool %(name)s. NFS server %(server)s is " "unreachable." msgstr "" "Der NFS-Speicherpool %(name)s konnte nicht inaktiviert werden. NFS-Server " "%(server)s ist nicht erreichbar." #, python-format msgid "" "Unable to deactivate pool %(name)s as it is associated with some templates" msgstr "" "Pool %(name)s konnte nicht inaktiviert werden, weil er einigen Vorlagen " "zugeordnet ist" #, python-format msgid "Unable to delete pool %(name)s as it is associated with some templates" msgstr "" "Pool %(name)s konnte nicht gelöscht werden, weil er einigen Vorlagen " "zugeordnet ist" #, python-format msgid "" "A volume group named '%(name)s' already exists. Please, choose another name " "to create the logical pool." msgstr "" "Eine Datenträgergruppe mit dem Namen '%(name)s' ist bereits vorhanden. " "Wählen Sie einen anderen Namen aus, um den logischen Pool zu erstellen." #, python-format msgid "Unable to update database with deep scan information due error: %(err)s" msgstr "" "Datenbank mit Tiefenscaninformationen kann aufgrund des folgenden Fehlers " "nicht aktualisiert werden: %(err)s" #, python-format msgid "Storage volume %(name)s already exists" msgstr "Speicherdatenträger %(name)s ist bereits vorhanden" #, python-format msgid "Storage volume %(name)s does not exist in storage pool %(pool)s" msgstr "" "Speicherdatenträger %(name)s ist nicht im Speicherpool %(pool)s vorhanden" #, python-format msgid "" "Unable to create storage volume %(volume)s because storage pool %(pool)s is " "not active" msgstr "" #, python-format msgid "Specify %(item)s in order to create storage volume %(volume)s" msgstr "Geben Sie %(item)s an, um Speicherdatenträger %(volume)s zu erstellen" #, python-format msgid "" "Unable to list storage volumes because storage pool %(pool)s is not active" msgstr "" "Speicherdatenträger konnten nicht aufgelistet werden, weil Speicherpool " "%(pool)s nicht aktiv ist" #, python-format msgid "" "Unable to create storage volume %(name)s in storage pool %(pool)s. Details: " "%(err)s" msgstr "" "Speicherdatenträger %(name)s konnte nicht in Speicherpool %(pool)s erstellt " "werden. Details: %(err)s" #, python-format msgid "" "Unable to list storage volumes in storage pool %(pool)s. Details: %(err)s" msgstr "" "Speicherdatenträger konnten nicht in Speicherpool %(pool)s aufgelistet " "werden. Details: %(err)s" #, python-format msgid "Unable to wipe storage volumes %(name)s. Details: %(err)s" msgstr "" "Speicherdatenträger %(name)s konnten nicht bereinigt werden. Details: %(err)s" #, python-format msgid "Unable to delete storage volume %(name)s. Details: %(err)s" msgstr "" "Speicherdatenträger %(name)s konnte nicht gelöscht werden. Details: %(err)s" #, python-format msgid "Unable to resize storage volume %(name)s. Details: %(err)s" msgstr "" "Größe des Speicherdatenträgers %(name)s konnte nicht geändert werden. " "Details: %(err)s" #, python-format msgid "Storage type %(type)s does not support volume create and delete" msgstr "" "Speichertyp %(type)s unterstützt nicht das Erstellen und Löschen von " "Datenträgern" msgid "Storage volume name must be a string" msgstr "Name des Speicherdatenträgers muss eine Zeichenfolge sein" msgid "Storage volume allocation must be an integer number" msgstr "Zuordnung des Speicherdatenträgers muss eine Ganzzahl sein" msgid "" "Storage volume format not supported. Valid formats: bochs, cloop, cow, dmg, " "qcow, qcow2, qed, raw, vmdk, vpc." msgstr "" msgid "Storage volume requires a volume name" msgstr "Speicherdatenträger erfordert einen Datenträgernamen" #, python-format msgid "" "Unable to update database with storage volume information due error: %(err)s" msgstr "" "Datenbank mit Datenträgerinformationen kann aufgrund des folgenden Fehlers " "nicht aktualisiert werden: %(err)s" #, python-format msgid "Only one of parameter %(param)s can be specified" msgstr "" #, python-format msgid "Create volume from %(param)s is not supported" msgstr "" msgid "Storage volume capacity must be an integer number." msgstr "" msgid "Storage volume URL must be http://, https://, ftp:// or ftps://." msgstr "" #, python-format msgid "Unable to access file %(url)s. Please, check it." msgstr "" #, python-format msgid "" "Unable to clone storage volume '%(name)s' in pool '%(pool)s'. Details: " "%(err)s" msgstr "" msgid "Specify chunk data and its size to upload a file." msgstr "" msgid "In order to upload a storage volume, specify the 'upload' parameter." msgstr "" msgid "" "Unable to upload chunk data as it does not match with requested chunk size." msgstr "" #, python-format msgid "The storage volume %(vol)s is not under an upload process." msgstr "" msgid "The upload chunk data will exceed the storage volume size." msgstr "" #, python-format msgid "Unable to upload chunk data to storage volume. Details: %(err)s." msgstr "" #, python-format msgid "Interface %(name)s does not exist" msgstr "Schnittstelle %(name)s ist nicht vorhanden" #, python-format msgid "Network %(name)s already exists" msgstr "Netz %(name)s ist bereits vorhanden" #, python-format msgid "Network %(name)s does not exist" msgstr "Netz %(name)s ist nicht vorhanden" #, python-format msgid "Subnet %(subnet)s specified for network %(network)s is not valid." msgstr "" "Das für das Netz %(network)s angegebene Teilnetz %(subnet)s ist nicht gültig." #, python-format msgid "Specify a network interface to create bridged network %(name)s" msgstr "" "Geben Sie eine Netzschnittstelle an, um überbrücktes Netz %(name)s zu " "erstellen" #, python-format msgid "Unable to delete active network %(name)s" msgstr "Aktives Netz %(name)s konnte nicht gelöscht werden" #, python-format msgid "Interface %(iface)s specified for network %(network)s is already in use" msgstr "" "Die für das Netz %(network)s angegebene Schnittstelle %(iface)s wird bereits " "verwendet" msgid "Interface should be bare NIC, bonding or bridge device." msgstr "Schnittstelle sollte bloßes NIC, Bonding oder Brückeneinheit sein." #, python-format msgid "Unable to create network %(name)s. Details: %(err)s" msgstr "Netz %(name)s konnte nicht erstellt werden. Details: %(err)s" #, python-format msgid "Unable to find a free IP address for network '%(name)s'" msgstr "Es konnte keine freie IP-Adresse für Netz '%(name)s' gefunden werden" #, python-format msgid "The interface %(iface)s already exists." msgstr "" msgid "Network name must be a string without slashes (/) or quotes (\")" msgstr "" msgid "Supported network types are isolated, NAT and bridge" msgstr "Unterstützte Netztypen sind Isoliert, NAT und Brücke" msgid "Network subnet must be a string with IP address and prefix or netmask" msgstr "" "Teilnetz des Netzes muss eine Zeichenfolge mit IP-Adresse und Präfix oder " "Netzmaske sein" msgid "Network interface must be a string" msgstr "Netzschnittstelle muss eine Zeichenfolge sein" msgid "Network VLAN ID must be an integer between 1 and 4094" msgstr "Netz-VLAN-ID muss eine Ganzzahl zwischen 1 und 4094 sein" msgid "Specify name and type to create a Network" msgstr "Geben Sie Name und Typ an, um ein Netz zu erstellen" #, python-format msgid "" "Unable to delete network %(name)s. There are some virtual machines %(vms)s " "and/or templates linked to this network." msgstr "" "Netz %(name)s konnte nicht inaktiviert werden. Es sind einige virtuellen " "Maschinen %(vms)s und/oder Vorlagen mit diesem Netz verknüpft." #, python-format msgid "" "Unable to deactivate network %(name)s. There are some virtual machines " "%(vms)s and/or templates linked to this network." msgstr "" "Netz %(name)s konnte nicht inaktiviert werden. Es sind einige virtuellen " "Maschinen %(vms)s und/oder Vorlagen mit diesem Netz verknüpft." #, python-format msgid "Bridge device %(name)s can not be the trunk device of a VLAN." msgstr "Brückeneinheit %(name)s kann nicht die Trunkeinheit eines VLAN sein." #, python-format msgid "Failed to activate interface %(iface)s: %(err)s." msgstr "Schnittstelle %(iface)s konnte nicht aktiviert werden: %(err)s." #, python-format msgid "" "Failed to activate interface %(iface)s. Please check the physical link " "status." msgstr "" "Schnittstelle %(iface)s konnte nicht aktiviert werden. Bitte überprüfen Sie " "den Status der physischen Verbindung." #, python-format msgid "Failed to start network %(name)s. Details: %(err)s" msgstr "" #, python-format msgid "Debug report %(name)s does not exist" msgstr "Debugbericht %(name)s ist nicht vorhanden" msgid "Debug report tool not found in system" msgstr "Debugberichtstool nicht im System gefunden" #, python-format msgid "Unable to create debug report %(name)s. Details: %(err)s." msgstr "Debugbericht %(name)s konnte nicht erstellt werden. Details: %(err)s." #, python-format msgid "Can not find any debug report with the given name %(name)s" msgstr "" #, python-format msgid "Unable to generate debug report %(name)s. Details: %(err)s" msgstr "Debugbericht %(name)s konnte nicht generiert werden. Details: %(err)s" msgid "You should give a name for the debug report file." msgstr "" msgid "" "Debug report name must be a string. Only letters, digits, underscore ('_') " "and hyphen ('-') are allowed." msgstr "" #, python-format msgid "" "The debug report with specified name \"%(name)s\" already exists. Please use " "another one." msgstr "" "Eine Datenträgergruppe mit dem Namen '%(name)s' ist bereits vorhanden. " "Wählen Sie einen anderen Namen aus, um den logischen Pool zu erstellen." #, python-format msgid "Storage server %(server)s was not used by Kimchi" msgstr "Speicherserver %(server)s wurde nicht von Kimchi verwendet" #, python-format msgid "Distro '%(name)s' does not exist" msgstr "Distro '%(name)s' ist nicht vorhanden" #, python-format msgid "Partition %(name)s does not exist in the host" msgstr "Partition %(name)s ist nicht im Host vorhanden" msgid "Unable to shutdown host machine as there are running virtual machines" msgstr "" "Hostmaschine konnte nicht heruntergefahren werden, weil virtuelle Maschinen " "ausgeführt werden" msgid "Unable to reboot host machine as there are running virtual machines" msgstr "" "Hostmaschine konnte nicht neu gestartet werden, weil virtuelle Maschinen " "ausgeführt werden" #, python-format msgid "Node device '%(name)s' not found" msgstr "Knoteneinheit '%(name)s' nicht gefunden" msgid "Conflicting flag filters specified." msgstr "" msgid "No packages marked for update" msgstr "Keine Pakete für Aktualisierung markiert" #, python-format msgid "Package %(name)s is not marked to be updated." msgstr "Paket %(name)s ist nicht für Aktualisierung markiert." #, python-format msgid "Error while getting packages marked to be updated. Details: %(err)s" msgstr "" "Fehler beim Abrufen von Paketen, die für die Aktualsierung markiert sind. " "Details: %(err)s" msgid "There is no compatible package manager for this system." msgstr "Es gibt keinen kompatiblen Paketmanager für dieses System." #, python-format msgid "Unable to find %(item)s in datastore" msgstr "%(item)s konnten nicht im Datenspeicher gefunden werden" #, python-format msgid "Invalid URI %(uri)s" msgstr "Ungültiger URI %(uri)s" #, python-format msgid "Timeout while running command '%(cmd)s' after %(seconds)s seconds" msgstr "" "Zeitlimitüberschreitung beim Ausführen des Befehls '%(cmd)s' nach " "%(seconds)s Sekunden" msgid "Unable to choose a virtual machine name" msgstr "" #, python-format msgid "Invalid data value '%(value)s'" msgstr "" #, python-format msgid "Invalid data unit '%(unit)s'" msgstr "" msgid "Invalid storage type. Types supported: 'cdrom', 'disk'" msgstr "Ungültiger Speichertyp. Unterstützte Typen: 'cdrom'" #, python-format msgid "The path '%(value)s' is not a valid local/remote path for the device" msgstr "" msgid "Only CDROM path can be update." msgstr "" #, python-format msgid "" "The storage device %(dev_name)s does not exist in the virtual machine " "%(vm_name)s" msgstr "" #, python-format msgid "Error while creating new storage device: %(error)s" msgstr "Fehler beim Erstellen einer neuen Speichereinheit: %(error)s" #, python-format msgid "Error while updating storage device: %(error)s" msgstr "Fehler beim Aktualisieren einer Speichereinheit: %(error)s" #, python-format msgid "Error while removing storage device: %(error)s" msgstr "Fehler beim Entfernen einer Speichereinheit: %(error)s" msgid "Do not support IDE device hot plug" msgstr "" msgid "" "Specify type and path or type and pool/volume to add a new virtual machine " "disk" msgstr "" "Geben Sie Typ und Pfad an, um einen neuen Datenträger für eine virtuelle " "Maschine hinzuzfügen" msgid "Specify path to update virtual machine disk" msgstr "" "Geben Sie einen Pfad an, um die Platte der virtuellen Maschine zu " "aktualisieren" #, python-format msgid "Controller type %(type)s limitation of %(limit)s devices reached" msgstr "" #, python-format msgid "Cannot retrieve disk path information for given pool/volume: %(error)s" msgstr "" msgid "Volume already in use by other virtual machine." msgstr "" msgid "" "Only one of path or pool/volume can be specified to add a new virtual " "machine disk" msgstr "" "Geben Sie Typ und Pfad an, um einen neuen Datenträger für eine virtuelle " "Maschine hinzuzfügen" #, python-format msgid "" "Volume chosen with format %(format)s does not fit in the storage type " "%(type)s" msgstr "" msgid "YUM Repository ID must be one word only string." msgstr "" "YUM-Repository-ID darf nur ein aus einer Zeichenfolge bestehendes Wort sein." msgid "Repository URL must be an http://, ftp:// or file:// URL." msgstr "Repository-URL muss ein http://-, ftp://- oder file://-URL sein." msgid "" "Repository configuration is a dictionary with specific values according to " "repository type." msgstr "" "Repository-Konfiguration ist ein Wörterbuch mit bestimmten Werten " "hinsichtlich Repository-Typ." msgid "Distribution to DEB repository must be a string" msgstr "Verteilung an DEB-Repository muss eine Zeichenfolge sein" msgid "Components to DEB repository must be listed in a array" msgstr "Komponenten für DEB-Repository müssen in einem Array aufgelistet sein" msgid "Components to DEB repository must be a string" msgstr "Komponenten für DEB-Repository müssen eine Zeichenfolge sein" msgid "Mirror list to repository must be a string" msgstr "" msgid "YUM Repository name must be string." msgstr "Name des YUM-Repositorys muss eine Zeichenfolge sein." msgid "GPG check must be a boolean value." msgstr "GPG-Prüfung muss ein boolescher Wert sein." msgid "GPG key must be a URL pointing to the ASCII-armored file." msgstr "GPG-Schlüssel muss ein URL sein, der auf die ASCII-Armor-Datei zeigt." #, python-format msgid "Could not update repository %(repo_id)s." msgstr "Repository %(repo_id)s konnte nicht aktualisiert werden." #, python-format msgid "Repository %(repo_id)s does not exist." msgstr "Repository %(repo_id)s ist nicht vorhanden." msgid "" "Specify repository base URL, mirror list or metalink in order to create or " "update a YUM repository." msgstr "" msgid "Repository management tool was not recognized for your system." msgstr "Repository-Verwaltungstool wurde für Ihr System nicht erkannt." #, python-format msgid "Repository %(repo_id)s is already enabled." msgstr "Repository %(repo_id)s ist bereits aktiviert." #, python-format msgid "Repository %(repo_id)s is already disabled." msgstr "Repository %(repo_id)s ist bereits inaktiviert." #, python-format msgid "Could not remove repository %(repo_id)s." msgstr "Repository %(repo_id)s konnte nicht entfernt werden." #, python-format msgid "Could not write repository configuration file %(repo_file)s" msgstr "" "Repository-Konfigurationsdatei %(repo_file)s konnte nicht geschrieben werden" msgid "Specify repository distribution in order to create a DEB repository." msgstr "" "Geben Sie die Repository-Verteilung an, um ein DEB-Repository zu erstellen." #, python-format msgid "Could not enable repository %(repo_id)s." msgstr "Repository %(repo_id)s konnte nicht aktiviert werden." #, python-format msgid "Could not disable repository %(repo_id)s." msgstr "Repository %(repo_id)s konnte nicht inaktiviert werden." msgid "YUM Repository ID already exists" msgstr "YUM-Repository-ID ist bereits vorhanden" msgid "YUM Repository name must be a string" msgstr "YUM-Repository-Name muss eine Zeichenfolge sein" #, python-format msgid "Unable to list repositories. Details: '%(err)s'" msgstr "Repositorys konnten nicht aufgelistet werden. Details: '%(err)s'" #, python-format msgid "Unable to retrieve repository information. Details: '%(err)s'" msgstr "" "Repository-Informationen konnten nicht abgerufen werden. Details: '%(err)s'" #, python-format msgid "Unable to add repository. Details: '%(err)s'" msgstr "Repository konnte nicht hinzugefügt werden. Details: '%(err)s'" #, python-format msgid "Unable to remove repository. Details: '%(err)s'" msgstr "Repository konnte nicht entfernt werden. Details: '%(err)s'" #, python-format msgid "" "Configuration items: '%(items)s' are not supported by repository manager" msgstr "" msgid "Repository metalink must be an http://, ftp:// or file:// URL." msgstr "" msgid "Cannot specify mirrorlist and metalink at the same time." msgstr "" #, python-format msgid "" "Virtual machine '%(vm)s' must be stopped before creating a snapshot of it." msgstr "" #, python-format msgid "" "Unable to create snapshot '%(name)s' on virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "Snapshot '%(name)s' does not exist on virtual machine '%(vm)s'." msgstr "" #, python-format msgid "" "Unable to retrieve snapshot '%(name)s' on virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "Unable to list snapshots on virtual machine '%(vm)s'. Details: %(err)s" msgstr "" #, python-format msgid "" "Unable to delete snapshot '%(name)s' on virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "" "Unable to retrieve current snapshot of virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "" "Unable to revert virtual machine '%(vm)s' to snapshot '%(name)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "" "Unable to create snapshot of virtual machine '%(vm)s' because it contains a " "disk with format '%(format)s'; only 'qcow2' is supported." msgstr "" msgid "The number of vCPUs is too large for this system." msgstr "" msgid "Invalid vCPU/topology combination." msgstr "" msgid "This host (or current configuration) does not allow CPU topology." msgstr "" msgid "ERROR CODE" msgstr "FEHLERCODE" msgid "REASON" msgstr "GRUND" msgid "STACK" msgstr "STACK" msgid "Go to Homepage" msgstr "Gehe zu Homepage" msgid "Create a New Virtual Machine" msgstr "Neue virtuelle Maschine erstellen" msgid "Virtual Machine Name" msgstr "Name der virtuellen Maschine" msgid "" "The name used to identify the virtual machine. If omitted, a name will be " "chosen based on the template used." msgstr "" "Der für die Kennzeichnung der virtuellen Maschine verwendete Name. Falls er " "ausgelassen wird, wird ein Name anhand der verwendeten Vorlage ausgewählt." msgid "Template" msgstr "Vorlage" msgid "Please create a template first." msgstr "Erstellen Sie zunächst eine Vorlage." msgid "Create a Template" msgstr "Vorlage erstellen" msgid "Please choose a template." msgstr "Wählen Sie eine Vorlage aus." msgid "OS" msgstr "BS" msgid "OS Version" msgstr "BS-Version" msgid "CPUS" msgstr "CPUS" msgid "Memory" msgstr "Speicher" msgid "Create" msgstr "Erstellen" msgid "Creating..." msgstr "" msgid "Edit Guest" msgstr "Gast bearbeiten" msgid "General" msgstr "Allgemein" msgid "Storage" msgstr "Speicher" msgid "Interface" msgstr "Schnittstelle" msgid "Permission" msgstr "Version" msgid "Host PCI Device" msgstr "" msgid "Snapshot" msgstr "" msgid "Name" msgstr "Name" msgid "CPUs" msgstr "CPUs" msgid "Memory (MB)" msgstr "Speicher" msgid "Icon" msgstr "Symbol" msgid "Device" msgstr "Einheitenname" msgid "Path" msgstr "NFS-Pfad" msgid "Network" msgstr "Netz" msgid "Type" msgstr "Typ" msgid "MAC Address" msgstr "" msgid "Available system users and groups" msgstr "" msgid "Selected system users and groups" msgstr "" msgid "User" msgstr "" msgid "All" msgstr "Alle" msgid "To Add" msgstr "" msgid "Added" msgstr "" msgid "filter" msgstr "" msgid "Product" msgstr "" msgid "Vendor" msgstr "Anbieter" msgid "Created" msgstr "" msgid "Save" msgstr "Speichern" msgid "Replace" msgstr "Ersetzen" msgid "Detach" msgstr "Abhängen" msgid "Cancel" msgstr "Abbrechen" msgid "revert" msgstr "" msgid "Add a Storage Device to VM" msgstr "Speichereinheit zur virtuellen Maschine hinzufügen" msgid "Device Type" msgstr "Einheitentyp" msgid "The device type. Currently, \"cdrom\" and \"disk\" are supported." msgstr "Der Einheitentyp. Derzeit wird nur \"cdrom\" unterstützt." msgid "Storage Pool" msgstr "Speicherpool" msgid "Storage pool which volume located in" msgstr "Speicherpoolpfad muss eine Zeichenfolge sein" msgid "Storage Volume" msgstr "Speicherpoolname" msgid "Storage volume to be attached" msgstr "Name des Speicherdatenträgers muss eine Zeichenfolge sein" msgid "File Path" msgstr "Dateipfad" msgid "The ISO file path in the server for CDROM." msgstr "Der ISO-Dateipfad auf dem Server für die CD-ROM." msgid "Attach" msgstr "Anhängen" msgid "Start" msgstr "Starten" msgid "Reset" msgstr "Zurücksetzen" msgid "Pause" msgstr "" msgid "Resume" msgstr "" msgid "Power Off" msgstr "" msgid "Actions" msgstr "Aktionen" msgid "Connect" msgstr "Verbinden" msgid "Clone" msgstr "" msgid "Edit" msgstr "Bearbeiten" msgid "Shut Down" msgstr "Herunterfahren" msgid "Delete" msgstr "Löschen" msgid "The username or password you entered is incorrect. Please try again." msgstr "" "Der Benutzername oder das Kennwort, den bzw. das Sie eingegeben haben, ist " "falsch. Versuchen Sie es bitte erneut." msgid "This field is required." msgstr "Dieses Feld ist erforderlich." msgid "Log in" msgstr "Anmelden" msgid "Logging in..." msgstr "Wird angemeldet..." msgid "Host" msgstr "Host" msgid "Guests" msgstr "Gäste" msgid "Templates" msgstr "Vorlagen" msgid "Failed to get application configuration" msgstr "Anwendungskonfiguration konnte nicht abgerufen werden" msgid "This is not a valid Linux path" msgstr "Dies ist kein gültiger Linux-Pfad" msgid "This is not a valid URL." msgstr "Dies ist kein gültiger URL." msgid "No such data available." msgstr "Keine solchen Daten verfügbar." msgid "" "Can not contact the host system. Verify the host system is up and that you " "have network connectivity to it. HTTP request response %1. " msgstr "" "Hostsystem kann nicht kontaktiert werden. Prüfen Sie, ob das Hostsystem " "aktiv ist und obNetzkonnektivität besteht. HTTP-Anforderungsantwort %1. " msgid "Unable to read file." msgstr "" msgid "Error while uploading file." msgstr "" msgid "Delete Confirmation" msgstr "Löschbestätigung" msgid "OK" msgstr "OK" msgid "Confirm" msgstr "Bestätigen" msgid "Warning" msgstr "Warnung" msgid "Cloning..." msgstr "" msgid "Loading..." msgstr "Wird geladen..." msgid "An error occurred while retrieving system information." msgstr "" msgid "Retry" msgstr "Wiederholen" msgid "Detailed message:" msgstr "Detaillierte Meldung:" msgid "No ISO found" msgstr "" msgid "This is not a valid ISO file." msgstr "Dies ist keine gültige ISO-Datei." msgid "This may take a long time. Do you want to continue?" msgstr "Dies wird einige Zeit dauern. Möchten Sie fortfahren?" msgid "This will permanently delete the template. Would you like to continue?" msgstr "Hiermit wird die Vorlage dauerhaft gelöscht. Möchten Sie fortfahren?" msgid "Unable to shut down system as there are some virtual machines running!" msgstr "" "System konnte nicht heruntergefahren werden, weil einige virtuellen " "Maschinen ausgeführt werden!" msgid "Max:" msgstr "Max:" msgid "Utilization" msgstr "Auslastung" msgid "Available" msgstr "Verfügbar" msgid "Read Rate" msgstr "Leserate" msgid "Write Rate" msgstr "Schreibrate" msgid "Received" msgstr "Empfangen" msgid "Sent" msgstr "Gesendet" msgid "" "Shutting down or restarting host will cause unsaved work lost. Continue to " "shut down/restarting?" msgstr "" "Durch das Herunterfahren oder Neustarten des Hosts können ungesicherte " "Arbeiten verloren gehen. Möchten Sie mit dem Herunterfahren/Neustarten " "fortfahren?" msgid "" "Repository will be removed permanently and can't be recovered. Do you want " "to continue?" msgstr "" "Repository wird dauerhaft entfernt und kann nicht wiederhergestellt werden. " "Möchten Sie fortfahren?" msgid "Repositories" msgstr "Repositorys" msgid "ID" msgstr "ID" msgid "Base URL" msgstr "Basis-URL" msgid "Is Mirror" msgstr "Ist Spiegel" msgid "URL Args" msgstr "URL-Args" msgid "Enabled" msgstr "Aktiviert" msgid "GPG Check" msgstr "GPG-Prüfung" msgid "GPG Key" msgstr "GPG-Schlüssel" msgid "Add" msgstr "Hinzufügen" msgid "Remove" msgstr "Entfernen" msgid "Enable" msgstr "Aktivieren" msgid "Disable" msgstr "Inaktivieren" msgid "Software Updates" msgstr "Software-Updates" msgid "Package Name" msgstr "Paketname" msgid "Version" msgstr "Version" msgid "Architecture" msgstr "Architektur" msgid "Repository" msgstr "Repository" msgid "Update All" msgstr "Alle aktualisieren" msgid "Updating..." msgstr "Wird aktualisiert..." msgid "Failed to retrieve packages update information." msgstr "" msgid "Failed to update package(s)." msgstr "Pakete konnten nicht aktualisiert werden." msgid "" "Debug report will be removed permanently and can't be recovered. Do you want " "to continue?" msgstr "" "Debugbericht wird dauerhaft entfernt und kann nicht wiederhergestellt " "werden. Möchten Sie fortfahren?" msgid "Debug Reports" msgstr "Debugberichte" msgid "Generated Time" msgstr "Generierte Zeit" msgid "Generate" msgstr "Generieren" msgid "Generating..." msgstr "Wird generiert..." msgid "Rename" msgstr "Umbenennen" msgid "Download" msgstr "Herunterladen" msgid "" "Report name should contain only letters, digits, underscore ('_') and/or " "hyphen ('-')." msgstr "" "Berichtsname darf nur Buchstaben, Zahlen und/oder Bindestriche ('-') " "enthalten." msgid "Pending..." msgstr "Wird geladen..." msgid "Report name is the same as the original one." msgstr "" msgid "" "This will delete the virtual machine and its virtual disks. This operation " "cannot be undone. Would you like to continue?" msgstr "" "Hiermit werden die virtuelle Maschine und deren virtuellen Platten gelöscht. " "Diese Operation kann nicht rückgängig gemacht werden. Möchten Sie fortfahren?" msgid "Power off Confirmation" msgstr "Löschbestätigung" msgid "" "This action may produce undesirable results, for example unflushed disk " "cache in the guest. Would you like to continue?" msgstr "" msgid "Reset Confirmation" msgstr "Löschbestätigung" msgid "" "There is a risk of data loss caused by reset without the guest OS shutdown. " "Would you like to continue?" msgstr "" msgid "Shut Down Confirmation" msgstr "Löschbestätigung" msgid "Note the guest OS may ignore this request. Would you like to continue?" msgstr "Hiermit wird die Vorlage dauerhaft gelöscht. Möchten Sie fortfahren?" msgid "Virtual Machine delete Confirmation" msgstr "" msgid "" "This virtual machine is not persistent. Power Off will delete it. Continue?" msgstr "" msgid "" "When the target guest has SCSI or iSCSI volumes, they will be cloned on " "default storage pool. The same will happen when the target pool does not " "have enough space to clone the volumes. Do you want to continue?" msgstr "" msgid "" "This CDROM will be detached permanently and you can re-attach it. Continue " "to detach it?" msgstr "" "Diese CD-ROM wird dauerhaft abgehängt und Sie können sie neu anhängen. " "Möchten Sie mit dem Abhängen fortfahren?" msgid "Attaching..." msgstr "Wird angehängt..." msgid "Replacing..." msgstr "Wird ersetzt..." msgid "Successfully attached!" msgstr "Erfolgreich angehängt!" msgid "Successfully replaced!" msgstr "Erfolgreich ersetzt!" msgid "Successfully detached!" msgstr "Erfolgreich abgehängt!" msgid "" "This disk will be detached permanently and you can re-attach it. Continue to " "detach it?" msgstr "" msgid "interface:" msgstr "" msgid "address:" msgstr "" msgid "link_type:" msgstr "" msgid "block:" msgstr "" msgid "drive_type:" msgstr "" msgid "model:" msgstr "" msgid "Affected devices:" msgstr "" msgid "The VLAN id must be between 1 and 4094." msgstr "Die VLAN-ID muss zwischen 1 und 4094 liegen." msgid "unavailable" msgstr "nicht verfügbar" msgid "" "This action will interrupt network connectivity for any virtual machine that " "depend on this network." msgstr "" "Diese Aktion unterbricht die Netzkonnektivität für jede virtuelle Maschine, " "die von diesem Netz abhängt." msgid "Create a network" msgstr "Netz erstellen" msgid "" "This network is not persistent. Instead of stop, this action will " "permanently delete it. Would you like to continue?" msgstr "" "Dieser Speicherpool ist nicht permanent. Durch diese Aktion wird er nicht " "inaktiviert, sondern permanent gelöscht. Möchten Sie fortfahren?" msgid "" "The bridged VLAN tag may not work well with NetworkManager enabled. You " "should consider disabling it." msgstr "" msgid "" "This will permanently delete the storage pool. Would you like to continue?" msgstr "" "Hiermit wird der Speicherpool dauerhaft gelöscht. Möchten Sie fortfahren?" msgid "This storage pool is empty." msgstr "Dieser Speicherpool ist leer." msgid "" "It will format your disk and you will loose any data in there, are you sure " "to continue? " msgstr "" "Hiermit wird Ihre Platte formatiert und Sie verlieren sämtliche Daten " "darauf. Sind Sie sicher, dass Sie fortfahren möchten? " msgid "SCSI Fibre Channel" msgstr "SCSI-Fibre Channel" msgid "No SCSI adapters found." msgstr "Keine SCSI-Adapter gefunden." msgid "Loading iSCSI targets..." msgstr "" msgid "No iSCSI found. Please input one." msgstr "" msgid "Failed to load iSCSI targets." msgstr "" msgid "The storage pool name can not be blank." msgstr "Der Speicherpoolname darf nicht leer sein." msgid "The storage pool path can not be blank." msgstr "Der Speicherpoolpfad darf nicht leer sein." msgid "NFS server mount path can not be blank." msgstr "Der Mountpfad des NFS-Servers darf nicht leer sein." msgid "Invalid NFS mount path." msgstr "Ungültiger NFS-Mountpfad." msgid "No logical device selected." msgstr "Keine logische Einheit ausgewählt." msgid "The iSCSI target can not be blank." msgstr "Das iSCSI-Ziel darf nicht leer sein." msgid "Server name can not be blank." msgstr "Servername darf nicht leer sein." msgid "This is not a valid Server Name or IP. Please, modify it." msgstr "" msgid "Looking for available partitions ..." msgstr "Es wird nach verfügbaren Partitionen gesucht..." msgid "No available partitions found." msgstr "Keine gültigen Partitionen gefunden." msgid "" "This storage pool is not persistent. Instead of deactivate, this action will " "permanently delete it. Would you like to continue?" msgstr "" "Dieser Speicherpool ist nicht permanent. Durch diese Aktion wird er nicht " "inaktiviert, sondern permanent gelöscht. Möchten Sie fortfahren?" msgid "Unable to retrieve partitions information." msgstr "" "Repository-Informationen konnten nicht abgerufen werden. Details: '%(err)s'" msgid "In progress..." msgstr "" msgid "Failed!" msgstr "" msgid "CDROM path needs to be a valid local/remote path and cannot be blank." msgstr "" msgid "Disk pool or volume cannot be blank." msgstr "Der Speicherpoolname darf nicht leer sein." msgid "Peers" msgstr "" msgid "Searching" msgstr "" msgid "No peers found." msgstr "" msgid "Help" msgstr "Hilfe" msgid "About" msgstr "Informationen" msgid "Log out" msgstr "Abmelden" msgid "Version:" msgstr "Version:" msgid "Session timeout, please re-login." msgstr "" msgid "User Name" msgstr "Benutzername" msgid "Password" msgstr "Kennwort" msgid "Generate a New Debug Report" msgstr "Neuen Debugbericht erstellen" msgid "Report Name" msgstr "Berichtsname" msgid "" "The name used to identify the report. If omitted, a name will be chosen " "based on current time. Name can contain: letters, digits, underscore (\"_\") " "and hyphen (\"-\")." msgstr "" "Der Name, mit dem der Bericht gekennzeichnet wird. Falls er ausgelassen " "wird, wird ein Name basierend auf der aktuellen Zeit ausgewählt. Der Name " "darf Buchstaben, Zahlen und Bindestriche (\"-\") enthalten." msgid "Rename a Debug Report" msgstr "Neuen Debugbericht erstellen" msgid "" "The name used to identify the report. Name can contain: letters, digits and " "hyphen (\"-\")." msgstr "" "Der Name, mit dem der Bericht gekennzeichnet wird. Falls er ausgelassen " "wird, wird ein Name basierend auf der aktuellen Zeit ausgewählt. Der Name " "darf Buchstaben, Zahlen und Bindestriche (\"-\") enthalten." msgid "Submit" msgstr "" msgid "Add a Repository" msgstr "Repository hinzufügen" msgid "Identifier" msgstr "Kennung" msgid "Single word, unique identifier for the repository." msgstr "Einzelnes Wort, eindeutige Kennung für das Repository." msgid "Textual name for the repository." msgstr "Textname für das Repository." msgid "URL" msgstr "URL" msgid "Required Field" msgstr "Erforderliches Feld" msgid "URL to the repository. Supported protocols are http, ftp, and file." msgstr "URL zum Repository. Unterstützte Protokolle sind http, ftp und file." msgid "Repository is a mirror" msgstr "Repository ist ein Spiegel." msgid "Distribution" msgstr "Verteilung" msgid "Distribution of the DEB repository." msgstr "Verteilung des DEB-Repositorys." msgid "Components" msgstr "Komponenten" msgid "List of components in DEB repository." msgstr "Liste der Komponenten im DEB-Repository." msgid "Edit Repository" msgstr "Repository bearbeiten" msgid "Mirror List URL" msgstr "Spiegellisten-URL" msgid "Yes" msgstr "Ja" msgid "No" msgstr "Nein" msgid "Add a Volume to Storage Pool" msgstr "" msgid "Fetch from remote URL" msgstr "" msgid "Enter the remote URL here." msgstr "" msgid "Upload a file" msgstr "" msgid "Choose the file you want to upload." msgstr "" msgid "Define a New Storage Pool" msgstr "Neuen Speicherpool definieren" msgid "Storage Pool Name" msgstr "Speicherpoolname" msgid "" "The name used to identify the storage pools, and it should not be empty." msgstr "" "Der Name, mit dem die Speicherpools gekennzeichnet werden. Er darf nicht " "leer sein." msgid "Storage Pool Type" msgstr "Speicherpooltyp" msgid "Storage Path" msgstr "Speicherpfad" msgid "" "The path of the Storage Pool. Each Storage Pool must have a unique path." msgstr "" "Der Pfad des Speicherpools. Jeder Speicherpool muss einen eindeutigen Pfad " "haben." msgid "" "Kimchi will try to create the directory when it does not already exist in " "your system." msgstr "" "Kimchi versucht, das Verzeichnis zu erstellen, wenn es noch nicht in Ihrem " "System vorhanden ist." msgid "NFS Server IP" msgstr "NFS-Server-IP" msgid "NFS server IP or hostname. It can be input or chosen from history." msgstr "" "IP oder Hostname des NFS-Servers. Diese(r) kann eingegeben oder aus dem " "Verlauf ausgewählt werden." msgid "NFS Path" msgstr "NFS-Pfad" msgid "The NFS exported path on NFS server." msgstr "Der NFS-Exportpfad auf dem NFS-Server." msgid "Device path" msgstr "Einheitenpfad" msgid "iSCSI Server" msgstr "iSCSI-Server" msgid "iSCSI server IP or hostname. It should not be empty." msgstr "IP oder Hostname des iSCSI-Servers. Diese(r) darf nicht leer sein." msgid "Server" msgstr "Server" msgid "Port" msgstr "Port" msgid "Target" msgstr "Ziel" msgid "The iSCSI target on iSCSI server" msgstr "Das iSCSI-Ziel auf dem iSCSI-Server" msgid "Add iSCSI Authentication" msgstr "iSCSI-Authentifizierung hinzufügen" msgid "iSCSI Authentication" msgstr "iSCSI-Authentifizierung" msgid "SCSI Adapter" msgstr "SCSI-Adapter" msgid "Please, wait..." msgstr "Bitte warten..." msgid "Add Template" msgstr "Vorlage hinzufügen" msgid "Where is the source media for this template? " msgstr "Wo ist der Quellendatenträger für diese Vorlage?" msgid "Local ISO Image" msgstr "Lokales ISO-Image" msgid "Local Image File" msgstr "" msgid "Remote ISO Image" msgstr "Fernes ISO-Image" msgid "Search ISOs" msgstr "ISOs suchen" msgid "The following ISOs are available:" msgstr "Die folgenden ISOs sind verfügbar:" msgid "OS: " msgstr "BS: " msgid "Version: " msgstr "Version: " msgid "Size: " msgstr "Größe: " msgid "Search more ISOs" msgstr "Weitere ISOs suchen" msgid "Create Templates from Selected ISO" msgstr "Vorlagen aus ausgewähltem ISO erstellen" msgid "I want to use a specific ISO file" msgstr "Ich möchte eine bestimmte ISO-Datei verwenden" msgid "Loading default remote ISOs ..." msgstr "Standardmäßige ferne ISOs werden geladen ..." msgid "Arch: " msgstr "Arch: " msgid "I want to use a custom URL" msgstr "Ich möchte einen benutzerdefinierten URL verwenden" msgid "Edit Template" msgstr "Vorlage bearbeiten" msgid "Processor" msgstr "Prozessor" msgid "CDROM" msgstr "CD-ROM" msgid "Image File" msgstr "" msgid "Graphics" msgstr "Grafik" msgid "Disk(GB)" msgstr "" msgid "Disk Format" msgstr "" msgid "CPU Number" msgstr "CPU-Anzahl" msgid "Manually set CPU topology" msgstr "" msgid "Cores" msgstr "" msgid "Threads" msgstr "" msgid "CPU" msgstr "CPU" msgid "Disk I/O" msgstr "Platten-E/A" msgid "Network I/O" msgstr "Netz-E/A" msgid "Livetile" msgstr "Live Tile" msgid "No guests found." msgstr "Keine Gäste gefunden." msgid "Shut down" msgstr "Herunterfahren" msgid "Restart" msgstr "Erneut starten" msgid "Basic Information" msgstr "Basisinformationen" msgid "OS Distro" msgstr "BS-Distro" msgid "OS Code Name" msgstr "BS-Codename" msgid "CPU(s)" msgstr "" msgid "System Statistics" msgstr "Systemstatistik" msgid "Update Progress" msgstr "Aktualisierungsfortschritt" msgid "Network Name" msgstr "Netzname" msgid "State" msgstr "Status" msgid "Network Type" msgstr "Netztyp" msgid "Address Space" msgstr "Adressraum" msgid "Name should not contain '/' and '\"'." msgstr "Ungültiger Speicherpoolname. Er darf nicht '/' enthalten." msgid "Isolated: no external network connection" msgstr "Isolatiert: keine physisische Netzverbindung" msgid "NAT: outbound physical network connection only" msgstr "NAT: nur ausgehende physische Netzverbindung" msgid "Bridged: Virtual machines are connected to physical network directly" msgstr "" "Überbrückt: Virtuelle Maschinen sind direkt mit physischem Netz verbunden" msgid "(No interfaces found)" msgstr "" msgid "Destination" msgstr "Ziel:" msgid "Enable VLAN" msgstr "Virtuelles LAN (VLAN) aktivieren:" msgid "VLAN ID" msgstr "VLAN-ID:" msgid "Stop" msgstr "Stoppen" msgid "%Used" msgstr "" msgid "Location" msgstr "Position" msgid "Capacity" msgstr "Kapazität" msgid "Allocated" msgstr "Zugeordnet" msgid "active" msgstr "aktiv" msgid "inactive" msgstr "inaktiv" msgid "Deactivate" msgstr "Inaktivieren" msgid "Activate" msgstr "Aktivieren" msgid "Add Volume" msgstr "" msgid "Extend" msgstr "" msgid "Undefine" msgstr "Definition aufheben" msgid "Format" msgstr "Format:" msgid "Allocation" msgstr "Zuordnung:" msgid "No templates found." msgstr "Keine Vorlagen gefunden." kimchi-1.5.0/po/en_US.po000066400000000000000000001170621254252253000147570ustar00rootroot00000000000000# English translations for kimchi package. # Copyright (C) 2013 ORGANIZATION # Adam Litke , 2013. # msgid "" msgstr "" "Project-Id-Version: kimchi 0.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-06-24 09:39-0300\n" "PO-Revision-Date: 2013-07-11 17:32-0400\n" "Last-Translator: Crístian Viana \n" "Language-Team: English\n" "Language: en_US\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: pygettext.py 1.5\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #, python-format msgid "Unknown parameter %(value)s" msgstr "" #, python-format msgid "Delete is not allowed for %(resource)s" msgstr "" #, python-format msgid "%(resource)s does not implement update method" msgstr "" #, python-format msgid "Create is not allowed for %(resource)s" msgstr "" msgid "Unable to parse JSON request" msgstr "" msgid "This API only supports JSON" msgstr "" #, python-format msgid "Parameters does not match requirement in schema: %(err)s" msgstr "" msgid "You don't have permission to perform this operation." msgstr "" msgid "Datastore is not initiated in the model object." msgstr "" #, python-format msgid "Unable to start task due error: %(err)s" msgstr "" #, python-format msgid "Timeout of %(seconds)s seconds expired while running task '%(task)s." msgstr "" #, python-format msgid "Authentication failed for user '%(username)s'. [Error code: %(code)s]" msgstr "" msgid "You are not authorized to access Kimchi" msgstr "" #, python-format msgid "Specify %(item)s to login into Kimchi" msgstr "" #, python-format msgid "User %(user_id)s not found with given LDAP settings." msgstr "" #, python-format msgid "Invalid LDAP configuration: %(item)s : %(value)s" msgstr "" msgid "Unknown \"_cap\" specified" msgstr "" msgid "\"_passthrough\" should be \"true\" or \"false\"" msgstr "" msgid "\"_passthrough_affected_by\" should be a device name string" msgstr "" #, python-format msgid "Error while getting block devices. Details: %(err)s" msgstr "" #, python-format msgid "Error while getting block device information for %(device)s." msgstr "" #, python-format msgid "Unable to find distro file: %(filename)s" msgstr "" #, python-format msgid "" "Unable to parse distro file: %(filename)s. Make sure, it is a JSON file." msgstr "" #, python-format msgid "Unable to login to iSCSI host target %(portal)s. Details: %(err)s" msgstr "" #, python-format msgid "Unable to login to iSCSI host %(host)s target %(target)s" msgstr "" #, python-format msgid "Unable to find ISO file %(filename)s" msgstr "" #, python-format msgid "The ISO file %(filename)s is not bootable" msgstr "" #, python-format msgid "The ISO file %(filename)s does not have a valid El Torito boot record" msgstr "" #, python-format msgid "Invalid El Torito validation entry in ISO %(filename)s" msgstr "" #, python-format msgid "Invalid El Torito boot indicator in ISO %(filename)s" msgstr "" #, python-format msgid "Unexpected volume type for primary volume in ISO %(filename)s" msgstr "" #, python-format msgid "Bad format while reading volume descriptor in ISO %(filename)s" msgstr "" #, python-format msgid "" "The hypervisor doesn't have permission to use this ISO %(filename)s. " "Consider moving it under /var/lib/libvirt, or set the search permission to " "file access control lists for '%(user)s' user if possible, or add the " "'%(user)s' to the ISO path group, or (not recommended) 'chmod -R o+x " "'path_to_iso'.Details: %(err)s" msgstr "" msgid "An error occurred when probing image OS information." msgstr "" msgid "No OS information found in given image." msgstr "" #, python-format msgid "Unable to read image file %(filename)s" msgstr "" #, python-format msgid "" "Image file must be an existing file on system. %(filename)s is not a valid " "input." msgstr "" #, python-format msgid "Virtual machine %(name)s already exists" msgstr "" #, python-format msgid "Virtual machine %(name)s does not exist" msgstr "" #, python-format msgid "" "Unable to rename virtual machine %(name)s. The name %(new_name)s is already " "in use or the virtual machine is not powered off." msgstr "" #, python-format msgid "Unable to retrieve screenshot for stopped virtual machine %(name)s" msgstr "" msgid "Remote ISO image is not supported by this server." msgstr "" #, python-format msgid "Screenshot is not supported on virtual machine %(name)s" msgstr "" #, python-format msgid "Unable to create virtual machine %(name)s. Details: %(err)s" msgstr "" #, python-format msgid "Unable to update virtual machine %(name)s. Details: %(err)s" msgstr "" #, python-format msgid "Unable to retrieve virtual machine %(name)s. Details: %(err)s" msgstr "" #, python-format msgid "Unable to connect to powered off virtual machine %(name)s." msgstr "" msgid "Virtual machine name must be a string without slashes (/)" msgstr "" #, python-format msgid "Invalid template URI %(value)s specified for virtual machine" msgstr "" #, python-format msgid "Invalid storage pool URI %(value)s specified for virtual machine" msgstr "" msgid "Supported virtual machine graphics are Spice or VNC" msgstr "" msgid "Graphics address to listen on must be IPv4 or IPv6" msgstr "" msgid "Specify a template to create a virtual machine from" msgstr "" #, python-format msgid "Unable to start virtual machine %(name)s. Details: %(err)s" msgstr "" #, python-format msgid "Unable to power off virtual machine %(name)s. Details: %(err)s" msgstr "" #, python-format msgid "Unable to delete virtual machine %(name)s. Details: %(err)s" msgstr "" #, python-format msgid "Unable to reset virtual machine %(name)s. Details: %(err)s" msgstr "" msgid "User name list must be an array" msgstr "" msgid "User name must be a string" msgstr "" msgid "Group name list must be an array" msgstr "" msgid "Group name must be a string" msgstr "" #, python-format msgid "User(s) '%(users)s' do not exist" msgstr "" #, python-format msgid "Group(s) '%(groups)s' do not exist" msgstr "" #, python-format msgid "Unable to shutdown virtual machine %(name)s. Details: %(err)s" msgstr "" #, python-format msgid "" "Unable to get access metadata of virtual machine %(name)s. Details: %(err)s" msgstr "" msgid "The guest console password must be a string." msgstr "" msgid "The life time for the guest console password must be a number." msgstr "" #, python-format msgid "Virtual machine '%(name)s' must be stopped before cloning it." msgstr "" #, python-format msgid "Insufficient disk space to clone virtual machine '%(name)s'" msgstr "" #, python-format msgid "Unable to clone VM '%(name)s'. Details: %(err)s" msgstr "" #, python-format msgid "Invalid operation for non-persistent virtual machine %(name)s" msgstr "" #, python-format msgid "Cannot suspend VM '%(name)s' because it is not running." msgstr "" #, python-format msgid "Unable to suspend VM '%(name)s'. Details: %(err)s" msgstr "" #, python-format msgid "Cannot resume VM '%(name)s' because it is not paused." msgstr "" #, python-format msgid "Unable to resume VM '%(name)s'. Details: %(err)s" msgstr "" msgid "Memory assigned is higher then the maximum allowed in the host." msgstr "" #, python-format msgid "" "VM '%(name)s' does not support live memory update. Update the memory with " "the machine offline to enable this feature." msgstr "" msgid "Only increase memory is allowed in active VMs" msgstr "" msgid "" "For live memory update, new memory value must be equal old memory value plus " "multiples of 1024 Mib" msgstr "" msgid "There are not enough free slots of 1024 Mib in the guest." msgstr "" msgid "" "Host's libvirt version does not support memory devices. Libvirt must be >= " "1.2.14" msgstr "" #, python-format msgid "Error attaching memory device. Details: %(error)s" msgstr "" #, python-format msgid "" "VM %(vmid)s does not contain directly assigned host device %(dev_name)s." msgstr "" #, python-format msgid "The host device %(dev_name)s is not allowed to directly assign to VM." msgstr "" msgid "" "No IOMMU groups found. Host PCI pass through needs IOMMU group to function " "correctly. Please enable Intel VT-d or AMD IOMMU in your BIOS, then verify " "the Kernel is compiled with IOMMU support. For Intel CPU, add intel_iommu=on " "to your Kernel parameter in /boot/grub2/grub.conf. For AMD CPU, add iommu=pt " "iommu=1." msgstr "" msgid "\"name\" should be a device name string" msgstr "" #, python-format msgid "" "The device %(name)s is probably in use by the host. Unable to attach it to " "the guest." msgstr "" #, python-format msgid "Interface %(iface)s does not exist in virtual machine %(name)s" msgstr "" #, python-format msgid "" "Network %(network)s specified for virtual machine %(name)s does not exist" msgstr "" msgid "Supported virtual machine interfaces type is only network" msgstr "" msgid "Network name for virtual machine interface must be a string" msgstr "" msgid "Invalid network model card specified for virtual machine interface" msgstr "" msgid "Specify type and network to add a new virtual machine interface" msgstr "" msgid "MAC Address must respect this format FF:FF:FF:FF:FF:FF" msgstr "" #, python-format msgid "MAC Address %(mac)s already exists in virtual machine %(name)s" msgstr "" msgid "Invalid MAC Address" msgstr "" msgid "Cannot change MAC address of a running virtual machine" msgstr "" #, python-format msgid "Template %(name)s already exists" msgstr "" #, python-format msgid "" "Network '%(network)s' specified for template %(template)s does not exist" msgstr "" #, python-format msgid "" "Storage pool %(pool)s specified for template %(template)s does not exist" msgstr "" #, python-format msgid "Storage pool %(pool)s specified for template %(template)s is not active" msgstr "" #, python-format msgid "Invalid parameter '%(param)s' specified for CDROM." msgstr "" #, python-format msgid "Network %(network)s specified for template %(template)s is not active" msgstr "" msgid "Template name must be a string" msgstr "" msgid "Template icon must be a path to the image" msgstr "" msgid "Template distribution must be a string" msgstr "" msgid "Template distribution version must be a string" msgstr "" msgid "The number of CPUs must be an integer greater than 0" msgstr "" msgid "Amount of memory (MB) must be an integer greater than 512" msgstr "" msgid "Template CDROM must be a local or remote ISO file" msgstr "" #, python-format msgid "Invalid storage pool URI %(value)s specified for template" msgstr "" msgid "Specify an ISO image as CDROM or a base image to create a template" msgstr "" msgid "All networks for the template must be specified in a list." msgstr "" msgid "Specify a volume to a template when storage pool is iSCSI or SCSI" msgstr "" #, python-format msgid "The volume %(volume)s is not in storage pool %(pool)s" msgstr "" #, python-format msgid "Unable to create template due error: %(err)s" msgstr "" #, python-format msgid "Unable to delete template due error: %(err)s" msgstr "" msgid "Disk size must be an integer greater than 1GB." msgstr "" msgid "Template base image must be a valid local image file" msgstr "" #, python-format msgid "Cannot identify base image %(path)s format" msgstr "" msgid "" "When specifying CPU topology, VCPUs must be a product of sockets, cores, and " "threads." msgstr "" msgid "" "When specifying CPU topology, each element must be an integer greater than " "zero." msgstr "" msgid "" "Invalid disk image format. Valid formats: bochs, cloop, cow, dmg, qcow, " "qcow2, qed, raw, vmdk, vpc." msgstr "" #, python-format msgid "Storage pool %(name)s already exists" msgstr "" #, python-format msgid "Storage pool %(name)s does not exist" msgstr "" #, python-format msgid "Specify %(item)s in order to create the storage pool %(name)s" msgstr "" #, python-format msgid "Unable to delete active storage pool %(name)s" msgstr "" #, python-format msgid "Unable to list storage pools. Details: %(err)s" msgstr "" #, python-format msgid "Unable to create storage pool %(name)s. Details: %(err)s" msgstr "" #, python-format msgid "" "Unable to get number of storage volumes in storage pool %(name)s. Details: " "%(err)s" msgstr "" #, python-format msgid "Unable to activate storage pool %(name)s. Details: %(err)s" msgstr "" #, python-format msgid "Unable to deactivate storage pool %(name)s. Details: %(err)s" msgstr "" #, python-format msgid "Unable to delete storage pool %(name)s. Details: %(err)s" msgstr "" #, python-format msgid "" "Unable to create NFS Pool as export path %(path)s may block during mount" msgstr "" #, python-format msgid "Unable to create NFS Pool as export path %(path)s mount failed" msgstr "" #, python-format msgid "Unsupported storage pool type: %(type)s" msgstr "" #, python-format msgid "Error while retrieving storage pool XML to %(pool)s" msgstr "" msgid "Storage pool name must be a string without slashes (/)" msgstr "" msgid "" "Supported storage pool types are dir, netfs, logical, iscsi, isci and kimchi-" "iso" msgstr "" msgid "Storage pool path must be a string" msgstr "" msgid "Storage pool host must be a IP or hostname" msgstr "" msgid "Storage pool device must be the absolute path to the block device" msgstr "" msgid "Storage pool devices parameter must be a list" msgstr "" msgid "Target IQN of an iSCSI pool must be a string" msgstr "" msgid "Port of a remote storage server must be an integer between 1 and 65535" msgstr "" msgid "iSCSI target username must be a string" msgstr "" msgid "iSCSI target password must be a string" msgstr "" msgid "Specify name and type to create a storage pool" msgstr "" #, python-format msgid "" "%(disk)s is not a valid disk/partition. Could not add it to the pool " "%(pool)s." msgstr "" #, python-format msgid "Unable to extend logical pool %(pool)s. Details: %(err)s" msgstr "" msgid "The parameter disks only can be updated for logical storage pool." msgstr "" msgid "The SCSI host adapter name must be a string." msgstr "" msgid "The storage pool kimchi_isos is reserved for internal use" msgstr "" #, python-format msgid "" "Unable to activate NFS storage pool %(name)s. NFS server %(server)s is " "unreachable." msgstr "" #, python-format msgid "" "Unable to deactivate NFS storage pool %(name)s. NFS server %(server)s is " "unreachable." msgstr "" #, python-format msgid "" "Unable to deactivate pool %(name)s as it is associated with some templates" msgstr "" #, python-format msgid "Unable to delete pool %(name)s as it is associated with some templates" msgstr "" #, python-format msgid "" "A volume group named '%(name)s' already exists. Please, choose another name " "to create the logical pool." msgstr "" #, python-format msgid "Unable to update database with deep scan information due error: %(err)s" msgstr "" #, python-format msgid "Storage volume %(name)s already exists" msgstr "" #, python-format msgid "Storage volume %(name)s does not exist in storage pool %(pool)s" msgstr "" #, python-format msgid "" "Unable to create storage volume %(volume)s because storage pool %(pool)s is " "not active" msgstr "" #, python-format msgid "Specify %(item)s in order to create storage volume %(volume)s" msgstr "" #, python-format msgid "" "Unable to list storage volumes because storage pool %(pool)s is not active" msgstr "" #, python-format msgid "" "Unable to create storage volume %(name)s in storage pool %(pool)s. Details: " "%(err)s" msgstr "" #, python-format msgid "" "Unable to list storage volumes in storage pool %(pool)s. Details: %(err)s" msgstr "" #, python-format msgid "Unable to wipe storage volumes %(name)s. Details: %(err)s" msgstr "" #, python-format msgid "Unable to delete storage volume %(name)s. Details: %(err)s" msgstr "" #, python-format msgid "Unable to resize storage volume %(name)s. Details: %(err)s" msgstr "" #, python-format msgid "Storage type %(type)s does not support volume create and delete" msgstr "" msgid "Storage volume name must be a string" msgstr "" msgid "Storage volume allocation must be an integer number" msgstr "" msgid "" "Storage volume format not supported. Valid formats: bochs, cloop, cow, dmg, " "qcow, qcow2, qed, raw, vmdk, vpc." msgstr "" msgid "Storage volume requires a volume name" msgstr "" #, python-format msgid "" "Unable to update database with storage volume information due error: %(err)s" msgstr "" #, python-format msgid "Only one of parameter %(param)s can be specified" msgstr "" #, python-format msgid "Create volume from %(param)s is not supported" msgstr "" msgid "Storage volume capacity must be an integer number." msgstr "" msgid "Storage volume URL must be http://, https://, ftp:// or ftps://." msgstr "" #, python-format msgid "Unable to access file %(url)s. Please, check it." msgstr "" #, python-format msgid "" "Unable to clone storage volume '%(name)s' in pool '%(pool)s'. Details: " "%(err)s" msgstr "" msgid "Specify chunk data and its size to upload a file." msgstr "" msgid "In order to upload a storage volume, specify the 'upload' parameter." msgstr "" msgid "" "Unable to upload chunk data as it does not match with requested chunk size." msgstr "" #, python-format msgid "The storage volume %(vol)s is not under an upload process." msgstr "" msgid "The upload chunk data will exceed the storage volume size." msgstr "" #, python-format msgid "Unable to upload chunk data to storage volume. Details: %(err)s." msgstr "" #, python-format msgid "Interface %(name)s does not exist" msgstr "" #, python-format msgid "Network %(name)s already exists" msgstr "" #, python-format msgid "Network %(name)s does not exist" msgstr "" #, python-format msgid "Subnet %(subnet)s specified for network %(network)s is not valid." msgstr "" #, python-format msgid "Specify a network interface to create bridged network %(name)s" msgstr "" #, python-format msgid "Unable to delete active network %(name)s" msgstr "" #, python-format msgid "Interface %(iface)s specified for network %(network)s is already in use" msgstr "" msgid "Interface should be bare NIC, bonding or bridge device." msgstr "" #, python-format msgid "Unable to create network %(name)s. Details: %(err)s" msgstr "" #, python-format msgid "Unable to find a free IP address for network '%(name)s'" msgstr "" #, python-format msgid "The interface %(iface)s already exists." msgstr "" msgid "Network name must be a string without slashes (/) or quotes (\")" msgstr "" msgid "Supported network types are isolated, NAT and bridge" msgstr "" msgid "Network subnet must be a string with IP address and prefix or netmask" msgstr "" msgid "Network interface must be a string" msgstr "" msgid "Network VLAN ID must be an integer between 1 and 4094" msgstr "" msgid "Specify name and type to create a Network" msgstr "" #, python-format msgid "" "Unable to delete network %(name)s. There are some virtual machines %(vms)s " "and/or templates linked to this network." msgstr "" #, python-format msgid "" "Unable to deactivate network %(name)s. There are some virtual machines " "%(vms)s and/or templates linked to this network." msgstr "" #, python-format msgid "Bridge device %(name)s can not be the trunk device of a VLAN." msgstr "" #, python-format msgid "Failed to activate interface %(iface)s: %(err)s." msgstr "" #, python-format msgid "" "Failed to activate interface %(iface)s. Please check the physical link " "status." msgstr "" #, python-format msgid "Failed to start network %(name)s. Details: %(err)s" msgstr "" #, python-format msgid "Debug report %(name)s does not exist" msgstr "" msgid "Debug report tool not found in system" msgstr "" #, python-format msgid "Unable to create debug report %(name)s. Details: %(err)s." msgstr "" #, python-format msgid "Can not find any debug report with the given name %(name)s" msgstr "" #, python-format msgid "Unable to generate debug report %(name)s. Details: %(err)s" msgstr "" msgid "You should give a name for the debug report file." msgstr "" msgid "" "Debug report name must be a string. Only letters, digits, underscore ('_') " "and hyphen ('-') are allowed." msgstr "" #, python-format msgid "" "The debug report with specified name \"%(name)s\" already exists. Please use " "another one." msgstr "" #, python-format msgid "Storage server %(server)s was not used by Kimchi" msgstr "" #, python-format msgid "Distro '%(name)s' does not exist" msgstr "" #, python-format msgid "Partition %(name)s does not exist in the host" msgstr "" msgid "Unable to shutdown host machine as there are running virtual machines" msgstr "" msgid "Unable to reboot host machine as there are running virtual machines" msgstr "" #, python-format msgid "Node device '%(name)s' not found" msgstr "" msgid "Conflicting flag filters specified." msgstr "" msgid "No packages marked for update" msgstr "" #, python-format msgid "Package %(name)s is not marked to be updated." msgstr "" #, python-format msgid "Error while getting packages marked to be updated. Details: %(err)s" msgstr "" msgid "There is no compatible package manager for this system." msgstr "" #, python-format msgid "Unable to find %(item)s in datastore" msgstr "" #, python-format msgid "Invalid URI %(uri)s" msgstr "" #, python-format msgid "Timeout while running command '%(cmd)s' after %(seconds)s seconds" msgstr "" msgid "Unable to choose a virtual machine name" msgstr "" #, python-format msgid "Invalid data value '%(value)s'" msgstr "" #, python-format msgid "Invalid data unit '%(unit)s'" msgstr "" msgid "Invalid storage type. Types supported: 'cdrom', 'disk'" msgstr "" #, python-format msgid "The path '%(value)s' is not a valid local/remote path for the device" msgstr "" msgid "Only CDROM path can be update." msgstr "" #, python-format msgid "" "The storage device %(dev_name)s does not exist in the virtual machine " "%(vm_name)s" msgstr "" #, python-format msgid "Error while creating new storage device: %(error)s" msgstr "" #, python-format msgid "Error while updating storage device: %(error)s" msgstr "" #, python-format msgid "Error while removing storage device: %(error)s" msgstr "" msgid "Do not support IDE device hot plug" msgstr "" msgid "" "Specify type and path or type and pool/volume to add a new virtual machine " "disk" msgstr "" msgid "Specify path to update virtual machine disk" msgstr "" #, python-format msgid "Controller type %(type)s limitation of %(limit)s devices reached" msgstr "" #, python-format msgid "Cannot retrieve disk path information for given pool/volume: %(error)s" msgstr "" msgid "Volume already in use by other virtual machine." msgstr "" msgid "" "Only one of path or pool/volume can be specified to add a new virtual " "machine disk" msgstr "" #, python-format msgid "" "Volume chosen with format %(format)s does not fit in the storage type " "%(type)s" msgstr "" msgid "YUM Repository ID must be one word only string." msgstr "" msgid "Repository URL must be an http://, ftp:// or file:// URL." msgstr "" msgid "" "Repository configuration is a dictionary with specific values according to " "repository type." msgstr "" msgid "Distribution to DEB repository must be a string" msgstr "" msgid "Components to DEB repository must be listed in a array" msgstr "" msgid "Components to DEB repository must be a string" msgstr "" msgid "Mirror list to repository must be a string" msgstr "" msgid "YUM Repository name must be string." msgstr "" msgid "GPG check must be a boolean value." msgstr "" msgid "GPG key must be a URL pointing to the ASCII-armored file." msgstr "" #, python-format msgid "Could not update repository %(repo_id)s." msgstr "" #, python-format msgid "Repository %(repo_id)s does not exist." msgstr "" msgid "" "Specify repository base URL, mirror list or metalink in order to create or " "update a YUM repository." msgstr "" msgid "Repository management tool was not recognized for your system." msgstr "" #, python-format msgid "Repository %(repo_id)s is already enabled." msgstr "" #, python-format msgid "Repository %(repo_id)s is already disabled." msgstr "" #, python-format msgid "Could not remove repository %(repo_id)s." msgstr "" #, python-format msgid "Could not write repository configuration file %(repo_file)s" msgstr "" msgid "Specify repository distribution in order to create a DEB repository." msgstr "" #, python-format msgid "Could not enable repository %(repo_id)s." msgstr "" #, python-format msgid "Could not disable repository %(repo_id)s." msgstr "" msgid "YUM Repository ID already exists" msgstr "" msgid "YUM Repository name must be a string" msgstr "" #, python-format msgid "Unable to list repositories. Details: '%(err)s'" msgstr "" #, python-format msgid "Unable to retrieve repository information. Details: '%(err)s'" msgstr "" #, python-format msgid "Unable to add repository. Details: '%(err)s'" msgstr "" #, python-format msgid "Unable to remove repository. Details: '%(err)s'" msgstr "" #, python-format msgid "" "Configuration items: '%(items)s' are not supported by repository manager" msgstr "" msgid "Repository metalink must be an http://, ftp:// or file:// URL." msgstr "" msgid "Cannot specify mirrorlist and metalink at the same time." msgstr "" #, python-format msgid "" "Virtual machine '%(vm)s' must be stopped before creating a snapshot of it." msgstr "" #, python-format msgid "" "Unable to create snapshot '%(name)s' on virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "Snapshot '%(name)s' does not exist on virtual machine '%(vm)s'." msgstr "" #, python-format msgid "" "Unable to retrieve snapshot '%(name)s' on virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "Unable to list snapshots on virtual machine '%(vm)s'. Details: %(err)s" msgstr "" #, python-format msgid "" "Unable to delete snapshot '%(name)s' on virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "" "Unable to retrieve current snapshot of virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "" "Unable to revert virtual machine '%(vm)s' to snapshot '%(name)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "" "Unable to create snapshot of virtual machine '%(vm)s' because it contains a " "disk with format '%(format)s'; only 'qcow2' is supported." msgstr "" msgid "The number of vCPUs is too large for this system." msgstr "" msgid "Invalid vCPU/topology combination." msgstr "" msgid "This host (or current configuration) does not allow CPU topology." msgstr "" msgid "ERROR CODE" msgstr "" msgid "REASON" msgstr "" msgid "STACK" msgstr "" msgid "Go to Homepage" msgstr "" msgid "Create a New Virtual Machine" msgstr "" msgid "Virtual Machine Name" msgstr "" msgid "" "The name used to identify the virtual machine. If omitted, a name will be " "chosen based on the template used." msgstr "" msgid "Template" msgstr "" msgid "Please create a template first." msgstr "" msgid "Create a Template" msgstr "" msgid "Please choose a template." msgstr "" msgid "OS" msgstr "" msgid "OS Version" msgstr "" msgid "CPUS" msgstr "" msgid "Memory" msgstr "" msgid "Create" msgstr "" msgid "Creating..." msgstr "" msgid "Edit Guest" msgstr "" msgid "General" msgstr "" msgid "Storage" msgstr "" msgid "Interface" msgstr "" msgid "Permission" msgstr "" msgid "Host PCI Device" msgstr "" msgid "Snapshot" msgstr "" msgid "Name" msgstr "" msgid "CPUs" msgstr "" msgid "Memory (MB)" msgstr "" msgid "Icon" msgstr "" msgid "Device" msgstr "" msgid "Path" msgstr "" msgid "Network" msgstr "" msgid "Type" msgstr "" msgid "MAC Address" msgstr "" msgid "Available system users and groups" msgstr "" msgid "Selected system users and groups" msgstr "" msgid "User" msgstr "" msgid "All" msgstr "" msgid "To Add" msgstr "" msgid "Added" msgstr "" msgid "filter" msgstr "" msgid "Product" msgstr "" msgid "Vendor" msgstr "" msgid "Created" msgstr "" msgid "Save" msgstr "" msgid "Replace" msgstr "" msgid "Detach" msgstr "" msgid "Cancel" msgstr "" msgid "revert" msgstr "" msgid "Add a Storage Device to VM" msgstr "" msgid "Device Type" msgstr "" msgid "The device type. Currently, \"cdrom\" and \"disk\" are supported." msgstr "" msgid "Storage Pool" msgstr "" msgid "Storage pool which volume located in" msgstr "" msgid "Storage Volume" msgstr "" msgid "Storage volume to be attached" msgstr "" msgid "File Path" msgstr "" msgid "The ISO file path in the server for CDROM." msgstr "" msgid "Attach" msgstr "" msgid "Start" msgstr "" msgid "Reset" msgstr "" msgid "Pause" msgstr "" msgid "Resume" msgstr "" msgid "Power Off" msgstr "" msgid "Actions" msgstr "" msgid "Connect" msgstr "" msgid "Clone" msgstr "" msgid "Edit" msgstr "" msgid "Shut Down" msgstr "" msgid "Delete" msgstr "" msgid "The username or password you entered is incorrect. Please try again." msgstr "" msgid "This field is required." msgstr "" msgid "Log in" msgstr "" msgid "Logging in..." msgstr "" msgid "Host" msgstr "" msgid "Guests" msgstr "" msgid "Templates" msgstr "" msgid "Failed to get application configuration" msgstr "" msgid "This is not a valid Linux path" msgstr "" msgid "This is not a valid URL." msgstr "" msgid "No such data available." msgstr "" msgid "" "Can not contact the host system. Verify the host system is up and that you " "have network connectivity to it. HTTP request response %1. " msgstr "" msgid "Unable to read file." msgstr "" msgid "Error while uploading file." msgstr "" msgid "Delete Confirmation" msgstr "" msgid "OK" msgstr "" msgid "Confirm" msgstr "" msgid "Warning" msgstr "" msgid "Cloning..." msgstr "" msgid "Loading..." msgstr "" msgid "An error occurred while retrieving system information." msgstr "" msgid "Retry" msgstr "" msgid "Detailed message:" msgstr "" msgid "No ISO found" msgstr "" msgid "This is not a valid ISO file." msgstr "" msgid "This may take a long time. Do you want to continue?" msgstr "" msgid "This will permanently delete the template. Would you like to continue?" msgstr "" msgid "Unable to shut down system as there are some virtual machines running!" msgstr "" msgid "Max:" msgstr "" msgid "Utilization" msgstr "" msgid "Available" msgstr "" msgid "Read Rate" msgstr "" msgid "Write Rate" msgstr "" msgid "Received" msgstr "" msgid "Sent" msgstr "" msgid "" "Shutting down or restarting host will cause unsaved work lost. Continue to " "shut down/restarting?" msgstr "" msgid "" "Repository will be removed permanently and can't be recovered. Do you want " "to continue?" msgstr "" msgid "Repositories" msgstr "" msgid "ID" msgstr "" msgid "Base URL" msgstr "" msgid "Is Mirror" msgstr "" msgid "URL Args" msgstr "" msgid "Enabled" msgstr "" msgid "GPG Check" msgstr "" msgid "GPG Key" msgstr "" msgid "Add" msgstr "" msgid "Remove" msgstr "" msgid "Enable" msgstr "" msgid "Disable" msgstr "" msgid "Software Updates" msgstr "" msgid "Package Name" msgstr "" msgid "Version" msgstr "" msgid "Architecture" msgstr "" msgid "Repository" msgstr "" msgid "Update All" msgstr "" msgid "Updating..." msgstr "" msgid "Failed to retrieve packages update information." msgstr "" msgid "Failed to update package(s)." msgstr "" msgid "" "Debug report will be removed permanently and can't be recovered. Do you want " "to continue?" msgstr "" msgid "Debug Reports" msgstr "" msgid "Generated Time" msgstr "" msgid "Generate" msgstr "" msgid "Generating..." msgstr "" msgid "Rename" msgstr "" msgid "Download" msgstr "" msgid "" "Report name should contain only letters, digits, underscore ('_') and/or " "hyphen ('-')." msgstr "" msgid "Pending..." msgstr "" msgid "Report name is the same as the original one." msgstr "" msgid "" "This will delete the virtual machine and its virtual disks. This operation " "cannot be undone. Would you like to continue?" msgstr "" msgid "Power off Confirmation" msgstr "" msgid "" "This action may produce undesirable results, for example unflushed disk " "cache in the guest. Would you like to continue?" msgstr "" msgid "Reset Confirmation" msgstr "" msgid "" "There is a risk of data loss caused by reset without the guest OS shutdown. " "Would you like to continue?" msgstr "" msgid "Shut Down Confirmation" msgstr "" msgid "Note the guest OS may ignore this request. Would you like to continue?" msgstr "" msgid "Virtual Machine delete Confirmation" msgstr "" msgid "" "This virtual machine is not persistent. Power Off will delete it. Continue?" msgstr "" msgid "" "When the target guest has SCSI or iSCSI volumes, they will be cloned on " "default storage pool. The same will happen when the target pool does not " "have enough space to clone the volumes. Do you want to continue?" msgstr "" msgid "" "This CDROM will be detached permanently and you can re-attach it. Continue " "to detach it?" msgstr "" msgid "Attaching..." msgstr "" msgid "Replacing..." msgstr "" msgid "Successfully attached!" msgstr "" msgid "Successfully replaced!" msgstr "" msgid "Successfully detached!" msgstr "" msgid "" "This disk will be detached permanently and you can re-attach it. Continue to " "detach it?" msgstr "" msgid "interface:" msgstr "" msgid "address:" msgstr "" msgid "link_type:" msgstr "" msgid "block:" msgstr "" msgid "drive_type:" msgstr "" msgid "model:" msgstr "" msgid "Affected devices:" msgstr "" msgid "The VLAN id must be between 1 and 4094." msgstr "" msgid "unavailable" msgstr "" msgid "" "This action will interrupt network connectivity for any virtual machine that " "depend on this network." msgstr "" msgid "Create a network" msgstr "" msgid "" "This network is not persistent. Instead of stop, this action will " "permanently delete it. Would you like to continue?" msgstr "" msgid "" "The bridged VLAN tag may not work well with NetworkManager enabled. You " "should consider disabling it." msgstr "" msgid "" "This will permanently delete the storage pool. Would you like to continue?" msgstr "" msgid "This storage pool is empty." msgstr "" msgid "" "It will format your disk and you will loose any data in there, are you sure " "to continue? " msgstr "" msgid "SCSI Fibre Channel" msgstr "" msgid "No SCSI adapters found." msgstr "" msgid "Loading iSCSI targets..." msgstr "" msgid "No iSCSI found. Please input one." msgstr "" msgid "Failed to load iSCSI targets." msgstr "" msgid "The storage pool name can not be blank." msgstr "" msgid "The storage pool path can not be blank." msgstr "" msgid "NFS server mount path can not be blank." msgstr "" msgid "Invalid NFS mount path." msgstr "" msgid "No logical device selected." msgstr "" msgid "The iSCSI target can not be blank." msgstr "" msgid "Server name can not be blank." msgstr "" msgid "This is not a valid Server Name or IP. Please, modify it." msgstr "" msgid "Looking for available partitions ..." msgstr "" msgid "No available partitions found." msgstr "" msgid "" "This storage pool is not persistent. Instead of deactivate, this action will " "permanently delete it. Would you like to continue?" msgstr "" msgid "Unable to retrieve partitions information." msgstr "" msgid "In progress..." msgstr "" msgid "Failed!" msgstr "" msgid "CDROM path needs to be a valid local/remote path and cannot be blank." msgstr "" msgid "Disk pool or volume cannot be blank." msgstr "" msgid "Peers" msgstr "" msgid "Searching" msgstr "" msgid "No peers found." msgstr "" msgid "Help" msgstr "" msgid "About" msgstr "" msgid "Log out" msgstr "" msgid "Version:" msgstr "" msgid "Session timeout, please re-login." msgstr "" msgid "User Name" msgstr "" msgid "Password" msgstr "" msgid "Generate a New Debug Report" msgstr "" msgid "Report Name" msgstr "" msgid "" "The name used to identify the report. If omitted, a name will be chosen " "based on current time. Name can contain: letters, digits, underscore (\"_\") " "and hyphen (\"-\")." msgstr "" msgid "Rename a Debug Report" msgstr "" msgid "" "The name used to identify the report. Name can contain: letters, digits and " "hyphen (\"-\")." msgstr "" msgid "Submit" msgstr "" msgid "Add a Repository" msgstr "" msgid "Identifier" msgstr "" msgid "Single word, unique identifier for the repository." msgstr "" msgid "Textual name for the repository." msgstr "" msgid "URL" msgstr "" msgid "Required Field" msgstr "" msgid "URL to the repository. Supported protocols are http, ftp, and file." msgstr "" msgid "Repository is a mirror" msgstr "" msgid "Distribution" msgstr "" msgid "Distribution of the DEB repository." msgstr "" msgid "Components" msgstr "" msgid "List of components in DEB repository." msgstr "" msgid "Edit Repository" msgstr "" msgid "Mirror List URL" msgstr "" msgid "Yes" msgstr "" msgid "No" msgstr "" msgid "Add a Volume to Storage Pool" msgstr "" msgid "Fetch from remote URL" msgstr "" msgid "Enter the remote URL here." msgstr "" msgid "Upload a file" msgstr "" msgid "Choose the file you want to upload." msgstr "" msgid "Define a New Storage Pool" msgstr "" msgid "Storage Pool Name" msgstr "" msgid "" "The name used to identify the storage pools, and it should not be empty." msgstr "" msgid "Storage Pool Type" msgstr "" msgid "Storage Path" msgstr "" msgid "" "The path of the Storage Pool. Each Storage Pool must have a unique path." msgstr "" msgid "" "Kimchi will try to create the directory when it does not already exist in " "your system." msgstr "" msgid "NFS Server IP" msgstr "" msgid "NFS server IP or hostname. It can be input or chosen from history." msgstr "" msgid "NFS Path" msgstr "" msgid "The NFS exported path on NFS server." msgstr "" msgid "Device path" msgstr "" msgid "iSCSI Server" msgstr "" msgid "iSCSI server IP or hostname. It should not be empty." msgstr "" msgid "Server" msgstr "" msgid "Port" msgstr "" msgid "Target" msgstr "" msgid "The iSCSI target on iSCSI server" msgstr "" msgid "Add iSCSI Authentication" msgstr "" msgid "iSCSI Authentication" msgstr "" msgid "SCSI Adapter" msgstr "" msgid "Please, wait..." msgstr "" msgid "Add Template" msgstr "" msgid "Where is the source media for this template? " msgstr "" msgid "Local ISO Image" msgstr "" msgid "Local Image File" msgstr "" msgid "Remote ISO Image" msgstr "" msgid "Search ISOs" msgstr "" msgid "The following ISOs are available:" msgstr "" msgid "OS: " msgstr "" msgid "Version: " msgstr "" msgid "Size: " msgstr "" msgid "Search more ISOs" msgstr "" msgid "Create Templates from Selected ISO" msgstr "" msgid "I want to use a specific ISO file" msgstr "" msgid "Loading default remote ISOs ..." msgstr "" msgid "Arch: " msgstr "" msgid "I want to use a custom URL" msgstr "" msgid "Edit Template" msgstr "" msgid "Processor" msgstr "" msgid "CDROM" msgstr "" msgid "Image File" msgstr "" msgid "Graphics" msgstr "" msgid "Disk(GB)" msgstr "" msgid "Disk Format" msgstr "" msgid "CPU Number" msgstr "" msgid "Manually set CPU topology" msgstr "" msgid "Cores" msgstr "" msgid "Threads" msgstr "" msgid "CPU" msgstr "" msgid "Disk I/O" msgstr "" msgid "Network I/O" msgstr "" msgid "Livetile" msgstr "" msgid "No guests found." msgstr "" msgid "Shut down" msgstr "" msgid "Restart" msgstr "" msgid "Basic Information" msgstr "" msgid "OS Distro" msgstr "" msgid "OS Code Name" msgstr "" msgid "CPU(s)" msgstr "" msgid "System Statistics" msgstr "" msgid "Update Progress" msgstr "" msgid "Network Name" msgstr "" msgid "State" msgstr "" msgid "Network Type" msgstr "" msgid "Address Space" msgstr "" msgid "Name should not contain '/' and '\"'." msgstr "" msgid "Isolated: no external network connection" msgstr "" msgid "NAT: outbound physical network connection only" msgstr "" msgid "Bridged: Virtual machines are connected to physical network directly" msgstr "" msgid "(No interfaces found)" msgstr "" msgid "Destination" msgstr "" msgid "Enable VLAN" msgstr "" msgid "VLAN ID" msgstr "" msgid "Stop" msgstr "" msgid "%Used" msgstr "" msgid "Location" msgstr "" msgid "Capacity" msgstr "" msgid "Allocated" msgstr "" msgid "active" msgstr "" msgid "inactive" msgstr "" msgid "Deactivate" msgstr "" msgid "Activate" msgstr "" msgid "Add Volume" msgstr "" msgid "Extend" msgstr "" msgid "Undefine" msgstr "" msgid "Format" msgstr "" msgid "Allocation" msgstr "" msgid "No templates found." msgstr "" kimchi-1.5.0/po/es_ES.po000066400000000000000000001670561254252253000147540ustar00rootroot00000000000000# English translations for kimchi package. # Copyright (C) 2013 ORGANIZATION # msgid "" msgstr "" "Project-Id-Version: kimchi 0.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-06-24 09:39-0300\n" "PO-Revision-Date: 2013-07-11 17:32-0400\n" "Last-Translator: Crístian Viana \n" "Language-Team: English\n" "Language: es_ES\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: pygettext.py 1.5\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #, python-format msgid "Unknown parameter %(value)s" msgstr "" #, python-format msgid "Delete is not allowed for %(resource)s" msgstr "Suprimir no está permitido para %(resource)s" #, python-format msgid "%(resource)s does not implement update method" msgstr "%(resource)s no implementa método de actualización" #, python-format msgid "Create is not allowed for %(resource)s" msgstr "Crear no está permitido para %(resource)s" msgid "Unable to parse JSON request" msgstr "No se puede analizar la solicitud JSON" msgid "This API only supports JSON" msgstr "Esta API sólo da soporte a JSON" #, python-format msgid "Parameters does not match requirement in schema: %(err)s" msgstr "" msgid "You don't have permission to perform this operation." msgstr "" msgid "Datastore is not initiated in the model object." msgstr "El almacén de datos no se ha iniciado en el objeto de modelo." #, python-format msgid "Unable to start task due error: %(err)s" msgstr "No se puede iniciar la tarea debido a un error: %(err)s" #, python-format msgid "Timeout of %(seconds)s seconds expired while running task '%(task)s." msgstr "" #, python-format msgid "Authentication failed for user '%(username)s'. [Error code: %(code)s]" msgstr "" "La autenticación ha fallado para el usuario '%(username)s'. [Código de " "error: %(code)s]" msgid "You are not authorized to access Kimchi" msgstr "No tiene autorización para acceder a Kimchi" #, python-format msgid "Specify %(item)s to login into Kimchi" msgstr "Especifique %(item)s para iniciar la sesión en Kimchi" #, python-format msgid "User %(user_id)s not found with given LDAP settings." msgstr "" #, python-format msgid "Invalid LDAP configuration: %(item)s : %(value)s" msgstr "" msgid "Unknown \"_cap\" specified" msgstr "" msgid "\"_passthrough\" should be \"true\" or \"false\"" msgstr "" msgid "\"_passthrough_affected_by\" should be a device name string" msgstr "" #, python-format msgid "Error while getting block devices. Details: %(err)s" msgstr "" "Se ha producido un error al obtener dispositivos de bloque. Detalles: %(err)s" #, python-format msgid "Error while getting block device information for %(device)s." msgstr "" "Se ha producido un error al obtener información de dispositivo de bloque " "para %(device)s." #, python-format msgid "Unable to find distro file: %(filename)s" msgstr "No se puede encontrar el archivo distro: %(filename)s" #, python-format msgid "" "Unable to parse distro file: %(filename)s. Make sure, it is a JSON file." msgstr "" "No se puede analizar el archivo distro: %(filename)s. Asegúrese de que es un " "archivo JSON." #, python-format msgid "Unable to login to iSCSI host target %(portal)s. Details: %(err)s" msgstr "" "No se puede iniciar la sesión en %(portal)s del destino de host iSCSI. " "Detalles: %(err)s" #, python-format msgid "Unable to login to iSCSI host %(host)s target %(target)s" msgstr "" "No se puede iniciar la sesión en el destino %(target)s del %(host)s host de " "iSCSI" #, python-format msgid "Unable to find ISO file %(filename)s" msgstr "" #, python-format msgid "The ISO file %(filename)s is not bootable" msgstr "El archivo ISO %(filename)s no es arrancable" #, python-format msgid "The ISO file %(filename)s does not have a valid El Torito boot record" msgstr "" "El archivo ISO %(filename)s no tiene un registro de arranque de El Torito " "válido" #, python-format msgid "Invalid El Torito validation entry in ISO %(filename)s" msgstr "Entrada de validación de El Torito no válida en ISO %(filename)s" #, python-format msgid "Invalid El Torito boot indicator in ISO %(filename)s" msgstr "Indicador de arranque de El Torito no válido en ISO %(filename)s" #, python-format msgid "Unexpected volume type for primary volume in ISO %(filename)s" msgstr "" "Tipo de volumen inesperado para el volumen primario en ISO %(filename)s" #, python-format msgid "Bad format while reading volume descriptor in ISO %(filename)s" msgstr "" "Formato incorrecto mientras se leía el descriptor de volumen en ISO " "%(filename)s" #, python-format msgid "" "The hypervisor doesn't have permission to use this ISO %(filename)s. " "Consider moving it under /var/lib/libvirt, or set the search permission to " "file access control lists for '%(user)s' user if possible, or add the " "'%(user)s' to the ISO path group, or (not recommended) 'chmod -R o+x " "'path_to_iso'.Details: %(err)s" msgstr "" "El hipervisor no tiene permiso para utilizar este ISO %(filename)s. " "Considere moverlo a /var/lib/libvirt, o establezca el permiso de búsqueda en " "listas de control de accesos de archivo para el usuario '%(user)s' si es " "posible, o añada el '%(user)s' al grupo de vías de acceso ISO, o (no " "recomendado) 'chmod -R o+x 'path_to_iso'.Detalles: %(err)s" msgid "An error occurred when probing image OS information." msgstr "" msgid "No OS information found in given image." msgstr "" #, python-format msgid "Unable to read image file %(filename)s" msgstr "" #, python-format msgid "" "Image file must be an existing file on system. %(filename)s is not a valid " "input." msgstr "" #, python-format msgid "Virtual machine %(name)s already exists" msgstr "La máquina virtual %(name)s ya existe" #, python-format msgid "Virtual machine %(name)s does not exist" msgstr "La máquina virtual %(name)s no existe" #, python-format msgid "" "Unable to rename virtual machine %(name)s. The name %(new_name)s is already " "in use or the virtual machine is not powered off." msgstr "" #, python-format msgid "Unable to retrieve screenshot for stopped virtual machine %(name)s" msgstr "" "No se puede recuperar la captura de pantalla para la máquina virtual " "detenida %(name)s" msgid "Remote ISO image is not supported by this server." msgstr "La imagen ISO remota no está soportada por este servidor." #, python-format msgid "Screenshot is not supported on virtual machine %(name)s" msgstr "" #, python-format msgid "Unable to create virtual machine %(name)s. Details: %(err)s" msgstr "No se puede crear la máquina virtual %(name)s. Detalles: %(err)s" #, python-format msgid "Unable to update virtual machine %(name)s. Details: %(err)s" msgstr "No se puede crear la máquina virtual %(name)s. Detalles: %(err)s" #, python-format msgid "Unable to retrieve virtual machine %(name)s. Details: %(err)s" msgstr "No se puede recuperar la máquina virtual %(name)s. Detalles: %(err)s" #, python-format msgid "Unable to connect to powered off virtual machine %(name)s." msgstr "" msgid "Virtual machine name must be a string without slashes (/)" msgstr "" #, python-format msgid "Invalid template URI %(value)s specified for virtual machine" msgstr "" #, python-format msgid "Invalid storage pool URI %(value)s specified for virtual machine" msgstr "" msgid "Supported virtual machine graphics are Spice or VNC" msgstr "" msgid "Graphics address to listen on must be IPv4 or IPv6" msgstr "" "La dirección de gráficos en que hay que estar a la escucha debe ser IPv4 o " "IPv6" msgid "Specify a template to create a virtual machine from" msgstr "" "Especifique una plantilla a partir de la que se creará una máquina virtual" #, python-format msgid "Unable to start virtual machine %(name)s. Details: %(err)s" msgstr "No se puede iniciar la máquina virtual %(name)s. Detalles: %(err)s" #, python-format msgid "Unable to power off virtual machine %(name)s. Details: %(err)s" msgstr "No se puede detener la máquina virtual %(name)s. Detalles: %(err)s" #, python-format msgid "Unable to delete virtual machine %(name)s. Details: %(err)s" msgstr "No se puede suprimir la máquina virtual %(name)s. Detalles: %(err)s" #, python-format msgid "Unable to reset virtual machine %(name)s. Details: %(err)s" msgstr "No se puede redenominar la máquina virtual %(name)s. Detalles: %(err)s" msgid "User name list must be an array" msgstr "" msgid "User name must be a string" msgstr "El nombre de red debe ser una serie" msgid "Group name list must be an array" msgstr "" msgid "Group name must be a string" msgstr "El nombre de red debe ser una serie" #, python-format msgid "User(s) '%(users)s' do not exist" msgstr "El usuario '%(users)s' no existe." #, python-format msgid "Group(s) '%(groups)s' do not exist" msgstr "El usuario '%(groups)s' no existe." #, python-format msgid "Unable to shutdown virtual machine %(name)s. Details: %(err)s" msgstr "No se puede detener la máquina virtual %(name)s. Detalles: %(err)s" #, python-format msgid "" "Unable to get access metadata of virtual machine %(name)s. Details: %(err)s" msgstr "No se puede iniciar la máquina virtual %(name)s. Detalles: %(err)s" msgid "The guest console password must be a string." msgstr "" msgid "The life time for the guest console password must be a number." msgstr "" #, python-format msgid "Virtual machine '%(name)s' must be stopped before cloning it." msgstr "" #, python-format msgid "Insufficient disk space to clone virtual machine '%(name)s'" msgstr "" #, python-format msgid "Unable to clone VM '%(name)s'. Details: %(err)s" msgstr "" #, python-format msgid "Invalid operation for non-persistent virtual machine %(name)s" msgstr "" #, python-format msgid "Cannot suspend VM '%(name)s' because it is not running." msgstr "" #, python-format msgid "Unable to suspend VM '%(name)s'. Details: %(err)s" msgstr "" #, python-format msgid "Cannot resume VM '%(name)s' because it is not paused." msgstr "" #, python-format msgid "Unable to resume VM '%(name)s'. Details: %(err)s" msgstr "" msgid "Memory assigned is higher then the maximum allowed in the host." msgstr "" #, python-format msgid "" "VM '%(name)s' does not support live memory update. Update the memory with " "the machine offline to enable this feature." msgstr "" msgid "Only increase memory is allowed in active VMs" msgstr "" msgid "" "For live memory update, new memory value must be equal old memory value plus " "multiples of 1024 Mib" msgstr "" msgid "There are not enough free slots of 1024 Mib in the guest." msgstr "" msgid "" "Host's libvirt version does not support memory devices. Libvirt must be >= " "1.2.14" msgstr "" #, python-format msgid "Error attaching memory device. Details: %(error)s" msgstr "" #, python-format msgid "" "VM %(vmid)s does not contain directly assigned host device %(dev_name)s." msgstr "" #, python-format msgid "The host device %(dev_name)s is not allowed to directly assign to VM." msgstr "" msgid "" "No IOMMU groups found. Host PCI pass through needs IOMMU group to function " "correctly. Please enable Intel VT-d or AMD IOMMU in your BIOS, then verify " "the Kernel is compiled with IOMMU support. For Intel CPU, add intel_iommu=on " "to your Kernel parameter in /boot/grub2/grub.conf. For AMD CPU, add iommu=pt " "iommu=1." msgstr "" msgid "\"name\" should be a device name string" msgstr "" #, python-format msgid "" "The device %(name)s is probably in use by the host. Unable to attach it to " "the guest." msgstr "" #, python-format msgid "Interface %(iface)s does not exist in virtual machine %(name)s" msgstr "La interfaz %(iface)s no existe en la máquina virtual %(name)s" #, python-format msgid "" "Network %(network)s specified for virtual machine %(name)s does not exist" msgstr "" "La red %(network)s especificada para la máquina virtual %(name)s no existe" msgid "Supported virtual machine interfaces type is only network" msgstr "El tipo de interfaces de máquina virtual soportado es de red solamente" msgid "Network name for virtual machine interface must be a string" msgstr "" "El nombre de red para la interfaz de máquina virtual debe ser una serie" msgid "Invalid network model card specified for virtual machine interface" msgstr "" "Especificada tarjeta de modelo de red no válida para la interfaz de máquina " "virtual" msgid "Specify type and network to add a new virtual machine interface" msgstr "" "Especifique el tipo y la red para añadir una interfaz de máquina virtual " "nueva" msgid "MAC Address must respect this format FF:FF:FF:FF:FF:FF" msgstr "" #, python-format msgid "MAC Address %(mac)s already exists in virtual machine %(name)s" msgstr "" msgid "Invalid MAC Address" msgstr "" msgid "Cannot change MAC address of a running virtual machine" msgstr "" #, python-format msgid "Template %(name)s already exists" msgstr "La plantilla %(name)s ya existe" #, python-format msgid "" "Network '%(network)s' specified for template %(template)s does not exist" msgstr "" "La red '%(network)s' especificada para la plantilla %(template)s no existe" #, python-format msgid "" "Storage pool %(pool)s specified for template %(template)s does not exist" msgstr "" "La agrupación de almacenamiento %(pool)s especificada para la plantilla " "%(template)s no existe" #, python-format msgid "Storage pool %(pool)s specified for template %(template)s is not active" msgstr "" "La agrupación de almacenamiento %(pool)s especificada para la plantilla " "%(template)s no está activa" #, python-format msgid "Invalid parameter '%(param)s' specified for CDROM." msgstr "Parámetro no válido '%(param)s' especificado para CDROM." #, python-format msgid "Network %(network)s specified for template %(template)s is not active" msgstr "" "La red %(network)s especificada para la plantilla %(template)s no está activa" msgid "Template name must be a string" msgstr "El nombre de plantilla debe ser una serie" msgid "Template icon must be a path to the image" msgstr "El icono de plantilla debe ser una vía de acceso a la imagen" msgid "Template distribution must be a string" msgstr "La distribución de plantilla debe ser una serie" msgid "Template distribution version must be a string" msgstr "La versión de distribución de plantilla debe ser una serie" msgid "The number of CPUs must be an integer greater than 0" msgstr "El número de CPUs debe ser un entero" msgid "Amount of memory (MB) must be an integer greater than 512" msgstr "La cantidad de memoria (MB) debe ser un entero mayor que 512" msgid "Template CDROM must be a local or remote ISO file" msgstr "El CDROM de plantilla debe ser un archivo ISO local o remoto" #, python-format msgid "Invalid storage pool URI %(value)s specified for template" msgstr "" "URI de agrupación de almacenamiento no válido %(value)s especificado para la " "plantilla" msgid "Specify an ISO image as CDROM or a base image to create a template" msgstr "Especifique una imagen de ISO como CDROM para crear una plantilla" msgid "All networks for the template must be specified in a list." msgstr "Todas las redes para la plantilla deben especificarse en una lista." msgid "Specify a volume to a template when storage pool is iSCSI or SCSI" msgstr "" #, python-format msgid "The volume %(volume)s is not in storage pool %(pool)s" msgstr "" #, python-format msgid "Unable to create template due error: %(err)s" msgstr "No se puede crear la plantilla debido a un error: %(err)s" #, python-format msgid "Unable to delete template due error: %(err)s" msgstr "No se puede suprimir la plantilla debido a un error: %(err)s" msgid "Disk size must be an integer greater than 1GB." msgstr "" msgid "Template base image must be a valid local image file" msgstr "El CDROM de plantilla debe ser un archivo ISO local o remoto" #, python-format msgid "Cannot identify base image %(path)s format" msgstr "" msgid "" "When specifying CPU topology, VCPUs must be a product of sockets, cores, and " "threads." msgstr "" msgid "" "When specifying CPU topology, each element must be an integer greater than " "zero." msgstr "" msgid "" "Invalid disk image format. Valid formats: bochs, cloop, cow, dmg, qcow, " "qcow2, qed, raw, vmdk, vpc." msgstr "" #, python-format msgid "Storage pool %(name)s already exists" msgstr "La agrupación de almacenamiento %(name)s ya existe" #, python-format msgid "Storage pool %(name)s does not exist" msgstr "La agrupación de almacenamiento %(name)s no existe" #, python-format msgid "Specify %(item)s in order to create the storage pool %(name)s" msgstr "" "Especifique %(item)s para poder crear la agrupación de almacenamiento " "%(name)s" #, python-format msgid "Unable to delete active storage pool %(name)s" msgstr "No se puede suprimir la agrupación de almacenamiento activa %(name)s" #, python-format msgid "Unable to list storage pools. Details: %(err)s" msgstr "No se pueden listar agrupaciones de almacenamiento. Detalles: %(err)s" #, python-format msgid "Unable to create storage pool %(name)s. Details: %(err)s" msgstr "" "No se puede crear la agrupación de almacenamiento %(name)s. Detalles: %(err)s" #, python-format msgid "" "Unable to get number of storage volumes in storage pool %(name)s. Details: " "%(err)s" msgstr "" "No se puede obtener el número de volúmenes de almacenamiento en la " "agrupación de almacenamiento %(name)s. Detalles: %(err)s" #, python-format msgid "Unable to activate storage pool %(name)s. Details: %(err)s" msgstr "" "No se puede activar la agrupación de almacenamiento %(name)s. Detalles: " "%(err)s" #, python-format msgid "Unable to deactivate storage pool %(name)s. Details: %(err)s" msgstr "" "No se puede desactivar la agrupación de almacenamiento %(name)s. Detalles: " "%(err)s" #, python-format msgid "Unable to delete storage pool %(name)s. Details: %(err)s" msgstr "" "No se puede suprimir la agrupación de almacenamiento %(name)s. Detalles: " "%(err)s" #, python-format msgid "" "Unable to create NFS Pool as export path %(path)s may block during mount" msgstr "" "No se puede crear la agrupación de NFS ya que la vía de acceso de " "exportación %(path)s podría bloquearse durante el montaje" #, python-format msgid "Unable to create NFS Pool as export path %(path)s mount failed" msgstr "" "No se puede crear la agrupación de NFS ya que el montaje de la vía de acceso " "de exportación %(path)s ha fallado" #, python-format msgid "Unsupported storage pool type: %(type)s" msgstr "Tipo de agrupación de almacenamiento no soportado: %(type)s" #, python-format msgid "Error while retrieving storage pool XML to %(pool)s" msgstr "" msgid "Storage pool name must be a string without slashes (/)" msgstr "" msgid "" "Supported storage pool types are dir, netfs, logical, iscsi, isci and kimchi-" "iso" msgstr "" msgid "Storage pool path must be a string" msgstr "La vía de acceso de la agrupación de almacenamiento debe ser una serie" msgid "Storage pool host must be a IP or hostname" msgstr "" "El host de la agrupación de almacenamiento debe ser un IP o nombre de host" msgid "Storage pool device must be the absolute path to the block device" msgstr "" msgid "Storage pool devices parameter must be a list" msgstr "" "El parámetro de los dispositivos de agrupación de almacenamiento debe ser " "una lista" msgid "Target IQN of an iSCSI pool must be a string" msgstr "El IQN destino de una agrupación de iSCSI debe ser una serie" msgid "Port of a remote storage server must be an integer between 1 and 65535" msgstr "" "El puerto de un servidor de almacenamiento remoto debe ser un entero entre 1 " "y 65535" msgid "iSCSI target username must be a string" msgstr "" msgid "iSCSI target password must be a string" msgstr "" msgid "Specify name and type to create a storage pool" msgstr "" "Especifique el nombre y el tipo para crear una agrupación de almacenamiento" #, python-format msgid "" "%(disk)s is not a valid disk/partition. Could not add it to the pool " "%(pool)s." msgstr "" "%(disk)s no es un disco/partición. No se ha podido añadir a la agrupación " "%(pool)s." #, python-format msgid "Unable to extend logical pool %(pool)s. Details: %(err)s" msgstr "" msgid "The parameter disks only can be updated for logical storage pool." msgstr "" "Los discos de parámetro sólo pueden actualizarse para la agrupación de " "almacenamiento lógico." msgid "The SCSI host adapter name must be a string." msgstr "El nombre del adaptador de host SCSI debe ser una serie." msgid "The storage pool kimchi_isos is reserved for internal use" msgstr "" "La agrupación de almacenamiento kimchi_isos está reservada para uso interno" #, python-format msgid "" "Unable to activate NFS storage pool %(name)s. NFS server %(server)s is " "unreachable." msgstr "" "No se puede activar la agrupación de almacenamiento NFS %(name)s. El " "servidor NFS %(server)s está fuera de alcance." #, python-format msgid "" "Unable to deactivate NFS storage pool %(name)s. NFS server %(server)s is " "unreachable." msgstr "" "No se puede desactivar la agrupación de almacenamiento NFS %(name)s. El " "servidor NFS %(server)s está fuera de alcance." #, python-format msgid "" "Unable to deactivate pool %(name)s as it is associated with some templates" msgstr "" "No se puede desactivar la agrupación %(name)s ya que está asociada con " "algunas plantillas" #, python-format msgid "Unable to delete pool %(name)s as it is associated with some templates" msgstr "" "No se puede suprimir la agrupación %(name)s ya que está asociada con algunas " "plantillas" #, python-format msgid "" "A volume group named '%(name)s' already exists. Please, choose another name " "to create the logical pool." msgstr "" "Un grupo de volúmenes denominado '%(name)s' ya existe. Elija otro nombre " "para crear la agrupación lógica." #, python-format msgid "Unable to update database with deep scan information due error: %(err)s" msgstr "" "No se puede actualizar la base de datos con la información de exploración " "profunda debido a un error: %(err)s" #, python-format msgid "Storage volume %(name)s already exists" msgstr "El volumen de almacenamiento %(name)s ya existe" #, python-format msgid "Storage volume %(name)s does not exist in storage pool %(pool)s" msgstr "" "El volumen de almacenamiento %(name)s no existe en la agrupación de " "almacenamiento %(pool)s" #, python-format msgid "" "Unable to create storage volume %(volume)s because storage pool %(pool)s is " "not active" msgstr "" #, python-format msgid "Specify %(item)s in order to create storage volume %(volume)s" msgstr "" "Especifique %(item)s para poder crear el volumen de almacenamiento %(volume)s" #, python-format msgid "" "Unable to list storage volumes because storage pool %(pool)s is not active" msgstr "" "No se pueden listar los volúmenes de almacenamiento porque la agrupación de " "almacenamiento %(pool)s no está activa" #, python-format msgid "" "Unable to create storage volume %(name)s in storage pool %(pool)s. Details: " "%(err)s" msgstr "" "No se puede crear el volumen de almacenamiento %(name)s en la agrupación de " "almacenamiento %(pool)s. Detalles: %(err)s" #, python-format msgid "" "Unable to list storage volumes in storage pool %(pool)s. Details: %(err)s" msgstr "" "No se pueden listar volúmenes de almacenamiento en la agrupación de " "almacenamiento %(pool)s. Detalles: %(err)s" #, python-format msgid "Unable to wipe storage volumes %(name)s. Details: %(err)s" msgstr "" "No se pueden borrar los volúmenes de almacenamiento %(name)s. Detalles: " "%(err)s" #, python-format msgid "Unable to delete storage volume %(name)s. Details: %(err)s" msgstr "" "No se puede suprimir el volumen de almacenamiento %(name)s. Detalles: %(err)s" #, python-format msgid "Unable to resize storage volume %(name)s. Details: %(err)s" msgstr "" "No se puede redimensionar el volumen de almacenamiento %(name)s. Detalles: " "%(err)s" #, python-format msgid "Storage type %(type)s does not support volume create and delete" msgstr "" "El tipo de almacenamiento %(type)s no da soporte a crear y suprimir volúmenes" msgid "Storage volume name must be a string" msgstr "El nombre de volumen de almacenamiento debe ser una serie" msgid "Storage volume allocation must be an integer number" msgstr "La asignación de volumen de almacenamiento debe ser un número entero" msgid "" "Storage volume format not supported. Valid formats: bochs, cloop, cow, dmg, " "qcow, qcow2, qed, raw, vmdk, vpc." msgstr "" msgid "Storage volume requires a volume name" msgstr "El volumen de almacenamiento requiere un nombre de volumen" #, python-format msgid "" "Unable to update database with storage volume information due error: %(err)s" msgstr "" "No se puede actualizar la base de datos con la información de volumen de " "almacenamiento debido a un error: %(err)s" #, python-format msgid "Only one of parameter %(param)s can be specified" msgstr "" #, python-format msgid "Create volume from %(param)s is not supported" msgstr "" msgid "Storage volume capacity must be an integer number." msgstr "" msgid "Storage volume URL must be http://, https://, ftp:// or ftps://." msgstr "" #, python-format msgid "Unable to access file %(url)s. Please, check it." msgstr "" #, python-format msgid "" "Unable to clone storage volume '%(name)s' in pool '%(pool)s'. Details: " "%(err)s" msgstr "" msgid "Specify chunk data and its size to upload a file." msgstr "" msgid "In order to upload a storage volume, specify the 'upload' parameter." msgstr "" msgid "" "Unable to upload chunk data as it does not match with requested chunk size." msgstr "" #, python-format msgid "The storage volume %(vol)s is not under an upload process." msgstr "" msgid "The upload chunk data will exceed the storage volume size." msgstr "" #, python-format msgid "Unable to upload chunk data to storage volume. Details: %(err)s." msgstr "" #, python-format msgid "Interface %(name)s does not exist" msgstr "La interfaz %(name)s no existe" #, python-format msgid "Network %(name)s already exists" msgstr "La red %(name)s ya existe" #, python-format msgid "Network %(name)s does not exist" msgstr "La red %(name)s no existe" #, python-format msgid "Subnet %(subnet)s specified for network %(network)s is not valid." msgstr "" "La subred %(subnet)s especificada para la red %(network)s no es válida." #, python-format msgid "Specify a network interface to create bridged network %(name)s" msgstr "Especifique una interfaz de red para crear una red puenteada %(name)s" #, python-format msgid "Unable to delete active network %(name)s" msgstr "No se puede suprimir la red activa %(name)s" #, python-format msgid "Interface %(iface)s specified for network %(network)s is already in use" msgstr "" "La interfaz %(iface)s especificada para la red %(network)s ya está en uso" msgid "Interface should be bare NIC, bonding or bridge device." msgstr "La interfaz debe ser dispositivo de puente, enlazado o NIC simple." #, python-format msgid "Unable to create network %(name)s. Details: %(err)s" msgstr "No se puede crear la red %(name)s. Detalles: %(err)s" #, python-format msgid "Unable to find a free IP address for network '%(name)s'" msgstr "No se puede encontrar una dirección IP libre para la red '%(name)s'" #, python-format msgid "The interface %(iface)s already exists." msgstr "La interfaz %(iface)s ya existe" msgid "Network name must be a string without slashes (/) or quotes (\")" msgstr "" msgid "Supported network types are isolated, NAT and bridge" msgstr "Los tipos de red soportados son aislada, NAT y puente" msgid "Network subnet must be a string with IP address and prefix or netmask" msgstr "" "La subred de red debe ser una serie con dirección IP y prefijo o máscara de " "red" msgid "Network interface must be a string" msgstr "La interfaz de red debe ser una serie" msgid "Network VLAN ID must be an integer between 1 and 4094" msgstr "El ID de VLAN de red debe ser un entero entre 1 y 4094" msgid "Specify name and type to create a Network" msgstr "Especifique el nombre y el tipo para crear una red" #, python-format msgid "" "Unable to delete network %(name)s. There are some virtual machines %(vms)s " "and/or templates linked to this network." msgstr "" "No se puede suprimir la red %(name)s. Hay algunas máquinas virtuales %(vms)s " "y/o plantillas enlazadas a esta red." #, python-format msgid "" "Unable to deactivate network %(name)s. There are some virtual machines " "%(vms)s and/or templates linked to this network." msgstr "" "No se puede desactivar la red %(name)s. Hay algunas máquinas virtuales " "%(vms)s y/o plantillas enlazadas a esta red." #, python-format msgid "Bridge device %(name)s can not be the trunk device of a VLAN." msgstr "" "El dispositivo de puente %(name)s no puede ser el dispositivo de conexión " "troncal de una VLAN." #, python-format msgid "Failed to activate interface %(iface)s: %(err)s." msgstr "No se puede activar la interfaz %(iface)s: %(err)s." #, python-format msgid "" "Failed to activate interface %(iface)s. Please check the physical link " "status." msgstr "" "No se puede activar la interfaz %(iface)s. Compruebe el estado del enlace " "físico." #, python-format msgid "Failed to start network %(name)s. Details: %(err)s" msgstr "" #, python-format msgid "Debug report %(name)s does not exist" msgstr "El informe de depuración %(name)s no existe" msgid "Debug report tool not found in system" msgstr "Herramienta de informes de depuración no encontrada en el sistema" #, python-format msgid "Unable to create debug report %(name)s. Details: %(err)s." msgstr "" "No se puede crear el informe de depuración %(name)s. Detalles: %(err)s." #, python-format msgid "Can not find any debug report with the given name %(name)s" msgstr "" #, python-format msgid "Unable to generate debug report %(name)s. Details: %(err)s" msgstr "" "No se puede generar el informe de depuración %(name)s. Detalles: %(err)s" msgid "You should give a name for the debug report file." msgstr "" msgid "" "Debug report name must be a string. Only letters, digits, underscore ('_') " "and hyphen ('-') are allowed." msgstr "" #, python-format msgid "" "The debug report with specified name \"%(name)s\" already exists. Please use " "another one." msgstr "" "Un grupo de volúmenes denominado '%(name)s' ya existe. Elija otro nombre " "para crear la agrupación lógica." #, python-format msgid "Storage server %(server)s was not used by Kimchi" msgstr "Kimchi no utilizaba el servidor de almacenamiento %(server)s" #, python-format msgid "Distro '%(name)s' does not exist" msgstr "Distro '%(name)s' no existe" #, python-format msgid "Partition %(name)s does not exist in the host" msgstr "La partición %(name)s no existe en el host" msgid "Unable to shutdown host machine as there are running virtual machines" msgstr "" "No se puede concluir la máquina host ya que hay máquinas virtuales en " "ejecución" msgid "Unable to reboot host machine as there are running virtual machines" msgstr "" "No se puede rearrancar la máquina host ya que hay máquinas virtuales en " "ejecución" #, python-format msgid "Node device '%(name)s' not found" msgstr "No se ha encontrado el dispositivo de nodo '%(name)s'" msgid "Conflicting flag filters specified." msgstr "" msgid "No packages marked for update" msgstr "No hay paquetes marcados para su actualización" #, python-format msgid "Package %(name)s is not marked to be updated." msgstr "El paquete %(name)s no está marcado para su actualización." #, python-format msgid "Error while getting packages marked to be updated. Details: %(err)s" msgstr "" "Se ha producido un error al obtener paquetes marcados para su actualización. " "Detalles: %(err)s" msgid "There is no compatible package manager for this system." msgstr "No hay ningún gestor de paquetes compatible para este sistema." #, python-format msgid "Unable to find %(item)s in datastore" msgstr "No se puede encontrar %(item)s en el almacén de datos" #, python-format msgid "Invalid URI %(uri)s" msgstr "URI %(uri)s no válido" #, python-format msgid "Timeout while running command '%(cmd)s' after %(seconds)s seconds" msgstr "" "Tiempo de espera excedido al ejecutar el mandato '%(cmd)s' después de " "%(seconds)s segundos" msgid "Unable to choose a virtual machine name" msgstr "" #, python-format msgid "Invalid data value '%(value)s'" msgstr "" #, python-format msgid "Invalid data unit '%(unit)s'" msgstr "" msgid "Invalid storage type. Types supported: 'cdrom', 'disk'" msgstr "Tipo de almacenamiento no válido. Tipos soportados: 'cdrom'" #, python-format msgid "The path '%(value)s' is not a valid local/remote path for the device" msgstr "" msgid "Only CDROM path can be update." msgstr "" #, python-format msgid "" "The storage device %(dev_name)s does not exist in the virtual machine " "%(vm_name)s" msgstr "" #, python-format msgid "Error while creating new storage device: %(error)s" msgstr "" "Se ha producido un error al crear el nuevo dispositivo de almacenamiento: " "%(error)s" #, python-format msgid "Error while updating storage device: %(error)s" msgstr "" "Se ha producido un error al actualizar el dispositivo de almacenamiento: " "%(error)s" #, python-format msgid "Error while removing storage device: %(error)s" msgstr "" "Se ha producido un error al eliminar el dispositivo de almacenamiento: " "%(error)s" msgid "Do not support IDE device hot plug" msgstr "" msgid "" "Specify type and path or type and pool/volume to add a new virtual machine " "disk" msgstr "" "Especifique el tipo y la vía de acceso para añadir un disco de máquina " "virtual nuevo" msgid "Specify path to update virtual machine disk" msgstr "" "Especifique la vía de acceso para actualizar el disco de máquina virtual" #, python-format msgid "Controller type %(type)s limitation of %(limit)s devices reached" msgstr "" #, python-format msgid "Cannot retrieve disk path information for given pool/volume: %(error)s" msgstr "" msgid "Volume already in use by other virtual machine." msgstr "" msgid "" "Only one of path or pool/volume can be specified to add a new virtual " "machine disk" msgstr "" "Especifique el tipo y la vía de acceso para añadir un disco de máquina " "virtual nuevo" #, python-format msgid "" "Volume chosen with format %(format)s does not fit in the storage type " "%(type)s" msgstr "" msgid "YUM Repository ID must be one word only string." msgstr "El ID de repositorio YUM debe ser una serie de una sola palabra." msgid "Repository URL must be an http://, ftp:// or file:// URL." msgstr "El URL de repositorio debe ser http://, ftp:// o archivo:// URL." msgid "" "Repository configuration is a dictionary with specific values according to " "repository type." msgstr "" "La configuración de repositorio es un diccionario con valores específicos " "según el tipo de repositorio." msgid "Distribution to DEB repository must be a string" msgstr "El repositorio de Distribución a DEB debe ser una serie" msgid "Components to DEB repository must be listed in a array" msgstr "El repositorio de Componentes a DEB debe estar listado en una matriz" msgid "Components to DEB repository must be a string" msgstr "El repositorio de Componentes a DEB debe ser una serie" msgid "Mirror list to repository must be a string" msgstr "" msgid "YUM Repository name must be string." msgstr "El nombre del repositorio YUM debe ser una serie." msgid "GPG check must be a boolean value." msgstr "La comprobación de GPG debe ser un valor booleano." msgid "GPG key must be a URL pointing to the ASCII-armored file." msgstr "La clave GPG debe ser un URL que apunta al archivo blindado por ASCII." #, python-format msgid "Could not update repository %(repo_id)s." msgstr "No se ha podido actualizar el repositorio %(repo_id)s." #, python-format msgid "Repository %(repo_id)s does not exist." msgstr "El repositorio %(repo_id)s no existe." msgid "" "Specify repository base URL, mirror list or metalink in order to create or " "update a YUM repository." msgstr "" msgid "Repository management tool was not recognized for your system." msgstr "" "La herramienta de gestión de repositorio no se ha reconocido para su sistema." #, python-format msgid "Repository %(repo_id)s is already enabled." msgstr "El repositorio %(repo_id)s ya está habilitado." #, python-format msgid "Repository %(repo_id)s is already disabled." msgstr "El repositorio %(repo_id)s ya está inhabilitado." #, python-format msgid "Could not remove repository %(repo_id)s." msgstr "No se ha podido eliminar el repositorio %(repo_id)s." #, python-format msgid "Could not write repository configuration file %(repo_file)s" msgstr "" "No se ha podido grabar el archivo de configuración del repositorio " "%(repo_file)s" msgid "Specify repository distribution in order to create a DEB repository." msgstr "" "Especifique la distribución del repositorio para crear un repositorio de DEB." #, python-format msgid "Could not enable repository %(repo_id)s." msgstr "No se ha podido habilitar el repositorio %(repo_id)s." #, python-format msgid "Could not disable repository %(repo_id)s." msgstr "No se ha podido inhabilitar el repositorio %(repo_id)s." msgid "YUM Repository ID already exists" msgstr "El ID de repositorio de YUM ya existe" msgid "YUM Repository name must be a string" msgstr "El nombre del repositorio de YUM debe ser una serie" #, python-format msgid "Unable to list repositories. Details: '%(err)s'" msgstr "No se pueden listar repositorios. Detalles: '%(err)s'" #, python-format msgid "Unable to retrieve repository information. Details: '%(err)s'" msgstr "No se puede recuperar información del repositorio. Detalles: '%(err)s'" #, python-format msgid "Unable to add repository. Details: '%(err)s'" msgstr "No se puede añadir el repositorio. Detalles: '%(err)s'" #, python-format msgid "Unable to remove repository. Details: '%(err)s'" msgstr "No se puede eliminar el repositorio. Detalles: '%(err)s'" #, python-format msgid "" "Configuration items: '%(items)s' are not supported by repository manager" msgstr "" msgid "Repository metalink must be an http://, ftp:// or file:// URL." msgstr "" msgid "Cannot specify mirrorlist and metalink at the same time." msgstr "" #, python-format msgid "" "Virtual machine '%(vm)s' must be stopped before creating a snapshot of it." msgstr "" #, python-format msgid "" "Unable to create snapshot '%(name)s' on virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "Snapshot '%(name)s' does not exist on virtual machine '%(vm)s'." msgstr "" #, python-format msgid "" "Unable to retrieve snapshot '%(name)s' on virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "Unable to list snapshots on virtual machine '%(vm)s'. Details: %(err)s" msgstr "" #, python-format msgid "" "Unable to delete snapshot '%(name)s' on virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "" "Unable to retrieve current snapshot of virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "" "Unable to revert virtual machine '%(vm)s' to snapshot '%(name)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "" "Unable to create snapshot of virtual machine '%(vm)s' because it contains a " "disk with format '%(format)s'; only 'qcow2' is supported." msgstr "" msgid "The number of vCPUs is too large for this system." msgstr "" msgid "Invalid vCPU/topology combination." msgstr "" msgid "This host (or current configuration) does not allow CPU topology." msgstr "" msgid "ERROR CODE" msgstr "CÓDIGO DE ERROR" msgid "REASON" msgstr "RAZÓN" msgid "STACK" msgstr "PILA" msgid "Go to Homepage" msgstr "Ir a la página inicial" msgid "Create a New Virtual Machine" msgstr "Crear una nueva máquina virtual" msgid "Virtual Machine Name" msgstr "Nombre de máquina virtual" msgid "" "The name used to identify the virtual machine. If omitted, a name will be " "chosen based on the template used." msgstr "" "El nombre que se utiliza para identificar la máquina virtual. Si se omite, " "se elegirá un nombre basándose en la plantilla utilizada." msgid "Template" msgstr "Plantilla" msgid "Please create a template first." msgstr "Cree una plantilla primero." msgid "Create a Template" msgstr "Crear una plantilla" msgid "Please choose a template." msgstr "Elija una plantilla." msgid "OS" msgstr "SO" msgid "OS Version" msgstr "Versión del SO" msgid "CPUS" msgstr "CPUS" msgid "Memory" msgstr "Memoria" msgid "Create" msgstr "Crear" msgid "Creating..." msgstr "" msgid "Edit Guest" msgstr "Editar invitado" msgid "General" msgstr "General" msgid "Storage" msgstr "Almacenamiento" msgid "Interface" msgstr "Interfaz" msgid "Permission" msgstr "Versión" msgid "Host PCI Device" msgstr "" msgid "Snapshot" msgstr "" msgid "Name" msgstr "Nombre" msgid "CPUs" msgstr "CPUs" msgid "Memory (MB)" msgstr "Memoria" msgid "Icon" msgstr "Icono" msgid "Device" msgstr "Nombre de dispositivo" msgid "Path" msgstr "Vía de acceso NFS" msgid "Network" msgstr "Red" msgid "Type" msgstr "Tipo" msgid "MAC Address" msgstr "" msgid "Available system users and groups" msgstr "" msgid "Selected system users and groups" msgstr "" msgid "User" msgstr "" msgid "All" msgstr "Todo" msgid "To Add" msgstr "" msgid "Added" msgstr "" msgid "filter" msgstr "" msgid "Product" msgstr "" msgid "Vendor" msgstr "Proveedor" msgid "Created" msgstr "" msgid "Save" msgstr "Guardar" msgid "Replace" msgstr "Sustituir" msgid "Detach" msgstr "Desconectar" msgid "Cancel" msgstr "Cancelar" msgid "revert" msgstr "" msgid "Add a Storage Device to VM" msgstr "Añadir un dispositivo de almacenamiento a VM" msgid "Device Type" msgstr "Tipo de dispositivo" msgid "The device type. Currently, \"cdrom\" and \"disk\" are supported." msgstr "El tipo de dispositivo. Actualmente sólo está soportado \"cdrom\"." msgid "Storage Pool" msgstr "Agrupación de almacenamiento" msgid "Storage pool which volume located in" msgstr "La vía de acceso de la agrupación de almacenamiento debe ser una serie" msgid "Storage Volume" msgstr "Nombre de agrupación de almacenamiento" msgid "Storage volume to be attached" msgstr "El nombre de volumen de almacenamiento debe ser una serie" msgid "File Path" msgstr "Vía de acceso de archivo" msgid "The ISO file path in the server for CDROM." msgstr "La vía de acceso del archivo ISO en el servidor para el CDROM." msgid "Attach" msgstr "Conectar" msgid "Start" msgstr "Iniciar" msgid "Reset" msgstr "Restablecer" msgid "Pause" msgstr "" msgid "Resume" msgstr "" msgid "Power Off" msgstr "" msgid "Actions" msgstr "Acciones" msgid "Connect" msgstr "Conectar" msgid "Clone" msgstr "" msgid "Edit" msgstr "Editar" msgid "Shut Down" msgstr "Concluir" msgid "Delete" msgstr "Suprimir" msgid "The username or password you entered is incorrect. Please try again." msgstr "" "El nombre de usuario o contraseña que ha especificado es incorrecto. Por " "favor, vuelva a intentarlo." msgid "This field is required." msgstr "Este campo es obligatorio." msgid "Log in" msgstr "Iniciar sesión" msgid "Logging in..." msgstr "Iniciando sesión..." msgid "Host" msgstr "Host" msgid "Guests" msgstr "Invitados" msgid "Templates" msgstr "Plantillas" msgid "Failed to get application configuration" msgstr "No se ha podido obtener la configuración de la aplicación" msgid "This is not a valid Linux path" msgstr "No es una vía de acceso de Linux válida" msgid "This is not a valid URL." msgstr "No es un URL válido." msgid "No such data available." msgstr "No hay datos de ese tipo disponibles." msgid "" "Can not contact the host system. Verify the host system is up and that you " "have network connectivity to it. HTTP request response %1. " msgstr "" "No se puede contactar con el sistema host, Verifique que el sistema host " "está activo y que tiene conectividad de red con él. Respuesta de solicitud " "HTTP %1. " msgid "Unable to read file." msgstr "" msgid "Error while uploading file." msgstr "" msgid "Delete Confirmation" msgstr "Confirmación de supresión" msgid "OK" msgstr "Aceptar" msgid "Confirm" msgstr "Confirmar" msgid "Warning" msgstr "Aviso" msgid "Cloning..." msgstr "" msgid "Loading..." msgstr "Cargando..." msgid "An error occurred while retrieving system information." msgstr "" msgid "Retry" msgstr "Reintentar" msgid "Detailed message:" msgstr "Mensaje detallado:" msgid "No ISO found" msgstr "" msgid "This is not a valid ISO file." msgstr "No es un archivo ISO válido." msgid "This may take a long time. Do you want to continue?" msgstr "Tardará mucho tiempo. ¿Desea continuar?" msgid "This will permanently delete the template. Would you like to continue?" msgstr "Esto suprimirá permanentemente la plantilla. ¿Desea continuar?" msgid "Unable to shut down system as there are some virtual machines running!" msgstr "" "No se puede concluir el sistema ya que hay algunas máquinas virtuales en " "ejecución." msgid "Max:" msgstr "Máx.:" msgid "Utilization" msgstr "Utilización" msgid "Available" msgstr "Disponible" msgid "Read Rate" msgstr "Velocidad de lectura" msgid "Write Rate" msgstr "Velocidad de escritura" msgid "Received" msgstr "Recibido" msgid "Sent" msgstr "Enviado" msgid "" "Shutting down or restarting host will cause unsaved work lost. Continue to " "shut down/restarting?" msgstr "" "Concluir o reiniciar el host hará que se pierda el trabajo no guardado. " "¿Desea continuar para concluir/reiniciar?" msgid "" "Repository will be removed permanently and can't be recovered. Do you want " "to continue?" msgstr "" "El repositorio se eliminará de forma permanente y no se puede recuperar. " "¿Desea continuar?" msgid "Repositories" msgstr "Repositorios" msgid "ID" msgstr "ID" msgid "Base URL" msgstr "URL base" msgid "Is Mirror" msgstr "Es duplicado" msgid "URL Args" msgstr "Args de URL" msgid "Enabled" msgstr "Habilitado" msgid "GPG Check" msgstr "Comprobación GPG" msgid "GPG Key" msgstr "Clave GPG" msgid "Add" msgstr "Añadir" msgid "Remove" msgstr "Eliminar" msgid "Enable" msgstr "Habilitar" msgid "Disable" msgstr "Inhabilitar" msgid "Software Updates" msgstr "Actualizaciones de software" msgid "Package Name" msgstr "Nombre de paquete" msgid "Version" msgstr "Versión" msgid "Architecture" msgstr "Arquitectura" msgid "Repository" msgstr "Repositorio" msgid "Update All" msgstr "Actualizar todo" msgid "Updating..." msgstr "Actualizando..." msgid "Failed to retrieve packages update information." msgstr "" msgid "Failed to update package(s)." msgstr "No se han podido actualizar paquetes." msgid "" "Debug report will be removed permanently and can't be recovered. Do you want " "to continue?" msgstr "" "El informe de depuración se eliminará permanentemente y no se puede " "recuperar. ¿Desea continuar?" msgid "Debug Reports" msgstr "Informes de depuración" msgid "Generated Time" msgstr "Tiempo generado" msgid "Generate" msgstr "Generar" msgid "Generating..." msgstr "Generando..." msgid "Rename" msgstr "Redenominar" msgid "Download" msgstr "Descargar" msgid "" "Report name should contain only letters, digits, underscore ('_') and/or " "hyphen ('-')." msgstr "" "El nombre de informe debe contener sólo letras, dígitos y/o guión ('-')." msgid "Pending..." msgstr "Cargando..." msgid "Report name is the same as the original one." msgstr "" msgid "" "This will delete the virtual machine and its virtual disks. This operation " "cannot be undone. Would you like to continue?" msgstr "" "Esto suprimirá la máquina virtual y sus discos virtuales. Esta operación no " "puede deshacerse. ¿Desea continuar?" msgid "Power off Confirmation" msgstr "Confirmación de supresión" msgid "" "This action may produce undesirable results, for example unflushed disk " "cache in the guest. Would you like to continue?" msgstr "" msgid "Reset Confirmation" msgstr "Confirmación de supresión" msgid "" "There is a risk of data loss caused by reset without the guest OS shutdown. " "Would you like to continue?" msgstr "" msgid "Shut Down Confirmation" msgstr "Confirmación de supresión" msgid "Note the guest OS may ignore this request. Would you like to continue?" msgstr "Esto suprimirá permanentemente la plantilla. ¿Desea continuar?" msgid "Virtual Machine delete Confirmation" msgstr "" msgid "" "This virtual machine is not persistent. Power Off will delete it. Continue?" msgstr "" msgid "" "When the target guest has SCSI or iSCSI volumes, they will be cloned on " "default storage pool. The same will happen when the target pool does not " "have enough space to clone the volumes. Do you want to continue?" msgstr "" msgid "" "This CDROM will be detached permanently and you can re-attach it. Continue " "to detach it?" msgstr "" "Este CDROM se desconectará de forma permanente pero puede volver a " "conectarlo. ¿Desea continuar para desconectarlo?" msgid "Attaching..." msgstr "Conectando..." msgid "Replacing..." msgstr "Sustituyendo..." msgid "Successfully attached!" msgstr "¡Conectado correctamente!" msgid "Successfully replaced!" msgstr "¡Sustituido correctamente!" msgid "Successfully detached!" msgstr "¡Desconectado correctamente!" msgid "" "This disk will be detached permanently and you can re-attach it. Continue to " "detach it?" msgstr "" msgid "interface:" msgstr "" msgid "address:" msgstr "" msgid "link_type:" msgstr "" msgid "block:" msgstr "" msgid "drive_type:" msgstr "" msgid "model:" msgstr "" msgid "Affected devices:" msgstr "" msgid "The VLAN id must be between 1 and 4094." msgstr "El ID de VLAN debe estar entre 1 y 4094." msgid "unavailable" msgstr "no disponible" msgid "" "This action will interrupt network connectivity for any virtual machine that " "depend on this network." msgstr "" "Esta acción interrumpirá la conectividad de red para cualquier máquina " "virtual que dependa de esta red." msgid "Create a network" msgstr "Crear una red" msgid "" "This network is not persistent. Instead of stop, this action will " "permanently delete it. Would you like to continue?" msgstr "" "Esta agrupación de almacenamiento no es persistente. En lugar de desactivar, " "esta acción la suprimirá permanentemente. ¿Desea continuar?" msgid "" "The bridged VLAN tag may not work well with NetworkManager enabled. You " "should consider disabling it." msgstr "" msgid "" "This will permanently delete the storage pool. Would you like to continue?" msgstr "" "Esto suprimirá permanentemente la agrupación de almacenamiento. ¿Desea " "continuar?" msgid "This storage pool is empty." msgstr "Esta agrupación de almacenamiento está vacía." msgid "" "It will format your disk and you will loose any data in there, are you sure " "to continue? " msgstr "" "Dará formato al disco y se perderán los datos que tenga en él. ¿Está seguro " "de que desea continuar? " msgid "SCSI Fibre Channel" msgstr "Canal de fibra de SCSI" msgid "No SCSI adapters found." msgstr "No se han encontrado adaptadores SCSI." msgid "Loading iSCSI targets..." msgstr "" msgid "No iSCSI found. Please input one." msgstr "" msgid "Failed to load iSCSI targets." msgstr "" msgid "The storage pool name can not be blank." msgstr "El nombre de la agrupación de almacenamiento no puede estar en blanco." msgid "The storage pool path can not be blank." msgstr "" "La vía de acceso de la agrupación de almacenamiento no puede estar en blanco." msgid "NFS server mount path can not be blank." msgstr "La vía de acceso de montaje del servidor NFS no puede estar en blanco." msgid "Invalid NFS mount path." msgstr "Vía de acceso de montaje de NFS no válida." msgid "No logical device selected." msgstr "No se ha seleccionado ningún dispositivo lógico." msgid "The iSCSI target can not be blank." msgstr "El destino iSCSI no puede estar en blanco." msgid "Server name can not be blank." msgstr "El nombre de servidor no puede estar en blanco." msgid "This is not a valid Server Name or IP. Please, modify it." msgstr "" msgid "Looking for available partitions ..." msgstr "Buscando particiones disponibles..." msgid "No available partitions found." msgstr "No se han encontrado particiones disponibles." msgid "" "This storage pool is not persistent. Instead of deactivate, this action will " "permanently delete it. Would you like to continue?" msgstr "" "Esta agrupación de almacenamiento no es persistente. En lugar de desactivar, " "esta acción la suprimirá permanentemente. ¿Desea continuar?" msgid "Unable to retrieve partitions information." msgstr "No se puede recuperar información del repositorio. Detalles: '%(err)s'" msgid "In progress..." msgstr "" msgid "Failed!" msgstr "" msgid "CDROM path needs to be a valid local/remote path and cannot be blank." msgstr "" msgid "Disk pool or volume cannot be blank." msgstr "El nombre de la agrupación de almacenamiento no puede estar en blanco." msgid "Peers" msgstr "" msgid "Searching" msgstr "" msgid "No peers found." msgstr "" msgid "Help" msgstr "Ayuda" msgid "About" msgstr "Acerca de" msgid "Log out" msgstr "Finalizar sesión" msgid "Version:" msgstr "Versión:" msgid "Session timeout, please re-login." msgstr "" msgid "User Name" msgstr "Nombre de usuario" msgid "Password" msgstr "Contraseña" msgid "Generate a New Debug Report" msgstr "Generar un Informe de depuración nuevo" msgid "Report Name" msgstr "Nombre de informe" msgid "" "The name used to identify the report. If omitted, a name will be chosen " "based on current time. Name can contain: letters, digits, underscore (\"_\") " "and hyphen (\"-\")." msgstr "" "El nombre que se utiliza para identificar el informe. Si se omite, se " "elegirá un nombre basándose en la hora actual. El nombre puede contener: " "letras, dígitos y guión (\"-\")." msgid "Rename a Debug Report" msgstr "Generar un Informe de depuración nuevo" msgid "" "The name used to identify the report. Name can contain: letters, digits and " "hyphen (\"-\")." msgstr "" "El nombre que se utiliza para identificar el informe. Si se omite, se " "elegirá un nombre basándose en la hora actual. El nombre puede contener: " "letras, dígitos y guión (\"-\")." msgid "Submit" msgstr "" msgid "Add a Repository" msgstr "Añadir un repositorio" msgid "Identifier" msgstr "Identificador" msgid "Single word, unique identifier for the repository." msgstr "Identificador exclusivo de una sola palabra para el repositorio." msgid "Textual name for the repository." msgstr "Nombre textual para el repositorio." msgid "URL" msgstr "URL" msgid "Required Field" msgstr "Campo obligatorio" msgid "URL to the repository. Supported protocols are http, ftp, and file." msgstr "URL al repositorio. Los protocolos soportados son http, ftp y archivo." msgid "Repository is a mirror" msgstr "El repositorio es un duplicado." msgid "Distribution" msgstr "Distribución" msgid "Distribution of the DEB repository." msgstr "Distribución del repositorio DEB." msgid "Components" msgstr "Componentes" msgid "List of components in DEB repository." msgstr "Lista de componentes en el repositorio DEB." msgid "Edit Repository" msgstr "Editar repositorio" msgid "Mirror List URL" msgstr "URL de lista duplicada" msgid "Yes" msgstr "Sí" msgid "No" msgstr "No" msgid "Add a Volume to Storage Pool" msgstr "" msgid "Fetch from remote URL" msgstr "" msgid "Enter the remote URL here." msgstr "" msgid "Upload a file" msgstr "" msgid "Choose the file you want to upload." msgstr "" msgid "Define a New Storage Pool" msgstr "Definir una agrupación de almacenamiento nueva" msgid "Storage Pool Name" msgstr "Nombre de agrupación de almacenamiento" msgid "" "The name used to identify the storage pools, and it should not be empty." msgstr "" "El nombre que se utiliza para identificar las agrupaciones de almacenamiento " "y no debe estar vacío." msgid "Storage Pool Type" msgstr "Tipo de agrupación de almacenamiento" msgid "Storage Path" msgstr "Vía de acceso de almacenamiento" msgid "" "The path of the Storage Pool. Each Storage Pool must have a unique path." msgstr "" "La vía de acceso de la agrupación de almacenamiento. Cada agrupación de " "almacenamiento debe tener una vía de acceso exclusiva." msgid "" "Kimchi will try to create the directory when it does not already exist in " "your system." msgstr "Kimchi intentará crear el directorio cuando no existe en el sistema." msgid "NFS Server IP" msgstr "IP de Servidor NFS" msgid "NFS server IP or hostname. It can be input or chosen from history." msgstr "" "IP o nombre de host de servidor NFS. Puede especificarse o elegirse del " "historial." msgid "NFS Path" msgstr "Vía de acceso NFS" msgid "The NFS exported path on NFS server." msgstr "La vía de acceso exportada de NFS en el servidor NFS." msgid "Device path" msgstr "Vía de acceso del dispositivo" msgid "iSCSI Server" msgstr "Servidor iSCSI" msgid "iSCSI server IP or hostname. It should not be empty." msgstr "IP o nombre de host de servidor iSCSI. No debe estar vacío." msgid "Server" msgstr "Servidor" msgid "Port" msgstr "Puerto" msgid "Target" msgstr "Destino" msgid "The iSCSI target on iSCSI server" msgstr "El destino iSCSI en el servidor iSCSI" msgid "Add iSCSI Authentication" msgstr "Añadir Autenticación iSCSI" msgid "iSCSI Authentication" msgstr "Autenticación iSCSI" msgid "SCSI Adapter" msgstr "Adaptador SCSI" msgid "Please, wait..." msgstr "Por favor, espere..." msgid "Add Template" msgstr "Añadir plantilla" msgid "Where is the source media for this template? " msgstr "¿Dónde está el soporte de origen para esta plantilla?" msgid "Local ISO Image" msgstr "Imagen ISO local" msgid "Local Image File" msgstr "" msgid "Remote ISO Image" msgstr "Imagen ISO remota" msgid "Search ISOs" msgstr "Buscar ISOs" msgid "The following ISOs are available:" msgstr "Las siguientes ISO están disponibles:" msgid "OS: " msgstr "SO: " msgid "Version: " msgstr "Versión: " msgid "Size: " msgstr "Tamaño: " msgid "Search more ISOs" msgstr "Buscar más ISO" msgid "Create Templates from Selected ISO" msgstr "Crear plantillas a partir de ISO seleccionadas" msgid "I want to use a specific ISO file" msgstr "Deseo utilizar un archivo ISO específico" msgid "Loading default remote ISOs ..." msgstr "Cargando ISO remotas predeterminadas ..." msgid "Arch: " msgstr "Arch: " msgid "I want to use a custom URL" msgstr "Deseo utilizar un URL personalizado" msgid "Edit Template" msgstr "Editar plantilla" msgid "Processor" msgstr "Procesador" msgid "CDROM" msgstr "CDROM" msgid "Image File" msgstr "" msgid "Graphics" msgstr "Gráficos" msgid "Disk(GB)" msgstr "" msgid "Disk Format" msgstr "" msgid "CPU Number" msgstr "Número de CPU" msgid "Manually set CPU topology" msgstr "" msgid "Cores" msgstr "" msgid "Threads" msgstr "" msgid "CPU" msgstr "CPU" msgid "Disk I/O" msgstr "E/S de disco" msgid "Network I/O" msgstr "E/S de red" msgid "Livetile" msgstr "Livetile" msgid "No guests found." msgstr "No se ha encontrado invitados." msgid "Shut down" msgstr "Concluir" msgid "Restart" msgstr "Reiniciar" msgid "Basic Information" msgstr "Información básica" msgid "OS Distro" msgstr "Distro de SO" msgid "OS Code Name" msgstr "Nombre de código de SO" msgid "CPU(s)" msgstr "" msgid "System Statistics" msgstr "Estadísticas del sistema" msgid "Update Progress" msgstr "Actualizar progreso" msgid "Network Name" msgstr "Nombre de red" msgid "State" msgstr "Estado" msgid "Network Type" msgstr "Tipo de red" msgid "Address Space" msgstr "Espacio de direcciones" msgid "Name should not contain '/' and '\"'." msgstr "" "Nombre de agrupación de almacenamiento no válido. No debe contener '/'." msgid "Isolated: no external network connection" msgstr "Aislado: no hay conexión de red física" msgid "NAT: outbound physical network connection only" msgstr "NAT: conexión de red física saliente solamente" msgid "Bridged: Virtual machines are connected to physical network directly" msgstr "" "Puenteado: Las máquinas virtuales están conectadas a la red física " "directamente" msgid "(No interfaces found)" msgstr "" msgid "Destination" msgstr "Destino:" msgid "Enable VLAN" msgstr "Habilitar VLAN:" msgid "VLAN ID" msgstr "ID de VLAN:" msgid "Stop" msgstr "Detener" msgid "%Used" msgstr "" msgid "Location" msgstr "Ubicación" msgid "Capacity" msgstr "Capacidad" msgid "Allocated" msgstr "Asignado" msgid "active" msgstr "activo" msgid "inactive" msgstr "inactivo" msgid "Deactivate" msgstr "Desactivar" msgid "Activate" msgstr "Activar" msgid "Add Volume" msgstr "" msgid "Extend" msgstr "" msgid "Undefine" msgstr "No definir" msgid "Format" msgstr "Formato:" msgid "Allocation" msgstr "Asignado:" msgid "No templates found." msgstr "No se han encontrado plantillas." kimchi-1.5.0/po/fr_FR.po000066400000000000000000001772551254252253000147560ustar00rootroot00000000000000# English translations for kimchi package. # Copyright (C) 2013 ORGANIZATION # msgid "" msgstr "" "Project-Id-Version: kimchi 0.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-06-24 09:39-0300\n" "PO-Revision-Date: 2014-08-27 21:30+0000\n" "Last-Translator: BobSynfig\n" "Language-Team: French (http://www.transifex.com/projects/p/kimchi/language/" "fr/)\n" "Language: fr_FR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: pygettext.py 1.5\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #, python-format msgid "Unknown parameter %(value)s" msgstr "Paramètre inconnu %(value)s" #, python-format msgid "Delete is not allowed for %(resource)s" msgstr "La suppression n'est pas autorisée pour %(resource)s" #, python-format msgid "%(resource)s does not implement update method" msgstr "%(resource)s n'implémente pas de méthode de mise à jour" #, python-format msgid "Create is not allowed for %(resource)s" msgstr "La création n'est pas autorisée pour %(resource)s" msgid "Unable to parse JSON request" msgstr "Impossible de parser la requête JSON" msgid "This API only supports JSON" msgstr "Cette API supporte uniquement le JSON" #, python-format msgid "Parameters does not match requirement in schema: %(err)s" msgstr "" "Les paramètres ne correspondent pas à ce qui est requis dans le schéma: " "%(err)s" msgid "You don't have permission to perform this operation." msgstr "Vous n'avez pas la permission d'effectuer cette opération." msgid "Datastore is not initiated in the model object." msgstr "Le magasin de données n'est pas initié dans l'objet modèle." #, python-format msgid "Unable to start task due error: %(err)s" msgstr "Impossible de démarrer la tâche à cause de l'erreur: %(err)s" #, python-format msgid "Timeout of %(seconds)s seconds expired while running task '%(task)s." msgstr "" #, python-format msgid "Authentication failed for user '%(username)s'. [Error code: %(code)s]" msgstr "" "L'authentification a échoué pour l'utilisateur '%(username)s'. [Code " "d'Erreur: %(code)s]" msgid "You are not authorized to access Kimchi" msgstr "Vous n'êtes pas autorisé à accéder à Kimchi" #, python-format msgid "Specify %(item)s to login into Kimchi" msgstr "Spécifiez %(item)s pour vous logguer dans Kimchi" #, python-format msgid "User %(user_id)s not found with given LDAP settings." msgstr "" #, python-format msgid "Invalid LDAP configuration: %(item)s : %(value)s" msgstr "" msgid "Unknown \"_cap\" specified" msgstr "\"_cap\" spécifiée inconnue" msgid "\"_passthrough\" should be \"true\" or \"false\"" msgstr "\"_passthrough\" doit être \"true\" ou \"false\"" msgid "\"_passthrough_affected_by\" should be a device name string" msgstr "\"_passthrough_affected_by\" doit être un nom de périphérique" #, python-format msgid "Error while getting block devices. Details: %(err)s" msgstr "Erreur durant l'accès aux périphériques de bloc. Détails: %(err)s" #, python-format msgid "Error while getting block device information for %(device)s." msgstr "" "Erreur durant l'obtention de l'information sur le périphérique de bloc " "%(device)s." #, python-format msgid "Unable to find distro file: %(filename)s" msgstr "Impossible de trouver le fichier de distro: %(filename)s" #, python-format msgid "" "Unable to parse distro file: %(filename)s. Make sure, it is a JSON file." msgstr "" "Impossible de parser le fichier de distro: %(filename)s. Veuillez vous " "assurer qu'il s'agit d'un fichier JSON." #, python-format msgid "Unable to login to iSCSI host target %(portal)s. Details: %(err)s" msgstr "" "Impossible de se connecter à l'hôte cible iSCSI %(portal)s. Détails: %(err)s " #, python-format msgid "Unable to login to iSCSI host %(host)s target %(target)s" msgstr "Impossible de se connecter à l'hôte iSCSI %(host)s cible %(target)s" #, python-format msgid "Unable to find ISO file %(filename)s" msgstr "Impossible de trouver le fichier ISO %(filename)s" #, python-format msgid "The ISO file %(filename)s is not bootable" msgstr "Le fichier ISO %(filename)s n'est pas bootable" #, python-format msgid "The ISO file %(filename)s does not have a valid El Torito boot record" msgstr "" "Le fichier ISO %(filename)s n'a pas d'enregistrement de boot El Torito valide" #, python-format msgid "Invalid El Torito validation entry in ISO %(filename)s" msgstr "Entrée de validation El Torito invalide dans l'ISO %(filename)s" #, python-format msgid "Invalid El Torito boot indicator in ISO %(filename)s" msgstr "Indicateur de boot El Torito invalide dans l'ISO %(filename)s" #, python-format msgid "Unexpected volume type for primary volume in ISO %(filename)s" msgstr "" "Type de volume inattendu pour le volume primaire dans l'ISO %(filename)s" #, python-format msgid "Bad format while reading volume descriptor in ISO %(filename)s" msgstr "" "Mauvais format durant la lecture du descripteur de volume dans l'ISO " "%(filename)s" #, python-format msgid "" "The hypervisor doesn't have permission to use this ISO %(filename)s. " "Consider moving it under /var/lib/libvirt, or set the search permission to " "file access control lists for '%(user)s' user if possible, or add the " "'%(user)s' to the ISO path group, or (not recommended) 'chmod -R o+x " "'path_to_iso'.Details: %(err)s" msgstr "" "L'hyperviseur n'a pas la permission d'utiliser cet ISO %(filename)s. " "Veuillez considérer de le déplacer sous /var/lib/libvirt,, ou de définir la " "permission de recherche sur les listes de contrpole d'accès fichier pour " "l'utilisateur '%(user)s' si possible, ou ajouter le '%(user)s' au groupe de " "chemins d'ISO, ou (non recommandé) 'chmod -R o+x 'chemin_vers_iso'.Détails: " "%(err)s" msgid "An error occurred when probing image OS information." msgstr "" "Une erreur est survenue lors de la détection de l'information d'OS de " "l'image." msgid "No OS information found in given image." msgstr "Aucune information d'OS trouvée sur l'image donnée." #, python-format msgid "Unable to read image file %(filename)s" msgstr "Impossible de lire le fichier image %(filename)s" #, python-format msgid "" "Image file must be an existing file on system. %(filename)s is not a valid " "input." msgstr "" "Le fichier image doit être un fichier existant sur le système. %(filename)s " "n'est pas une donnée valide." #, python-format msgid "Virtual machine %(name)s already exists" msgstr "La machine virtuelle %(name)s existe déjà" #, python-format msgid "Virtual machine %(name)s does not exist" msgstr "La machine virtuelle %(name)s n'existe pas" #, python-format msgid "" "Unable to rename virtual machine %(name)s. The name %(new_name)s is already " "in use or the virtual machine is not powered off." msgstr "" "Impossible de renommer la machine virtuelle %(name)s. Le nom %(new_name)s " "est déja utilisé ou la machine virtuelle n'est pas éteinte." #, python-format msgid "Unable to retrieve screenshot for stopped virtual machine %(name)s" msgstr "" "Impossible de récupérer une capture d'écran pour la machine virtuelle " "stoppée %(name)s" msgid "Remote ISO image is not supported by this server." msgstr "L'image ISO distante n'est pas supportée par le serveur." #, python-format msgid "Screenshot is not supported on virtual machine %(name)s" msgstr "Copie d'écran non supportée par la machine virtuelle %(name)s" #, python-format msgid "Unable to create virtual machine %(name)s. Details: %(err)s" msgstr "Impossible de créer la machine virtuelle %(name)s. Détails: %(err)s" #, python-format msgid "Unable to update virtual machine %(name)s. Details: %(err)s" msgstr "" "Impossible de mettre à jour la machine virtuelle %(name)s. Détails: %(err)s" #, python-format msgid "Unable to retrieve virtual machine %(name)s. Details: %(err)s" msgstr "" "Impossible de récupérer la machine virtuelle %(name)s. Détails: %(err)s" #, python-format msgid "Unable to connect to powered off virtual machine %(name)s." msgstr "Impossible de se connecter à la machine virtuelle éteinte %(name)s." msgid "Virtual machine name must be a string without slashes (/)" msgstr "" #, python-format msgid "Invalid template URI %(value)s specified for virtual machine" msgstr "" #, python-format msgid "Invalid storage pool URI %(value)s specified for virtual machine" msgstr "" msgid "Supported virtual machine graphics are Spice or VNC" msgstr "" msgid "Graphics address to listen on must be IPv4 or IPv6" msgstr "L'adresse d'écoute du graphics doit être IPv4 ou IPv6" msgid "Specify a template to create a virtual machine from" msgstr "Spécifier un modèle à partir duquel créer une machine virtuelle" #, python-format msgid "Unable to start virtual machine %(name)s. Details: %(err)s" msgstr "Impossible de démarrer la machine virtuelle %(name)s. Détails: %(err)s" #, python-format msgid "Unable to power off virtual machine %(name)s. Details: %(err)s" msgstr "" "Impossible de mettre hors tension la machine virtuelle %(name)s. Détails: " "%(err)s" #, python-format msgid "Unable to delete virtual machine %(name)s. Details: %(err)s" msgstr "" "Impossible de supprimer la machine virtuelle %(name)s. Détails: %(err)s" #, python-format msgid "Unable to reset virtual machine %(name)s. Details: %(err)s" msgstr "" "Impossible de réinitrialiser la machine virtuelle %(name)s. Détails: %(err)s" msgid "User name list must be an array" msgstr "" msgid "User name must be a string" msgstr "Le nom d'utilisateur doit être une chaîne de caractères" msgid "Group name list must be an array" msgstr "" msgid "Group name must be a string" msgstr "Le nom de groupe doit être une chaîne de caractères" #, python-format msgid "User(s) '%(users)s' do not exist" msgstr "Le(s) utilisateur(s) '%(users)s' n'existe(nt) pas" #, python-format msgid "Group(s) '%(groups)s' do not exist" msgstr "Le(s) groupe(s) '%(groups)s' n'existe(nt) pas" #, python-format msgid "Unable to shutdown virtual machine %(name)s. Details: %(err)s" msgstr "Impossible d'éteindre la machine virtuelle %(name)s. Détails: %(err)s" #, python-format msgid "" "Unable to get access metadata of virtual machine %(name)s. Details: %(err)s" msgstr "" "Impossible d'accéder aux metadata de la machine virtuelle %(name)s. Détails: " "%(err)s" msgid "The guest console password must be a string." msgstr "Le mot de passe de console invitée doit être une chaîne de caractères." msgid "The life time for the guest console password must be a number." msgstr "La durée de vie du mot de passe de console invitée doit être un nombre" #, python-format msgid "Virtual machine '%(name)s' must be stopped before cloning it." msgstr "" #, python-format msgid "Insufficient disk space to clone virtual machine '%(name)s'" msgstr "" #, python-format msgid "Unable to clone VM '%(name)s'. Details: %(err)s" msgstr "" #, python-format msgid "Invalid operation for non-persistent virtual machine %(name)s" msgstr "" #, python-format msgid "Cannot suspend VM '%(name)s' because it is not running." msgstr "" #, python-format msgid "Unable to suspend VM '%(name)s'. Details: %(err)s" msgstr "" #, python-format msgid "Cannot resume VM '%(name)s' because it is not paused." msgstr "" #, python-format msgid "Unable to resume VM '%(name)s'. Details: %(err)s" msgstr "" msgid "Memory assigned is higher then the maximum allowed in the host." msgstr "" #, python-format msgid "" "VM '%(name)s' does not support live memory update. Update the memory with " "the machine offline to enable this feature." msgstr "" msgid "Only increase memory is allowed in active VMs" msgstr "" msgid "" "For live memory update, new memory value must be equal old memory value plus " "multiples of 1024 Mib" msgstr "" msgid "There are not enough free slots of 1024 Mib in the guest." msgstr "" msgid "" "Host's libvirt version does not support memory devices. Libvirt must be >= " "1.2.14" msgstr "" #, python-format msgid "Error attaching memory device. Details: %(error)s" msgstr "" #, python-format msgid "" "VM %(vmid)s does not contain directly assigned host device %(dev_name)s." msgstr "" "La machine virtuelle %(vmid)s ne peut pas contenir le périphérique hôte " "directement assigné %(dev_name)s." #, python-format msgid "The host device %(dev_name)s is not allowed to directly assign to VM." msgstr "" "The périphérique hôte %(dev_name)s ne peut être directement assigné à la " "machine virtuelle" msgid "" "No IOMMU groups found. Host PCI pass through needs IOMMU group to function " "correctly. Please enable Intel VT-d or AMD IOMMU in your BIOS, then verify " "the Kernel is compiled with IOMMU support. For Intel CPU, add intel_iommu=on " "to your Kernel parameter in /boot/grub2/grub.conf. For AMD CPU, add iommu=pt " "iommu=1." msgstr "" msgid "\"name\" should be a device name string" msgstr "\"name\" doit être un nom de périphérique" #, python-format msgid "" "The device %(name)s is probably in use by the host. Unable to attach it to " "the guest." msgstr "" #, python-format msgid "Interface %(iface)s does not exist in virtual machine %(name)s" msgstr "L'interface %(iface)s n'existe pas dans la machine virtuelle %(name)s" #, python-format msgid "" "Network %(network)s specified for virtual machine %(name)s does not exist" msgstr "" "Le réseau %(network)s spécifié pour la machine virtuelle %(name)s n'existe " "pas" msgid "Supported virtual machine interfaces type is only network" msgstr "" "Le type d'interface de machine virtuelle supporté est réseau uniquement" msgid "Network name for virtual machine interface must be a string" msgstr "" "Le nom de réseau pour l'interface de la machine virtuelle doit être une " "chaîne de caractères" msgid "Invalid network model card specified for virtual machine interface" msgstr "" "Modèle de carte réseau spécifié invalide pour l'interface de machine " "virtuelle" msgid "Specify type and network to add a new virtual machine interface" msgstr "" "Spécifier le type et le réseau à ajouter à la nouvelle interface de la " "machine virtuelle" msgid "MAC Address must respect this format FF:FF:FF:FF:FF:FF" msgstr "" #, python-format msgid "MAC Address %(mac)s already exists in virtual machine %(name)s" msgstr "" msgid "Invalid MAC Address" msgstr "" msgid "Cannot change MAC address of a running virtual machine" msgstr "" #, python-format msgid "Template %(name)s already exists" msgstr "Le modèle %(name)s existe déjà" #, python-format msgid "" "Network '%(network)s' specified for template %(template)s does not exist" msgstr "" "Le réseau '%(network)s' spécifié pour le modèle %(template)s n'existe pas" #, python-format msgid "" "Storage pool %(pool)s specified for template %(template)s does not exist" msgstr "" "Le pool de stockage spécifié %(pool)s pour le modèle %(template)s n'existe " "pas" #, python-format msgid "Storage pool %(pool)s specified for template %(template)s is not active" msgstr "" "Le pool de stockage spécifié %(pool)s pour le modèle %(template)s n'est pas " "actif" #, python-format msgid "Invalid parameter '%(param)s' specified for CDROM." msgstr "Paramètres '%(param)s' spécifié invalide pour le CDROM" #, python-format msgid "Network %(network)s specified for template %(template)s is not active" msgstr "" "Le réseau %(network)s spécifié pour le modèle %(template)s n'est pas actif" msgid "Template name must be a string" msgstr "Le modèle de nom doit être une chaîne de caractères" msgid "Template icon must be a path to the image" msgstr "Le modèle d'icone doit être un chemin vers l'image" msgid "Template distribution must be a string" msgstr "Le modèle de distribution doit être une chaîne de caractères" msgid "Template distribution version must be a string" msgstr "" "Le modèle de version de distribution doit être une chaîne de caractères" msgid "The number of CPUs must be an integer greater than 0" msgstr "Le nombre de CPU doit être un nombre entier supérieur à 0" msgid "Amount of memory (MB) must be an integer greater than 512" msgstr "La quantité de mémoire (Mo) doit être un nombre entier supérieur à 512" msgid "Template CDROM must be a local or remote ISO file" msgstr "Le CDROM modèle doit être un fichier ISO local ou distant" #, python-format msgid "Invalid storage pool URI %(value)s specified for template" msgstr "URI %(value)s du pool de stockage spécifiée invalide pour le modèle" msgid "Specify an ISO image as CDROM or a base image to create a template" msgstr "" "Spécifiez une image ISO comme CDROM ou une image de base pour créer un modèle" msgid "All networks for the template must be specified in a list." msgstr "Tous les réseaux pour le modèle doivent être spécifiés dans une liste" msgid "Specify a volume to a template when storage pool is iSCSI or SCSI" msgstr "" #, python-format msgid "The volume %(volume)s is not in storage pool %(pool)s" msgstr "Le volume %(volume)s n'est pas dans le pool de stockage %(pool)s" #, python-format msgid "Unable to create template due error: %(err)s" msgstr "Impossible de créer le modèle à cause de l'erreur: %(err)s" #, python-format msgid "Unable to delete template due error: %(err)s" msgstr "Impossilbe de supprimer le modèle à cause de l'erreur: %(err)s" msgid "Disk size must be an integer greater than 1GB." msgstr "La taille de disque doit être un entier supérieur à 1Go." msgid "Template base image must be a valid local image file" msgstr "L'image de base de modèle doit petre un fichier image local valide" #, python-format msgid "Cannot identify base image %(path)s format" msgstr "Ne peut identifier le format de l'image de base %(path)s" msgid "" "When specifying CPU topology, VCPUs must be a product of sockets, cores, and " "threads." msgstr "" msgid "" "When specifying CPU topology, each element must be an integer greater than " "zero." msgstr "" "Dans la topologie de CPU, chaque élément doit être un entier strictement " "positif." msgid "" "Invalid disk image format. Valid formats: bochs, cloop, cow, dmg, qcow, " "qcow2, qed, raw, vmdk, vpc." msgstr "" #, python-format msgid "Storage pool %(name)s already exists" msgstr "Le pool de stockage %(name)s existe déjà" #, python-format msgid "Storage pool %(name)s does not exist" msgstr "Le pool de stockage %(name)s n'existe pas" #, python-format msgid "Specify %(item)s in order to create the storage pool %(name)s" msgstr "Spécifier %(item)s afin de créer le pool de stockage %(name)s" #, python-format msgid "Unable to delete active storage pool %(name)s" msgstr "Impossible de supprimer le pool de stockage actif %(name)s" #, python-format msgid "Unable to list storage pools. Details: %(err)s" msgstr "Impossible de lister les pools de stockage. Détails: %(err)s" #, python-format msgid "Unable to create storage pool %(name)s. Details: %(err)s" msgstr "Impossilble de créer le pool de stockage %(name)s. Détails: %(err)s" #, python-format msgid "" "Unable to get number of storage volumes in storage pool %(name)s. Details: " "%(err)s" msgstr "" "Impossible d'obtenir le nombre de volumes de stockage dans le pool de " "stockage%(name)s. Détails: %(err)s" #, python-format msgid "Unable to activate storage pool %(name)s. Details: %(err)s" msgstr "Impossible d'activer le pool de stockage %(name)s. Détails: %(err)s" #, python-format msgid "Unable to deactivate storage pool %(name)s. Details: %(err)s" msgstr "" "Impossible de désactiver le pool de stockage %(name)s. Détails: %(err)s" #, python-format msgid "Unable to delete storage pool %(name)s. Details: %(err)s" msgstr "" "Impossible de supprimer le pool de stockage %(name)s. Détails: %(err)s " #, python-format msgid "" "Unable to create NFS Pool as export path %(path)s may block during mount" msgstr "" "Impossible de créer le Pool NFS du fait que le chemin d'export %(path)s " "pourrait se bloquer durant le montage" #, python-format msgid "Unable to create NFS Pool as export path %(path)s mount failed" msgstr "" "Impossible de créer le pool NFS du fait que le montage du chemin d'export " "%(path)s a échoué" #, python-format msgid "Unsupported storage pool type: %(type)s" msgstr "Type de pool de stockage non supporté: %(type)s" #, python-format msgid "Error while retrieving storage pool XML to %(pool)s" msgstr "" msgid "Storage pool name must be a string without slashes (/)" msgstr "" msgid "" "Supported storage pool types are dir, netfs, logical, iscsi, isci and kimchi-" "iso" msgstr "" "Les types de pool de stockage supportés sont: dir, netfs, logical, iscsi, " "isci et kimchi-iso" msgid "Storage pool path must be a string" msgstr "Le chemin du pool de stockage doit être une chaîne de caractères" msgid "Storage pool host must be a IP or hostname" msgstr "L'hôte du pool de stockage doit être une IP ou un nom d'hôte" msgid "Storage pool device must be the absolute path to the block device" msgstr "" msgid "Storage pool devices parameter must be a list" msgstr "Le paramètre de périphérique de pool de stockage doit être une list" msgid "Target IQN of an iSCSI pool must be a string" msgstr "La cible IQN d'un pool iSCSI doit être une chaîne de caractères" msgid "Port of a remote storage server must be an integer between 1 and 65535" msgstr "" "Le port d'un serveur de stockage distant doit être un nombre entier entre 1 " "et 65535" msgid "iSCSI target username must be a string" msgstr "" "Le nom d'utilisateur de la cible iSCSI doit être une chaîne de caractères" msgid "iSCSI target password must be a string" msgstr "Le mot de passe de la cible iSCSI doit être une chaîne de caractères" msgid "Specify name and type to create a storage pool" msgstr "Spécifier un nom et un type pour créer un pool de stockage" #, python-format msgid "" "%(disk)s is not a valid disk/partition. Could not add it to the pool " "%(pool)s." msgstr "" "%(disk)s n'est pas un(e) disque/partition valide. N'a pu l'ajouter au pool " "%(pool)s." #, python-format msgid "Unable to extend logical pool %(pool)s. Details: %(err)s" msgstr "Impossible d'agrandir le pool logique %(pool)s. Détails: %(err)s" msgid "The parameter disks only can be updated for logical storage pool." msgstr "" "Les disques en paramètre peuvent seulement être mis à jour pour un pool de " "stockage logique." msgid "The SCSI host adapter name must be a string." msgstr "Le nom d'adaptateur de l'hôte SCSI doit être une chapine de caractères" msgid "The storage pool kimchi_isos is reserved for internal use" msgstr "Le pool de stockage kimchi_isos est réservé à un usage interne" #, python-format msgid "" "Unable to activate NFS storage pool %(name)s. NFS server %(server)s is " "unreachable." msgstr "" "Impossible d'activer le pool de stockage NFS%(name)s. Le serveur NFS " "%(server)s n'est pas joignable." #, python-format msgid "" "Unable to deactivate NFS storage pool %(name)s. NFS server %(server)s is " "unreachable." msgstr "" "Impossible de désactiver le pool de stockage NFS%(name)s. Le serveur NFS " "%(server)s n'est pas joignable." #, python-format msgid "" "Unable to deactivate pool %(name)s as it is associated with some templates" msgstr "" "Impossible de désactiver le pool %(name)s du fait qu'il est associé à des " "modèles" #, python-format msgid "Unable to delete pool %(name)s as it is associated with some templates" msgstr "" "Impossible de supprimer le pool %(name)s du fait qu'il est associé à des " "modèles" #, python-format msgid "" "A volume group named '%(name)s' already exists. Please, choose another name " "to create the logical pool." msgstr "" "Un groupe de volume appelé '%(name)s' existe déjà. Veuillez choisir un autre " "nom pour créer le pool logique." #, python-format msgid "Unable to update database with deep scan information due error: %(err)s" msgstr "" "Impossible de mettre à jour la base de données avec les informations de scan " "profond à cause de l'erreur: %(err)s" #, python-format msgid "Storage volume %(name)s already exists" msgstr "Le volume de stockage %(name)s existe déjà" #, python-format msgid "Storage volume %(name)s does not exist in storage pool %(pool)s" msgstr "" "Le volume de stockage %(name)s n'existe pas dans le pool de stockage %(pool)s" #, python-format msgid "" "Unable to create storage volume %(volume)s because storage pool %(pool)s is " "not active" msgstr "" "Impossible de créer le volume de stockage %(volume)s car le pool de stockage " "%(pool)s n'est pas actif" #, python-format msgid "Specify %(item)s in order to create storage volume %(volume)s" msgstr "Spécifier %(item)s afin de créer le volume de stockage %(volume)s" #, python-format msgid "" "Unable to list storage volumes because storage pool %(pool)s is not active" msgstr "" "Impossible de lister les volumes de stockage car le pool de stockage " "%(pool)s n'est pas actif" #, python-format msgid "" "Unable to create storage volume %(name)s in storage pool %(pool)s. Details: " "%(err)s" msgstr "" "Impossible de créer le volume de stockage %(name)s dans le pool de stockage " "%(pool)s. Détails: %(err)s" #, python-format msgid "" "Unable to list storage volumes in storage pool %(pool)s. Details: %(err)s" msgstr "" "Impossible de lister les volumes de stockage dans le pool de stockage " "%(pool)s. Détails: %(err)s" #, python-format msgid "Unable to wipe storage volumes %(name)s. Details: %(err)s" msgstr "Impossible de wiper les volumes de stockage %(name)s. Détails: %(err)s" #, python-format msgid "Unable to delete storage volume %(name)s. Details: %(err)s" msgstr "" "Impossible de supprimer le volume de stockage %(name)s. Détails: %(err)s " #, python-format msgid "Unable to resize storage volume %(name)s. Details: %(err)s" msgstr "" "Impossible de redimensionner le volume de stockage %(name)s. Détails: %(err)s" #, python-format msgid "Storage type %(type)s does not support volume create and delete" msgstr "" "Le type de stockage %(type)s ne supporte pas ni la création ni la " "suppression de volume" msgid "Storage volume name must be a string" msgstr "Le nom de volume de stockage doit être une chaîne de caractères" msgid "Storage volume allocation must be an integer number" msgstr "L'allocation de volume de stockage doit être une nombre entier" msgid "" "Storage volume format not supported. Valid formats: bochs, cloop, cow, dmg, " "qcow, qcow2, qed, raw, vmdk, vpc." msgstr "" msgid "Storage volume requires a volume name" msgstr "Le volume de stockage requiert un nom de volume" #, python-format msgid "" "Unable to update database with storage volume information due error: %(err)s" msgstr "" "Impossible de mettre à jour la base de données avec les informations du " "volume de stockage à cause de l'erreur: %(err)s" #, python-format msgid "Only one of parameter %(param)s can be specified" msgstr "Seulement un seul des paramêtre %(param)s peut être spécifié" #, python-format msgid "Create volume from %(param)s is not supported" msgstr "La création de volume avec %(param)s n'est pas supportée" msgid "Storage volume capacity must be an integer number." msgstr "La capacité du volume de stockage doit être un nombre entier." msgid "Storage volume URL must be http://, https://, ftp:// or ftps://." msgstr "" "L'URL du volume de stockage doit être http://, https://, ftp:// ou ftps://." #, python-format msgid "Unable to access file %(url)s. Please, check it." msgstr "Impossible d'accéder au fichier %(url)s. Veuillez le vérifier." #, python-format msgid "" "Unable to clone storage volume '%(name)s' in pool '%(pool)s'. Details: " "%(err)s" msgstr "" msgid "Specify chunk data and its size to upload a file." msgstr "" msgid "In order to upload a storage volume, specify the 'upload' parameter." msgstr "" msgid "" "Unable to upload chunk data as it does not match with requested chunk size." msgstr "" #, python-format msgid "The storage volume %(vol)s is not under an upload process." msgstr "" msgid "The upload chunk data will exceed the storage volume size." msgstr "" #, python-format msgid "Unable to upload chunk data to storage volume. Details: %(err)s." msgstr "" #, python-format msgid "Interface %(name)s does not exist" msgstr "L'interface %(name)s n'existe pas" #, python-format msgid "Network %(name)s already exists" msgstr "Le réseau %(name)s existe déjà" #, python-format msgid "Network %(name)s does not exist" msgstr "Le réseau %(name)s n'existe pas" #, python-format msgid "Subnet %(subnet)s specified for network %(network)s is not valid." msgstr "" "Le sous-réseau %(subnet)s spécifié pour le réseau %(network)s n'est pas " "valide" #, python-format msgid "Specify a network interface to create bridged network %(name)s" msgstr "Spécifier une interface réseau pour créer le réseau bridge %(name)s" #, python-format msgid "Unable to delete active network %(name)s" msgstr "Impossible de supprimer le réseau actif %(name)s" #, python-format msgid "Interface %(iface)s specified for network %(network)s is already in use" msgstr "" "L'interface %(iface)s spécifiée pour le réseau %(network)s est déjà utilisée" msgid "Interface should be bare NIC, bonding or bridge device." msgstr "L'interface doit être un périphérique NIC vide, bonding ou bridgé." #, python-format msgid "Unable to create network %(name)s. Details: %(err)s" msgstr "Impossible de créer le réseau %(name)s. Détails: %(err)s" #, python-format msgid "Unable to find a free IP address for network '%(name)s'" msgstr "Impossible de trouver une adresse IP libre pour le réseau '%(name)s'" #, python-format msgid "The interface %(iface)s already exists." msgstr "L'interface %(iface)s existe déjà" msgid "Network name must be a string without slashes (/) or quotes (\")" msgstr "" msgid "Supported network types are isolated, NAT and bridge" msgstr "Les types de réseaux supportés sont isolated, NAT et bridge" msgid "Network subnet must be a string with IP address and prefix or netmask" msgstr "" "Le sous-réseau doit être une chaine de caractères avec une adresse IP et un " "préfixe ou un masque de réseau" msgid "Network interface must be a string" msgstr "L'interface de réseau doit être une chaîne de caractères" msgid "Network VLAN ID must be an integer between 1 and 4094" msgstr "L'ID de VLAN du réseau doit être un nombre entier entre 1 et 4094" msgid "Specify name and type to create a Network" msgstr "Spécifiez un nom et un type pour créer un réseau" #, python-format msgid "" "Unable to delete network %(name)s. There are some virtual machines %(vms)s " "and/or templates linked to this network." msgstr "" "Impossible de supprimer le réseau %(name)s. Il y a des machines virtuelles " "%(vms)s et/ou des modèles liés à ce réseau. " #, python-format msgid "" "Unable to deactivate network %(name)s. There are some virtual machines " "%(vms)s and/or templates linked to this network." msgstr "" "Impossible de désactiver réseau %(name)s. Il y a des machines virtuelles" "%(vms)s et/ou des modèles liés à ce réseau. " #, python-format msgid "Bridge device %(name)s can not be the trunk device of a VLAN." msgstr "" "Le périphérique bridge %(name)s ne peut être le périphérique tronc d'un VLAN." #, python-format msgid "Failed to activate interface %(iface)s: %(err)s." msgstr "Échec durant l'activation de l'interface %(iface)s: %(err)s." #, python-format msgid "" "Failed to activate interface %(iface)s. Please check the physical link " "status." msgstr "" "Échec durant l'activation de l'interface %(iface)s. Veuillez vérifier le " "statut du lien physique." #, python-format msgid "Failed to start network %(name)s. Details: %(err)s" msgstr "" #, python-format msgid "Debug report %(name)s does not exist" msgstr "Le rapport de déboggage %(name)s n'existe pas" msgid "Debug report tool not found in system" msgstr "L'outil de rapport de déboggage n'a pas été trouvé dans le système" #, python-format msgid "Unable to create debug report %(name)s. Details: %(err)s." msgstr "" "Impossible de créer le rapport de déboggage %(name)s. Détails: %(err)s." #, python-format msgid "Can not find any debug report with the given name %(name)s" msgstr "" "Impossible de trouver un rapport de déboggage avec le nom fourni %(name)s" #, python-format msgid "Unable to generate debug report %(name)s. Details: %(err)s" msgstr "" "Impossible de générer le rapport de déboggage %(name)s. Détails: %(err)s" msgid "You should give a name for the debug report file." msgstr "Vous devriez donner un nom au fichier de rapport de déboggage." msgid "" "Debug report name must be a string. Only letters, digits, underscore ('_') " "and hyphen ('-') are allowed." msgstr "" "Le nom du rapport de déboggage doit être une chaîne de caractères. Seulement " "les lettres, chiffres, blanc souligné ('_') et tirets ('-') sont acceptés." #, python-format msgid "" "The debug report with specified name \"%(name)s\" already exists. Please use " "another one." msgstr "" "Le rapport de déboggage avec le nom spécifié \"%(name)s\" existe déjà. " "Veuillez en utiliser un autre." #, python-format msgid "Storage server %(server)s was not used by Kimchi" msgstr "Le server de stockage %(server)s n'était pas utilisé par Kimchi" #, python-format msgid "Distro '%(name)s' does not exist" msgstr "La distro '%(name)s' n'existe pas" #, python-format msgid "Partition %(name)s does not exist in the host" msgstr "La partition %(name)s n'existe pas sur cet hôte" msgid "Unable to shutdown host machine as there are running virtual machines" msgstr "" "Impossible d'éteindre la machine hôte car des machines virtuelles en sont " "cours d'exécution" msgid "Unable to reboot host machine as there are running virtual machines" msgstr "" "Impossible de redémarrer la machine hôte car des machines virtuelles en sont " "cours d'exécution" #, python-format msgid "Node device '%(name)s' not found" msgstr "Périphérique de noeud '%(name)s' non trouvé" msgid "Conflicting flag filters specified." msgstr "Filtres incompatibles spécifiés." msgid "No packages marked for update" msgstr "Aucun paquet marqué pour mise à jour" #, python-format msgid "Package %(name)s is not marked to be updated." msgstr "Le paquet %(name)s n'est pas marqué pour mise à jour" #, python-format msgid "Error while getting packages marked to be updated. Details: %(err)s" msgstr "" "Erreur durant la récupération des paquets marqués pour la miseà jour. " "Détails: %(err)s" msgid "There is no compatible package manager for this system." msgstr "Il n'y a pas de gestionnaire de paquets compatible avec ce système." #, python-format msgid "Unable to find %(item)s in datastore" msgstr "Impossible de trouver %(item)s dans le magasin de données" #, python-format msgid "Invalid URI %(uri)s" msgstr "URI %(uri)s invalide" #, python-format msgid "Timeout while running command '%(cmd)s' after %(seconds)s seconds" msgstr "" "Timeout durant l'exécution de la commande '%(cmd)s' après %(seconds)s " "secondes" msgid "Unable to choose a virtual machine name" msgstr "Impossible de sélectionner un nom de machine virtuelle" #, python-format msgid "Invalid data value '%(value)s'" msgstr "" #, python-format msgid "Invalid data unit '%(unit)s'" msgstr "" msgid "Invalid storage type. Types supported: 'cdrom', 'disk'" msgstr "Type de stockage invalide. Les Types supportés sont: 'cdrom', 'disk'" #, python-format msgid "The path '%(value)s' is not a valid local/remote path for the device" msgstr "" msgid "Only CDROM path can be update." msgstr "Seulement le chemin d'un CDROM peut être modifié." #, python-format msgid "" "The storage device %(dev_name)s does not exist in the virtual machine " "%(vm_name)s" msgstr "" "Le périphérique de stockage %(dev_name)s n'existe pas dans la machine " "virtuelle %(vm_name)s" #, python-format msgid "Error while creating new storage device: %(error)s" msgstr "" "Erreur durant la création du nouveau périphérique de stockage: %(error)s" #, python-format msgid "Error while updating storage device: %(error)s" msgstr "Erreur durant la mise à jour du périphérique de stockage: %(error)s" #, python-format msgid "Error while removing storage device: %(error)s" msgstr "Erreur durant le retrait du périphérique de stockage: %(error)s" msgid "Do not support IDE device hot plug" msgstr "Ne pas supporter le branchement à chaud de périphérique IDE" msgid "" "Specify type and path or type and pool/volume to add a new virtual machine " "disk" msgstr "" "Spécifier le type et le chemin ou le type et le pool/volume pour ajouter un " "nouveau disque de machine virtuelle." msgid "Specify path to update virtual machine disk" msgstr "Spécifier un chemin pour mettre à jour le disque de machine virtuelle" #, python-format msgid "Controller type %(type)s limitation of %(limit)s devices reached" msgstr "" "La limitation de %(limit)s périphériques a été atteinte pour le contrôleur " "de type %(type)s " #, python-format msgid "Cannot retrieve disk path information for given pool/volume: %(error)s" msgstr "" msgid "Volume already in use by other virtual machine." msgstr "" msgid "" "Only one of path or pool/volume can be specified to add a new virtual " "machine disk" msgstr "" "Seul un chemin ou pool/volume peut être spécifié pour ajouter un nouveau " "disque de machine virtuelle" #, python-format msgid "" "Volume chosen with format %(format)s does not fit in the storage type " "%(type)s" msgstr "" "Le volume de format %(format)s sélectionné ne correspond pas au type de " "stockage %(type)s" msgid "YUM Repository ID must be one word only string." msgstr "" "L'ID du dépôt YUM doit être une chaîne de caractères ne comportant qu'un " "seul mot" msgid "Repository URL must be an http://, ftp:// or file:// URL." msgstr "L'URL du dépôt doit être une URL en http://, ftp:// ou file://." msgid "" "Repository configuration is a dictionary with specific values according to " "repository type." msgstr "" "La configuration du dépôt est un dictionaire avec des valeurs spécifiques en " "accord avec le type de dépôt." msgid "Distribution to DEB repository must be a string" msgstr "" "La distribution dans le nom de dépôt DEB doit être une chaîne de caractères" msgid "Components to DEB repository must be listed in a array" msgstr "Les composants dans le dépôt DEB doivent être listés dans un tableau" msgid "Components to DEB repository must be a string" msgstr "Les composants dans le dépôt DEB doivent être une chaîne de caractères" msgid "Mirror list to repository must be a string" msgstr "" msgid "YUM Repository name must be string." msgstr "Le nom du dépôt YUM doit être une chaîne de caractères" msgid "GPG check must be a boolean value." msgstr "La vérification GPG doit être une valeur booléenne." msgid "GPG key must be a URL pointing to the ASCII-armored file." msgstr "La clé GPG doit être une URL pointant vers un fichier ASCII non armé." #, python-format msgid "Could not update repository %(repo_id)s." msgstr "Ne peut mettre à jour le dépôt %(repo_id)s." #, python-format msgid "Repository %(repo_id)s does not exist." msgstr "Le dépôt %(repo_id)s n'existe pas." msgid "" "Specify repository base URL, mirror list or metalink in order to create or " "update a YUM repository." msgstr "" msgid "Repository management tool was not recognized for your system." msgstr "L'outil de gestion de dépôt n'a pas été reconnu pour votre système." #, python-format msgid "Repository %(repo_id)s is already enabled." msgstr "Le dépôt %(repo_id)s est déjà activé." #, python-format msgid "Repository %(repo_id)s is already disabled." msgstr "Le dépôt %(repo_id)s est déjà désactivé." #, python-format msgid "Could not remove repository %(repo_id)s." msgstr "Ne peut supprimer le dépôt %(repo_id)s. " #, python-format msgid "Could not write repository configuration file %(repo_file)s" msgstr "Ne peut écrire le fichier de configuration du dépôt %(repo_file)s" msgid "Specify repository distribution in order to create a DEB repository." msgstr "Spécifier la distribution du dépôt afin de créer un dépôt DEB." #, python-format msgid "Could not enable repository %(repo_id)s." msgstr "Ne peut activer le dépôt %(repo_id)s." #, python-format msgid "Could not disable repository %(repo_id)s." msgstr "Ne peut désactiver le dépôt %(repo_id)s." msgid "YUM Repository ID already exists" msgstr "L'ID du dépôt YUM existe déjà" msgid "YUM Repository name must be a string" msgstr "Le nom du dépôt YUM doit être une chaîne de caractères" #, python-format msgid "Unable to list repositories. Details: '%(err)s'" msgstr "Impossible de lister les dépôts. Détails: '%(err)s'" #, python-format msgid "Unable to retrieve repository information. Details: '%(err)s'" msgstr "Impossible de récupérer les informations du dépôt. Détails: '%(err)s'" #, python-format msgid "Unable to add repository. Details: '%(err)s'" msgstr "Impossible d'ajouter un dépôt. Détails: '%(err)s'" #, python-format msgid "Unable to remove repository. Details: '%(err)s'" msgstr "Impossible de supprimer un dépôt. Détails: '%(err)s'" #, python-format msgid "" "Configuration items: '%(items)s' are not supported by repository manager" msgstr "" "Éléments de configurations: %(items)s ne sont pas supportés par le " "gestionnaire de dépôt" msgid "Repository metalink must be an http://, ftp:// or file:// URL." msgstr "" msgid "Cannot specify mirrorlist and metalink at the same time." msgstr "" #, python-format msgid "" "Virtual machine '%(vm)s' must be stopped before creating a snapshot of it." msgstr "" #, python-format msgid "" "Unable to create snapshot '%(name)s' on virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "Snapshot '%(name)s' does not exist on virtual machine '%(vm)s'." msgstr "" #, python-format msgid "" "Unable to retrieve snapshot '%(name)s' on virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "Unable to list snapshots on virtual machine '%(vm)s'. Details: %(err)s" msgstr "" #, python-format msgid "" "Unable to delete snapshot '%(name)s' on virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "" "Unable to retrieve current snapshot of virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "" "Unable to revert virtual machine '%(vm)s' to snapshot '%(name)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "" "Unable to create snapshot of virtual machine '%(vm)s' because it contains a " "disk with format '%(format)s'; only 'qcow2' is supported." msgstr "" msgid "The number of vCPUs is too large for this system." msgstr "" msgid "Invalid vCPU/topology combination." msgstr "" msgid "This host (or current configuration) does not allow CPU topology." msgstr "" msgid "ERROR CODE" msgstr "ERROR CODE" msgid "REASON" msgstr "REASON" msgid "STACK" msgstr "STACK" msgid "Go to Homepage" msgstr "Aller à la page d'accueil" msgid "Create a New Virtual Machine" msgstr "Créer une nouvelle Machine Virtuelle" msgid "Virtual Machine Name" msgstr "Nom de Machine Virtuelle" msgid "" "The name used to identify the virtual machine. If omitted, a name will be " "chosen based on the template used." msgstr "" "Le nm est utilisé pour identifier une machine virtuelle. Si omis, un nom " "sera choisi en se basant sur le modèle utilisé." msgid "Template" msgstr "Modèle" msgid "Please create a template first." msgstr "Veuillez d'abord créer un modèle." msgid "Create a Template" msgstr "Créer un modèle" msgid "Please choose a template." msgstr "Veuillez choisir un modèle" msgid "OS" msgstr "OS" msgid "OS Version" msgstr "Version de l'OS" msgid "CPUS" msgstr "CPUS" msgid "Memory" msgstr "Mémoire" msgid "Create" msgstr "Créer" msgid "Creating..." msgstr "Création en cours..." msgid "Edit Guest" msgstr "Éditer l'Invité" msgid "General" msgstr "Général" msgid "Storage" msgstr "Stockage" msgid "Interface" msgstr "Interface" msgid "Permission" msgstr "Permission" msgid "Host PCI Device" msgstr "Périphérique PCI Hôte" msgid "Snapshot" msgstr "" msgid "Name" msgstr "Nom" msgid "CPUs" msgstr "CPUs" msgid "Memory (MB)" msgstr "Mémoire (Mo)" msgid "Icon" msgstr "Icone" msgid "Device" msgstr "Périphérique" msgid "Path" msgstr "Chemin" msgid "Network" msgstr "Réseau" msgid "Type" msgstr "Type" msgid "MAC Address" msgstr "" msgid "Available system users and groups" msgstr "Utilisateurs et groupes systèmes disponibles" msgid "Selected system users and groups" msgstr "Utilisateurs et groupes systèmes sélectionnés" msgid "User" msgstr "" msgid "All" msgstr "Tous" msgid "To Add" msgstr "À Ajouter" msgid "Added" msgstr "Ajouter" msgid "filter" msgstr "Filtre" msgid "Product" msgstr "Produit" msgid "Vendor" msgstr "Vendeur" msgid "Created" msgstr "" msgid "Save" msgstr "Enregistrer" msgid "Replace" msgstr "Remplacer" msgid "Detach" msgstr "Détacher" msgid "Cancel" msgstr "Annuler" msgid "revert" msgstr "" msgid "Add a Storage Device to VM" msgstr "Ajouter un Périphérique de Stockage à la VM" msgid "Device Type" msgstr "Type de Périphérique" msgid "The device type. Currently, \"cdrom\" and \"disk\" are supported." msgstr "" "Le type de périphérique. Actuellement, \"cdrom\" et \"disk\" sont supportés." msgid "Storage Pool" msgstr "Pool de Stockage" msgid "Storage pool which volume located in" msgstr "Pool de Stockage dans lequel le volume est situé" msgid "Storage Volume" msgstr "Volume de Stockage" msgid "Storage volume to be attached" msgstr "Le volume de stockage à attacher" msgid "File Path" msgstr "Chemin de Fichier" msgid "The ISO file path in the server for CDROM." msgstr "Le chemin de fichier ISO sur le serveur comme CDROM." msgid "Attach" msgstr "Attacher" msgid "Start" msgstr "Démarrer" msgid "Reset" msgstr "Réinitialiser" msgid "Pause" msgstr "" msgid "Resume" msgstr "" msgid "Power Off" msgstr "Mettre hors tension" msgid "Actions" msgstr "Actions" msgid "Connect" msgstr "Connecter" msgid "Clone" msgstr "Cloner" msgid "Edit" msgstr "Éditer" msgid "Shut Down" msgstr "Éteindre" msgid "Delete" msgstr "Supprimer" msgid "The username or password you entered is incorrect. Please try again." msgstr "" "Le nom d'utilisateur ou le mot de passe que vous avez entré est incorrect. " "Veuillez essayer à nouveau." msgid "This field is required." msgstr "Ce champ est requis." msgid "Log in" msgstr "Se connecter" msgid "Logging in..." msgstr "En cours de connexion..." msgid "Host" msgstr "Hôte" msgid "Guests" msgstr "Invités" msgid "Templates" msgstr "Modèles" msgid "Failed to get application configuration" msgstr "Échec lors de l'obtention de la configuration de l'application" msgid "This is not a valid Linux path" msgstr "Ce n'est pas un chemin Linux valide" msgid "This is not a valid URL." msgstr "Ce n'est pas une URL valide." msgid "No such data available." msgstr "De telles données ne sont pas disponibles." msgid "" "Can not contact the host system. Verify the host system is up and that you " "have network connectivity to it. HTTP request response %1. " msgstr "" "Ne peut contacter le système hôte. Vérifiez que le système hôte est allumé " "et que vous avez une connectivité réseau avec lui. Réponse de requête HTTP " "%1." msgid "Unable to read file." msgstr "" msgid "Error while uploading file." msgstr "" msgid "Delete Confirmation" msgstr "Confirmation de Suppression" msgid "OK" msgstr "OK" msgid "Confirm" msgstr "Confirmer" msgid "Warning" msgstr "Avertissement" msgid "Cloning..." msgstr "" msgid "Loading..." msgstr "Chargement en cours..." msgid "An error occurred while retrieving system information." msgstr "" msgid "Retry" msgstr "Essayer à nouveau" msgid "Detailed message:" msgstr "Message détaillé:" msgid "No ISO found" msgstr "Aucune ISO détectée" msgid "This is not a valid ISO file." msgstr "Ce n'est pas un fichier ISO valide." msgid "This may take a long time. Do you want to continue?" msgstr "Cela va prendre un long moment. Voulez-vous continuer ?" msgid "This will permanently delete the template. Would you like to continue?" msgstr "" "Cela va supprimer de manière permanent le modèle. Souhaites-vous continuer ?" msgid "Unable to shut down system as there are some virtual machines running!" msgstr "" "Impossible d'éteindre le système du fait que certaines machines virtuelles " "sont lancées !" msgid "Max:" msgstr "Max:" msgid "Utilization" msgstr "Utilisation" msgid "Available" msgstr "Disponible" msgid "Read Rate" msgstr "Taux en Lecture" msgid "Write Rate" msgstr "Taux en Écriture" msgid "Received" msgstr "Reçu" msgid "Sent" msgstr "Envoyé" msgid "" "Shutting down or restarting host will cause unsaved work lost. Continue to " "shut down/restarting?" msgstr "" "Éteindre ou redémarrer l'hôte causera la perte de tout travail non " "enregistré. Continuer à éteindre/redémarrer ?" msgid "" "Repository will be removed permanently and can't be recovered. Do you want " "to continue?" msgstr "" "Le dépôt sera retiré de façon permanente et ne pourra être rétabli. Voulez-" "vous continuer ?" msgid "Repositories" msgstr "Dépôts" msgid "ID" msgstr "ID" msgid "Base URL" msgstr "URL de base" msgid "Is Mirror" msgstr "Est un miroir" msgid "URL Args" msgstr "Arguments d'URL" msgid "Enabled" msgstr "Activé" msgid "GPG Check" msgstr "Vérification GPG" msgid "GPG Key" msgstr "Clé GPG" msgid "Add" msgstr "Ajouter" msgid "Remove" msgstr "Retirer" msgid "Enable" msgstr "Activer" msgid "Disable" msgstr "Désactiver" msgid "Software Updates" msgstr "Mises à jour Logiciel" msgid "Package Name" msgstr "Nom de paquet" msgid "Version" msgstr "Version" msgid "Architecture" msgstr "Architecture" msgid "Repository" msgstr "Dépôt" msgid "Update All" msgstr "Tout mettre à jour" msgid "Updating..." msgstr "En cours de mise à jour..." msgid "Failed to retrieve packages update information." msgstr "Échec de récupération des informations de mise-à-jour des paquets." msgid "Failed to update package(s)." msgstr "Échec durant la mise à jour du/des paquet(s)" msgid "" "Debug report will be removed permanently and can't be recovered. Do you want " "to continue?" msgstr "" "Le rapport de déboggage sera enlevé de façon permanente et ne pourra être " "rétabli. Voulez-vous continuer ?" msgid "Debug Reports" msgstr "Rapports de Déboggage" msgid "Generated Time" msgstr "Horodatage de génération" msgid "Generate" msgstr "Générer" msgid "Generating..." msgstr "En cours de génération..." msgid "Rename" msgstr "Renommer" msgid "Download" msgstr "Télécharger" msgid "" "Report name should contain only letters, digits, underscore ('_') and/or " "hyphen ('-')." msgstr "" "Le nom de rapport devrait contenir uniquement des lettres, nombres, " "soulignement ('_') et/ou tiret ('-')." msgid "Pending..." msgstr "En attente..." msgid "Report name is the same as the original one." msgstr "Le nom du rapport est le même que celui d'origine." msgid "" "This will delete the virtual machine and its virtual disks. This operation " "cannot be undone. Would you like to continue?" msgstr "" "Cela va supprimer la machine virtuelle et tous ses disques virtuels. Cette " "opération est irréversible. Voulez-vous continuer ?" msgid "Power off Confirmation" msgstr "Confirmation de mise hors tension" msgid "" "This action may produce undesirable results, for example unflushed disk " "cache in the guest. Would you like to continue?" msgstr "" "Cette action pourrait produire des résultats indésirables, par exemple un " "cache disque non flushé dans l'invité. Voulez-vous continuer ?" msgid "Reset Confirmation" msgstr "Confirmation de Réinitialisation" msgid "" "There is a risk of data loss caused by reset without the guest OS shutdown. " "Would you like to continue?" msgstr "" "Il y a un risque de perte de données causées par une réinitialisation sans " "extinction de l'OS invité. Voulez-vous continuer ?" msgid "Shut Down Confirmation" msgstr "Confirmation d'Extinction" msgid "Note the guest OS may ignore this request. Would you like to continue?" msgstr "" "Noter que l'OS invité pourrait ignorer cette requête. Voulez-vous continuer ?" msgid "Virtual Machine delete Confirmation" msgstr "Confirmation de suppression de Machine Virtuelle" msgid "" "This virtual machine is not persistent. Power Off will delete it. Continue?" msgstr "" msgid "" "When the target guest has SCSI or iSCSI volumes, they will be cloned on " "default storage pool. The same will happen when the target pool does not " "have enough space to clone the volumes. Do you want to continue?" msgstr "" msgid "" "This CDROM will be detached permanently and you can re-attach it. Continue " "to detach it?" msgstr "" "Ce CDROM sera détaché de façon permanente et vous pourrez le ré-attacher. " "Continuer le détachement ?" msgid "Attaching..." msgstr "En cours d'attachement..." msgid "Replacing..." msgstr "En cours de Remplacement..." msgid "Successfully attached!" msgstr "Attaché avec succès !" msgid "Successfully replaced!" msgstr "Remplacé avec succès !" msgid "Successfully detached!" msgstr "Détaché avec Succès !" msgid "" "This disk will be detached permanently and you can re-attach it. Continue to " "detach it?" msgstr "" "Ce disque sera définitivement détaché et peut être ré-attaché. Continuer à " "le détacher ?" msgid "interface:" msgstr "" msgid "address:" msgstr "" msgid "link_type:" msgstr "" msgid "block:" msgstr "" msgid "drive_type:" msgstr "" msgid "model:" msgstr "" msgid "Affected devices:" msgstr "" msgid "The VLAN id must be between 1 and 4094." msgstr "L'id du VLAN doit être entre 1 et 4094." msgid "unavailable" msgstr "non disponible" msgid "" "This action will interrupt network connectivity for any virtual machine that " "depend on this network." msgstr "" "Cette action va interrompre la connectivité réseau pour tout machine " "virtuelle qui dépend de ce réseau." msgid "Create a network" msgstr "Créer un réseau" msgid "" "This network is not persistent. Instead of stop, this action will " "permanently delete it. Would you like to continue?" msgstr "" "Ce réseau n'est pas persistant. Au lieu de s'arrêter, cette actionva le " "suppromer de manière permanente. Voulez-vous continuer ?" msgid "" "The bridged VLAN tag may not work well with NetworkManager enabled. You " "should consider disabling it." msgstr "" msgid "" "This will permanently delete the storage pool. Would you like to continue?" msgstr "" "Cela va effacer de manière permanente le pool de stockage. Voulez-vous " "continuer ?" msgid "This storage pool is empty." msgstr "Ce pool de stockage est vide." msgid "" "It will format your disk and you will loose any data in there, are you sure " "to continue? " msgstr "" "Cela va formater votre disque et vous allez perdre toutes les données qui " "s'y trouvent, êtes-vous sûr de continuer ?" msgid "SCSI Fibre Channel" msgstr "Canal Fibre SCSI" msgid "No SCSI adapters found." msgstr "Aucun adaptateur SCSI trouvé." msgid "Loading iSCSI targets..." msgstr "" msgid "No iSCSI found. Please input one." msgstr "" msgid "Failed to load iSCSI targets." msgstr "" msgid "The storage pool name can not be blank." msgstr "Le nom de pool de stockage ne peut être vierge." msgid "The storage pool path can not be blank." msgstr "Le chemin de pool de stockage ne peut être vierge." msgid "NFS server mount path can not be blank." msgstr "Le chemin de montage du serveur NFS ne peut être vierge." msgid "Invalid NFS mount path." msgstr "Chemin de montage NFS invalide." msgid "No logical device selected." msgstr "Aucun périphérique logique sélectionné." msgid "The iSCSI target can not be blank." msgstr "La cible iSCSI ne peut être vierge." msgid "Server name can not be blank." msgstr "Le nom de serveur ne peut être vierge." msgid "This is not a valid Server Name or IP. Please, modify it." msgstr "" msgid "Looking for available partitions ..." msgstr "En cours de recherche de partitions disponibles..." msgid "No available partitions found." msgstr "Aucune partition disponible trouvée." msgid "" "This storage pool is not persistent. Instead of deactivate, this action will " "permanently delete it. Would you like to continue?" msgstr "" "Le pool de stockage n'est pas persistent. Au lieu de le désactiver, cette " "action va le supprimer de manière permanente. Voulez-vous continuer ?" msgid "Unable to retrieve partitions information." msgstr "Impossible de récupérer les informations des partitions." msgid "In progress..." msgstr "En cours..." msgid "Failed!" msgstr "Échec!" msgid "CDROM path needs to be a valid local/remote path and cannot be blank." msgstr "" "Le chemin de CDROM doit être un chemin local/distant valide et ne peut être " "virge." msgid "Disk pool or volume cannot be blank." msgstr "Le pool de disque ou le volume ne peut être vierge." msgid "Peers" msgstr "" msgid "Searching" msgstr "" msgid "No peers found." msgstr "" msgid "Help" msgstr "Aide" msgid "About" msgstr "A propos..." msgid "Log out" msgstr "Se déconnecter" msgid "Version:" msgstr "Version:" msgid "Session timeout, please re-login." msgstr "Session expirée, veuillez vous reconnecter." msgid "User Name" msgstr "Nom d'Utilisateur" msgid "Password" msgstr "Mot de Passe" msgid "Generate a New Debug Report" msgstr "Générer un Nouveau Rapport de Déboggage" msgid "Report Name" msgstr "Nom du Rapport" msgid "" "The name used to identify the report. If omitted, a name will be chosen " "based on current time. Name can contain: letters, digits, underscore (\"_\") " "and hyphen (\"-\")." msgstr "" "Le nom utilisé pour identifier le rapport. Si omis, un nom sera choisi basé " "sur l'heure courante. Le nom peut contenir des lettres, des nombres, le " "soulignement (\"_\") et le tiret (\"-\")." msgid "Rename a Debug Report" msgstr "Renommer un Rapport de Déboggage" msgid "" "The name used to identify the report. Name can contain: letters, digits and " "hyphen (\"-\")." msgstr "" "Le nom utilisé pour identifer le rapport. Le nom peut contenir des lettres, " "nombres et tirets (\"-\")." msgid "Submit" msgstr "Soumettre" msgid "Add a Repository" msgstr "Ajouter un Dépôt" msgid "Identifier" msgstr "Identificateur" msgid "Single word, unique identifier for the repository." msgstr "Mot unique, identifiant unique pour le dépôt." msgid "Textual name for the repository." msgstr "Nom textuel pour le dépôt." msgid "URL" msgstr "URL" msgid "Required Field" msgstr "Champ requis" msgid "URL to the repository. Supported protocols are http, ftp, and file." msgstr "URL du dépôt. Les protocoles supportés sont http, ftp et ficheir." msgid "Repository is a mirror" msgstr "Le dépôt est un miroir" msgid "Distribution" msgstr "Distribution" msgid "Distribution of the DEB repository." msgstr "Distribution du dépôt DEB." msgid "Components" msgstr "Composants" msgid "List of components in DEB repository." msgstr "Liste des composants dans le dépôt DEB." msgid "Edit Repository" msgstr "Editer le Dépôt" msgid "Mirror List URL" msgstr "URL de Liste de Miroir" msgid "Yes" msgstr "Oui" msgid "No" msgstr "Non" msgid "Add a Volume to Storage Pool" msgstr "iAjouter un Volume au Pool de Stockage" msgid "Fetch from remote URL" msgstr "" msgid "Enter the remote URL here." msgstr "Saisir une URL distante ici" msgid "Upload a file" msgstr "Charger un fichier" msgid "Choose the file you want to upload." msgstr "" msgid "Define a New Storage Pool" msgstr "Définir un Nouveau Pool de Stockage" msgid "Storage Pool Name" msgstr "Nom de Pool de Stockage" msgid "" "The name used to identify the storage pools, and it should not be empty." msgstr "" "Le nom utilisé pour identifier les pools de stockage, et il ne doit pas être " "vide." msgid "Storage Pool Type" msgstr "Type de Pool de Stockage" msgid "Storage Path" msgstr "Chemin de Stockage" msgid "" "The path of the Storage Pool. Each Storage Pool must have a unique path." msgstr "" "Le chemin du Pool de Stockage. Chaque Pool de Stockage doit avoir un chemin " "unique." msgid "" "Kimchi will try to create the directory when it does not already exist in " "your system." msgstr "" "Kimchi va essayer de créer un répertoire quand il n'existe pas déjà dans " "votre système." msgid "NFS Server IP" msgstr "IP du Serveur NFS" msgid "NFS server IP or hostname. It can be input or chosen from history." msgstr "" "IP du Serveur NFS ou nom d'hôte. Il peut être saisi ou entré à partir de " "l'historique." msgid "NFS Path" msgstr "Chemin NFS" msgid "The NFS exported path on NFS server." msgstr "Le chemin NFS exporté sur le serveur NFS." msgid "Device path" msgstr "Chemin du Périphérique" msgid "iSCSI Server" msgstr "Serveur iSCSI" msgid "iSCSI server IP or hostname. It should not be empty." msgstr "IP du Serveur iSCSI ou nom d'hôte. Il ne devrait pas être vide." msgid "Server" msgstr "Serveur" msgid "Port" msgstr "Port" msgid "Target" msgstr "Cible" msgid "The iSCSI target on iSCSI server" msgstr "La cible iSCSI sur le serveur iSCSI" msgid "Add iSCSI Authentication" msgstr "Ajouter l'Authentification iSCSI" msgid "iSCSI Authentication" msgstr "Authentification iSCSI" msgid "SCSI Adapter" msgstr "Adaptateur SCSI" msgid "Please, wait..." msgstr "Veuillez patienter..." msgid "Add Template" msgstr "Ajouter un Modèle" msgid "Where is the source media for this template? " msgstr "Où se trouve le media source pour le modèle ?" msgid "Local ISO Image" msgstr "Image ISO Locale" msgid "Local Image File" msgstr "Fichier Image Local" msgid "Remote ISO Image" msgstr "Image ISO Distante" msgid "Search ISOs" msgstr "Rechercher des ISOs" msgid "The following ISOs are available:" msgstr "Les ISOs suivants sont disponibles:" msgid "OS: " msgstr "OS: " msgid "Version: " msgstr "Version: " msgid "Size: " msgstr "Taille: " msgid "Search more ISOs" msgstr "Chercher plus d'ISOs" msgid "Create Templates from Selected ISO" msgstr "Créer des modèles depuis l'ISO sélectionné" msgid "I want to use a specific ISO file" msgstr "Je veux utiliser un fichier ISO spécifique" msgid "Loading default remote ISOs ..." msgstr "Chargement des ISOs distants par défaut en cours..." msgid "Arch: " msgstr "Arch: " msgid "I want to use a custom URL" msgstr "Je veux utiliser une URL personnalisée" msgid "Edit Template" msgstr "Éditer un Modèle" msgid "Processor" msgstr "Processeur" msgid "CDROM" msgstr "CDROM" msgid "Image File" msgstr "Fichier Image" msgid "Graphics" msgstr "Graphiques" msgid "Disk(GB)" msgstr "" msgid "Disk Format" msgstr "" msgid "CPU Number" msgstr "Nombre de CPU" msgid "Manually set CPU topology" msgstr "" msgid "Cores" msgstr "" msgid "Threads" msgstr "" msgid "CPU" msgstr "CPU" msgid "Disk I/O" msgstr "E/S Disque" msgid "Network I/O" msgstr "E/S Réseau" msgid "Livetile" msgstr "Livetile" msgid "No guests found." msgstr "Aucun invité trouvé." msgid "Shut down" msgstr "Éteindre" msgid "Restart" msgstr "Redémarrer" msgid "Basic Information" msgstr "Informations de Base" msgid "OS Distro" msgstr "Distro de l'OS" msgid "OS Code Name" msgstr "Nom de code de l'OS" msgid "CPU(s)" msgstr "" msgid "System Statistics" msgstr "Statistiques Système" msgid "Update Progress" msgstr "Progrès de la Mise à Jour" msgid "Network Name" msgstr "Nom de Réseau" msgid "State" msgstr "État" msgid "Network Type" msgstr "Type de Réseau" msgid "Address Space" msgstr "Espace d'adressage" msgid "Name should not contain '/' and '\"'." msgstr "Le nom ne devrait pas contenir '/' et '\"'." msgid "Isolated: no external network connection" msgstr "Isolé: pas de connexion à un réseau externe" msgid "NAT: outbound physical network connection only" msgstr "NAT: connexion physique au réseau sortant uniquement" msgid "Bridged: Virtual machines are connected to physical network directly" msgstr "" "Bridgé: Les macines virtuelles sont connectées directement au réseau physique" msgid "(No interfaces found)" msgstr "(Aucune interface trouvée)" msgid "Destination" msgstr "Destination" msgid "Enable VLAN" msgstr "Activer le VLAN" msgid "VLAN ID" msgstr "ID de VLAN" msgid "Stop" msgstr "Arrêter" msgid "%Used" msgstr "" msgid "Location" msgstr "Emplacement" msgid "Capacity" msgstr "Capacité" msgid "Allocated" msgstr "Alloué" msgid "active" msgstr "actif" msgid "inactive" msgstr "inactif" msgid "Deactivate" msgstr "Désactiver" msgid "Activate" msgstr "Activer" msgid "Add Volume" msgstr "Ajouter un Volume" msgid "Extend" msgstr "Étendre" msgid "Undefine" msgstr "Supprimer" msgid "Format" msgstr "Format" msgid "Allocation" msgstr "Allocation" msgid "No templates found." msgstr "Aucun modèle trouvé." kimchi-1.5.0/po/gen-pot.in000066400000000000000000000003041254252253000152750ustar00rootroot00000000000000#!/bin/bash for src in $@; do if [ ${src: -3} == ".py" ]; then cat $src else cat $src | @CHEETAH@ compile - fi done | xgettext --no-location -o kimchi.pot -L Python - kimchi-1.5.0/po/it_IT.po000066400000000000000000001644541254252253000147650ustar00rootroot00000000000000# English translations for kimchi package. # Copyright (C) 2013 ORGANIZATION # msgid "" msgstr "" "Project-Id-Version: kimchi 0.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-06-24 09:39-0300\n" "PO-Revision-Date: 2013-07-11 17:32-0400\n" "Last-Translator: Crístian Viana \n" "Language-Team: English\n" "Language: it_IT\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: pygettext.py 1.5\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #, python-format msgid "Unknown parameter %(value)s" msgstr "" #, python-format msgid "Delete is not allowed for %(resource)s" msgstr "Eliminazione non consentita per %(resource)s" #, python-format msgid "%(resource)s does not implement update method" msgstr "%(resource)s non implementa il metodo di aggiornamento" #, python-format msgid "Create is not allowed for %(resource)s" msgstr "Creazione non consentita per %(resource)s" msgid "Unable to parse JSON request" msgstr "Impossibile analizzare la richiesta JSON" msgid "This API only supports JSON" msgstr "L'API supporta solo JSON" #, python-format msgid "Parameters does not match requirement in schema: %(err)s" msgstr "" msgid "You don't have permission to perform this operation." msgstr "" msgid "Datastore is not initiated in the model object." msgstr "Archivio dati non inizializzato nell'oggetto modello." #, python-format msgid "Unable to start task due error: %(err)s" msgstr "Impossibile avviare l'attività a causa dell'errore: %(err)s" #, python-format msgid "Timeout of %(seconds)s seconds expired while running task '%(task)s." msgstr "" #, python-format msgid "Authentication failed for user '%(username)s'. [Error code: %(code)s]" msgstr "" "Autenticazione non riuscita per l'utente '%(username)s'. [Codice di errore: " "%(code)s]" msgid "You are not authorized to access Kimchi" msgstr "Non si dispone dell'autorizzazione ad accedere a Kimchi" #, python-format msgid "Specify %(item)s to login into Kimchi" msgstr "Specificare %(item)s per accedere a Kimchi" #, python-format msgid "User %(user_id)s not found with given LDAP settings." msgstr "" #, python-format msgid "Invalid LDAP configuration: %(item)s : %(value)s" msgstr "" msgid "Unknown \"_cap\" specified" msgstr "" msgid "\"_passthrough\" should be \"true\" or \"false\"" msgstr "" msgid "\"_passthrough_affected_by\" should be a device name string" msgstr "" #, python-format msgid "Error while getting block devices. Details: %(err)s" msgstr "" "Errore durante il richiamo dei dispositivi del blocco. Dettagli: %(err)s" #, python-format msgid "Error while getting block device information for %(device)s." msgstr "" "Errore durante il richiamo delle informazioni sul dispositivo del blocco per " "%(device)s." #, python-format msgid "Unable to find distro file: %(filename)s" msgstr "Impossibile trovare il file distro: %(filename)s" #, python-format msgid "" "Unable to parse distro file: %(filename)s. Make sure, it is a JSON file." msgstr "" "Impossibile analizzare il file distro: %(filename)s. Verificare che sia un " "file JSON." #, python-format msgid "Unable to login to iSCSI host target %(portal)s. Details: %(err)s" msgstr "" "Impossibile accedere a %(portal)s di destinazione host iSCSI. Dettagli: " "%(err)s" #, python-format msgid "Unable to login to iSCSI host %(host)s target %(target)s" msgstr "Impossibile accedere alla destinazione %(target)s host %(host)s iSCSI" #, python-format msgid "Unable to find ISO file %(filename)s" msgstr "" #, python-format msgid "The ISO file %(filename)s is not bootable" msgstr "Il file ISO %(filename)s non è avviabile" #, python-format msgid "The ISO file %(filename)s does not have a valid El Torito boot record" msgstr "Il file ISO %(filename)s non ha un record di avvio El Torito valido" #, python-format msgid "Invalid El Torito validation entry in ISO %(filename)s" msgstr "Voce di convalida El Torito non valida in ISO %(filename)s" #, python-format msgid "Invalid El Torito boot indicator in ISO %(filename)s" msgstr "Indicatore di avvio El Torito non valido in ISO %(filename)s" #, python-format msgid "Unexpected volume type for primary volume in ISO %(filename)s" msgstr "Tipo di volume imprevisto per il volume primario in ISO %(filename)s" #, python-format msgid "Bad format while reading volume descriptor in ISO %(filename)s" msgstr "" "Formato non corretto durante la lettura del descrittore volume in ISO " "%(filename)s" #, python-format msgid "" "The hypervisor doesn't have permission to use this ISO %(filename)s. " "Consider moving it under /var/lib/libvirt, or set the search permission to " "file access control lists for '%(user)s' user if possible, or add the " "'%(user)s' to the ISO path group, or (not recommended) 'chmod -R o+x " "'path_to_iso'.Details: %(err)s" msgstr "" "L'hypervisor non dispone dell'autorizzazione per utilizzare questo ISO " "%(filename)s. Spostarlo in /var/lib/libvirt o impostare l'autorizzazione di " "ricerca per gli elenchi di controllo accesso ai file per l'utente " "'%(user)s', se possibile, o aggiungere '%(user)s' al gruppo percorso ISO o " "(non consigliato) 'chmod -R o+x 'path_to_iso'. Dettagli: %(err)s" msgid "An error occurred when probing image OS information." msgstr "" msgid "No OS information found in given image." msgstr "" #, python-format msgid "Unable to read image file %(filename)s" msgstr "" #, python-format msgid "" "Image file must be an existing file on system. %(filename)s is not a valid " "input." msgstr "" #, python-format msgid "Virtual machine %(name)s already exists" msgstr "Macchina virtuale %(name)s già esistente" #, python-format msgid "Virtual machine %(name)s does not exist" msgstr "La macchina virtuale %(name)s non esiste" #, python-format msgid "" "Unable to rename virtual machine %(name)s. The name %(new_name)s is already " "in use or the virtual machine is not powered off." msgstr "" #, python-format msgid "Unable to retrieve screenshot for stopped virtual machine %(name)s" msgstr "" "Impossibile richiamare l'immagine per la macchina virtuale arrestata %(name)s" msgid "Remote ISO image is not supported by this server." msgstr "L'immagine ISO remota non è supportata da questo server." #, python-format msgid "Screenshot is not supported on virtual machine %(name)s" msgstr "" #, python-format msgid "Unable to create virtual machine %(name)s. Details: %(err)s" msgstr "Impossibile creare la macchina virtuale %(name)s. Dettagli: %(err)s" #, python-format msgid "Unable to update virtual machine %(name)s. Details: %(err)s" msgstr "Impossibile creare la macchina virtuale %(name)s. Dettagli: %(err)s" #, python-format msgid "Unable to retrieve virtual machine %(name)s. Details: %(err)s" msgstr "" "Impossibile richiamare la macchina virtuale %(name)s. Dettagli: %(err)s" #, python-format msgid "Unable to connect to powered off virtual machine %(name)s." msgstr "" msgid "Virtual machine name must be a string without slashes (/)" msgstr "" #, python-format msgid "Invalid template URI %(value)s specified for virtual machine" msgstr "" #, python-format msgid "Invalid storage pool URI %(value)s specified for virtual machine" msgstr "" msgid "Supported virtual machine graphics are Spice or VNC" msgstr "" msgid "Graphics address to listen on must be IPv4 or IPv6" msgstr "" "L'indirizzo dei grafici su cui rimanere in ascolto deve essere IPv4 o IPv6" msgid "Specify a template to create a virtual machine from" msgstr "Specificare un modello da cui creare una macchina virtuale" #, python-format msgid "Unable to start virtual machine %(name)s. Details: %(err)s" msgstr "Impossibile avviare la macchina virtuale %(name)s. Dettagli: %(err)s" #, python-format msgid "Unable to power off virtual machine %(name)s. Details: %(err)s" msgstr "Impossibile arrestare la macchina virtuale %(name)s. Dettagli: %(err)s" #, python-format msgid "Unable to delete virtual machine %(name)s. Details: %(err)s" msgstr "Impossibile eliminare la macchina virtuale %(name)s. Dettagli: %(err)s" #, python-format msgid "Unable to reset virtual machine %(name)s. Details: %(err)s" msgstr "" "Impossibile ridenominare la macchina virtuale %(name)s. Dettagli: %(err)s" msgid "User name list must be an array" msgstr "" msgid "User name must be a string" msgstr "Il nome della rete deve essere una stringa" msgid "Group name list must be an array" msgstr "" msgid "Group name must be a string" msgstr "Il nome della rete deve essere una stringa" #, python-format msgid "User(s) '%(users)s' do not exist" msgstr "L'utente '%(users)s' non esiste." #, python-format msgid "Group(s) '%(groups)s' do not exist" msgstr "L'utente '%(groups)s' non esiste." #, python-format msgid "Unable to shutdown virtual machine %(name)s. Details: %(err)s" msgstr "Impossibile arrestare la macchina virtuale %(name)s. Dettagli: %(err)s" #, python-format msgid "" "Unable to get access metadata of virtual machine %(name)s. Details: %(err)s" msgstr "Impossibile avviare la macchina virtuale %(name)s. Dettagli: %(err)s" msgid "The guest console password must be a string." msgstr "" msgid "The life time for the guest console password must be a number." msgstr "" #, python-format msgid "Virtual machine '%(name)s' must be stopped before cloning it." msgstr "" #, python-format msgid "Insufficient disk space to clone virtual machine '%(name)s'" msgstr "" #, python-format msgid "Unable to clone VM '%(name)s'. Details: %(err)s" msgstr "" #, python-format msgid "Invalid operation for non-persistent virtual machine %(name)s" msgstr "" #, python-format msgid "Cannot suspend VM '%(name)s' because it is not running." msgstr "" #, python-format msgid "Unable to suspend VM '%(name)s'. Details: %(err)s" msgstr "" #, python-format msgid "Cannot resume VM '%(name)s' because it is not paused." msgstr "" #, python-format msgid "Unable to resume VM '%(name)s'. Details: %(err)s" msgstr "" msgid "Memory assigned is higher then the maximum allowed in the host." msgstr "" #, python-format msgid "" "VM '%(name)s' does not support live memory update. Update the memory with " "the machine offline to enable this feature." msgstr "" msgid "Only increase memory is allowed in active VMs" msgstr "" msgid "" "For live memory update, new memory value must be equal old memory value plus " "multiples of 1024 Mib" msgstr "" msgid "There are not enough free slots of 1024 Mib in the guest." msgstr "" msgid "" "Host's libvirt version does not support memory devices. Libvirt must be >= " "1.2.14" msgstr "" #, python-format msgid "Error attaching memory device. Details: %(error)s" msgstr "" #, python-format msgid "" "VM %(vmid)s does not contain directly assigned host device %(dev_name)s." msgstr "" #, python-format msgid "The host device %(dev_name)s is not allowed to directly assign to VM." msgstr "" msgid "" "No IOMMU groups found. Host PCI pass through needs IOMMU group to function " "correctly. Please enable Intel VT-d or AMD IOMMU in your BIOS, then verify " "the Kernel is compiled with IOMMU support. For Intel CPU, add intel_iommu=on " "to your Kernel parameter in /boot/grub2/grub.conf. For AMD CPU, add iommu=pt " "iommu=1." msgstr "" msgid "\"name\" should be a device name string" msgstr "" #, python-format msgid "" "The device %(name)s is probably in use by the host. Unable to attach it to " "the guest." msgstr "" #, python-format msgid "Interface %(iface)s does not exist in virtual machine %(name)s" msgstr "L'interfaccia %(iface)s non esiste nella macchina virtuale %(name)s" #, python-format msgid "" "Network %(network)s specified for virtual machine %(name)s does not exist" msgstr "" "La rete %(network)s specificata per la macchina virtuale %(name)s non esiste" msgid "Supported virtual machine interfaces type is only network" msgstr "" "Il tipo supportato per le interfacce della macchina virtuale è solo rete" msgid "Network name for virtual machine interface must be a string" msgstr "" "Il nome di rete per l'interfaccia della macchina virtuale deve essere una " "stringa" msgid "Invalid network model card specified for virtual machine interface" msgstr "" "Scheda modello di rete non valida per l'interfaccia della macchina virtuale" msgid "Specify type and network to add a new virtual machine interface" msgstr "" "Specificare il tipo e la rete per aggiungere una nuova interfaccia della " "macchina virtuale" msgid "MAC Address must respect this format FF:FF:FF:FF:FF:FF" msgstr "" #, python-format msgid "MAC Address %(mac)s already exists in virtual machine %(name)s" msgstr "" msgid "Invalid MAC Address" msgstr "" msgid "Cannot change MAC address of a running virtual machine" msgstr "" #, python-format msgid "Template %(name)s already exists" msgstr "Modello %(name)s già esistente" #, python-format msgid "" "Network '%(network)s' specified for template %(template)s does not exist" msgstr "" "La rete '%(network)s' specificata per il modello %(template)s non esiste" #, python-format msgid "" "Storage pool %(pool)s specified for template %(template)s does not exist" msgstr "" "Il pool di memoria %(pool)s specificato per il modello %(template)s non " "esiste" #, python-format msgid "Storage pool %(pool)s specified for template %(template)s is not active" msgstr "" "Il pool di memoria %(pool)s specificato per il modello %(template)s non è " "attivo" #, python-format msgid "Invalid parameter '%(param)s' specified for CDROM." msgstr "Parametro non valido %(param)s' specificato per CDROM." #, python-format msgid "Network %(network)s specified for template %(template)s is not active" msgstr "" "La rete %(network)s specificata per il modello %(template)s non è attiva" msgid "Template name must be a string" msgstr "Il nome del modello deve essere una stringa" msgid "Template icon must be a path to the image" msgstr "L'icona del modello deve essere un percorso all'immagine" msgid "Template distribution must be a string" msgstr "La distribuzione del modello deve essere una stringa" msgid "Template distribution version must be a string" msgstr "La versione della distribuzione del modello deve essere una stringa" msgid "The number of CPUs must be an integer greater than 0" msgstr "Il numero di CPU deve essere un numero intero" msgid "Amount of memory (MB) must be an integer greater than 512" msgstr "" "La quantità di memoria (MB) deve essere un numero intero maggiore di 512" msgid "Template CDROM must be a local or remote ISO file" msgstr "Il CDROM del modello deve essere un file ISO locale o remoto" #, python-format msgid "Invalid storage pool URI %(value)s specified for template" msgstr "URI pool di memoria non valido: %(value)s specificato per il modello" msgid "Specify an ISO image as CDROM or a base image to create a template" msgstr "Specificare un'immagine ISO come CDROM per creare un modello" msgid "All networks for the template must be specified in a list." msgstr "Tutte le reti per il modello devono essere specificate in un elenco." msgid "Specify a volume to a template when storage pool is iSCSI or SCSI" msgstr "" #, python-format msgid "The volume %(volume)s is not in storage pool %(pool)s" msgstr "" #, python-format msgid "Unable to create template due error: %(err)s" msgstr "Impossibile creare il modello a causa dell'errore: %(err)s" #, python-format msgid "Unable to delete template due error: %(err)s" msgstr "Impossibile eliminare il modello a causa dell'errore: %(err)s" msgid "Disk size must be an integer greater than 1GB." msgstr "" msgid "Template base image must be a valid local image file" msgstr "Il CDROM del modello deve essere un file ISO locale o remoto" #, python-format msgid "Cannot identify base image %(path)s format" msgstr "" msgid "" "When specifying CPU topology, VCPUs must be a product of sockets, cores, and " "threads." msgstr "" msgid "" "When specifying CPU topology, each element must be an integer greater than " "zero." msgstr "" msgid "" "Invalid disk image format. Valid formats: bochs, cloop, cow, dmg, qcow, " "qcow2, qed, raw, vmdk, vpc." msgstr "" #, python-format msgid "Storage pool %(name)s already exists" msgstr "Pool di memoria %(name)s già esistente" #, python-format msgid "Storage pool %(name)s does not exist" msgstr "Il pool di memoria %(name)s non esiste" #, python-format msgid "Specify %(item)s in order to create the storage pool %(name)s" msgstr "Specificare %(item)s per poter creare il pool di memoria %(name)s" #, python-format msgid "Unable to delete active storage pool %(name)s" msgstr "Impossibile eliminare il pool di memoria attivo %(name)s" #, python-format msgid "Unable to list storage pools. Details: %(err)s" msgstr "Impossibile elencare i pool di memoria. Dettagli: %(err)s" #, python-format msgid "Unable to create storage pool %(name)s. Details: %(err)s" msgstr "Impossibile creare il pool di memoria %(name)s. Dettagli: %(err)s" #, python-format msgid "" "Unable to get number of storage volumes in storage pool %(name)s. Details: " "%(err)s" msgstr "" "Impossibile ottenere il numero di volumi di memoria nel pool di memoria " "%(name)s. Dettagli: %(err)s" #, python-format msgid "Unable to activate storage pool %(name)s. Details: %(err)s" msgstr "Impossibile attivare il pool di memoria %(name)s. Dettagli: %(err)s" #, python-format msgid "Unable to deactivate storage pool %(name)s. Details: %(err)s" msgstr "Impossibile disattivare il pool di memoria %(name)s. Dettagli: %(err)s" #, python-format msgid "Unable to delete storage pool %(name)s. Details: %(err)s" msgstr "Impossibile eliminare il pool di memoria %(name)s. Dettagli: %(err)s" #, python-format msgid "" "Unable to create NFS Pool as export path %(path)s may block during mount" msgstr "" "Impossibile creare il pool NFS poiché il percorso di esportazione %(path)s " "potrebbe bloccarsi durante il montaggio" #, python-format msgid "Unable to create NFS Pool as export path %(path)s mount failed" msgstr "" "Impossibile creare il pool NFS poiché il montaggio del percorso di " "esportazione %(path)s ha avuto esito negativo" #, python-format msgid "Unsupported storage pool type: %(type)s" msgstr "Tipo di pool di memoria non supportato: %(type)s" #, python-format msgid "Error while retrieving storage pool XML to %(pool)s" msgstr "" msgid "Storage pool name must be a string without slashes (/)" msgstr "" msgid "" "Supported storage pool types are dir, netfs, logical, iscsi, isci and kimchi-" "iso" msgstr "" msgid "Storage pool path must be a string" msgstr "Il percorso del pool di memoria deve essere una stringa" msgid "Storage pool host must be a IP or hostname" msgstr "L'host del pool di memoria deve essere un nome host o IP" msgid "Storage pool device must be the absolute path to the block device" msgstr "" msgid "Storage pool devices parameter must be a list" msgstr "Il parametro dispositivi pool di memoria deve essere un elenco" msgid "Target IQN of an iSCSI pool must be a string" msgstr "L'IQN di destinazione di un pool iSCSI deve essere una stringa" msgid "Port of a remote storage server must be an integer between 1 and 65535" msgstr "" "La porta di un server di memoria remoto deve essere un numero intero tra 1 e " "65535" msgid "iSCSI target username must be a string" msgstr "" msgid "iSCSI target password must be a string" msgstr "" msgid "Specify name and type to create a storage pool" msgstr "Specificare nome e tipo per creare un pool di memoria" #, python-format msgid "" "%(disk)s is not a valid disk/partition. Could not add it to the pool " "%(pool)s." msgstr "" "%(disk)s non è un disco/partizione valido. Impossibile aggiungerlo al pool " "%(pool)s." #, python-format msgid "Unable to extend logical pool %(pool)s. Details: %(err)s" msgstr "" msgid "The parameter disks only can be updated for logical storage pool." msgstr "" "Solo il parametro dischi può essere aggiornato per il pool di memoria logico." msgid "The SCSI host adapter name must be a string." msgstr "Il nome adattatore host SCSI deve essere una stringa." msgid "The storage pool kimchi_isos is reserved for internal use" msgstr "Il pool di memoria kimchi_isos è riservato per uso interno" #, python-format msgid "" "Unable to activate NFS storage pool %(name)s. NFS server %(server)s is " "unreachable." msgstr "" "Impossibile attivare il pool di memoria NFS %(name)s. Il server NFS " "%(server)s è irraggiungibile." #, python-format msgid "" "Unable to deactivate NFS storage pool %(name)s. NFS server %(server)s is " "unreachable." msgstr "" "Impossibile disattivare il pool di memoria NFS %(name)s. Il server NFS " "%(server)s è irraggiungibile." #, python-format msgid "" "Unable to deactivate pool %(name)s as it is associated with some templates" msgstr "" "Impossibile disattivare il pool %(name)s poiché è associato ad alcuni modelli" #, python-format msgid "Unable to delete pool %(name)s as it is associated with some templates" msgstr "" "Impossibile eliminare il pool %(name)s poiché è associato ad alcuni modelli" #, python-format msgid "" "A volume group named '%(name)s' already exists. Please, choose another name " "to create the logical pool." msgstr "" "Un gruppo di volumi denominato '%(name)s' esiste già. Scegliere un altro " "nome per creare il pool logico." #, python-format msgid "Unable to update database with deep scan information due error: %(err)s" msgstr "" "Impossibile aggiornare il database con informazioni approfondite sulla " "scansione a causa dell'errore: %(err)s" #, python-format msgid "Storage volume %(name)s already exists" msgstr "Volume di memoria %(name)s già esistente" #, python-format msgid "Storage volume %(name)s does not exist in storage pool %(pool)s" msgstr "Il volume di memoria %(name)s non esiste nel pool di memoria %(pool)s" #, python-format msgid "" "Unable to create storage volume %(volume)s because storage pool %(pool)s is " "not active" msgstr "" #, python-format msgid "Specify %(item)s in order to create storage volume %(volume)s" msgstr "Specificare %(item)s per poter creare il volume di memoria %(volume)s" #, python-format msgid "" "Unable to list storage volumes because storage pool %(pool)s is not active" msgstr "" "Impossibile elencare i volumi di memoria poiché il pool di memoria %(pool)s " "non è attivo" #, python-format msgid "" "Unable to create storage volume %(name)s in storage pool %(pool)s. Details: " "%(err)s" msgstr "" "Impossibile creare il volume di memoria %(name)s nel pool di memoria " "%(pool)s. Dettagli: %(err)s" #, python-format msgid "" "Unable to list storage volumes in storage pool %(pool)s. Details: %(err)s" msgstr "" "Impossibile elencare i volumi di memoria nel pool di memoria %(pool)s. " "Dettagli: %(err)s" #, python-format msgid "Unable to wipe storage volumes %(name)s. Details: %(err)s" msgstr "Impossibile ripulire i volumi di memoria %(name)s. Dettagli: %(err)s" #, python-format msgid "Unable to delete storage volume %(name)s. Details: %(err)s" msgstr "Impossibile eliminare il volume di memoria %(name)s. Dettagli: %(err)s" #, python-format msgid "Unable to resize storage volume %(name)s. Details: %(err)s" msgstr "" "Impossibile ridimensionare il volume di memoria %(name)s. Dettagli: %(err)s" #, python-format msgid "Storage type %(type)s does not support volume create and delete" msgstr "" "Il tipo di memoria %(type)s non supporta la creazione ed eliminazione del " "volume" msgid "Storage volume name must be a string" msgstr "Il nome del volume di memoria deve essere una stringa" msgid "Storage volume allocation must be an integer number" msgstr "L'assegnazione del volume di memoria deve essere un numero intero" msgid "" "Storage volume format not supported. Valid formats: bochs, cloop, cow, dmg, " "qcow, qcow2, qed, raw, vmdk, vpc." msgstr "" msgid "Storage volume requires a volume name" msgstr "Il volume di memoria richiede un nome volume" #, python-format msgid "" "Unable to update database with storage volume information due error: %(err)s" msgstr "" "Impossibile aggiornare il database con informazioni sul volume di memoria a " "causa dell'errore: %(err)s" #, python-format msgid "Only one of parameter %(param)s can be specified" msgstr "" #, python-format msgid "Create volume from %(param)s is not supported" msgstr "" msgid "Storage volume capacity must be an integer number." msgstr "" msgid "Storage volume URL must be http://, https://, ftp:// or ftps://." msgstr "" #, python-format msgid "Unable to access file %(url)s. Please, check it." msgstr "" #, python-format msgid "" "Unable to clone storage volume '%(name)s' in pool '%(pool)s'. Details: " "%(err)s" msgstr "" msgid "Specify chunk data and its size to upload a file." msgstr "" msgid "In order to upload a storage volume, specify the 'upload' parameter." msgstr "" msgid "" "Unable to upload chunk data as it does not match with requested chunk size." msgstr "" #, python-format msgid "The storage volume %(vol)s is not under an upload process." msgstr "" msgid "The upload chunk data will exceed the storage volume size." msgstr "" #, python-format msgid "Unable to upload chunk data to storage volume. Details: %(err)s." msgstr "" #, python-format msgid "Interface %(name)s does not exist" msgstr "L'interfaccia %(name)s non esiste" #, python-format msgid "Network %(name)s already exists" msgstr "Rete %(name)s già esistente" #, python-format msgid "Network %(name)s does not exist" msgstr "La rete %(name)s non esiste" #, python-format msgid "Subnet %(subnet)s specified for network %(network)s is not valid." msgstr "" "La sottorete %(subnet)s specificata per la rete %(network)s non è valida ." #, python-format msgid "Specify a network interface to create bridged network %(name)s" msgstr "" "Specificare un'interfaccia di rete per creare la rete con bridge %(name)s" #, python-format msgid "Unable to delete active network %(name)s" msgstr "Impossibile eliminare la rete attiva %(name)s" #, python-format msgid "Interface %(iface)s specified for network %(network)s is already in use" msgstr "" "L'interfaccia %(iface)s specificata per la rete %(network)s è già in uso" msgid "Interface should be bare NIC, bonding or bridge device." msgstr "" "L'interfaccia deve essere un dispositivo bridge o di collegamento NIC bare-" "metal." #, python-format msgid "Unable to create network %(name)s. Details: %(err)s" msgstr "Impossibile creare la rete %(name)s. Dettagli: %(err)s" #, python-format msgid "Unable to find a free IP address for network '%(name)s'" msgstr "Impossibile trovare un indirizzo IP libero per la rete '%(name)s'" #, python-format msgid "The interface %(iface)s already exists." msgstr "L'interfaccia %(iface)s già esistente." msgid "Network name must be a string without slashes (/) or quotes (\")" msgstr "" msgid "Supported network types are isolated, NAT and bridge" msgstr "I tipi di rete supportati sono isolata, NAT e bridge" msgid "Network subnet must be a string with IP address and prefix or netmask" msgstr "" "La sottorete della rete deve essere una stringa con indirizzo IP e prefisso " "o maschera di rete" msgid "Network interface must be a string" msgstr "L'interfaccia di rete deve essere una stringa" msgid "Network VLAN ID must be an integer between 1 and 4094" msgstr "L'ID VLAN di rete deve essere un numero intero tra 1 e 4094" msgid "Specify name and type to create a Network" msgstr "Specificare nome e tipo per creare una rete" #, python-format msgid "" "Unable to delete network %(name)s. There are some virtual machines %(vms)s " "and/or templates linked to this network." msgstr "" "Impossibile eliminare la rete %(name)s. Ci sono alcune macchine virtuali " "%(vms)s e/o modelli collegati a tale rete." #, python-format msgid "" "Unable to deactivate network %(name)s. There are some virtual machines " "%(vms)s and/or templates linked to this network." msgstr "" "Impossibile disattivare la rete %(name)s. Ci sono alcune macchine virtualie " "%(vms)s e/o modelli collegati a tale rete." #, python-format msgid "Bridge device %(name)s can not be the trunk device of a VLAN." msgstr "" "Il dispositivo bridge %(name)s non può essere il dispositivo trunk di una " "VLAN." #, python-format msgid "Failed to activate interface %(iface)s: %(err)s." msgstr "Impossibile attivare l'interfaccia %(iface)s: %(err)s." #, python-format msgid "" "Failed to activate interface %(iface)s. Please check the physical link " "status." msgstr "" "Impossibile attivare l'interfaccia %(iface)s. Controllare lo stato del link " "fisico." #, python-format msgid "Failed to start network %(name)s. Details: %(err)s" msgstr "" #, python-format msgid "Debug report %(name)s does not exist" msgstr "Il report di debug %(name)s non esiste" msgid "Debug report tool not found in system" msgstr "Strumento report di debug non trovato nel sistema" #, python-format msgid "Unable to create debug report %(name)s. Details: %(err)s." msgstr "Impossibile creare il report di debug %(name)s. Dettagli: %(err)s." #, python-format msgid "Can not find any debug report with the given name %(name)s" msgstr "" #, python-format msgid "Unable to generate debug report %(name)s. Details: %(err)s" msgstr "Impossibile generare il report di debug %(name)s. Dettagli: %(err)s" msgid "You should give a name for the debug report file." msgstr "" msgid "" "Debug report name must be a string. Only letters, digits, underscore ('_') " "and hyphen ('-') are allowed." msgstr "" #, python-format msgid "" "The debug report with specified name \"%(name)s\" already exists. Please use " "another one." msgstr "" "Un gruppo di volumi denominato '%(name)s' esiste già. Scegliere un altro " "nome per creare il pool logico." #, python-format msgid "Storage server %(server)s was not used by Kimchi" msgstr "Il server di memoria %(server)s non è stato utilizzato da Kimchi" #, python-format msgid "Distro '%(name)s' does not exist" msgstr "Distro '%(name)s' non esistente" #, python-format msgid "Partition %(name)s does not exist in the host" msgstr "La partizione %(name)s non esiste nell'host" msgid "Unable to shutdown host machine as there are running virtual machines" msgstr "" "Impossibile arrestare la macchina host poiché sono presenti macchine " "virtuali in esecuzione" msgid "Unable to reboot host machine as there are running virtual machines" msgstr "" "Impossibile riavviare la macchina host poiché sono presenti macchine " "virtuali in esecuzione" #, python-format msgid "Node device '%(name)s' not found" msgstr "Dispositivo nodo '%(name)s' non trovato" msgid "Conflicting flag filters specified." msgstr "" msgid "No packages marked for update" msgstr "Nessun pacchetto contrassegnato per l'aggiornamento" #, python-format msgid "Package %(name)s is not marked to be updated." msgstr "Il pacchetto %(name)s non è contrassegnato per l'aggiornamento." #, python-format msgid "Error while getting packages marked to be updated. Details: %(err)s" msgstr "" "Errore durante il richiamo dei pacchetti contrassegnati per l'aggiornamento. " "Dettagli: %(err)s" msgid "There is no compatible package manager for this system." msgstr "Non è presente un gestore pacchetti compatibile per questo sistema." #, python-format msgid "Unable to find %(item)s in datastore" msgstr "Impossibile trovare %(item)s nell'archivio dati" #, python-format msgid "Invalid URI %(uri)s" msgstr "URI %(uri)s non valido" #, python-format msgid "Timeout while running command '%(cmd)s' after %(seconds)s seconds" msgstr "" "È stato raggiunto il timeout durante l'esecuzione del comando '%(cmd)s' dopo " "%(seconds)s secondi" msgid "Unable to choose a virtual machine name" msgstr "" #, python-format msgid "Invalid data value '%(value)s'" msgstr "" #, python-format msgid "Invalid data unit '%(unit)s'" msgstr "" msgid "Invalid storage type. Types supported: 'cdrom', 'disk'" msgstr "Tipo di memoria non valido. I tipi supportati sono: 'cdrom'" #, python-format msgid "The path '%(value)s' is not a valid local/remote path for the device" msgstr "" msgid "Only CDROM path can be update." msgstr "" #, python-format msgid "" "The storage device %(dev_name)s does not exist in the virtual machine " "%(vm_name)s" msgstr "" #, python-format msgid "Error while creating new storage device: %(error)s" msgstr "" "Errore durante la creazione del nuovo dispositivo di memoria: %(error)s" #, python-format msgid "Error while updating storage device: %(error)s" msgstr "Errore durante l'aggiornamento del dispositivo di memoria: %(error)s" #, python-format msgid "Error while removing storage device: %(error)s" msgstr "Errore durante la rimozione del dispositivo di memoria: %(error)s" msgid "Do not support IDE device hot plug" msgstr "" msgid "" "Specify type and path or type and pool/volume to add a new virtual machine " "disk" msgstr "" "Specificare tipo e percorso per aggiungere un nuovo disco della macchina " "virtuale" msgid "Specify path to update virtual machine disk" msgstr "" "Specificare il percorso per aggiornare il disco della macchina virtuale" #, python-format msgid "Controller type %(type)s limitation of %(limit)s devices reached" msgstr "" #, python-format msgid "Cannot retrieve disk path information for given pool/volume: %(error)s" msgstr "" msgid "Volume already in use by other virtual machine." msgstr "" msgid "" "Only one of path or pool/volume can be specified to add a new virtual " "machine disk" msgstr "" "Specificare tipo e percorso per aggiungere un nuovo disco della macchina " "virtuale" #, python-format msgid "" "Volume chosen with format %(format)s does not fit in the storage type " "%(type)s" msgstr "" msgid "YUM Repository ID must be one word only string." msgstr "L'ID repository YUM deve essere una stringa di una sola parola." msgid "Repository URL must be an http://, ftp:// or file:// URL." msgstr "L'URL del repository deve essere http://, ftp:// o file:// URL." msgid "" "Repository configuration is a dictionary with specific values according to " "repository type." msgstr "" "La configurazione del repository è un dizionario con valori specifici in " "base al tipo di repository." msgid "Distribution to DEB repository must be a string" msgstr "La distribuzione al repository DEB deve essere una stringa" msgid "Components to DEB repository must be listed in a array" msgstr "I componenti per il repository DEB devono essere elencati in un array" msgid "Components to DEB repository must be a string" msgstr "I componenti per il repository DEB devono essere una stringa" msgid "Mirror list to repository must be a string" msgstr "" msgid "YUM Repository name must be string." msgstr "Il nome del repository YUM deve essere una stringa." msgid "GPG check must be a boolean value." msgstr "Il controllo GPG deve essere un valore booleano." msgid "GPG key must be a URL pointing to the ASCII-armored file." msgstr "La chiave GPG deve essere un URL che punta al file blindato ASCII." #, python-format msgid "Could not update repository %(repo_id)s." msgstr "Impossibile aggiornare il repository %(repo_id)s." #, python-format msgid "Repository %(repo_id)s does not exist." msgstr "Il repository %(repo_id)s non esiste." msgid "" "Specify repository base URL, mirror list or metalink in order to create or " "update a YUM repository." msgstr "" msgid "Repository management tool was not recognized for your system." msgstr "" "Lo strumento di gestione del repository non è stato riconosciuto per il " "sistema." #, python-format msgid "Repository %(repo_id)s is already enabled." msgstr "Il repository %(repo_id)s è già abilitato." #, python-format msgid "Repository %(repo_id)s is already disabled." msgstr "Il repository %(repo_id)s è già disabilitato." #, python-format msgid "Could not remove repository %(repo_id)s." msgstr "Impossibile rimuovere il repository %(repo_id)s." #, python-format msgid "Could not write repository configuration file %(repo_file)s" msgstr "" "Impossibile scrivere il file di configurazione del repository %(repo_file)s" msgid "Specify repository distribution in order to create a DEB repository." msgstr "" "Specificare la distribuzione del repository per poter creare un repository " "DEB." #, python-format msgid "Could not enable repository %(repo_id)s." msgstr "Impossibile abilitare il repository %(repo_id)s." #, python-format msgid "Could not disable repository %(repo_id)s." msgstr "Impossibile disabilitare il repository %(repo_id)s." msgid "YUM Repository ID already exists" msgstr "ID repository YUM già esistente" msgid "YUM Repository name must be a string" msgstr "Il nome del repository YUM deve essere una stringa" #, python-format msgid "Unable to list repositories. Details: '%(err)s'" msgstr "Impossibile elencare i repository. Dettagli: '%(err)s'" #, python-format msgid "Unable to retrieve repository information. Details: '%(err)s'" msgstr "" "Impossibile richiamare le informazioni sul repository. Dettagli: '%(err)s'" #, python-format msgid "Unable to add repository. Details: '%(err)s'" msgstr "Impossibile aggiungere il repository. Dettagli: '%(err)s'" #, python-format msgid "Unable to remove repository. Details: '%(err)s'" msgstr "Impossibile rimuovere il repository. Dettagli: '%(err)s'" #, python-format msgid "" "Configuration items: '%(items)s' are not supported by repository manager" msgstr "" msgid "Repository metalink must be an http://, ftp:// or file:// URL." msgstr "" msgid "Cannot specify mirrorlist and metalink at the same time." msgstr "" #, python-format msgid "" "Virtual machine '%(vm)s' must be stopped before creating a snapshot of it." msgstr "" #, python-format msgid "" "Unable to create snapshot '%(name)s' on virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "Snapshot '%(name)s' does not exist on virtual machine '%(vm)s'." msgstr "" #, python-format msgid "" "Unable to retrieve snapshot '%(name)s' on virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "Unable to list snapshots on virtual machine '%(vm)s'. Details: %(err)s" msgstr "" #, python-format msgid "" "Unable to delete snapshot '%(name)s' on virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "" "Unable to retrieve current snapshot of virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "" "Unable to revert virtual machine '%(vm)s' to snapshot '%(name)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "" "Unable to create snapshot of virtual machine '%(vm)s' because it contains a " "disk with format '%(format)s'; only 'qcow2' is supported." msgstr "" msgid "The number of vCPUs is too large for this system." msgstr "" msgid "Invalid vCPU/topology combination." msgstr "" msgid "This host (or current configuration) does not allow CPU topology." msgstr "" msgid "ERROR CODE" msgstr "CODICE DI ERRORE" msgid "REASON" msgstr "CAUSA" msgid "STACK" msgstr "STACK" msgid "Go to Homepage" msgstr "Vai alla home page" msgid "Create a New Virtual Machine" msgstr "Crea una nuova macchina virtuale" msgid "Virtual Machine Name" msgstr "Nome macchina virtuale" msgid "" "The name used to identify the virtual machine. If omitted, a name will be " "chosen based on the template used." msgstr "" "Il nome utilizzato per identificare la macchina virtuale. Se il nome viene " "omesso ne verrà scelto uno in base al modello utilizzato." msgid "Template" msgstr "Modello" msgid "Please create a template first." msgstr "Creare prima un modello." msgid "Create a Template" msgstr "Crea un modello" msgid "Please choose a template." msgstr "Scegliere un modello." msgid "OS" msgstr "SO" msgid "OS Version" msgstr "Versione SO" msgid "CPUS" msgstr "CPUS" msgid "Memory" msgstr "Memoria" msgid "Create" msgstr "Crea" msgid "Creating..." msgstr "" msgid "Edit Guest" msgstr "Modifica guest" msgid "General" msgstr "Generale" msgid "Storage" msgstr "Memoria" msgid "Interface" msgstr "Interfaccia" msgid "Permission" msgstr "Versione" msgid "Host PCI Device" msgstr "" msgid "Snapshot" msgstr "" msgid "Name" msgstr "Nome" msgid "CPUs" msgstr "CPU" msgid "Memory (MB)" msgstr "Memoria" msgid "Icon" msgstr "Icona" msgid "Device" msgstr "Nome dispositivo" msgid "Path" msgstr "Percorso NFS" msgid "Network" msgstr "Rete" msgid "Type" msgstr "Tipo" msgid "MAC Address" msgstr "" msgid "Available system users and groups" msgstr "" msgid "Selected system users and groups" msgstr "" msgid "User" msgstr "" msgid "All" msgstr "Tutti" msgid "To Add" msgstr "" msgid "Added" msgstr "" msgid "filter" msgstr "" msgid "Product" msgstr "" msgid "Vendor" msgstr "Fornitore" msgid "Created" msgstr "" msgid "Save" msgstr "Salva" msgid "Replace" msgstr "Sostituisci" msgid "Detach" msgstr "Scollega" msgid "Cancel" msgstr "Annulla" msgid "revert" msgstr "" msgid "Add a Storage Device to VM" msgstr "Aggiungi un dispositivo di memoria alla VM" msgid "Device Type" msgstr "Tipo dispositivo" msgid "The device type. Currently, \"cdrom\" and \"disk\" are supported." msgstr "Il tipo di dispositivo. Attualmente, è supportato solo \"cdrom\"." msgid "Storage Pool" msgstr "Pool di memoria" msgid "Storage pool which volume located in" msgstr "Il percorso del pool di memoria deve essere una stringa" msgid "Storage Volume" msgstr "Nome pool di memoria" msgid "Storage volume to be attached" msgstr "Il nome del volume di memoria deve essere una stringa" msgid "File Path" msgstr "Percorso file" msgid "The ISO file path in the server for CDROM." msgstr "Il percorso file ISO nel server per CDROM." msgid "Attach" msgstr "Allega" msgid "Start" msgstr "Avvia" msgid "Reset" msgstr "Reimposta" msgid "Pause" msgstr "" msgid "Resume" msgstr "" msgid "Power Off" msgstr "" msgid "Actions" msgstr "Azioni" msgid "Connect" msgstr "Connetti" msgid "Clone" msgstr "" msgid "Edit" msgstr "Modifica" msgid "Shut Down" msgstr "Arresta" msgid "Delete" msgstr "Elimina" msgid "The username or password you entered is incorrect. Please try again." msgstr "" "Il nome utente o la password immessi non sono corretti. Ripetere " "l'operazione." msgid "This field is required." msgstr "Questo campo è obbligatorio." msgid "Log in" msgstr "Accedi" msgid "Logging in..." msgstr "Accesso in corso..." msgid "Host" msgstr "Host" msgid "Guests" msgstr "Guest" msgid "Templates" msgstr "Modelli" msgid "Failed to get application configuration" msgstr "Richiamo della configurazione dell'applicazione non riuscito" msgid "This is not a valid Linux path" msgstr "Non è un percorso Linux valido" msgid "This is not a valid URL." msgstr "Non è un URL valido." msgid "No such data available." msgstr "Dati indicati non disponibili." msgid "" "Can not contact the host system. Verify the host system is up and that you " "have network connectivity to it. HTTP request response %1. " msgstr "" "Impossibile contattare il sistema host. Verificare che il sistema host sia " "attivo e che si disponga della connettività di rete per tale sistema. " "Risposta alla richiesta HTTP %1. " msgid "Unable to read file." msgstr "" msgid "Error while uploading file." msgstr "" msgid "Delete Confirmation" msgstr "Conferma eliminazione" msgid "OK" msgstr "OK" msgid "Confirm" msgstr "Conferma" msgid "Warning" msgstr "Avvertenza" msgid "Cloning..." msgstr "" msgid "Loading..." msgstr "Caricamento in corso..." msgid "An error occurred while retrieving system information." msgstr "" msgid "Retry" msgstr "Riprova" msgid "Detailed message:" msgstr "Messaggio dettagliato:" msgid "No ISO found" msgstr "" msgid "This is not a valid ISO file." msgstr "Non è un file ISO valido." msgid "This may take a long time. Do you want to continue?" msgstr "Richiederà molto tempo. Continuare?" msgid "This will permanently delete the template. Would you like to continue?" msgstr "L'azione eliminerà permanentemente il modello. Continuare?" msgid "Unable to shut down system as there are some virtual machines running!" msgstr "" "Impossibile arrestare il sistema poiché sono in esecuzione alcune macchine " "virtuali." msgid "Max:" msgstr "Massimo:" msgid "Utilization" msgstr "Utilizzo" msgid "Available" msgstr "Disponibile" msgid "Read Rate" msgstr "Velocità di lettura" msgid "Write Rate" msgstr "Velocità di scrittura" msgid "Received" msgstr "Ricevuti" msgid "Sent" msgstr "Inviati" msgid "" "Shutting down or restarting host will cause unsaved work lost. Continue to " "shut down/restarting?" msgstr "" "L'arresto o il riavvio dell'host provocherà la perdita del lavoro non " "salvato. Continuare con l'arresto o il riavvio?" msgid "" "Repository will be removed permanently and can't be recovered. Do you want " "to continue?" msgstr "" "Il repository verrà rimosso permanentemente e non potrà essere ripristinato. " "Si desidera continuare?" msgid "Repositories" msgstr "Repository" msgid "ID" msgstr "ID" msgid "Base URL" msgstr "URL di base" msgid "Is Mirror" msgstr "È speculare" msgid "URL Args" msgstr "Argomenti URL" msgid "Enabled" msgstr "Abilitato" msgid "GPG Check" msgstr "Controllo GPG" msgid "GPG Key" msgstr "Chiave GPG" msgid "Add" msgstr "Aggiungi" msgid "Remove" msgstr "Rimuovi" msgid "Enable" msgstr "Abilita" msgid "Disable" msgstr "Disabilita" msgid "Software Updates" msgstr "Aggiornamenti del software" msgid "Package Name" msgstr "Nome pacchetto" msgid "Version" msgstr "Versione" msgid "Architecture" msgstr "Architettura" msgid "Repository" msgstr "Repository" msgid "Update All" msgstr "Aggiorna tutto" msgid "Updating..." msgstr "Aggiornamento in corso..." msgid "Failed to retrieve packages update information." msgstr "" msgid "Failed to update package(s)." msgstr "Aggiornamento dei pacchetti non riuscito." msgid "" "Debug report will be removed permanently and can't be recovered. Do you want " "to continue?" msgstr "" "Il report del debug verrà rimosso permanentemente e non potrà essere " "ripristinato. Si desidera continuare?" msgid "Debug Reports" msgstr "Report di debug" msgid "Generated Time" msgstr "Ora di creazione" msgid "Generate" msgstr "Crea" msgid "Generating..." msgstr "Creazione in corso..." msgid "Rename" msgstr "Ridenomina" msgid "Download" msgstr "Scarica" msgid "" "Report name should contain only letters, digits, underscore ('_') and/or " "hyphen ('-')." msgstr "" "Il nome del report può contenere solo lettere, cifre e/o trattini ('-')." msgid "Pending..." msgstr "Caricamento in corso..." msgid "Report name is the same as the original one." msgstr "" msgid "" "This will delete the virtual machine and its virtual disks. This operation " "cannot be undone. Would you like to continue?" msgstr "" "L'operazione eliminerà la macchina virtuale e i relativi dischi virtuali e " "non è reversibile. Continuare?" msgid "Power off Confirmation" msgstr "Conferma eliminazione" msgid "" "This action may produce undesirable results, for example unflushed disk " "cache in the guest. Would you like to continue?" msgstr "" msgid "Reset Confirmation" msgstr "Conferma eliminazione" msgid "" "There is a risk of data loss caused by reset without the guest OS shutdown. " "Would you like to continue?" msgstr "" msgid "Shut Down Confirmation" msgstr "Conferma eliminazione" msgid "Note the guest OS may ignore this request. Would you like to continue?" msgstr "L'azione eliminerà permanentemente il modello. Continuare?" msgid "Virtual Machine delete Confirmation" msgstr "" msgid "" "This virtual machine is not persistent. Power Off will delete it. Continue?" msgstr "" msgid "" "When the target guest has SCSI or iSCSI volumes, they will be cloned on " "default storage pool. The same will happen when the target pool does not " "have enough space to clone the volumes. Do you want to continue?" msgstr "" msgid "" "This CDROM will be detached permanently and you can re-attach it. Continue " "to detach it?" msgstr "" "Il CDROM verrà scollegato permanentemente e non sarà possibile ricollegarlo. " "Continuare con lo scollegamento?" msgid "Attaching..." msgstr "Collegamento in corso..." msgid "Replacing..." msgstr "Sostituzione in corso..." msgid "Successfully attached!" msgstr "Collegamento riuscito." msgid "Successfully replaced!" msgstr "Sostituzione riuscita." msgid "Successfully detached!" msgstr "Scollegamento riuscito." msgid "" "This disk will be detached permanently and you can re-attach it. Continue to " "detach it?" msgstr "" msgid "interface:" msgstr "" msgid "address:" msgstr "" msgid "link_type:" msgstr "" msgid "block:" msgstr "" msgid "drive_type:" msgstr "" msgid "model:" msgstr "" msgid "Affected devices:" msgstr "" msgid "The VLAN id must be between 1 and 4094." msgstr "L'ID VLAN deve essere compreso tra 1 e 4094." msgid "unavailable" msgstr "non disponibile" msgid "" "This action will interrupt network connectivity for any virtual machine that " "depend on this network." msgstr "" "L'azione interromperà la connettività di rete per qualsiasi macchina " "virtuale che dipende da questa rete." msgid "Create a network" msgstr "Crea una rete" msgid "" "This network is not persistent. Instead of stop, this action will " "permanently delete it. Would you like to continue?" msgstr "" "Il pool di memoria non è permanente. Invece di disattivarlo, l'azione lo " "eliminerà permanentemente. Continuare?" msgid "" "The bridged VLAN tag may not work well with NetworkManager enabled. You " "should consider disabling it." msgstr "" msgid "" "This will permanently delete the storage pool. Would you like to continue?" msgstr "L'azione eliminerà permanentemente il pool di memoria. Continuare?" msgid "This storage pool is empty." msgstr "Il pool di memoria è vuoto." msgid "" "It will format your disk and you will loose any data in there, are you sure " "to continue? " msgstr "" "Il disco verrà formattato e tutti i dati su di esso andranno persi, sicuri " "di voler continuare? " msgid "SCSI Fibre Channel" msgstr "Canale a fibre ottiche SCSI" msgid "No SCSI adapters found." msgstr "Nessun adattatore SCSI trovato." msgid "Loading iSCSI targets..." msgstr "" msgid "No iSCSI found. Please input one." msgstr "" msgid "Failed to load iSCSI targets." msgstr "" msgid "The storage pool name can not be blank." msgstr "Il campo per il nome del pool di memoria non può essere vuoto." msgid "The storage pool path can not be blank." msgstr "Il campo per il percorso del pool di memoria non può essere vuoto." msgid "NFS server mount path can not be blank." msgstr "" "Il campo per il percorso di montaggio del server NFS non può essere vuoto." msgid "Invalid NFS mount path." msgstr "Percorso di montaggio NFS non valido." msgid "No logical device selected." msgstr "Nessun dispositivo logico selezionato." msgid "The iSCSI target can not be blank." msgstr "Il campo per la destinazione iSCSI non può essere vuoto." msgid "Server name can not be blank." msgstr "Il campo per il nome del server non può essere vuoto." msgid "This is not a valid Server Name or IP. Please, modify it." msgstr "" msgid "Looking for available partitions ..." msgstr "Ricerca di partizioni disponibili in corso..." msgid "No available partitions found." msgstr "Nessuna partizione disponibile trovata." msgid "" "This storage pool is not persistent. Instead of deactivate, this action will " "permanently delete it. Would you like to continue?" msgstr "" "Il pool di memoria non è permanente. Invece di disattivarlo, l'azione lo " "eliminerà permanentemente. Continuare?" msgid "Unable to retrieve partitions information." msgstr "" "Impossibile richiamare le informazioni sul repository. Dettagli: '%(err)s'" msgid "In progress..." msgstr "" msgid "Failed!" msgstr "" msgid "CDROM path needs to be a valid local/remote path and cannot be blank." msgstr "" msgid "Disk pool or volume cannot be blank." msgstr "Il campo per il nome del pool di memoria non può essere vuoto." msgid "Peers" msgstr "" msgid "Searching" msgstr "" msgid "No peers found." msgstr "" msgid "Help" msgstr "Guida" msgid "About" msgstr "Info su" msgid "Log out" msgstr "Disconnetti" msgid "Version:" msgstr "Versione:" msgid "Session timeout, please re-login." msgstr "" msgid "User Name" msgstr "Nome utente" msgid "Password" msgstr "Password" msgid "Generate a New Debug Report" msgstr "Crea un nuovo report di debug" msgid "Report Name" msgstr "Nome report" msgid "" "The name used to identify the report. If omitted, a name will be chosen " "based on current time. Name can contain: letters, digits, underscore (\"_\") " "and hyphen (\"-\")." msgstr "" "Il nome utilizzato per identificare il report. Se il nome viene omesso, ne " "viene scelto uno in base all'ora corrente. Il nome può contenere lettere, " "cifre e trattini (\"-\")." msgid "Rename a Debug Report" msgstr "Crea un nuovo report di debug" msgid "" "The name used to identify the report. Name can contain: letters, digits and " "hyphen (\"-\")." msgstr "" "Il nome utilizzato per identificare il report. Se il nome viene omesso, ne " "viene scelto uno in base all'ora corrente. Il nome può contenere lettere, " "cifre e trattini (\"-\")." msgid "Submit" msgstr "" msgid "Add a Repository" msgstr "Aggiungi un repository" msgid "Identifier" msgstr "Identificativo" msgid "Single word, unique identifier for the repository." msgstr "Identificativo univoco di una sola parola per il repository." msgid "Textual name for the repository." msgstr "Nome in formato testo per il repository." msgid "URL" msgstr "URL" msgid "Required Field" msgstr "Campo obbligatorio" msgid "URL to the repository. Supported protocols are http, ftp, and file." msgstr "URL al repository. I protocolli supportati sono http, ftp e file." msgid "Repository is a mirror" msgstr "Il repository è un elemento speculare." msgid "Distribution" msgstr "Distribuzione" msgid "Distribution of the DEB repository." msgstr "Distribuzione del repository DEB." msgid "Components" msgstr "Componenti" msgid "List of components in DEB repository." msgstr "Elenco di componenti nel repository DEB." msgid "Edit Repository" msgstr "Modifica repository" msgid "Mirror List URL" msgstr "URL elenco elementi speculari" msgid "Yes" msgstr "Sì" msgid "No" msgstr "No" msgid "Add a Volume to Storage Pool" msgstr "" msgid "Fetch from remote URL" msgstr "" msgid "Enter the remote URL here." msgstr "" msgid "Upload a file" msgstr "" msgid "Choose the file you want to upload." msgstr "" msgid "Define a New Storage Pool" msgstr "Definisci un nuovo pool di memoria" msgid "Storage Pool Name" msgstr "Nome pool di memoria" msgid "" "The name used to identify the storage pools, and it should not be empty." msgstr "" "Il nome utilizzato per identificare i pool di memoria; il campo non deve " "essere vuoto." msgid "Storage Pool Type" msgstr "Tipo di pool di memoria" msgid "Storage Path" msgstr "Percorso di memoria" msgid "" "The path of the Storage Pool. Each Storage Pool must have a unique path." msgstr "" "Il percorso del pool di memoria. Ogni pool di memoria deve avere un percorso " "univoco." msgid "" "Kimchi will try to create the directory when it does not already exist in " "your system." msgstr "" "Kimchi tenterà di creare la directory nel caso non esista ancora sul sistema." msgid "NFS Server IP" msgstr "IP server NFS" msgid "NFS server IP or hostname. It can be input or chosen from history." msgstr "" "Il nome host o l'indirizzo IP del server NFS. È possibile immetterlo o " "sceglierlo dalla cronologia." msgid "NFS Path" msgstr "Percorso NFS" msgid "The NFS exported path on NFS server." msgstr "Il percorso esportato NFS sul server NFS." msgid "Device path" msgstr "Percorso dispositivo" msgid "iSCSI Server" msgstr "Server iSCSI" msgid "iSCSI server IP or hostname. It should not be empty." msgstr "" "Il nome host o l'indirizzo IP del server iSCSI. Il campo non deve essere " "vuoto." msgid "Server" msgstr "Server" msgid "Port" msgstr "Porta" msgid "Target" msgstr "Destinazione" msgid "The iSCSI target on iSCSI server" msgstr "La destinazione iSCSI sul server iSCSI" msgid "Add iSCSI Authentication" msgstr "Aggiungi autenticazione iSCSI" msgid "iSCSI Authentication" msgstr "Autenticazione iSCSI" msgid "SCSI Adapter" msgstr "Adattatore SCSI" msgid "Please, wait..." msgstr "Attendere..." msgid "Add Template" msgstr "Aggiungi modello" msgid "Where is the source media for this template? " msgstr "Dov'è il supporto di origine per questo modello?" msgid "Local ISO Image" msgstr "Immagine ISO locale" msgid "Local Image File" msgstr "" msgid "Remote ISO Image" msgstr "Immagine ISO remota" msgid "Search ISOs" msgstr "Ricerca ISO" msgid "The following ISOs are available:" msgstr "Sono disponibili i seguenti file ISO:" msgid "OS: " msgstr "SO: " msgid "Version: " msgstr "Versione: " msgid "Size: " msgstr "Dimensione: " msgid "Search more ISOs" msgstr "Ricerca più ISO" msgid "Create Templates from Selected ISO" msgstr "Crea modelli da ISO selezionato" msgid "I want to use a specific ISO file" msgstr "Utilizzare un file ISO specifico" msgid "Loading default remote ISOs ..." msgstr "Caricamento di ISO remoti predefiniti in corso..." msgid "Arch: " msgstr "Arch: " msgid "I want to use a custom URL" msgstr "Utilizzare un URL personalizzato" msgid "Edit Template" msgstr "Modifica modello" msgid "Processor" msgstr "Processore" msgid "CDROM" msgstr "CDROM" msgid "Image File" msgstr "" msgid "Graphics" msgstr "Grafici" msgid "Disk(GB)" msgstr "" msgid "Disk Format" msgstr "" msgid "CPU Number" msgstr "Numero CPU" msgid "Manually set CPU topology" msgstr "" msgid "Cores" msgstr "" msgid "Threads" msgstr "" msgid "CPU" msgstr "CPU" msgid "Disk I/O" msgstr "I/O disco" msgid "Network I/O" msgstr "I/O di rete" msgid "Livetile" msgstr "Riquadro animato" msgid "No guests found." msgstr "Nessuna macchina guest trovata." msgid "Shut down" msgstr "Arresta" msgid "Restart" msgstr "Riavvia" msgid "Basic Information" msgstr "Informazioni di base" msgid "OS Distro" msgstr "Distro SO" msgid "OS Code Name" msgstr "Nome codice SO" msgid "CPU(s)" msgstr "" msgid "System Statistics" msgstr "Statistiche di sistema" msgid "Update Progress" msgstr "Avanzamento aggiornamento" msgid "Network Name" msgstr "Nome rete" msgid "State" msgstr "Stato" msgid "Network Type" msgstr "Tipo di Rete" msgid "Address Space" msgstr "Spazio indirizzo" msgid "Name should not contain '/' and '\"'." msgstr "Nome pool di memoria non valido. Non deve contenere '/'." msgid "Isolated: no external network connection" msgstr "Isolata: nessuna connessione di rete fisica" msgid "NAT: outbound physical network connection only" msgstr "NAT: solo connessione di rete fisica in uscita" msgid "Bridged: Virtual machines are connected to physical network directly" msgstr "" "Con bridge: le macchine virtuali sono connesse direttamente alla rete fisica" msgid "(No interfaces found)" msgstr "" msgid "Destination" msgstr "Destinazione:" msgid "Enable VLAN" msgstr "Abilita VLAN:" msgid "VLAN ID" msgstr "ID VLAN:" msgid "Stop" msgstr "Arresta" msgid "%Used" msgstr "" msgid "Location" msgstr "Ubicazione" msgid "Capacity" msgstr "Capacità" msgid "Allocated" msgstr "Assegnato" msgid "active" msgstr "attivo" msgid "inactive" msgstr "non attivo" msgid "Deactivate" msgstr "Disattiva" msgid "Activate" msgstr "Attiva" msgid "Add Volume" msgstr "" msgid "Extend" msgstr "" msgid "Undefine" msgstr "Rimuovi definizione" msgid "Format" msgstr "Formato:" msgid "Allocation" msgstr "Allocazione:" msgid "No templates found." msgstr "Nessun modello trovato." kimchi-1.5.0/po/ja_JP.po000066400000000000000000002015171254252253000147300ustar00rootroot00000000000000# English translations for kimchi package. # Copyright (C) 2013 ORGANIZATION # msgid "" msgstr "" "Project-Id-Version: kimchi 0.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-06-24 09:39-0300\n" "PO-Revision-Date: 2013-07-11 17:32-0400\n" "Last-Translator: Crístian Viana \n" "Language-Team: English\n" "Language: ja_JP\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: pygettext.py 1.5\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #, python-format msgid "Unknown parameter %(value)s" msgstr "" #, python-format msgid "Delete is not allowed for %(resource)s" msgstr "%(resource)s ã®å‰Šé™¤ã¯è¨±å¯ã•れã¾ã›ã‚“" #, python-format msgid "%(resource)s does not implement update method" msgstr "%(resource)s ã¯æ›´æ–°ãƒ¡ã‚½ãƒƒãƒ‰ã‚’実装ã—ã¦ã„ã¾ã›ã‚“" #, python-format msgid "Create is not allowed for %(resource)s" msgstr "%(resource)s ã®ä½œæˆã¯è¨±å¯ã•れã¾ã›ã‚“" msgid "Unable to parse JSON request" msgstr "JSON è¦æ±‚ã‚’è§£æžã§ãã¾ã›ã‚“" msgid "This API only supports JSON" msgstr "ã“ã® API 㯠JSON ã®ã¿ã‚µãƒãƒ¼ãƒˆã—ã¾ã™" #, python-format msgid "Parameters does not match requirement in schema: %(err)s" msgstr "" msgid "You don't have permission to perform this operation." msgstr "" msgid "Datastore is not initiated in the model object." msgstr "データ・ストアã¯ã€ãƒ¢ãƒ‡ãƒ«ãƒ»ã‚ªãƒ–ジェクトã§é–‹å§‹ã•れã¦ã„ã¾ã›ã‚“。" #, python-format msgid "Unable to start task due error: %(err)s" msgstr "次ã®ã‚¨ãƒ©ãƒ¼ã®ãŸã‚ã€ã‚¿ã‚¹ã‚¯ã‚’é–‹å§‹ã§ãã¾ã›ã‚“: %(err)s" #, python-format msgid "Timeout of %(seconds)s seconds expired while running task '%(task)s." msgstr "" #, python-format msgid "Authentication failed for user '%(username)s'. [Error code: %(code)s]" msgstr "" "ユーザー「%(username)sã€ã®èªè¨¼ã«å¤±æ•—ã—ã¾ã—ãŸã€‚[エラー・コード: %(code)s]" msgid "You are not authorized to access Kimchi" msgstr "Kimchi ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’許å¯ã•れã¦ã„ã¾ã›ã‚“" #, python-format msgid "Specify %(item)s to login into Kimchi" msgstr "Kimchi ã«ãƒ­ã‚°ã‚¤ãƒ³ã™ã‚‹ã«ã¯ã€%(item)s を指定ã—ã¾ã™" #, python-format msgid "User %(user_id)s not found with given LDAP settings." msgstr "" #, python-format msgid "Invalid LDAP configuration: %(item)s : %(value)s" msgstr "" msgid "Unknown \"_cap\" specified" msgstr "" msgid "\"_passthrough\" should be \"true\" or \"false\"" msgstr "" msgid "\"_passthrough_affected_by\" should be a device name string" msgstr "" #, python-format msgid "Error while getting block devices. Details: %(err)s" msgstr "" "ブロック・デãƒã‚¤ã‚¹ã‚’å–å¾—ã—ã¦ã„ã‚‹ã¨ãã«ã€ã‚¨ãƒ©ãƒ¼ãŒã‚りã¾ã—ãŸã€‚詳細: %(err)s" #, python-format msgid "Error while getting block device information for %(device)s." msgstr "" "%(device)s ã®ãƒ–ロック・デãƒã‚¤ã‚¹æƒ…報をå–å¾—ã—ã¦ã„ã‚‹ã¨ãã«ã€ã‚¨ãƒ©ãƒ¼ãŒã‚りã¾ã—ãŸã€‚" #, python-format msgid "Unable to find distro file: %(filename)s" msgstr "ディストリビューション・ファイル %(filename)s ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" #, python-format msgid "" "Unable to parse distro file: %(filename)s. Make sure, it is a JSON file." msgstr "" "ディストリビューション・ファイル %(filename)s ã‚’è§£æžã§ãã¾ã›ã‚“。JSON ファイル" "ã§ã‚ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。" #, python-format msgid "Unable to login to iSCSI host target %(portal)s. Details: %(err)s" msgstr "" "iSCSI ホスト・ターゲット %(portal)s ã«ãƒ­ã‚°ã‚¤ãƒ³ã§ãã¾ã›ã‚“。詳細: %(err)s" #, python-format msgid "Unable to login to iSCSI host %(host)s target %(target)s" msgstr "iSCSI ホスト %(host)s ターゲット %(target)s ã«ãƒ­ã‚°ã‚¤ãƒ³ã§ãã¾ã›ã‚“" #, python-format msgid "Unable to find ISO file %(filename)s" msgstr "" #, python-format msgid "The ISO file %(filename)s is not bootable" msgstr "ISO ファイル %(filename)s ã¯ã€ãƒ–ートå¯èƒ½ã§ã¯ã‚りã¾ã›ã‚“" #, python-format msgid "The ISO file %(filename)s does not have a valid El Torito boot record" msgstr "" "ISO ファイル %(filename)s ã«ã¯ã€æœ‰åŠ¹ãª El Torito ブート・レコードãŒã‚りã¾ã›ã‚“" #, python-format msgid "Invalid El Torito validation entry in ISO %(filename)s" msgstr "無効㪠El Torito 検証エントリー㌠ISO %(filename)s ã«ã‚りã¾ã™" #, python-format msgid "Invalid El Torito boot indicator in ISO %(filename)s" msgstr "無効㪠El Torito ブート・インジケーター㌠ISO %(filename)s ã«ã‚りã¾ã™" #, python-format msgid "Unexpected volume type for primary volume in ISO %(filename)s" msgstr "" "1 次ボリュームã®äºˆæœŸã—ãªã„ボリューム・タイプ㌠ISO %(filename)s ã«ã‚りã¾ã™" #, python-format msgid "Bad format while reading volume descriptor in ISO %(filename)s" msgstr "" "ボリューム・ディスクリプターを ISO %(filename)s ã‹ã‚‰èª­ã¿å–ã£ã¦ã„ã¾ã—ãŸãŒã€" "フォーマットãŒä¸æ­£ã§ã—ãŸ" #, python-format msgid "" "The hypervisor doesn't have permission to use this ISO %(filename)s. " "Consider moving it under /var/lib/libvirt, or set the search permission to " "file access control lists for '%(user)s' user if possible, or add the " "'%(user)s' to the ISO path group, or (not recommended) 'chmod -R o+x " "'path_to_iso'.Details: %(err)s" msgstr "" "ãƒã‚¤ãƒ‘ーãƒã‚¤ã‚¶ãƒ¼ã«ã“ã® ISO %(filename)s を使用ã™ã‚‹æ¨©é™ãŒã‚りã¾ã›ã‚“。/var/lib/" "libvirt ã®ä¸‹ã«ç§»å‹•ã™ã‚‹ã‹ã€å¯èƒ½ã§ã‚ã‚Œã°æ¤œç´¢è¨±å¯ã‚’「%(user)sã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ãƒ•ァイ" "ル・アクセス制御リストã«è¨­å®šã™ã‚‹ã‹ã€ã€Œ%(user)sã€ã‚’ISO パス・グループã«è¿½åŠ ã™" "ã‚‹ã‹ã€ã¾ãŸã¯ã€Œchmod -R o+x path_to_isoã€ã‚’実行 (推奨ã•れã¾ã›ã‚“) ã—ã¦ãã ã•" "ã„。詳細: %(err)s" msgid "An error occurred when probing image OS information." msgstr "" msgid "No OS information found in given image." msgstr "" #, python-format msgid "Unable to read image file %(filename)s" msgstr "" #, python-format msgid "" "Image file must be an existing file on system. %(filename)s is not a valid " "input." msgstr "" #, python-format msgid "Virtual machine %(name)s already exists" msgstr "仮想マシン %(name)s ã¯æ—¢ã«å­˜åœ¨ã—ã¾ã™" #, python-format msgid "Virtual machine %(name)s does not exist" msgstr "仮想マシン %(name)s ã¯å­˜åœ¨ã—ã¾ã›ã‚“" #, python-format msgid "" "Unable to rename virtual machine %(name)s. The name %(new_name)s is already " "in use or the virtual machine is not powered off." msgstr "" #, python-format msgid "Unable to retrieve screenshot for stopped virtual machine %(name)s" msgstr "åœæ­¢ã—ã¦ã„る仮想マシン %(name)s ã®ã‚¹ã‚¯ãƒªãƒ¼ãƒ³ãƒ»ã‚·ãƒ§ãƒƒãƒˆã‚’å–å¾—ã§ãã¾ã›ã‚“" msgid "Remote ISO image is not supported by this server." msgstr "リモート ISO イメージã¯ã€ã“ã®ã‚µãƒ¼ãƒãƒ¼ã§ã¯ã‚µãƒãƒ¼ãƒˆã•れã¦ã„ã¾ã›ã‚“。" #, python-format msgid "Screenshot is not supported on virtual machine %(name)s" msgstr "" #, python-format msgid "Unable to create virtual machine %(name)s. Details: %(err)s" msgstr "仮想マシン %(name)s を作æˆã§ãã¾ã›ã‚“。詳細: %(err)s" #, python-format msgid "Unable to update virtual machine %(name)s. Details: %(err)s" msgstr "仮想マシン %(name)s を作æˆã§ãã¾ã›ã‚“。詳細: %(err)s" #, python-format msgid "Unable to retrieve virtual machine %(name)s. Details: %(err)s" msgstr "仮想マシン %(name)s ã‚’å–å¾—ã§ãã¾ã›ã‚“。詳細: %(err)s" #, python-format msgid "Unable to connect to powered off virtual machine %(name)s." msgstr "" msgid "Virtual machine name must be a string without slashes (/)" msgstr "" #, python-format msgid "Invalid template URI %(value)s specified for virtual machine" msgstr "" #, python-format msgid "Invalid storage pool URI %(value)s specified for virtual machine" msgstr "" msgid "Supported virtual machine graphics are Spice or VNC" msgstr "" msgid "Graphics address to listen on must be IPv4 or IPv6" msgstr "" "listen を行ã†ã‚°ãƒ©ãƒ•ィックス・アドレスã¯ã€IPv4 ã¾ãŸã¯ IPv6 ã§ãªã‘れã°ãªã‚Šã¾ã›" "ã‚“" msgid "Specify a template to create a virtual machine from" msgstr "仮想マシンã®ä½œæˆå…ƒã¨ãªã‚‹ãƒ†ãƒ³ãƒ—レートを指定ã—ã¦ãã ã•ã„" #, python-format msgid "Unable to start virtual machine %(name)s. Details: %(err)s" msgstr "仮想マシン %(name)s ã‚’å§‹å‹•ã§ãã¾ã›ã‚“。詳細: %(err)s" #, python-format msgid "Unable to power off virtual machine %(name)s. Details: %(err)s" msgstr "仮想マシン %(name)s ã‚’åœæ­¢ã§ãã¾ã›ã‚“。詳細: %(err)s" #, python-format msgid "Unable to delete virtual machine %(name)s. Details: %(err)s" msgstr "仮想マシン %(name)s を削除ã§ãã¾ã›ã‚“。詳細: %(err)s" #, python-format msgid "Unable to reset virtual machine %(name)s. Details: %(err)s" msgstr "仮想マシン %(name)s ã‚’åå‰å¤‰æ›´ã§ãã¾ã›ã‚“。詳細: %(err)s" msgid "User name list must be an array" msgstr "" msgid "User name must be a string" msgstr "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯åã¯ã‚¹ãƒˆãƒªãƒ³ã‚°ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“" msgid "Group name list must be an array" msgstr "" msgid "Group name must be a string" msgstr "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯åã¯ã‚¹ãƒˆãƒªãƒ³ã‚°ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“" #, python-format msgid "User(s) '%(users)s' do not exist" msgstr "ユーザー「%(users)sã€ã¯å­˜åœ¨ã—ã¾ã›ã‚“。" #, python-format msgid "Group(s) '%(groups)s' do not exist" msgstr "ユーザー「%(groups)sã€ã¯å­˜åœ¨ã—ã¾ã›ã‚“。" #, python-format msgid "Unable to shutdown virtual machine %(name)s. Details: %(err)s" msgstr "仮想マシン %(name)s ã‚’åœæ­¢ã§ãã¾ã›ã‚“。詳細: %(err)s" #, python-format msgid "" "Unable to get access metadata of virtual machine %(name)s. Details: %(err)s" msgstr "仮想マシン %(name)s ã‚’å§‹å‹•ã§ãã¾ã›ã‚“。詳細: %(err)s" msgid "The guest console password must be a string." msgstr "" msgid "The life time for the guest console password must be a number." msgstr "" #, python-format msgid "Virtual machine '%(name)s' must be stopped before cloning it." msgstr "" #, python-format msgid "Insufficient disk space to clone virtual machine '%(name)s'" msgstr "" #, python-format msgid "Unable to clone VM '%(name)s'. Details: %(err)s" msgstr "" #, python-format msgid "Invalid operation for non-persistent virtual machine %(name)s" msgstr "" #, python-format msgid "Cannot suspend VM '%(name)s' because it is not running." msgstr "" #, python-format msgid "Unable to suspend VM '%(name)s'. Details: %(err)s" msgstr "" #, python-format msgid "Cannot resume VM '%(name)s' because it is not paused." msgstr "" #, python-format msgid "Unable to resume VM '%(name)s'. Details: %(err)s" msgstr "" msgid "Memory assigned is higher then the maximum allowed in the host." msgstr "" #, python-format msgid "" "VM '%(name)s' does not support live memory update. Update the memory with " "the machine offline to enable this feature." msgstr "" msgid "Only increase memory is allowed in active VMs" msgstr "" msgid "" "For live memory update, new memory value must be equal old memory value plus " "multiples of 1024 Mib" msgstr "" msgid "There are not enough free slots of 1024 Mib in the guest." msgstr "" msgid "" "Host's libvirt version does not support memory devices. Libvirt must be >= " "1.2.14" msgstr "" #, python-format msgid "Error attaching memory device. Details: %(error)s" msgstr "" #, python-format msgid "" "VM %(vmid)s does not contain directly assigned host device %(dev_name)s." msgstr "" #, python-format msgid "The host device %(dev_name)s is not allowed to directly assign to VM." msgstr "" msgid "" "No IOMMU groups found. Host PCI pass through needs IOMMU group to function " "correctly. Please enable Intel VT-d or AMD IOMMU in your BIOS, then verify " "the Kernel is compiled with IOMMU support. For Intel CPU, add intel_iommu=on " "to your Kernel parameter in /boot/grub2/grub.conf. For AMD CPU, add iommu=pt " "iommu=1." msgstr "" msgid "\"name\" should be a device name string" msgstr "" #, python-format msgid "" "The device %(name)s is probably in use by the host. Unable to attach it to " "the guest." msgstr "" #, python-format msgid "Interface %(iface)s does not exist in virtual machine %(name)s" msgstr "インターフェース %(iface)s ã¯ä»®æƒ³ãƒžã‚·ãƒ³ %(name)s ã«ã¯å­˜åœ¨ã—ã¾ã›ã‚“" #, python-format msgid "" "Network %(network)s specified for virtual machine %(name)s does not exist" msgstr "" "仮想マシン %(name)s ç”¨ã«æŒ‡å®šã•れã¦ã„ã‚‹ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ %(network)s ã¯å­˜åœ¨ã—ã¾ã›ã‚“" msgid "Supported virtual machine interfaces type is only network" msgstr "" "サãƒãƒ¼ãƒˆã•れã¦ã„る仮想マシン・インターフェース・タイプã¯ã€ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã ã‘ã§" "ã™" msgid "Network name for virtual machine interface must be a string" msgstr "" "仮想マシン・インターフェースã®ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯åã¯ã‚¹ãƒˆãƒªãƒ³ã‚°ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“" msgid "Invalid network model card specified for virtual machine interface" msgstr "" "無効ãªãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ãƒ»ãƒ¢ãƒ‡ãƒ«ãƒ»ã‚«ãƒ¼ãƒ‰ãŒä»®æƒ³ãƒžã‚·ãƒ³ãƒ»ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ãƒ¼ã‚¹ã«æŒ‡å®šã•れã¦" "ã„ã¾ã™" msgid "Specify type and network to add a new virtual machine interface" msgstr "" "æ–°ã—ã„仮想マシン・インターフェースã«è¿½åŠ ã™ã‚‹ã‚¿ã‚¤ãƒ—ãŠã‚ˆã³ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚’指定ã—" "ã¾ã™" msgid "MAC Address must respect this format FF:FF:FF:FF:FF:FF" msgstr "" #, python-format msgid "MAC Address %(mac)s already exists in virtual machine %(name)s" msgstr "" msgid "Invalid MAC Address" msgstr "" msgid "Cannot change MAC address of a running virtual machine" msgstr "" #, python-format msgid "Template %(name)s already exists" msgstr "テンプレート %(name)s ã¯æ—¢ã«å­˜åœ¨ã—ã¾ã™" #, python-format msgid "" "Network '%(network)s' specified for template %(template)s does not exist" msgstr "" "テンプレート %(template)s ç”¨ã«æŒ‡å®šã•れã¦ã„ã‚‹ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã€Œ%(network)sã€ã¯å­˜åœ¨" "ã—ã¾ã›ã‚“" #, python-format msgid "" "Storage pool %(pool)s specified for template %(template)s does not exist" msgstr "" "テンプレート %(template)s ç”¨ã«æŒ‡å®šã•れã¦ã„るストレージ・プール %(pool)s ã¯å­˜" "在ã—ã¾ã›ã‚“" #, python-format msgid "Storage pool %(pool)s specified for template %(template)s is not active" msgstr "" "テンプレート %(template)s ç”¨ã«æŒ‡å®šã•れã¦ã„るストレージ・プール %(pool)s ã¯ã‚¢" "クティブã§ã¯ã‚りã¾ã›ã‚“" #, python-format msgid "Invalid parameter '%(param)s' specified for CDROM." msgstr "CDROM ã«æŒ‡å®šã•れã¦ã„るパラメーター「%(param)sã€ã¯ç„¡åйã§ã™ã€‚" #, python-format msgid "Network %(network)s specified for template %(template)s is not active" msgstr "" "テンプレート %(template)s ç”¨ã«æŒ‡å®šã•れã¦ã„ã‚‹ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ %(network)s ã¯ã‚¢ã‚¯" "ティブã§ã¯ã‚りã¾ã›ã‚“" msgid "Template name must be a string" msgstr "テンプレートåã¯ã‚¹ãƒˆãƒªãƒ³ã‚°ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“" msgid "Template icon must be a path to the image" msgstr "テンプレート・アイコンã¯ã‚¤ãƒ¡ãƒ¼ã‚¸ã®ãƒ‘スã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“" msgid "Template distribution must be a string" msgstr "テンプレート・ディストリビューションã¯ã‚¹ãƒˆãƒªãƒ³ã‚°ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“" msgid "Template distribution version must be a string" msgstr "" "テンプレート・ディストリビューション・ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã¯ã‚¹ãƒˆãƒªãƒ³ã‚°ã§ãªã‘れã°ãªã‚Šã¾" "ã›ã‚“" msgid "The number of CPUs must be an integer greater than 0" msgstr "CPU æ•°ã¯æ•´æ•°ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“" msgid "Amount of memory (MB) must be an integer greater than 512" msgstr "メモリーã®é‡ (MB å˜ä½) ã¯ã€512 より大ãã„æ•´æ•°ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“" msgid "Template CDROM must be a local or remote ISO file" msgstr "" "テンプレート CDROM ã¯ã€ãƒ­ãƒ¼ã‚«ãƒ«ã¾ãŸã¯ãƒªãƒ¢ãƒ¼ãƒˆ ISO ファイルã§ãªã‘れã°ãªã‚Šã¾ã›" "ã‚“" #, python-format msgid "Invalid storage pool URI %(value)s specified for template" msgstr "" "無効ãªã‚¹ãƒˆãƒ¬ãƒ¼ã‚¸ãƒ»ãƒ—ール URI %(value)s ãŒãƒ†ãƒ³ãƒ—ãƒ¬ãƒ¼ãƒˆã«æŒ‡å®šã•れã¦ã„ã¾ã™" msgid "Specify an ISO image as CDROM or a base image to create a template" msgstr "" "CDROM ã¨ã—ã¦ã€ãƒ†ãƒ³ãƒ—レートを作æˆã™ã‚‹ãŸã‚ã® ISO イメージを指定ã—ã¦ãã ã•ã„" msgid "All networks for the template must be specified in a list." msgstr "テンプレート用ã®ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚’ã™ã¹ã¦ãƒªã‚¹ãƒˆã«æŒ‡å®šã™ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚" msgid "Specify a volume to a template when storage pool is iSCSI or SCSI" msgstr "" #, python-format msgid "The volume %(volume)s is not in storage pool %(pool)s" msgstr "" #, python-format msgid "Unable to create template due error: %(err)s" msgstr "次ã®ã‚¨ãƒ©ãƒ¼ã®ãŸã‚ã€ãƒ†ãƒ³ãƒ—レートを作æˆã§ãã¾ã›ã‚“: %(err)s" #, python-format msgid "Unable to delete template due error: %(err)s" msgstr "次ã®ã‚¨ãƒ©ãƒ¼ã®ãŸã‚ã€ãƒ†ãƒ³ãƒ—レートを削除ã§ãã¾ã›ã‚“: %(err)s" msgid "Disk size must be an integer greater than 1GB." msgstr "" msgid "Template base image must be a valid local image file" msgstr "" "テンプレート CDROM ã¯ã€ãƒ­ãƒ¼ã‚«ãƒ«ã¾ãŸã¯ãƒªãƒ¢ãƒ¼ãƒˆ ISO ファイルã§ãªã‘れã°ãªã‚Šã¾ã›" "ã‚“" #, python-format msgid "Cannot identify base image %(path)s format" msgstr "" msgid "" "When specifying CPU topology, VCPUs must be a product of sockets, cores, and " "threads." msgstr "" msgid "" "When specifying CPU topology, each element must be an integer greater than " "zero." msgstr "" msgid "" "Invalid disk image format. Valid formats: bochs, cloop, cow, dmg, qcow, " "qcow2, qed, raw, vmdk, vpc." msgstr "" #, python-format msgid "Storage pool %(name)s already exists" msgstr "ストレージ・プール %(name)s ã¯æ—¢ã«å­˜åœ¨ã—ã¾ã™" #, python-format msgid "Storage pool %(name)s does not exist" msgstr "ストレージ・プール %(name)s ã¯å­˜åœ¨ã—ã¾ã›ã‚“" #, python-format msgid "Specify %(item)s in order to create the storage pool %(name)s" msgstr "" "ストレージ・プール %(name)s を作æˆã™ã‚‹ãŸã‚ã«ã¯ã€%(item)s を指定ã—ã¦ãã ã•ã„" #, python-format msgid "Unable to delete active storage pool %(name)s" msgstr "アクティブ・ストレージ・プール %(name)s ã¯å‰Šé™¤ã§ãã¾ã›ã‚“" #, python-format msgid "Unable to list storage pools. Details: %(err)s" msgstr "ストレージ・プールをリストã§ãã¾ã›ã‚“。詳細: %(err)s" #, python-format msgid "Unable to create storage pool %(name)s. Details: %(err)s" msgstr "ストレージ・プール %(name)s を作æˆã§ãã¾ã›ã‚“。詳細: %(err)s" #, python-format msgid "" "Unable to get number of storage volumes in storage pool %(name)s. Details: " "%(err)s" msgstr "" "ストレージ・プール %(name)s ã®ã‚¹ãƒˆãƒ¬ãƒ¼ã‚¸ãƒ»ãƒœãƒªãƒ¥ãƒ¼ãƒ ã®æ•°ã‚’å–å¾—ã§ãã¾ã›ã‚“。詳" "ç´°:%(err)s" #, python-format msgid "Unable to activate storage pool %(name)s. Details: %(err)s" msgstr "ストレージ・プール %(name)s をアクティブã«ã§ãã¾ã›ã‚“。詳細: %(err)s" #, python-format msgid "Unable to deactivate storage pool %(name)s. Details: %(err)s" msgstr "ストレージ・プール %(name)s ã‚’éžã‚¢ã‚¯ãƒ†ã‚£ãƒ–ã«ã§ãã¾ã›ã‚“。詳細: %(err)s" #, python-format msgid "Unable to delete storage pool %(name)s. Details: %(err)s" msgstr "ストレージ・プール %(name)s を削除ã§ãã¾ã›ã‚“。詳細: %(err)s" #, python-format msgid "" "Unable to create NFS Pool as export path %(path)s may block during mount" msgstr "" "マウント中ã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆãƒ»ãƒ‘ス %(path)s ãŒãƒ–ロックã•れã¦ã„ãŸå¯èƒ½æ€§ãŒã‚ã‚‹ãŸ" "ã‚ã€NFS プールを作æˆã§ãã¾ã›ã‚“" #, python-format msgid "Unable to create NFS Pool as export path %(path)s mount failed" msgstr "" "エクスãƒãƒ¼ãƒˆãƒ»ãƒ‘ス %(path)s ã®ãƒžã‚¦ãƒ³ãƒˆã«å¤±æ•—ã—ãŸãŸã‚ã€NFS プールを作æˆã§ãã¾" "ã›ã‚“" #, python-format msgid "Unsupported storage pool type: %(type)s" msgstr "サãƒãƒ¼ãƒˆã•れã¦ã„ãªã„ストレージ・プール・タイプ: %(type)s" #, python-format msgid "Error while retrieving storage pool XML to %(pool)s" msgstr "" msgid "Storage pool name must be a string without slashes (/)" msgstr "" msgid "" "Supported storage pool types are dir, netfs, logical, iscsi, isci and kimchi-" "iso" msgstr "" msgid "Storage pool path must be a string" msgstr "ストレージ・プール・パスã¯ã‚¹ãƒˆãƒªãƒ³ã‚°ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“" msgid "Storage pool host must be a IP or hostname" msgstr "ストレージ・プール・ホストã¯ã€IP ã¾ãŸã¯ãƒ›ã‚¹ãƒˆåã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“" msgid "Storage pool device must be the absolute path to the block device" msgstr "" msgid "Storage pool devices parameter must be a list" msgstr "ストレージ・プール・デãƒã‚¤ã‚¹ãƒ»ãƒ‘ラメーターã¯ãƒªã‚¹ãƒˆã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“" msgid "Target IQN of an iSCSI pool must be a string" msgstr "iSCSI プールã®ã‚¿ãƒ¼ã‚²ãƒƒãƒˆ IQN ã¯ã‚¹ãƒˆãƒªãƒ³ã‚°ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“" msgid "Port of a remote storage server must be an integer between 1 and 65535" msgstr "" "リモート・ストレージ・サーãƒãƒ¼ã®ãƒãƒ¼ãƒˆã¯ã€1 ã‹ã‚‰ 65535 ã¾ã§ã®æ•´æ•°ã§ãªã‘れã°ãª" "りã¾ã›ã‚“" msgid "iSCSI target username must be a string" msgstr "" msgid "iSCSI target password must be a string" msgstr "" msgid "Specify name and type to create a storage pool" msgstr "ストレージ・プールを作æˆã™ã‚‹ã«ã¯ã€åå‰ã¨ã‚¿ã‚¤ãƒ—を指定ã—ã¦ãã ã•ã„" #, python-format msgid "" "%(disk)s is not a valid disk/partition. Could not add it to the pool " "%(pool)s." msgstr "" "%(disk)s ã¯ã€æœ‰åйãªãƒ‡ã‚£ã‚¹ã‚¯/パーティションã§ã¯ãªã„ãŸã‚ã€ãƒ—ール %(pool)s ã«è¿½" "加ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚" #, python-format msgid "Unable to extend logical pool %(pool)s. Details: %(err)s" msgstr "" msgid "The parameter disks only can be updated for logical storage pool." msgstr "" "è«–ç†ã‚¹ãƒˆãƒ¬ãƒ¼ã‚¸ãƒ»ãƒ—ãƒ¼ãƒ«ã‚’å¯¾è±¡ã«æ›´æ–°ã§ãã‚‹ã®ã¯ã€ãƒ‘ラメーター・ディスクã ã‘ã§" "ã™ã€‚" msgid "The SCSI host adapter name must be a string." msgstr "SCSI ホスト・アダプターåã¯ã‚¹ãƒˆãƒªãƒ³ã‚°ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“。" msgid "The storage pool kimchi_isos is reserved for internal use" msgstr "ストレージ・プール kimchi_isos ã¯ã€å†…部使用ã®ãŸã‚ã«äºˆç´„ã•れã¦ã„ã¾ã™" #, python-format msgid "" "Unable to activate NFS storage pool %(name)s. NFS server %(server)s is " "unreachable." msgstr "" "NFS ストレージ・プール %(name)s をアクティブã«ã§ãã¾ã›ã‚“。NFS サーãƒãƒ¼ " "%(server)s ã«åˆ°é”ã§ãã¾ã›ã‚“。" #, python-format msgid "" "Unable to deactivate NFS storage pool %(name)s. NFS server %(server)s is " "unreachable." msgstr "" "NFS ストレージ・プール %(name)s ã‚’éžã‚¢ã‚¯ãƒ†ã‚£ãƒ–ã«ã§ãã¾ã›ã‚“。NFS サーãƒãƒ¼ " "%(server)s ã«åˆ°é”ã§ãã¾ã›ã‚“。" #, python-format msgid "" "Unable to deactivate pool %(name)s as it is associated with some templates" msgstr "" "プール %(name)s ã¯ã„ãã¤ã‹ã®ãƒ†ãƒ³ãƒ—レートã«é–¢é€£ä»˜ã‘られã¦ã„ã‚‹ãŸã‚ã€éžã‚¢ã‚¯ãƒ†ã‚£" "ブã«ã§ãã¾ã›ã‚“" #, python-format msgid "Unable to delete pool %(name)s as it is associated with some templates" msgstr "" "プール %(name)s ã¯ã„ãã¤ã‹ã®ãƒ†ãƒ³ãƒ—レートã«é–¢é€£ä»˜ã‘られã¦ã„ã‚‹ãŸã‚ã€å‰Šé™¤ã§ãã¾" "ã›ã‚“" #, python-format msgid "" "A volume group named '%(name)s' already exists. Please, choose another name " "to create the logical pool." msgstr "" "åå‰ã€Œ%(name)sã€ã®ãƒœãƒªãƒ¥ãƒ¼ãƒ ãƒ»ã‚°ãƒ«ãƒ¼ãƒ—ã¯æ—¢ã«å­˜åœ¨ã—ã¾ã™ã€‚è«–ç†ãƒ—ールを作æˆã™ã‚‹" "ã«ã¯ã€åˆ¥ã®åå‰ã‚’é¸æŠžã—ã¦ãã ã•ã„。" #, python-format msgid "Unable to update database with deep scan information due error: %(err)s" msgstr "" "次ã®ã‚¨ãƒ©ãƒ¼ã®ãŸã‚ã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’ãƒ‡ã‚£ãƒ¼ãƒ—ãƒ»ã‚¹ã‚­ãƒ£ãƒ³æƒ…å ±ã§æ›´æ–°ã§ãã¾ã›ã‚“: " "%(err)s" #, python-format msgid "Storage volume %(name)s already exists" msgstr "ストレージ・ボリューム %(name)s ã¯æ—¢ã«å­˜åœ¨ã—ã¾ã™" #, python-format msgid "Storage volume %(name)s does not exist in storage pool %(pool)s" msgstr "" "ストレージ・ボリューム %(name)s ã¯ã€ã‚¹ãƒˆãƒ¬ãƒ¼ã‚¸ãƒ»ãƒ—ール %(pool)s ã«å­˜åœ¨ã—ã¾ã›" "ã‚“" #, python-format msgid "" "Unable to create storage volume %(volume)s because storage pool %(pool)s is " "not active" msgstr "" #, python-format msgid "Specify %(item)s in order to create storage volume %(volume)s" msgstr "" "ストレージ・ボリューム %(volume)s を作æˆã™ã‚‹ãŸã‚ã«ã¯ã€%(item)s を指定ã—ã¦ãã " "ã•ã„" #, python-format msgid "" "Unable to list storage volumes because storage pool %(pool)s is not active" msgstr "" "ストレージ・プール %(pool)s ãŒã‚¢ã‚¯ãƒ†ã‚£ãƒ–ã§ã¯ãªã„ãŸã‚ã€ã‚¹ãƒˆãƒ¬ãƒ¼ã‚¸ãƒ»ãƒœãƒªãƒ¥ãƒ¼ãƒ " "をリストã§ãã¾ã›ã‚“" #, python-format msgid "" "Unable to create storage volume %(name)s in storage pool %(pool)s. Details: " "%(err)s" msgstr "" "ストレージ・ボリューム %(name)s をストレージ・プール %(pool)s ã«ä½œæˆã§ãã¾ã›" "ん。詳細: %(err)s" #, python-format msgid "" "Unable to list storage volumes in storage pool %(pool)s. Details: %(err)s" msgstr "" "ストレージ・プール %(pool)s ã®ã‚¹ãƒˆãƒ¬ãƒ¼ã‚¸ãƒ»ãƒœãƒªãƒ¥ãƒ¼ãƒ ã‚’リストã§ãã¾ã›ã‚“。詳" "ç´°: %(err)s" #, python-format msgid "Unable to wipe storage volumes %(name)s. Details: %(err)s" msgstr "ストレージ・プール %(name)s をワイプã§ãã¾ã›ã‚“。詳細: %(err)s" #, python-format msgid "Unable to delete storage volume %(name)s. Details: %(err)s" msgstr "ストレージ・ボリューム %(name)s を削除ã§ãã¾ã›ã‚“。詳細: %(err)s" #, python-format msgid "Unable to resize storage volume %(name)s. Details: %(err)s" msgstr "ストレージ・ボリューム %(name)s をサイズ変更ã§ãã¾ã›ã‚“。詳細: %(err)s" #, python-format msgid "Storage type %(type)s does not support volume create and delete" msgstr "" "ストレージ・タイプ %(type)s ã§ã¯ã€ãƒœãƒªãƒ¥ãƒ¼ãƒ ä½œæˆãŠã‚ˆã³å‰Šé™¤ã¯ã‚µãƒãƒ¼ãƒˆã•れã¦ã„" "ã¾ã›ã‚“" msgid "Storage volume name must be a string" msgstr "ストレージ・ボリュームåã¯ã‚¹ãƒˆãƒªãƒ³ã‚°ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“" msgid "Storage volume allocation must be an integer number" msgstr "ã‚¹ãƒˆãƒ¬ãƒ¼ã‚¸ãƒ»ãƒœãƒªãƒ¥ãƒ¼ãƒ å‰²ã‚ŠæŒ¯ã‚Šã¯æ•´æ•°ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“" msgid "" "Storage volume format not supported. Valid formats: bochs, cloop, cow, dmg, " "qcow, qcow2, qed, raw, vmdk, vpc." msgstr "" msgid "Storage volume requires a volume name" msgstr "ストレージ・ボリュームã«ã¯ãƒœãƒªãƒ¥ãƒ¼ãƒ åãŒå¿…è¦ã§ã™" #, python-format msgid "" "Unable to update database with storage volume information due error: %(err)s" msgstr "" "次ã®ã‚¨ãƒ©ãƒ¼ã®ãŸã‚ã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’ã‚¹ãƒˆãƒ¬ãƒ¼ã‚¸ãƒ»ãƒœãƒªãƒ¥ãƒ¼ãƒ æƒ…å ±ã§æ›´æ–°ã§ãã¾ã›ã‚“: " "%(err)s" #, python-format msgid "Only one of parameter %(param)s can be specified" msgstr "" #, python-format msgid "Create volume from %(param)s is not supported" msgstr "" msgid "Storage volume capacity must be an integer number." msgstr "" msgid "Storage volume URL must be http://, https://, ftp:// or ftps://." msgstr "" #, python-format msgid "Unable to access file %(url)s. Please, check it." msgstr "" #, python-format msgid "" "Unable to clone storage volume '%(name)s' in pool '%(pool)s'. Details: " "%(err)s" msgstr "" msgid "Specify chunk data and its size to upload a file." msgstr "" msgid "In order to upload a storage volume, specify the 'upload' parameter." msgstr "" msgid "" "Unable to upload chunk data as it does not match with requested chunk size." msgstr "" #, python-format msgid "The storage volume %(vol)s is not under an upload process." msgstr "" msgid "The upload chunk data will exceed the storage volume size." msgstr "" #, python-format msgid "Unable to upload chunk data to storage volume. Details: %(err)s." msgstr "" #, python-format msgid "Interface %(name)s does not exist" msgstr "インターフェース %(name)s ã¯å­˜åœ¨ã—ã¾ã›ã‚“" #, python-format msgid "Network %(name)s already exists" msgstr "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ %(name)s ã¯æ—¢ã«å­˜åœ¨ã—ã¾ã™" #, python-format msgid "Network %(name)s does not exist" msgstr "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ %(name)s ã¯å­˜åœ¨ã—ã¾ã›ã‚“" #, python-format msgid "Subnet %(subnet)s specified for network %(network)s is not valid." msgstr "" "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ %(network)s ç”¨ã«æŒ‡å®šã•れã¦ã„るサブãƒãƒƒãƒˆ %(subnet)s ã¯ç„¡åйã§ã™ã€‚" #, python-format msgid "Specify a network interface to create bridged network %(name)s" msgstr "" "ブリッジ接続ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ %(name)s を作æˆã™ã‚‹ã«ã¯ã€ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ãƒ»ã‚¤ãƒ³ã‚¿ãƒ¼" "フェースを指定ã—ã¦ãã ã•ã„" #, python-format msgid "Unable to delete active network %(name)s" msgstr "アクティブ・ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ %(name)s ã¯å‰Šé™¤ã§ãã¾ã›ã‚“" #, python-format msgid "Interface %(iface)s specified for network %(network)s is already in use" msgstr "" "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ %(network)s ç”¨ã«æŒ‡å®šã•れã¦ã„るインターフェース %(iface)s ã¯ã€æ—¢" "ã«ä½¿ç”¨ã•れã¦ã„ã¾ã™" msgid "Interface should be bare NIC, bonding or bridge device." msgstr "" "インターフェースã¯ãƒ™ã‚¢ NICã€çµåˆã€ã¾ãŸã¯ãƒ–リッジ・デãƒã‚¤ã‚¹ã§ãªã‘れã°ãªã‚Šã¾ã›" "ん。" #, python-format msgid "Unable to create network %(name)s. Details: %(err)s" msgstr "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ %(name)s を作æˆã§ãã¾ã›ã‚“。詳細: %(err)s" #, python-format msgid "Unable to find a free IP address for network '%(name)s'" msgstr "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã€Œ%(name)sã€ã®ãƒ•リー IP アドレスãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。" #, python-format msgid "The interface %(iface)s already exists." msgstr "" msgid "Network name must be a string without slashes (/) or quotes (\")" msgstr "" msgid "Supported network types are isolated, NAT and bridge" msgstr "サãƒãƒ¼ãƒˆã•れã¦ã„ã‚‹ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ãƒ»ã‚¿ã‚¤ãƒ—ã¯éš”離ã€NATã€ãŠã‚ˆã³ãƒ–リッジã§ã™" msgid "Network subnet must be a string with IP address and prefix or netmask" msgstr "" "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ãƒ»ã‚µãƒ–ãƒãƒƒãƒˆã¯ã€IP アドレスã¨ãƒ—レフィックスã¾ãŸã¯ãƒãƒƒãƒˆãƒžã‚¹ã‚¯ãŒ" "å…¥ã£ãŸã‚¹ãƒˆãƒªãƒ³ã‚°ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“" msgid "Network interface must be a string" msgstr "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ãƒ»ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ェースã¯ã‚¹ãƒˆãƒªãƒ³ã‚°ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“" msgid "Network VLAN ID must be an integer between 1 and 4094" msgstr "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ VLAN ID ã¯ã€1 ã‹ã‚‰ 4094 ã¾ã§ã®æ•´æ•°ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“" msgid "Specify name and type to create a Network" msgstr "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚’作æˆã™ã‚‹ã«ã¯ã€åå‰ã¨ã‚¿ã‚¤ãƒ—を指定ã—ã¦ãã ã•ã„" #, python-format msgid "" "Unable to delete network %(name)s. There are some virtual machines %(vms)s " "and/or templates linked to this network." msgstr "" #, python-format msgid "" "Unable to deactivate network %(name)s. There are some virtual machines " "%(vms)s and/or templates linked to this network." msgstr "" #, python-format msgid "Bridge device %(name)s can not be the trunk device of a VLAN." msgstr "" "ブリッジ・デãƒã‚¤ã‚¹ %(name)s ã‚’ã€VLAN ã®ãƒˆãƒ©ãƒ³ã‚¯ãƒ»ãƒ‡ãƒã‚¤ã‚¹ã«ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›" "ん。" #, python-format msgid "Failed to activate interface %(iface)s: %(err)s." msgstr "インターフェース %(iface)s ã®æ´»å‹•化ã«å¤±æ•—ã—ã¾ã—ãŸ: %(err)s。" #, python-format msgid "" "Failed to activate interface %(iface)s. Please check the physical link " "status." msgstr "" "インターフェース %(iface)s ã®æ´»å‹•化ã«å¤±æ•—ã—ã¾ã—ãŸã€‚物ç†ãƒªãƒ³ã‚¯çжæ³ã‚’確èªã—ã¦ã" "ã ã•ã„。" #, python-format msgid "Failed to start network %(name)s. Details: %(err)s" msgstr "" #, python-format msgid "Debug report %(name)s does not exist" msgstr "デãƒãƒƒã‚°ãƒ»ãƒ¬ãƒãƒ¼ãƒˆ %(name)s ã¯å­˜åœ¨ã—ã¾ã›ã‚“。" msgid "Debug report tool not found in system" msgstr "デãƒãƒƒã‚°ãƒ»ãƒ¬ãƒãƒ¼ãƒˆãƒ»ãƒ„ールãŒã‚·ã‚¹ãƒ†ãƒ ã«è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" #, python-format msgid "Unable to create debug report %(name)s. Details: %(err)s." msgstr "デãƒãƒƒã‚°ãƒ»ãƒ¬ãƒãƒ¼ãƒˆ %(name)s を作æˆã§ãã¾ã›ã‚“。詳細: %(err)s" #, python-format msgid "Can not find any debug report with the given name %(name)s" msgstr "" #, python-format msgid "Unable to generate debug report %(name)s. Details: %(err)s" msgstr "デãƒãƒƒã‚°ãƒ»ãƒ¬ãƒãƒ¼ãƒˆ %(name)s を生æˆã§ãã¾ã›ã‚“。詳細: %(err)s" msgid "You should give a name for the debug report file." msgstr "" msgid "" "Debug report name must be a string. Only letters, digits, underscore ('_') " "and hyphen ('-') are allowed." msgstr "" #, python-format msgid "" "The debug report with specified name \"%(name)s\" already exists. Please use " "another one." msgstr "" "åå‰ã€Œ%(name)sã€ã®ãƒœãƒªãƒ¥ãƒ¼ãƒ ãƒ»ã‚°ãƒ«ãƒ¼ãƒ—ã¯æ—¢ã«å­˜åœ¨ã—ã¾ã™ã€‚è«–ç†ãƒ—ールを作æˆã™ã‚‹" "ã«ã¯ã€åˆ¥ã®åå‰ã‚’é¸æŠžã—ã¦ãã ã•ã„。" #, python-format msgid "Storage server %(server)s was not used by Kimchi" msgstr "" "ストレージ・サーãƒãƒ¼ %(server)s ã¯ã€Kimchi ã«ã‚ˆã£ã¦ä½¿ç”¨ã•れã¦ã„ã¾ã›ã‚“ã§ã—ãŸ" #, python-format msgid "Distro '%(name)s' does not exist" msgstr "ディストリビューション「%(name)sã€ã¯å­˜åœ¨ã—ã¾ã›ã‚“" #, python-format msgid "Partition %(name)s does not exist in the host" msgstr "パーティション %(name)s ã¯ã€ãƒ›ã‚¹ãƒˆã«å­˜åœ¨ã—ã¾ã›ã‚“" msgid "Unable to shutdown host machine as there are running virtual machines" msgstr "稼åƒä¸­ã®ä»®æƒ³ãƒžã‚·ãƒ³ãŒã‚ã‚‹ãŸã‚ã€ãƒ›ã‚¹ãƒˆãƒ»ãƒžã‚·ãƒ³ã‚’シャットダウンã§ãã¾ã›ã‚“" msgid "Unable to reboot host machine as there are running virtual machines" msgstr "稼åƒä¸­ã®ä»®æƒ³ãƒžã‚·ãƒ³ãŒã‚ã‚‹ãŸã‚ã€ãƒ›ã‚¹ãƒˆãƒ»ãƒžã‚·ãƒ³ã‚’リブートã§ãã¾ã›ã‚“" #, python-format msgid "Node device '%(name)s' not found" msgstr "ノード・デãƒã‚¤ã‚¹ã€Œ%(name)sã€ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" msgid "Conflicting flag filters specified." msgstr "" msgid "No packages marked for update" msgstr "æ›´æ–°ã®å¯¾è±¡ã¨ã—ã¦ãƒžãƒ¼ã‚¯ã•れã¦ã„るパッケージã¯ã‚りã¾ã›ã‚“" #, python-format msgid "Package %(name)s is not marked to be updated." msgstr "パッケージ %(name)s ã¯ã€æ›´æ–°ã®å¯¾è±¡ã¨ã—ã¦ãƒžãƒ¼ã‚¯ã•れã¦ã„ã¾ã›ã‚“。" #, python-format msgid "Error while getting packages marked to be updated. Details: %(err)s" msgstr "" "æ›´æ–°ã®å¯¾è±¡ã¨ã—ã¦ãƒžãƒ¼ã‚¯ã•れãŸãƒ‘ッケージをå–å¾—ã—ã¦ã„ã‚‹ã¨ãã«ã€ã‚¨ãƒ©ãƒ¼ãŒã‚りã¾ã—" "ãŸã€‚詳細: %(err)s" msgid "There is no compatible package manager for this system." msgstr "ã“ã®ã‚·ã‚¹ãƒ†ãƒ ç”¨ã®äº’æ›ãƒ‘ッケージ・マãƒãƒ¼ã‚¸ãƒ£ãƒ¼ãŒã‚りã¾ã›ã‚“。" #, python-format msgid "Unable to find %(item)s in datastore" msgstr "%(item)s ã¯ãƒ‡ãƒ¼ã‚¿ãƒ»ã‚¹ãƒˆã‚¢ã«è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" #, python-format msgid "Invalid URI %(uri)s" msgstr "無効㪠URI %(uri)s" #, python-format msgid "Timeout while running command '%(cmd)s' after %(seconds)s seconds" msgstr "" "コマンド「%(cmd)sã€ã‚’実行ã—ã¦ã„ã¾ã—ãŸãŒã€%(seconds)s 秒を経éŽã—ã¦ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆ" "ã«ãªã‚Šã¾ã—ãŸ" msgid "Unable to choose a virtual machine name" msgstr "" #, python-format msgid "Invalid data value '%(value)s'" msgstr "" #, python-format msgid "Invalid data unit '%(unit)s'" msgstr "" msgid "Invalid storage type. Types supported: 'cdrom', 'disk'" msgstr "" "ストレージ・タイプãŒç„¡åйã§ã™ã€‚サãƒãƒ¼ãƒˆã•れã¦ã„るタイプã¯ã€Œcdromã€ã§ã™ã€‚" #, python-format msgid "The path '%(value)s' is not a valid local/remote path for the device" msgstr "" msgid "Only CDROM path can be update." msgstr "" #, python-format msgid "" "The storage device %(dev_name)s does not exist in the virtual machine " "%(vm_name)s" msgstr "" #, python-format msgid "Error while creating new storage device: %(error)s" msgstr "" "æ–°ã—ã„ストレージ・デãƒã‚¤ã‚¹ã‚’作æˆã—ã¦ã„ã‚‹ã¨ãã«ã€ã‚¨ãƒ©ãƒ¼ãŒã‚りã¾ã—ãŸ: %(error)s" #, python-format msgid "Error while updating storage device: %(error)s" msgstr "" "ストレージ・デãƒã‚¤ã‚¹ã‚’æ›´æ–°ã—ã¦ã„ã‚‹ã¨ãã«ã€ã‚¨ãƒ©ãƒ¼ãŒã‚りã¾ã—ãŸ: %(error)s" #, python-format msgid "Error while removing storage device: %(error)s" msgstr "" "ストレージ・デãƒã‚¤ã‚¹ã‚’削除ã—ã¦ã„ã‚‹ã¨ãã«ã€ã‚¨ãƒ©ãƒ¼ãŒã‚りã¾ã—ãŸ: %(error)s" msgid "Do not support IDE device hot plug" msgstr "" msgid "" "Specify type and path or type and pool/volume to add a new virtual machine " "disk" msgstr "æ–°ã—ã„仮想マシン・ディスクã«è¿½åŠ ã™ã‚‹ã‚¿ã‚¤ãƒ—ãŠã‚ˆã³ãƒ‘スを指定ã—ã¾ã™" msgid "Specify path to update virtual machine disk" msgstr "仮想マシン・ディスクを更新ã™ã‚‹ã«ã¯ã€ãƒ‘スを指定ã—ã¦ãã ã•ã„" #, python-format msgid "Controller type %(type)s limitation of %(limit)s devices reached" msgstr "" #, python-format msgid "Cannot retrieve disk path information for given pool/volume: %(error)s" msgstr "" msgid "Volume already in use by other virtual machine." msgstr "" msgid "" "Only one of path or pool/volume can be specified to add a new virtual " "machine disk" msgstr "æ–°ã—ã„仮想マシン・ディスクã«è¿½åŠ ã™ã‚‹ã‚¿ã‚¤ãƒ—ãŠã‚ˆã³ãƒ‘スを指定ã—ã¾ã™" #, python-format msgid "" "Volume chosen with format %(format)s does not fit in the storage type " "%(type)s" msgstr "" msgid "YUM Repository ID must be one word only string." msgstr "YUM リãƒã‚¸ãƒˆãƒªãƒ¼ ID ã¯ã€1 ワードã®ã¿ã®ã‚¹ãƒˆãƒªãƒ³ã‚°ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“" msgid "Repository URL must be an http://, ftp:// or file:// URL." msgstr "" "リãƒã‚¸ãƒˆãƒªãƒ¼ URL 㯠http://ã€ftp://ã€ã¾ãŸã¯ file:// URL ã§ãªã‘れã°ãªã‚Šã¾ã›" "ん。" msgid "" "Repository configuration is a dictionary with specific values according to " "repository type." msgstr "" "リãƒã‚¸ãƒˆãƒªãƒ¼æ§‹æˆã¨ã¯ã€ãƒªãƒã‚¸ãƒˆãƒªãƒ¼ãƒ»ã‚¿ã‚¤ãƒ—ã«å¿œã˜ã¦ç‰¹å®šã®å€¤ãŒå…¥ã£ãŸãƒ‡ã‚£ã‚¯ã‚·ãƒ§" "ナリーã§ã™ã€‚" msgid "Distribution to DEB repository must be a string" msgstr "" "DEB リãƒã‚¸ãƒˆãƒªãƒ¼ã¸ã®ãƒ‡ã‚£ã‚¹ãƒˆãƒªãƒ“ューションã¯ã€ã‚¹ãƒˆãƒªãƒ³ã‚°ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“" msgid "Components to DEB repository must be listed in a array" msgstr "" "DEB リãƒã‚¸ãƒˆãƒªãƒ¼ã¸ã®ã‚³ãƒ³ãƒãƒ¼ãƒãƒ³ãƒˆã¯ã€é…列ã¨ã—ã¦ãƒªã‚¹ãƒˆã•れã¦ã„ãªã‘れã°ãªã‚Šã¾" "ã›ã‚“" msgid "Components to DEB repository must be a string" msgstr "DEB リãƒã‚¸ãƒˆãƒªãƒ¼ã¸ã®ã‚³ãƒ³ãƒãƒ¼ãƒãƒ³ãƒˆã¯ã€ã‚¹ãƒˆãƒªãƒ³ã‚°ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“" msgid "Mirror list to repository must be a string" msgstr "" msgid "YUM Repository name must be string." msgstr "YUM リãƒã‚¸ãƒˆãƒªãƒ¼åã¯ã‚¹ãƒˆãƒªãƒ³ã‚°ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“。" msgid "GPG check must be a boolean value." msgstr "GPG ãƒã‚§ãƒƒã‚¯ã¯ãƒ–ール値ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“。" msgid "GPG key must be a URL pointing to the ASCII-armored file." msgstr "GPG éµã¯ã€ASCII ã§ä¿å­˜ã•れãŸãƒ•ァイルを指㙠URL ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“。" #, python-format msgid "Could not update repository %(repo_id)s." msgstr "リãƒã‚¸ãƒˆãƒªãƒ¼ %(repo_id)s ã‚’æ›´æ–°ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚" #, python-format msgid "Repository %(repo_id)s does not exist." msgstr "リãƒã‚¸ãƒˆãƒªãƒ¼ %(repo_id)s ã¯å­˜åœ¨ã—ã¾ã›ã‚“。" msgid "" "Specify repository base URL, mirror list or metalink in order to create or " "update a YUM repository." msgstr "" msgid "Repository management tool was not recognized for your system." msgstr "システム用ã®ãƒªãƒã‚¸ãƒˆãƒªãƒ¼ç®¡ç†ãƒ„ールãŒèªè­˜ã•れã¾ã›ã‚“ã§ã—ãŸã€‚" #, python-format msgid "Repository %(repo_id)s is already enabled." msgstr "リãƒã‚¸ãƒˆãƒªãƒ¼ %(repo_id)s ã¯æ—¢ã«æœ‰åйã«ãªã£ã¦ã„ã¾ã™ã€‚" #, python-format msgid "Repository %(repo_id)s is already disabled." msgstr "リãƒã‚¸ãƒˆãƒªãƒ¼ %(repo_id)s ã¯æ—¢ã«ç„¡åйã«ãªã£ã¦ã„ã¾ã™ã€‚" #, python-format msgid "Could not remove repository %(repo_id)s." msgstr "リãƒã‚¸ãƒˆãƒªãƒ¼ %(repo_id)s を削除ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚" #, python-format msgid "Could not write repository configuration file %(repo_file)s" msgstr "" "リãƒã‚¸ãƒˆãƒªãƒ¼æ§‹æˆãƒ•ァイル %(repo_file)s を書ã込むã“ã¨ãŒã§ãã¾ã›ã‚“ã§ã—ãŸ" msgid "Specify repository distribution in order to create a DEB repository." msgstr "" "DEB リãƒã‚¸ãƒˆãƒªãƒ¼ã‚’作æˆã™ã‚‹ãŸã‚ã«ã¯ã€ãƒªãƒã‚¸ãƒˆãƒªãƒ¼ãƒ»ãƒ‡ã‚£ã‚¹ãƒˆãƒªãƒ“ューションを指" "定ã—ã¦ãã ã•ã„。" #, python-format msgid "Could not enable repository %(repo_id)s." msgstr "リãƒã‚¸ãƒˆãƒªãƒ¼ %(repo_id)s を有効ã«ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚" #, python-format msgid "Could not disable repository %(repo_id)s." msgstr "リãƒã‚¸ãƒˆãƒªãƒ¼ %(repo_id)s を無効ã«ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚" msgid "YUM Repository ID already exists" msgstr "YUM リãƒã‚¸ãƒˆãƒªãƒ¼ ID ã¯æ—¢ã«å­˜åœ¨ã—ã¾ã™" msgid "YUM Repository name must be a string" msgstr "YUM リãƒã‚¸ãƒˆãƒªãƒ¼åã¯ã‚¹ãƒˆãƒªãƒ³ã‚°ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“" #, python-format msgid "Unable to list repositories. Details: '%(err)s'" msgstr "リãƒã‚¸ãƒˆãƒªãƒ¼ã‚’リストã§ãã¾ã›ã‚“。詳細: 「%(err)sã€" #, python-format msgid "Unable to retrieve repository information. Details: '%(err)s'" msgstr "リãƒã‚¸ãƒˆãƒªãƒ¼æƒ…報をå–å¾—ã§ãã¾ã›ã‚“。詳細: 「%(err)sã€" #, python-format msgid "Unable to add repository. Details: '%(err)s'" msgstr "リãƒã‚¸ãƒˆãƒªãƒ¼ã‚’追加ã§ãã¾ã›ã‚“。詳細: 「%(err)sã€" #, python-format msgid "Unable to remove repository. Details: '%(err)s'" msgstr "リãƒã‚¸ãƒˆãƒªãƒ¼ã‚’削除ã§ãã¾ã›ã‚“。詳細: 「%(err)sã€" #, python-format msgid "" "Configuration items: '%(items)s' are not supported by repository manager" msgstr "" msgid "Repository metalink must be an http://, ftp:// or file:// URL." msgstr "" msgid "Cannot specify mirrorlist and metalink at the same time." msgstr "" #, python-format msgid "" "Virtual machine '%(vm)s' must be stopped before creating a snapshot of it." msgstr "" #, python-format msgid "" "Unable to create snapshot '%(name)s' on virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "Snapshot '%(name)s' does not exist on virtual machine '%(vm)s'." msgstr "" #, python-format msgid "" "Unable to retrieve snapshot '%(name)s' on virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "Unable to list snapshots on virtual machine '%(vm)s'. Details: %(err)s" msgstr "" #, python-format msgid "" "Unable to delete snapshot '%(name)s' on virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "" "Unable to retrieve current snapshot of virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "" "Unable to revert virtual machine '%(vm)s' to snapshot '%(name)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "" "Unable to create snapshot of virtual machine '%(vm)s' because it contains a " "disk with format '%(format)s'; only 'qcow2' is supported." msgstr "" msgid "The number of vCPUs is too large for this system." msgstr "" msgid "Invalid vCPU/topology combination." msgstr "" msgid "This host (or current configuration) does not allow CPU topology." msgstr "" msgid "ERROR CODE" msgstr "エラー・コード" msgid "REASON" msgstr "ç†ç”±" msgid "STACK" msgstr "スタック" msgid "Go to Homepage" msgstr "ホーム・ページã«ç§»å‹•ã™ã‚‹" msgid "Create a New Virtual Machine" msgstr "æ–°è¦ä»®æƒ³ãƒžã‚·ãƒ³ã®ä½œæˆ" msgid "Virtual Machine Name" msgstr "仮想マシンå" msgid "" "The name used to identify the virtual machine. If omitted, a name will be " "chosen based on the template used." msgstr "" "åå‰ã¯ä»®æƒ³ãƒžã‚·ãƒ³ã‚’識別ã™ã‚‹ãŸã‚ã«ä½¿ç”¨ã•れã¾ã™ã€‚çœç•¥ã™ã‚‹ã¨ã€ä½¿ç”¨ã•れã¦ã„るテン" "プレートã«åŸºã¥ã„ã¦é¸æŠžã•れã¾ã™ã€‚" msgid "Template" msgstr "テンプレート" msgid "Please create a template first." msgstr "ã¾ãšãƒ†ãƒ³ãƒ—レートを作æˆã—ã¦ãã ã•ã„。" msgid "Create a Template" msgstr "テンプレートã®ä½œæˆ" msgid "Please choose a template." msgstr "ãƒ†ãƒ³ãƒ—ãƒ¬ãƒ¼ãƒˆã‚’é¸æŠžã—ã¦ãã ã•ã„。" msgid "OS" msgstr "OS" msgid "OS Version" msgstr "OS ãƒãƒ¼ã‚¸ãƒ§ãƒ³" msgid "CPUS" msgstr "CPU" msgid "Memory" msgstr "メモリー" msgid "Create" msgstr "作æˆ" msgid "Creating..." msgstr "" msgid "Edit Guest" msgstr "ゲストã®ç·¨é›†" msgid "General" msgstr "一般" msgid "Storage" msgstr "ストレージ" msgid "Interface" msgstr "インターフェース" msgid "Permission" msgstr "ãƒãƒ¼ã‚¸ãƒ§ãƒ³" msgid "Host PCI Device" msgstr "" msgid "Snapshot" msgstr "" msgid "Name" msgstr "åå‰" msgid "CPUs" msgstr "CPU" msgid "Memory (MB)" msgstr "メモリー" msgid "Icon" msgstr "アイコン" msgid "Device" msgstr "デãƒã‚¤ã‚¹å" msgid "Path" msgstr "NFS パス" msgid "Network" msgstr " ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯" msgid "Type" msgstr "タイプ" msgid "MAC Address" msgstr "" msgid "Available system users and groups" msgstr "" msgid "Selected system users and groups" msgstr "" msgid "User" msgstr "" msgid "All" msgstr "ã™ã¹ã¦" msgid "To Add" msgstr "" msgid "Added" msgstr "" msgid "filter" msgstr "" msgid "Product" msgstr "" msgid "Vendor" msgstr "ベンダー" msgid "Created" msgstr "" msgid "Save" msgstr "ä¿å­˜" msgid "Replace" msgstr "交æ›" msgid "Detach" msgstr "切り離ã—" msgid "Cancel" msgstr "å–æ¶ˆ" msgid "revert" msgstr "" msgid "Add a Storage Device to VM" msgstr "VM ã«ã‚¹ãƒˆãƒ¬ãƒ¼ã‚¸ãƒ»ãƒ‡ãƒã‚¤ã‚¹ã‚’追加" msgid "Device Type" msgstr "デãƒã‚¤ã‚¹ãƒ»ã‚¿ã‚¤ãƒ—" msgid "The device type. Currently, \"cdrom\" and \"disk\" are supported." msgstr "デãƒã‚¤ã‚¹ãƒ»ã‚¿ã‚¤ãƒ—。ç¾åœ¨ã‚µãƒãƒ¼ãƒˆã•れã¦ã„ã‚‹ã®ã¯ \"cdrom\" ã®ã¿ã§ã™ã€‚" msgid "Storage Pool" msgstr "ストレージ・プール" msgid "Storage pool which volume located in" msgstr "ストレージ・プール・パスã¯ã‚¹ãƒˆãƒªãƒ³ã‚°ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“" msgid "Storage Volume" msgstr "ストレージ・プールå" msgid "Storage volume to be attached" msgstr "ストレージ・ボリュームåã¯ã‚¹ãƒˆãƒªãƒ³ã‚°ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“" msgid "File Path" msgstr "ファイル・パス" msgid "The ISO file path in the server for CDROM." msgstr "サーãƒãƒ¼å†…ã§ã® CDROM ã® ISO ファイル・パス。" msgid "Attach" msgstr "接続" msgid "Start" msgstr "é–‹å§‹" msgid "Reset" msgstr "リセット" msgid "Pause" msgstr "" msgid "Resume" msgstr "" msgid "Power Off" msgstr "" msgid "Actions" msgstr "アクション" msgid "Connect" msgstr "接続" msgid "Clone" msgstr "" msgid "Edit" msgstr "編集" msgid "Shut Down" msgstr "シャットダウン" msgid "Delete" msgstr "削除" msgid "The username or password you entered is incorrect. Please try again." msgstr "入力ã—ãŸãƒ¦ãƒ¼ã‚¶ãƒ¼åã¾ãŸã¯ãƒ‘スワードãŒèª¤ã£ã¦ã„ã¾ã™ã€‚やり直ã—ã¦ãã ã•ã„。" msgid "This field is required." msgstr "ã“ã®ãƒ•ィールドã¯å¿…é ˆã§ã™ã€‚" msgid "Log in" msgstr "ログイン" msgid "Logging in..." msgstr "ログインã—ã¦ã„ã¾ã™..." msgid "Host" msgstr "ホスト" msgid "Guests" msgstr "ゲスト" msgid "Templates" msgstr "テンプレート" msgid "Failed to get application configuration" msgstr "アプリケーション構æˆã‚’å–å¾—ã§ãã¾ã›ã‚“ã§ã—ãŸ" msgid "This is not a valid Linux path" msgstr "有効㪠Linux パスã§ã¯ã‚りã¾ã›ã‚“" msgid "This is not a valid URL." msgstr "有効㪠URL ã§ã¯ã‚りã¾ã›ã‚“。" msgid "No such data available." msgstr "ãã®ã‚ˆã†ãªãƒ‡ãƒ¼ã‚¿ã¯ã‚りã¾ã›ã‚“。" msgid "" "Can not contact the host system. Verify the host system is up and that you " "have network connectivity to it. HTTP request response %1. " msgstr "" "ãƒ›ã‚¹ãƒˆãƒ»ã‚·ã‚¹ãƒ†ãƒ ã«æŽ¥ç¶šã§ãã¾ã›ã‚“。ホスト・システムãŒç¨¼åƒã—ã¦ã„ã¦ã€ãƒãƒƒãƒˆãƒ¯ãƒ¼" "ク接続ãŒè¡Œã‚れã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。HTTP è¦æ±‚応答 %1" msgid "Unable to read file." msgstr "" msgid "Error while uploading file." msgstr "" msgid "Delete Confirmation" msgstr "削除ã®ç¢ºèª" msgid "OK" msgstr "OK" msgid "Confirm" msgstr "確èª" msgid "Warning" msgstr "警告" msgid "Cloning..." msgstr "" msgid "Loading..." msgstr "ロードã—ã¦ã„ã¾ã™..." msgid "An error occurred while retrieving system information." msgstr "" msgid "Retry" msgstr "å†è©¦è¡Œ" msgid "Detailed message:" msgstr "詳細メッセージ:" msgid "No ISO found" msgstr "" msgid "This is not a valid ISO file." msgstr "有効㪠ISO ファイルã§ã¯ã‚りã¾ã›ã‚“。" msgid "This may take a long time. Do you want to continue?" msgstr "ã—ã°ã‚‰ã時間ãŒã‹ã‹ã‚‹ã“ã¨ãŒã‚りã¾ã™ã€‚続行ã—ã¾ã™ã‹?" msgid "This will permanently delete the template. Would you like to continue?" msgstr "テンプレートã¯å®Œå…¨ã«å‰Šé™¤ã•れã¾ã™ã€‚続行ã—ã¾ã™ã‹?" msgid "Unable to shut down system as there are some virtual machines running!" msgstr "" "ã„ãã¤ã‹ã®ä»®æƒ³ãƒžã‚·ãƒ³ãŒç¨¼åƒã—ã¦ã„ã‚‹ãŸã‚ã«ã€ã‚·ã‚¹ãƒ†ãƒ ã‚’シャットダウンã§ãã¾ã›ã‚“!" msgid "Max:" msgstr "最大:" msgid "Utilization" msgstr "使用率" msgid "Available" msgstr "使用å¯èƒ½" msgid "Read Rate" msgstr "読ã¿å–り速度" msgid "Write Rate" msgstr "書ãè¾¼ã¿é€Ÿåº¦" msgid "Received" msgstr "å—信済ã¿" msgid "Sent" msgstr "é€ä¿¡æ¸ˆã¿" msgid "" "Shutting down or restarting host will cause unsaved work lost. Continue to " "shut down/restarting?" msgstr "" "ホストをシャットダウンã¾ãŸã¯å†å§‹å‹•ã™ã‚‹ã¨ã€ä¿å­˜ã•れã¦ã„ãªã„作業ã¯å¤±ã‚れã¾ã™ã€‚" "シャットダウン/å†å§‹å‹•を続行ã—ã¾ã™ã‹?" msgid "" "Repository will be removed permanently and can't be recovered. Do you want " "to continue?" msgstr "" "リãƒã‚¸ãƒˆãƒªãƒ¼ã¯å®Œå…¨ã«å‰Šé™¤ã•れã€ãƒªã‚«ãƒãƒªãƒ¼ã§ããªããªã‚Šã¾ã™ã€‚続行ã—ã¾ã™ã‹?" msgid "Repositories" msgstr "リãƒã‚¸ãƒˆãƒªãƒ¼" msgid "ID" msgstr "ID" msgid "Base URL" msgstr "ベース URL" msgid "Is Mirror" msgstr "ミラー" msgid "URL Args" msgstr "URL 引数" msgid "Enabled" msgstr "使用å¯èƒ½" msgid "GPG Check" msgstr "GPG ãƒã‚§ãƒƒã‚¯" msgid "GPG Key" msgstr "GPG éµ" msgid "Add" msgstr "追加" msgid "Remove" msgstr "除去" msgid "Enable" msgstr "使用å¯èƒ½" msgid "Disable" msgstr "使用ä¸å¯" msgid "Software Updates" msgstr "ソフトウェア更新" msgid "Package Name" msgstr "パッケージå" msgid "Version" msgstr "ãƒãƒ¼ã‚¸ãƒ§ãƒ³" msgid "Architecture" msgstr "アーキテクãƒãƒ£ãƒ¼" msgid "Repository" msgstr "リãƒã‚¸ãƒˆãƒªãƒ¼" msgid "Update All" msgstr "ã™ã¹ã¦æ›´æ–°" msgid "Updating..." msgstr "æ›´æ–°ã—ã¦ã„ã¾ã™..." msgid "Failed to retrieve packages update information." msgstr "" msgid "Failed to update package(s)." msgstr "パッケージを更新ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚" msgid "" "Debug report will be removed permanently and can't be recovered. Do you want " "to continue?" msgstr "" "デãƒãƒƒã‚°ãƒ»ãƒ¬ãƒãƒ¼ãƒˆã¯å®Œå…¨ã«å‰Šé™¤ã•れã€ãƒªã‚«ãƒãƒªãƒ¼ã§ããªããªã‚Šã¾ã™ã€‚続行ã—ã¾ã™ã‹?" msgid "Debug Reports" msgstr "デãƒãƒƒã‚°ãƒ»ãƒ¬ãƒãƒ¼ãƒˆ" msgid "Generated Time" msgstr "ç”Ÿæˆæ™‚刻" msgid "Generate" msgstr "生æˆ" msgid "Generating..." msgstr "生æˆã—ã¦ã„ã¾ã™..." msgid "Rename" msgstr "åå‰å¤‰æ›´" msgid "Download" msgstr "ダウンロード" msgid "" "Report name should contain only letters, digits, underscore ('_') and/or " "hyphen ('-')." msgstr "レãƒãƒ¼ãƒˆåã«ä½¿ç”¨ã§ãã‚‹ã®ã¯ã€è‹±å­—ã€æ•°å­—ã€ãŠã‚ˆã³ãƒã‚¤ãƒ•ン (-) ã®ã¿ã§ã™ã€‚" msgid "Pending..." msgstr "ロードã—ã¦ã„ã¾ã™..." msgid "Report name is the same as the original one." msgstr "" msgid "" "This will delete the virtual machine and its virtual disks. This operation " "cannot be undone. Would you like to continue?" msgstr "" "仮想マシンã¨ãã®ä»®æƒ³ãƒ‡ã‚£ã‚¹ã‚¯ãŒå‰Šé™¤ã•れã¾ã™ã€‚ã“ã®æ“作ã¯å…ƒã«æˆ»ã™ã“ã¨ãŒã§ãã¾ã›" "ん。続行ã—ã¾ã™ã‹?" msgid "Power off Confirmation" msgstr "削除ã®ç¢ºèª" msgid "" "This action may produce undesirable results, for example unflushed disk " "cache in the guest. Would you like to continue?" msgstr "" msgid "Reset Confirmation" msgstr "削除ã®ç¢ºèª" msgid "" "There is a risk of data loss caused by reset without the guest OS shutdown. " "Would you like to continue?" msgstr "" msgid "Shut Down Confirmation" msgstr "削除ã®ç¢ºèª" msgid "Note the guest OS may ignore this request. Would you like to continue?" msgstr "テンプレートã¯å®Œå…¨ã«å‰Šé™¤ã•れã¾ã™ã€‚続行ã—ã¾ã™ã‹?" msgid "Virtual Machine delete Confirmation" msgstr "" msgid "" "This virtual machine is not persistent. Power Off will delete it. Continue?" msgstr "" msgid "" "When the target guest has SCSI or iSCSI volumes, they will be cloned on " "default storage pool. The same will happen when the target pool does not " "have enough space to clone the volumes. Do you want to continue?" msgstr "" msgid "" "This CDROM will be detached permanently and you can re-attach it. Continue " "to detach it?" msgstr "" "ã“ã® CDROM ã¯å®Œå…¨ã«åˆ‡ã‚Šé›¢ã•れã¾ã™ãŒã€å†æŽ¥ç¶šã§ãã¾ã™ã€‚切り離ã—を続行ã—ã¾ã™ã‹?" msgid "Attaching..." msgstr "接続ã—ã¦ã„ã¾ã™..." msgid "Replacing..." msgstr "交æ›ã—ã¦ã„ã¾ã™..." msgid "Successfully attached!" msgstr "æ­£å¸¸ã«æŽ¥ç¶šã—ã¾ã—ãŸ!" msgid "Successfully replaced!" msgstr "正常ã«äº¤æ›ã—ã¾ã—ãŸ!" msgid "Successfully detached!" msgstr "正常ã«åˆ‡ã‚Šé›¢ã—ã¾ã—ãŸ!" msgid "" "This disk will be detached permanently and you can re-attach it. Continue to " "detach it?" msgstr "" msgid "interface:" msgstr "" msgid "address:" msgstr "" msgid "link_type:" msgstr "" msgid "block:" msgstr "" msgid "drive_type:" msgstr "" msgid "model:" msgstr "" msgid "Affected devices:" msgstr "" msgid "The VLAN id must be between 1 and 4094." msgstr "VLAN ID ã¯ã€1 ã‹ã‚‰ 4094 ã¾ã§ã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“。" msgid "unavailable" msgstr "使用ä¸å¯" msgid "" "This action will interrupt network connectivity for any virtual machine that " "depend on this network." msgstr "" "ã“ã®ã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã¯ã€ã“ã®ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«ä¾å­˜ã—ã¦ã„る仮想マシンã®ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯æŽ¥ç¶š" "を妨ã’ã¾ã™ã€‚" msgid "Create a network" msgstr "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã®ä½œæˆ" msgid "" "This network is not persistent. Instead of stop, this action will " "permanently delete it. Would you like to continue?" msgstr "" "ã“ã®ã‚¹ãƒˆãƒ¬ãƒ¼ã‚¸ãƒ»ãƒ—ãƒ¼ãƒ«ã¯æ°¸ç¶šçš„ãªã‚‚ã®ã§ã¯ã‚りã¾ã›ã‚“。ã“ã®ã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã§ã€éžã‚¢ã‚¯" "ティブã«ãªã‚‹ã®ã§ã¯ãªã完全ã«å‰Šé™¤ã•れã¾ã™ã€‚続行ã—ã¾ã™ã‹?" msgid "" "The bridged VLAN tag may not work well with NetworkManager enabled. You " "should consider disabling it." msgstr "" msgid "" "This will permanently delete the storage pool. Would you like to continue?" msgstr "ストレージ・プールã¯å®Œå…¨ã«å‰Šé™¤ã•れã¾ã™ã€‚続行ã—ã¾ã™ã‹?" msgid "This storage pool is empty." msgstr "ã“ã®ã‚¹ãƒˆãƒ¬ãƒ¼ã‚¸ãƒ»ãƒ—ールã¯ç©ºã§ã™ã€‚" msgid "" "It will format your disk and you will loose any data in there, are you sure " "to continue? " msgstr "" "ディスクã¯ãƒ•ォーマットã•れã€ãã®ä¸­ã®ãƒ‡ãƒ¼ã‚¿ã¯ã™ã¹ã¦å¤±ã‚れã¾ã™ã€‚続行ã—ã¾ã™ã‹?" msgid "SCSI Fibre Channel" msgstr "SCSI ファイãƒãƒ¼ãƒ»ãƒãƒ£ãƒãƒ«" msgid "No SCSI adapters found." msgstr "SCSI アダプターãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。" msgid "Loading iSCSI targets..." msgstr "" msgid "No iSCSI found. Please input one." msgstr "" msgid "Failed to load iSCSI targets." msgstr "" msgid "The storage pool name can not be blank." msgstr "ストレージ・プールåをブランクã«ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。" msgid "The storage pool path can not be blank." msgstr "ストレージ・プール・パスをブランクã«ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。" msgid "NFS server mount path can not be blank." msgstr "NFS サーãƒãƒ¼ãƒ»ãƒžã‚¦ãƒ³ãƒˆãƒ»ãƒ‘スをブランクã«ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。" msgid "Invalid NFS mount path." msgstr "NFS マウント・パスãŒç„¡åйã§ã™ã€‚" msgid "No logical device selected." msgstr "è«–ç†ãƒ‡ãƒã‚¤ã‚¹ãŒé¸æŠžã•れã¦ã„ã¾ã›ã‚“。" msgid "The iSCSI target can not be blank." msgstr "iSCSI ターゲットをブランクã«ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。" msgid "Server name can not be blank." msgstr "サーãƒãƒ¼åをブランクã«ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。" msgid "This is not a valid Server Name or IP. Please, modify it." msgstr "" msgid "Looking for available partitions ..." msgstr "愛用å¯èƒ½ãªãƒ‘ーティションを探ã—ã¦ã„ã¾ã™..." msgid "No available partitions found." msgstr "使用å¯èƒ½ãªãƒ‘ーティションãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。" msgid "" "This storage pool is not persistent. Instead of deactivate, this action will " "permanently delete it. Would you like to continue?" msgstr "" "ã“ã®ã‚¹ãƒˆãƒ¬ãƒ¼ã‚¸ãƒ»ãƒ—ãƒ¼ãƒ«ã¯æ°¸ç¶šçš„ãªã‚‚ã®ã§ã¯ã‚りã¾ã›ã‚“。ã“ã®ã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã§ã€éžã‚¢ã‚¯" "ティブã«ãªã‚‹ã®ã§ã¯ãªã完全ã«å‰Šé™¤ã•れã¾ã™ã€‚続行ã—ã¾ã™ã‹?" msgid "Unable to retrieve partitions information." msgstr "リãƒã‚¸ãƒˆãƒªãƒ¼æƒ…報をå–å¾—ã§ãã¾ã›ã‚“。詳細: 「%(err)sã€" msgid "In progress..." msgstr "" msgid "Failed!" msgstr "" msgid "CDROM path needs to be a valid local/remote path and cannot be blank." msgstr "" msgid "Disk pool or volume cannot be blank." msgstr "ストレージ・プールåをブランクã«ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。" msgid "Peers" msgstr "" msgid "Searching" msgstr "" msgid "No peers found." msgstr "" msgid "Help" msgstr "ヘルプ" msgid "About" msgstr "è£½å“æƒ…å ±" msgid "Log out" msgstr "ログアウト" msgid "Version:" msgstr "ãƒãƒ¼ã‚¸ãƒ§ãƒ³: " msgid "Session timeout, please re-login." msgstr "" msgid "User Name" msgstr "ユーザーå" msgid "Password" msgstr "パスワード" msgid "Generate a New Debug Report" msgstr "æ–°è¦ãƒ‡ãƒãƒƒã‚°ãƒ»ãƒ¬ãƒãƒ¼ãƒˆã®ç”Ÿæˆ" msgid "Report Name" msgstr "レãƒãƒ¼ãƒˆå" msgid "" "The name used to identify the report. If omitted, a name will be chosen " "based on current time. Name can contain: letters, digits, underscore (\"_\") " "and hyphen (\"-\")." msgstr "" "åå‰ã¯ãƒ¬ãƒãƒ¼ãƒˆã‚’識別ã™ã‚‹ãŸã‚ã«ä½¿ç”¨ã•れã¾ã™ã€‚çœç•¥ã™ã‚‹ã¨ã€ç¾åœ¨æ™‚刻ã«åŸºã¥ã„ã¦é¸" "択ã•れã¾ã™ã€‚åå‰ã«ã¯è‹±å­—ã€æ•°å­—ã€ãŠã‚ˆã³ãƒã‚¤ãƒ•ン (-) を使用ã§ãã¾ã™ã€‚" msgid "Rename a Debug Report" msgstr "æ–°è¦ãƒ‡ãƒãƒƒã‚°ãƒ»ãƒ¬ãƒãƒ¼ãƒˆã®ç”Ÿæˆ" msgid "" "The name used to identify the report. Name can contain: letters, digits and " "hyphen (\"-\")." msgstr "" "åå‰ã¯ãƒ¬ãƒãƒ¼ãƒˆã‚’識別ã™ã‚‹ãŸã‚ã«ä½¿ç”¨ã•れã¾ã™ã€‚çœç•¥ã™ã‚‹ã¨ã€ç¾åœ¨æ™‚刻ã«åŸºã¥ã„ã¦é¸" "択ã•れã¾ã™ã€‚åå‰ã«ã¯è‹±å­—ã€æ•°å­—ã€ãŠã‚ˆã³ãƒã‚¤ãƒ•ン (-) を使用ã§ãã¾ã™ã€‚" msgid "Submit" msgstr "" msgid "Add a Repository" msgstr "リãƒã‚¸ãƒˆãƒªãƒ¼ã®è¿½åŠ " msgid "Identifier" msgstr "ID" msgid "Single word, unique identifier for the repository." msgstr "リãƒã‚¸ãƒˆãƒªãƒ¼ã®å›ºæœ‰ ID を示ã™å˜ä¸€ã®ãƒ¯ãƒ¼ãƒ‰ã€‚" msgid "Textual name for the repository." msgstr "リãƒã‚¸ãƒˆãƒªãƒ¼ã®ãƒ†ã‚­ã‚¹ãƒˆå。" msgid "URL" msgstr "URL" msgid "Required Field" msgstr "必須フィールド" msgid "URL to the repository. Supported protocols are http, ftp, and file." msgstr "" "リãƒã‚¸ãƒˆãƒªãƒ¼ã® URL ã§ã€ã‚µãƒãƒ¼ãƒˆã•れã¦ã„るプロトコル㯠httpã€ftpã€ãŠã‚ˆã³ file " "ã§ã™ã€‚" msgid "Repository is a mirror" msgstr "リãƒã‚¸ãƒˆãƒªãƒ¼ã¯ãƒŸãƒ©ãƒ¼ã§ã™ã€‚" msgid "Distribution" msgstr "ディストリビューション" msgid "Distribution of the DEB repository." msgstr "DEB リãƒã‚¸ãƒˆãƒªãƒ¼ã®ãƒ‡ã‚£ã‚¹ãƒˆãƒªãƒ“ューション。" msgid "Components" msgstr "コンãƒãƒ¼ãƒãƒ³ãƒˆ" msgid "List of components in DEB repository." msgstr "DEB リãƒã‚¸ãƒˆãƒªãƒ¼å†…ã®ã‚³ãƒ³ãƒãƒ¼ãƒãƒ³ãƒˆã®ãƒªã‚¹ãƒˆã€‚" msgid "Edit Repository" msgstr "リãƒã‚¸ãƒˆãƒªãƒ¼ã®ç·¨é›†" msgid "Mirror List URL" msgstr "ミラー・リスト URL" msgid "Yes" msgstr " ã¯ã„" msgid "No" msgstr " ã„ã„ãˆ" msgid "Add a Volume to Storage Pool" msgstr "" msgid "Fetch from remote URL" msgstr "" msgid "Enter the remote URL here." msgstr "" msgid "Upload a file" msgstr "" msgid "Choose the file you want to upload." msgstr "" msgid "Define a New Storage Pool" msgstr "æ–°è¦ã‚¹ãƒˆãƒ¬ãƒ¼ã‚¸ãƒ»ãƒ—ールã®å®šç¾©" msgid "Storage Pool Name" msgstr "ストレージ・プールå" msgid "" "The name used to identify the storage pools, and it should not be empty." msgstr "" "åå‰ã¯ã‚¹ãƒˆãƒ¬ãƒ¼ã‚¸ãƒ»ãƒ—ールを識別ã™ã‚‹ãŸã‚ã«ä½¿ç”¨ã•れã¾ã™ã€‚空ã«ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›" "ん。" msgid "Storage Pool Type" msgstr "ストレージ・プール・タイプ" msgid "Storage Path" msgstr "ストレージ・パス" msgid "" "The path of the Storage Pool. Each Storage Pool must have a unique path." msgstr "" "ストレージ・プールã®ãƒ‘ス。ãれãžã‚Œã®ã‚¹ãƒˆãƒ¬ãƒ¼ã‚¸ãƒ»ãƒ—ールã«å›ºæœ‰ã®ãƒ‘スãŒå¿…è¦ã§" "ã™ã€‚" msgid "" "Kimchi will try to create the directory when it does not already exist in " "your system." msgstr "" "ディレクトリーãŒã‚·ã‚¹ãƒ†ãƒ ã«å­˜åœ¨ã—ãªã„å ´åˆã€Kimchi ãŒãã®ä½œæˆã‚’試ã¿ã¾ã™ã€‚" msgid "NFS Server IP" msgstr "NFS サーãƒãƒ¼ IP" msgid "NFS server IP or hostname. It can be input or chosen from history." msgstr "" "NFS サーãƒãƒ¼ IP ã¾ãŸã¯ãƒ›ã‚¹ãƒˆå。入力ã™ã‚‹ã“ã¨ã‚‚ã€ãƒ’ストリーã‹ã‚‰é¸æŠžã™ã‚‹ã“ã¨ã‚‚" "ã§ãã¾ã™ã€‚" msgid "NFS Path" msgstr "NFS パス" msgid "The NFS exported path on NFS server." msgstr "NFS ãŒãƒ‘スを NFS サーãƒãƒ¼ã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã—ã¾ã—ãŸã€‚" msgid "Device path" msgstr "デãƒã‚¤ã‚¹ãƒ»ãƒ‘ス" msgid "iSCSI Server" msgstr "iSCSI サーãƒãƒ¼" msgid "iSCSI server IP or hostname. It should not be empty." msgstr "iSCSI サーãƒãƒ¼ IP ã¾ãŸã¯ãƒ›ã‚¹ãƒˆå。空ã«ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。" msgid "Server" msgstr "サーãƒãƒ¼" msgid "Port" msgstr "ãƒãƒ¼ãƒˆ" msgid "Target" msgstr "ターゲット" msgid "The iSCSI target on iSCSI server" msgstr "iSCSI サーãƒãƒ¼ä¸Šã® iSCSI ターゲット" msgid "Add iSCSI Authentication" msgstr "iSCSI èªè¨¼ã®è¿½åŠ " msgid "iSCSI Authentication" msgstr "iSCSI èªè¨¼" msgid "SCSI Adapter" msgstr "SCSI アダプター" msgid "Please, wait..." msgstr "ãŠå¾…ã¡ãã ã•ã„..." msgid "Add Template" msgstr "テンプレートã®è¿½åŠ " msgid "Where is the source media for this template? " msgstr "ã“ã®ãƒ†ãƒ³ãƒ—レートã®ã‚½ãƒ¼ã‚¹ãƒ»ãƒ¡ãƒ‡ã‚£ã‚¢ã¯ã©ã“ã«ã‚りã¾ã™ã‹?" msgid "Local ISO Image" msgstr "ローカル ISO イメージ" msgid "Local Image File" msgstr "" msgid "Remote ISO Image" msgstr "リモート ISO イメージ" msgid "Search ISOs" msgstr "ISO ã®æ¤œç´¢" msgid "The following ISOs are available:" msgstr "次㮠ISO ãŒä½¿ç”¨å¯èƒ½ã§ã™:" msgid "OS: " msgstr "OS: " msgid "Version: " msgstr "ãƒãƒ¼ã‚¸ãƒ§ãƒ³: " msgid "Size: " msgstr "サイズ: " msgid "Search more ISOs" msgstr "ISO ã‚’ã•ã‚‰ã«æ¤œç´¢" msgid "Create Templates from Selected ISO" msgstr "é¸æŠžã—㟠ISO ã‹ã‚‰ãƒ†ãƒ³ãƒ—レートを作æˆ" msgid "I want to use a specific ISO file" msgstr "特定㮠ISO ファイルを使用ã™ã‚‹" msgid "Loading default remote ISOs ..." msgstr "デフォルトã®ãƒªãƒ¢ãƒ¼ãƒˆ ISO をロードã—ã¦ã„ã¾ã™..." msgid "Arch: " msgstr "アーキテクãƒãƒ£ãƒ¼: " msgid "I want to use a custom URL" msgstr "カスタム URL を使用ã™ã‚‹" msgid "Edit Template" msgstr "テンプレートã®ç·¨é›†" msgid "Processor" msgstr "プロセッサー" msgid "CDROM" msgstr "CDROM" msgid "Image File" msgstr "" msgid "Graphics" msgstr "グラフィックス" msgid "Disk(GB)" msgstr "" msgid "Disk Format" msgstr "" msgid "CPU Number" msgstr "CPU æ•°" msgid "Manually set CPU topology" msgstr "" msgid "Cores" msgstr "" msgid "Threads" msgstr "" msgid "CPU" msgstr "CPU" msgid "Disk I/O" msgstr "ディスク入出力" msgid "Network I/O" msgstr "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯å…¥å‡ºåŠ›" msgid "Livetile" msgstr "ライブタイル" msgid "No guests found." msgstr "ゲストãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。" msgid "Shut down" msgstr "シャットダウン" msgid "Restart" msgstr "å†å§‹å‹•" msgid "Basic Information" msgstr "基本情報" msgid "OS Distro" msgstr "OS ディストリビューション" msgid "OS Code Name" msgstr "OS コードå" msgid "CPU(s)" msgstr "" msgid "System Statistics" msgstr "システム統計情報" msgid "Update Progress" msgstr "æ›´æ–°ã®é€²è¡Œçжæ³" msgid "Network Name" msgstr "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯å" msgid "State" msgstr "状態" msgid "Network Type" msgstr "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ãƒ»ã‚¿ã‚¤ãƒ—" msgid "Address Space" msgstr "アドレス・スペース" msgid "Name should not contain '/' and '\"'." msgstr "" msgid "Isolated: no external network connection" msgstr "隔離: 物ç†ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯æŽ¥ç¶šãªã—" msgid "NAT: outbound physical network connection only" msgstr "NAT: アウトãƒã‚¦ãƒ³ãƒ‰ç‰©ç†ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯æŽ¥ç¶šã®ã¿" msgid "Bridged: Virtual machines are connected to physical network directly" msgstr "ブリッジ: 仮想マシンãŒç›´æŽ¥ç‰©ç†ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«æŽ¥ç¶šã•れる" msgid "(No interfaces found)" msgstr "" msgid "Destination" msgstr "宛先:" msgid "Enable VLAN" msgstr "VLAN を使用å¯èƒ½ã«ã™ã‚‹:" msgid "VLAN ID" msgstr "VLAN ID:" msgid "Stop" msgstr "åœæ­¢" msgid "%Used" msgstr "" msgid "Location" msgstr "ロケーション" msgid "Capacity" msgstr "容é‡" msgid "Allocated" msgstr "å‰²ã‚Šå½“ã¦æ¸ˆã¿" msgid "active" msgstr "アクティブ" msgid "inactive" msgstr "éžã‚¢ã‚¯ãƒ†ã‚£ãƒ–" msgid "Deactivate" msgstr "éžã‚¢ã‚¯ãƒ†ã‚£ãƒ–ã«ã™ã‚‹" msgid "Activate" msgstr "アクティブã«ã™ã‚‹" msgid "Add Volume" msgstr "" msgid "Extend" msgstr "" msgid "Undefine" msgstr "定義を解除ã™ã‚‹" msgid "Format" msgstr "フォーマット:" msgid "Allocation" msgstr "割り振り:" msgid "No templates found." msgstr "テンプレートãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。" kimchi-1.5.0/po/kimchi.pot000077500000000000000000001170621254252253000154010ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-06-24 09:39-0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" #, python-format msgid "Unknown parameter %(value)s" msgstr "" #, python-format msgid "Delete is not allowed for %(resource)s" msgstr "" #, python-format msgid "%(resource)s does not implement update method" msgstr "" #, python-format msgid "Create is not allowed for %(resource)s" msgstr "" msgid "Unable to parse JSON request" msgstr "" msgid "This API only supports JSON" msgstr "" #, python-format msgid "Parameters does not match requirement in schema: %(err)s" msgstr "" msgid "You don't have permission to perform this operation." msgstr "" msgid "Datastore is not initiated in the model object." msgstr "" #, python-format msgid "Unable to start task due error: %(err)s" msgstr "" #, python-format msgid "Timeout of %(seconds)s seconds expired while running task '%(task)s." msgstr "" #, python-format msgid "Authentication failed for user '%(username)s'. [Error code: %(code)s]" msgstr "" msgid "You are not authorized to access Kimchi" msgstr "" #, python-format msgid "Specify %(item)s to login into Kimchi" msgstr "" #, python-format msgid "User %(user_id)s not found with given LDAP settings." msgstr "" #, python-format msgid "Invalid LDAP configuration: %(item)s : %(value)s" msgstr "" msgid "Unknown \"_cap\" specified" msgstr "" msgid "\"_passthrough\" should be \"true\" or \"false\"" msgstr "" msgid "\"_passthrough_affected_by\" should be a device name string" msgstr "" #, python-format msgid "Error while getting block devices. Details: %(err)s" msgstr "" #, python-format msgid "Error while getting block device information for %(device)s." msgstr "" #, python-format msgid "Unable to find distro file: %(filename)s" msgstr "" #, python-format msgid "" "Unable to parse distro file: %(filename)s. Make sure, it is a JSON file." msgstr "" #, python-format msgid "Unable to login to iSCSI host target %(portal)s. Details: %(err)s" msgstr "" #, python-format msgid "Unable to login to iSCSI host %(host)s target %(target)s" msgstr "" #, python-format msgid "Unable to find ISO file %(filename)s" msgstr "" #, python-format msgid "The ISO file %(filename)s is not bootable" msgstr "" #, python-format msgid "The ISO file %(filename)s does not have a valid El Torito boot record" msgstr "" #, python-format msgid "Invalid El Torito validation entry in ISO %(filename)s" msgstr "" #, python-format msgid "Invalid El Torito boot indicator in ISO %(filename)s" msgstr "" #, python-format msgid "Unexpected volume type for primary volume in ISO %(filename)s" msgstr "" #, python-format msgid "Bad format while reading volume descriptor in ISO %(filename)s" msgstr "" #, python-format msgid "" "The hypervisor doesn't have permission to use this ISO %(filename)s. " "Consider moving it under /var/lib/libvirt, or set the search permission to " "file access control lists for '%(user)s' user if possible, or add the " "'%(user)s' to the ISO path group, or (not recommended) 'chmod -R o+x " "'path_to_iso'.Details: %(err)s" msgstr "" msgid "An error occurred when probing image OS information." msgstr "" msgid "No OS information found in given image." msgstr "" #, python-format msgid "Unable to read image file %(filename)s" msgstr "" #, python-format msgid "" "Image file must be an existing file on system. %(filename)s is not a valid " "input." msgstr "" #, python-format msgid "Virtual machine %(name)s already exists" msgstr "" #, python-format msgid "Virtual machine %(name)s does not exist" msgstr "" #, python-format msgid "" "Unable to rename virtual machine %(name)s. The name %(new_name)s is already " "in use or the virtual machine is not powered off." msgstr "" #, python-format msgid "Unable to retrieve screenshot for stopped virtual machine %(name)s" msgstr "" msgid "Remote ISO image is not supported by this server." msgstr "" #, python-format msgid "Screenshot is not supported on virtual machine %(name)s" msgstr "" #, python-format msgid "Unable to create virtual machine %(name)s. Details: %(err)s" msgstr "" #, python-format msgid "Unable to update virtual machine %(name)s. Details: %(err)s" msgstr "" #, python-format msgid "Unable to retrieve virtual machine %(name)s. Details: %(err)s" msgstr "" #, python-format msgid "Unable to connect to powered off virtual machine %(name)s." msgstr "" msgid "Virtual machine name must be a string without slashes (/)" msgstr "" #, python-format msgid "Invalid template URI %(value)s specified for virtual machine" msgstr "" #, python-format msgid "Invalid storage pool URI %(value)s specified for virtual machine" msgstr "" msgid "Supported virtual machine graphics are Spice or VNC" msgstr "" msgid "Graphics address to listen on must be IPv4 or IPv6" msgstr "" msgid "Specify a template to create a virtual machine from" msgstr "" #, python-format msgid "Unable to start virtual machine %(name)s. Details: %(err)s" msgstr "" #, python-format msgid "Unable to power off virtual machine %(name)s. Details: %(err)s" msgstr "" #, python-format msgid "Unable to delete virtual machine %(name)s. Details: %(err)s" msgstr "" #, python-format msgid "Unable to reset virtual machine %(name)s. Details: %(err)s" msgstr "" msgid "User name list must be an array" msgstr "" msgid "User name must be a string" msgstr "" msgid "Group name list must be an array" msgstr "" msgid "Group name must be a string" msgstr "" #, python-format msgid "User(s) '%(users)s' do not exist" msgstr "" #, python-format msgid "Group(s) '%(groups)s' do not exist" msgstr "" #, python-format msgid "Unable to shutdown virtual machine %(name)s. Details: %(err)s" msgstr "" #, python-format msgid "" "Unable to get access metadata of virtual machine %(name)s. Details: %(err)s" msgstr "" msgid "The guest console password must be a string." msgstr "" msgid "The life time for the guest console password must be a number." msgstr "" #, python-format msgid "Virtual machine '%(name)s' must be stopped before cloning it." msgstr "" #, python-format msgid "Insufficient disk space to clone virtual machine '%(name)s'" msgstr "" #, python-format msgid "Unable to clone VM '%(name)s'. Details: %(err)s" msgstr "" #, python-format msgid "Invalid operation for non-persistent virtual machine %(name)s" msgstr "" #, python-format msgid "Cannot suspend VM '%(name)s' because it is not running." msgstr "" #, python-format msgid "Unable to suspend VM '%(name)s'. Details: %(err)s" msgstr "" #, python-format msgid "Cannot resume VM '%(name)s' because it is not paused." msgstr "" #, python-format msgid "Unable to resume VM '%(name)s'. Details: %(err)s" msgstr "" msgid "Memory assigned is higher then the maximum allowed in the host." msgstr "" #, python-format msgid "" "VM '%(name)s' does not support live memory update. Update the memory with " "the machine offline to enable this feature." msgstr "" msgid "Only increase memory is allowed in active VMs" msgstr "" msgid "" "For live memory update, new memory value must be equal old memory value plus " "multiples of 1024 Mib" msgstr "" msgid "There are not enough free slots of 1024 Mib in the guest." msgstr "" msgid "" "Host's libvirt version does not support memory devices. Libvirt must be >= " "1.2.14" msgstr "" #, python-format msgid "Error attaching memory device. Details: %(error)s" msgstr "" #, python-format msgid "" "VM %(vmid)s does not contain directly assigned host device %(dev_name)s." msgstr "" #, python-format msgid "The host device %(dev_name)s is not allowed to directly assign to VM." msgstr "" msgid "" "No IOMMU groups found. Host PCI pass through needs IOMMU group to function " "correctly. Please enable Intel VT-d or AMD IOMMU in your BIOS, then verify " "the Kernel is compiled with IOMMU support. For Intel CPU, add intel_iommu=on " "to your Kernel parameter in /boot/grub2/grub.conf. For AMD CPU, add iommu=pt " "iommu=1." msgstr "" msgid "\"name\" should be a device name string" msgstr "" #, python-format msgid "" "The device %(name)s is probably in use by the host. Unable to attach it to " "the guest." msgstr "" #, python-format msgid "Interface %(iface)s does not exist in virtual machine %(name)s" msgstr "" #, python-format msgid "" "Network %(network)s specified for virtual machine %(name)s does not exist" msgstr "" msgid "Supported virtual machine interfaces type is only network" msgstr "" msgid "Network name for virtual machine interface must be a string" msgstr "" msgid "Invalid network model card specified for virtual machine interface" msgstr "" msgid "Specify type and network to add a new virtual machine interface" msgstr "" msgid "MAC Address must respect this format FF:FF:FF:FF:FF:FF" msgstr "" #, python-format msgid "MAC Address %(mac)s already exists in virtual machine %(name)s" msgstr "" msgid "Invalid MAC Address" msgstr "" msgid "Cannot change MAC address of a running virtual machine" msgstr "" #, python-format msgid "Template %(name)s already exists" msgstr "" #, python-format msgid "" "Network '%(network)s' specified for template %(template)s does not exist" msgstr "" #, python-format msgid "" "Storage pool %(pool)s specified for template %(template)s does not exist" msgstr "" #, python-format msgid "Storage pool %(pool)s specified for template %(template)s is not active" msgstr "" #, python-format msgid "Invalid parameter '%(param)s' specified for CDROM." msgstr "" #, python-format msgid "Network %(network)s specified for template %(template)s is not active" msgstr "" msgid "Template name must be a string" msgstr "" msgid "Template icon must be a path to the image" msgstr "" msgid "Template distribution must be a string" msgstr "" msgid "Template distribution version must be a string" msgstr "" msgid "The number of CPUs must be an integer greater than 0" msgstr "" msgid "Amount of memory (MB) must be an integer greater than 512" msgstr "" msgid "Template CDROM must be a local or remote ISO file" msgstr "" #, python-format msgid "Invalid storage pool URI %(value)s specified for template" msgstr "" msgid "Specify an ISO image as CDROM or a base image to create a template" msgstr "" msgid "All networks for the template must be specified in a list." msgstr "" msgid "Specify a volume to a template when storage pool is iSCSI or SCSI" msgstr "" #, python-format msgid "The volume %(volume)s is not in storage pool %(pool)s" msgstr "" #, python-format msgid "Unable to create template due error: %(err)s" msgstr "" #, python-format msgid "Unable to delete template due error: %(err)s" msgstr "" msgid "Disk size must be an integer greater than 1GB." msgstr "" msgid "Template base image must be a valid local image file" msgstr "" #, python-format msgid "Cannot identify base image %(path)s format" msgstr "" msgid "" "When specifying CPU topology, VCPUs must be a product of sockets, cores, and " "threads." msgstr "" msgid "" "When specifying CPU topology, each element must be an integer greater than " "zero." msgstr "" msgid "" "Invalid disk image format. Valid formats: bochs, cloop, cow, dmg, qcow, " "qcow2, qed, raw, vmdk, vpc." msgstr "" #, python-format msgid "Storage pool %(name)s already exists" msgstr "" #, python-format msgid "Storage pool %(name)s does not exist" msgstr "" #, python-format msgid "Specify %(item)s in order to create the storage pool %(name)s" msgstr "" #, python-format msgid "Unable to delete active storage pool %(name)s" msgstr "" #, python-format msgid "Unable to list storage pools. Details: %(err)s" msgstr "" #, python-format msgid "Unable to create storage pool %(name)s. Details: %(err)s" msgstr "" #, python-format msgid "" "Unable to get number of storage volumes in storage pool %(name)s. Details: " "%(err)s" msgstr "" #, python-format msgid "Unable to activate storage pool %(name)s. Details: %(err)s" msgstr "" #, python-format msgid "Unable to deactivate storage pool %(name)s. Details: %(err)s" msgstr "" #, python-format msgid "Unable to delete storage pool %(name)s. Details: %(err)s" msgstr "" #, python-format msgid "" "Unable to create NFS Pool as export path %(path)s may block during mount" msgstr "" #, python-format msgid "Unable to create NFS Pool as export path %(path)s mount failed" msgstr "" #, python-format msgid "Unsupported storage pool type: %(type)s" msgstr "" #, python-format msgid "Error while retrieving storage pool XML to %(pool)s" msgstr "" msgid "Storage pool name must be a string without slashes (/)" msgstr "" msgid "" "Supported storage pool types are dir, netfs, logical, iscsi, isci and kimchi-" "iso" msgstr "" msgid "Storage pool path must be a string" msgstr "" msgid "Storage pool host must be a IP or hostname" msgstr "" msgid "Storage pool device must be the absolute path to the block device" msgstr "" msgid "Storage pool devices parameter must be a list" msgstr "" msgid "Target IQN of an iSCSI pool must be a string" msgstr "" msgid "Port of a remote storage server must be an integer between 1 and 65535" msgstr "" msgid "iSCSI target username must be a string" msgstr "" msgid "iSCSI target password must be a string" msgstr "" msgid "Specify name and type to create a storage pool" msgstr "" #, python-format msgid "" "%(disk)s is not a valid disk/partition. Could not add it to the pool " "%(pool)s." msgstr "" #, python-format msgid "Unable to extend logical pool %(pool)s. Details: %(err)s" msgstr "" msgid "The parameter disks only can be updated for logical storage pool." msgstr "" msgid "The SCSI host adapter name must be a string." msgstr "" msgid "The storage pool kimchi_isos is reserved for internal use" msgstr "" #, python-format msgid "" "Unable to activate NFS storage pool %(name)s. NFS server %(server)s is " "unreachable." msgstr "" #, python-format msgid "" "Unable to deactivate NFS storage pool %(name)s. NFS server %(server)s is " "unreachable." msgstr "" #, python-format msgid "" "Unable to deactivate pool %(name)s as it is associated with some templates" msgstr "" #, python-format msgid "Unable to delete pool %(name)s as it is associated with some templates" msgstr "" #, python-format msgid "" "A volume group named '%(name)s' already exists. Please, choose another name " "to create the logical pool." msgstr "" #, python-format msgid "Unable to update database with deep scan information due error: %(err)s" msgstr "" #, python-format msgid "Storage volume %(name)s already exists" msgstr "" #, python-format msgid "Storage volume %(name)s does not exist in storage pool %(pool)s" msgstr "" #, python-format msgid "" "Unable to create storage volume %(volume)s because storage pool %(pool)s is " "not active" msgstr "" #, python-format msgid "Specify %(item)s in order to create storage volume %(volume)s" msgstr "" #, python-format msgid "" "Unable to list storage volumes because storage pool %(pool)s is not active" msgstr "" #, python-format msgid "" "Unable to create storage volume %(name)s in storage pool %(pool)s. Details: " "%(err)s" msgstr "" #, python-format msgid "" "Unable to list storage volumes in storage pool %(pool)s. Details: %(err)s" msgstr "" #, python-format msgid "Unable to wipe storage volumes %(name)s. Details: %(err)s" msgstr "" #, python-format msgid "Unable to delete storage volume %(name)s. Details: %(err)s" msgstr "" #, python-format msgid "Unable to resize storage volume %(name)s. Details: %(err)s" msgstr "" #, python-format msgid "Storage type %(type)s does not support volume create and delete" msgstr "" msgid "Storage volume name must be a string" msgstr "" msgid "Storage volume allocation must be an integer number" msgstr "" msgid "" "Storage volume format not supported. Valid formats: bochs, cloop, cow, dmg, " "qcow, qcow2, qed, raw, vmdk, vpc." msgstr "" msgid "Storage volume requires a volume name" msgstr "" #, python-format msgid "" "Unable to update database with storage volume information due error: %(err)s" msgstr "" #, python-format msgid "Only one of parameter %(param)s can be specified" msgstr "" #, python-format msgid "Create volume from %(param)s is not supported" msgstr "" msgid "Storage volume capacity must be an integer number." msgstr "" msgid "Storage volume URL must be http://, https://, ftp:// or ftps://." msgstr "" #, python-format msgid "Unable to access file %(url)s. Please, check it." msgstr "" #, python-format msgid "" "Unable to clone storage volume '%(name)s' in pool '%(pool)s'. Details: " "%(err)s" msgstr "" msgid "Specify chunk data and its size to upload a file." msgstr "" msgid "In order to upload a storage volume, specify the 'upload' parameter." msgstr "" msgid "" "Unable to upload chunk data as it does not match with requested chunk size." msgstr "" #, python-format msgid "The storage volume %(vol)s is not under an upload process." msgstr "" msgid "The upload chunk data will exceed the storage volume size." msgstr "" #, python-format msgid "Unable to upload chunk data to storage volume. Details: %(err)s." msgstr "" #, python-format msgid "Interface %(name)s does not exist" msgstr "" #, python-format msgid "Network %(name)s already exists" msgstr "" #, python-format msgid "Network %(name)s does not exist" msgstr "" #, python-format msgid "Subnet %(subnet)s specified for network %(network)s is not valid." msgstr "" #, python-format msgid "Specify a network interface to create bridged network %(name)s" msgstr "" #, python-format msgid "Unable to delete active network %(name)s" msgstr "" #, python-format msgid "Interface %(iface)s specified for network %(network)s is already in use" msgstr "" msgid "Interface should be bare NIC, bonding or bridge device." msgstr "" #, python-format msgid "Unable to create network %(name)s. Details: %(err)s" msgstr "" #, python-format msgid "Unable to find a free IP address for network '%(name)s'" msgstr "" #, python-format msgid "The interface %(iface)s already exists." msgstr "" msgid "Network name must be a string without slashes (/) or quotes (\")" msgstr "" msgid "Supported network types are isolated, NAT and bridge" msgstr "" msgid "Network subnet must be a string with IP address and prefix or netmask" msgstr "" msgid "Network interface must be a string" msgstr "" msgid "Network VLAN ID must be an integer between 1 and 4094" msgstr "" msgid "Specify name and type to create a Network" msgstr "" #, python-format msgid "" "Unable to delete network %(name)s. There are some virtual machines %(vms)s " "and/or templates linked to this network." msgstr "" #, python-format msgid "" "Unable to deactivate network %(name)s. There are some virtual machines " "%(vms)s and/or templates linked to this network." msgstr "" #, python-format msgid "Bridge device %(name)s can not be the trunk device of a VLAN." msgstr "" #, python-format msgid "Failed to activate interface %(iface)s: %(err)s." msgstr "" #, python-format msgid "" "Failed to activate interface %(iface)s. Please check the physical link " "status." msgstr "" #, python-format msgid "Failed to start network %(name)s. Details: %(err)s" msgstr "" #, python-format msgid "Debug report %(name)s does not exist" msgstr "" msgid "Debug report tool not found in system" msgstr "" #, python-format msgid "Unable to create debug report %(name)s. Details: %(err)s." msgstr "" #, python-format msgid "Can not find any debug report with the given name %(name)s" msgstr "" #, python-format msgid "Unable to generate debug report %(name)s. Details: %(err)s" msgstr "" msgid "You should give a name for the debug report file." msgstr "" msgid "" "Debug report name must be a string. Only letters, digits, underscore ('_') " "and hyphen ('-') are allowed." msgstr "" #, python-format msgid "" "The debug report with specified name \"%(name)s\" already exists. Please use " "another one." msgstr "" #, python-format msgid "Storage server %(server)s was not used by Kimchi" msgstr "" #, python-format msgid "Distro '%(name)s' does not exist" msgstr "" #, python-format msgid "Partition %(name)s does not exist in the host" msgstr "" msgid "Unable to shutdown host machine as there are running virtual machines" msgstr "" msgid "Unable to reboot host machine as there are running virtual machines" msgstr "" #, python-format msgid "Node device '%(name)s' not found" msgstr "" msgid "Conflicting flag filters specified." msgstr "" msgid "No packages marked for update" msgstr "" #, python-format msgid "Package %(name)s is not marked to be updated." msgstr "" #, python-format msgid "Error while getting packages marked to be updated. Details: %(err)s" msgstr "" msgid "There is no compatible package manager for this system." msgstr "" #, python-format msgid "Unable to find %(item)s in datastore" msgstr "" #, python-format msgid "Invalid URI %(uri)s" msgstr "" #, python-format msgid "Timeout while running command '%(cmd)s' after %(seconds)s seconds" msgstr "" msgid "Unable to choose a virtual machine name" msgstr "" #, python-format msgid "Invalid data value '%(value)s'" msgstr "" #, python-format msgid "Invalid data unit '%(unit)s'" msgstr "" msgid "Invalid storage type. Types supported: 'cdrom', 'disk'" msgstr "" #, python-format msgid "The path '%(value)s' is not a valid local/remote path for the device" msgstr "" msgid "Only CDROM path can be update." msgstr "" #, python-format msgid "" "The storage device %(dev_name)s does not exist in the virtual machine " "%(vm_name)s" msgstr "" #, python-format msgid "Error while creating new storage device: %(error)s" msgstr "" #, python-format msgid "Error while updating storage device: %(error)s" msgstr "" #, python-format msgid "Error while removing storage device: %(error)s" msgstr "" msgid "Do not support IDE device hot plug" msgstr "" msgid "" "Specify type and path or type and pool/volume to add a new virtual machine " "disk" msgstr "" msgid "Specify path to update virtual machine disk" msgstr "" #, python-format msgid "Controller type %(type)s limitation of %(limit)s devices reached" msgstr "" #, python-format msgid "Cannot retrieve disk path information for given pool/volume: %(error)s" msgstr "" msgid "Volume already in use by other virtual machine." msgstr "" msgid "" "Only one of path or pool/volume can be specified to add a new virtual " "machine disk" msgstr "" #, python-format msgid "" "Volume chosen with format %(format)s does not fit in the storage type " "%(type)s" msgstr "" msgid "YUM Repository ID must be one word only string." msgstr "" msgid "Repository URL must be an http://, ftp:// or file:// URL." msgstr "" msgid "" "Repository configuration is a dictionary with specific values according to " "repository type." msgstr "" msgid "Distribution to DEB repository must be a string" msgstr "" msgid "Components to DEB repository must be listed in a array" msgstr "" msgid "Components to DEB repository must be a string" msgstr "" msgid "Mirror list to repository must be a string" msgstr "" msgid "YUM Repository name must be string." msgstr "" msgid "GPG check must be a boolean value." msgstr "" msgid "GPG key must be a URL pointing to the ASCII-armored file." msgstr "" #, python-format msgid "Could not update repository %(repo_id)s." msgstr "" #, python-format msgid "Repository %(repo_id)s does not exist." msgstr "" msgid "" "Specify repository base URL, mirror list or metalink in order to create or " "update a YUM repository." msgstr "" msgid "Repository management tool was not recognized for your system." msgstr "" #, python-format msgid "Repository %(repo_id)s is already enabled." msgstr "" #, python-format msgid "Repository %(repo_id)s is already disabled." msgstr "" #, python-format msgid "Could not remove repository %(repo_id)s." msgstr "" #, python-format msgid "Could not write repository configuration file %(repo_file)s" msgstr "" msgid "Specify repository distribution in order to create a DEB repository." msgstr "" #, python-format msgid "Could not enable repository %(repo_id)s." msgstr "" #, python-format msgid "Could not disable repository %(repo_id)s." msgstr "" msgid "YUM Repository ID already exists" msgstr "" msgid "YUM Repository name must be a string" msgstr "" #, python-format msgid "Unable to list repositories. Details: '%(err)s'" msgstr "" #, python-format msgid "Unable to retrieve repository information. Details: '%(err)s'" msgstr "" #, python-format msgid "Unable to add repository. Details: '%(err)s'" msgstr "" #, python-format msgid "Unable to remove repository. Details: '%(err)s'" msgstr "" #, python-format msgid "" "Configuration items: '%(items)s' are not supported by repository manager" msgstr "" msgid "Repository metalink must be an http://, ftp:// or file:// URL." msgstr "" msgid "Cannot specify mirrorlist and metalink at the same time." msgstr "" #, python-format msgid "" "Virtual machine '%(vm)s' must be stopped before creating a snapshot of it." msgstr "" #, python-format msgid "" "Unable to create snapshot '%(name)s' on virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "Snapshot '%(name)s' does not exist on virtual machine '%(vm)s'." msgstr "" #, python-format msgid "" "Unable to retrieve snapshot '%(name)s' on virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "Unable to list snapshots on virtual machine '%(vm)s'. Details: %(err)s" msgstr "" #, python-format msgid "" "Unable to delete snapshot '%(name)s' on virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "" "Unable to retrieve current snapshot of virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "" "Unable to revert virtual machine '%(vm)s' to snapshot '%(name)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "" "Unable to create snapshot of virtual machine '%(vm)s' because it contains a " "disk with format '%(format)s'; only 'qcow2' is supported." msgstr "" msgid "The number of vCPUs is too large for this system." msgstr "" msgid "Invalid vCPU/topology combination." msgstr "" msgid "This host (or current configuration) does not allow CPU topology." msgstr "" msgid "ERROR CODE" msgstr "" msgid "REASON" msgstr "" msgid "STACK" msgstr "" msgid "Go to Homepage" msgstr "" msgid "Create a New Virtual Machine" msgstr "" msgid "Virtual Machine Name" msgstr "" msgid "" "The name used to identify the virtual machine. If omitted, a name will be " "chosen based on the template used." msgstr "" msgid "Template" msgstr "" msgid "Please create a template first." msgstr "" msgid "Create a Template" msgstr "" msgid "Please choose a template." msgstr "" msgid "OS" msgstr "" msgid "OS Version" msgstr "" msgid "CPUS" msgstr "" msgid "Memory" msgstr "" msgid "Create" msgstr "" msgid "Creating..." msgstr "" msgid "Edit Guest" msgstr "" msgid "General" msgstr "" msgid "Storage" msgstr "" msgid "Interface" msgstr "" msgid "Permission" msgstr "" msgid "Host PCI Device" msgstr "" msgid "Snapshot" msgstr "" msgid "Name" msgstr "" msgid "CPUs" msgstr "" msgid "Memory (MB)" msgstr "" msgid "Icon" msgstr "" msgid "Device" msgstr "" msgid "Path" msgstr "" msgid "Network" msgstr "" msgid "Type" msgstr "" msgid "MAC Address" msgstr "" msgid "Available system users and groups" msgstr "" msgid "Selected system users and groups" msgstr "" msgid "User" msgstr "" msgid "All" msgstr "" msgid "To Add" msgstr "" msgid "Added" msgstr "" msgid "filter" msgstr "" msgid "Product" msgstr "" msgid "Vendor" msgstr "" msgid "Created" msgstr "" msgid "Save" msgstr "" msgid "Replace" msgstr "" msgid "Detach" msgstr "" msgid "Cancel" msgstr "" msgid "revert" msgstr "" msgid "Add a Storage Device to VM" msgstr "" msgid "Device Type" msgstr "" msgid "The device type. Currently, \"cdrom\" and \"disk\" are supported." msgstr "" msgid "Storage Pool" msgstr "" msgid "Storage pool which volume located in" msgstr "" msgid "Storage Volume" msgstr "" msgid "Storage volume to be attached" msgstr "" msgid "File Path" msgstr "" msgid "The ISO file path in the server for CDROM." msgstr "" msgid "Attach" msgstr "" msgid "Start" msgstr "" msgid "Reset" msgstr "" msgid "Pause" msgstr "" msgid "Resume" msgstr "" msgid "Power Off" msgstr "" msgid "Actions" msgstr "" msgid "Connect" msgstr "" msgid "Clone" msgstr "" msgid "Edit" msgstr "" msgid "Shut Down" msgstr "" msgid "Delete" msgstr "" msgid "The username or password you entered is incorrect. Please try again." msgstr "" msgid "This field is required." msgstr "" msgid "Log in" msgstr "" msgid "Logging in..." msgstr "" msgid "Host" msgstr "" msgid "Guests" msgstr "" msgid "Templates" msgstr "" msgid "Failed to get application configuration" msgstr "" msgid "This is not a valid Linux path" msgstr "" msgid "This is not a valid URL." msgstr "" msgid "No such data available." msgstr "" msgid "" "Can not contact the host system. Verify the host system is up and that you " "have network connectivity to it. HTTP request response %1. " msgstr "" msgid "Unable to read file." msgstr "" msgid "Error while uploading file." msgstr "" msgid "Delete Confirmation" msgstr "" msgid "OK" msgstr "" msgid "Confirm" msgstr "" msgid "Warning" msgstr "" msgid "Cloning..." msgstr "" msgid "Loading..." msgstr "" msgid "An error occurred while retrieving system information." msgstr "" msgid "Retry" msgstr "" msgid "Detailed message:" msgstr "" msgid "No ISO found" msgstr "" msgid "This is not a valid ISO file." msgstr "" msgid "This may take a long time. Do you want to continue?" msgstr "" msgid "This will permanently delete the template. Would you like to continue?" msgstr "" msgid "Unable to shut down system as there are some virtual machines running!" msgstr "" msgid "Max:" msgstr "" msgid "Utilization" msgstr "" msgid "Available" msgstr "" msgid "Read Rate" msgstr "" msgid "Write Rate" msgstr "" msgid "Received" msgstr "" msgid "Sent" msgstr "" msgid "" "Shutting down or restarting host will cause unsaved work lost. Continue to " "shut down/restarting?" msgstr "" msgid "" "Repository will be removed permanently and can't be recovered. Do you want " "to continue?" msgstr "" msgid "Repositories" msgstr "" msgid "ID" msgstr "" msgid "Base URL" msgstr "" msgid "Is Mirror" msgstr "" msgid "URL Args" msgstr "" msgid "Enabled" msgstr "" msgid "GPG Check" msgstr "" msgid "GPG Key" msgstr "" msgid "Add" msgstr "" msgid "Remove" msgstr "" msgid "Enable" msgstr "" msgid "Disable" msgstr "" msgid "Software Updates" msgstr "" msgid "Package Name" msgstr "" msgid "Version" msgstr "" msgid "Architecture" msgstr "" msgid "Repository" msgstr "" msgid "Update All" msgstr "" msgid "Updating..." msgstr "" msgid "Failed to retrieve packages update information." msgstr "" msgid "Failed to update package(s)." msgstr "" msgid "" "Debug report will be removed permanently and can't be recovered. Do you want " "to continue?" msgstr "" msgid "Debug Reports" msgstr "" msgid "Generated Time" msgstr "" msgid "Generate" msgstr "" msgid "Generating..." msgstr "" msgid "Rename" msgstr "" msgid "Download" msgstr "" msgid "" "Report name should contain only letters, digits, underscore ('_') and/or " "hyphen ('-')." msgstr "" msgid "Pending..." msgstr "" msgid "Report name is the same as the original one." msgstr "" msgid "" "This will delete the virtual machine and its virtual disks. This operation " "cannot be undone. Would you like to continue?" msgstr "" msgid "Power off Confirmation" msgstr "" msgid "" "This action may produce undesirable results, for example unflushed disk " "cache in the guest. Would you like to continue?" msgstr "" msgid "Reset Confirmation" msgstr "" msgid "" "There is a risk of data loss caused by reset without the guest OS shutdown. " "Would you like to continue?" msgstr "" msgid "Shut Down Confirmation" msgstr "" msgid "Note the guest OS may ignore this request. Would you like to continue?" msgstr "" msgid "Virtual Machine delete Confirmation" msgstr "" msgid "" "This virtual machine is not persistent. Power Off will delete it. Continue?" msgstr "" msgid "" "When the target guest has SCSI or iSCSI volumes, they will be cloned on " "default storage pool. The same will happen when the target pool does not " "have enough space to clone the volumes. Do you want to continue?" msgstr "" msgid "" "This CDROM will be detached permanently and you can re-attach it. Continue " "to detach it?" msgstr "" msgid "Attaching..." msgstr "" msgid "Replacing..." msgstr "" msgid "Successfully attached!" msgstr "" msgid "Successfully replaced!" msgstr "" msgid "Successfully detached!" msgstr "" msgid "" "This disk will be detached permanently and you can re-attach it. Continue to " "detach it?" msgstr "" msgid "interface:" msgstr "" msgid "address:" msgstr "" msgid "link_type:" msgstr "" msgid "block:" msgstr "" msgid "drive_type:" msgstr "" msgid "model:" msgstr "" msgid "Affected devices:" msgstr "" msgid "The VLAN id must be between 1 and 4094." msgstr "" msgid "unavailable" msgstr "" msgid "" "This action will interrupt network connectivity for any virtual machine that " "depend on this network." msgstr "" msgid "Create a network" msgstr "" msgid "" "This network is not persistent. Instead of stop, this action will " "permanently delete it. Would you like to continue?" msgstr "" msgid "" "The bridged VLAN tag may not work well with NetworkManager enabled. You " "should consider disabling it." msgstr "" msgid "" "This will permanently delete the storage pool. Would you like to continue?" msgstr "" msgid "This storage pool is empty." msgstr "" msgid "" "It will format your disk and you will loose any data in there, are you sure " "to continue? " msgstr "" msgid "SCSI Fibre Channel" msgstr "" msgid "No SCSI adapters found." msgstr "" msgid "Loading iSCSI targets..." msgstr "" msgid "No iSCSI found. Please input one." msgstr "" msgid "Failed to load iSCSI targets." msgstr "" msgid "The storage pool name can not be blank." msgstr "" msgid "The storage pool path can not be blank." msgstr "" msgid "NFS server mount path can not be blank." msgstr "" msgid "Invalid NFS mount path." msgstr "" msgid "No logical device selected." msgstr "" msgid "The iSCSI target can not be blank." msgstr "" msgid "Server name can not be blank." msgstr "" msgid "This is not a valid Server Name or IP. Please, modify it." msgstr "" msgid "Looking for available partitions ..." msgstr "" msgid "No available partitions found." msgstr "" msgid "" "This storage pool is not persistent. Instead of deactivate, this action will " "permanently delete it. Would you like to continue?" msgstr "" msgid "Unable to retrieve partitions information." msgstr "" msgid "In progress..." msgstr "" msgid "Failed!" msgstr "" msgid "CDROM path needs to be a valid local/remote path and cannot be blank." msgstr "" msgid "Disk pool or volume cannot be blank." msgstr "" msgid "Peers" msgstr "" msgid "Searching" msgstr "" msgid "No peers found." msgstr "" msgid "Help" msgstr "" msgid "About" msgstr "" msgid "Log out" msgstr "" msgid "Version:" msgstr "" msgid "Session timeout, please re-login." msgstr "" msgid "User Name" msgstr "" msgid "Password" msgstr "" msgid "Generate a New Debug Report" msgstr "" msgid "Report Name" msgstr "" msgid "" "The name used to identify the report. If omitted, a name will be chosen " "based on current time. Name can contain: letters, digits, underscore (\"_\") " "and hyphen (\"-\")." msgstr "" msgid "Rename a Debug Report" msgstr "" msgid "" "The name used to identify the report. Name can contain: letters, digits and " "hyphen (\"-\")." msgstr "" msgid "Submit" msgstr "" msgid "Add a Repository" msgstr "" msgid "Identifier" msgstr "" msgid "Single word, unique identifier for the repository." msgstr "" msgid "Textual name for the repository." msgstr "" msgid "URL" msgstr "" msgid "Required Field" msgstr "" msgid "URL to the repository. Supported protocols are http, ftp, and file." msgstr "" msgid "Repository is a mirror" msgstr "" msgid "Distribution" msgstr "" msgid "Distribution of the DEB repository." msgstr "" msgid "Components" msgstr "" msgid "List of components in DEB repository." msgstr "" msgid "Edit Repository" msgstr "" msgid "Mirror List URL" msgstr "" msgid "Yes" msgstr "" msgid "No" msgstr "" msgid "Add a Volume to Storage Pool" msgstr "" msgid "Fetch from remote URL" msgstr "" msgid "Enter the remote URL here." msgstr "" msgid "Upload a file" msgstr "" msgid "Choose the file you want to upload." msgstr "" msgid "Define a New Storage Pool" msgstr "" msgid "Storage Pool Name" msgstr "" msgid "" "The name used to identify the storage pools, and it should not be empty." msgstr "" msgid "Storage Pool Type" msgstr "" msgid "Storage Path" msgstr "" msgid "" "The path of the Storage Pool. Each Storage Pool must have a unique path." msgstr "" msgid "" "Kimchi will try to create the directory when it does not already exist in " "your system." msgstr "" msgid "NFS Server IP" msgstr "" msgid "NFS server IP or hostname. It can be input or chosen from history." msgstr "" msgid "NFS Path" msgstr "" msgid "The NFS exported path on NFS server." msgstr "" msgid "Device path" msgstr "" msgid "iSCSI Server" msgstr "" msgid "iSCSI server IP or hostname. It should not be empty." msgstr "" msgid "Server" msgstr "" msgid "Port" msgstr "" msgid "Target" msgstr "" msgid "The iSCSI target on iSCSI server" msgstr "" msgid "Add iSCSI Authentication" msgstr "" msgid "iSCSI Authentication" msgstr "" msgid "SCSI Adapter" msgstr "" msgid "Please, wait..." msgstr "" msgid "Add Template" msgstr "" msgid "Where is the source media for this template? " msgstr "" msgid "Local ISO Image" msgstr "" msgid "Local Image File" msgstr "" msgid "Remote ISO Image" msgstr "" msgid "Search ISOs" msgstr "" msgid "The following ISOs are available:" msgstr "" msgid "OS: " msgstr "" msgid "Version: " msgstr "" msgid "Size: " msgstr "" msgid "Search more ISOs" msgstr "" msgid "Create Templates from Selected ISO" msgstr "" msgid "I want to use a specific ISO file" msgstr "" msgid "Loading default remote ISOs ..." msgstr "" msgid "Arch: " msgstr "" msgid "I want to use a custom URL" msgstr "" msgid "Edit Template" msgstr "" msgid "Processor" msgstr "" msgid "CDROM" msgstr "" msgid "Image File" msgstr "" msgid "Graphics" msgstr "" msgid "Disk(GB)" msgstr "" msgid "Disk Format" msgstr "" msgid "CPU Number" msgstr "" msgid "Manually set CPU topology" msgstr "" msgid "Cores" msgstr "" msgid "Threads" msgstr "" msgid "CPU" msgstr "" msgid "Disk I/O" msgstr "" msgid "Network I/O" msgstr "" msgid "Livetile" msgstr "" msgid "No guests found." msgstr "" msgid "Shut down" msgstr "" msgid "Restart" msgstr "" msgid "Basic Information" msgstr "" msgid "OS Distro" msgstr "" msgid "OS Code Name" msgstr "" msgid "CPU(s)" msgstr "" msgid "System Statistics" msgstr "" msgid "Update Progress" msgstr "" msgid "Network Name" msgstr "" msgid "State" msgstr "" msgid "Network Type" msgstr "" msgid "Address Space" msgstr "" msgid "Name should not contain '/' and '\"'." msgstr "" msgid "Isolated: no external network connection" msgstr "" msgid "NAT: outbound physical network connection only" msgstr "" msgid "Bridged: Virtual machines are connected to physical network directly" msgstr "" msgid "(No interfaces found)" msgstr "" msgid "Destination" msgstr "" msgid "Enable VLAN" msgstr "" msgid "VLAN ID" msgstr "" msgid "Stop" msgstr "" msgid "%Used" msgstr "" msgid "Location" msgstr "" msgid "Capacity" msgstr "" msgid "Allocated" msgstr "" msgid "active" msgstr "" msgid "inactive" msgstr "" msgid "Deactivate" msgstr "" msgid "Activate" msgstr "" msgid "Add Volume" msgstr "" msgid "Extend" msgstr "" msgid "Undefine" msgstr "" msgid "Format" msgstr "" msgid "Allocation" msgstr "" msgid "No templates found." msgstr "" kimchi-1.5.0/po/ko_KR.po000066400000000000000000001701611254252253000147520ustar00rootroot00000000000000# English translations for kimchi package. # Copyright (C) 2013 ORGANIZATION # msgid "" msgstr "" "Project-Id-Version: kimchi 0.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-06-24 09:39-0300\n" "PO-Revision-Date: 2013-07-11 17:32-0400\n" "Last-Translator: Crístian Viana \n" "Language-Team: English\n" "Language: ko_KR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: pygettext.py 1.5\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #, python-format msgid "Unknown parameter %(value)s" msgstr "" #, python-format msgid "Delete is not allowed for %(resource)s" msgstr "%(resource)sì˜ ì‚­ì œëŠ” 허용ë˜ì§€ 않ìŒ" #, python-format msgid "%(resource)s does not implement update method" msgstr "%(resource)sì—서는 ì—…ë°ì´íЏ 메소드를 구현하지 않ìŒ" #, python-format msgid "Create is not allowed for %(resource)s" msgstr "%(resource)sì˜ ìž‘ì„±ì€ í—ˆìš©ë˜ì§€ 않ìŒ" msgid "Unable to parse JSON request" msgstr "JSON ìš”ì²­ì„ êµ¬ë¬¸ ë¶„ì„í•  수 없습니다." msgid "This API only supports JSON" msgstr "ì´ API는 JSONë§Œ ì§€ì›í•©ë‹ˆë‹¤." #, python-format msgid "Parameters does not match requirement in schema: %(err)s" msgstr "" msgid "You don't have permission to perform this operation." msgstr "" msgid "Datastore is not initiated in the model object." msgstr "ë°ì´í„° 저장소가 ëª¨ë¸ ì˜¤ë¸Œì íЏì—서 시작ë˜ì§€ 않았습니다." #, python-format msgid "Unable to start task due error: %(err)s" msgstr "오류 ë•Œë¬¸ì— ìž‘ì—…ì„ ì‹œìž‘í•  수 ì—†ìŒ: %(err)s" #, python-format msgid "Timeout of %(seconds)s seconds expired while running task '%(task)s." msgstr "" #, python-format msgid "Authentication failed for user '%(username)s'. [Error code: %(code)s]" msgstr "ì‚¬ìš©ìž '%(username)s'ì˜ ì¸ì¦ì´ 실패했습니다. [오류 코드: %(code)s]" msgid "You are not authorized to access Kimchi" msgstr "Kimchiì— ì•¡ì„¸ìŠ¤í•  ê¶Œí•œì´ ì—†ìŠµë‹ˆë‹¤." #, python-format msgid "Specify %(item)s to login into Kimchi" msgstr "Kimchiì— ë¡œê·¸ì¸í•˜ë ¤ë©´ %(item)sì„(를) 지정하십시오." #, python-format msgid "User %(user_id)s not found with given LDAP settings." msgstr "" #, python-format msgid "Invalid LDAP configuration: %(item)s : %(value)s" msgstr "" msgid "Unknown \"_cap\" specified" msgstr "" msgid "\"_passthrough\" should be \"true\" or \"false\"" msgstr "" msgid "\"_passthrough_affected_by\" should be a device name string" msgstr "" #, python-format msgid "Error while getting block devices. Details: %(err)s" msgstr "ë¸”ë¡ ìž¥ì¹˜ë¥¼ 가져오는 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤. 세부사항: %(err)s" #, python-format msgid "Error while getting block device information for %(device)s." msgstr "%(device)sì— ëŒ€í•œ ë¸”ë¡ ìž¥ì¹˜ 정보를 가져오는 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤." #, python-format msgid "Unable to find distro file: %(filename)s" msgstr "distro 파ì¼ì„ ì°¾ì„ ìˆ˜ ì—†ìŒ: %(filename)s" #, python-format msgid "" "Unable to parse distro file: %(filename)s. Make sure, it is a JSON file." msgstr "" "distro 파ì¼(%(filename)s)ì„ êµ¬ë¬¸ ë¶„ì„í•  수 없습니다. JSON 파ì¼ì¸ì§€ 확ì¸í•˜ì‹­ì‹œ" "오." #, python-format msgid "Unable to login to iSCSI host target %(portal)s. Details: %(err)s" msgstr "iSCSI 호스트 ëŒ€ìƒ %(portal)sì— ë¡œê·¸ì¸í•  수 없습니다. 세부사항: %(err)s" #, python-format msgid "Unable to login to iSCSI host %(host)s target %(target)s" msgstr "iSCSI host %(host)s ëŒ€ìƒ %(target)sì— ë¡œê·¸ì¸í•  수 없습니다." #, python-format msgid "Unable to find ISO file %(filename)s" msgstr "" #, python-format msgid "The ISO file %(filename)s is not bootable" msgstr "ISO íŒŒì¼ %(filename)sì€(는) 부트 가능하지 않습니다." #, python-format msgid "The ISO file %(filename)s does not have a valid El Torito boot record" msgstr "ISO íŒŒì¼ %(filename)sì— ìœ íš¨í•œ El Torito 부트 레코드가 없습니다." #, python-format msgid "Invalid El Torito validation entry in ISO %(filename)s" msgstr "" "ISO %(filename)sì— ì˜¬ë°”ë¥´ì§€ ì•Šì€ El Torito 유효성 ê²€ì¦ í•­ëª©ì´ ìžˆìŠµë‹ˆë‹¤." #, python-format msgid "Invalid El Torito boot indicator in ISO %(filename)s" msgstr "ISO %(filename)sì— ì˜¬ë°”ë¥´ì§€ ì•Šì€ El Torito 부트 표시기가 있습니다." #, python-format msgid "Unexpected volume type for primary volume in ISO %(filename)s" msgstr "ISO %(filename)sì—서 기본 ë³¼ë¥¨ì´ ì˜ˆìƒì¹˜ ì•Šì€ ë³¼ë¥¨ 유형입니다." #, python-format msgid "Bad format while reading volume descriptor in ISO %(filename)s" msgstr "" "ISO %(filename)sì—서 볼륨 디스í¬ë¦½í„°ë¥¼ ì½ëŠ” ì¤‘ì— ìž˜ëª»ëœ í˜•ì‹ì´ 발견ë˜ì—ˆìŠµë‹ˆ" "다." #, python-format msgid "" "The hypervisor doesn't have permission to use this ISO %(filename)s. " "Consider moving it under /var/lib/libvirt, or set the search permission to " "file access control lists for '%(user)s' user if possible, or add the " "'%(user)s' to the ISO path group, or (not recommended) 'chmod -R o+x " "'path_to_iso'.Details: %(err)s" msgstr "" "하ì´í¼ë°”ì´ì €ê°€ ì´ ISO %(filename)sì„(를) 사용할 ê¶Œí•œì´ ì—†ìŠµë‹ˆë‹¤. ì´ë¥¼ /var/" "lib/libvirt 아래로 ì´ë™ì‹œí‚¤ê±°ë‚˜, (가능한 경우) 검색 ê¶Œí•œì„ '%(user)s' 사용ìž" "ì˜ íŒŒì¼ ì•¡ì„¸ìŠ¤ 제어 목ë¡ì— 설정하거나, '%(user)s'ì„(를) ISO 경로 ê·¸ë£¹ì— ì¶”ê°€" "하거나, 'chmod -R o+x 'path_to_iso'(권장ë˜ì§€ 않ìŒ)ì— ì¶”ê°€í•˜ì‹­ì‹œì˜¤. 세부사항: " "%(err)s" msgid "An error occurred when probing image OS information." msgstr "" msgid "No OS information found in given image." msgstr "" #, python-format msgid "Unable to read image file %(filename)s" msgstr "" #, python-format msgid "" "Image file must be an existing file on system. %(filename)s is not a valid " "input." msgstr "" #, python-format msgid "Virtual machine %(name)s already exists" msgstr "ê°€ìƒ ë¨¸ì‹  %(name)sì´(ê°€) ì´ë¯¸ 존재합니다." #, python-format msgid "Virtual machine %(name)s does not exist" msgstr "ê°€ìƒ ë¨¸ì‹  %(name)sì´(ê°€) 없습니다." #, python-format msgid "" "Unable to rename virtual machine %(name)s. The name %(new_name)s is already " "in use or the virtual machine is not powered off." msgstr "" #, python-format msgid "Unable to retrieve screenshot for stopped virtual machine %(name)s" msgstr "ì¤‘ì§€ëœ ê°€ìƒ ë¨¸ì‹  %(name)sì— ëŒ€í•œ 스í¬ë¦°ìƒ·ì„ 검색할 수 없습니다." msgid "Remote ISO image is not supported by this server." msgstr "ì›ê²© ISO ì´ë¯¸ì§€ëŠ” ì´ ì„œë²„ì—서 ì§€ì›í•˜ì§€ 않습니다." #, python-format msgid "Screenshot is not supported on virtual machine %(name)s" msgstr "" #, python-format msgid "Unable to create virtual machine %(name)s. Details: %(err)s" msgstr "ê°€ìƒ ë¨¸ì‹  %(name)sì„(를) 작성할 수 없습니다. 세부사항: %(err)s" #, python-format msgid "Unable to update virtual machine %(name)s. Details: %(err)s" msgstr "ê°€ìƒ ë¨¸ì‹  %(name)sì„(를) 작성할 수 없습니다. 세부사항: %(err)s" #, python-format msgid "Unable to retrieve virtual machine %(name)s. Details: %(err)s" msgstr "ê°€ìƒ ë¨¸ì‹  %(name)sì„(를) 검색할 수 없습니다. 세부사항: %(err)s" #, python-format msgid "Unable to connect to powered off virtual machine %(name)s." msgstr "" msgid "Virtual machine name must be a string without slashes (/)" msgstr "" #, python-format msgid "Invalid template URI %(value)s specified for virtual machine" msgstr "" #, python-format msgid "Invalid storage pool URI %(value)s specified for virtual machine" msgstr "" msgid "Supported virtual machine graphics are Spice or VNC" msgstr "" msgid "Graphics address to listen on must be IPv4 or IPv6" msgstr "ì²­ì·¨ ëŒ€ìƒ ê·¸ëž˜í”½ 주소는 IPv4 ë˜ëŠ” IPv6여야 합니다." msgid "Specify a template to create a virtual machine from" msgstr "ê°€ìƒ ë¨¸ì‹ ì„ ìž‘ì„±í•˜ê¸° 위한 템플리트를 지정하십시오." #, python-format msgid "Unable to start virtual machine %(name)s. Details: %(err)s" msgstr "ê°€ìƒ ë¨¸ì‹  %(name)sì„(를) 시작할 수 없습니다. 세부사항: %(err)s" #, python-format msgid "Unable to power off virtual machine %(name)s. Details: %(err)s" msgstr "ê°€ìƒ ë¨¸ì‹  %(name)sì„(를) 중지할 수 없습니다. 세부사항: %(err)s" #, python-format msgid "Unable to delete virtual machine %(name)s. Details: %(err)s" msgstr "ê°€ìƒ ë¨¸ì‹  %(name)sì„(를) 삭제할 수 없습니다. 세부사항: %(err)s" #, python-format msgid "Unable to reset virtual machine %(name)s. Details: %(err)s" msgstr "ê°€ìƒ ë¨¸ì‹  %(name)sì˜ ì´ë¦„ì„ ë°”ê¿€ 수 없습니다. 세부사항: %(err)s" msgid "User name list must be an array" msgstr "" msgid "User name must be a string" msgstr "ë„¤íŠ¸ì›Œí¬ ì´ë¦„ì€ ë¬¸ìžì—´ì´ì–´ì•¼ 합니다." msgid "Group name list must be an array" msgstr "" msgid "Group name must be a string" msgstr "ë„¤íŠ¸ì›Œí¬ ì´ë¦„ì€ ë¬¸ìžì—´ì´ì–´ì•¼ 합니다." #, python-format msgid "User(s) '%(users)s' do not exist" msgstr "'%(users)s' 사용ìžê°€ 없습니다." #, python-format msgid "Group(s) '%(groups)s' do not exist" msgstr "'%(groups)s' 사용ìžê°€ 없습니다." #, python-format msgid "Unable to shutdown virtual machine %(name)s. Details: %(err)s" msgstr "ê°€ìƒ ë¨¸ì‹  %(name)sì„(를) 중지할 수 없습니다. 세부사항: %(err)s" #, python-format msgid "" "Unable to get access metadata of virtual machine %(name)s. Details: %(err)s" msgstr "ê°€ìƒ ë¨¸ì‹  %(name)sì„(를) 시작할 수 없습니다. 세부사항: %(err)s" msgid "The guest console password must be a string." msgstr "" msgid "The life time for the guest console password must be a number." msgstr "" #, python-format msgid "Virtual machine '%(name)s' must be stopped before cloning it." msgstr "" #, python-format msgid "Insufficient disk space to clone virtual machine '%(name)s'" msgstr "" #, python-format msgid "Unable to clone VM '%(name)s'. Details: %(err)s" msgstr "" #, python-format msgid "Invalid operation for non-persistent virtual machine %(name)s" msgstr "" #, python-format msgid "Cannot suspend VM '%(name)s' because it is not running." msgstr "" #, python-format msgid "Unable to suspend VM '%(name)s'. Details: %(err)s" msgstr "" #, python-format msgid "Cannot resume VM '%(name)s' because it is not paused." msgstr "" #, python-format msgid "Unable to resume VM '%(name)s'. Details: %(err)s" msgstr "" msgid "Memory assigned is higher then the maximum allowed in the host." msgstr "" #, python-format msgid "" "VM '%(name)s' does not support live memory update. Update the memory with " "the machine offline to enable this feature." msgstr "" msgid "Only increase memory is allowed in active VMs" msgstr "" msgid "" "For live memory update, new memory value must be equal old memory value plus " "multiples of 1024 Mib" msgstr "" msgid "There are not enough free slots of 1024 Mib in the guest." msgstr "" msgid "" "Host's libvirt version does not support memory devices. Libvirt must be >= " "1.2.14" msgstr "" #, python-format msgid "Error attaching memory device. Details: %(error)s" msgstr "" #, python-format msgid "" "VM %(vmid)s does not contain directly assigned host device %(dev_name)s." msgstr "" #, python-format msgid "The host device %(dev_name)s is not allowed to directly assign to VM." msgstr "" msgid "" "No IOMMU groups found. Host PCI pass through needs IOMMU group to function " "correctly. Please enable Intel VT-d or AMD IOMMU in your BIOS, then verify " "the Kernel is compiled with IOMMU support. For Intel CPU, add intel_iommu=on " "to your Kernel parameter in /boot/grub2/grub.conf. For AMD CPU, add iommu=pt " "iommu=1." msgstr "" msgid "\"name\" should be a device name string" msgstr "" #, python-format msgid "" "The device %(name)s is probably in use by the host. Unable to attach it to " "the guest." msgstr "" #, python-format msgid "Interface %(iface)s does not exist in virtual machine %(name)s" msgstr "ê°€ìƒ ë¨¸ì‹  %(name)sì— %(iface)s ì¸í„°íŽ˜ì´ìŠ¤ê°€ 없습니다." #, python-format msgid "" "Network %(network)s specified for virtual machine %(name)s does not exist" msgstr "ê°€ìƒ ë¨¸ì‹  %(name)sì— ëŒ€í•´ ì§€ì •ëœ %(network)s 네트워í¬ê°€ 없습니다." msgid "Supported virtual machine interfaces type is only network" msgstr "ì§€ì›ë˜ëŠ” ê°€ìƒ ë¨¸ì‹  ì¸í„°íŽ˜ì´ìФ ìœ í˜•ì€ ë„¤íŠ¸ì›Œí¬ë¿ìž…니다." msgid "Network name for virtual machine interface must be a string" msgstr "ê°€ìƒ ë¨¸ì‹  ì¸í„°íŽ˜ì´ìŠ¤ì˜ ë„¤íŠ¸ì›Œí¬ ì´ë¦„ì€ ë¬¸ìžì—´ì´ì–´ì•¼ 합니다." msgid "Invalid network model card specified for virtual machine interface" msgstr "" "ê°€ìƒ ë¨¸ì‹  ì¸í„°íŽ˜ì´ìŠ¤ì— ëŒ€í•´ 올바르지 ì•Šì€ ë„¤íŠ¸ì›Œí¬ ëª¨ë¸ ì¹´ë“œê°€ 지정ë˜ì—ˆìŠµë‹ˆ" "다." msgid "Specify type and network to add a new virtual machine interface" msgstr "새 ê°€ìƒ ë¨¸ì‹  ì¸í„°íŽ˜ì´ìŠ¤ë¥¼ 추가할 유형 ë° ë„¤íŠ¸ì›Œí¬ë¥¼ 지정하십시오." msgid "MAC Address must respect this format FF:FF:FF:FF:FF:FF" msgstr "" #, python-format msgid "MAC Address %(mac)s already exists in virtual machine %(name)s" msgstr "" msgid "Invalid MAC Address" msgstr "" msgid "Cannot change MAC address of a running virtual machine" msgstr "" #, python-format msgid "Template %(name)s already exists" msgstr "템플리트 %(name)sì´(ê°€) ì´ë¯¸ 존재합니다." #, python-format msgid "" "Network '%(network)s' specified for template %(template)s does not exist" msgstr "템플리트 %(template)sì— ëŒ€í•´ ì§€ì •ëœ '%(network)s' 네트워í¬ê°€ 없습니다." #, python-format msgid "" "Storage pool %(pool)s specified for template %(template)s does not exist" msgstr "" "템플리트 %(template)sì— ëŒ€í•´ ì§€ì •ëœ ìŠ¤í† ë¦¬ì§€ í’€ %(pool)sì´(ê°€) 없습니다." #, python-format msgid "Storage pool %(pool)s specified for template %(template)s is not active" msgstr "" "템플리트 %(template)sì— ëŒ€í•´ ì§€ì •ëœ ìŠ¤í† ë¦¬ì§€ í’€ %(pool)sì´(ê°€) í™œì„±ì´ ì•„ë‹™ë‹ˆ" "다." #, python-format msgid "Invalid parameter '%(param)s' specified for CDROM." msgstr "CDROMì— ëŒ€í•´ 올바르지 ì•Šì€ ë§¤ê°œë³€ìˆ˜ '%(param)s'ì´(ê°€) 지정ë˜ì—ˆìŠµë‹ˆë‹¤." #, python-format msgid "Network %(network)s specified for template %(template)s is not active" msgstr "" "템플리트 %(template)sì— ëŒ€í•´ ì§€ì •ëœ %(network)s 네트워í¬ê°€ í™œì„±ì´ ì•„ë‹™ë‹ˆë‹¤." msgid "Template name must be a string" msgstr "템플리트 ì´ë¦„ì€ ë¬¸ìžì—´ì´ì–´ì•¼ 합니다." msgid "Template icon must be a path to the image" msgstr "템플리트 ì•„ì´ì½˜ì€ ì´ë¯¸ì§€ì˜ 경로여야 합니다." msgid "Template distribution must be a string" msgstr "템플리트 ë°°í¬ëŠ” 문ìžì—´ì´ì–´ì•¼ 합니다." msgid "Template distribution version must be a string" msgstr "템플리트 ë°°í¬ ë²„ì „ì€ ë¬¸ìžì—´ì´ì–´ì•¼ 합니다." msgid "The number of CPUs must be an integer greater than 0" msgstr "CPU 수는 정수여야 합니다." msgid "Amount of memory (MB) must be an integer greater than 512" msgstr "메모리 용량(MB)ì€ 512보다 í° ì •ìˆ˜ì—¬ì•¼ 합니다." msgid "Template CDROM must be a local or remote ISO file" msgstr "템플리트 CDROMì€ ë¡œì»¬ ë˜ëŠ” ì›ê²© ISO 파ì¼ì´ì–´ì•¼ 합니다." #, python-format msgid "Invalid storage pool URI %(value)s specified for template" msgstr "" "í…œí”Œë¦¬íŠ¸ì— ëŒ€í•´ 올바르지 ì•Šì€ ìŠ¤í† ë¦¬ì§€ í’€ URI %(value)sì´(ê°€) 지정ë˜ì—ˆìŠµë‹ˆë‹¤." msgid "Specify an ISO image as CDROM or a base image to create a template" msgstr "템플리트를 작성하려면 ISO ì´ë¯¸ì§€ë¥¼ CDROM으로 지정하십시오." msgid "All networks for the template must be specified in a list." msgstr "í…œí”Œë¦¬íŠ¸ì˜ ëª¨ë“  네트워í¬ê°€ 목ë¡ì— 지정ë˜ì–´ì•¼ 합니다." msgid "Specify a volume to a template when storage pool is iSCSI or SCSI" msgstr "" #, python-format msgid "The volume %(volume)s is not in storage pool %(pool)s" msgstr "" #, python-format msgid "Unable to create template due error: %(err)s" msgstr "오류 ë•Œë¬¸ì— í…œí”Œë¦¬íŠ¸ë¥¼ 작성할 수 ì—†ìŒ: %(err)s" #, python-format msgid "Unable to delete template due error: %(err)s" msgstr "오류 ë•Œë¬¸ì— í…œí”Œë¦¬íŠ¸ë¥¼ 삭제할 수 ì—†ìŒ: %(err)s" msgid "Disk size must be an integer greater than 1GB." msgstr "" msgid "Template base image must be a valid local image file" msgstr "템플리트 CDROMì€ ë¡œì»¬ ë˜ëŠ” ì›ê²© ISO 파ì¼ì´ì–´ì•¼ 합니다." #, python-format msgid "Cannot identify base image %(path)s format" msgstr "" msgid "" "When specifying CPU topology, VCPUs must be a product of sockets, cores, and " "threads." msgstr "" msgid "" "When specifying CPU topology, each element must be an integer greater than " "zero." msgstr "" msgid "" "Invalid disk image format. Valid formats: bochs, cloop, cow, dmg, qcow, " "qcow2, qed, raw, vmdk, vpc." msgstr "" #, python-format msgid "Storage pool %(name)s already exists" msgstr "스토리지 í’€ %(name)sì´(ê°€) ì´ë¯¸ 존재합니다." #, python-format msgid "Storage pool %(name)s does not exist" msgstr "스토리지 í’€ %(name)sì´(ê°€) 없습니다." #, python-format msgid "Specify %(item)s in order to create the storage pool %(name)s" msgstr "스토리지 í’€ %(name)sì„(를) 작성하려면 %(item)sì„(를) 지정하십시오." #, python-format msgid "Unable to delete active storage pool %(name)s" msgstr "활성 스토리지 í’€ %(name)sì„(를) 삭제할 수 없습니다." #, python-format msgid "Unable to list storage pools. Details: %(err)s" msgstr "스토리지 í’€ì„ ë‚˜ì—´í•  수 없습니다. 세부사항: %(err)s" #, python-format msgid "Unable to create storage pool %(name)s. Details: %(err)s" msgstr "스토리지 í’€ %(name)sì„(를) 작성할 수 없습니다. 세부사항: %(err)s" #, python-format msgid "" "Unable to get number of storage volumes in storage pool %(name)s. Details: " "%(err)s" msgstr "" "스토리지 í’€ %(name)sì— ìžˆëŠ” 스토리지 ë³¼ë¥¨ì˜ ìˆ˜ë¥¼ 가져올 수 없습니다. 세부사" "í•­: %(err)s" #, python-format msgid "Unable to activate storage pool %(name)s. Details: %(err)s" msgstr "스토리지 í’€ %(name)sì„(를) 활성화할 수 없습니다. 세부사항: %(err)s" #, python-format msgid "Unable to deactivate storage pool %(name)s. Details: %(err)s" msgstr "스토리지 í’€ %(name)sì„(를) 비활성화할 수 없습니다. 세부사항: %(err)s" #, python-format msgid "Unable to delete storage pool %(name)s. Details: %(err)s" msgstr "스토리지 í’€ %(name)sì„(를) 삭제할 수 없습니다. 세부사항: %(err)s" #, python-format msgid "" "Unable to create NFS Pool as export path %(path)s may block during mount" msgstr "" "내보내기 경로 %(path)sì´(ê°€) 마운트 ì¤‘ì— ì°¨ë‹¨ë  ìˆ˜ 있으므로 NFS í’€ì„ ìž‘ì„±í•  " "수 없습니다." #, python-format msgid "Unable to create NFS Pool as export path %(path)s mount failed" msgstr "" "내보내기 경로 %(path)s 마운트가 실패했으므로 NFS í’€ì„ ìž‘ì„±í•  수 없습니다." #, python-format msgid "Unsupported storage pool type: %(type)s" msgstr "ì§€ì›ë˜ì§€ 않는 스토리지 í’€ 유형: %(type)s" #, python-format msgid "Error while retrieving storage pool XML to %(pool)s" msgstr "" msgid "Storage pool name must be a string without slashes (/)" msgstr "" msgid "" "Supported storage pool types are dir, netfs, logical, iscsi, isci and kimchi-" "iso" msgstr "" msgid "Storage pool path must be a string" msgstr "스토리지 í’€ 경로는 문ìžì—´ì´ì–´ì•¼ 합니다." msgid "Storage pool host must be a IP or hostname" msgstr "스토리지 í’€ 호스트는 IP ë˜ëŠ” 호스트 ì´ë¦„ì´ì–´ì•¼ 합니다." msgid "Storage pool device must be the absolute path to the block device" msgstr "" msgid "Storage pool devices parameter must be a list" msgstr "스토리지 í’€ 장치는 목ë¡ì´ì–´ì•¼ 합니다." msgid "Target IQN of an iSCSI pool must be a string" msgstr "iSCSI í’€ì˜ ëŒ€ìƒ IQNì€ ë¬¸ìžì—´ì´ì–´ì•¼ 합니다." msgid "Port of a remote storage server must be an integer between 1 and 65535" msgstr "ì›ê²© 스토리지 ì„œë²„ì˜ í¬íŠ¸ëŠ” 1ê³¼ 65535 사ì´ì˜ 정수여야 합니다." msgid "iSCSI target username must be a string" msgstr "" msgid "iSCSI target password must be a string" msgstr "" msgid "Specify name and type to create a storage pool" msgstr "스토리지 í’€ì„ ìž‘ì„±í•˜ë ¤ë©´ ì´ë¦„ ë° ìœ í˜•ì„ ì§€ì •í•˜ì‹­ì‹œì˜¤." #, python-format msgid "" "%(disk)s is not a valid disk/partition. Could not add it to the pool " "%(pool)s." msgstr "" "%(disk)sì€(는) 유효한 디스í¬/íŒŒí‹°ì…˜ì´ ì•„ë‹™ë‹ˆë‹¤. ì´ë¥¼ %(pool)s í’€ì— ì¶”ê°€í•  수 " "없습니다." #, python-format msgid "Unable to extend logical pool %(pool)s. Details: %(err)s" msgstr "" msgid "The parameter disks only can be updated for logical storage pool." msgstr "논리 스토리지 í’€ì˜ ë§¤ê°œë³€ìˆ˜ 디스í¬ë§Œ ì—…ë°ì´íŠ¸í•  수 있습니다." msgid "The SCSI host adapter name must be a string." msgstr "SCSI 호스트 어댑터 ì´ë¦„ì€ ë¬¸ìžì—´ì´ì–´ì•¼ 합니다." msgid "The storage pool kimchi_isos is reserved for internal use" msgstr "스토리지 í’€ kimchi_isos는 ë‚´ë¶€ ìš©ë„로 예약ë˜ì—ˆìŠµë‹ˆë‹¤." #, python-format msgid "" "Unable to activate NFS storage pool %(name)s. NFS server %(server)s is " "unreachable." msgstr "" "NFS 스토리지 í’€ %(name)sì„(를) 활성화할 수 없습니다. NFS 서버 %(server)sì— ì—°" "ê²°í•  수 없습니다." #, python-format msgid "" "Unable to deactivate NFS storage pool %(name)s. NFS server %(server)s is " "unreachable." msgstr "" "NFS 스토리지 í’€ %(name)sì„(를) 비활성화할 수 없습니다. NFS 서버 %(server)sì— " "ì—°ê²°í•  수 없습니다." #, python-format msgid "" "Unable to deactivate pool %(name)s as it is associated with some templates" msgstr "" "ì¼ë¶€ 템플리트와 ì—°ê´€ë˜ì–´ 있으므로 %(name)s í’€ì„ ë¹„í™œì„±í™”í•  수 없습니다." #, python-format msgid "Unable to delete pool %(name)s as it is associated with some templates" msgstr "ì¼ë¶€ 템플리트와 ì—°ê´€ë˜ì–´ 있으므로 %(name)s í’€ì„ ì‚­ì œí•  수 없습니다." #, python-format msgid "" "A volume group named '%(name)s' already exists. Please, choose another name " "to create the logical pool." msgstr "" "ì´ë¦„ì´ '%(name)s'ì¸ ë³¼ë¥¨ ê·¸ë£¹ì´ ì´ë¯¸ 존재합니다. 논리 í’€ì„ ìž‘ì„±í•˜ë ¤ë©´ 다른 ì´" "ë¦„ì„ ì„ íƒí•˜ì‹­ì‹œì˜¤." #, python-format msgid "Unable to update database with deep scan information due error: %(err)s" msgstr "" "오류 ë•Œë¬¸ì— ìžì„¸í•œ 스캔 정보로 ë°ì´í„°ë² ì´ìŠ¤ë¥¼ ì—…ë°ì´íŠ¸í•  수 ì—†ìŒ: %(err)s" #, python-format msgid "Storage volume %(name)s already exists" msgstr "스토리지 볼륨 %(name)sì´(ê°€) ì´ë¯¸ 존재합니다." #, python-format msgid "Storage volume %(name)s does not exist in storage pool %(pool)s" msgstr "스토리지 볼륨 %(name)sì´(ê°€) 스토리지 í’€ %(pool)sì— ì—†ìŠµë‹ˆë‹¤." #, python-format msgid "" "Unable to create storage volume %(volume)s because storage pool %(pool)s is " "not active" msgstr "" #, python-format msgid "Specify %(item)s in order to create storage volume %(volume)s" msgstr "스토리지 볼륨 %(volume)sì„(를) 작성하려면 %(item)sì„(를) 지정하십시오." #, python-format msgid "" "Unable to list storage volumes because storage pool %(pool)s is not active" msgstr "" "스토리지 í’€ %(pool)sì´(ê°€) í™œì„±ì´ ì•„ë‹ˆë¯€ë¡œ 스토리지 ë³¼ë¥¨ì„ ë‚˜ì—´í•  수 없습니" "다." #, python-format msgid "" "Unable to create storage volume %(name)s in storage pool %(pool)s. Details: " "%(err)s" msgstr "" "스토리지 볼륨 %(name)sì„(를) 스토리지 í’€ %(pool)sì— ìž‘ì„±í•  수 없습니다. 세부" "사항: %(err)s" #, python-format msgid "" "Unable to list storage volumes in storage pool %(pool)s. Details: %(err)s" msgstr "" "스토리지 í’€ %(pool)sì˜ ìŠ¤í† ë¦¬ì§€ ë³¼ë¥¨ì„ ë‚˜ì—´í•  수 없습니다. 세부사항: %(err)s" #, python-format msgid "Unable to wipe storage volumes %(name)s. Details: %(err)s" msgstr "스토리지 í’€ %(name)sì„(를) 삭제할 수 없습니다. 세부사항: %(err)s" #, python-format msgid "Unable to delete storage volume %(name)s. Details: %(err)s" msgstr "스토리지 볼륨 %(name)sì„(를) 삭제할 수 없습니다. 세부사항: %(err)s" #, python-format msgid "Unable to resize storage volume %(name)s. Details: %(err)s" msgstr "스토리지 볼륨 %(name)sì˜ í¬ê¸°ë¥¼ ì¡°ì •í•  수 없습니다. 세부사항: %(err)s" #, python-format msgid "Storage type %(type)s does not support volume create and delete" msgstr "스토리지 유형 %(type)sì€(는) 볼륨 작성 ë° ì‚­ì œë¥¼ ì§€ì›í•˜ì§€ 않습니다." msgid "Storage volume name must be a string" msgstr "스토리지 볼륨 ì´ë¦„ì€ ë¬¸ìžì—´ì´ì–´ì•¼ 합니다." msgid "Storage volume allocation must be an integer number" msgstr "스토리지 볼륨 í• ë‹¹ì€ ì •ìˆ˜ì—¬ì•¼ 합니다." msgid "" "Storage volume format not supported. Valid formats: bochs, cloop, cow, dmg, " "qcow, qcow2, qed, raw, vmdk, vpc." msgstr "" msgid "Storage volume requires a volume name" msgstr "스토리지 ë³¼ë¥¨ì€ ë³¼ë¥¨ ì´ë¦„ì´ í•„ìš”í•©ë‹ˆë‹¤." #, python-format msgid "" "Unable to update database with storage volume information due error: %(err)s" msgstr "" "오류 ë•Œë¬¸ì— ìŠ¤í† ë¦¬ì§€ 볼륨 정보로 ë°ì´í„°ë² ì´ìŠ¤ë¥¼ ì—…ë°ì´íŠ¸í•  수 ì—†ìŒ: %(err)s" #, python-format msgid "Only one of parameter %(param)s can be specified" msgstr "" #, python-format msgid "Create volume from %(param)s is not supported" msgstr "" msgid "Storage volume capacity must be an integer number." msgstr "" msgid "Storage volume URL must be http://, https://, ftp:// or ftps://." msgstr "" #, python-format msgid "Unable to access file %(url)s. Please, check it." msgstr "" #, python-format msgid "" "Unable to clone storage volume '%(name)s' in pool '%(pool)s'. Details: " "%(err)s" msgstr "" msgid "Specify chunk data and its size to upload a file." msgstr "" msgid "In order to upload a storage volume, specify the 'upload' parameter." msgstr "" msgid "" "Unable to upload chunk data as it does not match with requested chunk size." msgstr "" #, python-format msgid "The storage volume %(vol)s is not under an upload process." msgstr "" msgid "The upload chunk data will exceed the storage volume size." msgstr "" #, python-format msgid "Unable to upload chunk data to storage volume. Details: %(err)s." msgstr "" #, python-format msgid "Interface %(name)s does not exist" msgstr "ì¸í„°íŽ˜ì´ìФ %(name)sì´(ê°€) 없습니다." #, python-format msgid "Network %(name)s already exists" msgstr "ë„¤íŠ¸ì›Œí¬ %(name)sì´(ê°€) ì´ë¯¸ 존재합니다." #, python-format msgid "Network %(name)s does not exist" msgstr "ë„¤íŠ¸ì›Œí¬ %(name)sì´(ê°€) 없습니다." #, python-format msgid "Subnet %(subnet)s specified for network %(network)s is not valid." msgstr "" "ë„¤íŠ¸ì›Œí¬ %(network)sì— ëŒ€í•´ ì§€ì •ëœ ì„œë¸Œë„· %(subnet)sì´(ê°€) 유효하지 않습니다." #, python-format msgid "Specify a network interface to create bridged network %(name)s" msgstr "" "ë¸Œë¦¿ì§€ëœ ë„¤íŠ¸ì›Œí¬ %(name)sì„(를) 작성할 ë„¤íŠ¸ì›Œí¬ ì¸í„°íŽ˜ì´ìŠ¤ë¥¼ 지정하십시오." #, python-format msgid "Unable to delete active network %(name)s" msgstr "활성 ë„¤íŠ¸ì›Œí¬ %(name)sì„(를) 삭제할 수 없습니다." #, python-format msgid "Interface %(iface)s specified for network %(network)s is already in use" msgstr "" "ë„¤íŠ¸ì›Œí¬ %(network)sì— ëŒ€í•´ ì§€ì •ëœ ì¸í„°íŽ˜ì´ìФ %(iface)sì´(ê°€) ì´ë¯¸ 사용 중입" "니다." msgid "Interface should be bare NIC, bonding or bridge device." msgstr "ì¸í„°íŽ˜ì´ìŠ¤ëŠ” 순수 NIC, 본딩 ë˜ëŠ” 브릿지 장치여야 합니다." #, python-format msgid "Unable to create network %(name)s. Details: %(err)s" msgstr "ë„¤íŠ¸ì›Œí¬ %(name)sì„(를) 작성할 수 없습니다. 세부사항: %(err)s" #, python-format msgid "Unable to find a free IP address for network '%(name)s'" msgstr "ë„¤íŠ¸ì›Œí¬ '%(name)s'ì— ëŒ€í•œ 여유 IP 주소를 ì°¾ì„ ìˆ˜ 없습니다." #, python-format msgid "The interface %(iface)s already exists." msgstr "" msgid "Network name must be a string without slashes (/) or quotes (\")" msgstr "" msgid "Supported network types are isolated, NAT and bridge" msgstr "ì§€ì›ë˜ëŠ” ë„¤íŠ¸ì›Œí¬ ìœ í˜•ì€ ê²©ë¦¬, NAT ë° ë¸Œë¦¿ì§€ìž…ë‹ˆë‹¤." msgid "Network subnet must be a string with IP address and prefix or netmask" msgstr "" "ë„¤íŠ¸ì›Œí¬ ì„œë¸Œë„·ì€ IP 주소 ë° ì ‘ë‘ë¶€ ë˜ëŠ” 넷마스í¬ê°€ 있는 문ìžì—´ì´ì–´ì•¼ 합니다." msgid "Network interface must be a string" msgstr "ë„¤íŠ¸ì›Œí¬ ì¸í„°íŽ˜ì´ìŠ¤ëŠ” 문ìžì—´ì´ì–´ì•¼ 합니다." msgid "Network VLAN ID must be an integer between 1 and 4094" msgstr "ë„¤íŠ¸ì›Œí¬ VLAN ID는 1ê³¼ 4094 사ì´ì˜ 정수여야 합니다." msgid "Specify name and type to create a Network" msgstr "네트워í¬ë¥¼ 작성하려면 ì´ë¦„ ë° ìœ í˜•ì„ ì§€ì •í•˜ì‹­ì‹œì˜¤." #, python-format msgid "" "Unable to delete network %(name)s. There are some virtual machines %(vms)s " "and/or templates linked to this network." msgstr "" #, python-format msgid "" "Unable to deactivate network %(name)s. There are some virtual machines " "%(vms)s and/or templates linked to this network." msgstr "" #, python-format msgid "Bridge device %(name)s can not be the trunk device of a VLAN." msgstr "브릿지 장치 %(name)sì€(는) VLANì˜ íŠ¸ë í¬ 장치가 ë  ìˆ˜ 없습니다." #, python-format msgid "Failed to activate interface %(iface)s: %(err)s." msgstr "%(iface)s ì¸í„°íŽ˜ì´ìŠ¤ë¥¼ 활성화하지 못함: %(err)s." #, python-format msgid "" "Failed to activate interface %(iface)s. Please check the physical link " "status." msgstr "" "%(iface)s ì¸í„°íŽ˜ì´ìŠ¤ë¥¼ 활성화하지 못했습니다. ë¬¼ë¦¬ì  ë§í¬ ìƒíƒœë¥¼ 확ì¸í•˜ì‹­ì‹œ" "오." #, python-format msgid "Failed to start network %(name)s. Details: %(err)s" msgstr "" #, python-format msgid "Debug report %(name)s does not exist" msgstr "디버그 보고서 %(name)sì´(ê°€) 없습니다." msgid "Debug report tool not found in system" msgstr "디버그 보고서 ë„구가 ì‹œìŠ¤í…œì— ì—†ìŠµë‹ˆë‹¤." #, python-format msgid "Unable to create debug report %(name)s. Details: %(err)s." msgstr "디버그 보고서 %(name)sì„(를) 작성할 수 없습니다. 세부사항: %(err)s" #, python-format msgid "Can not find any debug report with the given name %(name)s" msgstr "" #, python-format msgid "Unable to generate debug report %(name)s. Details: %(err)s" msgstr "디버그 보고서 %(name)sì„(를) ìƒì„±í•  수 없습니다. 세부사항: %(err)s" msgid "You should give a name for the debug report file." msgstr "" msgid "" "Debug report name must be a string. Only letters, digits, underscore ('_') " "and hyphen ('-') are allowed." msgstr "" #, python-format msgid "" "The debug report with specified name \"%(name)s\" already exists. Please use " "another one." msgstr "" "ì´ë¦„ì´ '%(name)s'ì¸ ë³¼ë¥¨ ê·¸ë£¹ì´ ì´ë¯¸ 존재합니다. 논리 í’€ì„ ìž‘ì„±í•˜ë ¤ë©´ 다른 ì´" "ë¦„ì„ ì„ íƒí•˜ì‹­ì‹œì˜¤." #, python-format msgid "Storage server %(server)s was not used by Kimchi" msgstr "스토리지 서버 %(server)sì€(는) Kimchiì—서 사용ë˜ì§€ 않았습니다." #, python-format msgid "Distro '%(name)s' does not exist" msgstr "Distro '%(name)s'ì´(ê°€) 없습니다." #, python-format msgid "Partition %(name)s does not exist in the host" msgstr "파티션 %(name)sì´(ê°€) í˜¸ìŠ¤íŠ¸ì— ì—†ìŠµë‹ˆë‹¤." msgid "Unable to shutdown host machine as there are running virtual machines" msgstr "ê°€ìƒ ë¨¸ì‹ ì„ ì‹¤í–‰ ì¤‘ì¸ í˜¸ìŠ¤íŠ¸ ë¨¸ì‹ ì„ ì¢…ë£Œí•  수 없습니다." msgid "Unable to reboot host machine as there are running virtual machines" msgstr "ê°€ìƒ ë¨¸ì‹ ì„ ì‹¤í–‰ ì¤‘ì¸ í˜¸ìŠ¤íŠ¸ ë¨¸ì‹ ì„ ë‹¤ì‹œ 부팅할 수 없습니다." #, python-format msgid "Node device '%(name)s' not found" msgstr "노드 장치 '%(name)s'ì´(ê°€) 없습니다." msgid "Conflicting flag filters specified." msgstr "" msgid "No packages marked for update" msgstr "ì—…ë°ì´íЏ í‘œì‹œëœ íŒ¨í‚¤ì§€ê°€ 없습니다." #, python-format msgid "Package %(name)s is not marked to be updated." msgstr "패키지 %(name)sì€(는) ì—…ë°ì´íЏë˜ë„ë¡ í‘œì‹œë˜ì§€ 않았습니다." #, python-format msgid "Error while getting packages marked to be updated. Details: %(err)s" msgstr "" "ì—…ë°ì´íЏë˜ë„ë¡ í‘œì‹œëœ íŒ¨í‚¤ì§€ë¥¼ 가져오는 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤. 세부사항: " "%(err)s" msgid "There is no compatible package manager for this system." msgstr "ì´ ì‹œìŠ¤í…œì— ëŒ€í•´ 호환 가능한 패키지 관리ìžê°€ 없습니다." #, python-format msgid "Unable to find %(item)s in datastore" msgstr "ë°ì´í„° 저장소ì—서 %(item)sì„(를) ì°¾ì„ ìˆ˜ 없습니다." #, python-format msgid "Invalid URI %(uri)s" msgstr "올바르지 ì•Šì€ URI %(uri)s" #, python-format msgid "Timeout while running command '%(cmd)s' after %(seconds)s seconds" msgstr "%(seconds)sì´ˆ í›„ì— '%(cmd)s' 명령 실행 중 ì œí•œì‹œê°„ì´ ì´ˆê³¼ë˜ì—ˆìŠµë‹ˆë‹¤." msgid "Unable to choose a virtual machine name" msgstr "" #, python-format msgid "Invalid data value '%(value)s'" msgstr "" #, python-format msgid "Invalid data unit '%(unit)s'" msgstr "" msgid "Invalid storage type. Types supported: 'cdrom', 'disk'" msgstr "올바르지 ì•Šì€ ìŠ¤í† ë¦¬ì§€ 유형입니다. ì§€ì›ë˜ëŠ” 유형: 'cdrom'" #, python-format msgid "The path '%(value)s' is not a valid local/remote path for the device" msgstr "" msgid "Only CDROM path can be update." msgstr "" #, python-format msgid "" "The storage device %(dev_name)s does not exist in the virtual machine " "%(vm_name)s" msgstr "" #, python-format msgid "Error while creating new storage device: %(error)s" msgstr "새 스토리지 장치를 작성하는 ì¤‘ì— ì˜¤ë¥˜ ë°œìƒ: %(error)s" #, python-format msgid "Error while updating storage device: %(error)s" msgstr "스토리지 장치를 ì—…ë°ì´íŠ¸í•˜ëŠ” ì¤‘ì— ì˜¤ë¥˜ ë°œìƒ: %(error)s" #, python-format msgid "Error while removing storage device: %(error)s" msgstr "스토리지 장치를 제거하는 ì¤‘ì— ì˜¤ë¥˜ ë°œìƒ: %(error)s" msgid "Do not support IDE device hot plug" msgstr "" msgid "" "Specify type and path or type and pool/volume to add a new virtual machine " "disk" msgstr "새 ê°€ìƒ ë¨¸ì‹  디스í¬ë¥¼ 추가할 유형 ë° ê²½ë¡œë¥¼ 지정하십시오." msgid "Specify path to update virtual machine disk" msgstr "ê°€ìƒ ë¨¸ì‹  디스í¬ë¥¼ ì—…ë°ì´íŠ¸í•  경로를 지정하십시오." #, python-format msgid "Controller type %(type)s limitation of %(limit)s devices reached" msgstr "" #, python-format msgid "Cannot retrieve disk path information for given pool/volume: %(error)s" msgstr "" msgid "Volume already in use by other virtual machine." msgstr "" msgid "" "Only one of path or pool/volume can be specified to add a new virtual " "machine disk" msgstr "새 ê°€ìƒ ë¨¸ì‹  디스í¬ë¥¼ 추가할 유형 ë° ê²½ë¡œë¥¼ 지정하십시오." #, python-format msgid "" "Volume chosen with format %(format)s does not fit in the storage type " "%(type)s" msgstr "" msgid "YUM Repository ID must be one word only string." msgstr "YUM 저장소 ID는 ë‹¨ì¼ ë‹¨ì–´ì˜ ë¬¸ìžì—´ì´ì–´ì•¼ 합니다." msgid "Repository URL must be an http://, ftp:// or file:// URL." msgstr "저장소 URLì€ http://, ftp:// ë˜ëŠ” file:// URLì´ì–´ì•¼ 합니다." msgid "" "Repository configuration is a dictionary with specific values according to " "repository type." msgstr "저장소 êµ¬ì„±ì€ ì €ìž¥ì†Œ ìœ í˜•ì— ë”°ë¥¸ 특정 ê°’ì´ ìžˆëŠ” 사전입니다." msgid "Distribution to DEB repository must be a string" msgstr "DEB ì €ìž¥ì†Œì— ëŒ€í•œ ë°°í¬ëŠ” 문ìžì—´ì´ì–´ì•¼ 합니다." msgid "Components to DEB repository must be listed in a array" msgstr "DEB ì €ìž¥ì†Œì— ëŒ€í•œ 구성요소는 ë°°ì—´ì— ë‚˜ì—´ë˜ì–´ì•¼ 합니다." msgid "Components to DEB repository must be a string" msgstr "DEB ì €ìž¥ì†Œì— ëŒ€í•œ 구성요소는 문ìžì—´ì´ì–´ì•¼ 합니다." msgid "Mirror list to repository must be a string" msgstr "" msgid "YUM Repository name must be string." msgstr "YUM 저장소 ì´ë¦„ì€ ë¬¸ìžì—´ì´ì–´ì•¼ 합니다." msgid "GPG check must be a boolean value." msgstr "GPG 검사는 부울 ê°’ì´ì–´ì•¼ 합니다." msgid "GPG key must be a URL pointing to the ASCII-armored file." msgstr "GPG 키는 ASCII 보호 파ì¼ì„ 가리키는 URLì´ì–´ì•¼ 합니다." #, python-format msgid "Could not update repository %(repo_id)s." msgstr "%(repo_id)s 저장소를 ì—…ë°ì´íŠ¸í•  수 없습니다." #, python-format msgid "Repository %(repo_id)s does not exist." msgstr "%(repo_id)s 저장소가 없습니다." msgid "" "Specify repository base URL, mirror list or metalink in order to create or " "update a YUM repository." msgstr "" msgid "Repository management tool was not recognized for your system." msgstr "해당 ì‹œìŠ¤í…œì— ëŒ€í•œ 저장소 관리 ë„구가 ì¸ì‹ë˜ì§€ 않았습니다." #, python-format msgid "Repository %(repo_id)s is already enabled." msgstr "%(repo_id)s 저장소가 ì´ë¯¸ 사용으로 설정ë˜ì–´ 있습니다." #, python-format msgid "Repository %(repo_id)s is already disabled." msgstr "%(repo_id)s 저장소가 ì´ë¯¸ 사용 안함으로 설정ë˜ì–´ 있습니다." #, python-format msgid "Could not remove repository %(repo_id)s." msgstr "%(repo_id)s 저장소를 제거할 수 없습니다." #, python-format msgid "Could not write repository configuration file %(repo_file)s" msgstr "저장소 구성 íŒŒì¼ %(repo_file)sì„(를) 작성할 수 없습니다." msgid "Specify repository distribution in order to create a DEB repository." msgstr "DEB 저장소를 작성하려면 저장소 ë°°í¬ë¥¼ 지정하십시오." #, python-format msgid "Could not enable repository %(repo_id)s." msgstr "%(repo_id)s 저장소를 사용으로 설정할 수 없습니다." #, python-format msgid "Could not disable repository %(repo_id)s." msgstr "%(repo_id)s 저장소를 사용 안함으로 설정할 수 없습니다." msgid "YUM Repository ID already exists" msgstr "YUM 저장소 IDê°€ ì´ë¯¸ 존재합니다." msgid "YUM Repository name must be a string" msgstr "YUM 저장소 ì´ë¦„ì€ ë¬¸ìžì—´ì´ì–´ì•¼ 합니다." #, python-format msgid "Unable to list repositories. Details: '%(err)s'" msgstr "저장소를 나열할 수 없습니다. 세부사항: '%(err)s'" #, python-format msgid "Unable to retrieve repository information. Details: '%(err)s'" msgstr "저장소 정보를 나열할 수 없습니다. 세부사항: '%(err)s'" #, python-format msgid "Unable to add repository. Details: '%(err)s'" msgstr "저장소를 추가할 수 없습니다. 세부사항: '%(err)s'" #, python-format msgid "Unable to remove repository. Details: '%(err)s'" msgstr "저장소를 제거할 수 없습니다. 세부사항: '%(err)s'" #, python-format msgid "" "Configuration items: '%(items)s' are not supported by repository manager" msgstr "" msgid "Repository metalink must be an http://, ftp:// or file:// URL." msgstr "" msgid "Cannot specify mirrorlist and metalink at the same time." msgstr "" #, python-format msgid "" "Virtual machine '%(vm)s' must be stopped before creating a snapshot of it." msgstr "" #, python-format msgid "" "Unable to create snapshot '%(name)s' on virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "Snapshot '%(name)s' does not exist on virtual machine '%(vm)s'." msgstr "" #, python-format msgid "" "Unable to retrieve snapshot '%(name)s' on virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "Unable to list snapshots on virtual machine '%(vm)s'. Details: %(err)s" msgstr "" #, python-format msgid "" "Unable to delete snapshot '%(name)s' on virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "" "Unable to retrieve current snapshot of virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "" "Unable to revert virtual machine '%(vm)s' to snapshot '%(name)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "" "Unable to create snapshot of virtual machine '%(vm)s' because it contains a " "disk with format '%(format)s'; only 'qcow2' is supported." msgstr "" msgid "The number of vCPUs is too large for this system." msgstr "" msgid "Invalid vCPU/topology combination." msgstr "" msgid "This host (or current configuration) does not allow CPU topology." msgstr "" msgid "ERROR CODE" msgstr "오류 코드" msgid "REASON" msgstr "ì´ìœ " msgid "STACK" msgstr "스íƒ" msgid "Go to Homepage" msgstr "홈 페ì´ì§€ë¡œ ì´ë™" msgid "Create a New Virtual Machine" msgstr "새 ê°€ìƒ ë¨¸ì‹  작성" msgid "Virtual Machine Name" msgstr "ê°€ìƒ ë¨¸ì‹  ì´ë¦„" msgid "" "The name used to identify the virtual machine. If omitted, a name will be " "chosen based on the template used." msgstr "" "ê°€ìƒ ë¨¸ì‹ ì„ ì‹ë³„하는 ë° ì‚¬ìš©ë˜ëŠ” ì´ë¦„입니다. ìƒëžµë˜ë©´ ì´ë¦„ì€ ì‚¬ìš©ëœ í…œí”Œë¦¬íŠ¸" "를 기반으로 ì„ íƒë©ë‹ˆë‹¤." msgid "Template" msgstr "템플리트" msgid "Please create a template first." msgstr "템플리트를 먼저 작성하십시오." msgid "Create a Template" msgstr "템플리트 작성" msgid "Please choose a template." msgstr "템플리트를 ì„ íƒí•˜ì‹­ì‹œì˜¤." msgid "OS" msgstr "OS" msgid "OS Version" msgstr "OS 버전" msgid "CPUS" msgstr "CPUS" msgid "Memory" msgstr "메모리" msgid "Create" msgstr "작성" msgid "Creating..." msgstr "" msgid "Edit Guest" msgstr "게스트 편집" msgid "General" msgstr "ì¼ë°˜" msgid "Storage" msgstr "스토리지" msgid "Interface" msgstr "ì¸í„°íŽ˜ì´ìФ" msgid "Permission" msgstr "버전" msgid "Host PCI Device" msgstr "" msgid "Snapshot" msgstr "" msgid "Name" msgstr "ì´ë¦„" msgid "CPUs" msgstr "CPU" msgid "Memory (MB)" msgstr "메모리" msgid "Icon" msgstr "ì•„ì´ì½˜" msgid "Device" msgstr "장치 ì´ë¦„" msgid "Path" msgstr "NFS 경로" msgid "Network" msgstr "네트워í¬" msgid "Type" msgstr "유형" msgid "MAC Address" msgstr "" msgid "Available system users and groups" msgstr "" msgid "Selected system users and groups" msgstr "" msgid "User" msgstr "" msgid "All" msgstr "모ë‘" msgid "To Add" msgstr "" msgid "Added" msgstr "" msgid "filter" msgstr "" msgid "Product" msgstr "" msgid "Vendor" msgstr "공급업체" msgid "Created" msgstr "" msgid "Save" msgstr "저장" msgid "Replace" msgstr "êµì²´" msgid "Detach" msgstr "분리" msgid "Cancel" msgstr "취소" msgid "revert" msgstr "" msgid "Add a Storage Device to VM" msgstr "스토리지 장치를 VMì— ì¶”ê°€" msgid "Device Type" msgstr "장치 유형" msgid "The device type. Currently, \"cdrom\" and \"disk\" are supported." msgstr "장치 유형입니다. 현재 \"cdrom\"ë§Œ ì§€ì›ë©ë‹ˆë‹¤." msgid "Storage Pool" msgstr "스토리지 í’€" msgid "Storage pool which volume located in" msgstr "스토리지 í’€ 경로는 문ìžì—´ì´ì–´ì•¼ 합니다." msgid "Storage Volume" msgstr "스토리지 í’€ ì´ë¦„" msgid "Storage volume to be attached" msgstr "스토리지 볼륨 ì´ë¦„ì€ ë¬¸ìžì—´ì´ì–´ì•¼ 합니다." msgid "File Path" msgstr "íŒŒì¼ ê²½ë¡œ" msgid "The ISO file path in the server for CDROM." msgstr "CDROMì„ ìœ„í•œ ì„œë²„ì˜ ISO íŒŒì¼ ê²½ë¡œìž…ë‹ˆë‹¤." msgid "Attach" msgstr "ì—°ê²°" msgid "Start" msgstr "시작" msgid "Reset" msgstr "다시 설정" msgid "Pause" msgstr "" msgid "Resume" msgstr "" msgid "Power Off" msgstr "" msgid "Actions" msgstr "조치" msgid "Connect" msgstr "ì—°ê²°" msgid "Clone" msgstr "" msgid "Edit" msgstr "편집" msgid "Shut Down" msgstr "시스템 종료" msgid "Delete" msgstr "ì‚­ì œ" msgid "The username or password you entered is incorrect. Please try again." msgstr "" "입력한 ì‚¬ìš©ìž ì´ë¦„ ë˜ëŠ” 비밀번호가 올바르지 않습니다. 다시 시ë„하십시오." msgid "This field is required." msgstr "ì´ í•„ë“œëŠ” 필수입니다." msgid "Log in" msgstr "로그ì¸" msgid "Logging in..." msgstr "ë¡œê·¸ì¸ ì¤‘..." msgid "Host" msgstr "호스트" msgid "Guests" msgstr "게스트" msgid "Templates" msgstr "템플리트" msgid "Failed to get application configuration" msgstr "애플리케ì´ì…˜ êµ¬ì„±ì„ ê°€ì ¸ì˜¤ì§€ 못했습니다." msgid "This is not a valid Linux path" msgstr "올바른 Linux 경로가 아닙니다." msgid "This is not a valid URL." msgstr "올바른 URLì´ ì•„ë‹™ë‹ˆë‹¤." msgid "No such data available." msgstr "해당 ë°ì´í„°ê°€ 없습니다." msgid "" "Can not contact the host system. Verify the host system is up and that you " "have network connectivity to it. HTTP request response %1. " msgstr "" "호스트 ì‹œìŠ¤í…œì— ì ‘ì†í•  수 없습니다. 호스트 ì‹œìŠ¤í…œì´ ê°€ë™ë˜ì—ˆê³  ì´ì— 대한 네트" "ì›Œí¬ ì—°ê²°ì´ ìžˆëŠ”ì§€ 확ì¸í•˜ì‹­ì‹œì˜¤. HTTP 요청 ì‘답 %1. " msgid "Unable to read file." msgstr "" msgid "Error while uploading file." msgstr "" msgid "Delete Confirmation" msgstr "ì‚­ì œ 확ì¸" msgid "OK" msgstr "확ì¸" msgid "Confirm" msgstr "확ì¸" msgid "Warning" msgstr "경고" msgid "Cloning..." msgstr "" msgid "Loading..." msgstr "로드 중..." msgid "An error occurred while retrieving system information." msgstr "" msgid "Retry" msgstr "재시ë„" msgid "Detailed message:" msgstr "세부 메시지:" msgid "No ISO found" msgstr "" msgid "This is not a valid ISO file." msgstr "올바른 ISO 파ì¼ì´ 아닙니다." msgid "This may take a long time. Do you want to continue?" msgstr "ì‹œê°„ì´ ì˜¤ëž˜ 걸립니다. 계ì†í•˜ì‹œê² ìŠµë‹ˆê¹Œ?" msgid "This will permanently delete the template. Would you like to continue?" msgstr "템플리트가 ì˜êµ¬ì ìœ¼ë¡œ ì‚­ì œë©ë‹ˆë‹¤. 계ì†í•˜ì‹œê² ìŠµë‹ˆê¹Œ?" msgid "Unable to shut down system as there are some virtual machines running!" msgstr "ì¼ë¶€ ê°€ìƒ ë¨¸ì‹ ì´ ì‹¤í–‰ 중ì´ë¯€ë¡œ ì‹œìŠ¤í…œì„ ì¢…ë£Œí•  수 없습니다." msgid "Max:" msgstr "최대:" msgid "Utilization" msgstr "ì´ìš©ë¥ " msgid "Available" msgstr "사용 가능" msgid "Read Rate" msgstr "ì½ê¸° ì†ë„" msgid "Write Rate" msgstr "쓰기 ì†ë„" msgid "Received" msgstr "ë°›ìŒ" msgid "Sent" msgstr "보냄" msgid "" "Shutting down or restarting host will cause unsaved work lost. Continue to " "shut down/restarting?" msgstr "" "호스트를 종료하거나 다시 시작하면 저장ë˜ì§€ ì•Šì€ ìž‘ì—…ì´ ì†ì‹¤ë©ë‹ˆë‹¤. 시스템 종" "료/다시 ì‹œìž‘ì„ ê³„ì†í•˜ì‹œê² ìŠµë‹ˆê¹Œ?" msgid "" "Repository will be removed permanently and can't be recovered. Do you want " "to continue?" msgstr "저장소가 ì˜êµ¬ì ìœ¼ë¡œ 제거ë˜ì–´ 복구할 수 없습니다. 계ì†í•˜ì‹œê² ìŠµë‹ˆê¹Œ?" msgid "Repositories" msgstr "저장소" msgid "ID" msgstr "ID" msgid "Base URL" msgstr "기본 URL" msgid "Is Mirror" msgstr "미러임" msgid "URL Args" msgstr "URL ì¸ìˆ˜" msgid "Enabled" msgstr "사용함" msgid "GPG Check" msgstr "GPG 검사" msgid "GPG Key" msgstr "GPG 키" msgid "Add" msgstr "추가" msgid "Remove" msgstr "제거" msgid "Enable" msgstr "사용" msgid "Disable" msgstr "사용 안함" msgid "Software Updates" msgstr "소프트웨어 ì—…ë°ì´íЏ" msgid "Package Name" msgstr "패키지 ì´ë¦„" msgid "Version" msgstr "버전" msgid "Architecture" msgstr "아키í…처" msgid "Repository" msgstr "저장소" msgid "Update All" msgstr "ëª¨ë‘ ì—…ë°ì´íЏ" msgid "Updating..." msgstr "ì—…ë°ì´íЏ 중..." msgid "Failed to retrieve packages update information." msgstr "" msgid "Failed to update package(s)." msgstr "패키지를 ì—…ë°ì´íŠ¸í•˜ì§€ 못했습니다." msgid "" "Debug report will be removed permanently and can't be recovered. Do you want " "to continue?" msgstr "" "디버그 보고서가 ì˜êµ¬ì ìœ¼ë¡œ 제거ë˜ì–´ 복구할 수 없습니다. 계ì†í•˜ì‹œê² ìŠµë‹ˆê¹Œ?" msgid "Debug Reports" msgstr "디버그 보고서" msgid "Generated Time" msgstr "ìƒì„± 시간" msgid "Generate" msgstr "ìƒì„±" msgid "Generating..." msgstr "ìƒì„± 중..." msgid "Rename" msgstr "ì´ë¦„ 바꾸기" msgid "Download" msgstr "다운로드" msgid "" "Report name should contain only letters, digits, underscore ('_') and/or " "hyphen ('-')." msgstr "보고서 ì´ë¦„ì—는 문ìž, ìˆ«ìž ë°/ë˜ëŠ” 하ì´í”ˆ('-')ë§Œ í¬í•¨ë˜ì–´ì•¼ 합니다." msgid "Pending..." msgstr "로드 중..." msgid "Report name is the same as the original one." msgstr "" msgid "" "This will delete the virtual machine and its virtual disks. This operation " "cannot be undone. Would you like to continue?" msgstr "" "ê°€ìƒ ë¨¸ì‹  ë° í•´ë‹¹ ê°€ìƒ ë””ìŠ¤í¬ê°€ ì‚­ì œë©ë‹ˆë‹¤. ì´ ì¡°ìž‘ì€ ì‹¤í–‰ 취소할 수 없습니" "다. 계ì†í•˜ì‹œê² ìŠµë‹ˆê¹Œ?" msgid "Power off Confirmation" msgstr "ì‚­ì œ 확ì¸" msgid "" "This action may produce undesirable results, for example unflushed disk " "cache in the guest. Would you like to continue?" msgstr "" msgid "Reset Confirmation" msgstr "ì‚­ì œ 확ì¸" msgid "" "There is a risk of data loss caused by reset without the guest OS shutdown. " "Would you like to continue?" msgstr "" msgid "Shut Down Confirmation" msgstr "ì‚­ì œ 확ì¸" msgid "Note the guest OS may ignore this request. Would you like to continue?" msgstr "템플리트가 ì˜êµ¬ì ìœ¼ë¡œ ì‚­ì œë©ë‹ˆë‹¤. 계ì†í•˜ì‹œê² ìŠµë‹ˆê¹Œ?" msgid "Virtual Machine delete Confirmation" msgstr "" msgid "" "This virtual machine is not persistent. Power Off will delete it. Continue?" msgstr "" msgid "" "When the target guest has SCSI or iSCSI volumes, they will be cloned on " "default storage pool. The same will happen when the target pool does not " "have enough space to clone the volumes. Do you want to continue?" msgstr "" msgid "" "This CDROM will be detached permanently and you can re-attach it. Continue " "to detach it?" msgstr "" "ì´ CDROMì€ ì˜êµ¬ì ìœ¼ë¡œ 분리ë˜ë©° 다시 ì—°ê²°í•  수 있습니다. 분리를 계ì†í•˜ì‹œê² ìŠµë‹ˆ" "까?" msgid "Attaching..." msgstr "ì—°ê²° 중..." msgid "Replacing..." msgstr "êµì²´ 중..." msgid "Successfully attached!" msgstr "ì—°ê²°ë˜ì—ˆìŠµë‹ˆë‹¤." msgid "Successfully replaced!" msgstr "êµì²´ë˜ì—ˆìŠµë‹ˆë‹¤." msgid "Successfully detached!" msgstr "분리ë˜ì—ˆìŠµë‹ˆë‹¤." msgid "" "This disk will be detached permanently and you can re-attach it. Continue to " "detach it?" msgstr "" msgid "interface:" msgstr "" msgid "address:" msgstr "" msgid "link_type:" msgstr "" msgid "block:" msgstr "" msgid "drive_type:" msgstr "" msgid "model:" msgstr "" msgid "Affected devices:" msgstr "" msgid "The VLAN id must be between 1 and 4094." msgstr "VLAN ID는 1ê³¼ 4094 사ì´ì—¬ì•¼ 합니다." msgid "unavailable" msgstr "사용 불가능" msgid "" "This action will interrupt network connectivity for any virtual machine that " "depend on this network." msgstr "" "ì´ ì¡°ì¹˜ëŠ” ì´ ë„¤íŠ¸ì›Œí¬ì— ì˜ì¡´í•˜ëŠ” ê°€ìƒ ë¨¸ì‹ ì˜ ë„¤íŠ¸ì›Œí¬ ì—°ê²°ì„ ì¸í„°ëŸ½íŠ¸í•©ë‹ˆë‹¤." msgid "Create a network" msgstr "ë„¤íŠ¸ì›Œí¬ ìž‘ì„±" msgid "" "This network is not persistent. Instead of stop, this action will " "permanently delete it. Would you like to continue?" msgstr "" "ì´ ìŠ¤í† ë¦¬ì§€ í’€ì€ ì§€ì†ì ì´ì§€ 않습니다. ì´ ì¡°ì¹˜ëŠ” í’€ì„ ë¹„í™œì„±í™”í•˜ì§€ 않고 ì˜êµ¬ì " "으로 삭제합니다. 계ì†í•˜ì‹œê² ìŠµë‹ˆê¹Œ?" msgid "" "The bridged VLAN tag may not work well with NetworkManager enabled. You " "should consider disabling it." msgstr "" msgid "" "This will permanently delete the storage pool. Would you like to continue?" msgstr "스토리지 í’€ì´ ì˜êµ¬ì ìœ¼ë¡œ ì‚­ì œë©ë‹ˆë‹¤. 계ì†í•˜ì‹œê² ìŠµë‹ˆê¹Œ?" msgid "This storage pool is empty." msgstr "ì´ ìŠ¤í† ë¦¬ì§€ í’€ì€ ë¹„ì–´ 있습니다." msgid "" "It will format your disk and you will loose any data in there, are you sure " "to continue? " msgstr "디스í¬ê°€ í¬ë§·ë˜ê³  ë°ì´í„°ê°€ ì†ì‹¤ë©ë‹ˆë‹¤. 계ì†í•˜ì‹œê² ìŠµë‹ˆê¹Œ? " msgid "SCSI Fibre Channel" msgstr "SCSI 파ì´ë²„ 채ë„" msgid "No SCSI adapters found." msgstr "SCSI 어댑터가 없습니다." msgid "Loading iSCSI targets..." msgstr "" msgid "No iSCSI found. Please input one." msgstr "" msgid "Failed to load iSCSI targets." msgstr "" msgid "The storage pool name can not be blank." msgstr "스토리지 í’€ ì´ë¦„ì€ ë¹„ì›Œë‘˜ 수 없습니다." msgid "The storage pool path can not be blank." msgstr "스토리지 í’€ 경로는 비워둘 수 없습니다." msgid "NFS server mount path can not be blank." msgstr "NFS 서버 마운트 경로는 비워둘 수 없습니다." msgid "Invalid NFS mount path." msgstr "올바르지 ì•Šì€ NFS 마운트 경로입니다." msgid "No logical device selected." msgstr "논리 장치가 ì„ íƒë˜ì§€ 않았습니다." msgid "The iSCSI target can not be blank." msgstr "iSCSI 대ìƒì€ 비워둘 수 없습니다." msgid "Server name can not be blank." msgstr "서버 ì´ë¦„ì€ ë¹„ì›Œë‘˜ 수 없습니다." msgid "This is not a valid Server Name or IP. Please, modify it." msgstr "" msgid "Looking for available partitions ..." msgstr "사용 가능한 íŒŒí‹°ì…˜ì„ ì°¾ëŠ” 중..." msgid "No available partitions found." msgstr "사용 가능한 íŒŒí‹°ì…˜ì´ ì—†ìŠµë‹ˆë‹¤." msgid "" "This storage pool is not persistent. Instead of deactivate, this action will " "permanently delete it. Would you like to continue?" msgstr "" "ì´ ìŠ¤í† ë¦¬ì§€ í’€ì€ ì§€ì†ì ì´ì§€ 않습니다. ì´ ì¡°ì¹˜ëŠ” í’€ì„ ë¹„í™œì„±í™”í•˜ì§€ 않고 ì˜êµ¬ì " "으로 삭제합니다. 계ì†í•˜ì‹œê² ìŠµë‹ˆê¹Œ?" msgid "Unable to retrieve partitions information." msgstr "저장소 정보를 나열할 수 없습니다. 세부사항: '%(err)s'" msgid "In progress..." msgstr "" msgid "Failed!" msgstr "" msgid "CDROM path needs to be a valid local/remote path and cannot be blank." msgstr "" msgid "Disk pool or volume cannot be blank." msgstr "스토리지 í’€ ì´ë¦„ì€ ë¹„ì›Œë‘˜ 수 없습니다." msgid "Peers" msgstr "" msgid "Searching" msgstr "" msgid "No peers found." msgstr "" msgid "Help" msgstr "ë„움ë§" msgid "About" msgstr "ì •ë³´" msgid "Log out" msgstr "로그아웃" msgid "Version:" msgstr "버전: " msgid "Session timeout, please re-login." msgstr "" msgid "User Name" msgstr "ì‚¬ìš©ìž ì´ë¦„" msgid "Password" msgstr "비밀번호" msgid "Generate a New Debug Report" msgstr "새 디버그 보고서 ìƒì„±" msgid "Report Name" msgstr "보고서 ì´ë¦„" msgid "" "The name used to identify the report. If omitted, a name will be chosen " "based on current time. Name can contain: letters, digits, underscore (\"_\") " "and hyphen (\"-\")." msgstr "" "보고서를 ì‹ë³„하는 ë° ì‚¬ìš©ë˜ëŠ” ì´ë¦„입니다. ìƒëžµë˜ë©´ ì´ë¦„ì€ í˜„ìž¬ ì‹œê°„ì„ ê¸°ë°˜ìœ¼" "로 ì„ íƒë©ë‹ˆë‹¤. ì´ë¦„ì€ ë¬¸ìž, ìˆ«ìž ë° í•˜ì´í”ˆ(\"-\")ì„ í¬í•¨í•  수 있습니다." msgid "Rename a Debug Report" msgstr "새 디버그 보고서 ìƒì„±" msgid "" "The name used to identify the report. Name can contain: letters, digits and " "hyphen (\"-\")." msgstr "" "보고서를 ì‹ë³„하는 ë° ì‚¬ìš©ë˜ëŠ” ì´ë¦„입니다. ìƒëžµë˜ë©´ ì´ë¦„ì€ í˜„ìž¬ ì‹œê°„ì„ ê¸°ë°˜ìœ¼" "로 ì„ íƒë©ë‹ˆë‹¤. ì´ë¦„ì€ ë¬¸ìž, ìˆ«ìž ë° í•˜ì´í”ˆ(\"-\")ì„ í¬í•¨í•  수 있습니다." msgid "Submit" msgstr "" msgid "Add a Repository" msgstr "저장소 추가" msgid "Identifier" msgstr "ID" msgid "Single word, unique identifier for the repository." msgstr "ì €ìž¥ì†Œì— ëŒ€í•œ ë‹¨ì¼ ë‹¨ì–´ì˜ ê³ ìœ  ID입니다." msgid "Textual name for the repository." msgstr "ì €ìž¥ì†Œì— ëŒ€í•œ í…스트 ì´ë¦„입니다." msgid "URL" msgstr "URL" msgid "Required Field" msgstr "필수 필드" msgid "URL to the repository. Supported protocols are http, ftp, and file." msgstr "ì €ìž¥ì†Œì— ëŒ€í•œ URL입니다. ì§€ì›ë˜ëŠ” í”„ë¡œí† ì½œì€ http, ftp ë° file입니다." msgid "Repository is a mirror" msgstr "저장소가 미러입니다." msgid "Distribution" msgstr "ë°°í¬" msgid "Distribution of the DEB repository." msgstr "DEB ì €ìž¥ì†Œì˜ ë°°í¬ìž…니다." msgid "Components" msgstr "구성요소" msgid "List of components in DEB repository." msgstr "DEB ì €ìž¥ì†Œì˜ êµ¬ì„±ìš”ì†Œ 목ë¡ìž…니다." msgid "Edit Repository" msgstr "저장소 편집" msgid "Mirror List URL" msgstr "미러 ëª©ë¡ URL" msgid "Yes" msgstr "예" msgid "No" msgstr "아니오" msgid "Add a Volume to Storage Pool" msgstr "" msgid "Fetch from remote URL" msgstr "" msgid "Enter the remote URL here." msgstr "" msgid "Upload a file" msgstr "" msgid "Choose the file you want to upload." msgstr "" msgid "Define a New Storage Pool" msgstr "새 스토리지 í’€ ì •ì˜" msgid "Storage Pool Name" msgstr "스토리지 í’€ ì´ë¦„" msgid "" "The name used to identify the storage pools, and it should not be empty." msgstr "스토리지 í’€ì„ ì‹ë³„하는 ë° ì‚¬ìš©ë˜ëŠ” ì´ë¦„ì´ë©° 비어 있지 않아야 합니다." msgid "Storage Pool Type" msgstr "스토리지 í’€ 유형" msgid "Storage Path" msgstr "스토리지 경로" msgid "" "The path of the Storage Pool. Each Storage Pool must have a unique path." msgstr "스토리지 í’€ì˜ ê²½ë¡œìž…ë‹ˆë‹¤. ê° ìŠ¤í† ë¦¬ì§€ í’€ì€ ê³ ìœ  경로를 가져야 합니다." msgid "" "Kimchi will try to create the directory when it does not already exist in " "your system." msgstr "" "디렉토리가 ì‹œìŠ¤í…œì— ì´ë¯¸ 존재하지 않으면 Kimchiê°€ 디렉토리 ìž‘ì„±ì„ ì‹œë„합니다." msgid "NFS Server IP" msgstr "NFS 서버 IP" msgid "NFS server IP or hostname. It can be input or chosen from history." msgstr "" "NFS 서버 IP ë˜ëŠ” 호스트 ì´ë¦„입니다. ì´ê²ƒì€ 입력하거나 히스토리ì—서 ì„ íƒí•  수 " "있습니다." msgid "NFS Path" msgstr "NFS 경로" msgid "The NFS exported path on NFS server." msgstr "NFS 서버ì—서 NFSì˜ ë‚´ë³´ë‚¸ 경로입니다." msgid "Device path" msgstr "장치 경로" msgid "iSCSI Server" msgstr "iSCSI 서버" msgid "iSCSI server IP or hostname. It should not be empty." msgstr "iSCSI 서버 IP ë˜ëŠ” 호스트 ì´ë¦„입니다. 비어 있지 않아야 합니다." msgid "Server" msgstr "서버" msgid "Port" msgstr "í¬íЏ" msgid "Target" msgstr "대ìƒ" msgid "The iSCSI target on iSCSI server" msgstr "iSCSI ì„œë²„ì˜ iSCSI 대ìƒ" msgid "Add iSCSI Authentication" msgstr "iSCSI ì¸ì¦ 추가" msgid "iSCSI Authentication" msgstr "iSCSI ì¸ì¦" msgid "SCSI Adapter" msgstr "SCSI 어댑터" msgid "Please, wait..." msgstr "잠시 기다려 주십시오." msgid "Add Template" msgstr "템플리트 추가" msgid "Where is the source media for this template? " msgstr "ì´ í…œí”Œë¦¬íŠ¸ì˜ ì†ŒìŠ¤ 매체는 ì–´ë””ì— ìžˆìŠµë‹ˆê¹Œ?" msgid "Local ISO Image" msgstr "로컬 ISO ì´ë¯¸ì§€" msgid "Local Image File" msgstr "" msgid "Remote ISO Image" msgstr "ì›ê²© ISO ì´ë¯¸ì§€" msgid "Search ISOs" msgstr "ISO 검색" msgid "The following ISOs are available:" msgstr "ë‹¤ìŒ ISOê°€ 사용 가능합니다." msgid "OS: " msgstr "OS: " msgid "Version: " msgstr "버전: " msgid "Size: " msgstr "í¬ê¸°: " msgid "Search more ISOs" msgstr "추가 ISO 검색" msgid "Create Templates from Selected ISO" msgstr "ì„ íƒí•œ ISO로부터 템플리트 작성" msgid "I want to use a specific ISO file" msgstr "특정 ISO 파ì¼ì„ 사용하려고 합니다." msgid "Loading default remote ISOs ..." msgstr "기본 ì›ê²© ISO 로드 중..." msgid "Arch: " msgstr "Arch: " msgid "I want to use a custom URL" msgstr "ì‚¬ìš©ìž ì •ì˜ URLì„ ì‚¬ìš©í•˜ë ¤ê³  합니다." msgid "Edit Template" msgstr "템플리트 편집" msgid "Processor" msgstr "프로세서" msgid "CDROM" msgstr "CDROM" msgid "Image File" msgstr "" msgid "Graphics" msgstr "그래픽" msgid "Disk(GB)" msgstr "" msgid "Disk Format" msgstr "" msgid "CPU Number" msgstr "CPU 번호" msgid "Manually set CPU topology" msgstr "" msgid "Cores" msgstr "" msgid "Threads" msgstr "" msgid "CPU" msgstr "CPU" msgid "Disk I/O" msgstr "ë””ìŠ¤í¬ I/O" msgid "Network I/O" msgstr "ë„¤íŠ¸ì›Œí¬ I/O" msgid "Livetile" msgstr "ë¼ì´ë¸Œíƒ€ì¼" msgid "No guests found." msgstr "게스트가 없습니다." msgid "Shut down" msgstr "시스템 종료" msgid "Restart" msgstr "다시 시작" msgid "Basic Information" msgstr "기본 ì •ë³´" msgid "OS Distro" msgstr "OS Distro" msgid "OS Code Name" msgstr "OS 코드 ì´ë¦„" msgid "CPU(s)" msgstr "" msgid "System Statistics" msgstr "시스템 통계" msgid "Update Progress" msgstr "ì§„í–‰ìƒíƒœ ì—…ë°ì´íЏ" msgid "Network Name" msgstr "ë„¤íŠ¸ì›Œí¬ ì´ë¦„" msgid "State" msgstr "ìƒíƒœ" msgid "Network Type" msgstr "ë„¤íŠ¸ì›Œí¬ ìœ í˜•" msgid "Address Space" msgstr "주소 공간" msgid "Name should not contain '/' and '\"'." msgstr "올바르지 ì•Šì€ ìŠ¤í† ë¦¬ì§€ í’€ ì´ë¦„입니다. '/'를 í¬í•¨í•˜ì§€ 않아야 합니다." msgid "Isolated: no external network connection" msgstr "격리ë¨: ë¬¼ë¦¬ì  ë„¤íŠ¸ì›Œí¬ ì—°ê²° ì—†ìŒ" msgid "NAT: outbound physical network connection only" msgstr "NAT: 아웃바운드 ë¬¼ë¦¬ì  ë„¤íŠ¸ì›Œí¬ ì—°ê²°ë§Œ" msgid "Bridged: Virtual machines are connected to physical network directly" msgstr "브릿지ë¨: ê°€ìƒ ë¨¸ì‹ ì´ ë¬¼ë¦¬ì  ë„¤íŠ¸ì›Œí¬ì— ì§ì ‘ ì—°ê²°ë¨" msgid "(No interfaces found)" msgstr "" msgid "Destination" msgstr "대ìƒ:" msgid "Enable VLAN" msgstr "VLAN 사용:" msgid "VLAN ID" msgstr "VLAN ID:" msgid "Stop" msgstr "중지" msgid "%Used" msgstr "" msgid "Location" msgstr "위치" msgid "Capacity" msgstr "용량" msgid "Allocated" msgstr "할당ë¨" msgid "active" msgstr "활성" msgid "inactive" msgstr "비활성" msgid "Deactivate" msgstr "비활성화" msgid "Activate" msgstr "활성화" msgid "Add Volume" msgstr "" msgid "Extend" msgstr "" msgid "Undefine" msgstr "ì •ì˜ ì·¨ì†Œ" msgid "Format" msgstr "í¬ë§·:" msgid "Allocation" msgstr "할당:" msgid "No templates found." msgstr "템플리트가 없습니다." kimchi-1.5.0/po/pt_BR.po000066400000000000000000002046451254252253000147600ustar00rootroot00000000000000# i18n portable object for kimchi. # Copyright (C) IBM, Corp. 2013-2014 # ShaoHe Feng , 2013-04-18. # # 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 # msgid "" msgstr "" "Project-Id-Version: kimchi 1.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-06-24 09:39-0300\n" "PO-Revision-Date: 2015-03-23 12:57+0000\n" "Last-Translator: Crístian Deives dos Santos Viana \n" "Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/" "kimchi/language/pt_BR/)\n" "Language: pt_BR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" #, python-format msgid "Unknown parameter %(value)s" msgstr "Parâmetro desconhecido: %(value)s" #, python-format msgid "Delete is not allowed for %(resource)s" msgstr "Método de remoção não é permitido em %(resource)s" #, python-format msgid "%(resource)s does not implement update method" msgstr "%(resource)s não implementa método de atualização" #, python-format msgid "Create is not allowed for %(resource)s" msgstr "Método de criação não é permitido em %(resource)s" msgid "Unable to parse JSON request" msgstr "Não é possível realizar a leitura da requisição do JSON" msgid "This API only supports JSON" msgstr "Essa API suporta apenas JSON" #, python-format msgid "Parameters does not match requirement in schema: %(err)s" msgstr "Parâmetros não correspondem à especificação do esquema: %(err)s" msgid "You don't have permission to perform this operation." msgstr "Você não tem permissão para executar esta operação." msgid "Datastore is not initiated in the model object." msgstr "Datastore não está inicializado no objeto modelo." #, python-format msgid "Unable to start task due error: %(err)s" msgstr "Não foi possível iniciar a tarefa devido a um erro: %(err)s" #, python-format msgid "Timeout of %(seconds)s seconds expired while running task '%(task)s." msgstr "" "Limite de tempo de %(seconds)s segundos expirado ao executar a tarefa " "'%(task)s'." #, python-format msgid "Authentication failed for user '%(username)s'. [Error code: %(code)s]" msgstr "" "Autenticação falhou para o usuário '%(username)s'. [Código de erro: %(code)s]" msgid "You are not authorized to access Kimchi" msgstr "Você não está autorizado para acessar o Kimchi" #, python-format msgid "Specify %(item)s to login into Kimchi" msgstr "Especifique %(item)s para autenticar no Kimchi" #, python-format msgid "User %(user_id)s not found with given LDAP settings." msgstr "Usuário %(user_id)s não encontrado com as configurações LDAP dadas." #, python-format msgid "Invalid LDAP configuration: %(item)s : %(value)s" msgstr "Configurações LDAP inválidas: %(item)s : %(value)s" msgid "Unknown \"_cap\" specified" msgstr "\"_cap\" desconhecido especificado" msgid "\"_passthrough\" should be \"true\" or \"false\"" msgstr "\"_passthrough\" deve ser \"true\" ou \"false\"" msgid "\"_passthrough_affected_by\" should be a device name string" msgstr "\"_passthrough_affected_by\" deve ser um texto do nome do dispositivo" #, python-format msgid "Error while getting block devices. Details: %(err)s" msgstr "Erro ao consultar block devices. Detalhes %(err)s" #, python-format msgid "Error while getting block device information for %(device)s." msgstr "Erro ao consultar informações de block devices para %(device)s." #, python-format msgid "Unable to find distro file: %(filename)s" msgstr "Não foi possível encontrar o arquivo da distribuição: %(filename)s" #, python-format msgid "" "Unable to parse distro file: %(filename)s. Make sure, it is a JSON file." msgstr "" "Não foi possível ler o arquivo da distribuição: %(filename)s. Confirme se é " "um arquivo JSON." #, python-format msgid "Unable to login to iSCSI host target %(portal)s. Details: %(err)s" msgstr "" "Não foi possível logar na máquina alvo do iSCSI %(portal)s. Detalhes: %(err)s" #, python-format msgid "Unable to login to iSCSI host %(host)s target %(target)s" msgstr "Não foi possível logar na máquina %(host)s alvo %(target)s do iSCSI" #, python-format msgid "Unable to find ISO file %(filename)s" msgstr "Não foi possível encontrar a ISO %(filename)s" #, python-format msgid "The ISO file %(filename)s is not bootable" msgstr "A ISO %(filename)s não é bootável" #, python-format msgid "The ISO file %(filename)s does not have a valid El Torito boot record" msgstr "A ISO %(filename)s não possui uma gravação válida de boot El Torito" #, python-format msgid "Invalid El Torito validation entry in ISO %(filename)s" msgstr "Validação El Torito inválida na ISO %(filename)s" #, python-format msgid "Invalid El Torito boot indicator in ISO %(filename)s" msgstr "Indicador de boot El Torito inválido na ISO %(filename)s" #, python-format msgid "Unexpected volume type for primary volume in ISO %(filename)s" msgstr "" "Tipo de volume não esperado para um volume primário na ISO %(filename)s" #, python-format msgid "Bad format while reading volume descriptor in ISO %(filename)s" msgstr "Formato errado na leitura do descritor de volume na ISO %(filename)s" #, python-format msgid "" "The hypervisor doesn't have permission to use this ISO %(filename)s. " "Consider moving it under /var/lib/libvirt, or set the search permission to " "file access control lists for '%(user)s' user if possible, or add the " "'%(user)s' to the ISO path group, or (not recommended) 'chmod -R o+x " "'path_to_iso'.Details: %(err)s" msgstr "" "O servidor não tem permissão para acessar a ISO %(filename)s. Considere mudá-" "la para o diretório /var/lib/libvirt, ou mude as permissões para que o " "usuário '%(user)s' tenha acesso, ou, adicione o usuário '%(user)s' no grupo " "do caminho da ISO, ou (não recomendado) 'chmod -R o+x 'caminho_para_iso'. " "Detalhes: %(err)s" msgid "An error occurred when probing image OS information." msgstr "Ocorreu um erro ao identificar o sistema operacional da imagem." msgid "No OS information found in given image." msgstr "" "Nenhuma informação de sistema operacional encontrada na imagem fornecida." #, python-format msgid "Unable to read image file %(filename)s" msgstr "Não foi possível ler o arquivo de imagem %(filename)s." #, python-format msgid "" "Image file must be an existing file on system. %(filename)s is not a valid " "input." msgstr "" "Arquivo de imagem deve ser um arquivo existente no sistema. %(filename)s não " "é uma entrada válida." #, python-format msgid "Virtual machine %(name)s already exists" msgstr "Máquina virtual %(name)s já existe" #, python-format msgid "Virtual machine %(name)s does not exist" msgstr "Máquina virtual %(name)s não existe" #, python-format msgid "" "Unable to rename virtual machine %(name)s. The name %(new_name)s is already " "in use or the virtual machine is not powered off." msgstr "" "Não foi possível renomear a máquina virtual %(name)s. O nome %(new_name)s já " "está em uso ou a máquina virtual não está ligada." #, python-format msgid "Unable to retrieve screenshot for stopped virtual machine %(name)s" msgstr "" "Não foi possível tirar uma foto da tela para a máquina virtual %(name)s que " "está desligada" msgid "Remote ISO image is not supported by this server." msgstr "Imagem de ISO remota não é suportada por esse servidor." #, python-format msgid "Screenshot is not supported on virtual machine %(name)s" msgstr "Foto da tela não é suportado na máquina virtual %(name)s" #, python-format msgid "Unable to create virtual machine %(name)s. Details: %(err)s" msgstr "Não foi possível criar a máquina virtual %(name)s. Detalhes: %(err)s" #, python-format msgid "Unable to update virtual machine %(name)s. Details: %(err)s" msgstr "" "Não foi possível atualizar a máquina virtual %(name)s. Detalhes: %(err)s" #, python-format msgid "Unable to retrieve virtual machine %(name)s. Details: %(err)s" msgstr "" "Não foi possível encontrar a máquina virtual %(name)s. Detalhes: %(err)s" #, python-format msgid "Unable to connect to powered off virtual machine %(name)s." msgstr "Não foi possível conectar à máquina virtual desligada %(name)s." msgid "Virtual machine name must be a string without slashes (/)" msgstr "" #, python-format msgid "Invalid template URI %(value)s specified for virtual machine" msgstr "URI do Modelo inválida %(value)s especificada para máquina virtual" #, python-format msgid "Invalid storage pool URI %(value)s specified for virtual machine" msgstr "" "URI do Storage pool URI inválida %(value)s especificada para máquina virtual" msgid "Supported virtual machine graphics are Spice or VNC" msgstr "Gráficos suportados para a máquina virtual são Spice ou VNC" msgid "Graphics address to listen on must be IPv4 or IPv6" msgstr "Endereço para receber eventos gráficos deve ser IPv4 ou IPv6" msgid "Specify a template to create a virtual machine from" msgstr "Especifique um modelo para ser base da criação da máquina virtual" #, python-format msgid "Unable to start virtual machine %(name)s. Details: %(err)s" msgstr "Não foi possível iniciar a máquina virtual %(name)s. Detalhes: %(err)s" #, python-format msgid "Unable to power off virtual machine %(name)s. Details: %(err)s" msgstr "" "Não foi possível forçar o desligamento da máquina virtual %(name)s. " "Detalhes: %(err)s" #, python-format msgid "Unable to delete virtual machine %(name)s. Details: %(err)s" msgstr "Não foi possível remover a máquina virtual %(name)s. Detalhes: %(err)s" #, python-format msgid "Unable to reset virtual machine %(name)s. Details: %(err)s" msgstr "" "Não foi possível reiniciar a máquina virtual %(name)s. Detalhes: %(err)s" msgid "User name list must be an array" msgstr "Lista de nomes de usuário deve ser um array" msgid "User name must be a string" msgstr "Nome de usuário deve ser um texto" msgid "Group name list must be an array" msgstr "Lista de nomes de grupo deve ser um array" msgid "Group name must be a string" msgstr "Nome de grupo deve ser um texto" #, python-format msgid "User(s) '%(users)s' do not exist" msgstr "Usuário(s) '%(users)s' não existe(m)" #, python-format msgid "Group(s) '%(groups)s' do not exist" msgstr "Grupo(s) '%(groups)s' não existe(m)" #, python-format msgid "Unable to shutdown virtual machine %(name)s. Details: %(err)s" msgstr "" "Não foi possível desligar a máquina virtual %(name)s. Detalhes: %(err)s" #, python-format msgid "" "Unable to get access metadata of virtual machine %(name)s. Details: %(err)s" msgstr "" "Não foi possível acessar os metadados da máquina virtual %(name)s. Detalhes: " "%(err)s" msgid "The guest console password must be a string." msgstr "A senha para o console do guest deve ser um texto." msgid "The life time for the guest console password must be a number." msgstr "O tempo de vida da senha do console do guest deve ser um número." #, python-format msgid "Virtual machine '%(name)s' must be stopped before cloning it." msgstr "A máquina virtual '%(name)s' deve estar parada antes de cloná-la." #, python-format msgid "Insufficient disk space to clone virtual machine '%(name)s'" msgstr "Espaço em disco insuficiente para clonar a máquina virtual '%(name)s'" #, python-format msgid "Unable to clone VM '%(name)s'. Details: %(err)s" msgstr "Não foi possível clonar a VM '%(name)s'. Detalhes: %(err)s" #, python-format msgid "Invalid operation for non-persistent virtual machine %(name)s" msgstr "Operação inválida para máquina virtual não-persistente %(name)s" #, python-format msgid "Cannot suspend VM '%(name)s' because it is not running." msgstr "" #, python-format msgid "Unable to suspend VM '%(name)s'. Details: %(err)s" msgstr "" #, python-format msgid "Cannot resume VM '%(name)s' because it is not paused." msgstr "" #, python-format msgid "Unable to resume VM '%(name)s'. Details: %(err)s" msgstr "" msgid "Memory assigned is higher then the maximum allowed in the host." msgstr "" #, python-format msgid "" "VM '%(name)s' does not support live memory update. Update the memory with " "the machine offline to enable this feature." msgstr "" msgid "Only increase memory is allowed in active VMs" msgstr "" msgid "" "For live memory update, new memory value must be equal old memory value plus " "multiples of 1024 Mib" msgstr "" msgid "There are not enough free slots of 1024 Mib in the guest." msgstr "" msgid "" "Host's libvirt version does not support memory devices. Libvirt must be >= " "1.2.14" msgstr "" #, python-format msgid "Error attaching memory device. Details: %(error)s" msgstr "" #, python-format msgid "" "VM %(vmid)s does not contain directly assigned host device %(dev_name)s." msgstr "" "A VM %(vmid)s não contém o dispositivo de host atribuído diretamente " "%(dev_name)s." #, python-format msgid "The host device %(dev_name)s is not allowed to directly assign to VM." msgstr "" "Não é permitido atribuir diretamente o dispositivo de host %(dev_name)s." msgid "" "No IOMMU groups found. Host PCI pass through needs IOMMU group to function " "correctly. Please enable Intel VT-d or AMD IOMMU in your BIOS, then verify " "the Kernel is compiled with IOMMU support. For Intel CPU, add intel_iommu=on " "to your Kernel parameter in /boot/grub2/grub.conf. For AMD CPU, add iommu=pt " "iommu=1." msgstr "" "Nenhum grupo IOMMU encontrado. Passthrough de host PCI necessita do grupo " "IOMMU para funcionar corretamente. Por favor, habilite o suporte ao Intel VT-" "d ou AMD IOMMU. Para uma CPU Intel, adicione \"intel_iommu=on\" nos seus " "parâmetros de kernel em \"/boot/grub2/grub.conf\". Para uma CPU AMD, " "adicione \"iommu=pt iommu=1\"." msgid "\"name\" should be a device name string" msgstr "\"nome\" deve ser um texto do nome do dispositivo." #, python-format msgid "" "The device %(name)s is probably in use by the host. Unable to attach it to " "the guest." msgstr "" #, python-format msgid "Interface %(iface)s does not exist in virtual machine %(name)s" msgstr "Interface %(iface)s não existe na máquina virtual %(name)s" #, python-format msgid "" "Network %(network)s specified for virtual machine %(name)s does not exist" msgstr "" "Rede %(network)s especificada para a máquina virtual %(name)s não existe" msgid "Supported virtual machine interfaces type is only network" msgstr "Tipo de interface suportado das máquinas virtuais é somente rede" msgid "Network name for virtual machine interface must be a string" msgstr "Nome da rede para a interface da máquina virtual deve ser texto" msgid "Invalid network model card specified for virtual machine interface" msgstr "Modelo de placa de rede inválido para a interface da máquina virtual" msgid "Specify type and network to add a new virtual machine interface" msgstr "" "Especifique o tipo e a rede para adicionar uma nova interface da máquina " "virtual" msgid "MAC Address must respect this format FF:FF:FF:FF:FF:FF" msgstr "" #, python-format msgid "MAC Address %(mac)s already exists in virtual machine %(name)s" msgstr "" msgid "Invalid MAC Address" msgstr "" msgid "Cannot change MAC address of a running virtual machine" msgstr "" #, python-format msgid "Template %(name)s already exists" msgstr "Modelo %(name)s já existe" #, python-format msgid "" "Network '%(network)s' specified for template %(template)s does not exist" msgstr "Rede '%(network)s' especificada para o modelo %(template)s não existe" #, python-format msgid "" "Storage pool %(pool)s specified for template %(template)s does not exist" msgstr "" "Storage pool %(pool)s especificado para o modelo %(template)s não existe" #, python-format msgid "Storage pool %(pool)s specified for template %(template)s is not active" msgstr "" "Storage pool %(pool)s especificado para o modelo %(template)s não está ativo" #, python-format msgid "Invalid parameter '%(param)s' specified for CDROM." msgstr "Parâmetro inválido '%(param)s' especificado para CDROM" #, python-format msgid "Network %(network)s specified for template %(template)s is not active" msgstr "Rede %(network)s especificada para modelo %(template)s não está ativa" msgid "Template name must be a string" msgstr "Nome do modelo deve ser um texto" msgid "Template icon must be a path to the image" msgstr "Ãcone do modelo deve ser um caminho para uma imagem" msgid "Template distribution must be a string" msgstr "Distribuição do modelo deve ser um texto" msgid "Template distribution version must be a string" msgstr "Versão da distribuição do modelo deve ser um texto" msgid "The number of CPUs must be an integer greater than 0" msgstr "O número de CPUs deve ser um inteiro maior do que 0" msgid "Amount of memory (MB) must be an integer greater than 512" msgstr "Quantidade de memória (MB) deve ser um inteiro maior que 512" msgid "Template CDROM must be a local or remote ISO file" msgstr "Modelo do CDROM deve ser um arquivo ISO local ou remoto" #, python-format msgid "Invalid storage pool URI %(value)s specified for template" msgstr "URI de storage pool inválido %(value)s especificado para modelo" msgid "Specify an ISO image as CDROM or a base image to create a template" msgstr "" "Especifique uma imagem ISO como CD-ROM ou uma imagem base para criar um " "modelo" msgid "All networks for the template must be specified in a list." msgstr "Todas redes para o modelo devem ser especificadas em uma lista" msgid "Specify a volume to a template when storage pool is iSCSI or SCSI" msgstr "" "Especifique um volume para o template quando o storage pool for iSCSI or SCSI" #, python-format msgid "The volume %(volume)s is not in storage pool %(pool)s" msgstr "O volume %(volume)s não está no storage pool %(pool)s" #, python-format msgid "Unable to create template due error: %(err)s" msgstr "Não foi possível criar o modelo devido a um erro: %(err)s" #, python-format msgid "Unable to delete template due error: %(err)s" msgstr "Não foi possível remover o modelo devido a um erro: %(err)s" msgid "Disk size must be an integer greater than 1GB." msgstr "O tamanho do disco deve ser um número inteiro maior que 1GB." msgid "Template base image must be a valid local image file" msgstr "Imagem base do modelo deve ser um arquivo de imagem local válido" #, python-format msgid "Cannot identify base image %(path)s format" msgstr "Não foi possível identificar o formato da imagem base %(path)s" msgid "" "When specifying CPU topology, VCPUs must be a product of sockets, cores, and " "threads." msgstr "" "Ao especificar a topologia de CPU, VCPUs deve ser um produto de sockets, " "cores e threads." msgid "" "When specifying CPU topology, each element must be an integer greater than " "zero." msgstr "" "Ao especificar a topologia de CPU, cada elemento deve ser um número inteiro " "maior do que zero." msgid "" "Invalid disk image format. Valid formats: bochs, cloop, cow, dmg, qcow, " "qcow2, qed, raw, vmdk, vpc." msgstr "" "Formato de imagem de disco inválido. Formatos válidos: bochs, cloop, cow, " "dmg, qcow, qcow2, qed, raw, vmdk, vpc." #, python-format msgid "Storage pool %(name)s already exists" msgstr "Storage pool %(name)s já existe" #, python-format msgid "Storage pool %(name)s does not exist" msgstr "Storage pool %(name)s não existe" #, python-format msgid "Specify %(item)s in order to create the storage pool %(name)s" msgstr "Especifique %(item)s para criar o storage pool %(name)s" #, python-format msgid "Unable to delete active storage pool %(name)s" msgstr "Não foi possível remover o storage pool ativo %(name)s" #, python-format msgid "Unable to list storage pools. Details: %(err)s" msgstr "Não foi possível listar os storage pools. Detalhes: %(err)s" #, python-format msgid "Unable to create storage pool %(name)s. Details: %(err)s" msgstr "Não foi possível criar o storage pool %(name)s. Detalhes: %(err)s" #, python-format msgid "" "Unable to get number of storage volumes in storage pool %(name)s. Details: " "%(err)s" msgstr "" "Não foi possível saber o número de volumes no storage pool %(name)s. " "Detalhes: %(err)s" #, python-format msgid "Unable to activate storage pool %(name)s. Details: %(err)s" msgstr "Não foi possivel ativar o storage pool %(name)s. Detalhes: %(err)s" #, python-format msgid "Unable to deactivate storage pool %(name)s. Details: %(err)s" msgstr "Não foi possivel desativar o storage pool %(name)s. Detalhes: %(err)s" #, python-format msgid "Unable to delete storage pool %(name)s. Details: %(err)s" msgstr "Não foi possivel remover o storage pool %(name)s. Detalhes: %(err)s" #, python-format msgid "" "Unable to create NFS Pool as export path %(path)s may block during mount" msgstr "" "Não foi possível criar Pool NFS uma vez que o caminho de exportação %(path)s " "pode bloquear durante a montagem" #, python-format msgid "Unable to create NFS Pool as export path %(path)s mount failed" msgstr "" "Não foi possível criar NFS Pool uma vez que a montagem do caminho de " "exportação %(path)s falhou" #, python-format msgid "Unsupported storage pool type: %(type)s" msgstr "Tipo de storage pool não suportado: %(type)s" #, python-format msgid "Error while retrieving storage pool XML to %(pool)s" msgstr "Erro durante a leitura do XML do storage pool %(pool)s" msgid "Storage pool name must be a string without slashes (/)" msgstr "" msgid "" "Supported storage pool types are dir, netfs, logical, iscsi, isci and kimchi-" "iso" msgstr "" "Tipos de storage pool supportados são dir, netfs, logical, iscsi, scsi e " "kimchi-iso" msgid "Storage pool path must be a string" msgstr "Caminho para storage pool deve ser um texto" msgid "Storage pool host must be a IP or hostname" msgstr "Host do storage pool deve ser um IP ou um hostname" msgid "Storage pool device must be the absolute path to the block device" msgstr "" "Dispositivo do storage pool deve ser o caminho absoluto para o block device" msgid "Storage pool devices parameter must be a list" msgstr "Parâmetro dos dispositivos do storage pool devem ser uma lista" msgid "Target IQN of an iSCSI pool must be a string" msgstr "Alvo IQN de um pool iSCSI deve ser um texto" msgid "Port of a remote storage server must be an integer between 1 and 65535" msgstr "" "Porta de um servidor remoto de storage deve ser um inteiro entre 1 e 65535" msgid "iSCSI target username must be a string" msgstr "Usuário do iSCSI target deve ser um texto" msgid "iSCSI target password must be a string" msgstr "Senha do iSCSI target deve ser um texto" msgid "Specify name and type to create a storage pool" msgstr "Especifique o nome e o tipo para criar um storage pool" #, python-format msgid "" "%(disk)s is not a valid disk/partition. Could not add it to the pool " "%(pool)s." msgstr "" "%(disk)s não é um disco/partição válido. Não foi possível adicioná-lo ao " "pool %(pool)s." #, python-format msgid "Unable to extend logical pool %(pool)s. Details: %(err)s" msgstr "Não foi possível extender o pool lógico %(pool)s. Detalhes: %(err)s" msgid "The parameter disks only can be updated for logical storage pool." msgstr "" "O parâmetro discos somente pode ser atualizado para storage pool lógicos." msgid "The SCSI host adapter name must be a string." msgstr "O nome do adaptador SCSI host deve ser um texto" msgid "The storage pool kimchi_isos is reserved for internal use" msgstr "O storage pool kimchi_isos é reservado para uso interno" #, python-format msgid "" "Unable to activate NFS storage pool %(name)s. NFS server %(server)s is " "unreachable." msgstr "" "Não foi possível ativar o storage pool NFS %(name)s. Servidor NFS %(server)s " "está inacessível." #, python-format msgid "" "Unable to deactivate NFS storage pool %(name)s. NFS server %(server)s is " "unreachable." msgstr "" "Não foi possível desativar o storage pool NFS %(name)s. Servidor NFS " "%(server)s está inacessível." #, python-format msgid "" "Unable to deactivate pool %(name)s as it is associated with some templates" msgstr "" "Não foi possível desativar o pool %(name)s uma vez que ele está associado " "com algum dos modelos" #, python-format msgid "Unable to delete pool %(name)s as it is associated with some templates" msgstr "" "Não foi possível remover o pool %(name)s uma vez que ele está associado com " "algum dos modelos" #, python-format msgid "" "A volume group named '%(name)s' already exists. Please, choose another name " "to create the logical pool." msgstr "" "Um grupo de volume chamado '%(name)s' já existe. Por favor, escolha outro " "nome para criar o pool lógico." #, python-format msgid "Unable to update database with deep scan information due error: %(err)s" msgstr "" "Não foi possível atualizar a base de dados com informações de mais ISOs " "devido a um erro: %(err)s" #, python-format msgid "Storage volume %(name)s already exists" msgstr "Volume de storage %(name)s já existe" #, python-format msgid "Storage volume %(name)s does not exist in storage pool %(pool)s" msgstr "Volume de storage %(name)s não existe no storage pool %(pool)s" #, python-format msgid "" "Unable to create storage volume %(volume)s because storage pool %(pool)s is " "not active" msgstr "" "Não foi possível criar o storaget volume %(volume)s pois o storage pool " "%(pool)s não está ativo" #, python-format msgid "Specify %(item)s in order to create storage volume %(volume)s" msgstr "Especifique %(item)s para poder criar o volume %(volume)s" #, python-format msgid "" "Unable to list storage volumes because storage pool %(pool)s is not active" msgstr "" "Não foi possível listar volumes pois o storage pool %(pool)s não está ativo" #, python-format msgid "" "Unable to create storage volume %(name)s in storage pool %(pool)s. Details: " "%(err)s" msgstr "" "Não foi possível criar o volume %(name)s no storage pool %(pool)s. Detalhes: " "%(err)s" #, python-format msgid "" "Unable to list storage volumes in storage pool %(pool)s. Details: %(err)s" msgstr "" "Não foi possível listar os volumes do storage pool %(pool)s. Detalhes: " "%(err)s" #, python-format msgid "Unable to wipe storage volumes %(name)s. Details: %(err)s" msgstr "Não foi possível limpar o volume %(name)s. Detalhes: %(err)s" #, python-format msgid "Unable to delete storage volume %(name)s. Details: %(err)s" msgstr "Não foi possível remover o volume %(name)s. Detalhes: %(err)s" #, python-format msgid "Unable to resize storage volume %(name)s. Details: %(err)s" msgstr "Não foi possível redimensionar o volume %(name)s. Detalhes: %(err)s" #, python-format msgid "Storage type %(type)s does not support volume create and delete" msgstr "Storage do tipo %(type)s não suporta criação ou remoção de volume" msgid "Storage volume name must be a string" msgstr "Nome do volume deve ser um texto" msgid "Storage volume allocation must be an integer number" msgstr "Alocação do volume de storage deve ser um número inteiro" msgid "" "Storage volume format not supported. Valid formats: bochs, cloop, cow, dmg, " "qcow, qcow2, qed, raw, vmdk, vpc." msgstr "" "Formato de volume de storage inválido. Formatos válidos: bochs, cloop, cow, " "dmg, qcow, qcow2, qed, raw, vmdk, vpc." msgid "Storage volume requires a volume name" msgstr "Volume de storage requer um nome" #, python-format msgid "" "Unable to update database with storage volume information due error: %(err)s" msgstr "" "Não foi possível atualizar a base de dados com informações de volume de " "storage devido a um erro: %(err)s" #, python-format msgid "Only one of parameter %(param)s can be specified" msgstr "Somente um parâmetro %(param)s pode ser especificado" #, python-format msgid "Create volume from %(param)s is not supported" msgstr "Criar um volume a partir de %(param)s não é suportado" msgid "Storage volume capacity must be an integer number." msgstr "A capacidade do storage volume deve ser um número inteiro." msgid "Storage volume URL must be http://, https://, ftp:// or ftps://." msgstr "" "URL para o storage volume deve ser http://, https://, ftp:// ou ftps://." #, python-format msgid "Unable to access file %(url)s. Please, check it." msgstr "Erro ao acessar arquivo %(url)s. Por favor, verifique isso." #, python-format msgid "" "Unable to clone storage volume '%(name)s' in pool '%(pool)s'. Details: " "%(err)s" msgstr "" "Não foi possível clonar o volume de storage '%(name)s' no pool '%(pool)s'. " "Detalhes: %(err)s" msgid "Specify chunk data and its size to upload a file." msgstr "" msgid "In order to upload a storage volume, specify the 'upload' parameter." msgstr "" msgid "" "Unable to upload chunk data as it does not match with requested chunk size." msgstr "" #, python-format msgid "The storage volume %(vol)s is not under an upload process." msgstr "" msgid "The upload chunk data will exceed the storage volume size." msgstr "" #, python-format msgid "Unable to upload chunk data to storage volume. Details: %(err)s." msgstr "" #, python-format msgid "Interface %(name)s does not exist" msgstr "Interface %(name)s não existe" #, python-format msgid "Network %(name)s already exists" msgstr "Rede %(name)s já existe" #, python-format msgid "Network %(name)s does not exist" msgstr "Rede %(name)s não existe" #, python-format msgid "Subnet %(subnet)s specified for network %(network)s is not valid." msgstr "" "A subrede %(subnet)s especificada para a rede %(network)s não é válida." #, python-format msgid "Specify a network interface to create bridged network %(name)s" msgstr "Especifique uma interface de rede para criar a rede de bridge %(name)s" #, python-format msgid "Unable to delete active network %(name)s" msgstr "Não foi possível remover a rede ativa %(name)s" #, python-format msgid "Interface %(iface)s specified for network %(network)s is already in use" msgstr "" "A interface %(iface)s especificada para a rede %(network)s já está em uso" msgid "Interface should be bare NIC, bonding or bridge device." msgstr "Interface deve ser 'bare NIC', 'bonding' ou 'dispositivo de bridge'." #, python-format msgid "Unable to create network %(name)s. Details: %(err)s" msgstr "Não foi possível criar a rede %(name)s. Detalhes: %(err)s" #, python-format msgid "Unable to find a free IP address for network '%(name)s'" msgstr "Não foi possível encontrar um endereço IP livre para a rede '%(name)s'" #, python-format msgid "The interface %(iface)s already exists." msgstr "A interface %(iface)s já existe" msgid "Network name must be a string without slashes (/) or quotes (\")" msgstr "" msgid "Supported network types are isolated, NAT and bridge" msgstr "Tipos de rede suportados são isolada, NAT e bridge" msgid "Network subnet must be a string with IP address and prefix or netmask" msgstr "" "Subrede deve ser um texto com endereço IP e prefixo, ou máscara de rede" msgid "Network interface must be a string" msgstr "Interface de rede deve ser um texto" msgid "Network VLAN ID must be an integer between 1 and 4094" msgstr "ID da rede VLAN deve ser um inteiro entre 1 e 4094" msgid "Specify name and type to create a Network" msgstr "Especifique o nome e o tipo para criar uma rede" #, python-format msgid "" "Unable to delete network %(name)s. There are some virtual machines %(vms)s " "and/or templates linked to this network." msgstr "" "Não foi possível desativar a rede %(name)s. Há alguma máquina virtual " "%(vms)s e/ou modelo associados a esta rede." #, python-format msgid "" "Unable to deactivate network %(name)s. There are some virtual machines " "%(vms)s and/or templates linked to this network." msgstr "" "Não foi possível desativar a rede %(name)s. Há alguma máquina virtual " "%(vms)s e/ou modelo associados a esta rede." #, python-format msgid "Bridge device %(name)s can not be the trunk device of a VLAN." msgstr "" "Dispositivo da bridge %(name)s não pode ser um dispositivo vinculado a uma " "VLAN." #, python-format msgid "Failed to activate interface %(iface)s: %(err)s." msgstr "Não foi possível ativar a interface %(iface)s: %(err)s." #, python-format msgid "" "Failed to activate interface %(iface)s. Please check the physical link " "status." msgstr "" "Não foi possível ativar a interface %(iface)s. Por favor, verifique o status " "da conexão física." #, python-format msgid "Failed to start network %(name)s. Details: %(err)s" msgstr "Não foi possível iniciar a rede %(name)s. Detalhes: %(err)s" #, python-format msgid "Debug report %(name)s does not exist" msgstr "Relatório de debug %(name)s não existe" msgid "Debug report tool not found in system" msgstr "Ferramenta de relatório de debug não encontrada no sistema" #, python-format msgid "Unable to create debug report %(name)s. Details: %(err)s." msgstr "" "Não foi possível criar o relatório de debug %(name)s. Detalhes: %(err)s." #, python-format msgid "Can not find any debug report with the given name %(name)s" msgstr "Não foi possível encontrar nenhum relatório com o nome %(name)s" #, python-format msgid "Unable to generate debug report %(name)s. Details: %(err)s" msgstr "" "Não foi possível gerar o relatório de debug %(name)s. Detalhes: %(err)s" msgid "You should give a name for the debug report file." msgstr "Você deve dar um nome para o arquivo do relatório de debug." msgid "" "Debug report name must be a string. Only letters, digits, underscore ('_') " "and hyphen ('-') are allowed." msgstr "" "Nome do relatório deve ser um texto. Somente letras, digitos, underscore " "('_') e hífem ('-') são permitidos." #, python-format msgid "" "The debug report with specified name \"%(name)s\" already exists. Please use " "another one." msgstr "" "O relatório de debug com o nome especificado \"%(name)s\" já existe. Por " "favor, use outro nome." #, python-format msgid "Storage server %(server)s was not used by Kimchi" msgstr "Servidor de storage %(server)s não foi usado pelo Kimchi" #, python-format msgid "Distro '%(name)s' does not exist" msgstr "Distribuição '%(name)s' não existe" #, python-format msgid "Partition %(name)s does not exist in the host" msgstr "Partição %(name)s não existe no host" msgid "Unable to shutdown host machine as there are running virtual machines" msgstr "" "Não foi possível desligar o host uma vez que há máquinas virtuais ligadas" msgid "Unable to reboot host machine as there are running virtual machines" msgstr "" "Não foi possível resetar o host uma vez que há máquinas virtuais ligadas" #, python-format msgid "Node device '%(name)s' not found" msgstr "Dispositivo de nó '%(name)s' não encontrado" msgid "Conflicting flag filters specified." msgstr "Foram especificados filtros de flag com conflito." msgid "No packages marked for update" msgstr "Nenhum pacote marcado para atualização" #, python-format msgid "Package %(name)s is not marked to be updated." msgstr "Pacote %(name)s não está marcado para atualização." #, python-format msgid "Error while getting packages marked to be updated. Details: %(err)s" msgstr "Erro ao buscar pacotes marcados para atualização. Detalhes: %(err)s" msgid "There is no compatible package manager for this system." msgstr "Não há gerenciador de pacotes compatível para este sistema." #, python-format msgid "Unable to find %(item)s in datastore" msgstr "Não foi possível encontrar %(item)s no datastore" #, python-format msgid "Invalid URI %(uri)s" msgstr "URI %(uri)s inválida" #, python-format msgid "Timeout while running command '%(cmd)s' after %(seconds)s seconds" msgstr "" "Fim do limite de tempo ao rodar comando '%(cmd)s' após %(seconds)s segundos" msgid "Unable to choose a virtual machine name" msgstr "Não foi possível escolher um nome para a máquina virtual" #, python-format msgid "Invalid data value '%(value)s'" msgstr "Valor inválido '%(value)s'" #, python-format msgid "Invalid data unit '%(unit)s'" msgstr "Unidade inválida '%(unit)s'" msgid "Invalid storage type. Types supported: 'cdrom', 'disk'" msgstr "Tipo de storage inválido. Tipos suportados: 'cdrom', 'disco'" #, python-format msgid "The path '%(value)s' is not a valid local/remote path for the device" msgstr "" "O caminho '%(value)s' não é um caminho local/remoto válido para este " "dispositivo" msgid "Only CDROM path can be update." msgstr "Apenas o caminho do CD-ROM pode ser atualizado." #, python-format msgid "" "The storage device %(dev_name)s does not exist in the virtual machine " "%(vm_name)s" msgstr "O disco %(dev_name)s não existe na máquina virtual %(vm_name)s" #, python-format msgid "Error while creating new storage device: %(error)s" msgstr "Erro ao criar novo dispositivo de storage: %(error)s" #, python-format msgid "Error while updating storage device: %(error)s" msgstr "Erro ao atualizar dispositivo de storage: %(error)s" #, python-format msgid "Error while removing storage device: %(error)s" msgstr "Erro ao remover dispositivo de storage: %(error)s" msgid "Do not support IDE device hot plug" msgstr "Dispositivo IDE hot plug não é suportado" msgid "" "Specify type and path or type and pool/volume to add a new virtual machine " "disk" msgstr "" "Especifique o tipo e o caminho, ou o tipo e o pool/volume, para adicionar um " "novo disco da máquina virtual" msgid "Specify path to update virtual machine disk" msgstr "Especifique o caminho para atualizar o disco da máquina virtual" #, python-format msgid "Controller type %(type)s limitation of %(limit)s devices reached" msgstr "" "Limitação do tipo do controlador %(type)s de %(limit)s dispositivos foi " "alcançada" #, python-format msgid "Cannot retrieve disk path information for given pool/volume: %(error)s" msgstr "" "Não foi possível buscar informações do caminho do disco para o pool/volume " "dado: %(error)s" msgid "Volume already in use by other virtual machine." msgstr "Volume já em uso por outra máquina virtual." msgid "" "Only one of path or pool/volume can be specified to add a new virtual " "machine disk" msgstr "" "Somente um caminho ou pool/volume pode ser especificado para adicionar um " "novo disco da máquina virtual." #, python-format msgid "" "Volume chosen with format %(format)s does not fit in the storage type " "%(type)s" msgstr "" "Volume escolhido com formato %(format)s não se enquadra no tipo de storage " "%(type)s" msgid "YUM Repository ID must be one word only string." msgstr "ID do repositório YUM deve ser apenas uma palavra." msgid "Repository URL must be an http://, ftp:// or file:// URL." msgstr "URL do repositório deve ser uma URL http://, ftp:// ou file://." msgid "" "Repository configuration is a dictionary with specific values according to " "repository type." msgstr "" "Configuração do repositório é um dicionário com valores específicos de " "acordo com o tipo do repositório." msgid "Distribution to DEB repository must be a string" msgstr "Distribuição para o repositório DEB deve ser um texto" msgid "Components to DEB repository must be listed in a array" msgstr "Componentes para o repositório DEB deve ser um array" msgid "Components to DEB repository must be a string" msgstr "Componentes para o repositório DEB deve ser um texto" msgid "Mirror list to repository must be a string" msgstr "" msgid "YUM Repository name must be string." msgstr "Nome do repositório YUM deve ser um texto." msgid "GPG check must be a boolean value." msgstr "Verificação de GPG deve ser um valor booleano." msgid "GPG key must be a URL pointing to the ASCII-armored file." msgstr "" "Chave GPG deve ser uma URL apontando para o arquivo no formato ASCII-armor." #, python-format msgid "Could not update repository %(repo_id)s." msgstr "Não foi possível atualizar o repositório %(repo_id)s." #, python-format msgid "Repository %(repo_id)s does not exist." msgstr "Repositório %(repo_id)s não existe." msgid "" "Specify repository base URL, mirror list or metalink in order to create or " "update a YUM repository." msgstr "" msgid "Repository management tool was not recognized for your system." msgstr "" "Ferramenta de gerenciamento de repositório não foi reconhecida no seu " "sistema." #, python-format msgid "Repository %(repo_id)s is already enabled." msgstr "Repositório %(repo_id)s já está habilitado." #, python-format msgid "Repository %(repo_id)s is already disabled." msgstr "Repositório %(repo_id)s já está desabilitado." #, python-format msgid "Could not remove repository %(repo_id)s." msgstr "Não foi possível remover o repositório %(repo_id)s." #, python-format msgid "Could not write repository configuration file %(repo_file)s" msgstr "" "Não foi possível gravar o arquivo de configuração do repositório " "%(repo_file)s" msgid "Specify repository distribution in order to create a DEB repository." msgstr "" "Especificar o repositório de distribuição para poder criar o repositório DEB." #, python-format msgid "Could not enable repository %(repo_id)s." msgstr "Não foi possível habilitar o repositório %(repo_id)s." #, python-format msgid "Could not disable repository %(repo_id)s." msgstr "Não foi possível desabilitar o repositório %(repo_id)s." msgid "YUM Repository ID already exists" msgstr "ID do repositório YUM já existe" msgid "YUM Repository name must be a string" msgstr "Nome do repositório YUM deve ser um texto" #, python-format msgid "Unable to list repositories. Details: '%(err)s'" msgstr "Não é possível listar os repositórios. Detalhes: '%(err)s'" #, python-format msgid "Unable to retrieve repository information. Details: '%(err)s'" msgstr "" "Não foi possível carregar as informações do repositório. Detalhes: '%(err)s'" #, python-format msgid "Unable to add repository. Details: '%(err)s'" msgstr "Não foi possível adicionar o repositório. Detalhes: '%(err)s'" #, python-format msgid "Unable to remove repository. Details: '%(err)s'" msgstr "Não foi possível remover o repositório. Detalhes: '%(err)s'" #, python-format msgid "" "Configuration items: '%(items)s' are not supported by repository manager" msgstr "" "Itens de configuração '%(items)s' não são suportados pelo gerenciador de " "repositórios." msgid "Repository metalink must be an http://, ftp:// or file:// URL." msgstr "" msgid "Cannot specify mirrorlist and metalink at the same time." msgstr "" #, python-format msgid "" "Virtual machine '%(vm)s' must be stopped before creating a snapshot of it." msgstr "" "A máquina virtual '%(vm)s' deve estar parada antes de criar um snapshot dela" #, python-format msgid "" "Unable to create snapshot '%(name)s' on virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" "Não foi possível criar o snapshot '%(name)s' na máquina virtual '%(vm)s'. " "Detalhes: %(err)s" #, python-format msgid "Snapshot '%(name)s' does not exist on virtual machine '%(vm)s'." msgstr "O snapshot '%(name)s' não existe na máquina virtual '%(vm)s'." #, python-format msgid "" "Unable to retrieve snapshot '%(name)s' on virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" "Não foi possível recuperar o snapshot '%(name)s' da máquina virtual " "'%(vm)s'. Detalhes: %(err)s" #, python-format msgid "Unable to list snapshots on virtual machine '%(vm)s'. Details: %(err)s" msgstr "" "Não foi possível listar os snapshots da máquina virtual '%(vm)s'. Detalhes: " "%(err)s" #, python-format msgid "" "Unable to delete snapshot '%(name)s' on virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" "Não foi possível remover o snapshot '%(name)s' da máquina virtual '%(vm)s'. " "Detalhes: %(err)s" #, python-format msgid "" "Unable to retrieve current snapshot of virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" "Não foi possível recuperar o snapshot atual da máquina virtual '%(vm)s'. " "Detalhes: %(err)s." #, python-format msgid "" "Unable to revert virtual machine '%(vm)s' to snapshot '%(name)s'. Details: " "%(err)s" msgstr "" "Não foi possível reverter a máquina virtual '%(vm)s' para o snapshot " "'%(name)s'. Detalhes: %(err)s" #, python-format msgid "" "Unable to create snapshot of virtual machine '%(vm)s' because it contains a " "disk with format '%(format)s'; only 'qcow2' is supported." msgstr "" "Não foi possível criar o snapshot para a máquina virtual '%(vm)s' porque ela " "contém discos no formato '%(format)s'; somente 'qcow2' é suportado." msgid "The number of vCPUs is too large for this system." msgstr "O número de VCPUs é grande demais para esse sistema." msgid "Invalid vCPU/topology combination." msgstr "Combinação inválida de VCPU/topologia." msgid "This host (or current configuration) does not allow CPU topology." msgstr "Este host (ou configuração atual) não permite topologia de CPU." msgid "ERROR CODE" msgstr "CÓDIGO DE ERRO" msgid "REASON" msgstr "MOTIVO" msgid "STACK" msgstr "PILHA" msgid "Go to Homepage" msgstr "Ir para a Página Inicial" msgid "Create a New Virtual Machine" msgstr "Criar nova Máquina Virtual" msgid "Virtual Machine Name" msgstr "Nome da Máquina Virtual" msgid "" "The name used to identify the virtual machine. If omitted, a name will be " "chosen based on the template used." msgstr "" "O nome usado para identificar a máquina virtual. Se ele for omitido, a " "escolha será baseada no modelo selecionado." msgid "Template" msgstr "Modelo" msgid "Please create a template first." msgstr "Por favor, crie um modelo primeiro." msgid "Create a Template" msgstr "Criar um Modelo" msgid "Please choose a template." msgstr "Por favor, escolha um modelo." msgid "OS" msgstr "Sistema Operacional" msgid "OS Version" msgstr "Versão do Sistema Speracional" msgid "CPUS" msgstr "CPUS" msgid "Memory" msgstr "Memória" msgid "Create" msgstr "Criar" msgid "Creating..." msgstr "Criando..." msgid "Edit Guest" msgstr "Editar Guest" msgid "General" msgstr "Geral" msgid "Storage" msgstr "Storage" msgid "Interface" msgstr "Interface" msgid "Permission" msgstr "Permissão" msgid "Host PCI Device" msgstr "Dispositivo de host PCI" msgid "Snapshot" msgstr "Snapshot" msgid "Name" msgstr "Nome" msgid "CPUs" msgstr "CPUs" msgid "Memory (MB)" msgstr "Memória (MB)" msgid "Icon" msgstr "Ãcone" msgid "Device" msgstr "Dispositivo" msgid "Path" msgstr "Caminho" msgid "Network" msgstr "Rede" msgid "Type" msgstr "Tipo" msgid "MAC Address" msgstr "" msgid "Available system users and groups" msgstr "Usuários e grupos de sistema disponíveis" msgid "Selected system users and groups" msgstr "Usuários e grupos de sistema selecionados" msgid "User" msgstr "Usuário" msgid "All" msgstr "Todos" msgid "To Add" msgstr "Para adicionar" msgid "Added" msgstr "Adicionado" msgid "filter" msgstr "filtro" msgid "Product" msgstr "Produto" msgid "Vendor" msgstr "Vendor" msgid "Created" msgstr "Criado" msgid "Save" msgstr "Salvar" msgid "Replace" msgstr "Substituir" msgid "Detach" msgstr "Remover" msgid "Cancel" msgstr "Cancelar" msgid "revert" msgstr "Reverter" msgid "Add a Storage Device to VM" msgstr "Adicionar um dispositivo de storage à VM" msgid "Device Type" msgstr "Tipo do Dispositivo" msgid "The device type. Currently, \"cdrom\" and \"disk\" are supported." msgstr "" "O tipo do dispositivo. Atualmente, \"cdrom\" e \"disco\" são suportados." msgid "Storage Pool" msgstr "Storage Pool" msgid "Storage pool which volume located in" msgstr "Storage pool no qual o volume está localizado" msgid "Storage Volume" msgstr "Volume de storage" msgid "Storage volume to be attached" msgstr "Volume de storage a ser adicionado" msgid "File Path" msgstr "Caminho do Arquivo" msgid "The ISO file path in the server for CDROM." msgstr "O caminho do arquivo ISO para o CDROM no servidor." msgid "Attach" msgstr "Adicionar" msgid "Start" msgstr "Iniciar" msgid "Reset" msgstr "Reiniciar" msgid "Pause" msgstr "" msgid "Resume" msgstr "" msgid "Power Off" msgstr "Forçar desligamento" msgid "Actions" msgstr "Ações" msgid "Connect" msgstr "Conectar" msgid "Clone" msgstr "Clonar" msgid "Edit" msgstr "Editar" msgid "Shut Down" msgstr "Desligar" msgid "Delete" msgstr "Remover" msgid "The username or password you entered is incorrect. Please try again." msgstr "" "O usuário ou senha inseridos estão incorretos. Por favor, tente novamente." msgid "This field is required." msgstr "Esse campo é obrigatório." msgid "Log in" msgstr "Entrar" msgid "Logging in..." msgstr "Entrando..." msgid "Host" msgstr "Host" msgid "Guests" msgstr "Guests" msgid "Templates" msgstr "Modelos" msgid "Failed to get application configuration" msgstr "Não foi possível carregar as configurações da aplicação" msgid "This is not a valid Linux path" msgstr "Este não é um caminho válido no Linux" msgid "This is not a valid URL." msgstr "Essa não é uma URL válida." msgid "No such data available." msgstr "Não há dados disponíveis." msgid "" "Can not contact the host system. Verify the host system is up and that you " "have network connectivity to it. HTTP request response %1. " msgstr "" "Não foi possível contactar o sistema host. Verique se o sistema do host está " "ligado e se você possui conectividade de rede com ele. Resposta da " "requisição HTTP %1. " msgid "Unable to read file." msgstr "" msgid "Error while uploading file." msgstr "" msgid "Delete Confirmation" msgstr "Confirmação de remoção" msgid "OK" msgstr "OK" msgid "Confirm" msgstr "Confirmar" msgid "Warning" msgstr "Aviso" msgid "Cloning..." msgstr "" msgid "Loading..." msgstr "Carregando..." msgid "An error occurred while retrieving system information." msgstr "Ocorreu um erro ao recuperar informações do sistema." msgid "Retry" msgstr "Tentar novamente" msgid "Detailed message:" msgstr "Mensagem detalhada:" msgid "No ISO found" msgstr "Nenhuma ISO encontrada" msgid "This is not a valid ISO file." msgstr "Esse não é um arquivo ISO válido." msgid "This may take a long time. Do you want to continue?" msgstr "Isso vai levar um longo tempo. Deseja continuar?" msgid "This will permanently delete the template. Would you like to continue?" msgstr "O modelo vai ser permanentemente removido. Deseja continuar?" msgid "Unable to shut down system as there are some virtual machines running!" msgstr "" "Não foi possível desligar o sistema porque algumas máquinas virtuais estão " "ligadas!" msgid "Max:" msgstr "Máximo:" msgid "Utilization" msgstr "Utilização" msgid "Available" msgstr "Disponível" msgid "Read Rate" msgstr "Taxa de leitura" msgid "Write Rate" msgstr "Taxa de escrita" msgid "Received" msgstr "Recebido" msgid "Sent" msgstr "Enviado" msgid "" "Shutting down or restarting host will cause unsaved work lost. Continue to " "shut down/restarting?" msgstr "" "Desligar ou reiniciar o host causará perda de trabalho que não foi salvo. " "Continuar o processo de desligar/reiniciar?" msgid "" "Repository will be removed permanently and can't be recovered. Do you want " "to continue?" msgstr "" "Repositório será removido permanentemente e não poderá ser recuperado. " "Deseja continuar?" msgid "Repositories" msgstr "Repositórios" msgid "ID" msgstr "ID" msgid "Base URL" msgstr "URL Base" msgid "Is Mirror" msgstr "É mirror" msgid "URL Args" msgstr "Argumentos da URL" msgid "Enabled" msgstr "Ativado" msgid "GPG Check" msgstr "Verificação GPG" msgid "GPG Key" msgstr "Chave GPG" msgid "Add" msgstr "Adicionar" msgid "Remove" msgstr "Remover" msgid "Enable" msgstr "Ativar" msgid "Disable" msgstr "Desativar" msgid "Software Updates" msgstr "Atualizações de software" msgid "Package Name" msgstr "Nome do pacote" msgid "Version" msgstr "Versão" msgid "Architecture" msgstr "Arquitetura" msgid "Repository" msgstr "Repositório" msgid "Update All" msgstr "Atualizar todos" msgid "Updating..." msgstr "Atualizando..." msgid "Failed to retrieve packages update information." msgstr "Não foi possível recuperar as informações de atualização de pacoates." msgid "Failed to update package(s)." msgstr "Erro ao atualizar pacote(s)." msgid "" "Debug report will be removed permanently and can't be recovered. Do you want " "to continue?" msgstr "" "Relatório de debug será permanentemente removido e não poderá ser " "recuperado. Deseja continuar?" msgid "Debug Reports" msgstr "Relatórios de Debug" msgid "Generated Time" msgstr "Tempo gerado" msgid "Generate" msgstr "Gerar" msgid "Generating..." msgstr "Gerando..." msgid "Rename" msgstr "Renomear" msgid "Download" msgstr "Baixar" msgid "" "Report name should contain only letters, digits, underscore ('_') and/or " "hyphen ('-')." msgstr "" "Nome do relatório deve apenas conter letras, números, underscore ('_') e/ou " "hífen ('-')." msgid "Pending..." msgstr "Pendente..." msgid "Report name is the same as the original one." msgstr "Nome do relatório é o mesmo que o original." msgid "" "This will delete the virtual machine and its virtual disks. This operation " "cannot be undone. Would you like to continue?" msgstr "" "A máquina virtual vai ser removida com todos seus discos. Essa operação é " "irreversível. Deseja continuar?" msgid "Power off Confirmation" msgstr "Confirmação de desligamento forçado" msgid "" "This action may produce undesirable results, for example unflushed disk " "cache in the guest. Would you like to continue?" msgstr "" "Essa ação pode produzir resultados não desejáveis, como por exemplo cache de " "disco não-atualizado no guest. Deseja continuar?" msgid "Reset Confirmation" msgstr "Confirmação de reinicialização" msgid "" "There is a risk of data loss caused by reset without the guest OS shutdown. " "Would you like to continue?" msgstr "" "Existe um risco de perda de dados causado pela reinicialização sem o " "desligamento do sistema operacional do guest. Deseja continuar?" msgid "Shut Down Confirmation" msgstr "Confirmação de desligamento" msgid "Note the guest OS may ignore this request. Would you like to continue?" msgstr "" "O sistema operacional do guest pode ignorar essa requisição. Deseja " "continuar?" msgid "Virtual Machine delete Confirmation" msgstr "Confirmação de Remoção da Máquina Virtual" msgid "" "This virtual machine is not persistent. Power Off will delete it. Continue?" msgstr "" "Essa máquina virtual não é persistente. O desligamento irá removê-la. Deseja " "continuar?" msgid "" "When the target guest has SCSI or iSCSI volumes, they will be cloned on " "default storage pool. The same will happen when the target pool does not " "have enough space to clone the volumes. Do you want to continue?" msgstr "" "Quando o guest de destino tiver volumes SCSI ou iSCSI, eles serão clonados " "no storage pool padrão. O mesmo vai acontecer quando o pool de destino não " "tiver espaço suficiente para clonar os volumes. Você deseja continuar?" msgid "" "This CDROM will be detached permanently and you can re-attach it. Continue " "to detach it?" msgstr "" "Esse CDROM será desconectado permanentemente e você pode reconectá-lo. " "Deseja continuar a remoção? " msgid "Attaching..." msgstr "Adicionando..." msgid "Replacing..." msgstr "Substituindo..." msgid "Successfully attached!" msgstr "Adicionado com sucesso!" msgid "Successfully replaced!" msgstr "Substituído com sucesso!" msgid "Successfully detached!" msgstr "Removido com sucesso!" msgid "" "This disk will be detached permanently and you can re-attach it. Continue to " "detach it?" msgstr "" "Esse disco será desconectado permanentemente e você pode reconectá-lo. " "Deseja continuar a remoção? " msgid "interface:" msgstr "interface:" msgid "address:" msgstr "endereço:" msgid "link_type:" msgstr "tipo do link:" msgid "block:" msgstr "bloco:" msgid "drive_type:" msgstr "tipo do drive:" msgid "model:" msgstr "modelo:" msgid "Affected devices:" msgstr "Dispositivos afetados:" msgid "The VLAN id must be between 1 and 4094." msgstr "ID da VLAN deve ser um número entre 1 e 4094." msgid "unavailable" msgstr "indisponível" msgid "" "This action will interrupt network connectivity for any virtual machine that " "depend on this network." msgstr "" "Esta ação irá interromper a conectividade da rede para qualquer máquina " "virtual que depende dessa rede." msgid "Create a network" msgstr "Criar uma rede" msgid "" "This network is not persistent. Instead of stop, this action will " "permanently delete it. Would you like to continue?" msgstr "" "Essa rede não é persistente. Ao invés de parar, essa ação irá removê-la " "permantemente. Deseja continuar?" msgid "" "The bridged VLAN tag may not work well with NetworkManager enabled. You " "should consider disabling it." msgstr "" msgid "" "This will permanently delete the storage pool. Would you like to continue?" msgstr "O storage pool vai ser permanentemente removido. Deseja continuar?" msgid "This storage pool is empty." msgstr "Esse storage pool está vazio." msgid "" "It will format your disk and you will loose any data in there, are you sure " "to continue? " msgstr "" "Isso formatará seu disco e você perderá toda informação, você tem certeza " "que quer continuar?" msgid "SCSI Fibre Channel" msgstr "SCSI Fibre Channel" msgid "No SCSI adapters found." msgstr "Nenhum adaptador SCSI encontrado." msgid "Loading iSCSI targets..." msgstr "Carregando iSCSI targets..." msgid "No iSCSI found. Please input one." msgstr "Nenhum iSCSI encontrado. Por favor, forneça um." msgid "Failed to load iSCSI targets." msgstr "Erro ao carregar iSCSI targets." msgid "The storage pool name can not be blank." msgstr "O nome do storage pool não pode ser vazio." msgid "The storage pool path can not be blank." msgstr "O caminho do storage pool não pode ser vazio." msgid "NFS server mount path can not be blank." msgstr "Caminho de montagem do servidor de NFS não pode ser vazio." msgid "Invalid NFS mount path." msgstr "Caminho de montagem do NFS inválido." msgid "No logical device selected." msgstr "Nenhum dispositivo lógico selecionado." msgid "The iSCSI target can not be blank." msgstr "O alvo iSCSI não pode ser vazio." msgid "Server name can not be blank." msgstr "Nome do servidor não pode ser vazio." msgid "This is not a valid Server Name or IP. Please, modify it." msgstr "Este não é um nome ou IP de servidor válido. Por favor, modifique-o." msgid "Looking for available partitions ..." msgstr "Procurando por partições disponíveis ..." msgid "No available partitions found." msgstr "Nenhuma partição disponível encontrada." msgid "" "This storage pool is not persistent. Instead of deactivate, this action will " "permanently delete it. Would you like to continue?" msgstr "" "O storage pool não é persistente. Ao invés de desativar, essa ação vai " "removê-lo permanentemente. Deseja continuar?" msgid "Unable to retrieve partitions information." msgstr "Não foi possível recuperar as informações das partições." msgid "In progress..." msgstr "Em progresso..." msgid "Failed!" msgstr "Falhou!" msgid "CDROM path needs to be a valid local/remote path and cannot be blank." msgstr "" "Caminho do CDROM precisa ser um caminho local válido e não pode ser vazio." msgid "Disk pool or volume cannot be blank." msgstr "Pool ou volume do disco não pode ser vazio." msgid "Peers" msgstr "Peers" msgid "Searching" msgstr "Procurando" msgid "No peers found." msgstr "Nenhum peer encontrado." msgid "Help" msgstr "Ajuda" msgid "About" msgstr "Sobre" msgid "Log out" msgstr "Sair" msgid "Version:" msgstr "Versão:" msgid "Session timeout, please re-login." msgstr "Fim do limite do tempo da sessão, por favor se autentique novamente." msgid "User Name" msgstr "Usuário" msgid "Password" msgstr "Senha" msgid "Generate a New Debug Report" msgstr "Gerar um novo Relatório de Debug" msgid "Report Name" msgstr "Nome do Relatório" msgid "" "The name used to identify the report. If omitted, a name will be chosen " "based on current time. Name can contain: letters, digits, underscore (\"_\") " "and hyphen (\"-\")." msgstr "" "O nome usado para identificar o relatório. Se omitido, um nome será " "escolhido baseado no horário atual. O nome pode conter: letras, números, " "underscore ('_') e hífen ('-')." msgid "Rename a Debug Report" msgstr "Renomear um Relatório de Debug" msgid "" "The name used to identify the report. Name can contain: letters, digits and " "hyphen (\"-\")." msgstr "" "O nome usado para identificar o relatório. O nome pode conter: letras, " "dígitos e hífen (\"-\")." msgid "Submit" msgstr "Enviar" msgid "Add a Repository" msgstr "Adicionar um Repositório" msgid "Identifier" msgstr "Identificador" msgid "Single word, unique identifier for the repository." msgstr "Uma única palavra, identificador único para o repositório." msgid "Textual name for the repository." msgstr "Nome textual para o repositório." msgid "URL" msgstr "URL" msgid "Required Field" msgstr "Campo Obrigatório" msgid "URL to the repository. Supported protocols are http, ftp, and file." msgstr "URL para o repositório. Protocolos suportados são http, ftp e file." msgid "Repository is a mirror" msgstr "Repositório é um mirror" msgid "Distribution" msgstr "Distribuição" msgid "Distribution of the DEB repository." msgstr "Distribuição para o repositório DEB." msgid "Components" msgstr "Componentes" msgid "List of components in DEB repository." msgstr "Lista de componentes para o repositório DEB." msgid "Edit Repository" msgstr "Editar Repositório" msgid "Mirror List URL" msgstr "URL para a lista de mirror" msgid "Yes" msgstr "Sim" msgid "No" msgstr "Não" msgid "Add a Volume to Storage Pool" msgstr "Adicionar um volume ao Storage Pool" msgid "Fetch from remote URL" msgstr "Fazer download de uma URL remota" msgid "Enter the remote URL here." msgstr "Digite a URL remota aqui." msgid "Upload a file" msgstr "Fazer upload de um arquivo" msgid "Choose the file you want to upload." msgstr "Escolha o arquivo que você quer fazer upload." msgid "Define a New Storage Pool" msgstr "Definir novo Storage Pool" msgid "Storage Pool Name" msgstr "Nome do Storage Pool" msgid "" "The name used to identify the storage pools, and it should not be empty." msgstr "O nome usado para identificar o storage pool e não deve ser vazio." msgid "Storage Pool Type" msgstr "Tipo do Storage Pool" msgid "Storage Path" msgstr "Caminho do storage" msgid "" "The path of the Storage Pool. Each Storage Pool must have a unique path." msgstr "" "O caminho do Storage Pool. Cada Storage Pool deve ter um caminho único." msgid "" "Kimchi will try to create the directory when it does not already exist in " "your system." msgstr "" "O Kimchi vai tentar criar o diretório se ainda não existir no seu sistema." msgid "NFS Server IP" msgstr "IP do servidor NFS" msgid "NFS server IP or hostname. It can be input or chosen from history." msgstr "" "IP ou hostname do servidor NFS. Pode ser inserido ou escolhido do histórico." msgid "NFS Path" msgstr "Caminho do NFS" msgid "The NFS exported path on NFS server." msgstr "O caminho exportado do servidor NFS." msgid "Device path" msgstr "Caminho do dispositivo" msgid "iSCSI Server" msgstr "Servidor iSCSI" msgid "iSCSI server IP or hostname. It should not be empty." msgstr "IP ou hostname do servidor iSCSI. Não deve ser vazio." msgid "Server" msgstr "Servidor" msgid "Port" msgstr "Porta" msgid "Target" msgstr "Alvo" msgid "The iSCSI target on iSCSI server" msgstr "O alvo iSCSI no servidor iSCSI" msgid "Add iSCSI Authentication" msgstr "Adicionar as credenciais do iSCSI" msgid "iSCSI Authentication" msgstr "Credenciais do iSCSI" msgid "SCSI Adapter" msgstr "Adaptador SCSI" msgid "Please, wait..." msgstr "Por favor, aguarde..." msgid "Add Template" msgstr "Adicionar Modelo" msgid "Where is the source media for this template? " msgstr "Onde está a mídia de origem desse modelo? " msgid "Local ISO Image" msgstr "Imagem ISO Local" msgid "Local Image File" msgstr "Arquivo de Imagem Local" msgid "Remote ISO Image" msgstr "Imagem ISO Remota" msgid "Search ISOs" msgstr "Procurar ISOs" msgid "The following ISOs are available:" msgstr "As seguintes ISOs estão disponíveis:" msgid "OS: " msgstr "Sistema Operacional: " msgid "Version: " msgstr "Versão: " msgid "Size: " msgstr "Tamanho: " msgid "Search more ISOs" msgstr "Procurar por mais ISOs" msgid "Create Templates from Selected ISO" msgstr "Criar Modelos a partir das ISOs selecionadas" msgid "I want to use a specific ISO file" msgstr "Eu quero usar um arquivo ISO específico" msgid "Loading default remote ISOs ..." msgstr "Carregando ISOs remotas ..." msgid "Arch: " msgstr "Arquitetura: " msgid "I want to use a custom URL" msgstr "Eu quero usar uma URL personalizada" msgid "Edit Template" msgstr "Editar Modelo" msgid "Processor" msgstr "Processador" msgid "CDROM" msgstr "CD-ROM" msgid "Image File" msgstr "Arquivo de imagem" msgid "Graphics" msgstr "Gráficos" msgid "Disk(GB)" msgstr "Disco (GB)" msgid "Disk Format" msgstr "" msgid "CPU Number" msgstr "Quantidade de CPUs" msgid "Manually set CPU topology" msgstr "Configurar manualmente a topologia de CPU" msgid "Cores" msgstr "Cores" msgid "Threads" msgstr "Threads" msgid "CPU" msgstr "CPU" msgid "Disk I/O" msgstr "Disco E/S" msgid "Network I/O" msgstr "Rede E/S" msgid "Livetile" msgstr "Tela ao vivo" msgid "No guests found." msgstr "Nenhum guest encontrado." msgid "Shut down" msgstr "Desligar" msgid "Restart" msgstr "Reiniciar" msgid "Basic Information" msgstr "Informações básicas" msgid "OS Distro" msgstr "Distribuição" msgid "OS Code Name" msgstr "Nome-código do sistema operacional" msgid "CPU(s)" msgstr "CPU(s)" msgid "System Statistics" msgstr "Estatísticas do sistema" msgid "Update Progress" msgstr "Progresso da atualização" msgid "Network Name" msgstr "Nome da rede" msgid "State" msgstr "Estado" msgid "Network Type" msgstr "Tipo da rede" msgid "Address Space" msgstr "Espaço de endereço" msgid "Name should not contain '/' and '\"'." msgstr "O nome não deve conter '/' and '\"'." msgid "Isolated: no external network connection" msgstr "Isolada: nenhuma conexão externa" msgid "NAT: outbound physical network connection only" msgstr "NAT: somente conexão de rede física de saída" msgid "Bridged: Virtual machines are connected to physical network directly" msgstr "" "Bridged: Máquinas virtuais estão conectadas diretamente com a rede física" msgid "(No interfaces found)" msgstr "(Nenhuma interface encontrada)" msgid "Destination" msgstr "Destino" msgid "Enable VLAN" msgstr "Habilitar VLAN" msgid "VLAN ID" msgstr "ID da VLAN" msgid "Stop" msgstr "Parar" msgid "%Used" msgstr "" msgid "Location" msgstr "Localização" msgid "Capacity" msgstr "Capacidade" msgid "Allocated" msgstr "Alocado" msgid "active" msgstr "ativo" msgid "inactive" msgstr "inativo" msgid "Deactivate" msgstr "Desativar" msgid "Activate" msgstr "Ativar" msgid "Add Volume" msgstr "Adicionar volume" msgid "Extend" msgstr "Aumentar" msgid "Undefine" msgstr "Indefinir" msgid "Format" msgstr "Formato" msgid "Allocation" msgstr "Alocação" msgid "No templates found." msgstr "Nenhum modelo encontrado." kimchi-1.5.0/po/ru_RU.po000066400000000000000000002056001254252253000147760ustar00rootroot00000000000000# English translations for kimchi package. # Copyright (C) 2013 ORGANIZATION # msgid "" msgstr "" "Project-Id-Version: kimchi 0.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-06-24 09:39-0300\n" "PO-Revision-Date: 2014-08-28 17:32+0000\n" "Last-Translator: Aline Manera \n" "Language-Team: Russian (http://www.transifex.com/projects/p/kimchi/language/" "ru/)\n" "Language: ru_RU\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: pygettext.py 1.5\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #, python-format msgid "Unknown parameter %(value)s" msgstr "" #, python-format msgid "Delete is not allowed for %(resource)s" msgstr "Удаление запрещено Ð´Ð»Ñ %(resource)s" #, python-format msgid "%(resource)s does not implement update method" msgstr "%(resource)s не реализуют метод обновлениÑ" #, python-format msgid "Create is not allowed for %(resource)s" msgstr "Создание запрещено Ð´Ð»Ñ %(resource)s" msgid "Unable to parse JSON request" msgstr "Ошибка анализа запроÑа JSON" msgid "This API only supports JSON" msgstr "Эта Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ API поддерживает только JSON" #, python-format msgid "Parameters does not match requirement in schema: %(err)s" msgstr "" msgid "You don't have permission to perform this operation." msgstr "" msgid "Datastore is not initiated in the model object." msgstr "Хранилище данных в объекте модели не инициализировано." #, python-format msgid "Unable to start task due error: %(err)s" msgstr "Ðе удалоÑÑŒ запуÑтить задачу из-за ошибки %(err)s" #, python-format msgid "Timeout of %(seconds)s seconds expired while running task '%(task)s." msgstr "" #, python-format msgid "Authentication failed for user '%(username)s'. [Error code: %(code)s]" msgstr "Сбой идентификации Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %(username)s. [Код ошибки: %(code)s]" msgid "You are not authorized to access Kimchi" msgstr "Ðет прав доÑтупа к Kimchi" #, python-format msgid "Specify %(item)s to login into Kimchi" msgstr "Укажите %(item)s Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ð° в Kimchi" #, python-format msgid "User %(user_id)s not found with given LDAP settings." msgstr "" #, python-format msgid "Invalid LDAP configuration: %(item)s : %(value)s" msgstr "" msgid "Unknown \"_cap\" specified" msgstr "" msgid "\"_passthrough\" should be \"true\" or \"false\"" msgstr "" msgid "\"_passthrough_affected_by\" should be a device name string" msgstr "" #, python-format msgid "Error while getting block devices. Details: %(err)s" msgstr "Ошибка Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð±Ð»Ð¾Ñ‡Ð½Ñ‹Ñ… уÑтройÑтв. СведениÑ: %(err)s" #, python-format msgid "Error while getting block device information for %(device)s." msgstr "Ошибка Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ð¸ о блочных уÑтройÑтвах Ð´Ð»Ñ %(device)s." #, python-format msgid "Unable to find distro file: %(filename)s" msgstr "Ðе найден файл варианта ОС: %(filename)s" #, python-format msgid "" "Unable to parse distro file: %(filename)s. Make sure, it is a JSON file." msgstr "" "Ошибка анализа файла варианта ОС %(filename)s. УбедитеÑÑŒ, что Ñто файл JSON." #, python-format msgid "Unable to login to iSCSI host target %(portal)s. Details: %(err)s" msgstr "Ðе удалоÑÑŒ войти в целевой %(portal)s хоÑта iSCSI. СведениÑ: %(err)s" #, python-format msgid "Unable to login to iSCSI host %(host)s target %(target)s" msgstr "Ðе удалоÑÑŒ войти в целевой %(target)s хоÑта iSCSI %(host)s" #, python-format msgid "Unable to find ISO file %(filename)s" msgstr "" #, python-format msgid "The ISO file %(filename)s is not bootable" msgstr "Файл ISO %(filename)s не загрузочный" #, python-format msgid "The ISO file %(filename)s does not have a valid El Torito boot record" msgstr "" "Файл ISO %(filename)s не Ñодержит правильную загрузочную запиÑÑŒ El Torito" #, python-format msgid "Invalid El Torito validation entry in ISO %(filename)s" msgstr "ÐедопуÑÑ‚Ð¸Ð¼Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ проверки El Torito в образе ISO %(filename)s" #, python-format msgid "Invalid El Torito boot indicator in ISO %(filename)s" msgstr "ÐедопуÑтимый индикатор загрузки El Torito в образе ISO %(filename)s" #, python-format msgid "Unexpected volume type for primary volume in ISO %(filename)s" msgstr "Ðеожиданный тип тома Ð´Ð»Ñ Ð³Ð»Ð°Ð²Ð½Ð¾Ð³Ð¾ тома в образе ISO %(filename)s" #, python-format msgid "Bad format while reading volume descriptor in ISO %(filename)s" msgstr "Ðеверный формат деÑкриптора тома в образе ISO %(filename)s" #, python-format msgid "" "The hypervisor doesn't have permission to use this ISO %(filename)s. " "Consider moving it under /var/lib/libvirt, or set the search permission to " "file access control lists for '%(user)s' user if possible, or add the " "'%(user)s' to the ISO path group, or (not recommended) 'chmod -R o+x " "'path_to_iso'.Details: %(err)s" msgstr "" "У гипервизора нет прав доÑтупа Ð´Ð»Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ñтого образа ISO " "%(filename)s. ПеремеÑтите его в каталог /var/lib/libvirt, добавьте " "разрешение на поиÑк в ÑпиÑки ÐºÐ¾Ð½Ñ‚Ñ€Ð¾Ð»Ñ Ð´Ð¾Ñтупа Ð´Ð»Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %(user)s, " "еÑли Ñто возможно, добавьте %(user)s в группу пути к образу ISO или (не " "рекомендуетÑÑ) выполните команду 'chmod -R o+x 'path_to_iso'. СведениÑ: " "%(err)s" msgid "An error occurred when probing image OS information." msgstr "" msgid "No OS information found in given image." msgstr "" #, python-format msgid "Unable to read image file %(filename)s" msgstr "" #, python-format msgid "" "Image file must be an existing file on system. %(filename)s is not a valid " "input." msgstr "" #, python-format msgid "Virtual machine %(name)s already exists" msgstr "Ð’Ð¸Ñ€Ñ‚ÑƒÐ°Ð»ÑŒÐ½Ð°Ñ Ð¼Ð°ÑˆÐ¸Ð½Ð° %(name)s уже ÑущеÑтвует" #, python-format msgid "Virtual machine %(name)s does not exist" msgstr "Ð’Ð¸Ñ€Ñ‚ÑƒÐ°Ð»ÑŒÐ½Ð°Ñ Ð¼Ð°ÑˆÐ¸Ð½Ð° %(name)s не ÑущеÑтвует" #, python-format msgid "" "Unable to rename virtual machine %(name)s. The name %(new_name)s is already " "in use or the virtual machine is not powered off." msgstr "" #, python-format msgid "Unable to retrieve screenshot for stopped virtual machine %(name)s" msgstr "" "Ðе удалоÑÑŒ получить Ñнимок Ñкрана Ð´Ð»Ñ Ð¾Ñтановленной виртуальной машины " "%(name)s" msgid "Remote ISO image is not supported by this server." msgstr "Удаленный образ ISO не поддерживаетÑÑ Ñтим Ñервером." #, python-format msgid "Screenshot is not supported on virtual machine %(name)s" msgstr "" #, python-format msgid "Unable to create virtual machine %(name)s. Details: %(err)s" msgstr "Ðе удалоÑÑŒ Ñоздать виртуальную машину %(name)s. СведениÑ: %(err)s" #, python-format msgid "Unable to update virtual machine %(name)s. Details: %(err)s" msgstr "Ðе удалоÑÑŒ Ñоздать виртуальную машину %(name)s. СведениÑ: %(err)s" #, python-format msgid "Unable to retrieve virtual machine %(name)s. Details: %(err)s" msgstr "Ðе удалоÑÑŒ получить виртуальную машину %(name)s. СведениÑ: %(err)s" #, python-format msgid "Unable to connect to powered off virtual machine %(name)s." msgstr "" msgid "Virtual machine name must be a string without slashes (/)" msgstr "" #, python-format msgid "Invalid template URI %(value)s specified for virtual machine" msgstr "" #, python-format msgid "Invalid storage pool URI %(value)s specified for virtual machine" msgstr "" msgid "Supported virtual machine graphics are Spice or VNC" msgstr "" msgid "Graphics address to listen on must be IPv4 or IPv6" msgstr "" "ÐÐ´Ñ€ÐµÑ Ð¿Ñ€Ð¸ÐµÐ¼Ð° запроÑов Ð´Ð»Ñ Ð³Ñ€Ð°Ñ„Ð¸Ñ‡ÐµÑкой подÑиÑтемы должен быть IPv4 или IPv6" msgid "Specify a template to create a virtual machine from" msgstr "Укажите шаблон Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð²Ð¸Ñ€Ñ‚ÑƒÐ°Ð»ÑŒÐ½Ð¾Ð¹ машины" #, python-format msgid "Unable to start virtual machine %(name)s. Details: %(err)s" msgstr "Ðе удалоÑÑŒ запуÑтить виртуальную машину %(name)s. СведениÑ: %(err)s" #, python-format msgid "Unable to power off virtual machine %(name)s. Details: %(err)s" msgstr "Ðе удалоÑÑŒ оÑтановить виртуальную машину %(name)s. СведениÑ: %(err)s" #, python-format msgid "Unable to delete virtual machine %(name)s. Details: %(err)s" msgstr "Ðе удалоÑÑŒ удалить виртуальную машину %(name)s. СведениÑ: %(err)s" #, python-format msgid "Unable to reset virtual machine %(name)s. Details: %(err)s" msgstr "" "Ðе удалоÑÑŒ переименовать виртуальную машину %(name)s. СведениÑ: %(err)s" msgid "User name list must be an array" msgstr "" msgid "User name must be a string" msgstr "Ð˜Ð¼Ñ Ñети должно быть Ñтрокой" msgid "Group name list must be an array" msgstr "" msgid "Group name must be a string" msgstr "Ð˜Ð¼Ñ Ñети должно быть Ñтрокой" #, python-format msgid "User(s) '%(users)s' do not exist" msgstr "Пользователь %(users)s не ÑущеÑтвует." #, python-format msgid "Group(s) '%(groups)s' do not exist" msgstr "Пользователь %(groups)s не ÑущеÑтвует." #, python-format msgid "Unable to shutdown virtual machine %(name)s. Details: %(err)s" msgstr "Ðе удалоÑÑŒ оÑтановить виртуальную машину %(name)s. СведениÑ: %(err)s" #, python-format msgid "" "Unable to get access metadata of virtual machine %(name)s. Details: %(err)s" msgstr "Ðе удалоÑÑŒ запуÑтить виртуальную машину %(name)s. СведениÑ: %(err)s" msgid "The guest console password must be a string." msgstr "" msgid "The life time for the guest console password must be a number." msgstr "" #, python-format msgid "Virtual machine '%(name)s' must be stopped before cloning it." msgstr "" #, python-format msgid "Insufficient disk space to clone virtual machine '%(name)s'" msgstr "" #, python-format msgid "Unable to clone VM '%(name)s'. Details: %(err)s" msgstr "" #, python-format msgid "Invalid operation for non-persistent virtual machine %(name)s" msgstr "" #, python-format msgid "Cannot suspend VM '%(name)s' because it is not running." msgstr "" #, python-format msgid "Unable to suspend VM '%(name)s'. Details: %(err)s" msgstr "" #, python-format msgid "Cannot resume VM '%(name)s' because it is not paused." msgstr "" #, python-format msgid "Unable to resume VM '%(name)s'. Details: %(err)s" msgstr "" msgid "Memory assigned is higher then the maximum allowed in the host." msgstr "" #, python-format msgid "" "VM '%(name)s' does not support live memory update. Update the memory with " "the machine offline to enable this feature." msgstr "" msgid "Only increase memory is allowed in active VMs" msgstr "" msgid "" "For live memory update, new memory value must be equal old memory value plus " "multiples of 1024 Mib" msgstr "" msgid "There are not enough free slots of 1024 Mib in the guest." msgstr "" msgid "" "Host's libvirt version does not support memory devices. Libvirt must be >= " "1.2.14" msgstr "" #, python-format msgid "Error attaching memory device. Details: %(error)s" msgstr "" #, python-format msgid "" "VM %(vmid)s does not contain directly assigned host device %(dev_name)s." msgstr "" #, python-format msgid "The host device %(dev_name)s is not allowed to directly assign to VM." msgstr "" msgid "" "No IOMMU groups found. Host PCI pass through needs IOMMU group to function " "correctly. Please enable Intel VT-d or AMD IOMMU in your BIOS, then verify " "the Kernel is compiled with IOMMU support. For Intel CPU, add intel_iommu=on " "to your Kernel parameter in /boot/grub2/grub.conf. For AMD CPU, add iommu=pt " "iommu=1." msgstr "" msgid "\"name\" should be a device name string" msgstr "" #, python-format msgid "" "The device %(name)s is probably in use by the host. Unable to attach it to " "the guest." msgstr "" #, python-format msgid "Interface %(iface)s does not exist in virtual machine %(name)s" msgstr "Ð˜Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ %(iface)s не ÑущеÑтвует в виртуальной машине %(name)s" #, python-format msgid "" "Network %(network)s specified for virtual machine %(name)s does not exist" msgstr "" "Сеть %(network)s, ÑƒÐºÐ°Ð·Ð°Ð½Ð½Ð°Ñ Ð´Ð»Ñ Ð²Ð¸Ñ€Ñ‚ÑƒÐ°Ð»ÑŒÐ½Ð¾Ð¹ машины %(name)s, не ÑущеÑтвует" msgid "Supported virtual machine interfaces type is only network" msgstr "ПоддерживаетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ один тип интерфейÑов виртуальной машины - Ñеть" msgid "Network name for virtual machine interface must be a string" msgstr "Ð˜Ð¼Ñ Ñети Ð´Ð»Ñ Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñа виртуальной машины должно быть Ñтрокой" msgid "Invalid network model card specified for virtual machine interface" msgstr "" "Указана недопуÑÑ‚Ð¸Ð¼Ð°Ñ ÐºÐ°Ñ€Ñ‚Ð° модели Ñети Ð´Ð»Ñ Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñа виртуальной машины" msgid "Specify type and network to add a new virtual machine interface" msgstr "Укажите тип и Ñеть Ð´Ð»Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ интерфейÑа виртуальной машины" msgid "MAC Address must respect this format FF:FF:FF:FF:FF:FF" msgstr "" #, python-format msgid "MAC Address %(mac)s already exists in virtual machine %(name)s" msgstr "" msgid "Invalid MAC Address" msgstr "" msgid "Cannot change MAC address of a running virtual machine" msgstr "" #, python-format msgid "Template %(name)s already exists" msgstr "Шаблон %(name)s уже ÑущеÑтвует" #, python-format msgid "" "Network '%(network)s' specified for template %(template)s does not exist" msgstr "Сеть %(network)s, ÑƒÐºÐ°Ð·Ð°Ð½Ð½Ð°Ñ Ð´Ð»Ñ ÑˆÐ°Ð±Ð»Ð¾Ð½Ð° %(template)s, не ÑущеÑтвует" #, python-format msgid "" "Storage pool %(pool)s specified for template %(template)s does not exist" msgstr "Пул памÑти %(pool)s, указанный Ð´Ð»Ñ ÑˆÐ°Ð±Ð»Ð¾Ð½Ð° %(template)s, не ÑущеÑтвует" #, python-format msgid "Storage pool %(pool)s specified for template %(template)s is not active" msgstr "Пул памÑти %(pool)s, указанный Ð´Ð»Ñ ÑˆÐ°Ð±Ð»Ð¾Ð½Ð° %(template)s, не активен" #, python-format msgid "Invalid parameter '%(param)s' specified for CDROM." msgstr "Указан недопуÑтимый параметр %(param)s Ð´Ð»Ñ CDROM." #, python-format msgid "Network %(network)s specified for template %(template)s is not active" msgstr "Сеть %(network)s, ÑƒÐºÐ°Ð·Ð°Ð½Ð½Ð°Ñ Ð´Ð»Ñ ÑˆÐ°Ð±Ð»Ð¾Ð½Ð° %(template)s, не активна" msgid "Template name must be a string" msgstr "Ð˜Ð¼Ñ ÑˆÐ°Ð±Ð»Ð¾Ð½Ð° должно быть Ñтрокой" msgid "Template icon must be a path to the image" msgstr "Значок шаблона должен быть путем к образу" msgid "Template distribution must be a string" msgstr "Вариант шаблона должен быть Ñтрокой" msgid "Template distribution version must be a string" msgstr "ВерÑÐ¸Ñ Ð²Ð°Ñ€Ð¸Ð°Ð½Ñ‚Ð° шаблона должна быть Ñтрокой" msgid "The number of CPUs must be an integer greater than 0" msgstr "ЧиÑло процеÑÑоров должно быть целым чиÑлом" msgid "Amount of memory (MB) must be an integer greater than 512" msgstr "Объем памÑти (МБ) должен быть целым чиÑлом больше 512" msgid "Template CDROM must be a local or remote ISO file" msgstr "CDROM шаблона должен быть локальным или удаленным файлом ISO" #, python-format msgid "Invalid storage pool URI %(value)s specified for template" msgstr "Ð”Ð»Ñ ÑˆÐ°Ð±Ð»Ð¾Ð½Ð° указан недопуÑтимый URI пула памÑти %(value)s" msgid "Specify an ISO image as CDROM or a base image to create a template" msgstr "Укажите образ ISO в качеÑтве CDROM Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ ÑˆÐ°Ð±Ð»Ð¾Ð½Ð°" msgid "All networks for the template must be specified in a list." msgstr "Ð’Ñе Ñети Ð´Ð»Ñ ÑˆÐ°Ð±Ð»Ð¾Ð½Ð° должны быть указаны в ÑпиÑке." msgid "Specify a volume to a template when storage pool is iSCSI or SCSI" msgstr "" #, python-format msgid "The volume %(volume)s is not in storage pool %(pool)s" msgstr "" #, python-format msgid "Unable to create template due error: %(err)s" msgstr "Ðе удалоÑÑŒ Ñоздать шаблон из-за ошибки %(err)s" #, python-format msgid "Unable to delete template due error: %(err)s" msgstr "Ðе удалоÑÑŒ удалить шаблон из-за ошибки %(err)s" msgid "Disk size must be an integer greater than 1GB." msgstr "" msgid "Template base image must be a valid local image file" msgstr "CDROM шаблона должен быть локальным или удаленным файлом ISO" #, python-format msgid "Cannot identify base image %(path)s format" msgstr "" msgid "" "When specifying CPU topology, VCPUs must be a product of sockets, cores, and " "threads." msgstr "" msgid "" "When specifying CPU topology, each element must be an integer greater than " "zero." msgstr "" msgid "" "Invalid disk image format. Valid formats: bochs, cloop, cow, dmg, qcow, " "qcow2, qed, raw, vmdk, vpc." msgstr "" #, python-format msgid "Storage pool %(name)s already exists" msgstr "Пул памÑти %(name)s уже ÑущеÑтвует" #, python-format msgid "Storage pool %(name)s does not exist" msgstr "Пул памÑти %(name)s не ÑущеÑтвует" #, python-format msgid "Specify %(item)s in order to create the storage pool %(name)s" msgstr "Укажите %(item)s Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¿ÑƒÐ»Ð° памÑти %(name)s" #, python-format msgid "Unable to delete active storage pool %(name)s" msgstr "Ðе удалоÑÑŒ удалить активный пул памÑти %(name)s" #, python-format msgid "Unable to list storage pools. Details: %(err)s" msgstr "Ðе удалоÑÑŒ вывеÑти ÑпиÑок пулов памÑти. СведениÑ: %(err)s" #, python-format msgid "Unable to create storage pool %(name)s. Details: %(err)s" msgstr "Ðе удалоÑÑŒ Ñоздать пул памÑти %(name)s. СведениÑ: %(err)s" #, python-format msgid "" "Unable to get number of storage volumes in storage pool %(name)s. Details: " "%(err)s" msgstr "" "Ðе удалоÑÑŒ получить чиÑло томов в пуле памÑти %(name)s. СведениÑ: %(err)s" #, python-format msgid "Unable to activate storage pool %(name)s. Details: %(err)s" msgstr "Ðе удалоÑÑŒ активировать пул памÑти %(name)s. СведениÑ: %(err)s" #, python-format msgid "Unable to deactivate storage pool %(name)s. Details: %(err)s" msgstr "Ðе удалоÑÑŒ деактивировать пул памÑти %(name)s. СведениÑ: %(err)s" #, python-format msgid "Unable to delete storage pool %(name)s. Details: %(err)s" msgstr "Ðе удалоÑÑŒ удалить пул памÑти %(name)s. СведениÑ: %(err)s" #, python-format msgid "" "Unable to create NFS Pool as export path %(path)s may block during mount" msgstr "" "Ðе удалоÑÑŒ Ñоздать пул NFS: ÑкÑпортированный путь %(path)s мог быть " "заблокирован во Ð²Ñ€ÐµÐ¼Ñ Ð¼Ð¾Ð½Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ" #, python-format msgid "Unable to create NFS Pool as export path %(path)s mount failed" msgstr "" "Ðе удалоÑÑŒ Ñоздать пул NFS: не удалоÑÑŒ Ñмонтировать ÑкÑпортированный путь " "%(path)s" #, python-format msgid "Unsupported storage pool type: %(type)s" msgstr "Ðеподдерживаемый тип пула памÑти: %(type)s" #, python-format msgid "Error while retrieving storage pool XML to %(pool)s" msgstr "" msgid "Storage pool name must be a string without slashes (/)" msgstr "" msgid "" "Supported storage pool types are dir, netfs, logical, iscsi, isci and kimchi-" "iso" msgstr "" msgid "Storage pool path must be a string" msgstr "Путь к пулу памÑти должен быть Ñтрокой" msgid "Storage pool host must be a IP or hostname" msgstr "ХоÑÑ‚ пула памÑти должен быть IP-адреÑом или именем хоÑта" msgid "Storage pool device must be the absolute path to the block device" msgstr "" msgid "Storage pool devices parameter must be a list" msgstr "Параметр уÑтройÑтв пула памÑти должен быть ÑпиÑком" msgid "Target IQN of an iSCSI pool must be a string" msgstr "Целевой IQN пула iSCSI должен быть Ñтрокой" msgid "Port of a remote storage server must be an integer between 1 and 65535" msgstr "Порт удаленного Ñервера памÑти должен быть целым чиÑлом от 1 до 65535" msgid "iSCSI target username must be a string" msgstr "" msgid "iSCSI target password must be a string" msgstr "" msgid "Specify name and type to create a storage pool" msgstr "Укажите Ð¸Ð¼Ñ Ð¸ тип Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¿ÑƒÐ»Ð° памÑти" #, python-format msgid "" "%(disk)s is not a valid disk/partition. Could not add it to the pool " "%(pool)s." msgstr "" "%(disk)s не ÑвлÑетÑÑ Ð´Ð¾Ð¿ÑƒÑтимым диÑком/разделом. Ðе удалоÑÑŒ добавить его в " "пул %(pool)s." #, python-format msgid "Unable to extend logical pool %(pool)s. Details: %(err)s" msgstr "" msgid "The parameter disks only can be updated for logical storage pool." msgstr "ДиÑки параметров можно обновлÑть только Ð´Ð»Ñ Ð»Ð¾Ð³Ð¸Ñ‡ÐµÑкого пула памÑти." msgid "The SCSI host adapter name must be a string." msgstr "Ð˜Ð¼Ñ Ð°Ð´Ð°Ð¿Ñ‚ÐµÑ€Ð° хоÑта SCSI должно быть Ñтрокой." msgid "The storage pool kimchi_isos is reserved for internal use" msgstr "kimchi_isos пула памÑти зарезервирован Ð´Ð»Ñ Ð²Ð½ÑƒÑ‚Ñ€ÐµÐ½Ð½ÐµÐ³Ð¾ иÑпользованиÑ" #, python-format msgid "" "Unable to activate NFS storage pool %(name)s. NFS server %(server)s is " "unreachable." msgstr "" "Ðе удалоÑÑŒ активировать пул памÑти NFS %(name)s. Сервер NFS %(server)s " "недоÑтупен." #, python-format msgid "" "Unable to deactivate NFS storage pool %(name)s. NFS server %(server)s is " "unreachable." msgstr "" "Ðе удалоÑÑŒ деактивировать пул памÑти NFS %(name)s. Сервер NFS %(server)s " "недоÑтупен." #, python-format msgid "" "Unable to deactivate pool %(name)s as it is associated with some templates" msgstr "" "Ðе удалоÑÑŒ деактивировать пул %(name)s: пул ÑвÑзан Ñ Ð½ÐµÐºÐ¾Ñ‚Ð¾Ñ€Ñ‹Ð¼Ð¸ шаблонами" #, python-format msgid "Unable to delete pool %(name)s as it is associated with some templates" msgstr "Ðе удалоÑÑŒ удалить пул %(name)s: пул ÑвÑзан Ñ Ð½ÐµÐºÐ¾Ñ‚Ð¾Ñ€Ñ‹Ð¼Ð¸ шаблонами" #, python-format msgid "" "A volume group named '%(name)s' already exists. Please, choose another name " "to create the logical pool." msgstr "" "Группа томов Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ %(name)s уже ÑущеÑтвует. Выберите другое Ð¸Ð¼Ñ Ð´Ð»Ñ " "ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð»Ð¾Ð³Ð¸Ñ‡ÐµÑкого пула." #, python-format msgid "Unable to update database with deep scan information due error: %(err)s" msgstr "" "Ðе удалоÑÑŒ обновить базу данных Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸ÐµÐ¹ глубокого ÑÐºÐ°Ð½Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¸Ð·-за " "ошибки %(err)s" #, python-format msgid "Storage volume %(name)s already exists" msgstr "Том %(name)s уже ÑущеÑтвует" #, python-format msgid "Storage volume %(name)s does not exist in storage pool %(pool)s" msgstr "Том %(name)s не ÑущеÑтвует в пуле памÑти %(pool)s" #, python-format msgid "" "Unable to create storage volume %(volume)s because storage pool %(pool)s is " "not active" msgstr "" #, python-format msgid "Specify %(item)s in order to create storage volume %(volume)s" msgstr "Укажите %(item)s Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ñ‚Ð¾Ð¼Ð° %(volume)s" #, python-format msgid "" "Unable to list storage volumes because storage pool %(pool)s is not active" msgstr "Ðе удалоÑÑŒ вывеÑти ÑпиÑок томов: пул памÑти %(pool)s не активен" #, python-format msgid "" "Unable to create storage volume %(name)s in storage pool %(pool)s. Details: " "%(err)s" msgstr "" "Ðе удалоÑÑŒ Ñоздать том %(name)s в пуле памÑти %(pool)s. СведениÑ: %(err)s" #, python-format msgid "" "Unable to list storage volumes in storage pool %(pool)s. Details: %(err)s" msgstr "" "Ðе удалоÑÑŒ вывеÑти ÑпиÑок томов в пуле памÑти %(pool)s. СведениÑ: %(err)s" #, python-format msgid "Unable to wipe storage volumes %(name)s. Details: %(err)s" msgstr "Ðе удалоÑÑŒ Ñтереть тома %(name)s. СведениÑ: %(err)s" #, python-format msgid "Unable to delete storage volume %(name)s. Details: %(err)s" msgstr "Ðе удалоÑÑŒ удалить том %(name)s. СведениÑ: %(err)s" #, python-format msgid "Unable to resize storage volume %(name)s. Details: %(err)s" msgstr "Ðе удалоÑÑŒ изменить размер тома %(name)s. СведениÑ: %(err)s" #, python-format msgid "Storage type %(type)s does not support volume create and delete" msgstr "Тип памÑти %(type)s не поддерживает Ñоздание и удаление томов" msgid "Storage volume name must be a string" msgstr "Ð˜Ð¼Ñ Ñ‚Ð¾Ð¼Ð° должно быть Ñтрокой" msgid "Storage volume allocation must be an integer number" msgstr "Выделение тома должно быть целым чиÑлом" msgid "" "Storage volume format not supported. Valid formats: bochs, cloop, cow, dmg, " "qcow, qcow2, qed, raw, vmdk, vpc." msgstr "" msgid "Storage volume requires a volume name" msgstr "Тому требуетÑÑ Ð¸Ð¼Ñ" #, python-format msgid "" "Unable to update database with storage volume information due error: %(err)s" msgstr "" "Ðе удалоÑÑŒ обновить базу данных Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸ÐµÐ¹ о томах из-за ошибки %(err)s" #, python-format msgid "Only one of parameter %(param)s can be specified" msgstr "" #, python-format msgid "Create volume from %(param)s is not supported" msgstr "" msgid "Storage volume capacity must be an integer number." msgstr "" msgid "Storage volume URL must be http://, https://, ftp:// or ftps://." msgstr "" #, python-format msgid "Unable to access file %(url)s. Please, check it." msgstr "" #, python-format msgid "" "Unable to clone storage volume '%(name)s' in pool '%(pool)s'. Details: " "%(err)s" msgstr "" msgid "Specify chunk data and its size to upload a file." msgstr "" msgid "In order to upload a storage volume, specify the 'upload' parameter." msgstr "" msgid "" "Unable to upload chunk data as it does not match with requested chunk size." msgstr "" #, python-format msgid "The storage volume %(vol)s is not under an upload process." msgstr "" msgid "The upload chunk data will exceed the storage volume size." msgstr "" #, python-format msgid "Unable to upload chunk data to storage volume. Details: %(err)s." msgstr "" #, python-format msgid "Interface %(name)s does not exist" msgstr "Ð˜Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ %(name)s не ÑущеÑтвует" #, python-format msgid "Network %(name)s already exists" msgstr "Сеть %(name)s уже ÑущеÑтвует" #, python-format msgid "Network %(name)s does not exist" msgstr "Сеть %(name)s не ÑущеÑтвует" #, python-format msgid "Subnet %(subnet)s specified for network %(network)s is not valid." msgstr "ПодÑеть %(subnet)s, ÑƒÐºÐ°Ð·Ð°Ð½Ð½Ð°Ñ Ð´Ð»Ñ Ñети %(network)s, недопуÑтима." #, python-format msgid "Specify a network interface to create bridged network %(name)s" msgstr "" "Укажите Ñетевой Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ñети %(name)s Ñ Ð´Ð¾Ñтупом через моÑÑ‚" #, python-format msgid "Unable to delete active network %(name)s" msgstr "Ðе удалоÑÑŒ удалить активную Ñеть %(name)s" #, python-format msgid "Interface %(iface)s specified for network %(network)s is already in use" msgstr "Ð˜Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ %(iface)s, указанный Ð´Ð»Ñ Ñети %(network)s, уже иÑпользуетÑÑ" msgid "Interface should be bare NIC, bonding or bridge device." msgstr "" "Ð˜Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть Ñетевой картой, уÑтройÑтвом моÑта или ÑвÑзующим " "уÑтройÑтвом." #, python-format msgid "Unable to create network %(name)s. Details: %(err)s" msgstr "Ðе удалоÑÑŒ Ñоздать Ñеть %(name)s. СведениÑ: %(err)s" #, python-format msgid "Unable to find a free IP address for network '%(name)s'" msgstr "Ðе найден Ñвободный IP-Ð°Ð´Ñ€ÐµÑ Ð´Ð»Ñ Ñети %(name)s" #, python-format msgid "The interface %(iface)s already exists." msgstr "" msgid "Network name must be a string without slashes (/) or quotes (\")" msgstr "" msgid "Supported network types are isolated, NAT and bridge" msgstr "Поддерживаемые типы Ñетей: isolated, NAT и bridge" msgid "Network subnet must be a string with IP address and prefix or netmask" msgstr "" "ПодÑеть Ñети должна быть Ñтрокой, Ñодержащей IP-адреÑ, Ð¿Ñ€ÐµÑ„Ð¸ÐºÑ Ð¸Ð»Ð¸ маÑку Ñети" msgid "Network interface must be a string" msgstr "Сетевой Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть Ñтрокой" msgid "Network VLAN ID must be an integer between 1 and 4094" msgstr "Сетевой ИД VLAN должен быть целым чиÑлом от 1 до 4094" msgid "Specify name and type to create a Network" msgstr "Укажите Ð¸Ð¼Ñ Ð¸ тип Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ñети" #, python-format msgid "" "Unable to delete network %(name)s. There are some virtual machines %(vms)s " "and/or templates linked to this network." msgstr "" #, python-format msgid "" "Unable to deactivate network %(name)s. There are some virtual machines " "%(vms)s and/or templates linked to this network." msgstr "" #, python-format msgid "Bridge device %(name)s can not be the trunk device of a VLAN." msgstr "" "УÑтройÑтво моÑта %(name)s не может быть магиÑтральным уÑтройÑтвом VLAN." #, python-format msgid "Failed to activate interface %(iface)s: %(err)s." msgstr "Ðе удалоÑÑŒ активировать Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ %(iface)s: %(err)s." #, python-format msgid "" "Failed to activate interface %(iface)s. Please check the physical link " "status." msgstr "" "Ðе далоÑÑŒ активировать Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ %(iface)s. Проверьте ÑоÑтоÑние физичеÑкой " "линии ÑвÑзи. " #, python-format msgid "Failed to start network %(name)s. Details: %(err)s" msgstr "" #, python-format msgid "Debug report %(name)s does not exist" msgstr "Отладочный отчет %(name)s не ÑущеÑтвует" msgid "Debug report tool not found in system" msgstr "ИнÑтрумент отладочного отчета не найден в ÑиÑтеме" #, python-format msgid "Unable to create debug report %(name)s. Details: %(err)s." msgstr "Ðе удалоÑÑŒ Ñоздать отладочный отчет %(name)s. СведениÑ: %(err)s." #, python-format msgid "Can not find any debug report with the given name %(name)s" msgstr "" #, python-format msgid "Unable to generate debug report %(name)s. Details: %(err)s" msgstr "Ðе удалоÑÑŒ Ñоздать отладочный отчет %(name)s. СведениÑ: %(err)s" msgid "You should give a name for the debug report file." msgstr "" msgid "" "Debug report name must be a string. Only letters, digits, underscore ('_') " "and hyphen ('-') are allowed." msgstr "" #, python-format msgid "" "The debug report with specified name \"%(name)s\" already exists. Please use " "another one." msgstr "" "Группа томов Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ %(name)s уже ÑущеÑтвует. Выберите другое Ð¸Ð¼Ñ Ð´Ð»Ñ " "ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð»Ð¾Ð³Ð¸Ñ‡ÐµÑкого пула." #, python-format msgid "Storage server %(server)s was not used by Kimchi" msgstr "Сервер памÑти %(server)s не иÑпользовалÑÑ Kimchi" #, python-format msgid "Distro '%(name)s' does not exist" msgstr "Вариант ОС %(name)s не ÑущеÑтвует" #, python-format msgid "Partition %(name)s does not exist in the host" msgstr "Раздел %(name)s не ÑущеÑтвует на хоÑте" msgid "Unable to shutdown host machine as there are running virtual machines" msgstr "" "Ðе удалоÑÑŒ завершить работу ÑиÑтемы хоÑта: выполнÑÑŽÑ‚ÑÑ Ð²Ð¸Ñ€Ñ‚ÑƒÐ°Ð»ÑŒÐ½Ñ‹Ðµ машины" msgid "Unable to reboot host machine as there are running virtual machines" msgstr "Ðе удалоÑÑŒ перезагрузить ÑиÑтему хоÑта: выполнÑÑŽÑ‚ÑÑ Ð²Ð¸Ñ€Ñ‚ÑƒÐ°Ð»ÑŒÐ½Ñ‹Ðµ машины" #, python-format msgid "Node device '%(name)s' not found" msgstr "УÑтройÑтво %(name)s узла не найдено" msgid "Conflicting flag filters specified." msgstr "" msgid "No packages marked for update" msgstr "Ðет пакетов, помеченных Ð´Ð»Ñ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ" #, python-format msgid "Package %(name)s is not marked to be updated." msgstr "Пакет %(name)s не помечен Ð´Ð»Ñ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ." #, python-format msgid "Error while getting packages marked to be updated. Details: %(err)s" msgstr "Ошибка Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð¿Ð°ÐºÐµÑ‚Ð¾Ð², помеченных Ð´Ð»Ñ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ. СведениÑ: %(err)s" msgid "There is no compatible package manager for this system." msgstr "Ðет ÑовмеÑтимого админиÑтратора пакетов Ð´Ð»Ñ Ñтой ÑиÑтемы." #, python-format msgid "Unable to find %(item)s in datastore" msgstr "Ðе найден %(item)s в хранилище данных" #, python-format msgid "Invalid URI %(uri)s" msgstr "ÐедопуÑтимый URI %(uri)s" #, python-format msgid "Timeout while running command '%(cmd)s' after %(seconds)s seconds" msgstr "ИÑтек тайм-аут Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ‹ %(cmd)s (%(seconds)s Ñ)" msgid "Unable to choose a virtual machine name" msgstr "" #, python-format msgid "Invalid data value '%(value)s'" msgstr "" #, python-format msgid "Invalid data unit '%(unit)s'" msgstr "" msgid "Invalid storage type. Types supported: 'cdrom', 'disk'" msgstr "ÐедопуÑтимый тип памÑти. Поддерживаемые типы: cdrom" #, python-format msgid "The path '%(value)s' is not a valid local/remote path for the device" msgstr "" msgid "Only CDROM path can be update." msgstr "" #, python-format msgid "" "The storage device %(dev_name)s does not exist in the virtual machine " "%(vm_name)s" msgstr "" #, python-format msgid "Error while creating new storage device: %(error)s" msgstr "Ошибка ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ ÑƒÑтройÑтва хранениÑ: %(error)s" #, python-format msgid "Error while updating storage device: %(error)s" msgstr "Ошибка Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ ÑƒÑтройÑтва хранениÑ: %(error)s" #, python-format msgid "Error while removing storage device: %(error)s" msgstr "Ошибка ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ ÑƒÑтройÑтва хранениÑ: %(error)s" msgid "Do not support IDE device hot plug" msgstr "" msgid "" "Specify type and path or type and pool/volume to add a new virtual machine " "disk" msgstr "Укажите тип и путь Ð´Ð»Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ диÑка виртуальной машины" msgid "Specify path to update virtual machine disk" msgstr "Укажите путь Ð´Ð»Ñ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð´Ð¸Ñка виртуальной машины" #, python-format msgid "Controller type %(type)s limitation of %(limit)s devices reached" msgstr "" #, python-format msgid "Cannot retrieve disk path information for given pool/volume: %(error)s" msgstr "" msgid "Volume already in use by other virtual machine." msgstr "" msgid "" "Only one of path or pool/volume can be specified to add a new virtual " "machine disk" msgstr "Укажите тип и путь Ð´Ð»Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ диÑка виртуальной машины" #, python-format msgid "" "Volume chosen with format %(format)s does not fit in the storage type " "%(type)s" msgstr "" msgid "YUM Repository ID must be one word only string." msgstr "" "ИД хранилища YUM должен быть Ñтрокой, ÑоÑтоÑщей только из одного Ñлова." msgid "Repository URL must be an http://, ftp:// or file:// URL." msgstr "URL хранилища должен быть http://, ftp:// или file:// ." msgid "" "Repository configuration is a dictionary with specific values according to " "repository type." msgstr "" "ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ Ñ…Ñ€Ð°Ð½Ð¸Ð»Ð¸Ñ‰Ð° предÑтавлÑет Ñобой Ñловарь значений, определÑемых " "типом хранилища." msgid "Distribution to DEB repository must be a string" msgstr "Вариант Ð´Ð»Ñ Ñ…Ñ€Ð°Ð½Ð¸Ð»Ð¸Ñ‰Ð° DEB должен быть Ñтрокой" msgid "Components to DEB repository must be listed in a array" msgstr "Компоненты Ð´Ð»Ñ Ñ…Ñ€Ð°Ð½Ð¸Ð»Ð¸Ñ‰Ð° DEB должны быть перечиÑлены в маÑÑиве" msgid "Components to DEB repository must be a string" msgstr "Компоненты Ð´Ð»Ñ Ñ…Ñ€Ð°Ð½Ð¸Ð»Ð¸Ñ‰Ð° DEB должны быть Ñтрокой" msgid "Mirror list to repository must be a string" msgstr "" msgid "YUM Repository name must be string." msgstr "Ð˜Ð¼Ñ Ñ…Ñ€Ð°Ð½Ð¸Ð»Ð¸Ñ‰Ð° YUM должно быть Ñтрокой." msgid "GPG check must be a boolean value." msgstr "Проверка GPG должна быть булевÑким значением." msgid "GPG key must be a URL pointing to the ASCII-armored file." msgstr "" "Ключ GPG должен быть URL, указывающим на защищенный файл Ñ ÐºÐ¾Ð´Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸ÐµÐ¼ " "ASCII." #, python-format msgid "Could not update repository %(repo_id)s." msgstr "Ðе удалоÑÑŒ обновить хранилище %(repo_id)s." #, python-format msgid "Repository %(repo_id)s does not exist." msgstr "Хранилище %(repo_id)s не ÑущеÑтвует." msgid "" "Specify repository base URL, mirror list or metalink in order to create or " "update a YUM repository." msgstr "" msgid "Repository management tool was not recognized for your system." msgstr "Ðе раÑпознан инÑтрумент ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ñ…Ñ€Ð°Ð½Ð¸Ð»Ð¸Ñ‰ÐµÐ¼ Ð´Ð»Ñ ÑиÑтемы." #, python-format msgid "Repository %(repo_id)s is already enabled." msgstr "Хранилище %(repo_id)s уже включено." #, python-format msgid "Repository %(repo_id)s is already disabled." msgstr "Хранилище %(repo_id)s уже выключено." #, python-format msgid "Could not remove repository %(repo_id)s." msgstr "Ðе удалоÑÑŒ удалить хранилище %(repo_id)s." #, python-format msgid "Could not write repository configuration file %(repo_file)s" msgstr "Ðе удалоÑÑŒ запиÑать в файл конфигурации хранилища %(repo_file)s" msgid "Specify repository distribution in order to create a DEB repository." msgstr "Укажите вариант хранилища Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ñ…Ñ€Ð°Ð½Ð¸Ð»Ð¸Ñ‰Ð° DEB." #, python-format msgid "Could not enable repository %(repo_id)s." msgstr "Ðе удалоÑÑŒ включить хранилище %(repo_id)s." #, python-format msgid "Could not disable repository %(repo_id)s." msgstr "Ðе удалоÑÑŒ выключить хранилище %(repo_id)s." msgid "YUM Repository ID already exists" msgstr "ИД хранилища YUM уже ÑущеÑтвует" msgid "YUM Repository name must be a string" msgstr "Ð˜Ð¼Ñ Ñ…Ñ€Ð°Ð½Ð¸Ð»Ð¸Ñ‰Ð° YUM должно быть Ñтрокой" #, python-format msgid "Unable to list repositories. Details: '%(err)s'" msgstr "Ðе удалоÑÑŒ вывеÑти ÑпиÑок хранилищ. СведениÑ: %(err)s" #, python-format msgid "Unable to retrieve repository information. Details: '%(err)s'" msgstr "Ðе удалоÑÑŒ получить информацию о хранилище. СведениÑ: %(err)s" #, python-format msgid "Unable to add repository. Details: '%(err)s'" msgstr "Ðе удалоÑÑŒ добавить хранилище. СведениÑ: %(err)s" #, python-format msgid "Unable to remove repository. Details: '%(err)s'" msgstr "Ðе удалоÑÑŒ удалить хранилище. СведениÑ: %(err)s" #, python-format msgid "" "Configuration items: '%(items)s' are not supported by repository manager" msgstr "" msgid "Repository metalink must be an http://, ftp:// or file:// URL." msgstr "" msgid "Cannot specify mirrorlist and metalink at the same time." msgstr "" #, python-format msgid "" "Virtual machine '%(vm)s' must be stopped before creating a snapshot of it." msgstr "" #, python-format msgid "" "Unable to create snapshot '%(name)s' on virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "Snapshot '%(name)s' does not exist on virtual machine '%(vm)s'." msgstr "" #, python-format msgid "" "Unable to retrieve snapshot '%(name)s' on virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "Unable to list snapshots on virtual machine '%(vm)s'. Details: %(err)s" msgstr "" #, python-format msgid "" "Unable to delete snapshot '%(name)s' on virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "" "Unable to retrieve current snapshot of virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "" "Unable to revert virtual machine '%(vm)s' to snapshot '%(name)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "" "Unable to create snapshot of virtual machine '%(vm)s' because it contains a " "disk with format '%(format)s'; only 'qcow2' is supported." msgstr "" msgid "The number of vCPUs is too large for this system." msgstr "" msgid "Invalid vCPU/topology combination." msgstr "" msgid "This host (or current configuration) does not allow CPU topology." msgstr "" msgid "ERROR CODE" msgstr "Код ошибки" msgid "REASON" msgstr "ПРИЧИÐÐ" msgid "STACK" msgstr "Стек" msgid "Go to Homepage" msgstr "Перейти на главную Ñтраницу" msgid "Create a New Virtual Machine" msgstr "Создать новую виртуальную машину" msgid "Virtual Machine Name" msgstr "Ð˜Ð¼Ñ Ð²Ð¸Ñ€Ñ‚ÑƒÐ°Ð»ÑŒÐ½Ð¾Ð¹ машины" msgid "" "The name used to identify the virtual machine. If omitted, a name will be " "chosen based on the template used." msgstr "" "Ð˜Ð¼Ñ Ð´Ð»Ñ Ð¸Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ð¸ виртуальной машины. ЕÑли не указано, Ð¸Ð¼Ñ Ð±ÑƒÐ´ÐµÑ‚ выбрано " "в завиÑимоÑти от иÑпользуемого шаблона." msgid "Template" msgstr "Шаблон" msgid "Please create a template first." msgstr "ПожалуйÑта, Ñоздайте шаблон в первую очередь." msgid "Create a Template" msgstr "Создать шаблон" msgid "Please choose a template." msgstr "ПожалуйÑта, выберите шаблон." msgid "OS" msgstr "ОС" msgid "OS Version" msgstr "ВерÑÐ¸Ñ ÐžÐ¡" msgid "CPUS" msgstr "ПроцеÑÑоры" msgid "Memory" msgstr "ПамÑть" msgid "Create" msgstr "Создать" msgid "Creating..." msgstr "" msgid "Edit Guest" msgstr "Изменить гоÑтевую ÑиÑтему" msgid "General" msgstr "Общее" msgid "Storage" msgstr "Хранилище" msgid "Interface" msgstr "ИнтерфейÑ" msgid "Permission" msgstr "ВерÑиÑ" msgid "Host PCI Device" msgstr "" msgid "Snapshot" msgstr "" msgid "Name" msgstr "ИмÑ" msgid "CPUs" msgstr "ПроцеÑÑоры" msgid "Memory (MB)" msgstr "ПамÑть (Мб)" msgid "Icon" msgstr "Значок" msgid "Device" msgstr "Ð˜Ð¼Ñ ÑƒÑтройÑтва" msgid "Path" msgstr "Путь NFS" msgid "Network" msgstr "Сеть" msgid "Type" msgstr "Тип" msgid "MAC Address" msgstr "" msgid "Available system users and groups" msgstr "" msgid "Selected system users and groups" msgstr "" msgid "User" msgstr "" msgid "All" msgstr "Ð’Ñе" msgid "To Add" msgstr "" msgid "Added" msgstr "" msgid "filter" msgstr "" msgid "Product" msgstr "" msgid "Vendor" msgstr "Вендор" msgid "Created" msgstr "" msgid "Save" msgstr "Сохранить" msgid "Replace" msgstr "Заменить" msgid "Detach" msgstr "Отключить" msgid "Cancel" msgstr "Отмена" msgid "revert" msgstr "" msgid "Add a Storage Device to VM" msgstr "Добавить уÑтройÑтво Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð² VM" msgid "Device Type" msgstr "Тип уÑтройÑтва" msgid "The device type. Currently, \"cdrom\" and \"disk\" are supported." msgstr "Тип уÑтройÑтва. Ð’ данный момент поддерживаетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ \"cdrom\"." msgid "Storage Pool" msgstr "Пул памÑти" msgid "Storage pool which volume located in" msgstr "Путь к пулу памÑти должен быть Ñтрокой" msgid "Storage Volume" msgstr "Ð˜Ð¼Ñ Ð¿ÑƒÐ»Ð° памÑти" msgid "Storage volume to be attached" msgstr "Ð˜Ð¼Ñ Ñ‚Ð¾Ð¼Ð° должно быть Ñтрокой" msgid "File Path" msgstr "Путь к файлу" msgid "The ISO file path in the server for CDROM." msgstr "Путь к файлу ISO Ð´Ð»Ñ CDROM на Ñервере." msgid "Attach" msgstr "Подключить" msgid "Start" msgstr "ЗапуÑтить" msgid "Reset" msgstr "СброÑить" msgid "Pause" msgstr "" msgid "Resume" msgstr "" msgid "Power Off" msgstr "Выключить" msgid "Actions" msgstr "ДейÑтвиÑ" msgid "Connect" msgstr "Подключить" msgid "Clone" msgstr "Клонировать" msgid "Edit" msgstr "Редактировать" msgid "Shut Down" msgstr "Завершить работу" msgid "Delete" msgstr "Удалить" msgid "The username or password you entered is incorrect. Please try again." msgstr "Указано неверное Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸Ð»Ð¸ пароль. Введите еще раз." msgid "This field is required." msgstr "Это обÑзательное поле." msgid "Log in" msgstr "Войти" msgid "Logging in..." msgstr "Вход..." msgid "Host" msgstr "ХоÑÑ‚" msgid "Guests" msgstr "ГоÑтевые ÑиÑтемы" msgid "Templates" msgstr "Шаблоны" msgid "Failed to get application configuration" msgstr "Ðе удалоÑÑŒ получить конфигурацию приложениÑ" msgid "This is not a valid Linux path" msgstr "Этот недопуÑтимый путь в Linux" msgid "This is not a valid URL." msgstr "Это недопуÑтимый URL." msgid "No such data available." msgstr "Ðет таких данных." msgid "" "Can not contact the host system. Verify the host system is up and that you " "have network connectivity to it. HTTP request response %1. " msgstr "" "Ðет ÑвÑзи Ñ ÑиÑтемой хоÑта. УбедитеÑÑŒ, что ÑиÑтема хоÑта работает и доÑтупна " "Ð´Ð»Ñ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ. Ответ на Ð·Ð°Ð¿Ñ€Ð¾Ñ HTTP: %1. " msgid "Unable to read file." msgstr "" msgid "Error while uploading file." msgstr "" msgid "Delete Confirmation" msgstr "Подтверждение удалениÑ" msgid "OK" msgstr "OK" msgid "Confirm" msgstr "Подтвердить" msgid "Warning" msgstr "Предупреждение" msgid "Cloning..." msgstr "" msgid "Loading..." msgstr "ЗагружаетÑÑ..." msgid "An error occurred while retrieving system information." msgstr "" msgid "Retry" msgstr "Повторить" msgid "Detailed message:" msgstr "Подробное Ñообщение:" msgid "No ISO found" msgstr "" msgid "This is not a valid ISO file." msgstr "Этот файл не ÑвлÑетÑÑ Ð´Ð¾Ð¿ÑƒÑтимым образом ISO." msgid "This may take a long time. Do you want to continue?" msgstr "Это займет много времени. Продолжить?" msgid "This will permanently delete the template. Would you like to continue?" msgstr "Шаблон будет безвозвратно удален. Продолжить?" msgid "Unable to shut down system as there are some virtual machines running!" msgstr "" "Ðевозможно завершить работу ÑиÑтемы, поÑкольку в ней работают виртуальные " "машины!" msgid "Max:" msgstr "МакÑ.:" msgid "Utilization" msgstr "ИÑпользование" msgid "Available" msgstr "ДоÑтупно" msgid "Read Rate" msgstr "СкороÑть чтениÑ" msgid "Write Rate" msgstr "СкороÑть запиÑи" msgid "Received" msgstr "Получено" msgid "Sent" msgstr "Отправлено" msgid "" "Shutting down or restarting host will cause unsaved work lost. Continue to " "shut down/restarting?" msgstr "" "Завершение работы и перезапуÑк хоÑта приведут к потере неÑохраненной работы. " "Продолжить завершение работы/перезапуÑк?" msgid "" "Repository will be removed permanently and can't be recovered. Do you want " "to continue?" msgstr "Хранилище будет удалено без возможноÑти воÑÑтановлениÑ. Продолжить?" msgid "Repositories" msgstr "Хранилища" msgid "ID" msgstr "ИД" msgid "Base URL" msgstr "Базовый URL" msgid "Is Mirror" msgstr "Ð—ÐµÑ€ÐºÐ°Ð»ÑŒÐ½Ð°Ñ ÐºÐ¾Ð¿Ð¸Ñ" msgid "URL Args" msgstr "Ðргументы URL" msgid "Enabled" msgstr "Включено" msgid "GPG Check" msgstr "Проверка GPG" msgid "GPG Key" msgstr "Ключ GPG" msgid "Add" msgstr "Добавить" msgid "Remove" msgstr "Удалить" msgid "Enable" msgstr "Включить" msgid "Disable" msgstr "Выключить" msgid "Software Updates" msgstr "ÐžÐ±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¼Ð½Ð¾Ð³Ð¾ обеÑпечениÑ" msgid "Package Name" msgstr "Ð˜Ð¼Ñ Ð¿Ð°ÐºÐµÑ‚Ð°" msgid "Version" msgstr "ВерÑиÑ" msgid "Architecture" msgstr "Ðрхитектура" msgid "Repository" msgstr "Хранилище" msgid "Update All" msgstr "Обновить вÑÑ‘" msgid "Updating..." msgstr "Обновление..." msgid "Failed to retrieve packages update information." msgstr "" msgid "Failed to update package(s)." msgstr "Ðе удалоÑÑŒ обновить пакеты." msgid "" "Debug report will be removed permanently and can't be recovered. Do you want " "to continue?" msgstr "" "Отладочный отчет будет удален без возможноÑти воÑÑтановлениÑ. Продолжить?" msgid "Debug Reports" msgstr "Отладочные отчеты" msgid "Generated Time" msgstr "Ð’Ñ€ÐµÐ¼Ñ ÑозданиÑ" msgid "Generate" msgstr "Создать" msgid "Generating..." msgstr "Создание..." msgid "Rename" msgstr "Переименовать" msgid "Download" msgstr "Загрузить" msgid "" "Report name should contain only letters, digits, underscore ('_') and/or " "hyphen ('-')." msgstr "Ð˜Ð¼Ñ Ð¾Ñ‚Ñ‡ÐµÑ‚Ð° должно Ñодержать только буквы, цифры и дефиÑÑ‹ ('-')." msgid "Pending..." msgstr "ЗагружаетÑÑ..." msgid "Report name is the same as the original one." msgstr "" msgid "" "This will delete the virtual machine and its virtual disks. This operation " "cannot be undone. Would you like to continue?" msgstr "" "Будет удалена Ð²Ð¸Ñ€Ñ‚ÑƒÐ°Ð»ÑŒÐ½Ð°Ñ Ð¼Ð°ÑˆÐ¸Ð½Ð° вмеÑте Ñо Ñвоими виртуальными диÑками. Это " "Ð½ÐµÐ¾Ð±Ñ€Ð°Ñ‚Ð¸Ð¼Ð°Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ñ. Продолжить?" msgid "Power off Confirmation" msgstr "Подтверждение удалениÑ" msgid "" "This action may produce undesirable results, for example unflushed disk " "cache in the guest. Would you like to continue?" msgstr "" msgid "Reset Confirmation" msgstr "Подтверждение удалениÑ" msgid "" "There is a risk of data loss caused by reset without the guest OS shutdown. " "Would you like to continue?" msgstr "" msgid "Shut Down Confirmation" msgstr "Подтверждение удалениÑ" msgid "Note the guest OS may ignore this request. Would you like to continue?" msgstr "Шаблон будет безвозвратно удален. Продолжить?" msgid "Virtual Machine delete Confirmation" msgstr "" msgid "" "This virtual machine is not persistent. Power Off will delete it. Continue?" msgstr "" msgid "" "When the target guest has SCSI or iSCSI volumes, they will be cloned on " "default storage pool. The same will happen when the target pool does not " "have enough space to clone the volumes. Do you want to continue?" msgstr "" msgid "" "This CDROM will be detached permanently and you can re-attach it. Continue " "to detach it?" msgstr "" "Этот CDROM будет отключен. Его можно будет Ñнова подключить. Отключить?" msgid "Attaching..." msgstr "Подключение..." msgid "Replacing..." msgstr "Замена..." msgid "Successfully attached!" msgstr "УÑпешно подключен!" msgid "Successfully replaced!" msgstr "УÑпешно заменен!" msgid "Successfully detached!" msgstr "УÑпешно отключен!" msgid "" "This disk will be detached permanently and you can re-attach it. Continue to " "detach it?" msgstr "" msgid "interface:" msgstr "" msgid "address:" msgstr "" msgid "link_type:" msgstr "" msgid "block:" msgstr "" msgid "drive_type:" msgstr "" msgid "model:" msgstr "" msgid "Affected devices:" msgstr "" msgid "The VLAN id must be between 1 and 4094." msgstr "ИД VLAN должен быть от 1 до 4094." msgid "unavailable" msgstr "недоÑтупно" msgid "" "This action will interrupt network connectivity for any virtual machine that " "depend on this network." msgstr "" "Это дейÑтвие нарушит Ñетевые ÑÐ¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Ñƒ вÑех виртуальных машин, которые " "завиÑÑÑ‚ от Ñтой Ñети." msgid "Create a network" msgstr "Создать Ñеть" msgid "" "This network is not persistent. Instead of stop, this action will " "permanently delete it. Would you like to continue?" msgstr "" "Этот пул памÑти не поÑтоÑнный. ВмеÑто деактивации, Ñто дейÑтвие безвозвратно " "его удалит. Продолжить?" msgid "" "The bridged VLAN tag may not work well with NetworkManager enabled. You " "should consider disabling it." msgstr "" msgid "" "This will permanently delete the storage pool. Would you like to continue?" msgstr "Пул памÑти будет безвозвратно удален. Продолжить?" msgid "This storage pool is empty." msgstr "Этот пул памÑти пуÑтой." msgid "" "It will format your disk and you will loose any data in there, are you sure " "to continue? " msgstr "" "ДиÑк будет отформатирован, и вÑе данные на нем будут потерÑны. Ð’Ñ‹ " "дейÑтвительно хотите продолжить? " msgid "SCSI Fibre Channel" msgstr "SCSI Fibre Channel" msgid "No SCSI adapters found." msgstr "Ðе найдены адаптеры SCSI." msgid "Loading iSCSI targets..." msgstr "" msgid "No iSCSI found. Please input one." msgstr "" msgid "Failed to load iSCSI targets." msgstr "" msgid "The storage pool name can not be blank." msgstr "Ðе указано Ð¸Ð¼Ñ Ð¿ÑƒÐ»Ð° памÑти." msgid "The storage pool path can not be blank." msgstr "Ðе указан путь к пулу памÑти." msgid "NFS server mount path can not be blank." msgstr "Ðе указан путь Ð¼Ð¾Ð½Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ñервера NFS." msgid "Invalid NFS mount path." msgstr "ÐедопуÑтимый путь Ð¼Ð¾Ð½Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ NFS." msgid "No logical device selected." msgstr "Ðе выбрано логичеÑкое уÑтройÑтво." msgid "The iSCSI target can not be blank." msgstr "Ðе указан целевой объект iSCSI." msgid "Server name can not be blank." msgstr "Ðе указано Ð¸Ð¼Ñ Ñервера." msgid "This is not a valid Server Name or IP. Please, modify it." msgstr "" msgid "Looking for available partitions ..." msgstr "ПоиÑк доÑтупных разделов..." msgid "No available partitions found." msgstr "Ðе найдены доÑтупные разделы." msgid "" "This storage pool is not persistent. Instead of deactivate, this action will " "permanently delete it. Would you like to continue?" msgstr "" "Этот пул памÑти не поÑтоÑнный. ВмеÑто деактивации, Ñто дейÑтвие безвозвратно " "его удалит. Продолжить?" msgid "Unable to retrieve partitions information." msgstr "Ðе удалоÑÑŒ получить информацию о хранилище. СведениÑ: %(err)s" msgid "In progress..." msgstr "" msgid "Failed!" msgstr "" msgid "CDROM path needs to be a valid local/remote path and cannot be blank." msgstr "" msgid "Disk pool or volume cannot be blank." msgstr "Ðе указано Ð¸Ð¼Ñ Ð¿ÑƒÐ»Ð° памÑти." msgid "Peers" msgstr "" msgid "Searching" msgstr "" msgid "No peers found." msgstr "" msgid "Help" msgstr "Помощь" msgid "About" msgstr "О программе" msgid "Log out" msgstr "Выйти" msgid "Version:" msgstr "ВерÑиÑ:" msgid "Session timeout, please re-login." msgstr "" msgid "User Name" msgstr "Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ" msgid "Password" msgstr "Пароль" msgid "Generate a New Debug Report" msgstr "Создать новый отладочный отчет" msgid "Report Name" msgstr "Ð˜Ð¼Ñ Ð¾Ñ‚Ñ‡ÐµÑ‚Ð°" msgid "" "The name used to identify the report. If omitted, a name will be chosen " "based on current time. Name can contain: letters, digits, underscore (\"_\") " "and hyphen (\"-\")." msgstr "" "Ð˜Ð¼Ñ Ð´Ð»Ñ Ð¸Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ð¸ отчета. ЕÑли не указано, Ð¸Ð¼Ñ Ð±ÑƒÐ´ÐµÑ‚ Ñформировано на " "оÑнове текущего времени. Ð˜Ð¼Ñ Ð¼Ð¾Ð¶ÐµÑ‚ Ñодержать: буквы, цифры и дефиÑÑ‹ (\"-\")." msgid "Rename a Debug Report" msgstr "Создать новый отладочный отчет" msgid "" "The name used to identify the report. Name can contain: letters, digits and " "hyphen (\"-\")." msgstr "" "Ð˜Ð¼Ñ Ð´Ð»Ñ Ð¸Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ð¸ отчета. ЕÑли не указано, Ð¸Ð¼Ñ Ð±ÑƒÐ´ÐµÑ‚ Ñформировано на " "оÑнове текущего времени. Ð˜Ð¼Ñ Ð¼Ð¾Ð¶ÐµÑ‚ Ñодержать: буквы, цифры и дефиÑÑ‹ (\"-\")." msgid "Submit" msgstr "Подтвердить" msgid "Add a Repository" msgstr "Добавить хранилище" msgid "Identifier" msgstr "Идентификатор" msgid "Single word, unique identifier for the repository." msgstr "Одиночное Ñлово - уникальный идентификатор хранилища." msgid "Textual name for the repository." msgstr "ТекÑтовое Ð¸Ð¼Ñ Ñ…Ñ€Ð°Ð½Ð¸Ð»Ð¸Ñ‰Ð°." msgid "URL" msgstr "URL" msgid "Required Field" msgstr "ОбÑзательное поле" msgid "URL to the repository. Supported protocols are http, ftp, and file." msgstr "URL хранилища. Поддерживаемые протоколы: http, ftp, file." msgid "Repository is a mirror" msgstr "Хранилище ÑвлÑетÑÑ Ð·ÐµÑ€ÐºÐ°Ð»ÑŒÐ½Ð¾Ð¹ копией." msgid "Distribution" msgstr "Вариант" msgid "Distribution of the DEB repository." msgstr "Вариант хранилища DEB." msgid "Components" msgstr "Компоненты" msgid "List of components in DEB repository." msgstr "СпиÑок компонентов в хранилище DEB." msgid "Edit Repository" msgstr "Изменить хранилище" msgid "Mirror List URL" msgstr "URL ÑпиÑка зеркальных копий" msgid "Yes" msgstr "Да" msgid "No" msgstr "Ðет" msgid "Add a Volume to Storage Pool" msgstr "" msgid "Fetch from remote URL" msgstr "" msgid "Enter the remote URL here." msgstr "" msgid "Upload a file" msgstr "" msgid "Choose the file you want to upload." msgstr "" msgid "Define a New Storage Pool" msgstr "Создать пул памÑти" msgid "Storage Pool Name" msgstr "Ð˜Ð¼Ñ Ð¿ÑƒÐ»Ð° памÑти" msgid "" "The name used to identify the storage pools, and it should not be empty." msgstr "Ð˜Ð¼Ñ Ð´Ð»Ñ Ð¸Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ð¸ пулов памÑти. Ðе может быть пуÑтым." msgid "Storage Pool Type" msgstr "Тип пула памÑти" msgid "Storage Path" msgstr "Путь к диÑку" msgid "" "The path of the Storage Pool. Each Storage Pool must have a unique path." msgstr "Путь к пулу памÑти. Каждый пул памÑти должен иметь уникальный путь." msgid "" "Kimchi will try to create the directory when it does not already exist in " "your system." msgstr "Kimchi попытаетÑÑ Ñоздать каталог, еÑли он не ÑущеÑтвует в ÑиÑтеме." msgid "NFS Server IP" msgstr "IP-Ð°Ð´Ñ€ÐµÑ Ñервера NFS" msgid "NFS server IP or hostname. It can be input or chosen from history." msgstr "" "IP-Ð°Ð´Ñ€ÐµÑ Ð¸Ð»Ð¸ Ð¸Ð¼Ñ Ñ…Ð¾Ñта Ñервера NFS. Его можно ввеÑти или выбрать в " "хронологии." msgid "NFS Path" msgstr "Путь NFS" msgid "The NFS exported path on NFS server." msgstr "ЭкÑпортированный путь NFS на Ñервере NFS." msgid "Device path" msgstr "Путь к уÑтройÑтву" msgid "iSCSI Server" msgstr "Сервер iSCSI" msgid "iSCSI server IP or hostname. It should not be empty." msgstr "IP-Ð°Ð´Ñ€ÐµÑ Ð¸Ð»Ð¸ Ð¸Ð¼Ñ Ñ…Ð¾Ñта Ñервера iSCSI. Ðе может быть пуÑтым." msgid "Server" msgstr "Сервер" msgid "Port" msgstr "Порт" msgid "Target" msgstr "Целевой объект" msgid "The iSCSI target on iSCSI server" msgstr "Целевой объект iSCSI на Ñервере iSCSI" msgid "Add iSCSI Authentication" msgstr "Добавить идентификацию iSCSI" msgid "iSCSI Authentication" msgstr "Ð˜Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ iSCSI" msgid "SCSI Adapter" msgstr "Ðдаптер SCSI" msgid "Please, wait..." msgstr "Подождите..." msgid "Add Template" msgstr "Добавить шаблон" msgid "Where is the source media for this template? " msgstr "Где находитÑÑ Ð¸Ñходный ноÑитель Ð´Ð»Ñ Ñтого шаблона?" msgid "Local ISO Image" msgstr "Локальный образ ISO" msgid "Local Image File" msgstr "" msgid "Remote ISO Image" msgstr "Удаленный образ ISO" msgid "Search ISOs" msgstr "ПоиÑк образов ISO" msgid "The following ISOs are available:" msgstr "ДоÑтупные образы ISO:" msgid "OS: " msgstr "ОС: " msgid "Version: " msgstr "ВерÑиÑ: " msgid "Size: " msgstr "Размер: " msgid "Search more ISOs" msgstr "ПоиÑк дополнительных образов ISO" msgid "Create Templates from Selected ISO" msgstr "Создать шаблоны из выбранных образов ISO" msgid "I want to use a specific ISO file" msgstr "ИÑпользовать конкретный файл ISO" msgid "Loading default remote ISOs ..." msgstr "Загрузка удаленных ISO по умолчанию..." msgid "Arch: " msgstr "Ðрхитектура: " msgid "I want to use a custom URL" msgstr "ИÑпользовать другой URL" msgid "Edit Template" msgstr "Изменить шаблон" msgid "Processor" msgstr "ПроцеÑÑор" msgid "CDROM" msgstr "CDROM" msgid "Image File" msgstr "" msgid "Graphics" msgstr "Графика" msgid "Disk(GB)" msgstr "" msgid "Disk Format" msgstr "" msgid "CPU Number" msgstr "КоличеÑтво процеÑÑоров" msgid "Manually set CPU topology" msgstr "" msgid "Cores" msgstr "" msgid "Threads" msgstr "" msgid "CPU" msgstr "ПроцеÑÑор" msgid "Disk I/O" msgstr "ДиÑковый ввод-вывод" msgid "Network I/O" msgstr "Сетевой ввод-вывод" msgid "Livetile" msgstr "Livetile" msgid "No guests found." msgstr "Ðе найдены гоÑтевые ÑиÑтемы." msgid "Shut down" msgstr "Выключен" msgid "Restart" msgstr "ПерезапуÑк" msgid "Basic Information" msgstr "Ð‘Ð°Ð·Ð¾Ð²Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ" msgid "OS Distro" msgstr "Вариант ОС" msgid "OS Code Name" msgstr "Кодовое Ð¸Ð¼Ñ ÐžÐ¡" msgid "CPU(s)" msgstr "" msgid "System Statistics" msgstr "СиÑÑ‚ÐµÐ¼Ð½Ð°Ñ ÑтатиÑтика" msgid "Update Progress" msgstr "Ход обновлениÑ" msgid "Network Name" msgstr "Ð˜Ð¼Ñ Ñети" msgid "State" msgstr "СоÑтоÑние" msgid "Network Type" msgstr "Тип Ñети" msgid "Address Space" msgstr "ÐдреÑное проÑтранÑтво" msgid "Name should not contain '/' and '\"'." msgstr "ÐедопуÑтимое Ð¸Ð¼Ñ Ð¿ÑƒÐ»Ð° памÑти. Ð’ имени не должно быть Ñимволов '/'." msgid "Isolated: no external network connection" msgstr "Изолированный (без физичеÑких Ñетевых Ñоединений)" msgid "NAT: outbound physical network connection only" msgstr "NAT (только иÑходÑщее физичеÑкое Ñетевое Ñоединение)" msgid "Bridged: Virtual machines are connected to physical network directly" msgstr "Через моÑÑ‚ (прÑмое подключение виртуальных машин к физичеÑкой Ñети)" msgid "(No interfaces found)" msgstr "" msgid "Destination" msgstr "Целевое раÑположение:" msgid "Enable VLAN" msgstr "Включить VLAN:" msgid "VLAN ID" msgstr "" msgid "Stop" msgstr "Завершить" msgid "%Used" msgstr "" msgid "Location" msgstr "РаÑположение" msgid "Capacity" msgstr "ЕмкоÑть" msgid "Allocated" msgstr "Выделено" msgid "active" msgstr "активен" msgid "inactive" msgstr "неактивен" msgid "Deactivate" msgstr "Выключить" msgid "Activate" msgstr "Ðктивировать" msgid "Add Volume" msgstr "" msgid "Extend" msgstr "" msgid "Undefine" msgstr "Удалить" msgid "Format" msgstr "Формат:" msgid "Allocation" msgstr "Выделение реÑурÑов:" msgid "No templates found." msgstr "Ðе найдены шаблоны." kimchi-1.5.0/po/zh_CN.po000066400000000000000000001673151254252253000147550ustar00rootroot00000000000000# i18n portable object for kimchi. # Copyright (C) IBM, Corp. 2013-2014 # ShaoHe Feng , 2013-04-18. # # 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 # msgid "" msgstr "" "Project-Id-Version: kimchi 0.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-06-24 09:39-0300\n" "PO-Revision-Date: 2013-06-27 10:48+0000\n" "Last-Translator: ShaoHe Feng \n" "Language-Team: ShaoHe Feng \n" "Language: zh_CN\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: pygettext.py 1.5\n" "X-Poedit-Country: CHINA\n" "X-Poedit-Language: Chinese\n" "X-Poedit-SourceCharset: utf-8\n" #, python-format msgid "Unknown parameter %(value)s" msgstr "未知å˜é‡ %(value)s" #, python-format msgid "Delete is not allowed for %(resource)s" msgstr "ä¸å…许删除%(resource)s" #, python-format msgid "%(resource)s does not implement update method" msgstr "䏿”¯æŒæ›´æ–°%(resource)s" #, python-format msgid "Create is not allowed for %(resource)s" msgstr "ä¸å…许创建%(resource)s" msgid "Unable to parse JSON request" msgstr "无法解æžJSON请求" msgid "This API only supports JSON" msgstr "这个API仅支æŒJSON" #, python-format msgid "Parameters does not match requirement in schema: %(err)s" msgstr "傿•°ä¸ç¬¦åˆè¦æ±‚的格å¼ï¼š%(err)s" msgid "You don't have permission to perform this operation." msgstr "您没有æƒé™æ‰§è¡Œè¿™é¡¹æ“作。" msgid "Datastore is not initiated in the model object." msgstr "尚未为model对象åˆå§‹åŒ–æ•°æ®å­˜å‚¨ã€‚" #, python-format msgid "Unable to start task due error: %(err)s" msgstr "由于错误%(err)s任务å¯åŠ¨å¤±è´¥" #, python-format msgid "Timeout of %(seconds)s seconds expired while running task '%(task)s." msgstr "任务'%(task)sè¶…æ—¶%(seconds)s秒。" #, python-format msgid "Authentication failed for user '%(username)s'. [Error code: %(code)s]" msgstr "用户'%(username)s'身份验è¯å¤±è´¥.[错误代ç ï¼š%(code)s]" msgid "You are not authorized to access Kimchi" msgstr "您没有被授æƒè®¿é—®Kimchi" #, python-format msgid "Specify %(item)s to login into Kimchi" msgstr "指定登录Kimchiçš„%(item)s" #, python-format msgid "User %(user_id)s not found with given LDAP settings." msgstr "使用指定的LDAPé…置未找到%(user_id)s用户" #, python-format msgid "Invalid LDAP configuration: %(item)s : %(value)s" msgstr "无效的LDAPé…置:%(item)s : %(value)s" msgid "Unknown \"_cap\" specified" msgstr "未识别的\"_cap\"" msgid "\"_passthrough\" should be \"true\" or \"false\"" msgstr "\"_passthrough\"值应为\"true\"或者\"false\"" msgid "\"_passthrough_affected_by\" should be a device name string" msgstr "\"_passthrough_affected_by\"应为一个字符串型设备å" #, python-format msgid "Error while getting block devices. Details: %(err)s" msgstr "获å–å—设备时出错。详情:%(err)s" #, python-format msgid "Error while getting block device information for %(device)s." msgstr "获å–å—设备 %(device)s ä¿¡æ¯æ—¶å‡ºé”™ã€‚" #, python-format msgid "Unable to find distro file: %(filename)s" msgstr "找ä¸åˆ°å‘行版文件:%(filename)s" #, python-format msgid "" "Unable to parse distro file: %(filename)s. Make sure, it is a JSON file." msgstr "ä¸èƒ½è§£æžå‘行版文件:%(filename)s。请确ä¿å®ƒæ˜¯ä¸€ä¸ªJSONæ ¼å¼çš„æ–‡ä»¶ã€‚" #, python-format msgid "Unable to login to iSCSI host target %(portal)s. Details: %(err)s" msgstr "无法通过 %(portal)s 登录iSCSI主机和目标。详情:%(err)s" #, python-format msgid "Unable to login to iSCSI host %(host)s target %(target)s" msgstr "无法登录iSCSI主机%(host)s上的目标%(target)s。" #, python-format msgid "Unable to find ISO file %(filename)s" msgstr "未能找到ISO文件 %(filename)s" #, python-format msgid "The ISO file %(filename)s is not bootable" msgstr "ISO文件%(filename)sä¸å¯å¼•导。" #, python-format msgid "The ISO file %(filename)s does not have a valid El Torito boot record" msgstr "ISO文件%(filename)s没有有效的El Torito引导记录。" #, python-format msgid "Invalid El Torito validation entry in ISO %(filename)s" msgstr "在ISO文件%(filename)s中å‘现无效的El Torito校验æ¡ç›®ã€‚。" #, python-format msgid "Invalid El Torito boot indicator in ISO %(filename)s" msgstr "ISO文件%(filename)sçš„El Torito引导标志是无效的" #, python-format msgid "Unexpected volume type for primary volume in ISO %(filename)s" msgstr "未能识别ISO文件%(filename)s的主å·ç±»åž‹" #, python-format msgid "Bad format while reading volume descriptor in ISO %(filename)s" msgstr "ISO文件%(filename)sçš„å·æè¿°ç¬¦æ ¼å¼é”™è¯¯" #, python-format msgid "" "The hypervisor doesn't have permission to use this ISO %(filename)s. " "Consider moving it under /var/lib/libvirt, or set the search permission to " "file access control lists for '%(user)s' user if possible, or add the " "'%(user)s' to the ISO path group, or (not recommended) 'chmod -R o+x " "'path_to_iso'.Details: %(err)s" msgstr "" "hypervisor没有访问ISO文件%(filename)sçš„æƒé™ã€‚å¯ä»¥å°†ISO移到/var/lib/libvirtç›®" "录下;或为'%(user)s'用户设置访问æƒé™ï¼›æˆ–å°†'%(user)s'用户增加到ISO路径的属组;" "或者为所有的用户增加访问æƒé™ 'chmod -R o+x 'ï¼ˆä¸æŽ¨è)。详情:%(err)s" msgid "An error occurred when probing image OS information." msgstr "æœç´¢é•œåƒæ“ä½œç³»ç»Ÿä¿¡æ¯æ—¶å‘生错误。" msgid "No OS information found in given image." msgstr "åœ¨æŒ‡å®šçš„é•œåƒæ–‡ä»¶ä¸­æœªå‘现æ“作系统信æ¯ã€‚" #, python-format msgid "Unable to read image file %(filename)s" msgstr "未能读å–é•œåƒæ–‡ä»¶ %(filename)s" #, python-format msgid "" "Image file must be an existing file on system. %(filename)s is not a valid " "input." msgstr "ç£ç›˜æ–‡ä»¶å¿…须已存在系统中,%(filename)s䏿˜¯åˆæ³•文件å" #, python-format msgid "Virtual machine %(name)s already exists" msgstr "虚拟机%(name)så·²ç»å­˜åœ¨" #, python-format msgid "Virtual machine %(name)s does not exist" msgstr "虚拟机%(name)sä¸å­˜åœ¨" #, python-format msgid "" "Unable to rename virtual machine %(name)s. The name %(new_name)s is already " "in use or the virtual machine is not powered off." msgstr "" "未能实现虚拟机 %(name)s é‡å‘½å,åç§° %(new_name)s 已被使用或者该虚拟机未关" "机。" #, python-format msgid "Unable to retrieve screenshot for stopped virtual machine %(name)s" msgstr "ä¸èƒ½èŽ·å–åœæ­¢çжæ€çš„虚拟机%(name)s的截å±" msgid "Remote ISO image is not supported by this server." msgstr "该æœåС噍䏿”¯æŒè¿œç¨‹ISO镜åƒã€‚" #, python-format msgid "Screenshot is not supported on virtual machine %(name)s" msgstr "虚拟机 %(name)s 䏿”¯æŒå¿«ç…§" #, python-format msgid "Unable to create virtual machine %(name)s. Details: %(err)s" msgstr "ä¸èƒ½åˆ›å»ºè™šæ‹Ÿæœº%(name)s。详情:%(err)s" #, python-format msgid "Unable to update virtual machine %(name)s. Details: %(err)s" msgstr "ä¸èƒ½æ›´æ–°è™šæ‹Ÿæœº%(name)s。详情:%(err)s" #, python-format msgid "Unable to retrieve virtual machine %(name)s. Details: %(err)s" msgstr "ä¸èƒ½èŽ·å–虚拟机%(name)s。详情:%(err)s" #, python-format msgid "Unable to connect to powered off virtual machine %(name)s." msgstr "虚拟机%(name)s已关机,连接失败。" msgid "Virtual machine name must be a string without slashes (/)" msgstr "" #, python-format msgid "Invalid template URI %(value)s specified for virtual machine" msgstr "无效的虚拟机模æ¿URI %(value)s" #, python-format msgid "Invalid storage pool URI %(value)s specified for virtual machine" msgstr "无效的虚拟机存储池URI %(value)s" msgid "Supported virtual machine graphics are Spice or VNC" msgstr "虚拟机图形界é¢ä»…支æŒSpice以åŠVNC" msgid "Graphics address to listen on must be IPv4 or IPv6" msgstr "远程图形访问的监å¬åœ°å€å¿…须是IPv4或IPv6地å€ã€‚" msgid "Specify a template to create a virtual machine from" msgstr "指定用于创建虚拟机的模æ¿" #, python-format msgid "Unable to start virtual machine %(name)s. Details: %(err)s" msgstr "ä¸èƒ½å¯åŠ¨è™šæ‹Ÿæœº %(name)s. 详情:%(err)s" #, python-format msgid "Unable to power off virtual machine %(name)s. Details: %(err)s" msgstr "ä¸èƒ½å…³é—­è™šæ‹Ÿæœº%(name)s。详情:%(err)s" #, python-format msgid "Unable to delete virtual machine %(name)s. Details: %(err)s" msgstr "ä¸èƒ½åˆ é™¤è™šæ‹Ÿæœº %(name)s。详情:%(err)s" #, python-format msgid "Unable to reset virtual machine %(name)s. Details: %(err)s" msgstr "未能é‡ç½®è™šæ‹Ÿæœº%(name)s。详情:%(err)s" msgid "User name list must be an array" msgstr "用户å列表必须为一个数组" msgid "User name must be a string" msgstr "用户å必须是一个字符串" msgid "Group name list must be an array" msgstr "组å称列表必须为一个数组" msgid "Group name must be a string" msgstr "用户组å称必须是一个字符串" #, python-format msgid "User(s) '%(users)s' do not exist" msgstr "用户'%(users)s'ä¸å­˜åœ¨" #, python-format msgid "Group(s) '%(groups)s' do not exist" msgstr "用户组'%(groups)s'ä¸å­˜åœ¨" #, python-format msgid "Unable to shutdown virtual machine %(name)s. Details: %(err)s" msgstr "未能关闭虚拟机%(name)s。详情:%(err)s" #, python-format msgid "" "Unable to get access metadata of virtual machine %(name)s. Details: %(err)s" msgstr "无法获得虚拟机 %(name)s的元数æ®ï¼Œè¯¦æƒ…:%(err)s" msgid "The guest console password must be a string." msgstr "客户机控制å°å¯†ç å¿…须为一个字符串。" msgid "The life time for the guest console password must be a number." msgstr "å®¢æˆ·æœºå‘½ä»¤è¡Œå¯†ç æœ‰æ•ˆæ—¶é—´å¿…须是一个数字。" #, python-format msgid "Virtual machine '%(name)s' must be stopped before cloning it." msgstr "虚拟机'%(name)s'在制作副本å‰å¿…须关机。" #, python-format msgid "Insufficient disk space to clone virtual machine '%(name)s'" msgstr "制作虚拟机'%(name)s'副本所需的ç£ç›˜ç©ºé—´ä¸è¶³" #, python-format msgid "Unable to clone VM '%(name)s'. Details: %(err)s" msgstr "未能æˆåŠŸåˆ¶ä½œè™šæ‹Ÿæœº'%(name)s'副本。详情:%(err)s" #, python-format msgid "Invalid operation for non-persistent virtual machine %(name)s" msgstr "" #, python-format msgid "Cannot suspend VM '%(name)s' because it is not running." msgstr "" #, python-format msgid "Unable to suspend VM '%(name)s'. Details: %(err)s" msgstr "" #, python-format msgid "Cannot resume VM '%(name)s' because it is not paused." msgstr "" #, python-format msgid "Unable to resume VM '%(name)s'. Details: %(err)s" msgstr "" msgid "Memory assigned is higher then the maximum allowed in the host." msgstr "" #, python-format msgid "" "VM '%(name)s' does not support live memory update. Update the memory with " "the machine offline to enable this feature." msgstr "" msgid "Only increase memory is allowed in active VMs" msgstr "" msgid "" "For live memory update, new memory value must be equal old memory value plus " "multiples of 1024 Mib" msgstr "" msgid "There are not enough free slots of 1024 Mib in the guest." msgstr "" msgid "" "Host's libvirt version does not support memory devices. Libvirt must be >= " "1.2.14" msgstr "" #, python-format msgid "Error attaching memory device. Details: %(error)s" msgstr "" #, python-format msgid "" "VM %(vmid)s does not contain directly assigned host device %(dev_name)s." msgstr "虚拟机%(vmid)s未指明被分é…的主机设备%(dev_name)s。" #, python-format msgid "The host device %(dev_name)s is not allowed to directly assign to VM." msgstr "主机设备%(dev_name)sä¸å…许直接分é…给虚拟机。" msgid "" "No IOMMU groups found. Host PCI pass through needs IOMMU group to function " "correctly. Please enable Intel VT-d or AMD IOMMU in your BIOS, then verify " "the Kernel is compiled with IOMMU support. For Intel CPU, add intel_iommu=on " "to your Kernel parameter in /boot/grub2/grub.conf. For AMD CPU, add iommu=pt " "iommu=1." msgstr "" "未找到IOMMU groups。主机PCI pass through需è¦IOMMU groupæ‰å¯ä»¥æ­£ç¡®å·¥ä½œã€‚请在" "BIOS设置里将Intel VT-d 或者 AMD IOMMU 设为使能,而åŽç¡®è®¤å†…核支æŒIOMMU。对于" "Intel CPU,在路径/boot/grub2/grub.conf中添加内核å˜é‡intel_iommu=on。对于AMD " "CPU,则添加iommu=pt iommu=1。" msgid "\"name\" should be a device name string" msgstr "\"name\"应该为一个字符串型的设备å" #, python-format msgid "" "The device %(name)s is probably in use by the host. Unable to attach it to " "the guest." msgstr "" #, python-format msgid "Interface %(iface)s does not exist in virtual machine %(name)s" msgstr "虚拟机 %(name)s ä¸­æ²¡æœ‰æŽ¥å£ %(iface)s" #, python-format msgid "" "Network %(network)s specified for virtual machine %(name)s does not exist" msgstr "为虚拟机%(name)s指定的网络%(network)sä¸å­˜åœ¨" msgid "Supported virtual machine interfaces type is only network" msgstr "åªæ”¯æŒç½‘络类型的虚拟机接å£" msgid "Network name for virtual machine interface must be a string" msgstr "虚拟机接å£çš„网络å字必须是字符串" msgid "Invalid network model card specified for virtual machine interface" msgstr "è™šæ‹ŸæœºæŽ¥å£æŒ‡å®šçš„ç½‘ç»œæ¨¡åž‹å¡æ— æ•ˆ" msgid "Specify type and network to add a new virtual machine interface" msgstr "ä¸ºæ–°çš„è™šæ‹ŸæœºæŽ¥å£æŒ‡å®šç±»åž‹å’Œç½‘络" msgid "MAC Address must respect this format FF:FF:FF:FF:FF:FF" msgstr "" #, python-format msgid "MAC Address %(mac)s already exists in virtual machine %(name)s" msgstr "" msgid "Invalid MAC Address" msgstr "" msgid "Cannot change MAC address of a running virtual machine" msgstr "" #, python-format msgid "Template %(name)s already exists" msgstr "æ¨¡æ¿ %(name)s å·²ç»å­˜åœ¨" #, python-format msgid "" "Network '%(network)s' specified for template %(template)s does not exist" msgstr "ä¸ºæ¨¡æ¿ %(template)s 指定的网络 '%(network)s' ä¸å­˜åœ¨" #, python-format msgid "" "Storage pool %(pool)s specified for template %(template)s does not exist" msgstr "ä¸ºæ¨¡æ¿ %(template)s 指定的存储池 '%(pool)s' ä¸å­˜åœ¨" #, python-format msgid "Storage pool %(pool)s specified for template %(template)s is not active" msgstr "ä¸ºæ¨¡æ¿ %(template)s 指定的存储池 '%(pool)s' 没有激活" #, python-format msgid "Invalid parameter '%(param)s' specified for CDROM." msgstr "为CDROMæŒ‡å®šçš„å‚æ•° '%(param)s' 无效" #, python-format msgid "Network %(network)s specified for template %(template)s is not active" msgstr "ä¸ºæ¨¡æ¿ %(template)s 指定的网络 '%(network)s' 没有激活" msgid "Template name must be a string" msgstr "模æ¿çš„å字必须是一个字符串" msgid "Template icon must be a path to the image" msgstr "模æ¿çš„图标必须是一个指å‘镜åƒçš„路径" msgid "Template distribution must be a string" msgstr "模æ¿çš„å‘行版必须是一个字符串" msgid "Template distribution version must be a string" msgstr "模æ¿çš„å‘行版版本å·å¿…须是一个字符串" msgid "The number of CPUs must be an integer greater than 0" msgstr "CPUæ•°é‡å¿…须为一个大于0的整数" msgid "Amount of memory (MB) must be an integer greater than 512" msgstr "总内存数(MB为å•ä½ï¼‰å¿…须是一个大于512的整数" msgid "Template CDROM must be a local or remote ISO file" msgstr "模æ¿çš„CDROM必须是一个本地或者远程的ISO文件" #, python-format msgid "Invalid storage pool URI %(value)s specified for template" msgstr "ç»™æ¨¡æ¿æŒ‡å®šäº†æ— æ•ˆçš„存储池URI %(value)s" msgid "Specify an ISO image as CDROM or a base image to create a template" msgstr "指定一个ISO镜åƒä½œä¸ºåˆ›å»ºæ¨¡æ¿çš„CDROM或者基础镜åƒ" msgid "All networks for the template must be specified in a list." msgstr "ä¸ºæ¨¡æ¿æŒ‡å®šçš„网络必须在一个列表中" msgid "Specify a volume to a template when storage pool is iSCSI or SCSI" msgstr "当存储池类型为iSCSI或者SCSIçš„æ—¶å€™é¡»ä¸ºæ¨¡æ¿æŒ‡å®šä¸€ä¸ªå·" #, python-format msgid "The volume %(volume)s is not in storage pool %(pool)s" msgstr "å·%(volume)sä¸åœ¨å­˜å‚¨æ± %(pool)s中" #, python-format msgid "Unable to create template due error: %(err)s" msgstr "创建模æ¿å¤±è´¥ã€‚详情:%(err)s" #, python-format msgid "Unable to delete template due error: %(err)s" msgstr "由于错误:%(err)s,未能删除模æ¿" msgid "Disk size must be an integer greater than 1GB." msgstr "ç£ç›˜å¤§å°å¿…须大于1GB。" msgid "Template base image must be a valid local image file" msgstr "模æ¿åŸºç¡€é•œåƒå¿…é¡»ä¸ºä¸€ä¸ªæœ‰æ•ˆçš„æœ¬åœ°é•œåƒæ–‡ä»¶" #, python-format msgid "Cannot identify base image %(path)s format" msgstr "未能识别基础镜åƒ%(path)sæ ¼å¼" msgid "" "When specifying CPU topology, VCPUs must be a product of sockets, cores, and " "threads." msgstr "CPU拓扑中,VCPUs必须包括sockets, cores 以åŠthreads。" msgid "" "When specifying CPU topology, each element must be an integer greater than " "zero." msgstr "CPU拓扑中,æ¯ä¸€ä¸ªå‚数必须为大于零的整数。" msgid "" "Invalid disk image format. Valid formats: bochs, cloop, cow, dmg, qcow, " "qcow2, qed, raw, vmdk, vpc." msgstr "" "无效的ç£ç›˜é•œåƒæ ¼å¼ã€‚有效的格å¼ä¸ºï¼šbochs, cloop, cow, dmg, qcow, qcow2, qed, " "raw, vmdk, vpc。" #, python-format msgid "Storage pool %(name)s already exists" msgstr "存储池%(name)så·²ç»å­˜åœ¨" #, python-format msgid "Storage pool %(name)s does not exist" msgstr "存储池%(name)sä¸å­˜åœ¨" #, python-format msgid "Specify %(item)s in order to create the storage pool %(name)s" msgstr "为新存储池%(name)s指定%(item)s" #, python-format msgid "Unable to delete active storage pool %(name)s" msgstr "ä¸èƒ½åˆ é™¤æ¿€æ´»çš„存储池 %(name)s" #, python-format msgid "Unable to list storage pools. Details: %(err)s" msgstr "ä¸èƒ½åˆ—举存储池。 详情: %(err)s" #, python-format msgid "Unable to create storage pool %(name)s. Details: %(err)s" msgstr "ä¸èƒ½åˆ›å»ºå­˜å‚¨æ±  %(name)s。详情: %(err)s" #, python-format msgid "" "Unable to get number of storage volumes in storage pool %(name)s. Details: " "%(err)s" msgstr "ä¸èƒ½èŽ·å–储存池%(name)s中å·çš„æ•°ç›®ã€‚详情: %(err)s" #, python-format msgid "Unable to activate storage pool %(name)s. Details: %(err)s" msgstr "ä¸èƒ½æ¿€æ´»å‚¨å­˜æ± %(name)s。详情: %(err)s" #, python-format msgid "Unable to deactivate storage pool %(name)s. Details: %(err)s" msgstr "ä¸èƒ½åœç”¨å‚¨å­˜æ± %(name)s。详情: %(err)s" #, python-format msgid "Unable to delete storage pool %(name)s. Details: %(err)s" msgstr "ä¸èƒ½åˆ é™¤å‚¨å­˜æ± %(name)s。详情: %(err)s" #, python-format msgid "" "Unable to create NFS Pool as export path %(path)s may block during mount" msgstr "ä¸èƒ½åˆ›å»ºNFS存储池,å¯èƒ½å¯¼å‡ºè·¯å¾„%(path)s在挂载时被阻塞了" #, python-format msgid "Unable to create NFS Pool as export path %(path)s mount failed" msgstr "ä¸èƒ½åˆ›å»ºNFS存储池,挂载导出路径%(path)s失败" #, python-format msgid "Unsupported storage pool type: %(type)s" msgstr "䏿”¯æŒçš„存储池类型:%(type)s" #, python-format msgid "Error while retrieving storage pool XML to %(pool)s" msgstr "查询存储池XML到%(pool)s时出现错误" msgid "Storage pool name must be a string without slashes (/)" msgstr "" msgid "" "Supported storage pool types are dir, netfs, logical, iscsi, isci and kimchi-" "iso" msgstr "存储池类型仅支æŒdir,netfs,logical,iscsi,isci以åŠkimchi-iso" msgid "Storage pool path must be a string" msgstr "存储池路径必须是字符串" msgid "Storage pool host must be a IP or hostname" msgstr "存储池主机必须是一个IPåŽè€…主机å" msgid "Storage pool device must be the absolute path to the block device" msgstr "存储池设备必须为å—设备的一个ç»å¯¹è·¯å¾„" msgid "Storage pool devices parameter must be a list" msgstr "å­˜å‚¨æ± è®¾å¤‡å‚æ•°å¿…须是一个列表" msgid "Target IQN of an iSCSI pool must be a string" msgstr "iSCSI存储池的目标IQN必须是字符串" msgid "Port of a remote storage server must be an integer between 1 and 65535" msgstr "远程存储æœåŠ¡å™¨çš„ç«¯å£å¿…须是1到65535之间的整数" msgid "iSCSI target username must be a string" msgstr "iSCSI目标用户å必须为一个字符串" msgid "iSCSI target password must be a string" msgstr "iSCSI目标密ç å¿…须为一个字符串" msgid "Specify name and type to create a storage pool" msgstr "为新存储池指定å字和类型" #, python-format msgid "" "%(disk)s is not a valid disk/partition. Could not add it to the pool " "%(pool)s." msgstr "%(disk)s 䏿˜¯æœ‰æ•ˆçš„ç£ç›˜/分区。ä¸èƒ½è¢«æ·»åŠ åˆ°å­˜å‚¨æ± %(pool)s中" #, python-format msgid "Unable to extend logical pool %(pool)s. Details: %(err)s" msgstr "未能实现逻辑池%(pool)s的扩展,详情:%(err)s" msgid "The parameter disks only can be updated for logical storage pool." msgstr "åªæœ‰é€»è¾‘å­˜å‚¨æ± æ”¯æŒæ›´æ–°ç£ç›˜å‚数。" msgid "The SCSI host adapter name must be a string." msgstr "SCSI主机适é…器å必须是个字符串" msgid "The storage pool kimchi_isos is reserved for internal use" msgstr "存储池kimchi_isos留作内部使用" #, python-format msgid "" "Unable to activate NFS storage pool %(name)s. NFS server %(server)s is " "unreachable." msgstr "ä¸èƒ½æ¿€æ´»NFS存储池%(name)s。NFSæœåС噍%(server)sä¸å¯åˆ°è¾¾ã€‚" #, python-format msgid "" "Unable to deactivate NFS storage pool %(name)s. NFS server %(server)s is " "unreachable." msgstr "ä¸èƒ½åœç”¨NFS存储池%(name)s。NFSæœåС噍%(server)sä¸å¯åˆ°è¾¾ã€‚" #, python-format msgid "" "Unable to deactivate pool %(name)s as it is associated with some templates" msgstr "ä¸èƒ½åœç”¨å­˜å‚¨æ± %(name)s,该存储池与一些模æ¿å…³è”" #, python-format msgid "Unable to delete pool %(name)s as it is associated with some templates" msgstr "ä¸èƒ½åˆ é™¤å­˜å‚¨æ± %(name)s,该存储池与一些模æ¿å…³è”" #, python-format msgid "" "A volume group named '%(name)s' already exists. Please, choose another name " "to create the logical pool." msgstr "å·ç»„'%(name)s'å·²ç»å­˜åœ¨ï¼Œè¯·é€‰æ‹©å…¶å®ƒçš„åå­—æ¥åˆ›å»ºé€»è¾‘存储池。" #, python-format msgid "Unable to update database with deep scan information due error: %(err)s" msgstr "全盘扫æä¿¡æ¯æ›´æ–°å¤±è´¥ã€‚详情:%(err)s。" #, python-format msgid "Storage volume %(name)s already exists" msgstr "存储å·%(name)så·²ç»å­˜åœ¨" #, python-format msgid "Storage volume %(name)s does not exist in storage pool %(pool)s" msgstr "存储池%(pool)s中没有存储å·%(name)s" #, python-format msgid "" "Unable to create storage volume %(volume)s because storage pool %(pool)s is " "not active" msgstr "未能创建存储å·%(volume)s,因为存储池%(pool)s 未被激活" #, python-format msgid "Specify %(item)s in order to create storage volume %(volume)s" msgstr "为新存储å·%(volume)s指定指定%(item)s" #, python-format msgid "" "Unable to list storage volumes because storage pool %(pool)s is not active" msgstr "ä¸èƒ½åˆ—出存储å·ï¼Œå› ä¸ºå­˜å‚¨æ± %(pool)s没有激活" #, python-format msgid "" "Unable to create storage volume %(name)s in storage pool %(pool)s. Details: " "%(err)s" msgstr "ä¸èƒ½åœ¨å­˜å‚¨æ± %(pool)s中创建存储å·%(name)s。详情:%(err)s" #, python-format msgid "" "Unable to list storage volumes in storage pool %(pool)s. Details: %(err)s" msgstr "ä¸èƒ½åœ¨å­˜å‚¨æ± %(pool)s中列出存储å·ã€‚详情:%(err)s" #, python-format msgid "Unable to wipe storage volumes %(name)s. Details: %(err)s" msgstr "ä¸èƒ½æ“¦é™¤å­˜å‚¨å·%(name)s。详情:%(err)s" #, python-format msgid "Unable to delete storage volume %(name)s. Details: %(err)s" msgstr "ä¸èƒ½åˆ é™¤å­˜å‚¨å·%(name)s。详情:%(err)s" #, python-format msgid "Unable to resize storage volume %(name)s. Details: %(err)s" msgstr "ä¸èƒ½æ”¹å˜å­˜å‚¨å·%(name)s的大å°ã€‚详情:%(err)s" #, python-format msgid "Storage type %(type)s does not support volume create and delete" msgstr "存储类型%(type)s䏿”¯æŒå·çš„创建和删除" msgid "Storage volume name must be a string" msgstr "存储å·çš„å字必须是字符串" msgid "Storage volume allocation must be an integer number" msgstr "存储å·åˆ†é…é¢å¿…须是整数" msgid "" "Storage volume format not supported. Valid formats: bochs, cloop, cow, dmg, " "qcow, qcow2, qed, raw, vmdk, vpc." msgstr "" "䏿”¯æŒè¯¥å­˜å‚¨å·æ ¼å¼ï¼Œæ”¯æŒçš„æ ¼å¼ï¼šbochs, cloop, cow, dmg, qcow, qcow2, qed, " "raw, vmdk, vpc。" msgid "Storage volume requires a volume name" msgstr "存储å·éœ€è¦åå­—" #, python-format msgid "" "Unable to update database with storage volume information due error: %(err)s" msgstr "存储å·ä¿¡æ¯æ›´æ–°å¤±è´¥ã€‚详情:%(err)s" #, python-format msgid "Only one of parameter %(param)s can be specified" msgstr "åªèƒ½å¯¹å‚æ•°%(param)s中的一个进行指定" #, python-format msgid "Create volume from %(param)s is not supported" msgstr "䏿”¯æŒä»Ž%(param)s创建虚拟机" msgid "Storage volume capacity must be an integer number." msgstr "存储å·å®¹é‡å¿…须为一个整数" msgid "Storage volume URL must be http://, https://, ftp:// or ftps://." msgstr "存储å·URL必须为http://,https://,ftp://或ftps://" #, python-format msgid "Unable to access file %(url)s. Please, check it." msgstr "ä¸èƒ½è®¿é—®æ–‡ä»¶%(url)s,请检查该文件是å¦å­˜åœ¨ã€‚" #, python-format msgid "" "Unable to clone storage volume '%(name)s' in pool '%(pool)s'. Details: " "%(err)s" msgstr "未能于存储池'%(pool)s'制作存储å·'%(name)s'的副本,详情:%(err)s" msgid "Specify chunk data and its size to upload a file." msgstr "" msgid "In order to upload a storage volume, specify the 'upload' parameter." msgstr "" msgid "" "Unable to upload chunk data as it does not match with requested chunk size." msgstr "" #, python-format msgid "The storage volume %(vol)s is not under an upload process." msgstr "" msgid "The upload chunk data will exceed the storage volume size." msgstr "" #, python-format msgid "Unable to upload chunk data to storage volume. Details: %(err)s." msgstr "" #, python-format msgid "Interface %(name)s does not exist" msgstr "接å£%(name)sä¸å­˜åœ¨" #, python-format msgid "Network %(name)s already exists" msgstr "网络%(name)så·²ç»å­˜åœ¨" #, python-format msgid "Network %(name)s does not exist" msgstr "网络%(name)sä¸å­˜åœ¨" #, python-format msgid "Subnet %(subnet)s specified for network %(network)s is not valid." msgstr "给网络%(network)s指定的å­ç½‘%(subnet)s无效" #, python-format msgid "Specify a network interface to create bridged network %(name)s" msgstr "æŒ‡å®šä¸€ä¸ªç½‘ç»œæŽ¥å£æ¥åˆ›å»ºæ¡¥æŽ¥ç±»åž‹çš„网络%(name)s" #, python-format msgid "Unable to delete active network %(name)s" msgstr "ä¸èƒ½åˆ é™¤æ¿€æ´»çš„网络%(name)s" #, python-format msgid "Interface %(iface)s specified for network %(network)s is already in use" msgstr "给网络%(network)s指定的接å£%(iface)s已被使用" msgid "Interface should be bare NIC, bonding or bridge device." msgstr "接å£åº”该是一个裸的网络接å£å¡ã€bonding或者桥接设备。" #, python-format msgid "Unable to create network %(name)s. Details: %(err)s" msgstr "ä¸èƒ½åˆ›å»ºç½‘络%(name)s。详情:%(err)s" #, python-format msgid "Unable to find a free IP address for network '%(name)s'" msgstr "ä¸èƒ½ä¸ºç½‘络'%(name)s'找到一个未使用的IP网络地å€ã€‚" #, python-format msgid "The interface %(iface)s already exists." msgstr "" msgid "Network name must be a string without slashes (/) or quotes (\")" msgstr "" msgid "Supported network types are isolated, NAT and bridge" msgstr "支æŒçš„网络类型有隔离ã€NAT和桥接" msgid "Network subnet must be a string with IP address and prefix or netmask" msgstr "网络å­ç½‘必须是一个IP地å€åŠ ç½‘ç»œå‰ç¼€æˆ–å­ç½‘掩ç çš„字符串" msgid "Network interface must be a string" msgstr "网络接å£å¿…须是一个字符串" msgid "Network VLAN ID must be an integer between 1 and 4094" msgstr "网络VLANå·å¿…须是1到4094之间的整数" msgid "Specify name and type to create a Network" msgstr "为新网络指定å字和类型" #, python-format msgid "" "Unable to delete network %(name)s. There are some virtual machines %(vms)s " "and/or templates linked to this network." msgstr "" #, python-format msgid "" "Unable to deactivate network %(name)s. There are some virtual machines " "%(vms)s and/or templates linked to this network." msgstr "" #, python-format msgid "Bridge device %(name)s can not be the trunk device of a VLAN." msgstr "ä¸èƒ½ä»¥æ¡¥è®¾å¤‡%(name)s作为VLANçš„trunk设备。" #, python-format msgid "Failed to activate interface %(iface)s: %(err)s." msgstr "网络接å£å¯åŠ¨å¤±è´¥ %(iface)s:%(err)s。" #, python-format msgid "" "Failed to activate interface %(iface)s. Please check the physical link " "status." msgstr "网络接å£%(iface)så¯åŠ¨å¤±è´¥ï¼Œè¯·æ£€æŸ¥ç½‘ç»œè¿žæŽ¥æƒ…å†µã€‚" #, python-format msgid "Failed to start network %(name)s. Details: %(err)s" msgstr "å¯åŠ¨ç½‘ç»œ%(name)s失败,详情:%(err)s" #, python-format msgid "Debug report %(name)s does not exist" msgstr "诊断报告%(name)sä¸å­˜åœ¨" msgid "Debug report tool not found in system" msgstr "系统上没有诊断报告工具" #, python-format msgid "Unable to create debug report %(name)s. Details: %(err)s." msgstr "ä¸èƒ½åˆ›å»ºè¯Šæ–­æŠ¥å‘Š%(name)s。详情:%(err)s" #, python-format msgid "Can not find any debug report with the given name %(name)s" msgstr "未能找到指定åç§°%(name)s的调试报告" #, python-format msgid "Unable to generate debug report %(name)s. Details: %(err)s" msgstr "ä¸èƒ½ç”Ÿæˆè¯Šæ–­æŠ¥å‘Š%(name)s。详情:%(err)s" msgid "You should give a name for the debug report file." msgstr "ä¸èƒ½ç”Ÿæˆè¯Šæ–­æŠ¥å‘Š%(name)s。详情:%(err)s" msgid "" "Debug report name must be a string. Only letters, digits, underscore ('_') " "and hyphen ('-') are allowed." msgstr "" "调试报告åç§°å¿…é¡»ä¸ºä¸€ä¸ªå­—ç¬¦ä¸²ã€‚åªæœ‰è‹±æ–‡å­—符,数字,下划线('_')以åŠè¿žå­—符('-')" "ä¸ºåˆæ³•字符。" #, python-format msgid "" "The debug report with specified name \"%(name)s\" already exists. Please use " "another one." msgstr "å字为\"'%(name)s\"的调试报告已ç»å­˜åœ¨ï¼Œè¯·é€‰æ‹©å…¶å®ƒçš„å字。" #, python-format msgid "Storage server %(server)s was not used by Kimchi" msgstr "存储æœåС噍%(server)s未被Kimchi使用" #, python-format msgid "Distro '%(name)s' does not exist" msgstr "å‘行版本'%(name)s'ä¸å­˜åœ¨" #, python-format msgid "Partition %(name)s does not exist in the host" msgstr "主机中上没有分区%(name)s" msgid "Unable to shutdown host machine as there are running virtual machines" msgstr "有虚拟机在è¿è¡Œï¼Œä¸èƒ½å…³é—­ä¸»æœº" msgid "Unable to reboot host machine as there are running virtual machines" msgstr "有虚拟机在è¿è¡Œï¼Œä¸èƒ½é‡èµ·ä¸»æœº" #, python-format msgid "Node device '%(name)s' not found" msgstr "没有找到节点设备'%(name)s'" msgid "Conflicting flag filters specified." msgstr "flag filters冲çªã€‚" msgid "No packages marked for update" msgstr "没有软件包标识è¦å‡çº§" #, python-format msgid "Package %(name)s is not marked to be updated." msgstr "软件包%(name)s没有标识为è¦å‡çº§" #, python-format msgid "Error while getting packages marked to be updated. Details: %(err)s" msgstr "èŽ·å–æ ‡è¯†ä¸ºè¦å‡çº§çš„软件包时出错。详情:%(err)s" msgid "There is no compatible package manager for this system." msgstr "系统上没有兼容的软件包管ç†å™¨" #, python-format msgid "Unable to find %(item)s in datastore" msgstr "在数æ®å­˜å‚¨ä¸­æ‰¾ä¸åˆ°%(item)s" #, python-format msgid "Invalid URI %(uri)s" msgstr "无效的URI %(uri)s" #, python-format msgid "Timeout while running command '%(cmd)s' after %(seconds)s seconds" msgstr "命令'%(cmd)s'è¿è¡Œ%(seconds)sç§’åŽè¶…时。" msgid "Unable to choose a virtual machine name" msgstr "未能选择一个虚拟机åç§°" #, python-format msgid "Invalid data value '%(value)s'" msgstr "" #, python-format msgid "Invalid data unit '%(unit)s'" msgstr "" msgid "Invalid storage type. Types supported: 'cdrom', 'disk'" msgstr "无效的存储类型。支æŒç±»åž‹ä¸ºï¼š'cdrom','disk'" #, python-format msgid "The path '%(value)s' is not a valid local/remote path for the device" msgstr "路径'%(value)s'䏿˜¯è®¾å¤‡çš„æœ‰æ•ˆæœ¬åœ°/远程路径" msgid "Only CDROM path can be update." msgstr "仅支æŒCDROM路径更新。" #, python-format msgid "" "The storage device %(dev_name)s does not exist in the virtual machine " "%(vm_name)s" msgstr "存储设备%(dev_name)s在虚拟机%(vm_name)s中ä¸å­˜åœ¨" #, python-format msgid "Error while creating new storage device: %(error)s" msgstr "创建新的存储设备时出错:%(error)s" #, python-format msgid "Error while updating storage device: %(error)s" msgstr "更新存储设备时出错:%(error)s" #, python-format msgid "Error while removing storage device: %(error)s" msgstr "移除存储设备时出错:%(error)s" msgid "Do not support IDE device hot plug" msgstr "䏿”¯æŒIDEè®¾å¤‡çš„çƒ­æ’æ‹”" msgid "" "Specify type and path or type and pool/volume to add a new virtual machine " "disk" msgstr "为添加新建虚拟机ç£ç›˜æŒ‡å®šç±»åž‹å’Œè·¯å¾„或者类型和存储池/存储å·" msgid "Specify path to update virtual machine disk" msgstr "指定更新虚拟机ç£ç›˜çš„路径" #, python-format msgid "Controller type %(type)s limitation of %(limit)s devices reached" msgstr "控制器类型为%(type)s的设备达到上é™%(limit)s" #, python-format msgid "Cannot retrieve disk path information for given pool/volume: %(error)s" msgstr "未能为给出的存储池/å­˜å‚¨å·æ‰¾åˆ°å¯¹åº”ç£ç›˜è·¯å¾„ä¿¡æ¯ï¼š%(error)s" msgid "Volume already in use by other virtual machine." msgstr "该å·å·²ç»è¢«å…¶ä»–虚拟机使用。" msgid "" "Only one of path or pool/volume can be specified to add a new virtual " "machine disk" msgstr "增加虚拟机ç£ç›˜æ—¶ï¼Œä»…能指定路径或存储池/存储å·ä¸­çš„一个" #, python-format msgid "" "Volume chosen with format %(format)s does not fit in the storage type " "%(type)s" msgstr "æ ¼å¼ä¸º%(format)sçš„å·ä¸ç¬¦åˆå­˜å‚¨ç±»åž‹%(type)s" msgid "YUM Repository ID must be one word only string." msgstr "YUM软件仓库ID必须是åªåŒ…å«ä¸€ä¸ªå•è¯çš„字符串" msgid "Repository URL must be an http://, ftp:// or file:// URL." msgstr "软件仓库URL必须是http://〠ftp:// 或 file://" msgid "" "Repository configuration is a dictionary with specific values according to " "repository type." msgstr "软件仓库é…置是一个与仓库键和特定值对应的字典" msgid "Distribution to DEB repository must be a string" msgstr "DEB仓库的å‘行版本必须是一个字符串" msgid "Components to DEB repository must be listed in a array" msgstr "DEB仓库的组件必须以数组形å¼åˆ—出" msgid "Components to DEB repository must be a string" msgstr "DEB仓库的组件必须是一个字符串" msgid "Mirror list to repository must be a string" msgstr "" msgid "YUM Repository name must be string." msgstr "YUM仓库的å字必须是一个字符串" msgid "GPG check must be a boolean value." msgstr "GPG校验必须是一个布尔值" msgid "GPG key must be a URL pointing to the ASCII-armored file." msgstr "GPG键必须是一个指å‘ASCII转义文件(.asc文件)的URL" #, python-format msgid "Could not update repository %(repo_id)s." msgstr "ä¸èƒ½æ›´æ–°è½¯ä»¶ä»“库%(repo_id)s" #, python-format msgid "Repository %(repo_id)s does not exist." msgstr "软件仓库%(repo_id)sä¸å­˜åœ¨ã€‚" msgid "" "Specify repository base URL, mirror list or metalink in order to create or " "update a YUM repository." msgstr "" msgid "Repository management tool was not recognized for your system." msgstr "您的系统无法识别软件管ç†å·¥å…·" #, python-format msgid "Repository %(repo_id)s is already enabled." msgstr "软件仓库%(repo_id)så·²ç»å¯ç”¨ã€‚" #, python-format msgid "Repository %(repo_id)s is already disabled." msgstr "软件仓库%(repo_id)så·²ç»ç¦ç”¨ã€‚" #, python-format msgid "Could not remove repository %(repo_id)s." msgstr "ä¸èƒ½ç§»é™¤è½¯ä»¶ä»“库%(repo_id)s" #, python-format msgid "Could not write repository configuration file %(repo_file)s" msgstr "无法写软件仓库的é…置文件%(repo_file)s" msgid "Specify repository distribution in order to create a DEB repository." msgstr "指定软件仓库å‘行版本æ¥åˆ›å»ºä¸€ä¸ªDEB仓库。" #, python-format msgid "Could not enable repository %(repo_id)s." msgstr "ä¸èƒ½å¯ç”¨è½¯ä»¶ä»“库%(repo_id)s" #, python-format msgid "Could not disable repository %(repo_id)s." msgstr "ä¸èƒ½ç¦ç”¨è½¯ä»¶ä»“库%(repo_id)s" msgid "YUM Repository ID already exists" msgstr "YUM仓库IDå·²ç»å­˜åœ¨" msgid "YUM Repository name must be a string" msgstr "YUM仓库å字必须是一个字符串" #, python-format msgid "Unable to list repositories. Details: '%(err)s'" msgstr "ä¸èƒ½åˆ—举软件仓库。详情:'%(err)s'" #, python-format msgid "Unable to retrieve repository information. Details: '%(err)s'" msgstr "ä¸èƒ½èŽ·å–软件仓库的信æ¯ã€‚详情:'%(err)s'" #, python-format msgid "Unable to add repository. Details: '%(err)s'" msgstr "ä¸èƒ½å¢žåŠ è½¯ä»¶ä»“åº“ã€‚è¯¦æƒ…ï¼š'%(err)s'" #, python-format msgid "Unable to remove repository. Details: '%(err)s'" msgstr "ä¸èƒ½ç§»é™¤è½¯ä»¶ä»“库。详情:'%(err)s'" #, python-format msgid "" "Configuration items: '%(items)s' are not supported by repository manager" msgstr "è½¯ä»¶ä»“åº“ä¸æ”¯æŒé…置类型: %(items)s" msgid "Repository metalink must be an http://, ftp:// or file:// URL." msgstr "" msgid "Cannot specify mirrorlist and metalink at the same time." msgstr "" #, python-format msgid "" "Virtual machine '%(vm)s' must be stopped before creating a snapshot of it." msgstr "虚拟机'%(vm)s'在制作快照å‰å¿…须关机。" #, python-format msgid "" "Unable to create snapshot '%(name)s' on virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "未能为虚拟机'%(vm)s'制作快照'%(name)s'。详情:%(err)s" #, python-format msgid "Snapshot '%(name)s' does not exist on virtual machine '%(vm)s'." msgstr "å¿«ç…§'%(name)s'ä¸å­˜åœ¨è™šæ‹Ÿæœº'%(vm)s'上。" #, python-format msgid "" "Unable to retrieve snapshot '%(name)s' on virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "未能在虚拟机'%(vm)s'找到快照'%(name)s'。详情:%(err)s" #, python-format msgid "Unable to list snapshots on virtual machine '%(vm)s'. Details: %(err)s" msgstr "未能列出虚拟机'%(vm)s'的快照。详情:%(err)s" #, python-format msgid "" "Unable to delete snapshot '%(name)s' on virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "未能删除虚拟机'%(vm)s'å¿«ç…§'%(name)s'。详情:%(err)s" #, python-format msgid "" "Unable to retrieve current snapshot of virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "未能找到虚拟机'%(vm)s'当å‰å¿«ç…§ã€‚详情:%(err)s" #, python-format msgid "" "Unable to revert virtual machine '%(vm)s' to snapshot '%(name)s'. Details: " "%(err)s" msgstr "未能æ¢å¤è™šæ‹Ÿæœº'%(vm)s'到快照'%(name)s'。详情:%(err)s" #, python-format msgid "" "Unable to create snapshot of virtual machine '%(vm)s' because it contains a " "disk with format '%(format)s'; only 'qcow2' is supported." msgstr "" "未能为虚拟机'%(vm)s'创建快照因为其使用了格å¼ä¸º'%(format)s'çš„ç£ç›˜ï¼›å½“å‰ä»…支" "æŒ'qcow2'æ ¼å¼ã€‚" msgid "The number of vCPUs is too large for this system." msgstr "vCPUs的数é‡å¯¹è¯¥ç³»ç»Ÿè€Œè¨€å¤ªå¤§ã€‚" msgid "Invalid vCPU/topology combination." msgstr "无效的vCPU/topology组åˆã€‚" msgid "This host (or current configuration) does not allow CPU topology." msgstr "当å‰ä¸»æœºï¼ˆæˆ–当å‰é…置)ä¸å…许CPU拓扑。" msgid "ERROR CODE" msgstr "错误ç " msgid "REASON" msgstr "原因" msgid "STACK" msgstr "调用栈" msgid "Go to Homepage" msgstr "返回主页" msgid "Create a New Virtual Machine" msgstr "创建一个新的虚拟机" msgid "Virtual Machine Name" msgstr "虚拟机åç§°" msgid "" "The name used to identify the virtual machine. If omitted, a name will be " "chosen based on the template used." msgstr "å字是虚拟机的标识。如果çœç•¥ï¼Œå°†ä¼šåŸºäºŽä½¿ç”¨çš„æ¨¡æ¿é€‰æ‹©ä¸€ä¸ªå字。" msgid "Template" msgstr "模æ¿" msgid "Please create a template first." msgstr "请先选择一个模æ¿" msgid "Create a Template" msgstr "创建一个模æ¿" msgid "Please choose a template." msgstr "请选择模æ¿ã€‚" msgid "OS" msgstr "æ“作系统" msgid "OS Version" msgstr "æ“作系统版本" msgid "CPUS" msgstr "中央处ç†å™¨" msgid "Memory" msgstr "内存" msgid "Create" msgstr "创建" msgid "Creating..." msgstr "正在创建..." msgid "Edit Guest" msgstr "修改客户机" msgid "General" msgstr "常规" msgid "Storage" msgstr "存储" msgid "Interface" msgstr "网络接å£" msgid "Permission" msgstr "æƒé™" msgid "Host PCI Device" msgstr "主机PCI设备" msgid "Snapshot" msgstr "å¿«ç…§" msgid "Name" msgstr "åç§°" msgid "CPUs" msgstr "中央处ç†å™¨" msgid "Memory (MB)" msgstr "内存(MB)" msgid "Icon" msgstr "图标" msgid "Device" msgstr "设备åç§°" msgid "Path" msgstr "路径" msgid "Network" msgstr "网络" msgid "Type" msgstr "类型" msgid "MAC Address" msgstr "" msgid "Available system users and groups" msgstr "å¯é€‰çš„系统用户åŠç”¨æˆ·ç»„" msgid "Selected system users and groups" msgstr "已选的系统用户åŠç”¨æˆ·ç»„" msgid "User" msgstr "用户" msgid "All" msgstr "所有" msgid "To Add" msgstr "待添加" msgid "Added" msgstr "已添加" msgid "filter" msgstr "过滤器" msgid "Product" msgstr "产å“" msgid "Vendor" msgstr "厂商" msgid "Created" msgstr "创建于" msgid "Save" msgstr "ä¿å­˜" msgid "Replace" msgstr "替æ¢" msgid "Detach" msgstr "å¸è½½" msgid "Cancel" msgstr "å–æ¶ˆ" msgid "revert" msgstr "æ¢å¤" msgid "Add a Storage Device to VM" msgstr "为虚拟机添加一个存储设备" msgid "Device Type" msgstr "设备类型" msgid "The device type. Currently, \"cdrom\" and \"disk\" are supported." msgstr "è®¾å¤‡ç±»åž‹ã€‚ç›®å‰æ”¯æŒè®¾å¤‡ç±»åž‹ï¼š\"cdrom\"å’Œ\"disk\"。 " msgid "Storage Pool" msgstr "存储池" msgid "Storage pool which volume located in" msgstr "å­˜å‚¨å·æ‰€åœ¨çš„存储池" msgid "Storage Volume" msgstr "存储å·" msgid "Storage volume to be attached" msgstr "被添加的存储å·" msgid "File Path" msgstr "文件路径" msgid "The ISO file path in the server for CDROM." msgstr "æœåŠ¡å™¨ç«¯CDROM所使用的ISO文件路径" msgid "Attach" msgstr "装载" msgid "Start" msgstr "å¯ç”¨" msgid "Reset" msgstr "é‡ç½®" msgid "Pause" msgstr "" msgid "Resume" msgstr "" msgid "Power Off" msgstr "关闭电æº" msgid "Actions" msgstr "æ“作" msgid "Connect" msgstr "连接到" msgid "Clone" msgstr "制作副本" msgid "Edit" msgstr "编辑" msgid "Shut Down" msgstr "关机" msgid "Delete" msgstr "删除" msgid "The username or password you entered is incorrect. Please try again." msgstr "ç”¨æˆ·åæˆ–密ç é”™è¯¯ï¼Œè¯·é‡æ–°è¾“入。" msgid "This field is required." msgstr "需è¦å¡«å†™æ­¤å¤„" msgid "Log in" msgstr "登录" msgid "Logging in..." msgstr "登录中..." msgid "Host" msgstr "主机" msgid "Guests" msgstr "客户机" msgid "Templates" msgstr "模æ¿" msgid "Failed to get application configuration" msgstr "获å–应用é…置失败" msgid "This is not a valid Linux path" msgstr "è¿™ä¸æ˜¯ä¸€ä¸ªæœ‰æ•ˆçš„Linux路径" msgid "This is not a valid URL." msgstr "è¿™ä¸æ˜¯ä¸€ä¸ªæœ‰æ•ˆçš„URL" msgid "No such data available." msgstr "没有å¯ç”¨çš„æ•°æ®" msgid "" "Can not contact the host system. Verify the host system is up and that you " "have network connectivity to it. HTTP request response %1. " msgstr "" "连接ä¸ä¸Šä¸»æœºã€‚请确ä¿ä¸»æœºç³»ç»Ÿå·²å¯åŠ¨ï¼Œå¹¶ä¸”èƒ½é€šè¿‡ç½‘ç»œè¿žæŽ¥ä¸»æœºã€‚HTTP请求å“应:%1" msgid "Unable to read file." msgstr "" msgid "Error while uploading file." msgstr "" msgid "Delete Confirmation" msgstr "删除确认" msgid "OK" msgstr "确定" msgid "Confirm" msgstr "确认" msgid "Warning" msgstr "警告" msgid "Cloning..." msgstr "" msgid "Loading..." msgstr "正在加载..." msgid "An error occurred while retrieving system information." msgstr "" msgid "Retry" msgstr "é‡è¯•" msgid "Detailed message:" msgstr "详细消æ¯ï¼š" msgid "No ISO found" msgstr "没有å‘现ISO文件" msgid "This is not a valid ISO file." msgstr "è¿™ä¸æ˜¯ä¸€ä¸ªæœ‰æ•ˆçš„ISO文件" msgid "This may take a long time. Do you want to continue?" msgstr "这需è¦ä¸€æ®µæ—¶é—´ã€‚是å¦ç»§ç»­ï¼Ÿ" msgid "This will permanently delete the template. Would you like to continue?" msgstr "这将永久删除模æ¿ã€‚是å¦ç»§ç»­ï¼Ÿ" msgid "Unable to shut down system as there are some virtual machines running!" msgstr "有虚拟机在è¿è¡Œï¼Œä¸èƒ½å…³é—­ä¸»æœºã€‚" msgid "Max:" msgstr "最大:" msgid "Utilization" msgstr "利用率" msgid "Available" msgstr "å¯åˆ©ç”¨çš„" msgid "Read Rate" msgstr "读速率" msgid "Write Rate" msgstr "写速率" msgid "Received" msgstr "接收" msgid "Sent" msgstr "å‘é€" msgid "" "Shutting down or restarting host will cause unsaved work lost. Continue to " "shut down/restarting?" msgstr "关闭或者é‡å¯ä¸»æœºä¼šå¯¼è‡´æ²¡æœ‰ä¿å­˜çš„工作丢失。继续关机/é‡å¯ï¼Ÿ" msgid "" "Repository will be removed permanently and can't be recovered. Do you want " "to continue?" msgstr "软件仓库将被永久删除,ä¸èƒ½æ¢å¤ã€‚是å¦ç»§ç»­ï¼Ÿ" msgid "Repositories" msgstr "软件仓库" msgid "ID" msgstr "标识符" msgid "Base URL" msgstr "基本URL" msgid "Is Mirror" msgstr "是å¦ä¸ºé•œåƒ" msgid "URL Args" msgstr "URL傿•°" msgid "Enabled" msgstr "å·²å¯ç”¨" msgid "GPG Check" msgstr "GPG校验" msgid "GPG Key" msgstr "GPGé”®" msgid "Add" msgstr "增加" msgid "Remove" msgstr "删除" msgid "Enable" msgstr "使能" msgid "Disable" msgstr "ç¦ç”¨" msgid "Software Updates" msgstr "软件更新" msgid "Package Name" msgstr "软件包åç§°" msgid "Version" msgstr "版本" msgid "Architecture" msgstr "体系结构" msgid "Repository" msgstr "软件仓库" msgid "Update All" msgstr "更新所有" msgid "Updating..." msgstr "正在更新..." msgid "Failed to retrieve packages update information." msgstr "查找软件包更新信æ¯å¤±è´¥ã€‚" msgid "Failed to update package(s)." msgstr "更新软件包失败" msgid "" "Debug report will be removed permanently and can't be recovered. Do you want " "to continue?" msgstr "诊断报告将被永久删除,并且ä¸èƒ½æ¢å¤ã€‚是å¦ç»§ç»­ï¼Ÿ" msgid "Debug Reports" msgstr "主机诊断报告" msgid "Generated Time" msgstr "ç”Ÿæˆæ—¶é—´" msgid "Generate" msgstr "生æˆ" msgid "Generating..." msgstr "正在生æˆ..." msgid "Rename" msgstr "é‡å‘½å" msgid "Download" msgstr "下载" msgid "" "Report name should contain only letters, digits, underscore ('_') and/or " "hyphen ('-')." msgstr "报告å字中åªèƒ½åŒ…å«å­—æ¯ã€æ•°å­—ã€ä¸‹åˆ’线('_')和连字符('-')" msgid "Pending..." msgstr "正在加载..." msgid "Report name is the same as the original one." msgstr "报告å称与原始åç§°é‡å¤ã€‚" msgid "" "This will delete the virtual machine and its virtual disks. This operation " "cannot be undone. Would you like to continue?" msgstr "这将删除虚拟机和它的虚拟ç£ç›˜ã€‚该æ“作ä¸èƒ½æ’¤é”€ï¼Œç»§ç»­å—?" msgid "Power off Confirmation" msgstr "关闭电æºç¡®è®¤" msgid "" "This action may produce undesirable results, for example unflushed disk " "cache in the guest. Would you like to continue?" msgstr "这样åšå¯èƒ½å¯¼è‡´ä¸è‰¯åŽæžœï¼Œæ¯”如客户机ç£ç›˜ç¼“存未刷新,确认è¦ç»§ç»­å—?" msgid "Reset Confirmation" msgstr "é‡ç½®ç¡®è®¤" msgid "" "There is a risk of data loss caused by reset without the guest OS shutdown. " "Would you like to continue?" msgstr "在客户机æ“作系统未关闭的情况下é‡ç½®æœ‰é£Žé™©å¯¼è‡´æ•°æ®ä¸¢å¤±ï¼Œç¡®è®¤è¦ç»§ç»­å—?" msgid "Shut Down Confirmation" msgstr "关机确认" msgid "Note the guest OS may ignore this request. Would you like to continue?" msgstr "注æ„,客户机æ“作系统å¯èƒ½ä¼šå¿½ç•¥è¿™ä¸ªè¯·æ±‚,确认è¦ç»§ç»­å—?" msgid "Virtual Machine delete Confirmation" msgstr "虚拟机删除确认" msgid "" "This virtual machine is not persistent. Power Off will delete it. Continue?" msgstr "è¯¥è™šæ‹Ÿæœºä¸æ˜¯ä¸€ä¸ªç¨³å®šçš„虚拟机,关机将会删除它,是å¦ç»§ç»­ï¼Ÿ" msgid "" "When the target guest has SCSI or iSCSI volumes, they will be cloned on " "default storage pool. The same will happen when the target pool does not " "have enough space to clone the volumes. Do you want to continue?" msgstr "" "当目标客户机使用SCSI或者iSCSIå­˜å‚¨å·æ—¶ï¼Œè¿™äº›å­˜å‚¨å·çš„副本将被放置于默认存储池" "中。在目标存储池没有足够空间放置其他存储å·çš„æ—¶å€™ä¹Ÿä¼šå¦‚此。确认继续?" msgid "" "This CDROM will be detached permanently and you can re-attach it. Continue " "to detach it?" msgstr "CDROM将被永久å¸è½½ï¼Œä½ å¯ä»¥é‡æ–°è£…载它。继续å¸è½½ï¼Ÿ" msgid "Attaching..." msgstr "正在装载" msgid "Replacing..." msgstr "正在替æ¢..." msgid "Successfully attached!" msgstr "æˆåŠŸè£…è½½" msgid "Successfully replaced!" msgstr "æˆåŠŸæ›¿æ¢" msgid "Successfully detached!" msgstr "æˆåŠŸå¸è½½" msgid "" "This disk will be detached permanently and you can re-attach it. Continue to " "detach it?" msgstr "该ç£ç›˜å°†ä¼šè¢«æ°¸ä¹…å¸è½½ï¼Œä½ å¯ä»¥é‡æ–°æ·»åŠ å®ƒï¼Œç»§ç»­æ‰§è¡Œå¸è½½æ“作å—?" msgid "interface:" msgstr "接å£ï¼š" msgid "address:" msgstr "地å€ï¼š" msgid "link_type:" msgstr "连接类型:" msgid "block:" msgstr "å—:" msgid "drive_type:" msgstr "设备类型:" msgid "model:" msgstr "模型:" msgid "Affected devices:" msgstr "被影å“的设备:" msgid "The VLAN id must be between 1 and 4094." msgstr "VLAN 标识符必须在1至4094之间" msgid "unavailable" msgstr "无法获å–" msgid "" "This action will interrupt network connectivity for any virtual machine that " "depend on this network." msgstr "此æ“作将中断ä¾èµ–此网络的虚拟机的网络连接。" msgid "Create a network" msgstr "创建一个网络" msgid "" "This network is not persistent. Instead of stop, this action will " "permanently delete it. Would you like to continue?" msgstr "" "这是一个临时的网络é…置,该æ“ä½œä¼šæ°¸ä¹…åœ°åˆ é™¤è¿™ä¸ªç½‘ç»œè€Œä¸æ˜¯åœæ­¢å…¶è¿è¡Œï¼Œç¡®å®šè¦ç»§" "ç»­å—?" msgid "" "The bridged VLAN tag may not work well with NetworkManager enabled. You " "should consider disabling it." msgstr "" msgid "" "This will permanently delete the storage pool. Would you like to continue?" msgstr "这将永久删除存储池。是å¦ç»§ç»­ï¼Ÿ" msgid "This storage pool is empty." msgstr "这个存储池为空" msgid "" "It will format your disk and you will loose any data in there, are you sure " "to continue? " msgstr "ä½ çš„ç£ç›˜å°†ä¼šæ ¼å¼åŒ–,ç£ç›˜ä¸Šçš„æ•°æ®ä¼šä¸¢å¤±ï¼Œä½ ç¡®å®šè¦ç»§ç»­å—?" msgid "SCSI Fibre Channel" msgstr "SCSI光纤通é“" msgid "No SCSI adapters found." msgstr "没有å‘现SCSI适é…器" msgid "Loading iSCSI targets..." msgstr "读å–iSCSI目标..." msgid "No iSCSI found. Please input one." msgstr "未能找到iSCSI,请输入一个。" msgid "Failed to load iSCSI targets." msgstr "读å–iSCSI目标失败。" msgid "The storage pool name can not be blank." msgstr "存储池的åç§°ä¸èƒ½ä¸ºç©ºã€‚" msgid "The storage pool path can not be blank." msgstr "存储池的路径ä¸èƒ½ä¸ºç©ºã€‚" msgid "NFS server mount path can not be blank." msgstr "NFSæœåŠ¡å™¨æŒ‚è½½è·¯å¾„ä¸èƒ½ä¸ºç©ºã€‚" msgid "Invalid NFS mount path." msgstr "无效的NFS挂载路径。" msgid "No logical device selected." msgstr "没有选择逻辑设备。" msgid "The iSCSI target can not be blank." msgstr "iSCSI目标ä¸èƒ½ä¸ºç©ºã€‚" msgid "Server name can not be blank." msgstr "æœåС噍ä¸èƒ½ä¸ºç©ºã€‚" msgid "This is not a valid Server Name or IP. Please, modify it." msgstr "è¿™ä¸æ˜¯ä½ ä¸ªæœ‰æ•ˆçš„æœåŠ¡å™¨å称或IP地å€ï¼Œè¯·å¯¹å…¶è¿›è¡Œä¿®æ”¹ã€‚" msgid "Looking for available partitions ..." msgstr "查找有效的分区 ..." msgid "No available partitions found." msgstr "没有å‘现模æ¿ã€‚" msgid "" "This storage pool is not persistent. Instead of deactivate, this action will " "permanently delete it. Would you like to continue?" msgstr "å¯¹äºŽéžæŒä¹…存储池,这个æ“ä½œå°†ä¼šæ°¸ä¹…åˆ é™¤å­˜å‚¨æ± è€Œä¸æ˜¯åœç”¨ã€‚是å¦ç»§ç»­ï¼Ÿ" msgid "Unable to retrieve partitions information." msgstr "未能找到分区信æ¯ã€‚" msgid "In progress..." msgstr "正在进行..." msgid "Failed!" msgstr "失败ï¼" msgid "CDROM path needs to be a valid local/remote path and cannot be blank." msgstr "CDROM路径需è¦ä¸€ä¸ªæœ‰æ•ˆçš„æœ¬åœ°/远程路径且ä¸èƒ½ä¸ºç©ºã€‚" msgid "Disk pool or volume cannot be blank." msgstr "存储池或å·ä¸èƒ½ä¸ºç©º" msgid "Peers" msgstr "对等机" msgid "Searching" msgstr "正在查询" msgid "No peers found." msgstr "没有å‘现对等机。" msgid "Help" msgstr "帮助" msgid "About" msgstr "关于" msgid "Log out" msgstr "登出" msgid "Version:" msgstr "版本:" msgid "Session timeout, please re-login." msgstr "ç™»å½•è¶…æ—¶ï¼Œè¯·é‡æ–°ç™»å½•。" msgid "User Name" msgstr "用户å" msgid "Password" msgstr "密ç " msgid "Generate a New Debug Report" msgstr "产生一个新的诊断报告" msgid "Report Name" msgstr "诊断报告å" msgid "" "The name used to identify the report. If omitted, a name will be chosen " "based on current time. Name can contain: letters, digits, underscore (\"_\") " "and hyphen (\"-\")." msgstr "" "åå­—ç”¨æ¥æ ‡è¯†è¯Šæ–­æŠ¥å‘Šã€‚如果çœç•¥ï¼Œå°†ä¼šåŸºäºŽå½“剿—¶é—´ç”Ÿæˆä¸€ä¸ªæ–°å字。å字中å¯ä»¥åŒ…" "å«å­—æ¯ã€æ•°å­—ã€ä¸‹åˆ’线 ('_') 和连字符('-')" msgid "Rename a Debug Report" msgstr "é‡å‘½å一个调试报告" msgid "" "The name used to identify the report. Name can contain: letters, digits and " "hyphen (\"-\")." msgstr "报告的唯一表示å称,åç§°å¯ä»¥åŒ…å«ï¼šè‹±æ–‡å­—符,数字和连字符(\"-\")。" msgid "Submit" msgstr "æäº¤" msgid "Add a Repository" msgstr "增加一个软件仓库" msgid "Identifier" msgstr "标识符" msgid "Single word, unique identifier for the repository." msgstr "一个å•è¯ï¼Œå”¯ä¸€æ ‡è¯†è½¯ä»¶ä»“库" msgid "Textual name for the repository." msgstr "软件仓库的字é¢åå­—" msgid "URL" msgstr "URL" msgid "Required Field" msgstr "必需的字段" msgid "URL to the repository. Supported protocols are http, ftp, and file." msgstr "软件仓库的URL,支æŒçš„å议有httpã€ftpã€å’Œfile" msgid "Repository is a mirror" msgstr "软件仓库是一个镜åƒ" msgid "Distribution" msgstr "å‘行版" msgid "Distribution of the DEB repository." msgstr "DEB仓库的å‘行版" msgid "Components" msgstr "组件" msgid "List of components in DEB repository." msgstr "DEB仓库中的组件列表" msgid "Edit Repository" msgstr "修改软件仓库" msgid "Mirror List URL" msgstr "镜åƒåˆ—表URL" msgid "Yes" msgstr "是" msgid "No" msgstr "å¦" msgid "Add a Volume to Storage Pool" msgstr "为存储池添加一个å·" msgid "Fetch from remote URL" msgstr "从远程URL获å–" msgid "Enter the remote URL here." msgstr "在这里输入远程URL。" msgid "Upload a file" msgstr "上传一个文件" msgid "Choose the file you want to upload." msgstr "选择需è¦ä¸Šä¼ çš„æ–‡ä»¶ã€‚" msgid "Define a New Storage Pool" msgstr "定义一个新的存储池" msgid "Storage Pool Name" msgstr "存储池åç§°" msgid "" "The name used to identify the storage pools, and it should not be empty." msgstr "该å称用æ¥å”¯ä¸€æ ‡è¯†å­˜å‚¨æ± ï¼Œè¯¥åç§°ä¸èƒ½ä¸ºç©ºã€‚" msgid "Storage Pool Type" msgstr "存储池类型" msgid "Storage Path" msgstr "存储路径" msgid "" "The path of the Storage Pool. Each Storage Pool must have a unique path." msgstr "存储池的路径.æ¯ä¸ªå­˜å‚¨æ± çš„路径是唯一的。" msgid "" "Kimchi will try to create the directory when it does not already exist in " "your system." msgstr "如果目录ä¸å­˜åœ¨ï¼ŒKIMCHI会自动在系统中创建一个新的目录" msgid "NFS Server IP" msgstr "NFSæœåС噍IP" msgid "NFS server IP or hostname. It can be input or chosen from history." msgstr "NFSæœåС噍IP或者主机å,å¯ä»¥ç›´æŽ¥è¾“入或者从历å²è®°å½•中选å–。" msgid "NFS Path" msgstr "NFS 路径" msgid "The NFS exported path on NFS server." msgstr "NFSæœåŠ¡å™¨ä¸Šå¯¼å‡ºçš„NFS路径" msgid "Device path" msgstr "设备路径" msgid "iSCSI Server" msgstr "iSCSIæœåС噍" msgid "iSCSI server IP or hostname. It should not be empty." msgstr "iSCSIæœåС噍IP或者主机å, ä¸èƒ½ä¸ºç©ºã€‚" msgid "Server" msgstr "æœåС噍" msgid "Port" msgstr "端å£" msgid "Target" msgstr "目标" msgid "The iSCSI target on iSCSI server" msgstr "iSCSI目标" msgid "Add iSCSI Authentication" msgstr "添加ISCSI认è¯" msgid "iSCSI Authentication" msgstr "iSCSI认è¯" msgid "SCSI Adapter" msgstr "SCSI适é…器" msgid "Please, wait..." msgstr "请等待..." msgid "Add Template" msgstr "创建模æ¿" msgid "Where is the source media for this template? " msgstr "模æ¿çš„æºä»‹è´¨åœ¨å“ªé‡Œï¼Ÿ" msgid "Local ISO Image" msgstr "本地ISO镜åƒ" msgid "Local Image File" msgstr "æœ¬åœ°é•œåƒæ–‡ä»¶" msgid "Remote ISO Image" msgstr "远程ISO镜åƒ" msgid "Search ISOs" msgstr "æœç´¢ISO" msgid "The following ISOs are available:" msgstr "å¯ç”¨ISO文件如下" msgid "OS: " msgstr "æ“作系统: " msgid "Version: " msgstr "版本: " msgid "Size: " msgstr "大å°ï¼š" msgid "Search more ISOs" msgstr "æœç´¢æ›´å¤šISO" msgid "Create Templates from Selected ISO" msgstr "从选中的ISO中创建模æ¿" msgid "I want to use a specific ISO file" msgstr "指定一个ISO文件" msgid "Loading default remote ISOs ..." msgstr "加载默认的远程ISOs ..." msgid "Arch: " msgstr "体系结构:" msgid "I want to use a custom URL" msgstr "我想用一个自定义的URL" msgid "Edit Template" msgstr "编辑模æ¿" msgid "Processor" msgstr "处ç†å™¨" msgid "CDROM" msgstr "光驱" msgid "Image File" msgstr "é•œåƒæ–‡ä»¶" msgid "Graphics" msgstr "图形" msgid "Disk(GB)" msgstr "ç£ç›˜(GB)" msgid "Disk Format" msgstr "" msgid "CPU Number" msgstr "CPU个数" msgid "Manually set CPU topology" msgstr "手动é…ç½®CPU拓扑" msgid "Cores" msgstr "内核数" msgid "Threads" msgstr "线程" msgid "CPU" msgstr "处ç†å™¨" msgid "Disk I/O" msgstr "ç£ç›˜I/O" msgid "Network I/O" msgstr "网络I/O" msgid "Livetile" msgstr "å±å¹•" msgid "No guests found." msgstr "没有å‘现客户机" msgid "Shut down" msgstr "关机" msgid "Restart" msgstr "é‡å¯" msgid "Basic Information" msgstr "基本信æ¯" msgid "OS Distro" msgstr "æ“作系统å‘行版" msgid "OS Code Name" msgstr "æ“作系统代å·" msgid "CPU(s)" msgstr "CPU(s)" msgid "System Statistics" msgstr "系统统计信æ¯" msgid "Update Progress" msgstr "更新进度" msgid "Network Name" msgstr "网络åç§°" msgid "State" msgstr "状æ€" msgid "Network Type" msgstr "网络类型" msgid "Address Space" msgstr "地å€ç©ºé—´" msgid "Name should not contain '/' and '\"'." msgstr "å字中ä¸èƒ½åŒ…å«â€˜/’和'\"'。" msgid "Isolated: no external network connection" msgstr "隔离: åŒç‰©ç†ç½‘络ä¸è¿žé€š" msgid "NAT: outbound physical network connection only" msgstr "NAT: 从虚拟机到物ç†ç½‘络å•å‘连接" msgid "Bridged: Virtual machines are connected to physical network directly" msgstr "桥接:虚拟机å¯ä»¥ç›´æŽ¥è¿žæŽ¥åˆ°ç‰©ç†ç½‘络中。" msgid "(No interfaces found)" msgstr "(没有å‘现网络接å£)" msgid "Destination" msgstr "目标设备" msgid "Enable VLAN" msgstr "å¯ç”¨VLAN" msgid "VLAN ID" msgstr "VLANå·" msgid "Stop" msgstr "åœæ­¢" msgid "%Used" msgstr "" msgid "Location" msgstr "路径" msgid "Capacity" msgstr "容é‡" msgid "Allocated" msgstr "已分é…" msgid "active" msgstr "已激活" msgid "inactive" msgstr "未激活" msgid "Deactivate" msgstr "åœç”¨" msgid "Activate" msgstr "激活" msgid "Add Volume" msgstr "添加å·" msgid "Extend" msgstr "扩展" msgid "Undefine" msgstr "å–æ¶ˆå®šä¹‰" msgid "Format" msgstr "æ ¼å¼" msgid "Allocation" msgstr "分é…" msgid "No templates found." msgstr "没有å‘现模æ¿" kimchi-1.5.0/po/zh_TW.po000066400000000000000000001533451254252253000150050ustar00rootroot00000000000000# English translations for kimchi package. # Copyright (C) 2013 ORGANIZATION # msgid "" msgstr "" "Project-Id-Version: kimchi 0.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-06-24 09:39-0300\n" "PO-Revision-Date: 2013-07-11 17:32-0400\n" "Last-Translator: Crístian Viana \n" "Language-Team: English\n" "Language: zh_TW\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: pygettext.py 1.5\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #, python-format msgid "Unknown parameter %(value)s" msgstr "" #, python-format msgid "Delete is not allowed for %(resource)s" msgstr "ä¸å®¹è¨±é‡å° %(resource)s 執行刪除" #, python-format msgid "%(resource)s does not implement update method" msgstr "%(resource)s 未實作更新方法" #, python-format msgid "Create is not allowed for %(resource)s" msgstr "ä¸å®¹è¨±é‡å° %(resource)s 執行建立" msgid "Unable to parse JSON request" msgstr "ç„¡æ³•å‰–æž JSON è¦æ±‚" msgid "This API only supports JSON" msgstr "æ­¤ API åƒ…æ”¯æ´ JSON" #, python-format msgid "Parameters does not match requirement in schema: %(err)s" msgstr "" msgid "You don't have permission to perform this operation." msgstr "" msgid "Datastore is not initiated in the model object." msgstr "未在模型物件中起始資料儲存庫。" #, python-format msgid "Unable to start task due error: %(err)s" msgstr "由於下列錯誤,無法開始工作:%(err)s" #, python-format msgid "Timeout of %(seconds)s seconds expired while running task '%(task)s." msgstr "" #, python-format msgid "Authentication failed for user '%(username)s'. [Error code: %(code)s]" msgstr "使用者 '%(username)s' 的鑑別失敗。[錯誤碼:%(code)s]" msgid "You are not authorized to access Kimchi" msgstr "æ‚¨æœªç²æŽˆæ¬Šä¾†å­˜å– Kimchi" #, python-format msgid "Specify %(item)s to login into Kimchi" msgstr "指定 %(item)s 以登入 Kimchi" #, python-format msgid "User %(user_id)s not found with given LDAP settings." msgstr "" #, python-format msgid "Invalid LDAP configuration: %(item)s : %(value)s" msgstr "" msgid "Unknown \"_cap\" specified" msgstr "" msgid "\"_passthrough\" should be \"true\" or \"false\"" msgstr "" msgid "\"_passthrough_affected_by\" should be a device name string" msgstr "" #, python-format msgid "Error while getting block devices. Details: %(err)s" msgstr "å–å¾—å€å¡Šè£ç½®æ™‚發生錯誤。詳細資料:%(err)s" #, python-format msgid "Error while getting block device information for %(device)s." msgstr "å–å¾— %(device)s çš„å€å¡Šè£ç½®è³‡è¨Šæ™‚發生錯誤。" #, python-format msgid "Unable to find distro file: %(filename)s" msgstr "找ä¸åˆ° distro 檔案:%(filename)s" #, python-format msgid "" "Unable to parse distro file: %(filename)s. Make sure, it is a JSON file." msgstr "ç„¡æ³•å‰–æž distro 檔案:%(filename)s。請確ä¿å®ƒæ˜¯ JSON 檔案。" #, python-format msgid "Unable to login to iSCSI host target %(portal)s. Details: %(err)s" msgstr "無法登入 iSCSI 主機目標 %(portal)s。詳細資料:%(err)s" #, python-format msgid "Unable to login to iSCSI host %(host)s target %(target)s" msgstr "無法登入 iSCSI 主機 %(host)s 目標 %(target)s" #, python-format msgid "Unable to find ISO file %(filename)s" msgstr "" #, python-format msgid "The ISO file %(filename)s is not bootable" msgstr "ISO 檔案 %(filename)s ä¸å¯é–‹æ©Ÿ" #, python-format msgid "The ISO file %(filename)s does not have a valid El Torito boot record" msgstr "ISO 檔案 %(filename)s 沒有有效的 El Torito 開機記錄" #, python-format msgid "Invalid El Torito validation entry in ISO %(filename)s" msgstr "ISO %(filename)s 中有無效的 El Torito 驗證項目" #, python-format msgid "Invalid El Torito boot indicator in ISO %(filename)s" msgstr "ISO %(filename)s 中有無效的 El Torito 啟動指示器" #, python-format msgid "Unexpected volume type for primary volume in ISO %(filename)s" msgstr "ISO %(filename)s 中有主è¦ç£ç¢Ÿå€çš„éžé æœŸç£å€é¡žåž‹" #, python-format msgid "Bad format while reading volume descriptor in ISO %(filename)s" msgstr "è®€å– ISO %(filename)s 中的ç£å€æè¿°å­æ™‚é‡åˆ°ä¸ç•¶çš„æ ¼å¼" #, python-format msgid "" "The hypervisor doesn't have permission to use this ISO %(filename)s. " "Consider moving it under /var/lib/libvirt, or set the search permission to " "file access control lists for '%(user)s' user if possible, or add the " "'%(user)s' to the ISO path group, or (not recommended) 'chmod -R o+x " "'path_to_iso'.Details: %(err)s" msgstr "" "Hypervisor 沒有使用此 ISO %(filename)s çš„è¨±å¯æ¬Šã€‚請考é‡å°‡å…¶ç§»å‹•至 /var/lib/" "libvirt 下ã€å°‡æœå°‹è¨±å¯æ¬Šè¨­ç‚º'%(user)s' ä½¿ç”¨è€…çš„æª”æ¡ˆå­˜å–æŽ§åˆ¶æ¸…å–®ï¼ˆè‹¥æœ‰å¯èƒ½ï¼‰ã€" "å°‡ '%(user)s' 新增至 ISO 路徑群組或(建議ä¸è¦åŸ·è¡Œæ­¤å‹•作)執行 'chmod -R o+x " "'path_to_iso'。詳細資料:%(err)s" msgid "An error occurred when probing image OS information." msgstr "" msgid "No OS information found in given image." msgstr "" #, python-format msgid "Unable to read image file %(filename)s" msgstr "" #, python-format msgid "" "Image file must be an existing file on system. %(filename)s is not a valid " "input." msgstr "" #, python-format msgid "Virtual machine %(name)s already exists" msgstr "虛擬機器 %(name)s 已存在" #, python-format msgid "Virtual machine %(name)s does not exist" msgstr "虛擬機器 %(name)s ä¸å­˜åœ¨" #, python-format msgid "" "Unable to rename virtual machine %(name)s. The name %(new_name)s is already " "in use or the virtual machine is not powered off." msgstr "" #, python-format msgid "Unable to retrieve screenshot for stopped virtual machine %(name)s" msgstr "無法擷å–å·²åœæ­¢è™›æ“¬æ©Ÿå™¨ %(name)s 的畫é¢" msgid "Remote ISO image is not supported by this server." msgstr "此伺æœå™¨ä¸æ”¯æ´é ç«¯ ISO æ˜ åƒæª”。" #, python-format msgid "Screenshot is not supported on virtual machine %(name)s" msgstr "" #, python-format msgid "Unable to create virtual machine %(name)s. Details: %(err)s" msgstr "無法建立虛擬機器 %(name)s。詳細資料:%(err)s" #, python-format msgid "Unable to update virtual machine %(name)s. Details: %(err)s" msgstr "無法建立虛擬機器 %(name)s。詳細資料:%(err)s" #, python-format msgid "Unable to retrieve virtual machine %(name)s. Details: %(err)s" msgstr "無法擷å–虛擬機器 %(name)s。詳細資料:%(err)s" #, python-format msgid "Unable to connect to powered off virtual machine %(name)s." msgstr "" msgid "Virtual machine name must be a string without slashes (/)" msgstr "" #, python-format msgid "Invalid template URI %(value)s specified for virtual machine" msgstr "" #, python-format msgid "Invalid storage pool URI %(value)s specified for virtual machine" msgstr "" msgid "Supported virtual machine graphics are Spice or VNC" msgstr "" msgid "Graphics address to listen on must be IPv4 or IPv6" msgstr "è¦æŽ¥è½çš„圖形å¡ä½å€å¿…須是 IPv4 或 IPv6" msgid "Specify a template to create a virtual machine from" msgstr "指定用於建立虛擬機器的範本" #, python-format msgid "Unable to start virtual machine %(name)s. Details: %(err)s" msgstr "無法啟動虛擬機器 %(name)s。詳細資料:%(err)s" #, python-format msgid "Unable to power off virtual machine %(name)s. Details: %(err)s" msgstr "ç„¡æ³•åœæ­¢è™›æ“¬æ©Ÿå™¨ %(name)s。詳細資料:%(err)s" #, python-format msgid "Unable to delete virtual machine %(name)s. Details: %(err)s" msgstr "無法刪除虛擬機器 %(name)s。詳細資料:%(err)s" #, python-format msgid "Unable to reset virtual machine %(name)s. Details: %(err)s" msgstr "ç„¡æ³•é‡æ–°å‘½å虛擬機器 %(name)s。詳細資料:%(err)s" msgid "User name list must be an array" msgstr "" msgid "User name must be a string" msgstr "網路å稱必須是字串" msgid "Group name list must be an array" msgstr "" msgid "Group name must be a string" msgstr "網路å稱必須是字串" #, python-format msgid "User(s) '%(users)s' do not exist" msgstr "使用者 '%(users)s' ä¸å­˜åœ¨ã€‚" #, python-format msgid "Group(s) '%(groups)s' do not exist" msgstr "使用者 '%(groups)s' ä¸å­˜åœ¨ã€‚" #, python-format msgid "Unable to shutdown virtual machine %(name)s. Details: %(err)s" msgstr "ç„¡æ³•åœæ­¢è™›æ“¬æ©Ÿå™¨ %(name)s。詳細資料:%(err)s" #, python-format msgid "" "Unable to get access metadata of virtual machine %(name)s. Details: %(err)s" msgstr "無法啟動虛擬機器 %(name)s。詳細資料:%(err)s" msgid "The guest console password must be a string." msgstr "" msgid "The life time for the guest console password must be a number." msgstr "" #, python-format msgid "Virtual machine '%(name)s' must be stopped before cloning it." msgstr "" #, python-format msgid "Insufficient disk space to clone virtual machine '%(name)s'" msgstr "" #, python-format msgid "Unable to clone VM '%(name)s'. Details: %(err)s" msgstr "" #, python-format msgid "Invalid operation for non-persistent virtual machine %(name)s" msgstr "" #, python-format msgid "Cannot suspend VM '%(name)s' because it is not running." msgstr "" #, python-format msgid "Unable to suspend VM '%(name)s'. Details: %(err)s" msgstr "" #, python-format msgid "Cannot resume VM '%(name)s' because it is not paused." msgstr "" #, python-format msgid "Unable to resume VM '%(name)s'. Details: %(err)s" msgstr "" msgid "Memory assigned is higher then the maximum allowed in the host." msgstr "" #, python-format msgid "" "VM '%(name)s' does not support live memory update. Update the memory with " "the machine offline to enable this feature." msgstr "" msgid "Only increase memory is allowed in active VMs" msgstr "" msgid "" "For live memory update, new memory value must be equal old memory value plus " "multiples of 1024 Mib" msgstr "" msgid "There are not enough free slots of 1024 Mib in the guest." msgstr "" msgid "" "Host's libvirt version does not support memory devices. Libvirt must be >= " "1.2.14" msgstr "" #, python-format msgid "Error attaching memory device. Details: %(error)s" msgstr "" #, python-format msgid "" "VM %(vmid)s does not contain directly assigned host device %(dev_name)s." msgstr "" #, python-format msgid "The host device %(dev_name)s is not allowed to directly assign to VM." msgstr "" msgid "" "No IOMMU groups found. Host PCI pass through needs IOMMU group to function " "correctly. Please enable Intel VT-d or AMD IOMMU in your BIOS, then verify " "the Kernel is compiled with IOMMU support. For Intel CPU, add intel_iommu=on " "to your Kernel parameter in /boot/grub2/grub.conf. For AMD CPU, add iommu=pt " "iommu=1." msgstr "" msgid "\"name\" should be a device name string" msgstr "" #, python-format msgid "" "The device %(name)s is probably in use by the host. Unable to attach it to " "the guest." msgstr "" #, python-format msgid "Interface %(iface)s does not exist in virtual machine %(name)s" msgstr "ä»‹é¢ %(iface)s ä¸å­˜åœ¨æ–¼è™›æ“¬æ©Ÿå™¨ %(name)s 中" #, python-format msgid "" "Network %(network)s specified for virtual machine %(name)s does not exist" msgstr "為虛擬機器 %(name)s 指定的網路 %(network)s ä¸å­˜åœ¨" msgid "Supported virtual machine interfaces type is only network" msgstr "唝䏀嗿”¯æ´çš„虛擬機器介é¢é¡žåž‹æ˜¯ç¶²è·¯" msgid "Network name for virtual machine interface must be a string" msgstr "虛擬機器介é¢çš„網路å稱必須是字串" msgid "Invalid network model card specified for virtual machine interface" msgstr "ç‚ºè™›æ“¬æ©Ÿå™¨ä»‹é¢æŒ‡å®šçš„網路模型å¡ç„¡æ•ˆ" msgid "Specify type and network to add a new virtual machine interface" msgstr "指定類型和網路以新增虛擬機器介é¢" msgid "MAC Address must respect this format FF:FF:FF:FF:FF:FF" msgstr "" #, python-format msgid "MAC Address %(mac)s already exists in virtual machine %(name)s" msgstr "" msgid "Invalid MAC Address" msgstr "" msgid "Cannot change MAC address of a running virtual machine" msgstr "" #, python-format msgid "Template %(name)s already exists" msgstr "範本 %(name)s 已存在" #, python-format msgid "" "Network '%(network)s' specified for template %(template)s does not exist" msgstr "為範本 %(template)s 指定的網路 '%(network)s' ä¸å­˜åœ¨" #, python-format msgid "" "Storage pool %(pool)s specified for template %(template)s does not exist" msgstr "為範本 %(template)s æŒ‡å®šçš„å„²å­˜å€ '%(pool)s' ä¸å­˜åœ¨" #, python-format msgid "Storage pool %(pool)s specified for template %(template)s is not active" msgstr "為範本 %(template)s æŒ‡å®šçš„å„²å­˜å€ '%(pool)s' 未處於作用中狀態" #, python-format msgid "Invalid parameter '%(param)s' specified for CDROM." msgstr "為 CDROM æŒ‡å®šçš„åƒæ•¸ '%(param)s' 無效。" #, python-format msgid "Network %(network)s specified for template %(template)s is not active" msgstr "為範本 %(template)s 指定的網路 %(network)s 未處於作用中狀態" msgid "Template name must be a string" msgstr "範本å稱必須是字串" msgid "Template icon must be a path to the image" msgstr "範本圖示必須是影åƒçš„路徑" msgid "Template distribution must be a string" msgstr "範本發行套件必須是字串" msgid "Template distribution version must be a string" msgstr "範本發行版本必須是字串" msgid "The number of CPUs must be an integer greater than 0" msgstr "CPU 數目必須是整數" msgid "Amount of memory (MB) must be an integer greater than 512" msgstr "è¨˜æ†¶é«”æ•¸é‡ (MB) 必須是大於 512 的整數" msgid "Template CDROM must be a local or remote ISO file" msgstr "範本 CDROM 必須是本端或é ç«¯ ISO 檔案" #, python-format msgid "Invalid storage pool URI %(value)s specified for template" msgstr "ç‚ºç¯„æœ¬æŒ‡å®šçš„å„²å­˜å€ URI %(value)s 無效" msgid "Specify an ISO image as CDROM or a base image to create a template" msgstr "指定 ISO æ˜ åƒæª”作為 CDROM 以建立範本" msgid "All networks for the template must be specified in a list." msgstr "範本的所有網路都必須在清單中指定。" msgid "Specify a volume to a template when storage pool is iSCSI or SCSI" msgstr "" #, python-format msgid "The volume %(volume)s is not in storage pool %(pool)s" msgstr "" #, python-format msgid "Unable to create template due error: %(err)s" msgstr "由於下列錯誤,無法建立範本:%(err)s" #, python-format msgid "Unable to delete template due error: %(err)s" msgstr "由於下列錯誤,無法刪除範本:%(err)s" msgid "Disk size must be an integer greater than 1GB." msgstr "" msgid "Template base image must be a valid local image file" msgstr "範本 CDROM 必須是本端或é ç«¯ ISO 檔案" #, python-format msgid "Cannot identify base image %(path)s format" msgstr "" msgid "" "When specifying CPU topology, VCPUs must be a product of sockets, cores, and " "threads." msgstr "" msgid "" "When specifying CPU topology, each element must be an integer greater than " "zero." msgstr "" msgid "" "Invalid disk image format. Valid formats: bochs, cloop, cow, dmg, qcow, " "qcow2, qed, raw, vmdk, vpc." msgstr "" #, python-format msgid "Storage pool %(name)s already exists" msgstr "å„²å­˜å€ %(name)s 已存在" #, python-format msgid "Storage pool %(name)s does not exist" msgstr "å„²å­˜å€ %(name)s ä¸å­˜åœ¨" #, python-format msgid "Specify %(item)s in order to create the storage pool %(name)s" msgstr "指定 %(item)s ä»¥å»ºç«‹å„²å­˜å€ %(name)s" #, python-format msgid "Unable to delete active storage pool %(name)s" msgstr "ç„¡æ³•åˆªé™¤ä½œç”¨ä¸­çš„å„²å­˜å€ %(name)s" #, python-format msgid "Unable to list storage pools. Details: %(err)s" msgstr "無法列出儲存å€ã€‚詳細資料:%(err)s" #, python-format msgid "Unable to create storage pool %(name)s. Details: %(err)s" msgstr "ç„¡æ³•å»ºç«‹å„²å­˜å€ %(name)s。詳細資料:%(err)s" #, python-format msgid "" "Unable to get number of storage volumes in storage pool %(name)s. Details: " "%(err)s" msgstr "無法å–å¾—å„²å­˜å€ %(name)s 中儲存ç£å€çš„æ•¸ç›®ã€‚詳細資料:%(err)s" #, python-format msgid "Unable to activate storage pool %(name)s. Details: %(err)s" msgstr "ç„¡æ³•å•Ÿå‹•å„²å­˜å€ %(name)s。詳細資料:%(err)s" #, python-format msgid "Unable to deactivate storage pool %(name)s. Details: %(err)s" msgstr "ç„¡æ³•å–æ¶ˆå•Ÿå‹•å„²å­˜å€ %(name)s。詳細資料:%(err)s" #, python-format msgid "Unable to delete storage pool %(name)s. Details: %(err)s" msgstr "ç„¡æ³•åˆªé™¤å„²å­˜å€ %(name)s。詳細資料:%(err)s" #, python-format msgid "" "Unable to create NFS Pool as export path %(path)s may block during mount" msgstr "無法建立 NFS 儲存å€ï¼Œå› ç‚ºåœ¨è£è¼‰æœŸé–“,匯出路徑 %(path)s å¯èƒ½æœƒå°éŽ–" #, python-format msgid "Unable to create NFS Pool as export path %(path)s mount failed" msgstr "無法建立 NFS 儲存å€ï¼Œå› ç‚ºåŒ¯å‡ºè·¯å¾‘ %(path)s è£è¼‰å¤±æ•—" #, python-format msgid "Unsupported storage pool type: %(type)s" msgstr "ä¸å—支æ´çš„儲存å€é¡žåž‹ï¼š%(type)s" #, python-format msgid "Error while retrieving storage pool XML to %(pool)s" msgstr "" msgid "Storage pool name must be a string without slashes (/)" msgstr "" msgid "" "Supported storage pool types are dir, netfs, logical, iscsi, isci and kimchi-" "iso" msgstr "" msgid "Storage pool path must be a string" msgstr "儲存å€è·¯å¾‘必須是字串" msgid "Storage pool host must be a IP or hostname" msgstr "儲存å€ä¸»æ©Ÿå¿…須是 IP 或主機å稱" msgid "Storage pool device must be the absolute path to the block device" msgstr "" msgid "Storage pool devices parameter must be a list" msgstr "儲存å€è£ç½®åƒæ•¸å¿…須是清單" msgid "Target IQN of an iSCSI pool must be a string" msgstr "iSCSI 儲存å€çš„目標 IQN 必須是字串" msgid "Port of a remote storage server must be an integer between 1 and 65535" msgstr "é ç«¯å„²å­˜é«”伺æœå™¨çš„埠必須是介於 1 å’Œ 65535 之間的整數" msgid "iSCSI target username must be a string" msgstr "" msgid "iSCSI target password must be a string" msgstr "" msgid "Specify name and type to create a storage pool" msgstr "指定å稱和類型以建立儲存å€" #, python-format msgid "" "%(disk)s is not a valid disk/partition. Could not add it to the pool " "%(pool)s." msgstr "%(disk)s 䏿˜¯æœ‰æ•ˆçš„ç£ç¢Ÿ/分割å€ã€‚無法將它新增至儲存å€%(pool)s。" #, python-format msgid "Unable to extend logical pool %(pool)s. Details: %(err)s" msgstr "" msgid "The parameter disks only can be updated for logical storage pool." msgstr "åªèƒ½é‡å°é‚è¼¯å„²å­˜å€æ›´æ–°ã€Œåƒ…é™ç£ç¢Ÿã€åƒæ•¸ã€‚" msgid "The SCSI host adapter name must be a string." msgstr "SCSI ä¸»æ©Ÿé…æŽ¥å¡å稱必須是字串。" msgid "The storage pool kimchi_isos is reserved for internal use" msgstr "å„²å­˜å€ kimchi_isos ä¿ç•™ä¾›å…§éƒ¨ä½¿ç”¨" #, python-format msgid "" "Unable to activate NFS storage pool %(name)s. NFS server %(server)s is " "unreachable." msgstr "無法啟動 NFS å„²å­˜å€ %(name)s。NFS 伺æœå™¨ %(server)s無法連線。" #, python-format msgid "" "Unable to deactivate NFS storage pool %(name)s. NFS server %(server)s is " "unreachable." msgstr "ç„¡æ³•å–æ¶ˆå•Ÿå‹• NFS å„²å­˜å€ %(name)s。NFS 伺æœå™¨ %(server)s無法連線。" #, python-format msgid "" "Unable to deactivate pool %(name)s as it is associated with some templates" msgstr "ç„¡æ³•å–æ¶ˆå•Ÿå‹•å„²å­˜å€ %(name)s,因為它與部分範本相關è¯" #, python-format msgid "Unable to delete pool %(name)s as it is associated with some templates" msgstr "ç„¡æ³•åˆªé™¤å„²å­˜å€ %(name)s,因為它與部分範本相關è¯" #, python-format msgid "" "A volume group named '%(name)s' already exists. Please, choose another name " "to create the logical pool." msgstr "å為 '%(name)s' çš„ç£å€ç¾¤çµ„å·²å­˜åœ¨ã€‚è«‹é¸æ“‡å¦ä¸€å€‹å稱以建立é‚輯儲存å€ã€‚" #, python-format msgid "Unable to update database with deep scan information due error: %(err)s" msgstr "由於下列錯誤,無法使用深層掃æè³‡è¨Šä¾†æ›´æ–°è³‡æ–™åº«ï¼š%(err)s" #, python-format msgid "Storage volume %(name)s already exists" msgstr "儲存ç£å€ %(name)s 已存在" #, python-format msgid "Storage volume %(name)s does not exist in storage pool %(pool)s" msgstr "儲存ç£å€ %(name)s ä¸å­˜åœ¨æ–¼å„²å­˜å€ %(pool)s 中" #, python-format msgid "" "Unable to create storage volume %(volume)s because storage pool %(pool)s is " "not active" msgstr "" #, python-format msgid "Specify %(item)s in order to create storage volume %(volume)s" msgstr "指定 %(item)s 以建立儲存ç£å€ %(volume)s" #, python-format msgid "" "Unable to list storage volumes because storage pool %(pool)s is not active" msgstr "無法列出儲存ç£å€ï¼Œå› ç‚ºå„²å­˜å€ %(pool)s 未處於作用中狀態" #, python-format msgid "" "Unable to create storage volume %(name)s in storage pool %(pool)s. Details: " "%(err)s" msgstr "ç„¡æ³•åœ¨å„²å­˜å€ %(pool)s 中建立儲存ç£å€ %(name)s。詳細資料:%(err)s" #, python-format msgid "" "Unable to list storage volumes in storage pool %(pool)s. Details: %(err)s" msgstr "ç„¡æ³•åˆ—å‡ºå„²å­˜å€ %(pool)s 中的儲存ç£å€ã€‚詳細資料:%(err)s" #, python-format msgid "Unable to wipe storage volumes %(name)s. Details: %(err)s" msgstr "無法清除儲存ç£å€ %(name)s。詳細資料:%(err)s" #, python-format msgid "Unable to delete storage volume %(name)s. Details: %(err)s" msgstr "無法刪除儲存ç£å€ %(name)s。詳細資料:%(err)s" #, python-format msgid "Unable to resize storage volume %(name)s. Details: %(err)s" msgstr "無法調整儲存ç£å€ %(name)s 的大å°ã€‚詳細資料:%(err)s" #, python-format msgid "Storage type %(type)s does not support volume create and delete" msgstr "儲存體類型 %(type)s 䏿”¯æ´ç£å€å»ºç«‹å’Œåˆªé™¤" msgid "Storage volume name must be a string" msgstr "儲存ç£å€å稱必須是字串" msgid "Storage volume allocation must be an integer number" msgstr "儲存ç£å€é…置必須是整數" msgid "" "Storage volume format not supported. Valid formats: bochs, cloop, cow, dmg, " "qcow, qcow2, qed, raw, vmdk, vpc." msgstr "" msgid "Storage volume requires a volume name" msgstr "儲存ç£å€éœ€è¦ç£å€å稱" #, python-format msgid "" "Unable to update database with storage volume information due error: %(err)s" msgstr "由於下列錯誤,無法使用儲存ç£å€è³‡è¨Šä¾†æ›´æ–°è³‡æ–™åº«ï¼š%(err)s" #, python-format msgid "Only one of parameter %(param)s can be specified" msgstr "" #, python-format msgid "Create volume from %(param)s is not supported" msgstr "" msgid "Storage volume capacity must be an integer number." msgstr "" msgid "Storage volume URL must be http://, https://, ftp:// or ftps://." msgstr "" #, python-format msgid "Unable to access file %(url)s. Please, check it." msgstr "" #, python-format msgid "" "Unable to clone storage volume '%(name)s' in pool '%(pool)s'. Details: " "%(err)s" msgstr "" msgid "Specify chunk data and its size to upload a file." msgstr "" msgid "In order to upload a storage volume, specify the 'upload' parameter." msgstr "" msgid "" "Unable to upload chunk data as it does not match with requested chunk size." msgstr "" #, python-format msgid "The storage volume %(vol)s is not under an upload process." msgstr "" msgid "The upload chunk data will exceed the storage volume size." msgstr "" #, python-format msgid "Unable to upload chunk data to storage volume. Details: %(err)s." msgstr "" #, python-format msgid "Interface %(name)s does not exist" msgstr "ä»‹é¢ %(name)s ä¸å­˜åœ¨" #, python-format msgid "Network %(name)s already exists" msgstr "網路 %(name)s 已存在" #, python-format msgid "Network %(name)s does not exist" msgstr "網路 %(name)s ä¸å­˜åœ¨" #, python-format msgid "Subnet %(subnet)s specified for network %(network)s is not valid." msgstr "為網路 %(network)s 指定的å­ç¶²è·¯ %(subnet)s 無效。" #, python-format msgid "Specify a network interface to create bridged network %(name)s" msgstr "指定網路介é¢ä»¥å»ºç«‹æ©‹æŽ¥çš„網路 %(name)s" #, python-format msgid "Unable to delete active network %(name)s" msgstr "無法刪除作用中的網路 %(name)s" #, python-format msgid "Interface %(iface)s specified for network %(network)s is already in use" msgstr "為網路 %(network)s æŒ‡å®šçš„ä»‹é¢ %(iface)s 已在使用中" msgid "Interface should be bare NIC, bonding or bridge device." msgstr "介颿‡‰è©²æ˜¯è£¸éœ² NICã€æŽ¥åˆè£ç½®æˆ–橋接器è£ç½®ã€‚" #, python-format msgid "Unable to create network %(name)s. Details: %(err)s" msgstr "無法建立網路 %(name)s。詳細資料:%(err)s" #, python-format msgid "Unable to find a free IP address for network '%(name)s'" msgstr "找ä¸åˆ°ç¶²è·¯ '%(name)s' çš„å¯ç”¨ IP ä½å€" #, python-format msgid "The interface %(iface)s already exists." msgstr "" msgid "Network name must be a string without slashes (/) or quotes (\")" msgstr "" msgid "Supported network types are isolated, NAT and bridge" msgstr "å—æ”¯æ´çš„網路類型是隔離å¼ã€NAT 和橋接器" msgid "Network subnet must be a string with IP address and prefix or netmask" msgstr "網路的å­ç¶²è·¯å¿…é ˆæ˜¯å«æœ‰ IP ä½å€ã€å­—首或網路é®ç½©çš„字串" msgid "Network interface must be a string" msgstr "網路介é¢å¿…須是字串" msgid "Network VLAN ID must be an integer between 1 and 4094" msgstr "網路 VLAN ID 必須是介於 1 å’Œ 4094 之間的整數" msgid "Specify name and type to create a Network" msgstr "指定å稱和類型以建立網路" #, python-format msgid "" "Unable to delete network %(name)s. There are some virtual machines %(vms)s " "and/or templates linked to this network." msgstr "" #, python-format msgid "" "Unable to deactivate network %(name)s. There are some virtual machines " "%(vms)s and/or templates linked to this network." msgstr "" #, python-format msgid "Bridge device %(name)s can not be the trunk device of a VLAN." msgstr "橋接器è£ç½® %(name)s ä¸èƒ½æ˜¯ VLAN 的幹線è£ç½®ã€‚" #, python-format msgid "Failed to activate interface %(iface)s: %(err)s." msgstr "ç„¡æ³•å•Ÿå‹•ä»‹é¢ %(iface)s:%(err)s。" #, python-format msgid "" "Failed to activate interface %(iface)s. Please check the physical link " "status." msgstr "ç„¡æ³•å•Ÿå‹•ä»‹é¢ %(iface)s。請檢查實際éˆçµç‹€æ…‹ã€‚" #, python-format msgid "Failed to start network %(name)s. Details: %(err)s" msgstr "" #, python-format msgid "Debug report %(name)s does not exist" msgstr "除錯報告 %(name)s ä¸å­˜åœ¨" msgid "Debug report tool not found in system" msgstr "在系統中找ä¸åˆ°é™¤éŒ¯å ±å‘Šå·¥å…·" #, python-format msgid "Unable to create debug report %(name)s. Details: %(err)s." msgstr "無法建立除錯報告 %(name)s。詳細資料:%(err)s。" #, python-format msgid "Can not find any debug report with the given name %(name)s" msgstr "" #, python-format msgid "Unable to generate debug report %(name)s. Details: %(err)s" msgstr "無法產生除錯報告 %(name)s。詳細資料:%(err)s" msgid "You should give a name for the debug report file." msgstr "" msgid "" "Debug report name must be a string. Only letters, digits, underscore ('_') " "and hyphen ('-') are allowed." msgstr "" #, python-format msgid "" "The debug report with specified name \"%(name)s\" already exists. Please use " "another one." msgstr "å為 '%(name)s' çš„ç£å€ç¾¤çµ„å·²å­˜åœ¨ã€‚è«‹é¸æ“‡å¦ä¸€å€‹å稱以建立é‚輯儲存å€ã€‚" #, python-format msgid "Storage server %(server)s was not used by Kimchi" msgstr "Kimchi 未使用儲存體伺æœå™¨ %(server)s" #, python-format msgid "Distro '%(name)s' does not exist" msgstr "Distro '%(name)s' ä¸å­˜åœ¨" #, python-format msgid "Partition %(name)s does not exist in the host" msgstr "åˆ†å‰²å€ %(name)s ä¸å­˜åœ¨æ–¼ä¸»æ©Ÿä¸­" msgid "Unable to shutdown host machine as there are running virtual machines" msgstr "無法關閉主機,因為有一些虛擬機器正在執行中" msgid "Unable to reboot host machine as there are running virtual machines" msgstr "ç„¡æ³•å°‡ä¸»æ©Ÿé‡æ–°é–‹æ©Ÿï¼Œå› ç‚ºæœ‰ä¸€äº›è™›æ“¬æ©Ÿå™¨æ­£åœ¨åŸ·è¡Œä¸­" #, python-format msgid "Node device '%(name)s' not found" msgstr "找ä¸åˆ°ç¯€é»žè£ç½® '%(name)s'" msgid "Conflicting flag filters specified." msgstr "" msgid "No packages marked for update" msgstr "沒有套件標示為è¦é€²è¡Œæ›´æ–°" #, python-format msgid "Package %(name)s is not marked to be updated." msgstr "套件 %(name)s 未標示為è¦é€²è¡Œæ›´æ–°ã€‚" #, python-format msgid "Error while getting packages marked to be updated. Details: %(err)s" msgstr "å–得標示為è¦é€²è¡Œæ›´æ–°çš„套件時發生錯誤。詳細資料:%(err)s" msgid "There is no compatible package manager for this system." msgstr "沒有此系統的相容套件管ç†ç¨‹å¼ã€‚" #, python-format msgid "Unable to find %(item)s in datastore" msgstr "在資料儲存庫中找ä¸åˆ° %(item)s" #, python-format msgid "Invalid URI %(uri)s" msgstr "URI %(uri)s 無效" #, python-format msgid "Timeout while running command '%(cmd)s' after %(seconds)s seconds" msgstr "執行指令 '%(cmd)s' %(seconds)s 秒之後逾時" msgid "Unable to choose a virtual machine name" msgstr "" #, python-format msgid "Invalid data value '%(value)s'" msgstr "" #, python-format msgid "Invalid data unit '%(unit)s'" msgstr "" msgid "Invalid storage type. Types supported: 'cdrom', 'disk'" msgstr "å„²å­˜é«”é¡žåž‹ç„¡æ•ˆã€‚å—æ”¯æ´çš„類型:'cdrom'" #, python-format msgid "The path '%(value)s' is not a valid local/remote path for the device" msgstr "" msgid "Only CDROM path can be update." msgstr "" #, python-format msgid "" "The storage device %(dev_name)s does not exist in the virtual machine " "%(vm_name)s" msgstr "" #, python-format msgid "Error while creating new storage device: %(error)s" msgstr "建立新的儲存è£ç½®æ™‚發生錯誤:%(error)s" #, python-format msgid "Error while updating storage device: %(error)s" msgstr "更新儲存è£ç½®æ™‚發生錯誤:%(error)s" #, python-format msgid "Error while removing storage device: %(error)s" msgstr "移除儲存è£ç½®æ™‚發生錯誤:%(error)s" msgid "Do not support IDE device hot plug" msgstr "" msgid "" "Specify type and path or type and pool/volume to add a new virtual machine " "disk" msgstr "指定類型和路徑以新增虛擬機器ç£ç¢Ÿ" msgid "Specify path to update virtual machine disk" msgstr "指定路徑以更新虛擬機器ç£ç¢Ÿ" #, python-format msgid "Controller type %(type)s limitation of %(limit)s devices reached" msgstr "" #, python-format msgid "Cannot retrieve disk path information for given pool/volume: %(error)s" msgstr "" msgid "Volume already in use by other virtual machine." msgstr "" msgid "" "Only one of path or pool/volume can be specified to add a new virtual " "machine disk" msgstr "指定類型和路徑以新增虛擬機器ç£ç¢Ÿ" #, python-format msgid "" "Volume chosen with format %(format)s does not fit in the storage type " "%(type)s" msgstr "" msgid "YUM Repository ID must be one word only string." msgstr "YUM 儲存庫 ID 必須是僅é™ä¸€å€‹å–®å­—的字串。" msgid "Repository URL must be an http://, ftp:// or file:// URL." msgstr "儲存庫 URL 必須是 http://ã€ftp:// 或 file:// URL。" msgid "" "Repository configuration is a dictionary with specific values according to " "repository type." msgstr "儲存庫é…ç½®æ˜¯å­—å…¸ï¼Œå…¶ä¸­åŒ…å«æ–¼å„²å­˜åº«é¡žåž‹å°æ‡‰çš„特定值。" msgid "Distribution to DEB repository must be a string" msgstr "DEB 儲存庫的發行套件必須是字串" msgid "Components to DEB repository must be listed in a array" msgstr "DEB 儲存庫的元件必須以陣列的形å¼åˆ—出" msgid "Components to DEB repository must be a string" msgstr "DEB 儲存庫的元件必須是字串" msgid "Mirror list to repository must be a string" msgstr "" msgid "YUM Repository name must be string." msgstr "YUM 儲存庫å稱必須是字串。" msgid "GPG check must be a boolean value." msgstr "GPG 檢查必須是布林值。" msgid "GPG key must be a URL pointing to the ASCII-armored file." msgstr "GPG é‡‘é‘°å¿…é ˆæ˜¯æŒ‡å‘ ASCII è£ç”²æª”案的 URL。" #, python-format msgid "Could not update repository %(repo_id)s." msgstr "無法更新儲存庫 %(repo_id)s。" #, python-format msgid "Repository %(repo_id)s does not exist." msgstr "儲存庫 %(repo_id)s ä¸å­˜åœ¨ã€‚" msgid "" "Specify repository base URL, mirror list or metalink in order to create or " "update a YUM repository." msgstr "" msgid "Repository management tool was not recognized for your system." msgstr "未能辨識系統的儲存庫管ç†å·¥å…·ã€‚" #, python-format msgid "Repository %(repo_id)s is already enabled." msgstr "已啟用儲存庫 %(repo_id)s。" #, python-format msgid "Repository %(repo_id)s is already disabled." msgstr "å·²åœç”¨å„²å­˜åº« %(repo_id)s。" #, python-format msgid "Could not remove repository %(repo_id)s." msgstr "無法移除儲存庫 %(repo_id)s。" #, python-format msgid "Could not write repository configuration file %(repo_file)s" msgstr "無法寫入儲存庫é…置檔 %(repo_file)s" msgid "Specify repository distribution in order to create a DEB repository." msgstr "指定儲存庫發行套件以建立 DEB 儲存庫。" #, python-format msgid "Could not enable repository %(repo_id)s." msgstr "無法啟用儲存庫 %(repo_id)s。" #, python-format msgid "Could not disable repository %(repo_id)s." msgstr "無法åœç”¨å„²å­˜åº« %(repo_id)s。" msgid "YUM Repository ID already exists" msgstr "YUM 儲存庫 ID 已存在" msgid "YUM Repository name must be a string" msgstr "YUM 儲存庫å稱必須是字串" #, python-format msgid "Unable to list repositories. Details: '%(err)s'" msgstr "無法列出儲存庫。詳細資料:'%(err)s'" #, python-format msgid "Unable to retrieve repository information. Details: '%(err)s'" msgstr "無法擷å–儲存庫資訊。詳細資料:'%(err)s'" #, python-format msgid "Unable to add repository. Details: '%(err)s'" msgstr "無法新增儲存庫。詳細資料:'%(err)s'" #, python-format msgid "Unable to remove repository. Details: '%(err)s'" msgstr "無法移除儲存庫。詳細資料:'%(err)s'" #, python-format msgid "" "Configuration items: '%(items)s' are not supported by repository manager" msgstr "" msgid "Repository metalink must be an http://, ftp:// or file:// URL." msgstr "" msgid "Cannot specify mirrorlist and metalink at the same time." msgstr "" #, python-format msgid "" "Virtual machine '%(vm)s' must be stopped before creating a snapshot of it." msgstr "" #, python-format msgid "" "Unable to create snapshot '%(name)s' on virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "Snapshot '%(name)s' does not exist on virtual machine '%(vm)s'." msgstr "" #, python-format msgid "" "Unable to retrieve snapshot '%(name)s' on virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "Unable to list snapshots on virtual machine '%(vm)s'. Details: %(err)s" msgstr "" #, python-format msgid "" "Unable to delete snapshot '%(name)s' on virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "" "Unable to retrieve current snapshot of virtual machine '%(vm)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "" "Unable to revert virtual machine '%(vm)s' to snapshot '%(name)s'. Details: " "%(err)s" msgstr "" #, python-format msgid "" "Unable to create snapshot of virtual machine '%(vm)s' because it contains a " "disk with format '%(format)s'; only 'qcow2' is supported." msgstr "" msgid "The number of vCPUs is too large for this system." msgstr "" msgid "Invalid vCPU/topology combination." msgstr "" msgid "This host (or current configuration) does not allow CPU topology." msgstr "" msgid "ERROR CODE" msgstr "錯誤碼" msgid "REASON" msgstr "原因" msgid "STACK" msgstr "堆疊" msgid "Go to Homepage" msgstr "跳至首é " msgid "Create a New Virtual Machine" msgstr "建立新的虛擬機器" msgid "Virtual Machine Name" msgstr "虛擬機器å稱" msgid "" "The name used to identify the virtual machine. If omitted, a name will be " "chosen based on the template used." msgstr "用來識別虛擬機器的å稱。如果çœç•¥ï¼Œå‰‡æœƒæ ¹æ“šæ‰€ç”¨çš„ç¯„æœ¬é¸æ“‡å稱。" msgid "Template" msgstr "範本" msgid "Please create a template first." msgstr "請先建立範本。" msgid "Create a Template" msgstr "建立範本" msgid "Please choose a template." msgstr "è«‹é¸æ“‡ç¯„本。" msgid "OS" msgstr "OS" msgid "OS Version" msgstr "OS 版本" msgid "CPUS" msgstr "CPUS" msgid "Memory" msgstr "記憶體" msgid "Create" msgstr "建立" msgid "Creating..." msgstr "" msgid "Edit Guest" msgstr "編輯客體" msgid "General" msgstr "一般" msgid "Storage" msgstr "儲存體" msgid "Interface" msgstr "介é¢" msgid "Permission" msgstr "版本" msgid "Host PCI Device" msgstr "" msgid "Snapshot" msgstr "" msgid "Name" msgstr "å稱" msgid "CPUs" msgstr "CPU" msgid "Memory (MB)" msgstr "記憶體" msgid "Icon" msgstr "圖示" msgid "Device" msgstr "è£ç½®å稱" msgid "Path" msgstr "NFS 路徑" msgid "Network" msgstr "網路" msgid "Type" msgstr "類型" msgid "MAC Address" msgstr "" msgid "Available system users and groups" msgstr "" msgid "Selected system users and groups" msgstr "" msgid "User" msgstr "" msgid "All" msgstr "全部" msgid "To Add" msgstr "" msgid "Added" msgstr "" msgid "filter" msgstr "" msgid "Product" msgstr "" msgid "Vendor" msgstr "供應商" msgid "Created" msgstr "" msgid "Save" msgstr "儲存" msgid "Replace" msgstr "å–代" msgid "Detach" msgstr "分離" msgid "Cancel" msgstr "å–æ¶ˆ " msgid "revert" msgstr "" msgid "Add a Storage Device to VM" msgstr "將儲存è£ç½®æ–°å¢žè‡³ VM" msgid "Device Type" msgstr "è£ç½®é¡žåž‹" msgid "The device type. Currently, \"cdrom\" and \"disk\" are supported." msgstr "è£ç½®é¡žåž‹ã€‚ç›®å‰åƒ…æ”¯æ´ \"cdrom\"。" msgid "Storage Pool" msgstr "儲存å€" msgid "Storage pool which volume located in" msgstr "儲存å€è·¯å¾‘必須是字串" msgid "Storage Volume" msgstr "儲存å€å稱" msgid "Storage volume to be attached" msgstr "儲存ç£å€å稱必須是字串" msgid "File Path" msgstr "檔案路徑" msgid "The ISO file path in the server for CDROM." msgstr "CDROM çš„ ISO 檔案路徑在伺æœå™¨ä¸­ã€‚" msgid "Attach" msgstr "連接" msgid "Start" msgstr "é–‹å§‹" msgid "Reset" msgstr "é‡è¨­" msgid "Pause" msgstr "" msgid "Resume" msgstr "" msgid "Power Off" msgstr "" msgid "Actions" msgstr "動作" msgid "Connect" msgstr "連接" msgid "Clone" msgstr "" msgid "Edit" msgstr "編輯" msgid "Shut Down" msgstr "關閉" msgid "Delete" msgstr "刪除" msgid "The username or password you entered is incorrect. Please try again." msgstr "您輸入的使用者åç¨±æˆ–å¯†ç¢¼ä¸æ­£ç¢ºã€‚è«‹é‡è©¦ã€‚" msgid "This field is required." msgstr "æ­¤æ¬„ä½æ˜¯å¿…è¦çš„。" msgid "Log in" msgstr "登入" msgid "Logging in..." msgstr "正在登入..." msgid "Host" msgstr "主機" msgid "Guests" msgstr "客體" msgid "Templates" msgstr "範本" msgid "Failed to get application configuration" msgstr "無法å–得應用程å¼é…ç½®" msgid "This is not a valid Linux path" msgstr "這是無效的 Linux 路徑" msgid "This is not a valid URL." msgstr "這是無效的 URL。" msgid "No such data available." msgstr "沒有此類å¯ç”¨è³‡æ–™ã€‚" msgid "" "Can not contact the host system. Verify the host system is up and that you " "have network connectivity to it. HTTP request response %1. " msgstr "" "無法連接至主機系統。請驗證主機系統是å¦å·²å•Ÿå‹•ï¼Œä»¥åŠæ‚¨æ˜¯å¦å…·æœ‰èˆ‡å®ƒçš„連線。HTTP " "è¦æ±‚回應為 %1。" msgid "Unable to read file." msgstr "" msgid "Error while uploading file." msgstr "" msgid "Delete Confirmation" msgstr "刪除確èª" msgid "OK" msgstr "確定" msgid "Confirm" msgstr "確èª" msgid "Warning" msgstr "警告" msgid "Cloning..." msgstr "" msgid "Loading..." msgstr "正在載入..." msgid "An error occurred while retrieving system information." msgstr "" msgid "Retry" msgstr "é‡è©¦" msgid "Detailed message:" msgstr "詳細的訊æ¯ï¼š" msgid "No ISO found" msgstr "" msgid "This is not a valid ISO file." msgstr "這是無效的 ISO 檔案。" msgid "This may take a long time. Do you want to continue?" msgstr "它將需è¦å¾ˆé•·æ™‚間。è¦ç¹¼çºŒå—Žï¼Ÿ" msgid "This will permanently delete the template. Would you like to continue?" msgstr "此動作將永久地刪除範本。è¦ç¹¼çºŒå—Žï¼Ÿ" msgid "Unable to shut down system as there are some virtual machines running!" msgstr "無法關閉系統,因為有幾個虛擬機器正在執行中ï¼" msgid "Max:" msgstr "上é™ï¼š" msgid "Utilization" msgstr "使用率" msgid "Available" msgstr "å¯ç”¨" msgid "Read Rate" msgstr "讀å–速率" msgid "Write Rate" msgstr "寫入速率" msgid "Received" msgstr "已接收" msgid "Sent" msgstr "已傳é€" msgid "" "Shutting down or restarting host will cause unsaved work lost. Continue to " "shut down/restarting?" msgstr "é—œé–‰æˆ–é‡æ–°å•Ÿå‹•主機將導致未儲存的工作éºå¤±ã€‚è¦ç¹¼çºŒé—œé–‰/釿–°å•Ÿå‹•嗎?" msgid "" "Repository will be removed permanently and can't be recovered. Do you want " "to continue?" msgstr "將會永久地移除儲存庫並且無法回復。è¦ç¹¼çºŒå—Žï¼Ÿ" msgid "Repositories" msgstr "儲存庫" msgid "ID" msgstr "ID" msgid "Base URL" msgstr "基本 URL" msgid "Is Mirror" msgstr "æ˜¯é¡æ˜ " msgid "URL Args" msgstr "URL 引數" msgid "Enabled" msgstr "已啟用" msgid "GPG Check" msgstr "GPG 檢查" msgid "GPG Key" msgstr "GPG 金鑰" msgid "Add" msgstr "新增" msgid "Remove" msgstr "移除" msgid "Enable" msgstr "啟用" msgid "Disable" msgstr "åœç”¨" msgid "Software Updates" msgstr "軟體更新" msgid "Package Name" msgstr "套件å稱" msgid "Version" msgstr "版本" msgid "Architecture" msgstr "æž¶æ§‹" msgid "Repository" msgstr "儲存庫" msgid "Update All" msgstr "全部更新" msgid "Updating..." msgstr "正在更新..." msgid "Failed to retrieve packages update information." msgstr "" msgid "Failed to update package(s)." msgstr "無法更新套件。" msgid "" "Debug report will be removed permanently and can't be recovered. Do you want " "to continue?" msgstr "將會永久地移除除錯報告並且無法回復。è¦ç¹¼çºŒå—Žï¼Ÿ" msgid "Debug Reports" msgstr "除錯報告" msgid "Generated Time" msgstr "產生時間" msgid "Generate" msgstr "產生" msgid "Generating..." msgstr "正在產生..." msgid "Rename" msgstr "釿–°å‘½å" msgid "Download" msgstr "下載" msgid "" "Report name should contain only letters, digits, underscore ('_') and/or " "hyphen ('-')." msgstr "報告åç¨±åªæ‡‰è©²åŒ…å«å­—æ¯ã€æ•¸å­—åŠ/或連字號 ('-')。" msgid "Pending..." msgstr "正在載入..." msgid "Report name is the same as the original one." msgstr "" msgid "" "This will delete the virtual machine and its virtual disks. This operation " "cannot be undone. Would you like to continue?" msgstr "此動作將會刪除虛擬機器åŠå…¶è™›æ“¬ç£ç¢Ÿã€‚此作業無法復原。è¦ç¹¼çºŒå—Žï¼Ÿ" msgid "Power off Confirmation" msgstr "刪除確èª" msgid "" "This action may produce undesirable results, for example unflushed disk " "cache in the guest. Would you like to continue?" msgstr "" msgid "Reset Confirmation" msgstr "刪除確èª" msgid "" "There is a risk of data loss caused by reset without the guest OS shutdown. " "Would you like to continue?" msgstr "" msgid "Shut Down Confirmation" msgstr "刪除確èª" msgid "Note the guest OS may ignore this request. Would you like to continue?" msgstr "此動作將永久地刪除範本。è¦ç¹¼çºŒå—Žï¼Ÿ" msgid "Virtual Machine delete Confirmation" msgstr "" msgid "" "This virtual machine is not persistent. Power Off will delete it. Continue?" msgstr "" msgid "" "When the target guest has SCSI or iSCSI volumes, they will be cloned on " "default storage pool. The same will happen when the target pool does not " "have enough space to clone the volumes. Do you want to continue?" msgstr "" msgid "" "This CDROM will be detached permanently and you can re-attach it. Continue " "to detach it?" msgstr "" "將會永久地分離此 CDROM,但是您å¯ä»¥å°‡å…¶é‡æ–°é€£æŽ¥ã€‚è¦ç¹¼çºŒåˆ†é›¢æ­¤ CDROM 嗎?" msgid "Attaching..." msgstr "正在連接..." msgid "Replacing..." msgstr "正在å–代..." msgid "Successfully attached!" msgstr "已順利連接ï¼" msgid "Successfully replaced!" msgstr "已順利å–代ï¼" msgid "Successfully detached!" msgstr "已順利分離ï¼" msgid "" "This disk will be detached permanently and you can re-attach it. Continue to " "detach it?" msgstr "" msgid "interface:" msgstr "" msgid "address:" msgstr "" msgid "link_type:" msgstr "" msgid "block:" msgstr "" msgid "drive_type:" msgstr "" msgid "model:" msgstr "" msgid "Affected devices:" msgstr "" msgid "The VLAN id must be between 1 and 4094." msgstr "VLAN ID 必須介於 1 å’Œ 4094 之間。" msgid "unavailable" msgstr "無法使用" msgid "" "This action will interrupt network connectivity for any virtual machine that " "depend on this network." msgstr "此動作將會岔斷ä¾è³´æ–¼æ­¤ç¶²è·¯ä¹‹æ‰€æœ‰è™›æ“¬æ©Ÿå™¨çš„網路連線功能。" msgid "Create a network" msgstr "建立網路" msgid "" "This network is not persistent. Instead of stop, this action will " "permanently delete it. Would you like to continue?" msgstr "" "此儲存å€ä¸æ˜¯æŒçºŒæ€§çš„ã€‚æ­¤å‹•ä½œä¸æ˜¯æœƒå°‡å…¶å–消啟動,而是會將其永久地刪除。è¦ç¹¼çºŒ" "嗎?" msgid "" "The bridged VLAN tag may not work well with NetworkManager enabled. You " "should consider disabling it." msgstr "" msgid "" "This will permanently delete the storage pool. Would you like to continue?" msgstr "此動作將永久地刪除儲存å€ã€‚è¦ç¹¼çºŒå—Žï¼Ÿ" msgid "This storage pool is empty." msgstr "æ­¤å„²å­˜å€æ˜¯ç©ºçš„。" msgid "" "It will format your disk and you will loose any data in there, are you sure " "to continue? " msgstr "此動作會格å¼åŒ–您的ç£ç¢Ÿï¼Œè€Œæ‚¨å°‡æœƒéºå¤±ç£ç¢Ÿä¸­çš„æ‰€æœ‰è³‡æ–™ã€‚確定è¦ç¹¼çºŒå—Žï¼Ÿ" msgid "SCSI Fibre Channel" msgstr "SCSI 光纖通é“" msgid "No SCSI adapters found." msgstr "找ä¸åˆ° SCSI 酿ޥå¡ã€‚" msgid "Loading iSCSI targets..." msgstr "" msgid "No iSCSI found. Please input one." msgstr "" msgid "Failed to load iSCSI targets." msgstr "" msgid "The storage pool name can not be blank." msgstr "儲存å€å稱ä¸èƒ½ç©ºç™½ã€‚" msgid "The storage pool path can not be blank." msgstr "儲存å€è·¯å¾‘ä¸èƒ½ç©ºç™½ã€‚" msgid "NFS server mount path can not be blank." msgstr "NFS 伺æœå™¨è£è¼‰è·¯å¾‘ä¸èƒ½ç©ºç™½ã€‚" msgid "Invalid NFS mount path." msgstr "NFS è£è¼‰è·¯å¾‘無效。" msgid "No logical device selected." msgstr "未é¸å–é‚輯è£ç½®ã€‚" msgid "The iSCSI target can not be blank." msgstr "iSCSI 目標ä¸èƒ½ç©ºç™½ã€‚" msgid "Server name can not be blank." msgstr "伺æœå™¨å稱ä¸èƒ½ç©ºç™½ã€‚" msgid "This is not a valid Server Name or IP. Please, modify it." msgstr "" msgid "Looking for available partitions ..." msgstr "正在尋找å¯ç”¨çš„åˆ†å‰²å€ ..." msgid "No available partitions found." msgstr "找ä¸åˆ°å¯ç”¨çš„分割å€ã€‚" msgid "" "This storage pool is not persistent. Instead of deactivate, this action will " "permanently delete it. Would you like to continue?" msgstr "" "此儲存å€ä¸æ˜¯æŒçºŒæ€§çš„ã€‚æ­¤å‹•ä½œä¸æ˜¯æœƒå°‡å…¶å–消啟動,而是會將其永久地刪除。è¦ç¹¼çºŒ" "嗎?" msgid "Unable to retrieve partitions information." msgstr "無法擷å–儲存庫資訊。詳細資料:'%(err)s'" msgid "In progress..." msgstr "" msgid "Failed!" msgstr "" msgid "CDROM path needs to be a valid local/remote path and cannot be blank." msgstr "" msgid "Disk pool or volume cannot be blank." msgstr "儲存å€å稱ä¸èƒ½ç©ºç™½ã€‚" msgid "Peers" msgstr "" msgid "Searching" msgstr "" msgid "No peers found." msgstr "" msgid "Help" msgstr "說明" msgid "About" msgstr "相關" msgid "Log out" msgstr "登出" msgid "Version:" msgstr "版本:" msgid "Session timeout, please re-login." msgstr "" msgid "User Name" msgstr "使用者å稱" msgid "Password" msgstr "密碼" msgid "Generate a New Debug Report" msgstr "產生新的除錯報告" msgid "Report Name" msgstr "報告å稱" msgid "" "The name used to identify the report. If omitted, a name will be chosen " "based on current time. Name can contain: letters, digits, underscore (\"_\") " "and hyphen (\"-\")." msgstr "" "用來識別報告的å稱。如果çœç•¥ï¼Œå‰‡æœƒæ ¹æ“šç¾è¡Œæ™‚間鏿“‡å稱。å稱å¯ä»¥åŒ…å«ï¼šå­—æ¯ã€" "數字和連字號 (\"-\")。" msgid "Rename a Debug Report" msgstr "產生新的除錯報告" msgid "" "The name used to identify the report. Name can contain: letters, digits and " "hyphen (\"-\")." msgstr "" "用來識別報告的å稱。如果çœç•¥ï¼Œå‰‡æœƒæ ¹æ“šç¾è¡Œæ™‚間鏿“‡å稱。å稱å¯ä»¥åŒ…å«ï¼šå­—æ¯ã€" "數字和連字號 (\"-\")。" msgid "Submit" msgstr "" msgid "Add a Repository" msgstr "新增儲存庫" msgid "Identifier" msgstr "ID" msgid "Single word, unique identifier for the repository." msgstr "單字,儲存庫的唯一 ID。" msgid "Textual name for the repository." msgstr "儲存庫的文字å稱。" msgid "URL" msgstr "URL" msgid "Required Field" msgstr "å¿…è¦æ¬„ä½" msgid "URL to the repository. Supported protocols are http, ftp, and file." msgstr "儲存庫的 URLã€‚å—æ”¯æ´çš„通訊å”定包括 httpã€ftp å’Œ file。" msgid "Repository is a mirror" msgstr "å„²å­˜åº«æ˜¯é¡æ˜ ã€‚" msgid "Distribution" msgstr "發行套件" msgid "Distribution of the DEB repository." msgstr "DEB 儲存庫的發行套件。" msgid "Components" msgstr "元件" msgid "List of components in DEB repository." msgstr "DEB 儲存庫中的元件清單。" msgid "Edit Repository" msgstr "編輯儲存庫" msgid "Mirror List URL" msgstr "顿˜ æ¸…å–® URL" msgid "Yes" msgstr "是" msgid "No" msgstr "å¦" msgid "Add a Volume to Storage Pool" msgstr "" msgid "Fetch from remote URL" msgstr "" msgid "Enter the remote URL here." msgstr "" msgid "Upload a file" msgstr "" msgid "Choose the file you want to upload." msgstr "" msgid "Define a New Storage Pool" msgstr "定義新的儲存å€" msgid "Storage Pool Name" msgstr "儲存å€å稱" msgid "" "The name used to identify the storage pools, and it should not be empty." msgstr "用來識別儲存å€çš„åç¨±ï¼Œä¸æ‡‰è©²æ˜¯ç©ºçš„。" msgid "Storage Pool Type" msgstr "儲存å€é¡žåž‹" msgid "Storage Path" msgstr "儲存體路徑" msgid "" "The path of the Storage Pool. Each Storage Pool must have a unique path." msgstr "儲存å€çš„路徑。æ¯ä¸€å€‹å„²å­˜å€éƒ½å¿…須有一個唯一的路徑。" msgid "" "Kimchi will try to create the directory when it does not already exist in " "your system." msgstr "Kimchi 將嘗試建立該目錄(當該目錄尚ä¸å­˜åœ¨æ–¼ç³»çµ±ä¸­æ™‚)。" msgid "NFS Server IP" msgstr "NFS 伺æœå™¨ IP" msgid "NFS server IP or hostname. It can be input or chosen from history." msgstr "NFS 伺æœå™¨ IP 或主機å稱。å¯ä»¥ç›´æŽ¥è¼¸å…¥ï¼Œä¹Ÿå¯ä»¥å¾žæ­·ç¨‹ä¸­é¸æ“‡ã€‚" msgid "NFS Path" msgstr "NFS 路徑" msgid "The NFS exported path on NFS server." msgstr "NFS 伺æœå™¨ä¸Š NFS 匯出的路徑。" msgid "Device path" msgstr "è£ç½®è·¯å¾‘" msgid "iSCSI Server" msgstr "iSCSI 伺æœå™¨" msgid "iSCSI server IP or hostname. It should not be empty." msgstr "iSCSI 伺æœå™¨ IP 或主機åç¨±ã€‚å®ƒä¸æ‡‰è©²æ˜¯ç©ºçš„。" msgid "Server" msgstr "伺æœå™¨" msgid "Port" msgstr "埠" msgid "Target" msgstr "目標" msgid "The iSCSI target on iSCSI server" msgstr "iSCSI 伺æœå™¨ä¸Šçš„ iSCSI 目標" msgid "Add iSCSI Authentication" msgstr "新增 iSCSI 鑑別" msgid "iSCSI Authentication" msgstr "iSCSI 鑑別" msgid "SCSI Adapter" msgstr "SCSI 酿ޥå¡" msgid "Please, wait..." msgstr "è«‹ç¨å€™..." msgid "Add Template" msgstr "新增範本" msgid "Where is the source media for this template? " msgstr "此範本的來æºåª’體使–¼ä½•處?" msgid "Local ISO Image" msgstr "本端 ISO æ˜ åƒæª”" msgid "Local Image File" msgstr "" msgid "Remote ISO Image" msgstr "é ç«¯ ISO æ˜ åƒæª”" msgid "Search ISOs" msgstr "æœå°‹ ISO" msgid "The following ISOs are available:" msgstr "下列 ISO å¯ç”¨ï¼š" msgid "OS: " msgstr "OS:" msgid "Version: " msgstr "版本:" msgid "Size: " msgstr "大å°ï¼š" msgid "Search more ISOs" msgstr "æœå°‹æ›´å¤š ISO" msgid "Create Templates from Selected ISO" msgstr "å¾žæ‰€é¸ ISO 建立範本" msgid "I want to use a specific ISO file" msgstr "我想使用特定的 ISO 檔案" msgid "Loading default remote ISOs ..." msgstr "正在載入é è¨­é ç«¯ ISO ..." msgid "Arch: " msgstr "架構:" msgid "I want to use a custom URL" msgstr "我想使用自訂 URL" msgid "Edit Template" msgstr "編輯範本" msgid "Processor" msgstr "處ç†å™¨" msgid "CDROM" msgstr "CDROM" msgid "Image File" msgstr "" msgid "Graphics" msgstr "圖形å¡" msgid "Disk(GB)" msgstr "" msgid "Disk Format" msgstr "" msgid "CPU Number" msgstr "CPU 數目" msgid "Manually set CPU topology" msgstr "" msgid "Cores" msgstr "" msgid "Threads" msgstr "" msgid "CPU" msgstr "CPU" msgid "Disk I/O" msgstr "ç£ç¢Ÿ I/O" msgid "Network I/O" msgstr "網路 I/O" msgid "Livetile" msgstr "Livetile" msgid "No guests found." msgstr "找ä¸åˆ°å®¢é«”。" msgid "Shut down" msgstr "關閉" msgid "Restart" msgstr "釿–°å•Ÿå‹•" msgid "Basic Information" msgstr "基本資訊" msgid "OS Distro" msgstr "OS Distro" msgid "OS Code Name" msgstr "OS 程å¼ç¢¼å稱" msgid "CPU(s)" msgstr "" msgid "System Statistics" msgstr "系統統計資料" msgid "Update Progress" msgstr "更新進度" msgid "Network Name" msgstr "網路å稱" msgid "State" msgstr "狀態" msgid "Network Type" msgstr "網路類型" msgid "Address Space" msgstr "ä½å€ç©ºé–“" msgid "Name should not contain '/' and '\"'." msgstr "儲存å€åç¨±ç„¡æ•ˆã€‚å®ƒä¸æ‡‰è©²åŒ…å« '/'。" msgid "Isolated: no external network connection" msgstr "已隔離:沒有實體網路連線" msgid "NAT: outbound physical network connection only" msgstr "NAT:僅é™å‡ºåŸ å¯¦é«”網路連線" msgid "Bridged: Virtual machines are connected to physical network directly" msgstr "已橋接:虛擬機器直接已連接至實體網路" msgid "(No interfaces found)" msgstr "" msgid "Destination" msgstr "目的地:" msgid "Enable VLAN" msgstr "啟用 VLAN:" msgid "VLAN ID" msgstr "VLAN ID:" msgid "Stop" msgstr "åœæ­¢" msgid "%Used" msgstr "" msgid "Location" msgstr "ä½ç½®" msgid "Capacity" msgstr "容é‡" msgid "Allocated" msgstr "å·²é…ç½®" msgid "active" msgstr "作用中" msgid "inactive" msgstr "éžä½œç”¨ä¸­" msgid "Deactivate" msgstr "å–æ¶ˆå•Ÿå‹•" msgid "Activate" msgstr "啟動" msgid "Add Volume" msgstr "" msgid "Extend" msgstr "" msgid "Undefine" msgstr "å–æ¶ˆå®šç¾©" msgid "Format" msgstr "æ ¼å¼ï¼š" msgid "Allocation" msgstr "é…置:" msgid "No templates found." msgstr "找ä¸åˆ°ç¯„本。" kimchi-1.5.0/src/000077500000000000000000000000001254252253000135505ustar00rootroot00000000000000kimchi-1.5.0/src/Makefile.am000066400000000000000000000030711254252253000156050ustar00rootroot00000000000000# # Kimchi # # Copyright IBM Corp, 2013-2015 # # 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 SUBDIRS = kimchi distros.d nginx EXTRA_DIST = kimchid.in \ kimchi.conf.in \ firewalld.xml \ $(NULL) bin_SCRIPTS = kimchid confdir = $(sysconfdir)/kimchi dist_conf_DATA = kimchi.conf template.conf BUILT_SOURCES = kimchi.conf do_substitution = \ sed -e 's,[@]pythondir[@],$(pythondir),g' \ -e 's,[@]localstatedir[@],$(localstatedir),g' \ -e 's,[@]PACKAGE[@],$(PACKAGE),g' \ -e 's,[@]VERSION[@],$(VERSION),g' kimchid: kimchid.in Makefile $(do_substitution) < $(srcdir)/kimchid.in > kimchid chmod +x kimchid kimchi.conf: kimchi.conf.in Makefile $(do_substitution) < kimchi.conf.in > kimchi.conf # Generate unique Diffie-Hellman group with 2048-bit all-local: dhparams.pem dhparams.pem: openssl dhparam -out dhparams.pem 2048 CLEANFILES = $(bin_SCRIPTS) $(BUILT_SOURCES) dhparams.pem kimchi-1.5.0/src/distros.d/000077500000000000000000000000001254252253000154615ustar00rootroot00000000000000kimchi-1.5.0/src/distros.d/Makefile.am000066400000000000000000000015141254252253000175160ustar00rootroot00000000000000# # Kimchi # # Copyright IBM Corp, 2013 # # 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 distrosdir = $(sysconfdir)/kimchi/distros.d dist_distros_DATA = *.json kimchi-1.5.0/src/distros.d/debian.json000066400000000000000000000003631254252253000176000ustar00rootroot00000000000000[ { "name": "debian-Wheezy", "os_distro": "debian", "os_arch": "x86_64", "os_version": "7.7.0", "path": "http://caesar.acc.umu.se/debian-cd/7.7.0/amd64/iso-cd/debian-7.7.0-amd64-netinst.iso" } ] kimchi-1.5.0/src/distros.d/fedora.json000066400000000000000000000017551254252253000176240ustar00rootroot00000000000000[ { "name": "Fedora 20", "os_distro": "fedora", "os_arch": "x86_64", "os_version": "20", "path": "http://fedora.mirrors.tds.net/pub/fedora/releases/20/Live/x86_64/Fedora-Live-Desktop-x86_64-20-1.iso" }, { "name": "Fedora 18 (PPC64)", "os_distro": "fedora", "os_arch": "ppc64", "os_version": "18", "path": "http://mirrors.kernel.org/fedora-secondary/releases/18/Fedora/ppc64/iso/Fedora-18-ppc64-DVD.iso" }, { "name": "Fedora 19 (PPC64)", "os_distro": "fedora", "os_arch": "ppc64", "os_version": "19", "path": "http://mirrors.kernel.org/fedora-secondary/releases/19/Fedora/ppc64/iso/Fedora-19-ppc64-DVD.iso" }, { "name": "Fedora 20 (PPC64)", "os_distro": "fedora", "os_arch": "ppc64", "os_version": "20", "path": "http://mirrors.kernel.org/fedora-secondary/releases/20/Fedora/ppc64/iso/Fedora-20-ppc64-DVD.iso" } ] kimchi-1.5.0/src/distros.d/gentoo.json000066400000000000000000000004101254252253000176420ustar00rootroot00000000000000[ { "name": "gentoo-20141204", "os_distro": "gentoo", "os_arch": "x86_64", "os_version": "20141204", "path": "http://distfiles.gentoo.org/releases/amd64/autobuilds/current-iso/install-amd64-minimal-20141204.iso" } ] kimchi-1.5.0/src/distros.d/opensuse.json000066400000000000000000000013531254252253000202170ustar00rootroot00000000000000[ { "name": "opensuse-12.3", "os_distro": "opensuse", "os_arch": "x86_64", "os_version": "12.3", "path": "http://suse.mirrors.tds.net/pub/opensuse/distribution/12.3/iso/openSUSE-12.3-DVD-x86_64.iso" }, { "name": "opensuse-13.1", "os_distro": "opensuse", "os_arch": "x86_64", "os_version": "13.1", "path": "http://suse.mirrors.tds.net/pub/opensuse/distribution/13.1/iso/openSUSE-13.1-DVD-x86_64.iso" }, { "name": "opensuse-13.2", "os_distro": "opensuse", "os_arch": "x86_64", "os_version": "13.2", "path": "http://suse.mirrors.tds.net/pub/opensuse/distribution/13.2/iso/openSUSE-13.2-DVD-x86_64.iso" } ] kimchi-1.5.0/src/distros.d/ubuntu.json000066400000000000000000000023211254252253000176740ustar00rootroot00000000000000[ { "name": "Ubuntu 13.04 (Raring Ringtail)", "os_distro": "ubuntu", "os_arch": "x86_64", "os_version": "13.04", "path": "http://ubuntu-releases.cs.umn.edu/13.04/ubuntu-13.04-desktop-amd64.iso" }, { "name": "Ubuntu 13.10 (Saucy Salamander)", "os_distro": "ubuntu", "os_arch": "x86_64", "os_version": "13.10", "path": "http://ubuntu-releases.cs.umn.edu/13.10/ubuntu-13.10-desktop-amd64.iso" }, { "name": "Ubuntu Server 14.04 LE (Trusty Tahr)", "os_distro": "ubuntu", "os_arch": "ppc64", "os_version": "14.04", "path": "http://cdimages.ubuntu.com/releases/14.04/release/ubuntu-14.04-server-ppc64el.iso" }, { "name": "Ubuntu Server 14.04 LE (Trusty Tahr)", "os_distro": "ubuntu", "os_arch": "x86_64", "os_version": "14.04", "path": "http://releases.ubuntu.com/14.04/ubuntu-14.04-desktop-amd64.iso" }, { "name": "Ubuntu Server 14.10 (Utopic Unicorn)", "os_distro": "ubuntu", "os_arch": "x86_64", "os_version": "14.10", "path": "http://releases.ubuntu.com/14.10/ubuntu-14.10-desktop-amd64.iso" } ] kimchi-1.5.0/src/firewalld.xml000066400000000000000000000006341254252253000162460ustar00rootroot00000000000000 kimchid Kimchid is a daemon service for kimchi which is a HTML5 based management tool for KVM. It is designed to make it as easy as possible to get started with KVM and create your first guest. kimchi-1.5.0/src/kimchi.conf.in000066400000000000000000000031561254252253000162750ustar00rootroot00000000000000# # Configuration file for Kimchi Web Server # [server] # Hostname or IP address to listen on #host = 0.0.0.0 # Port to listen on #port = 8000 # If present, start an SSL-enabled server on the given port #ssl_port = 8001 # Cherrypy server port #cherrypy_port = 8010 # The full path to an SSL Certificate in PEM format. If left unspecified, # Kimchi will generate a self-signed certificate automatically. #ssl_cert = # The corresponding private key in PEM format for the SSL Certificate supplied # above. If left blank, Kimchi will generate a self-signed certificate. #ssl_key = # Running environment of the server #environment = production # Federation feature: register Kimchi server on openSLP and discover peers # in the same network. Check README-federation for more details. #federation = off # Max request body size in KB, default value is 4GB #max_body_size = 4 * 1024 * 1024 # Automatically create ISO pool on server start up #create_iso_pool = true [logging] # Log directory #log_dir = @localstatedir@/log/kimchi # Logging level: debug, info, warning, error or critical #log_level = debug [display] # Port for websocket proxy to listen on #display_proxy_port = 64667 [authentication] # Authentication method, available option: pam, ldap. # method = pam # If specified method to ldap, following fields need to be specified. # ldap server domain name used to authenticate. # ldap_server = "localhost" # Search tree base in ldap # ldap_search_base = "ou=People, dc=kimchi, dc=org" # User id filter # ldap_search_filter = "uid=%(username)s" # User IDs regarded as kimchi admin # ldap_admin_id = "foo@foo.com, bar@bar.com" kimchi-1.5.0/src/kimchi/000077500000000000000000000000001254252253000150145ustar00rootroot00000000000000kimchi-1.5.0/src/kimchi/API.json000066400000000000000000001016201254252253000163200ustar00rootroot00000000000000{ "$schema": "http://json-schema.org/draft-03/schema#", "title": "Kimchi API", "description": "Json schema for Kimchi API", "type": "object", "kimchitype": { "graphics": { "description": "Configure graphics parameters for the new VM", "type": "object", "properties": { "type": { "enum": ["spice", "vnc"], "error": "KCHVM0014E" }, "listen": { "error": "KCHVM0015E", "type": [ { "type": "string", "format": "ip-address" }, { "type": "string", "format": "ipv6" } ] } } }, "cpu_info": { "description": "Configure CPU specifics for a VM.", "type": "object", "properties": { "topology": { "description": "Configure the guest CPU topology.", "type": "object", "properties": { "sockets": { "type": "integer", "required": true, "minimum": 1, "error": "KCHTMPL0026E" }, "cores": { "type": "integer", "required": true, "minimum": 1, "error": "KCHTMPL0026E" }, "threads": { "type": "integer", "required": true, "minimum": 1, "error": "KCHTMPL0026E" } } } } } }, "properties": { "debugreports_create": { "type": "object", "error": "KCHDR0006E", "properties": { "name": { "description": "The name for the debug report file.", "type": "string", "pattern": "^[_A-Za-z0-9-]*$", "error": "KCHDR0007E" } } }, "debugreport_update": { "type": "object", "properties": { "name": { "description": "New name of debug report", "type": "string", "pattern": "^[_A-Za-z0-9-]*$", "error": "KCHDR0007E" } }, "additionalProperties": false }, "storagepools_create": { "type": "object", "error": "KCHPOOL0026E", "properties": { "name": { "description": "The name of the Storage Pool", "type": "string", "minLength": 1, "pattern": "^[^/]*$", "required": true, "error": "KCHPOOL0016E" }, "type": { "description": "The type of the defined Storage Pool", "type": "string", "pattern": "^dir|netfs|logical|kimchi-iso|iscsi|scsi$", "required": true, "error": "KCHPOOL0017E" }, "path": { "description": "The path of the defined Storage Pool", "type": "string", "error": "KCHPOOL0018E" }, "source": { "description": "Dictionary containing source information of the pool", "type": "object", "properties": { "host": { "description": "IP or hostname of server for a pool backed from a remote host", "type": "string", "error": "KCHPOOL0019E" }, "path": { "description": "Export path on NFS server for NFS pool", "type": "string", "error": "KCHPOOL0018E" }, "devices": { "description": "Array of devices to be used in the Storage Pool", "type": "array", "minItems": 1, "uniqueItems": true, "error": "KCHPOOL0021E", "items": { "description": "Full path of the block device node", "type": "string", "error": "KCHPOOL0020E" } }, "target": { "description": "Target IQN of an iSCSI pool", "type": "string", "error": "KCHPOOL0022E" }, "port": { "description": "Listening port of a remote storage server", "type": "integer", "minimum": 1, "maximum": 65535, "error": "KCHPOOL0023E" }, "adapter_name": { "description": "SCSI host name", "type": "string", "error": "KCHPOOL0030E" }, "auth": { "description": "Storage back-end authentication information", "type": "object", "properties": { "username": { "description": "Login username of the iSCSI target", "type": "string", "error": "KCHPOOL0024E" }, "password": { "description": "Login password of the iSCSI target", "type": "string", "error": "KCHPOOL0025E" } } } } } } }, "storagepool_update": { "type": "object", "properties": { "autostart": { "description": "Set autostart value of the pool", "type": "boolean" }, "disks": { "description": "List of disks/partitions to be added", "type": "array", "items": { "type": "string" }, "minItems": 1, "uniqueItems": true } }, "additionalProperties": false }, "storagevolumes_create": { "type": "object", "properties": { "name": { "description": "The name of the Storage Volume", "type": "string", "minLength": 1, "error": "KCHVOL0013E" }, "capacity": { "description": "The total size (MiB) of the storage volume", "type": "number", "minimum": 1, "error": "KCHVOL0020E" }, "upload": { "description": "When the storage volume will be uploaded", "type": "boolean", "error": "KCHVOL0025E" }, "allocation": { "description": "The size(MiB) of allocation when create the storage volume", "type": "number", "minimum": 1, "error": "KCHVOL0014E" }, "format": { "description": "The format of the volume", "type": "string", "pattern": "^(|bochs|cloop|cow|dmg|qcow|qcow2|qed|raw|vmdk|vpc)$", "error": "KCHVOL0015E" }, "url": { "description": "The remote URL of the storage volume", "type": "string", "pattern": "^(http|ftp)[s]?://", "error": "KCHVOL0021E" } } }, "storagevolume_update": { "type": "object", "properties": { "chunk": { "description": "Upload storage volume chunk", "error": "KCHVOL0024E", "required": true }, "chunk_size": { "description": "Chunk size of uploaded storage volume", "type": "string", "error": "KCHVOL0024E", "required": true } }, "additionalProperties": false }, "vms_create": { "type": "object", "error": "KCHVM0016E", "properties": { "name": { "description": "The name of the new VM", "type": "string", "pattern": "^[^/]*$", "error": "KCHVM0011E" }, "template": { "description": "The URI of a template to use when building a VM", "type": "string", "pattern": "^/templates/(.*?)/?$", "required": true, "error": "KCHVM0012E" }, "storagepool": { "description": "Assign a specefic Storage Pool to the new VM", "type": "string", "pattern": "^/storagepools/[^/]+/?$", "error": "KCHVM0013E" }, "graphics": { "$ref": "#/kimchitype/graphics" } } }, "vm_update": { "type": "object", "properties": { "name": { "description": "New name of VM", "type": "string", "pattern": "^[^/]*$", "minLength": 1, "error": "KCHVM0011E" }, "users": { "description": "Array of users who have permission to the VM", "type": "array", "uniqueItems": true, "error": "KCHVM0023E", "items": { "description": "User name", "type": "string", "error": "KCHVM0024E" } }, "groups": { "description": "Array of groups who have permission to the VM", "type": "array", "uniqueItems": true, "error": "KCHVM0025E", "items": { "description": "Group name", "type": "string", "error": "KCHVM0026E" } }, "graphics": { "description": "Graphics information from guest", "type": "object", "properties": { "passwd": { "description": "New graphics password.", "type": "string", "error": "KCHVM0031E" }, "passwdValidTo": { "description": "Life time for the graphics password.", "type": "number", "error": "KCHVM0032E" } } }, "cpus": { "description": "The new number of virtual CPUs for the VM", "type": "integer", "minimum": 1, "error": "KCHTMPL0012E" }, "memory": { "description": "The new amount (MB) of memory for the VM", "type": "integer", "minimum": 512, "error": "KCHTMPL0013E" } }, "additionalProperties": false }, "networks_create": { "type": "object", "error": "KCHNET0016E", "properties": { "name": { "description": "The name of the new network", "type": "string", "minLength": 1, "pattern": "^[^/\"]*$", "required": true, "error": "KCHNET0011E" }, "connection": { "description": "Specifies how this network should be connected to the other networks", "type": "string", "pattern": "^isolated|nat|bridge$", "required": true, "error": "KCHNET0012E" }, "subnet": { "description": "Network segment in slash-separated format with ip address and prefix or netmask", "type": "string", "error": "KCHNET0013E" }, "interface": { "description": "The name of a network interface on the host", "type": "string", "error": "KCHNET0014E" }, "vlan_id": { "description": "Network's VLAN ID", "type": "integer", "maximum": 4094, "minimum": 1, "error": "KCHNET0015E" } } }, "vmifaces_create": { "type": "object", "error": "KCHVMIF0007E", "properties": { "type": { "description": "The type of VM network interface that libvirt supports", "type": "string", "pattern": "^network$", "required": true, "error": "KCHVMIF0004E" }, "network": { "description": "the name of one available network", "minLength": 1, "type": "string", "error": "KCHVMIF0005E" }, "model": { "description": "model of emulated network interface card", "type": "string", "pattern": "^ne2k_pci|i82551|i82557b|i82559er|rtl8139|e1000|pcnet|virtio$", "error": "KCHVMIF0006E" }, "mac": { "description": "Network Interface Card MAC address", "type": "string", "pattern": "(^$)|^(([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$)", "error": "KCHVMIF0010E" } } }, "vmiface_update": { "type": "object", "error": "KCHVMIF0008E", "properties": { "mac": { "description": "Network Interface Card MAC address", "type": "string", "pattern": "^([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$", "error": "KCHVMIF0010E" } } }, "templates_create": { "type": "object", "error": "KCHTMPL0016E", "properties": { "name": { "description": "The name of the template", "type": "string", "pattern": "^[^ ]+( +[^ ]+)*$", "minLength": 1, "error": "KCHTMPL0008E" }, "icon": { "description": "The template icon path", "type": "string", "pattern": "^images/", "error": "KCHTMPL0009E" }, "os_distro": { "description": "Distribution name of the Operating System", "type": "string", "minLength": 1, "error": "KCHTMPL0010E" }, "os_version": { "description": "Version of the Operating System", "type": "string", "minLength": 1, "error": "KCHTMPL0011E" }, "cpus": { "description": "Number of CPUs for the template", "type": "integer", "minimum": 1, "error": "KCHTMPL0012E" }, "memory": { "description": "Memory (MB) for the template", "type": "integer", "minimum": 512, "error": "KCHTMPL0013E" }, "cdrom": { "description": "Path for cdrom", "type": "string", "pattern": "^((/)|(http)[s]?:|[t]?(ftp)[s]?:)+.*$", "error": "KCHTMPL0014E" }, "disks": { "description": "List of disks", "type": "array", "items": { "type": "object", "properties": { "index": { "description": "Index of the disk", "type": "integer", "minimum": 0 }, "size": { "description": "Size (GB) of the disk", "type": "number", "minimum": 1, "error": "KCHTMPL0022E" }, "base": { "description": "Base image of the disk", "type": "string", "pattern": "^/.+$", "error": "KCHTMPL0023E" } } }, "minItems": 1, "uniqueItems": true }, "storagepool": { "description": "Location of the storage pool", "type": "string", "pattern": "^/storagepools/[^/]+/?$", "error": "KCHTMPL0015E" }, "networks": { "description": "list of which networks will be assigned to the new VM.", "type": "array", "items": { "type": "string" }, "error": "KCHTMPL0017E" }, "folder": { "description": "Folder", "type": "array", "items": { "type": "string" } }, "graphics": { "$ref": "#/kimchitype/graphics" }, "cpu_info": { "$ref": "#/kimchitype/cpu_info" } }, "additionalProperties": false, "error": "KCHAPI0001E" }, "storageservers_get_list": { "type": "object", "properties": { "_target_type": { "description": "List storage servers of given type", "type": "string", "pattern": "^netfs|iscsi$" } }, "additionalProperties": false, "error": "KCHAPI0001E" }, "storagetargets_get_list": { "type": "object", "properties": { "_target_type": { "description": "List storage servers of given type", "type": "string", "pattern": "^netfs|iscsi$" }, "_server_port": { "description": "the port of iscsi storage servers", "type": "string", "pattern": "^[0-9]{1,5}$" } }, "additionalProperties": false, "error": "KCHAPI0001E" }, "vmstorages_create": { "type": "object", "error": "KCHVMSTOR0012E", "properties": { "type": { "description": "The storage type", "type": "string", "pattern": "^cdrom|disk$", "required": true, "error": "KCHVMSTOR0002E" }, "pool": { "description": "Storage pool name disk image locate in", "type": "string", "minLength": 1, "error": "KCHVMSTOR0012E" }, "vol": { "description": "Storage volume name of disk image", "type": "string", "minLength": 1, "error": "KCHVMSTOR0012E" }, "path": { "description": "Path of iso image file or disk mount point", "type": "string", "pattern": "^((/)|(http)[s]?:|[t]?(ftp)[s]?:)+.*$", "error": "KCHVMSTOR0003E" } } }, "vmstorage_update": { "type": "object", "error": "KCHVMSTOR0013E", "properties": { "path": { "description": "Path of iso image file or disk mount point", "type": "string", "pattern": "^(|(/)|(http)[s]?:|[t]?(ftp)[s]?:)+.*$", "required": true, "error": "KCHVMSTOR0003E" } }, "additionalProperties": false }, "template_update": { "type": "object", "properties": { "name": { "description": "The name of the template", "type": "string", "pattern": "^[^ ]+( +[^ ]+)*$", "minLength": 1, "error": "KCHTMPL0008E" }, "icon": { "description": "The template icon path", "type": "string", "pattern": "^images/", "error": "KCHTMPL0009E" }, "os_distro": { "description": "Distribution name of the Operating System", "type": "string", "minLength": 1, "error": "KCHTMPL0010E" }, "os_version": { "description": "Version of the Operating System", "type": "string", "minLength": 1, "error": "KCHTMPL0011E" }, "cpus": { "description": "Number of CPUs for the template", "type": "integer", "minimum": 1, "error": "KCHTMPL0012E" }, "memory": { "description": "Memory (MB) for the template", "type": "integer", "minimum": 512, "error": "KCHTMPL0013E" }, "cdrom": { "description": "Path for cdrom", "type": "string", "pattern": "^((/)|(http)[s]?:|[t]?(ftp)[s]?:)+.*$", "error": "KCHTMPL0014E" }, "disks": { "description": "List of disks", "type": "array", "items": { "type": "object", "properties": { "index": { "description": "Index of the disk", "type": "integer", "minimum": 0 }, "size": { "description": "Size (GB) of the disk", "type": "integer", "minimum": 1, "error": "KCHTMPL0022E" }, "format": { "description": "Type of the image of the disk", "type": "string", "pattern": "^(bochs|cloop|cow|dmg|qcow|qcow2|qed|raw|vmdk|vpc)$", "error": "KCHTMPL0027E" } } }, "minItems": 1, "uniqueItems": true }, "storagepool": { "description": "Location of the storage pool", "type": "string", "pattern": "^/storagepools/[^/]+/?$", "error": "KCHTMPL0015E" }, "networks": { "description": "list of which networks will be assigned to the new VM.", "type": "array", "items": { "type": "string" }, "error": "KCHTMPL0017E" }, "folder": { "description": "Folder", "type": "array", "items": { "type": "string" } }, "graphics": { "$ref": "#/kimchitype/graphics" }, "cpu_info": { "$ref": "#/kimchitype/cpu_info" } }, "additionalProperties": false, "error": "KCHAPI0001E" }, "repositories_create": { "type": "object", "properties": { "repo_id": { "description": "Repository ID used for YUM repository.", "type": "string", "error": "KCHREPOS0001E" }, "baseurl": { "description": "URL to the directory where the repodata directory of a repository is located. Can be an http://, ftp:// or file:// URL.", "type": "string", "error": "KCHREPOS0002E" }, "config": { "description": "Dictionary containing repository configuration", "type": "object", "error": "KCHREPOS0003E", "properties": { "dist": { "description": "Distribution to DEB repository", "type": "string", "error": "KCHREPOS0004E" }, "comps": { "description": "List of components to DEB repository", "type": "array", "error": "KCHREPOS0005E", "uniqueItems": true, "items": { "description": "Component name", "type": "string", "error": "KCHREPOS0006E" } }, "repo_name": { "description": "YUM repository name", "type": "string", "error": "KCHREPOS0023E" }, "mirrorlist": { "description": "URL to a file containing a list of baseurls", "type": "string", "error": "KCHREPOS0007E" }, "metalink": { "description": "URL to a metalink file for the repomd.xml", "type": "string", "error": "KCHREPOS0029E" } } } }, "additionalProperties": false, "error": "KCHAPI0001E" }, "repository_update": { "type": "object", "properties": { "baseurl": { "description": "URL to the directory where the repodata directory of a repository is located. Can be an http://, ftp:// or file:// URL.", "type": "string", "error": "KCHREPOS0002E" }, "config": { "description": "Dictionary containing repository configuration", "type": "object", "error": "KCHREPOS0003E", "properties": { "dist": { "description": "Distribution to DEB repository", "type": "string", "error": "KCHREPOS0004E" }, "comps": { "description": "List of components to DEB repository", "type": "array", "error": "KCHREPOS0005E", "uniqueItems": true, "items": { "description": "Component name", "type": "string", "error": "KCHREPOS0006E" } }, "repo_name": { "description": "Human-readable string describing the YUM repository.", "type": "string", "error": "KCHREPOS0008E" }, "mirrorlist": { "description": "URL to a file containing a list of baseurls for YUM repository", "type": "string", "error": "KCHREPOS0007E" }, "gpgcheck": { "description": "Indicates if a GPG signature check on the packages gotten from repository should be performed.", "type": "boolean", "error": "KCHREPOS0009E" }, "gpgkey": { "description": "URL pointing to the ASCII-armored GPG key file for the repository.", "type": "string", "error": "KCHREPOS0010E" } } } }, "additionalProperties": false, "error": "KCHAPI0001E" }, "devices_get_list": { "type": "object", "properties": { "_cap": { "description": "List specific type of device", "type": "string", "pattern": "^fc_host|net|pci|scsi|scsi_host|storage|system|usb|usb_device$", "error": "KCHDEVS0001E" }, "_passthrough": { "description": "List only devices eligible to be assigned to guest", "type": "string", "pattern": "^true|false$", "error": "KCHDEVS0002E" }, "_passthrough_affected_by": { "description": "List the affected devices in the same group of a certain device to be assigned to guest", "type": "string", "pattern": "^[_A-Za-z0-9-]+$", "error": "KCHDEVS0003E" } }, "additionalProperties": false, "error": "KCHAPI0001E" }, "vmhostdevs_create": { "type": "object", "properties": { "name": { "description": "Then name of the device to assign to VM", "type": "string", "pattern": "^[_A-Za-z0-9-]+$", "required": true, "error": "KCHVMHDEV0004E" } }, "error": "KCHAPI0001E" } } } kimchi-1.5.0/src/kimchi/Makefile.am000066400000000000000000000034211254252253000170500ustar00rootroot00000000000000# # Kimchi # # Copyright IBM Corp, 2013 # # 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 SUBDIRS = control model xmlutils kimchi_PYTHON = $(filter-out config.py, $(wildcard *.py)) nodist_kimchi_PYTHON = config.py EXTRA_DIST = \ API.json \ config.py.in if WITH_SPICE WITH_SPICE=yes else WITH_SPICE=no endif kimchidir = $(pythondir)/kimchi install-data-local: $(MKDIR_P) $(DESTDIR)$(kimchidir) $(INSTALL_DATA) API.json $(DESTDIR)$(kimchidir)/API.json uninstall-local: $(RM) $(DESTDIR)$(kimchidir)/API.json do_substitution = \ sed -e 's,[@]prefix[@],$(prefix),g' \ -e 's,[@]datadir[@],$(datadir),g' \ -e 's,[@]sysconfdir[@],$(sysconfdir),g' \ -e 's,[@]localstatedir[@],$(localstatedir),g' \ -e 's,[@]pkgdatadir[@],$(pkgdatadir),g' \ -e 's,[@]kimchidir[@],$(kimchidir),g' \ -e 's,[@]kimchiversion[@],$(PACKAGE_VERSION),g' \ -e 's,[@]kimchirelease[@],$(PACKAGE_RELEASE),g' \ -e 's,[@]withspice[@],$(WITH_SPICE),g' config.py: config.py.in Makefile $(do_substitution) < $(srcdir)/config.py.in > config.py BUILT_SOURCES = config.py CLEANFILES = config.py kimchi-1.5.0/src/kimchi/__init__.py000066400000000000000000000014171254252253000171300ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-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 kimchi-1.5.0/src/kimchi/asynctask.py000066400000000000000000000050041254252253000173650ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-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 import cherrypy import threading import traceback from kimchi.exception import OperationFailed class AsyncTask(object): def __init__(self, id, target_uri, fn, objstore, opaque=None): if objstore is None: raise OperationFailed("KCHASYNC0001E") self.id = str(id) self.target_uri = target_uri self.fn = fn self.objstore = objstore self.status = 'running' self.message = 'OK' self._save_helper() self._cp_request = cherrypy.serving.request self.thread = threading.Thread(target=self._run_helper, args=(opaque, self._status_cb)) self.thread.setDaemon(True) self.thread.start() def _status_cb(self, message, success=None): if success is None: self.message = message self._save_helper() return if success is not None: self.status = 'finished' if success else 'failed' self.message = message self._save_helper() def _save_helper(self): obj = {} for attr in ('id', 'target_uri', 'message', 'status'): obj[attr] = getattr(self, attr) try: with self.objstore as session: session.store('task', self.id, obj) except Exception as e: raise OperationFailed('KCHASYNC0002E', {'err': e.message}) def _run_helper(self, opaque, cb): cherrypy.serving.request = self._cp_request try: self.fn(cb, opaque) except Exception, e: cherrypy.log.error_log.error("Error in async_task %s " % self.id) cherrypy.log.error_log.error(traceback.format_exc()) cb("Unexpected exception: %s" % e.message, False) kimchi-1.5.0/src/kimchi/auth.py000066400000000000000000000277431254252253000163440ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-2015 # # 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 import base64 import cherrypy import fcntl import ldap import multiprocessing import os import PAM import pty import re import termios import time import urllib2 from kimchi import template from kimchi.config import config from kimchi.exception import InvalidOperation, OperationFailed from kimchi.utils import get_all_tabs, run_command USER_NAME = 'username' USER_GROUPS = 'groups' USER_ROLES = 'roles' REFRESH = 'robot-refresh' tabs = get_all_tabs() def redirect_login(): url = "/login.html" if cherrypy.request.path_info.endswith(".html"): next_url = cherrypy.serving.request.request_line.split()[1] next_url = urllib2.quote(next_url.encode('utf-8'), safe="") url = "/login.html?next=%s" % next_url raise cherrypy.HTTPRedirect(url, 303) def debug(msg): pass # cherrypy.log.error(msg) class User(object): @classmethod def get(cls, auth_args): auth_type = auth_args.pop('auth_type') for klass in cls.__subclasses__(): if auth_type == klass.auth_type: try: if not klass.authenticate(**auth_args): debug("cannot verify user with the given password") return None except OperationFailed: raise return klass(auth_args['username']) class PAMUser(User): auth_type = "pam" def __init__(self, username): self.user = {} self.user[USER_NAME] = username self.user[USER_GROUPS] = None # after adding support to change user roles that info should be read # from a specific objstore and fallback to default only if any entry is # found self.user[USER_ROLES] = dict.fromkeys(tabs, 'user') def get_groups(self): out, err, rc = run_command(['id', '-Gn', self.user[USER_NAME]]) if rc == 0: self.user[USER_GROUPS] = out.rstrip().split(" ") return self.user[USER_GROUPS] def get_roles(self): if self.has_sudo(): # after adding support to change user roles that info should be # read from a specific objstore and fallback to default only if # any entry is found self.user[USER_ROLES] = dict.fromkeys(tabs, 'admin') return self.user[USER_ROLES] def has_sudo(self): result = multiprocessing.Value('i', 0, lock=False) p = multiprocessing.Process(target=self._has_sudo, args=(result,)) p.start() p.join() return result.value def _has_sudo(self, result): result.value = False _master, slave = pty.openpty() os.setsid() fcntl.ioctl(slave, termios.TIOCSCTTY, 0) out, err, exit = run_command(['sudo', '-l', '-U', self.user[USER_NAME], 'sudo']) if exit == 0: debug("User %s is allowed to run sudo" % self.user[USER_NAME]) # sudo allows a wide range of configurations, such as controlling # which binaries the user can execute with sudo. # For now, we will just check whether the user is allowed to run # any command with sudo. out, err, exit = run_command(['sudo', '-l', '-U', self.user[USER_NAME]]) for line in out.split('\n'): if line and re.search("(ALL)", line): result.value = True debug("User %s can run any command with sudo" % result.value) return debug("User %s can only run some commands with sudo" % self.user[USER_NAME]) else: debug("User %s is not allowed to run sudo" % self.user[USER_NAME]) def get_user(self): return self.user @staticmethod def authenticate(username, password, service="passwd"): '''Returns True if authenticate is OK via PAM.''' def _auth(result): def _pam_conv(auth, query_list, userData=None): resp = [] for i in range(len(query_list)): query, qtype = query_list[i] if qtype == PAM.PAM_PROMPT_ECHO_ON: resp.append((username, 0)) elif qtype == PAM.PAM_PROMPT_ECHO_OFF: resp.append((password, 0)) elif qtype == PAM.PAM_PROMPT_ERROR_MSG: cherrypy.log.error_log.error( "PAM authenticate prompt error: %s" % query) resp.append(('', 0)) elif qtype == PAM.PAM_PROMPT_TEXT_INFO: resp.append(('', 0)) else: return None return resp auth = PAM.pam() auth.start(service) auth.set_item(PAM.PAM_USER, username) auth.set_item(PAM.PAM_CONV, _pam_conv) try: auth.authenticate() result.value = 0 except PAM.error, (resp, code): result.value = code result = multiprocessing.Value('i', 0, lock=False) p = multiprocessing.Process(target=_auth, args=(result, )) p.start() p.join() if result.value != 0: msg_args = {'username': username, 'code': result.value} raise OperationFailed("KCHAUTH0001E", msg_args) return True class LDAPUser(User): auth_type = "ldap" def __init__(self, username): self.user = {} self.user[USER_NAME] = username self.user[USER_GROUPS] = list() # FIXME: user roles will be changed according roles assignment after # objstore is integrated self.user[USER_ROLES] = dict.fromkeys(tabs, 'user') @staticmethod def authenticate(username, password): ldap_server = config.get("authentication", "ldap_server").strip('"') ldap_search_base = config.get( "authentication", "ldap_search_base").strip('"') ldap_search_filter = config.get( "authentication", "ldap_search_filter", vars={"username": username.encode("utf-8")}).strip('"') connect = ldap.open(ldap_server) try: result = connect.search_s( ldap_search_base, ldap.SCOPE_SUBTREE, ldap_search_filter) if len(result) == 0: entity = ldap_search_filter % {'username': username} raise ldap.LDAPError("Invalid ldap entity:%s" % entity) connect.bind_s(result[0][0], password) connect.unbind_s() return True except ldap.INVALID_CREDENTIALS: # invalid user password raise OperationFailed("KCHAUTH0002E") except ldap.NO_SUCH_OBJECT: # ldap search base specified wrongly. raise OperationFailed("KCHAUTH0005E", {"item": 'ldap_search_base', "value": ldap_search_base}) except ldap.LDAPError, e: arg = {"username": username, "code": e.message} raise OperationFailed("KCHAUTH0001E", arg) def get_groups(self): return self.user[USER_GROUPS] def get_roles(self): admin_ids = config.get( "authentication", "ldap_admin_id").strip('"').split(',') for admin_id in admin_ids: if self.user[USER_NAME] == admin_id.strip(): self.user[USER_ROLES] = dict.fromkeys(tabs, 'admin') return self.user[USER_ROLES] def get_user(self): return self.user def from_browser(): # Enable Basic Authentication for REST tools. # Ajax request sent from jQuery in browser will have "X-Requested-With" # header. We will check it to determine whether enable BA. requestHeader = cherrypy.request.headers.get("X-Requested-With", None) return (requestHeader == "XMLHttpRequest") def check_auth_session(): """ A user is considered authenticated if we have an established session open for the user. """ cherrypy.session.acquire_lock() session = cherrypy.session.get(USER_NAME, None) cherrypy.session.release_lock() if session is not None: debug("Session authenticated for user %s" % session) kimchiRobot = cherrypy.request.headers.get('Kimchi-Robot') if kimchiRobot == "kimchi-robot": if (time.time() - cherrypy.session[REFRESH] > cherrypy.session.timeout * 60): cherrypy.session[USER_NAME] = None cherrypy.lib.sessions.expire() raise cherrypy.HTTPError(401, "sessionTimeout") else: cherrypy.session[REFRESH] = time.time() return True debug("Session not found") return False def check_auth_httpba(): """ REST API users may authenticate with HTTP Basic Auth. This is not allowed for the UI because web browsers would cache the credentials and make it impossible for the user to log out without closing their browser completely """ if from_browser() or not template.can_accept('application/json'): return False authheader = cherrypy.request.headers.get('AUTHORIZATION') if not authheader: debug("No authentication headers found") return False debug("Authheader: %s" % authheader) # TODO: what happens if you get an auth header that doesn't use basic auth? b64data = re.sub("Basic ", "", authheader) decodeddata = base64.b64decode(b64data.encode("ASCII")) # TODO: test how this handles ':' characters in username/passphrase. username, password = decodeddata.decode().split(":", 1) return login(username, password) def login(username, password, **kwargs): auth_args = {'auth_type': config.get("authentication", "method"), 'username': username, 'password': password} user = User.get(auth_args) if not user: debug("User cannot be verified with the supplied password") return None debug("User verified, establishing session") cherrypy.session.acquire_lock() cherrypy.session.regenerate() cherrypy.session[USER_NAME] = username cherrypy.session[USER_GROUPS] = user.get_groups() cherrypy.session[USER_ROLES] = user.get_roles() cherrypy.session[REFRESH] = time.time() cherrypy.session.release_lock() return user.get_user() def logout(): cherrypy.session.acquire_lock() cherrypy.session[USER_NAME] = None cherrypy.session[REFRESH] = 0 cherrypy.session.release_lock() cherrypy.lib.sessions.close() def kimchiauth(): debug("Entering kimchiauth...") session_missing = cherrypy.session.missing if check_auth_session(): return if check_auth_httpba(): return # not a REST full request, redirect login page directly if ("Accept" in cherrypy.request.headers and not template.can_accept('application/json')): redirect_login() # from browser, and it stays on one page. if session_missing and cherrypy.request.cookie.get("lastPage") is not None: raise cherrypy.HTTPError(401, "sessionTimeout") if not from_browser(): cherrypy.response.headers['WWW-Authenticate'] = 'Basic realm=kimchi' e = InvalidOperation('KCHAUTH0002E') raise cherrypy.HTTPError(401, e.message.encode('utf-8')) kimchi-1.5.0/src/kimchi/basemodel.py000066400000000000000000000040761254252253000173300ustar00rootroot00000000000000# # 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 class BaseModel(object): ''' This model squashes all sub-model's public callable methods to itself. Model methods are not limited to get_list, create, lookup, update, delete. Controller can call generate_action_handler to generate new actions, which call the related model methods. So all public callable methods of a sub-model should be mapped to this model. ''' def __init__(self, model_instances): for model_instance in model_instances: cls_name = model_instance.__class__.__name__ if cls_name.endswith('Model'): method_prefix = cls_name[:-len('Model')].lower() else: method_prefix = cls_name.lower() callables = [m for m in dir(model_instance) if not m.startswith('_') and callable(getattr(model_instance, m))] for member_name in callables: m = getattr(model_instance, member_name, None) setattr(self, '%s_%s' % (method_prefix, member_name), m) class Singleton(type): _instances = {} def __call__(cls, *args, **kwargs): if cls not in cls._instances: inst = super(Singleton, cls).__call__(*args, **kwargs) cls._instances[cls] = inst return cls._instances[cls] kimchi-1.5.0/src/kimchi/cachebust.py000066400000000000000000000017701254252253000173340ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-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 import os from kimchi.config import paths def href(url): # for error.html, url is absolute path f = os.path.join(paths.ui_dir, url.lstrip("/")) mtime = os.path.getmtime(f) return "%s?cacheBust=%s" % (url, mtime) kimchi-1.5.0/src/kimchi/config.py.in000066400000000000000000000251761254252253000172530ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-2015 # # 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 # import libvirt import os import platform import threading from ConfigParser import SafeConfigParser from kimchi.xmlutils.utils import xpath_get_text __version__ = "@kimchiversion@" __release__ = "@kimchirelease@" __with_spice__ = "@withspice@" DEFAULT_LOG_LEVEL = "debug" kimchiLock = threading.Lock() # Storage pool constant for read-only pool types READONLY_POOL_TYPE = ['iscsi', 'scsi', 'mpath'] def get_object_store(): return os.path.join(paths.state_dir, 'objectstore') def get_distros_store(): return os.path.join(paths.conf_dir, 'distros.d') def get_screenshot_path(): return os.path.join(paths.state_dir, 'screenshots') def get_debugreports_path(): return os.path.join(paths.state_dir, 'debugreports') def get_version(): return "-".join([__version__, __release__]) def find_qemu_binary(find_emulator=False): try: connect = libvirt.open(None) except Exception, e: raise Exception("Unable to get qemu binary location: %s" % e) try: xml = connect.getCapabilities() # On Little Endian system, the qemu binary is # qemu-system-ppc64, not qemu-system-ppc64le as expected arch = platform.machine() if arch == "ppc64le": arch = "ppc64" if find_emulator: expr = "/capabilities/guest/arch[@name='%s']\ /emulator" % arch else: expr = "/capabilities/guest/arch[@name='%s']\ /domain[@type='kvm']/emulator" % arch res = xpath_get_text(xml, expr) location = res[0] except Exception, e: raise Exception("Unable to get qemu binary location: %s" % e) finally: connect.close() return location class Paths(object): def __init__(self): self.prefix = self.get_prefix() self.installed = (self.prefix == '@pkgdatadir@') self.ui_dir = self.add_prefix('ui') self.spice_file = os.path.join(self.ui_dir, 'spice-html5/pages/spice_auto.html') if __with_spice__ == 'yes': self.spice_dir = self.add_prefix('ui/spice-html5') elif os.path.exists('@datadir@/spice-html5'): self.spice_dir = '@datadir@/spice-html5' else: self.spice_dir = '/usr/share/spice-html5' if os.path.exists('@datadir@/novnc'): self.novnc_dir = '@datadir@/novnc' else: self.novnc_dir = '/usr/share/novnc' if self.installed: self.nginx_conf_dir = '@sysconfdir@/nginx/conf.d' self.state_dir = '@localstatedir@/lib/kimchi' self.log_dir = '@localstatedir@/log/kimchi' self.conf_dir = '@sysconfdir@/kimchi' self.src_dir = '@kimchidir@' self.plugins_dir = '@kimchidir@/plugins' self.mo_dir = '@prefix@/share/locale' self.spice_css_file = os.path.join(self.spice_dir, 'spice.css') else: self.nginx_conf_dir = self.add_prefix('src/nginx') self.state_dir = self.add_prefix('data') self.log_dir = self.add_prefix('log') self.conf_dir = self.add_prefix('src') self.src_dir = self.add_prefix('src/kimchi') self.plugins_dir = self.add_prefix('plugins') self.mo_dir = self.add_prefix('mo') self.spice_css_file = os.path.join(self.spice_dir, 'css/spice.css') def get_prefix(self): if __file__.startswith("/"): base = os.path.dirname(__file__) else: base = os.path.dirname('./%s' % __file__) if os.access('%s/../../src/kimchi/config.py' % base, os.F_OK): return os.path.abspath('%s/../..' % base) else: return '@pkgdatadir@' def add_prefix(self, subdir): return os.path.join(self.prefix, subdir) def get_template_path(self, resource): return os.path.join(self.ui_dir, 'pages/%s.tmpl' % resource) paths = Paths() class PluginPaths(Paths): def __init__(self, name): super(PluginPaths, self).__init__() self.plugin_dir = os.path.join('plugins', name) if self.installed: self.conf_dir = '@sysconfdir@/kimchi/plugins.d' self.src_dir = os.path.join('@kimchidir@', self.plugin_dir) else: self.conf_dir = self.add_prefix(self.plugin_dir) self.src_dir = self.add_prefix(self.plugin_dir) self.ui_dir = self.add_prefix(os.path.join(self.plugin_dir, 'ui')) self.mo_dir = self.add_prefix(os.path.join(self.plugin_dir, 'mo')) self.conf_file = os.path.join(self.conf_dir, '%s.conf' % name) class UIConfig(dict): # expires is one year. CACHEEXPIRES = 31536000 def __init__(self, paths): ui_configs = {} for sub_dir in ('css', 'js', 'libs', 'images'): ui_configs['/' + sub_dir] = { 'tools.staticdir.on': True, 'tools.staticdir.dir': os.path.join(paths.ui_dir, sub_dir), 'tools.nocache.on': False} if sub_dir != 'images': ui_configs['/' + sub_dir].update({ 'tools.expires.on': True, 'tools.expires.secs': self.CACHEEXPIRES}) self.update(ui_configs) class KimchiConfig(dict): # session time out is 10 minutes SESSIONSTIMEOUT = 10 kimchi_config = { '/': { 'tools.trailing_slash.on': False, 'request.methods_with_bodies': ('POST', 'PUT'), 'tools.nocache.on': True, 'tools.proxy.on': True, 'tools.sessions.on': True, 'tools.sessions.name': 'kimchi', 'tools.sessions.secure': True, 'tools.sessions.httponly': True, 'tools.sessions.locking': 'explicit', 'tools.sessions.storage_type': 'ram', 'tools.sessions.timeout': SESSIONSTIMEOUT, 'tools.kimchiauth.on': False }, '/novnc': { 'tools.staticdir.on': True, 'tools.staticdir.dir': paths.novnc_dir, 'tools.nocache.on': True, 'tools.kimchiauth.on': True }, '/spice_auto.html': { 'tools.staticfile.on': True, 'tools.staticfile.filename': paths.spice_file, 'tools.nocache.on': True, 'tools.kimchiauth.on': True }, '/spice-html5': { 'tools.staticdir.on': True, 'tools.staticdir.dir': paths.spice_dir, 'tools.nocache.on': True }, '/spice-html5/spice.css': { 'tools.staticfile.on': True, 'tools.staticfile.filename': paths.spice_css_file, 'tools.nocache.on': True, }, '/kimchi-ui.html': { 'tools.kimchiauth.on': True }, '/data/screenshots': { 'tools.staticdir.on': True, 'tools.staticdir.dir': get_screenshot_path(), 'tools.nocache.on': False }, '/data/debugreports': { 'tools.staticdir.on': True, 'tools.staticdir.dir': get_debugreports_path(), 'tools.nocache.on': False, 'tools.kimchiauth.on': True, 'tools.staticdir.content_types': {'xz': 'application/x-xz'} }, '/config/ui/tabs.xml': { 'tools.staticfile.on': True, 'tools.staticfile.filename': '%s/config/ui/tabs.xml' % paths.prefix, 'tools.nocache.on': True }, '/favicon.ico': { 'tools.staticfile.on': True, 'tools.staticfile.filename': '%s/images/logo.ico' % paths.ui_dir }, '/robots.txt': { 'tools.staticfile.on': True, 'tools.staticfile.filename': '%s/robots.txt' % paths.ui_dir }, '/help': { 'tools.staticdir.on': True, 'tools.staticdir.dir': '%s/ui/pages/help' % paths.prefix, 'tools.staticdir.index': 'en_US/index.html', 'tools.nocache.on': True } } def __init__(self): super(KimchiConfig, self).__init__(self) self.update(self.kimchi_config) self.update(UIConfig(paths)) class PluginConfig(dict): def __init__(self, plugin_name): super(PluginConfig, self).__init__(self) plugin_config = { '/ui/config/tab-ext.xml': { 'tools.staticfile.on': True, 'tools.staticfile.filename': os.path.join(PluginPaths(plugin_name).ui_dir, 'config/tab-ext.xml'), 'tools.nocache.on': True}} self.update(plugin_config) self.update(UIConfig(PluginPaths(plugin_name))) def _get_config(): config = SafeConfigParser() config.add_section("server") config.set("server", "host", "0.0.0.0") config.set("server", "port", "8000") config.set("server", "ssl_port", "8001") config.set("server", "cherrypy_port", "8010") config.set("server", "ssl_cert", "") config.set("server", "ssl_key", "") config.set("server", "environment", "production") config.set("server", "federation", "off") config.set("server", "create_iso_pool", "true") config.set('server', 'max_body_size', '4*1024*1024') config.add_section("authentication") config.set("authentication", "method", "pam") config.set("authentication", "ldap_server", "") config.set("authentication", "ldap_search_base", "") config.set("authentication", "ldap_search_filter", "") config.set("authentication", "ldap_admin_id", "") config.add_section("logging") config.set("logging", "log_dir", paths.log_dir) config.set("logging", "log_level", DEFAULT_LOG_LEVEL) config.add_section("display") config.set("display", "display_proxy_port", "64667") config_file = os.path.join(paths.conf_dir, 'kimchi.conf') if os.path.exists(config_file): config.read(config_file) return config config = _get_config() if __name__ == '__main__': print paths.prefix kimchi-1.5.0/src/kimchi/control/000077500000000000000000000000001254252253000164745ustar00rootroot00000000000000kimchi-1.5.0/src/kimchi/control/Makefile.am000066400000000000000000000016121254252253000205300ustar00rootroot00000000000000# # Kimchi # # Copyright IBM Corp, 2013 # # 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 SUBDIRS = vm control_PYTHON = *.py controldir = $(pythondir)/kimchi/control install-data-local: $(MKDIR_P) $(DESTDIR)$(controldir) kimchi-1.5.0/src/kimchi/control/__init__.py000066400000000000000000000016241254252253000206100ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-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 import os from kimchi.control.utils import load_url_sub_node sub_nodes = load_url_sub_node(os.path.dirname(__file__), __name__) kimchi-1.5.0/src/kimchi/control/base.py000066400000000000000000000344111254252253000177630ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-2015 # # 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 import cherrypy import re import urllib2 import kimchi.template from kimchi.auth import USER_GROUPS, USER_NAME, USER_ROLES from kimchi.control.utils import get_class_name, internal_redirect, model_fn from kimchi.control.utils import parse_request, validate_method from kimchi.control.utils import validate_params from kimchi.exception import InvalidOperation, InvalidParameter from kimchi.exception import KimchiException, MissingParameter, NotFoundError from kimchi.exception import OperationFailed, UnauthorizedError class Resource(object): """ A Resource represents a single entity in the API (such as a Virtual Machine) To create new Resource types, subclass this and change the following things in the child class: - If the Resource requires more than one identifier set self.model_args as appropriate. This should only be necessary if this Resource is logically nested. For example: A Storage Volume belongs to a Storage Pool so the Storage Volume would set model args to (pool_ident, volume_ident). - Implement the base operations of 'lookup' and 'delete' in the model(s). - Set the 'data' property to a JSON-serializable representation of the Resource. """ def __init__(self, model, ident=None): self.model = model self.ident = ident self.model_args = (ident,) self.role_key = None self.admin_methods = [] def _redirect(self, action_result, code=303): if isinstance(action_result, list): uri_params = [] for arg in action_result: if arg is None: arg = '' uri_params.append(urllib2.quote(arg.encode('utf-8'), safe="")) raise cherrypy.HTTPRedirect(self.uri_fmt % tuple(uri_params), code) elif action_result is not None and action_result != self.ident: uri_params = list(self.model_args[:-1]) uri_params += [urllib2.quote(action_result.encode('utf-8'), safe="")] raise cherrypy.HTTPRedirect(self.uri_fmt % tuple(uri_params), code) def generate_action_handler(self, action_name, action_args=None, destructive=False): def _render_element(self, ident): self._redirect(ident) uri_params = [] for arg in self.model_args: if arg is None: arg = '' uri_params.append(urllib2.quote(arg.encode('utf-8'), safe="")) raise internal_redirect(self.uri_fmt % tuple(uri_params)) return self._generate_action_handler_base(action_name, _render_element, destructive=destructive, action_args=action_args) def generate_action_handler_task(self, action_name, action_args=None): def _render_task(self, task): cherrypy.response.status = 202 return kimchi.template.render('Task', task) return self._generate_action_handler_base(action_name, _render_task, action_args=action_args) def _generate_action_handler_base(self, action_name, render_fn, destructive=False, action_args=None): def wrapper(*args, **kwargs): validate_method(('POST'), self.role_key, self.admin_methods) try: self.lookup() if not self.is_authorized(): raise UnauthorizedError('KCHAPI0009E') model_args = list(self.model_args) if action_args is not None: request = parse_request() model_args.extend(request[key] for key in action_args) action_fn = getattr(self.model, model_fn(self, action_name)) action_result = action_fn(*model_args) if destructive is False or \ ('persistent' in self.info.keys() and self.info['persistent'] is True): return render_fn(self, action_result) except MissingParameter, e: raise cherrypy.HTTPError(400, e.message) except InvalidParameter, e: raise cherrypy.HTTPError(400, e.message) except InvalidOperation, e: raise cherrypy.HTTPError(400, e.message) except UnauthorizedError, e: raise cherrypy.HTTPError(403, e.message) except NotFoundError, e: raise cherrypy.HTTPError(404, e.message) except OperationFailed, e: raise cherrypy.HTTPError(500, e.message) except KimchiException, e: raise cherrypy.HTTPError(500, e.message) wrapper.__name__ = action_name wrapper.exposed = True return wrapper def lookup(self): try: lookup = getattr(self.model, model_fn(self, 'lookup')) self.info = lookup(*self.model_args) except AttributeError: self.info = {} def delete(self): try: fn = getattr(self.model, model_fn(self, 'delete')) fn(*self.model_args) cherrypy.response.status = 204 except AttributeError: e = InvalidOperation('KCHAPI0002E', {'resource': get_class_name(self)}) raise cherrypy.HTTPError(405, e.message) except OperationFailed, e: raise cherrypy.HTTPError(500, e.message) except InvalidOperation, e: raise cherrypy.HTTPError(400, e.message) @cherrypy.expose def index(self, *args, **kargs): method = validate_method(('GET', 'DELETE', 'PUT'), self.role_key, self.admin_methods) try: self.lookup() if not self.is_authorized(): raise UnauthorizedError('KCHAPI0009E') return {'GET': self.get, 'DELETE': self.delete, 'PUT': self.update}[method](*args, **kargs) except InvalidOperation, e: raise cherrypy.HTTPError(400, e.message) except InvalidParameter, e: raise cherrypy.HTTPError(400, e.message) except UnauthorizedError, e: raise cherrypy.HTTPError(403, e.message) except NotFoundError, e: raise cherrypy.HTTPError(404, e.message) except OperationFailed, e: raise cherrypy.HTTPError(500, e.message) except KimchiException, e: raise cherrypy.HTTPError(500, e.message) def is_authorized(self): user_name = cherrypy.session.get(USER_NAME, '') user_groups = cherrypy.session.get(USER_GROUPS, []) user_role = cherrypy.session.get(USER_ROLES, {}).get(self.role_key) users = self.data.get("users", None) groups = self.data.get("groups", None) if (users is None and groups is None) or user_role == 'admin': return True return user_name in users or len(set(user_groups) & set(groups)) > 0 def update(self, *args, **kargs): try: update = getattr(self.model, model_fn(self, 'update')) except AttributeError: e = InvalidOperation('KCHAPI0003E', {'resource': get_class_name(self)}) raise cherrypy.HTTPError(405, e.message) params = parse_request() validate_params(params, self, 'update') args = list(self.model_args) + [params] ident = update(*args) self._redirect(ident) return self.get() def get(self): self.lookup() return kimchi.template.render(get_class_name(self), self.data) @property def data(self): """ Override this in inherited classes to provide the Resource representation as a python dictionary. """ return {} class Collection(object): """ A Collection is a container for Resource objects. To create a new Collection type, subclass this and make the following changes to the child class: - Set self.resource to the type of Resource that this Collection contains - Set self.resource_args. This can remain an empty list if the Resources can be initialized with only one identifier. Otherwise, include additional values as needed (eg. to identify a parent resource). - Set self.model_args. Similar to above, this is needed only if the model needs additional information to identify this Collection. - Implement the base operations of 'create' and 'get_list' in the model. """ def __init__(self, model): self.model = model self.resource = Resource self.resource_args = [] self.model_args = [] self.role_key = None self.admin_methods = [] def create(self, params, *args): try: create = getattr(self.model, model_fn(self, 'create')) except AttributeError: e = InvalidOperation('KCHAPI0005E', {'resource': get_class_name(self)}) raise cherrypy.HTTPError(405, e.message) validate_params(params, self, 'create') args = self.model_args + [params] name = create(*args) cherrypy.response.status = 201 args = self.resource_args + [name] res = self.resource(self.model, *args) return res.get() def _get_resources(self, flag_filter): try: get_list = getattr(self.model, model_fn(self, 'get_list')) idents = get_list(*self.model_args, **flag_filter) res_list = [] for ident in idents: # internal text, get_list changes ident to unicode for sorted args = self.resource_args + [ident] res = self.resource(self.model, *args) res.lookup() res_list.append(res) return res_list except AttributeError: return [] def _cp_dispatch(self, vpath): if vpath: ident = vpath.pop(0) ident = urllib2.unquote(ident) # incoming text, from URL, is not unicode, need decode args = self.resource_args + [ident.decode("utf-8")] return self.resource(self.model, *args) def filter_data(self, resources, fields_filter): data = [] for res in resources: if not res.is_authorized(): continue if all(key in res.data and (res.data[key] == val or res.data[key] in val or re.match(str(val), res.data[key])) for key, val in fields_filter.iteritems()): data.append(res.data) return data def get(self, filter_params): def _split_filter(params): flag_filter = dict() fields_filter = params for key, val in params.items(): if key.startswith('_'): flag_filter[key] = fields_filter.pop(key) return flag_filter, fields_filter flag_filter, fields_filter = _split_filter(filter_params) resources = self._get_resources(flag_filter) data = self.filter_data(resources, fields_filter) return kimchi.template.render(get_class_name(self), data) @cherrypy.expose def index(self, *args, **kwargs): method = validate_method(('GET', 'POST'), self.role_key, self.admin_methods) try: if method == 'GET': filter_params = cherrypy.request.params validate_params(filter_params, self, 'get_list') return self.get(filter_params) elif method == 'POST': return self.create(parse_request(), *args) except InvalidOperation, e: raise cherrypy.HTTPError(400, e.message) except InvalidParameter, e: raise cherrypy.HTTPError(400, e.message) except MissingParameter, e: raise cherrypy.HTTPError(400, e.message) except NotFoundError, e: raise cherrypy.HTTPError(404, e.message) except OperationFailed, e: raise cherrypy.HTTPError(500, e.message) except KimchiException, e: raise cherrypy.HTTPError(500, e.message) class AsyncCollection(Collection): """ A Collection to create it's resource by asynchronous task """ def __init__(self, model): super(AsyncCollection, self).__init__(model) def create(self, params, *args): try: create = getattr(self.model, model_fn(self, 'create')) except AttributeError: e = InvalidOperation('KCHAPI0005E', {'resource': get_class_name(self)}) raise cherrypy.HTTPError(405, e.message) validate_params(params, self, 'create') args = self.model_args + [params] task = create(*args) cherrypy.response.status = 202 return kimchi.template.render("Task", task) class SimpleCollection(Collection): """ A Collection without Resource definition """ def __init__(self, model): super(SimpleCollection, self).__init__(model) def get(self, filter_params): res_list = [] try: get_list = getattr(self.model, model_fn(self, 'get_list')) res_list = get_list(*self.model_args) except AttributeError: pass return kimchi.template.render(get_class_name(self), res_list) kimchi-1.5.0/src/kimchi/control/config.py000066400000000000000000000032011254252253000203070ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-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 from kimchi.control.base import Collection, Resource from kimchi.control.utils import UrlSubNode @UrlSubNode("config") class Config(Resource): def __init__(self, model, id=None): super(Config, self).__init__(model, id) self.capabilities = Capabilities(self.model) self.distros = Distros(model) @property def data(self): return self.info class Capabilities(Resource): def __init__(self, model, id=None): super(Capabilities, self).__init__(model, id) @property def data(self): return self.info class Distros(Collection): def __init__(self, model): super(Distros, self).__init__(model) self.resource = Distro class Distro(Resource): def __init__(self, model, ident): super(Distro, self).__init__(model, ident) @property def data(self): return self.info kimchi-1.5.0/src/kimchi/control/cpuinfo.py000066400000000000000000000024571254252253000205210ustar00rootroot00000000000000# # 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 from kimchi.control.base import Resource class CPUInfo(Resource): def __init__(self, model): super(CPUInfo, self).__init__(model) self.admin_methods = ['GET'] self.role_key = 'host' self.uri_fmt = "/host/cpuinfo" @property def data(self): return {'threading_enabled': self.info['guest_threads_enabled'], 'sockets': self.info['sockets'], 'cores': self.info['cores_available'], 'threads_per_core': self.info['threads_per_core'] } kimchi-1.5.0/src/kimchi/control/debugreports.py000066400000000000000000000041611254252253000215550ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-2015 # # 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 from kimchi.control.base import AsyncCollection, Resource from kimchi.control.utils import internal_redirect from kimchi.control.utils import UrlSubNode @UrlSubNode('debugreports', True) class DebugReports(AsyncCollection): def __init__(self, model): super(DebugReports, self).__init__(model) self.resource = DebugReport self.role_key = 'host' self.admin_methods = ['GET', 'POST'] def _get_resources(self, filter_params): res_list = super(DebugReports, self)._get_resources(filter_params) return sorted(res_list, key=lambda x: x.data['time'], reverse=True) class DebugReport(Resource): def __init__(self, model, ident): super(DebugReport, self).__init__(model, ident) self.role_key = 'host' self.admin_methods = ['GET', 'PUT', 'POST'] self.uri_fmt = '/debugreports/%s' self.content = DebugReportContent(model, ident) @property def data(self): return {'name': self.ident, 'uri': self.info['uri'], 'time': self.info['ctime']} class DebugReportContent(Resource): def __init__(self, model, ident): super(DebugReportContent, self).__init__(model, ident) self.role_key = 'host' self.admin_methods = ['GET'] def get(self): self.lookup() raise internal_redirect(self.info['uri']) kimchi-1.5.0/src/kimchi/control/groups.py000066400000000000000000000020271254252253000203660ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-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 from kimchi.control.base import SimpleCollection from kimchi.control.utils import UrlSubNode @UrlSubNode('groups', True) class Groups(SimpleCollection): def __init__(self, model): super(Groups, self).__init__(model) self.role_key = 'guests' kimchi-1.5.0/src/kimchi/control/host.py000066400000000000000000000112521254252253000200240ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-2015 # # 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 from kimchi.control.cpuinfo import CPUInfo from kimchi.control.base import Collection, Resource, SimpleCollection from kimchi.control.utils import UrlSubNode from kimchi.exception import NotFoundError @UrlSubNode('host', True) class Host(Resource): def __init__(self, model, id=None): super(Host, self).__init__(model, id) self.role_key = 'host' self.admin_methods = ['GET', 'POST'] self.uri_fmt = '/host/%s' self.reboot = self.generate_action_handler('reboot') self.shutdown = self.generate_action_handler('shutdown') self.stats = HostStats(self.model) self.partitions = Partitions(self.model) self.devices = Devices(self.model) self.packagesupdate = PackagesUpdate(self.model) self.repositories = Repositories(self.model) self.swupdate = self.generate_action_handler_task('swupdate') self.cpuinfo = CPUInfo(self.model) @property def data(self): return self.info class HostStats(Resource): def __init__(self, model, id=None): super(HostStats, self).__init__(model, id) self.role_key = 'host' self.admin_methods = ['GET'] self.history = HostStatsHistory(self.model) @property def data(self): return self.info class HostStatsHistory(Resource): @property def data(self): return self.info class Partitions(Collection): def __init__(self, model): super(Partitions, self).__init__(model) self.role_key = 'storage' self.admin_methods = ['GET'] self.resource = Partition # Defining get_resources in order to return list of partitions in UI # sorted by their path def _get_resources(self, flag_filter): res_list = super(Partitions, self)._get_resources(flag_filter) res_list = filter(lambda x: x.info['available'], res_list) res_list.sort(key=lambda x: x.info['path']) return res_list class Partition(Resource): def __init__(self, model, id): self.role_key = 'storage' self.admin_methods = ['GET'] super(Partition, self).__init__(model, id) @property def data(self): if not self.info['available']: raise NotFoundError("KCHPART0001E", {'name': self.info['name']}) return self.info class Devices(Collection): def __init__(self, model): super(Devices, self).__init__(model) self.resource = Device class VMHolders(SimpleCollection): def __init__(self, model, device_id): super(VMHolders, self).__init__(model) self.model_args = (device_id, ) class Device(Resource): def __init__(self, model, id): super(Device, self).__init__(model, id) self.vm_holders = VMHolders(self.model, id) @property def data(self): return self.info class PackagesUpdate(Collection): def __init__(self, model): super(PackagesUpdate, self).__init__(model) self.role_key = 'host' self.admin_methods = ['GET'] self.resource = PackageUpdate class PackageUpdate(Resource): def __init__(self, model, id=None): super(PackageUpdate, self).__init__(model, id) self.role_key = 'host' self.admin_methods = ['GET'] @property def data(self): return self.info class Repositories(Collection): def __init__(self, model): super(Repositories, self).__init__(model) self.role_key = 'host' self.admin_methods = ['GET', 'POST'] self.resource = Repository class Repository(Resource): def __init__(self, model, id): super(Repository, self).__init__(model, id) self.role_key = 'host' self.admin_methods = ['GET', 'PUT', 'POST', 'DELETE'] self.uri_fmt = "/host/repositories/%s" self.enable = self.generate_action_handler('enable') self.disable = self.generate_action_handler('disable') @property def data(self): return self.info kimchi-1.5.0/src/kimchi/control/interfaces.py000066400000000000000000000031221254252253000211670ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-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 from kimchi.control.base import Collection, Resource from kimchi.control.utils import UrlSubNode @UrlSubNode('interfaces', True) class Interfaces(Collection): def __init__(self, model): super(Interfaces, self).__init__(model) self.role_key = 'network' self.admin_methods = ['GET'] self.resource = Interface class Interface(Resource): def __init__(self, model, ident): super(Interface, self).__init__(model, ident) self.role_key = 'network' self.admin_methods = ['GET'] self.uri_fmt = "/interfaces/%s" @property def data(self): return {'name': self.ident, 'type': self.info['type'], 'ipaddr': self.info['ipaddr'], 'netmask': self.info['netmask'], 'status': self.info['status']} kimchi-1.5.0/src/kimchi/control/networks.py000066400000000000000000000040431254252253000207230ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-2015 # # 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 from kimchi.control.base import Collection, Resource from kimchi.control.utils import UrlSubNode @UrlSubNode('networks', True) class Networks(Collection): def __init__(self, model): super(Networks, self).__init__(model) self.role_key = 'network' self.admin_methods = ['POST'] self.resource = Network class Network(Resource): def __init__(self, model, ident): super(Network, self).__init__(model, ident) self.role_key = 'network' self.admin_methods = ['PUT', 'POST', 'DELETE'] self.uri_fmt = "/networks/%s" self.activate = self.generate_action_handler('activate') self.deactivate = self.generate_action_handler('deactivate', destructive=True) @property def data(self): return {'name': self.ident, 'vms': self.info['vms'], 'in_use': self.info['in_use'], 'autostart': self.info['autostart'], 'connection': self.info['connection'], 'interface': self.info['interface'], 'subnet': self.info['subnet'], 'dhcp': self.info['dhcp'], 'state': self.info['state'], 'persistent': self.info['persistent']} kimchi-1.5.0/src/kimchi/control/peers.py000066400000000000000000000020631254252253000201650ustar00rootroot00000000000000# # 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 from kimchi.control.base import SimpleCollection from kimchi.control.utils import UrlSubNode @UrlSubNode("peers", True) class Peers(SimpleCollection): def __init__(self, model): super(Peers, self).__init__(model) self.role_key = 'peers' self.admin_methods = ['GET'] kimchi-1.5.0/src/kimchi/control/plugins.py000066400000000000000000000017631254252253000205360ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-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 from kimchi.control.base import SimpleCollection from kimchi.control.utils import UrlSubNode @UrlSubNode("plugins") class Plugins(SimpleCollection): def __init__(self, model): super(Plugins, self).__init__(model) kimchi-1.5.0/src/kimchi/control/storagepools.py000066400000000000000000000076551254252253000216040ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-2015 # # 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 import cherrypy from kimchi.control.base import Collection, Resource from kimchi.control.storagevolumes import IsoVolumes, StorageVolumes from kimchi.control.utils import get_class_name, model_fn from kimchi.control.utils import validate_params from kimchi.model.storagepools import ISO_POOL_NAME from kimchi.control.utils import UrlSubNode @UrlSubNode('storagepools', True) class StoragePools(Collection): def __init__(self, model): super(StoragePools, self).__init__(model) self.role_key = 'storage' self.admin_methods = ['POST'] self.resource = StoragePool isos = IsoPool(model) setattr(self, ISO_POOL_NAME, isos) def create(self, params, *args): try: create = getattr(self.model, model_fn(self, 'create')) except AttributeError: error = 'Create is not allowed for %s' % get_class_name(self) raise cherrypy.HTTPError(405, error) validate_params(params, self, 'create') args = self.model_args + [params] name = create(*args) args = self.resource_args + [name] res = self.resource(self.model, *args) resp = res.get() if 'task_id' in res.data: cherrypy.response.status = 202 else: cherrypy.response.status = 201 return resp def _get_resources(self, filter_params): try: res_list = super(StoragePools, self)._get_resources(filter_params) # Append reserved pools isos = getattr(self, ISO_POOL_NAME) isos.lookup() res_list.append(isos) except AttributeError: pass return res_list class StoragePool(Resource): def __init__(self, model, ident): super(StoragePool, self).__init__(model, ident) self.role_key = 'storage' self.admin_methods = ['PUT', 'POST', 'DELETE'] self.uri_fmt = "/storagepools/%s" self.activate = self.generate_action_handler('activate') self.deactivate = self.generate_action_handler('deactivate', destructive=True) self.storagevolumes = StorageVolumes(self.model, ident) @property def data(self): res = {'name': self.ident, 'state': self.info['state'], 'capacity': self.info['capacity'], 'allocated': self.info['allocated'], 'available': self.info['available'], 'path': self.info['path'], 'source': self.info['source'], 'type': self.info['type'], 'nr_volumes': self.info['nr_volumes'], 'autostart': self.info['autostart'], 'persistent': self.info['persistent']} val = self.info.get('task_id') if val: res['task_id'] = val return res class IsoPool(Resource): def __init__(self, model): super(IsoPool, self).__init__(model, ISO_POOL_NAME) self.storagevolumes = IsoVolumes(self.model, ISO_POOL_NAME) @property def data(self): return {'name': self.ident, 'state': self.info['state'], 'type': self.info['type']} kimchi-1.5.0/src/kimchi/control/storageservers.py000066400000000000000000000041461254252253000221310ustar00rootroot00000000000000# # 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 import kimchi.template from kimchi.control.base import Collection, Resource from kimchi.control.utils import get_class_name, model_fn, UrlSubNode @UrlSubNode('storageservers', True) class StorageServers(Collection): def __init__(self, model): super(StorageServers, self).__init__(model) self.role_key = 'storage' self.admin_methods = ['GET'] self.resource = StorageServer class StorageServer(Resource): def __init__(self, model, ident): super(StorageServer, self).__init__(model, ident) self.role_key = 'storage' self.admin_methods = ['GET'] self.storagetargets = StorageTargets(self.model, self.ident.decode("utf-8")) @property def data(self): return self.info class StorageTargets(Collection): def __init__(self, model, server): super(StorageTargets, self).__init__(model) self.role_key = 'storage' self.admin_methods = ['GET'] self.server = server self.resource_args = [self.server, ] self.model_args = [self.server, ] def get(self, filter_params): res_list = [] get_list = getattr(self.model, model_fn(self, 'get_list')) res_list = get_list(*self.model_args, **filter_params) return kimchi.template.render(get_class_name(self), res_list) kimchi-1.5.0/src/kimchi/control/storagevolumes.py000066400000000000000000000057031254252253000221320ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-2015 # # 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 import kimchi.template from kimchi.control.base import AsyncCollection, Collection, Resource from kimchi.control.utils import get_class_name, model_fn class StorageVolumes(AsyncCollection): def __init__(self, model, pool): super(StorageVolumes, self).__init__(model) self.resource = StorageVolume self.pool = pool self.resource_args = [self.pool, ] self.model_args = [self.pool, ] def filter_data(self, resources, fields_filter): # filter directory from storage volumes fields_filter.update({'type': ['file', 'block', 'network']}) return super(StorageVolumes, self).filter_data(resources, fields_filter) class StorageVolume(Resource): def __init__(self, model, pool, ident): super(StorageVolume, self).__init__(model, ident) self.pool = pool self.ident = ident self.info = {} self.model_args = [self.pool, self.ident] self.uri_fmt = '/storagepools/%s/storagevolumes/%s' self.resize = self.generate_action_handler('resize', ['size']) self.wipe = self.generate_action_handler('wipe') self.clone = self.generate_action_handler_task('clone') @property def data(self): res = {'name': self.ident, 'type': self.info['type'], 'capacity': self.info['capacity'], 'allocation': self.info['allocation'], 'path': self.info['path'], 'used_by': self.info['used_by'], 'format': self.info['format']} for key in ('os_version', 'os_distro', 'bootable', 'base'): val = self.info.get(key) if val: res[key] = val return res class IsoVolumes(Collection): def __init__(self, model, pool): super(IsoVolumes, self).__init__(model) self.pool = pool def get(self, filter_params): res_list = [] try: get_list = getattr(self.model, model_fn(self, 'get_list')) res_list = get_list(*self.model_args) except AttributeError: pass return kimchi.template.render(get_class_name(self), res_list) kimchi-1.5.0/src/kimchi/control/tasks.py000066400000000000000000000022631254252253000201760ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-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 from kimchi.control.base import Collection, Resource from kimchi.control.utils import UrlSubNode @UrlSubNode("tasks", True) class Tasks(Collection): def __init__(self, model): super(Tasks, self).__init__(model) self.resource = Task class Task(Resource): def __init__(self, model, id): super(Task, self).__init__(model, id) @property def data(self): return self.info kimchi-1.5.0/src/kimchi/control/templates.py000066400000000000000000000041371254252253000210510ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-2015 # # 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 from kimchi.control.base import Collection, Resource from kimchi.control.utils import UrlSubNode @UrlSubNode('templates', True) class Templates(Collection): def __init__(self, model): super(Templates, self).__init__(model) self.role_key = 'templates' self.admin_methods = ['GET', 'POST'] self.resource = Template class Template(Resource): def __init__(self, model, ident): super(Template, self).__init__(model, ident) self.role_key = 'templates' self.admin_methods = ['PUT', 'POST', 'DELETE'] self.uri_fmt = "/templates/%s" self.clone = self.generate_action_handler('clone') @property def data(self): return { 'name': self.ident, 'icon': self.info['icon'], 'invalid': self.info['invalid'], 'os_distro': self.info['os_distro'], 'os_version': self.info['os_version'], 'cpus': self.info['cpus'], 'memory': self.info['memory'], 'cdrom': self.info.get('cdrom', None), 'disks': self.info['disks'], 'storagepool': self.info['storagepool'], 'networks': self.info['networks'], 'folder': self.info.get('folder', []), 'graphics': self.info['graphics'], 'cpu_info': self.info.get('cpu_info') } kimchi-1.5.0/src/kimchi/control/users.py000066400000000000000000000025021254252253000202060ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-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 from kimchi.control.base import SimpleCollection from kimchi.control.utils import get_class_name, model_fn, UrlSubNode from kimchi.template import render @UrlSubNode('users', True) class Users(SimpleCollection): def __init__(self, model): super(Users, self).__init__(model) self.role_key = 'guests' def get(self, filter_params): res_list = [] get_list = getattr(self.model, model_fn(self, 'get_list')) res_list = get_list(*self.model_args, **filter_params) return render(get_class_name(self), res_list) kimchi-1.5.0/src/kimchi/control/utils.py000066400000000000000000000103771254252253000202160ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-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 # import cherrypy import json from jsonschema import Draft3Validator, ValidationError, FormatChecker from kimchi.auth import USER_ROLES from kimchi.exception import InvalidParameter, OperationFailed from kimchi.utils import import_module, listPathModules def get_class_name(cls): try: sub_class = cls.__subclasses__()[0] except AttributeError: sub_class = cls.__class__.__name__ return sub_class.lower() def model_fn(cls, fn_name): return '%s_%s' % (get_class_name(cls), fn_name) def validate_method(allowed, role_key, admin_methods): method = cherrypy.request.method.upper() if method not in allowed: raise cherrypy.HTTPError(405) user_role = cherrypy.session.get(USER_ROLES, {}).get(role_key) if user_role and user_role != 'admin' and method in admin_methods: raise cherrypy.HTTPError(403) return method def mime_in_header(header, mime): if header not in cherrypy.request.headers: accepts = 'application/json' else: accepts = cherrypy.request.headers[header] if accepts.find(';') != -1: accepts, _ = accepts.split(';', 1) if mime in accepts.split(','): return True return False def parse_request(): if 'Content-Length' not in cherrypy.request.headers: return {} if mime_in_header('Content-Type', 'application/json'): if cherrypy.request.body.length == 0: return {} rawbody = cherrypy.request.body.read() try: return json.loads(rawbody) except ValueError: e = OperationFailed('KCHAPI0006E') raise cherrypy.HTTPError(400, e.message) elif mime_in_header('Content-Type', 'multipart/form-data'): return cherrypy.request.params else: e = OperationFailed('KCHAPI0007E') raise cherrypy.HTTPError(415, e.message) def internal_redirect(url): raise cherrypy.InternalRedirect(url.encode("utf-8")) def validate_params(params, instance, action): root = cherrypy.request.app.root if hasattr(root, 'api_schema'): api_schema = root.api_schema else: return operation = model_fn(instance, action) validator = Draft3Validator(api_schema, format_checker=FormatChecker()) request = {operation: params} try: validator.validate(request) except ValidationError, e: if e.schema.get('error'): raise InvalidParameter(e.schema['error'], {'value': str(e.instance)}) else: raise InvalidParameter("KCHAPI0008E", {"err": str(e.message)}) class UrlSubNode(object): def __init__(self, name, auth=False): """ admin_methods must be None, or a list containing zero or more of the string values ['GET', 'POST', 'PUT', 'DELETE'] """ self.name = name self.auth = auth def __call__(self, fun): fun._url_sub_node_name = {"name": self.name} fun.url_auth = self.auth return fun def load_url_sub_node(path, package_name, expect_attr="_url_sub_node_name"): sub_nodes = {} for mod_name in listPathModules(path): if mod_name.startswith("_"): continue module = import_module(package_name + '.' + mod_name) for node in [getattr(module, x) for x in dir(module)]: if not hasattr(node, expect_attr): continue name = getattr(node, expect_attr)["name"] sub_nodes.update({name: node}) return sub_nodes kimchi-1.5.0/src/kimchi/control/vm/000077500000000000000000000000001254252253000171165ustar00rootroot00000000000000kimchi-1.5.0/src/kimchi/control/vm/Makefile.am000066400000000000000000000015611254252253000211550ustar00rootroot00000000000000# # Kimchi # # Copyright IBM Corp, 2013 # # 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 vm_PYTHON = *.py vmdir = $(pythondir)/kimchi/control/vm install-data-local: $(MKDIR_P) $(DESTDIR)$(vmdir) kimchi-1.5.0/src/kimchi/control/vm/__init__.py000066400000000000000000000016171254252253000212340ustar00rootroot00000000000000# # 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 import os from kimchi.control.utils import load_url_sub_node sub_nodes = load_url_sub_node(os.path.dirname(__file__), __name__) kimchi-1.5.0/src/kimchi/control/vm/hostdevs.py000066400000000000000000000026501254252253000213320ustar00rootroot00000000000000# # 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 from kimchi.control.base import Collection, Resource from kimchi.control.utils import UrlSubNode @UrlSubNode("hostdevs") class VMHostDevs(Collection): def __init__(self, model, vmid): super(VMHostDevs, self).__init__(model) self.resource = VMHostDev self.vmid = vmid self.resource_args = [self.vmid, ] self.model_args = [self.vmid, ] class VMHostDev(Resource): def __init__(self, model, vmid, ident): super(VMHostDev, self).__init__(model, ident) self.vmid = vmid self.ident = ident self.model_args = [self.vmid, self.ident] @property def data(self): return self.info kimchi-1.5.0/src/kimchi/control/vm/ifaces.py000066400000000000000000000027211254252253000207240ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2014-2015 # # 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 from kimchi.control.base import Collection, Resource from kimchi.control.utils import UrlSubNode @UrlSubNode("ifaces") class VMIfaces(Collection): def __init__(self, model, vm): super(VMIfaces, self).__init__(model) self.resource = VMIface self.vm = vm self.resource_args = [self.vm, ] self.model_args = [self.vm, ] class VMIface(Resource): def __init__(self, model, vm, ident): super(VMIface, self).__init__(model, ident) self.vm = vm self.ident = ident self.info = {} self.model_args = [self.vm, self.ident] self.uri_fmt = '/vms/%s/ifaces/%s' @property def data(self): return self.info kimchi-1.5.0/src/kimchi/control/vm/snapshots.py000066400000000000000000000035541254252253000215210ustar00rootroot00000000000000# # 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 from kimchi.control.base import AsyncCollection, Resource from kimchi.control.utils import UrlSubNode @UrlSubNode('snapshots') class VMSnapshots(AsyncCollection): def __init__(self, model, vm): super(VMSnapshots, self).__init__(model) self.resource = VMSnapshot self.vm = vm self.resource_args = [self.vm, ] self.model_args = [self.vm, ] self.current = CurrentVMSnapshot(model, vm) class VMSnapshot(Resource): def __init__(self, model, vm, ident): super(VMSnapshot, self).__init__(model, ident) self.vm = vm self.ident = ident self.model_args = [self.vm, self.ident] self.uri_fmt = '/vms/%s/snapshots/%s' self.revert = self.generate_action_handler('revert') @property def data(self): return self.info class CurrentVMSnapshot(Resource): def __init__(self, model, vm): super(CurrentVMSnapshot, self).__init__(model) self.vm = vm self.model_args = [self.vm] self.uri_fmt = '/vms/%s/snapshots/current' @property def data(self): return self.info kimchi-1.5.0/src/kimchi/control/vm/storages.py000066400000000000000000000027371254252253000213300ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2014-2015 # # 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 from kimchi.control.base import Collection, Resource from kimchi.control.utils import UrlSubNode @UrlSubNode("storages") class VMStorages(Collection): def __init__(self, model, vm): super(VMStorages, self).__init__(model) self.resource = VMStorage self.vm = vm self.resource_args = [self.vm, ] self.model_args = [self.vm, ] class VMStorage(Resource): def __init__(self, model, vm, ident): super(VMStorage, self).__init__(model, ident) self.vm = vm self.ident = ident self.info = {} self.model_args = [self.vm, self.ident] self.uri_fmt = '/vms/%s/storages/%s' @property def data(self): return self.info kimchi-1.5.0/src/kimchi/control/vms.py000066400000000000000000000047221254252253000176600ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-2015 # # 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 from kimchi.control.base import AsyncCollection, Resource from kimchi.control.utils import internal_redirect, UrlSubNode from kimchi.control.vm import sub_nodes @UrlSubNode('vms', True) class VMs(AsyncCollection): def __init__(self, model): super(VMs, self).__init__(model) self.resource = VM self.role_key = 'guests' self.admin_methods = ['POST'] class VM(Resource): def __init__(self, model, ident): super(VM, self).__init__(model, ident) self.role_key = 'guests' self.screenshot = VMScreenShot(model, ident) self.uri_fmt = '/vms/%s' for ident, node in sub_nodes.items(): setattr(self, ident, node(model, self.ident)) self.start = self.generate_action_handler('start') self.poweroff = self.generate_action_handler('poweroff', destructive=True) self.shutdown = self.generate_action_handler('shutdown', destructive=True) self.reset = self.generate_action_handler('reset', destructive=True) self.connect = self.generate_action_handler('connect') self.clone = self.generate_action_handler_task('clone') self.suspend = self.generate_action_handler('suspend') self.resume = self.generate_action_handler('resume') @property def data(self): return self.info class VMScreenShot(Resource): def __init__(self, model, ident): super(VMScreenShot, self).__init__(model, ident) self.role_key = 'guests' def get(self): self.lookup() raise internal_redirect(self.info) kimchi-1.5.0/src/kimchi/disks.py000066400000000000000000000146361254252253000165150ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-2015 # # 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 import os.path import re import subprocess from parted import Device as PDevice from parted import Disk as PDisk from kimchi.exception import OperationFailed from kimchi.utils import kimchi_log def _get_dev_node_path(maj_min): """ Returns device node path given the device number 'major:min' """ dm_name = "/sys/dev/block/%s/dm/name" % maj_min if os.path.exists(dm_name): with open(dm_name) as dm_f: content = dm_f.read().rstrip('\n') return "/dev/mapper/" + content uevent = "/sys/dev/block/%s/uevent" % maj_min with open(uevent) as ueventf: content = ueventf.read() data = dict(re.findall(r'(\S+)=(".*?"|\S+)', content.replace("\n", " "))) return "/dev/%s" % data["DEVNAME"] def _get_lsblk_devs(keys, devs=[]): lsblk = subprocess.Popen( ["lsblk", "-Pbo"] + [','.join(keys)] + devs, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = lsblk.communicate() if lsblk.returncode != 0: raise OperationFailed("KCHDISKS0001E", {'err': err}) return _parse_lsblk_output(out, keys) def _get_dev_major_min(name): maj_min = None keys = ["NAME", "MAJ:MIN"] dev_list = _get_lsblk_devs(keys) for dev in dev_list: if dev['name'].split()[0] == name: maj_min = dev['maj:min'] break else: raise OperationFailed("KCHDISKS0002E", {'device': name}) return maj_min def _is_dev_leaf(devNodePath): try: # By default, lsblk prints a device information followed by children # device information childrenCount = len( _get_lsblk_devs(["NAME"], [devNodePath])) - 1 except OperationFailed as e: # lsblk is known to fail on multipath devices # Assume these devices contain children kimchi_log.error( "Error getting device info for %s: %s", devNodePath, e) return False return childrenCount == 0 def _is_dev_extended_partition(devType, devNodePath): if devType != 'part': return False diskPath = devNodePath.rstrip('0123456789') device = PDevice(diskPath) try: extended_part = PDisk(device).getExtendedPartition() except NotImplementedError as e: kimchi_log.warning( "Error getting extended partition info for dev %s type %s: %s", devNodePath, devType, e.message) # Treate disk with unsupported partiton table as if it does not # contain extended partitions. return False if extended_part and extended_part.path == devNodePath: return True return False def _parse_lsblk_output(output, keys): # output is on format key="value", # where key can be NAME, TYPE, FSTYPE, SIZE, MOUNTPOINT, etc lines = output.rstrip("\n").split("\n") r = [] for line in lines: d = {} for key in keys: expression = r"%s=\".*?\"" % key match = re.search(expression, line) field = match.group() k, v = field.split('=', 1) d[k.lower()] = v[1:-1] r.append(d) return r def _get_vgname(devNodePath): """ Return volume group name of a physical volume. If the device node path is not a physical volume, return empty string. """ pvs = subprocess.Popen( ["pvs", "--unbuffered", "--nameprefixes", "--noheadings", "-o", "vg_name", devNodePath], stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = pvs.communicate() if pvs.returncode != 0: return "" return re.findall(r"LVM2_VG_NAME='([^\']*)'", out)[0] def _is_available(name, devtype, fstype, mountpoint, majmin): devNodePath = _get_dev_node_path(majmin) # Only list unmounted and unformated and leaf and (partition or disk) # leaf means a partition, a disk has no partition, or a disk not held # by any multipath device. Physical volume belongs to no volume group # is also listed. Extended partitions should not be listed. if (devtype in ['part', 'disk', 'mpath'] and fstype in ['', 'LVM2_member'] and mountpoint == "" and _get_vgname(devNodePath) == "" and _is_dev_leaf(devNodePath) and not _is_dev_extended_partition(devtype, devNodePath)): return True return False def get_partitions_names(check=False): names = set() keys = ["NAME", "TYPE", "FSTYPE", "MOUNTPOINT", "MAJ:MIN"] # output is on format key="value", # where key can be NAME, TYPE, FSTYPE, MOUNTPOINT for dev in _get_lsblk_devs(keys): # split()[0] to avoid the second part of the name, after the # whiteline name = dev['name'].split()[0] if check and not _is_available(name, dev['type'], dev['fstype'], dev['mountpoint'], dev['maj:min']): continue names.add(name) return list(names) def get_partition_details(name): majmin = _get_dev_major_min(name) dev_path = _get_dev_node_path(majmin) keys = ["TYPE", "FSTYPE", "SIZE", "MOUNTPOINT"] try: dev = _get_lsblk_devs(keys, [dev_path])[0] except OperationFailed as e: kimchi_log.error( "Error getting partition info for %s: %s", name, e) return {} dev['available'] = _is_available(name, dev['type'], dev['fstype'], dev['mountpoint'], majmin) if dev['mountpoint']: # Sometimes the mountpoint comes with [SWAP] or other # info which is not an actual mount point. Filtering it regexp = re.compile(r"\[.*\]") if regexp.search(dev['mountpoint']) is not None: dev['mountpoint'] = '' dev['path'] = dev_path dev['name'] = name return dev kimchi-1.5.0/src/kimchi/distroloader.py000066400000000000000000000043741254252253000200710ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-2015 # # 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 # import glob import json import os from kimchi import config from kimchi.exception import NotFoundError, OperationFailed from kimchi.utils import kimchi_log ARCHS = {'x86_64': ['x86_64', 'amd64', 'i686', 'x86', 'i386'], 'amd64': ['x86_64', 'amd64', 'i686', 'x86', 'i386'], 'ppc64': ['ppc', 'ppc64'], 'ppc64le': ['ppc64', 'ppc64le']} class DistroLoader(object): def __init__(self, location=None): self.location = location or config.get_distros_store() def _get_json_info(self, fname): msg_args = {'filename': fname} if not os.path.isfile(fname): msg = "DistroLoader: failed to find distro file: %s" % fname kimchi_log.error(msg) raise NotFoundError("KCHDL0001E", msg_args) try: with open(fname) as f: data = json.load(f) return data except ValueError: msg = "DistroLoader: failed to parse distro file: %s" % fname kimchi_log.error(msg) raise OperationFailed("KCHDL0002E", msg_args) def get(self): arch_list = ARCHS.get(os.uname()[4]) all_json_files = glob.glob("%s/%s" % (self.location, "*.json")) distros = [] for f in all_json_files: distros.extend(self._get_json_info(f)) # Return all remote ISOs arch not found return dict([(distro['name'], distro) for distro in distros if (arch_list is None or distro['os_arch'] in arch_list)]) kimchi-1.5.0/src/kimchi/exception.py000066400000000000000000000052171254252253000173710ustar00rootroot00000000000000# # Kimchi # # Copyright IBM, Corp. 2013-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 import cherrypy import gettext from kimchi.i18n import messages as _messages from kimchi.template import get_lang, validate_language class KimchiException(Exception): def __init__(self, code='', args={}): self.code = code for key, value in args.iteritems(): if isinstance(value, unicode): continue # value is not unicode: convert it try: # In case the value formats itself to an ascii string. args[key] = unicode(str(value), 'utf-8') except UnicodeEncodeError: # In case the value is a KimchiException or it formats # itself to a unicode string. args[key] = unicode(value) if cherrypy.request.app: msg = self._get_translation() else: msg = _messages.get(code, code) msg = unicode(msg, 'utf-8') % args pattern = "%s: %s" % (code, msg) Exception.__init__(self, pattern) def _get_translation(self): lang = validate_language(get_lang()) paths = cherrypy.request.app.root.paths domain = cherrypy.request.app.root.domain messages = cherrypy.request.app.root.messages text = messages.get(self.code, self.code) try: translation = gettext.translation(domain, paths.mo_dir, [lang]) except: translation = gettext return translation.gettext(text) class NotFoundError(KimchiException): pass class OperationFailed(KimchiException): pass class MissingParameter(KimchiException): pass class InvalidParameter(KimchiException): pass class InvalidOperation(KimchiException): pass class IsoFormatError(KimchiException): pass class ImageFormatError(KimchiException): pass class TimeoutExpired(KimchiException): pass class UnauthorizedError(KimchiException): pass kimchi-1.5.0/src/kimchi/i18n.py000066400000000000000000000622521254252253000161540ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2014-2015 # # 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 import gettext _ = gettext.gettext messages = { "KCHAPI0001E": _("Unknown parameter %(value)s"), "KCHAPI0002E": _("Delete is not allowed for %(resource)s"), "KCHAPI0003E": _("%(resource)s does not implement update method"), "KCHAPI0005E": _("Create is not allowed for %(resource)s"), "KCHAPI0006E": _("Unable to parse JSON request"), "KCHAPI0007E": _("This API only supports JSON"), "KCHAPI0008E": _("Parameters does not match requirement in schema: %(err)s"), "KCHAPI0009E": _("You don't have permission to perform this operation."), "KCHASYNC0001E": _("Datastore is not initiated in the model object."), "KCHASYNC0002E": _("Unable to start task due error: %(err)s"), "KCHASYNC0003E": _("Timeout of %(seconds)s seconds expired while running task '%(task)s."), "KCHAUTH0001E": _("Authentication failed for user '%(username)s'. [Error code: %(code)s]"), "KCHAUTH0002E": _("You are not authorized to access Kimchi"), "KCHAUTH0003E": _("Specify %(item)s to login into Kimchi"), "KCHAUTH0004E": _("User %(user_id)s not found with given LDAP settings."), "KCHAUTH0005E": _("Invalid LDAP configuration: %(item)s : %(value)s"), "KCHDEVS0001E": _('Unknown "_cap" specified'), "KCHDEVS0002E": _('"_passthrough" should be "true" or "false"'), "KCHDEVS0003E": _('"_passthrough_affected_by" should be a device name string'), "KCHDISKS0001E": _("Error while getting block devices. Details: %(err)s"), "KCHDISKS0002E": _("Error while getting block device information for %(device)s."), "KCHDL0001E": _("Unable to find distro file: %(filename)s"), "KCHDL0002E": _("Unable to parse distro file: %(filename)s. Make sure, it is a JSON file."), "KCHISCSI0001E": _("Unable to login to iSCSI host target %(portal)s. Details: %(err)s"), "KCHISCSI0002E": _("Unable to login to iSCSI host %(host)s target %(target)s"), "KCHISO0001E": _("Unable to find ISO file %(filename)s"), "KCHISO0002E": _("The ISO file %(filename)s is not bootable"), "KCHISO0003E": _("The ISO file %(filename)s does not have a valid El Torito boot record"), "KCHISO0004E": _("Invalid El Torito validation entry in ISO %(filename)s"), "KCHISO0005E": _("Invalid El Torito boot indicator in ISO %(filename)s"), "KCHISO0006E": _("Unexpected volume type for primary volume in ISO %(filename)s"), "KCHISO0007E": _("Bad format while reading volume descriptor in ISO %(filename)s"), "KCHISO0008E": _("The hypervisor doesn't have permission to use this ISO %(filename)s. " "Consider moving it under /var/lib/libvirt, or set the search permission " "to file access control lists for '%(user)s' user if possible, or add the " "'%(user)s' to the ISO path group, or (not recommended) 'chmod -R o+x 'path_to_iso'." "Details: %(err)s" ), "KCHIMG0001E": _("An error occurred when probing image OS information."), "KCHIMG0002E": _("No OS information found in given image."), "KCHIMG0003E": _("Unable to read image file %(filename)s"), "KCHIMG0004E": _("Image file must be an existing file on system. %(filename)s is not a valid input."), "KCHVM0001E": _("Virtual machine %(name)s already exists"), "KCHVM0002E": _("Virtual machine %(name)s does not exist"), "KCHVM0003E": _("Unable to rename virtual machine %(name)s. The name %(new_name)s is already in use or the virtual machine is not powered off."), "KCHVM0004E": _("Unable to retrieve screenshot for stopped virtual machine %(name)s"), "KCHVM0005E": _("Remote ISO image is not supported by this server."), "KCHVM0006E": _("Screenshot is not supported on virtual machine %(name)s"), "KCHVM0007E": _("Unable to create virtual machine %(name)s. Details: %(err)s"), "KCHVM0008E": _("Unable to update virtual machine %(name)s. Details: %(err)s"), "KCHVM0009E": _("Unable to retrieve virtual machine %(name)s. Details: %(err)s"), "KCHVM0010E": _("Unable to connect to powered off virtual machine %(name)s."), "KCHVM0011E": _("Virtual machine name must be a string without slashes (/)"), "KCHVM0012E": _("Invalid template URI %(value)s specified for virtual machine"), "KCHVM0013E": _("Invalid storage pool URI %(value)s specified for virtual machine"), "KCHVM0014E": _("Supported virtual machine graphics are Spice or VNC"), "KCHVM0015E": _("Graphics address to listen on must be IPv4 or IPv6"), "KCHVM0016E": _("Specify a template to create a virtual machine from"), "KCHVM0019E": _("Unable to start virtual machine %(name)s. Details: %(err)s"), "KCHVM0020E": _("Unable to power off virtual machine %(name)s. Details: %(err)s"), "KCHVM0021E": _("Unable to delete virtual machine %(name)s. Details: %(err)s"), "KCHVM0022E": _("Unable to reset virtual machine %(name)s. Details: %(err)s"), "KCHVM0023E": _("User name list must be an array"), "KCHVM0024E": _("User name must be a string"), "KCHVM0025E": _("Group name list must be an array"), "KCHVM0026E": _("Group name must be a string"), "KCHVM0027E": _("User(s) '%(users)s' do not exist"), "KCHVM0028E": _("Group(s) '%(groups)s' do not exist"), "KCHVM0029E": _("Unable to shutdown virtual machine %(name)s. Details: %(err)s"), "KCHVM0030E": _("Unable to get access metadata of virtual machine %(name)s. Details: %(err)s"), "KCHVM0031E": _("The guest console password must be a string."), "KCHVM0032E": _("The life time for the guest console password must be a number."), "KCHVM0033E": _("Virtual machine '%(name)s' must be stopped before cloning it."), "KCHVM0034E": _("Insufficient disk space to clone virtual machine '%(name)s'"), "KCHVM0035E": _("Unable to clone VM '%(name)s'. Details: %(err)s"), "KCHVM0036E": _("Invalid operation for non-persistent virtual machine %(name)s"), "KCHVM0037E": _("Cannot suspend VM '%(name)s' because it is not running."), "KCHVM0038E": _("Unable to suspend VM '%(name)s'. Details: %(err)s"), "KCHVM0039E": _("Cannot resume VM '%(name)s' because it is not paused."), "KCHVM0040E": _("Unable to resume VM '%(name)s'. Details: %(err)s"), "KCHVM0041E": _("Memory assigned is higher then the maximum allowed in the host."), "KCHVM0042E": _("VM '%(name)s' does not support live memory update. Update the memory with the machine offline to enable this feature."), "KCHVM0043E": _("Only increase memory is allowed in active VMs"), "KCHVM0044E": _("For live memory update, new memory value must be equal old memory value plus multiples of 1024 Mib"), "KCHVM0045E": _("There are not enough free slots of 1024 Mib in the guest."), "KCHVM0046E": _("Host's libvirt version does not support memory devices. Libvirt must be >= 1.2.14"), "KCHVM0047E": _("Error attaching memory device. Details: %(error)s"), "KCHVMHDEV0001E": _("VM %(vmid)s does not contain directly assigned host device %(dev_name)s."), "KCHVMHDEV0002E": _("The host device %(dev_name)s is not allowed to directly assign to VM."), "KCHVMHDEV0003E": _("No IOMMU groups found. Host PCI pass through needs IOMMU group to function correctly. " "Please enable Intel VT-d or AMD IOMMU in your BIOS, then verify the Kernel is compiled with IOMMU support. " "For Intel CPU, add intel_iommu=on to your Kernel parameter in /boot/grub2/grub.conf. " "For AMD CPU, add iommu=pt iommu=1."), "KCHVMHDEV0004E": _('"name" should be a device name string'), "KCHVMHDEV0005E": _('The device %(name)s is probably in use by the host. Unable to attach it to the guest.'), "KCHVMIF0001E": _("Interface %(iface)s does not exist in virtual machine %(name)s"), "KCHVMIF0002E": _("Network %(network)s specified for virtual machine %(name)s does not exist"), "KCHVMIF0004E": _("Supported virtual machine interfaces type is only network"), "KCHVMIF0005E": _("Network name for virtual machine interface must be a string"), "KCHVMIF0006E": _("Invalid network model card specified for virtual machine interface"), "KCHVMIF0007E": _("Specify type and network to add a new virtual machine interface"), "KCHVMIF0008E": _("MAC Address must respect this format FF:FF:FF:FF:FF:FF"), "KCHVMIF0009E": _("MAC Address %(mac)s already exists in virtual machine %(name)s"), "KCHVMIF0010E": _("Invalid MAC Address"), "KCHVMIF0011E": _("Cannot change MAC address of a running virtual machine"), "KCHTMPL0001E": _("Template %(name)s already exists"), "KCHTMPL0003E": _("Network '%(network)s' specified for template %(template)s does not exist"), "KCHTMPL0004E": _("Storage pool %(pool)s specified for template %(template)s does not exist"), "KCHTMPL0005E": _("Storage pool %(pool)s specified for template %(template)s is not active"), "KCHTMPL0006E": _("Invalid parameter '%(param)s' specified for CDROM."), "KCHTMPL0007E": _("Network %(network)s specified for template %(template)s is not active"), "KCHTMPL0008E": _("Template name must be a string"), "KCHTMPL0009E": _("Template icon must be a path to the image"), "KCHTMPL0010E": _("Template distribution must be a string"), "KCHTMPL0011E": _("Template distribution version must be a string"), "KCHTMPL0012E": _("The number of CPUs must be an integer greater than 0"), "KCHTMPL0013E": _("Amount of memory (MB) must be an integer greater than 512"), "KCHTMPL0014E": _("Template CDROM must be a local or remote ISO file"), "KCHTMPL0015E": _("Invalid storage pool URI %(value)s specified for template"), "KCHTMPL0016E": _("Specify an ISO image as CDROM or a base image to create a template"), "KCHTMPL0017E": _("All networks for the template must be specified in a list."), "KCHTMPL0018E": _("Specify a volume to a template when storage pool is iSCSI or SCSI"), "KCHTMPL0019E": _("The volume %(volume)s is not in storage pool %(pool)s"), "KCHTMPL0020E": _("Unable to create template due error: %(err)s"), "KCHTMPL0021E": _("Unable to delete template due error: %(err)s"), "KCHTMPL0022E": _("Disk size must be an integer greater than 1GB."), "KCHTMPL0023E": _("Template base image must be a valid local image file"), "KCHTMPL0024E": _("Cannot identify base image %(path)s format"), "KCHTMPL0025E": _("When specifying CPU topology, VCPUs must be a product of sockets, cores, and threads."), "KCHTMPL0026E": _("When specifying CPU topology, each element must be an integer greater than zero."), "KCHTMPL0027E": _("Invalid disk image format. Valid formats: bochs, cloop, cow, dmg, qcow, qcow2, qed, raw, vmdk, vpc."), "KCHPOOL0001E": _("Storage pool %(name)s already exists"), "KCHPOOL0002E": _("Storage pool %(name)s does not exist"), "KCHPOOL0004E": _("Specify %(item)s in order to create the storage pool %(name)s"), "KCHPOOL0005E": _("Unable to delete active storage pool %(name)s"), "KCHPOOL0006E": _("Unable to list storage pools. Details: %(err)s"), "KCHPOOL0007E": _("Unable to create storage pool %(name)s. Details: %(err)s"), "KCHPOOL0008E": _("Unable to get number of storage volumes in storage pool %(name)s. Details: %(err)s"), "KCHPOOL0009E": _("Unable to activate storage pool %(name)s. Details: %(err)s"), "KCHPOOL0010E": _("Unable to deactivate storage pool %(name)s. Details: %(err)s"), "KCHPOOL0011E": _("Unable to delete storage pool %(name)s. Details: %(err)s"), "KCHPOOL0012E": _("Unable to create NFS Pool as export path %(path)s may block during mount"), "KCHPOOL0013E": _("Unable to create NFS Pool as export path %(path)s mount failed"), "KCHPOOL0014E": _("Unsupported storage pool type: %(type)s"), "KCHPOOL0015E": _("Error while retrieving storage pool XML to %(pool)s"), "KCHPOOL0016E": _("Storage pool name must be a string without slashes (/)"), "KCHPOOL0017E": _("Supported storage pool types are dir, netfs, logical, iscsi, isci and kimchi-iso"), "KCHPOOL0018E": _("Storage pool path must be a string"), "KCHPOOL0019E": _("Storage pool host must be a IP or hostname"), "KCHPOOL0020E": _("Storage pool device must be the absolute path to the block device"), "KCHPOOL0021E": _("Storage pool devices parameter must be a list"), "KCHPOOL0022E": _("Target IQN of an iSCSI pool must be a string"), "KCHPOOL0023E": _("Port of a remote storage server must be an integer between 1 and 65535"), "KCHPOOL0024E": _("iSCSI target username must be a string"), "KCHPOOL0025E": _("iSCSI target password must be a string"), "KCHPOOL0026E": _("Specify name and type to create a storage pool"), "KCHPOOL0027E": _("%(disk)s is not a valid disk/partition. Could not add it to the pool %(pool)s."), "KCHPOOL0028E": _("Unable to extend logical pool %(pool)s. Details: %(err)s"), "KCHPOOL0029E": _("The parameter disks only can be updated for logical storage pool."), "KCHPOOL0030E": _("The SCSI host adapter name must be a string."), "KCHPOOL0031E": _("The storage pool kimchi_isos is reserved for internal use"), "KCHPOOL0032E": _("Unable to activate NFS storage pool %(name)s. NFS server %(server)s is unreachable."), "KCHPOOL0033E": _("Unable to deactivate NFS storage pool %(name)s. NFS server %(server)s is unreachable."), "KCHPOOL0034E": _("Unable to deactivate pool %(name)s as it is associated with some templates"), "KCHPOOL0035E": _("Unable to delete pool %(name)s as it is associated with some templates"), "KCHPOOL0036E": _("A volume group named '%(name)s' already exists. Please, choose another name to create the logical pool."), "KCHPOOL0037E": _("Unable to update database with deep scan information due error: %(err)s"), "KCHVOL0001E": _("Storage volume %(name)s already exists"), "KCHVOL0002E": _("Storage volume %(name)s does not exist in storage pool %(pool)s"), "KCHVOL0003E": _("Unable to create storage volume %(volume)s because storage pool %(pool)s is not active"), "KCHVOL0004E": _("Specify %(item)s in order to create storage volume %(volume)s"), "KCHVOL0006E": _("Unable to list storage volumes because storage pool %(pool)s is not active"), "KCHVOL0007E": _("Unable to create storage volume %(name)s in storage pool %(pool)s. Details: %(err)s"), "KCHVOL0008E": _("Unable to list storage volumes in storage pool %(pool)s. Details: %(err)s"), "KCHVOL0009E": _("Unable to wipe storage volumes %(name)s. Details: %(err)s"), "KCHVOL0010E": _("Unable to delete storage volume %(name)s. Details: %(err)s"), "KCHVOL0011E": _("Unable to resize storage volume %(name)s. Details: %(err)s"), "KCHVOL0012E": _("Storage type %(type)s does not support volume create and delete"), "KCHVOL0013E": _("Storage volume name must be a string"), "KCHVOL0014E": _("Storage volume allocation must be an integer number"), "KCHVOL0015E": _("Storage volume format not supported. Valid formats: bochs, cloop, cow, dmg, qcow, qcow2, qed, raw, vmdk, vpc."), "KCHVOL0016E": _("Storage volume requires a volume name"), "KCHVOL0017E": _("Unable to update database with storage volume information due error: %(err)s"), "KCHVOL0018E": _("Only one of parameter %(param)s can be specified"), "KCHVOL0019E": _("Create volume from %(param)s is not supported"), "KCHVOL0020E": _("Storage volume capacity must be an integer number."), "KCHVOL0021E": _("Storage volume URL must be http://, https://, ftp:// or ftps://."), "KCHVOL0022E": _("Unable to access file %(url)s. Please, check it."), "KCHVOL0023E": _("Unable to clone storage volume '%(name)s' in pool '%(pool)s'. Details: %(err)s"), "KCHVOL0024E": _("Specify chunk data and its size to upload a file."), "KCHVOL0025E": _("In order to upload a storage volume, specify the 'upload' parameter."), "KCHVOL0026E": _("Unable to upload chunk data as it does not match with requested chunk size."), "KCHVOL0027E": _("The storage volume %(vol)s is not under an upload process."), "KCHVOL0028E": _("The upload chunk data will exceed the storage volume size."), "KCHVOL0029E": _("Unable to upload chunk data to storage volume. Details: %(err)s."), "KCHIFACE0001E": _("Interface %(name)s does not exist"), "KCHNET0001E": _("Network %(name)s already exists"), "KCHNET0002E": _("Network %(name)s does not exist"), "KCHNET0003E": _("Subnet %(subnet)s specified for network %(network)s is not valid."), "KCHNET0004E": _("Specify a network interface to create bridged network %(name)s"), "KCHNET0005E": _("Unable to delete active network %(name)s"), "KCHNET0006E": _("Interface %(iface)s specified for network %(network)s is already in use"), "KCHNET0007E": _("Interface should be bare NIC, bonding or bridge device."), "KCHNET0008E": _("Unable to create network %(name)s. Details: %(err)s"), "KCHNET0009E": _("Unable to find a free IP address for network '%(name)s'"), "KCHNET0010E": _("The interface %(iface)s already exists."), "KCHNET0011E": _("Network name must be a string without slashes (/) or quotes (\")"), "KCHNET0012E": _("Supported network types are isolated, NAT and bridge"), "KCHNET0013E": _("Network subnet must be a string with IP address and prefix or netmask"), "KCHNET0014E": _("Network interface must be a string"), "KCHNET0015E": _("Network VLAN ID must be an integer between 1 and 4094"), "KCHNET0016E": _("Specify name and type to create a Network"), "KCHNET0017E": _("Unable to delete network %(name)s. There are some virtual machines %(vms)s and/or templates linked to this network."), "KCHNET0018E": _("Unable to deactivate network %(name)s. There are some virtual machines %(vms)s and/or templates linked to this network."), "KCHNET0019E": _("Bridge device %(name)s can not be the trunk device of a VLAN."), "KCHNET0020E": _("Failed to activate interface %(iface)s: %(err)s."), "KCHNET0021E": _("Failed to activate interface %(iface)s. Please check the physical link status."), "KCHNET0022E": _("Failed to start network %(name)s. Details: %(err)s"), "KCHDR0001E": _("Debug report %(name)s does not exist"), "KCHDR0002E": _("Debug report tool not found in system"), "KCHDR0003E": _("Unable to create debug report %(name)s. Details: %(err)s."), "KCHDR0004E": _("Can not find any debug report with the given name %(name)s"), "KCHDR0005E": _("Unable to generate debug report %(name)s. Details: %(err)s"), "KCHDR0006E": _("You should give a name for the debug report file."), "KCHDR0007E": _("Debug report name must be a string. Only letters, digits, underscore ('_') and hyphen ('-') are allowed."), "KCHDR0008E": _("The debug report with specified name \"%(name)s\" already exists. Please use another one."), "KCHSR0001E": _("Storage server %(server)s was not used by Kimchi"), "KCHDISTRO0001E": _("Distro '%(name)s' does not exist"), "KCHPART0001E": _("Partition %(name)s does not exist in the host"), "KCHHOST0001E": _("Unable to shutdown host machine as there are running virtual machines"), "KCHHOST0002E": _("Unable to reboot host machine as there are running virtual machines"), "KCHHOST0003E": _("Node device '%(name)s' not found"), "KCHHOST0004E": _("Conflicting flag filters specified."), "KCHPKGUPD0001E": _("No packages marked for update"), "KCHPKGUPD0002E": _("Package %(name)s is not marked to be updated."), "KCHPKGUPD0003E": _("Error while getting packages marked to be updated. Details: %(err)s"), "KCHPKGUPD0004E": _("There is no compatible package manager for this system."), "KCHOBJST0001E": _("Unable to find %(item)s in datastore"), "KCHUTILS0001E": _("Invalid URI %(uri)s"), "KCHUTILS0002E": _("Timeout while running command '%(cmd)s' after %(seconds)s seconds"), "KCHUTILS0003E": _("Unable to choose a virtual machine name"), "KCHUTILS0004E": _("Invalid data value '%(value)s'"), "KCHUTILS0005E": _("Invalid data unit '%(unit)s'"), "KCHVMSTOR0002E": _("Invalid storage type. Types supported: 'cdrom', 'disk'"), "KCHVMSTOR0003E": _("The path '%(value)s' is not a valid local/remote path for the device"), "KCHVMSTOR0006E": _("Only CDROM path can be update."), "KCHVMSTOR0007E": _("The storage device %(dev_name)s does not exist in the virtual machine %(vm_name)s"), "KCHVMSTOR0008E": _("Error while creating new storage device: %(error)s"), "KCHVMSTOR0009E": _("Error while updating storage device: %(error)s"), "KCHVMSTOR0010E": _("Error while removing storage device: %(error)s"), "KCHVMSTOR0011E": _("Do not support IDE device hot plug"), "KCHVMSTOR0012E": _("Specify type and path or type and pool/volume to add a new virtual machine disk"), "KCHVMSTOR0013E": _("Specify path to update virtual machine disk"), "KCHVMSTOR0014E": _("Controller type %(type)s limitation of %(limit)s devices reached"), "KCHVMSTOR0015E": _("Cannot retrieve disk path information for given pool/volume: %(error)s"), "KCHVMSTOR0016E": _("Volume already in use by other virtual machine."), "KCHVMSTOR0017E": _("Only one of path or pool/volume can be specified to add a new virtual machine disk"), "KCHVMSTOR0018E": _("Volume chosen with format %(format)s does not fit in the storage type %(type)s"), "KCHREPOS0001E": _("YUM Repository ID must be one word only string."), "KCHREPOS0002E": _("Repository URL must be an http://, ftp:// or file:// URL."), "KCHREPOS0003E": _("Repository configuration is a dictionary with specific values according to repository type."), "KCHREPOS0004E": _("Distribution to DEB repository must be a string"), "KCHREPOS0005E": _("Components to DEB repository must be listed in a array"), "KCHREPOS0006E": _("Components to DEB repository must be a string"), "KCHREPOS0007E": _("Mirror list to repository must be a string"), "KCHREPOS0008E": _("YUM Repository name must be string."), "KCHREPOS0009E": _("GPG check must be a boolean value."), "KCHREPOS0010E": _("GPG key must be a URL pointing to the ASCII-armored file."), "KCHREPOS0011E": _("Could not update repository %(repo_id)s."), "KCHREPOS0012E": _("Repository %(repo_id)s does not exist."), "KCHREPOS0013E": _("Specify repository base URL, mirror list or metalink in order to create or update a YUM repository."), "KCHREPOS0014E": _("Repository management tool was not recognized for your system."), "KCHREPOS0015E": _("Repository %(repo_id)s is already enabled."), "KCHREPOS0016E": _("Repository %(repo_id)s is already disabled."), "KCHREPOS0017E": _("Could not remove repository %(repo_id)s."), "KCHREPOS0018E": _("Could not write repository configuration file %(repo_file)s"), "KCHREPOS0019E": _("Specify repository distribution in order to create a DEB repository."), "KCHREPOS0020E": _("Could not enable repository %(repo_id)s."), "KCHREPOS0021E": _("Could not disable repository %(repo_id)s."), "KCHREPOS0022E": _("YUM Repository ID already exists"), "KCHREPOS0023E": _("YUM Repository name must be a string"), "KCHREPOS0024E": _("Unable to list repositories. Details: '%(err)s'"), "KCHREPOS0025E": _("Unable to retrieve repository information. Details: '%(err)s'"), "KCHREPOS0026E": _("Unable to add repository. Details: '%(err)s'"), "KCHREPOS0027E": _("Unable to remove repository. Details: '%(err)s'"), "KCHREPOS0028E": _("Configuration items: '%(items)s' are not supported by repository manager"), "KCHREPOS0029E": _("Repository metalink must be an http://, ftp:// or file:// URL."), "KCHREPOS0030E": _("Cannot specify mirrorlist and metalink at the same time."), "KCHSNAP0001E": _("Virtual machine '%(vm)s' must be stopped before creating a snapshot of it."), "KCHSNAP0002E": _("Unable to create snapshot '%(name)s' on virtual machine '%(vm)s'. Details: %(err)s"), "KCHSNAP0003E": _("Snapshot '%(name)s' does not exist on virtual machine '%(vm)s'."), "KCHSNAP0004E": _("Unable to retrieve snapshot '%(name)s' on virtual machine '%(vm)s'. Details: %(err)s"), "KCHSNAP0005E": _("Unable to list snapshots on virtual machine '%(vm)s'. Details: %(err)s"), "KCHSNAP0006E": _("Unable to delete snapshot '%(name)s' on virtual machine '%(vm)s'. Details: %(err)s"), "KCHSNAP0008E": _("Unable to retrieve current snapshot of virtual machine '%(vm)s'. Details: %(err)s"), "KCHSNAP0009E": _("Unable to revert virtual machine '%(vm)s' to snapshot '%(name)s'. Details: %(err)s"), "KCHSNAP0010E": _("Unable to create snapshot of virtual machine '%(vm)s' because it contains a disk with format '%(format)s'; only 'qcow2' is supported."), "KCHCPUINF0001E": _("The number of vCPUs is too large for this system."), "KCHCPUINF0002E": _("Invalid vCPU/topology combination."), "KCHCPUINF0003E": _("This host (or current configuration) does not allow CPU topology."), } kimchi-1.5.0/src/kimchi/imageinfo.py000066400000000000000000000042321254252253000173250ustar00rootroot00000000000000# # 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 import json import os import sys import guestfs from kimchi.exception import ImageFormatError, InvalidParameter, TimeoutExpired from kimchi.utils import run_command, kimchi_log def probe_img_info(path): cmd = ["qemu-img", "info", "--output=json", path] info = dict() try: out = run_command(cmd, 10)[0] except TimeoutExpired: kimchi_log.warning("Cannot decide format of base img %s", path) return None info = json.loads(out) info['virtual-size'] = info['virtual-size'] >> 30 info['actual-size'] = info['actual-size'] >> 30 return info def probe_image(image_path): if not os.path.isfile(image_path): raise InvalidParameter("KCHIMG0004E", {'filename': image_path}) if not os.access(image_path, os.R_OK): raise ImageFormatError("KCHIMG0003E", {'filename': image_path}) g = guestfs.GuestFS(python_return_dict=True) g.add_drive_opts(image_path, readonly=1) g.launch() try: roots = g.inspect_os() except: raise ImageFormatError("KCHIMG0001E") if len(roots) == 0: raise ImageFormatError("KCHIMG0002E") for root in roots: version = "%d.%d" % (g.inspect_get_major_version(root), g.inspect_get_minor_version(root)) distro = "%s" % (g.inspect_get_distro(root)) return (distro, version) if __name__ == '__main__': print probe_image(sys.argv[1]) kimchi-1.5.0/src/kimchi/iscsi.py000066400000000000000000000057641254252253000165140ustar00rootroot00000000000000# # 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-1301USA import subprocess from kimchi.exception import OperationFailed class TargetClient(object): def __init__(self, target, host, port=None, auth=None): self.portal = host + ("" if port is None else ":%s" % port) self.target = target self.auth = auth self.targetCmd = ['iscsiadm', '--mode', 'node', '--targetname', self.target, '--portal', self.portal] def _update_db(self, Name, Value): self._run_cmd(['--op=update', '--name', Name, '--value', Value]) def _update_auth(self): if self.auth is None: items = (('node.session.auth.authmethod', 'None'), ('node.session.auth.username', ''), ('node.session.auth.password', '')) else: items = (('node.session.auth.authmethod', 'CHAP'), ('node.session.auth.username', self.auth['username']), ('node.session.auth.password', self.auth['password'])) for name, value in items: self._update_db(name, value) def _run_cmd(self, cmd): iscsiadm = subprocess.Popen( self.targetCmd + cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = iscsiadm.communicate() if iscsiadm.returncode != 0: msg_args = {'portal': self.portal, 'err': err} raise OperationFailed("KCHISCSI0001E", msg_args) return out def _discover(self): iscsiadm = subprocess.Popen( ['iscsiadm', '--mode', 'discovery', '--type', 'sendtargets', '--portal', self.portal], stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = iscsiadm.communicate() if iscsiadm.returncode != 0: msg_args = {'portal': self.portal, 'err': err} raise OperationFailed("KCHISCSI0001E", msg_args) return out def _run_op(self, op): self._run_cmd(['--' + op]) def login(self): self._discover() self._update_auth() self._run_op('login') def logout(self): self._run_op('logout') def validate(self): try: self.login() except OperationFailed: return False self.logout() return True kimchi-1.5.0/src/kimchi/isoinfo.py000066400000000000000000000507031254252253000170410ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-2015 # # 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 import contextlib import glob import platform import os import re import stat import struct import sys import urllib2 from kimchi.exception import IsoFormatError from kimchi.utils import check_url_path, kimchi_log iso_dir = [ ## # Portions of this data from libosinfo: http://libosinfo.org/ # # Each tuple has the following three members: # Distro ID: Nickname for the distro or OS family # Distro Version: A function or string that provides a specific version # given a regular expression match on the volume id string # Regular Expression: A regex to match against the ISO Volume ID ## ('openbsd', lambda m: m.group(2), ('OpenBSD/(i386|amd64) (\d+\.\d+) Install CD')), ('centos', lambda m: m.group(1), ('CentOS_(\d+\.\d+)_Final')), ('windows', '2000', ('W2AFPP|SP1AFPP|SP2AFPP|YRMAFPP|ZRMAFPP|W2AOEM|SP1AOEM|SP2AOEM' + '|YRMAOEM|ZRMAOEM|W2ASEL|SP2ASEL|W2SFPP|SP1SFPP|SP2SFPP|YRMSFPP' + '|ZRMSFPP|W2SOEM|W2SOEM|SP1SOEM|SP2SOEM|YRMSOEM|ZRMSOEM|W2SSEL' + '|SP2SSEL|W2PFPP|SP1PFPP|SP2PFPP|YRMPFPP|ZRMPFPP|W2POEM|SP1POEM' + '|SP2POEM|YRMPOEM|ZRMPOEM|W2PSEL|SP2PSEL|W2PCCP|WIN2000|W2K_SP4')), ('windows', 'xp', ('WXPFPP|WXHFPP|WXPCCP|WXHCCP|WXPOEM|WXHOEM|WXPVOL|WXPEVL|XRMPFPP' + '|XRMHFPP|XRMPCCP|XRMHCCP|XRMPOEM|XRMHOEM|XRMPVOL|XRMSD2|X1APFPP' + '|X1AHFPP|X1APCCP|X1APCCP|X1AHCCP|X1APOEM|X1AHOEM|X1APVOL|VRMPFPP' + '|VRMHFPP|VRMPCCP|VRMHCCP|VRMPOEM|VRMHOEM|VRMPVOL|VRMSD2|VX2PFPP' + '|VX2HFPP|VX2PCCP|VX2HCCP|VX2POEM|VX2HOEM|VX2PRMFPP|VX2PVOL|GRTMUPD' + '|GRTMPFPP|GRTMPRMFPP|GRTMHFPP|GRTMHKFPP|GRTMHKNFPP|GRTMHRMFPP' + '|GRTMPOEM|GRTMHOEM|GRTMPVOL|GRTMPKNVOL|GRTMPKVOL|GRTMPRMVOL' + '|MX2PFPP|MRMSD2|ARMPXFPP|ARMPXCCP|ARMPXOEM|ARMPXVOL|AX2PXCFPP' + '|AX2PXFPP|NRMPIFPP')), ('windows', '2003', ('ARMECHK|ARMEVOL|ARMSVOL|ARMWVOL|ARMEEVL|ARMSEVL|ARMWEVL|ARMEOEM' + '|ARMDOEM|ARMSOEM|ARMWOEM|ARMEFPP|ARMDFPP|ARMSFPP|ARMWFPP|NRMECHK' + '|NRMEVOL|NRMSVOL|NRMWVOL|NRMEEVL|NRMSEVL|NRMWEVL|NRMEOEM|NRMDOEM' + '|NRMSOEM|NRMWOEM|NRMEFPP|NRMDFPP|NRMSFPP|NRMSFPP|CRMSVOL|CRMSXVOL' + '|BRMEVOL|BX2DVOL|ARMEEVL|BRMEEVL|CR0SP2|ARMEICHK|ARMEIFPP|ARMEIEVL' + '|ARMEIOEM|ARMDIOEM|ARMEXFPP|ARMDFPP|ARMSXFPP|CR0SPX2|NRMEICHK' + '|NRMEIFPP|NRMDIFPP|NRMEIOEM|NRMDIOEM|NRMEIVOL|NRMEIEVL|BRMEXVOL' + '|BX2DXVOL|ARMEIFPP|CR0SPI2')), ('windows', '2003r2', ('CRMEFPP|CRMSFPP|CR0SCD2|CR0ECD2|BX2SFPP|BX2EFPP|BRMECD2FRE' + '|BRMSCD2FRE|CRMEXFPP|CRMSXFPP|CR0SCD2X|CR0ECD2X|BX2SXFPP|BX2EXFPP' + '|BRMECD2XFRE|BRMSCD2XFRE|CRMDVOL|CRMDXVOL')), ('windows', '2008', ('KRTMSVOL|KRTMSCHK|KRMWVOL|KRMSVOL|KRTMSXVOL|KRTMSXCHK|KRMWXVOL' + '|KRMSXVOL')), ('windows', '2008r2', ('GRMSXVOL|GRMSXFRER|GRMSHXVOL|GRMSIAIVOL|SRVHPCR2')), ('windows', 'vista', ('FB1EVOL|LRMCFRE|FRTMBVOL|FRMBVOL|FRMEVOL|FB1EXVOL|LRMCXFRE' + '|FRTMBXVOL|FRMBXVOL|FRMEXVOL|LRMEVOL|LRMEXVOL')), ('windows', '7', ('GRMCULFRER|GSP1RMCNPRFRER|GSP1RMCNULFRER|GSP1RMCULFRER' + '|GSP1RMCPRFRER|GRMCENVOL|GRMCNENVOL|GRMCPRFRER|GSP1RMCPRVOL' + '|GRMCULXFRER|GSP1RMCPRXFRER|GSP1RMCNHPXFRER|GRMCHPXFRER|GRMCXCHK' + '|GSP1RMCENXVOL|GRMCENXVOL|GRMCNENXVOL|GRMCPRXFRER|GSP1RMCPRXVOL')), ('windows', '8', ('HB1_CCPA_X86FRE|HRM_CCSA_X86FRE|HRM_CCSA_X86CHK|HRM_CCSNA_X86CHK' + '|HRM_CCSNA_X86FRE|HRM_CENA_X86FREV|HRM_CENA_X86CHKV' + '|HRM_CENNA_X86FREV|HRM_CENNA_X86CHKV|HRM_CPRA_X86FREV' + '|HRM_CPRNA_X86FREV|HB1_CCPA_X64FRE|HRM_CCSA_X64FRE' + '|HRM_CCSA_X64CHK|HRM_CCSNA_X64FRE|HRM_CCSNA_X64CHK' + '|HRM_CENNA_X64FREV|HRM_CENNA_X64CHKV|HRM_CENA_X64FREV' + '|HRM_CENA_X64CHKV|HRM_CPRA_X64FREV|HRM_CPRNA_X64FREV')), ('sles', '10', 'SLES10|SUSE-Linux-Enterprise-Server.001'), ('sles', '11', 'SUSE_SLES-11-0-0'), ('sles', '12', 'SLE-12'), ('sles', lambda m: "11sp%s" % m.group(1), 'SLES-11-SP(\d+)'), ('opensuse', lambda m: m.group(1), 'openSUSE[ -](\d+\.\d+)'), ('opensuse', '11.1', 'SU1110.001'), ('opensuse', '11.3', 'openSUSE-DVD-i586-Build0702..001|openSUSE-DVD-x86_64.0702..001'), ('opensuse', '11.4', 'openSUSE-DVD-i586-Build0024|openSUSE-DVD-x86_640024'), ('opensuse', '12.1', 'openSUSE-DVD-i586-Build0039|openSUSE-DVD-x86_640039'), ('opensuse', '12.2', 'openSUSE-DVD-i586-Build0167|openSUSE-DVD-x86_640167'), ('rhel', '4.8', 'RHEL/4-U8'), ('rhel', lambda m: m.group(2), 'RHEL(-LE)?[_/-](\d+\.\d+)'), ('debian', lambda m: m.group(1), 'Debian (\d+\.\d+)'), ('ubuntu', lambda m: m.group(2), '[Uu]buntu(-Server)? (\d+\.\d+)'), ('fedora', lambda m: m.group(1), 'Fedora[ -](\d+)'), ('fedora', lambda m: m.group(1), 'Fedora.*-(\d+)-'), ('gentoo', lambda m: m.group(1), 'Gentoo Linux \w+ (\d+)'), ('powerkvm', 'live_cd', 'POWERKVM_LIVECD'), ('arch', lambda m: m.group(1), 'ARCH_(\d+)'), ] class IsoImage(object): """ Scan an iso9660 image to extract the Volume ID and check for boot-ability ISO-9660 specification: http://www.ecma-international.org/publications/standards/Ecma-119.htm El-Torito specification: http://download.intel.com/support/motherboards/desktop/sb/specscdrom.pdf """ SECTOR_SIZE = 2048 VOL_DESC = struct.Struct("=B5sBB32s32s") EL_TORITO_BOOT_RECORD = struct.Struct("=B5sB32s32sI") EL_TORITO_VALIDATION_ENTRY = struct.Struct("=BBH24sHBB") EL_TORITO_BOOT_ENTRY = struct.Struct("=BBHBBHL20x") # Path table info starting in ISO9660 offset 132. We force little # endian byte order (the '<' sign) because Power systems can run on # both. # First int is path table size, next 4 bytes are discarded (it is # the same info but in big endian) and next int is the location. PATH_TABLE_SIZE_LOC = struct.Struct(" path_size: # Didn't find the '/ppc' directory. ISO is not bootable. self.bootable = False return # Get the 'ppc' directory record using 'dir_loc'. ppc_dir_offset = dir_loc * IsoImage.SECTOR_SIZE # We need to find the sector size of this dir entry. The # size of the File Section is located 10 bytes after # the dir location. DIR_SIZE_FMT = struct.Struct("<10sI") data = self._get_iso_data(ppc_dir_offset, DIR_SIZE_FMT.size) unused, dir_size = self._unpack(DIR_SIZE_FMT, data) # If the dir is in the middle of a sector, the sector is # padded zero and won't be utilized. We need to round up # the result dir_sectorsize = dir_size / IsoImage.SECTOR_SIZE if dir_size % IsoImage.SECTOR_SIZE: dir_sectorsize += 1 # Fixed-size directory record fields: # - length of directory record (1 byte) # - extended attr. record length (1 byte) # - location of extend in both-endian format (8 bytes) # - data length (size of extend) in both-endian (8 bytes) # - recording date and time (7 bytes) # - file flags (1 byte) # - file unit size interleaved (1 byte) # - interleave gap size (1 byte) # - volume sequence number (4 bytes) # - length of file identifier (1 byte) # # Of all these fields, we will use only 3 of them, 'ignoring' # 30 bytes total. STATIC_DIR_RECORD_FMT = struct.Struct(" %(name)s 262144 hvm """ lock = threading.Lock() user = None @classmethod def probe_user(cls): with cls.lock: if cls.user: return cls.user arch = 'ppc64' if platform.machine() == 'ppc64le' \ else platform.machine() xml = cls.SIMPLE_VM_XML % {'name': KVMUSERTEST_VM_NAME, 'arch': arch} with RollbackContext() as rollback: with cls.lock: conn = libvirt.open(None) rollback.prependDefer(conn.close) f = libvirt.VIR_DOMAIN_START_AUTODESTROY dom = conn.createXML(xml, flags=f) rollback.prependDefer(dom.destroy) filename = '/var/run/libvirt/qemu/%s.pid' % KVMUSERTEST_VM_NAME with open(filename) as f: pidStr = f.read() p = psutil.Process(int(pidStr)) # bug fix #357 # in psutil 2.0 and above versions, username will be a method, # not a string if callable(p.username): cls.user = p.username() else: cls.user = p.username return cls.user if __name__ == '__main__': ut = UserTests() print ut.probe_user() kimchi-1.5.0/src/kimchi/mockmodel.py000066400000000000000000000605241254252253000173470ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-2015 # # 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 import libvirt import lxml.etree as ET import os import random import time import kimchi.model.cpuinfo from lxml import objectify from lxml.builder import E from kimchi import config from kimchi import imageinfo from kimchi import osinfo from kimchi.exception import NotFoundError, OperationFailed from kimchi.model.debugreports import DebugReportsModel from kimchi.model.host import DeviceModel from kimchi.model.libvirtstoragepool import IscsiPoolDef, NetfsPoolDef from kimchi.model.libvirtstoragepool import StoragePoolDef from kimchi.model.model import Model from kimchi.model.storagepools import StoragePoolModel from kimchi.model.storagevolumes import StorageVolumeModel, StorageVolumesModel from kimchi.model.templates import LibvirtVMTemplate from kimchi.model.users import PAMUsersModel from kimchi.model.groups import PAMGroupsModel from kimchi.objectstore import ObjectStore from kimchi.utils import add_task, get_next_clone_name, kimchi_log from kimchi.vmtemplate import VMTemplate from kimchi.xmlutils.utils import xml_item_update fake_user = {'root': 'letmein!'} mockmodel_defaults = {'storagepool': '/storagepools/default-pool', 'domain': 'test', 'arch': 'i686'} class MockModel(Model): _mock_vms = {} _mock_snapshots = {} _XMLDesc = libvirt.virDomain.XMLDesc _defineXML = libvirt.virConnect.defineXML _undefineDomain = libvirt.virDomain.undefine _libvirt_get_vol_path = LibvirtVMTemplate._get_volume_path def __init__(self, objstore_loc=None): # Override osinfo.defaults to ajust the values according to # test:///default driver defaults = dict(osinfo.defaults) defaults.update(mockmodel_defaults) osinfo.defaults = dict(defaults) self._mock_devices = MockDevices() self._mock_partitions = MockPartitions() self._mock_storagevolumes = MockStorageVolumes() self._mock_swupdate = MockSoftwareUpdate() self._mock_repositories = MockRepositories() kimchi.model.cpuinfo.get_topo_capabilities = \ MockModel.get_topo_capabilities libvirt.virConnect.defineXML = MockModel.domainDefineXML libvirt.virDomain.XMLDesc = MockModel.domainXMLDesc libvirt.virDomain.undefine = MockModel.undefineDomain libvirt.virDomain.attachDeviceFlags = MockModel.attachDeviceFlags libvirt.virDomain.detachDeviceFlags = MockModel.detachDeviceFlags libvirt.virDomain.updateDeviceFlags = MockModel.updateDeviceFlags libvirt.virStorageVol.resize = MockModel.volResize libvirt.virStorageVol.wipePattern = MockModel.volWipePattern IscsiPoolDef.prepare = NetfsPoolDef.prepare = StoragePoolDef.prepare PAMUsersModel.auth_type = 'fake' PAMGroupsModel.auth_type = 'fake' super(MockModel, self).__init__('test:///default', objstore_loc) self.objstore_loc = objstore_loc self.objstore = ObjectStore(objstore_loc) # The MockModel methods are instantiated on runtime according to Model # and BaseModel # Because that a normal method override will not work here # Instead of that we also need to do the override on runtime for method in dir(self): if method.startswith('_mock_'): mock_method = getattr(self, method) if not callable(mock_method): continue m = method[6:] model_method = getattr(self, m) setattr(self, '_model_' + m, model_method) setattr(self, m, mock_method) DeviceModel.lookup = self._mock_device_lookup StoragePoolModel._update_lvm_disks = self._update_lvm_disks StorageVolumesModel.get_list = self._mock_storagevolumes_get_list StorageVolumeModel.doUpload = self._mock_storagevolume_doUpload DebugReportsModel._gen_debugreport_file = self._gen_debugreport_file LibvirtVMTemplate._get_volume_path = self._get_volume_path VMTemplate.get_iso_info = self._probe_image imageinfo.probe_image = self._probe_image def reset(self): MockModel._mock_vms = {} MockModel._mock_snapshots = {} self._mock_swupdate = MockSoftwareUpdate() self._mock_repositories = MockRepositories() if hasattr(self, 'objstore'): self.objstore = ObjectStore(self.objstore_loc) params = {'vms': [u'test'], 'templates': [], 'networks': [u'default'], 'storagepools': [u'default-pool']} for res, items in params.iteritems(): resources = getattr(self, '%s_get_list' % res)() for i in resources: if i in items: continue try: getattr(self, '%s_deactivate' % res[:-1])(i) except: pass getattr(self, '%s_delete' % res[:-1])(i) volumes = self.storagevolumes_get_list('default-pool') for v in volumes: self.storagevolume_delete('default-pool', v) @staticmethod def get_topo_capabilities(conn): # The libvirt test driver doesn't return topology. xml = "" return ET.fromstring(xml) @staticmethod def domainDefineXML(conn, xml): name = objectify.fromstring(xml).name.text try: dom = conn.lookupByName(name) if not dom.isActive(): MockModel._mock_vms[name] = xml except: pass return MockModel._defineXML(conn, xml) @staticmethod def domainXMLDesc(dom, flags=0): return MockModel._mock_vms.get(dom.name(), MockModel._XMLDesc(dom, flags)) @staticmethod def undefineDomain(dom): name = dom.name() if name in MockModel._mock_vms.keys(): del MockModel._mock_vms[dom.name()] return MockModel._undefineDomain(dom) @staticmethod def attachDeviceFlags(dom, xml, flags=0): old_xml = dom.XMLDesc(libvirt.VIR_DOMAIN_XML_SECURE) root = objectify.fromstring(old_xml) dev = objectify.fromstring(xml) root.devices.append(dev) MockModel._mock_vms[dom.name()] = ET.tostring(root, encoding="utf-8") @staticmethod def _get_device_node(dom, xml): xpath_map = {'disk': 'target', 'interface': 'mac', 'graphics': 'listen'} dev = objectify.fromstring(xml) dev_id = dev.find(xpath_map[dev.tag]).items() dev_filter = '' for key, value in dev_id: dev_filter += "[@%s='%s']" % (key, value) old_xml = dom.XMLDesc(libvirt.VIR_DOMAIN_XML_SECURE) root = objectify.fromstring(old_xml) devices = root.devices dev = devices.find("./%s/%s%s/.." % (dev.tag, xpath_map[dev.tag], dev_filter)) return (root, dev) @staticmethod def detachDeviceFlags(dom, xml, flags=0): root, dev = MockModel._get_device_node(dom, xml) root.devices.remove(dev) MockModel._mock_vms[dom.name()] = ET.tostring(root, encoding="utf-8") @staticmethod def updateDeviceFlags(dom, xml, flags=0): root, old_dev = MockModel._get_device_node(dom, xml) root.devices.replace(old_dev, objectify.fromstring(xml)) MockModel._mock_vms[dom.name()] = ET.tostring(root, encoding="utf-8") @staticmethod def volResize(vol, size, flags=0): new_xml = xml_item_update(vol.XMLDesc(0), './capacity', str(size)) vol.delete(0) pool = vol.storagePoolLookupByVolume() pool.createXML(new_xml) @staticmethod def volWipePattern(vol, algorithm, flags=0): new_xml = xml_item_update(vol.XMLDesc(0), './allocation', '0') vol.delete(0) pool = vol.storagePoolLookupByVolume() pool.createXML(new_xml) def _probe_image(self, path): return ('unknown', 'unknown') def _get_volume_path(self, pool, vol): pool_info = self.storagepool_lookup(pool) if pool_info['type'] == 'scsi': return self._mock_storagevolumes.scsi_volumes[vol]['path'] return MockModel._libvirt_get_vol_path(pool, vol) def _gen_debugreport_file(self, name): return add_task('/debugreports/%s' % name, self._create_log, self.objstore, name) def _create_log(self, cb, name): path = config.get_debugreports_path() tmpf = os.path.join(path, name + '.tmp') realf = os.path.join(path, name + '.txt') length = random.randint(1000, 10000) with open(tmpf, 'w') as fd: while length: fd.write('I am logged') length = length - 1 os.rename(tmpf, realf) cb("OK", True) def _update_lvm_disks(self, pool_name, disks): conn = self.conn.get() pool = conn.storagePoolLookupByName(pool_name.encode('utf-8')) xml = pool.XMLDesc(0) root = ET.fromstring(xml) source = root.xpath('./source')[0] for d in disks: dev = E.device(path=d) source.append(dev) conn.storagePoolDefineXML(ET.tostring(root), 0) def _mock_host_shutdown(self, *name): kimchi_log.info("The host system will be shutted down") def _mock_host_reboot(self, *name): kimchi_log.info("The host system will be rebooted") def _mock_storagevolumes_create(self, pool, params): vol_source = ['url', 'capacity'] index_list = list(i for i in range(len(vol_source)) if vol_source[i] in params) create_param = vol_source[index_list[0]] name = params.get('name') if name is None and create_param == 'url': params['name'] = os.path.basename(params['url']) del params['url'] params['capacity'] = 1024 return self._model_storagevolumes_create(pool, params) def _mock_storagevolumes_get_list(self, pool): pool_info = self.storagepool_lookup(pool) if pool_info['type'] == 'scsi': return self._mock_storagevolumes.scsi_volumes.keys() return self._model_storagevolumes_get_list(pool) def _mock_storagevolume_lookup(self, pool, vol): pool_info = self.storagepool_lookup(pool) if pool_info['type'] == 'scsi': return self._mock_storagevolumes.scsi_volumes[vol] return self._model_storagevolume_lookup(pool, vol) def _mock_storagevolume_doUpload(self, cb, vol, offset, data, data_size): vol_path = vol.path() # MockModel does not create the storage volume as a file # So create it to do the file upload if offset == 0: dirname = os.path.dirname(vol_path) if not os.path.exists(dirname): os.makedirs(dirname) open(vol_path, 'w').close() try: with open(vol_path, 'a') as fd: fd.seek(offset) fd.write(data) except Exception, e: os.remove(vol_path) cb('', False) raise OperationFailed("KCHVOL0029E", {"err": e.message}) def _mock_partitions_get_list(self): return self._mock_partitions.partitions.keys() def _mock_partition_lookup(self, name): return self._mock_partitions.partitions[name] def _mock_devices_get_list(self, _cap=None, _passthrough=None, _passthrough_affected_by=None): if _cap is None: return self._mock_devices.devices.keys() if _cap == 'fc_host': _cap = 'scsi_host' return [dev['name'] for dev in self._mock_devices.devices.values() if dev['device_type'] == _cap] def _mock_device_lookup(self, dev_name): return self._mock_devices.devices[dev_name] def _mock_packagesupdate_get_list(self): return self._mock_swupdate.pkgs.keys() def _mock_packageupdate_lookup(self, pkg_name): return self._mock_swupdate.pkgs[pkg_name] def _mock_host_swupdate(self, args=None): task_id = add_task('/host/swupdate', self._mock_swupdate.doUpdate, self.objstore) return self.task_lookup(task_id) def _mock_repositories_get_list(self): return self._mock_repositories.repos.keys() def _mock_repositories_create(self, params): # Create a repo_id if not given by user. The repo_id will follow # the format kimchi_repo_, where integer is the number of # seconds since the Epoch (January 1st, 1970), in UTC. repo_id = params.get('repo_id', None) if repo_id is None: repo_id = "kimchi_repo_%s" % str(int(time.time() * 1000)) params.update({'repo_id': repo_id}) config = params.get('config', {}) info = {'repo_id': repo_id, 'baseurl': params['baseurl'], 'enabled': True, 'config': {'repo_name': config.get('repo_name', repo_id), 'gpgkey': config.get('gpgkey', []), 'gpgcheck': True, 'mirrorlist': params.get('mirrorlist', '')}} self._mock_repositories.repos[repo_id] = info return repo_id def _mock_repository_lookup(self, repo_id): return self._mock_repositories.repos[repo_id] def _mock_repository_delete(self, repo_id): del self._mock_repositories.repos[repo_id] def _mock_repository_enable(self, repo_id): self._mock_repositories.repos[repo_id]['enabled'] = True def _mock_repository_disable(self, repo_id): self._mock_repositories.repos[repo_id]['enabled'] = False def _mock_repository_update(self, repo_id, params): self._mock_repositories.repos[repo_id].update(params) return repo_id def _mock_vm_clone(self, name): new_name = get_next_clone_name(self.vms_get_list(), name) snapshots = MockModel._mock_snapshots.get(name, []) MockModel._mock_snapshots[new_name] = snapshots return self._model_vm_clone(name) def _mock_vmsnapshots_create(self, vm_name, params): name = params.get('name', unicode(int(time.time()))) params = {'vm_name': vm_name, 'name': name} taskid = add_task(u'/vms/%s/snapshots/%s' % (vm_name, name), self._vmsnapshots_create_task, self.objstore, params) return self.task_lookup(taskid) def _vmsnapshots_create_task(self, cb, params): vm_name = params['vm_name'] name = params['name'] parent = u'' snapshots = MockModel._mock_snapshots.get(vm_name, []) for sn in snapshots: if sn.current: sn.current = False parent = sn.name snapshots.append(MockVMSnapshot(name, {'parent': parent})) MockModel._mock_snapshots[vm_name] = snapshots cb('OK', True) def _mock_vmsnapshots_get_list(self, vm_name): snapshots = MockModel._mock_snapshots.get(vm_name, []) return sorted([snap.name for snap in snapshots]) def _mock_currentvmsnapshot_lookup(self, vm_name): for sn in MockModel._mock_snapshots.get(vm_name, []): if sn.current: return sn.info def _mock_vmsnapshot_lookup(self, vm_name, name): for sn in MockModel._mock_snapshots.get(vm_name, []): if sn.name == name: return sn.info raise NotFoundError('KCHSNAP0003E', {'name': name, 'vm': vm_name}) def _mock_vmsnapshot_delete(self, vm_name, name): snapshots = MockModel._mock_snapshots.get(vm_name, []) for sn in snapshots: if sn.name == name: del snapshots[snapshots.index(sn)] MockModel._mock_snapshots[vm_name] = snapshots def _mock_vmsnapshot_revert(self, vm_name, name): snapshots = MockModel._mock_snapshots.get(vm_name, []) for sn in snapshots: if sn.current: sn.current = False for sn in snapshots: if sn.name == name: sn.current = True class MockStorageVolumes(object): def __init__(self): base_path = "/dev/disk/by-path/pci-0000:0e:00.0-fc-0x20-lun" self.scsi_volumes = {'unit:0:0:1': {'capacity': 1024, 'format': 'unknown', 'allocation': 512, 'type': 'block', 'path': base_path + '1', 'used_by': []}, 'unit:0:0:2': {'capacity': 2048, 'format': 'unknown', 'allocation': 512, 'type': 'block', 'path': base_path + '2', 'used_by': []}} class MockPartitions(object): def __init__(self): self.partitions = {"vdx": {"available": True, "name": "vdx", "fstype": "", "path": "/dev/vdx", "mountpoint": "", "type": "disk", "size": "2147483648"}, "vdz": {"available": True, "name": "vdz", "fstype": "", "path": "/dev/vdz", "mountpoint": "", "type": "disk", "size": "2147483648"}} class MockDevices(object): def __init__(self): self.devices = { 'computer': {'device_type': 'system', 'firmware': {'release_date': '01/01/2012', 'vendor': 'LENOVO', 'version': 'XXXXX (X.XX )'}, 'hardware': {'serial': 'PXXXXX', 'uuid': '9d660370-820f-4241-8731-5a60c97e8aa6', 'vendor': 'LENOVO', 'version': 'ThinkPad T420'}, 'name': 'computer', 'parent': None, 'product': '4180XXX'}, 'pci_0000_03_00_0': {'bus': 3, 'device_type': 'pci', 'domain': 0, 'driver': {'name': 'iwlwifi'}, 'function': 0, 'iommuGroup': 7, 'name': 'pci_0000_03_00_0', 'parent': 'computer', 'path': '/sys/devices/pci0000:00/0000:03:00.0', 'product': { 'description': 'Centrino Advanced-N 6205 [Taylor Peak]', 'id': '0x0085'}, 'slot': 0, 'vendor': {'description': 'Intel Corporation', 'id': '0x8086'}}, 'pci_0000_0d_00_0': {'bus': 13, 'device_type': 'pci', 'domain': 0, 'driver': {'name': 'sdhci-pci'}, 'function': 0, 'iommuGroup': 7, 'name': 'pci_0000_0d_00_0', 'parent': 'computer', 'path': '/sys/devices/pci0000:00/0000:0d:00.0', 'product': {'description': 'PCIe SDXC/MMC Host Controller', 'id': '0xe823'}, 'slot': 0, 'vendor': {'description': 'Ricoh Co Ltd', 'id': '0x1180'}}, 'scsi_host0': {'adapter': {'fabric_wwn': '37df6c1efa1b4388', 'type': 'fc_host', 'wwnn': 'efb6563f06434a98', 'wwpn': '742f32073aab45d7'}, 'device_type': 'scsi_host', 'host': 0, 'name': 'scsi_host0', 'parent': 'computer', 'path': '/sys/devices/pci0000:00/0000:40:00.0/0'}, 'scsi_host1': {'adapter': {'fabric_wwn': '542efa5dced34123', 'type': 'fc_host', 'wwnn': 'b7433a40c9b84092', 'wwpn': '25c1f485ae42497f'}, 'device_type': 'scsi_host', 'host': 0, 'name': 'scsi_host1', 'parent': 'computer', 'path': '/sys/devices/pci0000:00/0000:40:00.0/1'}, 'scsi_host2': {'adapter': {'fabric_wwn': '5c373c334c20478d', 'type': 'fc_host', 'wwnn': 'f2030bec4a254e6b', 'wwpn': '07dbca4164d44096'}, 'device_type': 'scsi_host', 'host': 0, 'name': 'scsi_host2', 'parent': 'computer', 'path': '/sys/devices/pci0000:00/0000:40:00.0/2'}} class MockSoftwareUpdate(object): def __init__(self): self.pkgs = { 'udevmountd': {'repository': 'openSUSE-13.1-Update', 'version': '0.81.5-14.1', 'arch': 'x86_64', 'package_name': 'udevmountd'}, 'sysconfig-network': {'repository': 'openSUSE-13.1-Extras', 'version': '0.81.5-14.1', 'arch': 'x86_64', 'package_name': 'sysconfig-network'}, 'libzypp': {'repository': 'openSUSE-13.1-Update', 'version': '13.9.0-10.1', 'arch': 'noarch', 'package_name': 'libzypp'}} self._num2update = 3 def doUpdate(self, cb, params): msgs = [] for pkg in self.pkgs.keys(): msgs.append("Updating package %s" % pkg) cb('\n'.join(msgs)) time.sleep(1) time.sleep(2) msgs.append("All packages updated") cb('\n'.join(msgs), True) # After updating all packages any package should be listed to be # updated, so reset self._packages self.pkgs = {} class MockRepositories(object): def __init__(self): self.repos = {"kimchi_repo_1392167832": {"repo_id": "kimchi_repo_1392167832", "enabled": True, "baseurl": "http://www.fedora.org", "config": {"repo_name": "kimchi_repo_1392167832", "gpgkey": [], "gpgcheck": True, "mirrorlist": ""}}} class MockVMSnapshot(object): def __init__(self, name, params={}): self.name = name self.current = True self.info = {'created': params.get('created', unicode(int(time.time()))), 'name': name, 'parent': params.get('parent', u''), 'state': params.get('state', u'shutoff')} kimchi-1.5.0/src/kimchi/model/000077500000000000000000000000001254252253000161145ustar00rootroot00000000000000kimchi-1.5.0/src/kimchi/model/Makefile.am000066400000000000000000000015641254252253000201560ustar00rootroot00000000000000# # Kimchi # # Copyright IBM Corp, 2013 # # 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 model_PYTHON = *.py modeldir = $(pythondir)/kimchi/model install-data-local: $(MKDIR_P) $(DESTDIR)$(modeldir) kimchi-1.5.0/src/kimchi/model/__init__.py000066400000000000000000000014121254252253000202230ustar00rootroot00000000000000# # 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 kimchi-1.5.0/src/kimchi/model/config.py000066400000000000000000000142741254252253000177430ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2014-2015 # # 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 from multiprocessing.pool import ThreadPool import cherrypy from kimchi.basemodel import Singleton from kimchi.config import config as kconfig from kimchi.config import find_qemu_binary, get_version from kimchi.distroloader import DistroLoader from kimchi.exception import NotFoundError from kimchi.model.debugreports import DebugReportsModel from kimchi.model.featuretests import FeatureTests, FEATURETEST_POOL_NAME from kimchi.model.featuretests import FEATURETEST_VM_NAME from kimchi.repositories import Repositories from kimchi.screenshot import VMScreenshot from kimchi.swupdate import SoftwareUpdate from kimchi.utils import check_url_path, kimchi_log, run_command class ConfigModel(object): def __init__(self, **kargs): pass def lookup(self, name): proxy_port = kconfig.get('display', 'display_proxy_port') return {'display_proxy_port': proxy_port, 'version': get_version()} class CapabilitiesModel(object): __metaclass__ = Singleton def __init__(self, **kargs): self.conn = kargs['conn'] self.qemu_stream = False self.libvirt_stream_protocols = [] self.fc_host_support = False self.metadata_support = False self.kernel_vfio = False self.mem_hotplug_support = False # Subscribe function to set host capabilities to be run when cherrypy # server is up # It is needed because some features tests depends on the server cherrypy.engine.subscribe('start', self._set_capabilities) # Subscribe function to clean any Kimchi leftovers cherrypy.engine.subscribe('stop', self._clean_leftovers) def _clean_leftovers(self): conn = self.conn.get() FeatureTests.disable_libvirt_error_logging() try: dom = conn.lookupByName(FEATURETEST_VM_NAME) dom.undefine() except Exception: # Any exception can be ignored here pass try: pool = conn.storagePoolLookupByName(FEATURETEST_POOL_NAME) pool.undefine() except Exception: # Any exception can be ignored here pass FeatureTests.enable_libvirt_error_logging() def _set_capabilities(self): kimchi_log.info("*** Running feature tests ***") conn = self.conn.get() self.qemu_stream = FeatureTests.qemu_supports_iso_stream() self.nfs_target_probe = FeatureTests.libvirt_support_nfs_probe(conn) self.fc_host_support = FeatureTests.libvirt_support_fc_host(conn) self.metadata_support = FeatureTests.has_metadata_support(conn) self.kernel_vfio = FeatureTests.kernel_support_vfio() self.mem_hotplug_support = FeatureTests.has_mem_hotplug_support(conn) self.libvirt_stream_protocols = [] for p in ['http', 'https', 'ftp', 'ftps', 'tftp']: if FeatureTests.libvirt_supports_iso_stream(conn, p): self.libvirt_stream_protocols.append(p) kimchi_log.info("*** Feature tests completed ***") _set_capabilities.priority = 90 def _qemu_support_spice(self): qemu_path = find_qemu_binary(find_emulator=True) out, err, rc = run_command(['ldd', qemu_path]) if rc != 0: kimchi_log.error('Failed to find qemu binary dependencies: %s', err) return False for line in out.split('\n'): if line.lstrip().startswith('libspice-server.so'): return True return False def lookup(self, *ident): report_tool = DebugReportsModel.get_system_report_tool() try: SoftwareUpdate() except Exception: update_tool = False else: update_tool = True try: repo = Repositories() except Exception: repo_mngt_tool = None else: repo_mngt_tool = repo._pkg_mnger.TYPE return {'libvirt_stream_protocols': self.libvirt_stream_protocols, 'qemu_spice': self._qemu_support_spice(), 'qemu_stream': self.qemu_stream, 'screenshot': VMScreenshot.get_stream_test_result(), 'system_report_tool': bool(report_tool), 'update_tool': update_tool, 'repo_mngt_tool': repo_mngt_tool, 'federation': kconfig.get("server", "federation"), 'auth': kconfig.get("authentication", "method"), 'kernel_vfio': self.kernel_vfio, 'nm_running': FeatureTests.is_nm_running(), 'mem_hotplug_support': self.mem_hotplug_support } class DistrosModel(object): def __init__(self, **kargs): distroloader = DistroLoader() self.distros = distroloader.get() def get_list(self): def validate_distro(distro): if check_url_path(distro['path']): return distro['name'] n_processes = len(self.distros.keys()) pool = ThreadPool(processes=n_processes) map_res = pool.map_async(validate_distro, self.distros.values()) pool.close() pool.join() res = list(set(map_res.get()) - set([None])) return sorted(res) class DistroModel(object): def __init__(self, **kargs): self._distros = DistrosModel() def lookup(self, name): try: return self._distros.distros[name] except KeyError: raise NotFoundError("KCHDISTRO0001E", {'name': name}) kimchi-1.5.0/src/kimchi/model/cpuinfo.py000066400000000000000000000114361254252253000201360ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2014-2015 # # 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 import platform from xml.etree import ElementTree as ET from kimchi.exception import InvalidParameter, InvalidOperation from kimchi.utils import kimchi_log, run_command ARCH = 'power' if platform.machine().startswith('ppc') else 'x86' def get_topo_capabilities(connect): """ This helper function exists solely to be overridden for mockmodel tests. Since other modules use getCapabilies(), it can't be overridden directly. """ xml = connect.getCapabilities() capabilities = ET.fromstring(xml) return capabilities.find('host').find('cpu').find('topology') class CPUInfoModel(object): """ Get information about a CPU for hyperthreading (on x86) or SMT (on POWER) for logic when creating templates and VMs. """ def __init__(self, **kargs): self.guest_threads_enabled = False self.sockets = 0 self.cores_present = 0 self.cores_available = 0 self.cores_per_socket = 0 self.threads_per_core = 0 self.max_threads = 0 self.conn = kargs['conn'] libvirt_topology = None try: connect = self.conn.get() libvirt_topology = get_topo_capabilities(connect) except Exception as e: kimchi_log.info("Unable to get CPU topology capabilities: %s" % e.message) return if libvirt_topology is None: kimchi_log.info("cpu_info topology not supported.") return if ARCH == 'power': # IBM PowerPC self.guest_threads_enabled = True out, error, rc = run_command(['ppc64_cpu', '--smt']) if rc or 'on' in out: # SMT has to be disabled for guest to use threads as CPUs. # rc is always zero, whether SMT is off or on. self.guest_threads_enabled = False out, error, rc = run_command(['ppc64_cpu', '--cores-present']) if not rc: self.cores_present = int(out.split()[-1]) out, error, rc = run_command(['ppc64_cpu', '--cores-on']) if not rc: self.cores_available = int(out.split()[-1]) out, error, rc = run_command(['ppc64_cpu', '--threads-per-core']) if not rc: self.threads_per_core = int(out.split()[-1]) self.sockets = self.cores_present/self.threads_per_core if self.sockets == 0: self.sockets = 1 self.cores_per_socket = self.cores_present/self.sockets else: # Intel or AMD self.guest_threads_enabled = True self.sockets = int(libvirt_topology.get('sockets')) self.cores_per_socket = int(libvirt_topology.get('cores')) self.cores_present = self.cores_per_socket * self.sockets self.cores_available = self.cores_present self.threads_per_core = int(libvirt_topology.get('threads')) def lookup(self, ident): return { 'guest_threads_enabled': self.guest_threads_enabled, 'sockets': self.sockets, 'cores_per_socket': self.cores_per_socket, 'cores_present': self.cores_present, 'cores_available': self.cores_available, 'threads_per_core': self.threads_per_core, } def check_topology(self, vcpus, topology): """ param vcpus: should be an integer param iso_path: the path of the guest ISO param topology: {'sockets': x, 'cores': x, 'threads': x} """ sockets = topology['sockets'] cores = topology['cores'] threads = topology['threads'] if not self.guest_threads_enabled: raise InvalidOperation("KCHCPUINF0003E") if vcpus != sockets * cores * threads: raise InvalidParameter("KCHCPUINF0002E") if vcpus > self.cores_available * self.threads_per_core: raise InvalidParameter("KCHCPUINF0001E") if threads > self.threads_per_core: raise InvalidParameter("KCHCPUINF0002E") kimchi-1.5.0/src/kimchi/model/debugreports.py000066400000000000000000000172611254252253000212020ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2014-2015 # # 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 import fnmatch import glob import logging import os import shutil import subprocess import time from kimchi import config from kimchi.exception import InvalidParameter, KimchiException, NotFoundError from kimchi.exception import OperationFailed from kimchi.model.tasks import TaskModel from kimchi.utils import add_task, kimchi_log from kimchi.utils import run_command class DebugReportsModel(object): def __init__(self, **kargs): self.objstore = kargs['objstore'] self.task = TaskModel(**kargs) def create(self, params): ident = params.get('name').strip() # Generate a name with time and millisec precision, if necessary if ident is None or ident == "": ident = 'report-' + str(int(time.time() * 1000)) else: if ident in self.get_list(): raise InvalidParameter("KCHDR0008E", {"name": ident}) taskid = self._gen_debugreport_file(ident) return self.task.lookup(taskid) def get_list(self): path = config.get_debugreports_path() file_pattern = os.path.join(path, '*.*') file_lists = glob.glob(file_pattern) file_lists = [os.path.split(file)[1] for file in file_lists] name_lists = [file.split('.', 1)[0] for file in file_lists] return name_lists def _gen_debugreport_file(self, name): gen_cmd = self.get_system_report_tool() if gen_cmd is not None: return add_task('/debugreports/%s' % name, gen_cmd, self.objstore, name) raise OperationFailed("KCHDR0002E") @staticmethod def sosreport_generate(cb, name): def log_error(e): log = logging.getLogger('Model') log.warning('Exception in generating debug file: %s', e) try: command = ['sosreport', '--batch', '--name=%s' % name] output, error, retcode = run_command(command) if retcode != 0: raise OperationFailed("KCHDR0003E", {'name': name, 'err': retcode}) # SOSREPORT might create file in /tmp or /var/tmp # FIXME: The right way should be passing the tar.xz file directory # though the parameter '--tmp-dir', but it is failing in Fedora 20 patterns = ['/tmp/sosreport-%s-*', '/var/tmp/sosreport-%s-*'] reports = [] reportFile = None for p in patterns: reports = reports + [f for f in glob.glob(p % name)] for f in reports: if not fnmatch.fnmatch(f, '*.md5'): reportFile = f break # Some error in sosreport happened if reportFile is None: kimchi_log.error('Debug report file not found. See sosreport ' 'output for detail:\n%s', output) fname = (patterns[0] % name).split('/')[-1] raise OperationFailed('KCHDR0004E', {'name': fname}) md5_report_file = reportFile + '.md5' report_file_extension = '.' + reportFile.split('.', 1)[1] path = config.get_debugreports_path() target = os.path.join(path, name + report_file_extension) # Moving report msg = 'Moving debug report file "%s" to "%s"' % (reportFile, target) kimchi_log.info(msg) shutil.move(reportFile, target) # Deleting md5 msg = 'Deleting report md5 file: "%s"' % (md5_report_file) kimchi_log.info(msg) with open(md5_report_file) as f: md5 = f.read().strip() kimchi_log.info('Md5 file content: "%s"', md5) os.remove(md5_report_file) cb('OK', True) return except KimchiException as e: log_error(e) raise except OSError as e: log_error(e) raise except Exception, e: # No need to call cb to update the task status here. # The task object will catch the exception raised here # and update the task status there log_error(e) raise OperationFailed("KCHDR0005E", {'name': name, 'err': e}) @staticmethod def get_system_report_tool(): # Please add new possible debug report command here # and implement the report generating function # based on the new report command report_tools = ({'cmd': 'sosreport --help', 'fn': DebugReportsModel.sosreport_generate},) # check if the command can be found by shell one by one for helper_tool in report_tools: try: retcode = subprocess.call(helper_tool['cmd'], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) if retcode == 0: return helper_tool['fn'] except Exception, e: kimchi_log.info('Exception running command: %s', e) return None class DebugReportModel(object): def __init__(self, **kargs): pass def lookup(self, name): path = config.get_debugreports_path() file_pattern = os.path.join(path, name) file_pattern = file_pattern + '.*' try: file_target = glob.glob(file_pattern)[0] except IndexError: raise NotFoundError("KCHDR0001E", {'name': name}) ctime = os.stat(file_target).st_mtime ctime = time.strftime("%Y-%m-%d-%H:%M:%S", time.localtime(ctime)) file_target = os.path.split(file_target)[-1] file_target = os.path.join("/data/debugreports", file_target) return {'uri': file_target, 'ctime': ctime} def update(self, name, params): path = config.get_debugreports_path() file_pattern = os.path.join(path, name + '.*') try: file_source = glob.glob(file_pattern)[0] except IndexError: raise NotFoundError("KCHDR0001E", {'name': name}) file_target = file_source.replace(name, params['name']) if os.path.isfile(file_target): raise InvalidParameter('KCHDR0008E', {'name': params['name']}) shutil.move(file_source, file_target) kimchi_log.info('%s renamed to %s' % (file_source, file_target)) return params['name'] def delete(self, name): path = config.get_debugreports_path() file_pattern = os.path.join(path, name + '.*') try: file_target = glob.glob(file_pattern)[0] except IndexError: raise NotFoundError("KCHDR0001E", {'name': name}) os.remove(file_target) class DebugReportContentModel(object): def __init__(self, **kargs): self._debugreport = DebugReportModel() def lookup(self, name): return self._debugreport.lookup(name) kimchi-1.5.0/src/kimchi/model/diskutils.py000066400000000000000000000061651254252253000205110ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2014-2015 # # 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 from kimchi.exception import OperationFailed, NotFoundError from kimchi.model.vms import VMModel, VMsModel from kimchi.utils import kimchi_log from kimchi.xmlutils.disk import get_vm_disk_info, get_vm_disks """ Functions that multiple storage-related models (e.g. VMStoragesModel, VolumesModel) will need. """ def get_disk_used_by(objstore, conn, path): try: with objstore as session: try: used_by = session.get('storagevolume', path)['used_by'] except (KeyError, NotFoundError): kimchi_log.info('Volume %s not found in obj store.' % path) used_by = [] # try to find this volume in existing vm vms_list = VMsModel.get_vms(conn) for vm in vms_list: dom = VMModel.get_vm(vm, conn) storages = get_vm_disks(dom) for disk in storages.keys(): d_info = get_vm_disk_info(dom, disk) if path == d_info['path']: used_by.append(vm) try: session.store('storagevolume', path, {'used_by': used_by}) except Exception as e: # Let the exception be raised. If we allow disks' # used_by to be out of sync, data corruption could # occour if a disk is added to two guests # unknowingly. kimchi_log.error('Unable to store storage volume id in' ' objectstore due error: %s', e.message) raise OperationFailed('KCHVOL0017E', {'err': e.message}) except Exception as e: # This exception is going to catch errors returned by 'with', # specially ones generated by 'session.store'. It is outside # to avoid conflict with the __exit__ function of 'with' raise OperationFailed('KCHVOL0017E', {'err': e.message}) return used_by def set_disk_used_by(objstore, path, new_used_by): try: with objstore as session: session.store('storagevolume', path, {'used_by': new_used_by}) except Exception as e: raise OperationFailed('KCHVOL0017E', {'err': e.message}) kimchi-1.5.0/src/kimchi/model/featuretests.py000066400000000000000000000215461254252253000212140ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-2015 # # 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 import cherrypy import libvirt import lxml.etree as ET import platform import subprocess from lxml.builder import E from kimchi.rollbackcontext import RollbackContext from kimchi.utils import kimchi_log, run_command, servermethod FEATURETEST_VM_NAME = "FEATURETEST_VM" FEATURETEST_POOL_NAME = "FEATURETEST_POOL" ISO_STREAM_XML = """ %(name)s 1048576 hvm
""" SIMPLE_VM_XML = """ %(name)s 10240 hvm """ MAXMEM_VM_XML = """ %(name)s 20480 10240 hvm """ DEV_MEM_XML = """ 10240 0 """ SCSI_FC_XML = """ %(name)s /dev/disk/by-path """ class FeatureTests(object): @staticmethod def disable_libvirt_error_logging(): def libvirt_errorhandler(userdata, error): # A libvirt error handler to ignore annoying messages in stderr pass # Filter functions are enable only in production env if cherrypy.config.get('environment') != 'production': return # Register the error handler to hide libvirt error in stderr libvirt.registerErrorHandler(f=libvirt_errorhandler, ctx=None) @staticmethod def enable_libvirt_error_logging(): # Filter functions are enable only in production env if cherrypy.config.get('environment') != 'production': return # Unregister the error handler libvirt.registerErrorHandler(f=None, ctx=None) @staticmethod def libvirt_supports_iso_stream(conn, protocol): conn_type = conn.getType().lower() domain_type = 'test' if conn_type == 'test' else 'kvm' arch = 'i686' if conn_type == 'test' else platform.machine() arch = 'ppc64' if arch == 'ppc64le' else arch xml = ISO_STREAM_XML % {'name': FEATURETEST_VM_NAME, 'domain': domain_type, 'protocol': protocol, 'arch': arch} try: FeatureTests.disable_libvirt_error_logging() dom = conn.defineXML(xml) dom.undefine() return True except libvirt.libvirtError, e: kimchi_log.error(e.message) return False finally: FeatureTests.enable_libvirt_error_logging() @staticmethod def libvirt_support_nfs_probe(conn): def _get_xml(): obj = E.source(E.host(name='localhost'), E.format(type='nfs')) xml = ET.tostring(obj) return xml try: FeatureTests.disable_libvirt_error_logging() conn.findStoragePoolSources('netfs', _get_xml(), 0) except libvirt.libvirtError as e: kimchi_log.error(e.message) if e.get_error_code() == 38: # if libvirt cannot find showmount, # it returns 38--general system call failure return False finally: FeatureTests.enable_libvirt_error_logging() return True @staticmethod @servermethod def qemu_supports_iso_stream(): host = cherrypy.server.socket_host port = cherrypy.server.socket_port cmd = "qemu-io -r http://%s:%d/images/icon-fedora.png \ -c 'read -v 0 512'" % (host, port) proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) stdout, stderr = proc.communicate() return len(stderr) == 0 @staticmethod def libvirt_support_fc_host(conn): try: FeatureTests.disable_libvirt_error_logging() pool = None pool_xml = SCSI_FC_XML % {'name': FEATURETEST_POOL_NAME} pool = conn.storagePoolDefineXML(pool_xml, 0) except libvirt.libvirtError as e: if e.get_error_code() == 27: # Libvirt requires adapter name, not needed when supports to FC return False finally: FeatureTests.enable_libvirt_error_logging() pool is None or pool.undefine() return True @staticmethod def has_metadata_support(conn): KIMCHI_META_URL = "https://github.com/kimchi-project/kimchi/" KIMCHI_NAMESPACE = "kimchi" with RollbackContext() as rollback: FeatureTests.disable_libvirt_error_logging() rollback.prependDefer(FeatureTests.enable_libvirt_error_logging) conn_type = conn.getType().lower() domain_type = 'test' if conn_type == 'test' else 'kvm' arch = 'i686' if conn_type == 'test' else platform.machine() arch = 'ppc64' if arch == 'ppc64le' else arch dom = conn.defineXML(SIMPLE_VM_XML % {'name': FEATURETEST_VM_NAME, 'domain': domain_type, 'arch': arch}) rollback.prependDefer(dom.undefine) try: dom.setMetadata(libvirt.VIR_DOMAIN_METADATA_ELEMENT, "", KIMCHI_NAMESPACE, KIMCHI_META_URL, flags=libvirt.VIR_DOMAIN_AFFECT_CURRENT) return True except libvirt.libvirtError: return False @staticmethod def kernel_support_vfio(): out, err, rc = run_command(['modprobe', 'vfio-pci']) if rc != 0: kimchi_log.warning("Unable to load Kernal module vfio-pci.") return False return True @staticmethod def is_nm_running(): '''Tries to determine whether NetworkManager is running.''' out, err, rc = run_command(['nmcli', 'dev', 'status']) if rc != 0: return False return True @staticmethod def has_mem_hotplug_support(conn): ''' A memory device can be hot-plugged or hot-unplugged since libvirt version 1.2.14. ''' # Libvirt < 1.2.14 does not support memory devices, so firstly, check # its version, then try to attach a device. These steps avoid errors # with Libvirt 'test' driver for KVM version = 1000000*1 + 1000*2 + 14 if libvirt.getVersion() < version: return False with RollbackContext() as rollback: FeatureTests.disable_libvirt_error_logging() rollback.prependDefer(FeatureTests.enable_libvirt_error_logging) conn_type = conn.getType().lower() domain_type = 'test' if conn_type == 'test' else 'kvm' arch = 'i686' if conn_type == 'test' else platform.machine() arch = 'ppc64' if arch == 'ppc64le' else arch dom = conn.defineXML(MAXMEM_VM_XML % {'name': FEATURETEST_VM_NAME, 'domain': domain_type, 'arch': arch}) rollback.prependDefer(dom.undefine) try: dom.attachDeviceFlags(DEV_MEM_XML, libvirt.VIR_DOMAIN_MEM_CONFIG) return True except libvirt.libvirtError: return False kimchi-1.5.0/src/kimchi/model/groups.py000066400000000000000000000034551254252253000200140ustar00rootroot00000000000000# # 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 import grp from kimchi.config import config class GroupsModel(object): def __init__(self, **args): auth_type = config.get("authentication", "method") for klass in GroupsModel.__subclasses__(): if auth_type == klass.auth_type: self.grp = klass(**args) def get_list(self, **args): if hasattr(self.grp, '_get_list'): return self.grp._get_list(**args) else: return list() def validate(self, gid): return self.grp._validate(gid) class PAMGroupsModel(GroupsModel): auth_type = 'pam' def __init__(self, **kargs): pass def _get_list(self): return sorted([group.gr_name for group in grp.getgrall()]) def _validate(self, gid): try: grp.getgrnam(gid) except KeyError: return False return True class LDAPGroupsModel(GroupsModel): auth_type = 'ldap' def __init__(self, **kargs): pass def _validate(self, gid): return False kimchi-1.5.0/src/kimchi/model/host.py000066400000000000000000000424771254252253000174610ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2014-2015 # # 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 import libvirt import os import time import platform from collections import defaultdict import psutil from cherrypy.process.plugins import BackgroundTask from kimchi import disks from kimchi import netinfo from kimchi.basemodel import Singleton from kimchi.model import hostdev from kimchi.exception import InvalidOperation, InvalidParameter from kimchi.exception import NotFoundError, OperationFailed from kimchi.model.config import CapabilitiesModel from kimchi.model.tasks import TaskModel from kimchi.model.vms import DOM_STATE_MAP from kimchi.repositories import Repositories from kimchi.swupdate import SoftwareUpdate from kimchi.utils import add_task, kimchi_log from kimchi.xmlutils.utils import xpath_get_text HOST_STATS_INTERVAL = 1 class HostModel(object): def __init__(self, **kargs): self.conn = kargs['conn'] self.objstore = kargs['objstore'] self.task = TaskModel(**kargs) self.host_info = self._get_host_info() def _get_ppc_cpu_info(self): res = {} with open('/proc/cpuinfo') as f: for line in f.xreadlines(): # Parse CPU, CPU's revision and CPU's clock information for key in ['cpu', 'revision', 'clock']: if key in line: info = line.split(':')[1].strip() if key == 'clock': value = float(info.split('MHz')[0].strip()) / 1000 else: value = info.split('(')[0].strip() res[key] = value # Power machines show, for each cpu/core, a block with # all cpu information. Here we control the scan of the # necessary information (1st block provides # everything), skipping the function when find all # information. if len(res.keys()) == 3: return "%(cpu)s (%(revision)s) @ %(clock)s GHz\ " % res return "" def _get_host_info(self): res = {} if platform.machine().startswith('ppc'): res['cpu_model'] = self._get_ppc_cpu_info() else: with open('/proc/cpuinfo') as f: for line in f.xreadlines(): if "model name" in line: res['cpu_model'] = line.split(':')[1].strip() break res['cpus'] = 0 res['memory'] = 0L # Include IBM PowerKVM name to supported distro names _sup_distros = platform._supported_dists + ('ibm_powerkvm',) # 'fedora' '17' 'Beefy Miracle' distro, version, codename = platform.linux_distribution( supported_dists=_sup_distros) res['os_distro'] = distro res['os_version'] = version res['os_codename'] = unicode(codename, "utf-8") return res def lookup(self, *name): cpus = psutil.NUM_CPUS # psutil is unstable on how to get the number of # cpus, different versions call it differently if hasattr(psutil, 'cpu_count'): cpus = psutil.cpu_count() elif hasattr(psutil, '_psplatform'): for method_name in ['_get_num_cpus', 'get_num_cpus']: method = getattr(psutil._psplatform, method_name, None) if method is not None: cpus = method() break self.host_info['cpus'] = cpus self.host_info['memory'] = psutil.phymem_usage().total return self.host_info def swupdate(self, *name): try: swupdate = SoftwareUpdate() except: raise OperationFailed('KCHPKGUPD0004E') pkgs = swupdate.getNumOfUpdates() if pkgs == 0: raise OperationFailed('KCHPKGUPD0001E') kimchi_log.debug('Host is going to be updated.') taskid = add_task('/host/swupdate', swupdate.doUpdate, self.objstore, None) return self.task.lookup(taskid) def shutdown(self, args=None): # Check for running vms before shutdown running_vms = self._get_vms_list_by_state('running') if len(running_vms) > 0: raise OperationFailed("KCHHOST0001E") kimchi_log.info('Host is going to shutdown.') os.system('shutdown -h now') def reboot(self, args=None): # Find running VMs running_vms = self._get_vms_list_by_state('running') if len(running_vms) > 0: raise OperationFailed("KCHHOST0002E") kimchi_log.info('Host is going to reboot.') os.system('reboot') def _get_vms_list_by_state(self, state): conn = self.conn.get() return [dom.name().decode('utf-8') for dom in conn.listAllDomains(0) if (DOM_STATE_MAP[dom.info()[0]]) == state] class HostStatsModel(object): __metaclass__ = Singleton def __init__(self, **kargs): self.host_stats = defaultdict(list) self.host_stats_thread = BackgroundTask(HOST_STATS_INTERVAL, self._update_host_stats) self.host_stats_thread.start() def lookup(self, *name): return {'cpu_utilization': self.host_stats['cpu_utilization'][-1], 'memory': self.host_stats['memory'][-1], 'disk_read_rate': self.host_stats['disk_read_rate'][-1], 'disk_write_rate': self.host_stats['disk_write_rate'][-1], 'net_recv_rate': self.host_stats['net_recv_rate'][-1], 'net_sent_rate': self.host_stats['net_sent_rate'][-1]} def _update_host_stats(self): preTimeStamp = self.host_stats['timestamp'] timestamp = time.time() # FIXME when we upgrade psutil, we can get uptime by psutil.uptime # we get uptime by float(open("/proc/uptime").readline().split()[0]) # and calculate the first io_rate after the OS started. with open("/proc/uptime") as time_f: seconds = (timestamp - preTimeStamp if preTimeStamp else float(time_f.readline().split()[0])) self.host_stats['timestamp'] = timestamp self._get_host_disk_io_rate(seconds) self._get_host_network_io_rate(seconds) self._get_percentage_host_cpu_usage() self._get_host_memory_stats() # store only 60 stats (1 min) for key, value in self.host_stats.iteritems(): if isinstance(value, list): if len(value) == 60: self.host_stats[key] = value[10:] def _get_percentage_host_cpu_usage(self): # This is cpu usage producer. This producer will calculate the usage # at an interval of HOST_STATS_INTERVAL. # The psutil.cpu_percent works as non blocking. # psutil.cpu_percent maintains a cpu time sample. # It will update the cpu time sample when it is called. # So only this producer can call psutil.cpu_percent in kimchi. self.host_stats['cpu_utilization'].append(psutil.cpu_percent(None)) def _get_host_memory_stats(self): virt_mem = psutil.virtual_memory() # available: # the actual amount of available memory that can be given # instantly to processes that request more memory in bytes; this # is calculated by summing different memory values depending on # the platform (e.g. free + buffers + cached on Linux) memory_stats = {'total': virt_mem.total, 'free': virt_mem.free, 'cached': virt_mem.cached, 'buffers': virt_mem.buffers, 'avail': virt_mem.available} self.host_stats['memory'].append(memory_stats) def _get_host_disk_io_rate(self, seconds): disk_read_bytes = self.host_stats['disk_read_bytes'] disk_write_bytes = self.host_stats['disk_write_bytes'] prev_read_bytes = disk_read_bytes[-1] if disk_read_bytes else 0 prev_write_bytes = disk_write_bytes[-1] if disk_write_bytes else 0 disk_io = psutil.disk_io_counters(False) read_bytes = disk_io.read_bytes write_bytes = disk_io.write_bytes rd_rate = int(float(read_bytes - prev_read_bytes) / seconds + 0.5) wr_rate = int(float(write_bytes - prev_write_bytes) / seconds + 0.5) self.host_stats['disk_read_rate'].append(rd_rate) self.host_stats['disk_write_rate'].append(wr_rate) self.host_stats['disk_read_bytes'].append(read_bytes) self.host_stats['disk_write_bytes'].append(write_bytes) def _get_host_network_io_rate(self, seconds): net_recv_bytes = self.host_stats['net_recv_bytes'] net_sent_bytes = self.host_stats['net_sent_bytes'] prev_recv_bytes = net_recv_bytes[-1] if net_recv_bytes else 0 prev_sent_bytes = net_sent_bytes[-1] if net_sent_bytes else 0 net_ios = psutil.network_io_counters(True) recv_bytes = 0 sent_bytes = 0 for key in set(netinfo.nics() + netinfo.wlans()) & set(net_ios.iterkeys()): recv_bytes = recv_bytes + net_ios[key].bytes_recv sent_bytes = sent_bytes + net_ios[key].bytes_sent rx_rate = int(float(recv_bytes - prev_recv_bytes) / seconds + 0.5) tx_rate = int(float(sent_bytes - prev_sent_bytes) / seconds + 0.5) self.host_stats['net_recv_rate'].append(rx_rate) self.host_stats['net_sent_rate'].append(tx_rate) self.host_stats['net_recv_bytes'].append(recv_bytes) self.host_stats['net_sent_bytes'].append(sent_bytes) class HostStatsHistoryModel(object): def __init__(self, **kargs): self.history = HostStatsModel(**kargs) def lookup(self, *name): return {'cpu_utilization': self.history.host_stats['cpu_utilization'], 'memory': self.history.host_stats['memory'], 'disk_read_rate': self.history.host_stats['disk_read_rate'], 'disk_write_rate': self.history.host_stats['disk_write_rate'], 'net_recv_rate': self.history.host_stats['net_recv_rate'], 'net_sent_rate': self.history.host_stats['net_sent_rate']} class PartitionsModel(object): def __init__(self, **kargs): pass def get_list(self): result = disks.get_partitions_names() return result class PartitionModel(object): def __init__(self, **kargs): pass def lookup(self, name): return disks.get_partition_details(name) class DevicesModel(object): def __init__(self, **kargs): self.conn = kargs['conn'] self.caps = CapabilitiesModel(**kargs) self.cap_map = \ {'net': libvirt.VIR_CONNECT_LIST_NODE_DEVICES_CAP_NET, 'pci': libvirt.VIR_CONNECT_LIST_NODE_DEVICES_CAP_PCI_DEV, 'scsi': libvirt.VIR_CONNECT_LIST_NODE_DEVICES_CAP_SCSI, 'scsi_host': libvirt.VIR_CONNECT_LIST_NODE_DEVICES_CAP_SCSI_HOST, 'storage': libvirt.VIR_CONNECT_LIST_NODE_DEVICES_CAP_STORAGE, 'usb_device': libvirt.VIR_CONNECT_LIST_NODE_DEVICES_CAP_USB_DEV, 'usb': libvirt.VIR_CONNECT_LIST_NODE_DEVICES_CAP_USB_INTERFACE} # TODO: when no longer supporting Libvirt < 1.0.5 distros # (like RHEL6) remove this verification and insert the # key 'fc_host' with the libvirt variable in the hash # declaration above. try: self.cap_map['fc_host'] = \ libvirt.VIR_CONNECT_LIST_NODE_DEVICES_CAP_FC_HOST except AttributeError: self.cap_map['fc_host'] = None def get_list(self, _cap=None, _passthrough=None, _passthrough_affected_by=None): if _passthrough_affected_by is not None: # _passthrough_affected_by conflicts with _cap and _passthrough if (_cap, _passthrough) != (None, None): raise InvalidParameter("KCHHOST0004E") return sorted( self._get_passthrough_affected_devs(_passthrough_affected_by)) if _cap == 'fc_host': dev_names = self._get_devices_fc_host() else: dev_names = self._get_devices_with_capability(_cap) if _passthrough is not None and _passthrough.lower() == 'true': conn = self.conn.get() passthrough_names = [ dev['name'] for dev in hostdev.get_passthrough_dev_infos(conn)] dev_names = list(set(dev_names) & set(passthrough_names)) dev_names.sort() return dev_names def _get_devices_with_capability(self, cap): conn = self.conn.get() if cap is None: cap_flag = 0 else: cap_flag = self.cap_map.get(cap) if cap_flag is None: return [] return [name.name() for name in conn.listAllDevices(cap_flag)] def _get_passthrough_affected_devs(self, dev_name): conn = self.conn.get() info = DeviceModel(conn=self.conn).lookup(dev_name) affected = hostdev.get_affected_passthrough_devices(conn, info) return [dev_info['name'] for dev_info in affected] def _get_devices_fc_host(self): conn = self.conn.get() # Libvirt < 1.0.5 does not support fc_host capability if not self.caps.fc_host_support: ret = [] scsi_hosts = self._get_devices_with_capability('scsi_host') for host in scsi_hosts: xml = conn.nodeDeviceLookupByName(host).XMLDesc(0) path = '/device/capability/capability/@type' if 'fc_host' in xpath_get_text(xml, path): ret.append(host) return ret # Double verification to catch the case where the libvirt # supports fc_host but does not, for some reason, recognize # the libvirt.VIR_CONNECT_LIST_NODE_DEVICES_CAP_FC_HOST # attribute. if not self.cap_map['fc_host']: return conn.listDevices('fc_host', 0) return self._get_devices_with_capability('fc_host') class DeviceModel(object): def __init__(self, **kargs): self.conn = kargs['conn'] def lookup(self, nodedev_name): conn = self.conn.get() try: dev = conn.nodeDeviceLookupByName(nodedev_name) except: raise NotFoundError('KCHHOST0003E', {'name': nodedev_name}) return hostdev.get_dev_info(dev) class PackagesUpdateModel(object): def __init__(self, **kargs): try: self.host_swupdate = SoftwareUpdate() except: self.host_swupdate = None def get_list(self): if self.host_swupdate is None: raise OperationFailed('KCHPKGUPD0004E') return self.host_swupdate.getUpdates() class PackageUpdateModel(object): def __init__(self, **kargs): pass def lookup(self, name): try: swupdate = SoftwareUpdate() except Exception: raise OperationFailed('KCHPKGUPD0004E') return swupdate.getUpdate(name) class RepositoriesModel(object): def __init__(self, **kargs): try: self.host_repositories = Repositories() except: self.host_repositories = None def get_list(self): if self.host_repositories is None: raise InvalidOperation('KCHREPOS0014E') return sorted(self.host_repositories.getRepositories()) def create(self, params): if self.host_repositories is None: raise InvalidOperation('KCHREPOS0014E') return self.host_repositories.addRepository(params) class RepositoryModel(object): def __init__(self, **kargs): try: self._repositories = Repositories() except: self._repositories = None def lookup(self, repo_id): if self._repositories is None: raise InvalidOperation('KCHREPOS0014E') return self._repositories.getRepository(repo_id) def enable(self, repo_id): if self._repositories is None: raise InvalidOperation('KCHREPOS0014E') return self._repositories.enableRepository(repo_id) def disable(self, repo_id): if self._repositories is None: raise InvalidOperation('KCHREPOS0014E') return self._repositories.disableRepository(repo_id) def update(self, repo_id, params): if self._repositories is None: raise InvalidOperation('KCHREPOS0014E') return self._repositories.updateRepository(repo_id, params) def delete(self, repo_id): if self._repositories is None: raise InvalidOperation('KCHREPOS0014E') return self._repositories.removeRepository(repo_id) kimchi-1.5.0/src/kimchi/model/hostdev.py000066400000000000000000000233231254252253000201450ustar00rootroot00000000000000# # 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 import os from pprint import pformat from pprint import pprint from kimchi.model.libvirtconnection import LibvirtConnection from kimchi.utils import kimchi_log from kimchi.xmlutils.utils import dictize def _get_all_host_dev_infos(libvirt_conn): node_devs = libvirt_conn.listAllDevices(0) return [get_dev_info(node_dev) for node_dev in node_devs] def _get_dev_info_tree(dev_infos): devs = dict([(dev_info['name'], dev_info) for dev_info in dev_infos]) root = None for dev_info in dev_infos: if dev_info['parent'] is None: root = dev_info continue try: parent = devs[dev_info['parent']] except KeyError: kimchi_log.error('Parent %s of device %s does not exist.', dev_info['parent'], dev_info['name']) continue try: children = parent['children'] except KeyError: parent['children'] = [dev_info] else: children.append(dev_info) return root def _is_pci_qualified(pci_dev): # PCI bridge is not suitable to passthrough # KVM does not support passthrough graphic card now blacklist_classes = (0x030000, 0x060000) with open(os.path.join(pci_dev['path'], 'class')) as f: pci_class = int(f.readline().strip(), 16) if pci_class & 0xff0000 in blacklist_classes: return False return True def get_passthrough_dev_infos(libvirt_conn): ''' Get devices eligible to be passed through to VM. ''' def is_eligible(dev): return dev['device_type'] in ('usb_device', 'scsi') or \ (dev['device_type'] == 'pci' and _is_pci_qualified(dev)) dev_infos = _get_all_host_dev_infos(libvirt_conn) return [dev_info for dev_info in dev_infos if is_eligible(dev_info)] def _get_same_iommugroup_devices(dev_infos, device_info): dev_dict = dict([(dev_info['name'], dev_info) for dev_info in dev_infos]) def get_iommu_group(dev_info): # Find out the iommu group of a given device. # Child device belongs to the same iommu group as the parent device. try: return dev_info['iommuGroup'] except KeyError: pass parent = dev_info['parent'] while parent is not None: try: parent_info = dev_dict[parent] except KeyError: kimchi_log.error("Parent %s of device %s does not exist", parent, dev_info['name']) break try: iommuGroup = parent_info['iommuGroup'] except KeyError: pass else: return iommuGroup parent = parent_info['parent'] return None iommu_group = get_iommu_group(device_info) if iommu_group is None: return [] return [dev_info for dev_info in dev_infos if dev_info['name'] != device_info['name'] and get_iommu_group(dev_info) == iommu_group] def _get_children_devices(dev_infos, device_info): def get_children_recursive(parent): try: children = parent['children'] except KeyError: return [] result = [] for child in children: result.append(child) result.extend(get_children_recursive(child)) return result # Annotate every the dev_info element with children information _get_dev_info_tree(dev_infos) for dev_info in dev_infos: if dev_info['name'] == device_info['name']: return get_children_recursive(dev_info) return [] def get_affected_passthrough_devices(libvirt_conn, passthrough_dev): dev_infos = _get_all_host_dev_infos(libvirt_conn) group_devices = _get_same_iommugroup_devices(dev_infos, passthrough_dev) if not group_devices: # On host without iommu group support, the affected devices should # at least include all children devices group_devices.extend(_get_children_devices(dev_infos, passthrough_dev)) return group_devices def get_dev_info(node_dev): ''' Parse the node device XML string into dict according to http://libvirt.org/formatnode.html. scsi_generic is not documented in libvirt official website. Try to parse scsi_generic according to the following libvirt path series. https://www.redhat.com/archives/libvir-list/2013-June/msg00014.html scsi_target is not documented in libvirt official website. Try to parse scsi_target according to the libvirt commit db19834a0a. ''' xmlstr = node_dev.XMLDesc(0) info = dictize(xmlstr)['device'] dev_type = info['capability'].pop('type') info['device_type'] = dev_type cap_dict = info.pop('capability') info.update(cap_dict) info['parent'] = node_dev.parent() if dev_type in ('scsi', 'scsi_generic', 'scsi_target', 'system', 'usb'): return info if dev_type in ('net', 'pci', 'scsi_host', 'storage', 'usb_device'): return globals()['_get_%s_dev_info' % dev_type](info) kimchi_log.error("Unknown device type: %s", dev_type) return info def _get_net_dev_info(info): cap = info.pop('capability') links = {"80203": "IEEE 802.3", "80211": "IEEE 802.11"} link_raw = cap['type'] info['link_type'] = links.get(link_raw, link_raw) return info def _get_pci_dev_info(info): for k in ('vendor', 'product'): try: description = info[k].pop('pyval') except KeyError: description = None info[k]['description'] = description if 'path' not in info: # Old libvirt does not provide syspath info info['path'] = \ "/sys/bus/pci/devices/" \ "%(domain)04x:%(bus)02x:%(slot)02x.%(function)01x" % { 'domain': info['domain'], 'bus': info['bus'], 'slot': info['slot'], 'function': info['function']} try: info['iommuGroup'] = int(info['iommuGroup']['number']) except KeyError: # Old libvirt does not provide syspath info, figure it out ourselves iommu_link = os.path.join(info['path'], 'iommu_group') if os.path.exists(iommu_link): iommu_path = os.path.realpath(iommu_link) try: info['iommuGroup'] = int(iommu_path.rsplit('/', 1)[1]) except (ValueError, IndexError): # No IOMMU group support at all. pass else: # No IOMMU group support at all. pass return info def _get_scsi_host_dev_info(info): try: cap_info = info.pop('capability') except KeyError: # kimchi.model.libvirtstoragepool.ScsiPoolDef assumes # info['adapter']['type'] always exists. info['adapter'] = {'type': ''} return info if isinstance(cap_info, list): info['adapter'] = {} for cap in cap_info: if cap['type'] == 'vport_ops': del cap['type'] info['adapter']['vport_ops'] = cap else: info['adapter'].update(cap) else: info['adapter'] = cap_info return info def _get_storage_dev_info(info): try: cap_info = info.pop('capability') except KeyError: return info if cap_info['type'] == 'removable': cap_info['available'] = bool(cap_info.pop('media_available')) if cap_info['available']: for k in ('size', 'label'): try: cap_info[k] = cap_info.pop('media_' + k) except KeyError: cap_info[k] = None info['media'] = cap_info return info def _get_usb_device_dev_info(info): for k in ('vendor', 'product'): try: info[k]['description'] = info[k].pop('pyval') except KeyError: # Some USB devices don't provide vendor/product description. pass return info # For test and debug def _print_host_dev_tree(libvirt_conn): dev_infos = _get_all_host_dev_infos(libvirt_conn) root = _get_dev_info_tree(dev_infos) if root is None: print "No device found" return print '-----------------' print '\n'.join(_format_dev_node(root)) def _format_dev_node(node): try: children = node['children'] del node['children'] except KeyError: children = [] lines = [] lines.extend([' ~' + line for line in pformat(node).split('\n')]) count = len(children) for i, child in enumerate(children): if count == 1: lines.append(' \-----------------') else: lines.append(' +-----------------') clines = _format_dev_node(child) if i == count - 1: p = ' ' else: p = ' |' lines.extend([p + cline for cline in clines]) lines.append('') return lines if __name__ == '__main__': libvirt_conn = LibvirtConnection('qemu:///system').get() _print_host_dev_tree(libvirt_conn) print 'Eligible passthrough devices:' pprint(get_passthrough_dev_infos(libvirt_conn)) kimchi-1.5.0/src/kimchi/model/interfaces.py000066400000000000000000000026671254252253000206240ustar00rootroot00000000000000# # 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 from kimchi import netinfo from kimchi.exception import NotFoundError from kimchi.model.networks import NetworksModel class InterfacesModel(object): def __init__(self, **kargs): self.conn = kargs['conn'] self.networks = NetworksModel(**kargs) def get_list(self): return list(set(netinfo.all_favored_interfaces()) - set(self.networks.get_all_networks_interfaces())) class InterfaceModel(object): def __init__(self, **kargs): pass def lookup(self, name): try: return netinfo.get_interface_info(name) except ValueError: raise NotFoundError("KCHIFACE0001E", {'name': name}) kimchi-1.5.0/src/kimchi/model/libvirtconnection.py000066400000000000000000000127571254252253000222350ustar00rootroot00000000000000# # 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 import threading import time import cherrypy import libvirt from kimchi.utils import kimchi_log class LibvirtConnection(object): _connections = {} _connectionLock = threading.Lock() def __init__(self, uri): self.uri = uri if self.uri not in LibvirtConnection._connections: LibvirtConnection._connections[self.uri] = {} self._connections = LibvirtConnection._connections[self.uri] self.wrappables = self.get_wrappable_objects() def get_wrappable_objects(self): """ When a wrapped function returns an instance of another libvirt object, we also want to wrap that object so we can catch errors that happen when calling its methods. """ objs = [] for name in ('virDomain', 'virDomainSnapshot', 'virInterface', 'virNWFilter', 'virNetwork', 'virNodeDevice', 'virSecret', 'virStoragePool', 'virStorageVol', 'virStream'): try: attr = getattr(libvirt, name) except AttributeError: pass objs.append(attr) return tuple(objs) def get(self, conn_id=0): """ Return current connection to libvirt or open a new one. Wrap all callable libvirt methods so we can catch connection errors and handle them by restarting the server. """ def wrapMethod(f): def wrapper(*args, **kwargs): try: ret = f(*args, **kwargs) return ret except libvirt.libvirtError as e: edom = e.get_error_domain() ecode = e.get_error_code() EDOMAINS = (libvirt.VIR_FROM_REMOTE, libvirt.VIR_FROM_RPC) ECODES = (libvirt.VIR_ERR_SYSTEM_ERROR, libvirt.VIR_ERR_INTERNAL_ERROR, libvirt.VIR_ERR_NO_CONNECT, libvirt.VIR_ERR_INVALID_CONN) if edom in EDOMAINS and ecode in ECODES: kimchi_log.error('Connection to libvirt broken. ' 'Recycling. ecode: %d edom: %d' % (ecode, edom)) with LibvirtConnection._connectionLock: self._connections[conn_id] = None raise wrapper.__name__ = f.__name__ wrapper.__doc__ = f.__doc__ return wrapper with LibvirtConnection._connectionLock: conn = self._connections.get(conn_id) if not conn: retries = 5 while True: retries = retries - 1 try: conn = libvirt.open(self.uri) break except libvirt.libvirtError: kimchi_log.error('Unable to connect to libvirt.') if not retries: kimchi_log.error("Unable to establish connection " "with libvirt. Please check " "your libvirt URI which is often " "defined in " "/etc/libvirt/libvirt.conf") cherrypy.engine.stop() exit(1) time.sleep(2) for name in dir(libvirt.virConnect): method = getattr(conn, name) if callable(method) and not name.startswith('_'): setattr(conn, name, wrapMethod(method)) for cls in self.wrappables: for name in dir(cls): method = getattr(cls, name) if callable(method) and not name.startswith('_'): setattr(cls, name, wrapMethod(method)) self._connections[conn_id] = conn # In case we're running into troubles with keeping the # connections alive we should place here: # conn.setKeepAlive(interval=5, count=3) # However the values need to be considered wisely to not affect # hosts which are hosting a lot of virtual machines return conn def isQemuURI(self): """ This method will return True or Value when the system libvirt URI is a qemu based URI. For example: qemu:///system or qemu+tcp://someipaddress/system """ if self.get().getURI().startswith('qemu'): return True else: return False kimchi-1.5.0/src/kimchi/model/libvirtstoragepool.py000066400000000000000000000221051254252253000224200ustar00rootroot00000000000000# # 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 import os import tempfile import lxml.etree as ET from lxml.builder import E import libvirt from kimchi.exception import InvalidParameter, OperationFailed, TimeoutExpired from kimchi.iscsi import TargetClient from kimchi.rollbackcontext import RollbackContext from kimchi.utils import kimchi_log, parse_cmd_output, run_command class StoragePoolDef(object): @classmethod def create(cls, poolArgs): for klass in cls.__subclasses__(): if poolArgs['type'] == klass.poolType: return klass(poolArgs) raise OperationFailed("KCHPOOL0014E", {'type': poolArgs['type']}) def __init__(self, poolArgs): self.poolArgs = poolArgs def prepare(self, conn): ''' Validate pool arguments and perform preparations. Operation which would cause side effect should be put here. Subclasses can optionally override this method, or it always succeeds by default. ''' pass @property def xml(self): ''' Subclasses have to override this method to actually generate the storage pool XML definition. Should cause no side effect and be idempotent''' # TODO: When add new pool type, should also add the related test in # tests/test_storagepool.py raise OperationFailed("KCHPOOL0015E", {'pool': self}) class DirPoolDef(StoragePoolDef): poolType = 'dir' @property def xml(self): # Required parameters # name: # type: # path: pool = E.pool(type='dir') pool.append(E.name(self.poolArgs['name'])) pool.append(E.target(E.path(self.poolArgs['path']))) return ET.tostring(pool, encoding='unicode', pretty_print=True) class NetfsPoolDef(StoragePoolDef): poolType = 'netfs' def __init__(self, poolArgs): super(NetfsPoolDef, self).__init__(poolArgs) self.path = '/var/lib/kimchi/nfs_mount/' + self.poolArgs['name'] def prepare(self, conn): mnt_point = tempfile.mkdtemp(dir='/tmp') export_path = "%s:%s" % ( self.poolArgs['source']['host'], self.poolArgs['source']['path']) mount_cmd = ["mount", "-o", 'soft,timeo=100,retrans=3,retry=0', export_path, mnt_point] umount_cmd = ["umount", "-f", export_path] mounted = False # Due to an NFS bug (See Red Hat BZ 1023059), NFSv4 exports may take # 10-15 seconds to mount the first time. cmd_timeout = 15 with RollbackContext() as rollback: rollback.prependDefer(os.rmdir, mnt_point) try: run_command(mount_cmd, cmd_timeout) rollback.prependDefer(run_command, umount_cmd, cmd_timeout) except TimeoutExpired: raise InvalidParameter("KCHPOOL0012E", {'path': export_path}) with open("/proc/mounts", "rb") as f: rawMounts = f.read() output_items = ['dev_path', 'mnt_point', 'type'] mounts = parse_cmd_output(rawMounts, output_items) for item in mounts: if 'dev_path' in item and item['dev_path'] == export_path: mounted = True if not mounted: raise InvalidParameter("KCHPOOL0013E", {'path': export_path}) @property def xml(self): # Required parameters # name: # type: # source[host]: # source[path]: pool = E.pool(type='netfs') pool.append(E.name(self.poolArgs['name'])) source = E.source() source.append(E.host(name=self.poolArgs['source']['host'])) source.append(E.dir(path=self.poolArgs['source']['path'])) pool.append(source) pool.append(E.target(E.path(self.path))) return ET.tostring(pool, encoding='unicode', pretty_print=True) class LogicalPoolDef(StoragePoolDef): poolType = 'logical' def __init__(self, poolArgs): super(LogicalPoolDef, self).__init__(poolArgs) self.path = '/dev/' + self.poolArgs['name'] @property def xml(self): # Required parameters # name: # type: # source[devices]: pool = E.pool(type='logical') pool.append(E.name(self.poolArgs['name'])) source = E.source() for device_path in self.poolArgs['source']['devices']: source.append(E.device(path=device_path)) pool.append(source) pool.append(E.target(E.path(self.path))) return ET.tostring(pool, encoding='unicode', pretty_print=True) class ScsiPoolDef(StoragePoolDef): poolType = 'scsi' def prepare(self, conn=None): tmp_name = self.poolArgs['source']['name'] self.poolArgs['source']['name'] = tmp_name.replace('scsi_', '') # fc_host adapters type are only available in libvirt >= 1.0.5 if not self.poolArgs['fc_host_support']: self.poolArgs['source']['adapter']['type'] = 'scsi_host' msg = "Libvirt version <= 1.0.5. Setting SCSI host name as '%s'; "\ "setting SCSI adapter type as 'scsi_host'; "\ "ignoring wwnn and wwpn." % tmp_name kimchi_log.info(msg) # Path for Fibre Channel scsi hosts self.poolArgs['path'] = '/dev/disk/by-path' if not self.poolArgs['source']['adapter']['type']: self.poolArgs['source']['adapter']['type'] = 'scsi_host' @property def xml(self): # Required parameters # name: # source[adapter][type]: # source[name]: # source[adapter][wwnn]: # source[adapter][wwpn]: # path: pool = E.pool(type='scsi') pool.append(E.name(self.poolArgs['name'])) adapter = E.adapter(type=self.poolArgs['source']['adapter']['type']) adapter.set('name', self.poolArgs['source']['name']) adapter.set('wwnn', self.poolArgs['source']['adapter']['wwnn']) adapter.set('wwpn', self.poolArgs['source']['adapter']['wwpn']) pool.append(E.source(adapter)) pool.append(E.target(E.path(self.poolArgs['path']))) return ET.tostring(pool, encoding='unicode', pretty_print=True) class IscsiPoolDef(StoragePoolDef): poolType = 'iscsi' def prepare(self, conn): source = self.poolArgs['source'] if not TargetClient(**source).validate(): msg_args = {'host': source['host'], 'target': source['target']} raise OperationFailed("KCHISCSI0002E", msg_args) self._prepare_auth(conn) def _prepare_auth(self, conn): try: auth = self.poolArgs['source']['auth'] except KeyError: return try: virSecret = conn.secretLookupByUsage( libvirt.VIR_SECRET_USAGE_TYPE_ISCSI, self.poolArgs['name']) except libvirt.libvirtError: secret = E.secret(ephemeral='no', private='yes') description = E.description('Secret for iSCSI storage pool %s' % self.poolArgs['name']) secret.append(description) secret.append(E.auth(type='chap', username=auth['username'])) usage = E.usage(type='iscsi') usage.append(E.target(self.poolArgs['name'])) secret.append(usage) virSecret = conn.secretDefineXML(ET.tostring(secret)) virSecret.setValue(auth['password']) @property def xml(self): # Required parameters # name: # type: # source[host]: # source[target]: # # Optional parameters # source[port]: pool = E.pool(type='iscsi') pool.append(E.name(self.poolArgs['name'])) host = E.host(name=self.poolArgs['source']['host']) port = self.poolArgs['source'].get('port') if port is not None: host.set('port', str(port)) source = E.source(host) source.append(E.device(path=self.poolArgs['source']['target'])) source_auth = self.poolArgs['source'].get('auth') if source_auth is not None: auth = E.auth(type='chap') auth.set('username', source_auth['username']) secret = E.secret(type='iscsi') secret.set('usage', self.poolArgs['name']) auth.append(secret) source.append(auth) pool.append(source) pool.append(E.target(E.path('/dev/disk/by-id'))) return ET.tostring(pool, encoding='unicode', pretty_print=True) kimchi-1.5.0/src/kimchi/model/model.py000066400000000000000000000035741254252253000175770ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2014-2015 # # 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 import inspect import os from kimchi.basemodel import BaseModel from kimchi.model.libvirtconnection import LibvirtConnection from kimchi.objectstore import ObjectStore from kimchi.utils import import_module, listPathModules class Model(BaseModel): def __init__(self, libvirt_uri=None, objstore_loc=None): self.objstore = ObjectStore(objstore_loc) self.conn = LibvirtConnection(libvirt_uri) kargs = {'objstore': self.objstore, 'conn': self.conn} this = os.path.basename(__file__) this_mod = os.path.splitext(this)[0] models = [] for mod_name in listPathModules(os.path.dirname(__file__)): if mod_name.startswith("_") or mod_name == this_mod: continue module = import_module('model.' + mod_name) members = inspect.getmembers(module, inspect.isclass) for cls_name, instance in members: if inspect.getmodule(instance) == module: if cls_name.endswith('Model'): models.append(instance(**kargs)) return super(Model, self).__init__(models) kimchi-1.5.0/src/kimchi/model/networks.py000066400000000000000000000357031254252253000203520ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2014-2015 # # 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 import sys import time import ipaddr import libvirt from xml.sax.saxutils import escape from kimchi import netinfo from kimchi import network as knetwork from kimchi.config import paths from kimchi.exception import InvalidOperation, InvalidParameter from kimchi.exception import MissingParameter, NotFoundError, OperationFailed from kimchi.osinfo import defaults as tmpl_defaults from kimchi.rollbackcontext import RollbackContext from kimchi.utils import kimchi_log, run_command from kimchi.xmlutils.network import create_vlan_tagged_bridge_xml from kimchi.xmlutils.network import to_network_xml from kimchi.xmlutils.utils import xpath_get_text KIMCHI_BRIDGE_PREFIX = 'kb' class NetworksModel(object): def __init__(self, **kargs): self.conn = kargs['conn'] if self.conn.isQemuURI(): self._check_default_networks() def _check_default_networks(self): networks = list(set(tmpl_defaults['networks'])) conn = self.conn.get() error_msg = ("Please, check the configuration in %s/template.conf to " "ensure it lists only valid networks." % paths.conf_dir) for net_name in networks: try: net = conn.networkLookupByName(net_name) except libvirt.libvirtError, e: msg = "Fatal: Unable to find network %s." kimchi_log.error(msg, net_name) kimchi_log.error(error_msg) kimchi_log.error("Details: %s", e.message) sys.exit(1) if net.isActive() == 0: try: net.create() except libvirt.libvirtError as e: msg = "Fatal: Unable to activate network %s." kimchi_log.error(msg, net_name) kimchi_log.error(error_msg) kimchi_log.error("Details: %s", e.message) sys.exit(1) def create(self, params): conn = self.conn.get() name = params['name'] if name in self.get_list(): raise InvalidOperation("KCHNET0001E", {'name': name}) connection = params["connection"] # set forward mode, isolated do not need forward if connection != 'isolated': params['forward'] = {'mode': connection} # set subnet, bridge network do not need subnet if connection in ["nat", 'isolated']: self._set_network_subnet(params) # only bridge network need bridge(linux bridge) or interface(macvtap) if connection == 'bridge': self._set_network_bridge(params) params['name'] = escape(params['name']) xml = to_network_xml(**params) try: network = conn.networkDefineXML(xml.encode("utf-8")) network.setAutostart(True) except libvirt.libvirtError as e: raise OperationFailed("KCHNET0008E", {'name': name, 'err': e.get_error_message()}) return name def get_list(self): conn = self.conn.get() names = conn.listNetworks() + conn.listDefinedNetworks() return sorted(map(lambda x: x.decode('utf-8'), names)) def _get_available_address(self, addr_pools=[]): invalid_addrs = [] for net_name in self.get_list(): network = NetworkModel.get_network(self.conn.get(), net_name) xml = network.XMLDesc(0) subnet = NetworkModel.get_network_from_xml(xml)['subnet'] subnet and invalid_addrs.append(ipaddr.IPNetwork(subnet)) addr_pools = addr_pools if addr_pools else knetwork.PrivateNets return knetwork.get_one_free_network(invalid_addrs, addr_pools) def _set_network_subnet(self, params): netaddr = params.get('subnet', '') # lookup a free network address for nat and isolated automatically if not netaddr: netaddr = self._get_available_address() if not netaddr: raise OperationFailed("KCHNET0009E", {'name': params['name']}) try: ip = ipaddr.IPNetwork(netaddr) except ValueError: raise InvalidParameter("KCHNET0003E", {'subent': netaddr, 'network': params['name']}) if ip.ip == ip.network: ip.ip = ip.ip + 1 dhcp_start = str(ip.ip + ip.numhosts / 2) dhcp_end = str(ip.ip + ip.numhosts - 2) params.update({'net': str(ip), 'dhcp': {'range': {'start': dhcp_start, 'end': dhcp_end}}}) def _ensure_iface_up(self, iface): if netinfo.operstate(iface) != 'up': _, err, rc = run_command(['ip', 'link', 'set', 'dev', iface, 'up']) if rc != 0: raise OperationFailed("KCHNET0020E", {'iface': iface, 'err': err}) # Add a delay to wait for the link change takes into effect. for i in range(10): time.sleep(1) if netinfo.operstate(iface) == 'up': break else: raise OperationFailed("KCHNET0021E", {'iface': iface}) def _set_network_bridge(self, params): try: iface = params['interface'] if iface in self.get_all_networks_interfaces(): msg_args = {'iface': iface, 'network': params['name']} raise InvalidParameter("KCHNET0006E", msg_args) except KeyError: raise MissingParameter("KCHNET0004E", {'name': params['name']}) self._ensure_iface_up(iface) if netinfo.is_bridge(iface): if 'vlan_id' in params: raise InvalidParameter('KCHNET0019E', {'name': iface}) params['bridge'] = iface elif netinfo.is_bare_nic(iface) or netinfo.is_bonding(iface): if params.get('vlan_id') is None: params['forward']['dev'] = iface else: params['bridge'] = \ self._create_vlan_tagged_bridge(str(iface), str(params['vlan_id'])) else: raise InvalidParameter("KCHNET0007E") def get_all_networks_interfaces(self): net_names = self.get_list() interfaces = [] for name in net_names: conn = self.conn.get() network = conn.networkLookupByName(name.encode("utf-8")) xml = network.XMLDesc(0) net_dict = NetworkModel.get_network_from_xml(xml) forward = net_dict['forward'] (forward['mode'] == 'bridge' and forward['interface'] and interfaces.append(forward['interface'][0]) is None or interfaces.extend(forward['interface'] + forward['pf'])) net_dict['bridge'] and interfaces.append(net_dict['bridge']) return interfaces def _create_vlan_tagged_bridge(self, interface, vlan_id): # Truncate the interface name if it exceeds 8 characters to make sure # the length of bridge name is less than 15 (its maximum value). br_name = KIMCHI_BRIDGE_PREFIX + interface[-8:] + '-' + vlan_id br_xml = create_vlan_tagged_bridge_xml(br_name, interface, vlan_id) conn = self.conn.get() bridges = [] for net in conn.listAllNetworks(): # Bridged networks do not have a bridge name # So in those cases, libvirt raises an error when trying to get # the bridge name try: bridges.append(net.bridgeName()) except libvirt.libvirtError, e: kimchi_log.error(e.message) if br_name in bridges: raise InvalidOperation("KCHNET0010E", {'iface': br_name}) with RollbackContext() as rollback: try: vlan_tagged_br = conn.interfaceDefineXML(br_xml, 0) rollback.prependDefer(vlan_tagged_br.destroy) vlan_tagged_br.create(0) except libvirt.libvirtError as e: raise OperationFailed(e.message) else: return br_name class NetworkModel(object): def __init__(self, **kargs): self.conn = kargs['conn'] self.objstore = kargs['objstore'] def lookup(self, name): network = self.get_network(self.conn.get(), name) xml = network.XMLDesc(0) net_dict = self.get_network_from_xml(xml) subnet = net_dict['subnet'] dhcp = net_dict['dhcp'] forward = net_dict['forward'] interface = net_dict['bridge'] connection = forward['mode'] or "isolated" # FIXME, if we want to support other forward mode well. if connection == 'bridge': # macvtap bridge interface = interface or forward['interface'][0] # exposing the network on linux bridge or macvtap interface interface_subnet = knetwork.get_dev_netaddr(interface) subnet = subnet if subnet else interface_subnet # libvirt use format 192.168.0.1/24, standard should be 192.168.0.0/24 # http://www.ovirt.org/File:Issue3.png if subnet: subnet = ipaddr.IPNetwork(subnet) subnet = "%s/%s" % (subnet.network, subnet.prefixlen) return {'connection': connection, 'interface': interface, 'subnet': subnet, 'dhcp': dhcp, 'vms': self._get_vms_attach_to_a_network(name), 'in_use': self._is_network_in_use(name), 'autostart': network.autostart() == 1, 'state': network.isActive() and "active" or "inactive", 'persistent': True if network.isPersistent() else False} def _is_network_in_use(self, name): # All the networks listed as default in template.conf file should not # be deactivate or deleted. Otherwise, we will allow user create # inconsistent templates from scratch if name in tmpl_defaults['networks']: return True vms = self._get_vms_attach_to_a_network(name) return bool(vms) or self._is_network_used_by_template(name) def _is_network_used_by_template(self, network): with self.objstore as session: templates = session.get_list('template') for tmpl in templates: tmpl_net = session.get('template', tmpl)['networks'] if network in tmpl_net: return True return False def _get_vms_attach_to_a_network(self, network, filter="all"): DOM_STATE_MAP = {'nostate': 0, 'running': 1, 'blocked': 2, 'paused': 3, 'shutdown': 4, 'shutoff': 5, 'crashed': 6} state = DOM_STATE_MAP.get(filter) vms = [] conn = self.conn.get() for dom in conn.listAllDomains(0): networks = self._vm_get_networks(dom) if network.encode('utf-8') in networks and \ (state is None or state == dom.state(0)[0]): vms.append(dom.name()) return vms def _vm_get_networks(self, dom): xml = dom.XMLDesc(0) xpath = "/domain/devices/interface[@type='network']/source/@network" return xpath_get_text(xml, xpath) def activate(self, name): network = self.get_network(self.conn.get(), name) try: network.create() except libvirt.libvirtError, e: raise OperationFailed('KCHNET0022E', {'name': name, 'err': e.message}) def deactivate(self, name): if self._is_network_in_use(name): vms = self._get_vms_attach_to_a_network(name) vms.sort() raise InvalidOperation("KCHNET0018E", {'name': name, 'vms': ', '.join(vms)}) network = self.get_network(self.conn.get(), name) network.destroy() def delete(self, name): if self._is_network_in_use(name): vms = self._get_vms_attach_to_a_network(name) vms.sort() raise InvalidOperation("KCHNET0017E", {'name': name, 'vms': ', '.join(vms)}) network = self.get_network(self.conn.get(), name) if network.isActive(): raise InvalidOperation("KCHNET0005E", {'name': name}) self._remove_vlan_tagged_bridge(network) network.undefine() @staticmethod def get_network(conn, name): name = name.encode("utf-8") try: return conn.networkLookupByName(name) except libvirt.libvirtError: raise NotFoundError("KCHNET0002E", {'name': name}) @staticmethod def get_network_from_xml(xml): address = xpath_get_text(xml, "/network/ip/@address") address = address and address[0] or '' netmask = xpath_get_text(xml, "/network/ip/@netmask") netmask = netmask and netmask[0] or '' net = address and netmask and "/".join([address, netmask]) or '' dhcp_start = xpath_get_text(xml, "/network/ip/dhcp/range/@start") dhcp_start = dhcp_start and dhcp_start[0] or '' dhcp_end = xpath_get_text(xml, "/network/ip/dhcp/range/@end") dhcp_end = dhcp_end and dhcp_end[0] or '' dhcp = {'start': dhcp_start, 'end': dhcp_end} forward_mode = xpath_get_text(xml, "/network/forward/@mode") forward_mode = forward_mode and forward_mode[0] or '' forward_if = xpath_get_text(xml, "/network/forward/interface/@dev") forward_pf = xpath_get_text(xml, "/network/forward/pf/@dev") bridge = xpath_get_text(xml, "/network/bridge/@name") bridge = bridge and bridge[0] or '' return {'subnet': net, 'dhcp': dhcp, 'bridge': bridge, 'forward': {'mode': forward_mode, 'interface': forward_if, 'pf': forward_pf}} def _remove_vlan_tagged_bridge(self, network): try: bridge = network.bridgeName() except libvirt.libvirtError: pass else: if bridge.startswith(KIMCHI_BRIDGE_PREFIX): conn = self.conn.get() iface = conn.interfaceLookupByName(bridge) iface.isActive() and iface.destroy(0) iface.undefine() kimchi-1.5.0/src/kimchi/model/peers.py000066400000000000000000000047671254252253000176220ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2014-2015 # # 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 import cherrypy import re import socket from kimchi.config import config from kimchi.utils import kimchi_log, run_command class PeersModel(object): def __init__(self, **kargs): # check federation feature is enabled on Kimchi server if config.get("server", "federation") == "off": return # register server on openslp hostname = socket.getfqdn(config.get("server", "host")) port = config.get("server", "ssl_port") self.url = hostname + ":" + port cmd = ["slptool", "register", "service:kimchid://%s" % self.url] out, error, ret = run_command(cmd) if out and len(out) != 0: kimchi_log.error("Unable to register server on openSLP." " Details: %s" % out) cherrypy.engine.subscribe('exit', self._peer_deregister) def _peer_deregister(self): cmd = ["slptool", "deregister", "service:kimchid://%s" % self.url] out, error, ret = run_command(cmd) if out and len(out) != 0: kimchi_log.error("Unable to deregister server on openSLP." " Details: %s" % out) def get_list(self): # check federation feature is enabled on Kimchi server if config.get("server", "federation") == "off": return [] cmd = ["slptool", "findsrvs", "service:kimchid"] out, error, ret = run_command(cmd) if ret != 0: return [] peers = [] for server in out.strip().split("\n"): match = re.match("service:kimchid://(.*?),.*", server) peer = match.group(1) if peer != self.url: peers.append("https://" + peer) return peers kimchi-1.5.0/src/kimchi/model/plugins.py000066400000000000000000000017431254252253000201540ustar00rootroot00000000000000# # 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 from kimchi.utils import get_enabled_plugins class PluginsModel(object): def __init__(self, **kargs): pass def get_list(self): return [plugin for (plugin, config) in get_enabled_plugins()] kimchi-1.5.0/src/kimchi/model/storagepools.py000066400000000000000000000460531254252253000212170ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2014-2015 # # 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 import libvirt import lxml.etree as ET import sys from lxml.builder import E from kimchi.config import config, paths from kimchi.scan import Scanner from kimchi.exception import InvalidOperation, MissingParameter from kimchi.exception import NotFoundError, OperationFailed from kimchi.model.config import CapabilitiesModel from kimchi.model.host import DeviceModel from kimchi.model.libvirtstoragepool import StoragePoolDef from kimchi.osinfo import defaults as tmpl_defaults from kimchi.utils import add_task, kimchi_log, pool_name_from_uri, run_command from kimchi.xmlutils.utils import xpath_get_text ISO_POOL_NAME = u'kimchi_isos' POOL_STATE_MAP = {0: 'inactive', 1: 'initializing', 2: 'active', 3: 'degraded', 4: 'inaccessible'} # Types of pools supported STORAGE_SOURCES = {'netfs': {'addr': '/pool/source/host/@name', 'path': '/pool/source/dir/@path'}, 'iscsi': {'addr': '/pool/source/host/@name', 'port': '/pool/source/host/@port', 'path': '/pool/source/device/@path'}, 'scsi': {'adapter_type': '/pool/source/adapter/@type', 'adapter_name': '/pool/source/adapter/@name', 'wwnn': '/pool/source/adapter/@wwnn', 'wwpn': '/pool/source/adapter/@wwpn'}} class StoragePoolsModel(object): def __init__(self, **kargs): self.conn = kargs['conn'] self.objstore = kargs['objstore'] self.scanner = Scanner(self._clean_scan) self.scanner.delete() self.caps = CapabilitiesModel(**kargs) self.device = DeviceModel(**kargs) if self.conn.isQemuURI(): self._check_default_pools() def _check_default_pools(self): pools = {} default_pool = tmpl_defaults['storagepool'] default_pool = default_pool.split('/')[2] pools[default_pool] = {} if default_pool == 'default': pools[default_pool] = {'path': '/var/lib/libvirt/images'} if config.get("server", "create_iso_pool") == "true": pools['ISO'] = {'path': '/var/lib/kimchi/isos'} error_msg = ("Please, check the configuration in %s/template.conf to " "ensure it has a valid storage pool." % paths.conf_dir) conn = self.conn.get() for pool_name in pools: try: pool = conn.storagePoolLookupByName(pool_name) except libvirt.libvirtError, e: pool_path = pools[pool_name].get('path') if pool_path is None: msg = "Fatal: Unable to find storage pool %s. " + error_msg kimchi_log.error(msg % pool_name) kimchi_log.error("Details: %s", e.message) sys.exit(1) # Try to create the pool pool = E.pool(E.name(pool_name), type='dir') pool.append(E.target(E.path(pool_path))) xml = ET.tostring(pool) try: pool = conn.storagePoolDefineXML(xml, 0) # Add build step to make sure target directory created pool.build(libvirt.VIR_STORAGE_POOL_BUILD_NEW) pool.setAutostart(1) except libvirt.libvirtError, e: msg = "Fatal: Unable to create storage pool %s. " msg += error_msg kimchi_log.error(msg % pool_name) kimchi_log.error("Details: %s", e.message) sys.exit(1) if pool.isActive() == 0: try: pool.create(0) except libvirt.libvirtError, e: msg = "Fatal: Unable to craete storage pool %s. " msg += error_msg kimchi_log.error(msg % pool_name) kimchi_log.error("Details: %s", e.message) sys.exit(1) def get_list(self): try: conn = self.conn.get() names = conn.listStoragePools() names += conn.listDefinedStoragePools() return sorted(map(lambda x: x.decode('utf-8'), names)) except libvirt.libvirtError as e: raise OperationFailed("KCHPOOL0006E", {'err': e.get_error_message()}) def create(self, params): task_id = None conn = self.conn.get() try: name = params['name'] if name == ISO_POOL_NAME: raise InvalidOperation("KCHPOOL0031E") # The user may want to create a logical pool with the same name # used before but a volume group will already exist with this name # So check the volume group does not exist to create the pool if params['type'] == 'logical': vgdisplay_cmd = ['vgdisplay', name.encode('utf-8')] output, error, returncode = run_command(vgdisplay_cmd) # From vgdisplay error codes: # 1 error reading VGDA # 2 volume group doesn't exist # 3 not all physical volumes of volume group online # 4 volume group not found # 5 no volume groups found at all # 6 error reading VGDA from lvmtab if returncode not in [2, 4, 5]: raise InvalidOperation("KCHPOOL0036E", {'name': name}) if params['type'] == 'kimchi-iso': task_id = self._do_deep_scan(params) if params['type'] == 'scsi': adapter_name = params['source']['adapter_name'] extra_params = self.device.lookup(adapter_name) # Adds name, adapter_type, wwpn and wwnn to source information params['source'].update(extra_params) params['fc_host_support'] = self.caps.fc_host_support poolDef = StoragePoolDef.create(params) poolDef.prepare(conn) xml = poolDef.xml.encode("utf-8") except KeyError, item: raise MissingParameter("KCHPOOL0004E", {'item': str(item), 'name': name}) if name in self.get_list(): raise InvalidOperation("KCHPOOL0001E", {'name': name}) try: if task_id: # Create transient pool for deep scan conn.storagePoolCreateXML(xml, 0) return name pool = conn.storagePoolDefineXML(xml, 0) if params['type'] in ['logical', 'dir', 'netfs', 'scsi']: pool.build(libvirt.VIR_STORAGE_POOL_BUILD_NEW) # autostart dir, logical, netfs and scsi storage pools created # from kimchi pool.setAutostart(1) else: # disable autostart for others pool.setAutostart(0) except libvirt.libvirtError as e: kimchi_log.error("Problem creating Storage Pool: %s", e) raise OperationFailed("KCHPOOL0007E", {'name': name, 'err': e.get_error_message()}) if params['type'] == 'netfs': output, error, returncode = run_command(['setsebool', '-P', 'virt_use_nfs=1']) if error or returncode: kimchi_log.error("Unable to set virt_use_nfs=1. If you use " "SELinux, this may prevent NFS pools from " "being used.") return name def _clean_scan(self, pool_name): try: conn = self.conn.get() pool = conn.storagePoolLookupByName(pool_name.encode("utf-8")) pool.destroy() with self.objstore as session: session.delete('scanning', pool_name) except Exception, e: err = "Exception %s occured when cleaning scan result" kimchi_log.debug(err % e.message) def _do_deep_scan(self, params): scan_params = dict(ignore_list=[]) scan_params['scan_path'] = params['path'] params['type'] = 'dir' for pool in self.get_list(): try: res = StoragePoolModel(conn=self.conn, objstore=self.objstore).lookup(pool) if res['state'] == 'active': scan_params['ignore_list'].append(res['path']) except Exception, e: err = "Exception %s occured when get ignore path" kimchi_log.debug(err % e.message) params['path'] = self.scanner.scan_dir_prepare(params['name']) scan_params['pool_path'] = params['path'] task_id = add_task('/storagepools/%s' % ISO_POOL_NAME, self.scanner.start_scan, self.objstore, scan_params) # Record scanning-task/storagepool mapping for future querying try: with self.objstore as session: session.store('scanning', params['name'], task_id) return task_id except Exception as e: raise OperationFailed('KCHPOOL0037E', {'err': e.message}) class StoragePoolModel(object): def __init__(self, **kargs): self.conn = kargs['conn'] self.objstore = kargs['objstore'] @staticmethod def get_storagepool(name, conn): conn = conn.get() try: return conn.storagePoolLookupByName(name.encode("utf-8")) except libvirt.libvirtError as e: if e.get_error_code() == libvirt.VIR_ERR_NO_STORAGE_POOL: raise NotFoundError("KCHPOOL0002E", {'name': name}) else: raise def _get_storagepool_vols_num(self, pool): try: if pool.isActive(): pool.refresh(0) return pool.numOfVolumes() else: return 0 except libvirt.libvirtError as e: # If something (say a busy pool) prevents the refresh, # throwing an Exception here would prevent all pools from # displaying information -- so return None for busy kimchi_log.error("ERROR: Storage Pool get vol count: %s " % e.get_error_message()) kimchi_log.error("ERROR: Storage Pool get vol count error no: %s " % e.get_error_code()) return 0 except Exception as e: raise OperationFailed("KCHPOOL0008E", {'name': pool.name(), 'err': e.get_error_message()}) def _get_storage_source(self, pool_type, pool_xml): source = {} if pool_type not in STORAGE_SOURCES: return source for key, val in STORAGE_SOURCES[pool_type].items(): res = xpath_get_text(pool_xml, val) if len(res) == 1: source[key] = res[0] elif len(res) == 0: source[key] = "" else: source[key] = res return source def _nfs_status_online(self, pool, poolArgs=None): if not poolArgs: xml = pool.XMLDesc(0) pool_type = xpath_get_text(xml, "/pool/@type")[0] source = self._get_storage_source(pool_type, xml) poolArgs = {} poolArgs['name'] = pool.name() poolArgs['type'] = pool_type poolArgs['source'] = {'path': source['path'], 'host': source['addr']} conn = self.conn.get() poolDef = StoragePoolDef.create(poolArgs) try: poolDef.prepare(conn) return True except Exception: return False def lookup(self, name): pool = self.get_storagepool(name, self.conn) info = pool.info() autostart = True if pool.autostart() else False persistent = True if pool.isPersistent() else False xml = pool.XMLDesc(0) path = xpath_get_text(xml, "/pool/target/path")[0] pool_type = xpath_get_text(xml, "/pool/@type")[0] source = self._get_storage_source(pool_type, xml) # FIXME: nfs workaround - prevent any libvirt operation # for a nfs if the corresponding NFS server is down. if pool_type == 'netfs' and not self._nfs_status_online(pool): kimchi_log.debug("NFS pool %s is offline, reason: NFS " "server %s is unreachable.", name, source['addr']) # Mark state as '4' => inaccessible. info[0] = 4 # skip calculating volumes nr_volumes = 0 else: nr_volumes = self._get_storagepool_vols_num(pool) res = {'state': POOL_STATE_MAP[info[0]], 'path': path, 'source': source, 'type': pool_type, 'autostart': autostart, 'capacity': info[1], 'allocated': info[2], 'available': info[3], 'nr_volumes': nr_volumes, 'persistent': persistent} if not pool.isPersistent(): # Deal with deep scan generated pool try: with self.objstore as session: task_id = session.get('scanning', name) res['task_id'] = str(task_id) res['type'] = 'kimchi-iso' except NotFoundError: # User created normal pool pass return res def _update_lvm_disks(self, pool_name, disks): # check if all the disks/partitions exists in the host for disk in disks: lsblk_cmd = ['lsblk', disk] output, error, returncode = run_command(lsblk_cmd) if returncode != 0: kimchi_log.error('%s is not a valid disk/partition. Could not ' 'add it to the pool %s.', disk, pool_name) raise OperationFailed('KCHPOOL0027E', {'disk': disk, 'pool': pool_name}) # add disks to the lvm pool using vgextend + virsh refresh vgextend_cmd = ["vgextend", pool_name] vgextend_cmd += disks output, error, returncode = run_command(vgextend_cmd) if returncode != 0: msg = "Could not add disks to pool %s, error: %s" kimchi_log.error(msg, pool_name, error) raise OperationFailed('KCHPOOL0028E', {'pool': pool_name, 'err': error}) # refreshing pool state pool = self.get_storagepool(pool_name, self.conn) if pool.isActive(): pool.refresh(0) def update(self, name, params): pool = self.get_storagepool(name, self.conn) if 'autostart' in params: if params['autostart']: pool.setAutostart(1) else: pool.setAutostart(0) if 'disks' in params: # check if pool is type 'logical' xml = pool.XMLDesc(0) pool_type = xpath_get_text(xml, "/pool/@type")[0] if pool_type != 'logical': raise InvalidOperation('KCHPOOL0029E') self._update_lvm_disks(name, params['disks']) ident = pool.name() return ident.decode('utf-8') def activate(self, name): pool = self.get_storagepool(name, self.conn) # FIXME: nfs workaround - do not activate a NFS pool # if the NFS server is not reachable. xml = pool.XMLDesc(0) pool_type = xpath_get_text(xml, "/pool/@type")[0] if pool_type == 'netfs' and not self._nfs_status_online(pool): # block the user from activating the pool. source = self._get_storage_source(pool_type, xml) raise OperationFailed("KCHPOOL0032E", {'name': name, 'server': source['addr']}) return try: pool.create(0) except libvirt.libvirtError as e: raise OperationFailed("KCHPOOL0009E", {'name': name, 'err': e.get_error_message()}) def _pool_used_by_template(self, pool_name): with self.objstore as session: templates = session.get_list('template') for tmpl in templates: t_info = session.get('template', tmpl) t_pool = pool_name_from_uri(t_info['storagepool']) if t_pool == pool_name: return True return False def deactivate(self, name): if self._pool_used_by_template(name): raise InvalidOperation('KCHPOOL0034E', {'name': name}) pool = self.get_storagepool(name, self.conn) # FIXME: nfs workaround - do not try to deactivate a NFS pool # if the NFS server is not reachable. xml = pool.XMLDesc(0) pool_type = xpath_get_text(xml, "/pool/@type")[0] if pool_type == 'netfs' and not self._nfs_status_online(pool): # block the user from dactivating the pool. source = self._get_storage_source(pool_type, xml) raise OperationFailed("KCHPOOL0033E", {'name': name, 'server': source['addr']}) return try: persistent = pool.isPersistent() pool.destroy() except libvirt.libvirtError as e: raise OperationFailed("KCHPOOL0010E", {'name': name, 'err': e.get_error_message()}) # If pool was not persistent, then it was erased by destroy() and # must return nothing here, to trigger _redirect() and avoid errors if not persistent: return "" def delete(self, name): if self._pool_used_by_template(name): raise InvalidOperation('KCHPOOL0035E', {'name': name}) pool = self.get_storagepool(name, self.conn) if pool.isActive(): raise InvalidOperation("KCHPOOL0005E", {'name': name}) try: pool.undefine() except libvirt.libvirtError as e: raise OperationFailed("KCHPOOL0011E", {'name': name, 'err': e.get_error_message()}) class IsoPoolModel(object): def __init__(self, **kargs): pass def lookup(self, name): return {'state': 'active', 'type': 'kimchi-iso'} kimchi-1.5.0/src/kimchi/model/storageservers.py000066400000000000000000000055371254252253000215560ustar00rootroot00000000000000# # 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 from kimchi.exception import NotFoundError from kimchi.model.storagepools import StoragePoolModel, StoragePoolsModel # Types of remote storage servers supported STORAGE_SERVERS = ['netfs', 'iscsi'] class StorageServersModel(object): def __init__(self, **kargs): self.conn = kargs['conn'] self.pool = StoragePoolModel(**kargs) self.pools = StoragePoolsModel(**kargs) def get_list(self, _target_type=None): if not _target_type: target_type = STORAGE_SERVERS else: target_type = [_target_type] pools = self.pools.get_list() server_list = [] for pool in pools: try: pool_info = self.pool.lookup(pool) if (pool_info['type'] in target_type and pool_info['source']['addr'] not in server_list): # Avoid to add same server for multiple times # if it hosts more than one storage type server_list.append(pool_info['source']['addr']) except NotFoundError: pass return server_list class StorageServerModel(object): def __init__(self, **kargs): self.conn = kargs['conn'] self.pool = StoragePoolModel(**kargs) def lookup(self, server): conn = self.conn.get() pools = conn.listStoragePools() pools += conn.listDefinedStoragePools() for pool in pools: try: pool_info = self.pool.lookup(pool) if (pool_info['type'] in STORAGE_SERVERS and pool_info['source']['addr'] == server): info = dict(host=server) if (pool_info['type'] == "iscsi" and 'port' in pool_info['source']): info["port"] = pool_info['source']['port'] return info except NotFoundError: # Avoid inconsistent pool result because of lease between list # lookup pass raise NotFoundError("KCHSR0001E", {'server': server}) kimchi-1.5.0/src/kimchi/model/storagetargets.py000066400000000000000000000113301254252253000215220ustar00rootroot00000000000000# # 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 import libvirt import lxml.etree as ET from lxml import objectify from lxml.builder import E from kimchi.model.config import CapabilitiesModel from kimchi.model.storageservers import STORAGE_SERVERS from kimchi.utils import kimchi_log, patch_find_nfs_target class StorageTargetsModel(object): def __init__(self, **kargs): self.conn = kargs['conn'] self.caps = CapabilitiesModel(**kargs) def get_list(self, storage_server, _target_type=None, _server_port=None): target_list = list() if not _target_type: target_types = STORAGE_SERVERS else: target_types = [_target_type] for target_type in target_types: if not self.caps.nfs_target_probe and target_type == 'netfs': targets = patch_find_nfs_target(storage_server) else: xml = self._get_storage_server_spec(server=storage_server, target_type=target_type, server_port=_server_port) conn = self.conn.get() try: ret = conn.findStoragePoolSources(target_type, xml, 0) except libvirt.libvirtError as e: err = "Query storage pool source fails because of %s" kimchi_log.warning(err, e.get_error_message()) continue targets = self._parse_target_source_result(target_type, ret) target_list.extend(targets) # Get all netfs and iscsi paths in use used_paths = [] try: conn = self.conn.get() # Get all existing ISCSI and NFS pools pools = conn.listAllStoragePools( libvirt.VIR_CONNECT_LIST_STORAGE_POOLS_ISCSI | libvirt.VIR_CONNECT_LIST_STORAGE_POOLS_NETFS) for pool in pools: pool_xml = pool.XMLDesc(0) root = objectify.fromstring(pool_xml) if root.get('type') == 'netfs' and \ root.source.dir is not None: used_paths.append(root.source.dir.get('path')) elif root.get('type') == 'iscsi' and \ root.source.device is not None: used_paths.append(root.source.device.get('path')) except libvirt.libvirtError as e: err = "Query storage pool source fails because of %s" kimchi_log.warning(err, e.get_error_message()) # Filter target_list to not not show the used paths target_list = [elem for elem in target_list if elem.get('target') not in used_paths] return [dict(t) for t in set(tuple(t.items()) for t in target_list)] def _get_storage_server_spec(self, **kwargs): # Required parameters: # server: # target_type: extra_args = [] server_type = kwargs['target_type'] if server_type == 'netfs': extra_args.append(E.format(type='nfs')) else: extra_args.append(E.format(type=server_type)) host_attr = {"name": kwargs['server']} server_port = kwargs.get("server_port") if server_port is not None: host_attr['port'] = server_port obj = E.source(E.host(host_attr), *extra_args) xml = ET.tostring(obj) return xml def _parse_target_source_result(self, target_type, xml_str): root = objectify.fromstring(xml_str) ret = [] for source in root.getchildren(): if target_type == 'netfs': target_path = source.dir.get('path') type = source.format.get('type') if target_type == 'iscsi': target_path = source.device.get('path') type = target_type host_name = source.host.get('name') ret.append(dict(host=host_name, target_type=type, target=target_path)) return ret kimchi-1.5.0/src/kimchi/model/storagevolumes.py000066400000000000000000000511141254252253000215470ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2014-2015 # # 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 import contextlib import lxml.etree as ET import os import tempfile import threading import time import urllib2 from lxml.builder import E import libvirt from kimchi.config import READONLY_POOL_TYPE from kimchi.exception import InvalidOperation, InvalidParameter, IsoFormatError from kimchi.exception import MissingParameter, NotFoundError, OperationFailed from kimchi.isoinfo import IsoImage from kimchi.model.diskutils import get_disk_used_by, set_disk_used_by from kimchi.model.storagepools import StoragePoolModel from kimchi.model.tasks import TaskModel from kimchi.utils import add_task, get_next_clone_name, get_unique_file_name from kimchi.utils import kimchi_log from kimchi.xmlutils.utils import xpath_get_text VOLUME_TYPE_MAP = {0: 'file', 1: 'block', 2: 'directory', 3: 'network'} READ_CHUNK_SIZE = 1048576 # 1 MiB REQUIRE_NAME_PARAMS = ['capacity'] upload_volumes = dict() class StorageVolumesModel(object): def __init__(self, **kargs): self.conn = kargs['conn'] self.objstore = kargs['objstore'] self.task = TaskModel(**kargs) def create(self, pool_name, params): vol_source = ['url', 'capacity'] name = params.get('name') index_list = list(i for i in range(len(vol_source)) if vol_source[i] in params) if len(index_list) != 1: raise InvalidParameter("KCHVOL0018E", {'param': ",".join(vol_source)}) create_param = vol_source[index_list[0]] # Verify if the URL is valid if create_param == 'url': url = params['url'] try: urllib2.urlopen(url).close() except: raise InvalidParameter('KCHVOL0022E', {'url': url}) all_vol_names = self.get_list(pool_name) if name is None: # the methods listed in 'REQUIRE_NAME_PARAMS' cannot have # 'name' == None if create_param in REQUIRE_NAME_PARAMS: raise InvalidParameter('KCHVOL0016E') # if 'name' is omitted - except for the methods listed in # 'REQUIRE_NAME_PARAMS' - the default volume name will be the # file/URL basename. if create_param == 'url': name = os.path.basename(params['url']) else: name = 'upload-%s' % int(time.time()) name = get_unique_file_name(all_vol_names, name) params['name'] = name try: create_func = getattr(self, '_create_volume_with_%s' % create_param) except AttributeError: raise InvalidParameter("KCHVOL0019E", {'param': create_param}) pool_info = StoragePoolModel(conn=self.conn, objstore=self.objstore).lookup(pool_name) if pool_info['type'] in READONLY_POOL_TYPE: raise InvalidParameter("KCHVOL0012E", {'type': pool_info['type']}) if pool_info['state'] == 'inactive': raise InvalidParameter('KCHVOL0003E', {'pool': pool_name, 'volume': name}) if name in all_vol_names: raise InvalidParameter('KCHVOL0001E', {'name': name}) params['pool'] = pool_name targeturi = '/storagepools/%s/storagevolumes/%s' % (pool_name, name) taskid = add_task(targeturi, create_func, self.objstore, params) return self.task.lookup(taskid) def _create_volume_with_capacity(self, cb, params): pool_name = params.pop('pool') vol_xml = """ %(name)s %(allocation)s %(capacity)s """ params.setdefault('allocation', 0) params.setdefault('format', 'qcow2') name = params['name'] try: pool = StoragePoolModel.get_storagepool(pool_name, self.conn) xml = vol_xml % params except KeyError, item: raise MissingParameter("KCHVOL0004E", {'item': str(item), 'volume': name}) try: pool.createXML(xml, 0) except libvirt.libvirtError as e: raise OperationFailed("KCHVOL0007E", {'name': name, 'pool': pool, 'err': e.get_error_message()}) vol_info = StorageVolumeModel(conn=self.conn, objstore=self.objstore).lookup(pool_name, name) vol_path = vol_info['path'] set_disk_used_by(self.objstore, vol_info['path'], []) if params.get('upload', False): upload_volumes[vol_path] = {'lock': threading.Lock(), 'offset': 0, 'cb': cb} cb('ready for upload') else: cb('OK', True) def _create_volume_with_url(self, cb, params): pool_name = params['pool'] name = params['name'] url = params['url'] pool_model = StoragePoolModel(conn=self.conn, objstore=self.objstore) pool = pool_model.lookup(pool_name) if pool['type'] in ['dir', 'netfs']: file_path = os.path.join(pool['path'], name) else: file_path = tempfile.mkstemp(prefix=name)[1] with contextlib.closing(urllib2.urlopen(url)) as response: with open(file_path, 'w') as volume_file: remote_size = response.info().getheader('Content-Length', '-') downloaded_size = 0 try: while True: chunk_data = response.read(READ_CHUNK_SIZE) if not chunk_data: break volume_file.write(chunk_data) downloaded_size += len(chunk_data) cb('%s/%s' % (downloaded_size, remote_size)) except (IOError, libvirt.libvirtError) as e: if os.path.isfile(file_path): os.remove(file_path) raise OperationFailed('KCHVOL0007E', {'name': name, 'pool': pool_name, 'err': e.message}) if pool['type'] in ['dir', 'netfs']: virt_pool = StoragePoolModel.get_storagepool(pool_name, self.conn) virt_pool.refresh(0) else: def _stream_handler(stream, nbytes, fd): return fd.read(nbytes) virt_stream = virt_vol = None try: task = self.create(pool_name, {'name': name, 'format': 'raw', 'capacity': downloaded_size, 'allocation': downloaded_size}) self.task.wait(task['id']) virt_vol = StorageVolumeModel.get_storagevolume(pool_name, name, self.conn) virt_stream = self.conn.get().newStream(0) virt_vol.upload(virt_stream, 0, downloaded_size, 0) with open(file_path) as fd: virt_stream.sendAll(_stream_handler, fd) virt_stream.finish() except (IOError, libvirt.libvirtError) as e: try: if virt_stream: virt_stream.abort() if virt_vol: virt_vol.delete(0) except libvirt.libvirtError, virt_e: kimchi_log.error(virt_e.message) finally: raise OperationFailed('KCHVOL0007E', {'name': name, 'pool': pool_name, 'err': e.message}) finally: os.remove(file_path) vol_info = StorageVolumeModel(conn=self.conn, objstore=self.objstore).lookup(pool_name, name) set_disk_used_by(self.objstore, vol_info['path'], []) cb('OK', True) def get_list(self, pool_name): pool = StoragePoolModel.get_storagepool(pool_name, self.conn) if not pool.isActive(): raise InvalidOperation("KCHVOL0006E", {'pool': pool_name}) try: pool.refresh(0) return sorted(map(lambda x: x.decode('utf-8'), pool.listVolumes())) except libvirt.libvirtError as e: raise OperationFailed("KCHVOL0008E", {'pool': pool_name, 'err': e.get_error_message()}) class StorageVolumeModel(object): def __init__(self, **kargs): self.conn = kargs['conn'] self.objstore = kargs['objstore'] self.task = TaskModel(**kargs) self.storagevolumes = StorageVolumesModel(**kargs) self.storagepool = StoragePoolModel(**kargs) @staticmethod def get_storagevolume(poolname, name, conn): pool = StoragePoolModel.get_storagepool(poolname, conn) if not pool.isActive(): raise InvalidOperation("KCHVOL0006E", {'name': pool}) try: return pool.storageVolLookupByName(name.encode("utf-8")) except libvirt.libvirtError as e: if e.get_error_code() == libvirt.VIR_ERR_NO_STORAGE_VOL: raise NotFoundError("KCHVOL0002E", {'name': name, 'pool': poolname}) else: raise def lookup(self, pool, name): vol = StorageVolumeModel.get_storagevolume(pool, name, self.conn) path = vol.path() info = vol.info() xml = vol.XMLDesc(0) try: fmt = xpath_get_text(xml, "/volume/target/format/@type")[0] except IndexError: # Not all types of libvirt storage can provide volume format # infomation. When there is no format information, we assume # it's 'raw'. fmt = 'raw' iso_img = None # 'raw' volumes from 'logical' pools may actually be 'iso'; # libvirt always reports them as 'raw' pool_info = self.storagepool.lookup(pool) if pool_info['type'] == 'logical' and fmt == 'raw': try: iso_img = IsoImage(path) except IsoFormatError: # not 'iso' afterall pass else: fmt = 'iso' used_by = get_disk_used_by(self.objstore, self.conn, path) res = dict(type=VOLUME_TYPE_MAP[info[0]], capacity=info[1], allocation=info[2], path=path, used_by=used_by, format=fmt) if fmt == 'iso': if os.path.islink(path): path = os.path.join(os.path.dirname(path), os.readlink(path)) os_distro = os_version = 'unknown' try: if iso_img is None: iso_img = IsoImage(path) os_distro, os_version = iso_img.probe() bootable = True except IsoFormatError: bootable = False res.update( dict(os_distro=os_distro, os_version=os_version, path=path, bootable=bootable)) return res def wipe(self, pool, name): volume = StorageVolumeModel.get_storagevolume(pool, name, self.conn) try: volume.wipePattern(libvirt.VIR_STORAGE_VOL_WIPE_ALG_ZERO, 0) except libvirt.libvirtError as e: raise OperationFailed("KCHVOL0009E", {'name': name, 'err': e.get_error_message()}) def delete(self, pool, name): pool_info = StoragePoolModel(conn=self.conn, objstore=self.objstore).lookup(pool) if pool_info['type'] in READONLY_POOL_TYPE: raise InvalidParameter("KCHVOL0012E", {'type': pool_info['type']}) volume = StorageVolumeModel.get_storagevolume(pool, name, self.conn) try: volume.delete(0) except libvirt.libvirtError as e: raise OperationFailed("KCHVOL0010E", {'name': name, 'err': e.get_error_message()}) def resize(self, pool, name, size): volume = StorageVolumeModel.get_storagevolume(pool, name, self.conn) # When decreasing the storage volume capacity, the flag # VIR_STORAGE_VOL_RESIZE_SHRINK must be used flags = 0 if volume.info()[1] > size: # FIXME: Even using VIR_STORAGE_VOL_RESIZE_SHRINK flag it is not # possible to decrease the volume capacity due a libvirt bug # For reference: # - https://bugzilla.redhat.com/show_bug.cgi?id=1021802 flags = libvirt.VIR_STORAGE_VOL_RESIZE_SHRINK try: volume.resize(size, flags) except libvirt.libvirtError as e: raise OperationFailed("KCHVOL0011E", {'name': name, 'err': e.get_error_message()}) def clone(self, pool, name, new_pool=None, new_name=None): """Clone a storage volume. Arguments: pool -- The name of the original pool. name -- The name of the original volume. new_pool -- The name of the destination pool (optional). If omitted, the new volume will be created on the same pool as the original one. new_name -- The name of the new volume (optional). If omitted, a new value based on the original volume's name will be used. Return: A Task running the clone operation. """ # the same pool will be used if no pool is specified if new_pool is None: new_pool = pool # a default name based on the original name will be used if no name # is specified if new_name is None: base, ext = os.path.splitext(name) new_name = get_next_clone_name(self.storagevolumes.get_list(pool), base, ext) params = {'pool': pool, 'name': name, 'new_pool': new_pool, 'new_name': new_name} taskid = add_task(u'/storagepools/%s/storagevolumes/%s' % (pool, new_name), self._clone_task, self.objstore, params) return self.task.lookup(taskid) def _clone_task(self, cb, params): """Asynchronous function which performs the clone operation. This function copies all the data inside the original volume into the new one. Arguments: cb -- A callback function to signal the Task's progress. params -- A dict with the following values: "pool": The name of the original pool. "name": The name of the original volume. "new_pool": The name of the destination pool. "new_name": The name of the new volume. """ orig_pool_name = params['pool'] orig_vol_name = params['name'] new_pool_name = params['new_pool'] new_vol_name = params['new_name'] try: cb('setting up volume cloning') orig_vir_vol = StorageVolumeModel.get_storagevolume(orig_pool_name, orig_vol_name, self.conn) orig_vol = self.lookup(orig_pool_name, orig_vol_name) new_vir_pool = StoragePoolModel.get_storagepool(new_pool_name, self.conn) cb('building volume XML') root_elem = E.volume() root_elem.append(E.name(new_vol_name)) root_elem.append(E.capacity(unicode(orig_vol['capacity']), unit='bytes')) target_elem = E.target() target_elem.append(E.format(type=orig_vol['format'])) root_elem.append(target_elem) new_vol_xml = ET.tostring(root_elem, encoding='utf-8', pretty_print=True) cb('cloning volume') new_vir_pool.createXMLFrom(new_vol_xml, orig_vir_vol, 0) except (InvalidOperation, NotFoundError, libvirt.libvirtError), e: raise OperationFailed('KCHVOL0023E', {'name': orig_vol_name, 'pool': orig_pool_name, 'err': e.get_error_message()}) new_vol = self.lookup(new_pool_name, new_vol_name) cb('adding volume to the object store') set_disk_used_by(self.objstore, new_vol['path'], []) cb('OK', True) def doUpload(self, cb, vol, offset, data, data_size): try: st = self.conn.get().newStream(0) vol.upload(st, offset, data_size) st.send(data) st.finish() except Exception as e: st and st.abort() cb('', False) try: vol.delete(0) except Exception as e: pass raise OperationFailed("KCHVOL0029E", {"err": e.message}) def update(self, pool, name, params): chunk_data = params['chunk'].fullvalue() chunk_size = int(params['chunk_size']) if len(chunk_data) != chunk_size: raise OperationFailed("KCHVOL0026E") vol = StorageVolumeModel.get_storagevolume(pool, name, self.conn) vol_path = vol.path() vol_capacity = vol.info()[1] vol_data = upload_volumes.get(vol_path) if vol_data is None: raise OperationFailed("KCHVOL0027E", {"vol": vol_path}) cb = vol_data['cb'] lock = vol_data['lock'] with lock: offset = vol_data['offset'] if (offset + chunk_size) > vol_capacity: raise OperationFailed("KCHVOL0028E") cb('%s/%s' % (offset, vol_capacity)) self.doUpload(cb, vol, offset, chunk_data, chunk_size) cb('%s/%s' % (offset + chunk_size, vol_capacity)) vol_data['offset'] += chunk_size if vol_data['offset'] == vol_capacity: del upload_volumes[vol_path] cb('OK', True) class IsoVolumesModel(object): def __init__(self, **kargs): self.conn = kargs['conn'] self.storagevolume = StorageVolumeModel(**kargs) def get_list(self): iso_volumes = [] conn = self.conn.get() pools = conn.listStoragePools() pools += conn.listDefinedStoragePools() for pool_name in pools: try: pool = StoragePoolModel.get_storagepool(pool_name, self.conn) pool.refresh(0) volumes = pool.listVolumes() except Exception, e: # Skip inactive pools kimchi_log.debug("Shallow scan: skipping pool %s because of " "error: %s", (pool_name, e.message)) continue for volume in volumes: res = self.storagevolume.lookup(pool_name, volume.decode("utf-8")) if res['format'] == 'iso' and res['bootable']: res['name'] = '%s' % volume iso_volumes.append(res) return iso_volumes kimchi-1.5.0/src/kimchi/model/tasks.py000066400000000000000000000041331254252253000176140ustar00rootroot00000000000000# # 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 import time from kimchi.exception import TimeoutExpired class TasksModel(object): def __init__(self, **kargs): self.objstore = kargs['objstore'] def get_list(self): with self.objstore as session: return session.get_list('task') class TaskModel(object): def __init__(self, **kargs): self.objstore = kargs['objstore'] def lookup(self, id): with self.objstore as session: return session.get('task', str(id)) def wait(self, id, timeout=10): """Wait for a task until it stops running (successfully or due to an error). If the Task finishes its execution before , this function returns normally; otherwise an exception is raised. Parameters: id -- The Task ID. timeout -- The maximum time, in seconds, that this function should wait for the Task. If the Task runs for more than , "TimeoutExpired" is raised. """ for i in range(0, timeout): with self.objstore as session: task = session.get('task', str(id)) if task['status'] != 'running': return time.sleep(1) raise TimeoutExpired('KCHASYNC0003E', {'seconds': timeout, 'task': task['target_uri']}) kimchi-1.5.0/src/kimchi/model/templates.py000066400000000000000000000270541254252253000204740ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2014-2015 # # 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 import copy import os import stat import libvirt from kimchi.exception import InvalidOperation, InvalidParameter from kimchi.exception import NotFoundError, OperationFailed from kimchi.kvmusertests import UserTests from kimchi.model.cpuinfo import CPUInfoModel from kimchi.utils import pool_name_from_uri from kimchi.utils import probe_file_permission_as_user, run_setfacl_set_attr from kimchi.vmtemplate import VMTemplate from kimchi.xmlutils.utils import xpath_get_text class TemplatesModel(object): def __init__(self, **kargs): self.objstore = kargs['objstore'] self.conn = kargs['conn'] def create(self, params): name = params.get('name', '').strip() iso = params.get('cdrom') # check search permission if iso and iso.startswith('/') and os.path.exists(iso): st_mode = os.stat(iso).st_mode if stat.S_ISREG(st_mode) or stat.S_ISBLK(st_mode): user = UserTests().probe_user() run_setfacl_set_attr(iso, user=user) ret, excp = probe_file_permission_as_user(iso, user) if ret is False: raise InvalidParameter('KCHISO0008E', {'filename': iso, 'user': user, 'err': excp}) cpu_info = params.get('cpu_info') if cpu_info: topology = cpu_info.get('topology') # Check, even though currently only topology # is supported. if topology: sockets = topology['sockets'] cores = topology['cores'] threads = topology['threads'] if params.get('cpus') is None: params['cpus'] = sockets * cores * threads # check_topoology will raise the appropriate # exception if a topology is invalid. CPUInfoModel(conn=self.conn).\ check_topology(params['cpus'], topology) conn = self.conn.get() pool_uri = params.get(u'storagepool', '') if pool_uri: try: pool_name = pool_name_from_uri(pool_uri) pool = conn.storagePoolLookupByName(pool_name.encode("utf-8")) except Exception: raise InvalidParameter("KCHTMPL0004E", {'pool': pool_name, 'template': name}) tmp_volumes = [disk['volume'] for disk in params.get('disks', []) if 'volume' in disk] self.template_volume_validate(tmp_volumes, pool) for net_name in params.get(u'networks', []): try: conn.networkLookupByName(net_name.encode('utf-8')) except Exception: raise InvalidParameter("KCHTMPL0003E", {'network': net_name, 'template': name}) # Creates the template class with necessary information # Checkings will be done while creating this class, so any exception # will be raised here t = LibvirtVMTemplate(params, scan=True, conn=self.conn) name = params['name'] try: with self.objstore as session: if name in session.get_list('template'): raise InvalidOperation("KCHTMPL0001E", {'name': name}) session.store('template', name, t.info) except InvalidOperation: raise except Exception, e: raise OperationFailed('KCHTMPL0020E', {'err': e.message}) return name def get_list(self): with self.objstore as session: return session.get_list('template') def template_volume_validate(self, tmp_volumes, pool): kwargs = {'conn': self.conn, 'objstore': self.objstore} pool_type = xpath_get_text(pool.XMLDesc(0), "/pool/@type")[0] pool_name = unicode(pool.name(), 'utf-8') # as we discussion, we do not mix disks from 2 different types of # storage pools, for instance: we do not create a template with 2 # disks, where one comes from a SCSI pool and other is a .img in # a DIR pool. if pool_type in ['iscsi', 'scsi']: if not tmp_volumes: raise InvalidParameter("KCHTMPL0018E") storagevolumes = __import__("kimchi.model.storagevolumes", fromlist=['']) pool_volumes = storagevolumes.StorageVolumesModel( **kwargs).get_list(pool_name) vols = set(tmp_volumes) - set(pool_volumes) if vols: raise InvalidParameter("KCHTMPL0019E", {'pool': pool_name, 'volume': vols}) class TemplateModel(object): def __init__(self, **kargs): self.objstore = kargs['objstore'] self.conn = kargs['conn'] self.templates = TemplatesModel(**kargs) @staticmethod def get_template(name, objstore, conn, overrides=None): with objstore as session: params = session.get('template', name) if overrides: params.update(overrides) return LibvirtVMTemplate(params, False, conn) def lookup(self, name): t = self.get_template(name, self.objstore, self.conn) return t.validate_integrity() def clone(self, name): # set default name subfixs = [v[len(name):] for v in self.templates.get_list() if v.startswith(name)] indexs = [int(v.lstrip("-clone")) for v in subfixs if v.startswith("-clone") and v.lstrip("-clone").isdigit()] indexs.sort() index = "1" if not indexs else str(indexs[-1] + 1) clone_name = name + "-clone" + index temp = self.lookup(name) temp['name'] = clone_name ident = self.templates.create(temp) return ident def delete(self, name): try: with self.objstore as session: session.delete('template', name) except NotFoundError: raise except Exception as e: raise OperationFailed('KCHTMPL0021E', {'err': e.message}) def update(self, name, params): old_t = self.lookup(name) new_t = copy.copy(old_t) new_t.update(params) if not self._validate_updated_cpu_params(new_t): raise InvalidParameter('KCHTMPL0025E') ident = name conn = self.conn.get() pool_uri = new_t.get(u'storagepool', '') if pool_uri: try: pool_name = pool_name_from_uri(pool_uri) pool = conn.storagePoolLookupByName(pool_name.encode("utf-8")) except Exception: raise InvalidParameter("KCHTMPL0004E", {'pool': pool_name, 'template': name}) tmp_volumes = [disk['volume'] for disk in new_t.get('disks', []) if 'volume' in disk] self.templates.template_volume_validate(tmp_volumes, pool) for net_name in params.get(u'networks', []): try: conn.networkLookupByName(net_name.encode('utf-8')) except Exception: raise InvalidParameter("KCHTMPL0003E", {'network': net_name, 'template': name}) self.delete(name) try: ident = self.templates.create(new_t) except: ident = self.templates.create(old_t) raise return ident def _validate_updated_cpu_params(self, info): # Note: cpu_info is the parent of topology. cpus is vcpus vcpus = info['cpus'] cpu_info = info.get('cpu_info') # cpu_info will always be at least an empty dict topology = cpu_info.get('topology') if topology is None: return True return vcpus == topology['sockets'] * topology['cores'] * \ topology['threads'] class LibvirtVMTemplate(VMTemplate): def __init__(self, args, scan=False, conn=None): self.conn = conn VMTemplate.__init__(self, args, scan) def _storage_validate(self): pool_uri = self.info['storagepool'] pool_name = pool_name_from_uri(pool_uri) try: conn = self.conn.get() pool = conn.storagePoolLookupByName(pool_name.encode("utf-8")) except libvirt.libvirtError: raise InvalidParameter("KCHTMPL0004E", {'pool': pool_name, 'template': self.name}) if not pool.isActive(): raise InvalidParameter("KCHTMPL0005E", {'pool': pool_name, 'template': self.name}) return pool def _get_all_networks_name(self): conn = self.conn.get() return sorted(conn.listNetworks() + conn.listDefinedNetworks()) def _get_all_storagepools_name(self): conn = self.conn.get() names = conn.listStoragePools() + conn.listDefinedStoragePools() return sorted(map(lambda x: x.decode('utf-8'), names)) def _network_validate(self): names = self.info['networks'] for name in names: try: conn = self.conn.get() network = conn.networkLookupByName(name.encode('utf-8')) except libvirt.libvirtError: raise InvalidParameter("KCHTMPL0003E", {'network': name, 'template': self.name}) if not network.isActive(): raise InvalidParameter("KCHTMPL0007E", {'network': name, 'template': self.name}) def _get_storage_path(self): pool = self._storage_validate() xml = pool.XMLDesc(0) return xpath_get_text(xml, "/pool/target/path")[0] def _get_storage_type(self): pool = self._storage_validate() xml = pool.XMLDesc(0) return xpath_get_text(xml, "/pool/@type")[0] def _get_volume_path(self, pool, vol): pool = self._storage_validate() try: return pool.storageVolLookupByName(vol).path() except: raise NotFoundError("KCHVOL0002E", {'name': vol, 'pool': pool}) def fork_vm_storage(self, vm_uuid): # Provision storage: # TODO: Rebase on the storage API once upstream pool = self._storage_validate() vol_list = self.to_volume_list(vm_uuid) try: for v in vol_list: # outgoing text to libvirt, encode('utf-8') pool.createXML(v['xml'].encode('utf-8'), 0) except libvirt.libvirtError as e: raise OperationFailed("KCHVMSTOR0008E", {'error': e.message}) return vol_list kimchi-1.5.0/src/kimchi/model/users.py000066400000000000000000000053701254252253000176340ustar00rootroot00000000000000# # 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 import ldap import pwd from kimchi.config import config from kimchi.exception import NotFoundError class UsersModel(object): def __init__(self, **args): auth_type = config.get("authentication", "method") for klass in UsersModel.__subclasses__(): if auth_type == klass.auth_type: self.user = klass(**args) def get_list(self, **args): return self.user._get_list(**args) def validate(self, user): return self.user._validate(user) class PAMUsersModel(UsersModel): auth_type = 'pam' def __init__(self, **kargs): pass def _get_list(self): return [user.pw_name for user in pwd.getpwall() if user.pw_shell.rsplit("/")[-1] not in ["nologin", "false"]] def _validate(self, user): try: return user in self._get_list() except: return False class LDAPUsersModel(UsersModel): auth_type = 'ldap' def __init__(self, **kargs): pass def _get_list(self, _user_id=''): return self._get_user(_user_id) def _validate(self, user): try: self._get_user(user) return True except NotFoundError: return False def _get_user(self, _user_id): ldap_server = config.get("authentication", "ldap_server").strip('"') ldap_search_base = config.get( "authentication", "ldap_search_base").strip('"') ldap_search_filter = config.get( "authentication", "ldap_search_filter", vars={"username": _user_id.encode("utf-8")}).strip('"') connect = ldap.open(ldap_server) try: result = connect.search_s( ldap_search_base, ldap.SCOPE_SUBTREE, ldap_search_filter) if len(result) == 0: raise NotFoundError("KCHAUTH0004E", {'user_id': _user_id}) return result[0][1] except ldap.NO_SUCH_OBJECT: raise NotFoundError("KCHAUTH0004E", {'user_id': _user_id}) kimchi-1.5.0/src/kimchi/model/utils.py000066400000000000000000000130061254252253000176260ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2014-2015 # # 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 import libvirt from lxml import etree, objectify from lxml.builder import E, ElementMaker from kimchi.exception import OperationFailed KIMCHI_META_URL = "https://github.com/kimchi-project/kimchi" KIMCHI_NAMESPACE = "kimchi" def get_vm_name(vm_name, t_name, name_list): if vm_name: return vm_name for i in xrange(1, 1000): # VM will have templace name, but without slashes vm_name = "%s-vm-%i" % (t_name.replace('/', '-'), i) if vm_name not in name_list: return vm_name raise OperationFailed("KCHUTILS0003E") def get_vm_config_flag(dom, mode="persistent"): # libvirt.VIR_DOMAIN_AFFECT_CURRENT is 0 # VIR_DOMAIN_AFFECT_LIVE is 1, VIR_DOMAIN_AFFECT_CONFIG is 2 flag = {"live": libvirt.VIR_DOMAIN_AFFECT_LIVE, "persistent": libvirt.VIR_DOMAIN_AFFECT_CONFIG, "current": libvirt.VIR_DOMAIN_AFFECT_CURRENT, "all": libvirt.VIR_DOMAIN_AFFECT_CONFIG + libvirt.VIR_DOMAIN_AFFECT_LIVE if dom.isActive() and dom.isPersistent() else libvirt.VIR_DOMAIN_AFFECT_CURRENT} return flag[mode] # avoid duplicate codes def update_node(root, node): old_node = root.find(node.tag) (root.replace(old_node, node) if old_node is not None else root.append(node)) return root def _kimchi_set_metadata_node(dom, node): # some other tools will not let libvirt create a persistent # configuration, raise exception. if not dom.isPersistent(): msg = 'The VM has not a persistent configuration' raise OperationFailed("KCHVM0030E", {'name': dom.name(), "err": msg}) xml = dom.XMLDesc(libvirt.VIR_DOMAIN_XML_INACTIVE) root = etree.fromstring(xml) kimchi = root.find("metadata/{%s}kimchi" % KIMCHI_META_URL) EM = ElementMaker(namespace=KIMCHI_META_URL, nsmap={KIMCHI_NAMESPACE: KIMCHI_META_URL}) kimchi = EM("kimchi") if kimchi is None else kimchi update_node(kimchi, node) metadata = root.find("metadata") metadata = E.metadata() if metadata is None else metadata update_node(metadata, kimchi) update_node(root, metadata) dom.connect().defineXML(etree.tostring(root)) def libvirt_get_kimchi_metadata_node(dom, mode="current"): if not metadata_exists(dom): return None try: xml = dom.metadata(libvirt.VIR_DOMAIN_METADATA_ELEMENT, KIMCHI_META_URL, flags=get_vm_config_flag(dom, mode)) return etree.fromstring(xml) except libvirt.libvirtError: return None def set_metadata_node(dom, node, metadata_support, mode="all"): if metadata_support: kimchi = libvirt_get_kimchi_metadata_node(dom, mode) kimchi = E.metadata(E.kimchi()) if kimchi is None else kimchi update_node(kimchi, node) kimchi_xml = etree.tostring(kimchi) # From libvirt doc, Passing None for @metadata says to remove that # element from the domain XML (passing the empty string leaves the # element present). Do not support remove the old metadata. dom.setMetadata(libvirt.VIR_DOMAIN_METADATA_ELEMENT, kimchi_xml, KIMCHI_NAMESPACE, KIMCHI_META_URL, flags=get_vm_config_flag(dom, mode)) else: # FIXME remove this code when all distro libvirt supports metadata # element _kimchi_set_metadata_node(dom, node) def _kimchi_get_metadata_node(dom, tag): # some other tools will not let libvirt create a persistent # configuration, just return empty if not dom.isPersistent(): return None xml = dom.XMLDesc(libvirt.VIR_DOMAIN_XML_INACTIVE) root = etree.fromstring(xml) kimchi = root.find("metadata/{%s}kimchi" % KIMCHI_META_URL) # remove the "kimchi" prefix of xml if kimchi is not None: for elem in kimchi.getiterator(): if not hasattr(elem.tag, 'find'): continue i = elem.tag.find('}') if i >= 0: elem.tag = elem.tag[i+1:] objectify.deannotate(kimchi) etree.cleanup_namespaces(kimchi) return kimchi return None def get_metadata_node(dom, tag, metadata_support, mode="current"): if metadata_support: kimchi = libvirt_get_kimchi_metadata_node(dom, mode) else: # FIXME remove this code when all distro libvirt supports metadata # element kimchi = _kimchi_get_metadata_node(dom, tag) if kimchi is not None: node = kimchi.find(tag) if node is not None: return etree.tostring(node) return "" def metadata_exists(dom): xml = dom.XMLDesc(libvirt.VIR_DOMAIN_XML_INACTIVE) root = etree.fromstring(xml) if root.find("metadata") is None: return False return True kimchi-1.5.0/src/kimchi/model/vmhostdevs.py000066400000000000000000000310121254252253000206650ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2014-2015 # # 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 import glob import os import libvirt from lxml import etree, objectify from lxml.builder import E from kimchi.exception import InvalidOperation, InvalidParameter, NotFoundError from kimchi.exception import OperationFailed from kimchi.model.config import CapabilitiesModel from kimchi.model.host import DeviceModel, DevicesModel from kimchi.model.utils import get_vm_config_flag from kimchi.model.vms import DOM_STATE_MAP, VMModel from kimchi.rollbackcontext import RollbackContext from kimchi.utils import kimchi_log, run_command import platform class VMHostDevsModel(object): def __init__(self, **kargs): self.conn = kargs['conn'] self.caps = CapabilitiesModel(**kargs) def get_list(self, vmid): dom = VMModel.get_vm(vmid, self.conn) xmlstr = dom.XMLDesc(0) root = objectify.fromstring(xmlstr) try: hostdev = root.devices.hostdev except AttributeError: return [] return [self._deduce_dev_name(e) for e in hostdev] @staticmethod def _toint(num_str): if num_str.startswith('0x'): return int(num_str, 16) elif num_str.startswith('0'): return int(num_str, 8) else: return int(num_str) def _deduce_dev_name(self, e): return getattr(self, '_deduce_dev_name_%s' % e.attrib['type'])(e) def _deduce_dev_name_pci(self, e): attrib = {} for field in ('domain', 'bus', 'slot', 'function'): attrib[field] = self._toint(e.source.address.attrib[field]) return 'pci_%(domain)04x_%(bus)02x_%(slot)02x_%(function)x' % attrib def _deduce_dev_name_scsi(self, e): attrib = {} for field in ('bus', 'target', 'unit'): attrib[field] = self._toint(e.source.address.attrib[field]) attrib['host'] = self._toint( e.source.adapter.attrib['name'][len('scsi_host'):]) return 'scsi_%(host)d_%(bus)d_%(target)d_%(unit)d' % attrib def _deduce_dev_name_usb(self, e): dev_names = DevicesModel(conn=self.conn).get_list(_cap='usb_device') usb_infos = [DeviceModel(conn=self.conn).lookup(dev_name) for dev_name in dev_names] unknown_dev = None try: evendor = self._toint(e.source.vendor.attrib['id']) eproduct = self._toint(e.source.product.attrib['id']) except AttributeError: evendor = 0 eproduct = 0 else: unknown_dev = 'usb_vendor_%s_product_%s' % (evendor, eproduct) try: ebus = self._toint(e.source.address.attrib['bus']) edevice = self._toint(e.source.address.attrib['device']) except AttributeError: ebus = -1 edevice = -1 else: unknown_dev = 'usb_bus_%s_device_%s' % (ebus, edevice) for usb_info in usb_infos: ivendor = self._toint(usb_info['vendor']['id']) iproduct = self._toint(usb_info['product']['id']) if evendor == ivendor and eproduct == iproduct: return usb_info['name'] ibus = usb_info['bus'] idevice = usb_info['device'] if ebus == ibus and edevice == idevice: return usb_info['name'] return unknown_dev def _passthrough_device_validate(self, dev_name): eligible_dev_names = \ DevicesModel(conn=self.conn).get_list(_passthrough='true') if dev_name not in eligible_dev_names: raise InvalidParameter('KCHVMHDEV0002E', {'dev_name': dev_name}) def create(self, vmid, params): dev_name = params['name'] self._passthrough_device_validate(dev_name) dev_info = DeviceModel(conn=self.conn).lookup(dev_name) with RollbackContext() as rollback: try: dev = self.conn.get().nodeDeviceLookupByName(dev_name) dev.dettach() except Exception: raise OperationFailed('KCHVMHDEV0005E', {'name': dev_name}) else: rollback.prependDefer(dev.reAttach) attach_device = getattr( self, '_attach_%s_device' % dev_info['device_type']) info = attach_device(vmid, dev_info) rollback.commitAll() return info def _get_pci_device_xml(self, dev_info): if 'detach_driver' not in dev_info: dev_info['detach_driver'] = 'kvm' source = E.source(E.address(domain=str(dev_info['domain']), bus=str(dev_info['bus']), slot=str(dev_info['slot']), function=str(dev_info['function']))) driver = E.driver(name=dev_info['detach_driver']) host_dev = E.hostdev(source, driver, mode='subsystem', type='pci', managed='yes') return etree.tostring(host_dev) @staticmethod def _validate_pci_passthrough_env(): # Linux kernel < 3.5 doesn't provide /sys/kernel/iommu_groups if os.path.isdir('/sys/kernel/iommu_groups'): if not glob.glob('/sys/kernel/iommu_groups/*'): raise InvalidOperation("KCHVMHDEV0003E") # Enable virt_use_sysfs on RHEL6 and older distributions # In recent Fedora, there is no virt_use_sysfs. out, err, rc = run_command(['getsebool', 'virt_use_sysfs']) if rc == 0 and out.rstrip('\n') != "virt_use_sysfs --> on": out, err, rc = run_command(['setsebool', '-P', 'virt_use_sysfs=on']) if rc != 0: kimchi_log.warning("Unable to turn on sebool virt_use_sysfs") def _attach_pci_device(self, vmid, dev_info): self._validate_pci_passthrough_env() dom = VMModel.get_vm(vmid, self.conn) # Due to libvirt limitation, we don't support live assigne device to # vfio driver. driver = ('vfio' if DOM_STATE_MAP[dom.info()[0]] == "shutoff" and self.caps.kernel_vfio else 'kvm') # on powerkvm systems it must be vfio driver. distro, _, _ = platform.linux_distribution() if distro == 'IBM_PowerKVM': driver = 'vfio' # Attach all PCI devices in the same IOMMU group dev_model = DeviceModel(conn=self.conn) devs_model = DevicesModel(conn=self.conn) affected_names = devs_model.get_list( _passthrough_affected_by=dev_info['name']) passthrough_names = devs_model.get_list( _cap='pci', _passthrough='true') group_names = list(set(affected_names) & set(passthrough_names)) pci_infos = [dev_model.lookup(dev_name) for dev_name in group_names] pci_infos.append(dev_info) device_flags = get_vm_config_flag(dom, mode='all') with RollbackContext() as rollback: for pci_info in pci_infos: pci_info['detach_driver'] = driver xmlstr = self._get_pci_device_xml(pci_info) try: dom.attachDeviceFlags(xmlstr, device_flags) except libvirt.libvirtError: kimchi_log.error( 'Failed to attach host device %s to VM %s: \n%s', pci_info['name'], vmid, xmlstr) raise rollback.prependDefer(dom.detachDeviceFlags, xmlstr, device_flags) rollback.commitAll() return dev_info['name'] def _get_scsi_device_xml(self, dev_info): adapter = E.adapter(name=('scsi_host%s' % dev_info['host'])) address = E.address(type='scsi', bus=str(dev_info['bus']), target=str(dev_info['target']), unit=str(dev_info['lun'])) host_dev = E.hostdev(E.source(adapter, address), mode='subsystem', type='scsi', sgio='unfiltered') return etree.tostring(host_dev) def _attach_scsi_device(self, vmid, dev_info): xmlstr = self._get_scsi_device_xml(dev_info) dom = VMModel.get_vm(vmid, self.conn) dom.attachDeviceFlags(xmlstr, get_vm_config_flag(dom, mode='all')) return dev_info['name'] def _get_usb_device_xml(self, dev_info): source = E.source( E.vendor(id=dev_info['vendor']['id']), E.product(id=dev_info['product']['id']), E.address(bus=str(dev_info['bus']), device=str(dev_info['device'])), startupPolicy='optional') host_dev = E.hostdev(source, mode='subsystem', ype='usb', managed='yes') return etree.tostring(host_dev) def _attach_usb_device(self, vmid, dev_info): xmlstr = self._get_usb_device_xml(dev_info) dom = VMModel.get_vm(vmid, self.conn) dom.attachDeviceFlags(xmlstr, get_vm_config_flag(dom, mode='all')) return dev_info['name'] class VMHostDevModel(object): def __init__(self, **kargs): self.conn = kargs['conn'] def lookup(self, vmid, dev_name): dom = VMModel.get_vm(vmid, self.conn) xmlstr = dom.XMLDesc(0) root = objectify.fromstring(xmlstr) try: hostdev = root.devices.hostdev except AttributeError: raise NotFoundError('KCHVMHDEV0001E', {'vmid': vmid, 'dev_name': dev_name}) devsmodel = VMHostDevsModel(conn=self.conn) for e in hostdev: deduced_name = devsmodel._deduce_dev_name(e) if deduced_name == dev_name: return {'name': dev_name, 'type': e.attrib['type']} raise NotFoundError('KCHVMHDEV0001E', {'vmid': vmid, 'dev_name': dev_name}) def delete(self, vmid, dev_name): dom = VMModel.get_vm(vmid, self.conn) xmlstr = dom.XMLDesc(0) root = objectify.fromstring(xmlstr) try: hostdev = root.devices.hostdev except AttributeError: raise NotFoundError('KCHVMHDEV0001E', {'vmid': vmid, 'dev_name': dev_name}) devsmodel = VMHostDevsModel(conn=self.conn) pci_devs = [(devsmodel._deduce_dev_name(e), e) for e in hostdev if e.attrib['type'] == 'pci'] for e in hostdev: if devsmodel._deduce_dev_name(e) == 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) break else: raise NotFoundError('KCHVMHDEV0001E', {'vmid': vmid, 'dev_name': dev_name}) def _delete_affected_pci_devices(self, dom, dev_name, pci_devs): dev_model = DeviceModel(conn=self.conn) try: dev_model.lookup(dev_name) except NotFoundError: return affected_names = set( DevicesModel( conn=self.conn).get_list(_passthrough_affected_by=dev_name)) for pci_name, e in pci_devs: if pci_name in affected_names: xmlstr = etree.tostring(e) dom.detachDeviceFlags( xmlstr, get_vm_config_flag(dom, mode='all')) class VMHoldersModel(object): def __init__(self, **kargs): self.conn = kargs['conn'] def get_list(self, device_id): devsmodel = VMHostDevsModel(conn=self.conn) conn = self.conn.get() doms = conn.listAllDomains(0) res = [] for dom in doms: dom_name = dom.name() if device_id in devsmodel.get_list(dom_name): state = DOM_STATE_MAP[dom.info()[0]] res.append({"name": dom_name, "state": state}) return res kimchi-1.5.0/src/kimchi/model/vmifaces.py000066400000000000000000000140701254252253000202650ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2014-2015 # # 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 import random import libvirt from lxml import etree, objectify from kimchi.exception import InvalidParameter, MissingParameter from kimchi.exception import NotFoundError, InvalidOperation from kimchi.model.config import CapabilitiesModel from kimchi.model.vms import DOM_STATE_MAP, VMModel from kimchi.xmlutils.interface import get_iface_xml class VMIfacesModel(object): def __init__(self, **kargs): self.conn = kargs['conn'] self.caps = CapabilitiesModel(**kargs) def get_list(self, vm): macs = [] for iface in self.get_vmifaces(vm, self.conn): macs.append(iface.mac.get('address')) return macs def create(self, vm, params): conn = self.conn.get() networks = conn.listNetworks() + conn.listDefinedNetworks() networks = map(lambda x: x.decode('utf-8'), networks) if params['type'] == 'network': network = params.get("network") if network is None: raise MissingParameter('KCHVMIF0007E') if network not in networks: raise InvalidParameter('KCHVMIF0002E', {'name': vm, 'network': network}) macs = (iface.mac.get('address') for iface in self.get_vmifaces(vm, self.conn)) # user defined customized mac address if 'mac' in params and params['mac']: # make sure it is unique if params['mac'] in macs: raise InvalidParameter('KCHVMIF0009E', {'name': vm, 'mac': params['mac']}) # otherwise choose a random mac address else: while True: params['mac'] = VMIfacesModel.random_mac() if params['mac'] not in macs: break dom = VMModel.get_vm(vm, self.conn) os_data = VMModel.vm_get_os_metadata(dom, self.caps.metadata_support) os_version, os_distro = os_data xml = get_iface_xml(params, conn.getInfo()[0], os_distro, os_version) flags = 0 if dom.isPersistent(): flags |= libvirt.VIR_DOMAIN_AFFECT_CONFIG if DOM_STATE_MAP[dom.info()[0]] != "shutoff": flags |= libvirt.VIR_DOMAIN_AFFECT_LIVE dom.attachDeviceFlags(xml, flags) return params['mac'] @staticmethod def get_vmifaces(vm, conn): dom = VMModel.get_vm(vm, conn) xml = dom.XMLDesc(0) root = objectify.fromstring(xml) return root.devices.findall("interface") @staticmethod def random_mac(): mac = [0x52, 0x54, 0x00, random.randint(0x00, 0x7f), random.randint(0x00, 0xff), random.randint(0x00, 0xff)] return ':'.join(map(lambda x: u'%02x' % x, mac)) class VMIfaceModel(object): def __init__(self, **kargs): self.conn = kargs['conn'] def _get_vmiface(self, vm, mac): ifaces = VMIfacesModel.get_vmifaces(vm, self.conn) for iface in ifaces: if iface.mac.get('address') == mac: return iface return None def lookup(self, vm, mac): info = {} iface = self._get_vmiface(vm, mac) if iface is None: raise NotFoundError("KCHVMIF0001E", {'name': vm, 'iface': mac}) info['type'] = iface.attrib['type'] info['mac'] = iface.mac.get('address') if iface.find("model") is not None: info['model'] = iface.model.get('type') if info['type'] == 'network': info['network'] = iface.source.get('network') if info['type'] == 'bridge': info['bridge'] = iface.source.get('bridge') return info def delete(self, vm, mac): dom = VMModel.get_vm(vm, self.conn) iface = self._get_vmiface(vm, mac) if iface is None: raise NotFoundError("KCHVMIF0001E", {'name': vm, 'iface': mac}) flags = 0 if dom.isPersistent(): flags |= libvirt.VIR_DOMAIN_AFFECT_CONFIG if DOM_STATE_MAP[dom.info()[0]] != "shutoff": flags |= libvirt.VIR_DOMAIN_AFFECT_LIVE dom.detachDeviceFlags(etree.tostring(iface), flags) def update(self, vm, mac, params): dom = VMModel.get_vm(vm, self.conn) iface = self._get_vmiface(vm, mac) if iface is None: raise NotFoundError("KCHVMIF0001E", {'name': vm, 'iface': mac}) # cannot change mac address in a running system if DOM_STATE_MAP[dom.info()[0]] != "shutoff": raise InvalidOperation('KCHVMIF0011E') # mac address is a required parameter if 'mac' not in params: raise MissingParameter('KCHVMIF0008E') # new mac address must be unique if self._get_vmiface(vm, params['mac']) is not None: raise InvalidParameter('KCHVMIF0009E', {'name': vm, 'mac': params['mac']}) flags = 0 if dom.isPersistent(): flags |= libvirt.VIR_DOMAIN_AFFECT_CONFIG # remove the current nic xml = etree.tostring(iface) dom.detachDeviceFlags(xml, flags=flags) # add the nic with the desired mac address iface.mac.attrib['address'] = params['mac'] xml = etree.tostring(iface) dom.attachDeviceFlags(xml, flags=flags) return [vm, params['mac']] kimchi-1.5.0/src/kimchi/model/vms.py000066400000000000000000001454561254252253000173120ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2014-2015 # # 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 from lxml.builder import E import lxml.etree as ET from lxml import etree, objectify import os import random import string import time import uuid from xml.etree import ElementTree import libvirt from kimchi import model, vnc from kimchi.config import READONLY_POOL_TYPE, config from kimchi.exception import InvalidOperation, InvalidParameter from kimchi.exception import NotFoundError, OperationFailed from kimchi.kvmusertests import UserTests from kimchi.model.config import CapabilitiesModel from kimchi.model.tasks import TaskModel from kimchi.model.templates import TemplateModel from kimchi.model.utils import get_vm_name from kimchi.model.utils import get_metadata_node from kimchi.model.utils import set_metadata_node from kimchi.rollbackcontext import RollbackContext from kimchi.screenshot import VMScreenshot from kimchi.utils import add_task, convert_data_size, get_next_clone_name from kimchi.utils import import_class, kimchi_log, run_setfacl_set_attr from kimchi.utils import template_name_from_uri from kimchi.xmlutils.cpu import get_cpu_xml, get_numa_xml from kimchi.xmlutils.utils import xpath_get_text, xml_item_update from kimchi.xmlutils.utils import dictize DOM_STATE_MAP = {0: 'nostate', 1: 'running', 2: 'blocked', 3: 'paused', 4: 'shutdown', 5: 'shutoff', 6: 'crashed', 7: 'pmsuspended'} VM_STATIC_UPDATE_PARAMS = {'name': './name', 'cpus': './vcpu'} VM_LIVE_UPDATE_PARAMS = {} XPATH_DOMAIN_DISK = "/domain/devices/disk[@device='disk']/source/@file" XPATH_DOMAIN_DISK_BY_FILE = "./devices/disk[@device='disk']/source[@file='%s']" XPATH_DOMAIN_NAME = '/domain/name' XPATH_DOMAIN_MAC = "/domain/devices/interface[@type='network']/mac/@address" XPATH_DOMAIN_MAC_BY_ADDRESS = "./devices/interface[@type='network']/"\ "mac[@address='%s']" XPATH_DOMAIN_MEMORY = '/domain/memory' XPATH_DOMAIN_MEMORY_UNIT = '/domain/memory/@unit' XPATH_DOMAIN_UUID = '/domain/uuid' XPATH_NUMA_CELL = './cpu/numa/cell' class VMsModel(object): def __init__(self, **kargs): self.conn = kargs['conn'] self.objstore = kargs['objstore'] self.caps = CapabilitiesModel(**kargs) self.task = TaskModel(**kargs) def create(self, params): t_name = template_name_from_uri(params['template']) vm_list = self.get_list() name = get_vm_name(params.get('name'), t_name, vm_list) # incoming text, from js json, is unicode, do not need decode if name in vm_list: raise InvalidOperation("KCHVM0001E", {'name': name}) vm_overrides = dict() pool_uri = params.get('storagepool') if pool_uri: vm_overrides['storagepool'] = pool_uri vm_overrides['fc_host_support'] = self.caps.fc_host_support t = TemplateModel.get_template(t_name, self.objstore, self.conn, vm_overrides) if not self.caps.qemu_stream and t.info.get('iso_stream', False): raise InvalidOperation("KCHVM0005E") t.validate() data = {'name': name, 'template': t, 'graphics': params.get('graphics', {})} taskid = add_task(u'/vms/%s' % name, self._create_task, self.objstore, data) return self.task.lookup(taskid) def _create_task(self, cb, params): """ params: A dict with the following values: - vm_uuid: The UUID of the VM being created - template: The template being used to create the VM - name: The name for the new VM """ vm_uuid = str(uuid.uuid4()) t = params['template'] name = params['name'] conn = self.conn.get() cb('Storing VM icon') # Store the icon for displaying later icon = t.info.get('icon') if icon: try: with self.objstore as session: session.store('vm', vm_uuid, {'icon': icon}) except Exception as e: # It is possible to continue Kimchi executions without store # vm icon info kimchi_log.error('Error trying to update database with guest ' 'icon information due error: %s', e.message) # If storagepool is SCSI, volumes will be LUNs and must be passed by # the user from UI or manually. cb('Provisioning storage for new VM') vol_list = [] if t._get_storage_type() not in ["iscsi", "scsi"]: vol_list = t.fork_vm_storage(vm_uuid) graphics = params.get('graphics', {}) stream_protocols = self.caps.libvirt_stream_protocols xml = t.to_vm_xml(name, vm_uuid, libvirt_stream_protocols=stream_protocols, graphics=graphics, volumes=vol_list) cb('Defining new VM') try: conn.defineXML(xml.encode('utf-8')) except libvirt.libvirtError as e: if t._get_storage_type() not in READONLY_POOL_TYPE: for v in vol_list: vol = conn.storageVolLookupByPath(v['path']) vol.delete(0) raise OperationFailed("KCHVM0007E", {'name': name, 'err': e.get_error_message()}) cb('Updating VM metadata') VMModel.vm_update_os_metadata(VMModel.get_vm(name, self.conn), t.info, self.caps.metadata_support) cb('OK', True) def get_list(self): return VMsModel.get_vms(self.conn) @staticmethod def get_vms(conn): conn_ = conn.get() names = [dom.name().decode('utf-8') for dom in conn_.listAllDomains(0)] names = sorted(names, key=unicode.lower) return names class VMModel(object): def __init__(self, **kargs): self.conn = kargs['conn'] self.objstore = kargs['objstore'] self.caps = CapabilitiesModel(**kargs) self.vmscreenshot = VMScreenshotModel(**kargs) self.users = import_class('kimchi.model.users.UsersModel')(**kargs) self.groups = import_class('kimchi.model.groups.GroupsModel')(**kargs) self.vms = VMsModel(**kargs) self.task = TaskModel(**kargs) self.storagepool = model.storagepools.StoragePoolModel(**kargs) self.storagevolume = model.storagevolumes.StorageVolumeModel(**kargs) self.storagevolumes = model.storagevolumes.StorageVolumesModel(**kargs) cls = import_class('kimchi.model.vmsnapshots.VMSnapshotModel') self.vmsnapshot = cls(**kargs) cls = import_class('kimchi.model.vmsnapshots.VMSnapshotsModel') self.vmsnapshots = cls(**kargs) self.stats = {} def update(self, name, params): dom = self.get_vm(name, self.conn) dom = self._static_vm_update(dom, params) self._live_vm_update(dom, params) return dom.name().decode('utf-8') def clone(self, name): """Clone a virtual machine based on an existing one. The new virtual machine will have the exact same configuration as the original VM, except for the name, UUID, MAC addresses and disks. The name will have the form "-clone-", with starting at 1; the UUID will be generated randomly; the MAC addresses will be generated randomly with no conflicts within the original and the new VM; and the disks will be new volumes [mostly] on the same storage pool, with the same content as the original disks. The storage pool 'default' will always be used when cloning SCSI and iSCSI disks and when the original storage pool cannot hold the new volume. An exception will be raised if the virtual machine is not shutoff, if there is no available space to copy a new volume to the storage pool 'default' (when there was also no space to copy it to the original storage pool) and if one of the virtual machine's disks belong to a storage pool not supported by Kimchi. Parameters: name -- The name of the existing virtual machine to be cloned. Return: A Task running the clone operation. """ name = name.decode('utf-8') # VM must be shutoff in order to clone it info = self.lookup(name) if info['state'] != u'shutoff': raise InvalidParameter('KCHVM0033E', {'name': name}) # the new VM's name will be used as the Task's 'target_uri' so it needs # to be defined now. vms_being_created = [] # lookup names of VMs being created right now with self.objstore as session: task_names = session.get_list('task') for tn in task_names: t = session.get('task', tn) if t['target_uri'].startswith('/vms/'): uri_name = t['target_uri'][5:] # 5 = len('/vms/') vms_being_created.append(uri_name) current_vm_names = self.vms.get_list() + vms_being_created new_name = get_next_clone_name(current_vm_names, name) # create a task with the actual clone function taskid = add_task(u'/vms/%s/clone' % new_name, self._clone_task, self.objstore, {'name': name, 'new_name': new_name}) return self.task.lookup(taskid) def _clone_task(self, cb, params): """Asynchronous function which performs the clone operation. Parameters: cb -- A callback function to signal the Task's progress. params -- A dict with the following values: "name": the name of the original VM. "new_name": the name of the new VM. """ name = params['name'] new_name = params['new_name'] vir_conn = self.conn.get() # fetch base XML cb('reading source VM XML') try: vir_dom = vir_conn.lookupByName(name) flags = libvirt.VIR_DOMAIN_XML_SECURE xml = vir_dom.XMLDesc(flags).decode('utf-8') except libvirt.libvirtError, e: raise OperationFailed('KCHVM0035E', {'name': name, 'err': e.message}) # update UUID cb('updating VM UUID') old_uuid = xpath_get_text(xml, XPATH_DOMAIN_UUID)[0] new_uuid = unicode(uuid.uuid4()) xml = xml_item_update(xml, './uuid', new_uuid) # update MAC addresses cb('updating VM MAC addresses') xml = self._clone_update_mac_addresses(xml) with RollbackContext() as rollback: # copy disks cb('copying VM disks') xml = self._clone_update_disks(xml, rollback) # update objstore entry cb('updating object store') self._clone_update_objstore(old_uuid, new_uuid, rollback) # update name cb('updating VM name') xml = xml_item_update(xml, './name', new_name) # create new guest cb('defining new VM') try: vir_conn.defineXML(xml) except libvirt.libvirtError, e: raise OperationFailed('KCHVM0035E', {'name': name, 'err': e.message}) rollback.commitAll() cb('OK', True) @staticmethod def _clone_update_mac_addresses(xml): """Update the MAC addresses with new values in the XML descriptor of a cloning domain. The new MAC addresses will be generated randomly, and their values are guaranteed to be distinct from the ones in the original VM. Arguments: xml -- The XML descriptor of the original domain. Return: The XML descriptor with the new MAC addresses instead of the old ones. """ old_macs = xpath_get_text(xml, XPATH_DOMAIN_MAC) new_macs = [] for mac in old_macs: while True: new_mac = model.vmifaces.VMIfacesModel.random_mac() # make sure the new MAC doesn't conflict with the original VM # and with the new values on the new VM. if new_mac not in (old_macs + new_macs): new_macs.append(new_mac) break xml = xml_item_update(xml, XPATH_DOMAIN_MAC_BY_ADDRESS % mac, new_mac, 'address') return xml def _clone_update_disks(self, xml, rollback): """Clone disks from a virtual machine. The disks are copied as new volumes and the new VM's XML is updated accordingly. Arguments: xml -- The XML descriptor of the original VM + new value for "/domain/uuid". rollback -- A rollback context so the new volumes can be removed if an error occurs during the cloning operation. Return: The XML descriptor with the new disk paths instead of the old ones. """ # the UUID will be used to create the disk paths uuid = xpath_get_text(xml, XPATH_DOMAIN_UUID)[0] all_paths = xpath_get_text(xml, XPATH_DOMAIN_DISK) vir_conn = self.conn.get() def _delete_disk_from_objstore(path): with self.objstore as session: session.delete('storagevolume', path) domain_name = xpath_get_text(xml, XPATH_DOMAIN_NAME)[0] for i, path in enumerate(all_paths): try: vir_orig_vol = vir_conn.storageVolLookupByPath(path) vir_pool = vir_orig_vol.storagePoolLookupByVolume() orig_pool_name = vir_pool.name().decode('utf-8') orig_vol_name = vir_orig_vol.name().decode('utf-8') except libvirt.libvirtError, e: raise OperationFailed('KCHVM0035E', {'name': domain_name, 'err': e.message}) orig_pool = self.storagepool.lookup(orig_pool_name) orig_vol = self.storagevolume.lookup(orig_pool_name, orig_vol_name) new_pool_name = orig_pool_name new_pool = orig_pool if orig_pool['type'] in ['dir', 'netfs', 'logical']: # if a volume in a pool 'dir', 'netfs' or 'logical' cannot hold # a new volume with the same size, the pool 'default' should # be used if orig_vol['capacity'] > orig_pool['available']: kimchi_log.warning('storage pool \'%s\' doesn\'t have ' 'enough free space to store image ' '\'%s\'; falling back to \'default\'', orig_pool_name, path) new_pool_name = u'default' new_pool = self.storagepool.lookup(u'default') # ...and if even the pool 'default' cannot hold a new # volume, raise an exception if orig_vol['capacity'] > new_pool['available']: domain_name = xpath_get_text(xml, XPATH_DOMAIN_NAME)[0] raise InvalidOperation('KCHVM0034E', {'name': domain_name}) elif orig_pool['type'] in ['scsi', 'iscsi']: # SCSI and iSCSI always fall back to the storage pool 'default' kimchi_log.warning('cannot create new volume for clone in ' 'storage pool \'%s\'; falling back to ' '\'default\'', orig_pool_name) new_pool_name = u'default' new_pool = self.storagepool.lookup(u'default') # if the pool 'default' cannot hold a new volume, raise # an exception if orig_vol['capacity'] > new_pool['available']: domain_name = xpath_get_text(xml, XPATH_DOMAIN_NAME)[0] raise InvalidOperation('KCHVM0034E', {'name': domain_name}) else: # unexpected storage pool type raise InvalidOperation('KCHPOOL0014E', {'type': orig_pool['type']}) # new volume name: -. # e.g. 1234-5678-9012-3456-0.img ext = os.path.splitext(path)[1] new_vol_name = u'%s-%d%s' % (uuid, i, ext) task = self.storagevolume.clone(orig_pool_name, orig_vol_name, new_name=new_vol_name) self.task.wait(task['id'], 3600) # 1 h # get the new volume path and update the XML descriptor new_vol = self.storagevolume.lookup(new_pool_name, new_vol_name) xml = xml_item_update(xml, XPATH_DOMAIN_DISK_BY_FILE % path, new_vol['path'], 'file') # set the new disk's used_by with self.objstore as session: session.store('storagevolume', new_vol['path'], {'used_by': [domain_name]}) rollback.prependDefer(_delete_disk_from_objstore, new_vol['path']) # remove the new volume should an error occur later rollback.prependDefer(self.storagevolume.delete, new_pool_name, new_vol_name) return xml def _clone_update_objstore(self, old_uuid, new_uuid, rollback): """Update Kimchi's object store with the cloning VM. Arguments: old_uuid -- The UUID of the original VM. new_uuid -- The UUID of the new, clonning VM. rollback -- A rollback context so the object store entry can be removed if an error occurs during the cloning operation. """ with self.objstore as session: try: vm = session.get('vm', old_uuid) icon = vm['icon'] session.store('vm', new_uuid, {'icon': icon}) except NotFoundError: # if we cannot find an object store entry for the original VM, # don't store one with an empty value. pass else: # we need to define a custom function to prepend to the # rollback context because the object store session needs to be # opened and closed correctly (i.e. "prependDefer" only # accepts one command at a time but we need more than one to # handle an object store). def _rollback_objstore(): with self.objstore as session_rb: session_rb.delete('vm', new_uuid, ignore_missing=True) # remove the new object store entry should an error occur later rollback.prependDefer(_rollback_objstore) def _build_access_elem(self, dom, users, groups): auth = config.get("authentication", "method") access_xml = get_metadata_node(dom, "access", self.caps.metadata_support) auth_elem = None if not access_xml: # there is no metadata element 'access' access_elem = E.access() else: access_elem = ET.fromstring(access_xml) same_auth = access_elem.xpath('./auth[@type="%s"]' % auth) if len(same_auth) > 0: # there is already a sub-element 'auth' with the same type; # update it. auth_elem = same_auth[0] if users is not None: for u in auth_elem.findall('user'): auth_elem.remove(u) if groups is not None: for g in auth_elem.findall('group'): auth_elem.remove(g) if auth_elem is None: # there is no sub-element 'auth' with the same type # (or no 'auth' at all); create it. auth_elem = E.auth(type=auth) access_elem.append(auth_elem) if users is not None: for u in users: auth_elem.append(E.user(u)) if groups is not None: for g in groups: auth_elem.append(E.group(g)) return access_elem def _vm_update_access_metadata(self, dom, params): users = groups = None if "users" in params: users = params["users"] for user in users: if not self.users.validate(user): raise InvalidParameter("KCHVM0027E", {'users': user}) if "groups" in params: groups = params["groups"] for group in groups: if not self.groups.validate(group): raise InvalidParameter("KCHVM0028E", {'groups': group}) if users is None and groups is None: return node = self._build_access_elem(dom, users, groups) set_metadata_node(dom, node, self.caps.metadata_support) def _get_access_info(self, dom): users = groups = list() access_xml = (get_metadata_node(dom, "access", self.caps.metadata_support) or """""") access_info = dictize(access_xml) auth = config.get("authentication", "method") if ('auth' in access_info['access'] and ('type' in access_info['access']['auth'] or len(access_info['access']['auth']) > 1)): users = xpath_get_text(access_xml, "/access/auth[@type='%s']/user" % auth) groups = xpath_get_text(access_xml, "/access/auth[@type='%s']/group" % auth) elif auth == 'pam': # Compatible to old permission tagging users = xpath_get_text(access_xml, "/access/user") groups = xpath_get_text(access_xml, "/access/group") return users, groups @staticmethod def vm_get_os_metadata(dom, metadata_support): os_xml = (get_metadata_node(dom, "os", metadata_support) or """""") os_elem = ET.fromstring(os_xml) return (os_elem.attrib.get("version"), os_elem.attrib.get("distro")) @staticmethod def vm_update_os_metadata(dom, params, metadata_support): distro = params.get("os_distro") version = params.get("os_version") if distro is None: return os_elem = E.os({"distro": distro, "version": version}) set_metadata_node(dom, os_elem, metadata_support) def _update_graphics(self, dom, xml, params): root = objectify.fromstring(xml) graphics = root.devices.find("graphics") if graphics is None: return xml password = params['graphics'].get("passwd") if password is not None and len(password.strip()) == 0: password = "".join(random.sample(string.ascii_letters + string.digits, 8)) if password is not None: graphics.attrib['passwd'] = password expire = params['graphics'].get("passwdValidTo") to = graphics.attrib.get('passwdValidTo') if to is not None: if (time.mktime(time.strptime(to, '%Y-%m-%dT%H:%M:%S')) - time.time() <= 0): expire = expire if expire is not None else 30 if expire is not None: expire_time = time.gmtime(time.time() + float(expire)) valid_to = time.strftime('%Y-%m-%dT%H:%M:%S', expire_time) graphics.attrib['passwdValidTo'] = valid_to if not dom.isActive(): return ET.tostring(root, encoding="utf-8") xml = dom.XMLDesc(libvirt.VIR_DOMAIN_XML_SECURE) dom.updateDeviceFlags(etree.tostring(graphics), libvirt.VIR_DOMAIN_AFFECT_LIVE) return xml def _backup_snapshots(self, snap, all_info): """ Append "snap" and the children of "snap" to the list "all_info". The list *must* always contain the parent snapshots before their children so the function "_redefine_snapshots" can work correctly. Arguments: snap -- a native domain snapshot. all_info -- a list of dict keys: "{'xml': , 'current': '}" """ all_info.append({'xml': snap.getXMLDesc(0), 'current': snap.isCurrent(0)}) for child in snap.listAllChildren(0): self._backup_snapshots(child, all_info) def _redefine_snapshots(self, dom, all_info): """ Restore the snapshots stored in "all_info" to the domain "dom". Arguments: dom -- the domain which will have its snapshots restored. all_info -- a list of dict keys, as described in "_backup_snapshots", containing the original snapshot information. """ for info in all_info: flags = libvirt.VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE if info['current']: flags |= libvirt.VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT dom.snapshotCreateXML(info['xml'], flags) def _static_vm_update(self, dom, params): old_xml = new_xml = dom.XMLDesc(0) for key, val in params.items(): if key in VM_STATIC_UPDATE_PARAMS: if type(val) == int: val = str(val) xpath = VM_STATIC_UPDATE_PARAMS[key] new_xml = xml_item_update(new_xml, xpath, val) # Updating memory and NUMA if necessary, if vm is offline if not dom.isActive(): if 'memory' in params: new_xml = self._update_memory_config(new_xml, params) elif 'cpus' in params and \ (xpath_get_text(new_xml, XPATH_NUMA_CELL + '/@memory') != []): vcpus = params['cpus'] new_xml = xml_item_update( new_xml, XPATH_NUMA_CELL, value='0-' + str(vcpus - 1) if vcpus > 1 else '0', attr='cpus') if 'graphics' in params: new_xml = self._update_graphics(dom, new_xml, params) snapshots_info = [] vm_name = dom.name() conn = self.conn.get() try: if 'name' in params: state = DOM_STATE_MAP[dom.info()[0]] if state != 'shutoff': msg_args = {'name': vm_name, 'new_name': params['name']} raise InvalidParameter("KCHVM0003E", msg_args) lflags = libvirt.VIR_DOMAIN_SNAPSHOT_LIST_ROOTS dflags = (libvirt.VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN | libvirt.VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY) for virt_snap in dom.listAllSnapshots(lflags): snapshots_info.append({'xml': virt_snap.getXMLDesc(0), 'current': virt_snap.isCurrent(0)}) self._backup_snapshots(virt_snap, snapshots_info) virt_snap.delete(dflags) # Undefine old vm, only if name is going to change dom.undefine() dom = conn.defineXML(new_xml) if 'name' in params: self._redefine_snapshots(dom, snapshots_info) except libvirt.libvirtError as e: dom = conn.defineXML(old_xml) if 'name' in params: self._redefine_snapshots(dom, snapshots_info) raise OperationFailed("KCHVM0008E", {'name': vm_name, 'err': e.get_error_message()}) return dom def _update_memory_config(self, xml, params): # Checks if NUMA memory is already configured, if not, checks if CPU # element is already configured (topology). Then add NUMA element as # apropriated root = ET.fromstring(xml) numa_mem = xpath_get_text(xml, XPATH_NUMA_CELL + '/@memory') vcpus = params.get('cpus') if numa_mem == []: if vcpus is None: vcpus = int(xpath_get_text(xml, VM_STATIC_UPDATE_PARAMS['cpus'])[0]) cpu = root.find('./cpu') if cpu is None: cpu = get_cpu_xml(vcpus, params['memory'] << 10) root.insert(0, ET.fromstring(cpu)) else: numa_element = get_numa_xml(vcpus, params['memory'] << 10) cpu.insert(0, ET.fromstring(numa_element)) else: if vcpus is not None: xml = xml_item_update( xml, XPATH_NUMA_CELL, value='0-' + str(vcpus - 1) if vcpus > 1 else '0', attr='cpus') root = ET.fromstring(xml_item_update(xml, XPATH_NUMA_CELL, str(params['memory'] << 10), attr='memory')) # Remove currentMemory, automatically set later by libvirt currentMem = root.find('.currentMemory') if currentMem is not None: root.remove(currentMem) memory = root.find('.memory') # Update/Adds maxMemory accordingly if not self.caps.mem_hotplug_support: if memory is not None: memory.text = str(params['memory'] << 10) else: if memory is not None: root.remove(memory) maxMem = root.find('.maxMemory') host_mem = self.conn.get().getInfo()[1] slots = (host_mem - params['memory']) >> 10 # Libvirt does not accepts slots <= 1 if slots < 0: raise OperationFailed("KCHVM0041E") elif slots == 0: slots = 1 if maxMem is None: max_mem_xml = E.maxMemory( str(host_mem * 1024), unit='Kib', slots=str(slots)) root.insert(0, max_mem_xml) new_xml = ET.tostring(root, encoding="utf-8") else: # Update slots only new_xml = xml_item_update(ET.tostring(root, encoding="utf-8"), './maxMemory', str(slots), attr='slots') return new_xml return ET.tostring(root, encoding="utf-8") def _live_vm_update(self, dom, params): self._vm_update_access_metadata(dom, params) if 'memory' in params and dom.isActive(): self._update_memory_live(dom, params) def _update_memory_live(self, dom, params): # Check if host supports memory device if not self.caps.mem_hotplug_support: raise InvalidOperation("KCHVM0046E") # Check if the vm xml supports memory hotplug, if not, static update # must be done firstly, then Kimchi is going to update the xml xml = dom.XMLDesc(0) numa_mem = xpath_get_text(xml, XPATH_NUMA_CELL + '/@memory') max_mem = xpath_get_text(xml, './maxMemory') if numa_mem == [] or max_mem == []: raise OperationFailed('KCHVM0042E', {'name': dom.name()}) # Memory live update must be done in chunks of 1024 Mib or 1Gib new_mem = params['memory'] old_mem = int(xpath_get_text(xml, XPATH_DOMAIN_MEMORY)[0]) >> 10 if new_mem < old_mem: raise OperationFailed('KCHVM0043E') if (new_mem - old_mem) % 1024 != 0: raise OperationFailed('KCHVM0044E') # Check slot spaces: total_slots = int(xpath_get_text(xml, './maxMemory/@slots')[0]) needed_slots = (new_mem - old_mem) / 1024 used_slots = len(xpath_get_text(xml, './devices/memory')) if needed_slots > (total_slots - used_slots): raise OperationFailed('KCHVM0045E') elif needed_slots == 0: # New memory value is same that current memory set return # Finally, we are ok to hot add the memory devices try: self._hot_add_memory_devices(dom, needed_slots) except Exception as e: raise OperationFailed("KCHVM0047E", {'error': e.message}) def _hot_add_memory_devices(self, dom, amount): # Hot add given number of memory devices in the guest flags = libvirt.VIR_DOMAIN_MEM_CONFIG | libvirt.VIR_DOMAIN_MEM_LIVE # Create memory device xml mem_dev_xml = etree.tostring( E.memory( E.target( E.size('1', unit='GiB'), E.node('0')), model='dimm')) # Add chunks of 1G of memory for i in range(amount): dom.attachDeviceFlags(mem_dev_xml, flags) def _has_video(self, dom): dom = ElementTree.fromstring(dom.XMLDesc(0)) return dom.find('devices/video') is not None def _update_guest_stats(self, name): try: dom = VMModel.get_vm(name, self.conn) vm_uuid = dom.UUIDString() info = dom.info() state = DOM_STATE_MAP[info[0]] if state != 'running': self.stats[vm_uuid] = {} return if self.stats.get(vm_uuid, None) is None: self.stats[vm_uuid] = {} timestamp = time.time() prevStats = self.stats.get(vm_uuid, {}) seconds = timestamp - prevStats.get('timestamp', 0) self.stats[vm_uuid].update({'timestamp': timestamp}) self._get_percentage_cpu_usage(vm_uuid, info, seconds) self._get_network_io_rate(vm_uuid, dom, seconds) self._get_disk_io_rate(vm_uuid, dom, seconds) except Exception as e: # VM might be deleted just after we get the list. # This is OK, just skip. kimchi_log.debug('Error processing VM stats: %s', e.message) def _get_percentage_cpu_usage(self, vm_uuid, info, seconds): prevCpuTime = self.stats[vm_uuid].get('cputime', 0) cpus = info[3] cpuTime = info[4] - prevCpuTime base = (((cpuTime) * 100.0) / (seconds * 1000.0 * 1000.0 * 1000.0)) percentage = max(0.0, min(100.0, base / cpus)) self.stats[vm_uuid].update({'cputime': info[4], 'cpu': percentage}) def _get_network_io_rate(self, vm_uuid, dom, seconds): prevNetRxKB = self.stats[vm_uuid].get('netRxKB', 0) prevNetTxKB = self.stats[vm_uuid].get('netTxKB', 0) currentMaxNetRate = self.stats[vm_uuid].get('max_net_io', 100) rx_bytes = 0 tx_bytes = 0 tree = ElementTree.fromstring(dom.XMLDesc(0)) for target in tree.findall('devices/interface/target'): dev = target.get('dev') io = dom.interfaceStats(dev) rx_bytes += io[0] tx_bytes += io[4] netRxKB = float(rx_bytes) / 1000 netTxKB = float(tx_bytes) / 1000 rx_stats = (netRxKB - prevNetRxKB) / seconds tx_stats = (netTxKB - prevNetTxKB) / seconds rate = rx_stats + tx_stats max_net_io = round(max(currentMaxNetRate, int(rate)), 1) self.stats[vm_uuid].update({'net_io': rate, 'max_net_io': max_net_io, 'netRxKB': netRxKB, 'netTxKB': netTxKB}) def _get_disk_io_rate(self, vm_uuid, dom, seconds): prevDiskRdKB = self.stats[vm_uuid].get('diskRdKB', 0) prevDiskWrKB = self.stats[vm_uuid].get('diskWrKB', 0) currentMaxDiskRate = self.stats[vm_uuid].get('max_disk_io', 100) rd_bytes = 0 wr_bytes = 0 tree = ElementTree.fromstring(dom.XMLDesc(0)) for target in tree.findall("devices/disk/target"): dev = target.get("dev") io = dom.blockStats(dev) rd_bytes += io[1] wr_bytes += io[3] diskRdKB = float(rd_bytes) / 1024 diskWrKB = float(wr_bytes) / 1024 rd_stats = (diskRdKB - prevDiskRdKB) / seconds wr_stats = (diskWrKB - prevDiskWrKB) / seconds rate = rd_stats + wr_stats max_disk_io = round(max(currentMaxDiskRate, int(rate)), 1) self.stats[vm_uuid].update({'disk_io': rate, 'max_disk_io': max_disk_io, 'diskRdKB': diskRdKB, 'diskWrKB': diskWrKB}) def lookup(self, name): dom = self.get_vm(name, self.conn) info = dom.info() state = DOM_STATE_MAP[info[0]] screenshot = None # (type, listen, port, passwd, passwdValidTo) graphics = self._vm_get_graphics(name) graphics_port = graphics[2] graphics_port = graphics_port if state == 'running' else None try: if state == 'running' and self._has_video(dom): screenshot = self.vmscreenshot.lookup(name) elif state == 'shutoff': # reset vm stats when it is powered off to avoid sending # incorrect (old) data self.stats[dom.UUIDString()] = {} except NotFoundError: pass with self.objstore as session: try: extra_info = session.get('vm', dom.UUIDString()) except NotFoundError: extra_info = {} icon = extra_info.get('icon') self._update_guest_stats(name) vm_stats = self.stats.get(dom.UUIDString(), {}) res = {} res['cpu_utilization'] = vm_stats.get('cpu', 0) res['net_throughput'] = vm_stats.get('net_io', 0) res['net_throughput_peak'] = vm_stats.get('max_net_io', 100) res['io_throughput'] = vm_stats.get('disk_io', 0) res['io_throughput_peak'] = vm_stats.get('max_disk_io', 100) users, groups = self._get_access_info(dom) if state == 'shutoff': xml = dom.XMLDesc(0) val = xpath_get_text(xml, XPATH_DOMAIN_MEMORY)[0] unit_list = xpath_get_text(xml, XPATH_DOMAIN_MEMORY_UNIT) if len(unit_list) > 0: unit = unit_list[0] else: unit = 'KiB' memory = convert_data_size(val, unit, 'MiB') else: memory = info[2] >> 10 return {'name': name, 'state': state, 'stats': res, 'uuid': dom.UUIDString(), 'memory': memory, 'cpus': info[3], 'screenshot': screenshot, 'icon': icon, # (type, listen, port, passwd, passwdValidTo) 'graphics': {"type": graphics[0], "listen": graphics[1], "port": graphics_port, "passwd": graphics[3], "passwdValidTo": graphics[4]}, 'users': users, 'groups': groups, 'access': 'full', 'persistent': True if dom.isPersistent() else False } def _vm_get_disk_paths(self, dom): xml = dom.XMLDesc(0) xpath = "/domain/devices/disk[@device='disk']/source/@file" return xpath_get_text(xml, xpath) @staticmethod def get_vm(name, conn): conn = conn.get() try: # outgoing text to libvirt, encode('utf-8') return conn.lookupByName(name.encode("utf-8")) except libvirt.libvirtError as e: if e.get_error_code() == libvirt.VIR_ERR_NO_DOMAIN: raise NotFoundError("KCHVM0002E", {'name': name}) else: raise OperationFailed("KCHVM0009E", {'name': name, 'err': e.message}) def delete(self, name): conn = self.conn.get() dom = self.get_vm(name, self.conn) if not dom.isPersistent(): raise InvalidOperation("KCHVM0036E", {'name': name}) self._vmscreenshot_delete(dom.UUIDString()) paths = self._vm_get_disk_paths(dom) info = self.lookup(name) if info['state'] != 'shutoff': self.poweroff(name) # delete existing snapshots before deleting VM # libvirt's Test driver does not support the function # "virDomainListAllSnapshots", so "VMSnapshots.get_list" will raise # "OperationFailed" in that case. try: snapshot_names = self.vmsnapshots.get_list(name) except OperationFailed, e: kimchi_log.error('cannot list snapshots: %s; ' 'skipping snapshot deleting...' % e.message) else: for s in snapshot_names: self.vmsnapshot.delete(name, s) try: dom.undefine() except libvirt.libvirtError as e: raise OperationFailed("KCHVM0021E", {'name': name, 'err': e.get_error_message()}) for path in paths: try: vol = conn.storageVolLookupByPath(path) pool = vol.storagePoolLookupByVolume() xml = pool.XMLDesc(0) pool_type = xpath_get_text(xml, "/pool/@type")[0] if pool_type not in READONLY_POOL_TYPE: vol.delete(0) # Update objstore to remove the volume with self.objstore as session: session.delete('storagevolume', path, ignore_missing=True) except libvirt.libvirtError as e: kimchi_log.error('Unable to get storage volume by path: %s' % e.message) except Exception as e: raise OperationFailed('KCHVOL0017E', {'err': e.message}) try: with self.objstore as session: if path in session.get_list('storagevolume'): used_by = session.get('storagevolume', path)['used_by'] used_by.remove(name) session.store('storagevolume', path, {'used_by': used_by}) except Exception as e: raise OperationFailed('KCHVOL0017E', {'err': e.message}) try: with self.objstore as session: session.delete('vm', dom.UUIDString(), ignore_missing=True) except Exception as e: # It is possible to delete vm without delete its database info kimchi_log.error('Error deleting vm information from database: ' '%s', e.message) vnc.remove_proxy_token(name) def start(self, name): # make sure the ISO file has read permission dom = self.get_vm(name, self.conn) xml = dom.XMLDesc(0) xpath = "/domain/devices/disk[@device='cdrom']/source/@file" isofiles = xpath_get_text(xml, xpath) user = UserTests.probe_user() for iso in isofiles: run_setfacl_set_attr(iso, user=user) dom = self.get_vm(name, self.conn) try: dom.create() except libvirt.libvirtError as e: raise OperationFailed("KCHVM0019E", {'name': name, 'err': e.get_error_message()}) def poweroff(self, name): dom = self.get_vm(name, self.conn) try: dom.destroy() except libvirt.libvirtError as e: raise OperationFailed("KCHVM0020E", {'name': name, 'err': e.get_error_message()}) def shutdown(self, name): dom = self.get_vm(name, self.conn) try: dom.shutdown() except libvirt.libvirtError as e: raise OperationFailed("KCHVM0029E", {'name': name, 'err': e.get_error_message()}) def reset(self, name): dom = self.get_vm(name, self.conn) try: dom.reset(flags=0) except libvirt.libvirtError as e: raise OperationFailed("KCHVM0022E", {'name': name, 'err': e.get_error_message()}) def _vm_get_graphics(self, name): dom = self.get_vm(name, self.conn) xml = dom.XMLDesc(libvirt.VIR_DOMAIN_XML_SECURE) expr = "/domain/devices/graphics/@type" res = xpath_get_text(xml, expr) graphics_type = res[0] if res else None expr = "/domain/devices/graphics/@listen" res = xpath_get_text(xml, expr) graphics_listen = res[0] if res else None graphics_port = graphics_passwd = graphics_passwdValidTo = None if graphics_type: expr = "/domain/devices/graphics[@type='%s']/@port" res = xpath_get_text(xml, expr % graphics_type) graphics_port = int(res[0]) if res else None expr = "/domain/devices/graphics[@type='%s']/@passwd" res = xpath_get_text(xml, expr % graphics_type) graphics_passwd = res[0] if res else None expr = "/domain/devices/graphics[@type='%s']/@passwdValidTo" res = xpath_get_text(xml, expr % graphics_type) if res: to = time.mktime(time.strptime(res[0], '%Y-%m-%dT%H:%M:%S')) graphics_passwdValidTo = to - time.mktime(time.gmtime()) return (graphics_type, graphics_listen, graphics_port, graphics_passwd, graphics_passwdValidTo) def connect(self, name): # (type, listen, port, passwd, passwdValidTo) graphics_port = self._vm_get_graphics(name)[2] if graphics_port is not None: vnc.add_proxy_token(name, graphics_port) else: raise OperationFailed("KCHVM0010E", {'name': name}) def _vmscreenshot_delete(self, vm_uuid): screenshot = VMScreenshotModel.get_screenshot(vm_uuid, self.objstore, self.conn) screenshot.delete() try: with self.objstore as session: session.delete('screenshot', vm_uuid) except Exception as e: # It is possible to continue Kimchi executions without delete # screenshots kimchi_log.error('Error trying to delete vm screenshot from ' 'database due error: %s', e.message) def suspend(self, name): """Suspend the virtual machine's execution and puts it in the state 'paused'. Use the function "resume" to restore its state. If the VM is not running, an exception will be raised. Parameters: name -- the name of the VM to be suspended. """ vm = self.lookup(name) if vm['state'] != 'running': raise InvalidOperation('KCHVM0037E', {'name': name}) vir_dom = self.get_vm(name, self.conn) try: vir_dom.suspend() except libvirt.libvirtError, e: raise OperationFailed('KCHVM0038E', {'name': name, 'err': e.message}) def resume(self, name): """Resume the virtual machine's execution and puts it in the state 'running'. The VM should have been suspended previously by the function "suspend" and be in the state 'paused', otherwise an exception will be raised. Parameters: name -- the name of the VM to be resumed. """ vm = self.lookup(name) if vm['state'] != 'paused': raise InvalidOperation('KCHVM0039E', {'name': name}) vir_dom = self.get_vm(name, self.conn) try: vir_dom.resume() except libvirt.libvirtError, e: raise OperationFailed('KCHVM0040E', {'name': name, 'err': e.message}) class VMScreenshotModel(object): def __init__(self, **kargs): self.objstore = kargs['objstore'] self.conn = kargs['conn'] def lookup(self, name): dom = VMModel.get_vm(name, self.conn) d_info = dom.info() vm_uuid = dom.UUIDString() if DOM_STATE_MAP[d_info[0]] != 'running': raise NotFoundError("KCHVM0004E", {'name': name}) screenshot = self.get_screenshot(vm_uuid, self.objstore, self.conn) img_path = screenshot.lookup() # screenshot info changed after scratch generation try: with self.objstore as session: session.store('screenshot', vm_uuid, screenshot.info) except Exception as e: # It is possible to continue Kimchi executions without store # screenshots kimchi_log.error('Error trying to update database with guest ' 'screenshot information due error: %s', e.message) return img_path @staticmethod def get_screenshot(vm_uuid, objstore, conn): try: with objstore as session: try: params = session.get('screenshot', vm_uuid) except NotFoundError: params = {'uuid': vm_uuid} session.store('screenshot', vm_uuid, params) except Exception as e: # The 'except' outside of 'with' is necessary to catch possible # exception from '__exit__' when calling 'session.store' # It is possible to continue Kimchi vm executions without # screenshots kimchi_log.error('Error trying to update database with guest ' 'screenshot information due error: %s', e.message) return LibvirtVMScreenshot(params, conn) class LibvirtVMScreenshot(VMScreenshot): def __init__(self, vm_uuid, conn): VMScreenshot.__init__(self, vm_uuid) self.conn = conn def _generate_scratch(self, thumbnail): def handler(stream, buf, opaque): fd = opaque os.write(fd, buf) fd = os.open(thumbnail, os.O_WRONLY | os.O_TRUNC | os.O_CREAT, 0644) try: conn = self.conn.get() dom = conn.lookupByUUIDString(self.vm_uuid) vm_name = dom.name() stream = conn.newStream(0) dom.screenshot(stream, 0, 0) stream.recvAll(handler, fd) except libvirt.libvirtError: try: stream.abort() except: pass raise NotFoundError("KCHVM0006E", {'name': vm_name}) else: stream.finish() finally: os.close(fd) kimchi-1.5.0/src/kimchi/model/vmsnapshots.py000066400000000000000000000172471254252253000210660ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2014-2015 # # 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 import time import libvirt import lxml.etree as ET from lxml import objectify from lxml.builder import E from kimchi.exception import InvalidOperation, NotFoundError, OperationFailed from kimchi.model.tasks import TaskModel from kimchi.model.vms import DOM_STATE_MAP, VMModel from kimchi.model.vmstorages import VMStorageModel, VMStoragesModel from kimchi.utils import add_task from kimchi.xmlutils.utils import xpath_get_text class VMSnapshotsModel(object): def __init__(self, **kargs): self.conn = kargs['conn'] self.objstore = kargs['objstore'] self.task = TaskModel(**kargs) self.vmstorages = VMStoragesModel(**kargs) self.vmstorage = VMStorageModel(**kargs) def create(self, vm_name, params={}): """Create a snapshot with the current domain state. The VM must be stopped and contain only disks with format 'qcow2'; otherwise an exception will be raised. Parameters: vm_name -- the name of the VM where the snapshot will be created. params -- a dict with the following values: "name": The snapshot name (optional). If omitted, a default value based on the current time will be used. Return: A Task running the operation. """ vir_dom = VMModel.get_vm(vm_name, self.conn) if DOM_STATE_MAP[vir_dom.info()[0]] != u'shutoff': raise InvalidOperation('KCHSNAP0001E', {'vm': vm_name}) # if the VM has a non-CDROM disk with type 'raw', abort. for storage_name in self.vmstorages.get_list(vm_name): storage = self.vmstorage.lookup(vm_name, storage_name) type = storage['type'] format = storage['format'] if type != u'cdrom' and format != u'qcow2': raise InvalidOperation('KCHSNAP0010E', {'vm': vm_name, 'format': format}) name = params.get('name', unicode(int(time.time()))) task_params = {'vm_name': vm_name, 'name': name} taskid = add_task(u'/vms/%s/snapshots/%s' % (vm_name, name), self._create_task, self.objstore, task_params) return self.task.lookup(taskid) def _create_task(self, cb, params): """Asynchronous function which actually creates the snapshot. Parameters: cb -- a callback function to signal the Task's progress. params -- a dict with the following values: "vm_name": the name of the VM where the snapshot will be created. "name": the snapshot name. """ vm_name = params['vm_name'] name = params['name'] cb('building snapshot XML') root_elem = E.domainsnapshot() root_elem.append(E.name(name)) xml = ET.tostring(root_elem, encoding='utf-8') try: cb('fetching snapshot domain') vir_dom = VMModel.get_vm(vm_name, self.conn) cb('creating snapshot') vir_dom.snapshotCreateXML(xml, 0) except (NotFoundError, OperationFailed, libvirt.libvirtError), e: raise OperationFailed('KCHSNAP0002E', {'name': name, 'vm': vm_name, 'err': e.message}) cb('OK', True) def get_list(self, vm_name): vir_dom = VMModel.get_vm(vm_name, self.conn) try: vir_snaps = vir_dom.listAllSnapshots(0) return sorted([s.getName().decode('utf-8') for s in vir_snaps], key=unicode.lower) except libvirt.libvirtError, e: raise OperationFailed('KCHSNAP0005E', {'vm': vm_name, 'err': e.message}) class VMSnapshotModel(object): def __init__(self, **kargs): self.conn = kargs['conn'] def lookup(self, vm_name, name): vir_snap = self.get_vmsnapshot(vm_name, name) try: snap_xml_str = vir_snap.getXMLDesc(0).decode('utf-8') except libvirt.libvirtError, e: raise OperationFailed('KCHSNAP0004E', {'name': name, 'vm': vm_name, 'err': e.message}) snap_xml = objectify.fromstring(snap_xml_str) try: parent = unicode(snap_xml.parent.name) except AttributeError: parent = u'' return {'created': unicode(snap_xml.creationTime), 'name': unicode(snap_xml.name), 'parent': parent, 'state': unicode(snap_xml.state)} def delete(self, vm_name, name): try: vir_snap = self.get_vmsnapshot(vm_name, name) vir_snap.delete(0) except libvirt.libvirtError, e: raise OperationFailed('KCHSNAP0006E', {'name': name, 'vm': vm_name, 'err': e.message}) def revert(self, vm_name, name): try: vir_dom = VMModel.get_vm(vm_name, self.conn) vir_snap = self.get_vmsnapshot(vm_name, name) vir_dom.revertToSnapshot(vir_snap, 0) # get vm name recorded in the snapshot and return new uri params vm_new_name = xpath_get_text(vir_snap.getXMLDesc(0), 'domain/name')[0] return [vm_new_name, name] except libvirt.libvirtError, e: raise OperationFailed('KCHSNAP0009E', {'name': name, 'vm': vm_name, 'err': e.message}) def get_vmsnapshot(self, vm_name, name): vir_dom = VMModel.get_vm(vm_name, self.conn) try: return vir_dom.snapshotLookupByName(name, 0) except libvirt.libvirtError, e: code = e.get_error_code() if code == libvirt.VIR_ERR_NO_DOMAIN_SNAPSHOT: raise NotFoundError('KCHSNAP0003E', {'name': name, 'vm': vm_name}) else: raise OperationFailed('KCHSNAP0004E', {'name': name, 'vm': vm_name, 'err': e.message}) class CurrentVMSnapshotModel(object): def __init__(self, **kargs): self.conn = kargs['conn'] self.vmsnapshot = VMSnapshotModel(**kargs) def lookup(self, vm_name): vir_dom = VMModel.get_vm(vm_name, self.conn) try: vir_snap = vir_dom.snapshotCurrent(0) snap_name = vir_snap.getName().decode('utf-8') except libvirt.libvirtError, e: if e.get_error_code() == libvirt.VIR_ERR_NO_DOMAIN_SNAPSHOT: return {} raise OperationFailed('KCHSNAP0008E', {'vm': vm_name, 'err': e.message}) return self.vmsnapshot.lookup(vm_name, snap_name) kimchi-1.5.0/src/kimchi/model/vmstorages.py000066400000000000000000000234641254252253000206710ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2014-2015 # # 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 import string from lxml import etree from kimchi.exception import InvalidOperation, InvalidParameter, NotFoundError from kimchi.exception import OperationFailed from kimchi.model.config import CapabilitiesModel from kimchi.model.vms import DOM_STATE_MAP, VMModel from kimchi.model.storagevolumes import StorageVolumeModel from kimchi.model.utils import get_vm_config_flag from kimchi.osinfo import lookup from kimchi.model.diskutils import get_disk_used_by, set_disk_used_by from kimchi.utils import kimchi_log from kimchi.xmlutils.disk import get_device_node, get_disk_xml from kimchi.xmlutils.disk import get_vm_disk_info, get_vm_disks HOTPLUG_TYPE = ['scsi', 'virtio'] def _get_device_bus(dev_type, dom, metadata_support): try: version, distro = VMModel.vm_get_os_metadata(dom, metadata_support) except: version, distro = ('unknown', 'unknown') return lookup(distro, version)[dev_type+'_bus'] class VMStoragesModel(object): def __init__(self, **kargs): self.conn = kargs['conn'] self.objstore = kargs['objstore'] self.caps = CapabilitiesModel(**kargs) def _get_available_bus_address(self, bus_type, vm_name): if bus_type not in ['ide']: return dict() # libvirt limitation of just 1 ide controller # each controller have at most 2 buses and each bus 2 units. dom = VMModel.get_vm(vm_name, self.conn) disks = self.get_list(vm_name) valid_id = [('0', '0'), ('0', '1'), ('1', '0'), ('1', '1')] controller_id = '0' for dev_name in disks: disk = get_device_node(dom, dev_name) if disk.target.attrib['bus'] == 'ide': controller_id = disk.address.attrib['controller'] bus_id = disk.address.attrib['bus'] unit_id = disk.address.attrib['unit'] if (bus_id, unit_id) in valid_id: valid_id.remove((bus_id, unit_id)) continue if not valid_id: raise OperationFailed('KCHVMSTOR0014E', {'type': 'ide', 'limit': 4}) else: address = {'controller': controller_id, 'bus': valid_id[0][0], 'unit': valid_id[0][1]} return dict(address=address) def create(self, vm_name, params): vol_model = None # Path will never be blank due to API.json verification. # There is no need to cover this case here. if not ('vol' in params) ^ ('path' in params): raise InvalidParameter("KCHVMSTOR0017E") dom = VMModel.get_vm(vm_name, self.conn) params['bus'] = _get_device_bus(params['type'], dom, self.caps.metadata_support) params['format'] = 'raw' dev_list = [dev for dev, bus in get_vm_disks(dom).iteritems() if bus == params['bus']] dev_list.sort() if len(dev_list) == 0: params['index'] = 0 else: char = dev_list.pop()[2] params['index'] = string.ascii_lowercase.index(char) + 1 if (params['bus'] not in HOTPLUG_TYPE and DOM_STATE_MAP[dom.info()[0]] != 'shutoff'): raise InvalidOperation('KCHVMSTOR0011E') if params.get('vol'): try: pool = params['pool'] vol_model = StorageVolumeModel(conn=self.conn, objstore=self.objstore) vol_info = vol_model.lookup(pool, params['vol']) except KeyError: raise InvalidParameter("KCHVMSTOR0012E") except Exception as e: raise InvalidParameter("KCHVMSTOR0015E", {'error': e}) if len(vol_info['used_by']) != 0: raise InvalidParameter("KCHVMSTOR0016E") valid_format = { "disk": ["raw", "bochs", "qcow", "qcow2", "qed", "vmdk"], "cdrom": "iso"} if vol_info['type'] == 'file': if (params['type'] == 'disk' and vol_info['format'] in valid_format[params['type']]): params['format'] = vol_info['format'] else: raise InvalidParameter("KCHVMSTOR0018E", {"format": vol_info['format'], "type": params['type']}) params['path'] = vol_info['path'] params['disk'] = vol_info['type'] params.update(self._get_available_bus_address(params['bus'], vm_name)) # Add device to VM dev, xml = get_disk_xml(params) try: conn = self.conn.get() dom = conn.lookupByName(vm_name) dom.attachDeviceFlags(xml, get_vm_config_flag(dom, 'all')) except Exception as e: raise OperationFailed("KCHVMSTOR0008E", {'error': e.message}) # Don't put a try-block here. Let the exception be raised. If we # allow disks used_by to be out of sync, data corruption could # occour if a disk is added to two guests unknowingly. if params.get('vol'): used_by = vol_info['used_by'] used_by.append(vm_name) set_disk_used_by(self.objstore, params['path'], used_by) return dev def get_list(self, vm_name): dom = VMModel.get_vm(vm_name, self.conn) return get_vm_disks(dom).keys() class VMStorageModel(object): def __init__(self, **kargs): self.conn = kargs['conn'] self.objstore = kargs['objstore'] self.caps = CapabilitiesModel(**kargs) def lookup(self, vm_name, dev_name): # Retrieve disk xml and format return dict dom = VMModel.get_vm(vm_name, self.conn) return get_vm_disk_info(dom, dev_name) def delete(self, vm_name, dev_name): conn = self.conn.get() try: bus_type = self.lookup(vm_name, dev_name)['bus'] dom = conn.lookupByName(vm_name) except NotFoundError: raise if (bus_type not in HOTPLUG_TYPE and DOM_STATE_MAP[dom.info()[0]] != 'shutoff'): raise InvalidOperation('KCHVMSTOR0011E') try: disk = get_device_node(dom, dev_name) path = get_vm_disk_info(dom, dev_name)['path'] if path is None or len(path) < 1: path = self.lookup(vm_name, dev_name)['path'] # This has to be done before it's detached. If it wasn't # in the obj store, its ref count would have been updated # by get_disk_used_by() if path is not None: used_by = get_disk_used_by(self.objstore, self.conn, path) else: kimchi_log.error("Unable to decrement volume used_by on" " delete because no path could be found.") dom.detachDeviceFlags(etree.tostring(disk), get_vm_config_flag(dom, 'all')) except Exception as e: raise OperationFailed("KCHVMSTOR0010E", {'error': e.message}) if used_by is not None and vm_name in used_by: used_by.remove(vm_name) set_disk_used_by(self.objstore, path, used_by) else: kimchi_log.error("Unable to update %s:%s used_by on delete." % (vm_name, dev_name)) def update(self, vm_name, dev_name, params): old_disk_used_by = None new_disk_used_by = None dom = VMModel.get_vm(vm_name, self.conn) dev_info = self.lookup(vm_name, dev_name) if dev_info['type'] != 'cdrom': raise InvalidOperation("KCHVMSTOR0006E") params['path'] = params.get('path', '') old_disk_path = dev_info['path'] new_disk_path = params['path'] if new_disk_path != old_disk_path: # An empty path means a CD-ROM was empty or ejected: if old_disk_path is not '': old_disk_used_by = get_disk_used_by( self.objstore, self.conn, old_disk_path) if new_disk_path is not '': new_disk_used_by = get_disk_used_by( self.objstore, self.conn, new_disk_path) dev_info.update(params) dev, xml = get_disk_xml(dev_info) try: dom.updateDeviceFlags(xml, get_vm_config_flag(dom, 'all')) except Exception as e: raise OperationFailed("KCHVMSTOR0009E", {'error': e.message}) try: if old_disk_used_by is not None and \ vm_name in old_disk_used_by: old_disk_used_by.remove(vm_name) set_disk_used_by(self.objstore, old_disk_path, old_disk_used_by) if new_disk_used_by is not None: new_disk_used_by.append(vm_name) set_disk_used_by(self.objstore, new_disk_path, new_disk_used_by) except Exception as e: kimchi_log.error("Unable to update dev used_by on update due to" " %s:" % e.message) return dev kimchi-1.5.0/src/kimchi/netinfo.py000066400000000000000000000132201254252253000170260ustar00rootroot00000000000000# Project Kimchi # # Copyright IBM, Corp. 2013-2015 # # 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 # import ethtool import glob import os NET_PATH = '/sys/class/net' NIC_PATH = '/sys/class/net/*/device' BRIDGE_PATH = '/sys/class/net/*/bridge' BONDING_PATH = '/sys/class/net/*/bonding' WLAN_PATH = '/sys/class/net/*/wireless' NET_BRPORT = '/sys/class/net/%s/brport' NET_MASTER = '/sys/class/net/%s/master' NET_STATE = '/sys/class/net/%s/carrier' PROC_NET_VLAN = '/proc/net/vlan/' BONDING_SLAVES = '/sys/class/net/%s/bonding/slaves' BRIDGE_PORTS = '/sys/class/net/%s/brif' def wlans(): return [b.split('/')[-2] for b in glob.glob(WLAN_PATH)] def is_wlan(iface): return iface in wlans() # FIXME if we do not want to list usb nic def nics(): return list(set([b.split('/')[-2] for b in glob.glob(NIC_PATH)]) - set(wlans())) def is_nic(iface): return iface in nics() def bondings(): return [b.split('/')[-2] for b in glob.glob(BONDING_PATH)] def is_bonding(iface): return iface in bondings() def vlans(): return list(set([b.split('/')[-1] for b in glob.glob(NET_PATH + '/*')]) & set([b.split('/')[-1] for b in glob.glob(PROC_NET_VLAN + '*')])) def is_vlan(iface): return iface in vlans() def bridges(): return [b.split('/')[-2] for b in glob.glob(BRIDGE_PATH)] def is_bridge(iface): return iface in bridges() def all_interfaces(): return [d.rsplit("/", 1)[-1] for d in glob.glob(NET_PATH + '/*')] def slaves(bonding): with open(BONDING_SLAVES % bonding) as bonding_file: res = bonding_file.readline().split() return res def ports(bridge): return os.listdir(BRIDGE_PORTS % bridge) def is_brport(nic): return os.path.exists(NET_BRPORT % nic) def is_bondlave(nic): return os.path.exists(NET_MASTER % nic) def operstate(dev): link_status = link_detected(dev) return "down" if link_status == "n/a" else "up" def link_detected(dev): # try to read interface carrier (link) status try: with open(NET_STATE % dev) as dev_file: carrier = dev_file.readline().strip() # when IOError is raised, interface is down except IOError: return "n/a" # if value is 1, interface up with cable connected # 0 corresponds to interface up with cable disconnected return "yes" if carrier == '1' else "no" def get_vlan_device(vlan): """ Return the device of the given VLAN. """ dev = None if os.path.exists(PROC_NET_VLAN + vlan): with open(PROC_NET_VLAN + vlan) as vlan_file: for line in vlan_file: if "Device:" in line: dummy, dev = line.split() break return dev def get_bridge_port_device(bridge): """Return the nics list that belongs to bridge.""" # br --- v --- bond --- nic1 if bridge not in bridges(): raise ValueError('unknown bridge %s' % bridge) nics = [] for port in ports(bridge): if port in vlans(): device = get_vlan_device(port) if device in bondings(): nics.extend(slaves(device)) else: nics.append(device) if port in bondings(): nics.extend(slaves(port)) else: nics.append(port) return nics def aggregated_bridges(): return [bridge for bridge in bridges() if (set(get_bridge_port_device(bridge)) & set(nics()))] def bare_nics(): "The nic is not a port of a bridge or a slave of bond." return [nic for nic in nics() if not (is_brport(nic) or is_bondlave(nic))] def is_bare_nic(iface): return iface in bare_nics() # The nic will not be exposed when it is a port of a bridge or # a slave of bond. # The bridge will not be exposed when all it's port are tap. def all_favored_interfaces(): return aggregated_bridges() + bare_nics() + bondings() def get_interface_type(iface): # FIXME if we want to get more device type # just support nic, bridge, bondings and vlan, for we just # want to expose this 4 kinds of interface try: if is_nic(iface): return "nic" if is_bonding(iface): return "bonding" if is_bridge(iface): return "bridge" if is_vlan(iface): return "vlan" return 'unknown' except IOError: return 'unknown' def get_interface_info(iface): if iface not in ethtool.get_devices(): raise ValueError('unknown interface: %s' % iface) ipaddr = '' netmask = '' try: ipaddr = ethtool.get_ipaddr(iface) netmask = ethtool.get_netmask(iface) except IOError: pass iface_link_detected = link_detected(iface) iface_status = 'active' if iface_link_detected != "n/a" else "inactive" return {'name': iface, 'type': get_interface_type(iface), 'status': iface_status, 'link_detected': iface_link_detected, 'ipaddr': ipaddr, 'netmask': netmask} kimchi-1.5.0/src/kimchi/network.py000066400000000000000000000041101254252253000170530ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-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 # import ethtool import ipaddr APrivateNets = ipaddr.IPNetwork("10.0.0.0/8") BPrivateNets = ipaddr.IPNetwork("172.16.0.0/12") CPrivateNets = ipaddr.IPNetwork('192.168.0.0/16') PrivateNets = [CPrivateNets, BPrivateNets, APrivateNets] DefaultNetsPool = [ipaddr.IPNetwork('192.168.122.0/23'), ipaddr.IPNetwork('192.168.124.0/22'), ipaddr.IPNetwork('192.168.128.0/17')] def get_dev_netaddr(dev): info = ethtool.get_interfaces_info(dev)[0] return (info.ipv4_address and "%s/%s" % (info.ipv4_address, info.ipv4_netmask) or '') def get_dev_netaddrs(): nets = [] for dev in ethtool.get_devices(): devnet = get_dev_netaddr(dev) devnet and nets.append(ipaddr.IPNetwork(devnet)) return nets # used_nets should include all the subnet allocated in libvirt network # will get host network by get_dev_netaddrs def get_one_free_network(used_nets, nets_pool=PrivateNets): def _get_free_network(nets, used_nets): for net in nets.subnet(new_prefix=24): if not any(net.overlaps(used) for used in used_nets): return str(net) return None used_nets = used_nets + get_dev_netaddrs() for nets in nets_pool: net = _get_free_network(nets, used_nets) if net: return net return None kimchi-1.5.0/src/kimchi/objectstore.py000066400000000000000000000112471254252253000177160ustar00rootroot00000000000000# Project Kimchi # # Copyright IBM, Corp. 2013-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 import json import sqlite3 import threading import traceback try: from collections import OrderedDict except ImportError: from ordereddict import OrderedDict from kimchi import config from kimchi.exception import NotFoundError from kimchi.utils import kimchi_log class ObjectStoreSession(object): def __init__(self, conn): self.conn = conn self.conn.text_factory = lambda x: unicode(x, "utf-8", "ignore") def _get_list(self, obj_type): c = self.conn.cursor() res = c.execute('SELECT id FROM objects WHERE type=?', (obj_type,)) return [x[0] for x in res] def get_list(self, obj_type, sort_key=None): ids = self._get_list(obj_type) if sort_key is None: return ids objects = [(ident, self.get(obj_type, ident)) for ident in ids] objects.sort(key=lambda (_, obj): obj[sort_key]) return [ident for ident, _ in objects] def get(self, obj_type, ident): c = self.conn.cursor() res = c.execute('SELECT json FROM objects WHERE type=? AND id=?', (obj_type, ident)) try: jsonstr = res.fetchall()[0][0] except IndexError: self.conn.rollback() raise NotFoundError("KCHOBJST0001E", {'item': ident}) return json.loads(jsonstr) def delete(self, obj_type, ident, ignore_missing=False): c = self.conn.cursor() c.execute('DELETE FROM objects WHERE type=? AND id=?', (obj_type, ident)) if c.rowcount != 1 and not ignore_missing: self.conn.rollback() raise NotFoundError("KCHOBJST0001E", {'item': ident}) self.conn.commit() def store(self, obj_type, ident, data): jsonstr = json.dumps(data) c = self.conn.cursor() c.execute('DELETE FROM objects WHERE type=? AND id=?', (obj_type, ident)) c.execute('INSERT INTO objects (id, type, json) VALUES (?,?,?)', (ident, obj_type, jsonstr)) self.conn.commit() class ObjectStore(object): def __init__(self, location=None): self._lock = threading.Semaphore() self._connections = OrderedDict() self.location = location or config.get_object_store() with self._lock: self._init_db() def _init_db(self): conn = self._get_conn() c = conn.cursor() c.execute('''SELECT * FROM sqlite_master WHERE type='table' AND tbl_name='objects'; ''') res = c.fetchall() # Because the tasks are regarded as temporary resource, the task states # are purged every time the daemon startup if len(res) == 0: c.execute('''CREATE TABLE objects (id TEXT, type TEXT, json TEXT, PRIMARY KEY (id, type))''') conn.commit() return # Clear out expired objects from a previous session c.execute('''DELETE FROM objects WHERE type = 'task'; ''') conn.commit() def _get_conn(self): ident = threading.currentThread().ident try: return self._connections[ident] except KeyError: self._connections[ident] = sqlite3.connect(self.location, timeout=10) if len(self._connections.keys()) > 10: id, conn = self._connections.popitem(last=False) conn.interrupt() del conn return self._connections[ident] def __enter__(self): self._lock.acquire() return ObjectStoreSession(self._get_conn()) def __exit__(self, type, value, tb): self._lock.release() if type is not None and issubclass(type, sqlite3.DatabaseError): # Logs the error and return False, which makes __exit__ raise # exception again kimchi_log.error(traceback.format_exc()) return False kimchi-1.5.0/src/kimchi/osinfo.py000066400000000000000000000205021254252253000166620ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-2015 # # 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 import copy import glob import os import psutil from collections import defaultdict from configobj import ConfigObj from distutils.version import LooseVersion from kimchi.config import paths SUPPORTED_ARCHS = {'x86': ('i386', 'i686', 'x86_64'), 'power': ('ppc', 'ppc64'), 'ppc64le': ('ppc64le')} template_specs = {'x86': {'old': dict(disk_bus='ide', nic_model='e1000', sound_model='ich6'), 'modern': dict(disk_bus='virtio', nic_model='virtio', sound_model='ich6')}, 'power': {'old': dict(disk_bus='scsi', nic_model='spapr-vlan', cdrom_bus='scsi', kbd_type="kbd", kbd_bus='usb', mouse_bus='usb', tablet_bus='usb', memory=1280), 'modern': dict(disk_bus='virtio', nic_model='virtio', cdrom_bus='scsi', kbd_bus='usb', kbd_type="kbd", mouse_bus='usb', tablet_bus='usb', memory=1280)}, 'ppc64le': {'old': dict(disk_bus='virtio', nic_model='virtio', cdrom_bus='scsi', kbd_bus='usb', kbd_type="keyboard", mouse_bus='usb', tablet_bus='usb', memory=1280), 'modern': dict(disk_bus='virtio', nic_model='virtio', cdrom_bus='scsi', kbd_bus='usb', kbd_type="keyboard", mouse_bus='usb', tablet_bus='usb', memory=1280)}} custom_specs = {'fedora': {'22': dict(video_model='qxl')}} modern_version_bases = {'x86': {'debian': '6.0', 'ubuntu': '7.10', 'opensuse': '10.3', 'centos': '5.3', 'rhel': '6.0', 'fedora': '16', 'gentoo': '0', 'sles': '11', 'arch': '0'}, 'power': {'rhel': '6.5', 'fedora': '19', 'ubuntu': '14.04', 'opensuse': '13.1', 'sles': '11sp3'}, 'ppc64le': {'rhel': '6.5', 'fedora': '19', 'ubuntu': '14.04', 'opensuse': '13.1', 'sles': '11sp3'}} icon_available_distros = [icon[5:-4] for icon in glob.glob1('%s/images/' % paths.ui_dir, 'icon-*.png')] def _get_tmpl_defaults(): """ ConfigObj returns a dict like below when no changes were made in the template configuration file (template.conf) {'main': {}, 'storage': {'disk.0': {}}, 'processor': {}, 'graphics': {}} The default values should be like below: {'main': {'networks': ['default'], 'memory': '1024'}, 'storage': {'pool': 'default', 'disk.0': {'format': 'qcow2', 'size': '10'}}, 'processor': {'cpus': '1'}, 'graphics': {'type': 'spice', 'listen': '127.0.0.1'}} """ # Create dict with default values tmpl_defaults = defaultdict(dict) tmpl_defaults['main']['networks'] = ['default'] tmpl_defaults['main']['memory'] = 1024 tmpl_defaults['storage']['pool'] = 'default' tmpl_defaults['storage']['disk.0'] = {'size': 10, 'format': 'qcow2'} tmpl_defaults['processor']['cpus'] = 1 tmpl_defaults['graphics'] = {'type': 'vnc', 'listen': '127.0.0.1'} default_config = ConfigObj(tmpl_defaults) # Load template configuration file config_file = os.path.join(paths.conf_dir, 'template.conf') config = ConfigObj(config_file) # Merge default configuration with file configuration default_config.merge(config) # Create a dict with default values according to data structure # expected by VMTemplate defaults = {'domain': 'kvm', 'arch': os.uname()[4], 'cdrom_bus': 'ide', 'cdrom_index': 2, 'mouse_bus': 'ps2'} # Parse main section to get networks and memory values main_section = default_config.pop('main') defaults.update(main_section) # Parse storage section to get storage pool and disks values storage_section = default_config.pop('storage') defaults['storagepool'] = '/storagepools/' + storage_section.pop('pool') defaults['disks'] = [] for disk in storage_section.keys(): data = storage_section[disk] data['index'] = int(disk.split('.')[1]) defaults['disks'].append(data) # Parse processor section to get cpus and cpu_topology values processor_section = default_config.pop('processor') defaults['cpus'] = processor_section.pop('cpus') defaults['cpu_info'] = {} if len(processor_section.keys()) > 0: defaults['cpu_info']['topology'] = processor_section # Update defaults values with graphics values defaults['graphics'] = default_config.pop('graphics') return defaults # Set defaults values according to template.conf file defaults = _get_tmpl_defaults() def _get_arch(): for arch, sub_archs in SUPPORTED_ARCHS.iteritems(): if os.uname()[4] in sub_archs: return arch def get_template_default(template_type, field): host_arch = _get_arch() # Assuming 'power' = 'ppc64le' because lookup() does the same, # claiming libvirt compatibility. host_arch = 'power' if host_arch == 'ppc64le' else host_arch tmpl_defaults = copy.deepcopy(defaults) tmpl_defaults.update(template_specs[host_arch][template_type]) return tmpl_defaults[field] def lookup(distro, version): """ Lookup all parameters needed to run a VM of a known or unknown operating system type and version. The data is constructed by starting with the 'defaults' and merging the parameters given for the identified OS. If known, a link to a remote install CD is added. """ params = copy.deepcopy(defaults) params['os_distro'] = distro params['os_version'] = version arch = _get_arch() # Setting maxMemory of the VM, which will be equal total Host memory in Kib params['max_memory'] = psutil.TOTAL_PHYMEM >> 10 # set up arch to ppc64 instead of ppc64le due to libvirt compatibility if params["arch"] == "ppc64le": params["arch"] = "ppc64" if distro in modern_version_bases[arch]: if LooseVersion(version) >= LooseVersion( modern_version_bases[arch][distro]): params.update(template_specs[arch]['modern']) else: params.update(template_specs[arch]['old']) else: params['os_distro'] = params['os_version'] = "unknown" params.update(template_specs[arch]['old']) # Get custom specifications params.update(custom_specs.get(distro, {}).get(version, {})) if distro in icon_available_distros: params['icon'] = 'images/icon-%s.png' % distro else: params['icon'] = 'images/icon-vm.png' return params kimchi-1.5.0/src/kimchi/proxy.py000066400000000000000000000072541254252253000165570ustar00rootroot00000000000000#!/usr/bin/python # # Project Kimchi # # Copyright IBM, Corp. 2014-2015 # # 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 module contains functions that the manipulate # and configure the Nginx proxy. import os import pwd import subprocess from string import Template from kimchi import sslcert from kimchi.config import paths def _create_proxy_config(options): """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 'kimchi.conf' which will be used to launch the proxy. Arguments: options - OptionParser object with Kimchi config options """ # User that will run the worker process of the proxy. Fedora, # RHEL and Suse creates an user called 'nginx' when installing # the proxy. Ubuntu creates an user 'www-data' for it. user_proxy = 'nginx' try: pwd.getpwnam(user_proxy) except KeyError: user_proxy = 'www-data' config_dir = paths.conf_dir nginx_config_dir = paths.nginx_conf_dir cert = options.ssl_cert key = options.ssl_key # No certificates specified by the user if not cert or not key: cert = '%s/kimchi-cert.pem' % config_dir key = '%s/kimchi-key.pem' % config_dir # create cert files if they don't exist if not os.path.exists(cert) or not os.path.exists(key): ssl_gen = sslcert.SSLCert() with open(cert, "w") as f: f.write(ssl_gen.cert_pem()) with open(key, "w") as f: f.write(ssl_gen.key_pem()) # Setting up Diffie-Hellman group with 2048-bit file dhparams_pem = os.path.join(config_dir, "dhparams.pem") # Read template file and create a new config file # with the specified parameters. with open(os.path.join(nginx_config_dir, "kimchi.conf.in")) as template: data = template.read() data = Template(data) data = data.safe_substitute(user=user_proxy, proxy_port=options.port, kimchid_port=options.cherrypy_port, proxy_ssl_port=options.ssl_port, cert_pem=cert, cert_key=key, max_body_size=eval(options.max_body_size), dhparams_pem=dhparams_pem) # Write file to be used for nginx. config_file = open(os.path.join(nginx_config_dir, "kimchi.conf"), "w") config_file.write(data) config_file.close() def start_proxy(options): """Start nginx reverse proxy.""" _create_proxy_config(options) nginx_config_dir = paths.nginx_conf_dir config_file = "%s/kimchi.conf" % nginx_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) kimchi-1.5.0/src/kimchi/repositories.py000066400000000000000000000410061254252253000201160ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2014-2015 # # 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 import copy import os import time import urlparse from ConfigParser import ConfigParser from kimchi.basemodel import Singleton from kimchi.config import kimchiLock from kimchi.exception import InvalidOperation, InvalidParameter from kimchi.exception import OperationFailed, NotFoundError, MissingParameter from kimchi.utils import validate_repo_url from kimchi.yumparser import get_yum_repositories, write_repo_to_file class Repositories(object): __metaclass__ = Singleton """ Class to represent and operate with repositories information. """ def __init__(self): try: __import__('yum') self._pkg_mnger = YumRepo() except ImportError: try: __import__('apt_pkg') self._pkg_mnger = AptRepo() except ImportError: raise InvalidOperation('KCHREPOS0014E') def addRepository(self, params): """ Add and enable a new repository """ config = params.get('config', {}) extra_keys = list( set(config.keys()).difference(set(self._pkg_mnger.CONFIG_ENTRY))) if len(extra_keys) > 0: raise InvalidParameter("KCHREPOS0028E", {'items': ",".join(extra_keys)}) return self._pkg_mnger.addRepo(params) def getRepositories(self): """ Return a dictionary with all Kimchi's repositories. Each element uses the format {: {repo}}, where repo is a dictionary in the repositories.Repositories() format. """ return self._pkg_mnger.getRepositoriesList() def getRepository(self, repo_id): """ Return a dictionary with all info from a given repository ID. """ info = self._pkg_mnger.getRepo(repo_id) info['repo_id'] = repo_id return info def enableRepository(self, repo_id): """ Enable a repository. """ return self._pkg_mnger.toggleRepo(repo_id, True) def disableRepository(self, repo_id): """ Disable a given repository. """ return self._pkg_mnger.toggleRepo(repo_id, False) def updateRepository(self, repo_id, params): """ Update the information of a given repository. The input is the repo_id of the repository to be updated and a dict with the information to be updated. """ return self._pkg_mnger.updateRepo(repo_id, params) def removeRepository(self, repo_id): """ Remove a given repository """ return self._pkg_mnger.removeRepo(repo_id) class YumRepo(object): """ Class to represent and operate with YUM repositories. It's loaded only on those systems listed at YUM_DISTROS and loads necessary modules in runtime. """ TYPE = 'yum' DEFAULT_CONF_DIR = "/etc/yum.repos.d" CONFIG_ENTRY = ('repo_name', 'mirrorlist', 'metalink') def __init__(self): self._confdir = self.DEFAULT_CONF_DIR def _get_repos(self, errcode): try: kimchiLock.acquire() repos = get_yum_repositories() except Exception, e: kimchiLock.release() raise OperationFailed(errcode, {'err': str(e)}) finally: kimchiLock.release() return repos def getRepositoriesList(self): """ Return a list of repositories IDs """ repos = self._get_repos('KCHREPOS0024E') return repos.keys() def getRepo(self, repo_id): """ Return a dictionary in the repositories.Repositories() of the given repository ID format with the information of a YumRepository object. """ repos = self._get_repos('KCHREPOS0025E') if repo_id not in repos.keys(): raise NotFoundError("KCHREPOS0012E", {'repo_id': repo_id}) entry = repos.get(repo_id) info = {} info['enabled'] = entry.enabled info['baseurl'] = entry.baseurl or '' info['config'] = {} info['config']['repo_name'] = entry.name or '' info['config']['gpgcheck'] = entry.gpgcheck info['config']['gpgkey'] = entry.gpgkey or '' info['config']['mirrorlist'] = entry.mirrorlist or '' info['config']['metalink'] = entry.metalink or '' return info def addRepo(self, params): """ Add a given repository to YumBase """ # At least one base url, or one mirror, must be given. baseurl = params.get('baseurl', '') config = params.get('config', {}) mirrorlist = config.get('mirrorlist', '') metalink = config.get('metalink', '') if not baseurl and not mirrorlist and not metalink: raise MissingParameter("KCHREPOS0013E") if baseurl: validate_repo_url(baseurl) if mirrorlist: validate_repo_url(mirrorlist) if metalink: validate_repo_url(metalink) if mirrorlist and metalink: raise InvalidOperation('KCHREPOS0030E') repo_id = params.get('repo_id', None) if repo_id is None: repo_id = "kimchi_repo_%s" % str(int(time.time() * 1000)) repos = self._get_repos('KCHREPOS0026E') if repo_id in repos.keys(): raise InvalidOperation("KCHREPOS0022E", {'repo_id': repo_id}) repo_name = config.get('repo_name', repo_id) repo = {'baseurl': baseurl, 'mirrorlist': mirrorlist, 'name': repo_name, 'gpgcheck': 1, 'gpgkey': [], 'enabled': 1, 'metalink': metalink} # write a repo file in the system with repo{} information. parser = ConfigParser() parser.add_section(repo_id) for key, value in repo.iteritems(): if value: parser.set(repo_id, key, value) repofile = os.path.join(self._confdir, repo_id + '.repo') try: with open(repofile, 'w') as fd: parser.write(fd) except: raise OperationFailed("KCHREPOS0018E", {'repo_file': repofile}) return repo_id def toggleRepo(self, repo_id, enable): repos = self._get_repos('KCHREPOS0011E') if repo_id not in repos.keys(): raise NotFoundError("KCHREPOS0012E", {'repo_id': repo_id}) entry = repos.get(repo_id) if enable and entry.enabled: raise InvalidOperation("KCHREPOS0015E", {'repo_id': repo_id}) if not enable and not entry.enabled: raise InvalidOperation("KCHREPOS0016E", {'repo_id': repo_id}) kimchiLock.acquire() try: if enable: entry.enable() else: entry.disable() write_repo_to_file(entry) except: if enable: raise OperationFailed("KCHREPOS0020E", {'repo_id': repo_id}) raise OperationFailed("KCHREPOS0021E", {'repo_id': repo_id}) finally: kimchiLock.release() return repo_id def updateRepo(self, repo_id, params): """ Update a given repository in repositories.Repositories() format """ repos = self._get_repos('KCHREPOS0011E') if repo_id not in repos.keys(): raise NotFoundError("KCHREPOS0012E", {'repo_id': repo_id}) entry = repos.get(repo_id) baseurl = params.get('baseurl', None) config = params.get('config', {}) mirrorlist = config.get('mirrorlist', None) metalink = config.get('metalink', None) if baseurl is not None and len(baseurl.strip()) == 0: baseurl = None if mirrorlist is not None and len(mirrorlist.strip()) == 0: mirrorlist = None if metalink is not None and len(metalink.strip()) == 0: metalink = None if baseurl is None and mirrorlist is None and metalink is None: raise MissingParameter("KCHREPOS0013E") if baseurl is not None: validate_repo_url(baseurl) entry.baseurl = baseurl if mirrorlist is not None: validate_repo_url(mirrorlist) entry.mirrorlist = mirrorlist if metalink is not None: validate_repo_url(metalink) entry.metalink = metalink if mirrorlist and metalink: raise InvalidOperation('KCHREPOS0030E') entry.id = params.get('repo_id', repo_id) entry.name = config.get('repo_name', entry.name) entry.gpgcheck = config.get('gpgcheck', entry.gpgcheck) entry.gpgkey = config.get('gpgkey', entry.gpgkey) kimchiLock.acquire() write_repo_to_file(entry) kimchiLock.release() return repo_id def removeRepo(self, repo_id): """ Remove a given repository """ repos = self._get_repos('KCHREPOS0027E') if repo_id not in repos.keys(): raise NotFoundError("KCHREPOS0012E", {'repo_id': repo_id}) entry = repos.get(repo_id) parser = ConfigParser() with open(entry.repofile) as fd: parser.readfp(fd) if len(parser.sections()) == 1: os.remove(entry.repofile) return parser.remove_section(repo_id) with open(entry.repofile, "w") as fd: parser.write(fd) class AptRepo(object): """ Class to represent and operate with YUM repositories. It's loaded only on those systems listed at YUM_DISTROS and loads necessary modules in runtime. """ TYPE = 'deb' KIMCHI_LIST = "kimchi-source.list" CONFIG_ENTRY = ('dist', 'comps') def __init__(self): getattr(__import__('apt_pkg'), 'init_config')() getattr(__import__('apt_pkg'), 'init_system')() config = getattr(__import__('apt_pkg'), 'config') self.pkg_lock = getattr(__import__('apt_pkg'), 'SystemLock') module = __import__('aptsources.sourceslist', globals(), locals(), ['SourcesList'], -1) self._sourceparts_path = '/%s%s' % ( config.get('Dir::Etc'), config.get('Dir::Etc::sourceparts')) self._sourceslist = getattr(module, 'SourcesList') self.filename = os.path.join(self._sourceparts_path, self.KIMCHI_LIST) if not os.path.exists(self.filename): with open(self.filename, 'w') as fd: fd.write("# This file is managed by Kimchi and it must not " "be modified manually\n") def _get_repos(self): try: with self.pkg_lock(): repos = self._sourceslist() repos.refresh() except Exception, e: kimchiLock.release() raise OperationFailed('KCHREPOS0025E', {'err': e.message}) return repos def _get_repo_id(self, repo): data = urlparse.urlparse(repo.uri) name = data.hostname or data.path return '%s-%s-%s' % (name, repo.dist, "-".join(repo.comps)) def _get_source_entry(self, repo_id): kimchiLock.acquire() repos = self._get_repos() kimchiLock.release() for r in repos: # Ignore deb-src repositories if r.type != 'deb': continue if self._get_repo_id(r) != repo_id: continue return r return None def getRepositoriesList(self): """ Return a list of repositories IDs APT repositories there aren't the concept about repository ID, so for internal control, the repository ID will be built as described in _get_repo_id() """ kimchiLock.acquire() repos = self._get_repos() kimchiLock.release() res = [] for r in repos: # Ignore deb-src repositories if r.type != 'deb': continue res.append(self._get_repo_id(r)) return res def getRepo(self, repo_id): """ Return a dictionary in the repositories.Repositories() format of the given repository ID with the information of a SourceEntry object. """ r = self._get_source_entry(repo_id) if r is None: raise NotFoundError("KCHREPOS0012E", {'repo_id': repo_id}) info = {'enabled': not r.disabled, 'baseurl': r.uri, 'config': {'dist': r.dist, 'comps': r.comps}} return info def addRepo(self, params): """ Add a new APT repository based on """ # To create a APT repository the dist is a required parameter # (in addition to baseurl, verified on controller through API.json) config = params.get('config', None) if config is None: raise MissingParameter("KCHREPOS0019E") if 'dist' not in config.keys(): raise MissingParameter("KCHREPOS0019E") uri = params['baseurl'] dist = config['dist'] comps = config.get('comps', []) validate_repo_url(uri) kimchiLock.acquire() try: repos = self._get_repos() source_entry = repos.add('deb', uri, dist, comps, file=self.filename) with self.pkg_lock(): repos.save() except Exception as e: kimchiLock.release() raise OperationFailed("KCHREPOS0026E", {'err': e.message}) kimchiLock.release() return self._get_repo_id(source_entry) def toggleRepo(self, repo_id, enable): """ Enable a given repository """ r = self._get_source_entry(repo_id) if r is None: raise NotFoundError("KCHREPOS0012E", {'repo_id': repo_id}) if enable and not r.disabled: raise InvalidOperation("KCHREPOS0015E", {'repo_id': repo_id}) if not enable and r.disabled: raise InvalidOperation("KCHREPOS0016E", {'repo_id': repo_id}) if enable: line = 'deb' else: line = '#deb' kimchiLock.acquire() try: repos = self._get_repos() with self.pkg_lock(): repos.remove(r) repos.add(line, r.uri, r.dist, r.comps, file=self.filename) repos.save() except: kimchiLock.release() if enable: raise OperationFailed("KCHREPOS0020E", {'repo_id': repo_id}) raise OperationFailed("KCHREPOS0021E", {'repo_id': repo_id}) finally: kimchiLock.release() return repo_id def updateRepo(self, repo_id, params): """ Update a given repository in repositories.Repositories() format """ old_info = self.getRepo(repo_id) updated_info = copy.deepcopy(old_info) updated_info['baseurl'] = params.get( 'baseurl', updated_info['baseurl']) if 'config' in params.keys(): config = params['config'] updated_info['config']['dist'] = config.get( 'dist', old_info['config']['dist']) updated_info['config']['comps'] = config.get( 'comps', old_info['config']['comps']) self.removeRepo(repo_id) try: return self.addRepo(updated_info) except: self.addRepo(old_info) raise def removeRepo(self, repo_id): """ Remove a given repository """ r = self._get_source_entry(repo_id) if r is None: raise NotFoundError("KCHREPOS0012E", {'repo_id': repo_id}) kimchiLock.acquire() try: repos = self._get_repos() with self.pkg_lock(): repos.remove(r) repos.save() except: kimchiLock.release() raise OperationFailed("KCHREPOS0017E", {'repo_id': repo_id}) finally: kimchiLock.release() kimchi-1.5.0/src/kimchi/rollbackcontext.py000066400000000000000000000044721254252253000205730ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-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 # import sys class RollbackContext(object): ''' A context manager for recording and playing rollback. The first exception will be remembered and re-raised after rollback Sample usage: with RollbackContext() as rollback: step1() rollback.prependDefer(lambda: undo step1) def undoStep2(arg): pass step2() rollback.prependDefer(undoStep2, arg) ''' def __init__(self, *args): self._finally = [] def __enter__(self): return self def __exit__(self, exc_type, exc_value, traceback): """ According to Python official doc. This function should only re-raise the exception from undo functions. Python automatically re-raises the original exception when this function does not return True. http://docs.python.org/2/library/stdtypes.html#contextmanager.__exit__ """ undoExcInfo = None for undo, args, kwargs in self._finally: try: undo(*args, **kwargs) except Exception: # keep the earliest exception info if undoExcInfo is None: undoExcInfo = sys.exc_info() if exc_type is None and undoExcInfo is not None: raise undoExcInfo[0], undoExcInfo[1], undoExcInfo[2] def defer(self, func, *args, **kwargs): self._finally.append((func, args, kwargs)) def prependDefer(self, func, *args, **kwargs): self._finally.insert(0, (func, args, kwargs)) def commitAll(self): self._finally = [] kimchi-1.5.0/src/kimchi/root.py000066400000000000000000000125171254252253000163570ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-2015 # # 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 import cherrypy import json import os from distutils.version import LooseVersion from kimchi import auth from kimchi import template from kimchi.i18n import messages from kimchi.config import paths from kimchi.control import sub_nodes from kimchi.control.base import Resource from kimchi.control.utils import parse_request from kimchi.exception import MissingParameter, OperationFailed class Root(Resource): def __init__(self, model, dev_env=False): 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'] if not dev_env: self._cp_config = dict([(key, self.error_production_handler) for key in self._handled_error]) else: self._cp_config = dict([(key, self.error_development_handler) for key in self._handled_error]) def _set_CSP(self): # set Content-Security-Policy to prevent XSS attacks headers = cherrypy.response.headers headers['Content-Security-Policy'] = "default-src 'self'" def error_production_handler(self, status, message, traceback, version): self._set_CSP() data = {'code': status, 'reason': message} res = template.render('error.html', data) if (type(res) is unicode and LooseVersion(cherrypy.__version__) < LooseVersion('3.2.5')): res = res.encode("utf-8") return res def error_development_handler(self, status, message, traceback, version): self._set_CSP() data = {'code': status, 'reason': message, 'call_stack': cherrypy._cperror.format_exc()} res = template.render('error.html', data) if (type(res) is unicode and LooseVersion(cherrypy.__version__) < LooseVersion('3.2.5')): res = res.encode("utf-8") return res def get(self): last_page = cherrypy.request.cookie.get("lastPage") # when session timeout, only session cookie is None. # when first login, both session and lastPage are None. if (cherrypy.session.originalid is None and last_page is None and not template.can_accept('application/json') and template.can_accept_html()): raise cherrypy.HTTPRedirect("/login.html", 303) return self.default(self.default_page) @cherrypy.expose def default(self, page, **kwargs): if page.endswith('.html'): return template.render(page, kwargs) if page.endswith('.json'): cherrypy.response.headers['Content-Type'] = \ 'application/json;charset=utf-8' context = template.render_cheetah_file(page, None) return context.encode("utf-8") raise cherrypy.HTTPError(404) @cherrypy.expose def tabs(self, page, **kwargs): # In order to load the Guests tab, we also use Cheetah in the tab # template to save the delay of the extra get to the guest page # For that, the tab template needs to know the correct path to ui files data = {} data['ui_dir'] = paths.ui_dir if page.endswith('.html'): context = template.render('tabs/' + page, data) cherrypy.response.cookie[ "lastPage"] = "/#tabs/" + page[:-5] cherrypy.response.cookie['lastPage']['path'] = '/' return context raise cherrypy.HTTPError(404) class KimchiRoot(Root): def __init__(self, model, dev_env): super(KimchiRoot, self).__init__(model, dev_env) self.default_page = 'kimchi-ui.html' for ident, node in sub_nodes.items(): setattr(self, ident, node(model)) with open(os.path.join(paths.src_dir, 'API.json')) as f: self.api_schema = json.load(f) self.paths = paths self.domain = 'kimchi' self.messages = messages @cherrypy.expose def login(self, *args): try: params = parse_request() username = params['username'] password = params['password'] except KeyError, item: e = MissingParameter('KCHAUTH0003E', {'item': str(item)}) raise cherrypy.HTTPError(400, e.message) try: user_info = auth.login(username, password) except OperationFailed: raise cherrypy.HTTPError(401) return json.dumps(user_info) @cherrypy.expose def logout(self): auth.logout() return '{}' kimchi-1.5.0/src/kimchi/scan.py000066400000000000000000000056661254252253000163270ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-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 # import glob import hashlib import os.path import shutil import tempfile import time from kimchi.isoinfo import IsoImage, probe_iso from kimchi.utils import kimchi_log SCAN_IGNORE = ['/tmp/kimchi-scan-*'] class Scanner(object): SCAN_TTL = 300 def __init__(self, record_clean_cb): self.clean_cb = record_clean_cb def delete(self): self.clean_stale(-1) def clean_stale(self, window=SCAN_TTL): """ Clear scan pools generated before time window, Clear all scan pools if window is -1. """ try: now = time.time() clean_list = glob.glob("/tmp/kimchi-scan-*") for d in clean_list: transient_pool = \ os.path.basename(d).replace('kimchi-scan-', '')[0: -6] if now - os.path.getmtime(d) > window: shutil.rmtree(d) self.clean_cb(transient_pool) except OSError as e: msg = "Exception %s occured when cleaning stale pool, ignore" kimchi_log.debug(msg % e.message) def scan_dir_prepare(self, name): # clean stale scan storage pools self.clean_stale() return tempfile.mkdtemp(prefix='kimchi-scan-' + name, dir='/tmp') def start_scan(self, cb, params): def updater(iso_info): iso_name = os.path.basename(iso_info['path'])[:-3] duplicates = "%s/%s*" % (params['pool_path'], iso_name) for f in glob.glob(duplicates): iso_img = IsoImage(f) if (iso_info['distro'], iso_info['version']) == \ iso_img.probe(): return iso_path = iso_name + hashlib.md5(iso_info['path']).hexdigest() + \ '.iso' link_name = os.path.join(params['pool_path'], os.path.basename(iso_path)) os.symlink(iso_info['path'], link_name) ignore_paths = params.get('ignore_list', []) scan_params = dict(path=params['scan_path'], updater=updater, ignore_list=ignore_paths + SCAN_IGNORE) probe_iso(None, scan_params) cb('', True) kimchi-1.5.0/src/kimchi/screenshot.py000066400000000000000000000132041254252253000175430ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-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 # import glob import os import signal import tempfile import time import uuid try: from PIL import Image except ImportError: import Image from kimchi import config from kimchi.utils import kimchi_log (fd, pipe) = tempfile.mkstemp() stream_test_result = None class VMScreenshot(object): OUTDATED_SECS = 5 THUMBNAIL_SIZE = (256, 256) LIVE_WINDOW = 60 MAX_STREAM_ATTEMPTS = 10 def __init__(self, args): self.vm_uuid = args['uuid'] args.setdefault('thumbnail', os.path.join(config.get_screenshot_path(), '%s-%s.png' % (self.vm_uuid, str(uuid.uuid4())))) self.info = args @staticmethod def get_stream_test_result(): return stream_test_result def lookup(self): now = time.time() try: last_update = os.path.getmtime(self.info['thumbnail']) except OSError: last_update = 0 if now - last_update > self.OUTDATED_SECS: self._clean_extra(self.LIVE_WINDOW) self._generate_thumbnail() return '/data/screenshots/%s' %\ os.path.basename(self.info['thumbnail']) def _clean_extra(self, window=-1): """ Clear screenshots before time specified by window, Clear all screenshots if window is -1. """ try: now = time.time() clear_list = glob.glob("%s/%s-*.png" % (config.get_screenshot_path(), self.vm_uuid)) for f in clear_list: if now - os.path.getmtime(f) > window: os.unlink(f) except OSError: pass def delete(self): return self._clean_extra() def _generate_scratch(self, thumbnail): """ Generate screenshot of given vm. Override me in child class. """ pass def _create_black_image(self, thumbnail): image = Image.new("RGB", self.THUMBNAIL_SIZE, 'black') image.save(thumbnail) def _watch_stream_creation(self, thumbnail): """ This is a verification test for libvirt stream functionality. It is necessary to avoid the server hangs while creating the screenshot image using libvirt stream API. This problem was found in libvirt 0.9.6 for SLES11 SP2. This test consists in running the screeshot creation with a timeout. If timeout occurs, the libvirt is taking too much time to create the screenshot image and the stream must be disabled it if happens successively (to avoid blocking server requests). """ pid = os.fork() if pid == 0: try: self._generate_scratch(thumbnail) os._exit(0) except: os._exit(1) else: counter = 0 ret = os.waitpid(pid, os.WNOHANG) while ret == (0, 0) and counter < 3: counter += 1 time.sleep(1) ret = os.waitpid(pid, os.WNOHANG) fd = open(pipe, "a") if ret != (pid, 0): fd.write("-") if ret[0] != pid: os.kill(int(pid), signal.SIGKILL) os.waitpid(pid, 0) else: fd.write("+") fd.close() def _get_test_result(self): if not os.path.exists(pipe): return fd = open(pipe, "r") data = fd.read() fd.close() if len(data) >= self.MAX_STREAM_ATTEMPTS or bool('+' in data): global stream_test_result stream_test_result = bool('+' in data) os.remove(pipe) def _generate_thumbnail(self): thumbnail = os.path.join(config.get_screenshot_path(), '%s-%s.png' % (self.vm_uuid, str(uuid.uuid4()))) self._get_test_result() if stream_test_result is None: self._watch_stream_creation(thumbnail) elif stream_test_result: try: self._generate_scratch(thumbnail) except: kimchi_log.error("screenshot_creation: Unable to create " "screenshot image %s." % thumbnail) else: self._create_black_image(thumbnail) if os.path.getsize(thumbnail) == 0: self._create_black_image(thumbnail) else: im = Image.open(thumbnail) try: # Prevent Image lib from lazy load, # work around pic truncate validation in thumbnail generation im.thumbnail(self.THUMBNAIL_SIZE) except Exception as e: kimchi_log.warning("Image load with warning: %s." % e) im.save(thumbnail, "PNG") self.info['thumbnail'] = thumbnail kimchi-1.5.0/src/kimchi/server.py000066400000000000000000000153651254252253000167060ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-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 # import cherrypy import logging import logging.handlers import os from kimchi import auth from kimchi import config from kimchi.model import model from kimchi import mockmodel from kimchi import vnc from kimchi.config import KimchiConfig, PluginConfig from kimchi.control import sub_nodes from kimchi.proxy import start_proxy, terminate_proxy from kimchi.root import KimchiRoot from kimchi.utils import get_enabled_plugins, import_class LOGGING_LEVEL = {"debug": logging.DEBUG, "info": logging.INFO, "warning": logging.WARNING, "error": logging.ERROR, "critical": logging.CRITICAL} def set_no_cache(): from time import strftime, gmtime h = [('Expires', 'Mon, 26 Jul 1997 05:00:00 GMT'), ('Cache-Control', 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0'), ('Pragma', 'no-cache'), ('Last-Modified', strftime("%a, %d %b %Y %H:%M:%S GMT", gmtime()))] hList = cherrypy.response.header_list if isinstance(hList, list): hList.extend(h) else: hList = h class Server(object): def __init__(self, options): # Launch reverse proxy start_proxy(options) make_dirs = [ os.path.dirname(os.path.abspath(options.access_log)), os.path.dirname(os.path.abspath(options.error_log)), os.path.dirname(os.path.abspath(config.get_object_store())), os.path.abspath(config.get_screenshot_path()), os.path.abspath(config.get_debugreports_path()), os.path.abspath(config.get_distros_store()) ] for directory in make_dirs: if not os.path.isdir(directory): os.makedirs(directory) self.configObj = KimchiConfig() # We'll use the session timeout (= 10 minutes) and the # nginx timeout (= 10 minutes). This monitor isn't involved # in anything other than monitor the timeout of the connection, # thus it is safe to unsubscribe. cherrypy.engine.timeout_monitor.unsubscribe() cherrypy.tools.nocache = cherrypy.Tool('on_end_resource', set_no_cache) cherrypy.tools.kimchiauth = cherrypy.Tool('before_handler', auth.kimchiauth) # Setting host to 127.0.0.1. This makes kimchi runs # as a localhost app, inaccessible to the outside # directly. You must go through the proxy. cherrypy.server.socket_host = '127.0.0.1' cherrypy.server.socket_port = options.cherrypy_port max_body_size_in_bytes = eval(options.max_body_size) * 1024 cherrypy.server.max_request_body_size = max_body_size_in_bytes cherrypy.log.access_file = options.access_log cherrypy.log.error_file = options.error_log logLevel = LOGGING_LEVEL.get(options.log_level, logging.DEBUG) dev_env = options.environment != 'production' # Enable cherrypy screen logging if running environment # is not 'production' if dev_env: cherrypy.log.screen = True # Create handler to rotate access log file h = logging.handlers.RotatingFileHandler(options.access_log, 'a', 10000000, 1000) h.setLevel(logLevel) h.setFormatter(cherrypy._cplogging.logfmt) # Add access log file to cherrypy configuration cherrypy.log.access_log.addHandler(h) # Create handler to rotate error log file h = logging.handlers.RotatingFileHandler(options.error_log, 'a', 10000000, 1000) h.setLevel(logLevel) h.setFormatter(cherrypy._cplogging.logfmt) # Add rotating log file to cherrypy configuration cherrypy.log.error_log.addHandler(h) # Handling running mode if not dev_env: cherrypy.config.update({'environment': 'production'}) if hasattr(options, 'model'): model_instance = options.model elif options.test: model_instance = mockmodel.MockModel() else: model_instance = model.Model() if isinstance(model_instance, model.Model): vnc_ws_proxy = vnc.new_ws_proxy() cherrypy.engine.subscribe('exit', vnc_ws_proxy.terminate) for ident, node in sub_nodes.items(): if node.url_auth: cfg = self.configObj ident = "/%s" % ident cfg[ident] = {'tools.kimchiauth.on': True} self.app = cherrypy.tree.mount(KimchiRoot(model_instance, dev_env), config=self.configObj) self._load_plugins() # Terminate proxy when cherrypy server is terminated cherrypy.engine.subscribe('exit', terminate_proxy) cherrypy.lib.sessions.init() def _load_plugins(self): for plugin_name, plugin_config in get_enabled_plugins(): try: plugin_class = ('plugins.%s.%s' % (plugin_name, plugin_config['kimchi']['plugin_class'])) script_name = plugin_config['kimchi']['uri'] del plugin_config['kimchi'] plugin_config.update(PluginConfig(plugin_name)) except KeyError: continue try: plugin_app = import_class(plugin_class)() except ImportError: cherrypy.log.error_log.error("Failed to import plugin %s" % plugin_class) continue cherrypy.tree.mount(plugin_app, script_name, plugin_config) def start(self): # Subscribe to SignalHandler plugin if hasattr(cherrypy.engine, 'signal_handler'): cherrypy.engine.signal_handler.subscribe() cherrypy.engine.start() cherrypy.engine.block() def stop(self): cherrypy.engine.exit() def main(options): srv = Server(options) srv.start() kimchi-1.5.0/src/kimchi/sslcert.py000066400000000000000000000050241254252253000170460ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-2014 # Copyright (C) 2004-2005 OSAF. All Rights Reserved. # # Portions of this file were derived from the python-m2crypto unit tests: # http://svn.osafoundation.org/m2crypto/trunk/tests/test_x509.py # # 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 import time from M2Crypto import ASN1, EVP, RSA, X509 class SSLCert(object): def __init__(self): self._gen() def _gen(self): def keygen_cb(*args): pass def passphrase_cb(*args): return '' self.cert = X509.X509() pubkey = EVP.PKey() rsa = RSA.gen_key(2048, 65537, keygen_cb) pubkey.assign_rsa(rsa) self._key = rsa.as_pem(None, callback=passphrase_cb) rsa = None # Set a serial number that is unlikely to repeat sn = int(time.time()) % (2 ** 32 - 1) self.cert.set_serial_number(sn) self.cert.set_version(2) subject = self.cert.get_subject() subject.C = 'US' subject.CN = 'kimchi' subject.O = 'kimchi-project.org' t = long(time.time()) + time.timezone now = ASN1.ASN1_UTCTIME() now.set_time(t) nowPlusYear = ASN1.ASN1_UTCTIME() nowPlusYear.set_time(t + 60 * 60 * 24 * 365) self.cert.set_not_before(now) self.cert.set_not_after(nowPlusYear) issuer = X509.X509_Name() issuer.CN = 'kimchi' issuer.O = 'kimchi-project.org' self.cert.set_issuer(issuer) self.cert.set_pubkey(pubkey) self.cert.sign(pubkey, 'sha1') def cert_text(self): return self.cert.as_text() def cert_pem(self): return self.cert.as_pem() def key_pem(self): return self._key def main(): c = SSLCert() print c.cert_text() print c.cert_pem() print c.key_pem() if __name__ == '__main__': main() kimchi-1.5.0/src/kimchi/swupdate.py000066400000000000000000000214241254252253000172250ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2014-2015 # # 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 import subprocess import time from kimchi.basemodel import Singleton from kimchi.config import kimchiLock from kimchi.exception import NotFoundError, OperationFailed from kimchi.utils import kimchi_log, run_command from kimchi.yumparser import get_yum_packages_list_update class SoftwareUpdate(object): __metaclass__ = Singleton """ Class to represent and operate with OS software update. """ def __init__(self): # This stores all packages to be updated for Kimchi perspective. It's a # dictionary of dictionaries, in the format {'package_name': package}, # where: # package = {'package_name': , 'version': , # 'arch': , 'repository': # } self._packages = {} # This stores the number of packages to update self._num2update = 0 # Get the distro of host machine and creates an object related to # correct package management system try: __import__('yum') kimchi_log.info("Loading YumUpdate features.") self._pkg_mnger = YumUpdate() except ImportError: try: __import__('apt') kimchi_log.info("Loading AptUpdate features.") self._pkg_mnger = AptUpdate() except ImportError: zypper_help = ["zypper", "--help"] (stdout, stderr, returncode) = run_command(zypper_help) if returncode == 0: kimchi_log.info("Loading ZypperUpdate features.") self._pkg_mnger = ZypperUpdate() else: raise Exception("There is no compatible package manager " "for this system.") def _scanUpdates(self): """ Update self._packages with packages to be updated. """ self._packages = {} self._num2update = 0 # Call system pkg_mnger to get the packages as list of dictionaries. for pkg in self._pkg_mnger.getPackagesList(): # Check if already exist a package in self._packages pkg_id = pkg.get('package_name') if pkg_id in self._packages.keys(): # package already listed to update. do nothing continue # Update the self._packages and self._num2update self._packages[pkg_id] = pkg self._num2update = self._num2update + 1 def getUpdates(self): """ Return the self._packages. """ self._scanUpdates() return self._packages def getUpdate(self, name): """ Return a dictionary with all info from a given package name. """ if name not in self._packages.keys(): raise NotFoundError('KCHPKGUPD0002E', {'name': name}) return self._packages[name] def getNumOfUpdates(self): """ Return the number of packages to be updated. """ self._scanUpdates() return self._num2update def doUpdate(self, cb, params): """ Execute the update """ # reset messages cb('') cmd = self._pkg_mnger.update_cmd proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) msgs = [] while proc.poll() is None: msgs.append(proc.stdout.readline()) cb(''.join(msgs)) time.sleep(0.5) # read the final output lines msgs.extend(proc.stdout.readlines()) retcode = proc.poll() if retcode == 0: return cb(''.join(msgs), True) msgs.extend(proc.stderr.readlines()) return cb(''.join(msgs), False) class YumUpdate(object): """ Class to represent and operate with YUM software update system. It's loaded only on those systems listed at YUM_DISTROS and loads necessary modules in runtime. """ def __init__(self): self._pkgs = {} self.update_cmd = ["yum", "-y", "update"] def _refreshUpdateList(self): """ Update the list of packages to be updated in the system. """ try: kimchiLock.acquire() self._pkgs = get_yum_packages_list_update() except Exception, e: raise OperationFailed('KCHPKGUPD0003E', {'err': str(e)}) finally: kimchiLock.release() def getPackagesList(self): """ Return a list of package's dictionaries. Each dictionary contains the information about a package, in the format: package = {'package_name': , 'version': , 'arch': , 'repository': } """ self._refreshUpdateList() pkg_list = [] for pkg in self._pkgs: package = {'package_name': pkg.name, 'version': pkg.version, 'arch': pkg.arch, 'repository': pkg.ui_from_repo} pkg_list.append(package) return pkg_list class AptUpdate(object): """ Class to represent and operate with APT software update system. It's loaded only on those systems listed at APT_DISTROS and loads necessary modules in runtime. """ def __init__(self): self._pkgs = {} self.pkg_lock = getattr(__import__('apt_pkg'), 'SystemLock') self.update_cmd = ['apt-get', 'upgrade', '-y'] def _refreshUpdateList(self): """ Update the list of packages to be updated in the system. """ apt_cache = getattr(__import__('apt'), 'Cache')() try: with self.pkg_lock(): apt_cache.update() apt_cache.upgrade() self._pkgs = apt_cache.get_changes() except Exception, e: kimchiLock.release() raise OperationFailed('KCHPKGUPD0003E', {'err': e.message}) def getPackagesList(self): """ Return a list of package's dictionaries. Each dictionary contains the information about a package, in the format package = {'package_name': , 'version': , 'arch': , 'repository': } """ kimchiLock.acquire() self._refreshUpdateList() kimchiLock.release() pkg_list = [] for pkg in self._pkgs: package = {'package_name': pkg.shortname, 'version': pkg.candidate.version, 'arch': pkg._pkg.architecture, 'repository': pkg.candidate.origins[0].label} pkg_list.append(package) return pkg_list class ZypperUpdate(object): """ Class to represent and operate with Zypper software update system. It's loaded only on those systems listed at ZYPPER_DISTROS and loads necessary modules in runtime. """ def __init__(self): self._pkgs = {} self.update_cmd = ["zypper", "--non-interactive", "update", "--auto-agree-with-licenses"] def _refreshUpdateList(self): """ Update the list of packages to be updated in the system. """ self._pkgs = [] cmd = ["zypper", "list-updates"] (stdout, stderr, returncode) = run_command(cmd) if len(stderr) > 0: raise OperationFailed('KCHPKGUPD0003E', {'err': stderr}) for line in stdout.split('\n'): if line.find('v |') >= 0: info = line.split(' | ') package = {'package_name': info[2], 'version': info[4], 'arch': info[5], 'repository': info[1]} self._pkgs.append(package) def getPackagesList(self): """ Return a list of package's dictionaries. Each dictionary contains the information about a package, in the format package = {'package_name': , 'version': , 'arch': , 'repository': } """ kimchiLock.acquire() self._refreshUpdateList() kimchiLock.release() return self._pkgs kimchi-1.5.0/src/kimchi/template.py000066400000000000000000000063471254252253000172130ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-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 import cherrypy import errno import json from kimchi.config import paths from Cheetah.Template import Template from glob import iglob def get_lang(): cookie = cherrypy.request.cookie if "kimchiLang" in cookie.keys(): return [cookie["kimchiLang"].value] lang = cherrypy.request.headers.get("Accept-Language", "en_US") if lang and lang.find(';') != -1: lang, _ = lang.split(';', 1) # the language from Accept-Language is the format as en-us # convert it into en_US langs = lang.split(',') for idx, val in enumerate(langs): if "-" in val: langCountry = val.split('-') langCountry[1] = langCountry[1].upper() langs[idx] = "_".join(langCountry) return langs def get_support_languages(): mopath = "%s/*" % paths.mo_dir return [path.rsplit('/', 1)[1] for path in iglob(mopath)] def validate_language(langs): supportLangs = get_support_languages() for lang in langs: if lang in supportLangs: return lang return "en_US" def can_accept(mime): if 'Accept' not in cherrypy.request.headers: accepts = 'text/html' else: accepts = cherrypy.request.headers['Accept'] if accepts.find(';') != -1: accepts, _ = accepts.split(';', 1) if mime in map(lambda x: x.strip(), accepts.split(',')): return True return False def can_accept_html(): return can_accept('text/html') or \ can_accept('application/xaml+xml') or \ can_accept('*/*') def render_cheetah_file(resource, data): paths = cherrypy.request.app.root.paths filename = paths.get_template_path(resource) try: params = {'data': data} lang = validate_language(get_lang()) gettext_conf = {'domain': cherrypy.request.app.root.domain, 'localedir': paths.mo_dir, 'lang': [lang]} params['lang'] = gettext_conf return Template(file=filename, searchList=params).respond() except OSError, e: if e.errno == errno.ENOENT: raise cherrypy.HTTPError(404) else: raise def render(resource, data): if can_accept('application/json'): cherrypy.response.headers['Content-Type'] = \ 'application/json;charset=utf-8' return json.dumps(data, indent=2, separators=(',', ':')) elif can_accept_html(): return render_cheetah_file(resource, data) else: raise cherrypy.HTTPError(406) kimchi-1.5.0/src/kimchi/utils.py000066400000000000000000000431301254252253000165270ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-2015 # # 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 # import cherrypy import contextlib import grp import os import psutil import pwd import re import subprocess import traceback import urllib2 import xml.etree.ElementTree as ET from httplib import HTTPConnection, HTTPException from multiprocessing import Process, Queue from threading import Timer from urlparse import urlparse from cherrypy.lib.reprconf import Parser from kimchi.asynctask import AsyncTask from kimchi.config import paths, PluginPaths from kimchi.exception import InvalidParameter, TimeoutExpired kimchi_log = cherrypy.log.error_log task_id = 0 def _uri_to_name(collection, uri): expr = '/%s/(.*?)$' % collection m = re.match(expr, uri) if not m: raise InvalidParameter("KCHUTILS0001E", {'uri': uri}) return m.group(1) def template_name_from_uri(uri): return _uri_to_name('templates', uri) def pool_name_from_uri(uri): return _uri_to_name('storagepools', uri) def get_next_task_id(): global task_id task_id += 1 return task_id def add_task(target_uri, fn, objstore, opaque=None): id = get_next_task_id() AsyncTask(id, target_uri, fn, objstore, opaque) return id def is_digit(value): if isinstance(value, int): return True elif isinstance(value, basestring): value = value.strip() return value.isdigit() else: return False def _load_plugin_conf(name): plugin_conf = PluginPaths(name).conf_file if not os.path.exists(plugin_conf): cherrypy.log.error_log.error("Plugin configuration file %s" " doesn't exist." % plugin_conf) return try: return Parser().dict_from_file(plugin_conf) except ValueError as e: cherrypy.log.error_log.error("Failed to load plugin " "conf from %s: %s" % (plugin_conf, e.message)) def get_enabled_plugins(): plugin_dir = paths.plugins_dir try: dir_contents = os.listdir(plugin_dir) except OSError: return for name in dir_contents: if os.path.isdir(os.path.join(plugin_dir, name)): plugin_config = _load_plugin_conf(name) try: if plugin_config['kimchi']['enable']: yield (name, plugin_config) except (TypeError, KeyError): continue def get_all_tabs(): files = [os.path.join(paths.prefix, 'config/ui/tabs.xml')] for plugin, _ in get_enabled_plugins(): files.append(os.path.join(PluginPaths(plugin).ui_dir, 'config/tab-ext.xml')) tabs = [] for f in files: root = ET.parse(f) tabs.extend([t.text.lower() for t in root.getiterator('title')]) return tabs def import_class(class_path): module_name, class_name = class_path.rsplit('.', 1) try: mod = import_module(module_name) return getattr(mod, class_name) except (ImportError, AttributeError): raise ImportError('Class %s can not be imported' % class_path) def import_module(module_name): return __import__(module_name, globals(), locals(), ['']) def check_url_path(path): try: code = '' parse_result = urlparse(path) server_name = parse_result.netloc urlpath = parse_result.path if not urlpath: # Just a server, as with a repo. with contextlib.closing(urllib2.urlopen(path)) as res: code = res.getcode() else: # socket.gaierror could be raised, # which is a child class of IOError conn = HTTPConnection(server_name, timeout=15) # Don't try to get the whole file: conn.request('HEAD', path) code = conn.getresponse().status conn.close() if code != 200: return False except (urllib2.URLError, HTTPException, IOError, ValueError): return False return True def run_command(cmd, timeout=None): """ cmd is a sequence of command arguments. timeout is a float number in seconds. timeout default value is None, means command run without timeout. """ # subprocess.kill() can leave descendants running # and halting the execution. Using psutil to # get all descendants from the subprocess and # kill them recursively. def kill_proc(proc, timeout_flag): try: parent = psutil.Process(proc.pid) for child in parent.get_children(recursive=True): child.kill() # kill the process after no children is left proc.kill() except OSError: pass else: timeout_flag[0] = True proc = None timer = None timeout_flag = [False] try: proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) if timeout is not None: timer = Timer(timeout, kill_proc, [proc, timeout_flag]) timer.setDaemon(True) timer.start() out, error = proc.communicate() kimchi_log.debug("Run command: '%s'", " ".join(cmd)) if out: kimchi_log.debug("out:\n%s", out) if proc.returncode != 0: kimchi_log.error("rc: %s error: %s returned from cmd: %s", proc.returncode, error, ' '.join(cmd)) elif error: kimchi_log.debug("error: %s returned from cmd: %s", error, ' '.join(cmd)) if timeout_flag[0]: msg = ("subprocess is killed by signal.SIGKILL for " "timeout %s seconds" % timeout) kimchi_log.error(msg) msg_args = {'cmd': " ".join(cmd), 'seconds': str(timeout)} raise TimeoutExpired("KCHUTILS0002E", msg_args) return out, error, proc.returncode except TimeoutExpired: raise except OSError as e: msg = "Impossible to execute '%s'" % ' '.join(cmd) kimchi_log.debug("%s", msg) return None, "%s %s" % (msg, e), -1 except Exception as e: msg = "Failed to run command: %s." % " ".join(cmd) msg = msg if proc is None else msg + "\n error code: %s." kimchi_log.error("%s %s", msg, e) if proc: return out, error, proc.returncode else: return None, msg, -1 finally: if timer and not timeout_flag[0]: timer.cancel() def parse_cmd_output(output, output_items): res = [] for line in output.split("\n"): if line: res.append(dict(zip(output_items, line.split()))) return res def patch_find_nfs_target(nfs_server): cmd = ["showmount", "--no-headers", "--exports", nfs_server] try: out = run_command(cmd, 10)[0] except TimeoutExpired: kimchi_log.warning("server %s query timeout, may not have any path " "exported", nfs_server) return list() targets = parse_cmd_output(out, output_items=['target']) for target in targets: target['type'] = 'nfs' target['host_name'] = nfs_server return targets def listPathModules(path): modules = set() for f in os.listdir(path): base, ext = os.path.splitext(f) if ext in ('.py', '.pyc', '.pyo'): modules.add(base) return sorted(modules) def run_setfacl_set_attr(path, attr="r", user=""): set_user = ["setfacl", "--modify", "user:%s:%s" % (user, attr), path] out, error, ret = run_command(set_user) return ret == 0 def probe_file_permission_as_user(file, user): def probe_permission(q, file, user): uid = pwd.getpwnam(user).pw_uid gid = pwd.getpwnam(user).pw_gid gids = [g.gr_gid for g in grp.getgrall() if user in g.gr_mem] os.setgid(gid) os.setgroups(gids) os.setuid(uid) try: with open(file): q.put((True, None)) except Exception as e: kimchi_log.debug(traceback.format_exc()) q.put((False, e)) queue = Queue() p = Process(target=probe_permission, args=(queue, file, user)) p.start() p.join() return queue.get() def validate_repo_url(url): url_parts = url.split('://') # [0] = prefix, [1] = rest of URL if url_parts[0] == '': raise InvalidParameter("KCHREPOS0002E") if url_parts[0] in ['http', 'https', 'ftp']: if not check_url_path(url): raise InvalidParameter("KCHUTILS0001E", {'uri': url}) elif url_parts[0] == 'file': if not os.path.exists(url_parts[1]): raise InvalidParameter("KCHUTILS0001E", {'uri': url}) else: raise InvalidParameter("KCHREPOS0002E") def get_next_clone_name(all_names, basename, name_suffix=''): """Find the next available name for a cloned resource. If any resource named "-clone-" is found in "all_names", use the maximum "number" + 1; else, use 1. Arguments: all_names -- All existing names for the resource type. This list will be used to make sure the new name won't conflict with existing names. basename -- The name of the original resource. name_suffix -- The resource name suffix (optional). This parameter exist so that a resource named "foo.img" gets the name "foo-clone-1.img" instead of "foo.img-clone-1". If this parameter is used, the suffix should not be present in "basename". Return: A UTF-8 string in the format "-clone-". """ re_group_num = 'num' re_expr = u'%s-clone-(?P<%s>\d+)' % (basename, re_group_num) if name_suffix != '': re_expr = u'%s%s' % (re_expr, name_suffix) max_num = 0 re_compiled = re.compile(re_expr) for n in all_names: match = re_compiled.match(n) if match is not None: max_num = max(max_num, int(match.group(re_group_num))) # increments the maximum "clone number" found new_name = u'%s-clone-%d' % (basename, max_num + 1) if name_suffix != '': new_name = new_name + name_suffix return new_name def get_unique_file_name(all_names, name): """Find the next available, unique name for a file. If a file named "" isn't found in "", use that same "". There's no need to generate a new name in that case. If any file named " ()" is found in "all_names", use the maximum "number" + 1; else, use 1. Arguments: all_names -- All existing file names. This list will be used to make sure the new name won't conflict with existing names. name -- The name of the original file. Return: A string in the format " ()", or "". """ if name not in all_names: return name re_group_num = 'num' re_expr = u'%s \((?P<%s>\d+)\)' % (name, re_group_num) max_num = 0 re_compiled = re.compile(re_expr) for n in all_names: match = re_compiled.match(n) if match is not None: max_num = max(max_num, int(match.group(re_group_num))) return u'%s (%d)' % (name, max_num + 1) def servermethod(f): def wrapper(*args, **kwargs): server_state = str(cherrypy.engine.state) if server_state not in ["states.STARTED", "states.STARTING"]: return False return f(*args, **kwargs) return wrapper def convert_data_size(value, from_unit, to_unit='B'): """Convert a data value from one unit to another unit (e.g. 'MiB' -> 'GiB'). The data units supported by this function are made up of one prefix and one suffix. The valid prefixes are those defined in the SI (i.e. metric system) and those defined by the IEC, and the valid suffixes indicate if the base unit is bit or byte. Take a look at the tables below for the possible values: Prefixes: ================================== =================================== PREFIX (SI) | DESCRIPTION | VALUE PREFIX (IEC) | DESCRIPTION | VALUE ================================== =================================== k | kilo | 1000 Ki | kibi | 1024 ---------------------------------- ----------------------------------- M | mega | 1000^2 Mi | mebi | 1024^2 ---------------------------------- ----------------------------------- G | giga | 1000^3 Gi | gibi | 1024^3 ---------------------------------- ----------------------------------- T | tera | 1000^4 Ti | tebi | 1024^4 ---------------------------------- ----------------------------------- P | peta | 1000^5 Pi | pebi | 1024^5 ---------------------------------- ----------------------------------- E | exa | 1000^6 Ei | exbi | 1024^6 ---------------------------------- ----------------------------------- Z | zetta | 1000^7 Zi | zebi | 1024^7 ---------------------------------- ----------------------------------- Y | yotta | 1000^8 Yi | yobi | 1024^8 ================================== =================================== Suffixes: ======================= SUFFIX | DESCRIPTION ======================= b | bit ----------------------- B | byte (default) ======================= See http://en.wikipedia.org/wiki/Binary_prefix for more details on those units. If a wrong unit is provided, an error will be raised. Examples: convert_data_size(5, 'MiB', 'KiB') -> 5120.0 convert_data_size(5, 'MiB', 'M') -> 5.24288 convert_data_size(5, 'MiB', 'GiB') -> 0.0048828125 convert_data_size(5, 'MiB', 'Tb') -> 4.194304e-05 convert_data_size(5, 'MiB') -> 5242880.0 convert_data_size(5, 'mib') -> #ERROR# (invalid from_unit) Parameters: value -- the value to be converted, in the unit specified by 'from_unit'. this parameter can be of any type which can be cast to float (e.g. int, float, str). from_unit -- the unit of 'value', as described above. to_unit -- the unit of the return value, as described above. Return: A float number representing 'value' (in 'from_unit') converted to 'to_unit'. """ SI_PREFIXES = ['k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'] # The IEC prefixes are the equivalent SI prefixes + 'i' # but, exceptionally, 'k' becomes 'Ki' instead of 'ki'. IEC_PREFIXES = map(lambda p: 'Ki' if p == 'k' else p + 'i', SI_PREFIXES) PREFIXES_BY_BASE = {1000: SI_PREFIXES, 1024: IEC_PREFIXES} SUFFIXES_WITH_MULT = {'b': 1, 'B': 8} DEFAULT_SUFFIX = 'B' if not from_unit: raise InvalidParameter('KCHUTILS0005E', {'unit': from_unit}) if not to_unit: raise InvalidParameter('KCHUTILS0005E', {'unit': to_unit}) # set the default suffix if from_unit[-1] not in SUFFIXES_WITH_MULT: from_unit += DEFAULT_SUFFIX if to_unit[-1] not in SUFFIXES_WITH_MULT: to_unit += DEFAULT_SUFFIX # split prefix and suffix for better parsing from_p = from_unit[:-1] from_s = from_unit[-1] to_p = to_unit[:-1] to_s = to_unit[-1] # validate parameters try: value = float(value) except TypeError: raise InvalidParameter('KCHUTILS0004E', {'value': value}) if from_p != '' and from_p not in (SI_PREFIXES + IEC_PREFIXES): raise InvalidParameter('KCHUTILS0005E', {'unit': from_unit}) if from_s not in SUFFIXES_WITH_MULT: raise InvalidParameter('KCHUTILS0005E', {'unit': from_unit}) if to_p != '' and to_p not in (SI_PREFIXES + IEC_PREFIXES): raise InvalidParameter('KCHUTILS0005E', {'unit': to_unit}) if to_s not in SUFFIXES_WITH_MULT: raise InvalidParameter('KCHUTILS0005E', {'unit': to_unit}) # if the units are the same, return the input value if from_unit == to_unit: return value # convert 'value' to the most basic unit (bits)... bits = value for suffix, mult in SUFFIXES_WITH_MULT.iteritems(): if from_s == suffix: bits *= mult break if from_p != '': for base, prefixes in PREFIXES_BY_BASE.iteritems(): for i, p in enumerate(prefixes): if from_p == p: bits *= base**(i + 1) break # ...then convert the value in bits to the destination unit ret = bits for suffix, mult in SUFFIXES_WITH_MULT.iteritems(): if to_s == suffix: ret /= float(mult) break if to_p != '': for base, prefixes in PREFIXES_BY_BASE.iteritems(): for i, p in enumerate(prefixes): if to_p == p: ret /= float(base)**(i + 1) break return ret kimchi-1.5.0/src/kimchi/vmtemplate.py000066400000000000000000000361601254252253000175520ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-2015 # # 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 import os import stat import time import urlparse import uuid from lxml import etree from lxml.builder import E from kimchi import imageinfo from kimchi import osinfo from kimchi.exception import InvalidParameter, IsoFormatError, MissingParameter from kimchi.exception import ImageFormatError, OperationFailed from kimchi.isoinfo import IsoImage from kimchi.utils import check_url_path, pool_name_from_uri from kimchi.xmlutils.cpu import get_cpu_xml from kimchi.xmlutils.disk import get_disk_xml from kimchi.xmlutils.graphics import get_graphics_xml from kimchi.xmlutils.interface import get_iface_xml from kimchi.xmlutils.qemucmdline import get_qemucmdline_xml class VMTemplate(object): def __init__(self, args, scan=False): """ Construct a VM Template from a widely variable amount of information. The only required parameter is a name for the VMTemplate. If present, the os_distro and os_version fields are used to lookup recommended settings. Any parameters provided by the caller will override the defaults. If scan is True and a cdrom or a base img is present, the operating system will be detected by probing the installation media. """ self.info = {} self.fc_host_support = args.get('fc_host_support') # Fetch defaults based on the os distro and version try: distro, version = self._get_os_info(args, scan) except ImageFormatError as e: raise OperationFailed('KCHTMPL0020E', {'err': e.message}) os_distro = args.get('os_distro', distro) os_version = args.get('os_version', version) entry = osinfo.lookup(os_distro, os_version) self.info.update(entry) # Auto-generate a template name and no one is passed if 'name' not in args or args['name'] == '': args['name'] = self._gen_name(distro, version) self.name = args['name'] # Override with the passed in parameters graph_args = args.get('graphics') if graph_args: graphics = dict(self.info['graphics']) graphics.update(graph_args) args['graphics'] = graphics self.info.update(args) # Assign right disk format to logical and [i]scsi storagepools if self._get_storage_type() in ['logical', 'iscsi', 'scsi']: for i, disk in enumerate(self.info['disks']): self.info['disks'][i]['format'] = 'raw' def _get_os_info(self, args, scan): distro = version = 'unknown' # Identify the cdrom if present iso = args.get('cdrom', '') if len(iso) > 0: if not iso.startswith('/'): self.info.update({'iso_stream': True}) if scan: distro, version = self.get_iso_info(iso) return distro, version # CDROM is not presented: check for base image base_imgs = [] for d in args.get('disks', []): if 'base' in d.keys(): base_imgs.append(d) if scan: distro, version = imageinfo.probe_image(d['base']) if 'size' not in d.keys(): d_info = imageinfo.probe_img_info(d['base']) d['size'] = d_info['virtual-size'] if len(base_imgs) == 0: raise MissingParameter("KCHTMPL0016E") return distro, version def _gen_name(self, distro, version): if distro == 'unknown': name = str(uuid.uuid4()) else: name = distro + version + '.' + str(int(time.time() * 1000)) return name def get_iso_info(self, iso): iso_prefixes = ['/', 'http', 'https', 'ftp', 'ftps', 'tftp'] if len(filter(iso.startswith, iso_prefixes)) == 0: raise InvalidParameter("KCHTMPL0006E", {'param': iso}) try: iso_img = IsoImage(iso) return iso_img.probe() except IsoFormatError: raise InvalidParameter("KCHISO0001E", {'filename': iso}) def _get_cdrom_xml(self, libvirt_stream_protocols): if 'cdrom' not in self.info: return '' params = {} params['type'] = 'cdrom' params['format'] = 'raw' params['bus'] = self.info['cdrom_bus'] params['index'] = self.info['cdrom_index'] params['path'] = self.info['cdrom'] if self.info.get('iso_stream', False): protocol = urlparse.urlparse(params['path']).scheme if protocol not in libvirt_stream_protocols: driveOpt = 'file=%(path)s,if=none,id=drive-%(bus)s0-1-0,' driveOpt += 'readonly=on,format=%(format)s' deviceOpt = '%(bus)s-cd,bus=%(bus)s.1,unit=0,' deviceOpt += 'drive=drive-%(bus)s0-1-0,id=%(bus)s0-1-0' args = {} args['-drive'] = driveOpt % params args['-device'] = deviceOpt % params # return qemucmdline XML return get_qemucmdline_xml(args) dev, xml = get_disk_xml(params) return xml def _get_disks_xml(self, vm_uuid): # Current implementation just allows to create disk in one single # storage pool, so we cannot mix the types (scsi volumes vs img file) storage_type = self._get_storage_type() storage_path = self._get_storage_path() base_disk_params = {'type': 'disk', 'disk': 'file', 'bus': self.info['disk_bus'], 'format': 'qcow2'} logical_disk_params = {'format': 'raw'} iscsi_disk_params = {'disk': 'block', 'format': 'raw'} scsi_disk = 'volume' if self.fc_host_support else 'block' scsi_disk_params = {'disk': scsi_disk, 'type': 'lun', 'format': 'raw', 'bus': 'scsi'} disks_xml = '' pool_name = pool_name_from_uri(self.info['storagepool']) for index, disk in enumerate(self.info['disks']): params = dict(base_disk_params) params['format'] = disk.get('format', params['format']) params.update(locals().get('%s_disk_params' % storage_type, {})) params['index'] = index volume = disk.get('volume') if volume is not None: params['path'] = self._get_volume_path(pool_name, volume) else: volume = "%s-%s.img" % (vm_uuid, params['index']) params['path'] = os.path.join(storage_path, volume) disks_xml += get_disk_xml(params)[1] return unicode(disks_xml, 'utf-8') def to_volume_list(self, vm_uuid): storage_path = self._get_storage_path() fmt = 'raw' if self._get_storage_type() in ['logical'] else 'qcow2' ret = [] for i, d in enumerate(self.info['disks']): index = d.get('index', i) volume = "%s-%s.img" % (vm_uuid, index) info = {'name': volume, 'capacity': d['size'], 'format': fmt, 'path': '%s/%s' % (storage_path, volume)} if 'logical' == self._get_storage_type() or \ fmt not in ['qcow2', 'raw']: info['allocation'] = info['capacity'] else: info['allocation'] = 0 if 'base' in d: info['base'] = dict() base_fmt = imageinfo.probe_img_info(d['base'])['format'] if base_fmt is None: raise InvalidParameter("KCHTMPL0024E", {'path': d['base']}) info['base']['path'] = d['base'] info['base']['format'] = base_fmt v_tree = E.volume(E.name(info['name'])) v_tree.append(E.allocation(str(info['allocation']), unit='G')) v_tree.append(E.capacity(str(info['capacity']), unit='G')) target = E.target( E.format(type=info['format']), E.path(info['path'])) if 'base' in d: v_tree.append(E.backingStore( E.path(info['base']['path']), E.format(type=info['base']['format']))) v_tree.append(target) info['xml'] = etree.tostring(v_tree) ret.append(info) return ret def _get_networks_xml(self): networks = "" params = {'type': 'network', 'model': self.info['nic_model']} for nw in self.info['networks']: params['network'] = nw networks += get_iface_xml(params, self.info['arch'], self.info['os_distro'], self.info['os_version']) return unicode(networks, 'utf-8') def _get_input_output_xml(self): sound = """ """ mouse = """ """ keyboard = """ """ tablet = """ """ video = """ """ input_output = "" if 'mouse_bus' in self.info.keys(): input_output += mouse % self.info if 'kbd_bus' in self.info.keys(): input_output += keyboard % self.info if 'tablet_bus' in self.info.keys(): input_output += tablet % self.info if 'sound_model' in self.info.keys(): input_output += sound % self.info if 'video_model' in self.info.keys(): input_output += video % self.info return input_output def _get_cpu_xml(self): # Include CPU topology, if provided cpu_info = self.info.get('cpu_info') if cpu_info is not None: cpu_topo = cpu_info.get('topology') return get_cpu_xml(self.info.get('cpus'), self.info.get('memory') << 10, cpu_topo) def to_vm_xml(self, vm_name, vm_uuid, **kwargs): params = dict(self.info) params['name'] = vm_name params['uuid'] = vm_uuid params['networks'] = self._get_networks_xml() params['input_output'] = self._get_input_output_xml() params['qemu-namespace'] = '' params['cdroms'] = '' params['qemu-stream-cmdline'] = '' params['cpu_info'] = self._get_cpu_xml() params['disks'] = self._get_disks_xml(vm_uuid) graphics = dict(self.info['graphics']) graphics.update(kwargs.get('graphics', {})) params['graphics'] = get_graphics_xml(graphics) libvirt_stream_protocols = kwargs.get('libvirt_stream_protocols', []) cdrom_xml = self._get_cdrom_xml(libvirt_stream_protocols) if not urlparse.urlparse(self.info.get('cdrom', "")).scheme in \ libvirt_stream_protocols and \ params.get('iso_stream', False): params['qemu-stream-cmdline'] = cdrom_xml else: params['cdroms'] = cdrom_xml # Setting maximum number of slots to avoid errors when hotplug memory # Number of slots are the numbers of chunks of 1GB that fit inside # the max_memory of the host minus memory assigned to the VM params['slots'] = ((params['max_memory'] >> 10) - params['memory']) >> 10 if params['slots'] < 0: raise OperationFailed("KCHVM0041E") elif params['slots'] == 0: params['slots'] = 1 xml = """ %(qemu-stream-cmdline)s %(name)s %(uuid)s %(max_memory)s %(memory)s %(cpus)s %(cpu_info)s hvm destroy restart restart %(disks)s %(cdroms)s %(networks)s %(graphics)s %(input_output)s """ % params # Adding PPC console configuration if params['arch'] in ['ppc', 'ppc64']: ppc_console = """
""" xml = xml.replace("", ppc_console) return xml def validate(self): self._storage_validate() self._network_validate() self._iso_validate() def _iso_validate(self): pass def _network_validate(self): pass def _storage_validate(self): pass def fork_vm_storage(self, vm_uuid): pass def _get_storage_path(self): return '' def _get_storage_type(self): return '' def _get_volume_path(self): return '' def _get_all_networks_name(self): return [] def _get_all_storagepools_name(self): return [] def validate_integrity(self): invalid = {} # validate networks integrity invalid_networks = list(set(self.info['networks']) - set(self._get_all_networks_name())) if invalid_networks: invalid['networks'] = invalid_networks # validate storagepools integrity pool_uri = self.info['storagepool'] pool_name = pool_name_from_uri(pool_uri) if pool_name not in self._get_all_storagepools_name(): invalid['storagepools'] = [pool_name] # validate iso integrity # FIXME when we support multiples cdrom devices iso = self.info.get('cdrom') if iso: if os.path.exists(iso): st_mode = os.stat(iso).st_mode if not (stat.S_ISREG(st_mode) or stat.S_ISBLK(st_mode)): invalid['cdrom'] = [iso] elif not check_url_path(iso): invalid['cdrom'] = [iso] self.info['invalid'] = invalid return self.info kimchi-1.5.0/src/kimchi/vnc.py000066400000000000000000000046561254252253000161670ustar00rootroot00000000000000#!/usr/bin/env python2 # # Project Kimchi # # Copyright IBM, Corp. 2013-2015 # # 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 import base64 import errno import os from multiprocessing import Process from websockify import WebSocketProxy from kimchi.config import config, paths WS_TOKENS_DIR = '/var/lib/kimchi/vnc-tokens' def new_ws_proxy(): try: os.makedirs(WS_TOKENS_DIR, mode=0755) except OSError as e: if e.errno == errno.EEXIST: pass cert = config.get('server', 'ssl_cert') key = config.get('server', 'ssl_key') if not (cert and key): cert = '%s/kimchi-cert.pem' % paths.conf_dir key = '%s/kimchi-key.pem' % paths.conf_dir params = {'web': os.path.join(paths.ui_dir, 'pages/websockify'), 'listen_port': config.get('display', 'display_proxy_port'), 'target_cfg': WS_TOKENS_DIR, 'key': key, 'cert': cert, 'ssl_only': True} def start_proxy(): server = WebSocketProxy(**params) server.start_server() proc = Process(target=start_proxy) proc.start() return proc def add_proxy_token(name, port): with open(os.path.join(WS_TOKENS_DIR, name), 'w') as f: """ From python documentation base64.urlsafe_b64encode(s) substitutes - instead of + and _ instead of / in the standard Base64 alphabet, BUT the result can still contain = which is not safe in a URL query component. So remove it when needed as base64 can work well without it. """ name = base64.urlsafe_b64encode(name).rstrip('=') f.write('%s: localhost:%s' % (name.encode('utf-8'), port)) def remove_proxy_token(name): try: os.unlink(os.path.join(WS_TOKENS_DIR, name)) except OSError: pass kimchi-1.5.0/src/kimchi/xmlutils/000077500000000000000000000000001254252253000166755ustar00rootroot00000000000000kimchi-1.5.0/src/kimchi/xmlutils/Makefile.am000066400000000000000000000016001254252253000207260ustar00rootroot00000000000000# # 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 xmlutils_PYTHON = *.py xmlutilsdir = $(pythondir)/kimchi/xmlutils install-data-local: $(MKDIR_P) $(DESTDIR)$(xmlutilsdir) kimchi-1.5.0/src/kimchi/xmlutils/__init__.py000066400000000000000000000014121254252253000210040ustar00rootroot00000000000000# # 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 kimchi-1.5.0/src/kimchi/xmlutils/cpu.py000066400000000000000000000040271254252253000200410ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2015 # # 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 import lxml.etree as ET from lxml.builder import E def get_numa_xml(cpus, memory): # Returns the NUMA xml to be add into CPU element # Currently, supports only one node/cell # # # xml = E.numa(E.cell( id='0', cpus='0-' + str(cpus - 1) if cpus > 1 else '0', memory=str(memory), unit='KiB')) return ET.tostring(xml) def get_topology_xml(cpu_topo): # Return the cpu TOPOLOGY element # xml = E.topology( sockets=str(cpu_topo['sockets']), cores=str(cpu_topo['cores']), threads=str(cpu_topo['threads'])) return ET.tostring(xml) def get_cpu_xml(cpus, memory, cpu_topo=None): # Returns the libvirt CPU element based on given numa and topology # CPU element will always have numa element # # # # # # xml = E.cpu(ET.fromstring(get_numa_xml(cpus, memory))) if cpu_topo is not None: xml.insert(0, ET.fromstring(get_topology_xml(cpu_topo))) return ET.tostring(xml) kimchi-1.5.0/src/kimchi/xmlutils/disk.py000066400000000000000000000117631254252253000202110ustar00rootroot00000000000000# # 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 import lxml.etree as ET import os import socket import stat import string import urlparse from lxml import objectify from lxml.builder import E from kimchi.exception import InvalidParameter, NotFoundError from kimchi.utils import check_url_path BUS_TO_DEV_MAP = {'ide': 'hd', 'virtio': 'vd', 'scsi': 'sd'} DEV_TYPE_SRC_ATTR_MAP = {'file': 'file', 'block': 'dev'} def get_disk_xml(params): """ [source XML according to src_type] """ path = params['path'] disk_type = params.get('disk', None) if disk_type is None: disk_type = _get_disk_type(path) if len(path) > 0 else 'file' disk = E.disk(type=disk_type, device=params['type']) driver = E.driver(name='qemu', type=params['format']) if params['type'] != 'cdrom': driver.set('cache', 'none') disk.append(driver) # Get device name according to bus and index values dev = params.get('dev', (BUS_TO_DEV_MAP[params['bus']] + string.lowercase[params.get('index', 0)])) disk.append(E.target(dev=dev, bus=params['bus'])) if params.get('address'): # ide disk target id is always '0' disk.append(E.address( type='drive', controller=params['address']['controller'], bus=params['address']['bus'], target='0', unit=params['address']['unit'])) if len(params['path']) == 0: return (dev, ET.tostring(disk, encoding='utf-8', pretty_print=True)) if disk_type == 'network': """ """ output = urlparse.urlparse(params['path']) port = str(output.port or socket.getservbyname(output.scheme)) source = E.source(protocol=output.scheme, name=output.path) source.append(E.host(name=output.hostname, port=port)) else: """ """ source = E.source() source.set(DEV_TYPE_SRC_ATTR_MAP[disk_type], params['path']) disk.append(source) return (dev, ET.tostring(disk, encoding='utf-8', pretty_print=True)) def _get_disk_type(path): if check_url_path(path): return 'network' if not os.path.exists(path): raise InvalidParameter("KCHVMSTOR0003E", {'value': path}) # Check if path is a valid local path if os.path.isfile(path): return 'file' r_path = os.path.realpath(path) if stat.S_ISBLK(os.stat(r_path).st_mode): return 'block' raise InvalidParameter("KCHVMSTOR0003E", {'value': path}) def get_device_node(dom, dev_name): xml = dom.XMLDesc(0) devices = objectify.fromstring(xml).devices disk = devices.xpath("./disk/target[@dev='%s']/.." % dev_name) if not disk: raise NotFoundError("KCHVMSTOR0007E", {'dev_name': dev_name, 'vm_name': dom.name()}) return disk[0] def get_vm_disk_info(dom, dev_name): # Retrieve disk xml and format return dict disk = get_device_node(dom, dev_name) if disk is None: return None try: source = disk.source if source is not None: src_type = disk.attrib['type'] if src_type == 'network': host = source.host path = (source.attrib['protocol'] + '://' + host.attrib['name'] + ':' + host.attrib['port'] + source.attrib['name']) else: path = source.attrib[DEV_TYPE_SRC_ATTR_MAP[src_type]] except: path = "" return {'dev': dev_name, 'path': path, 'type': disk.attrib['device'], 'format': disk.driver.attrib['type'], 'bus': disk.target.attrib['bus']} def get_vm_disks(dom): xml = dom.XMLDesc(0) devices = objectify.fromstring(xml).devices storages = {} all_disks = devices.xpath("./disk[@device='disk']") all_disks.extend(devices.xpath("./disk[@device='cdrom']")) for disk in all_disks: storages[disk.target.attrib['dev']] = disk.target.attrib['bus'] return storages kimchi-1.5.0/src/kimchi/xmlutils/graphics.py000066400000000000000000000031171254252253000210510ustar00rootroot00000000000000# # 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 import lxml.etree as ET from lxml.builder import E def get_graphics_xml(params): """ - For spice graphics: """ graphics = E.graphics(type=params['type'], autoport='yes', listen=params['listen']) graphics_xml = ET.tostring(graphics, encoding='utf-8', pretty_print=True) if params['type'] == 'vnc': return graphics_xml # For spice graphics, a channel also must be configured channel = E.channel(type='spicevmc') channel.append(E.target(type='virtio', name='com.redhat.spice.0')) channel_xml = ET.tostring(channel, encoding='utf-8', pretty_print=True) return graphics_xml + channel_xml kimchi-1.5.0/src/kimchi/xmlutils/interface.py000066400000000000000000000042411254252253000212100ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2014-2015 # # 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 import lxml.etree as ET from distutils.version import LooseVersion from lxml.builder import E from kimchi import osinfo def get_iface_xml(params, arch=None, os_distro=None, os_version=None): """ """ interface = E.interface(type=params['type']) interface.append(E.source(network=params['network'])) model = params.get('model') # no model specified; let's try querying osinfo if model is None: # if os_distro and os_version are invalid, nic_model will also be None model = osinfo.lookup(os_distro, os_version).get('nic_model') # only append 'model' to the XML if it's been specified as a parameter or # returned by osinfo.lookup; otherwise let libvirt use its default value if model is not None: interface.append(E.model(type=model)) mac = params.get('mac', None) if mac is not None: interface.append(E.mac(address=mac)) # Hack to disable vhost feature in Ubuntu LE and SLES LE (PPC) if arch == 'ppc64' and \ ((os_distro == 'ubuntu' and LooseVersion(os_version) >= LooseVersion('14.04')) or (os_distro == 'sles' and LooseVersion(os_version) >= LooseVersion('12'))): interface.append(E.driver(name='qemu')) return ET.tostring(interface, encoding='utf-8', pretty_print=True) kimchi-1.5.0/src/kimchi/xmlutils/network.py000066400000000000000000000067101254252253000207440ustar00rootroot00000000000000# # 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 import ipaddr import lxml.etree as ET from lxml.builder import E # FIXME, do not support ipv6 def _get_dhcp_elem(**kwargs): """ """ dhcp = E.dhcp() if 'range' in kwargs.keys(): dhcp_range = E.range(start=kwargs['range']['start'], end=kwargs['range']['end']) dhcp.append(dhcp_range) if 'hosts' in kwargs.keys(): for host in kwargs['hosts']: dhcp.append(E.host(mac=host['mac'], name=host['name'], ip=host['ip'])) return dhcp if len(dhcp) > 0 else None def _get_ip_elem(**kwargs): """ """ if 'net' not in kwargs.keys(): return None net = ipaddr.IPNetwork(kwargs['net']) ip = E.ip(address=str(net.ip), netmask=str(net.netmask)) dhcp_params = kwargs.get('dhcp', {}) dhcp = _get_dhcp_elem(**dhcp_params) if dhcp is not None: ip.append(dhcp) return ip def _get_forward_elem(**kwargs): """ """ if "mode" in kwargs.keys() and kwargs['mode'] is None: return None forward = E.forward() if 'mode' in kwargs.keys(): forward.set('mode', kwargs['mode']) if 'dev' in kwargs.keys(): forward.set('dev', kwargs['dev']) if 'managed' in kwargs.keys(): forward.set('managed', kwargs['managed']) return forward def to_network_xml(**kwargs): network = E.network(E.name(kwargs['name'])) bridge = kwargs.get('bridge') if bridge: network.append(E.bridge(name=bridge)) # None means is Isolated network, {} means default mode nat params = kwargs.get('forward', {"mode": None}) forward = _get_forward_elem(**params) if forward is not None: network.append(forward) if 'net' in kwargs: network.append(_get_ip_elem(**kwargs)) return ET.tostring(network) def create_vlan_tagged_bridge_xml(bridge, interface, vlan_id): vlan = E.vlan(E.interface(name=interface)) vlan.set('tag', vlan_id) m = E.interface( E.start(mode='onboot'), E.bridge( E.interface( vlan, type='vlan', name='.'.join([interface, vlan_id]))), type='bridge', name=bridge) return ET.tostring(m) kimchi-1.5.0/src/kimchi/xmlutils/qemucmdline.py000066400000000000000000000032121254252253000215500ustar00rootroot00000000000000# # 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 import lxml.etree as ET from lxml.builder import ElementMaker QEMU_NAMESPACE = "http://libvirt.org/schemas/domain/qemu/1.0" def get_qemucmdline_xml(args): """ """ EM = ElementMaker(namespace=QEMU_NAMESPACE, nsmap={'qemu': QEMU_NAMESPACE}) root = EM.commandline() for opt, value in args.iteritems(): root.append(EM.arg(value=opt)) root.append(EM.arg(value=value)) return ET.tostring(root, encoding='utf-8', pretty_print=True) kimchi-1.5.0/src/kimchi/xmlutils/utils.py000066400000000000000000000035731254252253000204170ustar00rootroot00000000000000# # 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 import lxml.etree as ET from lxml import objectify def xpath_get_text(xml, expr): doc = ET.fromstring(xml) res = [] for x in doc.xpath(expr): if isinstance(x, unicode): x = x.encode('utf-8') elif not isinstance(x, str): x = x.text res.append(x) return res def xml_item_update(xml, xpath, value, attr=None): root = ET.fromstring(xml) item = root.find(xpath) if attr is None: item.text = value else: item.set(attr, value) return ET.tostring(root, encoding="utf-8") def dictize(xmlstr): root = objectify.fromstring(xmlstr) return {root.tag: _dictize(root)} def _dictize(e): d = {} if e.text is not None: if not e.attrib and e.countchildren() == 0: return e.pyval d['pyval'] = e.pyval d.update(e.attrib) for child in e.iterchildren(): if child.tag in d: continue if len(child) > 1: d[child.tag] = [ _dictize(same_tag_child) for same_tag_child in child] else: d[child.tag] = _dictize(child) return d kimchi-1.5.0/src/kimchi/yumparser.py000066400000000000000000000165251254252253000174260ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2015 # # 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 import subprocess from os import listdir from os.path import isfile, splitext class YumRepoObject(object): def __init__(self, repo_id, repofile): self.repo_id = repo_id self.name = None self.baseurl = None self.enabled = True self.gpgcheck = True self.gpgkey = None self.metalink = None self.mirrorlist = None self.repofile = repofile self.string_attrs = ['baseurl', 'gpgkey', 'name', 'metalink', 'mirrorlist'] self.boolean_attrs = ['enabled', 'gpgcheck'] def set_attribute(self, key, strvalue): if key in self.string_attrs: setattr(self, key, strvalue) elif key in self.boolean_attrs: setattr(self, key, (strvalue == '1')) def get_attribute_str(self, key): if key not in self.get_attributes(): return None if key in self.boolean_attrs: str_value = '1' if getattr(self, key) is True else '0' else: str_value = getattr(self, key) if str_value is None: return None return key + '=' + str_value def get_attributes(self): return self.string_attrs + self.boolean_attrs def enable(self): self.enabled = True def disable(self): self.enabled = False def __str__(self): str_obj = '[' + self.repo_id + ']' + '\n' for key in self.get_attributes(): if self.get_attribute_str(key) is not None: str_obj += self.get_attribute_str(key) + '\n' return str_obj def get_repo_files(): def _is_repository_file(f): _, f_extension = splitext(f) return isfile(f) and (f_extension == '.repo') YUM_REPO_DIR = '/etc/yum.repos.d' return [YUM_REPO_DIR+'/'+f for f in listdir(YUM_REPO_DIR) if _is_repository_file(YUM_REPO_DIR+'/'+f)] def _ignore_line_repo_file(line): return line.startswith("#") or '=' not in line def _get_repos_from_file(repo_file): repos_from_file = {} current_repo = None current_repo_id = None with open(repo_file) as f: for line in f.readlines(): line = line.strip() if line.startswith("["): if current_repo is not None: repos_from_file[current_repo_id] = current_repo current_repo_id = line.strip('[]') current_repo = YumRepoObject(current_repo_id, repo_file) continue if _ignore_line_repo_file(line): continue key, value = line.split('=', 1) key = key.strip() value = value.strip() current_repo.set_attribute(key, value) # add the last repo from file. if current_repo is not None: repos_from_file[current_repo_id] = current_repo return repos_from_file def get_yum_repositories(): repo_files = get_repo_files() repos = {} for yum_repo in repo_files: repos.update(_get_repos_from_file(yum_repo)) return repos def _retrieve_repo_line_index(data, repo): repo_entry = '[' + repo.repo_id + ']\n' try: repo_index = data.index(repo_entry) except: return None return repo_index def _update_repo_file_data(data, repo, repo_index): remaining_repo_attrs = repo.get_attributes() for i in range(repo_index + 1, len(data)): line = data[i].strip() if line.startswith('['): break if _ignore_line_repo_file(line): continue key, _ = line.split('=', 1) key = key.strip() attr_str = repo.get_attribute_str(key) if attr_str is None: continue remaining_repo_attrs.remove(key) data[i] = attr_str + '\n' for attr in remaining_repo_attrs: attr_str = repo.get_attribute_str(attr) if attr_str is None: continue data.insert(repo_index+1, attr_str + '\n') return data def write_repo_to_file(repo): with open(repo.repofile) as f: data = f.readlines() repo_index = _retrieve_repo_line_index(data, repo) if repo_index is None: return data = _update_repo_file_data(data, repo, repo_index) with open(repo.repofile, 'w') as f: f.writelines(data) def _get_last_line_repo(data, repo_index): stop_delete_index = None for i in range(repo_index+1, len(data)): line = data[i].strip() if line.startswith('['): stop_delete_index = i - 1 break if stop_delete_index is None: stop_delete_index = len(data) - 1 return stop_delete_index def _remove_repo_file_data(data, repo_index): last_line_repo = _get_last_line_repo(data, repo_index) for i in range(last_line_repo, repo_index - 1, -1): data.pop(i) return data def delete_repo_from_file(repo): with open(repo.repofile) as f: data = f.readlines() repo_index = _retrieve_repo_line_index(data, repo) if repo_index is None: return data = _remove_repo_file_data(data, repo_index) with open(repo.repofile, 'w') as f: f.writelines(data) class YumUpdatePackageObject(object): def __init__(self, name, arch, version, repo): self.name = name self.arch = arch self.version = version self.ui_from_repo = repo def _include_line_checkupdate_output(line): tokens = line.split() if len(tokens) != 3: return False if '.' not in tokens[0]: return False return True def _filter_lines_checkupdate_output(output): if output is None: return [] out = [l for l in output.split('\n') if _include_line_checkupdate_output(l)] return out def _get_yum_checkupdate_output(): cmd = ['yum', 'check-update', '-d0'] yum_update_cmd = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, error = yum_update_cmd.communicate() if error != '': return None return out def get_yum_packages_list_update(checkupdate_output=None): if checkupdate_output is None: checkupdate_output = _get_yum_checkupdate_output() filtered_output = _filter_lines_checkupdate_output(checkupdate_output) packages = [] for line in filtered_output: line = line.split() index = 0 name_arch = line[index] index += 1 version = line[index] index += 1 repo = line[index] name, arch = name_arch.rsplit('.', 1) packages.append(YumUpdatePackageObject(name, arch, version, repo)) return packages kimchi-1.5.0/src/kimchid.in000066400000000000000000000077661254252253000155300ustar00rootroot00000000000000#!/usr/bin/env python2 # # Project Kimchi # # Copyright IBM, Corp. 2013-2015 # # 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 import os import sys sys.path.insert(1, '@pythondir@') from optparse import OptionParser import kimchi.server import kimchi.config as config if not config.paths.installed: sys.path.append(config.paths.prefix) ACCESS_LOG = "kimchi-access.log" ERROR_LOG = "kimchi-error.log" 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.config.get("server", "host") port = config.config.get("server", "port") ssl_port = config.config.get("server", "ssl_port") cherrypy_port = config.config.get("server", "cherrypy_port") runningEnv = config.config.get("server", "environment") federation = config.config.get("server", "federation") isopool = config.config.get("server", "create_iso_pool") logDir = config.config.get("logging", "log_dir") logLevel = config.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 (default %s)" % port) parser.add_option('--ssl-port', type="int", default=ssl_port, help="Port to enable SSL (default %s)" % ssl_port) parser.add_option('--cherrypy_port', type="int", default=cherrypy_port, help="Cherrypy server port (default %s)" % cherrypy_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('--federation', default=federation, help="Register and discover Kimchi peers in the same " "network using openSLP. Check README-federation for" " more details.") parser.add_option('--create_iso_pool', default=isopool, help="Automatically create ISO pool on server start up.") parser.add_option('--test', action='store_true', help="Run server in mock model") (options, args) = parser.parse_args() # Update config.config with the command line values # So the whole application will have access to accurate values for sec in config.config.sections(): for item in config.config.options(sec): if hasattr(options, item): config.config.set(sec, item, str(getattr(options, item))) # Add non-option arguments setattr(options, 'ssl_cert', config.config.get('server', 'ssl_cert')) setattr(options, 'ssl_key', config.config.get('server', 'ssl_key')) setattr(options, 'max_body_size', config.config.get('server', 'max_body_size')) kimchi.server.main(options) if __name__ == '__main__': sys.exit(main(sys.argv[1:])) kimchi-1.5.0/src/nginx/000077500000000000000000000000001254252253000146735ustar00rootroot00000000000000kimchi-1.5.0/src/nginx/Makefile.am000066400000000000000000000015771254252253000167410ustar00rootroot00000000000000# # Kimchi # # Copyright IBM Corp, 2015 # # 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 EXTRA_DIST = kimchi.conf.in confdir = $(sysconfdir)/nginx/conf.d dist_conf_DATA = kimchi.conf.in CLEANFILES = kimchi.conf kimchi-1.5.0/src/nginx/kimchi.conf.in000066400000000000000000000063421254252253000174200ustar00rootroot00000000000000# Project Kimchi # # Copyright IBM, Corp. 2014-2015 # # 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 ${user}; 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; client_max_body_size ${max_body_size}k; # Timeout set to 10 minutes to avoid the 504 Gateway Timeout # when Kimchi is processing a request. proxy_connect_timeout 600; proxy_send_timeout 600; proxy_read_timeout 600; send_timeout 600; server { listen ${proxy_ssl_port} ssl; ssl_certificate ${cert_pem}; ssl_certificate_key ${cert_key}; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA:@STRENGTH'; ssl_prefer_server_ciphers on; ssl_dhparam ${dhparams_pem}; add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;"; add_header X-Frame-Options DENY; add_header X-Content-Type-Options nosniff; add_header X-XSS-Protection "1; mode=block"; location / { proxy_pass http://127.0.0.1:${kimchid_port}; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_redirect http://127.0.0.1:${kimchid_port}/ https://$host:${proxy_ssl_port}/; } } server { listen ${proxy_port}; rewrite ^/(.*)$ https://$host:${proxy_ssl_port}/$1 redirect; } } kimchi-1.5.0/src/template.conf000066400000000000000000000017171254252253000162400ustar00rootroot00000000000000# # Configuration file for Kimchi Templates # [main] # Memory in MB #memory = 1024 # List of networks separated by comma # Represents the virtual network interfaces to be assigned to guest #networks = default, [storage] # Storage pool used to handle the guest disk #pool = default # Specify multiple [[disk.X]] sub-sections to add multiples disks to guest # All the disk files will be created in the same storage pool as set above [[disk.0]] # Disk size in GB #size = 10 # Disk format #format = qcow2 [graphics] # Graphics type # Valid options: vnc | spice #type = vnc # The network which the vnc/spice server listens on #listen = 127.0.0.1 [processor] # Number of vcpus # When specifying CPU topology, make sure cpus value is equal to the product # of sockets, cores, and threads. #cpus = 1 # Number of sockets (not set by default) #sockets = # Number of cores per socket (not set by default) #cores = # Number of threads per core (not set by default) #threads = kimchi-1.5.0/tests/000077500000000000000000000000001254252253000141235ustar00rootroot00000000000000kimchi-1.5.0/tests/Makefile.am000066400000000000000000000031151254252253000161570ustar00rootroot00000000000000# # Kimchi # # Copyright IBM Corp, 2013 # # 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 EXTRA_DIST = \ Makefile.am \ run_tests.sh.in \ test_config.py.in \ $(filter-out test_config.py, $(wildcard *.py)) \ $(NULL) noinst_SCRIPTS = run_tests.sh do_substitution = \ sed -e 's,[@]HAVE_PYMOD_UNITTEST[@],$(HAVE_PYMOD_UNITTEST),g' \ -e 's,[@]prefix[@],$(prefix),g' \ -e 's,[@]datadir[@],$(datadir),g' \ -e 's,[@]PYTHON_VERSION[@],$(PYTHON_VERSION),g' \ -e 's,[@]kimchidir[@],$(pythondir)/kimchi,g' \ -e 's,[@]pkgdatadir[@],$(pkgdatadir),g' run_tests.sh: run_tests.sh.in Makefile $(do_substitution) < $(srcdir)/run_tests.sh.in > run_tests.sh chmod +x run_tests.sh test_config.py: test_config.py.in Makefile $(do_substitution) < $(srcdir)/test_config.py.in > test_config.py check-local: $(MKDIR_P) $(top_srcdir)/data/screenshots ./run_tests.sh BUILT_SOURCES = test_config.py CLEANFILES = run_tests.sh test_config.py kimchi-1.5.0/tests/iso_gen.py000066400000000000000000000156671254252253000161370ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-2015 # # 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 import platform import struct from kimchi.isoinfo import IsoImage iso_des = [ ('openbsd', lambda v: True, lambda v: 'OpenBSD/i386 %s Install CD' % v), ('centos', lambda v: True, lambda v: 'CentOS_%s_Final' % v), ('windows', '2000', 'W2AFPP'), ('windows', 'xp', 'WXPFPP'), ('windows', '2003', 'ARMECHK'), ('windows', '2003r2', 'CRMEFPP'), ('windows', '2008', 'KRTMSVOL'), ('windows', '2008r2', 'GRMSXVOL'), ('windows', 'vista', 'FB1EVOL'), ('windows', '7', 'GRMCULFRER'), ('windows', '8', 'HB1_CCPA_X86FRE'), ('sles', '10', 'SLES10'), ('sles', '11', 'SUSE_SLES-11-0-0'), ('opensuse', '11.1', 'SU1110.001'), ('opensuse', '11.3', 'openSUSE-DVD-x86_64.0702..001'), ('opensuse', '11.4', 'openSUSE-DVD-x86_640024'), ('opensuse', '12.1', 'openSUSE-DVD-x86_640039'), ('opensuse', '12.2', 'openSUSE-DVD-x86_640167'), ('opensuse', lambda v: True, lambda v: 'openSUSE-%s' % v), ('rhel', '4.8', 'RHEL/4-U8'), ('rhel', lambda v: v.startswith('6.'), lambda v: 'RHEL_%s' % v), ('debian', lambda v: True, lambda v: 'Debian %s' % v), ('ubuntu', lambda v: v in ('7.10', '8.04', '8.10', '9.04', '9.10', '10.04', '10.10', '11.04', '11.10', '12.04', '12.10', '13.04', '13.10', '14.04'), lambda v: 'Ubuntu %s' % v), ('fedora', lambda v: v in ('16', '17', '18', '19'), lambda v: 'Fedora %s' % v) ] class FakeIsoImage(object): def _build_iso(self, fd, iso_volid, bootable): if platform.machine().startswith('ppc'): self._build_powerpc_bootable_iso(fd, iso_volid) return self._build_intel_iso(fd, iso_volid, bootable) def _build_powerpc_bootable_iso(self, fd, iso_volid): self._build_prim_vol(fd, iso_volid) self._build_bootable_ppc_path_table(fd) def _build_intel_iso(self, fd, iso_volid, bootable): # Do not change the order of the method calls self._build_el_boot(fd, bootable) self._build_prim_vol(fd, iso_volid) self._build_el_torito(fd) def _build_prim_vol(self, fd, iso_volid): fd.seek(16 * IsoImage.SECTOR_SIZE) fmt = IsoImage.VOL_DESC vd_type = 1 vd_ident = 'CD001' vd_ver = 1 pad0 = 1 sys_id = 'fake os' vol_id = iso_volid data = (vd_type, vd_ident, vd_ver, pad0, sys_id, vol_id) s = fmt.pack(*data) fd.write(s) self._add_sector_padding(fd, s) def _add_sector_padding(self, fd, s): padding_len = IsoImage.SECTOR_SIZE - len(s) fmt = struct.Struct('=%ss' % padding_len) s = fmt.pack('a' * padding_len) fd.write(s) def _build_el_torito(self, fd): fmt = IsoImage.EL_TORITO_BOOT_RECORD vd_type = 0 vd_ident = 'CD001' vd_ver = 1 et_ident = "EL TORITO SPECIFICATION:" pad0 = 'a' * 32 boot_cat = 0 data = (vd_type, vd_ident, vd_ver, et_ident, pad0, boot_cat) s = fmt.pack(*data) fd.write(s) self._add_sector_padding(fd, s) def _build_el_boot(self, fd, bootable): fmt = IsoImage.EL_TORITO_VALIDATION_ENTRY hdr_id = 0 platform_id = 0 pad0 = 1 ident = 'c' * 24 csum = 1 key55 = 0x55 keyAA = 0xaa data = (hdr_id, platform_id, pad0, ident, csum, key55, keyAA) s = fmt.pack(*data) fd.write(s) fmt = IsoImage.EL_TORITO_BOOT_ENTRY if bootable: boot = 0x88 else: boot = 0 media_type = 1 load_seg = 1 sys_type = 1 pad0 = 1 sectors = 1 load_rba = 1 data = (boot, media_type, load_seg, sys_type, pad0, sectors, load_rba) s = fmt.pack(*data) fd.write(s) s = 'a' * IsoImage.SECTOR_SIZE fd.write(s) def _build_bootable_ppc_path_table(self, fd): # write path table locator PATH_TABLE_LOC_OFFSET = 16 * IsoImage.SECTOR_SIZE + 132 PATH_TABLE_SIZE_LOC = struct.Struct(" 0: iface = interfaces[0]['name'] _do_network_test(self, model, {'name': u'bridge-network', 'connection': 'bridge', 'interface': iface, 'vlan_id': 987}) kimchi-1.5.0/tests/test_mock_storagepool.py000066400000000000000000000121451254252253000211060ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # Project Kimchi # # Copyright IBM, Corp. 2015 # # 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 import json import os import unittest from functools import partial from kimchi.mockmodel import MockModel from utils import get_free_port, patch_auth, request, run_server model = None test_server = None host = None port = None ssl_port = None cherrypy_port = None def setUpModule(): global test_server, model, host, port, ssl_port, cherrypy_port patch_auth() model = MockModel('/tmp/obj-store-test') host = '127.0.0.1' port = get_free_port('http') ssl_port = get_free_port('https') cherrypy_port = get_free_port('cherrypy_port') test_server = run_server(host, port, ssl_port, test_mode=True, cherrypy_port=cherrypy_port, model=model) def tearDownModule(): test_server.stop() os.unlink('/tmp/obj-store-test') class MockStoragepoolTests(unittest.TestCase): def setUp(self): self.request = partial(request, host, ssl_port) model.reset() def _task_lookup(self, taskid): return json.loads(self.request('/tasks/%s' % taskid).read()) def test_storagepool(self): # MockModel always returns 2 partitions (vdx, vdz) partitions = json.loads(self.request('/host/partitions').read()) devs = [dev['path'] for dev in partitions] # MockModel always returns 3 FC devices fc_devs = json.loads(self.request('/host/devices?_cap=fc_host').read()) fc_devs = [dev['name'] for dev in fc_devs] poolDefs = [ {'type': 'dir', 'name': u'kīмÑhÄ«UnitTestDirPool', 'path': '/tmp/kimchi-images'}, {'type': 'netfs', 'name': u'kīмÑhÄ«UnitTestNSFPool', 'source': {'host': 'localhost', 'path': '/var/lib/kimchi/nfs-pool'}}, {'type': 'scsi', 'name': u'kīмÑhÄ«UnitTestSCSIFCPool', 'source': {'adapter_name': fc_devs[0]}}, {'type': 'iscsi', 'name': u'kīмÑhÄ«UnitTestISCSIPool', 'source': {'host': '127.0.0.1', 'target': 'iqn.2015-01.localhost.kimchiUnitTest'}}, {'type': 'logical', 'name': u'kīмÑhÄ«UnitTestLogicalPool', 'source': {'devices': [devs[0]]}}] def _do_test(params): name = params['name'] uri = '/storagepools/%s' % name.encode('utf-8') req = json.dumps(params) resp = self.request('/storagepools', req, 'POST') self.assertEquals(201, resp.status) # activate the storage pool resp = self.request(uri + '/activate', '{}', 'POST') storagepool = json.loads(self.request(uri).read()) self.assertEquals('active', storagepool['state']) # Set autostart flag of an active storage pool for autostart in [True, False]: t = {'autostart': autostart} req = json.dumps(t) resp = self.request(uri, req, 'PUT') storagepool = json.loads(self.request(uri).read()) self.assertEquals(autostart, storagepool['autostart']) # Extend an active logical pool if params['type'] == 'logical': t = {'disks': [devs[1]]} req = json.dumps(t) resp = self.request(uri, req, 'PUT') self.assertEquals(200, resp.status) # Deactivate the storage pool resp = self.request(uri + '/deactivate', '{}', 'POST') storagepool = json.loads(self.request(uri).read()) self.assertEquals('inactive', storagepool['state']) # Set autostart flag of an inactive storage pool for autostart in [True, False]: t = {'autostart': autostart} req = json.dumps(t) resp = self.request(uri, req, 'PUT') storagepool = json.loads(self.request(uri).read()) self.assertEquals(autostart, storagepool['autostart']) # Extend an inactive logical pool if params['type'] == 'logical': t = {'disks': [devs[1]]} req = json.dumps(t) resp = self.request(uri, req, 'PUT') self.assertEquals(200, resp.status) # Delete the storage pool resp = self.request(uri, '{}', 'DELETE') self.assertEquals(204, resp.status) for pool in poolDefs: _do_test(pool) kimchi-1.5.0/tests/test_mock_storagevolume.py000066400000000000000000000065241254252253000214500ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # Project Kimchi # # Copyright IBM, Corp. 2015 # # 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 import json import os import unittest from functools import partial from kimchi.mockmodel import MockModel from test_model_storagevolume import _do_volume_test from utils import get_free_port, patch_auth, request, run_server model = None test_server = None host = None port = None ssl_port = None cherrypy_port = None def setUpModule(): global test_server, model, host, port, ssl_port, cherrypy_port patch_auth() model = MockModel('/tmp/obj-store-test') host = '127.0.0.1' port = get_free_port('http') ssl_port = get_free_port('https') cherrypy_port = get_free_port('cherrypy_port') test_server = run_server(host, port, ssl_port, test_mode=True, cherrypy_port=cherrypy_port, model=model) def tearDownModule(): test_server.stop() os.unlink('/tmp/obj-store-test') class MockStorageVolumeTests(unittest.TestCase): def setUp(self): self.request = partial(request, host, ssl_port) def test_storagevolume(self): # MockModel always returns 2 partitions (vdx, vdz) partitions = json.loads(self.request('/host/partitions').read()) devs = [dev['path'] for dev in partitions] # MockModel always returns 3 FC devices fc_devs = json.loads(self.request('/host/devices?_cap=fc_host').read()) fc_devs = [dev['name'] for dev in fc_devs] poolDefs = [ {'type': 'dir', 'name': u'kīмÑhÄ«UnitTestDirPool', 'path': '/tmp/kimchi-images'}, {'type': 'netfs', 'name': u'kīмÑhÄ«UnitTestNSFPool', 'source': {'host': 'localhost', 'path': '/var/lib/kimchi/nfs-pool'}}, {'type': 'scsi', 'name': u'kīмÑhÄ«UnitTestSCSIFCPool', 'source': {'adapter_name': fc_devs[0]}}, {'type': 'iscsi', 'name': u'kīмÑhÄ«UnitTestISCSIPool', 'source': {'host': '127.0.0.1', 'target': 'iqn.2015-01.localhost.kimchiUnitTest'}}, {'type': 'logical', 'name': u'kīмÑhÄ«UnitTestLogicalPool', 'source': {'devices': [devs[0]]}}] for pool in poolDefs: pool_name = pool['name'] uri = '/storagepools/%s' % pool_name.encode('utf-8') req = json.dumps(pool) resp = self.request('/storagepools', req, 'POST') self.assertEquals(201, resp.status) # activate the storage pool resp = self.request(uri + '/activate', '{}', 'POST') self.assertEquals(200, resp.status) _do_volume_test(self, model, host, ssl_port, pool_name) kimchi-1.5.0/tests/test_mockmodel.py000066400000000000000000000120331254252253000175050ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-2015 # # 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 import cherrypy import json import os import time import unittest import kimchi.mockmodel from utils import get_free_port, patch_auth, request, run_server, wait_task from kimchi.osinfo import get_template_default test_server = None model = None host = None port = None ssl_port = None fake_iso = None def setUpModule(): global host, port, ssl_port, model, test_server, fake_iso cherrypy.request.headers = {'Accept': 'application/json'} model = kimchi.mockmodel.MockModel('/tmp/obj-store-test') patch_auth() port = get_free_port('http') ssl_port = get_free_port('https') host = '127.0.0.1' test_server = run_server(host, port, ssl_port, test_mode=True, model=model) fake_iso = '/tmp/fake.iso' open(fake_iso, 'w').close() def tearDown(): test_server.stop() os.unlink('/tmp/obj-store-test') os.unlink(fake_iso) class MockModelTests(unittest.TestCase): def setUp(self): model.reset() def test_screenshot_refresh(self): # Create a VM req = json.dumps({'name': 'test', 'cdrom': fake_iso}) request(host, ssl_port, '/templates', req, 'POST') req = json.dumps({'name': 'test-vm', 'template': '/templates/test'}) resp = request(host, ssl_port, '/vms', req, 'POST') task = json.loads(resp.read()) wait_task(model.task_lookup, task['id']) # Test screenshot refresh for running vm request(host, ssl_port, '/vms/test-vm/start', '{}', 'POST') resp = request(host, ssl_port, '/vms/test-vm/screenshot') self.assertEquals(200, resp.status) self.assertEquals('image/png', resp.getheader('content-type')) resp1 = request(host, ssl_port, '/vms/test-vm') rspBody = resp1.read() testvm_Data = json.loads(rspBody) screenshotURL = testvm_Data['screenshot'] time.sleep(5) resp2 = request(host, ssl_port, screenshotURL) self.assertEquals(200, resp2.status) self.assertEquals(resp2.getheader('content-type'), resp.getheader('content-type')) self.assertEquals(resp2.getheader('content-length'), resp.getheader('content-length')) self.assertEquals(resp2.getheader('last-modified'), resp.getheader('last-modified')) def test_vm_list_sorted(self): req = json.dumps({'name': 'test', 'cdrom': fake_iso}) request(host, ssl_port, '/templates', req, 'POST') def add_vm(name): # Create a VM req = json.dumps({'name': name, 'template': '/templates/test'}) task = json.loads(request(host, ssl_port, '/vms', req, 'POST').read()) wait_task(model.task_lookup, task['id']) vms = [u'abc', u'bca', u'cab', u'xba'] for vm in vms: add_vm(vm) vms.append(u'test') self.assertEqual(model.vms_get_list(), sorted(vms)) def test_vm_info(self): model.templates_create({'name': u'test', 'cdrom': fake_iso}) task = model.vms_create({'name': u'test-vm', 'template': '/templates/test'}) wait_task(model.task_lookup, task['id']) vms = model.vms_get_list() self.assertEquals(2, len(vms)) self.assertIn(u'test-vm', vms) keys = set(('name', 'state', 'stats', 'uuid', 'memory', 'cpus', 'screenshot', 'icon', 'graphics', 'users', 'groups', 'access', 'persistent')) stats_keys = set(('cpu_utilization', 'net_throughput', 'net_throughput_peak', 'io_throughput', 'io_throughput_peak')) info = model.vm_lookup(u'test-vm') self.assertEquals(keys, set(info.keys())) self.assertEquals('shutoff', info['state']) self.assertEquals('test-vm', info['name']) self.assertEquals(get_template_default('old', 'memory'), info['memory']) self.assertEquals(1, info['cpus']) self.assertEquals('images/icon-vm.png', info['icon']) self.assertEquals(stats_keys, set(info['stats'].keys())) self.assertEquals('vnc', info['graphics']['type']) self.assertEquals('127.0.0.1', info['graphics']['listen']) kimchi-1.5.0/tests/test_model.py000066400000000000000000001477331254252253000166530ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # Project Kimchi # # Copyright IBM, Corp. 2013-2015 # # 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 import grp import os import pwd import re import shutil import time import unittest import uuid import iso_gen import kimchi.objectstore import utils from kimchi import netinfo from kimchi.basemodel import Singleton from kimchi.config import config from kimchi.exception import InvalidOperation from kimchi.exception import InvalidParameter, NotFoundError, OperationFailed from kimchi.osinfo import get_template_default from kimchi.model import model from kimchi.model.libvirtconnection import LibvirtConnection from kimchi.rollbackcontext import RollbackContext from kimchi.utils import add_task invalid_repository_urls = ['www.fedora.org', # missing protocol '://www.fedora.org', # missing protocol 'http://www.fedora', # invalid domain name 'file:///home/foobar'] # invalid path TMP_DIR = '/var/lib/kimchi/tests/' UBUNTU_ISO = TMP_DIR + 'ubuntu14.04.iso' def setUpModule(): if not os.path.exists(TMP_DIR): os.makedirs(TMP_DIR) iso_gen.construct_fake_iso(UBUNTU_ISO, True, '14.04', 'ubuntu') # Some FeatureTests functions depend on server to validate their result. # As CapabilitiesModel is a Singleton class it will get the first result # from FeatureTests which may be wrong when using the Model instance # directly - the case of this test_model.py # So clean Singleton instances to make sure to get the right result when # running the following tests. Singleton._instances = {} def tearDownModule(): shutil.rmtree(TMP_DIR) class ModelTests(unittest.TestCase): def setUp(self): self.tmp_store = '/tmp/kimchi-store-test' def tearDown(self): # FIXME: Tests using 'test:///default' URI should be moved to # test_rest or test_mockmodel to avoid overriding problems LibvirtConnection._connections['test:///default'] = {} os.unlink(self.tmp_store) def test_vm_info(self): inst = model.Model('test:///default', self.tmp_store) vms = inst.vms_get_list() self.assertEquals(1, len(vms)) self.assertEquals('test', vms[0]) keys = set(('name', 'state', 'stats', 'uuid', 'memory', 'cpus', 'screenshot', 'icon', 'graphics', 'users', 'groups', 'access', 'persistent')) stats_keys = set(('cpu_utilization', 'net_throughput', 'net_throughput_peak', 'io_throughput', 'io_throughput_peak')) info = inst.vm_lookup('test') self.assertEquals(keys, set(info.keys())) self.assertEquals('running', info['state']) self.assertEquals('test', info['name']) self.assertEquals(2048, info['memory']) self.assertEquals(2, info['cpus']) self.assertEquals(None, info['icon']) self.assertEquals(stats_keys, set(info['stats'].keys())) self.assertRaises(NotFoundError, inst.vm_lookup, 'nosuchvm') self.assertEquals([], info['users']) self.assertEquals([], info['groups']) self.assertTrue(info['persistent']) @unittest.skipUnless(utils.running_as_root(), 'Must be run as root') def test_vm_lifecycle(self): inst = model.Model(objstore_loc=self.tmp_store) with RollbackContext() as rollback: vol_params = {'name': u'test-vol', 'capacity': 1024} task = inst.storagevolumes_create(u'default', vol_params) rollback.prependDefer(inst.storagevolume_delete, u'default', vol_params['name']) inst.task_wait(task['id']) task = inst.task_lookup(task['id']) self.assertEquals('finished', task['status']) vol = inst.storagevolume_lookup(u'default', vol_params['name']) params = {'name': 'test', 'disks': [{'base': vol['path'], 'size': 1}], 'cdrom': UBUNTU_ISO} inst.templates_create(params) rollback.prependDefer(inst.template_delete, 'test') params = {'name': 'kimchi-vm', 'template': '/templates/test'} task = inst.vms_create(params) rollback.prependDefer(inst.vm_delete, 'kimchi-vm') inst.task_wait(task['id'], 10) task = inst.task_lookup(task['id']) self.assertEquals('finished', task['status']) vms = inst.vms_get_list() self.assertTrue('kimchi-vm' in vms) inst.vm_start('kimchi-vm') info = inst.vm_lookup('kimchi-vm') self.assertEquals('running', info['state']) self.assertRaises(InvalidOperation, inst.vmsnapshots_create, u'kimchi-vm') inst.vm_poweroff(u'kimchi-vm') vm = inst.vm_lookup(u'kimchi-vm') empty_snap = inst.currentvmsnapshot_lookup(u'kimchi-vm') self.assertEquals({}, empty_snap) # this snapshot should be deleted when its VM is deleted params = {'name': u'mysnap'} task = inst.vmsnapshots_create(u'kimchi-vm', params) inst.task_wait(task['id']) task = inst.task_lookup(task['id']) self.assertEquals('finished', task['status']) self.assertRaises(NotFoundError, inst.vmsnapshot_lookup, u'kimchi-vm', u'foobar') snap = inst.vmsnapshot_lookup(u'kimchi-vm', params['name']) self.assertTrue(int(time.time()) >= int(snap['created'])) self.assertEquals(vm['state'], snap['state']) self.assertEquals(params['name'], snap['name']) self.assertEquals(u'', snap['parent']) snaps = inst.vmsnapshots_get_list(u'kimchi-vm') self.assertEquals([params['name']], snaps) current_snap = inst.currentvmsnapshot_lookup(u'kimchi-vm') self.assertEquals(snap, current_snap) task = inst.vmsnapshots_create(u'kimchi-vm') snap_name = task['target_uri'].split('/')[-1] rollback.prependDefer(inst.vmsnapshot_delete, u'kimchi-vm', snap_name) inst.task_wait(task['id']) task = inst.task_lookup(task['id']) self.assertEquals('finished', task['status']) snaps = inst.vmsnapshots_get_list(u'kimchi-vm') self.assertEquals(sorted([params['name'], snap_name], key=unicode.lower), snaps) snap = inst.vmsnapshot_lookup(u'kimchi-vm', snap_name) current_snap = inst.currentvmsnapshot_lookup(u'kimchi-vm') self.assertEquals(snap, current_snap) # update vm name inst.vm_update('kimchi-vm', {'name': u'kimchi-vm-new'}) # Look up the first created snapshot from the renamed vm snap = inst.vmsnapshot_lookup(u'kimchi-vm-new', params['name']) # snapshot revert to the first created vm result = inst.vmsnapshot_revert(u'kimchi-vm-new', params['name']) self.assertEquals(result, [u'kimchi-vm', snap['name']]) vm = inst.vm_lookup(u'kimchi-vm') self.assertEquals(vm['state'], snap['state']) current_snap = inst.currentvmsnapshot_lookup(u'kimchi-vm') self.assertEquals(params['name'], current_snap['name']) self.assertRaises(NotFoundError, inst.vmsnapshot_delete, u'kimchi-vm', u'foobar') # suspend and resume the VM info = inst.vm_lookup(u'kimchi-vm') self.assertEquals(info['state'], 'shutoff') self.assertRaises(InvalidOperation, inst.vm_suspend, u'kimchi-vm') inst.vm_start(u'kimchi-vm') info = inst.vm_lookup(u'kimchi-vm') self.assertEquals(info['state'], 'running') inst.vm_suspend(u'kimchi-vm') info = inst.vm_lookup(u'kimchi-vm') self.assertEquals(info['state'], 'paused') self.assertRaises(InvalidParameter, inst.vm_update, u'kimchi-vm', {'name': 'foo'}) inst.vm_resume(u'kimchi-vm') info = inst.vm_lookup(u'kimchi-vm') self.assertEquals(info['state'], 'running') self.assertRaises(InvalidOperation, inst.vm_resume, u'kimchi-vm') # leave the VM suspended to make sure a paused VM can be # deleted correctly inst.vm_suspend(u'kimchi-vm') vms = inst.vms_get_list() self.assertFalse('kimchi-vm' in vms) @unittest.skipUnless(utils.running_as_root(), 'Must be run as root') def test_image_based_template(self): inst = model.Model(objstore_loc=self.tmp_store) with RollbackContext() as rollback: vol = 'base-vol.img' params = {'name': vol, 'capacity': 1073741824, # 1 GiB 'allocation': 1048576, # 1 MiB 'format': 'qcow2'} task_id = inst.storagevolumes_create('default', params)['id'] rollback.prependDefer(inst.storagevolume_delete, 'default', vol) inst.task_wait(task_id) self.assertEquals('finished', inst.task_lookup(task_id)['status']) vol_path = inst.storagevolume_lookup('default', vol)['path'] params = {'name': 'test', 'disks': [{'base': vol_path}]} self.assertRaises(OperationFailed, inst.templates_create, params) # Hack the model objstore to add a new template # It is needed as the image file must be a bootable image when # using model # As it is difficult to create one on test runtime, inject a # template with an empty image file to the objstore to test the # feature tmpl_name = "img-tmpl" tmpl_info = {"cpus": 1, "cdrom": "", "graphics": {"type": "vnc", "listen": "127.0.0.1"}, "networks": ["default"], "memory": 1024, "folder": [], "icon": "images/icon-vm.png", "os_distro": "unknown", "os_version": "unknown", "disks": [{"base": vol_path, "size": 10}], "storagepool": "/storagepools/default"} with inst.objstore as session: session.store('template', tmpl_name, tmpl_info) params = {'name': 'kimchi-vm', 'template': '/templates/img-tmpl'} task = inst.vms_create(params) inst.task_wait(task['id']) rollback.prependDefer(inst.vm_delete, 'kimchi-vm') vms = inst.vms_get_list() self.assertTrue('kimchi-vm' in vms) inst.vm_start('kimchi-vm') rollback.prependDefer(inst.vm_poweroff, 'kimchi-vm') info = inst.vm_lookup('kimchi-vm') self.assertEquals('running', info['state']) @unittest.skipUnless(utils.running_as_root(), 'Must be run as root') def test_vm_graphics(self): inst = model.Model(objstore_loc=self.tmp_store) params = {'name': 'test', 'disks': [], 'cdrom': UBUNTU_ISO} inst.templates_create(params) with RollbackContext() as rollback: params = {'name': 'kimchi-vnc', 'template': '/templates/test'} task1 = inst.vms_create(params) inst.task_wait(task1['id']) rollback.prependDefer(inst.vm_delete, 'kimchi-vnc') info = inst.vm_lookup('kimchi-vnc') self.assertEquals('vnc', info['graphics']['type']) self.assertEquals('127.0.0.1', info['graphics']['listen']) graphics = {'type': 'spice', 'listen': '127.0.0.1'} params = {'name': 'kimchi-spice', 'template': '/templates/test', 'graphics': graphics} task2 = inst.vms_create(params) inst.task_wait(task2['id']) rollback.prependDefer(inst.vm_delete, 'kimchi-spice') info = inst.vm_lookup('kimchi-spice') self.assertEquals('spice', info['graphics']['type']) self.assertEquals('127.0.0.1', info['graphics']['listen']) inst.template_delete('test') @unittest.skipUnless(utils.running_as_root(), 'Must be run as root') def test_vm_ifaces(self): inst = model.Model(objstore_loc=self.tmp_store) with RollbackContext() as rollback: params = {'name': 'test', 'disks': [], 'cdrom': UBUNTU_ISO} inst.templates_create(params) rollback.prependDefer(inst.template_delete, 'test') # Create a network net_name = 'test-network' net_args = {'name': net_name, 'connection': 'nat', 'subnet': '127.0.100.0/24'} inst.networks_create(net_args) rollback.prependDefer(inst.network_delete, net_name) inst.network_activate(net_name) rollback.prependDefer(inst.network_deactivate, net_name) for vm_name in ['kimchi-ifaces', 'kimchi-ifaces-running']: params = {'name': vm_name, 'template': '/templates/test'} task = inst.vms_create(params) inst.task_wait(task['id']) rollback.prependDefer(inst.vm_delete, vm_name) ifaces = inst.vmifaces_get_list(vm_name) self.assertEquals(1, len(ifaces)) iface = inst.vmiface_lookup(vm_name, ifaces[0]) self.assertEquals(17, len(iface['mac'])) self.assertEquals("default", iface['network']) self.assertIn("model", iface) # attach network interface to vm iface_args = {"type": "network", "network": "test-network", "model": "virtio"} mac = inst.vmifaces_create(vm_name, iface_args) # detach network interface from vm rollback.prependDefer(inst.vmiface_delete, vm_name, mac) self.assertEquals(17, len(mac)) iface = inst.vmiface_lookup(vm_name, mac) self.assertEquals("network", iface["type"]) self.assertEquals("test-network", iface['network']) self.assertEquals("virtio", iface["model"]) # attach network interface to vm without providing model iface_args = {"type": "network", "network": "test-network"} mac = inst.vmifaces_create(vm_name, iface_args) rollback.prependDefer(inst.vmiface_delete, vm_name, mac) iface = inst.vmiface_lookup(vm_name, mac) self.assertEquals("network", iface["type"]) self.assertEquals("test-network", iface['network']) # update vm interface newMacAddr = '54:50:e3:44:8a:af' iface_args = {"mac": newMacAddr} inst.vmiface_update(vm_name, mac, iface_args) iface = inst.vmiface_lookup(vm_name, newMacAddr) self.assertEquals(newMacAddr, iface['mac']) # undo mac address change iface_args = {"mac": mac} inst.vmiface_update(vm_name, newMacAddr, iface_args) iface = inst.vmiface_lookup(vm_name, mac) self.assertEquals(mac, iface['mac']) @unittest.skipUnless(utils.running_as_root(), 'Must be run as root') def test_vm_disk(self): disk_path = os.path.join(TMP_DIR, 'existent2.iso') open(disk_path, 'w').close() modern_disk_bus = get_template_default('modern', 'disk_bus') def _attach_disk(expect_bus=modern_disk_bus): disk_args = {"type": "disk", "pool": pool, "vol": vol} disk = inst.vmstorages_create(vm_name, disk_args) storage_list = inst.vmstorages_get_list(vm_name) self.assertEquals(prev_count + 1, len(storage_list)) # Check the bus type to be 'virtio' disk_info = inst.vmstorage_lookup(vm_name, disk) self.assertEquals(u'disk', disk_info['type']) self.assertEquals(vol_path, disk_info['path']) self.assertEquals(expect_bus, disk_info['bus']) return disk inst = model.Model(objstore_loc=self.tmp_store) with RollbackContext() as rollback: path = os.path.join(TMP_DIR, 'kimchi-images') pool = 'test-pool' vol = 'test-volume.img' vol_path = "%s/%s" % (path, vol) if not os.path.exists(path): os.mkdir(path) rollback.prependDefer(shutil.rmtree, path) args = {'name': pool, 'path': path, 'type': 'dir'} inst.storagepools_create(args) rollback.prependDefer(inst.storagepool_delete, pool) # Activate the pool before adding any volume inst.storagepool_activate(pool) rollback.prependDefer(inst.storagepool_deactivate, pool) params = {'name': vol, 'capacity': 1073741824, # 1 GiB 'allocation': 536870912, # 512 MiB 'format': 'qcow2'} task_id = inst.storagevolumes_create(pool, params)['id'] rollback.prependDefer(inst.storagevolume_delete, pool, vol) inst.task_wait(task_id) vm_name = 'kimchi-cdrom' params = {'name': 'test', 'disks': [], 'cdrom': UBUNTU_ISO} inst.templates_create(params) rollback.prependDefer(inst.template_delete, 'test') params = {'name': vm_name, 'template': '/templates/test'} task1 = inst.vms_create(params) inst.task_wait(task1['id']) rollback.prependDefer(inst.vm_delete, vm_name) prev_count = len(inst.vmstorages_get_list(vm_name)) self.assertEquals(1, prev_count) # Volume format with mismatched type raise error cdrom_args = {"type": "cdrom", "pool": pool, "vol": vol} self.assertRaises(InvalidParameter, inst.vmstorages_create, vm_name, cdrom_args) # Cold plug and unplug a disk disk = _attach_disk() inst.vmstorage_delete(vm_name, disk) # Hot plug a disk inst.vm_start(vm_name) disk = _attach_disk() # VM disk still there after powered off inst.vm_poweroff(vm_name) disk_info = inst.vmstorage_lookup(vm_name, disk) self.assertEquals(u'disk', disk_info['type']) inst.vmstorage_delete(vm_name, disk) # Specifying pool and path at same time will fail disk_args = {"type": "disk", "pool": pool, "vol": vol, "path": disk_path} self.assertRaises( InvalidParameter, inst.vmstorages_create, vm_name, disk_args) old_distro_iso = TMP_DIR + 'rhel4_8.iso' iso_gen.construct_fake_iso(old_distro_iso, True, '4.8', 'rhel') vm_name = 'kimchi-ide-bus-vm' params = {'name': 'old_distro_template', 'disks': [], 'cdrom': old_distro_iso} inst.templates_create(params) rollback.prependDefer(inst.template_delete, 'old_distro_template') params = {'name': vm_name, 'template': '/templates/old_distro_template'} task2 = inst.vms_create(params) inst.task_wait(task2['id']) rollback.prependDefer(inst.vm_delete, vm_name) # Need to check the right disk_bus for old distro disk = _attach_disk(get_template_default('old', 'disk_bus')) inst.vmstorage_delete('kimchi-ide-bus-vm', disk) # Hot plug IDE bus disk does not work inst.vm_start(vm_name) self.assertRaises(InvalidOperation, _attach_disk) inst.vm_poweroff(vm_name) @unittest.skipUnless(utils.running_as_root(), 'Must be run as root') def test_vm_cdrom(self): inst = model.Model(objstore_loc=self.tmp_store) with RollbackContext() as rollback: vm_name = 'kimchi-cdrom' params = {'name': 'test', 'disks': [], 'cdrom': UBUNTU_ISO} inst.templates_create(params) rollback.prependDefer(inst.template_delete, 'test') params = {'name': vm_name, 'template': '/templates/test'} task = inst.vms_create(params) inst.task_wait(task['id']) rollback.prependDefer(inst.vm_delete, vm_name) prev_count = len(inst.vmstorages_get_list(vm_name)) self.assertEquals(1, prev_count) # dummy .iso files iso_path = os.path.join(TMP_DIR, 'existent.iso') iso_path2 = os.path.join(TMP_DIR, 'existent2.iso') open(iso_path, 'w').close() rollback.prependDefer(os.remove, iso_path) open(iso_path2, 'w').close() rollback.prependDefer(os.remove, iso_path2) wrong_iso_path = '/nonexistent.iso' # Create a cdrom cdrom_args = {"type": "cdrom", "path": iso_path} cdrom_dev = inst.vmstorages_create(vm_name, cdrom_args) storage_list = inst.vmstorages_get_list(vm_name) self.assertEquals(prev_count + 1, len(storage_list)) # Get cdrom info cd_info = inst.vmstorage_lookup(vm_name, cdrom_dev) self.assertEquals(u'cdrom', cd_info['type']) self.assertEquals(iso_path, cd_info['path']) # update path of existing cd with # non existent iso self.assertRaises(InvalidParameter, inst.vmstorage_update, vm_name, cdrom_dev, {'path': wrong_iso_path}) # Make sure CD ROM still exists after failure cd_info = inst.vmstorage_lookup(vm_name, cdrom_dev) self.assertEquals(u'cdrom', cd_info['type']) self.assertEquals(iso_path, cd_info['path']) # update path of existing cd with existent iso of shutoff vm inst.vmstorage_update(vm_name, cdrom_dev, {'path': iso_path2}) cdrom_info = inst.vmstorage_lookup(vm_name, cdrom_dev) self.assertEquals(iso_path2, cdrom_info['path']) # update path of existing cd with existent iso of running vm inst.vm_start(vm_name) inst.vmstorage_update(vm_name, cdrom_dev, {'path': iso_path}) cdrom_info = inst.vmstorage_lookup(vm_name, cdrom_dev) self.assertEquals(iso_path, cdrom_info['path']) # eject cdrom cdrom_dev = inst.vmstorage_update(vm_name, cdrom_dev, {'path': ''}) cdrom_info = inst.vmstorage_lookup(vm_name, cdrom_dev) self.assertEquals('', cdrom_info['path']) inst.vm_poweroff(vm_name) # removing non existent cdrom self.assertRaises(NotFoundError, inst.vmstorage_delete, vm_name, "fakedev") # removing valid cdrom inst.vmstorage_delete(vm_name, cdrom_dev) storage_list = inst.vmstorages_get_list(vm_name) self.assertEquals(prev_count, len(storage_list)) # Create a new cdrom using a remote iso valid_remote_iso_path = utils.get_remote_iso_path() cdrom_args = {"type": "cdrom", "path": valid_remote_iso_path} cdrom_dev = inst.vmstorages_create(vm_name, cdrom_args) storage_list = inst.vmstorages_get_list(vm_name) self.assertEquals(prev_count + 1, len(storage_list)) # Update remote-backed cdrom with the same ISO inst.vmstorage_update(vm_name, cdrom_dev, {'path': valid_remote_iso_path}) cdrom_info = inst.vmstorage_lookup(vm_name, cdrom_dev) cur_cdrom_path = re.sub(":80/", '/', cdrom_info['path']) self.assertEquals(valid_remote_iso_path, cur_cdrom_path) @unittest.skipUnless(utils.running_as_root(), 'Must be run as root') def test_vm_storage_provisioning(self): inst = model.Model(objstore_loc=self.tmp_store) with RollbackContext() as rollback: params = {'name': 'test', 'disks': [{'size': 1}], 'cdrom': UBUNTU_ISO} inst.templates_create(params) rollback.prependDefer(inst.template_delete, 'test') params = {'name': 'test-vm-1', 'template': '/templates/test'} task = inst.vms_create(params) inst.task_wait(task['id']) rollback.prependDefer(inst.vm_delete, 'test-vm-1') vm_info = inst.vm_lookup(params['name']) disk_path = '%s/%s-0.img' % ( inst.storagepool_lookup('default')['path'], vm_info['uuid']) self.assertTrue(os.access(disk_path, os.F_OK)) self.assertFalse(os.access(disk_path, os.F_OK)) def test_vm_memory_hotplug(self): config.set("authentication", "method", "pam") inst = model.Model(None, objstore_loc=self.tmp_store) orig_params = {'name': 'test', 'memory': 1024, 'cdrom': UBUNTU_ISO} inst.templates_create(orig_params) with RollbackContext() as rollback: params = {'name': 'kimchi-vm1', 'template': '/templates/test'} task1 = inst.vms_create(params) inst.task_wait(task1['id']) rollback.prependDefer(utils.rollback_wrapper, inst.vm_delete, 'kimchi-vm1') # Start vm inst.vm_start('kimchi-vm1') rollback.prependDefer(utils.rollback_wrapper, inst.vm_poweroff, 'kimchi-vm1') # Hotplug memory, only available in Libvirt >= 1.2.14 params = {'memory': 2048} if inst.capabilities_lookup()['mem_hotplug_support']: inst.vm_update('kimchi-vm1', params) rollback.prependDefer(utils.rollback_wrapper, inst.vm_delete, 'kimchi-vm1') self.assertEquals(params['memory'], inst.vm_lookup('kimchi-vm1')['memory']) else: self.assertRaises(InvalidOperation, inst.vm_update, 'kimchi-vm1', params) def test_vm_edit(self): config.set("authentication", "method", "pam") inst = model.Model(None, objstore_loc=self.tmp_store) orig_params = {'name': 'test', 'memory': 1024, 'cpus': 1, 'cdrom': UBUNTU_ISO} inst.templates_create(orig_params) with RollbackContext() as rollback: params_1 = {'name': 'kimchi-vm1', 'template': '/templates/test'} params_2 = {'name': 'kimchi-vm2', 'template': '/templates/test'} task1 = inst.vms_create(params_1) inst.task_wait(task1['id']) rollback.prependDefer(utils.rollback_wrapper, inst.vm_delete, 'kimchi-vm1') task2 = inst.vms_create(params_2) inst.task_wait(task2['id']) rollback.prependDefer(utils.rollback_wrapper, inst.vm_delete, 'kimchi-vm2') vms = inst.vms_get_list() self.assertTrue('kimchi-vm1' in vms) # make sure "vm_update" works when the domain has a snapshot inst.vmsnapshots_create(u'kimchi-vm1') # update vm graphics when vm is not running inst.vm_update(u'kimchi-vm1', {"graphics": {"passwd": "123456"}}) inst.vm_start('kimchi-vm1') rollback.prependDefer(utils.rollback_wrapper, inst.vm_poweroff, 'kimchi-vm1') vm_info = inst.vm_lookup(u'kimchi-vm1') self.assertEquals('123456', vm_info['graphics']["passwd"]) self.assertEquals(None, vm_info['graphics']["passwdValidTo"]) # update vm graphics when vm is running inst.vm_update(u'kimchi-vm1', {"graphics": {"passwd": "abcdef", "passwdValidTo": 20}}) vm_info = inst.vm_lookup(u'kimchi-vm1') self.assertEquals('abcdef', vm_info['graphics']["passwd"]) self.assertGreaterEqual(20, vm_info['graphics']['passwdValidTo']) info = inst.vm_lookup('kimchi-vm1') self.assertEquals('running', info['state']) params = {'name': 'new-vm'} self.assertRaises(InvalidParameter, inst.vm_update, 'kimchi-vm1', params) # change VM users and groups, when wm is running. inst.vm_update(u'kimchi-vm1', {'users': ['root'], 'groups': ['root']}) vm_info = inst.vm_lookup(u'kimchi-vm1') self.assertEquals(['root'], vm_info['users']) self.assertEquals(['root'], vm_info['groups']) # change VM users and groups by removing all elements, # when wm is running. inst.vm_update(u'kimchi-vm1', {'users': [], 'groups': []}) vm_info = inst.vm_lookup(u'kimchi-vm1') self.assertEquals([], vm_info['users']) self.assertEquals([], vm_info['groups']) inst.vm_poweroff('kimchi-vm1') self.assertRaises(OperationFailed, inst.vm_update, 'kimchi-vm1', {'name': 'kimchi-vm2'}) params = {'name': u'пeω-∨м', 'cpus': 4, 'memory': 2048} inst.vm_update('kimchi-vm1', params) rollback.prependDefer(utils.rollback_wrapper, inst.vm_delete, u'пeω-∨м') self.assertEquals(info['uuid'], inst.vm_lookup(u'пeω-∨м')['uuid']) info = inst.vm_lookup(u'пeω-∨м') for key in params.keys(): self.assertEquals(params[key], info[key]) # change only VM users - groups are not changed (default is empty) users = inst.users_get_list()[:3] inst.vm_update(u'пeω-∨м', {'users': users}) self.assertEquals(users, inst.vm_lookup(u'пeω-∨м')['users']) self.assertEquals([], inst.vm_lookup(u'пeω-∨м')['groups']) # change only VM groups - users are not changed (default is empty) groups = inst.groups_get_list()[:2] inst.vm_update(u'пeω-∨м', {'groups': groups}) self.assertEquals(users, inst.vm_lookup(u'пeω-∨м')['users']) self.assertEquals(groups, inst.vm_lookup(u'пeω-∨м')['groups']) # change VM users and groups by adding a new element to each one users.append(pwd.getpwuid(os.getuid()).pw_name) groups.append(grp.getgrgid(os.getgid()).gr_name) inst.vm_update(u'пeω-∨м', {'users': users, 'groups': groups}) self.assertEquals(users, inst.vm_lookup(u'пeω-∨м')['users']) self.assertEquals(groups, inst.vm_lookup(u'пeω-∨м')['groups']) # change VM users (wrong value) and groups # when an error occurs, everything fails and nothing is changed self.assertRaises(InvalidParameter, inst.vm_update, u'пeω-∨м', {'users': ['userdoesnotexist'], 'groups': []}) self.assertEquals(users, inst.vm_lookup(u'пeω-∨м')['users']) self.assertEquals(groups, inst.vm_lookup(u'пeω-∨м')['groups']) # change VM users and groups (wrong value) # when an error occurs, everything fails and nothing is changed self.assertRaises(InvalidParameter, inst.vm_update, u'пeω-∨м', {'users': [], 'groups': ['groupdoesnotexist']}) self.assertEquals(users, inst.vm_lookup(u'пeω-∨м')['users']) self.assertEquals(groups, inst.vm_lookup(u'пeω-∨м')['groups']) # change VM users and groups by removing all elements inst.vm_update(u'пeω-∨м', {'users': [], 'groups': []}) self.assertEquals([], inst.vm_lookup(u'пeω-∨м')['users']) self.assertEquals([], inst.vm_lookup(u'пeω-∨м')['groups']) def test_get_interfaces(self): inst = model.Model('test:///default', objstore_loc=self.tmp_store) expected_ifaces = netinfo.all_favored_interfaces() ifaces = inst.interfaces_get_list() self.assertEquals(len(expected_ifaces), len(ifaces)) for name in expected_ifaces: iface = inst.interface_lookup(name) self.assertEquals(iface['name'], name) self.assertIn('type', iface) self.assertIn('status', iface) self.assertIn('ipaddr', iface) self.assertIn('netmask', iface) def test_async_tasks(self): class task_except(Exception): pass def quick_op(cb, message): cb(message, True) def long_op(cb, params): time.sleep(params.get('delay', 3)) cb(params.get('message', ''), params.get('result', False)) def abnormal_op(cb, params): try: raise task_except except: cb("Exception raised", False) def continuous_ops(cb, params): cb("step 1 OK") time.sleep(2) cb("step 2 OK") time.sleep(2) cb("step 3 OK", params.get('result', True)) inst = model.Model('test:///default', objstore_loc=self.tmp_store) taskid = add_task('', quick_op, inst.objstore, 'Hello') inst.task_wait(taskid) self.assertEquals(1, taskid) self.assertEquals('finished', inst.task_lookup(taskid)['status']) self.assertEquals('Hello', inst.task_lookup(taskid)['message']) taskid = add_task('', long_op, inst.objstore, {'delay': 3, 'result': False, 'message': 'It was not meant to be'}) self.assertEquals(2, taskid) self.assertEquals('running', inst.task_lookup(taskid)['status']) self.assertEquals('OK', inst.task_lookup(taskid)['message']) inst.task_wait(taskid) self.assertEquals('failed', inst.task_lookup(taskid)['status']) self.assertEquals('It was not meant to be', inst.task_lookup(taskid)['message']) taskid = add_task('', abnormal_op, inst.objstore, {}) inst.task_wait(taskid) self.assertEquals('Exception raised', inst.task_lookup(taskid)['message']) self.assertEquals('failed', inst.task_lookup(taskid)['status']) taskid = add_task('', continuous_ops, inst.objstore, {'result': True}) self.assertEquals('running', inst.task_lookup(taskid)['status']) inst.task_wait(taskid, timeout=10) self.assertEquals('finished', inst.task_lookup(taskid)['status']) @unittest.skipUnless(utils.running_as_root(), 'Must be run as root') def test_delete_running_vm(self): inst = model.Model(objstore_loc=self.tmp_store) with RollbackContext() as rollback: params = {'name': u'test', 'disks': [], 'cdrom': UBUNTU_ISO} inst.templates_create(params) rollback.prependDefer(inst.template_delete, 'test') params = {'name': u'kīмÑhÄ«-∨м', 'template': u'/templates/test'} task = inst.vms_create(params) inst.task_wait(task['id']) rollback.prependDefer(utils.rollback_wrapper, inst.vm_delete, u'kīмÑhÄ«-∨м') inst.vm_start(u'kīмÑhÄ«-∨м') self.assertEquals(inst.vm_lookup(u'kīмÑhÄ«-∨м')['state'], 'running') rollback.prependDefer(utils.rollback_wrapper, inst.vm_poweroff, u'kīмÑhÄ«-∨м') inst.vm_delete(u'kīмÑhÄ«-∨м') vms = inst.vms_get_list() self.assertFalse(u'kīмÑhÄ«-∨м' in vms) @unittest.skipUnless(utils.running_as_root(), 'Must be run as root') def test_vm_list_sorted(self): inst = model.Model(objstore_loc=self.tmp_store) with RollbackContext() as rollback: params = {'name': 'test', 'disks': [], 'cdrom': UBUNTU_ISO} inst.templates_create(params) rollback.prependDefer(inst.template_delete, 'test') params = {'name': 'kimchi-vm', 'template': '/templates/test'} task = inst.vms_create(params) inst.task_wait(task['id']) rollback.prependDefer(inst.vm_delete, 'kimchi-vm') vms = inst.vms_get_list() self.assertEquals(vms, sorted(vms, key=unicode.lower)) def test_vm_clone(self): inst = model.Model('test:///default', objstore_loc=self.tmp_store) all_vm_names = inst.vms_get_list() name = all_vm_names[0] original_vm = inst.vm_lookup(name) if original_vm['state'] == u'shutoff': inst.vm_start(name) # the VM 'test' should be running by now, so we can't clone it yet self.assertRaises(InvalidParameter, inst.vm_clone, name) with RollbackContext() as rollback: inst.vm_poweroff(name) rollback.prependDefer(inst.vm_start, name) # create two simultaneous clones of the same VM # and make sure both of them complete successfully task1 = inst.vm_clone(name) task2 = inst.vm_clone(name) clone1_name = task1['target_uri'].split('/')[-2] rollback.prependDefer(inst.vm_delete, clone1_name) clone2_name = task2['target_uri'].split('/')[-2] rollback.prependDefer(inst.vm_delete, clone2_name) inst.task_wait(task1['id']) task1 = inst.task_lookup(task1['id']) self.assertEquals('finished', task1['status']) inst.task_wait(task2['id']) task2 = inst.task_lookup(task2['id']) self.assertEquals('finished', task2['status']) # update the original VM info because its state has changed original_vm = inst.vm_lookup(name) clone_vm = inst.vm_lookup(clone1_name) self.assertNotEqual(original_vm['name'], clone_vm['name']) self.assertTrue(re.match(u'%s-clone-\d+' % original_vm['name'], clone_vm['name'])) del original_vm['name'] del clone_vm['name'] self.assertNotEqual(original_vm['uuid'], clone_vm['uuid']) del original_vm['uuid'] del clone_vm['uuid'] # compare all VM settings except the ones already compared # (and removed) above (i.e. 'name' and 'uuid') self.assertEquals(original_vm, clone_vm) def test_use_test_host(self): inst = model.Model('test:///default', objstore_loc=self.tmp_store) with RollbackContext() as rollback: params = {'name': 'test', 'disks': [], 'cdrom': UBUNTU_ISO, 'storagepool': '/storagepools/default-pool', 'domain': 'test', 'arch': 'i686'} inst.templates_create(params) rollback.prependDefer(inst.template_delete, 'test') params = {'name': 'kimchi-vm', 'template': '/templates/test'} task = inst.vms_create(params) inst.task_wait(task['id']) rollback.prependDefer(inst.vm_delete, 'kimchi-vm') vms = inst.vms_get_list() self.assertTrue('kimchi-vm' in vms) @unittest.skipUnless(utils.running_as_root(), 'Must be run as root') def test_debug_reports(self): inst = model.Model('test:///default', objstore_loc=self.tmp_store) if not inst.capabilities_lookup()['system_report_tool']: raise unittest.SkipTest("Without debug report tool") try: timeout = int(os.environ['TEST_REPORT_TIMEOUT']) except (ValueError, KeyError): timeout = 120 namePrefix = 'unitTestReport' # sosreport always deletes unsual letters like '-' and '_' in the # generated report file name. uuidstr = str(uuid.uuid4()).translate(None, "-_") reportName = namePrefix + uuidstr try: inst.debugreport_delete(namePrefix + '*') except NotFoundError: pass with RollbackContext() as rollback: report_list = inst.debugreports_get_list() self.assertFalse(reportName in report_list) try: tmp_name = reportName + "_1" task = inst.debugreports_create({'name': reportName}) rollback.prependDefer(inst.debugreport_delete, tmp_name) taskid = task['id'] inst.task_wait(taskid, timeout) self.assertEquals('finished', inst.task_lookup(taskid)['status'], "It is not necessary an error. " "You may need to increase the " "timeout number by " "TEST_REPORT_TIMEOUT=200 " "./run_tests.sh test_model") report_list = inst.debugreports_get_list() self.assertTrue(reportName in report_list) name = inst.debugreport_update(reportName, {'name': tmp_name}) self.assertEquals(name, tmp_name) report_list = inst.debugreports_get_list() self.assertTrue(tmp_name in report_list) except OperationFailed, e: if 'debugreport tool not found' not in e.message: raise e def test_get_distros(self): inst = model.Model('test:///default', objstore_loc=self.tmp_store) distros = inst.distros_get_list() for d in distros: distro = inst.distro_lookup(d) self.assertIn('name', distro) self.assertIn('os_distro', distro) self.assertIn('os_version', distro) self.assertIn('os_arch', distro) self.assertIn('path', distro) @unittest.skipUnless(utils.running_as_root(), 'Must be run as root') def test_deep_scan(self): inst = model.Model(None, objstore_loc=self.tmp_store) with RollbackContext() as rollback: deep_path = os.path.join(TMP_DIR, 'deep-scan') subdir_path = os.path.join(deep_path, 'isos') if not os.path.exists(subdir_path): os.makedirs(subdir_path) ubuntu_iso = os.path.join(deep_path, 'ubuntu12.04.iso') sles_iso = os.path.join(subdir_path, 'sles10.iso') iso_gen.construct_fake_iso(ubuntu_iso, True, '12.04', 'ubuntu') iso_gen.construct_fake_iso(sles_iso, True, '10', 'sles') args = {'name': 'kimchi-scanning-pool', 'path': deep_path, 'type': 'kimchi-iso'} inst.storagepools_create(args) rollback.prependDefer(shutil.rmtree, deep_path) rollback.prependDefer(shutil.rmtree, args['path']) rollback.prependDefer(inst.storagepool_deactivate, args['name']) time.sleep(1) volumes = inst.storagevolumes_get_list(args['name']) self.assertEquals(len(volumes), 2) def test_repository_create(self): inst = model.Model('test:///default', objstore_loc=self.tmp_store) yum_repos = [{'repo_id': 'fedora-fake', 'baseurl': 'http://www.fedora.org'}, {'repo_id': 'fedora-updates-fake', 'config': {'mirrorlist': 'http://www.fedoraproject.org'}}] deb_repos = [{'baseurl': 'http://archive.ubuntu.com/ubuntu/', 'config': {'dist': 'quantal'}}, {'baseurl': 'http://archive.ubuntu.com/ubuntu/', 'config': {'dist': 'quantal', 'comps': ['main']}}] yum_invalid_repos = [] deb_invalid_repos = [] for url in invalid_repository_urls: wrong_baseurl = {'repo_id': 'wrong-id', 'baseurl': url} wrong_mirrorlist = {'repo_id': 'wrong-id', 'baseurl': 'www.example.com', 'config': {'mirrorlist': url}} wrong_config_item = { 'repo_id': 'wrong-id', 'baseurl': 'www.example.com', 'config': { 'gpgkey': 'file:///tmp/KEY-fedora-updates-fake-19'}} yum_invalid_repos.append(wrong_baseurl) yum_invalid_repos.append(wrong_mirrorlist) yum_invalid_repos.append(wrong_config_item) wrong_baseurl['config'] = {'dist': 'tasty'} wrong_config = {'baseurl': deb_repos[0]['baseurl'], 'config': { 'unsupported_item': "a_unsupported_item"}} deb_invalid_repos.append(wrong_baseurl) deb_invalid_repos.append(wrong_config) repo_type = inst.capabilities_lookup()['repo_mngt_tool'] if repo_type == 'yum': test_repos = yum_repos invalid_repos = yum_invalid_repos elif repo_type == 'deb': test_repos = deb_repos invalid_repos = deb_invalid_repos else: # repository management tool was not recognized by Kimchi # skip test case return # create repositories with invalid data for repo in invalid_repos: self.assertRaises(InvalidParameter, inst.repositories_create, repo) for repo in test_repos: system_host_repos = len(inst.repositories_get_list()) repo_id = inst.repositories_create(repo) host_repos = inst.repositories_get_list() self.assertEquals(system_host_repos + 1, len(host_repos)) repo_info = inst.repository_lookup(repo_id) self.assertEquals(repo_id, repo_info['repo_id']) self.assertEquals(True, repo_info.get('enabled')) self.assertEquals(repo.get('baseurl', ''), repo_info.get('baseurl')) original_config = repo.get('config', {}) config_info = repo_info.get('config', {}) if repo_type == 'yum': self.assertEquals(original_config.get('mirrorlist', ''), config_info.get('mirrorlist', '')) self.assertEquals(True, config_info['gpgcheck']) else: self.assertEquals(original_config['dist'], config_info['dist']) self.assertEquals(original_config.get('comps', []), config_info.get('comps', [])) inst.repository_delete(repo_id) self.assertRaises(NotFoundError, inst.repository_lookup, repo_id) self.assertRaises(NotFoundError, inst.repository_lookup, 'google') def test_repository_update(self): inst = model.Model('test:///default', objstore_loc=self.tmp_store) yum_repo = {'repo_id': 'fedora-fake', 'baseurl': 'http://www.fedora.org'} yum_new_repo = {'baseurl': 'http://www.fedoraproject.org'} deb_repo = {'baseurl': 'http://archive.ubuntu.com/ubuntu/', 'config': {'dist': 'quantal'}} deb_new_repo = {'baseurl': 'http://br.archive.canonical.com/ubuntu/', 'config': {'dist': 'utopic'}} yum_invalid_repos = [] deb_invalid_repos = [] for url in invalid_repository_urls: wrong_baseurl = {'baseurl': url} wrong_mirrorlist = {'baseurl': 'www.example.com', 'config': {'mirrorlist': url}} yum_invalid_repos.append(wrong_baseurl) yum_invalid_repos.append(wrong_mirrorlist) wrong_baseurl['config'] = {'dist': 'tasty'} deb_invalid_repos.append(wrong_baseurl) repo_type = inst.capabilities_lookup()['repo_mngt_tool'] if repo_type == 'yum': repo = yum_repo new_repo = yum_new_repo invalid_repos = yum_invalid_repos elif repo_type == 'deb': repo = deb_repo new_repo = deb_new_repo invalid_repos = deb_invalid_repos else: # repository management tool was not recognized by Kimchi # skip test case return system_host_repos = len(inst.repositories_get_list()) with RollbackContext() as rollback: repo_id = inst.repositories_create(repo) rollback.prependDefer(inst.repository_delete, repo_id) host_repos = inst.repositories_get_list() self.assertEquals(system_host_repos + 1, len(host_repos)) # update repositories with invalid data for tmp_repo in invalid_repos: self.assertRaises(InvalidParameter, inst.repository_update, repo_id, tmp_repo) new_repo_id = inst.repository_update(repo_id, new_repo) repo_info = inst.repository_lookup(new_repo_id) self.assertEquals(new_repo_id, repo_info['repo_id']) self.assertEquals(new_repo['baseurl'], repo_info['baseurl']) self.assertEquals(True, repo_info['enabled']) inst.repository_update(new_repo_id, repo) def test_repository_disable_enable(self): inst = model.Model('test:///default', objstore_loc=self.tmp_store) yum_repo = {'repo_id': 'fedora-fake', 'baseurl': 'http://www.fedora.org'} deb_repo = {'baseurl': 'http://archive.ubuntu.com/ubuntu/', 'config': {'dist': 'quantal'}} repo_type = inst.capabilities_lookup()['repo_mngt_tool'] if repo_type == 'yum': repo = yum_repo elif repo_type == 'deb': repo = deb_repo else: # repository management tool was not recognized by Kimchi # skip test case return system_host_repos = len(inst.repositories_get_list()) repo_id = inst.repositories_create(repo) host_repos = inst.repositories_get_list() self.assertEquals(system_host_repos + 1, len(host_repos)) repo_info = inst.repository_lookup(repo_id) self.assertEquals(True, repo_info['enabled']) inst.repository_disable(repo_id) repo_info = inst.repository_lookup(repo_id) self.assertEquals(False, repo_info['enabled']) inst.repository_enable(repo_id) repo_info = inst.repository_lookup(repo_id) self.assertEquals(True, repo_info['enabled']) # remove files creates inst.repository_delete(repo_id) class BaseModelTests(unittest.TestCase): class FoosModel(object): def __init__(self): self.data = {} def create(self, params): self.data.update(params) def get_list(self): return list(self.data) class TestModel(kimchi.basemodel.BaseModel): def __init__(self): foo = BaseModelTests.FoosModel() super(BaseModelTests.TestModel, self).__init__([foo]) def test_root_model(self): t = BaseModelTests.TestModel() t.foos_create({'item1': 10}) self.assertEquals(t.foos_get_list(), ['item1']) kimchi-1.5.0/tests/test_model_network.py000066400000000000000000000122111254252253000204020ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # Project Kimchi # # Copyright IBM, Corp. 2015 # # 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 import json import os import unittest from functools import partial from kimchi.model.model import Model from kimchi.rollbackcontext import RollbackContext from utils import get_free_port, patch_auth, request, rollback_wrapper from utils import run_server model = None test_server = None host = None port = None ssl_port = None cherrypy_port = None def setUpModule(): global test_server, model, host, port, ssl_port, cherrypy_port patch_auth() model = Model(None, '/tmp/obj-store-test') host = '127.0.0.1' port = get_free_port('http') ssl_port = get_free_port('https') cherrypy_port = get_free_port('cherrypy_port') test_server = run_server(host, port, ssl_port, test_mode=True, cherrypy_port=cherrypy_port, model=model) def tearDownModule(): test_server.stop() os.unlink('/tmp/obj-store-test') def _do_network_test(self, model, params): with RollbackContext() as rollback: net_name = params['name'] uri = '/networks/%s' % net_name.encode('utf-8') # Create a network req = json.dumps(params) resp = self.request('/networks', req, 'POST') rollback.prependDefer(rollback_wrapper, model.network_delete, net_name) self.assertEquals(201, resp.status) # Verify the network resp = self.request(uri) network = json.loads(resp.read()) self.assertEquals('inactive', network['state']) self.assertTrue(network['persistent']) # activate the network resp = self.request(uri + '/activate', '{}', 'POST') rollback.prependDefer(rollback_wrapper, model.network_deactivate, net_name) self.assertEquals(200, resp.status) resp = self.request(uri) network = json.loads(resp.read()) self.assertEquals('active', network['state']) # Deactivate the network resp = self.request(uri + '/deactivate', '{}', 'POST') self.assertEquals(200, resp.status) resp = self.request(uri) network = json.loads(resp.read()) self.assertEquals('inactive', network['state']) # Delete the network resp = self.request(uri, '{}', 'DELETE') self.assertEquals(204, resp.status) class NetworkTests(unittest.TestCase): def setUp(self): self.request = partial(request, host, ssl_port) def test_get_networks(self): networks = json.loads(self.request('/networks').read()) self.assertIn('default', [net['name'] for net in networks]) with RollbackContext() as rollback: # Now add a couple of Networks to the mock model for i in xrange(5): name = 'network-%i' % i req = json.dumps({'name': name, 'connection': 'nat', 'subnet': '127.0.10%i.0/24' % i}) resp = self.request('/networks', req, 'POST') rollback.prependDefer(model.network_delete, name) self.assertEquals(201, resp.status) network = json.loads(resp.read()) self.assertEquals([], network["vms"]) nets = json.loads(self.request('/networks').read()) self.assertEquals(len(networks) + 5, len(nets)) network = json.loads(self.request('/networks/network-1').read()) keys = [u'name', u'connection', u'interface', u'subnet', u'dhcp', u'vms', u'in_use', u'autostart', u'state', u'persistent'] self.assertEquals(sorted(keys), sorted(network.keys())) def test_network_lifecycle(self): # Verify all the supported network type networks = [{'name': u'kīмÑhÄ«-пet', 'connection': 'isolated'}, {'name': u'nat-network', 'connection': 'nat'}, {'name': u'subnet-network', 'connection': 'nat', 'subnet': '127.0.100.0/24'}] # Verify the current system has at least one interface to create a # bridged network interfaces = json.loads(self.request('/interfaces?type=nic').read()) if len(interfaces) > 0: iface = interfaces[0]['name'] networks.append({'name': u'bridge-network', 'connection': 'bridge', 'interface': iface}) for net in networks: _do_network_test(self, model, net) kimchi-1.5.0/tests/test_model_storagepool.py000066400000000000000000000075471254252253000212670ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # Project Kimchi # # Copyright IBM, Corp. 2015 # # 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 import json import os import unittest from functools import partial from kimchi.model.model import Model from kimchi.rollbackcontext import RollbackContext from utils import get_free_port, patch_auth, request from utils import run_server model = None test_server = None host = None port = None ssl_port = None cherrypy_port = None def setUpModule(): global test_server, model, host, port, ssl_port, cherrypy_port patch_auth() model = Model(None, '/tmp/obj-store-test') host = '127.0.0.1' port = get_free_port('http') ssl_port = get_free_port('https') cherrypy_port = get_free_port('cherrypy_port') test_server = run_server(host, port, ssl_port, test_mode=True, cherrypy_port=cherrypy_port, model=model) def tearDownModule(): test_server.stop() os.unlink('/tmp/obj-store-test') class StoragepoolTests(unittest.TestCase): def setUp(self): self.request = partial(request, host, ssl_port) def test_get_storagepools(self): storagepools = json.loads(self.request('/storagepools').read()) self.assertIn('default', [pool['name'] for pool in storagepools]) with RollbackContext() as rollback: # Now add a couple of StoragePools to the mock model for i in xrange(3): name = u'kīмÑhÄ«-storagepool-%i' % i req = json.dumps({'name': name, 'type': 'dir', 'path': '/var/lib/libvirt/images/%i' % i}) resp = self.request('/storagepools', req, 'POST') rollback.prependDefer(model.storagepool_delete, name) self.assertEquals(201, resp.status) # Pool name must be unique req = json.dumps({'name': name, 'type': 'dir', 'path': '/var/lib/libvirt/images/%i' % i}) resp = self.request('/storagepools', req, 'POST') self.assertEquals(400, resp.status) # Verify pool information resp = self.request('/storagepools/%s' % name.encode("utf-8")) p = json.loads(resp.read()) keys = [u'name', u'state', u'capacity', u'allocated', u'available', u'path', u'source', u'type', u'nr_volumes', u'autostart', u'persistent'] self.assertEquals(sorted(keys), sorted(p.keys())) self.assertEquals(name, p['name']) self.assertEquals('inactive', p['state']) self.assertEquals(True, p['persistent']) self.assertEquals(True, p['autostart']) self.assertEquals(0, p['nr_volumes']) pools = json.loads(self.request('/storagepools').read()) self.assertEquals(len(storagepools) + 3, len(pools)) # Reserved pool return 400 req = json.dumps({'name': 'kimchi_isos', 'type': 'dir', 'path': '/var/lib/libvirt/images/%i' % i}) resp = request(host, ssl_port, '/storagepools', req, 'POST') self.assertEquals(400, resp.status) kimchi-1.5.0/tests/test_model_storagevolume.py000066400000000000000000000253361254252253000216210ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # Project Kimchi # # Copyright IBM, Corp. 2015 # # 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 import json import os import requests import unittest from functools import partial from kimchi.config import paths, READONLY_POOL_TYPE from kimchi.model.model import Model from kimchi.mockmodel import MockModel from kimchi.rollbackcontext import RollbackContext from utils import fake_auth_header, get_free_port, patch_auth, request from utils import rollback_wrapper, run_server, wait_task model = None test_server = None host = None port = None ssl_port = None cherrypy_port = None def setUpModule(): global test_server, model, host, port, ssl_port, cherrypy_port patch_auth() model = Model(None, '/tmp/obj-store-test') host = '127.0.0.1' port = get_free_port('http') ssl_port = get_free_port('https') cherrypy_port = get_free_port('cherrypy_port') test_server = run_server(host, port, ssl_port, test_mode=True, cherrypy_port=cherrypy_port, model=model) def tearDownModule(): test_server.stop() os.unlink('/tmp/obj-store-test') def _do_volume_test(self, model, host, ssl_port, pool_name): def _task_lookup(taskid): return json.loads(self.request('/tasks/%s' % taskid).read()) uri = '/storagepools/%s/storagevolumes' % pool_name.encode('utf-8') resp = self.request(uri) self.assertEquals(200, resp.status) resp = self.request('/storagepools/%s' % pool_name.encode('utf-8')) pool_info = json.loads(resp.read()) with RollbackContext() as rollback: # Create storage volume with 'capacity' vol = 'test-volume' vol_uri = uri + '/' + vol req = json.dumps({'name': vol, 'format': 'raw', 'capacity': 1073741824}) # 1 GiB resp = self.request(uri, req, 'POST') if pool_info['type'] in READONLY_POOL_TYPE: self.assertEquals(400, resp.status) else: rollback.prependDefer(rollback_wrapper, model.storagevolume_delete, pool_name, vol) self.assertEquals(202, resp.status) task_id = json.loads(resp.read())['id'] wait_task(_task_lookup, task_id) status = json.loads(self.request('/tasks/%s' % task_id).read()) self.assertEquals('finished', status['status']) vol_info = json.loads(self.request(vol_uri).read()) vol_info['name'] = vol vol_info['format'] = 'raw' vol_info['capacity'] = 1073741824 # Resize the storage volume: increase its capacity to 2 GiB req = json.dumps({'size': 2147483648}) # 2 GiB resp = self.request(vol_uri + '/resize', req, 'POST') self.assertEquals(200, resp.status) storagevolume = json.loads(self.request(vol_uri).read()) self.assertEquals(2147483648, storagevolume['capacity']) # Resize the storage volume: decrease its capacity to 512 MiB # FIXME: Due a libvirt bug it is not possible to decrease the # volume capacity # For reference: # - https://bugzilla.redhat.com/show_bug.cgi?id=1021802 req = json.dumps({'size': 536870912}) # 512 MiB resp = self.request(vol_uri + '/resize', req, 'POST') # It is only possible when using MockModel if isinstance(model, MockModel): self.assertEquals(200, resp.status) storagevolume = json.loads(self.request(vol_uri).read()) self.assertEquals(536870912, storagevolume['capacity']) else: self.assertEquals(500, resp.status) # Wipe the storage volume resp = self.request(vol_uri + '/wipe', '{}', 'POST') self.assertEquals(200, resp.status) storagevolume = json.loads(self.request(vol_uri).read()) self.assertEquals(0, storagevolume['allocation']) # Clone the storage volume vol_info = json.loads(self.request(vol_uri).read()) resp = self.request(vol_uri + '/clone', '{}', 'POST') self.assertEquals(202, resp.status) task = json.loads(resp.read()) cloned_vol_name = task['target_uri'].split('/')[-1] rollback.prependDefer(model.storagevolume_delete, pool_name, cloned_vol_name) wait_task(_task_lookup, task['id']) task = json.loads(self.request('/tasks/%s' % task['id']).read()) self.assertEquals('finished', task['status']) resp = self.request(uri + '/' + cloned_vol_name.encode('utf-8')) self.assertEquals(200, resp.status) cloned_vol = json.loads(resp.read()) self.assertNotEquals(vol_info['name'], cloned_vol['name']) self.assertNotEquals(vol_info['path'], cloned_vol['path']) for key in ['name', 'path', 'allocation']: del vol_info[key] del cloned_vol[key] self.assertEquals(vol_info, cloned_vol) # Delete the storage volume resp = self.request(vol_uri, '{}', 'DELETE') self.assertEquals(204, resp.status) resp = self.request(vol_uri) self.assertEquals(404, resp.status) # Storage volume upload # It is done through a sequence of POST and several PUT requests filename = 'COPYING.LGPL' filepath = os.path.join(paths.get_prefix(), filename) filesize = os.stat(filepath).st_size # Create storage volume for upload req = json.dumps({'name': filename, 'format': 'raw', 'capacity': filesize, 'upload': True}) resp = self.request(uri, req, 'POST') if pool_info['type'] in READONLY_POOL_TYPE: self.assertEquals(400, resp.status) else: rollback.prependDefer(rollback_wrapper, model.storagevolume_delete, pool_name, filename) self.assertEquals(202, resp.status) task_id = json.loads(resp.read())['id'] wait_task(_task_lookup, task_id) status = json.loads(self.request('/tasks/%s' % task_id).read()) self.assertEquals('ready for upload', status['message']) # Upload volume content url = 'https://%s:%s' % (host, ssl_port) + uri + '/' + filename # Create a file with 5M to upload # Max body size is set to 4M so the upload will fail with 413 newfile = '/tmp/5m-file' with open(newfile, 'wb') as fd: fd.seek(5*1024*1024-1) fd.write("\0") rollback.prependDefer(os.remove, newfile) with open(newfile, 'rb') as fd: with open(newfile + '.tmp', 'wb') as tmp_fd: data = fd.read() tmp_fd.write(data) with open(newfile + '.tmp', 'rb') as tmp_fd: r = requests.put(url, data={'chunk_size': len(data)}, files={'chunk': tmp_fd}, verify=False, headers=fake_auth_header()) self.assertEquals(r.status_code, 413) # Do upload index = 0 chunk_size = 2 * 1024 content = '' with open(filepath, 'rb') as fd: while True: with open(filepath + '.tmp', 'wb') as tmp_fd: fd.seek(index*chunk_size) data = fd.read(chunk_size) tmp_fd.write(data) with open(filepath + '.tmp', 'rb') as tmp_fd: r = requests.put(url, data={'chunk_size': len(data)}, files={'chunk': tmp_fd}, verify=False, headers=fake_auth_header()) self.assertEquals(r.status_code, 200) content += data index = index + 1 if len(data) < chunk_size: break rollback.prependDefer(os.remove, filepath + '.tmp') resp = self.request(uri + '/' + filename) self.assertEquals(200, resp.status) uploaded_path = json.loads(resp.read())['path'] with open(uploaded_path) as fd: uploaded_content = fd.read() self.assertEquals(content, uploaded_content) # Create storage volume with 'url' url = 'https://github.com/kimchi-project/kimchi/raw/master/COPYING' req = json.dumps({'url': url}) resp = self.request(uri, req, 'POST') if pool_info['type'] in READONLY_POOL_TYPE: self.assertEquals(400, resp.status) else: rollback.prependDefer(model.storagevolume_delete, pool_name, 'COPYING') self.assertEquals(202, resp.status) task = json.loads(resp.read()) wait_task(_task_lookup, task['id']) resp = self.request(uri + '/COPYING') self.assertEquals(200, resp.status) class StorageVolumeTests(unittest.TestCase): def setUp(self): self.request = partial(request, host, ssl_port) def test_get_storagevolume(self): uri = '/storagepools/default/storagevolumes' resp = self.request(uri) self.assertEquals(200, resp.status) keys = [u'name', u'type', u'capacity', u'allocation', u'path', u'used_by', u'format'] for vol in json.loads(resp.read()): resp = self.request(uri + '/' + vol['name']) self.assertEquals(200, resp.status) all_keys = keys[:] vol_info = json.loads(resp.read()) if vol_info['format'] == 'iso': all_keys.extend([u'os_distro', u'os_version', u'bootable']) self.assertEquals(sorted(all_keys), sorted(vol_info.keys())) def test_storagevolume_action(self): _do_volume_test(self, model, host, ssl_port, 'default') kimchi-1.5.0/tests/test_networkxml.py000066400000000000000000000150071254252253000177510ustar00rootroot00000000000000# # Kimchi # # Copyright IBM, Corp. 2013-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 import ipaddr import unittest import lxml.etree as ET import utils from kimchi.xmlutils import network as nxml from kimchi.xmlutils.utils import xpath_get_text class NetworkXmlTests(unittest.TestCase): def test_dhcp_xml(self): """ Test network dhcp xml """ dhcp_range = {"start": "192.168.122.100", "end": "192.168.122.254"} host1 = {"mac": "00:16:3e:77:e2:ed", "name": "foo.example.com", "ip": "192.168.122.10"} host2 = {"mac": "00:16:3e:3e:a9:1a", "name": "bar.example.com", "ip": "192.168.122.11"} params = {} dhcp = nxml._get_dhcp_elem(**params) self.assertEquals(None, dhcp) params["range"] = dhcp_range xml = ET.tostring(nxml._get_dhcp_elem(**params)) start = xpath_get_text(xml, "/dhcp/range/@start") end = xpath_get_text(xml, "/dhcp/range/@end") self.assertEquals(dhcp_range['start'], start[0]) self.assertEquals(dhcp_range['end'], end[0]) params["hosts"] = [host1, host2] xml = ET.tostring(nxml._get_dhcp_elem(**params)) ip = xpath_get_text(xml, "/dhcp/host/@ip") self.assertEquals(ip, [host1['ip'], host2['ip']]) def test_ip_xml(self): """ Test network ip xml """ dhcp_range = {"start": "192.168.122.100", "end": "192.168.122.254"} params = {} dhcp = nxml._get_dhcp_elem(**params) self.assertEquals(None, dhcp) params["net"] = "192.168.122.0/255.255.255.0" params["dhcp"] = {'range': dhcp_range} xml = ET.tostring(nxml._get_ip_elem(**params)) start = xpath_get_text(xml, "/ip/dhcp/range/@start")[0] end = xpath_get_text(xml, "/ip/dhcp/range/@end")[0] self.assertEquals(dhcp_range['start'], start) self.assertEquals(dhcp_range['end'], end) address = xpath_get_text(xml, "/ip/@address")[0] netmask = xpath_get_text(xml, "/ip/@netmask")[0] self.assertEquals(address, params["net"].split("/")[0]) self.assertEquals(netmask, params["net"].split("/")[1]) # test _get_ip_xml can accepts strings: '192.168.122.0/24', # which is same as "192.168.122.0/255.255.255.0" params["net"] = "192.168.122.0/24" xml = ET.tostring(nxml._get_ip_elem(**params)) netmask = xpath_get_text(xml, "/ip/@netmask")[0] self.assertEquals(netmask, str(ipaddr.IPNetwork(params["net"]).netmask)) def test_forward_xml(self): """ Test network forward xml """ params = {"mode": None} forward = nxml._get_forward_elem(**params) self.assertEquals(None, forward) params["mode"] = 'nat' params["dev"] = 'eth0' xml = ET.tostring(nxml._get_forward_elem(**params)) mode = xpath_get_text(xml, "/forward/@mode")[0] dev = xpath_get_text(xml, "/forward/@dev")[0] self.assertEquals(params['mode'], mode) self.assertEquals(params['dev'], dev) def test_network_xml(self): """ Test network xml """ params = {"name": "test", "forward": {"mode": "nat", "dev": ""}, "net": "192.168.0.0/255.255.255.0"} xml = nxml.to_network_xml(**params) name = xpath_get_text(xml, "/network/name")[0] self.assertEquals(name, params['name']) forward_mode = xpath_get_text(xml, "/network/forward/@mode")[0] self.assertEquals(forward_mode, params['forward']['mode']) forward_dev = xpath_get_text(xml, "/network/forward/@dev")[0] self.assertEquals(forward_dev, '') address = xpath_get_text(xml, "/network/ip/@address")[0] self.assertEquals(address, params["net"].split("/")[0]) netmask = xpath_get_text(xml, "/network/ip/@netmask")[0] self.assertEquals(netmask, params["net"].split("/")[1]) dhcp_start = xpath_get_text(xml, "/network/ip/dhcp/range/@start") self.assertEquals(dhcp_start, []) dhcp_end = xpath_get_text(xml, "/network/ip/dhcp/range/@end") self.assertEquals(dhcp_end, []) # test optional params params['forward']['dev'] = "eth0" params['dhcp'] = {"range": {'start': '192.168.0.1', 'end': '192.168.0.254'}} xml = nxml.to_network_xml(**params) forward_dev = xpath_get_text(xml, "/network/forward/@dev")[0] self.assertEquals(forward_dev, params['forward']['dev']) dhcp_start = xpath_get_text(xml, "/network/ip/dhcp/range/@start")[0] self.assertEquals(dhcp_start, params['dhcp']['range']['start']) dhcp_end = xpath_get_text(xml, "/network/ip/dhcp/range/@end")[0] self.assertEquals(dhcp_end, params['dhcp']['range']['end']) # test _get_ip_xml can accepts strings: '192.168.122.0/24', # which is same as "192.168.122.0/255.255.255.0" params["net"] = "192.168.0.0/24" xml = nxml.to_network_xml(**params) netmask = xpath_get_text(xml, "/network/ip/@netmask")[0] self.assertEquals(netmask, str(ipaddr.IPNetwork(params["net"]).netmask)) class InterfaceXmlTests(unittest.TestCase): def test_vlan_tagged_bridge_no_ip(self): expected_xml = """ """ actual_xml = nxml.create_vlan_tagged_bridge_xml('br10', 'em1', '10') self.assertEquals(actual_xml, utils.normalize_xml(expected_xml)) kimchi-1.5.0/tests/test_objectstore.py000066400000000000000000000055121254252253000200620ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # Project Kimchi # # Copyright IBM, Corp. 2015 # # 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 import os import tempfile import threading import unittest from kimchi.exception import NotFoundError from kimchi import objectstore tmpfile = None def setUpModule(): global tmpfile tmpfile = tempfile.mktemp() def tearDownModule(): os.unlink(tmpfile) class ObjectStoreTests(unittest.TestCase): def test_objectstore(self): store = objectstore.ObjectStore(tmpfile) with store as session: # Test create session.store('fÇ’Ç’', 'tÄ›st1', {'α': 1}) session.store('fÇ’Ç’', 'tÄ›st2', {'β': 2}) # Test list items = session.get_list('fÇ’Ç’') self.assertTrue(u'tÄ›st1' in items) self.assertTrue(u'tÄ›st2' in items) # Test get item = session.get('fÇ’Ç’', 'tÄ›st1') self.assertEquals(1, item[u'α']) # Test delete session.delete('fÇ’Ç’', 'tÄ›st2') self.assertEquals(1, len(session.get_list('fÇ’Ç’'))) # Test get non-existent item self.assertRaises(NotFoundError, session.get, 'α', 'β') # Test delete non-existent item self.assertRaises(NotFoundError, session.delete, 'fÇ’Ç’', 'tÄ›st2') # Test refresh existing item session.store('fÇ’Ç’', 'tÄ›st1', {'α': 2}) item = session.get('fÇ’Ç’', 'tÄ›st1') self.assertEquals(2, item[u'α']) def test_object_store_threaded(self): def worker(ident): with store as session: session.store('foo', ident, {}) store = objectstore.ObjectStore(tmpfile) threads = [] for i in xrange(50): t = threading.Thread(target=worker, args=(i,)) t.setDaemon(True) t.start() threads.append(t) for t in threads: t.join() with store as session: self.assertEquals(50, len(session.get_list('foo'))) self.assertEquals(10, len(store._connections.keys())) kimchi-1.5.0/tests/test_osinfo.py000066400000000000000000000060511254252253000170330ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-2015 # # 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 import unittest from kimchi.osinfo import _get_arch, get_template_default, lookup from kimchi.osinfo import modern_version_bases class OSInfoTests(unittest.TestCase): def test_default_lookup(self): entry = lookup(None, None) self.assertEquals('unknown', entry['os_distro']) self.assertEquals('unknown', entry['os_version']) self.assertEquals(['default'], entry['networks']) def test_old_distros(self): old_versions = {'debian': '5.0', 'ubuntu': '7.04', 'opensuse': '10.1', 'centos': '5.1', 'rhel': '5.1', 'fedora': '15'} for distro, version in old_versions.iteritems(): entry = lookup(distro, version) self.assertEquals(entry['disk_bus'], get_template_default('old', 'disk_bus')) self.assertEquals(entry['nic_model'], get_template_default('old', 'nic_model')) def test_modern_bases(self): for distro, version in modern_version_bases[_get_arch()].iteritems(): entry = lookup(distro, version) self.assertEquals(entry['disk_bus'], get_template_default('modern', 'disk_bus')) self.assertEquals(entry['nic_model'], get_template_default('modern', 'nic_model')) def test_modern_distros(self): # versions based on ppc64 modern distros modern_versions = {'ubuntu': '14.04', 'opensuse': '13.1', 'rhel': '6.5', 'fedora': '19', 'sles': '11sp3'} for distro, version in modern_versions.iteritems(): entry = lookup(distro, version) self.assertEquals(entry['disk_bus'], get_template_default('modern', 'disk_bus')) self.assertEquals(entry['nic_model'], get_template_default('modern', 'nic_model')) def test_lookup_unknown_distro_version_returns_old_distro(self): distro = 'unknown_distro' version = 'unknown_version' entry = lookup(distro, version) self.assertEquals(entry['disk_bus'], get_template_default('old', 'disk_bus')) self.assertEquals(entry['nic_model'], get_template_default('old', 'nic_model')) kimchi-1.5.0/tests/test_plugin.py000066400000000000000000000103011254252253000170250ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-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 import json import os import unittest from functools import partial import kimchi.mockmodel import kimchi.server from kimchi.utils import get_enabled_plugins import utils test_server = None model = None host = None port = None ssl_port = None def setUpModule(): global test_server, model, host, port, ssl_port utils.patch_auth() model = kimchi.mockmodel.MockModel('/tmp/obj-store-test') host = '127.0.0.1' port = utils.get_free_port('http') ssl_port = utils.get_free_port('https') test_server = utils.run_server(host, port, ssl_port, test_mode=True, model=model) def tearDownModule(): test_server.stop() os.unlink('/tmp/obj-store-test') @unittest.skipUnless( 'sample' in [plugin for plugin, _config in get_enabled_plugins()], 'sample plugin is not enabled, skip this test!') class PluginTests(unittest.TestCase): def setUp(self): self.request = partial(utils.request, host, ssl_port) def _create_rectangle(self, name, length, width): req = json.dumps({'name': name, 'length': length, 'width': width}) resp = self.request('/plugins/sample/rectangles', req, 'POST') return resp def _get_rectangle(self, name): resp = self.request('/plugins/sample/rectangles/%s' % name) return json.loads(resp.read()) def _create_rectangle_and_assert(self, name, length, width): resp = self._create_rectangle(name, length, width) self.assertEquals(201, resp.status) rectangle = self._get_rectangle(name) self.assertEquals(rectangle['name'], name) self.assertEquals(rectangle['length'], length) self.assertEquals(rectangle['width'], width) def _get_rectangles_list(self): resp = self.request('/plugins/sample/rectangles') rectangles = json.loads(resp.read()) name_list = [rectangle['name'] for rectangle in rectangles] return name_list def test_rectangles(self): # Create two new rectangles self._create_rectangle_and_assert('small', 10, 8) self._create_rectangle_and_assert('big', 20, 16) # Verify they're in the list name_list = self._get_rectangles_list() self.assertIn('small', name_list) self.assertIn('big', name_list) # Update the big rectangle. req = json.dumps({'length': 40, 'width': 30}) resp = self.request('/plugins/sample/rectangles/big', req, 'PUT') self.assertEquals(200, resp.status) big = self._get_rectangle('big') self.assertEquals(big['length'], 40) self.assertEquals(big['width'], 30) # Delete two rectangles resp = self.request('/plugins/sample/rectangles/big', '{}', 'DELETE') self.assertEquals(204, resp.status) resp = self.request('/plugins/sample/rectangles/small', '{}', 'DELETE') self.assertEquals(204, resp.status) name_list = self._get_rectangles_list() self.assertEquals([], name_list) def test_bad_params(self): # Bad name resp = self._create_rectangle(1.0, 30, 40) self.assertEquals(400, resp.status) # Bad length value resp = self._create_rectangle('test', -10.0, 40) self.assertEquals(400, resp.status) # Missing param for width req = json.dumps({'name': 'nowidth', 'length': 40}) resp = self.request('/plugins/sample/rectangles', req, 'POST') self.assertEquals(400, resp.status) kimchi-1.5.0/tests/test_rest.py000066400000000000000000001435361254252253000165250ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # Project Kimchi # # Copyright IBM, Corp. 2013-2015 # # 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 import json import os import re import time import unittest import urllib2 import urlparse from functools import partial import iso_gen import kimchi.mockmodel import kimchi.server from kimchi.osinfo import get_template_default from kimchi.rollbackcontext import RollbackContext from kimchi.utils import add_task from utils import get_free_port, patch_auth, request from utils import run_server, wait_task test_server = None model = None host = None port = None ssl_port = None cherrypy_port = None fake_iso = '/tmp/fake.iso' def setUpModule(): global test_server, model, host, port, ssl_port, cherrypy_port patch_auth() model = kimchi.mockmodel.MockModel('/tmp/obj-store-test') host = '127.0.0.1' port = get_free_port('http') ssl_port = get_free_port('https') cherrypy_port = get_free_port('cherrypy_port') test_server = run_server(host, port, ssl_port, test_mode=True, cherrypy_port=cherrypy_port, model=model) # Create fake ISO to do the tests iso_gen.construct_fake_iso(fake_iso, True, '12.04', 'ubuntu') iso_gen.construct_fake_iso("/var/lib/libvirt/images/fedora.iso", True, "17", "fedora") def tearDownModule(): test_server.stop() os.unlink('/tmp/obj-store-test') os.unlink(fake_iso) os.unlink("/var/lib/libvirt/images/fedora.iso") class RestTests(unittest.TestCase): def _async_op(self, cb, opaque): time.sleep(1) cb('success', True) def _except_op(self, cb, opaque): time.sleep(1) raise Exception("Oops, this is an exception handle test." " You can ignore it safely") cb('success', True) def _intermid_op(self, cb, opaque): time.sleep(1) cb('in progress') def setUp(self): self.request = partial(request, host, ssl_port) model.reset() def assertHTTPStatus(self, code, *args): resp = self.request(*args) self.assertEquals(code, resp.status) def test_get_vms(self): vms = json.loads(self.request('/vms').read()) # test_rest.py uses MockModel() which connects to libvirt URI # test:///default. By default this driver already has one VM created self.assertEquals(1, len(vms)) # Create a template as a base for our VMs req = json.dumps({'name': 'test', 'cdrom': fake_iso}) resp = self.request('/templates', req, 'POST') self.assertEquals(201, resp.status) test_users = ['root'] test_groups = ['wheel'] # Now add a couple of VMs to the mock model for i in xrange(10): name = 'vm-%i' % i req = json.dumps({'name': name, 'template': '/templates/test', 'users': test_users, 'groups': test_groups}) resp = self.request('/vms', req, 'POST') self.assertEquals(202, resp.status) task = json.loads(resp.read()) wait_task(self._task_lookup, task['id']) vms = json.loads(self.request('/vms').read()) self.assertEquals(11, len(vms)) vm = json.loads(self.request('/vms/vm-1').read()) self.assertEquals('vm-1', vm['name']) self.assertEquals('shutoff', vm['state']) self.assertEquals([], vm['users']) self.assertEquals([], vm['groups']) def test_edit_vm(self): req = json.dumps({'name': 'test', 'cdrom': fake_iso}) resp = self.request('/templates', req, 'POST') self.assertEquals(201, resp.status) req = json.dumps({'name': 'vm-1', 'template': '/templates/test'}) resp = self.request('/vms', req, 'POST') self.assertEquals(202, resp.status) task = json.loads(resp.read()) wait_task(self._task_lookup, task['id']) vm = json.loads(self.request('/vms/vm-1').read()) self.assertEquals('vm-1', vm['name']) resp = self.request('/vms/vm-1/start', '{}', 'POST') self.assertEquals(200, resp.status) req = json.dumps({'unsupported-attr': 'attr'}) resp = self.request('/vms/vm-1', req, 'PUT') self.assertEquals(400, resp.status) req = json.dumps({'name': 'new-vm'}) resp = self.request('/vms/vm-1', req, 'PUT') self.assertEquals(400, resp.status) req = json.dumps({'cpus': 3}) resp = self.request('/vms/vm-1', req, 'PUT') self.assertEquals(200, resp.status) # Check if there is support to memory hotplug, once vm is running resp = self.request('/config/capabilities').read() conf = json.loads(resp) req = json.dumps({'memory': 2048}) resp = self.request('/vms/vm-1', req, 'PUT') if conf['mem_hotplug_support']: self.assertEquals(200, resp.status) else: self.assertEquals(400, resp.status) req = json.dumps({"graphics": {'passwd': "abcdef"}}) resp = self.request('/vms/vm-1', req, 'PUT') info = json.loads(resp.read()) self.assertEquals('abcdef', info["graphics"]["passwd"]) self.assertEquals(None, info["graphics"]["passwdValidTo"]) resp = self.request('/vms/vm-1/poweroff', '{}', 'POST') self.assertEquals(200, resp.status) req = json.dumps({"graphics": {'passwd': "123456", 'passwdValidTo': 20}}) resp = self.request('/vms/vm-1', req, 'PUT') info = json.loads(resp.read()) self.assertEquals('123456', info["graphics"]["passwd"]) self.assertGreaterEqual(20, info["graphics"]["passwdValidTo"]) req = json.dumps({'name': 12}) resp = self.request('/vms/vm-1', req, 'PUT') self.assertEquals(400, resp.status) req = json.dumps({'name': ''}) resp = self.request('/vms/vm-1', req, 'PUT') self.assertEquals(400, resp.status) req = json.dumps({'cpus': -2}) resp = self.request('/vms/vm-1', req, 'PUT') self.assertEquals(400, resp.status) req = json.dumps({'cpus': 'four'}) resp = self.request('/vms/vm-1', req, 'PUT') self.assertEquals(400, resp.status) req = json.dumps({'memory': 100}) resp = self.request('/vms/vm-1', req, 'PUT') self.assertEquals(400, resp.status) req = json.dumps({'memory': 'ten gigas'}) resp = self.request('/vms/vm-1', req, 'PUT') self.assertEquals(400, resp.status) req = json.dumps({'name': 'new-name', 'cpus': 5, 'UUID': 'notallowed'}) resp = self.request('/vms/vm-1', req, 'PUT') self.assertEquals(400, resp.status) params = {'name': u'∨м-црdαtеd', 'cpus': 5, 'memory': 3072} req = json.dumps(params) resp = self.request('/vms/vm-1', req, 'PUT') self.assertEquals(303, resp.status) vm = json.loads(self.request('/vms/∨м-црdαtеd', req).read()) for key in params.keys(): self.assertEquals(params[key], vm[key]) # change only VM users - groups are not changed (default is empty) resp = self.request('/users', '{}', 'GET') users = json.loads(resp.read()) req = json.dumps({'users': users}) resp = self.request('/vms/∨м-црdαtеd', req, 'PUT') self.assertEquals(200, resp.status) info = json.loads(self.request('/vms/∨м-црdαtеd', '{}').read()) self.assertEquals(users, info['users']) # change only VM groups - users are not changed (default is empty) resp = self.request('/groups', '{}', 'GET') groups = json.loads(resp.read()) req = json.dumps({'groups': groups}) resp = self.request('/vms/∨м-црdαtеd', req, 'PUT') self.assertEquals(200, resp.status) info = json.loads(self.request('/vms/∨м-црdαtеd', '{}').read()) self.assertEquals(groups, info['groups']) # change VM users (wrong value) and groups # when an error occurs, everything fails and nothing is changed req = json.dumps({'users': ['userdoesnotexist'], 'groups': []}) resp = self.request('/vms/∨м-црdαtеd', req, 'PUT') self.assertEquals(400, resp.status) # change VM users and groups (wrong value) # when an error occurs, everything fails and nothing is changed req = json.dumps({'users': [], 'groups': ['groupdoesnotexist']}) resp = self.request('/vms/∨м-црdαtеd', req, 'PUT') self.assertEquals(400, resp.status) def test_vm_lifecycle(self): # Create a Template req = json.dumps({'name': 'test', 'disks': [{'size': 1}], 'icon': 'images/icon-debian.png', 'cdrom': fake_iso}) resp = self.request('/templates', req, 'POST') self.assertEquals(201, resp.status) # Create a VM req = json.dumps({'name': 'test-vm', 'template': '/templates/test'}) resp = self.request('/vms', req, 'POST') task = json.loads(resp.read()) wait_task(self._task_lookup, task['id']) self.assertEquals(202, resp.status) # Verify the VM vm = json.loads(self.request('/vms/test-vm').read()) self.assertEquals('shutoff', vm['state']) self.assertEquals('images/icon-debian.png', vm['icon']) # Verify the volume was created vol_uri = '/storagepools/default-pool/storagevolumes/%s-0.img' resp = self.request(vol_uri % vm['uuid']) vol = json.loads(resp.read()) self.assertEquals(1 << 30, vol['capacity']) self.assertEquals(['test-vm'], vol['used_by']) # Start the VM resp = self.request('/vms/test-vm/start', '{}', 'POST') vm = json.loads(self.request('/vms/test-vm').read()) self.assertEquals('running', vm['state']) # Test screenshot resp = self.request(vm['screenshot'], method='HEAD') self.assertEquals(200, resp.status) self.assertTrue(resp.getheader('Content-type').startswith('image')) # Clone a running VM resp = self.request('/vms/test-vm/clone', '{}', 'POST') self.assertEquals(400, resp.status) # Force poweroff the VM resp = self.request('/vms/test-vm/poweroff', '{}', 'POST') vm = json.loads(self.request('/vms/test-vm').read()) self.assertEquals('shutoff', vm['state']) # Test create VM with same name fails with 400 req = json.dumps({'name': 'test-vm', 'template': '/templates/test'}) resp = self.request('/vms', req, 'POST') self.assertEquals(400, resp.status) # Clone a VM resp = self.request('/vms/test-vm/clone', '{}', 'POST') self.assertEquals(202, resp.status) task = json.loads(resp.read()) wait_task(self._task_lookup, task['id']) task = json.loads(self.request('/tasks/%s' % task['id'], '{}').read()) self.assertEquals('finished', task['status']) clone_vm_name = task['target_uri'].split('/')[-2] self.assertTrue(re.match(u'test-vm-clone-\d+', clone_vm_name)) resp = self.request('/vms/test-vm', '{}') original_vm_info = json.loads(resp.read()) resp = self.request('/vms/%s' % clone_vm_name, '{}') self.assertEquals(200, resp.status) clone_vm_info = json.loads(resp.read()) self.assertNotEqual(original_vm_info['name'], clone_vm_info['name']) del original_vm_info['name'] del clone_vm_info['name'] self.assertNotEqual(original_vm_info['uuid'], clone_vm_info['uuid']) del original_vm_info['uuid'] del clone_vm_info['uuid'] self.assertEquals(original_vm_info, clone_vm_info) # Create a snapshot on a stopped VM params = {'name': 'test-snap'} resp = self.request('/vms/test-vm/snapshots', json.dumps(params), 'POST') self.assertEquals(202, resp.status) task = json.loads(resp.read()) wait_task(self._task_lookup, task['id']) task = json.loads(self.request('/tasks/%s' % task['id']).read()) self.assertEquals('finished', task['status']) # Look up a non-existing snapshot resp = self.request('/vms/test-vm/snapshots/snap404', '{}', 'GET') self.assertEquals(404, resp.status) # Look up a snapshot resp = self.request('/vms/test-vm/snapshots/%s' % params['name'], '{}', 'GET') self.assertEquals(200, resp.status) snap = json.loads(resp.read()) self.assertTrue(int(time.time()) >= int(snap['created'])) self.assertEquals(params['name'], snap['name']) self.assertEquals(u'', snap['parent']) self.assertEquals(u'shutoff', snap['state']) resp = self.request('/vms/test-vm/snapshots', '{}', 'GET') self.assertEquals(200, resp.status) snaps = json.loads(resp.read()) self.assertEquals(1, len(snaps)) # Look up current snapshot (the one created above) resp = self.request('/vms/test-vm/snapshots/current', '{}', 'GET') self.assertEquals(200, resp.status) snap = json.loads(resp.read()) self.assertEquals(params['name'], snap['name']) resp = self.request('/vms/test-vm/snapshots', '{}', 'POST') self.assertEquals(202, resp.status) task = json.loads(resp.read()) snap_name = task['target_uri'].split('/')[-1] wait_task(self._task_lookup, task['id']) resp = self.request('/tasks/%s' % task['id'], '{}', 'GET') task = json.loads(resp.read()) self.assertEquals('finished', task['status']) resp = self.request('/vms/test-vm/snapshots', '{}', 'GET') self.assertEquals(200, resp.status) snaps = json.loads(resp.read()) self.assertEquals(2, len(snaps)) # Look up current snapshot (the one created above) resp = self.request('/vms/test-vm/snapshots/current', '{}', 'GET') self.assertEquals(200, resp.status) snap = json.loads(resp.read()) self.assertEquals(snap_name, snap['name']) # Revert to snapshot resp = self.request('/vms/test-vm/snapshots/%s/revert' % params['name'], '{}', 'POST') self.assertEquals(200, resp.status) snap = json.loads(resp.read()) resp = self.request('/vms/test-vm', '{}', 'GET') self.assertEquals(200, resp.status) vm = json.loads(resp.read()) self.assertEquals(vm['state'], snap['state']) resp = self.request('/vms/test-vm/snapshots/current', '{}', 'GET') self.assertEquals(200, resp.status) current_snap = json.loads(resp.read()) self.assertEquals(snap, current_snap) # Delete a snapshot resp = self.request('/vms/test-vm/snapshots/%s' % params['name'], '{}', 'DELETE') self.assertEquals(204, resp.status) # Suspend the VM resp = self.request('/vms/test-vm', '{}', 'GET') self.assertEquals(200, resp.status) vm = json.loads(resp.read()) self.assertEquals(vm['state'], 'shutoff') resp = self.request('/vms/test-vm/suspend', '{}', 'POST') self.assertEquals(400, resp.status) resp = self.request('/vms/test-vm/start', '{}', 'POST') self.assertEquals(200, resp.status) resp = self.request('/vms/test-vm', '{}', 'GET') self.assertEquals(200, resp.status) vm = json.loads(resp.read()) self.assertEquals(vm['state'], 'running') resp = self.request('/vms/test-vm/suspend', '{}', 'POST') self.assertEquals(200, resp.status) resp = self.request('/vms/test-vm', '{}', 'GET') self.assertEquals(200, resp.status) vm = json.loads(resp.read()) self.assertEquals(vm['state'], 'paused') # Resume the VM resp = self.request('/vms/test-vm/resume', '{}', 'POST') self.assertEquals(200, resp.status) resp = self.request('/vms/test-vm', '{}', 'GET') self.assertEquals(200, resp.status) vm = json.loads(resp.read()) self.assertEquals(vm['state'], 'running') # Delete the VM resp = self.request('/vms/test-vm', '{}', 'DELETE') self.assertEquals(204, resp.status) # Delete the Template resp = self.request('/templates/test', '{}', 'DELETE') self.assertEquals(204, resp.status) # Verify the volume was deleted self.assertHTTPStatus(404, vol_uri % vm['uuid']) def test_vm_graphics(self): # Create a Template req = json.dumps({'name': 'test', 'cdrom': fake_iso}) resp = self.request('/templates', req, 'POST') self.assertEquals(201, resp.status) # Create a VM with default args req = json.dumps({'name': 'test-vm', 'template': '/templates/test'}) resp = self.request('/vms', req, 'POST') self.assertEquals(202, resp.status) task = json.loads(resp.read()) wait_task(self._task_lookup, task['id']) # Verify the VM vm = json.loads(self.request('/vms/test-vm').read()) self.assertEquals('127.0.0.1', vm['graphics']['listen']) self.assertEquals('vnc', vm['graphics']['type']) # Delete the VM resp = self.request('/vms/test-vm', '{}', 'DELETE') self.assertEquals(204, resp.status) # Create a VM with specified graphics type and listen graphics = {'type': 'vnc', 'listen': '127.0.0.1'} req = json.dumps({'name': 'test-vm', 'template': '/templates/test', 'graphics': graphics}) resp = self.request('/vms', req, 'POST') self.assertEquals(202, resp.status) task = json.loads(resp.read()) wait_task(self._task_lookup, task['id']) # Verify the VM vm = json.loads(self.request('/vms/test-vm').read()) self.assertEquals('127.0.0.1', vm['graphics']['listen']) self.assertEquals('vnc', vm['graphics']['type']) # Delete the VM resp = self.request('/vms/test-vm', '{}', 'DELETE') self.assertEquals(204, resp.status) # Create a VM with listen as ipv6 address graphics = {'type': 'spice', 'listen': 'fe00::0'} req = json.dumps({'name': 'test-vm', 'template': '/templates/test', 'graphics': graphics}) resp = self.request('/vms', req, 'POST') self.assertEquals(202, resp.status) task = json.loads(resp.read()) wait_task(self._task_lookup, task['id']) # Verify the VM vm = json.loads(self.request('/vms/test-vm').read()) self.assertEquals('fe00::0', vm['graphics']['listen']) self.assertEquals('spice', vm['graphics']['type']) # Delete the VM resp = self.request('/vms/test-vm', '{}', 'DELETE') self.assertEquals(204, resp.status) # Create a VM with specified graphics type and default listen graphics = {'type': 'spice'} req = json.dumps({'name': 'test-vm', 'template': '/templates/test', 'graphics': graphics}) resp = self.request('/vms', req, 'POST') self.assertEquals(202, resp.status) task = json.loads(resp.read()) wait_task(self._task_lookup, task['id']) # Verify the VM vm = json.loads(self.request('/vms/test-vm').read()) self.assertEquals('127.0.0.1', vm['graphics']['listen']) self.assertEquals('spice', vm['graphics']['type']) # Delete the VM resp = self.request('/vms/test-vm', '{}', 'DELETE') self.assertEquals(204, resp.status) # Try to create a VM with invalid graphics type graphics = {'type': 'invalid'} req = json.dumps({'name': 'test-vm', 'template': '/templates/test', 'graphics': graphics}) resp = self.request('/vms', req, 'POST') self.assertEquals(400, resp.status) # Try to create a VM with invalid graphics listen graphics = {'type': 'spice', 'listen': 'invalid'} req = json.dumps({'name': 'test-vm', 'template': '/templates/test', 'graphics': graphics}) resp = self.request('/vms', req, 'POST') self.assertEquals(400, resp.status) # Delete the Template resp = self.request('/templates/test', '{}', 'DELETE') self.assertEquals(204, resp.status) def test_vm_storage_devices(self): with RollbackContext() as rollback: # Create a template as a base for our VMs req = json.dumps({'name': 'test', 'cdrom': fake_iso}) resp = self.request('/templates', req, 'POST') self.assertEquals(201, resp.status) # Delete the template rollback.prependDefer(self.request, '/templates/test', '{}', 'DELETE') # Create a VM with default args req = json.dumps({'name': 'test-vm', 'template': '/templates/test'}) resp = self.request('/vms', req, 'POST') self.assertEquals(202, resp.status) task = json.loads(resp.read()) wait_task(self._task_lookup, task['id']) # Delete the VM rollback.prependDefer(self.request, '/vms/test-vm', '{}', 'DELETE') # Check storage devices resp = self.request('/vms/test-vm/storages', '{}', 'GET') devices = json.loads(resp.read()) self.assertEquals(2, len(devices)) dev_types = [] for d in devices: self.assertIn(u'type', d.keys()) self.assertIn(u'dev', d.keys()) self.assertIn(u'path', d.keys()) dev_types.append(d['type']) self.assertEquals(['cdrom', 'disk'], sorted(dev_types)) # Attach cdrom with nonexistent iso req = json.dumps({'dev': 'hdx', 'type': 'cdrom', 'path': '/tmp/nonexistent.iso'}) resp = self.request('/vms/test-vm/storages', req, 'POST') self.assertEquals(400, resp.status) # Create temp storage pool req = json.dumps({'name': 'tmp', 'capacity': 1024, 'allocated': 512, 'path': '/tmp', 'type': 'dir'}) resp = self.request('/storagepools', req, 'POST') self.assertEquals(201, resp.status) resp = self.request('/storagepools/tmp/activate', req, 'POST') self.assertEquals(200, resp.status) # 'name' is required for this type of volume req = json.dumps({'capacity': 1024, 'allocation': 512, 'type': 'disk', 'format': 'raw'}) resp = self.request('/storagepools/tmp/storagevolumes', req, 'POST') self.assertEquals(400, resp.status) req = json.dumps({'name': "attach-volume", 'capacity': 1024, 'allocation': 512, 'type': 'disk', 'format': 'raw'}) resp = self.request('/storagepools/tmp/storagevolumes', req, 'POST') self.assertEquals(202, resp.status) time.sleep(1) # Attach cdrom with both path and volume specified open('/tmp/existent.iso', 'w').close() req = json.dumps({'dev': 'hdx', 'type': 'cdrom', 'pool': 'tmp', 'vol': 'attach-volume', 'path': '/tmp/existent.iso'}) resp = self.request('/vms/test-vm/storages', req, 'POST') self.assertEquals(400, resp.status) # Attach disk with both path and volume specified req = json.dumps({'dev': 'hdx', 'type': 'disk', 'pool': 'tmp', 'vol': 'attach-volume', 'path': '/tmp/existent.iso'}) resp = self.request('/vms/test-vm/storages', req, 'POST') self.assertEquals(400, resp.status) # Attach disk with only pool specified req = json.dumps({'dev': 'hdx', 'type': 'cdrom', 'pool': 'tmp'}) resp = self.request('/vms/test-vm/storages', req, 'POST') self.assertEquals(400, resp.status) # Attach disk with pool and vol specified req = json.dumps({'type': 'disk', 'pool': 'tmp', 'vol': 'attach-volume'}) resp = self.request('/vms/test-vm/storages', req, 'POST') self.assertEquals(201, resp.status) cd_info = json.loads(resp.read()) self.assertEquals('disk', cd_info['type']) # Attach a cdrom with existent dev name req = json.dumps({'type': 'cdrom', 'path': '/tmp/existent.iso'}) resp = self.request('/vms/test-vm/storages', req, 'POST') self.assertEquals(201, resp.status) cd_info = json.loads(resp.read()) cd_dev = cd_info['dev'] self.assertEquals('cdrom', cd_info['type']) self.assertEquals('/tmp/existent.iso', cd_info['path']) # Delete the file and cdrom rollback.prependDefer(self.request, '/vms/test-vm/storages/hdx', '{}', 'DELETE') os.remove('/tmp/existent.iso') # Change path of storage cdrom cdrom = u'http://fedora.mirrors.tds.net/pub/fedora/releases/20/'\ 'Live/x86_64/Fedora-Live-Desktop-x86_64-20-1.iso' req = json.dumps({'path': cdrom}) resp = self.request('/vms/test-vm/storages/' + cd_dev, req, 'PUT') self.assertEquals(200, resp.status) cd_info = json.loads(resp.read()) self.assertEquals(urlparse.urlparse(cdrom).path, urlparse.urlparse(cd_info['path']).path) # Test GET devs = json.loads(self.request('/vms/test-vm/storages').read()) self.assertEquals(4, len(devs)) # Detach storage cdrom resp = self.request('/vms/test-vm/storages/' + cd_dev, '{}', 'DELETE') self.assertEquals(204, resp.status) # Test GET devs = json.loads(self.request('/vms/test-vm/storages').read()) self.assertEquals(3, len(devs)) resp = self.request('/storagepools/tmp/deactivate', {}, 'POST') self.assertEquals(200, resp.status) resp = self.request('/storagepools/tmp', {}, 'DELETE') self.assertEquals(204, resp.status) def test_vm_iface(self): with RollbackContext() as rollback: # Create a template as a base for our VMs req = json.dumps({'name': 'test', 'cdrom': fake_iso}) resp = self.request('/templates', req, 'POST') self.assertEquals(201, resp.status) # Delete the template rollback.prependDefer(self.request, '/templates/test', '{}', 'DELETE') # Create a VM with default args req = json.dumps({'name': 'test-vm', 'template': '/templates/test'}) resp = self.request('/vms', req, 'POST') self.assertEquals(202, resp.status) task = json.loads(resp.read()) wait_task(self._task_lookup, task['id']) # Delete the VM rollback.prependDefer(self.request, '/vms/test-vm', '{}', 'DELETE') # Create a network req = json.dumps({'name': 'test-network', 'connection': 'nat', 'net': '127.0.1.0/24'}) resp = self.request('/networks', req, 'POST') self.assertEquals(201, resp.status) # Delete the network rollback.prependDefer(self.request, '/networks/test-network', '{}', 'DELETE') ifaces = json.loads(self.request('/vms/test-vm/ifaces').read()) self.assertEquals(1, len(ifaces)) for iface in ifaces: res = json.loads(self.request('/vms/test-vm/ifaces/%s' % iface['mac']).read()) self.assertEquals('default', res['network']) self.assertEquals(17, len(res['mac'])) self.assertEquals(get_template_default('old', 'nic_model'), res['model']) # try to attach an interface without specifying 'model' req = json.dumps({'type': 'network'}) resp = self.request('/vms/test-vm/ifaces', req, 'POST') self.assertEquals(400, resp.status) # attach network interface to vm req = json.dumps({"type": "network", "network": "test-network", "model": "virtio"}) resp = self.request('/vms/test-vm/ifaces', req, 'POST') self.assertEquals(201, resp.status) iface = json.loads(resp.read()) self.assertEquals('test-network', iface['network']) self.assertEquals(17, len(iface['mac'])) self.assertEquals('virtio', iface['model']) self.assertEquals('network', iface['type']) # update vm interface newMacAddr = '54:50:e3:44:8a:af' req = json.dumps({"network": "default", "model": "virtio", "type": "network", "mac": newMacAddr}) resp = self.request('/vms/test-vm/ifaces/%s' % iface['mac'], req, 'PUT') self.assertEquals(303, resp.status) iface = json.loads(self.request('/vms/test-vm/ifaces/%s' % newMacAddr).read()) self.assertEquals(newMacAddr, iface['mac']) # detach network interface from vm resp = self.request('/vms/test-vm/ifaces/%s' % iface['mac'], '{}', 'DELETE') self.assertEquals(204, resp.status) def test_vm_customise_storage(self): # Create a Template req = json.dumps({'name': 'test', 'cdrom': fake_iso, 'disks': [{'size': 1}]}) resp = self.request('/templates', req, 'POST') self.assertEquals(201, resp.status) # Create alternate storage req = json.dumps({'name': 'alt', 'capacity': 1024, 'allocated': 512, 'path': '/tmp', 'type': 'dir'}) resp = self.request('/storagepools', req, 'POST') self.assertEquals(201, resp.status) resp = self.request('/storagepools/alt/activate', req, 'POST') self.assertEquals(200, resp.status) # Create a VM req = json.dumps({'name': 'test-vm', 'template': '/templates/test', 'storagepool': '/storagepools/alt'}) resp = self.request('/vms', req, 'POST') self.assertEquals(202, resp.status) task = json.loads(resp.read()) wait_task(self._task_lookup, task['id']) resp = self.request('/vms/test-vm', {}, 'GET') vm_info = json.loads(resp.read()) # Test template not changed after vm customise its pool t = json.loads(self.request('/templates/test').read()) self.assertEquals(t['storagepool'], '/storagepools/default-pool') # Verify the volume was created vol_uri = '/storagepools/alt/storagevolumes/%s-0.img' % vm_info['uuid'] resp = self.request(vol_uri) vol = json.loads(resp.read()) self.assertEquals(1 << 30, vol['capacity']) # Delete the VM resp = self.request('/vms/test-vm', '{}', 'DELETE') self.assertEquals(204, resp.status) # Verify the volume was deleted self.assertHTTPStatus(404, vol_uri) def test_scsi_fc_storage(self): # Create scsi fc pool req = json.dumps({'name': 'scsi_fc_pool', 'type': 'scsi', 'source': {'adapter_name': 'scsi_host2'}}) resp = self.request('/storagepools', req, 'POST') self.assertEquals(201, resp.status) # Test create vms using lun of this pool # activate the storage pool resp = self.request('/storagepools/scsi_fc_pool/activate', '{}', 'POST') # Create template fails because SCSI volume is missing tmpl_params = {'name': 'test_fc_pool', 'cdrom': fake_iso, 'storagepool': '/storagepools/scsi_fc_pool'} req = json.dumps(tmpl_params) resp = self.request('/templates', req, 'POST') self.assertEquals(400, resp.status) # Choose SCSI volume to create template resp = self.request('/storagepools/scsi_fc_pool/storagevolumes') lun_name = json.loads(resp.read())[0]['name'] tmpl_params['disks'] = [{'index': 0, 'volume': lun_name}] req = json.dumps(tmpl_params) resp = self.request('/templates', req, 'POST') self.assertEquals(201, resp.status) # Create vm in scsi pool req = json.dumps({'name': 'test-vm', 'template': '/templates/test_fc_pool'}) resp = self.request('/vms', req, 'POST') self.assertEquals(202, resp.status) task = json.loads(resp.read()) wait_task(self._task_lookup, task['id']) # Start the VM resp = self.request('/vms/test-vm/start', '{}', 'POST') vm = json.loads(self.request('/vms/test-vm').read()) self.assertEquals('running', vm['state']) # Force poweroff the VM resp = self.request('/vms/test-vm/poweroff', '{}', 'POST') vm = json.loads(self.request('/vms/test-vm').read()) self.assertEquals('shutoff', vm['state']) # Delete the VM resp = self.request('/vms/test-vm', '{}', 'DELETE') self.assertEquals(204, resp.status) def test_unnamed_vms(self): # Create a Template req = json.dumps({'name': 'test', 'cdrom': fake_iso}) resp = self.request('/templates', req, 'POST') self.assertEquals(201, resp.status) # Create 5 unnamed vms from this template for i in xrange(1, 6): req = json.dumps({'template': '/templates/test'}) task = json.loads(self.request('/vms', req, 'POST').read()) wait_task(self._task_lookup, task['id']) resp = self.request('/vms/test-vm-%i' % i, {}, 'GET') self.assertEquals(resp.status, 200) count = len(json.loads(self.request('/vms').read())) self.assertEquals(6, count) def test_create_vm_without_template(self): req = json.dumps({'name': 'vm-without-template'}) resp = self.request('/vms', req, 'POST') self.assertEquals(400, resp.status) resp = json.loads(resp.read()) self.assertIn(u"KCHVM0016E:", resp['reason']) def test_create_vm_with_bad_template_uri(self): req = json.dumps({'name': 'vm-bad-template', 'template': '/mytemplate'}) resp = self.request('/vms', req, 'POST') self.assertEquals(400, resp.status) resp = json.loads(resp.read()) self.assertIn(u"KCHVM0012E", resp['reason']) def test_create_vm_with_img_based_template(self): resp = json.loads( self.request('/storagepools/default-pool/storagevolumes').read()) self.assertEquals(0, len(resp)) # Create a Template mock_base = '/tmp/mock.img' open(mock_base, 'w').close() req = json.dumps({'name': 'test', 'disks': [{'base': mock_base}]}) resp = self.request('/templates', req, 'POST') self.assertEquals(201, resp.status) req = json.dumps({'template': '/templates/test'}) resp = self.request('/vms', req, 'POST') self.assertEquals(202, resp.status) task = json.loads(resp.read()) wait_task(self._task_lookup, task['id']) # Test storage volume created with backing store of base file resp = json.loads( self.request('/storagepools/default-pool/storagevolumes').read()) self.assertEquals(1, len(resp)) def _create_pool(self, name): req = json.dumps({'name': name, 'capacity': 10240, 'allocated': 5120, 'path': '/var/lib/libvirt/images/', 'type': 'dir'}) resp = self.request('/storagepools', req, 'POST') self.assertEquals(201, resp.status) # Verify the storage pool storagepool = json.loads(self.request('/storagepools/%s' % name).read()) self.assertEquals('inactive', storagepool['state']) return name def _delete_pool(self, name): # Delete the storage pool resp = self.request('/storagepools/%s' % name, '{}', 'DELETE') self.assertEquals(204, resp.status) def test_iso_scan_shallow(self): # fake environment preparation self._create_pool('pool-3') self.request('/storagepools/pool-3/activate', '{}', 'POST') params = {'name': 'fedora.iso', 'capacity': 1073741824, # 1 GiB 'type': 'file', 'format': 'iso'} task_info = model.storagevolumes_create('pool-3', params) wait_task(self._task_lookup, task_info['id']) storagevolume = json.loads(self.request( '/storagepools/kimchi_isos/storagevolumes/').read())[0] self.assertEquals('fedora.iso', storagevolume['name']) self.assertEquals('iso', storagevolume['format']) self.assertEquals('/var/lib/libvirt/images/fedora.iso', storagevolume['path']) self.assertEquals(1073741824, storagevolume['capacity']) # 1 GiB self.assertEquals(0, storagevolume['allocation']) self.assertEquals('17', storagevolume['os_version']) self.assertEquals('fedora', storagevolume['os_distro']) self.assertEquals(True, storagevolume['bootable']) # Create a template # In real model os distro/version can be omitted # as we will scan the iso req = json.dumps({'name': 'test', 'cdrom': storagevolume['path'], 'os_distro': storagevolume['os_distro'], 'os_version': storagevolume['os_version']}) resp = self.request('/templates', req, 'POST') self.assertEquals(201, resp.status) # Verify the template t = json.loads(self.request('/templates/test').read()) self.assertEquals('test', t['name']) self.assertEquals('fedora', t['os_distro']) self.assertEquals('17', t['os_version']) self.assertEquals(get_template_default('old', 'memory'), t['memory']) # Deactivate or destroy scan pool return 405 resp = self.request('/storagepools/kimchi_isos/storagevolumes' '/deactivate', '{}', 'POST') self.assertEquals(405, resp.status) resp = self.request('/storagepools/kimchi_isos/storagevolumes', '{}', 'DELETE') self.assertEquals(405, resp.status) # Delete the template resp = self.request('/templates/%s' % t['name'], '{}', 'DELETE') self.assertEquals(204, resp.status) resp = self.request('/storagepools/pool-3/deactivate', '{}', 'POST') self.assertEquals(200, resp.status) self._delete_pool('pool-3') def test_screenshot_refresh(self): # Create a VM req = json.dumps({'name': 'test', 'cdrom': fake_iso}) resp = self.request('/templates', req, 'POST') req = json.dumps({'name': 'test-vm', 'template': '/templates/test'}) resp = self.request('/vms', req, 'POST') task = json.loads(resp.read()) wait_task(self._task_lookup, task['id']) # Test screenshot for shut-off state vm resp = self.request('/vms/test-vm/screenshot') self.assertEquals(404, resp.status) # Test screenshot for running vm resp = self.request('/vms/test-vm/start', '{}', 'POST') vm = json.loads(self.request('/vms/test-vm').read()) resp = self.request(vm['screenshot'], method='HEAD') self.assertEquals(200, resp.status) self.assertTrue(resp.getheader('Content-type').startswith('image')) # Test screenshot sub-resource redirect resp = self.request('/vms/test-vm/screenshot') self.assertEquals(200, resp.status) self.assertEquals('image/png', resp.getheader('content-type')) lastMod1 = resp.getheader('last-modified') # Take another screenshot instantly and compare the last Modified date resp = self.request('/vms/test-vm/screenshot') lastMod2 = resp.getheader('last-modified') self.assertEquals(lastMod2, lastMod1) resp = self.request('/vms/test-vm/screenshot', '{}', 'DELETE') self.assertEquals(405, resp.status) # No screenshot after stopped the VM self.request('/vms/test-vm/poweroff', '{}', 'POST') resp = self.request('/vms/test-vm/screenshot') self.assertEquals(404, resp.status) # Picture link not available after VM deleted self.request('/vms/test-vm/start', '{}', 'POST') vm = json.loads(self.request('/vms/test-vm').read()) img_lnk = vm['screenshot'] self.request('/vms/test-vm', '{}', 'DELETE') resp = self.request(img_lnk) self.assertEquals(404, resp.status) def test_interfaces(self): resp = self.request('/interfaces').read() self.assertIn('name', resp) interfaces = json.loads(resp) keys = ['name', 'type', 'ipaddr', 'netmask', 'status'] for interface in interfaces: self.assertEquals(sorted(keys), sorted(interface.keys())) def _task_lookup(self, taskid): return json.loads(self.request('/tasks/%s' % taskid).read()) def test_tasks(self): id1 = add_task('/tasks/1', self._async_op, model.objstore) id2 = add_task('/tasks/2', self._except_op, model.objstore) id3 = add_task('/tasks/3', self._intermid_op, model.objstore) target_uri = urllib2.quote('^/tasks/*', safe="") filter_data = 'status=running&target_uri=%s' % target_uri tasks = json.loads(self.request('/tasks?%s' % filter_data).read()) self.assertEquals(3, len(tasks)) tasks = json.loads(self.request('/tasks').read()) tasks_ids = [int(t['id']) for t in tasks] self.assertEquals(set([id1, id2, id3]) - set(tasks_ids), set([])) wait_task(self._task_lookup, id2) foo2 = json.loads(self.request('/tasks/%s' % id2).read()) keys = ['id', 'status', 'message', 'target_uri'] self.assertEquals(sorted(keys), sorted(foo2.keys())) self.assertEquals('failed', foo2['status']) wait_task(self._task_lookup, id3) foo3 = json.loads(self.request('/tasks/%s' % id3).read()) self.assertEquals('in progress', foo3['message']) self.assertEquals('running', foo3['status']) def test_config(self): resp = self.request('/config').read() conf = json.loads(resp) keys = ["display_proxy_port", "version"] self.assertEquals(keys, sorted(conf.keys())) def test_capabilities(self): resp = self.request('/config/capabilities').read() conf = json.loads(resp) keys = [u'libvirt_stream_protocols', u'qemu_stream', u'qemu_spice', u'screenshot', u'system_report_tool', u'update_tool', u'repo_mngt_tool', u'federation', u'kernel_vfio', u'auth', u'nm_running', u'mem_hotplug_support'] self.assertEquals(sorted(keys), sorted(conf.keys())) def test_peers(self): resp = self.request('/peers').read() self.assertEquals([], json.loads(resp)) def test_distros(self): resp = self.request('/config/distros').read() distros = json.loads(resp) for distro in distros: self.assertIn('name', distro) self.assertIn('os_distro', distro) self.assertIn('os_version', distro) self.assertIn('path', distro) # Test in X86 ident = "Fedora 20" resp = self.request('/config/distros/%s' % urllib2.quote(ident)).read() distro = json.loads(resp) if os.uname()[4] in ['x86_64', 'amd64']: self.assertEquals(distro['name'], ident) self.assertEquals(distro['os_distro'], "fedora") self.assertEquals(distro['os_version'], "20") self.assertEquals(distro['os_arch'], "x86_64") self.assertIn('path', distro) else: # Distro not found error self.assertIn('KCHDISTRO0001E', distro.get('reason')) # Test in PPC ident = "Fedora 20 (PPC64)" resp = self.request('/config/distros/%s' % urllib2.quote(ident)).read() distro = json.loads(resp) if os.uname()[4] == 'ppc64': self.assertEquals(distro['name'], ident) self.assertEquals(distro['os_distro'], "fedora") self.assertEquals(distro['os_version'], "20") self.assertEquals(distro['os_arch'], "ppc64") self.assertIn('path', distro) else: # Distro not found error self.assertIn('KCHDISTRO0001E', distro.get('reason')) def test_debugreports(self): resp = request(host, ssl_port, '/debugreports') self.assertEquals(200, resp.status) def _report_delete(self, name): request(host, ssl_port, '/debugreports/%s' % name, '{}', 'DELETE') def test_create_debugreport(self): req = json.dumps({'name': 'report1'}) with RollbackContext() as rollback: resp = request(host, ssl_port, '/debugreports', req, 'POST') self.assertEquals(202, resp.status) task = json.loads(resp.read()) # make sure the debugreport doesn't exist until the # the task is finished wait_task(self._task_lookup, task['id']) rollback.prependDefer(self._report_delete, 'report2') resp = request(host, ssl_port, '/debugreports/report1') debugreport = json.loads(resp.read()) self.assertEquals("report1", debugreport['name']) self.assertEquals(200, resp.status) req = json.dumps({'name': 'report2'}) resp = request(host, ssl_port, '/debugreports/report1', req, 'PUT') self.assertEquals(303, resp.status) def test_debugreport_download(self): req = json.dumps({'name': 'report1'}) with RollbackContext() as rollback: resp = request(host, ssl_port, '/debugreports', req, 'POST') self.assertEquals(202, resp.status) task = json.loads(resp.read()) # make sure the debugreport doesn't exist until the # the task is finished wait_task(self._task_lookup, task['id'], 20) rollback.prependDefer(self._report_delete, 'report1') resp = request(host, ssl_port, '/debugreports/report1') debugreport = json.loads(resp.read()) self.assertEquals("report1", debugreport['name']) self.assertEquals(200, resp.status) resp = request(host, ssl_port, '/debugreports/report1/content') self.assertEquals(200, resp.status) resp = request(host, ssl_port, '/debugreports/report1') debugre = json.loads(resp.read()) resp = request(host, ssl_port, debugre['uri']) self.assertEquals(200, resp.status) def test_repositories(self): def verify_repo(t, res): for field in ('repo_id', 'enabled', 'baseurl', 'config'): if field in t.keys(): self.assertEquals(t[field], res[field]) base_uri = '/host/repositories' resp = self.request(base_uri) self.assertEquals(200, resp.status) # Already have one repo in Kimchi's system self.assertEquals(1, len(json.loads(resp.read()))) # Create a repository repo = {'repo_id': 'fedora-fake', 'baseurl': 'http://www.fedora.org'} req = json.dumps(repo) resp = self.request(base_uri, req, 'POST') self.assertEquals(201, resp.status) # Verify the repository res = json.loads(self.request('%s/fedora-fake' % base_uri).read()) verify_repo(repo, res) # Update the repository params = {} params['baseurl'] = repo['baseurl'] = 'http://www.fedoraproject.org' resp = self.request('%s/fedora-fake' % base_uri, json.dumps(params), 'PUT') # Verify the repository res = json.loads(self.request('%s/fedora-fake' % base_uri).read()) verify_repo(repo, res) # Delete the repository resp = self.request('%s/fedora-fake' % base_uri, '{}', 'DELETE') self.assertEquals(204, resp.status) class HttpsRestTests(RestTests): """ Run all of the same tests as above, but use https instead """ def setUp(self): self.request = partial(request, host, ssl_port) model.reset() kimchi-1.5.0/tests/test_rollbackcontext.py000066400000000000000000000063601254252253000207370ustar00rootroot00000000000000# # 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 import unittest from kimchi.rollbackcontext import RollbackContext class FirstError(Exception): '''A hypothetical exception to be raise in the test firstly.''' pass class SecondError(Exception): '''A hypothetical exception to be raise in the test secondly.''' pass class RollbackContextTests(unittest.TestCase): def setUp(self): self._counter = 0 def _inc_counter(self): self._counter += 1 def _raise(self, exception=FirstError): raise exception() def test_rollback(self): with RollbackContext() as rollback: rollback.prependDefer(self._inc_counter) rollback.prependDefer(self._inc_counter) self.assertEquals(self._counter, 2) def test_raise(self): try: with RollbackContext() as rollback: rollback.prependDefer(self._inc_counter) rollback.prependDefer(self._inc_counter) raise FirstError() rollback.prependDefer(self._inc_counter) except FirstError: # All undo before the FirstError should be run self.assertEquals(self._counter, 2) else: self.fail('Should have raised FirstError') def test_raise_undo(self): try: with RollbackContext() as rollback: rollback.prependDefer(self._inc_counter) rollback.prependDefer(self._raise) rollback.prependDefer(self._inc_counter) except FirstError: # All undo should be run self.assertEquals(self._counter, 2) else: self.fail('Should have raised FirstError') def test_raise_prefer_original(self): try: with RollbackContext() as rollback: rollback.prependDefer(self._raise, SecondError) raise FirstError() except FirstError: pass except SecondError: self.fail('Should have preferred FirstError to SecondError') else: self.fail('Should have raised FirstError') def test_raise_prefer_first_undo(self): try: with RollbackContext() as rollback: rollback.prependDefer(self._raise, SecondError) rollback.prependDefer(self._raise, FirstError) except FirstError: pass except SecondError: self.fail('Should have preferred FirstError to SecondError') else: self.fail('Should have raised FirstError') kimchi-1.5.0/tests/test_server.py000066400000000000000000000225201254252253000170430ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-2015 # # 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 import base64 import cherrypy import json import os import tempfile import threading import unittest from functools import partial import utils from kimchi import mockmodel from kimchi.control.base import Collection, Resource test_server = None model = None host = None port = None ssl_port = None cherrypy_port = None tmpfile = None def setUpModule(): global test_server, model, host, port, ssl_port, cherrypy_port, tmpfile utils.patch_auth() tmpfile = tempfile.mktemp() model = mockmodel.MockModel(tmpfile) host = '127.0.0.1' port = utils.get_free_port('http') ssl_port = utils.get_free_port('https') cherrypy_port = utils.get_free_port('cherrypy_port') test_server = utils.run_server(host, port, ssl_port, test_mode=True, cherrypy_port=cherrypy_port, model=model) def tearDownModule(): test_server.stop() os.unlink(tmpfile) class ServerTests(unittest.TestCase): def setUp(self): self.request = partial(utils.request, host, ssl_port) model.reset() def assertValidJSON(self, txt): try: json.loads(txt) except ValueError: self.fail("Invalid JSON: %s" % txt) def test_server_start(self): """ Test that we can start a server and receive HTTP:200. """ resp = self.request('/') self.assertEquals(200, resp.status) def test_multithreaded_connection(self): def worker(): for i in xrange(100): ret = model.vms_get_list() self.assertEquals('test', ret[0]) threads = [] for i in xrange(100): t = threading.Thread(target=worker) t.setDaemon(True) t.start() threads.append(t) for t in threads: t.join() def test_collection(self): c = Collection(model) # The base Collection is always empty cherrypy.request.method = 'GET' cherrypy.request.headers['Accept'] = 'application/json' self.assertEquals('[]', c.index()) # POST and DELETE raise HTTP:405 by default for method in ('POST', 'DELETE'): cherrypy.request.method = method try: c.index() except cherrypy.HTTPError, e: self.assertEquals(405, e.code) else: self.fail("Expected exception not raised") def test_resource(self): r = Resource(model) # Test the base Resource representation cherrypy.request.method = 'GET' cherrypy.request.headers['Accept'] = 'application/json' self.assertEquals('{}', r.index()) # POST and DELETE raise HTTP:405 by default for method in ('POST', 'DELETE'): cherrypy.request.method = method try: r.index() except cherrypy.HTTPError, e: self.assertEquals(405, e.code) else: self.fail("Expected exception not raised") def test_404(self): """ A non-existent path should return HTTP:404 """ url_list = ['/doesnotexist', '/vms/blah'] for url in url_list: resp = self.request(url) self.assertEquals(404, resp.status) # Verify it works for DELETE too resp = self.request('/templates/blah', '', 'DELETE') self.assertEquals(404, resp.status) def test_accepts(self): """ Verify the following expectations regarding the client Accept header: If omitted, default to html If 'application/json', serve the rest api If 'text/html', serve the UI If both of the above (in any order), serve the rest api If neither of the above, HTTP:406 """ resp = self.request("/", headers={}) location = resp.getheader('location') self.assertTrue(location.endswith("login.html")) resp = self.request("/login.html", headers={}) self.assertTrue('' in resp.read().lower()) resp = self.request("/", headers={'Accept': 'application/json'}) self.assertValidJSON(resp.read()) resp = self.request("/", headers={'Accept': 'text/html'}) location = resp.getheader('location') self.assertTrue(location.endswith("login.html")) resp = self.request("/", headers={'Accept': 'application/json, text/html'}) self.assertValidJSON(resp.read()) resp = self.request("/", headers={'Accept': 'text/html, application/json'}) self.assertValidJSON(resp.read()) h = {'Accept': 'text/plain'} resp = self.request('/', None, 'GET', h) self.assertEquals(406, resp.status) def test_auth_unprotected(self): hdrs = {'AUTHORIZATION': ''} uris = ['/js/kimchi.min.js', '/css/theme-default.min.css', '/libs/jquery-1.10.0.min.js', '/images/icon-vm.png', '/login.html', '/logout'] for uri in uris: resp = self.request(uri, None, 'HEAD', hdrs) self.assertEquals(200, resp.status) def test_auth_protected(self): hdrs = {'AUTHORIZATION': ''} uris = ['/vms', '/vms/doesnotexist', '/tasks'] for uri in uris: resp = self.request(uri, None, 'GET', hdrs) self.assertEquals(401, resp.status) def test_auth_bad_creds(self): # Test HTTPBA hdrs = {'AUTHORIZATION': "Basic " + base64.b64encode("nouser:badpass")} resp = self.request('/vms', None, 'GET', hdrs) self.assertEquals(401, resp.status) # Test REST API hdrs = {'AUTHORIZATION': ''} req = json.dumps({'username': 'nouser', 'password': 'badpass'}) resp = self.request('/login', req, 'POST', hdrs) self.assertEquals(401, resp.status) def test_auth_browser_no_httpba(self): # Kimchi detects REST requests from the browser by looking for a # specific header hdrs = {"X-Requested-With": "XMLHttpRequest"} # Try our request (Note that request() will add a valid HTTPBA header) resp = self.request('/vms', None, 'GET', hdrs) self.assertEquals(401, resp.status) self.assertEquals(None, resp.getheader('WWW-Authenticate')) def test_auth_session(self): hdrs = {'AUTHORIZATION': '', 'Content-Type': 'application/json', 'Accept': 'application/json'} # Test we are logged out resp = self.request('/tasks', None, 'GET', hdrs) self.assertEquals(401, resp.status) # Execute a login call user, pw = mockmodel.fake_user.items()[0] req = json.dumps({'username': user, 'password': pw}) resp = self.request('/login', req, 'POST', hdrs) self.assertEquals(200, resp.status) user_info = json.loads(resp.read()) self.assertEquals(sorted(user_info.keys()), ['groups', 'roles', 'username']) roles = user_info['roles'] for tab, role in roles.iteritems(): self.assertEquals(role, u'admin') cookie = resp.getheader('set-cookie') hdrs['Cookie'] = cookie # Test we are logged in with the cookie resp = self.request('/tasks', None, 'GET', hdrs) self.assertEquals(200, resp.status) # Execute a logout call resp = self.request('/logout', '{}', 'POST', hdrs) self.assertEquals(200, resp.status) del hdrs['Cookie'] # Test we are logged out resp = self.request('/tasks', None, 'GET', hdrs) self.assertEquals(401, resp.status) def test_get_param(self): # Create a mock ISO file mockiso = '/tmp/mock.iso' open('/tmp/mock.iso', 'w').close() # Create 2 different templates req = json.dumps({'name': 'test-tmpl1', 'cdrom': mockiso}) self.request('/templates', req, 'POST') req = json.dumps({'name': 'test-tmpl2', 'cdrom': mockiso}) self.request('/templates', req, 'POST') # Remove mock iso os.unlink(mockiso) # Get the templates resp = self.request('/templates') self.assertEquals(200, resp.status) res = json.loads(resp.read()) self.assertEquals(2, len(res)) # Get a specific template resp = self.request('/templates?name=test-tmpl1') self.assertEquals(200, resp.status) res = json.loads(resp.read()) self.assertEquals(1, len(res)) self.assertEquals('test-tmpl1', res[0]['name']) kimchi-1.5.0/tests/test_storagepoolxml.py000066400000000000000000000137051254252253000206210ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2015 # # 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 import lxml.etree as ET import unittest from kimchi.model.libvirtstoragepool import StoragePoolDef class StoragepoolXMLTests(unittest.TestCase): def test_get_storagepool_xml(self): poolDefs = [ {'def': {'type': 'dir', 'name': 'unitTestDirPool', 'path': '/var/temp/images'}, 'xml': """ unitTestDirPool /var/temp/images """}, {'def': {'type': 'netfs', 'name': 'unitTestNFSPool', 'source': {'host': '127.0.0.1', 'path': '/var/export'}}, 'xml': """ unitTestNFSPool /var/lib/kimchi/nfs_mount/unitTestNFSPool """}, {'def': {'type': 'logical', 'name': 'unitTestLogicalPool', 'source': {'devices': ['/dev/hda', '/dev/hdb']}}, 'xml': """ unitTestLogicalPool /dev/unitTestLogicalPool """}, {'def': {'type': 'iscsi', 'name': 'unitTestISCSIPool', 'source': { 'host': '127.0.0.1', 'target': 'iqn.2003-01.org.linux-iscsi.localhost'}}, 'xml': """ unitTestISCSIPool /dev/disk/by-id """}, {'def': {'type': 'iscsi', 'name': 'unitTestISCSIPoolPort', 'source': { 'host': '127.0.0.1', 'port': 3266, 'target': 'iqn.2003-01.org.linux-iscsi.localhost'}}, 'xml': """ unitTestISCSIPoolPort /dev/disk/by-id """}, {'def': {'type': 'iscsi', 'name': 'unitTestISCSIPoolAuth', 'source': { 'host': '127.0.0.1', 'target': 'iqn.2003-01.org.linux-iscsi.localhost', 'auth': {'username': 'testUser', 'password': 'ActuallyNotUsedInPoolXML'}}}, 'xml': """ unitTestISCSIPoolAuth /dev/disk/by-id """}, {'def': {'type': 'scsi', 'name': 'unitTestSCSIFCPool', 'path': '/dev/disk/by-path', 'source': { 'name': 'scsi_host3', 'adapter': { 'type': 'fc_host', 'wwpn': '0123456789abcdef', 'wwnn': 'abcdef0123456789'}}}, 'xml': """ unitTestSCSIFCPool /dev/disk/by-path """}] for poolDef in poolDefs: defObj = StoragePoolDef.create(poolDef['def']) xmlStr = defObj.xml parser = ET.XMLParser(remove_blank_text=True) t1 = ET.fromstring(xmlStr, parser) t2 = ET.fromstring(poolDef['xml'], parser) self.assertEquals(ET.tostring(t1), ET.tostring(t2)) kimchi-1.5.0/tests/test_template.py000066400000000000000000000352601254252253000173550ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # Project Kimchi # # Copyright IBM, Corp. 2015 # # 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 import json import os import unittest from functools import partial from kimchi.config import READONLY_POOL_TYPE from kimchi.mockmodel import MockModel from utils import get_free_port, patch_auth, request, run_server model = None test_server = None host = None port = None ssl_port = None cherrypy_port = None def setUpModule(): global test_server, model, host, port, ssl_port, cherrypy_port patch_auth() model = MockModel('/tmp/obj-store-test') host = '127.0.0.1' port = get_free_port('http') ssl_port = get_free_port('https') cherrypy_port = get_free_port('cherrypy_port') test_server = run_server(host, port, ssl_port, test_mode=True, cherrypy_port=cherrypy_port, model=model) def tearDownModule(): test_server.stop() os.unlink('/tmp/obj-store-test') class TemplateTests(unittest.TestCase): def setUp(self): self.request = partial(request, host, ssl_port) model.reset() def test_tmpl_lifecycle(self): resp = self.request('/templates') self.assertEquals(200, resp.status) self.assertEquals(0, len(json.loads(resp.read()))) # Create a template without cdrom and disk specified fails with 400 t = {'name': 'test', 'os_distro': 'ImagineOS', 'os_version': '1.0', 'memory': 1024, 'cpus': 1, 'storagepool': '/storagepools/alt'} req = json.dumps(t) resp = self.request('/templates', req, 'POST') self.assertEquals(400, resp.status) # Create a template t = {'name': 'test', 'cdrom': '/tmp/mock.iso'} req = json.dumps(t) resp = self.request('/templates', req, 'POST') self.assertEquals(201, resp.status) # Verify the template keys = ['name', 'icon', 'invalid', 'os_distro', 'os_version', 'cpus', 'memory', 'cdrom', 'disks', 'storagepool', 'networks', 'folder', 'graphics', 'cpu_info'] tmpl = json.loads(self.request('/templates/test').read()) self.assertEquals(sorted(tmpl.keys()), sorted(keys)) # Verify if default disk format was configured self.assertEquals(tmpl['disks'][0]['format'], 'qcow2') # Clone a template resp = self.request('/templates/test/clone', '{}', 'POST') self.assertEquals(303, resp.status) # Verify the cloned template tmpl_cloned = json.loads(self.request('/templates/test-clone1').read()) del tmpl['name'] del tmpl_cloned['name'] self.assertEquals(tmpl, tmpl_cloned) # Delete the cloned template resp = self.request('/templates/test-clone1', '{}', 'DELETE') self.assertEquals(204, resp.status) # Create a template with same name fails with 400 req = json.dumps({'name': 'test', 'cdrom': '/tmp/mock.iso'}) resp = self.request('/templates', req, 'POST') self.assertEquals(400, resp.status) # Create an image based template open('/tmp/mock.img', 'w').close() t = {'name': 'test_img_template', 'disks': [{'base': '/tmp/mock.img'}]} req = json.dumps(t) resp = self.request('/templates', req, 'POST') self.assertEquals(201, resp.status) os.remove('/tmp/mock.img') # Test disk format t = {'name': 'test-format', 'cdrom': '/tmp/mock.iso', 'disks': [{'index': 0, 'size': 10, 'format': 'vmdk'}]} req = json.dumps(t) resp = self.request('/templates', req, 'POST') self.assertEquals(201, resp.status) tmpl = json.loads(self.request('/templates/test-format').read()) self.assertEquals(tmpl['disks'][0]['format'], 'vmdk') def test_customized_tmpl(self): # Create a template t = {'name': 'test', 'cdrom': '/tmp/mock.iso'} req = json.dumps(t) resp = self.request('/templates', req, 'POST') self.assertEquals(201, resp.status) tmpl = json.loads(self.request('/templates/test').read()) # Update name new_name = u'kīмÑhÄ«Tmpl' new_tmpl_uri = '/templates/%s' % new_name.encode('utf-8') req = json.dumps({'name': new_name}) resp = self.request('/templates/test', req, 'PUT') self.assertEquals(303, resp.status) resp = self.request(new_tmpl_uri) update_tmpl = json.loads(resp.read()) self.assertEquals(new_name, update_tmpl['name']) del tmpl['name'] del update_tmpl['name'] self.assertEquals(tmpl, update_tmpl) # Update icon req = json.dumps({'icon': 'images/icon-fedora.png'}) resp = self.request(new_tmpl_uri, req, 'PUT') self.assertEquals(200, resp.status) update_tmpl = json.loads(resp.read()) self.assertEquals('images/icon-fedora.png', update_tmpl['icon']) # Update os_distro and os_version req = json.dumps({'os_distro': 'fedora', 'os_version': '21'}) resp = self.request(new_tmpl_uri, req, 'PUT') self.assertEquals(200, resp.status) update_tmpl = json.loads(resp.read()) self.assertEquals('fedora', update_tmpl['os_distro']) self.assertEquals('21', update_tmpl['os_version']) # Update cpus req = json.dumps({'cpus': 2}) resp = self.request(new_tmpl_uri, req, 'PUT') self.assertEquals(200, resp.status) update_tmpl = json.loads(resp.read()) self.assertEquals(2, update_tmpl['cpus']) # Update memory req = json.dumps({'memory': 2048}) resp = self.request(new_tmpl_uri, req, 'PUT') self.assertEquals(200, resp.status) update_tmpl = json.loads(resp.read()) self.assertEquals(2048, update_tmpl['memory']) # Update cpu_info resp = self.request(new_tmpl_uri) cpu_info = json.loads(resp.read())['cpu_info'] self.assertEquals(cpu_info, {}) self.assertEquals(cpu_info.get('topology'), None) cpu_info_data = {'cpu_info': {'topology': {'sockets': 1, 'cores': 2, 'threads': 1}}} resp = self.request(new_tmpl_uri, json.dumps(cpu_info_data), 'PUT') self.assertEquals(200, resp.status) update_tmpl = json.loads(resp.read()) self.assertEquals(update_tmpl['cpu_info'], cpu_info_data['cpu_info']) # Update cdrom cdrom_data = {'cdrom': '/tmp/mock2.iso'} resp = self.request(new_tmpl_uri, json.dumps(cdrom_data), 'PUT') self.assertEquals(200, resp.status) update_tmpl = json.loads(resp.read()) self.assertEquals(update_tmpl['cdrom'], cdrom_data['cdrom']) # Update disks disk_data = {'disks': [{'index': 0, 'size': 10}, {'index': 1, 'size': 20}]} resp = self.request(new_tmpl_uri, json.dumps(disk_data), 'PUT') self.assertEquals(200, resp.status) resp = self.request(new_tmpl_uri) self.assertEquals(200, resp.status) updated_tmpl = json.loads(resp.read()) self.assertEquals(updated_tmpl['disks'], disk_data['disks']) # For all supported types, edit the template and check if # the change was made. disk_types = ['bochs', 'cloop', 'cow', 'dmg', 'qcow', 'qcow2', 'qed', 'raw', 'vmdk', 'vpc'] for disk_type in disk_types: disk_data = {'disks': [{'index': 0, 'format': disk_type, 'size': 10}]} resp = self.request(new_tmpl_uri, json.dumps(disk_data), 'PUT') self.assertEquals(200, resp.status) resp = self.request(new_tmpl_uri) self.assertEquals(200, resp.status) updated_tmpl = json.loads(resp.read()) self.assertEquals(updated_tmpl['disks'], disk_data['disks']) # Update folder folder_data = {'folder': ['mock', 'isos']} resp = self.request(new_tmpl_uri, json.dumps(folder_data), 'PUT') self.assertEquals(200, resp.status) update_tmpl = json.loads(resp.read()) self.assertEquals(update_tmpl['folder'], folder_data['folder']) # Update graphics req = json.dumps({'graphics': {'type': 'spice'}}) resp = self.request(new_tmpl_uri, req, 'PUT') self.assertEquals(200, resp.status) update_tmpl = json.loads(resp.read()) self.assertEquals('spice', update_tmpl['graphics']['type']) req = json.dumps({'graphics': {'type': 'vnc', 'listen': 'fe00::0'}}) resp = self.request(new_tmpl_uri, req, 'PUT') self.assertEquals(200, resp.status) update_tmpl = json.loads(resp.read()) self.assertEquals('vnc', update_tmpl['graphics']['type']) self.assertEquals('fe00::0', update_tmpl['graphics']['listen']) def test_customized_network(self): # Create a template t = {'name': 'test', 'cdrom': '/tmp/mock.iso'} req = json.dumps(t) resp = self.request('/templates', req, 'POST') self.assertEquals(201, resp.status) # Create networks to be used for testing networks = [{'name': u'kīмÑhÄ«-пet', 'connection': 'isolated'}, {'name': u'nat-network', 'connection': 'nat'}, {'name': u'subnet-network', 'connection': 'nat', 'subnet': '127.0.100.0/24'}] # Verify the current system has at least one interface to create a # bridged network interfaces = json.loads(self.request('/interfaces?type=nic').read()) if len(interfaces) > 0: iface = interfaces[0]['name'] networks.append({'name': u'bridge-network', 'connection': 'bridge', 'interface': iface}) networks.append({'name': u'bridge-network', 'connection': 'bridge', 'interface': iface, 'vlan_id': 987}) tmpl_nets = [] for net in networks: self.request('/networks', json.dumps(net), 'POST') tmpl_nets.append(net['name']) req = json.dumps({'networks': tmpl_nets}) resp = self.request('/templates/test', req, 'PUT') self.assertEquals(200, resp.status) def test_customized_storagepool(self): # Create a template t = {'name': 'test', 'cdrom': '/tmp/mock.iso'} req = json.dumps(t) resp = self.request('/templates', req, 'POST') self.assertEquals(201, resp.status) # MockModel always returns 2 partitions (vdx, vdz) partitions = json.loads(self.request('/host/partitions').read()) devs = [dev['path'] for dev in partitions] # MockModel always returns 3 FC devices fc_devs = json.loads(self.request('/host/devices?_cap=fc_host').read()) fc_devs = [dev['name'] for dev in fc_devs] poolDefs = [ {'type': 'dir', 'name': u'kīмÑhÄ«UnitTestDirPool', 'path': '/tmp/kimchi-images'}, {'type': 'netfs', 'name': u'kīмÑhÄ«UnitTestNSFPool', 'source': {'host': 'localhost', 'path': '/var/lib/kimchi/nfs-pool'}}, {'type': 'scsi', 'name': u'kīмÑhÄ«UnitTestSCSIFCPool', 'source': {'adapter_name': fc_devs[0]}}, {'type': 'iscsi', 'name': u'kīмÑhÄ«UnitTestISCSIPool', 'source': {'host': '127.0.0.1', 'target': 'iqn.2015-01.localhost.kimchiUnitTest'}}, {'type': 'logical', 'name': u'kīмÑhÄ«UnitTestLogicalPool', 'source': {'devices': [devs[0]]}}] for pool in poolDefs: self.request('/storagepools', json.dumps(pool), 'POST') pool_uri = '/storagepools/%s' % pool['name'].encode('utf-8') self.request(pool_uri + '/activate', '{}', 'POST') req = None if pool['type'] in READONLY_POOL_TYPE: resp = self.request(pool_uri + '/storagevolumes') vols = json.loads(resp.read()) if len(vols) > 0: vol = vols[0]['name'] req = json.dumps({'storagepool': pool_uri, 'disks': [{'volume': vol}]}) else: req = json.dumps({'storagepool': pool_uri}) if req is not None: resp = self.request('/templates/test', req, 'PUT') self.assertEquals(200, resp.status) def test_tmpl_integrity(self): # Create a network and a pool for testing template integrity net = {'name': u'nat-network', 'connection': 'nat'} self.request('/networks', json.dumps(net), 'POST') pool = {'type': 'dir', 'name': 'dir-pool', 'path': '/tmp/dir-pool'} self.request('/storagepools', json.dumps(pool), 'POST') pool_uri = '/storagepools/%s' % pool['name'].encode('utf-8') self.request(pool_uri + '/activate', '{}', 'POST') # Create a template using the custom network and pool t = {'name': 'test', 'cdrom': '/tmp/mock.iso', 'networks': ['nat-network'], 'storagepool': '/storagepools/dir-pool'} req = json.dumps(t) resp = self.request('/templates', req, 'POST') self.assertEquals(201, resp.status) # Try to delete network # It should fail as it is associated to a template resp = self.request('/networks/nat-network', '{}', 'DELETE') self.assertIn("KCHNET0017E", json.loads(resp.read())["reason"]) # Update template to release network and then delete it params = {'networks': []} req = json.dumps(params) self.request('/templates/test', req, 'PUT') resp = self.request('/networks/nat-network', '{}', 'DELETE') self.assertEquals(204, resp.status) # Try to delete the storagepool # It should fail as it is associated to a template resp = self.request('/storagepools/dir-pool', '{}', 'DELETE') self.assertEquals(400, resp.status) # Verify the template res = json.loads(self.request('/templates/test').read()) self.assertEquals(res['invalid']['cdrom'], ['/tmp/mock.iso']) kimchi-1.5.0/tests/test_utils.py000066400000000000000000000060471254252253000167030ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2015 # # 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 import unittest from kimchi.exception import InvalidParameter from kimchi.utils import convert_data_size class UtilsTests(unittest.TestCase): def test_convert_data_size(self): failure_data = [{'val': None, 'from': 'MiB'}, {'val': self, 'from': 'MiB'}, {'val': 1, 'from': None}, {'val': 1, 'from': ''}, {'val': 1, 'from': 'foo'}, {'val': 1, 'from': 'kib'}, {'val': 1, 'from': 'MiB', 'to': None}, {'val': 1, 'from': 'MiB', 'to': ''}, {'val': 1, 'from': 'MiB', 'to': 'foo'}, {'val': 1, 'from': 'MiB', 'to': 'kib'}] for d in failure_data: if 'to' in d: self.assertRaises(InvalidParameter, convert_data_size, d['val'], d['from'], d['to']) else: self.assertRaises(InvalidParameter, convert_data_size, d['val'], d['from']) success_data = [{'got': convert_data_size(5, 'MiB', 'MiB'), 'want': 5}, {'got': convert_data_size(5, 'MiB', 'KiB'), 'want': 5120}, {'got': convert_data_size(5, 'MiB', 'M'), 'want': 5.24288}, {'got': convert_data_size(5, 'MiB', 'GiB'), 'want': 0.0048828125}, {'got': convert_data_size(5, 'MiB', 'Tb'), 'want': 4.194304e-05}, {'got': convert_data_size(5, 'KiB', 'MiB'), 'want': 0.0048828125}, {'got': convert_data_size(5, 'M', 'MiB'), 'want': 4.76837158203125}, {'got': convert_data_size(5, 'GiB', 'MiB'), 'want': 5120}, {'got': convert_data_size(5, 'Tb', 'MiB'), 'want': 596046.4477539062}, {'got': convert_data_size(5, 'MiB'), 'want': convert_data_size(5, 'MiB', 'B')}] for d in success_data: self.assertEquals(d['got'], d['want']) kimchi-1.5.0/tests/test_vmtemplate.py000066400000000000000000000112731254252253000177160ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-2015 # # 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 import os import unittest import uuid from kimchi.osinfo import get_template_default from kimchi.vmtemplate import VMTemplate from kimchi.xmlutils.utils import xpath_get_text class VMTemplateTests(unittest.TestCase): def setUp(self): self.iso = '/tmp/mock.iso' open(self.iso, 'w').close() def tearDown(self): os.unlink(self.iso) def test_minimal_construct(self): disk_bus = get_template_default('old', 'disk_bus') memory = get_template_default('old', 'memory') nic_model = get_template_default('old', 'nic_model') fields = (('name', 'test'), ('os_distro', 'unknown'), ('os_version', 'unknown'), ('cpus', 1), ('memory', memory), ('networks', ['default']), ('disk_bus', disk_bus), ('nic_model', nic_model), ('graphics', {'type': 'vnc', 'listen': '127.0.0.1'}), ('cdrom', self.iso)) args = {'name': 'test', 'cdrom': self.iso} t = VMTemplate(args) for name, val in fields: self.assertEquals(val, t.info.get(name)) def test_construct_overrides(self): graphics = {'type': 'spice', 'listen': '127.0.0.1'} args = {'name': 'test', 'disks': [{'size': 10}, {'size': 20}], 'graphics': graphics, "cdrom": self.iso} t = VMTemplate(args) self.assertEquals(2, len(t.info['disks'])) self.assertEquals(graphics, t.info['graphics']) def test_specified_graphics(self): # Test specified listen graphics = {'type': 'vnc', 'listen': '127.0.0.1'} args = {'name': 'test', 'disks': [{'size': 10}, {'size': 20}], 'graphics': graphics, 'cdrom': self.iso} t = VMTemplate(args) self.assertEquals(graphics, t.info['graphics']) # Test specified type graphics = {'type': 'spice', 'listen': '127.0.0.1'} args['graphics'] = graphics t = VMTemplate(args) self.assertEquals(graphics, t.info['graphics']) # If no listen specified, test the default listen graphics = {'type': 'vnc'} args['graphics'] = graphics t = VMTemplate(args) self.assertEquals(graphics['type'], t.info['graphics']['type']) self.assertEquals('127.0.0.1', t.info['graphics']['listen']) def test_to_xml(self): graphics = {'type': 'spice', 'listen': '127.0.0.1'} vm_uuid = str(uuid.uuid4()).replace('-', '') if os.uname()[4] in ['ppc', 'ppc64', 'ppc64le']: maxmem = 3328 else: maxmem = 3072 t = VMTemplate({'name': 'test-template', 'cdrom': self.iso, 'max_memory': maxmem << 10}) xml = t.to_vm_xml('test-vm', vm_uuid, graphics=graphics) self.assertEquals(vm_uuid, xpath_get_text(xml, "/domain/uuid")[0]) self.assertEquals('test-vm', xpath_get_text(xml, "/domain/name")[0]) expr = "/domain/devices/graphics/@type" self.assertEquals(graphics['type'], xpath_get_text(xml, expr)[0]) expr = "/domain/devices/graphics/@listen" self.assertEquals(graphics['listen'], xpath_get_text(xml, expr)[0]) expr = "/domain/maxMemory/@slots" self.assertEquals('2', xpath_get_text(xml, expr)[0]) def test_arg_merging(self): """ Make sure that default parameters from osinfo do not override user- provided parameters. """ graphics = {'type': 'vnc', 'listen': '127.0.0.1'} args = {'name': 'test', 'os_distro': 'opensuse', 'os_version': '12.3', 'cpus': 2, 'memory': 2048, 'networks': ['foo'], 'cdrom': self.iso, 'graphics': graphics} t = VMTemplate(args) self.assertEquals(2, t.info.get('cpus')) self.assertEquals(2048, t.info.get('memory')) self.assertEquals(['foo'], t.info.get('networks')) self.assertEquals(self.iso, t.info.get('cdrom')) self.assertEquals(graphics, t.info.get('graphics')) kimchi-1.5.0/tests/test_yumparser.py000066400000000000000000000132121254252253000175620ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2015 # # 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 import os import tempfile import unittest from kimchi.model import model from kimchi.rollbackcontext import RollbackContext from kimchi.yumparser import delete_repo_from_file, get_repo_files from kimchi.yumparser import get_yum_packages_list_update from kimchi.yumparser import get_yum_repositories, write_repo_to_file from kimchi.yumparser import YumRepoObject TEMP_REPO_FILE = '' def _is_yum_distro(): inst = model.Model('test:///default') repo_type = inst.capabilities_lookup()['repo_mngt_tool'] return repo_type == 'yum' def _create_fake_repos(repo_file_name): repo1 = YumRepoObject('fake-repo-1', repo_file_name) repo2 = YumRepoObject('fake-repo-2', repo_file_name) repo3 = YumRepoObject('fake-repo-3', repo_file_name) repo4 = YumRepoObject('fake-repo-4', repo_file_name) repos = [repo1, repo2, repo3, repo4] return repos def _create_empty_repo_file(): data = """ # # This is a repository file with no repositories at all # No repositories must be added after reading this file. # """ _, tmp_file_name = tempfile.mkstemp(suffix='.repo', dir='/etc/yum.repos.d') with open(tmp_file_name, 'w') as f: f.writelines(data) return tmp_file_name def _create_fake_repos_file(): _, tmp_file_name = tempfile.mkstemp(suffix='.repo', dir='/etc/yum.repos.d') fake_repos = _create_fake_repos(tmp_file_name) file_data = '' for repo in fake_repos: file_data += str(repo) + '\n' with open(tmp_file_name, 'w') as f: f.writelines(file_data) return tmp_file_name def _generate_yumcheckupdate_output(): output = """ Repository 'REPOSITORY1' is missing name in configuration, using id Repository 'REPOSITORY1-OPTIONAL' is missing name in configuration, using id PACKAGE1.noarch 20150611.-gg-FAKE1 REPOSITORY1 PACKAGE2.x86_64 20150611.-no-FAKE2 REPOSITORY2 PACKAGE3.dot.dot.i386 20150611.-re-FAKE3 REPOSITORY3 Obsoleting Packages OBSOLETE4.dot.dot.i386 20150611.FAKE4 REPOSITORY4 OBSOLETE5.dot.dot.fakearch 20150611.FAKE5 REPOSITORY5 """ return output @unittest.skipIf(not _is_yum_distro(), 'Skipping: YUM exclusive test') def setUpModule(): global TEMP_REPO_FILE TEMP_REPO_FILE = _create_fake_repos_file() @unittest.skipIf(not _is_yum_distro(), 'Skipping: YUM exclusive test') def tearDownModule(): os.remove(TEMP_REPO_FILE) @unittest.skipIf(not _is_yum_distro(), 'Skipping: YUM exclusive test') class YumParserTests(unittest.TestCase): def test_get_yum_repositories(self): repo_files = get_repo_files() repo_objects = get_yum_repositories() self.assertGreaterEqual(len(repo_objects), len(repo_files)) def test_empty_repo_file(self): with RollbackContext() as rollback: repos = get_yum_repositories() tmp_file_name = _create_empty_repo_file() rollback.prependDefer(os.remove, tmp_file_name) repos_after = get_yum_repositories() self.assertEqual(len(repos_after), len(repos)) def test_update_repo_attributes(self): repos = get_yum_repositories() fake_repo_2 = repos['fake-repo-2'] fake_repo_2.disable() fake_repo_2.name = 'This is a fake repo' fake_repo_2.baseurl = 'http://a.fake.repo.url' fake_repo_2.gpgkey = 'file://a/fake/gpg/key.fake' fake_repo_2.gpgcheck = False fake_repo_2.metalink = 'this is not a true metalink' fake_repo_2.mirrorlist = 'fake mirrorlist' write_repo_to_file(fake_repo_2) repos = get_yum_repositories() fake_repo_2 = repos['fake-repo-2'] self.assertEqual(False, fake_repo_2.enabled) self.assertEqual(False, fake_repo_2.gpgcheck) self.assertEqual('This is a fake repo', fake_repo_2.name) self.assertEqual('http://a.fake.repo.url', fake_repo_2.baseurl) self.assertEqual('file://a/fake/gpg/key.fake', fake_repo_2.gpgkey) self.assertEqual('this is not a true metalink', fake_repo_2.metalink) self.assertEqual('fake mirrorlist', fake_repo_2.mirrorlist) def test_delete_repo_from_file(self): repos = get_yum_repositories() fake_repo_3 = repos['fake-repo-3'] delete_repo_from_file(fake_repo_3) repos = get_yum_repositories() repos_id = repos.keys() self.assertNotIn('fake-repo-3', repos_id) def test_yum_checkupdate_parsing(self): output = _generate_yumcheckupdate_output() packages = get_yum_packages_list_update(output) self.assertEqual(len(packages), 5) self.assertEqual(packages[0].ui_from_repo, 'REPOSITORY1') self.assertEqual(packages[1].version, '20150611.-no-FAKE2') self.assertEqual(packages[2].name, 'PACKAGE3.dot.dot') self.assertEqual(packages[3].arch, 'i386') self.assertEqual(packages[4].arch, 'fakearch') kimchi-1.5.0/tests/utils.py000066400000000000000000000202101254252253000156300ustar00rootroot00000000000000# # Project Kimchi # # Copyright IBM, Corp. 2013-2015 # # 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 # import base64 import cherrypy import grp import httplib import inspect import json import os import socket import ssl import sys import time import threading import unittest from contextlib import closing from lxml import etree import kimchi.mockmodel import kimchi.server from kimchi.config import config, paths from kimchi.auth import User, USER_NAME, USER_GROUPS, USER_ROLES, tabs from kimchi.exception import NotFoundError, OperationFailed from kimchi.utils import kimchi_log _ports = {} # provide missing unittest decorators and API for python 2.6; these decorators # do not actually work, just avoid the syntax failure if sys.version_info[:2] == (2, 6): def skipUnless(condition, reason): if not condition: sys.stderr.write('[expected failure] ') raise Exception(reason) return lambda obj: obj unittest.skipUnless = skipUnless unittest.expectedFailure = lambda obj: obj def assertGreater(self, a, b, msg=None): if not a > b: self.fail('%s not greater than %s' % (repr(a), repr(b))) def assertGreaterEqual(self, a, b, msg=None): if not a >= b: self.fail('%s not greater than or equal to %s' % (repr(a), repr(b))) def assertIsInstance(self, obj, cls, msg=None): if not isinstance(obj, cls): self.fail('%s is not an instance of %r' % (repr(obj), cls)) def assertIn(self, a, b, msg=None): if a not in b: self.fail("%s is not in %b" % (repr(a), repr(b))) def assertNotIn(self, a, b, msg=None): if a in b: self.fail("%s is in %b" % (repr(a), repr(b))) unittest.TestCase.assertGreaterEqual = assertGreaterEqual unittest.TestCase.assertGreater = assertGreater unittest.TestCase.assertIsInstance = assertIsInstance unittest.TestCase.assertIn = assertIn unittest.TestCase.assertNotIn = assertNotIn def get_free_port(name='http'): global _ports if _ports.get(name) is not None: return _ports[name] sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) with closing(sock): try: sock.bind(("0.0.0.0", 0)) except: raise Exception("Could not find a free port") _ports[name] = sock.getsockname()[1] return _ports[name] def run_server(host, port, ssl_port, test_mode, cherrypy_port=None, model=None, environment='development'): if cherrypy_port is None: cherrypy_port = get_free_port('cherrypy_port') if ssl_port is None: ssl_port = get_free_port('https') args = type('_', (object,), {'host': host, 'port': port, 'ssl_port': ssl_port, 'cherrypy_port': cherrypy_port, 'max_body_size': '4*1024', 'ssl_cert': '', 'ssl_key': '', 'test': test_mode, 'access_log': '/dev/null', 'error_log': '/dev/null', 'environment': environment, 'log_level': 'debug'})() if model is not None: setattr(args, 'model', model) s = kimchi.server.Server(args) t = threading.Thread(target=s.start) t.setDaemon(True) t.start() cherrypy.engine.wait(cherrypy.engine.states.STARTED) return s def silence_server(): """ Silence server status messages on stdout """ cherrypy.config.update({"environment": "embedded"}) def running_as_root(): return os.geteuid() == 0 def _request(conn, path, data, method, headers): if headers is None: headers = {'Content-Type': 'application/json', 'Accept': 'application/json'} if 'AUTHORIZATION' not in headers.keys(): user, pw = kimchi.mockmodel.fake_user.items()[0] hdr = "Basic " + base64.b64encode("%s:%s" % (user, pw)) headers['AUTHORIZATION'] = hdr conn.request(method, path, data, headers) return conn.getresponse() def request(host, port, path, data=None, method='GET', headers=None): # verify if HTTPSConnection has context parameter if "context" in inspect.getargspec(httplib.HTTPSConnection.__init__).args: context = ssl._create_unverified_context() conn = httplib.HTTPSConnection(host, port, context=context) else: conn = httplib.HTTPSConnection(host, port) return _request(conn, path, data, method, headers) def get_remote_iso_path(): """ Get a remote iso with the right arch from the distro files shipped with kimchi. """ host_arch = os.uname()[4] remote_path = '' with open(os.path.join(paths.conf_dir, 'distros.d', 'fedora.json')) \ as fedora_isos: # Get a list of dicts json_isos_list = json.load(fedora_isos) for iso in json_isos_list: if (iso.get('os_arch')) == host_arch: remote_path = iso.get('path') break return remote_path class FakeUser(User): auth_type = "fake" sudo = True def __init__(self, username): self.user = {} self.user[USER_NAME] = username self.user[USER_GROUPS] = None self.user[USER_ROLES] = dict.fromkeys(tabs, 'user') def get_groups(self): return sorted([group.gr_name for group in grp.getgrall()])[0:3] def get_roles(self): if self.sudo: self.user[USER_ROLES] = dict.fromkeys(tabs, 'admin') return self.user[USER_ROLES] def get_user(self): return self.user @staticmethod def authenticate(username, password, service="passwd"): try: return kimchi.mockmodel.fake_user[username] == password except KeyError, e: raise OperationFailed("KCHAUTH0001E", {'username': 'username', 'code': e.message}) def patch_auth(sudo=True): """ Override the authenticate function with a simple test against an internal dict of users and passwords. """ config.set("authentication", "method", "fake") FakeUser.sudo = sudo def normalize_xml(xml_str): return etree.tostring(etree.fromstring(xml_str, etree.XMLParser(remove_blank_text=True))) def wait_task(task_lookup, taskid, timeout=10): for i in range(0, timeout): task_info = task_lookup(taskid) if task_info['status'] == "running": kimchi_log.info("Waiting task %s, message: %s", taskid, task_info['message']) time.sleep(1) else: return kimchi_log.error("Timeout while process long-run task, " "try to increase timeout value.") # The action functions in model backend raise NotFoundError exception if the # element is not found. But in some tests, these functions are called after # the element has been deleted if test finishes correctly, then NofFoundError # exception is raised and rollback breaks. To avoid it, this wrapper ignores # the NotFoundError. def rollback_wrapper(func, resource, *args): try: func(resource, *args) except NotFoundError: # VM has been deleted already return # This function is used to test storage volume upload. # If we use self.request, we may encode multipart formdata by ourselves # requests lib take care of encode part, so use this lib instead def fake_auth_header(): headers = {'Accept': 'application/json'} user, pw = kimchi.mockmodel.fake_user.items()[0] hdr = "Basic " + base64.b64encode("%s:%s" % (user, pw)) headers['AUTHORIZATION'] = hdr return headers kimchi-1.5.0/ui/000077500000000000000000000000001254252253000133765ustar00rootroot00000000000000kimchi-1.5.0/ui/Makefile.am000066400000000000000000000012641254252253000154350ustar00rootroot00000000000000# # Kimchi # # Copyright IBM, Corp. 2013 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. SUBDIRS = css images js libs pages spice-html5 uidir = $(datadir)/kimchi/ui dist_ui_DATA = robots.txt kimchi-1.5.0/ui/css/000077500000000000000000000000001254252253000141665ustar00rootroot00000000000000kimchi-1.5.0/ui/css/Makefile.am000066400000000000000000000014151254252253000162230ustar00rootroot00000000000000# # Kimchi # # Copyright IBM, Corp. 2013 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. EXTRA_DIST = theme-default cssdir = $(datadir)/kimchi/ui/css dist_css_DATA = theme-default.min.css theme-default.min.css: theme-default/*.css cat $^ > $@ CLEANFILES = theme-default.min.css kimchi-1.5.0/ui/css/theme-default/000077500000000000000000000000001254252253000167125ustar00rootroot00000000000000kimchi-1.5.0/ui/css/theme-default/about.css000066400000000000000000000012361254252253000205400ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ .about-window { width: 350px; height: 300px; } kimchi-1.5.0/ui/css/theme-default/button.css000066400000000000000000000414351254252253000207460ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2015 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* Generated at http://colorzilla.com/gradient-editor/ */ .btn { display: inline-block; height: 42px; margin: 3px; vertical-align: top; border: 1px solid #aaa; -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; -moz-box-sizing: content-box; box-sizing: content-box; box-shadow: -2px -2px 2px #eaeaea, 2px 2px 2px #fff, 3px 3px 3px white inset, -3px -3px 3px rgba(0, 0, 0, .25) inset; background: #ffffff; background: -moz-linear-gradient(top, #ffffff 0%, #e5e5e5 100%); background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ffffff), color-stop(100%, #e5e5e5)); background: -webkit-linear-gradient(top, #ffffff 0%, #e5e5e5 100%); background: -o-linear-gradient(top, #ffffff 0%, #e5e5e5 100%); background: -ms-linear-gradient(top, #ffffff 0%, #e5e5e5 100%); background: linear-gradient(to bottom, #ffffff 0%, #e5e5e5 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e5e5e5', GradientType=0); line-height: 42px; color: #333; font-size: 13px; text-shadow: -1px -1px 1px #aaa, 1px 1px 1px #fff; text-align: center; text-overflow: ellipsis; white-space: nowrap; cursor: pointer; } .btn[disabled] { opacity: 0.3; } .btn:not([disabled]):hover { box-shadow: -2px -2px 2px #dadada, 2px 2px 2px #fff, 3px 3px 3px white inset, -3px -3px 3px rgba(0, 0, 0, .25) inset; background: #d5d5d5; background: -moz-linear-gradient(top, #d5d5d5 0%, #eeeeee 100%); background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #d5d5d5), color-stop(100%, #eeeeee)); background: -webkit-linear-gradient(top, #d5d5d5 0%, #eeeeee 100%); background: -o-linear-gradient(top, #d5d5d5 0%, #eeeeee 100%); background: -ms-linear-gradient(top, #d5d5d5 0%, #eeeeee 100%); background: linear-gradient(to bottom, #d5d5d5 0%, #eeeeee 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#d5d5d5', endColorstr='#eeeeee', GradientType=0); } .btn:not([disabled]):active { box-shadow: -2px -2px 2px #eaeaea, 2px 2px 2px #fff, 3px 3px 3px rgba(0, 0, 0, .25) inset, -3px -3px 3px white inset; background: #ffffff; background: -moz-linear-gradient(top, #e5e5e5 0%, #ffffff 100%); background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #e5e5e5), color-stop(100%, #ffffff)); background: -webkit-linear-gradient(top, #e5e5e5 0%, #ffffff 100%); background: -o-linear-gradient(top, #e5e5e5 0%, #ffffff 100%); background: -ms-linear-gradient(top, #e5e5e5 0%, #ffffff 100%); background: linear-gradient(to bottom, #e5e5e5 0%, #ffffff 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#e5e5e5', endColorstr='#ffffff', GradientType=0); } .btn.loading { box-shadow: none; cursor: default; } .btn.loading .icon { background: url(../images/theme-default/icon-load.png) center center no-repeat; } .btn.pause-gray .icon { background: url(../images/theme-default/ac22_pause_grey.png) center center no-repeat; } .btn.resume-gray .icon { background: url(../images/theme-default/ac24_resume_grey.png) center center no-repeat; } .btn .text { padding: 0 10px; } .btn .icon { display: block; width: 42px; height: 42px; } .btn.dropdown { text-align: left; position: relative; padding-right: 25px; } .btn.dropdown .arrow { position: absolute; width: 15px; height: 42px; line-height: 42px; top: 0; right: 10px; background: url(../images/theme-default/arrow-down-black.png) no-repeat center center; right: 10px; } .btn .input { margin-left: 10px; } /* Generated at http://colorzilla.com/gradient-editor/ */ .btn-tool { display: inline-block; height: 38px; margin: 6px 3px; vertical-align: top; -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; -moz-box-sizing: content-box; box-sizing: content-box; box-shadow: -1px -1px 1px #777, 1px 1px 1px #eee, 2px 2px 2px #ddd inset, -3px -3px 3px rgba(0, 0, 0, .25) inset; background: #f3f3f3; background: -moz-linear-gradient(top, #f3f3f3 0%, #dddddd 50%, #d8d8d8 51%, #cccccc 100%); background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f3f3f3), color-stop(50%, #dddddd), color-stop(51%, #d8d8d8), color-stop(100%, #cccccc)); background: -webkit-linear-gradient(top, #f3f3f3 0%, #dddddd 50%, #d8d8d8 51%, #cccccc 100%); background: -o-linear-gradient(top, #f3f3f3 0%, #dddddd 50%, #d8d8d8 51%, #cccccc 100%); background: -ms-linear-gradient(top, #f3f3f3 0%, #dddddd 50%, #d8d8d8 51%, #cccccc 100%); background: linear-gradient(to bottom, #f3f3f3 0%, #dddddd 50%, #d8d8d8 51%, #cccccc 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f3f3f3', endColorstr='#cccccc', GradientType=0); overflow: hidden; cursor: pointer; } .btn-tool:hover { box-shadow: -1px -1px 1px #777, 1px 1px 1px #eee, 2px 2px 2px rgba(0, 0, 0, .25) inset, -3px -3px 3px rgba(0, 0, 0, .25) inset; } /* Generated at http://colorzilla.com/gradient-editor/ */ .btn-tool.left,.btn-tool.right { -webkit-border-radius: 0; -moz-border-radius: 0; border-radius: 0; background: #dddddd; background: -moz-linear-gradient(top, #dddddd 0%, #999999 100%); background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #dddddd), color-stop(100%, #999999)); background: -webkit-linear-gradient(top, #dddddd 0%, #999999 100%); background: -o-linear-gradient(top, #dddddd 0%, #999999 100%); background: -ms-linear-gradient(top, #dddddd 0%, #999999 100%); background: linear-gradient(to bottom, #dddddd 0%, #999999 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#dddddd', endColorstr='#999999', GradientType=0); } .btn-tool:active,.btn-tool.active { box-shadow: -1px -1px 1px #777, 1px 1px 1px #eee, 3px 3px 3px rgba(0, 0, 0, .35) inset; } .btn-tool.left { -webkit-border-top-left-radius: 5px; -moz-border-top-left-radius: 5px; border-top-left-radius: 5px; -webkit-border-bottom-left-radius: 5px; -moz-border-bottom-left-radius: 5px; border-bottom-left-radius: 5px; } .btn-tool.right { -webkit-border-top-right-radius: 5px; -moz-border-top-right-radius: 5px; border-top-right-radius: 5px; -webkit-border-bottom-right-radius: 5px; -moz-border-bottom-right-radius: 5px; border-bottom-right-radius: 5px; } .btn-tool .icon { display: block; width: 48px; height: 38px; } .icon.reset { background: url(../images/theme-default/icon-reset.png) center center no-repeat; } .icon.power-up { background: url(../images/theme-default/icon-power-up.png) center center no-repeat; } .icon.power-down { background: url(../images/theme-default/icon-power-down.png) center center no-repeat; } .icon.pause { background: url(../images/theme-default/ac22_pause.png) center center no-repeat; } .icon.resume { background: url(../images/theme-default/ac24_resume.png) center center no-repeat; } .icon.search { background: url(../images/theme-default/icon-search.png) no-repeat center center; } .icon.sort { background: url(../images/theme-default/icon-sort.png) no-repeat center center; } .icon.design { background: url(../images/theme-default/icon-design.png) no-repeat center center; } .icon.list { background: url(../images/theme-default/icon-list.png) no-repeat center center; } .icon.detail { background: url(../images/theme-default/icon-detail.png) no-repeat center center; } .icon.add { line-height: 32px; text-align: center; text-shadow: -1px -1px 1px #aaa, 1px 1px 1px #eee; font-size: 38px; font-weight: bold; color: #7cae0a; } .icon.tree { width: 42px; background: url(../images/theme-default/icon-tree.png) no-repeat center center; } /* Generated at http://colorzilla.com/gradient-editor/ */ .btn-tool.tree { width: 42px; margin: 5px 10px; background: #ffffff; background: -moz-linear-gradient(top, #ffffff 0%, #e5e5e5 100%); background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ffffff), color-stop(100%, #e5e5e5)); background: -webkit-linear-gradient(top, #ffffff 0%, #e5e5e5 100%); background: -o-linear-gradient(top, #ffffff 0%, #e5e5e5 100%); background: -ms-linear-gradient(top, #ffffff 0%, #e5e5e5 100%); background: linear-gradient(to bottom, #ffffff 0%, #e5e5e5 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e5e5e5', GradientType=0); box-shadow: -1px -1px 1px #03385c, 1px 1px 1px #09F, 3px 3px 3px white inset, -3px -3px 3px rgba(0, 0, 0, .25) inset; } .btn-select { display: inline-block; position: relative; height: 30px; padding-right: 20px; vertical-align: top; -webkit-border-radius: 5px; -moz-border-radius: 5px; background: #fff; box-shadow: -1px -1px 1px #666, 1px 1px 1px #fff, 1px 1px 1px rgba(0, 0, 0, .15) inset; font-size: 13px; line-height: 30px; text-align: left; cursor: pointer; } .btn-select .input { border: 0 solid #CCCCCC; margin-right: 10px; font-size: 16px; height: 30px; line-height: 30px; width: 100%; position: absolute; padding: 0 5px; } .btn-select input.invalid-field { border: 1px solid #FF4444; } .btn-select .arrow { position: absolute; width: 15px; height: 30px; line-height: 30px; top: 0; right: 5px; background: url(../images/theme-default/arrow-down-black.png) no-repeat center center; } /* Generated at http://colorzilla.com/gradient-editor/ */ .button-big { display: block; margin-bottom: 10px; border: 1px solid #ccc; box-shadow: -1px -1px 1px #ccc, 1px 1px 1px #eee; text-shadow: -1px -1px 1px #ccc, 1px 1px 1px #fff; -webkit-border-radius: 05px; -moz-border-radius: 05px; border-radius: 05px; background: #ffffff; background: -moz-linear-gradient(top, #ffffff 0%, #e5e5e5 100%); background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ffffff), color-stop(100%, #e5e5e5)); background: -webkit-linear-gradient(top, #ffffff 0%, #e5e5e5 100%); background: -o-linear-gradient(top, #ffffff 0%, #e5e5e5 100%); background: -ms-linear-gradient(top, #ffffff 0%, #e5e5e5 100%); background: linear-gradient(to bottom, #ffffff 0%, #e5e5e5 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e5e5e5', GradientType=0); text-align: center; font-size: 13px; line-height: 38px; width: 100%; } .button-big:not([disabled]):hover { box-shadow: -1px -1px 1px #bbb, 1px 1px 1px #ddd; background: #eeeeee; background: -moz-linear-gradient(top, #eeeeee 0%, #d5d5d5 100%); background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #eeeeee), color-stop(100%, #d5d5d5)); background: -webkit-linear-gradient(top, #eeeeee 0%, #d5d5d5 100%); background: -o-linear-gradient(top, #eeeeee 0%, #d5d5d5 100%); background: -ms-linear-gradient(top, #eeeeee 0%, #d5d5d5 100%); background: linear-gradient(to bottom, #eeeeee 0%, #d5d5d5 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#d5d5d5', GradientType=0); } .button-big:not([disabled]):active { box-shadow: -1px -1px 1px #eee, 1px 1px 1px #ccc, 2px 2px 2px #ccc inset, -2px -2px 2px #aaa inset; background: -moz-linear-gradient(top, #e5e5e5 0%, #ffffff 100%); background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #e5e5e5), color-stop(100%, #ffffff)); background: -webkit-linear-gradient(top, #e5e5e5 0%, #ffffff 100%); background: -o-linear-gradient(top, #e5e5e5 0%, #ffffff 100%); background: -ms-linear-gradient(top, #e5e5e5 0%, #ffffff 100%); background: linear-gradient(to bottom, #e5e5e5 0%, #ffffff 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#e5e5e5', endColorstr='#ffffff', GradientType=0); } /* Generated at http://colorzilla.com/gradient-editor/ */ .button-big.red:not([disabled]) { text-shadow: -1px -1px 1px #9e0505, 1px 1px 1px #fc5d4c; border: 1px solid #b10f14; background: #ff3019; background: -moz-linear-gradient(top, #ff3019 0%, #cf0404 100%); background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ff3019), color-stop(100%, #cf0404)); background: -webkit-linear-gradient(top, #ff3019 0%, #cf0404 100%); background: -o-linear-gradient(top, #ff3019 0%, #cf0404 100%); background: -ms-linear-gradient(top, #ff3019 0%, #cf0404 100%); background: linear-gradient(to bottom, #ff3019 0%, #cf0404 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3019', endColorstr='#cf0404', GradientType=0); color: #fff; } .button-big.red:not([disabled]):hover { background: #ef2009; background: -moz-linear-gradient(top, #ef2009 0%, #bf0404 100%); background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ef2009), color-stop(100%, #bf0404)); background: -webkit-linear-gradient(top, #ef2009 0%, #bf0404 100%); background: -o-linear-gradient(top, #ef2009 0%, #bf0404 100%); background: -ms-linear-gradient(top, #ef2009 0%, #bf0404 100%); background: linear-gradient(to bottom, #ef2009 0%, #bf0404 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ef2009', endColorstr='#bf0404', GradientType=0); color: #fff; } .button-big.red:not([disabled]):active { background: -moz-linear-gradient(top, #cf0404 0%, #ff3019 100%); background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #cf0404), color-stop(100%, #ff3019)); background: -webkit-linear-gradient(top, #cf0404 0%, #ff3019 100%); background: -o-linear-gradient(top, #cf0404 0%, #ff3019 100%); background: -ms-linear-gradient(top, #cf0404 0%, #ff3019 100%); background: linear-gradient(to bottom, #cf0404 0%, #ff3019 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#cf0404', endColorstr='#ff3019', GradientType=0); } .button-big.disable { display: none; } .btn-normal { display: inline-block; height: 38px; margin: 9px 3px; vertical-align: top; background: #06F; line-height: 38px; padding: 0 20px; color: #EEE; border-radius: 8px; font-size: 13px; } .btn-normal:not([disabled]):hover { background: #04D; } .btn-normal:not([disabled]):active { box-shadow: -1px -1px 1px #eee, 1px 1px 1px #ccc, 2px 2px 2px #ccc inset, -2px -2px 2px #aaa inset; background: -moz-linear-gradient(top, #04d 0%, #06f 100%); background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #04d), color-stop(100%, #06f)); background: -webkit-linear-gradient(top, #04d 0%, #ff3019 100%); background: -o-linear-gradient(top, #04d 0%, #06f 100%); background: -ms-linear-gradient(top, #04d 0%, #06f 100%); background: linear-gradient(to bottom, #04d 0%, #06f 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#04d', endColorstr='#06f', GradientType=0); } .btn-normal[disabled] { background-color: silver; } .btn-group { float: right; padding: 0 10px; } .btn-small { display: inline-block; height: 25px; margin: 6px 3px; vertical-align: top; background: #06F; line-height: 25px; padding: 0 10px; color: #EEE; border-radius: 8px; font-size: 10px; } kimchi-1.5.0/ui/css/theme-default/circleGauge.css000066400000000000000000000013241254252253000216360ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ .circleGauge { position: relative; margin: 30px 10px 10px 10px; width: 70px; height: 70px; } kimchi-1.5.0/ui/css/theme-default/error.css000066400000000000000000000050241254252253000205560ustar00rootroot00000000000000/* * Kimchi * * Copyright IBM, Corp. 2013-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ .error-background { background: linear-gradient(to bottom, #4A4A4A 0%, #272727 100%) repeat scroll 0 0 transparent; border-top: 1px solid #6B6868; color: #EEEEEE; text-shadow: -1px -1px 1px #000000, 1px 1px 1px #555555; width: 1280px; margin: 0 auto; background-position: center center; } .error-msg { width: 1280px; margin: 0 auto; } .error-icon { background: linear-gradient(to bottom, #FFFFFF 0%, #E5E5E5 100%) repeat scroll 0 0 transparent; border: 1px solid #CCCCCC; border-radius: 8px 8px 8px 8px; color: #333333; text-shadow: -1px -1px 1px #CCCCCC, 1px 1px 1px #FFFFFF; } .error-text { margin: 10px 0 10px 10px; } #error-404-window { height: 100%; overflow: hidden; width: 100%; box-shadow: none; -webkit-border-radius: 0; -moz-border-radius: 0; border-radius: 0; border: none; } #error-404-window .content { margin: 0; } .error-msg>a.btn-normal { background: black; border-radius: 0 0 36px; box-shadow: -2px -2px 2px #eee, 2px 2px 2px #ccc; color: white; font-size: 18px; height: 36px; padding-right: 36px; } .error-msg>a.btn-normal:hover { background: #333; } .error-msg>a.btn-normal:active { box-shadow: -1px -1px 1px #eee, 1px 1px 1px #ccc, 1px 1px 1px #ccc inset, -1px -1px 1px #aaa inset; background: -moz-linear-gradient(top, black 0%, #888 100%); background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, black), color-stop(100%, #888)); background: -webkit-linear-gradient(top, black 0%, #888 100%); background: -o-linear-gradient(top, black 0%, #888 100%); background: -ms-linear-gradient(top, black 0%, #888 100%); background: linear-gradient(to bottom, black 0%, #888 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='black', endColorstr='#888', GradientType=0); } kimchi-1.5.0/ui/css/theme-default/form.css000066400000000000000000000024031254252253000203660ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ .form-section { padding: 10px; } .form-section>h2 { font-size: 14px; padding: 5px; } .form-section .field { padding: 5px 5px 5px 20px; overflow: hidden; } .form-section .field .text-help { font-size: 12px; color: #333; margin: 0 0 5px 5px; } .form-section .field input.text { border: 1px solid #ccc; font-size: 16px; height: 30px; line-height: 30px; padding: 0 5px; } .text-help { font-size: 12px; color: #333; margin: 0 0 5px 5px; } input.invalid-field[type="text"] { border-color: #FF4444!important; } input.invalid-field[type="text"][disabled] { border-color: #666666!important; } kimchi-1.5.0/ui/css/theme-default/framework.css000066400000000000000000000014441254252253000214240ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ body { background: url(../images/theme-default/bg.png); } .tmpl-html { display: none; } .container { margin: 0 auto; width: 1024px; } .hidden { display: none; } kimchi-1.5.0/ui/css/theme-default/grid.css000066400000000000000000000123071254252253000203540ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ .resizing { cursor: col-resize; } .grid { background: white; border: 1px solid transparent; border-radius: 2px; position: relative; } .grid-caption, .grid-toolbar, .grid-content, .grid-footer { display: block; } .grid-caption { background: #5af; color: white; font-family: arial; font-weight: bold; padding: 0 5px; } .grid-caption, .grid-toolbar { height: 24px; line-height: 24px; overflow: hidden; } .grid-toolbar-button { background: none; border: 1px solid transparent; border-radius: 4px; height: 24px; padding: 0 5px; vertical-align: top; } .grid-toolbar-button:not([disabled]):hover { background: #e0e0e0; border-color: #eee; } .grid-content { bottom: 0; overflow: hidden; position: absolute; width: 100%; } .grid-header, .grid-body { overflow: hidden; width: 100%; } .grid-header { background: #f0f0f0; background: -moz-linear-gradient(top, #f0f0f0 0%, #ddd 50%, #d0d0d0 51%, #e0e0e0 100%); background: -webkit-linear-gradient(top, #f0f0f0 0%, #ddd 50%, #d0d0d0 51%, #e0e0e0 100%); background: -o-linear-gradient(top, #f0f0f0 0%, #ddd 50%, #d0d0d0 51%, #e0e0e0 100%); background: -ms-linear-gradient(top, #f0f0f0 0%, #ddd 50%, #d0d0d0 51%, #e0e0e0 100%); background: linear-gradient(to bottom, #f0f0f0 0%, #ddd 50%, #d0d0d0 51%, #e0e0e0 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f0f0f0', endColorstr='#e0e0e0', GradientType=0); border-bottom: 1px solid #ccc; border-top: 1px solid #ccc; height: 29px; } .grid-frozen-header-view, .grid-header-view, .grid-frozen-body-view, .grid-body-view { box-sizing: border-box; -moz-box-sizing: border-box; overflow: hidden; position: absolute; vertical-align: top; } .grid-frozen-header-view, .grid-header-view { top: 0; } .grid-frozen-header-view, .grid-header-view, .grid-frozen-body-view { } .grid-frozen-header-view { z-index: 3; } .grid-header-view { z-index: 2; } .grid-frozen-body-view { z-index: 1; } .grid-frozen-body-view, .grid-body-view { bottom: 0; top: 30px; } .grid-header-view, .grid-body-view { right: 0; } .grid-frozen-header-view, .grid-header-view { } .grid-header-wrapper { width: 10000px; } .grid-frozen-body-wrapper { padding-bottom: 30px; } .grid-body-view { overflow: auto; } .grid table.grid-frozen-header-container, .grid table.grid-header-container, .grid table.grid-frozen-body-container, .grid table.grid-body-container { box-sizing: border-box; } .grid th, .grid td { -moz-box-sizing: border-box; box-sizing: border-box; border: 1px solid #ccc; height: 30px; } .grid .cell-text-wrapper { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .grid th { border-bottom: 0 none; border-top: 0 none; } .grid-body { cursor: default; } .grid-body tr.hover { background: #bdf; } .grid-body tr.selected { background: #b0d0f0; background: -moz-linear-gradient(top, #b0d0f0 0%, #acf 50%, #a0c0ff 51%, #b0d0f0 100%); background: -webkit-linear-gradient(top, #b0d0f0 0%, #acf 50%, #a0c0ff 51%, #b0d0f0 100%); background: -o-linear-gradient(top, #b0d0f0 0%, #acf 50%, #a0c0ff 51%, #b0d0f0 100%); background: -ms-linear-gradient(top, #b0d0f0 0%, #acf 50%, #a0c0ff 51%, #b0d0f0 100%); background: linear-gradient(to bottom, #b0d0f0 0%, #acf 50%, #a0c0ff 51%, #b0d0f0 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#b0d0f0', endColorstr='#bef', GradientType=0); } .grid-resizer-leftmost, .grid-resizer { border-left: 1px solid #5af; position: absolute; top: 0; width: 0; z-index: 4; } .grid-mask { background: rgba(190, 190, 190, .9); bottom: 0; left: 0; position: absolute; right: 0; z-index: 5; } .grid-loading { bottom: 0; height: 68px; left: 0; margin: auto; position: absolute; right: 0; text-align: center; top: 0; width: 49px; white-space: nowrap; } .grid-loading-icon { background: url("../images/theme-default/kimchi-loading.gif") no-repeat left top; height: 48px; width: 49px; } .grid-message { background: white; box-sizing: border-box; bottom: 0; left: 0; overflow: auto; padding: .2em .5em; position: absolute; right: 0; z-index: 5; } .grid-message-text { line-height: 25px; } .retry-button { margin: 0 1em; } kimchi-1.5.0/ui/css/theme-default/guest-edit.css000066400000000000000000000177501254252253000215100ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2015 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #guest-edit-window { font-size: 13px; height: 420px; width: 820px; } #guest-edit-tabs { background: transparent; border: none; height: 100%; padding: 0; } #form-guest-edit-general { padding: 1em; } #form-guest-edit-general .edit-general-inline { display: inline-block; } #form-guest-edit-storage input[readonly] { background: none; border-color: transparent; text-overflow: ellipsis; } .guest-edit-fieldset { padding-right: 0; } .guest-edit-wrapper-label { height: 38px; line-height: 38px; margin-top: 5px; vertical-align: top; min-width: 100px; } #form-guest-edit-storage .guest-edit-wrapper-label { width: 60px; } .guest-edit-wrapper-controls { width: 470px; } #form-guest-edit-storage .guest-edit-wrapper-controls { width: 486px; } .guest-edit-wrapper-controls input[type="text"] { font-size: 16px; height: 38px; background: #fff; -webkit-border-radius: 5px; border-radius: 5px; box-shadow: 2px 2px 2px #eee inset; border-top: 1px solid #bbb; border-left: 1px solid #bbb; padding-left: 10px; width: 450px; } .guest-edit-wrapper-controls input[type="text"][disabled] { color: #bbb; background-color: #fafafa; cursor: not-allowed; } .guest-edit-cdrom-row-container { max-height: 180px; overflow: auto; } .guest-edit-cdrom-row-container input[type="text"] { width: 400px; } #form-guest-edit-storage .header, .guest-edit-snapshot .header, .guest-edit-interface .header, #form-guest-edit-permission .ldap .header { margin-bottom: 8px; padding-bottom: 2px; font-weight: bold; border-bottom: 1px solid #999999; overflow: hidden; } #form-guest-edit-storage .body .item, .guest-edit-snapshot .body .item, .guest-edit-snapshot .task .item, .guest-edit-interface .body .item { margin: 5px 0; } #form-guest-edit-storage .cell, .guest-edit-interface .cell { display: inline-block; width: 200px; } .guest-edit-snapshot .cell { display: inline-block; } .guest-edit-snapshot .sel { width: 25px; vertical-align: top; } .guest-edit-snapshot .icon { background: url('../../images/theme-default/kimchi-loading15x15.gif') no-repeat; display: block; width: 16px; height: 16px; vertical-align: middle; margin-left: 2px; } .guest-edit-snapshot .name { width: 400px; } .guest-edit-snapshot .created { width: 270px; } #form-guest-edit-storage .cell.dev { width: 60px; } #form-guest-edit-storage .cell.path { width: 440px; } #form-guest-edit-storage .cell.dev input, #form-guest-edit-storage .cell.path input { box-sizing: border-box; width: 100%; } .guest-edit-interface .body select { width: 180px; padding: 0px; } #form-guest-edit-storage .action-area, .guest-edit-snapshot .action-area, .guest-edit-interface .action-area { float: right; } #form-guest-edit-storage .action-area { line-height: 24px; } #form-guest-edit-storage button, .guest-edit-snapshot button, .guest-edit-interface button { width: 20px; height: 20px; } #form-guest-edit-storage .body button:not(:last-child), .guest-edit-interface .body button:not(:last-child) { margin-right: 2px; } .guest-edit-snapshot .hide, .guest-edit-interface .hide { display: none!important; } .guest-edit-permission .pam { height: 220px; padding: 5px 10px!important; } .guest-edit-permission .hide { display: none; } .guest-edit-permission .pam .column { display: inline-block; vertical-align: top; } .guest-edit-permission .pam .title { margin-bottom: 3px; } .guest-edit-permission .pam input[type="text"] { margin-bottom: 3px; font-size: 12px; width: 97%; } .guest-edit-permission .pam .body { border: 1px solid #999999; font-size: 12px; padding: 1px; height: 192px; overflow: auto; } .guest-edit-permission .pam .body .head { margin-bottom: 3px; font-weight: bold; background: linear-gradient(to bottom, #E5E5E5 0%, #C4C4C4 100%) repeat scroll 0 0 transparent; } .guest-edit-permission .pam .body .item { padding: 2px 3px; margin-bottom: 1px; cursor: pointer; } .guest-edit-permission .pam .body .item:hover { background-color: #AAAAAA; } .guest-edit-permission .pam .body .item-picked { background-color: #BBBBBB; } .guest-edit-permission .pam .body .item .icon { display: inline-block; height: 15px; width: 15px; vertical-align: bottom; } .guest-edit-permission .pam .body .item .user-icon { background: url('/images/theme-default/user.png') no-repeat scroll; background-size: 15px 15px; } .guest-edit-permission .pam .body .item .group-icon { background: url('/images/theme-default/group.png') no-repeat scroll; background-size: 15px 15px; } .guest-edit-permission .pam .body .column-user { width: 48%; } .guest-edit-permission .pam .body .column-group { width: 50%; } .guest-edit-permission .pam .control { width: 5%; } .guest-edit-permission .pam .control button { width: 26px; margin-left: 7px; } .guest-edit-permission .pam .control button:first-child { margin-top: 110px; margin-bottom: 2px; } .guest-edit-permission .pam .control .ui-button-text-only .ui-button-text { padding: 2px 8px; } .guest-edit-permission .pam .avail { width: 46%; } .guest-edit-permission .pam .selected { width: 46%; float: right; } #form-guest-edit-permission .ldap .body .item { margin: 8px 0; } #form-guest-edit-permission .ldap .cell { width: 250px; } #form-guest-edit-permission .ldap .action-area { float: right; line-height: 24px; } #form-guest-edit-permission .ldap button { width: 20px; height: 20px; } #form-guest-edit-permission input[type="text"] { width: 300px; } #form-guest-edit-permission .ldap .header button { margin-bottom: 1px; } #form-guest-edit-permission .ldap .checked { border-color: red; border-style: solid; border-width: 1px; } #form-guest-edit-permission .ldap .checked.hide { display: none; } .guest-edit-pci { height: 79%; overflow: auto; font-size: 12px; } .guest-edit-pci .guest-scroll-indent { width: 783px; } .guest-edit-pci .filter { height: 35px; margin-right: 5px; overflow: hidden; } .guest-edit-pci .group { float: right; } .guest-edit-pci .filter .control { border: 1px solid #AAAAAA; font-size: 12px; background-color: white; } .guest-edit-pci .filter select { border-right: 0px!important; border-radius: 7px 0px 0px 7px; padding: 2px 2px 2px 7px; width: 100px; height: 24px; } .guest-edit-pci .filter select option { padding-left: 7px; } .guest-edit-pci .filter input { border-radius: 0px 7px 7px 0px; padding: 3px 3px 3px 10px; width: 200px; height: 16px; font-style: italic; } .guest-edit-pci .header { margin-bottom: 8px; padding-bottom: 2px; font-weight: bold; border-bottom: 1px solid #999999; } .guest-edit-pci .item { margin-bottom: 4px; overflow: hidden; } .guest-edit-pci .cell { display: inline-block; vertical-align: middle; margin-right: 10px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .guest-edit-pci .item button { width: 20px; height: 20px; float: right; } .guest-edit-pci .name { width: 18%; max-width: 18%; } .guest-edit-pci .product { width: 45%; max-width: 45%; } .guest-edit-pci .vendor { width: 25%; max-width: 25%; } kimchi-1.5.0/ui/css/theme-default/guest-storage-add.css000066400000000000000000000035721254252253000227520ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #guest-storage-add-window { font-size: 13px; height: 600px; width: 700px; } .guest-storage-add-fieldset { padding: 1em; } #guest-storage-add-window .btn { width: 587px; } #form-guest-storage-add .form-section .field { overflow: visible; } #guest-storage-add-window input[type="text"] { font-size: 16px; height: 38px; background: #fff; -webkit-border-radius: 5px; border-radius: 5px; box-shadow: 2px 2px 2px #eee inset; border-top: 1px solid #bbb; border-left: 1px solid #bbb; padding-left: 10px; width: 600px; } #guest-storage-add-window input[type="text"][disabled] { color: #bbb; background-color: #fafafa; cursor: not-allowed; } .guest-storage-add-wrapper-label, .guest-storage-add-wrapper-controls { display: inline-block; } .guest-storage-add-wrapper-label { height: 38px; line-height: 38px; margin-top: 5px; vertical-align: top; width: 80px; } .guest-storage-add-wrapper-controls { width: 470px; } #vm-storage-button-add[disabled] { background: #c0c0c0; color: #ddd; padding-left: 26px; } #vm-storage-button-add.loading[disabled] { background: url("../../images/theme-default/loading.gif") 7px center no-repeat #c0c0c0; color: #ddd; padding-left: 26px; } kimchi-1.5.0/ui/css/theme-default/host.css000066400000000000000000000133071254252253000204050ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ .host-panel { font-size: 12px; margin-bottom: 100px; } .host-panel .logo-container, .host-panel .info-container, .host-panel .section-label, .host-panel .section-value { display: inline-block; vertical-align: top; } .host-panel .section-label { display: inline-block; margin-right: 1em; vertical-align: top; } .host-panel .logo { background: url("../images/icon-vm.png") no-repeat left top; height: 128px; width: 128px; } .host-panel .hostname { text-decoration: underline; } .host-panel .action-panel { margin-top: 2em; padding-left: 10px; } .host-panel .button-icon { background: url("../images/theme-default/host-icon-sprite.png") no-repeat left top; display: inline-block; height: 12px; width: 12px; } .host-panel .action-icon-stop { background-position: -14px 0; } .host-panel .action-icon-restart { background-position: -28px 0; } .host-panel .action-icon-download { background-position: -42px 0; } .host-panel .action-icon-connect { background-position: -56px 0; } .host-panel .action-icon-add { background-position: -70px 0; } .host-panel .action-icon-edit { background-position: -84px 0; } .host-panel .action-icon-remove { background-position: -98px 0; } .host-panel button:disabled .action-icon-start { background-position: 0 -14px; } .host-panel button:disabled .action-icon-stop { background-position: -14px -14px; } .host-panel button:disabled .action-icon-restart { background-position: -28px -14px; } .host-panel button:disabled .action-icon-download { background-position: -42px -14px; } .host-panel button:disabled .action-icon-connect { background-position: -56px -14px; } .host-panel button:disabled .action-icon-add { background-position: -70px -14px; } .host-panel button:disabled .action-icon-edit { background-position: -84px -14px; } .host-panel button:disabled .action-icon-remove { background-position: -98px -14px; } .host-panel .info-container { padding-top: 16px; width: 890px; } .host-panel .section-header { background: #EEE; border-radius: 5px; cursor: pointer; line-height: 2em; margin: 1em 0 1em; padding-left: 6px; } .host-panel .section-header:hover { background: #06f; color: white; } .host-panel .section-content { padding-left: 1em; } .host-panel .section-header .arrow { border-color: transparent; border-style: solid; display: inline-block; margin-right: 6px; width: 0; } .host-panel .section-header[aria-expanded="true"] .arrow { border-top-color: black; border-width: 8px 4px 0; border-bottom: none; } .host-panel .section-header[aria-expanded="true"]:hover .arrow { border-top-color: white; } .host-panel .section-header[aria-expanded="false"] .arrow { border-left-color: black; border-right: none; border-width: 4px 0 4px 8px; } .host-panel .section-header[aria-expanded="false"]:hover .arrow { border-left-color: white; } .host-panel .section-row { line-height: 1.6em; margin-bottom: 1em; } .host-panel .section-label { width: 100px; } #frequency-textbox { width: 20px; } #container-chart-cpu, #container-chart-memory, #container-chart-disk-io, #container-chart-network-io { border: 1px solid white; box-shadow: 2px 2px 2px gray, 2px -2px 2px gray, -2px -2px 2px gray, -2px 2px 2px gray; height: 100px; width: 500px; } #container-chart-disk-io .disk-write, #container-chart-network-io .network-sent { stroke: #f80; } /* Debug Report */ .cell-text-wrapper { margin-left: 10px; } .host-panel #available-reports-grid { border-color: #ddd; height: 400px; width: 850px; } .host-panel select#available-reports-list { width: 300px; } .host-panel select#available-reports-list option { margin: .2em 1em; } .debug-report-name, .debug-report-time { width: 424px; } #id-debug-img { background: url(../../images/theme-default/kimchi-loading15x15.gif) 12px center no-repeat; padding-left: 23px; } /* End of Debug Report */ /* Software Updates */ .host-panel #software-updates-grid { border-color: #ddd; height: 300px; width: 850px; } .software-update-name, .software-update-repos { width: 224px; } .software-update-version, .software-update-arch { width: 200px; } .host-panel #software-updates-progress-textarea { border: 1px solid #ddd; box-sizing: border-box; height: 100px; padding: .2em .5em; resize: vertical; width: 852px; } /* End of Software Updates */ /* Repository */ .host-panel #repositories-grid { border-color: #ddd; height: 200px; width: 850px; } .host-panel #repositories-grid .repository-id { width: 120px; } .host-panel #repositories-grid .repository-name { width: 640px; } .host-panel #repositories-grid .repository-enabled { width: 88px; } .host-panel #repositories-grid .repository-baseurl.deb { width: 400px; } .host-panel #repositories-grid .repository-enabled.deb { width: 100px; } .host-panel #repositories-grid .repository-gpgcheck.deb { width: 150px; } /* End of Repository */ kimchi-1.5.0/ui/css/theme-default/jquery-ui.custom.css000066400000000000000000000121371254252253000226730ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ .ui-button-primary { border-radius: 8px 8px 8px 8px; } .ui-button-primary.ui-state-default { background: none repeat scroll 0 0 #0066FF; border: 0 none; } .ui-button-primary.ui-state-disabled { background-color: silver; opacity: 1; } .ui-button-primary.ui-state-hover { background: #0044DD; } .ui-button-primary .ui-button-text { padding: 10px 23px; font-size: 13px; color: #EEEEEE; } .ui-button-secondary { border: 1px solid #AAAAAA; border-radius: 5px 5px 5px 5px; cursor: pointer; } .ui-button-secondary.ui-state-default { background: linear-gradient(to bottom, #FFFFFF 0%, #E5E5E5 100%) repeat scroll 0 0 transparent; box-shadow: -2px -2px 2px #EAEAEA, 2px 2px 2px #FFFFFF, 3px 3px 3px white inset, -3px -3px 3px rgba(0, 0, 0, 0.25) inset; } .ui-button-secondary.ui-state-hover { background: linear-gradient(to bottom, #d5d5d5 0%, #eeeeee 100%); box-shadow: -2px -2px 2px #dadada, 2px 2px 2px #fff, 3px 3px 3px white inset, -3px -3px 3px rgba(0, 0, 0, .25) inset; } .ui-button-secondary .ui-button-text { font-size: 13px; color: #333333; text-overflow: ellipsis; text-shadow: -1px -1px 1px #AAAAAA, 1px 1px 1px #FFFFFF; white-space: nowrap; } .ui-button-secondary.ui-button-text-only .ui-button-text { padding: 12px 23px 13px 20px; } .ui-button-secondary.ui-button-text-icon-secondary .ui-button-text { padding: 12px 35px 13px 13px; } .ui-button-secondary .ui-button-icon-secondary { padding-right: 5px; width: 15px; height: 15px; } .ui-menu { background: linear-gradient(to bottom, #EEEEEE 0%, #CCCCCC 10px, #CCCCCC 96%, #A5A5A5 100%) repeat scroll 0 0 transparent; padding: 10px 10px 0; width: 250px; } .ui-menu .ui-menu-item a { background: linear-gradient(to bottom, #FFFFFF 0%, #E5E5E5 100%) repeat scroll 0 0 transparent; border: 1px solid #CCCCCC; border-radius: 5px 5px 5px 5px; box-shadow: -1px -1px 1px #CCCCCC, 1px 1px 1px #EEEEEE; display: block; font-size: 13px; line-height: 38px; margin-bottom: 10px; text-align: center; text-shadow: -1px -1px 1px #CCCCCC, 1px 1px 1px #FFFFFF; width: 96%; } .ui-menu .ui-menu-item a.ui-state-focus { background: linear-gradient(to bottom, #EEEEEE 0%, #D5D5D5 100%) repeat scroll 0 0 transparent; box-shadow: -1px -1px 1px #BBBBBB, 1px 1px 1px #DDDDDD; margin: 0px 0px 10px 0px; } .ui-menu .ui-menu-item a.red:not([disabled]) { background: linear-gradient(to bottom, #FF3019 0%, #CF0404 100%) repeat scroll 0 0 transparent; border: 1px solid #B10F14; color: #FFFFFF; text-shadow: -1px -1px 1px #9E0505, 1px 1px 1px #FC5D4C; } .ui-menu .ui-menu-item a.red:hover:not([disabled]) { background: linear-gradient(to bottom, #EF2009 0%, #BF0404 100%) repeat scroll 0 0 transparent; } .ui-menu .ui-state-disabled { opacity: 1; } .ui-menu .ui-state-disabled a { color: gray; } .ui-widget-overlay { background: url("../images/theme-default/bg-mask.png") repeat scroll 0 0 transparent; opacity: 1; } .ui-dialog { background: none; background-color: #EEEEEE; border: 2px solid #0F71B4; border-radius: 8px; padding: 0px; } .ui-dialog .ui-dialog-titlebar { border: none; border-bottom-left-radius: 0px; border-bottom-right-radius: 0px; background: none; padding: 13px 0px 13px 10px; box-shadow: 0 1px 3px rgba(0,0,0,0.15), 0 -1px 0 rgba(0,0,0,0.05) inset; } .ui-dialog .ui-dialog-title { font-size: 18px; color: #0066CC; } .ui-dialog .ui-dialog-titlebar-close { margin: 4px 0 0; background: none repeat scroll 0 0 #EEEEEE; border: 2px solid #CCCCCC; border-radius: 35px 35px 35px 35px; color: #CCCCCC; cursor: pointer; height: 35px; width: 35px; position: absolute; right: 7px; text-align: center; top: 5px; } .ui-dialog .ui-dialog-titlebar .ui-state-hover { border: 2px solid #444444; color: #444444; } .ui-dialog .ui-dialog-titlebar .ui-button-text { font-size: 24px; font-weight: bold; padding: 0px; text-indent: 0px; } .ui-dialog .ui-dialog-titlebar .ui-button-icon-primary { display: none; } .ui-dialog .ui-dialog-buttonpane { padding: 0px; background-color: transparent; border-width: 0; box-shadow: 0 -1px 1px rgba(0, 0, 0, 0.15); } .ui-dialog .ui-dialog-buttonpane button { cursor: pointer; margin: 0.5em 13px 0.5em 0; } kimchi-1.5.0/ui/css/theme-default/line-chart.css000066400000000000000000000026161254252253000214570ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ .chart-container { background: black; } .line-chart { overflow: hidden; } .line-chart .background { fill: black; } .line-chart text { color: red; font-size: 12px; } .line-chart polyline { fill: none; stroke: #0cf; stroke-width: 2px; } .line-chart line { stroke: white; stroke-width: 1px; } .chart-container, .chart-vaxis-container, .chart-legend-container, .chart-label { display: inline-block; margin-right: 10px; vertical-align: top; } .chart-vaxis-container { width: 80px; } .chart-legend-container .legend-wrapper { margin: 0 5px 5px 0; } .chart-legend-container .legend-icon { margin-right: 5px; width: 20px; } .chart-legend-container .legend-label { } .chart-legend-container .latest-value { margin-left: 25px; } kimchi-1.5.0/ui/css/theme-default/list.css000066400000000000000000000147611254252253000204100ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2015 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ .list-vm { margin: 10px; } /* Generated at http://colorzilla.com/gradient-editor/ */ .list-vm>li { margin-bottom: 10px; background: #ffffff; background: -moz-linear-gradient(top, #ffffff 0%, #e5e5e5 100%); background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ffffff), color-stop(100%, #e5e5e5)); background: -webkit-linear-gradient(top, #ffffff 0%, #e5e5e5 100%); background: -o-linear-gradient(top, #ffffff 0%, #e5e5e5 100%); background: -ms-linear-gradient(top, #ffffff 0%, #e5e5e5 100%); background: linear-gradient(to bottom, #ffffff 0%, #e5e5e5 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e5e5e5', GradientType=0); border: 1px solid #ccc; color: #333; -webkit-border-radius: 8px; -moz-border-radius: 8px; border-radius: 8px; } .list-vm li>* { height: 130px; display: table-cell; vertical-align: top; position: relative; border-left: 1px solid #ccc; border-right: 1px solid #fff; } .list-vm li>*:FIRST-CHILD { border-left: none; } .list-vm li>*:LAST-CHILD { border-right: none; } .list-vm li>.guest-tile{ text-align: center; vertical-align: middle; } .list-vm .handle { display: block; width: 50px; height: 130px; box-sizing: border-box; box-shadow: inset 4px 4px 4px #0289e2, inset -4px -4px 4px #04385d; background: #0b6bad url(../images/theme-default/arrow_out.png) center center no-repeat; border-top-right: 1px solid #CCC; -webkit-border-top-right-radius: 8px; -moz-border-top-right-radius: 8px; border-top-right-radius: 8px; border-bottom-right: 1px solid #CCC; -webkit-border-bottom-right-radius: 8px; -moz-border-bottom-right-radius: 8px; border-bottom-right-radius: 8px; } .list-vm .subtitle { color: #666; font-size: 13px; text-align: center; line-height: 10px; font-weight: bold; } .list-vm .tile .imgload { display: none; } .list-vm .tile.shutoff .imgactive { max-height: 110px; max-width: 170px; height: auto; width: auto; display:inline; border: none; position: relative; } .list-vm .tile.paused .imgactive { max-height: 110px; max-width: 170px; height: auto; width: auto; display:inline; border: none; position: relative; } .list-vm .tile.running .imgactive{ max-height: 110px; max-width: 170px; height: auto; width: auto; display:inline; border: none; cursor: crosshair; cursor: -moz-zoom-in; cursor: -webkit-zoom-in; } .list-vm .tile .overlay { max-height: 110px; max-width: 170px; height: auto; width: auto; position:absolute; bottom:0; right:0; display:none; } .guest-type { width: 257px; } .guest-cpu { width: 91px; } .guest-network { width: 91px; } .guest-storage { width: 91px; } .guest-tile { width: 190px; } .guest-users { width: 93px; } .guest-actions { width: 125px; min-width: 125px; } .guest-handle { width: 50px; } .guest-general { padding: 10px; border-bottom: 1px solid #ccc; width: 237px; } .guest-ip { padding: 0 10px; border-top: 1px solid #fff; } .guest-general .title { color: #666; font-size: 16px; font-weight: normal; height: 25px; line-height: 25px; text-shadow: -1px -1px 1px #ccc, 1px 1px 1px #fff; max-width: 237px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .guest-general .text { font-weight: bold; color: #999; font-size: 11px; text-shadow: -1px -1px 1px #ccc, 1px 1px 1px #fff; } .guest-users .top { border-bottom: 1px solid #ccc; padding: 3px 10px; } .guest-users .bottom { border-top: 1px solid #fff; padding: 3px 10px; } .guest-users .users { height: 45px; line-height: 45px; background: url(../images/theme-default/icon-user.png) left center no-repeat; padding-left: 50px; font-size: 36px; font-weight: bold; } .guest-users .snapshots { height: 40px; line-height: 40px; background: url(../images/theme-default/icon-camera.png) left center no-repeat; padding-left: 50px; font-size: 36px; font-weight: bold; } .guest-users .mini-text { font-size: 11px; font-weight: normal; text-shadow: -1px -1px 1px #ccc, 1px 1px 1px #fff; } .guest-actions .top { padding: 7px 10px; width: 200px; } .guest-actions .top button { display: inline-block; width: 42px; height: 42px; } @-moz-document url-prefix() { .guest-actions .top button span { margin-left: -3px; margin-top: -1px; } } .guest-actions .bottom { padding: 0 10px; } .list-vm .tile { max-width: 170px; max-height: 110px; width: auto; height: auto; margin: 10px; } .list-vm .tile:not(.shutoff) && .tile:not(.paused) img { box-shadow: -1px -1px 2px rgb(0, 0, 0, .25), 3px 3px 3px #fff; } .list-vm .shutoff { position: relative; box-shadow: none !important; } .list-vm .shutoff img { opacity: 0.4; } .list-vm .paused { position: relative; box-shadow: none !important; } .list-vm .paused img { opacity: 0.6; } .list-title { color: #666; font-weight: bold; font-size: 12px; overflow: hidden; margin: 10px; } .list-title li { display: table-cell; padding: 0 1px; } .list-no-result { font-size: 16px; height: 48px; line-height: 48px; text-shadow: -1px -1px 1px #ccc, 1px 1px 1px #fff; padding-left: 10px; } .guest-pending { margin: 10px; } .guest-pending .icon { background: url('../../images/theme-default/kimchi-loading15x15.gif') no-repeat; display: inline-block; width: 20px; height: 20px; vertical-align: middle; } .guest-pending .text { color: #666666; margin-left: 5px; text-shadow: -1px -1px 1px #CCCCCC, 1px 1px 1px #FFFFFF; } kimchi-1.5.0/ui/css/theme-default/login-window.css000066400000000000000000000036451254252253000220510ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #login-window { height: 360px; width: 400px; } #login-window>header>.title-text { front: #000000; font-size: 18px; height: 48px; line-height: 48px; font-weight: bold; text-shadow: -1px -1px 1px #eaeaea, 1px 1px 1px #fff; } #login-window footer #form-language { height: 48px; line-height: 48px; padding-right: 10px; text-align: right; } #login-window .login-panel #form-login { padding: 40px 40px 0; } #login-window>header>.logo { display:inline; margin: 11px 0 0 2px; float: left; width: 25px; height: 25px; background: url(../images/logo.ico) no-repeat center center; } #login-window .login-panel .row { margin-bottom: 28px; } #login-window .login-panel input[type="text"], #login-window .login-panel input[type="password"] { font-size: 18px; height: 40px; padding-left: 10px; padding-right: 10px; width: 290px; } #login-window .login-panel .msg-required { color: red; } #login-window .login-panel button { font-size: 18px; height: 40px; min-width: 160px; float: right; } #login-window .login-panel button[disabled] { background: #888; color: #DDD; } .language { display:inline-block; float:right; margin:11px 10px 0 0; } .i18n-selector { padding:2px 0; background: #FFFBF0; } kimchi-1.5.0/ui/css/theme-default/message.css000066400000000000000000000052411254252253000210520ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #messageField { position: fixed; margin: auto; left: 0; right: 0; top: 0; width: 1024px; max-width: 100%; z-index: 200; } .message { background-color: #FFF68F; position: relative; margin-bottom: 5px; } .message.warn { background-color: #FFF68F; } .message.error { background-color: #FFAEB9; } .message.success { background-color: #90EE90; } .message .close { position: absolute; width: 30px; height: 30px; top: 0; right: 0; color: #545454; font-size: 12px; text-align: center; line-height: 30px; cursor: pointer; } .message .content { padding: 0 30px 0 10px; line-height: 30px; } .confirmbox { position: absolute; margin: auto; left: 0; right: 0; top: 0; bottom: 0; box-shadow: 2px 2px 6px #000; border: 2px solid #0f71b4; -webkit-border-radius: 8px; -moz-border-radius: 8px; border-radius: 8px; background-color: black; box-sizing: border-box; max-width: 100%; max-height: 100%; width: 350px; height: 200px; z-index: 9999; } .confirmbox>footer { position: absolute; left: 0; right: 0; bottom: 0; height: 48px; box-shadow: 0 -1px 1px rgba(0, 0, 0, 0.15); } .confirmbox .title { display: inline-block; padding: 10px 10px 0 10px; line-height: 20px; color: white; } .confirmbox .content { padding: 20px 10px 0px 100px; line-height: 16px; font-size: 13px; color: white; background: url(../images/theme-default/alert.png) no-repeat 20px center; height: 41px; vertical-align: middle; } .confirmbox .close { position: absolute; width: 13px; height: 13px; top: 7px; right: 7px; -webkit-border-radius: 13px; -moz-border-radius: 13px; border-radius: 13px; border: 2px solid #ccc; color: #ccc; font-size: 13px; text-align: center; line-height: 13px; font-weight: bold; background: #4a4a4a;; cursor: pointer; } .confirmbox>header>.close:hover { border: 2px solid #444; color: #444; } kimchi-1.5.0/ui/css/theme-default/nav-tree.css000066400000000000000000000051501254252253000211460ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ .nav-tree { overflow: hidden; border-bottom: 1px solid #000; } .nav-tree .item { overflow: hidden; border-top: 1px solid #000; border-bottom: 1px solid #444; background: #222; *vertical-align: top; } .nav-tree .item .arrow { float: left; width: 42px; height: 48px; border-right: 1px solid #000; background: transparent center center no-repeat url("../images/theme-default/folder-arrow-right.png"); } .nav-tree .item.on .arrow { background: transparent center center no-repeat url("../images/theme-default/folder-arrow-down.png"); } .nav-tree .item.nochild .arrow { background: none; } .nav-tree .item .arrow+.item-link { border-left: 1px solid #444; } .nav-tree .sub { display: none; } .nav-tree .item.on+.sub { display: block; } .nav-tree .sub .item { padding-left: 44px; } .nav-tree .item-link { display: block; position: relative; height: 48px; overflow: hidden; line-height: 48px; color: #eee; } .nav-tree .item-link .count { position: absolute; height: 24px; right: 10px; margin: 12px 0; padding: 0 9px; background: #900; box-shadow: 1px 1px 1px #333, -1px -1px 1px #000, 1px 1px 1px #600 inset; -webkit-border-radius: 24px; -moz-border-radius: 24px; border-radius: 24px; text-align: center; color: #fff; font-size: 10px; line-height: 24px; } .nav-tree .item-link .title { position: absolute; left: 42px; right: 42px; overflow: hidden; color: #fff; font-size: 13px; text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } .nav-tree .item-link .thumb { position: absolute; width: 42px; height: 48px; } .nav-tree .item-link .thumb.host { background: center center no-repeat url("../images/theme-default/thumb-host.png"); } .nav-tree .item-link .thumb.guest { background: center center no-repeat url("../images/theme-default/thumb-guest.png"); } kimchi-1.5.0/ui/css/theme-default/navbar.css000066400000000000000000000025211254252253000206750ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ .navbar { height: 48px; border-top: 1px solid #2c85c3; border-bottom: 1px solid #04385d; background: #0769ac url(../images/theme-default/nav-bg.png) repeat-x; } .nav-menu { height: 48px; position: relative; } .nav-menu li { float: left; height: 48px; } .nav-menu .item { display: block; min-width: 100px; height: 48px; line-height: 48px; padding: 0 10px; text-align: center; font-size: 13px; color: #eee; outline: none; } .nav-menu .item.current:focus { outline: white dotted thin; } .menu-arrow { position: absolute; width: 0; bottom: -1px; left: 50px; border: 10px solid transparent; border-top: none; border-bottom-color: #e4e4e4; } kimchi-1.5.0/ui/css/theme-default/network.css000066400000000000000000000141321254252253000211160ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ .network { font-size: 12px; font-weight: bold; color: #666666; } .network .list { margin: 0px 10px; } .network .list .header > * { margin-right: 2px; } .network .list .item { margin-bottom: 10px; border-radius: 8px 8px 8px 8px; background: linear-gradient(to bottom, #FFFFFF 0%, #E5E5E5 100%) repeat scroll 0 0 transparent; border: 1px solid #CCCCCC; position: relative; height: 54px; } .network .list .item > *:first-child { border-left: none; } .network .list .item > * { border-left: 1px solid #CCCCCC; border-right: 1px solid #FFFFFF; } .network .list .item > *:last-child { border-right: none; } .network .list .column { display: inline-block; padding: 10px 10px 10px 2px; overflow: hidden; } .network .list .item .cell { padding: 19px 10px 17px 2px; height: 19px; color: #999999; } .network .list .item .cell:first-child { padding-left: 10px; width: 183px; max-width: 183px; color: #666666; } .network .list .column-name { width: 190px; max-width: 190px; text-overflow: ellipsis; } .network .list .column-state { width: 70px; } .network .list .column-type { width: 130px; } .network .list .column-interface { width: 130px; } .network .list .column-space { width: 270px; } .network .list .item .column-space-no-border-right { border-right: none; } .network .list .column-action { display: inline-block; position: absolute; height: 55px; } .network .list .hide-action-item { display: none; } .network .list .menu-container { display: none; top: 58px; } .network .list .action-button { float: right; margin-top: 5px; margin-left: 5px; } .network .list .action-button-icon { background: url("../images/theme-default/arrow-down-black.png") no-repeat scroll center center transparent; } .network .list .ui-state-disabled { margin: 0px; } .network .list .network-state { display: inline-block; height: 16px; width: 16px; border-radius: 8px; margin-left: 29px; } .network .list .nw-loading { background: #c0c0c0 url(../../images/theme-default/loading.gif) center no-repeat; } .network .list .up { background: linear-gradient(to bottom, #BFD255 0%, #8EB92A 50%, #72AA00 51%, #9ECB2D 100%) repeat scroll 0 0 transparent; } .network .list .down { background: linear-gradient(to bottom, #AFAFAF 0%, #AFAFAF 50%, #AFAFAF 51%, #AFAFAF 100%) repeat scroll 0 0 transparent; } .network-config { font-family: Arial; font-size: 12px; margin-bottom: 40px; display: none; } .network-config .section-container { margin-top: 20px; } .network-config .section-container:first-child { margin-top: 10px; } .network-config .section-container:last-child { height: 200px; } .network-config .section-container .bridged-inline { display: inline-block; vertical-align: top; max-width: 520px; } .network-config .section-header { font-weight: bold; font-size: 14px; } .network-config .section-content { margin-top: 10px; margin-left: 20px; } .network-config input[type="text"] { border: 1px solid #CCCCCC; font-size: 16px; height: 30px; width: 300px; line-height: 30px; padding: 0 5px; } .network-config input.invalid-field[type="text"] { border-color: #FF4444; } .network-config input.invalid-field[type="text"][disabled] { border-color: #666666; } .network-config input[type="radio"] { margin-right: 5px; margin-top: 0px; } .network-config select { color: #666666; border: solid 1px; background-color: white; padding: 3px 4px 3px 0; } .network-config .input-container { height: 20px; } .network-config label { vertical-align: top; } .network-type-wrapper-controls input[type="text"] { height: 38px; line-height: 38px; background: #fff; -webkit-border-radius: 5px; border-radius: 5px; box-shadow: 2px 2px 2px #eee inset; border-top: 1px solid #bbb; border-left: 1px solid #bbb; padding: 0 10px; margin-top: 5px; width: 50px; } .network-type-wrapper-controls > .dropdown { margin: 5px 0 0 1px; width: 180px; } .network-type-wrapper-controls input[type="text"][disabled] { color: #bbb; background-color: #fafafa; cursor: not-allowed; } .network-type-wrapper-controls span[type="text"] { padding: 0 10px; } .bridge-option-column { display: inline-block; vertical-align: middle; } .bridge-option-column label { margin-left: 42px; } .network-type-wrapper-controls { width: 80px; display: inline-block; vertical-align: top; padding: 5px 5px 5px 22px; } #enableVlan { margin-left: 42px; vertical-align: middle; } #labelEnableVlan { vertical-align: middle; } #labelNetworkVlanID { margin-left: 42px; vertical-align: middle; display: none; } #networkVlanID { width: 80px; vertical-align: middle; display: none; } .network-config .input-hint-icon { margin: -1px 1px 0 0; display: inline-block; } .network-config .input-hint { margin-top: 3px; } .network-config .input-hint-text { vertical-align: top; } .network-label { background: none repeat scroll 0 0 #FFFFFF; border-left: 1px solid #BBBBBB; border-radius: 5px 5px 5px 5px; border-top: 1px solid #BBBBBB; box-shadow: 2px 2px 2px #EEEEEE inset; color: #333333; font-size: 13px; padding: 10px; width: 100%; } .ui-state-default a { color: #212121; }kimchi-1.5.0/ui/css/theme-default/popover.css000066400000000000000000000067211254252253000211240ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ .popover { -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; background: #eee; border: 2px solid #096aad; box-shadow: 1px 1px 2px rgba(0, 0, 0, .5); z-index: 9999; position: absolute; top: 125%; left: 0; display: none; cursor: default; width: 100%; } .popover:BEFORE { content: ""; display: block; border: 12px solid transparent; border-bottom-color: #096aad; position: absolute; top: -24px; left: 20px; } .popover:AFTER { content: ""; display: block; border: 10px solid transparent; border-bottom-color: #eee; position: absolute; top: -20px; left: 22px; } .popover.right-side { left: auto; right: 0; } .popover.right-side:BEFORE { left: auto; right: 20px; } .popover.right-side:AFTER { left: auto; right: 22px; } /* Generated at http://colorzilla.com/gradient-editor/ */ .actionsheet { background: rgb(238, 238, 238); background: -moz-linear-gradient(top, rgba(238, 238, 238, 1) 0%, rgba(204, 204, 204, 1) 10px, rgba(204, 204, 204, 1) 96%, rgba(165, 165, 165, 1) 100%); background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, rgba(238, 238, 238, 1)), color-stop(10px, rgba(204, 204, 204, 1)), color-stop(96%, rgba(204, 204, 204, 1)), color-stop(100%, rgba(165, 165, 165, 1))); background: -webkit-linear-gradient(top, rgba(238, 238, 238, 1) 0%, rgba(204, 204, 204, 1) 10px, rgba(204, 204, 204, 1) 96%, rgba(165, 165, 165, 1) 100%); background: -o-linear-gradient(top, rgba(238, 238, 238, 1) 0%, rgba(204, 204, 204, 1) 10px, rgba(204, 204, 204, 1) 96%, rgba(165, 165, 165, 1) 100%); background: -ms-linear-gradient(top, rgba(238, 238, 238, 1) 0%, rgba(204, 204, 204, 1) 10px, rgba(204, 204, 204, 1) 96%, rgba(165, 165, 165, 1) 100%); background: linear-gradient(to bottom, rgba(238, 238, 238, 1) 0%, rgba(204, 204, 204, 1) 10px, rgba(204, 204, 204, 1) 96%, rgba(165, 165, 165, 1) 100%); padding: 10px 10px 0 10px; } .select-list { max-height: 195px; overflow: auto; } .select-list>li { height: 48px; padding: 0 20px 0 40px; border-bottom: 1px solid #ccc; box-shadow: 0px 1px 1px #fff; text-shadow: -1px -1px 1px #ddd, 1px 1px 1px #fff; color: #222; font-size: 12px; line-height: 48px; } .select-list>li:LAST-CHILD { border-bottom: none; box-shadow: inherit; } .select-list>li:hover { background: #f8f8f8 url(../images/theme-default/check-grey.png) no-repeat 10px center; } .select-list>li.active { background: #f8f8f8 url(../images/theme-default/check-green.png) no-repeat 10px center; } kimchi-1.5.0/ui/css/theme-default/report-add.css000066400000000000000000000015301254252253000214640ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #report-add-window { height: 300px; width: 400px; } #report-add-window .field { font-size: 12px; } #report-name-textbox { -moz-box-sizing: border-box; box-sizing: border-box; margin: .5em 0; width: 100%; } kimchi-1.5.0/ui/css/theme-default/report-rename.css000066400000000000000000000020241254252253000222020ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #report-rename-window { height: 300px; width: 400px; } #report-rename-window .field { font-size: 12px; } #report-name-textbox { -moz-box-sizing: border-box; box-sizing: border-box; margin: .5em 0; width: 100%; } #button-report-rename[disabled] { background: #c0c0c0 url(../../images/theme-default/loading.gif) 7px center no-repeat; color: #DDD; prenameing-left: 26px; } kimchi-1.5.0/ui/css/theme-default/repository-add.css000066400000000000000000000017161254252253000223760ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #repository-add-window { height: 500px; width: 1000px; } #repository-add-window span.required { color: red; padding-left: 5px; vertical-align: top; } #repository-add-window .textbox-wrapper input[type="text"] { box-sizing: border-box; width: 100%; } #repository-add-window .textbox-wrapper label { vertical-align: middle; } kimchi-1.5.0/ui/css/theme-default/repository-edit.css000066400000000000000000000035331254252253000225720ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ .yum div#repository-edit-window { height: 680px; width: 1000px; } .deb div#repository-edit-window { height: 480px; width: 1000px; } .repository-edit-fieldset { float: left; padding: 1em; width: 95%; } .repository-edit-wrapper-label, .repository-edit-wrapper-controls { display: inline-block; height: 38px; line-height: 38px; margin-top: 5px; vertical-align: top; } .repository-edit-wrapper-label { width: 150px; } .repository-edit-wrapper-controls label { vertical-align: middle; } .repository-edit-wrapper-controls { width: 100%; } .repository-edit-wrapper-controls input[type="text"] { font-size: 16px; height: 38px; line-height: 38px; background: #fff; -webkit-border-radius: 5px; border-radius: 5px; box-shadow: 2px 2px 2px #eee inset; border-top: 1px solid #bbb; border-left: 1px solid #bbb; padding: 0 10px; width: 100%; } .repository-edit-wrapper-controls input[type="text"][readonly] { color: #bbb; background-color: #fafafa; } .repository-edit-wrapper-controls input[type="text"][disabled] { color: #bbb; background-color: #fafafa; cursor: not-allowed; } .deb .yum{ display: none; } .yum .deb{ display: none; } kimchi-1.5.0/ui/css/theme-default/reset.css000066400000000000000000000026701254252253000205530ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ html,body,div,span,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr, address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub, sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table, caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure, figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark, audio,video,button { margin: 0; padding: 0; border: 0; font-family: Tahoma, Geneva, sans-serif; } article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section { display: block; } ol,ul { list-style: none; } table { border-collapse: collapse; border-spacing: 0; } img { border: none; } a { text-decoration: none; } a:active,a:hover { outline: none; } a label { cursor: pointer; } kimchi-1.5.0/ui/css/theme-default/storage.css000066400000000000000000000303761254252253000211010ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2015 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* STORAGE */ .handle { width: 49px; } .storage-allocate-padding-user { padding-right: 108px; } .storage-title { font-size: 13px; height: 18px; padding: 10px; color: #666; float: left; max-width: 85px; overflow: hidden; text-overflow: ellipsis; font-weight: bold; line-height: 18px; white-space: nowrap; } .usage { font-size: 13px; height: 18px; padding: 10px; color: #666; float: right; font-weight: bold; line-height: 18px; } .storage-text { font-size: 12px; min-height: 18px; padding: 10px; color: #999999; font-weight: bold; line-height: 18px; } .list-storage { margin: 10px; } .list-storage .storage-li { width: 1004px; margin-top: 10px; background: #ffffff; background: -moz-linear-gradient(top, #ffffff 0%, #e5e5e5 100%); background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ffffff), color-stop(100%, #e5e5e5)); background: -webkit-linear-gradient(top, #ffffff 0%, #e5e5e5 100%); background: -o-linear-gradient(top, #ffffff 0%, #e5e5e5 100%); background: -ms-linear-gradient(top, #ffffff 0%, #e5e5e5 100%); background: linear-gradient(to bottom, #ffffff 0%, #e5e5e5 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e5e5e5', GradientType=0); border: 1px solid #ccc; color: #333; -moz-border-top-left-radius: 8px; -moz-border-top-right-radius: 8px; -webkit-border-top-left-radius: 8px; -webkit-border-top-right-radius: 8px; -moz-border-bottom-left-radius: 8px; -moz-border-bottom-right-radius: 8px; -webkit-border-bottom-left-radius: 8px; -webkit-border-bottom-right-radius: 8px; border-top-left-radius: 8px; border-top-right-radius: 8px; border-bottom-left-radius: 8px; border-bottom-right-radius: 8px; } .list-storage .storage-li>* { height: 25px; display: table-cell; vertical-align: middle; position: relative; border-left: 1px solid #ccc; border-right: 1px solid #fff; } .list-storage .storage-li>*:FIRST-CHILD { border-left: none; } .list-storage .storage-li>*:LAST-CHILD { border-right: none; } .list-storage .storage-li[data-stat="active"]:hover { border: 1px solid rgb(11, 107, 173); box-shadow: 0px 0px 5px rgb(11, 107, 173); cursor: default; } .list-storage .storage-li>.guest-tile { text-align: center; vertical-align: middle; } .list-storage .subtitle { color: #666; font-size: 13px; text-align: center; line-height: 10px; font-weight: bold; } .list-storage .tile .imgload { display: none; max-height: 110px; max-width: 170px; height: auto; width: auto; } .list-storage .tile .imgactive { max-height: 110px; max-width: 170px; height: auto; width: auto; } .storage-volum { height: 40px; width: 186px; display: table-cell; vertical-align: top; position: relative; border-left: 1px solid #ccc; border-right: 1px solid #fff; } .storage-name { width: 199px; } .storage-state { width: 51px; } .storage-location { width: 288px; } .storage-type { width: 98px; } .storage-capacity { width: 98px; } .storage-allocate { width: 98px; } .storage-button { width: 108px; text-align: center; } .title-name { width: 199px; } .title-usage { padding-right: 10px; float: right; } .title-state { width: 51px; } .title-location { width: 288px; } .title-type { width: 98px; } .title-capacity { width: 98px; } .title-allocate { width: 98px; } .title-action { width: 108px; } .status-dot { background: #72AA00; background: linear-gradient(to bottom, #BFD255 0%, #8EB92A 50%, #72AA00 51%, #9ECB2D 100%) repeat scroll 0 0 transparent; border: 1px solid #72AA00; border-radius: 13px; box-shadow: 3px 3px 3px #FFFFFF, -3px -3px 3px #DDDDDD; height: 13px; margin: 20px 18px; width: 13px; } .toolable { position: relative; } .toolable .tooltip { display: none; border: 2px solid #0B6BAD; background: #fff; padding: 6px; position: absolute; color: #666666; font-weight: bold; font-size: 11px; -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; z-index: 100; top: -300%; left: -140%; white-space: nowrap; } .toolable:hover .tooltip { display: block; } .toolable .tooltip:after { -moz-border-bottom-colors: none; -moz-border-left-colors: none; -moz-border-right-colors: none; -moz-border-top-colors: none; border-color: #fff transparent transparent; border-image: none; border-style: solid; border-width: 7px; content: ""; display: block; left: 15px; position: absolute; bottom: -14px; } .toolable .tooltip:before { -moz-border-bottom-colors: none; -moz-border-left-colors: none; -moz-border-right-colors: none; -moz-border-top-colors: none; border-color: #0B6BAD transparent transparent; border-image: none; border-style: solid; border-width: 8px; content: ""; display: block; left: 14px; position: absolute; bottom: -18px; } .inactive { background: #E80501; background: linear-gradient(to bottom, #E88692 0%, #E84845 50%, #E80501 51%, #E84845 100%) repeat scroll 0 0 transparent; border: 1px solid #FF340C; } .storage-volumes { width: 90px; } .storage-actions { width: 125px; } .storage-action { width: 70px; } .detail-view-icon { background: url(../images/large_details_icon.png) no-repeat center center; height: 30px; width: 42px; } .volumes { background: #73716F; width: 1004px; display: none; margin-top: 10px; border: 1px solid rgb(204, 204, 204); } .hide-content { display: none!important; } .volumeslist { padding: 7px; max-height: 272px; min-height: 136px; overflow: auto; color: #ffffff; } .volumes>.footer { height: 48px; z-index: 100; box-shadow: 0 -1px 1px rgba(0, 0, 0, 0.15); } .volume-title { float: left; padding: 4px; margin-bottom: 5px; width: 130px; } .pool-empty { text-align:center; line-height:136px; } .volume-title>.volume-name { font-size: 14px; font-weight: normal; padding-bottom: 5px; max-width: 120px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .volume-box { border-radius: 8px; background: white; color: #666666; float: left; height: 100px; margin: 7px; padding: 10px; width: 205px; border: 1px solid rgb(204, 204, 204); } .volume-box .volume-state { font-size: 75%; } .volume-box .label { color: white; font-weight: bold; padding: 1px 5px; text-shadow: none; } .volume-box .used { background-color: #FF7121; border-radius: 5px 5px 5px 5px; } .volume-box .free { background: none repeat scroll 0 0 #72AA00; border-radius: 5px 5px 5px 5px; } .volume-setting { float: right; padding: 5px; } .volume-setting>* { height: 16px; width: 16px; border: none; float: left; padding: 2px; cursor: pointer; } .field>select { height: 30px; width: 160px; font-size: 14px; padding-left: 8px; } .clear { clear: both; } .volume-text { color: #999999; float: left; font-size: 10px; font-weight: bold; height: 18px; line-height: 18px; width: 142px; max-width: 85px; overflow: hidden; text-overflow: ellipsis; } .volume-textquota { color: #999999; float: left; font-size: 10px; font-weight: bold; height: 18px; line-height: 18px; width: 142px; max-width: 95px; overflow: hidden; text-overflow: ellipsis; } .volume-type-position { display: inline; padding-right: 5px; clear: both; width: 90px; border-right: 1px solid #999; float: left; white-space: nowrap; } .volume-quota-position { display: inline; width: 90px; padding-left: 5px; float: left; border-left: 1px solid #eee; white-space: nowrap; } .list-storage .storage-li[data-stat="active"]>.handle>.arrow-down { background: url(../images/theme-default/arrow-down.png) no-repeat center center; height: 52px; width: 45px; } .list-storage .storage-li[data-stat="inactive"]>.handle>.arrow-down { background: url(../images/theme-default/arrow-down-disable.png) no-repeat center center; height: 52px; width: 45px; } .arrow-up { background: url(../images/theme-default/arrow-up.png) no-repeat center center; height: 52px; width: 45px; } .storage-icon { border: 1px solid #CCCCCC; border-radius: 8px 8px 8px 8px; height: 40px; width: 40px; margin: 0 10px 10px 0; float: left; display: inline; } .volume-default { background: url(../images/theme-default/icon-volume-default.png) no-repeat center center; } .icon-raw { background: url(../images/theme-default/icon-raw.png) no-repeat center center; } .icon-qcow2 { background: url(../images/theme-default/icon-qcow2.png) no-repeat center center; } .icon-iso { background: url(../images/theme-default/icon-iso.png) no-repeat center center; } .host-partition { padding-left:13px; } .host-partition>div { font-size: 13px; height: 18px; padding: 10px; color: #666; float: left; max-width: 200px; overflow: hidden; text-overflow: ellipsis; font-weight: bold; line-height: 18px; white-space: nowrap; } .storage-type-wrapper-controls { width: 300px; display: inline-block; vertical-align: top; padding: 5px 5px 5px 22px; } .storage-type-wrapper-controls input[type="text"] { height: 38px; line-height: 38px; background: #fff; -webkit-border-radius: 5px; border-radius: 5px; box-shadow: 2px 2px 2px #eee inset; border-top: 1px solid #bbb; border-left: 1px solid #bbb; padding: 0 10px; margin-top: 5px; width: 250px; } .storage-type-wrapper-controls > .dropdown { margin: 5px 0 0 1px; width: 200px; } .storage-type-wrapper-controls input[type="text"][disabled] { color: #bbb; background-color: #fafafa; cursor: not-allowed; } .storage-add-input-width { width: 285px; } .form-section .storage-field { overflow: visible; } .storage-base-input-width { width: 300px; } .storage-window { width: 600px; height: 700px; } .storage-port-width { width:40px; } .storage-auth-width { width: 150px; } .storage-window .form-section .field { overflow: visible; } #pool-loading { margin: 10px 15px; background: #C0C0C0 url(../../images/theme-default/loading.gif) 7px center no-repeat; padding: 0 20px 0 26px; } .storage-admin .filter-select { display: inline-block; position: relative; } #iscsiportId, .storage-admin .filter-select input { border: 1px solid #CCCCCC; border-radius: 1px; font-size: 14px; padding: 3px 3px 3px 10px; height: 30px; } .storage-admin .filter-select input::-ms-clear { display: none; } #iSCSIServer input { width: 410px; } #iscsiportId { width: 60px; } #iSCSITarget input { width: 493px; } /* Progress bar */ .volume-progress { clear: both; width: 140px; } .volume-progress .progress-bar-outer { background: #ccc; height: 4px; overflow: hidden; width: 100%; } .volume-progress .progress-bar-inner { background: #090; height: 100%; width: 0%; } .volume-progress .progress-label { color: #999; font-size: 10px; line-height: 16px; } .volume-progress .progress-transferred { float: right; } /* End of Progress bar */ kimchi-1.5.0/ui/css/theme-default/storagepool-add-volume.css000066400000000000000000000017411254252253000240200ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #sp-add-volume-window { height: 400px; width: 500px; } #sp-add-volume-window .textbox-wrapper input[type="text"] { box-sizing: border-box; width: 100%; } #sp-add-volume-window .textbox-wrapper label { vertical-align: middle; } #sp-add-volume-window input[type="text"][disabled] { color: #bbb; background-color: #fafafa; cursor: not-allowed; } kimchi-1.5.0/ui/css/theme-default/template-edit.css000066400000000000000000000072711254252253000221710ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2015 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #template-edit-window { font-size: 13px; height: 500px; width: 800px; } #edit-template-tabs { background: none repeat scroll 0 0 transparent; border: medium none; height: 100%; padding: 0; } #edit-template-tabs .form-template-inline-wrapper { display: inline-block; vertical-align: top; } .template-edit-wrapper-label { vertical-align: top; min-width: 100px; height: 35px; line-height: 35px; margin: 7px 0 8px; } .template-edit-wrapper-controls { vertical-align: top; width: 400px; } .template-edit-wrapper-controls input[type="text"] { height: 38px; line-height: 38px; background: #fff; -webkit-border-radius: 5px; border-radius: 5px; box-shadow: 2px 2px 2px #eee inset; box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; border-top: 1px solid #bbb; border-left: 1px solid #bbb; padding: 0 10px; margin-top: 5px; width: 100%; } .template-edit-wrapper-controls > .dropdown { margin: 5px 0 0 1px; width: 372px; } .template-edit-wrapper-controls input[type="text"][disabled] { color: #bbb; background-color: #fafafa; cursor: not-allowed; } #edit-template-tabs .template-tab-header { margin-bottom: 8px; padding-bottom: 2px; font-weight: bold; border-bottom: 1px solid #999999; overflow: hidden; } #edit-template-tabs .template-tab-header .action-area { float: right; height: 20px; width: 20px; } #edit-template-tabs .template-interface-cell { display: inline-block; width: 250px; } #edit-template-tabs .template-storage-cell{ display: inline-block; width: 180px; } #edit-template-tabs .template-storage-cell label { height: 25px; padding: 2px; border: 1px; } #form-template-storage .template-tab-body select { width: 140px; } #form-template-storage .template-tab-body input { width: 56px; height: 17px; } #form-template-storage .template-tab-body .template-storage-name { width: 170px; } #form-template-storage .template-tab-body .template-storage-disk-format { width: 160px; } #edit-template-tabs .template-tab-body input[readonly] { background: none repeat scroll 0 0 rgba(0, 0, 0, 0); border-color: transparent; text-overflow: ellipsis; } #edit-template-tabs .template-tab-body .item { height: 25px; } #form-template-interface .template-tab-body select { width: 180px; } #edit-template-tabs .template-tab-body .action-area { float: right; } #edit-template-tabs .template-tab-body .action-area button { width: 20px; height: 20px; } #edit-template-tabs .hide { display: none; } #form-template-processor select, #form-template-processor input[type="text"] { margin-left: 10px; } #form-template-processor input[type="checkbox"] { margin-right: 5px; } #form-template-processor .manual { margin-top: 10px; margin-left: -3px; } #form-template-processor .topology { margin: 10px 30px; } #form-template-processor .topology div { margin-bottom: 10px; } #form-template-processor .topology select { width: 80px; } kimchi-1.5.0/ui/css/theme-default/template.css000066400000000000000000000034331254252253000212420ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ .tile-template>li>label:hover .summary { opacity: 0.1; } .tile-template>li>label:hover .list-info { top: 0; } .tile-template .summary { -webkit-transition: opacity 0.25s; -moz-transition: opacity 0.25s; transition: opacity 0.25s; } .tile-template .list-info { -webkit-transition: top 0.25s; -moz-transition: top 0.25s; transition: top 0.25s; position: absolute; top: 100%; width: 100%; } .tile-template .list-info>li { border-bottom: 1px dotted #ccc; padding: 5px; font-size: 12px; line-height: 20px; overflow: hidden; width: 96%; } .tile-template .list-info>li>label { display: inline-block; color: #111; width: auto; text-align: left; cursor: pointer; } .tile-template .list-info>li>span { float: right; color: #444693; width: auto; text-align: right; } .os-icon { text-align: center; } .os-icon .title { display: block; font-size: 14px; margin-bottom: 5px; overflow: hidden; width: 260px; word-break: break-all; word-wrap: break-word; height: 50px; line-height: 25px; } .os-icon img { margin-top: 7px; width: 64px; height: 64px; } kimchi-1.5.0/ui/css/theme-default/template_add.css000066400000000000000000000147121254252253000220540ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2015 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ .page-list { position: absolute; left: 0; right: 0; top: 0; bottom: 0; overflow: hidden; } .page { position: absolute; left: 100%; width: 100%; height: 100%; overflow: auto; } .page>header { position: relative; overflow: hidden; } .back { float: left; display : block; width: 50px; height: 52px; background: url(../images/theme-default/icon-back.png) center center no-repeat; cursor: pointer; display: block; } .step-title { color: #333; font-size: 18px; font-weight: normal; padding: 15px 10px; } .step-choose>li>a { display: block; margin: 0 10px 10px; padding: 20px 10px 20px 65px; border: 2px solid #ccc; background: url(../images/theme-default/icon-local.png) 15px center no-repeat; cursor: pointer; } .step-choose>li>a.local { background-image: url(../images/theme-default/icon-local.png); } .step-choose>li>a.remote { background-image: url(../images/theme-default/icon-remote.png); } .step-choose>li>a:HOVER { border: 2px solid #06C; } .step-subtitle { font-size: 16px; height: 48px; line-height: 48px; color: #06C; margin: 0 10px; font-weight: bold; text-shadow: -1px -1px 1px #eaeaea, 1px 1px 1px #fff; } .custom-iso-field { position: relative; padding: 0 10px 10px; } .custom-iso-field>.input-wrapper { margin-right: 110px; } .custom-iso-field>.input-wrapper>input.text { padding: 10px; color: #333; font-size: 13px; background: #fff; -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; box-shadow: 2px 2px 2px #eee inset; border-top: 1px solid #bbb; border-left: 1px solid #bbb; width: 100%; } .custom-iso-field>button { position: absolute; top: -6px; right: 8px; } .iso-field .button-field { padding: 0 20px; text-align: right; } .check-all { display: inline-block; position: relative; height: 38px; line-height: 38px; margin: 5px; font-size: 13px; } .check-all input { margin: 0 5px 0 0; } .box { background: #ffffff; background: -moz-linear-gradient(top, #ffffff 0%, #e5e5e5 100%); background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ffffff), color-stop(100%, #e5e5e5)); background: -webkit-linear-gradient(top, #ffffff 0%, #e5e5e5 100%); background: -o-linear-gradient(top, #ffffff 0%, #e5e5e5 100%); background: -ms-linear-gradient(top, #ffffff 0%, #e5e5e5 100%); background: linear-gradient(to bottom, #ffffff 0%, #e5e5e5 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e5e5e5', GradientType=0); border: 1px solid #ccc; color: #333; text-shadow: -1px -1px 1px #ccc, 1px 1px 1px #fff; -webkit-border-radius: 8px; -moz-border-radius: 8px; border-radius: 8px; } .box:HOVER { border: 1px solid #aaa; -webkit-box-shadow: #bbb 0px 0px 5px; box-shadow: #bbb 0px 0px 5px; } .box-iso { padding: 10px; margin: 5px; overflow: hidden; } .iso-icon { float: left; width: 58px; height: 58px; margin: 0 5px 0 0; border: 1px solid #CCCCCC; border-radius: 8px; background: url(../../images/icon-vm.png) center center no-repeat; background-size: 58px; } .iso-icon.centos { background-image: url(../images/icon-centos.png); } .iso-icon.debian { background-image: url(../images/icon-debian.png); } .iso-icon.fedora { background-image: url(../images/icon-fedora.png); } .iso-icon.opensuse { background-image: url(../images/icon-opensuse.png); } .iso-icon.ubuntu { background-image: url(../images/icon-ubuntu.png); } .iso-icon.gentoo { background-image: url(../images/icon-gentoo.png); } .list-iso { overflow: hidden; margin: 5px; } .list-iso li { float: left; width: 320px; } .list-iso>li>label { display: block; cursor: pointer; } .list-iso>li>label>input[type="checkbox"] { display: none; } .list-iso>li>label>input[type="checkbox"]:CHECKED+.box-iso { border: 1px solid rgb(11, 107, 173); -webkit-box-shadow: rgb(11, 107, 173) 0px 0px 4px; box-shadow: rgb(11, 107, 173) 0px 0px 4px; } .iso-title { margin: 0; display: block; position: relative; height: 23px; line-height: 23px; font-size: 14px; font-weight: normal; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .iso-title>label>input { display: block; position: absolute; top: 0; right: 2px; } .iso-info { margin-top: 5px; overflow: hidden; } .iso-info-col { float: left; width: 50%; -moz-box-sizing: border-box; box-sizing: border-box; padding: 0 0 0 5px; } .iso-info-col:FIRST-CHILD { padding: 0 5px 0 0; border-right: 1px solid #999; } .iso-info-item { font-weight: bold; color: #999; font-size: 11px; line-height: 18px; max-width: 106px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } #iso-search { margin: 10px 15px; } #iso-search-loading { margin: 10px 15px; background: #C0C0C0 url(../../images/theme-default/loading.gif) 7px center no-repeat; padding: 0 20px 0 26px; } #iso-more-loading { background: #C0C0C0 url(../../images/theme-default/loading.gif) 7px center no-repeat; padding: 0 20px 0 26px; } #vm-image-local-box .body { margin: 30px 0 0 26px; } #vm-image-local-box .body input { background: none repeat scroll 0 0 #FFFFFF; border-left: 1px solid #BBBBBB; border-radius: 5px 5px 5px 5px; border-top: 1px solid #BBBBBB; box-shadow: 2px 2px 2px #EEEEEE inset; color: #333333; font-size: 13px; padding: 10px; margin-left: 10px; width: 600px; } #vm-image-local-box .body button { margin-left: 10px; } kimchi-1.5.0/ui/css/theme-default/template_list.css000066400000000000000000000136651254252253000223050ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ .list-template.framework { float: left; clear: both; } .template-box { border-radius: 8px 8px 8px 8px; box-shadow: none; color: #666666; float: left; height: auto; margin: 10px 11px 10px 0; padding: 10px; width: 308px; } .template-title { font-size: 16px; height: 25px; line-height: 25px; } .template-icon { border: 1px solid #CCCCCC; border-radius: 8px 8px 8px 8px; height: 58px; margin: 0 10px 10px 0; width: 48px; } .template-icon img { width: 58px; } .template-text { color: #999999; float: left; font-size: 11px; font-weight: bold; height: 18px; line-height: 18px; width: 142px; display: table; } .white-box { background: #ffffff; background: -moz-linear-gradient(top, #ffffff 0%, #e5e5e5 100%); background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ffffff), color-stop(100%, #e5e5e5)); background: -webkit-linear-gradient(top, #ffffff 0%, #e5e5e5 100%); background: -o-linear-gradient(top, #ffffff 0%, #e5e5e5 100%); background: -ms-linear-gradient(top, #ffffff 0%, #e5e5e5 100%); background: linear-gradient(to bottom, #ffffff 0%, #e5e5e5 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e5e5e5', GradientType=0); border: 1px solid #CCCCCC; color: #333333; text-shadow: -1px -1px 1px #CCCCCC, 1px 1px 1px #FFFFFF; } .row-select { -moz-border-bottom-colors: none; -moz-border-left-colors: none; -moz-border-right-colors: none; -moz-border-top-colors: none; background: linear-gradient(to bottom, #FFFFFF 0%, #E5E5E5 100%) repeat scroll 0 0 transparent; border-color: #999999 #AAAAAA #AAAAAA #999999; border-image: none; border-radius: 5px 5px 5px 5px; border-right: 1px solid #AAAAAA; border-style: solid; border-width: 1px; float: left; font-size: 13px; height: 42px; line-height: 42px; margin: 5px 0 0 10px; padding-left: 10px; text-align: left; text-shadow: -1px -1px 1px #AAAAAA, 1px 1px 1px #FFFFFF; width: 100px; } .bevel3 { box-shadow: -2px -2px 2px #EAEAEA, 2px 2px 2px #FFFFFF, 3px 3px 3px white inset, -3px -3px 3px rgba(0, 0, 0, 0.25) inset; color: #333333; } .row-drop { left: 10px; position: relative; top: 50px; } .template-action-hidden { visibility: hidden; } .template-action-show { visibility: visible; display: block; } template-hidden { display: none; } .select-drop { background: none repeat scroll 0 0 #EEEEEE; border: 2px solid #096AAD; border-radius: 5px 5px 5px 5px; box-shadow: 6px 6px 6px; height: 147px; left: 0; position: absolute; top: 8px; width: 250px; z-index: 2147483647; } .button-drop { background: linear-gradient(to bottom, #EEEEEE 0%, #CCCCCC 10px, #CCCCCC 96%, #A5A5A5 100%) repeat scroll 0 0 transparent; } .action-bevel { box-shadow: -1px -1px 1px #CCCCCC, 1px 1px 1px #EEEEEE; } .template-border { border: 1px solid rgb(204, 204, 204); } .template-button-position { position: relative; left: 250px; top: 55px; z-index: 5555; } .tempate-action-position { float: right; width: 83px; margin: 0; } .template-actiontext-position { width: 250px; height: 160px; } .template-line { left: 200px; } .template-os-position { padding-right: 10px; clear: both; width: 142px; border-right: 1px solid #999; float: left; } .template-cpu-position { border-left: 1px solid #eee; padding-left: 10px; float: left; width: 132px; } .template-icon-position { float: left; height: 58px; width: 58px; } .template-icon img.template-type-icon-position { width: 20px; height: 20px; position: relative; top: -15px; left: 49px; } .template-title-position { float: left; width: 120px; } .template-results { background: linear-gradient(to bottom, #FFFFFF 35px, rgba(255, 255, 255, 0) 100%) repeat scroll 0 0 transparent; float: left; height: 60px; margin-bottom: -22px; padding-left: 10px; width: 1014px; } .select-row-action { background: linear-gradient(to bottom, #FFFFFF 0%, #E5E5E5 100%) repeat scroll 0 0 transparent; border: 1px solid #CCCCCC; border-radius: 5px 5px 5px 5px; float: left; font-size: 13px; height: 38px; line-height: 38px; margin: 10px 10px 0; text-align: center; text-shadow: -1px -1px 1px #CCCCCC, 1px 1px 1px #FFFFFF; width: 230px; } .select-row-delete { background: linear-gradient(to bottom, #FF3019 0%, #CF0404 100%) repeat scroll 0 0 transparent; border: 1px solid #B10F14; border-radius: 5px 5px 5px 5px; color: #FFFFFF; float: left; font-size: 13px; font-weight: bold; height: 38px; line-height: 38px; margin: 10px 10px 0; text-align: center; text-shadow: -1px -1px 1px #9E0505, 1px 1px 1px #FC5D4C; width: 230px; } .template-general .title { color: black; font-size: 16px; font-weight: normal; height: 25px; line-height: 25px; text-shadow: -1px -1px 1px #ccc, 1px 1px 1px #fff; max-width: 130px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .processing { cursor: wait; } kimchi-1.5.0/ui/css/theme-default/tile-check.css000066400000000000000000000020431254252253000214330ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ .tile-check { overflow: hidden; } .tile-check>li { float: left; padding: 5px; } .tile-check>li>label { display: block; cursor: pointer; } .tile-check>li>label>input[type="radio"] { display: none; } .tile-check>li>label>.info { display: block; position: relative; overflow: hidden; border: 4px solid #ccc; } .tile-check>li>label>input[type="radio"]:CHECKED+.info { border: 4px solid #06C; } kimchi-1.5.0/ui/css/theme-default/toolbar.css000066400000000000000000000032461254252253000210730ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* Generated at http://colorzilla.com/gradient-editor/ */ .toolbar { position: relative; height: 48px; padding: 0 5px; overflow: hidden; background: #e5e5e5; background: -moz-linear-gradient(top, #e5e5e5 0%, #c4c4c4 100%); background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #e5e5e5), color-stop(100%, #c4c4c4)); background: -webkit-linear-gradient(top, #e5e5e5 0%, #c4c4c4 100%); background: -o-linear-gradient(top, #e5e5e5 0%, #c4c4c4 100%); background: -ms-linear-gradient(top, #e5e5e5 0%, #c4c4c4 100%); background: linear-gradient(to bottom, #e5e5e5 0%, #c4c4c4 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#e5e5e5', endColorstr='#c4c4c4', GradientType=0); border-bottom: 1px solid #aaa; } .toolbar .filters { float: left; } .toolbar .tools { float: right; } .toolbar .divide { display: inline-block; height: 42px; margin: 3px; vertical-align: top; border-left: 1px solid #999; border-right: 1px solid #eee; } kimchi-1.5.0/ui/css/theme-default/topbar.css000066400000000000000000000106531254252253000207200ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2015 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* Generated at http://colorzilla.com/gradient-editor/ */ .topbar { height: 52px; background: #4a4a4a; /* Old browsers */ background: -moz-linear-gradient(top, #4a4a4a 0%, #272727 100%); /* FF3.6+ */ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #4a4a4a), color-stop(100%, #272727)); /* Chrome,Safari4+ */ background: -webkit-linear-gradient(top, #4a4a4a 0%, #272727 100%); /* Chrome10+,Safari5.1+ */ background: -o-linear-gradient(top, #4a4a4a 0%, #272727 100%); /* Opera 11.10+ */ background: -ms-linear-gradient(top, #4a4a4a 0%, #272727 100%); /* IE10+ */ background: linear-gradient(to bottom, #4a4a4a 0%, #272727 100%); /* W3C */ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#4a4a4a', endColorstr='#272727', GradientType=0); border-top: 1px solid #6b6868; boder-bottom: 1px solid #151718; position: relative; } #logo { height: 48px; line-height: 48px; padding: 0 10px; font-size: 20px; font-weight: normal; color: #eee; text-shadow: -1px -1px 1px #000, 1px 1px 1px #555; vertical-align: top; max-width: 250px; overflow: hidden; } .nav-top { position: absolute; right: 0; top: 0; border-left: 1px solid #000; border-right: 1px solid #585858; } .nav-top>li { float: left; border-left: 1px solid #585858; border-right: 1px solid #000; } .nav-top .icon { display: block; position: relative; width: 58px; height: 48px; } .nav-top .icon .count { position: absolute; top: 3px; right: 3px; height: 16px; line-height: 17px; padding: 0 5px; -webkit-border-radius: 12px; -moz-border-radius: 12px; border-radius: 12px; font-size: 10px; color: #fff; text-align: center; background: #06C; text-shadow: none; } .icon.setting { background: url(../images/theme-default/icon-setting.png) no-repeat center center; } .icon.tool { background: url(../images/theme-default/icon-tool.png) no-repeat center center; } .icon.event { background: url(../images/theme-default/icon-event.png) no-repeat center center; } .icon.alert { background: url(../images/theme-default/icon-alert.png) no-repeat center center; } #user { color: white; cursor: pointer; display: block; position: relative; height: 52px; margin: 0 12px; } #user span { display: inline-block; margin-top: 16px; } #user:hover #user-name { border-bottom: 1px solid white; } #user.not-logged-in { display: none; } #user-icon { background: url("../images/theme-default/user-icon.png") no-repeat left top; height: 16px; width: 16px; } #user-name { height: 16px; line-height: 16px; } #user .arrow { border: 6px solid transparent; border-bottom: none; border-top-color: white; display: inline-block; width: 0; } #user .action-panel { top: 45px; color: black; padding: 12px 18px; white-space: nowrap; line-height: 12px; width: inherit; } .user-menu-item { color: black; font-size: 14px; } a#btn-logout:hover { text-decoration: underline; } @media ( max-width : 640px) { #logo { display: none; } } .peers { color: white; cursor: pointer; height: 52px; margin: 0 12px; } .peers span { margin-top: 25px; } .peers .arrow { border: 6px solid transparent; border-bottom: none; border-top-color: white; display: inline-block; width: 0; } .peers .dropdown { top: 45px; right: 110px; color: black; padding: 10px 15px; white-space: nowrap; line-height: 12px; width: inherit; } .peers .dropdown a { display: block; padding: 10px; } kimchi-1.5.0/ui/css/theme-default/window.css000066400000000000000000000047131254252253000207400ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* Hide the "Build Me" warning */ #buildme { display: none; } .bgmask { position: fixed; left: 0; right: 0; top: 0; bottom: 0; background: url(../images/theme-default/bg-mask.png); z-index: 100; overflow: hidden; } .window { position: absolute; margin: auto; left: 0; right: 0; top: 0; bottom: 0; box-shadow: 2px 2px 6px #000; border: 2px solid #0f71b4; -webkit-border-radius: 8px; -moz-border-radius: 8px; border-radius: 8px; background-color: #eee; box-sizing: border-box; max-width: 100%; max-height: 100%; } .window>header, .window>form>header { position: absolute; left: 0; right: 0; top: 0; height: 48px; z-index: 100; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.05); } .window footer { position: absolute; left: 0; right: 0; bottom: 0; height: 56px; z-index: 100; box-shadow: 0 -1px 1px rgba(0, 0, 0, 0.15); } .window .content { position: absolute; left: 0; right: 0; top: 0; bottom: 0; overflow: auto; margin: 48px 0 56px; } .window .close { position: absolute; width: 30px; height: 30px; top: 7px; right: 7px; -webkit-border-radius: 30px; -moz-border-radius: 30px; border-radius: 30px; border: 2px solid #ccc; color: #ccc; font-size: 24px; text-align: center; line-height: 30px; font-weight: bold; background: #eee; cursor: pointer; } .window>header>.close:HOVER, .window>form>header>.close:HOVER { border: 2px solid #444; color: #444; } .window>header>.title, .window>form>header>.title { font-size: 18px; height: 48px; line-height: 48px; color: #06C; margin: 0 10px; font-weight: bold; text-shadow: -1px -1px 1px #eaeaea, 1px 1px 1px #fff; } kimchi-1.5.0/ui/images/000077500000000000000000000000001254252253000146435ustar00rootroot00000000000000kimchi-1.5.0/ui/images/Makefile.am000066400000000000000000000012531254252253000167000ustar00rootroot00000000000000# # Kimchi # # Copyright IBM, Corp. 2013 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. SUBDIRS = theme-default imagedir = $(datadir)/kimchi/ui/images dist_image_DATA = *.png *.ico kimchi-1.5.0/ui/images/icon-centos.png000066400000000000000000000111761254252253000176000ustar00rootroot00000000000000‰PNG  IHDR?<ÑËbqbKGDÿÿÿ ½§“ pHYs ð ðB¬4˜tIMEÔ ’ÂøÀtEXtCommentCreated with The GIMPïd%nâIDATxÚå›yxTÕÝÇ?çÞ™É2$! IÈ – „%a°Å¢`…j«O‹ˆ¯¯Ä Y"†¥"·ê[­hբЄ‚È!@HØÂö% $3“Ì̽¿÷J€@ÂæÛö<Ïùgî™{Î÷·/çÂ]"¢‰HºˆL‘úü§ ÑE¤›ˆ™-†§TDfˆH˜ˆüG€O‘\ãü)Ûû©˜î ù“ˆÔùwçxš˜f¾÷lŽ\X|¿}™ Î-ÄtŸ÷ŠÈû"q·%@»ÀžÀ{Þ³[:7Ã8¿÷þ9¸r§éâ)ù0ˆº›àÕ2Ó,9ÜÆ±öYŒó{«n«4|›?…O‹gÊ”ÅþðàPJý낯äx7¿§7×wn…Qz¨š-¶Fðk=B”OðçÀ(¥Ô±I± pbÎðžÎ®ïÜšQrðâÓËWVL1qú_Êò¦+q_2^D¢ï´ P5b­ÔÅšJ€ÖÀTÓq,ѹþ GÁe*ÄS‚.”5tß*ñm:[“ÇË•Åo0p×OpZ)eÜ.ðM€‚,bÞX””»)f â)¹D7¥*p–åNÃ}pþí'aîišU„QÙ‚PºE”¦ÎŠ)¦˜æ a(]¡”Z <£”:Wð–š±Ò 9z~Møñ’¬j©%@d@{bƒºqª4‡‚ó+1ªÐÏF³Ðþ Y@tœ%>lûx-"— €à[×_%?–f&{ænÅq¦¤Z^é6Æ}ZžP;f©¡s¢4›¼S£)íM":Ò$´?g»Xsx4Ê ®Zâ×”„º?«ò^Wa)9ÿ³–+¹«”Âyº„{žíŽxYo/Ããò\šÕßFHBáIÑwÆà)îçêØ™žÞÆå9Ã÷ž«~å:­Z¦(­ìå ï³ ¬™´ˆØ.é5ýWØ#/¦ÊZ¥nÊoi·f-5â‚zÐ9v gyl<:‡çämõ ¾ÛÉÚI‹‰j×€´Q}¨ôÿÃÕÙ,$…?N O,y§>¡¨lÿmL¯Á¾ùÛ8ž}ˆø^Íi|_bÊO^)º¾ñx ›Žþ³Î]tŒI„½-ÂíõͺÍBÛ§»×µ ÛÿšÅ®9›±úÛ°úþà±ÝéÙh&ÍÃ~MQÙ~Ö‡†NÇØQ„Û[s»‚Ýf¡õ Î¤<•ÎŽ/6±ùÝ•n/í‡ÝK÷‰ý+Tàöªx“AÝéó>zmê?MózPì:ÀÚ#¯£P¤7È Ø/á–%@L¡Í“i¤ IçÀw;Èš±Ãã%eHÉw$¾g3ºOì‡OÿQ㯈 êAzÃI»òY°çW(\H›Èghõ,'KsXuh^ÃIÏF3ˆ°§Üô¡,>îy¶;ížéÆ®¯7³æE úBoîz/Ù³V°bä<Â’¢øÙ¡NdÝ›’6KMÆu£i½‡9va›ÿ‘RÏ ¶žxS š†Àm”²çÌVC׆“èûYG§r¢4»vò³Òö©®$?žJî'ëÈùh JS¤¾Ð›Æ?O"÷ãuä}ºÓ0ñºÜt›Øn¯÷E·YîçE)]"ê¤àðœbCÁ$J*ý¸Û(%çäì/ú–”úÏTÚ€Y$”¢KÜ8êú6®¹¤<•Nòã©X²“ìY+ð–yI’NË_·gÏÜ­l~o%†Ç@L!ÿûݬË\Lh³H"Û5à™Ó̓ HБ╬È‘2oqwæ1JÙtt»Ï~Eˈߒý …®½üÿ2NÏiz7~‡¨€NæuA[ýmt|ù>R§‘7{«&,Àâk¥ËÈŸÓzPgÖO[Êæ÷~Àp{«Dûæñý«s)=uÊ,^DÔ-¯þ(ÂxÓ÷´c.Oõù¶°÷ì\ë=DrÄ”zN°îÈÜF bFбÚÿZí6ÚþWW’iOΟײíãu(M«õ>-ÙöÉ:v~± Ók^#:TÏ>ÈÉœ#IÀ$ éF6@D”VÝà1Óc¼q:ïh”ÛQ^ÁžëÐÓc:É=ù{ÎÌ!9b0-ÃqÁ}ŒÕ‡_ÃkºèÚ ƒp{««‚ M×h?ô^Z>–Êî¹[ØòÞJ: »—¦ýÚ°ýó,r>Zƒi˜×K=0½&……¥za¡£'ðn $Àª]¸ øi˜3\¼=æûQsñº<5Ò!¯édóñ™ì>ó%É¿£Cô‹ºö±êÐhJÜÇI‰¥n•ÿ7 £å¯;÷—õd½µ ÝÇB—Q}h=¨3§/#çÃÕUDýz#7·€±cçéGu>«N*‰RG»âG_àIÓ0§îþz‹}ýäï(?節‡&÷äGì<ý9ƒûÒ.r(åÞ"VÍ9ç.”ÒP>Á(Ÿ 4¿z˜^“M3Wóçµè>ÒÇü‚¸®‰lš¹‚]˾.ǯŽ<Y0zÔ7-(ê$"3öÕ¨@€vE±ñQ1̱k~ŒZ—¹¸ÂˆÜD!ÑkºØ~êöœCrÄ´ ÿ-¥îãl=ñnÓ…OÂcøµ›ˆÖž G‹È›½¡ý°{IøE+¶¾‘Ü¿¬¯ðK¹€)lܸŸŒŒùÚ™3%]Yר +ÀßR Üb¸½™»ælöß0m)îÒrT¥~*¥õoABȨZÄEçËQäÚG«ˆ' ð‰¥¸ìJi¦f)¶Ùc4 Ìêç®ßäÖ4ìÑŒF÷µàȪ}¸Î9hÒ7¹Æ9’n³‰ ÎKç]±b7%ÿÐÇO蟚˜Xžˆ 6)¥¤¼E‰ˆxÂð¯ï™»5lãôe¸Î–V<¨H¿Ùƒ±ÙñÖRMYЕ‹Ý‚fS¢k¶bPïžbJ£Ükw&®r†Û‹µŒÖèV¬ìƒŒ3‡£üZµŠáí¿1"#ë®Ó4õè@3%"/‹a¾’¿lwز_ãuV­jV„p”®n6ZEiІ=›Óþ÷ÝM¥kK¡•à;SK.¸Ò>ø`%6ì¿¥| ´´Œ‚‚BÌËR^Óºti¸ñýÌøø°ÍÀo| AŽ¡T©_ˆŸ:>׎‘o1KÓt ÿP;TTUOÞJѳ!nAq±ƒ;QªV Î+Áá(W@\¹w¹ªtm}Å”iGVÿØhuÆBŠž­( Ô‰ ¢ß§ƒÑí6¼ÞÚ °Ùt,VÍ× º2m6K¡Rj PRYÛ¿_Œr_g”•`”ƒ˜µG¨YÙ˜u˜±cæ^{€¸¸PfÌø4k¹K×µÀ?*ÁGZ”RnY¨4¥âº6ù0mÔý!«^Ÿ1\¬ˆ|Y•Ï+v£4US…G×5†ëE]»¯¾Ê¢¸Ø© yª[p@€ïïˆ ÇpÒ·lÇ;øÄ?„½^[Üù‹ñžÉ®]F¨Ù°5€Ýî_¥UÖ°a=ƈ¤–ÑùÀ(`©Rʬì&–JÃà抈#¾góY1Á ßù”’ãÅ—X¸kç1æÏÏA«x µ3â•>øûÛÈÌ\Ä߾ʢm»† z"M/óÅœ_E\Pw¬¦OÁwx-ǯÝ8¬1½ñžÞ€ûð¢@Yü±„§M/oÞ"š)SJ³f‘û@^¥¥¿8Œ+ýÖ÷(FÕkZ_7ú’^k#'!!v†?ii‰Lk æçlgðàtêØØsö+ÖLàDi6š=ßäç\9oâ-ÜŽoËaØâz R4Nˆ #ã!iÒ$"~ àrøJ ø;Šgtkz¦ûÄ~Äר‰€¯¯•W_½Ÿ^½’øèÕ|ùev»1c¤W¯$4M¸P~áÄm”‚éÅÖh¾­^@<\Y#1.ÂïžñX#»Öºú“Ð8œÌÌ´j»W×µç%W¿Þ£]#D4€å(žˆê¿§÷b«ã[cQŸ0±?]Ò™6u1³g¯'*ª.'þ’´´&|ðþ ŠŠœUøi”äS–ûÖ˜ÞøµÏ@¼¥¸6Æs|~ÞÄÖ°Ea¿#¡I“§ 4[·ŽÝ <¬¹ð‹à½Zu12°Tiê¥À˜à}?+ºE¿.ðzõêðÒË}HKKäÓ³`A!!v&fü’¦Í"™œ¹ˆåËwVñÁ#wþÊwÌÄÞ¿”Ñ€àÚšqn¾ÉÏWàF* 4bbBÌøø°¥Ôï­J©ë¹ ·v$Á[éFišVÚ5=‘øøzW¹ü wfaÔ辤§'òþ{+X° ‡ºÁvFîK«V1¼ûÎr.ÜV½ù0=”ø†²³°ÆõÅ7y8˜\['bí¯õËX£{\›b¢Äc©Û¥ÈWŠ‘ÀÚj8~9s½Ú ²$/°]))mðÁŸÑ aè%ˆ@xxS¦¤C‡FL²˜Ù³×ÌÔ©¿¢S§^zñ+æÏÏ©4¹N|*^Üû¿Äµ5Kô½øwšŽxœ8³^Ås|þ©Ó°Å?\UÄD»ÿÎo£%üäÜ€ã±I”É0Lµò‡=¸œn&Mz˜¤¤(D„ˆˆ@F¼r?mÛ6$óÍoYºt;õë1n|?bcCÈ|óÛÚ…¬JÃ}x>e;f¡'á—2¥ûR–;ï©õø&ý7¶F.@m…û‰àq`íâ²Æàm,] lÙrˆÑ£¿!..”qãû“Ò¶¯½ö;6bÖ¬å,\˜CݺþŒߟ-¢˜þÖ-ʽ‰þ”;ÿÊr§aý9¾­G bàÌ‹Q¸¿6¯béÚÿ™`z+ìCå%§;Ó¥U°sç1†ý ]×øä“!$·Š!câ¾ùzññadf$99†W^™Ã’%Ûo¥cûÐßqmžˆ%"ÿÔi€àÜ<÷¡øwȤN×Á(DZv(Fñ ´ÚÅмÜ22°sÇ1&O^IJå;©_?ˆIo :&˜ ãç³~Ý~nù6•ÒqYHYÞ[èÁÍðk÷z… l›ŠçèrŒâ=8³Ç`–Üts´Ö•þ‹>üs DGóÚ˜ˆ fÒ¤…¬X±‹Ûv‹LL܇¿1ðk;Õº" tåLBYü1'¸•ÍnªK+"œ;çÀjÕynxoºwoÆ{ï¯`ùò]·=%­P¸|‰%¦7>-žFÊ‹*€ÿ”ýyÇËÝH^n>’J»v o?x4,°ÆöÁ8»wþ75Žøî(xضí0cÇÌ#0Ð1c¤E‹èÛvy,aíð¿'³ü®­o`ï½d­™§C¤Bܯœ{÷àé§ÿBII³ÞyŒ6)qW­7M©>A“K/»˜hé…êdL×IœkžÅ8¿ÿŸ÷Ù®šwÈàiš¢}‡x Ó¬ÖŠ‹Ç‘’Ço<ÌâÅy”•{ªÔŠÃÃñó³‚ó2ê‚­Ù“pE/Oi>ØEÙ‚0O­ÇÚðÁj›ÒlèÞmojš:×­[3IOO¼qY×HlZß·qBx azT¹ñÏÆ¦R ¥91Ä‹Ba˜e”[5h1¨Ê;|,AhÊ J/ñØâÔÈ5V–Æj,5½~]Kg d–:­9üš:íÈ«²¡Û(Åk–aÓ°h>—N+b|m#‡¾–ºkç*ÕtÜÞë§7é 5 Èä"×þYǦ¨£Ö_¶™ºÌš\üE#&(´¸ñ†Ÿ5ì;…ö*°ûzÙÙ-WvïÔ‹+›-/Š\û“Ö¯N:¶\³ã#±étŽK€-æ`˜Rj'wxÜñý"Òø£Ës®çÊC#´ã%YWoò bF~–ÐeÀ àÔÝøØàŽfìFúYCWvŠ}ÍŒìr™ÔiÔƒöÑ/zý,¡K€—”Rwø]"¢D$QÄÌ*.;h.Þ÷¤|¸9Q–xNî“""ߊHÓš^'ùW%BSù‡Ã}ÚÈ;ù±8Ýg<"²XD"øw•$b.4LO™ˆ9GDýG|TXUd†ˆ$þ”gù?ê5¼ÕôŠºIEND®B`‚kimchi-1.5.0/ui/images/icon-debian.png000066400000000000000000000102171254252253000175220ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aËbKGDÿÿÿ ½§“ pHYs  ÒÝ~ütIMEÝ 9軄IIDATxÚí]OLgÿMcäÈ`Ç&듬0vq”VmŒÙ]i/±Ñ!œJ¤­b$vµÍ%¸Rs#É-+Õä’­Z$µRè ¢„Û®l÷²Ò®ü§­¶‘MŒJ Illƒ`Í`XÛØã?3ãó»âó}¿ï½ß{ß{ïdÈqzAÈKlúCÔ~:‹ƒtJc'`?Åùa‡ä×G!å?.‰QÐÖ{™Øô‡¨­hÿ]YÃnb =chë½LÀmTÖs‹N³$[ à•ïµñx™@J£»‰µÿ3^«†Þ5€3çÚ 4 4vb+Çö÷‹ÈB0ûîâ\‘O¢íhF¯2DŒå$µ1ó 6¼”Fô7 ²Z°}D„ÝÄ¡•PY{ Ðªñv>…V ÃÝÐ5èœvÉX‹¦'À¦?Dm<^ÀÆÌó†þ¿­V ~usz×@S“hæ_ü ™@Xðï¢w Bs ÀuÈ8_ ÆKž?!‰Q鈖„¼ñü¸‡ÝÄöÓÙñi]ž»=öRÓŠ{Šl´çËU\òŒÎvw2*àÍ\€Z½_p’šíNûqôqÑ3&¸Ev–“ÔÙîNâ¥ë%…S_ ­ûé,”Fɼé&À^*czÑ‹,öŸRÇ%Ï~=ùgâT ‰Qñá;5%q¸:*kOÙŸ7Jtj6Xæ4Ü%bÙüý·x;õ­V tC׎ÓÂt ¸–üÿ¦?Dí&’G)ã0¶¢q^¾§É7q|Gq*À§ÐkwÚÑåu+nZ_p¥U2RO¿ÃÛù §éŠÿQÃH (^ùžQäè}Îo£Å}±þð[NˆÜHRÚüv§º¡k‚ÝÜí¥2¦õ©YrurºiH@Haóó…œÙwWð$K.£–Fï³Ö Ѭ›¯4Ðî´ã̹6¨¬(´jÑåÛãŸSkS³¬…áÿ#Þ¢ƒ†.ئ?DýÔÿ ëéòº›ææ ·;í¸<ÿW¢© °—ʘ¢ÝÃ$‘¤w âÝ™»MwƒÉE˜ËW²èF-ÂúÔ,«Í7Œ Ë;nF¢­÷2qÅÿ ­ºîß±:9}\ãØtx3 6/°C|$^šK<„̼›S6¦_i4 ãöZ­(Ñ\¡²= ñá;¢q¼/èÏž/©Zãb…V‹ž1tºoH²7é}B­¸½u[Ã"_svxwµšþV«D¾–ìæ@§ûA×ÔŠýt\$š8%À^*c*Õr»§w âÃè7„L}%˜|f¥ÑPß¡šyŽå$%ćï?{¾¤Øœ~³o¢)C¼zÑ¢Ó,™}wë·¬˼ÃÅéÏÂЙ´\$FU{—nöMH¶ó† çúûÃøH}aõÃoÅA€™²Ëë>‘¯®VäœÖͧqÑ3f®74|3`íX7‡‹µ7sêõã…ªîÈOûæÓ® é}RñÀtyÝ€ƒ#¨²ö`›ƒÜ§‹_KÌ/o~!ÂÆ!FÁü{ü‹Èÿ¬ÒhऄŒÓ0°Út¯¼ù'Ñq›Y lúCÇæþ’g ÛÑEpqCÈ)ªQýz× ¼ù%×e€Q ¬?œEÌùF¯õ†¼¹€j®=5Þ|!Êͧ£–ÃöðdÁÏZ­¨®ö@ãèã5]M/m=ö|IéœvÖÅ"ŠF~ÚgA÷…h6}g9I­?œÅÆÌ~ìý¸ìçòÃÙ¬¤:nÄËŒÝеŠñ=­ô®A¬?œeýÖí’Þ'¬&æ7ûîB,‘{©Œé¥ëévbmj¶¦{ú­häè}D»‡ÉW¾gœ^Ïžv•BÂíïörÑC¡¨wìýîKðºÂéWhÕH= ŠâÔ¿™ PÑîá’›N÷h}%{v–“ÔV4Žl0Œ·óA£÷ñÇ_(.:4c-®¶ÛóÄ(6n .lGÉV«H'ƒ?¿ŸÎBuµGðÍå{Vò*–îÚ=ÛÝI ú 0Yúßûz:I´{˜ÌEbœoª®ö”%€B«Ænbí¸¿¡ÝigÝ“P— P PÛmÇ'ª’ UhÕ‚+ÿR"UïDïò<Þ¹[×Ô¹þ>âÝ™»„eîVÜ^N*v4Ž>ƃ¤w [³ÝÄË>„º@³RO¿«"ÆýHp³Ÿ¿ù ­ïùÿV÷Æ—"Âû/ˆ×x)Û*¶lªŠ8ôÂ¥*˜ ¥Ñ€ŽñÁjùöRS~)]oÀGU±qêS‚íæ¨¬=Œk•z,øîG««áwØž¬Jæÿ’gLPõ¿âž:ÎNÒ5ö|Æòlw‹N³¤qØCÒüèã\qFÛf„•Ì¿ÒhÔ÷ç'VZ5L¾ Ha¾=Î6Ÿ4 ‚ù§çáå÷ó“*n»æ\º¯º ‹ÄͿЧ?ÿzµÝi—Ôàçr%x %@¥Ó_oÑ#W§??KFߥK™@˜œLñ*膄#@¾6Ñ»›®Ÿ Õj©hÝ^ºî [Z)\Ò<æ['¡sõà̹6ÆŸï&Ö º&¬¨¤<…"Hj>Xö )üv–“—þ:__q¥ixk "ÜÚKeLùMLñt#¾ƒíèbÍþš¾ñk„¾â…\¦*kZ¸è"™/þèûŠfC¥ä—úŠ0ÍÝãÅÄ•Ä߸èÃm›4óùEŠbAñ͘Ðêÿü°ƒ¨Gƒ0×píÖx±š&5½b@.£Ê|j6èoˆ#Ô àª²±:&^Väiì6èœvóA:GrEž4€E‹ÙŒÓÆ/Œ^'˜¦¡ÐÑWÙ@IE'|iP¸×EêíÛ£›mKáÌѺÒóŽe BÐmòõ–j¥æƒd¹Ø_qQd!Î\¼€+v²u=~_ˆ>õIïªÒ]I9”kû>œvÞY` DK¡Â¯R®‡ï½ÂÍ›EÇøˆ9 ×µtÙy©uaô:ÁG›¤\@©j”Øô‡(¥±?ö~L^¬£fÓ*;=,¿°&‰Q\&¸$§Š%¯YÌ'¬•|º¡kh¯£_ï•ïõSÿ'`:ýù„E&P¬(ΓoEã ËZžvÆ©OkÞ¦¾J¾Ëê$G½kÀ\Ë‹žÐN»9ßüs Vðñ¥svýjl°]$õ®Á‚$ÐÆÌslúCT=¦3é}Bm¿eWÇa ¾²Žƒt¶à)¶(nòThÕ°Ì=ÀêäW×ê™@˜óù‰u[¦P~/Wì&’Ðß8Ô;™Sï0«®ö  cur™@é>BŽòÅè¸ýÎõ÷ùcäöRá5«?âŸøUÎo õÞQ'©ºÚsb¢¦ß«Ê „øMêï'º_ùžQ|TYó¢ªéä# ÛYNR-:Í’ÚnƒÊj9Q°:9-Škì½TÆs~VvH©jª|- ”ËùoEãœÌ°«™@äè=‡£ëvk°Ì=8ñãÃwš*µù/úo‘¥Úº[­–²÷ý|•ر"SåãKjóՃ؎.bÓ¢’Þ'T»Ó޳ÝÄÿ£‚Ïí§³xÑKä"1êÇÞÉRñ>Ý·¨¿9ÐÐïÄ* 8ÌM—δiì6 и?älw'‘ô>¡ÈÑ{xÏÿ7£÷°—ʘZt¢x6M‚z#ƒZ7=C¡mC¹gcІj¨FaeèÐH,ètß Z­lÌ<‡þæ^ôß"s‘¥sÚÍfßÄ KðSÿ'(5äš+¼ò=£VÜ^dƒae^G¥'¤ Õ´ÊÒ”ÏIl  š|æÇ Gs~,øerëS³¤Îi7ùú„&XœÆÖ?R\‹CÚêdá²c\ ã#‚OHgõŸï,'©H·³¬@´.Ï™…`v.£^?^€qêSâ¥ëEßÍ›|æÝÄYî•ò‚YA,¢‘Õɯ/¡èVu14¬²þÿÖþ¡l—°Xâî—®{Ôv4Žýt–¹P æøð²Ü&ÑÅ—Õ †¤É– „±ŸÎ¢Òè6Ã&Š×M9#@ÌùUÎÄ}ùZ4=ùIïê—Éiì¥q;Ý7ˆj^ö<|jÞp¢Ò9 c7±†jgõ)tyÝ¢kS'¸XØriVÃøê¹ãÓ5Ðæ_ã°¡ËëF&®;M\íÆ_òŒ‰v>2ÁÅ¢–³ªÐªñÛô?Dõ‡ï¥2¦_&§IúäÓ'¼ÕjÁÛù 8™¾©UCç´Cs@ôOÜròå˜t€XGÃç"1jÅí=kíN;L¾ óA:Gf!l¿ˆ­hÛÑÅŠ½zùnBãèkšw9#Ó”k®ß¹ãùª]¡U£Ë;^rôÎròÄ­³ääËWz S¡UCeínÈ.Ú÷éÉá´Ð8lÐ]*)É ˜â…•Ü@q¬-öçáèôm6ÆV4^R(´jh6tÜi*“Ϫyì@캠’x¤‡=4ó†óF¦h Ôé*K(£œ„´õ^®ú›ýt3 ¤¼ü"P} ³Æakx½€Œ@ç´Wõ ¦Æ~˜oÆþ}™ hÑi–ª™Ë·þð[¨¬=æÓðJø©"æU£~™œ–5€ p¶»“¨†kS³¢4uÚÀ‹ ®ö a¥Ñ[â©ì¤djÑõQ!r@ÇøHň Yº2D@€f©Ë;Îø™ÝÄ^ôß"eHÀáȳJíÌ»‰µ²ƒ‘d49€Ê¯uì³|øP†È ÐÖ{™¨”"^qOÉZ@ª€_Oþ™`l´ŸÎbiô¾ì¤JàðÙ6¦¨àí|\?Ç.CDhë½LTŠ VÜS‚¶nËàF¯3¦‰\¬ˆ†§aé L±õ®A¨®öˆ¶€T&$¨tWÐjµàÃè72¤äh´è4KWüEa#<Êm½— SÑІ“¢Ð+ïT ŽV53`+GbüsÙ H•tdÀD‚µ©Ù†O“E (ä$ ÃSbªµ´KàêÕl"³4Þ̨¥2µòóbï/” À¹HŒ*7S/ßtyÝ’êÓ“ ‡j2†`™{ º¹;²à-:ÍÒ‡ÑoÃøHÙÏУ]dHÐÔ¢ 4,sänc)Y€|œvÖå9s¹úÂL Œh÷0Iç ~ö|IÉ7вÅù‚÷TYkÐjµ@eµ`7‘Äû/dm 5Ð1Ô›.ž2ÐØYNR«“ÓŒ¯„Ë$0ª%‚,%N€|"¬?œÅÆÌ  ÐªqÑ3&WI™Å¡cêéwHÍ È@qÕØ{«š.@"dÈÃÈÂ'Þ祇X¶Z-P]íÊj‘ìPÈSK€bÐ¥f[Ñ8Š\ÅÁf»‰5¨í6Ù]È!Câør½ŽjHIEND®B`‚kimchi-1.5.0/ui/images/icon-fedora.png000066400000000000000000000105411254252253000175400ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aËbKGDÿÿÿ ½§“ pHYs  šœtIMEÝ *î]ÎiTXtCommentCreated with GIMPd.eÅIDATxÚíyt[ÕÇ?O›-Y’wì8NB !@H¡T%L8¤aia†­´40L– 9ÀÐÃÖ –‡@™9å”R(C!¤bIÈBÒ1Q6;!^âݲ-ÉZß›?¬Ò„Äö{Ò“üä¼ï9::>~O÷½ûýÞßýÝ{÷wA‡:tèСC‡:tèСC‡:tèСC‡£Âh}1—»¦˜–üLM~WÀ~Ä7@è;â»Ø}äÇçõøuh›pppEò3Yå"vo'?›}^¤ `äIÏW‹“²Tt °x Xïóz"º²Gz!ðÃd+¿ä3>Rk“bx×çõtëÈ ñ@ pw²ÿÖ"‚ÀÀJŸ×Ó§ @âMÀMÀý@eŽèµ xxÞçõÄt¤Nþà᤟‹¨~üQ«N£ Qâ/挒AÊvà^Ÿ×³^ÀÐÄžÒ鉵À->¯ç.€cÉ?7éIat£¸ÒçõlÒÂÃ4BþuÀÇ'ù00éu¹kn8á-@röîàž\b0?ÏBYy ]ݽ„‚¡t~êq`…ÏëO8¸Ü5Nà-÷÷‚ 0óŒi\ô½Yœ6e åÅ”Û(,°|{MWo„Æö ­=4îbý'_²ëë=HbBn1«k|^Oà„€Ë]39ùâ.-Þ¼Y,Zpœu2e…ùŠïß±¯“‡~ó1ëñ·ÈC-°Øçõõp¹kæ3° R¢5â§OŸÊÝË.cöié»"½¡w¯ÚJíþVB­ˆøƒ4äT@{R[F­’-«Öȯªª`ùm?â’yST¬‘¦Ž7>ö áh‚D8H¨e?ѾÎáDpn6-1‹ä;€õÀx-‘Áùgó¿ÿ3§O*W•|§ÍLsgˆ}½LòŠ*1MÄ‚ƒ® Ê'Îû]ÇÁMÑQ3 Lzû¯§i‰üŸÞpÏ=øO8læÌ½ûø¢£Geãpž<Áh´'^IÖÙ¨™x˜%\MÀ xôþ[¸ëÆ 12Û &Äcû}³½„ÂÉç`´X»mqrxœûp¹k®îÕRË_±ü:.»pZVÊÚרsü¾7φcâ™ÆA­Ï=Ù˜,2d˜üÙÀ‹Z"ÿê%ÿÀµ—ÎÌJYÝ}Q>ÝÙ:¸f±â?!œ\îšy9)—»¦Š¹ý|­?{ö î[vqVÊJˆ¿ö=Á¡}9³½˜‚1ƒ®vçoºÜ5ãsÑ<Ti…|›ÍŠç¾ÄlTç•#±âqú÷„(±c'?ýÕ§l¢õå–ŽÅâ,ìßÀ 95œìùTK¦ÿöeWqëÒ¹)ÝOH|¾«™õŸíbëv­-ô#ÎB%e¥”VŒAÈ/¤¡#B,¡|j? áß·e¨É¢™ˆ'È”6sµB~Ii¼¼[žI¹×àçß}Ÿ¯nøÊ4±UN&¿´:¥ç 6í!ÜÕ4Ø¿·³ÕŽ,2d€ü%Z"à_oºR1ù QâÅ?mcÉMÈ"@›÷Ò[¿1Ú¯ø9­ ƒÎÍ ,Õ´Hp~†bøv;þt?f“|­wõE¸í?^â«{R¯Xƒ{õ©X +Ô´u€KÍ@Sµ-ÀÍh,€Óýýs‘ðà3«Ó"ÿoÖ Ð¸›„BK0„3»~¦É.Àå®±3º­)\tþtEׯþd/ëÖ«­%‰  »ùݶÙ^„`²»úÏ亊æ,À]É!‹f`6›9oæ8Ù×·v…øåÊß«ú ñPý Jú,ÎÒ¡®8)Y×Ú€Ë]S ,×ZëŸ{îäËwþ}þ}úêæô·Ô#ÆÂò…ë(î’åÉ:׌XÄÈïÑ;ã«åï †ã¬ÿ(3±’$éi“}½Ñbî’TZ\SKW A”—9e_»é«â±xÆž%ÚÓ.Ÿ³%kuž¶’[´jR%ò°ÿ›¶Œ>K"”OŠI–ºÜ5ùZ°iÑü@þcµud6ˆ$ÆåG †¡–‰ì.Ö‚4iþŠìòH·?óQÙ BŌƬÔ}Zp¹k¢W4 AQ´O¦7ï ŒòCϤ¸¬ÀÅ醎¥kæ’;{öG“¹Q§R"Ž$ÊZQ,ÎI\®S+slo—?lãŠR]¡ 0ÌÿшE³ÆAÊp¹kŠ€Suj‡‡1φÙY&ûúx¿¢ôB““9³ntòe:öj‚ ¿ª£½íJ ™6péäkÙ8L¶Bý”x¨7' [€aMÖÊIŠî‰öv¤2$MY&]òú бSfú¢þÖTŠTè4§ÇO#04èjãèPH9En:]€}4wú´ ªŒõ §ÌN9*8Ô²?Õ¢#aYjRL f ‚`¤Èaeâ¸2Œ26xXåO½^}É™ô‡£|Q[?äu½}ýÔ5tHˆ&3“c¾‹³Lî*Þqñ·*þ©ÒM𲂳½‹³ ³­ƒ)Á4@âfáæN£º¬ #:sØÌÜ~ÍùÈ™YÄ|öuO½ñ5]½é' —qB-uŒDcÔ„°8JÉ+®Äì(;n\üò«¦sÅü hyf#î3ÇpÎÔ2îøïÍìoêMƒ}‰¾CµŠBÆÔlŒéøigU0Ùœ8'…ãä™X +ŽKþ3*5Eþw­Æ}×ÌĘFŽàá}Ä]#ö#’(Ò`±â?ƒÂÉç`.(òÚ/œ¢içñ”j's\©ÍĆ;›w6ªñœ€Ù^BÑ”ÙX ‡¯4³ÉÀä*'Z‡kB‘â{úÛlÞ£Ö#¤ì=š²YQùeã)¨œ,{]Ün5a2jÿL‹"»|ï`Çhª1ˆ @À^}*yÅÊòïu÷Eiï S^˜¯iÔ5Ëk€‰h?Cµé ÷T·Yél•““ÿ7lÜÙªiòcq‘m»;†¼FŒG 6ïÁ¿ws&ȇJ´)€¼¢ ¬å©{ñ«ÞÙM{OX³øŸ÷öÒØd|#ÔZÏ&ÂMÃe M{4)“ÕAÁØôVƒýq~þìv}£­s£1‘U«wó‡õGÏб0áŽzëwÐåÛ@ÛAEÑÀÙ@æ|AÀ>îtCz“qê¿iá¦_6pÞŒ*NŸXÆÉc ‡œ .°Z˜5õ$E9wè¤Ã?|ê÷Þ`ß6íl¢ñpb<‚‹"Æ#$¢ýŠ6€ŒjäÁ˜gK‘ôá®f¢=íÄûÿ>˶¦nkdþÆŒéSyíù[éóª—µë6‘£Ð–ƒkŤ”îöulÜO/UîÎÚ½ìoô3¥ºˆQŽ:Ÿ×Ó®)ä—S¼2&‰q‚ÍûˆtVí9"±'ÞNËOËĘ_éz¸‹ÐS·=Ý‘o¥s³ê£“Í©¸õš|:ù©¡ب)È™ã?ÊLw5ëëÒ©L «Ó=pJ}(Ú&xx¿Nã™Õ`´X‡Ê B-uHb\§15uš€Á"ÑF’Äd ¼Ž±Öçõ„µ%SžìkãA6¦HuóŸU˜å{ÿ‰HH§0u€w´'@ŒEtSÇ>¯§[s@ÁÂ$eþ¸\‹Yþ©xáp4WÈoVªF™šO¦$±k‘*Ê åHZÚrf.â¿Ô>Fe _Jr椂yófÊ> 4MÐÓÈܧæYê ®¤ °`²e.ä{Áò†k÷÷çù[}^Ïëjÿ¨ªˆ‡ƒŠfö¬'MÌHMM˜0–KçË?·â«½‡sA÷dâGÕH"±¡OÇ>ÚKw”’W¬îÉr‚ ððŠëÈ·È|øéN­“ÿ®ÏëùXûÅÓ»US0˜Õ‹ûÿÉõ‹™5U~¾„H,Á'¶k™üè|LL†Ð Æø‚Á„½Zl3“&çökç+ºgKm3ýýšEWø¼ž¦œ€$Æ[³½ç¤YŠ“¾‹K/™ÏËO-#OÁäÀŸ×mÓrë¿ÙçõlÍd‰ µÖÄòòÍÅ2‡PËþM2QTTÈý÷\ǹʃPwèdÍû´Jþã>¯çåL’$"!ÂÝÍä—ŒUæÀŒTMÃâ<‰þ¶ƒÄBþAwÓ:X¸`.·_ÿ}J©YŽ'^xW³N°"el_@ëòŠ*‡: óØ­f.>»ŠÉU3Sº`Œžž=}!zzƒXó-”—8˜0¶„3¦”§•˜aãWlÚò¥É÷פê5âãQB­õŒ9EÖõß;£’åK§SâÈüA0ç‘gÞÐ"ù]ÀbŸ×Ó›­3º=<ÜÑ€Éê ¯hè#&W9yàÆYªí>¤0%‰+ߤ¾þÉ¿ÜçõÔe³ÐŒ×x°q÷QÛ»Ž‡;—œ–òž{m3þe³Íþ¹>¯'ëiÆk]’Dú¾Ù9èB‘Ñ 0ýä⬼ì›ëyö…ÿÓùk€¹Ùnùjt @–‡7°ógŽ 30Y^ª(¶*>Ü9üîÝ/xÌó{­‘ÿpÏ‘ßw¼»V¤9oAˆ"|O@z@4ö_¿éɥ߮\Í¿cõ’`ظñéEëFB>@öÉÌb,BoÝ_)¨>õ(Ÿ ¥»Ÿp4¡hî^ ¢1‘Ÿ}7ÿü-~æóz~{ŒEìµ]N‘??.š?•$n‹cøÒÚgÆÁ%†„õC`Àü[ß8®W”ü¤žNÓû<•î а‹àá}ßF‹¢ÄÆṲ́9ÔÚÇ w½¨5òÛ÷ñÈøè·îðGO]é’QèÛòëK¿u ø7É,-C…l­éX€mÀORDý­X+&’_\ůßÜÅW9v«Y•îì ³êxõHÄ5z¾¸Åçõ¤2‰ óï\³ÈTì}?Þ\† CLÙ´ß'6íCÅ$þåéÏxäæÙT•ÚRþM «ï}Á‹/­&ÒTÇvà^Ÿ×³>ž”$©&ÑÈGv°'ÝóÓÀ_­À¹é<@"¢ïP-Ûwsuí\µø<~ôƒÓ¨.——º©=ÀGŸ×ñá'_ðù絈’¨%âë€_ôy=igˆªl¾Õ<ƶAxT„[‰E#f|^OÂå®ù1°H{A_ãt6bÕó‡Xõ‚gq1ã«+WUNuU)c+ŠI$´uöÒÞÑC[G7MMm8؈Ñ<<ŸF _PŠ‹a€>‹#a%èýõ¥‰óïxçà®O/Z7ÿÎw.2R0=«’&\îš»€_¡6l>¬ôy=i%œsûç‘à‘Ïûùû%›ž¼¤ëì[VÛ&u÷G^}ib$`H:7 NPÒÉ÷‹Ð­î\zxUñºÜ5FànàAÀrÞ¬N’¾Þçõäì>7U31»Ü53€—€Y£ôÝ $dzج†S7ꘜœüv!sÚxc Ùr_Òœ÷­I¿ýø¼?:tèСC‡:tèСC‡:tèСC‡:tèБ3ø¯âÄ:FâhËIEND®B`‚kimchi-1.5.0/ui/images/icon-gentoo.png000066400000000000000000000357131254252253000176030ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aËbKGDÿÿÿ ½§“ pHYsÃÃÇo¨dtIMEÝ  6þÅŠÎ IDATxÚí½w˜dWyçÿ9çÆÊ»§»§gF£Q $ ²íõÚîíÇþaLr›ŒMð’Á¼`¼¶Iv±H„`Ve43MîžžŽ•n<çüþ¨êžêꪞIç¹}Cݪ®ºï÷¼ù}0Æž?·Ãþ©ÿ „0ëºý À¯â§ð!ƾãöb½¦ó†òR­y’Öl5Z %0Fˆªâ°<,¥¸_)}‹m[G|_Tž÷â­•ŸwPüÔ`öH™ûî:äĉº0¨§oŠc~3Š%JYh#146` A¬ø¥@ ƒ%Á¶ žg°,>£I>ÔßWxäÊ«6¤`=€ÓæË5Ùúõ×ÜùúZM¿3 ­Ljl[iÓ$º´l¤t@ˆñqt/„DZÍû, €Š#â(@ë)À¶4Žeß73–£ÿø—uÛ5ÆX ¡'p2 ÿíoÞñ¢ò‚ùXÙ[“Ô±•±1X`$²‘ÒÆ²l„°ÂBZß·pe ­ I¢‰"M+ŒÑM¥„eá86Ò¶H£ˆ(¬!08–ÁµUÉpŸ›Ñ¯xñ/n½ûgYDœN0B¾ù¥[ÿ²R“¯Œg,ÑÆ8 l¤å`Y.Òr)\‡JE ÇX¶@ кm3`šÇJA’âØÔSªµƒA °liIÒ$"C¤Ð¸ŽÁwõžLVüÃ/üò¦ý,ê §„æÚ/ÞòÖz`½-ˆœ¬2à ,ËòpŸáaŸ‘ ½=×…TV+‰­õQ‚k ʬ<_ÚŒil*…j-¥RI(—C´6HKbYÆhÒ$­plMÆ7‘Ÿác#Î;Ÿzцàg§ Âÿ×o†¡ø·Zຠ„‹%=l×§TÊ11á±i³Ä±!M;S5 ¯Z¯ë£×u,ÓØ/,ÄT* õz ,ÛF`Hӌ–ŠlÖñÅ{ûGœ¿¾ìÒ‘r’haÛâ ¬wÄQ‚ç»æº¯üp[Šëª5çÌTûácÙ®—c ?ÇÙçxlÜIr”X­D[žåŒ:Ê–AмfTƒtA÷кñÃP3;Ôc´ÖHËBPiFãXŠ\ÆàgÅk‡6øŸxêSB¥´R<€cŸÜ~<ðHåÝõºýÖ0ñÑd–‡çç)• <åb— 0Ä«n'üÒ¬o­³½ý5mŽž«.\ ]w ¹Ÿž‚¥R„” *‰‘Bc[šBÎÉÉ_Û¼9í¶³ ê ¬1¾ú¥› &ò÷U¯¤t#3¸^–B¡ÄOʰu+¦‹·O¬"Vë¬W+¯«v‚·ÜÛ„n hå:ÆÀôtHD(­°„)Pi„ÏÖ T ½ÎE—_>ðÈO“H8áÐZcY–ùúÕß}]­æýMûh‘AÚrù6l(rÙÓ…±×ã”naÁõJ,‰„%¬¸®»pÓE¡lU,›ÿwv6 ¢AȆG`YÏQ”JâÞÿÒè“Z”Ä €Ù# õškþß÷~P«yWÄ:‹<7OOïO»ÄaxsÜlí„_ÕBpÕA$´¿¯›²Ø&~LSaŒcÍìl$U­ÒBë)LCQôuÜÓk½ã¹/ùPµšŠ\ÎúùÀ¾G‰{Wý»k?‘š,È ¹|/££=<íi|ÿ1:tí hB«Pºƒhè Hvµšf¥1ã H™ŸÐF7L`LŠ- ®£(äÙ90äþâeÏØuºr„ ¼÷ÇÛÏBÿ–ZÍ)‘AZ9Š=œuVžó/x³¾z%Æjz~•j5/ž ±Š{ttð*@ê£/·n˜æ±n„Œa “±ñÜ‹åˆz=BÊ(ÂX’.êmQïüÎõSïB¼ý´ôº>ž_ʃÂ|ãKß¹$ ÜÛêa%²ØN¾¾!Î’ÇæÍñ»é­[;WX檳îÐIYìÆ–î£)&¢X³PP±BÕQ…% ®­)Ù_ìu®zæ3û>LÆÇ Ƥ”ækWûâ8t\r(“ÁñJ ò”‹]††OñÛD = è­×Ls¯TÓ±Í×°Ìþõj ,Y X(GAŒÑCC4Xl©Èe5…¢õ²ç½pèŸjµTd³ÖÏ„æëWçÉQàÜÄ9R2¸n‘¡‘.¹Ô¦§çÄ¿“^ TÃÝ«ÚDÕ]?hÕV8•–ˆO›#ÉUZ †ùù:Jk´R4R¤4xVJo¯¼cx,sù“Ÿ\HfpÝWoº ¬9÷ÔÂ,Š,¶[`xÃ.»Ô¦X:9Ä?j{"–ˆÞ €® h³–EA›¥°ìèpjÀÒy¥† Úh´V –4Ø–¢3¦gÀyÊ3ŸÙwÏ©€|¬P)W¹îkßÝÖ=õÈG“Ųs pÉ%§€ø_e, –ÕØ¤–Ùaí×Dóº8úzÓïƒãåM¶·n@>ïÑSÊ"…IJl@’jA¢l+–˜>”ÜõÝ›f>'„0I¢ú8€RÛ¶Ì×¾póB¥–))S™ahdœK/uM_ÿ)æo‘¦m3¾9Ë—®ëâaùZ²i‹˜¶c»n@S””+i¢–¹”` g+ŠE;Ë9Co>îp~z8€m[æÚ«o¾³VsKÚdAxôŒpá…§ñf‰ ,mK3~™;È•3~Åìoá+89K¦cË}ÐøŒR1C6ë!„Ä’6Z ”–„‰Íü¢Øº÷xæ¾{.[orëi€ë¿zó?uû"e²áS(õsæ¶,FO#;·)d á[‰½æÖ$¤ä( º»ƒhBÆw(²HÙÌ9@¢Œ$Nm+V~qÞü×wn<üê“ ‚G!„¹ñ›ßr½*^« † ž_dãD/gŸs dþ±¾¯Õä- 計պA«¬o×–rPE'NÐzÞ²·IO)‹mÙHÙHgÓFj›JÝbqA|üÆëödà¸u€4Uüèû·e*sa­\Íš<Ò.06>ÆeϰÉdN?,é­:€JYEiÚÝRh× ÖÚ:9ŠZ­ƒÖж¡±¯Ö"’8i„ŸB°¤ÆµSJ=æÇOÏ¿ê9£'09õ¸9€ãØ&¨EŸªÚxáQêégÛ¶Ó“øºáÚ€´0Ž‹ñ3˜\SêÁô`J½àºG9C«°Jëߤ\) –|ËK‡ù¬G&ë#…@HczA”ØÌÏË-qÝ­ßðíCpâžëqq¥4ß½ñ—ÖÔ-õ0"çõ²íœ.ºøô!~’ j5H°mp½ÆŒ ˆÂƱã@& Ù,ØöÑïž$ˆéÃÇëótL13GSÍZƒG­œŽ§ÊP©Ö›VCÿ,¥Á– ¥H?yòsŸ3|ŸãÈSËlÛ2i¨¾%.!=úúûØzæéAx•"FLM‚ïCÿ¦§“Íbr9ŒÈC(¡ªa¦û§à¡]°s'bú0B+„ã`ÆÆ1›0ž×"û—t.Šd>-ç¬Ö–Xe ŠMåPˆ†‚¡µ Õ‹AZsî¹ù{S¿qJ9@Å|ïÛ?zYP1ŸªGy4yüì\0ÈÙçúÙGˆýÀsalÓ¼ãnÄï<Ì‘é y‡bÞÃÏd)=‡ ¸P ô`ÃØnã7ìÝs4#I­‡ ´x WqÿÀ*½@Cµ¢”j$šƒ”º‘cÑdóê-/xáȇ´ÖBqr „0×}ù¦©ZÕŽu#óŒŽnä²g8ds§ÆÀC!´‚sÏgź{;âê¯ÜG¥RƵ5™ŒËb¹L!›¡”ŠEƆÛØÇÐH¶–‚áj&«h {A„á1@`V‹ÚD”Á€jµˆ4M›U7ËÙ9_“)¨w¿ð…Ãÿ+Ž•xS‡¡ZƒÉÃGS»µ†O~n§PI3Æ‹lÛ܃Vu⨌%¤¨ ˆ8/ñ=M-¢’ I´H- Ô"¶Uáâó{ñD™ó·•Ht…òü½9Á·<À#û&ðàƒ˜À–-Öa²ä*fµg°Õlņ`%§Èf\\Çi*‡c©± ¨Û~ã ‡ÿ·m[æ„`Æ Ÿ4Z‚°AX8ŽKOOóvšØú¤©"Ž5óópÿ}ðÐ}‚3¶l@¥!qPE'A£ XÆè´ŒQUÒh“–)•$»wì`ãp)ËÌ-,à»?øÞ uB®MÚH8㌆’ÙÍó·DìV@ µe'ÐÁO`€lÆÁ±íeëÀIª-ê¡$¬Ù¯½á†ÃûXüÇ$áí?º]z®û‹ÆXá -×ó)9-Ч—Ì4c Ji’DÇšz ÎÚ10%ÊBȼ´lÛ–²á¹:MÒ-«áèB*MªI¢ˆ¢”°¦¹üò§bÛ)B¤M'‹Â¨£# F…óäü„°>O—9kK–ÃÓS<¼c{÷ïcûö‡0¤ì}Da}&Ø´¹ÉX¬¾NÇhÉ  ´êÍ@’mY N€hr› ”¨ÐÇuß:ø?Mü@+œZŸŸÛ$,Çr\Ûµql‰Ñ)µÚ‰tPßǵ0Æ µ&M5qœ1&1„¡Æq$i¢´¨Û¦af‰‹€ß³, ä2š¡[¶&¥¼Xg~¶)ŸÛ•AV³ôNJ¡è¦ ¶)ƒ«d³.–%—A  Ñ6õP Óì¾yýã'ËcØþTkÕ+R$±ð|×µ0F17gˆ¢Ó£ƒÆø8¦Phè$J)Ò¦(BEm1"I%–ãEq㉷úc1ÍkšzœrÁÖ"‡§gÉøŠ Xdrr/˜­B’¤ÎìÓj^-û;ÈýöÐpkˆ¸“(h­â!—u±,±‚$Ê¢Z—8&{Ëõ7ܶ0o? ¬×swÜr16NÖÃÍ:¸Žaa¾Âþ½M®zЇ”°qry0cHµ!Š ‹‹1ç{ uÇAŠBÐè#ÒºÒ Ï¤J ÂB‡ØVÌ@Éaqv•¨4¡\IV+}¢3:p•âׯ VÜßÁDÈe–¥ˆ‚€‡–hãˆñ Œ8ÅfáEBÚLNyA€Ö¦ñ€ïŽñ¼ç¿âÞg\™yžïˆ õ}¿óÛoÜ:<ýp¯U¹:[ µ‹Ð6½yÍYçmÀ$Q “ÆŒ[òîÁj#~Ù„[jT¦[ˆØô.K6…{i¦·| ,y›{ÛøžM¥hÝø¯©‘@Pç©ß¹yæsBˆß?Ž ¸ú_¿`Ý{ÿ#‹ÒÊd«õ©°9cË\öŒË0±" Æ8ŒylÙz4ˆrªFÀw ¦§S*ÕjCV…àØš|V/ÙR,9ŸºøâLÚïxÅüÅ×£èï„Aô|~ùW‰òœGd@ä¸ð¢ β0Qìn$™´w'Y beâèZ‰"­!bÓ€Uû–ã JIݨV` …c+ 9MjÕ.üÅÝû˜ƒAo}㻿_ ô•ŽÝÃBE2:>@šfyÑ/¿ßvIê1Ib(3l>úN-Òî¼15e˜_¨,óY­,Àq4¾GšË[?ÒRýé‹_8twûgüîo¿æöKžzÅÓÆ6\@=²ÐÆ£§wˆç>?G¡€Ù¹£Q{Ð^LÒ1B¸ž,¡v¯ƒøKÇåZ£Jã>…c)[·MpùÓŸLXN‰#ï9Œ FFÁvNâvïFìß•jJÄ)°£I¢’c4º 6jãI[¶ÇàP/gŸå0¾æÄo-Fíš+ØZNÞ)3ˆ¶ãN hã­@h (¡&NÒåm©pM>§ñòêâ+¯è½ë1å¼õõùS3õWńȓ¤6¹|žL¦@.ßCYÇãéϸ37U*1d³ãã‚!°ìS„(‚©)ÄP.k‚@‘(Ý4OÛhƒJìÔ±-ò—áa—  “08Ú©¬=y´S³ ÓÞm¤CŽ@ÇÄN XK 4Ï+5…R [Â`Û ß5{Íü³žUìëDëuàÏ_ÿÁL½¾P[¨Fœ{Î…BÃ3ŠÃG",+C±PD É|-etl‚g<ã"z‹9âš"M¡“Œ ú0–Ã)Õ*bnÊe¨Ty‚iÚ¡¶ _P(@¡Ð ¼`%áÛËÌU‡ÞE¦½w¡éœÔ1C¨EXÅúÛf~+âØFê#I£®kkr9›M^ù¬+û>ÕNïãÊzëÿâó3sµßÙ41B6+Ée³8^ž…ªËÁ©¹l?½¥<õ$á12<ÊYçm¡˜É•@>'…þAŒ}ŠÐú󒤑®uÃ÷Ô^¦½´¬ñ—JÍÛÙÿªbÒV%°=C¨MùkŸý­ŽËv Õ"­Ö4©n4LRaÛšŒkÈÒò³Ÿ]*µÓ{Ý–»ÖZd¼ž?Ég=fæjLOW9ppŽ8¬SÌDœf–‘!ÍÔì&UxBSxè¾ÜqÇý('Å/J‚İc—æ®;‡ö#’ø´p'ÇÁø~#=\¶fò´Øù«âútø,—ãõµ¢‡kÞ»F‚ëJ,¹Ô0[‚‘h-A9Ånž|Å£Kêmo|÷¯MM—¿<28€Jªì›ŽxÚÅ£ø^)]F¸ì>’ËÚÆÏgè-õ6ç}{«Øæ_õ¦×¾»èåï¨õ3ƒ°Îà`?…¢M',Nä2G{H5™©²{çýx~†Ñ±ÍœsFÅ®½s‹ýL9H©—«øv†›Æñ}ë”˜Š«rþ;äö-•‡™ö$³2H‹…µÊ{±2[h™öÍÿõ”§@®­LO(× 6o˜›Y`qvO”Ícqרùà#üÝÇ?·Y©ô–bNY– ›Ë¥I³3‡Æ³%ýý½(e˜™«²¸’ËçßxžŸ#J4¾Ó‹ï–0"ËàÐ(ÏQv}íåƒÐQö·øú•êÞ`]Å¡]\¿k…}M—°÷yç•ù­cr±ë~ÅþC Ü{ï]TËG¸ôÉÅýÿßË~ib‰î'Ô¸ÚvÎ>öÞµçÿ|âýÕÀ}R¥fíQ©Æ6‚Œkáy‚Ô&§g™›_`°?Ë–-ýòÀ}w¢Óccd¼4z†yÞ Nñ)ÚV¦€µ×û­˜µm®]ÖáΕí}[šT‰Ö~†-= 1°iSgâG)b÷ƒŠ]»ñð#˜ŸŸÃuêµpŽ'åQ6Ñv¿bË«^þ¶K yû£½EûÇBYšT+’TsøÈŽm14˜ã¬³Î¦¯çLj¡‹6>ýƒÃ<ÿã¸'/¡¤« hË9*„Û+ƒ»±yÓ…í·W/‰c`t6nì¬ÜÿìÚ}„L2sx?–è³Y,WBÓòãNê\2ƈ½{Þ¾yóøå/ù½7]<:\xW.cÿ·œï¤)‰RÄiJ6?BoÏ9ÔBe|†††yîó‹ÆóO<ÑY‡Lq±"Ñw{[ µ¬MKhÄpL“=›† ¿"êg``¶œÑY…ر qÇíû¸óÞûð\‹óÎ`ÇŽä³½T‚›”ÒÂjvžtfºiÓÆqäÈÜCCý¿ü;¿ùڱѱÒßõ•¼_͸6ãçRÈo£Þ$þÈèW]•7®wR]¹@‹þ¶"xhWøX²]ñy-(beÖð .ÐòÞR©‘ßé«?²qóÍ»¹ûþ)|&6¸<´sB×IÓJ™ÏZ-U½§Í‘çm{žõú×ýéábac˜xã1¶qϾê$É|ƒh]b¦«¹§½È”n‹úénîÞGaîespàâºoíå'w?@_¯Ï¦ YMOóȮ휱q¼ó]¯ÚØJs›Ó`‰ë¯¹÷¶JYö‡‰›·Œså³Ý“ZpbºÌÔõڇ˦_“ H³z›N¢ãæÞÒ™ œÓ…ø“Óˆoß|€;ï}€‘¡,ƒ=;vM2=½‡ ýElÏ% Ëÿü¨3‚Näìÿæ—ï˜)WìþD¹ 3œuö—>]žÜj£6'P'ßñ&~ÒeÓéÓÍË×:r8³Ë²zSӈ뾵;îz€-{IƒEví9D­>ˆþ #CLÍLW>úÑ×Ûé}*9€ùÚ5?èÿúïØ¿Xv2‰r±œ<=e”óŸ$ÍÉçBÇÐþ;sѦÁ·ËÿNºÀ*íIæ·iù­£§&&:ÿð4⚯ïæÞvpÁYÃìÝŸQõÉLIDAT³— ©Õ§éÏ2Ø—cvn‘4®ÿîcJ }¼gýu_»õ¹qh§VwD¢]\¯È3.aóqò=|më®YíÓaAê5;u‘ùí`ëæä‚á.KíœD|åk³k÷nÎ=s|/ Z¤á"=yêµqj®þðß¼úv¢µ<¹³Ì4‰Û¢º}SµæŠDydsý<÷yN ñÛLÀcqÑÍAÄúr÷d{+Ù¶vô²¥·Ðئñ÷ìG\ýå]ìÛ¿m›û¸ÿ{m&6öb›MãÃÄaD†ú½—N:Òq¢Û'“øRJsÝ5·¦^µþ RëMo}y½›^{ÒDÀ®ùª(‰·VËÖÓÂÄÅŸá‘ažóÜ<žw “A—Ö%VÝ ›6ò¬gû§¼¯@ë2´­ 0f}X:_"î¤íw+햲ы°“ß#Uð£[BñõoÜÁ™ÛF8°o?q¼ÀÐ@–ž¢KÌ“$1õJ…Êb@*Ó¯|ø#oøõcµ•=Ñ"À\ím›Hì= ‹TùËçœsǹäRûÔwj:VÌØcÅXɪW·ûðEÛ{Z(ßJÛ†Í[:ó…(F|ç¦27}ÿ..¼ð x`/d¨¿HÆ7Dõ¢0"Š"‚jDbÔ÷?ò‘7üúcnñXÇõ×ÞölYß«TmícÙ.~ê8çž/OöR¦svn{­þzA°ÊÉß!PÐ)0”Ɇ ‰¿PF|íë“Ü÷ànÎ=gœÜI>04PÀµÊ4qœ€„Õ€X¥;?òÑ×?g½œý„@anøÆm¯ŽêÖÇëCª=/Ïå—²éjúí³Ÿ.²{)Ž‚%°tã´¢‹}ÁFƒ«nfÞÕ_ÞÁá™z{<ö<@_IÑ×SDèˆÙ™¨4FâS«U‰•ZÙ”9/ ãu ÖÇZk,Ë27|ó¶¿®-Ê76B¹™l‰g>k˜ £§Ï¢ÝÒ²—]¦»_¾uæ/;u: Í÷+Úˆ?2ÖX“ ÓØþâ‹_¹›ùÅÃä³YŒ î“d3& 8rx?Q\DZ²Q ¥UìdÌøëþìUêxžÃã€0ˆÈd}ó­koÿÇê‚|U5–”ÉûxÖ• ŸFËÉ4›=vÊÉ?–s¦“ý¿¢—O?{<ß¶`x¤±Õ*e/…ÞZ×^wa4G!_¤§×¢”HBtTçÈôA¸†Ä'‰”N«Xñà»ßóÆèxÅã€j% PÌšo}ý¶OWÅËÂØAbÏW^ÙGÿàéE|£;Wçv’ýfß\ˆ•æ]«²'[¦¾ü vy•*âú§ùÞÞƒ”!Åbž±Ÿ¬q¸@’Ô™›9LªBÐ. Hutäáù>ÿ‰=ª†}öã1ó Ŭ¹þk·ýKuQþ^»|zzûyæ•}§¼_P7w~§º<ÚX?ë$þ2ëï¦ü5¯•ŠP,vå^síÃÜ¿ýal'%Ÿó8c¢„-#ª•L²87‡&Áµ³¨Ôªhÿ{>øgós‹Ú˜~LÐZ7Ùþm_ª.ˆ_ƒO±w€g^Ù{ú_7œ>«5ÐY#9è¨7Ot¦ý²~ `h¸3ËW î}@‹¯^{ÓÓ3ضbb¼—þ’‹ÑUªåytR^\ÄE!_" ÕýïúÀŸN92'zz‹œX–enüæm×–çùo$ŸB©+.?}‰¯»TåvMÐè6ë[Ùýy¶Óå×øÑ­‘øÆ·nG©­«<åÂs°L(,GÒ¨N­ZGH({H”0®îxç{_svP…Ÿyl©RÉøëoÿRež_«GŸl¾—§?}ѧ/ñÛKµWdìèÎ;j÷¥#Å&—ëüúþCˆoÝx€;ïÞ‰)}½[7¡“ ZÅÔëóÄÕ a”Šb)‹Na±<óÃßxÉ¿òüm[“ýÑ@an¼þÖÿU›çõÈC?ÓËS.æŒ3O}ÇÐv??º™˜Ñ¡NÕ¦»˜ˆtßw«“KW#îºKñÕkïd~¡BÎó´§l%ç’¸‚%ÕÊ, ssÍMcz{³XÂf~aæ“ïþÀë_õxºïBsãu·\V¹¹VwIµã9ïüQÎ=OœòN¡íÄïVœ¡×èÕ·JX'ái”a—ºD6ç7Ü8Én݉R1®—páy1i C‚41•ò ÓS3(q\¥¯7‡çyTªå×¾çoøØã»9. R¸é†ÿ:3ªss8(í"­ ›6 ³yóiBü¦‡o™•ë–´¬cµhi÷˜c{ÿZG©§Ñgh•2ðð#ˆ/}å^ö8‚V›7õ01:BVBƒ ™™™äÈôA­6Goo!åÊâïßxí‰Ü­añÃ[d‰(wk­"Iµ²‘³¿i³M¡xÍú&á—,:Ó¡:·ý|…‡Ð¬Ï \‚m7ˆ/;ˆ¾j qËm5®½þÇÔê!¾¯¸àIñ”8ª HÐIÉC™_°¤ Z›¡Xðq]'ª×«O}ÿ‡Þrÿ‰ŠÚ®[Zg²¾±âì—‚ }‰v0¸äó=ŒoÌÐ××L‚ÔÍüæ$vþZúº%¬ÛaÇöÒlÝÕ·ûÌJ‚·ÿ°lzûV_›FŽþ¿|¿æ‡Tª ;\ú” \+À¨£ê$Ñ<²—ùÅϵ‰£Šß÷öÕkõÒûþêÍœÈýº9Àµ×|÷·“ˆ_‰•ƒ1.Ž“aÃhƒƒ ­F]˜£iOˆÆê,M[øq/ãnuÁšc5^\«%˱úñvp±û¾¾ÎP¯Gˆ»ïÖ|û»÷°gß$Ž•rÉe[ñDBWÁÄ$i•$ª±gï,FòY—(\ ›õ°yÇ»ßÿúK*•Ú ŸHë€ÂÜðõ~¢Z•(ã‚t)õôÑÛ+ÈdÝ´Z Íê•]ìä®àèÆEÖh¯Þ‰°k*vÇÓšu7\]нôþ=ûwݵÈwt•ÅE6Žõ°uËITA[ Ò ˜j¹Ì¾ýeŠ—8®a[mÒ¿}ïÞüg'+Sk]VÀu×~ÿZº¿TZ¯§,5¶+Ç6Wþë—›Œ–a#°°—l¶I|@É£+dudýÐ)[1ÍÅúÀÒÊàÍ?FtQàôÑDŒõ¶ZoýG~vu³¥¥÷šB<ô`ÌýîæžûvR,ú\qÙfLEUZÅFeîøÉCT+1}¥<®c;ƒœ¯×«/þ‡O¾÷¶S]›¹¦ày·´IÂC‰6–´Éå›íQ[WÅêÒ {M.`:8VÌÚ¢ £K¶k×ë˜ím"f-‡Îb ñàvÍž½³Ü~ǽÔ€']°‘BVE\Û ÒD ¦Îää$ÿuËä³y 8vc•Í$‘wüý?^pÉm·n‘ÿ‰÷œúÒün|ÏÞ–yúó_TCeˆC8õ1Â'—ïç¼'å6;Û—]ÖÌ]C<^e×t \×Z;³Æ{V³{Ü®ìH!ví4<òHïgïÞ}ôõçØ¼±—ZµŒçIT …Á¨€4©ò“{âÀþ#  ÏÛH‘¦©ÖZ¾ù“Ÿ~ïGêõ@d2>§ÃèÊÎ>ÿœs®°«lŠ£å°K®Õ%DzylÖ¡vRaÝùk`=3½ý4_è\…£ ìŸD<ü`Âéy¦'§‰“O¹p3I\%ŽêØV,RTZ%«ÜvûvÒD³yã\ß U@’ȪçeF?ú·o¯~âSï9M–Ý^qœDÉf¦x9°$RƒF¢µ^®Š‘¢Cc¤N"  h'ü±€Ð-@cºÙ¬åÚnvԫͺ©9ص]q`j‘™éy×PÈëøÄQ)„ÑRÒ¸¦ÎÜB»ö’ËdÈf°¬”4©âKO}Ú¹¿õ‡ô[šÓpØe¿kÞóöo>od–ma¥­ZTš’¦]äþ:eÿ*‹î–õÕt=Y©;¸.ôtðÝ`¶Šxø!xx÷šÁs ÂÄˆÔ -Bc[)* à ŽÕÐöçêLMMÓß[j¬®NB¥GÉUŸþ§÷|ïo?NÓÑUh­‡ï»ëAžõœgb;­JŒV”ËŠBÁZs”c9€Öã ¢ ‘3²`§¡àátósb×xhû${öNbÕX^ ,Çàx …"Mb ‚Ñ!®åjr¹BO©€D uÂüBíF¥Õo~ò3ï)Ÿ=˜Œ0j~®Œp<,c°µDPZ3?['Ÿ/,'D¶:‚tK@È´ˆMó eQ›£çí¾U@,wÑ0-ÀYOʶ%Ù¸™Üj&1½ˆØµ+fçöivíÞI=E Çx®ÄóÁ’š$ލ5¢°‚ïi¤Œ ‚˜J-$<ÇǤšr°X©¾üsÿüþÏ><+>ñÉwŸÖÄ_–%ƒ ÎžÝزe–[N a˜ TÃ7¾d»k±’ˆºX‚B5ÎU[m}W@0¦ñÝr9(W®1 }‡Û Ø¿gŠ}‘$ŠÁR# Ž­Èl’8¤ºP!¨/bYŠ\N$u’DS«a‚Šׂ$¾Ý±Âçösï¯üÓgß'ÄiOú5P.WÄG>øñž+¹õG·0±e+¶'0F£ŒF)Å}eÆ'Š«üÿËìÞt°:°}±%ðxfÆo˜uNKßÔ vì øÁ÷ç‰êUfæf˜_,3±a) qR§X²Èe]â0dn±LP« Ó€RÉEʘ(Œ‰E­R¯)‚Z‚„QRÝ?}öýÿX­6·?-Ä_Óð¶·¼ÿ¢0H’‡ññ³Ø0¾™3&Æ ë†(­FF‹d³Îºeÿ£Àš³¥ [›Æ2)ÅR#IÑA‚ص'àÚkÄ¥SMO±e|)-+ eÉeI²¸0OP¯¡Uˆë(J%—8®£5„ALµšP­ÄD±"1ñާ7rÞ+^÷‡Ú¶$?£+íúøÀ‡oT½½2…qffë\ñ¬g2Ô;@XWD‘@kÉØxžo­Öþ;þx ÄD§ÙÐ)m”[åòÏãB¬ ÂöU¾yÍ]ô”rø™ ÕZž¢C¥¼HµnÉPÈÒ˜ñ³3ÍecS’¸Â@¿6J)ÒÄP¯¥TÊ•Fý}j[ñs>ñé÷ýˆŸòÑBó'¯|ëŽã¼ sH?Ϧc<ûyÏ%©EDuMƒ1#Jø«» Øe¿¦O ‹(0¦±Ô«´ëãd²ŠÒ†DÃl~ø£IvlßK_O/㮓pdz†é#‹lÙÜO©`Öë,ÎÏ QA™|^â{š4MHSEiç*•˜z¬Vü¯7 ¿ìïüÓ”Ÿ±f8øå/}ËE}ÅÜOl/ËáiCo‰ÑÑ-<óª+Hêš°Å£%ù|†!¿­]¿NS°ý~­!šJ‹Ý`õ~¦Qucd#Pyïýî¿ï0ÕZ¬'1:&ã{(4³Ó“,,V™˜è§¯'C¥¼H½Rò–4Äa!B mR’¸AüZ%fn®N¹š`,uÀqyþg>óþ‡Êåª(rüÌàïù˜½óáq)["—/2¿˜²íì­Ì,žõœ+(ærDõ„(h,-¤M±”¡TtV°êcr%S¯ ­ Š!Išá_Ùpà¸nƒÅK° n¿ý »wÍEFÇô3,–ñ¼R¤hÐSÊËØ,ÌÍG¶%‘R“&uTZ'—X¤IB’Ĥ),.†LM— ãÛ/ù×ý࿜î6ýã!„yåËÞô–í~Ѳ<ú{†ÈåóÌ/&Di–‰­[¸ì’‹ÐQB*âH5P2’LÆÅó,<϶–%VK¬¿e¥­ÖU9’´qe7f»ã4ö–ÛØ”€É©;wLñÈÃÓ€F…ëjµ: UúûJ yärB+jÕZ“ð`tB’`"2>¸ž@¥ªAx¥I˜™­2ydç/»lð_÷ú7'iª„õSªè=j$IÊ·oü¾øòo¨*£3•ªa|lßÏÌQ ƒC\~Å¥ôöô„1*V$±B)ÓR„! ²© Êf£ÄæÞ’XR"­&±››í‚t Z‹82[eïî#ìÛ;M=Ф4ô÷eÑÚ°oÿ4}¥,†²ôõyÄaBµRA«) J…¨$²Y‹Œ/ÑF‘&)©RhÓX~ýÀ¡yfæË?.ÜÿñéÏ|`÷Ïâ¬_7–Æ¿ò-ïÃä]££#Ì-$”+ ¥Ò#Cxù"\6Ïù_€çfHtjЩB¥4­vS„XR‚%°m´¬ÝÓX8B%žZäþ{!¬Çh­¨ÅZ[ÄIGj4†8Mé/¸œµuËÔ*u‚z­bŒI€t&!“•d³ÓÐîÓ¤ÙÒb®²k÷ÔA)ôo}þóýƒ©©1<ÜÏÏúX„æ¿ÿÆ…Í›JYßàúªÇþɾÞ~lËc~1ahh€b>ÃÄø(™|žL¶€í¹ ÙC¦-ýGMª4ÓS³,ÎGÌY¤\®P­Wñý,R4°X®²X©‘¤)–08Ž`˦A&F‹¨4¢^ ˆÂ¦ ZEÝ0éŒNð\Èü†~¡Ž,c A¢ Ûw*åê]ýïùç …ï{ü¼Œu‡¾æßúª0Nÿ¡÷Ø2чey \Œð¨†û&kTË ™LÛ÷q¤ƒR†þ>†‡û°%„aLšJjAD¥Rkô4SwÓÔ`Û6ATÇqjõÅj•LƧ·¡·d1Зǖ$õZ Ë’ X–@…RaØ(±¶¤"—˰$»1ËBrߎCÌÍW_ñÅÿȧÖYýc€¼ü¥oºIž[,dØ4Z$M%?WDZ;©°ïPÀ“Ï£õ‰CMJ¦fˆcçúd2Y‚Zc ®ï!¤…0Š\Þ¥ÏE aõmz{|\Gb´ZN;7FaLŠº¡7ƒV qR' jÄQ )Áól,«‘ÌÒê`0ÀýMQ©Ö_–Ëçÿ퓟øË8IRaÛO`1;;Ïgþþ_Š;v\PÆ01œ'ŒRjõ:¹lÛóq½,ùB/¶íã».›Di„€L&6`B.¯’‘¦š4M—£8c[ÈåÆJŒÆh´J›…ˆ ¨4$Mâ†Ð)RJÛnä1XÖ2é•1<ôð4åJð{¾oéSŸz_x:¥föXâôŠ?¿8LÌÓ$âÌM}ô”r ¤tI•Àq<„´QJ¢µÀv|,ËBZ6BJŽÖ‚‰†5Ðì¯f8šÖkP` Æèå ­1¨Ë'­IÓ˜8Ž2›Àr]×q°l Œ¡Dì;´pððLå-Wøoÿ÷¯ÿ Žá8öT=YXšÙB>ø¡Ï‹éÛ?¶i,÷jÇñ›}yt[³Ì•&ÙÑt0³‚à‚Fîašªe§”’ TL©î­Tã·]qÙ“¾0qææáJóO!–¹RX¶m^ùÊwä{ ò‚bÞû§BÞ=WZcDKõÎÑ$@Ó:û› §J¥(¥ÑÚDŠr5Ù^’O»®óåÙr<ó…ϨֈS$¶Ÿ˜í§ Úƒ‚—¼ä/Š['Š¥4çjm®²-¹MJÎ2†qÓê©2©Òf¯Öæ‘45+mnBaËsBIT|dˆ pHYs × ×B(›xtEXtSoftwarewww.inkscape.org›î< cIDATxœí{ÅÇ?s<£‰Š¥F Ï& MMD¥(*ÑT4‰o4M¥°4)é£MÔ¢ˆF M$Ä2Æ'#‰‰D|Dñ…‘>1øÀ€EávòGÏÂÞ2»·»3»{G÷§jjo§{ºwýžî_ÿz.ˆ¢»´4ÛOsñp/Çñp/Çñp/Çñp/Çñp/Çñp/Çñp/Çñp/Çñp/Çñp/Çñp/Çñp/Çñp/Çñp/Çñp/Çñp/Çñp/Çñp/ÇéÝl ÅVÀ`` ‹Ž‚Ÿ×+´4ï7ËÎfl)¯‰S¡ØÀ0`HÁ1XEQë€w€åŸo/‹´4«ª°iàPày-Í«°¡aôX¨Pô&GûAª~X<OkiÞ+aã0àµøëJàùøX¶kiru·¸ =J*;Ga|<°Cs-  ááøxRK³@…bOàße®]_û×øxRKóy}ÍíL·€ E?à»À÷Ñ4æ.OÃj`>ðöñq×~<_?_Kó\öæu¦Û ~¦_œ h²9ÍâUàfàv-ÍêzTÐí BÑ \|ØªÉætÖw7ii^Ȳàn#ŠÀtìïÄô´ ùYÇëÀHà@`ë8í~à4-ÍGYTÔt¨Pô.~ lßTcšÏ‡ÀåÀÌÂÙAìǘŽí[€C²x,4U*ë±sw×Y ŒÒÒ¼>åÑQp.0,"XDÑÝz¼ U(Žþ‚ÁMZš ÒVÚ¨P nÃÎá=–S´4sÔ¼—šb7}\«Ç/¹\…âרÁq8 íL¡áP¡8Ûø;6´âîM»–FL Å~9x;êˆà7DÑ ALN ‚è°( «°.íÙZšï¤©¸a‹A*[«P܈ÄøÆïÌ€Á Äàîk“梶ñí·¶Éö“eÁäø¹¿4¾nRê}°wEËZ‚Ž»¯—KÛU(ŽÅÞTÅüQKsr-Fe.ŠƒÇðŸÄ Zš‹ “ëû\ Oœþ)0ë \Ÿ¿H…b[à*¬pz%”û†–f÷Z ÊT*;bƒ†dVè–ÅGÀ>Zš·ó'T(pp|A¾O€'€·€=±ë¥ÆwÓ´4Ëk1(3¨P´`"d&n¹|Ž}¤èâX¾Õl V,f 6Äé“¢ëúßÃú¯[±]܇X¹Áþ¢hi63L…BSj2¸qt‹°wk`g`]¯‹t`§zïa]ÆÃþ-^¬—±iÆc(Ýø9à̄Ɵ ÜÀæ{õÄÇhì‚ÉŠZš™Eù¦bЧ¤°;Ïl# &»ÙÐ|àb-ÍËI‰ñ^ÁǶljðw÷½U,MpðóÉ3µ4çå?˜Ku£ûßçhi: ÊÙ ˜‡u”TC˜Ü,ËGÔªPôÁöB#°ÂšÌ¦éU5| É*\»Q¤ÀÃÀ7K$)|î«PŽÔ²Ñã~lÀäÆÞD…bìæÊ]+,ãq¬ÛtQWU(†bÇ6gcïÐJ¹EKs^ù»i¢Äù¥ ƒ¾Ù”nüUØ»§Çb#Š6¢¥ù»’V O‡VÒøqÙoki¦ûbÇ1•òdy» iPêîèôG‹wÈîR”gp°½–f Ö 4 ë[ÏæŒ‹÷rðJ6®ÎJPv…–fp0°°ÂKz䦖4(µ<¹²èû¸„<jifåŸÃZšOµ4sµ4'bgI\¯8_“ÃU”c¡–¦+‘”$~ÄÀŸ+Èîœ6”8_|·˜g~©Bµ4³IrÜ»a´0ï½X·r)/“VZšO±±åèï*¨š4XZâüð¢ï¯'äÓEÙ—aŸÝÅ$žÍ-SN{õTD< ™LyA}#‹ºM=ÐZäÝKjÈ›U(¦¨PLR¡¸V…âJŠQùÄø~kÂu#Î=p.OG™´ªÐÒ¬ŽçøÀhНdU_£H#€RÏÖAÀaߟÂ<ÒÐÀìÝ>x$^ãγ ¡ìÖ8`¢—€R!Ñ™:U´4b_Qóf‰,gfY_#H#€?•IûAþ-ÍÇXvW#ñtŽ‹[›§/Ös·‘x„ÿUàWØ ÊB2yŽcïŽÂ¾A¬˜ÓU(¾uõ¤fhiž§t/0)ŽqËç}˜Fù.9<]ð}TBž`³ˆ-Í;Zš‹±[«4›ÄS—=ˆq,ßpà|:q‡Å©ÇZªy­Ç«y­.ßºÇæ¥tÒ®Î*q¾7pGì¶@K£±ƒ¿§ò/N-r ïÂpéb´4+µ4S±®Ýk¨ãÔ,žºÞŒuˆÊ¦ÙÈÅ*#ÛÆ™UA ;F{µä¢šÂµAÚx€¾Ø•¯â‘ž{°¯3YWtÝÎØ…ŸÏ€—´4+‹ÒwÅn˜,hªè—zGGMú‡D-½Flè­h¯ÙQO² û6Jµ ‰Zš–×ø=vî]Ì1Zš«·²±¨Pì,×Ò¼Ûl[º"«¨àÛ°Û”K±¸øE¹wñªPì ÌŽLH^ ¥q9<¬.d%€>ØU»ñ]dÝ€Ý9´»þÝëAëÝM”ä5Ì3VK“45ô¤ Ë!Ûa#~÷ϤÀÎÌÕÒLªC¹Î“Y,£6Ä‘%w§e\¦'¦^ÛÃOf’~äZàŠZ–s=•Q·7„ÄQ;gc_9´ÊËŸfhiîÊÜ0O'êþš¸Øw?;@…]ÐIй[ŽÝê|»–fqBº§4ã=}±oý;=\ ¬mö?Np•¦¿+ØÓ\üŽ^Çñp/Çñp/Çñp/Çñp/Çñp/Çñp/Çñp/Çñp/Çñp/Çñp/Çñp/Çñp/Çñp/Çñp/Çñp/Çñp/Çñp/Çñp/Çù?Ìx›ì:æ˜ÂIEND®B`‚kimchi-1.5.0/ui/images/icon-ubuntu.png000066400000000000000000000113221254252253000176200ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aËsBIT|dˆ pHYs × ×B(›xtEXtSoftwarewww.inkscape.org›î<OIDATxœíyxTÕÝÇ?³e²‡$LDG¨¸ÔZh´¥U,2"îR‹Zw±+U@|i-XQŸºT´Ex+¸T…" ðªÔ­T,¸<ˆ 0"! É„d²Îvß?î%f›Ì¹çÎL˜ù<Ï<’sÏùÍ9ßœ{Ï9¿ó;I’H‘¼ãm@Šø’@’“@’“@’“@’“@’“@’“@’“@’“@’“@’“@’“@’cŽ·zárØò€ÊçTåZ äÙ®€§Ãµ Ø |­\wÛîúXÚ+ ÇËr°Ëa3£ÉÊç4ÁEìÖ*Ÿmv§û¸¨¸>-—Ãf.¦“€1*ºX¬Þ³;Ým1*W8}N.‡-˜ˆüW>ï»ñxÑlDîÖÛîº8Û}F.‡-x¸Èг9¡h–ØnO¼QC Àå°Y€Û€¹@QœÍQK5ð(ð¼ÝéöÅÛ˜ÞHX(/uWó“ãlN´ìæ¯%êKcB Àå°#ãm‹ ¶ÚîwãmHWJ.‡m° ¸(Þ¶èÄ&àV»Ó}0Þ†#aàrØJ·'kŽgª€©v§{k¼ ™ v9lÓ-ÿòwÜ¢|ç¸×Àå°Ç€ßÅ͈ø²˜ewºƒñ2 np9lÙÀ*ä¼df0Íît7Æ£ð¸Àå° Eþâgļp0¤¥#y[µd±˜dwºˆ±H=1€ËaƒÜø¶˜,S^!ySo'gü4Œ9ù̼÷Ðôá?ñl^¿º,šlÝÈ"øD°¹½S(ùÛèß9êBŠçü ƒ5£Çßj©úýu´îú4šìÝÀèXö1€òÌßJîö­ÃÎdÐâuÒ3{M'y[©œs­;£éíJcõN“a ò¶¿Š>ÜøE³ÿ¶ñA~'(¼ù¢-æ `•Rgº«y€ÇèãoûÖSÎÆ2phéG’qÖØh‹›„\gº£»” >?ÎÏ:obÄ÷¤ŸzŽ–"‹É"] Lï.Ó³ŒXaHëù¥¯7Œ¹Z‹]¦Ô¡nèæª,ì¼Xõ*C “눑˜‹‡`.*ÁÜ¿sÑ ˜mòÕ`¶ðÔô%è©ÃWî¢mïç´}óÞ_#ùååü`Cmä…5OðY·\Ûh½ôô ^Fçö­§œMöW’ýó©˜ò {Mk.…²;aúÏ%gÂujsð†³‘ü>¼ßîŠØ†æO6EnxwŠ‘ër‚ˆÌº¢Ë0PYÏGxÆa0BÎùW=î*,%b|HªæßHÓGoƒÁÈàç?Ä2øªî ÔUóݯ~’°iþ õð'þ xò,¯ò&ßFþôY ס¼‡IAj—ÏWÕ ’ßGõ’»D6>ÀB¥n…¢ÇKàUÄÊ“ÇhêôߺUK6‰Ý¿‘ñã_`tM[7Pµà&$o/^àÁGž¼—–[„Ú\§W‰ÎT¨Îù"ó …© ˜AKÖ‘1òüöŸ=uÔ­^*¶ ƒ¾Š¹h0M½MÅ—àyç•Nb“~<›WSvë¹xÞ}U¬ ß3_©ca}p9lw–a¬#ÎaÀÜ—0ã+ßÏ¡ÛÇ"ù½,i ^¶ó€!BËô© röøÊö¶ÿÌ`NÃ<ðD‚G 6Ô!üBË ÁoíN÷Ó¢2Ö(~ûsE劜 ¿fÐⵘ 䆥ädò.»£ý÷’ÏKíòG…—kî?ˆA‹×‘yÎ8 &yð$ù½øÊö¨sǪñæ*u-a=€Ëaû=ðˆÌBÐïê{(¸aN·ŸK­Í”ÝRŠÿHEûÏJžpb¡i&.$ÁÆ£4ú.ÍÿÙHÛ¾/08KÉÉXJNÆWö ë_Ò¥ÜüÁîtG½ØÐ!P¶k•¡ãެ±“)~è0ôü"ÜøÁª»¥ýÿé§bÐã:' ðׯ¤‚À‘JY0Á¦ü"ùSPLÚ€ACÇ(IT-¸‰¦ÖEŸGxš€Á"¶¡‰ššˆŽo=e$E÷?²ñ²ÇNÁ³a-_|@ë®Oiúh™¥Z¿øÆ÷×Ðôï öZ–)¯Ìs.$sô/Éu!ÆŒ¿–Á@ÑÌg©¨>DÛ7ŸEv¯z²ëüïZ3Õ¼\¡9£0 ¦ä©Í˜úõ›Ö{påwþ¢ýylê×$‰@}MTe›r È»by—ÞÒ$ºjÊï¹õ¡¨ÊVÁ?ìN÷•Z3Ñ,e‹öôØ¥k0PòÄF¬§œ­ú–š¡þÍ焚aÊ·QpÃÃ䌟Ñ}m{?§üî‹DO£è¯ukºˆQÀè´E;ç¢_EÔø’· ÿañk&:7î'î¦zñHm-ªï³?‹\e]A²‘ë^"0E@Ý0fåQpÃêÓR9ûršþ½^sh|ïuÊï‘Èò¯Ÿ1+O/“4×½&(sÓºxúL(ì*Þ1üÕ‡(¿o"­_éïPëýn7•³/'PçV•Þ”WHþuºùÃLÒº> µaYÒ†žJî%7ªJ+µ6S9ë2|e߈6#$¾Ê~ä‚-êü6s'ýFõ*b„ Dnƒ¨Ñ*€Éïï‘Çôn =¡¨yq¾Šoõ0£WÚö}‰{ñªÒLfr'Þ —)šÚ á`0™ÉþùTUi[¶o¡aýrÑ&¨¦i«“¦ßV•6{ìբ޸@‰Ã':#ÏWõì6Õã~ânÑÅGLÍs³ 6‡dÊ·‘ñ㨽„{ã4¥-¢BK0Bý!ɾ@ÝÜFÆ•øk*õ0!"ü5•ÔÿCÝâ\ŽÊïQ·EB À`2“9z¼ª´žÍ«D5 ›WA06]féÅÒÒõ0!.85Ò,%vrÆ_Kÿ é?c!9ã¯ÅRboÿ½ðsôÕ'ÃæÓºó?øí‹´xÝÔ¦ùÓðîzÆŒ,Ò†F\mjˆ:S-‹AªUg°¤QpýlyݾëJ›¤þÍç¨]±Éçåè«Obö#²~zIÈü<›^ŽÚh½ðüßj2Ç„ï½,ƒ‡ë±H—@•Ë·Á’Æ ¥Nò.ŸÑó2«ÁHÞå3´Ô‰Á’€{é]½Žë›¶:£³XGZwmS•.í„ázµû½¨òJ)¸~6Öag†Mgv&×Ï ØÒDÃÛ=ï‚MõÂ?E¨«Vµêh¢‹¢öÒ"€° @–{'w­pä]vGû;A¨¿(UTÁb‚÷ۯ¦I¬‹¢^ŒÓòVu駉̻Æ`$ýô1òö,×WH­Íݶcûª&Ä^7jþ2S~‘ìðw¹~$ŸW¢£î´ ¬ê¬ÃÏŠ8Sëð³ðl^ Á­{¶“ñ£Ÿuú}B÷ßí†ïvÇ£è¨{€„ˆ˜"~hé^÷?·íý<âLÛï1šH?¥û#sñàˆóŒi'ŽPõˆ2ˆToDNF‹<„@ëWŸÈîPjߤ`ûš¾Õ~záX,Åb7|ˆ¤ðöùa£‚øÊ¾¡ìÖóDõÙZaUç+wEäŸWÿæsøÊ]¤ŸÖó2wB÷'6·ÃÎ"DÝh€*ÕÕ®X@Û¾/ækÛ÷%µ+ÈFed…t1fåééb5¦ü"U«˜¾ƒº .=@•šD’ÏKÅ}êßx¦gïX)HýÏPqŸ£}ˆd»ïé^=h²JÑY¬#¡z¬®xé"UmÑZÞv£ÒAòy©yq Ε¤Ÿ>¦}xض÷sZ¿ú¤½ÛyûWoë { {Þy%zËu ç—תJçÓçõØS‹¾Žô_¹ _¹Kç÷€Ád¦ßÕ÷„Í'ýŒŸ`9aX¬š 9j\ØtÁ–&¼"®65D©–G€ð)à§yÛfUi#ݤ¡'¹ã§©r÷jÞºAkPéPDÝ %}ïÕ{ñt9¸Sœ1$T¥õ¨ünQ{(géF:+ -Û·¨ZU3fåa»÷)ÑÅGLá 0f†ŸŠÔ¹iùì=LØ¥å\c­SÁk5Þß )à§ñý·T¥Íy>¹ÕíЃ¬RYçõþÂzŒÆÖ¨r‹Mmpð8Wª®¬Â›çµqŠ%Öagb›ù¬ª´RÀ¯gЈ¸ `òAÊBñø:¤CHW é™ |ìM½vÞôˆeàPüáŒêáÖýM¯K•Èm5š œ†©K(ŒÚ•R½¯ß\t%K×Ëþ:“vâ.xS¾º3/õ5Ôý}‘^æ¬Óz"©ˆåà5òèF°©žÚ—þ¨:½1»¼AÖ¹‘GõVKöWRòÔæˆ"Õ­X § ›æº!€÷аÑžM/Ó¶g‡êô†4«ððp ïê±ÝûE3Ÿ(RHÛÞÏiب9ŠK(‘ë^š D¨Ø¨5Ÿ‘$ªÜLàèUɽ÷аö…öÿ›úõW½Å¼'L¹üf.C–oxâ)PWMÕoÔ+:ÀF­ÑA@\¨µè#È_]Æáy×1hÑZ i½Gž¯yö¡NñúúÏXû QÈgžwžñ@Ð,&.ÉÃÄ¥EFÁñ(RäK€Û"yvâè«O¨¯¡ÿŒ?a0§µÿ¼nõÒNŸ=vŠ.¨¯Á½d-Ÿ½ßéQã«ø––ÿ^^ª‘ëZ¼‚íN·¤· žÿKÅÌÉje_ùþNngK7ŠYì?RAÅÌI4ÿ÷ÝöÆ7˜Ó° Ž)ßÖ?8<ªÔµD[ý?tšèØŽ\·B.enúAÑùª¡~íóÔ­| _ù~ay68WÊÿ0)¸qŽª!¢Ál¡è§µ '»ó ÖyÿžÐíðh—ö¸H—ÌUɱq¡èxl\VéÅ?²"¢û+œBË—GUv6Ùn]ŽÓóÕõVä¥Ê¸œضgm{vP»l®ƒ#ÓNŠ< ZæO&ˆ@r]ê‚n°;Ý]ÛT` q<=T øåífÃÈFu l/稤 ˜ª×©¡ óî`»Ó½ÕK$¯ú(áLjê¸ÙÎܪԡnè¾=Üît¯tóˆˆMG…¼u¦`P‹”ºÓ•XŘ…NžC±¢mÏ|•"J¯áðÈuÈu¦;1€ÝéÓ€±(O/ªÜ„ÔÚ6äm¥æÅyѳ˜¦Ô™îÄ,BˆÝénD>[@] ý¤mß—òѱ½œh¨¥rÖe´îŒêÑí&)ut›…ËaƒÜÅ©óªL@Ly…äM½œñÓ0æäc0[ðÜCÓ‡ÿijyu´@Ž5¾þ§^t æp9lC‘EpFÌ ×CZºÖ=;‘ÿ€‹Ô— QÊ-¥¿Ccã¯JãÑøÇ(aÊsn ÇÁQ‹€)±|æw%.€®¸¶éÀ2â8ccÚ'ytç‡#!àrØJ·ˆÓÚA ©BžÞÕu†O- (R©ÑÀ¦xÛ¢#›€Ñ‰Òø@=@G\Û8`!Ð=Rdßd;òz~øS%bLÂôQ*jp ²\_e?òw•ˆ ÚtÄå°Y€Û€¹èèr.˜jdéçíN·/ÞÆôF à.‡-x¸w i¤ xX"Òu[OúŒŽ¡lC›ˆ£p:\È›c×ëEl׊%}Nq9lVä#Ô§ /4Å*lX%ò Þà=»tãEŸ@G”S´G#÷ “ªé.ä¿òµÀ6=§*×bäãU²;\AîÆ=®Uȱ÷¾V®»µ„bKdŽ[¤PGBΤˆ)$9)$9)$9)$9)$9)$9)$9)$9)$9)$9)$9)$9ÿ< ÍÝ¢ŽÆqIEND®B`‚kimchi-1.5.0/ui/images/icon-vm.png000066400000000000000000000056401254252253000167260ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aË gIDATxÚí]hU×C¢h¢eþKI£eFσ¼8Ü›äÞsÎ=ç;¿ßï|÷Ü“š‚ ‚ ‚ ‚ ‚ ‚ ‚ ‚ ‚ ‚ ‚ ‚ ‚ ‚ ‚ ‚ ‚ ‚ ‚ ¢RqâĉÏíÚµköØØØüýû÷/–”:pàÀÝüâ¡C‡š£ ¿¹KÎëäüN9~^®¯õ­CWW× ÉçI †‡‡—¢Œ|å#¡nrMƒÖuêŽûóåƒëp}¾|¢ùᙑÚù¡Mâ¶¥ä1 ù>|ø Èwttty¡g‰¶)ê‹6Õú×NPat¨T"-Ñ+••ô€Tè[rüv4É5Iº_Ò°üÜ-ׯ֎¨õìühIYÉûKRöWå||rùZ§%‘ó>)¿l: „DƒËq£ü}@Ò½rí×'ç3)ÏãR昤~9oSrÝçYP@­¨Ÿ¶åƒùÚ2’Æ¥ì/ã¹ñüh´‡!uâÀÃ* wIEÉùIIÏJº"ibRzUÒó’žÐ†C¥[Ðð>D§iƒÝ'y>&Ç r¼œ§üW亟Kz\v$DùJ¤ÅÚˆ ÈÃr<-ÇßåÉçÓ${Mÿ~F¯?‚û‘k€€õ :^êÿIOÉùK(§P$½,é¬\ó=9ÅÀR‹T;mÀèïééy`æÌ™×åW9›ÔØØø,:$®ÙTseimm}Á¶ü3fÜÈf³ßĨ5Àè•4(¿Ò6“fÍšusïÞ½?R´¸ZYÒðÐÐÐ÷çÍ›÷¾kV®\‰Á5 ×€ü¦hD©ô×êëëÿl[ÙÙ³gßÞ·oßÏÔ\·Ä©°é4¹HFòã Ö\´hѵÁÁÁo`Ä™X "I¾Ï»6>’çªÔå» 5¬€-©q¹ f}ëÖ­—㔿víÚ×Ô%´ÇuCq-@;ü”X — oÞ¼ùšÜ÷CÄhW+Ÿ  ?-ç—çÎk]ö¦M›þ¤f; €€ ²üüˆ<Ç›q: •Jåd <R»ŒBOƒ½#ò~>UþÒÂ… ­+ÜÜÜœC¼ AÔ]®~KGM|zGGǶåΙ3''ÖñÈ8¤³ Böööþ3N uvv¾+ùþ@ž§Q¹ ©õkÙ ¼åBähÚ°aÃM)ó'H‘ç´Mu 2$é™t:}Û¶Â3ä¶oßþ&¬FŸ‹Ù2æä‘N¼°|ùrW⃿DÀ„¼B@󾀦ˆÅ¬€Ÿ)m¿ÓÒ~·â–]07Rèf)üQ1Ÿw¬ô ¹ïfˆ‚mÝ€1ÿ$wïÞýºË¨‘FOg ݦ¡B¤îëë{®î¥XG íÔõŒËèÿCÜÑ_RÀtk{¿œÿÚÅ ¨ßü%æ²ðƒ¶nÀÇüKðw Z\—¡¡ Ñø'˜"¢‡•*4%T+ëyŸ”çøÐ§Ü’@£XÌ¡ï‘ôc‰F?v1;vìø4 CDnã|Ì{{û-˜Z˜Üèô3$4Æx£z*×+†’ñ%—SV0¦ Ã5‘Šâ@˜±qqÍ?ÈÖßßÿ¦j&ú³¡`\Fµ*ŠK'[#ü¨€u2“É\Pfé`¦2~$]t•®n ®ù×r^À4M5üÚ¤ eýFÕÑ6Ïìén<³k{•%ÀhL{âtŒ‹ð1ÿSYšÐÐ`ó_F爖g„Îp%pþ[ˆòJJcš! Ã÷‰iþcnÀÇüKtþ–jìŸQÊ’ €†0Ê$›€–Gßà@Ç_·n]®*™ÓŽÊÃK xš¨t÷æ’ €‰90Ê!óµÓÄKÐ?$^ºê3õ++˜ÂüÚµ!mܦ#qƳ.ëìì|¤Ñ ë3 ]ˆCg!ó*ñð¾>…—Nè¬t:ýßPe•|¤ábnÀ¼wÀ 9oØŽœ|Òo¾z'A£vÂõ L=uÝÀq×ö©øHÃS¹£5€ ‰˜ÿ>Òo(¬Y³ÆF{øŸ®-Ñ©2ÖA0•s9ù¤ßP¼sÅê¢êãX]/0n£˜nÙ²%ç8Ë)øHÃ…ÜHñÆuÚTHú EtR6›µ}çqN_מ)V†Ö»2 à# çsÆ­hàtÆåY!é7$öìÙ“+ไ€Ų49¾]¬c¥Þ9©KeÀG޾M3«utái3T5Í|*é7$$ïœÍ\Þ\[Œ0¨÷Î;+›>Ò°<ÈÇX©+|—Õ 1ŶmÛ®…~C@"}Û`´(YÌuMix²Ž®ëü‡Ôüß®Ià%“'nÉ}7‹uF6®/f %°¼-ùAF¾Q±ð•†ÍÒ*%PÆõ•i1é7$丬 ? $cÅôe›X¡¬ à# à Ê=?ÕUÃX'ÿX ó_Pú 8 „•Á,ã‚tØ«Þéc¶pê¡äw¥¢ à# ›E¸¡Ï»˜ÿbÒo@| ¢à›€³>Ò®yfÍë¤àÅŠ'€4¬û+¬–{'lﵑ~àß:ÍħhºHÔSX½ãºPöbÅÀGÖhøº¤w%Êþ$¤ô˜§ô;Âû„pçã,9Ôµ„Çb¬w(?øHÃÉÒÖólé7$àjtÊ: ±Ê?âò¬¿ÐBøBèhÕÀGF”- ‘s1ÿ6ÒoHÀg#ÖÀl#Î3NÎGŠ©øHÃ0ç6"‹«ôš°6*| ¸.ñVÒ¾¬_L§õ3±Ñª!€4ŒÆYµjUpé7 Ð¥«|Û\—«áu1”O¼ëiuê"€4œ„ô›ô+ŸÝã´Xº›–‚ÕëºÙDF¿T^\u𑆓~“ €Ù*G7™ïîî¾Tìþ+V\×YĈyûY•ð•†CK¿ ÀìX2(øH}}ý;SÝ¿qãÆçôGÖ,­ZøHá¥ß¤±tˆ†¨UzQ·È™€ÎeS§ªÐzAšÈ²ñê$€4ZúMŠ‘¼°[YûÀ¼c”G6{×o0+ÊêgäóM«š>ÒpHé7I¨¯Õelد.ºÝ›ÙªÎ¬u€»Šª•UMi¸ˆ†~ÞEúM’¬dõÀG®)ò ÌmÜ'*D.¤¢é-q·G#*D®™b7ŸýI€IÈŒãjæ³+,KñyhX¥8ÛÄÉìã/º7`&ÔæŒ*)Jzª©©Ézp”d›8Ÿ7ŸHK:ÕØØøW,[¶ìCÉ«‡Ç¢Ÿ_Ç­Oœ";::~‹)¦|¡¶gÕUÐ=’R©”õ«å’lé+ ë×>Ç\¶y5iõêÕ¿×=»\¥ß|"Uœ­bÛÚڞƌÓ¼P4›Ã„_Y²dÉUw8ý[Åúj=›tE7£>©#¯£ß×ÿFâ›Í¢±Þàu=cJ⥡ ›``û˜~X$]YhîÒn@¶Úê=º=:®ÁH…ß×=óïôm|Çíâñ»£zMFeÜù>h²;‚Eƒ`¦«ƒ†t›ý‡Ên»ø@$°úgIÿƒÛQLÉ 4K*¨$–Õ?Œ ‚ ‚ ‚ ‚ ‚ ‚ ‚ ‚ ‚ ‚ ‚ ‚ ‚ ‚ ‚ ‚ ‚ ‚ ‚ ’Æÿß©‡¼–IEND®B`‚kimchi-1.5.0/ui/images/logo.ico000066400000000000000000000022761254252253000163060ustar00rootroot00000000000000 ¨(  €  |y’`®ª”Á½†ÊÅ,¸=@¸=¿ÉCõåLwtq4ƒ€Ø­©ÿÙÔÿõïÿý÷ÿðêÝIn×GóäKÿýTÿþgg…‚b«§ÿåàÿþùÔþù2]þù2ZþùØõ÷AñP3÷RÈþ^ÿ,þqð6þx&ÓÎ1þùbþø HþY®)þoÿ5þw_·& ÷3rþ5]tþVxþø ìNþ^ÿ!þiK› aâ.øþ'RÙþUw>þh† ÊC åLÅÄÌ´þz.¼þEB¸&ÿþ <äþDi§7*¿?›âh³þÿ;ÀþÑŒ©Í*ÿþHŸ“1¬9”؉¶þÿNÆþ㜠ÑÛ-ÿþK¨ÖZÑÙfÕ—܇(ºþÿ]Ëþì#¡â.ÿþErÓMÎ!ÕWÐ6v¬£îå;ÀþÿhÏþF´%"Ö,_àlË1ÄÉÏ>ÈU| h—IÑÚ¶þòSÈþ`¤›I·!­ÿÉ'¾3)àg–„Àn®þy>Áþ"…V¢•ÿ¾$°Ë+çL%È*ã`L$þIrSþˆ|š‹àº$¨ÿÊ-·àË1¸^X ë**ãð%Ê{%Èq*âÙ>þÿhGþÿ€dþ›Ÿ ŽK¾&©ÿÍ;¹ÿÑJ¾ÿÐG½q>þD1þÿ4þÿGþÿeCþÿcþÙŠqþNÆ)®QÏCºéÓUÀÃÔWÁ5K#þ M&þf[7þ˜oPþGà‡€dÀ€uÀ€oç±€Sñ€wƒð\ðwð4ü\øgà€ Æá€eÆq€nÀ€\à€ið‡€nkimchi-1.5.0/ui/images/theme-default/000077500000000000000000000000001254252253000173675ustar00rootroot00000000000000kimchi-1.5.0/ui/images/theme-default/Makefile.am000066400000000000000000000012401254252253000214200ustar00rootroot00000000000000# # Kimchi # # Copyright IBM, Corp. 2013 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. imagedir = $(datadir)/kimchi/ui/images/theme-default dist_image_DATA = *.png *.gif kimchi-1.5.0/ui/images/theme-default/ac22_pause.png000066400000000000000000000023031254252253000220170ustar00rootroot00000000000000‰PNG  IHDRä‚íÅtEXtSoftwareAdobe ImageReadyqÉe<fiTXtXML:com.adobe.xmp ' 5DóIDATxÚbüÿÿ?= ˆ`dd„ñ¹X&€ø%Eë›ãYÐøâØõœŒ™Ú˜Eÿ2ügøõÿÃO†¯<¿ÝNŒ: üvB±ø±H¶±5ƒÜô‹áÃ†ß ÿÿûÅð.PHŠDu8-bfdE„$¾3üºø¯$9ê`€ 22°•ƒ‡RuL„R #‘©Š:&:Q‹F-µhÔ¢‘hÑ"õý¡Ô¢—Àjù²Ríÿ‚ u8-ú ¬¼aŠA5'¨šúÈM&C¢¾µXZATØZAEkp0 ûb.IEND®B`‚kimchi-1.5.0/ui/images/theme-default/ac22_pause_grey.png000066400000000000000000000022271254252253000230520ustar00rootroot00000000000000‰PNG  IHDRä‚íÅtEXtSoftwareAdobe ImageReadyqÉe<fiTXtXML:com.adobe.xmp ­XðÃÇIDATxÚbüÿÿ?= 2‡‘‘‘¡¬¬ÌÈœ Ä’ ßBñs ?¹··w;ˆO¬:œX3ˆ Rüçφ¿ÿJþû÷oPH ˆ¿’¢§E,,,’06ÌU@Í _ˆ™â@|uDÅ(ˆ`—ÈUG·Ä0jѨE£Z4jÑp±è96…ÀJí ™êpZ”TüVs‚0°Š~ùøñã* Ð2ÔA*GäFR É ­Ž‘kJæ—@õ_‰U‡l@€…~¯—, 6IEND®B`‚kimchi-1.5.0/ui/images/theme-default/ac24_resume.png000066400000000000000000000024751254252253000222160ustar00rootroot00000000000000‰PNG  IHDRä‚íÅtEXtSoftwareAdobe ImageReadyqÉe<fiTXtXML:com.adobe.xmp äJ¤`mIDATxÚ´–½JÄ@Çg6{ñÎD‚ß`¡"XZûvö×YX(ˆ ú‚¯ ˜JßŰÖÎBP°¸B°ð2Îf³[£·Émþ0!™,óÛ™M‰Œ$Ø2¨)i=/³%–oÀöVzÞXÙÄøõ™'%×âª7}ËŸÞžgÇ&£ýS|àì#ö¡+HØŽéú2˜Šº…ñýQyL ! {¥‚šf¤‚@”`ö­-¼sÈE |e žE¡Þ_ÜôõIòæd8¬˜uÿ êèl¸|`zƒg?Z„]íדÁou©U:,•°²QS¥ç.ï%ÕÕ•+lb+Ì Èæ 4&Á³ L©€¡÷ŒlØÎ©}†­dd´¾D°·áán kd´:¯!­5Ã_ï ¢¾ÞAÿA¼ÆA¼€\ U A*:¤j¨ Æ^>05ø0óTÞ'.ü¯ÒàÔH# 6õ#Àþgn)F¨ IEND®B`‚kimchi-1.5.0/ui/images/theme-default/ac24_resume_grey.png000066400000000000000000000024021254252253000232320ustar00rootroot00000000000000‰PNG  IHDRä‚íÅtEXtSoftwareAdobe ImageReadyqÉe<fiTXtXML:com.adobe.xmp xØB»2IDATxÚ¼–Ñ„ †ѧÝìãv ¾hAà F›°€³ƒkƶƒ{Ü{¾,;“ˆ!,žèÁM2ÁÀ>f€A*¥$ÿbÒÝÅêº>íåPsò¦i> © Ý8 ÃM}Cs†>ê b–¾Š1F¢(ÒÁ×eu”žAólÛV!„sN’$Y¼( º¨ôˆÄqÌp¬ë: Yˆ¶ÒÏßr “¨Hð[ÁMŠzÖü`÷ÞÔ-“mnð¼(ˆŽô}/œO“#Œû¸" †6è÷ˆl‘á Ú‚1ß•f ÆB”5Ëó[áí0ØLAʲA#JÓT‡Üƒ€lï 5ˆWÐoo Õû¤Ö¹@þ r…¬Ý£1˲Jƒ¦iú4E q†XÿæwŸí‹¡}€é­müw{ 0të¸Ç¥ùIEND®B`‚kimchi-1.5.0/ui/images/theme-default/alert.png000066400000000000000000000067211254252253000212120ustar00rootroot00000000000000‰PNG  IHDR1)œÁê pHYs  šœ MiCCPPhotoshop ICC profilexÚSwX“÷>ß÷eVBØð±—l"#¬ÈY¢’a„@Å…ˆ VœHUÄ‚Õ Hˆâ (¸gAŠˆZ‹U\8îܧµ}zïííû×û¼çœçüÎyÏ€&‘æ¢j9R…<:ØOHÄɽ€Hà æËÂgÅðyx~t°?ü¯opÕ.$ÇáÿƒºP&W ‘à"ç RÈ.TÈȰS³d ”ly|B"ª ìôI>Ø©“ÜØ¢©™(G$@»`UR,À ¬@".À®€Y¶2G€½vŽX@`€™B,Ì 8CÍ L 0Ò¿à©_p…¸HÀ˕͗KÒ3¸•Ðwòðàâ!âÂl±Ba)f ä"œ—›#HçLÎ ùÑÁþ8?çæäáæfçlïôÅ¢þkðo">!ñßþ¼ŒNÏïÚ_ååÖpǰu¿k©[ÚVhßù]3Û  Z Ðzù‹y8ü@ž¡PÈ< í%b¡½0ã‹>ÿ3áoà‹~öü@þÛzðqš@™­À£ƒýqanv®RŽçËB1n÷ç#þÇ…ýŽ)Ñâ4±\,ŠñX‰¸P"MÇy¹R‘D!É•âé2ñ–ý “w ¬†OÀN¶µËlÀ~î‹XÒv@~ó-Œ ‘g42y÷“¿ù@+Í—¤ã¼è\¨”LÆD *°A Á¬ÀœÁ¼ÀaD@ $À<Bä€ ¡–ATÀ:ص° šá´Á18 çà\ëp`žÂ¼† AÈa!:ˆbŽØ"ΙŽ"aH4’€¤ éˆQ"ÅÈr¤©Bj‘]H#ò-r9\@úÛÈ 2ŠüмG1”²QÔu@¹¨ŠÆ sÑt4]€–¢kÑ´=€¶¢§ÑKèut}ŠŽc€Ñ1fŒÙa\Œ‡E`‰X&ÇcåX5V5cX7vÀžaï$‹€ì^„Âl‚GXLXC¨%ì#´ºW ƒ„1Â'"“¨O´%zùÄxb:±XF¬&î!!ž%^'_“H$É’äN !%2I IkHÛH-¤S¤>ÒiœL&ëmÉÞä²€¬ —‘·O’ûÉÃä·:ňâL ¢$R¤”J5e?奟2B™ ªQÍ©žÔªˆ:ŸZIm vP/S‡©4uš%Í›Cˤ-£ÕКigi÷h/étº ݃E—ЗÒkèéçéƒôw † ƒÇHb(k{§·/™L¦Ó—™ÈT0×2™g˜˜oUX*ö*|‘Ê•:•V•~•çªTUsU?Õyª T«U«^V}¦FU³Pã© Ô«Õ©U»©6®ÎRwRPÏQ_£¾_ý‚úc ²†…F †H£Tc·Æ!Æ2eñXBÖrVë,k˜Mb[²ùìLvûv/{LSCsªf¬f‘fæqÍƱàð9ÙœJÎ!Î Î{--?-±Öj­f­~­7ÚzÚ¾ÚbírííëÚïup@,õ:m:÷u º6ºQº…ºÛuÏê>Ócëyé õÊõéÝÑGõmô£õêïÖïÑ7046l18cðÌcèk˜i¸Ñð„á¨Ëhº‘Äh£ÑI£'¸&î‡gã5x>f¬ob¬4ÞeÜkVyVõV׬IÖ\ë,ëmÖWlPW› ›:›Ë¶¨­›­Äv›mßâ)Ò)õSnÚ1ìüì ìšìí9öaö%ömöÏÌÖ;t;|rtuÌvlp¼ë¤á4éĩÃéWgg¡só5¦KË—v—Sm§Š§nŸzË•åîºÒµÓõ£›»›Ü­ÙmÔÝÌ=Å}«ûM.›É]Ã=ïAôð÷XâqÌã§›§Âóç/^v^Y^û½O³œ&žÖ0mÈÛÄ[à½Ë{`:>=eúÎé>Æ>ŸzŸ‡¾¦¾"ß=¾#~Ö~™~üžû;úËýø¿áyòñN`Áå½³k™¥5»/ >B Yr“oÀòùc3Üg,šÑÊZú0Ì&LÖކÏß~o¦ùLé̶ˆàGlˆ¸i™ù})*2ª.êQ´Stqt÷,Ö¬äYûg½Žñ©Œ¹;Ûj¶rvg¬jlRlc웸€¸ª¸x‡øEñ—t$ í‰äÄØÄ=‰ãsçlš3œäšT–tc®åÜ¢¹æéÎËžwç|þü/÷„óû%ÒŸ3 cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFþIDATxÚÔ™KhQ†¿™Ä¤¨‰Z›¶RE#U7jܨUp¡ •ª ¨ nT„ HA°B£¢â«Š AW]»PA\¹LW ‚ \ù(¾úŠ‹œ@2ÉÌäÜ$þ0Ì™;ßœ¹÷?玕M`H‹³Àà50|4ÑQØ@+ðè•ÿë€UÀ>à³vg¶€(𨠨à90ç€èö¸´­2ÍÑd«sH6+„ ]޽§Ù·&D 8áñØÀîfƒˆ}žs ˜×Li´~´ÂGäŒC´7ž{XÙh³³Ä‰ç—ìû\>9®?$€“2‹!çeƒÒì&jL;6¯7ûX üu‰üK`«cÿàE#^§¨¼Fá2Ñ™årNH6§î±F@–TÂïëç6È3Ú@tW”Ý~X^/[RìVeˆp+È=H§ ¥ð»Êd¿ê„&uÛï ÷ qØl")&h¢­Q(êœT‚ª0Ì­D p©‚߂إ¾:lÓ‚ˆ7 •²^Òõ¸DZ"Ñ­úk…è'm¤†€eA!là¼ÇšÙ¤l`Ø%q¬ ‘ ¸¼2 ̸´MK»_õÛýE +xAЦ˜ÔSäŒEA#;,vÜ+D°>`gqà™K4ly@Aü4pÑKe×&O1Nóé›Dù]µHd•Þ_%"“âö=5úM±&ß/ã«,Äà˜@?0"7Ÿ—-Daö!0»†k殺øö´Üì•4¸Vý€ïòû·¬€üžïú¸Sú¶ØŽšYÙ'JCíP^€4ÒõãÅš¼±¸ 8­ ûCJ}d‹NnË…3ÀEˆ|…ýÓJ}„eºµm1Ÿ´r-àæ!åš$ ´Û@7º=Z(,w‰ç,ˆ[AaíÕažVn4±ÈIçšú!)„Lµ1{Úê¶·†jç¸D#)OßÀ0GÆ(¬Xû°­¨qà>p˜ú7ÐÖu­%‹ð¾IEND®B`‚kimchi-1.5.0/ui/images/theme-default/arrow-down-black.png000066400000000000000000000055761254252253000232630ustar00rootroot00000000000000‰PNG  IHDR Mi pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-Û cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅF©IDATxÚœÑ=JCQ†áw 7?XتéÓ^pmf+q3.Bƒ…!ÙA"Xäµ9W4  ™ê+æáƒ™P9g."bÜ“#û[àØ„JDÜfæêÔ¶Zël€è2s{Z¯@«]­õêzlq]ZØŸÀå_¸¡7à x)í8ûÿð!Šˆ~¾C-êT½VûÌT]ªê½:v‡ãüÂÀ¸ú–Ÿ¿›Ú| /‡_B ë¸IEND®B`‚kimchi-1.5.0/ui/images/theme-default/arrow-down-disable.png000066400000000000000000000007301254252253000235750ustar00rootroot00000000000000‰PNG  IHDRVÎŽWsBIT|dˆIDAT8ÝÑ¿oÍaÅñ×ùjš¨ „¹½·“Y"F£3!!i$,µøb²ˆ1IºÚübEbAú½·íw`±2¨ö1ø”‹Ägy’'ç¼?ç<ÿíêºJUUz½Þ›gffF±>É›ª®ë”R¶—Rv/..®úSH]×Ã8…›ØYa3Îaûëºþ-¬ßïãh’©$»pu“Iöa70Ñï÷§ñvbbâgk—aïª$’ÿ7ÑGqSßT{‰[m¥q|hÓŸÇËn· ߃ZØìÁuli¯ßcu«¿Û.zÑívËß2ÌÍÍ;p­=‡Û:Û:óãããßy~ ‚ùùù`Nâîá,žw:eú_‚ i¥”-è>žu:¥•<+NÓ4UÓ4íÿ7ó r·~K°“DIEND®B`‚kimchi-1.5.0/ui/images/theme-default/arrow-down.png000066400000000000000000000010311254252253000221670ustar00rootroot00000000000000‰PNG  IHDRVÎŽWsBIT|dˆÐIDAT8Ý’¿Kp‡ŸçÅLèQ¡AS5´w‚DSD{QC$…wèáTÐaKËÅ…'º´¶õDc’¦G[Rní "yÞ·¡4ä%è3¾¼ÏÃûò¾ðßF€|>oD¤ÎÎN¦¦¦ö ÷Õ¯‘ÏçM)ßØØ¸´¶¶Ö±WI¡PèîÏ€\}êà©zµP(üQ622Ò¥ÞŽˆbD\PŸtd2™’z'"«ÕÎL&ó1›Í®6’ÑÑÑ  >T¨Mu9Ôu¶]8÷Ô*pòWI¹\u("î«GÕuõ…ZìÈf³_Ô÷ѯžV»#âœÚ—Ëå ßJ¥R¤”®Õ*í!Êê'ÆÆÆzRJ5õp@ÝÞãêBJé:ðèÖàf«ÕZ™žžþyþ-£÷y ¸¹šº<†RJ§€ïÀK ,MNNlµeû#â2PúÛåU`_»ÿ5PL)-Öëõ´Éí8õüüüúÀÀÀbD̪g#âxDtGDS}«Þ–'&&¶q¿ý™¹¹9WÔyµW=£¾RËñ¹V«í`v¬¶5ããã4›ÍcÀ5àú¡Z­¶vcvM¥R‰J¥ò×ü¿ÉÛ†%öø¼üIEND®B`‚kimchi-1.5.0/ui/images/theme-default/arrow-up.png000066400000000000000000000007761254252253000216630ustar00rootroot00000000000000‰PNG  IHDRVÎŽWsBIT|dˆµIDAT8Ý‘=kSqÆçA«‚W¥Š/—,*¸è ~?@I/y±¹äÔ $Jo6·N~'‡XŠâ¤T ÅŠ(n‚C}¯b"ÅgûsÎó{Î9øo+¶Ûm€£@|èt:S{“i…,ËBÒ9Û¹íG’²,›<dû„í®¤+’.ÚîÚ^hµZûÿHh6›3qXNŽ„ xܰ½ÖívwF}3£F£±¸jûpº€lŸ€9à€í À»R©´5¿O\Íöåb…3’BÒ†¤eI5I¯%aû˜í»¶¯×ëõßþHÓt/p ÈY "bH“$Yt¸]LÀ7 V{½ÞרV«ûE GŠ€uàf¿ß1:qš¦§l?.aû pÈÛ˶[¶ç$!é™íðrü#z½ÞÛ IO%Ùö¡ÂŸ%’æ%Íê§žØ^´ý¼ßï{TÜñ•í²íÇ’v$í“4årù¸í{€#b)ÏóíI€qU*•Ã’î#¢–[@X²½+ÀÊÊÊgàP6“<ÏlÛƒÁ`·œ_ú¼-ÿ˜~DÝ uÜ7ÄIEND®B`‚kimchi-1.5.0/ui/images/theme-default/arrow_out.png000066400000000000000000000057501254252253000221250ustar00rootroot00000000000000‰PNG  IHDR`Ât(Å pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-Û cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFIDATxÚìØ½jÃ0†áWDÑ’AƒC¡·Õ¥cnÑ«oÀSï PèÖµ!M{º(;Ž}œB‡rÆÂòóùOÖpœˆpm»áÍ;ιXºà øžƒ"2¸r¨ëº°ÑÜÕàï=MÓ|¼p:(1FrδmÛk!RJTU¥ 8;è½WL&j.>&`ömNHÙt3lð)"w"3Ls~*à èÕsÛ{¿:àè×ü»‚ž€gçÜ^‹'¡_„gs{ ãÃ8þT{€”Ò#ð¾ÜɶîËþe ŠÈßÇ¥¨›ƒSøoWOÆ 6lذaÆ ÿGlu«“XÄê$V'¹¦ý ÑÄmòIEND®B`‚kimchi-1.5.0/ui/images/theme-default/bg-mask.png000066400000000000000000000055231254252253000214230ustar00rootroot00000000000000‰PNG  IHDR((Œþ¸m pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-Û cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅF~IDATxÚìÕ1 €0Ñ1à öþ…Ü;Ø©QkùÂlR Â[ªjã2ÝÍ}ªêqöÕ½‘œ‰qG`jÀHŽ›ž81®»çÀ´¸iƒ‰qG`jÀHŽ{ý$J¢$J¢$J¢$J¢$J¢$J¢$J¢$J¢$J¢$‘dÝÿÿCæá>ùÂjIEND®B`‚kimchi-1.5.0/ui/images/theme-default/bg.png000066400000000000000000001054011254252253000204660ustar00rootroot00000000000000‰PNG  IHDRåÍÈT  pHYs  šœ cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFЇIDATxÚŒýÙv]鑤í@‚èU÷ZªT(•9Ru¿)‘hhþƒñÐrÅ>Øq A‘ÀZs~7æææÇ?þ||||{{;==}~~>>>>:::99ùôéÓÑÑÑÓÓÓóóóÇ___ŸŸŸ?þüüü|rròáÇçç磣£———>½½½œœœžžþøñãçÏŸWWWOOOgggOOOGGGŸ?~yyyzzz{{ûüùóíííùùùñññ‡úßþ©ÿûñãÇÇÇǾîõõµx||üôéÓÛÛÛóósðööÖs¾¼¼üüùóøøøõõõÓ§OÇÇÇýë‡NOOûÝóóó?¾¼¼¼¼¼ÿüùÓ[üøñøøøôôô¿ÿû¿?~üøñãÇÞèéééãÇ?~üx{{;;;{}}=99i•<çÑÑÑÝÝݧOŸžŸŸÏÎÎ~þüùúúÚ2^\\üøñãùùùÓ§O?~üؾ¸¸èu¾ÿÞ¿>??Ÿžž¾½½õRß¿ÿøñãÏŸ?OOO?|øðòòÒºµ=[¯Ö ô}ËÉÉIo÷óçÏóóóþ÷åååÇ'''çççOOOýùää¤÷:::jãú„OŸ>õ }r{wrrr||Ü£¾¾¾žžžþüùóóçÏoooíu»ðöööãÇËËË>|ÿþýìììåååìì¬Ãc{~»ã>~üxttt~~þüüüôôt~~ÞOßßß÷Y­Î‡:v?~üèCþüÙvÞßߟžžöÃ}ÓÉɉÖz}ÿþ½%~}}½¸¸èd´¾ý×·©ŽEëõòòÒŽö-ÇÇÇ¡ÇÇÇ“““6ììì¬EüðáCŸà”øð¡ýðáÃããckÔuêNNNZýþ©ÿëÝÓÓÓïß¿¿¾¾^^^>==}úôéþþ¾è9ÏÎÎ~üøñúúÚ7~ÿþýóçÏŸ>}êKONN^__ûEÛÖ™èÔöi}W×þÇggg'''GGGÇÇǶ×××~ìâââééÉ^üüù3kÒ¾vu;+­çñññ÷ïߟžž...ÎÎÎîîîÎÎÎ>}úÔ"·ÅÝ™îF—áèè¨ÓÖœe†žŸŸ¿ÿ~zzêÁئŒÈçÏŸ»Ïý@ þøøxqqѱîs²2'''ýƒbOŸžž>|øÐµo‰Úèããã¬Fß{š5míz—?þ»¼¼d*ÞÞÞnnnŽŽŽzú~¬¿ïU___ooo?}úôòòÒ¥·¸ø>ô>m|ÛÙ"ö¶^¸{ÖªeT~üø‘é’uÛÅÞÿõõµïíõþ©Åå:^^^²1ìëùùùããcÒM`Ÿ>~ü˜IÈrt…Ü 6¯sÐouµúº¾·«ØÞ´­@×òÛ·o-Nþ¤‡ìÁz˜îp÷üôôôìì,«üððpqq‘ù<::zxxèw…~þüyqq‘kSÚèÓÓÓœž«¾Ö'ßÕ·úô)»Ó¥êE\û?~ÜÝݵ ýJ¶¬ûÙQûòåËÓÓÓËËËÇû^¶£ÏqÆ~þüùéÓ§ÜN›Â3ôxÇÇÇÇwwwmóÙÙY'¯~}}ÍÞäG²¾VªSxrròôôÔ¯þü¹+Ò³ö}Ý!7³ÝÙýñãGËt||ÜZ´Ç-S?w8??ϧ´Á sÕåk/ݽMGD¨Ðç÷ë]μkáÃ{æ~¥‡ì`uF³ˆ]ý£££ÎMÏÑÑÑýý}¯Óúpy¢‹ÜWïÒ#µ¶}E† ‡ÉÛö^¿gëJwJ\ÚV»·ë9®®™‡éÃÝ„>³ßÊ:vRÝ«NyÛ-ëläsX®Ür–®}ÏÞ÷Ã=ÃÓÓ“k“è“Ûýóóó¯_¿^^^v|=p;{ÚΠŠWzî××ׯ_¿vSÛÈ‚’>·•궉çºýùëׯ¿ýö[W<ÃÜyê‡ÏÏÏ÷畸›‚³^ÞM͇ö¯.eÏбmAWQØd ;7mpÓúöOýwzzÚabY{Â"‹‹‹îIÇe㥞¤+×Þ÷“¾Ži{Ù>«õŽ-Èýý}Qc_×SµÇýÀ?²|ççç'''E#}K«ÔIòçññ1“Ö­sPúƇ‡‡þœ¹r»2‡Å`Ÿ?î}OOOooo¯®®Ê€¡®h‡¦•~u ì»û܇sJ¯b˜‚ ¶D¶ëW+®e˜OOOïîî2%4Tãò6™ÛÓ÷°àø˜eí[2½ýt¦.³ÜrDÓ¯¯¯™œ§§'+”àùù¹K–é=;;ˬãîé3“gggå­TÓ~÷_f²È6t’ĸ-Sg®-q3ooo…Ë=a¯Æuv%\ ÇÑ—öumX?ÖZ¯eAK¶Ú›gÝëõíJ(/1Ê w‡ËŠJ{È_ÑAi‘]ï>­ÕÈÅ9—Ò "òNX6èññ®ÒÅÎ×uNdú¥]Ζ¨ý Røüù³ jÅ:¸Y:§¨›±`òØ‹“¿üå/œiG°Ç’¯ªò§ƒÂê.z¶$Ü[õJk{ÐrÕljûÝ è4ô¸Ý§Žufƒ ð„}]ÏVªq`ÏDºø‘6 ×xåøÚª\|ÏÈr`¤ó0mÕÇKq ]zªŸ?½u!;£"TÑH×ïÓ§Oùáááòò2«ŸÓïÙн{†Ò'·;ym6²SÒ:sÁë£Ä­€€2 „éKÏÏÏóN'†@ô%˸ÈÂÛµËËKÇ.Kß]ê!3L…C½{&Æñh¿ÎÏÏ?ˆá:…eN-ôýý}«Ù~Ë]]]µU‰–àøøxÍ KÞÝ*/ÉqùòeW~ÓÿB$B¸Öõ3˜.d§+×÷%R.@f£ó׿¶¸YÄ,ÙÃÃCrém`V«™iég¤Ì777¬rß»ÑpÙî§OŸºZO=|f¾3"Ƶañ kÚçä‚Á5ýÊÕÕU^®Ð‹ÃéúË6H6Ùê+\ëëë.O¸¸¸+ô G߯|þüùüüüáá!ýãÇÇÇÇþïçÏŸ»?ݺּ‡|xx@÷¦ÏÏÏÁ±'ÿïÿý¿+ó™éoÎÎÎÀeH'¸Û)±hÉÚQ€@×T‚É4v³ ¬ˆv_er=a®“ ‘üv:9Ùƒü,cß–€„„ÈÜîD¶«ÒŸ N‚êZål°y/ÕAéüeª;RÅ£ÉÝ<µ» E‚|µ¯]ø®“¨·xŒc=‘»½ÁþŒz¹„%—(\ÉY2êLogJÝÚ‚8A ~¸ÿí¬w~ú•îÆ[8Ú Gë€e_ƒá#DA'ýë_ûš¼¹(°|||ä2ŠPsd=tw´.ÏXÓÖæ\TtÖ}ô7½mÙf0ÚB¨u`òååeYÀ*‘ˆt€SªV¼y_Ýïæ‹;yÆ…?…•m@^"d­2[f¬[á€Vß&¹E½B'÷ïÄàBvŽYm1»¨ã¬@>9©U¶h¡2çmD…ž¡³em™: ;¤Ú%ýíŸl¢£¢@®óÚët÷ºó½rèýT³k$LéwÞ[îP1•ؾƒÏj•8¾¾C˜Û·$äû›."T!£ËÞt³sR[Çj¹½ª”¢%öu%Áº0Ò¡?;;k™„Ô ûê 0é9òúú:ûúðð ¾%PÙªUNË)Ät²/..ÀÒmËãoºZ}c–U IM‘Ç(hÑ2Ø2OŸ>…ü\ çäéÙ9›î'{*GíÏÆ¢äÙ6qvˆ{ñòõNvæ&[&á~}}=…Väp[5ð$ lÑÒœžžŠV¯Ã/:ÓíS©nN™ “݉›æ[[f âÛ£ v÷ð¹–~]°:p' u‡>ªš´”ÄêÀ°ò'BçnKfRDtyyyww—5µOÝÜzÿu€9}—ºmoÔϧ9±v×ó·‰-ExˆåRµo/8 Õu))Ýoenoo¬UÇHŠlµŸžž®®®x‰LXßëÃ[[†‰ýê³ô=^÷ç=~ûý÷ß;[îDUD i/öáÃå>ö/Çªè¢øË )rÂA:EŠ]¾·]RÙFâadz7œ9…cxž $Ž…J„ó Ðés<žÚ©<’¿«jP³¥ïw3öô—’%þ ›èæ·Ó¢pö²ðº÷kòi‚ÈÅÛËW âªV1:zB'^= [C²ÑÊ«ºê"i9YOØ£ ¸ó®™3ÔœLROØ2vůâõð/ØbUC…ž———w| ©§Í¾ººR/"n¥Š7l3 ‡ñ¼ Ü’t |®Â)5ºÞ¿›“Y4Í ã¤@ʰ}Ë&y:wÈ”<–öâõ„ÌX&¡ØŸùçp ÓP[Ÿßõ»ººÊQ´,_¾|éºl²Øõ몛{¶Îk«Ä.ä==|™h磣“8æáEUj*@”Ô_]]õ[ÿ¢[÷¹ÿŽŠ¸$hXJ þ,N»¿¿ÏÜDÛ°û.ƒ3ÓÙP§x{{{žâUIgʱ:%!Y9#ĹNíÝÝ]4`V¯VÐW¨z÷æwww®r†)}ÈÓÓ“z¾W \žŸ=??Ï9B³Y>®§ÿÃÃCðÊÝÝ]æ!ÒÓååe€.l® ¡»¤ÞZ÷— CY”˜»Ÿd{²j½ŽgíJgË1÷~üøñðð°0_—ª XXß|xxxxxˆ9It–U&i›Xš•ãñ×z˜.$éüü\Ä/˜ì’ô9+¹Wà«,¶O¨Ä˜,ùøñceÔb§bΰÂ<Òóóó;9#Û-f݃iª˜å­+ˆ"”ýkAsHkº€²/ꆹ‘²œ€[…YqËF}ly^ìaþcƒÏÎΪ ­ÅêÌõRz6I‰üþþ¾x&›ZHÐÝ~||¼¹¹ùúõk!²Óì‹Û³0ÈÖ8ú.'àää$BBG¿Åì‹í€nbÖ¾EQWŒ{rrrwwW!ƒómµÛ÷Ê]H…º^¡í³m–3-ŠèüÀãZOÈúR‘z%´Öäc³çEäT!¡ÙO#ünÎÁñµè}è±O/ÄÉT÷·*ÝÒ€]:½›â{f`/–yx¯ÈýaÂ9¦^²“—IX¨¸•jË»W¥ºŽBWKÞÐÎõR•©6£/×,nAlíV¨)HÞAž.:D;±Ô[ ÙíîUõÕɵ×$C¦;Á]Ô Q½u‘C¡d×Xæ® øªËv_l£öÑö ÙxEòöQLϬv@ûW0ËA9£ƒ× -€<'¿ÿþ;ï¹¾ië¶ø‘ØOK‰ânzÛ~=—qww—%V¡A²–"æð¼y[é9ëÚt>¬K ­Þˆ£‰R£¾ŸÉ쫉#¡7>¹ƒ‚@„¦ã™ïkÿ$k^Ò~{Sä¡LŽô«Êк‹]ë,z;–^#I¯¯(håå*ÝÀÔ²mº0œ†Aò*ÕkS––®èÓ¿n¦±œ5'JºÒ›æ(ŽŽŽÞÑ2¿Æ0t\àví½è6ÿ¨G%*j&†@•!ûTu^ˆv¯à";ý È:fü: Ž—ò7À…Un﫲^__+^·-ŸÛŒË\uªƒÞ¹É¸ùk)Éò¹*üÃVÚP“ŠûCÂ%숖½w¿½½ ÈË›õÕHBËPAžj³J(Ue¡¶ºnJE”UqØ[ÛÍÌT^ÚÍNXw¥ÈAú/BwÎûK.å©}¾ dIÉÚ[€-Xr§öx £Ì$2NÇ¢¸¿+ßZ¸#$1öKŵ…ªsK^î‰W%†- õ[îb@ëÕÀ þãôìÒšýññ±[úòòÒNT X²³ÂwZàpß‚¼Ñ, ¯­7†gSî²lUç&„AßÁ¶xô<ß¿W¬ùþýûññ±DyÙƒj‡p±þ&ߨçG ¹+.ÊZ•› ñ$¬¬b3 ëÌx¨ðªk Ü»_Úv”­Zñœ©¿ªZvñì\-$vµ¥ïÈ(Ù~Éa?NjIG@¦£Ôº¬îRH\ÉG ŒUÆ» ¬D3GÏsʼnA<>>FZ/­ëèè]'K+…éÂ!w{ÓFþøñcߢ8’/>è&‚ûdþ[Ÿ‘ãããw"SìÜ9UvËÎõ7Lwߪn®´ ¾?D)Ï“uŠnÒ#|@Šó ÝÝþ²?\^^ò­AfOð^jßr€Ò‚<ý†ÙÝljos*sË¡óS=I’¥·sv{ V ¿GPˆÌÈ‹Šª÷„9bŸ¡O°Ðº[™„¨*Œ†+‹€[mà@g±·SI ²7Ä>öë!è½Eág¸2a—RèÞà[ÁLV§l¦9lo w|ÿµV¦=béU¥ø>ÔØ÷|‹Ùè5ʲ7.¢,›e^î¦ lãÑ Æ{OãéidmŽÁ¾ µ€RðÇj>==ýïÿý¿õ~ùÞ=L‰x6_¿~í̵¬…Y}Q©}{ÓÅ óªê-­"ccœ„ŒŽškݼEGíqñ1-£IÏØóὠת‘@‰T1Îv8îïï///ߕڶ³§0ökùe«3‚¬ãÜ÷™0¾%Ó–Bá^$šÅ¾½Z—0ø¥ÈÙ*M”ôOþò—¿ø T¬5o=GOæ„ ™æ ªtÑCäâ³¾™=ášÞ°¥ËÇ6—ªî\ æÂmâþà€ëÙ~˜ÅSÑÔpBÍ`8ÜáàÆŸ?ìDWMÀIö”XØ¥Ø*:௠õB¦Óï•¡ÓSµl»-[|Sè 1¥e~hXZ…Ì*\¨?7mØ&9!² h×äݾ¢)aNmæa‘’¸lu¹…‘ÜÝÝ!ÞÅ+ú¨²ÄÙ¿z©ÂÖîåê1{Œ|©ˆ6 × ê1„öË %àSYèîî®B¼‹‚/¶8“oxsƵ”+Õg]Ç©BÊÆk©èKó.¤†0b°ÈÛÛÛÏŸ?ßÝÝ}ùòe5 Ü+-˹.]F‹³›ºy±]=‰F «|½TÊ»lZϸő†ÁXþìå/ßúnͽkÙ7ÛYÆ´­âœ!µ†B=î#C¨ºM£À%®ˆ tl¿yh_Nïô… ‹šæLyßÝÝáYz /ê^Ð7‡ ¨´LÀ)y~~5³&•ǰÍX|ÌŒýCrïôdÈ1ôè—"+„©6IJ"ÙtK|Û4ÿìììêêÊ¿ö‹ÛØ­ºDDŒiË!´>T•äÜN'Ü:¿#tZeIŸ¥roaSX wFb×JÐN nêÛ^žuhÎbéë:´³*öDš–nKiKù…e˜x(]àddÈ>|…*àåõº”ð?|øP!M¶'pDø ¯þ:˜F[.ÑC —5¬÷3À¾~øúúúÛ·oy&ù 9Ý2 ߬¢Íê¥Ð†;7½vúII›Ë °mo´¬f©î'ÿþïÿ¾œÜVÀòp¾µ—ÊÍâb¡†ƒ… ½UÙ² UY¡^(\]=°Â³m¿WP%´ëò@ F9=ƒQ‹ÀÓ+ªé+È!ʽ4ra>~¨t©B%ØÈJV p%Z^›[CDV\èe€óÂÍrÿí’¨a 8» ’ú.¿³(‹ZR‹Ð=Z¶³"vð¾huÀ+—p›D‹ÐÞùÚü&t{ãØ¡]J-µ„o³.’e"qZS[;ájnÓl„ D‡v‹°f¶Ö‡ô™9ñê1ÒŬ(»®# Ç â-“[Ydìõ&tŽ 0X @Œ­¼3T(­ÊÂÛ€bÑ0wkW ¬l™¥Ô¢­€w€ÔËwcq‹?~üøíÛ7R¾ýz,,ììììëׯ_¾|ùúõk |ìB3—ãÿãÇd j¾ÅVÉ‚*ê¦ ¨#ƒ‰lÙQ¢Áá?~¼»»«NñöövJobS3Ær1?KÖ™!(@‹ ·^ªQíÔ­ìów\°ã+ÏË«¶s¸½ÿ¶È¢u÷Tçççß¾}۽בޟÑJî¯\‘P=W"üì"ní½ SÙ AÌ'÷’혋¶÷Ï$ÖôÛIæzB˜TÂU^_“œ8e^ßr_­šºjÉ )®F'†dC‹â6ºh»§É— ÃöE‰Óm™BQ[µ¢,¤¨1áý˜ps/Ÿ¦4µ¸£`hKá"¹¥4è¶KLT#@á¦.¶lFÔ–þúúº®\L«}M³.e®¬TµÍ·ûvªÇúCÈ ˜ê¢JŠWä|‚à˜—ø[y/‚K¶£íRuÿqq½åÓn/®p{ÝÒy¼m*1-^«‹öÒÇ_Ùö}á=XÏ=Vú¥<‰mP/e7ûÇ777ò¸îqÌUª…Ãe3òãÕÆçÊRë$9??+MaÅmÑr¨™¤_ÅùææÆiÓ(åç_º¦ dƒ<ó†+ˆÂÉ"ã9gm?îœ:›·õ-§J!ºóÔnÉ×® mW@ƒ†Ä œ ´‡Ù„Ôë-úØÚ¼¨²‘í_!ömg_Ê_ë߉ɧID\ÌŠ·ˆvUaV2ZRz@ÃçCÜÉn`Ùmø×××ãÈ®;IøL½¶„& Xê¨eê -ÓØûgÛkìTÕpd…¡Œ ä¨Så€$S*¹&'ùꅻݓj°œ‰†Ñ0•wÖéO o ¡Ì §¦Â·Ð¯žÏ8bu*ƛȷZs¬\,{>t… ±Z i)ŒUö½ßױ؀rñÌp©›â¨¾h*º'œ×Åyd/äo™6Np\|òúúú!Ž ÙT~ñJ.•!Yõî­oi*‡À£xfYû>”9Ä(íínØfv%AzP†Ø®UÎÝGíÉÁÕµÛMpyyÉElog[õðð=Ñ©Œw¼íV>†–QÌ8ùpd¥°8„5_û g# ‘Nª“ì"‹Ñ:ˆõ]½WŠˆöz3–¾RÞAÑÂEŸFDÞ¾SŸÐàTXÆÜFDª$ý_–µ?Šd/b±½µÈ©oSÎùùyN_¥GÐóúúïýåååúúº;×oqdeH¬ÎÄRîÁ¢gññ¶˜G¬¦ìl‡ØÕ4VHך¦÷"³s>6¨]"yKA[ðÚš<>>þóŸÿÌEtúäºÖ,ºU¢¬fÛÎÏσ¥ Îƽ>¬=^?Ž<ªR–¶¦¤¢(æ¨ేªlUÀråÜÅE1Ûv’í, þ¦]Ó¿Ô|þü¹="f*¾*2Þ–ýSÍÓý!CÒÙ’öß¾}Ó½¤ª°.Û Ù÷'PC+óû÷ïÙ ÉÔK!ÿyüéÉá¡ò†[•(=ê± 36t ©Ë#J} ¶ 껃Eœ .c9jVÑìΦBÑ«)§¡tÙZõ¯Ô<éÏ!L‚íüLÕbX¶kƒÄ¨3[§S¿ ÐE*ú3uDÅXSa+IÏYUòǪda–µnïm|¤[—¼\Ì·Ì׸º Ìvаכ8ñ¨÷÷÷Õ ±uúWÁqmÇë;~,~IGV‘=lø¨ï…êšâ;¯D ¶­4—Â*dÂ{ê›Ø¡ô‡Ýx—B 3¡ ]:µº,Q³ã7æ.ZaúÝÆ¼Ú¨fÖM¨dàœe>pFÉ@.gªó ´ëëkE[“ÖFk¥×háíè='ŸÜòR*PB’.K­àâȸ9Ê ŠS+GþžlÑó¦wÙû Žô¡ÁŘêHU}©#ìØ¾ ƧðE:©eÀéѽ-‡Ø1`äžÅˆq–zâg°´ˆ¬±nDyæKøúŠ -Âõõ5;"vròvEr-;Ѷ¥éjy­Z»á,tY”)÷29­h5[ÅðMK!åU$hºW¨8Ü´e]ÜŽªµÕ8<ЖD]Ú#jéNÔ¯³îd—™Õ'Œ)pÚ= EëVIÿK$<ÁFl$r•¼;™: –.‚¦”±¡„°´77a{\êI˜6g« ôç¬ã¼òÎݺjžë#£ì<-i¨«’màôµ¡#0<úf—«¸QYéååe”y{¯¼f5ÞÃ{õ3 &Àà ¬üe ¡¾_äÊm7o±fž]‹„Z´- RÚÓn„ƒº©Ûñîîî}é0‚ß{½ê€ÆHò×Â)ZŠº Vy}A0#»Ö ªiA¹Aú X36ŠãZ³M] ðNoTF¢I¸aCObF¦Eã(Üp¦Â¼šÀ`”€ZÆA%sÕ™<°ùª8òEJ*âþ´æªbúËËËâ„׈ĎÚhæÊÐn²…qáþs§ÙWuEI_i£ÓïžkK1FJ|ëÃßÞÞÂ+ÞQ´óósõhuÕî ¯®®(Ë-M›'Å,ivGVÉ´{œ ë¸kOEYdŠ+úÀž-Ë{'Î[Ý™u‚Úoß¾`e, ÐwÑõÓÉ­Ì̪锦ñ\5kdÓG  8§´/‹KàÐqe-4çV ò%xk1±]e# OJè–ã›ÃòWiöèEcŒÙï•å[ýøþ©¸¥³Û:ë©\§Å Ë.Þ»Õoooƒ`œãFIjª›iZ‡ÿQžW)ÖÅÖzu¤–—Þ 6¬ïSéœíÙÁ‚«-œ—4bÀ‡´Ùôšq–Q Ýb0º¤œÚÖP…ÅË\67Âü,‚¨L]Á©KR_@'°ÞÞHTÅ„ »ã¾MFÐ :úÙl%þrnrCÂJôy|vTœ vûsº·4Ô9"×ïðœ’*… ܈ S׉êã HᆻˆD;ˆËÔ+± }Å9«›¹¢³,Dµb½îNÛNf;OˆìTG>„Ú–/»¦<K¨†LÒ H¼;2T~!gǧl«$W+UjÉnoouϵ1uó|ýúõææFkå’…³Fz£ ¨YÅ5='¦ ^^^Ö ˆy©ø´³ÐhôcÔÑѼõÞ¹¬ß¡Zv“2èLGF¶'Æ‚ ;–d䃹’ãÊë[sm$Ý|û׉þ³&07XçRTç%€óö²Q1 ǯ(?õ‰’^¢†ßèªXÜÕÝõ¤¤Æ?§ìÐ;9… x<ï:ÿûß•Žºp5I 9]Îwtä.ÈA:˜æ–£“º¯òi5F"Êš­ZÑzNW¦¹ÓŒ9µŒJ·-ÑUçÇ–^—¦$Ž©ƒ¸žíCÚ1}Fjtª1E OAØð3q*øOU=<› la‡knG»Ä\й,-EÚ_ÃÿÈ–Øc½7 ¾Zþ€E]8±\ÄN°ÐÖÁhéê%׸x¨ÇÇÇ'ÿñÿÑò>ù:Œœip·*?!öuåÕQÚ?4zÿÜd[]`È Î‡n&NH°å_{ yå(”žô ížmÍe-öÀ¬u¶¨FŽ@FŸU„Z´Ž ¬;Zîx%5ŒŸŠ/–-Î!„(Ž"M[`ò™MÔ‹UæB)v¼ü¼D…Ù›öØre-—SÔK _~Õ$Z·LOæ]uªøL¡bƒWÊÖhWªžw{ÞÞÞjHBåTp³Ç"3õúí¯ßQ™=3A °¶ qÚùxû²ƒìã¥;.«ù[Z •.åªBÒÞwÅnK–-äŠ:pí€!Î1‚X2Ù˜T;± ÔxÀÉr#££tŒtàŒ$èŒô(ÌÐFJÿÚ(‡ò6ÔuNCË._ü ŒD¡ÚA@Ǭ&¿âîñ·|æòµÚÿÂm2™‘D{Äþ Œ+Šß‚ëL̯³&ÙƒüdUp„ÒÁû*A¦‘¨8¸¿-~MÞøÃ&!é!l+©QIÙΘJ···t@7×ë%ËRW CF© ˆ©@dôIHWø|Ëë+¡¼¨­USMÉ4ªÆmwƒ¬_Þ€¦¤b©+f뢸;ª\î t: íõðÅo«Mœe¹x[P „Ããn¶±™:ÒðÎnη¢œ¯n­q¶2ðË3tÐ+<:—Åj´k(>Gbì–SÉD:1~ë:<]˜µ;ªÝ; ÚAÅB@±Ì¿Ä¿vÖ =l“ÓÁȸíÍ?p£Ôœ2¢ñÎ¥LyÍ rlh,Òì/¦ˆÂ\Œ–åF博$uùè’’]y«&f†L_ÃAòLoðæB0죣£wÅ(r¨'T@(h@éëWÄ´+zu¿ž£_ ¬Ô¬Z)²‡€Kº] DÏÖÓ4–V‰—Ô6¸ãâ{ÓÒ8éÂjD†ÒpV  ˆÒ/V Š 6ˆ·®’×Ç:p=ÛV`˜¹,brØ$¤ôí—"–XBI¯\Ûµ½ ¢à?:;gIéW‹ÔÛ›F]Ê^|ùòE€Ä²¥4Þ¶u°§˜û<¾è#í„#q—å€îXÀN*Ñ”Üwß…;á:¹ÀÞ«c½‚éù(J…z¸ÍvÀ*v|úôéÛ·o†Æy‰N¼š])Btý_£rê$󡆄\ƒàéãÇ]¾¦ßÝÝÎw£/ÏH&Û×tMCg¶ÿøññ1\£ûºBb(¢„}Û‹»¾!}H^7¹K¹{[FÛu›í‡Tó‘¬+ÅÙi[ooo_¿~Õ²d"€ÒZþzqÕY°TëOÕ*aHFÛËž¿"eV™¬N½&_ƤYîË‚Á;c»Ÿé+6uËXZÃrøáÇoß¾…Ç#y-×ÙðX\¼¶ “;²æŸÿü§òÛ‡N‘$îa™XUS«™RÄ…m5ð¶åýn…Uy4U9.µ˜½ñQrˆ¶ª.~Ä9ÕX·è¶P}{©wU/bßyImeµþX¬xÑ–Ô$"…øÛ¬—™iÑ)¿êÑ Üíóc^KW-ué¼h ík&Ð혫øhhô£¶\ì§®8VÞ²my-N8×ååe2óŠø\o³v‡Y!X 'Pu B}{{;•±¶pà:à‚NŒ%ä‡1éXã%,4Ã8¹| å,*“ìðfèý^Qâ‘ýˆtdà—H¾¹r/;P”ZËÎà\ô ‹Q¼[ ±óÝè3qȶÞS5Û!ê[Ü:ö:´a¬*ߺν_ü_ÿë=>>6q€`”®ÜȪxc£û/}$ÀÌwP»RþøñãíííÍÍB1^nš}ÙÊΆÂ³ñ–÷]ö‚.x!,¹PŠ[…s?Ðp”vØ;Q ”'`™_­‘ ÝÆÔ³ ºOÌ+ËýôôT3L—ûŽ·E—jïFáA®jÀª¸B9ªªÄR^úÆÔµ€ü4Ê·Û§M‘Ya9#ÄÏî ˆ^sÅ,æptÔ¾~ýÚñB*Š­BuOÙ¹oè Ó»u.œ¿€¸õd¹‰T§Ë+êíŠÍZÀåbonËn15Ñï6-QkÚ©6.Ñúíí-Æ*÷±Üïì–Ž°î½vû¥Ù™Ž¬£YºÿYªbÄ­Dàjêß°\¼v±ëëkž‘¬Z€×ê?*Él0›RÕÕ 0ØËnàÃÃC½bþò`(°RÓ¾Íaøƒ ¿óuÍK‘Òù1” 4¸¢wÞC™pG¡¨­°y>_-Ýt§\¹½:êDM\]bÇn%\E†¹ SvV#ÊØû䳿ýío¨òÔh葇®µà B3ûr)và[Ž© Ó÷¾­ÒÆBl»ŽÖY¸IOÕq”­k…b ¥Àƒ€áwù;º­ÊÑ$^6!a«(¿“NI[îÀ›Ô4© )MµªTÜÄ|­ÆË ãsw²nX5vGq„~úRa¨6Cç(çur2X˜ì}ËNmØ›k/nÝÔx7@GZz׃ÿôéSÙ´Œ¡\¸§,˜ÈÚ#@¡S_žŸ\ñaB¦tSì ü( É!0øòåK‡¦uQŒ(\‰C‰ ­Ý2C`ÿå(ªä[³f“ºu™Ìhµy Ü̃£ÿr÷ÕGÚ€˜ ¬WëCÃßð3sƒ÷[̪GØdULVF«Â6½ˆ²\¡j­ÕŸô!v ØÀ 9^‘‚o‡²èËcdVr2ÚŒ´Úg«Þñä“dÚ/St*$½ç…ª½xø* ÒUPÛ9õºv´…ôÙ¶m¹é¢ã¥b²*ªÙú,k+"ð0Ò©¿éXè¤MüGl#VCóƒ%÷ÑU[îŠ 2÷ öååe‰…ò[»( Ò³iSRyšXòx §€´j­Öïomqsu/ScXF©wä‚ Ù(¤Æ³yšÏ€Æ˜¦Ð¸¦W3fS[%â•SAÿå3êfÌöí¶St\vÖMqòJBšŸ£».þnm,Ь.eLme§ÑFMC«§]ðUL—¡Â CÅW“Ë膟«döùy–&³˜$ñÂcÃçèö6ê¶pÇèE^]]‰&®®®¢®®j»•ìQ¿}û– b&ZÛ觬TSœðÊ—°ÖA×À8)¨ 6”áß²uc‚[hÎ63ƒë0üüù³iYŠ|Û†8AýWýÙÙÙÉßþö7Ô¬C鑰‚Á”Âðqæ%Ëvíc©‹F2ŠÕù\¾›Ù†“†Ö˾íî­H(UhÄ·¢Içx)¤VÛÝÓ &ÏëˆwKR«¥Ò’=˜iöÓ#]BLÈ«ýâÒ2Qy/ßçs¯šš“Ú;« ËA=aeàUW¨‡‡E×â‹wH¸L_Á“Û>RJ´Ò;gW½ÃÒN†¿m:ŸŠUÌÞ†à×âÍh ;\ Ý"ÛMÀ™²ƒÒlYÀ#¦Ðôâx*ïò‘´‹ùð—µ=ŒHpàp{Gv\æäüIô97)cØ!FÒX^s˜‰5Ù¥ Îû9ß}»c³Åù ø?ÔÌ—‰/Ìþ^ÕÅwÄÏMó,œÌ±Fƒ2úûûûŠU‚•U=Ù²¤&;ÊÜ™ èláÍÂÔÆY VËiu <0µ…lwƒµëInoo%LèZÙê8ÛkàDö‡oß¾á|hø._·5¤æÓUÄaè,ÃÛ…‰9"ÇdÑQè±wä $™Ç¢Á¾ñާ…Éu zl5âCdu­îP %·*&廀£———Sàe®äztÏxkŠD¢"èì ‚½Nµ8žŽIÊ•>¤>I]×××é­à¹3Hòú˜5ŸíèqÁ¾+AäUµA ÝXä˜aàÑì“ £êÆ¢ýVÉÞ}¹ª<ámš+ä¬#8ê<±\âcÍ?òf]Šëj:š>f‚t_F[Ñ·ƒVAº‚ùèò•¿jY,)ž’ í.°Â-RúÃÃecï@ÃÐpÇþ©*¹™Í:¤±H‰Fe/µ7¡?ç’ô¦jÚÌ6ëÇR‘w&²yBݼ]BÓZÀNvÄ_ÒÒáe´[4c­T™Ó«C¶M†Ô"”‡iìŽM‹ÀoGœ!³Hqi¯Âà\U)yoO·}EQJqÄ3W>ð0ë1Šé•äú®®®ZÏVãââ¢âÜÖÞÞÈ¿üå/xƒ žI}ÀÖa«Í¥`áåÔð¼— ®@tV™üÑ6-ªïS/⌊·ò€(Ë”‹Pˆ0 AÕ@¿ }8¬…=€c›´e6ØPK_it«(z]™r‹C$K^¿M޹´v–Î"šrGë¼f¯S&ö‡¸ öÜ7R ;p93DéL!&Ĕن3˜`JbGh¸RI=ÎZüöÛo¾LÓß :‹è{å`ìà.„™>k*¢8 ËíÜ’ƒ¦¢M2zgVߨ7ã ·"²ÔfÈ×ÖÞ€\+adVÉJï®l´LÂâþè|Íè_•fx½T苤 Zå©îüÉ#wð6¤¾´2ûêðm²£¥¡ž¦z˜ýNeµÞìÅ믱^±mëJ+¾Ù+hå—iبèýý=6íóóó»þ”'DãA K¨&¯BãÉÏÊi*i”×¾‚¸Ä¤ЀQLªiY³ßÛSåªl/ÔÖ5µØX°')Ñ’ðͧ:¦gœ9¤b!Êö4­eë;PE;® /ÿ°-ÝY„ÿ²S^—SÛ²˜û%ŽÇYé– ¯Ãâ˃õYMOå†]²E¸Ø-%×þÍvIˆ_Ñv!h¿Æðaõ~ûö@CV³Þ•*¥0»"øðêêjG­v@…ž[ÆÀQ#Ù ' ›»Ž}NîUB¶­«¹¢pj0•ŠN‡¦b¯*ìcy½¶÷‰‡¨“™É¶-~¼²DÎ hRœzEí] ¬Î*½…:×××>Y’ÝÍÞ“Ýì¯òÈÖoõmhBÌCéï{ÝÕ€U´ZªE,2VÖ^†ZÛÌ ôRC¿tkþšm]Y˲ií;á·4™û×A[öÀ}ã.ä›\b‰mÝè›`nu—  ¤Rì»äo6Zkü2ÌrQ…nmöXë6œ]F×ü2µë<óÕ}éÅÅ…h~u'½µBwW¢xz cfÇ5’м€7)c°><»‹Xºê ÌÐ?íüAÓVß*µa9kjœ¾«ç-Né…#L"$"ã[ŸÏŸ?ÿë_ÿŠ¡q|||òü££CÎX™‹ç`ЇZùVVI/I3ê ï¬RƒºÜg{ß40Á©Ü¬|³È„|'¸Q"hÆ-£ O£ª€Jlü¯ÏéaŒåUE3€j  ÞŽ›ÃqFï´Ú*vƒ8@"Ÿ©ò^ sðvÔ‚‹ww¨Ègçvä¸]E™mÒ.ÕSkí¨HãvX‹Z±.å©‘ Í···“ßÿ]iQ¢ører¥½j»FhÅ&0¸ÜuH>qÆÞ|i8H¾è§0¸´KÛ[³±³?ÂpÕý’Áqçt²­®¾o× ‰L”¡2À:›–vÐzº£§vø ‹q 0ЦÈ%¼oBK!ª¶J‹U#£°8½cXÒ:ØK)?[¨EvÛH±xMkƒËîä]„8n™mÓ„–3Mô„;=ù·û· Ï͵Öüîò´äÿÕËÖvbÈyv«…FþWݤ8"ü/ª+Þ‚¬¼…“cÔWÓŒç(Þ¼ÔŽ|1HÁ®¥ º6ñÐMe zÍÓxÛÝvyyÉŠ¯b;1v¦æ*Bñ ]ÁpØhÊ`Ñ¥/“› -²©Ûƒ„F¸*Ê2<3Ø´‡@…žÈ«À¬(lÛ2a|||¼¾¾¶}ÇàªÌêN2ošwÔÌ4Ë{¥V6gÌ´Ã…W_1-Èw‡Êb#@[aþÝH¼i’;OOOMe·!ù;©bRØÇv=è ßq{­»qF‡¨õè訞-¼Þ¡¡(ohÅ)t:´²Ì„¡–¿ö Ä$»¥®ò´]“³_Œ}cS‰óÁ¼´šö7;¡ÅÝë,v¼ˆ¦i"ê[ºüÛŸ»H/¹Ì»T-磻Âìãóóóñíí-Bƒ šª/x†Å¸Ðæå¯ô)ÙE›ápºÕ²ˆðbšüPØ%›åúûy«‹§eÊ*¨GPh3m/Û4‘.)!,îùí4ï}ñß$@Öl\ÛÕ•!Ø—8Qx­Ÿg§øj¡¦˜"ñ’<ð—H̶ø]f¾e¹]Û±C¶Žþç>ÿÊB¯ºÄ»wŠ·‘Ý5kåÛörgá |B".õâeÉ–X¸ý± ~#puÐw„Ý*KÖÔåˆBÞùÐÏ­EVùM¿ðÂ’ÑVºFcó2'·×Wèl²þç-\µ) ¨¯A sÕ¦X£™E)çäoû®“YÆó<£¦±ãAG˜Lvy¢&on´€W®¡SNCåÙ<1Å À>™'Ó"á¥æ ©Ðþ Õne{úfê9”-œ°}ç¬.¯ŠH7N‚±Ü;Ä0Mª;ùWñFÅņ!Úí„HÒtf­iܺ~tÖºïíꨖ‰ëKé>«ÜßßßÜÜqí$K^U¤¸âèè¨qÏ\C²Ñz,XZ’›,+µJƒ²ÈV¹´U2½*dfTáµµ¡Yʃá9™EzVƒ¨ %•¶2XL¬ø‡e/‰ÌÕg€N¹x!HŽTó£(o⥺Ëc‚¶^O½ßyåïY&‡~A` œé¢,w¹N|†ï¬T&îä—õ!µm& i[ÝÑ|N¡‚÷vkËZŒ´¬‚釵(¥ÖNSUu iÐL"Ù,øãJAŠª °]0£q-5w¡Ô"ú<99!1$ßïeM•é:õ3Ÿ@¶N×ô©·2Œ Z£™Z€$f‘”Íca›\ L(ê“Ý'͉6جùÙlcרÀ­x/?ë+¥4ß±…úv¦;˜jÛ¸3fEö"roZÏoÞßß›%-ÚÙòÄ&[ä´Q³žºÍL•!q‹™I K¨àÄó¶l'¶ƒû AÁ®fÏF o`Ù‰ %ëŽH@l›jñº AÏO”ÛÛÛw´Á°Âö²ãEyŠH»b'4ûƒíÜ « ¨„Ný@Ķmh½a3WŽ#ž O”ùló̼Åʵ­Vp¨0T ª ®£Q’-[ ñß~û­GÕ[ŸtÅ0m)WvnÉ+;®²Žvpýß‹c¬½áØa¿„§ÿ…ú3F ú…÷Wñ%‘hŸÕç0Ðt¶žJ—¥O¸¸¸hmWücuDV–ø½‚^|wO?ßÖíÎÏÏooouP`?ÿ—-pÐÔæÆ@§W–B!4õPEo[ªè|˜S ÜgÃdH;Y©ÅÍSáªdi·)———±d£¹-ÑÞRå¥zÅ—ºPªò;Çž­CÃjöÖ’-ƒVH:+W"Ci7E¦©îŽÛ?E´Éà¿î°.catu+ï©6·´ ð¯L  ‘~)µÓ‚ÞÉUšö³ÍŒéè݉OOOÂQ­AWWW½iHë¯Û€­^£¿_y‰ª‹«A¢WZa*ï¢N™¾‹+áÓø#’‹K©„uƒL@XVøJ»)%ôj;ðIåð@}5m«rX™ÕžÜŠ- niufžì ð‹(˜eŠÍeб³†°ž*™ xcít\²÷üdÛ º-€R ´ÁâéìÌ_óHní·ß~뤊úÉb!ãe›¥ YbHÒ¯€úUW¢rð.‘ §ÇùÛVRíJÙˆææ1«ŽkðØ‹¬c$uMݤË@ až¨G9÷0gì[VöÏKݼ¤°2 ¾‹xƒ’J‹h.ÉoJ” èæ4H¹êFôniåBU³\“˜ŠÙ´põ»èŽ/å=:dß¾}ÓóÄAí*â„ 1ïNø]Ué¿þë¿”IÈÇ‘i؉©.ÍŽ“Á´JÚBä 5Þ¶Ænç2'„3€ê`Wý*›Kîx°¤qÍTMxÕ{âù]ËEÏ  Ú0ØF&QÅm­ b<¬¦ ö’J͆Â9ŸRov‡’œ’}÷¡Ôd¥jYŠe±xZ:ýBXÖt‡û"Vqí!Kj͉v¶ArÖª<,n0åòwLÒr·f»ÕSýÕFÖüýïß¼a µ„ï/L£‹CˆTp0H"ìL¹Ääßm¥ßÉuýåýý})QAwß²"Y¾H½RŒ²(˜®/ [†ëª©ap5!WÆj‚~ÃUºüKºí¥}ZátòÅ0i”ma±äß@/ñgøZHušNÿZ©¿ÕïÖBLx«ý<áo¤Õ¤¡‘Ãê1p«ç·ríÒ_´nÿ:¹^X D¤–âgÛì+Â3ž`Çи\nr«Ü~ } ³ZØéê¥K*€Z@$,¥éEEÏÖ&­P ÷tDZ²¦a4Ëë\vvÅE¥Œ|K%â.ÆÎÃX»Þƒþæý%;GeR•U#…)’[ËO­¸¿¿‡8è$§2Æa½”&z xô¯ý«øU»Ó¨±³ˆ™n—ô\¦`,èN°jηäØß]¢ž}ÒÕбBWöy[+5 íôiìˆh™D¾ØMÝ&0ÂÈ_•mD6žÑæ_³íÚ;ƒ8ë®Ð%I±ûSí§+ªn¬f†¯¨˜L@`T§W• î&èéØ 8COjU$ôW…?¶tâÔµà;j©ž ™¶õEZɉå‚b¢y†µÊbSˆC¦!y%l÷´  HÁefÖ“ç/zþ¶Ú Ð Ò6JaÅÀÔ'©Ôè²úQýÃ.DÉÑf$Ä›`Æ_BÌ‚YÎëªi8åy:{ äË{l®Ó^šd¤ ˆ_‹Šöàiw¦= #YÅ^$Å'B0=¥êÒ« dI‰ã …‹Iþp_^usˆj~}Q©•1áy6U4ñžþk+Üb¤€Ç«IßmÓrF~g({¢L½‡£RPü–Æ5êB -Zµ]Dbƒ˜¥ÙªN[Ùô¶¯1åWH29N3áõŠÙ3Òú[ÐCHCcëÿv@ÕºÙ\D¶ðúúº›À‰²=² §]ªls7íòò2êIL¨Ç{:ÊÐ@\»N7S°!ÊÇ}Ù¡hNöâzÈT÷Èšûtpèbnöè+a¬h@–Â9ÉQë£Ü–¡n~ûX…2%ä¢)%@\äåîýâk/FCS4ÆÐJ$heÖYÅí®°‡d¨e*(bqÜ;E»èp'|, en§q+Ya§¡ZPýT´œ]ªß”AÄ‹¢ þ———”b‘Ñé=jѹ©ì…MTÓ2¹v¨Û~ssc¶üê#d­ƒ "u†Dù¸Ëò°S+yg)4úB…•ïw¶II E©\/ å_Mן?þöí[f+üaõVì–5®ãÛÛÛñÝÝmáÎJm+5šk`ÆCøÚ݃–ȨxNðäW¤äMi"鬷b}µªõ _ÕxTH¯¯¯ëšÜžRµ~ùy ¬. ´1áàUÃÅaþ«¨€Þ*´=ÓwP^½iq0Öì¶®^qðªå­‚ \LÄ™a.LWâ)mh솼ä€xñ`d™ž™uWîG±­C[¦ýóîîNDXH¹¢ý::::]±´~"B0i”É.bC©·.zyŸ`æàS…Àíôå¼¹¡èHLݧF„V€ Ÿ£A‡«\¿^+¥n'ÜêÜ·@:rõ-9¯à¡¾]t%ب±»Z½Å$¹)]@úuÕuù–¾—;ÆÂÙžJoðDÓDÀ‚:É~'iõ,ªÇµìY®xý¸x¨ß‹ýé¡k{0¯P9z{RHyz—Æ«0—‡†7ÇnéssCÇì›6m–©H7Lx&*°fõð#¥ŸŒÍj,¶9Dã“þ=~0š†=ÆîÍ© ôH*AI˜‚¢úÝtP­È8Ï‚ê¼EÁº[¤tSõ/×LÚ!d²—¹ÑÎßr½•»™ílXiŸoѹJÊx»Óåå‹P8ÔA{Y k±"`´²•o`…Ìwæµ^h—-¸9p§JÞÙEgõIH«FI~3z÷2ý¢Np¿¸Èbæ]@vÛYᣎ‹nêqµ¡-d9k­5ŽsÙ¬R<š{+Û&öZ­úø¯nÿÅÅEמöy°ÝÉP-Hsg¿ñìììòò²ÓÐÖY©¶ÌNQ@[W‚€Ê#·óeJ òQžÝCR=; ©¡Ð¹||T8hìS‘¥‰µÔ$ÓU› ¿~ý©¼×¼Ñ[Y#4õÕöy,¬% !Ñ*

Â;ziúB.LOËÙÙÙíí­I8¤•{_Yúƒµõ ·WË¢](|×p!Ò0Ó>"}ùò%Âë&õê¥kJÚÁìîõõu õðð`³rÄ; jg¨‡Ñn·=Èo•£@â²T|ºöUC@éF*›w³¡ÐaVW\‹…ÖÂ6O¦ÙÆ7êÇo§sU[yb`æ0<’zÿ GXÍÕ+ŸÕãEïMÇ‹OVN6b›o‘Ô8S­Û …ršŽ ­…6á[T©8 @øóäåÅæä'HQZÝ.Ê,Wg8OðLv‰ö”@6sI ÛiÌìÐ²ŠŽ} jüŽÁƒ3a÷TMèʱ„² öÂ¬ŽŽŽ~!Ybÿ*×××?~¼¾¾^I³ö ”?0óSúJTëÐïÄ\\\T¸Wx܆¼’kÿšWÝÎRÙ >ƒu)/.æ¿°iŽjÔÙB+òõ60rJµbø»$᥌"NcoW¶ÃŒ£Í‹§ÉÜVÔÈT6ÃÇŽ'¡·]Ê„p2„r©NåŽsÖ@bx3óDpN¥Føa¬¤.Г¿@áÓÓSv .›¡ýTt ‚Ö:(i.DUTiè»E‡æÝ,†×ù(“Xˆ4wî6‹ü¾©T-V°hâKæ¿¿¿À…ŽÙ“ ÐknéRÅLÛô›s±˜ü>v¹ÞFÕQÅqdVaq®¼Ç.÷> !òȉÐÜôs×ÎPrqq‘íì>°|ÒbF„Ze”þéææ†Á“éË8]’:DUI‹ŒŠ&[%ÏD´àaIhBåYá=7¢€ZL*g{tttòþÏÿ;êÊZ±vì*U~>½&u´ý;W¸&øW‚iȯ¿æÚüÁëTžÁu+çË©WÛð€Ö)_Lë›ֵ͂aå×ôG`røD¡Ú™µÓÁœÖ"nKÆà @EVðDV]}QúDv®iº$ðWøµC ž]·)üm´´ìŠÌf~v‹l“‚< AW‘Åy¯Jgó³ EmšÅ]1ëþ^6ÄcÚEt¾íù³ÐûªïTÁ@‡€Ô« b‘´d±Á]+“V"ë†ì`&ñz8¨ùðl©>м¾exvìd¢Ì`\SSq„aT¡Œ é™Rè­ß=Ûï¿ÿNb †b(°£mîC}ip€üÎK9¨Ôo3âb·d7„’Èʺ 0>ÑB—µ[TÕ^…]N­ ¿ª[á7$|²|‹®£l Þä’CCQý™ ¼}…þޏ¾„¡MS„ÝR¨…ñš(— 0™Bð¶?µäÔá6úçÏŸ!Ö°‡³§¥oWÎÅŒ[UŠA´´{ûð𰘣~81Ï{â‹‚Y%³­PR³Šb«þ²èòôªÅP>\e.¨f«b _Sn)íñ#{Ô¥½äîÁ«Ò/ÐfkÝ O*®Ìåy¨D`fQ²úˆíæ§kÄ´l›†OÛüzñæ¥n3>q»Š#žv•õûÝ Ý•¾iɘÎåæÓ®êà 1+Åo½F`ƒ¤eã¥ÄZ Z}Kôýû÷jLx¡;tdÕ¾ºiïlߢŠÅY©pÉ'ÂÆœµÁöRp¹ â ׯ¨ü¢*Ô;bÝc¿Ã;[¬››y Aþ„r‰ˆ³„`–J Dci›vb¥&ý¬‹ªu˜ƒ¾—>VÏfw8œ¼zÀõbU,Ër ÜØ•3!‚ßQ^=ùÕÕUH0B£ËRr•ê3mà­bó&€Ù&u„ŠlËo+ ©Ì´É & ‘«µ¥H†úÚ½¾¾¾Vša«W³"ÃjËC£†‰´!—A‘+”JÒ¨#T4±æËÿõ9¸ŒÙÊ6-Û¿ d¨iÅY^â¾ãÏW¡‘š§ŽœiÇËK!DÓÏÑöÝÄèŒnßÁNË ¢#mßú_»˜ß¦\]]ýóŸÿ4ÙPÿ*lµùðÝù¯_¿¢Ó(©;·Ã7cÒŠ>é¬ X—RÍ^ZpKm|PýEÞQ_ŸÙ\!›žÚ{ÿüCcZÁ»ë ƒT©[ÝtƒA4å˜Ùîq™÷\¶óþr@íb8šUèepVIέîѤìF$­]qu=Êö-ÙŸ*pjŒÉÔ‚’½ÏékkÃî#ɦÈçþ`²/Þ¬Iáú@\¬òýŽ¥îóå 23µôÞ¥›@K´`I@ÂÎT£®/1M.ŽCo]}è;A¥[þðð°zí N…MÑX[÷ÛÛÛ««+†œ(3êJñkÉ*o TQ7`l»šj@°<éj‚ô½{¾›F{»r¯{¶òó½@¡Eèóëîßêèö`·61ÇÁk‘á’ZXq”$eBNÊš7£¶–!)y-¯Ýàž­F¡ã&…TW„B¦ dð·Æ þ±n½ƒü¾W#“(Ò~+^DÒ`éŸ?b1/€ì&­Î2 ˆLT4‹–l„>3TYŒØh¡eîàÌÅGûû_Rº"Gè¸ãDÀ]líæ„”vŽ:áRah hà1ýHß0¨’4X¬£R{h:>äFû¬Ð CÁ Ñ½lÒŽÄBœý}¹P§v1©¤óÕÔåT±éÈÑÍÅ‘:99y§¢õ¶FæaÜUðhÃJ<ÛE€ËÊ'ýöÛo[ÌŒþXU0Ë¿“‚!È Ž~³%"ÌgíŠ ­È¬ÊWÛ±¸“畯¬àf3~ËÌe TYÿ²–Ë–P‚ƒ·×Rlz ÊnÁ·´¶E –BCSÀZù˜–˜¦½²Ë,©—wú{»7µí<ïՈؾ&ƒ*DÏeLƒ>¿e‹SnÍÖÂàñæø §,X-A^Ñ+$Ë€—ÍkðaÞsõν°bôÎ4ëµa···×××µaäµQ@ÆÅ“7”lÞ®dõÓÈö<¯à¸'ØQ<¥ßV‹wãåuAõ— 1΀£+zYHûÐó¯àdkµµ:) f zxt†õ~®ØG^úäääTi@™¸HqIµ&{°ê;¥ Îäô¹ò»v]D!ðßz,…’í>ÛÙXA-¬›N‘OkTüv–$¼z[Þv Ô2ð™ü%žò!ü@·"PKýÖêƒ-d¸©&ý•«ßd”Úó&7™¢h4¦þ*`udù „ks ”Ïùfq¤ç]xËØ€;Ö”¤Üùé4+2o6²,ÛfT[KýçÁާâ0/ô±]©æ©2ª©’1îȆ>t‡ bTD3c‹Ÿï„:QàÍÍÍ¿þõ¯ß~û-<¸‚Bf*$¸*?²ôgÍÇMœ×r—!x{{KýÝ|]“Ê~Å%ƒÕ+ÚKv@aq[©¿Äh•Ún?ëKÿ"ÛÖW4îHT6ÖÊFZ:©”R¥(0|`°›¼òÎBJdÀ‡`Ðø4u‡ÞHøPÂÉçŒEHz+(ÑFÄq 40ñìåååææ&ÐJªÐ©¡Ø›Aâ`u;™éìv¸Më˲*¥Š·9¬ì-4>à ÷ôöö6ÒZ8˜‚”˜œ&§ à ×êäÔfäbÍö¯„¯Žr}ˆD•ÃtãRÅï,1ÒcˆêQÌnS¸iæ.ÎÃÃêltÄ‘ÿY ,׃D"\­Ġ tŠ3´C™;0©"~m67µFJ‚®®®ú1J†&MCaiWïý0Ë Ò3ØŠï°Lœó Æy[ªÙ›ã³ˆwww•ûœ¶­­s¨™’PÑ)ˆèeIþ¥8Eú±V´ûQG‘ôËÔÅRËײx½#Ίiøš±Î+Ë5ï¼§R±ºÓ¿¼§íØ^€=ÉH@÷×××åãK— ”‰£™ ˜b€W•H­F]ƒ]Na ôE9tõ8ÐBDðb‘O/¢Ž6®L •£££ãÞšÖíUì_¬ÄOê¥ÔdWŒÛ9P*³ˆÛŠ´}ˆõíÄýý}ªÈ Üí±õk–„+È€EcÙ×¥ B ‹Õ>Å»¹±ÄB13"±^º!×××ü#×dî!É †°¿xñ¿€Þ-nŠ|~~þõë×jÂ4!™.…L¿'{%­™:3áõv[|e°,b…#zÀêá˺DTBWŒlÛ‚À¯t\h¸ œi§m‚"§ÑÓ×Q&¯FF,”ò·pýS~ߘô•æt*ᬢy¡Û&FØ4ެ5à€á¡~  ¿ãÿÌWBÖ”\¯î]1€Î³>¡ IX‚ß ¯UXèèíâì8® ¨2L„¢=Š] D'Y4ž´·&«$3§¥PmUÑ;vdž}û¶šÆôP–VfT§VsÄNê¥ZÒPÓöükÌÜfy¸ÏfÞJ=f©œ[èÓ ÃëmEQÞ°sh =qÿd²Žr6¸äzù”Ù’Ü"3 J#¶LŒ„ÐnwÚHùrï˜ÍÖ¦õ.n JËä ‹˜õŠíDµ>¼”‹ß7[† \‡¸\¢“q Íä ʵ9ˆåð"vŽ€†[Å…v«oUY8Omñ{/%+9ÖÊÈmû¡é:Vx <ì¢Léóçϧr¯¾Äv½÷Çbƒ¸†EI ©GýÌ6tbV µûm <%¦pµ]¿nrÍêkªµU¥»ú¸ x•WzS®·Í« b;?·9da£&nÔ•ËòÕóY3pV¿¶M¬þf\í(û>•÷ÒØ:K…%«òÒÅPsòc’Š^äüüüêêÊ|M¬márNÂlUdòŠ4b ‚Ãa"îLÝÅÑ·¸}zz…MY|¯züŽÜýÛ¿ýÇ­[hÍÄþ²„T’Á6ãv•gbéZ¨˜/ö‰æ·áÛ×*äBóTÜC”/ìäéàE­weÇÛvð ܵgȨKµƒwfñééz¥X­½©à/濸b{4 fò!bõt}Tè/tÌ ½ý@ԃܕ¬³"“ÄÜmW)Ý ÜN‹(ȱÝí…2èË ‡ {À‡Uß> ­¿{Ý9΋ˆ}ò¼ì™~Üü2…uˆ-´@" ê(ènu&òŒÛ…²¦T/ Âl†šîú戳â-´v”:¹=''Y»Li q„•››H™SÕkʲqp«ñ1¥ÊÜÖØ] ÍôöRZá·³(¿i¿Œí$ûÏ/;%þIuƒaSæïŒCܱ®·›ÿÔ–¨ÃÇA×ø%ë•i´qõL×»€ùè9³­¡ Îб&ñ6rñŽlÏ6–x82`Õø²;[‡’YËwwwG@Ó`Ȭìç» Š‡»[sÆÖÛÖ›/ÚVøuè©….Ñõ¦†gôøN„ó“7+ø3ü ´üOdµ’±1-Ë϶KL‘£Í”%h4‡&øëIpzº,Û‘–ʼnôdìüF„ÅŽÄ2J‘ÍCÔý^@òښأá³<ªÖrB¦Ä> ¾»×××zFL|>==}¯¹«&·ÓÄùëæ3õOAU\l ƒ{*Åq¬LrS$4e¥¤ßÛʽ’ŸšB¸ÍwºÒH;É*ë´’Iw…Èòo@¹eÀ%ØûöM_¦WöÃçä7J ðù¡ÔÁúK·³ ,ÐÉ­ÕÛsqŠØ)PÓÈ´Ù-RNÍ#¯ˆ•å[$8ìW¶µ¡VeÜ.IE&yDv§7úK<¯···Sº*ã|ÿþ½ÄMUÐN›å"›!¨ûšåÛ.[ ùj˜›°ÛøU0+ÈüîP¸ö¾°Òª©¶¯ù ¥M:»h\ *ª®™%M¤{UD]J‹†P*f`xìøš;m<áææf|Ø…L Ú?#ïÌÐRÉSê‰+Vßj•Y ªÝΠ6hˆõYŠÂÁìÂÈŠgÅ,‹Zn`Y¦ýT–ÚqÜù¶h(†ao‘w‹ò}ýÊê3&û­Rw ­ ùS‚Ú¢3ûo…`•Çþ,RÉVí¤Sy Ð6$S<»ã·vrSžD}kõ DAJŸ)ú§7C•Ê€Ì(^ïÚ”Ü[ÑhI%7}¡‡Þýqáµ²èò•×Ã+WÙD}>P^K|[Mõpñ;¿„))‰7ý0ëýìY"£R’Ý[ÅW‚ËÃvÅAT2M*–=bxáêxn!žÔ«„£;}{{»ª-…Y8rëv*š3½æ/¬§VÈ(LÔ_ÅU0Ý×m ¸ø pM¬y0‹^"»qÛÜß—8æè³µf6W¸TîmŸò—;á`”«BƒÆ$±b6^A‹Š'cLíTÀº 3ôÉ•Êß%Ï@å²HÐÌ"Ìǽ²rhëv±êqý0 Âí½”õ—ÊžàåJ>+ºÑNÛR^wwwqqA™Gd| p±Ìk%™BU5³m1µ n¸àlU'ê#\xíì0Íw¼ÙÎÚ^\\¤áSäתE˜uÑc?>>ÆÊÈ(8‚8™ý+¼L Õ0°L•û¿ÌFsà¡!ƒú%)m¯e‹iÃ=ph|lç°¤[8ÖŽîÃyà1¥{Ê›;:¹+N¢ØaÚÖõ¥Qïd›Ýá¨N£&g±â¦Ë'BÑ  Î-"LÁó7ÁÚÞ®€wç)_l–AÉÜJ˦· × GŒ%£öaý±™LÊyú8¾}û¯G¯ìíéé)’u†?®Bgº›"mSýè†moÀ•;¸Ú¬ÆÌ È•ÝÜ܈¯Z± ð–väª)ñˆ%šã ¦3g™›¾5³jÆŸÞJ¹}e1M mÚ…‰èjëéRڪšn˜`œ=C aÖp’º»»kÏâѶ(˜„ZÂ5ôéûKÑŽíï̉ª‘’Ž‹'¹Ìa™ÌÖw7°BWB~EsåÈrÙe2ü™-øí·ßäX0»¡¬i†°5Äñëçuý»ó´Õ{‘à‚¶UB‡ÏUˆ¥=¥×\ûk‚|ëûûûÌAõ>¿u¸Úþ{ÔìêHÆrÖÖ¡×¼»»ë ««×CöúúzòŸÿùŸÊ3!>y¥ÞÙµÞªéÁüùƒVUl:Â8öiÇÊS âHñÅH‰9…ëëkdm5\OÀ­º¶)ëȨß}Ñ’´$ˆmÖÃ’ <öXzäÃ5N­v“¦~,³!I_aÍ-. D/QO¿·VbXÉGù±B‘/c´íÊ_¿~Å…ÌA£·–<ÔACQO%ÊAòçzÍâ@w¯Ù‚t‘ÞÅl2PTèNdèÖ„èR$…)['K]]¨;ڥߦêVÁ¨>Î òŰe bì£ pµ¨6æGª-«cÉXËš»ýÌ$Ȭu v!¦¤™Ìþ™%ÀÊmeúî‰dµùÓct4QHÛòŽE°2ývdh1Nôˆ‘Ô7¶¦·µÓÁkK. ) 2sEA›#Ú}ÃåJ‚G: š ÄãqÿãHL¯®®h—³ ;FËD/ˆÌrp&!¯k‡[T¯ÚÙÌ+ÉTËJ{.Rm$F¡%JixÉ_Þ­¤ çÓÜ&%H‚À‹Dù¦ÖÿÒ`ùs´FÚði¿*&™†š]ÙI]#·°ËÕéT»† è?q‚›@»ÔˆmL ©´ƒX9‹++2ˇ$4ä5»«6P@rФÉl;í ¬0 ²Îl‹Ž´“è†À ßÑàGGGL¡XQO…ŠÏðÛìÜ·oß$˜¾;ܬ‡ÁC”´[ÒôX÷KÖtí°c9K!¿|ùÒÒ,‘bÓvTe=z‹ø²R*vIzl1y½:–ˆ8ˆÐm¦ƒ\ ÞÞ“DéH~þüùõëWoAȤ .ÝT°0Ä‹â»bÁÀÜìµt‹Ö½íe©±ÓE²Ã=v™ñŽÜpLÛ#5ÈÕÅQéÐÊŠšm~/üþûïPL8V„RT×k˜Tâék,Þ»-ßB¹üÂfiË¥ê[/}~~nJ(pвÁ–µºµšvîÙrĶ›§IÁfÇX.gYϱð.ıû©äƒ'°Òø*[]Å!Å?œà– –BIi5àbe( éÕδÅw?),Û±†$×Q7µ0@´°¯˜¡Ù*ÛdE¯ _nš5ÕxH[r'‘ü‚/%U«/·£éºY(y”4Ú ÝáwÒd J—.½ Ç.®ˆÃRú™R~$ì†Ê슖ÉÕtcÇaÉDQ¹P~eB,½ÏiïÃ5})¶~×ÁҜ˚$µÒ!Õq–)"ȶS‚%Œ špoªMrÉ4 %Kœ°þUÔqTé0땸À™Ò5ÝfÛx¼ýX\àQKc0ôž×^†bŒÄâ ié §92!Ïœ‹I-´(fèÂq»£ñŽrw ¡¦ëéÝ|ÿþ=<Á9¨þÒÍ_½™È”Úcàóo"(î«Ï”øwF bÝÉ-«Q^–†cT#A,`UFŽ›kšº7.©Ø’u¿Þ9)B0 ˆ¸`¿hÐòùÅåßá¥j¡kþ¯ DÕÕÕU°(XGPsâ·oß:FȈW ®Cª±HÄ&ñu»…ÂÄ?^^^R¤“\'·¨±¤ÔÚ: ÄeYVÉ“Æ)HƒÚ¦~þü9O’9i«æ-Žf & ®jdG‡•­ÀáøvLUþºŠV#ZO¥„4jÔ)ûé(G3ºu`Ã+kŒÁ@†Š›;…¡R®Îâ>鮼Uj4bV¹âþµOc@OOOO~ÿýw…S“X Õ… [yZA?µG•´žÃ˜íLˆ!ó<ÎÝÝê¿÷ቘA½eBû0dÙ!ÖjÒß>X¢º£VúÝ£Š¢ôx¬ÌrûaòŽNQ¥`íŽ>>ùë_ÿª¨ã M“Å΄'èµý1lgÚÈým)T2—·M|KðÛž`Ù¥@b#*ÝëÎu/ ~Ø~;­êè¨IÌíÝôµµ©Ð2ÇÓÝj¶w˜ô®ˆ8aë¬êÓÙ]½ e›¥‘*ü¯ÅË¢aô»&mmLþ@i]jëÕV¡ÃCªC*¢­•ÅÕ6'ÒÝÒ†Ò vòÿñÖ×Ô8Î6œ´²Õ»]DB¡ÐÉ÷±46*²)V<_ l½Ãvö3=pÏÉø­TVU~Ü.Ñù†òÈ-1®‚ä.Açзeƒ2‹†êmÓ°V HWâùùùØxO#ÿŠf¨v“V3ÐŒBŠ}V6Yd܇±«œµýÇ~é³àXûGÞ€]l30¸Í{Ál’Ž(H®¾ þ›Ð¶Õ¥7ÔωtDŸ¦onÍ3—d«Mu93ŸËòiãqttìì@nÞ™çYþ;ýuåSƒj1Ýz)X_QlÚÝßk»#¹Qꈒœ~k×p高ìäùíâÜ>a½7µ———Sªç[êÅÏ€hªPÃùCïp:onnÄ:i™YﺫMÛéÐ0£»Ûψ®´äÓGQV¯&é.-1tÇü™ÊçìÝ‘qø@¨Öé‘”ráúÀVúÓG‰;퉋wÔ–' :èQ;@¢·˜Æâ9=ÃÖ`…˜Ü# ï õ|õÂU¢ïåÓ[ä[€8WÆ0ijiÑ|:Ïèç2ø¥:m0¹-»ïÚaÄów^a1©a†ºC™¿èÜdÛªÀbr²&-n§1¤äƒÈ4777eÔö$ò¤­b€‚3ŽUeUŠ£YW‡Ð/üy°qÍogËâg(sítwýëšNUÿ·ábo̼_Ç‘]%ÔmÞViýd%4eWô@½ZÖ3Sj7€rB_‘ò—¼Ê°š¨]»ºrä¿:6º¬ÁÒê|ôL·åÿ.öÅóóóÉßÿþ÷âKc|%@ ‰¸ÇÈ‹¸ô[¹*QÒU è ­&‡è ç¹Œs ɦ׊h#«¯S Ýâ°uäF3“‚¹y»Õ'Ûû"T†*Eé18Û_}KKÂʽ˜QßTm²àX +¯äδD———Z-V—@‹Õ^oà†['ECçãPõY5õd(»!­U ‰ÕXEù¤ì ~`íàQê9‡Ð´ÓÓÓ“ÿú¯ÿ¢ŠÇ‹Ñ©çü­T‰Áæ%,z}vr¤Ð©­§Sµ]Q*ؾ ªqVh‡’Ë«s0^̹:ñ¢ÀÕ‰Ø`×õŽTo%X!;l˜}Ç Îêt×1«7K…À~¥-;ÈívðŠ½¹<¼GR7N¤;¹ ²wþ¨Ÿ7/¼@SK\?¦ðž¿e¹°®HL´8ìŽí“û%5Ro®5º¹¹Ù*¤·ÅÞÁ¨§âÑe‰ËÒv’¹iwÕîÕÉ63íÝ2œ©¢WLØ)Æ…×®½‚aNsRûóçÏÛÛÛl¼fµbAÝŽWa¤·ÎT—µTbXðŽœ*o®4`¼ç¬ð¡Dä hÇê@9WqI*?~¬v´ !Ù~«¤ A%ŒåHÔW×ß#û¢äŠ/ÅÙ ÚWWW°y‚ñØ8ÄUËzӢʂ„ÊK;AÜéTdõ?H,=Eµ¤4–÷$`ÈT¬6„Eüòå‹ÕW&¯¤£a.´²ßê¿Uú.äR¹èC¤ÆM}š©|u€“K²FâÖê ô)¬ì[VZï[…׿Q¢¶’U‰29 3]ï$N»óSiX8;kdýÞÎ)–æšÄ¸=ƒŽßN±`¿¢¤ÇèÊ5E¨ÄZòăïôŒ(5#Œ¥% ÙZMðYvÞ×ElUçää÷ßß2/¶×®fð$[²¼4õ…"d„&œÏãHfå^p‰C-(¬…¡÷gggÙÅíÈ0t›,.žÑׯëý’Óˆæ3'®Ó³=’H!~Íoãu…J}D£Å›EDjôÒʃ¡&Ð4±Á;â¸GF! R¢³0N#ýyáNNå“דˆe]ZŸ¿Ò€‹ÿÈV¥(ƒ^NM¥ïä4tøvŽˆºkuHÙ¬"ÍŠ·IT#ÝsJ”ØI¨ÞÑ„4‚ÂŽåÝjþ¶Õ1Qð*µÚ”<7JDˆÜIj^sù(<ùµa+o„iŒë™ï E¡¤”eUm¢WdÆ¡ÉWèxA*0\òëׯ¢ä‰ðœŒ§‚R¡¼­NÅ6É/ÌÁš˜ Õ(õŽ ®DBqMVSñt•ú D‡¢ÝU Îxh4p\Ô”+HnD[ïÿvݰ…Â)­Á:FƒÃnú§,` ¸„BLÉJ¡™ÎåRÝõHÐYÓØ |—©Ê°í‡ÙcEiJ ôw†l0 ê­ 3h£™lů{)½ÁŠÕ</æ&!UvOa Dÿ´ªŸ j@À݆6‹&J;¨ŽH”¸1ò†÷^°Û+~u*ÊÑíòURZ•!7xuËÄO^À9Žƒžbð» µ£LÚDÚ.2ÙÑ’rð å`ÌÔÜטP"¼² 46ÌnØ…‰7Ù¡z€·‡h°mßa=;FÔ„OÅ|Z‰(4öFI°35LöÕ¹ÈâmIBE`‡éÔÍB·/FŽeŒÅxf•mߥUZÅVØâ2¾qG[“ü†æ,-QžÁ0¥Óê%"¡å1-Gs5m6µ²LKÕi}U0žhžå˜™Ý!;ÈšMËŃL³÷K©A+CÂ[­•y,–6/åošjkW¨*îãíæéŽªÚb|)i;V¿¬P’Z^ÇŽ¶ƒüô¯ñWBl"²x5‹ø•HúŠ¿¶Õä—•«E(K KÞ®©¸ƒL§¬ !–àîë+Lv½¶çÖö©Ül' &.AExÛŸg#JÓw¡†°XúVh·']YBq rKt.ƒ±±ô•y…kÁÐéÂkÌül|ÍÆly9\_±­ž–®•é– öí87Ëkaã¤ï´* öÃPAÎ5SðC0]xµ—Ê|ÊßUqÑ<`‚êPgþ]‚å€Ú÷=÷ÒtÕV#Q¹ç`>6­F¨­ÀV›t© &V¾Uv€àmÿÃÃC¯ ‡ëVÀ&¤ÐÙ¤íþüùsoß¿¿¾¾$TÌ$NQã2<ê±ÄüÀ 8ÔRoœo½u¨œ=*hVr¶½ ŠÃš‚CÓ`ÀRãU†4.~•DPˆy||T!/ãé•o©›éKY“¡ˆ­ °B¶X5tWQ ÐkZ® “ {ÇӑꮽgëyfŠ1NNNŽkQÏ`$~›D²ué+® «³‡Q3ˆˆ6èÛX²eÃíZÙÚØÁ  ¸¥¾.Ø²à˜øÅ;ùíâââîî]#bg¢÷v o·=bÄáNÓ4F9¯Þ‚ŸŸ|xx¸¾¾‡6qPJ‰Ý¶S«Î[À¾ˆYÍÌG'(ä£ÉÐ 3Ÿth³á+›Ì‘B`Z/iõåèéh“×ã¬ýüùóêê ¨Ü“ ‹ªÁØ—F Ú£c9;ai¦uQGXqÌmú¼!Ì—cO®’£ë%IÒ-ƒQ¥ÐJ¢‘å0ÁU¨^ÈK¥yà`ª›9£RŸ®bÜðµÑvú]i 'T’÷ˆ]¸âÔÌ Â Eö-Ÿj¦ß¤Äߨ‚fÈI­ï¼âª}d Št–]â–gñ˜w¶‘œãE/..*vÉéïª_®Ö»¸¤XA¼ÎêµPÛ›) ::::΃1h›ãí*ÎKÒã#bÍ$Xâ¸îÐîSI’OëAQ /l!MN°™{Ý.†ä—Rl묗W Z3mß#2Õx·B.ã}Ảíµ×âW&·x~·®ëÑöR8 .˜U_ËBœ-?àì-u»í–{N|ÀŒV€  Ô=¡ p=P´ÄiæÉ«iÑ8â"2uDÙEJD0±~{°•Oµ#&¡Œû“›RFLm™ó!öÝQþ5ѳúkD‡›°:;|^Wƒz7|ä ›ª7Ìˬ%È/‹ZeŠö[æÛ¿¢YѦtúë<^ù7… ’ÊHeèº]n9 ž÷ºÍz4ÔEGdÚfjÈë¶RF˜2_’R>5šâœV¦ÿ»Lß·ùÏÕŠ(ȉwÉÄ’{˜¹ÒúÇÍ¥%¸Ô$Rô…›+f/Wyí ȆÝîx£ÒøA®ï Ös‡¡Rè@\ÒRšGÛ!(9cÞf’_Ü)ž†ç#Ð"Ûb¥à÷ƒ!”b,M8‚3ݪÈYú •à[J`ªpLPç@Iýè訰›®:ÅêÔÚ§eb¬>pëVô^½#y·HÖ[´s(vLZ+Ù2N;P©O+Ö$Ý`’B%+ÐýÎÙë'køfï+A9$áoaz®xSjU$À_éÊËËKµtß+‘püŽ?ê[1‘êèèèR S²Ùp¬ø;EK0*­ O¼‚ÿåCñ›%«Ãs©ÄjƒÖ©{ú¥ê™ÙdxpÝŽî¾±XÁ1FPD–=ûã?Å\ÎØ„vA!ÌÈq£^È;›‘Ômy·Ô'ÚFV–Ôó+“w&º3Á‘|¦4h YíWUh†Ð8¤‰ÒèPXŽú³ffba6«?Äcnã bW—½°>hù:ËékKJ¢lXT' ì^__K¤:¾…öåLEî Æ8%`>Í‘cN¸œÎ2²;IkYIc¼½½5ì=«¦†Y¼O ¸¦Ò(÷™Ö ü‹:Û.»ííÊ)ò¼¨i‡·%&—ïÔøÃíííõõµæ§æVfçI)Awì(ì ¥„/G"SGœÞä°æ¸#ʨº/ÑŒ±`†·cbUs¶]VHÉá???‡QÃö­‘ 52÷oë äžþW¨J™?àcCæ%hÿWêeåáäš(D< .Q¹Y„-5.ynÓ\1˜X^+æêÜ€#Z jbúÎÁR0€2pð,.”€S]]E¦^' ü~8»ætæènØG¤íÀÁ—Èã¦!²¸œÐ6ºU˜ð¾=[ŠIŸ>} ÆÖ·½ã þÌœ†šû1æ_õñååå½8»ÈÌOŒ,þ½uÛx± ÚÚ9²Îr X•šŒŽSj÷ìPƒr¦ Fþhé8¨œX)þçF0Ô· Ë4‚"õñ¶ß1c‰Hð*ÔãuWd³¬cGT Ê(í«—N´’Œd 0¤çRrê¾`œ›6òÝÈ_Ó"Àp|ÂʘîðèöœÐ6ç¾_]„Ö*-»ƒä(ây‘ÏÉajIx}}=])FJ Äf {7søV®'³OÂ-.Ÿ˜Ýù¥Q°$n¼FýÂÚ¶²5^ÊÃ+Ù·4EM¹«8ÒƒUVcL›(ÃV°T0'ø!üAw¶ÐœžræÓèTÊV@ÓÒ"Äž ð`Vcù ¿©’™ºx0þw§p!û ²VF!ly‰¢m£~äè}@Äz£Ü7RÞŽ—mBîÕ]ìXB Þ!ùßÿñ[¾‹À! ²+$‹ÅCJ-{\±­áüc #=h{‘—‡ªL…÷} Ñ·-ý=hÒ˜Dêjra ®îrøÅmJšr‚uÔ¨-q .z{ÈI•8f#û-wƒæR:˜jã;† Iw1/ÝŽ$,z•r 9îLÐ ´g‘cBË7S .ô«³¾—l³7ÒCŽAð±M,zÛkR£r¼¥ôd±QÈ¢ârz¥;Ô¨’`†=p|IJÛàƒ~ùM†8DŸFn«Âg#‹} Ì…ÃöÚìjd3s¥eYôYýgù+ÖbT†>[xŸ,hµ2ÔÌgp2oƒ9Ù÷æÜ¨Þš¤ÇG©‰0r+\®Éª¶'`è†WŸkOsÑO£ ¸e}JŠ€²±Êi¬@ShÜþ¯Ø„Þ[¾_2N2wu3+¨ ¢Õ¿¤Fp-‰ëa®tºQþ\VÀ“)SYÀcz Í0"Ã$rÝn +X°ß…à1;|Íq,6GÑ‹œ )‚¬FPÞ–Iûöí[ÍÔÕ ”I 36Tèf÷“Uvj€’w¯œÓ ­¥$c+…Ýt|+Ó]¤ÙŠ£µ(êÕæeT‹ÿ cÊ„ú݃ F×fŠVE“îÝÝÝ·oßVuÐJ’(e†Â_¹4 ì Ô<þÚ÷¯Y²ß9RÝÚ–\€M„ÆÝ›ÃÍF´òê½Ç!–®«Ï†Ÿ²R„.ýÆþ€Z°ÊWF)âÅx´o«‚%Z‰­ñ.•¾´‰Õª°¾Ë2§˜ ‰ìPp¬A9;çQAZ¼Ê +MuPÀGg^ @ºQ¢öUÜ'÷âF-»ˆ‹Ç¡Vë‘B´§=äâÜÚ¹º6&2üy$ñ–ÓÍãE°¢8hU“½. `>»LY/€ )Abeß…ÉèYÂü6Zdɧ‡oP|Œû±Gg!ýßnŽó*HgM) à©b#Âv=èœiK²Déþü_žz˺,¹-€ÐôÏÿ!¯åÓ<áh=Éu¼Ý6~®RS¿Õïôq´Ñö:·#ìÕ0¹¶•c»6ô•púÛN²…þý›ÿþƒŽÉÛ øÿy^•ß;ÿßGž ºb÷&IEND®B`‚kimchi-1.5.0/ui/images/theme-default/check-green.png000066400000000000000000000066551254252253000222640ustar00rootroot00000000000000‰PNG  IHDRbKv3 pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-Û cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFØIDATxÚ¬”KH”Q†Ÿïügþ9sѰéâH‘9$ÒDbdEdDV˜vˆèÑ¢$"¨¨E›Š w T´Ð ZD ƒ.Hº-¢"é&v§B©$ÇñŸ9mþ ‰¢´¾ÍYÎÃ÷¾ß÷±Öò¿KþḀ2@ð+À ànjr6›0ë•ÒMkRÇ€¯zˆ@åÍŒ:3³NÔš¥…e—ß| L:ô.`–4¨Ò‰årÜÑ$‹ÇNko¨i¿æ[Фõ¡å»TEQ©œtÆYübÓ‚¶+ÀkàðFD<=É¡•{TeQBZDËt¯{®Õu"/v KDÒø“ËMÀYÿ<”Pý55žf¥‰™°öêgn›7¥Óï°SDúw¡S±HF!_¦ò0µ[Ô¤ñerÊÑŒrC¬Òu×§­ìîO¾ÁÒ °b·*OV©³•µjNA\n?¿gûrÀi52ª¼Zv”¸F(Ž—?[5ý|+ðÈï²[DìÏ~y±¸Äu€¤‰PŸ¬’‹ë9Õ€ çcf/SGt€ÉnPȑ׻¬¢¹èò»ü$"Ùß%JmovvšˆìèÇûÚm`É FØêÁDaÁä½ççï¾ \ŠHê—é°ÖºU+¯z­º¤]ægÒÐßi‹R  §w¬«¼ÕâK¾ ôü,{°ü€g²ÙÞ6BQE"ÑÈ·ºä‰ À+à1ðùw@å_zÖZ·qµ×•ê¥@»`" Cåøm±pÙ+à!ðND2Zl|³³ÖZgßRïL:Å)åÀÈhÉëy‰ýw€g@'Ðÿ7iÉUÆ\öóG¶ÙLà“µPh¼¬D¿:þ$;W?b*"ÖZëYk5ð¥ånýQ ¤NŠÕ>žoEÄÖ'íC£@ ¾|/íp¡¹x†ãoG¯ˆ üíù} 'Ü„5«IEND®B`‚kimchi-1.5.0/ui/images/theme-default/check-grey.png000066400000000000000000000067171254252253000221310ustar00rootroot00000000000000‰PNG  IHDRbKv3 pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-Û cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFúIDATxÚ¬”OlTUƧ÷¾?÷Í{dZœiªf`š2©Ô4&¤¡FÛF4ne£a`a¤0,ܰÁ×&ÆFJ¢.Ä`M j¤%ºhÄС© 3©8ef.›WRT[=›·¸y¿û}ß9犵–ÿ»ä?ü§Ð@Xꀕ5ÀÜ7y1‚ç•RoíÙ»÷]àO½J`K ôG†‡yC;Îh[*ubttô2ð00­W tO¹œïééyO)Uèèè8µcçΓqWE½J 9°ÿ£¹\î}¥Ôƒ©TêÂ3Û¶}\~~‘º^…es°RylC6û¡Rª­5Š®<=44¡µþ8ÌŠÈ"qç–: `fü]Þ3¶oß#²Ù´RmƘz©TšH&“3±Â©-W¡pëÖu€‰m¶Ä@ øåÝ»7mÊçj¥Ú}ß§P(L>´~ý40œn,·¦§R©l)ö÷2<4TJ§ÓßMMMݸ}Ùà`ûÀÀÀGÚq²¾çÑÙÙyþ‰Riø9VyEDìÝyÕ3™L‡ã8… ž}¼Xüò•ÇŸüÖ(òwlßþ¶ã8›}Ï#™L^ï/'€ÙXeUDš÷Û¨–ñññ—c^¨Õjõ«ss¯Q`̘çy$ z{{?Ëwu} œN‹Èß÷쬵ֵÖêÏÝqœ¯ƒ C½®½ýPk¹ž‡1†t&3ïêú˜.µ•Æå&À§ÇŽ5çæç_þXR†!‰ ‘HüÕ××÷p8ÌßãÐø°n­uËåòìÂÂÂK®ëÆr7~†áEà4ð›ˆ4þi°‰ÃnZkÕs»v}\«ÕŽ(¥ˆ¢èRww÷÷Ày`f%Ûw@ãjÄkV«ÕF£j­es¡pBD~³\ÑöRÝ^S±ÖÚºµV×&''ßÑJ=•N§ÏgË"R_Ó#CC ä€kÀOq–v­Ð¥õ4€OÇu¹ùoßÈ[€ÔÝSö)¥¬IEND®B`‚kimchi-1.5.0/ui/images/theme-default/folder-arrow-down.png000066400000000000000000000056141254252253000234530ustar00rootroot00000000000000‰PNG  IHDR éz¦j pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-Û cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅF·IDATxÚ”Ð1 Â` †á7õ×b í 袞 ×¼ƒ÷tprì):‰ ü¥µŸK+Uì`–,ß“˜$þ-`f;` ,r'`‹IÂÌ6yžÂ0Ä97¸!˲¨;4fEQœ“$ù Ó4]àæ$ÕÀpeYÖqÃuÛ+ ¡{„¤@ÒHÒÈ{¯ªªÔÖJÒ\R$)èÂïq=8õÞÿ@wÓÆ@pîfÖ ¢ Zôì€×“îsÔõ'kùIEND®B`‚kimchi-1.5.0/ui/images/theme-default/folder-arrow-right.png000066400000000000000000000056161254252253000236230ustar00rootroot00000000000000‰PNG  IHDR {D pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-Û cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅF¹IDATxÚ„Ñ1JÇ0à/%X\¡›‚àà ô<^ÊÑxOÐYtqè :8ˆ´â¿qi4ô?ïñ~Ö@}ð–‡E“xW­V©Ïi4šu1Ú˜|mŒ¶(ZýJ­º¶oX´¸üÄÚõﻈp#@2ÅjuÖ‚W¡TT‚Ýk EEE±HU$S©TÒ3D¡ŒT~9-ºnöœÙ«&§L–Xïóù† Óûâ’7~ðy}/†¼³€Õ“B‚˜ØM{IBq®T(%c ‡§Ìø~ê´‚[áP ï×­_{ëÕ’A£"@DI±¤¬À‡…Q¨ý%6ù`Pú¼ìœìª)ÖŒaó̯šÙÎ];:Ð/϶ådIʃƒkeRü¤üöööA…a!“—Ÿ÷ºÉdÚ¿}çö·Z[[‹ †xgéé,>>þ ¦­ÊÍÎëyX{‹Çí©5 záö­Ûl´BE\IMµÈ³­9í@£¤îÆÕƒÁPˆWrÈE{Vî=À.hµÚSð\æñzövwwëñ®bA°¡ˆ°Â™…×B*X@TV6¿ì¾ÉGª]bKÏüÇ–‘yrÏ÷àm>¶ñ,ôÌ¥L©ŠT1¤ì-öÌÜÝaIH Ï(œñMÙ¼2é9\XéV¿·º0_0½bÚ ?F("úu=ˆzÜh²ËP:KÊ”HÛ¨dCmj¥!IHJ³¬ÙŽwV®ø:--5¤rš3Î_0o}N¦]Yùi¥Ï0ÁÀ¢££‰x©Èvˆ1*:JBih¢hèbuÕÒ6ê úçÂãuØÏ-õŽŸáï/?=VT{±–5Þk”˜O1]¾h!‘ï+0»m¯½tñ`ß *·nSÃ[O[[›Hd–2_ˆF€ ¬££c&§×ë‡V·d,ð+>5ƒ0›0ôùõ×6 _ ¡ƒ.ˆÙ¤¼p&Ópðø®æôÉê‡ÖìÙ½7âÑ£G²pÊ çÔqqqqR\ ¼…½9‡ø×d4¡··÷8¬ÝÅÎÂ(éd…Ftoƒ\˜M‚€ „;s䨑OÛÚlüpSâhÅ”BU§Ó9%à¹Yí&Œ¡ÌEÖÓWŸ‹¹Ü.é9’RuC‚¢yÔÓ"$Œ¥y?_©»¼³jOÕ¥“'j¸‘P mDÁÍÓ$]Œî ¹L(­$C ä"‰TÀäþL80WJÙ¼PŽK^¶|ÙABf¤âD­«³KÆÃ{†SÍZ×Y‘"eé?å KѺ¯ÕiwÆM³ŠfyG cZ«`j'&¼ÛÛ×+`K##à• ¸í“Ê3§Nž*¡ø§f6›YbRKHLd,+;³ΜÁÄ¥---éÊI'd–üZòÊ9sçìKKO+™8i"C*¦×7!Ž~ùrâa±%ý¸\°–,B6gÀ H.†œÖ4Ûã@š§þÖ]Ç`büêñð~¨]]]‰é– îu¡JðsÕñ+Œ÷õ ¨ª$NùGç¿uÛG=¥e¥LJHcl(Ålaù¶¹bs׋Þ7¸ÇO[— /‡77;÷›šXcãßìÓÉœÎi³ù~³ÄòäÉÉ„¥º@wË$sXžD'^ÕX’SJgÀí¯¦»ƒ >»NñsÜi°`,b…Xú…š²Ü ¹>d-z¾`7ö½ uáÙyÁï »÷Ïð²¯çÿ 0˜ÁŠ.%¾­øIEND®B`‚kimchi-1.5.0/ui/images/theme-default/host-icon-sprite.png000066400000000000000000000020121254252253000232770ustar00rootroot00000000000000‰PNG  IHDRnVèi,bKGDÿÿÿ ½§“ pHYs  šœtIMEÝ ¸ïMiTXtCommentCreated with GIMPd.enIDAThÞíY¿OAþör„êKT,¬±»Ø@A!ÄÄÂÄȉ6ÚQðhLCBk¢•†‚D[… [ÑèSÊ#F‚ñ³’ÍÜÞîÎÞþ@Ž—lr3óvÞ·óî›yohŽBGé0G¤Or×<>ÉZZÛt'H¶@l‘œHj9 I¤‡¬uã8’U’+ê+QX×"9 €QÉY’­²Gr‹ä'’JòL&ÿÞ ·’–¥)Ç8§œÇ2G²äwËÔù0ÝJÐÀÕ4t{F<Ï;ðËê~ëä¸xÏj?pÑëOäDN¤ð[U%ˆˆÓÁ~ø^R ›_UkævdÒt½ðLD6ÓØî`cÀ:€¸|À”ˆ¼KbÓu½\EU=c'ô[«6°¼[UË!w–3fTu@##,ëæ}ߥT¯×çî©2™¤ª[†Ìí2€Ÿ‰î*U•®lJ!Ë1Í m Ä9 ŒÎ@ÉNëpÀ%güPU·ê@^4ÛcÃA·gDDWªIϲ ·Ð°êÀ‚ùý9D·^Ò¿Ÿ.ã‡ë“ÁÙ? `;ÐUÕ¦ˆ,&b\Ž œ´Ú "²#";h/í,õZ´("¼´ºªjïUêõzluÀèü7Õ/)‹lJ§ÝTÕ7ÑcØVy]D½Šyï¯«Í Ö´é@ß×ušdæixju‹ÈF"ÇELœöÃj1L‘NyLZ¼ÝæcEçqÆæ6€Ñ@×W¹¹UŠˆ—8“\GVTu¸Sò…©ˆÅ,XÚªª:Uôñw#òµÓnxå ¤ H‘@彪¾0à†ˆ¬µ¥E‘?n«êRš+/ÛyÇiA¹ à xÖÀ?L:ñá`õIEND®B`‚kimchi-1.5.0/ui/images/theme-default/icon-alert.png000066400000000000000000000067311254252253000221410ustar00rootroot00000000000000‰PNG  IHDR"_ªù½ pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-Û cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFIDATxÚ¬–MOW†Ÿ{çRÏðaPB@]tÝnQÔe—•ÊÂBY¥â/tÇ’ÿ€”UvÙd….P»îŠ,TT""Õ(6vœzH°ù°™ë“E/•ãÎxÜ–+Y–ì™gÞsÞ÷Ü;JD¸Í¥¹åuë@ÓÿƒRê>ððEƽ/€Ÿç@S\ïLÂ…wÖÖÖ¾ŸŸ¿›üæøø¸³°°ð««Ô¦ß6W¾ïß5Æ uzWæææv€Ï€p°Ñl6Ëù|ž|>1&855Uvê$µ‡@ëðð04Æ066F.—K㽺À%r¹½½½}Ç1Ýn7Uˆì¸2#¥” FÀU½^?ʶ0ÎÊáp†á;k-i“$"Ï\É6 x œ”J¥£Aek­€ëav€ãZ­FQ”|éy^ÓU“©0Î666^¥E¤êÊ”RÝaf9ªT*ív»Ý¶Ö&÷0vsˆ€N†ïSÖ’ ¼ÎËår5Éi­õŽ{è¿RxQ¯×Oœ>í1dhàpÖjµÚ Æì¸Ù½î7$«äÖîîn¥_¡3$NR7hÎÞÞÞ?¦¥ÛíVþ à²Z­6:ÎE_tþLs8 xì[kÿè-Ùí,â ÙgŠ[ €÷ZëGJ©/µÖ?Vk}œ§)TýSJyÀ4p˜>*À;  ¼êÀ…ƒŠ3ëo×>úy`xZ,___?=88R©$›››o–——¹‡å{[vs’ÂÏÅbñû•••¯FFFð}Ïó°ÖE[[[‹«««¿¸­î#…©“²¸¸øi.—crr’B¡Àôô4³³³ÌḬ̀´´ôPDFDÄ cÊ9°Ambbb¶P(0::ŠçyÔZ|ßf\/£¬ØœÏEäqA€1¥J)Œ1Œÿ䆊{¥hOÂ0<‘€¯Ýß¿)¥6Œ1ûîÁWÃÄñ˜ î;èiÉ[71›#ô†“th—ÁuaÝ™Óv»ôÆ&øׇúÄ«æ2×¢¿IEND®B`‚kimchi-1.5.0/ui/images/theme-default/icon-back.png000066400000000000000000000003641254252253000217260ustar00rootroot00000000000000‰PNG  IHDR szzô»IDATXGíÕ[ € P]Z+É¥µ”––‚EÖÜyI`ÐW÷8jÅ0øŠƒóÃH;°å%L’e”JøšoÉìâ^&ïhÃÝ÷pWÀS¸ Ž€%ìmei…—\ ´Ã!€E8`þ@‘Zu:`Ñ  `4lÀ‚ò9ïþ3Ðâ¡¿ã:‹;Ä¥ÜâÁã„HŠ+B2†P7fêî0‘ž0þç+0¼$!z3j-IEND®B`‚kimchi-1.5.0/ui/images/theme-default/icon-camera.png000066400000000000000000000113741254252253000222610ustar00rootroot00000000000000‰PNG  IHDR- †„ñD pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-Û cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅF'IDATxÚÔX]lÇþΙ™»w¯MÁ?Ø`ÀüØn±Œ‘E„L -RQE¥jPE£$*Ú*F*’ÅUÛ'xhUÊC¥åZ¥B}i¥HmúPB…¦‘jŸ"hC±ñÅ×û3;Ó‡Ì^]À€‘QÚiv÷ì9ßœ9ós–œsø DtïsÀ”×qŒ¿¬¿šthózÀ€Û^g€Ïy]`À ÓþÞG@ÙÛÈÔÌH½ÍûAÏ! °@ä?¼í¯Ô ,B¬ÕZÿ”ˆý·×œs¿0ãœëdæoèòï>0Æ|+I’; iЩ”$¢2€”ˆÆ³,{ËZ;å}¹¹@“F@û«Y)5 ¥ü&‘sîJ–e¿2ÆL‹"¢Ž žgæA)%˜Ì+üú~`ŒéLÓtoµZý-€¸°ì˜¹[kÍQAk}—FQJÍŸO¥ÌÃ0L„Ö9g­µDZʲ¬4_;Î9XkQ©T–X àzÚ !Ðå…ˆÖÚ¬_¿~|Ó¦MÿÞ¸qã¿Z[['ÌNLLØsçÎEgΜéºtéÒ’$i}”­"âJ)öô«dÃ˼ ­…ÈÒ¥K«{öì¹¼oß¾¿øÀÛ.xêêØ¶m[×ÈÈHùøñã«OŸ>ýÌÔÔÔ—æc×ã"T€N˜Y< :Î[–/_>uôèÑw‡‡‡ßð2…ÚÃ0ü"NÓôbžçïøÄ97044ô§Ã‡Žãø¹GùõÞ @ ï¨‘ñ§×5GеV¶´´ÌŒŒŒ¼7<<ü"zÀ@¥RyÀV+È0 oZkϦiúK"ºèœ wïÞ}ääÉ“]išûÜŸ+¯9òµ„ Ð2˲çyn{{{+årYYkßzP§”ÝÝÝíííý½½½¼}ûöwˆè6U*•CvQ“¢ ²5ÖÚ§„Ciš"¢÷s³§NúNKKËÖ+V(f¦Â·?ÌÜÞÞÞÖÙÙ)\0S—þæææ—ššš:K¥RBDn§šˆÈ‘jkk»rìØ±×¶lÙò;"ZEÑ!"ú®”’´Öuþ%"äyŽ,ËÇñëµZíù$I&˜yqGGÇÂ0ü:ÍÌ•ÒDtùÂ… ‡ÔŠH "ê7Æt¤iúØy$ÉdOOÏÇD$ƒ ø<=£”¢r¹\/"ÅwÎ!Ïs(¥v0óÎ$I^uÎñÌÌ ô=ˆ¹˜y™ïM¡‘H„õ¢òâ6lØp­­­”„CBˆ¦0 Q.—¡”ºÏ^QH´Ö/Œ¿AD·²,û‡µ6af=ƒi­€öÆâ"BÐZ?hfΛššnúþDÔ¡”RUu.îB Ãeq¯0n­!¢I¥Tç\ÑÖZ“oìø.Б?h"¢‰‰‰¢iO˜¹*¥´RJ~çÊå²RJµú¶¸d­-5pò\<ýiõ^èèãœW¯^mó g¼%„0ó)R}}}Ÿ!J~jYîœ[l­Å£FÀƒ€ÉÉÉÞ#GŽçgYöºsîƒG9ÖZ§8à2µ2sï|‹Ûm­Ýxâĉ D”ApÃó"ýóaÀ÷îÝûþæÍ›Ïјb 3o+RóQÀŸhf^¤”úAE«ªÕª¸qãÆG»ví]¶lÙYf6ºÝÝÝ·GGGÏòI€öÎŽ(ŠFã8þÝtÎËÏŸ?ÿÔØØX?5÷õõ%ƒƒƒ7º»»ß$¢—l*—Ë;™ùÛE¯þ™‚–RŠ0 _hnn¦§§_"¢›^sÎГçù"!Ä€7ˆhm-—Ë_%¢J)C­õg º $­µŠ¢h/€õqÿ&MÓ÷„Óιë®QÄÌ;Ã0\)„ø€§…2 C„a8ï>¾>¹ÐBzÒ†+ C°™™7K)/æyþ7·ˆ(P!¢>›ˆˆ¥”(•J¬œs¹iì§ã{ˆ, ·ë/I’uY–­+á{&Ap_oòÛÒ÷õ~ú–sîm«žP~×'lc Œ1(Š3C¥T]o>›ÜÒÒ2  À‡詟Çq¼¶Z­-0Sê‘.°bzoÌÿùðq!]]]Óû÷ïÿÈ—û„¼±&ËlÐïÿá)ü÷…~l~ à¯Þ)@ùÒæÛ¿È¯êAr³n\ÿ3t6't‘ìÒIEND®B`‚kimchi-1.5.0/ui/images/theme-default/icon-design.png000066400000000000000000000107221254252253000222760ustar00rootroot00000000000000‰PNG  IHDR$cîí› pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-Û cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFýIDATxÚ¤V[lUYþþuÙ×smÏÉÑ`:Ð!¦%BI¸¤/MÔ˜ bJŒ˜ƒ—5QÀ"ɤÆ⃑@@C` B„¶´4TRJ L¶ç´§ç¶ö^ˇ٧9&º’•ìý¯ýëÿ¿ï[‹ðòÁĈh9%XÆAD PÆ˜ÇÆ˜I5>eˆh9ÀÐÆ˜@@sþ8“É1Î9¦§§±°°°˜T¼“H$¾Ï9ÿ<€€$y,F)5´bÅŠ¯Y–51<›ÍÖ&''ƒíÛ·³‘‘ª) ºj^ª  €cªa.þc( ß¾7??ÿw†ˆ,˲Z\×ýn¹\þT½š‹;å|ááǪ££ƒ§£¼•(ªlŒˆ–»®û)åfOËåò©Z­vÏ£_ÔG"Êe2™ßzž7T­VÇ#‹ø,ç|e] ±( µuëÖUfffVÄb±/ !Þ2Æü«T*ýI)5æû>DäÂó¼í®ëþ”ˆšc°m{[©T:Ì{ÃCϰÝD1~,Û,¥D† "X–×uÁ9fa® Ãð‹MMM_ðUἰâõ0 000ð4›Í‚ˆhc,•J¥~'¥|ËqX–­5*•Ê\†Òu]7Cˆç]"(¥ µF”Bˆg*Zk½°°P(‹i°mBLMMáÌ™3_Ù´iÓßê-âBˆ7=σïûRBk ˲J)!ÀØ‹YPçØR Š–R¦}߇–esŽR©!D²#”¥”sŽã|¢NDÎ9lÛ^”ùË5òäUßcð}Œ±ÅøÈDëìçÌó4 Ã÷óùü©Æ¾Gœ¸iÛöcÌàÿœóB*•zÇSnh#cOcycW¯^­ >ü«ÙÙÙSJ©@)UK§Óçz{{{šššÞVJ…²o$w†aÕ j/Š©Çù¾ÿï#GŽjkkûq­VWJA)5ÙÝÝý‹¶¶¶[u¤º‚”Rltt4700°Ö÷}{ÇŽcÝÝÝÿÚ•H$Þ¶m›7¶Mkd2y­½½ýÏ«W¯{ðà¿råÊÆéééoQj) x<~éÂ… ÝAÔnݺµ¢¯¯ïµŽŽŽé 6ŒqÎg,0Ô°+¡ED@uíÚµüþýûßËd2?÷}ŸÕU†!,ËLjE!A´>\z–i•ÌmÛ¶Mݾ}Û‘RÆ´ÖK=¹\î¯ÍÍÍ7ÌŒŽŽÎ\ºt©¸yóæâãǯ*¥þ³´}J©d¿Q•ˆæÌGN¾ð,›˜˜À7ÉdðäÉ€ѲèhYRJŒ%ÏŸ?¿ËåÔ®]»(ŸÏKž1¦¥T*%c±Ø¢o‚ ð¯]»æíܹó#²hff===8}úô3-dŒ­bŒÑÒ£À³{ÿþýÿظqã_”R`I)W»®ûZ­öÉ¥U5ÆÄÇÇÇ? `¯¸ÁÔ[È‚ øŒÖÓcLs*•úÉñãÇW=zÔpιã8[c_®“_k0 ¡”B¥R‰‹Åöè6I¯¬ÐúõëqâÄ 8ް,+8wî\áúõë¿B|ÎÓAS†n䦵µõ}ÇqÜ={ö°žžž¢Rê=Û¶‡¤”i"ÒDT“R‰ÄT6›Ø²eË{ÑZj¸âìsTÙó¼¹t:]B”Tÿ@ˆvBu>5¼SC[u$]4Äð†gÝp3‘¢^šô¿ÏXõêðxIEND®B`‚kimchi-1.5.0/ui/images/theme-default/icon-detail.png000066400000000000000000000060071254252253000222700ustar00rootroot00000000000000‰PNG  IHDRoï, pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-Û cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅF2IDATxÚìÖ?NÃ0€ñï½$vP›¶\‚•!8Rކ:—™ã .ªøRüX슸â%C¤|z¶RÄ̸ä*Ddl€+@3~?=ð|Ç2¾hœs÷ªÚa¨`f»q÷€¥`YE'"[UED²Íl†á¨RðWDnœsTU…ªæÞkà+'U}vÎÝyï³OX×õ PC ö"rTUα¥Î¹ð§[ |4Mó཯‹E©ªYŠWÛ¶O€AÌ 3«€k`™†“Èì8‡\K JçœÑáw48þg±òÞwªÚá Ca×÷ý˜NUµ‘­ˆd¿4ª:˜Ùìpv8;œÎs:Œšèp™Ña²8¯À[ jŒúøÌ¹§˜¢ÃI.ýçý7ЍœýùbÁjIEND®B`‚kimchi-1.5.0/ui/images/theme-default/icon-event.png000066400000000000000000000073171254252253000221540ustar00rootroot00000000000000‰PNG  IHDR"®¡¢0 pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-Û cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFúIDATxÚ¼–AOÜFÅcÏxÖ^¯ñ®C–´eY!h‘ ”V‘*›hS•vÕcÄ­‡~>¹ä’{Où•zè ©ç¤ªP£ŠCn¥¥Š©(MDB ]¼ÓCgÑ&Ú˜% ü¥‘,{ì7~ÿ÷ÞŒ0Æð¦Êá –l_!Ž›W>>¶Ÿ€»À# Ízùˆ=c =PY¾‚à‡›7on­®®î­¬¬| ôÂN£WC`xfffhvv¶Üßßï/..ί­­=2Æ@œˆÆŒ¬¿V«Å¹\ŽR©„Öz¸ÙlŽÀÁY Ä ŽãÆÆÆúÂ0¤T*‘$‰ö}ÿcÀ5Æ8g¦sÅb1)—Ëïûh­QJáyÞ"àÚ!Î,Þ®V«…BAk­q]!J©‰ýý}Ù«…z™”òW®\‰”RB)…ëºÿ7\ÊáÝÝÝ)@æ´`h¸®»1??ï{ž‡RêÈ“RJWJù%P4ƨӪÑÛ—.]Z+—ËßEQt×ó¼À.ÒB­õ3 o¿ÕÌ\yÛЯJ«4 œ³&ÎwˆÁÿ[ÀC!D#+A²À„)ZŸ¥À®]½±Ï…½ß°#íÖ»6F.0|\{¯³À&pÇæä?ÀáëôÌÞ;þüçׯ_ŸQJu“Rjf{{ûååå_Ž dyŒ¿*“““¦¦¦Ïópœîâm4ïÝ»÷x||\ !_e™!ùxúôés+´ÃnY¾¹qãÆ\µZ GFFÂ(ŠÃ)e¯`°±±qçêÕ«_Û­gßÓzùÏ.sssžç†!I’EQ¦Çº9ŽSëØ¢šm±t‚5oß¾=§µ¦T*Ç1ù|ÏóNBãÑaèþýû¿W*•¸óÔÕ©²ï¥” ’$¡¯¯ïÄ@Žãq¼o-ô¢@Œ1cÀõÙk—¢¨­ÂV75¦Àc˱äôÕžÙñ¢ßDý7´™†»WãIEND®B`‚kimchi-1.5.0/ui/images/theme-default/icon-iso.png000066400000000000000000000101341254252253000216140ustar00rootroot00000000000000‰PNG  IHDR((Œþ¸m pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-Û cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅF‡IDATxÚì˜]L“gÇ-Ö"È—aˆ|HÈŒu‰Ñ5“x3F³iÜGâÅ–¨L—ìfK¬w»ÑÍ ½kÆÍ2Pôb[¦‘éäb‹c%‘ T•-V[,RmiKá-íûì‚¶Z¤Pˆ–y’^ô}Ïû<ÿsÎó?BÁB% \ÍÙ2£¹Ø ¼ ¬J¼ÈëA è®­@ßTëÈzÝ´û(fb¥Ñ\|\žúÕæ•KÙ˜—κåK(ÍR“—¦š@§X¢ëÉ(ƒ#´:üôyƾÎÉzi6û% Pi4¯>¯*Ìøú£òv­Î¡8sqRßÚ¼A.XÝ4ö¹1Ù}Ç:Y¯³&õ±bÆŸÂо£¬þ¦8vu@<òÅ\å‘?(Ž]eõ7…Âо#™½“·ëÙqÑê/K.ZÝbëÙ¡0´ïŸqÿhˆ•Fs.ððÖ<· Ø&ëuþÉiæË Ø3UšÉMôÅúÜ4²Õ)x¤0CJ2Õ”LA’Ρ)ûŸ­Na}nZœÎ}oû^i:E³Êƒ†ª"ª 30Ù}l9ÓCI¦šÃ› ¨Öj^Ð=Ôò€‹ &[BµVƒ¡²(N§Áââè•™@ν’ì[»<Ni4£4šÙr¦g˜ʢ˜ÇŸ·åLJ£€j­†Ã› (ÉTÿ{¥Î#…1Ù}˜ì><G( í{¦é%÷¼ßØ+l^)©5k;…ÂÐ^ûü“Ir­cp$¹YA”å qZi4oþ:"¯7Ûß+É:¸«,‡ÑŒ3¬ÙûÚt,nmuø±yƒ ç X=ÎÀ8å9©|SQÈ»«²þi>5nc^:ÛŠ³x'?p†P0FyNjB6oV‡ŸÈ˜x&QÚkjn8§ AH–…Å—>qÙáßôóÉXH­ÝËŸ¸ãrÝšN¡0´×LÆ3cÏ5ö¹qŽŒÇ= †·†FqGšÑ¢ŒÅ,UM2uŠ‚e©Ï‚ô8â®gì=çÈ8}n€s3VY¯3™ì¾ã'-ÏÊU $sË ’(HW±*#¹‘óôx#&@Æ7'-.Lvßñ©fæD9¯®¾kˆ¦~î±·†Há‰|™Ÿ¦¢4KtRËR§®Šßf00ÙÔk .éZ,ëuVë°´ÓÐ1Hã=7lä.YDY¶zÖ™w²£ ·zøîú Öaig¢A>aÕõº¦¿züÒû”ž§£,O]DyNêœJCî*e<û‡%~¼ý˜¿xÈz]Ó\›…—l^ÅXH®ËKW±fÙÜ*—¦Âå7ðÛ=ÍàN̹›‰Ü<Õ+fç€ÿÁÅÛC£|¦ÕŸ®šS˜o»4?ôqážë°´hZP—G¿ö>¥uÀç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-Û cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFÒIDATxÚìÖ1N1…áÏÙ! ¤@„4Üÿ ´œ€’:¤(»’¡±/Ë6ø5cÏžñû‹IaN-̬RJwXáœãb¢†xÃ+¶}Iv9ç'Ç1ã,çü8ådÃ0tèê/µ÷xþƒß|À²/ìq‹Kô±Æ ®p2'QcŠ)¥cì#bQ<= Ã®xðcED‡£rý¬^c•RššÒ|…&4 šMƒ¦AÓ iÐühŠ©§%îðQÎ˺»þ†|a‹Mš{Õÿ4 Õ?›Ûü,IEND®B`‚kimchi-1.5.0/ui/images/theme-default/icon-load.png000066400000000000000000000071361254252253000217510ustar00rootroot00000000000000‰PNG  IHDR­¿œó OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-Û pHYs  šœtIMEÝ9÷ʦ¢IDATHÇÖkˆUUðß=÷ΨYã4 :Úƒ,,,Šd,HÊža~‰JûÒÃGV£Þ}5­­È¨SÒSèAYdi‚E Q"å«qÌÑLË&Ágæôeß:ï¸à°9gíõ_û®õÿ¯} þÇB”0ãQÄø!„þ_|ÁIXažÇMñÓ\ÛÛ×·«±±Ñ3+WÚ³gOÍØÄÉÙÙ˜”y?·”ŠÅ†Ù³finn00 $y+Æ2em FV*•ÂæÍ›O.A¡„R¡)„ИqõÇ'›VãBI­&ð$žôv¬ÃúÂm…:5Àá8~A#îÆ‹!„étB‚ ø­x—b"VÏùÆaÚ¾µ›$!„:\3r›¾ÁZ|=€(ûb’ƒ˜žµ)+?~{l‚˜sváløàÓuÇQÁ²6´Ú›ÂV¼šóOÀÄ$ÖqLÎù=¾CǤÖVØü,¨G)•öÆ÷ 5üM †àÌœsG<¶xþØ‹± }؉]8˜áÖ!Î`¤HJ¨ô~Eß RÈ¢õq½û¢÷:|8Ûô|•ÐÁ2ß›p亩ק«V­ÒÖÖÖ³dÉ’½xƒ£ðº[[[ûZZZªãᜨê¬&J¥È‚Ý8/ãlAÝÍwÞ¡sÛv–.]Úƒß`Íš5ÚÛÛmܸQ¡“N©1J†F%CܳpÞbÌÏmx$„ðÔ××>|¸4M%I¢»»ÛÑ£G«#nÀêȬªíÄòäÂ'û5xÜB˜>H¢§§ÇŒ3 ÐÕÕeΜ9Uýpe1Csñè*„ ?oÛžŽ?nîÏmúÏá¥HÕ4Ó»añ†›‹±¹¸Ãxí O¿¹Ϩ¶jÃð6âÌÃl,ÇXY¼ßb vÒ4U©TŠ Ëå¾E•Êåx ç:5ë} ¯—ËåŽj“úU*õØŠâz*à[ñ>Þ«*¿¦ÿJ±R© Še™€{19ÇíZ–â÷þÞÁör¹œž &)E¡Â˜ŠKâ8)f@{£âŠ“÷3|Q.—÷ÿçQ>A&Ñ`œ…‹âm76R1‰OõNÞ‚¯ÐQ.—{ó86ä/ÐßÐd“IEND®B`‚kimchi-1.5.0/ui/images/theme-default/icon-local.png000066400000000000000000000006511254252253000221170ustar00rootroot00000000000000‰PNG  IHDR szzôpIDATXGí– qÂ@†A8´H´(hª H8 UP€‚Zð3w IH²Ç+íLvæHØ»ýn íVÍÖ®9~«h2`Í@¬f6ì›ü“ª5€H›|UmTðû“î/ËÖV<ºà]}N¥‰d&¿wéGb]´® € œˆ‰2„ØBÎÏ.8Àä¬ €Ô ¥ô"}: 'I@ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-Û cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅF?IDATxÚœ–}l•ÕÇ?¿sÎóÜçöÞÛ{{ûX(/Ý` Xp°fŽ-BE‹CÁâ]F¢S1˜a2EEL`,nlkf¦2˜1 £5¡3¢¼¸Ò9AÞZÞÚb¥´—Ûöö>çìÞKŠÎhöKžž“ßïû{û~ϾØD#f¼*©I`¦YœްW?ì't_èü%˜ JFý6˜ùÂh‰,)Düè¥ðÜÂÈc÷œL¥RüzÛ6ÚÚÚø¿m–.«?k¸Ü¿Ý‰/p'ýwaÁ#k]>,uÎ1gΜÏõ5ŸSÕu¥GQ:eÒâEa&V× Õè§7lèknnv_ÀR§’ …Ø#¶§gQ¬‡XSè¨ Ѩêèêt»wï.úÙÂw]‚#TBŒ^íM\Ú`ªähxeó¦Ü±ƒ„ö3™)=ôÎÁƒ§N=™vO¥ø³3.ÿÖ C§vž²ÙO(@ßïM¼{™7v»d€¦VG·fkÓÿÚÕ~´dp¥;:r.{¬÷—‘º'æ˜òg DVNÕ¥“8ú䇶Ϩ»¼1³~`nxÖˆ$+T„Q*Bé ½êá5w”$â✻V¶sŽhªÔnøéÃ¥7z·ÒâS!¾ÌÔ©u?÷¿²œ™«I*[áÕ¬‰[!>I<üì‰iµ}Ám3Jâ™ñqÖÇâwÝ»,+‰¯²IñH`ˆ¡õ3jýuõ¸h:‰ì<]9w‚ÄJ1H.5U%¿{èóµšý~.ü _ÂL¿.Ÿ9µtà‰¥›Îe»þé#¸Â„b&?Ö,?¿g?j´ÞÚ€þ§±ž­ýËÙԣ˷ڪd§TW„‘õ÷ðÕŸºŠ”:^þxÀ…ÝÅ*DÄ ¢ ` ÊªâÆŠ^èî.aÄx|wñÆ-Êÿí]nÄq“”%ÎcÔÀù»»‡»†Óƒ8mq×vÀ8èu¸K J‡ÿßnMÇ¡çБÃî½ï²jÕªœñÌY©H¾@?ÐÛÜÜþfûv™¢CljY0Æâº†°§®Ñ söÒ·›~´Îûñ¡]´pœööv6nܘ>عs'd³Yí¡‚é:±èšþ[‡”Cx&jz]þò9Û Jó‹òB¦w¼øÚêvŽoزe 8çPJÑÛÛK&“)Õ­ñkïCt±B#¸AôìÉjlÅ€þÆ’…\hù ÷{‘;ˆX“üTýXUrn_þRK.Ì“Éd$“ÉÐ××G.—SÃÍVú¾µÔ«ÞV*Þ˜2eðì°–úk–öæÍاÿÝÒ*{½!¤uÜÔHy}qѬ™¬âó¾ªã‰!Üéöj?  ¹Y%Ó?ókï»ÓŒy.&¦6->q1H6‡š=¥;úÌÊ7%mçœêÅÚc+ž¬¬úÓß÷”Å+gSXÙ–~g9ïúÛÛlö­ ù“Ö‘D­ÿÖ´øÓ J•‰!©|Ì`ñÀ–¼¸®É,œýGàU)ˆ˜vv>ø\½úý/ž? ­ŠëÇUB².Ï–ÐYPšR1DÑè\‰6òü-þÊ;€—3Eç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-Û cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅF:IDATxÚ”–mpUÕ†Ÿµ÷¹çÜïÜ{“/$Œ"”`¡H…ðÑ*•RúÁØ™¶€­?:¶?ZÊ´´S-j+­fèÔqÆ’™N©…q"Ó:Øj)Q5"‚R B †|'÷œ½û#¹:Úý÷ÌZïzßµÖ»ŽðÉO”ÆIË/ÊTkÑXþÓÙfg‡°Ÿü)H—HÑêêÉ ÷d´'›^rîœ?qCs*G]]gΜ¹a¬óiâ)&%2,R!Á ƒS¾¾nÞ—¿}û¦§•è†ÿ @àZêNí¸âD“à†!À¸TÕ%ºøá‡éillüŸR©:¥S$3þ&IA4ÚÁ(ç*r$Qì /4äâÔdË@yQôÜ•ê+Õ³ä!io¶¿²Íìð³˜ë+ÓŽÊzý­ŽwŽ7¥¾ø€új"Ãì¡>ö½ú¼Ùyéƒ×(@ßv¯ZU³D¶jMžãA~™}*l&½óÚ?ÚûqqJAûùöáï¯[Õ½â{jceüJ)@ñ­¢J]½ëI³éB‹µc%RÓïP³>S+iGòb)!žœ¨-~ð.‹Å’b­ýXgk!K› ›LT˜…Ú¢I!–'RV-?Yø Y3¶*¿ŒØì»åG^„ñ±„ã`µOYþ”žÊüÚh8‚cÇ´ÑZˆEñU+¿–‰ÆÔ‰hÊàÅÁ‹‚Eß4WýlæRʱ 0“gÉ¢L ‹½¨Ž‚Å'.üÒÍÛ^/ˆß¼ŸÐ\¿RƒÙ]QúÙä삟?Úq޼ꄮ~óbT/ø&kÞ>ñ7T"ŸPõlµT;’ð¢ Ê"(n+ÿñ›e‰ù/þfËco\éêC”\»”Ö€>¶ß^8¶ŸïCÇÕÕ·$ÓÜå†CU$!E™Rf„õÏX똔Yè‚ðÁa³'ðÇ̼Æ!£Dˆ„\IëÑú,ð&œÎ¿øåOùÓ3 gU?ôTÄ)êHz¥Á›NUÜÝ \È%l{ßvúC\ʱP +"ÊŒhŒènô žï.AÈuX~ç½N`–ÿ«Ößè vZØÉœSâü8w©³€À ý,Ú5Œ ÝÀE’ZAëåý «©ém{èÐAÖ®];ì8¡³Q·ð9 ÝÁÖßoq¥Â¤ìÕ> XDZ† ÏÆR¥AÓã·.¨Û±&T·á0ͧߣµµ•Í›7—vîÜI}}=ýýýZ;„Kªä.d¤CH{Y%nÄì³uu؃ñ´,Aizãñíë›Oó8À–-[¨¯¯ÇZ‹RŠîînz{{s‹jo_­–åpÖ#6’5–òdMG2<~P×Î[É©–÷º§}^݃%>BO(*WsRã¤íäöH6ÐÛÛ+½½½ôôô0<<¬Gi˜³BͯY,u^Œ’hBPŽÁbù\ùš*ÒKöè£ÇŽÈ}ÇÏŸí:Z^V©æä¦ÀX¼Â R[XNÂøœîlcУé•L‘Ì‚Õêþ[Èn„ªhRðbàÛ€ÒÄÌK‹«~ý²«ã{ÅZ«†û1ܳ¦ðÔðöóóÕlõ@ß®\´­—ÛÙ7ÔO³µøŽËøxŠyÑ<¦kI‘8Xñq˜¹oê_÷NÎ_¾ Ø%£&©±Ï7­óî¥g·»žT*Ff-`x²ƒ–ìX“³yàE7 F|B*j–M~òHMéºÀ_€–€!cMèÀéß-:pvó£ÁåiZ]@± kAiÐ!‹•c!U¿=:­øþ]ÀsÀû€k¯±IÈû°ûðŒÆ–GÖ·\yeÉPp%%€ˆŒ¹†3v’¶"½ì£ù7-ŠÏÜ 4'rwýz€Ü•ËkÊN^üû¼ÃíϬø°¯iæ 9m­Ñ#“,6Ê÷Ës»jJ¿sº2ó…7½x h¿æâ¹ ³]·ô wÌÊš¾‰`c€D…t<s‹;<'ùphüë“üwÞîi¯2ÍÀœIEND®B`‚kimchi-1.5.0/ui/images/theme-default/icon-qcow2.png000066400000000000000000000111141254252253000220540ustar00rootroot00000000000000‰PNG  IHDR((Œþ¸m EiCCPICC ProfilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüºÇhbKGDÿÿÿ ½§“ pHYs  šœtIMEÝ 9¿)>ˆIDATXÃí˜{pTWÇ?çÞ}ož› IiHR`”’AÁ©Pìˆ0­`F¨H©µ•eÚúÇQëÊ3ÖR,ïéà(ŠE§ÓB”‚SiRyÒ“ <6ïìûÞã» )ÙL í?=3ûÇž{óû}sá³ñÿ urGi°Èl€°}@h’<@-°[n+jPì(@5pª ÅÖcTýN«¡+Þ¤ú:}ZLH—ÊdšÇÒ'[zs€Õ@®ÜV$‡/1D¹m*àm-ê’í!x“:ÉF“H½ »AAUÄ+êÎ2 0 ¸6|å5V©P>T:#Æ(²V 6/=ZGú«yýJפ+ëÀGnÒ_-gÅßêÐ`…wŽM.?|1)*`½OµvZì ýA|¾¤¢ÍÀGãôõþIÿ…Ö|!Ê[=ô5)@6xdãMݤEuqõ†ü~ÃÎRCH"Ê×»¸Øáåk÷ÅÐôIܾ(‡2â(L¶#„Œ‡ªõùÝ£IÚ®²§Ý~ùR@—ñ&ƒ¢ˆO(•H‰ 꺴«|cXW³i~ËÀØ—Ë–ôyOJð†>Ù!e8xLªòF`kášì `ɧÀ¶”ÿRX£jP@†mª øùÂt6ºœXT…c ]€ûûóx± uÔu†;ò'ØœŸÌÏ]㟠á€zòdï¯É–w[ø|šý˳H±y­ªÎ^cŽÓÊžeÓÉwÚ¨î𰹤‰Ê/ë]¼^ë¦ôÖg¾9ƒ/üù2+³âYœËL‡…_ž¿Am§—SÎ`_un_p`T N7Sëö MÔéè*LµyåË™üõJ'KŽ\fUNŸK0³wYµn3VQëöñÚ²é¼ÓÜË©1¥Úéõk¦ÚYjçDs+]a_u;A]ÒÐè jQ-µ®6õø™é°°6×ÁSs¦ ¥¤Í$7ÁÂ?º©h÷’{ Šún?.§•ý5í´ô8PÓÁl§ €’æ¦Å° ÍÎþšvŠRí¦Úy§¹‡ ­Vå$rpy+þ^G@“㌬ÙSÝÎogðHv Òìl_’Á‰æ^|š¤±ÇÏêû™›l¥öñ|²ãÍÔtxù®+™ûbMlt9©êðpîz?‰f•¥qìªhãëÙ „t¸ØêáÙy)üîKl*iâæ@Ã(Y×ÍÅ/—·’d1°{i&ñf•ãM=ä&˜1«‚gN7³oyOÏÂ.µÒØã牒ÿ°wY—¿3›êO”4à 霻ÞG²ÍÈÕn?Ý~ÝèCÏÏOejŒ‰w›À̃UÔuyGïÅŽ²¯ åÛµML4«tùµ{®A¨Çås_áb)’ѳô½‡‹`ÈQ4g«(r¨ä|µN‚0+º7ªWLQ«Ïwj›Ú||Û¯SðPFŒMA uª]âö…0ª)!¨éôø5úƒ:Ù fâŒ*ÆaBéÔwùp{‚ ˆÛB—,ΈÃ4¸V€_Ó=ïßÐl*GfÇ+ÎÖͬüSYÊ{¤{Br_hkAŽ"vø‚ÌÝå\ë €A!qXŒ|°>Ÿœjâx]'?˜Š/ ñpV<›f8Bpâ¿}¬}£žž`ø(“l3ÑöÔw*¯^ÝY6mãÇé ö’³ë\ZÔ4óVqa«'$õìa¬q9‘FÔX™åàLñ,V­ãx}'¨p¨ü©igó[ üúÃ[aÏL‹¥é{sùéÂtÐ$kò{æðÑèáÖp¸ÑÎ$¯{Clœåd×…Vž]œAqžƒùû+ B ïSnï÷ggZHøEQ &•—¦³Á•ŒI„#a¼-2‘ðš“dåüú|â ‡ª „C?zsgPøÕÙÖ½Ý0tnœ‰é±¦ õ›ãB ¥d^’…Kmô>¬GÙÜ )ªÂ‘7¾Ùpׇé q!>’à _œ†*%22'ïÇàU<§ƒw•¼ üè0ùÛEéç:Ø~áÇ®tâéÜÖ½€˜X«rüh~*ùIÖ°Ûï¢]_DDÂÜ$ ‡Wdá_>«Ý*Ý„€9+÷'˜1E63<Ð&pìÞ\5 +ÑŒ+Ñ<²´Ž,'¨A½@Ž­„1¯Ý~¦|°LPIÊ:}÷¬ü–¹½xCrp#À4n@¯®“¹¯’¢?^âÅßœt¸Ÿœ¿AÑž r÷VÒÒ‰¸78@ÐU!„Ój@˜Rl†1…0Zš‘#vf¬â´0*Böˆ›Ç ’. Ù¬ˆ“¥Å³¾Ñíטj7FÓ#»wˆQιÃ矟—Bqž‡YE‘²X4Ž÷f¥QnÈwRíF¿”0ÔL~M†¿t40yœˆbÁÁë]ÊõÂ’yr[Ñâñ~N6‘Ï¿ƒQv/"FF,÷{¹­è&ŸIÿu 5ð±©ÍIEND®B`‚kimchi-1.5.0/ui/images/theme-default/icon-raw.png000066400000000000000000000111071254252253000216140ustar00rootroot00000000000000‰PNG  IHDR((Œþ¸m EiCCPICC ProfilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüºÇhbKGDÿÿÿ ½§“ pHYs  šœtIMEÝ Ad,0ƒIDATXÃí˜ilT×Ç÷½™7žÅÛx¼€q ì€ †xiA¥I”(ˆ´UIdº (m•V@÷Fý€HT©(¡j•„ªI¢T* M¤&”¨XÔÆØ€ƒ—Ç ^ˆÇËØ³Ï{·f</ƒmjÒ/9_žæ¾;÷ýÏùŸÿ¹ç^øÜþ7S¾R7ø>PØ`†ÈcðûäÎêëÓ¯Ô  8Y™këp˜Õ ËjH×Ô@@wD ©ÌexüÃ|¢ÃSlŠåÎj™8Å4ÅßæÎÈöʰ!Ùã¤kêM"xB:v“‚ªˆWÕ½õ)À 3qf<_R>Pw¯Ã,½:<ûБVò_¿ÈÁOæ<³Þºì&ÿõÖ¿ÝŠë%¸‹l¢ê‘C³¦ØP­ý)öö‘° @Dré–¯OçŸ7Gæ<ù/ôzñ"4ôú ëR€l÷ɫ݆¦OIqóÖ²ÓÞ:SD"Ͷ”r±ÏÏWîI%¤s pÏÚ|,H£*ÛŠC1ª‡¦-eƒIE2ïµú﹃òÅ!Ó5“¢ˆÏ¨”H‰ †´«œ+t˜6·l«è˜0õwõ_ sZJƒ¨CŸ­I¦*ï„¶WmšDñp›’QlÆŽªI‹4õùxê½vZãÆž)¥<ÛÆOÏv²ç|O|üýÇ—²aQ…o\¢s8ÄwWæðêC…üª®‹þuMŒ<_Áúý”l $…uJ‘Èñ€Üþ»>¼ÉîÚ.NuzXá²±kMþ¸9Å™)”gÛxriæ¸w':<TäDßß—}VåÚ(ͲbR'®{’fÓíÊvŸ?Ì®Ú.rm&ºŸ[ÍÂtmÜœ§Š£ .÷û©ÊsP˜¦qÝàxìùvÞm¤"ÇN}Ï•1€«bŽìô$¥^™P?“Úh”þq}übOgÑç³;æÈKÆ¢ØìöÓã S‘kGSe.+û?%#ÅDQº…Õ96"†äÌáœÁ§cGÆŽ*Žm*áT§‡—ÎuÅß/ÏJ¡Ôeåý«C½6„nH¾^ìœ@ó96V¸¢tþõÊn„ª<;«²mœëa$lÌà»6dÙþ&–h⇧;x  ½÷ß“@oÌß®2Ô9{s˜/ÌsP:–ǯ{ȶ™y¬(“+ƒ†‚:ç{½TçÙ)϶Åó4™™&QœÅ nÄÛ6àåûïá‹ó ôF¾ýµ%ã–ybi&¿¹Ø;N(ß.uqöf”Êó½^¾Yê"USo›ÓRœhz,?-jtÒJ—•§•-},ÛßIJýM”l&1Æ©¹Û¦¥ÏÏ|‡Æ…^õ½^òްιnï,Êé êèö2JïŸ.»iÐ: ©Ïωkç§’ï0ÑÜ1ÝoEÁœï‰>ÏÜ&lÈ6¬/×oŽ aÜ>”wy?‘¨°³rä¦iøEÆ·œÿÇ^'AXÃ?¥HÖç¨Íµýú¶[ž T>Xà°)ˆx§2$î@³*ºÁPPg$l°8ÃBšYÅœÐ^x#mܾ0(‚øFeHÖ¤¡ÎÔ ß¿»¼ºMåðŠtå­Úd²xôÏõ¹§ûÈ÷E䛑í•EBˆÔÄ …ûèô„À¤€8SÌœÛRÆó'¯q¬µŸoÜ—G ¤óð¢t¶ÝëDÁ7†yú6†ÂÑ£L¶MãÖwVMLý6uo½w±ŸçgØŸÙ\ªO)’£5U½¾ˆ4&aòΦRÒ¬ Ã:.rrªf9´r¬­aV8ÐÐÃ_Z>åÙ£í¼kÖ/HåÚså¼°&tɦç¸5íªžDpÉÎ$“‹b¬ÅùÖr¯]èåë ¨)qRñÇFB€P£~ Ó˜¿¿<ÕAH®êydh*/®Égki6šˆJa¦-2}­Ì²R»¥Œ4“BåfBR"d’æÎ¤°ûL›ÿÞÿqšÆÂTmVýæŒ !R²:+…nù0"ÆÔ=Z,âBJ„ªp¸ÅÍ“ïµßñazVgÜQG¾ZÄ¿´UJdlLNHŽÑߪ%.+&!î¨x™fyéùëµùÔ;Ùs¡‡w?éÇ7Ë{ŽTÇŠü¬"²,k”ö;8JÌL$S€DByV ‡Ö/"øÈB® †htûV:­,ɰ ÅœIÚœþÚBj‚ÒL ¥™–I>ÎBÀ<Ë”qÎ2¦}7¶¦ýŒH™@A("©ïܵí·ÞíÇ‘£Ž„mÆý†Aá›Tÿþ#~òa÷œƒûEmÕ¸Dñx"1zÃ3¨†*„pYM‹B®Í4m"$+32I»é´˜—Õ„Y°ÇhžV$@¶E'êj–?>Ô™o7O ̈y#&Òpªñ­Î¥¦Ä‰Ó¢¢HÙ¬®Îô³Ñ¬ˆó[Ë\¡<»9(%xúÔ¥)ñ£É€É àD’†]DÛ8yèã>ˆÈ¹³zÝL¯€³­@eìúwTewC12¹ßÊÕÝ|nslÿïÒkñ ë€IEND®B`‚kimchi-1.5.0/ui/images/theme-default/icon-remote.png000066400000000000000000000017551254252253000223260ustar00rootroot00000000000000‰PNG  IHDR szzô´IDATXG•ÖõEp¨@¨À£°Ï „ ˆ+*0V V`¨¨ÀPXÎçÞLÜߺ›„yo^öææÏwçßåþ½/£§¡þ}ðü øIš¿ßÏÁ§à7ÁÜêöþ Š‚ý,¸ ·0€ü˜À¦6×ìÃò‡&ð‡t|LÇnŽd¸5>N9 ¯‚ž!˜àìÏtÌö·``N·\?t–Ôžú€~— ï¸pÁø˜7ª›Þÿ¬&#‡à¯38w|õý+ƒK÷Ë KÈðî&kW8ú*XãÕ Ï€œÓ7Q@#› áWöœ¿ ~›¿b>@—þžÁm¯QT¬ õ YÈ×`#¬É†¾`@yÿ,í=?à,ýj À1ØÜöäFñRó ºO{ú5Æ€ûް?¥¯×(5Õík‚âï`cÀÞa¬ øK#p!Ä–Zz €ê.mΈ#,ðš²%Ÿ;çGïGs_ U{ÏÀ(Õ{þI~+îC®4j&µ•z Fe ©ØYjšòL—PRó]ð1¸ÒÙÚ·çkèê @èÊÀ¶ˆªÐÍ̤ ½a€j ØZT3üãCð§à£&œ¯…:d¤FªlDÉœGÓô:äle`kBhÔúÚ‚)½à‹´¤ïúÚ#5-ÛBj)Åù+5ð8@í,µ½mùm]U™«ìÛ"BèÎGépt£%„¶×ˆ¬Úê“z¿Æak´†€‹;æA8ă2\[µ£´òß0Ù€ùß[|[¬2Ô4§`Y¨8¼jkoÔ{ F°žøÔéEšï¬Ün¿n‘Cf‘¨³‘lHýî‚nÕßÿ>7|Ÿº2€ˆžÖT]ÝÂ3›矑Ï<àFÔÙïF=€¶£L”C¶nôêBp¯j¸¹ çÔÏS<ë‡S°Y÷ŒöÁÊdiÈk´†‚¯c÷|'c£îårAëßÑ!εBõF?r=%îò…´ þ¿¾š(‡nlkµ_0ÀÈ9-‡+pUc)W&úCº€çœp|çS:sr•øÙ4mæ·hã—V%ªl¨ï1ƒ_À÷ß«× ñþb*RIEND®B`‚kimchi-1.5.0/ui/images/theme-default/icon-reset.png000066400000000000000000000107401254252253000221470ustar00rootroot00000000000000‰PNG  IHDRK–W· pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-Û cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅF IDATxÚœVilT×þî}˼™±gñó†mÆÆxa±”})`™†D1¡)F„4E¢¨B­Q¤"$›_D J‘Û´J•Б(M‰A°$mÀ0D‰«@ÀØ`–‚—YÏò–{úÃcglŠr¤«÷tõÞùt¾ó…áé`dYQÝŒs‘a[fœ„H?­#ù)¿c2ç’Ó“_¸ÓÀÈø¦ï Ê¤Šºy«Š*ªw;\9 ãêˆ+ÀÀ0Æa©¾PÿÝ?÷üûÜÛ©D|ðqÀÒhw°Ã[8crÕŒ_Ú–í``coŒ±‘\ò¹½úÊÂ@ÕLÓH_ˆG†B£n¢XrôÒòº²šY¯¦TÞ^Û°ôBGçÉ_T²‚ˆàv9ïäù»|žœnÆx4m˜¹¶*猒¬Vë“&Ï3ÒÉÓñð`ìqôrcÌã˯ ̘Óä+,Ý,)Zyž×ýZûÛû||ü´~ìì¥7—Ϋï}aå² šC ,mÛ6¿r­[?täÔºk=·7ª²â✠0R‰÷»ÎÛô(4HÙ43ž›WXU\Y»¦(PýŠ$)Ói¤ ë¾÷ÚÿôÆO¨<œâDƇO$åCGN5üýİ,«$Y1úº7ýç_Ÿ~8^%ª¨¨›»¹°lê:ÕéžM¶ ÆãcàœÝüí¶Í V-›ÉbF|GªTÆs·5¥„ôcp€tÚ8ý¢éëtkxL0“˧8«g-|5 W pYÌX<‘œ|îrWýªeó;¾K‰Á`pôÕÐu7.u-š¾ð#Íó #byyÍÌúMçÇ„sëÆÕž¶–×WoX÷ü/8—®db¤ÉÔ2˲ÆÝŸ9s;vì@~~þØimmE,ø·º:ËŠœ‡æÐŽž:³Ø4-–]t¯çúÝHo×[f*áU]îÙ ‘| "¨²„®ë=‹®Þ¼­<3­Êý±©© ±X,[rKK‹`ºõnË0î2ƪ Ëš&ˆ\O&“öÇííéÖ={|–iÎ$"!àv»T”M:.Ërêá`pAÿPhNv¤>Ÿo\äÞ‚âêª9KĹTh¤3Š}› VÀ€Y–Y×u˜¦ .Iàœç€Ûp:ÔþÖ_mi¹Ñ{çgϯõ{s‹3ÌX‰D²1Isç¦Ïy7oRù•xxà°m™š'€"Kp¨Š‡ÙêÕ«!'“I`\’,Å@’$ …”¾ûcË~Þ¸|á—™ZKø®]»°sçÎ1T#™¼bé^—Ç×ètç6È$!"øú½{C'Nž ‹/Ž9!"J aõç ñáda4÷D#¡G­­­C2û÷ïGggç8zcÁþpdà¿—$Yã\’Æ8çÇ•ìÞû»Ò³g;T|\ïž»üå²iÏ|Ahªü›Ë§>Ü7Øÿº®£­­ Û·oÏ.“qV3ÿÙæÉµ³ ÛWB!lk0 ¶{[å­[·ŽÐc¤Ñ~ìäÅÀôÙ×ìZÎð·1Íû ðð›`0Èš››Ÿ8'ÑðEÛ2ÃŒq=ûÞ‚[¶(˜U_7ïÍ–•Œè[?²¢¢~ùó{òKÊwÛöH]’°ÿùõ¹Ï¶ ÞíéË4š00øèà–UM]ðÜúOîÜ•$–m (/)>¿áÅÆ£‹fÏìÐýÞ[RKKËhR1cZ úàšÃ[°FÓ´‚ŒÂ¦è“Kˆè~"ˆˆˆƒ1‡¬¨~—×_[6mÖâèÀƒ›¶ešžâŠrEs­Bˆ²â«Í/6¾õëŸmx§¾vj‡Ë©Ý)vð½¿Ò—_Ý|öJïÃö—æ'"€‚DÒH  \N<Š IŠâÈñåWäxòd‡V1Ð×½þjçgG¶¼¾{a4)~¿rÉÎþdMÃqÝï¹`À£ #˜::æDÛ_þöãƒGNþÑéÐ $ÎAD 0ÆÊp,(³AX–¸Vžçxé@Û¾¾{ÁÀÔ@© Àœ0Ñiû«ëÿ¼ù¥Mn—v.edX ”i‘ ÙÂH›6$YªùaCcƒCÓ05PÚ  @p"àã"í¥ €z¿°èý£§_þ¦§omïû•iÃô !TÆ)ŠœÈózB3k+»–Ì;¶bñÜóz ?qëz h6*y(-øêjwÝp*U.l‘Ë iŽXiQÁ­ºšÊ[™œE²†û÷7E2%¢dž,kÏ5<õ²ý¿?Ý L´PpIEND®B`‚kimchi-1.5.0/ui/images/theme-default/icon-search.png000066400000000000000000000101451254252253000222710ustar00rootroot00000000000000‰PNG  IHDR µB pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-Û cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFIDATxÚ¼—Kˆ[ׯ¿sî¹éêêj†ÏH¸Öd*„Ø¡Á’ÿͲìthpGd(¨ ÙÐ0  bÛö#J©—¥”; À”RÊ›§$‰4MÿEÑ«Q-é¨Ó»AIÞJ>€íŽãüÒ4Í×¥”ŽeYð}ÿÆôôô¹\n³Õj¯]»6DZÇ1¢(ZÞÚÚz>‚ó"Ù°)µø¦iΚ¦ùšRÊq8{üøñöîÝû%€ í………â©S§ollì¢hZ)õ‡^¯÷ë8Žc]Þµº9jù|þ½R©ÄJ¥Â£Gþ…ä+$_$ù0ɽ$÷üé¹sçÆëõúûµZ;wîä¶mÛÛ4}à˜Rêñb±¸611Á¹¹¹‹I’Ì“|Šä’6IAÒ ™ Ëår­V«mÔëuîÞ½û IŸ¤s7 Ô׆RjÊ0ŒQÇqP«Õþ®”j8à+!D$„ ¢ `\¹r¥µµµuLÓ|ðÌ™3ÝÉw\}`&¥,)¥`Y\×ý€¯¬ !Òo´µ™Ö¥Ýét¾L’RJuuµ À%)‡&n(¥`.]ºÔpUGs›”t“åÓ4õ“$"­V«9ÎÀžwF$?B„RJ,//ÿLqUß²`(I)GI>”e\×]k4é0]z3Â(Š.ü—ös“““kmºúäÀ€ Û¶Ÿ“RN !°k×®%×u…ÎH6 0Ͳl3MÓ·²,ƒÂÍåro{ž÷(€IÛìð€²ã8¿RJÍ+¥Ïç;óóóÿÔ¾ÚBð®æ­ !Þñç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-Û cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅF{IDATxÚ¤Ö[ÈUUðßÖ#i^Ã,ûJ?ÈÓ2+Á‚Ì.Hbù``RÐC!ÒåŇÉŠJˆ2$¡}(È2Tè&=E˜†B ii–f^òÚY®ÕËlÛ·BÃfÿg­ùÏÌZ3{+¥¸RJYUJ9ÐÐE¸W«”¢K.Âé.ìRÜÏZnÃપÎÔ@)¥B«ªªNsó .ÖI¥”7K) K)£ø¥”q=ÖŽ®åœÇ–R––R^É98'Ä”R­“RJSJ%tCJizJiJJiUJ韆­¤”¥”^ˆ}w¦”>oØV¤”ÆÖUN§.ÑÛx¬«L¿ã8&X~Ä8ôuá/bY«ÕJ­œ3œÁ÷=HÆ;¿Léuð2T'Ož¬ £ðì±éÖáÃXÌÂýÖµ¶à ,:thª'N4ÌÀ\ÞÀ>Ås„›ƒ`¶`–^Ë&Ì6lبËUËþˆ´&ù £Œ‹#ÛZvãY<Œ ¸.ð8ÒtZ=ztHDwU8|¼Ax7æ`YcÏßY_NÌÆp|ˆV¼ŒÃÇ‘êðáÃ+1 —áJ +ñ¾ '¿b¶ã^,²Íx(H¦ÅÞSø%Îrk+çüF÷8ì¯q{ä¨ýò°}…1‘õÔnSƒd(® ½©•s.\Ícèo”臆íTôG-cð×~J«”’0Ž”E¦3£t§£ùîª'J”eÂ~:­œó«‘ò5¸õÜ™‰çq0ŸÂ%ø)æÄº/ñ¦7ïör{µoß>¿KQÅ8™ãâýÀz5é}¸#. ü‰g°qüøñG Ú»wosS_ôÆ-ñ¾ó1K"ãºD_D@ÃñQ)ðÙ}}}i fYÕ2ëƒ`^Ô}Td°÷à¥\›£Ú½{÷YB¼Ž§{”¦ƒïâZ ²¸!ÆM·¬Æ“'N< Õ®]»jܨýÅþ¿tðhÿÚîrè‘ÁžÐ)=¦­è-h7zª>³³_ÇA9g¡ës΋sΧâ}]Îy~ÎynÎùµ^ëœó¢°ÏË9¯ ¼“s^’sþàì™ìر㜉'â›°GŸŒOº¢Ý„ÚíöعsçpÌ‘²ºÝnÿw»ºþV Þ v‘ü½Úíöq¼Ûë€zýõ’ƒØŠ‰ l[ŒúóÊ¿¹Ý Àý.o}IEND®B`‚kimchi-1.5.0/ui/images/theme-default/icon-sort.png000066400000000000000000000065351254252253000220230ustar00rootroot00000000000000‰PNG  IHDR @†û pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-Û cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFˆIDATxÚ¼–ÍnÓ@Çã8醴nÚPQËg%DÅ „¸öÆ‹D0gѲÐLP±'aÉlœ·EdÞD~Œ8§À'U®ÙéŒ#Öê­Vëe·Û‘LUUlë—Jf"r<BIm¬´XÄqÜPÕ¨„ÿ<ðø|Ëç·ŒU€³8ŽoŒÙ Vuã•YÝjÑ¡Œu€{Æ ãR´s`_UkÀ pVô‡™sÎí”ð é‚’bMàcIßgæ?0 JF{æ½o+ÖC‡±º¬«IÅŽ»ÆL.êf«Î¿ˆõ€ºsîÕ$¬òÌB«£–µ¦|‘fÀ¡õƒIY壩×›ÖÏòb¡ 5sï}Ëzãì8¬ò—g­Ýn/onn¾å˜$ɰdÁeCX‹ÈÏMSQÕ@D˜rÎù!wÒsÙvÎ ­vG«ª¿ëLUªV½÷Ókã7«KfÖÁ»ÖǪÞû…(ŠÞ¥i:ç½Ùåç¼÷{À´1Ò2¬þøáQÕÀx4;À¢qy|1ßÈGÕ„.~І²ºÂ¬ðáBpÆNZRf¡2¦ªü×"úÖ>IEND®B`‚kimchi-1.5.0/ui/images/theme-default/icon-tool.png000066400000000000000000000105621254252253000220040ustar00rootroot00000000000000‰PNG  IHDRÔôU pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-Û cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFIDATxÚ¼–mlS×ÇÿçÚ×ñK|íĉÚ¤LÑ(# ‹/ËJYº¢vñ‰)T¨j$`:AØV:@›h·i#ZˆR¼PÄZ±R!8ï¼T„’ˆ,1!©í$~¹Éõ}öcæ¤dHû°óŲ|÷ÿœÿó#"ü¿–cÉï:6ùdi"F„(´9ÿÃdÈààÏŒ0£Ÿ³‰`Æ Å^¯÷g&“É”H$Â<ð7444öO>ËAiœ^(---Þ´iÓ‡ÃáˆD"=ÇŽ{ÿÚµkSf¥*}UU•«ººú㢢¢J»ÝUUîÖ×׿süøñ.“ÔÐ*¨©©ùÀh4våçç/±ÙlEápøÓU«Vý„ˆTfægˆhÀ¿†††Ö?zôè»Ýþ®ÅbÁ‚ ;ÎÃápøµæææ©”Òåȯ¨¨xyóæÍ?·X,§srrNçII’†œNçDd8,777w)™1f ¹ÝnZ¾|ùž{÷îýAQH’„ÂÂÂ⺺º7‰H rÐ «W¯^¼eË–ív»O–å_ªªz\Ó´C‚ ¨¬ôIXÎÎ;?ܾ}û²céŒ13€÷ìÙó¡¡!5Ãd2A–åu”   ´´´pÛ¶m¬Vk½Ífû£$I_hšvÈ`0œƒû¢Ñèn¼§e$Y–=eee¿r¹\TWW× ÀÀU^^¾>릧§‘žž“É”  cÍš5K7nܸ?==½9;;û”Ífk!¢ßƯ¢Ñè9½^ÿI^^^7ÔtaX–åïmݺõp,;pôèÑ¡;v¼^^^þ–$IEñIoèt»Ýn©®®v¬[·î×6›í„Ãá8)IR €C&“霢(çôzýo=ÏŸxëL˜I–q,‰´ ‚§Óiܵk×ûgÏž­«¬¬ÜPPP—˳٠á¿ßÿNEñ]Y–ÿ&IÒçY,Ÿ¢(§S@S¼ÇâŒ1O}mmíÒööö‡Á`E¡ññq¦P(D333”\š¦ÑÄÄutt|@ºxñâÁÎÎÎîÞ½ûÛ7oNܾ}ûyˆÈMD"þÓÅD "ˆtçÏŸ_ÙßßÿM,£D"A‰D‚4M£¹+‘HP(¢ŽŽŽ3¬~¿ÿ•®®®é¾¾¾Ã) ó,Æ•1nÃ;wòÒÒÒ~š‘‘ñ}“Éd×ét™‚ ˜æ4>4MÃää$úúú>kmm­ñz½«W®\ÙÁã,YºÙ±– b®Î@DÉš¦-ŠF£Å@àGccc#ñxü;*“ ÛÛÛψHGDz"bÏLâÔÔ'"Æ79ÔNDæ¶¶¶²ÁÁÁáX,6/Ðï÷îr¹<<„ ¼ZóÃæ,€Ä'€Ûçó Œü7`KK˲,¿ ûY@á9 "%û÷ï?‹Å^ƒo?~üxDQ”Y/)¬V+–-[özSSÓY–³ù¨gç(KKe~¼{÷îO}>µ´´|MD oܸñêÀÀÀðÿ¤0¦ãj¨°¹¶¶ö¯§N¢îîî;¡PèDTHDÖK—.­x^Iý~ÿY·Û]Ä3ô‰ÂëKJDQÜXYYùË}ûö}ÙÜÜL===_ONNVÑb"Êâæ1\¾|ùÕ癦»»ûLIII.! KãŠÞÚ»wïß›ššèÂ… tëÖ­þƒˆDÞ""®xpRUÕ‘HäÏ@€®_¿~÷óSe2€×Ö®]{ ±±Qëì중‘š˜˜8œ¢HŸr〩g¨ªêoˆè%"JïííýÅýû÷"²‘!éÆl·ÛíªªªÚ&Ë2[¸p!²²²zEQü'€(€)ƘúÔEO’!€¼^ïõ‡VŽŽEA<ïcŒõ3Æ ®\¹2‰DDé É·UkjjÖ¸ž,’$é¤ ÆQžÜ3s{ƒ1¦ñªè¼^oO[[Ûz§Ífó{õõõßöööfeffîàãÇ4•¼ðX~¿hÑ¢²%K–|$IÒe>ƒÆùç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-Û cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFñIDATxÚÌ–=kTA†Ÿ3s?r“¬"Æ(FI!h´[»-Œ?@LÚÔVv)Äßaa/QlAD0XF´0!,Œq1°f³É5{sslÎâ²Inr×ö²ÌÌ;sÎ{žQUþE D¤€®q ´€ ë[ÀNi!`À9w^D&Ed¼`üU½—çùR¯B±ˆL:çnyïñÞï7þvžç›yžßQÕHDZe…Ä9w-Š"’$!ŽcDd×`UEUo.//?VZY¡ï=I’P©TÃpß qÇÀYËSOBÇ1aâœ+òÀ ,“£öŠ-@÷ Ww‹¢(Ntl²”Ð&ðð0ªÕê*pÈK»NUóéééG‹‹‹jµZÕ9G–e­z½~jdddC¬U«ÕÆÄÄÄgà°VFHŒ ƒÀà²õU`vllìõüüü++Ø5`x ¼>ˆHZÖ )° ü–€9 FGGž™Àðø$"u3ÃÀÁºm¿;Êm±uàI³ÙÄNðEDÞÙ¢1p¬,® Ójí*|ß+®‚’ö½âªH¨’"‣ª>çÜxY\ì‰,±ýç½÷ZWEB 0<<ÜLÓ”4ýådï=eqU$”ÔjµûVg_­f†††žApñ duâÊt"à#0Ìï€8Žg L°'®c†¹v©ª~jjêñÂÂÂ¥•••jEÝIï½ïÆ•¨ê^®I€þJ¥²Úh4®w М®£f”v mþ0¼KÕ‘m(4›žw…¹ýÖ¶ EÚKÁ:ç.8ç&ƒ ß/Wªú$˲{Y–-Û=“ADnpúÛÞûÍ,Ëþ2ì´ñ."ÕQßß C4 › ªêìι\µÓüø2ThÙ­šZÝ4:Èp÷·É`7nÝúûŽ“þq2PÒþ®‡Ìiscç.Øõ)#dbÞÄŽ'-ÙAWØ·íÕT³Uúsê·VqÒ¯”RIEND®B`‚kimchi-1.5.0/ui/images/theme-default/icon-user.png000066400000000000000000000123661254252253000220110ustar00rootroot00000000000000‰PNG  IHDR$(–ÂXã pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-Û cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅF !IDATxÚ¬XKŒ×u=÷¾W]]=3Ýœá"ʇCÃcƒ–%$ @‰`d‘8Zd ßE Û Ÿ•aà A6Î&‹ YyeÈB¯Hl0òG´àÐâHCçCNÿª«Þ{÷Þ,ªºM%ŒØ R@¡»ª_uº÷ÜsÏ-úú_ÿ –ÙˆwîÞÁ½»û8sæ ŒlÛ;ÿ©nÞ}6Ïósu2™Löf³Ùwêºþöd299î®\ÙÆûÙüûYLÔìBˆñsýþÚƒ úòÞCT1LqpxðG‡‡‡ßUÕ¿2Ø÷ð>7ofK-df8箤”þž™?¹¶ÖÇÚê|æAD #äy§ƒnY–¿}tt´C /Ñ«ËÞ|QK¥+Ƹ±·w÷ïºÝî'‹¢€ˆ`VWPj†º®Q‡€Ì{ôz½§öï¼rñ©‹/fÞß\wóÛWz=ܽ{÷¥ãããç³,Cu]#ÔUPס®B@J 1%äyŽápxùÖ­Ÿ™ˆa†¥v?‹:Ë2þjžwrUEJ‚#ꪆªÂ1Ã`ˆ1"Æ…ˆ¢Ûͱ»»û{[—.}UDÞ^*e¯¾öÚR¡4µ_ê÷× "H)"Æf†™5Ÿ0¤˜R„ŠªpìP×uïøþý˪º áÉÉãÁ˜¡(zl¤ÔF(% QSn‘„’ÔfSÃ;{{¶,±½ª.0¨6éru1€Òþ–$AT‘$ÁeY8þü-qð›››KUY‚„á][æˆ*¼ËÀL€”Ò"ÍwA¯×ÝíÅ’Òr€¶/_~ü"ùÓ7?êÞy€ @Ô ÞÀL03$‘¦Êb„¤kÄòôáÁѯѵ¥½uûö2¢øÜt2¹ä3”"ˆš4ª(Lµ%·6ü’&B!F¨î_êo¿ÈÌËŠ1.踮ë„UçâÃ䂪‚˜`èC𧝮j©ªj˜wr,ClÿÌ3ì¢N§óë׿wëððècƒA£Ês=rŽ&0H‚Š"¥„ñhŒþ©þÉ /¼ðo''' ¢Ç:sæÌ2Âx|éÒS¯˜ÙF£vÑ…Š€9™A 3mAµæÝƒg>þÌ×¶¶.ýûµk×Ñét–i®/GÑ„¢(¾±½½ýæ7¾5+g½Ì{°s- À`­üb03lhû/7NoþmŒi©è€¿³·¿TÙàÝ<ýôÆÆ~þÖíO¬®¬"`æ9¡ZŽ&Ó)Ξ=sûÜOük •ýôæMt²ì‘ æçæüòå¬\Ú Q™wó©É'ÄІ70U4j085øÁæéÍw˜ªŠ•••G ®ˆ€ˆàœ{·R?|ò=@ÕýþàûE·xÙTÑ<¦PA{lÈó½¢÷ã:„ñ{È?:yŽ£ãûX[]Å?ø$RJð—·¶%®*œ ‡Ñ¢=*Jnà~xáÂ…ÇÇGëÒ–¹ pì@ޱ¶6§N­¿9–úß[“šÚ<‡÷%$¥…®™üÎμ÷8<<Äô› bHèôrŠÆË¼ ÜísçžxCUž+g3Ķ̛)3£¿¶v,’vg³rqí¼ûýŠ^PÕUã‹&u"MSœ“RD$amuãñyÞ1Ñ|pöìÙÃîíïcV–H1B$‰Ñ ÀìâÁÁa½¨Ò$ØØXGЇ$vú`ÞÓäKŠ`&¨ BŒX__‡ŠÀÌÌi¿ßǬ,1O0šŒ3¬ôV˜‰7OŸ¦Q½Gžwá3#`x$˜ÇLM;hHk`"1=cÜvìà³ E¯hì†4=M$ÀF¯(>P¬¬`4¢ÓÉÀ ,cuxéˆÈ©ê•jVýÅt2¹Z–%ªYIÒ€iCX!„Þî;»^–ÓÏèüÜ/ÿ¿ÍeÌ|uV–/ͪú÷‡Ãá‡ËÉ'£†£!ªziR‰ꪆ÷Y–]=>¾ÿJ¯W|†™¿é³ì»Dô:€ðD8ÇTõåÂËÓéôâl6Ãd2Åx<Âh4FY–ˆ¡†ª5„oU×y‡,ë „u²ì¹@á9T¸ãØ}ÓgþŸ˜ùºáÑ=Ëÿ/ôy6%ùâÑÑñ¯§·TÕWU…é´Äx4Âd:A5›!Ô5ûÒäC‰AÔuç<˜ YæÁŽ`æ/…^*§åëÿàŸÔÔö”ͺ®þd:~Á9·Ñ/ ®kÌf3Ìʳj†ºªblS¥‹¢1R"pH> šùFý È»9²¬2:«"¿yçîßèÝ?`â?#¢Ì{š÷¾¹ˆ™Ïîïï#„úÅÕÕ5ˆ*blÌV݆UU5Ca H)"iZ(,@m%6ž(ÄÇ ç7 ªètÞ9xïàØe“ÑøSÃÑøÙ~ðYQ}•™á°²²B?ûÏ[zt|üâéõÆkÓRˆˆ)!„€’4‘QU@ óiÂÌ Ô.±.Ä5Äb‚šBR„sYæá¼³ƒc>÷öÛ»_):ùÍ‹—.¾åvv>‚ápøôÿñUfZ˼G1ņ#’Z¸b ™©ùSçà¼kŸÞÃû ™w‹›6ö¥é¦Š¤ SÌàcÿÞ½s½Õ•ý‹O>yÍ3;:88ü­éd|~}c©WL LM³tŽ!Þ·ŠÛYÌðs€Ö’°c0ÿ˜÷Í1ïMT!€5޳ÛíboïΧßÚÝý–!<¹¿¿ÿ;>Ë.9À ´.Ed…‰ÁÐxji£6¯2P㉽e˜Þ93·þ›L "3¡èæO&[·nÝzÞ‹ÊÕrVîdÞ/j­ûKIÚ="¥Øð¨íT17ô ˆhþ©ÇN†ÌgÈ:t²¬‰ZæÁÞDmZ™<8¹è«ºú•:ÔêZ’¹¦««*¤}µ2÷=1¤ÔN)AU›”-dÍDÒ>T“z@ÕRcS ³ ê „`ÚQ•'|]Õ')¦›¡ª?bD–e ã®$5/d­6*jÖZÖ‡Ó5üSQ ˆšˆ©„”d1vƒ œ‚ “¤ï'‘k¾“çÿàœ{-Ôõó¢ú»1¦_öŽ×ÍÌEHJP¨$)T0…¨ÁTÚñ§ABm¿&R¨ÒÂ3'IpÌð™‡k£ÓRÕn‹È·Éð*ˆnpÏÃlà' üÀ¿aÇ@-zÅÕ®éÓ!„­é´<_ŽÇ.Å€”Ú|@܆æ¡1¨áEãÑ;YÅJEQŒºEqÛ1ß‘ ÷ã$á‡fØc ž¤wõ2¸ÎL׳,ËŠ¢X[_?µíØíˆÈ•Éd´5™”›“é¤7+g½BGTœ™1ÀÎ¥,ó©›uQt§«««Ãþ ‡ˆc|³®ë×'“əտЊwoÿ5ÜÕÖ ª`IEND®B`‚kimchi-1.5.0/ui/images/theme-default/icon-volume-default.png000066400000000000000000000102511254252253000237530ustar00rootroot00000000000000‰PNG  IHDR((Œþ¸m EiCCPICC ProfilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüºÇhbKGDÿÿÿ ½§“ pHYs  šœtIMEÝ *Fà‹ŒåIDATXÃí˜mlSçÇϽ××±ã$à$@j²Ò&IË:B*ШÄZ•ª«Ô‚Z¢B5¡jmµU í}Ú‡iÝ—!iS_¦­«ØJ«±FLUÕw*h¥ ’kšѰ•„b‚íØ×÷Þ³¶ƒ›ØÅÛ‡žo~ü\=ÿsÎÿÎyøÊ®ÌTÞÅ'z€M€¨|ÀEÀ.3†8pxF¶v~zY€ê‰ötÌ÷ƒ'¿ÝÄêÆjR®°û“1~úÞi¢©âi‘=×åËËA¥)Tº¿Ü^¾çzniÐ=¡±Êä‘¥ó¨0›ß<5£Î!ùT\¸¯|¹ÍóÜÒàå¡1îeˆÕÿ j9ÜÛ<·,©7¦ÔÏ’AŽ'V¼x‚‘x*]å+=˜ºâôEkÎ ‚ G88 ¹ÆË{뿎í 힀Wh½s1õ>ƒ[w}Äþ3ÑÿçZ÷`„çÿ.¸²ˆ$×~¸lë[ƒe­e`(`µœÙ(‚…úB*1Û{¯¼¡HW›LhšL¶œÿE¯P^ÍÈÁ5óôc"Îæ³ Hºt¬n ø5Ôä¤j¹B8aãÑ"r\.$¢)—Ås¼T{t<9ãEÌvKާ@S—:„+¬j¬ÆÌîUtÜøûŸÅ¿Î®k´ç’Å]/ôÎßwŽPÜ–gí-ÍJ©ªÜ MÏôqzÜC%+<ÜØÎ÷÷œâõ~s ËáöE5l¾!ˆRŠ7þ}‘õ»¹J_eêý&gþÆTêêÛ{c‹ýü<4§ò­w7´9yUüj×òѸ-î4ìb¬k«C<’r¸kQ½]KXÛ=À냔GcGß?þ9½:Äo¤3³°ŠSß[Ê/W„ÀÖeU.Óit2ÎH.¸ËêIgFï.©ã©Ã£<¶ª‘®Ö ËþÒ(=í§2.ùû«½ÃX¿îl`Ž©óøŠ›Úê1UZ ÅŽtZ)òº©ÖÇíT;Ža‰ ¤ÀpghüæÝa6¼64ù}KµÉµUfIófÑ•Rˆ7×VðÁÙ8®íæÌhÓ‡;%‚Ò5vsß+C3¾L—tÇ͂쾻™k!º’Y“)äÈþÖ5h­óa¨™UX£ÄG‡I¿[¢«%ȶÃ#üóãñ¨u‰÷ U&÷´ùÙ²´×úÒiŸÁ¸^œHò€D`im;×,"yǵ|rÞ¢?G)¸)èãº9^ÌŒ3_˜é¯Ú¸•iŒx•¢m®—¶¹Þi>– ð”ÈAÉß ‹€T1MW²ÇL%TX¶ÐIÌZûí O0aKÖ 0‹8áº4=ÛOç?à'ûÏ”Ü/|F矎Òòç~Æm—LzSÅÔWWJÕù ”Wc¾ß¸, •™F˜´½Ê«Sç3ðhJ•™4_V$c@½WSo÷t-¹÷|ÒášJO^`nÆ5€*pÏÍ]ÿÑÍóéj ôêh"ƒÀJàd±˜ýMÚÔ^g-¨ô$E –r̤#Fî¡…€Ép*O³ÿ[®ÈÎçT–VÙÚ¹ªØ'àz`Бyþͪl6#™Èý^¶vžá++³ýêQçó‡³@IEND®B`‚kimchi-1.5.0/ui/images/theme-default/kimchi-loading.gif000066400000000000000000000140451254252253000227410ustar00rootroot00000000000000GIF89a10çÿ@C\ I9CGMU7 8n14= @IVZ>asC6 ˆhn%L•— m‰t€œ3 4 *^ž+E‰o 8#%„—390_56-=/3¹12“©O"*QMÇE#E4;D(>8L( = ¡¯6 6]Xm¤ª#7$@/%*5+¯±ß'8Xã ®¸:B™ ŸABIñ/?zýL_(aü g+4ü(F3KESGý/M6!ÇÒ-=?• 1ARAmR4;_4&D-ÁË!CJ¸ Ń*; FÕ3NZN=2T=,Hjl:l3jTbx95GQ(R :I9/O 4M(*Kd Q£v>)XF;lB2hV·Y¡_gT¡Uƒ%a]µ9Thexþ C*\g‰CM)hmŒKcÞ6µ_²gTAAa1b»nƒ:^yž;°GcAkÉfÍ{ tŒ>m”I”ù2RpÏkÍÃFWtÛ}‰"uw:k›œ[‹+o¬³E½¨YDou‚˜A|´[# záŒhMºbBˆF†£k94Äe$ôQf’¯ ’©;„ÅK·dƒ\™©P‹Z›·Ùbx £Òo« Ñ]Ý™£¨p®Õt×t,¾yJÍiÒ¢½UŸ%ešCO”Öðv,ä|,ïz#åt…õoˆÄ‚c ®Ð¬Æf–Áï€é&·ŒYúƒ L¶ *Âj­(õ„-Ò~Ô¼Þ:¿÷‰ ÕEú‰(öŒ&JÁ ß[h©Ùy§ÇZÂ&h¿g¾*ÐŽØð–4x¾iºvu¾,áŒãë›`Œø@@€ (` Á#~0yƒ‰IBÉ©Á¦Ì*h,V¤KŒóZ°—„Æ’È5‰-A+JºSɘݻ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mz`@!ù ÿ,10þÿ H° Áƒ*\Ȱ¡Ã‡#J<ÂÄ‹?4P  €G>`Œø@@€ (` Á#~0yƒ‰IBÉ©Á¦Ì*h,V¤KŒóZ°—„Æ’È5‰-A+JºSɘݻ Lx`.bÄp‘£°B8n̘sŠã„ÇR…êh ˜Ëß ¶‹ 7  n#&Y­L© “†-›®S± ò"†­¶®ÜGíêmY3àÿ‘¢ÍÚ5äo:1«mír0†Q‡`Œø@@€ (` Á#~0yƒ‰IBÉ©Á¦Ì*h,V¤KŒóZ°—„Æ’È5‰-A+JºSɘݻ Lx`.bÄp‘£°B8n̘sŠã„ÇR…êh ˜Ëß ¶‹ 7  n#&Y­L© “†-›®S± ò"†­¶®ÜGíêmY3àÿ‘¢ÍÚ5äo:1«mír0†Q‡`Œø@@€ (` Á#~0yƒ‰IBÉ©Á¦Ì*h,V¤KŒóZ°—„Æ’È5‰-A+JºSɘݻ Lx`.bÄp‘£°B8n̘sŠã„ÇR…êh ˜Ëß ¶‹ 7  n#&Y­L© “†-›®S± ò"†­¶®ÜGíêmY3àÿ‘¢ÍÚ5äo:1«mír0†Q‡ë¬Ã©/"¾$ƒN?5b 4¨ªjW= Årk5ììC 9ðÀÃO‚ÈŽ!ù ÿ,10þÿ H° Áƒ*\Ȱ¡Ã‡#J<ÂÄ‹?4P  €G>`Œø@@€ (` Á#~0yƒ‰IBÉ©Á¦Ì*h,V¤KŒóZ°—„Æ’È5‰-A+JºSɘݻ Lx`.bÄp‘£°B8n̘sŠã„ÇR…êh „$Hp !ø°a»HzcÄ"4ô¼˜4fµ2äPdΜ:] & [6]§ Ö¨#IÒ"<˜ó"†Í¸®‚U ‰ª4i‘2Á£vþU϶¬Á*‹¶wLˆTñlÖ®¤ÞÐà7˜·vŽ íÜÒ``t2Ì~┇!•èŠ`aˆ`A›4(I ƒ°¥Ã@ø1“ |ý$É$ÊSk¤1Ð)Ä8ãŒ5ù¤Ì$Œ<œS…™û„ˆ×>4HòãÇŒ¨‚*€ÁK¤Ã{–$YB÷IJ!3,èðc‹_Ná¦0eVAc‘Ï]b¤XHnd±<Í`. %™m$M¶D٢Π% Ý©Šdl)’ Y¢Ü:heiE$7¢dqN] ™Ê«Wnni.bþÄp‘ƒ&òÞÎá¸1cfÌ(!mé^ýXªPƒ $ôC/ÚýóŽ0ÃìB oDÂ"ˆ AåÂIÿlCŒ4ÌÔ’‰A1ÇutH…þ3Œ4Ød£Ë)ÕP‡$’,‚&)Ä 1Ø´¨KAU"J%“,¢L޲KÙ,Ó AU,2d‘HD),fcÍ5P2¥!U ôF'Ì´hÍ9‰!$‘t& c¦8åaH%lºfqÎYÐ&xJÈ )ê0ИÌd£%šI2‰ ràXài t 1Î8cM>)3 #6šX`!ôN<ñpzP:‹ÈHþE°¡"¦¼bQ0xÈk:§H)ÀÐÄM+›Ø!g,µ†)Ñ„ù̶ã,C: aJ9ôL;Ð ÁpÇ/åȳäJ±Ð æDƒ D3N¶!ÑDe|¡EB'Œ` 2øn9øÄûÅ!Ÿ¬ò‰_AP 'äë A8À Ĩ€N945áˆ/Èt¼Š#e4ÑÂÈ!Œ0Ä%Eü òŒ7ߨC«PcsDz\ïeÐò@2°Œ -/{Ž?Kùb35û"‹ÁŸX¢ .aqD#´ØR6ÞxsuëÜœŒÓ«°Â ,è„E´TãöÖóh§Ï:ëŒí‹/É ÓÏAØÍÛqçXC±ø] ;ûh«9ðÀÃâG^P@!ù ÿ,10þÿ H° Áƒ*\Ȱ¡C„ Èð°bà  HÀĢǃàÀ(°àˆ ,¤üˆ`d‡ (PlØ0Ób†‘AfE"QÏŠ $ùñcFNAGfXÐáÇ–¦œÂE}ÈBÂ,W§m­¨¢Ã–([Ô­ˆ$H–(·Ö²½%‹ÜŠdvÀ½[‘®9”9\¸ˆÃEŽnÕ¦„ãÆŒ™1W X„´åoÏc©Bu4 B$8 ø£WÔw†í"èADˆÐÐc`.N[·“ƬV&ƒŠÌ™S§ "Ûc‡IÖMש‚5êH’´&¾¼ˆac®«`C¢*þMZ¤Œï¨]Û³-kF°Ê¢ðãùþ#Djy6k×Ú‚oHþ›NÌ0gÍ9‰žxtà # 8åaH%ºÂW >XÐ&JÈ cé0ÐÌdsI2‰‡r\Õi t 1Î8cM>)3 #ÕU!ôN<ñàxP:‹ÈHE°q”"¦¼bQ0xÈÁd£¥¤H)À|ÄM+›Ø!g ´†)ÑÈçh¶£æB: aJ9ô¼)Ð ÁpÇ/åȃ€J±Ð ‚Dƒ D3NÑDe|¡EB'Œ` 2øÁg9ø4úÅ!Ÿ¬ò‰_AP 'Tê A8À Ä ¨€N95áˆ/È亊#e4ѯ!Œ0Ä%µú òŒ7ߨó«P#m®²ŒéeÐAì@2 ‹ -ËzŽ?(ù"-5¹ú"‹¨ŸX¢ .aqD#´ØR6ÞxsÏLëL›Œº«°Â ,è„E´T£ð½ó¥Ï:ëüë‹/É ÓÏAØÍ ¯UC±h\ ;ûØ™9ðÀÃÉ,·,P@!ù ÿ,10þÿ H° Áƒ*\Ȱ¡C„ Èð°bà  HÀĢǃàÀ(°àˆ ,¤üˆ`d‡ (PlØ0Ób†‘AfE"QÏŠ $ùñcFNAGfXÐáÇ–¦œÂE}ÈBÂ,W§m­¨¢Ã–([Ô­ˆ$H–(·Ö²½%‹ÜŠdvÀ½[‘®9¾ݪÜÒ–¿„ ’ ÁÁ½$1A„ =æâ$y ‡"sæÔé‚Hsg5êH’´¦Ó«UiÒ"e° VYDÛvnÝzú=PÌìÚºÿ—ÇP%ä®–ÿÛô\R AcuT”4ɺœ×Q×þ¤y¨l£Ö¤£zT1Ý"9ÚasT‘©Wƒá‘#¿‡ã”Š”ÌGÜ´²‰bPqJk˜t©á`;ꀆ)åÐÓÙ ÁpÇ/åȃ$J±Ð &Dƒ D3ކÑDe|¡EB'Œ` 2øb9øÄøÅ!Ÿ¬ò‰_AP 'äè A8À Ĩ€N95áˆ/Èt¹Š#e4ј!Œ0Ä%Eù òŒ7ߨó«Pcg—²YãeÐæ@2°‰ -ozŽ?(ùb'5]ú"‹‘ŸX¢ .aqD#´ØR6ÞxsÏLëÜ™Œ£«°Â ,è„E´Tãê¦+ó¥Ï:ëŒê‹/É ÓÏAØÍ«±®UC±øZ ;û@H<ððá³G!ù ÿ,10þÿ H° Áƒ*\Ȱ¡C„ Èð°bà  HÀĢǃàÀ(°àˆ ,¤üˆ`d‡ (PlØ0Ób†‘AfE"QÏŠ $ùñcFNAGfXÐáÇ–¦œÂE}ÈBÂ,W§m­¨¢Ã–([Ô­ˆ$H–(·Ö²½%‹ÜŠdvÀ½[‘®9¾ݪÜÒ–¿„ ’ ÁÁ½$1A„ =æâ$y ‡"sæÔé‚Hsg5êH’´¦Ó«UiÒ"e° VYDÛvnÝzú=PÌìÚºÿ—ÇP%ä®–ÿÛô\R AÒÿIšd]ÎëåÊ&¡1jMZzºErµ)Â&{0asC6 ˆhn%L•— m‰t€œ3 4 *^ž+E‰o 8#%„—390_56-=/3¹12“©O"*QMÇE#E4;D(>8L( = ¡¯6 6]Xm¤ª#7$@/%*5+¯±ß'8Xã ®¸:B™ ŸABIñ/?zýL_(aü g+4ü(F3KESGý/M6!ÇÒ-=?• 1ARAmR4;_4&D-ÁË!CJ¸ Ń*; FÕ3NZN=2T=,Hjl:l3jTbx95GQ(R :I9/O 4M(*Kd Q£v>)XF;lB2hV·Y¡_gT¡Uƒ%a]µ9Thexþ C*\g‰CM)hmŒKcÞ6µ_²gTAAa1b»nƒ:^yž;°GcAkÉfÍ{ tŒ>m”I”ù2RpÏkÍÃFWtÛ}‰"uw:k›œ[‹+o¬³E½¨YDou‚˜A|´[# záŒhMºbBˆF†£k94Äe$ôQf’¯ ’©;„ÅK·dƒ\™©P‹Z›·Ùbx £Òo« Ñ]Ý™£¨p®Õt×t,¾yJÍiÒ¢½UŸ%ešCO”Öðv,ä|,ïz#åt…õoˆÄ‚c ®Ð¬Æf–Áï€é&·ŒYúƒ L¶ *Âj­(õ„-Ò~Ô¼Þ:¿÷‰ ÕEú‰(öŒ&JÁ ß[h©Ùÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ!ÿ NETSCAPE2.0!ù ÿ,ÿ H° Áƒ*\Ȱ¡Ã‡#JœH±¢Å!ù ÿ,&ÿ H° A‚Ü,˜°áBÜ*|H±¢Å‹3jÜȱ£G!ù ÿ,-ÿ H° A‚Ü,˜°áBÜ*|H‘¢ÃŠ#bü7cÇŠ7ŠI²¤É€!ù ÿ,5ÿ H° A‚Ü,˜°áBÜ*|H‘¢ÃŠ#bü7cÇŠjô8dÉ… O¼¸±`@!ù ÿ,9ÿ H° A‚Ü,˜°áBÜ*|H‘¢ÃŠ#bü7cÇŠjô82£Dˆ%Q:l˜R¥Ë!ù ÿ,=ÿ H° A‚Ü,˜°áBÜ*|H‘¢CˆNœ¸pcÆŽ9äx‘aE‰QJÄh°¡B—#=¦ÿ H°`An D˜P!Á†F\¨á@ˆ¹ ĸPã?Ž=‚|èñãÈ’Mv¼¸eK‹ ]¾œ™Òa@!ù ÿ,9ÿ H°`An D˜P!Á†F\8q ÄŠ'fŒ¸‘cGn-‚<8òßÈ ¦TÈP`Ë !ù ÿ,1ÿ H°`An D˜P!Á†F\8q ÄŠ'fŒ¸‘cÇŠ !rÓÈp$Æ !ù ÿ,,ÿ H°`An D˜P!Á†F\8q ÄŠ'fŒ¸‘cÇŠ CŠIr`@!ù ÿ,&ÿ H°`An D˜P!Á†F\8±¢Å‹3jÜȱ£G…;kimchi-1.5.0/ui/images/theme-default/loading.gif000066400000000000000000000042161254252253000214760ustar00rootroot00000000000000GIF89aõ!ÁÁÁÂÂÂÃÃÃÄÄÄÅÅÅÆÆÆÇÇÇÈÈÈÉÉÉÊÊÊËËËÌÌÌÍÍÍÎÎÎÏÏÏÐÐÐÓÓÓÔÔÔÖÖÖØØØÙÙÙÛÛÛÜÜÜÝÝÝßßßâââäääåååèèèàààÑÑÑÚÚÚíííõõõéééðððáááÒÒÒÕÕÕñññ×××ëëëãããïïïÞÞÞìììÀÀÀ!ÿ NETSCAPE2.0!þ-Made by Krasimira Nejcheva (www.loadinfo.net)!ù !,”Àp*•ˆÈ`Rm6!€ ¤.Nè I Š'…J0¢¡„ód" …€$B„¡Ë iC ƒCgB I “ H’”C‡B_ˆ&‡ pŠ%$  e BS F(hD!Ê &ŠÇ_ÌJ ÐTÅIA!ù #,ŒÀ‘p8z<ˆH¡„0ÊdF…Ê )à|šOÌjJŒ< D§³EC€$’M Pð '" w {BGHC I‰‹H‘C IuHH ‡E    •B •IGF# §H ^à ÇI#ÏA!ù ,‰ÀŽpØq8ˆHaDÈb '‚dG3é4;—”´È94§Rg0–H å@D2ƒÈ¨"H6”è° a DGD C &€H‰‹„’C IDŸD –  l CŸ( iµR& » [‡ÂÆ[š–DA!ù ,ŒÀp¸a0ˆHai°±T6IRH25ŸŽ€lšCå“y„ÛÍã²P‡#(µ&CHGJdNHGH C%I *%‰‹H ‘’CIH ILB & ¦iC  ¨H‡» S¼Ä–SBÎDA!ù $,‹@’pHZ,ˆHRà!¤P„‘¤ò!9I´Ø1L&‘Ù $†Áð°<‰PЮ"1 XP$! CcI ƒ„RˆŠLBHGC  D!B  #BŸk$H $k¿¥RBÆ$[CÀRA!ù ,Š@ŽpÈQ(ˆHaCÀ‘H„¥¤òh>%)'a)˜L ƒÃ.Àˆ¢PpPŽMdؘ<DE4AIC †I,‹…‡‰‹,CIGD D'C %-H  !sdH –+ˆI§ÀÅZxIA!ù !,‡ÀpB ˆHáB„@2dj„šW‹tQ„RÉÐYà ’@ƒTF’²1 ˆID ‡I †ˆŠzvH D H B† xHj* 'uS!)S!‰!¿BÆÄbSA!ù #,‹À‘p8:ˆÈ =#A#©ô(œÐ…:2@GÁ’6»€q ÀâU" RÒ I C‡gD †ˆI‹ CIH†˜D"C€ H!  Qœ+##ŸD$#\COTA!ù ,ˆÀŽpØ)ˆH¡AÈ`I&¢Óì4LÑÁ!hPÓÀ…ñ$(aA±$ –‡À>H*ŽBfI& ‚„†ˆŠC ID!D}#l]$%B}%' ,,Y)·QBÀYC»IA!ù ,Àp¸!ˆH!°I$63™(4Ÿ Ï9PDˆ)(†@p`¦ÅpN>& $ D…%‚ I%*„H†ˆC I cD'HC-% BB y|C&$IBGÃ%ÈD ÈA!ù $,…@’pH ˆH¡@h00“±IB0FRÀh  ¬Œ" ($ºžDÚ,‡FD .$IGBrI‹…‡‰HŒC I aC Iw¡M   ‘" P$$$}IB½„¸ ·IA!ù ,Š@ŽpÈ ˆHΠRà49XaœÐB)FB‹Á   )­Ò`#)Ã0¼œ2ÓaÂ@*"I]B,†}H ‹…‡T‹ MBIyB"ƒB C & C] °&[I¿¼%BÁ£ÅB ¼A;kimchi-1.5.0/ui/images/theme-default/logo-plain.gif000066400000000000000000000031011254252253000221120ustar00rootroot00000000000000GIF89a80çÿ@C\ I9CGMU7 8n14= @IVZ>asC6 ˆhn%L•— m‰t€œ3 4 *^ž+E‰o 8#%„—390_56-=/3¹12“©O"*QMÇE#E4;D(>8L( = ¡¯6 6]Xm¤ª#7$@/%*5+¯±ß'8Xã ®¸:B™ ŸABIñ/?zýL_(aü g+4ü(F3KESGý/M6!ÇÒ-=?• 1ARAmR4;_4&D-ÁË!CJ¸ Ń*; FÕ3NZN=2T=,Hjl:l3jTbx95GQ(R :I9/O 4M(*Kd Q£v>)XF;lB2hV·Y¡_gT¡Uƒ%a]µ9Thexþ C*\g‰CM)hmŒKcÞ6µ_²gTAAa1b»nƒ:^yž;°GcAkÉfÍ{ tŒ>m”I”ù2RpÏkÍÃFWtÛ}‰"uw:k›œ[‹+o¬³E½¨YDou‚˜A|´[# záŒhMºbBˆF†£k94Äe$ôQf’¯ ’©;„ÅK·dƒ\™©P‹Z›·Ùbx £Òo« Ñ]Ý™£¨p®Õt×t,¾yJÍiÒ¢½UŸ%ešCO”Öðv,ä|,ïz#åt…õoˆÄ‚c ®Ð¬Æf–Áï€é&·ŒYúƒ L¶ *Âj­(õ„-Ò~Ô¼Þ:¿÷‰ ÕEú‰(öŒ&JÁ ß[h©Ùy§ÇZÂ&h¿g¾*ÐŽØð–4x¾iºvu¾,áŒãë›ë¬C¶/¾$ƒN!?5b 4p˽m= Åòw5ìì³-DäÀ?‹G.¹H;kimchi-1.5.0/ui/images/theme-default/logo-white.png000066400000000000000000000232271254252253000221610ustar00rootroot00000000000000‰PNG  IHDRì0/–@ pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-Û cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFÂIDATxÚì}{˜Õ™÷ïÔµ»úÞ3=÷+3̆a.îWÑhEI Æ DÅÕäñËFã ÆÇx‹It%×ÏO£Ñl|X]²nÜhVdFD1\ä>Ì0æ~é[uWï>ÕSÓ è³âRï󜧻«êÔ©®:¿ú½ç}ßóB)Bp–BpVd€ˆPDÙg€Îês¦ú¼©@Ù±:«§™~k¦cÎJŒÿg‰%ÿD8ÇãÍ`•Xílì7Ï@¥²c Ðq&° ¦ú"ûn€˜²¢±cõO˜€o!Ñ °çV€Âqœ’Ÿ“_æå¼WÅûP¥SÊ‹>¡1&GßhßV—gum è3 <Ç áxž º=Ó´ˆNiŒß´j팹sé¶Í›­§h‰ØQÀjfH™Õ À^Q0ÁOÓo$=|µM•<d~.Ë9N89ÓÿÀÉÖ“0UaE I’$eeWØT=Û’ @ ó´)"p'Z::ö†#‘ ‰Q5“Êl‰%`?Cøvµ°•—ÏSº· Ržé 6¸1¤F¼èˆÝ2½<í¯l}ñTÀf™…Š{±}0?«æ˜ND5®Ç½q_55ðN¶íÈá© JdT8 ¢¨zÒáü+†ÙuköÍZb‰ØQ@ —✚k|N<…Î"x¨¡x “×V¼]ôíÂßyÇ9ÿ ÄXP»ïÇ?ià›Û¯(«¬Ý3mÕM¿ãï¶³±0ᮩ­Ü`cçë[j¥Êò¿W6¼0[¤Cèè‡6yvkÅ¢WÝe! »™,±Äì„ .ÉmsÄ\&üBİšÆäÇ+ÿT´:÷qÁ.ôˆ°¢оÿÁ·³Ç•|:ïþ»~4qÉ·³vcÕ¤ÐWÎy÷D~ƧáIã¾ïúË;ÓøÖ.f74ÓÅ—¿ê®¿ÙtÞØ—9~%„ä áWVôbØïËpHCÂ-5#±z<€!Vâ¸0"±²Ì0ÀI²áDøs®gÿÉÅŽ2îµb=/hÀ’6Ó²"8dWºiP8Z0†Ìï¦\pcÎzÁ.ô°bB}}Ó&Yv9Ã5³çÜ3uÉ·ö±Î ›Àš/Œ‚êʱŠÒŸuº”[Kl[¶ _“ÛáåÍÿlŽC>_™~†ŽM¸LPË:òQvÌ)Elà+½”Ò¯ÜFq( ”>Ëëëë÷¦3ZU'€jìYîpÀ ¬Ð¯T¸Ï¯šóãt€„‚£×͹À‡Dp%wü³ä[ó` P]gtÎ’E¿üÁkßa@‹²}AVB¦’Ü.Šâ`Ί«öùÿáÆÝʘÜ#z!C„"BŒøeÁt}_DU. ”>D)}açΕìz("cL}ì±Ç.£”þŒRú"¥ô*]Òî»ï¾Ë"‘È}ôѵ‚XM6¾Ô××°{öy( €¢çŸþÚH$òÔ¶mÛ¦±çbù. †M+‡ë0ÖB¢"¶ˆD êð/ò|,ç 3æSÍ` Ïš?O›5žŠá‰†_6© Ï™:…n}o'€óºÝ’Cwf¶-S‘=^‰ÊšìÔ9Òï°IZ0¢"…Éì…’¡ŽM)•!*€|õ‹/®¸í¶Û¦±C^ð ¥T&„œ¸õÖ[ÇȲ¬TWWÿ=¥ônv_/ƒ˜Î^æç͟ŵE4­\¹rLŸ>}¥ôÓ}·äQ‰h&ÃÓå8sé-]-zMü€Š4JálPöPŠnö¢šÀI12þ×<}Ž2•,ùr¨WR'Æ£«H48UìëÉV9* º¸îloþ¡!jûskëÉwZ»ú:Mà4Tìó+F騳NÎÏϯxî¹ç.—eY°Àݦÿu0üÀOü‘`±¯y¿Ðà <ÂúƒjAæÂ¬Á¤"†gÔ×`Ä(=¨„Þ ¥CzK\Ñ8½Åî± ™˜.fbO˜@DRŒÙõ“éi Óâ-6·ï_ýöÌ÷}Úà7•øÐ41Úç‹ÍÒÂcƒwyN±_GAÁãŽ{£¿ÐhË<=ïË @ €‰¯½öگכ  Àu¦qzŒµû€wMÌ'„8øØýŒ°ó)ÌxE( ÌÆÉ^ö=Êöõ³ýºÙØCáØqVöìT6Î4 bdÃaŒ’Ï®MMmÇô¬xXÏ~[~ï °Fp¿€Ý›È€äLH\Ð#m]­-ôܪz#Ò^ª#HQOõМ¢¹Ó§Q=F<(êT”ãÿùλM¬cnxõÿCÛÖŠM;ê‡t GUÑÜÝWq,þgÿÄqÿ´÷XÛ/N´´õâËuõPBˆ@ý³Ï>;µ¶¶¶‚uì›Ù¸5@%‰°¬"BH-â~V4yê ºÙÿËÎîS3PõÈ0ŽÕ±3°°—}BŒ È˜,€rVGaû‚ì¼{˜‘(Uâ„j Øu ±óï3Úa×î0•’ à0;ß {qX¨¹@ŒN#&¦WãÊ)½Ÿóäý–xò6(Y%ÔÔO¹@ì_7nЧ¨¿ ¦#=Íý¥m-ífË/@gOMç6|ƒÎ›Ü@ç}c:7c&7=QÌ0«~25 ¥Ùþ~rÌL)対î{Ö|ÿÚÀŒ¥›k2 f;±pb®,á0ßÛrû´ê’ŸæåçI_2»ÆÔÝsÏ=Snºé¦™lÛOìfcÝ(!Dg÷+°fÍšoRJÿ/¥t;†3løo¿ýöÙ”Ò'9²@æK/½´ §§g5¥ô[[[×®^½z>€f¬]»vÁÁƒ¯£”ÞI)]»gÏž;î¼óÎ Ì2{! ô³\±jÕªË"‘È-F½®®®›ÛÛÛQJûSUØ={ö8øÃÎù裌vÖ}òÉ'F;S;N%”ÒßPJÿ²sçΙ»^˜ ›KÜžõÃæˆ{ ±{A;z£j®®„Æ,¼2û€cwÜ{Ƕ—º^ÙÐö –wïî,ÊÎËúÛÀØyPØA†Âg…£­;w™^œÙ2=ó’©Í/·µÞ<5óÄ¿eö6V8}2.?²Ü=ðv6Ý,O¯;ðüZ~à éŠ:ßI{öìq®\¹²áÞ{ï]À6=`kÄÄv ÙíöÁ$5Sgmk²,‡Àëõö÷ööÖy½Þ…6(ÎÎÎ.~úé§×ùýþ'–-[V][[;›½¶˜3a„šGy¤¤®®îÈõ×_ßÌþS€Úüüüé7nœßÐÐPÆš=Θiii³c:˜&”‰'Žûõ¯ý.«-&UUUM~ä‘GÆ644^¾|y‹éaf„ÃÈT?–|Å ;Âç:H¼“åŒRxÊfÀS±Rù<´9j‹ÃÞqßc,ÌW.÷Oñus׾ΚýÛ/˜æÖ·ß&ê@ºNÎGY¥©åÛK®9ò.W¶¡[WBD‹Á-g»1-+L¦ûÚo¾qÕßRJG¸¡xÏYº»» }ôÑk™‘i3€Ç0ìvÒR®S“e92ŠÁJ“$) ~¿¿Áëõ^É 8טA)}~þóŸ/b`}À®P à(Ïóîk®¹æ»”Ò û_…Æ¿úê«sXûØù¦³±õr$‚%Öct×ÍC~`k§ À.žçÝK—.]‰„K곬˖\@€ip±ùD{î$9õ res&@÷•Ø$“¦Ö å,È\çpÚÞqØñk0Ôþ0‚1ĵÓáHSXwvC­9ŸSÒ]3sÖôI˜’ÅW¶6¾þ©žÑ‰ÆA)…ÄqÈIw¢ÞÕ\Z•%®0u,_`²ûœ9sVddd±Ÿ5ÒM>àó=í ÷WëÆ_ŽãŠp­Ç°[lß¶mÛžžç—šþWÑ-·ÜR^WWWÎÀzsClŒi”½ pö”kx1¥Ö-[¶¼l´C)`…}~mTb˜£q6àΧø@â1ÐX ¢â£•î0†£•ôK.kèF"âç4ƒ%€¦é )Já9ðv'hx(+ÖEæ4ÔÒ­&]H&#‹@ø÷×^˜™µø@¾BËòì:xžB”dä+ý|•Ò?À8ÌŠ£H-Ñ5ÑhôY+˜‘&„ó󱾯@&„dè2p^ƒ)œ“’]SSÓñá‡ûx€{õêÕUlÛ&$¢­"ì¼ñmɸwfyÕt¼ÊŒJGL×±À_-µ÷ëÁ°æT¢ªÀsÐ8„Æ´ÀsjfFf+Ff74ØÐp¯P´¾¬>1˜Le$@ r"NmBÚø>´ñ}0Õ<ÿÖð K„#C­íCšÓ“>ØdùRW1†32¦úÏy à.·€,˳ZZZÖ áîΓ½;1œýÑpɘアvïÞmÇÜ:zyyùX¶m cÑÈ(/ãù¤þÝd£ìžúRú¯¿ù¢¬€1‘Ç€–bÂשŽx$„ š›ŒNFóƒ"Nir‡*ˆaÉ‹  =YF1~‰&àòøÎþP¬;×#±a7/á¼üP†‰ù/¨ÚÝÏ:íÎÞÞÞ' ''çÖ 6” áB9Õ15ÀƒO’ÙÊÍ¥°£aŒ‹°q5pÅΑ Gkg´h7‹a¿F sŠúMi Gu‰#Ñb ‡!Æ0Šÿ5·|2íà4tpN‰ÇC襽„¡§š­\‡ß;N02 o«Á–T†3ƒQMˆë€ñ>!D„'Ó¦š@¾ 1æ¢=ôГš¦5B¼+W®|˜Öv/…su;‘QžU¯é·Û¸ïä ¬-ùú3¬ –áˆ7 РªzâõNT]'‡û«ßÞ²EBÂe†ŽBÐz`7I¢£ŒÒ‡)tèÃÜd,³¤ˆrÖØ@A ;àÃp“&è±Ju`ÊÞ5â°Ÿò‹²+LCüâ¿8±wïÞ;Àf³Ílii¹Å¤“ÿágÕÞÙÙ¹‹ýžHáÙ$ž ‹ñ,,_ kdÛWÓ¸çJœC'ƒ‘„uŸ#Ç4 ÿ¯Oš–±!adÿäøîäÝäóG£<â‚[ô¤2 '¢èñù¾•Y˜v¿/Ío3ÆÖœÍqX"<¡ IDKÅàvÿ€IÍüÒ:+¥T­®®þKww÷zC5~æ™gưq(ÿ?ZàD[[Ûvv]?xê©§®BbjßD$\A‘ˆ~Êb/ ´ ÃþÛ+Ø17·çI' cHÕA ð˜To¸á†‡¿–%”Òîßÿþ÷ëu]?Nñ®Zµê™ûî»o1€K‘ð«.0cÍš5SصYcÑÿå€MØ–Bʲ•§—Žë™‡1xž€·Ih<Ž ûþß.Y¶,3e ›œ…“;¾†žMãa-†¾ØÐh»HGGǾôì´BÉ©;®ºnY€è‹/¾¼_˜ò;ªoüÏpñå‡Õ²«‡g>ø¡jÅŒ´tŸ+`;Mß“@$„PJ)ýÕ¯~ÕÒÔÔt?°SJg³1eßïï¥nð Û„u·ó û>k?÷è£æ8îZÇxžw¯[·î®`0x{SSÓ’æææÅ”Ò§Ö¯_¥4ŒDPÿù´ùœz–|E"œ®&CûøÕ7\)Ú²åžü,yüØM=ÝQAuúñß'»./»ÿxé•‹~óõM2N;¾†¶ìÿ0ɲyå“G€fûÖͧ=øöÓ­¡>4Ô¶ò#ÁŒƒ—dfHß½ã'wï@–|ûûÛOÚ{$nËívΙ?©]²9‚™:æ\çmî4}S^f`x‰h¤%6PJÿÀÑcÇŽ}b:Tb@h¾úê«GÛôÏjo´ýæåR>F"y€ÅŠ¢Td#Lñ'Ÿ°SJû !çÚÇÎó™÷Ã’¯FHêr“ °æ%!…ÝŽz÷k‹_þ zë¦Æ¶ñ±Á! Öô„G=ÞïŠumw±m²@)ŠëÝ÷Þz½ËÌpÙe“hûÁÉ(Æa³újX‡©}6·Ï㬻bÒ½¤êÃeþú.ש™‹¾gÝ^ /¤Å›ÎÇð\\ó—g˲<†×ýјùbù÷Ÿ>;»?Fö j²«Îë$¤n'„¨¦{OSíváÒº)ëÿý‰_6pÛìv%glÁ¢˜^ÐÇŸª¥Ž°3­È‰@¥Îlà5HB:|JɧŠÍ–š{ØbWK,À¦ˆaÔ‰Aq‰šÛ›&•N€ñK­|ÒD·êˆþ´Um^¬Û#»O€¿Ð‰@©îb’ƒGL@ž§a®»èSŒL—jù-±{°ÆÀÆ£Ó—–~´7l!—•]@"‰%h„ô,@¡z|¶7Ëè;•ð Å›(dæ m¸fùÝs'Œï yò} wwï¸^͈pþ";¼vxsmp¥‹T8x7*Ò½•çóœÄHw“Å®–X€=hã´þ–'¦ÌWž‹y”mDdjB ϸœ<è/¢! xŠÒìÜÁ'.Ÿû³¹9ï±ñ­ÞêõG8gµ ŽR v»ç¢AÓè ¬ü ÜÓ°‰ç¸QçßZb‰Ø‘’\fchpëèì|åùm»„7%ý?Ѹü¨¨ë¨®%¢8l€,‚§.¸xª.S¸ïÞúšõ•^y›a0Z¸d‰~|è`y€XÆCÌÀ‹‰OqÄÑ#˜ä»êøœœï­÷Û¤ û]“., ±%“œK|FŠ5M ˱´ùhKîM^ùf¯zéÑÁ`NO($‡CA‘¨j×µ¸W#å>û±ëKÇl½"/°IâÈ †W¨š¾xÁõŸTíz!TÓËå¼pŠNàâì˜å]txEÑÚGK\¦z!$bdcgX+:Ç’‹°F̪‘M …bqû¡ÞPÕÑP4w_ßPº Ð+üîþºtO[@a8œÏH–Ýî¾Çs4ýøƒûJWðþ ÓKì#ŽíX˜uÃŽé—=—cO;jªc^O›:g}oëfX€µÄì™Öœ -Yâš.Õ˜Šk"GÀ9D‘*’ s‰,ù†*«bxõäêæ<ûĤŽü¶5û?-Ë–ý±YiWï˜éŸû96¥Ãi9Ã&f `-±ûÙ€N94—Ô$Þ£­ãj|7O“‘ˆ6ÂóT+`=§±«XK.F£S2üÏ´”C* Í`5'×MÇŒæŽIæBf¿c¬¾fbeÕ24Yb ðÿÁÐìžÁuIEND®B`‚kimchi-1.5.0/ui/images/theme-default/nav-bg.png000066400000000000000000000057431254252253000212600ustar00rootroot00000000000000‰PNG  IHDR2 iÐì pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-Û cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFIDATxÚìXË K°ÿÿËñ„ƒÈ>Ð)ÕN …î&d-%XÜ .h;è©í MïºÕ»éÝA—«‚Ùõ1P7ùÌ«ëŸú”Ľ§;èOz/9/EZT ÊA!{AÇPàɃي´§Xí2Š’&Yô2ÈœÂÌxygO™LÎ?ÜtªCeQ.ç µM©‚ ®8zxI¼ª·8âiÇÙ‰H±”@€¬ô~½9ðSë¼ é¥A3.Ää3wnt¦^£¹Öx68zI$(†Ù’‰ÐY§Šf…4‹0SVüÏ’ù¯ Ù#$J% š©9&  ÄÔª÷¬ÿ½¦z{jÝê" ½[ð>»i𠇚IEND®B`‚kimchi-1.5.0/ui/images/theme-default/thumb-guest.png000066400000000000000000000074701254252253000223510ustar00rootroot00000000000000‰PNG  IHDR&5ž pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-Û cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFcIDATxÚ´VMH\WþÎ}?“çøüÁÌØ`Ì8 ¥.Z* E쪄TRi#þd—!)4 ¡‹H»é¢\µéª.º´va) epUê¢Õ–FC;‚ÿ¤L} uÞ›{O>'ÒŒ˜÷œsÏ9ß9çv`hp@ Æñ‚løÀO`¨5Mó­x<þj0Ô¥”ÇíX!¶–——+WVVëZlÛ~3‘H \¼x±,@)u¼áAÓ4¤R©×îܹ£&''¿ÖMÓ|¥££ãõ«W¯–UVVB"Âó@CCÃÉh4Ú5??ÿnYb±˜‡ws‚ç‰X,Çã/èD”%"·Àá€u/ùõOø €ç“¤Xär¹\PqVa3ôäíq*•º;==ýS{{û¡P¨>N'“É/Ç ‰"ÓADRf·¶¶"]]]ƒápø”ß1¬3³`~LbÏó.9ŽóþææfR Ìܲ±±Ñ¸ºº>‚cv]WD"‘)e¹R*Ï@®ÀÅãñ3±X ™LÌŒP(íïïf³Y^°03¤” "0³ "¡+¥î»®»¼÷p0ÌM)Ã0Žìx7Jß±@é}}}õõõ=zÔTVVvæ f#Ó³D4 `…˜ÌŒL&óFiié%åäaÀf&“¦iv†aøÀï~Ùž625øÀ˜™|RÊbæ3‡“©©)³¯¯ïÜâââ?¼ƒAf.c檧éùvK™Ù`fÂnÄÏ*‰DB·,ëÃ{÷îe™™¥”kƒ™ŸL”žçš¯d2‰‘‘‘@MMÍ ¥¤ÿqa¿aÐ4-ÿ¯ÀÜÜàúõëH&“‡:ö<RJ¯ºº:ËÌäÇÁúú:\×EKK \×ݧÛÚÚŠ¡¡!Äãñ–ËÌS‘HäóÙÙY—™ÕöööµÞÞÞgV¾qãÆÆÆþwy Ô†ñIOOÏÂÒÒ33¯­­ýÐÞÞ~Îï:Dï@ã…hõéŸ>þ·ñÊ•+oߺuKÙ¶=]QQÑ!¥ LMMý600pwaaÁõ ØwÌú-÷ð Ç‚ˆÞéìì¼yþüùSJ)Yø Èår°,ëD[[[‰â3)emccc·a‚™111±233#ˆH+Üç†aétú—ñññº»»g:;;÷9&Û¶/ŒŽŽ~ÕÜÜ\±;[€rgɶí“%%%˲v·2™ ¤Ü?{¤”ŠˆÞ«ªªúæ V靈©©éûÓ§OjYÖ»Bˆ½ï €„gËËË_ÜÞÞ†išùËiš– ƒ˜YÛ`M±ê—Oݾ};âòå˨««ÓDœØ»Ðlær¹kDt³°'ÌøÈ¯¥¾7“¶üúþ @åWV1ây^i6›TJÍ3ófþ‘™/0sy1vè(«N)UJD/Q•ÿTúÀæS–Ë>ü7Æç§ïâã[ÉIEND®B`‚kimchi-1.5.0/ui/images/theme-default/thumb-host.png000066400000000000000000000117151254252253000221740ustar00rootroot00000000000000‰PNG  IHDR&<Û@\ pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-Û cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFøIDATxÚÄW[lT×]ûœ;÷Î ¶Ç‚ÁØÄ®“’hqDPú U N75m#Ôˆ4¥m$ÂjJ£¨ öD­„*5’ R I … Sµ8qB Šbw:~ žñŒ}gÎ}í~䨙˜±I¾z¤«‘fÎ=kï³÷^k 13þ_Ë"škP `1€zÕSï–- `À €«lÞœà× .`)€MMM‹zè¡ÛW­ZÕ¶xñâF˲b+¥ étº¿¯¯ï­^xáo½½½ÿð_ àš+&fž-sCgÛ é™gžY¿yóæoÏ›7¯Zýô !þÁjÍÌ fF¡PHŸ9sæÅ|ð/ÒÆ8×0KÍ%€:jkkwœ8qât*•âT*5222r)›ÍòÄÄÄYÏó¾ÎÌmŽã´Ø¶}¶m. œÍfydd„Ï;÷RSSÓ*uL}Ks‚€*k‰ÄÃ'Ož<ŸJ¥xhhèå\.·nrrò#Çq2Al`æf¾™#ÝÝÝ+”RCžç±ã8lÛ6g³Y¾xñâ+õõõËõ™òzà&€f]‡~9•Jñààà»w﮹páÂN¥»®û3'õþ,p[OOÏ<Ïcffß÷Y)Åù|žûúú~ æšì+€'¬ßºuëž5<<Ìù|ž …ÂÛW¯^ýO>Ÿ/ž9sæ›õõõk¥”÷ø‘aÛ«««wìܹó Û¶Ý ˜™9v]—ÇÇÇK¯¿þúBzz*6œÐ£tÛo¼±³¹¹yC<Ú²¬ZfþžR*AD0 £X(†3™Ì¤RŠ¥”¡H$RÇF£Q‹Å ¥œNÎóʯ ,˜Ø=÷Üs³iš7˜¦¹@?%?~AJyØ4ÍÇãñŽšššÕÉdru]]]{2™ÜP[[{_:~qæèêj¤”k„˜™*e.ÈÖÖÖF)%Þ}÷ÝÈŽ;:š-˺])…t:tuu%FGGzž'‰(`f"¢3ÇöìÙ³lÙ²e "ñInB„B¡&éðfÖ|€ÖW_}uך5k¾‡•ã8Ò¶m@D"„Ãa¥”rK¥’‚ôñËeš¦Ò ö¡ay˲²Ã0îB\1 c, Qå£ÂšFkˆè–J¬ID¬g½âµ{&•Rƒº¾Ï[–u*‹er¹\“eYwK)÷›¦y,‹õ~ÒåbÙ¾¾¾¶¶¶î›Îq×uÝ-ÌüfneæÌÜÀÌÖ‘#Gî.‹¾ã8C«¹Ð& Æ€ ~÷Èür–Ôo—ΑþÄ ÞžçÑò¥%®’átŒf’ Lë©ÞËÚK@’ñO¼ø¬Ä«Q0ûpŒ7,û2ú”ÖÍ}çIEND®B`‚kimchi-1.5.0/ui/images/theme-default/user.png000066400000000000000000000024521254252253000210560ustar00rootroot00000000000000‰PNG  IHDR szzôtEXtSoftwareAdobe ImageReadyqÉe<ÌIDATxÚ¼W]LU¾ó³3³,»l—mjÀ-lWhY`aAÐÐZÓ¦/m¤M4õÅ65¦ic4©/þ>é‹>ÔhŒõÅWI0¦Æ`ÒV–•¤IÓ¥â&(UÒýeg×ïŒ;“e;à¤wr˜;;sïùιç|çÀ•ËeöÇ_ˬzÄ¢=l£Áqãþ¸ g^hb a¤ªª?©Eu´T.Í%¦'™•á¯ßÅ83ÝÑØÃŠ™¦¸Én·ít:EQT*•ØÚÚËårj>—ÿó˓ӿªVˆV’rX”ùš,ÉA§ËÉl6ãyÞ@R(„L&óF&Ùe/YÙ›7ýµ¼^8žcç;·ÛTÜ #ëHS®m ä —ËÅð “eùÅøÁó[°Þ|²v€„b #Ž®Vhg$Yb~¿ÿÃxwŸ°%媋çxÖÚÒúºÃéÐ,5SlÁèSåémÉŠÔ¿™åµBGcm,Ö;ö_Ä‚’ZBÊ_¾úÚù?­ðïò³S§G¾À+[ó@5]Ý…ƒg.\¼P¢TÔ™ÏLHù;ï½}/ÐxËJ°Z¢b*Pc‰™É—[ZöŽ^ùæ[çõk×µãÑÑá#‡ÙÈÈ wADÏY±^˳bt ­ƒÈ…Üÿ+ "m¢Æ°zP“°>uå~xfnúi?ÐÑü ŸÑF$ÕÔK›Á2mãÚâcP6uK•AW¬ÊQëêê>À㛦i—ŸÆ†IÉF…GW¢Y+ІÐsµÅfëÈ|s)º¿Óg Àëó¾¯+ß,×·*/‰þÿŇҰsWº) <Ý’GØ%•JR¿§TCShoè^vwJhd”½elâõQêý¥æoeèÙÒÜÔt7D=ú½ ÞFôù;@?ÆÐ@6å y^p<&¸ŠkÅ=FôÆ{"Õ¹»ÓBÄb’ (nw –8vr0ªhx`_$œEn>ëui5«Õ<ЊùÕ…{ {&&~aS‰›™™¥ò¿YЦw³¾þ~ÖÛÛÃê½õã¨Ï×#*¯Ç!‡ ƒËËËžäÝ$›ŸŸgóÉy¶´´ÄÒP ¶ººj(î2𼡌:#4/ÔТW1—äZÀ«!c•ûò†å¸m_»öÑo·oQ¤¶W yÊ£sÄWµ,YÕ‘²%È,ä&dŽš³†ä]#rT~2ˆIEND®B`‚kimchi-1.5.0/ui/js/000077500000000000000000000000001254252253000140125ustar00rootroot00000000000000kimchi-1.5.0/ui/js/Makefile.am000066400000000000000000000014511254252253000160470ustar00rootroot00000000000000# # Kimchi # # Copyright IBM, Corp. 2013 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. EXTRA_DIST = src widgets jsdir = $(datadir)/kimchi/ui/js dist_js_DATA = kimchi.min.js $(filter-out kimchi.min.js, $(wildcard *.js)) kimchi.min.js: widgets/*.js src/*.js cat $(sort $^) > $@ CLEANFILES = kimchi.min.js kimchi-1.5.0/ui/js/src/000077500000000000000000000000001254252253000146015ustar00rootroot00000000000000kimchi-1.5.0/ui/js/src/kimchi.api.js000066400000000000000000001254541254252253000171660ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2015 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ var kimchi = { url : "../../../", widget: {}, trackingTasks: [], /** * A wrapper of jQuery.ajax function to allow custom bindings. * * @param settings an extended object to jQuery Ajax settings object * with some extra properties (see below) * * resend: if the XHR has failed due to 401, the XHR can be resent * after user being authenticated successfully by setting resend * to true: settings = {resend: true}. It's useful for switching * pages (Guests, Templates, etc.). * e.g., the user wants to list guests by clicking Guests tab, * but he is told not authorized and a login window will pop up. * After login, the Ajax request for /vms will be resent without * user clicking the tab again. * Default to false. */ requestJSON : function(settings) { settings['originalError'] = settings['error']; settings['error'] = null; settings['kimchi'] = true; return $.ajax(settings); }, /** * * Get host capabilities * suc: callback if succeed err: callback if failed */ getCapabilities : function(suc, err, done) { done = typeof done !== 'undefined' ? done: function(){}; kimchi.requestJSON({ url : "config/capabilities", type : "GET", contentType : "application/json", dataType : "json", success: suc, error: err, complete: done }); }, /** * Get the i18 strings. */ getI18n: function(suc, err, url, sync) { kimchi.requestJSON({ url : url ? url : 'i18n.json', type : 'GET', resend: true, dataType : 'json', async : !sync, success : suc, error: err }); }, /** * Get the host static information. */ getHost: function(suc, err) { kimchi.requestJSON({ url : 'host', type : 'GET', resend: true, contentType : 'application/json', dataType : 'json', success : suc, error: err }); }, /** * Get the dynamic host stats (usually used for monitoring). */ getHostStats : function(suc, err) { kimchi.requestJSON({ url : 'host/stats', type : 'GET', contentType : 'application/json', headers: {'Kimchi-Robot': 'kimchi-robot'}, dataType : 'json', success : suc, error: err }); }, /** * Get the historic host stats. */ getHostStatsHistory : function(suc, err) { kimchi.requestJSON({ url : 'host/stats/history', type : 'GET', resend: true, contentType : 'application/json', headers: {'Kimchi-Robot': 'kimchi-robot'}, dataType : 'json', success : suc, error: err }); }, /** * * Create a new Virtual Machine. Usage: kimchi.createVM({ name: 'MyUbuntu', * template: '/templates/ubuntu_base' }, creationSuc, creationErr); * * settings: name *(optional)*: The name of the VM. Used to identify the VM * in this API. If omitted, a name will be chosen based on the template * used. template: The URI of a Template to use when building the VM * storagepool *(optional)*: Assign a specific Storage Pool to the new VM * suc: callback if succeed err: callback if failed */ createVM : function(settings, suc, err) { kimchi.requestJSON({ url : "vms", type : "POST", contentType : "application/json", data : JSON.stringify(settings), dataType : "json" }).done(suc).fail(err); }, /** * * Create a new Template. settings name: The name of the Template. Used to * identify the Template in this API suc: callback if succeed err: callback * if failed */ createTemplate : function(settings, suc, err) { kimchi.requestJSON({ url : "templates", type : "POST", contentType : "application/json", data : JSON.stringify(settings), dataType : "json", success: suc, error: err }); }, deleteTemplate : function(tem, suc, err) { kimchi.requestJSON({ url : 'templates/' + encodeURIComponent(tem), type : 'DELETE', contentType : 'application/json', dataType : 'json', success : suc, error : err }); }, cloneTemplate : function(tem, suc, err) { kimchi.requestJSON({ url : 'templates/' + encodeURIComponent(tem) + "/clone", type : 'POST', contentType : 'application/json', dataType : 'json', success : suc, error : err }); }, listTemplates : function(suc, err) { kimchi.requestJSON({ url : 'templates', type : 'GET', contentType : 'application/json', dataType : 'json', success : suc, error : err }); }, /** * Retrieve the information of a template by the given name. */ retrieveTemplate : function(templateName, suc, err) { kimchi.requestJSON({ url : "templates/" + encodeURIComponent(templateName), type : 'GET', contentType : 'application/json', dataType : 'json' }).done(suc); }, /** * Update a template with new information. TODO: Update me when the RESTful * API is available. Now work it around by remove the template and then * recreate it with new information. */ updateTemplate : function(name, settings, suc, err) { $.ajax({ url : "templates/" + encodeURIComponent(name), type : 'PUT', contentType : 'application/json', data : JSON.stringify(settings), dataType : 'json' }).done(suc).fail(err); }, /** * Create a new Storage Pool. settings name: The name of the Storage Pool * path: The path of the defined Storage Pool type: The type of the defined * Storage Pool capacity: The total space which can be used to store volumes * The unit is MBytes suc: callback if succeed err: callback if failed */ createStoragePool : function(settings, suc, err) { kimchi.requestJSON({ url : 'storagepools', type : 'POST', contentType : 'application/json', data : JSON.stringify(settings), dataType : 'json' }).done(suc).fail(err); }, updateStoragePool : function(name, content, suc, err) { $.ajax({ url : "storagepools/" + encodeURIComponent(name), type : 'PUT', contentType : 'application/json', dataType : 'json', data : JSON.stringify(content) }).done(suc).fail(err ? err : function(data) { kimchi.message.error(data.responseJSON.reason); }); }, startVM : function(vm, suc, err) { kimchi.requestJSON({ url : 'vms/' + encodeURIComponent(vm) + '/start', type : 'POST', contentType : 'application/json', dataType : 'json', success : suc, error : err }); }, poweroffVM : function(vm, suc, err) { kimchi.requestJSON({ url : 'vms/' + encodeURIComponent(vm) + '/poweroff', type : 'POST', contentType : 'application/json', dataType : 'json', success : suc, error : err }); }, shutdownVM : function(vm, suc, err) { kimchi.requestJSON({ url : 'vms/' + encodeURIComponent(vm) + '/shutdown', type : 'POST', contentType : 'application/json', dataType : 'json', success : suc, error : err }); }, resetVM : function(vm, suc, err) { kimchi.requestJSON({ url : 'vms/' + encodeURIComponent(vm) + '/reset', type : 'POST', contentType : 'application/json', dataType : 'json', success : suc, error : err }); }, suspendVM : function(vm, suc, err) { kimchi.requestJSON({ url : 'vms/' + encodeURIComponent(vm) + '/suspend', type : 'POST', contentType : 'application/json', dataType : 'json', success : suc, error : err }); }, resumeVM : function(vm, suc, err) { kimchi.requestJSON({ url : 'vms/' + encodeURIComponent(vm) + '/resume', type : 'POST', contentType : 'application/json', dataType : 'json', success : suc, error : err }); }, /** * Retrieve the information of a given VM by its name. * * @param vm VM name * @param suc callback for success * @param err callback for error */ retrieveVM : function(vm, suc, err) { $.ajax({ url : 'vms/' + encodeURIComponent(vm), type : 'GET', contentType : 'application/json', dataType : 'json', success: suc, error: err }); }, /** * Update a VM with new information. */ updateVM : function(name, settings, suc, err) { $.ajax({ url : "vms/" + encodeURIComponent(name), type : 'PUT', contentType : 'application/json', data : JSON.stringify(settings), dataType : 'json', success: suc, error: err }); }, deleteVM : function(vm, suc, err) { kimchi.requestJSON({ url : 'vms/' + encodeURIComponent(vm), type : 'DELETE', contentType : 'application/json', dataType : 'json', success : suc, error : err }); }, vncToVM : function(vm) { kimchi.requestJSON({ url : 'config', type : 'GET', dataType : 'json' }).done(function(data, textStatus, xhr) { proxy_port = data['display_proxy_port']; kimchi.requestJSON({ url : "vms/" + encodeURIComponent(vm) + "/connect", type : "POST", dataType : "json" }).done(function() { url = 'https://' + location.hostname + ':' + proxy_port; url += "/console.html?url=" + encodeURIComponent("novnc/vnc_auto.html"); url += "&port=" + proxy_port; /* * From python documentation base64.urlsafe_b64encode(s) * substitutes - instead of + and _ instead of / in the * standard Base64 alphabet, BUT the result can still * contain = which is not safe in a URL query component. * So remove it when needed as base64 can work well without it. * */ url += "&path=?token=" + kimchi.urlSafeB64Encode(vm).replace(/=*$/g, ""); url += "&kimchi=" + location.port; url += '&encrypt=1'; window.open(url); }); }).error(function() { kimchi.message.error.code('KCHAPI6002E'); }); }, spiceToVM : function(vm) { kimchi.requestJSON({ url : 'config', type : 'GET', dataType : 'json' }).done(function(data, textStatus, xhr) { proxy_port = data['display_proxy_port']; kimchi.requestJSON({ url : "vms/" + encodeURIComponent(vm) + "/connect", type : "POST", dataType : "json" }).done(function(data, textStatus, xhr) { url = 'https://' + location.hostname + ':' + proxy_port; url += "/console.html?url=spice_auto.html&port=" + proxy_port; url += "&listen=" + location.hostname; /* * From python documentation base64.urlsafe_b64encode(s) * substitutes - instead of + and _ instead of / in the * standard Base64 alphabet, BUT the result can still * contain = which is not safe in a URL query component. * So remove it when needed as base64 can work well without it. * */ url += "&token=" + kimchi.urlSafeB64Encode(vm).replace(/=*$/g, ""); url += "&kimchi=" + location.port; url += '&encrypt=1'; window.open(url); }); }).error(function() { kimchi.message.error.code('KCHAPI6002E'); }); }, listVMs : function(suc, err) { kimchi.requestJSON({ url : 'vms', type : 'GET', contentType : 'application/json', headers: {'Kimchi-Robot': 'kimchi-robot'}, dataType : 'json', resend: true, success : suc, error : err }); }, listTemplates : function(suc, err) { kimchi.requestJSON({ url : 'templates', type : 'GET', contentType : 'application/json', dataType : 'json', resend: true, success : suc, error : err }); }, listStoragePools : function(suc, err) { kimchi.requestJSON({ url : 'storagepools', type : 'GET', contentType : 'application/json', dataType : 'json', resend: true, success : suc, error : err }); }, listStorageVolumes : function(poolName, suc, err) { $.ajax({ url : 'storagepools/' + encodeURIComponent(poolName) + '/storagevolumes', type : 'GET', contentType : 'application/json', dataType : 'json', success : suc, error : err }); }, listIsos : function(suc, err) { kimchi.requestJSON({ url : 'storagepools/kimchi_isos/storagevolumes', type : 'GET', contentType : 'application/json', dataType : 'json', success : suc, error : err }); }, listDistros : function(suc, err) { kimchi.requestJSON({ url : 'config/distros', type : 'GET', contentType : 'application/json', dataType : 'json', success : suc, error : err }); }, stepListDeepScanIsos : function(suc, err) { var deepScanHandler = { stop : false }; var isoPool = 'iso' + new Date().getTime(); kimchi.createStoragePool({ name : isoPool, type : 'kimchi-iso', path : '/' }, function(result) { var taskId = result.task_id; function monitorTask() { if (deepScanHandler.stop) { return; } kimchi.getTask(taskId, function(result) { var status = result.status; if (status === "finished") { if (deepScanHandler.stop) { return; } kimchi.listStorageVolumes(isoPool, function(isos) { if (deepScanHandler.stop) { return; } suc(isos, true); }, err); } else if (status === "running") { if (deepScanHandler.stop) { return; } kimchi.listStorageVolumes(isoPool, function(isos) { if (deepScanHandler.stop) { return; } suc(isos, false); setTimeout(monitorTask, 2000); }, err); } else if (status === "failed") { if (deepScanHandler.stop) { return; } err(result.message); } }, err); } setTimeout(monitorTask, 2000); }, err); return deepScanHandler; }, getTask : function(taskId, suc, err) { kimchi.requestJSON({ url : 'tasks/' + encodeURIComponent(taskId), type : 'GET', contentType : 'application/json', dataType : 'json', success : suc, error : err }); }, getTasksByFilter : function(filter, suc, err, sync) { kimchi.requestJSON({ url : 'tasks?' + filter, type : 'GET', contentType : 'application/json', dataType : 'json', async : !sync, success : suc, error : err }); }, login : function(settings, suc, err) { $.ajax({ url : "login", type : "POST", contentType : "application/json", data : JSON.stringify(settings), dataType : "json" }).done(suc).fail(err); }, logout : function(suc, err) { kimchi.requestJSON({ url : 'logout', type : 'POST', contentType : "application/json", dataType : "json" }).done(suc).fail(err); }, deleteStoragePool : function(poolName, suc, err) { $.ajax({ url : 'storagepools/' + encodeURIComponent(poolName), type : 'DELETE', contentType : 'application/json', dataType : 'json', success : suc, error : err }); }, changePoolState : function(poolName, state, suc, err) { if (state === 'activate' || state === 'deactivate') $.ajax({ url : 'storagepools/' + encodeURIComponent(poolName) + '/' + state, type : 'POST', contentType : 'application/json', dataType : 'json', success : suc, error : err }); }, listPlugins : function(suc, err, sync) { kimchi.requestJSON({ url : 'plugins', type : 'GET', contentType : 'application/json', dataType : 'json', resend: true, async : !sync, success : suc, error : err }); }, listNetworks : function(suc, err) { kimchi.requestJSON({ url : 'networks', type : 'GET', contentType : 'application/json', dataType : 'json', resend : true, success : suc, error : err ? err : function(data) { kimchi.message.error(data.responseJSON.reason); } }); }, toggleNetwork : function(name, on, suc, err) { var action = on ? "activate" : "deactivate"; kimchi.requestJSON({ url : 'networks/' + encodeURIComponent(name) + '/' + action, type : 'POST', contentType : 'application/json', dataType : 'json', success : suc, error : err ? err : function(data) { kimchi.message.error(data.responseJSON.reason); } }); }, createNetwork : function(network, suc, err) { kimchi.requestJSON({ url : 'networks', type : 'POST', contentType : 'application/json', dataType : 'json', data : JSON.stringify(network), success : suc, error : err ? err : function(data) { kimchi.message.error(data.responseJSON.reason); } }); }, getInterfaces : function(suc, err) { kimchi.requestJSON({ url : 'interfaces', type : 'GET', contentType : 'application/json', dataType : 'json', resend : true, success : suc, error : err ? err : function(data) { kimchi.message.error(data.responseJSON.reason); } }); }, deleteNetwork : function(name, suc, err) { kimchi.requestJSON({ url : 'networks/' + encodeURIComponent(name), type : 'DELETE', contentType : 'application/json', dataType : 'json', success : suc, error : err ? err : function(data) { kimchi.message.error(data.responseJSON.reason); } }); }, listReports : function(suc, err) { kimchi.requestJSON({ url : 'debugreports', type : 'GET', contentType : 'application/json', dataType : 'json', resend: true, success : suc, error : err }); }, trackTask : function(taskID, suc, err, progress) { var onTaskResponse = function(result) { var taskStatus = result['status']; switch(taskStatus) { case 'running': progress && progress(result); setTimeout(function() { kimchi.trackTask(taskID, suc, err, progress); }, 2000); break; case 'finished': suc && suc(result); break; case 'failed': err && err(result); break; default: break; } }; kimchi.getTask(taskID, onTaskResponse, err); if(kimchi.trackingTasks.indexOf(taskID) < 0) kimchi.trackingTasks.push(taskID); }, createReport: function(settings, suc, err, progress) { var onResponse = function(data) { taskID = data['id']; kimchi.trackTask(taskID, suc, err, progress); }; kimchi.requestJSON({ url : 'debugreports', type : "POST", contentType : "application/json", data : JSON.stringify(settings), dataType : "json", success : onResponse, error : err }); }, renameReport : function(name, settings, suc, err) { $.ajax({ url : "debugreports/" + encodeURIComponent(name), type : 'PUT', contentType : 'application/json', data : JSON.stringify(settings), dataType : 'json', success: suc, error: err }); }, deleteReport: function(settings, suc, err) { var reportName = encodeURIComponent(settings['name']); kimchi.requestJSON({ url : 'debugreports/' + reportName, type : 'DELETE', contentType : 'application/json', dataType : 'json', success : suc, error : err }); }, downloadReport: function(settings, suc, err) { window.open(settings['file']); }, shutdown: function(settings, suc, err) { var reboot = settings && settings['reboot'] === true; var url = 'host/' + (reboot ? 'reboot' : 'shutdown'); kimchi.requestJSON({ url : url, type : 'POST', contentType : 'application/json', dataType : 'json', success : suc, error : err }); }, listHostPartitions : function(suc, err) { kimchi.requestJSON({ url : 'host/partitions', type : 'GET', contentType : 'application/json', dataType : 'json', success : suc, error : err }); }, getStorageServers: function(type, suc, err) { var url = 'storageservers?_target_type=' + type; kimchi.requestJSON({ url : url, type : 'GET', contentType : 'application/json', dataType : 'json', success : suc, error : err ? err : function(data) { kimchi.message.error(data.responseJSON.reason); } }); }, getStorageTargets: function(server,type, suc, err) { var url = 'storageservers/' + server + '/storagetargets?_target_type=' + type; kimchi.requestJSON({ url : url, type : 'GET', contentType : 'application/json', timeout: 2000, dataType : 'json', success : suc, error : err }); }, getStoragePool: function(poolName, suc, err) { var url = kimchi.url + 'storagepools/' + encodeURIComponent(poolName); kimchi.requestJSON({ url : url, type : 'GET', contentType : 'application/json', timeout: 2000, dataType : 'json', success : suc, error : err }); }, getStoragePoolVolume: function(poolName, volumeName, suc, err) { var url = 'storagepools/' + encodeURIComponent(poolName) + '/storagevolumes/' + encodeURIComponent(volumeName); kimchi.requestJSON({ url : url, type : 'GET', contentType : 'application/json', timeout: 2000, dataType : 'json', success : suc, error : err }); }, addVMStorage : function(settings, suc, err) { var vm = encodeURIComponent(settings['vm']); delete settings['vm']; kimchi.requestJSON({ url : 'vms/' + vm + '/storages', type : 'POST', contentType : 'application/json', data : JSON.stringify(settings), dataType : 'json', success : suc, error : err }); }, retrieveVMStorage : function(settings, suc, err) { var vm = encodeURIComponent(settings['vm']); var dev = encodeURIComponent(settings['dev']); kimchi.requestJSON({ url : "vms/" + vm + '/storages/' + dev, type : 'GET', contentType : 'application/json', dataType : 'json', success: suc, error: err }); }, replaceVMStorage : function(settings, suc, err) { var vm = encodeURIComponent(settings['vm']); var dev = encodeURIComponent(settings['dev']); kimchi.requestJSON({ url : 'vms/' + vm + '/storages/' + dev, type : 'PUT', contentType : 'application/json', data : JSON.stringify({ path: settings['path'] }), dataType : 'json', success : suc, error : err }); }, deleteVMStorage : function(settings, suc, err) { var vm = settings['vm']; var dev = settings['dev']; kimchi.requestJSON({ url : 'vms/' + encodeURIComponent(vm) + '/storages/' + encodeURIComponent(dev), type : 'DELETE', contentType : 'application/json', dataType : 'json', success : suc, error : err }); }, listVMStorages : function(params, suc, err) { var vm = encodeURIComponent(params['vm']); var type = params['storageType']; var url = 'vms/' + vm + '/storages'; if(type) { url += '?type=' + type; } kimchi.requestJSON({ url : url, type : 'GET', contentType : 'application/json', dataType : 'json', success : suc, error : err }); }, listSoftwareUpdates : function(suc, err) { kimchi.requestJSON({ url : 'host/packagesupdate', type : 'GET', contentType : 'application/json', dataType : 'json', resend: true, success : suc, error : err }); }, updateSoftware : function(suc, err, progress) { var taskID = -1; var onResponse = function(data) { taskID = data['id']; trackTask(); }; var trackTask = function() { kimchi.getTask(taskID, onTaskResponse, err); }; var onTaskResponse = function(result) { var taskStatus = result['status']; switch(taskStatus) { case 'running': progress && progress(result); setTimeout(function() { trackTask(); }, 200); break; case 'finished': case 'failed': suc(result); break; default: break; } }; kimchi.requestJSON({ url : 'host/swupdate', type : "POST", contentType : "application/json", dataType : "json", success : onResponse, error : err }); }, createRepository : function(settings, suc, err) { kimchi.requestJSON({ url : "host/repositories", type : "POST", contentType : "application/json", data : JSON.stringify(settings), dataType : "json", success: suc, error: err }); }, retrieveRepository : function(repository, suc, err) { var reposID = encodeURIComponent(repository); kimchi.requestJSON({ url : "host/repositories/" + reposID, type : 'GET', contentType : 'application/json', dataType : 'json', success : suc, error : err }); }, updateRepository : function(name, settings, suc, err) { var reposID = encodeURIComponent(name); $.ajax({ url : "host/repositories/" + reposID, type : 'PUT', contentType : 'application/json', data : JSON.stringify(settings), dataType : 'json', success : suc, error : err }); }, enableRepository : function(name, enable, suc, err) { var reposID = encodeURIComponent(name); $.ajax({ url : "host/repositories/" + reposID + '/' + (enable === true ? 'enable' : 'disable'), type : 'POST', contentType : 'application/json', dataType : 'json', success : suc, error : err }); }, deleteRepository : function(repository, suc, err) { var reposID = encodeURIComponent(repository); kimchi.requestJSON({ url : 'host/repositories/' + reposID, type : 'DELETE', contentType : 'application/json', dataType : 'json', success : suc, error : err }); }, listRepositories : function(suc, err) { kimchi.requestJSON({ url : 'host/repositories', type : 'GET', contentType : 'application/json', dataType : 'json', resend: true, success : suc, error : err }); }, getHostFCDevices: function(suc, err) { var url = 'host/devices?_cap=fc_host'; kimchi.requestJSON({ url : url, type : 'GET', contentType : 'application/json', dataType : 'json', success : suc, error : err ? err : function(data) { kimchi.message.error(data.responseJSON.reason); } }); }, getGuestInterfaces: function(name, suc, err) { var url = 'vms/'+encodeURIComponent(name)+'/ifaces'; kimchi.requestJSON({ url : url, type : 'GET', contentType : 'application/json', dataType : 'json', success : suc, error : err || function(data) { kimchi.message.error(data.responseJSON.reason); } }); }, createGuestInterface : function(name, interface, suc, err) { kimchi.requestJSON({ url : 'vms/'+encodeURIComponent(name)+'/ifaces', type : 'POST', contentType : 'application/json', dataType : 'json', data : JSON.stringify(interface), success : suc, error : err || function(data) { kimchi.message.error(data.responseJSON.reason); } }); }, deleteGuestInterface : function(vm, mac, suc, err) { kimchi.requestJSON({ url : 'vms/'+encodeURIComponent(vm)+'/ifaces/'+encodeURIComponent(mac), type : 'DELETE', contentType : 'application/json', dataType : 'json', success : suc, error : err ? err : function(data) { kimchi.message.error(data.responseJSON.reason); } }); }, updateGuestInterface : function(vm, mac, interface, suc, err) { $.ajax({ url : 'vms/'+encodeURIComponent(vm)+'/ifaces/'+encodeURIComponent(mac), type : 'PUT', contentType : 'application/json', data : JSON.stringify(interface), dataType : 'json', success: suc, error: err ? err : function(data) { kimchi.message.error(data.responseJSON.reason); } }); }, getUserById : function(data, suc, err) { kimchi.requestJSON({ url : 'users?_user_id=' + data.user_id, type : 'GET', contentType : 'application/json', dataType : 'json', resend : true, async : false, success : suc && suc(data), error : err ? err : function(data) { kimchi.message.error(data.responseJSON.reason); } }); }, getUsers : function(suc, err) { kimchi.requestJSON({ url : 'users', type : 'GET', contentType : 'application/json', dataType : 'json', resend : true, success : suc, error : err ? err : function(data) { kimchi.message.error(data.responseJSON.reason); } }); }, getGroups : function(suc, err) { kimchi.requestJSON({ url : 'groups', type : 'GET', contentType : 'application/json', dataType : 'json', resend : true, success : suc, error : err ? err : function(data) { kimchi.message.error(data.responseJSON.reason); } }); }, getHostPCIDevices : function(suc, err) { kimchi.requestJSON({ url : 'host/devices?_passthrough=true&_cap=pci', type : 'GET', contentType : 'application/json', dataType : 'json', resend : true, success : suc, error : err ? err : function(data) { kimchi.message.error(data.responseJSON.reason); } }); }, getPCIDeviceCompanions : function(pcidev, suc, err) { kimchi.requestJSON({ url : 'host/devices?_passthrough_affected_by=' + pcidev, type : 'GET', contentType : 'application/json', dataType : 'json', resend : true, success : suc, error : err ? err : function(data) { kimchi.message.error(data.responseJSON.reason); } }); }, getISCSITargets : function(server, port, suc, err) { server = encodeURIComponent(server); port = port ? '&_server_port='+encodeURIComponent(port) : ''; kimchi.requestJSON({ url : 'storageservers/'+server+'/storagetargets?_target_type=iscsi'+port, type : 'GET', contentType : 'application/json', dataType : 'json', resend : true, success : suc, error : err ? err : function(data) { kimchi.message.error(data.responseJSON.reason); } }); }, getPeers : function(suc, err) { kimchi.requestJSON({ url : 'peers', type : 'GET', contentType : 'application/json', dataType : 'json', resend : true, success : suc, error : err ? err : function(data) { kimchi.message.error(data.responseJSON.reason); } }); }, getVMPCIDevices : function(id, suc, err) { kimchi.requestJSON({ url : 'vms/'+encodeURIComponent(id)+'/hostdevs', type : 'GET', contentType : 'application/json', dataType : 'json', resend : true, success : suc, error : err ? err : function(data) { kimchi.message.error(data.responseJSON.reason); } }); }, addVMPCIDevice : function(vm, device, suc, err) { kimchi.requestJSON({ url : 'vms/'+ encodeURIComponent(vm) +'/hostdevs', type : 'POST', contentType : 'application/json', dataType : 'json', data : JSON.stringify(device), success : suc, error : err ? err : function(data) { kimchi.message.error(data.responseJSON.reason); } }); }, removeVMPCIDevice : function(vm, device, suc, err) { kimchi.requestJSON({ url : 'vms/'+ encodeURIComponent(vm) +'/hostdevs/' + encodeURIComponent(device), type : 'DELETE', contentType : 'application/json', dataType : 'json', success : suc, error : err ? err : function(data) { kimchi.message.error(data.responseJSON.reason); } }); }, /** * Create a new volume with capacity */ createVolumeWithCapacity: function(poolName, settings, suc, err) { kimchi.requestJSON({ url : 'storagepools/' + encodeURIComponent(poolName) + '/storagevolumes', type : 'POST', contentType : "application/json", data : JSON.stringify(settings), dataType : "json", success : suc, error : err }); }, /** * Upload volume content */ uploadVolumeToSP: function(poolName, volumeName, settings, suc, err) { var url = 'storagepools/' + encodeURIComponent(poolName) + '/storagevolumes/' + encodeURIComponent(volumeName); var fd = settings['formData']; kimchi.requestJSON({ url : url, type : 'PUT', data : fd, processData : false, contentType : false, dataType: 'json', success : suc, error : err }); }, /** * Add a volume to a given storage pool by URL. */ downloadVolumeToSP: function(settings, suc, err) { var sp = encodeURIComponent(settings['sp']); delete settings['sp']; kimchi.requestJSON({ url : 'storagepools/' + sp + '/storagevolumes', type : 'POST', data : JSON.stringify(settings), contentType : 'application/json', dataType : 'json', success : suc, error : err }); }, cloneGuest: function(vm, suc, err) { kimchi.requestJSON({ url : 'vms/'+encodeURIComponent(vm)+"/clone", type : 'POST', contentType : 'application/json', dataType : 'json', success : suc, error : err ? err : function(data) { kimchi.message.error(data.responseJSON.reason); } }); }, listSnapshots : function(vm, suc, err) { kimchi.requestJSON({ url : 'vms/'+encodeURIComponent(vm)+'/snapshots', type : 'GET', contentType : 'application/json', dataType : 'json', resend : true, success : suc, error : err ? err : function(data) { kimchi.message.error(data.responseJSON.reason); } }); }, getCurrentSnapshot : function(vm, suc, err, sync) { kimchi.requestJSON({ url : 'vms/'+encodeURIComponent(vm)+'/snapshots/current', type : 'GET', contentType : 'application/json', dataType : 'json', async : !sync, resend : true, success : suc, error : err ? err : function(data) { kimchi.message.error(data.responseJSON.reason); } }); }, revertSnapshot : function(vm, snapshot, suc, err) { kimchi.requestJSON({ url : 'vms/'+encodeURIComponent(vm)+'/snapshots/'+encodeURIComponent(snapshot)+'/revert', type : 'POST', contentType : 'application/json', dataType : 'json', success : suc, error : err ? err : function(data) { kimchi.message.error(data.responseJSON.reason); } }); }, createSnapshot : function(vm, suc, err) { kimchi.requestJSON({ url : 'vms/'+encodeURIComponent(vm)+'/snapshots', type : 'POST', contentType : 'application/json', dataType : 'json', success : suc, error : err ? err : function(data) { kimchi.message.error(data.responseJSON.reason); } }); }, deleteSnapshot : function(vm, snapshot, suc, err) { kimchi.requestJSON({ url : 'vms/'+encodeURIComponent(vm)+'/snapshots/'+encodeURIComponent(snapshot), type : 'DELETE', contentType : 'application/json', dataType : 'json', success : suc, error : err ? err : function(data) { kimchi.message.error(data.responseJSON.reason); } }); }, getCPUInfo : function(suc, err) { kimchi.requestJSON({ url : 'host/cpuinfo', type : 'GET', contentType : 'application/json', dataType : 'json', resend : true, success : suc, error : err ? err : function(data) { kimchi.message.error(data.responseJSON.reason); } }); } }; kimchi-1.5.0/ui/js/src/kimchi.cookie.js000066400000000000000000000025511254252253000176560ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ kimchi.cookie = { set: function(key, value, expireDays) { value = encodeURIComponent(value); value += '; secure' if (expireDays) { var expireDate = new Date(); expireDate.setDate(expireDate.getDate() + expireDays); value += '; expires=' + expireDate.toUTCString(); } document.cookie = key + '=' + value; }, get: function(key) { var cookieRe = new RegExp(';?\\\s*(' + key + ')=(\s*[^;]*);?', 'g'); var match = cookieRe.exec(document.cookie); return match ? decodeURIComponent(match[2]) : undefined; }, remove: function(key) { var utcString = new Date().toUTCString(); document.cookie = key + '=; expires=' + utcString; } }; kimchi-1.5.0/ui/js/src/kimchi.form.js000066400000000000000000000030571254252253000173520ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ (function($) { $.fn.serializeObject = function() { var formDataArray = $(this).serializeArray(); var formData = new Object(); $.each(formDataArray, function(index, data) { formData.setDeepValue(data.name, data.value); }); return formData; }; }(jQuery)); (function($) { $.fn.fillWithObject = function(obj) { $(this).find("input").each(function(){ switch($(this).attr('type')) { case 'text': $(this).val(obj.getDeepValue($(this).attr("name"))); break; case 'radio': case 'checkbox': var a=String($(this).val()); var b=String(obj.getDeepValue($(this).attr("name"))); $(this).prop("checked",(a==b)); break; default: break; } }); }; }(jQuery)); kimchi-1.5.0/ui/js/src/kimchi.grid.js000066400000000000000000000441371254252253000173400ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2015 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ kimchi.widget.Grid = function(opts) { this.opts = $.extend({}, this.opts, opts); this.createDOM(); this.reload(); }; kimchi.widget.Grid.prototype = (function() { var htmlStr = [ '

', '
', '
', '
', '', '
', '
', '
', '
', '', '
', '
', '
', '
', '
', '
', '
', '', '
', '
', '
', '
', '
', '', '
', '
', '
', '
', '', '', '
', '', '', '', '
' ].join(''); var CONTAINER_NORMAL = 0, CONTAINER_FROZEN = 1; var setupHeaders = function(header, body, fields) { var colGroup = $('').appendTo(header); var headerHeader = $(''); var headerRow = $('').appendTo(headerHeader); $.each(fields || [], function(i, field) { $('') .appendTo(colGroup); $('
' + field['label'] + '
').appendTo(headerRow); }); headerHeader.appendTo(header); var totalWidth = 0; $('col', colGroup).each(function(index, col) { var width = $(col).width(); totalWidth += width; $(col).css('width', width + 'px'); }); $(body).append(colGroup.clone()); return totalWidth; }; var getValue = function(name, obj) { var result=undefined; if(!Array.isArray(name)) { name=name.parseKey(); } if(name.length!=0) { var tmpName=name.shift(); if(obj[tmpName]!=undefined) { result=obj[tmpName]; } if(name.length!=0) { result=getValue(name,obj[tmpName]); } } return(result); }; var fillBody = function(container, fields) { var data = this.data; var tbody = ($('tbody', container).length && $('tbody', container)) || $('').appendTo(container); tbody.empty(); $.each(data, function(i, row) { var rowNode = $('').appendTo(tbody); $.each(fields, function(fi, field) { var value = getValue(field['name'], row); $('
' + value.toString() + '
' ).appendTo(rowNode); }); }); }; var fixTableLayout = function(style) { $.each([ this.frozenHeaderContainer, this.headerContainer, this.frozenBodyContainer, this.bodyContainer ], function(i, tableNode) { $(tableNode).css('table-layout', style || 'fixed'); }); }; var initResizing = function(event) { var resizer = event.data.resizer; var pageX = event.pageX; var tailPos = $(this).width() + $(this).offset()['left']; var atResizer = Math.abs(pageX - tailPos) <= 2; var isResizing = !$(resizer).hasClass('hidden'); $('body')[(atResizer || isResizing) ? 'addClass' : 'removeClass' ]('resizing'); }; var clearResizing = function(event) { $(event.data.resizer).hasClass('hidden') && $('body').removeClass('resizing'); }; var stylingRow = function(row, className, add) { var index = $(row).index() + 1; $('tr', this.frozenBodyContainer) .removeClass(className); $('tr', this.bodyContainer) .removeClass(className); if(add === false) { return; } $('tr:nth-child(' + index + ')', this.frozenBodyContainer) .addClass(className); $('tr:nth-child(' + index + ')', this.bodyContainer) .addClass(className); }; var setBodyListeners = function() { if(this['opts']['rowSelection'] != 'disabled') { $('tr', this.gridBody).on('mouseover', { grid: this }, function(event) { if (! $(this).hasClass('no-hover')) stylingRow.call(event.data.grid, this, 'hover'); }); $('tr', this.gridBody).on('mouseout', { grid: this }, function(event) { stylingRow.call(event.data.grid, this, 'hover', false); }); $('tr', this.gridBody).on('click', { grid: this }, function(event) { var grid = event.data.grid; grid.selectedIndex = $(this).index(); stylingRow.call(grid, this, 'selected'); grid['opts']['onRowSelected'] && grid['opts']['onRowSelected'](); }); } $('.grid-body-view', this.domNode).on('scroll', { grid: this }, function(event) { var grid = event.data.grid; $('.grid-header .grid-header-view', grid.domNode) .prop('scrollLeft', this.scrollLeft); $('.grid-body .grid-frozen-body-view', grid.domNode) .prop('scrollTop', this.scrollTop); }); }; var setData = function(data) { this.data = data; fillBody.call(this, this.frozenBodyContainer, this['opts']['frozenFields']); fillBody.call(this, this.bodyContainer, this['opts']['fields']); setBodyListeners.call(this); }; var getSelected = function() { return this.selectedIndex >= 0 ? this.data[this.selectedIndex] : null; }; var startResizing = function(container, event) { var grid = event.data.grid; kimchi.widget.Grid.beingResized = grid; if(!($('body').hasClass('resizing') && $(grid.resizer).hasClass('hidden'))) { return; } grid.columnBeingResized = container; var pageX = event.pageX; var gridOffsetX = grid.domNode.offset()['left']; var leftmostOffsetX = $(container).offset()['left'] - gridOffsetX; var left = pageX - gridOffsetX; var contentHeight = $('.grid-content', grid.domNode).height(); $(grid.resizerLeftmost).css({ left: leftmostOffsetX + 'px', height: contentHeight + 'px' }); $(grid.resizer).css({ left: left + 'px', height: contentHeight + 'px' }); $(grid.resizerLeftmost).removeClass('hidden'); $(grid.resizer).removeClass('hidden'); event.preventDefault(); }; var endResizing = function(event) { var grid = kimchi.widget.Grid.beingResized; if(!$('body').hasClass('resizing')) { return; } $(grid.resizerLeftmost).addClass('hidden'); $(grid.resizer).addClass('hidden'); $('body').removeClass('resizing'); var leftmostOffset = $(grid.columnBeingResized).offset()['left']; var left = event.pageX; if(leftmostOffset > left) { return; } resizeColumnWidth.call( grid, $(grid.columnBeingResized).index(), left - leftmostOffset ); fixTableLayout.call(grid); grid.columnBeingResized = null; kimchi.widget.Grid.beingResized = null; }; var resizeColumnWidth = function(index, width) { var width = Math.ceil(width); var widthArray = []; var totalWidth = 0; var header = this.headerContainer; var body = this.bodyContainer; if(this.containerBeingResized === CONTAINER_FROZEN) { header = this.frozenHeaderContainer; body = this.frozenBodyContainer; } $('col', header).each(function(i, colNode) { var w = index === i ? width : $(colNode).width(); widthArray.push(w); totalWidth += w; }); $.each([header, body], function(i, container) { container.css({ 'table-layout': 'fixed', width: totalWidth + 'px' }); $('col:nth-child(' + (index + 1) + ')', container).css({ width: width + 'px' }); }); if(this.containerBeingResized === CONTAINER_FROZEN) { var headerView = $('.grid-header-view', this.domNode); var bodyView = $('.grid-body-view', this.domNode); $.each([headerView, bodyView], function(i, view) { view.css({ left: totalWidth + 'px' }); }); } }; var positionResizer = function(event) { var grid = event.data.grid; if($(grid.resizer).hasClass('hidden')) { return; } var pageX = event.pageX; var gridOffsetX = $(grid.domNode).offset()['left']; var leftMost = $(grid.resizerLeftmost).position()['left']; var offsetX = pageX - gridOffsetX; offsetX = offsetX >= leftMost ? offsetX : leftMost; $(grid.resizer).css('left', offsetX + 'px'); }; var showMessage = function(msg) { $('.detailed-text', this.messageNode).text(msg); $(this.messageNode).removeClass('hidden'); }; var hideMessage = function() { $(this.messageNode).addClass('hidden'); }; var reload = function() { var data = this['opts']['data']; if(!data) { return; } $(this.messageNode).addClass('hidden'); if($.isArray(data)) { return this.setData(data); } if($.isFunction(data)) { var loadData = data; $(this.maskNode).removeClass('hidden'); loadData($.proxy(function(data) { this.setData(data); $(this.maskNode).addClass('hidden'); }, this)); } }; var destroy = function() { $('body').off('mousemove.grid#' + this['opts']['id'], positionResizer); $('body').off('mouseup.grid#' + this['opts']['id'], endResizing); }; var createDOM = function() { var containerID = this['opts']['container']; var container = $('#' + containerID); var gridID = this['opts']['id']; var rowSelection = this['opts']['rowSelection'] || 'single'; var domNode = $(kimchi.substitute(htmlStr, { id: gridID, loading: i18n['KCHGRD6001M'], message: i18n['KCHGRD6002M'], buttonLabel: i18n['KCHGRD6003M'], detailedLabel: i18n['KCHGRD6004'] })).appendTo(container); this.domNode = domNode; var height = domNode.height(); var width = domNode.width(); var title = this['opts']['title']; var titleNode = null; if(title) { titleNode = $('
' + title + '
') .prependTo(domNode); } var toolbarButtons = this['opts']['toolbarButtons']; var toolbarNode = null; if(toolbarButtons) { toolbarNode = $('
'); if(titleNode) { titleNode.after(toolbarNode); } else { toolbarNode.prependTo(domNode); } $.each(toolbarButtons, function(i, button) { var btnHTML = [ '', button['label'], '' ].join(''); var btnNode = $(btnHTML).appendTo(toolbarNode); button['onClick'] && btnNode.on('click', button['onClick']); }); } var frozenHeaderContainer = $('.grid-frozen-header-container', domNode); var frozenBodyContainer = $('.grid-frozen-body-container', domNode); var frozenWidth = setupHeaders( frozenHeaderContainer, frozenBodyContainer, this['opts']['frozenFields'] ); this.frozenHeaderContainer = frozenHeaderContainer; this.frozenBodyContainer = frozenBodyContainer; var headerContainer = $('.grid-header-container', domNode); var bodyContainer = $('.grid-body-container', domNode); setupHeaders(headerContainer, bodyContainer, this['opts']['fields']); this.headerContainer = headerContainer; this.bodyContainer = bodyContainer; fixTableLayout.call(this, 'auto'); var gridContentNode = $('.grid-content', domNode); var captionHeight = titleNode && $(titleNode).height() || 0; var toolbarHeight = toolbarNode && $(toolbarNode).height() || 0; gridContentNode.css('top', (captionHeight + toolbarHeight) + 'px'); var maskNode = $('.grid-mask', domNode); maskNode.css('top', captionHeight + 'px'); this.maskNode = maskNode; var messageNode = $('.grid-message', domNode); messageNode.css('top', captionHeight + 'px'); this.messageNode = messageNode; var headerView = $('.grid-header-view', domNode); var bodyView = $('.grid-body-view', domNode); headerView.css('left', (frozenWidth) + 'px'); bodyView.css('left', (frozenWidth) + 'px'); var bodyWidth = width - frozenWidth; headerContainer.css('width', bodyWidth + 'px'); bodyContainer.css('width', bodyWidth + 'px'); fixTableLayout.call(this); var gridBody = $('.grid-body', domNode); this.gridBody = gridBody; this.resizerLeftmost = $('.grid-resizer-leftmost', domNode); this.resizer = $('.grid-resizer', domNode); var gridHeader = $('.grid-header', domNode); $('th', gridHeader).on('mouseover mousemove', { resizer: this.resizer }, initResizing); $('th', gridHeader).on('mouseout', { resizer: this.resizer }, clearResizing); this.containerBeingResized = CONTAINER_NORMAL; $('th', frozenHeaderContainer).on('mousedown', { grid: this }, function(event) { event.data.grid.containerBeingResized = CONTAINER_FROZEN; startResizing(this, event); }); $('th', headerContainer).on('mousedown', { grid: this }, function(event) { event.data.grid.containerBeingResized = CONTAINER_NORMAL; startResizing(this, event); }); $('body').on('mousemove.grid#' + this['opts']['id'], { grid: this }, positionResizer); $('body').on('mouseup.grid#' + this['opts']['id'], endResizing); var data = this['opts']['data']; $('.retry-button', domNode).on('click', { grid: this }, function(event) { event.data.grid.reload(); }); }; return { opts: { container: null, id: null, rowSelection: 'single', onRowSelected: null, title: null, toolbarButtons: null, frozenFields: null, fields: null }, createDOM: createDOM, setData: setData, getSelected: getSelected, reload: reload, destroy: destroy, showMessage: showMessage }; })(); kimchi-1.5.0/ui/js/src/kimchi.guest_add_main.js000066400000000000000000000056051254252253000213530ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ kimchi.guest_add_main = function() { var showTemplates = function() { kimchi.topic('templateCreated').unsubscribe(showTemplates); kimchi.listTemplates(function(result) { if (result && result.length) { $('#prompt-create-template').addClass('hidden'); $('#prompt-choose-template').removeClass('hidden'); var html = ''; var tmpl = $('#tmpl-template').html(); $.each(result, function(index, value) { html += kimchi.substitute(tmpl, value); }); $('#templateTile').html(html); return; } $('#btn-create-template').on('click', function(event) { kimchi.topic('templateCreated').subscribe(showTemplates); kimchi.window.open('template-add.html'); event.preventDefault(); }); $('#prompt-choose-template').addClass('hidden'); $('#prompt-create-template').removeClass('hidden'); }, function(err) { kimchi.message.error(err.responseJSON.reason); }); }; function validateForm() { if (!$('input[name=template]:checked', '#templateTile').val()) { return false; } return true; } $('#form-vm-add').change(function() { if (validateForm()) { $('#vm-doAdd').attr('disabled', false); } }); var addGuest = function(event) { $('#vm-doAdd').attr('disabled', true); $('#vm-doAdd').attr('style', 'display:none'); $('#vm-doAdding').attr('style', 'display'); var formData = $('#form-vm-add').serializeObject(); kimchi.createVM(formData, function() { kimchi.listVmsAuto(); kimchi.window.close(); }, function(jqXHR, textStatus, errorThrown) { $('#vm-doAdd').attr('style', 'display'); $('#vm-doAdding').attr('style', 'display:none'); var reason = jqXHR && jqXHR['responseJSON'] && jqXHR['responseJSON']['reason']; kimchi.message.error(reason); }); return false; }; $('#form-vm-add').on('submit', addGuest); $('#vm-doAdd').on('click', addGuest); showTemplates(); }; kimchi-1.5.0/ui/js/src/kimchi.guest_edit_main.js000066400000000000000000001006541254252253000215500ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2015 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ kimchi.guest_edit_main = function() { var buttonContainer = $('#action-button-container'); $('#guest-edit-tabs').tabs({ beforeActivate: function(event, ui) { var display_list = null; if(kimchi.thisVMState === "running") { display_list = ['form-guest-edit-permission']; } else { display_list = ['form-guest-edit-general', 'form-guest-edit-permission']; } $(buttonContainer).addClass('hidden'); var deactivated = ui['newPanel']; if(display_list.indexOf($(deactivated).attr('id')) >= 0) { $(buttonContainer).removeClass('hidden'); } } }); var guestEditForm = $('#form-guest-edit-general'); var saveButton = $('#guest-edit-button-save'); var authType; var refreshCDROMs = function() { kimchi.listVMStorages({ vm: kimchi.selectedGuest }, function(storages) { var container = $('#form-guest-edit-storage .body'); $(container).empty(); $.each(storages, function(index, storage) { storage['vm'] = kimchi.selectedGuest; rowHTML = $('#' + storage['type'] + '-row-tmpl').html(); var templated = kimchi.substitute(rowHTML, storage); container.append(templated); }); $('.replace', container).button({ icons: { primary: 'ui-icon-pencil' }, text: false }); $('.detach', container).button({ icons: { primary: 'ui-icon-trash' }, text: false }); if (kimchi.thisVMState === 'running') { $('.detach[data-type="cdrom"]', container).remove(); } $('.save', container).button({ icons: { primary: 'ui-icon-disk' }, text: false }); $('.cancel', container).button({ icons: { primary: 'ui-icon-arrowreturnthick-1-w' }, text: false }); }); }; var initStorageListeners = function() { var container = $('#form-guest-edit-storage .body'); var toggleCDROM = function(rowNode, toEdit) { $('button.replace,button.detach', rowNode) [(toEdit ? 'add' : 'remove') + 'Class']('hidden'); $('button.save,button.cancel', rowNode) [(toEdit ? 'remove' : 'add') + 'Class']('hidden'); var pathBox = $('.path input', rowNode) .prop('readonly', !toEdit); toEdit && pathBox.select(); pathBox.val(pathBox.attr('value')); }; var replaceCDROM = function(event) { event.preventDefault(); kimchi.selectedGuestStorage = $(this).data('dev'); $('.item', container).each(function(i, n) { toggleCDROM(n); }); var rowNode = $('#cdrom-' + kimchi.selectedGuestStorage); toggleCDROM(rowNode, true); }; $(container).on('click', 'button.replace', replaceCDROM); $(container).on('click', 'button.detach', function(e) { e.preventDefault(); var settings = { title : i18n['KCHAPI6004M'], content : i18n['KCHVMCD6001M'], confirm : i18n['KCHAPI6002M'], cancel : i18n['KCHAPI6003M'] }; if ($(this).data('type') == "disk") settings['content'] = i18n['KCHVMCD6009M']; var dev = $(this).data('dev'); kimchi.confirm(settings, function() { kimchi.deleteVMStorage({ vm: kimchi.selectedGuest, dev: dev }, function() { kimchi.topic('kimchi/vmCDROMDetached').publish(); }); }); }); $(container).on('click', 'button.save', function(event) { event.preventDefault(); var path = $('#cdrom-path-' + kimchi.selectedGuestStorage).val(); var settings = { vm: kimchi.selectedGuest, dev: kimchi.selectedGuestStorage, path: path }; kimchi.replaceVMStorage(settings, function(result) { kimchi.topic('kimchi/vmCDROMReplaced').publish({ result: result }); }, function(result) { var errText = result['reason'] || result['responseJSON']['reason']; kimchi.message.error(errText); }); }); $(container).on('click', 'button.cancel', function(event) { event.preventDefault(); var rowNode = $('#cdrom-' + kimchi.selectedGuestStorage); toggleCDROM(rowNode); }); }; var setupInterface = function() { $(".add", "#form-guest-edit-interface").button({ icons: { primary: "ui-icon-plusthick" }, text: false }).click(function(evt){ evt.preventDefault(); addItem({ id: -1, mac: "", network: "", type: "network", viewMode: "hide", editMode: "" }); }); var toggleEdit = function(item, on, itemId){ $("#label-mac-" + itemId, item).toggleClass("hide", on); $("#edit-mac-" + itemId, item).toggleClass("hide", !on); $("#label-network-" + itemId, item).toggleClass("hide", false); $("select", item).toggleClass("hide", true); $(".action-area", item).toggleClass("hide"); }; var addItem = function(data) { if (data.id == -1) { data.id = $('#form-guest-edit-interface > .body').children().size() } var itemNode = $.parseHTML(kimchi.substitute($('#interface-tmpl').html(),data)); $(".body", "#form-guest-edit-interface").append(itemNode); $("select", itemNode).append(networkOptions); if(data.network!==""){ $("select", itemNode).val(data.network); } $(".edit", itemNode).button({ disabled: kimchi.thisVMState === "running", icons: { primary: "ui-icon-pencil" }, text: false }).click(function(evt){ evt.preventDefault(); toggleEdit($(this).closest('div'), true, data.id); }); $(".delete", itemNode).button({ icons: { primary: "ui-icon-trash" }, text: false }).click(function(evt){ evt.preventDefault(); var item = $(this).parent().parent(); kimchi.deleteGuestInterface(kimchi.selectedGuest, item.prop("id"), function(){ item.remove(); }); }); $(".save", itemNode).button({ icons: { primary: "ui-icon-disk" }, text: false }).click(function(evt){ evt.preventDefault(); var item = $(this).parent().parent(); var interface = { network: $("select", item).val(), type: "network", mac: $(":text", item).val() }; var postUpdate = function(mac){ $("#label-network-" + data.id, item).text(interface.network); $("#label-mac-" + data.id, item).text(mac); $("#edit-mac-" + data.id, item).val(mac); toggleEdit(item, false, data.id); }; if(item.prop("id")==""){ kimchi.createGuestInterface(kimchi.selectedGuest, interface, function(data){ item.prop("id", data.mac); postUpdate(data.mac); }); }else{ if (item.prop('id') == interface.mac) { toggleEdit(item, false, data.id); } else { kimchi.updateGuestInterface(kimchi.selectedGuest, item.prop('id'), interface, function(data){ item.prop("id", data.mac); postUpdate(data.mac); }); } } }); $(".cancel", itemNode).button({ icons: { primary: "ui-icon-arrowreturnthick-1-w" }, text: false }).click(function(evt){ evt.preventDefault(); var item = $(this).parent().parent(); $("label", item).text()==="" ? item.remove() : toggleEdit(item, false, data.id); }); }; var networkOptions = ""; kimchi.listNetworks(function(data){ for(var i=0;i"+data[i].name+""; } kimchi.getGuestInterfaces(kimchi.selectedGuest, function(data){ for(var i=0;i .tile'); liveTile.addClass(vmObject.state); liveTile.find('.imgactive').attr('src',tile_src); var imgLoad=liveTile.find('.imgload'); imgLoad.on('load', function() { var oldImg=$(this).parent().find('.imgactive'); oldImg.removeClass("imgactive").addClass("imgload"); oldImg.attr("src",""); $(this).addClass("imgactive").removeClass("imgload"); $(this).off('load'); }); imgLoad.attr('src',load_src); //Link the stopped tile to the start action, the running tile to open the console, and the paused tile to resume if(!(vmObject.isCloning || vmObject.isCreating)){ if (vmPoweredOffBool) { liveTile.off("click", kimchi.openVmConsole); liveTile.off("click", kimchi.vmresume); liveTile.on("click", kimchi.vmstart); liveTile.hover(function(event){$(this).find('.overlay').show()}, function(event){$(this).find('.overlay').hide()}); } else if (vmSuspendedBool) { liveTile.off("click", kimchi.vmstart); liveTile.off("click", kimchi.openVmConsole); liveTile.on("click", kimchi.vmresume); if(vmObject.state="paused") { liveTile.find('.overlay').attr('src',"/images/theme-default/ac24_resume.png"); liveTile.find('.overlay').attr('alt',"Resume"); } liveTile.hover(function(event){$(this).find('.overlay').show()}, function(event){$(this).find('.overlay').hide()}); } else { liveTile.off("click", kimchi.vmstart); liveTile.off("click", kimchi.vmresume); liveTile.on("click", kimchi.openVmConsole); } } //Setup the gauges var stats=vmObject.stats; var gaugeValue=0; gaugeValue=parseInt(stats.net_throughput); kimchi.circleGaugeInit(result, "net_throughput",gaugeValue,(gaugeValue*100/stats.net_throughput_peak)); gaugeValue=parseInt(stats.io_throughput); kimchi.circleGaugeInit(result, "io_throughput",gaugeValue,(gaugeValue*100/stats.io_throughput_peak)); gaugeValue=parseInt(stats.cpu_utilization); kimchi.circleGaugeInit(result, "cpu_utilization",gaugeValue+"%",gaugeValue); //Setup the VM Actions var guestActions=result.find("div[name=guest-actions]"); guestActions.find(".shutoff-disabled").prop("disabled", !vmRunningBool); guestActions.find(".running-disabled").prop("disabled", vmRunningBool); guestActions.find(".non-persistent-disabled").prop("disabled", !vmPersistent); guestActions.find(".reset-disabled").prop("disabled", vmPoweredOffBool || !vmPersistent); guestActions.find(".pause-disabled").prop("disabled", vmPoweredOffBool || !vmPersistent); if (vmSuspendedBool) { //VM is paused //Hide Start guestActions.find(".running-hidden").hide(); //Hide Pause button and menu guestActions.find(".pause-disabled").hide(); guestActions.find(".pause-hidden").hide(); } if (vmRunningBool) { //VM IS running //Hide Start guestActions.find(".running-hidden").hide(); //Hide Resume guestActions.find(".resume-hidden").hide(); } if (vmPoweredOffBool) { //VM is powered off //Hide PowerOff guestActions.find(".shutoff-hidden").hide(); //Hide Pause guestActions.find(".pause-hidden").hide(); //Hide Resume guestActions.find(".resume-hidden").hide(); } var consoleActions=guestActions.find("[name=vm-console]"); if ((vmObject.graphics['type'] == 'vnc') || (vmObject.graphics['type'] == 'spice')) { consoleActions.on("click", kimchi.openVmConsole); consoleActions.show(); } else { //we don't recognize the VMs supported graphics, so hide the menu choice consoleActions.hide(); consoleActions.off("click",kimchi.openVmConsole); } //Setup action event handlers if(!(vmObject.isCloning || vmObject.isCreating)){ guestActions.find("[name=vm-start]").on({click : kimchi.vmstart}); guestActions.find("[name=vm-poweroff]").on({click : kimchi.vmpoweroff}); if ((vmRunningBool) || (vmSuspendedBool)) { //If the guest is not running, do not enable reset; otherwise, reset is enabled (when running or paused) guestActions.find("[name=vm-reset]").on({click : kimchi.vmreset}); //If the guest is not running, do not enable shutdown;otherwise, shutdown is enabled (when running or paused) guestActions.find("[name=vm-shutdown]").on({click : kimchi.vmshutdown}); } if (vmSuspendedBool) { guestActions.find("[name=vm-resume]").on({click : kimchi.vmresume}); } if (vmRunningBool) { guestActions.find("[name=vm-pause]").on({click : kimchi.vmsuspend}); } guestActions.find("[name=vm-edit]").on({click : kimchi.vmedit}); guestActions.find("[name=vm-delete]").on({click : kimchi.vmdelete}); guestActions.find("[name=vm-clone]").click(function(){ var guest = $(this).closest('li[name=guest]').attr("id"); kimchi.confirm({ title : i18n['KCHAPI6006M'], content : i18n['KCHVM6010M'], confirm : i18n['KCHAPI6002M'], cancel : i18n['KCHAPI6003M'] }, function() { kimchi.cloneGuest(guest, function(data){ kimchi.listVmsAuto(); }); }, null); }); //Maintain menu open state var actionMenu=guestActions.find("div[name=actionmenu]"); if (openMenu) { $('.popover', actionMenu).toggle(); } }else{ guestActions.find('.btn').attr('disabled', true); $('.popover', guestActions.find("div[name=actionmenu]")).remove(); result.find('.guest-pending').removeClass('hide-content'); pendingText = result.find('.guest-pending .text') if(vmObject.isCloning) pendingText.text(i18n['KCHAPI6009M']); else pendingText.text(i18n['KCHAPI6008M']); } return result; }; kimchi.circleGaugeInit = function(topElement, divName, display, percentage){ var gauge=topElement.find('div[name="' + divName + '"] .circleGauge'); if(gauge) { var data=Object(); data.percentage = percentage; data.display = display; gauge.data(data); } gauge.circleGauge(); return(gauge); }; kimchi.guestSetRequestHeader = function(xhr) { xhr.setRequestHeader('Accept', 'text/html'); }; kimchi.guest_main = function() { if(kimchi.tabMode['guests'] === 'admin') { $('.tools').attr('style','display'); $("#vm-add").on("click", function(event) { kimchi.window.open('guest-add.html'); }); } kimchi.guestTemplate = $('#guest-tmpl').html(); kimchi.guestElem=$('
').html(kimchi.guestTemplate).find('li'); $('#guests-root-container').on('remove', function() { kimchi.vmTimeout && clearTimeout(kimchi.vmTimeout); }); kimchi.listVmsAuto() }; kimchi.editTemplate = function(guestTemplate, oldPopStat) { if (oldPopStat) { return guestTemplate.replace("vm-action", "vm-action open"); } return guestTemplate; }; kimchi-1.5.0/ui/js/src/kimchi.guest_media_main.js000066400000000000000000000035721254252253000217030ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ kimchi.guest_media_main = function() { var refreshCDROMs = function() { kimchi.listVMStorages({ vm: kimchi.selectedGuest, storageType: 'cdrom' }, function(storages) { var rowHTML = $('#cdrom-row-tmpl').html(); var container = $('#guest-edit-cdrom-row-container'); $(container).empty(); $.each(storages, function(index, storage) { storage['vm'] = kimchi.selectedGuest; var templated = kimchi.substitute(rowHTML, storage); container.append(templated); }); var replaceCDROM = function(event) { event.preventDefault(); kimchi.selectedGuestStorage = $(this).data('dev'); kimchi.window.open("guest-cdrom-edit.html"); }; $('input[type="text"][name="cdrom"]', container).on('click', replaceCDROM); $('.replace', container).on('click', replaceCDROM); }); }; refreshCDROMs(); var onReplaced = function(params) { refreshCDROMs(); }; kimchi.topic('kimchi/vmCDROMReplaced').subscribe(onReplaced); kimchi.clearGuestMedia = function() { kimchi.topic('kimchi/vmCDROMReplaced').unsubscribe(onReplaced); }; }; kimchi-1.5.0/ui/js/src/kimchi.guest_storage_add.main.js000066400000000000000000000151401254252253000230110ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2014-2015 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ kimchi.guest_storage_add_main = function() { var types = [{ label: 'cdrom', value: 'cdrom', }, { label: 'disk', value: 'disk', }]; var typesRunning = [{ label: 'disk', value: 'disk' }]; var storageAddForm = $('#form-guest-storage-add'); var submitButton = $('#guest-storage-button-add'); var typeTextbox = $('input[name="type"]', storageAddForm); var pathTextbox = $('input[name="path"]', storageAddForm); var poolTextbox = $('input[name="pool"]', storageAddForm); var volTextbox = $('input[name="vol"]', storageAddForm); typeTextbox.change(function() { var pathObject = {'cdrom': ".path-section", 'disk': '.volume-section'} selectType = $(this).val(); $.each(pathObject, function(type, value) { if(selectType == type){ $(value).removeClass('hidden'); } else { $(value).addClass('hidden'); } }); if ($(".path-section").hasClass('hidden')) { $(poolTextbox).val('default'); $(poolTextbox).change(); $(pathTextbox).val(""); } else { $(poolTextbox).val(""); $(volTextbox).val(""); } }); kimchi.listStoragePools(function(result) { var options = []; if (result && result.length) { $.each(result, function(index, storagePool) { if ((storagePool.state=="active") && (storagePool.type !== 'kimchi-iso')) { options.push({ label: storagePool.name, value: storagePool.name }); } }); kimchi.select('guest-add-storage-pool-list', options); } }); poolTextbox.change(function() { var options = []; kimchi.listStorageVolumes($(this).val(), function(result) { var validVolType = { cdrom: /iso/, disk: /^(raw|qcow|qcow2|bochs|qed|vmdk)$/}; $('#guest-disk').selectMenu(); if (result.length) { $.each(result, function(index, value) { // Only unused volume can be attached if (value.used_by.length == 0 && (value.type != 'file' || validVolType[selectType].test(value.format))) { options.push({ label: value.name, value: value.name }); } }); if (options.length) { $(volTextbox).val(options[0].value); $(volTextbox).change(); } } $('#guest-disk').selectMenu("setData", options); }); }); typeTextbox.change(function() { var pathObject = {'cdrom': ".path-section", 'disk': '.volume-section'} var selectType = $(this).val(); $.each(pathObject, function(type, value) { if(selectType == type){ $(value).removeClass('hidden'); } else { $(value).addClass('hidden'); } }); }); if (kimchi.thisVMState === 'running') { types =typesRunning; $(typeTextbox).val('disk'); typeTextbox.change(); poolTextbox.change(); } var selectType = $(typeTextbox).val(); kimchi.select('guest-storage-type-list', types); var validateCDROM = function(settings) { if (/^((https|http|ftp|ftps|tftp|\/).*)+$/.test(settings['path'])) return true; else { kimchi.message.error.code('KCHVMSTOR0001E'); return false; } } var validateDisk = function(settings) { if (settings['pool'] && settings['vol']) return true; else { kimchi.message.error.code('KCHVMSTOR0002E'); return false; } } validator = {cdrom: validateCDROM, disk: validateDisk}; var submitForm = function(event) { if (submitButton.prop('disabled')) { return false; } var formData = storageAddForm.serializeObject(); var settings = { vm: kimchi.selectedGuest, type: typeTextbox.val(), }; $(submitButton).prop('disabled', true); $.each([pathTextbox, poolTextbox, volTextbox], function(i, c) { $(c).prop('disabled', true); val = $(c).val() if (val && val != '') { settings[$(c).attr('name')] = $(c).val(); } }); // Validate form for cdrom and disk validateSpecifiedForm = validator[settings['type']]; if (!validateSpecifiedForm(settings)) { $(submitButton).prop('disabled', false); $.each([submitButton, pathTextbox, poolTextbox, volTextbox], function(i, c) { $(c).prop('disabled', false); }); return false; } $(submitButton).addClass('loading').text(i18n['KCHVMCD6003M']); kimchi.addVMStorage(settings, function(result) { kimchi.window.close(); kimchi.topic('kimchi/vmCDROMAttached').publish({ result: result }); }, function(result) { var errText = result['reason'] || result['responseJSON']['reason']; kimchi.message.error(errText); $.each([submitButton, pathTextbox, poolTextbox, volTextbox], function(i, c) { $(c).prop('disabled', false); }); $(submitButton).removeClass('loading').text(i18n['KCHVMCD6002M']); }); event.preventDefault(); }; storageAddForm.on('submit', submitForm); submitButton.on('click', submitForm); pathTextbox.on('change input propertychange', function(event) { $(submitButton).prop('disabled', $(this).val() === ''); }); volTextbox.on('change propertychange', function (event) { $(submitButton).prop('disabled', $(this).val() === ''); }); }; kimchi-1.5.0/ui/js/src/kimchi.host.js000066400000000000000000000737471254252253000174010ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ kimchi.host={}; kimchi.host_main = function() { var expand = function(header, toExpand) { var controlledNode = $(header).attr('aria-controls'); $('#' + controlledNode)[toExpand ? 'removeClass' : 'addClass']('hidden'); $(header).attr('aria-expanded', toExpand ? 'true' : 'false'); }; var repositoriesGrid = null; var initRepositoriesGrid = function(repo_type) { var gridFields=[]; if (repo_type == "yum") { gridFields=[{ name: 'repo_id', label: i18n['KCHREPO6004M'], 'class': 'repository-id' }, { name: 'config[repo_name]', label: i18n['KCHREPO6005M'], 'class': 'repository-name' }, { name: 'enabled', label: i18n['KCHREPO6009M'], 'class': 'repository-enabled' }]; } else if (repo_type == "deb") { gridFields=[{ name: 'baseurl', label: i18n['KCHREPO6006M'], makeTitle: true, 'class': 'repository-baseurl deb' }, { name: 'enabled', label: i18n['KCHREPO6009M'], 'class': 'repository-enabled deb' }, { name: 'config[dist]', label: "dist", 'class': 'repository-gpgcheck deb' }, { name: 'config[comps]', label: "comps", 'class': 'repository-gpgcheck deb' }]; } else { gridFields=[{ name: 'repo_id', label: i18n['KCHREPO6004M'], 'class': 'repository-id' }, { name: 'enabled', label: i18n['KCHREPO6009M'], 'class': 'repository-enabled' }, { name: 'baseurl', label: i18n['KCHREPO6006M'], makeTitle: true, 'class': 'repository-baseurl' }]; } repositoriesGrid = new kimchi.widget.Grid({ container: 'repositories-grid-container', id: 'repositories-grid', title: i18n['KCHREPO6003M'], toolbarButtons: [{ id: 'repositories-grid-add-button', label: i18n['KCHREPO6012M'], onClick: function(event) { kimchi.window.open({url:'repository-add.html', class: repo_type}); } }, { id: 'repositories-grid-enable-button', label: i18n['KCHREPO6016M'], disabled: true, onClick: function(event) { var repository = repositoriesGrid.getSelected(); if(!repository) { return; } var name = repository['repo_id']; var enable = !repository['enabled']; $(this).prop('disabled', true); kimchi.enableRepository(name, enable, function() { kimchi.topic('kimchi/repositoryUpdated').publish(); }); } }, { id: 'repositories-grid-edit-button', label: i18n['KCHREPO6013M'], disabled: true, onClick: function(event) { var repository = repositoriesGrid.getSelected(); if(!repository) { return; } kimchi.selectedRepository = repository['repo_id']; kimchi.window.open({url:'repository-edit.html', class: repo_type}); } }, { id: 'repositories-grid-remove-button', label: i18n['KCHREPO6014M'], disabled: true, onClick: function(event) { var repository = repositoriesGrid.getSelected(); if(!repository) { return; } var settings = { title : i18n['KCHREPO6001M'], content : i18n['KCHREPO6002M'], confirm : i18n['KCHAPI6004M'], cancel : i18n['KCHAPI6003M'] }; kimchi.confirm(settings, function() { kimchi.deleteRepository( repository['repo_id'], function(result) { kimchi.topic('kimchi/repositoryDeleted').publish(result); }, function(error) { } ); }); } }], onRowSelected: function(row) { var repository = repositoriesGrid.getSelected(); if(!repository) { return; } $('#repositories-grid-remove-button').prop('disabled', false); $('#repositories-grid-edit-button').prop('disabled', false); var enabled = repository['enabled']; $('#repositories-grid-enable-button') .text(i18n[enabled ? 'KCHREPO6017M' : 'KCHREPO6016M']) .prop('disabled', false); }, frozenFields: [], fields: gridFields, data: listRepositories }); }; var listRepositories = function(gridCallback) { kimchi.listRepositories(function(repositories) { if($.isFunction(gridCallback)) { gridCallback(repositories); } else { if(repositoriesGrid) { repositoriesGrid.setData(repositories); } else { initRepositoriesGrid(); repositoriesGrid.setData(repositories); } } }, function(error) { var message = error && error['responseJSON'] && error['responseJSON']['reason']; if($.isFunction(gridCallback)) { gridCallback([]); } repositoriesGrid && repositoriesGrid.showMessage(message || i18n['KCHUPD6008M']); }); $('#repositories-grid-remove-button').prop('disabled', true); $('#repositories-grid-edit-button').prop('disabled', true); $('#repositories-grid-enable-button').prop('disabled', true); }; var softwareUpdatesGridID = 'software-updates-grid'; var softwareUpdatesGrid = null; var progressAreaID = 'software-updates-progress-textarea'; var reloadProgressArea = function(result) { var progressArea = $('#' + progressAreaID)[0]; $(progressArea).text(result['message']); var scrollTop = $(progressArea).prop('scrollHeight'); $(progressArea).prop('scrollTop', scrollTop); }; var initSoftwareUpdatesGrid = function(softwareUpdates) { softwareUpdatesGrid = new kimchi.widget.Grid({ container: 'software-updates-grid-container', id: softwareUpdatesGridID, title: i18n['KCHUPD6001M'], rowSelection: 'disabled', toolbarButtons: [{ id: softwareUpdatesGridID + '-update-button', label: i18n['KCHUPD6006M'], disabled: true, onClick: function(event) { var updateButton = $(this); var progressArea = $('#' + progressAreaID)[0]; $('#software-updates-progress-container').removeClass('hidden'); $(progressArea).text(''); !kimchi.isElementInViewport(progressArea) && progressArea.scrollIntoView(); $(updateButton).text(i18n['KCHUPD6007M']).prop('disabled', true); kimchi.updateSoftware(function(result) { reloadProgressArea(result); $(updateButton).text(i18n['KCHUPD6006M']).prop('disabled', false); kimchi.topic('kimchi/softwareUpdated').publish({ result: result }); }, function(error) { var message = error && error['responseJSON'] && error['responseJSON']['reason']; kimchi.message.error(message || i18n['KCHUPD6009M']); $(updateButton).text(i18n['KCHUPD6006M']).prop('disabled', false); }, reloadProgressArea); } }], frozenFields: [], fields: [{ name: 'package_name', label: i18n['KCHUPD6002M'], 'class': 'software-update-name' }, { name: 'version', label: i18n['KCHUPD6003M'], 'class': 'software-update-version' }, { name: 'arch', label: i18n['KCHUPD6004M'], 'class': 'software-update-arch' }, { name: 'repository', label: i18n['KCHUPD6005M'], 'class': 'software-update-repos' }], data: listSoftwareUpdates }); }; var listSoftwareUpdates = function(gridCallback) { kimchi.listSoftwareUpdates(function(softwareUpdates) { if($.isFunction(gridCallback)) { gridCallback(softwareUpdates); } else { if(softwareUpdatesGrid) { softwareUpdatesGrid.setData(softwareUpdates); } else { initSoftwareUpdatesGrid(softwareUpdates); } } var updateButton = $('#' + softwareUpdatesGridID + '-update-button'); $(updateButton).prop('disabled', softwareUpdates.length === 0); }, function(error) { var message = error && error['responseJSON'] && error['responseJSON']['reason']; if($.isFunction(gridCallback)) { gridCallback([]); } softwareUpdatesGrid && softwareUpdatesGrid.showMessage(message || i18n['KCHUPD6008M']); }); }; var reportGridID = 'available-reports-grid'; var reportGrid = null; var enableReportButtons = function(toEnable) { var buttonID = '#{grid}-{btn}-button'; $.each(['rename', 'remove', 'download'], function(i, n) { $(kimchi.substitute(buttonID, { grid: reportGridID, btn: n })).prop('disabled', !toEnable); }); }; var initReportGrid = function(reports) { reportGrid = new kimchi.widget.Grid({ container: 'available-reports-grid-container', id: reportGridID, title: i18n['KCHDR6002M'], toolbarButtons: [{ id: reportGridID + '-generate-button', label: i18n['KCHDR6006M'], onClick: function(event) { kimchi.window.open('report-add.html'); } }, { id: reportGridID + '-rename-button', label: i18n['KCHDR6008M'], disabled: true, onClick: function(event) { var report = reportGrid.getSelected(); if(!report) { return; } kimchi.selectedReport = report['name']; kimchi.window.open('report-rename.html'); } }, { id: reportGridID + '-remove-button', label: i18n['KCHDR6009M'], disabled: true, onClick: function(event) { var report = reportGrid.getSelected(); if(!report) { return; } var settings = { title : i18n['KCHAPI6004M'], content : i18n['KCHDR6001M'], confirm : i18n['KCHAPI6002M'], cancel : i18n['KCHAPI6003M'] }; kimchi.confirm(settings, function() { kimchi.deleteReport({ name: report['name'] }, function(result) { listDebugReports(); }, function(error) { kimchi.message.error(error.responseJSON.reason); }); }); } }, { id: reportGridID + '-download-button', label: i18n['KCHDR6010M'], disabled: true, onClick: function(event) { var report = reportGrid.getSelected(); if(!report) { return; } kimchi.downloadReport({ file: report['uri'] }); } }], onRowSelected: function(row) { var report = reportGrid.getSelected(); // Only enable report buttons if the selected line is not a // pending report if (report['time'] == i18n['KCHDR6007M']) { var gridElement = $('#'+ reportGridID); var row = $('tr:contains(' + report['name'] + ')', gridElement); enableReportButtons(false); row.attr('class', ''); } else { enableReportButtons(true); } }, frozenFields: [], fields: [{ name: 'name', label: i18n['KCHDR6003M'], 'class': 'debug-report-name' }, { name: 'time', label: i18n['KCHDR6005M'], 'class': 'debug-report-time' }], data: reports }); }; var getPendingReports = function() { var reports = [] var filter = 'status=running&target_uri=' + encodeURIComponent('^/debugreports/*') kimchi.getTasksByFilter(filter, function(tasks) { for(var i = 0; i < tasks.length; i++) { reportName = tasks[i].target_uri.replace(/^\/debugreports\//, '') || i18n['KCHDR6012M']; reports.push({'name': reportName, 'time': i18n['KCHDR6007M']}) if(kimchi.trackingTasks.indexOf(tasks[i].id) >= 0) { continue; } kimchi.trackTask(tasks[i].id, function(result) { kimchi.topic('kimchi/debugReportAdded').publish(); }, function(result) { // Error message from Async Task status if (result['message']) { var errText = result['message']; } // Error message from standard kimchi exception else { var errText = result['responseJSON']['reason']; } result && kimchi.message.error(errText); kimchi.topic('kimchi/debugReportAdded').publish(); }, null); } }, null, true); return reports; }; var listDebugReports = function() { kimchi.listReports(function(reports) { pendingReports = getPendingReports(); allReports = pendingReports.concat(reports); $('#debug-report-section').removeClass('hidden'); // Row selection will be cleared so disable buttons here enableReportButtons(false); if(reportGrid) { reportGrid.setData(allReports); } else { initReportGrid(allReports); } // Set id-debug-img to pending reports // It will display a loading icon var gridElement = $('#' + reportGridID); $.each($('td:contains(' + i18n['KCHDR6007M'] + ')', gridElement), function(index, row) { $(row).parent().addClass('no-hover'); $(row).attr('id', 'id-debug-img'); }); }, function(error) { if(error['status'] == 403) { $('#debug-report-section').addClass('hidden'); return; } $('#debug-report-section').removeClass('hidden'); }); }; var shutdownButtonID = '#host-button-shutdown'; var restartButtonID = '#host-button-restart'; var shutdownHost = function(params) { var settings = { title : i18n['KCHAPI6004M'], content : i18n['KCHHOST6008M'], confirm : i18n['KCHAPI6002M'], cancel : i18n['KCHAPI6003M'] }; kimchi.confirm(settings, function() { kimchi.shutdown(params); $(shutdownButtonID).prop('disabled', true); $(restartButtonID).prop('disabled', true); // Check if there is any VM is running. kimchi.listVMs(function(vms) { for(var i = 0; i < vms.length; i++) { if(vms[i]['state'] === 'running') { kimchi.message.error.code('KCHHOST6001E'); $(shutdownButtonID).prop('disabled', false); $(restartButtonID).prop('disabled', false); return; } } }); }, function() { }); }; var initPage = function() { $('#host-info-container .section-header').each(function(i, header) { $('').prependTo(header); var toExpand = $(header).attr('aria-expanded') !== 'false'; expand(header, toExpand); }); $('#host-info-container').on('click', '.section-header', function(event) { var toExpand = $(this).attr('aria-expanded') === 'false'; expand(this, toExpand); }); $('#host-button-shutdown').on('click', function(event) { shutdownHost(null); }); $('#host-button-restart').on('click', function(event) { shutdownHost({ reboot: true }); }); var setupUI = function() { if (kimchi.capabilities == undefined) { setTimeout(setupUI, 2000); return; } if((kimchi.capabilities['repo_mngt_tool']) && (kimchi.capabilities['repo_mngt_tool']!="None")) { initRepositoriesGrid(kimchi.capabilities['repo_mngt_tool']); $('#repositories-section').switchClass('hidden', kimchi.capabilities['repo_mngt_tool']); kimchi.topic('kimchi/repositoryAdded') .subscribe(listRepositories); kimchi.topic('kimchi/repositoryUpdated') .subscribe(listRepositories); kimchi.topic('kimchi/repositoryDeleted') .subscribe(listRepositories); } if(kimchi.capabilities['update_tool']) { $('#software-update-section').removeClass('hidden'); initSoftwareUpdatesGrid(); kimchi.topic('kimchi/softwareUpdated') .subscribe(listSoftwareUpdates); $('#software-updates-progress-container').accordion({ collapsible: true }); } if(kimchi.capabilities['system_report_tool']) { listDebugReports(); kimchi.topic('kimchi/debugReportAdded') .subscribe(listDebugReports); kimchi.topic('kimchi/debugReportRenamed') .subscribe(listDebugReports); } }; setupUI(); }; kimchi.getHost(function(data) { var htmlTmpl = $('#host-tmpl').html(); data['logo'] = data['logo'] || ''; data['memory'] = kimchi.formatMeasurement(data['memory'], { fixed: 2 }); var templated = kimchi.substitute(htmlTmpl, data); $('#host-content-container').html(templated); initPage(); initTracker(); }); var StatsMgr = function() { var statsArray = { cpu: { u: { type: 'percent', legend: i18n['KCHHOST6002M'], points: [] } }, memory: { u: { type: 'value', base: 2, fixed: 2, legend: i18n['KCHHOST6003M'], points: [] } }, diskIO: { r: { type: 'value', base: 2, fixed: 2, unit: 'B/s', legend: i18n['KCHHOST6004M'], points: [] }, w: { type: 'value', base: 2, fixed: 2, unit: 'B/s', legend: i18n['KCHHOST6005M'], 'class': 'disk-write', points: [] } }, networkIO: { r: { type: 'value', base: 2, fixed: 2, unit: 'B/s', legend: i18n['KCHHOST6006M'], points: [] }, s: { type: 'value', base: 2, fixed: 2, unit: 'B/s', legend: i18n['KCHHOST6007M'], 'class': 'network-sent', points: [] } } }; var SIZE = 20; var cursor = SIZE; var add = function(stats) { for(var key in stats) { var item = stats[key]; for(var metrics in item) { var value = item[metrics]['v']; var max = item[metrics]['max']; var unifiedMetrics = statsArray[key][metrics]; var ps = unifiedMetrics['points']; if(!Array.isArray(value)){ ps.push(value); if(ps.length > SIZE + 1) { ps.shift(); } } else{ ps=ps.concat(value); ps.splice(0, ps.length-SIZE-1); unifiedMetrics['points']=ps; } if(max !== undefined) { unifiedMetrics['max'] = max; } else { if(unifiedMetrics['type'] !== 'value') { continue; } max = -Infinity; $.each(ps, function(i, value) { if(value > max) { max = value; } }); if(max === 0) { ++max; } max *= 1.1; unifiedMetrics['max'] = max; } } } cursor++; }; var get = function(which) { var stats = statsArray[which]; var lines = []; for(var k in stats) { var obj = stats[k]; var line = { type: obj['type'], base: obj['base'], unit: obj['unit'], fixed: obj['fixed'], legend: obj['legend'] }; if(obj['max']) { line['max'] = obj['max']; } if(obj['class']) { line['class'] = obj['class']; } var ps = obj['points']; var numStats = ps.length; var unifiedPoints = []; $.each(ps, function(i, value) { unifiedPoints.push({ x: cursor - numStats + i, y: value }); }); line['points'] = unifiedPoints; lines.push(line); } return lines; }; return { add: add, get: get }; }; var Tracker = function(charts) { var charts = charts; var timer = null; var statsPool = new StatsMgr(); var setCharts = function(newCharts) { charts = newCharts; for(var key in charts) { var chart = charts[key]; chart.updateUI(statsPool.get(key)); } }; var self = this; var UnifyStats = function(stats) { var result= { cpu: { u: { v: stats['cpu_utilization'] } }, memory: { u: { } }, diskIO: { r: { v: stats['disk_read_rate'] }, w: { v: stats['disk_write_rate'] } }, networkIO: { r: { v: stats['net_recv_rate'] }, s: { v: stats['net_sent_rate'] } } }; if(Array.isArray(stats['memory'])){ result.memory.u['v']=[]; result.memory.u['max']=-Infinity; for(var i=0;i * 2) HTML DOM lang attribute; or if not set -> * 3) DEFAULT (en_US). */ get: function() { return kimchi.cookie.get('kimchiLang') || $('html').prop('lang') || 'en_US'; }, set: function(lang) { kimchi.cookie.set('kimchiLang', lang, 365); } }; kimchi-1.5.0/ui/js/src/kimchi.line-chart.js000066400000000000000000000143061254252253000204340ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * new kimchi.widget.LineChart({ * node: 'line-chart-cpu', * id: 'line-chart', * type: 'value' * }); */ kimchi.widget.LineChart = function(params) { var container = $('#' + params['node']); container.addClass('chart-container'); var height = container.height(); var width = container.width(); var numHLines = 4; var linesSpace = height / numHLines; var period = params['period'] || 20; var xFactor = width / period; var yFactor = height / 100; var xStart = params['xStart'] || 0; var linesOffset = 0; var canvasID = params['id']; var maxValue = params['maxValue'] || -Infinity; var type = params['type']; var chartVAxis = null; var chartTitle = null; var chartLegend = null; var seriesMap = {}; var formatSettings = {}; var setMaxValue = function(newValue) { maxValue = newValue; }; /** * * settings: { * 'class': 'disk-read-rate' * } */ var updateUI = function(data) { var container = $('#' + params['node']); if(!container.length) { return; } if(!$.isArray(data)) { data = [data]; } var seriesCount = 0; var singleSeries = data.length === 1; var firstSeries = data[0]; // TODO: Multiple axes support. if(type === 'value') { $.each(data, function(i, series) { if(series['max'] > maxValue) { maxValue = series['max']; formatSettings = { base: series['base'], unit: series['unit'], fixed: series['fixed'] }; } }); } var canvasNode = $('#' + canvasID); canvasNode.length && canvasNode.remove(); var htmlStr = [ '', '' ]; for(var x = linesOffset; x < width; x += linesSpace) { htmlStr.push( '' ); } linesOffset -= xFactor; while(linesOffset < 0) { linesOffset = linesSpace + linesOffset; } for(var y = height - linesSpace; y > 0; y -= linesSpace) { htmlStr.push( '' ); } var maxValueLabel = i18n['KCHHOST6001M'] + ' ' + (type === 'value' ? kimchi.formatMeasurement(maxValue, formatSettings) : '100%'); if(!chartVAxis) { chartVAxis = $('
' + maxValueLabel + '
' ); container.before(chartVAxis); } else { chartVAxis.text(maxValueLabel); } seriesNames = []; $.each(data, function(i, series) { var points = series['points']; var className = series['class']; var latestPoint = points.slice(-1).pop(); xStart = latestPoint['x'] - period; htmlStr.push(''); }); htmlStr.push(''); var canvasNode = $(htmlStr.join('')).appendTo(container); if(!chartLegend) { chartLegend = $('
'); container.after(chartLegend); } else { chartLegend.empty(); } $('polyline.series', canvasNode).each(function(i, polyline) { var wrapper = $('
') .appendTo(chartLegend); $([ '', '', '' ].join('')).appendTo(wrapper); $('line', wrapper).css({ stroke: $(polyline).css('stroke'), 'stroke-width': $(polyline).css('stroke-width') }); var label = data[i]['legend']; var base = data[i]['base']; $('') .appendTo(wrapper); var latestPoint = data[i]['points'].slice(-1).pop(); var latestValue = latestPoint['y']; if(type === 'value') { latestValue = kimchi.formatMeasurement( latestValue, formatSettings ); } else { latestValue += '%'; } $('
' + latestValue + '
') .appendTo(wrapper); }); }; return { setMaxValue: setMaxValue, updateUI: updateUI } }; kimchi-1.5.0/ui/js/src/kimchi.login.js000066400000000000000000000044031254252253000175130ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2014-2015 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ kimchi.login_main = function() { var selectedLanguage = kimchi.lang.get(); $('#userLang').val(selectedLanguage); $('#userLang').on('change', function() { kimchi.lang.set($(this).val()); location.reload(); }); var query = window.location.search; var error = /.*error=(.*?)(&|$)/g.exec(query); if (error && error[1] == "sessionTimeout") { $("#messSession").show(); } var userNameBox = $('#username'); var passwordBox = $('#password'); var loginButton = $('#btn-login'); var login = function(event) { $("#login").hide(); $("#logging").show(); var userName = userNameBox.val(); userName && kimchi.user.setUserName(userName); var settings = { username: userName, password: passwordBox.val() }; kimchi.login(settings, function(data) { var query = window.location.search; var next = /.*next=(.*?)(&|$)/g.exec(query); if (next) { var next_url = decodeURIComponent(next[1]); } else { var lastPage = kimchi.cookie.get('lastPage'); var next_url = lastPage ? lastPage.replace(/\"/g,'') : "/"; } kimchi.cookie.set('roles',JSON.stringify(data.roles)); window.location.replace(window.location.pathname.replace(/\/+login.html/, '') + next_url) }, function() { $("#messUserPass").show(); $("#messSession").hide(); $("#logging").hide(); $("#login").show(); }); return false; }; $('#btn-login').bind('click', login); }; kimchi-1.5.0/ui/js/src/kimchi.main.js000066400000000000000000000311101254252253000173220ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2015 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ kimchi.tabMode = {}; kimchi.capabilities = undefined; kimchi.getCapabilities(function(result) { kimchi.capabilities = result; if(kimchi.capabilities.federation=="on") $('#peers').removeClass('hide-content'); }, function() { kimchi.capabilities = {}; }); kimchi.main = function() { kimchi.isLoggingOut = false; kimchi.popable(); var genTabs = function(tabs) { var tabsHtml = []; $(tabs).each(function(i, tab) { var title = tab['title']; var path = tab['path']; var mode = tab['mode']; if (mode != 'none') { var helpPath = kimchi.checkHelpFile(path); var disableHelp = (helpPath.length == 0 ? "disableHelp" : helpPath); tabsHtml.push( '
  • ', '', title, '', '', '
  • ' ); } }); return tabsHtml.join(''); }; var parseTabs = function(xmlData) { var tabs = []; $(xmlData).find('tab').each(function() { var $tab = $(this); var titleKey = $tab.find('title').text(); var title = i18n[titleKey] ? i18n[titleKey] : titleKey; var path = $tab.find('path').text(); var roles = kimchi.cookie.get('roles'); if (roles) { var role = JSON.parse(roles)[titleKey.toLowerCase()]; var mode = $tab.find('[role="' + role + '"]').attr('mode'); kimchi.tabMode[titleKey.toLowerCase()] = mode; tabs.push({ title: title, path: path, mode: mode }); } else { document.location.href = 'login.html'; } }); return tabs; }; var retrieveTabs = function(url) { var tabs; $.ajax({ url : url, async : false, success : function(xmlData) { tabs = parseTabs(xmlData); } }); return tabs; }; var tabConfigUrl = 'config/ui/tabs.xml'; var pluginConfigUrl = 'plugins/{plugin}/ui/config/tab-ext.xml'; var pluginI18nUrl = 'plugins/{plugin}/i18n.json'; var DEFAULT_HASH; var buildTabs = function(callback) { var tabs = retrieveTabs(tabConfigUrl); kimchi.listPlugins(function(plugins) { $(plugins).each(function(i, p) { var url = kimchi.substitute(pluginConfigUrl, { plugin: p }); var i18nUrl = kimchi.substitute(pluginI18nUrl, { plugin: p }); kimchi.getI18n(function(i18nObj){ $.extend(i18n, i18nObj)}, function(i18nObj){ //i18n is not define by plugin }, i18nUrl, true); tabs.push.apply(tabs, retrieveTabs(url)); }); var defaultTab = tabs[1] var defaultTabPath = defaultTab && defaultTab['path'] // Remove file extension from 'defaultTabPath' DEFAULT_HASH = defaultTabPath && defaultTabPath.substring(0, defaultTabPath.lastIndexOf('.')) $('#nav-menu').append(genTabs(tabs)); callback && callback(); }, function(data) { kimchi.message.error(data.responseJSON.reason); }, true); }; var onLanguageChanged = function(lang) { kimchi.lang.set(lang); location.reload(); }; /** * Do the following setup: * 1) Clear any timing events. * 2) If the given URL is invalid (i.e., no corresponding href value in * page tab list.), then clear location.href and inform the user; * * Or else: * Move the page tab indicator to the right position; * Load the page content via Ajax. */ var onKimchiRedirect = function(url) { /* * Find the corresponding tab node and animate the arrow indicator to * point to the tab. If nothing found, inform user the URL is invalid * and clear location.hash to jump to home page. */ var tab = $('#nav-menu a[href="' + url + '"]'); if (tab.length === 0) { location.hash = ''; return; } // Animate arrow indicator. var left = $(tab).parent().position().left; var width = $(tab).parent().width(); $('.menu-arrow').stop().animate({ left : left + width / 2 - 10 }); // Update the visual style of tabs; focus the selected one. $('#nav-menu a').removeClass('current'); $(tab).addClass('current'); $(tab).focus(); // Disable Help button according to selected tab if ($(tab).hasClass("disableHelp")) { $('#btn-help').css('cursor', "not-allowed"); $('#btn-help').off("click"); } else { $('#btn-help').css('cursor', "pointer"); $('#btn-help').on("click", kimchi.openHelp); } // Load page content. loadPage(url); }; /** * Use Ajax to dynamically load a page without a page refreshing. Handle * arrow cursor animation, DOM node focus, and page content rendering. */ var loadPage = function(url) { // Get the page content through Ajax and render it. url && $('#main').load(url, function(responseText, textStatus, jqXHR) { if (jqXHR['status'] === 401 || jqXHR['status'] === 303) { var isSessionTimeout = jqXHR['responseText'].indexOf("sessionTimeout")!=-1; document.location.href= isSessionTimeout ? 'login.html?error=sessionTimeout' : 'login.html'; return; } }); }; /* * Update page content. * 1) If user types in the main page URL without hash, then we apply the * default hash. e.g., http://kimchi.company.com:8000; * 2) If user types a URL with hash, then we publish an "redirect" event * to load the page, e.g., http://kimchi.company.com:8000/#templates. */ var updatePage = function() { // Parse hash string. var hashString = (location.hash && location.hash.substr(1)); /* * If hash string is empty, then apply the default one; * or else, publish an "redirect" event to load the page. */ if (!hashString) { location.hash = DEFAULT_HASH; } else { kimchi.topic('redirect').publish(hashString + '.html'); } }; /** * Register listeners including: * 1) Kimchi redirect event * 2) hashchange event * 3) Tab list click event * 4) Log-out button click event * 5) About button click event * 6) Help button click event * 7) Peers button click event */ var searchingPeers = false; var initListeners = function() { kimchi.topic('languageChanged').subscribe(onLanguageChanged); kimchi.topic('redirect').subscribe(onKimchiRedirect); /* * If hash value is changed, then we know the user is intended to load * another page. */ window.onhashchange = updatePage; /* * Register click listener of tabs. Replace the default reloading page * behavior of with Ajax loading. */ $('#nav-menu').on('click', 'a.item', function(event) { var href = $(this).attr('href'); // Remove file extension from 'href' location.hash = href.substring(0,href.lastIndexOf('.')) /* * We use the HTML file name for hash, like: guests for guests.html * and templates for templates.html. * Retrieve hash value from the given URL and update location's * hash part. It has 2 effects: one is to publish Kimchi "redirect" * event to trigger listener, the other is to put an entry into the * browser's address history to make pages be bookmark-able. */ // Prevent causing browser redirecting to other page. event.preventDefault(); }); // Perform logging out via Ajax request. $('#btn-logout').on('click', function() { kimchi.logout(function() { kimchi.isLoggingOut = true; document.location.href = "login.html"; }, function(err) { kimchi.message.error(err.responseJSON.reason); }); }); // Set handler for about button $('#btn-about').on('click', function(event) { kimchi.window.open({"content": $('#about-tmpl').html()}); event.preventDefault(); }); // Set handler for help button $('#btn-help').on('click', kimchi.openHelp); // Set handler to peers drop down $('#peers').on('click', function() { // Check if any request is in progress if ($('.popover', '#peers').is(':visible') || searchingPeers == true) return $('#search-peers').show(); $('#no-peers').addClass('hide-content'); $('a', '#peers').remove(); searchingPeers = true; kimchi.getPeers(function(data){ $('#search-peers').hide(); if (data.length == 0) $('#no-peers').removeClass('hide-content'); for(var i=0; i"+data[i]+""); } searchingPeers = false; }); }); }; var initUI = function() { $(document).bind('ajaxError', function(event, jqXHR, ajaxSettings, errorThrown) { if (!ajaxSettings['kimchi']) { return; } if (jqXHR['status'] === 401) { var isSessionTimeout = jqXHR['responseText'].indexOf("sessionTimeout")!=-1; kimchi.user.showUser(false); kimchi.previousAjax = ajaxSettings; $(".empty-when-logged-off").empty(); $(".remove-when-logged-off").remove(); document.location.href= isSessionTimeout ? 'login.html?error=sessionTimeout' : 'login.html'; return; } else if((jqXHR['status'] == 0) && ("error"==jqXHR.statusText) && !kimchi.isLoggingOut) { kimchi.message.error(i18n['KCHAPI6007E'].replace("%1", jqXHR.state())); } if(ajaxSettings['originalError']) { ajaxSettings['originalError'](jqXHR, jqXHR.statusText, errorThrown); } }); kimchi.user.showUser(true); initListeners(); updatePage(); }; // Load i18n translation strings first and then render the page. kimchi.getI18n( function(i18nStrings){ //success i18n = i18nStrings; buildTabs(initUI); }, function(data){ //error kimchi.message.error(data.responseJSON.reason); }); }; kimchi.checkHelpFile = function(path) { var lang = kimchi.lang.get(); var url = "" // Find help page path according to tab name if (/^tabs/.test(path)) url = path.replace("tabs", "help/" + lang); else if (/^plugins/.test(path)) url = path.slice(0, path.lastIndexOf('/')) + "help/" + lang + path.slice(path.lastIndexOf('/')); // Checking if help page exist. $.ajax({ url: url, async: false, error: function() { url = ""; }, success: function() { } }); return url; }; kimchi.openHelp = function(e) { var tab = $('#nav-menu a.current'); var url = $(tab).parent().find("input[name='helpPath']").val(); window.open(url, "Kimchi Help"); e.preventDefault(); }; kimchi-1.5.0/ui/js/src/kimchi.message.js000066400000000000000000000100061254252253000200230ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ kimchi.message = function(msg, level, node) { var container = node || $('#messageField'); if ($(container).size() < 1) { container = $('
    ').appendTo(document.body); } var message = ''; var $message = $(message); $(container).append($message); $message.fadeIn(100); setTimeout(function() { $message.fadeOut(2000, function() { $(this).remove(); }); }, 4000); $(container).on("click", ".close", function(e) { $(this).parent().fadeOut(200, function() { $(this).remove(); }); }); }; /** * A public function of confirm box. * * @param msg * type:[object] * @param msg.title * The title of the confirm box. * @param msg.content * The main text of the confirm box. * @param msg.confirm * The text of the confirm button. * @param msg.cancel * the text of the cancel button. * @param confirmCallback * the callback function of click the confirm button. * @param cancelCallback * The callback function of click the cancel and X button. */ kimchi.confirm = function(settings, confirmCallback, cancelCallback) { if ($('#confirmbox-container ').size() < 1) { $(document.body).append('
    '); } var confirmboxHtml = '
    '; confirmboxHtml += '
    '; confirmboxHtml += '

    ' + (settings.title || '') + '

    '; confirmboxHtml += '
    X
    '; confirmboxHtml += '
    '; confirmboxHtml += '
    '; confirmboxHtml += settings.content + '
    '; confirmboxHtml += '
    '; confirmboxHtml += '
    '; confirmboxHtml += ''; confirmboxHtml += ''; confirmboxHtml += '
    '; confirmboxHtml += '
    '; confirmboxHtml += '
    '; var confirmboxNode = $(confirmboxHtml); $('#confirmbox-container').append(confirmboxNode); confirmboxNode.fadeIn(); $('#confirmbox-container').on("click", "#button-confirm", function(e) { if (confirmCallback) { confirmCallback(); } confirmboxNode.fadeOut(1, function() { $('#confirmbox-container').remove(); }); }); $('#confirmbox-container').on("click", ".cancel", function(e) { if (cancelCallback) { cancelCallback(); } confirmboxNode.fadeOut(1, function() { $('#confirmbox-container').remove(); }); }); }; kimchi.message.warn = function(msg, node) { kimchi.message(msg, 'warn', node); }; kimchi.message.error = function(msg, node) { kimchi.message(msg, 'error', node); }; kimchi.message.error.code = function(code) { msg = code + ": " + i18n[code] kimchi.message(msg, 'error'); }; kimchi.message.success = function(msg, node) { kimchi.message(msg, 'success', node); }; kimchi-1.5.0/ui/js/src/kimchi.network.js000066400000000000000000000361251254252253000201020ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2015 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ kimchi.NETWORK_TYPE_BRIDGE = "bridged"; kimchi.initNetwork = function() { if(kimchi.tabMode['network'] === 'admin') { $('.tools').attr('style','display'); $('#network-content .header span:last-child').attr('style','display'); kimchi.initNetworkCreation(); } kimchi.initNetworkListView(); kimchi.initNetworkDialog(); kimchi.initNetworkCleanup(); }; kimchi.initNetworkListView = function() { kimchi.listNetworks(function(data) { for (var i = 0; i < data.length; i++) { var network = { name : data[i].name, in_use : data[i].in_use, state : data[i].state === "active" ? "up" : "down" }; if (data[i].connection === "bridge") { network.type = kimchi.NETWORK_TYPE_BRIDGE; } else { network.type = data[i].connection; } network.interface = data[i].interface ? data[i].interface : null; network.addrSpace = data[i].subnet ? data[i].subnet : null; network.persistent = data[i].persistent; kimchi.addNetworkItem(network); } }); }; kimchi.addNetworkItem = function(network) { $("#networkBody").append(kimchi.getNetworkItemHtml(network)); if(kimchi.tabMode["network"] === "admin") { $(".column-action").attr("style","display"); } else { $(".column-space").addClass('column-space-no-border-right'); } kimchi.addNetworkActions(network); }; kimchi.getNetworkItemHtml = function(network) { if(!network.interface) { network.interface = i18n["KCHNET6001M"]; } if(!network.addrSpace) { network.addrSpace = i18n["KCHNET6001M"]; } if(i18n["network_type_" + network.type]) { network.type = i18n["network_type_" + network.type]; } var disable_in_use = network.in_use ? "ui-state-disabled" : ""; var networkItem = kimchi.substitute($('#networkItem').html(), { name : network.name, state : network.state, type : network.type, interface: network.interface, addrSpace : network.addrSpace, startClass : network.state === "up" ? "hide-action-item" : "", stopClass : network.state === "down" ? "hide-action-item" : disable_in_use, stopDisabled : network.in_use ? "disabled" : "", deleteClass : network.state === "up" || network.in_use ? "ui-state-disabled" : "", deleteDisabled: network.state === "up" || network.in_use ? "disabled" : "" }); return networkItem; }; kimchi.stopNetwork = function(network,menu) { $(".network-state", $("#" + kimchi.escapeStr(network.name))).switchClass("up", "nw-loading"); $("[nwAct='stop']", menu).addClass("ui-state-disabled"); kimchi.toggleNetwork(network.name, false, function() { $("[nwAct='start']", menu).removeClass("hide-action-item"); $("[nwAct='stop']", menu).addClass("hide-action-item"); $("[nwAct='stop']", menu).removeClass("ui-state-disabled"); if (!network.in_use) { $("[nwAct='delete']", menu).removeClass("ui-state-disabled"); $(":first-child", $("[nwAct='delete']", menu)).removeAttr("disabled"); } $(".network-state", $("#" + kimchi.escapeStr(network.name))).switchClass("nw-loading", "down"); }, function(err) { $(".network-state", $("#" + kimchi.escapeStr(network.name))).switchClass("nw-loading", "up"); if (!network.in_use) { $("[nwAct='stop']", menu).removeClass("ui-state-disabled"); } kimchi.message.error(err.responseJSON.reason); }); } kimchi.addNetworkActions = function(network) { $(".menu-container", "#" + kimchi.escapeStr(network.name)).menu(); $('#' + kimchi.escapeStr(network.name)).on('click', '.menu-container li', function(evt) { var menu = $(evt.currentTarget).parent(); if ($(evt.currentTarget).attr("nwAct") === "start") { $(".network-state", $("#" + kimchi.escapeStr(network.name))).switchClass("down", "nw-loading"); $("[nwAct='start']", menu).addClass("ui-state-disabled"); $("[nwAct='delete']", menu).addClass("ui-state-disabled"); $(":first-child", $("[nwAct='delete']", menu)).attr("disabled", true); kimchi.toggleNetwork(network.name, true, function() { $("[nwAct='start']", menu).addClass("hide-action-item"); $("[nwAct='start']", menu).removeClass("ui-state-disabled"); $("[nwAct='stop']", menu).removeClass("hide-action-item"); network.state = "up"; if (network.in_use) { $("[nwAct='stop']", menu).addClass("ui-state-disabled"); } $(".network-state", $("#" + kimchi.escapeStr(network.name))).switchClass("nw-loading", "up"); }, function(err) { $(".network-state", $("#" + kimchi.escapeStr(network.name))).switchClass("nw-loading","down"); $("[nwAct='start']", menu).removeClass("ui-state-disabled"); if (!network.in_use) { $("[nwAct='delete']", menu).removeClass("ui-state-disabled"); } $(":first-child", $("[nwAct='delete']", menu)).removeAttr("disabled"); kimchi.message.error(err.responseJSON.reason); }); } else if ($(evt.currentTarget).attr("nwAct") === "stop") { if (network.in_use) { return false; } if (!network.persistent) { var settings = { title : i18n['KCHAPI6001M'], content : i18n['KCHNET6004M'], confirm : i18n['KCHAPI6002M'], cancel : i18n['KCHAPI6003M'] }; kimchi.confirm(settings, function() { kimchi.stopNetwork(network, menu); $(evt.currentTarget).parents(".item").remove(); }, null); } else { kimchi.stopNetwork(network, menu); network.state = "down"; } } else if ($(evt.currentTarget).attr("nwAct") === "delete") { if (network.state === "up" || network.in_use) { return false; } kimchi.confirm({ title : i18n['KCHAPI6006M'], content : i18n['KCHNET6002M'], confirm : i18n['KCHAPI6002M'], cancel : i18n['KCHAPI6003M'] }, function() { kimchi.deleteNetwork(network.name, function() { $(evt.currentTarget).parents(".item").remove(); }); }, null); } }); $("#networkBody .column-action .popable").button({ icons : { secondary : "action-button-icon" } }); }; kimchi.initNetworkCreation = function() { $("#networkAdd").on("click", function() { kimchi.openNetworkDialog(function() { var errorCallback = function(){ $("#networkFormOk").button("enable"); $("#networkName").removeAttr("readonly"); $("#networkFormOk span").text(i18n.KCHAPI6005M); }; var network = kimchi.getNetworkDialogValues(); var data = { name : network.name, connection: network.type }; if (network.type === kimchi.NETWORK_TYPE_BRIDGE) { data.connection = "bridge"; data.interface = network.interface; if ($("#enableVlan").prop("checked")) { data.vlan_id = network.vlan_id; if (!(data.vlan_id >=1 && data.vlan_id <= 4094)) { kimchi.message.error.code('KCHNET6001E'); errorCallback(); return; } } } kimchi.createNetwork(data, function(result) { network.state = result.state === "active" ? "up" : "down"; network.interface = result.interface ? result.interface : i18n["KCHNET6001M"]; network.addrSpace = result.subnet ? result.subnet : i18n["KCHNET6001M"]; network.persistent = result.persistent; kimchi.addNetworkItem(network); $("#networkConfig").dialog("close"); }, function(data) { kimchi.message.error(data.responseJSON.reason); errorCallback(); }); }); }); }; kimchi.initNetworkDialog = function() { buttonsObj= {}; buttonsObj['id'] = "networkFormOk"; buttonsObj['text'] = i18n.KCHAPI6005M; buttonsObj['class'] = "ui-button-primary"; buttonsObj['disabled'] = true; buttonsObj['click'] = function() { }; $("#networkConfig").dialog({ autoOpen : false, modal : true, width : 600, draggable : false, resizable : false, closeText: "X", dialogClass : "network-ui-dialog remove-when-logged-off", open : function(){ $(".ui-dialog-titlebar-close", $("#networkConfig").parent()).removeAttr("title"); }, beforeClose : function() { kimchi.cleanNetworkDialog(); }, buttons : [buttonsObj] }); kimchi.setupNetworkFormEvent(); }; kimchi.openNetworkDialog = function(okCallback) { kimchi.getInterfaces(function(result) { var options = []; $('#networkDestinationID').selectMenu(); var nics = {}; for (var i = 0; i < result.length; i++) { options.push({label:result[i].name,value:result[i].name}); nics[result[i].name] = result[i]; } result.length>0 && $("#networkDestinationID").selectMenu("setData", options); onChange = function() { $("#networkDestinationLabel").text($("#networkDestinationID li:first-child").text()); $("#networkDestinationID li:first-child").addClass("active"); if (result.length>0 && nics[$("#networkDestinationLabel").text()].type === "bridge") { $("#enableVlan").prop("checked", false); $("#enableVlan").prop("disabled", true); $("#networkVlanID").val(""); $("#networkVlanID").toggle(false); $("#labelNetworkVlanID").toggle(false); } else { $("#enableVlan").prop("disabled",false); } }; $("#networkDestinationLabel").on("change", onChange); kimchi.setDefaultNetworkType(result.length!==0); onChange(); }); $("#networkConfig").dialog({ title : i18n.KCHNET6003M }); $("#networkFormOk").on("click", function() { $("#networkFormOk").button("disable"); $("#networkName").prop("readonly", "readonly"); $("#networkFormOk span").text(i18n.KCHAPI6008M); okCallback(); }); $("#enableVlan").on("click", function() { $("#networkVlanID").prop("disabled", !this.checked); if (!this.checked) { $("#networkVlanID").slideUp(100); $("#labelNetworkVlanID").slideUp(100); $("#networkVlanID").val(""); } else { $("#networkVlanID").slideDown(100); $("#labelNetworkVlanID").slideDown(100); } }); $("#networkConfig").dialog("open"); }; kimchi.enableBridgeOptions = function(enable) { if (!enable) { $("#enableVlan").prop("checked", false); $("#networkVlanID").toggle(false); $("#labelNetworkVlanID").toggle(false); $("#networkVlanID").val(""); $("#networkDestinationLabel").text(""); $("#bridgeOptions").slideUp(100); } else if (!$("#networkDestinationLabel").text()){ $("#networkDestinationLabel").text($("#networkDestinationID li:first-child").text()); $("#bridgeOptions").slideDown(100); $("#networkVlanID").toggle(false); $("#labelNetworkVlanID").toggle(false); } }; kimchi.setDefaultNetworkType = function(isInterfaceAvail) { $("#networkTypeBri").prop("checked", isInterfaceAvail); $("#networkTypeBri").prop("disabled", !isInterfaceAvail); $("#networkTypeNat").prop("checked", !isInterfaceAvail); if (!isInterfaceAvail) { kimchi.enableBridgeOptions(false); $("#networkBriDisabledLabel").show(); } else { if (kimchi.capabilities && kimchi.capabilities.nm_running) { kimchi.message.warn(i18n['KCHNET6001W']); } $("#bridgeOptions").slideDown(100); $("#networkVlanID").toggle(false); $("#labelNetworkVlanID").toggle(false); $("#networkBriDisabledLabel").hide(); } }; kimchi.getNetworkDialogValues = function() { var network = { name : $("#networkName").val(), type : $("input:radio[name=networkType]:checked").val() }; if (network.type === kimchi.NETWORK_TYPE_BRIDGE) { network.interface = $("#networkDestinationLabel").text(); network.vlan_id = parseInt($("#networkVlanID").val()); } return network; }; kimchi.cleanNetworkDialog = function() { $("input:text", "#networkConfig").val(null).removeClass("invalid-field"); $("#networkTypeIso").prop("checked", false); $("#networkTypeNat").prop("checked", false); $("#networkTypeBri").prop("checked", false); $("#networkDestinationLabel").text($("#networkDestinationID li:first-child").text()); $("#networkFormOk").off("click"); $("#networkFormOk").button("disable"); $("#networkFormOk span").text(i18n.KCHAPI6005M); $("#networkName").removeAttr("readonly"); $("#networkVlanID").toggle(false); $("#labelNetworkVlanID").toggle(false); $("#enableVlan").prop("checked", false); }; kimchi.setupNetworkFormEvent = function() { $("#networkName").on("keyup", function(event) { $("#networkName").toggleClass("invalid-field", !$("#networkName").val().match(/^[^\"\/]+$/)); kimchi.updateNetworkFormButton(); }); $("#networkTypeIso").on("click", function(event) { kimchi.enableBridgeOptions(false); }); $("#networkTypeNat").on("click", function(event) { kimchi.enableBridgeOptions(false); }); $("#networkTypeBri").on("click", function(event) { kimchi.enableBridgeOptions(true); }); }; kimchi.updateNetworkFormButton = function() { if($("#networkName").hasClass("invalid-field")){ $("#networkFormOk").button("disable"); }else{ $("#networkFormOk").button("enable"); } }; kimchi.initNetworkCleanup = function() { $("#network-content").on("remove", function() { $("#networkConfig").dialog("destroy"); }); }; kimchi-1.5.0/ui/js/src/kimchi.object.js000066400000000000000000000047311254252253000176550ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ Object.defineProperty(Object.prototype, "getDeepValue", { value: function(key) { var result=undefined; try { if(!Array.isArray(key)) { key=key.parseKey(); } if(key.length!=0) { var tmpName=key.shift(); if(this[tmpName]!=undefined) { result=this[tmpName]; } if(key.length!=0) { result=result.getDeepValue(key); } } } catch (err) { //do nothing } return(result); } }); Object.defineProperty(Object.prototype, "setDeepValue", { value: function(key, val) { var keys; if(Array.isArray(key)) { keys=key; } else { keys=key.parseKey(); } if(keys.length!=0) { var key=keys.shift(); if(keys.length==0) { if(this[key]==undefined) { this[key]=val; } else if(Array.isArray(this[key])){ this[key].push(val); } else { var tmpArray=[] tmpArray.push(this[key]); tmpArray.push(val); this[key]=tmpArray; } } else { if(this[key]==undefined) { this[key]=new Object(); this[key].setDeepValue(keys,val); } else if(Array.isArray(this[key])){ var tmpO=new Object(); this[key].push(tmpO); tmpO.setDeepValue(keys,val); } else { this[key].setDeepValue(keys,val); } } } return(this); } }); kimchi-1.5.0/ui/js/src/kimchi.popable.js000066400000000000000000000022301254252253000200210ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ kimchi.popable = function() { $(document).click(function(e) { $('.popable').each(function(i, n) { n === e.target || $.contains(n, e.target) || $('.popover', n).toggle(false); }); }); $(document).on('click', '.popable', function(e) { var popup = $('.popover', this)[0]; $(popup).toggle(); // Scroll the popup menu into viewport if invisible. !$(popup).is(':visible') || kimchi.isElementInViewport(popup) || popup.scrollIntoView(); }); }; kimchi-1.5.0/ui/js/src/kimchi.report_add_main.js000066400000000000000000000047071254252253000215410ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ kimchi.report_add_main = function() { var reportGridID = 'available-reports-grid'; var addReportForm = $('#form-report-add'); var submitButton = $('#button-report-add'); var nameTextbox = $('input[name="name"]', addReportForm); nameTextbox.select(); var submitForm = function(event) { if(submitButton.prop('disabled')) { return false; } var reportName = nameTextbox.val(); var validator = RegExp("^[_A-Za-z0-9-]*$"); if (!validator.test(reportName)) { kimchi.message.error.code('KCHDR6011M'); return false; } var formData = addReportForm.serializeObject(); var taskAccepted = false; var onTaskAccepted = function() { if(taskAccepted) { return; } taskAccepted = true; kimchi.window.close(); kimchi.topic('kimchi/debugReportAdded').publish(); }; kimchi.createReport(formData, function(result) { onTaskAccepted(); kimchi.topic('kimchi/debugReportAdded').publish(); }, function(result) { // Error message from Async Task status if (result['message']) { var errText = result['message']; } // Error message from standard kimchi exception else { var errText = result['responseJSON']['reason']; } result && kimchi.message.error(errText); taskAccepted && $('.grid-body-view table tr:first-child', '#' + reportGridID).remove(); submitButton.prop('disabled', false); nameTextbox.select(); }, onTaskAccepted); event.preventDefault(); }; addReportForm.on('submit', submitForm); submitButton.on('click', submitForm); }; kimchi-1.5.0/ui/js/src/kimchi.report_rename_main.js000066400000000000000000000045211254252253000222520ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ kimchi.report_rename_main = function() { var renameReportForm = $('#form-report-rename'); var submitButton = $('#button-report-rename'); var nameTextbox = $('input[name="name"]', renameReportForm); var submitForm = function(event) { if(submitButton.prop('disabled')) { return false; } var reportName = nameTextbox.val(); // if the user hasn't changed the report's name, // nothing should be done. if (reportName == kimchi.selectedReport) { kimchi.message.error.code('KCHDR6013M'); return false; } var validator = RegExp("^[A-Za-z0-9-]*$"); if (!validator.test(reportName)) { kimchi.message.error.code('KCHDR6011M'); return false; } var formData = renameReportForm.serializeObject(); submitButton.prop('disabled', true); nameTextbox.prop('disabled', true); kimchi.renameReport(kimchi.selectedReport, formData, function(result) { submitButton.prop('disabled', false); nameTextbox.prop('disabled', false); kimchi.window.close(); kimchi.topic('kimchi/debugReportRenamed').publish({ result: result }); }, function(result) { var errText = result && result['responseJSON'] && result['responseJSON']['reason']; kimchi.message.error(errText); submitButton.prop('disabled', false); nameTextbox.prop('disabled', false).focus(); }); event.preventDefault(); }; renameReportForm.on('submit', submitForm); submitButton.on('click', submitForm); nameTextbox.val(kimchi.selectedReport).select(); }; kimchi-1.5.0/ui/js/src/kimchi.repository_add_main.js000066400000000000000000000061471254252253000224450ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ kimchi.repository_add_main = function() { var addForm = $('#form-repository-add'); var addButton = $('#button-repository-add'); var validateField = function(event) { var valid=($(this).val()!==''); $(addButton).prop('disabled', !valid); return(valid); }; var validateForm = function(event) { var valid=false; addForm.find('input.required').each( function() { valid=($(this).val()!==''); return(!valid); }); return(valid); } addForm.find('input.required').on('input propertychange', validateField); var weedObject = function(obj) { for (var key in obj) { if (obj.hasOwnProperty(key)) { if((typeof(obj[key])==="object") && !Array.isArray(obj[key])) { weedObject(obj[key]); } else if(obj[key] == '') { delete obj[key]; } } } } var addRepository = function(event) { var valid = validateForm(); if(!valid) { return false; } var formData = $(addForm).serializeObject(); if (formData && formData.isMirror!=undefined) { formData.isMirror=(String(formData.isMirror).toLowerCase() === 'true'); } if(formData.isMirror) { if(formData.config==undefined) { formData.config=new Object(); } formData.config.mirrorlist=formData.baseurl; delete formData.baseurl; delete formData.isMirror; } weedObject(formData); if(formData.config && formData.config.comps) { formData.config.comps=formData.config.comps.split(/[,\s]/); for(var i=0; i>formData.config.comps.length; i++) { formData.config.comps[i]=formData.config.comps[i].trim(); } for (var j=formData.config.comps.indexOf(""); j!=-1; j=formData.config.comps.indexOf("")) { formData.config.comps.splice(j, 1); } } kimchi.createRepository(formData, function() { kimchi.topic('kimchi/repositoryAdded').publish(); kimchi.window.close(); }, function(jqXHR, textStatus, errorThrown) { var reason = jqXHR && jqXHR['responseJSON'] && jqXHR['responseJSON']['reason']; kimchi.message.error(reason); }); return false; }; $(addForm).on('submit', addRepository); }; kimchi-1.5.0/ui/js/src/kimchi.repository_edit_main.js000066400000000000000000000050361254252253000226360ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ kimchi.repository_edit_main = function() { var editForm = $('#form-repository-edit'); var saveButton = $('#repository-edit-button-save'); if(kimchi.capabilities['repo_mngt_tool']=="yum") { editForm.find('input.deb').prop('disabled', true); } else if(kimchi.capabilities['repo_mngt_tool']=="deb") { editForm.find('input.yum').prop('disabled', true); } kimchi.retrieveRepository(kimchi.selectedRepository, function(repository) { editForm.fillWithObject(repository); $('input', editForm).on('input propertychange', function(event) { if($(this).val() !== '') { $(saveButton).prop('disabled', false); } }); }); var editRepository = function(event) { var formData = $(editForm).serializeObject(); if (formData && formData.config) { formData.config.gpgcheck=(String(formData.config.gpgcheck).toLowerCase() === 'true'); } if(formData.config && formData.config.comps) { formData.config.comps=formData.config.comps.split(/[,\s]/); for(var i=0; i>formData.config.comps.length; i++) { formData.config.comps[i]=formData.config.comps[i].trim(); } for (var j=formData.config.comps.indexOf(""); j!=-1; j=formData.config.comps.indexOf("")) { formData.config.comps.splice(j, 1); } } kimchi.updateRepository(kimchi.selectedRepository, formData, function() { kimchi.topic('kimchi/repositoryUpdated').publish(); kimchi.window.close(); }, function(jqXHR, textStatus, errorThrown) { var reason = jqXHR && jqXHR['responseJSON'] && jqXHR['responseJSON']['reason']; kimchi.message.error(reason); }); return false; }; $(editForm).on('submit', editRepository); $(saveButton).on('click', editRepository); }; kimchi-1.5.0/ui/js/src/kimchi.select.js000066400000000000000000000032371254252253000176660ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ kimchi.select = function(id, options) { var listControl = $('#'+ id); var targetId = listControl.data('target'); var labelId = listControl.data('label'); var value = $('#' + targetId).val(); var item; var itemTag = 'li'; var selectedClass = 'active'; $.each(options, function(index, option) { item = $('<' + itemTag + '>'); item.text(option.label); item.data('value', option.value); if(option.value === value) { item.addClass(selectedClass); $('#' + labelId).text(option.label); } listControl.append(item); }); listControl.on('click', itemTag, function() { listControl.children().removeClass(selectedClass); $(this).addClass(selectedClass); $('#' + labelId).text($(this).text()); var target = $('#' + targetId); var oldValue = target.val(); var newValue = $(this).data('value'); target.val(newValue); if(oldValue !== newValue) { target.change(); } }); }; kimchi-1.5.0/ui/js/src/kimchi.storage_main.js000066400000000000000000000367451254252253000210710ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2015 * * Licensed under the Apache License, Version 2.0 (the 'License'); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an 'AS IS' BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ kimchi.doListStoragePools = function() { kimchi.listStoragePools(function(result) { var storageHtml = $('#storageTmpl').html(); if (result && result.length) { var listHtml = ''; $.each(result, function(index, value) { value.usage = Math.round(value.allocated / value.capacity * 100) || 0; value.capacity = kimchi.changetoProperUnit(value.capacity,1); value.allocated = kimchi.changetoProperUnit(value.allocated,1); value.enableExt = value.type==="logical" ? "" : "hide-content"; if ('kimchi-iso' !== value.type) { listHtml += kimchi.substitute(storageHtml, value); } }); $('#storagepoolsList').html(listHtml); if(kimchi.tabMode['storage'] === 'admin') { $('.storage-button').attr('style','display'); } else { $('.storage-allocate').addClass('storage-allocate-padding-user'); } kimchi.storageBindClick(); } else { $('#storagepoolsList').html(''); } }, function(err) { kimchi.message.error(err.responseJSON.reason); }); } kimchi.storageBindClick = function() { $('.inactive').each(function(index) { if ('active' === $(this).data('state')) { $(this).hide(); } else { $(this).show(); } }); $('.list-storage .storage-state .active').each(function(index) { if ('active' === $(this).data('state')) { $(this).show(); } else { $(this).hide(); } }); $('.pool-activate').each(function(index) { if ('active' === $(this).data('stat')) { $(this).hide(); } else { $(this).show(); } }); $('.pool-deactivate').each(function(index) { if ('active' === $(this).data('stat')) { $(this).show(); } else { $(this).hide(); } }); $('.pool-add-volume').each(function(index) { var canAddVolume = $(this).data('stat') === 'active' && $(this).data('type') !== 'iscsi' && $(this).data('type') !== 'scsi'; if(canAddVolume) { $(this).show(); } else { $(this).hide(); } }); if(kimchi.tabMode['storage'] === 'admin') { $('.pool-delete').on('click', function(event) { var $pool = $(this); var settings = { title : i18n['KCHAPI6001M'], content : i18n['KCHPOOL6001M'], confirm : i18n['KCHAPI6002M'], cancel : i18n['KCHAPI6003M'] }; kimchi.confirm(settings, function() { var poolName = $pool.data('name'); kimchi.deleteStoragePool(poolName, function() { kimchi.doListStoragePools(); }, function(err) { kimchi.message.error(err.responseJSON.reason); }); }); }); $('.pool-activate').on('click', function(event) { var poolName = $(this).data('name'); kimchi.changePoolState(poolName, 'activate', function() { kimchi.doListStoragePools(); }, function(err) { kimchi.message.error(err.responseJSON.reason); }); }); $('.pool-deactivate').on('click', function(event) { var poolName = $(this).data('name'); var settings = { title : i18n['KCHAPI6001M'], content : i18n['KCHPOOL6012M'], confirm : i18n['KCHAPI6002M'], cancel : i18n['KCHAPI6003M'] }; if (!$(this).data('persistent')) { kimchi.confirm(settings, function() { kimchi.changePoolState(poolName, 'deactivate', function() { kimchi.doListStoragePools(); }, function(err) { kimchi.message.error(err.responseJSON.reason); }); }, function() { return false; }); } else { kimchi.changePoolState(poolName, 'deactivate', function() { kimchi.doListStoragePools(); }, function(err) { kimchi.message.error(err.responseJSON.reason); }); } }); $('.pool-add-volume').on('click', function(event) { var poolName = $(this).data('name'); kimchi.selectedSP = poolName; kimchi.window.open('storagepool-add-volume.html'); }); $('.storage-action').on('click', function() { var storage_action = $(this); var deleteButton = storage_action.find('.pool-delete'); if ('active' === deleteButton.data('stat')) { deleteButton.attr('disabled', 'disabled'); } else { deleteButton.removeAttr('disabled'); } }); $('.pool-extend').on('click', function() { $("#logicalPoolExtend").dialog("option", "poolName", $(this).data('name')); $("#logicalPoolExtend").dialog("open"); }); } $('.storage-li').on('click', function(event) { if (!$(event.target).parents().hasClass('bottom')) { if ($(this).data('stat') === 'active') { var that = $(this); var volumeDiv = $('#volume' + that.data('name')); var slide = $(this).next('.volumes'); if (that.hasClass('in')) { kimchi.doListVolumes(that); } else { slide.slideUp('slow'); that.addClass('in'); kimchi.changeArrow(that.children().last().children()); } } } }); } kimchi._generateVolumeHTML = function(volume) { if(volume['type'] === 'kimchi-iso') { return ''; } var volumeHtml = $('#volumeTmpl').html(); volume.capacity = kimchi.changetoProperUnit(volume.capacity,1); volume.allocation = kimchi.changetoProperUnit(volume.allocation,1); return kimchi.substitute(volumeHtml, volume); }; kimchi.doListVolumes = function(poolObj) { var poolName = poolObj.data('name') var getOngoingVolumes = function() { var result = {} var filter = 'status=running&target_uri=' + encodeURIComponent('^/storagepools/' + poolName + '/*') kimchi.getTasksByFilter(filter, function(tasks) { for(var i = 0; i < tasks.length; i++) { var volumeName = tasks[i].target_uri.split('/').pop(); result[volumeName] = tasks[i]; if(kimchi.trackingTasks.indexOf(tasks[i].id) >= 0) { continue; } kimchi.trackTask(tasks[i].id, function(result) { kimchi.topic('kimchi/volumeTransferFinished').publish(result); }, function(result) { kimchi.topic('kimchi/volumeTransferError').publish(result); }, function(result) { kimchi.topic('kimchi/volumeTransferProgress').publish(result); }); } }, null, true); return result; }; var volumeDiv = $('#volume' + poolName); $(volumeDiv).empty(); var slide = poolObj.next('.volumes'); var handleArrow = poolObj.children().last().children(); kimchi.listStorageVolumes(poolName, function(result) { var listHtml = ''; var ongoingVolumes = []; var ongoingVolumesMap = getOngoingVolumes(); $.each(ongoingVolumesMap, function(volumeName, task) { ongoingVolumes.push(volumeName) var volume = { poolName: poolName, used_by: [], capacity: 0, name: volumeName, format: '', bootable: null, os_distro: '', allocation: 0, os_version: '', path: '', type: 'file' }; listHtml += kimchi._generateVolumeHTML(volume); }); $.each(result, function(index, value) { if (ongoingVolumes.indexOf(value.name) == -1) { value.poolname = poolName; listHtml += kimchi._generateVolumeHTML(value); } }); if (listHtml.length > 0) { volumeDiv.html(listHtml); } else { volumeDiv.html("
    " + i18n['KCHPOOL6002M'] + "
    "); } $.each(ongoingVolumesMap, function(volumeName, task) { kimchi.topic('kimchi/volumeTransferProgress').publish(task); }); poolObj.removeClass('in'); kimchi.changeArrow(handleArrow); slide.slideDown('slow'); }, function(err) { kimchi.message.error(err.responseJSON.reason); }); } kimchi.initLogicalPoolExtend = function() { $("#logicalPoolExtend").dialog({ autoOpen : false, modal : true, width : 600, resizable : false, closeText: "X", open : function(){ $('#loading-info', '#logicalPoolExtend').removeClass('hidden'); $(".ui-dialog-titlebar-close", $("#logicalPoolExtend").parent()).removeAttr("title"); kimchi.listHostPartitions(function(data) { $('#loading-info', '#logicalPoolExtend').addClass('hidden'); if (data.length > 0) { for(var i=0;i(' + err.responseJSON.reason + ')'); $('.host-partition').addClass('text-help'); }); }, beforeClose : function() { $('.host-partition', '#logicalPoolExtend').empty(); }, buttons : [{ class: "ui-button-primary", text: i18n.KCHAPI6007M, click: function(){ var devicePaths = []; $("input[type='checkbox']:checked", "#logicalPoolExtend").each(function(){ devicePaths.push($(this).prop('value')); }) kimchi.updateStoragePool($("#logicalPoolExtend").dialog("option", "poolName"),{disks: devicePaths},function(data){ var item = $("#"+$("#logicalPoolExtend").dialog("option", "poolName")); $(".usage", $(".storage-name", item)).text((Math.round(data.allocated/data.capacity*100)||0)+"%"); $(".storage-text", $(".storage-capacity", item)).text(kimchi.changetoProperUnit(data.capacity,1)); $(".storage-text", $(".storage-allocate", item)).text(kimchi.changetoProperUnit(data.allocated,1)); }); $(this).dialog("close"); } }] }); } kimchi.storage_main = function() { if(kimchi.tabMode['storage'] === 'admin') { $('.tools').attr('style','display'); $('#storage-pool-add').on('click', function() { kimchi.window.open('storagepool-add.html'); }); $('.list-title .title-actions').attr('style','display'); } kimchi.doListStoragePools(); kimchi.initLogicalPoolExtend(); kimchi.topic('kimchi/storageVolumeAdded').subscribe(function() { pool = kimchi.selectedSP; var poolNode = $('.storage-li[data-name="' + pool + '"]'); kimchi.doListVolumes(poolNode); }); kimchi.topic('kimchi/volumeTransferProgress').subscribe(function(result) { var extractProgressData = function(data) { var sizeArray = /(\d+)\/(\d+)/g.exec(data) || [0, 0, 0]; var downloaded = sizeArray[1]; var percent = 0; if(downloaded) { var total = sizeArray[2]; if(!isNaN(total)) { percent = downloaded / total * 100; } } var formatted = kimchi.formatMeasurement(downloaded); var size = (1.0 * formatted['v']).toFixed(1) + formatted['s']; return { size: size, percent: percent }; }; var uriElements = result.target_uri.split('/'); var poolName = uriElements[2]; var volumeName = uriElements.pop(); var progress = extractProgressData(result['message']); var size = progress['size']; var percent = progress['percent']; volumeBox = $('#volume' + poolName + ' [data-volume-name="' + volumeName + '"]'); $('.progress-bar-inner', volumeBox).css({ width: percent + '%' }); $('.progress-transferred', volumeBox).text(size); $('.volume-progress', volumeBox).removeClass('hidden'); $('.progress-status', volumeBox).text(i18n['KCHPOOL6014M']); }); kimchi.topic('kimchi/volumeTransferFinished').subscribe(function(result) { var uriElements = result.target_uri.split('/'); var poolName = uriElements[2]; var volumeName = uriElements.pop(); var volumeBox = $('#volume' + poolName + ' [data-volume-name="' + volumeName + '"]'); $('.volume-progress', volumeBox).addClass('hidden'); kimchi.getStoragePoolVolume(poolName, volumeName, function(volume) { var html = kimchi._generateVolumeHTML(volume); $(volumeBox).replaceWith(html); }, function(err) { kimchi.message.error(err.responseJSON.reason); }); }); kimchi.topic('kimchi/volumeTransferError').subscribe(function(result) { // Error message from Async Task status if (result['message']) { var errText = result['message']; } // Error message from standard kimchi exception else { var errText = result['responseJSON']['reason']; } result && kimchi.message.error(errText); var uriElements = result.target_uri.split('/'); var poolName = uriElements[2]; var volumeName = uriElements.pop(); volumeBox = $('#volume' + poolName + ' [data-volume-name="' + volumeName + '"]'); $('.progress-status', volumeBox).text(i18n['KCHPOOL6015M']); }); }; kimchi.changeArrow = function(obj) { if ($(obj).hasClass('arrow-down')) { $(obj).removeClass('arrow-down').addClass('arrow-up'); } else { $(obj).removeClass('arrow-up').addClass('arrow-down'); } } kimchi-1.5.0/ui/js/src/kimchi.storagepool_add_main.js000066400000000000000000000355701254252253000225660ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2015 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ kimchi.storagepool_add_main = function() { kimchi.initStorageAddPage(); $('#form-pool-add').on('submit', kimchi.addPool); $('#pool-doAdd').on('click', kimchi.addPool); // 'pool-doAdd' button starts as disabled. $("#pool-doAdd").button(); $("#pool-doAdd").button("disable"); // Make any change in the form fields enables the // 'pool-doAdd' button if all the visible form // fields are filled, disables it otherwise. $('#form-pool-add').on('input change propertychange', function() { if (!kimchi.inputsNotBlank()) $("#pool-doAdd").button("disable"); else $("#pool-doAdd").button("enable"); }); }; kimchi.storageFilterSelect = function(id, isUpdate) { var input = $('input', '#'+id); var options = $(".option", '#'+id); var filter = function(container, key){ container.children().each(function(){ $(this).css("display", $(this).text().indexOf(key)==-1 ? "none" : ""); }); }; if(!isUpdate){ input.on("keyup", function(){ filter(options, input.val()); }); } options.children().each(function(){ $(this).click(function(){ options.children().removeClass("active"); input.val($(this).text()); input.trigger("change"); $(this).addClass("active"); filter(options, ""); }); }); }; kimchi.setupISCSI = function(){ var loadTargets = function(server, port, callback){ var isUpdate = $(".option", "#iSCSITarget").children().length > 0; $(".option", "#iSCSITarget").empty(); $('input', "#iSCSITarget").attr("placeholder", i18n['KCHPOOL6006M']); kimchi.getISCSITargets(server, port, function(data){ if(data.length==0){ $('input', "#iSCSITarget").attr("placeholder", i18n['KCHPOOL6007M']); }else{ for(var i=0; i"+data[i].target+""); $(".option", "#iSCSITarget").append(itemNode); } $('input', "#iSCSITarget").attr("placeholder", ""); $(".popover", "#iSCSITarget").css("display", "block"); } kimchi.storageFilterSelect('iSCSITarget', isUpdate); $('input', "#iSCSITarget").trigger("focus"); callback(); }, function(data){ $('input', "#iSCSITarget").attr("placeholder", i18n['KCHPOOL6008M']); callback(); kimchi.message.error(data.responseJSON.reason); }); }; var triggerLoadTarget = function(){ $('input', "#iSCSITarget").val(""); var server = $("#iscsiserverId").val().trim(); var port = $("#iscsiportId").val().trim(); if(server!="" && !$("#iscsiserverId").hasClass("invalid-field") && !$("#iscsiportId").hasClass("invalid-field")){ $("#iscsiserverId").attr("disabled", true); $("#iscsiportId").attr("disabled", true); loadTargets(server, port, function(){ $("#iscsiserverId").attr("disabled", false); $("#iscsiportId").attr("disabled", false); }); } }; $("#iscsiserverId").change(function(){ $('input', "#iSCSITarget").off('focus', triggerLoadTarget); $('input', "#iSCSITarget").one('focus', triggerLoadTarget); }); $("#iscsiportId").change(function(){ $('input', "#iSCSITarget").off('focus', triggerLoadTarget); $('input', "#iSCSITarget").one('focus', triggerLoadTarget); }); var initISCSIServers = function(){ kimchi.getStorageServers("iscsi", function(data){ for(var i=0;i"+data[i].host+""); $(".option", "#iSCSIServer").append(itemNode); $(itemNode).click(function(){ $("#iscsiportId").val($(this).prop("port")); $("#iscsiserverId").val($(this).text()); triggerLoadTarget(); }).prop("port", data[i].port); } kimchi.storageFilterSelect('iSCSIServer', false); }); }; initISCSIServers(); }; kimchi.initStorageAddPage = function() { kimchi.listHostPartitions(function(data) { if (data.length > 0) { var deviceHtml = $('#partitionTmpl').html(); var listHtml = ''; valid_types = ['part', 'disk', 'mpath']; $.each(data, function(index, value) { if (valid_types.indexOf(value.type) != -1) { listHtml += kimchi.substitute(deviceHtml, value); } }); $('.host-partition', '#form-pool-add').html(listHtml); } else { $('.host-partition').html(i18n['KCHPOOL6011M']); $('.host-partition').addClass('text-help'); } }, function(err) { $('.host-partition').html(i18n['KCHPOOL6013M'] + '
    (' + err.responseJSON.reason + ')'); $('.host-partition').addClass('text-help'); }); kimchi.getHostFCDevices(function(data){ if(data.length>0){ for(var i=0;i 0) { $.each(data, function(index, value) { serverContent.push({ label : value.host, value : value.host }); }); } $('#serverComboboxId').combobox("setData", serverContent); $('input[name=nfsServerType]').change(function() { if ($(this).val() === 'input') { $('#nfsServerInputDiv').removeClass('tmpl-html'); $('#nfsServerChooseDiv').addClass('tmpl-html'); } else { $('#nfsServerInputDiv').addClass('tmpl-html'); $('#nfsServerChooseDiv').removeClass('tmpl-html'); } }); $('#nfsserverId').on("change keyup",function() { if ($(this).val() !== '' && kimchi.isServer($(this).val())) { $('#nfspathId').prop('disabled',false); $(this).removeClass("invalid-field"); } else { $(this).addClass("invalid-field"); $('#nfspathId').prop( "disabled",true); } $('#targetFilterSelectId').filterselect('clear'); }); $('#nfspathId').focus(function() { var targetContent = []; kimchi.getStorageTargets($('#nfsserverId').val(), 'netfs', function(data) { if (data.length > 0) { $.each(data, function(index, value) { targetContent.push({ label : value.target, value : value.target }); }); } $('#targetFilterSelectId').filterselect("setData", targetContent); }); }); }); $('#poolTypeInputId').change(function() { var poolObject = {'dir': ".path-section", 'netfs': '.nfs-section', 'iscsi': '.iscsi-section', 'scsi': '.scsi-section', 'logical': '.logical-section'} var selectType = $(this).val(); $.each(poolObject, function(type, value) { if(selectType == type){ $(value).removeClass('tmpl-html'); } else { $(value).addClass('tmpl-html'); } }); }); $('#authId').click(function() { if ($(this).prop("checked")) { $('.authenticationfield').removeClass('tmpl-html'); } else { $('.authenticationfield').addClass('tmpl-html'); } }); $('#iscsiportId').keyup(function(event) { $(this).toggleClass("invalid-field",!/^[0-9]*$/.test($(this).val())); }); $('#iscsiserverId').keyup(function(event) { $(this).toggleClass("invalid-field",!kimchi.isServer($(this).val().trim())); }).change(function(event) { $(this).toggleClass("invalid-field",!kimchi.isServer($(this).val().trim())); }); kimchi.setupISCSI(); }; /* Returns 'true' if all form fields were filled, 'false' if * any field is left blank. The function takes into account * the current poolType selected. * * Any 'field is blank' verification that were done in other * validate functions were deleted, since we're doing it here * already. */ kimchi.inputsNotBlank = function() { if (!$('#poolId').val()) return false; var poolType = $("#poolTypeInputId").val(); if (poolType === "dir") { if (!$('#pathId').val()) return false; } else if (poolType === "netfs") { if (!$('#nfspathId').val()) return false; if (!$('#nfsserverId').val()) return false; } else if (poolType === "iscsi") { if (!$('#iscsiserverId').val()) return false; if (!$('#iscsiTargetId').val()) return false; } else if (poolType === "logical") { if ($("input[name=devices]:checked").length === 0) return false; } return true; }; kimchi.validateForm = function() { var poolType = $("#poolTypeInputId").val(); if (poolType === "dir") { return kimchi.validateDirForm(); } else if (poolType === "netfs") { return kimchi.validateNfsForm(); } else if (poolType === "iscsi") { return kimchi.validateIscsiForm(); } else if (poolType === "logical") { return kimchi.validateLogicalForm(); } else { return true; } }; kimchi.validateDirForm = function () { var path = $('#pathId').val(); if (!/(^\/.*)$/.test(path)) { kimchi.message.error.code('KCHAPI6003E'); return false; } return true; }; kimchi.validateNfsForm = function () { var nfspath = $('#nfspathId').val(); var nfsserver = $('#nfsserverId').val(); if (!kimchi.validateServer(nfsserver)) { return false; } if (!/((\/([0-9a-zA-Z-_\.]+)))$/.test(nfspath)) { kimchi.message.error.code('KCHPOOL6005E'); return false; } $('#nfs-mount-loading').removeClass('hidden'); return true; }; kimchi.validateIscsiForm = function() { var iscsiServer = $('#iscsiserverId').val(); var iscsiTarget = $('#iscsiTargetId').val(); if (!kimchi.validateServer(iscsiServer)) { return false; } return true; }; kimchi.validateServer = function(serverField) { if(!kimchi.isServer(serverField)) { kimchi.message.error.code('KCHPOOL6009E'); return false; } return true; }; kimchi.validateLogicalForm = function () { if ($("input[name=devices]:checked").length === 0) { kimchi.message.error.code('KCHPOOL6006E'); return false; } else { return true; } }; kimchi.addPool = function(event) { if (kimchi.validateForm()) { var formData = $('#form-pool-add').serializeObject(); delete formData.authname; var poolType = $('#poolTypeId').selectMenu('value'); if (poolType === 'dir') { formData.path = $('#pathId').val(); } else if (poolType === 'logical') { var source = {}; if (!$.isArray(formData.devices)) { var deviceObj = []; deviceObj[0] = formData.devices; source.devices = deviceObj; } else { source.devices = formData.devices; } delete formData.devices; formData.source = source; } else if (poolType === 'netfs'){ var source = {}; source.path = $('#nfspathId').val(); source.host = $('#nfsserverId').val(); formData.source = source; } else if (poolType === 'iscsi') { var source = {}; source.target = $('#iscsiTargetId').val(); source.host = $('#iscsiserverId').val(); $('#iscsiportId').val() !== '' ? source.port = parseInt($('#iscsiportId').val()): null; if ($('#authId').prop("checked")) { source.auth = { "username" : $('#usernameId').val(), "password" : $('#passwordId').val() }; } formData.source = source; } else if (poolType === 'scsi'){ formData.source = { adapter_name: $('#scsiAdapter').selectMenu('value') }; } var storagePoolAddingFunc = function() { $('input', '#form-pool-add').attr('disabled','disabled'); $('#pool-doAdd').hide(); $('#pool-loading').show(); kimchi.createStoragePool(formData, function() { kimchi.doListStoragePools(); kimchi.window.close(); }, function(err) { kimchi.message.error(err.responseJSON.reason); $('input', '#form-pool-add').removeAttr('disabled'); $('#pool-loading').hide(); $('#pool-doAdd').show(); }); }; if (poolType === 'logical') { var settings = { title : i18n['KCHAPI6001M'], content : i18n['KCHPOOL6003M'], confirm : i18n['KCHAPI6002M'], cancel : i18n['KCHAPI6003M'] }; kimchi.confirm(settings, function() { storagePoolAddingFunc(); }, function() { }); } else { storagePoolAddingFunc(); } } }; kimchi-1.5.0/ui/js/src/kimchi.storagepool_add_volume_main.js000066400000000000000000000131601254252253000241440ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2014-2015 * * Licensed under the Apache License, Version 2.0 (the 'License'); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an 'AS IS' BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ kimchi.sp_add_volume_main = function() { // download from remote server or upload from local file var type = 'download'; var addButton = $('#sp-add-volume-button'); var remoteURLBox = $('#volume-remote-url'); var localFileBox = $('#volume-input-file'); var typeRadios = $('input.volume-type'); var isValidURL = function() { var url = $(remoteURLBox).val(); return kimchi.template_check_url(url); }; var isValidFile = function() { var fileName = $(localFileBox).val(); return fileName.length > 0; }; $(typeRadios).change(function(event) { $('.volume-input').prop('disabled', true); $('.volume-input.' + this.value).prop('disabled', false); type = this.value; if(type == 'download') { $(addButton).prop('disabled', !isValidURL()); } else { $(addButton).prop('disabled', !isValidFile()); } }); $(remoteURLBox).on('input propertychange', function(event) { $(addButton).prop('disabled', !isValidURL()); }); $(localFileBox).on('change', function(event) { $(addButton).prop('disabled', !isValidFile()); }); var onError = function(result) { $(this).prop('disabled', false); $(typeRadios).prop('disabled', false); if(!result) { return; } var msg = result['message'] || ( result['responseJSON'] && result['responseJSON']['reason'] ); kimchi.message.error(msg); }; var fetchRemoteFile = function() { var volumeURL = remoteURLBox.val(); var volumeName = volumeURL.split(/(\\|\/)/g).pop(); kimchi.downloadVolumeToSP({ sp: kimchi.selectedSP, url: volumeURL }, function(result) { kimchi.window.close(); kimchi.topic('kimchi/storageVolumeAdded').publish(); }, onError); }; var uploadFile = function() { var chunkSize = 8 * 1024 * 1024; // 8MB var uploaded = 0; var blobFile = $(localFileBox)[0].files[0]; var createUploadVol = function() { kimchi.createVolumeWithCapacity(kimchi.selectedSP, { name: blobFile.name, format: '', capacity: blobFile.size, upload: true }, function(result) { kimchi.window.close(); trackVolCreation(result.id); }, onError); }; var uploadRequest = function(blob) { var fd = new FormData(); fd.append('chunk', blob); fd.append('chunk_size', blob.size); kimchi.uploadVolumeToSP(kimchi.selectedSP, blobFile.name, { formData: fd }, function(result) { if (uploaded < blobFile.size) setTimeout(doUpload, 500); }, onError); uploaded += blob.size }; // Check file exists and has read permission try { var blob = blobFile.slice(0, 20); var reader = new FileReader(); reader.onloadend = function(e) { if (e.loaded == 0) kimchi.message.error.code('KCHAPI6008E'); else createUploadVol(); }; reader.readAsBinaryString(blob); } catch (err) { kimchi.message.error.code('KCHAPI6008E'); return; } var doUpload = function() { try { var blob = blobFile.slice(uploaded, uploaded + chunkSize); var reader = new FileReader(); reader.onloadend = function(e) { if (e.loaded == 0) kimchi.message.error.code('KCHAPI6009E'); else uploadRequest(blob); }; reader.readAsBinaryString(blob); } catch (err) { kimchi.message.error.code('KCHAPI6009E'); return; } } var trackVolCreation = function(taskid) { var onTaskResponse = function(result) { var taskStatus = result['status']; var taskMsg = result['message']; if (taskStatus == 'running') { if (taskMsg != 'ready for upload') { setTimeout(function() { trackVolCreation(taskid); }, 2000); } else { kimchi.topic('kimchi/storageVolumeAdded').publish(); doUpload(); } } }; kimchi.getTask(taskid, onTaskResponse, onError); }; }; $(addButton).on('click', function(event) { $(this).prop('disabled', true); $(typeRadios).prop('disabled', true); if(type === 'download') { fetchRemoteFile(); } else { uploadFile(); } event.preventDefault(); }); }; kimchi-1.5.0/ui/js/src/kimchi.string.js000066400000000000000000000025521254252253000177140ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ Object.defineProperty(String.prototype, "parseKey", { value: function(parsedKey) { try { if (!Array.isArray(parsedKey)) { parsedKey=[]; } } catch (err) { parsedKey=[]; } var openBracket=this.indexOf("["); if (openBracket!=-1) { var id=this.slice(0, openBracket); parsedKey.push(id); var closeBracket=this.lastIndexOf("]"); if (closeBracket==-1) { closeBracket=this.length; } var tmpName=this.slice(openBracket+1,closeBracket); tmpName.parseKey(parsedKey); } else { parsedKey.push(this); } return(parsedKey); } }); kimchi-1.5.0/ui/js/src/kimchi.substitute.js000066400000000000000000000030021254252253000206100ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ kimchi.substitute = function(templateStr, data, tag) { tag = tag || /\{([^\}]+)\}/g; var escapeHtml = function(html) { return String(html) .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"') .replace(/'/g, '''); }; return templateStr.replace(tag, function(matchResult, express) { var propertyArray = express.split('!'); var defaultValue = propertyArray[1] || ''; propertyArray = propertyArray[0].split('.'); var value = data, i = 0, l = propertyArray.length, property; for (; i < l; i++) { property = propertyArray[i]; if (value) { value = value[property]; } else { break; } } return escapeHtml((value || value === 0) ? value : defaultValue); }); }; kimchi-1.5.0/ui/js/src/kimchi.template_add_main.js000066400000000000000000000352361254252253000220420ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2015 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ kimchi.switchPage = function(fromPageId, toPageId, direction) { direction = direction || 'left'; var toLeftBegin; var fromLeftEnd; if('left' === direction) { toLeftBegin = '100%'; fromLeftEnd = '-100%'; } else if('right' === direction) { toLeftBegin = '-100%'; fromLeftEnd = '100%'; } var formPage = $('#'+fromPageId); var toPage = $('#'+toPageId); toPage.css({ left: toLeftBegin }); formPage.animate({ left: fromLeftEnd, opacity: 0.1 }, 400); toPage.animate({ left: '0', opacity: 1 }, 400); }; kimchi.template_add_main = function() { kimchi.deepScanHandler = null; // 1-1 local iso $('#iso-local').click(function() { kimchi.switchPage('iso-type-box', 'iso-local-box'); initLocalIsoField(); initIsoFileField(); kimchi.listIsos(function(isos) { if (isos && isos.length) { showLocalIsoField(isos); $('#iso-more').show(); } else { $('#iso-search').show(); } }, function(err) { kimchi.message.error(err.responseJSON.reason); }); }); $('#iso-local-box-back').click(function() { if (kimchi.deepScanHandler) { kimchi.deepScanHandler.stop = true; } kimchi.switchPage('iso-local-box', 'iso-type-box', 'right'); }); $('#iso-search').click(function() { var settings = { content : i18n['KCHTMPL6002M'] }; kimchi.confirm(settings, function() { $('#iso-search').hide(); $('#iso-search-loading').show(); deepScan('#iso-search'); }); }); $('#iso-more').click(function() { var settings = { content : i18n['KCHTMPL6002M'] }; kimchi.confirm(settings, function() { $('#iso-more').hide(); $('#iso-more-loading').show(); deepScan('#iso-more'); }); }); $('#iso-search-loading').click(function() { $('#iso-search-loading').hide(); $('#iso-search').show(); if (kimchi.deepScanHandler) { kimchi.deepScanHandler.stop = true; } }); $('#iso-more-loading').click(function() { $('#iso-more-loading').hide(); $('#iso-more').show(); if (kimchi.deepScanHandler) { kimchi.deepScanHandler.stop = true; } }); var deepScan = function(button) { kimchi.deepScanHandler = kimchi.stepListDeepScanIsos(function(isos, isFinished) { if (isos && isos.length) { if(button === '#iso-search') { $(button + '-loading').hide(); button = '#iso-more'; $(button + '-loading').show(); } showLocalIsoField(isos); } else { if (isFinished) { kimchi.message.warn(i18n['KCHTMPL6001W']); } } if (isFinished) { $(button + '-loading').hide(); $(button).show(); } }, function(err) { kimchi.message.error(err.responseJSON.reason); $(button + '-loading').hide(); $(button).show(); }); }; //1-1-1 local iso list var initLocalIsoField = function() { kimchi.isoInfo = {}; $('#local-iso-field').hide(); $('#select-all-local-iso').prop('checked', false); $('#btn-template-local-iso-create').attr('disabled', 'disabled'); $('#iso-search').hide(); $('#iso-more').hide(); $('#iso-search-loading').hide(); $('#iso-more-loading').hide(); $('#list-local-iso').empty(); }; var showLocalIsoField = function(isos) { var html = ''; var template = $('#tmpl-list-local-iso').html(); $.each(isos, function(index, volume) { var isoId = volume.os_distro + '*' + volume.name + '*' + volume.os_version; if (!kimchi.isoInfo[isoId]) { volume.isoId = isoId; volume.capacity = kimchi.changetoProperUnit(volume.capacity, 1); kimchi.isoInfo[isoId] = volume; html += kimchi.substitute(template, volume); } }); $('#list-local-iso').append(html); $('#local-iso-field').show(); }; $('#select-all-local-iso').click(function() { $('#list-local-iso [type="checkbox"]').prop('checked', $(this).prop('checked')); if ($(this).prop('checked')) { $('#btn-template-local-iso-create').removeAttr('disabled'); } else { $('#btn-template-local-iso-create').attr('disabled', 'disabled'); } }); $('#list-local-iso').on('click', '[type="checkbox"]', function() { var checkedLength = $('#list-local-iso [type="checkbox"]:checked').length; if (checkedLength) { $('#btn-template-local-iso-create').removeAttr('disabled'); var length = $('#list-local-iso [type="checkbox"]').length; $('#select-all-local-iso').prop('checked', length == checkedLength); } else { $('#select-all-local-iso').prop('checked', false); $('#btn-template-local-iso-create').attr('disabled', 'disabled'); } }); $('#btn-template-local-iso-create').click(function() { submitIso('form-local-iso'); }); //1-1-2 local iso file var initIsoFileField = function() { $('#iso-file-check').prop('checked', false); $('#iso-file-box').hide(); $('#iso-file').val(''); $('#btn-template-file-create').attr('disabled', 'disabled'); }; $('#iso-file-check').click(function() { if ($(this).prop('checked')) { $('#iso-file-box').slideDown(); } else { $('#iso-file-box').slideUp(); } }); $('#iso-file').on('input propertychange', function() { if ($('#iso-file').val()) { $('#btn-template-file-create').removeAttr('disabled'); } else { $('#btn-template-file-create').attr('disabled', 'disabled'); } }); $('#btn-template-file-create').click(function() { var isoFile = $('#iso-file').val(); if (!kimchi.template_check_path(isoFile)) { kimchi.message.error.code('KCHAPI6003E'); return; } var data = { "cdrom" : isoFile }; addTemplate(data); }); //1-2 remote iso $('#iso-remote').css('opacity', 0.3).css('cursor', 'not-allowed'); var enabledRemoteIso = function() { if (kimchi.capabilities == undefined) { setTimeout(enabledRemoteIso, 2000); return; } if (kimchi.capabilities.qemu_stream != true) { return; } $('#iso-remote').css('opacity', 1).css('cursor', 'pointer'); $('#iso-remote').click(function() { kimchi.switchPage('iso-type-box', 'iso-remote-box'); initRemoteIsoField(); initIsoUrlField(); kimchi.listDistros(function(isos) { showRemoteIsoField(isos); }, function() { }); }); }; enabledRemoteIso(); $('#iso-remote-box-back').click(function() { kimchi.switchPage('iso-remote-box', 'iso-type-box', 'right'); }); //1-2-1 remote iso list var initRemoteIsoField = function() { $('#load-remote-iso').show(); $('#remote-iso-field').hide(); $('#iso-url-field').hide(); $('#select-all-remote-iso').prop('checked', false); $('#btn-template-remote-iso-create').attr('disabled', 'disabled'); }; var showRemoteIsoField = function(isos) { if (isos && isos.length) { kimchi.isoInfo = {}; var html = ''; var template = $('#tmpl-list-remote-iso').html(); $.each(isos, function(index, volume) { var isoId = volume.os_distro + '*' + volume.name + '*' + volume.os_version; if (!kimchi.isoInfo[isoId]) { volume.isoId = isoId; kimchi.isoInfo[isoId] = volume; html += kimchi.substitute(template, volume); } }); $('#list-remote-iso').html(html); $('#load-remote-iso').hide() $('#remote-iso-field').show(); $('#iso-url-field').show(); } else { $('#load-remote-iso').hide() $('#iso-url-field').show(); kimchi.message.warn(i18n['KCHTMPL6001W']); } }; $('#select-all-remote-iso').click(function() { $('#list-remote-iso [type="checkbox"]').prop('checked', $(this).prop('checked')); if ($(this).prop('checked')) { $('#btn-template-remote-iso-create').removeAttr('disabled'); } else { $('#btn-template-remote-iso-create').attr('disabled', 'disabled'); } }); $('#list-remote-iso').on('click', '[type="checkbox"]', function() { var checkedLength = $('#list-remote-iso [type="checkbox"]:checked').length; if (checkedLength) { $('#btn-template-remote-iso-create').removeAttr('disabled'); var length = $('#list-remote-iso [type="checkbox"]').length; $('#select-all-remote-iso').prop('checked', length == checkedLength); } else { $('#select-all-remote-iso').prop('checked', false); $('#btn-template-remote-iso-create').attr('disabled', 'disabled'); } }); $('#btn-template-remote-iso-create').click(function() { submitIso('form-remote-iso'); }); //1-2-2 remote iso url var initIsoUrlField = function() { $('#iso-url-check').prop('checked', false); $('#iso-url-box').hide(); $('#iso-url').val(''); $('#btn-template-url-create').attr('disabled', 'disabled'); } $('#iso-url-check').click(function() { if ($(this).prop('checked')) { $('#iso-url-box').slideDown(); } else { $('#iso-url-box').slideUp(); } }); $('#iso-url').on('input propertychange', function() { if ($('#iso-url').val()) { $('#btn-template-url-create').removeAttr('disabled'); } else { $('#btn-template-url-create').attr('disabled', 'disabled'); } }); $('#vm-image-local').click(function(){ kimchi.switchPage('iso-type-box', 'vm-image-local-box'); }); $('#vm-image-local-box-back').click(function(){ kimchi.switchPage('vm-image-local-box', 'iso-type-box', 'right'); }); $('input', '#vm-image-local-box').on('keyup cut paste', function(){ setTimeout(function(){ var isValid = kimchi.template_check_path($('input', '#vm-image-local-box').val()); $('input', '#vm-image-local-box').toggleClass('invalid-field', !isValid); $('button', $('.body', '#vm-image-local-box')).button(isValid ? "enable" : "disable"); }, 0); }); $('button', $('.body', '#vm-image-local-box')).button({ disabled: true }).click(function(){ $('input', '#vm-image-local-box').prop('disabled', true); $(this).button('option', { label: i18n['KCHAPI6008M'], disabled: true }); addTemplate({disks:[{base:$('input', '#vm-image-local-box').val()}]}, function(){ $('input', '#vm-image-local-box').prop('disabled', false); $('button', $('.body', '#vm-image-local-box')).button('option', { label: i18n['KCHAPI6005M'], disabled: false }); }); }); $('#btn-template-url-create').click(function() { var isoUrl = $('#iso-url').val(); if (!kimchi.template_check_url(isoUrl)) { kimchi.message.error.code('KCHAPI6004E'); return; } var data = { "cdrom" : isoUrl }; addTemplate(data); }); //do create var addTemplate = function(data, callback) { kimchi.createTemplate(data, function() { if(callback) callback(); kimchi.doListTemplates(); kimchi.window.close(); kimchi.topic('templateCreated').publish(); }, function(err) { if(callback) callback(); kimchi.message.error(err.responseJSON.reason); }); }; var submitIso = function(formId) { var formData = $('#' + formId).serializeObject(); if (formData.iso) { var length = 0; var successNum = 0; var addTemplate = function(isoInfo) { var data = { "os_distro" : isoInfo.os_distro, "os_version" : isoInfo.os_version, "cdrom" : isoInfo.path }; kimchi.createTemplate(data, function() { successNum++; $('input[value="' + isoInfo.isoId + '"]').prop('checked', false); $('.check-all>input').prop('checked', false); kimchi.doListTemplates(); kimchi.topic('templateCreated').publish(data); if (successNum === length) { kimchi.window.close(); } }, function(err) { kimchi.message.error(err.responseJSON.reason); }); }; if (formData.iso instanceof Array) { length = formData.iso.length; $.each(formData.iso, function(index, value) { addTemplate(kimchi.isoInfo[value]); }); } else { length = 1; addTemplate(kimchi.isoInfo[formData.iso]); } } }; }; kimchi.template_check_url = function(url) { var reg = /(https|http|ftp|ftps|tftp):\/\//; if (url.constructor === String) { return reg.test(url); } return false; }; kimchi.template_check_path = function(filePath) { var reg = /((\/([0-9a-zA-Z-_ \.]+))+)$/; if (filePath.constructor === String) { return reg.test(filePath); } return false; }; kimchi-1.5.0/ui/js/src/kimchi.template_edit_main.js000066400000000000000000000377371254252253000222470ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2015 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ kimchi.template_edit_main = function() { var templateEditMain = $('#edit-template-tabs'); var origDisks; var origPool; var origNetworks; var templateDiskSize; $('#template-name', templateEditMain).val(kimchi.selectedTemplate); templateEditMain.tabs(); var initTemplate = function(template) { origDisks = template.disks; origPool = template.storagepool; origNetworks = template.networks; for(var i=0;iVNC'); $('#template-edit-graphics').append(''); kimchi.select('template-edit-graphics-list', vncOpt); var enableSpice = function() { if (kimchi.capabilities == undefined) { setTimeout(enableSpice, 2000); return; } if (kimchi.capabilities.qemu_spice == true) { spiceOpt = [{label: 'Spice', value: 'spice'}] kimchi.select('template-edit-graphics-list', spiceOpt); } }; enableSpice(); var initStorage = function(result) { var scsipools = {}; var addStorageItem = function(storageData) { var thisName = storageData.storageName; var nodeStorage = $.parseHTML(kimchi.substitute($('#template-storage-pool-tmpl').html(), storageData)); $('.template-tab-body', '#form-template-storage').append(nodeStorage); var storageOptions = ''; var scsiOptions = ''; $('#selectStorageName').find('option').remove(); $.each(result, function(index, storageEntities) { if((storageEntities.state === 'active') && (storageEntities.type != 'kimchi-iso')) { if(storageEntities.type === 'iscsi' || storageEntities.type === 'scsi') { kimchi.listStorageVolumes(storageEntities.name, function(currentVolume) { $.each(currentVolume, function(indexSCSI, scsiEntities) { var tmpPath = storageEntities.name + '/' + scsiEntities.name; var isSlected = tmpPath === thisName ? ' selected' : ''; scsiOptions += '' + tmpPath + ''; }); $('#selectStorageName').append(scsiOptions); }, function() {}); } else { var isSlected = storageEntities.name === thisName ? ' selected' : ''; storageOptions += '' + storageEntities.name + ''; } } }); $('#selectStorageName').append(storageOptions); // Set disk format $('#diskFormat').val(storageData.storageDiskFormat); $('#diskFormat').on('change', function() { $('.template-storage-disk-format').val($(this).val()); }); $('#selectStorageName').change(function() { var selectedItem = $(this).parent().parent(); var tempStorageNameFull = $(this).val(); var tempName = tempStorageNameFull.split('/'); var tempStorageName = tempName[0]; $('.template-storage-name').val(tempStorageNameFull); kimchi.getStoragePool(tempStorageName, function(info) { tempType = info.type; selectedItem.find('.template-storage-type').val(tempType); if (tempType === 'iscsi' || tempType === 'scsi') { kimchi.getStoragePoolVolume(tempStorageName, tempName[tempName.length-1], function(info) { volSize = info.capacity / Math.pow(1024, 3); $('.template-storage-disk', selectedItem).attr('readonly', true).val(volSize); $('#diskFormat').val('raw'); $('#diskFormat').prop('disabled', true).change(); }); } else if (tempType === 'logical') { $('.template-storage-disk', selectedItem).attr('readonly', false); $('#diskFormat').val('raw'); $('#diskFormat').prop('disabled', true).change(); } else { $('.template-storage-disk', selectedItem).attr('readonly', false); if ($('#diskFormat').prop('disabled') == true) { $('#diskFormat').val('qcow2'); $('#diskFormat').prop('disabled', false).change(); } } }); }); }; if ((origDisks && origDisks.length) && (origPool && origPool.length)) { splitPool = origPool.split('/'); var defaultPool = splitPool[splitPool.length-1]; var defaultType; kimchi.getStoragePool(defaultPool, function(info) { defaultType = info.type; $.each(origDisks, function(index, diskEntities) { var storageNodeData = { viewMode : '', editMode : 'hide', storageName : defaultPool, storageType : defaultType, storageDisk : diskEntities.size, storageDiskFormat : diskEntities.format ? diskEntities.format : 'qcow2' } if (diskEntities.volume) { kimchi.getStoragePoolVolume(defaultPool, diskEntities.volume, function(info) { var volSize = info.capacity / Math.pow(1024, 3); var nodeData = storageNodeData nodeData.storageName = defaultPool + '/' + diskEntities.volume; nodeData.storageDisk = volSize; addStorageItem(nodeData); $('.template-storage-disk').attr('readonly', true); $('#diskFormat').val('raw'); $('#diskFormat').prop('disabled', true).change(); }); } else if (defaultType === 'logical') { addStorageItem(storageNodeData); $('#diskFormat').val('raw'); $('#diskFormat').prop('disabled', true).change(); } else { addStorageItem(storageNodeData); } }); }); } $('#template-edit-storage-add-button').button({ icons: { primary: "ui-icon-plusthick" }, text: false, disabled: true }).click(function(event) { event.preventDefault(); var storageNodeData = { viewMode : 'hide', editMode : '', storageName : 'null', storageType : 'dir', storageDisk : '10' } addStorageItem(storageNodeData); }); }; var initInterface = function(result) { var networkItemNum = 0; var addInterfaceItem = function(networkData) { var networkName = networkData.networkV; var nodeInterface = $.parseHTML(kimchi.substitute($('#template-interface-tmpl').html(), networkData)); $('.template-tab-body', '#form-template-interface').append(nodeInterface); $('.delete', '#form-template-interface').button({ icons : {primary : 'ui-icon-trash'}, text : false }).click(function(evt) { evt.preventDefault(); $(this).parent().parent().remove(); }); var networkOptions = ''; for(var i=0;i' + result[i].name + ''; } } $('select', '#form-template-interface #networkID' + networkItemNum).append(networkOptions); networkItemNum += 1; }; if(result && result.length > 0) { for(var i=0;idata.threads_per_core?" selected":""; options += ""+Math.pow(2,i)+""; } $('select', '#form-template-processor').append(options); if(template.cpus) $("#cpus").val(template.cpus); var topo = template.cpu_info.topology; if(topo&&topo.cores) $("#cores").val(topo.cores); if(topo&&topo.threads){ $('select', '#form-template-processor').val(topo.threads); $("input:checkbox", "#form-template-processor").trigger('click'); } }); }; kimchi.listNetworks(initInterface); kimchi.listStoragePools(initStorage); initProcessor(); }; kimchi.retrieveTemplate(kimchi.selectedTemplate, initTemplate); $('#tmpl-edit-button-save').on('click', function() { var editableFields = [ 'name', 'memory', 'disks', 'graphics']; var data = {}; //Fix me: Only support one storage pool now var storages = $('.template-tab-body .item', '#form-template-storage'); var tempName = $('.template-storage-name', storages).val(); var tmpItem = $('#form-template-storage .item'); tempName = tempName.split('/'); var tempNameHead = tempName[0]; var tempNameTail = tempNameHead; if($('.template-storage-type', tmpItem).val() === 'iscsi' || $('.template-storage-type', tmpItem).val() == 'scsi') { tempNameTail = tempName[tempName.length-1]; } tempName = '/storagepools/' + tempNameHead; data['storagepool'] = tempName; $.each(editableFields, function(i, field) { /* Support only 1 disk at this moment */ if (field == 'disks') { if($('.template-storage-type', tmpItem).val() === 'iscsi' || $('.template-storage-type', tmpItem).val() == 'scsi') { origDisks[0]['size'] && delete origDisks[0]['size']; origDisks[0]['volume'] = tempNameTail; } else { origDisks[0]['volume'] && delete origDisks[0]['volume']; origDisks[0].size = Number($('.template-storage-disk', tmpItem).val()); } origDisks[0].format = $('.template-storage-disk-format', tmpItem).val(); data[field] = origDisks; } else if (field == 'graphics') { var type = $('#form-template-general [name="' + field + '"]').val(); data[field] = {'type': type}; } else { data[field] = $('#form-template-general [name="' + field + '"]').val(); } }); data['memory'] = Number(data['memory']); data['cpus'] = parseInt($('#cpus').val()); if($("input:checkbox", "#form-template-processor").prop("checked")){ data['cpu_info'] = { topology: { sockets: 1, cores: parseInt($("#cores").val()), threads: parseInt($("#threads").val()) } }; }else{ data['cpu_info'] = {}; } var networks = $('.template-tab-body .item', '#form-template-interface'); var networkForUpdate = new Array(); $.each(networks, function(index, networkEntities) { var thisValue = $('select', networkEntities).val(); networkForUpdate.push(thisValue); }); if (networkForUpdate instanceof Array) { data.networks = networkForUpdate; } else if (networkForUpdate != null) { data.networks = [networkForUpdate]; } else { data.networks = []; } kimchi.updateTemplate($('#template-name').val(), data, function() { kimchi.doListTemplates(); kimchi.window.close(); }, function(err) { kimchi.message.error(err.responseJSON.reason); }); }); }; kimchi-1.5.0/ui/js/src/kimchi.template_main.js000066400000000000000000000075451254252253000212340ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ kimchi.doListTemplates = function() { kimchi.listTemplates(function(result) { if (result && result.length) { $('#noTemplates').hide(); var listHtml = ''; var templateHtml = $('#templateTmpl').html(); $.each(result, function(index, value) { var isLocal; if(value.cdrom){ isLocal = /^\//.test(value['cdrom']); }else{ for(var i=0;i= 0 && rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && rect.right <= (window.innerWidth || document.documentElement.clientWidth) ); }; /** * To change the byte to proper unit. * @param number needed to change unit. * @param digits after the decimal point. * @returns str with unit. */ kimchi.changetoProperUnit = function(numOrg, digits, base) { if (numOrg === undefined) { return ""; } var suffixes = [ 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y', 'B' ]; var base = base || 1024; var numTemp = numOrg; var result = numOrg.toFixed(digits) + 'B'; for ( var i = 0; i < suffixes.length; i++) { var numTemp = numTemp / base; if (numTemp < 1) break; result = numTemp.toFixed(digits) + suffixes[i] } return result; }; /** * kimchi.formatMeasurement util. * * Refer to "Units of information" ( * http://en.wikipedia.org/wiki/Units_of_information * ) for more information about measurement units. * * @param number The number to be normalized. * @param settings * * base Measurement base, accepts 2 or 10. defaults to 2. * * unit The unit of the measurement, e.g., B, Bytes/s, bps, etc. * * fixed The number of digits after the decimal point. * * @returns [object] * * v The number part of the measurement. * * s The suffix part of the measurement including multiple and unit. * e.g., kB/s means 1000B/s, KiB/s for 1024B/s. */ (function() { var unitBaseMapping = { 2: [{ us: 'Ki', v: 1024 }, { us: 'Mi', v: 1048576 }, { us: 'Gi', v: 1073741824 }, { us: 'Ti', v: 1099511627776 }, { us: 'Pi', v: 1125899906842624 }], 10: [{ us: 'k', v: 1000 }, { us: 'M', v: 1000000 }, { us: 'G', v: 1000000000 }, { us: 'T', v: 1000000000000 }, { us: 'P', v: 1000000000000000 }] }; var Formatted = function(value, suffix) { this['v'] = value; this['s'] = suffix; }; Formatted.prototype.toString = function() { return this['v'] + this['s']; }; var format = function(number, settings) { if(number === (undefined || null) || isNaN(number)) { return number; } var settings = settings || {}; var unit = settings['unit'] || 'B'; var base = settings['base'] || 2; if(base !== 2 && base !== 10) { return new Formatted(number, unit); } var fixed = settings['fixed']; var unitMapping = unitBaseMapping[base]; for(var i = unitMapping.length - 1; i >= 0; i--) { var mapping = unitMapping[i]; var suffix = mapping['us']; var startingValue = mapping['v']; if(number < startingValue) { continue; } var formatted = number / startingValue; formatted = fixed ? formatted.toFixed(fixed) : formatted; return new Formatted(formatted, suffix + unit); } return new Formatted(fixed ? number.toFixed(fixed) : number, unit); }; kimchi.formatMeasurement = format; })(); kimchi.isUnsignedNumeric = function(number) { var reg = /^d+(.d+)?$/ return reg.test(number); } kimchi.isServer = function(server) { var domain = "([0-9a-z_!~*'()-]+\.)*([0-9a-z][0-9a-z-]{0,61})?[0-9a-z]\.[a-z]{2,6}"; var ip = "(\\d{1,3}\.){3}\\d{1,3}"; regex = new RegExp('^' + domain + '|' + ip + '$'); if (!regex.test(server)) { return false; } else { return true; } }; kimchi.escapeStr = function(str) { if (str) return str.replace(/([ #;?%&,.+*~\\':"!^$[\]()<=>`{|}\/@])/g,'\\$&'); return str; }; kimchi.urlSafeB64Decode = function(str) { return atob(str.replace(/-/g, '+').replace(/_/g, '/')); } kimchi.urlSafeB64Encode = function(str) { return btoa(str).replace(/\+/g, '-').replace(/\//g, '_'); } kimchi-1.5.0/ui/js/src/kimchi.window.js000066400000000000000000000040441254252253000177130ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2013-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ kimchi.window = (function() { var _windows = []; var _listeners = {}; var open = function(settings) { var settings = jQuery.type(settings) === 'object' ? settings : { url: settings }; var windowID = settings['id'] || 'window-' + _windows.length; if ($('#' + windowID).length) { $('#' + windowID).remove(); } _windows.push(windowID); _listeners[windowID] = settings['close']; var windowNode = $('
    ', { id: windowID, 'class': settings['class'] ? settings['class'] + ' bgmask remove-when-logged-off' : 'bgmask remove-when-logged-off' }); $(windowNode).css(settings['style'] || ''); $(windowNode).appendTo('body').on('click', '.window .close', function() { kimchi.window.close(); }); if (settings['url']) { $(windowNode).load(settings['url']).fadeIn(100); return; } settings['content'] && $(windowNode).html(settings['content']); }; var close = function() { var windowID = _windows.pop(); if(_listeners[windowID]) { _listeners[windowID](); _listeners[windowID] = null; } delete _listeners[windowID]; $('#' + windowID).fadeOut(100, function() { $(this).remove(); }); }; return { open: open, close: close }; })(); kimchi-1.5.0/ui/js/widgets/000077500000000000000000000000001254252253000154605ustar00rootroot00000000000000kimchi-1.5.0/ui/js/widgets/button-dropDown.js000066400000000000000000000023441254252253000211260ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2014 * * Licensed under the Apache License, Version 2.0 (the 'License'); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an 'AS IS' BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ (function($) { $.widget('kimchi.dropdownButton', { _create : function() { this.actionDiv = this.element; this.actionDiv.addClass('btn dropdown popable'); this.actionDiv.find('div').addClass('popover'); this.actionDiv.find('button').addClass('button-big'); }, destroy : function() { this.actionDiv.removeClass('btn dropdown popable'); this.actionDiv.find('div').removeClass('popover'); this.actionDiv.find('button').removeClass('button-big'); $.Widget.prototype.destroy.call(this); } }); }(jQuery)); kimchi-1.5.0/ui/js/widgets/circleGauge.js000066400000000000000000000065631254252253000202420ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ (function($) { $.widget('kimchi.circleGauge', { options : { color : '#87C004', fillColor : '#87C004', lineWidth : 20, shadowSize : '2px', font : 'bold 13px Geneva, sans-serif', textAlign : 'center', radius : 35, peakRate : 100, display : 0, circle : 0, label : '' }, _create : function() { //valuesAttr="{" + this.element.data('value')+ "}"; //console.info(valuesAttr); //values=eval("(" + valuesAttr + ")"); //$.extend(this.options, values); this.options.display=this.element.data('display'); this.options.percentage=this.element.data('percentage'); this._fixupPeakRate(); this._draw(); }, setValues : function(values) { $.extend(this.options, values); this._fixupPeakRate(); this._draw(); }, _fixupPeakRate : function() { if (this.options.circle>this.options.peakRate) { this.options.peakRate=this.options.circle; } }, _draw : function() { this.element.empty(); var canvas = document.createElement('canvas'); //this.element.append($(canvas)); //I don't quite understand this line so trying the one below... this.element.append(canvas); var ctx = canvas.getContext('2d'); var radius = this.options.radius; var shadowSize = 2; var width = height = radius * 2; $(canvas).attr('height', height); $(canvas).attr('width', width); $(canvas).css({ 'boxShadow' : shadowSize + 'px ' + shadowSize + 'px ' + shadowSize + 'px #fff, -' + shadowSize + 'px -' + shadowSize + 'px ' + shadowSize + 'px #eaeaea', borderRadius : radius + 'px' }); ctx.clearRect(0, 0, width, height); ctx.fillStyle = this.options.fillColor; ctx.font = this.options.font; ctx.textAlign = 'center'; var originPos = radius; ctx.textBaseline = 'middle'; ctx.fillText(this.options.display, originPos, originPos); ctx.strokeStyle = this.options.color; ctx.lineWidth = this.options.lineWidth; ctx.beginPath(); ctx.arc(originPos, originPos, radius, -.5 * Math.PI, (this.options.percentage / 50 - .5) * Math.PI); ctx.stroke(); }, destroy : function() { this.element.empty(); $.Widget.prototype.destroy.call(this); } }); }(jQuery)); kimchi.circleGauge = function(selector) { $(selector).circleGauge(); }; kimchi-1.5.0/ui/js/widgets/combobox.js000066400000000000000000000107511254252253000176320ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2014 * * Licensed under the Apache License, Version 2.0 (the 'License'); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an 'AS IS' BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ (function($) { $.widget('kimchi.combobox', { _create : function() { this.selectDiv = this.element; this.listControl = this.selectDiv.find('ul').first(); this.listControl.html(''); this.target = this.selectDiv.find('input').first(); this.selectDiv.addClass('btn-select dropdown popable'); this.target.addClass('input'); this.target.width(this.selectDiv.width()+10); this.listControl.addClass('select-list'); this.listControl.parent().addClass('popover'); }, setData : function(options) { var that = this; var value = this.target.val(); var selectedClass = 'active'; var itemTag = 'li'; if (options.length > 0) { that.target.after($('')); that.listControl.on('click', itemTag, function(e) { that.listControl.children().removeClass(selectedClass); $(this).addClass(selectedClass); var oldValue = that.target.val(); var newValue = $(this).data('value'); that.target.val(newValue); if (oldValue !== newValue) { that.target.change(); } }); that.selectDiv.click(function(e) { that.listControl.html(''); var items = that._dataList(options); $.each(items, function(index, item) { that.listControl.append(item); }) }); that.target.keyup(function(event) { that.listControl.html(''); var items = that._dataList(options); var temp = 0; $.each(items, function(index, item) { if (item.text().indexOf(that.target.val()) == 0) { that.listControl.append(item); temp++; } }); if (temp > 0 && that.listControl.html() !== '') { that._open(); } else { that._close(); } }); } }, value : function(value) { if (value === undefined) { return this.target.val(); } this.target.val(value); }, _dataList : function(options) { var item; var itemTag = 'li'; var selectedClass = 'active'; var items = []; var that = this; $.each(options, function(index, option) { item = $('<' + itemTag + '>' + option.label +''); item.data('value', option.value); if (option.value === that.target.val()) { item.addClass(selectedClass); } items.push(item); }); return items; }, clear : function() { this.target.val(""); }, _open : function() { var isOpen = this.selectDiv.hasClass('open'); if (!isOpen) { this.selectDiv.addClass('open'); } }, _close : function() { var isOpen = this.selectDiv.hasClass('open'); if (isOpen) { this.selectDiv.removeClass('open'); } }, destroy : function() { this.selectDiv.removeClass('btn-select dropdown popable'); this.target.removeClass('input'); this.listControl.removeClass('select-list'); this.listControl.parent().removeClass('popover'); $.Widget.prototype.destroy.call(this); } }); }(jQuery)); kimchi-1.5.0/ui/js/widgets/filter-select.js000066400000000000000000000116541254252253000205670ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2014 * * Licensed under the Apache License, Version 2.0 (the 'License'); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an 'AS IS' BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ (function($) { $.widget('kimchi.filterselect', { _create : function() { this.selectDiv = this.element; this.listControl = this.selectDiv.find('ul').first(); this.listControl.html(''); this.target = this.selectDiv.find('input').first(); this.selectDiv.addClass('btn-select dropdown popable'); this.target.addClass('input'); this.target.width(this.selectDiv.width()+10); this.listControl.addClass('select-list'); this.listControl.parent().addClass('popover'); }, setData : function(options) { var that = this; var value = this.target.val(); var selectedClass = 'active'; var itemTag = 'li'; if (options.length > 0) { that.target.after($('')); that.listControl.on('click', itemTag, function(e) { that.listControl.children().removeClass(selectedClass); $(this).addClass(selectedClass); var oldValue = that.target.val(); var newValue = $(this).data('value'); that.target.val(newValue); if (oldValue !== newValue) { that.target.change(); that.target.removeClass("invalid-field"); } }); that.selectDiv.click(function(e) { that.listControl.html(''); var items = that._dataList(options); if (items.length === 0) { that.listControl.html(i18n['KCHAPI6005E']); } else { $.each(items, function(index, item) { that.listControl.append(item); }); } }); that.target.keyup(function(event) { that.listControl.html(''); var items = that._dataList(options); var temp = 0; $.each(items, function(index, item) { if (item.text().indexOf(that.target.val()) == 0) { that.listControl.append(item); temp++; } }); if (that.listControl.html() === '') { that.target.addClass("invalid-field"); that.listControl.html(i18n['KCHAPI6005E']); } else { that.target.removeClass("invalid-field"); } if (temp > 0) { that._open(); } }); } }, value : function(value) { if (value === undefined) { return this.target.val(); } this.target.val(value); }, _dataList : function(options) { var item; var itemTag = 'li'; var selectedClass = 'active'; var items = []; var that = this; $.each(options, function(index, option) { item = $('<' + itemTag + '>' + option.label +''); item.data('value', option.value); if (option.value === that.target.val()) { item.addClass(selectedClass); } items.push(item); }); return items; }, clear : function() { this.target.val(""); }, _open : function() { var isOpen = this.selectDiv.hasClass('open'); if (!isOpen) { this.selectDiv.addClass('open'); } }, _close : function() { var isOpen = this.selectDiv.hasClass('open'); if (isOpen) { this.selectDiv.removeClass('open'); } }, destroy : function() { this.selectDiv.removeClass('btn-select dropdown popable'); this.target.removeClass('input'); this.listControl.removeClass('select-list'); this.listControl.parent().removeClass('popover') $.Widget.prototype.destroy.call(this); } }); }(jQuery)); kimchi-1.5.0/ui/js/widgets/select-menu.js000066400000000000000000000062541254252253000202460ustar00rootroot00000000000000/* * Project Kimchi * * Copyright IBM, Corp. 2014 * * Licensed under the Apache License, Version 2.0 (the 'License'); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an 'AS IS' BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ (function($) { $.widget('kimchi.selectMenu', { _create : function() { this.selectDiv = this.element; this.listControl = this.selectDiv.find('ul').first(); this.listControl.html(''); this.target = this.selectDiv.find('input').first(); this.label = this.selectDiv.find('span').first(); this.selectDiv.addClass('btn dropdown popable'); this.target.addClass('input'); this.listControl.addClass('select-list'); this.listControl.parent().addClass('popover'); }, setData : function (options) { var that = this; var value = this.target.val(); var selectedClass = 'active'; var itemTag = 'li'; var item; that.listControl.find('li').remove(); that.label.text(""); that.target.val(""); if (options.length > 0) { $.each(options, function(index, option) { item = $('<' + itemTag + '>' + option.label +''); item.data('value', option.value); if(option.value === value) { item.addClass(selectedClass); that.label.text(option.label); that.target.val(option.value); } that.listControl.append(item); }); that.listControl.on('click', itemTag, function() { that.listControl.children().removeClass(selectedClass); $(this).addClass(selectedClass); that.label.text($(this).text()); var oldValue = that.target.val(); var newValue = $(this).data('value'); that.target.val(newValue); if(oldValue !== newValue) { that.target.change(); } }); } }, value : function(data) { if (data === undefined) { return this.target.val(); } this.target.val(data.value); this.label.val(data.label); }, destroy : function() { this.selectDiv.removeClass('btn dropdown popable'); this.target.removeClass('input'); this.label.removeClass('input'); this.listControl.removeClass('select-list'); this.listControl.parent().removeClass('popover'); $.Widget.prototype.destroy.call(this); } }); }(jQuery)); kimchi-1.5.0/ui/libs/000077500000000000000000000000001254252253000143275ustar00rootroot00000000000000kimchi-1.5.0/ui/libs/Makefile.am000066400000000000000000000012511254252253000163620ustar00rootroot00000000000000# # Kimchi # # Copyright IBM, Corp. 2013 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. SUBDIRS = themes jsdir = $(datadir)/kimchi/ui/libs dist_js_DATA = $(wildcard *.js) $(NULL) kimchi-1.5.0/ui/libs/jquery-1.10.0.min.js000066400000000000000000002655421254252253000175170ustar00rootroot00000000000000/*! jQuery v1.10.0 | (c) 2005, 2013 jQuery Foundation, Inc. | jquery.org/license //@ sourceMappingURL=jquery-1.10.0.min.map */ (function(e,t){var n,r,i=typeof t,o=e.location,a=e.document,s=a.documentElement,l=e.jQuery,u=e.$,c={},p=[],f="1.10.0",d=p.concat,h=p.push,g=p.slice,m=p.indexOf,y=c.toString,v=c.hasOwnProperty,b=f.trim,x=function(e,t){return new x.fn.init(e,t,r)},w=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,T=/\S+/g,C=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,N=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,k=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,E=/^[\],:{}\s]*$/,S=/(?:^|:|,)(?:\s*\[)+/g,A=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,j=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,D=/^-ms-/,L=/-([\da-z])/gi,H=function(e,t){return t.toUpperCase()},q=function(e){(a.addEventListener||"load"===e.type||"complete"===a.readyState)&&(_(),x.ready())},_=function(){a.addEventListener?(a.removeEventListener("DOMContentLoaded",q,!1),e.removeEventListener("load",q,!1)):(a.detachEvent("onreadystatechange",q),e.detachEvent("onload",q))};x.fn=x.prototype={jquery:f,constructor:x,init:function(e,n,r){var i,o;if(!e)return this;if("string"==typeof e){if(i="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:N.exec(e),!i||!i[1]&&n)return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e);if(i[1]){if(n=n instanceof x?n[0]:n,x.merge(this,x.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:a,!0)),k.test(i[1])&&x.isPlainObject(n))for(i in n)x.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i]);return this}if(o=a.getElementById(i[2]),o&&o.parentNode){if(o.id!==i[2])return r.find(e);this.length=1,this[0]=o}return this.context=a,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):x.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),x.makeArray(e,this))},selector:"",length:0,toArray:function(){return g.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=x.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return x.each(this,e,t)},ready:function(e){return x.ready.promise().done(e),this},slice:function(){return this.pushStack(g.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(x.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:h,sort:[].sort,splice:[].splice},x.fn.init.prototype=x.fn,x.extend=x.fn.extend=function(){var e,n,r,i,o,a,s=arguments[0]||{},l=1,u=arguments.length,c=!1;for("boolean"==typeof s&&(c=s,s=arguments[1]||{},l=2),"object"==typeof s||x.isFunction(s)||(s={}),u===l&&(s=this,--l);u>l;l++)if(null!=(o=arguments[l]))for(i in o)e=s[i],r=o[i],s!==r&&(c&&r&&(x.isPlainObject(r)||(n=x.isArray(r)))?(n?(n=!1,a=e&&x.isArray(e)?e:[]):a=e&&x.isPlainObject(e)?e:{},s[i]=x.extend(c,a,r)):r!==t&&(s[i]=r));return s},x.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),noConflict:function(t){return e.$===x&&(e.$=u),t&&e.jQuery===x&&(e.jQuery=l),x},isReady:!1,readyWait:1,holdReady:function(e){e?x.readyWait++:x.ready(!0)},ready:function(e){if(e===!0?!--x.readyWait:!x.isReady){if(!a.body)return setTimeout(x.ready);x.isReady=!0,e!==!0&&--x.readyWait>0||(n.resolveWith(a,[x]),x.fn.trigger&&x(a).trigger("ready").off("ready"))}},isFunction:function(e){return"function"===x.type(e)},isArray:Array.isArray||function(e){return"array"===x.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?c[y.call(e)]||"object":typeof e},isPlainObject:function(e){var n;if(!e||"object"!==x.type(e)||e.nodeType||x.isWindow(e))return!1;try{if(e.constructor&&!v.call(e,"constructor")&&!v.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(r){return!1}if(x.support.ownLast)for(n in e)return v.call(e,n);for(n in e);return n===t||v.call(e,n)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||a;var r=k.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=x.buildFragment([e],t,i),i&&x(i).remove(),x.merge([],r.childNodes))},parseJSON:function(n){return e.JSON&&e.JSON.parse?e.JSON.parse(n):null===n?n:"string"==typeof n&&(n=x.trim(n),n&&E.test(n.replace(A,"@").replace(j,"]").replace(S,"")))?Function("return "+n)():(x.error("Invalid JSON: "+n),t)},parseXML:function(n){var r,i;if(!n||"string"!=typeof n)return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(o){r=t}return r&&r.documentElement&&!r.getElementsByTagName("parsererror").length||x.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&x.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(D,"ms-").replace(L,H)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,a=M(e);if(n){if(a){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(a){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:b&&!b.call("\ufeff\u00a0")?function(e){return null==e?"":b.call(e)}:function(e){return null==e?"":(e+"").replace(C,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(M(Object(e))?x.merge(n,"string"==typeof e?[e]:e):h.call(n,e)),n},inArray:function(e,t,n){var r;if(t){if(m)return m.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,o=0;if("number"==typeof r)for(;r>o;o++)e[i++]=n[o];else while(n[o]!==t)e[i++]=n[o++];return e.length=i,e},grep:function(e,t,n){var r,i=[],o=0,a=e.length;for(n=!!n;a>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,a=M(e),s=[];if(a)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(s[s.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(s[s.length]=r);return d.apply([],s)},guid:1,proxy:function(e,n){var r,i,o;return"string"==typeof n&&(o=e[n],n=e,e=o),x.isFunction(e)?(r=g.call(arguments,2),i=function(){return e.apply(n||this,r.concat(g.call(arguments)))},i.guid=e.guid=e.guid||x.guid++,i):t},access:function(e,n,r,i,o,a,s){var l=0,u=e.length,c=null==r;if("object"===x.type(r)){o=!0;for(l in r)x.access(e,n,l,r[l],!0,a,s)}else if(i!==t&&(o=!0,x.isFunction(i)||(s=!0),c&&(s?(n.call(e,i),n=null):(c=n,n=function(e,t,n){return c.call(x(e),n)})),n))for(;u>l;l++)n(e[l],r,s?i:i.call(e[l],l,n(e[l],r)));return o?e:c?n.call(e):u?n(e[0],r):a},now:function(){return(new Date).getTime()},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),x.ready.promise=function(t){if(!n)if(n=x.Deferred(),"complete"===a.readyState)setTimeout(x.ready);else if(a.addEventListener)a.addEventListener("DOMContentLoaded",q,!1),e.addEventListener("load",q,!1);else{a.attachEvent("onreadystatechange",q),e.attachEvent("onload",q);var r=!1;try{r=null==e.frameElement&&a.documentElement}catch(i){}r&&r.doScroll&&function o(){if(!x.isReady){try{r.doScroll("left")}catch(e){return setTimeout(o,50)}_(),x.ready()}}()}return n.promise(t)},x.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){c["[object "+t+"]"]=t.toLowerCase()});function M(e){var t=e.length,n=x.type(e);return x.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}r=x(a),function(e,t){var n,r,i,o,a,s,l,u,c,p,f,d,h,g,m,y,v,b="sizzle"+-new Date,w=e.document,T=0,C=0,N=lt(),k=lt(),E=lt(),S=!1,A=function(){return 0},j=typeof t,D=1<<31,L={}.hasOwnProperty,H=[],q=H.pop,_=H.push,M=H.push,O=H.slice,F=H.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},B="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",P="[\\x20\\t\\r\\n\\f]",R="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",W=R.replace("w","w#"),$="\\["+P+"*("+R+")"+P+"*(?:([*^$|!~]?=)"+P+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+W+")|)|)"+P+"*\\]",I=":("+R+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+$.replace(3,8)+")*)|.*)\\)|)",z=RegExp("^"+P+"+|((?:^|[^\\\\])(?:\\\\.)*)"+P+"+$","g"),X=RegExp("^"+P+"*,"+P+"*"),U=RegExp("^"+P+"*([>+~]|"+P+")"+P+"*"),V=RegExp(P+"*[+~]"),Y=RegExp("="+P+"*([^\\]'\"]*)"+P+"*\\]","g"),J=RegExp(I),G=RegExp("^"+W+"$"),Q={ID:RegExp("^#("+R+")"),CLASS:RegExp("^\\.("+R+")"),TAG:RegExp("^("+R.replace("w","w*")+")"),ATTR:RegExp("^"+$),PSEUDO:RegExp("^"+I),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+P+"*(even|odd|(([+-]|)(\\d*)n|)"+P+"*(?:([+-]|)"+P+"*(\\d+)|))"+P+"*\\)|)","i"),bool:RegExp("^(?:"+B+")$","i"),needsContext:RegExp("^"+P+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+P+"*((?:-\\d)?\\d*)"+P+"*\\)|)(?=[^-]|$)","i")},K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,et=/^(?:input|select|textarea|button)$/i,tt=/^h\d$/i,nt=/'|\\/g,rt=RegExp("\\\\([\\da-f]{1,6}"+P+"?|("+P+")|.)","ig"),it=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:0>r?String.fromCharCode(r+65536):String.fromCharCode(55296|r>>10,56320|1023&r)};try{M.apply(H=O.call(w.childNodes),w.childNodes),H[w.childNodes.length].nodeType}catch(ot){M={apply:H.length?function(e,t){_.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function at(e,t,n,i){var o,a,s,l,u,c,d,m,y,x;if((t?t.ownerDocument||t:w)!==f&&p(t),t=t||f,n=n||[],!e||"string"!=typeof e)return n;if(1!==(l=t.nodeType)&&9!==l)return[];if(h&&!i){if(o=Z.exec(e))if(s=o[1]){if(9===l){if(a=t.getElementById(s),!a||!a.parentNode)return n;if(a.id===s)return n.push(a),n}else if(t.ownerDocument&&(a=t.ownerDocument.getElementById(s))&&v(t,a)&&a.id===s)return n.push(a),n}else{if(o[2])return M.apply(n,t.getElementsByTagName(e)),n;if((s=o[3])&&r.getElementsByClassName&&t.getElementsByClassName)return M.apply(n,t.getElementsByClassName(s)),n}if(r.qsa&&(!g||!g.test(e))){if(m=d=b,y=t,x=9===l&&e,1===l&&"object"!==t.nodeName.toLowerCase()){c=bt(e),(d=t.getAttribute("id"))?m=d.replace(nt,"\\$&"):t.setAttribute("id",m),m="[id='"+m+"'] ",u=c.length;while(u--)c[u]=m+xt(c[u]);y=V.test(e)&&t.parentNode||t,x=c.join(",")}if(x)try{return M.apply(n,y.querySelectorAll(x)),n}catch(T){}finally{d||t.removeAttribute("id")}}}return At(e.replace(z,"$1"),t,n,i)}function st(e){return K.test(e+"")}function lt(){var e=[];function t(n,r){return e.push(n+=" ")>o.cacheLength&&delete t[e.shift()],t[n]=r}return t}function ut(e){return e[b]=!0,e}function ct(e){var t=f.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function pt(e,t,n){e=e.split("|");var r,i=e.length,a=n?null:t;while(i--)(r=o.attrHandle[e[i]])&&r!==t||(o.attrHandle[e[i]]=a)}function ft(e,t){var n=e.getAttributeNode(t);return n&&n.specified?n.value:e[t]===!0?t.toLowerCase():null}function dt(e,t){return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}function ht(e){return"input"===e.nodeName.toLowerCase()?e.defaultValue:t}function gt(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||D)-(~e.sourceIndex||D);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function mt(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function yt(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function vt(e){return ut(function(t){return t=+t,ut(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}s=at.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},r=at.support={},p=at.setDocument=function(e){var n=e?e.ownerDocument||e:w;return n!==f&&9===n.nodeType&&n.documentElement?(f=n,d=n.documentElement,h=!s(n),r.attributes=ct(function(e){return e.innerHTML="",pt("type|href|height|width",dt,"#"===e.firstChild.getAttribute("href")),pt(B,ft,null==e.getAttribute("disabled")),e.className="i",!e.getAttribute("className")}),r.input=ct(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")}),pt("value",ht,r.attributes&&r.input),r.getElementsByTagName=ct(function(e){return e.appendChild(n.createComment("")),!e.getElementsByTagName("*").length}),r.getElementsByClassName=ct(function(e){return e.innerHTML="
    ",e.firstChild.className="i",2===e.getElementsByClassName("i").length}),r.getById=ct(function(e){return d.appendChild(e).id=b,!n.getElementsByName||!n.getElementsByName(b).length}),r.getById?(o.find.ID=function(e,t){if(typeof t.getElementById!==j&&h){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){return e.getAttribute("id")===t}}):(delete o.find.ID,o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){var n=typeof e.getAttributeNode!==j&&e.getAttributeNode("id");return n&&n.value===t}}),o.find.TAG=r.getElementsByTagName?function(e,n){return typeof n.getElementsByTagName!==j?n.getElementsByTagName(e):t}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},o.find.CLASS=r.getElementsByClassName&&function(e,n){return typeof n.getElementsByClassName!==j&&h?n.getElementsByClassName(e):t},m=[],g=[],(r.qsa=st(n.querySelectorAll))&&(ct(function(e){e.innerHTML="",e.querySelectorAll("[selected]").length||g.push("\\["+P+"*(?:value|"+B+")"),e.querySelectorAll(":checked").length||g.push(":checked")}),ct(function(e){var t=n.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("t",""),e.querySelectorAll("[t^='']").length&&g.push("[*^$]="+P+"*(?:''|\"\")"),e.querySelectorAll(":enabled").length||g.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),g.push(",.*:")})),(r.matchesSelector=st(y=d.webkitMatchesSelector||d.mozMatchesSelector||d.oMatchesSelector||d.msMatchesSelector))&&ct(function(e){r.disconnectedMatch=y.call(e,"div"),y.call(e,"[s!='']:x"),m.push("!=",I)}),g=g.length&&RegExp(g.join("|")),m=m.length&&RegExp(m.join("|")),v=st(d.contains)||d.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},r.sortDetached=ct(function(e){return 1&e.compareDocumentPosition(n.createElement("div"))}),A=d.compareDocumentPosition?function(e,t){if(e===t)return S=!0,0;var i=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t);return i?1&i||!r.sortDetached&&t.compareDocumentPosition(e)===i?e===n||v(w,e)?-1:t===n||v(w,t)?1:c?F.call(c,e)-F.call(c,t):0:4&i?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var r,i=0,o=e.parentNode,a=t.parentNode,s=[e],l=[t];if(e===t)return S=!0,0;if(!o||!a)return e===n?-1:t===n?1:o?-1:a?1:c?F.call(c,e)-F.call(c,t):0;if(o===a)return gt(e,t);r=e;while(r=r.parentNode)s.unshift(r);r=t;while(r=r.parentNode)l.unshift(r);while(s[i]===l[i])i++;return i?gt(s[i],l[i]):s[i]===w?-1:l[i]===w?1:0},n):f},at.matches=function(e,t){return at(e,null,null,t)},at.matchesSelector=function(e,t){if((e.ownerDocument||e)!==f&&p(e),t=t.replace(Y,"='$1']"),!(!r.matchesSelector||!h||m&&m.test(t)||g&&g.test(t)))try{var n=y.call(e,t);if(n||r.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(i){}return at(t,f,null,[e]).length>0},at.contains=function(e,t){return(e.ownerDocument||e)!==f&&p(e),v(e,t)},at.attr=function(e,n){(e.ownerDocument||e)!==f&&p(e);var i=o.attrHandle[n.toLowerCase()],a=i&&L.call(o.attrHandle,n.toLowerCase())?i(e,n,!h):t;return a===t?r.attributes||!h?e.getAttribute(n):(a=e.getAttributeNode(n))&&a.specified?a.value:null:a},at.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},at.uniqueSort=function(e){var t,n=[],i=0,o=0;if(S=!r.detectDuplicates,c=!r.sortStable&&e.slice(0),e.sort(A),S){while(t=e[o++])t===e[o]&&(i=n.push(o));while(i--)e.splice(n[i],1)}return e},a=at.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=a(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=a(t);return n},o=at.selectors={cacheLength:50,createPseudo:ut,match:Q,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(rt,it),e[3]=(e[4]||e[5]||"").replace(rt,it),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||at.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&at.error(e[0]),e},PSEUDO:function(e){var n,r=!e[5]&&e[2];return Q.CHILD.test(e[0])?null:(e[3]&&e[4]!==t?e[2]=e[4]:r&&J.test(r)&&(n=bt(r,!0))&&(n=r.indexOf(")",r.length-n)-r.length)&&(e[0]=e[0].slice(0,n),e[2]=r.slice(0,n)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(rt,it).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=N[e+" "];return t||(t=RegExp("(^|"+P+")"+e+"("+P+"|$)"))&&N(e,function(e){return t.test("string"==typeof e.className&&e.className||typeof e.getAttribute!==j&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=at.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,l){var u,c,p,f,d,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!l&&!s;if(m){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){c=m[b]||(m[b]={}),u=c[e]||[],d=u[0]===T&&u[1],f=u[0]===T&&u[2],p=d&&m.childNodes[d];while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[T,d,f];break}}else if(v&&(u=(t[b]||(t[b]={}))[e])&&u[0]===T)f=u[1];else while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(v&&((p[b]||(p[b]={}))[e]=[T,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=o.pseudos[e]||o.setFilters[e.toLowerCase()]||at.error("unsupported pseudo: "+e);return r[b]?r(t):r.length>1?(n=[e,e,"",t],o.setFilters.hasOwnProperty(e.toLowerCase())?ut(function(e,n){var i,o=r(e,t),a=o.length;while(a--)i=F.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:ut(function(e){var t=[],n=[],r=l(e.replace(z,"$1"));return r[b]?ut(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:ut(function(e){return function(t){return at(e,t).length>0}}),contains:ut(function(e){return function(t){return(t.textContent||t.innerText||a(t)).indexOf(e)>-1}}),lang:ut(function(e){return G.test(e||"")||at.error("unsupported lang: "+e),e=e.replace(rt,it).toLowerCase(),function(t){var n;do if(n=h?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===d},focus:function(e){return e===f.activeElement&&(!f.hasFocus||f.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!o.pseudos.empty(e)},header:function(e){return tt.test(e.nodeName)},input:function(e){return et.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:vt(function(){return[0]}),last:vt(function(e,t){return[t-1]}),eq:vt(function(e,t,n){return[0>n?n+t:n]}),even:vt(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:vt(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:vt(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:vt(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}};for(n in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})o.pseudos[n]=mt(n);for(n in{submit:!0,reset:!0})o.pseudos[n]=yt(n);function bt(e,t){var n,r,i,a,s,l,u,c=k[e+" "];if(c)return t?0:c.slice(0);s=e,l=[],u=o.preFilter;while(s){(!n||(r=X.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),l.push(i=[])),n=!1,(r=U.exec(s))&&(n=r.shift(),i.push({value:n,type:r[0].replace(z," ")}),s=s.slice(n.length));for(a in o.filter)!(r=Q[a].exec(s))||u[a]&&!(r=u[a](r))||(n=r.shift(),i.push({value:n,type:a,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?at.error(e):k(e,l).slice(0)}function xt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function wt(e,t,n){var r=t.dir,o=n&&"parentNode"===r,a=C++;return t.first?function(t,n,i){while(t=t[r])if(1===t.nodeType||o)return e(t,n,i)}:function(t,n,s){var l,u,c,p=T+" "+a;if(s){while(t=t[r])if((1===t.nodeType||o)&&e(t,n,s))return!0}else while(t=t[r])if(1===t.nodeType||o)if(c=t[b]||(t[b]={}),(u=c[r])&&u[0]===p){if((l=u[1])===!0||l===i)return l===!0}else if(u=c[r]=[p],u[1]=e(t,n,s)||i,u[1]===!0)return!0}}function Tt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function Ct(e,t,n,r,i){var o,a=[],s=0,l=e.length,u=null!=t;for(;l>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),u&&t.push(s));return a}function Nt(e,t,n,r,i,o){return r&&!r[b]&&(r=Nt(r)),i&&!i[b]&&(i=Nt(i,o)),ut(function(o,a,s,l){var u,c,p,f=[],d=[],h=a.length,g=o||St(t||"*",s.nodeType?[s]:s,[]),m=!e||!o&&t?g:Ct(g,f,e,s,l),y=n?i||(o?e:h||r)?[]:a:m;if(n&&n(m,y,s,l),r){u=Ct(y,d),r(u,[],s,l),c=u.length;while(c--)(p=u[c])&&(y[d[c]]=!(m[d[c]]=p))}if(o){if(i||e){if(i){u=[],c=y.length;while(c--)(p=y[c])&&u.push(m[c]=p);i(null,y=[],u,l)}c=y.length;while(c--)(p=y[c])&&(u=i?F.call(o,p):f[c])>-1&&(o[u]=!(a[u]=p))}}else y=Ct(y===a?y.splice(h,y.length):y),i?i(null,a,y,l):M.apply(a,y)})}function kt(e){var t,n,r,i=e.length,a=o.relative[e[0].type],s=a||o.relative[" "],l=a?1:0,c=wt(function(e){return e===t},s,!0),p=wt(function(e){return F.call(t,e)>-1},s,!0),f=[function(e,n,r){return!a&&(r||n!==u)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;i>l;l++)if(n=o.relative[e[l].type])f=[wt(Tt(f),n)];else{if(n=o.filter[e[l].type].apply(null,e[l].matches),n[b]){for(r=++l;i>r;r++)if(o.relative[e[r].type])break;return Nt(l>1&&Tt(f),l>1&&xt(e.slice(0,l-1).concat({value:" "===e[l-2].type?"*":""})).replace(z,"$1"),n,r>l&&kt(e.slice(l,r)),i>r&&kt(e=e.slice(r)),i>r&&xt(e))}f.push(n)}return Tt(f)}function Et(e,t){var n=0,r=t.length>0,a=e.length>0,s=function(s,l,c,p,d){var h,g,m,y=[],v=0,b="0",x=s&&[],w=null!=d,C=u,N=s||a&&o.find.TAG("*",d&&l.parentNode||l),k=T+=null==C?1:Math.random()||.1;for(w&&(u=l!==f&&l,i=n);null!=(h=N[b]);b++){if(a&&h){g=0;while(m=e[g++])if(m(h,l,c)){p.push(h);break}w&&(T=k,i=++n)}r&&((h=!m&&h)&&v--,s&&x.push(h))}if(v+=b,r&&b!==v){g=0;while(m=t[g++])m(x,y,l,c);if(s){if(v>0)while(b--)x[b]||y[b]||(y[b]=q.call(p));y=Ct(y)}M.apply(p,y),w&&!s&&y.length>0&&v+t.length>1&&at.uniqueSort(p)}return w&&(T=k,u=C),x};return r?ut(s):s}l=at.compile=function(e,t){var n,r=[],i=[],o=E[e+" "];if(!o){t||(t=bt(e)),n=t.length;while(n--)o=kt(t[n]),o[b]?r.push(o):i.push(o);o=E(e,Et(i,r))}return o};function St(e,t,n){var r=0,i=t.length;for(;i>r;r++)at(e,t[r],n);return n}function At(e,t,n,i){var a,s,u,c,p,f=bt(e);if(!i&&1===f.length){if(s=f[0]=f[0].slice(0),s.length>2&&"ID"===(u=s[0]).type&&r.getById&&9===t.nodeType&&h&&o.relative[s[1].type]){if(t=(o.find.ID(u.matches[0].replace(rt,it),t)||[])[0],!t)return n;e=e.slice(s.shift().value.length)}a=Q.needsContext.test(e)?0:s.length;while(a--){if(u=s[a],o.relative[c=u.type])break;if((p=o.find[c])&&(i=p(u.matches[0].replace(rt,it),V.test(s[0].type)&&t.parentNode||t))){if(s.splice(a,1),e=i.length&&xt(s),!e)return M.apply(n,i),n;break}}}return l(e,f)(i,t,!h,n,V.test(e)),n}o.pseudos.nth=o.pseudos.eq;function jt(){}jt.prototype=o.filters=o.pseudos,o.setFilters=new jt,r.sortStable=b.split("").sort(A).join("")===b,p(),[0,0].sort(A),r.detectDuplicates=S,x.find=at,x.expr=at.selectors,x.expr[":"]=x.expr.pseudos,x.unique=at.uniqueSort,x.text=at.getText,x.isXMLDoc=at.isXML,x.contains=at.contains}(e);var O={};function F(e){var t=O[e]={};return x.each(e.match(T)||[],function(e,n){t[n]=!0}),t}x.Callbacks=function(e){e="string"==typeof e?O[e]||F(e):x.extend({},e);var n,r,i,o,a,s,l=[],u=!e.once&&[],c=function(t){for(r=e.memory&&t,i=!0,a=s||0,s=0,o=l.length,n=!0;l&&o>a;a++)if(l[a].apply(t[0],t[1])===!1&&e.stopOnFalse){r=!1;break}n=!1,l&&(u?u.length&&c(u.shift()):r?l=[]:p.disable())},p={add:function(){if(l){var t=l.length;(function i(t){x.each(t,function(t,n){var r=x.type(n);"function"===r?e.unique&&p.has(n)||l.push(n):n&&n.length&&"string"!==r&&i(n)})})(arguments),n?o=l.length:r&&(s=t,c(r))}return this},remove:function(){return l&&x.each(arguments,function(e,t){var r;while((r=x.inArray(t,l,r))>-1)l.splice(r,1),n&&(o>=r&&o--,a>=r&&a--)}),this},has:function(e){return e?x.inArray(e,l)>-1:!(!l||!l.length)},empty:function(){return l=[],o=0,this},disable:function(){return l=u=r=t,this},disabled:function(){return!l},lock:function(){return u=t,r||p.disable(),this},locked:function(){return!u},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],!l||i&&!u||(n?u.push(t):c(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return!!i}};return p},x.extend({Deferred:function(e){var t=[["resolve","done",x.Callbacks("once memory"),"resolved"],["reject","fail",x.Callbacks("once memory"),"rejected"],["notify","progress",x.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return x.Deferred(function(n){x.each(t,function(t,o){var a=o[0],s=x.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&x.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+"With"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?x.extend(e,r):r}},i={};return r.pipe=r.then,x.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=g.call(arguments),r=n.length,i=1!==r||e&&x.isFunction(e.promise)?r:0,o=1===i?e:x.Deferred(),a=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?g.call(arguments):r,n===s?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},s,l,u;if(r>1)for(s=Array(r),l=Array(r),u=Array(r);r>t;t++)n[t]&&x.isFunction(n[t].promise)?n[t].promise().done(a(t,u,n)).fail(o.reject).progress(a(t,l,s)):--i;return i||o.resolveWith(u,n),o.promise()}}),x.support=function(t){var n,r,o,s,l,u,c,p,f,d=a.createElement("div");if(d.setAttribute("className","t"),d.innerHTML="
    a",n=d.getElementsByTagName("*")||[],r=d.getElementsByTagName("a")[0],!r||!r.style||!n.length)return t;s=a.createElement("select"),u=s.appendChild(a.createElement("option")),o=d.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t.getSetAttribute="t"!==d.className,t.leadingWhitespace=3===d.firstChild.nodeType,t.tbody=!d.getElementsByTagName("tbody").length,t.htmlSerialize=!!d.getElementsByTagName("link").length,t.style=/top/.test(r.getAttribute("style")),t.hrefNormalized="/a"===r.getAttribute("href"),t.opacity=/^0.5/.test(r.style.opacity),t.cssFloat=!!r.style.cssFloat,t.checkOn=!!o.value,t.optSelected=u.selected,t.enctype=!!a.createElement("form").enctype,t.html5Clone="<:nav>"!==a.createElement("nav").cloneNode(!0).outerHTML,t.inlineBlockNeedsLayout=!1,t.shrinkWrapBlocks=!1,t.pixelPosition=!1,t.deleteExpando=!0,t.noCloneEvent=!0,t.reliableMarginRight=!0,t.boxSizingReliable=!0,o.checked=!0,t.noCloneChecked=o.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!u.disabled;try{delete d.test}catch(h){t.deleteExpando=!1}o=a.createElement("input"),o.setAttribute("value",""),t.input=""===o.getAttribute("value"),o.value="t",o.setAttribute("type","radio"),t.radioValue="t"===o.value,o.setAttribute("checked","t"),o.setAttribute("name","t"),l=a.createDocumentFragment(),l.appendChild(o),t.appendChecked=o.checked,t.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,d.attachEvent&&(d.attachEvent("onclick",function(){t.noCloneEvent=!1}),d.cloneNode(!0).click());for(f in{submit:!0,change:!0,focusin:!0})d.setAttribute(c="on"+f,"t"),t[f+"Bubbles"]=c in e||d.attributes[c].expando===!1;d.style.backgroundClip="content-box",d.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===d.style.backgroundClip;for(f in x(t))break;return t.ownLast="0"!==f,x(function(){var n,r,o,s="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",l=a.getElementsByTagName("body")[0];l&&(n=a.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",l.appendChild(n).appendChild(d),d.innerHTML="
    t
    ",o=d.getElementsByTagName("td"),o[0].style.cssText="padding:0;margin:0;border:0;display:none",p=0===o[0].offsetHeight,o[0].style.display="",o[1].style.display="none",t.reliableHiddenOffsets=p&&0===o[0].offsetHeight,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",x.swap(l,null!=l.style.zoom?{zoom:1}:{},function(){t.boxSizing=4===d.offsetWidth}),e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(d,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(d,null)||{width:"4px"}).width,r=d.appendChild(a.createElement("div")),r.style.cssText=d.style.cssText=s,r.style.marginRight=r.style.width="0",d.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),typeof d.style.zoom!==i&&(d.innerHTML="",d.style.cssText=s+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=3===d.offsetWidth,d.style.display="block",d.innerHTML="
    ",d.firstChild.style.width="5px",t.shrinkWrapBlocks=3!==d.offsetWidth,t.inlineBlockNeedsLayout&&(l.style.zoom=1)),l.removeChild(n),n=d=o=r=null)}),n=s=l=u=r=o=null,t}({});var B=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,P=/([A-Z])/g;function R(e,n,r,i){if(x.acceptData(e)){var o,a,s=x.expando,l=e.nodeType,u=l?x.cache:e,c=l?e[s]:e[s]&&s; if(c&&u[c]&&(i||u[c].data)||r!==t||"string"!=typeof n)return c||(c=l?e[s]=p.pop()||x.guid++:s),u[c]||(u[c]=l?{}:{toJSON:x.noop}),("object"==typeof n||"function"==typeof n)&&(i?u[c]=x.extend(u[c],n):u[c].data=x.extend(u[c].data,n)),a=u[c],i||(a.data||(a.data={}),a=a.data),r!==t&&(a[x.camelCase(n)]=r),"string"==typeof n?(o=a[n],null==o&&(o=a[x.camelCase(n)])):o=a,o}}function W(e,t,n){if(x.acceptData(e)){var r,i,o=e.nodeType,a=o?x.cache:e,s=o?e[x.expando]:x.expando;if(a[s]){if(t&&(r=n?a[s]:a[s].data)){x.isArray(t)?t=t.concat(x.map(t,x.camelCase)):t in r?t=[t]:(t=x.camelCase(t),t=t in r?[t]:t.split(" ")),i=t.length;while(i--)delete r[t[i]];if(n?!I(r):!x.isEmptyObject(r))return}(n||(delete a[s].data,I(a[s])))&&(o?x.cleanData([e],!0):x.support.deleteExpando||a!=a.window?delete a[s]:a[s]=null)}}}x.extend({cache:{},noData:{applet:!0,embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(e){return e=e.nodeType?x.cache[e[x.expando]]:e[x.expando],!!e&&!I(e)},data:function(e,t,n){return R(e,t,n)},removeData:function(e,t){return W(e,t)},_data:function(e,t,n){return R(e,t,n,!0)},_removeData:function(e,t){return W(e,t,!0)},acceptData:function(e){if(e.nodeType&&1!==e.nodeType&&9!==e.nodeType)return!1;var t=e.nodeName&&x.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),x.fn.extend({data:function(e,n){var r,i,o=null,a=0,s=this[0];if(e===t){if(this.length&&(o=x.data(s),1===s.nodeType&&!x._data(s,"parsedAttrs"))){for(r=s.attributes;r.length>a;a++)i=r[a].name,0===i.indexOf("data-")&&(i=x.camelCase(i.slice(5)),$(s,i,o[i]));x._data(s,"parsedAttrs",!0)}return o}return"object"==typeof e?this.each(function(){x.data(this,e)}):arguments.length>1?this.each(function(){x.data(this,e,n)}):s?$(s,e,x.data(s,e)):null},removeData:function(e){return this.each(function(){x.removeData(this,e)})}});function $(e,n,r){if(r===t&&1===e.nodeType){var i="data-"+n.replace(P,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:B.test(r)?x.parseJSON(r):r}catch(o){}x.data(e,n,r)}else r=t}return r}function I(e){var t;for(t in e)if(("data"!==t||!x.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}x.extend({queue:function(e,n,r){var i;return e?(n=(n||"fx")+"queue",i=x._data(e,n),r&&(!i||x.isArray(r)?i=x._data(e,n,x.makeArray(r)):i.push(r)),i||[]):t},dequeue:function(e,t){t=t||"fx";var n=x.queue(e,t),r=n.length,i=n.shift(),o=x._queueHooks(e,t),a=function(){x.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),o.cur=i,i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return x._data(e,n)||x._data(e,n,{empty:x.Callbacks("once memory").add(function(){x._removeData(e,t+"queue"),x._removeData(e,n)})})}}),x.fn.extend({queue:function(e,n){var r=2;return"string"!=typeof e&&(n=e,e="fx",r--),r>arguments.length?x.queue(this[0],e):n===t?this:this.each(function(){var t=x.queue(this,e,n);x._queueHooks(this,e),"fx"===e&&"inprogress"!==t[0]&&x.dequeue(this,e)})},dequeue:function(e){return this.each(function(){x.dequeue(this,e)})},delay:function(e,t){return e=x.fx?x.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,o=x.Deferred(),a=this,s=this.length,l=function(){--i||o.resolveWith(a,[a])};"string"!=typeof e&&(n=e,e=t),e=e||"fx";while(s--)r=x._data(a[s],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(l));return l(),o.promise(n)}});var z,X,U=/[\t\r\n\f]/g,V=/\r/g,Y=/^(?:input|select|textarea|button|object)$/i,J=/^(?:a|area)$/i,G=/^(?:checked|selected)$/i,Q=x.support.getSetAttribute,K=x.support.input;x.fn.extend({attr:function(e,t){return x.access(this,x.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){x.removeAttr(this,e)})},prop:function(e,t){return x.access(this,x.prop,e,t,arguments.length>1)},removeProp:function(e){return e=x.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,o,a=0,s=this.length,l="string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).addClass(e.call(this,t,this.className))});if(l)for(t=(e||"").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(U," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=x.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,a=0,s=this.length,l=0===arguments.length||"string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).removeClass(e.call(this,t,this.className))});if(l)for(t=(e||"").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(U," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?x.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e,r="boolean"==typeof t;return x.isFunction(e)?this.each(function(n){x(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var o,a=0,s=x(this),l=t,u=e.match(T)||[];while(o=u[a++])l=r?l:!s.hasClass(o),s[l?"addClass":"removeClass"](o)}else(n===i||"boolean"===n)&&(this.className&&x._data(this,"__className__",this.className),this.className=this.className||e===!1?"":x._data(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(U," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,o=this[0];{if(arguments.length)return i=x.isFunction(e),this.each(function(n){var o;1===this.nodeType&&(o=i?e.call(this,n,x(this).val()):e,null==o?o="":"number"==typeof o?o+="":x.isArray(o)&&(o=x.map(o,function(e){return null==e?"":e+""})),r=x.valHooks[this.type]||x.valHooks[this.nodeName.toLowerCase()],r&&"set"in r&&r.set(this,o,"value")!==t||(this.value=o))});if(o)return r=x.valHooks[o.type]||x.valHooks[o.nodeName.toLowerCase()],r&&"get"in r&&(n=r.get(o,"value"))!==t?n:(n=o.value,"string"==typeof n?n.replace(V,""):null==n?"":n)}}}),x.extend({valHooks:{option:{get:function(e){var t=x.find.attr(e,"value");return null!=t?t:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,l=0>i?s:o?i:0;for(;s>l;l++)if(n=r[l],!(!n.selected&&l!==i||(x.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&x.nodeName(n.parentNode,"optgroup"))){if(t=x(n).val(),o)return t;a.push(t)}return a},set:function(e,t){var n,r,i=e.options,o=x.makeArray(t),a=i.length;while(a--)r=i[a],(r.selected=x.inArray(x(r).val(),o)>=0)&&(n=!0);return n||(e.selectedIndex=-1),o}}},attr:function(e,n,r){var o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return typeof e.getAttribute===i?x.prop(e,n,r):(1===s&&x.isXMLDoc(e)||(n=n.toLowerCase(),o=x.attrHooks[n]||(x.expr.match.bool.test(n)?X:z)),r===t?o&&"get"in o&&null!==(a=o.get(e,n))?a:(a=x.find.attr(e,n),null==a?t:a):null!==r?o&&"set"in o&&(a=o.set(e,r,n))!==t?a:(e.setAttribute(n,r+""),r):(x.removeAttr(e,n),t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(T);if(o&&1===e.nodeType)while(n=o[i++])r=x.propFix[n]||n,x.expr.match.bool.test(n)?K&&Q||!G.test(n)?e[r]=!1:e[x.camelCase("default-"+n)]=e[r]=!1:x.attr(e,n,""),e.removeAttribute(Q?n:r)},attrHooks:{type:{set:function(e,t){if(!x.support.radioValue&&"radio"===t&&x.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{"for":"htmlFor","class":"className"},prop:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return a=1!==s||!x.isXMLDoc(e),a&&(n=x.propFix[n]||n,o=x.propHooks[n]),r!==t?o&&"set"in o&&(i=o.set(e,r,n))!==t?i:e[n]=r:o&&"get"in o&&null!==(i=o.get(e,n))?i:e[n]},propHooks:{tabIndex:{get:function(e){var t=x.find.attr(e,"tabindex");return t?parseInt(t,10):Y.test(e.nodeName)||J.test(e.nodeName)&&e.href?0:-1}}}}),X={set:function(e,t,n){return t===!1?x.removeAttr(e,n):K&&Q||!G.test(n)?e.setAttribute(!Q&&x.propFix[n]||n,n):e[x.camelCase("default-"+n)]=e[n]=!0,n}},x.each(x.expr.match.bool.source.match(/\w+/g),function(e,n){var r=x.expr.attrHandle[n]||x.find.attr;x.expr.attrHandle[n]=K&&Q||!G.test(n)?function(e,n,i){var o=x.expr.attrHandle[n],a=i?t:(x.expr.attrHandle[n]=t)!=r(e,n,i)?n.toLowerCase():null;return x.expr.attrHandle[n]=o,a}:function(e,n,r){return r?t:e[x.camelCase("default-"+n)]?n.toLowerCase():null}}),K&&Q||(x.attrHooks.value={set:function(e,n,r){return x.nodeName(e,"input")?(e.defaultValue=n,t):z&&z.set(e,n,r)}}),Q||(z={set:function(e,n,r){var i=e.getAttributeNode(r);return i||e.setAttributeNode(i=e.ownerDocument.createAttribute(r)),i.value=n+="","value"===r||n===e.getAttribute(r)?n:t}},x.expr.attrHandle.id=x.expr.attrHandle.name=x.expr.attrHandle.coords=function(e,n,r){var i;return r?t:(i=e.getAttributeNode(n))&&""!==i.value?i.value:null},x.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&r.specified?r.value:t},set:z.set},x.attrHooks.contenteditable={set:function(e,t,n){z.set(e,""===t?!1:t,n)}},x.each(["width","height"],function(e,n){x.attrHooks[n]={set:function(e,r){return""===r?(e.setAttribute(n,"auto"),r):t}}})),x.support.hrefNormalized||x.each(["href","src"],function(e,t){x.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}}),x.support.style||(x.attrHooks.style={get:function(e){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+""}}),x.support.optSelected||(x.propHooks.selected={get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}}),x.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){x.propFix[this.toLowerCase()]=this}),x.support.enctype||(x.propFix.enctype="encoding"),x.each(["radio","checkbox"],function(){x.valHooks[this]={set:function(e,n){return x.isArray(n)?e.checked=x.inArray(x(e).val(),n)>=0:t}},x.support.checkOn||(x.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var Z=/^(?:input|select|textarea)$/i,et=/^key/,tt=/^(?:mouse|contextmenu)|click/,nt=/^(?:focusinfocus|focusoutblur)$/,rt=/^([^.]*)(?:\.(.+)|)$/;function it(){return!0}function ot(){return!1}function at(){try{return a.activeElement}catch(e){}}x.event={global:{},add:function(e,n,r,o,a){var s,l,u,c,p,f,d,h,g,m,y,v=x._data(e);if(v){r.handler&&(c=r,r=c.handler,a=c.selector),r.guid||(r.guid=x.guid++),(l=v.events)||(l=v.events={}),(f=v.handle)||(f=v.handle=function(e){return typeof x===i||e&&x.event.triggered===e.type?t:x.event.dispatch.apply(f.elem,arguments)},f.elem=e),n=(n||"").match(T)||[""],u=n.length;while(u--)s=rt.exec(n[u])||[],g=y=s[1],m=(s[2]||"").split(".").sort(),g&&(p=x.event.special[g]||{},g=(a?p.delegateType:p.bindType)||g,p=x.event.special[g]||{},d=x.extend({type:g,origType:y,data:o,handler:r,guid:r.guid,selector:a,needsContext:a&&x.expr.match.needsContext.test(a),namespace:m.join(".")},c),(h=l[g])||(h=l[g]=[],h.delegateCount=0,p.setup&&p.setup.call(e,o,m,f)!==!1||(e.addEventListener?e.addEventListener(g,f,!1):e.attachEvent&&e.attachEvent("on"+g,f))),p.add&&(p.add.call(e,d),d.handler.guid||(d.handler.guid=r.guid)),a?h.splice(h.delegateCount++,0,d):h.push(d),x.event.global[g]=!0);e=null}},remove:function(e,t,n,r,i){var o,a,s,l,u,c,p,f,d,h,g,m=x.hasData(e)&&x._data(e);if(m&&(c=m.events)){t=(t||"").match(T)||[""],u=t.length;while(u--)if(s=rt.exec(t[u])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){p=x.event.special[d]||{},d=(r?p.delegateType:p.bindType)||d,f=c[d]||[],s=s[2]&&RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),l=o=f.length;while(o--)a=f[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&("**"!==r||!a.selector)||(f.splice(o,1),a.selector&&f.delegateCount--,p.remove&&p.remove.call(e,a));l&&!f.length&&(p.teardown&&p.teardown.call(e,h,m.handle)!==!1||x.removeEvent(e,d,m.handle),delete c[d])}else for(d in c)x.event.remove(e,d+t[u],n,r,!0);x.isEmptyObject(c)&&(delete m.handle,x._removeData(e,"events"))}},trigger:function(n,r,i,o){var s,l,u,c,p,f,d,h=[i||a],g=v.call(n,"type")?n.type:n,m=v.call(n,"namespace")?n.namespace.split("."):[];if(u=f=i=i||a,3!==i.nodeType&&8!==i.nodeType&&!nt.test(g+x.event.triggered)&&(g.indexOf(".")>=0&&(m=g.split("."),g=m.shift(),m.sort()),l=0>g.indexOf(":")&&"on"+g,n=n[x.expando]?n:new x.Event(g,"object"==typeof n&&n),n.isTrigger=o?2:3,n.namespace=m.join("."),n.namespace_re=n.namespace?RegExp("(^|\\.)"+m.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,n.result=t,n.target||(n.target=i),r=null==r?[n]:x.makeArray(r,[n]),p=x.event.special[g]||{},o||!p.trigger||p.trigger.apply(i,r)!==!1)){if(!o&&!p.noBubble&&!x.isWindow(i)){for(c=p.delegateType||g,nt.test(c+g)||(u=u.parentNode);u;u=u.parentNode)h.push(u),f=u;f===(i.ownerDocument||a)&&h.push(f.defaultView||f.parentWindow||e)}d=0;while((u=h[d++])&&!n.isPropagationStopped())n.type=d>1?c:p.bindType||g,s=(x._data(u,"events")||{})[n.type]&&x._data(u,"handle"),s&&s.apply(u,r),s=l&&u[l],s&&x.acceptData(u)&&s.apply&&s.apply(u,r)===!1&&n.preventDefault();if(n.type=g,!o&&!n.isDefaultPrevented()&&(!p._default||p._default.apply(h.pop(),r)===!1)&&x.acceptData(i)&&l&&i[g]&&!x.isWindow(i)){f=i[l],f&&(i[l]=null),x.event.triggered=g;try{i[g]()}catch(y){}x.event.triggered=t,f&&(i[l]=f)}return n.result}},dispatch:function(e){e=x.event.fix(e);var n,r,i,o,a,s=[],l=g.call(arguments),u=(x._data(this,"events")||{})[e.type]||[],c=x.event.special[e.type]||{};if(l[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){s=x.event.handlers.call(this,e,u),n=0;while((o=s[n++])&&!e.isPropagationStopped()){e.currentTarget=o.elem,a=0;while((i=o.handlers[a++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(i.namespace))&&(e.handleObj=i,e.data=i.data,r=((x.event.special[i.origType]||{}).handle||i.handler).apply(o.elem,l),r!==t&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,n){var r,i,o,a,s=[],l=n.delegateCount,u=e.target;if(l&&u.nodeType&&(!e.button||"click"!==e.type))for(;u!=this;u=u.parentNode||this)if(1===u.nodeType&&(u.disabled!==!0||"click"!==e.type)){for(o=[],a=0;l>a;a++)i=n[a],r=i.selector+" ",o[r]===t&&(o[r]=i.needsContext?x(r,this).index(u)>=0:x.find(r,this,null,[u]).length),o[r]&&o.push(i);o.length&&s.push({elem:u,handlers:o})}return n.length>l&&s.push({elem:this,handlers:n.slice(l)}),s},fix:function(e){if(e[x.expando])return e;var t,n,r,i=e.type,o=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=tt.test(i)?this.mouseHooks:et.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new x.Event(o),t=r.length;while(t--)n=r[t],e[n]=o[n];return e.target||(e.target=o.srcElement||a),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,o):e},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,i,o,s=n.button,l=n.fromElement;return null==e.pageX&&null!=n.clientX&&(i=e.target.ownerDocument||a,o=i.documentElement,r=i.body,e.pageX=n.clientX+(o&&o.scrollLeft||r&&r.scrollLeft||0)-(o&&o.clientLeft||r&&r.clientLeft||0),e.pageY=n.clientY+(o&&o.scrollTop||r&&r.scrollTop||0)-(o&&o.clientTop||r&&r.clientTop||0)),!e.relatedTarget&&l&&(e.relatedTarget=l===e.target?n.toElement:l),e.which||s===t||(e.which=1&s?1:2&s?3:4&s?2:0),e}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==at()&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:"focusin"},blur:{trigger:function(){return this===at()&&this.blur?(this.blur(),!1):t},delegateType:"focusout"},click:{trigger:function(){return x.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):t},_default:function(e){return x.nodeName(e.target,"a")}},beforeunload:{postDispatch:function(e){e.result!==t&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=x.extend(new x.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?x.event.trigger(i,null,t):x.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},x.removeEvent=a.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]===i&&(e[r]=null),e.detachEvent(r,n))},x.Event=function(e,n){return this instanceof x.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?it:ot):this.type=e,n&&x.extend(this,n),this.timeStamp=e&&e.timeStamp||x.now(),this[x.expando]=!0,t):new x.Event(e,n)},x.Event.prototype={isDefaultPrevented:ot,isPropagationStopped:ot,isImmediatePropagationStopped:ot,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=it,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=it,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=it,this.stopPropagation()}},x.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){x.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!x.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),x.support.submitBubbles||(x.event.special.submit={setup:function(){return x.nodeName(this,"form")?!1:(x.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=x.nodeName(n,"input")||x.nodeName(n,"button")?n.form:t;r&&!x._data(r,"submitBubbles")&&(x.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),x._data(r,"submitBubbles",!0))}),t)},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&x.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){return x.nodeName(this,"form")?!1:(x.event.remove(this,"._submit"),t)}}),x.support.changeBubbles||(x.event.special.change={setup:function(){return Z.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(x.event.add(this,"propertychange._change",function(e){"checked"===e.originalEvent.propertyName&&(this._just_changed=!0)}),x.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),x.event.simulate("change",this,e,!0)})),!1):(x.event.add(this,"beforeactivate._change",function(e){var t=e.target;Z.test(t.nodeName)&&!x._data(t,"changeBubbles")&&(x.event.add(t,"change._change",function(e){!this.parentNode||e.isSimulated||e.isTrigger||x.event.simulate("change",this.parentNode,e,!0)}),x._data(t,"changeBubbles",!0))}),t)},handle:function(e){var n=e.target;return this!==n||e.isSimulated||e.isTrigger||"radio"!==n.type&&"checkbox"!==n.type?e.handleObj.handler.apply(this,arguments):t},teardown:function(){return x.event.remove(this,"._change"),!Z.test(this.nodeName)}}),x.support.focusinBubbles||x.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){x.event.simulate(t,e.target,x.event.fix(e),!0)};x.event.special[t]={setup:function(){0===n++&&a.addEventListener(e,r,!0)},teardown:function(){0===--n&&a.removeEventListener(e,r,!0)}}}),x.fn.extend({on:function(e,n,r,i,o){var a,s;if("object"==typeof e){"string"!=typeof n&&(r=r||n,n=t);for(a in e)this.on(a,n,r,e[a],o);return this}if(null==r&&null==i?(i=n,r=n=t):null==i&&("string"==typeof n?(i=r,r=t):(i=r,r=n,n=t)),i===!1)i=ot;else if(!i)return this;return 1===o&&(s=i,i=function(e){return x().off(e),s.apply(this,arguments)},i.guid=s.guid||(s.guid=x.guid++)),this.each(function(){x.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,o;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,x(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if("object"==typeof e){for(o in e)this.off(o,n,e[o]);return this}return(n===!1||"function"==typeof n)&&(r=n,n=t),r===!1&&(r=ot),this.each(function(){x.event.remove(this,e,r,n)})},trigger:function(e,t){return this.each(function(){x.event.trigger(e,t,this)})},triggerHandler:function(e,n){var r=this[0];return r?x.event.trigger(e,n,r,!0):t}});var st=/^.[^:#\[\.,]*$/,lt=/^(?:parents|prev(?:Until|All))/,ut=x.expr.match.needsContext,ct={children:!0,contents:!0,next:!0,prev:!0};x.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if("string"!=typeof e)return this.pushStack(x(e).filter(function(){for(t=0;i>t;t++)if(x.contains(r[t],this))return!0}));for(t=0;i>t;t++)x.find(e,r[t],n);return n=this.pushStack(i>1?x.unique(n):n),n.selector=this.selector?this.selector+" "+e:e,n},has:function(e){var t,n=x(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(x.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e||[],!0))},filter:function(e){return this.pushStack(ft(this,e||[],!1))},is:function(e){return!!ft(this,"string"==typeof e&&ut.test(e)?x(e):e||[],!1).length},closest:function(e,t){var n,r=0,i=this.length,o=[],a=ut.test(e)||"string"!=typeof e?x(e,t||this.context):0;for(;i>r;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(11>n.nodeType&&(a?a.index(n)>-1:1===n.nodeType&&x.find.matchesSelector(n,e))){n=o.push(n);break}return this.pushStack(o.length>1?x.unique(o):o)},index:function(e){return e?"string"==typeof e?x.inArray(this[0],x(e)):x.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?x(e,t):x.makeArray(e&&e.nodeType?[e]:e),r=x.merge(this.get(),n);return this.pushStack(x.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function pt(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}x.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return x.dir(e,"parentNode")},parentsUntil:function(e,t,n){return x.dir(e,"parentNode",n)},next:function(e){return pt(e,"nextSibling")},prev:function(e){return pt(e,"previousSibling")},nextAll:function(e){return x.dir(e,"nextSibling")},prevAll:function(e){return x.dir(e,"previousSibling")},nextUntil:function(e,t,n){return x.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return x.dir(e,"previousSibling",n)},siblings:function(e){return x.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return x.sibling(e.firstChild)},contents:function(e){return x.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:x.merge([],e.childNodes)}},function(e,t){x.fn[e]=function(n,r){var i=x.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=x.filter(r,i)),this.length>1&&(ct[e]||(i=x.unique(i)),lt.test(e)&&(i=i.reverse())),this.pushStack(i)}}),x.extend({filter:function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?x.find.matchesSelector(r,e)?[r]:[]:x.find.matches(e,x.grep(t,function(e){return 1===e.nodeType}))},dir:function(e,n,r){var i=[],o=e[n];while(o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!x(o).is(r)))1===o.nodeType&&i.push(o),o=o[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function ft(e,t,n){if(x.isFunction(t))return x.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return x.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(st.test(t))return x.filter(t,e,n);t=x.filter(t,e)}return x.grep(e,function(e){return x.inArray(e,t)>=0!==n})}function dt(e){var t=ht.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}var ht="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",gt=/ jQuery\d+="(?:null|\d+)"/g,mt=RegExp("<(?:"+ht+")[\\s/>]","i"),yt=/^\s+/,vt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bt=/<([\w:]+)/,xt=/\s*$/g,At={option:[1,""],legend:[1,"
    ","
    "],area:[1,"",""],param:[1,"",""],thead:[1,"","
    "],tr:[2,"","
    "],col:[2,"","
    "],td:[3,"","
    "],_default:x.support.htmlSerialize?[0,"",""]:[1,"X
    ","
    "]},jt=dt(a),Dt=jt.appendChild(a.createElement("div"));At.optgroup=At.option,At.tbody=At.tfoot=At.colgroup=At.caption=At.thead,At.th=At.td,x.fn.extend({text:function(e){return x.access(this,function(e){return e===t?x.text(this):this.empty().append((this[0]&&this[0].ownerDocument||a).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=e?x.filter(e,this):this,i=0;for(;null!=(n=r[i]);i++)t||1!==n.nodeType||x.cleanData(Ft(n)),n.parentNode&&(t&&x.contains(n.ownerDocument,n)&&_t(Ft(n,"script")),n.parentNode.removeChild(n));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++){1===e.nodeType&&x.cleanData(Ft(e,!1));while(e.firstChild)e.removeChild(e.firstChild);e.options&&x.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return x.clone(this,e,t)})},html:function(e){return x.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(gt,""):t;if(!("string"!=typeof e||Tt.test(e)||!x.support.htmlSerialize&&mt.test(e)||!x.support.leadingWhitespace&&yt.test(e)||At[(bt.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(vt,"<$1>");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(x.cleanData(Ft(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=x.map(this,function(e){return[e.nextSibling,e.parentNode]}),t=0;return this.domManip(arguments,function(n){var r=e[t++],i=e[t++];i&&(r&&r.parentNode!==i&&(r=this.nextSibling),x(this).remove(),i.insertBefore(n,r))},!0),t?this:this.remove()},detach:function(e){return this.remove(e,!0)},domManip:function(e,t,n){e=d.apply([],e);var r,i,o,a,s,l,u=0,c=this.length,p=this,f=c-1,h=e[0],g=x.isFunction(h);if(g||!(1>=c||"string"!=typeof h||x.support.checkClone)&&Nt.test(h))return this.each(function(r){var i=p.eq(r);g&&(e[0]=h.call(this,r,i.html())),i.domManip(e,t,n)});if(c&&(l=x.buildFragment(e,this[0].ownerDocument,!1,!n&&this),r=l.firstChild,1===l.childNodes.length&&(l=r),r)){for(a=x.map(Ft(l,"script"),Ht),o=a.length;c>u;u++)i=l,u!==f&&(i=x.clone(i,!0,!0),o&&x.merge(a,Ft(i,"script"))),t.call(this[u],i,u);if(o)for(s=a[a.length-1].ownerDocument,x.map(a,qt),u=0;o>u;u++)i=a[u],kt.test(i.type||"")&&!x._data(i,"globalEval")&&x.contains(s,i)&&(i.src?x._evalUrl(i.src):x.globalEval((i.text||i.textContent||i.innerHTML||"").replace(St,"")));l=r=null}return this}});function Lt(e,t){return x.nodeName(e,"table")&&x.nodeName(1===t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function Ht(e){return e.type=(null!==x.find.attr(e,"type"))+"/"+e.type,e}function qt(e){var t=Et.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function _t(e,t){var n,r=0;for(;null!=(n=e[r]);r++)x._data(n,"globalEval",!t||x._data(t[r],"globalEval"))}function Mt(e,t){if(1===t.nodeType&&x.hasData(e)){var n,r,i,o=x._data(e),a=x._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)x.event.add(t,n,s[n][r])}a.data&&(a.data=x.extend({},a.data))}}function Ot(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!x.support.noCloneEvent&&t[x.expando]){i=x._data(t);for(r in i.events)x.removeEvent(t,r,i.handle);t.removeAttribute(x.expando)}"script"===n&&t.text!==e.text?(Ht(t).text=e.text,qt(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),x.support.html5Clone&&e.innerHTML&&!x.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Ct.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}x.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){x.fn[e]=function(e){var n,r=0,i=[],o=x(e),a=o.length-1;for(;a>=r;r++)n=r===a?this:this.clone(!0),x(o[r])[t](n),h.apply(i,n.get());return this.pushStack(i)}});function Ft(e,n){var r,o,a=0,s=typeof e.getElementsByTagName!==i?e.getElementsByTagName(n||"*"):typeof e.querySelectorAll!==i?e.querySelectorAll(n||"*"):t;if(!s)for(s=[],r=e.childNodes||e;null!=(o=r[a]);a++)!n||x.nodeName(o,n)?s.push(o):x.merge(s,Ft(o,n));return n===t||n&&x.nodeName(e,n)?x.merge([e],s):s}function Bt(e){Ct.test(e.type)&&(e.defaultChecked=e.checked)}x.extend({clone:function(e,t,n){var r,i,o,a,s,l=x.contains(e.ownerDocument,e);if(x.support.html5Clone||x.isXMLDoc(e)||!mt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(Dt.innerHTML=e.outerHTML,Dt.removeChild(o=Dt.firstChild)),!(x.support.noCloneEvent&&x.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||x.isXMLDoc(e)))for(r=Ft(o),s=Ft(e),a=0;null!=(i=s[a]);++a)r[a]&&Ot(i,r[a]);if(t)if(n)for(s=s||Ft(e),r=r||Ft(o),a=0;null!=(i=s[a]);a++)Mt(i,r[a]);else Mt(e,o);return r=Ft(o,"script"),r.length>0&&_t(r,!l&&Ft(e,"script")),r=s=i=null,o},buildFragment:function(e,t,n,r){var i,o,a,s,l,u,c,p=e.length,f=dt(t),d=[],h=0;for(;p>h;h++)if(o=e[h],o||0===o)if("object"===x.type(o))x.merge(d,o.nodeType?[o]:o);else if(wt.test(o)){s=s||f.appendChild(t.createElement("div")),l=(bt.exec(o)||["",""])[1].toLowerCase(),c=At[l]||At._default,s.innerHTML=c[1]+o.replace(vt,"<$1>")+c[2],i=c[0];while(i--)s=s.lastChild;if(!x.support.leadingWhitespace&&yt.test(o)&&d.push(t.createTextNode(yt.exec(o)[0])),!x.support.tbody){o="table"!==l||xt.test(o)?""!==c[1]||xt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;while(i--)x.nodeName(u=o.childNodes[i],"tbody")&&!u.childNodes.length&&o.removeChild(u)}x.merge(d,s.childNodes),s.textContent="";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),x.support.appendChecked||x.grep(Ft(d,"input"),Bt),h=0;while(o=d[h++])if((!r||-1===x.inArray(o,r))&&(a=x.contains(o.ownerDocument,o),s=Ft(f.appendChild(o),"script"),a&&_t(s),n)){i=0;while(o=s[i++])kt.test(o.type||"")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,l=x.expando,u=x.cache,c=x.support.deleteExpando,f=x.event.special;for(;null!=(n=e[s]);s++)if((t||x.acceptData(n))&&(o=n[l],a=o&&u[o])){if(a.events)for(r in a.events)f[r]?x.event.remove(n,r):x.removeEvent(n,r,a.handle);u[o]&&(delete u[o],c?delete n[l]:typeof n.removeAttribute!==i?n.removeAttribute(l):n[l]=null,p.push(o))}},_evalUrl:function(e){return x.ajax({url:e,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}) }}),x.fn.extend({wrapAll:function(e){if(x.isFunction(e))return this.each(function(t){x(this).wrapAll(e.call(this,t))});if(this[0]){var t=x(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&1===e.firstChild.nodeType)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return x.isFunction(e)?this.each(function(t){x(this).wrapInner(e.call(this,t))}):this.each(function(){var t=x(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=x.isFunction(e);return this.each(function(n){x(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){x.nodeName(this,"body")||x(this).replaceWith(this.childNodes)}).end()}});var Pt,Rt,Wt,$t=/alpha\([^)]*\)/i,It=/opacity\s*=\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp("^("+w+")(.*)$","i"),Yt=RegExp("^("+w+")(?!px)[a-z%]+$","i"),Jt=RegExp("^([+-])=("+w+")","i"),Gt={BODY:"block"},Qt={position:"absolute",visibility:"hidden",display:"block"},Kt={letterSpacing:0,fontWeight:400},Zt=["Top","Right","Bottom","Left"],en=["Webkit","O","Moz","ms"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,"none"===x.css(e,"display")||!x.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=x._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&nn(r)&&(o[a]=x._data(r,"olddisplay",ln(r.nodeName)))):o[a]||(i=nn(r),(n&&"none"!==n||!i)&&x._data(r,"olddisplay",i?n:x.css(r,"display"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"));return e}x.fn.extend({css:function(e,n){return x.access(this,function(e,n,r){var i,o,a={},s=0;if(x.isArray(n)){for(o=Rt(e),i=n.length;i>s;s++)a[n[s]]=x.css(e,n[s],!1,o);return a}return r!==t?x.style(e,n,r):x.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){var t="boolean"==typeof e;return this.each(function(){(t?e:nn(this))?x(this).show():x(this).hide()})}}),x.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":x.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,l=x.camelCase(n),u=e.style;if(n=x.cssProps[l]||(x.cssProps[l]=tn(u,l)),s=x.cssHooks[n]||x.cssHooks[l],r===t)return s&&"get"in s&&(o=s.get(e,!1,i))!==t?o:u[n];if(a=typeof r,"string"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(x.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||x.cssNumber[l]||(r+="px"),x.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(u[n]="inherit"),s&&"set"in s&&(r=s.set(e,r,i))===t)))try{u[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,l=x.camelCase(n);return n=x.cssProps[l]||(x.cssProps[l]=tn(e.style,l)),s=x.cssHooks[n]||x.cssHooks[l],s&&"get"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),"normal"===a&&n in Kt&&(a=Kt[n]),""===r||r?(o=parseFloat(a),r===!0||x.isNumeric(o)?o||0:a):a}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s.getPropertyValue(n)||s[n]:t,u=e.style;return s&&(""!==l||x.contains(e.ownerDocument,e)||(l=x.style(e,n)),Yt.test(l)&&Ut.test(n)&&(i=u.width,o=u.minWidth,a=u.maxWidth,u.minWidth=u.maxWidth=u.width=l,l=s.width,u.width=i,u.minWidth=o,u.maxWidth=a)),l}):a.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s[n]:t,u=e.style;return null==l&&u&&u[n]&&(l=u[n]),Yt.test(l)&&!zt.test(n)&&(i=u.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),u.left="fontSize"===n?"1em":l,l=u.pixelLeft+"px",u.left=i,a&&(o.left=a)),""===l?"auto":l});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function an(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;for(;4>o;o+=2)"margin"===n&&(a+=x.css(e,n+Zt[o],!0,i)),r?("content"===n&&(a-=x.css(e,"padding"+Zt[o],!0,i)),"margin"!==n&&(a-=x.css(e,"border"+Zt[o]+"Width",!0,i))):(a+=x.css(e,"padding"+Zt[o],!0,i),"padding"!==n&&(a+=x.css(e,"border"+Zt[o]+"Width",!0,i)));return a}function sn(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(x.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+an(e,t,n||(a?"border":"content"),r,o)+"px"}function ln(e){var t=a,n=Gt[e];return n||(n=un(e,t),"none"!==n&&n||(Pt=(Pt||x("