[PATCH 00/15] Summary gingerbase plugin code changes

From: chandrureddy <chandra@linux.vnet.ibm.com> Below are the series of patches to separate the host functionality from plugin kimchi to new plugin gingerbase chandrureddy (15): V5 Ginger Base : Taking off the host tab functionality from kimchi V5 Ginger Base : base folder files part 1 V5 Ginger Base : base folder files part 2 V5 Ginger Base : base plugin docs files V5 Ginger Base : base plugin build-aix and contrib folders V5 Ginger Base : base plugin m4 files V5 Ginger Base : control files V5 Ginger Base : base plugin model files V5 Ginger Base : base plugin tests files V5 Ginger Base : base plugin ui/pages/help files V5 Ginger Base : base plugin ui/pages files V5 Ginger Base : base plugin ui/js files V5 Ginger Base : base plugin ui/css files V5 Ginger Base : base plugin ui make, images and config files V5 Ginger Base : base plugin po files src/wok/plugins/gingerbase/API.json | 175 ++ src/wok/plugins/gingerbase/INSTALL | 369 ++++ src/wok/plugins/gingerbase/Makefile.am | 156 ++ src/wok/plugins/gingerbase/README.md | 1 + src/wok/plugins/gingerbase/VERSION | 1 + src/wok/plugins/gingerbase/__init__.py | 22 + src/wok/plugins/gingerbase/autogen.sh | 21 + src/wok/plugins/gingerbase/build-aux/config.rpath | 672 ++++++ src/wok/plugins/gingerbase/build-aux/genChangelog | 25 + src/wok/plugins/gingerbase/build-aux/pkg-version | 59 + src/wok/plugins/gingerbase/config.py.in | 60 + src/wok/plugins/gingerbase/config.rpath | 672 ++++++ src/wok/plugins/gingerbase/configure.ac | 104 + .../plugins/gingerbase/contrib/DEBIAN/Makefile.am | 18 + .../plugins/gingerbase/contrib/DEBIAN/control.in | 14 + src/wok/plugins/gingerbase/contrib/Makefile.am | 36 + src/wok/plugins/gingerbase/contrib/check_i18n.py | 83 + .../gingerbase/contrib/gingerbase.spec.fedora.in | 68 + .../gingerbase/contrib/gingerbase.spec.suse.in | 62 + src/wok/plugins/gingerbase/contrib/make-deb.sh.in | 15 + src/wok/plugins/gingerbase/control/Makefile.am | 26 + src/wok/plugins/gingerbase/control/__init__.py | 27 + src/wok/plugins/gingerbase/control/config.py | 42 + src/wok/plugins/gingerbase/control/cpuinfo.py | 38 + src/wok/plugins/gingerbase/control/debugreports.py | 62 + src/wok/plugins/gingerbase/control/host.py | 146 ++ src/wok/plugins/gingerbase/disks.py | 197 ++ src/wok/plugins/gingerbase/docs/API.md | 314 +++ src/wok/plugins/gingerbase/docs/Makefile.am | 27 + src/wok/plugins/gingerbase/docs/README.md | 201 ++ .../gingerbase/docs/gingerbase-host-tab.png | Bin 0 -> 79669 bytes src/wok/plugins/gingerbase/docs/kimchi-login.png | Bin 0 -> 318041 bytes src/wok/plugins/gingerbase/gingerbase.conf | 31 + src/wok/plugins/gingerbase/gingerbase.py | 62 + src/wok/plugins/gingerbase/i18n.py | 95 + src/wok/plugins/gingerbase/lscpu.py | 126 ++ src/wok/plugins/gingerbase/m4/ac_python_module.m4 | 30 + src/wok/plugins/gingerbase/m4/gettext.m4 | 383 ++++ src/wok/plugins/gingerbase/m4/iconv.m4 | 214 ++ src/wok/plugins/gingerbase/m4/intlmacosx.m4 | 51 + src/wok/plugins/gingerbase/m4/lib-ld.m4 | 110 + src/wok/plugins/gingerbase/m4/lib-link.m4 | 774 +++++++ src/wok/plugins/gingerbase/m4/lib-prefix.m4 | 224 ++ src/wok/plugins/gingerbase/m4/nls.m4 | 32 + src/wok/plugins/gingerbase/m4/po.m4 | 449 ++++ src/wok/plugins/gingerbase/m4/progtest.m4 | 92 + src/wok/plugins/gingerbase/mockmodel.py | 219 ++ src/wok/plugins/gingerbase/model/Makefile.am | 26 + src/wok/plugins/gingerbase/model/__init__.py | 19 + src/wok/plugins/gingerbase/model/config.py | 82 + src/wok/plugins/gingerbase/model/cpuinfo.py | 104 + src/wok/plugins/gingerbase/model/debugreports.py | 214 ++ src/wok/plugins/gingerbase/model/host.py | 427 ++++ src/wok/plugins/gingerbase/model/model.py | 54 + src/wok/plugins/gingerbase/po/LINGUAS | 11 + src/wok/plugins/gingerbase/po/Makefile.in.in | 398 ++++ src/wok/plugins/gingerbase/po/Makevars | 41 + src/wok/plugins/gingerbase/po/POTFILES.in | 3 + src/wok/plugins/gingerbase/po/de_DE.po | 2250 +++++++++++++++++++ src/wok/plugins/gingerbase/po/en_US.po | 2092 ++++++++++++++++++ src/wok/plugins/gingerbase/po/es_ES.po | 2268 +++++++++++++++++++ src/wok/plugins/gingerbase/po/fr_FR.po | 2290 ++++++++++++++++++++ src/wok/plugins/gingerbase/po/gen-pot.in | 9 + src/wok/plugins/gingerbase/po/gingerbase.pot | 2074 ++++++++++++++++++ src/wok/plugins/gingerbase/po/it_IT.po | 2237 +++++++++++++++++++ src/wok/plugins/gingerbase/po/ja_JP.po | 2233 +++++++++++++++++++ src/wok/plugins/gingerbase/po/ko_KR.po | 2163 ++++++++++++++++++ src/wok/plugins/gingerbase/po/pt_BR.po | 2289 +++++++++++++++++++ src/wok/plugins/gingerbase/po/ru_RU.po | 2165 ++++++++++++++++++ src/wok/plugins/gingerbase/po/zh_CN.po | 2117 ++++++++++++++++++ src/wok/plugins/gingerbase/po/zh_TW.po | 2105 ++++++++++++++++++ src/wok/plugins/gingerbase/repositories.py | 535 +++++ src/wok/plugins/gingerbase/swupdate.py | 277 +++ src/wok/plugins/gingerbase/tests/Makefile.am | 50 + src/wok/plugins/gingerbase/tests/run_tests.sh.in | 56 + src/wok/plugins/gingerbase/tests/test_config.py.in | 125 ++ src/wok/plugins/gingerbase/tests/test_host.py | 153 ++ src/wok/plugins/gingerbase/tests/test_model.py | 275 +++ src/wok/plugins/gingerbase/tests/test_rest.py | 184 ++ src/wok/plugins/gingerbase/tests/test_yumparser.py | 164 ++ src/wok/plugins/gingerbase/tests/utils.py | 261 +++ src/wok/plugins/gingerbase/ui/Makefile.am | 21 + src/wok/plugins/gingerbase/ui/config/Makefile.am | 23 + src/wok/plugins/gingerbase/ui/config/tab-ext.xml | 10 + src/wok/plugins/gingerbase/ui/css/Makefile.am | 27 + .../gingerbase/ui/css/theme-default/host.css | 288 +++ .../gingerbase/ui/css/theme-default/report-add.css | 38 + .../ui/css/theme-default/report-rename.css | 40 + .../ui/css/theme-default/repository-add.css | 43 + .../ui/css/theme-default/repository-edit.css | 89 + src/wok/plugins/gingerbase/ui/images/Makefile.am | 23 + src/wok/plugins/gingerbase/ui/images/icon-vm.png | Bin 0 -> 2976 bytes src/wok/plugins/gingerbase/ui/images/logo.ico | Bin 0 -> 1214 bytes .../gingerbase/ui/images/theme-default/Makefile.am | 21 + .../ui/images/theme-default/host-icon-sprite.png | Bin 0 -> 1034 bytes .../images/theme-default/kimchi-loading15x15.gif | Bin 0 -> 1653 bytes src/wok/plugins/gingerbase/ui/js/Makefile.am | 28 + .../plugins/gingerbase/ui/js/src/gingerbase.api.js | 372 ++++ .../gingerbase/ui/js/src/gingerbase.host.js | 860 ++++++++ .../gingerbase/ui/js/src/gingerbase.main.js | 27 + .../ui/js/src/gingerbase.report_add_main.js | 73 + .../ui/js/src/gingerbase.report_rename_main.js | 67 + .../ui/js/src/gingerbase.repository_add_main.js | 97 + .../ui/js/src/gingerbase.repository_edit_main.js | 75 + src/wok/plugins/gingerbase/ui/pages/Makefile.am | 23 + .../plugins/gingerbase/ui/pages/help/Makefile.am | 38 + .../gingerbase/ui/pages/help/de_DE/Makefile.am | 27 + .../gingerbase/ui/pages/help/de_DE/host.dita | 49 + .../plugins/gingerbase/ui/pages/help/dita-help.xsl | 26 + .../gingerbase/ui/pages/help/en_US/Makefile.am | 27 + .../gingerbase/ui/pages/help/en_US/host.dita | 68 + .../gingerbase/ui/pages/help/es_ES/Makefile.am | 27 + .../gingerbase/ui/pages/help/es_ES/host.dita | 49 + .../gingerbase/ui/pages/help/fr_FR/Makefile.am | 27 + .../gingerbase/ui/pages/help/fr_FR/host.dita | 65 + .../gingerbase/ui/pages/help/gingerbase.css | 209 ++ .../gingerbase/ui/pages/help/it_IT/Makefile.am | 27 + .../gingerbase/ui/pages/help/it_IT/host.dita | 51 + .../gingerbase/ui/pages/help/ja_JP/Makefile.am | 27 + .../gingerbase/ui/pages/help/ja_JP/host.dita | 69 + .../gingerbase/ui/pages/help/ko_KR/Makefile.am | 27 + .../gingerbase/ui/pages/help/ko_KR/host.dita | 51 + .../gingerbase/ui/pages/help/pt_BR/Makefile.am | 27 + .../gingerbase/ui/pages/help/pt_BR/host.dita | 72 + .../gingerbase/ui/pages/help/ru_RU/Makefile.am | 27 + .../gingerbase/ui/pages/help/ru_RU/host.dita | 48 + .../gingerbase/ui/pages/help/zh_CN/Makefile.am | 27 + .../gingerbase/ui/pages/help/zh_CN/host.dita | 45 + .../gingerbase/ui/pages/help/zh_TW/Makefile.am | 27 + .../gingerbase/ui/pages/help/zh_TW/host.dita | 49 + src/wok/plugins/gingerbase/ui/pages/host.html.tmpl | 178 ++ src/wok/plugins/gingerbase/ui/pages/i18n.json.tmpl | 149 ++ .../gingerbase/ui/pages/report-add.html.tmpl | 57 + .../gingerbase/ui/pages/report-rename.html.tmpl | 57 + .../gingerbase/ui/pages/repository-add.html.tmpl | 114 + .../gingerbase/ui/pages/repository-edit.html.tmpl | 118 + src/wok/plugins/gingerbase/yumparser.py | 354 +++ src/wok/plugins/kimchi/API.json | 134 -- src/wok/plugins/kimchi/Makefile.am | 3 +- src/wok/plugins/kimchi/config.py.in | 4 - src/wok/plugins/kimchi/control/debugreports.py | 61 - src/wok/plugins/kimchi/control/host.py | 99 +- src/wok/plugins/kimchi/disks.py | 196 -- src/wok/plugins/kimchi/docs/README.md | 6 +- src/wok/plugins/kimchi/i18n.py | 52 - src/wok/plugins/kimchi/kimchi.conf | 7 - src/wok/plugins/kimchi/mockmodel.py | 146 +- src/wok/plugins/kimchi/model/config.py | 21 - src/wok/plugins/kimchi/model/debugreports.py | 213 -- src/wok/plugins/kimchi/model/host.py | 334 +-- src/wok/plugins/kimchi/repositories.py | 533 ----- src/wok/plugins/kimchi/root.py | 1 - src/wok/plugins/kimchi/swupdate.py | 274 --- src/wok/plugins/kimchi/tests/test_authorization.py | 6 - src/wok/plugins/kimchi/tests/test_config.py.in | 8 - src/wok/plugins/kimchi/tests/test_host.py | 97 +- src/wok/plugins/kimchi/tests/test_model.py | 239 +- src/wok/plugins/kimchi/tests/test_rest.py | 54 - src/wok/plugins/kimchi/tests/test_yumparser.py | 162 -- src/wok/plugins/kimchi/ui/config/tab-ext.xml | 7 - .../plugins/kimchi/ui/css/theme-default/host.css | 287 --- .../kimchi/ui/css/theme-default/report-add.css | 37 - .../kimchi/ui/css/theme-default/report-rename.css | 39 - .../kimchi/ui/css/theme-default/repository-add.css | 42 - .../ui/css/theme-default/repository-edit.css | 88 - src/wok/plugins/kimchi/ui/js/src/kimchi.host.js | 858 -------- .../kimchi/ui/js/src/kimchi.report_add_main.js | 72 - .../kimchi/ui/js/src/kimchi.report_rename_main.js | 66 - .../kimchi/ui/js/src/kimchi.repository_add_main.js | 96 - .../ui/js/src/kimchi.repository_edit_main.js | 74 - .../plugins/kimchi/ui/pages/help/de_DE/host.dita | 49 - .../plugins/kimchi/ui/pages/help/en_US/host.dita | 68 - .../plugins/kimchi/ui/pages/help/es_ES/host.dita | 49 - .../plugins/kimchi/ui/pages/help/fr_FR/host.dita | 65 - .../plugins/kimchi/ui/pages/help/it_IT/host.dita | 51 - .../plugins/kimchi/ui/pages/help/ja_JP/host.dita | 69 - .../plugins/kimchi/ui/pages/help/ko_KR/host.dita | 51 - .../plugins/kimchi/ui/pages/help/pt_BR/host.dita | 72 - .../plugins/kimchi/ui/pages/help/ru_RU/host.dita | 48 - .../plugins/kimchi/ui/pages/help/zh_CN/host.dita | 45 - .../plugins/kimchi/ui/pages/help/zh_TW/host.dita | 49 - src/wok/plugins/kimchi/ui/pages/host.html.tmpl | 177 -- .../plugins/kimchi/ui/pages/report-add.html.tmpl | 56 - .../kimchi/ui/pages/report-rename.html.tmpl | 56 - .../kimchi/ui/pages/repository-add.html.tmpl | 113 - .../kimchi/ui/pages/repository-edit.html.tmpl | 117 - src/wok/plugins/kimchi/yumparser.py | 353 --- 187 files changed, 40827 insertions(+), 5791 deletions(-) create mode 100644 src/wok/plugins/gingerbase/API.json create mode 100644 src/wok/plugins/gingerbase/INSTALL create mode 100644 src/wok/plugins/gingerbase/Makefile.am create mode 120000 src/wok/plugins/gingerbase/README.md create mode 100644 src/wok/plugins/gingerbase/VERSION create mode 100644 src/wok/plugins/gingerbase/__init__.py create mode 100755 src/wok/plugins/gingerbase/autogen.sh create mode 100644 src/wok/plugins/gingerbase/build-aux/config.rpath create mode 100755 src/wok/plugins/gingerbase/build-aux/genChangelog create mode 100755 src/wok/plugins/gingerbase/build-aux/pkg-version create mode 100644 src/wok/plugins/gingerbase/config.py.in create mode 100644 src/wok/plugins/gingerbase/config.rpath create mode 100644 src/wok/plugins/gingerbase/configure.ac create mode 100644 src/wok/plugins/gingerbase/contrib/DEBIAN/Makefile.am create mode 100644 src/wok/plugins/gingerbase/contrib/DEBIAN/control.in create mode 100644 src/wok/plugins/gingerbase/contrib/Makefile.am create mode 100755 src/wok/plugins/gingerbase/contrib/check_i18n.py create mode 100644 src/wok/plugins/gingerbase/contrib/gingerbase.spec.fedora.in create mode 100644 src/wok/plugins/gingerbase/contrib/gingerbase.spec.suse.in create mode 100644 src/wok/plugins/gingerbase/contrib/make-deb.sh.in create mode 100644 src/wok/plugins/gingerbase/control/Makefile.am create mode 100644 src/wok/plugins/gingerbase/control/__init__.py create mode 100644 src/wok/plugins/gingerbase/control/config.py create mode 100644 src/wok/plugins/gingerbase/control/cpuinfo.py create mode 100644 src/wok/plugins/gingerbase/control/debugreports.py create mode 100644 src/wok/plugins/gingerbase/control/host.py create mode 100644 src/wok/plugins/gingerbase/disks.py create mode 100644 src/wok/plugins/gingerbase/docs/API.md create mode 100644 src/wok/plugins/gingerbase/docs/Makefile.am create mode 100644 src/wok/plugins/gingerbase/docs/README.md create mode 100644 src/wok/plugins/gingerbase/docs/gingerbase-host-tab.png create mode 100644 src/wok/plugins/gingerbase/docs/kimchi-login.png create mode 100644 src/wok/plugins/gingerbase/gingerbase.conf create mode 100644 src/wok/plugins/gingerbase/gingerbase.py create mode 100644 src/wok/plugins/gingerbase/i18n.py create mode 100644 src/wok/plugins/gingerbase/lscpu.py create mode 100644 src/wok/plugins/gingerbase/m4/ac_python_module.m4 create mode 100644 src/wok/plugins/gingerbase/m4/gettext.m4 create mode 100644 src/wok/plugins/gingerbase/m4/iconv.m4 create mode 100644 src/wok/plugins/gingerbase/m4/intlmacosx.m4 create mode 100644 src/wok/plugins/gingerbase/m4/lib-ld.m4 create mode 100644 src/wok/plugins/gingerbase/m4/lib-link.m4 create mode 100644 src/wok/plugins/gingerbase/m4/lib-prefix.m4 create mode 100644 src/wok/plugins/gingerbase/m4/nls.m4 create mode 100644 src/wok/plugins/gingerbase/m4/po.m4 create mode 100644 src/wok/plugins/gingerbase/m4/progtest.m4 create mode 100644 src/wok/plugins/gingerbase/mockmodel.py create mode 100644 src/wok/plugins/gingerbase/model/Makefile.am create mode 100644 src/wok/plugins/gingerbase/model/__init__.py create mode 100644 src/wok/plugins/gingerbase/model/config.py create mode 100644 src/wok/plugins/gingerbase/model/cpuinfo.py create mode 100644 src/wok/plugins/gingerbase/model/debugreports.py create mode 100644 src/wok/plugins/gingerbase/model/host.py create mode 100644 src/wok/plugins/gingerbase/model/model.py create mode 100644 src/wok/plugins/gingerbase/po/LINGUAS create mode 100644 src/wok/plugins/gingerbase/po/Makefile.in.in create mode 100644 src/wok/plugins/gingerbase/po/Makevars create mode 100644 src/wok/plugins/gingerbase/po/POTFILES.in create mode 100644 src/wok/plugins/gingerbase/po/de_DE.po create mode 100644 src/wok/plugins/gingerbase/po/en_US.po create mode 100644 src/wok/plugins/gingerbase/po/es_ES.po create mode 100644 src/wok/plugins/gingerbase/po/fr_FR.po create mode 100644 src/wok/plugins/gingerbase/po/gen-pot.in create mode 100755 src/wok/plugins/gingerbase/po/gingerbase.pot create mode 100644 src/wok/plugins/gingerbase/po/it_IT.po create mode 100644 src/wok/plugins/gingerbase/po/ja_JP.po create mode 100644 src/wok/plugins/gingerbase/po/ko_KR.po create mode 100644 src/wok/plugins/gingerbase/po/pt_BR.po create mode 100644 src/wok/plugins/gingerbase/po/ru_RU.po create mode 100644 src/wok/plugins/gingerbase/po/zh_CN.po create mode 100644 src/wok/plugins/gingerbase/po/zh_TW.po create mode 100644 src/wok/plugins/gingerbase/repositories.py create mode 100644 src/wok/plugins/gingerbase/swupdate.py create mode 100644 src/wok/plugins/gingerbase/tests/Makefile.am create mode 100644 src/wok/plugins/gingerbase/tests/run_tests.sh.in create mode 100644 src/wok/plugins/gingerbase/tests/test_config.py.in create mode 100644 src/wok/plugins/gingerbase/tests/test_host.py create mode 100644 src/wok/plugins/gingerbase/tests/test_model.py create mode 100644 src/wok/plugins/gingerbase/tests/test_rest.py create mode 100644 src/wok/plugins/gingerbase/tests/test_yumparser.py create mode 100644 src/wok/plugins/gingerbase/tests/utils.py create mode 100644 src/wok/plugins/gingerbase/ui/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/config/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/config/tab-ext.xml create mode 100644 src/wok/plugins/gingerbase/ui/css/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/css/theme-default/host.css create mode 100644 src/wok/plugins/gingerbase/ui/css/theme-default/report-add.css create mode 100644 src/wok/plugins/gingerbase/ui/css/theme-default/report-rename.css create mode 100644 src/wok/plugins/gingerbase/ui/css/theme-default/repository-add.css create mode 100644 src/wok/plugins/gingerbase/ui/css/theme-default/repository-edit.css create mode 100644 src/wok/plugins/gingerbase/ui/images/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/images/icon-vm.png create mode 100644 src/wok/plugins/gingerbase/ui/images/logo.ico create mode 100644 src/wok/plugins/gingerbase/ui/images/theme-default/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/images/theme-default/host-icon-sprite.png create mode 100644 src/wok/plugins/gingerbase/ui/images/theme-default/kimchi-loading15x15.gif create mode 100644 src/wok/plugins/gingerbase/ui/js/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.api.js create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.host.js create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.main.js create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.report_add_main.js create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.report_rename_main.js create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.repository_add_main.js create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.repository_edit_main.js create mode 100644 src/wok/plugins/gingerbase/ui/pages/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/de_DE/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/de_DE/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/dita-help.xsl create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/en_US/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/en_US/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/es_ES/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/es_ES/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/fr_FR/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/fr_FR/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/gingerbase.css create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/it_IT/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/it_IT/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/ja_JP/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/ja_JP/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/ko_KR/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/ko_KR/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/pt_BR/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/pt_BR/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/ru_RU/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/ru_RU/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/zh_CN/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/zh_CN/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/zh_TW/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/zh_TW/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/host.html.tmpl create mode 100644 src/wok/plugins/gingerbase/ui/pages/i18n.json.tmpl create mode 100644 src/wok/plugins/gingerbase/ui/pages/report-add.html.tmpl create mode 100644 src/wok/plugins/gingerbase/ui/pages/report-rename.html.tmpl create mode 100644 src/wok/plugins/gingerbase/ui/pages/repository-add.html.tmpl create mode 100644 src/wok/plugins/gingerbase/ui/pages/repository-edit.html.tmpl create mode 100644 src/wok/plugins/gingerbase/yumparser.py delete mode 100644 src/wok/plugins/kimchi/control/debugreports.py delete mode 100644 src/wok/plugins/kimchi/disks.py delete mode 100644 src/wok/plugins/kimchi/model/debugreports.py delete mode 100644 src/wok/plugins/kimchi/repositories.py delete mode 100644 src/wok/plugins/kimchi/swupdate.py delete mode 100644 src/wok/plugins/kimchi/tests/test_yumparser.py delete mode 100644 src/wok/plugins/kimchi/ui/css/theme-default/host.css delete mode 100644 src/wok/plugins/kimchi/ui/css/theme-default/report-add.css delete mode 100644 src/wok/plugins/kimchi/ui/css/theme-default/report-rename.css delete mode 100644 src/wok/plugins/kimchi/ui/css/theme-default/repository-add.css delete mode 100644 src/wok/plugins/kimchi/ui/css/theme-default/repository-edit.css delete mode 100644 src/wok/plugins/kimchi/ui/js/src/kimchi.host.js delete mode 100644 src/wok/plugins/kimchi/ui/js/src/kimchi.report_add_main.js delete mode 100644 src/wok/plugins/kimchi/ui/js/src/kimchi.report_rename_main.js delete mode 100644 src/wok/plugins/kimchi/ui/js/src/kimchi.repository_add_main.js delete mode 100644 src/wok/plugins/kimchi/ui/js/src/kimchi.repository_edit_main.js delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/de_DE/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/en_US/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/es_ES/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/fr_FR/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/it_IT/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/ja_JP/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/ko_KR/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/pt_BR/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/ru_RU/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/zh_CN/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/zh_TW/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/host.html.tmpl delete mode 100644 src/wok/plugins/kimchi/ui/pages/report-add.html.tmpl delete mode 100644 src/wok/plugins/kimchi/ui/pages/report-rename.html.tmpl delete mode 100644 src/wok/plugins/kimchi/ui/pages/repository-add.html.tmpl delete mode 100644 src/wok/plugins/kimchi/ui/pages/repository-edit.html.tmpl delete mode 100644 src/wok/plugins/kimchi/yumparser.py -- 2.1.0

From: chandrureddy <chandra@linux.vnet.ibm.com> --- src/wok/plugins/kimchi/API.json | 134 --------- src/wok/plugins/kimchi/Makefile.am | 3 +- src/wok/plugins/kimchi/config.py.in | 4 - src/wok/plugins/kimchi/control/host.py | 99 +----- src/wok/plugins/kimchi/docs/README.md | 6 +- src/wok/plugins/kimchi/i18n.py | 52 ---- src/wok/plugins/kimchi/kimchi.conf | 7 - src/wok/plugins/kimchi/mockmodel.py | 146 +-------- src/wok/plugins/kimchi/model/config.py | 21 -- src/wok/plugins/kimchi/model/host.py | 334 +-------------------- src/wok/plugins/kimchi/root.py | 1 - src/wok/plugins/kimchi/tests/test_authorization.py | 6 - src/wok/plugins/kimchi/tests/test_config.py.in | 8 - src/wok/plugins/kimchi/tests/test_host.py | 97 +----- src/wok/plugins/kimchi/tests/test_model.py | 239 +-------------- src/wok/plugins/kimchi/tests/test_rest.py | 54 ---- src/wok/plugins/kimchi/ui/config/tab-ext.xml | 7 - 17 files changed, 13 insertions(+), 1205 deletions(-) diff --git a/src/wok/plugins/kimchi/API.json b/src/wok/plugins/kimchi/API.json index fc1d2dd..6189207 100644 --- a/src/wok/plugins/kimchi/API.json +++ b/src/wok/plugins/kimchi/API.json @@ -59,30 +59,6 @@ } }, "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", @@ -684,116 +660,6 @@ "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": { diff --git a/src/wok/plugins/kimchi/Makefile.am b/src/wok/plugins/kimchi/Makefile.am index 34ddef4..f2b05cd 100644 --- a/src/wok/plugins/kimchi/Makefile.am +++ b/src/wok/plugins/kimchi/Makefile.am @@ -101,7 +101,6 @@ install-deb: install mkdir -p $(DESTDIR)/$(localstatedir)/lib/wok/ touch $(DESTDIR)/$(localstatedir)/lib/wok/objectstore mkdir -p $(DESTDIR)/$(localstatedir)/lib/wok/plugins/kimchi/vnc-tokens - mkdir -p $(DESTDIR)/$(localstatedir)/lib/wok/plugins/kimchi/debugreports mkdir -p $(DESTDIR)/$(localstatedir)/lib/wok/plugins/kimchi/screenshots mkdir -p $(DESTDIR)/$(localstatedir)/lib/wok/plugins/kimchi/isos @@ -144,7 +143,7 @@ install-data-local: $(MKDIR_P) $(DESTDIR)$(kimchidir) $(INSTALL_DATA) API.json $(DESTDIR)$(kimchidir)/API.json mkdir -p $(DESTDIR)/$(localstatedir)/lib/wok/plugins/kimchi/vnc-tokens - mkdir -p $(DESTDIR)/$(localstatedir)/lib/wok/plugins/kimchi/{debugreports,isos,screenshots} + mkdir -p $(DESTDIR)/$(localstatedir)/lib/wok/plugins/kimchi/{isos,screenshots} uninstall-local: $(RM) $(DESTDIR)$(kimchidir)/API.json diff --git a/src/wok/plugins/kimchi/config.py.in b/src/wok/plugins/kimchi/config.py.in index 6ae0ccd..43e7811 100644 --- a/src/wok/plugins/kimchi/config.py.in +++ b/src/wok/plugins/kimchi/config.py.in @@ -38,10 +38,6 @@ def get_distros_store(): return os.path.join(PluginPaths('kimchi').conf_dir, 'distros.d') -def get_debugreports_path(): - return os.path.join(PluginPaths('kimchi').state_dir, 'debugreports') - - def get_screenshot_path(): return os.path.join(PluginPaths('kimchi').state_dir, 'screenshots') diff --git a/src/wok/plugins/kimchi/control/host.py b/src/wok/plugins/kimchi/control/host.py index 0a40f1b..91edd73 100644 --- a/src/wok/plugins/kimchi/control/host.py +++ b/src/wok/plugins/kimchi/control/host.py @@ -19,7 +19,6 @@ from wok.control.base import Collection, Resource, SimpleCollection from wok.control.utils import UrlSubNode -from wok.exception import NotFoundError from cpuinfo import CPUInfo @@ -31,14 +30,7 @@ class Host(Resource): 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 @@ -46,54 +38,6 @@ class Host(Resource): 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) @@ -113,45 +57,4 @@ class Device(Resource): @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 + return self.info \ No newline at end of file diff --git a/src/wok/plugins/kimchi/docs/README.md b/src/wok/plugins/kimchi/docs/README.md index fb0aef9..c838f0e 100644 --- a/src/wok/plugins/kimchi/docs/README.md +++ b/src/wok/plugins/kimchi/docs/README.md @@ -177,13 +177,13 @@ Usage Connect your browser to https://localhost:8001. You should see a screen like: - + Wok 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: - + 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 @@ -197,7 +197,7 @@ top navigation bar. The template screen looks like: - + From this view, you can change the parameters of a template or create a new template using the "+" button in the upper right corner. diff --git a/src/wok/plugins/kimchi/i18n.py b/src/wok/plugins/kimchi/i18n.py index ea325b8..ca48160 100644 --- a/src/wok/plugins/kimchi/i18n.py +++ b/src/wok/plugins/kimchi/i18n.py @@ -32,9 +32,6 @@ messages = { "KCHDEVS0003E": _('"_passthrough_affected_by" should be a device name string'), "KCHDEVS0004E": _('"_available_only" should be "true" or "false"'), - "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."), @@ -246,31 +243,13 @@ messages = { "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."), - "KCHUTILS0003E": _("Unable to choose a virtual machine name"), "KCHVMSTOR0002E": _("Invalid storage type. Types supported: 'cdrom', 'disk'"), @@ -289,37 +268,6 @@ messages = { "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'."), diff --git a/src/wok/plugins/kimchi/kimchi.conf b/src/wok/plugins/kimchi/kimchi.conf index 1bf78e4..ebf346f 100644 --- a/src/wok/plugins/kimchi/kimchi.conf +++ b/src/wok/plugins/kimchi/kimchi.conf @@ -23,13 +23,6 @@ tools.staticdir.on = True tools.staticdir.dir = wok.config.PluginPaths('kimchi').state_dir + '/screenshots' tools.nocache.on = False -[/data/debugreports] -tools.staticdir.on = True -tools.staticdir.dir = wok.config.PluginPaths('kimchi').state_dir + '/debugreports' -tools.nocache.on = False -tools.wokauth.on = True -tools.staticdir.content_types = {'xz': 'application/x-xz'} - [/help] tools.staticdir.on = True tools.staticdir.dir = wok.config.PluginPaths('kimchi').ui_dir + '/pages/help' diff --git a/src/wok/plugins/kimchi/mockmodel.py b/src/wok/plugins/kimchi/mockmodel.py index 0832b20..5e5af0b 100644 --- a/src/wok/plugins/kimchi/mockmodel.py +++ b/src/wok/plugins/kimchi/mockmodel.py @@ -20,22 +20,19 @@ import libvirt import lxml.etree as ET import os -import random import time from lxml import objectify from lxml.builder import E from wok.exception import NotFoundError, OperationFailed from wok.objectstore import ObjectStore -from wok.utils import add_task, get_next_clone_name, wok_log +from wok.utils import add_task, get_next_clone_name from wok.xmlutils.utils import xml_item_update -import config import imageinfo import osinfo from model import cpuinfo from model import vmifaces -from model.debugreports import DebugReportsModel from model.host import DeviceModel from model.libvirtstoragepool import IscsiPoolDef, NetfsPoolDef from model.libvirtstoragepool import StoragePoolDef @@ -75,10 +72,7 @@ class MockModel(Model): osinfo.defaults = dict(defaults) self._mock_devices = MockDevices() - self._mock_partitions = MockPartitions() self._mock_storagevolumes = MockStorageVolumes() - self._mock_swupdate = MockSoftwareUpdate() - self._mock_repositories = MockRepositories() cpuinfo.get_topo_capabilities = MockModel.get_topo_capabilities vmifaces.getDHCPLeases = MockModel.getDHCPLeases @@ -119,7 +113,6 @@ class MockModel(Model): 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 @@ -127,8 +120,6 @@ class MockModel(Model): 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) @@ -258,22 +249,6 @@ class MockModel(Model): return MockModel._libvirt_get_vol_path(pool, vol) - def _gen_debugreport_file(self, name): - return add_task('/plugins/kimchi/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')) @@ -288,12 +263,6 @@ class MockModel(Model): conn.storagePoolDefineXML(ET.tostring(root), 0) - def _mock_host_shutdown(self, *name): - wok_log.info("The host system will be shutted down") - - def _mock_host_reboot(self, *name): - wok_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)) @@ -341,12 +310,6 @@ class MockModel(Model): 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, _available_only=None): @@ -362,56 +325,6 @@ class MockModel(Model): 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('/plugins/kimchi/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_<integer>, 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, []) @@ -496,18 +409,6 @@ class MockStorageVolumes(object): 'isvalid': True}} -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 = { @@ -585,51 +486,6 @@ class MockDevices(object): '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 diff --git a/src/wok/plugins/kimchi/model/config.py b/src/wok/plugins/kimchi/model/config.py index b6cc4d9..d00bb29 100644 --- a/src/wok/plugins/kimchi/model/config.py +++ b/src/wok/plugins/kimchi/model/config.py @@ -28,10 +28,7 @@ from wok.utils import check_url_path, run_command, wok_log from ..config import find_qemu_binary from ..distroloader import DistroLoader -from ..repositories import Repositories from ..screenshot import VMScreenshot -from ..swupdate import SoftwareUpdate -from debugreports import DebugReportsModel from featuretests import FeatureTests, FEATURETEST_POOL_NAME from featuretests import FEATURETEST_VM_NAME @@ -114,28 +111,10 @@ class CapabilitiesModel(object): 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, diff --git a/src/wok/plugins/kimchi/model/host.py b/src/wok/plugins/kimchi/model/host.py index f32cf62..f211a6a 100644 --- a/src/wok/plugins/kimchi/model/host.py +++ b/src/wok/plugins/kimchi/model/host.py @@ -18,28 +18,17 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import libvirt -import os -import platform import psutil -import time -from cherrypy.process.plugins import BackgroundTask -from collections import defaultdict from lxml import objectify -from wok.basemodel import Singleton -from wok.exception import InvalidOperation, InvalidParameter -from wok.exception import NotFoundError, OperationFailed -from wok.utils import add_task, wok_log +from wok.exception import InvalidParameter +from wok.exception import NotFoundError from wok.xmlutils.utils import xpath_get_text from wok.model.tasks import TaskModel import hostdev -from wok.plugins.kimchi import disks -from wok.plugins.kimchi import netinfo -from wok.plugins.kimchi.repositories import Repositories -from wok.plugins.kimchi.swupdate import SoftwareUpdate from config import CapabilitiesModel -from vms import DOM_STATE_MAP, VMModel, VMsModel +from vms import VMModel, VMsModel HOST_STATS_INTERVAL = 1 @@ -50,60 +39,10 @@ class HostModel(object): 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 + self.host_info = {} def lookup(self, *name): - cpus = 0 + cpus = psutil.NUM_CPUS # psutil is unstable on how to get the number of # cpus, different versions call it differently @@ -128,184 +67,6 @@ class HostModel(object): self.host_info['memory'] = psutil.virtual_memory().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') - - wok_log.debug('Host is going to be updated.') - taskid = add_task('/plugins/kimchi/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") - - wok_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") - - wok_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 = None - if hasattr(psutil, 'net_io_counters'): - net_ios = psutil.net_io_counters(True) - elif hasattr(psutil, 'network_io_counters'): - 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): @@ -501,88 +262,3 @@ class DeviceModel(object): if ebus == ibus and edevice == idevice: return usb_info['name'] return unknown_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) diff --git a/src/wok/plugins/kimchi/root.py b/src/wok/plugins/kimchi/root.py index 1e2bfc7..2c8ac5b 100644 --- a/src/wok/plugins/kimchi/root.py +++ b/src/wok/plugins/kimchi/root.py @@ -58,7 +58,6 @@ class KimchiRoot(WokRoot): make_dirs = [ os.path.abspath(config.get_distros_store()), - os.path.abspath(config.get_debugreports_path()), os.path.abspath(config.get_screenshot_path()) ] for directory in make_dirs: diff --git a/src/wok/plugins/kimchi/tests/test_authorization.py b/src/wok/plugins/kimchi/tests/test_authorization.py index 87d68ab..fda86a3 100644 --- a/src/wok/plugins/kimchi/tests/test_authorization.py +++ b/src/wok/plugins/kimchi/tests/test_authorization.py @@ -77,12 +77,6 @@ class AuthorizationTests(unittest.TestCase): resp = self.request('/plugins/kimchi/host/shutdown', '{}', 'POST') self.assertEquals(403, resp.status) - # Non-root users can not get or debug reports - resp = self.request('/plugins/kimchi/debugreports', '{}', 'GET') - self.assertEquals(403, resp.status) - resp = self.request('/plugins/kimchi/debugreports', '{}', 'POST') - self.assertEquals(403, resp.status) - # Non-root users can not create or delete network (only get) resp = self.request('/plugins/kimchi/networks', '{}', 'GET') self.assertEquals(200, resp.status) diff --git a/src/wok/plugins/kimchi/tests/test_config.py.in b/src/wok/plugins/kimchi/tests/test_config.py.in index e4db15a..09d12aa 100644 --- a/src/wok/plugins/kimchi/tests/test_config.py.in +++ b/src/wok/plugins/kimchi/tests/test_config.py.in @@ -22,7 +22,6 @@ from cherrypy.lib.reprconf import Parser from wok.config import Paths, PluginPaths, WokConfig -from wok.plugins.kimchi.config import get_debugreports_path from wok.plugins.kimchi.config import get_screenshot_path from wok.plugins.kimchi.config import KimchiConfig, KimchiPaths @@ -253,13 +252,6 @@ class ConfigTests(unittest.TestCase): '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.wokauth.on': True, - 'tools.staticdir.content_types': {'xz': 'application/x-xz'} - }, '/help': { 'tools.staticdir.on': True, 'tools.staticdir.dir': '%s/ui/pages/help' % pluginPrefix, diff --git a/src/wok/plugins/kimchi/tests/test_host.py b/src/wok/plugins/kimchi/tests/test_host.py index f3da49b..86cf5d0 100644 --- a/src/wok/plugins/kimchi/tests/test_host.py +++ b/src/wok/plugins/kimchi/tests/test_host.py @@ -20,16 +20,13 @@ import json import os -import platform -import psutil import tempfile -import time import unittest from functools import partial from wok.plugins.kimchi.mockmodel import MockModel -from utils import get_free_port, patch_auth, request, run_server, wait_task +from utils import get_free_port, patch_auth, request, run_server test_server = None @@ -62,98 +59,6 @@ class HostTests(unittest.TestCase): def setUp(self): self.request = partial(request, host, ssl_port) - def test_hostinfo(self): - resp = self.request('/plugins/kimchi/host').read() - info = json.loads(resp) - keys = ['os_distro', 'os_version', 'os_codename', 'cpu_model', - 'memory', 'cpus'] - self.assertEquals(sorted(keys), sorted(info.keys())) - - distro, version, codename = platform.linux_distribution() - self.assertEquals(distro, info['os_distro']) - self.assertEquals(version, info['os_version']) - self.assertEquals(unicode(codename, "utf-8"), info['os_codename']) - self.assertEquals(psutil.TOTAL_PHYMEM, info['memory']) - - def test_hoststats(self): - time.sleep(1) - stats_keys = ['cpu_utilization', 'memory', 'disk_read_rate', - 'disk_write_rate', 'net_recv_rate', 'net_sent_rate'] - resp = self.request('/plugins/kimchi/host/stats').read() - stats = json.loads(resp) - self.assertEquals(sorted(stats_keys), sorted(stats.keys())) - - cpu_utilization = stats['cpu_utilization'] - self.assertIsInstance(cpu_utilization, float) - self.assertGreaterEqual(cpu_utilization, 0.0) - self.assertTrue(cpu_utilization <= 100.0) - - memory_stats = stats['memory'] - self.assertIn('total', memory_stats) - self.assertIn('free', memory_stats) - self.assertIn('cached', memory_stats) - self.assertIn('buffers', memory_stats) - self.assertIn('avail', memory_stats) - - resp = self.request('/plugins/kimchi/host/stats/history').read() - history = json.loads(resp) - self.assertEquals(sorted(stats_keys), sorted(history.keys())) - - def test_host_actions(self): - def _task_lookup(taskid): - return json.loads( - self.request('/plugins/kimchi/tasks/%s' % taskid).read() - ) - - resp = self.request('/plugins/kimchi/host/shutdown', '{}', 'POST') - self.assertEquals(200, resp.status) - resp = self.request('/plugins/kimchi/host/reboot', '{}', 'POST') - self.assertEquals(200, resp.status) - - # Test system update - resp = self.request('/plugins/kimchi/host/packagesupdate', None, 'GET') - pkgs = json.loads(resp.read()) - self.assertEquals(3, len(pkgs)) - - pkg_keys = ['package_name', 'repository', 'arch', 'version'] - for p in pkgs: - name = p['package_name'] - resp = self.request('/plugins/kimchi/host/packagesupdate/' + name, - None, 'GET') - info = json.loads(resp.read()) - self.assertEquals(sorted(pkg_keys), sorted(info.keys())) - - resp = self.request('/plugins/kimchi/host/swupdate', '{}', 'POST') - task = json.loads(resp.read()) - task_params = [u'id', u'message', u'status', u'target_uri'] - self.assertEquals(sorted(task_params), sorted(task.keys())) - - resp = self.request('/tasks/' + task[u'id'], None, - 'GET') - task_info = json.loads(resp.read()) - self.assertEquals(task_info['status'], 'running') - wait_task(_task_lookup, task_info['id']) - resp = self.request('/tasks/' + task[u'id'], None, - 'GET') - task_info = json.loads(resp.read()) - self.assertEquals(task_info['status'], 'finished') - self.assertIn(u'All packages updated', task_info['message']) - pkgs = model.packagesupdate_get_list() - self.assertEquals(0, len(pkgs)) - - def test_host_partitions(self): - resp = self.request('/plugins/kimchi/host/partitions') - self.assertEquals(200, resp.status) - partitions = json.loads(resp.read()) - - keys = ['name', 'path', 'type', 'fstype', 'size', 'mountpoint', - 'available'] - for item in partitions: - resp = self.request('/plugins/kimchi/host/partitions/%s' % - item['name']) - info = json.loads(resp.read()) - self.assertEquals(sorted(info.keys()), sorted(keys)) - def test_host_devices(self): def asset_devices_type(devices, dev_type): for dev in devices: diff --git a/src/wok/plugins/kimchi/tests/test_model.py b/src/wok/plugins/kimchi/tests/test_model.py index 55117cf..c772dc5 100644 --- a/src/wok/plugins/kimchi/tests/test_model.py +++ b/src/wok/plugins/kimchi/tests/test_model.py @@ -25,7 +25,6 @@ import re import shutil import time import unittest -import uuid import wok.objectstore from wok.basemodel import Singleton @@ -1065,54 +1064,6 @@ class ModelTests(unittest.TestCase): 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) @@ -1151,194 +1102,6 @@ class ModelTests(unittest.TestCase): 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): @@ -1359,4 +1122,4 @@ class BaseModelTests(unittest.TestCase): def test_root_model(self): t = BaseModelTests.TestModel() t.foos_create({'item1': 10}) - self.assertEquals(t.foos_get_list(), ['item1']) + self.assertEquals(t.foos_get_list(), ['item1']) \ No newline at end of file diff --git a/src/wok/plugins/kimchi/tests/test_rest.py b/src/wok/plugins/kimchi/tests/test_rest.py index 8cf4bd3..8f12920 100644 --- a/src/wok/plugins/kimchi/tests/test_rest.py +++ b/src/wok/plugins/kimchi/tests/test_rest.py @@ -1266,60 +1266,6 @@ class RestTests(unittest.TestCase): # Distro not found error self.assertIn('KCHDISTRO0001E', distro.get('reason')) - def test_debugreports(self): - resp = request(host, ssl_port, '/plugins/kimchi/debugreports') - self.assertEquals(200, resp.status) - - def _report_delete(self, name): - request(host, ssl_port, '/plugins/kimchi/debugreports/%s' % name, '{}', - 'DELETE') - - def test_create_debugreport(self): - req = json.dumps({'name': 'report1'}) - with RollbackContext() as rollback: - resp = request(host, ssl_port, '/plugins/kimchi/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, - '/plugins/kimchi/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, - '/plugins/kimchi/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, '/plugins/kimchi/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, - '/plugins/kimchi/debugreports/report1') - debugreport = json.loads(resp.read()) - self.assertEquals("report1", debugreport['name']) - self.assertEquals(200, resp.status) - resp = request(host, ssl_port, - '/plugins/kimchi/debugreports/report1/content') - self.assertEquals(200, resp.status) - resp = request(host, ssl_port, - '/plugins/kimchi/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'): diff --git a/src/wok/plugins/kimchi/ui/config/tab-ext.xml b/src/wok/plugins/kimchi/ui/config/tab-ext.xml index ee88c88..48ec9ec 100644 --- a/src/wok/plugins/kimchi/ui/config/tab-ext.xml +++ b/src/wok/plugins/kimchi/ui/config/tab-ext.xml @@ -2,13 +2,6 @@ <tabs-ext> <tab> <access role="admin" mode="admin"/> - <access role="user" mode="none"/> - - <title>Host</title> - <path>plugins/kimchi/host.html</path> - </tab> - <tab> - <access role="admin" mode="admin"/> <access role="user" mode="byInstance"/> <title>Guests</title> -- 2.1.0

From: chandrureddy <chandra@linux.vnet.ibm.com> --- src/wok/plugins/gingerbase/API.json | 175 ++++++++ src/wok/plugins/gingerbase/INSTALL | 369 ++++++++++++++++ src/wok/plugins/gingerbase/Makefile.am | 156 +++++++ src/wok/plugins/gingerbase/VERSION | 1 + src/wok/plugins/gingerbase/__init__.py | 22 + src/wok/plugins/gingerbase/autogen.sh | 21 + src/wok/plugins/gingerbase/config.py.in | 60 +++ src/wok/plugins/gingerbase/config.rpath | 672 +++++++++++++++++++++++++++++ src/wok/plugins/gingerbase/configure.ac | 104 +++++ src/wok/plugins/gingerbase/gingerbase.conf | 31 ++ src/wok/plugins/gingerbase/gingerbase.py | 62 +++ src/wok/plugins/gingerbase/lscpu.py | 126 ++++++ src/wok/plugins/gingerbase/mockmodel.py | 297 +++++++++++++ 13 files changed, 2096 insertions(+) create mode 100644 src/wok/plugins/gingerbase/API.json create mode 100644 src/wok/plugins/gingerbase/INSTALL create mode 100644 src/wok/plugins/gingerbase/Makefile.am create mode 100644 src/wok/plugins/gingerbase/VERSION create mode 100644 src/wok/plugins/gingerbase/__init__.py create mode 100755 src/wok/plugins/gingerbase/autogen.sh create mode 100644 src/wok/plugins/gingerbase/config.py.in create mode 100644 src/wok/plugins/gingerbase/config.rpath create mode 100644 src/wok/plugins/gingerbase/configure.ac create mode 100644 src/wok/plugins/gingerbase/gingerbase.conf create mode 100644 src/wok/plugins/gingerbase/gingerbase.py create mode 100644 src/wok/plugins/gingerbase/lscpu.py create mode 100644 src/wok/plugins/gingerbase/mockmodel.py diff --git a/src/wok/plugins/gingerbase/API.json b/src/wok/plugins/gingerbase/API.json new file mode 100644 index 0000000..7b77eac --- /dev/null +++ b/src/wok/plugins/gingerbase/API.json @@ -0,0 +1,175 @@ +{ + "$schema": "http://json-schema.org/draft-03/schema#", + "title": "Ginger Base API", + "description": "Json schema for Gigner Base API", + "type": "object", + "gingerbasetype": { + "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": "GGBHOST0005E" + }, + "cores": { + "type": "integer", + "required": true, + "minimum": 1, + "error": "GGBHOST0005E" + }, + "threads": { + "type": "integer", + "required": true, + "minimum": 1, + "error": "GGBHOST0005E" + } + } + } + } + } + }, + "properties": { + "debugreports_create": { + "type": "object", + "error": "GGBDR0006E", + "properties": { + "name": { + "description": "The name for the debug report file.", + "type": "string", + "pattern": "^[_A-Za-z0-9-]*$", + "error": "GGBDR0007E" + } + } + }, + "debugreport_update": { + "type": "object", + "properties": { + "name": { + "description": "New name of debug report", + "type": "string", + "pattern": "^[_A-Za-z0-9-]*$", + "error": "GGBDR0007E" + } + }, + "additionalProperties": false + }, + "repositories_create": { + "type": "object", + "properties": { + "repo_id": { + "description": "Repository ID used for YUM repository.", + "type": "string", + "error": "GGBREPOS0001E" + }, + "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": "GGBREPOS0002E" + }, + "config": { + "description": "Dictionary containing repository configuration", + "type": "object", + "error": "GGBREPOS0003E", + "properties": { + "dist": { + "description": "Distribution to DEB repository", + "type": "string", + "error": "GGBREPOS0004E" + }, + "comps": { + "description": "List of components to DEB repository", + "type": "array", + "error": "GGBREPOS0005E", + "uniqueItems": true, + "items": { + "description": "Component name", + "type": "string", + "error": "GGBREPOS0006E" + } + }, + "repo_name": { + "description": "YUM repository name", + "type": "string", + "error": "GGBREPOS0023E" + }, + "mirrorlist": { + "description": "URL to a file containing a list of baseurls", + "type": "string", + "error": "GGBREPOS0007E" + }, + "metalink": { + "description": "URL to a metalink file for the repomd.xml", + "type": "string", + "error": "GGBREPOS0029E" + } + } + } + }, + "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": "GGBREPOS0002E" + }, + "config": { + "description": "Dictionary containing repository configuration", + "type": "object", + "error": "GGBREPOS0003E", + "properties": { + "dist": { + "description": "Distribution to DEB repository", + "type": "string", + "error": "GGBREPOS0004E" + }, + "comps": { + "description": "List of components to DEB repository", + "type": "array", + "error": "GGBREPOS0005E", + "uniqueItems": true, + "items": { + "description": "Component name", + "type": "string", + "error": "GGBREPOS0006E" + } + }, + "repo_name": { + "description": "Human-readable string describing the YUM repository.", + "type": "string", + "error": "GGBREPOS0008E" + }, + "mirrorlist": { + "description": "URL to a file containing a list of baseurls for YUM repository", + "type": "string", + "error": "GGBREPOS0007E" + }, + "gpgcheck": { + "description": "Indicates if a GPG signature check on the packages gotten from repository should be performed.", + "type": "boolean", + "error": "GGBREPOS0009E" + }, + "gpgkey": { + "description": "URL pointing to the ASCII-armored GPG key file for the repository.", + "type": "string", + "error": "GGBREPOS0010E" + } + } + } + }, + "additionalProperties": false, + "error": "GGBAPI0001E" + + } + } +} diff --git a/src/wok/plugins/gingerbase/INSTALL b/src/wok/plugins/gingerbase/INSTALL new file mode 100644 index 0000000..63bf076 --- /dev/null +++ b/src/wok/plugins/gingerbase/INSTALL @@ -0,0 +1,369 @@ +Installation 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 `<wchar.h>' 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. diff --git a/src/wok/plugins/gingerbase/Makefile.am b/src/wok/plugins/gingerbase/Makefile.am new file mode 100644 index 0000000..88f2b40 --- /dev/null +++ b/src/wok/plugins/gingerbase/Makefile.am @@ -0,0 +1,156 @@ +# +# Ginger Base +# +# Copyright IBM Corp, 2015 +# +# Code derived from Project Kimchi +# 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 = contrib control docs model po tests ui + +gingerbase_PYTHON = $(filter-out config.py, $(wildcard *.py)) + +nodist_gingerbase_PYTHON = config.py + +wokdir = $(pythondir)/wok +gingerbasedir = $(pythondir)/wok/plugins/gingerbase + +confdir = $(sysconfdir)/wok/plugins.d +dist_conf_DATA = gingerbase.conf + +AUTOMAKE_OPTIONS = foreign + +ACLOCAL_AMFLAGS = --install -I m4 + +EXTRA_DIST = \ + config.rpath \ + API.json \ + autogen.sh \ + COPYING.ASL2 \ + COPYING.LGPL \ + CONTRIBUTE.md \ + VERSION \ + build-aux/pkg-version \ + config.py.in \ + $(NULL) + + +PEP8_BLACKLIST = *config.py,*i18n.py,*tests/test_config.py + +I18N_FILES = ./i18n.py \ + $(NULL) + +check-local: + contrib/check_i18n.py $(I18N_FILES) + find . -path './.git' -prune -type f -o \ + -name '*.py' -o -name '*.py.in' | xargs $(PYFLAKES) | \ + 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/gingerbase.mo ; \ + done < po/LINGUAS + +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,[@]wokdir[@],$(wokdir),g' \ + -e 's,[@]gingerbasedir[@],$(gingerbasedir),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 + + +# +# Packaging helpers +# + +install-deb: install + cp -R $(top_srcdir)/contrib/DEBIAN $(DESTDIR)/ + mkdir -p $(DESTDIR)/$(localstatedir)/lib/wok/ + touch $(DESTDIR)/$(localstatedir)/lib/wok/objectstore_gingerbase + mkdir -p $(DESTDIR)/$(localstatedir)/lib/wok/plugins/gingerbase/debugreports + + +deb: contrib/make-deb.sh + $(top_srcdir)/contrib/make-deb.sh + +gingerbase.spec: contrib/gingerbase.spec.fedora contrib/gingerbase.spec.suse + @if test -e /etc/redhat-release; then \ + ln -sf contrib/gingerbase.spec.fedora $@ ; \ + elif test -e /etc/SuSE-release; then \ + ln -sf contrib/gingerbase.spec.suse $@ ; \ + else \ + echo "Unable to select a spec file for RPM build" ; \ + /bin/false ; \ + fi + +rpm: dist gingerbase.spec + $(MKDIR_P) rpm/BUILD rpm/RPMS rpm/SOURCES rpm/SPECS rpm/SRPMS + cp $(top_srcdir)/gingerbase.spec rpm/SPECS/gingerbase.spec + cp $(DIST_ARCHIVES) rpm/SOURCES + rpmbuild -ba --define "_topdir `pwd`/rpm" rpm/SPECS/gingerbase.spec + +fedora-rpm: contrib/gingerbase.spec.fedora + ln -sf contrib/gingerbase.spec.fedora gingerbase.spec + $(MAKE) rpm + +suse-rpm: contrib/gingerbase.spec.suse + ln -sf contrib/gingerbase.spec.suse gingerbase.spec + $(MAKE) rpm + +ChangeLog: + @if test -d .git; then \ + $(top_srcdir)/build-aux/genChangelog --release > $@; \ + fi + +install-data-local: + $(MKDIR_P) $(DESTDIR)/$(localstatedir)/lib/wok/ + touch $(DESTDIR)/$(localstatedir)/lib/wok/objectstore_gingerbase + $(MKDIR_P) $(DESTDIR)$(gingerbasedir) + $(INSTALL_DATA) API.json $(DESTDIR)$(gingerbasedir)/API.json + mkdir -p $(DESTDIR)/$(localstatedir)/lib/wok/plugins/gingerbase/debugreports + +uninstall-local: + $(RM) $(DESTDIR)$(gingerbasedir)/API.json + $(RM) -rf $(DESTDIR)/$(localstatedir)/lib/wok/plugins/gingerbase + +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 + +BUILT_SOURCES = config.py +CLEANFILES = config.py gingerbase.spec `find "$(top_srcdir)" -type f -name "*.pyc" -print` diff --git a/src/wok/plugins/gingerbase/VERSION b/src/wok/plugins/gingerbase/VERSION new file mode 100644 index 0000000..bc80560 --- /dev/null +++ b/src/wok/plugins/gingerbase/VERSION @@ -0,0 +1 @@ +1.5.0 diff --git a/src/wok/plugins/gingerbase/__init__.py b/src/wok/plugins/gingerbase/__init__.py new file mode 100644 index 0000000..13f2622 --- /dev/null +++ b/src/wok/plugins/gingerbase/__init__.py @@ -0,0 +1,22 @@ +# +# Project Ginger Base +# +# Copyright IBM, Corp. 2015 +# +# Code derived from Project Kimchi +# 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 gingerbase import GingerBase +__all__ = [GingerBase] diff --git a/src/wok/plugins/gingerbase/autogen.sh b/src/wok/plugins/gingerbase/autogen.sh new file mode 100755 index 0000000..0f22dba --- /dev/null +++ b/src/wok/plugins/gingerbase/autogen.sh @@ -0,0 +1,21 @@ +#!/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 diff --git a/src/wok/plugins/gingerbase/config.py.in b/src/wok/plugins/gingerbase/config.py.in new file mode 100644 index 0000000..e27e6bd --- /dev/null +++ b/src/wok/plugins/gingerbase/config.py.in @@ -0,0 +1,60 @@ +# +# Project Ginger Base +# +# Copyright IBM, Corp. 2015 +# +# Code derived from Project Kimchi +# 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 threading + +from wok.config import CACHEEXPIRES, PluginConfig, PluginPaths + +gingerBaseLock = threading.Lock() + + +def get_debugreports_path(): + return os.path.join(PluginPaths('gingerbase').state_dir, 'debugreports') + + +class GingerBasePaths(PluginPaths): + + def __init__(self): + super(GingerBasePaths, self).__init__('gingerbase') + + +gingerBasePaths = GingerBasePaths() + + +class GingerBaseConfig(PluginConfig): + def __init__(self): + super(GingerBaseConfig, self).__init__('gingerbase') + + custom_config = {} + for dirname in ('css', 'js', 'images'): + custom_config['/' + dirname] = { + 'tools.staticdir.on': True, + 'tools.staticdir.dir': os.path.join(gingerBasePaths.ui_dir, + dirname), + 'tools.wokauth.on': False, + 'tools.nocache.on': False} + if dirname != 'images': + custom_config['/' + dirname].update({ + 'tools.expires.on': True, + 'tools.expires.secs': CACHEEXPIRES}) + + self.update(custom_config) diff --git a/src/wok/plugins/gingerbase/config.rpath b/src/wok/plugins/gingerbase/config.rpath new file mode 100644 index 0000000..17298f2 --- /dev/null +++ b/src/wok/plugins/gingerbase/config.rpath @@ -0,0 +1,672 @@ +#! /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 <gord@gnu.ai.mit.edu>, 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 <kc5tja@dolphin.openprojects.net> 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=/' <<EOF + +# How to pass a linker flag through the compiler. +wl="$escaped_wl" + +# Static library suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally "so"). +shlibext="$shlibext" + +# Format of library name prefix. +libname_spec="$escaped_libname_spec" + +# Library names that the linker finds when passed -lNAME. +library_names_spec="$escaped_library_names_spec" + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec="$escaped_hardcode_libdir_flag_spec" + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator="$hardcode_libdir_separator" + +# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the +# resulting binary. +hardcode_direct="$hardcode_direct" + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L="$hardcode_minus_L" + +EOF diff --git a/src/wok/plugins/gingerbase/configure.ac b/src/wok/plugins/gingerbase/configure.ac new file mode 100644 index 0000000..09b4fad --- /dev/null +++ b/src/wok/plugins/gingerbase/configure.ac @@ -0,0 +1,104 @@ +# +# Ginger Base +# +# Copyright IBM Corp, 2015 +# +# Code derived from Project Kimchi +# 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([gingerbase], [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 + +AC_CONFIG_FILES([ + po/Makefile.in + po/gen-pot + Makefile + docs/Makefile + control/Makefile + model/Makefile + ui/Makefile + ui/config/Makefile + ui/css/Makefile + ui/images/Makefile + ui/images/theme-default/Makefile + ui/js/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 + contrib/Makefile + contrib/DEBIAN/Makefile + contrib/DEBIAN/control + contrib/gingerbase.spec.fedora + contrib/gingerbase.spec.suse + tests/Makefile +],[ + chmod +x po/gen-pot +]) + +AC_OUTPUT diff --git a/src/wok/plugins/gingerbase/gingerbase.conf b/src/wok/plugins/gingerbase/gingerbase.conf new file mode 100644 index 0000000..a7e6e08 --- /dev/null +++ b/src/wok/plugins/gingerbase/gingerbase.conf @@ -0,0 +1,31 @@ +[wok] +enable = True +plugin_class = "GingerBase" +uri = "/plugins/gingerbase" +extra_auth_api_class = "control.sub_nodes" + +[/] +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 = 'wok' +tools.sessions.secure = True +tools.sessions.httponly = True +tools.sessions.locking = 'explicit' +tools.sessions.storage_type = 'ram' +tools.sessions.timeout = 10 +tools.wokauth.on = True + +[/data/debugreports] +tools.staticdir.on = True +tools.staticdir.dir = wok.config.PluginPaths('gingerbase').state_dir + '/debugreports' +tools.nocache.on = False +tools.wokauth.on = True +tools.staticdir.content_types = {'xz': 'application/x-xz'} + +[/help] +tools.staticdir.on = True +tools.staticdir.dir = wok.config.PluginPaths('gingerbase').ui_dir + '/pages/help' +tools.nocache.on = True \ No newline at end of file diff --git a/src/wok/plugins/gingerbase/gingerbase.py b/src/wok/plugins/gingerbase/gingerbase.py new file mode 100644 index 0000000..aec1b15 --- /dev/null +++ b/src/wok/plugins/gingerbase/gingerbase.py @@ -0,0 +1,62 @@ +# +# Project Ginger Base +# +# Copyright IBM, Corp. 2015 +# +# Code derived from Project Kimchi +# 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 wok.i18n import messages +from wok.root import WokRoot + +import config +import mockmodel +from control import sub_nodes +from model import model as gingerBaseModel + + +class GingerBase(WokRoot): + def __init__(self, wok_options): + if hasattr(wok_options, "model"): + self.model = wok_options.model + elif wok_options.test: + self.model = mockmodel.MockModel() + else: + self.model = gingerBaseModel.Model() + + dev_env = wok_options.environment != 'production' + super(GingerBase, self).__init__(self.model, dev_env) + + for ident, node in sub_nodes.items(): + setattr(self, ident, node(self.model)) + + self.api_schema = json.load(open(os.path.join(os.path.dirname( + os.path.abspath(__file__)), 'API.json'))) + self.paths = config.gingerBasePaths + self.domain = 'gingerbase' + self.messages = messages + + make_dirs = [ + os.path.abspath(config.get_debugreports_path()), + ] + for directory in make_dirs: + if not os.path.isdir(directory): + os.makedirs(directory) + + def get_custom_conf(self): + return config.GingerBaseConfig() diff --git a/src/wok/plugins/gingerbase/lscpu.py b/src/wok/plugins/gingerbase/lscpu.py new file mode 100644 index 0000000..0fc1e72 --- /dev/null +++ b/src/wok/plugins/gingerbase/lscpu.py @@ -0,0 +1,126 @@ +# +# Project Ginger Base +# +# 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 logging + +from wok.utils import run_command +from wok.exception import NotFoundError + + +class LsCpu(object): + """ + Get CPU information about a CPU hyper threading/architecture on x86 + """ + def log_error(e): + """ + param e: error details to be logged + """ + log = logging.getLogger('Util') + log.warning('Exception in fetching the CPU architecture details: %s', + e) + + def __init__(self): + self.lsCpuInfo = {} + try: + # lscpu - display information about the CPU architecture + out, error, rc = run_command(['lscpu']) + # Output of lscpu on x86 is expected to be: + # Architecture: x86_64 + # CPU op-mode(s): 32-bit, 64-bit + # Byte Order: Little Endian + # CPU(s): 4 + # On-line CPU(s) list: 0-3 + # Thread(s) per core: 2 + # Core(s) per socket: 2 + # Socket(s): 1 + # NUMA node(s): 1 + # Vendor ID: GenuineIntel + # CPU family: 6 + # Model: 42 + # Model name: Intel(R) Core(TM) i5-2540M CPU @ 2.60GHz + # Stepping: 7 + # CPU MHz: 976.421 + # CPU max MHz: 3300.0000 + # CPU min MHz: 800.0000 + # BogoMIPS: 5182.99 + # Virtualization: VT-x + # L1d cache: 32K + # L1i cache: 32K + # L2 cache: 256K + # L3 cache: 3072K + # NUMA node0 CPU(s): 0-3 + + if not rc and (not out.isspace()): + lscpuout = out.split('\n') + if lscpuout and len(lscpuout) > 0: + for line in lscpuout: + if ":" in line and (len(line.split(':')) == 2): + self.lsCpuInfo[line.split(':')[0].strip()] = \ + line.split(':')[1].strip() + else: + continue + except Exception, e: + self.log_error(e) + raise NotFoundError("GGBCPUINF0004E") + + def get_sockets(self): + """ + param self: object of the class self + return: Socket(s) (information about the CPU architecture) + """ + try: + sockets = "Socket(s)" + if len(self.lsCpuInfo) > 0 and sockets in self.lsCpuInfo.keys(): + return int(self.lsCpuInfo[sockets]) + else: + raise NotFoundError("GGBCPUINF0005E") + except IndexError, e: + self.log_error(e) + raise NotFoundError("GGBCPUINF0005E") + + def get_cores_per_socket(self): + """ + param self: object of the class self + return: Core(s) per socket (information about the CPU architecture) + """ + try: + cores_per_socket = "Core(s) per socket" + if len(self.lsCpuInfo) > 0 and cores_per_socket \ + in self.lsCpuInfo.keys(): + return int(self.lsCpuInfo[cores_per_socket]) + else: + raise NotFoundError("GGBCPUINF0006E") + except IndexError, e: + self.log_error(e) + raise NotFoundError("GGBCPUINF0006E") + + def get_threads_per_core(self): + """ + param self: object of the class self + return: Thread(s) per core (information about the CPU architecture) + """ + try: + threads_per_core = "Thread(s) per core" + if len(self.lsCpuInfo) > 0 and threads_per_core \ + in self.lsCpuInfo.keys(): + return int(self.lsCpuInfo[threads_per_core]) + else: + raise NotFoundError("GGBCPUINF0007E") + except IndexError, e: + self.log_error(e) + raise NotFoundError("GGBCPUINF0007E") diff --git a/src/wok/plugins/gingerbase/mockmodel.py b/src/wok/plugins/gingerbase/mockmodel.py new file mode 100644 index 0000000..6af5628 --- /dev/null +++ b/src/wok/plugins/gingerbase/mockmodel.py @@ -0,0 +1,297 @@ +# +# Project Ginger Base +# +# Copyright IBM, Corp. 2015 +# +# Code derived from Project Kimchi +# 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 random +import time + +from wok.objectstore import ObjectStore +from wok.utils import add_task, wok_log + +import config +from model import cpuinfo +from model.debugreports import DebugReportsModel +from model.model import Model + +fake_user = {'root': 'letmein!'} +mockmodel_defaults = {'domain': 'test', 'arch': 'i686'} + + +class MockModel(Model): + + def __init__(self, objstore_loc=None): + # Override osinfo.defaults to ajust the values according to + # test:///default driver + + self._mock_devices = MockDevices() + self._mock_partitions = MockPartitions() + self._mock_swupdate = MockSoftwareUpdate() + self._mock_repositories = MockRepositories() + + cpuinfo.get_topo_capabilities = \ + MockModel.get_topo_capabilities + + super(MockModel, self).__init__(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) + + DebugReportsModel._gen_debugreport_file = self._gen_debugreport_file + + def reset(self): + self._mock_swupdate = MockSoftwareUpdate() + self._mock_repositories = MockRepositories() + + if hasattr(self, 'objstore'): + self.objstore = ObjectStore(self.objstore_loc) + + @staticmethod + def get_topo_capabilities(conn): + # The libvirt test driver doesn't return topology. + xml = "<topology sockets='1' cores='2' threads='2'/>" + return ET.fromstring(xml) + + def _gen_debugreport_file(self, name): + return add_task('/plugins/gingerbase/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 _mock_host_shutdown(self, *name): + wok_log.info("The host system will be shutted down") + + def _mock_host_reboot(self, *name): + wok_log.info("The host system will be rebooted") + + 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_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('/plugins/gingerbase/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 gingerbase_repo_<integer>, 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 = "gingerbase_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 + + +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 = {"gingerbase_repo_1392167832": + {"repo_id": "gingerbase_repo_1392167832", + "enabled": True, + "baseurl": "http://www.fedora.org", + "config": {"repo_name": "gingerbase_repo_1392167832", + "gpgkey": [], + "gpgcheck": True, + "mirrorlist": ""}}} -- 2.1.0

diff --git a/src/wok/plugins/gingerbase/Makefile.am b/src/wok/plugins/gingerbase/Makefile.am new file mode 100644 index 0000000..88f2b40 --- /dev/null +++ b/src/wok/plugins/gingerbase/Makefile.am @@ -0,0 +1,156 @@ +# +# Ginger Base +# +# Copyright IBM Corp, 2015 +# +# Code derived from Project Kimchi
This is a new file, so not derived from Kimchi. We need to add it for the files moved from Kimchi. Also when adding this statement, please, add a blank line after it. Example: # # Ginger Base # # Copyright IBM Corp, 2015 # # Code derived from Project Kimchi # # This library ...
+# 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 +

On 15/10/2015 14:03, Aline Manera wrote:
diff --git a/src/wok/plugins/gingerbase/Makefile.am b/src/wok/plugins/gingerbase/Makefile.am new file mode 100644 index 0000000..88f2b40 --- /dev/null +++ b/src/wok/plugins/gingerbase/Makefile.am @@ -0,0 +1,156 @@ +# +# Ginger Base +# +# Copyright IBM Corp, 2015 +# +# Code derived from Project Kimchi
This is a new file, so not derived from Kimchi. We need to add it for the files moved from Kimchi.
The same comment applies to all new files added for gingerbase.
Also when adding this statement, please, add a blank line after it. Example:
# # Ginger Base # # Copyright IBM Corp, 2015 # # Code derived from Project Kimchi # # This library ...
+# 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-devel mailing list Kimchi-devel@ovirt.org http://lists.ovirt.org/mailman/listinfo/kimchi-devel

Take care On 10/15/2015 10:33 PM, Aline Manera wrote:
diff --git a/src/wok/plugins/gingerbase/Makefile.am b/src/wok/plugins/gingerbase/Makefile.am new file mode 100644 index 0000000..88f2b40 --- /dev/null +++ b/src/wok/plugins/gingerbase/Makefile.am @@ -0,0 +1,156 @@ +# +# Ginger Base +# +# Copyright IBM Corp, 2015 +# +# Code derived from Project Kimchi
This is a new file, so not derived from Kimchi. We need to add it for the files moved from Kimchi.
Also when adding this statement, please, add a blank line after it. Example:
# # Ginger Base # # Copyright IBM Corp, 2015 # # Code derived from Project Kimchi # # This library ...
+# 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 +

Taken care :-) On 10/16/2015 08:20 PM, Chandra Shehkhar Reddy Potula wrote:
Take care
On 10/15/2015 10:33 PM, Aline Manera wrote:
diff --git a/src/wok/plugins/gingerbase/Makefile.am b/src/wok/plugins/gingerbase/Makefile.am new file mode 100644 index 0000000..88f2b40 --- /dev/null +++ b/src/wok/plugins/gingerbase/Makefile.am @@ -0,0 +1,156 @@ +# +# Ginger Base +# +# Copyright IBM Corp, 2015 +# +# Code derived from Project Kimchi
This is a new file, so not derived from Kimchi. We need to add it for the files moved from Kimchi.
Also when adding this statement, please, add a blank line after it. Example:
# # Ginger Base # # Copyright IBM Corp, 2015 # # Code derived from Project Kimchi # # This library ...
+# 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-devel mailing list Kimchi-devel@ovirt.org http://lists.ovirt.org/mailman/listinfo/kimchi-devel

From: chandrureddy <chandra@linux.vnet.ibm.com> --- src/wok/plugins/gingerbase/disks.py | 197 +++++++++++ src/wok/plugins/gingerbase/i18n.py | 95 +++++ src/wok/plugins/gingerbase/repositories.py | 535 +++++++++++++++++++++++++++++ src/wok/plugins/gingerbase/swupdate.py | 277 +++++++++++++++ src/wok/plugins/gingerbase/yumparser.py | 354 +++++++++++++++++++ src/wok/plugins/kimchi/disks.py | 196 ----------- src/wok/plugins/kimchi/repositories.py | 533 ---------------------------- src/wok/plugins/kimchi/swupdate.py | 274 --------------- src/wok/plugins/kimchi/yumparser.py | 353 ------------------- 9 files changed, 1458 insertions(+), 1356 deletions(-) create mode 100644 src/wok/plugins/gingerbase/disks.py create mode 100644 src/wok/plugins/gingerbase/i18n.py create mode 100644 src/wok/plugins/gingerbase/repositories.py create mode 100644 src/wok/plugins/gingerbase/swupdate.py create mode 100644 src/wok/plugins/gingerbase/yumparser.py delete mode 100644 src/wok/plugins/kimchi/disks.py delete mode 100644 src/wok/plugins/kimchi/repositories.py delete mode 100644 src/wok/plugins/kimchi/swupdate.py delete mode 100644 src/wok/plugins/kimchi/yumparser.py diff --git a/src/wok/plugins/gingerbase/disks.py b/src/wok/plugins/gingerbase/disks.py new file mode 100644 index 0000000..e8e5f7c --- /dev/null +++ b/src/wok/plugins/gingerbase/disks.py @@ -0,0 +1,197 @@ +# +# Project Ginger Base +# +# Copyright IBM, Corp. 2013-2015 +# +# Code derived from Project Kimchi +# 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 wok.exception import OperationFailed +from wok.utils import wok_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("GGBDISKS0001E", {'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("GGBDISKS0002E", {'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 + wok_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: + wok_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: + wok_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 diff --git a/src/wok/plugins/gingerbase/i18n.py b/src/wok/plugins/gingerbase/i18n.py new file mode 100644 index 0000000..69285eb --- /dev/null +++ b/src/wok/plugins/gingerbase/i18n.py @@ -0,0 +1,95 @@ +# +# Project Ginger Base +# +# Copyright IBM, Corp. 2015 +# +# Code derived from Project Kimchi +# 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 = { + "GGBAPI0001E": _("Unknown parameter %(value)s"), + + "GGBDISKS0001E": _("Error while getting block devices. Details: %(err)s"), + "GGBDISKS0002E": _("Error while getting block device information for %(device)s."), + + "GGBDR0001E": _("Debug report %(name)s does not exist"), + "GGBDR0002E": _("Debug report tool not found in system"), + "GGBDR0003E": _("Unable to create debug report %(name)s. Details: %(err)s."), + "GGBDR0004E": _("Can not find any debug report with the given name %(name)s"), + "GGBDR0005E": _("Unable to generate debug report %(name)s. Details: %(err)s"), + "GGBDR0006E": _("You should give a name for the debug report file."), + "GGBDR0007E": _("Debug report name must be a string. Only letters, digits, underscore ('_') and " + "hyphen ('-') are allowed."), + "GGBDR0008E": _("The debug report with specified name \"%(name)s\" already exists. Please use another one."), + + "GGBPART0001E": _("Partition %(name)s does not exist in the host"), + + "GGBHOST0001E": _("Unable to shutdown host machine as there are running virtual machines"), + "GGBHOST0002E": _("Unable to reboot host machine as there are running virtual machines"), + "GGBHOST0005E": _("When specifying CPU topology, each element must be an integer greater than zero."), + + "GGBPKGUPD0001E": _("No packages marked for update"), + "GGBPKGUPD0002E": _("Package %(name)s is not marked to be updated."), + "GGBPKGUPD0003E": _("Error while getting packages marked to be updated. Details: %(err)s"), + "GGBPKGUPD0004E": _("There is no compatible package manager for this system."), + + + "GGBREPOS0001E": _("YUM Repository ID must be one word only string."), + "GGBREPOS0002E": _("Repository URL must be an http://, ftp:// or file:// URL."), + "GGBREPOS0003E": _("Repository configuration is a dictionary with specific values according to repository type."), + "GGBREPOS0004E": _("Distribution to DEB repository must be a string"), + "GGBREPOS0005E": _("Components to DEB repository must be listed in a array"), + "GGBREPOS0006E": _("Components to DEB repository must be a string"), + "GGBREPOS0007E": _("Mirror list to repository must be a string"), + "GGBREPOS0008E": _("YUM Repository name must be string."), + "GGBREPOS0009E": _("GPG check must be a boolean value."), + "GGBREPOS0010E": _("GPG key must be a URL pointing to the ASCII-armored file."), + "GGBREPOS0011E": _("Could not update repository %(repo_id)s."), + "GGBREPOS0012E": _("Repository %(repo_id)s does not exist."), + "GGBREPOS0013E": _("Specify repository base URL, mirror list or metalink in order to create or " + "update a YUM repository."), + "GGBREPOS0014E": _("Repository management tool was not recognized for your system."), + "GGBREPOS0015E": _("Repository %(repo_id)s is already enabled."), + "GGBREPOS0016E": _("Repository %(repo_id)s is already disabled."), + "GGBREPOS0017E": _("Could not remove repository %(repo_id)s."), + "GGBREPOS0018E": _("Could not write repository configuration file %(repo_file)s"), + "GGBREPOS0019E": _("Specify repository distribution in order to create a DEB repository."), + "GGBREPOS0020E": _("Could not enable repository %(repo_id)s."), + "GGBREPOS0021E": _("Could not disable repository %(repo_id)s."), + "GGBREPOS0022E": _("YUM Repository ID already exists"), + "GGBREPOS0023E": _("YUM Repository name must be a string"), + "GGBREPOS0024E": _("Unable to list repositories. Details: '%(err)s'"), + "GGBREPOS0025E": _("Unable to retrieve repository information. Details: '%(err)s'"), + "GGBREPOS0026E": _("Unable to add repository. Details: '%(err)s'"), + "GGBREPOS0027E": _("Unable to remove repository. Details: '%(err)s'"), + "GGBREPOS0028E": _("Configuration items: '%(items)s' are not supported by repository manager"), + "GGBREPOS0029E": _("Repository metalink must be an http://, ftp:// or file:// URL."), + "GGBREPOS0030E": _("Cannot specify mirrorlist and metalink at the same time."), + + + "GGBCPUINF0001E": _("The number of vCPUs is too large for this system."), + "GGBCPUINF0002E": _("Invalid vCPU/topology combination."), + "GGBCPUINF0003E": _("This host (or current configuration) does not allow CPU topology."), + "GGBCPUINF0004E": _("This host (or current configuration) does not allow to fetch lscpu details."), + "GGBCPUINF0005E": _("This host (or current configuration) does not provide Socket(s) information."), + "GGBCPUINF0006E": _("This host (or current configuration) does not provide Core(s) per socket information."), + "GGBCPUINF0007E": _("This host (or current configuration) does not provide Thread(s) per core information."), + +} diff --git a/src/wok/plugins/gingerbase/repositories.py b/src/wok/plugins/gingerbase/repositories.py new file mode 100644 index 0000000..533864d --- /dev/null +++ b/src/wok/plugins/gingerbase/repositories.py @@ -0,0 +1,535 @@ +# +# Project Ginger Base +# +# Copyright IBM, Corp. 2014-2015 +# +# Code derived from Project Kimchi +# 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 wok.basemodel import Singleton +from wok.exception import InvalidOperation, InvalidParameter +from wok.exception import OperationFailed, NotFoundError, MissingParameter +from wok.utils import validate_repo_url + +from config import gingerBaseLock +from yumparser import get_yum_repositories, write_repo_to_file +from yumparser import get_display_name, get_expanded_url + + +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('GGBREPOS0014E') + + 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("GGBREPOS0028E", + {'items': ",".join(extra_keys)}) + + return self._pkg_mnger.addRepo(params) + + def getRepositories(self): + """ + Return a dictionary with all Ginger Base repositories. Each element + uses the format {<repo_id>: {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: + gingerBaseLock.acquire() + repos = get_yum_repositories() + except Exception, e: + gingerBaseLock.release() + raise OperationFailed(errcode, {'err': str(e)}) + finally: + gingerBaseLock.release() + + return repos + + def getRepositoriesList(self): + """ + Return a list of repositories IDs + """ + repos = self._get_repos('GGBREPOS0024E') + 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('GGBREPOS0025E') + + if repo_id not in repos.keys(): + raise NotFoundError("GGBREPOS0012E", {'repo_id': repo_id}) + + entry = repos.get(repo_id) + + display_name = get_display_name(entry.name) + + info = {} + info['enabled'] = entry.enabled + info['baseurl'] = entry.baseurl or '' + info['config'] = {} + info['config']['display_repo_name'] = display_name + 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("GGBREPOS0013E") + + if baseurl: + validate_repo_url(get_expanded_url(baseurl)) + + if mirrorlist: + validate_repo_url(get_expanded_url(mirrorlist)) + + if metalink: + validate_repo_url(get_expanded_url(metalink)) + + if mirrorlist and metalink: + raise InvalidOperation('GGBREPOS0030E') + + repo_id = params.get('repo_id', None) + if repo_id is None: + repo_id = "gingerbase_repo_%s" % str(int(time.time() * 1000)) + + repos = self._get_repos('GGBREPOS0026E') + if repo_id in repos.keys(): + raise InvalidOperation("GGBREPOS0022E", {'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("GGBREPOS0018E", + {'repo_file': repofile}) + + return repo_id + + def toggleRepo(self, repo_id, enable): + repos = self._get_repos('GGBREPOS0011E') + if repo_id not in repos.keys(): + raise NotFoundError("GGBREPOS0012E", {'repo_id': repo_id}) + + entry = repos.get(repo_id) + if enable and entry.enabled: + raise InvalidOperation("GGBREPOS0015E", {'repo_id': repo_id}) + + if not enable and not entry.enabled: + raise InvalidOperation("GGBREPOS0016E", {'repo_id': repo_id}) + + gingerBaseLock.acquire() + try: + if enable: + entry.enable() + else: + entry.disable() + + write_repo_to_file(entry) + except: + if enable: + raise OperationFailed("GGBREPOS0020E", {'repo_id': repo_id}) + + raise OperationFailed("GGBREPOS0021E", {'repo_id': repo_id}) + finally: + gingerBaseLock.release() + + return repo_id + + def updateRepo(self, repo_id, params): + """ + Update a given repository in repositories.Repositories() format + """ + repos = self._get_repos('GGBREPOS0011E') + if repo_id not in repos.keys(): + raise NotFoundError("GGBREPOS0012E", {'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("GGBREPOS0013E") + + if baseurl is not None: + validate_repo_url(get_expanded_url(baseurl)) + entry.baseurl = baseurl + + if mirrorlist is not None: + validate_repo_url(get_expanded_url(mirrorlist)) + entry.mirrorlist = mirrorlist + + if metalink is not None: + validate_repo_url(get_expanded_url(metalink)) + entry.metalink = metalink + + if mirrorlist and metalink: + raise InvalidOperation('GGBREPOS0030E') + + 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) + gingerBaseLock.acquire() + write_repo_to_file(entry) + gingerBaseLock.release() + return repo_id + + def removeRepo(self, repo_id): + """ + Remove a given repository + """ + repos = self._get_repos('GGBREPOS0027E') + if repo_id not in repos.keys(): + raise NotFoundError("GGBREPOS0012E", {'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' + GINGERBASE_LIST = "gingerbase-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.GINGERBASE_LIST) + if not os.path.exists(self.filename): + with open(self.filename, 'w') as fd: + fd.write("# This file is managed by Ginger Base 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: + gingerBaseLock.release() + raise OperationFailed('GGBREPOS0025E', {'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): + gingerBaseLock.acquire() + repos = self._get_repos() + gingerBaseLock.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() + """ + gingerBaseLock.acquire() + repos = self._get_repos() + gingerBaseLock.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("GGBREPOS0012E", {'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 <params> + """ + # 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("GGBREPOS0019E") + + if 'dist' not in config.keys(): + raise MissingParameter("GGBREPOS0019E") + + uri = params['baseurl'] + dist = config['dist'] + comps = config.get('comps', []) + + validate_repo_url(get_expanded_url(uri)) + + gingerBaseLock.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: + gingerBaseLock.release() + raise OperationFailed("GGBREPOS0026E", {'err': e.message}) + gingerBaseLock.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("GGBREPOS0012E", {'repo_id': repo_id}) + + if enable and not r.disabled: + raise InvalidOperation("GGBREPOS0015E", {'repo_id': repo_id}) + + if not enable and r.disabled: + raise InvalidOperation("GGBREPOS0016E", {'repo_id': repo_id}) + + if enable: + line = 'deb' + else: + line = '#deb' + + gingerBaseLock.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: + gingerBaseLock.release() + if enable: + raise OperationFailed("GGBREPOS0020E", {'repo_id': repo_id}) + + raise OperationFailed("GGBREPOS0021E", {'repo_id': repo_id}) + finally: + gingerBaseLock.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("GGBREPOS0012E", {'repo_id': repo_id}) + + gingerBaseLock.acquire() + try: + repos = self._get_repos() + with self.pkg_lock(): + repos.remove(r) + repos.save() + except: + gingerBaseLock.release() + raise OperationFailed("GGBREPOS0017E", {'repo_id': repo_id}) + finally: + gingerBaseLock.release() diff --git a/src/wok/plugins/gingerbase/swupdate.py b/src/wok/plugins/gingerbase/swupdate.py new file mode 100644 index 0000000..7ffd727 --- /dev/null +++ b/src/wok/plugins/gingerbase/swupdate.py @@ -0,0 +1,277 @@ +# +# Project Ginger Base +# +# Copyright IBM, Corp. 2014-2015 +# +# Code derived from Project Kimchi +# 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 signal +import subprocess +import time + +from wok.basemodel import Singleton +from wok.exception import NotFoundError, OperationFailed +from wok.utils import run_command, wok_log + +from config import gingerBaseLock +from 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 Ginger Base perspective. + # It's a dictionary of dictionaries, in the format + # {'package_name': package}, + # where: + # package = {'package_name': <string>, 'version': <string>, + # 'arch': <string>, 'repository': <string> + # } + 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') + wok_log.info("Loading YumUpdate features.") + self._pkg_mnger = YumUpdate() + except ImportError: + try: + __import__('apt') + wok_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: + wok_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('GGBPKGUPD0002E', {'name': name}) + + return self._packages[name] + + def getNumOfUpdates(self): + """ + Return the number of packages to be updated. + """ + self._scanUpdates() + return self._num2update + + def preUpdate(self): + """ + Make adjustments before executing the command in + a child process. + """ + os.setsid() + signal.signal(signal.SIGTERM, signal.SIG_IGN) + + 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, + preexec_fn=self.preUpdate) + 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: + gingerBaseLock.acquire() + self._pkgs = get_yum_packages_list_update() + except Exception, e: + raise OperationFailed('GGBPKGUPD0003E', {'err': str(e)}) + finally: + gingerBaseLock.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': <string>, 'version': <string>, + 'arch': <string>, 'repository': <string>} + """ + 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: + gingerBaseLock.release() + raise OperationFailed('GGBPKGUPD0003E', {'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': <string>, 'version': <string>, + 'arch': <string>, 'repository': <string>} + """ + gingerBaseLock.acquire() + self._refreshUpdateList() + gingerBaseLock.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('GGBPKGUPD0003E', {'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': <string>, 'version': <string>, + 'arch': <string>, 'repository': <string>} + """ + gingerBaseLock.acquire() + self._refreshUpdateList() + gingerBaseLock.release() + return self._pkgs diff --git a/src/wok/plugins/gingerbase/yumparser.py b/src/wok/plugins/gingerbase/yumparser.py new file mode 100644 index 0000000..ebce838 --- /dev/null +++ b/src/wok/plugins/gingerbase/yumparser.py @@ -0,0 +1,354 @@ +# +# Project Ginger Base +# +# Copyright IBM, Corp. 2015 +# +# Code derived from Project Kimchi +# 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 glob + +from os import listdir +from os.path import isfile, splitext, basename + +try: + import rpm +except ImportError: + pass + + +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) + + +def _get_releasever(): + release_file = glob.glob('/etc/*-release')[0] + transaction = rpm.TransactionSet() + match_iter = transaction.dbMatch('basenames', release_file) + + ret = '%releasever' + try: + ret = match_iter.next()['version'] + + except StopIteration: + pass + + return ret + + +def _get_basearch(): + cmd = ['uname', '-i'] + uname = subprocess.Popen(cmd, stdout=subprocess.PIPE) + return uname.communicate()[0].strip('"\n') + + +def _get_all_yum_vars(): + variables = {} + + def _get_var_content(varfile): + with open(varfile) as f: + variables[basename(varfile)] = f.read().strip('\n') + + map(lambda vfile: + _get_var_content(vfile), + glob.glob('/etc/yum/vars/*')) + + return variables + + +def _expand_variables(stringvar, split_char=' '): + yum_variables = _get_all_yum_vars() + yum_variables['releasever'] = _get_releasever() + yum_variables['basearch'] = _get_basearch() + + name_vars = [var for var in stringvar.split(split_char) + if var.startswith('$') and var.strip('$') in yum_variables] + + return reduce(lambda nm, var: + nm.replace(var, yum_variables[var.strip('$')]), + name_vars, + stringvar) + + +def get_display_name(name): + if not name or '$' not in name: + return name + + return _expand_variables(name) + + +def get_expanded_url(url): + url_path = url.split('://') + if len(url_path) != 2 or '$' not in url: + return url + + return _expand_variables(url, '/') + + +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 _ignore_obsoleting_packages_in(output): + out = '' + for l in output.split('\n'): + if 'Obsoleting ' in l: + break + out += l + '\n' + return out + + +def _filter_lines_checkupdate_output(output): + if output is None: + return [] + + output = _ignore_obsoleting_packages_in(output) + + 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() + return_code = yum_update_cmd.returncode + if return_code == 1: + 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 diff --git a/src/wok/plugins/kimchi/disks.py b/src/wok/plugins/kimchi/disks.py deleted file mode 100644 index eb40e3a..0000000 --- a/src/wok/plugins/kimchi/disks.py +++ /dev/null @@ -1,196 +0,0 @@ -# -# 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 wok.exception import OperationFailed -from wok.utils import wok_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 - wok_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: - wok_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: - wok_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 diff --git a/src/wok/plugins/kimchi/repositories.py b/src/wok/plugins/kimchi/repositories.py deleted file mode 100644 index c6e061f..0000000 --- a/src/wok/plugins/kimchi/repositories.py +++ /dev/null @@ -1,533 +0,0 @@ -# -# 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 wok.basemodel import Singleton -from wok.exception import InvalidOperation, InvalidParameter -from wok.exception import OperationFailed, NotFoundError, MissingParameter -from wok.utils import validate_repo_url - -from config import kimchiLock -from yumparser import get_yum_repositories, write_repo_to_file -from yumparser import get_display_name, get_expanded_url - - -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_id>: {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) - - display_name = get_display_name(entry.name) - - info = {} - info['enabled'] = entry.enabled - info['baseurl'] = entry.baseurl or '' - info['config'] = {} - info['config']['display_repo_name'] = display_name - 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(get_expanded_url(baseurl)) - - if mirrorlist: - validate_repo_url(get_expanded_url(mirrorlist)) - - if metalink: - validate_repo_url(get_expanded_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(get_expanded_url(baseurl)) - entry.baseurl = baseurl - - if mirrorlist is not None: - validate_repo_url(get_expanded_url(mirrorlist)) - entry.mirrorlist = mirrorlist - - if metalink is not None: - validate_repo_url(get_expanded_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 <params> - """ - # 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(get_expanded_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() diff --git a/src/wok/plugins/kimchi/swupdate.py b/src/wok/plugins/kimchi/swupdate.py deleted file mode 100644 index b966424..0000000 --- a/src/wok/plugins/kimchi/swupdate.py +++ /dev/null @@ -1,274 +0,0 @@ -# -# 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 os -import signal -import subprocess -import time - -from wok.basemodel import Singleton -from wok.exception import NotFoundError, OperationFailed -from wok.utils import run_command, wok_log - -from config import kimchiLock -from 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': <string>, 'version': <string>, - # 'arch': <string>, 'repository': <string> - # } - 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') - wok_log.info("Loading YumUpdate features.") - self._pkg_mnger = YumUpdate() - except ImportError: - try: - __import__('apt') - wok_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: - wok_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 preUpdate(self): - """ - Make adjustments before executing the command in - a child process. - """ - os.setsid() - signal.signal(signal.SIGTERM, signal.SIG_IGN) - - 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, - preexec_fn=self.preUpdate) - 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': <string>, 'version': <string>, - 'arch': <string>, 'repository': <string>} - """ - 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': <string>, 'version': <string>, - 'arch': <string>, 'repository': <string>} - """ - 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': <string>, 'version': <string>, - 'arch': <string>, 'repository': <string>} - """ - kimchiLock.acquire() - self._refreshUpdateList() - kimchiLock.release() - return self._pkgs diff --git a/src/wok/plugins/kimchi/yumparser.py b/src/wok/plugins/kimchi/yumparser.py deleted file mode 100644 index a481ac2..0000000 --- a/src/wok/plugins/kimchi/yumparser.py +++ /dev/null @@ -1,353 +0,0 @@ -# -# 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 -import glob - -from os import listdir -from os.path import isfile, splitext, basename - -try: - import rpm -except ImportError: - pass - - -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) - - -def _get_releasever(): - release_file = glob.glob('/etc/*-release')[0] - transaction = rpm.TransactionSet() - match_iter = transaction.dbMatch('basenames', release_file) - - ret = '%releasever' - try: - ret = match_iter.next()['version'] - - except StopIteration: - pass - - return ret - - -def _get_basearch(): - cmd = ['uname', '-i'] - uname = subprocess.Popen(cmd, stdout=subprocess.PIPE) - return uname.communicate()[0].strip('"\n') - - -def _get_all_yum_vars(): - variables = {} - - def _get_var_content(varfile): - with open(varfile) as f: - variables[basename(varfile)] = f.read().strip('\n') - - map(lambda vfile: - _get_var_content(vfile), - glob.glob('/etc/yum/vars/*')) - - return variables - - -def _expand_variables(stringvar, split_char=' '): - yum_variables = _get_all_yum_vars() - yum_variables['releasever'] = _get_releasever() - yum_variables['basearch'] = _get_basearch() - - name_vars = [var for var in stringvar.split(split_char) - if var.startswith('$') and var.strip('$') in yum_variables] - - return reduce(lambda nm, var: - nm.replace(var, yum_variables[var.strip('$')]), - name_vars, - stringvar) - - -def get_display_name(name): - if not name or '$' not in name: - return name - - return _expand_variables(name) - - -def get_expanded_url(url): - url_path = url.split('://') - if len(url_path) != 2 or '$' not in url: - return url - - return _expand_variables(url, '/') - - -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 _ignore_obsoleting_packages_in(output): - out = '' - for l in output.split('\n'): - if 'Obsoleting ' in l: - break - out += l + '\n' - return out - - -def _filter_lines_checkupdate_output(output): - if output is None: - return [] - - output = _ignore_obsoleting_packages_in(output) - - 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() - return_code = yum_update_cmd.returncode - if return_code == 1: - 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 -- 2.1.0

On 14/10/2015 08:36, chandra@linux.vnet.ibm.com wrote:
From: chandrureddy <chandra@linux.vnet.ibm.com>
--- src/wok/plugins/gingerbase/disks.py | 197 +++++++++++ src/wok/plugins/gingerbase/i18n.py | 95 +++++ src/wok/plugins/gingerbase/repositories.py | 535 +++++++++++++++++++++++++++++ src/wok/plugins/gingerbase/swupdate.py | 277 +++++++++++++++ src/wok/plugins/gingerbase/yumparser.py | 354 +++++++++++++++++++ src/wok/plugins/kimchi/disks.py | 196 ----------- src/wok/plugins/kimchi/repositories.py | 533 ---------------------------- src/wok/plugins/kimchi/swupdate.py | 274 --------------- src/wok/plugins/kimchi/yumparser.py | 353 ------------------- 9 files changed, 1458 insertions(+), 1356 deletions(-) create mode 100644 src/wok/plugins/gingerbase/disks.py create mode 100644 src/wok/plugins/gingerbase/i18n.py create mode 100644 src/wok/plugins/gingerbase/repositories.py create mode 100644 src/wok/plugins/gingerbase/swupdate.py create mode 100644 src/wok/plugins/gingerbase/yumparser.py delete mode 100644 src/wok/plugins/kimchi/disks.py delete mode 100644 src/wok/plugins/kimchi/repositories.py delete mode 100644 src/wok/plugins/kimchi/swupdate.py delete mode 100644 src/wok/plugins/kimchi/yumparser.py
diff --git a/src/wok/plugins/gingerbase/disks.py b/src/wok/plugins/gingerbase/disks.py new file mode 100644 index 0000000..e8e5f7c --- /dev/null +++ b/src/wok/plugins/gingerbase/disks.py @@ -0,0 +1,197 @@ +# +# Project Ginger Base +# +# Copyright IBM, Corp. 2013-2015 +# +# Code derived from Project Kimchi
Add a blank line here, please
+# 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 +

On 10/15/2015 10:40 PM, Aline Manera wrote:
On 14/10/2015 08:36, chandra@linux.vnet.ibm.com wrote:
From: chandrureddy <chandra@linux.vnet.ibm.com>
--- src/wok/plugins/gingerbase/disks.py | 197 +++++++++++ src/wok/plugins/gingerbase/i18n.py | 95 +++++ src/wok/plugins/gingerbase/repositories.py | 535 +++++++++++++++++++++++++++++ src/wok/plugins/gingerbase/swupdate.py | 277 +++++++++++++++ src/wok/plugins/gingerbase/yumparser.py | 354 +++++++++++++++++++ src/wok/plugins/kimchi/disks.py | 196 ----------- src/wok/plugins/kimchi/repositories.py | 533 ---------------------------- src/wok/plugins/kimchi/swupdate.py | 274 --------------- src/wok/plugins/kimchi/yumparser.py | 353 ------------------- 9 files changed, 1458 insertions(+), 1356 deletions(-) create mode 100644 src/wok/plugins/gingerbase/disks.py create mode 100644 src/wok/plugins/gingerbase/i18n.py create mode 100644 src/wok/plugins/gingerbase/repositories.py create mode 100644 src/wok/plugins/gingerbase/swupdate.py create mode 100644 src/wok/plugins/gingerbase/yumparser.py delete mode 100644 src/wok/plugins/kimchi/disks.py delete mode 100644 src/wok/plugins/kimchi/repositories.py delete mode 100644 src/wok/plugins/kimchi/swupdate.py delete mode 100644 src/wok/plugins/kimchi/yumparser.py
diff --git a/src/wok/plugins/gingerbase/disks.py b/src/wok/plugins/gingerbase/disks.py new file mode 100644 index 0000000..e8e5f7c --- /dev/null +++ b/src/wok/plugins/gingerbase/disks.py @@ -0,0 +1,197 @@ +# +# Project Ginger Base +# +# Copyright IBM, Corp. 2013-2015 +# +# Code derived from Project Kimchi
Add a blank line here, please
Taken care
+# 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: chandrureddy <chandra@linux.vnet.ibm.com> --- src/wok/plugins/gingerbase/README.md | 1 + src/wok/plugins/gingerbase/docs/API.md | 314 +++++++++++++++++++++ src/wok/plugins/gingerbase/docs/Makefile.am | 27 ++ src/wok/plugins/gingerbase/docs/README.md | 201 +++++++++++++ .../gingerbase/docs/gingerbase-host-tab.png | Bin 0 -> 79669 bytes src/wok/plugins/gingerbase/docs/kimchi-login.png | Bin 0 -> 318041 bytes 6 files changed, 543 insertions(+) create mode 120000 src/wok/plugins/gingerbase/README.md create mode 100644 src/wok/plugins/gingerbase/docs/API.md create mode 100644 src/wok/plugins/gingerbase/docs/Makefile.am create mode 100644 src/wok/plugins/gingerbase/docs/README.md create mode 100644 src/wok/plugins/gingerbase/docs/gingerbase-host-tab.png create mode 100644 src/wok/plugins/gingerbase/docs/kimchi-login.png diff --git a/src/wok/plugins/gingerbase/README.md b/src/wok/plugins/gingerbase/README.md new file mode 120000 index 0000000..0e01b43 --- /dev/null +++ b/src/wok/plugins/gingerbase/README.md @@ -0,0 +1 @@ +docs/README.md \ No newline at end of file diff --git a/src/wok/plugins/gingerbase/docs/API.md b/src/wok/plugins/gingerbase/docs/API.md new file mode 100644 index 0000000..e34c86c --- /dev/null +++ b/src/wok/plugins/gingerbase/docs/API.md @@ -0,0 +1,314 @@ +## Project Gigner Base REST API Specification + +The Ginger Base 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 '/plugins/gingerbase' to indicate the root of gingerbase plugin. + * Variable segments in the URI begin with a ':' and should replaced with the + appropriate resource identifier. + +#### Collection: Debug Reports + +**URI:** /plugins/gingerbase/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:** /plugins/gingerbase/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:** /plugins/gingerbase/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:** /plugins/gingerbase/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: HostStats + +**URI:** /plugins/gingerbase/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:** /plugins/gingerbase/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:** /plugins/gingerbase/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: Partitions + +**URI:** /plugins/gingerbase/host/partitions + +**Methods:** + +* **GET**: Retrieves a detailed list of all partitions of the host. + +### Resource: Partition + +**URI:** /plugins/gingerbase/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: Host Packages Update + +**URI:** /plugins/gingerbase/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:** /plugins/gingerbase/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:** /plugins/gingerbase/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:** /plugins/gingerbase/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 diff --git a/src/wok/plugins/gingerbase/docs/Makefile.am b/src/wok/plugins/gingerbase/docs/Makefile.am new file mode 100644 index 0000000..21874d4 --- /dev/null +++ b/src/wok/plugins/gingerbase/docs/Makefile.am @@ -0,0 +1,27 @@ +# +# Ginger Base +# +# Copyright IBM Corp, 2015 +# +# Code derived from Project Kimchi +# 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)/gingerbase/doc + +dist_doc_DATA = \ + API.md \ + README.md \ + gingerbase-host-tab.png \ + $(NULL) diff --git a/src/wok/plugins/gingerbase/docs/README.md b/src/wok/plugins/gingerbase/docs/README.md new file mode 100644 index 0000000..1089b08 --- /dev/null +++ b/src/wok/plugins/gingerbase/docs/README.md @@ -0,0 +1,201 @@ +Ginger Base Plugin +============== + +Ginger Base is an open source base host management plugin for Wok +(Webserver Originated from Kimchi), that provides an intuitive web panel with +common tools for configuring and managing the Linux systems. + +Wok is a cherrypy-based web framework with HTML5 support that is extended by +plugins which expose functionality through REST APIs. + +The current features of Base Host Management of Linux system include: + + Shutdown, Restart, Connect + + Basic Information + + System Statistics + + Software Updates + + Repository Management + + Debug Reports (SoS Reports) + +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 +dif +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 +========================= + +Ginger Base and Wok 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 it with the latest versions of +Fedora, RHEL, OpenSuSe, and Ubuntu. + +Getting Started +=============== + +Install Dependencies +-------------------- + +**For fedora and RHEL:** + + $ sudo yum install wok gettext-devel git \ + python-psutil sos python-lxml \ + libxslt pyparted \ + python-websockify 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 + + # 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 wok gettext \ + python-configobj \ + python-psutil sosreport \ + python-lxml xsltproc \ + python-parted websockify + + 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 wok gettext-tools \ + python-psutil python-lxml \ + libxslt-tools python-xml python-parted \ + python-configobj python-websockify + + 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://en.opensuse.org/SDB:Add_package_repositories) for more +information on how configure your system to access this repository. + +Build and Install +----------------- + + Wok: + $ ./autogen.sh --system + + $ make + $ sudo make install # Optional if running from the source tree + + Ginger Base: + $ cd plugins/gingerbasae + + $ ./autogen.sh --system + + $ make + $ sudo make install # Optional if running from the source tree + +Run +--- + + $ systemctl start wokd + +If you cannot access Wok, take a look at these 2 points: + +1. Firewall +Wok 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 Wok web server: + + semanage permissive -a httpd_t + +Test +---- + + $ cd plugins/gingerbase + $ 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: + + + +Wok 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. + + + +Ginger Base Host tab provides the base host functionality like system information, + system statistics, software updates, repositories and debug reports functionality. + +Also Ginger Base provides shutdown, re-start and connect options. + +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. diff --git a/src/wok/plugins/gingerbase/docs/gingerbase-host-tab.png b/src/wok/plugins/gingerbase/docs/gingerbase-host-tab.png new file mode 100644 index 0000000000000000000000000000000000000000..d84168d7e0182e91a2ed839c70051e0c1e0c8a45 GIT binary patch literal 79669 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 VxXX0{+N^&SV)#2i3&@w&{{w*cbGrZl literal 0 HcmV?d00001 diff --git a/src/wok/plugins/gingerbase/docs/kimchi-login.png b/src/wok/plugins/gingerbase/docs/kimchi-login.png new file mode 100644 index 0000000000000000000000000000000000000000..66387fd70adebc3b20b9520974a127ea7faa52ac GIT binary patch literal 318041 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%0A&`9-9b?c>R2A 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⪼mDSr{tK2+EhOBG_{{`e&G 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 NOI8XjSt(%@^gj?LcDMil literal 0 HcmV?d00001 -- 2.1.0

diff --git a/src/wok/plugins/gingerbase/docs/README.md b/src/wok/plugins/gingerbase/docs/README.md new file mode 100644 index 0000000..1089b08 --- /dev/null +++ b/src/wok/plugins/gingerbase/docs/README.md @@ -0,0 +1,201 @@ +Ginger Base Plugin +============== + +Ginger Base is an open source base host management plugin for Wok +(Webserver Originated from Kimchi), that provides an intuitive web panel with +common tools for configuring and managing the Linux systems. + +Wok is a cherrypy-based web framework with HTML5 support that is extended by +plugins which expose functionality through REST APIs. + +The current features of Base Host Management of Linux system include: + + Shutdown, Restart, Connect + + Basic Information + + System Statistics + + Software Updates + + Repository Management + + Debug Reports (SoS Reports) + +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
We have changed that to only point to the Current Version. You can check the wok README for more details.
+dif
Can the above line be removed?
+Mobile Browser Support: +----------------------- +* **Safari iOS:** Current-1 version +* **Android Browser** Current-1 version +
Same I said before. Only mention Current 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. +
The above statement is not needed any more.
+Hypervisor Distro Support +========================= + +Ginger Base and Wok 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 it with the latest versions of +Fedora, RHEL, OpenSuSe, and Ubuntu.
The Ginger community will be responsible for Ginger Base.
+ +Getting Started +=============== + +Install Dependencies +-------------------- + +**For fedora and RHEL:** + + $ sudo yum install wok gettext-devel git \ + python-psutil sos python-lxml \ + libxslt pyparted \ + python-websockify 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 +
libvirtd service is not needed by gingerbase
+ # 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 wok gettext \ + python-configobj \ + python-psutil sosreport \ + python-lxml xsltproc \ + python-parted websockify + + 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 wok gettext-tools \ + python-psutil python-lxml \ + libxslt-tools python-xml python-parted \ + python-configobj python-websockify + + 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://en.opensuse.org/SDB:Add_package_repositories) for more +information on how configure your system to access this repository. + +Build and Install +----------------- + + Wok: + $ ./autogen.sh --system + + $ make + $ sudo make install # Optional if running from the source tree + + Ginger Base: + $ cd plugins/gingerbasae + + $ ./autogen.sh --system + + $ make + $ sudo make install # Optional if running from the source tree + +Run +--- + + $ systemctl start wokd +
+If you cannot access Wok, take a look at these 2 points: + +1. Firewall +Wok 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 Wok web server: + + semanage permissive -a httpd_t +
Those instructions are related to WOK! So should be only on WOK guidelines.
+Test +---- + + $ cd plugins/gingerbase + $ 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: + +
I don't think the login page is needed here. Also an explanation on which tabs will be added when running wok with gingerbase would be good.
+ +Wok 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. + + + +Ginger Base Host tab provides the base host functionality like system information, + system statistics, software updates, repositories and debug reports functionality. + +Also Ginger Base provides shutdown, re-start and connect options. + +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.
Please, take a look in the Kimchi README file.

I have done these changes. My point here I guess would be if required any such changes we can take them in the later period too. Because we are changing many files every day and it is difficult to pick such changes every time there is one. On 10/15/2015 11:14 PM, Aline Manera wrote:
diff --git a/src/wok/plugins/gingerbase/docs/README.md b/src/wok/plugins/gingerbase/docs/README.md new file mode 100644 index 0000000..1089b08 --- /dev/null +++ b/src/wok/plugins/gingerbase/docs/README.md @@ -0,0 +1,201 @@ +Ginger Base Plugin +============== + +Ginger Base is an open source base host management plugin for Wok +(Webserver Originated from Kimchi), that provides an intuitive web panel with +common tools for configuring and managing the Linux systems. + +Wok is a cherrypy-based web framework with HTML5 support that is extended by +plugins which expose functionality through REST APIs. + +The current features of Base Host Management of Linux system include: + + Shutdown, Restart, Connect + + Basic Information + + System Statistics + + Software Updates + + Repository Management + + Debug Reports (SoS Reports) + +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
We have changed that to only point to the Current Version. You can check the wok README for more details.
+dif
Can the above line be removed?
+Mobile Browser Support: +----------------------- +* **Safari iOS:** Current-1 version +* **Android Browser** Current-1 version +
Same I said before. Only mention Current 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. +
The above statement is not needed any more.
+Hypervisor Distro Support +========================= + +Ginger Base and Wok 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 it with the latest versions of +Fedora, RHEL, OpenSuSe, and Ubuntu.
The Ginger community will be responsible for Ginger Base.
+ +Getting Started +=============== + +Install Dependencies +-------------------- + +**For fedora and RHEL:** + + $ sudo yum install wok gettext-devel git \ + python-psutil sos python-lxml \ + libxslt pyparted \ + python-websockify 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 +
libvirtd service is not needed by gingerbase
+ # 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 wok gettext \ + python-configobj \ + python-psutil sosreport \ + python-lxml xsltproc \ + python-parted websockify + + 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 wok gettext-tools \ + python-psutil python-lxml \ + libxslt-tools python-xml python-parted \ + python-configobj python-websockify + + 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://en.opensuse.org/SDB:Add_package_repositories) for more +information on how configure your system to access this repository. + +Build and Install +----------------- + + Wok: + $ ./autogen.sh --system + + $ make + $ sudo make install # Optional if running from the source tree + + Ginger Base: + $ cd plugins/gingerbasae + + $ ./autogen.sh --system + + $ make + $ sudo make install # Optional if running from the source tree + +Run +--- + + $ systemctl start wokd +
+If you cannot access Wok, take a look at these 2 points: + +1. Firewall +Wok 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 Wok web server: + + semanage permissive -a httpd_t +
Those instructions are related to WOK! So should be only on WOK guidelines.
+Test +---- + + $ cd plugins/gingerbase + $ 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: + +
I don't think the login page is needed here.
Also an explanation on which tabs will be added when running wok with gingerbase would be good.
+ +Wok 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. + + + +Ginger Base Host tab provides the base host functionality like system information, + system statistics, software updates, repositories and debug reports functionality. + +Also Ginger Base provides shutdown, re-start and connect options. + +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.
Please, take a look in the Kimchi README file.

From: chandrureddy <chandra@linux.vnet.ibm.com> --- src/wok/plugins/gingerbase/build-aux/config.rpath | 672 +++++++++++++++++++++ src/wok/plugins/gingerbase/build-aux/genChangelog | 25 + src/wok/plugins/gingerbase/build-aux/pkg-version | 59 ++ .../plugins/gingerbase/contrib/DEBIAN/Makefile.am | 18 + .../plugins/gingerbase/contrib/DEBIAN/control.in | 14 + src/wok/plugins/gingerbase/contrib/Makefile.am | 36 ++ src/wok/plugins/gingerbase/contrib/check_i18n.py | 83 +++ .../gingerbase/contrib/gingerbase.spec.fedora.in | 68 +++ .../gingerbase/contrib/gingerbase.spec.suse.in | 62 ++ src/wok/plugins/gingerbase/contrib/make-deb.sh.in | 15 + 10 files changed, 1052 insertions(+) create mode 100644 src/wok/plugins/gingerbase/build-aux/config.rpath create mode 100755 src/wok/plugins/gingerbase/build-aux/genChangelog create mode 100755 src/wok/plugins/gingerbase/build-aux/pkg-version create mode 100644 src/wok/plugins/gingerbase/contrib/DEBIAN/Makefile.am create mode 100644 src/wok/plugins/gingerbase/contrib/DEBIAN/control.in create mode 100644 src/wok/plugins/gingerbase/contrib/Makefile.am create mode 100755 src/wok/plugins/gingerbase/contrib/check_i18n.py create mode 100644 src/wok/plugins/gingerbase/contrib/gingerbase.spec.fedora.in create mode 100644 src/wok/plugins/gingerbase/contrib/gingerbase.spec.suse.in create mode 100644 src/wok/plugins/gingerbase/contrib/make-deb.sh.in diff --git a/src/wok/plugins/gingerbase/build-aux/config.rpath b/src/wok/plugins/gingerbase/build-aux/config.rpath new file mode 100644 index 0000000..17298f2 --- /dev/null +++ b/src/wok/plugins/gingerbase/build-aux/config.rpath @@ -0,0 +1,672 @@ +#! /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 <gord@gnu.ai.mit.edu>, 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 <kc5tja@dolphin.openprojects.net> 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=/' <<EOF + +# How to pass a linker flag through the compiler. +wl="$escaped_wl" + +# Static library suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally "so"). +shlibext="$shlibext" + +# Format of library name prefix. +libname_spec="$escaped_libname_spec" + +# Library names that the linker finds when passed -lNAME. +library_names_spec="$escaped_library_names_spec" + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec="$escaped_hardcode_libdir_flag_spec" + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator="$hardcode_libdir_separator" + +# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the +# resulting binary. +hardcode_direct="$hardcode_direct" + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L="$hardcode_minus_L" + +EOF diff --git a/src/wok/plugins/gingerbase/build-aux/genChangelog b/src/wok/plugins/gingerbase/build-aux/genChangelog new file mode 100755 index 0000000..803f24e --- /dev/null +++ b/src/wok/plugins/gingerbase/build-aux/genChangelog @@ -0,0 +1,25 @@ +#!/bin/bash + +# This script is based on code from the Kandan project: +# https://github.com/kandanapp/kandan/blob/master/gen-changelog.sh + +echo "CHANGELOG" +echo "=========" +echo +git for-each-ref --sort='*authordate' --format='%(tag)' refs/tags | tac |grep -v '^$' | while read TAG ; do + if [ $NEXT ]; then + echo "#### [$NEXT] ####" + elif [ "$1" != "--release" ]; then + echo "#### [Current] ####" + else + NEXT=$TAG + continue + fi + GIT_PAGER=cat git log --pretty=format:" * [%h] %<(78,trunc)%s (%an)" $TAG..$NEXT + NEXT=$TAG + echo; echo +done +FIRST=$(git for-each-ref --sort='*authordate' --format='%(tag)' refs/tags | head -1) + +echo "#### [$FIRST] ####" +GIT_PAGER=cat git log --pretty=format:" * [%h] %<(78,trunc)%s (%an)" $FIRST diff --git a/src/wok/plugins/gingerbase/build-aux/pkg-version b/src/wok/plugins/gingerbase/build-aux/pkg-version new file mode 100755 index 0000000..749cf6c --- /dev/null +++ b/src/wok/plugins/gingerbase/build-aux/pkg-version @@ -0,0 +1,59 @@ +#!/bin/sh +# +# Copyright 2008-2012 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# tags and output versions: +# - 4.9.0 => 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 diff --git a/src/wok/plugins/gingerbase/contrib/DEBIAN/Makefile.am b/src/wok/plugins/gingerbase/contrib/DEBIAN/Makefile.am new file mode 100644 index 0000000..1ed4e39 --- /dev/null +++ b/src/wok/plugins/gingerbase/contrib/DEBIAN/Makefile.am @@ -0,0 +1,18 @@ +# Copyright IBM Corp, 2015 +# +# Code derived from Project Kimchi +# 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 diff --git a/src/wok/plugins/gingerbase/contrib/DEBIAN/control.in b/src/wok/plugins/gingerbase/contrib/DEBIAN/control.in new file mode 100644 index 0000000..aacf946 --- /dev/null +++ b/src/wok/plugins/gingerbase/contrib/DEBIAN/control.in @@ -0,0 +1,14 @@ +Package: @PACKAGE_NAME@ +Version: @PACKAGE_VERSION@ +Section: base +Priority: optional +Architecture: all +Depends: wok, + python-psutil (>= 0.6.0), + sosreport, +Build-Depends: libxslt, + python-lxml +Maintainer: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com> +Description: Ginger Base is an open source base host management plugin for Wok +(Webserver Originated from Kimchi), that provides an intuitive web panel with +common tools for configuring and managing the Linux systems. diff --git a/src/wok/plugins/gingerbase/contrib/Makefile.am b/src/wok/plugins/gingerbase/contrib/Makefile.am new file mode 100644 index 0000000..ca8aa4c --- /dev/null +++ b/src/wok/plugins/gingerbase/contrib/Makefile.am @@ -0,0 +1,36 @@ +# Copyright IBM Corp, 2015 +# +# Code derived from Project Kimchi +# 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 \ + gingerbase.spec.fedora.in \ + gingerbase.spec.suse.in \ + 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 = gingerbase.spec.fedora gingerbase.spec.suse gingerbase.spec make-deb.sh diff --git a/src/wok/plugins/gingerbase/contrib/check_i18n.py b/src/wok/plugins/gingerbase/contrib/check_i18n.py new file mode 100755 index 0000000..3c32f1d --- /dev/null +++ b/src/wok/plugins/gingerbase/contrib/check_i18n.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python2 +# +# Project Ginger Base +# +# Copyright IBM, Corp. 2015 +# +# Code derived from Project Kimchi +# 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() diff --git a/src/wok/plugins/gingerbase/contrib/gingerbase.spec.fedora.in b/src/wok/plugins/gingerbase/contrib/gingerbase.spec.fedora.in new file mode 100644 index 0000000..a4ffb66 --- /dev/null +++ b/src/wok/plugins/gingerbase/contrib/gingerbase.spec.fedora.in @@ -0,0 +1,68 @@ +Name: Ginger Base +Version: @PACKAGE_VERSION@ +Release: @PACKAGE_RELEASE@%{?dist} +Summary: Wok plugin for base host management +BuildRoot: %{_topdir}/BUILD/%{name}-%{version}-%{release} +BuildArch: noarch +Group: System Environment/Base +License: LGPL/ASL2 +Source0: %{name}-%{version}.tar.gz +Requires: wok +Requires: python-psutil >= 0.6.0 +Requires: sos +BuildRequires: libxslt +BuildRequires: python-lxml + +%if 0%{?fedora} >= 15 || 0%{?rhel} >= 7 +%global with_systemd 1 +%endif + +%if 0%{?rhel} == 6 +Requires: python-ordereddict +BuildRequires: python-unittest2 +%endif + +%description +Ginger Base is an open source base host management plugin for Wok +(Webserver Originated from Kimchi), that provides an intuitive web panel with +common tools for configuring and managing the Linux systems. + +%prep + + +%build +%configure +make + + +%install +rm -rf %{buildroot} +make DESTDIR=%{buildroot} install + + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%attr(-,root,root) +%{python_sitelib}/wok/plugins/gingerbase/*.py* +%{python_sitelib}/wok/plugins/gingerbase/control/*.py* +%{python_sitelib}/wok/plugins/gingerbase/model/*.py* +%{python_sitelib}/wok/plugins/gingerbase/API.json +%{python_sitelib}/wok/plugins/gingerbase/ +%{_datadir}/wok/plugins/gingerbase/doc/API.md +%{_datadir}/wok/plugins/gingerbase/doc/README.md +%{_datadir}/wok/plugins/gingerbase/doc/README-federation.md +%{_prefix}/share/locale/*/LC_MESSAGES/gingerbase.mo +%{_datadir}/wok/plugins/gingerbase/ui/config/*.xml +%{_datadir}/wok/plugins/gingerbase/ui/ +%{_datadir}/wok/plugins/gingerbase +%{_sysconfdir}/wok/plugins.d/gingerbase.conf +%{_sysconfdir}/wok/ +%{_sharedstatedir}/wok/debugreports/ +%{_sharedstatedir}/wok/ + + +%changelog +* Thu Aug 25 2015 Chandra Shehkhar Reddy Potula <chandra@linux.vnet.ibm.com> 0.0-1s +- First build diff --git a/src/wok/plugins/gingerbase/contrib/gingerbase.spec.suse.in b/src/wok/plugins/gingerbase/contrib/gingerbase.spec.suse.in new file mode 100644 index 0000000..ba92606 --- /dev/null +++ b/src/wok/plugins/gingerbase/contrib/gingerbase.spec.suse.in @@ -0,0 +1,62 @@ +Name: Ginger Base +Version: @PACKAGE_VERSION@ +Release: @PACKAGE_RELEASE@%{?dist} +Summary: Wok plugin for base host management +BuildRoot: %{_topdir}/BUILD/%{name}-%{version}-%{release} +BuildArch: noarch +Group: System Environment/Base +License: LGPL/ASL2 +Source0: %{name}-%{version}.tar.gz +Requires: wok +Requires: python-psutil >= 0.6.0 +BuildRequires: libxslt-tools +BuildRequires: python-lxml + +%if 0%{?suse_version} == 1100 +Requires: python-ordereddict +%endif + +%if 0%{?suse_version} > 1140 +%global with_systemd 1 +%endif + +%description +Ginger Base is an open source base host management plugin for Wok +(Webserver Originated from Kimchi), that provides an intuitive web panel with +common tools for configuring and managing the Linux systems. + +%prep +%setup + +%install +rm -rf %{buildroot} +make DESTDIR=%{buildroot} install + + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%attr(-,root,root) +%{python_sitelib}/wok/plugins/gingerbase/*.py* +%{python_sitelib}/wok/plugins/gingerbase/control/*.py* +%{python_sitelib}/wok/plugins/gingerbase/model/*.py* +%{python_sitelib}/wok/plugins/gingerbase/API.json +%{python_sitelib}/wok/plugins/gingerbase/ +%{_datadir}/wok/plugins/gingerbase/doc/API.md +%{_datadir}/wok/plugins/gingerbase/doc/README.md +%{_datadir}/wok/plugins/gingerbase/doc/README-federation.md +%{_prefix}/share/locale/*/LC_MESSAGES/gingerbase.mo +%{_datadir}/wok/plugins/gingerbase/ui/config/*.xml +%{_datadir}/wok/plugins/gingerbase/ui/ +%{_datadir}/wok/plugins/gingerbase +%{_sysconfdir}/wok/plugins.d/gingerbase.conf +%{_sysconfdir}/wok/ +%{_var}/lib/wok/debugreports/ +%{_var}/lib/wok/ + + + +%changelog +* Thu Aug 25 2015 Chandra Shehkhar Reddy Potula <chandra@linux.vnet.ibm.com> 0.0-1 +- First build diff --git a/src/wok/plugins/gingerbase/contrib/make-deb.sh.in b/src/wok/plugins/gingerbase/contrib/make-deb.sh.in new file mode 100644 index 0000000..a4c92bf --- /dev/null +++ b/src/wok/plugins/gingerbase/contrib/make-deb.sh.in @@ -0,0 +1,15 @@ +#!/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 gingerbase-${VERSION}-${RELEASE}.noarch.deb +rm -rf $TMPDIR -- 2.1.0

diff --git a/src/wok/plugins/gingerbase/contrib/DEBIAN/Makefile.am b/src/wok/plugins/gingerbase/contrib/DEBIAN/Makefile.am new file mode 100644 index 0000000..1ed4e39 --- /dev/null +++ b/src/wok/plugins/gingerbase/contrib/DEBIAN/Makefile.am @@ -0,0 +1,18 @@
Missing project name in the license header
+# Copyright IBM Corp, 2015 +#
+# Code derived from Project Kimchi
It is a new file so the above line is not needed.
+# 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 diff --git a/src/wok/plugins/gingerbase/contrib/DEBIAN/control.in b/src/wok/plugins/gingerbase/contrib/DEBIAN/control.in new file mode 100644 index 0000000..aacf946 --- /dev/null +++ b/src/wok/plugins/gingerbase/contrib/DEBIAN/control.in @@ -0,0 +1,14 @@ +Package: @PACKAGE_NAME@ +Version: @PACKAGE_VERSION@ +Section: base +Priority: optional +Architecture: all +Depends: wok, + python-psutil (>= 0.6.0), + sosreport, +Build-Depends: libxslt, + python-lxml +Maintainer: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com> +Description: Ginger Base is an open source base host management plugin for Wok +(Webserver Originated from Kimchi), that provides an intuitive web panel with +common tools for configuring and managing the Linux systems. diff --git a/src/wok/plugins/gingerbase/contrib/Makefile.am b/src/wok/plugins/gingerbase/contrib/Makefile.am new file mode 100644 index 0000000..ca8aa4c --- /dev/null +++ b/src/wok/plugins/gingerbase/contrib/Makefile.am @@ -0,0 +1,36 @@ +# Copyright IBM Corp, 2015 +# +# Code derived from Project Kimchi
Same I commented above
+# 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: chandrureddy <chandra@linux.vnet.ibm.com> --- src/wok/plugins/gingerbase/m4/ac_python_module.m4 | 30 + src/wok/plugins/gingerbase/m4/gettext.m4 | 383 +++++++++++ src/wok/plugins/gingerbase/m4/iconv.m4 | 214 ++++++ src/wok/plugins/gingerbase/m4/intlmacosx.m4 | 51 ++ src/wok/plugins/gingerbase/m4/lib-ld.m4 | 110 +++ src/wok/plugins/gingerbase/m4/lib-link.m4 | 774 ++++++++++++++++++++++ src/wok/plugins/gingerbase/m4/lib-prefix.m4 | 224 +++++++ src/wok/plugins/gingerbase/m4/nls.m4 | 32 + src/wok/plugins/gingerbase/m4/po.m4 | 449 +++++++++++++ src/wok/plugins/gingerbase/m4/progtest.m4 | 92 +++ 10 files changed, 2359 insertions(+) create mode 100644 src/wok/plugins/gingerbase/m4/ac_python_module.m4 create mode 100644 src/wok/plugins/gingerbase/m4/gettext.m4 create mode 100644 src/wok/plugins/gingerbase/m4/iconv.m4 create mode 100644 src/wok/plugins/gingerbase/m4/intlmacosx.m4 create mode 100644 src/wok/plugins/gingerbase/m4/lib-ld.m4 create mode 100644 src/wok/plugins/gingerbase/m4/lib-link.m4 create mode 100644 src/wok/plugins/gingerbase/m4/lib-prefix.m4 create mode 100644 src/wok/plugins/gingerbase/m4/nls.m4 create mode 100644 src/wok/plugins/gingerbase/m4/po.m4 create mode 100644 src/wok/plugins/gingerbase/m4/progtest.m4 diff --git a/src/wok/plugins/gingerbase/m4/ac_python_module.m4 b/src/wok/plugins/gingerbase/m4/ac_python_module.m4 new file mode 100644 index 0000000..32b9d72 --- /dev/null +++ b/src/wok/plugins/gingerbase/m4/ac_python_module.m4 @@ -0,0 +1,30 @@ +dnl @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 <colliera@nu.ac.za>. +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 +]) diff --git a/src/wok/plugins/gingerbase/m4/gettext.m4 b/src/wok/plugins/gingerbase/m4/gettext.m4 new file mode 100644 index 0000000..f84e6a5 --- /dev/null +++ b/src/wok/plugins/gingerbase/m4/gettext.m4 @@ -0,0 +1,383 @@ +# 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 <drepper@cygnus.com>, 1995-2000. +dnl Bruno Haible <haible@clisp.cons.org>, 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 <inttypes.h> 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 <libintl.h> +$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 <libintl.h> +$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 <libintl.h> +$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], []) diff --git a/src/wok/plugins/gingerbase/m4/iconv.m4 b/src/wok/plugins/gingerbase/m4/iconv.m4 new file mode 100644 index 0000000..e2041b9 --- /dev/null +++ b/src/wok/plugins/gingerbase/m4/iconv.m4 @@ -0,0 +1,214 @@ +# 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 <stdlib.h> +#include <iconv.h>], + [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 <stdlib.h> +#include <iconv.h>], + [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 <iconv.h> +#include <string.h> +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 <stdlib.h> +#include <iconv.h> +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 +]) diff --git a/src/wok/plugins/gingerbase/m4/intlmacosx.m4 b/src/wok/plugins/gingerbase/m4/intlmacosx.m4 new file mode 100644 index 0000000..dd91025 --- /dev/null +++ b/src/wok/plugins/gingerbase/m4/intlmacosx.m4 @@ -0,0 +1,51 @@ +# 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 <CoreFoundation/CFPreferences.h>], + [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 <CoreFoundation/CFLocale.h>], [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]) +]) diff --git a/src/wok/plugins/gingerbase/m4/lib-ld.m4 b/src/wok/plugins/gingerbase/m4/lib-ld.m4 new file mode 100644 index 0000000..ebb3052 --- /dev/null +++ b/src/wok/plugins/gingerbase/m4/lib-ld.m4 @@ -0,0 +1,110 @@ +# 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 </dev/null` in +*GNU* | *'with BFD'*) + acl_cv_prog_gnu_ld=yes ;; +*) + acl_cv_prog_gnu_ld=no ;; +esac]) +with_gnu_ld=$acl_cv_prog_gnu_ld +]) + +dnl From libtool-1.4. Sets the variable LD. +AC_DEFUN([AC_LIB_PROG_LD], +[AC_ARG_WITH([gnu-ld], +[ --with-gnu-ld assume the C compiler uses GNU ld [default=no]], +test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no) +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +# 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 +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 +]) diff --git a/src/wok/plugins/gingerbase/m4/lib-link.m4 b/src/wok/plugins/gingerbase/m4/lib-link.m4 new file mode 100644 index 0000000..c73bd8e --- /dev/null +++ b/src/wok/plugins/gingerbase/m4/lib-link.m4 @@ -0,0 +1,774 @@ +# 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]) +]) diff --git a/src/wok/plugins/gingerbase/m4/lib-prefix.m4 b/src/wok/plugins/gingerbase/m4/lib-prefix.m4 new file mode 100644 index 0000000..1601cea --- /dev/null +++ b/src/wok/plugins/gingerbase/m4/lib-prefix.m4 @@ -0,0 +1,224 @@ +# 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 <http://docs.sun.com/app/docs/doc/816-5138/dev-env?l=en&a=view>. + 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" +]) diff --git a/src/wok/plugins/gingerbase/m4/nls.m4 b/src/wok/plugins/gingerbase/m4/nls.m4 new file mode 100644 index 0000000..003704c --- /dev/null +++ b/src/wok/plugins/gingerbase/m4/nls.m4 @@ -0,0 +1,32 @@ +# 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 <drepper@cygnus.com>, 1995-2000. +dnl Bruno Haible <haible@clisp.cons.org>, 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]) +]) diff --git a/src/wok/plugins/gingerbase/m4/po.m4 b/src/wok/plugins/gingerbase/m4/po.m4 new file mode 100644 index 0000000..8bc921d --- /dev/null +++ b/src/wok/plugins/gingerbase/m4/po.m4 @@ -0,0 +1,449 @@ +# 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 <drepper@cygnus.com>, 1995-2000. +dnl Bruno Haible <haible@clisp.cons.org>, 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 <<EOT +$* +EOT + } + gt_echo='echo_func' + fi + fi + + # A sed script that extracts the value of VARIABLE from a Makefile. + sed_x_variable=' +# Test if the hold space is empty. +x +s/P/P/ +x +ta +# Yes it was empty. Look if we have the expected variable definition. +/^[ ]*VARIABLE[ ]*=/{ + # Seen the first line of the variable definition. + s/^[ ]*VARIABLE[ ]*=// + ba +} +bd +:a +# Here we are processing a line from the variable definition. +# Remove comment, more precisely replace it with a space. +s/#.*$/ / +# See if the line ends in a backslash. +tb +:b +s/\\$// +# Print the line, without the trailing backslash. +p +tc +# There was no trailing backslash. The end of the variable definition is +# reached. Clear the hold space. +s/^.*$// +x +bd +:c +# A trailing backslash means that the variable definition continues in the +# next line. Put a nonempty string into the hold space to indicate this. +s/^.*$/P/ +x +:d +' +changequote([,])dnl + + # Set POTFILES to the value of the Makefile variable POTFILES. + sed_x_POTFILES=`$gt_echo "$sed_x_variable" | sed -e '/^ *#/d' -e 's/VARIABLE/POTFILES/g'` + POTFILES=`sed -n -e "$sed_x_POTFILES" < "$ac_file"` + # Compute POTFILES_DEPS as + # $(foreach file, $(POTFILES), $(top_srcdir)/$(file)) + POTFILES_DEPS= + for file in $POTFILES; do + POTFILES_DEPS="$POTFILES_DEPS "'$(top_srcdir)/'"$file" + done + POMAKEFILEDEPS="" + + 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 + if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then + # The LINGUAS file contains the set of available languages. + ALL_LINGUAS_=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"` + POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS" + else + # Set ALL_LINGUAS to the value of the Makefile variable LINGUAS. + sed_x_LINGUAS=`$gt_echo "$sed_x_variable" | sed -e '/^ *#/d' -e 's/VARIABLE/LINGUAS/g'` + ALL_LINGUAS_=`sed -n -e "$sed_x_LINGUAS" < "$ac_file"` + fi + # Hide the ALL_LINGUAS assigment from automake < 1.5. + eval 'ALL_LINGUAS''=$ALL_LINGUAS_' + # 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) + # Compute PROPERTIESFILES + # as $(foreach lang, $(ALL_LINGUAS), $(top_srcdir)/$(DOMAIN)_$(lang).properties) + # Compute CLASSFILES + # as $(foreach lang, $(ALL_LINGUAS), $(top_srcdir)/$(DOMAIN)_$(lang).class) + # Compute QMFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).qm) + # Compute MSGFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(frob $(lang)).msg) + # Compute RESOURCESDLLFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(frob $(lang))/$(DOMAIN).resources.dll) + case "$ac_given_srcdir" in + .) srcdirpre= ;; + *) srcdirpre='$(srcdir)/' ;; + esac + POFILES= + UPDATEPOFILES= + DUMMYPOFILES= + GMOFILES= + PROPERTIESFILES= + CLASSFILES= + QMFILES= + MSGFILES= + RESOURCESDLLFILES= + 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" + PROPERTIESFILES="$PROPERTIESFILES \$(top_srcdir)/\$(DOMAIN)_$lang.properties" + CLASSFILES="$CLASSFILES \$(top_srcdir)/\$(DOMAIN)_$lang.class" + QMFILES="$QMFILES $srcdirpre$lang.qm" + frobbedlang=`echo $lang | sed -e 's/\..*$//' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'` + MSGFILES="$MSGFILES $srcdirpre$frobbedlang.msg" + 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/'` + RESOURCESDLLFILES="$RESOURCESDLLFILES $srcdirpre$frobbedlang/\$(DOMAIN).resources.dll" + 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= + JAVACATALOGS= + QTCATALOGS= + TCLCATALOGS= + CSHARPCATALOGS= + if test -n "$INST_LINGUAS"; then + for lang in $INST_LINGUAS; do + CATALOGS="$CATALOGS $lang.gmo" + JAVACATALOGS="$JAVACATALOGS \$(DOMAIN)_$lang.properties" + QTCATALOGS="$QTCATALOGS $lang.qm" + frobbedlang=`echo $lang | sed -e 's/\..*$//' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'` + TCLCATALOGS="$TCLCATALOGS $frobbedlang.msg" + 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/'` + CSHARPCATALOGS="$CSHARPCATALOGS $frobbedlang/\$(DOMAIN).resources.dll" + done + fi + + sed -e "s|@POTFILES_DEPS@|$POTFILES_DEPS|g" -e "s|@POFILES@|$POFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@PROPERTIESFILES@|$PROPERTIESFILES|g" -e "s|@CLASSFILES@|$CLASSFILES|g" -e "s|@QMFILES@|$QMFILES|g" -e "s|@MSGFILES@|$MSGFILES|g" -e "s|@RESOURCESDLLFILES@|$RESOURCESDLLFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@JAVACATALOGS@|$JAVACATALOGS|g" -e "s|@QTCATALOGS@|$QTCATALOGS|g" -e "s|@TCLCATALOGS@|$TCLCATALOGS|g" -e "s|@CSHARPCATALOGS@|$CSHARPCATALOGS|g" -e 's,^#distdir:,distdir:,' < "$ac_file" > "$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" <<EOF +$frobbedlang.msg: $lang.po + @echo "\$(MSGFMT) -c --tcl -d \$(srcdir) -l $lang $srcdirpre$lang.po"; \ + \$(MSGFMT) -c --tcl -d "\$(srcdir)" -l $lang $srcdirpre$lang.po || { rm -f "\$(srcdir)/$frobbedlang.msg"; exit 1; } +EOF + done + fi + if grep -l '@CSHARPCATALOGS@' "$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/_/-/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" <<EOF +$frobbedlang/\$(DOMAIN).resources.dll: $lang.po + @echo "\$(MSGFMT) -c --csharp -d \$(srcdir) -l $lang $srcdirpre$lang.po -r \$(DOMAIN)"; \ + \$(MSGFMT) -c --csharp -d "\$(srcdir)" -l $lang $srcdirpre$lang.po -r "\$(DOMAIN)" || { rm -f "\$(srcdir)/$frobbedlang.msg"; exit 1; } +EOF + done + fi + if test -n "$POMAKEFILEDEPS"; then + cat >> "$ac_file.tmp" <<EOF +Makefile: $POMAKEFILEDEPS +EOF + fi + mv "$ac_file.tmp" "$ac_file" +]) + +dnl Initializes the accumulator used by AM_XGETTEXT_OPTION. +AC_DEFUN([AM_XGETTEXT_OPTION_INIT], +[ + XGETTEXT_EXTRA_OPTIONS= +]) + +dnl Registers an option to be passed to xgettext in the po subdirectory. +AC_DEFUN([AM_XGETTEXT_OPTION], +[ + AC_REQUIRE([AM_XGETTEXT_OPTION_INIT]) + XGETTEXT_EXTRA_OPTIONS="$XGETTEXT_EXTRA_OPTIONS $1" +]) diff --git a/src/wok/plugins/gingerbase/m4/progtest.m4 b/src/wok/plugins/gingerbase/m4/progtest.m4 new file mode 100644 index 0000000..2d804ac --- /dev/null +++ b/src/wok/plugins/gingerbase/m4/progtest.m4 @@ -0,0 +1,92 @@ +# progtest.m4 serial 6 (gettext-0.18) +dnl Copyright (C) 1996-2003, 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 +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 <drepper@cygnus.com>, 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 +]) -- 2.1.0

From: chandrureddy <chandra@linux.vnet.ibm.com> --- src/wok/plugins/gingerbase/control/Makefile.am | 26 ++++ src/wok/plugins/gingerbase/control/__init__.py | 27 ++++ src/wok/plugins/gingerbase/control/config.py | 42 ++++++ src/wok/plugins/gingerbase/control/cpuinfo.py | 38 ++++++ src/wok/plugins/gingerbase/control/debugreports.py | 62 +++++++++ src/wok/plugins/gingerbase/control/host.py | 146 +++++++++++++++++++++ src/wok/plugins/kimchi/control/debugreports.py | 61 --------- 7 files changed, 341 insertions(+), 61 deletions(-) create mode 100644 src/wok/plugins/gingerbase/control/Makefile.am create mode 100644 src/wok/plugins/gingerbase/control/__init__.py create mode 100644 src/wok/plugins/gingerbase/control/config.py create mode 100644 src/wok/plugins/gingerbase/control/cpuinfo.py create mode 100644 src/wok/plugins/gingerbase/control/debugreports.py create mode 100644 src/wok/plugins/gingerbase/control/host.py delete mode 100644 src/wok/plugins/kimchi/control/debugreports.py diff --git a/src/wok/plugins/gingerbase/control/Makefile.am b/src/wok/plugins/gingerbase/control/Makefile.am new file mode 100644 index 0000000..61b3a96 --- /dev/null +++ b/src/wok/plugins/gingerbase/control/Makefile.am @@ -0,0 +1,26 @@ +# +# Ginger Base +# +# Copyright IBM Corp, 2015 +# +# Code derived from Project Kimchi +# 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 + +control_PYTHON = *.py + +controldir = $(pythondir)/wok/plugins/gingerbase/control + +install-data-local: + $(MKDIR_P) $(DESTDIR)$(controldir) diff --git a/src/wok/plugins/gingerbase/control/__init__.py b/src/wok/plugins/gingerbase/control/__init__.py new file mode 100644 index 0000000..cf1682e --- /dev/null +++ b/src/wok/plugins/gingerbase/control/__init__.py @@ -0,0 +1,27 @@ +# +# Project Ginger Base +# +# Copyright IBM, Corp. 2015 +# +# Code derived from Project Kimchi +# 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 wok.control.utils import load_url_sub_node + + +sub_nodes = load_url_sub_node(os.path.dirname(__file__), __name__) diff --git a/src/wok/plugins/gingerbase/control/config.py b/src/wok/plugins/gingerbase/control/config.py new file mode 100644 index 0000000..fcbf5dd --- /dev/null +++ b/src/wok/plugins/gingerbase/control/config.py @@ -0,0 +1,42 @@ +# +# Project Ginger Base +# +# Copyright IBM, Corp. 2013-2014 +# +# Code derived from Project Kimchi +# 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 wok.control.base import Resource +from wok.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) + + @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 diff --git a/src/wok/plugins/gingerbase/control/cpuinfo.py b/src/wok/plugins/gingerbase/control/cpuinfo.py new file mode 100644 index 0000000..a101bf7 --- /dev/null +++ b/src/wok/plugins/gingerbase/control/cpuinfo.py @@ -0,0 +1,38 @@ +# +# Project Ginger Base +# +# Copyright IBM, Corp. 2014-2015 +# +# Code derived from Project Kimchi +# 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 wok.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'] + } diff --git a/src/wok/plugins/gingerbase/control/debugreports.py b/src/wok/plugins/gingerbase/control/debugreports.py new file mode 100644 index 0000000..bc5079f --- /dev/null +++ b/src/wok/plugins/gingerbase/control/debugreports.py @@ -0,0 +1,62 @@ +# +# Project Ginger Base +# +# Copyright IBM, Corp. 2013-2015 +# +# Code derived from Project Kimchi +# 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 wok.control.base import AsyncCollection, Resource +from wok.control.utils import internal_redirect +from wok.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']) diff --git a/src/wok/plugins/gingerbase/control/host.py b/src/wok/plugins/gingerbase/control/host.py new file mode 100644 index 0000000..586adce --- /dev/null +++ b/src/wok/plugins/gingerbase/control/host.py @@ -0,0 +1,146 @@ +# +# Project Ginger Base +# +# Copyright IBM, Corp. 2013-2015 +# +# Code derived from Project Kimchi +# 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 wok.control.base import Collection, Resource +from wok.control.utils import UrlSubNode +from wok.exception import NotFoundError + +from cpuinfo import CPUInfo + + +@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) + self.capabilities = Capabilities(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 Capabilities(Resource): + def __init__(self, model, id=None): + super(Capabilities, self).__init__(model, id) + + @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("GGBPART0001E", {'name': self.info['name']}) + + 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 diff --git a/src/wok/plugins/kimchi/control/debugreports.py b/src/wok/plugins/kimchi/control/debugreports.py deleted file mode 100644 index b5a3072..0000000 --- a/src/wok/plugins/kimchi/control/debugreports.py +++ /dev/null @@ -1,61 +0,0 @@ -# -# 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 wok.control.base import AsyncCollection, Resource -from wok.control.utils import internal_redirect -from wok.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']) -- 2.1.0

From: chandrureddy <chandra@linux.vnet.ibm.com> --- src/wok/plugins/gingerbase/model/Makefile.am | 26 ++ src/wok/plugins/gingerbase/model/__init__.py | 19 + src/wok/plugins/gingerbase/model/config.py | 82 +++++ src/wok/plugins/gingerbase/model/cpuinfo.py | 104 ++++++ src/wok/plugins/gingerbase/model/debugreports.py | 214 ++++++++++++ src/wok/plugins/gingerbase/model/host.py | 427 +++++++++++++++++++++++ src/wok/plugins/gingerbase/model/model.py | 54 +++ src/wok/plugins/kimchi/model/debugreports.py | 213 ----------- 8 files changed, 926 insertions(+), 213 deletions(-) create mode 100644 src/wok/plugins/gingerbase/model/Makefile.am create mode 100644 src/wok/plugins/gingerbase/model/__init__.py create mode 100644 src/wok/plugins/gingerbase/model/config.py create mode 100644 src/wok/plugins/gingerbase/model/cpuinfo.py create mode 100644 src/wok/plugins/gingerbase/model/debugreports.py create mode 100644 src/wok/plugins/gingerbase/model/host.py create mode 100644 src/wok/plugins/gingerbase/model/model.py delete mode 100644 src/wok/plugins/kimchi/model/debugreports.py diff --git a/src/wok/plugins/gingerbase/model/Makefile.am b/src/wok/plugins/gingerbase/model/Makefile.am new file mode 100644 index 0000000..01487ee --- /dev/null +++ b/src/wok/plugins/gingerbase/model/Makefile.am @@ -0,0 +1,26 @@ +# +# Ginger Base +# +# Copyright IBM Corp, 2015 +# +# Code derived from Project Kimchi +# 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)/wok/plugins/gingerbase/model + +install-data-local: + $(MKDIR_P) $(DESTDIR)$(modeldir) diff --git a/src/wok/plugins/gingerbase/model/__init__.py b/src/wok/plugins/gingerbase/model/__init__.py new file mode 100644 index 0000000..6702acb --- /dev/null +++ b/src/wok/plugins/gingerbase/model/__init__.py @@ -0,0 +1,19 @@ +# +# Project Ginger Base +# +# Copyright IBM, Corp. 2015 +# +# Code derived from Project Kimchi +# 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 diff --git a/src/wok/plugins/gingerbase/model/config.py b/src/wok/plugins/gingerbase/model/config.py new file mode 100644 index 0000000..dc800ec --- /dev/null +++ b/src/wok/plugins/gingerbase/model/config.py @@ -0,0 +1,82 @@ +# +# Project Ginger Base +# +# Copyright IBM, Corp. 2014-2015 +# +# Code derived from Project Kimchi +# 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 wok.basemodel import Singleton +from wok.config import config as kconfig +from wok.config import get_version +from wok.utils import wok_log + +from ..repositories import Repositories +from ..swupdate import SoftwareUpdate +from debugreports import DebugReportsModel + + +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): + # 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): + pass + + def _set_capabilities(self): + wok_log.info("*** Running feature tests ***") + wok_log.info("*** Feature tests completed ***") + _set_capabilities.priority = 90 + + 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 {'system_report_tool': bool(report_tool), + 'update_tool': update_tool, + 'repo_mngt_tool': repo_mngt_tool, + } diff --git a/src/wok/plugins/gingerbase/model/cpuinfo.py b/src/wok/plugins/gingerbase/model/cpuinfo.py new file mode 100644 index 0000000..c581d7d --- /dev/null +++ b/src/wok/plugins/gingerbase/model/cpuinfo.py @@ -0,0 +1,104 @@ +# +# Project Ginger Base +# +# Copyright IBM, Corp. 2014-2015 +# +# Code derived from Project Kimchi +# 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 wok.exception import InvalidParameter, InvalidOperation +from wok.utils import run_command +from ..lscpu import LsCpu + + +ARCH = 'power' if platform.machine().startswith('ppc') else 'x86' + + +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.lscpu = LsCpu() + + 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(self.lscpu.get_sockets()) + self.cores_per_socket = int(self.lscpu.get_cores_per_socket()) + self.cores_present = self.cores_per_socket * self.sockets + self.cores_available = self.cores_present + self.threads_per_core = self.lscpu.get_threads_per_core() + + 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("GGBCPUINF0003E") + if vcpus != sockets * cores * threads: + raise InvalidParameter("GGBCPUINF0002E") + if vcpus > self.cores_available * self.threads_per_core: + raise InvalidParameter("GGBCPUINF0001E") + if threads > self.threads_per_core: + raise InvalidParameter("GGBCPUINF0002E") diff --git a/src/wok/plugins/gingerbase/model/debugreports.py b/src/wok/plugins/gingerbase/model/debugreports.py new file mode 100644 index 0000000..a2d9642 --- /dev/null +++ b/src/wok/plugins/gingerbase/model/debugreports.py @@ -0,0 +1,214 @@ +# +# Project Ginger Base +# +# Copyright IBM, Corp. 2014-2015 +# +# Code derived from Project Kimchi +# 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 wok.exception import InvalidParameter, NotFoundError, OperationFailed +from wok.exception import WokException +from wok.utils import add_task, wok_log +from wok.utils import run_command +from wok.model.tasks import TaskModel + +from wok.plugins.gingerbase import config + + +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("GGBDR0008E", {"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('/plugins/gingerbase/debugreports/%s' % name, + gen_cmd, self.objstore, name) + + raise OperationFailed("GGBDR0002E") + + @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("GGBDR0003E", {'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: + wok_log.error('Debug report file not found. See sosreport ' + 'output for detail:\n%s', output) + fname = (patterns[0] % name).split('/')[-1] + raise OperationFailed('GGBDR0004E', {'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) + wok_log.info(msg) + shutil.move(reportFile, target) + # Deleting md5 + msg = 'Deleting report md5 file: "%s"' % (md5_report_file) + wok_log.info(msg) + with open(md5_report_file) as f: + md5 = f.read().strip() + wok_log.info('Md5 file content: "%s"', md5) + os.remove(md5_report_file) + cb('OK', True) + return + + except WokException 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("GGBDR0005E", {'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: + wok_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("GGBDR0001E", {'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("plugins/gingerbase/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("GGBDR0001E", {'name': name}) + + file_target = file_source.replace(name, params['name']) + if os.path.isfile(file_target): + raise InvalidParameter('GGBDR0008E', {'name': params['name']}) + + shutil.move(file_source, file_target) + wok_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("GGBDR0001E", {'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) diff --git a/src/wok/plugins/gingerbase/model/host.py b/src/wok/plugins/gingerbase/model/host.py new file mode 100644 index 0000000..8a8f686 --- /dev/null +++ b/src/wok/plugins/gingerbase/model/host.py @@ -0,0 +1,427 @@ +# +# Project Ginger Base +# +# Copyright IBM, Corp. 2015 +# +# Code derived from Project Kimchi +# 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 platform +import psutil +import time +from cherrypy.process.plugins import BackgroundTask +from collections import defaultdict +import glob + +from wok.basemodel import Singleton +from wok.exception import InvalidOperation +from wok.exception import OperationFailed +from wok.utils import add_task, wok_log + + +from .. import disks +from ..repositories import Repositories +from ..swupdate import SoftwareUpdate +from debugreports import DebugReportsModel +from wok.model.tasks import TaskModel +from wok.config import config as kconfig + + +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, 'NUM_CPUS'): + cpus = psutil.NUM_CPUS + + 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 + if hasattr(psutil, 'phymem_usage'): + self.host_info['memory'] = psutil.phymem_usage().total + elif hasattr(psutil, 'virtual_memory'): + self.host_info['memory'] = psutil.virtual_memory().total + return self.host_info + + def swupdate(self, *name): + try: + swupdate = SoftwareUpdate() + except: + raise OperationFailed('GGBPKGUPD0004E') + + pkgs = swupdate.getNumOfUpdates() + if pkgs == 0: + raise OperationFailed('GGBPKGUPD0001E') + + wok_log.debug('Host is going to be updated.') + taskid = add_task('/plugins/gingerbase/host/swupdate', + swupdate.doUpdate, + self.objstore, None) + return self.task.lookup(taskid) + + def shutdown(self, args=None): + # Check for running vms before shutdown + # FIXME : Find alternative way to figure out if any vms running + # running_vms = self._get_vms_list_by_state('running') + # if len(running_vms) > 0: + # raise OperationFailed("GGBHOST0001E") + + wok_log.info('Host is going to shutdown.') + os.system('shutdown -h now') + + def reboot(self, args=None): + # Find running VMs + # FIXME : Find alternative way to figure out if any vms running + # running_vms = self._get_vms_list_by_state('running') + # if len(running_vms) > 0: + # raise OperationFailed("GGBHOST0002E") + + wok_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(self.nics() + + self.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) + + def wlans(self): + WLAN_PATH = '/sys/class/net/*/wireless' + return [b.split('/')[-2] for b in glob.glob(WLAN_PATH)] + + # FIXME if we do not want to list usb nic + def nics(self): + NIC_PATH = '/sys/class/net/*/device' + return list(set([b.split('/')[-2] for b in glob.glob(NIC_PATH)]) - + set(self.wlans())) + + +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 CapabilitiesModel(object): + __metaclass__ = Singleton + + def __init__(self, **kargs): + pass + + 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 {'system_report_tool': bool(report_tool), + 'update_tool': update_tool, + 'repo_mngt_tool': repo_mngt_tool, + 'federation': kconfig.get("server", "federation") + } + + +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 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('GGBPKGUPD0004E') + + return self.host_swupdate.getUpdates() + + +class PackageUpdateModel(object): + def __init__(self, **kargs): + pass + + def lookup(self, name): + try: + swupdate = SoftwareUpdate() + except Exception: + raise OperationFailed('GGBPKGUPD0004E') + + 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('GGBREPOS0014E') + + return sorted(self.host_repositories.getRepositories()) + + def create(self, params): + if self.host_repositories is None: + raise InvalidOperation('GGBREPOS0014E') + + 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('GGBREPOS0014E') + + return self._repositories.getRepository(repo_id) + + def enable(self, repo_id): + if self._repositories is None: + raise InvalidOperation('GGBREPOS0014E') + + return self._repositories.enableRepository(repo_id) + + def disable(self, repo_id): + if self._repositories is None: + raise InvalidOperation('GGBREPOS0014E') + + return self._repositories.disableRepository(repo_id) + + def update(self, repo_id, params): + if self._repositories is None: + raise InvalidOperation('GGBREPOS0014E') + + return self._repositories.updateRepository(repo_id, params) + + def delete(self, repo_id): + if self._repositories is None: + raise InvalidOperation('GGBREPOS0014E') + + return self._repositories.removeRepository(repo_id) diff --git a/src/wok/plugins/gingerbase/model/model.py b/src/wok/plugins/gingerbase/model/model.py new file mode 100644 index 0000000..706c65c --- /dev/null +++ b/src/wok/plugins/gingerbase/model/model.py @@ -0,0 +1,54 @@ +# +# Project Ginger Base +# +# Copyright IBM, Corp. 2015 +# +# Code derived from Project Kimchi +# 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 wok import config +from wok.basemodel import BaseModel +from wok.objectstore import ObjectStore +from wok.utils import import_module, listPathModules + + +class Model(BaseModel): + def __init__(self, objstore_loc=None): + + if objstore_loc is None: + objstore_loc = config.get_object_store() + '_gingerbase' + + self.objstore = ObjectStore(objstore_loc) + kargs = {'objstore': self.objstore} + + 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('plugins.gingerbase.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) diff --git a/src/wok/plugins/kimchi/model/debugreports.py b/src/wok/plugins/kimchi/model/debugreports.py deleted file mode 100644 index dcd1b64..0000000 --- a/src/wok/plugins/kimchi/model/debugreports.py +++ /dev/null @@ -1,213 +0,0 @@ -# -# 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 wok.exception import InvalidParameter, NotFoundError, OperationFailed -from wok.exception import WokException -from wok.utils import add_task, wok_log -from wok.utils import run_command -from wok.model.tasks import TaskModel - -from wok.plugins.kimchi import config - - -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('/plugins/kimchi/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: - wok_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) - wok_log.info(msg) - shutil.move(reportFile, target) - # Deleting md5 - msg = 'Deleting report md5 file: "%s"' % (md5_report_file) - wok_log.info(msg) - with open(md5_report_file) as f: - md5 = f.read().strip() - wok_log.info('Md5 file content: "%s"', md5) - os.remove(md5_report_file) - cb('OK', True) - return - - except WokException 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: - wok_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("plugins/kimchi/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) - wok_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) -- 2.1.0

From: chandrureddy <chandra@linux.vnet.ibm.com> --- src/wok/plugins/gingerbase/mockmodel.py | 78 ------ src/wok/plugins/gingerbase/tests/Makefile.am | 50 ++++ src/wok/plugins/gingerbase/tests/run_tests.sh.in | 56 +++++ src/wok/plugins/gingerbase/tests/test_config.py.in | 125 ++++++++++ src/wok/plugins/gingerbase/tests/test_host.py | 153 ++++++++++++ src/wok/plugins/gingerbase/tests/test_model.py | 275 +++++++++++++++++++++ src/wok/plugins/gingerbase/tests/test_rest.py | 184 ++++++++++++++ src/wok/plugins/gingerbase/tests/test_yumparser.py | 164 ++++++++++++ src/wok/plugins/gingerbase/tests/utils.py | 261 +++++++++++++++++++ src/wok/plugins/kimchi/tests/test_yumparser.py | 162 ------------ 10 files changed, 1268 insertions(+), 240 deletions(-) create mode 100644 src/wok/plugins/gingerbase/tests/Makefile.am create mode 100644 src/wok/plugins/gingerbase/tests/run_tests.sh.in create mode 100644 src/wok/plugins/gingerbase/tests/test_config.py.in create mode 100644 src/wok/plugins/gingerbase/tests/test_host.py create mode 100644 src/wok/plugins/gingerbase/tests/test_model.py create mode 100644 src/wok/plugins/gingerbase/tests/test_rest.py create mode 100644 src/wok/plugins/gingerbase/tests/test_yumparser.py create mode 100644 src/wok/plugins/gingerbase/tests/utils.py delete mode 100644 src/wok/plugins/kimchi/tests/test_yumparser.py diff --git a/src/wok/plugins/gingerbase/mockmodel.py b/src/wok/plugins/gingerbase/mockmodel.py index 6af5628..32fc006 100644 --- a/src/wok/plugins/gingerbase/mockmodel.py +++ b/src/wok/plugins/gingerbase/mockmodel.py @@ -41,7 +41,6 @@ class MockModel(Model): # Override osinfo.defaults to ajust the values according to # test:///default driver - self._mock_devices = MockDevices() self._mock_partitions = MockPartitions() self._mock_swupdate = MockSoftwareUpdate() self._mock_repositories = MockRepositories() @@ -175,83 +174,6 @@ class MockPartitions(object): "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 = { diff --git a/src/wok/plugins/gingerbase/tests/Makefile.am b/src/wok/plugins/gingerbase/tests/Makefile.am new file mode 100644 index 0000000..df0bfde --- /dev/null +++ b/src/wok/plugins/gingerbase/tests/Makefile.am @@ -0,0 +1,50 @@ +# +# Ginger Base +# +# Copyright IBM Corp, 2015 +# +# Code derived from Project Kimchi +# 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,[@]wokdir[@],$(pythondir)/wok,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: + ./run_tests.sh + +BUILT_SOURCES = test_config.py +CLEANFILES = run_tests.sh test_config.py diff --git a/src/wok/plugins/gingerbase/tests/run_tests.sh.in b/src/wok/plugins/gingerbase/tests/run_tests.sh.in new file mode 100644 index 0000000..af05499 --- /dev/null +++ b/src/wok/plugins/gingerbase/tests/run_tests.sh.in @@ -0,0 +1,56 @@ +#!/bin/bash +# +# Project Ginger Base +# +# Copyright IBM, Corp. 2013-2015 +# +# Code derived from Project Kimchi +# 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 + +HAVE_UNITTEST=@HAVE_PYMOD_UNITTEST@ +PYTHON_VER=@PYTHON_VERSION@ + +if [ "$1" = "-v" ]; then + OPTS="-v" + shift +else + OPTS="" +fi + +if [ $# -ne 0 ]; then + ARGS="$@" +else + ARGS=`find -name "test_*.py" | xargs -I @ basename @ .py` +fi + +if [ "$HAVE_UNITTEST" != "yes" -o "$PYTHON_VER" == "2.6" ]; then + CMD="unit2" +else + CMD="python -m unittest" +fi + +LIST=($ARGS) +MODEL_LIST=() +MOCK_LIST=() +for ((i=0;i<${#LIST[@]};i++)); do + + if [[ ${LIST[$i]} == test_model* ]]; then + MODEL_LIST+=(${LIST[$i]}) + else + MOCK_LIST+=(${LIST[$i]}) + fi +done + +PYTHONPATH=../plugins:../src:../ $CMD $OPTS ${MODEL_LIST[@]} ${MOCK_LIST[@]} diff --git a/src/wok/plugins/gingerbase/tests/test_config.py.in b/src/wok/plugins/gingerbase/tests/test_config.py.in new file mode 100644 index 0000000..e653685 --- /dev/null +++ b/src/wok/plugins/gingerbase/tests/test_config.py.in @@ -0,0 +1,125 @@ +# +# Project Ginger Base +# +# Copyright IBM, Corp. 2014-2015 +# +# Code derived from Project Kimchi +# 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 cherrypy.lib.reprconf import Parser +from wok.config import Paths + +from wok.plugins.gingerbase.config import GingerBasePaths + +get_prefix = None + + +def setUpModule(): + global get_prefix + get_prefix = Paths.get_prefix + + +def tearDownModule(): + Paths.get_prefix = GingerBasePaths.get_prefix = get_prefix + + +class ConfigTests(unittest.TestCase): + def assertInstalledPath(self, actual, expected): + if '@pkgdatadir@' != '/usr/share/gingerbase': + usr_local = '/usr/local' + if not expected.startswith('/usr'): + expected = usr_local + expected + self.assertEquals(actual, expected) + + def test_installed_plugin_paths(self): + GingerBasePaths.get_prefix = lambda self: '@datadir@/wok' + paths = GingerBasePaths() + self.assertInstalledPath(paths.conf_dir, '/etc/wok/plugins.d') + self.assertInstalledPath(paths.conf_file, + '/etc/wok/plugins.d/gingerbase.conf') + self.assertInstalledPath(paths.src_dir, '@wokdir@/plugins/gingerbase') + self.assertInstalledPath(paths.ui_dir, + '@datadir@/wok/plugins/gingerbase/ui') + self.assertInstalledPath(paths.mo_dir, '@prefix@/share/locale') + + def test_gingerbase_config(self): + Paths.get_prefix = GingerBasePaths.get_prefix = get_prefix + CACHEEXPIRES = 31536000 + SESSIONSTIMEOUT = 10 + configObj = { + '/': { + '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': 'wok', + 'tools.sessions.secure': True, + 'tools.sessions.httponly': True, + 'tools.sessions.locking': 'explicit', + 'tools.sessions.storage_type': 'ram', + 'tools.sessions.timeout': SESSIONSTIMEOUT, + 'tools.wokauth.on': False + }, + '/css': { + 'tools.staticdir.on': True, + 'tools.staticdir.dir': '%s/ui/css' % GingerBasePaths().prefix, + 'tools.expires.on': True, + 'tools.expires.secs': CACHEEXPIRES, + 'tools.nocache.on': False + }, + '/js': { + 'tools.staticdir.on': True, + 'tools.staticdir.dir': '%s/ui/js' % GingerBasePaths().prefix, + 'tools.expires.on': True, + 'tools.expires.secs': CACHEEXPIRES, + 'tools.nocache.on': False + }, + '/libs': { + 'tools.staticdir.on': True, + 'tools.staticdir.dir': '%s/ui/libs' % GingerBasePaths().prefix, + 'tools.expires.on': True, + 'tools.expires.secs': CACHEEXPIRES, + 'tools.nocache.on': False, + }, + '/images': { + 'tools.staticdir.on': True, + 'tools.staticdir.dir': + '%s/ui/images' % GingerBasePaths().prefix, + 'tools.nocache.on': False + }, + '/favicon.ico': { + 'tools.staticfile.on': True, + 'tools.staticfile.filename': + '%s/images/logo.ico' % GingerBasePaths().ui_dir + }, + '/robots.txt': { + 'tools.staticfile.on': True, + 'tools.staticfile.filename': + '%s/robots.txt' % GingerBasePaths().ui_dir + }, + '/help': { + 'tools.staticdir.on': True, + 'tools.staticdir.dir': + '%s/ui/pages/help' % GingerBasePaths().prefix, + 'tools.staticdir.index': 'en_US/index.html', + 'tools.nocache.on': True + } + } + + gingerbase_config = \ + Parser().dict_from_file(GingerBasePaths().conf_file) + self.assertEquals(gingerbase_config, configObj) \ No newline at end of file diff --git a/src/wok/plugins/gingerbase/tests/test_host.py b/src/wok/plugins/gingerbase/tests/test_host.py new file mode 100644 index 0000000..d7cc0a8 --- /dev/null +++ b/src/wok/plugins/gingerbase/tests/test_host.py @@ -0,0 +1,153 @@ +# -*- coding: utf-8 -*- +# +# Project Ginger Base +# +# Copyright IBM, Corp. 2015 +# +# Code derived from Project Kimchi +# 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 platform +import psutil +import tempfile +import time +import unittest +from functools import partial + +from wok.plugins.gingerbase.mockmodel import MockModel +from utils import get_free_port, patch_auth, request, run_server, wait_task + + +test_server = None +model = None +host = None +ssl_port = None +tmpfile = None + + +def setUpModule(): + global test_server, model, host, ssl_port, tmpfile + + patch_auth() + tmpfile = tempfile.mktemp() + model = MockModel(tmpfile) + 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(tmpfile) + + +class HostTests(unittest.TestCase): + def setUp(self): + self.request = partial(request, host, ssl_port) + + def test_hostinfo(self): + resp = self.request('/plugins/gingerbase/host').read() + info = json.loads(resp) + keys = ['os_distro', 'os_version', 'os_codename', 'cpu_model', + 'memory', 'cpus'] + self.assertEquals(sorted(keys), sorted(info.keys())) + + distro, version, codename = platform.linux_distribution() + self.assertEquals(distro, info['os_distro']) + self.assertEquals(version, info['os_version']) + self.assertEquals(unicode(codename, "utf-8"), info['os_codename']) + self.assertEquals(psutil.TOTAL_PHYMEM, info['memory']) + + def test_hoststats(self): + time.sleep(1) + stats_keys = ['cpu_utilization', 'memory', 'disk_read_rate', + 'disk_write_rate', 'net_recv_rate', 'net_sent_rate'] + resp = self.request('/plugins/gingerbase/host/stats').read() + stats = json.loads(resp) + self.assertEquals(sorted(stats_keys), sorted(stats.keys())) + + cpu_utilization = stats['cpu_utilization'] + self.assertIsInstance(cpu_utilization, float) + self.assertGreaterEqual(cpu_utilization, 0.0) + self.assertTrue(cpu_utilization <= 100.0) + + memory_stats = stats['memory'] + self.assertIn('total', memory_stats) + self.assertIn('free', memory_stats) + self.assertIn('cached', memory_stats) + self.assertIn('buffers', memory_stats) + self.assertIn('avail', memory_stats) + + resp = self.request('/plugins/gingerbase/host/stats/history').read() + history = json.loads(resp) + self.assertEquals(sorted(stats_keys), sorted(history.keys())) + + def test_host_actions(self): + def _task_lookup(taskid): + return json.loads(self.request('/plugins/gingerbase/tasks/%s' % + taskid).read()) + + resp = self.request('/plugins/gingerbase/host/shutdown', '{}', 'POST') + self.assertEquals(200, resp.status) + resp = self.request('/plugins/gingerbase/host/reboot', '{}', 'POST') + self.assertEquals(200, resp.status) + + # Test system update + resp = self.request('/plugins/gingerbase/host/packagesupdate', + None, 'GET') + pkgs = json.loads(resp.read()) + self.assertEquals(3, len(pkgs)) + + pkg_keys = ['package_name', 'repository', 'arch', 'version'] + for p in pkgs: + name = p['package_name'] + resp = self.request('/plugins/gingerbase/host/packagesupdate/' + + name, None, 'GET') + info = json.loads(resp.read()) + self.assertEquals(sorted(pkg_keys), sorted(info.keys())) + + resp = self.request('/plugins/gingerbase/host/swupdate', '{}', 'POST') + task = json.loads(resp.read()) + task_params = [u'id', u'message', u'status', u'target_uri'] + self.assertEquals(sorted(task_params), sorted(task.keys())) + + resp = self.request('/tasks/' + task[u'id'], None, 'GET') + task_info = json.loads(resp.read()) + self.assertEquals(task_info['status'], 'running') + wait_task(_task_lookup, task_info['id']) + resp = self.request('/tasks/' + task[u'id'], None, 'GET') + task_info = json.loads(resp.read()) + self.assertEquals(task_info['status'], 'finished') + self.assertIn(u'All packages updated', task_info['message']) + pkgs = model.packagesupdate_get_list() + self.assertEquals(0, len(pkgs)) + + def test_host_partitions(self): + resp = self.request('/plugins/gingerbase/host/partitions') + self.assertEquals(200, resp.status) + partitions = json.loads(resp.read()) + + keys = ['name', 'path', 'type', 'fstype', 'size', 'mountpoint', + 'available'] + for item in partitions: + resp = self.request('/plugins/gingerbase/host/partitions/%s' % + item['name']) + info = json.loads(resp.read()) + self.assertEquals(sorted(info.keys()), sorted(keys)) \ No newline at end of file diff --git a/src/wok/plugins/gingerbase/tests/test_model.py b/src/wok/plugins/gingerbase/tests/test_model.py new file mode 100644 index 0000000..c3d5368 --- /dev/null +++ b/src/wok/plugins/gingerbase/tests/test_model.py @@ -0,0 +1,275 @@ +# -*- coding: utf-8 -*- +# +# Project Ginger Base +# +# Copyright IBM, Corp. 2013-2015 +# +# Code derived from Project Kimchi +# 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 shutil +import unittest + +import wok.objectstore +from wok.basemodel import Singleton +from wok.exception import InvalidParameter, NotFoundError +from wok.rollbackcontext import RollbackContext +from wok.plugins.gingerbase.model import model + +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/gingerbase/tests/' + + +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/gingerbase-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_repository_create(self): + inst = model.Model(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 Ginger Base + # 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(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 Ginger Base + # 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(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 Ginger Base + # 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(wok.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']) \ No newline at end of file diff --git a/src/wok/plugins/gingerbase/tests/test_rest.py b/src/wok/plugins/gingerbase/tests/test_rest.py new file mode 100644 index 0000000..7b65f38 --- /dev/null +++ b/src/wok/plugins/gingerbase/tests/test_rest.py @@ -0,0 +1,184 @@ +# -*- coding: utf-8 -*- +# +# Project Ginger Base +# +# Copyright IBM, Corp. 2013-2015 +# +# Code derived from Project Kimchi +# 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 time +import unittest +from functools import partial + +from wok.rollbackcontext import RollbackContext + +from wok.plugins.gingerbase import mockmodel + +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 + + +def setUpModule(): + global test_server, model, host, port, ssl_port, cherrypy_port + + patch_auth() + model = 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) + + +def tearDownModule(): + test_server.stop() + os.unlink('/tmp/obj-store-test') + + +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_debugreports(self): + resp = request(host, ssl_port, '/plugins/gingerbase/debugreports') + self.assertEquals(200, resp.status) + + def _report_delete(self, name): + request(host, ssl_port, '/plugins/gingerbase/debugreports/%s' % name, + '{}', 'DELETE') + + def test_create_debugreport(self): + req = json.dumps({'name': 'report1'}) + with RollbackContext() as rollback: + resp = request(host, ssl_port, '/plugins/gingerbase/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, + '/plugins/gingerbase/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, + '/plugins/gingerbase/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, '/plugins/gingerbase/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, + '/plugins/gingerbase/debugreports/report1') + debugreport = json.loads(resp.read()) + self.assertEquals("report1", debugreport['name']) + self.assertEquals(200, resp.status) + resp = request(host, ssl_port, + '/plugins/gingerbase/debugreports/report1/content') + self.assertEquals(200, resp.status) + resp = request(host, ssl_port, + '/plugins/gingerbase/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 = '/plugins/gingerbase/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() diff --git a/src/wok/plugins/gingerbase/tests/test_yumparser.py b/src/wok/plugins/gingerbase/tests/test_yumparser.py new file mode 100644 index 0000000..b485b35 --- /dev/null +++ b/src/wok/plugins/gingerbase/tests/test_yumparser.py @@ -0,0 +1,164 @@ +# +# Project Ginger Base +# +# Copyright IBM, Corp. 2015 +# +# Code derived from Project Kimchi +# 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 wok.rollbackcontext import RollbackContext + +from wok.plugins.gingerbase.model import model +from wok.plugins.gingerbase.yumparser \ + import delete_repo_from_file, get_repo_files +from wok.plugins.gingerbase.yumparser import get_yum_packages_list_update +from wok.plugins.gingerbase.yumparser import get_yum_repositories +from wok.plugins.gingerbase.yumparser import write_repo_to_file, YumRepoObject + + +TEMP_REPO_FILE = '' + + +def _is_yum_distro(): + inst = model.Model() + 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), 3) + 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[2].arch, 'i386') diff --git a/src/wok/plugins/gingerbase/tests/utils.py b/src/wok/plugins/gingerbase/tests/utils.py new file mode 100644 index 0000000..51ac782 --- /dev/null +++ b/src/wok/plugins/gingerbase/tests/utils.py @@ -0,0 +1,261 @@ +# +# Project Ginger Base +# +# Copyright IBM, Corp. 2013-2015 +# +# Code derived from Project Kimchi +# 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 threading +import time +import unittest +from contextlib import closing +from lxml import etree + +import wok.server +from wok.config import config, PluginPaths +from wok.auth import User, USER_NAME, USER_GROUPS, USER_ROLES, tabs +from wok.exception import NotFoundError, OperationFailed +from wok.utils import wok_log + +from wok.plugins.gingerbase import mockmodel + + +_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 = wok.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 = 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(PluginPaths('gingerbase').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 mockmodel.fake_user[username] == password + except KeyError, e: + raise OperationFailed("GGBAUTH0001E", {'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": + wok_log.info("Waiting task %s, message: %s", + taskid, task_info['message']) + time.sleep(1) + else: + return + wok_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 = mockmodel.fake_user.items()[0] + hdr = "Basic " + base64.b64encode("%s:%s" % (user, pw)) + headers['AUTHORIZATION'] = hdr + return headers diff --git a/src/wok/plugins/kimchi/tests/test_yumparser.py b/src/wok/plugins/kimchi/tests/test_yumparser.py deleted file mode 100644 index be5e95c..0000000 --- a/src/wok/plugins/kimchi/tests/test_yumparser.py +++ /dev/null @@ -1,162 +0,0 @@ -# -# 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 wok.rollbackcontext import RollbackContext - -from wok.plugins.kimchi.model import model -from wok.plugins.kimchi.yumparser import delete_repo_from_file, get_repo_files -from wok.plugins.kimchi.yumparser import get_yum_packages_list_update -from wok.plugins.kimchi.yumparser import get_yum_repositories -from wok.plugins.kimchi.yumparser import write_repo_to_file, 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), 3) - 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[2].arch, 'i386') -- 2.1.0

From: chandrureddy <chandra@linux.vnet.ibm.com> --- .../plugins/gingerbase/ui/pages/help/Makefile.am | 38 ++++ .../gingerbase/ui/pages/help/de_DE/Makefile.am | 27 +++ .../gingerbase/ui/pages/help/de_DE/host.dita | 49 +++++ .../plugins/gingerbase/ui/pages/help/dita-help.xsl | 26 +++ .../gingerbase/ui/pages/help/en_US/Makefile.am | 27 +++ .../gingerbase/ui/pages/help/en_US/host.dita | 68 +++++++ .../gingerbase/ui/pages/help/es_ES/Makefile.am | 27 +++ .../gingerbase/ui/pages/help/es_ES/host.dita | 49 +++++ .../gingerbase/ui/pages/help/fr_FR/Makefile.am | 27 +++ .../gingerbase/ui/pages/help/fr_FR/host.dita | 65 +++++++ .../gingerbase/ui/pages/help/gingerbase.css | 209 +++++++++++++++++++++ .../gingerbase/ui/pages/help/it_IT/Makefile.am | 27 +++ .../gingerbase/ui/pages/help/it_IT/host.dita | 51 +++++ .../gingerbase/ui/pages/help/ja_JP/Makefile.am | 27 +++ .../gingerbase/ui/pages/help/ja_JP/host.dita | 69 +++++++ .../gingerbase/ui/pages/help/ko_KR/Makefile.am | 27 +++ .../gingerbase/ui/pages/help/ko_KR/host.dita | 51 +++++ .../gingerbase/ui/pages/help/pt_BR/Makefile.am | 27 +++ .../gingerbase/ui/pages/help/pt_BR/host.dita | 72 +++++++ .../gingerbase/ui/pages/help/ru_RU/Makefile.am | 27 +++ .../gingerbase/ui/pages/help/ru_RU/host.dita | 48 +++++ .../gingerbase/ui/pages/help/zh_CN/Makefile.am | 27 +++ .../gingerbase/ui/pages/help/zh_CN/host.dita | 45 +++++ .../gingerbase/ui/pages/help/zh_TW/Makefile.am | 27 +++ .../gingerbase/ui/pages/help/zh_TW/host.dita | 49 +++++ .../plugins/kimchi/ui/pages/help/de_DE/host.dita | 49 ----- .../plugins/kimchi/ui/pages/help/en_US/host.dita | 68 ------- .../plugins/kimchi/ui/pages/help/es_ES/host.dita | 49 ----- .../plugins/kimchi/ui/pages/help/fr_FR/host.dita | 65 ------- .../plugins/kimchi/ui/pages/help/it_IT/host.dita | 51 ----- .../plugins/kimchi/ui/pages/help/ja_JP/host.dita | 69 ------- .../plugins/kimchi/ui/pages/help/ko_KR/host.dita | 51 ----- .../plugins/kimchi/ui/pages/help/pt_BR/host.dita | 72 ------- .../plugins/kimchi/ui/pages/help/ru_RU/host.dita | 48 ----- .../plugins/kimchi/ui/pages/help/zh_CN/host.dita | 45 ----- .../plugins/kimchi/ui/pages/help/zh_TW/host.dita | 49 ----- 36 files changed, 1186 insertions(+), 616 deletions(-) create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/de_DE/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/de_DE/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/dita-help.xsl create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/en_US/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/en_US/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/es_ES/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/es_ES/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/fr_FR/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/fr_FR/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/gingerbase.css create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/it_IT/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/it_IT/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/ja_JP/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/ja_JP/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/ko_KR/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/ko_KR/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/pt_BR/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/pt_BR/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/ru_RU/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/ru_RU/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/zh_CN/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/zh_CN/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/zh_TW/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/zh_TW/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/de_DE/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/en_US/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/es_ES/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/fr_FR/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/it_IT/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/ja_JP/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/ko_KR/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/pt_BR/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/ru_RU/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/zh_CN/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/zh_TW/host.dita diff --git a/src/wok/plugins/gingerbase/ui/pages/help/Makefile.am b/src/wok/plugins/gingerbase/ui/pages/help/Makefile.am new file mode 100644 index 0000000..68b5954 --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/pages/help/Makefile.am @@ -0,0 +1,38 @@ +# +# Ginger Base +# +# Copyright IBM Corp, 2015 +# +# Code derived from Project Kimchi +# 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 = zh_CN it_IT en_US zh_TW pt_BR ja_JP ru_RU ko_KR fr_FR de_DE es_ES + +DITA_HTML_FILES = $(patsubst %.dita,%.html,$(wildcard */*.dita)) +HTML_FILES = $(if $(DITA_HTML_FILES), $(DITA_HTML_FILES), $(wildcard */*.html)) +DITA_XSL_FILE = dita-help.xsl + +EXTRA_DIST = $(DITA_XSL_FILE) + +helpdir = $(datadir)/wok/plugins/gingerbase/ui/pages/help + +dist_help_DATA = gingerbase.css + +all: $(HTML_FILES) $(wildcard */*.dita) + +%.html: %.dita $(DITA_XSL_FILE) + xsltproc -o $@ $(DITA_XSL_FILE) $< + +CLEANFILES = $(HTML_FILES) diff --git a/src/wok/plugins/gingerbase/ui/pages/help/de_DE/Makefile.am b/src/wok/plugins/gingerbase/ui/pages/help/de_DE/Makefile.am new file mode 100644 index 0000000..d343f4d --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/pages/help/de_DE/Makefile.am @@ -0,0 +1,27 @@ +# +# Ginger Base +# +# Copyright IBM Corp, 2015 +# +# Code derived from Project Kimchi +# 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 + +de_DE_helpdir = $(datadir)/wok/plugins/gingerbase/ui/pages/help/de_DE + +dist_de_DE_help_DATA = $(wildcard *.html) $(NULL) + +EXTRA_DIST = $(wildcard *.dita) + +CLEANFILES = $(wildcard *.html) diff --git a/src/wok/plugins/gingerbase/ui/pages/help/de_DE/host.dita b/src/wok/plugins/gingerbase/ui/pages/help/de_DE/host.dita new file mode 100644 index 0000000..9f676df --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/pages/help/de_DE/host.dita @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--Arbortext, Inc., 1988-2011, v.4002--> +<!DOCTYPE cshelp PUBLIC "-//IBM//DTD DITA CSHelp//EN" + "..\dtd\cshelp.dtd"> + + +<!--This DITA specialized document type is not supported by the Authoring Tools development team. +For support please see: +https://w3.opensource.ibm.com/projects/dita-cshelp/--> +<cshelp id="kimhhost" xml:lang="de-de"> +<title>Host</title> +<shortdesc>Die Seite <wintitle>Host</wintitle> zeigt Informationen zum Hostsystem an und ermöglicht Ihnen, den Host herunterzufahren, erneut zu starten und eine Verbindung zu ihm herzustellen.</shortdesc> +<csbody> +<p>Sie können die folgenden Aktionen am Host durchführen:<ul> +<li>Wählen Sie <uicontrol>Herunterfahren</uicontrol> aus, um das Hostsystem herunterzufahren.</li> +<li>Wählen Sie <uicontrol>Erneut starten</uicontrol> aus, um das Hostsystem erneut zu starten.</li> +<li>Wählen Sie <uicontrol>Verbinden</uicontrol> aus, um eine VNC-Verbindung zum Hostsystem herzustellen, wenn noch keine Verbindung besteht.</li> +</ul></p> +<p>Klicken Sie auf die folgenden Abschnitte, um Informationen zum Host anzuzeigen:</p> +<dl><dlentry> +<dt>Basisinformationen</dt> +<dd>Dieser Abschnitt zeigt die Verteilung, die Version und den Codenamen des Hostbetriebssystems sowie den Prozessortyp, die Anzahl der Online-CPUs und die Speicherkapazität in GB an. </dd> +</dlentry><dlentry> +<dt>Systemstatistik</dt> +<dd>Dieser Abschnitt zeigt mithilfe von Grafiken Statistiken für CPU, Speicher, Platten-E/A und Netz-E/A für den Host an. </dd> +</dlentry><dlentry> +<dt>Software-Updates</dt> +<dd>Dieser Abschnitt zeigt Informationen für alle Pakete an, bei denen Aktualisierungen verfügbar sind, einschließlich Paketname, Version, Architektur und Repository. Sie können alle aufgelisteten Pakete aktualisieren, indem Sie <uicontrol>Alle aktualisieren</uicontrol> auswählen. Sie können nicht einzelne Pakete zur Aktualisierung auswählen.</dd> +</dlentry><dlentry> +<dt>Repositorys</dt> +<dd>Dieser Abschnitt zeigt Repositorys an, die dem Hostsystem zugeordnet sind. Sie können Repositorys hinzufügen, aktivieren, bearbeiten oder entfernen. Beim Hinzufügen wird ein Repository dem Hostsystem zugeordnet. Das Aktivieren eines Repositorys dagegen ermöglicht dem Host den Zugriff auf das Repository. Wenn Ihr System Red Hat Enterprise +Linux oder Fedora ist, können Sie <filepath>yum</filepath>-Repositorys hinzufügen. +Wenn Ihr System Ubuntu oder Debian ist, fügen Sie <filepath>deb</filepath>-Repositorys hinzu.<p>Wenn Sie mit yum-Repositorys arbeiten, können Sie eine GPG-Prüfung hinzufügen, um sicherzustellen, dass ein Paket aus diesem Repository nicht beschädigt wurde. +Wählen Sie ein Repository und dann <uicontrol>Bearbeiten</uicontrol> aus. Wählen Sie <uicontrol>Ja</uicontrol> aus, um <uicontrol>GPG-Prüfung</uicontrol> zu aktivieren, und geben Sie dann eine URL zur GPG-Schlüsseldatei für das Repository ein. </p></dd> +</dlentry><dlentry> +<dt>Debugberichte</dt> +<dd>Dieser Abschnitt zeigt Debugberichte, einschließlich Name und Dateipfad, an. +Sie haben die Möglichkeit, einen neuen Bericht zu erstellen oder einen bestehenden Bericht umzubenennen, zu entfernen oder herunterzuladen.<p>Der Debugbericht wird während des Befehls <cmdname>sosreport</cmdname> generiert. Er ist verfügbar für Red Hat Enterprise <tm tmtype="tm" trademark="Linux">Linux</tm>-, Fedora- +und Ubuntu-Verteilungen. Der Befehl generiert eine .tar-Datei, die Konfigurations- und Diagnoseinformationen enthält, wie zum Beispiel Kernelversion, geladene Module sowie System- und Servicekonfigurationdateien. +Der Befehl führt zudem externe Programme aus, um weitere Informationen zu sammeln, und speichert diese Ausgabe im resultierenden Archiv.</p> </dd> +</dlentry></dl> +</csbody> +<?tm 1392659967 1?> +</cshelp> + + +<!-- ENGL1SH_VERS10N 42248_4 DO NOT REMOVE OR CHANGE THIS LINE --> +<!-- T9N_SRC_ID 232 --> +<!-- T9N_SH1P_STR1NG KV310AAP001 1 --> diff --git a/src/wok/plugins/gingerbase/ui/pages/help/dita-help.xsl b/src/wok/plugins/gingerbase/ui/pages/help/dita-help.xsl new file mode 100644 index 0000000..2e66903 --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/pages/help/dita-help.xsl @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns="http://www.w3.org/1999/xhtml"> + <xsl:output method="xml" indent="yes" encoding="UTF-8" /> + + <xsl:template match="/"> + <html> + <head> + <title><xsl:value-of select="/cshelp/title" /></title> + <meta charset="UTF-8" /> + <link rel="shortcut icon" href="../../images/logo.ico" /> + <link rel="stylesheet" type="text/css" href="../gingerbase.css" /> + </head> + <body> + <xsl:apply-templates select="//cshelp" /> + </body> + </html> + </xsl:template> + + <xsl:template match="cshelp"> + <h1><xsl:value-of select="title" /></h1> + <p class="shortdesc"><xsl:value-of select="shortdesc" /></p> + <p class="csbody"><xsl:copy-of select="csbody/node()" /></p> + </xsl:template> +</xsl:stylesheet> diff --git a/src/wok/plugins/gingerbase/ui/pages/help/en_US/Makefile.am b/src/wok/plugins/gingerbase/ui/pages/help/en_US/Makefile.am new file mode 100644 index 0000000..80912ae --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/pages/help/en_US/Makefile.am @@ -0,0 +1,27 @@ +# +# Ginger Base +# +# Copyright IBM Corp, 2015 +# +# Code derived from Project Kimchi +# 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 + +en_US_helpdir = $(datadir)/wok/plugins/gingerbase/ui/pages/help/en_US + +dist_en_US_help_DATA = $(wildcard *.html) $(NULL) + +EXTRA_DIST = $(wildcard *.dita) + +CLEANFILES = $(wildcard *.html) \ No newline at end of file diff --git a/src/wok/plugins/gingerbase/ui/pages/help/en_US/host.dita b/src/wok/plugins/gingerbase/ui/pages/help/en_US/host.dita new file mode 100644 index 0000000..4af3498 --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/pages/help/en_US/host.dita @@ -0,0 +1,68 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--Arbortext, Inc., 1988-2011, v.4002--> +<!DOCTYPE cshelp PUBLIC "-//IBM//DTD DITA CSHelp//EN" + "..\dtd\cshelp.dtd"> +<?Pub Sty _display FontColor="red"?> +<?Pub Inc?> +<!--This DITA specialized document type is not supported by the Authoring Tools development team. +For support please see: +https://w3.opensource.ibm.com/projects/dita-cshelp/--> +<cshelp id="kimhhost" xml:lang="en-us"> +<title>Host</title> +<shortdesc>The <wintitle>Host</wintitle> page shows information about +the host system, and allows you to shut down, restart, and connect +to the host.</shortdesc> +<csbody> +<p>You can perform the following actions on the host:<ul> +<li>Select <uicontrol>Shut down</uicontrol> to shut down the host +system.</li> +<li>Select <uicontrol>Restart</uicontrol> to restart the host system.</li> +<li>Select <uicontrol>Connect</uicontrol> to open a VNC connection +to the host system, if it is not already connected.</li> +</ul></p> +<p>Click the following sections to display information about the host:</p> +<dl><dlentry> +<dt>Basic information</dt> +<dd>This section displays the host operating system distribution, +version, and code name, as well as the processor type, the number +of online CPUs and amount of memory in GB.</dd> +</dlentry><dlentry> +<dt>System statistics</dt> +<dd>This section displays graphs to show statistics for CPU, memory, +disk I/O, and network I/O for the host. </dd> +</dlentry><dlentry> +<dt>Software Updates</dt> +<dd>This section displays information for all of the packages that +have updates available, including package name, version, architecture, +and repository. You can update all of the packages listed by selecting <uicontrol>Update +All</uicontrol>. You cannot select individual packages for updates.</dd> +</dlentry><dlentry> +<dt>Repositories</dt> +<dd>This section displays repositories that are associated with the +host system. You can add, enable, edit, or remove repositories. Adding +a repository associates it with the host system while enabling a repository +allows the host to access it. If your system is Red Hat Enterprise +Linux or Fedora, you can add <filepath>yum</filepath> repositories. +If your system is Ubuntu or Debian, then add <filepath>deb</filepath> repositories.<p>If +you are working with yum repositories, you can add a GPG check to +verify that a package from this repository have not been corrupted. +Select a repository and then <uicontrol>Edit</uicontrol>. Select <uicontrol>Yes</uicontrol> to +enable <uicontrol>GPG Check</uicontrol> and then enter a URL to the +GPG key file for the repository.</p></dd> +</dlentry><dlentry> +<dt>Debug reports</dt> +<dd>This section displays debug reports, including name and file path. +You can select from options to generate a new report, or rename, remove, +or download an existing report.<p>The debug report is generated using +the <cmdname>sosreport</cmdname> command. It is available for Red +Hat Enterprise <tm tmtype="tm" trademark="Linux">Linux</tm>, Fedora, +and Ubuntu distributions. The command generates a .tar file that contains +configuration and diagnostic information, such as the running kernel +version, loaded modules, and system and service configuration files. +The command also runs external programs to collect further information +and stores this output in the resulting archive.</p> </dd> +</dlentry></dl> +</csbody><?Pub Caret -1?> +<?tm 1392659967 1?> +</cshelp> +<?Pub *0000003410?> diff --git a/src/wok/plugins/gingerbase/ui/pages/help/es_ES/Makefile.am b/src/wok/plugins/gingerbase/ui/pages/help/es_ES/Makefile.am new file mode 100644 index 0000000..6e7bad7 --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/pages/help/es_ES/Makefile.am @@ -0,0 +1,27 @@ +# +# Ginger Base +# +# Copyright IBM Corp, 2015 +# +# Code derived from Project Kimchi +# 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 + +es_ES_helpdir = $(datadir)/wok/plugins/gingerbase/ui/pages/help/es_ES + +dist_es_ES_help_DATA = $(wildcard *.html) $(NULL) + +EXTRA_DIST = $(wildcard *.dita) + +CLEANFILES = $(wildcard *.html) diff --git a/src/wok/plugins/gingerbase/ui/pages/help/es_ES/host.dita b/src/wok/plugins/gingerbase/ui/pages/help/es_ES/host.dita new file mode 100644 index 0000000..90f60f8 --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/pages/help/es_ES/host.dita @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--Arbortext, Inc., 1988-2011, v.4002--> +<!DOCTYPE cshelp PUBLIC "-//IBM//DTD DITA CSHelp//EN" + "..\dtd\cshelp.dtd"> + + +<!--This DITA specialized document type is not supported by the Authoring Tools development team. +For support please see: +https://w3.opensource.ibm.com/projects/dita-cshelp/--> +<cshelp id="kimhhost" xml:lang="es-es"> +<title>Host</title> +<shortdesc>La página <wintitle>Host</wintitle> muestra información sobre el sistema host y le permite concluir, reiniciar y conectar con el sistema principal.</shortdesc> +<csbody> +<p>Puede realizar las acciones siguientes en el host:<ul> +<li>Seleccione <uicontrol>Concluir</uicontrol> para concluir el sistema host.</li> +<li>Seleccione <uicontrol>Reiniciar</uicontrol> para reiniciar el sistema host.</li> +<li>Seleccione <uicontrol>Conectar</uicontrol> para abrir una conexión VNC al sistema host, si no está conectado aún.</li> +</ul></p> +<p>Pulse en las secciones siguientes para visualizar información acerca del host:</p> +<dl><dlentry> +<dt>Información básica</dt> +<dd>Esta sección muestra la distribución del sistema operativo de host, la versión, el nombre de código, así como el tipo de procesador, el número de CPU en línea y la cantidad de memoria en GB.</dd> +</dlentry><dlentry> +<dt>Estadísticas del sistema</dt> +<dd>Esta sección muestra gráficos para mostrar estadísticas para CPU, memoria, E/S de disco y E/S de red para el host. </dd> +</dlentry><dlentry> +<dt>Actualizaciones de software</dt> +<dd>En esta sección se muestra información para todos los paquetes que tienen actualizaciones disponibles, incluido el nombre de paquete, versión, arquitectura y repositorio. Puede actualizar todos los paquetes listados seleccionando <uicontrol>Actualizar todo</uicontrol>. No puede seleccionar paquetes individuales para las actualizaciones.</dd> +</dlentry><dlentry> +<dt>Repositorios</dt> +<dd>En esta sección se muestran los repositorios que están asociados con el sistema host. Puede añadir, habilitar, editar o eliminar repositorios. Añadir un repositorio lo asocia con el sistema host mientras que habilitar un repositorio permite que el host acceda a él. Si el sistema es Red Hat Enterprise +Linux o Fedora, puede añadir repositorios <filepath>yum</filepath>. +Si el sistema es Ubuntu o Debian, añada repositorios <filepath>deb</filepath>.<p>Si está trabajando con repositorios yum, puede añadir una comprobación GPG para verificar que un paquete de este repositorio no ha resultado dañado. +Seleccione un repositorio y, a continuación, <uicontrol>Editar</uicontrol>. Seleccione <uicontrol>Sí</uicontrol> para habilitar <uicontrol>Comprobación GPG</uicontrol> y, a continuación, especifique un URL al archivo de claves GPG para el repositorio. </p></dd> +</dlentry><dlentry> +<dt>Informes de depuración</dt> +<dd>En esta sección se muestran informes de depuración, incluido el nombre y la ruta de archivo. +Puede seleccionar entre opciones para generar un informe nuevo, o bien redenominar, eliminar o descargar un informe existente.<p>El informe de depuración se genera utilizando el mandato <cmdname>sosreport</cmdname>. Está disponible para distribuciones de Red +Hat Enterprise <tm tmtype="tm" trademark="Linux">Linux</tm>, Fedora y Ubuntu. El mandato genera un archivo .tar que contiene la información de configuración y de diagnóstico, como la versión de kernel en ejecución, los módulos de carga y los archivos de configuración del sistema y servicio. +El mandato también ejecuta programas externos para recopilar información adicional y almacena esta salida en el archivo resultante.</p> </dd> +</dlentry></dl> +</csbody> +<?tm 1392659967 1?> +</cshelp> + + +<!-- ENGL1SH_VERS10N 42248_4 DO NOT REMOVE OR CHANGE THIS LINE --> +<!-- T9N_SRC_ID 232 --> +<!-- T9N_SH1P_STR1NG KV310AAP001 1 --> diff --git a/src/wok/plugins/gingerbase/ui/pages/help/fr_FR/Makefile.am b/src/wok/plugins/gingerbase/ui/pages/help/fr_FR/Makefile.am new file mode 100644 index 0000000..759d249 --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/pages/help/fr_FR/Makefile.am @@ -0,0 +1,27 @@ +# +# Ginger Base +# +# Copyright IBM Corp, 2015 +# +# Code derived from Project Kimchi +# 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 + +fr_FR_helpdir = $(datadir)/wok/plugins/gingerbase/ui/pages/help/fr_FR + +dist_fr_FR_help_DATA = $(wildcard *.html) $(NULL) + +EXTRA_DIST = $(wildcard *.dita) + +CLEANFILES = $(wildcard *.html) diff --git a/src/wok/plugins/gingerbase/ui/pages/help/fr_FR/host.dita b/src/wok/plugins/gingerbase/ui/pages/help/fr_FR/host.dita new file mode 100644 index 0000000..099d342 --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/pages/help/fr_FR/host.dita @@ -0,0 +1,65 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--Arbortext, Inc., 1988-2011, v.4002--> +<!DOCTYPE cshelp PUBLIC "-//IBM//DTD DITA CSHelp//EN" + "..\dtd\cshelp.dtd"> + + +<!--This DITA specialized document type is not supported by the Authoring Tools development team. +For support please see: +https://w3.opensource.ibm.com/projects/dita-cshelp/--> +<cshelp id="kimhhost" xml:lang="fr-fr"> +<title>Hôte</title> +<shortdesc>La page <wintitle>Hôte</wintitle> affiche des informations +sur le système hôte et vous permet d'arrêter, de redémarrer et de vous +connecter à l'hôte.</shortdesc> +<csbody> +<p>Vous pouvez effectuer les actions suivantes sur l'hôte :<ul> +<li>Sélectionnez <uicontrol>Arrêter</uicontrol> pour arrêter le système hôte.</li> +<li>Sélectionnez <uicontrol>Redémarrer</uicontrol> pour redémarrer le système hôte.</li> +<li>Sélectionnez <uicontrol>Connexion</uicontrol> pour ouvrir une connexion VNC +au système hôte, si celui-ci n'est pas déjà connecté.</li> +</ul></p> +<p>Cliquez sur les sections suivantes pour afficher des informations sur l'hôte :</p> +<dl><dlentry> +<dt>Informations de base</dt> +<dd>Cette section affiche la distribution, la version et le nom de code +du système d'exploitation hôte, ainsi que le type de processeur, le nombre d'UC en ligne et la quantité de mémoire en Go.</dd> +</dlentry><dlentry> +<dt>Statistiques système</dt> +<dd>Cette section affiche les graphiques des statistiques pour l'UC, mémoire, ainsi que +les E-S disque et E-S réseau pour l'hôte. </dd> +</dlentry><dlentry> +<dt>Mises à jour logicielles</dt> +<dd>Cette section affiche des informations pour tous les modules qui +disposent de mises à jour disponibles, y compris le nom de module, la version, l'architecture +et le référentiel. Vous pouvez mettre à jour toutes les modules répertoriés en sélectionnant <uicontrol>Tout +mettre à jour</uicontrol>. Vous ne pouvez pas sélectionner des modules individuels pour les mises à jour.</dd> +</dlentry><dlentry> +<dt>Référentiels</dt> +<dd>Cette section affiche les référentiels associés au système hôte. Vous pouvez ajouter, activer, éditer ou retirer des référentiels. L'ajout d'un référentiel associe celui-ci au système hôte, +tandis que l'activation d'un référentiel permet à l'hôte d'y accéder. Si votre système est Red Hat Enterprise Linux ou Fedora, +vous pouvez ajouter des référentiels <filepath>yum</filepath>. +Si votre système est de type Ubuntu ou Debian, ajoutez des référentiels +<filepath>deb</filepath>.<p>Si vous travaillez avec des référentiels yum, vous pouvez ajouter un contrôle GPG +afin de vérifier qu'un module provenant de ce référentiel n'a pas été endommagé. +Sélectionnez un référentiel puis cliquez sur <uicontrol>Editer</uicontrol>. Sélectionnez <uicontrol>Oui</uicontrol> pour activer <uicontrol>Contrôle GPG</uicontrol>, puis entrez une URL pour le fichier de clés GPG du référentiel.</p></dd> +</dlentry><dlentry> +<dt>Rapports de débogage</dt> +<dd>Cette section affiche les rapports de débogage, y compris le nom et le chemin du fichier. +Vous pouvez faire un choix parmi les options afin de générer un nouveau rapport, ou renommer, supprimer, +ou télécharger un rapport existant.<p>Le rapport de débogage est généré à +l'aide de la commande <cmdname>sosreport</cmdname>. Cette option est disponible pour les distributions +Red Hat Enterprise <tm tmtype="tm" trademark="Linux">Linux</tm>, Fedora et Ubuntu. La commande génère un fichier .tar contenant la configuration et des informations de diagnostic, +telles que la version du noyau d'exécution, les modules chargés, ainsi que les fichiers de configuration +du système et de la maintenance. +La commande exécute également des programmes externes pour collecter des informations +supplémentaires et stocke cette sortie dans l'archive résultante.</p> </dd> +</dlentry></dl> +</csbody> +<?tm 1392659967 1?> +</cshelp> + + +<!-- ENGL1SH_VERS10N 42248_4 DO NOT REMOVE OR CHANGE THIS LINE --> +<!-- T9N_SRC_ID 232 --> +<!-- T9N_SH1P_STR1NG KV310AAP001 1 --> diff --git a/src/wok/plugins/gingerbase/ui/pages/help/gingerbase.css b/src/wok/plugins/gingerbase/ui/pages/help/gingerbase.css new file mode 100644 index 0000000..70c4551 --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/pages/help/gingerbase.css @@ -0,0 +1,209 @@ +/* + * Project Ginger Base + * + * Copyright IBM, Corp. 2015 + * + * Code derived from Project Kimchi + * 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: #FFFFFF; + margin-bottom: 1em; + margin-left: .5em; +} + +bold { + font-weight: bold; +} + +boldItalic { + font-weight: bold; + font-style: italic; +} + +italic { + font-style: italic; +} + +underlined { + text-decoration: underline; +} + +uicontrol { + font-weight: bold; +} + +filepath { + font-family: monospace, monospace; +}.option { + font-family: monospace, monospace; +} + +cmdname { + font-weight: bold; + font-family: monospace, monospace; +} + +.defparmname { + font-weight: bold; + text-decoration: underline; + font-family: monospace, monospace; +} + +.kwd { + font-weight: bold; +} + +.defkwd { + font-weight: bold; + text-decoration: underline; +} + +var { + font-style : italic; +} + +strongwintitle { + font-weight : bold; +} + +parmname { + font-weight: bold; + font-family: monospace, monospace; + white-space: nowrap; +} + +code { + font-family: monospace, monospace; +} + +pre { + font-family: monospace, monospace; +} + +CITE { + font-style: italic; +} + +EM { + font-style: italic; +} + +STRONG { + font-weight: bold; +} + +VAR { + font-style: italic; +} + +dt { + font-weight: bold; +} + +/*********************************************************** + * Basic fonts + ***********************************************************/ +body, +td, +th, +caption { + font-family: Verdana, Arial, Helvetica, sans-serif; + font-size: 10pt; +} + +pre, code { + font-family: MS Courier New, Courier, monospace; +} + +h1, h2, h3 { + font-size: 12pt; + font-weight: bold; + color: #336699; +} + +h4 { + font-size: 10pt; + font-weight: bold; + color: #336699; +} + +/*********************************************************** + * Basic indents, padding, and margin + ***********************************************************/ +body { + color: black; + background-color: white; + margin: 0; + padding-top: 0.2em; + padding-left: 0.6em; + padding-right: 0.2em; + padding-bottom: 1em; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + padding: 0; + margin-top: 1em; + margin-bottom: 0.75em; + margin-left: 0; + margin-right: 0; +} + +address, +dl, +li, +p { + padding: 0; + margin-top: 0.75em; + margin-bottom: 0.75em; + margin-left: 0; + margin-right: 0; + line-height: 125%; +} + +td dl { + margin-left: 2em; +} + +pre { + padding: 0; + margin-top: 0.75em; + margin-bottom: 0.75em; + margin-left: 2em; + margin-right: 0; +} + +ol, +ul { + padding: 0; + margin-top: 0.75em; + margin-bottom: 0.75em; + margin-left: 2.00em; + margin-right: 0; +} + +dd { + margin-left: 3.00em; + margin-top: 0.75em; + margin-bottom: 0.75em; +} + +dt { + margin-left: 1.00em; + margin-top: 0.75em; +} diff --git a/src/wok/plugins/gingerbase/ui/pages/help/it_IT/Makefile.am b/src/wok/plugins/gingerbase/ui/pages/help/it_IT/Makefile.am new file mode 100644 index 0000000..eb88467 --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/pages/help/it_IT/Makefile.am @@ -0,0 +1,27 @@ +# +# Ginger Base +# +# Copyright IBM Corp, 2015 +# +# Code derived from Project Kimchi +# 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 + +it_IT_helpdir = $(datadir)/wok/plugins/gingerbase/ui/pages/help/it_IT + +dist_it_IT_help_DATA = $(wildcard *.html) $(NULL) + +EXTRA_DIST = $(wildcard *.dita) + +CLEANFILES = $(wildcard *.html) diff --git a/src/wok/plugins/gingerbase/ui/pages/help/it_IT/host.dita b/src/wok/plugins/gingerbase/ui/pages/help/it_IT/host.dita new file mode 100644 index 0000000..c2783bf --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/pages/help/it_IT/host.dita @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--Arbortext, Inc., 1988-2011, v.4002--> +<!DOCTYPE cshelp PUBLIC "-//IBM//DTD DITA CSHelp//EN" + "..\dtd\cshelp.dtd"> + + +<!--This DITA specialized document type is not supported by the Authoring Tools development team. +For support please see: +https://w3.opensource.ibm.com/projects/dita-cshelp/--> +<cshelp id="kimhhost" xml:lang="it-it"> +<title>Host</title> +<shortdesc>La pagina <wintitle>Host</wintitle> visualizza le informazioni sul sistema host e consente di arrestarlo, riavviarlo e connettersi ad esso.</shortdesc> +<csbody> +<p>È possibile effettuare le seguenti operazioni sull'host:<ul> +<li>Selezionare <uicontrol>Arresta</uicontrol> per arrestare il sistema host.</li> +<li>Selezionare <uicontrol>Riavvia</uicontrol> per riavviare il sistema host.</li> +<li>Selezionare <uicontrol>Connetti</uicontrol> per aprire una connessione VNC al sistema host, se non è già connesso.</li> +</ul></p> +<p>Fare clic sulle seguenti sezioni per visualizzare le informazioni sull'host:</p> +<dl><dlentry> +<dt>Informazioni di base</dt> +<dd>Questa sezione visualizza il nome codice, la versione e la distribuzione del sistema operativo, come pure il tipo di processore, il numero di CPU in linea e la quantità di memoria in GB.</dd> +</dlentry><dlentry> +<dt>Statistiche di sistema</dt> +<dd>Questa sezione visualizza i grafici che mostrano le statistiche per la CPU, la memoria, l'I/O disco e di rete per l'host. </dd> +</dlentry><dlentry> +<dt>Aggiornamenti del software</dt> +<dd>Questa sezione visualizza le informazioni per tutti i pacchetti per cui sono disponibili gli aggiornamenti, incluso il nome, la versione, l'architettura e il repository del pacchetto. È possibile aggiornare tutti i pacchetti elencati, selezionando <uicontrol>Aggiorna tutto</uicontrol>. Non è possibile selezionare singoli pacchetti per gli aggiornamenti.</dd> +</dlentry><dlentry> +<dt>Repository</dt> +<dd>Questa sezione visualizza i repository associati al sistema host. È possibile aggiungere, abilitare, modificare o rimuovere i repository. L'aggiunta di un repository lo associa al sistema host, mentre l'abilitazione di un repository +consente all'host di accedervi. Se il sistema è Red Hat Enterprise +Linux o Fedora, è possibile aggiungere i repository <filepath>yum</filepath>. +Se il sistema è Ubuntu o Debian, aggiungere i repository <filepath>deb</filepath>.<p>Se si stanno utilizzando i repository yum, è possibile aggiungere un controllo GPG per verificare che un pacchetto da questo repository non sia stato corrotto. +Selezionare un repository, quindi <uicontrol>Modifica</uicontrol>. Selezionare <uicontrol>Sì</uicontrol> per abilitare il <uicontrol>controllo GPG</uicontrol>, quindi immettere un URL al file di chiavi GPG per il +repository.</p></dd> +</dlentry><dlentry> +<dt>Report di debug</dt> +<dd>Questa sezione visualizza i report di debug, incluso il nome e il percorso file. +Le opzioni disponibili consentono di generare un nuovo report oppure ridenominare, rimuovere o scaricare un report esistente.<p>Il report di debug viene generato utilizzando il comando <cmdname>sosreport</cmdname>. È disponibile per le distribuzioni Red +Hat Enterprise <tm tmtype="tm" trademark="Linux">Linux</tm>, Fedora e Ubuntu. Il comando genera un file .tar che contiene informazioni di diagnostica e configurazione, come la versione del kernel in esecuzione, i moduli caricati e i file di configurazione del servizio e del sistema. +Il comando esegue anche programmi esterni per raccogliere ulteriori informazioni e memorizza l'output nell'archivio risultante.</p> </dd> +</dlentry></dl> +</csbody> +<?tm 1392659967 1?> +</cshelp> + + +<!-- ENGL1SH_VERS10N 42248_4 DO NOT REMOVE OR CHANGE THIS LINE --> +<!-- T9N_SRC_ID 232 --> +<!-- T9N_SH1P_STR1NG KV310AAP001 1 --> diff --git a/src/wok/plugins/gingerbase/ui/pages/help/ja_JP/Makefile.am b/src/wok/plugins/gingerbase/ui/pages/help/ja_JP/Makefile.am new file mode 100644 index 0000000..8902470 --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/pages/help/ja_JP/Makefile.am @@ -0,0 +1,27 @@ +# +# Ginger Base +# +# Copyright IBM Corp, 2015 +# +# Code derived from Project Kimchi +# 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 + +ja_JP_helpdir = $(datadir)/wok/plugins/gingerbase/ui/pages/help/ja_JP + +dist_ja_JP_help_DATA = $(wildcard *.html) $(NULL) + +EXTRA_DIST = $(wildcard *.dita) + +CLEANFILES = $(wildcard *.html) diff --git a/src/wok/plugins/gingerbase/ui/pages/help/ja_JP/host.dita b/src/wok/plugins/gingerbase/ui/pages/help/ja_JP/host.dita new file mode 100644 index 0000000..2b9c765 --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/pages/help/ja_JP/host.dita @@ -0,0 +1,69 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--Arbortext, Inc., 1988-2011, v.4002--> +<!DOCTYPE cshelp PUBLIC "-//IBM//DTD DITA CSHelp//EN" + "..\dtd\cshelp.dtd"> + + +<!--This DITA specialized document type is not supported by the Authoring Tools development team. +For support please see: +https://w3.opensource.ibm.com/projects/dita-cshelp/--> +<cshelp id="kimhhost" xml:lang="ja-jp"> +<title>ホスト</title> +<shortdesc><wintitle>「ホスト」</wintitle>ページには、ホスト・システムに関する情報が表示されます。ここで、ホストをシャットダウン、再始動、またホストに接続することができます。 +</shortdesc> +<csbody> +<p>以下のアクションをホストに対して実行できます。 +<ul> +<li>ホスト・システムをシャットダウンするには<uicontrol>「シャットダウン」</uicontrol>を選択します。 +</li> +<li>ホスト・システムを再始動するには<uicontrol>「再始動」</uicontrol>を選択します。 +</li> +<li>ホスト・システムへの VNC 接続を (まだ接続されていない場合に) オープンするには、<uicontrol>「接続」</uicontrol>を選択します。 +</li> +</ul></p> +<p>ホストに関する情報を表示するには、以下の選択項目をクリックしてください。 +</p> +<dl><dlentry> +<dt>基本情報</dt> +<dd>このセクションには、ホスト・オペレーティング・システムのディストリビューション、バージョン、およびコード名、さらにプロセッサー・タイプ、オンライン CPU の数、およびメモリーの量 (GB 単位)が表示されます。 +</dd> +</dlentry><dlentry> +<dt>システム統計情報</dt> +<dd>このセクションには、ホストの CPU、メモリー、ディスク入出力、およびネットワーク入出力の統計情報を表すグラフが表示されます。 +</dd> +</dlentry><dlentry> +<dt>ソフトウェア更新</dt> +<dd>このセクションには、更新が用意されているパッケージすべての情報 +(パッケージ名、バージョン、アーキテクチャー、リポジトリーなど) が表示されます。 +<uicontrol>「すべて更新」</uicontrol>を選択すると、リストされているパッケージすべてを更新できます。 +更新する対象として個別のパッケージを選択することはできません。 +</dd> +</dlentry><dlentry> +<dt>リポジトリー</dt> +<dd>このセクションには、ホスト・システムに関連付けられているリポジトリーが表示されます。 +リポジトリーを追加する、有効にする、編集する、または削除することができます。 +リポジトリーを追加すると、そのリポジトリーがホスト・システムに関連付けられ、リポジトリーを有効にすると、そのリポジトリーにホストがアクセスできるようになります。 +システムが Red Hat Enterprise Linux または Fedora であれば、<filepath>yum</filepath> リポジトリーを追加できます。 +システムが Ubuntu または Debian であれば、<filepath>deb</filepath> リポジトリーを追加してください。 +<p>yum リポジトリーを操作している場合、そのリポジトリーに入っているパッケージが壊れていないことを確認するため、GPG チェックを追加できます。 +リポジトリーを選択し、<uicontrol>「編集」</uicontrol>をクリックしてください。 +<uicontrol>「はい」</uicontrol>を選択して<uicontrol>「GPG チェック」</uicontrol>を有効にしてから、そのリポジトリーの GPG 鍵ファイルの URL を入力してください。 +</p></dd> +</dlentry><dlentry> +<dt>デバッグ・レポート</dt> +<dd>このセクションには、デバッグ・レポート (名前やファイル・パスなど) が表示されます。 +新しいレポートを生成、既存のレポートを名前変更、削除、またはダウンロードするためのオプションを選択できます。 +<p>デバッグ・レポートは、<cmdname>sosreport</cmdname> コマンドで生成されます。 +これは、Red Hat Enterprise <tm tmtype="tm" trademark="Linux">Linux</tm>、Fedora、および Ubuntu ディストリビューションに用意されています。 +このコマンドは、構成および診断情報 (稼働中のカーネルのバージョン、ロードされているモジュール、システムおよびサービス構成ファイルなど) が入った .tar ファイルを生成します。 +このコマンドはまた、外部プログラムを実行して情報をさらに収集し、その出力を結果のアーカイブに保管します。 +</p> </dd> +</dlentry></dl> +</csbody> +<?tm 1392659967 1?> +</cshelp> + + +<!-- ENGL1SH_VERS10N 42248_4 DO NOT REMOVE OR CHANGE THIS LINE --> +<!-- T9N_SRC_ID 232 --> +<!-- T9N_SH1P_STR1NG KV310AAP001 1 --> diff --git a/src/wok/plugins/gingerbase/ui/pages/help/ko_KR/Makefile.am b/src/wok/plugins/gingerbase/ui/pages/help/ko_KR/Makefile.am new file mode 100644 index 0000000..959f17b --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/pages/help/ko_KR/Makefile.am @@ -0,0 +1,27 @@ +# +# Ginger Base +# +# Copyright IBM Corp, 2015 +# +# Code derived from Project Kimchi +# 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 + +ko_KR_helpdir = $(datadir)/wok/plugins/gingerbase/ui/pages/help/ko_KR + +dist_ko_KR_help_DATA = $(wildcard *.html) $(NULL) + +EXTRA_DIST = $(wildcard *.dita) + +CLEANFILES = $(wildcard *.html) diff --git a/src/wok/plugins/gingerbase/ui/pages/help/ko_KR/host.dita b/src/wok/plugins/gingerbase/ui/pages/help/ko_KR/host.dita new file mode 100644 index 0000000..220e166 --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/pages/help/ko_KR/host.dita @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--Arbortext, Inc., 1988-2011, v.4002--> +<!DOCTYPE cshelp PUBLIC "-//IBM//DTD DITA CSHelp//EN" + "..\dtd\cshelp.dtd"> + + +<!--This DITA specialized document type is not supported by the Authoring Tools development team. +For support please see: +https://w3.opensource.ibm.com/projects/dita-cshelp/--> +<cshelp id="kimhhost" xml:lang="ko-kr"> +<title>호스트</title> +<shortdesc><wintitle>호스트</wintitle> 페이지에는 호스트 시스템에 대한 정보가 표시되며 이 페이지를 사용하여 호스트를 종료 및 다시 시작하거나 호스트에 연결할 수 있습니다.</shortdesc> +<csbody> +<p>호스트에 대해 다음 조치를 수행할 수 있습니다.<ul> +<li>호스트 시스템을 종료하려면 <uicontrol>시스템 종료</uicontrol>를 선택합니다.</li> +<li>호스트 시스템을 다시 시작하려면 <uicontrol>다시 시작</uicontrol>을 선택합니다.</li> +<li>이미 연결되어 있지 않은 경우, 호스트 시스템에 대한 VNC 연결을 시작하려면 <uicontrol>연결</uicontrol>을 선택합니다.</li> +</ul></p> +<p>호스트에 대한 정보를 표시하려면 다음 섹션을 클릭하십시오.</p> +<dl><dlentry> +<dt>기본 정보</dt> +<dd>이 섹션에는 호스트 운영 체제 배포, +버전, 코드 이름, 프로세서 유형, 온라인 CPU 수, +메모리 용량(GB) 등이 표시됩니다.</dd> +</dlentry><dlentry> +<dt>시스템 통계</dt> +<dd>이 섹션에는 호스트의 CPU, 메모리, 디스크 I/O, 네트워크 I/O에 대한 통계를 표시하는 그래프가 표시됩니다. </dd> +</dlentry><dlentry> +<dt>소프트웨어 업데이트</dt> +<dd>이 섹션에는 패키지 이름, 버전, 아키텍처, 저장소를 비롯하여 사용 가능한 업데이트가 있는 모든 패키지에 대한 정보가 표시됩니다. <uicontrol>모두 업데이트</uicontrol>를 선택하여 나열된 모든 패키지를 업데이트할 수 있습니다. 업데이트에 대해 개별 패키지를 선택할 수는 없습니다.</dd> +</dlentry><dlentry> +<dt>저장소</dt> +<dd>이 섹션에는 호스트 시스템과 연관된 저장소가 표시됩니다. 저장소를 추가하거나, 사용으로 설정하거나, 편집하거나, 제거할 수 있습니다. 저장소를 추가하면 저장소가 호스트 시스템과 연관되며, 저장소를 사용으로 설정하면 호스트가 저장소에 액세스할 수 있습니다. 해당 시스템이 Red Hat Enterprise Linux 또는 Fedora인 경우, <filepath>yum</filepath> 저장소를 추가할 수 있습니다. +해당 시스템이 Ubuntu 또는 Debian인 경우, <filepath>deb</filepath> 저장소를 추가하십시오.<p>yum 저장소로 작업하는 경우, GPG 검사를 추가하여 이 저장소의 패키지가 손상되지 않았는지 확인할 수 있습니다. +저장소를 선택한 후 <uicontrol>편집</uicontrol>을 선택하십시오. <uicontrol>예</uicontrol>를 선택하여 +<uicontrol>GPG 검사</uicontrol>를 사용으로 설정한 후 +저장소에 대한 GPG 키 파일의 URL을 입력하십시오.</p></dd> +</dlentry><dlentry> +<dt>디버그 보고서</dt> +<dd>이 섹션에는 이름 및 파일 경로를 포함한 디버그 보고서가 표시됩니다. +새 보고서 생성, 기존 보고서 이름 바꾸기, 제거, 다운로드 등의 옵션 중에서 선택할 수 있습니다.<p>디버그 보고서는 <cmdname>sosreport</cmdname> 명령을 사용하여 생성됩니다. 이는 Red Hat Enterprise <tm tmtype="tm" trademark="Linux">Linux</tm>, Fedora 및 Ubuntu 배포에서 사용 가능합니다. 이 명령은 구성 및 진단 정보(예: 실행 중인 커널 버전, 로드된 모듈, 시스템 및 서비스 구성 파일)를 포함하는 .tar 파일을 생성합니다. +또한 이 명령은 외부 프로그램을 실행하여 추가 정보를 수집하고 결과 아카이브에 이 출력을 저장합니다.</p> </dd> +</dlentry></dl> +</csbody> +<?tm 1392659967 1?> +</cshelp> + + +<!-- ENGL1SH_VERS10N 42248_4 DO NOT REMOVE OR CHANGE THIS LINE --> +<!-- T9N_SRC_ID 232 --> +<!-- T9N_SH1P_STR1NG KV310AAP001 1 --> diff --git a/src/wok/plugins/gingerbase/ui/pages/help/pt_BR/Makefile.am b/src/wok/plugins/gingerbase/ui/pages/help/pt_BR/Makefile.am new file mode 100644 index 0000000..d957fdc --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/pages/help/pt_BR/Makefile.am @@ -0,0 +1,27 @@ +# +# Ginger Base +# +# Copyright IBM Corp, 2015 +# +# Code derived from Project Kimchi +# 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 + +pt_BR_helpdir = $(datadir)/wok/plugins/gingerbase/ui/pages/help/pt_BR + +dist_pt_BR_help_DATA = $(wildcard *.html) $(NULL) + +EXTRA_DIST = $(wildcard *.dita) + +CLEANFILES = $(wildcard *.html) diff --git a/src/wok/plugins/gingerbase/ui/pages/help/pt_BR/host.dita b/src/wok/plugins/gingerbase/ui/pages/help/pt_BR/host.dita new file mode 100644 index 0000000..a9814e8 --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/pages/help/pt_BR/host.dita @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--Arbortext, Inc., 1988-2011, v.4002--> +<!DOCTYPE cshelp PUBLIC "-//IBM//DTD DITA CSHelp//EN" + "..\dtd\cshelp.dtd"> + + +<!--This DITA specialized document type is not supported by the Authoring Tools development team. +For support please see: +https://w3.opensource.ibm.com/projects/dita-cshelp/--> +<cshelp id="kimhhost" xml:lang="pt-br"> +<title>Host</title> +<shortdesc>A página <wintitle>Host</wintitle> mostra informações sobre +o sistema host e permite encerrar, reiniciar e conectar +ao host.</shortdesc> +<csbody> +<p>É possível executar as ações a segur no host:<ul> +<li>Selecione <uicontrol>Encerrar</uicontrol> para encerrar o sistema +host.</li> +<li>Selecione <uicontrol>Reiniciar</uicontrol> para reiniciar o sistema host.</li> +<li>Selecione <uicontrol>Conectar</uicontrol> para abrir uma conexão VNC +para o sistema host, se ele já não estiver conectado.</li> +</ul></p> +<p>Clique nas seções a seguir para exibir informações sobre o host:</p> +<dl><dlentry> +<dt>Informações básicas</dt> +<dd>Esta seção exibe a distribuição do sistema operacional do host, +a versão e o nome do código, bem como o tipo de processador, o número de CPUs on-line e a quantia de +memória em GB.</dd> +</dlentry><dlentry> +<dt>Estatísticas do sistema</dt> +<dd>Esta seção exibe gráficos para mostrar estatísticas para CPU, memória, +E/S de disco e E/S de rede para o host. </dd> +</dlentry><dlentry> +<dt>Atualizações de software</dt> +<dd>Esta seção exibe informações de todos os pacotes que +possuem atualizações disponíveis, incluindo nome do pacote, versão, arquitetura +e repositório. É possível atualizar todos os pacotes listados selecionando <uicontrol>Atualizar +todos</uicontrol>. Não é possível selecionar pacotes individuais para atualizações.</dd> +</dlentry><dlentry> +<dt>Repositórios</dt> +<dd>Esta seção exibe repositórios que estão associados ao +sistema host. É possível incluir, ativar, editar ou remover repositórios. Incluir +um repositório o associa com o sistema host enquanto ativar um repositório +permite que o host o acesse. Se o seu sistema for Red Hat Enterprise +Linux ou Fedora, será possível incluir repositórios <filepath>yum</filepath>. +Se o seu sistema for Ubuntu ou Debian, inclua repositórios <filepath>deb</filepath>.<p>Se +você estiver trabalhando com repositórios yum, será possível incluir uma verificação de GPG para +verificar se um pacote desse repositório não foi corrompido. +Selecione um repositório e, em seguida, <uicontrol>Editar</uicontrol>. Selecione <uicontrol>Sim</uicontrol> para +ativar a <uicontrol>Verificação de GPG</uicontrol> e, então, insira uma URL no arquivo-chave de GPG para o +repositório.</p></dd> +</dlentry><dlentry> +<dt>Relatórios de depuração</dt> +<dd>Esta seção exibe relatórios de depuração, incluindo nome e caminho do arquivo. +É possível selecionar a partir das opções para gerar um novo relatório ou renomear, remover +ou fazer o download de um relatório existente.<p>O relatório de depuração é gerado usando +o comando <cmdname>sosreport</cmdname>. Ele está disponível para distribuições +Red Hat Enterprise <tm tmtype="tm" trademark="Linux">Linux</tm>, Fedora +e Ubuntu. O comando gera um arquivo .tar que contém +informações de configuração e de diagnóstico, como versão do kernel +em execução, módulos carregados e arquivos de configuração de sistema e de serviço. +O comando também executa programas externos para coletar informações adicionais +e armazena essa saída no archive resultante.</p> </dd> +</dlentry></dl> +</csbody> +<?tm 1392659967 1?> +</cshelp> + + +<!-- ENGL1SH_VERS10N 42248_4 DO NOT REMOVE OR CHANGE THIS LINE --> +<!-- T9N_SRC_ID 232 --> +<!-- T9N_SH1P_STR1NG KV310AAP001 1 --> diff --git a/src/wok/plugins/gingerbase/ui/pages/help/ru_RU/Makefile.am b/src/wok/plugins/gingerbase/ui/pages/help/ru_RU/Makefile.am new file mode 100644 index 0000000..d18dce7 --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/pages/help/ru_RU/Makefile.am @@ -0,0 +1,27 @@ +# +# Ginger Base +# +# Copyright IBM Corp, 2015 +# +# Code derived from Project Kimchi +# 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 + +ru_RU_helpdir = $(datadir)/wok/plugins/gingerbase/ui/pages/help/ru_RU + +dist_ru_RU_help_DATA = $(wildcard *.html) $(NULL) + +EXTRA_DIST = $(wildcard *.dita) + +CLEANFILES = $(wildcard *.html) diff --git a/src/wok/plugins/gingerbase/ui/pages/help/ru_RU/host.dita b/src/wok/plugins/gingerbase/ui/pages/help/ru_RU/host.dita new file mode 100644 index 0000000..54a78f5 --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/pages/help/ru_RU/host.dita @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--Arbortext, Inc., 1988-2011, v.4002--> +<!DOCTYPE cshelp PUBLIC "-//IBM//DTD DITA CSHelp//EN" + "..\dtd\cshelp.dtd"> + + +<!--This DITA specialized document type is not supported by the Authoring Tools development team. +For support please see: +https://w3.opensource.ibm.com/projects/dita-cshelp/--> +<cshelp id="kimhhost" xml:lang="ru-ru"> +<title>Хост</title> +<shortdesc>Страница <wintitle>Хост</wintitle> показывает информацию о системе хоста и позволяет останавливать хост, перезапускать хост и подключаться к нему.</shortdesc> +<csbody> +<p>На хосте можно выполнять следующие действия:<ul> +<li><uicontrol>Завершить работу</uicontrol> - остановить систему хоста.</li> +<li><uicontrol>Перезапустить</uicontrol> - перезапустить систему хоста.</li> +<li><uicontrol>Подключиться</uicontrol> - открыть соединение VNC с системой хоста, если оно еще не установлено.</li> +</ul></p> +<p>Щелкните на следующих разделах для просмотра информации о хосте:</p> +<dl><dlentry> +<dt>Базовая информация</dt> +<dd>В этом разделе показывается вариант операционной системы, его версия и кодовое имя, а также тип процессора, число подключенных процессоров и объем памяти в ГБ.</dd> +</dlentry><dlentry> +<dt>Системная статистика</dt> +<dd>В этом разделе показываются графики, отражающие статистическую информацию о процессоре, памяти, дисковом вводе-выводе и сетевом вводе-выводе для хоста. </dd> +</dlentry><dlentry> +<dt>Обновления программного обеспечения</dt> +<dd>В этом разделе показывается информация обо всех пакетах, для которых доступны обновления, включая имя пакета, версию, архитектуру и хранилище. Можно обновить все пакеты в списке щелчком на <uicontrol>Обновить все</uicontrol>. Отдельные пакеты для обновления выбрать нельзя.</dd> +</dlentry><dlentry> +<dt>Хранилища</dt> +<dd>В этом разделе показываются хранилища, связанные с системой хоста. Хранилища можно добавлять, активировать, изменять и удалять. При добавлении хранилище связывается с системой хоста, при активации хранилище становится доступным для хоста. Если система - Red Hat Enterprise Linux или Fedora, можно добавить хранилища <filepath>yum</filepath>. +Если система - Ubuntu или Debian, добавьте хранилища <filepath>deb</filepath>.<p>При работе с хранилищами yum можно добавить проверку GPG для проверки целостности пакетов из данного хранилища. +Выберите хранилище и щелкните на <uicontrol>Изменить</uicontrol>. Выберите <uicontrol>Да</uicontrol>, чтобы включить <uicontrol>Проверку GPG</uicontrol>, и введите URL файла ключей GPG для хранилища.</p></dd> +</dlentry><dlentry> +<dt>Отладочные отчеты</dt> +<dd>В этом разделе показываются отладочные отчеты, включая имя и путь. +Доступны команды для создания, переименования, удаления и загрузки отчетов.<p>Отладочный отчет создается командой <cmdname>sosreport</cmdname>. Он доступен для Red +Hat Enterprise <tm tmtype="tm" trademark="Linux">Linux</tm>, Fedora и Ubuntu. Команда создает файл .tar с конфигурационной и диагностической информацией, такой как версия ядра, загруженные модули и файлы конфигурации системы и служб. +Команда также выполняет внешние программы для сбора дополнительной информации и сохраняет их вывод в результирующем архиве.</p> </dd> +</dlentry></dl> +</csbody> +<?tm 1392659967 1?> +</cshelp> + + +<!-- ENGL1SH_VERS10N 42248_4 DO NOT REMOVE OR CHANGE THIS LINE --> +<!-- T9N_SRC_ID 232 --> +<!-- T9N_SH1P_STR1NG KV310AAP001 1 --> diff --git a/src/wok/plugins/gingerbase/ui/pages/help/zh_CN/Makefile.am b/src/wok/plugins/gingerbase/ui/pages/help/zh_CN/Makefile.am new file mode 100644 index 0000000..5fb1e83 --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/pages/help/zh_CN/Makefile.am @@ -0,0 +1,27 @@ +# +# Ginger Base +# +# Copyright IBM Corp, 2015 +# +# Code derived from Project Kimchi +# 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 + +zh_CN_helpdir = $(datadir)/wok/plugins/gingerbase/ui/pages/help/zh_CN + +dist_zh_CN_help_DATA = $(wildcard *.html) $(NULL) + +EXTRA_DIST = $(wildcard *.dita) + +CLEANFILES = $(wildcard *.html) diff --git a/src/wok/plugins/gingerbase/ui/pages/help/zh_CN/host.dita b/src/wok/plugins/gingerbase/ui/pages/help/zh_CN/host.dita new file mode 100644 index 0000000..a8622a2 --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/pages/help/zh_CN/host.dita @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--Arbortext, Inc., 1988-2011, v.4002--> +<!DOCTYPE cshelp PUBLIC "-//IBM//DTD DITA CSHelp//EN" + "..\dtd\cshelp.dtd"> + + +<!--This DITA specialized document type is not supported by the Authoring Tools development team. +For support please see: +https://w3.opensource.ibm.com/projects/dita-cshelp/--> +<cshelp id="kimhhost" xml:lang="zh-cn"> +<title>主机</title> +<shortdesc>“<wintitle>主机</wintitle>”页面显示有关主机系统的信息,并且允许您对主机进行关闭、启动和连接。</shortdesc> +<csbody> +<p>可对主机执行以下操作:<ul> +<li>选择<uicontrol>关闭</uicontrol>以关闭主机系统。</li> +<li>选择<uicontrol>重新启动</uicontrol>以重新启动主机系统。</li> +<li>选择<uicontrol>连接</uicontrol>以打开与主机系统的 VNC 连接(如果尚未连接)。</li> +</ul></p> +<p>单击以下部分以显示有关主机的信息:</p> +<dl><dlentry> +<dt>基本信息</dt> +<dd>本部分显示主机操作系统分发版、版本和代码名称以及处理器类型、联机 CPU 的数目和内存量(以 GB 计)。</dd> +</dlentry><dlentry> +<dt>系统统计信息</dt> +<dd>本部分显示图形,以显示主机有关 CPU、内存、磁盘 I/O 和网络 I/O 的统计信息。</dd> +</dlentry><dlentry> +<dt>软件更新</dt> +<dd>本部分显示有更新可用的所有软件包的信息,其中包括软件包名称、版本、体系结构和存储库。可通过选择<uicontrol>全部更新</uicontrol>来更新所列示的所有软件包。不能针对更新选择各个软件包。</dd> +</dlentry><dlentry> +<dt>存储库</dt> +<dd>本部分显示与主机系统关联的存储库。您可以添加、启用、编辑或除去存储库。当启用存储库会允许主机对其进行访问时,添加存储库会将其与主机系统关联。如果您的系统为 Red Hat Enterprise Linux 或 Fedora,那么可添加 <filepath>yum</filepath> 存储库。如果您的系统为 Ubuntu 或 Debian,那么请添加 <filepath>deb</filepath> 存储库。<p>如果要处理 Yum 存储库,您可以添加 GPG 检查以验证此存储库中的软件包是否已损坏。选择一个存储库,然后选择<uicontrol>编辑</uicontrol>。选择<uicontrol>是</uicontrol>以启用 <uicontrol>GPG 检查</uicontrol>,然后输入存储库的 GPG 密钥文件的 URL。</p></dd> +</dlentry><dlentry> +<dt>调试报告</dt> +<dd>本部分显示调试报告,其中包括名称和文件路径。您可以从选项中进行选择以生成新报告,或者对现有报告进行重命名、除去或下载。<p>调试报告将使用 +<cmdname>sosreport</cmdname> 命令生成。该报告可用于 Red +Hat Enterprise <tm tmtype="tm" trademark="Linux">Linux</tm>、Fedora 和 Ubuntu 分发版。该命令将生成包含配置和诊断信息的 .tar 文件,例如,正在运行的内核版本、已装入的模块以及系统和服务配置文件。该命令还会运行外部程序以收集更多信息并将此输出存储在生成的归档中。</p> </dd> +</dlentry></dl> +</csbody> +<?tm 1392659967 1?> +</cshelp> + + +<!-- ENGL1SH_VERS10N 42248_4 DO NOT REMOVE OR CHANGE THIS LINE --> +<!-- T9N_SRC_ID 232 --> +<!-- T9N_SH1P_STR1NG KV310AAP001 1 --> diff --git a/src/wok/plugins/gingerbase/ui/pages/help/zh_TW/Makefile.am b/src/wok/plugins/gingerbase/ui/pages/help/zh_TW/Makefile.am new file mode 100644 index 0000000..360d7e1 --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/pages/help/zh_TW/Makefile.am @@ -0,0 +1,27 @@ +# +# Ginger Base +# +# Copyright IBM Corp, 2015 +# +# Code derived from Project Kimchi +# 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 + +zh_TW_helpdir = $(datadir)/wok/plugins/gingerbase/ui/pages/help/zh_TW + +dist_zh_TW_help_DATA = $(wildcard *.html) $(NULL) + +EXTRA_DIST = $(wildcard *.dita) + +CLEANFILES = $(wildcard *.html) diff --git a/src/wok/plugins/gingerbase/ui/pages/help/zh_TW/host.dita b/src/wok/plugins/gingerbase/ui/pages/help/zh_TW/host.dita new file mode 100644 index 0000000..550945e --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/pages/help/zh_TW/host.dita @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--Arbortext, Inc., 1988-2011, v.4002--> +<!DOCTYPE cshelp PUBLIC "-//IBM//DTD DITA CSHelp//EN" + "..\dtd\cshelp.dtd"> + + +<!--This DITA specialized document type is not supported by the Authoring Tools development team. +For support please see: +https://w3.opensource.ibm.com/projects/dita-cshelp/--> +<cshelp id="kimhhost" xml:lang="zh-tw"> +<title>主機</title> +<shortdesc>「<wintitle>主機</wintitle>」頁面會顯示主機系統的相關資訊,並容許您關閉、重新啟動以及連接到主機。</shortdesc> +<csbody> +<p>您可以針對主機執行下列動作:<ul> +<li>選取<uicontrol>關閉</uicontrol>以關閉主機系統。</li> +<li>選取<uicontrol>重新啟動</uicontrol>以重新啟動主機系統。</li> +<li>選取<uicontrol>連接</uicontrol>以開啟與主機系統的 VNC 連線(如果尚未連線到主機系統)。</li> +</ul></p> +<p>按一下下列區段以顯示主機的相關資訊:</p> +<dl><dlentry> +<dt>基本資訊</dt> +<dd>此區段會顯示主機作業系統發行套件、版本、程式碼名稱以及處理器類型、線上 CPU 數目和記憶體數量 (GB)。</dd> +</dlentry><dlentry> +<dt>系統統計資料</dt> +<dd>此區段會顯示一些圖形,以顯示主機的 CPU、記憶體、磁碟 I/O 和網路 I/O 的統計資料。</dd> +</dlentry><dlentry> +<dt>軟體更新</dt> +<dd>此區段會顯示具有可用更新的所有套件的相關資訊,包括套件名稱、版本、架構和儲存庫。您可以透過選取<uicontrol>全部更新</uicontrol>來更新所有列出的套件。不能選取個別套件以進行更新。</dd> +</dlentry><dlentry> +<dt>儲存庫</dt> +<dd>此區段會顯示與主機系統相關聯的儲存庫。您可以新增、啟用、編輯或移除儲存庫。新增儲存庫可使它與主機系統相關聯,而啟用儲存庫則容許主機存取儲存庫。如果您的系統是 +Red Hat Enterprise Linux 或 Fedora,則可以新增 <filepath>yum</filepath> 儲存庫。如果您的系統是 +Ubuntu 或 Debian,則可以新增 <filepath>deb</filepath> 儲存庫。<p>如果您正在使用 +yum 儲存庫,則可以新增 GPG 檢查以驗證此儲存庫中的某個套件是否未毀損。選取儲存庫,然後選取<uicontrol>編輯</uicontrol>。選取<uicontrol>是</uicontrol>以啟用 <uicontrol>GPG 檢查</uicontrol>,然後輸入儲存庫的 GPG 金鑰檔的 URL。</p></dd> +</dlentry><dlentry> +<dt>除錯報告</dt> +<dd>此區段顯示除錯報告,包括名稱和檔案路徑。您可以選取選項以產生新報告、或是重新命名、移除或下載現有報告。<p>除錯報告是使用 +<cmdname>sosreport</cmdname> 指令產生的。該指令可用於 Red +Hat Enterprise <tm tmtype="tm" trademark="Linux">Linux</tm>、Fedora +及 Ubuntu 發行套件。該指令會產生 .tar 檔案,其包含配置與診斷資訊,例如執行中的核心版本、已載入模組以及系統和服務配置檔案。該指令還會執行外部程式來收集更多資訊並將此輸出儲存在產生的保存檔中。</p> </dd> +</dlentry></dl> +</csbody> +<?tm 1392659967 1?> +</cshelp> + + +<!-- ENGL1SH_VERS10N 42248_4 DO NOT REMOVE OR CHANGE THIS LINE --> +<!-- T9N_SRC_ID 232 --> +<!-- T9N_SH1P_STR1NG KV310AAP001 1 --> diff --git a/src/wok/plugins/kimchi/ui/pages/help/de_DE/host.dita b/src/wok/plugins/kimchi/ui/pages/help/de_DE/host.dita deleted file mode 100644 index 9f676df..0000000 --- a/src/wok/plugins/kimchi/ui/pages/help/de_DE/host.dita +++ /dev/null @@ -1,49 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!--Arbortext, Inc., 1988-2011, v.4002--> -<!DOCTYPE cshelp PUBLIC "-//IBM//DTD DITA CSHelp//EN" - "..\dtd\cshelp.dtd"> - - -<!--This DITA specialized document type is not supported by the Authoring Tools development team. -For support please see: -https://w3.opensource.ibm.com/projects/dita-cshelp/--> -<cshelp id="kimhhost" xml:lang="de-de"> -<title>Host</title> -<shortdesc>Die Seite <wintitle>Host</wintitle> zeigt Informationen zum Hostsystem an und ermöglicht Ihnen, den Host herunterzufahren, erneut zu starten und eine Verbindung zu ihm herzustellen.</shortdesc> -<csbody> -<p>Sie können die folgenden Aktionen am Host durchführen:<ul> -<li>Wählen Sie <uicontrol>Herunterfahren</uicontrol> aus, um das Hostsystem herunterzufahren.</li> -<li>Wählen Sie <uicontrol>Erneut starten</uicontrol> aus, um das Hostsystem erneut zu starten.</li> -<li>Wählen Sie <uicontrol>Verbinden</uicontrol> aus, um eine VNC-Verbindung zum Hostsystem herzustellen, wenn noch keine Verbindung besteht.</li> -</ul></p> -<p>Klicken Sie auf die folgenden Abschnitte, um Informationen zum Host anzuzeigen:</p> -<dl><dlentry> -<dt>Basisinformationen</dt> -<dd>Dieser Abschnitt zeigt die Verteilung, die Version und den Codenamen des Hostbetriebssystems sowie den Prozessortyp, die Anzahl der Online-CPUs und die Speicherkapazität in GB an. </dd> -</dlentry><dlentry> -<dt>Systemstatistik</dt> -<dd>Dieser Abschnitt zeigt mithilfe von Grafiken Statistiken für CPU, Speicher, Platten-E/A und Netz-E/A für den Host an. </dd> -</dlentry><dlentry> -<dt>Software-Updates</dt> -<dd>Dieser Abschnitt zeigt Informationen für alle Pakete an, bei denen Aktualisierungen verfügbar sind, einschließlich Paketname, Version, Architektur und Repository. Sie können alle aufgelisteten Pakete aktualisieren, indem Sie <uicontrol>Alle aktualisieren</uicontrol> auswählen. Sie können nicht einzelne Pakete zur Aktualisierung auswählen.</dd> -</dlentry><dlentry> -<dt>Repositorys</dt> -<dd>Dieser Abschnitt zeigt Repositorys an, die dem Hostsystem zugeordnet sind. Sie können Repositorys hinzufügen, aktivieren, bearbeiten oder entfernen. Beim Hinzufügen wird ein Repository dem Hostsystem zugeordnet. Das Aktivieren eines Repositorys dagegen ermöglicht dem Host den Zugriff auf das Repository. Wenn Ihr System Red Hat Enterprise -Linux oder Fedora ist, können Sie <filepath>yum</filepath>-Repositorys hinzufügen. -Wenn Ihr System Ubuntu oder Debian ist, fügen Sie <filepath>deb</filepath>-Repositorys hinzu.<p>Wenn Sie mit yum-Repositorys arbeiten, können Sie eine GPG-Prüfung hinzufügen, um sicherzustellen, dass ein Paket aus diesem Repository nicht beschädigt wurde. -Wählen Sie ein Repository und dann <uicontrol>Bearbeiten</uicontrol> aus. Wählen Sie <uicontrol>Ja</uicontrol> aus, um <uicontrol>GPG-Prüfung</uicontrol> zu aktivieren, und geben Sie dann eine URL zur GPG-Schlüsseldatei für das Repository ein. </p></dd> -</dlentry><dlentry> -<dt>Debugberichte</dt> -<dd>Dieser Abschnitt zeigt Debugberichte, einschließlich Name und Dateipfad, an. -Sie haben die Möglichkeit, einen neuen Bericht zu erstellen oder einen bestehenden Bericht umzubenennen, zu entfernen oder herunterzuladen.<p>Der Debugbericht wird während des Befehls <cmdname>sosreport</cmdname> generiert. Er ist verfügbar für Red Hat Enterprise <tm tmtype="tm" trademark="Linux">Linux</tm>-, Fedora- -und Ubuntu-Verteilungen. Der Befehl generiert eine .tar-Datei, die Konfigurations- und Diagnoseinformationen enthält, wie zum Beispiel Kernelversion, geladene Module sowie System- und Servicekonfigurationdateien. -Der Befehl führt zudem externe Programme aus, um weitere Informationen zu sammeln, und speichert diese Ausgabe im resultierenden Archiv.</p> </dd> -</dlentry></dl> -</csbody> -<?tm 1392659967 1?> -</cshelp> - - -<!-- ENGL1SH_VERS10N 42248_4 DO NOT REMOVE OR CHANGE THIS LINE --> -<!-- T9N_SRC_ID 232 --> -<!-- T9N_SH1P_STR1NG KV310AAP001 1 --> diff --git a/src/wok/plugins/kimchi/ui/pages/help/en_US/host.dita b/src/wok/plugins/kimchi/ui/pages/help/en_US/host.dita deleted file mode 100644 index 4af3498..0000000 --- a/src/wok/plugins/kimchi/ui/pages/help/en_US/host.dita +++ /dev/null @@ -1,68 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!--Arbortext, Inc., 1988-2011, v.4002--> -<!DOCTYPE cshelp PUBLIC "-//IBM//DTD DITA CSHelp//EN" - "..\dtd\cshelp.dtd"> -<?Pub Sty _display FontColor="red"?> -<?Pub Inc?> -<!--This DITA specialized document type is not supported by the Authoring Tools development team. -For support please see: -https://w3.opensource.ibm.com/projects/dita-cshelp/--> -<cshelp id="kimhhost" xml:lang="en-us"> -<title>Host</title> -<shortdesc>The <wintitle>Host</wintitle> page shows information about -the host system, and allows you to shut down, restart, and connect -to the host.</shortdesc> -<csbody> -<p>You can perform the following actions on the host:<ul> -<li>Select <uicontrol>Shut down</uicontrol> to shut down the host -system.</li> -<li>Select <uicontrol>Restart</uicontrol> to restart the host system.</li> -<li>Select <uicontrol>Connect</uicontrol> to open a VNC connection -to the host system, if it is not already connected.</li> -</ul></p> -<p>Click the following sections to display information about the host:</p> -<dl><dlentry> -<dt>Basic information</dt> -<dd>This section displays the host operating system distribution, -version, and code name, as well as the processor type, the number -of online CPUs and amount of memory in GB.</dd> -</dlentry><dlentry> -<dt>System statistics</dt> -<dd>This section displays graphs to show statistics for CPU, memory, -disk I/O, and network I/O for the host. </dd> -</dlentry><dlentry> -<dt>Software Updates</dt> -<dd>This section displays information for all of the packages that -have updates available, including package name, version, architecture, -and repository. You can update all of the packages listed by selecting <uicontrol>Update -All</uicontrol>. You cannot select individual packages for updates.</dd> -</dlentry><dlentry> -<dt>Repositories</dt> -<dd>This section displays repositories that are associated with the -host system. You can add, enable, edit, or remove repositories. Adding -a repository associates it with the host system while enabling a repository -allows the host to access it. If your system is Red Hat Enterprise -Linux or Fedora, you can add <filepath>yum</filepath> repositories. -If your system is Ubuntu or Debian, then add <filepath>deb</filepath> repositories.<p>If -you are working with yum repositories, you can add a GPG check to -verify that a package from this repository have not been corrupted. -Select a repository and then <uicontrol>Edit</uicontrol>. Select <uicontrol>Yes</uicontrol> to -enable <uicontrol>GPG Check</uicontrol> and then enter a URL to the -GPG key file for the repository.</p></dd> -</dlentry><dlentry> -<dt>Debug reports</dt> -<dd>This section displays debug reports, including name and file path. -You can select from options to generate a new report, or rename, remove, -or download an existing report.<p>The debug report is generated using -the <cmdname>sosreport</cmdname> command. It is available for Red -Hat Enterprise <tm tmtype="tm" trademark="Linux">Linux</tm>, Fedora, -and Ubuntu distributions. The command generates a .tar file that contains -configuration and diagnostic information, such as the running kernel -version, loaded modules, and system and service configuration files. -The command also runs external programs to collect further information -and stores this output in the resulting archive.</p> </dd> -</dlentry></dl> -</csbody><?Pub Caret -1?> -<?tm 1392659967 1?> -</cshelp> -<?Pub *0000003410?> diff --git a/src/wok/plugins/kimchi/ui/pages/help/es_ES/host.dita b/src/wok/plugins/kimchi/ui/pages/help/es_ES/host.dita deleted file mode 100644 index 90f60f8..0000000 --- a/src/wok/plugins/kimchi/ui/pages/help/es_ES/host.dita +++ /dev/null @@ -1,49 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!--Arbortext, Inc., 1988-2011, v.4002--> -<!DOCTYPE cshelp PUBLIC "-//IBM//DTD DITA CSHelp//EN" - "..\dtd\cshelp.dtd"> - - -<!--This DITA specialized document type is not supported by the Authoring Tools development team. -For support please see: -https://w3.opensource.ibm.com/projects/dita-cshelp/--> -<cshelp id="kimhhost" xml:lang="es-es"> -<title>Host</title> -<shortdesc>La página <wintitle>Host</wintitle> muestra información sobre el sistema host y le permite concluir, reiniciar y conectar con el sistema principal.</shortdesc> -<csbody> -<p>Puede realizar las acciones siguientes en el host:<ul> -<li>Seleccione <uicontrol>Concluir</uicontrol> para concluir el sistema host.</li> -<li>Seleccione <uicontrol>Reiniciar</uicontrol> para reiniciar el sistema host.</li> -<li>Seleccione <uicontrol>Conectar</uicontrol> para abrir una conexión VNC al sistema host, si no está conectado aún.</li> -</ul></p> -<p>Pulse en las secciones siguientes para visualizar información acerca del host:</p> -<dl><dlentry> -<dt>Información básica</dt> -<dd>Esta sección muestra la distribución del sistema operativo de host, la versión, el nombre de código, así como el tipo de procesador, el número de CPU en línea y la cantidad de memoria en GB.</dd> -</dlentry><dlentry> -<dt>Estadísticas del sistema</dt> -<dd>Esta sección muestra gráficos para mostrar estadísticas para CPU, memoria, E/S de disco y E/S de red para el host. </dd> -</dlentry><dlentry> -<dt>Actualizaciones de software</dt> -<dd>En esta sección se muestra información para todos los paquetes que tienen actualizaciones disponibles, incluido el nombre de paquete, versión, arquitectura y repositorio. Puede actualizar todos los paquetes listados seleccionando <uicontrol>Actualizar todo</uicontrol>. No puede seleccionar paquetes individuales para las actualizaciones.</dd> -</dlentry><dlentry> -<dt>Repositorios</dt> -<dd>En esta sección se muestran los repositorios que están asociados con el sistema host. Puede añadir, habilitar, editar o eliminar repositorios. Añadir un repositorio lo asocia con el sistema host mientras que habilitar un repositorio permite que el host acceda a él. Si el sistema es Red Hat Enterprise -Linux o Fedora, puede añadir repositorios <filepath>yum</filepath>. -Si el sistema es Ubuntu o Debian, añada repositorios <filepath>deb</filepath>.<p>Si está trabajando con repositorios yum, puede añadir una comprobación GPG para verificar que un paquete de este repositorio no ha resultado dañado. -Seleccione un repositorio y, a continuación, <uicontrol>Editar</uicontrol>. Seleccione <uicontrol>Sí</uicontrol> para habilitar <uicontrol>Comprobación GPG</uicontrol> y, a continuación, especifique un URL al archivo de claves GPG para el repositorio. </p></dd> -</dlentry><dlentry> -<dt>Informes de depuración</dt> -<dd>En esta sección se muestran informes de depuración, incluido el nombre y la ruta de archivo. -Puede seleccionar entre opciones para generar un informe nuevo, o bien redenominar, eliminar o descargar un informe existente.<p>El informe de depuración se genera utilizando el mandato <cmdname>sosreport</cmdname>. Está disponible para distribuciones de Red -Hat Enterprise <tm tmtype="tm" trademark="Linux">Linux</tm>, Fedora y Ubuntu. El mandato genera un archivo .tar que contiene la información de configuración y de diagnóstico, como la versión de kernel en ejecución, los módulos de carga y los archivos de configuración del sistema y servicio. -El mandato también ejecuta programas externos para recopilar información adicional y almacena esta salida en el archivo resultante.</p> </dd> -</dlentry></dl> -</csbody> -<?tm 1392659967 1?> -</cshelp> - - -<!-- ENGL1SH_VERS10N 42248_4 DO NOT REMOVE OR CHANGE THIS LINE --> -<!-- T9N_SRC_ID 232 --> -<!-- T9N_SH1P_STR1NG KV310AAP001 1 --> diff --git a/src/wok/plugins/kimchi/ui/pages/help/fr_FR/host.dita b/src/wok/plugins/kimchi/ui/pages/help/fr_FR/host.dita deleted file mode 100644 index 099d342..0000000 --- a/src/wok/plugins/kimchi/ui/pages/help/fr_FR/host.dita +++ /dev/null @@ -1,65 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!--Arbortext, Inc., 1988-2011, v.4002--> -<!DOCTYPE cshelp PUBLIC "-//IBM//DTD DITA CSHelp//EN" - "..\dtd\cshelp.dtd"> - - -<!--This DITA specialized document type is not supported by the Authoring Tools development team. -For support please see: -https://w3.opensource.ibm.com/projects/dita-cshelp/--> -<cshelp id="kimhhost" xml:lang="fr-fr"> -<title>Hôte</title> -<shortdesc>La page <wintitle>Hôte</wintitle> affiche des informations -sur le système hôte et vous permet d'arrêter, de redémarrer et de vous -connecter à l'hôte.</shortdesc> -<csbody> -<p>Vous pouvez effectuer les actions suivantes sur l'hôte :<ul> -<li>Sélectionnez <uicontrol>Arrêter</uicontrol> pour arrêter le système hôte.</li> -<li>Sélectionnez <uicontrol>Redémarrer</uicontrol> pour redémarrer le système hôte.</li> -<li>Sélectionnez <uicontrol>Connexion</uicontrol> pour ouvrir une connexion VNC -au système hôte, si celui-ci n'est pas déjà connecté.</li> -</ul></p> -<p>Cliquez sur les sections suivantes pour afficher des informations sur l'hôte :</p> -<dl><dlentry> -<dt>Informations de base</dt> -<dd>Cette section affiche la distribution, la version et le nom de code -du système d'exploitation hôte, ainsi que le type de processeur, le nombre d'UC en ligne et la quantité de mémoire en Go.</dd> -</dlentry><dlentry> -<dt>Statistiques système</dt> -<dd>Cette section affiche les graphiques des statistiques pour l'UC, mémoire, ainsi que -les E-S disque et E-S réseau pour l'hôte. </dd> -</dlentry><dlentry> -<dt>Mises à jour logicielles</dt> -<dd>Cette section affiche des informations pour tous les modules qui -disposent de mises à jour disponibles, y compris le nom de module, la version, l'architecture -et le référentiel. Vous pouvez mettre à jour toutes les modules répertoriés en sélectionnant <uicontrol>Tout -mettre à jour</uicontrol>. Vous ne pouvez pas sélectionner des modules individuels pour les mises à jour.</dd> -</dlentry><dlentry> -<dt>Référentiels</dt> -<dd>Cette section affiche les référentiels associés au système hôte. Vous pouvez ajouter, activer, éditer ou retirer des référentiels. L'ajout d'un référentiel associe celui-ci au système hôte, -tandis que l'activation d'un référentiel permet à l'hôte d'y accéder. Si votre système est Red Hat Enterprise Linux ou Fedora, -vous pouvez ajouter des référentiels <filepath>yum</filepath>. -Si votre système est de type Ubuntu ou Debian, ajoutez des référentiels -<filepath>deb</filepath>.<p>Si vous travaillez avec des référentiels yum, vous pouvez ajouter un contrôle GPG -afin de vérifier qu'un module provenant de ce référentiel n'a pas été endommagé. -Sélectionnez un référentiel puis cliquez sur <uicontrol>Editer</uicontrol>. Sélectionnez <uicontrol>Oui</uicontrol> pour activer <uicontrol>Contrôle GPG</uicontrol>, puis entrez une URL pour le fichier de clés GPG du référentiel.</p></dd> -</dlentry><dlentry> -<dt>Rapports de débogage</dt> -<dd>Cette section affiche les rapports de débogage, y compris le nom et le chemin du fichier. -Vous pouvez faire un choix parmi les options afin de générer un nouveau rapport, ou renommer, supprimer, -ou télécharger un rapport existant.<p>Le rapport de débogage est généré à -l'aide de la commande <cmdname>sosreport</cmdname>. Cette option est disponible pour les distributions -Red Hat Enterprise <tm tmtype="tm" trademark="Linux">Linux</tm>, Fedora et Ubuntu. La commande génère un fichier .tar contenant la configuration et des informations de diagnostic, -telles que la version du noyau d'exécution, les modules chargés, ainsi que les fichiers de configuration -du système et de la maintenance. -La commande exécute également des programmes externes pour collecter des informations -supplémentaires et stocke cette sortie dans l'archive résultante.</p> </dd> -</dlentry></dl> -</csbody> -<?tm 1392659967 1?> -</cshelp> - - -<!-- ENGL1SH_VERS10N 42248_4 DO NOT REMOVE OR CHANGE THIS LINE --> -<!-- T9N_SRC_ID 232 --> -<!-- T9N_SH1P_STR1NG KV310AAP001 1 --> diff --git a/src/wok/plugins/kimchi/ui/pages/help/it_IT/host.dita b/src/wok/plugins/kimchi/ui/pages/help/it_IT/host.dita deleted file mode 100644 index c2783bf..0000000 --- a/src/wok/plugins/kimchi/ui/pages/help/it_IT/host.dita +++ /dev/null @@ -1,51 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!--Arbortext, Inc., 1988-2011, v.4002--> -<!DOCTYPE cshelp PUBLIC "-//IBM//DTD DITA CSHelp//EN" - "..\dtd\cshelp.dtd"> - - -<!--This DITA specialized document type is not supported by the Authoring Tools development team. -For support please see: -https://w3.opensource.ibm.com/projects/dita-cshelp/--> -<cshelp id="kimhhost" xml:lang="it-it"> -<title>Host</title> -<shortdesc>La pagina <wintitle>Host</wintitle> visualizza le informazioni sul sistema host e consente di arrestarlo, riavviarlo e connettersi ad esso.</shortdesc> -<csbody> -<p>È possibile effettuare le seguenti operazioni sull'host:<ul> -<li>Selezionare <uicontrol>Arresta</uicontrol> per arrestare il sistema host.</li> -<li>Selezionare <uicontrol>Riavvia</uicontrol> per riavviare il sistema host.</li> -<li>Selezionare <uicontrol>Connetti</uicontrol> per aprire una connessione VNC al sistema host, se non è già connesso.</li> -</ul></p> -<p>Fare clic sulle seguenti sezioni per visualizzare le informazioni sull'host:</p> -<dl><dlentry> -<dt>Informazioni di base</dt> -<dd>Questa sezione visualizza il nome codice, la versione e la distribuzione del sistema operativo, come pure il tipo di processore, il numero di CPU in linea e la quantità di memoria in GB.</dd> -</dlentry><dlentry> -<dt>Statistiche di sistema</dt> -<dd>Questa sezione visualizza i grafici che mostrano le statistiche per la CPU, la memoria, l'I/O disco e di rete per l'host. </dd> -</dlentry><dlentry> -<dt>Aggiornamenti del software</dt> -<dd>Questa sezione visualizza le informazioni per tutti i pacchetti per cui sono disponibili gli aggiornamenti, incluso il nome, la versione, l'architettura e il repository del pacchetto. È possibile aggiornare tutti i pacchetti elencati, selezionando <uicontrol>Aggiorna tutto</uicontrol>. Non è possibile selezionare singoli pacchetti per gli aggiornamenti.</dd> -</dlentry><dlentry> -<dt>Repository</dt> -<dd>Questa sezione visualizza i repository associati al sistema host. È possibile aggiungere, abilitare, modificare o rimuovere i repository. L'aggiunta di un repository lo associa al sistema host, mentre l'abilitazione di un repository -consente all'host di accedervi. Se il sistema è Red Hat Enterprise -Linux o Fedora, è possibile aggiungere i repository <filepath>yum</filepath>. -Se il sistema è Ubuntu o Debian, aggiungere i repository <filepath>deb</filepath>.<p>Se si stanno utilizzando i repository yum, è possibile aggiungere un controllo GPG per verificare che un pacchetto da questo repository non sia stato corrotto. -Selezionare un repository, quindi <uicontrol>Modifica</uicontrol>. Selezionare <uicontrol>Sì</uicontrol> per abilitare il <uicontrol>controllo GPG</uicontrol>, quindi immettere un URL al file di chiavi GPG per il -repository.</p></dd> -</dlentry><dlentry> -<dt>Report di debug</dt> -<dd>Questa sezione visualizza i report di debug, incluso il nome e il percorso file. -Le opzioni disponibili consentono di generare un nuovo report oppure ridenominare, rimuovere o scaricare un report esistente.<p>Il report di debug viene generato utilizzando il comando <cmdname>sosreport</cmdname>. È disponibile per le distribuzioni Red -Hat Enterprise <tm tmtype="tm" trademark="Linux">Linux</tm>, Fedora e Ubuntu. Il comando genera un file .tar che contiene informazioni di diagnostica e configurazione, come la versione del kernel in esecuzione, i moduli caricati e i file di configurazione del servizio e del sistema. -Il comando esegue anche programmi esterni per raccogliere ulteriori informazioni e memorizza l'output nell'archivio risultante.</p> </dd> -</dlentry></dl> -</csbody> -<?tm 1392659967 1?> -</cshelp> - - -<!-- ENGL1SH_VERS10N 42248_4 DO NOT REMOVE OR CHANGE THIS LINE --> -<!-- T9N_SRC_ID 232 --> -<!-- T9N_SH1P_STR1NG KV310AAP001 1 --> diff --git a/src/wok/plugins/kimchi/ui/pages/help/ja_JP/host.dita b/src/wok/plugins/kimchi/ui/pages/help/ja_JP/host.dita deleted file mode 100644 index 2b9c765..0000000 --- a/src/wok/plugins/kimchi/ui/pages/help/ja_JP/host.dita +++ /dev/null @@ -1,69 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!--Arbortext, Inc., 1988-2011, v.4002--> -<!DOCTYPE cshelp PUBLIC "-//IBM//DTD DITA CSHelp//EN" - "..\dtd\cshelp.dtd"> - - -<!--This DITA specialized document type is not supported by the Authoring Tools development team. -For support please see: -https://w3.opensource.ibm.com/projects/dita-cshelp/--> -<cshelp id="kimhhost" xml:lang="ja-jp"> -<title>ホスト</title> -<shortdesc><wintitle>「ホスト」</wintitle>ページには、ホスト・システムに関する情報が表示されます。ここで、ホストをシャットダウン、再始動、またホストに接続することができます。 -</shortdesc> -<csbody> -<p>以下のアクションをホストに対して実行できます。 -<ul> -<li>ホスト・システムをシャットダウンするには<uicontrol>「シャットダウン」</uicontrol>を選択します。 -</li> -<li>ホスト・システムを再始動するには<uicontrol>「再始動」</uicontrol>を選択します。 -</li> -<li>ホスト・システムへの VNC 接続を (まだ接続されていない場合に) オープンするには、<uicontrol>「接続」</uicontrol>を選択します。 -</li> -</ul></p> -<p>ホストに関する情報を表示するには、以下の選択項目をクリックしてください。 -</p> -<dl><dlentry> -<dt>基本情報</dt> -<dd>このセクションには、ホスト・オペレーティング・システムのディストリビューション、バージョン、およびコード名、さらにプロセッサー・タイプ、オンライン CPU の数、およびメモリーの量 (GB 単位)が表示されます。 -</dd> -</dlentry><dlentry> -<dt>システム統計情報</dt> -<dd>このセクションには、ホストの CPU、メモリー、ディスク入出力、およびネットワーク入出力の統計情報を表すグラフが表示されます。 -</dd> -</dlentry><dlentry> -<dt>ソフトウェア更新</dt> -<dd>このセクションには、更新が用意されているパッケージすべての情報 -(パッケージ名、バージョン、アーキテクチャー、リポジトリーなど) が表示されます。 -<uicontrol>「すべて更新」</uicontrol>を選択すると、リストされているパッケージすべてを更新できます。 -更新する対象として個別のパッケージを選択することはできません。 -</dd> -</dlentry><dlentry> -<dt>リポジトリー</dt> -<dd>このセクションには、ホスト・システムに関連付けられているリポジトリーが表示されます。 -リポジトリーを追加する、有効にする、編集する、または削除することができます。 -リポジトリーを追加すると、そのリポジトリーがホスト・システムに関連付けられ、リポジトリーを有効にすると、そのリポジトリーにホストがアクセスできるようになります。 -システムが Red Hat Enterprise Linux または Fedora であれば、<filepath>yum</filepath> リポジトリーを追加できます。 -システムが Ubuntu または Debian であれば、<filepath>deb</filepath> リポジトリーを追加してください。 -<p>yum リポジトリーを操作している場合、そのリポジトリーに入っているパッケージが壊れていないことを確認するため、GPG チェックを追加できます。 -リポジトリーを選択し、<uicontrol>「編集」</uicontrol>をクリックしてください。 -<uicontrol>「はい」</uicontrol>を選択して<uicontrol>「GPG チェック」</uicontrol>を有効にしてから、そのリポジトリーの GPG 鍵ファイルの URL を入力してください。 -</p></dd> -</dlentry><dlentry> -<dt>デバッグ・レポート</dt> -<dd>このセクションには、デバッグ・レポート (名前やファイル・パスなど) が表示されます。 -新しいレポートを生成、既存のレポートを名前変更、削除、またはダウンロードするためのオプションを選択できます。 -<p>デバッグ・レポートは、<cmdname>sosreport</cmdname> コマンドで生成されます。 -これは、Red Hat Enterprise <tm tmtype="tm" trademark="Linux">Linux</tm>、Fedora、および Ubuntu ディストリビューションに用意されています。 -このコマンドは、構成および診断情報 (稼働中のカーネルのバージョン、ロードされているモジュール、システムおよびサービス構成ファイルなど) が入った .tar ファイルを生成します。 -このコマンドはまた、外部プログラムを実行して情報をさらに収集し、その出力を結果のアーカイブに保管します。 -</p> </dd> -</dlentry></dl> -</csbody> -<?tm 1392659967 1?> -</cshelp> - - -<!-- ENGL1SH_VERS10N 42248_4 DO NOT REMOVE OR CHANGE THIS LINE --> -<!-- T9N_SRC_ID 232 --> -<!-- T9N_SH1P_STR1NG KV310AAP001 1 --> diff --git a/src/wok/plugins/kimchi/ui/pages/help/ko_KR/host.dita b/src/wok/plugins/kimchi/ui/pages/help/ko_KR/host.dita deleted file mode 100644 index 220e166..0000000 --- a/src/wok/plugins/kimchi/ui/pages/help/ko_KR/host.dita +++ /dev/null @@ -1,51 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!--Arbortext, Inc., 1988-2011, v.4002--> -<!DOCTYPE cshelp PUBLIC "-//IBM//DTD DITA CSHelp//EN" - "..\dtd\cshelp.dtd"> - - -<!--This DITA specialized document type is not supported by the Authoring Tools development team. -For support please see: -https://w3.opensource.ibm.com/projects/dita-cshelp/--> -<cshelp id="kimhhost" xml:lang="ko-kr"> -<title>호스트</title> -<shortdesc><wintitle>호스트</wintitle> 페이지에는 호스트 시스템에 대한 정보가 표시되며 이 페이지를 사용하여 호스트를 종료 및 다시 시작하거나 호스트에 연결할 수 있습니다.</shortdesc> -<csbody> -<p>호스트에 대해 다음 조치를 수행할 수 있습니다.<ul> -<li>호스트 시스템을 종료하려면 <uicontrol>시스템 종료</uicontrol>를 선택합니다.</li> -<li>호스트 시스템을 다시 시작하려면 <uicontrol>다시 시작</uicontrol>을 선택합니다.</li> -<li>이미 연결되어 있지 않은 경우, 호스트 시스템에 대한 VNC 연결을 시작하려면 <uicontrol>연결</uicontrol>을 선택합니다.</li> -</ul></p> -<p>호스트에 대한 정보를 표시하려면 다음 섹션을 클릭하십시오.</p> -<dl><dlentry> -<dt>기본 정보</dt> -<dd>이 섹션에는 호스트 운영 체제 배포, -버전, 코드 이름, 프로세서 유형, 온라인 CPU 수, -메모리 용량(GB) 등이 표시됩니다.</dd> -</dlentry><dlentry> -<dt>시스템 통계</dt> -<dd>이 섹션에는 호스트의 CPU, 메모리, 디스크 I/O, 네트워크 I/O에 대한 통계를 표시하는 그래프가 표시됩니다. </dd> -</dlentry><dlentry> -<dt>소프트웨어 업데이트</dt> -<dd>이 섹션에는 패키지 이름, 버전, 아키텍처, 저장소를 비롯하여 사용 가능한 업데이트가 있는 모든 패키지에 대한 정보가 표시됩니다. <uicontrol>모두 업데이트</uicontrol>를 선택하여 나열된 모든 패키지를 업데이트할 수 있습니다. 업데이트에 대해 개별 패키지를 선택할 수는 없습니다.</dd> -</dlentry><dlentry> -<dt>저장소</dt> -<dd>이 섹션에는 호스트 시스템과 연관된 저장소가 표시됩니다. 저장소를 추가하거나, 사용으로 설정하거나, 편집하거나, 제거할 수 있습니다. 저장소를 추가하면 저장소가 호스트 시스템과 연관되며, 저장소를 사용으로 설정하면 호스트가 저장소에 액세스할 수 있습니다. 해당 시스템이 Red Hat Enterprise Linux 또는 Fedora인 경우, <filepath>yum</filepath> 저장소를 추가할 수 있습니다. -해당 시스템이 Ubuntu 또는 Debian인 경우, <filepath>deb</filepath> 저장소를 추가하십시오.<p>yum 저장소로 작업하는 경우, GPG 검사를 추가하여 이 저장소의 패키지가 손상되지 않았는지 확인할 수 있습니다. -저장소를 선택한 후 <uicontrol>편집</uicontrol>을 선택하십시오. <uicontrol>예</uicontrol>를 선택하여 -<uicontrol>GPG 검사</uicontrol>를 사용으로 설정한 후 -저장소에 대한 GPG 키 파일의 URL을 입력하십시오.</p></dd> -</dlentry><dlentry> -<dt>디버그 보고서</dt> -<dd>이 섹션에는 이름 및 파일 경로를 포함한 디버그 보고서가 표시됩니다. -새 보고서 생성, 기존 보고서 이름 바꾸기, 제거, 다운로드 등의 옵션 중에서 선택할 수 있습니다.<p>디버그 보고서는 <cmdname>sosreport</cmdname> 명령을 사용하여 생성됩니다. 이는 Red Hat Enterprise <tm tmtype="tm" trademark="Linux">Linux</tm>, Fedora 및 Ubuntu 배포에서 사용 가능합니다. 이 명령은 구성 및 진단 정보(예: 실행 중인 커널 버전, 로드된 모듈, 시스템 및 서비스 구성 파일)를 포함하는 .tar 파일을 생성합니다. -또한 이 명령은 외부 프로그램을 실행하여 추가 정보를 수집하고 결과 아카이브에 이 출력을 저장합니다.</p> </dd> -</dlentry></dl> -</csbody> -<?tm 1392659967 1?> -</cshelp> - - -<!-- ENGL1SH_VERS10N 42248_4 DO NOT REMOVE OR CHANGE THIS LINE --> -<!-- T9N_SRC_ID 232 --> -<!-- T9N_SH1P_STR1NG KV310AAP001 1 --> diff --git a/src/wok/plugins/kimchi/ui/pages/help/pt_BR/host.dita b/src/wok/plugins/kimchi/ui/pages/help/pt_BR/host.dita deleted file mode 100644 index a9814e8..0000000 --- a/src/wok/plugins/kimchi/ui/pages/help/pt_BR/host.dita +++ /dev/null @@ -1,72 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!--Arbortext, Inc., 1988-2011, v.4002--> -<!DOCTYPE cshelp PUBLIC "-//IBM//DTD DITA CSHelp//EN" - "..\dtd\cshelp.dtd"> - - -<!--This DITA specialized document type is not supported by the Authoring Tools development team. -For support please see: -https://w3.opensource.ibm.com/projects/dita-cshelp/--> -<cshelp id="kimhhost" xml:lang="pt-br"> -<title>Host</title> -<shortdesc>A página <wintitle>Host</wintitle> mostra informações sobre -o sistema host e permite encerrar, reiniciar e conectar -ao host.</shortdesc> -<csbody> -<p>É possível executar as ações a segur no host:<ul> -<li>Selecione <uicontrol>Encerrar</uicontrol> para encerrar o sistema -host.</li> -<li>Selecione <uicontrol>Reiniciar</uicontrol> para reiniciar o sistema host.</li> -<li>Selecione <uicontrol>Conectar</uicontrol> para abrir uma conexão VNC -para o sistema host, se ele já não estiver conectado.</li> -</ul></p> -<p>Clique nas seções a seguir para exibir informações sobre o host:</p> -<dl><dlentry> -<dt>Informações básicas</dt> -<dd>Esta seção exibe a distribuição do sistema operacional do host, -a versão e o nome do código, bem como o tipo de processador, o número de CPUs on-line e a quantia de -memória em GB.</dd> -</dlentry><dlentry> -<dt>Estatísticas do sistema</dt> -<dd>Esta seção exibe gráficos para mostrar estatísticas para CPU, memória, -E/S de disco e E/S de rede para o host. </dd> -</dlentry><dlentry> -<dt>Atualizações de software</dt> -<dd>Esta seção exibe informações de todos os pacotes que -possuem atualizações disponíveis, incluindo nome do pacote, versão, arquitetura -e repositório. É possível atualizar todos os pacotes listados selecionando <uicontrol>Atualizar -todos</uicontrol>. Não é possível selecionar pacotes individuais para atualizações.</dd> -</dlentry><dlentry> -<dt>Repositórios</dt> -<dd>Esta seção exibe repositórios que estão associados ao -sistema host. É possível incluir, ativar, editar ou remover repositórios. Incluir -um repositório o associa com o sistema host enquanto ativar um repositório -permite que o host o acesse. Se o seu sistema for Red Hat Enterprise -Linux ou Fedora, será possível incluir repositórios <filepath>yum</filepath>. -Se o seu sistema for Ubuntu ou Debian, inclua repositórios <filepath>deb</filepath>.<p>Se -você estiver trabalhando com repositórios yum, será possível incluir uma verificação de GPG para -verificar se um pacote desse repositório não foi corrompido. -Selecione um repositório e, em seguida, <uicontrol>Editar</uicontrol>. Selecione <uicontrol>Sim</uicontrol> para -ativar a <uicontrol>Verificação de GPG</uicontrol> e, então, insira uma URL no arquivo-chave de GPG para o -repositório.</p></dd> -</dlentry><dlentry> -<dt>Relatórios de depuração</dt> -<dd>Esta seção exibe relatórios de depuração, incluindo nome e caminho do arquivo. -É possível selecionar a partir das opções para gerar um novo relatório ou renomear, remover -ou fazer o download de um relatório existente.<p>O relatório de depuração é gerado usando -o comando <cmdname>sosreport</cmdname>. Ele está disponível para distribuições -Red Hat Enterprise <tm tmtype="tm" trademark="Linux">Linux</tm>, Fedora -e Ubuntu. O comando gera um arquivo .tar que contém -informações de configuração e de diagnóstico, como versão do kernel -em execução, módulos carregados e arquivos de configuração de sistema e de serviço. -O comando também executa programas externos para coletar informações adicionais -e armazena essa saída no archive resultante.</p> </dd> -</dlentry></dl> -</csbody> -<?tm 1392659967 1?> -</cshelp> - - -<!-- ENGL1SH_VERS10N 42248_4 DO NOT REMOVE OR CHANGE THIS LINE --> -<!-- T9N_SRC_ID 232 --> -<!-- T9N_SH1P_STR1NG KV310AAP001 1 --> diff --git a/src/wok/plugins/kimchi/ui/pages/help/ru_RU/host.dita b/src/wok/plugins/kimchi/ui/pages/help/ru_RU/host.dita deleted file mode 100644 index 54a78f5..0000000 --- a/src/wok/plugins/kimchi/ui/pages/help/ru_RU/host.dita +++ /dev/null @@ -1,48 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!--Arbortext, Inc., 1988-2011, v.4002--> -<!DOCTYPE cshelp PUBLIC "-//IBM//DTD DITA CSHelp//EN" - "..\dtd\cshelp.dtd"> - - -<!--This DITA specialized document type is not supported by the Authoring Tools development team. -For support please see: -https://w3.opensource.ibm.com/projects/dita-cshelp/--> -<cshelp id="kimhhost" xml:lang="ru-ru"> -<title>Хост</title> -<shortdesc>Страница <wintitle>Хост</wintitle> показывает информацию о системе хоста и позволяет останавливать хост, перезапускать хост и подключаться к нему.</shortdesc> -<csbody> -<p>На хосте можно выполнять следующие действия:<ul> -<li><uicontrol>Завершить работу</uicontrol> - остановить систему хоста.</li> -<li><uicontrol>Перезапустить</uicontrol> - перезапустить систему хоста.</li> -<li><uicontrol>Подключиться</uicontrol> - открыть соединение VNC с системой хоста, если оно еще не установлено.</li> -</ul></p> -<p>Щелкните на следующих разделах для просмотра информации о хосте:</p> -<dl><dlentry> -<dt>Базовая информация</dt> -<dd>В этом разделе показывается вариант операционной системы, его версия и кодовое имя, а также тип процессора, число подключенных процессоров и объем памяти в ГБ.</dd> -</dlentry><dlentry> -<dt>Системная статистика</dt> -<dd>В этом разделе показываются графики, отражающие статистическую информацию о процессоре, памяти, дисковом вводе-выводе и сетевом вводе-выводе для хоста. </dd> -</dlentry><dlentry> -<dt>Обновления программного обеспечения</dt> -<dd>В этом разделе показывается информация обо всех пакетах, для которых доступны обновления, включая имя пакета, версию, архитектуру и хранилище. Можно обновить все пакеты в списке щелчком на <uicontrol>Обновить все</uicontrol>. Отдельные пакеты для обновления выбрать нельзя.</dd> -</dlentry><dlentry> -<dt>Хранилища</dt> -<dd>В этом разделе показываются хранилища, связанные с системой хоста. Хранилища можно добавлять, активировать, изменять и удалять. При добавлении хранилище связывается с системой хоста, при активации хранилище становится доступным для хоста. Если система - Red Hat Enterprise Linux или Fedora, можно добавить хранилища <filepath>yum</filepath>. -Если система - Ubuntu или Debian, добавьте хранилища <filepath>deb</filepath>.<p>При работе с хранилищами yum можно добавить проверку GPG для проверки целостности пакетов из данного хранилища. -Выберите хранилище и щелкните на <uicontrol>Изменить</uicontrol>. Выберите <uicontrol>Да</uicontrol>, чтобы включить <uicontrol>Проверку GPG</uicontrol>, и введите URL файла ключей GPG для хранилища.</p></dd> -</dlentry><dlentry> -<dt>Отладочные отчеты</dt> -<dd>В этом разделе показываются отладочные отчеты, включая имя и путь. -Доступны команды для создания, переименования, удаления и загрузки отчетов.<p>Отладочный отчет создается командой <cmdname>sosreport</cmdname>. Он доступен для Red -Hat Enterprise <tm tmtype="tm" trademark="Linux">Linux</tm>, Fedora и Ubuntu. Команда создает файл .tar с конфигурационной и диагностической информацией, такой как версия ядра, загруженные модули и файлы конфигурации системы и служб. -Команда также выполняет внешние программы для сбора дополнительной информации и сохраняет их вывод в результирующем архиве.</p> </dd> -</dlentry></dl> -</csbody> -<?tm 1392659967 1?> -</cshelp> - - -<!-- ENGL1SH_VERS10N 42248_4 DO NOT REMOVE OR CHANGE THIS LINE --> -<!-- T9N_SRC_ID 232 --> -<!-- T9N_SH1P_STR1NG KV310AAP001 1 --> diff --git a/src/wok/plugins/kimchi/ui/pages/help/zh_CN/host.dita b/src/wok/plugins/kimchi/ui/pages/help/zh_CN/host.dita deleted file mode 100644 index a8622a2..0000000 --- a/src/wok/plugins/kimchi/ui/pages/help/zh_CN/host.dita +++ /dev/null @@ -1,45 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!--Arbortext, Inc., 1988-2011, v.4002--> -<!DOCTYPE cshelp PUBLIC "-//IBM//DTD DITA CSHelp//EN" - "..\dtd\cshelp.dtd"> - - -<!--This DITA specialized document type is not supported by the Authoring Tools development team. -For support please see: -https://w3.opensource.ibm.com/projects/dita-cshelp/--> -<cshelp id="kimhhost" xml:lang="zh-cn"> -<title>主机</title> -<shortdesc>“<wintitle>主机</wintitle>”页面显示有关主机系统的信息,并且允许您对主机进行关闭、启动和连接。</shortdesc> -<csbody> -<p>可对主机执行以下操作:<ul> -<li>选择<uicontrol>关闭</uicontrol>以关闭主机系统。</li> -<li>选择<uicontrol>重新启动</uicontrol>以重新启动主机系统。</li> -<li>选择<uicontrol>连接</uicontrol>以打开与主机系统的 VNC 连接(如果尚未连接)。</li> -</ul></p> -<p>单击以下部分以显示有关主机的信息:</p> -<dl><dlentry> -<dt>基本信息</dt> -<dd>本部分显示主机操作系统分发版、版本和代码名称以及处理器类型、联机 CPU 的数目和内存量(以 GB 计)。</dd> -</dlentry><dlentry> -<dt>系统统计信息</dt> -<dd>本部分显示图形,以显示主机有关 CPU、内存、磁盘 I/O 和网络 I/O 的统计信息。</dd> -</dlentry><dlentry> -<dt>软件更新</dt> -<dd>本部分显示有更新可用的所有软件包的信息,其中包括软件包名称、版本、体系结构和存储库。可通过选择<uicontrol>全部更新</uicontrol>来更新所列示的所有软件包。不能针对更新选择各个软件包。</dd> -</dlentry><dlentry> -<dt>存储库</dt> -<dd>本部分显示与主机系统关联的存储库。您可以添加、启用、编辑或除去存储库。当启用存储库会允许主机对其进行访问时,添加存储库会将其与主机系统关联。如果您的系统为 Red Hat Enterprise Linux 或 Fedora,那么可添加 <filepath>yum</filepath> 存储库。如果您的系统为 Ubuntu 或 Debian,那么请添加 <filepath>deb</filepath> 存储库。<p>如果要处理 Yum 存储库,您可以添加 GPG 检查以验证此存储库中的软件包是否已损坏。选择一个存储库,然后选择<uicontrol>编辑</uicontrol>。选择<uicontrol>是</uicontrol>以启用 <uicontrol>GPG 检查</uicontrol>,然后输入存储库的 GPG 密钥文件的 URL。</p></dd> -</dlentry><dlentry> -<dt>调试报告</dt> -<dd>本部分显示调试报告,其中包括名称和文件路径。您可以从选项中进行选择以生成新报告,或者对现有报告进行重命名、除去或下载。<p>调试报告将使用 -<cmdname>sosreport</cmdname> 命令生成。该报告可用于 Red -Hat Enterprise <tm tmtype="tm" trademark="Linux">Linux</tm>、Fedora 和 Ubuntu 分发版。该命令将生成包含配置和诊断信息的 .tar 文件,例如,正在运行的内核版本、已装入的模块以及系统和服务配置文件。该命令还会运行外部程序以收集更多信息并将此输出存储在生成的归档中。</p> </dd> -</dlentry></dl> -</csbody> -<?tm 1392659967 1?> -</cshelp> - - -<!-- ENGL1SH_VERS10N 42248_4 DO NOT REMOVE OR CHANGE THIS LINE --> -<!-- T9N_SRC_ID 232 --> -<!-- T9N_SH1P_STR1NG KV310AAP001 1 --> diff --git a/src/wok/plugins/kimchi/ui/pages/help/zh_TW/host.dita b/src/wok/plugins/kimchi/ui/pages/help/zh_TW/host.dita deleted file mode 100644 index 550945e..0000000 --- a/src/wok/plugins/kimchi/ui/pages/help/zh_TW/host.dita +++ /dev/null @@ -1,49 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!--Arbortext, Inc., 1988-2011, v.4002--> -<!DOCTYPE cshelp PUBLIC "-//IBM//DTD DITA CSHelp//EN" - "..\dtd\cshelp.dtd"> - - -<!--This DITA specialized document type is not supported by the Authoring Tools development team. -For support please see: -https://w3.opensource.ibm.com/projects/dita-cshelp/--> -<cshelp id="kimhhost" xml:lang="zh-tw"> -<title>主機</title> -<shortdesc>「<wintitle>主機</wintitle>」頁面會顯示主機系統的相關資訊,並容許您關閉、重新啟動以及連接到主機。</shortdesc> -<csbody> -<p>您可以針對主機執行下列動作:<ul> -<li>選取<uicontrol>關閉</uicontrol>以關閉主機系統。</li> -<li>選取<uicontrol>重新啟動</uicontrol>以重新啟動主機系統。</li> -<li>選取<uicontrol>連接</uicontrol>以開啟與主機系統的 VNC 連線(如果尚未連線到主機系統)。</li> -</ul></p> -<p>按一下下列區段以顯示主機的相關資訊:</p> -<dl><dlentry> -<dt>基本資訊</dt> -<dd>此區段會顯示主機作業系統發行套件、版本、程式碼名稱以及處理器類型、線上 CPU 數目和記憶體數量 (GB)。</dd> -</dlentry><dlentry> -<dt>系統統計資料</dt> -<dd>此區段會顯示一些圖形,以顯示主機的 CPU、記憶體、磁碟 I/O 和網路 I/O 的統計資料。</dd> -</dlentry><dlentry> -<dt>軟體更新</dt> -<dd>此區段會顯示具有可用更新的所有套件的相關資訊,包括套件名稱、版本、架構和儲存庫。您可以透過選取<uicontrol>全部更新</uicontrol>來更新所有列出的套件。不能選取個別套件以進行更新。</dd> -</dlentry><dlentry> -<dt>儲存庫</dt> -<dd>此區段會顯示與主機系統相關聯的儲存庫。您可以新增、啟用、編輯或移除儲存庫。新增儲存庫可使它與主機系統相關聯,而啟用儲存庫則容許主機存取儲存庫。如果您的系統是 -Red Hat Enterprise Linux 或 Fedora,則可以新增 <filepath>yum</filepath> 儲存庫。如果您的系統是 -Ubuntu 或 Debian,則可以新增 <filepath>deb</filepath> 儲存庫。<p>如果您正在使用 -yum 儲存庫,則可以新增 GPG 檢查以驗證此儲存庫中的某個套件是否未毀損。選取儲存庫,然後選取<uicontrol>編輯</uicontrol>。選取<uicontrol>是</uicontrol>以啟用 <uicontrol>GPG 檢查</uicontrol>,然後輸入儲存庫的 GPG 金鑰檔的 URL。</p></dd> -</dlentry><dlentry> -<dt>除錯報告</dt> -<dd>此區段顯示除錯報告,包括名稱和檔案路徑。您可以選取選項以產生新報告、或是重新命名、移除或下載現有報告。<p>除錯報告是使用 -<cmdname>sosreport</cmdname> 指令產生的。該指令可用於 Red -Hat Enterprise <tm tmtype="tm" trademark="Linux">Linux</tm>、Fedora -及 Ubuntu 發行套件。該指令會產生 .tar 檔案,其包含配置與診斷資訊,例如執行中的核心版本、已載入模組以及系統和服務配置檔案。該指令還會執行外部程式來收集更多資訊並將此輸出儲存在產生的保存檔中。</p> </dd> -</dlentry></dl> -</csbody> -<?tm 1392659967 1?> -</cshelp> - - -<!-- ENGL1SH_VERS10N 42248_4 DO NOT REMOVE OR CHANGE THIS LINE --> -<!-- T9N_SRC_ID 232 --> -<!-- T9N_SH1P_STR1NG KV310AAP001 1 --> -- 2.1.0

From: chandrureddy <chandra@linux.vnet.ibm.com> --- src/wok/plugins/gingerbase/ui/pages/Makefile.am | 23 +++ src/wok/plugins/gingerbase/ui/pages/host.html.tmpl | 178 +++++++++++++++++++++ src/wok/plugins/gingerbase/ui/pages/i18n.json.tmpl | 149 +++++++++++++++++ .../gingerbase/ui/pages/report-add.html.tmpl | 57 +++++++ .../gingerbase/ui/pages/report-rename.html.tmpl | 57 +++++++ .../gingerbase/ui/pages/repository-add.html.tmpl | 114 +++++++++++++ .../gingerbase/ui/pages/repository-edit.html.tmpl | 118 ++++++++++++++ src/wok/plugins/kimchi/ui/pages/host.html.tmpl | 177 -------------------- .../plugins/kimchi/ui/pages/report-add.html.tmpl | 56 ------- .../kimchi/ui/pages/report-rename.html.tmpl | 56 ------- .../kimchi/ui/pages/repository-add.html.tmpl | 113 ------------- .../kimchi/ui/pages/repository-edit.html.tmpl | 117 -------------- 12 files changed, 696 insertions(+), 519 deletions(-) create mode 100644 src/wok/plugins/gingerbase/ui/pages/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/host.html.tmpl create mode 100644 src/wok/plugins/gingerbase/ui/pages/i18n.json.tmpl create mode 100644 src/wok/plugins/gingerbase/ui/pages/report-add.html.tmpl create mode 100644 src/wok/plugins/gingerbase/ui/pages/report-rename.html.tmpl create mode 100644 src/wok/plugins/gingerbase/ui/pages/repository-add.html.tmpl create mode 100644 src/wok/plugins/gingerbase/ui/pages/repository-edit.html.tmpl delete mode 100644 src/wok/plugins/kimchi/ui/pages/host.html.tmpl delete mode 100644 src/wok/plugins/kimchi/ui/pages/report-add.html.tmpl delete mode 100644 src/wok/plugins/kimchi/ui/pages/report-rename.html.tmpl delete mode 100644 src/wok/plugins/kimchi/ui/pages/repository-add.html.tmpl delete mode 100644 src/wok/plugins/kimchi/ui/pages/repository-edit.html.tmpl diff --git a/src/wok/plugins/gingerbase/ui/pages/Makefile.am b/src/wok/plugins/gingerbase/ui/pages/Makefile.am new file mode 100644 index 0000000..2e57c9a --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/pages/Makefile.am @@ -0,0 +1,23 @@ +# +# Ginger Base +# +# Copyright IBM, Corp. 2015 +# +# Code derived from Project Kimchi +# 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 = help + +htmldir = $(datadir)/wok/plugins/gingerbase/ui/pages + +dist_html_DATA = $(wildcard *.tmpl) $(NULL) diff --git a/src/wok/plugins/gingerbase/ui/pages/host.html.tmpl b/src/wok/plugins/gingerbase/ui/pages/host.html.tmpl new file mode 100644 index 0000000..23a3131 --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/pages/host.html.tmpl @@ -0,0 +1,178 @@ +#* + * Project Ginger Base + * + * Copyright IBM, Corp. 2013-2015 + * + * Code derived from Project Kimchi + * 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 wok.cachebust import href +#silent t = gettext.translation($lang.domain, $lang.localedir, languages=$lang.lang, fallback=True) +#silent _ = t.gettext +#silent _t = t.gettext +<!DOCTYPE html> +<html> +<head> +<link rel="stylesheet" href="plugins/gingerbase/css/theme-default.min.css"> +<script src="plugins/gingerbase/js/gingerbase.min.js"></script> +</head> +<body> +<div id="host-root-container"> + <div class="toolbar"> + <div class="tools"> + </div> + </div> + <div id="host-content-container" class="empty-when-logged-off"></div> +</div> + +<script id="host-tmpl" type="gingerbase/template"> + <div class="host-panel"> + <div class="logo-container"> + <div class="logo" style="background-image: url({logo});"></div> + </div> + <div id="host-info-container" class="info-container"> + <h2 class="hostname">{hostname}</h2> + <div class="action-panel"> + <button id="host-button-shutdown" class="btn-normal-1 stop"> + <div class="button-icon action-icon-stop"></div> + $_("Shut down") + </button> + <button id="host-button-restart" class="btn-normal-1 restart"> + <div class="button-icon action-icon-restart"></div> + $_("Restart") + </button> + <button class="btn-normal-1 connect" disabled="disabled"> + <div class="button-icon action-icon-connect"></div> + $_("Connect") + </button> + </div> + <div class="host-section"> + <h3 class="section-header" + aria-expanded="false" + aria-controls="content-sys-info"> + $_("Basic Information") + </h3> + <div id="content-sys-info" class="section-content"> + <div class="section-row"> + <div class="section-label">$_("OS Distro")</div> + <div class="section-value">{os_distro}</div> + </div> + <div class="section-row"> + <div class="section-label">$_("OS Version")</div> + <div class="section-value">{os_version}</div> + </div> + <div class="section-row"> + <div class="section-label">$_("OS Code Name")</div> + <div class="section-value">{os_codename}</div> + </div> + <div class="section-row"> + <div class="section-label">$_("Processor")</div> + <div class="section-value">{cpu_model}</div> + </div> + <div class="section-row"> + <div class="section-label">$_("CPU(s)")</div> + <div class="section-value">{cpus}</div> + </div> + <div class="section-row"> + <div class="section-label">$_("Memory")</div> + <div class="section-value">{memory}</div> + </div> + </div> + </div> + <div class="host-section"> + <h3 class="section-header" + aria-controls="content-sys-statistics"> + $_("System Statistics") + </h3> + <div id="content-sys-statistics" class="section-content"> + <div class="section-row"> + <div class="section-label">$_("CPU")</div> + <div class="section-value"> + <div id="container-chart-cpu" class="inline-block"></div> + </div> + </div> + <div class="section-row"> + <div class="section-label">$_("Memory")</div> + <div class="section-value"> + <div id="container-chart-memory" class="inline-block"></div> + </div> + </div> + <div class="section-row"> + <div class="section-label">$_("Disk I/O")</div> + <div class="section-value"> + <div id="container-chart-disk-io" class="inline-block"></div> + </div> + </div> + <div class="section-row"> + <div class="section-label">$_("Network I/O")</div> + <div class="section-value"> + <div id="container-chart-network-io" class="inline-block"></div> + </div> + </div> + </div> + </div> + <div id="software-update-section" class="host-section hidden"> + <h3 class="section-header" + aria-controls="content-software-update"> + $_("Software Updates") + </h3> + <div id="content-software-update" class="section-content"> + <div class="section-row"> + <div class="section-value"> + <div id="software-updates-grid-container"></div> + <div id="software-updates-progress-container" class="hidden"> + <label for="software-updates-progress-textarea">$_("Update Progress")</label> + <textarea id="software-updates-progress-textarea" readonly></textarea> + </div> + </div> + </div> + </div> + </div> + <div id="repositories-section" class="host-section hidden"> + <h3 class="section-header" + aria-controls="content-repositories"> + $_("Repositories") + </h3> + <div id="content-repositories" class="section-content"> + <div class="section-row"> + <div class="section-value"> + <div id="repositories-grid-container"></div> + </div> + </div> + </div> + </div> + <div id="debug-report-section" class="host-section hidden"> + <h3 class="section-header" + aria-controls="content-sys-reports"> + $_("Debug Reports") + </h3> + <div id="content-sys-reports" class="section-content"> + <div class="section-row"> + <div class="section-value"> + <div id="available-reports-grid-container"></div> + </div> + </div> + </div> + </div> + </div> + </div> +</script> + +<script type="text/javascript"> + kimchi.host_main(); +</script> +</body> +</html> diff --git a/src/wok/plugins/gingerbase/ui/pages/i18n.json.tmpl b/src/wok/plugins/gingerbase/ui/pages/i18n.json.tmpl new file mode 100644 index 0000000..d8d9029 --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/pages/i18n.json.tmpl @@ -0,0 +1,149 @@ +#* + * Project Ginger Base + * + * Copyright IBM, Corp. 2015 + * + * Code derived from Project Kimchi + * 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 wok.cachebust import href +#silent t = gettext.translation($lang.domain, $lang.localedir, languages=$lang.lang, fallback=True) +#silent _ = t.gettext +#silent _t = t.gettext +{ + "GGBAUTH6001E": "$_("The username or password you entered is incorrect. Please try again.")", + "GGBAUTH6002E": "$_("This field is required.")", + + "GGBAUTH6001M": "$_("Log in")", + "GGBAUTH6002M": "$_("Logging in...")", + + "Host": "$_("Host")", + "Guests": "$_("Guests")", + "Templates": "$_("Templates")", + "Storage": "$_("Storage")", + "Network": "$_("Network")", + + "GGBAPI6002E": "$_("Failed to get application configuration")", + "GGBAPI6003E": "$_("This is not a valid Linux path")", + "GGBAPI6004E": "$_("This is not a valid URL.")", + "GGBAPI6005E": "$_("No such data available.")", + "GGBAPI6007E": "$_("Can not contact the host system. Verify the host system is up and that you have network connectivity to it. HTTP request response %1. ")", + "GGBAPI6008E": "$_("Unable to read file.")", + "GGBAPI6009E": "$_("Error while uploading file.")", + + "GGBAPI6001M": "$_("Delete Confirmation")", + "GGBAPI6002M": "$_("OK")", + "GGBAPI6003M": "$_("Cancel")", + "GGBAPI6004M": "$_("Confirm")", + "GGBAPI6005M": "$_("Create")", + "GGBAPI6006M": "$_("Warning")", + "GGBAPI6007M": "$_("Save")", + "GGBAPI6008M": "$_("Creating...")", + "GGBAPI6009M": "$_("Cloning...")", + + "GGBGRD6001M": "$_("Loading...")", + "GGBGRD6002M": "$_("An error occurred while retrieving system information.")", + "GGBGRD6003M": "$_("Retry")", + "GGBGRD6004M": "$_("Detailed message:")", + + "GGBHOST6001E": "$_("Unable to shut down system as there are some virtual machines running!")", + + "GGBHOST6001M": "$_("Max:")", + "GGBHOST6002M": "$_("Utilization")", + "GGBHOST6003M": "$_("Available")", + "GGBHOST6004M": "$_("Read Rate")", + "GGBHOST6005M": "$_("Write Rate")", + "GGBHOST6006M": "$_("Received")", + "GGBHOST6007M": "$_("Sent")", + "GGBHOST6008M": "$_("Shutting down or restarting host will cause unsaved work lost. Continue to shut down/restarting?")", + + + "GGBREPO6001M": "$_("Confirm")", + "GGBREPO6002M": "$_("Repository will be removed permanently and can't be recovered. Do you want to continue?")", + "GGBREPO6003M": "$_("Repositories")", + "GGBREPO6004M": "$_("ID")", + "GGBREPO6005M": "$_("Name")", + "GGBREPO6006M": "$_("Base URL")", + "GGBREPO6007M": "$_("Is Mirror")", + "GGBREPO6008M": "$_("URL Args")", + "GGBREPO6009M": "$_("Enabled")", + "GGBREPO6010M": "$_("GPG Check")", + "GGBREPO6011M": "$_("GPG Key")", + "GGBREPO6012M": "$_("Add")", + "GGBREPO6013M": "$_("Edit")", + "GGBREPO6014M": "$_("Remove")", + "GGBREPO6016M": "$_("Enable")", + "GGBREPO6017M": "$_("Disable")", + + + "GGBUPD6001M": "$_("Software Updates")", + "GGBUPD6002M": "$_("Package Name")", + "GGBUPD6003M": "$_("Version")", + "GGBUPD6004M": "$_("Architecture")", + "GGBUPD6005M": "$_("Repository")", + "GGBUPD6006M": "$_("Update All")", + "GGBUPD6007M": "$_("Updating...")", + "GGBUPD6008M": "$_("Failed to retrieve packages update information.")", + "GGBUPD6009M": "$_("Failed to update package(s).")", + + + "GGBDR6001M": "$_("Debug report will be removed permanently and can't be recovered. Do you want to continue?")", + "GGBDR6002M": "$_("Debug Reports")", + "GGBDR6003M": "$_("Name")", + "GGBDR6005M": "$_("Generated Time")", + "GGBDR6006M": "$_("Generate")", + "GGBDR6007M": "$_("Generating...")", + "GGBDR6008M": "$_("Rename")", + "GGBDR6009M": "$_("Remove")", + "GGBDR6010M": "$_("Download")", + "GGBDR6011M": "$_("Report name should contain only letters, digits, underscore ('_') and/or hyphen ('-').")", + "GGBDR6012M": "$_("Pending...")", + "GGBDR6013M": "$_("Report name is the same as the original one.")", + + "GGBVM6001M": "$_("This will delete the virtual machine and its virtual disks. This operation cannot be undone. Would you like to continue?")", + "GGBVM6002M": "$_("Power off Confirmation")", + "GGBVM6003M": "$_("This action may produce undesirable results, " + "for example unflushed disk cache in the guest. " + "Would you like to continue?")", + "GGBVM6004M": "$_("Reset Confirmation")", + "GGBVM6005M": "$_("There is a risk of data loss caused by reset without" + " the guest OS shutdown. Would you like to continue?")", + "GGBVM6006M": "$_("Shut Down Confirmation")", + "GGBVM6007M": "$_("Note the guest OS may ignore this request. Would you like to continue?")", + "GGBVM6008M": "$_("Virtual Machine delete Confirmation")", + "GGBVM6009M": "$_("This virtual machine is not persistent. Power Off will delete it. Continue?")", + "GGBVM6010M": "$_("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?")", + + "GGBVMCD6001M": "$_("This CDROM will be detached permanently and you can re-attach it. Continue to detach it?")", + "GGBVMCD6002M": "$_("Attach")", + "GGBVMCD6003M": "$_("Attaching...")", + "GGBVMCD6004M": "$_("Replace")", + "GGBVMCD6005M": "$_("Replacing...")", + "GGBVMCD6006M": "$_("Successfully attached!")", + "GGBVMCD6007M": "$_("Successfully replaced!")", + "GGBVMCD6008M": "$_("Successfully detached!")", + "GGBVMCD6009M": "$_("This disk will be detached permanently and you can re-attach it. Continue to detach it?")", + + "GGBVMED6001M": "$_("interface:")", + "GGBVMED6002M": "$_("address:")", + "GGBVMED6003M": "$_("link_type:")", + "GGBVMED6004M": "$_("block:")", + "GGBVMED6005M": "$_("drive_type:")", + "GGBVMED6006M": "$_("model:")", + "GGBVMED6007M": "$_("Affected devices:")", + + "GGBVMSTOR0001E": "$_("CDROM path needs to be a valid local/remote path and cannot be blank.")", + "GGBVMSTOR0002E": "$_("Disk pool or volume cannot be blank.")" +} diff --git a/src/wok/plugins/gingerbase/ui/pages/report-add.html.tmpl b/src/wok/plugins/gingerbase/ui/pages/report-add.html.tmpl new file mode 100644 index 0000000..7701dec --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/pages/report-add.html.tmpl @@ -0,0 +1,57 @@ +#* + * Project Ginger Base + * + * Copyright IBM, Corp. 2013-2015 + * + * Code derived from Project Kimchi + * 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 wok.cachebust import href +#silent t = gettext.translation($lang.domain, $lang.localedir, languages=$lang.lang, fallback=True) +#silent _ = t.gettext +#silent _t = t.gettext +<!DOCTYPE html> +<div id="report-add-window" class="window"> + <header> + <h1 class="title h1 grey">$_("Generate a New Debug Report")</h1> + </header> + <div class="content"> + <form id="form-report-add"> + <section class="form-section"> + <h2> + <label for="report-name-textbox">$_("Report Name")</label> + </h2> + <div class="field"> + <input type="text" class="text" id="report-name-textbox" name="name" /> + <span class="icon-info-circled light-grey c1"></span> + <span class="info-add-debug-report"> + $_("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 (\"-\").") + </span> + </div> + </section> + </form> + </div> + <footer> + <div class="btn-group"> + <button id="button-report-add" class="btn-normal"><span class="text">$_("Generate")</span></button> + <button id="button-report-cancel" class="btn-normal close" type="button"> + <span calss="text">$_("Cancel")</span> + </button> + </div> + </footer> +</div> +<script> + kimchi.report_add_main(); +</script> diff --git a/src/wok/plugins/gingerbase/ui/pages/report-rename.html.tmpl b/src/wok/plugins/gingerbase/ui/pages/report-rename.html.tmpl new file mode 100644 index 0000000..a08c2d9 --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/pages/report-rename.html.tmpl @@ -0,0 +1,57 @@ +#* + * Project Ginger Base + * + * Copyright IBM, Corp. 2014-2015 + * + * Code derived from Project Kimchi + * 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 wok.cachebust import href +#silent t = gettext.translation($lang.domain, $lang.localedir, languages=$lang.lang, fallback=True) +#silent _ = t.gettext +#silent _t = t.gettext +<!DOCTYPE html> +<div id="report-rename-window" class="window"> + <header> + <h1 class="title h1 grey">$_("Rename a Debug Report")</h1> + </header> + <div class="content"> + <form id="form-report-rename"> + <section class="form-section"> + <h2> + <label for="report-name-textbox">$_("Report Name")</label> + </h2> + <div class="field"> + <input type="text" class="text" id="report-name-textbox" name="name" /> + <span class="icon-info-circled light-grey c1"></span> + <span class="info-debug-report-rename"> + $_("The name used to identify the report. Name can contain: letters, digits and hyphen (\"-\").") + </span> + </div> + </section> + </form> + </div> + <footer> + <div class="btn-group"> + <button id="button-report-rename" class="btn-normal"><span class="text">$_("Submit")</span></button> + <button id-"button-report-rename-cancel" class="btn-normal close" type="button"> + <span class="text">$_("Cancel")</span> + </button> + </div> + </footer> +</div> +<script> + kimchi.report_rename_main(); +</script> diff --git a/src/wok/plugins/gingerbase/ui/pages/repository-add.html.tmpl b/src/wok/plugins/gingerbase/ui/pages/repository-add.html.tmpl new file mode 100644 index 0000000..5615ed7 --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/pages/repository-add.html.tmpl @@ -0,0 +1,114 @@ +#* + * Project Ginger Base + * + * Copyright IBM, Corp. 2014-2015 + * + * Code derived from Project Kimchi + * 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 wok.cachebust import href +#silent t = gettext.translation($lang.domain, $lang.localedir, languages=$lang.lang, fallback=True) +#silent _ = t.gettext +#silent _t = t.gettext +<div id="repository-add-window" class="window"> + <form id="form-repository-add"> + <header class="window-header"> + <h1 class="title h1 grey">$_("Add a Repository")</h1> + </header> + <section> + <div class="content"> + <div class="form-section yum"> + <h2>$_("Identifier")</h2> + <div class="field"> + <div class="textbox-wrapper"> + <input type="text" class="text" name="repo_id" /> + </div> + <div class="icon-info-circled light-grey c1 help-inline"></div> + <p class="text-help help-inline"> + $_("Single word, unique identifier for the repository.") + </p> + </div> + </div> + <section class="form-section yum"> + <h2>$_("Name")</h2> + <div class="field"> + <div class="textbox-wrapper"> + <input type="text" class="text" name="config[repo_name]" /> + </div> + <div class="icon-info-circled light-grey c1 help-inline"></div> + <p class="text-help help-inline"> + $_("Textual name for the repository.") + </p> + </div> + </section> + <section class="form-section"> + <h2>$_("URL")<span class="required" role="presentation" title='$_("Required Field")'>*</span></h2> + <div class="field"> + <div class="textbox-wrapper"> + <input type="text" class="text required" name="baseurl" /> + </div> + <div class="icon-info-circled light-grey c1 help-inline"></div> + <p class="text-help help-inline"> + $_("URL to the repository. Supported protocols are http, ftp, and file.") + </p> + </div> + <div class="field yum"> + <p class="yum"> + <input type="checkbox" name="isMirror" value="true" id="isMirror" /> + <label id="isMirrorLabel" for="isMirror">$_("Repository is a mirror")</label> + </p> + </div> + </section> + <section class="form-section repository-dist deb"> + <h2>$_("Distribution")</h2> + <div class="field"> + <div class="textbox-wrapper"> + <input type="text" class="text" name="config[dist]" /> + </div> + <div class="icon-info-circled light-grey c1 help-inline"></div> + <p class="text-help help-inline"> + $_("Distribution of the DEB repository.") + </p> + </div> + </section> + <section class="form-section repository-comps deb"> + <h2>$_("Components")</h2> + <div class="field"> + <div class="textbox-wrapper"> + <input type="text" class="text" name="config[comps]" /> + </div> + <div class="icon-info-circled light-grey c1 help-inline"></div> + <p class="text-help help-inline"> + $_("List of components in DEB repository.") + </p> + </div> + </section> + </div> + </section> + <footer> + <div class="btn-group"> + <button type="submit" id="button-repository-add" class="btn-normal" disabled="disabled"> + <span class="text">$_("Add")</span> + </button> + <button type="button" id="button-repository-close" class="btn-normal close"> + <span class="text">$("Cancel")</span> + </button> + </div> + </footer> + </form> +</div> +<script> + kimchi.repository_add_main(); +</script> diff --git a/src/wok/plugins/gingerbase/ui/pages/repository-edit.html.tmpl b/src/wok/plugins/gingerbase/ui/pages/repository-edit.html.tmpl new file mode 100644 index 0000000..12c9c37 --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/pages/repository-edit.html.tmpl @@ -0,0 +1,118 @@ +#* + * Project Ginger Base + * + * Copyright IBM, Corp. 2014-2015 + * + * Code derived from Project Kimchi + * 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 wok.cachebust import href +#silent t = gettext.translation($lang.domain, $lang.localedir, languages=$lang.lang, fallback=True) +#silent _ = t.gettext +#silent _t = t.gettext + +<div id="repository-edit-window" class="window"> + <form id="form-repository-edit"> + <header> + <h1 class="title h1 grey">$_("Edit Repository")</h1> + </header> + <div class="content"> + <section id="form-repository-edit"> + <fieldset class="repository-edit-fieldset"> + <div class="repository-id yum"> + <div class="repository-edit-wrapper-label"> + <label for="repository-edit-id-textbox">$_("ID")</label> + </div> + <div class="repository-edit-wrapper-controls"> + <input id="repository-edit-id-textbox" name="repo_id" type="text" disabled="disabled" readonly="readonly"/> + </div> + </div> + <div class="repository-name yum"> + <div class="repository-edit-wrapper-label"> + <label for="repository-edit-name-textbox">$_("Name")</label> + </div> + <div class="repository-edit-wrapper-controls"> + <input id="repository-edit-name-textbox" class="yum" name="config[repo_name]" type="text" /> + </div> + </div> + <div class="repository-url"> + <div class="repository-edit-wrapper-label"> + <label for="repository-edit-baseurl-textbox">$_("URL")</label> + </div> + <div class="repository-edit-wrapper-controls"> + <input id="repository-edit-baseurl-textbox" name="baseurl" type="text" /> + </div> + </div> + <div class="repository-dist deb"> + <div class="repository-edit-wrapper-label"> + <label for="repository-edit-urlargs-textbox">$_("Distribution")</label> + </div> + <div class="repository-edit-wrapper-controls"> + <input id="repository-edit-urlargs-textbox" class="deb" name="config[dist]" type="text" /> + </div> + </div> + <div class="repository-mirrorlist yum"> + <div class="repository-edit-wrapper-label"> + <label for="repository-edit-urlargs-textbox">$_("Mirror List URL")</label> + </div> + <div class="repository-edit-wrapper-controls"> + <input id="repository-edit-urlargs-textbox" class="yum" name="config[mirrorlist]" type="text" /> + </div> + </div> + <div class="repository-comps deb"> + <div class="repository-edit-wrapper-label"> + <label for="repository-edit-urlargs-textbox">$_("Components")</label> + </div> + <div class="repository-edit-wrapper-controls"> + <input id="repository-edit-urlargs-textbox" class="deb" name="config[comps]" type="text" /> + </div> + </div> + <div class="repository-gpgkey yum"> + <div class="repository-edit-wrapper-label"> + <label for="repository-edit-gpgkey-textbox">$_("GPG Key")</label> + </div> + <div class="repository-edit-wrapper-controls"> + <input id="repository-edit-gpgkey-textbox" class="yum" name="config[gpgkey]" type="text" /> + </div> + </div> + <div class="repository-gpgcheck yum"> + <div class="repository-edit-wrapper-label"> + <label>$_("GPG Check")</label> + </div> + <div class="repository-edit-wrapper-controls"> + <input id="repository-edit-gpgcheck-radio-true" class="yum" name="config[gpgcheck]" type="radio" value="true" /> + <label for="repository-edit-gpgcheck-radio-true">$_("Yes")</label> + <input id="repository-edit-gpgcheck-radio-false" class="yum" name="config[gpgcheck]" type="radio" value="false" /> + <label for="repository-edit-gpgcheck-radio-false">$_("No")</label> + </div> + </div> + </fieldset> + </section> + </div> + <footer> + <div class="btn-group"> + <button type="submit" id="repository-edit-button-save" class="btn-normal"> + <span class="text">$_("Save")</span> + </button> + <button type="button" id="repository-edit-button-cancel" class="close btn-normal"> + <span class="text">$_("Cancel")</span> + </button> + </div> + </footer> + </form> +</div> +<script type="text/javascript"> + kimchi.repository_edit_main(); +</script> diff --git a/src/wok/plugins/kimchi/ui/pages/host.html.tmpl b/src/wok/plugins/kimchi/ui/pages/host.html.tmpl deleted file mode 100644 index d87debc..0000000 --- a/src/wok/plugins/kimchi/ui/pages/host.html.tmpl +++ /dev/null @@ -1,177 +0,0 @@ -#* - * 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. - *# - -#unicode UTF-8 -#import gettext -#from wok.cachebust import href -#silent t = gettext.translation($lang.domain, $lang.localedir, languages=$lang.lang, fallback=True) -#silent _ = t.gettext -#silent _t = t.gettext -<!DOCTYPE html> -<html> -<head> -<link rel="stylesheet" href="plugins/kimchi/css/theme-default.min.css"> -<script src="plugins/kimchi/js/kimchi.min.js"></script> -</head> -<body> -<div id="host-root-container"> - <div class="toolbar"> - <div class="tools"> - </div> - </div> - <div id="host-content-container" class="empty-when-logged-off"></div> -</div> - -<script id="host-tmpl" type="kimchi/template"> - <div class="host-panel"> - <div class="logo-container"> - <div class="logo" style="background-image: url({logo});"></div> - </div> - <div id="host-info-container" class="info-container"> - <h2 class="hostname">{hostname}</h2> - <div class="action-panel"> - <button id="host-button-shutdown" class="btn-normal-1 stop"> - <div class="button-icon action-icon-stop"></div> - $_("Shut down") - </button> - <button id="host-button-restart" class="btn-normal-1 restart"> - <div class="button-icon action-icon-restart"></div> - $_("Restart") - </button> - <button class="btn-normal-1 connect" disabled="disabled"> - <div class="button-icon action-icon-connect"></div> - $_("Connect") - </button> - </div> - <div class="host-section"> - <h3 class="section-header" - aria-expanded="false" - aria-controls="content-sys-info"> - $_("Basic Information") - </h3> - <div id="content-sys-info" class="section-content"> - <div class="section-row"> - <div class="section-label">$_("OS Distro")</div> - <div class="section-value">{os_distro}</div> - </div> - <div class="section-row"> - <div class="section-label">$_("OS Version")</div> - <div class="section-value">{os_version}</div> - </div> - <div class="section-row"> - <div class="section-label">$_("OS Code Name")</div> - <div class="section-value">{os_codename}</div> - </div> - <div class="section-row"> - <div class="section-label">$_("Processor")</div> - <div class="section-value">{cpu_model}</div> - </div> - <div class="section-row"> - <div class="section-label">$_("CPU(s)")</div> - <div class="section-value">{cpus}</div> - </div> - <div class="section-row"> - <div class="section-label">$_("Memory")</div> - <div class="section-value">{memory}</div> - </div> - </div> - </div> - <div class="host-section"> - <h3 class="section-header" - aria-controls="content-sys-statistics"> - $_("System Statistics") - </h3> - <div id="content-sys-statistics" class="section-content"> - <div class="section-row"> - <div class="section-label">$_("CPU")</div> - <div class="section-value"> - <div id="container-chart-cpu" class="inline-block"></div> - </div> - </div> - <div class="section-row"> - <div class="section-label">$_("Memory")</div> - <div class="section-value"> - <div id="container-chart-memory" class="inline-block"></div> - </div> - </div> - <div class="section-row"> - <div class="section-label">$_("Disk I/O")</div> - <div class="section-value"> - <div id="container-chart-disk-io" class="inline-block"></div> - </div> - </div> - <div class="section-row"> - <div class="section-label">$_("Network I/O")</div> - <div class="section-value"> - <div id="container-chart-network-io" class="inline-block"></div> - </div> - </div> - </div> - </div> - <div id="software-update-section" class="host-section hidden"> - <h3 class="section-header" - aria-controls="content-software-update"> - $_("Software Updates") - </h3> - <div id="content-software-update" class="section-content"> - <div class="section-row"> - <div class="section-value"> - <div id="software-updates-grid-container"></div> - <div id="software-updates-progress-container" class="hidden"> - <label for="software-updates-progress-textarea">$_("Update Progress")</label> - <textarea id="software-updates-progress-textarea" readonly></textarea> - </div> - </div> - </div> - </div> - </div> - <div id="repositories-section" class="host-section hidden"> - <h3 class="section-header" - aria-controls="content-repositories"> - $_("Repositories") - </h3> - <div id="content-repositories" class="section-content"> - <div class="section-row"> - <div class="section-value"> - <div id="repositories-grid-container"></div> - </div> - </div> - </div> - </div> - <div id="debug-report-section" class="host-section hidden"> - <h3 class="section-header" - aria-controls="content-sys-reports"> - $_("Debug Reports") - </h3> - <div id="content-sys-reports" class="section-content"> - <div class="section-row"> - <div class="section-value"> - <div id="available-reports-grid-container"></div> - </div> - </div> - </div> - </div> - </div> - </div> -</script> - -<script type="text/javascript"> - kimchi.host_main(); -</script> -</body> -</html> diff --git a/src/wok/plugins/kimchi/ui/pages/report-add.html.tmpl b/src/wok/plugins/kimchi/ui/pages/report-add.html.tmpl deleted file mode 100644 index 25bf0a9..0000000 --- a/src/wok/plugins/kimchi/ui/pages/report-add.html.tmpl +++ /dev/null @@ -1,56 +0,0 @@ -#* - * 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. - *# -#unicode UTF-8 -#import gettext -#from wok.cachebust import href -#silent t = gettext.translation($lang.domain, $lang.localedir, languages=$lang.lang, fallback=True) -#silent _ = t.gettext -#silent _t = t.gettext -<!DOCTYPE html> -<div id="report-add-window" class="window"> - <header> - <h1 class="title h1 grey">$_("Generate a New Debug Report")</h1> - </header> - <div class="content"> - <form id="form-report-add"> - <section class="form-section"> - <h2> - <label for="report-name-textbox">$_("Report Name")</label> - </h2> - <div class="field"> - <input type="text" class="text" id="report-name-textbox" name="name" /> - <span class="icon-info-circled light-grey c1"></span> - <span class="info-add-debug-report"> - $_("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 (\"-\").") - </span> - </div> - </section> - </form> - </div> - <footer> - <div class="btn-group"> - <button id="button-report-add" class="btn-normal"><span class="text">$_("Generate")</span></button> - <button id="button-report-cancel" class="btn-normal close" type="button"> - <span calss="text">$_("Cancel")</span> - </button> - </div> - </footer> -</div> -<script> - kimchi.report_add_main(); -</script> diff --git a/src/wok/plugins/kimchi/ui/pages/report-rename.html.tmpl b/src/wok/plugins/kimchi/ui/pages/report-rename.html.tmpl deleted file mode 100644 index 90a0a80..0000000 --- a/src/wok/plugins/kimchi/ui/pages/report-rename.html.tmpl +++ /dev/null @@ -1,56 +0,0 @@ -#* - * 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. - *# -#unicode UTF-8 -#import gettext -#from wok.cachebust import href -#silent t = gettext.translation($lang.domain, $lang.localedir, languages=$lang.lang, fallback=True) -#silent _ = t.gettext -#silent _t = t.gettext -<!DOCTYPE html> -<div id="report-rename-window" class="window"> - <header> - <h1 class="title h1 grey">$_("Rename a Debug Report")</h1> - </header> - <div class="content"> - <form id="form-report-rename"> - <section class="form-section"> - <h2> - <label for="report-name-textbox">$_("Report Name")</label> - </h2> - <div class="field"> - <input type="text" class="text" id="report-name-textbox" name="name" /> - <span class="icon-info-circled light-grey c1"></span> - <span class="info-debug-report-rename"> - $_("The name used to identify the report. Name can contain: letters, digits and hyphen (\"-\").") - </span> - </div> - </section> - </form> - </div> - <footer> - <div class="btn-group"> - <button id="button-report-rename" class="btn-normal"><span class="text">$_("Submit")</span></button> - <button id-"button-report-rename-cancel" class="btn-normal close" type="button"> - <span class="text">$_("Cancel")</span> - </button> - </div> - </footer> -</div> -<script> - kimchi.report_rename_main(); -</script> diff --git a/src/wok/plugins/kimchi/ui/pages/repository-add.html.tmpl b/src/wok/plugins/kimchi/ui/pages/repository-add.html.tmpl deleted file mode 100644 index 950252a..0000000 --- a/src/wok/plugins/kimchi/ui/pages/repository-add.html.tmpl +++ /dev/null @@ -1,113 +0,0 @@ -#* - * 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. - *# -#unicode UTF-8 -#import gettext -#from wok.cachebust import href -#silent t = gettext.translation($lang.domain, $lang.localedir, languages=$lang.lang, fallback=True) -#silent _ = t.gettext -#silent _t = t.gettext -<div id="repository-add-window" class="window"> - <form id="form-repository-add"> - <header class="window-header"> - <h1 class="title h1 grey">$_("Add a Repository")</h1> - </header> - <section> - <div class="content"> - <div class="form-section yum"> - <h2>$_("Identifier")</h2> - <div class="field"> - <div class="textbox-wrapper"> - <input type="text" class="text" name="repo_id" /> - </div> - <div class="icon-info-circled light-grey c1 help-inline"></div> - <p class="text-help help-inline"> - $_("Single word, unique identifier for the repository.") - </p> - </div> - </div> - <section class="form-section yum"> - <h2>$_("Name")</h2> - <div class="field"> - <div class="textbox-wrapper"> - <input type="text" class="text" name="config[repo_name]" /> - </div> - <div class="icon-info-circled light-grey c1 help-inline"></div> - <p class="text-help help-inline"> - $_("Textual name for the repository.") - </p> - </div> - </section> - <section class="form-section"> - <h2>$_("URL")<span class="required" role="presentation" title='$_("Required Field")'>*</span></h2> - <div class="field"> - <div class="textbox-wrapper"> - <input type="text" class="text required" name="baseurl" /> - </div> - <div class="icon-info-circled light-grey c1 help-inline"></div> - <p class="text-help help-inline"> - $_("URL to the repository. Supported protocols are http, ftp, and file.") - </p> - </div> - <div class="field yum"> - <p class="yum"> - <input type="checkbox" name="isMirror" value="true" id="isMirror" /> - <label id="isMirrorLabel" for="isMirror">$_("Repository is a mirror")</label> - </p> - </div> - </section> - <section class="form-section repository-dist deb"> - <h2>$_("Distribution")</h2> - <div class="field"> - <div class="textbox-wrapper"> - <input type="text" class="text" name="config[dist]" /> - </div> - <div class="icon-info-circled light-grey c1 help-inline"></div> - <p class="text-help help-inline"> - $_("Distribution of the DEB repository.") - </p> - </div> - </section> - <section class="form-section repository-comps deb"> - <h2>$_("Components")</h2> - <div class="field"> - <div class="textbox-wrapper"> - <input type="text" class="text" name="config[comps]" /> - </div> - <div class="icon-info-circled light-grey c1 help-inline"></div> - <p class="text-help help-inline"> - $_("List of components in DEB repository.") - </p> - </div> - </section> - </div> - </section> - <footer> - <div class="btn-group"> - <button type="submit" id="button-repository-add" class="btn-normal" disabled="disabled"> - <span class="text">$_("Add")</span> - </button> - <button type="button" id="button-repository-close" class="btn-normal close"> - <span class="text">$("Cancel")</span> - </button> - </div> - </footer> - </form> -</div> -<script> - kimchi.repository_add_main(); -</script> diff --git a/src/wok/plugins/kimchi/ui/pages/repository-edit.html.tmpl b/src/wok/plugins/kimchi/ui/pages/repository-edit.html.tmpl deleted file mode 100644 index e5a3cfb..0000000 --- a/src/wok/plugins/kimchi/ui/pages/repository-edit.html.tmpl +++ /dev/null @@ -1,117 +0,0 @@ -#* - * 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. - *# -#unicode UTF-8 -#import gettext -#from wok.cachebust import href -#silent t = gettext.translation($lang.domain, $lang.localedir, languages=$lang.lang, fallback=True) -#silent _ = t.gettext -#silent _t = t.gettext - -<div id="repository-edit-window" class="window"> - <form id="form-repository-edit"> - <header> - <h1 class="title h1 grey">$_("Edit Repository")</h1> - </header> - <div class="content"> - <section id="form-repository-edit"> - <fieldset class="repository-edit-fieldset"> - <div class="repository-id yum"> - <div class="repository-edit-wrapper-label"> - <label for="repository-edit-id-textbox">$_("ID")</label> - </div> - <div class="repository-edit-wrapper-controls"> - <input id="repository-edit-id-textbox" name="repo_id" type="text" disabled="disabled" readonly="readonly"/> - </div> - </div> - <div class="repository-name yum"> - <div class="repository-edit-wrapper-label"> - <label for="repository-edit-name-textbox">$_("Name")</label> - </div> - <div class="repository-edit-wrapper-controls"> - <input id="repository-edit-name-textbox" class="yum" name="config[repo_name]" type="text" /> - </div> - </div> - <div class="repository-url"> - <div class="repository-edit-wrapper-label"> - <label for="repository-edit-baseurl-textbox">$_("URL")</label> - </div> - <div class="repository-edit-wrapper-controls"> - <input id="repository-edit-baseurl-textbox" name="baseurl" type="text" /> - </div> - </div> - <div class="repository-dist deb"> - <div class="repository-edit-wrapper-label"> - <label for="repository-edit-urlargs-textbox">$_("Distribution")</label> - </div> - <div class="repository-edit-wrapper-controls"> - <input id="repository-edit-urlargs-textbox" class="deb" name="config[dist]" type="text" /> - </div> - </div> - <div class="repository-mirrorlist yum"> - <div class="repository-edit-wrapper-label"> - <label for="repository-edit-urlargs-textbox">$_("Mirror List URL")</label> - </div> - <div class="repository-edit-wrapper-controls"> - <input id="repository-edit-urlargs-textbox" class="yum" name="config[mirrorlist]" type="text" /> - </div> - </div> - <div class="repository-comps deb"> - <div class="repository-edit-wrapper-label"> - <label for="repository-edit-urlargs-textbox">$_("Components")</label> - </div> - <div class="repository-edit-wrapper-controls"> - <input id="repository-edit-urlargs-textbox" class="deb" name="config[comps]" type="text" /> - </div> - </div> - <div class="repository-gpgkey yum"> - <div class="repository-edit-wrapper-label"> - <label for="repository-edit-gpgkey-textbox">$_("GPG Key")</label> - </div> - <div class="repository-edit-wrapper-controls"> - <input id="repository-edit-gpgkey-textbox" class="yum" name="config[gpgkey]" type="text" /> - </div> - </div> - <div class="repository-gpgcheck yum"> - <div class="repository-edit-wrapper-label"> - <label>$_("GPG Check")</label> - </div> - <div class="repository-edit-wrapper-controls"> - <input id="repository-edit-gpgcheck-radio-true" class="yum" name="config[gpgcheck]" type="radio" value="true" /> - <label for="repository-edit-gpgcheck-radio-true">$_("Yes")</label> - <input id="repository-edit-gpgcheck-radio-false" class="yum" name="config[gpgcheck]" type="radio" value="false" /> - <label for="repository-edit-gpgcheck-radio-false">$_("No")</label> - </div> - </div> - </fieldset> - </section> - </div> - <footer> - <div class="btn-group"> - <button type="submit" id="repository-edit-button-save" class="btn-normal"> - <span class="text">$_("Save")</span> - </button> - <button type="button" id="repository-edit-button-cancel" class="close btn-normal"> - <span class="text">$_("Cancel")</span> - </button> - </div> - </footer> - </form> -</div> -<script type="text/javascript"> - kimchi.repository_edit_main(); -</script> -- 2.1.0

From: chandrureddy <chandra@linux.vnet.ibm.com> --- src/wok/plugins/gingerbase/ui/js/Makefile.am | 28 + .../plugins/gingerbase/ui/js/src/gingerbase.api.js | 372 +++++++++ .../gingerbase/ui/js/src/gingerbase.host.js | 860 +++++++++++++++++++++ .../gingerbase/ui/js/src/gingerbase.main.js | 27 + .../ui/js/src/gingerbase.report_add_main.js | 73 ++ .../ui/js/src/gingerbase.report_rename_main.js | 67 ++ .../ui/js/src/gingerbase.repository_add_main.js | 97 +++ .../ui/js/src/gingerbase.repository_edit_main.js | 75 ++ src/wok/plugins/kimchi/ui/js/src/kimchi.host.js | 858 -------------------- .../kimchi/ui/js/src/kimchi.report_add_main.js | 72 -- .../kimchi/ui/js/src/kimchi.report_rename_main.js | 66 -- .../kimchi/ui/js/src/kimchi.repository_add_main.js | 96 --- .../ui/js/src/kimchi.repository_edit_main.js | 74 -- 13 files changed, 1599 insertions(+), 1166 deletions(-) create mode 100644 src/wok/plugins/gingerbase/ui/js/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.api.js create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.host.js create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.main.js create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.report_add_main.js create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.report_rename_main.js create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.repository_add_main.js create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.repository_edit_main.js delete mode 100644 src/wok/plugins/kimchi/ui/js/src/kimchi.host.js delete mode 100644 src/wok/plugins/kimchi/ui/js/src/kimchi.report_add_main.js delete mode 100644 src/wok/plugins/kimchi/ui/js/src/kimchi.report_rename_main.js delete mode 100644 src/wok/plugins/kimchi/ui/js/src/kimchi.repository_add_main.js delete mode 100644 src/wok/plugins/kimchi/ui/js/src/kimchi.repository_edit_main.js diff --git a/src/wok/plugins/gingerbase/ui/js/Makefile.am b/src/wok/plugins/gingerbase/ui/js/Makefile.am new file mode 100644 index 0000000..8713d4f --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/js/Makefile.am @@ -0,0 +1,28 @@ +# +# Ginger Base +# +# Copyright IBM, Corp. 2015 +# +# Code derived from Project Kimchi +# 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 + +jsdir = $(datadir)/wok/plugins/gingerbase/ui/js + +dist_js_DATA = gingerbase.min.js $(filter-out gingerbase.min.js, $(wildcard *.js)) + +gingerbase.min.js: src/*.js + cat $(sort $^) > $@ + +CLEANFILES = gingerbase.min.js diff --git a/src/wok/plugins/gingerbase/ui/js/src/gingerbase.api.js b/src/wok/plugins/gingerbase/ui/js/src/gingerbase.api.js new file mode 100644 index 0000000..ef6d9d4 --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/js/src/gingerbase.api.js @@ -0,0 +1,372 @@ +/* + * Project Ginger Base + * + * Copyright IBM, Corp. 2013-2015 + * + * Code derived from Project Kimchi + * 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 = { + + widget: {}, + + trackingTasks: [], + + /** + * + * Get host capabilities + * suc: callback if succeed err: callback if failed + */ + getCapabilities : function(suc, err, done) { + done = typeof done !== 'undefined' ? done: function(){}; + wok.requestJSON({ + url : "plugins/gingerbase/host/capabilities", + type : "GET", + contentType : "application/json", + dataType : "json", + success: suc, + error: err, + complete: done + }); + }, + + /** + * Get the i18 strings. + */ + getI18n: function(suc, err, url, sync) { + wok.requestJSON({ + url : url ? url : 'plugins/gingerbase/i18n.json', + type : 'GET', + resend: true, + dataType : 'json', + async : !sync, + success : suc, + error: err + }); + }, + + /** + * Get the host static information. + */ + getHost: function(suc, err) { + wok.requestJSON({ + url : 'plugins/gingerbase/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) { + wok.requestJSON({ + url : 'plugins/gingerbase/host/stats', + type : 'GET', + contentType : 'application/json', + headers: {'Wok-Robot': 'wok-robot'}, + dataType : 'json', + success : suc, + error: err + }); + }, + + /** + * Get the historic host stats. + */ + getHostStatsHistory : function(suc, err) { + wok.requestJSON({ + url : 'plugins/gingerbase/host/stats/history', + type : 'GET', + resend: true, + contentType : 'application/json', + headers: {'Wok-Robot': 'wok-robot'}, + dataType : 'json', + success : suc, + error: err + }); + }, + + getTask : function(taskId, suc, err) { + wok.requestJSON({ + url : 'plugins/gingerbase/tasks/' + encodeURIComponent(taskId), + type : 'GET', + contentType : 'application/json', + dataType : 'json', + success : suc, + error : err + }); + }, + + getTasksByFilter : function(filter, suc, err, sync) { + wok.requestJSON({ + url : 'plugins/gingerbase/tasks?' + filter, + type : 'GET', + contentType : 'application/json', + dataType : 'json', + async : !sync, + success : suc, + error : err + }); + }, + + listReports : function(suc, err) { + wok.requestJSON({ + url : 'plugins/gingerbase/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); + }; + + wok.requestJSON({ + url : 'plugins/gingerbase/debugreports', + type : "POST", + contentType : "application/json", + data : JSON.stringify(settings), + dataType : "json", + success : onResponse, + error : err + }); + }, + + renameReport : function(name, settings, suc, err) { + $.ajax({ + url : "plugins/gingerbase/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']); + wok.requestJSON({ + url : 'plugins/gingerbase/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 = 'plugins/gingerbase/host/' + (reboot ? 'reboot' : 'shutdown'); + wok.requestJSON({ + url : url, + type : 'POST', + contentType : 'application/json', + dataType : 'json', + success : suc, + error : err + }); + }, + + listHostPartitions : function(suc, err) { + wok.requestJSON({ + url : 'plugins/gingerbase/host/partitions', + type : 'GET', + contentType : 'application/json', + dataType : 'json', + success : suc, + error : err + }); + }, + + listSoftwareUpdates : function(suc, err) { + wok.requestJSON({ + url : 'plugins/gingerbase/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; + } + }; + + wok.requestJSON({ + url : 'plugins/gingerbase/host/swupdate', + type : "POST", + contentType : "application/json", + dataType : "json", + success : onResponse, + error : err + }); + }, + + createRepository : function(settings, suc, err) { + wok.requestJSON({ + url : "plugins/gingerbase/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); + wok.requestJSON({ + url : "plugins/gingerbase/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 : "plugins/gingerbase/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 : "plugins/gingerbase/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); + wok.requestJSON({ + url : 'plugins/gingerbase/host/repositories/' + reposID, + type : 'DELETE', + contentType : 'application/json', + dataType : 'json', + success : suc, + error : err + }); + }, + + listRepositories : function(suc, err) { + wok.requestJSON({ + url : 'plugins/gingerbase/host/repositories', + type : 'GET', + contentType : 'application/json', + dataType : 'json', + resend: true, + success : suc, + error : err + }); + }, + + getCPUInfo : function(suc, err) { + wok.requestJSON({ + url : 'plugins/gingerbase/host/cpuinfo', + type : 'GET', + contentType : 'application/json', + dataType : 'json', + resend : true, + success : suc, + error : err ? err : function(data) { + wok.message.error(data.responseJSON.reason); + } + }); + } +}; diff --git a/src/wok/plugins/gingerbase/ui/js/src/gingerbase.host.js b/src/wok/plugins/gingerbase/ui/js/src/gingerbase.host.js new file mode 100644 index 0000000..fbbdfad --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/js/src/gingerbase.host.js @@ -0,0 +1,860 @@ +/* + * Project Ginger Base + * + * Copyright IBM, Corp. 2013-2015 + * + * Code derived from Project Kimchi + * 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['GGBREPO6004M'], + 'class': 'repository-id' + }, { + name: 'config[repo_name]', + label: i18n['GGBREPO6005M'], + 'class': 'repository-name' + }, { + name: 'enabled', + label: i18n['GGBREPO6009M'], + 'class': 'repository-enabled' + }]; + } + else if (repo_type == "deb") { + gridFields=[{ + name: 'baseurl', + label: i18n['GGBREPO6006M'], + makeTitle: true, + 'class': 'repository-baseurl deb' + }, { + name: 'enabled', + label: i18n['GGBREPO6009M'], + '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['GGBREPO6004M'], + 'class': 'repository-id' + }, { + name: 'enabled', + label: i18n['GGBREPO6009M'], + 'class': 'repository-enabled' + }, { + name: 'baseurl', + label: i18n['GGBREPO6006M'], + makeTitle: true, + 'class': 'repository-baseurl' + }]; + } + repositoriesGrid = new wok.widget.Grid({ + container: 'repositories-grid-container', + id: 'repositories-grid', + title: i18n['GGBREPO6003M'], + toolbarButtons: [{ + id: 'repositories-grid-add-button', + label: i18n['GGBREPO6012M'], + onClick: function(event) { + wok.window.open({url:'plugins/gingerbase/repository-add.html', + class: repo_type}); + } + }, { + id: 'repositories-grid-enable-button', + label: i18n['GGBREPO6016M'], + 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() { + wok.topic('kimchi/repositoryUpdated').publish(); + }); + } + }, { + id: 'repositories-grid-edit-button', + label: i18n['GGBREPO6013M'], + disabled: true, + onClick: function(event) { + var repository = repositoriesGrid.getSelected(); + if(!repository) { + return; + } + kimchi.selectedRepository = repository['repo_id']; + wok.window.open({url:'plugins/gingerbase/repository-edit.html', + class: repo_type}); + } + }, { + id: 'repositories-grid-remove-button', + label: i18n['GGBREPO6014M'], + disabled: true, + onClick: function(event) { + var repository = repositoriesGrid.getSelected(); + if(!repository) { + return; + } + + var settings = { + title : i18n['GGBREPO6001M'], + content : i18n['GGBREPO6002M'], + confirm : i18n['GGBAPI6004M'], + cancel : i18n['GGBAPI6003M'] + }; + + wok.confirm(settings, function() { + kimchi.deleteRepository( + repository['repo_id'], + function(result) { + wok.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 ? 'GGBREPO6017M' : 'GGBREPO6016M']) + .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['GGBUPD6008M']); + }); + + $('#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 wok.widget.Grid({ + container: 'software-updates-grid-container', + id: softwareUpdatesGridID, + title: i18n['GGBUPD6001M'], + rowSelection: 'disabled', + toolbarButtons: [{ + id: softwareUpdatesGridID + '-update-button', + label: i18n['GGBUPD6006M'], + disabled: true, + onClick: function(event) { + var updateButton = $(this); + var progressArea = $('#' + progressAreaID)[0]; + $('#software-updates-progress-container').removeClass('hidden'); + $(progressArea).text(''); + !wok.isElementInViewport(progressArea) && + progressArea.scrollIntoView(); + $(updateButton).text(i18n['GGBUPD6007M']).prop('disabled', true); + + kimchi.updateSoftware(function(result) { + reloadProgressArea(result); + $(updateButton).text(i18n['GGBUPD6006M']).prop('disabled', false); + wok.topic('kimchi/softwareUpdated').publish({ + result: result + }); + }, function(error) { + var message = error && error['responseJSON'] && error['responseJSON']['reason']; + wok.message.error(message || i18n['GGBUPD6009M']); + $(updateButton).text(i18n['GGBUPD6006M']).prop('disabled', false); + }, reloadProgressArea); + } + }], + frozenFields: [], + fields: [{ + name: 'package_name', + label: i18n['GGBUPD6002M'], + 'class': 'software-update-name' + }, { + name: 'version', + label: i18n['GGBUPD6003M'], + 'class': 'software-update-version' + }, { + name: 'arch', + label: i18n['GGBUPD6004M'], + 'class': 'software-update-arch' + }, { + name: 'repository', + label: i18n['GGBUPD6005M'], + '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['GGBUPD6008M']); + }); + }; + + var reportGridID = 'available-reports-grid'; + var reportGrid = null; + var enableReportButtons = function(toEnable) { + var buttonID = '#{grid}-{btn}-button'; + $.each(['rename', 'remove', 'download'], function(i, n) { + $(wok.substitute(buttonID, { + grid: reportGridID, + btn: n + })).prop('disabled', !toEnable); + }); + }; + var initReportGrid = function(reports) { + reportGrid = new wok.widget.Grid({ + container: 'available-reports-grid-container', + id: reportGridID, + title: i18n['GGBDR6002M'], + toolbarButtons: [{ + id: reportGridID + '-generate-button', + label: i18n['GGBDR6006M'], + onClick: function(event) { + wok.window.open('plugins/gingerbase/report-add.html'); + } + }, { + id: reportGridID + '-rename-button', + label: i18n['GGBDR6008M'], + disabled: true, + onClick: function(event) { + var report = reportGrid.getSelected(); + if(!report) { + return; + } + + kimchi.selectedReport = report['name']; + wok.window.open('plugins/gingerbase/report-rename.html'); + } + }, { + id: reportGridID + '-remove-button', + label: i18n['GGBDR6009M'], + disabled: true, + onClick: function(event) { + var report = reportGrid.getSelected(); + if(!report) { + return; + } + + var settings = { + title : i18n['GGBAPI6004M'], + content : i18n['GGBDR6001M'], + confirm : i18n['GGBAPI6002M'], + cancel : i18n['GGBAPI6003M'] + }; + + wok.confirm(settings, function() { + kimchi.deleteReport({ + name: report['name'] + }, function(result) { + listDebugReports(); + }, function(error) { + wok.message.error(error.responseJSON.reason); + }); + }); + } + }, { + id: reportGridID + '-download-button', + label: i18n['GGBDR6010M'], + 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['GGBDR6007M']) { + var gridElement = $('#'+ reportGridID); + var row = $('tr:contains(' + report['name'] + ')', gridElement); + enableReportButtons(false); + row.attr('class', ''); + } + else { + enableReportButtons(true); + } + }, + frozenFields: [], + fields: [{ + name: 'name', + label: i18n['GGBDR6003M'], + 'class': 'debug-report-name' + }, { + name: 'time', + label: i18n['GGBDR6005M'], + 'class': 'debug-report-time' + }], + data: reports + }); + }; + + var getPendingReports = function() { + var reports = [] + var filter = 'status=running&target_uri=' + encodeURIComponent('^/plugins/gingerbase/debugreports/*') + + kimchi.getTasksByFilter(filter, function(tasks) { + for(var i = 0; i < tasks.length; i++) { + reportName = tasks[i].target_uri.replace(/^\/plugins\/gingerbase\/debugreports\//, '') || i18n['GGBDR6012M']; + reports.push({'name': reportName, 'time': i18n['GGBDR6007M']}) + + if(kimchi.trackingTasks.indexOf(tasks[i].id) >= 0) { + continue; + } + + kimchi.trackTask(tasks[i].id, function(result) { + wok.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 && wok.message.error(errText); + wok.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['GGBDR6007M'] + ')', 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['GGBAPI6004M'], + content : i18n['GGBHOST6008M'], + confirm : i18n['GGBAPI6002M'], + cancel : i18n['GGBAPI6003M'] + }; + + wok.confirm(settings, function() { + kimchi.shutdown(params); + $(shutdownButtonID).prop('disabled', true); + $(restartButtonID).prop('disabled', true); + // Check if there is any VM is running. + // FIXME : Find alternative way to figure out if any vms running + // kimchi.listVMs(function(vms) { + // for(var i = 0; i < vms.length; i++) { + // if(vms[i]['state'] === 'running') { + // wok.message.error.code('GGBHOST6001E'); + // $(shutdownButtonID).prop('disabled', false); + // $(restartButtonID).prop('disabled', false); + // return; + // } + // } + // + // }); + }, function() { + }); + }; + + var initPage = function() { + $('#host-info-container .section-header').each(function(i, header) { + $('<span class="arrow"></span>').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']); + wok.topic('kimchi/repositoryAdded') + .subscribe(listRepositories); + wok.topic('kimchi/repositoryUpdated') + .subscribe(listRepositories); + wok.topic('kimchi/repositoryDeleted') + .subscribe(listRepositories); + } + + if(kimchi.capabilities['update_tool']) { + $('#software-update-section').removeClass('hidden'); + initSoftwareUpdatesGrid(); + wok.topic('kimchi/softwareUpdated') + .subscribe(listSoftwareUpdates); + $('#software-updates-progress-container').accordion({ + collapsible: true + }); + } + + if(kimchi.capabilities['system_report_tool']) { + listDebugReports(); + wok.topic('kimchi/debugReportAdded') + .subscribe(listDebugReports); + wok.topic('kimchi/debugReportRenamed') + .subscribe(listDebugReports); + } + }; + setupUI(); + }; + + kimchi.getHost(function(data) { + var htmlTmpl = $('#host-tmpl').html(); + data['logo'] = data['logo'] || ''; + data['memory'] = wok.formatMeasurement(data['memory'], { + fixed: 2 + }); + var templated = wok.substitute(htmlTmpl, data); + $('#host-content-container').html(templated); + + initPage(); + initTracker(); + }); + + var StatsMgr = function() { + var statsArray = { + cpu: { + u: { + type: 'percent', + legend: i18n['GGBHOST6002M'], + points: [] + } + }, + memory: { + u: { + type: 'value', + base: 2, + fixed: 2, + legend: i18n['GGBHOST6003M'], + points: [] + } + }, + diskIO: { + r: { + type: 'value', + base: 2, + fixed: 2, + unit: 'B/s', + legend: i18n['GGBHOST6004M'], + points: [] + }, + w: { + type: 'value', + base: 2, + fixed: 2, + unit: 'B/s', + legend: i18n['GGBHOST6005M'], + 'class': 'disk-write', + points: [] + } + }, + networkIO: { + r: { + type: 'value', + base: 2, + fixed: 2, + unit: 'B/s', + legend: i18n['GGBHOST6006M'], + points: [] + }, + s: { + type: 'value', + base: 2, + fixed: 2, + unit: 'B/s', + legend: i18n['GGBHOST6007M'], + '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<stats['memory'].length;i++){ + result.memory.u['v'].push(stats['memory'][i]['avail']); + result.memory.u['max']=Math.max(result.memory.u['max'],stats['memory'][i]['total']); + } + } + else { + result.memory.u['v']=stats['memory']['avail'], + result.memory.u['max']=stats['memory']['total'] + } + return(result); + }; + + + var statsCallback = function(stats) { + var unifiedStats = UnifyStats(stats); + statsPool.add(unifiedStats); + for(var key in charts) { + var chart = charts[key]; + chart.updateUI(statsPool.get(key)); + } + timer = setTimeout(function() { + continueTrack(); + }, 1000); + }; + + var track = function() { + kimchi.getHostStatsHistory(statsCallback, + function() { + continueTrack(); + }); + }; + + var continueTrack = function() { + kimchi.getHostStats(statsCallback, + function() { + continueTrack(); + }); + }; + + var destroy = function() { + timer && clearTimeout(timer); + timer = null; + }; + + return { + setCharts: setCharts, + start: track, + stop: destroy + }; + }; + + var initTracker = function() { + // TODO: Extend tabs with onUnload event to unregister timers. + if(kimchi.hostTimer) { + kimchi.hostTimer.stop(); + delete kimchi.hostTimer; + } + + var trackedCharts = { + cpu: new wok.widget.LineChart({ + id: 'chart-cpu', + node: 'container-chart-cpu', + type: 'percent' + }), + memory: new wok.widget.LineChart({ + id: 'chart-memory', + node: 'container-chart-memory', + type: 'value' + }), + diskIO: new wok.widget.LineChart({ + id: 'chart-disk-io', + node: 'container-chart-disk-io', + type: 'value' + }), + networkIO: new wok.widget.LineChart({ + id: 'chart-network-io', + node: 'container-chart-network-io', + type: 'value' + }) + }; + + if(kimchi.hostTimer) { + kimchi.hostTimer.setCharts(trackedCharts); + } + else { + kimchi.hostTimer = new Tracker(trackedCharts); + kimchi.hostTimer.start(); + } + }; + + $('#host-root-container').on('remove', function() { + if(kimchi.hostTimer) { + kimchi.hostTimer.stop(); + delete kimchi.hostTimer; + } + + repositoriesGrid && repositoriesGrid.destroy(); + wok.topic('kimchi/repositoryAdded') + .unsubscribe(listRepositories); + wok.topic('kimchi/repositoryUpdated') + .unsubscribe(listRepositories); + wok.topic('kimchi/repositoryDeleted') + .unsubscribe(listRepositories); + + softwareUpdatesGrid && softwareUpdatesGrid.destroy(); + wok.topic('kimchi/softwareUpdated').unsubscribe(listSoftwareUpdates); + + reportGrid && reportGrid.destroy(); + wok.topic('kimchi/debugReportAdded').unsubscribe(listDebugReports); + wok.topic('kimchi/debugReportRenamed').unsubscribe(listDebugReports); + }); +}; diff --git a/src/wok/plugins/gingerbase/ui/js/src/gingerbase.main.js b/src/wok/plugins/gingerbase/ui/js/src/gingerbase.main.js new file mode 100644 index 0000000..9cb4fb4 --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/js/src/gingerbase.main.js @@ -0,0 +1,27 @@ +/* + * Project Ginger Base + * + * Copyright IBM, Corp. 2013-2015 + * + * Code derived from Project Kimchi + * 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.capabilities = undefined; +kimchi.getCapabilities(function(result) { + kimchi.capabilities = result; + + if(kimchi.capabilities.federation=="on") + $('#peers').removeClass('hide-content'); +}, function() { + kimchi.capabilities = {}; +}); diff --git a/src/wok/plugins/gingerbase/ui/js/src/gingerbase.report_add_main.js b/src/wok/plugins/gingerbase/ui/js/src/gingerbase.report_add_main.js new file mode 100644 index 0000000..29ba13a --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/js/src/gingerbase.report_add_main.js @@ -0,0 +1,73 @@ +/* + * Project Ginger Base + * + * Copyright IBM, Corp. 2013-2015 + * + * Code derived from Project Kimchi + * 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)) { + wok.message.error.code('GGBDR6011M'); + return false; + } + var formData = addReportForm.serializeObject(); + var taskAccepted = false; + var onTaskAccepted = function() { + if(taskAccepted) { + return; + } + taskAccepted = true; + wok.window.close(); + wok.topic('kimchi/debugReportAdded').publish(); + }; + + kimchi.createReport(formData, function(result) { + onTaskAccepted(); + wok.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 && wok.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); +}; diff --git a/src/wok/plugins/gingerbase/ui/js/src/gingerbase.report_rename_main.js b/src/wok/plugins/gingerbase/ui/js/src/gingerbase.report_rename_main.js new file mode 100644 index 0000000..0217afc --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/js/src/gingerbase.report_rename_main.js @@ -0,0 +1,67 @@ +/* + * Project Ginger Base + * + * Copyright IBM, Corp. 2015 + * + * Code derived from Project Kimchi + * 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) { + wok.message.error.code('GGBDR6013M'); + return false; + } + + var validator = RegExp("^[A-Za-z0-9-]*$"); + if (!validator.test(reportName)) { + wok.message.error.code('GGBDR6011M'); + 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); + wok.window.close(); + wok.topic('kimchi/debugReportRenamed').publish({ + result: result + }); + }, function(result) { + var errText = result && + result['responseJSON'] && + result['responseJSON']['reason']; + wok.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(); +}; diff --git a/src/wok/plugins/gingerbase/ui/js/src/gingerbase.repository_add_main.js b/src/wok/plugins/gingerbase/ui/js/src/gingerbase.repository_add_main.js new file mode 100644 index 0000000..4aa3849 --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/js/src/gingerbase.repository_add_main.js @@ -0,0 +1,97 @@ +/* + * Project Ginger Base + * + * Copyright IBM, Corp. 2015 + * + * Code derived from Project Kimchi + * 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() { + wok.topic('kimchi/repositoryAdded').publish(); + wok.window.close(); + }, function(jqXHR, textStatus, errorThrown) { + var reason = jqXHR && + jqXHR['responseJSON'] && + jqXHR['responseJSON']['reason']; + wok.message.error(reason); + }); + return false; + }; + + $(addForm).on('submit', addRepository); +}; diff --git a/src/wok/plugins/gingerbase/ui/js/src/gingerbase.repository_edit_main.js b/src/wok/plugins/gingerbase/ui/js/src/gingerbase.repository_edit_main.js new file mode 100644 index 0000000..5950da6 --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/js/src/gingerbase.repository_edit_main.js @@ -0,0 +1,75 @@ +/* + * Project Ginger Base + * + * Copyright IBM, Corp. 2015 + * + * Code derived from Project Kimchi + * 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() { + wok.topic('kimchi/repositoryUpdated').publish(); + wok.window.close(); + }, function(jqXHR, textStatus, errorThrown) { + var reason = jqXHR && + jqXHR['responseJSON'] && + jqXHR['responseJSON']['reason']; + wok.message.error(reason); + }); + + return false; + }; + + $(editForm).on('submit', editRepository); + $(saveButton).on('click', editRepository); +}; diff --git a/src/wok/plugins/kimchi/ui/js/src/kimchi.host.js b/src/wok/plugins/kimchi/ui/js/src/kimchi.host.js deleted file mode 100644 index c3765dc..0000000 --- a/src/wok/plugins/kimchi/ui/js/src/kimchi.host.js +++ /dev/null @@ -1,858 +0,0 @@ -/* - * 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.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[display_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 wok.widget.Grid({ - container: 'repositories-grid-container', - id: 'repositories-grid', - title: i18n['KCHREPO6003M'], - toolbarButtons: [{ - id: 'repositories-grid-add-button', - label: i18n['KCHREPO6012M'], - onClick: function(event) { - wok.window.open({url:'plugins/kimchi/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() { - wok.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']; - wok.window.open({url:'plugins/kimchi/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'] - }; - - wok.confirm(settings, function() { - kimchi.deleteRepository( - repository['repo_id'], - function(result) { - wok.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 wok.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(''); - !wok.isElementInViewport(progressArea) && - progressArea.scrollIntoView(); - $(updateButton).text(i18n['KCHUPD6007M']).prop('disabled', true); - - kimchi.updateSoftware(function(result) { - reloadProgressArea(result); - $(updateButton).text(i18n['KCHUPD6006M']).prop('disabled', false); - wok.topic('kimchi/softwareUpdated').publish({ - result: result - }); - }, function(error) { - var message = error && error['responseJSON'] && error['responseJSON']['reason']; - wok.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) { - $(wok.substitute(buttonID, { - grid: reportGridID, - btn: n - })).prop('disabled', !toEnable); - }); - }; - var initReportGrid = function(reports) { - reportGrid = new wok.widget.Grid({ - container: 'available-reports-grid-container', - id: reportGridID, - title: i18n['KCHDR6002M'], - toolbarButtons: [{ - id: reportGridID + '-generate-button', - label: i18n['KCHDR6006M'], - onClick: function(event) { - wok.window.open('plugins/kimchi/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']; - wok.window.open('plugins/kimchi/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'] - }; - - wok.confirm(settings, function() { - kimchi.deleteReport({ - name: report['name'] - }, function(result) { - listDebugReports(); - }, function(error) { - wok.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('^/plugins/kimchi/debugreports/*') - - kimchi.getTasksByFilter(filter, function(tasks) { - for(var i = 0; i < tasks.length; i++) { - reportName = tasks[i].target_uri.replace(/^\/plugins\/kimchi\/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) { - wok.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 && wok.message.error(errText); - wok.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'] - }; - - wok.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') { - wok.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) { - $('<span class="arrow"></span>').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']); - wok.topic('kimchi/repositoryAdded') - .subscribe(listRepositories); - wok.topic('kimchi/repositoryUpdated') - .subscribe(listRepositories); - wok.topic('kimchi/repositoryDeleted') - .subscribe(listRepositories); - } - - if(kimchi.capabilities['update_tool']) { - $('#software-update-section').removeClass('hidden'); - initSoftwareUpdatesGrid(); - wok.topic('kimchi/softwareUpdated') - .subscribe(listSoftwareUpdates); - $('#software-updates-progress-container').accordion({ - collapsible: true - }); - } - - if(kimchi.capabilities['system_report_tool']) { - listDebugReports(); - wok.topic('kimchi/debugReportAdded') - .subscribe(listDebugReports); - wok.topic('kimchi/debugReportRenamed') - .subscribe(listDebugReports); - } - }; - setupUI(); - }; - - kimchi.getHost(function(data) { - var htmlTmpl = $('#host-tmpl').html(); - data['logo'] = data['logo'] || ''; - data['memory'] = wok.formatMeasurement(data['memory'], { - fixed: 2 - }); - var templated = wok.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<stats['memory'].length;i++){ - result.memory.u['v'].push(stats['memory'][i]['avail']); - result.memory.u['max']=Math.max(result.memory.u['max'],stats['memory'][i]['total']); - } - } - else { - result.memory.u['v']=stats['memory']['avail'], - result.memory.u['max']=stats['memory']['total'] - } - return(result); - }; - - - var statsCallback = function(stats) { - var unifiedStats = UnifyStats(stats); - statsPool.add(unifiedStats); - for(var key in charts) { - var chart = charts[key]; - chart.updateUI(statsPool.get(key)); - } - timer = setTimeout(function() { - continueTrack(); - }, 1000); - }; - - var track = function() { - kimchi.getHostStatsHistory(statsCallback, - function() { - continueTrack(); - }); - }; - - var continueTrack = function() { - kimchi.getHostStats(statsCallback, - function() { - continueTrack(); - }); - }; - - var destroy = function() { - timer && clearTimeout(timer); - timer = null; - }; - - return { - setCharts: setCharts, - start: track, - stop: destroy - }; - }; - - var initTracker = function() { - // TODO: Extend tabs with onUnload event to unregister timers. - if(kimchi.hostTimer) { - kimchi.hostTimer.stop(); - delete kimchi.hostTimer; - } - - var trackedCharts = { - cpu: new wok.widget.LineChart({ - id: 'chart-cpu', - node: 'container-chart-cpu', - type: 'percent' - }), - memory: new wok.widget.LineChart({ - id: 'chart-memory', - node: 'container-chart-memory', - type: 'value' - }), - diskIO: new wok.widget.LineChart({ - id: 'chart-disk-io', - node: 'container-chart-disk-io', - type: 'value' - }), - networkIO: new wok.widget.LineChart({ - id: 'chart-network-io', - node: 'container-chart-network-io', - type: 'value' - }) - }; - - if(kimchi.hostTimer) { - kimchi.hostTimer.setCharts(trackedCharts); - } - else { - kimchi.hostTimer = new Tracker(trackedCharts); - kimchi.hostTimer.start(); - } - }; - - $('#host-root-container').on('remove', function() { - if(kimchi.hostTimer) { - kimchi.hostTimer.stop(); - delete kimchi.hostTimer; - } - - repositoriesGrid && repositoriesGrid.destroy(); - wok.topic('kimchi/repositoryAdded') - .unsubscribe(listRepositories); - wok.topic('kimchi/repositoryUpdated') - .unsubscribe(listRepositories); - wok.topic('kimchi/repositoryDeleted') - .unsubscribe(listRepositories); - - softwareUpdatesGrid && softwareUpdatesGrid.destroy(); - wok.topic('kimchi/softwareUpdated').unsubscribe(listSoftwareUpdates); - - reportGrid && reportGrid.destroy(); - wok.topic('kimchi/debugReportAdded').unsubscribe(listDebugReports); - wok.topic('kimchi/debugReportRenamed').unsubscribe(listDebugReports); - }); -}; diff --git a/src/wok/plugins/kimchi/ui/js/src/kimchi.report_add_main.js b/src/wok/plugins/kimchi/ui/js/src/kimchi.report_add_main.js deleted file mode 100644 index 5f098d3..0000000 --- a/src/wok/plugins/kimchi/ui/js/src/kimchi.report_add_main.js +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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)) { - wok.message.error.code('KCHDR6011M'); - return false; - } - var formData = addReportForm.serializeObject(); - var taskAccepted = false; - var onTaskAccepted = function() { - if(taskAccepted) { - return; - } - taskAccepted = true; - wok.window.close(); - wok.topic('kimchi/debugReportAdded').publish(); - }; - - kimchi.createReport(formData, function(result) { - onTaskAccepted(); - wok.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 && wok.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); -}; diff --git a/src/wok/plugins/kimchi/ui/js/src/kimchi.report_rename_main.js b/src/wok/plugins/kimchi/ui/js/src/kimchi.report_rename_main.js deleted file mode 100644 index 1bdb8d9..0000000 --- a/src/wok/plugins/kimchi/ui/js/src/kimchi.report_rename_main.js +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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) { - wok.message.error.code('KCHDR6013M'); - return false; - } - - var validator = RegExp("^[A-Za-z0-9-]*$"); - if (!validator.test(reportName)) { - wok.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); - wok.window.close(); - wok.topic('kimchi/debugReportRenamed').publish({ - result: result - }); - }, function(result) { - var errText = result && - result['responseJSON'] && - result['responseJSON']['reason']; - wok.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(); -}; diff --git a/src/wok/plugins/kimchi/ui/js/src/kimchi.repository_add_main.js b/src/wok/plugins/kimchi/ui/js/src/kimchi.repository_add_main.js deleted file mode 100644 index 656306b..0000000 --- a/src/wok/plugins/kimchi/ui/js/src/kimchi.repository_add_main.js +++ /dev/null @@ -1,96 +0,0 @@ -/* - * 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() { - wok.topic('kimchi/repositoryAdded').publish(); - wok.window.close(); - }, function(jqXHR, textStatus, errorThrown) { - var reason = jqXHR && - jqXHR['responseJSON'] && - jqXHR['responseJSON']['reason']; - wok.message.error(reason); - }); - return false; - }; - - $(addForm).on('submit', addRepository); -}; diff --git a/src/wok/plugins/kimchi/ui/js/src/kimchi.repository_edit_main.js b/src/wok/plugins/kimchi/ui/js/src/kimchi.repository_edit_main.js deleted file mode 100644 index 5bfc51e..0000000 --- a/src/wok/plugins/kimchi/ui/js/src/kimchi.repository_edit_main.js +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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() { - wok.topic('kimchi/repositoryUpdated').publish(); - wok.window.close(); - }, function(jqXHR, textStatus, errorThrown) { - var reason = jqXHR && - jqXHR['responseJSON'] && - jqXHR['responseJSON']['reason']; - wok.message.error(reason); - }); - - return false; - }; - - $(editForm).on('submit', editRepository); - $(saveButton).on('click', editRepository); -}; -- 2.1.0

From: chandrureddy <chandra@linux.vnet.ibm.com> --- src/wok/plugins/gingerbase/ui/css/Makefile.am | 27 ++ .../gingerbase/ui/css/theme-default/host.css | 288 +++++++++++++++++++++ .../gingerbase/ui/css/theme-default/report-add.css | 38 +++ .../ui/css/theme-default/report-rename.css | 40 +++ .../ui/css/theme-default/repository-add.css | 43 +++ .../ui/css/theme-default/repository-edit.css | 89 +++++++ .../plugins/kimchi/ui/css/theme-default/host.css | 287 -------------------- .../kimchi/ui/css/theme-default/report-add.css | 37 --- .../kimchi/ui/css/theme-default/report-rename.css | 39 --- .../kimchi/ui/css/theme-default/repository-add.css | 42 --- .../ui/css/theme-default/repository-edit.css | 88 ------- 11 files changed, 525 insertions(+), 493 deletions(-) create mode 100644 src/wok/plugins/gingerbase/ui/css/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/css/theme-default/host.css create mode 100644 src/wok/plugins/gingerbase/ui/css/theme-default/report-add.css create mode 100644 src/wok/plugins/gingerbase/ui/css/theme-default/report-rename.css create mode 100644 src/wok/plugins/gingerbase/ui/css/theme-default/repository-add.css create mode 100644 src/wok/plugins/gingerbase/ui/css/theme-default/repository-edit.css delete mode 100644 src/wok/plugins/kimchi/ui/css/theme-default/host.css delete mode 100644 src/wok/plugins/kimchi/ui/css/theme-default/report-add.css delete mode 100644 src/wok/plugins/kimchi/ui/css/theme-default/report-rename.css delete mode 100644 src/wok/plugins/kimchi/ui/css/theme-default/repository-add.css delete mode 100644 src/wok/plugins/kimchi/ui/css/theme-default/repository-edit.css diff --git a/src/wok/plugins/gingerbase/ui/css/Makefile.am b/src/wok/plugins/gingerbase/ui/css/Makefile.am new file mode 100644 index 0000000..4d4fcb6 --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/css/Makefile.am @@ -0,0 +1,27 @@ +# +# Ginger Base +# +# Copyright IBM, Corp. 2015 +# +# Code derived from Project Kimchi +# 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)/wok/plugins/gingerbase/ui/css +dist_css_DATA = theme-default.min.css + +theme-default.min.css: theme-default/*.css + cat $^ > $@ + +CLEANFILES = theme-default.min.css diff --git a/src/wok/plugins/gingerbase/ui/css/theme-default/host.css b/src/wok/plugins/gingerbase/ui/css/theme-default/host.css new file mode 100644 index 0000000..2e23dd3 --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/css/theme-default/host.css @@ -0,0 +1,288 @@ +/* + * Project Ginger Base + * + * Copyright IBM, Corp. 2013-2015 + * + * Code derived from Project Kimchi + * 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("plugins/gingerbase/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 */ diff --git a/src/wok/plugins/gingerbase/ui/css/theme-default/report-add.css b/src/wok/plugins/gingerbase/ui/css/theme-default/report-add.css new file mode 100644 index 0000000..5ca38ce --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/css/theme-default/report-add.css @@ -0,0 +1,38 @@ +/* + * Project Ginger Base + * + * Copyright IBM, Corp. 2013-2015 + * + * Code derived from Project Kimchi + * 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 { + margin: 0; + width: 100%; +} + +.info-add-debug-report { + font-size: 12px; + color: #999999; + font-weight: lighter; + font-family: 'Helvetica Neue', Helvetica, Arial; +} diff --git a/src/wok/plugins/gingerbase/ui/css/theme-default/report-rename.css b/src/wok/plugins/gingerbase/ui/css/theme-default/report-rename.css new file mode 100644 index 0000000..9f2664c --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/css/theme-default/report-rename.css @@ -0,0 +1,40 @@ +/* + * Project Ginger Base + * + * Copyright IBM, Corp. 2014-2015 + * + * Code derived from Project Kimchi + * 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: 0; + width: 100%; +} + +.info-debug-report-rename { + font-size: 12px; + color: #999999; + font-weight: lighter; + font-family: 'Helvetica Neue', Helvetica, Arial; +} diff --git a/src/wok/plugins/gingerbase/ui/css/theme-default/repository-add.css b/src/wok/plugins/gingerbase/ui/css/theme-default/repository-add.css new file mode 100644 index 0000000..a1e94c3 --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/css/theme-default/repository-add.css @@ -0,0 +1,43 @@ +/* + * Project Ginger Base + * + * Copyright IBM, Corp. 2014-2015 + * + * Code derived from Project Kimchi + * 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; +} + +#isMirrorLabel { + font-size: 14px; + font-weight: lighter; + font-family: 'Helvetica Neue', Helvetica, Arial; +} diff --git a/src/wok/plugins/gingerbase/ui/css/theme-default/repository-edit.css b/src/wok/plugins/gingerbase/ui/css/theme-default/repository-edit.css new file mode 100644 index 0000000..2af2423 --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/css/theme-default/repository-edit.css @@ -0,0 +1,89 @@ +/* + * Project Ginger Base + * + * Copyright IBM, Corp. 2014-2015 + * + * Code derived from Project Kimchi + * 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: 0 30px; + width: 95%; +} + +.repository-edit-wrapper-label, .repository-edit-wrapper-controls { + display: inline-block; + height: 30px; + line-height: 30px; + font-size: 14px; + vertical-align: top; +} + +.repository-edit-wrapper-label { + margin-top: 10px; + 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: 30px; + line-height: 30px; + padding: 0 10px; + width: 100%; + -moz-box-sizing: border-box; + box-sizing: border-box; + border: 1px solid #CCCCCC; +} + + +.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; +} diff --git a/src/wok/plugins/kimchi/ui/css/theme-default/host.css b/src/wok/plugins/kimchi/ui/css/theme-default/host.css deleted file mode 100644 index a0cccb1..0000000 --- a/src/wok/plugins/kimchi/ui/css/theme-default/host.css +++ /dev/null @@ -1,287 +0,0 @@ -/* - * 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("plugins/kimchi/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 */ diff --git a/src/wok/plugins/kimchi/ui/css/theme-default/report-add.css b/src/wok/plugins/kimchi/ui/css/theme-default/report-add.css deleted file mode 100644 index 8020182..0000000 --- a/src/wok/plugins/kimchi/ui/css/theme-default/report-add.css +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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. - */ -#report-add-window { - height: 300px; - width: 400px; -} - -#report-add-window .field { - font-size: 12px; -} - -#report-name-textbox { - margin: 0; - width: 100%; -} - -.info-add-debug-report { - font-size: 12px; - color: #999999; - font-weight: lighter; - font-family: 'Helvetica Neue', Helvetica, Arial; -} \ No newline at end of file diff --git a/src/wok/plugins/kimchi/ui/css/theme-default/report-rename.css b/src/wok/plugins/kimchi/ui/css/theme-default/report-rename.css deleted file mode 100644 index 2fb2698..0000000 --- a/src/wok/plugins/kimchi/ui/css/theme-default/report-rename.css +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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. - */ -#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: 0; - width: 100%; -} - -.info-debug-report-rename { - font-size: 12px; - color: #999999; - font-weight: lighter; - font-family: 'Helvetica Neue', Helvetica, Arial; -} diff --git a/src/wok/plugins/kimchi/ui/css/theme-default/repository-add.css b/src/wok/plugins/kimchi/ui/css/theme-default/repository-add.css deleted file mode 100644 index 4344569..0000000 --- a/src/wok/plugins/kimchi/ui/css/theme-default/repository-add.css +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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. - */ -#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; -} - -#isMirrorLabel { - font-size: 14px; - font-weight: lighter; - font-family: 'Helvetica Neue', Helvetica, Arial; -} \ No newline at end of file diff --git a/src/wok/plugins/kimchi/ui/css/theme-default/repository-edit.css b/src/wok/plugins/kimchi/ui/css/theme-default/repository-edit.css deleted file mode 100644 index 383a7fe..0000000 --- a/src/wok/plugins/kimchi/ui/css/theme-default/repository-edit.css +++ /dev/null @@ -1,88 +0,0 @@ -/* - * 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. - */ -.yum div#repository-edit-window { - height: 680px; - width: 1000px; -} - -.deb div#repository-edit-window { - height: 480px; - width: 1000px; -} - - -.repository-edit-fieldset { - float: left; - padding: 0 30px; - width: 95%; -} - -.repository-edit-wrapper-label, .repository-edit-wrapper-controls { - display: inline-block; - height: 30px; - line-height: 30px; - font-size: 14px; - vertical-align: top; -} - -.repository-edit-wrapper-label { - margin-top: 10px; - 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: 30px; - line-height: 30px; - padding: 0 10px; - width: 100%; - -moz-box-sizing: border-box; - box-sizing: border-box; - border: 1px solid #CCCCCC; -} - - -.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; -} -- 2.1.0

From: chandrureddy <chandra@linux.vnet.ibm.com> --- src/wok/plugins/gingerbase/ui/Makefile.am | 21 +++++++++++++++++++ src/wok/plugins/gingerbase/ui/config/Makefile.am | 23 +++++++++++++++++++++ src/wok/plugins/gingerbase/ui/config/tab-ext.xml | 10 +++++++++ src/wok/plugins/gingerbase/ui/images/Makefile.am | 23 +++++++++++++++++++++ src/wok/plugins/gingerbase/ui/images/icon-vm.png | Bin 0 -> 2976 bytes src/wok/plugins/gingerbase/ui/images/logo.ico | Bin 0 -> 1214 bytes .../gingerbase/ui/images/theme-default/Makefile.am | 21 +++++++++++++++++++ .../ui/images/theme-default/host-icon-sprite.png | Bin 0 -> 1034 bytes .../images/theme-default/kimchi-loading15x15.gif | Bin 0 -> 1653 bytes 9 files changed, 98 insertions(+) create mode 100644 src/wok/plugins/gingerbase/ui/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/config/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/config/tab-ext.xml create mode 100644 src/wok/plugins/gingerbase/ui/images/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/images/icon-vm.png create mode 100644 src/wok/plugins/gingerbase/ui/images/logo.ico create mode 100644 src/wok/plugins/gingerbase/ui/images/theme-default/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/images/theme-default/host-icon-sprite.png create mode 100644 src/wok/plugins/gingerbase/ui/images/theme-default/kimchi-loading15x15.gif diff --git a/src/wok/plugins/gingerbase/ui/Makefile.am b/src/wok/plugins/gingerbase/ui/Makefile.am new file mode 100644 index 0000000..3c4f517 --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/Makefile.am @@ -0,0 +1,21 @@ +# +# Ginger Base +# +# Copyright IBM, Corp. 2015 +# +# Code derived from Project Kimchi +# 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 = config css images js pages + +uidir = $(datadir)/wok/plugins/gingerbase/ui diff --git a/src/wok/plugins/gingerbase/ui/config/Makefile.am b/src/wok/plugins/gingerbase/ui/config/Makefile.am new file mode 100644 index 0000000..a8bc870 --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/config/Makefile.am @@ -0,0 +1,23 @@ +# +# Ginger Base +# +# Copyright IBM, Corp. 2015 +# +# Code derived from Project Kimchi +# 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. + +xmldir = $(datadir)/wok/plugins/gingerbase/ui/config + +dist_xml_DATA = \ + tab-ext.xml \ + $(NULL) diff --git a/src/wok/plugins/gingerbase/ui/config/tab-ext.xml b/src/wok/plugins/gingerbase/ui/config/tab-ext.xml new file mode 100644 index 0000000..2d2d9bd --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/config/tab-ext.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> +<tabs-ext> + <tab> + <access role="admin" mode="admin"/> + <access role="user" mode="none"/> + + <title>Host</title> + <path>plugins/gingerbase/host.html</path> + </tab> +</tabs-ext> diff --git a/src/wok/plugins/gingerbase/ui/images/Makefile.am b/src/wok/plugins/gingerbase/ui/images/Makefile.am new file mode 100644 index 0000000..0bc83bb --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/images/Makefile.am @@ -0,0 +1,23 @@ +# +# Ginger Base +# +# Copyright IBM, Corp. 2015 +# +# Code derived from Project Kimchi +# 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)/wok/plugins/gingerbase/ui/images + +dist_image_DATA = *.png *.ico diff --git a/src/wok/plugins/gingerbase/ui/images/icon-vm.png b/src/wok/plugins/gingerbase/ui/images/icon-vm.png new file mode 100644 index 0000000000000000000000000000000000000000..50dac50c5a0ee59f4e79170434f53bb3b94390e3 GIT binary patch literal 2976 zcmbVOi8~YiAK$c?G*_1+SxjOnw_GDMmIx6-d=n-&8()kq<W|T%lAFvDQI1%-m1|)L zlcVJ*<Q&6~-=FY(p3m`op6C63eO~YP`}I8UcZ`X#KIDYZ2><{9K^f?o9o~ea4Q4+) zTM++z0RXsMP<l7a{~h~n$Ah+@iE!)YqjU0|_6;wf3Y?G$eFEW)8b<MQ?WJ#f1svn~ zW8Di*&&S4-g#A+Fkt*GZrm-n<u_IM6(We`*ZXNYMVhw0Dd}H$USYdKOOU2Xs4X*T1 zd#1>T!sWRfzrMOa{5InHIB|B;uUC_y-b`P{ZH>Rk5(<NY|J%wp^O<gq>H9ra<F+|6 zGQ!&1-MW^RqUJqCnc(2Lz?#m}jmj$EY!((2tTXIgoMjoShCU#_*{IO9w4|NvVsN9l zBBP?x^W$-I;(4CFM&ZL);KH-rwYl&`?~o>3KJ!OrlIR$KnP)UzTQn=j#XOI|ZF6-7 zU@(}#JeQbSsf9S@p&gpBFwo>5OsTn;Ou_&>RUmbpVE)U-m*ub6rNo1(x2IOJ#${-4 zhM$#gEU}KG!6@slT|=`?%Q+m*mwCU0Lqa5J4I$NhCc#||5}_CV#ixK3qD}qi`<o`o zP>|}IG5eWO7^>=Z*LQ-CVQs=AqFqs%TRRud9FtFOFIu`bQ@6@ObG(bXh@GaiNOJ|C zZa(i~qELOe>cw0ingv-<*OFiMN9q>Y^sgX5dL^#m6Ow_5OC4OkjoBqE%h~!|!ysE> ze*jF6d8@E(EE?L`;;SLkL7(ele1qYGjSfPQZ?wX8lb*YA5C{SrP*Jr93kM>oJ6%k} z%Oxfvu#Z>fNw#a6su$WQW^v}~9w5rE<@xzQho4_FX>*pU#KDn~ZT2f{YTRdG<WY0K zoF`7M9v&f|YFUB`&f}fV)%4a<r9+=o#mmijs<P+{=bkLA-}2-~Ei?XiAMOKrtvRSG z{r&x0j2_}vlbgsrvTe*Kr4uv)t2hCG)+<}5Ei5h`xZ8}5R=dzA-+R&f25sNBmQ~Ix z*5M71e`g>N$S}zE9eSYV)2B~f4y~D1AP9#Ts;RF*8IjD(cs)4R097IpWXgPU`0Kcw zLl%cC(q~ed{eO?q1|{BgV0C?DwAEQDR!=z7Pk2o>GPB0FbX&R6082O^mlMyaCBsN( z^yawPZ5A65_Y0lXx!4E<XcdbUt<gdBQG=%5ntKG*;4o{5*Gaq+{!#p|h6^z(%d<@i zzqhloT*mch)2F-_ArN{RVR2!f`uQnW1$=ybJX^Q%)r~<ra;Txckti-mU%!K+cCI&5 zK~i#<W3}@-xUgD)7kW%*b8~ZF!I%Sz_4jXrGxxP$mT;KXLCW|x+(vnLPM&O>)0st& zRsPdrB()|9Hb`Q;GdhMnArG6+#HfXQul>xgFk9<I-@ioSK<37c%KsFdO)_q*#4&v> zr*p!a^(YaII(*t|O$0$uadaDrz@97R(fo}X`hGgij-L%6t77)cS&C&Umx~V|twZXT zPdoEPhj~m8<PN~FfaS@(`Y)wPNc<fau8HD29X>$epT)&sVKV4Xk(K_d--8?RUw$3v zjt|(Iu~9H?py1~0gRwS9DV-(pvuY*0)|1k~GF%DZynoy_T`(^X{AyrZGDAo#KPpvP zQNkR~z8LuYd~OP3yT4>SnNPdG>TBL|(z;^|Qp;aZPThZLTM??O=Q+cU`-%?^-j&I? zpE3SxT>%DEZ2$LoL69_!9Udu|n7k^H{^agGkZkcu5iqbtDKRM)51Q7_c<Xb_r$?)E zm`*?7E`EGz=Q(?I9@xQF7+E77Yba?06lawZu<|duY<Wza=fMue^59UI9Y!#f><J|^ zX}%9AibhJTu|n`Gr#<A*z}ZCQzNL9jjcT{xR0$vjeLHv>6CWqMB6o1tI;$Vl@33Z% zWJIUAM2LcV6TKz8_idv8-ns>F%(}?cvK8aH@5ulETwwOo9xvsZb|*s#e37!<d@v&6 zRGL10DnYx${=KIiSsKin`R!SEOOD}Z$iG?mQq0!RQ#psmF{-lN7uSSpzO@?mYr!7W zFDPul;cOY)pIKuy7d^%S;9_wOpZ4mjpv9#noM_>|t3`zqcKo1du&&F+HR;urCdAWp z<6k6<+8*7+DfKuISNP+hC#5lf!gWee)obKgHje7m6eM{AP~iW01B$<`iJhSM&^F7! zY}*Dcck6%!N`&*!n2ZBq1l8*@8_Bx59T~ixOO_EBD3c$)p<(*<>Cn*7kD5RyK8n83 z%WjB34PP8WHq}p1m03tP0VOv2wJqc?%$%_T+Fg_NEXeR2t&(6||02b6g#UCLU~qi3 z9Xn=jumiaXz?dl$YeE=4#`d(AQuiW<8{|2s#32m7W9=2_DNOrZg7w9D6&P@HY4ipB z?DMI*2m-#XN>R1Rj^tQ0saj^}#DB=)S(A}MITrK7Rl!{8Tn|qA$OE>V-D5jxYZEV9 zy49Pb4krQ-)Jl!c4lCX=I4)gi=%id*t;cur)5K8SQ`%x7-yPmvw*HDeV+0U&{kQ5F zd65-0$fA=`QxY#Efu3C<DskAeNM-UhXNW{)qYU!~vdQ!<XeBkWhbk>$(!P=EDtGkh z?1c{`PEK~M6EIQ7wsj|>RUYXmoR*W_np#5^Emo2TRwvi&O?DvHArYycuFQmCM#_Pc z^NzLNd<%KA0Y&*o*2J4<KJWnZ&i6HB96Y3YX|v&8iRMoc3DpQHIncRhv5<GFEmo57 zT#=Np3n!gV3zl?Wu1N|##y>?@>uD`PKd(0!yleGwrru=pVcV(0^bDi7>k9)Uy7ys) z>%tj;l6CdZyAj@unJa&yn^XsDB03(D0xoME6-S_p`eb;`{oGM3Q;#v-YOmgQYfXdj ze@V^#XLPo8exZkW4*`)WGLR%cxdUaYmjN5aMSPgzF5atP+^c^s_ClG^5s)lHSuC!6 zT{sI+sVt3ye7L%LkJ?1Czg@DS@OI$!#Y6J(?bbDqExhMdfL#4W<+$&*>E%DLaw&Hj z7Xhx=V+jjlhc?*}>qHQ69iGcR0hoDbRZmO{8(OR%)k8L$Kd{AuR+1uLB!<3#5=N!< zRWb#Z|NLn(U)nzdzh_IcZjBDywN5>%kgj1fCqHG$O8&CQwn0e9p8DO1W}lgM#(Iwa z@D-to`$u&1is*%4-nW?O<B@zkr4~V^?>jRIy*y5LOJ4VL2i?f(tXf@w9TGZ!f5#{m zkknXdV=c4`qBJ_D=qm>c(Y%h!!n+q-X4i~z%Cio2=4~*qf?_Kbd^6<aKEnOxYW)Op z^mQ)@OK6CFooaC;u@BLap_4avjFJIB(xZ(d4U?t*LN0vu80U}#O6v(-EzF;1Pn7X_ zuP=V|BxgQU;m+M-M-li@Ez$8akJ)}!!><TDF<cEqTNPdZ-rBV^bFE&*;nLvGcxfq~ zTS2eO%DRHQQyvko=d!Eh8W^e#9kz5)OSUUEwM)8P9OY3R`MLHT6?d`|#MIT)LgS<^ z6yx%0U4|_BHF=ZG%2GDU=aSt|&%+^$G(?AOZJ?6t#==lDO%vZ>TSUi+S!7o{{604J zvOS*tTce4vA~B~W0$^`l^{C5&BjEa;P20|6Hf~`}BIc$_0isO&jc5U#c7UAbC-&sO zotzTHYC7JUE;{TGL<fi6j8H3>-8pOYu|HJLvm)9;wPOpK^_ptrPX<rvG|jc;bq`#} z@9EWsf*>QL(>N1x7G0$tb~D_exI8=(L)?q%_H5YJhE?vk@SqODLErHLrnkGe6b+?I mVQE8J@&9#74TC1P9{|tL%c2?+(}WHuZvg71u^w5+A?$zXeWqvt literal 0 HcmV?d00001 diff --git a/src/wok/plugins/gingerbase/ui/images/logo.ico b/src/wok/plugins/gingerbase/ui/images/logo.ico new file mode 100644 index 0000000000000000000000000000000000000000..446143f066a60f479b2cb8f8d04ab3c97ff60e56 GIT binary patch literal 1214 zcma)*3rLeu6vyu=X_;nPV)$&PPF)r(wTQ|dTGOUtnOdf0mZ=cR#99xbub1{BqnD9^ z^Z>PV6h)fUny6#CN{3di2P{*h2ek@Oq0a4o*=I}2Iv?krbAR`oKi_vQA0faVCr83o zF{!X2#Dx$Nz}$(sm^sgR<Jj30yCMGpMl1z837jm3H1$<DU4IV>Tbdw<FM-;Hi<#et z=I}n~iB^qh8{XzCNyvT<I;$&znmT~?eFXZgAE@Om?1h(6Iq+2e1-ca!zOAO7n3*}; zXq6n?2kF<!f%cez;-Fgx4$e+xo{WR;oqhc_OW;#nF!Zm|JK}m8gi6aC+##`QA5PmJ zfeZ(o(}%&&1P5#*1vVbnssk~XhN5bNz=T)>5^+BS=V54SJ|^z)5I7%kU;>-skiq*{ z5B^=eF<T)pK9+)bV;9UCK>t-HOi+bkR-wK1xpfXL;S<?ho1pQ5gYzxiHR~=e+XHS( zYe7QMZb3IjWV72H-JpD~6z(tbgwn1o$D2s!YteWNJS!i9l%iW?+34Lvr*KL(6{_X| zobEjAb{lD|4qsmYvGF;~r0Aunc#>=c)0W4s|D{#(q9~vaX{rGms=((Wn*~LeWqIu} zkGvlzwaxjL25hey2bVweu<xK*t+@Oa_)UKTK^x4IwmKMOjm@oL`l)}_NGPy}tdb}w zHa>H`ji2N7m}Xsj#j7-`#=Dv}`)h&)9th^&^dR%>WH_MB8KcIXVf8p&s1xD|_k)R- zrk$Z0-|Gf}&4Au$KhU$k?3YR5by~D9M&-q$=ocNz4!IY&p7%OxuJf&+Ei-G(23hU; zHTLhMtjFR9ExVbPQVLzBFlROcIZ|#jmX6fm_hsVa3XP<aKAeAt8dqp&oBW=V^+d>Q zkcNnm%Ds?ggd^Rv2~9_o82cv;p6LSBD_g_s-n1uZ8#<EeLwTm~LE9J!Zdo@M&*jFU zoM+Z%F5)(8$8y`Wz~%Pd;Nlx@aH{<lk}}CcRMRXZMD&%Uhz3Ze$jpg#uec1IlFMPW MDQ4iZEk#_;cNAJoqyPW_ literal 0 HcmV?d00001 diff --git a/src/wok/plugins/gingerbase/ui/images/theme-default/Makefile.am b/src/wok/plugins/gingerbase/ui/images/theme-default/Makefile.am new file mode 100644 index 0000000..7e6f70a --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/images/theme-default/Makefile.am @@ -0,0 +1,21 @@ +# +# Ginger Base +# +# Copyright IBM, Corp. 2015 +# +# Code derived from Project Kimchi +# 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)/wok/plugins/gingerbase/ui/images/theme-default + +dist_image_DATA = *.png *.gif diff --git a/src/wok/plugins/gingerbase/ui/images/theme-default/host-icon-sprite.png b/src/wok/plugins/gingerbase/ui/images/theme-default/host-icon-sprite.png new file mode 100644 index 0000000000000000000000000000000000000000..da1cd3f2562a5905a526446bcc8fc18bea06c734 GIT binary patch literal 1034 zcmV+l1oiugP)<h;3K|Lk000e1NJLTq003?P000^Y1^@s6R_JLg00006VoOIv0RI60 z0RN!9r;`8x010qNS#tmY3ljhU3ljkVnw%H_000McNliru-3t>283nlSO%wnC03B&m zSad^gZEa<4bN~PV002XBWnpw>WFU8GbZ8()Nlj2>E@cM*00VAGL_t(&-tAexPZU8E z{`PW&1_K4^OH?eZvAftnL5(5A#KOeLoryLc6xvbn7idfrLqY*-qLqe%L|Ypgg$i36 z(dbjkBSwPpvl)`j+}`fa-u^(2muzw~^LF01^X{8@Zysm_jzUN2Fh`A~Pjc5hKFL~I z+Z}W#NVXC{Y>}KuY7;pNNspw5tO0f7IFeP8D-r4|QCJ)u*CII!fKd<0S(2@?9Y=DD z<R_9!@=PZG-V7bLl9r_@9LG4P1)Rq+9Y?Z{<af)|`7qr|9MBxV)c`acbbCfT&pQC{ z%j$mX<hUFic+YA-2XN6mak_;`9K$+|XK?mUTkTPj&CIsEF5cU<hDHKoBi7iJvbM^i z*Tus8!czN9a>$8s1<N-8RRC8_`$GnE?vb2Jz_2+0dq-p)ngI3#?S24@sTh|bQ+;d5 zH%uEL`5>TIAzA4bYua?6Ovagcnjz|Ai5Da5sM6$aQ8E^l$E3xZb^24#IlFC{{Sv!X zdPZ`HoHhZhMyRZj95%WP!xe@3m<5`5?4yL_;89M%??>JmIN;83>nfaa#_lVU`y{Vr z67H9I<>i9?7&xxqKI>29L{6meTNYI%0Emdw!G8E&QVE-1Rcq#UWYToK0q{&jHq+Sd zU}FNnI)H(=d=J2sh`dW;({;UEMO8gxC-hsZHn6+_8Cz8V%OQ7`GXQ2(brnD(BP{Cx z=6&CP5~WnH*XNDysWO?Qs#^et%pdJCfS-x(Dpi%PY)T=^F&E8^3~dd>ISl}e&Opgd z>jQ8Oz$E}@0sK%^x9UJ%4m8_i!$G%aL_`u-2dYWWvJAJ-u<F2q`TaRWw_eh}pDyEv z>yyFRKMi0z&>mIQrid&iVqA_4oV3~tBC;bQJ7_QMEcIHnC?X#LytKL>s%r052kP~D zY<0ls{5RDBFDZ*`N~hftRMj`pW7t-CT|^!ky^4A7udB@<*0kwB7vI-)nq=l_0(fe5 zkBi7gBF9Bcoc6<NF-#g4k&RAyOj^9%=3_<YamMC0fYCtLR}r}oxmAjYmj^hLTt`+1 zRCTyh@)?Dxh{Y^e+NuMpIv5&N7WDCVBl5M=0B!+z9Oa;-3`iRt9+5!hy{f(jFa_X- zh^)1x14RNBkv{-#tLjpkD=*u5$B=13xe4GPc-8~JKL<=Y@!??g0{{R307*qoM6N<$ Ef;%S0RsaA1 literal 0 HcmV?d00001 diff --git a/src/wok/plugins/gingerbase/ui/images/theme-default/kimchi-loading15x15.gif b/src/wok/plugins/gingerbase/ui/images/theme-default/kimchi-loading15x15.gif new file mode 100644 index 0000000000000000000000000000000000000000..aaa4f85a0560dcb59d4bb70154a9144417aae926 GIT binary patch literal 1653 zcmZ?wbhEHb6krfwcz&0`fx$V3fzy*s(30KRoyj+pP0*a%B9B4Xkl)0X$H9|dJd8D} zo<ZDBSSFF7*jZT0OhTc9Q7nTgk3rREDud*7MxI>8&Ju=(ISf+93MQOdag7Y~1hic{ z8T#{u6)cohTNtM^7+W$J#50+i$>`cj=^O84k`pyFn#{1$Ur8%a&i6QjtgEuCfQhw> zh77A6gQ$gokA@_-E$2dp^>Sv?oMy2Rvbjr`S1FsTIOwZtnQE_R*m$2oUC1KhF@wT7 z#vS5TPBXdYi#jqhIC*|#&}Xr)`pY25?86wZk@$x}Azj<#4}*rAu{Vcnu(UhJUj}_& zGsWW!mvn9Irz#jqI|d0m<_4Kq$D4?%x#%8bJFV#KwS(tqvz9fdTmMyIV-~+CKU<>^ zTODbStQ;$e9OEp8kfaJrQB(IojUXN?PfLA&1ruKlE$<Ybz{O>Dnh|c+IZj3l84L_z z+ZiGkGQ_8gg)Ec{ZB|VbVu;;p8Ir+}TJcZ8St};J)7e)ugI_wAy~kUSA^Gq;v#nzB zo6<uZ9TN=&l6EuXHCx41&a>X&p6tkweNrgxtWY&KLrITauKX0wDL;*ZSPITdWuHCl z7S2#|o1wN-skGcGd-j}YNrw7v?ff;HUH7htly%83WoVk=SR=P3TA8QnVNZtdt|Td^ z4tBRT;l<gOCKJSuq^f)gOk<w3o@>%d>z1S5joVY2V;E+x4Cszxn7#dGQiZ}|@k{wq ze5<)H#@>~ixp+mvx~nC^*GqKvReGJxyd=J8Z|Hp0)LG8{Q?7j|(|J;(^S(;?X-VtX z{Ej0{$vo>WNUb@RHtpd12Emt&YTJ7ve>HRaY*WxWB$BmO<7<oVrMfE&d+u577yI7H zdv${AuTG6`J!)PD74G*(XRN&WpI$)mKewN2NU*bGfUA+70W%{51B2pE7EU3C{|q`n zHZYS2Ffee)GW_S1@z}87U^9oXR?LYF3lFyoD0|KE*tqCuBO@a=9coY=j!k!j<aB0i zc<9u4hfS*nq@!EHIP1=djf>s;v1`@Ep>^V-!(BqkNq@`*laF`Fn|H~0Zd!7(0h{Hf zM42F;^~FLc<zy?bzucZ38xtI`nPf?{Nk)rZI#dI#a%KcAJ>AR3%!JJ}Tb!mjcL>V+ z&Dl|qe5_B>QtnB`#6;Il`9QBD85<TlO;@&EX5(p~fXzf_h=~b~c^s@tPtrczcWUF8 zl$)Y)G4W`lxU|rj6$Xj!z4E$EBA!9O@K)2-%Q<1V)NzW4rQ4Q{qQ@s^Df6<iU^CYa zVJ@$f%ZvcUgKd2BZZRt+Jap&~-N|`mN5EtIK6cxtnin4*pO_@<TefG1V5)aFPwc)q zGcP6L3rdhvk&Uz{R5;QluAbJjV`8#<o~Uk<jm4+?Cwh5=mxY`NNH{%#3wux+Vs{|2 sX~(-16pJpOC{Q`pufUDnn>s|9;tWh`McC5^G?`;~3OSj#0+YEl0GD)I?EnA( literal 0 HcmV?d00001 -- 2.1.0

From: chandrureddy <chandra@linux.vnet.ibm.com> --- src/wok/plugins/gingerbase/po/LINGUAS | 11 + src/wok/plugins/gingerbase/po/Makefile.in.in | 398 +++++ src/wok/plugins/gingerbase/po/Makevars | 41 + src/wok/plugins/gingerbase/po/POTFILES.in | 3 + src/wok/plugins/gingerbase/po/de_DE.po | 2250 +++++++++++++++++++++++++ src/wok/plugins/gingerbase/po/en_US.po | 2092 +++++++++++++++++++++++ src/wok/plugins/gingerbase/po/es_ES.po | 2268 +++++++++++++++++++++++++ src/wok/plugins/gingerbase/po/fr_FR.po | 2290 ++++++++++++++++++++++++++ src/wok/plugins/gingerbase/po/gen-pot.in | 9 + src/wok/plugins/gingerbase/po/gingerbase.pot | 2074 +++++++++++++++++++++++ src/wok/plugins/gingerbase/po/it_IT.po | 2237 +++++++++++++++++++++++++ src/wok/plugins/gingerbase/po/ja_JP.po | 2233 +++++++++++++++++++++++++ src/wok/plugins/gingerbase/po/ko_KR.po | 2163 ++++++++++++++++++++++++ src/wok/plugins/gingerbase/po/pt_BR.po | 2289 +++++++++++++++++++++++++ src/wok/plugins/gingerbase/po/ru_RU.po | 2165 ++++++++++++++++++++++++ src/wok/plugins/gingerbase/po/zh_CN.po | 2117 ++++++++++++++++++++++++ src/wok/plugins/gingerbase/po/zh_TW.po | 2105 +++++++++++++++++++++++ 17 files changed, 26745 insertions(+) create mode 100644 src/wok/plugins/gingerbase/po/LINGUAS create mode 100644 src/wok/plugins/gingerbase/po/Makefile.in.in create mode 100644 src/wok/plugins/gingerbase/po/Makevars create mode 100644 src/wok/plugins/gingerbase/po/POTFILES.in create mode 100644 src/wok/plugins/gingerbase/po/de_DE.po create mode 100644 src/wok/plugins/gingerbase/po/en_US.po create mode 100644 src/wok/plugins/gingerbase/po/es_ES.po create mode 100644 src/wok/plugins/gingerbase/po/fr_FR.po create mode 100644 src/wok/plugins/gingerbase/po/gen-pot.in create mode 100755 src/wok/plugins/gingerbase/po/gingerbase.pot create mode 100644 src/wok/plugins/gingerbase/po/it_IT.po create mode 100644 src/wok/plugins/gingerbase/po/ja_JP.po create mode 100644 src/wok/plugins/gingerbase/po/ko_KR.po create mode 100644 src/wok/plugins/gingerbase/po/pt_BR.po create mode 100644 src/wok/plugins/gingerbase/po/ru_RU.po create mode 100644 src/wok/plugins/gingerbase/po/zh_CN.po create mode 100644 src/wok/plugins/gingerbase/po/zh_TW.po diff --git a/src/wok/plugins/gingerbase/po/LINGUAS b/src/wok/plugins/gingerbase/po/LINGUAS new file mode 100644 index 0000000..3fcb18f --- /dev/null +++ b/src/wok/plugins/gingerbase/po/LINGUAS @@ -0,0 +1,11 @@ +en_US +pt_BR +zh_CN +de_DE +es_ES +fr_FR +it_IT +ja_JP +ko_KR +ru_RU +zh_TW diff --git a/src/wok/plugins/gingerbase/po/Makefile.in.in b/src/wok/plugins/gingerbase/po/Makefile.in.in new file mode 100644 index 0000000..d01fb31 --- /dev/null +++ b/src/wok/plugins/gingerbase/po/Makefile.in.in @@ -0,0 +1,398 @@ +# Makefile for PO directory in any package using GNU gettext. +# Copyright (C) 1995-1997, 2000-2007, 2009-2010 by Ulrich Drepper <drepper@gnu.ai.mit.edu> +# +# 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: diff --git a/src/wok/plugins/gingerbase/po/Makevars b/src/wok/plugins/gingerbase/po/Makevars new file mode 100644 index 0000000..927d590 --- /dev/null +++ b/src/wok/plugins/gingerbase/po/Makevars @@ -0,0 +1,41 @@ +# Makefile variables for PO directory in any package using GNU gettext. + +# Usually the message domain is the same as the package name. +DOMAIN = gingerbase + +# 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 = diff --git a/src/wok/plugins/gingerbase/po/POTFILES.in b/src/wok/plugins/gingerbase/po/POTFILES.in new file mode 100644 index 0000000..92eef1e --- /dev/null +++ b/src/wok/plugins/gingerbase/po/POTFILES.in @@ -0,0 +1,3 @@ +# List of source files which contain translatable strings. +i18n.py +ui/pages/*.tmpl diff --git a/src/wok/plugins/gingerbase/po/de_DE.po b/src/wok/plugins/gingerbase/po/de_DE.po new file mode 100644 index 0000000..ab34d62 --- /dev/null +++ b/src/wok/plugins/gingerbase/po/de_DE.po @@ -0,0 +1,2250 @@ +# English translations for gingerbase package. +# i18n portable object for gingerbase. +# Copyright (C) IBM, Corp. 2013-2015 +# +# Code derived from Project Kimchi +# 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: gingerbase 0.1\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-07-01 16:11-0300\n" +"PO-Revision-Date: 2013-07-11 17:32-0400\n" +"Last-Translator: Crístian Viana <vianac@linux.vnet.ibm.com>\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 "Timeout of %(seconds)s seconds expired while running task '%(task)s." +msgstr "" + +#, python-format +msgid "User %(user_id)s not found with given LDAP settings." +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 "Invalid URI %(uri)s" +msgstr "Ungültiger URI %(uri)s" + +msgid "Unable to choose a virtual machine name" +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 "Cancel" +msgstr "Abbrechen" + +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 "revert" +msgstr "" + +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 "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 "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 "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 "Processor" +msgstr "Prozessor" + +msgid "CPU(s)" +msgstr "" + +msgid "System Statistics" +msgstr "Systemstatistik" + +msgid "Software Updates" +msgstr "Software-Updates" + +msgid "Update Progress" +msgstr "Aktualisierungsfortschritt" + +msgid "Repositories" +msgstr "Repositorys" + +msgid "Debug Reports" +msgstr "Debugberichte" + +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 "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 "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 "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 "Filter" +msgstr "" + +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 "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 "Capacity" +msgstr "Kapazität" + +msgid "Allocated" +msgstr "Zugeordnet" + +msgid "Location" +msgstr "Position" + +msgid "Device path" +msgstr "Einheitenpfad" + +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 "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 "iSCSI Server" +msgstr "iSCSI-Server" + +msgid "Server" +msgstr "Server" + +msgid "Port" +msgstr "Port" + +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 "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 "User Name" +msgstr "Benutzername" + +msgid "Password" +msgstr "Kennwort" + +msgid "SCSI Adapter" +msgstr "SCSI-Adapter" + +msgid "Please, wait..." +msgstr "Bitte warten..." + +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 "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 "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 "No templates found." +msgstr "Keine Vorlagen gefunden." diff --git a/src/wok/plugins/gingerbase/po/en_US.po b/src/wok/plugins/gingerbase/po/en_US.po new file mode 100644 index 0000000..fc8e70f --- /dev/null +++ b/src/wok/plugins/gingerbase/po/en_US.po @@ -0,0 +1,2092 @@ +# English translations for gingerbase package. +# i18n portable object for gingerbase. +# Copyright (C) IBM, Corp. 2013-2015 +# +# Code derived from Project Kimchi +# 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 +# +# Adam Litke <agl@us.ibm.com>, 2013. +# +msgid "" +msgstr "" +"Project-Id-Version: gingerbase 0.1\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-07-01 16:11-0300\n" +"PO-Revision-Date: 2013-07-11 17:32-0400\n" +"Last-Translator: Crístian Viana <vianac@linux.vnet.ibm.com>\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 "Timeout of %(seconds)s seconds expired while running task '%(task)s." +msgstr "" + +#, python-format +msgid "User %(user_id)s not found with given LDAP settings." +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 "Invalid URI %(uri)s" +msgstr "" + +msgid "Unable to choose a virtual machine name" +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 "Cancel" +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 "revert" +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 "CPU" +msgstr "" + +msgid "Disk I/O" +msgstr "" + +msgid "Network I/O" +msgstr "" + +msgid "Livetile" +msgstr "" + +msgid "No guests found." +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 "Shut down" +msgstr "" + +msgid "Restart" +msgstr "" + +msgid "Basic Information" +msgstr "" + +msgid "OS Distro" +msgstr "" + +msgid "OS Code Name" +msgstr "" + +msgid "Processor" +msgstr "" + +msgid "CPU(s)" +msgstr "" + +msgid "System Statistics" +msgstr "" + +msgid "Software Updates" +msgstr "" + +msgid "Update Progress" +msgstr "" + +msgid "Repositories" +msgstr "" + +msgid "Debug Reports" +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 "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 "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 "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 "Filter" +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 "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 "Capacity" +msgstr "" + +msgid "Allocated" +msgstr "" + +msgid "Location" +msgstr "" + +msgid "Device path" +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 "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 "iSCSI Server" +msgstr "" + +msgid "Server" +msgstr "" + +msgid "Port" +msgstr "" + +msgid "iSCSI server IP or hostname. It should not be empty." +msgstr "" + +msgid "Target" +msgstr "" + +msgid "The iSCSI target on iSCSI server" +msgstr "" + +msgid "Add iSCSI Authentication" +msgstr "" + +msgid "iSCSI Authentication" +msgstr "" + +msgid "User Name" +msgstr "" + +msgid "Password" +msgstr "" + +msgid "SCSI Adapter" +msgstr "" + +msgid "Please, wait..." +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 "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 "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 "No templates found." +msgstr "" diff --git a/src/wok/plugins/gingerbase/po/es_ES.po b/src/wok/plugins/gingerbase/po/es_ES.po new file mode 100644 index 0000000..fd2fed3 --- /dev/null +++ b/src/wok/plugins/gingerbase/po/es_ES.po @@ -0,0 +1,2268 @@ +# English translations for gingerbase package. +# i18n portable object for gingerbase. +# Copyright (C) IBM, Corp. 2013-2015 +# +# Code derived from Project Kimchi +# 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: gingerbase 0.1\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-07-01 16:11-0300\n" +"PO-Revision-Date: 2013-07-11 17:32-0400\n" +"Last-Translator: Crístian Viana <vianac@linux.vnet.ibm.com>\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 "Timeout of %(seconds)s seconds expired while running task '%(task)s." +msgstr "" + +#, python-format +msgid "User %(user_id)s not found with given LDAP settings." +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 "Invalid URI %(uri)s" +msgstr "URI %(uri)s no válido" + +msgid "Unable to choose a virtual machine name" +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 "Cancel" +msgstr "Cancelar" + +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 "revert" +msgstr "" + +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 "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 "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 "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 "Processor" +msgstr "Procesador" + +msgid "CPU(s)" +msgstr "" + +msgid "System Statistics" +msgstr "Estadísticas del sistema" + +msgid "Software Updates" +msgstr "Actualizaciones de software" + +msgid "Update Progress" +msgstr "Actualizar progreso" + +msgid "Repositories" +msgstr "Repositorios" + +msgid "Debug Reports" +msgstr "Informes de depuración" + +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 "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 "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 "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 "Filter" +msgstr "" + +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 "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 "Capacity" +msgstr "Capacidad" + +msgid "Allocated" +msgstr "Asignado" + +msgid "Location" +msgstr "Ubicación" + +msgid "Device path" +msgstr "Vía de acceso del dispositivo" + +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 "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 "iSCSI Server" +msgstr "Servidor iSCSI" + +msgid "Server" +msgstr "Servidor" + +msgid "Port" +msgstr "Puerto" + +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 "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 "User Name" +msgstr "Nombre de usuario" + +msgid "Password" +msgstr "Contraseña" + +msgid "SCSI Adapter" +msgstr "Adaptador SCSI" + +msgid "Please, wait..." +msgstr "Por favor, espere..." + +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 "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 "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 "No templates found." +msgstr "No se han encontrado plantillas." diff --git a/src/wok/plugins/gingerbase/po/fr_FR.po b/src/wok/plugins/gingerbase/po/fr_FR.po new file mode 100644 index 0000000..21f8eb0 --- /dev/null +++ b/src/wok/plugins/gingerbase/po/fr_FR.po @@ -0,0 +1,2290 @@ +# English translations for gingerbase package. +# i18n portable object for gingerbase. +# Copyright (C) IBM, Corp. 2013-2015 +# +# Code derived from Project Kimchi +# 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: gingerbase 0.1\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-07-01 16:11-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 "Timeout of %(seconds)s seconds expired while running task '%(task)s." +msgstr "" + +#, python-format +msgid "User %(user_id)s not found with given LDAP settings." +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 "Invalid URI %(uri)s" +msgstr "URI %(uri)s invalide" + +msgid "Unable to choose a virtual machine name" +msgstr "Impossible de sélectionner un nom de machine virtuelle" + +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 "Cancel" +msgstr "Annuler" + +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 "revert" +msgstr "" + +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 "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 "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 "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 "Processor" +msgstr "Processeur" + +msgid "CPU(s)" +msgstr "" + +msgid "System Statistics" +msgstr "Statistiques Système" + +msgid "Software Updates" +msgstr "Mises à jour Logiciel" + +msgid "Update Progress" +msgstr "Progrès de la Mise à Jour" + +msgid "Repositories" +msgstr "Dépôts" + +msgid "Debug Reports" +msgstr "Rapports de Déboggage" + +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 "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 "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 "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." + +#, fuzzy +msgid "Filter" +msgstr "Filtre" + +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 "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 "Capacity" +msgstr "Capacité" + +msgid "Allocated" +msgstr "Alloué" + +msgid "Location" +msgstr "Emplacement" + +msgid "Device path" +msgstr "Chemin du Périphérique" + +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 "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 "iSCSI Server" +msgstr "Serveur iSCSI" + +msgid "Server" +msgstr "Serveur" + +msgid "Port" +msgstr "Port" + +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 "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 "User Name" +msgstr "Nom d'Utilisateur" + +msgid "Password" +msgstr "Mot de Passe" + +msgid "SCSI Adapter" +msgstr "Adaptateur SCSI" + +msgid "Please, wait..." +msgstr "Veuillez patienter..." + +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 "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 "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 "No templates found." +msgstr "Aucun modèle trouvé." diff --git a/src/wok/plugins/gingerbase/po/gen-pot.in b/src/wok/plugins/gingerbase/po/gen-pot.in new file mode 100644 index 0000000..507f0aa --- /dev/null +++ b/src/wok/plugins/gingerbase/po/gen-pot.in @@ -0,0 +1,9 @@ +#!/bin/bash + +for src in $@; do + if [ ${src: -3} == ".py" ]; then + cat $src + else + cat $src | @CHEETAH@ compile - + fi +done | xgettext --no-location -o gingerbase.pot -L Python - diff --git a/src/wok/plugins/gingerbase/po/gingerbase.pot b/src/wok/plugins/gingerbase/po/gingerbase.pot new file mode 100755 index 0000000..d4605c7 --- /dev/null +++ b/src/wok/plugins/gingerbase/po/gingerbase.pot @@ -0,0 +1,2074 @@ +# 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 <EMAIL@ADDRESS>, YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-07-01 16:11-0300\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: LANGUAGE <LL@li.org>\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 "Timeout of %(seconds)s seconds expired while running task '%(task)s." +msgstr "" + +#, python-format +msgid "User %(user_id)s not found with given LDAP settings." +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 "Invalid URI %(uri)s" +msgstr "" + +msgid "Unable to choose a virtual machine name" +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 "Cancel" +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 "revert" +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 "CPU" +msgstr "" + +msgid "Disk I/O" +msgstr "" + +msgid "Network I/O" +msgstr "" + +msgid "Livetile" +msgstr "" + +msgid "No guests found." +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 "Shut down" +msgstr "" + +msgid "Restart" +msgstr "" + +msgid "Basic Information" +msgstr "" + +msgid "OS Distro" +msgstr "" + +msgid "OS Code Name" +msgstr "" + +msgid "Processor" +msgstr "" + +msgid "CPU(s)" +msgstr "" + +msgid "System Statistics" +msgstr "" + +msgid "Software Updates" +msgstr "" + +msgid "Update Progress" +msgstr "" + +msgid "Repositories" +msgstr "" + +msgid "Debug Reports" +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 "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 "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 "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 "Filter" +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 "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 "Capacity" +msgstr "" + +msgid "Allocated" +msgstr "" + +msgid "Location" +msgstr "" + +msgid "Device path" +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 "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 "iSCSI Server" +msgstr "" + +msgid "Server" +msgstr "" + +msgid "Port" +msgstr "" + +msgid "iSCSI server IP or hostname. It should not be empty." +msgstr "" + +msgid "Target" +msgstr "" + +msgid "The iSCSI target on iSCSI server" +msgstr "" + +msgid "Add iSCSI Authentication" +msgstr "" + +msgid "iSCSI Authentication" +msgstr "" + +msgid "User Name" +msgstr "" + +msgid "Password" +msgstr "" + +msgid "SCSI Adapter" +msgstr "" + +msgid "Please, wait..." +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 "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 "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 "No templates found." +msgstr "" diff --git a/src/wok/plugins/gingerbase/po/it_IT.po b/src/wok/plugins/gingerbase/po/it_IT.po new file mode 100644 index 0000000..049d816 --- /dev/null +++ b/src/wok/plugins/gingerbase/po/it_IT.po @@ -0,0 +1,2237 @@ +# English translations for gingerbase package. +# i18n portable object for gingerbase. +# Copyright (C) IBM, Corp. 2013-2015 +# +# Code derived from Project Kimchi +# 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: gingerbase 0.1\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-07-01 16:11-0300\n" +"PO-Revision-Date: 2013-07-11 17:32-0400\n" +"Last-Translator: Crístian Viana <vianac@linux.vnet.ibm.com>\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 "Timeout of %(seconds)s seconds expired while running task '%(task)s." +msgstr "" + +#, python-format +msgid "User %(user_id)s not found with given LDAP settings." +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 "Invalid URI %(uri)s" +msgstr "URI %(uri)s non valido" + +msgid "Unable to choose a virtual machine name" +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 "Cancel" +msgstr "Annulla" + +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 "revert" +msgstr "" + +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 "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 "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 "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 "Processor" +msgstr "Processore" + +msgid "CPU(s)" +msgstr "" + +msgid "System Statistics" +msgstr "Statistiche di sistema" + +msgid "Software Updates" +msgstr "Aggiornamenti del software" + +msgid "Update Progress" +msgstr "Avanzamento aggiornamento" + +msgid "Repositories" +msgstr "Repository" + +msgid "Debug Reports" +msgstr "Report di debug" + +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 "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 "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 "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 "Filter" +msgstr "" + +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 "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 "Capacity" +msgstr "Capacità" + +msgid "Allocated" +msgstr "Assegnato" + +msgid "Location" +msgstr "Ubicazione" + +msgid "Device path" +msgstr "Percorso dispositivo" + +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 "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 "iSCSI Server" +msgstr "Server iSCSI" + +msgid "Server" +msgstr "Server" + +msgid "Port" +msgstr "Porta" + +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 "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 "User Name" +msgstr "Nome utente" + +msgid "Password" +msgstr "Password" + +msgid "SCSI Adapter" +msgstr "Adattatore SCSI" + +msgid "Please, wait..." +msgstr "Attendere..." + +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 "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 "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 "No templates found." +msgstr "Nessun modello trovato." diff --git a/src/wok/plugins/gingerbase/po/ja_JP.po b/src/wok/plugins/gingerbase/po/ja_JP.po new file mode 100644 index 0000000..a270d95 --- /dev/null +++ b/src/wok/plugins/gingerbase/po/ja_JP.po @@ -0,0 +1,2233 @@ +# English translations for gingerbase package. +# i18n portable object for gingerbase. +# Copyright (C) IBM, Corp. 2013-2015 +# +# Code derived from Project Kimchi +# 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: gingerbase 0.1\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-07-01 16:11-0300\n" +"PO-Revision-Date: 2013-07-11 17:32-0400\n" +"Last-Translator: Crístian Viana <vianac@linux.vnet.ibm.com>\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 "Timeout of %(seconds)s seconds expired while running task '%(task)s." +msgstr "" + +#, python-format +msgid "User %(user_id)s not found with given LDAP settings." +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 "Invalid URI %(uri)s" +msgstr "無効な URI %(uri)s" + +msgid "Unable to choose a virtual machine name" +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 "Cancel" +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 "revert" +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 "CPU" +msgstr "CPU" + +msgid "Disk I/O" +msgstr "ディスク入出力" + +msgid "Network I/O" +msgstr "ネットワーク入出力" + +msgid "Livetile" +msgstr "ライブタイル" + +msgid "No guests found." +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 "Shut down" +msgstr "シャットダウン" + +msgid "Restart" +msgstr "再始動" + +msgid "Basic Information" +msgstr "基本情報" + +msgid "OS Distro" +msgstr "OS ディストリビューション" + +msgid "OS Code Name" +msgstr "OS コード名" + +msgid "Processor" +msgstr "プロセッサー" + +msgid "CPU(s)" +msgstr "" + +msgid "System Statistics" +msgstr "システム統計情報" + +msgid "Software Updates" +msgstr "ソフトウェア更新" + +msgid "Update Progress" +msgstr "更新の進行状況" + +msgid "Repositories" +msgstr "リポジトリー" + +msgid "Debug Reports" +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 "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 "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 "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 "Filter" +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 "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 "Capacity" +msgstr "容量" + +msgid "Allocated" +msgstr "割り当て済み" + +msgid "Location" +msgstr "ロケーション" + +msgid "Device path" +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 "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 "iSCSI Server" +msgstr "iSCSI サーバー" + +msgid "Server" +msgstr "サーバー" + +msgid "Port" +msgstr "ポート" + +msgid "iSCSI server IP or hostname. It should not be empty." +msgstr "iSCSI サーバー IP またはホスト名。空にすることはできません。" + +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 "User Name" +msgstr "ユーザー名" + +msgid "Password" +msgstr "パスワード" + +msgid "SCSI Adapter" +msgstr "SCSI アダプター" + +msgid "Please, wait..." +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 "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 "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 "No templates found." +msgstr "テンプレートが見つかりません。" diff --git a/src/wok/plugins/gingerbase/po/ko_KR.po b/src/wok/plugins/gingerbase/po/ko_KR.po new file mode 100644 index 0000000..40b6d99 --- /dev/null +++ b/src/wok/plugins/gingerbase/po/ko_KR.po @@ -0,0 +1,2163 @@ +# English translations for gingerbase package. +# i18n portable object for gingerbase. +# Copyright (C) IBM, Corp. 2013-2015 +# +# Code derived from Project Kimchi +# 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: gingerbase 0.1\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-07-01 16:11-0300\n" +"PO-Revision-Date: 2013-07-11 17:32-0400\n" +"Last-Translator: Crístian Viana <vianac@linux.vnet.ibm.com>\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 "Timeout of %(seconds)s seconds expired while running task '%(task)s." +msgstr "" + +#, python-format +msgid "User %(user_id)s not found with given LDAP settings." +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 "Invalid URI %(uri)s" +msgstr "올바르지 않은 URI %(uri)s" + +msgid "Unable to choose a virtual machine name" +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 "Cancel" +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 "revert" +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 "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 "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 "Shut down" +msgstr "시스템 종료" + +msgid "Restart" +msgstr "다시 시작" + +msgid "Basic Information" +msgstr "기본 정보" + +msgid "OS Distro" +msgstr "OS Distro" + +msgid "OS Code Name" +msgstr "OS 코드 이름" + +msgid "Processor" +msgstr "프로세서" + +msgid "CPU(s)" +msgstr "" + +msgid "System Statistics" +msgstr "시스템 통계" + +msgid "Software Updates" +msgstr "소프트웨어 업데이트" + +msgid "Update Progress" +msgstr "진행상태 업데이트" + +msgid "Repositories" +msgstr "저장소" + +msgid "Debug Reports" +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 "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 "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 "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 "Filter" +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 "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 "Capacity" +msgstr "용량" + +msgid "Allocated" +msgstr "할당됨" + +msgid "Location" +msgstr "위치" + +msgid "Device path" +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 "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 "iSCSI Server" +msgstr "iSCSI 서버" + +msgid "Server" +msgstr "서버" + +msgid "Port" +msgstr "포트" + +msgid "iSCSI server IP or hostname. It should not be empty." +msgstr "iSCSI 서버 IP 또는 호스트 이름입니다. 비어 있지 않아야 합니다." + +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 "User Name" +msgstr "사용자 이름" + +msgid "Password" +msgstr "비밀번호" + +msgid "SCSI Adapter" +msgstr "SCSI 어댑터" + +msgid "Please, wait..." +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 "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 "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 "No templates found." +msgstr "템플리트가 없습니다." diff --git a/src/wok/plugins/gingerbase/po/pt_BR.po b/src/wok/plugins/gingerbase/po/pt_BR.po new file mode 100644 index 0000000..32b4c27 --- /dev/null +++ b/src/wok/plugins/gingerbase/po/pt_BR.po @@ -0,0 +1,2289 @@ +# i18n portable object for gingerbase. +# Copyright (C) IBM, Corp. 2013-2015 +# ShaoHe Feng <shaohef@linux.vnet.ibm.com>, 2013-04-18. +# +# Code derived from Project Kimchi +# 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: gingerbase 1.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-07-01 16:11-0300\n" +"PO-Revision-Date: 2015-03-23 12:57+0000\n" +"Last-Translator: Crístian Deives dos Santos Viana <cristiandeives@gmail." +"com>\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 "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 "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." + +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 "Invalid URI %(uri)s" +msgstr "URI %(uri)s inválida" + +msgid "Unable to choose a virtual machine name" +msgstr "Não foi possível escolher um nome para a máquina virtual" + +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 "Cancel" +msgstr "Cancelar" + +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 "revert" +msgstr "Reverter" + +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 "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 "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 "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 "Processor" +msgstr "Processador" + +msgid "CPU(s)" +msgstr "CPU(s)" + +msgid "System Statistics" +msgstr "Estatísticas do sistema" + +msgid "Software Updates" +msgstr "Atualizações de software" + +msgid "Update Progress" +msgstr "Progresso da atualização" + +msgid "Repositories" +msgstr "Repositórios" + +msgid "Debug Reports" +msgstr "Relatórios de Debug" + +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 "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 "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 "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." + +#, fuzzy +msgid "Filter" +msgstr "filtro" + +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 "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 "Capacity" +msgstr "Capacidade" + +msgid "Allocated" +msgstr "Alocado" + +msgid "Location" +msgstr "Localização" + +msgid "Device path" +msgstr "Caminho do dispositivo" + +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 "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 "iSCSI Server" +msgstr "Servidor iSCSI" + +msgid "Server" +msgstr "Servidor" + +msgid "Port" +msgstr "Porta" + +msgid "iSCSI server IP or hostname. It should not be empty." +msgstr "IP ou hostname do servidor iSCSI. Não deve ser vazio." + +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 "User Name" +msgstr "Usuário" + +msgid "Password" +msgstr "Senha" + +msgid "SCSI Adapter" +msgstr "Adaptador SCSI" + +msgid "Please, wait..." +msgstr "Por favor, aguarde..." + +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 "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 "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 "No templates found." +msgstr "Nenhum modelo encontrado." diff --git a/src/wok/plugins/gingerbase/po/ru_RU.po b/src/wok/plugins/gingerbase/po/ru_RU.po new file mode 100644 index 0000000..85aa295 --- /dev/null +++ b/src/wok/plugins/gingerbase/po/ru_RU.po @@ -0,0 +1,2165 @@ +# English translations for gingerbase package. +# i18n portable object for gingerbase. +# Copyright (C) IBM, Corp. 2013-2015 +# +# Code derived from Project Kimchi +# 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: gingerbase 0.1\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-07-01 16:11-0300\n" +"PO-Revision-Date: 2014-08-28 17:32+0000\n" +"Last-Translator: Aline Manera <aline.manera@gmail.com>\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 "Timeout of %(seconds)s seconds expired while running task '%(task)s." +msgstr "" + +#, python-format +msgid "User %(user_id)s not found with given LDAP settings." +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 "Invalid URI %(uri)s" +msgstr "Недопустимый URI %(uri)s" + +msgid "Unable to choose a virtual machine name" +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 "Cancel" +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 "revert" +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 "CPU" +msgstr "Процессор" + +msgid "Disk I/O" +msgstr "Дисковый ввод-вывод" + +msgid "Network I/O" +msgstr "Сетевой ввод-вывод" + +msgid "Livetile" +msgstr "Livetile" + +msgid "No guests found." +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 "Shut down" +msgstr "Выключен" + +msgid "Restart" +msgstr "Перезапуск" + +msgid "Basic Information" +msgstr "Базовая информация" + +msgid "OS Distro" +msgstr "Вариант ОС" + +msgid "OS Code Name" +msgstr "Кодовое имя ОС" + +msgid "Processor" +msgstr "Процессор" + +msgid "CPU(s)" +msgstr "" + +msgid "System Statistics" +msgstr "Системная статистика" + +msgid "Software Updates" +msgstr "Обновления программного обеспечения" + +msgid "Update Progress" +msgstr "Ход обновления" + +msgid "Repositories" +msgstr "Хранилища" + +msgid "Debug Reports" +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 "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 "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 "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 "Filter" +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 "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 "Capacity" +msgstr "Емкость" + +msgid "Allocated" +msgstr "Выделено" + +msgid "Location" +msgstr "Расположение" + +msgid "Device path" +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 "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 "iSCSI Server" +msgstr "Сервер iSCSI" + +msgid "Server" +msgstr "Сервер" + +msgid "Port" +msgstr "Порт" + +msgid "iSCSI server IP or hostname. It should not be empty." +msgstr "IP-адрес или имя хоста сервера iSCSI. Не может быть пустым." + +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 "User Name" +msgstr "Имя пользователя" + +msgid "Password" +msgstr "Пароль" + +msgid "SCSI Adapter" +msgstr "Адаптер SCSI" + +msgid "Please, wait..." +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 "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 "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 "No templates found." +msgstr "Не найдены шаблоны." diff --git a/src/wok/plugins/gingerbase/po/zh_CN.po b/src/wok/plugins/gingerbase/po/zh_CN.po new file mode 100644 index 0000000..acae59a --- /dev/null +++ b/src/wok/plugins/gingerbase/po/zh_CN.po @@ -0,0 +1,2117 @@ +# i18n portable object for gingerbase. +# Copyright (C) IBM, Corp. 2013-2015 +# ShaoHe Feng <shaohef@linux.vnet.ibm.com>, 2013-04-18. +# +# Code derived from Project Kimchi +# 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: gingerbase 0.1\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-07-01 16:11-0300\n" +"PO-Revision-Date: 2013-06-27 10:48+0000\n" +"Last-Translator: ShaoHe Feng <shaohef@linux.vnet.ibm.com>\n" +"Language-Team: ShaoHe Feng <shaohef@linux.vnet.ibm.com>\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 "Timeout of %(seconds)s seconds expired while running task '%(task)s." +msgstr "任务'%(task)s超时%(seconds)s秒。" + +#, python-format +msgid "User %(user_id)s not found with given LDAP settings." +msgstr "使用指定的LDAP配置未找到%(user_id)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 "Invalid URI %(uri)s" +msgstr "无效的URI %(uri)s" + +msgid "Unable to choose a virtual machine name" +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 "Cancel" +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 "revert" +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 "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 "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 "Shut down" +msgstr "关机" + +msgid "Restart" +msgstr "重启" + +msgid "Basic Information" +msgstr "基本信息" + +msgid "OS Distro" +msgstr "操作系统发行版" + +msgid "OS Code Name" +msgstr "操作系统代号" + +msgid "Processor" +msgstr "处理器" + +msgid "CPU(s)" +msgstr "CPU(s)" + +msgid "System Statistics" +msgstr "系统统计信息" + +msgid "Software Updates" +msgstr "软件更新" + +msgid "Update Progress" +msgstr "更新进度" + +msgid "Repositories" +msgstr "软件仓库" + +msgid "Debug Reports" +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 "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 "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 "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 "存储池或卷不能为空" + +#, fuzzy +msgid "Filter" +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 "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 "Capacity" +msgstr "容量" + +msgid "Allocated" +msgstr "已分配" + +msgid "Location" +msgstr "路径" + +msgid "Device path" +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 "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 "iSCSI Server" +msgstr "iSCSI服务器" + +msgid "Server" +msgstr "服务器" + +msgid "Port" +msgstr "端口" + +msgid "iSCSI server IP or hostname. It should not be empty." +msgstr "iSCSI服务器IP或者主机名, 不能为空。" + +msgid "Target" +msgstr "目标" + +msgid "The iSCSI target on iSCSI server" +msgstr "iSCSI目标" + +msgid "Add iSCSI Authentication" +msgstr "添加ISCSI认证" + +msgid "iSCSI Authentication" +msgstr "iSCSI认证" + +msgid "User Name" +msgstr "用户名" + +msgid "Password" +msgstr "密码" + +msgid "SCSI Adapter" +msgstr "SCSI适配器" + +msgid "Please, wait..." +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 "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 "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 "No templates found." +msgstr "没有发现模板" diff --git a/src/wok/plugins/gingerbase/po/zh_TW.po b/src/wok/plugins/gingerbase/po/zh_TW.po new file mode 100644 index 0000000..2922449 --- /dev/null +++ b/src/wok/plugins/gingerbase/po/zh_TW.po @@ -0,0 +1,2105 @@ +# English translations for gingerbase package. +# i18n portable object for gingerbase. +# Copyright (C) IBM, Corp. 2013-2015 +# +# Code derived from Project Kimchi +# 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: gingerbase 0.1\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-07-01 16:11-0300\n" +"PO-Revision-Date: 2013-07-11 17:32-0400\n" +"Last-Translator: Crístian Viana <vianac@linux.vnet.ibm.com>\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 "Timeout of %(seconds)s seconds expired while running task '%(task)s." +msgstr "" + +#, python-format +msgid "User %(user_id)s not found with given LDAP settings." +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 "Invalid URI %(uri)s" +msgstr "URI %(uri)s 無效" + +msgid "Unable to choose a virtual machine name" +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 "Cancel" +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 "revert" +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 "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 "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 "Shut down" +msgstr "關閉" + +msgid "Restart" +msgstr "重新啟動" + +msgid "Basic Information" +msgstr "基本資訊" + +msgid "OS Distro" +msgstr "OS Distro" + +msgid "OS Code Name" +msgstr "OS 程式碼名稱" + +msgid "Processor" +msgstr "處理器" + +msgid "CPU(s)" +msgstr "" + +msgid "System Statistics" +msgstr "系統統計資料" + +msgid "Software Updates" +msgstr "軟體更新" + +msgid "Update Progress" +msgstr "更新進度" + +msgid "Repositories" +msgstr "儲存庫" + +msgid "Debug Reports" +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 "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 "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 "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 "Filter" +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 "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 "Capacity" +msgstr "容量" + +msgid "Allocated" +msgstr "已配置" + +msgid "Location" +msgstr "位置" + +msgid "Device path" +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 "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 "iSCSI Server" +msgstr "iSCSI 伺服器" + +msgid "Server" +msgstr "伺服器" + +msgid "Port" +msgstr "埠" + +msgid "iSCSI server IP or hostname. It should not be empty." +msgstr "iSCSI 伺服器 IP 或主機名稱。它不應該是空的。" + +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 "User Name" +msgstr "使用者名稱" + +msgid "Password" +msgstr "密碼" + +msgid "SCSI Adapter" +msgstr "SCSI 配接卡" + +msgid "Please, wait..." +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 "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 "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 "No templates found." +msgstr "找不到範本。" -- 2.1.0

Reviewed-by: Daniel Barboza <dhbarboza82@gmail.com> Tested-by: Daniel Barboza <dhbarboza82@gmail.com> Good work! On 10/14/2015 08:35 AM, chandra@linux.vnet.ibm.com wrote:
From: chandrureddy <chandra@linux.vnet.ibm.com>
Below are the series of patches to separate the host functionality from plugin kimchi to new plugin gingerbase
chandrureddy (15): V5 Ginger Base : Taking off the host tab functionality from kimchi V5 Ginger Base : base folder files part 1 V5 Ginger Base : base folder files part 2 V5 Ginger Base : base plugin docs files V5 Ginger Base : base plugin build-aix and contrib folders V5 Ginger Base : base plugin m4 files V5 Ginger Base : control files V5 Ginger Base : base plugin model files V5 Ginger Base : base plugin tests files V5 Ginger Base : base plugin ui/pages/help files V5 Ginger Base : base plugin ui/pages files V5 Ginger Base : base plugin ui/js files V5 Ginger Base : base plugin ui/css files V5 Ginger Base : base plugin ui make, images and config files V5 Ginger Base : base plugin po files
src/wok/plugins/gingerbase/API.json | 175 ++ src/wok/plugins/gingerbase/INSTALL | 369 ++++ src/wok/plugins/gingerbase/Makefile.am | 156 ++ src/wok/plugins/gingerbase/README.md | 1 + src/wok/plugins/gingerbase/VERSION | 1 + src/wok/plugins/gingerbase/__init__.py | 22 + src/wok/plugins/gingerbase/autogen.sh | 21 + src/wok/plugins/gingerbase/build-aux/config.rpath | 672 ++++++ src/wok/plugins/gingerbase/build-aux/genChangelog | 25 + src/wok/plugins/gingerbase/build-aux/pkg-version | 59 + src/wok/plugins/gingerbase/config.py.in | 60 + src/wok/plugins/gingerbase/config.rpath | 672 ++++++ src/wok/plugins/gingerbase/configure.ac | 104 + .../plugins/gingerbase/contrib/DEBIAN/Makefile.am | 18 + .../plugins/gingerbase/contrib/DEBIAN/control.in | 14 + src/wok/plugins/gingerbase/contrib/Makefile.am | 36 + src/wok/plugins/gingerbase/contrib/check_i18n.py | 83 + .../gingerbase/contrib/gingerbase.spec.fedora.in | 68 + .../gingerbase/contrib/gingerbase.spec.suse.in | 62 + src/wok/plugins/gingerbase/contrib/make-deb.sh.in | 15 + src/wok/plugins/gingerbase/control/Makefile.am | 26 + src/wok/plugins/gingerbase/control/__init__.py | 27 + src/wok/plugins/gingerbase/control/config.py | 42 + src/wok/plugins/gingerbase/control/cpuinfo.py | 38 + src/wok/plugins/gingerbase/control/debugreports.py | 62 + src/wok/plugins/gingerbase/control/host.py | 146 ++ src/wok/plugins/gingerbase/disks.py | 197 ++ src/wok/plugins/gingerbase/docs/API.md | 314 +++ src/wok/plugins/gingerbase/docs/Makefile.am | 27 + src/wok/plugins/gingerbase/docs/README.md | 201 ++ .../gingerbase/docs/gingerbase-host-tab.png | Bin 0 -> 79669 bytes src/wok/plugins/gingerbase/docs/kimchi-login.png | Bin 0 -> 318041 bytes src/wok/plugins/gingerbase/gingerbase.conf | 31 + src/wok/plugins/gingerbase/gingerbase.py | 62 + src/wok/plugins/gingerbase/i18n.py | 95 + src/wok/plugins/gingerbase/lscpu.py | 126 ++ src/wok/plugins/gingerbase/m4/ac_python_module.m4 | 30 + src/wok/plugins/gingerbase/m4/gettext.m4 | 383 ++++ src/wok/plugins/gingerbase/m4/iconv.m4 | 214 ++ src/wok/plugins/gingerbase/m4/intlmacosx.m4 | 51 + src/wok/plugins/gingerbase/m4/lib-ld.m4 | 110 + src/wok/plugins/gingerbase/m4/lib-link.m4 | 774 +++++++ src/wok/plugins/gingerbase/m4/lib-prefix.m4 | 224 ++ src/wok/plugins/gingerbase/m4/nls.m4 | 32 + src/wok/plugins/gingerbase/m4/po.m4 | 449 ++++ src/wok/plugins/gingerbase/m4/progtest.m4 | 92 + src/wok/plugins/gingerbase/mockmodel.py | 219 ++ src/wok/plugins/gingerbase/model/Makefile.am | 26 + src/wok/plugins/gingerbase/model/__init__.py | 19 + src/wok/plugins/gingerbase/model/config.py | 82 + src/wok/plugins/gingerbase/model/cpuinfo.py | 104 + src/wok/plugins/gingerbase/model/debugreports.py | 214 ++ src/wok/plugins/gingerbase/model/host.py | 427 ++++ src/wok/plugins/gingerbase/model/model.py | 54 + src/wok/plugins/gingerbase/po/LINGUAS | 11 + src/wok/plugins/gingerbase/po/Makefile.in.in | 398 ++++ src/wok/plugins/gingerbase/po/Makevars | 41 + src/wok/plugins/gingerbase/po/POTFILES.in | 3 + src/wok/plugins/gingerbase/po/de_DE.po | 2250 +++++++++++++++++++ src/wok/plugins/gingerbase/po/en_US.po | 2092 ++++++++++++++++++ src/wok/plugins/gingerbase/po/es_ES.po | 2268 +++++++++++++++++++ src/wok/plugins/gingerbase/po/fr_FR.po | 2290 ++++++++++++++++++++ src/wok/plugins/gingerbase/po/gen-pot.in | 9 + src/wok/plugins/gingerbase/po/gingerbase.pot | 2074 ++++++++++++++++++ src/wok/plugins/gingerbase/po/it_IT.po | 2237 +++++++++++++++++++ src/wok/plugins/gingerbase/po/ja_JP.po | 2233 +++++++++++++++++++ src/wok/plugins/gingerbase/po/ko_KR.po | 2163 ++++++++++++++++++ src/wok/plugins/gingerbase/po/pt_BR.po | 2289 +++++++++++++++++++ src/wok/plugins/gingerbase/po/ru_RU.po | 2165 ++++++++++++++++++ src/wok/plugins/gingerbase/po/zh_CN.po | 2117 ++++++++++++++++++ src/wok/plugins/gingerbase/po/zh_TW.po | 2105 ++++++++++++++++++ src/wok/plugins/gingerbase/repositories.py | 535 +++++ src/wok/plugins/gingerbase/swupdate.py | 277 +++ src/wok/plugins/gingerbase/tests/Makefile.am | 50 + src/wok/plugins/gingerbase/tests/run_tests.sh.in | 56 + src/wok/plugins/gingerbase/tests/test_config.py.in | 125 ++ src/wok/plugins/gingerbase/tests/test_host.py | 153 ++ src/wok/plugins/gingerbase/tests/test_model.py | 275 +++ src/wok/plugins/gingerbase/tests/test_rest.py | 184 ++ src/wok/plugins/gingerbase/tests/test_yumparser.py | 164 ++ src/wok/plugins/gingerbase/tests/utils.py | 261 +++ src/wok/plugins/gingerbase/ui/Makefile.am | 21 + src/wok/plugins/gingerbase/ui/config/Makefile.am | 23 + src/wok/plugins/gingerbase/ui/config/tab-ext.xml | 10 + src/wok/plugins/gingerbase/ui/css/Makefile.am | 27 + .../gingerbase/ui/css/theme-default/host.css | 288 +++ .../gingerbase/ui/css/theme-default/report-add.css | 38 + .../ui/css/theme-default/report-rename.css | 40 + .../ui/css/theme-default/repository-add.css | 43 + .../ui/css/theme-default/repository-edit.css | 89 + src/wok/plugins/gingerbase/ui/images/Makefile.am | 23 + src/wok/plugins/gingerbase/ui/images/icon-vm.png | Bin 0 -> 2976 bytes src/wok/plugins/gingerbase/ui/images/logo.ico | Bin 0 -> 1214 bytes .../gingerbase/ui/images/theme-default/Makefile.am | 21 + .../ui/images/theme-default/host-icon-sprite.png | Bin 0 -> 1034 bytes .../images/theme-default/kimchi-loading15x15.gif | Bin 0 -> 1653 bytes src/wok/plugins/gingerbase/ui/js/Makefile.am | 28 + .../plugins/gingerbase/ui/js/src/gingerbase.api.js | 372 ++++ .../gingerbase/ui/js/src/gingerbase.host.js | 860 ++++++++ .../gingerbase/ui/js/src/gingerbase.main.js | 27 + .../ui/js/src/gingerbase.report_add_main.js | 73 + .../ui/js/src/gingerbase.report_rename_main.js | 67 + .../ui/js/src/gingerbase.repository_add_main.js | 97 + .../ui/js/src/gingerbase.repository_edit_main.js | 75 + src/wok/plugins/gingerbase/ui/pages/Makefile.am | 23 + .../plugins/gingerbase/ui/pages/help/Makefile.am | 38 + .../gingerbase/ui/pages/help/de_DE/Makefile.am | 27 + .../gingerbase/ui/pages/help/de_DE/host.dita | 49 + .../plugins/gingerbase/ui/pages/help/dita-help.xsl | 26 + .../gingerbase/ui/pages/help/en_US/Makefile.am | 27 + .../gingerbase/ui/pages/help/en_US/host.dita | 68 + .../gingerbase/ui/pages/help/es_ES/Makefile.am | 27 + .../gingerbase/ui/pages/help/es_ES/host.dita | 49 + .../gingerbase/ui/pages/help/fr_FR/Makefile.am | 27 + .../gingerbase/ui/pages/help/fr_FR/host.dita | 65 + .../gingerbase/ui/pages/help/gingerbase.css | 209 ++ .../gingerbase/ui/pages/help/it_IT/Makefile.am | 27 + .../gingerbase/ui/pages/help/it_IT/host.dita | 51 + .../gingerbase/ui/pages/help/ja_JP/Makefile.am | 27 + .../gingerbase/ui/pages/help/ja_JP/host.dita | 69 + .../gingerbase/ui/pages/help/ko_KR/Makefile.am | 27 + .../gingerbase/ui/pages/help/ko_KR/host.dita | 51 + .../gingerbase/ui/pages/help/pt_BR/Makefile.am | 27 + .../gingerbase/ui/pages/help/pt_BR/host.dita | 72 + .../gingerbase/ui/pages/help/ru_RU/Makefile.am | 27 + .../gingerbase/ui/pages/help/ru_RU/host.dita | 48 + .../gingerbase/ui/pages/help/zh_CN/Makefile.am | 27 + .../gingerbase/ui/pages/help/zh_CN/host.dita | 45 + .../gingerbase/ui/pages/help/zh_TW/Makefile.am | 27 + .../gingerbase/ui/pages/help/zh_TW/host.dita | 49 + src/wok/plugins/gingerbase/ui/pages/host.html.tmpl | 178 ++ src/wok/plugins/gingerbase/ui/pages/i18n.json.tmpl | 149 ++ .../gingerbase/ui/pages/report-add.html.tmpl | 57 + .../gingerbase/ui/pages/report-rename.html.tmpl | 57 + .../gingerbase/ui/pages/repository-add.html.tmpl | 114 + .../gingerbase/ui/pages/repository-edit.html.tmpl | 118 + src/wok/plugins/gingerbase/yumparser.py | 354 +++ src/wok/plugins/kimchi/API.json | 134 -- src/wok/plugins/kimchi/Makefile.am | 3 +- src/wok/plugins/kimchi/config.py.in | 4 - src/wok/plugins/kimchi/control/debugreports.py | 61 - src/wok/plugins/kimchi/control/host.py | 99 +- src/wok/plugins/kimchi/disks.py | 196 -- src/wok/plugins/kimchi/docs/README.md | 6 +- src/wok/plugins/kimchi/i18n.py | 52 - src/wok/plugins/kimchi/kimchi.conf | 7 - src/wok/plugins/kimchi/mockmodel.py | 146 +- src/wok/plugins/kimchi/model/config.py | 21 - src/wok/plugins/kimchi/model/debugreports.py | 213 -- src/wok/plugins/kimchi/model/host.py | 334 +-- src/wok/plugins/kimchi/repositories.py | 533 ----- src/wok/plugins/kimchi/root.py | 1 - src/wok/plugins/kimchi/swupdate.py | 274 --- src/wok/plugins/kimchi/tests/test_authorization.py | 6 - src/wok/plugins/kimchi/tests/test_config.py.in | 8 - src/wok/plugins/kimchi/tests/test_host.py | 97 +- src/wok/plugins/kimchi/tests/test_model.py | 239 +- src/wok/plugins/kimchi/tests/test_rest.py | 54 - src/wok/plugins/kimchi/tests/test_yumparser.py | 162 -- src/wok/plugins/kimchi/ui/config/tab-ext.xml | 7 - .../plugins/kimchi/ui/css/theme-default/host.css | 287 --- .../kimchi/ui/css/theme-default/report-add.css | 37 - .../kimchi/ui/css/theme-default/report-rename.css | 39 - .../kimchi/ui/css/theme-default/repository-add.css | 42 - .../ui/css/theme-default/repository-edit.css | 88 - src/wok/plugins/kimchi/ui/js/src/kimchi.host.js | 858 -------- .../kimchi/ui/js/src/kimchi.report_add_main.js | 72 - .../kimchi/ui/js/src/kimchi.report_rename_main.js | 66 - .../kimchi/ui/js/src/kimchi.repository_add_main.js | 96 - .../ui/js/src/kimchi.repository_edit_main.js | 74 - .../plugins/kimchi/ui/pages/help/de_DE/host.dita | 49 - .../plugins/kimchi/ui/pages/help/en_US/host.dita | 68 - .../plugins/kimchi/ui/pages/help/es_ES/host.dita | 49 - .../plugins/kimchi/ui/pages/help/fr_FR/host.dita | 65 - .../plugins/kimchi/ui/pages/help/it_IT/host.dita | 51 - .../plugins/kimchi/ui/pages/help/ja_JP/host.dita | 69 - .../plugins/kimchi/ui/pages/help/ko_KR/host.dita | 51 - .../plugins/kimchi/ui/pages/help/pt_BR/host.dita | 72 - .../plugins/kimchi/ui/pages/help/ru_RU/host.dita | 48 - .../plugins/kimchi/ui/pages/help/zh_CN/host.dita | 45 - .../plugins/kimchi/ui/pages/help/zh_TW/host.dita | 49 - src/wok/plugins/kimchi/ui/pages/host.html.tmpl | 177 -- .../plugins/kimchi/ui/pages/report-add.html.tmpl | 56 - .../kimchi/ui/pages/report-rename.html.tmpl | 56 - .../kimchi/ui/pages/repository-add.html.tmpl | 113 - .../kimchi/ui/pages/repository-edit.html.tmpl | 117 - src/wok/plugins/kimchi/yumparser.py | 353 --- 187 files changed, 40827 insertions(+), 5791 deletions(-) create mode 100644 src/wok/plugins/gingerbase/API.json create mode 100644 src/wok/plugins/gingerbase/INSTALL create mode 100644 src/wok/plugins/gingerbase/Makefile.am create mode 120000 src/wok/plugins/gingerbase/README.md create mode 100644 src/wok/plugins/gingerbase/VERSION create mode 100644 src/wok/plugins/gingerbase/__init__.py create mode 100755 src/wok/plugins/gingerbase/autogen.sh create mode 100644 src/wok/plugins/gingerbase/build-aux/config.rpath create mode 100755 src/wok/plugins/gingerbase/build-aux/genChangelog create mode 100755 src/wok/plugins/gingerbase/build-aux/pkg-version create mode 100644 src/wok/plugins/gingerbase/config.py.in create mode 100644 src/wok/plugins/gingerbase/config.rpath create mode 100644 src/wok/plugins/gingerbase/configure.ac create mode 100644 src/wok/plugins/gingerbase/contrib/DEBIAN/Makefile.am create mode 100644 src/wok/plugins/gingerbase/contrib/DEBIAN/control.in create mode 100644 src/wok/plugins/gingerbase/contrib/Makefile.am create mode 100755 src/wok/plugins/gingerbase/contrib/check_i18n.py create mode 100644 src/wok/plugins/gingerbase/contrib/gingerbase.spec.fedora.in create mode 100644 src/wok/plugins/gingerbase/contrib/gingerbase.spec.suse.in create mode 100644 src/wok/plugins/gingerbase/contrib/make-deb.sh.in create mode 100644 src/wok/plugins/gingerbase/control/Makefile.am create mode 100644 src/wok/plugins/gingerbase/control/__init__.py create mode 100644 src/wok/plugins/gingerbase/control/config.py create mode 100644 src/wok/plugins/gingerbase/control/cpuinfo.py create mode 100644 src/wok/plugins/gingerbase/control/debugreports.py create mode 100644 src/wok/plugins/gingerbase/control/host.py create mode 100644 src/wok/plugins/gingerbase/disks.py create mode 100644 src/wok/plugins/gingerbase/docs/API.md create mode 100644 src/wok/plugins/gingerbase/docs/Makefile.am create mode 100644 src/wok/plugins/gingerbase/docs/README.md create mode 100644 src/wok/plugins/gingerbase/docs/gingerbase-host-tab.png create mode 100644 src/wok/plugins/gingerbase/docs/kimchi-login.png create mode 100644 src/wok/plugins/gingerbase/gingerbase.conf create mode 100644 src/wok/plugins/gingerbase/gingerbase.py create mode 100644 src/wok/plugins/gingerbase/i18n.py create mode 100644 src/wok/plugins/gingerbase/lscpu.py create mode 100644 src/wok/plugins/gingerbase/m4/ac_python_module.m4 create mode 100644 src/wok/plugins/gingerbase/m4/gettext.m4 create mode 100644 src/wok/plugins/gingerbase/m4/iconv.m4 create mode 100644 src/wok/plugins/gingerbase/m4/intlmacosx.m4 create mode 100644 src/wok/plugins/gingerbase/m4/lib-ld.m4 create mode 100644 src/wok/plugins/gingerbase/m4/lib-link.m4 create mode 100644 src/wok/plugins/gingerbase/m4/lib-prefix.m4 create mode 100644 src/wok/plugins/gingerbase/m4/nls.m4 create mode 100644 src/wok/plugins/gingerbase/m4/po.m4 create mode 100644 src/wok/plugins/gingerbase/m4/progtest.m4 create mode 100644 src/wok/plugins/gingerbase/mockmodel.py create mode 100644 src/wok/plugins/gingerbase/model/Makefile.am create mode 100644 src/wok/plugins/gingerbase/model/__init__.py create mode 100644 src/wok/plugins/gingerbase/model/config.py create mode 100644 src/wok/plugins/gingerbase/model/cpuinfo.py create mode 100644 src/wok/plugins/gingerbase/model/debugreports.py create mode 100644 src/wok/plugins/gingerbase/model/host.py create mode 100644 src/wok/plugins/gingerbase/model/model.py create mode 100644 src/wok/plugins/gingerbase/po/LINGUAS create mode 100644 src/wok/plugins/gingerbase/po/Makefile.in.in create mode 100644 src/wok/plugins/gingerbase/po/Makevars create mode 100644 src/wok/plugins/gingerbase/po/POTFILES.in create mode 100644 src/wok/plugins/gingerbase/po/de_DE.po create mode 100644 src/wok/plugins/gingerbase/po/en_US.po create mode 100644 src/wok/plugins/gingerbase/po/es_ES.po create mode 100644 src/wok/plugins/gingerbase/po/fr_FR.po create mode 100644 src/wok/plugins/gingerbase/po/gen-pot.in create mode 100755 src/wok/plugins/gingerbase/po/gingerbase.pot create mode 100644 src/wok/plugins/gingerbase/po/it_IT.po create mode 100644 src/wok/plugins/gingerbase/po/ja_JP.po create mode 100644 src/wok/plugins/gingerbase/po/ko_KR.po create mode 100644 src/wok/plugins/gingerbase/po/pt_BR.po create mode 100644 src/wok/plugins/gingerbase/po/ru_RU.po create mode 100644 src/wok/plugins/gingerbase/po/zh_CN.po create mode 100644 src/wok/plugins/gingerbase/po/zh_TW.po create mode 100644 src/wok/plugins/gingerbase/repositories.py create mode 100644 src/wok/plugins/gingerbase/swupdate.py create mode 100644 src/wok/plugins/gingerbase/tests/Makefile.am create mode 100644 src/wok/plugins/gingerbase/tests/run_tests.sh.in create mode 100644 src/wok/plugins/gingerbase/tests/test_config.py.in create mode 100644 src/wok/plugins/gingerbase/tests/test_host.py create mode 100644 src/wok/plugins/gingerbase/tests/test_model.py create mode 100644 src/wok/plugins/gingerbase/tests/test_rest.py create mode 100644 src/wok/plugins/gingerbase/tests/test_yumparser.py create mode 100644 src/wok/plugins/gingerbase/tests/utils.py create mode 100644 src/wok/plugins/gingerbase/ui/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/config/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/config/tab-ext.xml create mode 100644 src/wok/plugins/gingerbase/ui/css/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/css/theme-default/host.css create mode 100644 src/wok/plugins/gingerbase/ui/css/theme-default/report-add.css create mode 100644 src/wok/plugins/gingerbase/ui/css/theme-default/report-rename.css create mode 100644 src/wok/plugins/gingerbase/ui/css/theme-default/repository-add.css create mode 100644 src/wok/plugins/gingerbase/ui/css/theme-default/repository-edit.css create mode 100644 src/wok/plugins/gingerbase/ui/images/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/images/icon-vm.png create mode 100644 src/wok/plugins/gingerbase/ui/images/logo.ico create mode 100644 src/wok/plugins/gingerbase/ui/images/theme-default/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/images/theme-default/host-icon-sprite.png create mode 100644 src/wok/plugins/gingerbase/ui/images/theme-default/kimchi-loading15x15.gif create mode 100644 src/wok/plugins/gingerbase/ui/js/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.api.js create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.host.js create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.main.js create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.report_add_main.js create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.report_rename_main.js create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.repository_add_main.js create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.repository_edit_main.js create mode 100644 src/wok/plugins/gingerbase/ui/pages/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/de_DE/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/de_DE/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/dita-help.xsl create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/en_US/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/en_US/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/es_ES/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/es_ES/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/fr_FR/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/fr_FR/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/gingerbase.css create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/it_IT/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/it_IT/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/ja_JP/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/ja_JP/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/ko_KR/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/ko_KR/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/pt_BR/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/pt_BR/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/ru_RU/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/ru_RU/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/zh_CN/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/zh_CN/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/zh_TW/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/zh_TW/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/host.html.tmpl create mode 100644 src/wok/plugins/gingerbase/ui/pages/i18n.json.tmpl create mode 100644 src/wok/plugins/gingerbase/ui/pages/report-add.html.tmpl create mode 100644 src/wok/plugins/gingerbase/ui/pages/report-rename.html.tmpl create mode 100644 src/wok/plugins/gingerbase/ui/pages/repository-add.html.tmpl create mode 100644 src/wok/plugins/gingerbase/ui/pages/repository-edit.html.tmpl create mode 100644 src/wok/plugins/gingerbase/yumparser.py delete mode 100644 src/wok/plugins/kimchi/control/debugreports.py delete mode 100644 src/wok/plugins/kimchi/disks.py delete mode 100644 src/wok/plugins/kimchi/model/debugreports.py delete mode 100644 src/wok/plugins/kimchi/repositories.py delete mode 100644 src/wok/plugins/kimchi/swupdate.py delete mode 100644 src/wok/plugins/kimchi/tests/test_yumparser.py delete mode 100644 src/wok/plugins/kimchi/ui/css/theme-default/host.css delete mode 100644 src/wok/plugins/kimchi/ui/css/theme-default/report-add.css delete mode 100644 src/wok/plugins/kimchi/ui/css/theme-default/report-rename.css delete mode 100644 src/wok/plugins/kimchi/ui/css/theme-default/repository-add.css delete mode 100644 src/wok/plugins/kimchi/ui/css/theme-default/repository-edit.css delete mode 100644 src/wok/plugins/kimchi/ui/js/src/kimchi.host.js delete mode 100644 src/wok/plugins/kimchi/ui/js/src/kimchi.report_add_main.js delete mode 100644 src/wok/plugins/kimchi/ui/js/src/kimchi.report_rename_main.js delete mode 100644 src/wok/plugins/kimchi/ui/js/src/kimchi.repository_add_main.js delete mode 100644 src/wok/plugins/kimchi/ui/js/src/kimchi.repository_edit_main.js delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/de_DE/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/en_US/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/es_ES/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/fr_FR/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/it_IT/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/ja_JP/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/ko_KR/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/pt_BR/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/ru_RU/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/zh_CN/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/zh_TW/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/host.html.tmpl delete mode 100644 src/wok/plugins/kimchi/ui/pages/report-add.html.tmpl delete mode 100644 src/wok/plugins/kimchi/ui/pages/report-rename.html.tmpl delete mode 100644 src/wok/plugins/kimchi/ui/pages/repository-add.html.tmpl delete mode 100644 src/wok/plugins/kimchi/ui/pages/repository-edit.html.tmpl delete mode 100644 src/wok/plugins/kimchi/yumparser.py

My overall comments are: 1) License header: 1.1) There are some files missing the project name 1.2) We just need to add "Code derived from Project Kimchi" to old files moved from Kimchi to Ginger Base. New files, created specific for Ginger Base, are not derived from Kimchi so don't need to have this statement. 2) Overall License: Ginger Base will be a separated project we need to point the license for it. Backend is LGPLv2 and frontend is Apache v2. We need 3 files: COPYING, COPYING.LGPL and COPYING.ASL2 Check Kimchi or Wok for more details 3) Tests Make sure "make check-local" and "make check" pass with success on RHEL 7.1, Ubuntu 15.04, openSUSE 13.2 and Fedora 22. 4) Build Make sure the package generated install and work as expected on RHEL 7.1, Ubuntu 15.04, openSUSE 13.2 and Fedora 22 with wok package and with and without Kimchi. Also test uninstalling all those packages. I was not able to apply those patches in the current master branch, so please, rebase and I can help with the tests on different Linux distributions. Regards, Aline Manera On 14/10/2015 08:35, chandra@linux.vnet.ibm.com wrote:
From: chandrureddy <chandra@linux.vnet.ibm.com>
Below are the series of patches to separate the host functionality from plugin kimchi to new plugin gingerbase
chandrureddy (15): V5 Ginger Base : Taking off the host tab functionality from kimchi V5 Ginger Base : base folder files part 1 V5 Ginger Base : base folder files part 2 V5 Ginger Base : base plugin docs files V5 Ginger Base : base plugin build-aix and contrib folders V5 Ginger Base : base plugin m4 files V5 Ginger Base : control files V5 Ginger Base : base plugin model files V5 Ginger Base : base plugin tests files V5 Ginger Base : base plugin ui/pages/help files V5 Ginger Base : base plugin ui/pages files V5 Ginger Base : base plugin ui/js files V5 Ginger Base : base plugin ui/css files V5 Ginger Base : base plugin ui make, images and config files V5 Ginger Base : base plugin po files
src/wok/plugins/gingerbase/API.json | 175 ++ src/wok/plugins/gingerbase/INSTALL | 369 ++++ src/wok/plugins/gingerbase/Makefile.am | 156 ++ src/wok/plugins/gingerbase/README.md | 1 + src/wok/plugins/gingerbase/VERSION | 1 + src/wok/plugins/gingerbase/__init__.py | 22 + src/wok/plugins/gingerbase/autogen.sh | 21 + src/wok/plugins/gingerbase/build-aux/config.rpath | 672 ++++++ src/wok/plugins/gingerbase/build-aux/genChangelog | 25 + src/wok/plugins/gingerbase/build-aux/pkg-version | 59 + src/wok/plugins/gingerbase/config.py.in | 60 + src/wok/plugins/gingerbase/config.rpath | 672 ++++++ src/wok/plugins/gingerbase/configure.ac | 104 + .../plugins/gingerbase/contrib/DEBIAN/Makefile.am | 18 + .../plugins/gingerbase/contrib/DEBIAN/control.in | 14 + src/wok/plugins/gingerbase/contrib/Makefile.am | 36 + src/wok/plugins/gingerbase/contrib/check_i18n.py | 83 + .../gingerbase/contrib/gingerbase.spec.fedora.in | 68 + .../gingerbase/contrib/gingerbase.spec.suse.in | 62 + src/wok/plugins/gingerbase/contrib/make-deb.sh.in | 15 + src/wok/plugins/gingerbase/control/Makefile.am | 26 + src/wok/plugins/gingerbase/control/__init__.py | 27 + src/wok/plugins/gingerbase/control/config.py | 42 + src/wok/plugins/gingerbase/control/cpuinfo.py | 38 + src/wok/plugins/gingerbase/control/debugreports.py | 62 + src/wok/plugins/gingerbase/control/host.py | 146 ++ src/wok/plugins/gingerbase/disks.py | 197 ++ src/wok/plugins/gingerbase/docs/API.md | 314 +++ src/wok/plugins/gingerbase/docs/Makefile.am | 27 + src/wok/plugins/gingerbase/docs/README.md | 201 ++ .../gingerbase/docs/gingerbase-host-tab.png | Bin 0 -> 79669 bytes src/wok/plugins/gingerbase/docs/kimchi-login.png | Bin 0 -> 318041 bytes src/wok/plugins/gingerbase/gingerbase.conf | 31 + src/wok/plugins/gingerbase/gingerbase.py | 62 + src/wok/plugins/gingerbase/i18n.py | 95 + src/wok/plugins/gingerbase/lscpu.py | 126 ++ src/wok/plugins/gingerbase/m4/ac_python_module.m4 | 30 + src/wok/plugins/gingerbase/m4/gettext.m4 | 383 ++++ src/wok/plugins/gingerbase/m4/iconv.m4 | 214 ++ src/wok/plugins/gingerbase/m4/intlmacosx.m4 | 51 + src/wok/plugins/gingerbase/m4/lib-ld.m4 | 110 + src/wok/plugins/gingerbase/m4/lib-link.m4 | 774 +++++++ src/wok/plugins/gingerbase/m4/lib-prefix.m4 | 224 ++ src/wok/plugins/gingerbase/m4/nls.m4 | 32 + src/wok/plugins/gingerbase/m4/po.m4 | 449 ++++ src/wok/plugins/gingerbase/m4/progtest.m4 | 92 + src/wok/plugins/gingerbase/mockmodel.py | 219 ++ src/wok/plugins/gingerbase/model/Makefile.am | 26 + src/wok/plugins/gingerbase/model/__init__.py | 19 + src/wok/plugins/gingerbase/model/config.py | 82 + src/wok/plugins/gingerbase/model/cpuinfo.py | 104 + src/wok/plugins/gingerbase/model/debugreports.py | 214 ++ src/wok/plugins/gingerbase/model/host.py | 427 ++++ src/wok/plugins/gingerbase/model/model.py | 54 + src/wok/plugins/gingerbase/po/LINGUAS | 11 + src/wok/plugins/gingerbase/po/Makefile.in.in | 398 ++++ src/wok/plugins/gingerbase/po/Makevars | 41 + src/wok/plugins/gingerbase/po/POTFILES.in | 3 + src/wok/plugins/gingerbase/po/de_DE.po | 2250 +++++++++++++++++++ src/wok/plugins/gingerbase/po/en_US.po | 2092 ++++++++++++++++++ src/wok/plugins/gingerbase/po/es_ES.po | 2268 +++++++++++++++++++ src/wok/plugins/gingerbase/po/fr_FR.po | 2290 ++++++++++++++++++++ src/wok/plugins/gingerbase/po/gen-pot.in | 9 + src/wok/plugins/gingerbase/po/gingerbase.pot | 2074 ++++++++++++++++++ src/wok/plugins/gingerbase/po/it_IT.po | 2237 +++++++++++++++++++ src/wok/plugins/gingerbase/po/ja_JP.po | 2233 +++++++++++++++++++ src/wok/plugins/gingerbase/po/ko_KR.po | 2163 ++++++++++++++++++ src/wok/plugins/gingerbase/po/pt_BR.po | 2289 +++++++++++++++++++ src/wok/plugins/gingerbase/po/ru_RU.po | 2165 ++++++++++++++++++ src/wok/plugins/gingerbase/po/zh_CN.po | 2117 ++++++++++++++++++ src/wok/plugins/gingerbase/po/zh_TW.po | 2105 ++++++++++++++++++ src/wok/plugins/gingerbase/repositories.py | 535 +++++ src/wok/plugins/gingerbase/swupdate.py | 277 +++ src/wok/plugins/gingerbase/tests/Makefile.am | 50 + src/wok/plugins/gingerbase/tests/run_tests.sh.in | 56 + src/wok/plugins/gingerbase/tests/test_config.py.in | 125 ++ src/wok/plugins/gingerbase/tests/test_host.py | 153 ++ src/wok/plugins/gingerbase/tests/test_model.py | 275 +++ src/wok/plugins/gingerbase/tests/test_rest.py | 184 ++ src/wok/plugins/gingerbase/tests/test_yumparser.py | 164 ++ src/wok/plugins/gingerbase/tests/utils.py | 261 +++ src/wok/plugins/gingerbase/ui/Makefile.am | 21 + src/wok/plugins/gingerbase/ui/config/Makefile.am | 23 + src/wok/plugins/gingerbase/ui/config/tab-ext.xml | 10 + src/wok/plugins/gingerbase/ui/css/Makefile.am | 27 + .../gingerbase/ui/css/theme-default/host.css | 288 +++ .../gingerbase/ui/css/theme-default/report-add.css | 38 + .../ui/css/theme-default/report-rename.css | 40 + .../ui/css/theme-default/repository-add.css | 43 + .../ui/css/theme-default/repository-edit.css | 89 + src/wok/plugins/gingerbase/ui/images/Makefile.am | 23 + src/wok/plugins/gingerbase/ui/images/icon-vm.png | Bin 0 -> 2976 bytes src/wok/plugins/gingerbase/ui/images/logo.ico | Bin 0 -> 1214 bytes .../gingerbase/ui/images/theme-default/Makefile.am | 21 + .../ui/images/theme-default/host-icon-sprite.png | Bin 0 -> 1034 bytes .../images/theme-default/kimchi-loading15x15.gif | Bin 0 -> 1653 bytes src/wok/plugins/gingerbase/ui/js/Makefile.am | 28 + .../plugins/gingerbase/ui/js/src/gingerbase.api.js | 372 ++++ .../gingerbase/ui/js/src/gingerbase.host.js | 860 ++++++++ .../gingerbase/ui/js/src/gingerbase.main.js | 27 + .../ui/js/src/gingerbase.report_add_main.js | 73 + .../ui/js/src/gingerbase.report_rename_main.js | 67 + .../ui/js/src/gingerbase.repository_add_main.js | 97 + .../ui/js/src/gingerbase.repository_edit_main.js | 75 + src/wok/plugins/gingerbase/ui/pages/Makefile.am | 23 + .../plugins/gingerbase/ui/pages/help/Makefile.am | 38 + .../gingerbase/ui/pages/help/de_DE/Makefile.am | 27 + .../gingerbase/ui/pages/help/de_DE/host.dita | 49 + .../plugins/gingerbase/ui/pages/help/dita-help.xsl | 26 + .../gingerbase/ui/pages/help/en_US/Makefile.am | 27 + .../gingerbase/ui/pages/help/en_US/host.dita | 68 + .../gingerbase/ui/pages/help/es_ES/Makefile.am | 27 + .../gingerbase/ui/pages/help/es_ES/host.dita | 49 + .../gingerbase/ui/pages/help/fr_FR/Makefile.am | 27 + .../gingerbase/ui/pages/help/fr_FR/host.dita | 65 + .../gingerbase/ui/pages/help/gingerbase.css | 209 ++ .../gingerbase/ui/pages/help/it_IT/Makefile.am | 27 + .../gingerbase/ui/pages/help/it_IT/host.dita | 51 + .../gingerbase/ui/pages/help/ja_JP/Makefile.am | 27 + .../gingerbase/ui/pages/help/ja_JP/host.dita | 69 + .../gingerbase/ui/pages/help/ko_KR/Makefile.am | 27 + .../gingerbase/ui/pages/help/ko_KR/host.dita | 51 + .../gingerbase/ui/pages/help/pt_BR/Makefile.am | 27 + .../gingerbase/ui/pages/help/pt_BR/host.dita | 72 + .../gingerbase/ui/pages/help/ru_RU/Makefile.am | 27 + .../gingerbase/ui/pages/help/ru_RU/host.dita | 48 + .../gingerbase/ui/pages/help/zh_CN/Makefile.am | 27 + .../gingerbase/ui/pages/help/zh_CN/host.dita | 45 + .../gingerbase/ui/pages/help/zh_TW/Makefile.am | 27 + .../gingerbase/ui/pages/help/zh_TW/host.dita | 49 + src/wok/plugins/gingerbase/ui/pages/host.html.tmpl | 178 ++ src/wok/plugins/gingerbase/ui/pages/i18n.json.tmpl | 149 ++ .../gingerbase/ui/pages/report-add.html.tmpl | 57 + .../gingerbase/ui/pages/report-rename.html.tmpl | 57 + .../gingerbase/ui/pages/repository-add.html.tmpl | 114 + .../gingerbase/ui/pages/repository-edit.html.tmpl | 118 + src/wok/plugins/gingerbase/yumparser.py | 354 +++ src/wok/plugins/kimchi/API.json | 134 -- src/wok/plugins/kimchi/Makefile.am | 3 +- src/wok/plugins/kimchi/config.py.in | 4 - src/wok/plugins/kimchi/control/debugreports.py | 61 - src/wok/plugins/kimchi/control/host.py | 99 +- src/wok/plugins/kimchi/disks.py | 196 -- src/wok/plugins/kimchi/docs/README.md | 6 +- src/wok/plugins/kimchi/i18n.py | 52 - src/wok/plugins/kimchi/kimchi.conf | 7 - src/wok/plugins/kimchi/mockmodel.py | 146 +- src/wok/plugins/kimchi/model/config.py | 21 - src/wok/plugins/kimchi/model/debugreports.py | 213 -- src/wok/plugins/kimchi/model/host.py | 334 +-- src/wok/plugins/kimchi/repositories.py | 533 ----- src/wok/plugins/kimchi/root.py | 1 - src/wok/plugins/kimchi/swupdate.py | 274 --- src/wok/plugins/kimchi/tests/test_authorization.py | 6 - src/wok/plugins/kimchi/tests/test_config.py.in | 8 - src/wok/plugins/kimchi/tests/test_host.py | 97 +- src/wok/plugins/kimchi/tests/test_model.py | 239 +- src/wok/plugins/kimchi/tests/test_rest.py | 54 - src/wok/plugins/kimchi/tests/test_yumparser.py | 162 -- src/wok/plugins/kimchi/ui/config/tab-ext.xml | 7 - .../plugins/kimchi/ui/css/theme-default/host.css | 287 --- .../kimchi/ui/css/theme-default/report-add.css | 37 - .../kimchi/ui/css/theme-default/report-rename.css | 39 - .../kimchi/ui/css/theme-default/repository-add.css | 42 - .../ui/css/theme-default/repository-edit.css | 88 - src/wok/plugins/kimchi/ui/js/src/kimchi.host.js | 858 -------- .../kimchi/ui/js/src/kimchi.report_add_main.js | 72 - .../kimchi/ui/js/src/kimchi.report_rename_main.js | 66 - .../kimchi/ui/js/src/kimchi.repository_add_main.js | 96 - .../ui/js/src/kimchi.repository_edit_main.js | 74 - .../plugins/kimchi/ui/pages/help/de_DE/host.dita | 49 - .../plugins/kimchi/ui/pages/help/en_US/host.dita | 68 - .../plugins/kimchi/ui/pages/help/es_ES/host.dita | 49 - .../plugins/kimchi/ui/pages/help/fr_FR/host.dita | 65 - .../plugins/kimchi/ui/pages/help/it_IT/host.dita | 51 - .../plugins/kimchi/ui/pages/help/ja_JP/host.dita | 69 - .../plugins/kimchi/ui/pages/help/ko_KR/host.dita | 51 - .../plugins/kimchi/ui/pages/help/pt_BR/host.dita | 72 - .../plugins/kimchi/ui/pages/help/ru_RU/host.dita | 48 - .../plugins/kimchi/ui/pages/help/zh_CN/host.dita | 45 - .../plugins/kimchi/ui/pages/help/zh_TW/host.dita | 49 - src/wok/plugins/kimchi/ui/pages/host.html.tmpl | 177 -- .../plugins/kimchi/ui/pages/report-add.html.tmpl | 56 - .../kimchi/ui/pages/report-rename.html.tmpl | 56 - .../kimchi/ui/pages/repository-add.html.tmpl | 113 - .../kimchi/ui/pages/repository-edit.html.tmpl | 117 - src/wok/plugins/kimchi/yumparser.py | 353 --- 187 files changed, 40827 insertions(+), 5791 deletions(-) create mode 100644 src/wok/plugins/gingerbase/API.json create mode 100644 src/wok/plugins/gingerbase/INSTALL create mode 100644 src/wok/plugins/gingerbase/Makefile.am create mode 120000 src/wok/plugins/gingerbase/README.md create mode 100644 src/wok/plugins/gingerbase/VERSION create mode 100644 src/wok/plugins/gingerbase/__init__.py create mode 100755 src/wok/plugins/gingerbase/autogen.sh create mode 100644 src/wok/plugins/gingerbase/build-aux/config.rpath create mode 100755 src/wok/plugins/gingerbase/build-aux/genChangelog create mode 100755 src/wok/plugins/gingerbase/build-aux/pkg-version create mode 100644 src/wok/plugins/gingerbase/config.py.in create mode 100644 src/wok/plugins/gingerbase/config.rpath create mode 100644 src/wok/plugins/gingerbase/configure.ac create mode 100644 src/wok/plugins/gingerbase/contrib/DEBIAN/Makefile.am create mode 100644 src/wok/plugins/gingerbase/contrib/DEBIAN/control.in create mode 100644 src/wok/plugins/gingerbase/contrib/Makefile.am create mode 100755 src/wok/plugins/gingerbase/contrib/check_i18n.py create mode 100644 src/wok/plugins/gingerbase/contrib/gingerbase.spec.fedora.in create mode 100644 src/wok/plugins/gingerbase/contrib/gingerbase.spec.suse.in create mode 100644 src/wok/plugins/gingerbase/contrib/make-deb.sh.in create mode 100644 src/wok/plugins/gingerbase/control/Makefile.am create mode 100644 src/wok/plugins/gingerbase/control/__init__.py create mode 100644 src/wok/plugins/gingerbase/control/config.py create mode 100644 src/wok/plugins/gingerbase/control/cpuinfo.py create mode 100644 src/wok/plugins/gingerbase/control/debugreports.py create mode 100644 src/wok/plugins/gingerbase/control/host.py create mode 100644 src/wok/plugins/gingerbase/disks.py create mode 100644 src/wok/plugins/gingerbase/docs/API.md create mode 100644 src/wok/plugins/gingerbase/docs/Makefile.am create mode 100644 src/wok/plugins/gingerbase/docs/README.md create mode 100644 src/wok/plugins/gingerbase/docs/gingerbase-host-tab.png create mode 100644 src/wok/plugins/gingerbase/docs/kimchi-login.png create mode 100644 src/wok/plugins/gingerbase/gingerbase.conf create mode 100644 src/wok/plugins/gingerbase/gingerbase.py create mode 100644 src/wok/plugins/gingerbase/i18n.py create mode 100644 src/wok/plugins/gingerbase/lscpu.py create mode 100644 src/wok/plugins/gingerbase/m4/ac_python_module.m4 create mode 100644 src/wok/plugins/gingerbase/m4/gettext.m4 create mode 100644 src/wok/plugins/gingerbase/m4/iconv.m4 create mode 100644 src/wok/plugins/gingerbase/m4/intlmacosx.m4 create mode 100644 src/wok/plugins/gingerbase/m4/lib-ld.m4 create mode 100644 src/wok/plugins/gingerbase/m4/lib-link.m4 create mode 100644 src/wok/plugins/gingerbase/m4/lib-prefix.m4 create mode 100644 src/wok/plugins/gingerbase/m4/nls.m4 create mode 100644 src/wok/plugins/gingerbase/m4/po.m4 create mode 100644 src/wok/plugins/gingerbase/m4/progtest.m4 create mode 100644 src/wok/plugins/gingerbase/mockmodel.py create mode 100644 src/wok/plugins/gingerbase/model/Makefile.am create mode 100644 src/wok/plugins/gingerbase/model/__init__.py create mode 100644 src/wok/plugins/gingerbase/model/config.py create mode 100644 src/wok/plugins/gingerbase/model/cpuinfo.py create mode 100644 src/wok/plugins/gingerbase/model/debugreports.py create mode 100644 src/wok/plugins/gingerbase/model/host.py create mode 100644 src/wok/plugins/gingerbase/model/model.py create mode 100644 src/wok/plugins/gingerbase/po/LINGUAS create mode 100644 src/wok/plugins/gingerbase/po/Makefile.in.in create mode 100644 src/wok/plugins/gingerbase/po/Makevars create mode 100644 src/wok/plugins/gingerbase/po/POTFILES.in create mode 100644 src/wok/plugins/gingerbase/po/de_DE.po create mode 100644 src/wok/plugins/gingerbase/po/en_US.po create mode 100644 src/wok/plugins/gingerbase/po/es_ES.po create mode 100644 src/wok/plugins/gingerbase/po/fr_FR.po create mode 100644 src/wok/plugins/gingerbase/po/gen-pot.in create mode 100755 src/wok/plugins/gingerbase/po/gingerbase.pot create mode 100644 src/wok/plugins/gingerbase/po/it_IT.po create mode 100644 src/wok/plugins/gingerbase/po/ja_JP.po create mode 100644 src/wok/plugins/gingerbase/po/ko_KR.po create mode 100644 src/wok/plugins/gingerbase/po/pt_BR.po create mode 100644 src/wok/plugins/gingerbase/po/ru_RU.po create mode 100644 src/wok/plugins/gingerbase/po/zh_CN.po create mode 100644 src/wok/plugins/gingerbase/po/zh_TW.po create mode 100644 src/wok/plugins/gingerbase/repositories.py create mode 100644 src/wok/plugins/gingerbase/swupdate.py create mode 100644 src/wok/plugins/gingerbase/tests/Makefile.am create mode 100644 src/wok/plugins/gingerbase/tests/run_tests.sh.in create mode 100644 src/wok/plugins/gingerbase/tests/test_config.py.in create mode 100644 src/wok/plugins/gingerbase/tests/test_host.py create mode 100644 src/wok/plugins/gingerbase/tests/test_model.py create mode 100644 src/wok/plugins/gingerbase/tests/test_rest.py create mode 100644 src/wok/plugins/gingerbase/tests/test_yumparser.py create mode 100644 src/wok/plugins/gingerbase/tests/utils.py create mode 100644 src/wok/plugins/gingerbase/ui/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/config/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/config/tab-ext.xml create mode 100644 src/wok/plugins/gingerbase/ui/css/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/css/theme-default/host.css create mode 100644 src/wok/plugins/gingerbase/ui/css/theme-default/report-add.css create mode 100644 src/wok/plugins/gingerbase/ui/css/theme-default/report-rename.css create mode 100644 src/wok/plugins/gingerbase/ui/css/theme-default/repository-add.css create mode 100644 src/wok/plugins/gingerbase/ui/css/theme-default/repository-edit.css create mode 100644 src/wok/plugins/gingerbase/ui/images/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/images/icon-vm.png create mode 100644 src/wok/plugins/gingerbase/ui/images/logo.ico create mode 100644 src/wok/plugins/gingerbase/ui/images/theme-default/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/images/theme-default/host-icon-sprite.png create mode 100644 src/wok/plugins/gingerbase/ui/images/theme-default/kimchi-loading15x15.gif create mode 100644 src/wok/plugins/gingerbase/ui/js/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.api.js create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.host.js create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.main.js create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.report_add_main.js create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.report_rename_main.js create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.repository_add_main.js create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.repository_edit_main.js create mode 100644 src/wok/plugins/gingerbase/ui/pages/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/de_DE/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/de_DE/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/dita-help.xsl create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/en_US/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/en_US/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/es_ES/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/es_ES/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/fr_FR/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/fr_FR/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/gingerbase.css create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/it_IT/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/it_IT/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/ja_JP/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/ja_JP/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/ko_KR/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/ko_KR/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/pt_BR/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/pt_BR/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/ru_RU/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/ru_RU/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/zh_CN/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/zh_CN/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/zh_TW/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/zh_TW/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/host.html.tmpl create mode 100644 src/wok/plugins/gingerbase/ui/pages/i18n.json.tmpl create mode 100644 src/wok/plugins/gingerbase/ui/pages/report-add.html.tmpl create mode 100644 src/wok/plugins/gingerbase/ui/pages/report-rename.html.tmpl create mode 100644 src/wok/plugins/gingerbase/ui/pages/repository-add.html.tmpl create mode 100644 src/wok/plugins/gingerbase/ui/pages/repository-edit.html.tmpl create mode 100644 src/wok/plugins/gingerbase/yumparser.py delete mode 100644 src/wok/plugins/kimchi/control/debugreports.py delete mode 100644 src/wok/plugins/kimchi/disks.py delete mode 100644 src/wok/plugins/kimchi/model/debugreports.py delete mode 100644 src/wok/plugins/kimchi/repositories.py delete mode 100644 src/wok/plugins/kimchi/swupdate.py delete mode 100644 src/wok/plugins/kimchi/tests/test_yumparser.py delete mode 100644 src/wok/plugins/kimchi/ui/css/theme-default/host.css delete mode 100644 src/wok/plugins/kimchi/ui/css/theme-default/report-add.css delete mode 100644 src/wok/plugins/kimchi/ui/css/theme-default/report-rename.css delete mode 100644 src/wok/plugins/kimchi/ui/css/theme-default/repository-add.css delete mode 100644 src/wok/plugins/kimchi/ui/css/theme-default/repository-edit.css delete mode 100644 src/wok/plugins/kimchi/ui/js/src/kimchi.host.js delete mode 100644 src/wok/plugins/kimchi/ui/js/src/kimchi.report_add_main.js delete mode 100644 src/wok/plugins/kimchi/ui/js/src/kimchi.report_rename_main.js delete mode 100644 src/wok/plugins/kimchi/ui/js/src/kimchi.repository_add_main.js delete mode 100644 src/wok/plugins/kimchi/ui/js/src/kimchi.repository_edit_main.js delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/de_DE/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/en_US/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/es_ES/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/fr_FR/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/it_IT/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/ja_JP/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/ko_KR/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/pt_BR/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/ru_RU/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/zh_CN/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/zh_TW/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/host.html.tmpl delete mode 100644 src/wok/plugins/kimchi/ui/pages/report-add.html.tmpl delete mode 100644 src/wok/plugins/kimchi/ui/pages/report-rename.html.tmpl delete mode 100644 src/wok/plugins/kimchi/ui/pages/repository-add.html.tmpl delete mode 100644 src/wok/plugins/kimchi/ui/pages/repository-edit.html.tmpl delete mode 100644 src/wok/plugins/kimchi/yumparser.py

On 10/15/2015 11:36 PM, Aline Manera wrote:
My overall comments are:
1) License header: 1.1) There are some files missing the project name
I have taken care of these changes in my V6 version. just want to let every body know that kimchi plugin do have such files with out project name which needs to be takes care.
1.2) We just need to add "Code derived from Project Kimchi" to old files moved from Kimchi to Ginger Base. New files, created specific for Ginger Base, are not derived from Kimchi so don't need to have this statement.
I have applied these changes in V6 version.
2) Overall License: Ginger Base will be a separated project we need to point the license for it. Backend is LGPLv2 and frontend is Apache v2. We need 3 files: COPYING, COPYING.LGPL and COPYING.ASL2 Check Kimchi or Wok for more details
Done.
3) Tests Make sure "make check-local" and "make check" pass with success on RHEL 7.1, Ubuntu 15.04, openSUSE 13.2 and Fedora 22. I have tested on my Fedora 22 version.
4) Build Make sure the package generated install and work as expected on RHEL 7.1, Ubuntu 15.04, openSUSE 13.2 and Fedora 22 with wok package and with and without Kimchi. Also test uninstalling all those packages. Tested on Fedora 22
I was not able to apply those patches in the current master branch, so please, rebase and I can help with the tests on different Linux distributions.
It is because of two recent file commits (Makefile.am and test_config.py.in). So I have rebased my file again with latest kimchi master and created new version of files (V6).
Regards, Aline Manera
On 14/10/2015 08:35, chandra@linux.vnet.ibm.com wrote:
From: chandrureddy <chandra@linux.vnet.ibm.com>
Below are the series of patches to separate the host functionality from plugin kimchi to new plugin gingerbase
chandrureddy (15): V5 Ginger Base : Taking off the host tab functionality from kimchi V5 Ginger Base : base folder files part 1 V5 Ginger Base : base folder files part 2 V5 Ginger Base : base plugin docs files V5 Ginger Base : base plugin build-aix and contrib folders V5 Ginger Base : base plugin m4 files V5 Ginger Base : control files V5 Ginger Base : base plugin model files V5 Ginger Base : base plugin tests files V5 Ginger Base : base plugin ui/pages/help files V5 Ginger Base : base plugin ui/pages files V5 Ginger Base : base plugin ui/js files V5 Ginger Base : base plugin ui/css files V5 Ginger Base : base plugin ui make, images and config files V5 Ginger Base : base plugin po files
src/wok/plugins/gingerbase/API.json | 175 ++ src/wok/plugins/gingerbase/INSTALL | 369 ++++ src/wok/plugins/gingerbase/Makefile.am | 156 ++ src/wok/plugins/gingerbase/README.md | 1 + src/wok/plugins/gingerbase/VERSION | 1 + src/wok/plugins/gingerbase/__init__.py | 22 + src/wok/plugins/gingerbase/autogen.sh | 21 + src/wok/plugins/gingerbase/build-aux/config.rpath | 672 ++++++ src/wok/plugins/gingerbase/build-aux/genChangelog | 25 + src/wok/plugins/gingerbase/build-aux/pkg-version | 59 + src/wok/plugins/gingerbase/config.py.in | 60 + src/wok/plugins/gingerbase/config.rpath | 672 ++++++ src/wok/plugins/gingerbase/configure.ac | 104 + .../plugins/gingerbase/contrib/DEBIAN/Makefile.am | 18 + .../plugins/gingerbase/contrib/DEBIAN/control.in | 14 + src/wok/plugins/gingerbase/contrib/Makefile.am | 36 + src/wok/plugins/gingerbase/contrib/check_i18n.py | 83 + .../gingerbase/contrib/gingerbase.spec.fedora.in | 68 + .../gingerbase/contrib/gingerbase.spec.suse.in | 62 + src/wok/plugins/gingerbase/contrib/make-deb.sh.in | 15 + src/wok/plugins/gingerbase/control/Makefile.am | 26 + src/wok/plugins/gingerbase/control/__init__.py | 27 + src/wok/plugins/gingerbase/control/config.py | 42 + src/wok/plugins/gingerbase/control/cpuinfo.py | 38 + src/wok/plugins/gingerbase/control/debugreports.py | 62 + src/wok/plugins/gingerbase/control/host.py | 146 ++ src/wok/plugins/gingerbase/disks.py | 197 ++ src/wok/plugins/gingerbase/docs/API.md | 314 +++ src/wok/plugins/gingerbase/docs/Makefile.am | 27 + src/wok/plugins/gingerbase/docs/README.md | 201 ++ .../gingerbase/docs/gingerbase-host-tab.png | Bin 0 -> 79669 bytes src/wok/plugins/gingerbase/docs/kimchi-login.png | Bin 0 -> 318041 bytes src/wok/plugins/gingerbase/gingerbase.conf | 31 + src/wok/plugins/gingerbase/gingerbase.py | 62 + src/wok/plugins/gingerbase/i18n.py | 95 + src/wok/plugins/gingerbase/lscpu.py | 126 ++ src/wok/plugins/gingerbase/m4/ac_python_module.m4 | 30 + src/wok/plugins/gingerbase/m4/gettext.m4 | 383 ++++ src/wok/plugins/gingerbase/m4/iconv.m4 | 214 ++ src/wok/plugins/gingerbase/m4/intlmacosx.m4 | 51 + src/wok/plugins/gingerbase/m4/lib-ld.m4 | 110 + src/wok/plugins/gingerbase/m4/lib-link.m4 | 774 +++++++ src/wok/plugins/gingerbase/m4/lib-prefix.m4 | 224 ++ src/wok/plugins/gingerbase/m4/nls.m4 | 32 + src/wok/plugins/gingerbase/m4/po.m4 | 449 ++++ src/wok/plugins/gingerbase/m4/progtest.m4 | 92 + src/wok/plugins/gingerbase/mockmodel.py | 219 ++ src/wok/plugins/gingerbase/model/Makefile.am | 26 + src/wok/plugins/gingerbase/model/__init__.py | 19 + src/wok/plugins/gingerbase/model/config.py | 82 + src/wok/plugins/gingerbase/model/cpuinfo.py | 104 + src/wok/plugins/gingerbase/model/debugreports.py | 214 ++ src/wok/plugins/gingerbase/model/host.py | 427 ++++ src/wok/plugins/gingerbase/model/model.py | 54 + src/wok/plugins/gingerbase/po/LINGUAS | 11 + src/wok/plugins/gingerbase/po/Makefile.in.in | 398 ++++ src/wok/plugins/gingerbase/po/Makevars | 41 + src/wok/plugins/gingerbase/po/POTFILES.in | 3 + src/wok/plugins/gingerbase/po/de_DE.po | 2250 +++++++++++++++++++ src/wok/plugins/gingerbase/po/en_US.po | 2092 ++++++++++++++++++ src/wok/plugins/gingerbase/po/es_ES.po | 2268 +++++++++++++++++++ src/wok/plugins/gingerbase/po/fr_FR.po | 2290 ++++++++++++++++++++ src/wok/plugins/gingerbase/po/gen-pot.in | 9 + src/wok/plugins/gingerbase/po/gingerbase.pot | 2074 ++++++++++++++++++ src/wok/plugins/gingerbase/po/it_IT.po | 2237 +++++++++++++++++++ src/wok/plugins/gingerbase/po/ja_JP.po | 2233 +++++++++++++++++++ src/wok/plugins/gingerbase/po/ko_KR.po | 2163 ++++++++++++++++++ src/wok/plugins/gingerbase/po/pt_BR.po | 2289 +++++++++++++++++++ src/wok/plugins/gingerbase/po/ru_RU.po | 2165 ++++++++++++++++++ src/wok/plugins/gingerbase/po/zh_CN.po | 2117 ++++++++++++++++++ src/wok/plugins/gingerbase/po/zh_TW.po | 2105 ++++++++++++++++++ src/wok/plugins/gingerbase/repositories.py | 535 +++++ src/wok/plugins/gingerbase/swupdate.py | 277 +++ src/wok/plugins/gingerbase/tests/Makefile.am | 50 + src/wok/plugins/gingerbase/tests/run_tests.sh.in | 56 + src/wok/plugins/gingerbase/tests/test_config.py.in | 125 ++ src/wok/plugins/gingerbase/tests/test_host.py | 153 ++ src/wok/plugins/gingerbase/tests/test_model.py | 275 +++ src/wok/plugins/gingerbase/tests/test_rest.py | 184 ++ src/wok/plugins/gingerbase/tests/test_yumparser.py | 164 ++ src/wok/plugins/gingerbase/tests/utils.py | 261 +++ src/wok/plugins/gingerbase/ui/Makefile.am | 21 + src/wok/plugins/gingerbase/ui/config/Makefile.am | 23 + src/wok/plugins/gingerbase/ui/config/tab-ext.xml | 10 + src/wok/plugins/gingerbase/ui/css/Makefile.am | 27 + .../gingerbase/ui/css/theme-default/host.css | 288 +++ .../gingerbase/ui/css/theme-default/report-add.css | 38 + .../ui/css/theme-default/report-rename.css | 40 + .../ui/css/theme-default/repository-add.css | 43 + .../ui/css/theme-default/repository-edit.css | 89 + src/wok/plugins/gingerbase/ui/images/Makefile.am | 23 + src/wok/plugins/gingerbase/ui/images/icon-vm.png | Bin 0 -> 2976 bytes src/wok/plugins/gingerbase/ui/images/logo.ico | Bin 0 -> 1214 bytes .../gingerbase/ui/images/theme-default/Makefile.am | 21 + .../ui/images/theme-default/host-icon-sprite.png | Bin 0 -> 1034 bytes .../images/theme-default/kimchi-loading15x15.gif | Bin 0 -> 1653 bytes src/wok/plugins/gingerbase/ui/js/Makefile.am | 28 + .../plugins/gingerbase/ui/js/src/gingerbase.api.js | 372 ++++ .../gingerbase/ui/js/src/gingerbase.host.js | 860 ++++++++ .../gingerbase/ui/js/src/gingerbase.main.js | 27 + .../ui/js/src/gingerbase.report_add_main.js | 73 + .../ui/js/src/gingerbase.report_rename_main.js | 67 + .../ui/js/src/gingerbase.repository_add_main.js | 97 + .../ui/js/src/gingerbase.repository_edit_main.js | 75 + src/wok/plugins/gingerbase/ui/pages/Makefile.am | 23 + .../plugins/gingerbase/ui/pages/help/Makefile.am | 38 + .../gingerbase/ui/pages/help/de_DE/Makefile.am | 27 + .../gingerbase/ui/pages/help/de_DE/host.dita | 49 + .../plugins/gingerbase/ui/pages/help/dita-help.xsl | 26 + .../gingerbase/ui/pages/help/en_US/Makefile.am | 27 + .../gingerbase/ui/pages/help/en_US/host.dita | 68 + .../gingerbase/ui/pages/help/es_ES/Makefile.am | 27 + .../gingerbase/ui/pages/help/es_ES/host.dita | 49 + .../gingerbase/ui/pages/help/fr_FR/Makefile.am | 27 + .../gingerbase/ui/pages/help/fr_FR/host.dita | 65 + .../gingerbase/ui/pages/help/gingerbase.css | 209 ++ .../gingerbase/ui/pages/help/it_IT/Makefile.am | 27 + .../gingerbase/ui/pages/help/it_IT/host.dita | 51 + .../gingerbase/ui/pages/help/ja_JP/Makefile.am | 27 + .../gingerbase/ui/pages/help/ja_JP/host.dita | 69 + .../gingerbase/ui/pages/help/ko_KR/Makefile.am | 27 + .../gingerbase/ui/pages/help/ko_KR/host.dita | 51 + .../gingerbase/ui/pages/help/pt_BR/Makefile.am | 27 + .../gingerbase/ui/pages/help/pt_BR/host.dita | 72 + .../gingerbase/ui/pages/help/ru_RU/Makefile.am | 27 + .../gingerbase/ui/pages/help/ru_RU/host.dita | 48 + .../gingerbase/ui/pages/help/zh_CN/Makefile.am | 27 + .../gingerbase/ui/pages/help/zh_CN/host.dita | 45 + .../gingerbase/ui/pages/help/zh_TW/Makefile.am | 27 + .../gingerbase/ui/pages/help/zh_TW/host.dita | 49 + src/wok/plugins/gingerbase/ui/pages/host.html.tmpl | 178 ++ src/wok/plugins/gingerbase/ui/pages/i18n.json.tmpl | 149 ++ .../gingerbase/ui/pages/report-add.html.tmpl | 57 + .../gingerbase/ui/pages/report-rename.html.tmpl | 57 + .../gingerbase/ui/pages/repository-add.html.tmpl | 114 + .../gingerbase/ui/pages/repository-edit.html.tmpl | 118 + src/wok/plugins/gingerbase/yumparser.py | 354 +++ src/wok/plugins/kimchi/API.json | 134 -- src/wok/plugins/kimchi/Makefile.am | 3 +- src/wok/plugins/kimchi/config.py.in | 4 - src/wok/plugins/kimchi/control/debugreports.py | 61 - src/wok/plugins/kimchi/control/host.py | 99 +- src/wok/plugins/kimchi/disks.py | 196 -- src/wok/plugins/kimchi/docs/README.md | 6 +- src/wok/plugins/kimchi/i18n.py | 52 - src/wok/plugins/kimchi/kimchi.conf | 7 - src/wok/plugins/kimchi/mockmodel.py | 146 +- src/wok/plugins/kimchi/model/config.py | 21 - src/wok/plugins/kimchi/model/debugreports.py | 213 -- src/wok/plugins/kimchi/model/host.py | 334 +-- src/wok/plugins/kimchi/repositories.py | 533 ----- src/wok/plugins/kimchi/root.py | 1 - src/wok/plugins/kimchi/swupdate.py | 274 --- src/wok/plugins/kimchi/tests/test_authorization.py | 6 - src/wok/plugins/kimchi/tests/test_config.py.in | 8 - src/wok/plugins/kimchi/tests/test_host.py | 97 +- src/wok/plugins/kimchi/tests/test_model.py | 239 +- src/wok/plugins/kimchi/tests/test_rest.py | 54 - src/wok/plugins/kimchi/tests/test_yumparser.py | 162 -- src/wok/plugins/kimchi/ui/config/tab-ext.xml | 7 - .../plugins/kimchi/ui/css/theme-default/host.css | 287 --- .../kimchi/ui/css/theme-default/report-add.css | 37 - .../kimchi/ui/css/theme-default/report-rename.css | 39 - .../kimchi/ui/css/theme-default/repository-add.css | 42 - .../ui/css/theme-default/repository-edit.css | 88 - src/wok/plugins/kimchi/ui/js/src/kimchi.host.js | 858 -------- .../kimchi/ui/js/src/kimchi.report_add_main.js | 72 - .../kimchi/ui/js/src/kimchi.report_rename_main.js | 66 - .../kimchi/ui/js/src/kimchi.repository_add_main.js | 96 - .../ui/js/src/kimchi.repository_edit_main.js | 74 - .../plugins/kimchi/ui/pages/help/de_DE/host.dita | 49 - .../plugins/kimchi/ui/pages/help/en_US/host.dita | 68 - .../plugins/kimchi/ui/pages/help/es_ES/host.dita | 49 - .../plugins/kimchi/ui/pages/help/fr_FR/host.dita | 65 - .../plugins/kimchi/ui/pages/help/it_IT/host.dita | 51 - .../plugins/kimchi/ui/pages/help/ja_JP/host.dita | 69 - .../plugins/kimchi/ui/pages/help/ko_KR/host.dita | 51 - .../plugins/kimchi/ui/pages/help/pt_BR/host.dita | 72 - .../plugins/kimchi/ui/pages/help/ru_RU/host.dita | 48 - .../plugins/kimchi/ui/pages/help/zh_CN/host.dita | 45 - .../plugins/kimchi/ui/pages/help/zh_TW/host.dita | 49 - src/wok/plugins/kimchi/ui/pages/host.html.tmpl | 177 -- .../plugins/kimchi/ui/pages/report-add.html.tmpl | 56 - .../kimchi/ui/pages/report-rename.html.tmpl | 56 - .../kimchi/ui/pages/repository-add.html.tmpl | 113 - .../kimchi/ui/pages/repository-edit.html.tmpl | 117 - src/wok/plugins/kimchi/yumparser.py | 353 --- 187 files changed, 40827 insertions(+), 5791 deletions(-) create mode 100644 src/wok/plugins/gingerbase/API.json create mode 100644 src/wok/plugins/gingerbase/INSTALL create mode 100644 src/wok/plugins/gingerbase/Makefile.am create mode 120000 src/wok/plugins/gingerbase/README.md create mode 100644 src/wok/plugins/gingerbase/VERSION create mode 100644 src/wok/plugins/gingerbase/__init__.py create mode 100755 src/wok/plugins/gingerbase/autogen.sh create mode 100644 src/wok/plugins/gingerbase/build-aux/config.rpath create mode 100755 src/wok/plugins/gingerbase/build-aux/genChangelog create mode 100755 src/wok/plugins/gingerbase/build-aux/pkg-version create mode 100644 src/wok/plugins/gingerbase/config.py.in create mode 100644 src/wok/plugins/gingerbase/config.rpath create mode 100644 src/wok/plugins/gingerbase/configure.ac create mode 100644 src/wok/plugins/gingerbase/contrib/DEBIAN/Makefile.am create mode 100644 src/wok/plugins/gingerbase/contrib/DEBIAN/control.in create mode 100644 src/wok/plugins/gingerbase/contrib/Makefile.am create mode 100755 src/wok/plugins/gingerbase/contrib/check_i18n.py create mode 100644 src/wok/plugins/gingerbase/contrib/gingerbase.spec.fedora.in create mode 100644 src/wok/plugins/gingerbase/contrib/gingerbase.spec.suse.in create mode 100644 src/wok/plugins/gingerbase/contrib/make-deb.sh.in create mode 100644 src/wok/plugins/gingerbase/control/Makefile.am create mode 100644 src/wok/plugins/gingerbase/control/__init__.py create mode 100644 src/wok/plugins/gingerbase/control/config.py create mode 100644 src/wok/plugins/gingerbase/control/cpuinfo.py create mode 100644 src/wok/plugins/gingerbase/control/debugreports.py create mode 100644 src/wok/plugins/gingerbase/control/host.py create mode 100644 src/wok/plugins/gingerbase/disks.py create mode 100644 src/wok/plugins/gingerbase/docs/API.md create mode 100644 src/wok/plugins/gingerbase/docs/Makefile.am create mode 100644 src/wok/plugins/gingerbase/docs/README.md create mode 100644 src/wok/plugins/gingerbase/docs/gingerbase-host-tab.png create mode 100644 src/wok/plugins/gingerbase/docs/kimchi-login.png create mode 100644 src/wok/plugins/gingerbase/gingerbase.conf create mode 100644 src/wok/plugins/gingerbase/gingerbase.py create mode 100644 src/wok/plugins/gingerbase/i18n.py create mode 100644 src/wok/plugins/gingerbase/lscpu.py create mode 100644 src/wok/plugins/gingerbase/m4/ac_python_module.m4 create mode 100644 src/wok/plugins/gingerbase/m4/gettext.m4 create mode 100644 src/wok/plugins/gingerbase/m4/iconv.m4 create mode 100644 src/wok/plugins/gingerbase/m4/intlmacosx.m4 create mode 100644 src/wok/plugins/gingerbase/m4/lib-ld.m4 create mode 100644 src/wok/plugins/gingerbase/m4/lib-link.m4 create mode 100644 src/wok/plugins/gingerbase/m4/lib-prefix.m4 create mode 100644 src/wok/plugins/gingerbase/m4/nls.m4 create mode 100644 src/wok/plugins/gingerbase/m4/po.m4 create mode 100644 src/wok/plugins/gingerbase/m4/progtest.m4 create mode 100644 src/wok/plugins/gingerbase/mockmodel.py create mode 100644 src/wok/plugins/gingerbase/model/Makefile.am create mode 100644 src/wok/plugins/gingerbase/model/__init__.py create mode 100644 src/wok/plugins/gingerbase/model/config.py create mode 100644 src/wok/plugins/gingerbase/model/cpuinfo.py create mode 100644 src/wok/plugins/gingerbase/model/debugreports.py create mode 100644 src/wok/plugins/gingerbase/model/host.py create mode 100644 src/wok/plugins/gingerbase/model/model.py create mode 100644 src/wok/plugins/gingerbase/po/LINGUAS create mode 100644 src/wok/plugins/gingerbase/po/Makefile.in.in create mode 100644 src/wok/plugins/gingerbase/po/Makevars create mode 100644 src/wok/plugins/gingerbase/po/POTFILES.in create mode 100644 src/wok/plugins/gingerbase/po/de_DE.po create mode 100644 src/wok/plugins/gingerbase/po/en_US.po create mode 100644 src/wok/plugins/gingerbase/po/es_ES.po create mode 100644 src/wok/plugins/gingerbase/po/fr_FR.po create mode 100644 src/wok/plugins/gingerbase/po/gen-pot.in create mode 100755 src/wok/plugins/gingerbase/po/gingerbase.pot create mode 100644 src/wok/plugins/gingerbase/po/it_IT.po create mode 100644 src/wok/plugins/gingerbase/po/ja_JP.po create mode 100644 src/wok/plugins/gingerbase/po/ko_KR.po create mode 100644 src/wok/plugins/gingerbase/po/pt_BR.po create mode 100644 src/wok/plugins/gingerbase/po/ru_RU.po create mode 100644 src/wok/plugins/gingerbase/po/zh_CN.po create mode 100644 src/wok/plugins/gingerbase/po/zh_TW.po create mode 100644 src/wok/plugins/gingerbase/repositories.py create mode 100644 src/wok/plugins/gingerbase/swupdate.py create mode 100644 src/wok/plugins/gingerbase/tests/Makefile.am create mode 100644 src/wok/plugins/gingerbase/tests/run_tests.sh.in create mode 100644 src/wok/plugins/gingerbase/tests/test_config.py.in create mode 100644 src/wok/plugins/gingerbase/tests/test_host.py create mode 100644 src/wok/plugins/gingerbase/tests/test_model.py create mode 100644 src/wok/plugins/gingerbase/tests/test_rest.py create mode 100644 src/wok/plugins/gingerbase/tests/test_yumparser.py create mode 100644 src/wok/plugins/gingerbase/tests/utils.py create mode 100644 src/wok/plugins/gingerbase/ui/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/config/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/config/tab-ext.xml create mode 100644 src/wok/plugins/gingerbase/ui/css/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/css/theme-default/host.css create mode 100644 src/wok/plugins/gingerbase/ui/css/theme-default/report-add.css create mode 100644 src/wok/plugins/gingerbase/ui/css/theme-default/report-rename.css create mode 100644 src/wok/plugins/gingerbase/ui/css/theme-default/repository-add.css create mode 100644 src/wok/plugins/gingerbase/ui/css/theme-default/repository-edit.css create mode 100644 src/wok/plugins/gingerbase/ui/images/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/images/icon-vm.png create mode 100644 src/wok/plugins/gingerbase/ui/images/logo.ico create mode 100644 src/wok/plugins/gingerbase/ui/images/theme-default/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/images/theme-default/host-icon-sprite.png create mode 100644 src/wok/plugins/gingerbase/ui/images/theme-default/kimchi-loading15x15.gif create mode 100644 src/wok/plugins/gingerbase/ui/js/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.api.js create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.host.js create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.main.js create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.report_add_main.js create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.report_rename_main.js create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.repository_add_main.js create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.repository_edit_main.js create mode 100644 src/wok/plugins/gingerbase/ui/pages/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/de_DE/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/de_DE/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/dita-help.xsl create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/en_US/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/en_US/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/es_ES/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/es_ES/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/fr_FR/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/fr_FR/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/gingerbase.css create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/it_IT/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/it_IT/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/ja_JP/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/ja_JP/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/ko_KR/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/ko_KR/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/pt_BR/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/pt_BR/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/ru_RU/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/ru_RU/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/zh_CN/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/zh_CN/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/zh_TW/Makefile.am create mode 100644 src/wok/plugins/gingerbase/ui/pages/help/zh_TW/host.dita create mode 100644 src/wok/plugins/gingerbase/ui/pages/host.html.tmpl create mode 100644 src/wok/plugins/gingerbase/ui/pages/i18n.json.tmpl create mode 100644 src/wok/plugins/gingerbase/ui/pages/report-add.html.tmpl create mode 100644 src/wok/plugins/gingerbase/ui/pages/report-rename.html.tmpl create mode 100644 src/wok/plugins/gingerbase/ui/pages/repository-add.html.tmpl create mode 100644 src/wok/plugins/gingerbase/ui/pages/repository-edit.html.tmpl create mode 100644 src/wok/plugins/gingerbase/yumparser.py delete mode 100644 src/wok/plugins/kimchi/control/debugreports.py delete mode 100644 src/wok/plugins/kimchi/disks.py delete mode 100644 src/wok/plugins/kimchi/model/debugreports.py delete mode 100644 src/wok/plugins/kimchi/repositories.py delete mode 100644 src/wok/plugins/kimchi/swupdate.py delete mode 100644 src/wok/plugins/kimchi/tests/test_yumparser.py delete mode 100644 src/wok/plugins/kimchi/ui/css/theme-default/host.css delete mode 100644 src/wok/plugins/kimchi/ui/css/theme-default/report-add.css delete mode 100644 src/wok/plugins/kimchi/ui/css/theme-default/report-rename.css delete mode 100644 src/wok/plugins/kimchi/ui/css/theme-default/repository-add.css delete mode 100644 src/wok/plugins/kimchi/ui/css/theme-default/repository-edit.css delete mode 100644 src/wok/plugins/kimchi/ui/js/src/kimchi.host.js delete mode 100644 src/wok/plugins/kimchi/ui/js/src/kimchi.report_add_main.js delete mode 100644 src/wok/plugins/kimchi/ui/js/src/kimchi.report_rename_main.js delete mode 100644 src/wok/plugins/kimchi/ui/js/src/kimchi.repository_add_main.js delete mode 100644 src/wok/plugins/kimchi/ui/js/src/kimchi.repository_edit_main.js delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/de_DE/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/en_US/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/es_ES/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/fr_FR/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/it_IT/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/ja_JP/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/ko_KR/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/pt_BR/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/ru_RU/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/zh_CN/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/help/zh_TW/host.dita delete mode 100644 src/wok/plugins/kimchi/ui/pages/host.html.tmpl delete mode 100644 src/wok/plugins/kimchi/ui/pages/report-add.html.tmpl delete mode 100644 src/wok/plugins/kimchi/ui/pages/report-rename.html.tmpl delete mode 100644 src/wok/plugins/kimchi/ui/pages/repository-add.html.tmpl delete mode 100644 src/wok/plugins/kimchi/ui/pages/repository-edit.html.tmpl delete mode 100644 src/wok/plugins/kimchi/yumparser.py
participants (4)
-
Aline Manera
-
Chandra Shehkhar Reddy Potula
-
chandra@linux.vnet.ibm.com
-
Daniel Henrique Barboza